public virtual bool HasEnoughFeedstockInHoppers()
        {
            float num = 0f;

            for (int i = 0; i < this.AdjCellsCardinalInBounds.Count; i++)
            {
                IntVec3      c         = this.AdjCellsCardinalInBounds[i];
                Thing        thing     = null;
                Thing        thing2    = null;
                List <Thing> thingList = c.GetThingList(base.Map);
                for (int j = 0; j < thingList.Count; j++)
                {
                    Thing thing3 = thingList[j];
                    if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(thing3.def))
                    {
                        thing = thing3;
                    }
                    if (thing3.def == ThingDefOf.Hopper)
                    {
                        thing2 = thing3;
                    }
                }
                if (thing != null && thing2 != null)
                {
                    num += (float)thing.stackCount * thing.def.ingestible.nutrition;
                }
                if (num >= base.def.building.nutritionCostPerDispense)
                {
                    return(true);
                }
            }
            return(false);
        }
Пример #2
0
        public static Toil TakeMealFromDispenser(TargetIndex ind, Pawn eater)
        {
            Toil toil = new Toil();

            toil.initAction = delegate()
            {
                Pawn actor  = toil.actor;
                Job  curJob = actor.jobs.curJob;
                Building_NutrientPasteDispenser building_NutrientPasteDispenser = (Building_NutrientPasteDispenser)curJob.GetTarget(ind).Thing;
                Thing thing = building_NutrientPasteDispenser.TryDispenseFood();
                if (thing == null)
                {
                    actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                }
                else
                {
                    actor.carryTracker.TryStartCarry(thing);
                    actor.CurJob.SetTarget(ind, actor.carryTracker.CarriedThing);
                }
            };
            toil.FailOnCannotTouch(ind, PathEndMode.Touch);
            toil.defaultCompleteMode = ToilCompleteMode.Delay;
            toil.defaultDuration     = Building_NutrientPasteDispenser.CollectDuration;
            return(toil);
        }
Пример #3
0
        public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false)
        {
            ISlotGroupParent slotGroupParent = thing as ISlotGroupParent;

            if (slotGroupParent == null)
            {
                return(null);
            }
            if (!pawn.CanReserve(thing.Position))
            {
                return(null);
            }
            int          num  = 0;
            List <Thing> list = pawn.Map.thingGrid.ThingsListAt(thing.Position);

            for (int i = 0; i < list.Count; i++)
            {
                Thing thing2 = list[i];
                if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(thing2.def))
                {
                    num += thing2.stackCount;
                }
            }
            if (num > 25)
            {
                JobFailReason.Is("AlreadyFilledLower".Translate());
                return(null);
            }
            return(HopperFillFoodJob(pawn, slotGroupParent));
        }
 public virtual Thing FindFeedInAnyHopper()
 {
     for (int i = 0; i < this.AdjCellsCardinalInBounds.Count; i++)
     {
         Thing        thing     = null;
         Thing        thing2    = null;
         List <Thing> thingList = this.AdjCellsCardinalInBounds[i].GetThingList(base.Map);
         for (int j = 0; j < thingList.Count; j++)
         {
             Thing thing3 = thingList[j];
             if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(thing3.def))
             {
                 thing = thing3;
             }
             if (thing3.def == ThingDefOf.Hopper)
             {
                 thing2 = thing3;
             }
         }
         if (thing != null && thing2 != null)
         {
             return(thing);
         }
     }
     return(null);
 }
