code:
using System;
using System.Collections.Generic;
using RimWorld;
using Verse;
using UnityEngine;
using System.Text;
using Multiplayer.API;
using System.Linq;

namespace rjw
{
	class Hediff_BasePregnancy : HediffWithComps
	{
		///<summary>
		///This hediff class simulates pregnancy.
		///</summary>
		/*It is different from vanilla in that if father disappears, this one still remembers him.
		Other weird variants can be derived
		As usuall, significant parts of this are completely stolen from Children and Pregnancy*/

		//Static fields
		private const int MiscarryCheckInterval = 1000;

		private const float MTBMiscarryStarvingDays = 0.5f;

		private const float MTBMiscarryWoundedDays = 0.5f;

		protected const int TicksPerDay = 60000;
		protected const int TicksPerHour = 2500;

		protected const string starvationMessage = "MessageMiscarriedStarvation";
		protected const string poorHealthMessage = "MessageMiscarriedPoorHealth";

		protected static readonly HashSet<String> non_genetic_traits = new HashSet<string>(DefDatabase<StringListDef>.GetNamed("NonInheritedTraits").strings);

		//Fields
		///All babies should be premade and stored here
		protected List<Pawn> babies;
		///Reference to daddy, goes null sometimes
		protected Pawn father;
		///Is pregnancy visible?
		protected bool is_discovered;
		///Is pregnancy type checked?
		public bool is_checked = false;
		///Mechanoid pregnancy, false - spawn agressive mech
		public bool is_hacked = false;
		///Contractions duration, effectively additional hediff stage, a dirty hack to make birthing process notable
		protected int contractions;
		///Gestation progress per tick
		protected float progress_per_tick;
		//
		// Properties
		//
		public float GestationProgress
		{
			get => Severity;
			private set => Severity = value;
		}

		private bool IsSeverelyWounded
		{
			get
			{
				float num = 0;
				List<Hediff> hediffs = pawn.health.hediffSet.hediffs;
				foreach (Hediff h in hediffs)
				{
					if (h is Hediff_Injury && (!h.IsPermanent() || !h.IsTended()))
					{
						num += h.Severity;
					}
				}
				List<Hediff_MissingPart> missingPartsCommonAncestors = pawn.health.hediffSet.GetMissingPartsCommonAncestors();
				foreach (Hediff_MissingPart mp in missingPartsCommonAncestors)
				{
					if (mp.IsFresh)
					{
						num += mp.Part.def.GetMaxHealth(pawn);
					}
				}
				return num > 38 * pawn.RaceProps.baseHealthScale;
			}
		}

		public override void PostMake()
		{
			// Ensure the hediff always applies to the torso, regardless of incorrect directive
			base.PostMake();
			BodyPartRecord torso = pawn.RaceProps.body.AllParts.Find(x => x.def.defName == "Torso");
			if (Part != torso)
				Part = torso;

			//(debug->add heddif)
			//init empty preg, instabirth, cause error during birthing
			//Initialize(pawn, father);
		}

		public override bool Visible => is_discovered;

		public void DiscoverPregnancy()
		{
			is_discovered = true;
			if (PawnUtility.ShouldSendNotificationAbout(this.pawn))
			{
				if (!is_checked)
				{
					string key1 = "RJW_PregnantTitle";
					string message_title = TranslatorFormattedStringExtensions.Translate(key1, pawn.LabelIndefinite());
					string key2 = "RJW_PregnantText";
					string message_text = TranslatorFormattedStringExtensions.Translate(key2, pawn.LabelIndefinite());
					Find.LetterStack.ReceiveLetter(message_title, message_text, LetterDefOf.NeutralEvent, pawn, null);

				}
				else
				{
					PregnancyMessage();
				}
			}
		}

		public void CheckPregnancy()
		{
			is_checked = true;
			if (!is_discovered)
				DiscoverPregnancy();
			else
				PregnancyMessage();
		}

		public virtual void PregnancyMessage()
		{
			string key1 = "RJW_PregnantTitle";
			string message_title = TranslatorFormattedStringExtensions.Translate(key1, pawn.LabelIndefinite());
			string key2 = "RJW_PregnantNormal";
			string message_text = TranslatorFormattedStringExtensions.Translate(key2, pawn.LabelIndefinite());
			Find.LetterStack.ReceiveLetter(message_title, message_text, LetterDefOf.NeutralEvent, pawn, null);
		}

		// Quick method to simply return a body part instance by a given part name
		internal static BodyPartRecord GetPawnBodyPart(Pawn pawn, String bodyPart)
		{
			return pawn.RaceProps.body.AllParts.Find(x => x.def == DefDatabase<BodyPartDef>.GetNamed(bodyPart));
		}

		public void Miscarry()
		{
			pawn.health?.RemoveHediff(this);
		}

		[SyncMethod]
		public Pawn partstospawn(Pawn baby, Pawn mother, Pawn dad)
		{
			//decide what parts to inherit
			//default use own parts
			Pawn partstospawn = baby;
			//Rand.PopState();
			//Rand.PushState(RJW_Multiplayer.PredictableSeed());
			//spawn with mother parts
			if (mother != null && Rand.Range(0, 100) <= 10)
				partstospawn = mother;
			//spawn with father parts
			if (dad != null && Rand.Range(0, 100) <= 10)
				partstospawn = dad;

			//Log.Message("[RJW] Pregnancy partstospawn " + partstospawn);
			return partstospawn;
		}

		[SyncMethod]
		public bool spawnfutachild(Pawn baby, Pawn mother, Pawn dad)
		{
			int futachance = 0;
			if (mother != null && Genital_Helper.is_futa(mother))
				futachance = futachance + 25;
			if (dad != null && Genital_Helper.is_futa(dad))
				futachance = futachance + 25;

			//Log.Message("[RJW] Pregnancy spawnfutachild " + futachance);
			//Rand.PopState();
			//Rand.PushState(RJW_Multiplayer.PredictableSeed());
			return (Rand.Range(0, 100) <= futachance);
		}

		[SyncMethod]
		public static Pawn Trytogetfather(ref Pawn mother)
		{
			//birthing with debug has no father
			//Postmake.initialize() has no father
			Log.Warning("Hediff_BasePregnancy::Trytogetfather() - debug? no father defined, trying to add one");

			Pawn pawn = mother;
			Pawn father = null;

			//possible fathers
			List<Pawn> partners = pawn.relations.RelatedPawns.Where(x =>
					Genital_Helper.has_penis(x) && !x.Dead &&
					(pawn.relations.DirectRelationExists(PawnRelationDefOf.Lover, x) ||
					pawn.relations.DirectRelationExists(PawnRelationDefOf.Fiance, x) ||
					pawn.relations.DirectRelationExists(PawnRelationDefOf.Spouse, x))
					).ToList();

			//add bonded animal
			if (xxx.is_zoophile(mother) && RJWSettings.bestiality_enabled)
				partners.AddRange(pawn.relations.RelatedPawns.Where(x =>
					Genital_Helper.has_penis(x) &&
					pawn.relations.DirectRelationExists(PawnRelationDefOf.Bond, x)).ToList());

			if (partners.Any())
			{
				father = partners.RandomElement();
				Log.Warning("Hediff_BasePregnancy::Trytogetfather() - father set to: " + xxx.get_pawnname(father));
			}

			return father;
		}

