public override void PawnDied(Corpse corpse)
        {
            Faction newFaction = corpse.InnerPawn.Faction;

            if (corpse.def.defName == "Corpse_Thermite")
            {
                PawnGenerationRequest request = new PawnGenerationRequest(PawnKindDef.Named("Worm"), newFaction, PawnGenerationContext.NonPlayer, -1, false, false, false, false, true, false, 1f, false, true, true, false, false);
                Pawn pawn  = PawnGenerator.GeneratePawn(request);
                Pawn pawn2 = PawnGenerator.GeneratePawn(request);
                Pawn pawn3 = PawnGenerator.GeneratePawn(request);
                PawnUtility.TrySpawnHatchedOrBornPawn(pawn, corpse.InnerPawn);
                PawnUtility.TrySpawnHatchedOrBornPawn(pawn2, corpse.InnerPawn);
                PawnUtility.TrySpawnHatchedOrBornPawn(pawn3, corpse.InnerPawn);
            }
        }
示例#2
0
        public static void DoBirthSpawn(Pawn mother, Pawn father)
        {
            int num = (mother.RaceProps.litterSizeCurve == null) ? 1 : Mathf.RoundToInt(Rand.ByCurve(mother.RaceProps.litterSizeCurve, 300));

            if (num < 1)
            {
                num = 1;
            }
            PawnGenerationRequest request = new PawnGenerationRequest(mother.kindDef, mother.Faction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, false, false, false, false, null, null, null, null, null, null, null);
            Pawn pawn = null;

            for (int i = 0; i < num; i++)
            {
                pawn = PawnGenerator.GeneratePawn(request);
                if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, mother))
                {
                    if (pawn.playerSettings != null && mother.playerSettings != null)
                    {
                        pawn.playerSettings.AreaRestriction = mother.playerSettings.AreaRestriction;
                    }
                    if (pawn.RaceProps.IsFlesh)
                    {
                        pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, mother);
                        if (father != null)
                        {
                            pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
                        }
                    }
                }
                else
                {
                    Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                }
                TaleRecorder.RecordTale(TaleDefOf.GaveBirth, mother, pawn);
            }
            if (mother.Spawned)
            {
                FilthMaker.MakeFilth(mother.Position, mother.Map, ThingDefOf.FilthAmnioticFluid, mother.LabelIndefinite(), 5);
                if (mother.caller != null)
                {
                    mother.caller.DoCall();
                }
                if (pawn.caller != null)
                {
                    pawn.caller.DoCall();
                }
            }
        }
示例#3
0
        // Token: 0x060028F1 RID: 10481 RVA: 0x00136C04 File Offset: 0x00135004
        public void Hatch()
        {
            try
            {
                PawnKindDef hatchKindDef = Rand.Chance(royalProgress) && !QueenPresent && !XenomorphUtil.HivelikesPresent(MyMap) && !RoyalPresent ? XenomorphDefOf.RRY_Xenomorph_RoyaleHugger : this.Props.hatcherPawn;
#if DEBUG
                //    Log.Message(string.Format("hatchKindDef: {0}", hatchKindDef));
#endif
                PawnGenerationRequest request = new PawnGenerationRequest(hatchKindDef, this.hatcheeFaction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, false, false, false, false, null, null, null, null, null, null, null, null);
                for (int i = 0; i < this.parent.stackCount; i++)
                {
                    Pawn pawn = PawnGenerator.GeneratePawn(request);
                    if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, this.parent))
                    {
                        if (pawn != null)
                        {
                            if (this.hatcheeParent != null)
                            {
                                if (pawn.playerSettings != null && this.hatcheeParent.playerSettings != null && this.hatcheeParent.Faction == this.hatcheeFaction)
                                {
                                    pawn.playerSettings.AreaRestriction = this.hatcheeParent.playerSettings.AreaRestriction;
                                }
                                if (pawn.RaceProps.IsFlesh)
                                {
                                    pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, this.hatcheeParent);
                                }
                            }
                            if (this.otherParent != null && (this.hatcheeParent == null || this.hatcheeParent.gender != this.otherParent.gender) && pawn.RaceProps.IsFlesh)
                            {
                                pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, this.otherParent);
                            }
                        }
                        if (this.parent.Spawned)
                        {
                            FilthMaker.MakeFilth(MyPos, MyMap, ThingDefOf.Filth_AmnioticFluid, 1);
                        }
                    }
                    else
                    {
                        Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                    }
                }
            }
            finally
            {
                this.parent.Destroy(DestroyMode.Vanish);
            }
        }
        public void Hatch()
        {
            try
            {
                PawnGenerationRequest request = new PawnGenerationRequest(Props.hatcherPawn, hatcheeFaction, PawnGenerationContext.NonPlayer, -1, forceGenerateNewPawn: false, newborn: true);
                int numToHatch = Props.numToHatch.RandomInRange;


                for (int i = 0; i < numToHatch; i++)
                {
                    Pawn pawn = PawnGenerator.GeneratePawn(request);
                    if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, parent))
                    {
                        if (pawn != null)
                        {
                            if (hatcheeParent != null)
                            {
                                if (pawn.playerSettings != null && hatcheeParent.playerSettings != null && hatcheeParent.Faction == hatcheeFaction)
                                {
                                    pawn.playerSettings.AreaRestriction = hatcheeParent.playerSettings.AreaRestriction;
                                }
                                if (pawn.RaceProps.IsFlesh)
                                {
                                    pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, hatcheeParent);
                                }
                            }
                            if (otherParent != null && (hatcheeParent == null || hatcheeParent.gender != otherParent.gender) && pawn.RaceProps.IsFlesh)
                            {
                                pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, otherParent);
                            }
                        }
                        if (parent.Spawned)
                        {
                            FilthMaker.TryMakeFilth(parent.Position, parent.Map, ThingDefOf.Filth_AmnioticFluid);
                        }
                    }
                    else
                    {
                        Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                    }
                }
            }
            finally
            {
                parent.Destroy();
            }
        }
示例#5
0
        public void HatchAvali()
        {
            PawnGenerationRequest request = new PawnGenerationRequest(Props.hatcherPawn, hatcheeFaction, PawnGenerationContext.PlayerStarter, -1, false, true, false, false, true, false, 0, false, true, true, false, false, false, false, null, null, null, null, null, null, null);

            for (int i = 0; i < parent.stackCount; i++)
            {
                Pawn pawn = PawnGenerator.GeneratePawn(request);
                if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, parent))
                {
                    if (pawn != null)
                    {
                        pawn.story.childhood = BackstoryDatabase.allBackstories["RimworldChildAvali"];
                        pawn.story.adulthood = BackstoryDatabase.allBackstories["RimworldAdultAvali"];
                        pawn.health.AddHediff(HediffDefOf.AvaliAgeTracker);

                        if (hatcheeParent != null)
                        {
                            if (pawn.playerSettings != null && hatcheeParent.playerSettings != null && hatcheeParent.Faction == hatcheeFaction)
                            {
                                pawn.playerSettings.AreaRestriction = hatcheeParent.playerSettings.AreaRestriction;
                            }
                            if (pawn.RaceProps.IsFlesh)
                            {
                                pawn.relations.AddDirectRelation(RimWorld.PawnRelationDefOf.Parent, hatcheeParent);
                            }
                        }
                        if (otherParent != null && (hatcheeParent == null || hatcheeParent.gender != otherParent.gender) && pawn.RaceProps.IsFlesh)
                        {
                            pawn.relations.AddDirectRelation(RimWorld.PawnRelationDefOf.Parent, otherParent);
                        }

                        Thought_Memory newThought = (Thought_Memory)ThoughtMaker.MakeThought(ThoughtDefOf.AvaliHatched);
                        pawn.needs.mood.thoughts.memories.TryGainMemory(newThought);
                    }
                    if (parent.Spawned)
                    {
                        FilthMaker.MakeFilth(parent.Position, parent.Map, RimWorld.ThingDefOf.Filth_AmnioticFluid, 5);
                    }
                }
                else
                {
                    Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                }
            }
            parent.Destroy(DestroyMode.Vanish);
        }
 // Token: 0x060028F1 RID: 10481 RVA: 0x00136C04 File Offset: 0x00135004
 public void Hatch()
 {
     try
     {
         PawnGenerationRequest request = new PawnGenerationRequest(this.Props.hatcherPawn, this.hatcheeFaction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, false, false, false, false, null, null, null, null, null, null, null, null);
         for (int i = 0; i < this.parent.stackCount; i++)
         {
             Pawn pawn = PawnGenerator.GeneratePawn(request);
             if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, this.parent))
             {
                 if (pawn != null)
                 {
                     if (this.hatcheeParent != null)
                     {
                         if (pawn.playerSettings != null && this.hatcheeParent.playerSettings != null && this.hatcheeParent.Faction == this.hatcheeFaction)
                         {
                             pawn.playerSettings.AreaRestriction = this.hatcheeParent.playerSettings.AreaRestriction;
                         }
                         if (pawn.RaceProps.IsFlesh)
                         {
                             pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, this.hatcheeParent);
                         }
                     }
                     if (this.otherParent != null && (this.hatcheeParent == null || this.hatcheeParent.gender != this.otherParent.gender) && pawn.RaceProps.IsFlesh)
                     {
                         pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, this.otherParent);
                     }
                 }
                 if (this.parent.Spawned)
                 {
                     FilthMaker.MakeFilth(this.parent.Position, this.parent.Map, ThingDefOf.Filth_AmnioticFluid, 1);
                 }
             }
             else
             {
                 Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
             }
         }
     }
     finally
     {
         this.parent.Destroy(DestroyMode.Vanish);
     }
 }