Пример #5
0
        //[DetourMethod(typeof(RimWorld.Building_NutrientPasteDispenser),"TryDispenseFood")]
        // RimWorld.Building_NutrientPasteDispenser
        public static Thing TryDispenseFood(this RimWorld.Building_NutrientPasteDispenser self, DispenseMode mode = DispenseMode.Standard, bool silent = false)
        {
            if (!self.CanDispenseNow)
            {
                return(null);
            }

            // ----- begin mod code ------

            List <Thing> ingredients;

            ingredients = IngredientsFor(self, mode);

            if (ingredients.Sum((arg) => arg.stackCount) < NutritionCostPerDispense)
            {
                if (!silent)
                {
                    Log.Error("Did not find enough food in hoppers while trying to dispense. (" + ingredients.Count + "/" + NutritionCostPerDispense + ")");
                }
                return(null);
            }
#if DEBUG
            //foreach (var e in query)
            //{
            //	Log.Message("dispenser has " + e.def + " rank: #" + rankForPawn(eater, e.def) + " total count: " + e.stackCount);
            //}
            //Log.Message("dispense");
#endif

            self.def.building.soundDispense.PlayOneShot(new TargetInfo(self.Position, self.Map, false));

            Thing           thing2          = ThingMaker.MakeThing(ThingDefOf.MealNutrientPaste, null);
            CompIngredients compIngredients = thing2.TryGetComp <CompIngredients>();

            float num = 0;

            for (int i = 0; num < NutritionCostPerDispense; i++)
            {
                var nutrition = ingredients[i].def.ingestible.nutrition;

                float num2 = Mathf.Min(ingredients[i].stackCount * nutrition, NutritionCostPerDispense);
                num += num2;
                ingredients[i].SplitOff(Convert.ToInt32(num2 / nutrition));
                compIngredients.RegisterIngredient(ingredients[i].def);
            }

            if (Config.SeparatedNutrientPaste && compIngredients.ingredients.Any((arg) => arg.DetermineFoodCategory() == FoodCategory.RawHuman))
            {
                thing2.def = ThingDef.Named("MealNutrientPasteCannibal");
            }

            // ----- end mod code ------

            return(thing2);
        }
        public static float GetAvailableNutrition(this RimWorld.Building_NutrientPasteDispenser self)
        {
            if (!self.CanDispenseNow)
            {
                return(0f);
            }

            var list = GetAllHoppersThings(self);

            return(Mathf.Floor(list.Sum((arg) => arg.stackCount) / NutritionCostPerDispense) * ThingDefOf.MealNutrientPaste.ingestible.CachedNutrition);
        }
Пример #7
0
        public static Job HopperFillFoodJob(Pawn pawn, ISlotGroupParent hopperSgp)
        {
            Building building = (Building)hopperSgp;

            if (!pawn.CanReserveAndReach(building.Position, PathEndMode.Touch, pawn.NormalMaxDanger()))
            {
                return(null);
            }
            ThingDef thingDef  = null;
            Thing    firstItem = building.Position.GetFirstItem(building.Map);

            if (firstItem != null)
            {
                if (!Building_NutrientPasteDispenser.IsAcceptableFeedstock(firstItem.def))
                {
                    if (firstItem.IsForbidden(pawn))
                    {
                        return(null);
                    }
                    return(HaulAIUtility.HaulAsideJobFor(pawn, firstItem));
                }
                thingDef = firstItem.def;
            }
            List <Thing> list = (thingDef != null) ? pawn.Map.listerThings.ThingsOfDef(thingDef) : pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree);
            bool         flag = false;

            for (int i = 0; i < list.Count; i++)
            {
                Thing thing = list[i];
                if (thing.def.IsNutritionGivingIngestible && (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty) && HaulAIUtility.PawnCanAutomaticallyHaul(pawn, thing, forced: false) && pawn.Map.haulDestinationManager.SlotGroupAt(building.Position).Settings.AllowedToAccept(thing))
                {
                    StoragePriority storagePriority = StoreUtility.CurrentStoragePriorityOf(thing);
                    if ((int)storagePriority >= (int)hopperSgp.GetSlotGroup().Settings.Priority)
                    {
                        flag = true;
                        JobFailReason.Is(TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans);
                    }
                    else
                    {
                        Job job = HaulAIUtility.HaulToCellStorageJob(pawn, thing, building.Position, fitInStoreCell: true);
                        if (job != null)
                        {
                            return(job);
                        }
                    }
                }
            }
            if (!flag)
            {
                JobFailReason.Is(NoFoodToFillHopperTrans);
            }
            return(null);
        }
            internal void <> m__0()
            {
                Pawn actor  = this.toil.actor;
                Job  curJob = actor.jobs.curJob;
                Building_NutrientPasteDispenser building_NutrientPasteDispenser = (Building_NutrientPasteDispenser)curJob.GetTarget(this.ind).Thing;
                Thing thing = building_NutrientPasteDispenser.TryDispenseFood();

                if (thing == null)
                {
                    actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                    return;
                }
                actor.carryTracker.TryStartCarry(thing);
                actor.CurJob.SetTarget(this.ind, actor.carryTracker.CarriedThing);
            }
