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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #5
0
        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;
            }
        }
Exemple #6
0
        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;
        }