示例#7
0
        public void Hatch()
        {
            try
            {
                PawnKindDef hatcherPawn = DefDatabase <PawnKindDef> .GetNamed("Ant_AntiniumQueen");

                FactionDef queenFactionDef = DefDatabase <FactionDef> .GetNamed("Ant_QueenFaction");

                Faction queenFaction = (from fac in Find.FactionManager.AllFactions where fac.def == queenFactionDef select fac).First();

                //PawnGenerationRequest request = new PawnGenerationRequest(hatcherPawn, queenFaction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, false, false, 1f, false, true, true, false, false, false, false, null, null, null, null, null, Gender.Female, null, null);

                PawnGenerationRequest request = new PawnGenerationRequest(hatcherPawn, queenFaction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, false, false, 1f, false, true, true, true, false, false, false, false, 0f, null, 1f, null, null, null, null, null, null, null, Gender.Female, null, null, null, null);

                Pawn pawn = PawnGenerator.GeneratePawn(request);
                if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, this))
                {
                    if (pawn != null)
                    {
                        pawn.SetFaction(Faction.OfPlayer);

                        TraitDef queenTrait = DefDatabase <TraitDef> .GetNamed("Ant_HiveQueenTrait");

                        List <Trait> traits = new List <Trait> {
                            new Trait(queenTrait)
                        };
                        pawn.story.traits.allTraits = traits;

                        pawn.health.AddHediff(AntHQDefOf.Ant_RoyalLarvaHediff);
                        Find.LetterStack.ReceiveLetter("LetterLabelRoyalLarva".Translate(pawn), "LetterRoyalLarva".Translate(pawn), LetterDefOf.PositiveEvent);

                        FilthMaker.TryMakeFilth(this.Position, this.Map, ThingDefOf.Filth_AmnioticFluid, 1);
                    }
                }
                else
                {
                    Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                }
            }
            finally
            {
                this.Destroy(DestroyMode.Vanish);
            }
        }
示例#8
0
        public override void Notify_PawnDied()
        {
            //base.Notify_PawnDied();
            float severityToTurn = Props.severityToTurn;

            Map map = this.parent.pawn.Corpse.Map;

            if (map != null && this.parent.Severity > severityToTurn)
            {
                Gender  oldGender = this.parent.pawn.gender;
                Faction faction   = null;
                if (Props.isHostile)
                {
                    faction = Find.FactionManager.FirstFactionOfDef(FactionDefOf.AncientsHostile);
                }
                int numToSpawn = Rand.RangeInclusive(Props.numberOfSpawn[0], Props.numberOfSpawn[1]);
                for (int i = 0; i < numToSpawn; i++)
                {
                    PawnGenerationRequest request = new PawnGenerationRequest(PawnKindDef.Named(Props.thingToTurnTo), faction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, false, false);
                    Pawn pawn = PawnGenerator.GeneratePawn(request);
                    PawnUtility.TrySpawnHatchedOrBornPawn(pawn, this.parent.pawn.Corpse);
                    if (Props.keepGender)
                    {
                        pawn.gender = oldGender;
                    }
                    if (Props.isHostile)
                    {
                        pawn.mindState.mentalStateHandler.TryStartMentalState(DefDatabase <MentalStateDef> .GetNamed("ManhunterPermanent", true), null, true, false, null, false);
                    }
                }

                for (int i = 0; i < 20; i++)
                {
                    IntVec3 c;
                    CellFinder.TryFindRandomReachableCellNear(this.parent.pawn.Corpse.Position, map, 2, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), null, null, out c);

                    FilthMaker.TryMakeFilth(c, this.parent.pawn.Corpse.Map, ThingDefOf.Filth_Blood);
                }


                SoundDefOf.Hive_Spawn.PlayOneShot(new TargetInfo(this.parent.pawn.Corpse.Position, map, false));
                this.parent.pawn.Corpse.Destroy();
            }
        }
        public override void CompTick()
        {
            var faction = this.parent.Faction ?? Faction.OfPlayer;

            try
            {
                var request = new PawnGenerationRequest(this.Props.hatcherPawn, faction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, true, false, false, false, false, 0f, null, 1f, null, null, null, null, null, null, null, null, null, null, null, null);
                for (int i = 0; i < this.parent.stackCount; i++)
                {
                    var pawn = PawnGenerator.GeneratePawn(request);
                    if (!PawnUtility.TrySpawnHatchedOrBornPawn(pawn, this.parent))
                    {
                        Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                    }
                }
            }
            finally
            {
                this.parent.Destroy(DestroyMode.Vanish);
            }
        }
示例#10
0
        private void BestialBirth(Pawn baby, List <Pawn> siblings)
        {
            Pawn mother = pawn; Pawn father = Utility.GetFather(baby, pawn);

            //backup melanin, LastName for when baby reset by other mod on spawn/backstorychange
            //var skin_whiteness = baby.story.melanin;
            //var last_name = baby.story.birthLastName;

            PawnUtility.TrySpawnHatchedOrBornPawn(baby, mother);

            Need_Sex sex_need = mother.needs?.TryGetNeed <Need_Sex>();

            if (mother.Faction != null && !(mother.Faction?.IsPlayer ?? false) && sex_need != null)
            {
                sex_need.CurLevel = 1.0f;
            }
            if (mother.Faction != null)
            {
                if (mother.Faction != baby.Faction)
                {
                    baby.SetFaction(mother.Faction);
                }
            }


            foreach (Pawn sibling in siblings)
            {
                baby.relations.AddDirectRelation(PawnRelationDefOf.Sibling, sibling);
            }
            siblings.Add(baby);
            train(baby, mother, father);

            PostBirth(mother, father, baby);

            //restore melanin, LastName for when baby reset by other mod on spawn/backstorychange
            //baby.story.melanin = skin_whiteness;
            //baby.story.birthLastName = last_name;
        }
示例#11
0
        private static void CountdownEnded()
        {
            List <Building> list           = ArchotechUtility.ShipBuildingsAttachedTo(ArchotechCountdown.shipRoot).ToList <Building>();
            StringBuilder   stringBuilder  = new StringBuilder();
            Pawn            theFutureTamer = null;

            foreach (Pawn current in PawnsFinder.AllMaps_FreeColonistsSpawned)
            {
                stringBuilder.AppendLine("   " + current.LabelCap);
                theFutureTamer = current;
            }

            foreach (Building current in list)
            {
                if (current.def.defName == "GR_ArchotechPlatform")
                {
                    Map     mapToPlaceAt      = current.Map;
                    IntVec3 positionToPlaceAt = current.Position;
                    current.Destroy(DestroyMode.Vanish);
                    Building new_Platform = (Building)ThingMaker.MakeThing(DefDatabase <ThingDef> .GetNamed("GR_SpentArchotechPlatform", true));
                    new_Platform.SetFaction(Faction.OfPlayer);
                    GenSpawn.Spawn(new_Platform, positionToPlaceAt, mapToPlaceAt);

                    PawnGenerationRequest request = new PawnGenerationRequest(PawnKindDef.Named("GR_ArchotechCentipede"), Faction.OfPlayer, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, false, false);
                    Pawn pawn = PawnGenerator.GeneratePawn(request);
                    pawn.training.Train(TrainableDefOf.Obedience, theFutureTamer, true);
                    pawn.training.Train(TrainableDefOf.Release, theFutureTamer, true);


                    PawnUtility.TrySpawnHatchedOrBornPawn(pawn, new_Platform);
                }
            }
            string victoryText = "GR_GameOverArchotech".Translate(stringBuilder.ToString());

            GameVictoryUtility.ShowCredits(victoryText);
        }