Пример #9
0
 private static float NutritionAvailableForFrom(Pawn p, Thing foodSource)
 {
     if (foodSource.def.IsNutritionGivingIngestible && p.RaceProps.WillAutomaticallyEat(foodSource))
     {
         return(foodSource.def.ingestible.nutrition * (float)foodSource.stackCount);
     }
     if (p.RaceProps.ToolUser && p.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
     {
         Building_NutrientPasteDispenser building_NutrientPasteDispenser = foodSource as Building_NutrientPasteDispenser;
         if (building_NutrientPasteDispenser != null && building_NutrientPasteDispenser.CanDispenseNow)
         {
             return(99999f);
         }
     }
     return(0f);
 }
Пример #10
0
 private static float NutritionAvailableForFrom(Pawn p, Thing foodSource)
 {
     if (foodSource.def.IsNutritionGivingIngestible && p.WillEat(foodSource))
     {
         return(foodSource.GetStatValue(StatDefOf.Nutrition) * (float)foodSource.stackCount);
     }
     if (p.RaceProps.ToolUser && p.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
     {
         Building_NutrientPasteDispenser building_NutrientPasteDispenser = foodSource as Building_NutrientPasteDispenser;
         if (building_NutrientPasteDispenser != null && building_NutrientPasteDispenser.CanDispenseNow && p.CanReach(building_NutrientPasteDispenser.InteractionCell, PathEndMode.OnCell, Danger.Some))
         {
             return(99999f);
         }
     }
     return(0f);
 }
Пример #11
0
        public static List <ThoughtDef> ThoughtsFromIngesting(Pawn ingester, Thing foodSource, ThingDef foodDef)
        {
            ingestThoughts.Clear();
            if (ingester.needs == null || ingester.needs.mood == null)
            {
                return(ingestThoughts);
            }
            if (!ingester.story.traits.HasTrait(TraitDefOf.Ascetic) && foodDef.ingestible.tasteThought != null)
            {
                ingestThoughts.Add(foodDef.ingestible.tasteThought);
            }
            CompIngredients compIngredients = foodSource.TryGetComp <CompIngredients>();
            Building_NutrientPasteDispenser building_NutrientPasteDispenser = foodSource as Building_NutrientPasteDispenser;

            if (IsHumanlikeMeat(foodDef) && ingester.RaceProps.Humanlike)
            {
                ingestThoughts.Add(ingester.story.traits.HasTrait(TraitDefOf.Cannibal) ? ThoughtDefOf.AteHumanlikeMeatDirectCannibal : ThoughtDefOf.AteHumanlikeMeatDirect);
            }
            else if (compIngredients != null)
            {
                for (int i = 0; i < compIngredients.ingredients.Count; i++)
                {
                    AddIngestThoughtsFromIngredient(compIngredients.ingredients[i], ingester, ingestThoughts);
                }
            }
            else if (building_NutrientPasteDispenser != null)
            {
                Thing thing = building_NutrientPasteDispenser.FindFeedInAnyHopper();
                if (thing != null)
                {
                    AddIngestThoughtsFromIngredient(thing.def, ingester, ingestThoughts);
                }
            }
            if (foodDef.ingestible.specialThoughtDirect != null)
            {
                ingestThoughts.Add(foodDef.ingestible.specialThoughtDirect);
            }
            if (foodSource.IsNotFresh())
            {
                ingestThoughts.Add(ThoughtDefOf.AteRottenFood);
            }
            if (ModsConfig.RoyaltyActive && InappropriateForTitle(foodDef, ingester, allowIfStarving: false))
            {
                ingestThoughts.Add(ThoughtDefOf.AteFoodInappropriateForTitle);
            }
            return(ingestThoughts);
        }
Пример #12
0
 public static List <ThoughtDef> ThoughtsFromIngesting(Pawn ingester, Thing foodSource, ThingDef foodDef)
 {
     FoodUtility.ingestThoughts.Clear();
     if (ingester.needs != null && ingester.needs.mood != null)
     {
         if (!ingester.story.traits.HasTrait(TraitDefOf.Ascetic) && foodDef.ingestible.tasteThought != null)
         {
             FoodUtility.ingestThoughts.Add(foodDef.ingestible.tasteThought);
         }
         CompIngredients compIngredients = foodSource.TryGetComp <CompIngredients>();
         Building_NutrientPasteDispenser building_NutrientPasteDispenser = foodSource as Building_NutrientPasteDispenser;
         if (FoodUtility.IsHumanlikeMeat(foodDef) && ingester.RaceProps.Humanlike)
         {
             FoodUtility.ingestThoughts.Add((!ingester.story.traits.HasTrait(TraitDefOf.Cannibal)) ? ThoughtDefOf.AteHumanlikeMeatDirect : ThoughtDefOf.AteHumanlikeMeatDirectCannibal);
         }
         else if (compIngredients != null)
         {
             for (int i = 0; i < compIngredients.ingredients.Count; i++)
             {
                 FoodUtility.AddIngestThoughtsFromIngredient(compIngredients.ingredients[i], ingester, FoodUtility.ingestThoughts);
             }
         }
         else if (building_NutrientPasteDispenser != null)
         {
             Thing thing = building_NutrientPasteDispenser.FindFeedInAnyHopper();
             if (thing != null)
             {
                 FoodUtility.AddIngestThoughtsFromIngredient(thing.def, ingester, FoodUtility.ingestThoughts);
             }
         }
         if (foodDef.ingestible.specialThoughtDirect != null)
         {
             FoodUtility.ingestThoughts.Add(foodDef.ingestible.specialThoughtDirect);
         }
         if (foodSource.IsNotFresh())
         {
             FoodUtility.ingestThoughts.Add(ThoughtDefOf.AteRottenFood);
         }
         return(FoodUtility.ingestThoughts);
     }
     return(FoodUtility.ingestThoughts);
 }
        static List <Thing> GetAllHoppersThings(this RimWorld.Building_NutrientPasteDispenser self)
        {
            var list = new List <Thing>();

            for (int i = 0; i < self.AdjCellsCardinalInBounds().Count; i++)
            {
                IntVec3  c       = self.AdjCellsCardinalInBounds()[i];
                Building edifice = c.GetEdifice(self.Map);
                if (edifice != null && edifice.def == ThingDefOf.Hopper
                    // && eater.CanReach(edifice, PathEndMode.Touch, Danger.Deadly, false, TraverseMode.ByPawn)
                    )
                {
                    List <Thing> thingList = self.AdjCellsCardinalInBounds()[i].GetThingList(self.Map).ToList();

                    list.AddRange(thingList.Where((Thing arg) => Building_NutrientPasteDispenser.IsAcceptableFeedstock(arg.def)));
                }
            }

            return(list);
        }
        private static float NutritionAvailableForFrom(Pawn p, Thing foodSource)
        {
            float result;

            if (foodSource.def.IsNutritionGivingIngestible && p.RaceProps.WillAutomaticallyEat(foodSource))
            {
                result = foodSource.GetStatValue(StatDefOf.Nutrition, true) * (float)foodSource.stackCount;
            }
            else
            {
                if (p.RaceProps.ToolUser && p.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
                {
                    Building_NutrientPasteDispenser building_NutrientPasteDispenser = foodSource as Building_NutrientPasteDispenser;
                    if (building_NutrientPasteDispenser != null && building_NutrientPasteDispenser.CanDispenseNow)
                    {
                        return(99999f);
                    }
                }
                result = 0f;
            }
            return(result);
        }
Пример #15
0
        public static ThingDef GetFinalIngestibleDef(Thing foodSource, bool harvest = false)
        {
            Building_NutrientPasteDispenser building_NutrientPasteDispenser = foodSource as Building_NutrientPasteDispenser;

            if (building_NutrientPasteDispenser != null)
            {
                return(building_NutrientPasteDispenser.DispensableDef);
            }
            Pawn pawn = foodSource as Pawn;

            if (pawn != null)
            {
                return(pawn.RaceProps.corpseDef);
            }
            if (harvest)
            {
                Plant plant = foodSource as Plant;
                if (plant != null && plant.HarvestableNow && plant.def.plant.harvestedThingDef.IsIngestible)
                {
                    return(plant.def.plant.harvestedThingDef);
                }
            }
            return(foodSource.def);
        }
Пример #16
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);
        }
 static Thing FindFeedInAnyHopper(RimWorld.Building_NutrientPasteDispenser self)
 {
     return((Thing)typeof(RimWorld.Building_NutrientPasteDispenser).GetMethod("FindFeedInAnyHopper", Helpers.AllBindingFlags).Invoke(self, null));
 }
Пример #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
        protected override Job TryGiveJob(Pawn pawn)
        {
            Need_Food food = pawn.needs.food;

            if (food == null || food.CurCategory < this.minCategory)
            {
                return(null);
            }
            bool flag;

            if (pawn.AnimalOrWildMan())
            {
                flag = true;
            }
            else
            {
                Hediff firstHediffOfDef = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Malnutrition, false);
                flag = (firstHediffOfDef != null && firstHediffOfDef.Severity > 0.4f);
            }
            bool     flag2              = pawn.needs.food.CurCategory == HungerCategory.Starving;
            bool     desperate          = flag2;
            bool     canRefillDispenser = true;
            bool     canUseInventory    = true;
            bool     allowCorpse        = flag;
            bool     flag3              = this.forceScanWholeMap;
            Thing    thing;
            ThingDef thingDef;

            if (!FoodUtility.TryFindBestFoodSourceFor(pawn, pawn, desperate, out thing, out thingDef, canRefillDispenser, canUseInventory, false, allowCorpse, false, pawn.IsWildMan(), flag3))
            {
                return(null);
            }
            Pawn pawn2 = thing as Pawn;

            if (pawn2 != null)
            {
                return(new Job(JobDefOf.PredatorHunt, pawn2)
                {
                    killIncappedTarget = true
                });
            }
            if (thing is Plant && thing.def.plant.harvestedThingDef == thingDef)
            {
                return(new Job(JobDefOf.Harvest, thing));
            }
            Building_NutrientPasteDispenser building_NutrientPasteDispenser = thing as Building_NutrientPasteDispenser;

            if (building_NutrientPasteDispenser != null && !building_NutrientPasteDispenser.HasEnoughFeedstockInHoppers())
            {
                Building building = building_NutrientPasteDispenser.AdjacentReachableHopper(pawn);
                if (building != null)
                {
                    ISlotGroupParent hopperSgp = building as ISlotGroupParent;
                    Job job = WorkGiver_CookFillHopper.HopperFillFoodJob(pawn, hopperSgp);
                    if (job != null)
                    {
                        return(job);
                    }
                }
                thing = FoodUtility.BestFoodSourceOnMap(pawn, pawn, flag2, out thingDef, FoodPreferability.MealLavish, false, !pawn.IsTeetotaler(), false, false, false, false, false, false, this.forceScanWholeMap);
                if (thing == null)
                {
                    return(null);
                }
            }
            float nutrition = FoodUtility.GetNutrition(thing, thingDef);

            return(new Job(JobDefOf.Ingest, thing)
            {
                count = FoodUtility.WillIngestStackCountOf(pawn, thingDef, nutrition)
            });
        }
 static Thing FindFeedInAnyHopper(RimWorld.Building_NutrientPasteDispenser self)
 {
     return((Thing)typeof(RimWorld.Building_NutrientPasteDispenser).GetMethod("FindFeedInAnyHopper", AccessTools.all).Invoke(self, null));
 }
