예제 #1
0
        public static void DebugFoodSearchFromMouse_OnGUI()
        {
            IntVec3 a    = UI.MouseCell();
            Pawn    pawn = Find.Selector.SingleSelectedThing as Pawn;

            if (pawn != null && pawn.Map == Find.VisibleMap)
            {
                Text.Anchor = TextAnchor.MiddleCenter;
                Text.Font   = GameFont.Tiny;
                foreach (Thing item in Find.VisibleMap.listerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree))
                {
                    ThingDef          finalIngestibleDef = FoodUtility.GetFinalIngestibleDef(item, false);
                    float             num    = FoodUtility.FoodOptimality(pawn, item, finalIngestibleDef, (a - item.Position).LengthHorizontal, false);
                    Vector2           vector = item.DrawPos.MapToUIPosition();
                    Rect              rect   = new Rect((float)(vector.x - 100.0), (float)(vector.y - 100.0), 200f, 200f);
                    string            text   = num.ToString("F0");
                    List <ThoughtDef> list   = FoodUtility.ThoughtsFromIngesting(pawn, item, finalIngestibleDef);
                    for (int i = 0; i < list.Count; i++)
                    {
                        string text2 = text;
                        text = text2 + "\n" + list[i].defName + "(" + FoodUtility.FoodOptimalityEffectFromMoodCurve.Evaluate(list[i].stages[0].baseMoodEffect).ToString("F0") + ")";
                    }
                    Widgets.Label(rect, text);
                }
                Text.Anchor = TextAnchor.UpperLeft;
            }
        }
예제 #2
0
        public static bool TryFindBestFoodSourceFor(Pawn getter, Pawn eater, bool desperate, out Thing foodSource, out ThingDef foodDef, bool canRefillDispenser = true, bool canUseInventory = true, bool allowForbidden = false, bool allowCorpse = true, bool allowSociallyImproper = false, bool allowHarvest = false, bool forceScanWholeMap = false)
        {
            bool  flag      = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);
            bool  allowDrug = !eater.IsTeetotaler();
            Thing thing     = null;

            if (canUseInventory)
            {
                if (flag)
                {
                    thing = FoodUtility.BestFoodInInventory(getter, null, FoodPreferability.MealAwful, FoodPreferability.MealLavish, 0f, false);
                }
                if (thing != null)
                {
                    if (getter.Faction != Faction.OfPlayer)
                    {
                        foodSource = thing;
                        foodDef    = FoodUtility.GetFinalIngestibleDef(foodSource, false);
                        return(true);
                    }
                    CompRottable compRottable = thing.TryGetComp <CompRottable>();
                    if (compRottable != null && compRottable.Stage == RotStage.Fresh && compRottable.TicksUntilRotAtCurrentTemp < 30000)
                    {
                        foodSource = thing;
                        foodDef    = FoodUtility.GetFinalIngestibleDef(foodSource, false);
                        return(true);
                    }
                }
            }
            ThingDef     thingDef;
            ref ThingDef foodDef2   = ref thingDef;
예제 #3
0
        private static Thing SpawnedFoodSearchInnerScan(Pawn eater, IntVec3 root, List <Thing> searchSet, PathEndMode peMode, TraverseParms traverseParams, float maxDistance = 9999f, Predicate <Thing> validator = null)
        {
            if (searchSet == null)
            {
                return(null);
            }
            Pawn  pawn   = traverseParams.pawn ?? eater;
            int   num    = 0;
            int   num2   = 0;
            Thing result = null;
            float num3   = 0f;
            float num4   = -3.40282347E+38f;

            for (int i = 0; i < searchSet.Count; i++)
            {
                Thing thing = searchSet[i];
                num2++;
                float num5 = (float)(root - thing.Position).LengthManhattan;
                if (!(num5 > maxDistance))
                {
                    num3 = FoodUtility.FoodOptimality(eater, thing, FoodUtility.GetFinalIngestibleDef(thing, false), num5, false);
                    if (!(num3 < num4) && pawn.Map.reachability.CanReach(root, thing, peMode, traverseParams) && thing.Spawned && (validator == null || validator(thing)))
                    {
                        result = thing;
                        num4   = num3;
                        num++;
                    }
                }
            }
            return(result);
        }