示例#12
0
        private static bool on_begin_DoBirthSpawn(ref Pawn mother, ref Pawn father)
        {
            //TODO: Set pregnant hediff to torso
            //--Log.Message("patches_pregnancy::PATCH_Hediff_Pregnant::DoBirthSpawn() called");
            var mother_name = (mother != null) ? mother.NameStringShort : "NULL";
            var father_name = (father != null) ? father.NameStringShort : "NULL";

            if (mother == null)
            {
                Log.Error("Hediff_Pregnant::DoBirthSpawn() - no mother defined");
                return(false);
            }

            if (father == null)
            {
                Log.Warning("Hediff_Pregnant::DoBirthSpawn() - no father defined");
            }
            // get a reference to the hediff we are applying
            Hediff_Pregnant self = (Hediff_Pregnant)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Pregnant"));

            // determine litter size
            int litter_size = (mother.RaceProps.litterSizeCurve == null) ? 1 : Mathf.RoundToInt(Rand.ByCurve(mother.RaceProps.litterSizeCurve, 300));

            if (litter_size < 1)
            {
                litter_size = 1;
            }
            float  skin_whiteness = Rand.Range(0, 1);
            string last_name      = null;

            // send a message about giving birth
            ////--Log.Message("Hediff_Pregnancy::DoBirthSpawn( " + mother_name + ", " + father_name + ", " + chance_successful + " ) - generating baby pawns");
            if (self.Visible && PawnUtility.ShouldSendNotificationAbout(mother))
            {
                Messages.Message("GivingBirth".Translate(new object[] { mother.LabelIndefinite() }).CapitalizeFirst(), mother, MessageTypeDefOf.NeutralEvent);
            }

            ////--Log.Message("Hediff_Pregnancy::DoBirthSpawn( " + mother_name + ", " + father_name + ", " + chance_successful + " ) - creating spawn request");

            List <Pawn> siblings = new List <Pawn>();

            for (int i = 0; i < litter_size; i++)
            {
                Pawn spawn_parent = mother;
                if (father != null && Mod_Settings.pregnancy_use_parent_method && (100 * Rand.Value) > Mod_Settings.pregnancy_weight_parent)
                {
                    spawn_parent = father;
                }
                PawnGenerationRequest request = new PawnGenerationRequest(spawn_parent.kindDef, spawn_parent.Faction, PawnGenerationContext.NonPlayer, spawn_parent.Map.Tile, false, true, false, false, false, false, 1, false, true, true, false, false, false, false, null, null, 0, 0, null, skin_whiteness, last_name);

                ////--Log.Message("Hediff_GenericPregnancy::DoBirthSpawn( " + mother_name + ", " + father_name + ", " + chance_successful + " ) - spawning baby");
                Pawn baby = PawnGenerator.GeneratePawn(request);

                if (PawnUtility.TrySpawnHatchedOrBornPawn(baby, mother))
                {
                    if (baby.playerSettings != null && mother.playerSettings != null)
                    {
                        baby.playerSettings.AreaRestriction = mother.playerSettings.AreaRestriction;
                    }
                    if (baby.RaceProps.IsFlesh)
                    {
                        baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, mother);
                        if (father != null)
                        {
                            baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
                        }

                        foreach (Pawn sibling in siblings)
                        {
                            baby.relations.AddDirectRelation(PawnRelationDefOf.Sibling, sibling);
                        }
                        siblings.Add(baby);

                        //inject RJW_BabyState to the newborn if RimWorldChildren is not active
                        if (!xxx.RimWorldChildrenIsActive && baby.kindDef.race == ThingDefOf.Human && baby.ageTracker.CurLifeStageIndex <= 1 && baby.ageTracker.AgeBiologicalYears < 1 && !baby.Dead)
                        {
                            // Clean out drug randomly generated drug addictions
                            baby.health.hediffSet.Clear();
                            baby.health.AddHediff(HediffDef.Named("RJW_BabyState"), null, null);
                            Hediff_SimpleBaby babystate = (Hediff_SimpleBaby)baby.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_BabyState"));
                            if (babystate != null)
                            {
                                babystate.GrowUpTo(0, true);
                            }
                        }
                    }
                }
                else
                {
                    Find.WorldPawns.PassToWorld(baby, PawnDiscardDecideMode.Discard);
                }
            }

            ////--Log.Message("Hediff_Pregnancy::DoBirthSpawn( " + mother_name + ", " + father_name + ", " + chance_successful + " ) - removing pregnancy");
            mother.health.RemoveHediff(self);

            return(false);
        }
        //Handles the spawning of pawns
        public override void GiveBirth()
        {
            Pawn mother = pawn;

            if (mother == null)
            {
                return;
            }

            if (!babies.NullOrEmpty())
            {
                foreach (Pawn baby in babies)
                {
                    baby.Discard(true);
                }
            }

            Faction spawn_faction = null;

            if (!is_hacked)
            {
                spawn_faction = Faction.OfMechanoids;
            }

            PawnGenerationRequest request = new PawnGenerationRequest(
                kind: PawnKindDef.Named("Mech_Scyther"),
                faction: spawn_faction,
                forceGenerateNewPawn: true,
                newborn: true
                );

            Pawn mech = PawnGenerator.GeneratePawn(request);

            PawnUtility.TrySpawnHatchedOrBornPawn(mech, mother);
            if (!is_hacked)
            {
                LordJob_MechanoidsDefend lordJob = new LordJob_MechanoidsDefend();
                Lord lord = LordMaker.MakeNewLord(mech.Faction, lordJob, mech.Map);
                lord.AddPawn(mech);
            }
            FilthMaker.TryMakeFilth(mech.PositionHeld, mech.MapHeld, mother.RaceProps.BloodDef, mother.LabelIndefinite());

            IEnumerable <BodyPartRecord> source = from x in mother.health.hediffSet.GetNotMissingParts() where
                                                  x.IsInGroup(BodyPartGroupDefOf.Torso) &&
                                                  !x.IsCorePart
                                                  //&& x.groups.Contains(BodyPartGroupDefOf.Torso)
                                                  //&& x.depth == BodyPartDepth.Inside
                                                  //&& x.height == BodyPartHeight.Bottom
                                                  //someday include depth filter
                                                  //so it doesnt cut out external organs (breasts)?
                                                  //vag  is genital part and genital is external
                                                  //anal is internal
                                                  //make sep part of vag?
                                                  //&& x.depth == BodyPartDepth.Inside
                                                  select x;

            if (source.Any())
            {
                foreach (BodyPartRecord part in source)
                {
                    mother.health.DropBloodFilth();
                }
                foreach (BodyPartRecord part in source)
                {
                    Hediff_MissingPart hediff_MissingPart = (Hediff_MissingPart)HediffMaker.MakeHediff(HediffDefOf.MissingBodyPart, mother, part);
                    hediff_MissingPart.lastInjury = HediffDefOf.Cut;
                    hediff_MissingPart.IsFresh    = true;
                    mother.health.AddHediff(hediff_MissingPart);
                }
            }
            mother.health.RemoveHediff(this);
        }
        //
        // Methods
        //
        public void DoBirthSpawn(Pawn mother, Pawn father, float chance_successful = 1.0f)
        {
            if (mother == null)
            {
                Log.Error("No mother defined");
                return;
            }
            if (father == null)
            {
                Log.Warning("No father defined");
            }

            float birthing_quality = mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("GivingBirth")).TryGetComp <HediffComp_TendDuration> ().tendQuality;

            mother.health.AddHediff(HediffDef.Named("PostPregnancy"), null, null);
            mother.health.AddHediff(HediffDef.Named("Lactating"), ChildrenUtility.GetPawnBodyPart(pawn, "Torso"), null);

            int num = (mother.RaceProps.litterSizeCurve == null) ? 1 : Mathf.RoundToInt(Rand.ByCurve(mother.RaceProps.litterSizeCurve, 300));

            if (num < 1)
            {
                num = 1;
            }

            // Make sure the pawn looks like mommy and daddy
            float skin_whiteness = Rand.Range(0, 1);
            // Pool of "genetic traits" the baby can inherit
            List <Trait> traitpool = new List <Trait>();

            if (mother.RaceProps.Humanlike)
            {
                // Add mom's traits to the pool
                foreach (Trait momtrait in mother.story.traits.allTraits)
                {
                    traitpool.Add(momtrait);
                }
                if (father != null)
                {
                    // Add dad's traits to the pool
                    foreach (Trait dadtrait in father.story.traits.allTraits)
                    {
                        traitpool.Add(dadtrait);
                    }
                    // Blend skin colour between mom and dad
                    skin_whiteness = Rand.Range(mother.story.melanin, father.story.melanin);
                }
                else
                {
                    // If dad doesn't exist, just use mom's skin colour
                    skin_whiteness = mother.story.melanin;
                }

                // Clear out any traits that aren't genetic from the list
                if (traitpool.Count > 0)
                {
                    foreach (Trait trait in traitpool.ToArray())
                    {
                        bool is_genetic = false;
                        foreach (TraitDef gentrait in genetic_traits)
                        {
                            if (gentrait.defName == trait.def.defName)
                            {
                                is_genetic = true;
                            }
                        }
                        if (!is_genetic)
                        {
                            traitpool.Remove(trait);
                        }
                    }
                }
            }

            // Todo: Perhaps add a way to pass on the parent's body build
            // Best way to do it might be to represent thin/fat/normal/hulk
            // as a pair of two values, strength and weight
            // For example, if the mother has an average body type, she would
            // have a strength of .5f and a weight of .5f. A fat pawn would have
            // a strength of .5f and a weight of .75f. A thin pawn would have a
            // strength of .25f and a weight of .25f. A hulk pawn would have
            // strength of .75f and weight of .75f
            //List<float> strength_pool = new List<float>();
            //List<float> weight_pool = new List<float>();

            //// Get mother and fathers info here if possible

            //float avg_strength = strength_pool.Average();
            //float avg_weight = weight_pool.Average();

            // Surname passing
            string last_name = null;

            if (mother.RaceProps.Humanlike)
            {
                if (father == null)
                {
                    last_name = NameTriple.FromString(mother.Name.ToStringFull).Last;
                }
                else
                {
                    last_name = NameTriple.FromString(father.Name.ToStringFull).Last;
                }
                //Log.Message ("Debug: Newborn is born to the " + last_name + " family.");
            }

            //PawnGenerationRequest request = new PawnGenerationRequest (mother.kindDef, mother.Faction, PawnGenerationContext.NonPlayer, mother.Map, false, true, false, false, true, false, 1, false, true, true, null, 0, 0, null, skin_whiteness, last_name);
            PawnGenerationRequest request = new PawnGenerationRequest(mother.kindDef, mother.Faction, PawnGenerationContext.NonPlayer, mother.Map.Tile, false, true, false, false, false, false, 1, false, true, true, false, false, null, 0, 0, null, skin_whiteness, last_name);

            Pawn baby = null;

            for (int i = 0; i < num; i++)
            {
                baby = PawnGenerator.GeneratePawn(request);
                if (PawnUtility.TrySpawnHatchedOrBornPawn(baby, mother))
                {
                    if (baby.playerSettings != null && mother.playerSettings != null)
                    {
                        baby.playerSettings.AreaRestriction = mother.playerSettings.AreaRestriction;
                    }
                    if (baby.RaceProps.IsFlesh)
                    {
                        baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, mother);
                        if (father != null)
                        {
                            baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
                        }
                    }

                    // Good until otherwise proven bad
                    bool successful_birth = true;
                    var  disabledBaby     = BackstoryDatabase.allBackstories ["CustomBackstory_NA_Childhood_Disabled"];
                    if (disabledBaby != null)
                    {
                        baby.story.childhood = disabledBaby;
                    }
                    else
                    {
                        Log.Error("Couldn't find the required Backstory: CustomBackstory_NA_Childhood_Disabled!");
                        baby.story.childhood = null;
                    }
                    baby.story.adulthood = null;
                    baby.workSettings.Disable(WorkTypeDefOf.Hunting);                      //hushes up the "has no ranged weapon" alert
                    // remove all traits
                    baby.story.traits.allTraits.Clear();

                    // Add some genetic traits
                    if (traitpool.Count > 0)
                    {
                        for (int j = 0; j != 2; j++)
                        {
                            Trait gentrait = traitpool.RandomElement();
                            if (!baby.story.traits.HasTrait(gentrait.def))
                            {
                                baby.story.traits.GainTrait(gentrait);
                            }
                        }
                    }
                    // Move the baby in front of the mother, rather than on top
                    if (mother.CurrentBed() != null)
                    {
                        baby.Position = baby.Position + new IntVec3(0, 0, 1).RotatedBy(mother.CurrentBed().Rotation);
                    }
                    // else {
                    //	 baby.Position = baby.Position + new IntVec3 (0, 0, 1).RotatedBy (mother.Rotation);
                    // }

                    // The baby died from bad chance of success
                    if (Rand.Value > chance_successful || chance_successful == 0)
                    {
                        successful_birth = false;
                    }

                    // Birth defects via drugs or alcohol
                    if (mother.health.hediffSet.HasHediff(HediffDef.Named("BirthDefectTracker")))
                    {
                        Hediff_BirthDefectTracker tracker = (Hediff_BirthDefectTracker)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("BirthDefectTracker"));
                        // The baby died in utero from chemical affect
                        if (tracker.stillbirth)
                        {
                            successful_birth = false;
                        }
                        // The baby lived! So far, anyways
                        else
                        {
                            // Should the baby get fetal alcohol syndrome?
                            if (tracker.fetal_alcohol)
                            {
                                baby.health.AddHediff(HediffDef.Named("FetalAlcoholSyndrome"));
                            }
                            // If the mother got high while pregnant, crongrats retard
                            // now your baby is addicted to crack
                            if (tracker.drug_addictions.Count > 0)
                            {
                                foreach (HediffDef addiction in tracker.drug_addictions)
                                {
                                    baby.health.AddHediff(addiction, null, null);
                                }
                            }
                        }
                    }

                    // Inbred?
                    if (father != null && mother.relations.FamilyByBlood.Contains <Pawn> (father))
                    {
                        // 50% chance to get a birth defect from inbreeding
                        if (Rand.Range(0, 1) == 1)
                        {
                            GiveRandomBirthDefect(baby);
                            if (baby.health.hediffSet.HasHediff(HediffDef.Named("DefectStillborn")))
                            {
                                successful_birth = false;
                            }
                        }
                    }



                    // The baby was born! Yay!
                    if (successful_birth == true)
                    {
                        // Give father a happy memory if the birth was successful and he's not dead
                        if (father != null && !father.health.Dead)
                        {
                            // The father is happy the baby was born
                            father.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("PartnerGaveBirth"));
                        }

                        // Send a message that the baby was born
                        if (mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("HumanPregnancy")).Visible&& PawnUtility.ShouldSendNotificationAbout(mother))
                        {
                            //Messages.Message ("MessageGaveBirth".Translate (new object[] {mother.LabelIndefinite ()}).CapitalizeFirst (), mother, MessageSound.Benefit);
                            Find.LetterStack.ReceiveLetter("LabelGaveBirth".Translate(new object[] { baby.LabelIndefinite() }), "MessageHumanBirth".Translate(new object[] {
                                mother.LabelIndefinite(),
                                baby.Name.ToStringShort
                            }), LetterDefOf.Good, baby, null);
                        }

                        // Try to give PPD. If not, give "New baby" thought
                        float chance = 0.2f;
                        if (mother.story.traits.HasTrait(TraitDefOf.Psychopath))
                        {
                            chance -= 1;
                        }
                        if (mother.story.traits.HasTrait(TraitDef.Named("Nerves")))
                        {
                            chance -= 0.2f * mother.story.traits.GetTrait(TraitDef.Named("Nerves")).Degree;
                        }
                        else if (mother.story.traits.HasTrait(TraitDef.Named("NaturalMood")))
                        {
                            if (mother.story.traits.GetTrait(TraitDef.Named("NaturalMood")).Degree == 2)
                            {
                                chance -= 1;
                            }
                            if (mother.story.traits.GetTrait(TraitDef.Named("NaturalMood")).Degree == -2)
                            {
                                chance += 0.6f;
                            }
                            // For some reason this is broken

                            /*} else if (mother.story.traits.HasTrait (TraitDef.Named ("Neurotic"))) {
                             * if (mother.story.traits.GetTrait (TraitDef.Named ("Neurotic")).Degree == 1) {
                             *      chance += 0.2f;
                             * } else
                             *      chance += 0.4f;*/
                        }

                        // Because for whatever dumb reason the Math class doesn't have a Clamp method
                        if (chance < 0)
                        {
                            chance = 0;
                        }

                        if (chance > 1)
                        {
                            chance = 1;
                        }
                        Log.Message("Debugging: Chance of PPD is " + chance * 100 + "%");


                        // Try to give PPD
                        if (Rand.Value < chance)
                        {
                            mother.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("PostPartumDepression"), null);
                            bool verybad = false;
                            if (mother.story.traits.HasTrait(TraitDef.Named("NaturalMood")))
                            {
                                if (mother.story.traits.GetTrait(TraitDef.Named("NaturalMood")).Degree == -2)
                                {
                                    verybad = true;
                                }
                            }
                            else if (mother.story.traits.HasTrait(TraitDef.Named("Neurotic")))
                            {
                                if (mother.story.traits.GetTrait(TraitDef.Named("Neurotic")).Degree == 2)
                                {
                                    verybad = true;
                                }
                            }
                            // This pawn gets an exceptionally bad case of PPD
                            if (verybad)
                            {
                                foreach (Thought_Memory thought in mother.needs.mood.thoughts.memories.Memories)
                                {
                                    if (thought.def.defName == "PostPartumDepression")
                                    {
                                        thought.SetForcedStage(thought.CurStageIndex + 1);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // If we didn't get PPD, then the pawn gets a mood buff
                            if (mother.health.hediffSet.HasHediff(HediffDef.Named("GaveBirthFlag")) == false)
                            {
                                mother.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("IGaveBirthFirstTime"));
                            }
                            else
                            {
                                mother.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("IGaveBirth"));
                            }
                        }
                    }
                    else
                    {
                        bool aborted = false;
                        if (chance_successful < 0f)
                        {
                            aborted = true;
                        }
                        if (baby != null)
                        {
                            Miscarry(baby, aborted);
                        }
                    }
                }
                else
                {
                    Find.WorldPawns.PassToWorld(baby, PawnDiscardDecideMode.Discard);
                }
            }
            // Post birth
            if (mother.Spawned)
            {
                // Spawn guck
                FilthMaker.MakeFilth(mother.Position, mother.Map, ThingDefOf.FilthAmnioticFluid, mother.LabelIndefinite(), 5);
                if (mother.caller != null)
                {
                    mother.caller.DoCall();
                }
                if (baby != null)
                {
                    if (baby.caller != null)
                    {
                        baby.caller.DoCall();
                    }
                }

                Log.Message("Birth quality = " + birthing_quality);
                // Possible tearing from pregnancy
                if (birthing_quality < 0.75f)
                {
                    if (birthing_quality < Rand.Value)
                    {
                        // Add a tear from giving birth
                        if (birthing_quality < Rand.Value)
                        {
                            mother.health.AddHediff(HediffDef.Named("PregnancyTearMajor"), ChildrenUtility.GetPawnBodyPart(mother, "Torso"), null);
                        }
                        else
                        {
                            mother.health.AddHediff(HediffDef.Named("PregnancyTear"), ChildrenUtility.GetPawnBodyPart(mother, "Torso"), null);
                        }
                    }
                }
            }
            pawn.health.RemoveHediff(pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("GivingBirth")));
            pawn.health.RemoveHediff(this);
        }
