public override bool ShouldExecute() { if (entity.World.Rand.NextDouble() < 0.005) { return(false); } // Don't search more often than every 15 seconds if (lastPOISearchTotalMs + 15000 > entity.World.ElapsedMilliseconds) { return(false); } if (cooldownUntilMs > entity.World.ElapsedMilliseconds) { return(false); } if (cooldownUntilTotalHours > entity.World.Calendar.TotalHours) { return(false); } if (whenInEmotionState != null && bhEmo?.IsInEmotionState(whenInEmotionState) != true) { return(false); } if (whenNotInEmotionState != null && bhEmo?.IsInEmotionState(whenNotInEmotionState) == true) { return(false); } EntityBehaviorMultiplyBase bh = entity.GetBehavior <EntityBehaviorMultiplyBase>(); if (bh != null && !bh.ShouldEat && entity.World.Rand.NextDouble() < 0.996) { return(false); // 0.4% chance go to the food source anyway just because (without eating anything). } targetPoi = null; extraTargetDist = 0; lastPOISearchTotalMs = entity.World.ElapsedMilliseconds; api.ModLoader.GetModSystem <EntityPartitioning>().WalkEntities(entity.ServerPos.XYZ, 10, (e) => { if (e is EntityItem) { EntityItem ei = (EntityItem)e; EnumFoodCategory?cat = ei.Itemstack?.Collectible?.NutritionProps?.FoodCategory; if (cat != null && eatItemCategories.Contains((EnumFoodCategory)cat)) { targetPoi = new LooseItemFoodSource(ei); return(false); } AssetLocation code = ei.Itemstack?.Collectible?.Code; if (code != null && eatItemCodes.Contains(code)) { targetPoi = new LooseItemFoodSource(ei); return(false); } } if (searchPlayerInv && e is EntityPlayer eplr) { if (eplr.Player.InventoryManager.Find(slot => slot.Inventory is InventoryBasePlayer && !slot.Empty && eatItemCodes.Contains(slot.Itemstack.Collectible.Code))) { targetPoi = new PlayerPoi(eplr); } } return(true); }); if (targetPoi == null) { targetPoi = porregistry.GetNearestPoi(entity.ServerPos.XYZ, 48, (poi) => { if (poi.Type != "food") { return(false); } IAnimalFoodSource foodPoi; if ((foodPoi = poi as IAnimalFoodSource)?.IsSuitableFor(entity, entityDiet) == true) { FailedAttempt attempt; failedSeekTargets.TryGetValue(foodPoi, out attempt); if (attempt == null || (attempt.Count < 4 || attempt.LastTryMs < world.ElapsedMilliseconds - 60000)) { return(true); } } return(false); }) as IAnimalFoodSource; } /*if (targetPoi != null) * { * if (targetPoi is BlockEntity || targetPoi is Block) * { * Block block = entity.World.BlockAccessor.GetBlock(targetPoi.Position.AsBlockPos); * Cuboidf[] collboxes = block.GetCollisionBoxes(entity.World.BlockAccessor, targetPoi.Position.AsBlockPos); * if (collboxes != null && collboxes.Length != 0 && collboxes[0].Y2 > 0.3f) * { * extraTargetDist = 0.15f; * } * } * }*/ return(targetPoi != null); }
public override bool ContinueExecute(float dt) { Vec3d pos = targetPoi.Position; pathTraverser.CurrentTarget.X = pos.X; pathTraverser.CurrentTarget.Y = pos.Y; pathTraverser.CurrentTarget.Z = pos.Z; Cuboidd targetBox = entity.SelectionBox.ToDouble().Translate(entity.ServerPos.X, entity.ServerPos.Y, entity.ServerPos.Z); double distance = targetBox.ShortestDistanceFrom(pos); float minDist = MinDistanceToTarget(); if (distance <= minDist) { pathTraverser.Stop(); if (animMeta != null) { entity.AnimManager.StopAnimation(animMeta.Code); } EntityBehaviorMultiplyBase bh = entity.GetBehavior <EntityBehaviorMultiplyBase>(); if (bh != null && !bh.ShouldEat) { return(false); } if (targetPoi.IsSuitableFor(entity, entityDiet) != true) { return(false); } if (eatAnimMeta != null && !eatAnimStarted) { entity.AnimManager.StartAnimation((targetPoi is LooseItemFoodSource && eatAnimMetaLooseItems != null) ? eatAnimMetaLooseItems : eatAnimMeta); eatAnimStarted = true; } eatTimeNow += dt; if (targetPoi is LooseItemFoodSource foodSource) { entity.World.SpawnCubeParticles(entity.ServerPos.XYZ, foodSource.ItemStack, 0.25f, 1, 0.25f + 0.5f * (float)entity.World.Rand.NextDouble()); } if (eatTimeNow > eatTime * 0.75f && !soundPlayed) { soundPlayed = true; if (eatSound != null) { entity.World.PlaySoundAt(eatSound, entity, null, true, 16, 1); } } if (eatTimeNow >= eatTime) { ITreeAttribute tree = entity.WatchedAttributes.GetTreeAttribute("hunger"); if (tree == null) { entity.WatchedAttributes["hunger"] = tree = new TreeAttribute(); } if (doConsumePortion) { float sat = targetPoi.ConsumeOnePortion(); quantityEaten += sat; tree.SetFloat("saturation", sat + tree.GetFloat("saturation", 0)); entity.WatchedAttributes.SetDouble("lastMealEatenTotalHours", entity.World.Calendar.TotalHours); entity.WatchedAttributes.MarkPathDirty("hunger"); } else { quantityEaten = 1; } failedSeekTargets.Remove(targetPoi); return(false); } } else { if (!pathTraverser.Active) { float rndx = (float)entity.World.Rand.NextDouble() * 0.3f - 0.15f; float rndz = (float)entity.World.Rand.NextDouble() * 0.3f - 0.15f; if (!pathTraverser.NavigateTo(targetPoi.Position.AddCopy(rndx, 0, rndz), moveSpeed, MinDistanceToTarget() - 0.15f, OnGoalReached, OnStuck, false, 500, 1)) { return(false); } } } if (nowStuck && entity.World.ElapsedMilliseconds > stuckatMs + eatTime * 1000) { return(false); } return(true); }
public override bool ShouldExecute() { if (entity.World.Rand.NextDouble() < 0.005) { return(false); } if (cooldownUntilMs > entity.World.ElapsedMilliseconds) { return(false); } if (cooldownUntilTotalHours > entity.World.Calendar.TotalHours) { return(false); } if (whenInEmotionState != null && bhEmo?.IsInEmotionState(whenInEmotionState) != true) { return(false); } if (whenNotInEmotionState != null && bhEmo?.IsInEmotionState(whenNotInEmotionState) == true) { return(false); } EntityBehaviorMultiplyBase bh = entity.GetBehavior <EntityBehaviorMultiplyBase>(); if (bh != null && !bh.ShouldEat && entity.World.Rand.NextDouble() < 0.996) { return(false); // 0.4% chance go to the food source anyway just because (without eating anything). } ItemSlot leftSlot = entity.LeftHandItemSlot; if (leftSlot.Empty) { return(false); } isEdible = false; EnumFoodCategory?cat = leftSlot.Itemstack.Collectible?.NutritionProps?.FoodCategory; if (cat != null && eatItemCategories.Contains((EnumFoodCategory)cat)) { isEdible = true; return(true); } AssetLocation code = leftSlot.Itemstack?.Collectible?.Code; if (code != null && eatItemCodes.Contains(code)) { isEdible = true; return(true); } if (!leftSlot.Empty) { entity.World.SpawnItemEntity(leftSlot.TakeOutWhole(), entity.ServerPos.XYZ); } return(false); }