From 04be163d63a69b738adfe457dbe8ad594ab5f74c Mon Sep 17 00:00:00 2001
From: lowercasedonkey <lowercasedonkey@gmail.com>
Date: Wed, 7 Oct 2020 17:21:04 -0400
Subject: [PATCH] work work

---
 src/interaction/siWork.js          | 496 ++++++++++++++++++++++++++++-
 src/interaction/slaveInteract.js   | 483 ----------------------------
 src/uncategorized/slaveInteract.tw |   5 +-
 3 files changed, 482 insertions(+), 502 deletions(-)

diff --git a/src/interaction/siWork.js b/src/interaction/siWork.js
index cc1b55c6cb9..eef1e0ceccf 100644
--- a/src/interaction/siWork.js
+++ b/src/interaction/siWork.js
@@ -1,7 +1,7 @@
 App.UI.SlaveInteract.work = function(slave) {
 	const el = document.createElement("p");
 	el.id = "si-work";
-	el.append(description());
+	el.append(work());
 	return el;
 
 	function work() {
@@ -11,8 +11,8 @@ App.UI.SlaveInteract.work = function(slave) {
 		let span;
 		const links = [];
 		const {
-			He,
-			him
+			His, He,
+			his, him
 		} = getPronouns(slave);
 
 		function appendLink(text, whoreClass, enabled, disabledText) {
@@ -30,13 +30,13 @@ App.UI.SlaveInteract.work = function(slave) {
 			const arc = V.arcologies.find((a) => a.leaderID === slave.ID);
 			p.className = "scene-intro";
 			p.textContent = `${He} is serving as your Agent${arc ? ` leading ${arc.name}` : ` but is not currently assigned to an arcology`}. `;
-			p.appendChild(App.UI.DOM.link(`Recall and reenslave ${him}`, () => { removeJob(slave, slave.assignment, false); App.UI.SlaveInteract.work(slave); }));
+			p.appendChild(App.UI.DOM.link(`Recall and reenslave ${him}`, () => { removeJob(slave, slave.assignment, false); refresh(); }));
 		} else if (slave.assignment === Job.AGENTPARTNER) {
 			const agent = getSlave(slave.relationshipTarget);
 			const arc = agent ? V.arcologies.find((a) => a.leaderID === agent.ID) : null;
 			p.className = "scene-intro";
 			p.textContent = `${He} is living with your Agent ${SlaveFullName(agent)}${arc ? ` in ${arc.name}` : ``}. `;
-			p.appendChild(App.UI.DOM.link(`Recall ${him}`, () => { removeJob(slave, slave.assignment, false); App.UI.SlaveInteract.work(slave); }));
+			p.appendChild(App.UI.DOM.link(`Recall ${him}`, () => { removeJob(slave, slave.assignment, false); refresh(); }));
 		} else {
 			div = document.createElement('div');
 			div.id = "mini-scene";
@@ -45,7 +45,7 @@ App.UI.SlaveInteract.work = function(slave) {
 			span = document.createElement('span');
 			span.id = "useSlave";
 			p.appendChild(span);
-			p.appendChild(App.UI.SlaveInteract.useSlaveDisplay(slave));
+			p.appendChild(useSlaveDisplay());
 		}
 		el.append(p);
 
@@ -96,7 +96,7 @@ App.UI.SlaveInteract.work = function(slave) {
 				span.textContent = `${He} is the Wardeness and is not available for other work`;
 				break;
 			default:
-			// CAN BE REASSIGNED
+				// CAN BE REASSIGNED
 				span.classList.remove("note");
 				span.id = "assignmentLinks";
 				span.appendChild(assignmentBlock());
@@ -108,7 +108,7 @@ App.UI.SlaveInteract.work = function(slave) {
 
 				div = document.createElement('div');
 				div.id = "fucktoy-pref";
-				div.append(App.UI.SlaveInteract.fucktoyPref(slave));
+				div.append(fucktoyPref());
 				span.appendChild(div);
 		}
 		el.append(span);
@@ -149,9 +149,10 @@ App.UI.SlaveInteract.work = function(slave) {
 		}
 
 		el.append(tutorBlock());
+		return el;
 
 		function generateLink(linkDesc) {
-		// is it just text?
+			// is it just text?
 			if (linkDesc.disabled) { return App.UI.DOM.disabledLink(linkDesc.text, [linkDesc.disabled]); }
 			// Are they already on this whoreClass?
 			if (linkDesc.whoreClass === slave.whoreClass) { return document.createTextNode(linkDesc.text); }
@@ -160,7 +161,7 @@ App.UI.SlaveInteract.work = function(slave) {
 				linkDesc.text,
 				() => {
 					slave.whoreClass = linkDesc.whoreClass;
-					App.UI.SlaveInteract.work(slave);
+					refresh();
 				},
 			);
 
@@ -214,7 +215,7 @@ App.UI.SlaveInteract.work = function(slave) {
 						`Stay on this assignment for another month`,
 						() => {
 							slave.sentence += 4;
-							App.UI.SlaveInteract.work(slave);
+							refresh();
 						},
 					)
 				);
@@ -256,7 +257,7 @@ App.UI.SlaveInteract.work = function(slave) {
 			}
 			const array = list.map((s) => {
 				if (shouldBeEnabled(slave, s)) {
-			 return App.UI.DOM.link(s, () => setTutorForSlave(slave, s));
+					return App.UI.DOM.link(s, () => setTutorForSlave(slave, s));
 				} else {
 					let reason = ["Already being taught this skill."];
 					return App.UI.DOM.disabledLink(s, reason);
@@ -282,14 +283,479 @@ App.UI.SlaveInteract.work = function(slave) {
 				if (cur !== tutor && tutor !== "None") {
 					V.slaveTutor[tutor].push(slave.ID);
 				}
-				App.UI.SlaveInteract.work(slave);
+				refresh();
 			}
 
 			return el;
-		};
+		}
 
-		return el;
+		function useSlaveDisplay() {
+			// Goal: Be able to write the entire "use her" block with only dom fragments.
+			let el = document.createElement('div');
+
+			/*
+			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 = [];
+			const dairyNameCaps = capFirstChar(V.dairyName);
+			// 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`});
+						}
+					} else {
+						sexOptions.push({text: `Fuck ${him}`, disabled: `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: `Fuck ${his} ass`, disabled: `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`});
+						sexOptions.push({text: `Eat ${him} out`, scene: `FLickPussy`});
+					}
+				}
+
+				if (slave.dick > 0) {
+					if (!(slave.chastityPenis)) {
+						sexOptions.push({text: `Grope ${his} dick`, scene: `FondleDick`});
+						if (canPenetrate(slave)) {
+							if (V.policies.sexualOpenness === 1 || slave.toyHole === "dick") {
+								sexOptions.push({text: `Ride ${his} dick`, scene: `FDick`});
+							}
+						}
+					} else {
+						sexOptions.push({text: `Use ${his} dick`, disabled: `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 !== Job.DAIRY && slave.assignment !== Job.ARCADE && slave.assignment !== Job.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 {
+							fillAssOptions.push({text: `Milk`, disabled: `${dairyNameCaps} is not producing enough milk to pump through the pipes`});
+							fillFaceOptions.push({text: `Milk`, disabled: `${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 {
+							fillAssOptions.push({text: `Cum`, disabled: `${dairyNameCaps} is not producing enough cum to pump through the pipes`});
+							fillFaceOptions.push({text: `Cum`, disabled: `${dairyNameCaps} is not producing enough cum to pump through the pipes`});
+						}
+					} /* dairyPiping === 1 */
+					if (V.boughtItem.toys.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.boughtItem.toys.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 !== Job.DAIRY && slave.assignment !== Job.ARCADE && slave.assignment !== Job.CELLBLOCK) {
+						if (V.boughtItem.toys.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) {
+					if (V.farmyardKennels > 0 && V.activeCanine) {
+						sexOptions.push({text: `Have a ${V.activeCanine.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "canine"}});
+					}
+					if (V.farmyardStables > 0 && V.activeHooved) {
+						sexOptions.push({text: `Let a ${V.activeHooved.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "hooved"}});
+					}
+					if (V.farmyardCages > 0 && V.activeFeline) {
+						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) {
+					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: `Fuck ${him} with ${his} daughter`, disabled: `${His} ${availRelatives.oneDaughterRel} is unavailable`});
+							} else {
+								sexOptions.push({text: `Fuck ${him} with one of ${his} daughters`, disabled: `${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: `Fuck ${him} with ${his} sister`, disabled: `${His} ${availRelatives.oneSisterRel} is unavailable`});
+							} else {
+								sexOptions.push({text: `Fuck ${him} with one of ${his} sisters`, disabled: `${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}});
+							}
+							*/
+						}
+					}
+				}
+				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 === Job.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}});
+				}
+				let ML = V.marrying.length;
+				if ((V.policies.mixedMarriage === 1 || V.cheatMode === 1) && slave.relationship !== 5 && slave.relationship !== -3) {
+					if (V.marrying.includes(slave.ID)) {
+						sexOptions.push({text: `Marry ${him}`, disabled: `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: `Marry ${him}`, disabled: `You already have a wedding planned for this weekend`});
+							}
+						} else {
+							sexOptions.push({text: `Marry ${him}`, disabled: `You can only marry up to two slaves per week`});
+						}
+					}
+				}
+				if (V.cheatMode === 1) {
+					sexOptions.push({text: `Check ${his} stats`, goto: `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(`Use ${him}: `);
+			el.appendChild(generateRows(sexOptions));
+			if (!jQuery.isEmptyObject(fillFaceOptions)) {
+				let fill = document.createElement('div');
+				fill.appendChild(document.createTextNode(` Fill ${his} mouth with: `));
+				fill.appendChild(generateRows(fillFaceOptions));
+				el.appendChild(fill);
+			}
+			if (!jQuery.isEmptyObject(fillAssOptions)) {
+				let fill = document.createElement('div');
+				fill.appendChild(document.createTextNode(` Fill ${his} ass with: `));
+				fill.appendChild(generateRows(fillAssOptions));
+				el.appendChild(fill);
+			}
+
+			function generateRows(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 (!["disabled", "goto", "note", "scene", "text", "update", "updateSlave"].includes(keys[j])) {
+							sexArray[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY";
+							console.log("Trash found while generateRows() was running: " + keys[j] + ": " + sexArray[i][keys[j]]);
+							break;
+						}
+					}
+					// is it just text?
+					if (sexArray[i].disabled) {
+						link = App.UI.DOM.disabledLink(sexArray[i].text, [sexArray[i].disabled]);
+					} 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) {
+							link.appendChild(App.UI.DOM.makeElement('span', sexArray[i].note, '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.goto) {
+						// just play the passage, no need to refresh anything here
+						Engine.play(sexOption.goto);
+					} else if (sexOption.scene) {
+						// Run scene and store render results temporarily
+						let frag = App.UI.DOM.renderPassage(sexOption.scene);
+
+						// Refresh (clears scene display)
+						App.UI.SlaveInteract.refreshAll(slave);
+
+						// Display scene render results
+						$("#mini-scene").append(frag);
+					} else {
+						// just refresh
+						App.UI.SlaveInteract.refreshAll(slave);
+					}
+				}
+			}
+			return el;
+		}
+
+		function fucktoyPref() {
+			const el = document.createElement('div');
+			let links = [];
+
+			function appendLink(text, toyHole, enabled, disabledText) {
+				const link = {text: text};
+				if (enabled) {
+					link.toyHole = toyHole;
+				} else {
+					link.disabled = disabledText;
+				}
+				links.push(link);
+			}
+
+			if ((slave.assignment === App.Data.Facilities.penthouse.jobs.fucktoy.assignment) || (slave.assignment === App.Data.Facilities.masterSuite.jobs.fucktoy.assignment) || (slave.assignment === App.Data.Facilities.masterSuite.manager.assignment)) {
+				App.UI.DOM.appendNewElement("span", el, "Fucktoy use preference:", "story-label");
+				el.append(` `);
+
+				const hole = App.UI.DOM.appendNewElement('span', el, `${slave.toyHole}. `);
+				hole.style.fontWeight = "bold";
+
+				appendLink('Mouth', 'mouth', true);
+				appendLink('Tits', 'boobs', true);
+				if (slave.vagina >= 0) {
+					appendLink('Pussy', 'pussy', slave.vagina > 0 && canDoVaginal(slave), `Take ${his} virginity before giving ${his} pussy special attention`);
+				}
+				appendLink('Ass', 'ass', (slave.anus > 0) && canDoAnal(slave), `Take ${his} anal virginity before giving ${his} ass special attention`);
+				if (slave.dick > 0 && canPenetrate(slave)) {
+					appendLink('Dick', 'dick', true);
+				}
+				appendLink('No Preference', "all her holes", true);
+			}
+
+			function generateLink(linkDesc) {
+				// is it just text?
+				if (linkDesc.disabled) { return App.UI.DOM.disabledLink(linkDesc.text, [linkDesc.disabled]); }
+				// Are they already on this toyHole?
+				if (linkDesc.toyHole === slave.toyHole) { return document.createTextNode(linkDesc.text); }
+				// Set up the link
+				const link = App.UI.DOM.link(
+					linkDesc.text,
+					() => {
+						slave.toyHole = linkDesc.toyHole;
+						jQuery('#fucktoy-pref').empty().append(fucktoyPref());
+					},
+				);
+
+				// add a note node if required
+				if (linkDesc.note) {
+					App.UI.DOM.appendNewElement("span", link, linkDesc.note, "note");
+				}
+				return link;
+			}
+
+			el.appendChild(App.UI.DOM.generateLinksStrip(links.map(generateLink)));
+
+			return el;
+		}
 	}
+
 	function refresh() {
 		jQuery("#si-work").empty().append(work());
 	}
diff --git a/src/interaction/slaveInteract.js b/src/interaction/slaveInteract.js
index 98e15986f3e..35e4f782e7a 100644
--- a/src/interaction/slaveInteract.js
+++ b/src/interaction/slaveInteract.js
@@ -62,489 +62,6 @@ App.UI.SlaveInteract.navigation = function(slave) {
 	}
 };
 
-/**
- * @param {App.Entity.SlaveState} slave
- * @returns {HTMLElement}
- */
-App.UI.SlaveInteract.fucktoyPref = function(slave) {
-	const {his} = getPronouns(slave);
-	const el = document.createElement('div');
-	let links = [];
-
-	function appendLink(text, toyHole, enabled, disabledText) {
-		const link = {text: text};
-		if (enabled) {
-			link.toyHole = toyHole;
-		} else {
-			link.disabled = disabledText;
-		}
-		links.push(link);
-	}
-
-	if ((slave.assignment === App.Data.Facilities.penthouse.jobs.fucktoy.assignment) || (slave.assignment === App.Data.Facilities.masterSuite.jobs.fucktoy.assignment) || (slave.assignment === App.Data.Facilities.masterSuite.manager.assignment)) {
-		App.UI.DOM.appendNewElement("span", el, "Fucktoy use preference:", "story-label");
-		el.append(` `);
-
-		const hole = App.UI.DOM.appendNewElement('span', el, `${slave.toyHole}. `);
-		hole.style.fontWeight = "bold";
-
-		appendLink('Mouth', 'mouth', true);
-		appendLink('Tits', 'boobs', true);
-		if (slave.vagina >= 0) {
-			appendLink('Pussy', 'pussy', slave.vagina > 0 && canDoVaginal(slave), `Take ${his} virginity before giving ${his} pussy special attention`);
-		}
-		appendLink('Ass', 'ass', (slave.anus > 0) && canDoAnal(slave), `Take ${his} anal virginity before giving ${his} ass special attention`);
-		if (slave.dick > 0 && canPenetrate(slave)) {
-			appendLink('Dick', 'dick', true);
-		}
-		appendLink('No Preference', "all her holes", true);
-	}
-
-	function generateLink(linkDesc) {
-		// is it just text?
-		if (linkDesc.disabled) { return App.UI.DOM.disabledLink(linkDesc.text, [linkDesc.disabled]); }
-		// Are they already on this toyHole?
-		if (linkDesc.toyHole === slave.toyHole) { return document.createTextNode(linkDesc.text); }
-		// Set up the link
-		const link = App.UI.DOM.link(
-			linkDesc.text,
-			() => {
-				slave.toyHole = linkDesc.toyHole;
-				jQuery('#fucktoy-pref').empty().append(App.UI.SlaveInteract.fucktoyPref(slave));
-			},
-		);
-
-		// add a note node if required
-		if (linkDesc.note) {
-			App.UI.DOM.appendNewElement("span", link, linkDesc.note, "note");
-		}
-		return link;
-	}
-
-	el.appendChild(App.UI.DOM.generateLinksStrip(links.map(generateLink)));
-
-	return 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 = [];
-	const dairyNameCaps = capFirstChar(V.dairyName);
-	// 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`});
-				}
-			} else {
-				sexOptions.push({text: `Fuck ${him}`, disabled: `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: `Fuck ${his} ass`, disabled: `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`});
-				sexOptions.push({text: `Eat ${him} out`, scene: `FLickPussy`});
-			}
-		}
-
-		if (slave.dick > 0) {
-			if (!(slave.chastityPenis)) {
-				sexOptions.push({text: `Grope ${his} dick`, scene: `FondleDick`});
-				if (canPenetrate(slave)) {
-					if (V.policies.sexualOpenness === 1 || slave.toyHole === "dick") {
-						sexOptions.push({text: `Ride ${his} dick`, scene: `FDick`});
-					}
-				}
-			} else {
-				sexOptions.push({text: `Use ${his} dick`, disabled: `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 !== Job.DAIRY && slave.assignment !== Job.ARCADE && slave.assignment !== Job.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 {
-					fillAssOptions.push({text: `Milk`, disabled: `${dairyNameCaps} is not producing enough milk to pump through the pipes`});
-					fillFaceOptions.push({text: `Milk`, disabled: `${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 {
-					fillAssOptions.push({text: `Cum`, disabled: `${dairyNameCaps} is not producing enough cum to pump through the pipes`});
-					fillFaceOptions.push({text: `Cum`, disabled: `${dairyNameCaps} is not producing enough cum to pump through the pipes`});
-				}
-			} /* dairyPiping === 1 */
-			if (V.boughtItem.toys.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.boughtItem.toys.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 !== Job.DAIRY && slave.assignment !== Job.ARCADE && slave.assignment !== Job.CELLBLOCK) {
-				if (V.boughtItem.toys.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) {
-			if (V.farmyardKennels > 0 && V.activeCanine) {
-				sexOptions.push({text: `Have a ${V.activeCanine.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "canine"}});
-			}
-			if (V.farmyardStables > 0 && V.activeHooved) {
-				sexOptions.push({text: `Let a ${V.activeHooved.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "hooved"}});
-			}
-			if (V.farmyardCages > 0 && V.activeFeline) {
-				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) {
-			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: `Fuck ${him} with ${his} daughter`, disabled: `${His} ${availRelatives.oneDaughterRel} is unavailable`});
-					} else {
-						sexOptions.push({text: `Fuck ${him} with one of ${his} daughters`, disabled: `${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: `Fuck ${him} with ${his} sister`, disabled: `${His} ${availRelatives.oneSisterRel} is unavailable`});
-					} else {
-						sexOptions.push({text: `Fuck ${him} with one of ${his} sisters`, disabled: `${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}});
-					}
-					*/
-				}
-			}
-		}
-		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 === Job.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}});
-		}
-		let ML = V.marrying.length;
-		if ((V.policies.mixedMarriage === 1 || V.cheatMode === 1) && slave.relationship !== 5 && slave.relationship !== -3) {
-			if (V.marrying.includes(slave.ID)) {
-				sexOptions.push({text: `Marry ${him}`, disabled: `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: `Marry ${him}`, disabled: `You already have a wedding planned for this weekend`});
-					}
-				} else {
-					sexOptions.push({text: `Marry ${him}`, disabled: `You can only marry up to two slaves per week`});
-				}
-			}
-		}
-		if (V.cheatMode === 1) {
-			sexOptions.push({text: `Check ${his} stats`, goto: `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(`Use ${him}: `);
-	el.appendChild(generateRows(sexOptions));
-	if (!jQuery.isEmptyObject(fillFaceOptions)) {
-		let fill = document.createElement('div');
-		fill.appendChild(document.createTextNode(` Fill ${his} mouth with: `));
-		fill.appendChild(generateRows(fillFaceOptions));
-		el.appendChild(fill);
-	}
-	if (!jQuery.isEmptyObject(fillAssOptions)) {
-		let fill = document.createElement('div');
-		fill.appendChild(document.createTextNode(` Fill ${his} ass with: `));
-		fill.appendChild(generateRows(fillAssOptions));
-		el.appendChild(fill);
-	}
-
-	function generateRows(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 (!["disabled", "goto", "note", "scene", "text", "update", "updateSlave"].includes(keys[j])) {
-					sexArray[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY";
-					console.log("Trash found while generateRows() was running: " + keys[j] + ": " + sexArray[i][keys[j]]);
-					break;
-				}
-			}
-			// is it just text?
-			if (sexArray[i].disabled) {
-				link = App.UI.DOM.disabledLink(sexArray[i].text, [sexArray[i].disabled]);
-			} 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) {
-					link.appendChild(App.UI.DOM.makeElement('span', sexArray[i].note, '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.goto) {
-				// just play the passage, no need to refresh anything here
-				Engine.play(sexOption.goto);
-			} else if (sexOption.scene) {
-				// Run scene and store render results temporarily
-				let frag = App.UI.DOM.renderPassage(sexOption.scene);
-
-				// Refresh (clears scene display)
-				App.UI.SlaveInteract.refreshAll(slave);
-
-				// Display scene render results
-				$("#mini-scene").append(frag);
-			} else {
-				// just refresh
-				App.UI.SlaveInteract.refreshAll(slave);
-			}
-		}
-	}
-	return el;
-};
-
 App.UI.SlaveInteract.custom = (function() {
 	let el;
 	let label;
diff --git a/src/uncategorized/slaveInteract.tw b/src/uncategorized/slaveInteract.tw
index af14eb5cf94..23387c6248b 100644
--- a/src/uncategorized/slaveInteract.tw
+++ b/src/uncategorized/slaveInteract.tw
@@ -90,10 +90,7 @@
 
 <div id="Work" class="tab-content">
 	<div class="content">
-		<p id="work"></p>
-		<script>
-			App.UI.SlaveInteract.work(getSlave(V.AS))
-		</script>
+		<<includeDOM App.UI.SlaveInteract.work(getSlave(V.AS))>>
 	</div>
 </div>
 
-- 
GitLab