예제 #1
0
        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;
 }
예제 #6
0
        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);
        }
예제 #7
0
 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();
     }
 }
예제 #8
0
        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);
            }
예제 #10
0
        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;
     }
 }
예제 #12
0
        /// <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;
예제 #13
0
        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);
        }
예제 #14
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
0
        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);
        }
예제 #18
0
        public static Thing BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate, out ThingDef foodDef, FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowDrug = true, bool allowCorpse = true, bool allowDispenserFull = true, bool allowDispenserEmpty = true, bool allowForbidden = false, bool allowSociallyImproper = false, bool allowHarvest = false)
        {
            foodDef = null;
            bool getterCanManipulate = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);

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

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

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

            if (getter.RaceProps.Humanlike)
            {
                Pawn              eater2         = eater;
                IntVec3           position       = getter.Position;
                List <Thing>      searchSet      = getter.Map.listerThings.ThingsMatching(thingRequest);
                PathEndMode       peMode         = PathEndMode.ClosestTouch;
                TraverseParms     traverseParams = TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false);
                Predicate <Thing> validator      = foodValidator;
                bestThing = FoodUtility.SpawnedFoodSearchInnerScan(eater2, position, searchSet, peMode, traverseParams, 9999f, validator);
                if (allowHarvest && getterCanManipulate)
                {
                    Thing thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.HarvestablePlant), PathEndMode.Touch, TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing x)
                    {
                        Plant plant = (Plant)x;
                        if (!plant.HarvestableNow)
                        {
                            return(false);
                        }
                        ThingDef harvestedThingDef = plant.def.plant.harvestedThingDef;
                        if (!harvestedThingDef.IsNutritionGivingIngestible)
                        {
                            return(false);
                        }
                        if (!getter.CanReserve(plant, 1, -1, null, false))
                        {
                            return(false);
                        }
                        if (!allowForbidden && plant.IsForbidden(getter))
                        {
                            return(false);
                        }
                        if (bestThing != null && (int)FoodUtility.GetFinalIngestibleDef(bestThing, false).ingestible.preferability >= (int)harvestedThingDef.ingestible.preferability)
                        {
                            return(false);
                        }
                        return(true);
                    }, null, 0, 30, false, RegionType.Set_Passable, false);
                    if (thing != null)
                    {
                        bestThing = thing;
                        foodDef   = FoodUtility.GetFinalIngestibleDef(thing, true);
                    }
                }
                if (foodDef == null && bestThing != null)
                {
                    foodDef = FoodUtility.GetFinalIngestibleDef(bestThing, false);
                }
            }
            else
            {
                int searchRegionsMax = 30;
                if (getter.Faction == Faction.OfPlayer)
                {
                    searchRegionsMax = 100;
                }
                FoodUtility.filtered.Clear();
                foreach (Thing item in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true))
                {
                    Pawn pawn = item as Pawn;
                    if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing)
                    {
                        FoodUtility.filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing);
                    }
                }
                bool flag = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings != null && getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null;
                Predicate <Thing> predicate = delegate(Thing t)
                {
                    if (!foodValidator(t))
                    {
                        return(false);
                    }
                    if (FoodUtility.filtered.Contains(t))
                    {
                        return(false);
                    }
                    if (!(t is Building_NutrientPasteDispenser) && (int)t.def.ingestible.preferability <= 2)
                    {
                        return(false);
                    }
                    if (t.IsNotFresh())
                    {
                        return(false);
                    }
                    return(true);
                };
                IntVec3           position       = getter.Position;
                Map               map            = getter.Map;
                ThingRequest      thingReq       = thingRequest;
                PathEndMode       peMode         = PathEndMode.ClosestTouch;
                TraverseParms     traverseParams = TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false);
                Predicate <Thing> validator      = predicate;
                bool              ignoreEntirelyForbiddenRegions = flag;
                bestThing = GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, 9999f, validator, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);
                FoodUtility.filtered.Clear();
                if (bestThing == null)
                {
                    desperate      = true;
                    position       = getter.Position;
                    map            = getter.Map;
                    thingReq       = thingRequest;
                    peMode         = PathEndMode.ClosestTouch;
                    traverseParams = TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false);
                    validator      = foodValidator;
                    ignoreEntirelyForbiddenRegions = flag;
                    bestThing = GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, 9999f, validator, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);
                }
                if (bestThing != null)
                {
                    foodDef = FoodUtility.GetFinalIngestibleDef(bestThing, false);
                }
            }
            return(bestThing);
        }
예제 #19
0
        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);
        }
예제 #20
0
        // 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);
        }
예제 #21
0
        // 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);
        }
예제 #22
0
        public static Thing BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate, out ThingDef foodDef, FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowDrug = true, bool allowCorpse = true, bool allowDispenserFull = true, bool allowDispenserEmpty = true, bool allowForbidden = false, bool allowSociallyImproper = false, bool allowHarvest = false, 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);
        }
예제 #23
0
        public static bool TryFindBestFoodSourceFor(Pawn getter, Pawn eater, bool desperate, out Thing foodSource, out ThingDef foodDef, bool canRefillDispenser = true, bool canUseInventory = true, bool allowForbidden = false, bool allowCorpse = true, bool allowSociallyImproper = false, bool allowHarvest = false, bool forceScanWholeMap = false, bool 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);
        }
예제 #24
0
        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);
        }
예제 #25
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);
        }
예제 #26
0
        // 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;
        }
예제 #27
0
 public static Thing BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate, out ThingDef foodDef, FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowDrug = true, bool allowCorpse = true, bool allowDispenserFull = true, bool allowDispenserEmpty = true, bool allowForbidden = false, bool allowSociallyImproper = false, bool allowHarvest = false)
 {
     FoodUtility.< BestFoodSourceOnMap > c__AnonStorey0 <BestFoodSourceOnMap> c__AnonStorey = new FoodUtility.< BestFoodSourceOnMap > c__AnonStorey0();
예제 #28
0
        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);
        }