From 97e6baf7ebdb075da0ded74c21667b41bdd6bafd Mon Sep 17 00:00:00 2001
From: lowercasedonkey <lowercasedonkey@gmail.com>
Date: Sun, 16 Feb 2020 13:24:57 -0500
Subject: [PATCH] move useSlave into App.UI.SlaveInteract

---
 src/js/slaveInteract.js            | 742 +++++++++++++++++++++++++++++
 src/js/useSlave.js                 | 741 ----------------------------
 src/uncategorized/slaveInteract.tw |  24 +-
 3 files changed, 754 insertions(+), 753 deletions(-)
 delete mode 100644 src/js/useSlave.js

diff --git a/src/js/slaveInteract.js b/src/js/slaveInteract.js
index 9c64ce85648..795673c95f5 100644
--- a/src/js/slaveInteract.js
+++ b/src/js/slaveInteract.js
@@ -262,3 +262,745 @@ App.UI.SlaveInteract.drugs = function(slave) {
 	}
 	return jQuery('#drugs').empty().append(el);
 };
+
+App.UI.SlaveInteract.useSlaveDisplay = function(slave) {
+	// Goal: Be able to write the entire "use her" block with only dom fragments.
+	let el = document.createElement('div');
+
+	const
+		{
+			// eslint-disable-next-line no-unused-vars
+			he, him, his, hers, himself, boy, He, His
+		} = getPronouns(slave);
+
+	/*
+	Array of objects.  Each object follows the form: {
+		text: "Link text",
+		scene: "scene to include",
+		goto: if another passage is needed
+		updateSlave: update slave itself if needed, like {trust: 2},
+		update: updates V.,
+		note: if a note must appear after the link
+	}
+	*/
+	const sexOptions = [];
+	const fillFaceOptions = [];
+	const fillAssOptions = [];
+	// if no scene, it's just text, no link.  Italicize it.
+
+	if (slave.fuckdoll === 0) {
+		if (slave.vagina > -1) {
+			if (canDoVaginal(slave)) {
+				sexOptions.push({text: `Fuck ${him}`, scene: `FVagina`});
+				if (canDoAnal(slave)) {
+					sexOptions.push({text: `Use ${his} holes`, scene: `FButt`});
+				}
+				if (slave.bellyPreg >= 300000) {
+					sexOptions.push({text: `Fuck ${him} on ${his} belly`, scene: `FBellyFuck`});
+				}
+				if (slave.bellyPreg >= 300000 && V.pregInventions >= 1) {
+					sexOptions.push({text: `Fuck ${him} in ${his} maternity swing`, scene: `FMaternitySwing`});
+				}
+				if (slave.bellyPreg >= 300000 && V.pregInventions >= 1) {
+					sexOptions.push({text: `Fuck ${him} with the help of ${his} assistants`, scene: `FAssistedSex`});
+				}
+				if (slave.bellyPreg >= 300000 && V.pregInventions >= 1) {
+					sexOptions.push({text: `Fuck ${him} in your goo pool`, scene: `FPoolSex`});
+				}
+			} else {
+				sexOptions.push({text: `Remove ${his} chastity belt if you wish to fuck ${him}`});
+			}
+		}
+		if (slave.bellyPreg >= 300000) {
+			if (canDoVaginal(slave) || canDoAnal(slave)) {
+				sexOptions.push({text: `Fuck ${him} on ${his} belly`, scene: `FBellyFuck`});
+				if (V.pregInventions >= 1) {
+					sexOptions.push({text: `Fuck ${him} in ${his} maternity swing`, scene: `FMaternitySwing`});
+					sexOptions.push({text: `Fuck ${him} with the help of ${his} assistants`, scene: `FAssistedSex`});
+					sexOptions.push({text: `Fuck ${him} in your goo pool`, scene: `FPoolSex`});
+				}
+			}
+		}
+
+		if (canDoAnal(slave)) {
+			sexOptions.push({text: `Fuck ${his} ass`, scene: `FAnus`});
+		} else {
+			sexOptions.push({text: `Remove ${his} chastity belt if you wish to fuck ${his} ass`});
+		}
+		sexOptions.push({text: `Use ${his} mouth`, scene: `FLips`});
+		sexOptions.push({text: `Kiss ${him}`, scene: `FKiss`});
+		if (hasAnyLegs(slave)) {
+			sexOptions.push({text: `Have ${him} dance for you`, scene: `FDance`});
+		}
+
+		sexOptions.push({text: `Play with ${his} tits`, scene: `FBoobs`});
+
+		sexOptions.push({text: `Caress ${him}`, scene: `FCaress`});
+
+		sexOptions.push({text: `Give ${him} a hug`, scene: `FEmbrace`});
+		if (V.cheatMode === 1) {
+			sexOptions.push({text: `Pat ${his} head`, scene: `FPat`});
+		}
+
+		sexOptions.push({text: `Grope ${his} boobs`, scene: `FondleBoobs`});
+		if (slave.nipples === "fuckable" && V.PC.dick > 0) {
+			sexOptions.push({text: `Fuck ${his} nipples`, scene: `FNippleFuck`});
+		}
+		if (slave.lactation > 0 && slave.boobs >= 2000 && slave.belly < 60000 && hasAnyArms(slave)) {
+			sexOptions.push({text: `Drink ${his} milk`, scene: `FSuckle`});
+		}
+
+		if (canDoAnal(slave)) {
+			sexOptions.push({text: `Grope ${his} butt`, scene: `FondleButt`});
+		}
+
+
+		if (slave.vagina > -1) {
+			if (canDoVaginal(slave)) {
+				sexOptions.push({text: `Grope ${his} pussy`, scene: `FondleVagina`});
+			}
+		}
+
+		if (slave.dick > 0) {
+			if (!(slave.chastityPenis)) {
+				sexOptions.push({text: `Grope ${his} dick`, scene: `FondleDick`});
+				if (canPenetrate(slave)) {
+					if (V.sexualOpeness === 1 || slave.toyHole === "dick") {
+						sexOptions.push({text: `Ride ${his} dick`, scene: `FDick`});
+					}
+				}
+			} else {
+				sexOptions.push({text: `Remove ${his} dick chastity belt if you wish to play with ${his} cock`});
+			}
+		}
+
+		if (hasAnyLegs(slave) && V.PC.dick > 0) {
+			sexOptions.push({text: `Get a footjob`, scene: `FFeet`});
+		}
+
+		if (canGetPregnant(slave) && (slave.geneticQuirks.superfetation !== 2 || V.geneticMappingUpgrade !== 0) && (slave.fuckdoll === 0) && V.seePreg !== 0) {
+			if (canImpreg(slave, V.PC)) {
+				sexOptions.push({text: `Impregnate ${him} yourself`, scene: `FPCImpreg`});
+			}
+			if (canImpreg(slave, slave)) {
+				sexOptions.push({text: `Use ${his} own seed to impregnate ${him}`, scene: `FSlaveSelfImpreg`});
+			}
+			sexOptions.push({text: `Use another slave to impregnate ${him}`, scene: `FSlaveImpreg`});
+		}
+		if (slave.assignment !== "work in the dairy" && slave.assignment !== "be confined in the arcade" && slave.assignment !== "be confined in the cellblock") {
+			if (V.dairyPiping === 1) {
+				if ((V.milkPipeline > 88 && V.milkPipeline !== 0) || V.arcologies[0].FSPastoralistLaw === 1) {
+					if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) {
+						if (slave.inflationType === "milk" || slave.inflationType === "none") {
+							fillAssOptions.push({text: `Milk`, scene: `FillUpButt`, updateSlave: {inflationType: "milk", inflationMethod: 2}});
+							fillFaceOptions.push({text: `Milk`, scene: `FillUpFace`, updateSlave: {inflationType: "milk", inflationMethod: 1}});
+						}
+					}
+				} else {
+					sexOptions.push({text: `${V.dairyNameCaps} is not producing enough milk to pump through the pipes`});
+				}
+				if ((V.cumPipeline > 88 && V.cumPipeline !== 0) || V.arcologies[0].FSPastoralistLaw === 1) {
+					if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) {
+						if (slave.inflationType === "cum" || slave.inflationType === "none") {
+							fillAssOptions.push({text: `Cum`, scene: `FillUpButt`, updateSlave: {inflationType: "cum", inflationMethod: 2}});
+							fillFaceOptions.push({text: `Cum`, scene: `FillUpFace`, updateSlave: {inflationType: "cum", inflationMethod: 1}});
+						}
+					}
+				} else {
+					sexOptions.push({text: `${V.dairyNameCaps} is not producing enough cum to pump through the pipes`});
+				}
+			} /* dairyPiping === 1 */
+			if (V.enema === 1) {
+				if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) {
+					if (slave.inflationType === "water" || slave.inflationType === "none") {
+						fillAssOptions.push({text: `Water`, scene: `FillUpButt`, updateSlave: {inflationType: "water", inflationMethod: 2}});
+					}
+					if (V.medicalEnema === 1) {
+						if (slave.inflationType === "aphrodisiac" || slave.inflationType === "none") {
+							fillAssOptions.push({text: `Aphrodisiacs`, scene: `FillUpButt`, updateSlave: {inflationType: "aphrodisiac", inflationMethod: 2}});
+						}
+						if (slave.inflationType === "curative" || slave.inflationType === "none") {
+							fillAssOptions.push({text: `Curatives`, scene: `FillUpButt`,  updateSlave: {inflationType: "curative", inflationMethod: 2}});
+						}
+						if (slave.inflationType === "tightener" || slave.inflationType === "none") {
+							fillAssOptions.push({text: `Rectal tighteners`, scene: `FillUpButt`,  updateSlave: {inflationType: "tightener", inflationMethod: 2}});
+						}
+					}
+				} /* inflation < 3 */
+			} /* enema === 1 */
+			if (V.wcPiping === 1) {
+				if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) {
+					if (slave.inflationType === "urine" || slave.inflationType === "none") {
+						fillAssOptions.push({text: `Urine`, scene: `FillUpButt`, updateSlave: {inflationType: "urine", inflationMethod: 2}});
+					}
+				}
+			} /* wcPiping === 1 */
+		} /* assigned to dairy or arcade */
+		if (slave.inflation === 0 && slave.bellyImplant < 1500) {
+			if (slave.assignment !== "work in the dairy" && slave.assignment !== "be confined in the arcade" && slave.assignment !== "be confined in the cellblock") {
+				if (V.buckets === 1) {
+					fillFaceOptions.push({text: `Two liters of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 1, inflationType: "food", inflationMethod: 1}});
+					if (slave.pregKnown === 0) {
+						fillFaceOptions.push({text: `A gallon of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 2, inflationType: "food", inflationMethod: 1}});
+						fillFaceOptions.push({text: `Two gallons of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 3, inflationType: "food", inflationMethod: 1}});
+					}
+				}
+				fillFaceOptions.push({text: `Get another slave to do it`, goto: `SlaveOnSlaveFeedingWorkAround`});
+			}
+		}
+		if (canDoVaginal(slave)) {
+			sexOptions.push({text: `Have another slave fuck ${his} pussy`, scene: `FSlaveSlaveVag`});
+		}
+		if (canPenetrate(slave)) {
+			sexOptions.push({text: `Have another slave ride ${his} cock`, scene: `FSlaveSlaveDick`});
+		}else if (slave.clit >= 4) {
+			sexOptions.push({text: `Have another slave ride ${his} clit-dick`, scene: `FSlaveSlaveDick`});
+		}
+		if (V.seeBestiality === 1 && V.cheatMode === 1) {
+			if (V.farmyardKennels > 0 && V.activeCanine !== 0) {
+				sexOptions.push({text: `Have a ${V.activeCanine.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "canine"}});
+			}
+			if (V.farmyardStable > 0 && V.activeHooved !== 0) {
+				sexOptions.push({text: `Let a ${V.activeHooved.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "hooved"}});
+			}
+			if (V.farmyardCages > 0 && V.activeFeline !== 0) {
+				sexOptions.push({text: `Have a ${V.activeFeline.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "feline"}});
+			}
+		}
+		sexOptions.push({text: `Abuse ${him}`, scene: `FAbuse`});
+		if (V.seeIncest === 1) {
+			if (V.familyTesting === 1) {
+				const availRelatives = availableRelatives(slave);
+				if (availRelatives.mother) {
+					sexOptions.push({text: `Fuck ${him} with ${his} mother`, scene: `FRelation`, update: {partner: "mother"}});
+				} else if (availRelatives.motherName !== null) {
+					sexOptions.push({text: `${His} mother, ${availRelatives.motherName}, is unavailable`});
+				}
+				/*
+				if (availRelatives.father) {
+					sexOptions.push({text: `Fuck ${him} with ${his} father`, scene: `FRelation`, update: {partner: "father"}});
+				} else if (availRelatives.fatherName !== null) {
+					sexOptions.push({text: `${His} father, ${availRelatives.motherName}, is unavailable`});
+				}
+				*/
+				if (slave.daughters > 0) {
+					if (availRelatives.daughters === 0) {
+						if (slave.daughters === 1) {
+							sexOptions.push({text: `${His} ${availRelatives.oneDaughterRel} is unavailable`});
+						} else {
+							sexOptions.push({text: `${His} daughters are unavailable`});
+						}
+					} else {
+						if (slave.daughters === 1) {
+							sexOptions.push({text: `Fuck ${him} with ${his} ${availRelatives.oneDaughterRel}`, scene: `FRelation`, update: {partner: "daughter"}});
+						} else {
+							sexOptions.push({text: `Fuck ${him} with one of ${his} daughters`, scene: `FRelation`, update: {partner: "daughter"}});
+						}
+						/*
+						if (availRelatives.daughters > 1) {
+							sexOptions.push({text: `Fuck ${him} with ${his} daughters`, scene: `FRelation`, update: {partner: "daughter"}});
+						}
+						*/
+					}
+				}
+				if (slave.sisters > 0) {
+					if (availRelatives.sisters === 0) {
+						if (slave.sisters === 1) {
+							sexOptions.push({text: `${His} ${availRelatives.oneSisterRel} is unavailable`});
+						} else {
+							sexOptions.push({text: `${His} sisters are unavailable`});
+						}
+					} else {
+						if (slave.sisters === 1) {
+							sexOptions.push({text: `Fuck ${him} with ${his} ${availRelatives.oneSisterRel}`, scene: `FRelation`, update: {partner: "sister"}});
+						} else {
+							sexOptions.push({text: `Fuck ${him} with one of ${his} sisters`, scene: `FRelation`, update: {partner: "sister"}});
+						}
+						/*
+						if (availRelatives.sisters > 1) {
+							sexOptions.push({text: `Fuck ${him} with ${his} sisters`, scene: `FRelation`, update: {partner: "sisters}});
+						}
+						*/
+					}
+				}
+			} else {
+				if (slave.relation !== 0) {
+					let assayedSlave = getSlave(slave.relationTarget);
+					const
+					{
+						daughter: daughter2, mother: mother2
+					} = getPronouns(assayedSlave);
+					if (isSlaveAvailable(assayedSlave)) {
+						if (slave.relation === "mother") {
+							sexOptions.push({text: `Fuck ${him} with ${his} ${daughter2}`, scene: `FRelation`, update: {partner: "relation"}});
+						} else if (slave.relation === "daughter") {
+							sexOptions.push({text: `Fuck ${him} with ${his} ${mother2}`, scene: `FRelation`, update: {partner: "relation"}});
+						} else if (slave.relation === "sister") {
+							sexOptions.push({text: `Fuck ${him} with ${his} ${sister2}`, scene: `FRelation`, update: {partner: "relation"}});
+						} else if (slave.relation === "twin") {
+							sexOptions.push({text: `Fuck ${him} with ${his} twin`, scene: `FRelation`, update: {partner: "relation"}});
+						}
+					} else {
+						sexOptions.push({text: `${assayedSlave.slaveName} is unavailable`});
+					}
+				}
+			}
+		}
+		if (slave.relationship > 0) {
+			const lover = getSlave(slave.relationshipTarget);
+			if (isSlaveAvailable(lover)) {
+				sexOptions.push({text: `Fuck ${him} with ${his} ${relationshipTermShort(slave)} ${SlaveFullName(lover)}`, scene: `FRelation`, update: {partner: "relationship"}});
+			} else {
+				if (lover.assignment === "be your agent") {
+					if (slave.broodmother < 2) {
+						sexOptions.push({text: `Send ${him} to live with your agent ${SlaveFullName(lover)}`, goto: `Agent Company`, update: {subSlave: lover}});
+					} else {
+						sexOptions.push({text: `A hyper-broodmother cannot be sent to live with your agent`});
+					}
+				} else {
+					sexOptions.push({text: `${SlaveFullName(lover)} is unavailable`});
+				}
+			}
+		}
+		if (slave.rivalryTarget !== 0 && hasAllLimbs(slave)) {
+			const rival = getSlave(slave.relationshipTarget);
+			if (isSlaveAvailable(rival) && hasAnyLegs(rival)) {
+				sexOptions.push({text: `Abuse ${his} rival with ${him}`, scene: `FRival`});
+			}
+		}
+		if (slave.fetish !== "mindbroken" && (canTalk(slave) || hasAnyArms(slave))) {
+			sexOptions.push({text: `Ask ${him} about ${his} feelings`, scene: `FFeelings`});
+			if (V.PC.dick > 0) {
+				sexOptions.push({text: `Make ${him} beg`, scene: `FBeg`});
+			}
+		}
+		if (slave.devotion >= 100 && slave.relationship < 0 && slave.relationship > -3) {
+			sexOptions.push({text: `Talk to ${him} about relationships`, goto: `Matchmaking`, update: {subSlave: 0, eventSlave: slave}});
+		}
+		let ML = V.marrying.length;
+		if ((V.MixedMarriage === 1 || V.cheatMode === 1) && slave.relationship !== 5 && slave.relationship !== -3) {
+			if (V.marrying.includes(slave.ID)) {
+				sexOptions.push({text: `You are already marrying ${him} this weekend`});
+			} else {
+				if (ML < 2) {
+					if (V.cheatMode === 1 || ML === 0) {
+						sexOptions.push({text: `Marry ${him}`, goto: "FMarry"});
+					} else {
+						sexOptions.push({text: `You already have a wedding planned for this weekend`});
+					}
+				} else {
+					sexOptions.push({text: `You can only marry up to two slaves per week`});
+				}
+			}
+		}
+		if (V.cheatMode === 1) {
+			sexOptions.push({text: `Check ${his} stats`, scene: `Slave Stats`});
+		}
+	} else { /* IS A FUCKDOLL */
+		sexOptions.push({text: `Fuck ${his} face hole`, scene: `FFuckdollOral`});
+		if (canDoVaginal(slave)) {
+			sexOptions.push({text: `Fuck ${his} front hole`, scene: `FFuckdollVaginal`});
+		}
+		if (canGetPregnant(slave) && (slave.geneticQuirks.superfetation !== 2 || V.geneticMappingUpgrade !== 0) && V.seePreg !== 0) {
+			if (canImpreg(slave, V.PC)) {
+				sexOptions.push({text: `Put a baby in ${him}`, scene: `FFuckdollImpreg`});
+			}
+		}
+		if (canDoAnal(slave)) {
+			sexOptions.push({text: `Fuck ${his} rear hole`, scene: `FFuckdollAnal`});
+		}
+	}
+	let activeSlaveRepSacrifice = repGainSacrifice(slave, V.arcologies[0]);
+	if (activeSlaveRepSacrifice > 0 && V.arcologies[0].FSPaternalist === "unset" && (slave.breedingMark === 0 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) {
+		sexOptions.push({
+	text: `Sacrifice ${him} on the altar`, goto: `Aztec Slave Sacrifice`, note: `This will kill ${him} and gain you ${activeSlaveRepSacrifice} reputation`, update: {sacrificeType: "life"}
+		});
+	}
+	el.append(`Or use ${him} here: `);
+	el.appendChild(generateRow(sexOptions));
+	if (!jQuery.isEmptyObject(fillFaceOptions)) {
+		let fill = document.createElement('div');
+		fill.appendChild(document.createTextNode(` Fill ${his} mouth with: `));
+		fill.appendChild(generateRow(fillFaceOptions));
+		el.appendChild(fill);
+	}
+	if (!jQuery.isEmptyObject(fillAssOptions)) {
+		let fill = document.createElement('div');
+		fill.appendChild(document.createTextNode(` Fill ${his} ass with: `));
+		fill.appendChild(generateRow(fillAssOptions));
+		el.appendChild(fill);
+	}
+
+	function generateRow(sexArray) {
+		let row = document.createElement('span');
+		for (let i = 0; i < sexArray.length; i++) {
+			let link;
+			const separator  = document.createTextNode(` | `);
+			const keys = Object.keys(sexArray[i]);
+
+			// Test to see if there was a problem with the key
+			for (let j = 0; j < keys.length; j++) {
+				if (["text", "scene", "goto", "updateSlave", "update", "note"].includes(keys[j])) {
+					continue;
+				} else {
+					sexArray[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY";
+					console.log("Trash found while generateRow() was running: " + keys[j] + ": " + sexArray[i][keys[j]]);
+					break;
+				}
+			}
+			// is it just text?
+			if (keys.length === 1) {
+				if (sexArray[i].text) {
+					link = document.createTextNode(sexArray[i].text);
+				} else {
+					console.log(`expected 'text' only, got: ${sexArray[i]}`);
+					link = document.createTextNode("error, text not found");
+				}
+			} else {
+				let passage = "";
+				if (sexArray[i].goto) {
+					passage = sexArray[i].goto;
+				}
+
+				// Set up the link
+				link = App.UI.DOM.link(
+					sexArray[i].text,
+					() => { click(sexArray[i]); },
+					[],
+					passage
+				);
+
+				// add a note node if required
+				if (sexArray[i].note) {
+					let note  = document.createTextNode(sexArray[i].note);
+					note.className = "note";
+					link.appendChild(note);
+				}
+			}
+			row.appendChild(link);
+			if (i < sexArray.length-1) {
+				row.appendChild(separator);
+			}
+		}
+
+		return row;
+
+		function click(sexOption) {
+			if (sexOption.updateSlave) {
+				Object.assign(slave, sexOption.updateSlave);
+			}
+			if (sexOption.update) {
+				Object.assign(V, sexOption.update);
+			}
+
+			if (sexOption.scene) {
+				App.UI.replace('#miniscene', `<<include "${sexOption.scene}">>`);
+			} else if (sexOption.goto) {
+				App.UI.replace('#miniscene', `<<goto "${sexOption.goto}">>`);
+			}
+
+			App.UI.SlaveInteract.refreshAll(slave);
+			return;
+		}
+	}
+	return jQuery('#useSlave').empty().append(el);
+};
+
+App.UI.SlaveInteract.bloating = function(slave) {
+	const
+		{
+			// eslint-disable-next-line no-unused-vars
+			he, him, his, hers, himself, boy, He, His
+		} = getPronouns(slave);
+	let bloating = document.createElement('div');
+	if (slave.inflation > 0) {
+		let intro = document.createElement('span');
+		intro.textContent = "Required Bloating";
+		intro.style.textDecoration = "underline";
+		bloating.append(intro);
+
+		bloating.append(": ");
+
+		let requirement = document.createElement('span');
+		requirement.style.fontWeight = "bold";
+		requirement.id = "inflate";
+		if (slave.inflation === 3) {
+			requirement.textContent = `${He} is required to keep 2 gallons of ${slave.inflationType} in ${him} at all times`;
+		} else if (slave.inflation === 2) {
+			requirement.textContent = `${He} is required to keep 4 liters of ${slave.inflationType} in ${him} at all times`;
+		} else if (slave.inflation === 1) {
+			requirement.textContent = `${He} is required to keep 2 liters of ${slave.inflationType} in ${him} at all times`;
+		}
+		bloating.append(requirement);
+		bloating.append(". ");
+
+		if (slave.inflationMethod === 3) {
+			let link = App.UI.DOM.link(
+				`Let ${him} deflate`,
+				() => {
+					slave.inflation = 0,
+					slave.inflationType = "none",
+					slave.inflationMethod = 0,
+					slave.cumSource = 0,
+					slave.milkSource = 0,
+					SetBellySize(slave),
+					App.UI.SlaveInteract.refreshAll(slave);
+				},
+			);
+			bloating.append(link);
+		} else {
+			let link = App.UI.DOM.link(
+				`Let ${him} deflate`,
+				() => {
+					slave.inflation = 0,
+					slave.inflationType = "none",
+					slave.inflationMethod = 0,
+					SetBellySize(slave),
+					App.UI.SlaveInteract.refreshAll(slave);
+				},
+			);
+			bloating.append(link);
+		}
+	}
+	// make sure it updates itself after run
+	return jQuery('#bloating').empty().append(bloating);
+};
+
+
+App.UI.SlaveInteract.fertility = function(slave) {
+	const
+		{
+			// eslint-disable-next-line no-unused-vars
+			he, him, his, hers, himself, boy, He, His
+		} = getPronouns(slave);
+	const separator  = document.createTextNode(` | `);
+	let fertilityblock = document.createElement('span');
+	if (slave.ovaries === 1 || slave.mpreg === 1 || slave.preg > 0) {
+		let note = document.createTextNode(``);
+		note.className = "note";
+		if (slave.preg < -1) {
+			note.textContent += `${He} is sterile`;
+		} else if (slave.pubertyXX === 0 && slave.preg < 1) {
+			note.textContent += `${He} is not yet fertile`;
+		} else if (slave.ovaryAge >= 47 && slave.preg < 1) {
+			note.textContent += `${He} is too old to become pregnant`;
+			if (slave.preg === -1) {
+				slave.preg = 0;
+				SetBellySize(slave);
+			}
+		} else if (slave.broodmotherOnHold === 1) {
+			note.textContent += `${His} pregnancy implant is turned off`;
+			if (slave.broodmotherCountDown > 0) {
+				note.textContent += `${he} is expected to be completely emptied of ${his} remaining brood in ${slave.broodmotherCountDown} week`;
+				if (slave.broodmotherCountDown > 1){
+					note.textContent += `s`;
+				}
+				note.textContent += `.`;
+				let link = App.UI.DOM.link(
+					`Turn on implant`,
+					() => {
+						slave.broodmotherOnHold = 0,
+						slave.broodmotherCountDown = 0;
+					},
+					[],
+					"Slave Interact"
+				);
+				fertilityblock.append(link);
+			}
+		} else if (slave.preg >= -1) {
+			fertilityblock.append("Contraception: ");
+			let fertility = document.createElement('span');
+			fertility.id = "fertility";
+			fertility.style.fontWeight = "bold";
+				if (slave.preg === -1) {
+					fertility.textContent = "using contraceptives";
+				} else if (slave.pregWeek < 0) {
+					fertility.textContent = "postpartum";
+				} else if (slave.preg === 0) {
+					fertility.textContent = "fertile";
+				} else if (slave.preg < 4) {
+					fertility.textContent = "may be pregnant";
+				} else {
+					fertility.textContent = `${slave.preg} weeks pregnant`;
+				}
+			fertility.textContent += ". ";
+			if (slave.preg > 0 && V.pregnancyMonitoringUpgrade === 1) {
+				fertilityblock.append(App.UI.DOM.passageLink("Inspect pregnancy", "Analyze Pregnancy"));
+				fertilityblock.append(` | `);
+			}
+			if (slave.preg === 0) {
+				let link = App.UI.DOM.link(
+					`Use contraceptives`,
+					() => {
+						slave.preg = -1,
+						App.UI.SlaveInteract.refreshAll(slave);
+					},
+				);
+				fertilityblock.append(link);
+			} else if (slave.preg === -1) {
+				let link = App.UI.DOM.link(
+					`Let ${him} get pregnant`,
+					() => {
+						slave.preg = 0,
+						App.UI.SlaveInteract.refreshAll(slave);
+					},
+				);
+				fertilityblock.append(link);
+			} else if (slave.induce === 1) {
+				note.textContent += `Hormones are being slipped into ${his} food; ${he} will give birth suddenly and rapidly this week`;
+			} else if (slave.preg > slave.pregData.normalBirth-2 && slave.preg > slave.pregData.minLiveBirth && slave.broodmother === 0 && slave.labor === 0) {
+				let link = App.UI.DOM.link(
+					`Induce labor`,
+					() => {
+						slave.labor = 1,
+						slave.induce = 1,
+						V.birthee = 1;
+					},
+					[],
+					"Slave Interact"
+				);
+				fertilityblock.append(link);
+				fertilityblock.appendChild(separator);
+				fertilityblock.append(App.UI.DOM.passageLink(`Give ${him} a cesarean section`, "csec"));
+			} else if (slave.broodmother > 0) {
+				if (slave.broodmotherOnHold !== 1) {
+					let link = App.UI.DOM.link(
+						`Turn off implant`,
+						() => {
+							slave.broodmotherOnHold = 1,
+							slave.broodmotherCountDown = 38-WombMinPreg(slave);
+						},
+					);
+					fertilityblock.append(link);
+				}
+				if (slave.broodmotherOnHold !== 1 && slave.preg >= 36) {
+					fertilityblock.appendChild(separator);
+				}
+				fertilityblock.appendChild(separator);
+				if (slave.preg > 37) {
+					fertilityblock.append(App.UI.DOM.passageLink(`Induce mass childbirth`, "BirthStorm"));
+				}
+			} else if (slave.preg > slave.pregData.minLiveBirth) {
+				let link = App.UI.DOM.link(
+					`Give  ${him} a cesarean section`,
+					() => {
+						slave.broodmotherOnHold = 0,
+						slave.broodmotherCountDown = 0;
+					},
+					[],
+					"csec"
+				);
+				fertilityblock.append(link);
+			} else if (slave.preg > 0 && slave.breedingMark === 1 && V.propOutcome === 1 && V.arcologies[0].FSRestart !== "unset" && V.eugenicsFullControl !== 1 && (slave.pregSource === -1 || slave.pregSource === -6)) {
+				note.textContent += "You are forbidden from aborting an Elite child";
+			} else if (slave.preg > 0) {
+				let link = App.UI.DOM.link(
+					`Abort ${his} pregnancy`,
+					() => {
+						slave.broodmotherOnHold = 0,
+						slave.broodmotherCountDown = 0;
+					},
+					[],
+					"Abort"
+				);
+				fertilityblock.append(link);
+			}
+		fertilityblock.append(note);
+		}
+	}
+	if (
+		(slave.pregKnown === 1) &&
+		(V.pregSpeedControl === 1) &&
+		(
+			slave.breedingMark !== 1 ||
+			V.propOutcome === 0 ||
+			V.eugenicsFullControl === 1 ||
+			V.arcologies[0].FSRestart === "unset"
+		) &&
+		(slave.indentureRestrictions < 1) &&
+		(slave.broodmother === 0) &&
+		V.seePreg !== 0
+	) {
+		let control = document.createElement('div');
+		let underline = document.createElement('span');
+
+		underline.style.textDecoration = "underline";
+		underline.textContent = "Pregnancy control";
+		control.append(underline);
+		control.append(": ");
+
+		if (slave.pregControl === "labor suppressors") {
+			control.append("Labor is suppressed. ");
+		} else if (slave.pregControl === "slow gestation") {
+			control.append("Slowed gestation speed. ");
+		} else if (slave.pregControl === "speed up") {
+			control.append("Faster gestation speed, staffed clinic recommended. ");
+		} else {
+			control.append("Normal gestation and birth. ");
+		}
+		fertilityblock.append(control);
+		control = document.createElement('div');
+		if (slave.preg >= slave.pregData.minLiveBirth) {
+			if (slave.pregControl === "labor suppressors") {
+				let link = App.UI.DOM.link(
+					`Normal Birth`,
+					() => {
+						slave.pregControl = "none",
+						App.UI.SlaveInteract.fertility(slave);
+					},
+				);
+				control.append(link);
+			} else {
+				let link = App.UI.DOM.link(
+					`Suppress Labor`,
+					() => {
+						slave.pregControl = "labor suppressors",
+						App.UI.SlaveInteract.fertility(slave);
+					},
+				);
+				control.append(link);
+			}
+		} else if (slave.preg < slave.pregData.normalBirth) {
+			if (slave.pregControl !== "none") {
+				let link = App.UI.DOM.link(
+					`Normal Gestation`,
+					() => {
+						slave.pregControl = "none",
+						App.UI.SlaveInteract.fertility(slave);
+					},
+				);
+				control.append(link);
+			}
+			if (slave.pregControl !== "slow gestation") {
+				control.append(separator);
+				let link = App.UI.DOM.link(
+					`Slow Gestation`,
+					() => {
+						slave.pregControl = "slow gestation",
+						App.UI.SlaveInteract.fertility(slave);
+					},
+				);
+				control.append(link);
+			}
+			if (slave.pregControl !== "speed up") {
+				control.append(separator);
+				let link = App.UI.DOM.link(
+					`Fast Gestation`,
+					() => {
+						slave.pregControl = "speed up",
+						App.UI.SlaveInteract.fertility(slave);
+					},
+				);
+				control.append(link);
+			}
+		}
+		fertilityblock.append(control);
+	}
+	return jQuery('#fertilityblock').empty().append(fertilityblock);
+};
+
+App.UI.SlaveInteract.refreshAll = function(slave) {
+	App.UI.SlaveInteract.bloating(slave);
+	App.UI.SlaveInteract.fertility(slave);
+	App.UI.SlaveInteract.useSlaveDisplay(slave);
+};
diff --git a/src/js/useSlave.js b/src/js/useSlave.js
deleted file mode 100644
index 6e138b27103..00000000000
--- a/src/js/useSlave.js
+++ /dev/null
@@ -1,741 +0,0 @@
-window.useSlaveDisplay = function(slave) {
-	// Goal: Be able to write the entire "use her" block with only dom fragments.
-	let el = document.createElement('div');
-
-	const
-		{
-			// eslint-disable-next-line no-unused-vars
-			he, him, his, hers, himself, boy, He, His
-		} = getPronouns(slave);
-
-	/*
-	Array of objects.  Each object follows the form: {
-		text: "Link text",
-		scene: "scene to include",
-		goto: if another passage is needed
-		updateSlave: update slave itself if needed, like {trust: 2},
-		update: updates V.,
-		note: if a note must appear after the link
-	}
-	*/
-	const sexOptions = [];
-	const fillFaceOptions = [];
-	const fillAssOptions = [];
-	// if no scene, it's just text, no link.  Italicize it.
-
-	if (slave.fuckdoll === 0) {
-		if (slave.vagina > -1) {
-			if (canDoVaginal(slave)) {
-				sexOptions.push({text: `Fuck ${him}`, scene: `FVagina`});
-				if (canDoAnal(slave)) {
-					sexOptions.push({text: `Use ${his} holes`, scene: `FButt`});
-				}
-				if (slave.bellyPreg >= 300000) {
-					sexOptions.push({text: `Fuck ${him} on ${his} belly`, scene: `FBellyFuck`});
-				}
-				if (slave.bellyPreg >= 300000 && V.pregInventions >= 1) {
-					sexOptions.push({text: `Fuck ${him} in ${his} maternity swing`, scene: `FMaternitySwing`});
-				}
-				if (slave.bellyPreg >= 300000 && V.pregInventions >= 1) {
-					sexOptions.push({text: `Fuck ${him} with the help of ${his} assistants`, scene: `FAssistedSex`});
-				}
-				if (slave.bellyPreg >= 300000 && V.pregInventions >= 1) {
-					sexOptions.push({text: `Fuck ${him} in your goo pool`, scene: `FPoolSex`});
-				}
-			} else {
-				sexOptions.push({text: `Remove ${his} chastity belt if you wish to fuck ${him}`});
-			}
-		}
-		if (slave.bellyPreg >= 300000) {
-			if (canDoVaginal(slave) || canDoAnal(slave)) {
-				sexOptions.push({text: `Fuck ${him} on ${his} belly`, scene: `FBellyFuck`});
-				if (V.pregInventions >= 1) {
-					sexOptions.push({text: `Fuck ${him} in ${his} maternity swing`, scene: `FMaternitySwing`});
-					sexOptions.push({text: `Fuck ${him} with the help of ${his} assistants`, scene: `FAssistedSex`});
-					sexOptions.push({text: `Fuck ${him} in your goo pool`, scene: `FPoolSex`});
-				}
-			}
-		}
-
-		if (canDoAnal(slave)) {
-			sexOptions.push({text: `Fuck ${his} ass`, scene: `FAnus`});
-		} else {
-			sexOptions.push({text: `Remove ${his} chastity belt if you wish to fuck ${his} ass`});
-		}
-		sexOptions.push({text: `Use ${his} mouth`, scene: `FLips`});
-		sexOptions.push({text: `Kiss ${him}`, scene: `FKiss`});
-		if (hasAnyLegs(slave)) {
-			sexOptions.push({text: `Have ${him} dance for you`, scene: `FDance`});
-		}
-
-		sexOptions.push({text: `Play with ${his} tits`, scene: `FBoobs`});
-
-		sexOptions.push({text: `Caress ${him}`, scene: `FCaress`});
-
-		sexOptions.push({text: `Give ${him} a hug`, scene: `FEmbrace`});
-		if (V.cheatMode === 1) {
-			sexOptions.push({text: `Pat ${his} head`, scene: `FPat`});
-		}
-
-		sexOptions.push({text: `Grope ${his} boobs`, scene: `FondleBoobs`});
-		if (slave.nipples === "fuckable" && V.PC.dick > 0) {
-			sexOptions.push({text: `Fuck ${his} nipples`, scene: `FNippleFuck`});
-		}
-		if (slave.lactation > 0 && slave.boobs >= 2000 && slave.belly < 60000 && hasAnyArms(slave)) {
-			sexOptions.push({text: `Drink ${his} milk`, scene: `FSuckle`});
-		}
-
-		if (canDoAnal(slave)) {
-			sexOptions.push({text: `Grope ${his} butt`, scene: `FondleButt`});
-		}
-
-
-		if (slave.vagina > -1) {
-			if (canDoVaginal(slave)) {
-				sexOptions.push({text: `Grope ${his} pussy`, scene: `FondleVagina`});
-			}
-		}
-
-		if (slave.dick > 0) {
-			if (!(slave.chastityPenis)) {
-				sexOptions.push({text: `Grope ${his} dick`, scene: `FondleDick`});
-				if (canPenetrate(slave)) {
-					if (V.sexualOpeness === 1 || slave.toyHole === "dick") {
-						sexOptions.push({text: `Ride ${his} dick`, scene: `FDick`});
-					}
-				}
-			} else {
-				sexOptions.push({text: `Remove ${his} dick chastity belt if you wish to play with ${his} cock`});
-			}
-		}
-
-		if (hasAnyLegs(slave) && V.PC.dick > 0) {
-			sexOptions.push({text: `Get a footjob`, scene: `FFeet`});
-		}
-
-		if (canGetPregnant(slave) && (slave.geneticQuirks.superfetation !== 2 || V.geneticMappingUpgrade !== 0) && (slave.fuckdoll === 0) && V.seePreg !== 0) {
-			if (canImpreg(slave, V.PC)) {
-				sexOptions.push({text: `Impregnate ${him} yourself`, scene: `FPCImpreg`});
-			}
-			if (canImpreg(slave, slave)) {
-				sexOptions.push({text: `Use ${his} own seed to impregnate ${him}`, scene: `FSlaveSelfImpreg`});
-			}
-			sexOptions.push({text: `Use another slave to impregnate ${him}`, scene: `FSlaveImpreg`});
-		}
-		if (slave.assignment !== "work in the dairy" && slave.assignment !== "be confined in the arcade" && slave.assignment !== "be confined in the cellblock") {
-			if (V.dairyPiping === 1) {
-				if ((V.milkPipeline > 88 && V.milkPipeline !== 0) || V.arcologies[0].FSPastoralistLaw === 1) {
-					if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) {
-						if (slave.inflationType === "milk" || slave.inflationType === "none") {
-							fillAssOptions.push({text: `Milk`, scene: `FillUpButt`, updateSlave: {inflationType: "milk", inflationMethod: 2}});
-							fillFaceOptions.push({text: `Milk`, scene: `FillUpFace`, updateSlave: {inflationType: "milk", inflationMethod: 1}});
-						}
-					}
-				} else {
-					sexOptions.push({text: `${V.dairyNameCaps} is not producing enough milk to pump through the pipes`});
-				}
-				if ((V.cumPipeline > 88 && V.cumPipeline !== 0) || V.arcologies[0].FSPastoralistLaw === 1) {
-					if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) {
-						if (slave.inflationType === "cum" || slave.inflationType === "none") {
-							fillAssOptions.push({text: `Cum`, scene: `FillUpButt`, updateSlave: {inflationType: "cum", inflationMethod: 2}});
-							fillFaceOptions.push({text: `Cum`, scene: `FillUpFace`, updateSlave: {inflationType: "cum", inflationMethod: 1}});
-						}
-					}
-				} else {
-					sexOptions.push({text: `${V.dairyNameCaps} is not producing enough cum to pump through the pipes`});
-				}
-			} /* dairyPiping === 1 */
-			if (V.enema === 1) {
-				if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) {
-					if (slave.inflationType === "water" || slave.inflationType === "none") {
-						fillAssOptions.push({text: `Water`, scene: `FillUpButt`, updateSlave: {inflationType: "water", inflationMethod: 2}});
-					}
-					if (V.medicalEnema === 1) {
-						if (slave.inflationType === "aphrodisiac" || slave.inflationType === "none") {
-							fillAssOptions.push({text: `Aphrodisiacs`, scene: `FillUpButt`, updateSlave: {inflationType: "aphrodisiac", inflationMethod: 2}});
-						}
-						if (slave.inflationType === "curative" || slave.inflationType === "none") {
-							fillAssOptions.push({text: `Curatives`, scene: `FillUpButt`,  updateSlave: {inflationType: "curative", inflationMethod: 2}});
-						}
-						if (slave.inflationType === "tightener" || slave.inflationType === "none") {
-							fillAssOptions.push({text: `Rectal tighteners`, scene: `FillUpButt`,  updateSlave: {inflationType: "tightener", inflationMethod: 2}});
-						}
-					}
-				} /* inflation < 3 */
-			} /* enema === 1 */
-			if (V.wcPiping === 1) {
-				if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) {
-					if (slave.inflationType === "urine" || slave.inflationType === "none") {
-						fillAssOptions.push({text: `Urine`, scene: `FillUpButt`, updateSlave: {inflationType: "urine", inflationMethod: 2}});
-					}
-				}
-			} /* wcPiping === 1 */
-		} /* assigned to dairy or arcade */
-		if (slave.inflation === 0 && slave.bellyImplant < 1500) {
-			if (slave.assignment !== "work in the dairy" && slave.assignment !== "be confined in the arcade" && slave.assignment !== "be confined in the cellblock") {
-				if (V.buckets === 1) {
-					fillFaceOptions.push({text: `Two liters of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 1, inflationType: "food", inflationMethod: 1}});
-					if (slave.pregKnown === 0) {
-						fillFaceOptions.push({text: `A gallon of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 2, inflationType: "food", inflationMethod: 1}});
-						fillFaceOptions.push({text: `Two gallons of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 3, inflationType: "food", inflationMethod: 1}});
-					}
-				}
-				fillFaceOptions.push({text: `Get another slave to do it`, goto: `SlaveOnSlaveFeedingWorkAround`});
-			}
-		}
-		if (canDoVaginal(slave)) {
-			sexOptions.push({text: `Have another slave fuck ${his} pussy`, scene: `FSlaveSlaveVag`});
-		}
-		if (canPenetrate(slave)) {
-			sexOptions.push({text: `Have another slave ride ${his} cock`, scene: `FSlaveSlaveDick`});
-		}else if (slave.clit >= 4) {
-			sexOptions.push({text: `Have another slave ride ${his} clit-dick`, scene: `FSlaveSlaveDick`});
-		}
-		if (V.seeBestiality === 1 && V.cheatMode === 1) {
-			if (V.farmyardKennels > 0 && V.activeCanine !== 0) {
-				sexOptions.push({text: `Have a ${V.activeCanine.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "canine"}});
-			}
-			if (V.farmyardStable > 0 && V.activeHooved !== 0) {
-				sexOptions.push({text: `Let a ${V.activeHooved.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "hooved"}});
-			}
-			if (V.farmyardCages > 0 && V.activeFeline !== 0) {
-				sexOptions.push({text: `Have a ${V.activeFeline.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "feline"}});
-			}
-		}
-		sexOptions.push({text: `Abuse ${him}`, scene: `FAbuse`});
-		if (V.seeIncest === 1) {
-			if (V.familyTesting === 1) {
-				const availRelatives = availableRelatives(slave);
-				if (availRelatives.mother) {
-					sexOptions.push({text: `Fuck ${him} with ${his} mother`, scene: `FRelation`, update: {partner: "mother"}});
-				} else if (availRelatives.motherName !== null) {
-					sexOptions.push({text: `${His} mother, ${availRelatives.motherName}, is unavailable`});
-				}
-				/*
-				if (availRelatives.father) {
-					sexOptions.push({text: `Fuck ${him} with ${his} father`, scene: `FRelation`, update: {partner: "father"}});
-				} else if (availRelatives.fatherName !== null) {
-					sexOptions.push({text: `${His} father, ${availRelatives.motherName}, is unavailable`});
-				}
-				*/
-				if (slave.daughters > 0) {
-					if (availRelatives.daughters === 0) {
-						if (slave.daughters === 1) {
-							sexOptions.push({text: `${His} ${availRelatives.oneDaughterRel} is unavailable`});
-						} else {
-							sexOptions.push({text: `${His} daughters are unavailable`});
-						}
-					} else {
-						if (slave.daughters === 1) {
-							sexOptions.push({text: `Fuck ${him} with ${his} ${availRelatives.oneDaughterRel}`, scene: `FRelation`, update: {partner: "daughter"}});
-						} else {
-							sexOptions.push({text: `Fuck ${him} with one of ${his} daughters`, scene: `FRelation`, update: {partner: "daughter"}});
-						}
-						/*
-						if (availRelatives.daughters > 1) {
-							sexOptions.push({text: `Fuck ${him} with ${his} daughters`, scene: `FRelation`, update: {partner: "daughter"}});
-						}
-						*/
-					}
-				}
-				if (slave.sisters > 0) {
-					if (availRelatives.sisters === 0) {
-						if (slave.sisters === 1) {
-							sexOptions.push({text: `${His} ${availRelatives.oneSisterRel} is unavailable`});
-						} else {
-							sexOptions.push({text: `${His} sisters are unavailable`});
-						}
-					} else {
-						if (slave.sisters === 1) {
-							sexOptions.push({text: `Fuck ${him} with ${his} ${availRelatives.oneSisterRel}`, scene: `FRelation`, update: {partner: "sister"}});
-						} else {
-							sexOptions.push({text: `Fuck ${him} with one of ${his} sisters`, scene: `FRelation`, update: {partner: "sister"}});
-						}
-						/*
-						if (availRelatives.sisters > 1) {
-							sexOptions.push({text: `Fuck ${him} with ${his} sisters`, scene: `FRelation`, update: {partner: "sisters}});
-						}
-						*/
-					}
-				}
-			} else {
-				if (slave.relation !== 0) {
-					let assayedSlave = getSlave(slave.relationTarget);
-					const
-					{
-						daughter: daughter2, mother: mother2
-					} = getPronouns(assayedSlave);
-					if (isSlaveAvailable(assayedSlave)) {
-						if (slave.relation === "mother") {
-							sexOptions.push({text: `Fuck ${him} with ${his} ${daughter2}`, scene: `FRelation`, update: {partner: "relation"}});
-						} else if (slave.relation === "daughter") {
-							sexOptions.push({text: `Fuck ${him} with ${his} ${mother2}`, scene: `FRelation`, update: {partner: "relation"}});
-						} else if (slave.relation === "sister") {
-							sexOptions.push({text: `Fuck ${him} with ${his} ${sister2}`, scene: `FRelation`, update: {partner: "relation"}});
-						} else if (slave.relation === "twin") {
-							sexOptions.push({text: `Fuck ${him} with ${his} twin`, scene: `FRelation`, update: {partner: "relation"}});
-						}
-					} else {
-						sexOptions.push({text: `${assayedSlave.slaveName} is unavailable`});
-					}
-				}
-			}
-		}
-		if (slave.relationship > 0) {
-			const lover = getSlave(slave.relationshipTarget);
-			if (isSlaveAvailable(lover)) {
-				sexOptions.push({text: `Fuck ${him} with ${his} ${relationshipTermShort(slave)} ${SlaveFullName(lover)}`, scene: `FRelation`, update: {partner: "relationship"}});
-			} else {
-				if (lover.assignment === "be your agent") {
-					if (slave.broodmother < 2) {
-						sexOptions.push({text: `Send ${him} to live with your agent ${SlaveFullName(lover)}`, goto: `Agent Company`, update: {subSlave: lover}});
-					} else {
-						sexOptions.push({text: `A hyper-broodmother cannot be sent to live with your agent`});
-					}
-				} else {
-					sexOptions.push({text: `${SlaveFullName(lover)} is unavailable`});
-				}
-			}
-		}
-		if (slave.rivalryTarget !== 0 && hasAllLimbs(slave)) {
-			const rival = getSlave(slave.relationshipTarget);
-			if (isSlaveAvailable(rival) && hasAnyLegs(rival)) {
-				sexOptions.push({text: `Abuse ${his} rival with ${him}`, scene: `FRival`});
-			}
-		}
-		if (slave.fetish !== "mindbroken" && (canTalk(slave) || hasAnyArms(slave))) {
-			sexOptions.push({text: `Ask ${him} about ${his} feelings`, scene: `FFeelings`});
-			if (V.PC.dick > 0) {
-				sexOptions.push({text: `Make ${him} beg`, scene: `FBeg`});
-			}
-		}
-		if (slave.devotion >= 100 && slave.relationship < 0 && slave.relationship > -3) {
-			sexOptions.push({text: `Talk to ${him} about relationships`, goto: `Matchmaking`, update: {subSlave: 0, eventSlave: slave}});
-		}
-		let ML = V.marrying.length;
-		if ((V.MixedMarriage === 1 || V.cheatMode === 1) && slave.relationship !== 5 && slave.relationship !== -3) {
-			if (V.marrying.includes(slave.ID)) {
-				sexOptions.push({text: `You are already marrying ${him} this weekend`});
-			} else {
-				if (ML < 2) {
-					if (V.cheatMode === 1 || ML === 0) {
-						sexOptions.push({text: `Marry ${him}`, goto: "FMarry"});
-					} else {
-						sexOptions.push({text: `You already have a wedding planned for this weekend`});
-					}
-				} else {
-					sexOptions.push({text: `You can only marry up to two slaves per week`});
-				}
-			}
-		}
-		if (V.cheatMode === 1) {
-			sexOptions.push({text: `Check ${his} stats`, scene: `Slave Stats`});
-		}
-	} else { /* IS A FUCKDOLL */
-		sexOptions.push({text: `Fuck ${his} face hole`, scene: `FFuckdollOral`});
-		if (canDoVaginal(slave)) {
-			sexOptions.push({text: `Fuck ${his} front hole`, scene: `FFuckdollVaginal`});
-		}
-		if (canGetPregnant(slave) && (slave.geneticQuirks.superfetation !== 2 || V.geneticMappingUpgrade !== 0) && V.seePreg !== 0) {
-			if (canImpreg(slave, V.PC)) {
-				sexOptions.push({text: `Put a baby in ${him}`, scene: `FFuckdollImpreg`});
-			}
-		}
-		if (canDoAnal(slave)) {
-			sexOptions.push({text: `Fuck ${his} rear hole`, scene: `FFuckdollAnal`});
-		}
-	}
-	let activeSlaveRepSacrifice = repGainSacrifice(slave, V.arcologies[0]);
-	if (activeSlaveRepSacrifice > 0 && V.arcologies[0].FSPaternalist === "unset" && (slave.breedingMark === 0 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) {
-		sexOptions.push({
-	text: `Sacrifice ${him} on the altar`, goto: `Aztec Slave Sacrifice`, note: `This will kill ${him} and gain you ${activeSlaveRepSacrifice} reputation`, update: {sacrificeType: "life"}
-		});
-	}
-	el.append(`Or use ${him} here: `);
-	el.appendChild(generateRow(sexOptions));
-	if (!jQuery.isEmptyObject(fillFaceOptions)) {
-		let fill = document.createElement('div');
-		fill.appendChild(document.createTextNode(` Fill ${his} mouth with: `));
-		fill.appendChild(generateRow(fillFaceOptions));
-		el.appendChild(fill);
-	}
-	if (!jQuery.isEmptyObject(fillAssOptions)) {
-		let fill = document.createElement('div');
-		fill.appendChild(document.createTextNode(` Fill ${his} ass with: `));
-		fill.appendChild(generateRow(fillAssOptions));
-		el.appendChild(fill);
-	}
-
-	function generateRow(sexArray) {
-		let row = document.createElement('span');
-		for (let i = 0; i < sexArray.length; i++) {
-			let link;
-			const separator  = document.createTextNode(` | `);
-			const keys = Object.keys(sexArray[i]);
-
-			// Test to see if there was a problem with the key
-			for (let j = 0; j < keys.length; j++) {
-				if (["text", "scene", "goto", "updateSlave", "update", "note"].includes(keys[j])) {
-					continue;
-				} else {
-					sexArray[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY";
-					console.log("Trash found while generateRow() was running: " + keys[j] + ": " + sexArray[i][keys[j]]);
-					break;
-				}
-			}
-			// is it just text?
-			if (keys.length === 1) {
-				if (sexArray[i].text) {
-					link = document.createTextNode(sexArray[i].text);
-				} else {
-					console.log(`expected 'text' only, got: ${sexArray[i]}`);
-					link = document.createTextNode("error, text not found");
-				}
-			} else {
-				let passage = "";
-				if (sexArray[i].goto) {
-					passage = sexArray[i].goto;
-				}
-
-				// Set up the link
-				link = App.UI.DOM.link(
-					sexArray[i].text,
-					() => { click(sexArray[i]); },
-					[],
-					passage
-				);
-
-				// add a note node if required
-				if (sexArray[i].note) {
-					let note  = document.createTextNode(sexArray[i].note);
-					note.className = "note";
-					link.appendChild(note);
-				}
-			}
-			row.appendChild(link);
-			if (i < sexArray.length-1) {
-				row.appendChild(separator);
-			}
-		}
-
-		return row;
-
-		function click(sexOption) {
-			if (sexOption.updateSlave) {
-				Object.assign(slave, sexOption.updateSlave);
-			}
-			if (sexOption.update) {
-				Object.assign(V, sexOption.update);
-			}
-
-			if (sexOption.scene) {
-				App.UI.replace('#miniscene', `<<include "${sexOption.scene}">>`);
-			} else if (sexOption.goto) {
-				App.UI.replace('#miniscene', `<<goto "${sexOption.goto}">>`);
-			}
-
-			SlaveInteractRefreshAll(slave);
-			return;
-		}
-	}
-	return jQuery('#useSlave').empty().append(el);
-};
-
-window.SlaveInteractBloating = function(slave) {
-	const
-		{
-			// eslint-disable-next-line no-unused-vars
-			he, him, his, hers, himself, boy, He, His
-		} = getPronouns(slave);
-	let bloating = document.createElement('div');
-	if (slave.inflation > 0) {
-		let intro = document.createElement('span');
-		intro.textContent = "Required Bloating";
-		intro.style.textDecoration = "underline";
-		bloating.append(intro);
-
-		bloating.append(": ");
-
-		let requirement = document.createElement('span');
-		requirement.style.fontWeight = "bold";
-		requirement.id = "inflate";
-		if (slave.inflation === 3) {
-			requirement.textContent = `${He} is required to keep 2 gallons of ${slave.inflationType} in ${him} at all times`;
-		} else if (slave.inflation === 2) {
-			requirement.textContent = `${He} is required to keep 4 liters of ${slave.inflationType} in ${him} at all times`;
-		} else if (slave.inflation === 1) {
-			requirement.textContent = `${He} is required to keep 2 liters of ${slave.inflationType} in ${him} at all times`;
-		}
-		bloating.append(requirement);
-		bloating.append(". ");
-
-		if (slave.inflationMethod === 3) {
-			let link = App.UI.DOM.link(
-				`Let ${him} deflate`,
-				() => {
-					slave.inflation = 0,
-					slave.inflationType = "none",
-					slave.inflationMethod = 0,
-					slave.cumSource = 0,
-					slave.milkSource = 0,
-					SetBellySize(slave),
-					SlaveInteractRefreshAll(slave);
-				},
-			);
-			bloating.append(link);
-		} else {
-			let link = App.UI.DOM.link(
-				`Let ${him} deflate`,
-				() => {
-					slave.inflation = 0,
-					slave.inflationType = "none",
-					slave.inflationMethod = 0,
-					SetBellySize(slave),
-					SlaveInteractRefreshAll(slave);
-				},
-			);
-			bloating.append(link);
-		}
-	}
-	// make sure it updates itself after run
-	return jQuery('#bloating').empty().append(bloating);
-};
-
-
-window.SlaveInteractFertility = function(slave) {
-	const
-		{
-			// eslint-disable-next-line no-unused-vars
-			he, him, his, hers, himself, boy, He, His
-		} = getPronouns(slave);
-	const separator  = document.createTextNode(` | `);
-	let fertilityblock = document.createElement('span');
-	if (slave.ovaries === 1 || slave.mpreg === 1 || slave.preg > 0) {
-		let note = document.createTextNode(``);
-		note.className = "note";
-		if (slave.preg < -1) {
-			note.textContent += `${He} is sterile`;
-		} else if (slave.pubertyXX === 0 && slave.preg < 1) {
-			note.textContent += `${He} is not yet fertile`;
-		} else if (slave.ovaryAge >= 47 && slave.preg < 1) {
-			note.textContent += `${He} is too old to become pregnant`;
-			if (slave.preg === -1) {
-				slave.preg = 0;
-				SetBellySize(slave);
-			}
-		} else if (slave.broodmotherOnHold === 1) {
-			note.textContent += `${His} pregnancy implant is turned off`;
-			if (slave.broodmotherCountDown > 0) {
-				note.textContent += `${he} is expected to be completely emptied of ${his} remaining brood in ${slave.broodmotherCountDown} week`;
-				if (slave.broodmotherCountDown > 1){
-					note.textContent += `s`;
-				}
-				note.textContent += `.`;
-				let link = App.UI.DOM.link(
-					`Turn on implant`,
-					() => {
-						slave.broodmotherOnHold = 0,
-						slave.broodmotherCountDown = 0;
-					},
-					[],
-					"Slave Interact"
-				);
-				fertilityblock.append(link);
-			}
-		} else if (slave.preg >= -1) {
-			fertilityblock.append("Contraception: ");
-			let fertility = document.createElement('span');
-			fertility.id = "fertility";
-			fertility.style.fontWeight = "bold";
-				if (slave.preg === -1) {
-					fertility.textContent = "using contraceptives";
-				} else if (slave.pregWeek < 0) {
-					fertility.textContent = "postpartum";
-				} else if (slave.preg === 0) {
-					fertility.textContent = "fertile";
-				} else if (slave.preg < 4) {
-					fertility.textContent = "may be pregnant";
-				} else {
-					fertility.textContent = `${slave.preg} weeks pregnant`;
-				}
-			fertility.textContent += ". ";
-			if (slave.preg > 0 && V.pregnancyMonitoringUpgrade === 1) {
-				fertilityblock.append(App.UI.DOM.passageLink("Inspect pregnancy", "Analyze Pregnancy"));
-				fertilityblock.append(` | `);
-			}
-			if (slave.preg === 0) {
-				let link = App.UI.DOM.link(
-					`Use contraceptives`,
-					() => {
-						slave.preg = -1,
-						SlaveInteractRefreshAll(slave);
-					},
-				);
-				fertilityblock.append(link);
-			} else if (slave.preg === -1) {
-				let link = App.UI.DOM.link(
-					`Let ${him} get pregnant`,
-					() => {
-						slave.preg = 0,
-						SlaveInteractRefreshAll(slave);
-					},
-				);
-				fertilityblock.append(link);
-			} else if (slave.induce === 1) {
-				note.textContent += `Hormones are being slipped into ${his} food; ${he} will give birth suddenly and rapidly this week`;
-			} else if (slave.preg > slave.pregData.normalBirth-2 && slave.preg > slave.pregData.minLiveBirth && slave.broodmother === 0 && slave.labor === 0) {
-				let link = App.UI.DOM.link(
-					`Induce labor`,
-					() => {
-						slave.labor = 1,
-						slave.induce = 1,
-						V.birthee = 1;
-					},
-					[],
-					"Slave Interact"
-				);
-				fertilityblock.append(link);
-				fertilityblock.appendChild(separator);
-				fertilityblock.append(App.UI.DOM.passageLink(`Give ${him} a cesarean section`, "csec"));
-			} else if (slave.broodmother > 0) {
-				if (slave.broodmotherOnHold !== 1) {
-					let link = App.UI.DOM.link(
-						`Turn off implant`,
-						() => {
-							slave.broodmotherOnHold = 1,
-							slave.broodmotherCountDown = 38-WombMinPreg(slave);
-						},
-					);
-					fertilityblock.append(link);
-				}
-				if (slave.broodmotherOnHold !== 1 && slave.preg >= 36) {
-					fertilityblock.appendChild(separator);
-				}
-				fertilityblock.appendChild(separator);
-				if (slave.preg > 37) {
-					fertilityblock.append(App.UI.DOM.passageLink(`Induce mass childbirth`, "BirthStorm"));
-				}
-			} else if (slave.preg > slave.pregData.minLiveBirth) {
-				let link = App.UI.DOM.link(
-					`Give  ${him} a cesarean section`,
-					() => {
-						slave.broodmotherOnHold = 0,
-						slave.broodmotherCountDown = 0;
-					},
-					[],
-					"csec"
-				);
-				fertilityblock.append(link);
-			} else if (slave.preg > 0 && slave.breedingMark === 1 && V.propOutcome === 1 && V.arcologies[0].FSRestart !== "unset" && V.eugenicsFullControl !== 1 && (slave.pregSource === -1 || slave.pregSource === -6)) {
-				note.textContent += "You are forbidden from aborting an Elite child";
-			} else if (slave.preg > 0) {
-				let link = App.UI.DOM.link(
-					`Abort ${his} pregnancy`,
-					() => {
-						slave.broodmotherOnHold = 0,
-						slave.broodmotherCountDown = 0;
-					},
-					[],
-					"Abort"
-				);
-				fertilityblock.append(link);
-			}
-		fertilityblock.append(note);
-		}
-	}
-	if (
-		(slave.pregKnown === 1) &&
-		(V.pregSpeedControl === 1) &&
-		(
-			slave.breedingMark !== 1 ||
-			V.propOutcome === 0 ||
-			V.eugenicsFullControl === 1 ||
-			V.arcologies[0].FSRestart === "unset"
-		) &&
-		(slave.indentureRestrictions < 1) &&
-		(slave.broodmother === 0) &&
-		V.seePreg !== 0
-	) {
-		let control = document.createElement('div');
-		let underline = document.createElement('span');
-
-		underline.style.textDecoration = "underline";
-		underline.textContent = "Pregnancy control";
-		control.append(underline);
-		control.append(": ");
-
-		if (slave.pregControl === "labor suppressors") {
-			control.append("Labor is suppressed. ");
-		} else if (slave.pregControl === "slow gestation") {
-			control.append("Slowed gestation speed. ");
-		} else if (slave.pregControl === "speed up") {
-			control.append("Faster gestation speed, staffed clinic recommended. ");
-		} else {
-			control.append("Normal gestation and birth. ");
-		}
-		fertilityblock.append(control);
-		control = document.createElement('div');
-		if (slave.preg >= slave.pregData.minLiveBirth) {
-			if (slave.pregControl === "labor suppressors") {
-				let link = App.UI.DOM.link(
-					`Normal Birth`,
-					() => {
-						slave.pregControl = "none",
-						SlaveInteractFertility(slave);
-					},
-				);
-				control.append(link);
-			} else {
-				let link = App.UI.DOM.link(
-					`Suppress Labor`,
-					() => {
-						slave.pregControl = "labor suppressors",
-						SlaveInteractFertility(slave);
-					},
-				);
-				control.append(link);
-			}
-		} else if (slave.preg < slave.pregData.normalBirth) {
-			if (slave.pregControl !== "none") {
-				let link = App.UI.DOM.link(
-					`Normal Gestation`,
-					() => {
-						slave.pregControl = "none",
-						SlaveInteractFertility(slave);
-					},
-				);
-				control.append(link);
-			}
-			if (slave.pregControl !== "slow gestation") {
-				control.append(separator);
-				let link = App.UI.DOM.link(
-					`Slow Gestation`,
-					() => {
-						slave.pregControl = "slow gestation",
-						SlaveInteractFertility(slave);
-					},
-				);
-				control.append(link);
-			}
-			if (slave.pregControl !== "speed up") {
-				control.append(separator);
-				let link = App.UI.DOM.link(
-					`Fast Gestation`,
-					() => {
-						slave.pregControl = "speed up",
-						SlaveInteractFertility(slave);
-					},
-				);
-				control.append(link);
-			}
-		}
-		fertilityblock.append(control);
-	}
-	return jQuery('#fertilityblock').empty().append(fertilityblock);
-};
-
-window.SlaveInteractRefreshAll = function(slave) {
-	SlaveInteractBloating(slave);
-	SlaveInteractFertility(slave);
-	useSlaveDisplay(slave);
-};
diff --git a/src/uncategorized/slaveInteract.tw b/src/uncategorized/slaveInteract.tw
index 5203120eed9..aff9b54d9d5 100644
--- a/src/uncategorized/slaveInteract.tw
+++ b/src/uncategorized/slaveInteract.tw
@@ -628,7 +628,7 @@
 
 	<<if $activeSlave.vagina > -1>>
 		<br>Vaginal accessory: ''<span id="vaginalAccessory">$activeSlave.vaginalAccessory</span>.''
-		<<link "None">><<set $activeSlave.vaginalAccessory = "none">><<replace "#vaginalAccessory">>$activeSlave.vaginalAccessory<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
+		<<link "None">><<set $activeSlave.vaginalAccessory = "none">><<replace "#vaginalAccessory">>$activeSlave.vaginalAccessory<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
 		<<if isItemAccessible("bullet vibrator")>>
 			| <<link "Bullet vibrator">><<set $activeSlave.vaginalAccessory = "bullet vibrator">><<replace "#vaginalAccessory">>$activeSlave.vaginalAccessory<</replace>><</link>>
 		<</if>>
@@ -660,7 +660,7 @@
 
 	<<if $activeSlave.dick > 0>>
 		<br>Dick accessory: ''<span id="dickAccessory">$activeSlave.dickAccessory</span>.''
-		<<link "None">><<set $activeSlave.dickAccessory = "none">><<replace "#dickAccessory">>$activeSlave.dickAccessory<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
+		<<link "None">><<set $activeSlave.dickAccessory = "none">><<replace "#dickAccessory">>$activeSlave.dickAccessory<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
 		<<if isItemAccessible("bullet vibrator") && $toysBoughtVaginalAttachments == 1>>
 			| <<link "Bullet vibrator">><<set $activeSlave.dickAccessory = "bullet vibrator">><<replace "#dickAccessory">>$activeSlave.dickAccessory<</replace>><</link>>
 		<</if>>
@@ -670,18 +670,18 @@
 	<</if>>
 
 	<br>Chastity device: ''<span id="chastity"><<if $activeSlave.chastityAnus == 1 && $activeSlave.chastityPenis == 1 && $activeSlave.chastityVagina == 1>>full chastity<<elseif $activeSlave.chastityPenis == 1 && $activeSlave.chastityVagina == 1>>genital chastity<<elseif $activeSlave.chastityAnus == 1 && $activeSlave.chastityPenis == 1>>combined chastity cage<<elseif $activeSlave.chastityAnus == 1 && $activeSlave.chastityVagina == 1>>combined chastity belt<<elseif $activeSlave.chastityVagina == 1>>chastity belt<<elseif $activeSlave.chastityPenis == 1>>chastity cage<<elseif $activeSlave.chastityAnus == 1>>anal chastity<<elseif $activeSlave.chastityAnus == 0 && $activeSlave.chastityPenis == 0 && $activeSlave.chastityVagina == 0>>none<<else>>THERE HAS BEEN AN ERROR<</if>></span>.''
-	<<link "None">><<set $activeSlave.chastityAnus = 0>><<set $activeSlave.chastityPenis = 0>><<set $activeSlave.chastityVagina = 0>><<replace "#chastity">>none<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
-	| <<link "Anal chastity">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 1>><<set $activeSlave.chastityPenis = 0>><<set $activeSlave.chastityVagina = 0>><<replace "#chastity">>anal chastity<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
+	<<link "None">><<set $activeSlave.chastityAnus = 0>><<set $activeSlave.chastityPenis = 0>><<set $activeSlave.chastityVagina = 0>><<replace "#chastity">>none<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
+	| <<link "Anal chastity">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 1>><<set $activeSlave.chastityPenis = 0>><<set $activeSlave.chastityVagina = 0>><<replace "#chastity">>anal chastity<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
 	<<if $activeSlave.vagina > -1>>
-		| <<link "Chastity belt">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 0>><<set $activeSlave.chastityPenis = 0>><<set $activeSlave.chastityVagina = 1>><<replace "#chastity">>Chastity belt<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
-		| <<link "Combined chastity belt">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 1>><<set $activeSlave.chastityPenis = 0>><<set $activeSlave.chastityVagina = 1>><<replace "#chastity">>Combined chastity belt<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
+		| <<link "Chastity belt">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 0>><<set $activeSlave.chastityPenis = 0>><<set $activeSlave.chastityVagina = 1>><<replace "#chastity">>Chastity belt<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
+		| <<link "Combined chastity belt">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 1>><<set $activeSlave.chastityPenis = 0>><<set $activeSlave.chastityVagina = 1>><<replace "#chastity">>Combined chastity belt<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
 	<</if>>
 	<<if $activeSlave.dick > 0>>
-		| <<link "Chastity cage">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 0>><<set $activeSlave.chastityPenis = 1>><<set $activeSlave.chastityVagina = 0>><<replace "#chastity">>Chastity cage<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
-		| <<link "Combined chastity cage">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 1>><<set $activeSlave.chastityPenis = 1>><<set $activeSlave.chastityVagina = 0>><<replace "#chastity">>Combined Chastity cage<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
+		| <<link "Chastity cage">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 0>><<set $activeSlave.chastityPenis = 1>><<set $activeSlave.chastityVagina = 0>><<replace "#chastity">>Chastity cage<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
+		| <<link "Combined chastity cage">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 1>><<set $activeSlave.chastityPenis = 1>><<set $activeSlave.chastityVagina = 0>><<replace "#chastity">>Combined Chastity cage<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
 		<<if $activeSlave.vagina > -1>>
-			| <<link "Genital chastity">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 0>><<set $activeSlave.chastityPenis = 1>><<set $activeSlave.chastityVagina = 1>><<replace "#chastity">>Genital chastity<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
-			| <<link "Full chastity">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 1>><<set $activeSlave.chastityPenis = 1>><<set $activeSlave.chastityVagina = 1>><<replace "#chastity">>Full chastity<</replace>><<run SlaveInteractRefreshAll($activeSlave)>><</link>>
+			| <<link "Genital chastity">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 0>><<set $activeSlave.chastityPenis = 1>><<set $activeSlave.chastityVagina = 1>><<replace "#chastity">>Genital chastity<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
+			| <<link "Full chastity">><<set $activeSlave.choosesOwnChastity = 0>><<set $activeSlave.chastityAnus = 1>><<set $activeSlave.chastityPenis = 1>><<set $activeSlave.chastityVagina = 1>><<replace "#chastity">>Full chastity<</replace>><<run App.UI.SlaveInteract.refreshAll($activeSlave)>><</link>>
 		<</if>>
 	<</if>>
 
@@ -720,7 +720,7 @@ Aphrodisiacs: <span id="aphrodisiacs"><strong><<if $activeSlave.aphrodisiacs > 1
 	| <<link "Anaphrodisiacs">><<set $activeSlave.aphrodisiacs = -1>><<replace "#aphrodisiacs">><strong>anaphrodisiacs</strong><</replace>><</link>>
 <br>
 <span id="fertilityblock"></span>
-<script>SlaveInteractFertility(V.activeSlave)</script>
+<script>App.UI.SlaveInteract.fertility(V.activeSlave)</script>
 <<set $reservedChildren = FetusGlobalReserveCount("incubator")>>
 <<set $reservedChildrenNursery = FetusGlobalReserveCount("nursery")>>
 <<set _reservedIncubator = WombReserveCount($activeSlave, "incubator")>>
@@ -838,7 +838,7 @@ Aphrodisiacs: <span id="aphrodisiacs"><strong><<if $activeSlave.aphrodisiacs > 1
 <</if>>
 
 <span id="bloating"></span>
-<script>SlaveInteractBloating(V.activeSlave)</script>
+<script>App.UI.SlaveInteract.bloating(V.activeSlave)</script>
 
 Hormones: <strong><span id="hormones">
 <<if $activeSlave.hormones == -2>>intensive male<<elseif $activeSlave.hormones == -1>>male<<elseif $activeSlave.hormones == 2>>intensive female<<elseif $activeSlave.hormones == 1>>female<<else>>none<</if>></span></strong>.
-- 
GitLab