Пример #21
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            Need_Food food = pawn.needs.food;

            if (food == null || (int)food.CurCategory < (int)minCategory)
            {
                return(null);
            }
            bool flag;

            if (pawn.AnimalOrWildMan())
            {
                flag = true;
            }
            else
            {
                Hediff firstHediffOfDef = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Malnutrition);
                flag = (firstHediffOfDef != null && firstHediffOfDef.Severity > 0.4f);
            }
            bool     flag2              = pawn.needs.food.CurCategory == HungerCategory.Starving;
            bool     desperate          = flag2;
            bool     canRefillDispenser = true;
            bool     canUseInventory    = true;
            bool     allowCorpse        = flag;
            bool     flag3              = forceScanWholeMap;
            Thing    foodSource         = default(Thing);
            ThingDef foodDef            = default(ThingDef);

            if (!FoodUtility.TryFindBestFoodSourceFor(pawn, pawn, desperate, out foodSource, out foodDef, canRefillDispenser, canUseInventory, allowForbidden: false, allowCorpse, allowSociallyImproper: false, pawn.IsWildMan(), flag3))
            {
                return(null);
            }
            Pawn pawn2 = foodSource as Pawn;

            if (pawn2 != null)
            {
                Job job = new Job(JobDefOf.PredatorHunt, pawn2);
                job.killIncappedTarget = true;
                return(job);
            }
            if (foodSource is Plant && foodSource.def.plant.harvestedThingDef == foodDef)
            {
                return(new Job(JobDefOf.Harvest, foodSource));
            }
            Building_NutrientPasteDispenser building_NutrientPasteDispenser = foodSource as Building_NutrientPasteDispenser;

            if (building_NutrientPasteDispenser != null && !building_NutrientPasteDispenser.HasEnoughFeedstockInHoppers())
            {
                Building building = building_NutrientPasteDispenser.AdjacentReachableHopper(pawn);
                if (building != null)
                {
                    ISlotGroupParent hopperSgp = building as ISlotGroupParent;
                    Job job2 = WorkGiver_CookFillHopper.HopperFillFoodJob(pawn, hopperSgp);
                    if (job2 != null)
                    {
                        return(job2);
                    }
                }
                foodSource = FoodUtility.BestFoodSourceOnMap(pawn, pawn, flag2, out foodDef, FoodPreferability.MealLavish, allowPlant: false, !pawn.IsTeetotaler(), allowCorpse: false, allowDispenserFull: false, allowDispenserEmpty: false, allowForbidden: false, allowSociallyImproper: false, allowHarvest: false, forceScanWholeMap);
                if (foodSource == null)
                {
                    return(null);
                }
            }
            float nutrition = FoodUtility.GetNutrition(foodSource, foodDef);
            Job   job3      = new Job(JobDefOf.Ingest, foodSource);

            job3.count = FoodUtility.WillIngestStackCountOf(pawn, foodDef, nutrition);
            return(job3);
        }