		[SyncMethod]
		public override void Tick()
		{
			ageTicks++;
			if (pawn.IsHashIntervalTick(1000))
				if (!pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_mech")))
				{
					//Log.Message("[RJW] Pregnancy is ticking for " + pawn + " this is " + this.def.defName + " will end in " + 1/progress_per_tick/TicksPerDay + " days resulting in "+ babies[0].def.defName);
					//Rand.PopState();
					//Rand.PushState(RJW_Multiplayer.PredictableSeed());
					//miscarry after starving 0.5 day
					if (pawn.needs.food != null && pawn.needs.food.CurCategory == HungerCategory.Starving && Rand.MTBEventOccurs(0.5f, TicksPerDay, MiscarryCheckInterval))
					{
						if (Visible && PawnUtility.ShouldSendNotificationAbout(pawn))
						{
							string text = "MessageMiscarriedStarvation".Translate(pawn.LabelIndefinite()).CapitalizeFirst();
							Messages.Message(text, pawn, MessageTypeDefOf.NegativeHealthEvent);
						}
						Miscarry();
						return;
					}
					//let beatings only be important when pregnancy is developed somewhat
					//miscarry after SeverelyWounded 0.5 day
					if (Visible && IsSeverelyWounded && Rand.MTBEventOccurs(0.5f, TicksPerDay, MiscarryCheckInterval))
					{
						if (Visible && PawnUtility.ShouldSendNotificationAbout(pawn))
						{
							string text = "MessageMiscarriedPoorHealth".Translate(pawn.LabelIndefinite()).CapitalizeFirst();
							Messages.Message(text, pawn, MessageTypeDefOf.NegativeHealthEvent);
						}
						Miscarry();
						return;
					}
				}

			if (xxx.has_quirk(pawn, "Breeder") || pawn.health.hediffSet.HasHediff(HediffDef.Named("FertilityEnhancer")))
				GestationProgress += progress_per_tick * 1.25f;
			else
				GestationProgress += progress_per_tick;

			// Check if pregnancy is far enough along to "show" for the body type
			if (!is_discovered)
			{
				BodyTypeDef bodyT = pawn?.story?.bodyType;
				//float threshold = 0f;

				if ((bodyT == BodyTypeDefOf.Thin && GestationProgress > 0.25f) ||
					(bodyT == BodyTypeDefOf.Female && GestationProgress > 0.35f) ||
					(GestationProgress > 0.50f))
					DiscoverPregnancy();

				//switch (bodyT)
				//{
				//case BodyType.Thin: threshold = 0.3f; break;
				//case BodyType.Female: threshold = 0.389f; break;
				//case BodyType.Male: threshold = 0.41f; break;
				//default: threshold = 0.5f; break;
				//}
				//if (GestationProgress > threshold){ DiscoverPregnancy(); }
			}

			// no birthings in caravan?
			// no idea if it has any effect on guests that left player map
			if (CurStageIndex == 3 && pawn.Map != null)
			{
				if (contractions == 0)
				{
					if (PawnUtility.ShouldSendNotificationAbout(this.pawn))
					{
						string text = "RJW_Contractions".Translate(pawn.LabelIndefinite());
						Messages.Message(text, pawn, MessageTypeDefOf.NeutralEvent);
					}
				}
				contractions++;
				if (contractions >= TicksPerHour)//birthing takes an hour
				{
					if (PawnUtility.ShouldSendNotificationAbout(this.pawn))
					{
						string message_title = "RJW_GaveBirthTitle".Translate(pawn.LabelIndefinite());
						string message_text = "RJW_GaveBirthText".Translate(pawn.LabelIndefinite());
						string baby_text = ((babies.Count == 1) ? "RJW_ABaby".Translate() : "RJW_NBabies".Translate(babies.Count));
						message_text = message_text + baby_text;
						Find.LetterStack.ReceiveLetter(message_title, message_text, LetterDefOf.PositiveEvent, pawn);
					}
					GiveBirth();
				}
			}
		}

		//
		//These functions are different from CnP
		//
		public override void ExposeData()//If you didn't know, this one is used to save the object for later loading of the game... and to load the data into the object, <sigh>
		{
			base.ExposeData();
			Scribe_References.Look(ref father, "father");
			Scribe_Values.Look(ref is_checked, "is_checked");
			Scribe_Values.Look(ref is_hacked, "is_hacked");
			Scribe_Values.Look(ref is_discovered, "is_discovered");
			Scribe_Values.Look(ref contractions, "contractions");
			Scribe_Collections.Look(ref babies, saveDestroyedThings: true, label: "babies", lookMode: LookMode.Deep, ctorArgs: new object[0]);
			Scribe_Values.Look(ref progress_per_tick, "progress_per_tick", 1);
		}

		//This should generate pawns to be born in due time. Should take into account all settings and parent races
		[SyncMethod]
		protected virtual void GenerateBabies()
		{
			Pawn mother = pawn;
			//Log.Message("Generating babies for " + this.def.defName);
			if (mother == null)
			{
				Log.Error("Hediff_BasePregnancy::GenerateBabies() - no mother defined");
				return;
			}

			if (father == null)
			{
				father = Trytogetfather(ref mother);
			}

			//Babies will have average number of traits of their parents, this way it will hopefully be compatible with various mods that change number of allowed traits
			int trait_count = 0;

			//Rand.PopState();
			//Rand.PushState(RJW_Multiplayer.PredictableSeed());
			List<Trait> traitpool = new List<Trait>();
			float skin_whiteness = Rand.Range(0, 1);

			//Log.Message("[RJW]Generating babies " + traitpool.Count + " traits at first");
			if (xxx.has_traits(mother) && mother.RaceProps.Humanlike)
			{
				foreach (Trait momtrait in mother.story.traits.allTraits)
				{
					if (!RJWPregnancySettings.trait_filtering_enabled || !non_genetic_traits.Contains(momtrait.def.defName))
						traitpool.Add(momtrait);
				}
				skin_whiteness = mother.story.melanin;
				trait_count = mother.story.traits.allTraits.Count;
			}
			if (father != null && xxx.has_traits(father) && father.RaceProps.Humanlike)
			{
				foreach (Trait poptrait in father.story.traits.allTraits)
				{
					if (!RJWPregnancySettings.trait_filtering_enabled || !non_genetic_traits.Contains(poptrait.def.defName))
						traitpool.Add(poptrait);
				}
				skin_whiteness = Rand.Range(skin_whiteness, father.story.melanin);
				trait_count = Mathf.RoundToInt((trait_count + father.story.traits.allTraits.Count) / 2f);
			}
			//this probably doesnt matter in 1.0 remove it and wait for bug reports =)
			//trait_count = trait_count > 2 ? trait_count : 2;//Tynan has hardcoded 2-3 traits per pawn.  In the above, result may be less than that. Let us not have disfunctional babies.

			//Log.Message("[RJW]Generating babies " + traitpool.Count + " traits aFter parents");
			Pawn parent = mother; //race of child
			Pawn parent2= father; //name for child

			//Decide on which parent is first to be inherited
			if (father != null && RJWPregnancySettings.use_parent_method)
			{
				//Log.Message("The baby race needs definition");
				//humanality
				if (xxx.is_human(mother) && xxx.is_human(father))
				{
					//Log.Message("It's of two humanlikes");
					if (!Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother))
					{
						//Log.Message("Mother will birth father race");
						parent = father;
					}
					else
					{
						//Log.Message("Mother will birth own race");
					}
				}
				else
				{
					//bestiality
					if ((!xxx.is_human(mother) && xxx.is_human(father)) ||
					    (xxx.is_human(mother) && !xxx.is_human(father)))
					{
						if (RJWPregnancySettings.bestiality_DNA_inheritance == 0.0f)
						{
							//Log.Message("mother will birth beast");
							if (xxx.is_human(mother))
								parent = father;
							else
								parent = mother;
						}
						else if (RJWPregnancySettings.bestiality_DNA_inheritance == 1.0f)
						{
							//Log.Message("mother will birth humanlike");
							if (xxx.is_human(mother))
								parent = mother;
							else
								parent = father;
						}
						else
						{
							if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother))
							{
								//Log.Message("Mother will birth father race");
								parent = father;
							}
							else
							{
								//Log.Message("Mother will birth own race");
							}
						}

					}
					//animality
					else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother))
					{
						//Log.Message("Mother will birth father race");
						parent = father;
					}
					else
					{
						//Log.Message("Mother will birth own race");
					}
				}
			}
			//slimes birth only other slimes
			if (mother.kindDef.race.defName.ToLower().Contains("slime"))
			{
				parent = mother;
			}
			if (father != null)
				if (father.kindDef.race.defName.ToLower().Contains("slime"))
				{
					parent = father;
				}
			//Log.Message("[RJW] The main parent is " + parent);
			//Log.Message("Mother: " + xxx.get_pawnname(mother) + " kind: " + mother.kindDef);
			//Log.Message("Father: " + xxx.get_pawnname(father) + " kind: " + father.kindDef);
			//Log.Message("Baby base: " + xxx.get_pawnname(parent) + " kind: " + parent.kindDef);

			// Surname passing
			string last_name = "";
			if (xxx.is_human(father))
				last_name = NameTriple.FromString(father.Name.ToStringFull).Last;
			if (xxx.is_human(mother) && last_name == "")
				last_name = NameTriple.FromString(mother.Name.ToStringFull).Last;
			//Log.Message("[RJW] Bady surname will be " + last_name);

			//Pawn generation request
			int MapTile = -1;
			PawnKindDef spawn_kind_def = parent.kindDef;
			Faction spawn_faction = mother.IsPrisoner ? null : mother.Faction;
			PawnGenerationRequest request = new PawnGenerationRequest(spawn_kind_def, spawn_faction, PawnGenerationContext.NonPlayer, MapTile, false, true, false, false, false, false, 1, false, true, false, false, false, false, false, null, null, null, 0, 0, null, skin_whiteness, last_name);

			//Log.Message("[RJW] Generated request, making babies");
			//Litter size. Let's use the main parent litter size, increased by fertility.
			float litter_size = (parent.RaceProps.litterSizeCurve == null) ? 1 : Rand.ByCurve(parent.RaceProps.litterSizeCurve);
			//Log.Message("[RJW] base Litter size " + litter_size);
			litter_size *= mother.health.capacities.GetLevel(xxx.reproduction);
			litter_size *= father == null ? 1 : father.health.capacities.GetLevel(xxx.reproduction);
			litter_size = Math.Max(1, litter_size);
			//Log.Message("[RJW] Litter size (w fertility) " + litter_size);

			//Babies size vs mother body size
			//assuming mother belly is 1/3 of mother body size
			float baby_size = spawn_kind_def.RaceProps.lifeStageAges[0].def.bodySizeFactor * spawn_kind_def.RaceProps.baseBodySize; // adult size/5
			//Log.Message("[RJW] Baby size " + baby_size);
			float max_litter = 1f / 3f / baby_size;
			//Log.Message("[RJW] Max size " + max_litter);
			max_litter *= ((xxx.has_quirk(mother, "Breeder") || xxx.has_quirk(mother, "Incubator")) ? 2 : 1);
			//Log.Message("[RJW] Max size (w quirks) " + max_litter);

			//Generate random amount of babies within litter/max size
			litter_size = (Rand.Range(litter_size, max_litter));
			//Log.Message("[RJW] Litter size roll 1:" + litter_size);
			litter_size = Mathf.RoundToInt(litter_size);
			//Log.Message("[RJW] Litter size roll 2:" + litter_size);
			litter_size = Math.Max(1, litter_size);
			//Log.Message("[RJW] final Litter size " + litter_size);

			for (int i = 0; i < litter_size; i++)
			{
				Pawn baby = PawnGenerator.GeneratePawn(request);
				//Choose traits to add to the child. Unlike CnP this will allow for some random traits
				if (xxx.is_human(baby) && traitpool.Count > 0)
				{
					int baby_trait_count = baby.story.traits.allTraits.Count;
					if (baby_trait_count > trait_count / 2)
					{
						baby.story.traits.allTraits.RemoveRange(0, Math.Max(trait_count / 2, 1) - 1);
					}
					List<Trait> to_add = new List<Trait>();
					while (to_add.Count < Math.Min(trait_count, traitpool.Count))
					{
						Trait gentrait = traitpool.RandomElement();
						if (!to_add.Contains(gentrait))
						{
							to_add.Add(gentrait);
						}
					}
					foreach (Trait trait in to_add)
					{
						// Skip to next check if baby already has the trait, or it conflicts with existing one.
						if (baby.story.traits.HasTrait(trait.def) || baby.story.traits.allTraits.Any(x => x.def.ConflictsWith(trait))) continue;

						baby.story.traits.GainTrait(trait);

						if (baby.story.traits.allTraits.Count >= trait_count)
						{
							break;
						}
					}
				}
				babies.Add(baby);
			}
		}

		//Handles the spawning of pawns and adding relations
		//this is extended by other scripts
		public virtual void GiveBirth()
		{
		}

		public virtual void PostBirth(Pawn mother, Pawn father, Pawn baby)
		{
			if (xxx.is_human(baby))
			{
				baby.story.childhood = null;
				baby.story.adulthood = null;
			}
			//inject RJW_BabyState to the newborn if RimWorldChildren is not active
			//cnp patches its hediff right into pawn generator, so its already in if it can
			if (!xxx.RimWorldChildrenIsActive)
			{
				if (xxx.is_human(baby) && baby.ageTracker.CurLifeStageIndex <= 1 && baby.ageTracker.AgeBiologicalYears < 1 && !baby.Dead)
				{
					// Clean out drugs, implants, and stuff randomly generated
					//no support for custom race stuff, if there is any
					baby.health.hediffSet.Clear();
					baby.health.AddHediff(HediffDef.Named("RJW_BabyState"), null, null);//RJW_Babystate.tick_rare actually forces CnP switch to CnP one if it can, don't know wat do
					Hediff_SimpleBaby babystate = (Hediff_SimpleBaby)baby.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_BabyState"));
					if (babystate != null)
					{
						babystate.GrowUpTo(0, true);
					}
				}
			}
			else
			{
				if (xxx.is_human(mother))
				{
					//BnC compatibility
					if (DefDatabase<HediffDef>.GetNamedSilentFail("BnC_RJW_PostPregnancy") == null)
					{
						mother.health.AddHediff(HediffDef.Named("PostPregnancy"), null, null);
						mother.health.AddHediff(HediffDef.Named("Lactating"), mother.RaceProps.body.AllParts.Find(x => x.def.defName == "Chest"), null);
					}
					if (xxx.is_human(baby))
						if (mother.records.GetAsInt(xxx.CountOfBirthHuman) == 0 &&
							mother.records.GetAsInt(xxx.CountOfBirthAnimal) == 0 &&
							mother.records.GetAsInt(xxx.CountOfBirthInsect) == 0 )
						{
							mother.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("IGaveBirthFirstTime"));
						}
						else
						{
							mother.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("IGaveBirth"));
						}
				}

				if (xxx.is_human(baby))
					if (xxx.is_human(father))
					{
						father.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("PartnerGaveBirth"));
					}

				if (xxx.is_human(baby))
				{
					Log.Message("[RJW]PostBirth:: Rewriting story of " + baby);
					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;
					}
				}
			}
			if (baby.playerSettings != null && mother.playerSettings != null)
			{
				baby.playerSettings.AreaRestriction = mother.playerSettings.AreaRestriction;
			}

			//spawn futa
			bool isfuta = spawnfutachild(baby, mother, father);

			Genital_Helper.add_anus(baby, partstospawn(baby, mother, father));

			if (baby.gender == Gender.Female || isfuta)
				Genital_Helper.add_breasts(baby, partstospawn(baby, mother, father), Gender.Female);

			if (isfuta)
			{
				Genital_Helper.add_genitals(baby, partstospawn(baby, mother, father), Gender.Male);
				Genital_Helper.add_genitals(baby, partstospawn(baby, mother, father), Gender.Female);
				baby.gender = Gender.Female;                //set gender to female for futas, should cause no errors since babies already generated with relations n stuff
			}
			else
				Genital_Helper.add_genitals(baby, partstospawn(baby, mother, father));

			if (mother.Spawned)
			{
				// 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);
				}
				// Spawn guck
				FilthMaker.MakeFilth(mother.Position, mother.Map, ThingDefOf.Filth_AmnioticFluid, mother.LabelIndefinite(), 5);
				mother.caller?.DoCall();
				baby.caller?.DoCall();
			}

			if (xxx.is_human(baby))
				mother.records.AddTo(xxx.CountOfBirthHuman, 1);
			if (xxx.is_animal(baby))
				mother.records.AddTo(xxx.CountOfBirthAnimal, 1);

			if ((mother.records.GetAsInt(xxx.CountOfBirthHuman) > 10 || mother.records.GetAsInt(xxx.CountOfBirthAnimal) > 20))
			{
				if (!xxx.has_quirk(mother, "Breeder"))
				{
					CompRJW.Comp(mother).quirks.AppendWithComma("Breeder");
				}
				if (!xxx.has_quirk(mother, "Impregnation fetish"))
				{
					CompRJW.Comp(mother).quirks.AppendWithComma("Impregnation fetish");
				}
			}
		}

		//This method is doing the work of the constructor since hediffs are created through HediffMaker instead of normal oop way
		//This can't be in PostMake() because there wouldn't be father.
		public void Initialize(Pawn mother, Pawn dad)
		{
			BodyPartRecord torso = mother.RaceProps.body.AllParts.Find(x => x.def.defName == "Torso");
			mother.health.AddHediff(this, torso);
			//Log.Message("[RJW]" + this.GetType().ToString() + " pregnancy hediff generated: " + this.Label);
			//Log.Message("[RJW]" + this.GetType().ToString() + " mother: " + mother + " father: " + dad);
			father = dad;
			if (father != null)
			{
				babies = new List<Pawn>();
				contractions = 0;
				//Log.Message("[RJW]" + this.GetType().ToString() + " generating babies before: " + this.babies.Count);
				GenerateBabies();
			}
			//progress_per_tick = babies.NullOrEmpty() ? 1f : (1.0f) / (babies[0].RaceProps.gestationPeriodDays * TicksPerDay/50);
			progress_per_tick = babies.NullOrEmpty() ? 1f : (1.0f) / (babies[0].RaceProps.gestationPeriodDays * TicksPerDay);
			//Log.Message("[RJW]" + this.GetType().ToString() + " generating babies after: " + this.babies.Count);
		}

		public override string DebugString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(base.DebugString());
			stringBuilder.AppendLine("Gestation progress: " + GestationProgress.ToStringPercent());
			//stringBuilder.AppendLine("Time left: " + ((int)((1f - GestationProgress) * babies[0].RaceProps.gestationPeriodDays * TicksPerDay/50)).ToStringTicksToPeriod());
			stringBuilder.AppendLine("Time left: " + ((int)((1f - GestationProgress) * babies[0].RaceProps.gestationPeriodDays * TicksPerDay)).ToStringTicksToPeriod());
			stringBuilder.AppendLine(" Father: " + xxx.get_pawnname(father));
			return stringBuilder.ToString();
		}
	}
}


