private float FoodFallPerTickAssumingCategory(HungerCategory cat) { float result; switch (cat) { case HungerCategory.Fed: result = 2.66666666E-05f * this.HungerRate; break; case HungerCategory.Hungry: result = 2.66666666E-05f * this.HungerRate * 0.5f; break; case HungerCategory.UrgentlyHungry: result = 2.66666666E-05f * this.HungerRate * 0.25f; break; case HungerCategory.Starving: result = 2.66666666E-05f * this.HungerRate * 0.15f; break; default: result = 999f; break; } return(result); }
public static string GetLabel(this HungerCategory hunger) { string result; switch (hunger) { case HungerCategory.Fed: result = "HungerLevel_Fed".Translate(); break; case HungerCategory.Hungry: result = "HungerLevel_Hungry".Translate(); break; case HungerCategory.UrgentlyHungry: result = "HungerLevel_UrgentlyHungry".Translate(); break; case HungerCategory.Starving: result = "HungerLevel_Starving".Translate(); break; default: throw new InvalidOperationException(); } return(result); }
private float FoodMultiplier(HungerCategory hunger) { float result; switch (hunger) { case HungerCategory.Fed: result = this.factorFed; break; case HungerCategory.Hungry: result = this.factorHungry; break; case HungerCategory.UrgentlyHungry: result = this.factorUrgentlyHungry; break; case HungerCategory.Starving: result = this.factorStarving; break; default: throw new InvalidOperationException(); } return(result); }
public override ThinkNode DeepCopy(bool resolve = true) { var JobGiver_GetFoodSpider = (JobGiver_GetFoodSpider)base.DeepCopy(resolve); JobGiver_GetFoodSpider.minCategory = minCategory; return(JobGiver_GetFoodSpider); }
public static string GetLabel(this HungerCategory hunger) { return(hunger switch { HungerCategory.Starving => "HungerLevel_Starving".Translate(), HungerCategory.UrgentlyHungry => "HungerLevel_UrgentlyHungry".Translate(), HungerCategory.Hungry => "HungerLevel_Hungry".Translate(), HungerCategory.Fed => "HungerLevel_Fed".Translate(), _ => throw new InvalidOperationException(), });
private float FoodMultiplier(HungerCategory hunger) { return(hunger switch { HungerCategory.Starving => factorStarving, HungerCategory.UrgentlyHungry => factorUrgentlyHungry, HungerCategory.Hungry => factorHungry, HungerCategory.Fed => factorFed, _ => throw new InvalidOperationException(), });
public float FoodFallPerTickAssumingCategory(HungerCategory cat, bool ignoreMalnutrition = false) { float num = (ignoreMalnutrition ? HungerRateIgnoringMalnutrition : HungerRate); return(cat switch { HungerCategory.Fed => 2.66666666E-05f * num, HungerCategory.Hungry => 2.66666666E-05f * num * 0.5f, HungerCategory.UrgentlyHungry => 2.66666666E-05f * num * 0.25f, HungerCategory.Starving => 2.66666666E-05f * num * 0.15f, _ => 999f, });
private float FoodMultiplier(HungerCategory hunger) { switch (hunger) { case HungerCategory.Starving: return(factorStarving); case HungerCategory.UrgentlyHungry: return(factorUrgentlyHungry); case HungerCategory.Hungry: return(factorHungry); case HungerCategory.Fed: return(factorFed); default: throw new InvalidOperationException(); } }
private float FoodFallPerTickAssumingCategory(HungerCategory cat) { switch (cat) { case HungerCategory.Fed: return(2.66666666E-05f * HungerRate); case HungerCategory.Hungry: return(2.66666666E-05f * HungerRate * 0.5f); case HungerCategory.UrgentlyHungry: return(2.66666666E-05f * HungerRate * 0.25f); case HungerCategory.Starving: return(2.66666666E-05f * HungerRate * 0.15f); default: return(999f); } }
private float FoodFallPerTickAssumingCategory(HungerCategory cat) { switch (cat) { case HungerCategory.Fed: return((float)(2.6666666599339806E-05 * this.HungerRate)); case HungerCategory.Hungry: return((float)(2.6666666599339806E-05 * this.HungerRate * 0.5)); case HungerCategory.UrgentlyHungry: return((float)(2.6666666599339806E-05 * this.HungerRate * 0.25)); case HungerCategory.Starving: return((float)(2.6666666599339806E-05 * this.HungerRate * 0.15000000596046448)); default: return(999f); } }
public float FoodFallPerTickAssumingCategory(HungerCategory cat, bool ignoreMalnutrition = false) { float num = ignoreMalnutrition ? HungerRateIgnoringMalnutrition : HungerRate; switch (cat) { case HungerCategory.Fed: return(2.66666666E-05f * num); case HungerCategory.Hungry: return(2.66666666E-05f * num * 0.5f); case HungerCategory.UrgentlyHungry: return(2.66666666E-05f * num * 0.25f); case HungerCategory.Starving: return(2.66666666E-05f * num * 0.15f); default: return(999f); } }
static bool Prefix(HungerCategory ___minCategory, float ___maxLevelPercentage, ref float __result, Pawn pawn) { //Log.Message("1"); Need_Food food = pawn.needs.food; if (food == null) { __result = 0f; return(false); } //Log.Message("2"); if (pawn.needs.food.CurCategory < HungerCategory.Starving && FoodUtility.ShouldBeFedBySomeone(pawn)) { __result = 0f; return(false); } //Log.Message("3"); if (food.CurCategory < ___minCategory) { __result = 0f; return(false); } //Log.Message("4"); if (food.CurLevelPercentage > ___maxLevelPercentage) { __result = 0f; return(false); } //Log.Message("5"); if (pawn.RaceProps.Humanlike) { if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat + ModSetting.eatThreshold) { if (pawn.timetable == null) { if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat) { __result = 9.5f; } else { __result = 0f; } return(false); } //Log.Message("6"); TimeAssignmentDef timeAssignmentDef = (pawn.timetable == null) ? TimeAssignmentDefOf.Anything : pawn.timetable.CurrentAssignment; if (timeAssignmentDef != TimeAssignmentDefDinner.DinnerDef) { //Log.Message("7"); if (pawn.timetable.GetAssignment((GenLocalDate.HourOfDay(pawn) + 1) % 24) == TimeAssignmentDefDinner.DinnerDef && food.CurLevelPercentage > pawn.RaceProps.FoodLevelPercentageWantEat * 0.48f) {//下一小时是dinner时间并且饥饿度百分比>0.45就不吃饭 __result = 0f; return(false); } if (pawn.timetable.GetAssignment((GenLocalDate.HourOfDay(pawn) + 2) % 24) == TimeAssignmentDefDinner.DinnerDef && food.CurLevelPercentage > pawn.RaceProps.FoodLevelPercentageWantEat * 0.8f) {//下2小时是dinner时间并且饥饿度百分比>0.8就不吃饭 __result = 0f; return(false); } //Log.Message("8"); if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat) { __result = 9.5f; } else { __result = 0f; } return(false); } if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat) { __result = 9.5f; } else { __result = 7.25f; } return(false); } else { __result = 0; } //Log.Message("{0} food priority = {1}".Translate(pawn.Label, __result)); } else if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat) { __result = 9.5f; } else { __result = 0f; } 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); }
private static bool Prefix(HungerCategory ___minCategory, float ___maxLevelPercentage, ref float __result, Pawn pawn) { var food = pawn.needs.food; if (food == null) { __result = 0f; return(false); } if (pawn.needs.food.CurCategory < HungerCategory.Starving && FoodUtility.ShouldBeFedBySomeone(pawn)) { __result = 0f; return(false); } if (food.CurCategory < ___minCategory) { __result = 0f; return(false); } if (food.CurLevelPercentage > ___maxLevelPercentage) { __result = 0f; return(false); } if (pawn.RaceProps.Humanlike) { if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat + ModSetting.eatThreshold) { if (pawn.timetable == null) { __result = food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat ? 9.5f : 0f; return(false); } var timeAssignmentDef = pawn.timetable == null ? TimeAssignmentDefOf.Anything : pawn.timetable.CurrentAssignment; if (timeAssignmentDef == TimeAssignmentDefDinner.DinnerDef) { __result = food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat ? 9.5f : 7.25f; return(false); } if (pawn.timetable.GetAssignment((GenLocalDate.HourOfDay(pawn) + 1) % 24) == TimeAssignmentDefDinner.DinnerDef && food.CurLevelPercentage > pawn.RaceProps.FoodLevelPercentageWantEat * 0.48f) { __result = 0f; return(false); } if (pawn.timetable.GetAssignment((GenLocalDate.HourOfDay(pawn) + 2) % 24) == TimeAssignmentDefDinner.DinnerDef && food.CurLevelPercentage > pawn.RaceProps.FoodLevelPercentageWantEat * 0.8f) { __result = 0f; return(false); } __result = food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat ? 9.5f : 0f; return(false); } __result = 0f; } else { __result = food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat ? 9.5f : 0f; } return(false); }