public static bool TryGetParts(Corpse corpse, RecipeInfo recipeInfo, BodyPartRecord part, float skillChance, ref List <Thing> result) { if (IsCleanAndDroppable(corpse.InnerPawn, part)) { CompRottable rot = corpse.TryGetComp <CompRottable>(); if ((rot == null ? corpse.Age <= recipeInfo.CorpseValidAge : rot.RotProgress <= recipeInfo.CorpseValidAge) && Rand.Chance(Math.Min(skillChance, recipeInfo.NaturalChance))) { result.Add(ThingMaker.MakeThing(part.def.spawnThingOnRemoved)); } return(true); } if (corpse.InnerPawn.health.hediffSet.hediffs.Any(x => x.Part == part && x.def.spawnThingOnRemoved != null && (x is Hediff_Implant || x is Hediff_AddedPart))) { result.AddRange(from hediff in corpse.InnerPawn.health.hediffSet.hediffs where hediff.Part == part && hediff.def.spawnThingOnRemoved != null && (hediff is Hediff_Implant || hediff is Hediff_AddedPart) && Rand.Chance(Math.Min(skillChance, recipeInfo.BionicChance)) select ThingMaker.MakeThing(hediff.def.spawnThingOnRemoved)); return(true); } return(false); }
public static bool TryGetParts(Corpse corpse, RecipeInfo recipeInfo, BodyPartRecord part, float skillChance, ref List <Thing> result, ref List <BodyPartRecord> damagedParts) { if (IsCleanAndDroppable(corpse.InnerPawn, part)) { damagedParts.Add(part); CompRottable rot = corpse.TryGetComp <CompRottable>(); if (rot == null ? corpse.Age <= recipeInfo.CorpseValidAge : rot.RotProgress + (corpse.Age - rot.RotProgress) * recipeInfo.FrozenDecay <= recipeInfo.CorpseValidAge) { if (Rand.Chance(Math.Min(skillChance, recipeInfo.NaturalChance))) { result.Add(ThingMaker.MakeThing(part.def.spawnThingOnRemoved)); } return(true); } } List <Hediff> bion = corpse.InnerPawn.health.hediffSet.hediffs.Where(x => part.Equals(x.Part) && x.def.spawnThingOnRemoved != null && (x is Hediff_Implant || x is Hediff_AddedPart)).ToList(); if (bion.Count > 0) { result.AddRange(bion.Where(x => Rand.Chance(Math.Min(skillChance, recipeInfo.BionicChance))) .Select(x => ThingMaker.MakeThing(x.def.spawnThingOnRemoved))); damagedParts.Add(part); return(true); } return(false); }
public static IEnumerable <Thing> TraverseBody(RecipeInfo recipeInfo, Corpse corpse, float skillChance) { BodyPartRecord core = corpse.InnerPawn.RaceProps.body.corePart; List <BodyPartRecord> queue = new List <BodyPartRecord> { core }; HediffSet hediffSet = corpse.InnerPawn.health.hediffSet; List <Thing> results = new List <Thing>(); List <BodyPartRecord> damagedParts = new List <BodyPartRecord>(); while (queue.Count > 0) { BodyPartRecord part = queue.First(); queue.Remove(part); //Drop parts and bionics that are higher on the body tree. if (TryGetParts(corpse, recipeInfo, part, skillChance, ref results, ref damagedParts) && core != part) { continue; } queue.AddRange(part.parts.Where(x => !hediffSet.PartIsMissing(x))); } if (results.Count > recipeInfo.PartNumber) { Random random = new Random(); return(results.OrderBy(i => random.Next()).Take(recipeInfo.PartNumber)); } foreach (BodyPartRecord part in damagedParts) { DamageHarvested(corpse.InnerPawn, part); } return(results); }
public static IEnumerable <Thing> TraverseBody(RecipeInfo recipeInfo, Corpse corpse, float skillChance) { BodyPartRecord core = corpse.InnerPawn.RaceProps.body.corePart; List <BodyPartRecord> queue = new List <BodyPartRecord> { core }; HediffSet hediffSet = corpse.InnerPawn.health.hediffSet; List <Thing> results = new List <Thing>(); while (queue.Count > 0) { BodyPartRecord part = queue.First(); queue.Remove(part); //Drop parts and bionics that are higher onthe body tree. if (TryGetParts(corpse, recipeInfo, part, skillChance, ref results) && core != part) { continue; } queue.AddRange(part.parts.Where(x => !hediffSet.PartIsMissing(x))); } return(results); }
public static void Postfix(ref IEnumerable <Thing> __result, RecipeDef recipeDef, Pawn worker, List <Thing> ingredients) { if (Constants.HumanRecipeDefs.Contains(recipeDef)) { RecipeInfo recipeSettings = null; float skillChance = worker.GetStatValue(StatDefOf.MedicalSurgerySuccessChance); if (recipeDef.Equals(AutopsyRecipeDefs.AutopsyBasic)) { recipeSettings = new RecipeInfo( Mod.BasicAutopsyOrganMaxChance.Value, Mod.BasicAutopsyCorpseAge.Value * 2500, Mod.BasicAutopsyBionicMaxChance.Value, Mod.BasicAutopsyMaxNumberOfOrgans.Value, Mod.BasicAutopsyFrozenDecay.Value); skillChance *= Mod.BasicAutopsyMedicalSkillScaling.Value; } else if (recipeDef.Equals(AutopsyRecipeDefs.AutopsyAdvanced)) { recipeSettings = new RecipeInfo( Mod.AdvancedAutopsyOrganMaxChance.Value, Mod.AdvancedAutopsyCorpseAge.Value * 2500, Mod.AdvancedAutopsyBionicMaxChance.Value, Mod.AdvancedAutopsyMaxNumberOfOrgans.Value, Mod.AdvancedAutopsyFrozenDecay.Value); skillChance *= Mod.AdvancedAutopsyMedicalSkillScaling.Value; } else if (recipeDef.Equals(AutopsyRecipeDefs.AutopsyGlitterworld)) { recipeSettings = new RecipeInfo( Mod.GlitterAutopsyOrganMaxChance.Value, Mod.GlitterAutopsyCorpseAge.Value * 2500, Mod.GlitterAutopsyBionicMaxChance.Value, Mod.GlitterAutopsyMaxNumberOfOrgans.Value, Mod.GlitterAutopsyFrozenDecay.Value); skillChance *= Mod.GlitterAutopsyMedicalSkillScaling.Value; } else if (recipeDef.Equals(AutopsyRecipeDefs.AutopsyAnimal)) { recipeSettings = new RecipeInfo( 0f, 0, Mod.AnimalAutopsyBionicMaxChance.Value, Mod.AnimalAutopsyMaxNumberOfOrgans.Value, 0); skillChance *= Mod.AnimalAutopsyMedicalSkillScaling.Value; } if (recipeSettings == null) { return; } List <Thing> result = __result as List <Thing> ?? __result.ToList(); foreach (Corpse corpse in ingredients.OfType <Corpse>()) { result.AddRange( NewMedicalRecipesUtility.TraverseBody(recipeSettings, corpse, skillChance)); } if (recipeDef.Equals(AutopsyRecipeDefs.AutopsyBasic)) { worker.needs?.mood?.thoughts?.memories?.TryGainMemory(AutopsyRecipeDefs.HarvestedHumanlikeCorpse, null); foreach (Pawn pawn in worker.Map.mapPawns.SpawnedPawnsInFaction(worker.Faction)) { if (pawn != worker) { pawn.needs?.mood?.thoughts?.memories?.TryGainMemory( AutopsyRecipeDefs.KnowHarvestedHumanlikeCorpse, null); } } } __result = result; } }
public static void Postfix(ref IEnumerable <Thing> __result, RecipeDef recipeDef, Pawn worker, List <Thing> ingredients) { RecipeInfo recipeSettings = null; float skillChance = worker.GetStatValue(StatDefOf.MedicalSurgerySuccessChance); switch (recipeDef.defName) { case Constants.AutopsyBasic: recipeSettings = new RecipeInfo( Mod.BasicAutopsyOrganMaxChance.Value, Mod.BasicAutopsyCorpseAge.Value * 2500, Mod.BasicAutopsyBionicMaxChance.Value, Mod.BasicAutopsyMaxNumberOfOrgans.Value, Mod.BasicAutopsyFrozenDecay.Value); skillChance *= Mod.BasicAutopsyMedicalSkillScaling.Value; break; case Constants.AutopsyAdvanced: recipeSettings = new RecipeInfo( Mod.AdvancedAutopsyOrganMaxChance.Value, Mod.AdvancedAutopsyCorpseAge.Value * 2500, Mod.AdvancedAutopsyBionicMaxChance.Value, Mod.AdvancedAutopsyMaxNumberOfOrgans.Value, Mod.AdvancedAutopsyFrozenDecay.Value); skillChance *= Mod.AdvancedAutopsyMedicalSkillScaling.Value; break; case Constants.AutopsyGlitterworld: recipeSettings = new RecipeInfo( Mod.GlitterAutopsyOrganMaxChance.Value, Mod.GlitterAutopsyCorpseAge.Value * 2500, Mod.GlitterAutopsyBionicMaxChance.Value, Mod.GlitterAutopsyMaxNumberOfOrgans.Value, Mod.GlitterAutopsyFrozenDecay.Value); skillChance *= Mod.GlitterAutopsyMedicalSkillScaling.Value; break; case Constants.AutopsyAnimal: recipeSettings = new RecipeInfo( 0f, 0, Mod.AnimalAutopsyBionicMaxChance.Value, Mod.AnimalAutopsyMaxNumberOfOrgans.Value, 0); skillChance *= Mod.AnimalAutopsyMedicalSkillScaling.Value; break; } if (recipeSettings == null) { return; } List <Thing> result = __result as List <Thing> ?? __result.ToList(); foreach (Corpse corpse in ingredients.OfType <Corpse>()) { result.AddRange( NewMedicaRecipesUtility.TraverseBody(recipeSettings, corpse, skillChance)); } __result = result; }