/// <summary>
        /// Generates a list of all Things that can be dropped from a part and its subparts
        /// </summary>
        /// <param name="pawn">Pawn from which to check hediffs</param>
        /// <param name="part">From where to look for hediffs</param>
        /// <param name="pos">Position where to drop natural subparts</param>
        /// <param name="map">Map where to drop natural subparts</param>
        /// <returns>All Things that hediffs from part and childparts can drop, with subparts inserted into the correct parent</returns>
        public static IEnumerable <Thing> MakeThingsFromHediffs(Pawn pawn, BodyPartRecord part, IntVec3 pos, Map map)
        {
            // stop if the part is missing
            if (!pawn.health.hediffSet.GetNotMissingParts().Contains(part))
            {
                yield break;
            }

            /// Things that can be made from all subPart hediffs
            List <Thing> subThings = new List <Thing>();

            foreach (BodyPartRecord subPart in part.GetDirectChildParts())                  // for each subpart
            {
                if (!MedicalRecipesUtility.IsClean(pawn, part))                             // If parent is not clean
                {
                    MedicalRecipesUtility.SpawnNaturalPartIfClean(pawn, subPart, pos, map); // try to make natural parts out of children
                }

                // add each thing coming from the child hediffs
                subThings.AddRange(MakeThingsFromHediffs(pawn, subPart, pos, map));
            }

            // for every thing makeable from hediffs on this part: add subparts if possible then return it
            List <Thing> items = new List <Thing>();

            foreach (Hediff hediff in from x in pawn.health.hediffSet.hediffs
                     where x.Part == part
                     select x)                              // for every hediff on the part
            {
                if (hediff.def.spawnThingOnRemoved != null) // if it spawns an item
                {
                    Thing item = ThingMaker.MakeThing(hediff.def.spawnThingOnRemoved);

                    if (item is ThingWithComps itemWithComps)   // compose if possible
                    {
                        AddSubparts(itemWithComps, subThings);
                    }

                    items.Add(item);
                }
            }

            // merge siblings
            for (int i = items.Count - 1; i >= 0; i--)
            {
                if (items[i] is ThingWithComps)
                {
                    AddSubparts(items[i] as ThingWithComps, items, false);
                }
            }

            // return all
            foreach (Thing item in items.Concat(subThings))
            {
                yield return(item);
            }

            yield break;
        }
        public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List <Thing> ingredients, Bill bill)
        {
            bool flag1 = pawn.health.hediffSet.hediffs.Any((Hediff d) => (d is Hediff_AddedPartModule) && d.Part == part);
            bool flag2 = this.IsViolationOnPawn(pawn, part, Faction.OfPlayer);

            if (billDoer != null)
            {
                if (base.CheckSurgeryFail(billDoer, pawn, ingredients, part, bill))
                {
                    return;
                }
                TaleRecorder.RecordTale(TaleDefOf.DidSurgery, new object[]
                {
                    billDoer,
                    pawn
                });
                MedicalRecipesUtility.SpawnNaturalPartIfClean(pawn, part, billDoer.Position, billDoer.Map);
                MedicalRecipesUtility.SpawnThingsFromHediffs(pawn, part, billDoer.Position, billDoer.Map);
            }

            if (flag1)
            {
                pawn.health.RestorePart(part, null, true);
                Hediff_BodyPartModule hediff_BodyPartModule = (Hediff_BodyPartModule)HediffMaker.MakeHediff(MSE_HediffDefOf.MSE_BodyPartModule, pawn, null);
                hediff_BodyPartModule.Part = part;
                pawn.health.hediffSet.AddDirect(hediff_BodyPartModule, null, null);
            }
            else
            {
                DamageDef surgicalCut      = DamageDefOf.SurgicalCut;
                float     amount           = 99999f;
                float     armorPenetration = 999f;
                pawn.TakeDamage(new DamageInfo(surgicalCut, amount, armorPenetration, -1f, null, part, null, DamageInfo.SourceCategory.ThingOrUnknown, null));
            }

            if (flag2 && pawn.Faction != null && billDoer != null && billDoer.Faction != null)
            {
                Faction          faction1       = pawn.Faction;
                Faction          faction2       = billDoer.Faction;
                int              goodwillChange = -20;
                string           reason         = "GoodwillChangedReason_RemovedBodyPart".Translate(part.LabelShort);
                GlobalTargetInfo?lookTarget     = new GlobalTargetInfo?(pawn);
                faction1.TryAffectGoodwillWith(faction2, goodwillChange, true, true, reason, lookTarget);
            }
        }
        public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List <Thing> ingredients, Bill bill)
        {
            bool flag1 = MedicalRecipesUtility.IsClean(pawn, part);
            bool flag2 = this.IsViolationOnPawn(pawn, part, Faction.OfPlayer);

            if (billDoer != null)
            {
                if (base.CheckSurgeryFail(billDoer, pawn, ingredients, part, bill))
                {
                    return;
                }
                TaleRecorder.RecordTale(TaleDefOf.DidSurgery, new object[]
                {
                    billDoer,
                    pawn
                });
                MedicalRecipesUtility.SpawnNaturalPartIfClean(pawn, part, billDoer.Position, billDoer.Map);
                MedicalRecipesUtility.SpawnThingsFromHediffs(pawn, part, billDoer.Position, billDoer.Map);
            }

            DamageDef surgicalCut      = DamageDefOf.SurgicalCut;
            float     amount           = 99999f;
            float     armorPenetration = 999f;

            pawn.TakeDamage(new DamageInfo(surgicalCut, amount, armorPenetration, -1f, null, part, null, DamageInfo.SourceCategory.ThingOrUnknown, null));

            if (flag1)
            {
                if (pawn.Dead)
                {
                    ThoughtUtility.GiveThoughtsForPawnExecuted(pawn, PawnExecutionKind.OrganHarvesting);
                }
                ThoughtUtility.GiveThoughtsForPawnOrganHarvested(pawn);
            }

            if (flag2 && pawn.Faction != null && billDoer != null && billDoer.Faction != null)
            {
                Faction          faction        = pawn.Faction;
                Faction          faction2       = billDoer.Faction;
                int              goodwillChange = -15;
                string           reason         = "GoodwillChangedReason_RemovedBodyPart".Translate(part.LabelShort);
                GlobalTargetInfo?lookTarget     = new GlobalTargetInfo?(pawn);
                faction.TryAffectGoodwillWith(faction2, goodwillChange, true, true, reason, lookTarget);
            }
        }