public ThingFilterStats(ThingFilter f) { this.allowedHitPointsPercents = f.AllowedHitPointsPercents; this.allowedHitPointsConfigurable = f.allowedHitPointsConfigurable; this.allowedQualitiesConfigurable = f.allowedQualitiesConfigurable; this.disallowWorsePreferability = GetDisallowWorsePreferability(f); this.disallowInedibleByHuman = GetDisallowInedibleByHuman(f); this.disallowCheaperThan = GetDisallowCheaperThan(f); this.allowedDefs = Util.CreateDefStatList(GetAllowedDefs(f)); if (GetAllowedQualities(f) != null) { this.allowedQualities = new QualityRangeStats(GetAllowedQualities(f)); } this.disallowedThingDefs = Util.CreateDefStatList(GetDisallowedThingDefs(f)); this.allowAllWhoCanMake = Util.CreateDefStatList(GetAllowAllWhoCanMake(f)); this.stuffCategoriesToAllow = Util.CreateDefStatList(GetStuffCategoriesToAllow(f)); this.disallowedSpecialFilters = Util.CreateDefStatList(GetDisallowedSpecialFilters(f)); this.thingDefs = Util.CreateDefStatList(GetThingDefs(f)); this.categories = Util.CreateList(GetCategories(f)); this.tradeTagsToAllow = Util.CreateList(GetTradeTagsToAllow(f)); this.tradeTagsToDisallow = Util.CreateList(GetTradeTagsToDisallow(f)); this.thingSetMakerTagsToAllow = Util.CreateList(GetThingSetMakerTagsToAllow(f)); this.thingSetMakerTagsToDisallow = Util.CreateList(GetThingSetMakerTagsToDisallow(f)); this.disallowedCategories = Util.CreateList(GetDisallowedCategories(f)); this.specialFiltersToAllow = Util.CreateList(GetSpecialFiltersToAllow(f)); this.specialFiltersToDisallow = Util.CreateList(GetSpecialFiltersToDisallow(f)); }
public virtual void CopyAllowancesFrom(ThingFilter other) { this.allowedDefs.Clear(); foreach (ThingDef thingDef in ThingFilter.AllStorableThingDefs) { this.SetAllow(thingDef, other.Allows(thingDef)); } this.disallowedSpecialFilters = other.disallowedSpecialFilters.ListFullCopyOrNull <SpecialThingFilterDef>(); this.allowedHitPointsPercents = other.allowedHitPointsPercents; this.allowedHitPointsConfigurable = other.allowedHitPointsConfigurable; this.allowedQualities = other.allowedQualities; this.allowedQualitiesConfigurable = other.allowedQualitiesConfigurable; this.thingDefs = other.thingDefs.ListFullCopyOrNull <ThingDef>(); this.categories = other.categories.ListFullCopyOrNull <string>(); this.tradeTagsToAllow = other.tradeTagsToAllow.ListFullCopyOrNull <string>(); this.tradeTagsToDisallow = other.tradeTagsToDisallow.ListFullCopyOrNull <string>(); this.thingSetMakerTagsToAllow = other.thingSetMakerTagsToAllow.ListFullCopyOrNull <string>(); this.thingSetMakerTagsToDisallow = other.thingSetMakerTagsToDisallow.ListFullCopyOrNull <string>(); this.disallowedCategories = other.disallowedCategories.ListFullCopyOrNull <string>(); this.specialFiltersToAllow = other.specialFiltersToAllow.ListFullCopyOrNull <string>(); this.specialFiltersToDisallow = other.specialFiltersToDisallow.ListFullCopyOrNull <string>(); this.stuffCategoriesToAllow = other.stuffCategoriesToAllow.ListFullCopyOrNull <StuffCategoryDef>(); this.allowAllWhoCanMake = other.allowAllWhoCanMake.ListFullCopyOrNull <ThingDef>(); this.disallowWorsePreferability = other.disallowWorsePreferability; this.disallowInedibleByHuman = other.disallowInedibleByHuman; this.allowWithComp = other.allowWithComp; this.disallowWithComp = other.disallowWithComp; this.disallowCheaperThan = other.disallowCheaperThan; this.disallowedThingDefs = other.disallowedThingDefs.ListFullCopyOrNull <ThingDef>(); if (this.settingsChangedCallback != null) { this.settingsChangedCallback(); } }
static void Postfix(ref Thing __result, Pawn holder, Pawn eater = null, FoodPreferability minFoodPref = FoodPreferability.NeverForNutrition, FoodPreferability maxFoodPref = FoodPreferability.MealLavish, float minStackNutrition = 0f, bool allowDrug = false) { if (!ModSetting.priorityRoomFood) { return; } ModData.findedInventoryFoodID = null; if (holder == null || holder.inventory == null) { return; } if (eater == null || eater.GetUniqueLoadID() == holder.GetUniqueLoadID())//操作者和吃饭者得为一个生物 { if (!holder.IsColonist) { return; } if (holder.RaceProps.Humanlike && holder.Spawned && holder.needs.food.CurLevelPercentage > holder.RaceProps.FoodLevelPercentageWantEat * 0.45f && holder.Map.areaManager.Home[holder.Position]) {//为人类 存在 在居住区 食物需要百分比大于想吃百分比*0.45 //Log.Message("down inventory food"); ModData.findedInventoryFoodID = __result.GetUniqueLoadID(); return;//记录找到的背包食物 } } //Log.Message("normal inventory food"); }
static bool Prefix( ref Thing __result, [NotNull] Pawn getter, [NotNull] Pawn eater, bool desperate, ref 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, bool forceScanWholeMap = false, bool ignoreReservations = false, FoodPreferability minPrefOverride = FoodPreferability.Undefined) { if (ShouldUseOptimizedCode(eater)) { __result = PMFoodUtilities.BestFoodSourceOnMapOptimized(getter, eater, desperate, out foodDef, maxPref, allowPlant, allowDrug, allowCorpse, allowDispenserFull, allowDispenserEmpty, allowForbidden, allowSociallyImproper, allowHarvest, forceScanWholeMap, ignoreReservations, minPrefOverride); return(false); } return(true); }
public FoodSearchParameters( Pawn getter, Pawn eater, bool desperate, bool canUseInventory, FoodPreferability maxPref, bool allowPlant, bool allowDrug, bool allowCorpse, bool allowDispenserFull, bool allowDispenserEmpty, bool allowForbidden, bool allowSociallyImproper, bool allowHarvest, bool forceScanWholeMap) { Getter = getter; Eater = eater; Desperate = desperate; CanUseInventory = canUseInventory; MaxPref = maxPref; AllowPlant = allowPlant; AllowDrug = allowDrug; AllowCorpse = allowCorpse; AllowDispenserFull = allowDispenserFull; AllowDispenserEmpty = allowDispenserEmpty; AllowForbidden = allowForbidden; AllowSociallyImproper = allowSociallyImproper; AllowHarvest = allowHarvest; ForceScanWholeMap = forceScanWholeMap; }
static Thing BestFoodInInventoryWNutrLimit(Pawn holder, Pawn eater = null, FoodPreferability minFoodPref = FoodPreferability.NeverForNutrition, FoodPreferability maxFoodPref = FoodPreferability.MealLavish, float minStackNutrition = 0f, bool allowDrug = false, float maxIndividualNutrition = 1000f) { if (holder.inventory == null) { return(null); } if (eater == null) { eater = holder; } ThingOwner <Thing> innerContainer = holder.inventory.innerContainer; for (int i = 0; i < innerContainer.Count; i++) { Thing thing = innerContainer[i]; var nutrition = thing.GetStatValue(StatDefOf.Nutrition, true); if (thing.def.IsNutritionGivingIngestible && thing.IngestibleNow && eater.WillEat(thing, holder, true) && thing.def.ingestible.preferability >= minFoodPref && thing.def.ingestible.preferability <= maxFoodPref && (allowDrug || !thing.def.IsDrug) && nutrition * thing.stackCount >= minStackNutrition && nutrition <= maxIndividualNutrition) { return(thing); } } return(null); }
public virtual void CopyAllowancesFrom(ThingFilter other) { allowedDefs.Clear(); foreach (ThingDef allDef in DefDatabase <ThingDef> .AllDefs) { SetAllow(allDef, other.Allows(allDef)); } disallowedSpecialFilters = other.disallowedSpecialFilters.ListFullCopyOrNull(); allowedHitPointsPercents = other.allowedHitPointsPercents; allowedHitPointsConfigurable = other.allowedHitPointsConfigurable; allowedQualities = other.allowedQualities; allowedQualitiesConfigurable = other.allowedQualitiesConfigurable; thingDefs = other.thingDefs.ListFullCopyOrNull(); categories = other.categories.ListFullCopyOrNull(); tradeTagsToAllow = other.tradeTagsToAllow.ListFullCopyOrNull(); tradeTagsToDisallow = other.tradeTagsToDisallow.ListFullCopyOrNull(); thingSetMakerTagsToAllow = other.thingSetMakerTagsToAllow.ListFullCopyOrNull(); thingSetMakerTagsToDisallow = other.thingSetMakerTagsToDisallow.ListFullCopyOrNull(); disallowedCategories = other.disallowedCategories.ListFullCopyOrNull(); specialFiltersToAllow = other.specialFiltersToAllow.ListFullCopyOrNull(); specialFiltersToDisallow = other.specialFiltersToDisallow.ListFullCopyOrNull(); stuffCategoriesToAllow = other.stuffCategoriesToAllow.ListFullCopyOrNull(); allowAllWhoCanMake = other.allowAllWhoCanMake.ListFullCopyOrNull(); disallowWorsePreferability = other.disallowWorsePreferability; disallowInedibleByHuman = other.disallowInedibleByHuman; allowWithComp = other.allowWithComp; disallowWithComp = other.disallowWithComp; disallowCheaperThan = other.disallowCheaperThan; disallowedThingDefs = other.disallowedThingDefs.ListFullCopyOrNull(); if (settingsChangedCallback != null) { settingsChangedCallback(); } }
public static Thing BestFoodInInventory(Pawn holder, Pawn eater = null, FoodPreferability minFoodPref = FoodPreferability.NeverForNutrition, FoodPreferability maxFoodPref = FoodPreferability.MealLavish, float minStackNutrition = 0f, bool allowDrug = false) { if (holder.inventory == null) { return(null); } if (eater == null) { eater = holder; } ThingOwner <Thing> innerContainer = holder.inventory.innerContainer; for (int i = 0; i < innerContainer.Count; i++) { Thing thing = innerContainer[i]; if (thing.def.IsNutritionGivingIngestible && thing.IngestibleNow && eater.RaceProps.CanEverEat(thing) && (int)thing.def.ingestible.preferability >= (int)minFoodPref && (int)thing.def.ingestible.preferability <= (int)maxFoodPref && (allowDrug || !thing.def.IsDrug)) { float num = thing.def.ingestible.nutrition * (float)thing.stackCount; if (num >= minStackNutrition) { return(thing); } } } return(null); }
public static bool Listener1( Pawn getter, Pawn eater, bool desperate, 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, bool forceScanWholeMap = false) { if (!Settings.androidsCanConsumeLivingPlants) { Settings.androidsCanConsumeLivingPlants = true; } if (Settings.androidsCanConsumeLivingPlants && eater != null && eater.IsAndroidTier() && eater == getter) { getter.RaceProps.intelligence = Intelligence.Animal; } return(true); }
public IngestiblePropertiesStats(IngestibleProperties p) { this.maxNumToIngestAtOnce = p.maxNumToIngestAtOnce; this.baseIngestTicks = p.baseIngestTicks; this.chairSearchRadius = p.chairSearchRadius; this.useEatingSpeedStat = p.useEatingSpeedStat; //this.ingestCommandString = p.ingestCommandString; //this.ingestReportString = p.ingestReportString; //this.ingestReportStringEat = p.ingestReportStringEat; this.ingestHoldUsesTable = p.ingestHoldUsesTable; this.foodType = p.foodType; this.joy = p.joy; this.preferability = p.preferability; this.nurseable = p.nurseable; this.optimalityOffsetHumanlikes = p.optimalityOffsetHumanlikes; this.optimalityOffsetFeedingAnimals = p.optimalityOffsetFeedingAnimals; this.drugCategory = p.drugCategory; if (p.ingestHoldOffsetStanding != null) { this.ingestHoldOffsetStanding = new HoldOffsetSetStats(p.ingestHoldOffsetStanding); } //Util.AssignDefStat(p.parent, out this.parent); Util.AssignDefStat(p.joyKind, out this.joyKind); Util.AssignDefStat(p.sourceDef, out this.sourceDef); Util.AssignDefStat(p.tasteThought, out this.tasteThought); Util.AssignDefStat(p.specialThoughtDirect, out this.specialThoughtDirect); Util.AssignDefStat(p.specialThoughtAsIngredient, out this.specialThoughtAsIngredient); Util.AssignDefStat(p.ingestEffect, out this.ingestEffect); Util.AssignDefStat(p.ingestEffectEat, out this.ingestEffectEat); Util.AssignDefStat(p.ingestSound, out this.ingestSound); }
public static void Prefix(Pawn getter, Pawn eater, ref FoodPreferability minPrefOverride, ref bool allowCorpse, ref bool allowSociallyImproper) { if (eater.isKroot()) { minPrefOverride = FoodPreferability.DesperateOnly; allowCorpse = true; allowSociallyImproper = true; } }
/// <summary> /// Tries the find best food source for the given getter and eater. /// </summary> /// Tries to find the best food source for the given getter and eater, taking into account humanoids that can eat plants /// <param name="getter">The getter.</param> /// <param name="eater">The eater.</param> /// <param name="desperate">if set to <c>true</c> [desperate].</param> /// <param name="foodSource">The food source.</param> /// <param name="foodDef">The food definition.</param> /// <param name="canRefillDispenser">if set to <c>true</c> [can refill dispenser].</param> /// <param name="canUseInventory">if set to <c>true</c> [can use inventory].</param> /// <param name="allowForbidden">if set to <c>true</c> [allow forbidden].</param> /// <param name="allowCorpse">if set to <c>true</c> [allow corpse].</param> /// <param name="allowSociallyImproper">if set to <c>true</c> [allow socially improper].</param> /// <param name="allowHarvest">if set to <c>true</c> [allow harvest].</param> /// <param name="forceScanWholeMap">if set to <c>true</c> [force scan whole map].</param> /// <param name="ignoreReservations">if set to <c>true</c> [ignore reservations].</param> /// <param name="minPrefOverride">The minimum preference override.</param> /// <returns></returns> public static bool TryFindBestFoodSourceForOptimized( 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 ignoreReservations = false, FoodPreferability minPrefOverride = FoodPreferability.Undefined) { bool canDoManipulation = getter.IsToolUser() && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); bool allowDrug = !eater.IsTeetotaler(); Thing thing1 = null; if (canUseInventory) { if (canDoManipulation) { thing1 = FoodUtility.BestFoodInInventory(getter, eater, minPrefOverride == FoodPreferability.Undefined ? FoodPreferability.MealAwful : minPrefOverride); } if (thing1 != null) { if (getter.Faction != Faction.OfPlayer) { foodSource = thing1; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource); return(true); } var comp = thing1.TryGetComp <CompRottable>(); if (comp != null && comp.Stage == RotStage.Fresh && comp.TicksUntilRotAtCurrentTemp < 30000) { foodSource = thing1; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource); return(true); } } } Pawn getter1 = getter; Pawn eater1 = eater; int num1 = desperate ? 1 : 0; ThingDef foodDef1 = null; ref ThingDef local = ref foodDef1;
private static float GetEdibleStuff(Map map) { float num = 0f; var selectedPreferability = LoadedModManager.GetMod <FoodAlertMod>().GetSettings <FoodAlertSettings>().foodPreferability; FoodPreferability selectedPreferabilityEnum = (FoodPreferability)Enum.Parse(typeof(FoodPreferability), selectedPreferability); foreach (KeyValuePair <ThingDef, int> keyValuePair in map.resourceCounter.AllCountedAmounts) { if (keyValuePair.Key.IsNutritionGivingIngestible && keyValuePair.Key.ingestible.HumanEdible) { if (selectedPreferabilityEnum > keyValuePair.Key.ingestible.preferability) { continue; } num += keyValuePair.Key.GetStatValueAbstract(StatDefOf.Nutrition, null) * (float)keyValuePair.Value; } } return(num); }
static bool Prefix(ref Thing __result, Pawn holder, Pawn eater = null, FoodPreferability minFoodPref = FoodPreferability.NeverForNutrition, FoodPreferability maxFoodPref = FoodPreferability.MealLavish, float minStackNutrition = 0f, bool allowDrug = false) { if (holder == null || holder.inventory == null) { return(false); } if (eater == null) { eater = holder; } if (eater == null || eater.Faction == null || !eater.Faction.IsPlayer) { return(true); } Comp_PawnMenu comp = eater.GetComp <Comp_PawnMenu>(); if (comp == null) { return(true); } if (!comp.activated()) { return(true); } ThingOwner <Thing> innerContainer = holder.inventory.innerContainer; for (int i = 0; i < innerContainer.Count; i++) { Thing thing = innerContainer[i]; if (thing.def.IsNutritionGivingIngestible && thing.IngestibleNow && eater.RaceProps.CanEverEat(thing) && thing.def.ingestible.preferability >= minFoodPref && thing.def.ingestible.preferability <= maxFoodPref && (allowDrug || !thing.def.IsDrug) && comp.contains(thing.def)) { float num = thing.def.ingestible.nutrition * (float)thing.stackCount; if (num >= minStackNutrition) { __result = thing; return(false); } } } return(true); }
private static float FoodSourceOptimality(Pawn eater, Thing t, float dist) { float num = 300f; num -= dist; ThingDef thingDef = (!(t is Building_NutrientPasteDispenser)) ? t.def : ThingDefOf.MealNutrientPaste; FoodPreferability preferability = thingDef.ingestible.preferability; if (preferability != FoodPreferability.NeverForNutrition) { if (preferability == FoodPreferability.DesperateOnly) { num -= 150f; } CompRottable compRottable = t.TryGetComp <CompRottable>(); if (compRottable != null) { if (compRottable.Stage == RotStage.Dessicated) { return(-9999999f); } if (compRottable.Stage == RotStage.Fresh && compRottable.TicksUntilRotAtCurrentTemp < 30000) { num += 12f; } } if (eater.needs != null && eater.needs.mood != null) { List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(eater, t); for (int i = 0; i < list.Count; i++) { num += FoodOptimalityEffectFromMoodCurve.Evaluate(list[i].stages[0].baseMoodEffect); } } num += thingDef.ingestible.optimalityOffset; return(num); } return(-9999999f); }
public static Thing BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate, 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) { var getterCanManipulate = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); if (!getterCanManipulate && getter != eater) { Log.Error(string.Concat(getter, " tried to find food to bring to ", eater, " but ", getter, " is incapable of Manipulation.")); return(null); } FoodPreferability minPref; if (!eater.RaceProps.Humanlike || eater == getter && eater.IsPrisoner) { minPref = FoodPreferability.NeverForNutrition; } else if (desperate) { minPref = FoodPreferability.DesperateOnly; } else { minPref = eater.needs.food.CurCategory <= HungerCategory.UrgentlyHungry ? FoodPreferability.RawBad : FoodPreferability.MealAwful; } Predicate <Thing> foodValidator = delegate(Thing t) { if (PrisonerFoodReservation.isReserved(t) && (eater != getter || !eater.IsPrisoner) && !desperate) { return(false); } if (!allowForbidden && t.IsForbidden(getter)) { return(false); } var building_NutrientPasteDispenser = t as Building_NutrientPasteDispenser; if (building_NutrientPasteDispenser != null) { if (!allowDispenserFull || ThingDefOf.MealNutrientPaste.ingestible.preferability < minPref || ThingDefOf.MealNutrientPaste.ingestible.preferability > maxPref || !getterCanManipulate || t.Faction != getter.Faction && t.Faction != getter.HostFaction || !building_NutrientPasteDispenser.powerComp.PowerOn || !allowDispenserEmpty && !building_NutrientPasteDispenser.HasEnoughFeedstockInHoppers() || !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))) { return(false); } } else { if (t.def.ingestible.preferability < minPref) { return(false); } if (t.def.ingestible.preferability > 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) || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || !getter.AnimalAwareOf(t) || !getter.CanReserve(t, 1, -1, null, false)) { return(false); } } return(true); }; ThingRequest thingRequest; if ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) != FoodTypeFlags.None && allowPlant) { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSource); } else { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree); } Thing thing; if (getter.RaceProps.Humanlike) { var validator = foodValidator; thing = SpawnedFoodSearchInnerScan(eater, getter.Position, getter.Map.listerThings.ThingsMatching(thingRequest), PathEndMode.ClosestTouch, TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator); } else { var searchRegionsMax = 30; if (getter.Faction == Faction.OfPlayer) { searchRegionsMax = 100; } filtered.Clear(); foreach (var current in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true)) { var pawn = current as Pawn; if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing) { filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing); } } var flag = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings != null && getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null; Predicate <Thing> predicate = t => foodValidator(t) && !filtered.Contains(t) && t.def.ingestible.preferability > FoodPreferability.DesperateOnly && !t.IsNotFresh(); var validator = predicate; var ignoreEntirelyForbiddenRegions = flag; thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); filtered.Clear(); if (thing == null) { desperate = true; validator = foodValidator; ignoreEntirelyForbiddenRegions = flag; thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); } } return(thing); }
private static bool Prefix(ref Thing __result, Pawn holder, Pawn eater = null, FoodPreferability minFoodPref = FoodPreferability.NeverForNutrition, FoodPreferability maxFoodPref = FoodPreferability.MealLavish, float minStackNutrition = 0.0f, bool allowDrug = false) { if (!Registry.IsActive) { return(true); } if (eater == null) { eater = holder; } var rules = Registry.GetRules(eater); if (eater.InMentalState || (rules == null) || rules.GetRestriction(RestrictionType.Food).IsVoid) { return(true); } if (holder.inventory == null) { __result = null; return(false); } var innerContainer = holder.inventory.innerContainer; foreach (var thing in innerContainer) { if (rules.GetRestriction(RestrictionType.Food).Allows(thing.def) && thing.def.IsNutritionGivingIngestible && thing.IngestibleNow && eater.RaceProps.CanEverEat(thing) && (thing.def.ingestible.preferability >= minFoodPref) && (thing.def.ingestible.preferability <= maxFoodPref) && (allowDrug || !thing.def.IsDrug) && (thing.GetStatValue(StatDefOf.Nutrition) * thing.stackCount >= (double)minStackNutrition)) { __result = thing; } return(false); } __result = null; return(false); }
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); }
internal static Thing _BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate, FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowLiquor = true, bool allowCorpse = true, bool allowDispenserFull = true, bool allowDispenserEmpty = true, bool allowForbidden = false) { Profiler.BeginSample("BestFoodInWorldFor getter=" + getter.LabelCap + " eater=" + eater.LabelCap); var getterCanManipulate = ( (getter.RaceProps.ToolUser) && (getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) ); if ( (!getterCanManipulate) && (getter != eater) ) { Log.Error(string.Format("{0} tried to find food to bring to {1} but {0} is incapable of Manipulation.", getter.LabelCap, eater.LabelCap)); Profiler.EndSample(); return(null); } var validator = new DispenserValidator(); validator.getterCanManipulate = getterCanManipulate; validator.allowDispenserFull = allowDispenserFull; validator.maxPref = maxPref; validator.allowForbidden = allowForbidden; validator.getter = getter; validator.allowDispenserEmpty = allowDispenserEmpty; validator.allowCorpse = allowCorpse; validator.allowLiquor = allowLiquor; validator.desperate = desperate; validator.eater = eater; validator.allowLiquor &= !desperate; validator.minPref = desperate ? FoodPreferability.DesperateOnly : !eater.RaceProps.Humanlike ? FoodPreferability.NeverForNutrition : eater.needs.food.CurCategory >= HungerCategory.UrgentlyHungry ? FoodPreferability.RawBad : FoodPreferability.MealAwful; var thingRequest = ( ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) == FoodTypeFlags.None) || (!allowPlant) ) ? ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree) : ThingRequest.ForGroup(ThingRequestGroup.FoodSource); var thingsRequested = Find.ListerThings.ThingsMatching(thingRequest); //DumpThingsRequestedForGroup( thingRequest, thingsRequested ); var potentialFoodSource = (Thing)null; if (getter.RaceProps.Humanlike) { //CCL_Log.Message( "Humanlike inner scan..." ); potentialFoodSource = SpawnedFoodSearchInnerScan( eater, getter.Position, thingsRequested, PathEndMode.ClosestTouch, TraverseParms.For( getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator.ValidateFast); } else { //CCL_Log.Message( "Non-humanlike closest reachable..." ); int searchRegionsMax = 30; if (getter.Faction == Faction.OfPlayer) { searchRegionsMax = 60; } potentialFoodSource = GenClosest.ClosestThingReachable( getter.Position, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For( getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator.Validate, null, searchRegionsMax, false); if (potentialFoodSource == null) { //CCL_Log.Message( "Non-humanlike closest reachable desperate..." ); validator.desperate = true; potentialFoodSource = GenClosest.ClosestThingReachable( getter.Position, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For( getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator.ValidateFast, null, searchRegionsMax, false); } } Profiler.EndSample(); //CCL_Log.Message( string.Format( "{0} picked {1} for {2}", getter.LabelShort, potentialFoodSource == null ? "nothing" : potentialFoodSource.ThingID, eater.LabelShort ) ); return(potentialFoodSource); }
// Token: 0x0600017C RID: 380 RVA: 0x0000DB3C File Offset: 0x0000BF3C public 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 flag2 = !eater.IsTeetotaler(); Thing thing = null; ThingDef thingDef = null; ThingDef foodDef2 = thingDef; bool allowPlant = getter == eater; Thing thing2 = FoodUtility.BestFoodSourceOnMap(getter, eater, desperate, out foodDef2, FoodPreferability.Undefined, allowPlant, flag2, allowCorpse, true, canRefillDispenser, allowForbidden, allowSociallyImproper, allowHarvest, forceScanWholeMap); if (thing == null && thing2 == null) { if (canUseInventory && flag) { FoodPreferability minFoodPref = FoodPreferability.DesperateOnly; bool allowDrug = flag2; thing = FoodUtility.BestFoodInInventory(getter, eater, minFoodPref, 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() && !getter.IsPrisoner))) { Pawn pawn = BestPawnToHuntForPredator(getter, forceScanWholeMap); 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 -= 32f; if (num > num2) { foodSource = thing2; foodDef = thingDef; return(true); } foodSource = thing; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, false); return(true); }
// There might be a cleaner way to do what looks like a deep neural network. private static FoodCategory _DetermineFoodCategory(ThingDef def) { var array = Enum.GetValues(typeof(FoodCategory)); var CategoryScores = new Dictionary <FoodCategory, float>(array.Length); foreach (FoodCategory entry in array) { CategoryScores.Add(entry, 0f); } if (def == ThingDefOf.NutrientPasteDispenser) { return(FoodCategory.MealAwful); } if (def.race != null) { CategoryScores[FoodCategory.Hunt] = float.MaxValue; } if (def.ingestible != null) { if (def.ingestible.nutrition <= 0f || def.IsDrug) { CategoryScores[FoodCategory.Ignore] = float.MaxValue; } FoodPreferability foodPref = def.ingestible.preferability; FoodTypeFlags foodType = def.ingestible.foodType; string defName = def.defName; switch (foodPref) { case FoodPreferability.MealFine: CategoryScores[FoodCategory.MealFine] += 100f; break; case FoodPreferability.MealAwful: CategoryScores[FoodCategory.MealAwful] += 100f; break; case FoodPreferability.MealSimple: CategoryScores[FoodCategory.MealSimple] += 100f; break; case FoodPreferability.MealLavish: CategoryScores[FoodCategory.MealLavish] += 100f; break; } if (!def.HasComp(typeof(CompRottable)) && (foodType & FoodTypeFlags.Meal) != 0) { CategoryScores[FoodCategory.MealSurvival] += 150f; } if ((foodType & FoodTypeFlags.Kibble) != 0) { CategoryScores[FoodCategory.Kibble] += 200f; } if ((foodType & FoodTypeFlags.AnimalProduct) != 0) { if (def.GetCompProperties <CompProperties_Hatcher>() != null) { CategoryScores[FoodCategory.FertEggs] += 500f; } //return WMFoodPref.Null; } if (def.ingestible.joyKind == JoyKindDefOf.Gluttonous && def.ingestible.joy >= 0.05f) { CategoryScores[FoodCategory.Luxury] += 500f; } if ((foodType & FoodTypeFlags.Tree) != 0) { CategoryScores[FoodCategory.Tree] += 500f; } if ((foodType & FoodTypeFlags.Plant) != 0) { if (def.plant == null) { CategoryScores[FoodCategory.Hay] += 100f; } else { if (def.plant.sowTags != null && def.plant.sowTags.Any()) { CategoryScores[FoodCategory.Plant] += 100f; } else { CategoryScores[FoodCategory.Grass] += 50f; } if (def.plant.harvestedThingDef != null) { CategoryScores[FoodCategory.Plant] += 200f; } if (def.plant.reproduces) { CategoryScores[FoodCategory.Grass] += 100f; } } } if (RimWorld.FoodUtility.IsHumanlikeMeat(def)) { CategoryScores[FoodCategory.RawHuman] += 50f; CategoryScores[FoodCategory.HumanlikeCorpse] += 50f; } if (def.IsCorpse) { CategoryScores[FoodCategory.Corpse] += 80f; CategoryScores[FoodCategory.HumanlikeCorpse] += 50f; CategoryScores[FoodCategory.InsectCorpse] += 50f; if (def.FirstThingCategory == ThingCategoryDefOf.CorpsesInsect) { CategoryScores[FoodCategory.InsectCorpse] += 50f; } if (def.ingestible.sourceDef.race.IsMechanoid) { CategoryScores[FoodCategory.Ignore] = float.MaxValue; } } if (def.ingestible.tasteThought != null && def.ingestible.tasteThought.stages.All((ThoughtStage arg) => arg.baseMoodEffect < 0)) { //if (def == ThingDef.Named("Megaspider_Meat")) if (def.ingestible.tasteThought == ThoughtDefOf.AteInsectMeatDirect) { CategoryScores[FoodCategory.InsectCorpse] += 50f; CategoryScores[FoodCategory.RawInsect] += 50f; } CategoryScores[FoodCategory.RawHuman] += 20f; CategoryScores[FoodCategory.RawBad] += 50f; } if ((def.ingestible.tasteThought == null || def.ingestible.tasteThought.stages.All((ThoughtStage arg) => arg.baseMoodEffect >= 0))) { CategoryScores[FoodCategory.RawTasty] += 20f; } //if ((foodType & FoodTypeFlags.AnimalProduct) != 0) // CategoryScores[FoodCategory.AnimalProduct] += 30f; if (foodPref == FoodPreferability.NeverForNutrition || def.IsDrug) { CategoryScores[FoodCategory.Ignore] = float.MaxValue; } } // non ingestible corpse ? //if (def.IsCorpse) // return FoodCategory.Ignore; var winner = CategoryScores.MaxBy(arg => arg.Value); var similar = CategoryScores.Where(arg => Mathf.Abs(arg.Value - winner.Value) < 10f); if (similar.Count() > 1) { Log.Warning("I'm not sure if " + def + " belongs to " + winner + " since others have similar scores: " + String.Join(" ; ", similar.Select(arg => arg.ToString()).ToArray())); } return(winner.Key); }
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, bool forceScanWholeMap = false, bool ignoreReservations = false, FoodPreferability minPrefOverride = FoodPreferability.Undefined) { foodDef = null; bool getterCanManipulate = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); if (!getterCanManipulate && getter != eater) { Log.Error(string.Concat(getter, " tried to find food to bring to ", eater, " but ", getter, " is incapable of Manipulation.")); return(null); } FoodPreferability minPref; if (minPrefOverride == FoodPreferability.Undefined) { if (eater.NonHumanlikeOrWildMan()) { minPref = FoodPreferability.NeverForNutrition; } else if (desperate) { minPref = FoodPreferability.DesperateOnly; } else { minPref = (((int)eater.needs.food.CurCategory >= 2) ? FoodPreferability.RawBad : FoodPreferability.MealAwful); } } else { minPref = minPrefOverride; } Predicate <Thing> foodValidator = delegate(Thing t) { Building_NutrientPasteDispenser building_NutrientPasteDispenser = t as Building_NutrientPasteDispenser; if (building_NutrientPasteDispenser != null) { if (!allowDispenserFull || !getterCanManipulate || (int)ThingDefOf.MealNutrientPaste.ingestible.preferability < (int)minPref || (int)ThingDefOf.MealNutrientPaste.ingestible.preferability > (int)maxPref || !eater.WillEat(ThingDefOf.MealNutrientPaste, getter) || (t.Faction != getter.Faction && t.Faction != getter.HostFaction) || (!allowForbidden && t.IsForbidden(getter)) || !building_NutrientPasteDispenser.powerComp.PowerOn || (!allowDispenserEmpty && !building_NutrientPasteDispenser.HasEnoughFeedstockInHoppers()) || !t.InteractionCell.Standable(t.Map) || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || !getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some))) { return(false); } } else { int stackCount = 1; if (bestFoodSourceOnMap_minNutrition_NewTemp.HasValue) { float statValue = t.GetStatValue(StatDefOf.Nutrition); stackCount = StackCountForNutrition(bestFoodSourceOnMap_minNutrition_NewTemp.Value, statValue); } if ((int)t.def.ingestible.preferability < (int)minPref || (int)t.def.ingestible.preferability > (int)maxPref || !eater.WillEat(t, getter) || !t.def.IsNutritionGivingIngestible || !t.IngestibleNow || (!allowCorpse && t is Corpse) || (!allowDrug && t.def.IsDrug) || (!allowForbidden && t.IsForbidden(getter)) || (!desperate && t.IsNotFresh()) || t.IsDessicated() || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || (!getter.AnimalAwareOf(t) && !forceScanWholeMap) || (!ignoreReservations && !getter.CanReserve(t, 10, stackCount))) { return(false); } } return(true); }; ThingRequest thingRequest = ((!((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) != 0 && allowPlant)) ? ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree) : ThingRequest.ForGroup(ThingRequestGroup.FoodSource)); Thing bestThing; if (getter.RaceProps.Humanlike) { bestThing = SpawnedFoodSearchInnerScan(eater, getter.Position, getter.Map.listerThings.ThingsMatching(thingRequest), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, foodValidator); if (allowHarvest && getterCanManipulate) { Thing thing = GenClosest.ClosestThingReachable(searchRegionsMax : (!forceScanWholeMap || bestThing != null) ? 30 : (-1), root : getter.Position, map : getter.Map, thingReq : ThingRequest.ForGroup(ThingRequestGroup.HarvestablePlant), peMode : PathEndMode.Touch, traverseParams : TraverseParms.For(getter), maxDistance : 9999f, validator : delegate(Thing x) { Plant plant = (Plant)x; if (!plant.HarvestableNow) { return(false); } ThingDef harvestedThingDef = plant.def.plant.harvestedThingDef; if (!harvestedThingDef.IsNutritionGivingIngestible) { return(false); } if (!eater.WillEat(harvestedThingDef, getter)) { return(false); } if (!getter.CanReserve(plant)) { return(false); } if (!allowForbidden && plant.IsForbidden(getter)) { return(false); } return((bestThing == null || (int)GetFinalIngestibleDef(bestThing).ingestible.preferability < (int)harvestedThingDef.ingestible.preferability) ? true : false); }); if (thing != null) { bestThing = thing; foodDef = GetFinalIngestibleDef(thing, harvest: true); } } if (foodDef == null && bestThing != null) { foodDef = GetFinalIngestibleDef(bestThing); } } else { int maxRegionsToScan = GetMaxRegionsToScan(getter, forceScanWholeMap); filtered.Clear(); foreach (Thing item in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, useCenter: 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) { filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing); } } bool ignoreEntirelyForbiddenRegions = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, cellTarget: true) && getter.playerSettings != null && getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null; Predicate <Thing> validator = delegate(Thing t) { if (!foodValidator(t)) { return(false); } if (filtered.Contains(t)) { return(false); } if (!(t is Building_NutrientPasteDispenser) && (int)t.def.ingestible.preferability <= 2) { return(false); } return((!t.IsNotFresh()) ? true : false); }; bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, validator, null, 0, maxRegionsToScan, forceAllowGlobalSearch: false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); filtered.Clear(); if (bestThing == null) { desperate = true; bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, foodValidator, null, 0, maxRegionsToScan, forceAllowGlobalSearch: false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); } if (bestThing != null) { foodDef = GetFinalIngestibleDef(bestThing); } } return(bestThing); }
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 ignoreReservations = false, FoodPreferability minPrefOverride = FoodPreferability.Undefined) { bool flag = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); bool allowDrug = !eater.IsTeetotaler(); Thing thing = null; if (canUseInventory) { if (flag) { thing = BestFoodInInventory(getter, eater, (minPrefOverride == FoodPreferability.Undefined) ? FoodPreferability.MealAwful : minPrefOverride); } if (thing != null) { if (getter.Faction != Faction.OfPlayer) { foodSource = thing; foodDef = GetFinalIngestibleDef(foodSource); return(true); } CompRottable compRottable = thing.TryGetComp <CompRottable>(); if (compRottable != null && compRottable.Stage == RotStage.Fresh && compRottable.TicksUntilRotAtCurrentTemp < 30000) { foodSource = thing; foodDef = GetFinalIngestibleDef(foodSource); return(true); } } } bool allowPlant = getter == eater; bool allowForbidden2 = allowForbidden; ThingDef foodDef2; Thing thing2 = BestFoodSourceOnMap(getter, eater, desperate, out foodDef2, FoodPreferability.MealLavish, allowPlant, allowDrug, allowCorpse, allowDispenserFull: true, canRefillDispenser, allowForbidden2, allowSociallyImproper, allowHarvest, forceScanWholeMap, ignoreReservations, minPrefOverride); if (thing != null || thing2 != null) { if (thing == null && thing2 != null) { foodSource = thing2; foodDef = foodDef2; return(true); } ThingDef finalIngestibleDef = GetFinalIngestibleDef(thing); if (thing2 == null) { foodSource = thing; foodDef = finalIngestibleDef; return(true); } float num = FoodOptimality(eater, thing2, foodDef2, (getter.Position - thing2.Position).LengthManhattan); float num2 = FoodOptimality(eater, thing, finalIngestibleDef, 0f); num2 -= 32f; if (num > num2) { foodSource = thing2; foodDef = foodDef2; return(true); } foodSource = thing; foodDef = GetFinalIngestibleDef(foodSource); return(true); } if (canUseInventory && flag) { thing = BestFoodInInventory(getter, eater, FoodPreferability.DesperateOnly, FoodPreferability.MealLavish, 0f, allowDrug); if (thing != null) { foodSource = thing; foodDef = GetFinalIngestibleDef(foodSource); return(true); } } if (thing2 == null && getter == eater && (getter.RaceProps.predator || (getter.IsWildMan() && !getter.IsPrisoner && !getter.WorkTypeIsDisabled(WorkTypeDefOf.Hunting)))) { Pawn pawn = BestPawnToHuntForPredator(getter, forceScanWholeMap); if (pawn != null) { foodSource = pawn; foodDef = GetFinalIngestibleDef(foodSource); return(true); } } foodSource = null; foodDef = null; return(false); }
private static bool Prefix(ref Thing __result, 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, bool forceScanWholeMap = false) { foodDef = null; if (!Registry.IsActive) { return(true); } var rules = Registry.GetRules(eater); if (eater.InMentalState || (rules == null) || rules.GetRestriction(RestrictionType.Food).IsVoid) { return(true); } Profiler.BeginSample("BestFoodInWorldFor getter=" + getter.LabelCap + " eater=" + eater.LabelCap); var 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."); Profiler.EndSample(); __result = null; return(false); } var minPref = !eater.NonHumanlikeOrWildMan() ? (!desperate ? (eater.needs.food.CurCategory < HungerCategory.UrgentlyHungry ? FoodPreferability.MealAwful : FoodPreferability.RawBad) : FoodPreferability.DesperateOnly) : FoodPreferability.NeverForNutrition; var foodValidator = (Predicate <Thing>)(thing => { Profiler.BeginSample("foodValidator"); if (!rules.GetRestriction(RestrictionType.Food).Allows(thing.def)) { Profiler.EndSample(); return(false); } if (thing is Building_NutrientPasteDispenser nutrientPasteDispenser) { if (!allowDispenserFull || !getterCanManipulate || (ThingDefOf.MealNutrientPaste.ingestible.preferability < minPref) || (ThingDefOf.MealNutrientPaste.ingestible.preferability > maxPref) || !eater.RaceProps.CanEverEat(ThingDefOf.MealNutrientPaste) || ((thing.Faction != getter.Faction) && (thing.Faction != getter.HostFaction)) || (!allowForbidden && thing.IsForbidden(getter)) || !nutrientPasteDispenser.powerComp.PowerOn || (!allowDispenserEmpty && !nutrientPasteDispenser.HasEnoughFeedstockInHoppers()) || !thing.InteractionCell.Standable(thing.Map) || !PrivateAccess.RimWorld_FoodUtility_IsFoodSourceOnMapSociallyProper(thing, getter, eater, allowSociallyImproper) || getter.IsWildMan() || !getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(thing.InteractionCell, thing.Map), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some))) { Profiler.EndSample(); return(false); } } else if ((thing.def.ingestible.preferability < minPref) || (thing.def.ingestible.preferability > maxPref) || !eater.RaceProps.WillAutomaticallyEat(thing) || !thing.def.IsNutritionGivingIngestible || !thing.IngestibleNow || (!allowCorpse && thing is Corpse) || (!allowDrug && thing.def.IsDrug) || (!allowForbidden && thing.IsForbidden(getter)) || (!desperate && thing.IsNotFresh()) || thing.IsDessicated() || !PrivateAccess.RimWorld_FoodUtility_IsFoodSourceOnMapSociallyProper(thing, getter, eater, allowSociallyImproper) || (!getter.AnimalAwareOf(thing) && !forceScanWholeMap) || !getter.CanReserve((LocalTargetInfo)thing)) { Profiler.EndSample(); return(false); } Profiler.EndSample(); return(true); }); var req = ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) == FoodTypeFlags.None) || !allowPlant?ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree) : ThingRequest.ForGroup(ThingRequestGroup.FoodSource); Thing bestThing; if (getter.RaceProps.Humanlike) { bestThing = PrivateAccess.RimWorld_FoodUtility_SpawnedFoodSearchInnerScan(eater, getter.Position, getter.Map.listerThings.ThingsMatching(req), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, foodValidator); if (allowHarvest && getterCanManipulate) { var searchRegionsMax = !forceScanWholeMap || (bestThing != null) ? 30 : -1; bool Validator(Thing thing) { if (!rules.GetRestriction(RestrictionType.Food).Allows(thing.def)) { return(false); } var plant = (Plant)thing; if (!plant.HarvestableNow) { return(false); } var harvestedThingDef = plant.def.plant.harvestedThingDef; return(harvestedThingDef.IsNutritionGivingIngestible && eater.RaceProps.CanEverEat(harvestedThingDef) && getter.CanReserve((LocalTargetInfo)plant) && (allowForbidden || !plant.IsForbidden(getter)) && ((bestThing == null) || (FoodUtility.GetFinalIngestibleDef(bestThing).ingestible.preferability < harvestedThingDef.ingestible.preferability))); } var foodSource = GenClosest.ClosestThingReachable(getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.HarvestablePlant), PathEndMode.Touch, TraverseParms.For(getter), 9999f, Validator, null, 0, searchRegionsMax); if (foodSource != null) { bestThing = foodSource; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, true); } } if ((foodDef == null) && (bestThing != null)) { foodDef = FoodUtility.GetFinalIngestibleDef(bestThing); } } else { var maxRegionsToScan = PrivateAccess.RimWorld_FoodUtility_GetMaxRegionsToScan(getter, forceScanWholeMap); PrivateAccess.RimWorld_FoodUtility_Filtered().Clear(); foreach (var thing in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true)) { if (thing is Pawn pawn && (pawn != getter) && pawn.RaceProps.Animal && (pawn.CurJob != null) && (pawn.CurJob.def == JobDefOf.Ingest) && pawn.CurJob.GetTarget(TargetIndex.A).HasThing) { PrivateAccess.RimWorld_FoodUtility_Filtered().Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing); } } var flag = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) && (getter.playerSettings?.EffectiveAreaRestrictionInPawnCurrentMap != null); var predicate = (Predicate <Thing>)(thing => foodValidator(thing) && !PrivateAccess.RimWorld_FoodUtility_Filtered().Contains(thing) && (thing is Building_NutrientPasteDispenser || (thing.def.ingestible.preferability > FoodPreferability.DesperateOnly)) && !thing.IsNotFresh()); var position1 = getter.Position; var map1 = getter.Map; var thingReq1 = req; var traverseParams1 = TraverseParms.For(getter); var validator1 = predicate; var ignoreEntirelyForbiddenRegions1 = flag; bestThing = GenClosest.ClosestThingReachable(position1, map1, thingReq1, PathEndMode.ClosestTouch, traverseParams1, 9999f, validator1, null, 0, maxRegionsToScan, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions1); PrivateAccess.RimWorld_FoodUtility_Filtered().Clear(); if (bestThing == null) { desperate = true; var position2 = getter.Position; var map2 = getter.Map; var thingReq2 = req; var traverseParams2 = TraverseParms.For(getter); var validator2 = foodValidator; var ignoreEntirelyForbiddenRegions2 = flag; bestThing = GenClosest.ClosestThingReachable(position2, map2, thingReq2, PathEndMode.ClosestTouch, traverseParams2, 9999f, validator2, null, 0, maxRegionsToScan, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions2); } if (bestThing != null) { foodDef = FoodUtility.GetFinalIngestibleDef(bestThing); } } Profiler.EndSample(); __result = bestThing; return(false); }
/// <summary> /// Gets the best food source on the map for the given getter and eater pawns /// </summary> /// this function gets the best food source on the map for the given pawns, making sure to optimize for the case where /// a humanoid pawn can eat plants /// <param name="getter">The getter.</param> /// <param name="eater">The eater.</param> /// <param name="desperate">if set to <c>true</c> [desperate].</param> /// <param name="foodDef">The food definition.</param> /// <param name="maxPref">The maximum preference.</param> /// <param name="allowPlant">if set to <c>true</c> [allow plant].</param> /// <param name="allowDrug">if set to <c>true</c> [allow drug].</param> /// <param name="allowCorpse">if set to <c>true</c> [allow corpse].</param> /// <param name="allowDispenserFull">if set to <c>true</c> [allow dispenser full].</param> /// <param name="allowDispenserEmpty">if set to <c>true</c> [allow dispenser empty].</param> /// <param name="allowForbidden">if set to <c>true</c> [allow forbidden].</param> /// <param name="allowSociallyImproper">if set to <c>true</c> [allow socially improper].</param> /// <param name="allowHarvest">if set to <c>true</c> [allow harvest].</param> /// <param name="forceScanWholeMap">if set to <c>true</c> [force scan whole map].</param> /// <param name="ignoreReservations">if set to <c>true</c> [ignore reservations].</param> /// <param name="minPrefOverride">The minimum preference override.</param> /// <returns></returns> public static Thing BestFoodSourceOnMapOptimized( [NotNull] Pawn getter, [NotNull] 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, bool forceScanWholeMap = false, bool ignoreReservations = false, FoodPreferability minPrefOverride = FoodPreferability.Undefined) { foodDef = null; HungerCategory foodCurCategory = eater.needs.food.CurCategory; bool getterCanManipulate = getter.IsToolUser() && 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 (minPrefOverride != FoodPreferability.Undefined) { minPref = minPrefOverride; } else if (!eater.NonHumanlikeOrWildMan()) //with the new patch, to 'recruit' sapient former humans pawns will need { if (!desperate) { if (foodCurCategory >= HungerCategory.UrgentlyHungry) { minPref = FoodPreferability.RawBad; } else { minPref = FoodPreferability.MealAwful; } } else { minPref = FoodPreferability.DesperateOnly; } } else { minPref = FoodPreferability.NeverForNutrition; } bool FoodValidator(Thing t) { if (allowDispenserFull && getterCanManipulate && t is Building_NutrientPasteDispenser nutrientPDispenser) { if (ThingDefOf.MealNutrientPaste.ingestible.preferability < minPref || ThingDefOf.MealNutrientPaste.ingestible.preferability > maxPref || !eater.WillEat(ThingDefOf.MealNutrientPaste, getter) || t.Faction != getter.Faction && t.Faction != getter.HostFaction || !allowForbidden && t.IsForbidden(getter) || !nutrientPDispenser.powerComp.PowerOn || !allowDispenserEmpty && !nutrientPDispenser.HasEnoughFeedstockInHoppers() || !t.InteractionCell.Standable(t.Map) || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || !getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some))) { return(false); } } else { FoodPreferability pref = GetAdjustedPreferability(eater, t); if (pref < minPref || pref > maxPref) { return(false); } if (!eater.WillEat(t, getter)) { return(false); } if (!t.def.IsNutritionGivingIngestible || !t.IngestibleNow) { return(false); } if (!allowCorpse && t is Corpse || !allowDrug && t.def.IsDrug || !allowForbidden && t.IsForbidden(getter) || !desperate && t.IsNotFresh() || t.IsDessicated() || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || !getter.AnimalAwareOf(t) && !forceScanWholeMap || !ignoreReservations && !getter.CanReserve((LocalTargetInfo)t, 10, 1)) { return(false); } } return(true); } ThingRequest thingRequest; if (!CanEatPlants(eater, allowPlant, foodCurCategory)) { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree); } else { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSource); } Thing bestThing; if (getter.IsHumanlike()) { //TODO split up search for hungry humanlike into 2 phases //whole map search for good food //small search for good plants bestThing = SpawnedFoodSearchInnerScan(eater, getter.Position, getter.Map.listerThings.ThingsMatching(thingRequest), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, FoodValidator); if (allowHarvest & getterCanManipulate) { int searchRegionsMax = !forceScanWholeMap || bestThing != null ? 30 : -1; bool HarvestValidator(Thing x) { var t = (Plant)x; if (!t.HarvestableNow) { return(false); } ThingDef harvestedThingDef = t.def.plant.harvestedThingDef; return(harvestedThingDef.IsNutritionGivingIngestible && eater.WillEat(harvestedThingDef, getter) && getter.CanReserve((LocalTargetInfo)t) && (allowForbidden || !t.IsForbidden(getter)) && (bestThing == null || FoodUtility.GetFinalIngestibleDef(bestThing) .ingestible.preferability < harvestedThingDef.ingestible.preferability)); } Thing foodSource = GenClosest.ClosestThingReachable(getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.HarvestablePlant), PathEndMode.Touch, TraverseParms.For(getter), 9999f, HarvestValidator, null, 0, searchRegionsMax); if (foodSource != null) { bestThing = foodSource; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, true); } } if (foodDef == null && bestThing != null) { foodDef = FoodUtility.GetFinalIngestibleDef(bestThing); } } else { int maxRegionsToScan = GetMaxRegionsToScan(getter, forceScanWholeMap, foodCurCategory); //this is where the lag comes from //humanlikes alwayse scan the whole map filtered.Clear(); foreach (Thing thing in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true)) { var pawn = thing as Pawn; if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing) { filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing); } } bool ignoreEntirelyForbiddenRegions = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings?.EffectiveAreaRestrictionInPawnCurrentMap != null; var validator = (Predicate <Thing>)(t => FoodValidator(t) && !filtered.Contains(t) && (t is Building_NutrientPasteDispenser || t.def.ingestible.preferability > FoodPreferability.DesperateOnly) && !t.IsNotFresh()); bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, validator, null, 0, maxRegionsToScan, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); filtered.Clear(); if (bestThing == null) { desperate = true; bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, FoodValidator, null, 0, maxRegionsToScan, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); } if (bestThing != null) { foodDef = FoodUtility.GetFinalIngestibleDef(bestThing); } } return(bestThing); }
// Token: 0x060000F1 RID: 241 RVA: 0x00008A58 File Offset: 0x00006C58 public static void TryFindBestFoodSourceFor_Prefix(ref bool __result, 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 animal = getter.RaceProps.Animal; bool flag2 = !eater.IsTeetotaler(); Thing thing = null; if (canUseInventory) { bool flag3 = animal; if (flag3) { thing = FoodUtility.BestFoodInInventory(getter, eater, FoodPreferability.MealAwful, FoodPreferability.MealLavish, 0f, false); } } bool flag4 = getter == eater; ThingDef thingDef; Thing thing2 = FoodUtility.BestFoodSourceOnMap(getter, eater, desperate, out thingDef, FoodPreferability.MealLavish, flag4, flag2, allowCorpse, true, canRefillDispenser, allowForbidden, allowSociallyImproper, allowHarvest, false); bool flag5 = thing == null && thing2 == null; if (flag5) { bool flag6 = canUseInventory && animal; if (flag6) { FoodPreferability minFoodPref = FoodPreferability.DesperateOnly; bool allowDrug = flag2; thing = FoodUtility.BestFoodInInventory(getter, eater, minFoodPref, FoodPreferability.MealLavish, 0f, allowDrug); bool flag7 = thing != null; if (flag7) { foodSource = thing; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, false); __result = true; } } foodSource = null; foodDef = null; __result = false; } bool flag8 = thing == null && thing2 != null; if (flag8) { foodSource = thing2; foodDef = thingDef; __result = true; } ThingDef finalIngestibleDef = FoodUtility.GetFinalIngestibleDef(thing, false); bool flag9 = thing2 == null; if (flag9) { foodSource = thing; foodDef = finalIngestibleDef; __result = 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 -= 32f; bool flag10 = num > num2; if (flag10) { foodSource = thing2; foodDef = thingDef; __result = true; } foodSource = thing; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, false); __result = true; }
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) { FoodUtility.< BestFoodSourceOnMap > c__AnonStorey0 <BestFoodSourceOnMap> c__AnonStorey = new FoodUtility.< BestFoodSourceOnMap > c__AnonStorey0();
static bool Prefix(Pawn eater, Pawn getter, bool allowPlant, bool allowForbidden, bool desperate, FoodPreferability maxPref, bool allowCorpse, bool allowDrug, out ThingDef foodDef, ref Thing __result) { foodDef = null; if (eater == null || eater.Faction == null || !eater.Faction.IsPlayer || eater.def.race.Humanlike) { return(true); } Comp_PawnMenu comp = eater.GetComp <Comp_PawnMenu>(); if (comp == null) { return(true); } if (!comp.activated()) { return(true); } FoodPreferability minPref = FoodPreferability.NeverForNutrition; Predicate <Thing> foodValidator = delegate(Thing t) { if (!allowForbidden && t.IsForbidden(getter)) { return(false); } if (t.def.ingestible.preferability < minPref) { return(false); } if (t.def.ingestible.preferability > 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) || !getter.AnimalAwareOf(t) || !getter.CanReserve(t, 1, -1, null, false)) { return(false); } return(comp.contains(t.def)); }; ThingRequest thingRequest; if ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) != FoodTypeFlags.None && allowPlant) { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSource); } else { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree); } int searchRegionsMax = 100; HashSet <Thing> ___filtered = new HashSet <Thing>(); foreach (Thing thing2 in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true)) { Pawn pawn = thing2 as Pawn; if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing) { ___filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing); } } bool ignoreEntirelyForbiddenRegions = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings != null && getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null; Predicate <Thing> predicate = (Thing t) => foodValidator(t) && !___filtered.Contains(t) && !t.IsNotFresh(); IntVec3 position = getter.Position; Map map = getter.Map; PathEndMode peMode = PathEndMode.ClosestTouch; TraverseParms traverseParams = TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false); Thing bestThing = GenClosest.ClosestThingReachable(position, map, thingRequest, peMode, traverseParams, 9999f, predicate, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); if (bestThing != null) { if (bestThing != null) { foodDef = FoodUtility.GetFinalIngestibleDef(bestThing, false); } __result = bestThing; return(false); } return(true); }
private static FoodCategory DetermineFoodCategory(ThingDef def) { if (def == null) { throw new ArgumentNullException(nameof(def)); } // List all foods with a race as huntable if (def.race != null) { return(FoodCategory.Hunt); } if (def.ingestible != null) { // If food has no nutritional value or is a drug ignore it if (def.ingestible.CachedNutrition <= 0f || def.IsDrug) { return(FoodCategory.Ignore); } FoodPreferability foodPref = def.ingestible.preferability; FoodTypeFlags foodType = def.ingestible.foodType; if (foodPref == FoodPreferability.NeverForNutrition) { return(FoodCategory.Ignore); } if (foodPref == FoodPreferability.MealFine) { return(FoodCategory.MealFine); } if (foodPref == FoodPreferability.MealAwful) { return(FoodCategory.MealAwful); } if (foodPref == FoodPreferability.MealSimple) { return((def == ThingDefOf.MealSurvivalPack || def == ThingDefOf.Pemmican) ? FoodCategory.MealSurvival : FoodCategory.MealSimple); } if (foodPref == FoodPreferability.MealLavish) { return(FoodCategory.MealLavish); } if ((foodType & FoodTypeFlags.Kibble) != 0) { return(FoodCategory.Kibble); } if ((foodType & FoodTypeFlags.AnimalProduct) != 0) { if (def.GetCompProperties <CompProperties_Hatcher>() != null) { return(FoodCategory.FertEggs); } return(FoodCategory.AnimalProduct); } if (def.ingestible.joyKind == JoyKindDefOf.Gluttonous && def.ingestible.joy >= 0.05f) { return(FoodCategory.Luxury); } if ((foodType & FoodTypeFlags.Tree) != 0) { return(FoodCategory.Tree); } if ((foodType & FoodTypeFlags.Plant) != 0) { if (def == ThingDefOf.Hay) { return(FoodCategory.Hay); } if (def.plant != null && !def.plant.sowTags.NullOrEmpty()) { return(FoodCategory.Plant); } if (def.thingCategories?.Contains(ThingCategoryDefOf.PlantMatter) ?? false) { return(FoodCategory.PlantMatter); } if (foodPref == FoodPreferability.DesperateOnly) { return(FoodCategory.Ignore); } return(FoodCategory.Grass); } if (def.IsCorpse) { if (RimWorld.FoodUtility.IsHumanlikeMeat(def)) { return(FoodCategory.HumanlikeCorpse); } if (def.FirstThingCategory == ThingCategoryDefOf.CorpsesInsect) { return(FoodCategory.InsectCorpse); } if (def.ingestible?.sourceDef?.race?.IsMechanoid ?? false) { return(FoodCategory.Ignore); } return(FoodCategory.Corpse); } if (def.ingestible.tasteThought != null && def.ingestible.tasteThought.stages.All((ThoughtStage arg) => arg.baseMoodEffect < 0)) { if (RimWorld.FoodUtility.IsHumanlikeMeat(def)) { return(FoodCategory.RawHuman); } if (def == ThingDef.Named("Meat_Megaspider") || def.ingestible.tasteThought == ThoughtDefOf.AteInsectMeatAsIngredient) { return(FoodCategory.RawInsect); } return(FoodCategory.RawBad); } if ((def.ingestible.tasteThought == null || def.ingestible.tasteThought.stages.All((ThoughtStage arg) => arg.baseMoodEffect >= 0))) { return(FoodCategory.RawTasty); } } // non ingestible corpse ? if (def.IsCorpse) { return(FoodCategory.Ignore); } return(FoodCategory.Null); }
private static FoodCategory _DetermineFoodCategory(ThingDef def) { // List Nutrient Paste Dispenser as an Awful meal source if (def == ThingDefOf.NutrientPasteDispenser) { return(FoodCategory.MealAwful); } // List all foods with a race as huntable if (def.race != null) { return(FoodCategory.Hunt); } if (def.ingestible != null) { //if food has no nutritional value or is a drug ignore it if (def.ingestible.CachedNutrition <= 0f || def.IsDrug) { return(FoodCategory.Ignore); } FoodPreferability foodPref = def.ingestible.preferability; FoodTypeFlags foodType = def.ingestible.foodType; if (foodPref == FoodPreferability.MealFine) { return(FoodCategory.MealFine); } if (foodPref == FoodPreferability.MealAwful) { return(FoodCategory.MealAwful); } //if (foodPref == FoodPreferability.MealSimple) // return FoodCategory.MealSimple; if (foodPref == FoodPreferability.MealSimple) { if (def.defName == "Pemmican" || def.defName == "MealSurvivalPack") { return(FoodCategory.MealSurvival); } return(FoodCategory.MealSimple); } if (foodPref == FoodPreferability.MealLavish) { return(FoodCategory.MealLavish); } if ((foodType & FoodTypeFlags.Kibble) != 0) { return(FoodCategory.Kibble); } if ((foodType & FoodTypeFlags.AnimalProduct) != 0) { if (def.GetCompProperties <CompProperties_Hatcher>() != null) { return(FoodCategory.FertEggs); } //return WMFoodPref.Null; } if (def.ingestible.joyKind == JoyKindDefOf.Gluttonous && def.ingestible.joy >= 0.05f) { return(FoodCategory.Luxury); } if ((foodType & FoodTypeFlags.Tree) != 0) { return(FoodCategory.Tree); } if ((foodType & FoodTypeFlags.Plant) != 0) { if (def == ThingDefOf.Hay) { return(FoodCategory.Hay); } if (def == ThingDef.Named("Plant_TallGrass") || def == ThingDef.Named("Plant_Grass")) { return(FoodCategory.Grass); } return(FoodCategory.Plant); } if (def.IsCorpse) { if (RimWorld.FoodUtility.IsHumanlikeMeat(def)) { return(FoodCategory.HumanlikeCorpse); } //TODO: Make more reliable if (def.ingestible.sourceDef.race.Animal) { if (def.FirstThingCategory == ThingCategoryDefOf.CorpsesInsect) { return(FoodCategory.InsectCorpse); } return(FoodCategory.Corpse); } if (def.ingestible.sourceDef.race.IsMechanoid) { return(FoodCategory.Ignore); } } if (def.ingestible.tasteThought != null && def.ingestible.tasteThought.stages.All((ThoughtStage arg) => arg.baseMoodEffect < 0)) { if (RimWorld.FoodUtility.IsHumanlikeMeat(def)) { return(FoodCategory.RawHuman); } if (def == ThingDef.Named("Meat_Megaspider")) { //if (def.ingestible.tasteThought == ThoughtDefOf.AteInsectMeatAsIngredient) return(FoodCategory.RawInsect); } return(FoodCategory.RawBad); } if ((def.ingestible.tasteThought == null || def.ingestible.tasteThought.stages.All((ThoughtStage arg) => arg.baseMoodEffect >= 0))) { return(FoodCategory.RawTasty); } if ((foodType & FoodTypeFlags.AnimalProduct) != 0) { return(FoodCategory.AnimalProduct); } if (foodPref == FoodPreferability.NeverForNutrition || def.IsDrug) { return(FoodCategory.Ignore); } } // non ingestible corpse ? if (def.IsCorpse) { return(FoodCategory.Ignore); } return(FoodCategory.Null); }