diff --git a/devTools/javaSanityCheck/ignoredVariables b/devTools/javaSanityCheck/ignoredVariables
index e282a23f8d92e433ce944f875bdf8ce55ef1309b..0e6cbe638bb2b6d26b98134a0fdb65ec6598b5ae 100644
--- a/devTools/javaSanityCheck/ignoredVariables
+++ b/devTools/javaSanityCheck/ignoredVariables
@@ -40,7 +40,6 @@ firstChild
 true
 missingLegs;missingArms;
 toy
-saRules
 plural
 bimboMaleNames
 RuleHasError
diff --git a/devTools/types/FC/human.d.ts b/devTools/types/FC/human.d.ts
index d30ac1dd6e352eacf55fb3f5a2cf3d4e7989eca5..4ab7343d54c56a9c59cc5ac857d7bf999eebe42d 100644
--- a/devTools/types/FC/human.d.ts
+++ b/devTools/types/FC/human.d.ts
@@ -382,22 +382,6 @@ declare global {
 			spermY: number;
 			inbreedingCoeff?: number;
 		}
-		interface Fetus {
-			ID: string;
-			/** initial age */
-			age: number;
-			/** initial real age (first week in mother) */
-			realAge: number;
-			motherID: number;
-			/** We can store who is father too. */
-			fatherID: number;
-			volume: number;
-			reserve: string;
-			identical: number;
-			splitted?: number;
-			twinID?: string;
-			genetics?: FetusGenetics;
-		}
 		//#endregion
 
 		type LimbState = InstanceType<typeof App.Entity.LimbState>;
diff --git a/src/descriptions/arcologyDescription.js b/src/descriptions/arcologyDescription.js
index 2efc51fbbbc81ae5cb781cdefc28170291b68694..ca595e1aa34322a997dc4f014a652b6a13a1512d 100644
--- a/src/descriptions/arcologyDescription.js
+++ b/src/descriptions/arcologyDescription.js
@@ -59,13 +59,13 @@ App.Desc.playerArcology = function(lastElement) {
 		} else if (V.weatherToday.name === "Gentle Snow") {
 			buffer.push(`It's a beautiful snowy day outside. The arcology has a gorgeous sheet of pure white snow and you can see a few jolly-looking snowmen built in the brisk chill. Citizens are wearing light furs and drinking hot coffee in the lovely weather.`);
 		} else if (V.weatherToday.severity === 1 && V.weatherType === 1) {
-			buffer.push (`It's a lovely, warm day today and plenty of people are outside enjoying the nice weather while it lasts in skimpier clothing than usual.`)
+			buffer.push(`It's a lovely, warm day today and plenty of people are outside enjoying the nice weather while it lasts in skimpier clothing than usual.`);
 		} else if (V.weatherToday.severity === 1 && V.weatherType === 5) {
-			buffer.push (`It's a cozy, brisk day today, and many citizens are carrying cups of steaming coffee, hot chocolate, and more esoteric drinks to warm themselves while they're out and about.`)
+			buffer.push(`It's a cozy, brisk day today, and many citizens are carrying cups of steaming coffee, hot chocolate, and more esoteric drinks to warm themselves while they're out and about.`);
 		} else if (V.weatherToday.severity === 1) {
-			buffer.push (`It's a nice day out today despite everything going on in the world, and plenty of citizens are outside enjoying the pleasant weather while it's here.`)
+			buffer.push(`It's a nice day out today despite everything going on in the world, and plenty of citizens are outside enjoying the pleasant weather while it's here.`);
 		} else if (V.weatherToday.name === "Light T-Storms") {
-			buffer.push(`It's a thundering downpour today. The cracks of loud thunder occassionally make someone jump with surprise, but people still soldier on in raincoats and umbrellas.`);
+			buffer.push(`It's a thundering downpour today. The cracks of loud thunder occasionally make someone jump with surprise, but people still soldier on in raincoats and umbrellas.`);
 		} else if (V.weatherToday.name === "Acid Rain") {
 			buffer.push(`Acidic rain splashes down today with an intimidating sizzle. Beyond how disgusting the toxic rain is, it's not actually particularly dangerous though, and most people are still out in the streets.`);
 		} else if (V.weatherToday.severity === 2 && V.weatherType === 1) {
@@ -108,7 +108,7 @@ App.Desc.playerArcology = function(lastElement) {
 			buffer.push(`The frenzy of winter descends upon the arcology. Terrible whips of snow smash against the arcology's walls and coat everything in a deep white, absorbing all into a howling vortex of ice and snow. Even the thickest furs seem to offer little protection against this arctic chill. Only the shielding protection of powerful weather cladding could possibly enable any sort of outside conduct or trade today.`);
 		} else if (V.weatherToday.severity === 4 && V.weatherType === 6) {
 			buffer.push(`The anger of the earth has come up towards the arcology. The whole city rumbles and quivers with the force of shifting tectonic plates underneath, sending mud crashing against the arcology's walls and violently shaking the whole arcology every so often with enough force to throw things off shelves and send them crashing to the ground. Only the shielding protection of powerful weather cladding could possibly enable any sort of outside conduct or trade today.`);
-		} 
+		}
 
 		return buffer.join(" ");
 	}