code:
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using Verse;

namespace rjw
{
	///<summary>
	///This hediff class simulates pregnancy with animal children, mother may be human. It is not intended to be reasonable.
	///Differences from humanlike pregnancy are that animals are given some training and that less punishing relations are used for parent-child.
	///</summary>
	class Hediff_BestialPregnancy : Hediff_BasePregnancy
	{
		private static readonly PawnRelationDef relation_birthgiver = DefDatabase<PawnRelationDef>.AllDefs.FirstOrDefault(d => d.defName== "RJW_Sire" );
		private static readonly PawnRelationDef relation_spawn = DefDatabase<PawnRelationDef>.AllDefs.FirstOrDefault(d => d.defName == "RJW_Pup");
		//static int max_train_level = TrainableUtility.TrainableDefsInListOrder.Sum(tr => tr.steps);

		public override void PregnancyMessage()
		{
			string message_title = "RJW_PregnantTitle".Translate(pawn.LabelIndefinite());
			string message_text1 = "RJW_PregnantText".Translate(pawn.LabelIndefinite());
			string message_text2 = "RJW_PregnantStrange".Translate();
			Find.LetterStack.ReceiveLetter(message_title, message_text1 + "\n" + message_text2, LetterDefOf.NeutralEvent, pawn);
		}

		//Makes half-human babies start off better. They start obedient, and if mother is a human, they get hediff to boost their training
		protected void train(Pawn baby, Pawn mother, Pawn father)
		{
			bool _;
			if (!xxx.is_human(baby) && baby.Faction == Faction.OfPlayer)
			{
				if (xxx.is_human(mother) && baby.Faction == Faction.OfPlayer && baby.training.CanAssignToTrain(TrainableDefOf.Obedience, out _).Accepted)
				{
					baby.training.Train(TrainableDefOf.Obedience, mother);
				}
				if (xxx.is_human(mother) && baby.Faction == Faction.OfPlayer && baby.training.CanAssignToTrain(TrainableDefOf.Tameness, out _).Accepted)
				{
					baby.training.Train(TrainableDefOf.Tameness, mother);
				}
			}
			//baby.RaceProps.TrainableIntelligence.LabelCap.
			//if (xxx.is_human(mother))
			//{
			//	Let the animals be born as colony property
			//	if (mother.IsPrisonerOfColony || mother.IsColonist)
			//	{
			//		baby.SetFaction(Faction.OfPlayer);
			//	}
			//	let it be trained half to the max
			//	var baby_int = baby.RaceProps.TrainableIntelligence;
			//	int max_int = TrainableUtility.TrainableDefsInListOrder.FindLastIndex(tr => (tr.requiredTrainableIntelligence == baby_int));
			//	if (max_int == -1)
			//		return;
			//	Log.Message("RJW training " + baby + " max_int is " + max_int);
			//	var available_tricks = TrainableUtility.TrainableDefsInListOrder.GetRange(0, max_int + 1);
			//	int max_steps = available_tricks.Sum(tr => tr.steps);
			//	Log.Message("RJW training " + baby + " vill do " + max_steps/2 + " steps");
			//	int t_score = Rand.Range(Mathf.RoundToInt(max_steps / 4), Mathf.RoundToInt(max_steps / 2));
			//	for (int i = 1; i <= t_score; i++)
			//	{
			//		var tr = available_tricks.Where(t => !baby.training.IsCompleted(t)). RandomElement();
			//		Log.Message("RJW training " + baby + " for " + tr);
			//		baby.training.Train(tr, mother);
			//	}

			//	baby.health.AddHediff(HediffDef.Named("RJW_smartPup"));
			//}
		}

		//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 beastiality/animal pregnancy birthing pawn count: " + babies.Count);
			}
			catch
			{
				Initialize(mother, father);
			}
			List<Pawn> siblings = new List<Pawn>();
			foreach (Pawn baby in babies)
			{
				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;
				}

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

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

				PostBirth(mother, father, baby);

				mother.health.RemoveHediff(this);
			}
		}

		///This method should be the only one to create the hediff
		//Hediffs are made HediffMaker.MakeHediff which returns hediff of class different than the one needed, so we do the cast and then do all the same operations as in parent class
		//I don't know whether it'd be possible to use standard constructor instead of this retardation
		public static void Create(Pawn mother, Pawn father)
		{
			if (mother == null)
				return;

			BodyPartRecord torso = mother.RaceProps.body.AllParts.Find(x => x.def.defName == "Torso");
			//Log.Message("RJW beastial "+ mother + " " + father);

			Hediff_BestialPregnancy hediff = (Hediff_BestialPregnancy)HediffMaker.MakeHediff(HediffDef.Named("RJW_pregnancy_beast"), mother, torso);
			hediff.Initialize(mother, father);
		}
	}
}

repo_name: Harper/rjw

license: mit


code:
using System;
using System.Collections.Generic;
using System.Text;
using RimWorld;
using Verse;
using UnityEngine;