示例#15
0
        //Handles the spawning of pawns and adding relations
        public override void GiveBirth()
        {
            Pawn mother = pawn;

            if (mother == null)
            {
                return;
            }
            try
            {
                //fail if hediff added through debug, since babies not initialized
                if (babies.Count > 9999)
                {
                    Log.Message("RJW humanlike pregnancy birthing pawn count: " + babies.Count);
                }
            }
            catch
            {
                if (father == null)
                {
                    Log.Message("RJW humanlike pregnancy father is null(debug?), setting father to mother");
                    father = mother;
                }

                Initialize(mother, father);
            }
            List <Pawn> siblings = new List <Pawn>();

            foreach (Pawn baby in babies)
            {
                PawnUtility.TrySpawnHatchedOrBornPawn(baby, mother);

                var sex_need = mother.needs.TryGetNeed <Need_Sex>();
                if (mother.Faction != null && !(mother.Faction?.IsPlayer ?? false) && sex_need != null)
                {
                    sex_need.CurLevel = 1.0f;
                }
                if (mother.Faction != null)
                {
                    if (mother.Faction != baby.Faction)
                    {
                        baby.SetFaction(mother.Faction);
                    }
                }
                if (mother.IsPrisonerOfColony)
                {
                    baby.guest.CapturedBy(Faction.OfPlayer);
                }

                baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, mother);
                if (father != null)
                {
                    baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
                }

                foreach (Pawn sibling in siblings)
                {
                    baby.relations.AddDirectRelation(PawnRelationDefOf.Sibling, sibling);
                }
                siblings.Add(baby);

                PostBirth(mother, father, baby);

                mother.health.RemoveHediff(this);
            }
        }
