protected override Thing FindFeedInAnyHopper() { // Check for generic hoppers if (compHopperUser != null) { var hoppers = compHopperUser.FindHoppers(); if (!hoppers.NullOrEmpty()) { foreach (var hopper in hoppers) { var resources = hopper.GetAllResources(compHopperUser.Resources); if (!resources.NullOrEmpty()) { foreach (var resource in resources) { // This check shouldn't be needed, but we'll do it as a fail-safe if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(resource.def)) { return(resource); } } } } } } // Check for vanilla hoppers return(base.FindFeedInAnyHopper()); }
public static bool Prefix(ref Job __result, Pawn pawn, Thing thing) { __result = null; if (!(thing is ISlotGroupParent hopperSgp)) { return(false); } var setting = hopperSgp.GetStoreSettings(); var limit = setting.GetStacklimit(); if (setting.IsRefillingDisabled() || limit == 0) { return(false); } foreach (var thing2 in pawn.Map.thingGrid.ThingsListAt(thing.Position)) { if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(thing2.def)) { if ((thing2.stackCount * 100) >= ((limit < 0 ? thing2.def.stackLimit : limit) * setting.GetRefillPercent())) { return(false); } } } return(true); }
static bool Prefix(Building_NutrientPasteDispenser __instance, ref Thing __result) { var fc = FridgeCache.GetFridgeCache(__instance.Map); foreach (IntVec3 cell in __instance.AdjCellsCardinalInBounds) { Thing thing = null; Thing holder = null; foreach (Thing t in cell.GetThingList(__instance.Map)) { if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(t.def)) { thing = t; } if (t.def == ThingDefOf.Hopper || fc?.HasFridgeAt(cell) == true) { holder = t; } } if (thing != null && holder != null) { __result = thing; return(false); } } return(false); }
public static bool HasEnoughFeedstockInStorage(ref bool __result, Building_NutrientPasteDispenser __instance) { if (!(__instance.def.GetModExtension <NPDModExtension>() is null)) { bool empty = __instance.def.GetModExtension <NPDModExtension>().ingredientList is null || !__instance.def.GetModExtension <NPDModExtension>().ingredientList.Any(); if (!empty && !(__instance.def.GetCompProperties <CompProperties_Refillable>() is null)) { __result = false; List <IngredientAndCostClass> ingredientList = __instance.def.GetModExtension <NPDModExtension>().ingredientList; for (int i = 0; i < ingredientList.Count; i++) { IngredientAndCostClass ingredient = ingredientList[i]; if (__instance.GetComp <CompRefillable>().items[i] < ingredient.nutritionCost) { __result = false; return(false); } } __result = true; return(false); } Log.Error("Must include ingredient list if using CompRefillable comp class"); } return(true); }
static bool Prefix(Building_NutrientPasteDispenser __instance, ref bool __result) { var fc = FridgeCache.GetFridgeCache(__instance.Map); float num = 0f; foreach (IntVec3 cell in __instance.AdjCellsCardinalInBounds) { Thing thing = null; Thing holder = null; foreach (Thing t in cell.GetThingList(__instance.Map)) { if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(t.def)) { thing = t; } if (t.def == ThingDefOf.Hopper || fc?.HasFridgeAt(cell) == true) { holder = t; } if (thing != null && holder != null) { num += (float)thing.stackCount * thing.GetStatValue(StatDefOf.Nutrition, true); if (num >= __instance.def.building.nutritionCostPerDispense) { __result = true; return(false); } break; } } } return(false); }
public static bool FindFeedInAnyCustomHopper(Building_NutrientPasteDispenser __instance, ref Thing __result, ref List <IntVec3> ___cachedAdjCellsCardinal) { if (___cachedAdjCellsCardinal is null) { ___cachedAdjCellsCardinal = (from c in GenAdj.CellsAdjacentCardinal(__instance) where c.InBounds(__instance.Map) select c).ToList <IntVec3>(); } foreach (IntVec3 c in ___cachedAdjCellsCardinal) { Thing thing = null; Thing thing2 = null; List <Thing> thingList = c.GetThingList(__instance.Map); foreach (Thing t in thingList) { if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(t.def)) { thing = t; } if (t.def == ThingDefOf.Hopper || t.def.thingClass == typeof(NPDHopper_Storage)) { thing2 = t; } } if (thing != null && thing2 != null) { __result = thing; return(false); } } __result = null; return(true); }
public Thing FindNextIngredientInHopper(List <IntVec3> cachedCells, Building_NutrientPasteDispenser instance, float[] nutrition) { foreach (IntVec3 c in cachedCells) { Thing thing = null; Thing thing2 = null; List <Thing> thingList = c.GetThingList(instance.Map); foreach (Thing t in thingList) { if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(t.def) && this.ingredientList.Any(x => x.thingDef == t.def) && nutrition[ingredientList.FindIndex(x => x.thingDef == t.def)] > 0f) { thing = t; } if (t.def == ThingDefOf.Hopper || t.def.thingClass == typeof(NPDHopper_Storage)) { thing2 = t; } } if (!(thing is null) && !(thing2 is null)) { return(thing); } } return(null); }
public static bool AdjacentReachableHopperCustom(Pawn reacher, Building_NutrientPasteDispenser __instance, ref Building __result, List <IntVec3> ___cachedAdjCellsCardinal) { if (__instance.def.HasModExtension <NutrientPasteCustom>()) { if (___cachedAdjCellsCardinal is null) { ___cachedAdjCellsCardinal = (from c in GenAdj.CellsAdjacentCardinal(__instance) where c.InBounds(__instance.Map) select c).ToList <IntVec3>(); } foreach (IntVec3 c in ___cachedAdjCellsCardinal) { Building edifice = c.GetEdifice(__instance.Map); if (!(edifice is null) && (edifice.def == ThingDefOf.Hopper || edifice.def.thingClass == typeof(NPDHopper_Storage)) && reacher.CanReach(edifice, PathEndMode.Touch, Danger.Deadly, false, TraverseMode.ByPawn)) { __result = edifice; return(false); } } } return(true); }
internal static List <IntVec3> _AdjCellsCardinalInBounds(Building_NutrientPasteDispenser obj) { if (__AdjCellsCardinalInBounds == null) { __AdjCellsCardinalInBounds = typeof(Building_NutrientPasteDispenser).GetProperty("AdjCellsCardinalInBounds", BindingFlags.Instance | BindingFlags.NonPublic); } return(__AdjCellsCardinalInBounds.GetValue(obj, null) as List <IntVec3>); }
internal static Thing _FindFeedInAnyHopper(this Building_NutrientPasteDispenser obj) { // Check for generic hoppers var CompHopperUser = obj.TryGetComp <CompHopperUser>(); if (CompHopperUser != null) { var hoppers = CompHopperUser.FindHoppers(); if (!hoppers.NullOrEmpty()) { foreach (var hopper in hoppers) { var resources = hopper.GetAllResources(CompHopperUser.Resources); if (!resources.NullOrEmpty()) { foreach (var resource in resources) { // This check shouldn't be needed, but we'll do it as a fail-safe if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(resource.def)) { return(resource); } } } } } } // Check for vanilla hoppers var adjCells = _AdjCellsCardinalInBounds(obj); for (int cellIndex = 0; cellIndex < adjCells.Count; ++cellIndex) { IntVec3 c = adjCells[cellIndex]; Thing resource = (Thing)null; Thing hopper = (Thing)null; List <Thing> thingList = c.GetThingList(); for (int thingIndex = 0; thingIndex < thingList.Count; ++thingIndex) { Thing thisThing = thingList[thingIndex]; if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(thisThing.def)) { resource = thisThing; } if (thisThing.def == ThingDefOf.Hopper) { hopper = thisThing; } } if ( (resource != null) && (hopper != null) ) { return(resource); } } return((Thing)null); }
public static bool DispensableDefCustom(ref ThingDef __result, Building_NutrientPasteDispenser __instance) { if (__instance.def.HasModExtension <NutrientPasteCustom>()) { __result = __instance.def.GetModExtension <NutrientPasteCustom>().customMeal; return(false); } return(true); }
internal static bool _HasEnoughFeedstockInHoppers(this Building_NutrientPasteDispenser obj) { int costPerDispense = obj.def.building.foodCostPerDispense; /* Research Project cut from A13 * if( ResearchProjectDef.Named( "NutrientResynthesis" ).IsFinished ) * { * costPerDispense--; * } */ // Check for generic hoppers var CompHopperUser = obj.TryGetComp <CompHopperUser>(); if (CompHopperUser != null) { if (CompHopperUser.EnoughResourcesInHoppers(costPerDispense)) { return(true); } } // Check for vanilla hoppers var adjCells = _AdjCellsCardinalInBounds(obj); int resourceCount = 0; for (int cellIndex = 0; cellIndex < adjCells.Count; ++cellIndex) { IntVec3 c = adjCells[cellIndex]; Thing resource = (Thing)null; Thing hopper = (Thing)null; List <Thing> thingList = GridsUtility.GetThingList(c); for (int thingIndex = 0; thingIndex < thingList.Count; ++thingIndex) { Thing thisThing = thingList[thingIndex]; if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(thisThing.def)) { resource = thisThing; } if (thisThing.def == ThingDefOf.Hopper) { hopper = thisThing; } } if ( (resource != null) && (hopper != null) ) { resourceCount += resource.stackCount; } if (resourceCount >= costPerDispense) { return(true); } } return(false); }
// RimWorld.Building_NutrientPasteDispenser //static private List<IntVec3> AdjCellsCardinalInBounds(this Building_NutrientPasteDispenser self) //{ // return (List<IntVec3>)typeof(RimWorld.Building_NutrientPasteDispenser).GetProperty("AdjCellsCardinalInBounds", Helpers.AllBindingFlags).GetValue(self,null); //} static private List <IntVec3> AdjCellsCardinalInBounds(this Building_NutrientPasteDispenser self) { if (self.cachedAdjCellsCardinal() == null) { var value = (from c in GenAdj.CellsAdjacentCardinal(self) where c.InBounds(self.Map) select c).ToList <IntVec3>(); self.cachedAdjCellsCardinal_set_(value); } return(self.cachedAdjCellsCardinal()); }
static void Postfix(Building __instance, ref IEnumerable <Gizmo> __result) { if (__instance is Building_NutrientPasteDispenser) { //Log.Message("Hello from Harmony Postfix Patch_Building_GetGizmos " + __result.Count()); //Building_NutrientPasteDispenser myThis = (Building_NutrientPasteDispenser)__instance; //MethodInfo CanDispenseNow = myThis.GetType().GetMethod("CanDispenseNow", BindingFlags.Instance | BindingFlags.Public); //MethodInfo TryDispenseFood = myThis.GetType().GetMethod("TryDispenseFood", BindingFlags.Instance | BindingFlags.Public); //int[] numbers = { 1, 5, 25 }; //foreach (int i in numbers) //{ // Gizmo newGizmo = new Command_Action // { // defaultLabel = "Dispense " + i, // action = delegate // { // int k = i; // for (int j = 0; j < k && (bool) CanDispenseNow.Invoke(myThis, null); j++) // { // TryDispenseFood.Invoke(myThis, null); // } // } // }; // __result.Add(newGizmo); //} Building_NutrientPasteDispenser myThis = (Building_NutrientPasteDispenser)__instance; int[] numbers = { 1, 5, 25 }; foreach (int i in numbers) { Gizmo newGizmo = new Command_Action { defaultLabel = "Dispense " + i, icon = ContentFinder <Texture2D> .Get("UI/Designators/Open"), action = delegate { for (int j = 0; j < i && myThis.CanDispenseNow; j++) { Thing meal = myThis.TryDispenseFood(); GenPlace.TryPlaceThing(meal, myThis.InteractionCell, myThis.Map, ThingPlaceMode.Near); } } }; __result = __result.AddItem(newGizmo); } //Log.Message("Goodbye from Harmony Postfix Patch_Building_GetGizmos " + __result.Count()); } }
static List <Thing> IngredientsFor(Building_NutrientPasteDispenser self, DispenseMode mode) { var list = GetAllHoppersThings(self); int[] foodCountByRank = new int[4]; for (int i = 0; i < 4; i++) { var current = foodCountByRank[i]; foodCountByRank[i] = list.Where((arg) => rankForPawn(mode, arg.def) == i).Sum((arg) => arg.stackCount); } FoodCategory[] ranking; if (mode == DispenseMode.Cannibal || mode == DispenseMode.CannibalClean) { ranking = ranksForCannibals; } else if (mode == DispenseMode.Animal) { ranking = ranksForAnimals; } else { ranking = ranksForOthers; } var rawbadindex = Array.IndexOf(ranking, FoodCategory.RawBad); var rawtastyindex = Array.IndexOf(ranking, FoodCategory.RawTasty); foodCountByRank[rawbadindex] = foodCountByRank[rawtastyindex] = foodCountByRank[rawbadindex] + foodCountByRank[rawtastyindex]; var query = (from e in list orderby foodCountByRank[rankForPawn(mode, e.def)] < 6, rankForPawn(mode, e.def), (e.TryGetComp <CompRottable>() != null ? e.TryGetComp <CompRottable>().TicksUntilRotAtCurrentTemp : -9999999) select e).ToList(); if (mode == DispenseMode.Clean) { query = query.Where((Thing arg) => !RimWorld.FoodUtility.IsHumanlikeMeat(arg.def) && arg.def.DetermineFoodCategory() != FoodCategory.RawInsect).ToList(); } else if (mode == DispenseMode.CannibalClean) { query = query.Where((Thing arg) => arg.def.DetermineFoodCategory() != FoodCategory.RawInsect).ToList(); } return(query); }
internal static Building _AdjacentReachableHopper(this Building_NutrientPasteDispenser obj, Pawn reacher) { // Check for generic hoppers var CompHopperUser = obj.TryGetComp <CompHopperUser>(); if (CompHopperUser != null) { var hoppers = CompHopperUser.FindHoppers(); if (!hoppers.NullOrEmpty()) { foreach (var hopper in hoppers) { if ( reacher.CanReach( ( TargetInfo )(( Thing )hopper.parent), PathEndMode.Touch, reacher.NormalMaxDanger(), false) ) { return((Building)hopper.parent); } } } } // Check for vanilla hoppers var adjCells = _AdjCellsCardinalInBounds(obj); for (int index = 0; index < adjCells.Count; ++index) { Building edifice = adjCells[index].GetEdifice(); if ( (edifice != null) && (edifice.def == ThingDefOf.Hopper) && (reacher.CanReach( ( TargetInfo )(( Thing )edifice), PathEndMode.Touch, reacher.NormalMaxDanger(), false)) ) { return(edifice); } } return((Building)null); }
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); }
static void Postfix(Building_NutrientPasteDispenser __instance, ref Thing __result) { if (__result == null) { //loop over Inputs for (int i = 0; i < __instance.AdjCellsCardinalInBounds.Count; i++) { //Get list of Items INutrientPasteDispenserInput input = (INutrientPasteDispenserInput)__instance.AdjCellsCardinalInBounds[i].GetThingList(__instance.Map).Where(thing => thing is INutrientPasteDispenserInput).FirstOrDefault(); if (input == null || input.NPDI_Item == null) { continue; } if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(input.NPDI_Item.def)) { __result = input.NPDI_Item; } if (__result != null) { break; } } } }
public static bool HasEnoughFeedstockInCustomHoppers(ref bool __result, Building_NutrientPasteDispenser __instance, ref List <IntVec3> ___cachedAdjCellsCardinal) { if (!(__instance.def.GetModExtension <NutrientPasteCustom>() is null)) { if (___cachedAdjCellsCardinal is null) { ___cachedAdjCellsCardinal = (from c in GenAdj.CellsAdjacentCardinal(__instance) where c.InBounds(__instance.Map) select c).ToList <IntVec3>(); } float num = 0f; bool empty = __instance.def.GetModExtension <NutrientPasteCustom>().ingredientList is null || !__instance.def.GetModExtension <NutrientPasteCustom>().ingredientList.Any(); if (!empty) { __result = false; List <IngredientAndCostClass> ingredientList = __instance.def.GetModExtension <NutrientPasteCustom>().ingredientList; bool[] ingredientFulfilled = new bool[ingredientList.Count]; float[] nutritionCost = new float[ingredientList.Count]; foreach (IntVec3 c in ___cachedAdjCellsCardinal) { Thing thing = null; Thing thing2 = null; List <Thing> thingList = c.GetThingList(__instance.Map); foreach (Thing t in thingList) { if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(t.def) && ingredientList.Any(x => x.thingDef == t.def) && nutritionCost[ingredientList.FindIndex(x => x.thingDef == t.def)] <= 0f) { thing = t; } if (t.def == ThingDefOf.Hopper || t.def.thingClass == typeof(NPDHopper_Storage)) { thing2 = t; } } if (!(thing is null) && !(thing2 is null)) { nutritionCost[ingredientList.FindIndex(x => x.thingDef == thing.def)] += (float)thing.stackCount * thing.GetStatValue(StatDefOf.Nutrition, true); if (nutritionCost[ingredientList.FindIndex(x => x.thingDef == thing.def)] >= ingredientList.Find(x => x.thingDef == thing.def).nutritionCost) { ingredientFulfilled[ingredientList.FindIndex(x => x.thingDef == thing.def)] = true; } } if (ingredientFulfilled.All(x => x)) { __result = true; return(false); } } return(false); } foreach (IntVec3 c in ___cachedAdjCellsCardinal) { Thing thing = null; Thing thing2 = null; List <Thing> thingList = c.GetThingList(__instance.Map); foreach (Thing t in thingList) { if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(t.def)) { thing = t; } if (t.def == ThingDefOf.Hopper || t.def.thingClass == typeof(NPDHopper_Storage)) { thing2 = t; } } if (thing != null && thing2 != null) { num += (float)thing.stackCount * thing.GetStatValue(StatDefOf.Nutrition, true); } if (num >= __instance.def.building.nutritionCostPerDispense) { __result = true; return(false); } } __result = false; return(false); } return(true); }
public 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, bool calculateWantedStackCount = false, FoodPreferability minPrefOverride = FoodPreferability.Undefined, float?minNutrition = null) { foodDef = 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 || (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; float statValue = t.GetStatValue(StatDefOf.Nutrition); if (minNutrition.HasValue) { stackCount = FoodUtility.StackCountForNutrition(minNutrition.Value, statValue); } else if (calculateWantedStackCount) { stackCount = FoodUtility.WillIngestStackCountOf(eater, t.def, 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) { 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)FoodUtility.GetFinalIngestibleDef(bestThing).ingestible.preferability < (int)harvestedThingDef.ingestible.preferability) ? true : false); }); if (thing != null) { bestThing = thing; foodDef = FoodUtility.GetFinalIngestibleDef(thing, harvest: true); } } if (foodDef == null && bestThing != null) { foodDef = FoodUtility.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 = FoodUtility.GetFinalIngestibleDef(bestThing); } } return(bestThing); }
static private List <IntVec3> cachedAdjCellsCardinal(this Building_NutrientPasteDispenser self) { return((List <IntVec3>) typeof(RimWorld.Building_NutrientPasteDispenser).GetField("cachedAdjCellsCardinal", Helpers.AllBindingFlags).GetValue(self)); }
static private void cachedAdjCellsCardinal_set_(this Building_NutrientPasteDispenser self, List <IntVec3> value) { typeof(RimWorld.Building_NutrientPasteDispenser).GetField("cachedAdjCellsCardinal", Helpers.AllBindingFlags).SetValue(self, value); }
internal static Job HopperFillFoodJob(Pawn pawn, Building hopper, Thing parent) { var hopperSgp = hopper as ISlotGroupParent; if ( (!pawn.CanReserveAndReach( hopper.Position, PathEndMode.Touch, pawn.NormalMaxDanger(), 1) ) ) { return(null); } ThingDef resourceDef = null; var firstItem = hopper.Position.GetFirstItem(); if (firstItem != null) { if ( ( (parent is Building_NutrientPasteDispenser) && (Building_NutrientPasteDispenser.IsAcceptableFeedstock(firstItem.def)) ) || ( (parent is Building_AutomatedFactory) && (((Building_AutomatedFactory)parent).CompHopperUser.ResourceSettings.AllowedToAccept(firstItem)) ) ) { resourceDef = firstItem.def; } else { if (firstItem.IsForbidden(pawn)) { return(( Job )null); } return(HaulAIUtility.HaulAsideJobFor(pawn, firstItem)); } } List <Thing> list = resourceDef != null ? Find.Map.listerThings.ThingsOfDef(resourceDef) : Find.Map.listerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree); for (int index = 0; index < list.Count; ++index) { Thing t = list[index]; if ( (t.def.IsNutritionGivingIngestible) && ( (t.def.ingestible.preferability == FoodPreferability.RawBad) || (t.def.ingestible.preferability == FoodPreferability.RawTasty) ) && (HaulAIUtility.PawnCanAutomaticallyHaul(pawn, t)) && ( (Find.SlotGroupManager.SlotGroupAt(hopper.Position).Settings.AllowedToAccept(t)) && (HaulAIUtility.StoragePriorityAtFor(t.Position, t) < hopperSgp.GetSlotGroup().Settings.Priority) ) ) { Job job = HaulAIUtility.HaulMaxNumToCellJob(pawn, t, hopper.Position, true); if (job != null) { return(job); } } } return(null); }
static private void cachedAdjCellsCardinal_set_(this Building_NutrientPasteDispenser self, List <IntVec3> value) { typeof(RimWorld.Building_NutrientPasteDispenser).GetField("cachedAdjCellsCardinal", AccessTools.all).SetValue(self, value); }
public static bool TryDispenseCustomFood(ref Thing __result, Building_NutrientPasteDispenser __instance, ref List <IntVec3> ___cachedAdjCellsCardinal) { if (__instance.def.HasModExtension <NutrientPasteCustom>()) { if (!__instance.CanDispenseNow) { __result = null; return(false); } List <ThingDef> list = new List <ThingDef>(); List <IngredientAndCostClass> ingredientList = __instance.def.GetModExtension <NutrientPasteCustom>().ingredientList; bool empty = !__instance.def.GetModExtension <NutrientPasteCustom>().ingredientList.Any(); Log.Message("-" + empty); if (!empty) { float[] nutritionLeft = new float[ingredientList.Count]; for (int i = 0; i < nutritionLeft.Length; i++) { nutritionLeft[i] = ingredientList[i].nutritionCost; } for (; ;) { Thing thing = __instance.def.GetModExtension <NutrientPasteCustom>().FindNextIngredientInHopper(___cachedAdjCellsCardinal, __instance, nutritionLeft); if (thing is null) { break; } int index = ingredientList.FindIndex(x => x.thingDef == thing.def); int num2 = Mathf.Min(thing.stackCount, Mathf.CeilToInt(nutritionLeft[index] / thing.GetStatValue(StatDefOf.Nutrition, true))); nutritionLeft[index] -= (float)num2 * thing.GetStatValue(StatDefOf.Nutrition, true); list.Add(thing.def); thing.SplitOff(num2); if (!nutritionLeft.Any(x => x > 0f)) { goto Block_3; } } } else { Log.Message("2"); float num = __instance.def.building.nutritionCostPerDispense - 0.0001f; for (; ;) { Thing thing = __instance.FindFeedInAnyHopper(); if (thing is null) { break; } int num2 = Mathf.Min(thing.stackCount, Mathf.CeilToInt(num / thing.GetStatValue(StatDefOf.Nutrition, true))); num -= (float)num2 * thing.GetStatValue(StatDefOf.Nutrition, true); list.Add(thing.def); thing.SplitOff(num2); if (num <= 0f) { goto Block_3; } } } Log.Error("Did not find enough food in hoppers while trying to dispense.", false); __result = null; return(false); Block_3: __instance.def.building.soundDispense.PlayOneShot(new TargetInfo(__instance.Position, __instance.Map, false)); Thing thing2 = ThingMaker.MakeThing(__instance.def.GetModExtension <NutrientPasteCustom>().customMeal, null); CompIngredients compIngredients = thing2.TryGetComp <CompIngredients>(); foreach (ThingDef ingredient in list) { if (!__instance.def.GetModExtension <NutrientPasteCustom>().mysteryIngredients) { compIngredients.RegisterIngredient(ingredient); } } __result = thing2; return(false); } return(true); }
static private List <IntVec3> cachedAdjCellsCardinal(this Building_NutrientPasteDispenser self) { return((List <IntVec3>) typeof(RimWorld.Building_NutrientPasteDispenser).GetField("cachedAdjCellsCardinal", AccessTools.all).GetValue(self)); }
static void Postfix(Building_NutrientPasteDispenser __instance, ref bool __result) { //Sadly witth the current valilla implementation adding support between mods is difficult. //Each mod needs to patch this but cant build on the progress of the other one. // //If for example Rimfrige supplies 50% of the nutriants then we will never know about it //If we want to support the input of other mods we need a patch for them. if (__result == false) { //Support for Rimfrige object rimFridgeCache = null; if (ProjectRimFactory_ModComponent.ModSupport_RrimFrige_Dispenser) { rimFridgeCache = ProjectRimFactory_ModComponent.ModSupport_RrimFridge_GetFridgeCache.Invoke(null, new object[] { (object)__instance.Map }); } float num = 0f; for (int i = 0; i < __instance.AdjCellsCardinalInBounds.Count; i++) { IntVec3 c = __instance.AdjCellsCardinalInBounds[i]; INutrientPasteDispenserInput input = (INutrientPasteDispenserInput)c.GetThingList(__instance.Map).Where(thing => thing is INutrientPasteDispenserInput).FirstOrDefault(); if (input != null && input.NPDI_Item != null && Building_NutrientPasteDispenser.IsAcceptableFeedstock(input.NPDI_Item.def)) { num += (float)input.NPDI_Item.stackCount * input.NPDI_Item.GetStatValue(StatDefOf.Nutrition); } else { Thing thing = null; Thing thing2 = null; List <Thing> thingList = c.GetThingList(__instance.Map); for (int j = 0; j < thingList.Count; j++) { Thing thing3 = thingList[j]; if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(thing3.def)) { thing = thing3; } //Support for Rimfrige if (rimFridgeCache != null) { bool isfc = (bool)ProjectRimFactory_ModComponent.ModSupport_RrimFridge_HasFridgeAt.Invoke(rimFridgeCache, new object[] { (object)c }); if (isfc) { thing2 = thing3; } } if (thing3.def == ThingDefOf.Hopper) { thing2 = thing3; } } if (thing != null && thing2 != null) { num += (float)thing.stackCount * thing.GetStatValue(StatDefOf.Nutrition); } } if (num >= __instance.def.building.nutritionCostPerDispense) { __result = true; break; } } } }