Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #4
0
    public override ThinkNode DeepCopy(bool resolve = true)
    {
        var JobGiver_GetFoodSpider = (JobGiver_GetFoodSpider)base.DeepCopy(resolve);

        JobGiver_GetFoodSpider.minCategory = minCategory;
        return(JobGiver_GetFoodSpider);
    }
Example #5
0
 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(),
     });
Example #7
0
        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,
            });
Example #8
0
        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();
            }
        }
Example #9
0
        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);
            }
        }
Example #11
0
        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);
        }
Example #13
0
        /// <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);
        }
Example #14
0
        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);
        }