/// <summary> /// Replaces SolidConsumerMonitor.FindFood to more efficiently find food for critters. /// </summary> public static void FindFood(SolidConsumerMonitor.Instance smi, float _) { var closest = new ClosestEdible(smi.GetComponent <DrowningMonitor>(), smi.GetComponent <Navigator>()); // Check the diet type first var diet = smi.def.diet; Grid.PosToXY(smi.gameObject.transform.GetPosition(), out int x, out int y); if (!diet.eatsPlantsDirectly) { // Check Critter Feeder with priority var storages = ListPool <Storage, SolidConsumerMonitor> .Allocate(); foreach (var creatureFeeder in Components.CreatureFeeders.Items) { var go = creatureFeeder.gameObject; if (go != null) { Grid.PosToXY(go.transform.GetPosition(), out int cx, out int cy); // Only check critter feeders that are somewhat nearby if (Math.Abs(x - cx) <= RADIUS && Math.Abs(y - cy) <= RADIUS) { storages.Clear(); go.GetComponents(storages); FindFood(storages, diet, ref closest); } } } storages.Recycle(); } var gsp = GameScenePartitioner.Instance; var nearby = ListPool <ScenePartitionerEntry, GameScenePartitioner> .Allocate(); gsp.GatherEntries(x - RADIUS, y - RADIUS, RADIUS << 1, RADIUS << 1, diet. eatsPlantsDirectly ? gsp.plants : gsp.pickupablesLayer, nearby); // Add plants or critters int n = nearby.Count; for (int i = 0; i < n; i++) { if (nearby[i].obj is KMonoBehaviour item && CanEatItem(item, diet)) { closest.CheckUpdate(item); } } nearby.Recycle(); smi.targetEdible = closest.target; }
/// <summary> /// Run on entry to SolidConsumerMonitor.lookingforfood to ensure that the critter /// has a tile when they initially become hungry. /// </summary> public static void FindFood(SolidConsumerMonitor.Instance smi) => FindFood(smi, 0.0f);