예제 #4
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.inventory == null)
            {
                return(null);
            }
            float invNutrition = GetInventoryPackableFoodNutrition(pawn);

            if (invNutrition > 0.4f)
            {
                return(null);
            }
            if (pawn.Map.resourceCounter.TotalHumanEdibleNutrition < (float)pawn.Map.mapPawns.ColonistsSpawnedCount * 1.5f)
            {
                return(null);
            }
            Thing thing = GenClosest.ClosestThing_Regionwise_ReachablePrioritized(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 20f, delegate(Thing t)
            {
                if (!IsGoodPackableFoodFor(t, pawn) || t.IsForbidden(pawn) || !pawn.CanReserve(t) || !t.IsSociallyProper(pawn))
                {
                    return(false);
                }
                float num2 = invNutrition + t.GetStatValue(StatDefOf.Nutrition) * (float)t.stackCount;
                if (num2 < 0.8f)
                {
                    return(false);
                }
                List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(pawn, t, FoodUtility.GetFinalIngestibleDef(t));
                for (int i = 0; i < list.Count; i++)
                {
                    if (list[i].stages[0].baseMoodEffect < 0f)
                    {
                        return(false);
                    }
                }
                return(true);
            }, (Thing x) => FoodUtility.FoodOptimality(pawn, x, FoodUtility.GetFinalIngestibleDef(x), 0f));

            if (thing == null)
            {
                return(null);
            }
            float num = pawn.needs.food.MaxLevel - invNutrition;
            int   a   = Mathf.FloorToInt(num / thing.GetStatValue(StatDefOf.Nutrition));

            a = Mathf.Min(a, thing.stackCount);
            a = Mathf.Max(a, 1);
            Job job = new Job(JobDefOf.TakeInventory, thing);

            job.count = a;
            return(job);
        }
		private Job IngestJob(Pawn pawn)
		{
			Thing thing = BestIngestTarget(pawn);
			if (thing == null)
			{
				return null;
			}
			ThingDef finalIngestibleDef = FoodUtility.GetFinalIngestibleDef(thing);
			Job job = JobMaker.MakeJob(JobDefOf.Ingest, thing);
			job.count = finalIngestibleDef.ingestible.maxNumToIngestAtOnce;
			job.ignoreForbidden = IgnoreForbid(pawn);
			job.overeat = true;
			return job;
		}
예제 #6
0
        private Job IngestJob(Pawn pawn)
        {
            Thing thing = this.BestIngestTarget(pawn);

            if (thing == null)
            {
                return(null);
            }
            ThingDef finalIngestibleDef = FoodUtility.GetFinalIngestibleDef(thing, false);
            Job      job = new Job(JobDefOf.Ingest, thing);

            job.count           = finalIngestibleDef.ingestible.maxNumToIngestAtOnce;
            job.ignoreForbidden = this.IgnoreForbid(pawn);
            job.overeat         = true;
            return(job);
        }
