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); }
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); }
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); }
//[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); }
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); }
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); }
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); }
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); }
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); }
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); }
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)); }
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); }
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)); }
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); }
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); }