Пример #22
0
        public static Job HopperFillFoodJob(Pawn pawn, ISlotGroupParent hopperSgp)
        {
            Building building = hopperSgp as Building;

            if (!pawn.CanReserveAndReach(building.Position, PathEndMode.Touch, pawn.NormalMaxDanger(), 1, -1, null, false))
            {
                return(null);
            }
            ThingDef thingDef  = null;
            Thing    firstItem = building.Position.GetFirstItem(building.Map);

            if (firstItem != null)
            {
                if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(firstItem.def))
                {
                    thingDef = firstItem.def;
                }
                else
                {
                    if (firstItem.IsForbidden(pawn))
                    {
                        return(null);
                    }
                    return(HaulAIUtility.HaulAsideJobFor(pawn, firstItem));
                }
            }
            List <Thing> list;

            if (thingDef == null)
            {
                list = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree);
            }
            else
            {
                list = pawn.Map.listerThings.ThingsOfDef(thingDef);
            }
            bool flag = false;

            for (int i = 0; i < list.Count; i++)
            {
                Thing thing = list[i];
                if (thing.def.IsNutritionGivingIngestible)
                {
                    if (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty)
                    {
                        if (HaulAIUtility.PawnCanAutomaticallyHaul(pawn, thing, false))
                        {
                            if (pawn.Map.slotGroupManager.SlotGroupAt(building.Position).Settings.AllowedToAccept(thing))
                            {
                                StoragePriority storagePriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                                if (storagePriority >= hopperSgp.GetSlotGroup().Settings.Priority)
                                {
                                    flag = true;
                                    JobFailReason.Is(WorkGiver_CookFillHopper.TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans);
                                }
                                else
                                {
                                    Job job = HaulAIUtility.HaulMaxNumToCellJob(pawn, thing, building.Position, true);
                                    if (job != null)
                                    {
                                        return(job);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (!flag)
            {
                JobFailReason.Is(WorkGiver_CookFillHopper.NoFoodToFillHopperTrans);
            }
            return(null);
        }