예제 #7
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.inventory == null)
            {
                return(null);
            }
            ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;

            for (int i = 0; i < innerContainer.Count; i++)
            {
                Thing thing = innerContainer[i];
                if (thing.def.ingestible != null && thing.def.ingestible.nutrition > 0.3f && thing.def.ingestible.preferability >= FoodPreferability.MealAwful && pawn.RaceProps.CanEverEat(thing))
                {
                    return(null);
                }
            }
            if (pawn.Map.resourceCounter.TotalHumanEdibleNutrition < (float)pawn.Map.mapPawns.ColonistsSpawnedCount * 1.5f)
            {
                return(null);
            }
            Thing thing2 = GenClosest.ClosestThing_Regionwise_ReachablePrioritized(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 20f, delegate(Thing t)
            {
                if (t.def.category != ThingCategory.Item || t.def.ingestible == null || t.def.ingestible.nutrition < 0.3f || t.IsForbidden(pawn) || t is Corpse || !pawn.CanReserve(t, 1, -1, null, false) || !t.IsSociallyProper(pawn) || !pawn.RaceProps.CanEverEat(t))
                {
                    return(false);
                }
                List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(pawn, t, FoodUtility.GetFinalIngestibleDef(t, false));
                for (int j = 0; j < list.Count; j++)
                {
                    if (list[j].stages[0].baseMoodEffect < 0f)
                    {
                        return(false);
                    }
                }
                return(true);
            }, (Thing x) => FoodUtility.FoodOptimality(pawn, x, FoodUtility.GetFinalIngestibleDef(x, false), 0f, false), 24, 30);

            if (thing2 == null)
            {
                return(null);
            }
            return(new Job(JobDefOf.TakeInventory, thing2)
            {
                count = 1
            });
        }
        private Job IngestJob(Pawn pawn)
        {
            Thing thing = this.BestIngestTarget(pawn);
            Job   result;

            if (thing == null)
            {
                result = null;
            }
            else
            {
                ThingDef finalIngestibleDef = FoodUtility.GetFinalIngestibleDef(thing, false);
                result = new Job(JobDefOf.Ingest, thing)
                {
                    count           = finalIngestibleDef.ingestible.maxNumToIngestAtOnce,
                    ignoreForbidden = this.IgnoreForbid(pawn),
                    overeat         = true
                };
            }
            return(result);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            Job result;

            if (pawn.inventory == null)
            {
                result = null;
            }
            else
            {
                float invNutrition = this.GetInventoryPackableFoodNutrition(pawn);
                if (invNutrition > 0.4f)
                {
                    result = null;
                }
                else if (pawn.Map.resourceCounter.TotalHumanEdibleNutrition < (float)pawn.Map.mapPawns.ColonistsSpawnedCount * 1.5f)
                {
                    result = null;
                }
                else
                {
                    Thing thing = GenClosest.ClosestThing_Regionwise_ReachablePrioritized(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 20f, delegate(Thing t)
                    {
                        bool result2;
                        if (!this.IsGoodPackableFoodFor(t, pawn) || t.IsForbidden(pawn) || !pawn.CanReserve(t, 1, -1, null, false) || !t.IsSociallyProper(pawn))
                        {
                            result2 = false;
                        }
                        else
                        {
                            float num3 = invNutrition + t.GetStatValue(StatDefOf.Nutrition, true) * (float)t.stackCount;
                            if (num3 < 0.8f)
                            {
                                result2 = false;
                            }
                            else
                            {
                                List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(pawn, t, FoodUtility.GetFinalIngestibleDef(t, false));
                                for (int i = 0; i < list.Count; i++)
                                {
                                    if (list[i].stages[0].baseMoodEffect < 0f)
                                    {
                                        return(false);
                                    }
                                }
                                result2 = true;
                            }
                        }
                        return(result2);
                    }, (Thing x) => FoodUtility.FoodOptimality(pawn, x, FoodUtility.GetFinalIngestibleDef(x, false), 0f, false), 24, 30);
                    if (thing == null)
                    {
                        result = null;
                    }
                    else
                    {
                        float num  = pawn.needs.food.MaxLevel - invNutrition;
                        int   num2 = Mathf.FloorToInt(num / thing.GetStatValue(StatDefOf.Nutrition, true));
                        num2   = Mathf.Min(num2, thing.stackCount);
                        num2   = Mathf.Max(num2, 1);
                        result = new Job(JobDefOf.TakeInventory, thing)
                        {
                            count = num2
                        };
                    }
                }
            }
            return(result);
        }
 internal float <> m__1(Thing x)
 {
     return(FoodUtility.FoodOptimality(this.pawn, x, FoodUtility.GetFinalIngestibleDef(x, false), 0f, false));
 }
            internal bool <> m__0(Thing t)
            {
                bool result;

                if (!this.$this.IsGoodPackableFoodFor(t, this.pawn) || t.IsForbidden(this.pawn) || !this.pawn.CanReserve(t, 1, -1, null, false) || !t.IsSociallyProper(this.pawn))
                {
                    result = false;
                }
                else
                {
                    float num = this.invNutrition + t.GetStatValue(StatDefOf.Nutrition, true) * (float)t.stackCount;
                    if (num < 0.8f)
                    {
                        result = false;
                    }
                    else
                    {
                        List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(this.pawn, t, FoodUtility.GetFinalIngestibleDef(t, false));
                        for (int i = 0; i < list.Count; i++)
                        {
                            if (list[i].stages[0].baseMoodEffect < 0f)
                            {
                                return(false);
                            }
                        }
                        result = true;
                    }
                }
                return(result);
            }