示例#16
0
        public void Hatch()
        {
            if (this.parent.Map != null)
            {
                FilthMaker.TryMakeFilth(this.parent.Position, this.parent.Map, ThingDefOf.Filth_AmnioticFluid, 1);


                for (int i = 0; i < this.parent.stackCount; i++)
                {
                    //Log.Message("Failure rate set to "+ GeneticRim_Settings.failureRate);
                    if (rand.NextDouble() < (1 - (GeneticRim_Settings.failureRate / 100)))
                    {
                        request = new PawnGenerationRequest(this.Props.hatcherPawn, Faction.OfPlayer, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, false, false);
                    }
                    else
                    {
                        request   = new PawnGenerationRequest(PawnKindDef.Named("GR_AberrantFleshbeast"), null, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, false, false);
                        WasMutant = true;
                    }
                    Pawn pawn = PawnGenerator.GeneratePawn(request);
                    if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, this.parent))
                    {
                        if (pawn != null)
                        {
                            if (pawn.Faction == Faction.OfPlayer)
                            {
                                pawn.health.AddHediff(HediffDef.Named("GR_RecentlyHatched"));
                            }

                            if (this.hatcheeParent != null)
                            {
                                if (pawn.playerSettings != null && this.hatcheeParent.playerSettings != null && this.hatcheeParent.Faction == this.hatcheeFaction)
                                {
                                    pawn.playerSettings.AreaRestriction = this.hatcheeParent.playerSettings.AreaRestriction;
                                }
                                if (pawn.RaceProps.IsFlesh)
                                {
                                    pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, this.hatcheeParent);
                                }
                            }
                            if (this.otherParent != null && (this.hatcheeParent == null || this.hatcheeParent.gender != this.otherParent.gender) && pawn.RaceProps.IsFlesh)
                            {
                                pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, this.otherParent);
                            }
                            if (WasMutant)
                            {
                                Messages.Message("GR_ANewCreatureWasBornMutant".Translate(), pawn, MessageTypeDefOf.NegativeEvent);
                            }
                            else
                            {
                                Messages.Message("GR_ANewCreatureWasBorn".Translate(), pawn, MessageTypeDefOf.PositiveEvent);
                            }
                        }
                        if (this.parent.Spawned)
                        {
                            FilthMaker.TryMakeFilth(this.parent.Position, this.parent.Map, ThingDefOf.Filth_AmnioticFluid, 1);
                        }
                    }
                    else
                    {
                        Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                    }
                }
                this.parent.Destroy(DestroyMode.Vanish);
            }
        }
    public static bool Replace_DoBirthSpawn(Pawn mother, Pawn father)
    {
        if (father is null || mother.kindDef == father.kindDef)
        {
            return(true);
        }

        var litterCount = Math.Min(GetLitterCount(mother), GetLitterCount(father));

        List <(PawnKindDef p, List <HybridDef> h)> hybridKinds = null;

        if (
            DogsMateMod.TryGetCompatibleFemales(father.kindDef, out var dict) &&
            dict.TryGetValue(mother.kindDef, out var hybridDefs) &&
            hybridDefs.Count > 0
            )
        {
            hybridKinds = hybridDefs.Select(h => h.children.Where(c => c.IsUsable).Select(a => (a, h)))
                          .SelectMany(x => x).Select(ah => ah.a.pawnKinds.Where(p => p != null).Select(p => (p, ah.h)))
                          .SelectMany(x => x).GroupBy(ph => ph.p)
                          .Select(g => (g.Key, g.Select(ph => ph.h).Where(h => h.IsUsable).ToList())).ToList();
            DogsMateMod.Debug(
                $"father=<{father.kindDef.ToStringSafe()}> " +
                $"mother=<{mother.kindDef.ToStringSafe()}> " +
                $"hybrids=<{hybridKinds.Select(ph => ph.p.label).ToCommaList()}>"
                );
        }

        Pawn child = null;

        for (var childIndex = 0; childIndex < litterCount; ++childIndex)
        {
            PawnKindDef childKind;
            HybridDef   hybridDef = null;
            if (hybridKinds != null)
            {
                hybridKinds.TryGetRandomElement(out var ph);
                ph.h.TryGetRandomElement(out hybridDef);
                childKind = ph.p;
            }
            else if (Rand.Value > 0.5f)
            {
                childKind = mother.kindDef;
            }
            else
            {
                childKind = father.kindDef;
            }

            bool newChildIsGood;
            var  newChild = PawnGenerator.GeneratePawn(new PawnGenerationRequest(
                                                           childKind,
                                                           mother.Faction,
                                                           forceGenerateNewPawn: false,
                                                           newborn: true
                                                           ));
            if (PawnUtility.TrySpawnHatchedOrBornPawn(newChild, mother))
            {
                if (newChild.playerSettings != null && mother.playerSettings != null)
                {
                    newChild.playerSettings.AreaRestriction = mother.playerSettings.AreaRestriction;
                }

                if (newChild.RaceProps.IsFlesh)
                {
                    newChild.relations.AddDirectRelation(PawnRelationDefOf.Parent, mother);
                    newChild.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
                }

                if (hybridDef != null)
                {
                    AddHediffs(newChild, hybridDef.childrenHediffs);
                    switch (newChild.gender)
                    {
                    case Gender.Male:
                        AddHediffs(newChild, hybridDef.maleChildrenHediffs);
                        break;

                    case Gender.Female:
                        AddHediffs(newChild, hybridDef.femaleChildrenHediffs);
                        break;
                    }
                }

                newChildIsGood = true;
            }
            else
            {
                Find.WorldPawns.PassToWorld(newChild, PawnDiscardDecideMode.Discard);
                newChildIsGood = false;
            }

            TaleRecorder.RecordTale(TaleDefOf.GaveBirth, mother, newChild);

            if (newChildIsGood)
            {
                child = newChild;
            }
        }

        if (!mother.Spawned)
        {
            return(false);
        }

        FilthMaker.TryMakeFilth(mother.Position, mother.Map, ThingDefOf.Filth_AmnioticFluid,
                                mother.LabelIndefinite(), 5);
        mother.caller?.DoCall();
        child?.caller?.DoCall();

        return(false);
    }
