public static List <ThoughtDef> GetBestMealThoughtsFor(this RimWorld.Building_NutrientPasteDispenser self, Pawn eater) { List <ThoughtDef> thoughts; if (!self.HasEnoughFeedstockInHoppers() || !eater.RaceProps.Humanlike) { return(new List <ThoughtDef>()); } var list = IngredientsFor(self, eater.IsCannibal() ? DispenseMode.Cannibal : DispenseMode.Standard); // make dummy meal for thoughts simulation Thing dummyMeal = ThingMaker.MakeThing(ThingDefOf.MealNutrientPaste, null); CompIngredients compIngredients = dummyMeal.TryGetComp <CompIngredients>(); float num = 0; for (int i = 0; num < NutritionCostPerDispense; i++) { float num2 = Mathf.Min(list[i].stackCount * list[i].GetStatValue(StatDefOf.Nutrition), NutritionCostPerDispense); num += num2; compIngredients.RegisterIngredient(list[i].def); } thoughts = RimWorld.FoodUtility.ThoughtsFromIngesting(eater, dummyMeal, dummyMeal.def); dummyMeal.Destroy(); return(thoughts); }
//private static FieldInfo ingredientsCompField; internal static void ClearIngs(CompIngredients ings) { if (ings != null) { ings.ingredients.Clear(); } }
public override bool Matches(Thing t) { if (!t.def.IsIngestible) { return(false); } CompIngredients ingredients = t.TryGetComp <CompIngredients>(); if (ingredients != null) { foreach (var ingredient in ingredients.ingredients) { CompProperties_FoodGroup foodGroup = ingredient.GetCompProperties <CompProperties_FoodGroup>(); if (foodGroup != null) { return(foodGroup.foodGroup == FoodGroup.Fruit); } } } else { CompProperties_FoodGroup foodGroup = t.def.GetCompProperties <CompProperties_FoodGroup>(); if (foodGroup != null) { return(foodGroup.foodGroup == FoodGroup.Fruit); } } return(false); }
public static void FoodIngested(Pawn ingester, Thing foodSource, ThingDef foodDef) { properties.Clear(); if (ingester.RaceProps.Animal) { return; } ReligionSettings_Social settings = ingester.GetReligionComponent().Religion.GetSettings <ReligionSettings_Social>(SettingsTagDefOf.FoodTag); if (settings != null) { properties.Add(settings.GetPropertyByObject(ingester, foodDef)); CompIngredients comp = foodSource.TryGetComp <CompIngredients>(); if (comp != null) { foreach (ThingDef ingredient in comp.ingredients) { properties.Add(settings.GetPropertyByObject(ingester, ingredient)); } } foreach (ReligionProperty property in properties) { if (property != null) { PietyUtility.TryApplyOnPawn(property.Subject, ingester, property.GetObject().LabelCap); } } } }
public override void CkeckResolve(Thing thing, int amount, float nutriment) { IngestibleInfo ingestibleInfo = null; if (FoodUtility.IsHumanlikeMeatOrHumanlikeCorpse(thing)) { ingestibleInfo = ThingsWanted[0]; } else if (ThingsWanted[0].inIngredient) { CompIngredients compIngredients = thing.TryGetComp <CompIngredients>(); if (compIngredients != null && !compIngredients.ingredients.NullOrEmpty()) { amount = 0; nutriment = 0; for (int i = 0; i < compIngredients.ingredients.Count; i++) { if (FoodUtility.IsHumanlikeMeat(compIngredients.ingredients[i])) { RecipeDef recipe = DefDatabase <RecipeDef> .AllDefsListForReading.Find(rec => rec.ProducedThingDef == thing.def); IngredientCount ingredient = recipe?.ingredients?.Find(ing => ing.filter.Allows(compIngredients.ingredients[i])) ?? null; if (ingredient != null) { amount += ingredient.CountRequiredOfFor(ThingsWanted[0].ingestible, recipe); nutriment += ingredient.GetBaseCount(); ingestibleInfo = ThingsWanted[0]; } } } } } DoUpdate(ingestibleInfo, amount, nutriment); }
static void Postfix(Thing __result, ThingDef def, ThingDef stuff) { if (Settings.CommonSenseMod == null || __result == null || __result.def == null || !__result.def.IsIngestible) { return; } CompIngredients ings = __result.TryGetComp <CompIngredients>(); if (ings == null || ings.ingredients.Count == 0) { return; } // if (def == PackedMeat.MysteriousPackDef) { ings.ingredients.Clear(); if (humanlikes == null) { humanlikes = DefDatabase <ThingDef> .AllDefsListForReading.Where(x => x.IsIngestible && x.ingestible.foodType == FoodTypeFlags.Meat && x.ingestible.sourceDef != null && x.ingestible.sourceDef.race != null && x.ingestible.sourceDef.race.Humanlike); } ThingDef td = humanlikes.RandomElement(); if (td != null) { ings.RegisterIngredient(td); } } else if (def == PackedMeat.OddPackDef) { ings.ingredients.Clear(); if (disgusting == null) { disgusting = DefDatabase <ThingDef> .AllDefsListForReading.Where(x => x.IsIngestible && x.ingestible.foodType == FoodTypeFlags.Meat && x.ingestible.sourceDef != null && x.ingestible.sourceDef.race != null && x.ingestible.sourceDef.race.Insect); } ThingDef td = disgusting.RandomElement(); if (td != null) { ings.RegisterIngredient(td); } } else if (def == PackedMeat.RegularPackDef) { ings.ingredients.Clear(); if (regular == null) { regular = DefDatabase <ThingDef> .AllDefsListForReading.Where(x => x.IsIngestible && x.ingestible.foodType == FoodTypeFlags.Meat && x.ingestible.sourceDef != null && x.ingestible.sourceDef.race != null && !x.ingestible.sourceDef.race.Humanlike && !x.ingestible.sourceDef.race.Insect && (x.ingredient == null || x.ingredient.mergeCompatibilityTags.NullOrEmpty())); } ThingDef td = regular.RandomElement(); if (td != null) { ings.RegisterIngredient(td); } } }
private static void Postfix(Thing __instance, Pawn ingester, float nutritionWanted) { if (ingester.RaceProps.Humanlike) { if (IsHumanlikeMeat(__instance.def)) { if (Rand.Chance(0.1f)) { TaleRecorder.RecordTale(VSIE_DefOf.VSIE_IngestedHumanFlesh, ingester); } return; } else { CompIngredients compIngredients = __instance.TryGetComp <CompIngredients>(); if (compIngredients != null) { for (int i = 0; i < compIngredients.ingredients.Count; i++) { if (IsHumanlikeMeat(compIngredients.ingredients[i])) { if (Rand.Chance(0.1f)) { TaleRecorder.RecordTale(VSIE_DefOf.VSIE_IngestedHumanFlesh, ingester); } return; } } } } } }
public static void ClearIngs(Thing thing) { CompIngredients comp = thing.TryGetComp <CompIngredients>(); if (comp != null) { comp.ingredients.Clear(); } }
static void Postfix(CompIngredients __instance, ref string __result) { if (__instance.ingredients == null || __instance.ingredients.Count == 0) { return; } __result += "\n" + "Nutrition.FoodGroups".Translate() + ": "; __result += string.Join(", ", __instance.ingredients.Select(ingredient => ingredient.GetCompProperties <CompProperties_FoodGroup>()).Where(x => x != null).Select(foodGroup => foodGroup.foodGroup.ToString("G")).ToArray()); }
//[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].GetStatValue(StatDefOf.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); }
static void StackIn(Thing thing, CompIngredients ingredients, Thing with) { ingredients.RegisterIngredient(with.def); CompRottable r = thing.TryGetComp <CompRottable>(); CompRottable rr = with.TryGetComp <CompRottable>(); if (r != null && rr != null) { r.RotProgress = (r.RotProgress * thing.stackCount + rr.RotProgress * with.stackCount) / (thing.stackCount + with.stackCount); } thing.stackCount += with.stackCount; }
// Token: 0x06000011 RID: 17 RVA: 0x00002740 File Offset: 0x00000940 public virtual void MakeProducts() { foreach (ThingDefCountClass thingCountClass in this.Extension.products) { Thing thing = ThingMaker.MakeThing(thingCountClass.thingDef, null); thing.stackCount = thingCountClass.count; CompIngredients compIngredients = ThingCompUtility.TryGetComp <CompIngredients>(thing); bool flag = compIngredients != null; if (flag) { compIngredients.ingredients.AddRange(from ThingDefCountClass i in this.Extension.ingredients select i.thingDef); } GenPlace.TryPlaceThing(thing, this.InteractionCell, base.Map, ThingPlaceMode.Near); } }
static void Postfix(ref IEnumerable <Thing> __result, ref Pawn __instance) { if (!Settings.pack_on_butchering || __result == null || !__result.Any()) { return; } var things = __result.ToList(); Thing meat = things.Find(x => x.def.IsIngestible && x.def.ingestible.foodType == FoodTypeFlags.Meat); if (meat == null || meat.def.ingestible.ateEvent != null) { return; } ThingDef d; if (FoodUtility.GetMeatSourceCategory(meat.def) == MeatSourceCategory.Humanlike) { d = PackedMeat.MysteriousPackDef; } else if (FoodUtility.GetMeatSourceCategory(meat.def) == MeatSourceCategory.Insect) { d = PackedMeat.OddPackDef; } else { d = PackedMeat.RegularPackDef; } ThingWithComps t = (ThingWithComps)ThingMaker.MakeThing(d, null); t.stackCount = meat.stackCount; CompIngredients ingredientsComp = t.TryGetComp <CompIngredients>(); if (ingredientsComp != null) { ingredientsComp.ingredients.Clear(); ingredientsComp.RegisterIngredient(meat.def); } things.Remove(meat); things.Insert(0, t); __result = things; }
static void Postfix(ref IEnumerable <Thing> __result, ref Pawn __instance) { if (!Settings.pack_on_butchering || __result == null || !__result.Any()) { return; } var things = __result.ToList(); Thing meat = things.Find(x => x.def.IsIngestible && x.def.ingestible.foodType == FoodTypeFlags.Meat); if (meat == null) { return; } ThingDef d; if (FoodUtility.IsHumanlikeMeat(meat.def)) { d = PackedMeat.MysteriousPackDef; } else if (!Settings.unusual_is_generic && meat.def.ingestible.specialThoughtDirect != null && meat.def.ingestible.specialThoughtDirect.stages[0].baseMoodEffect < 0) { d = PackedMeat.OddPackDef; } else { d = PackedMeat.RegularPackDef; } ThingWithComps t = (ThingWithComps)ThingMaker.MakeThing(d, null); t.stackCount = meat.stackCount; CompIngredients ingredientsComp = t.TryGetComp <CompIngredients>(); if (ingredientsComp != null) { ingredientsComp.ingredients.Clear(); ingredientsComp.RegisterIngredient(meat.def); } things.Remove(meat); things.Insert(0, t); __result = things; }
private static void ThoughtsFromIngesting_Postfix(Pawn ingester, Thing foodSource, ThingDef foodDef, ref List <ThoughtDef> __result) { if (!ingester.RaceProps.Humanlike) { return; } //direct consumption if (foodDef.IsHumanlikeBlood() && foodDef.ingestible.sourceDef != ingester.def && ingester.IsXenophobic()) //this line is alien specific { if (ingester.story.traits.HasTrait(TraitDefOf.Bloodlust)) { __result.Add(BloodBankUtilities.ConsumeHumanlikeBloodDirectBloodlustThought); } else if (ingester.story.traits.HasTrait(TraitDefOf.Cannibal)) { __result.Add(BloodBankUtilities.ConsumeHumanlikeBloodDirectCannibalThought); } else { __result.Add(BloodBankUtilities.ConsumeHumanlikeBloodDirectThought); } return; } //consumption as ingredient CompIngredients ingredientComp = foodSource.TryGetComp <CompIngredients>(); if (ingredientComp == null) { return; } __result.AddRange(from ingredient in ingredientComp.ingredients where ingredient.ingestible != null && ingredient.IsHumanlikeBlood() && ingredient.ingestible.sourceDef != ingester.def && ingester.IsXenophobic() //and this select ingester.story.traits.HasTrait(TraitDefOf.Cannibal) ? BloodBankUtilities.ConsumeHumanlikeBloodIngredientCannibalThought : BloodBankUtilities.ConsumeHumanlikeBloodIngredientThought); }
static int getflags(CompIngredients compIngredients) { if (compIngredients?.ingredients == null) { return(0); } int b = 0; //0 - clean; //1 - positive //2 - negative //4 - humanlike foreach (var ing in compIngredients.ingredients) { if (ing == null) { continue; } else if (!ing.IsIngestible) { continue; } else if (FoodUtility.GetMeatSourceCategory(ing) == MeatSourceCategory.Humanlike) { b = b | 4; } else if (ing.ingestible?.specialThoughtAsIngredient?.stages?.Count > 0) { //if(ing.ingestible.specialThoughtAsIngredient.stages[0].baseMoodEffect > 0) // b = b | 1; //else if (!Settings.odd_is_normal && ing.ingestible.specialThoughtAsIngredient.stages[0].baseMoodEffect < 0) { b = b | 2; } } } return(b); }
private static void ThoughtsFromIngesting_Postfix(Pawn ingester, Thing foodSource, ThingDef foodDef, ref List <ThoughtDef> __result) { if (!ingester.RaceProps.Humanlike) { return; } //direct consumption if (foodDef.IsHumanlikeBlood()) //much saving, so optimize. wow.🐶 { if (ingester.story.traits.HasTrait(TraitDefOf.Bloodlust)) { __result.Add(BloodBankUtilities.ConsumeHumanlikeBloodDirectBloodlustThought); } else if (ingester.story.traits.HasTrait(TraitDefOf.Cannibal)) { __result.Add(BloodBankUtilities.ConsumeHumanlikeBloodIngredientCannibalThought); } else { __result.Add(BloodBankUtilities.ConsumeHumanlikeBloodDirectThought); } return; } //consumption as ingredient CompIngredients ingredientComp = foodSource.TryGetComp <CompIngredients>(); if (ingredientComp == null) { return; } __result.AddRange(from ingredient in ingredientComp.ingredients where ingredient.ingestible != null && ingredient.IsHumanlikeBlood() //The mad bastard did it again! How can we deal with such optimized code?! select ingester.story.traits.HasTrait(TraitDefOf.Cannibal) ? BloodBankUtilities.ConsumeHumanlikeBloodIngredientCannibalThought : BloodBankUtilities.ConsumeHumanlikeBloodIngredientThought); }
public static bool PawnNotHaveActiveCondimentAsFood(Thing t, bool desperate, Pawn pawn) { if (desperate) { return(true); } List <ThoughtDef> hasThouthgs = pawn?.needs?.mood?.thoughts?.memories?.Memories .Where(m => ThoughtDefs.AllThoughts.Contains(m.def)) .Select(m => m.def) .ToList(); if (!hasThouthgs?.Any() ?? true) { return(true); } CompIngredients compIngredients = t.TryGetComp <CompIngredients>(); if (compIngredients == null) { return(true); } bool result = false; try { result = !compIngredients.ingredients .Any(def => def != null && hasThouthgs.Contains(def.ingestible.specialThoughtAsIngredient)); } catch (Exception e) { Log.Warning($"Something wonky happens to your meal {t}.\n{e}"); } return(result); }
static void Postfix(Thing __result, ThingDef def, ThingDef stuff) { if (!Settings.add_meal_ingredients || __result == null || !__result.def.IsIngestible) { return; } CompIngredients ings = __result.TryGetComp <CompIngredients>(); if (ings == null || ings.ingredients.Count > 0) { return; } RecipeDef d = hTable.TryGetValue(def); if (d == null) { d = DefDatabase <RecipeDef> .AllDefsListForReading.Where(x => !x.ingredients.NullOrEmpty() && x.products.Any(y => y.thingDef == def)).RandomElement(); if (d == null) { return; } hTable.Add(def, d); } foreach (IngredientCount c in d.ingredients) { ThingDef td = c.filter.AllowedThingDefs.Where( x => x.IsIngestible && !x.comps.Any(y => y.compClass == typeof(CompIngredients)) && !FoodUtility.IsHumanlikeMeat(x) && (x.ingestible.specialThoughtAsIngredient == null || x.ingestible.specialThoughtAsIngredient.stages[0].baseMoodEffect >= 0) ).RandomElement(); if (td != null) { ings.RegisterIngredient(td); } } }
static void Postfix(ref bool __result, ref Thing __instance, ref Thing other) { if (!Settings.separate_meals || __instance == null || !__result || other == null || !other.def.IsIngestible) { return; } CompIngredients ings = __instance.TryGetComp <CompIngredients>(); if (ings == null) { return; } CompIngredients otherings = other.TryGetComp <CompIngredients>(); if (otherings == null) { return; } __result = getflags(ings) == getflags(otherings); }
static void Postfix(Thing __instance, float __result, Pawn ingester, float nutritionWanted) { if (__result > 0) { bool isHumanLike = false; if (FoodUtility.IsHumanlikeMeat(__instance.def)) { isHumanLike = true; } else { CompIngredients compIngredients = __instance.TryGetComp <CompIngredients>(); if (compIngredients != null) { foreach (var ing in compIngredients.ingredients) { if (FoodUtility.IsHumanlikeMeat(ing)) { isHumanLike = true; break; } } } } if (isHumanLike && ingester.RaceProps.Humanlike) { var progress = CanibalismProgression.For(ingester); if (!progress.Locked) { progress.Add(__result); progress.TryBecomeCannibal(); } } } }
public virtual void CkeckResolve(Thing thing, int amount, float nutriment) { IngestibleInfo ingestibleInfo = null; for (int i = 0; i < ThingsWanted.Count; i++) { if (thingsIngested[ThingsWanted[i].ingestible] >= ThingsWanted[i].amount) { continue; } if (ThingsWanted[i].ingestible == thing.def) { ingestibleInfo = ThingsWanted[i]; break; } else if (ThingsWanted[i].inIngredient) { CompIngredients compIngredients = thing.TryGetComp <CompIngredients>(); if (compIngredients != null && compIngredients.ingredients.Contains(ThingsWanted[i].ingestible)) { RecipeDef recipe = DefDatabase <RecipeDef> .AllDefsListForReading.Find(rec => rec.ProducedThingDef == thing.def); IngredientCount ingredient = recipe?.ingredients?.Find(ing => ing.filter.Allows(ThingsWanted[i].ingestible)) ?? null; if (ingredient == null) { continue; } amount = ingredient.CountRequiredOfFor(ThingsWanted[i].ingestible, recipe); nutriment = ingredient.GetBaseCount(); ingestibleInfo = ThingsWanted[i]; break; } } } DoUpdate(ingestibleInfo, amount, nutriment); }
static void Postfix(ref List <ThoughtDef> __result, Pawn ingester, Thing foodSource, ThingDef foodDef) { if (__result == null || !__result.Any()) { return; } CompIngredients compIngredients = foodSource.TryGetComp <CompIngredients>(); if (compIngredients != null) { if (foodDef.defName == "avOddMeatPack" && compIngredients.ingredients.Count > 0) { __result.Remove(foodDef.ingestible.specialThoughtDirect); } foreach (var ingredient in (compIngredients.ingredients)) { if (foodDef.ingestible.tasteThought == ingredient.ingestible.tasteThought) { if (ingredient.ingestible.specialThoughtAsIngredient != null) { __result.Remove(ingredient.ingestible.specialThoughtAsIngredient); } if (ingredient.ingestible.specialThoughtDirect != null) { if (!__result.Contains(ingredient.ingestible.specialThoughtDirect)) { __result.Add(ingredient.ingestible.specialThoughtDirect); } } } } } }
public static IEnumerable <Thing> MakeRecipeProducts(RecipeDef recipeDef, Pawn worker, List <Thing> ingredients, Thing dominantIngredient, IBillGiver billGiver) { float efficiency = (recipeDef.efficiencyStat != null) ? worker.GetStatValue(recipeDef.efficiencyStat) : 1f; if (recipeDef.workTableEfficiencyStat != null) { Building_WorkTable building_WorkTable = billGiver as Building_WorkTable; if (building_WorkTable != null) { efficiency *= building_WorkTable.GetStatValue(recipeDef.workTableEfficiencyStat); } } if (recipeDef.products != null) { for (int k = 0; k < recipeDef.products.Count; k++) { ThingDefCountClass thingDefCountClass = recipeDef.products[k]; Thing thing = ThingMaker.MakeThing(stuff: (!thingDefCountClass.thingDef.MadeFromStuff) ? null : dominantIngredient.def, def: thingDefCountClass.thingDef); thing.stackCount = Mathf.CeilToInt((float)thingDefCountClass.count * efficiency); if (dominantIngredient != null) { thing.SetColor(dominantIngredient.DrawColor, reportFailure: false); } CompIngredients compIngredients = thing.TryGetComp <CompIngredients>(); if (compIngredients != null) { for (int l = 0; l < ingredients.Count; l++) { compIngredients.RegisterIngredient(ingredients[l].def); } } CompFoodPoisonable compFoodPoisonable = thing.TryGetComp <CompFoodPoisonable>(); if (compFoodPoisonable != null) { if (Rand.Chance(worker.GetRoom()?.GetStat(RoomStatDefOf.FoodPoisonChance) ?? RoomStatDefOf.FoodPoisonChance.roomlessScore)) { compFoodPoisonable.SetPoisoned(FoodPoisonCause.FilthyKitchen); } else if (Rand.Chance(worker.GetStatValue(StatDefOf.FoodPoisonChance))) { compFoodPoisonable.SetPoisoned(FoodPoisonCause.IncompetentCook); } } yield return(PostProcessProduct(thing, recipeDef, worker)); } } if (recipeDef.specialProducts == null) { yield break; } for (int k = 0; k < recipeDef.specialProducts.Count; k++) { for (int i = 0; i < ingredients.Count; i++) { Thing thing2 = ingredients[i]; switch (recipeDef.specialProducts[k]) { case SpecialProductType.Butchery: foreach (Thing item in thing2.ButcherProducts(worker, efficiency)) { yield return(PostProcessProduct(item, recipeDef, worker)); } break; case SpecialProductType.Smelted: foreach (Thing item2 in thing2.SmeltProducts(efficiency)) { yield return(PostProcessProduct(item2, recipeDef, worker)); } break; } } } }
public static void GenerateIngredients(Thing meal, Pawn eater) { CompIngredients compIngredients = meal.TryGetComp <CompIngredients>(); if (compIngredients != null) { // Stage 1: Generate random ingredients according to recipe // 1.1: Find recipe Func <RecipeDef, bool> validator = delegate(RecipeDef r) { bool directMatch = r.ProducedThingDef == meal.def; // Add compatibility for VCE Soups and Stews, whose original recipes only makes uncooked versions bool indirectMatch = (r.ProducedThingDef != null) ? (r.ProducedThingDef.ToString().Replace("Uncooked", "Cooked") == meal.def.ToString()) : false; return(directMatch || indirectMatch); }; RecipeDef mealRecipe = DefDatabase <RecipeDef> .AllDefsListForReading.First(validator); if (mealRecipe != null) { // 1.2: Generate ingredients from recipe List <string> ingredientCategoryOptions = new List <string>(); List <ThingDef> ingredientThingDefs = new List <ThingDef>(); // 1.3: Find ingredient categories and/or fixed thingDefs foreach (IngredientCount currIngredientCount in mealRecipe.ingredients) { if (currIngredientCount.filter.categories != null) { // Limit to 3 instances of an ingredient category int ingredientCatInstances = Math.Min((int)Math.Ceiling(currIngredientCount.count / 0.5f), 3); for (int i = 0; i < ingredientCatInstances; i++) { // Max limit of one condiment from Vanilla Cooking Expanded if (currIngredientCount.filter.categories.Contains("VCE_Condiments") && ingredientCategoryOptions.Contains("VCE_Condiments")) { continue; } else { ingredientCategoryOptions.Add(currIngredientCount.filter.categories.RandomElement()); } } } if (currIngredientCount.filter.thingDefs != null) { ingredientThingDefs.AddRange(currIngredientCount.filter.thingDefs); } } // 1.4: Generate random ingredient thingDefs based on categories, and add them to the existing list of fixed thingDefs // // By default, we ignore ingredients that are: // - Permanently disallowed by the Computer // - Disallowed specifically by the pawn's food restriction policy // - Humanlike and insect meats // - Fertilized eggs List <ThingDef> allowedIngredients = ThingCategoryDef.Named("FoodRaw").DescendantThingDefs.Where(x => !replimatRestrictions.disallowedIngredients.Contains(x) && eater.foodRestriction.CurrentFoodRestriction.Allows(x) && FoodUtility.GetMeatSourceCategory(x) != MeatSourceCategory.Humanlike && FoodUtility.GetMeatSourceCategory(x) != MeatSourceCategory.Insect && !x.thingCategories.Contains(ThingCategoryDefOf.EggsFertilized) ).ToList(); // Also check allowed condiments if Vanilla Cooking Expanded mod is active if (ModCompatibility.VanillaCookingExpandedIsActive) { allowedIngredients.AddRange(ThingCategoryDef.Named("VCE_Condiments").DescendantThingDefs.Where(x => !replimatRestrictions.disallowedIngredients.Contains(x) && eater.foodRestriction.CurrentFoodRestriction.Allows(x) )); } foreach (string currentIngredientCatOption in ingredientCategoryOptions) { List <ThingDef> ingredients = ThingCategoryDef.Named(currentIngredientCatOption).DescendantThingDefs.Where((ThingDef d) => allowedIngredients.Contains(d)).ToList(); ThingDef ingredient = (ingredients.Count > 0) ? ingredients.RandomElement() : null; // Avoid empty or duplicate ingredients if (ingredient != null && !ingredientThingDefs.Contains(ingredient)) { ingredientThingDefs.Add(ingredient); } } // Stage 2: Ideo replacements Ideo ideo = eater.Ideo; // 2.1 Human cannibalism for meals containing meat if (ideo?.HasHumanMeatEatingRequiredPrecept() == true) { List <ThingDef> existingMeats = ingredientThingDefs.FindAll((ThingDef d) => d.thingCategories.Contains(ThingCategoryDefOf.MeatRaw)); // Replace existing meats with a single instance of human meat if (existingMeats.Count > 0) { ingredientThingDefs = ingredientThingDefs.Except(existingMeats).ToList(); ingredientThingDefs.Add(ThingDefOf.Meat_Human); } } // 2.2 Insect meat loved for meals containing meat if (ideo?.HasPrecept(ReplimatDef.InsectMeatEating_Loved) == true) { List <ThingDef> existingMeats = ingredientThingDefs.FindAll((ThingDef d) => d.thingCategories.Contains(ThingCategoryDefOf.MeatRaw)); // Replace existing meats with a single instance of insect meat if (existingMeats.Count > 0) { ingredientThingDefs = ingredientThingDefs.Except(existingMeats).ToList(); ingredientThingDefs.Add(ReplimatDef.Meat_Megaspider); } } // 2.3 Fungus preferred for meals containing raw plant food if (ideo?.HasPrecept(ReplimatDef.FungusEating_Preferred) == true) { List <ThingDef> existingPlantFoodRaws = ingredientThingDefs.FindAll((ThingDef d) => d.thingCategories.Contains(ThingCategoryDefOf.PlantFoodRaw) || d.ingestible.foodType == FoodTypeFlags.VegetableOrFruit); // todo - fix // Replace existing raw plant food with a single instance of fungus if (existingPlantFoodRaws.Count > 0) { ingredientThingDefs = ingredientThingDefs.Except(existingPlantFoodRaws).ToList(); ingredientThingDefs.Add(ReplimatDef.RawFungus); } } // 2.4 Fungus despised for meals containing raw plant food if (ideo?.HasPrecept(ReplimatDef.FungusEating_Despised) == true) { ingredientThingDefs.Remove(ReplimatDef.RawFungus); } // Stage 3: Assign final ingredients to meal compIngredients.ingredients.AddRange(ingredientThingDefs); } } }
public static IEnumerable <Thing> MakeRecipeProductsInt(RecipeDef recipeDef, IRecipeProductWorker worker, List <Thing> ingredients, Thing dominantIngredient, IBillGiver billGiver) { float efficiency; if (recipeDef.efficiencyStat == null) { efficiency = 1f; } else { efficiency = worker.GetStatValue(recipeDef.efficiencyStat, true); } if (recipeDef.workTableEfficiencyStat != null) { Building_WorkTable building_WorkTable = billGiver as Building_WorkTable; if (building_WorkTable != null) { efficiency *= building_WorkTable.GetStatValue(recipeDef.workTableEfficiencyStat, true); } } if (recipeDef.products != null) { for (int i = 0; i < recipeDef.products.Count; i++) { ThingDefCountClass prod = recipeDef.products[i]; ThingDef stuffDef; if (prod.thingDef.MadeFromStuff) { stuffDef = dominantIngredient.def; } else { stuffDef = null; } Thing product = ThingMaker.MakeThing(prod.thingDef, stuffDef); product.stackCount = Mathf.CeilToInt((float)prod.count * efficiency); if (dominantIngredient != null) { product.SetColor(dominantIngredient.DrawColor, false); } CompIngredients ingredientsComp = product.TryGetComp <CompIngredients>(); if (ingredientsComp != null) { for (int l = 0; l < ingredients.Count; l++) { ingredientsComp.RegisterIngredient(ingredients[l].def); } } CompFoodPoisonable foodPoisonable = product.TryGetComp <CompFoodPoisonable>(); if (foodPoisonable != null) { Room room = worker.GetRoom(RegionType.Set_Passable); float chance = (room == null) ? RoomStatDefOf.FoodPoisonChance.roomlessScore : room.GetStat(RoomStatDefOf.FoodPoisonChance); if (Rand.Chance(chance)) { foodPoisonable.SetPoisoned(FoodPoisonCause.FilthyKitchen); } else { float statValue = worker.GetStatValue(StatDefOf.FoodPoisonChance, true); if (Rand.Chance(statValue)) { foodPoisonable.SetPoisoned(FoodPoisonCause.IncompetentCook); } } } yield return(GenRecipe2.PostProcessProduct(product, recipeDef, worker)); } } if (recipeDef.specialProducts != null) { for (int j = 0; j < recipeDef.specialProducts.Count; j++) { for (int k = 0; k < ingredients.Count; k++) { Thing ing = ingredients[k]; SpecialProductType specialProductType = recipeDef.specialProducts[j]; if (specialProductType != SpecialProductType.Butchery) { if (specialProductType == SpecialProductType.Smelted) { foreach (Thing product2 in ing.SmeltProducts(efficiency)) { yield return(GenRecipe2.PostProcessProduct(product2, recipeDef, worker)); } } } else { foreach (Thing product3 in ButcherProducts(ing, efficiency, worker)) { yield return(GenRecipe2.PostProcessProduct(product3, recipeDef, worker)); } } } } } }
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); }
public static void ClearIngs(CompIngredients ings) { ings.ingredients.Clear(); }
internal static List <ThoughtDef> _ThoughtsFromIngesting(Pawn ingester, Thing t) { ingestThoughts.Clear(); if (ingester.needs == null || ingester.needs.mood == null) { return(ingestThoughts); } ThingDef thingDef = t.def; if (thingDef == ThingDefOf.NutrientPasteDispenser) { thingDef = ThingDefOf.MealNutrientPaste; } if (!ingester.story.traits.HasTrait(TraitDefOf.Ascetic) && thingDef.ingestible.tasteThought != null) { ingestThoughts.Add(thingDef.ingestible.tasteThought); } CompIngredients compIngredients = t.TryGetComp <CompIngredients>(); if (FoodUtility.IsHumanlikeMeat(thingDef) && ingester.RaceProps.Humanlike) { 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++) { ThingDef thingDef2 = compIngredients.ingredients[i]; if (thingDef2.ingestible != null) { if (ingester.RaceProps.Humanlike && FoodUtility.IsHumanlikeMeat(thingDef2)) { ingestThoughts.Add((!ingester.story.traits.HasTrait(TraitDefOf.Cannibal)) ? ThoughtDefOf.AteHumanlikeMeatAsIngredient : ThoughtDefOf.AteHumanlikeMeatAsIngredientCannibal); } else if (thingDef2.ingestible.specialThoughtAsIngredient != null) { ingestThoughts.Add(thingDef2.ingestible.specialThoughtAsIngredient); } } } } else if (thingDef.ingestible.specialThoughtDirect != null) { ingestThoughts.Add(thingDef.ingestible.specialThoughtDirect); } if (t.IsNotFresh()) { ingestThoughts.Add(ThoughtDefOf.AteRottenFood); } List <ThoughtDef> newThoughts = new List <ThoughtDef>(); foreach (var thought in ingestThoughts) { if (DefDatabase <ThoughtDef> .GetNamedSilentFail(thought.defName + "PickyEater") != null) { newThoughts.Add(ThoughtDef.Named(thought.defName + "PickyEater")); } } ingestThoughts.AddRange(newThoughts); return(ingestThoughts); }
public static IEnumerable <Thing> MakeRecipeProducts(RecipeDef recipeDef, Pawn worker, List <Thing> ingredients, Thing dominantIngredient) { float efficiency; if (recipeDef.efficiencyStat == null) { efficiency = 1f; } else { efficiency = worker.GetStatValue(recipeDef.efficiencyStat, true); } if (recipeDef.products != null) { for (int i = 0; i < recipeDef.products.Count; i++) { ThingCountClass prod = recipeDef.products[i]; ThingDef stuffDef; if (prod.thingDef.MadeFromStuff) { stuffDef = dominantIngredient.def; } else { stuffDef = null; } Thing product = ThingMaker.MakeThing(prod.thingDef, stuffDef); product.stackCount = Mathf.CeilToInt((float)prod.count * efficiency); if (dominantIngredient != null) { product.SetColor(dominantIngredient.DrawColor, false); } CompIngredients ingredientsComp = product.TryGetComp <CompIngredients>(); if (ingredientsComp != null) { for (int l = 0; l < ingredients.Count; l++) { ingredientsComp.RegisterIngredient(ingredients[l].def); } } CompFoodPoisonable foodPoisonable = product.TryGetComp <CompFoodPoisonable>(); if (foodPoisonable != null) { float num = worker.GetStatValue(StatDefOf.FoodPoisonChance, true); Room room = worker.GetRoom(RegionType.Set_Passable); if (room != null) { num *= room.GetStat(RoomStatDefOf.FoodPoisonChanceFactor); } if (Rand.Value < num) { foodPoisonable.PoisonPercent = 1f; } } yield return(GenRecipe.PostProcessProduct(product, recipeDef, worker)); } } if (recipeDef.specialProducts != null) { for (int j = 0; j < recipeDef.specialProducts.Count; j++) { for (int k = 0; k < ingredients.Count; k++) { Thing ing = ingredients[k]; SpecialProductType specialProductType = recipeDef.specialProducts[j]; if (specialProductType != SpecialProductType.Butchery) { if (specialProductType == SpecialProductType.Smelted) { foreach (Thing product2 in ing.SmeltProducts(efficiency)) { yield return(GenRecipe.PostProcessProduct(product2, recipeDef, worker)); } } } else { foreach (Thing product3 in ing.ButcherProducts(worker, efficiency)) { yield return(GenRecipe.PostProcessProduct(product3, recipeDef, worker)); } } } } } }