예제 #12
0
        public static bool TryFindBestFoodSourceFor(Pawn getter, Pawn eater, bool desperate, out Thing foodSource, out ThingDef foodDef, bool canRefillDispenser = true, bool canUseInventory = true, bool allowForbidden = false, bool allowCorpse = true, bool allowSociallyImproper = false, bool allowHarvest = false)
        {
            bool  flag      = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);
            bool  allowDrug = !eater.IsTeetotaler();
            Thing thing     = null;

            if (canUseInventory)
            {
                if (flag)
                {
                    thing = FoodUtility.BestFoodInInventory(getter, null, FoodPreferability.MealAwful, FoodPreferability.MealLavish, 0f, false);
                }
                if (thing != null)
                {
                    if (getter.Faction != Faction.OfPlayer)
                    {
                        foodSource = thing;
                        foodDef    = FoodUtility.GetFinalIngestibleDef(foodSource, false);
                        return(true);
                    }
                    CompRottable compRottable = thing.TryGetComp <CompRottable>();
                    if (compRottable != null && compRottable.Stage == RotStage.Fresh && compRottable.TicksUntilRotAtCurrentTemp < 30000)
                    {
                        foodSource = thing;
                        foodDef    = FoodUtility.GetFinalIngestibleDef(foodSource, false);
                        return(true);
                    }
                }
            }
            bool     allowPlant = getter == eater;
            ThingDef thingDef   = default(ThingDef);
            Thing    thing2     = FoodUtility.BestFoodSourceOnMap(getter, eater, desperate, out thingDef, FoodPreferability.MealLavish, allowPlant, allowDrug, allowCorpse, true, canRefillDispenser, allowForbidden, allowSociallyImproper, allowHarvest);

            if (thing == null && thing2 == null)
            {
                if (canUseInventory && flag)
                {
                    thing = FoodUtility.BestFoodInInventory(getter, null, FoodPreferability.DesperateOnly, FoodPreferability.MealLavish, 0f, allowDrug);
                    if (thing != null)
                    {
                        foodSource = thing;
                        foodDef    = FoodUtility.GetFinalIngestibleDef(foodSource, false);
                        return(true);
                    }
                }
                if (thing2 == null && getter == eater && (getter.RaceProps.predator || getter.IsWildMan()))
                {
                    Pawn pawn = FoodUtility.BestPawnToHuntForPredator(getter);
                    if (pawn != null)
                    {
                        foodSource = pawn;
                        foodDef    = FoodUtility.GetFinalIngestibleDef(foodSource, false);
                        return(true);
                    }
                }
                foodSource = null;
                foodDef    = null;
                return(false);
            }
            if (thing == null && thing2 != null)
            {
                foodSource = thing2;
                foodDef    = thingDef;
                return(true);
            }
            ThingDef finalIngestibleDef = FoodUtility.GetFinalIngestibleDef(thing, false);

            if (thing2 == null)
            {
                foodSource = thing;
                foodDef    = finalIngestibleDef;
                return(true);
            }
            float num  = FoodUtility.FoodOptimality(eater, thing2, thingDef, (float)(getter.Position - thing2.Position).LengthManhattan, false);
            float num2 = FoodUtility.FoodOptimality(eater, thing, finalIngestibleDef, 0f, false);

            num2 = (float)(num2 - 32.0);
            if (num > num2)
            {
                foodSource = thing2;
                foodDef    = thingDef;
                return(true);
            }
            foodSource = thing;
            foodDef    = FoodUtility.GetFinalIngestibleDef(foodSource, false);
            return(true);
        }
예제 #13
0
        public static Thing BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate, out ThingDef foodDef, FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowDrug = true, bool allowCorpse = true, bool allowDispenserFull = true, bool allowDispenserEmpty = true, bool allowForbidden = false, bool allowSociallyImproper = false, bool allowHarvest = false)
        {
            foodDef = null;
            bool getterCanManipulate = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);

            if (!getterCanManipulate && getter != eater)
            {
                Log.Error(getter + " tried to find food to bring to " + eater + " but " + getter + " is incapable of Manipulation.");
                return(null);
            }
            FoodPreferability minPref;

            if (eater.NonHumanlikeOrWildMan())
            {
                minPref = FoodPreferability.NeverForNutrition;
            }
            else if (desperate)
            {
                minPref = FoodPreferability.DesperateOnly;
            }
            else
            {
                minPref = (FoodPreferability)(((int)eater.needs.food.CurCategory <= 2) ? 4 : 6);
            }
            Predicate <Thing> foodValidator = delegate(Thing t)
            {
                if (!allowForbidden && t.IsForbidden(getter))
                {
                    return(false);
                }
                Building_NutrientPasteDispenser building_NutrientPasteDispenser = t as Building_NutrientPasteDispenser;
                if (building_NutrientPasteDispenser != null)
                {
                    if (allowDispenserFull && (int)ThingDefOf.MealNutrientPaste.ingestible.preferability >= (int)minPref && (int)ThingDefOf.MealNutrientPaste.ingestible.preferability <= (int)maxPref && getterCanManipulate && !getter.IsWildMan() && (t.Faction == getter.Faction || t.Faction == getter.HostFaction) && building_NutrientPasteDispenser.powerComp.PowerOn && (allowDispenserEmpty || building_NutrientPasteDispenser.HasEnoughFeedstockInHoppers()) && FoodUtility.IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) && t.InteractionCell.Standable(t.Map) && getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map, false), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some, TraverseMode.ByPawn, false)))
                    {
                        goto IL_025e;
                    }
                    return(false);
                }
                if ((int)t.def.ingestible.preferability < (int)minPref)
                {
                    return(false);
                }
                if ((int)t.def.ingestible.preferability > (int)maxPref)
                {
                    return(false);
                }
                if (t.IngestibleNow && t.def.IsNutritionGivingIngestible && (allowCorpse || !(t is Corpse)) && (allowDrug || !t.def.IsDrug) && (desperate || !t.IsNotFresh()) && !t.IsDessicated() && eater.RaceProps.WillAutomaticallyEat(t) && FoodUtility.IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) && getter.AnimalAwareOf(t) && getter.CanReserve(t, 1, -1, null, false))
                {
                    goto IL_025e;
                }
                return(false);