namespace rjw
{
	class Hediff_HumanlikePregnancy : Hediff_BasePregnancy
	///<summary>
	///This hediff class simulates pregnancy resulting in humanlike childs.
	///</summary>
	{
		//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
			{
				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)
				{
					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);
			}
		}

		///This method should be the only one to create the hediff
		public static void Create(Pawn mother, Pawn father)
		{
			if (mother == null)
				return;

			var torso = mother.RaceProps.body.AllParts.Find(x => x.def.defName == "Torso");
			//Log.Message("[RJW]Humanlike pregnancy " + mother + " is bred by " + father);

			var hediff = (Hediff_HumanlikePregnancy)HediffMaker.MakeHediff(HediffDef.Named("RJW_pregnancy"), mother, torso);
			hediff.Initialize(mother, father);
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using RimWorld.Planet;
using Verse;
using System.Text;
using Verse.AI.Group;
using Multiplayer.API;

namespace rjw
{
	internal class Hediff_InsectEgg : HediffWithComps
	{
		/*public override void Tick()
		{
			base.Tick();
			//--Log.Message("[RJW]Hediff_InsectEgg::Tick() - InsectEgg growing");
		}*/

		protected int bornTick
		{
			get
			{
				return xxx.has_quirk(pawn, "Incubator") || pawn.health.hediffSet.HasHediff(HediffDef.Named("FertilityEnhancer")) ? ((HediffDef_InsectEgg)this.def).bornTick / 2 : ((HediffDef_InsectEgg)this.def).bornTick;
			}
		}

		protected int abortTick
		{
			get
			{
				return ((HediffDef_InsectEgg)this.def).abortTick;
			}
		}

		public float GestationProgress
		{
			get => Severity;
			private set => Severity = value;
		}

		public Pawn father;					//can be parentkind defined in egg
		public Pawn queen;					//can be any pawn
		public bool fertilized => father != null;
		protected List<Pawn> babies;

		///Contractions duration, effectively additional hediff stage, a dirty hack to make birthing process notable
		//protected const int TicksPerHour = 2500;
		protected int contractions = 0;

		public string parentDef
		{
			get
			{
				return ((HediffDef_InsectEgg)def).parentDef;
			}
		}

		public List<string> parentDefs
		{
			get
			{
				return ((HediffDef_InsectEgg)def).parentDefs;
			}
		}

		public override void PostAdd(DamageInfo? dinfo)
		{
			//--Log.Message("[RJW]Hediff_InsectEgg::PostAdd() - added parentDef:" + parentDef+"");
			base.PostAdd(dinfo);
		}

		public override void Tick()
		{
			this.ageTicks++;
			if (this.pawn.IsHashIntervalTick(1000))
			{
				if (this.ageTicks >= bornTick)
				{
					if (PawnUtility.ShouldSendNotificationAbout(this.pawn))
					{
						string key1 = "RJW_GaveBirthEggTitle";
						string message_title = TranslatorFormattedStringExtensions.Translate(key1, pawn.LabelIndefinite());
						string key2 = "RJW_GaveBirthEggText";
						string message_text = TranslatorFormattedStringExtensions.Translate(key2, pawn.LabelIndefinite());
						//Find.LetterStack.ReceiveLetter(message_title, message_text, LetterDefOf.NeutralEvent, pawn, null);
						Messages.Message(message_text, pawn, MessageTypeDefOf.SituationResolved);
					}
					GiveBirth();
					//someday add dmg to vag?
					//var dam = Rand.RangeInclusive(0, 1);
					//p.TakeDamage(new DamageInfo(DamageDefOf.Burn, dam, 999, -1.0f, null, rec, null));
				}
				else
				{
					//birthing takes an hour
					if (this.ageTicks >= bornTick - 2500 && contractions == 0)
					{
						if (PawnUtility.ShouldSendNotificationAbout(this.pawn))
						{
							string key = "RJW_EggContractions";
							string text = TranslatorFormattedStringExtensions.Translate(key, pawn.LabelIndefinite());
							Messages.Message(text, pawn, MessageTypeDefOf.NeutralEvent);
						}
						contractions++;
						pawn.health.AddHediff(HediffDef.Named("Hediff_Submitting"));
					}
				}
			}
		}

		public override void ExposeData()
		{
			base.ExposeData();
			Scribe_References.Look<Pawn>(ref this.father, "father", false);
			Scribe_References.Look<Pawn>(ref this.queen, "queen", false);
			Scribe_Collections.Look(ref babies, saveDestroyedThings: true, label: "babies", lookMode: LookMode.Deep, ctorArgs: new object[0]);
		}
		public override void Notify_PawnDied()
		{
			base.Notify_PawnDied();
			GiveBirth();
		}

		protected virtual void GenerateBabies()
		{

		}

		//should someday remake into birth eggs and then within few ticks hatch them
		[SyncMethod]
		public void GiveBirth()
		{
			Pawn mother = pawn;
			Pawn baby = null;
			//Rand.PopState();
			//Rand.PushState(RJW_Multiplayer.PredictableSeed());
			if (fertilized)
			{
				//Log.Message("[RJW]Hediff_InsectEgg::BirthBaby() - Egg of " + parentDef + " in " + mother.ToString() + " birth!");
				PawnKindDef spawn_kind_def = father.kindDef;
				//egg mostlikely insect or implanter spawned factionless through debug, set to insect
				Faction spawn_faction = Faction.OfInsects;

				//Log.Message("[RJW]Hediff_InsectEgg::BirthBaby() - insect " + (queen.Faction == Faction.OfInsects || father.Faction == Faction.OfInsects || mother.Faction == Faction.OfInsects));
				//Log.Message("[RJW]Hediff_InsectEgg::BirthBaby() - human " + (xxx.is_human(queen) && xxx.is_human(father)));
				//Log.Message("[RJW]Hediff_InsectEgg::BirthBaby() - animal1 " + (!xxx.is_human(queen) && !(queen.Faction?.IsPlayer ?? false)));
				//Log.Message("[RJW]Hediff_InsectEgg::BirthBaby() - animal2 ");

				//this is probably fucked up, idk how to filter insects from non insects/spiders etc
				//Hive Insects... probably
				if (queen.Faction == Faction.OfInsects || father.Faction == Faction.OfInsects || mother.Faction == Faction.OfInsects)
				{
					//Log.Message("[RJW]Hediff_InsectEgg::BirthBaby() - insect ");
					spawn_faction = Faction.OfInsects;
					int chance = 5;

					//random chance to make insect neutral/tamable
					if (father.Faction == Faction.OfInsects)
						chance = 5;
					if (father.Faction != Faction.OfInsects)
						chance = 10;
					if (father.Faction == Faction.OfPlayer)
						chance = 25;
					if (queen.Faction == Faction.OfPlayer)
						chance += 25;
					if (queen.Faction == Faction.OfPlayer && xxx.is_human(queen))
						chance += (int)(25 * queen.GetStatValue(StatDefOf.PsychicSensitivity));
					if (Rand.Range(0, 100) <= chance)
						spawn_faction = null;

					//chance tame insect on birth
					if (spawn_faction == null)
						if (queen.Faction == Faction.OfPlayer && xxx.is_human(queen))
							if (Rand.Range(0, 100) <= (int)(50 * queen.GetStatValue(StatDefOf.PsychicSensitivity)))
								spawn_faction = Faction.OfPlayer;
				}
				//humanlikes
				else if (xxx.is_human(queen) && xxx.is_human(father))
				{
					spawn_faction = queen.Faction;
				}
				//TODO: humnlike + animal, merge with insect stuff?
				//else if (xxx.is_human(queen) && !xxx.is_human(father))
				//{
				//	spawn_faction = queen.Faction;
				//}
				//animal, spawn implanter faction (if not player faction/not tamed)
				else if (!xxx.is_human(queen) && !(queen.Faction?.IsPlayer ?? false))
				{
					spawn_faction = queen.Faction;
				}
				//spawn factionless(tamable, probably)
				else
				{
					spawn_faction = null;
				}

				//Log.Message("[RJW]Hediff_InsectEgg::BirthBaby() " + spawn_kind_def + " of " + spawn_faction + " in " + (int)(50 * queen.GetStatValue(StatDefOf.PsychicSensitivity)) + " chance!");
				PawnGenerationRequest request = new PawnGenerationRequest(spawn_kind_def, spawn_faction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, false, false, 0, false, true, false, false, false, false, false, null, null, 0, 0);

				baby = PawnGenerator.GeneratePawn(request);
				if (PawnUtility.TrySpawnHatchedOrBornPawn(baby, mother))
				{
					Genital_Helper.sexualize_pawn(baby);
					if (spawn_faction == Faction.OfInsects)
					{
						//add ai to pawn?
						//LordManager.lords
						LordJob_DefendAndExpandHive lordJob = new LordJob_DefendAndExpandHive(true);
						Lord lord = LordMaker.MakeNewLord(baby.Faction, lordJob, baby.Map);
						lord.AddPawn(baby);
						lord.SetJob(lordJob);
						//Log.Message("[RJW]Hediff_InsectEgg::BirthBaby() " + baby.GetLord().DebugString());

					}
				}
				else
				{
					Find.WorldPawns.PassToWorld(baby, PawnDiscardDecideMode.Discard);
				}

				// 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);
				}

				/*
				if (Visible && baby != null)
				{
					string key = "MessageGaveBirth";
					string text = TranslatorFormattedStringExtensions.Translate(key, mother.LabelIndefinite()).CapitalizeFirst();
					Messages.Message(text, baby, MessageTypeDefOf.NeutralEvent);
				}
				*/

				mother.records.AddTo(xxx.CountOfBirthInsect, 1);

				if (mother.records.GetAsInt(xxx.CountOfBirthInsect) > 100)
				{
					if (!xxx.has_quirk(mother, "Incubator"))
					{
						CompRJW.Comp(mother).quirks.AppendWithComma("Incubator");
					}
					if (!xxx.has_quirk(mother, "Impregnation fetish"))
					{
						CompRJW.Comp(mother).quirks.AppendWithComma("Impregnation fetish");
					}
				}
			}
			else
			{
				string key = "EggDead";
				string text = TranslatorFormattedStringExtensions.Translate(key, pawn.LabelIndefinite()).CapitalizeFirst();
				Messages.Message(text, pawn, MessageTypeDefOf.SituationResolved);
			}
			// Post birth
			if (mother.Spawned)
			{
				// Spawn guck
				if (mother.caller != null)
				{
					mother.caller.DoCall();
				}
				if (baby != null)
				{
					if (baby.caller != null)
					{
						baby.caller.DoCall();
					}
				}
				FilthMaker.MakeFilth(mother.Position, mother.Map, ThingDefOf.Filth_AmnioticFluid, mother.LabelIndefinite(), 5);
				int howmuch = xxx.has_quirk(mother, "Incubator") ? Rand.Range(1, 3) * 2 : Rand.Range(1, 3);
				//DebugThingPlaceHelper.DebugSpawn(ThingDef.Named("InsectJelly"), mother.InteractionCell, howmuch, false);
				int i = 0;
				while (i++ < howmuch)
					GenSpawn.Spawn(ThingDefOf.InsectJelly, mother.InteractionCell, mother.Map);
			}

			mother.health.RemoveHediff(this);
		}

		public void Fertilize(Pawn pawn)
		{
			if (!fertilized && ageTicks < abortTick)
			{
				father = pawn;
			}
		}

		public void Implanter(Pawn pawn)
		{
			if (queen == null)
			{
				queen = pawn;
				if (((HediffDef_InsectEgg)this.def).selffertilized)
					Fertilize(pawn);
			}
		}

		public override bool TryMergeWith(Hediff other)
		{
			return false;
		}

		public bool IsParent(string defnam)
		{
			return parentDef == defnam || parentDefs.Contains(defnam);
		}

		public override string DebugString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(base.DebugString());
			stringBuilder.AppendLine(" Gestation progress: " + ((float)ageTicks / bornTick).ToStringPercent());
			stringBuilder.AppendLine(" Implanter: " + xxx.get_pawnname(queen));
			stringBuilder.AppendLine(" Fertilized:" + (fertilized).ToString());
			return stringBuilder.ToString();
		}
	}
}


code:
using RimWorld;
using System.Linq;
using Verse;
using Verse.AI;