@@ -877,7 +877,7 @@ App.Desc.playerArcology = function(lastElement) {
 		if (A.FSNeoImperialistLaw1 === 1) {
 			buffer.push(`Occasionally, an Imperial Knight in expensive battle armor wanders through the plaza, often accompaned by a small group of lesser soldiers with battle armor painted in the same fashion as the Knight's.`);
 		}
-	 	if (A.FSNeoImperialistLaw2 === 1) {
+		if (A.FSNeoImperialistLaw2 === 1) {
 			buffer.push(`You can see a Baron off in the distance, wearing a bright gold headband that shimmers in the dim neon light of the plaza, dictating some edict of yours down to a street merchant who scribbles down their words furiously.`);
 		}
 		if (A.FSAztecRevivalistLaw === 1) {
diff --git a/src/endWeek/saWhore.js b/src/endWeek/saWhore.js
index 9caf84edb00726555dd9481b581a8c1d981eb846..18fa3fd14cc751bb616c909a135ca0af78f893e8 100644
--- a/src/endWeek/saWhore.js
+++ b/src/endWeek/saWhore.js
@@ -939,7 +939,7 @@ App.SlaveAssignment.whore = (function() {
 					r += `, even if it's not real`;
 				}
 				r += `.`;
-			} else if (slave.bellyAccessory.FSRepopulationFocusPregPolicy === 1 && slave.bellyPreg >= 1500) {
+			} else if (arcology.FSRepopulationFocusPregPolicy === 1 && slave.bellyPreg >= 1500) {
 				r += ` It's currently trendy to plow a whore laden with child, a role ${he} fits perfectly.`;
 			} else if (arcology.FSRestart !== "unset") {
 				r += ` In the new culture of ${arcology.name}, ${his}`;
diff --git a/src/events/RESS/assFitting.js b/src/events/RESS/assFitting.js
index 0f7904c9e67ba2cea5f83f6c1f539d523ad2c1f0..c86a7a4ba39842bca5a192b61309ff09f04078a6 100644
--- a/src/events/RESS/assFitting.js
+++ b/src/events/RESS/assFitting.js
@@ -10,7 +10,7 @@ App.Events.RESSAssFitting = class RESSAssFitting extends App.Events.BaseEvent {
 				s => s.assignment !== "work as a servant",
 				s => s.devotion > 20,
 				s => s.butt > 5,
-				s => ["a bimbo outfit", "a biyelgee costume", "a bunny outfit", "a burkini", "a cheerleader outfit", "a comfortable bodysuit", "a dirndl", "a fallen nuns habit", "a huipil", "a latex catsuit", "a leotard", "a long qipao", "a maternity dress", "a military uniform", "a monokini", "a mounty outfit", "a nice nurse outfit", "a red army uniform", "a scalemail bikini", "a schoolgirl outfit", "a schutzstaffel uniform", "a slutty nurse outfit", "a slutty outfit", "a slutty qipao", "a slutty schutzstaffel uniform", "a succubus outfit", "attractive lingerie for a pregnant woman", "attractive lingerie", "battlearmor", "chains", "clubslut netting", "conservative clothing", "cutoffs and a t-shirt", "kitty lingerie", "lederhosen", "nice business attire", "overalls", "restrictive latex", "striped panties", "slutty business attire", "slutty jewelry", "spats and a tank top", "stretch pants and a crop-top", "uncomfortable straps", "Western clothing", "Imperial Plate", "a tight Imperial bodysuit",].includes(s.clothes),
+				s => ["a bimbo outfit", "a biyelgee costume", "a bunny outfit", "a burkini", "a cheerleader outfit", "a comfortable bodysuit", "a dirndl", "a fallen nuns habit", "a huipil", "a latex catsuit", "a leotard", "a long qipao", "a maternity dress", "a military uniform", "a monokini", "a mounty outfit", "a nice nurse outfit", "a red army uniform", "a scalemail bikini", "a schoolgirl outfit", "a schutzstaffel uniform", "a slutty nurse outfit", "a slutty outfit", "a slutty qipao", "a slutty schutzstaffel uniform", "a succubus outfit", "attractive lingerie for a pregnant woman", "attractive lingerie", "battlearmor", "chains", "clubslut netting", "conservative clothing", "cutoffs and a t-shirt", "kitty lingerie", "lederhosen", "nice business attire", "overalls", "restrictive latex", "striped panties", "slutty business attire", "slutty jewelry", "spats and a tank top", "stretch pants and a crop-top", "uncomfortable straps", "Western clothing", "Imperial Plate", "a tight Imperial bodysuit"].includes(s.clothes),
 				hasAnyArms,
 				canStand,
 			]
@@ -21,7 +21,7 @@ App.Events.RESSAssFitting = class RESSAssFitting extends App.Events.BaseEvent {
 		/** @type {Array<App.Entity.SlaveState>} */
 		let [eventSlave] = this.actors.map(a => getSlave(a));
 		const {
-			He, he, His, his, him
+			He, he, His, his, him, hers
 		} = getPronouns(eventSlave);
 		const {title: Master} = getEnunciation(eventSlave);
 
@@ -57,15 +57,15 @@ App.Events.RESSAssFitting = class RESSAssFitting extends App.Events.BaseEvent {
 		} else if (V.geneticMappingUpgrade >= 1 && eventSlave.geneticQuirks.rearLipedema === 2) {
 			t.push(`apparently a little bigger today than it was yesterday. ${His} body is constantly laying fat on ${his} ass and thighs, so this isn't really unexpected.`);
 		} else if (eventSlave.buttImplantType === "string") {
-			t.push(`apparently a little bigger today than it was yesterday. String implants like ${he}rs steadily grow if not regularly drained.`);
+			t.push(`apparently a little bigger today than it was yesterday. String implants like ${hers} steadily grow if not regularly drained.`);
 		} else if (eventSlave.diet === "corrective" && eventSlave.weight < -10) {
 			t.push(`apparently a little bigger today than it was yesterday. ${He} is underweight and being slowly plumped up, so this is a sign of progress.`);
 		} else if (eventSlave.hormoneBalance >= 200) {
-			t.push(`apparently bigger today than it was yesterday. Intensive female hormone regimens like ${he}rs sometimes cause minor ass expansion.`);
+			t.push(`apparently bigger today than it was yesterday. Intensive female hormone regimens like ${hers} sometimes cause minor ass expansion.`);
 		} else if (eventSlave.buttImplant / eventSlave.butt >= 0.5) {
-			t.push(`apparently a little bigger today than it was yesterday. Large implants like ${he}rs normally cause some slight size fluctuations.`);
+			t.push(`apparently a little bigger today than it was yesterday. Large implants like ${hers} normally cause some slight size fluctuations.`);
 		} else {
-			t.push(`apparently a little bigger today than it was yesterday. With a behind as big as ${he}rs, a little natural fluctuation is inevitable.`);
+			t.push(`apparently a little bigger today than it was yesterday. With a behind as big as ${hers}, a little natural fluctuation is inevitable.`);
 		}
 		App.Events.addParagraph(node, t);
 		t = [];
diff --git a/src/events/RESS/moistPussy.js b/src/events/RESS/moistPussy.js
index 35d07362956173c29e13eee697c20c7482de0550..9e8ce2e572b68bface7023ea3faeb5e3564b7f24 100644
--- a/src/events/RESS/moistPussy.js
+++ b/src/events/RESS/moistPussy.js
@@ -19,7 +19,7 @@ App.Events.RESSMoistPussy = class RESSMoistPussy extends App.Events.BaseEvent {
 		/** @type {Array<App.Entity.SlaveState>} */
 		let [eventSlave] = this.actors.map(a => getSlave(a));
 		const {
-			He, he, His, his, him
+			He, he, His, his, him, hers
 		} = getPronouns(eventSlave);
 		const belly = bellyAdjective(eventSlave);
 
@@ -145,7 +145,7 @@ App.Events.RESSMoistPussy = class RESSMoistPussy extends App.Events.BaseEvent {
 				t.push(`fuck ${him} powerfully, withdrawing your dick almost all the way and then hilting yourself in ${his} soaked slit.`);
 				t.push(VCheck.Vaginal(eventSlave, 1));
 			} else {
-				t.push(`trib ${him} with assurance, grinding your hips against ${he}rs and making ${him} feel your heat.`);
+				t.push(`trib ${him} with assurance, grinding your hips against ${hers} and making ${him} feel your heat.`);
 				seX(eventSlave, "vaginal", V.PC, "penetrative");
 			}
 			t.push(`${He} clings to you, accepting the closeness to ${his} ${getWrittenTitle(eventSlave)} and enjoying the loving attention, even as the extreme wetness of ${his} cunt and your ${V.PC.dick !== 0 ? "powerful thrusting" : "hungry grinding"} begin to produce lewd noises from between you.`);
diff --git a/src/interaction/siFinancial.js b/src/interaction/siFinancial.js
index 66410744c330f944daf76057e73630898fc08c76..1d16d3c40efad580439a9d2bc775af5f7d2f56d6 100644
--- a/src/interaction/siFinancial.js
+++ b/src/interaction/siFinancial.js
@@ -217,7 +217,7 @@ App.UI.SlaveInteract.financial = function(slave) {
 					"Discard Confirm",
 				)
 			);
-			if (V.seeExtreme === 1 && V.arcologies[0].FSPaternalist === "unset") {
+			if (V.seeExtreme === 1 && V.arcologies[0].FSPaternalist === "unset" && V.cheatMode === 1) {
 				linkArray.push(
 					App.UI.DOM.passageLink(
 						`Threaten ${his} life`,
diff --git a/src/interaction/siPhysicalRegimen.js b/src/interaction/siPhysicalRegimen.js
index 6c5a2e6974ceb0a076add5b763af2aa23b785c17..3bae0cd02bcc1769038285deec79d7e97f0d6f9d 100644
--- a/src/interaction/siPhysicalRegimen.js
+++ b/src/interaction/siPhysicalRegimen.js
@@ -263,16 +263,16 @@ App.UI.SlaveInteract.physicalRegimen = function(slave) {
 			title.appendChild(App.UI.SlaveInteract.generateRows(drugLevelOptions, slave, "", false, refresh));
 			el.append(title);
 
-			appendLabeledChoiceRow("Lips", lips);
-			appendLabeledChoiceRow("Breasts", breasts);
-			appendLabeledChoiceRow("Nipples", nipples);
-			appendLabeledChoiceRow("Butt", butt);
-			appendLabeledChoiceRow(slave.dick > 0 ? "Dick" : "Clit", dick);
-			appendLabeledChoiceRow("Balls", balls);
-			appendLabeledChoiceRow("Fertility", fertility);
-			appendLabeledChoiceRow("Hormones", hormones);
-			appendLabeledChoiceRow("Psych", psych);
-			appendLabeledChoiceRow("Misc", misc);
+			appendLabeledChoiceRow("Lips", lips, el);
+			appendLabeledChoiceRow("Breasts", breasts, el);
+			appendLabeledChoiceRow("Nipples", nipples, el);
+			appendLabeledChoiceRow("Butt", butt, el);
+			appendLabeledChoiceRow(slave.dick > 0 ? "Dick" : "Clit", dick, el);
+			appendLabeledChoiceRow("Balls", balls, el);
+			appendLabeledChoiceRow("Fertility", fertility, el);
+			appendLabeledChoiceRow("Hormones", hormones, el);
+			appendLabeledChoiceRow("Psych", psych, el);
+			appendLabeledChoiceRow("Misc", misc, el);
 
 			return el;
 		}
@@ -938,11 +938,11 @@ App.UI.SlaveInteract.physicalRegimen = function(slave) {
 				}
 			}
 
-			appendLabeledChoiceRow("Health", health);
-			appendLabeledChoiceRow("Weight", weight);
-			appendLabeledChoiceRow("Muscle", muscle);
-			appendLabeledChoiceRow("Production", production);
-			appendLabeledChoiceRow("Hormone", hormone);
+			appendLabeledChoiceRow("Health", health, el);
+			appendLabeledChoiceRow("Weight", weight, el);
+			appendLabeledChoiceRow("Muscle", muscle, el);
+			appendLabeledChoiceRow("Production", production, el);
+			appendLabeledChoiceRow("Hormone", hormone, el);
 
 			return el;
 		}
@@ -999,8 +999,8 @@ App.UI.SlaveInteract.physicalRegimen = function(slave) {
 			title.append(choice);
 			el.append(title);
 
-			appendLabeledChoiceRow("Milk", milk);
-			appendLabeledChoiceRow("Cum", cum);
+			appendLabeledChoiceRow("Milk", milk, el);
+			appendLabeledChoiceRow("Cum", cum, el);
 
 			return el;
 		}
@@ -1041,8 +1041,9 @@ App.UI.SlaveInteract.physicalRegimen = function(slave) {
 	/** Append a simple row of choices with a label to a container, if there are choices to be made.
 	 * @param {string} label
 	 * @param {RowItem[]} array
+	 * @param {HTMLElement} el
 	 */
-	function appendLabeledChoiceRow(label, array) {
+	function appendLabeledChoiceRow(label, array, el) {
 		if (array.length > 0) {
 			const links = document.createElement('div');
 			links.append(`${label}: `);
diff --git a/src/js/SlaveState.js b/src/js/SlaveState.js
index 5013271a4e18714f2db715b84d8aa89a17f36e6a..8f70503b91945b1852aaefda51a3749a7acdf19d 100644
--- a/src/js/SlaveState.js
+++ b/src/js/SlaveState.js
@@ -2605,7 +2605,7 @@ App.Entity.SlaveState = class SlaveState {
 		 * * 2: Middle class
 		 * * 3: Upper class
 		 * * 4: Top class
-		*/
+		 */
 		this.whoreClass = 0;
 		/** Maximum class for whore to target
 		 * * 1: Lower class
@@ -2621,7 +2621,7 @@ App.Entity.SlaveState = class SlaveState {
 		if (false) { // eslint-disable-line
 			/** @type {FC.PregnancyData | undefined} */
 			this.pregData = undefined;
-			/** @type {FC.Fetus[] | undefined} */
+			/** @type {App.Entity.Fetus[] | undefined} */
 			this.womb = undefined;
 			/** @type {string | undefined} */
 			this.clothingBaseColor = undefined;
diff --git a/src/js/ibcJS.js b/src/js/ibcJS.js
index df28d1be46b1fac6d5676776c763c112cfa447ec..58e02d5dbcc7913711c78ea10ee669ae740c3931 100644
--- a/src/js/ibcJS.js
+++ b/src/js/ibcJS.js
@@ -372,8 +372,8 @@ globalThis.ibc = (() => {
 	};
 
 	/** Determine the kinship between slaves `a` and `b`
-	 * @param {IBCRelative} [a] or zero
-	 * @param {IBCRelative} [b] or zero
+	 * @param {IBCRelative|0} [a] or zero
+	 * @param {IBCRelative|0} [b] or zero
 	 * @param {boolean} [ignore_coeffs=false]
 	 * @returns {number}
 	 */
diff --git a/src/js/wombJS.js b/src/js/wombJS.js
index 95b26b5c04e6a282463198e5e1afd444b6630d50..95a99995366950862a380fdc3051a11f139c3090 100644
--- a/src/js/wombJS.js
+++ b/src/js/wombJS.js
@@ -107,40 +107,40 @@ globalThis.WombInit = function(actor) {
 	});
 };
 
+App.Entity.Fetus = class {
+	/** Construct a new fetus
+	 * @param {number} age - initial age, after conception, in weeks
+	 * @param {number} fatherID
+	 * @param {FC.HumanState} mother
+	 * @param {string} name - name of ovum (generally ovumNN where NN is the number in the batch)
+	 */
+	constructor(age, fatherID, mother, name) {
+		/** Unique identifier for this fetus */
+		this.ID = generateNewID();
+		/** Week since conception */
+		this.age = age;
+		/** Week in mother (age since implantation) */
+		this.realAge = 1;
+		this.fatherID = fatherID;
+		this.volume = 1;
+		this.reserve = "";
+		/** All identical multiples share the same twinID */
+		this.twinID = "";
+		this.motherID = mother.ID;
+		this.genetics = generateGenetics(mother, fatherID, name);
+	}
+};
+
 /**
- *
  * @param {FC.HumanState} actor
  * @param {number} fCount
  * @param {number} fatherID
  * @param {number} age
- * @param {App.Entity.SlaveState} [surrogate]
+ * @param {FC.HumanState} [surrogate] genetic mother
  */
 globalThis.WombImpregnate = function(actor, fCount, fatherID, age, surrogate) {
-	let i;
-	for (i = 0; i < fCount; i++) {
-		/** @type {FC.Fetus} */
-		const tf = {
-			ID: generateNewID(),
-			age: age, // initial age
-			realAge: 1, // initial real age (first week in mother)
-			fatherID: fatherID, // We can store who is father too.
-			volume: 1, // Initial, to create property. Updated with actual data after WombGetVolume call.
-			reserve: "", // Initial, to create property. Used later to mark if this child is to be kept.
-			identical: 0, // Initial, to create property. Updated with actual data during fetalSplit call.
-			splitted: 0, // marker for already splitted fetus.
-			motherID: surrogate ? surrogate.ID : actor.ID // Initial biological mother ID setup.
-		};
-		if (surrogate) {
-			if (actor.eggType === "human") {
-				tf.genetics = generateGenetics(surrogate, fatherID, i + 1); // Stored genetic information.
-			}
-		} else {
-			if (actor.eggType === "human") {
-				tf.genetics = generateGenetics(actor, fatherID, i + 1); // Stored genetic information.
-			}
-		}
-		tf.ID = generateNewID();
-
+	for (let i = 0; i < fCount; i++) {
+		const tf = new App.Entity.Fetus(age, fatherID, surrogate || actor, `ovum${i}`);
 		try {
 			if (actor.womb.length === 0) {
 				actor.pregWeek = age;
@@ -157,28 +157,29 @@ globalThis.WombImpregnate = function(actor, fCount, fatherID, age, surrogate) {
 	WombUpdatePregVars(actor);
 };
 
+/**
+ * @param {FC.HumanState} actor (surrogate mother)
+ * @param {number} fCount
+ * @param {FC.HumanState} mother (genetic mother)
+ * @param {number} fatherID
+ * @param {number} age
+ */
 globalThis.WombSurrogate = function(actor, fCount, mother, fatherID, age) {
 	WombImpregnate(actor, fCount, fatherID, age, mother);
 };
 
-globalThis.WombImpregnateClone = function(actor, fCount, mother, motherOriginal, age) {
-	let i;
-	for (i = 0; i < fCount; i++) {
-		/** @type {FC.Fetus} */
-		const tf = {
-			ID: generateNewID(),
-			age: age, // initial age
-			realAge: 1, // initial real age (first week in mother)
-			fatherID: mother.ID, // We can store who is father too.
-			volume: 1, // Initial, to create property. Updated with actual data after WombGetVolume call.
-			reserve: "", // Initial, to create property. Used later to mark if this child is to be kept.
-			identical: 0, // Initial, to create property. Updated with actual data during fetalSplit call.
-			splitted: 0, // marker for already splitted fetus.
-			motherID: mother.ID, // Initial biological mother ID setup.
-			genetics: generateGenetics(mother, mother.ID, i + 1) // Stored genetic information.
-		};
-		// set up common relatives for the slave and her clone
-		setMissingParents(mother);
+/**
+ * @param {FC.HumanState} actor (surrogate mother)
+ * @param {number} fCount
+ * @param {FC.HumanState} mother (genetic parent being cloned)
+ * @param {number} age
+ */
+globalThis.WombImpregnateClone = function(actor, fCount, mother, age) {
+	setMissingParents(mother);
+	const motherOriginal = V.genePool.find(s => s.ID === mother.ID) || mother;
+
+	for (let i = 0; i < fCount; i++) {
+		const tf = new App.Entity.Fetus(age, mother.ID, mother, `ovum${i}`);
 
 		// gene corrections
 		tf.fatherID = -7;
@@ -193,6 +194,7 @@ globalThis.WombImpregnateClone = function(actor, fCount, mother, motherOriginal,
 		} else {
 			tf.genetics.motherName = mother.slaveName;
 			tf.genetics.fatherName = mother.slaveName;
+			// @ts-ignore - mother isn't the player, so must be a slave
 			tf.genetics.clone = SlaveFullName(mother);
 			tf.genetics.cloneID = mother.ID;
 		}
@@ -663,34 +665,26 @@ globalThis.WombSort = function(actor) {
 	});
 };
 
-// now function work with chance. Literary we give it "one from X" as chance.
+/** Split fetuses into identical twins based on chance
+ * @param {FC.HumanState} actor
+ * @param {number} chance
+ */
 globalThis.fetalSplit = function(actor, chance) {
-	actor.womb.forEach(function(s) {
-		if ((jsRandom(1, chance) >= chance) && s.splitted !== 1) {
-			/** @type {FC.Fetus} */
-			const nft = {
-				ID: generateNewID(),
-				age: s.age,
-				realAge: s.realAge,
-				fatherID: s.fatherID,
-				motherID: s.motherID,
-				volume: s.volume,
-				reserve: "", // splitted fetus is new separate, reserve - it's not genetic to split.
-				genetics: clone(s.genetics),
-				identical: 1 // this is marker that this fetus has at least one twin.
-			};
-			s.splitted = 1; // this is marker that this is already splitted fetus (to not split second time in loop), only source fetus needed it.
-			s.identical = 1; // this is marker that this fetus has at least one twin.
-
+	for (const s of actor.womb) {
+		if (jsRandom(1, chance) >= chance) {
+			// if this fetus is not already an identical, generate a new twin ID before cloning it
 			if (s.twinID === "" || s.twinID === undefined) {
 				s.twinID = generateNewID();
 			}
 
-			nft.twinID = s.twinID;
+			// clone the fetus with a new fetus ID
+			const nft = clone(s);
+			nft.ID = generateNewID();
+			nft.reserve = ""; // new fetus does not inherit reserve status
 
 			actor.womb.push(nft);
 		}
-	});
+	}
 	WombNormalizePreg(actor);
 };
 
diff --git a/src/markets/specificMarkets/schoolFutanari.js b/src/markets/specificMarkets/schoolFutanari.js
index 8e9ddba2aacb15447bbc37d00e9b735a591ac203..9bd0ba9588e877a223cc835ce3ac3754b3bb24bd 100644
--- a/src/markets/specificMarkets/schoolFutanari.js
+++ b/src/markets/specificMarkets/schoolFutanari.js
@@ -85,43 +85,43 @@ App.Markets.TFS = function() {
 								r.push(`You leave the Sisters' suite after a few hours of fucking and being fucked, feeling tired but satisfied.`);
 							}
 							if (canGetPregnant(V.PC)) {
-								r.push(knockMeUp(V.PC, 5, 0, -9, 1));
+								r.push(knockMeUp(V.PC, 5, 0, -9, true));
 							}
 							break;
 						case 2:
 							r.push(`She doesn't have to explain the Sisters' sexual equality this time, or that you have to subject yourself to it. You remember, and you let her know you're willing by giving her a friendly hug that squashes your breasts against each other and rubs your stiff pricks together. She reaches around you to grab your ass, already pulling you towards the pile of futas. You leave the Sisters' suite after a few hours of fucking and being fucked, in a state of total sexual satiation.`);
 							if (canGetPregnant(V.PC)) {
-								r.push(knockMeUp(V.PC, 10, 0, -9, 1));
+								r.push(knockMeUp(V.PC, 10, 0, -9, true));
 							}
 							break;
 						case 3:
 							r.push(`She asked that with a distinctly flirty tone, obviously hoping you'd agree again, and she isn't disappointed. You take her by the hand and skip over to the pile of futas, most of which know you very intimately by now. They see their Sister and you approaching, and those of them that don't have their mouths full greet you eagerly. Three of them quickly rearrange themselves to present you with a couple of dicks to sit on and a pussy to fuck, all at once. You leave the Sisters' suite after many hours of fucking and being fucked, tired but satisfied.`);
 							if (canGetPregnant(V.PC)) {
-								r.push(knockMeUp(V.PC, 20, 0, -9, 1));
+								r.push(knockMeUp(V.PC, 20, 0, -9, true));
 							}
 							break;
 						case 4:
 							r.push(`She asked that in a knowing voice, confident you'd agree, and was already moving in to kiss you when you did. She seems to want you more than usual today, and pulls you down onto the edge of the pit, guiding your cock into her pussy. She isn't selfish, of course, and reaches around to spread your buttocks so you can get fucked while you fuck. You leave the Sisters' suite after many hours of this, very tired. You wonder when you can make time to visit the Sisters again.`);
 							if (canGetPregnant(V.PC)) {
-								r.push(knockMeUp(V.PC, 40, 0, -9, 1));
+								r.push(knockMeUp(V.PC, 40, 0, -9, true));
 							}
 							break;
 						case 5:
 							r.push(`She runs her tongue over her lips as she asks, and sits you down on the edge of the pit and deepthroats you as soon as you agree. She wants your cum, and uses a couple of fingers to tickle your prostate and make it appear faster. You jerk with orgasm, and she pushes your wet cock up against your stomach so she can fuck your pussy. She pauses for a moment, letting a younger Sister enter her ass first. You leave the Sisters' suite after a full day of this, utterly exhausted but eager to return.`);
 							if (canGetPregnant(V.PC)) {
-								r.push(knockMeUp(V.PC, 60, 0, -9, 1));
+								r.push(knockMeUp(V.PC, 60, 0, -9, true));
 							}
 							break;
 						case 6:
 							r.push(`You nod, and she turns back towards the orgy, not seeing any reason to lead you, since you know the way. You both sink back into the pile of cocks, pussies, mouths, asses, boobs; the hours go by without you noticing. You leave the Sisters' suite unable to remember specifics, but you clearly fucked and got fucked by every futa there at least once. You're surprised when you learn how long you were there, but the worries of being an arcology owner no longer seem as pressing as they once did.`);
 							if (canGetPregnant(V.PC)) {
-								r.push(knockMeUp(V.PC, 80, 0, -9, 1));
+								r.push(knockMeUp(V.PC, 80, 0, -9, true));
 							}
 							break;
 						case 7:
 							r.push(`You don't even bother to respond, and head straight for the orgy. You insert yourself into an eager mouth, bending over so the matron following you can take you from behind. The worries of your life as an arcology owner seem very far away as she slides inside you. You only leave when ${V.assistant.name} repeatedly pages you over the arcology's public announcement system. On the way to your office, you notice how full of cum your stomach is, how relaxed your pussy and ass are, and how happy you feel.`);
 							if (canGetPregnant(V.PC)) {
-								r.push(knockMeUp(V.PC, 100, 0, -9, 1));
+								r.push(knockMeUp(V.PC, 100, 0, -9, true));
 							}
 							break;
 						case 8:
diff --git a/src/npc/databases/dfSlavesDatabase.js b/src/npc/databases/dfSlavesDatabase.js
index 60e7cb94785699a3ee7b1587df2efe0d633789ee..67eff09a4a1e2fd64de8da1607768d1f4011f151 100644
--- a/src/npc/databases/dfSlavesDatabase.js
+++ b/src/npc/databases/dfSlavesDatabase.js
@@ -335,7 +335,7 @@ App.Data.HeroSlaves.DF = [
 		intelligence: -60,
 		clitPiercing: 2
 	},
-	/* vibe nips, stupid, sensitive, no masturb implant*/
+	/* vibe nips, stupid, sensitive, no masturbation implant*/
 ];
 
 App.Data.HeroSlaves.DFextreme = [
diff --git a/src/npc/descriptions/crotch/crotch.js b/src/npc/descriptions/crotch/crotch.js
index a6508da476fad0d0f702ff457f553667d4f1014f..02c1596859d6d0073a7ec65f10928d37543926a8 100644
--- a/src/npc/descriptions/crotch/crotch.js
+++ b/src/npc/descriptions/crotch/crotch.js
@@ -8,7 +8,7 @@
 App.Desc.crotch = function(slave, {market, eventDescription} = {}) {
 	const r = [];
 	const {
-		he, him, his, He, His
+		he, him, his, He, His, hers
 	} = getPronouns(slave);
 	if (V.showClothing === 1 && !market) {
 		if (slave.assignment === "work in the dairy" && V.dairyRestraintsSetting > 1) {
@@ -604,9 +604,9 @@ App.Desc.crotch = function(slave, {market, eventDescription} = {}) {
 							r.push(`Its head peeks out from ${his} cleavage.`);
 						}
 					} else if (slave.dick > 5) {
-						r.push(`cheerleader skirt is not designed for someone with a cock as big as ${he}rs; its lower half sticks out beneath its edge.`);
+						r.push(`cheerleader skirt is not designed for someone with a cock as big as ${hers}; its lower half sticks out beneath its edge.`);
 					} else if (slave.dick > 3) {
-						r.push(`cheerleader skirt is not designed for someone with a cock as big as ${he}rs; its head is easily visible beneath its edge.`);
+						r.push(`cheerleader skirt is not designed for someone with a cock as big as ${hers}; its head is easily visible beneath its edge.`);
 					} else if (slave.dick > 0) {
 						r.push(`cheerleader skirt hides ${his} dick reasonably well as long as ${he} stands still.`);
 					} else if (slave.vagina === -1) {
diff --git a/src/npc/descriptions/mind.js b/src/npc/descriptions/mind.js
index 49910d4647baffd03584b67a00ef7d3a6a9f9f99..841e07912f996b422e58d7e028031ac2aac81c77 100644
--- a/src/npc/descriptions/mind.js
+++ b/src/npc/descriptions/mind.js
@@ -5,7 +5,7 @@
 App.Desc.mind = function(slave, {market, eventDescription} = {}) {
 	const r = [];
 	const {
-		he, him, his, He, His
+		he, him, his, He, His, hers
 	} = getPronouns(slave);
 	if (slave.fuckdoll === 0) {
 		r.push(App.Desc.eyes(slave, {market: market}));
@@ -505,7 +505,7 @@ App.Desc.mind = function(slave, {market, eventDescription} = {}) {
 					} else if (slave.fetishStrength > 60) {
 						r.push(`${He} enjoys <span class="lightcoral">breast play,</span> and is rapidly aroused by nipple stimulation.`);
 					} else {
-						r.push(`${He} <span class="lightcoral">really likes boobs,</span> ${he}rs and others.`);
+						r.push(`${He} <span class="lightcoral">really likes boobs,</span> ${hers} and others.`);
 					}
 					break;
 				case "pregnancy":
diff --git a/src/npc/generate/generateGenetics.js b/src/npc/generate/generateGenetics.js
index 4732839d024f7c64c14f1d560d1dbd737556603a..62a5510661294e33ba84fe35a11508c3bd781875 100644
--- a/src/npc/generate/generateGenetics.js
+++ b/src/npc/generate/generateGenetics.js
@@ -2,8 +2,10 @@
 
 globalThis.generateGenetics = (function() {
 	let mother;
+	/** @type {FC.HumanState|0} */
 	let activeMother;
 	let father;
+	/** @type {FC.HumanState|0} */
 	let activeFather;
 
 
@@ -15,10 +17,10 @@ globalThis.generateGenetics = (function() {
 	/**
 	 * @param {FC.HumanState} actor1
 	 * @param {number} actor2 Slave ID of actor 2
-	 * @param {number} x
+	 * @param {string} name Initial name of ovum
 	 * @returns {FC.FetusGenetics}
 	 */
-	function generateGenetics(actor1, actor2, x) {
+	function generateGenetics(actor1, actor2, name) {
 		const genes = {
 			gender: /** @type {FC.GenderGenes} */ ("XX"),
 			name: "blank",
@@ -91,10 +93,10 @@ globalThis.generateGenetics = (function() {
 		}
 
 		genes.gender = setGender(father, mother);
-		genes.name = setName(x);
-		genes.mother = setMotherID(actor1.ID);
+		genes.name = name;
+		genes.mother = actor1.ID;
 		genes.motherName = setMotherName(activeMother);
-		genes.father = setFatherID(actor2);
+		genes.father = actor2;
 		genes.fatherName = setFatherName(father, activeFather, actor2);
 		genes.inbreedingCoeff = ibc.kinship(mother, father);
 		genes.nationality = setNationality(father, mother);
@@ -172,16 +174,6 @@ globalThis.generateGenetics = (function() {
 		return gender;
 	}
 
-	// name
-	function setName(x) {
-		return `ovum${x}`;
-	}
-
-	// motherID
-	function setMotherID(actor1ID) {
-		return actor1ID;
-	}
-
 	// motherName
 	function setMotherName(activeMother) {
 		let motherName;
@@ -192,11 +184,6 @@ globalThis.generateGenetics = (function() {
 		return motherName;
 	}
 
-	// fatherID
-	function setFatherID(actor2) {
-		return actor2;
-	}
-
 	// fatherName
 	function setFatherName(father, activeFather, actor2) {
 		let fatherName;
@@ -687,8 +674,8 @@ globalThis.generateGenetics = (function() {
 
 	/**
 	 * Genetic quirks
-	 * @param {App.Entity.SlaveState|number} father
-	 * @param {App.Entity.SlaveState} mother
+	 * @param {FC.HumanState|0} father
+	 * @param {FC.HumanState} mother
 	 * @param {string} sex
 	 * @returns {object}
 	 */
diff --git a/src/npc/generate/newSlaveIntro.js b/src/npc/generate/newSlaveIntro.js
index 808644bb8b88ac99b18ca30789955fdfabad21e8..410b16ab907a55db8a8ad4b15f11c7810822c793 100644
--- a/src/npc/generate/newSlaveIntro.js
+++ b/src/npc/generate/newSlaveIntro.js
@@ -1,9 +1,8 @@
 /**
- *
  * @param {App.Entity.SlaveState} slave
- * @param {App.Entity.SlaveState} [slave2]
+ * @param {App.Entity.SlaveState} [slave2] recruiter slave, if present in the scene
  */
-App.UI.newSlaveIntro = function(slave, slave2 = V.eventSlave) {
+App.UI.newSlaveIntro = function(slave, slave2) {
 	const desc = SlaveTitle(slave);
 	const {title: Master} = getEnunciation(slave);
 	const {
@@ -1376,12 +1375,11 @@ App.UI.newSlaveIntro = function(slave, slave2 = V.eventSlave) {
 						result: function(slave) {
 							const r = [];
 							r.push(`You send ${him} out to be cleaned up and inducted, but have ${him} brought back afterward. You point out a clothes box on the couch and tell ${him} to get dressed, since you're about to make a tour of the club, and ${he}'ll be accompanying you. ${He} obeys without comment, but gasps with shock to find that ${he}'s been given a string sling bikini. ${He} climbs into it hesitantly, and finds that not only does its string bottom ride up between ${his} pussylips, it does not cover ${his} nipples at all: the strings part to either side of the nipples to let them stick through, bare. This can only generously be called clothing. ${He} accepts this with an obvious internal sigh, however, and walks dutifully behind you, ${his} bare feet slapping along as ${his} big butt bounces and ${his} tits constantly fall out of ${his} strings.`);
-							if (slave.behavioralFlaw !== "shamefast") {
-								r.push(`After a while, though, ${he} notices that ${he}'s getting a lot of very positive attention, and even starts to strut it a little. When you get back to the penthouse, you ask ${him} how ${he} felt. ${He} blushes. "Kinda hot, ${Master}" ${he}`);
-								r.push(`says, embarrassed.`);
+							if (slave.sexualFlaw !== "shamefast") {
+								r.push(`After a while, though, ${he} notices that ${he}'s getting a lot of very positive attention, and even starts to strut it a little. When you get back to the penthouse, you ask ${him} how ${he} felt. ${He} blushes. "Kinda hot, ${Master}" ${he} says, embarrassed.`);
 								r.push(Spoken(slave, `"I didn't think an older ${girl} like me would get so many stares."`));
 
-								r.push(`You reach out to grope ${his} tits,   and tell ${him} that with breasts like ${hers}, it's not surprising. ${He} <span class="hotpink">likes you</span> for liking ${his} body, and has <span class="mediumaquamarine">begun to trust</span> that even though ${he}'s old, ${he} can find a place under you.`);
+								r.push(`You reach out to grope ${his} tits, and tell ${him} that with breasts like ${hers}, it's not surprising. ${He} <span class="hotpink">likes you</span> for liking ${his} body, and has <span class="mediumaquamarine">begun to trust</span> that even though ${he}'s old, ${he} can find a place under you.`);
 								slave.trust += 4;
 								slave.devotion += 4;
 							} else {
@@ -1767,7 +1765,7 @@ App.UI.newSlaveIntro = function(slave, slave2 = V.eventSlave) {
 										r.push(`your pussy onto ${his} cock. ${He} shudders and moan softly as you slide yourself up and down ${his} shaft with steadily increasing speed. You keep your eyes locked on ${hers} all the while, as ${his} expression shifts from bewilderment to acceptance to ecstasy, as ${he} soon shoots ${his} seed up into you. Afterwards, you slip ${his} softening cock out of you, climb off of ${him}, and leave the exhausted and overwhelmed slave${girl} on your desk as you attend to business elsewhere. You think ${he}'s <span class="orangered">going to like it here.</span>`);
 										actX(slave, "penetrative");
 										if (canImpreg(V.PC, slave)) {
-											knockMeUp(V.PC, 100, 0, slave.ID, 1);
+											knockMeUp(V.PC, 100, 0, slave.ID, true);
 										}
 									} else {
 										r.push(`yourself into ${his}`);
@@ -3803,7 +3801,7 @@ App.UI.newSlaveIntro = function(slave, slave2 = V.eventSlave) {
 									slave.vagina = Math.clamp(slave.vagina, 3, 4);
 								}
 								actX(slave, "anal", 10);
-								assignJob(slave, "dairy");
+								assignJob(slave, Job.DAIRY);
 
 								r.push(`You order`);
 								if (V.HeadGirlID === 0) {
@@ -3836,7 +3834,7 @@ App.UI.newSlaveIntro = function(slave, slave2 = V.eventSlave) {
 									actX(slave, "vaginal", 10);
 								}
 								actX(slave, "anal", 10);
-								assignJob(slave, "dairy");
+								assignJob(slave, Job.DAIRY);
 
 								r.push(`Making use of`);
 								if (slave.trust < -20 || slave.devotion > 20) {
diff --git a/src/player/js/PlayerState.js b/src/player/js/PlayerState.js
index ddfff4e45098f5092ddb6943553f925d62b12e34..5749b3315afa66243ec381f87ff393c6f5b6b57d 100644
--- a/src/player/js/PlayerState.js
+++ b/src/player/js/PlayerState.js
@@ -253,7 +253,8 @@ App.Entity.PlayerState = class PlayerState {
 		/** Player's original surname
 		 * @type {string|number} */
 		this.birthSurname = "";
-		/** Player sex ("XX", "XY") */
+		/** Player sex ("XX", "XY")
+		 * @type {FC.GenderGenes} */
 		this.genes = "XY";
 		// exclusive major player variables here
 		/** your title's gender
@@ -1646,6 +1647,7 @@ App.Entity.PlayerState = class PlayerState {
 		this.sexualQuirk = "none";
 		/** 0: does not have; 1: carrier; 2: active
 		 * * heterochromia is an exception. String = active
+		 * @type {FC.GeneticQuirks}
 		 */
 		this.geneticQuirks = {
 			/** Oversized breasts. Increased growth rate, reduced shrink rate. Breasts try to return to oversized state if reduced. */
@@ -2017,7 +2019,7 @@ App.Entity.PlayerState = class PlayerState {
 			this.customTitle = undefined;
 			/** @type {FC.PregnancyData | undefined} */
 			this.pregData = undefined;
-			/** @type {FC.Fetus[] | undefined} */
+			/** @type {App.Entity.Fetus[] | undefined} */
 			this.womb = undefined;
 		}
 	}
diff --git a/src/pregmod/surrogacy.tw b/src/pregmod/surrogacy.tw
index dbebf1dbc0e5933a64fdc20982a6e512c1172746..ef0e0d234707a9f7cf2a9bc5f5dc2e0cc5fafbad 100644
--- a/src/pregmod/surrogacy.tw
+++ b/src/pregmod/surrogacy.tw
@@ -123,29 +123,11 @@
 	<<if $receptrix.ID == -1>>
 		Since the surgery required only a local anesthetic, you remain fully aware of the procedure as the autosurgery carries it out. You slowly rise to your feet, a hand to your lower belly, appreciating the clone growing within you.
 		<<set $PC.pregKnown = 1>>
-		<<if $donatrix.ID != -1>>
-			<<set _babyDaddy = $genePool.find(function(s) { return s.ID == $donatrix.ID; })>>
-			<<if ndef _babyDaddy>>
-				<<set _babyDaddy = $slaveIndices[$donatrix.ID]>>
-			<</if>>
-			<<run WombImpregnateClone($PC, 1, $donatrix, _babyDaddy, 1)>>
-		<<else>>
-			<<set _babyDaddy = $PC>>
-			<<run WombImpregnateClone($PC, 1, $PC, _babyDaddy, 1)>>
-		<</if>>
+		<<run WombImpregnateClone($PC, 1, $donatrix, 1)>>
 		<<run WombNormalizePreg($PC)>>
 	<<else>>
 		<<set $receptrix.pregKnown = 1>>
-		<<if $donatrix.ID != -1>>
-			<<set _babyDaddy = $genePool.find(function(s) { return s.ID == $donatrix.ID; })>>
-			<<if ndef _babyDaddy>>
-				<<set _babyDaddy = $slaveIndices[$donatrix.ID]>>
-			<</if>>
-			<<run WombImpregnateClone($receptrix, 1, $donatrix, _babyDaddy, 1)>>
-		<<else>>
-			<<set _babyDaddy = $PC>>
-			<<run WombImpregnateClone($receptrix, 1, $PC, _babyDaddy, 1)>>
-		<</if>>
+		<<run WombImpregnateClone($receptrix, 1, $donatrix, 1)>>
 		<<run WombNormalizePreg($receptrix)>>
 		<<setLocalPronouns $receptrix>>
 		<<if $receptrix.fetish == "mindbroken">>
diff --git a/src/uncategorized/nonRandomEvent.tw b/src/uncategorized/nonRandomEvent.tw
index 3eda44133ee553bda9e670245fdc143c0ac58ef7..30c3973bb0a557ba32c50bd8be6db60f0429675e 100644
--- a/src/uncategorized/nonRandomEvent.tw
+++ b/src/uncategorized/nonRandomEvent.tw
@@ -190,13 +190,13 @@
 <<elseif _effectiveWeek >= $murderAttemptWeek && $tempEventToggle>>
 	<<goto "Murder Attempt">>
 <<elseif $illegalDeals.slave !== 0>>
-	<<set $Event = "slave trade">>
+	<<set $event = "slave trade">>
 	<<goto "Murder Attempt">>
 <<elseif $illegalDeals.trade !== 0 && _effectiveWeek >= $illegalDeals.trade.week>>
-	<<set $Event = "trade deal">>
+	<<set $event = "trade deal">>
 	<<goto "Murder Attempt">>
 <<elseif $illegalDeals.military !== 0 && _effectiveWeek >= $illegalDeals.military.week>>
-	<<set $Event = "military deal">>
+	<<set $event = "military deal">>
 	<<goto "Murder Attempt">>
 <<else>>
 	<<if random(1,100) > _effectiveWeek+25>>