IL_025e:
                return(true);
            };
            ThingRequest thingRequest = ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) == FoodTypeFlags.None || !allowPlant) ? ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree) : ThingRequest.ForGroup(ThingRequestGroup.FoodSource);
            Thing        bestThing;

            if (getter.RaceProps.Humanlike)
            {
                Pawn              eater2         = eater;
                IntVec3           position       = getter.Position;
                List <Thing>      searchSet      = getter.Map.listerThings.ThingsMatching(thingRequest);
                PathEndMode       peMode         = PathEndMode.ClosestTouch;
                TraverseParms     traverseParams = TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false);
                Predicate <Thing> validator      = foodValidator;
                bestThing = FoodUtility.SpawnedFoodSearchInnerScan(eater2, position, searchSet, peMode, traverseParams, 9999f, validator);
                if (allowHarvest && getterCanManipulate)
                {
                    Thing thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.HarvestablePlant), PathEndMode.Touch, TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing x)
                    {
                        Plant plant = (Plant)x;
                        if (!plant.HarvestableNow)
                        {
                            return(false);
                        }
                        ThingDef harvestedThingDef = plant.def.plant.harvestedThingDef;
                        if (!harvestedThingDef.IsNutritionGivingIngestible)
                        {
                            return(false);
                        }
                        if (!getter.CanReserve(plant, 1, -1, null, false))
                        {
                            return(false);
                        }
                        if (!allowForbidden && plant.IsForbidden(getter))
                        {
                            return(false);
                        }
                        if (bestThing != null && (int)FoodUtility.GetFinalIngestibleDef(bestThing, false).ingestible.preferability >= (int)harvestedThingDef.ingestible.preferability)
                        {
                            return(false);
                        }
                        return(true);
                    }, null, 0, 30, false, RegionType.Set_Passable, false);
                    if (thing != null)
                    {
                        bestThing = thing;
                        foodDef   = FoodUtility.GetFinalIngestibleDef(thing, true);
                    }
                }
                if (foodDef == null && bestThing != null)
                {
                    foodDef = FoodUtility.GetFinalIngestibleDef(bestThing, false);
                }
            }
            else
            {
                int searchRegionsMax = 30;
                if (getter.Faction == Faction.OfPlayer)
                {
                    searchRegionsMax = 100;
                }
                FoodUtility.filtered.Clear();
                foreach (Thing item in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true))
                {
                    Pawn pawn = item as Pawn;
                    if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing)
                    {
                        FoodUtility.filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing);
                    }
                }
                bool flag = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings != null && getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null;
                Predicate <Thing> predicate = delegate(Thing t)
                {
                    if (!foodValidator(t))
                    {
                        return(false);
                    }
                    if (FoodUtility.filtered.Contains(t))
                    {
                        return(false);
                    }
                    if (!(t is Building_NutrientPasteDispenser) && (int)t.def.ingestible.preferability <= 2)
                    {
                        return(false);
                    }
                    if (t.IsNotFresh())
                    {
                        return(false);
                    }
                    return(true);
                };
                IntVec3           position       = getter.Position;
                Map               map            = getter.Map;
                ThingRequest      thingReq       = thingRequest;
                PathEndMode       peMode         = PathEndMode.ClosestTouch;
                TraverseParms     traverseParams = TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false);
                Predicate <Thing> validator      = predicate;
                bool              ignoreEntirelyForbiddenRegions = flag;
                bestThing = GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, 9999f, validator, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);
                FoodUtility.filtered.Clear();
                if (bestThing == null)
                {
                    desperate      = true;
                    position       = getter.Position;
                    map            = getter.Map;
                    thingReq       = thingRequest;
                    peMode         = PathEndMode.ClosestTouch;
                    traverseParams = TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false);
                    validator      = foodValidator;
                    ignoreEntirelyForbiddenRegions = flag;
                    bestThing = GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, 9999f, validator, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);
                }
                if (bestThing != null)
                {
                    foodDef = FoodUtility.GetFinalIngestibleDef(bestThing, false);
                }
            }
            return(bestThing);
        }