namespace rjw
{
	internal class Hediff_Orgasm : HediffWithComps
	{
		public override void PostAdd(DamageInfo? dinfo)
		{
			string key = "FeltOrgasm";
			string text = TranslatorFormattedStringExtensions.Translate(key, pawn.LabelIndefinite()).CapitalizeFirst();
			Messages.Message(text, pawn, MessageTypeDefOf.NeutralEvent);
		}
	}

	internal class Hediff_TransportCums : HediffWithComps
	{
		public override void PostAdd(DamageInfo? dinfo)
		{
			if (pawn.gender == Gender.Female)
			{
				string key = "CumsTransported";
				string text = TranslatorFormattedStringExtensions.Translate(key, pawn.LabelIndefinite()).CapitalizeFirst();
				Messages.Message(text, pawn, MessageTypeDefOf.NeutralEvent);
				PawnGenerationRequest req = new PawnGenerationRequest(PawnKindDefOf.Drifter, fixedGender:Gender.Male );
				Pawn cumSender = PawnGenerator.GeneratePawn(req);
				Find.WorldPawns.PassToWorld(cumSender);
				//Pawn cumSender = (from p in Find.WorldPawns.AllPawnsAlive where p.gender == Gender.Male select p).RandomElement<Pawn>();
				//--Log.Message("[RJW]" + this.GetType().ToString() + "PostAdd() - Sending " + xxx.get_pawnname(cumSender) + "'s cum into " + xxx.get_pawnname(pawn) + "'s vagina");
				PregnancyHelper.impregnate(pawn, cumSender, xxx.rjwSextype.Vaginal);
			}
			pawn.health.RemoveHediff(this);
		}
	}

	internal class Hediff_TransportEggs : HediffWithComps
	{
		public override void PostAdd(DamageInfo? dinfo)
		{
			if (pawn.gender == Gender.Female)
			{
				string key = "EggsTransported";
				string text = TranslatorFormattedStringExtensions.Translate(key, pawn.LabelIndefinite()).CapitalizeFirst();
				Messages.Message(text, pawn, MessageTypeDefOf.NeutralEvent);

				PawnKindDef spawn = PawnKindDefOf.Megascarab;
				PawnGenerationRequest req1 = new PawnGenerationRequest(spawn, fixedGender:Gender.Female );
				PawnGenerationRequest req2 = new PawnGenerationRequest(spawn, fixedGender:Gender.Male );
				Pawn implanter = PawnGenerator.GeneratePawn(req1);
				Pawn fertilizer = PawnGenerator.GeneratePawn(req2);
				Find.WorldPawns.PassToWorld(implanter);
				Find.WorldPawns.PassToWorld(fertilizer);
				Genital_Helper.sexualize_pawn(implanter);
				Genital_Helper.sexualize_pawn(fertilizer);
				//Pawn cumSender = (from p in Find.WorldPawns.AllPawnsAlive where p.gender == Gender.Male select p).RandomElement<Pawn>();
				//--Log.Message("[RJW]" + this.GetType().ToString() + "PostAdd() - Sending " + xxx.get_pawnname(cumSender) + "'s cum into " + xxx.get_pawnname(pawn) + "'s vagina");
				PregnancyHelper.impregnate(pawn, implanter, xxx.rjwSextype.Vaginal);
				PregnancyHelper.impregnate(pawn, fertilizer, xxx.rjwSextype.Vaginal);
			}
			pawn.health.RemoveHediff(this);
		}
	}
}


code:
using System.Collections.Generic;
using Verse;

namespace rjw
{
	internal class Hediff_MechImplants : HediffWithComps
	{
		public override bool TryMergeWith(Hediff other)
		{
			return false;
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;
using Verse.AI.Group;
using System.Linq;
using UnityEngine;

namespace rjw
{
	///<summary>
	///This hediff class simulates pregnancy with mechanoids, mother may be human. It is not intended to be reasonable.
	///Differences from bestial pregnancy are that ... it is lethal
	///TODO: extend with something "friendlier"? than Mech_Scyther.... two Mech_Scyther's? muhahaha
	///</summary>
	class Hediff_MechanoidPregnancy : Hediff_BasePregnancy
	{
		public override void PregnancyMessage()
		{
			string message_title = "RJW_PregnantTitle".Translate(pawn.LabelIndefinite());
			string message_text1 = "RJW_PregnantText".Translate(pawn.LabelIndefinite());
			string message_text2 = "RJW_PregnantMechStrange".Translate();
			Find.LetterStack.ReceiveLetter(message_title, message_text1 + "\n" + message_text2, LetterDefOf.ThreatBig, pawn);
		}

		public void Hack()
		{
			is_hacked = true;
		}

		public override void Notify_PawnDied()
		{
			base.Notify_PawnDied();
			GiveBirth();
		}

		//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);
		}

		///This method should be the only one to create the hediff
		//Hediffs are made HediffMaker.MakeHediff which returns hediff of class different than the one needed, so we do the cast and then do all the same operations as in parent class
		//I don't know whether it'd be possible to use standard constructor instead of this retardation
		public static void Create(Pawn mother, Pawn father)
		{
			if (mother == null)
				return;

			BodyPartRecord torso = mother.RaceProps.body.AllParts.Find(x => x.def.defName == "Torso");
			//Log.Message("RJW beastial "+ mother + " " + father);

			Hediff_MechanoidPregnancy hediff = (Hediff_MechanoidPregnancy)HediffMaker.MakeHediff(HediffDef.Named("RJW_pregnancy_mech"), mother, torso);
			hediff.Initialize(mother, father);
		}
	}
}


code:
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using Verse;
using Multiplayer.API;

namespace rjw
{
	internal class Hediff_Parasite : Hediff_Pregnant
	{
		[SyncMethod]
		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(father.kindDef, father.Faction, PawnGenerationContext.NonPlayer, -1, false, true, false, false, true, false, 1f, false, true, true, false, false, false,false, 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 = 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.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();
				}
			}
		}
	}
}


code:
using System;
using System.Collections.Generic;
using System.Text;
using RimWorld;
using Verse;
using Multiplayer.API;

namespace rjw
{
	public static class AgeStage
	{
		public const int Baby = 0;
		public const int Toddler = 1;
		public const int Child = 2;
		public const int Teenager = 3;
		public const int Adult = 4;
	}

	public class Hediff_SimpleBaby : HediffWithComps
	{
		// Keeps track of what stage the pawn has grown to
		private int grown_to = 0;

		//Properties
		public int Grown_To
		{
			get
			{
				return grown_to;
			}
		}

		public override string DebugString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(base.DebugString());
			return stringBuilder.ToString();
		}