示例#18
0
        //Handles the spawning of pawns
        public override void GiveBirth()
        {
            Pawn mother = pawn;

            if (mother == null)
            {
                return;
            }
            try
            {
                //fail if hediff added through debug, since babies not initialized
                if (babies.Count > 9999)
                {
                    Log.Message("RJW mech pregnancy birthing pawn count: " + babies.Count);
                }
            }
            catch
            {
                Initialize(mother, father);
            }
            foreach (Pawn baby in babies)
            {
                Faction spawn_faction = null;
                if (!is_hacked)
                {
                    spawn_faction = Faction.OfMechanoids;
                }

                Pawn baby1 = PawnGenerator.GeneratePawn(new PawnGenerationRequest(PawnKindDef.Named("Mech_Scyther"), spawn_faction));
                PawnUtility.TrySpawnHatchedOrBornPawn(baby1, mother);
                if (!is_hacked)
                {
                    LordJob_MechanoidsDefendShip lordJob = new LordJob_MechanoidsDefendShip(mother, baby1.Faction, 50f, mother.Position);
                    Lord lord = LordMaker.MakeNewLord(baby1.Faction, lordJob, baby1.Map);
                    lord.AddPawn(baby1);
                }
                FilthMaker.MakeFilth(baby1.PositionHeld, baby1.MapHeld, mother.RaceProps.BloodDef, mother.LabelIndefinite());
            }

            IEnumerable <BodyPartRecord> source = from x in mother.health.hediffSet.GetNotMissingParts()
                                                  where x.IsInGroup(BodyPartGroupDefOf.Torso) &&
                                                  !x.IsCorePart
                                                  //someday include depth filter
                                                  //so it doesnt cut out external organs (breasts)?
                                                  //vag  is genital part and genital is external
                                                  //anal is internal
                                                  //make sep part of vag?
                                                  //&& x.depth == BodyPartDepth.Inside
                                                  select x;

            if (source.Any())
            {
                foreach (BodyPartRecord part in source)
                {
                    Hediff_MissingPart hediff_MissingPart = (Hediff_MissingPart)HediffMaker.MakeHediff(HediffDefOf.MissingBodyPart, mother, part);
                    hediff_MissingPart.lastInjury = HediffDefOf.Cut;
                    hediff_MissingPart.IsFresh    = true;
                    mother.health.AddHediff(hediff_MissingPart);

                    //idk blood doesnt drop
                    //mother.health.DropBloodFilth();
                    //FilthMaker.MakeFilth(corpse.PositionHeld, corpse.MapHeld, mother.RaceProps.BloodDef, mother.LabelIndefinite());
                }
            }
            mother.health.RemoveHediff(this);
        }
        new public static void DoBirthSpawn(Pawn mother, Pawn father)
        {
            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            int num = (mother.RaceProps.litterSizeCurve == null) ? 1 : Mathf.RoundToInt(Rand.ByCurve(mother.RaceProps.litterSizeCurve));

            if (num < 1)
            {
                num = 1;
            }
            PawnGenerationRequest request = new PawnGenerationRequest(
                kind: father.kindDef,
                faction: father.Faction,
                forceGenerateNewPawn: true,
                newborn: true,
                canGeneratePawnRelations: false,
                mustBeCapableOfViolence: true,
                colonistRelationChanceFactor: 0,
                allowFood: false,
                allowAddictions: false,
                relationWithExtraPawnChanceFactor: 0
                );

            Pawn pawn = null;

            for (int i = 0; i < num; i++)
            {
                pawn = PawnGenerator.GeneratePawn(request);
                if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, mother))
                {
                    if (pawn.playerSettings != null && mother.playerSettings != null)
                    {
                        pawn.playerSettings.AreaRestriction = father.playerSettings.AreaRestriction;
                    }
                    if (pawn.RaceProps.IsFlesh)
                    {
                        pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, mother);
                        if (father != null)
                        {
                            pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
                        }
                    }
                }
                else
                {
                    Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                }
            }
            if (mother.Spawned)
            {
                FilthMaker.TryMakeFilth(mother.Position, mother.Map, ThingDefOf.Filth_AmnioticFluid, mother.LabelIndefinite(), 5);
                if (mother.caller != null)
                {
                    mother.caller.DoCall();
                }
                if (pawn.caller != null)
                {
                    pawn.caller.DoCall();
                }
            }
        }
        public override void CompTick()
        {
            base.CompTick();
            Pawn pawn = this.parent as Pawn;

            //Important, without a null map check creatures will reproduce while on caravans, producing errors
            if (pawn.Map != null)
            {
                if (this.Props.isGreenGoo)
                {
                    asexualFissionCounter++;
                    //This checks if the map has been filled with creatures. If this check wasn't made, the animal would fill
                    //the map and grind the game to a halt
                    if ((asexualFissionCounter >= ticksInday * reproductionIntervalDays) && ((this.parent.Map != null) && (this.parent.Map.listerThings.ThingsOfDef(ThingDef.Named(this.Props.GreenGooTarget)).Count < this.Props.GreenGooLimit)))
                    {
                        //The offspring has the pawn as both mother and father and I find this funny
                        Hediff_Pregnant.DoBirthSpawn(pawn, pawn);
                        //Only show a message if the pawn is part of the player's faction
                        if (pawn.Faction == Faction.OfPlayer)
                        {
                            Messages.Message(Props.asexualCloningMessage.Translate(pawn.LabelIndefinite().CapitalizeFirst()), pawn, MessageTypeDefOf.PositiveEvent, true);
                        }
                        asexualFissionCounter = 0;
                    }
                    //Just reset the counter if the map is filled
                    else if (asexualFissionCounter >= ticksInday * reproductionIntervalDays)
                    {
                        asexualFissionCounter = 0;
                    }
                }

                //Non-green goo creatures only reproduce if they are part of the player's faction, like vanilla animals
                else if ((pawn.Faction == Faction.OfPlayer) && (pawn.ageTracker.CurLifeStage.reproductive))
                {
                    asexualFissionCounter++;
                    if (asexualFissionCounter >= ticksInday * reproductionIntervalDays)
                    {
                        //If it produces eggs or spores, it will just spawn them. Note that these eggs are not part of the player's
                        //faction, the animal hatched from them will be wild
                        if (produceEggs)
                        {
                            GenSpawn.Spawn(ThingDef.Named(eggDef), pawn.Position, pawn.Map);
                            Messages.Message(Props.asexualEggMessage.Translate(pawn.LabelIndefinite().CapitalizeFirst()), pawn, MessageTypeDefOf.PositiveEvent, true);
                            asexualFissionCounter = 0;
                        }
                        //If not, do a normal fission
                        else
                        {
                            if (Props.convertsIntoAnotherDef)
                            {
                                PawnGenerationRequest request = new PawnGenerationRequest(PawnKindDef.Named(Props.newDef), pawn.Faction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, true, false, false, false, false, 0f, null, 1f, null, null, null, null, null, null, null, null, null, null, null, null);
                                Pawn pawnToGenerate           = PawnGenerator.GeneratePawn(request);
                                PawnUtility.TrySpawnHatchedOrBornPawn(pawnToGenerate, pawn);
                                Messages.Message(Props.asexualEggMessage.Translate(pawn.LabelIndefinite().CapitalizeFirst()), pawn, MessageTypeDefOf.PositiveEvent, true);
                                asexualFissionCounter = 0;
                            }
                            else
                            {
                                Hediff_Pregnant.DoBirthSpawn(pawn, pawn);
                                Messages.Message(Props.asexualEggMessage.Translate(pawn.LabelIndefinite().CapitalizeFirst()), pawn, MessageTypeDefOf.PositiveEvent, true);
                                asexualFissionCounter = 0;
                            }
                        }
                    }
                }
            }
        }
        private static bool on_begin_DoBirthSpawn(ref Pawn mother, ref Pawn father)
        {
            //--Log.Message("patches_pregnancy::PATCH_Hediff_Pregnant::DoBirthSpawn() called");

            if (mother == null)
            {
                Log.Error("Hediff_Pregnant::DoBirthSpawn() - no mother defined -> exit");
                return(false);
            }

            //vanilla debug?
            if (mother.gender == Gender.Male)
            {
                Log.Error("Hediff_Pregnant::DoBirthSpawn() - mother is male -> exit");
                return(false);
            }

            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());

            // get a reference to the hediff we are applying
            //do birth for vanilla pregnancy Hediff
            //if using rjw pregnancies - add RJW pregnancy Hediff and birth it instead
            Hediff_Pregnant self = (Hediff_Pregnant)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Pregnant"));

            if (self != null)
            {
                if (father == null)
                {
                    father = Hediff_BasePregnancy.Trytogetfather(ref mother);
                }
                Log.Message("patches_pregnancy::PATCH_Hediff_Pregnant::DoBirthSpawn():Vanilla_pregnancy birthing:" + xxx.get_pawnname(mother));
                if (RJWPregnancySettings.animal_pregnancy_enabled && ((father == null || xxx.is_animal(father)) && xxx.is_animal(mother)))
                {
                    //RJW Bestial pregnancy animal-animal
                    Log.Message(" override as Bestial birthing(animal-animal): Father-" + xxx.get_pawnname(father) + " Mother-" + xxx.get_pawnname(mother));
                    Hediff_BestialPregnancy.Create(mother, father);
                    Hediff_BestialPregnancy hediff = (Hediff_BestialPregnancy)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_beast"));
                    hediff.Initialize(mother, father);
                    hediff.GiveBirth();
                    if (self != null)
                    {
                        mother.health.RemoveHediff(self);
                    }

                    return(false);
                }
                else if (RJWPregnancySettings.bestial_pregnancy_enabled && ((xxx.is_animal(father) && xxx.is_human(mother)) || (xxx.is_human(father) && xxx.is_animal(mother))))
                {
                    //RJW Bestial pregnancy human-animal
                    Log.Message(" override as Bestial birthing(human-animal): Father-" + xxx.get_pawnname(father) + " Mother-" + xxx.get_pawnname(mother));
                    Hediff_BestialPregnancy.Create(mother, father);
                    Hediff_BestialPregnancy hediff = (Hediff_BestialPregnancy)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_beast"));
                    hediff.Initialize(mother, father);
                    hediff.GiveBirth();
                    if (self != null)
                    {
                        mother.health.RemoveHediff(self);
                    }

                    return(false);
                }
                else if (RJWPregnancySettings.humanlike_pregnancy_enabled && (xxx.is_human(father) && xxx.is_human(mother)))
                {
                    //RJW Humanlike pregnancy
                    Log.Message(" override as Humanlike birthing: Father-" + xxx.get_pawnname(father) + " Mother-" + xxx.get_pawnname(mother));
                    Hediff_HumanlikePregnancy.Create(mother, father);
                    Hediff_HumanlikePregnancy hediff = (Hediff_HumanlikePregnancy)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy"));
                    hediff.Initialize(mother, father);
                    hediff.GiveBirth();
                    if (self != null)
                    {
                        mother.health.RemoveHediff(self);
                    }

                    return(false);
                }
                else
                {
                    Log.Warning("Hediff_Pregnant::DoBirthSpawn() - rjw checks failed, vanilla pregnancy birth");
                    Log.Warning("Hediff_Pregnant::DoBirthSpawn(): Father-" + xxx.get_pawnname(father) + " Mother-" + xxx.get_pawnname(mother));
                    //vanilla pregnancy code, no effects on rjw
                    int num = (mother.RaceProps.litterSizeCurve == null) ? 1 : Mathf.RoundToInt(Rand.ByCurve(mother.RaceProps.litterSizeCurve));
                    if (num < 1)
                    {
                        num = 1;
                    }
                    PawnGenerationRequest request = new PawnGenerationRequest(mother.kindDef, mother.Faction, PawnGenerationContext.NonPlayer, -1, forceGenerateNewPawn: false, newborn: true);
                    Pawn pawn = null;
                    for (int i = 0; i < num; i++)
                    {
                        pawn = PawnGenerator.GeneratePawn(request);
                        if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, mother))
                        {
                            if (pawn.playerSettings != null && mother.playerSettings != null)
                            {
                                pawn.playerSettings.AreaRestriction = mother.playerSettings.AreaRestriction;
                            }
                            if (pawn.RaceProps.IsFlesh)
                            {
                                pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, mother);
                                if (father != null)
                                {
                                    pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
                                }
                            }
                        }
                        else
                        {
                            Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                        }
                        TaleRecorder.RecordTale(TaleDefOf.GaveBirth, mother, pawn);
                    }
                    if (mother.Spawned)
                    {
                        FilthMaker.MakeFilth(mother.Position, mother.Map, ThingDefOf.Filth_AmnioticFluid, mother.LabelIndefinite(), 5);
                        if (mother.caller != null)
                        {
                            mother.caller.DoCall();
                        }
                        if (pawn.caller != null)
                        {
                            pawn.caller.DoCall();
                        }
                    }
                    if (self != null)
                    {
                        mother.health.RemoveHediff(self);
                    }

                    return(false);
                }
            }

            // do birth for existing RJW pregnancies

            Hediff_HumanlikePregnancy rjwH = (Hediff_HumanlikePregnancy)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy"));

            if (rjwH != null)
            {
                //RJW Bestial pregnancy
                Log.Message("patches_pregnancy::PATCH_Hediff_Pregnant::DoBirthSpawn():RJW_pregnancy birthing:" + xxx.get_pawnname(mother));
                rjwH.GiveBirth();
                if (self == null)
                {
                    return(false);
                }
            }

            Hediff_BestialPregnancy rjwB = (Hediff_BestialPregnancy)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_beast"));

            if (rjwB != null)
            {
                //RJW Humanlike pregnancy
                Log.Message("patches_pregnancy::PATCH_Hediff_Pregnant::DoBirthSpawn():RJW_pregnancy_beast birthing:" + xxx.get_pawnname(mother));
                rjwB.GiveBirth();
                if (self == null)
                {
                    return(false);
                }
            }

            //debug, add RJW pregnancy and birth it
            Log.Message("patches_pregnancy::PATCH_Hediff_Pregnant::DoBirthSpawn():Debug_pregnancy birthing:" + xxx.get_pawnname(mother));
            if (father == null)
            {
                father = Hediff_BasePregnancy.Trytogetfather(ref mother);
            }

            /*
             * if (true)
             * {
             *      //RJW Mech pregnancy
             *      Log.Message(" override as mech birthing:" + xxx.get_pawnname(mother));
             *      Hediff_MechanoidPregnancy.Create(mother, father);
             *      Hediff_MechanoidPregnancy hediff = (Hediff_MechanoidPregnancy)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_mech"));
             *      hediff.GiveBirth();
             *      return false;
             * }
             */

            if (RJWPregnancySettings.bestial_pregnancy_enabled && ((xxx.is_animal(father) || xxx.is_animal(mother))) ||
                (xxx.is_animal(mother) && RJWPregnancySettings.animal_pregnancy_enabled))
            {
                //RJW Bestial pregnancy
                Log.Message(" override as Bestial birthing, mother: " + xxx.get_pawnname(mother));
                Hediff_BestialPregnancy.Create(mother, father);
                Hediff_BestialPregnancy hediff = (Hediff_BestialPregnancy)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_beast"));
                hediff.GiveBirth();
            }
            else if (RJWPregnancySettings.humanlike_pregnancy_enabled && ((father == null || xxx.is_human(father)) && xxx.is_human(mother)))
            {
                //RJW Humanlike pregnancy
                Log.Message(" override as Humanlike birthing, mother: " + xxx.get_pawnname(mother));
                Hediff_HumanlikePregnancy.Create(mother, father);
                Hediff_HumanlikePregnancy hediff = (Hediff_HumanlikePregnancy)mother.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy"));
                hediff.GiveBirth();
            }
            else
            {
                Log.Warning("Hediff_Pregnant::DoBirthSpawn() - debug vanilla pregnancy birth");
                //vanilla code
                int num = (mother.RaceProps.litterSizeCurve == null) ? 1 : Mathf.RoundToInt(Rand.ByCurve(mother.RaceProps.litterSizeCurve));
                if (num < 1)
                {
                    num = 1;
                }
                PawnGenerationRequest request = new PawnGenerationRequest(mother.kindDef, mother.Faction, PawnGenerationContext.NonPlayer, -1, forceGenerateNewPawn: false, newborn: true);
                Pawn pawn = null;
                for (int i = 0; i < num; i++)
                {
                    pawn = PawnGenerator.GeneratePawn(request);
                    if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, mother))
                    {
                        if (pawn.playerSettings != null && mother.playerSettings != null)
                        {
                            pawn.playerSettings.AreaRestriction = mother.playerSettings.AreaRestriction;
                        }
                        if (pawn.RaceProps.IsFlesh)
                        {
                            pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, mother);
                            if (father != null)
                            {
                                pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
                            }
                        }
                    }
                    else
                    {
                        Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                    }
                    TaleRecorder.RecordTale(TaleDefOf.GaveBirth, mother, pawn);
                }
                if (mother.Spawned)
                {
                    FilthMaker.MakeFilth(mother.Position, mother.Map, ThingDefOf.Filth_AmnioticFluid, mother.LabelIndefinite(), 5);
                    if (mother.caller != null)
                    {
                        mother.caller.DoCall();
                    }
                    if (pawn.caller != null)
                    {
                        pawn.caller.DoCall();
                    }
                }
                if (self != null)
                {
                    mother.health.RemoveHediff(self);
                }
            }
            return(false);
        }
        public void Hatch()
        {
            try
            {
                PawnGenerationRequest request = new PawnGenerationRequest(this.Props.hatcherPawn, this.hatcheeFaction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, true, false, false, false, false, 0f, null, 1f, null, null, null, null, null, null, null, null, null, null, null, null);
                for (int i = 0; i < this.parent.stackCount; i++)
                {
                    Pawn pawn = PawnGenerator.GeneratePawn(request);
                    if (PawnUtility.TrySpawnHatchedOrBornPawn(pawn, this.parent))
                    {
                        if (pawn != null)
                        {
                            if (this.hatcheeParent != null)
                            {
                                if (pawn.playerSettings != null && this.hatcheeParent.playerSettings != null && this.hatcheeParent.Faction == this.hatcheeFaction)
                                {
                                    pawn.playerSettings.AreaRestriction = this.hatcheeParent.playerSettings.AreaRestriction;
                                }
                                if (pawn.RaceProps.IsFlesh)
                                {
                                    pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, this.hatcheeParent);
                                }
                            }
                            if (this.otherParent != null && (this.hatcheeParent == null || this.hatcheeParent.gender != this.otherParent.gender) && pawn.RaceProps.IsFlesh)
                            {
                                pawn.relations.AddDirectRelation(PawnRelationDefOf.Parent, this.otherParent);
                            }
                            if (parent.Map != null)
                            {
                                List <Thing> ignoredThings   = new List <Thing>();
                                List <Pawn>  allPawnsSpawned = pawn.Map.mapPawns.AllPawnsSpawned;

                                for (int k = 0; k < allPawnsSpawned.Count; k++)
                                {
                                    if (allPawnsSpawned[k] != null && allPawnsSpawned[k].def.defName == pawn.def.defName)
                                    {
                                        ignoredThings.Add(allPawnsSpawned[k]);
                                    }
                                }
                                Thing pawnThing = pawn as Thing;
                                ignoredThings.Add(pawnThing);
                                // Log.Message(DefDatabase<DamageDef>.GetNamed(Props.damageDef).defName);
                                GenExplosion.DoExplosion(parent.Position, parent.Map, Props.range, DefDatabase <DamageDef> .GetNamed(Props.damageDef), parent, Props.damage, -1, SoundDef.Named(Props.soundDef), null, null, null, null, 0f, 1, false, null, 0f, 1, 0, false, null, ignoredThings);
                            }
                        }
                        if (this.parent.Spawned)
                        {
                            FilthMaker.TryMakeFilth(this.parent.Position, this.parent.Map, ThingDefOf.Filth_AmnioticFluid, 1, FilthSourceFlags.None);
                        }
                    }
                    else
                    {
                        Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Discard);
                    }
                }
            }
            finally
            {
                this.parent.Destroy(DestroyMode.Vanish);
            }
        }