		public override void PostMake()
		{
			Severity = Math.Max(0, Severity);
			if (grown_to == 0 && !pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_NoManipulationFlag")))
			{
				pawn.health.AddHediff(HediffDef.Named("RJW_NoManipulationFlag"), null, null);
			}
			base.PostMake();
		}

		public override void ExposeData()
		{
			//Scribe_Values.LookValue<int> (ref grown_to, "grown_to", 0);
			Scribe_Values.Look<int>(ref grown_to, "grown_to", 0);

			base.ExposeData();
		}

		internal void GrowUpTo(int stage)
		{
			GrowUpTo(stage, true);
		}

		[SyncMethod]
		internal void GrowUpTo(int stage, bool generated)
		{
			//Rand.PopState();
			//Rand.PushState(RJW_Multiplayer.PredictableSeed());
			grown_to = stage;

			// Update the Colonist Bar
			PortraitsCache.SetDirty(pawn);
			pawn.Drawer.renderer.graphics.ResolveAllGraphics();

			// At the toddler stage. Now we can move and talk.
			if (stage == 1)
			{
				Severity = Math.Max(0.5f, Severity);
				//pawn.needs.food.
			}
			// Re-enable skills that were locked out from toddlers
			if (stage == 2)
			{
				if (!generated)
				{
					if (xxx.RimWorldChildrenIsActive)
					{
						pawn.story.childhood = BackstoryDatabase.allBackstories["CustomBackstory_Rimchild"];
					}
					// Remove the hidden hediff stopping pawns from manipulating
				}
				if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_NoManipulationFlag")))
				{
					pawn.health.hediffSet.hediffs.Remove(pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_NoManipulationFlag")));
				}
				Severity = Math.Max(0.75f, Severity);
			}
			// The child has grown to a teenager so we no longer need this effect
			if (stage == 3)
			{
				if (!generated && pawn.story.childhood.title == "Child")
				{
					if (xxx.RimWorldChildrenIsActive)
					{
						pawn.story.childhood = BackstoryDatabase.allBackstories["CustomBackstory_Rimchild"];
					}
				}

				// Gain traits from life experiences
				if (pawn.story.traits.allTraits.Count < 3)
				{
					List<Trait> life_traitpool = new List<Trait>();
					// Try get cannibalism
					if (pawn.needs.mood.thoughts.memories.Memories.Find(x => x.def == ThoughtDefOf.AteHumanlikeMeatAsIngredient) != null)
					{
						life_traitpool.Add(new Trait(TraitDefOf.Cannibal, 0, false));
					}
					// Try to get bloodlust
					if (pawn.records.GetValue(RecordDefOf.KillsHumanlikes) > 0 || pawn.records.GetValue(RecordDefOf.AnimalsSlaughtered) >= 2)
					{
						life_traitpool.Add(new Trait(TraitDefOf.Bloodlust, 0, false));
					}
					// Try to get shooting accuracy
					if (pawn.records.GetValue(RecordDefOf.ShotsFired) > 100 && (int)pawn.records.GetValue(RecordDefOf.PawnsDowned) > 0)
					{
						life_traitpool.Add(new Trait(TraitDef.Named("ShootingAccuracy"), 1, false));
					}
					else if (pawn.records.GetValue(RecordDefOf.ShotsFired) > 100 && (int)pawn.records.GetValue(RecordDefOf.PawnsDowned) == 0)
					{
						life_traitpool.Add(new Trait(TraitDef.Named("ShootingAccuracy"), -1, false));
					}
					// Try to get brawler
					else if (pawn.records.GetValue(RecordDefOf.ShotsFired) < 15 && pawn.records.GetValue(RecordDefOf.PawnsDowned) > 1)
					{
						life_traitpool.Add(new Trait(TraitDefOf.Brawler, 0, false));
					}
					// Try to get necrophiliac
					if (pawn.records.GetValue(RecordDefOf.CorpsesBuried) > 50)
					{
						life_traitpool.Add(new Trait(xxx.necrophiliac, 0, false));
					}
					// Try to get nymphomaniac
					if (pawn.records.GetValue(RecordDefOf.BodiesStripped) > 50)
					{
						life_traitpool.Add(new Trait(xxx.nymphomaniac, 0, false));
					}
					// Try to get rapist
					if (pawn.records.GetValue(RecordDefOf.TimeAsPrisoner) > 300)
					{
						life_traitpool.Add(new Trait(xxx.rapist, 0, false));
					}
					// Try to get Dislikes Men/Women
					int male_rivals = 0;
					int female_rivals = 0;
					foreach (Pawn colinist in Find.AnyPlayerHomeMap.mapPawns.AllPawnsSpawned)
					{
						if (pawn.relations.OpinionOf(colinist) <= -20)
						{
							if (colinist.gender == Gender.Male)
								male_rivals++;
							else
								female_rivals++;
						}
					}
					// Find which gender we hate
					if (male_rivals > 3 || female_rivals > 3)
					{
						if (male_rivals > female_rivals)
							life_traitpool.Add(new Trait(TraitDefOf.DislikesMen, 0, false));
						else if (female_rivals > male_rivals)
							life_traitpool.Add(new Trait(TraitDefOf.DislikesWomen, 0, false));
					}
					// Pyromaniac never put out any fires. Seems kinda stupid
					/*if ((int)pawn.records.GetValue (RecordDefOf.FiresExtinguished) == 0) {
						life_traitpool.Add (new Trait (TraitDefOf.Pyromaniac, 0, false));
					}*/
					// Neurotic
					if (pawn.records.GetValue(RecordDefOf.TimesInMentalState) > 6)
					{
						life_traitpool.Add(new Trait(TraitDef.Named("Neurotic"), 2, false));
					}
					else if (pawn.records.GetValue(RecordDefOf.TimesInMentalState) > 3)
					{
						life_traitpool.Add(new Trait(TraitDef.Named("Neurotic"), 1, false));
					}

					// People(male or female) can turn gay during puberty
					//Rand.PopState();
					//Rand.PushState(RJW_Multiplayer.PredictableSeed());
					if (Rand.Value <= 0.03f && pawn.story.traits.allTraits.Count <= 3)
					{
						pawn.story.traits.GainTrait(new Trait(TraitDefOf.Gay, 0, true));
					}

					// Now let's try to add some life experience traits
					if (life_traitpool.Count > 0)
					{
						int i = 3;
						while (pawn.story.traits.allTraits.Count < 3 && i > 0)
						{
							Trait newtrait = life_traitpool.RandomElement();
							if (pawn.story.traits.HasTrait(newtrait.def) == false)
								pawn.story.traits.GainTrait(newtrait);
							i--;
						}
					}
				}

				pawn.health.RemoveHediff(this);
			}
		}

		public void TickRare()
		{
			//--Log.Message("[RJW]Hediff_SimpleBaby::TickRare is called");
			if (pawn.ageTracker.CurLifeStageIndex > Grown_To)
			{
				GrowUpTo(Grown_To + 1, false);
			}
			// Update the graphics set
			if (pawn.ageTracker.CurLifeStageIndex == AgeStage.Toddler)
				pawn.Drawer.renderer.graphics.ResolveAllGraphics();
			if (xxx.RimWorldChildrenIsActive)
			{
				//if (Prefs.DevMode)
				//	Log.Message("RJW child tick - CnP active");
				//we do not disable our hediff anymore
	//			if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_NoManipulationFlag")))
				//{
				//	pawn.health.hediffSet.hediffs.Remove(pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_NoManipulationFlag")));
				//	pawn.health.AddHediff(HediffDef.Named("NoManipulationFlag"), null, null);
				//}
				//if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_BabyState")))
				//{
				//	pawn.health.hediffSet.hediffs.Remove(pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_BabyState")));
				//	pawn.health.AddHediff(HediffDef.Named("BabyState"), null, null);
	//				if (Prefs.DevMode) Log.Message("RJW_Babystate self-removing");
	//			}
				if (pawn.ageTracker.CurLifeStageIndex <= 1)
				{   //The UnhappBaby feature is not included in RJW, but will
					// Check if the baby is hungry, and if so, add the whiny baby hediff
					var hunger = pawn.needs.food;
					var joy = pawn.needs.joy;
					if ((joy != null)&&(hunger!=null))
					{ //There's no way to patch out the CnP adressing nill fields
						if (hunger.CurLevelPercentage<hunger.PercentageThreshHungry || joy.CurLevelPercentage <0.1)
						{
							if (!pawn.health.hediffSet.HasHediff(HediffDef.Named("UnhappyBaby"))){
								//--Log.Message("Adding unhappy baby hediff");
								pawn.health.AddHediff(HediffDef.Named("UnhappyBaby"), null, null);
							}
						}
					}
				}
			}
		}

		public override void PostTick()
		{
			/*
			if (xxx.RimWorldChildrenIsActive)
			{
				if (pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_BabyState"))!=null)
				{
					pawn.health.RemoveHediff(this);
				}
				return;
			}
			*/
			//This void call every frame. should not logmes no reason
			//--Log.Message("[RJW]Hediff_SimpleBaby::PostTick is called");
			base.PostTick();
			if (pawn.Spawned)
			{
				if (pawn.IsHashIntervalTick(120))
				{
					TickRare();
				}
			}
		}

		public override bool Visible
		{
			get { return false; }
		}
	}
}


code:
using RimWorld;
using Verse;
using System;
using System.Linq;
using System.Collections.Generic;
using Multiplayer.API;

///RimWorldChildren pregnancy:
//using RimWorldChildren;

namespace rjw
{
	///
	/// This handles pregnancy chosing between different types of pregnancy awailable to it
	/// 1a:RimWorldChildren pregnancy for humanlikes
	/// 1b:RJW pregnancy for humanlikes
	/// 2:RJW pregnancy for bestiality
	/// 3:RJW pregnancy for insects
	/// 4:RJW pregnancy for mechanoids
	///

	public static class PregnancyHelper
	{
		//called by aftersex (including rape, breed, etc)
		//called by mcevent
		private static readonly HashSet<string> Pregnancy_filter = new HashSet<string>(DefDatabase<StringListDef>.GetNamed("Pregnancy_filter").strings);
		public static readonly HashSet<String> EggRace_filter = new HashSet<string>(DefDatabase<StringListDef>.GetNamed("EggRace_filter").strings);

		//pawn - "father"; partner = mother
		public static void impregnate(Pawn pawn, Pawn partner, xxx.rjwSextype sextype = xxx.rjwSextype.None)
		{

			if (RJWSettings.DevMode) Log.Message("Rimjobworld::impregnate(" + sextype + "):: " + xxx.get_pawnname(pawn) + " + " + xxx.get_pawnname(partner) + ":");

			//"mech" pregnancy
			if (sextype == xxx.rjwSextype.MechImplant)
			{
				if (RJWPregnancySettings.mechanoid_enabled)
				{
					if (RJWSettings.DevMode) Log.Message(" mechanoid pregnancy");

					//new pregnancy
						Hediff_MechanoidPregnancy.Create(partner, pawn);
						Hediff_MechanoidPregnancy hediff = (Hediff_MechanoidPregnancy)partner.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_mech"));
						if (RJWSettings.DevMode) Log.Message("[RJW] removing other pregnancies");
						if (partner.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy")))
						partner.health.RemoveHediff(partner.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy")));
						if (partner.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_beast")))
						partner.health.RemoveHediff(partner.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_beast")));
						if (partner.health.hediffSet.HasHediff(HediffDef.Named("Pregnant")))
						partner.health.RemoveHediff(partner.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Pregnant")));
						return;
					// Not an actual pregnancy. This implants mechanoid tech into the target.
					//may lead to pregnancy
					//old  "chip pregnancies", maybe integrate them somehow?
					//Rand.PopState();
					//Rand.PushState(RJW_Multiplayer.PredictableSeed());
					HediffDef_MechImplants egg = (from x in DefDatabase<HediffDef_MechImplants>.AllDefs	select x).RandomElement();
					if (egg != null)
					{
						if (RJWSettings.DevMode) Log.Message(" planting MechImplants:" + egg.ToString());
						PlantSomething(egg, partner, !Genital_Helper.has_vagina(partner), 1);
						return;
					}
					else
					{
						if (RJWSettings.DevMode) Log.Message(" no mech implant found");
					}
				}
				return;
			}

			// Sextype can result in pregnancy.
			if (!(sextype == xxx.rjwSextype.Vaginal || sextype == xxx.rjwSextype.DoublePenetration))
				return;

			//"insect" pregnancy
			//straight, female (partner) recives egg insertion from other/sex starter (pawn)
			if (Genital_Helper.has_vagina(partner) &&
					(Genital_Helper.has_ovipositorF(pawn) ||
						(Genital_Helper.has_ovipositorM(pawn) ||
							(Genital_Helper.has_penis(pawn) && EggRace_filter.Contains(pawn.kindDef.race.defName))))
				)
			{
				DoEgg(pawn, partner);
				return;
			}
			//reverse, female (pawn) starts sex/passive bestiality and fills herself with eggs - this is likely fucked up and needs fixing at jobdriver, processsex and aftersex levels
			else
			if (Genital_Helper.has_vagina(pawn) &&
					(Genital_Helper.has_ovipositorF(partner) ||
						(Genital_Helper.has_ovipositorM(partner) ||
							(Genital_Helper.has_penis(partner) && EggRace_filter.Contains(partner.kindDef.race.defName))))
				)
			{
				DoEgg(partner, pawn);
				return;
			}

			//"normal" and "beastial" pregnancy
			if (RJWSettings.DevMode) Log.Message(" 'normal' pregnancy checks");

			//futa-futa docking?
			//if (CanImpregnate(partner, pawn, sextype) && CanImpregnate(pawn, partner, sextype))
			//{
			//Log.Message("[RJW] futa-futa docking...");
			//return;
			//Doimpregnate(pawn, partner);
			//Doimpregnate(partner, pawn);
			//}
			//normal, when female is passive/recives interaction
			if (Genital_Helper.has_penis(pawn) && Genital_Helper.has_vagina(partner) && CanImpregnate(pawn, partner, sextype))
			{
				if (RJWSettings.DevMode) Log.Message(" impregnate forward");
				Doimpregnate(pawn, partner);
			}
			//reverse, when female active/starts interaction
			else if (Genital_Helper.has_vagina(pawn) && Genital_Helper.has_penis(partner) && CanImpregnate(partner, pawn, sextype))
			{
				if (RJWSettings.DevMode) Log.Message(" impregnate reverse");
				Doimpregnate(partner, pawn);
			}
		}

		///Can get preg with above conditions, do impregnation.

		[SyncMethod]
		public static void DoEgg(Pawn pawn, Pawn partner)
		{
			if (RJWPregnancySettings.insect_pregnancy_enabled)
			{
				if (RJWSettings.DevMode) Log.Message(" insect pregnancy");

				//female "insect" plant eggs
				if (Genital_Helper.has_ovipositorF(pawn))
				{
					float maxeggssize = partner.BodySize * (xxx.has_quirk(partner, "Incubator") ? 2f : 1f) * (Genital_Helper.has_ovipositorF(partner) ? 2f : 0.5f);
					float eggedsize = 0;
					foreach (Hediff_InsectEgg egg in partner.health.hediffSet.GetHediffs<Hediff_InsectEgg>())
					{
						eggedsize += egg.queen.RaceProps.baseBodySize / 5 * ((HediffDef_InsectEgg)egg.def).eggsize;
					}
					if (RJWSettings.DevMode) Log.Message(" determine " + xxx.get_pawnname(partner) + " size of eggs inside: " + eggedsize + " (max) " + maxeggssize);
					if (eggedsize < maxeggssize)
					{
						string defname = ((xxx.is_human(pawn) || !xxx.is_insect(pawn)) && !EggRace_filter.Contains(pawn.kindDef.race.defName)) ? "Megascarab" : pawn.def.defName;
						float eggssize = ((xxx.is_human(pawn) || !xxx.is_insect(pawn)) && !EggRace_filter.Contains(pawn.kindDef.race.defName)) ? 0.04f : pawn.RaceProps.baseBodySize / 5;
						//TODO: move "Megascarab" to InsectEgg and rework heddif, so it defaults to Megascarab if not insect
						//once there is some sort of genetic inheritance form parts/ovis
						//Rand.PopState();
						//Rand.PushState(RJW_Multiplayer.PredictableSeed());
						HediffDef_InsectEgg egg = (from x in DefDatabase<HediffDef_InsectEgg>.AllDefs where x.IsParent(defname) select x).RandomElement();
						if (egg != null)
						{
							int count;
							float maxeggs = 100;
							float mineggs = 0;
							if (egg.eggsize != 0)
							{
								maxeggs = ((maxeggssize - eggedsize) / eggssize);
								if (RJWSettings.DevMode) Log.Message(" max eggs: " + maxeggs);
							}
							if (maxeggs >= 1)
								mineggs = 1;

							count = Rand.Range((int)mineggs, (int)(maxeggs));

							if (RJWSettings.DevMode) Log.Message(" planting eggs: " + egg.ToString() + " (" + count + ")");

							PlantSomething(egg, partner, false, count);

							//set implanter/queen
							foreach (var egg1 in (from x in partner.health.hediffSet.GetHediffs<Hediff_InsectEgg>() where x.IsParent(defname) select x))
							{
								if (egg1.queen == null)
								{
									if (RJWSettings.DevMode) Log.Message(" set implanter/queen:" + xxx.get_pawnname(pawn));
									egg1.Implanter(pawn);
								}
							}

							if (!pawn.IsColonist)
								if (!partner.health.hediffSet.HasHediff(HediffDef.Named("RJW_Cocoon")) && partner.Faction != pawn.Faction)
									partner.health.AddHediff(HediffDef.Named("RJW_Cocoon"));
						}
					}
				}
				//male "insect" fertilize eggs
				else if (!pawn.health.hediffSet.HasHediff(xxx.sterilized))
				{
					foreach (var egg in (from x in partner.health.hediffSet.GetHediffs<Hediff_InsectEgg>() where x.IsParent(pawn.def.defName) select x))
					{
						if (!egg.fertilized)
						{
							if (RJWSettings.DevMode) Log.Message(xxx.get_pawnname(pawn) + " fertilize eggs:" + egg.ToString());
							egg.Fertilize(pawn);
						}
					}
				}
				return;
			}
		}

		[SyncMethod]
		public static void Doimpregnate(Pawn pawn, Pawn partner)
		{
			if (RJWSettings.DevMode) Log.Message("[RJW] Doimpregnate " + xxx.get_pawnname(pawn) + " is a father, " + xxx.get_pawnname(partner) + " is a mother");
			// fertility check
			float fertility = RJWPregnancySettings.humanlike_impregnation_chance / 100f;
			if (xxx.is_animal(partner))
				fertility = RJWPregnancySettings.animal_impregnation_chance / 100f;

			// Interspecies modifier
			if (pawn.def.defName != partner.def.defName)
			{
				if (RJWPregnancySettings.complex_interspecies)
					fertility *= SexUtility.BodySimilarity(pawn, partner);
				else
					fertility *= RJWPregnancySettings.interspecies_impregnation_modifier;
			}

			//Rand.PopState();
			//Rand.PushState(RJW_Multiplayer.PredictableSeed());
			float ReproductionFactor = Math.Min(pawn.health.capacities.GetLevel(xxx.reproduction), partner.health.capacities.GetLevel(xxx.reproduction));
			float pregnancy_threshold = fertility * ReproductionFactor;
			float non_pregnancy_chance = Rand.Value;
			BodyPartRecord torso = partner.RaceProps.body.AllParts.Find(x => x.def == BodyPartDefOf.Torso);

			if (non_pregnancy_chance > pregnancy_threshold || pregnancy_threshold == 0)
			{
				if (RJWSettings.DevMode) Log.Message("[RJW] Impregnation failed. Chance: " + pregnancy_threshold.ToStringPercent() + " fail roll: " + non_pregnancy_chance.ToStringPercent());
				return;
			}
			if (RJWSettings.DevMode) Log.Message("[RJW] Impregnation succeeded. Chance: " + pregnancy_threshold.ToStringPercent() + " succeess roll: " + non_pregnancy_chance.ToStringPercent());

			PregnancyDecider(partner, pawn);
		}

		///For checking normal pregnancy, should not for egg implantion or such.
		public static bool CanImpregnate(Pawn fucker, Pawn fucked, xxx.rjwSextype sextype = xxx.rjwSextype.Vaginal)
		{
			if (fucker == null || fucked == null) return false;

			if (RJWSettings.DevMode) Log.Message("Rimjobworld::CanImpregnate(" + sextype + "):: " + xxx.get_pawnname(fucker) + " + " + xxx.get_pawnname(fucked) + ":");

			if (sextype == xxx.rjwSextype.MechImplant && !RJWPregnancySettings.mechanoid_enabled)
			{
				if (RJWSettings.DevMode) Log.Message(" mechanoid 'pregnancy' disabled");
				return false;
			}

			if (!(sextype == xxx.rjwSextype.Vaginal || sextype == xxx.rjwSextype.DoublePenetration))
			{
				if (RJWSettings.DevMode) Log.Message(" sextype cannot result in pregnancy");
				return false;
			}

			// TODO: Add fertility nullifiers for undead.
			if (PregnancyHelper.Pregnancy_filter.Contains(fucker.kindDef.defName) ||
				(xxx.RoMIsActive && (fucked.health.hediffSet.HasHediff(HediffDef.Named("TM_UndeadHD")) || fucked.health.hediffSet.HasHediff(HediffDef.Named("TM_UndeadAnimalHD")))))
			{
				if (RJWSettings.DevMode) Log.Message(xxx.get_pawnname(fucked) + " filtered race that cant be pregnant");
				return false;
			}

			if (PregnancyHelper.Pregnancy_filter.Contains(fucked.kindDef.defName) ||
				(xxx.RoMIsActive && (fucker.health.hediffSet.HasHediff(HediffDef.Named("TM_UndeadHD")) || fucker.health.hediffSet.HasHediff(HediffDef.Named("TM_UndeadAnimalHD")))))
			{
				if (RJWSettings.DevMode) Log.Message(xxx.get_pawnname(fucker) + " filtered race that cant impregnate");
				return false;
			}

			if (fucked.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy")) ||
				fucked.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_beast")) ||
				fucked.health.hediffSet.HasHediff(HediffDef.Named("Pregnant")))
			{
				if (RJWSettings.DevMode) Log.Message(" already pregnant.");
				return false;
			}

			if ((from x in fucked.health.hediffSet.GetHediffs<Hediff_InsectEgg>() where x.def == DefDatabase<HediffDef_InsectEgg>.GetNamed(x.def.defName) select x).Any())
			{
				if (RJWSettings.DevMode) Log.Message(xxx.get_pawnname(fucked) + " cant get pregnant while eggs inside");
				return false;
			}

			if (!(Genital_Helper.has_penis(fucker) && Genital_Helper.has_vagina(fucked)) && !(Genital_Helper.has_penis(fucked) && Genital_Helper.has_vagina(fucker)))
			{
				if (RJWSettings.DevMode) Log.Message(" missing genitals for impregnation");
				return false;
			}

			if (fucker.health.capacities.GetLevel(xxx.reproduction) <= 0 || fucked.health.capacities.GetLevel(xxx.reproduction) <= 0)
			{
				if (RJWSettings.DevMode) Log.Message(" one (or both) pawn(s) infertile");
				return false;
			}

			if (xxx.is_human(fucked) && xxx.is_human(fucker) && (RJWPregnancySettings.humanlike_impregnation_chance == 0 || !RJWPregnancySettings.humanlike_pregnancy_enabled))
			{
				if (RJWSettings.DevMode) Log.Message(" human pregnancy chance set to 0% or pregnancy disabled.");
				return false;
			}
			else if (((xxx.is_animal(fucker) && xxx.is_human(fucked)) || (xxx.is_human(fucker) && xxx.is_animal(fucked))) && !RJWPregnancySettings.bestial_pregnancy_enabled)
			{
				if (RJWSettings.DevMode) Log.Message(" bestiality pregnancy chance set to 0% or pregnancy disabled.");
				return false;
			}
			else if (xxx.is_animal(fucked) && xxx.is_animal(fucker) && (RJWPregnancySettings.animal_impregnation_chance == 0 || !RJWPregnancySettings.animal_pregnancy_enabled))
			{
				if (RJWSettings.DevMode) Log.Message(" animal-animal pregnancy chance set to 0% or pregnancy disabled.");
				return false;
			}
			else if (fucker.def.defName != fucked.def.defName && (RJWPregnancySettings.interspecies_impregnation_modifier <= 0.0f && !RJWPregnancySettings.complex_interspecies))
			{
				if (RJWSettings.DevMode) Log.Message(" interspecies pregnancy disabled.");
				return false;
			}

			return true;
		}

		//Plant babies for human/bestiality pregnancy
		public static void PregnancyDecider(Pawn mother, Pawn father)
		{
			//human-human
			if (RJWPregnancySettings.humanlike_pregnancy_enabled && xxx.is_human(mother) && xxx.is_human(father))
			{
				Hediff_HumanlikePregnancy.Create(mother, father);
			}
			//human-animal
			//maybe make separate option for human males vs female animals???
			else if (RJWPregnancySettings.bestial_pregnancy_enabled && ((xxx.is_human(mother) && xxx.is_animal(father)) || (xxx.is_animal(mother) && xxx.is_human(father))))
			{
				Hediff_BestialPregnancy.Create(mother, father);
			}
			//animal-animal
			else if (xxx.is_animal(mother) && xxx.is_animal(father))
			{
				CompEggLayer compEggLayer = mother.TryGetComp<CompEggLayer>();
				// fertilize eggs of same species
				if (compEggLayer != null)
				{
					if (mother.kindDef == father.kindDef)
						compEggLayer.Fertilize(father);
				}
				else if (RJWPregnancySettings.animal_pregnancy_enabled)
				{
					Hediff_BestialPregnancy.Create(mother, father);
				}
			}
		}

		//Plant Insect eggs/mech chips/other preg mod hediff?
		public static bool PlantSomething(HediffDef def, Pawn target, bool isToAnal = false, int amount = 1)
		{
			if (def == null)
				return false;
			if (!isToAnal && !Genital_Helper.has_vagina(target))
				return false;
			if (isToAnal && !Genital_Helper.has_anus(target))
				return false;

			BodyPartRecord Part = (isToAnal) ? Genital_Helper.get_anus(target) : Genital_Helper.get_genitals(target);
			if (Part != null || Part.parts.Count != 0)
			{
				for (int i = 0; i < amount; i++)
				{
					if (RJWSettings.DevMode) Log.Message("[RJW] planting something weird");
					target.health.AddHediff(def, Part);
				}

				//killoff normal preg
				if (!isToAnal)
				{
					if (RJWSettings.DevMode) Log.Message("[RJW] removing other pregnancies");
					if (target.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy")))
						target.health.RemoveHediff(target.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy")));
					if (target.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_beast")))
						target.health.RemoveHediff(target.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_beast")));
					if (target.health.hediffSet.HasHediff(HediffDef.Named("Pregnant")))
						target.health.RemoveHediff(target.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Pregnant")));
				}

				return true;
			}
			return false;
		}

		///
		/// Remove CnP Pregnancy, that is added without passing rjw checks
		///
		public static void cleanup_CnP(Pawn pawn)
		{
			//They do subpar probability checks and disrespect our settings, but I fail to just prevent their doloving override.
			//probably needs harmonypatch
			//So I remove the hediff if it is created and recreate it if needed in our handler later

			if (Prefs.DevMode) Log.Message("[RJW] cleanup_CnP after love check");

			var h = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("HumanPregnancy"));
			if (h != null && h.ageTicks < 10) {
				pawn.health.RemoveHediff(h);
				if (Prefs.DevMode) Log.Message("[RJW] removed hediff from " + xxx.get_pawnname(pawn));
			}
		}

		///
		/// Remove Vanilla Pregnancy
		///
		public static void cleanup_vanilla(Pawn pawn)
		{
			if (Prefs.DevMode) Log.Message("[RJW] cleanup_vanilla after love check");

			var h = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Pregnant"));
			if (h != null && h.ageTicks < 10) {
				pawn.health.RemoveHediff(h);
				if (Prefs.DevMode) Log.Message("[RJW] removed hediff from " + xxx.get_pawnname(pawn));
			}
		}

		///
		/// Below is stuff for RimWorldChildren
		/// its not used, we rely only on our own pregnancies
		///

		///
		/// This function tries to call Children and pregnancy utilities to see if that mod could handle the pregnancy
		///
		/// <returns>true if cnp pregnancy will work, false if rjw one should be used instead</returns>
		public static bool CnP_WillAccept(Pawn mother)
		{
			if (!xxx.RimWorldChildrenIsActive)
				return false;

			return RimWorldChildren.ChildrenUtility.RaceUsesChildren(mother);
		}

		///
		/// This funtcion tries to call Children and Pregnancy to create humanlike pregnancy implemented by the said mod.
		///
		public static void CnP_DoPreg(Pawn mother, Pawn father)
		{
			if (!xxx.RimWorldChildrenIsActive)
                return;

            RimWorldChildren.Hediff_HumanPregnancy.Create(mother, father);
        }

	}
}


code:
using RimWorld;
using System;
using Verse;
using System.Collections.Generic;

namespace rjw
{
    public class Recipe_Abortion : Recipe_RemoveHediff
	{

		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipe)
		{
			BodyPartRecord part = pawn.RaceProps.body.corePart;
			if (recipe.appliedOnFixedBodyParts[0] != null)
				part = pawn.RaceProps.body.AllParts.Find(x => x.def == recipe.appliedOnFixedBodyParts[0]);
			if (part != null)
			{
				if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy"), true) && recipe.removesHediff == HediffDef.Named("RJW_pregnancy"))
				{
					Hediff_HumanlikePregnancy pregnancy = (Hediff_HumanlikePregnancy)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy"));
					if (pregnancy.is_checked)
						yield return part;
				}

				else if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_beast"), true) && recipe.removesHediff == HediffDef.Named("RJW_pregnancy_beast"))
				{
					Hediff_BestialPregnancy pregnancy = (Hediff_BestialPregnancy)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_beast"));
					if (pregnancy.is_checked)
						yield return part;
				}

				else if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_mech"), true) && recipe.removesHediff == HediffDef.Named("RJW_pregnancy_mech"))
				{
					Hediff_MechanoidPregnancy pregnancy = (Hediff_MechanoidPregnancy)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_mech"));
					if (pregnancy.is_checked)
						yield return part;
				}
			}
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_ClaimChild :  RecipeWorker
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipe)
		{
			if (pawn != null)//I have no idea how it works but Recipe_ShutDown : RecipeWorker does not return values when not applicable
			{
				//Log.Message("RJW Claim child check on " + pawn);
				if (xxx.is_human(pawn) && !pawn.IsColonist)
				{
					if ( (pawn.ageTracker.CurLifeStageIndex < 2))//Guess it is hardcoded for now to `baby` and `toddler` of standard 4 stages of human life
					{
						BodyPartRecord brain = pawn.health.hediffSet.GetBrain();
						if (brain != null)
						{
							//Log.Message("RJW Claim child is applicable");
							yield return brain;
						}
					}
				}
			}
		}

		public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List<Thing> ingredients, Bill bill)
		{
			if (pawn == null)
			{
				Log.Error("Error applying medical recipe, pawn is null");
				return;
			}
			pawn.SetFaction(Faction.OfPlayer);
			//we could do
			//pawn.SetFaction(billDoer.Faction);
			//but that is useless because GetPartsToApplyOn does not support factions anyway and all recipes are hardcoded to player.
		}
	}
}


code:
using RimWorld;
using System;
using Verse;
using System.Collections.Generic;

namespace rjw
{
    public class Recipe_DeterminePregnancy : RecipeWorker
    {
        public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipe)
        {
			/* Males can be impregnated by mechanoids, probably
			if (!xxx.is_female(pawn))
			{
				yield break;
			}
			*/
			BodyPartRecord part = pawn.RaceProps.body.corePart;
            if (recipe.appliedOnFixedBodyParts[0] != null)
                part = pawn.RaceProps.body.AllParts.Find(x => x.def == recipe.appliedOnFixedBodyParts[0]);
			if (part != null && (pawn.ageTracker.CurLifeStage.reproductive)
				|| pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy"), true)
				|| pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_beast"), true)
				|| pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_mech"), true)
				)
			{
				yield return part;
			}
        }

        public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List<Thing> ingredients, Bill bill)
        {
            if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy")))
            {
                Hediff_HumanlikePregnancy pregnancy = (Hediff_HumanlikePregnancy)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy"));
				pregnancy.CheckPregnancy();
            }

            else if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_beast")))
            {
                Hediff_BestialPregnancy pregnancy = (Hediff_BestialPregnancy)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_beast"));
				pregnancy.CheckPregnancy();
            }

            else if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_mech")))
            {
                Hediff_MechanoidPregnancy pregnancy = (Hediff_MechanoidPregnancy)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_mech"));
				pregnancy.CheckPregnancy();
            }

            else
            {
                Messages.Message(xxx.get_pawnname(billDoer) + " has determined " + xxx.get_pawnname(pawn) + " is not pregnant.", MessageTypeDefOf.NeutralEvent);
            }
        }
    }
}


code:
using System.Collections.Generic;
using Verse;

namespace rjw
{
	/// <summary>
	/// IUD - prevent pregnancy
	/// </summary>
	public class Recipe_InstallIUD : Recipe_InstallImplantToExistParts
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipe)
		{
			if (!xxx.is_female(pawn))
			{
				return new List<BodyPartRecord>();
			}
			return base.GetPartsToApplyOn(pawn, recipe);
		}
	}
}


code:
using RimWorld;
using System;
using Verse;
using System.Collections.Generic;

namespace rjw
{
    public class Recipe_PregnancyHackMech : RecipeWorker
    {
        public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipe)
        {
            BodyPartRecord part = pawn.RaceProps.body.corePart;
            if (recipe.appliedOnFixedBodyParts[0] != null)
                part = pawn.RaceProps.body.AllParts.Find(x => x.def == recipe.appliedOnFixedBodyParts[0]);
			if (part != null && pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_mech"), part, true))
			{
				Hediff_MechanoidPregnancy pregnancy = (Hediff_MechanoidPregnancy)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_mech"));
				//Log.Message("RJW_pregnancy_mech hack check: " + pregnancy.is_checked);
				if (pregnancy.is_checked)
					yield return part;
			}
        }

        public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List<Thing> ingredients, Bill bill)
        {

            if (pawn.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_mech")))
            {
                Hediff_MechanoidPregnancy pregnancy = (Hediff_MechanoidPregnancy)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_mech"));
				pregnancy.Hack();
            }
        }
    }
}


code:
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using Verse;

namespace rjw
{
	/// <summary>
	/// Sterilization
	/// </summary>
	public class Recipe_InstallImplantToExistParts : Recipe_InstallImplant
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipe)
		{
			bool blocked = Genital_Helper.genitals_blocked(pawn) || xxx.is_slime(pawn);

			if (!blocked)
				foreach (BodyPartRecord record in pawn.RaceProps.body.AllParts.Where(x => recipe.appliedOnFixedBodyParts.Contains(x.def)))
				{
					if (!pawn.health.hediffSet.hediffs.Any((Hediff x) => x.def == recipe.addsHediff))
					{
						yield return record;
					}
				}
		}
	}
}


code:
using RimWorld;
using Verse;

namespace rjw
{
	public class ThoughtWorker_ItchyCrotch : ThoughtWorker
	{
		protected override ThoughtState CurrentStateInternal(Pawn p)
		{
			int sev = std.genital_rash_severity(p);
			if (sev <= 0)
				return ThoughtState.Inactive;
			else if (sev == 1)
				return ThoughtState.ActiveAtStage(0);
			else
				return ThoughtState.ActiveAtStage(1);
		}
	}
}


code:
using RimWorld;
using Verse;

namespace rjw
{
	public class ThoughtWorker_SyphiliticThoughts : ThoughtWorker
	{
		protected override ThoughtState CurrentStateInternal(Pawn p)
		{
			//Log.Message("0");
			var syp = p.health.hediffSet.GetFirstHediffOfDef(std.syphilis.hediff_def);
			//Log.Message("1");
			if (syp != null)
			{
				//Log.Message("2");
				if (syp.Severity >= 0.80f)
				{
					//Log.Message("3");
					return ThoughtState.ActiveAtStage(1);
				}
				else if (syp.Severity >= 0.50f)
				{
					//Log.Message("4");
					return ThoughtState.ActiveAtStage(0);
				}
				//Log.Message("5");
			}
			//Log.Message("6");
			return ThoughtState.Inactive;
		}
	}
}


code:
using RimWorld;
using Verse;

namespace rjw
{
	public class ThoughtWorker_WastingAway : ThoughtWorker
	{
		protected override ThoughtState CurrentStateInternal(Pawn p)
		{
			if (!std.is_wasting_away(p))
				return ThoughtState.Inactive;
			else
				return ThoughtState.ActiveAtStage(0);
		}
	}
}