From 4059535e12291df7118fa64ac285633ab8eb4acd Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Thu, 7 Jan 2021 12:37:21 -0800
Subject: [PATCH] Move slave-scoped temporary cross-report variables out of
 saVars and onto a proxy object, so they get reset automatically.

---
 devTools/types/FC/gameState.d.ts              |   1 -
 devTools/types/FC/human.d.ts                  |  12 +-
 src/endWeek/endWeekUtils.js                   |  75 +++++++++++-
 src/endWeek/healthFunctions.js                |  20 ++--
 src/endWeek/reports/arcadeReport.js           |   2 +-
 src/endWeek/reports/brothelReport.js          |  25 ++--
 src/endWeek/reports/cellblockReport.js        |   4 +-
 src/endWeek/reports/clinicReport.js           |   4 +-
 src/endWeek/reports/clubReport.js             |   4 +-
 src/endWeek/reports/dairyReport.js            |   4 +-
 src/endWeek/reports/farmyardReport.js         |   4 +-
 src/endWeek/reports/masterSuiteReport.js      |  15 +--
 src/endWeek/reports/nurseryReport.js          |   4 +-
 src/endWeek/reports/penthouseReport.js        |  63 +++++------
 src/endWeek/reports/schoolroomReport.js       |   4 +-
 src/endWeek/reports/servantsQuartersReport.js |   4 +-
 src/endWeek/reports/spaReport.js              |   4 +-
 src/endWeek/saBeYourHeadGirl.js               |   4 +-
 src/endWeek/saDiet.js                         |  12 +-
 src/endWeek/saLiveWithHG.js                   |   6 +-
 src/endWeek/saLongTermEffects.js              |  16 +--
 src/endWeek/saLongTermMentalEffects.js        | 107 +++++++++---------
 src/endWeek/saLongTermPhysicalEffects.js      |   9 +-
 src/endWeek/saPregnancy.js                    |   8 +-
 src/endWeek/saRelationships.js                |  14 +--
 src/endWeek/saRules.js                        |  41 +++----
 src/endWeek/saServeYourOtherSlaves.js         |   4 +-
 src/endWeek/saSharedVariables.js              |  16 ---
 src/endWeek/saSocialEffects.js                |  11 +-
 src/endWeek/saWhore.js                        |   4 +-
 src/endWeek/slaveAssignmentReport.js          |   3 -
 src/endWeek/standardSlaveReport.js            |   4 +-
 src/js/SlaveState.js                          |   2 +
 src/js/utilsSlave.js                          |   4 +-
 34 files changed, 274 insertions(+), 240 deletions(-)

diff --git a/devTools/types/FC/gameState.d.ts b/devTools/types/FC/gameState.d.ts
index 922673d8a52..7a807edc4ba 100644
--- a/devTools/types/FC/gameState.d.ts
+++ b/devTools/types/FC/gameState.d.ts
@@ -155,7 +155,6 @@ declare namespace FC {
 		lastWeeksRepErrors?: string;
 		lastWeeksCashErrors?: string;
 
-		slaveUsedRest?: 1;
 		arcadeDemandDegResult?: 1 | 2 | 3 | 4 | 5;
 
 		FarmerDevotionThreshold?: number;
diff --git a/devTools/types/FC/human.d.ts b/devTools/types/FC/human.d.ts
index 35c15fc8a87..9f8c72766ed 100644
--- a/devTools/types/FC/human.d.ts
+++ b/devTools/types/FC/human.d.ts
@@ -18,6 +18,14 @@ declare global {
 			beforeGingering?: SlaveState;
 		}
 
+		export interface ReportSlave extends SlaveState {
+			paraphiliaSatisfied: number;
+			pornFameBonus: number;
+			inappropriateLactation: number;
+			fetishChanged: number;
+			slaveUsedRest: number;
+		}
+
 		export type SlaveUpdate = DeepPartialSlaveState;
 
 		//#region SlaveState types
@@ -211,7 +219,7 @@ declare global {
 			/** prefers big cocks */
 			| "size queen">;
 
-		type BreastShape = "normal" | "perky" | "saggy" | "torpedo-shaped" | "downward-facing" | "wide-set" | "deflated";
+		type BreastShape = "normal" | "perky" | "saggy" | "torpedo-shaped" | "downward-facing" | "wide-set" | "deflated" | "spherical";
 		type Diet = "healthy" | "restricted" | "corrective" | "muscle building" | "fattening" | "slimming" | "XX" | "XY" | "XXY" |
 			"cum production" | "cleansing" | "fertility" | "high caloric";
 		type Drug = "no drugs" |
@@ -255,7 +263,7 @@ declare global {
 		type TailShape = WithNone<"neko" | "inu" | "kit" | "kitsune" | "tanuki" | "ushi" | "usagi" | "risu" | "uma">;
 		type ToyHole = "all her holes" | "mouth" | "boobs" | "pussy" | "ass" | "dick";
 		type OvaryImplantType = 0 | "fertility" | "sympathy" | "asexual";
-		type NippleShape = "huge" | "puffy" | "inverted" | "tiny" | "cute" | "partially inverted" | "fuckable";
+		type NippleShape = "huge" | "puffy" | "inverted" | "tiny" | "cute" | "partially inverted" | "fuckable" | "flat";
 		/**
 		 * 0: no; 1: yes; 2: heavy
 		 */
diff --git a/src/endWeek/endWeekUtils.js b/src/endWeek/endWeekUtils.js
index 3e17832622d..3edbe5d4daa 100644
--- a/src/endWeek/endWeekUtils.js
+++ b/src/endWeek/endWeekUtils.js
@@ -1,14 +1,77 @@
 /**
  * Sets slave's fetish
- * @param {App.Entity.SlaveState} slave
- * @param {string} fetish
- * @param {int} strength
+ * @param {App.Entity.SlaveState|FC.ReportSlave} slave
+ * @param {FC.Fetish} fetish
+ * @param {number} strength
  */
 globalThis.fetishChange = function(slave, fetish, strength = 65) {
 	slave.fetish = fetish;
 	slave.fetishStrength = strength;
 	slave.fetishKnown = 1;
-	if (App.EndWeek.saVars) {
-		App.EndWeek.saVars.fetishChanged = 1;
+	if ('fetishChanged' in slave) {
+		slave.fetishChanged = 1;
+	}
+};
+
+/**
+ * Make a report slave proxy. This binds extra temporary data to a specific slave as she runs through all the SA reports.
+ * Use the {FC.ReportSlave} type to denote that your function requires this temporary proxy data.
+ * @param {App.Entity.SlaveState} slave
+ * @returns {FC.ReportSlave}
+ */
+App.SlaveAssignment.reportSlave = function(slave) {
+	const proxyProperties = {
+		/** Is this slave's paraphilia satisfied? (1: satisfied, 0: no paraphilia; -1: unsatisfied) */
+		paraphiliaSatisfied: 0,
+		/** A slave with a lot of porn viewers will have a stronger effect on societal norms. This is her multiplier for those effects. */
+		pornFameBonus: 1,
+		/** Used to condense all the possible galactorrhea lactation start points to a single line of text in saLongTermPhysicalEffects. */
+		inappropriateLactation: 0,
+		/** Used limit a slave to a single fetish change per week. */
+		fetishChanged: 0,
+		/** Is the slave resting this week? */
+		slaveUsedRest: 0,
+	};
+
+	/** effectively merge the proxy properties onto the slave
+	 * @returns {ProxyHandler<App.Entity.SlaveState>}
+	 */
+	function handler() {
+		return {
+			get(target, key) {
+				if (key in proxyProperties) {
+					return proxyProperties[key];
+				}
+				return target[key];
+			},
+			set(target, key, value) {
+				if (key in proxyProperties) {
+					proxyProperties[key] = value;
+				}
+				target[key] = value;
+				return true;
+			},
+			has(target, key) {
+				if (key in proxyProperties) {
+					return true;
+				}
+				return key in target;
+			}
+		};
+	}
+	return /** @type {FC.ReportSlave} */ (new Proxy(slave, handler()));
+};
+
+/**
+ * Iterable which gets prepared slaves via App.SlaveAssignment.reportSlave
+ * @param {App.Entity.SlaveState[]} slaves
+ * @yields {FC.ReportSlave}
+ */
+App.SlaveAssignment.reportSlaves = function*(slaves) {
+	let iterationCount = 0;
+	for (const slave of slaves) {
+		iterationCount++;
+		yield App.SlaveAssignment.reportSlave(slave);
 	}
-};
\ No newline at end of file
+	return iterationCount;
+};
diff --git a/src/endWeek/healthFunctions.js b/src/endWeek/healthFunctions.js
index 64b4202b316..83c389c795b 100644
--- a/src/endWeek/healthFunctions.js
+++ b/src/endWeek/healthFunctions.js
@@ -367,7 +367,7 @@ globalThis.slaveResting = function(slave) {
 
 /**
  * Run at the end of the week to take care of tiredness changes
- * @param {App.Entity.SlaveState} slave
+ * @param {FC.ReportSlave} slave
  * @returns {void}
  */
 globalThis.tired = function(slave) {
@@ -403,14 +403,14 @@ globalThis.tired = function(slave) {
 		} else if ([Job.HEADGIRL].includes(slave.assignment)) {
 			if (slaveResting(slave)) {
 				assignment -= 40;
-				V.slaveUsedRest = 1;
+				slave.slaveUsedRest = 1;
 			} else {
 				assignment += 22; // Always busy. Could benefit from a helper...
 			}
 		} else if (App.Data.misc.facilityHeads.includes(slave.assignment)) { // Heads are very busy, but always have luxurious conditions, so it balances out, save for the exceptions
 			if (slaveResting(slave)) {
 				assignment -= 10;
-				V.slaveUsedRest = 1;
+				slave.slaveUsedRest = 1;
 			} else {
 				assignment += 15;
 			}
@@ -433,7 +433,7 @@ globalThis.tired = function(slave) {
 		} else if ([Job.SUBORDINATE].includes(slave.assignment)) {
 			if (slaveResting(slave)) {
 				assignment -= 20;
-				V.slaveUsedRest = 1;
+				slave.slaveUsedRest = 1;
 			} else if (slave.subTarget === -1) {
 				if (slave.health.tired + 5 >= 90 && !willWorkToDeath(slave)) {
 					assignment += 1;
@@ -468,7 +468,7 @@ globalThis.tired = function(slave) {
 				// Additional invasions multiply it
 				if (slaveResting(slave)) {
 					assignment -= 20;
-					V.slaveUsedRest = 1;
+					slave.slaveUsedRest = 1;
 				} else if (slave.health.tired + 9 >= 90 && !willWorkToDeath(slave)) {
 					assignment += 2;
 				} else if (slave.devotion > 20) {
@@ -483,7 +483,7 @@ globalThis.tired = function(slave) {
 			} else { // Being a free range cow is relatively relaxing
 				if (slaveResting(slave)) {
 					assignment -= 40;
-					V.slaveUsedRest = 1;
+					slave.slaveUsedRest = 1;
 				} else if (slave.health.tired + 5 >= 90 && !willWorkToDeath(slave)) {
 					assignment += 2;
 				} else if (slave.devotion > 20) {
@@ -498,7 +498,7 @@ globalThis.tired = function(slave) {
 		} else if ([Job.MILKED].includes(slave.assignment)) {
 			if (slaveResting(slave)) {
 				assignment -= 5;
-				V.slaveUsedRest = 1;
+				slave.slaveUsedRest = 1;
 			} else if (slave.health.tired + 8 >= 90 && !willWorkToDeath(slave)) {
 				assignment += 1;
 			} else if (slave.devotion > 20) {
@@ -547,7 +547,7 @@ globalThis.tired = function(slave) {
 		} else if ([Job.GLORYHOLE, Job.FARMYARD].includes(slave.assignment)) { // Hard assignments
 			if (slaveResting(slave)) {
 				assignment -= 20;
-				V.slaveUsedRest = 1;
+				slave.slaveUsedRest = 1;
 			} else if (slave.health.tired + 20 >= 90 && !willWorkToDeath(slave)) {
 				assignment += 1;
 			} else if (slave.devotion > 20) {
@@ -558,7 +558,7 @@ globalThis.tired = function(slave) {
 		} else if (App.Data.misc.whoringAssignments.includes(slave.assignment)) { // Moderate assignments
 			if (slaveResting(slave)) {
 				assignment -= 20;
-				V.slaveUsedRest = 1;
+				slave.slaveUsedRest = 1;
 			} else if (slave.health.tired + 15 >= 90 && !willWorkToDeath(slave)) {
 				assignment += 1;
 			} else if (slave.devotion > 20) {
@@ -569,7 +569,7 @@ globalThis.tired = function(slave) {
 		} else if ([Job.FUCKTOY, Job.HOUSE, Job.QUARTER].includes(slave.assignment)) { // Easy assignments
 			if (slaveResting(slave)) {
 				assignment -= 20;
-				V.slaveUsedRest = 1;
+				slave.slaveUsedRest = 1;
 			} else if (slave.health.tired + 11 >= 90 && !willWorkToDeath(slave)) {
 				assignment += 1;
 			} else if (slave.devotion > 20) {
diff --git a/src/endWeek/reports/arcadeReport.js b/src/endWeek/reports/arcadeReport.js
index 40aa29586d6..a15d9d6fe77 100644
--- a/src/endWeek/reports/arcadeReport.js
+++ b/src/endWeek/reports/arcadeReport.js
@@ -37,7 +37,7 @@ App.EndWeek.arcadeReport = function() {
 		App.Events.addNode(el, [`${arcadeNameCaps}'s customers enjoy <span class="green">getting off in ${V.arcadeDecoration} surroundings.</span>`], "p", "indent");
 	}
 
-	for (const slave of slaves) {
+	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 		const {He} = getPronouns(slave);
 		r = [];
 		/* for the included passages */
diff --git a/src/endWeek/reports/brothelReport.js b/src/endWeek/reports/brothelReport.js
index f22c8e70c04..5bd5e95a8f6 100644
--- a/src/endWeek/reports/brothelReport.js
+++ b/src/endWeek/reports/brothelReport.js
@@ -5,13 +5,13 @@ App.EndWeek.brothelReport = function() {
 	const brothelStats = document.createElement("span");
 	el.append(brothelStats);
 
+	const madam = S.Madam ? App.SlaveAssignment.reportSlave(S.Madam) : undefined;
 	const slaves = App.Utils.sortedEmployees(App.Entity.facilities.brothel);
 	const SL = slaves.length;
 	let profits = 0;
 	V.legendaryWhoreID = 0;
 	V.legendaryWombID = 0;
 
-
 	// Statistics gathering
 	V.facility = V.facility || {};
 	V.facility.brothel = initFacilityStatistics(V.facility.brothel);
@@ -212,18 +212,18 @@ App.EndWeek.brothelReport = function() {
 			}
 			App.Events.addNode(el, r);
 
-			if ((SL + V.brothelSlavesGettingHelp < 10) && V.MadamNoSex !== 1 && !slaveResting(S.Madam)) {
+			if ((SL + V.brothelSlavesGettingHelp < 10) && V.MadamNoSex !== 1 && !slaveResting(madam)) {
 				const oldCash = V.cash;
 				if (V.showEWD !== 0) {
 					App.Events.addParagraph(
 						el,
 						[
 							He,
-							App.SlaveAssignment.whore(S.Madam)
+							App.SlaveAssignment.whore(madam)
 						]
 					);
 				} else {
-					App.SlaveAssignment.whore(S.Madam);
+					App.SlaveAssignment.whore(madam);
 				}
 				App.Events.addParagraph(
 					el,
@@ -252,23 +252,22 @@ App.EndWeek.brothelReport = function() {
 		el.append(whoreNumber);
 	}
 
-	if (S.Madam) {
-		const slave = S.Madam;
-		tired(slave);
+	if (madam) {
+		tired(madam);
 		if (V.showEWD !== 0) {
 			const madamEntry = App.UI.DOM.appendNewElement("div", el, '', "slave-report");
-			App.SlaveAssignment.appendSlaveArt(madamEntry, slave);
-			madamEntry.append(App.UI.favoriteToggle(slave), " ");
+			App.SlaveAssignment.appendSlaveArt(madamEntry, madam);
+			madamEntry.append(App.UI.favoriteToggle(madam), " ");
 			App.Events.addNode(
 				madamEntry,
 				[
-					App.UI.DOM.makeElement("span", SlaveFullName(slave), "slave-name"),
+					App.UI.DOM.makeElement("span", SlaveFullName(madam), "slave-name"),
 					`is serving as the Madam.`
 				]
 			);
-			madamEntry.append(App.SlaveAssignment.standardSlaveReport(slave, false));
+			madamEntry.append(App.SlaveAssignment.standardSlaveReport(madam, false));
 		} else {
-			App.SlaveAssignment.standardSlaveReport(slave, true);
+			App.SlaveAssignment.standardSlaveReport(madam, true);
 		}
 	}
 
@@ -283,7 +282,7 @@ App.EndWeek.brothelReport = function() {
 			aphrodisiacs = 2;
 		}
 		let oldCash = V.cash;
-		for (const slave of slaves) {
+		for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 			if ((V.legendaryWombID === 0) && (!isAmputee(slave)) && (slave.preg > slave.pregData.normalBirth / 1.33) && (slave.broodmother === 0) && (slave.eggType === "human") && (slave.counter.births > 10) && (slave.devotion > 50) && (slave.prestige === 0)) {
 				V.legendaryWombID = slave.ID;
 			}
diff --git a/src/endWeek/reports/cellblockReport.js b/src/endWeek/reports/cellblockReport.js
index 344449e1a79..b5148073f9d 100644
--- a/src/endWeek/reports/cellblockReport.js
+++ b/src/endWeek/reports/cellblockReport.js
@@ -169,7 +169,7 @@ App.EndWeek.cellblockReport = function() {
 
 
 	if (S.Wardeness) {
-		const slave = S.Wardeness;
+		const slave = App.SlaveAssignment.reportSlave(S.Wardeness);
 		tired(slave);
 		/* apply following SA passages to facility leader */
 		if (V.showEWD !== 0) {
@@ -189,7 +189,7 @@ App.EndWeek.cellblockReport = function() {
 		}
 	}
 
-	for (const slave of slaves) {
+	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 		const {He} = getPronouns(slave);
 		if (slave.devotion <= 20) {
 			if (slave.trust >= -20) {
diff --git a/src/endWeek/reports/clinicReport.js b/src/endWeek/reports/clinicReport.js
index 4583fe98399..f8d4ff599e6 100644
--- a/src/endWeek/reports/clinicReport.js
+++ b/src/endWeek/reports/clinicReport.js
@@ -251,7 +251,7 @@ App.EndWeek.clinicReport = function() {
 	}
 
 	if (S.Nurse) {
-		const slave = S.Nurse;
+		const slave = App.SlaveAssignment.reportSlave(S.Nurse);
 		tired(slave);
 		/* apply following SA passages to facility leader */
 		if (V.showEWD !== 0) {
@@ -266,7 +266,7 @@ App.EndWeek.clinicReport = function() {
 	}
 
 	let restedSlaves = 0;
-	for (const slave of slaves) {
+	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 		if (slave.devotion < 45) {
 			slave.devotion += 4;
 		}
diff --git a/src/endWeek/reports/clubReport.js b/src/endWeek/reports/clubReport.js
index 20230974547..efa670f5751 100644
--- a/src/endWeek/reports/clubReport.js
+++ b/src/endWeek/reports/clubReport.js
@@ -138,7 +138,7 @@ App.EndWeek.clubReport = function() {
 	}
 
 	if (S.DJ) {
-		const slave = S.DJ;
+		const slave = App.SlaveAssignment.reportSlave(S.DJ);
 		tired(slave);
 		/* apply following SA passages to facility leader */
 		if (V.showEWD !== 0) {
@@ -159,7 +159,7 @@ App.EndWeek.clubReport = function() {
 	}
 
 	if (slaves.length > 0) {
-		for (const slave of slaves) {
+		for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 			if (V.legendaryEntertainerID === 0 && slave.prestige === 0 && slave.skill.entertainment >= 100 && slave.devotion > 50) {
 				V.legendaryEntertainerID = slave.ID;
 			}
diff --git a/src/endWeek/reports/dairyReport.js b/src/endWeek/reports/dairyReport.js
index 6c67054e3d8..48558d4011c 100644
--- a/src/endWeek/reports/dairyReport.js
+++ b/src/endWeek/reports/dairyReport.js
@@ -337,7 +337,7 @@ App.EndWeek.dairyReport = function() {
 	}
 
 	if (V.MilkmaidID !== 0) {
-		const slave = S.Milkmaid;
+		const slave = App.SlaveAssignment.reportSlave(S.Milkmaid);
 		tired(slave);
 		/* apply following SA passages to facility leader */
 		if (V.showEWD !== 0) {
@@ -358,7 +358,7 @@ App.EndWeek.dairyReport = function() {
 	}
 
 	const oldCash = V.cash;
-	for (const slave of slaves) {
+	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 		/* Special attention section */
 		if (slave.devotion > 50 && slave.prestige === 0) {
 			if (
diff --git a/src/endWeek/reports/farmyardReport.js b/src/endWeek/reports/farmyardReport.js
index 5f9d59c893a..b1374a94995 100644
--- a/src/endWeek/reports/farmyardReport.js
+++ b/src/endWeek/reports/farmyardReport.js
@@ -3,7 +3,7 @@ App.Facilities.Farmyard.farmyardReport = function farmyardReport() {
 
 	const slaves = App.Utils.sortedEmployees(App.Entity.facilities.farmyard);
 	const devBonus = (V.farmyardDecoration !== "standard") ? 1 : 0;
-	const Farmer = S.Farmer;
+	const Farmer = S.Farmer ? App.SlaveAssignment.reportSlave(S.Farmer) : undefined;
 
 	let profits = 0;
 	let foodWeek = 0;
@@ -345,7 +345,7 @@ App.Facilities.Farmyard.farmyardReport = function farmyardReport() {
 
 		$(intro).append(farmhandCount(slaves.length));
 
-		for (const slave of slaves) {
+		for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 			slave.devotion += devBonus;
 
 			if (V.showEWD) {
diff --git a/src/endWeek/reports/masterSuiteReport.js b/src/endWeek/reports/masterSuiteReport.js
index 12397070278..f1ef6f8130e 100644
--- a/src/endWeek/reports/masterSuiteReport.js
+++ b/src/endWeek/reports/masterSuiteReport.js
@@ -1,5 +1,6 @@
 App.EndWeek.masterSuiteReport = function() {
 	let frag = document.createDocumentFragment();
+	const concubine = S.Concubine ? App.SlaveAssignment.reportSlave(S.Concubine) : undefined;
 	const slaves = App.Utils.sortedEmployees(App.Entity.facilities.masterSuite);
 	const msAvg = App.Utils.masterSuiteAverages();
 
@@ -159,7 +160,7 @@ App.EndWeek.masterSuiteReport = function() {
 	}
 
 	/** Generate text shared by concubine and non-concubine MS slaves
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {DocumentFragment}
 	 */
 	function commonText(slave) {
@@ -424,15 +425,15 @@ App.EndWeek.masterSuiteReport = function() {
 		$(intro).append(r.join(' '));
 	}
 
-	if (S.Concubine) {
-		tired(S.Concubine);
+	if (concubine) {
+		tired(concubine);
 		const slaveEntry = App.UI.DOM.appendNewElement("div", frag, '', "slave-report");
-		App.SlaveAssignment.appendSlaveArt(slaveEntry, S.Concubine);
-		slaveEntry.append(App.UI.favoriteToggle(S.Concubine), " ");
-		App.Events.addNode(slaveEntry, [concubineText(), commonText(S.Concubine)]);
+		App.SlaveAssignment.appendSlaveArt(slaveEntry, concubine);
+		slaveEntry.append(App.UI.favoriteToggle(concubine), " ");
+		App.Events.addNode(slaveEntry, [concubineText(), commonText(concubine)]);
 	}
 
-	for (const slave of slaves) {
+	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 		const slaveEntry = App.UI.DOM.appendNewElement("div", frag, '', "slave-report");
 		App.SlaveAssignment.appendSlaveArt(slaveEntry, slave);
 		slaveEntry.append(App.UI.favoriteToggle(slave), " ");
diff --git a/src/endWeek/reports/nurseryReport.js b/src/endWeek/reports/nurseryReport.js
index 4a4663bf304..2d3e3f3ffc2 100644
--- a/src/endWeek/reports/nurseryReport.js
+++ b/src/endWeek/reports/nurseryReport.js
@@ -135,7 +135,7 @@ App.Facilities.Nursery.nurseryReport = function nurseryReport() {
 	}
 
 	if (S.Matron) {
-		const slave = S.Matron;
+		const slave = App.SlaveAssignment.reportSlave(S.Matron);
 
 		if (V.showEWD !== 0) {
 			const matronEntry = App.UI.DOM.appendNewElement("div", frag, '', "slave-report");
@@ -149,7 +149,7 @@ App.Facilities.Nursery.nurseryReport = function nurseryReport() {
 	}
 
 	// FIXME: check these numbers over to make sure they make sense
-	for (const slave of slaves) {
+	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 		slave.devotion += devBonus;
 
 		if (slave.devotion <= 20 && slave.trust >= -20) {
diff --git a/src/endWeek/reports/penthouseReport.js b/src/endWeek/reports/penthouseReport.js
index 450dc08f442..248a54760b4 100644
--- a/src/endWeek/reports/penthouseReport.js
+++ b/src/endWeek/reports/penthouseReport.js
@@ -1,14 +1,15 @@
 App.EndWeek.penthouseReport = function() {
 	const el = document.createElement("p");
 
+	const penthouseSlaves = V.slaves.filter(s => assignmentVisible(s));
 	const HGSuiteSlaves = App.Utils.jobForAssignment(Job.HEADGIRLSUITE).employees();
-	const hgSlave = HGSuiteSlaves.length > 0 ? HGSuiteSlaves[0] : null;
+	const hgSlave = HGSuiteSlaves.length > 0 ? App.SlaveAssignment.reportSlave(HGSuiteSlaves[0]) : null;
 	const HGTrainSlavesIDs = slavesToTrain();
 
 	// penthouse images are larger and on the right (for some reason), so we need to initialize a second batch renderer instead of using the global SA Report one
 	let penthouseArtRenderer = null;
 	if (V.seeImages && V.seeReportImages) {
-		const penthouseArtSlaveIDs = V.slaves.filter(s => assignmentVisible(s)).map(s => s.ID);
+		const penthouseArtSlaveIDs = penthouseSlaves.map(s => s.ID);
 		if (hgSlave) {
 			penthouseArtSlaveIDs.push(hgSlave.ID);
 		}
@@ -16,35 +17,33 @@ App.EndWeek.penthouseReport = function() {
 		el.append(penthouseArtRenderer.writePreamble());
 	}
 
-	for (const slave of V.slaves) {
-		if (assignmentVisible(slave)) {
-			const slaveEntry = App.UI.DOM.appendNewElement("div", el, '', "slave-report");
-			if (penthouseArtRenderer) {
-				App.UI.DOM.appendNewElement("div", slaveEntry, penthouseArtRenderer.render(slave), ["imageRef", "medImg"]);
-			}
-			slaveEntry.append(App.UI.favoriteToggle(slave), " ");
-			slaveEntry.append(fullReport(slave));
-
-			if (slave.ID === V.HeadGirlID && hgSlave) {
-				/* Output the HG's slave immediately after the hg */
-				const {He2, he2} = getPronouns(hgSlave).appendSuffix("2");
-				const r = [];
-				if (hgSlave.assignment !== Job.HEADGIRLSUITE) {
-					r.push(`<span class="red">${hgSlave.slaveName} had been assigned to live with your Head Girl, but this week ${he2} was assigned to ${hgSlave.assignment}. ${He2} has been released to your penthouse for reassignment.</span>`);
-					removeJob(hgSlave, Job.HEADGIRLSUITE);
-				} else {
-					r.push(App.UI.DOM.makeElement("span", SlaveFullName(hgSlave), "slave-name"));
-					if (hgSlave.choosesOwnAssignment === 2) {
-						r.push(App.SlaveAssignment.choosesOwnJob(hgSlave));
-						r.push(He2);
-					}
-					if (penthouseArtRenderer) {
-						r.push(App.UI.DOM.makeElement("div", penthouseArtRenderer.render(hgSlave), ["imageRef", "medImg"]));
-					}
-					r.push(App.SlaveAssignment.liveWithHG(hgSlave));
+	for (const slave of App.SlaveAssignment.reportSlaves(penthouseSlaves)) {
+		const slaveEntry = App.UI.DOM.appendNewElement("div", el, '', "slave-report");
+		if (penthouseArtRenderer) {
+			App.UI.DOM.appendNewElement("div", slaveEntry, penthouseArtRenderer.render(slave), ["imageRef", "medImg"]);
+		}
+		slaveEntry.append(App.UI.favoriteToggle(slave), " ");
+		slaveEntry.append(fullReport(slave));
+
+		if (slave.ID === V.HeadGirlID && hgSlave) {
+			/* Output the HG's slave immediately after the hg */
+			const {He2, he2} = getPronouns(hgSlave).appendSuffix("2");
+			const r = [];
+			if (hgSlave.assignment !== Job.HEADGIRLSUITE) {
+				r.push(`<span class="red">${hgSlave.slaveName} had been assigned to live with your Head Girl, but this week ${he2} was assigned to ${hgSlave.assignment}. ${He2} has been released to your penthouse for reassignment.</span>`);
+				removeJob(hgSlave, Job.HEADGIRLSUITE);
+			} else {
+				r.push(App.UI.DOM.makeElement("span", SlaveFullName(hgSlave), "slave-name"));
+				if (hgSlave.choosesOwnAssignment === 2) {
+					r.push(App.SlaveAssignment.choosesOwnJob(hgSlave));
+					r.push(He2);
 				}
-				App.Events.addNode(el, r, "div", "slave-report");
+				if (penthouseArtRenderer) {
+					r.push(App.UI.DOM.makeElement("div", penthouseArtRenderer.render(hgSlave), ["imageRef", "medImg"]));
+				}
+				r.push(App.SlaveAssignment.liveWithHG(hgSlave));
 			}
+			App.Events.addNode(el, r, "div", "slave-report");
 		}
 	}
 
@@ -57,7 +56,7 @@ App.EndWeek.penthouseReport = function() {
 	return el;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 */
 	function fullReport(slave) {
 		const el = new DocumentFragment();
@@ -636,8 +635,8 @@ App.EndWeek.penthouseReport = function() {
 		if (S.HeadGirl) {
 			/** @type {FC.HeadGirlTrainee[][]} */
 			const HGPossibleSlaves = [[], [], [], [], [], []];
-			for (const slave of V.slaves) {
-				if (!assignmentVisible(slave) || slave.fuckdoll === 1 || slave.ID === V.BodyguardID || slave.ID === V.HeadGirlID || slave.fetish === "mindbroken") {
+			for (const slave of penthouseSlaves) {
+				if (slave.fuckdoll === 1 || slave.ID === V.BodyguardID || slave.ID === V.HeadGirlID || slave.fetish === "mindbroken") {
 					continue;
 				} else if (Array.isArray(V.personalAttention) && V.personalAttention.some(p => p.ID === slave.ID)) {
 					continue;
diff --git a/src/endWeek/reports/schoolroomReport.js b/src/endWeek/reports/schoolroomReport.js
index 0ab52049ad6..d5b51cc0edf 100644
--- a/src/endWeek/reports/schoolroomReport.js
+++ b/src/endWeek/reports/schoolroomReport.js
@@ -146,7 +146,7 @@ App.EndWeek.schoolroomReport = function() {
 	}
 
 	if (S.Schoolteacher) {
-		const slave = S.Schoolteacher;
+		const slave = App.SlaveAssignment.reportSlave(S.Schoolteacher);
 		tired(slave);
 		/* apply following SA passages to facility leader */
 		if (V.showEWD !== 0) {
@@ -161,7 +161,7 @@ App.EndWeek.schoolroomReport = function() {
 	}
 
 	let restedSlaves = 0;
-	for (const slave of slaves) {
+	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 		slave.devotion += devBonus;
 		if (slave.health.condition < -80) {
 			improveCondition(slave, 20);
diff --git a/src/endWeek/reports/servantsQuartersReport.js b/src/endWeek/reports/servantsQuartersReport.js
index a429906ac1e..419d3fac49c 100644
--- a/src/endWeek/reports/servantsQuartersReport.js
+++ b/src/endWeek/reports/servantsQuartersReport.js
@@ -205,7 +205,7 @@ App.EndWeek.servantsQuartersReport = function() {
 	}
 
 	if (S.Stewardess) {
-		const slave = S.Stewardess;
+		const slave = App.SlaveAssignment.reportSlave(S.Stewardess);
 		tired(slave);
 		/* apply following SA passages to facility leader */
 		if (V.showEWD !== 0) {
@@ -222,7 +222,7 @@ App.EndWeek.servantsQuartersReport = function() {
 	let SQMilk = 0;
 	let SQMilkSale = 0;
 
-	for (const slave of slaves) {
+	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 		slave.devotion += devBonus;
 		if (slave.devotion <= 20 && slave.trust >= -20) {
 			slave.devotion -= 5;
diff --git a/src/endWeek/reports/spaReport.js b/src/endWeek/reports/spaReport.js
index d127e367b02..02504be3e30 100644
--- a/src/endWeek/reports/spaReport.js
+++ b/src/endWeek/reports/spaReport.js
@@ -283,7 +283,7 @@ App.EndWeek.spaReport = function() {
 	}
 
 	if (S.Attendant) {
-		const slave = S.Attendant;
+		const slave = App.SlaveAssignment.reportSlave(S.Attendant);
 		tired(slave);
 		/* apply following SA passages to facility leader */
 		if (V.showEWD !== 0) {
@@ -303,7 +303,7 @@ App.EndWeek.spaReport = function() {
 		}
 	}
 
-	for (const slave of slaves) {
+	for (const slave of App.SlaveAssignment.reportSlaves(slaves)) {
 		const {He, he, his} = getPronouns(slave);
 		slave.devotion += devBonus;
 		improveCondition(slave, 5 + healthBonus);
diff --git a/src/endWeek/saBeYourHeadGirl.js b/src/endWeek/saBeYourHeadGirl.js
index eef75b7e0cb..9010419b068 100644
--- a/src/endWeek/saBeYourHeadGirl.js
+++ b/src/endWeek/saBeYourHeadGirl.js
@@ -12,7 +12,7 @@ App.SlaveAssignment.beYourHeadGirl = (function() {
 	return saBeYourHeadGirl;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {string}
 	 */
 	function saBeYourHeadGirl(slave) {
@@ -44,7 +44,7 @@ App.SlaveAssignment.beYourHeadGirl = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function updateHGState(slave) {
diff --git a/src/endWeek/saDiet.js b/src/endWeek/saDiet.js
index 4446e28c06e..a50a8e71578 100644
--- a/src/endWeek/saDiet.js
+++ b/src/endWeek/saDiet.js
@@ -19,7 +19,7 @@ App.SlaveAssignment.diet = (function() {
 	return saDiet;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {string}
 	 */
 	function saDiet(slave) {
@@ -32,8 +32,6 @@ App.SlaveAssignment.diet = (function() {
 		boobSize = slave.boobs - slave.boobsImplant - slave.boobsMilk;
 		buttSize = slave.butt - slave.buttImplant;
 
-		App.EndWeek.saVars.inappropriateLactation = 0; // TODO: once this is resetting properly, remove it from here
-
 		({
 			// eslint-disable-next-line no-unused-vars
 			he, him, his, hers, himself, girl, He, His, loli
@@ -71,7 +69,7 @@ App.SlaveAssignment.diet = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function foodEffects(slave) {
@@ -535,7 +533,7 @@ App.SlaveAssignment.diet = (function() {
 						}
 						weightGainShared(slave);
 						if (slave.geneticQuirks.galactorrhea === 2 && random(1, 100) < slave.hormoneBalance && slave.lactation === 0) {
-							App.EndWeek.saVars.inappropriateLactation = 1;
+							slave.inappropriateLactation = 1;
 						}
 					} else if (slave.weightDirection === 1) {
 						r.push(`${He} gains a little weight this week despite ${his} dietary troubles.`);
@@ -1125,7 +1123,7 @@ App.SlaveAssignment.diet = (function() {
 					}
 				}
 				if (slave.geneticQuirks.galactorrhea === 2 && random(1, 100) < slave.hormoneBalance && slave.lactation === 0) {
-					App.EndWeek.saVars.inappropriateLactation = 1;
+					slave.inappropriateLactation = 1;
 				}
 				break;
 			case "XY": // Male Hormones
@@ -1277,7 +1275,7 @@ App.SlaveAssignment.diet = (function() {
 					}
 				}
 				if (slave.geneticQuirks.galactorrhea === 2 && random(1, 100) < slave.hormoneBalance && slave.lactation === 0) {
-					App.EndWeek.saVars.inappropriateLactation = 1;
+					slave.inappropriateLactation = 1;
 				}
 				break;
 			case "cleansing": // chem reduce and health plus
diff --git a/src/endWeek/saLiveWithHG.js b/src/endWeek/saLiveWithHG.js
index 733f91b6737..34c9a78e2bf 100644
--- a/src/endWeek/saLiveWithHG.js
+++ b/src/endWeek/saLiveWithHG.js
@@ -22,7 +22,7 @@ App.SlaveAssignment.liveWithHG = (function() {
 	return saliveWithHG;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {DocumentFragment}
 	 */
 	function saliveWithHG(slave) {
@@ -1095,7 +1095,7 @@ App.SlaveAssignment.liveWithHG = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @param {App.Entity.SlaveState} HG
 	 */
 	function HGManagesTiredness(slave, HG) {
@@ -1615,7 +1615,7 @@ App.SlaveAssignment.liveWithHG = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function slaveReport(slave) {
diff --git a/src/endWeek/saLongTermEffects.js b/src/endWeek/saLongTermEffects.js
index 7e77d0ec17a..e47ce1a0fc9 100644
--- a/src/endWeek/saLongTermEffects.js
+++ b/src/endWeek/saLongTermEffects.js
@@ -14,7 +14,7 @@ App.SlaveAssignment.longTermEffects = (function() {
 	return saLongTermEffects;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {DocumentFragment}
 	 */
 	function saLongTermEffects(slave) {
@@ -560,7 +560,7 @@ App.SlaveAssignment.longTermEffects = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function aphrodisiacEffects(slave) {
@@ -610,7 +610,7 @@ App.SlaveAssignment.longTermEffects = (function() {
 			Effects.push("FemaleAttracted");
 		}
 		if (slave.geneticQuirks.galactorrhea === 2 && random(1, 100) < slave.hormoneBalance && slave.lactation === 0) {
-			App.EndWeek.saVars.inappropriateLactation = 1;
+			slave.inappropriateLactation = 1;
 		}
 		if (Effects.length > 0) {
 			switch (Effects.random()) {
@@ -692,7 +692,7 @@ App.SlaveAssignment.longTermEffects = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function hormoneBalance(slave) {
@@ -890,12 +890,12 @@ App.SlaveAssignment.longTermEffects = (function() {
 			}
 		}
 		if (slave.geneticQuirks.galactorrhea === 2 && random(1, 100) < slave.hormoneBalance && slave.lactation === 0) {
-			App.EndWeek.saVars.inappropriateLactation = 1;
+			slave.inappropriateLactation = 1;
 		}
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function puberty(slave) {
@@ -1134,7 +1134,7 @@ App.SlaveAssignment.longTermEffects = (function() {
 					if (slave.geneticQuirks.galactorrhea === 3) {
 						slave.geneticQuirks.galactorrhea = 2;
 						if (random(1, 100) < slave.hormoneBalance && slave.lactation === 0) {
-							App.EndWeek.saVars.inappropriateLactation = 1;
+							slave.inappropriateLactation = 1;
 						}
 					}
 				}
@@ -1147,7 +1147,7 @@ App.SlaveAssignment.longTermEffects = (function() {
 					if (slave.geneticQuirks.galactorrhea === 3) {
 						slave.geneticQuirks.galactorrhea = 2;
 						if (random(1, 100) < slave.hormoneBalance && slave.lactation === 0) {
-							App.EndWeek.saVars.inappropriateLactation = 1;
+							slave.inappropriateLactation = 1;
 						}
 					}
 				}
diff --git a/src/endWeek/saLongTermMentalEffects.js b/src/endWeek/saLongTermMentalEffects.js
index cc3ceb57302..5a8383c56b1 100644
--- a/src/endWeek/saLongTermMentalEffects.js
+++ b/src/endWeek/saLongTermMentalEffects.js
@@ -11,14 +11,13 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 	return saLongTermMentalEffects;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {string}
 	 */
 	function saLongTermMentalEffects(slave) {
 		r = [];
 
 		boobSize = slave.boobs - slave.boobsImplant - slave.boobsMilk;
-		App.EndWeek.saVars.paraphiliaSatisfied = 0; // TODO: once this is resetting properly, remove it from here
 
 		({
 			// eslint-disable-next-line no-unused-vars
@@ -1263,7 +1262,7 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function paraphiliaImpacts(slave) {
@@ -1287,28 +1286,28 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				}
 				if (["be confined in the arcade", "serve in the club", "serve the public", "whore", "work a glory hole", "work in the brothel"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by how many dicks ${he} gets to suck at work.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (V.PC.dick !== 0 && slave.toyHole === "mouth" && ["be your Concubine", "please you", "serve in the master suite"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by constant oral sex with you.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.inflation !== 0 && slave.inflationType === "cum") {
 					r.push(`${His} paraphilia is satisfied by swelling ${his} body with cum.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.dietCum === 1) {
 					r.push(`${His} paraphilia is satisfied by what ${he} gets to eat.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.dietCum === 2) {
 					r.push(`Other slaves in your penthouse are disturbed by ${his} insatiable appetite for human ejaculate, which ${his} heavy cum-diet encourages.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (V.feeder !== 0) {
 					r.push(`${His} paraphilia is satisfied by the way ${he} gets to eat.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.assignment === "work in the dairy" && V.dairyFeedersSetting > 0) {
 					// something involving cum production
 				} else {
 					r.push(`${He} doesn't seem to feel ${he}'s getting enough cum, leaving the cum addict <span class="devotion dec">depressed and anxious.</span>`);
 					slave.devotion -= 2;
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 				}
 				break;
 			case "anal addict":
@@ -1330,21 +1329,21 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				}
 				if (["be confined in the arcade", "serve in the club", "serve the public", "whore", "work a glory hole", "work in the brothel"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by how many dicks get shoved up ${his} butt at work.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.toyHole === "ass" && ["be your Concubine", "please you", "serve in the master suite"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by constant anal sex with you.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (V.suppository !== 0) {
 					r.push(`${His} paraphilia is satisfied by the way ${he} gets to take medication.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (plugWidth(slave) > 2) {
 					r.push(`${His} paraphilia is satisfied by the enormous plug ${he} wears in ${his} ass.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.assignment === "work in the dairy" && V.dairyStimulatorsSetting > 0) {
 					// major ass drilling
 				} else {
 					r.push(`${He} doesn't seem to feel ${he}'s getting buttfucked often enough, leaving the anal addict <span class="devotion dec">depressed and anxious.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 					slave.devotion -= 2;
 				}
 				if (slave.prostate === 0) {
@@ -1376,22 +1375,22 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				}
 				if (slave.porn.feed === 1 && slave.porn.viewerCount >= 10000) {
 					r.push(`${His} paraphilia is satisfied by the viewcounts on ${his} porn and the many viewers no doubt enjoying themselves to ${his} day to day life.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (["whore", "serve the public", "work in the brothel", "serve in the club", "be the DJ"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by how often ${he} gets publicly fucked at work.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.assignment === "recruit girls" && V.recruiterTarget === "other arcologies" && V.arcologies[0].influenceTarget !== -1) {
 					r.push(`${His} paraphilia is satisfied by the sheer amount of attention ${he} gets as a sexual Ambassador.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.assignment === "be the Schoolteacher" && V.schoolroom >= 20) {
 					r.push(`${His} paraphilia is satisfied by ${his} work as a sexual instructor; enough eyes are fixated on ${his} lessons.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.clothes === "no clothing") {
 					r.push(`${His} paraphilia is satisfied by ${his} total nudity.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else {
 					r.push(`${He} doesn't seem to feel ${he}'s getting fucked in public enough, leaving the attention whore <span class="devotion dec">depressed and anxious.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 					slave.devotion -= 2;
 				}
 				break;
@@ -1421,7 +1420,7 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				}
 				if (["get milked", "work in the dairy"].includes(slave.assignment) && slave.lactation > 0) {
 					r.push(`${His} paraphilia is satisfied by ${his} work as a cow; ${he} can feel ${his} udders swelling with milk.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.geneticQuirks.gigantomastia === 2 && slave.geneticQuirks.macromastia === 2 && V.geneticMappingUpgrade >= 1) {
 					r.push(`${His} paraphilia is satisfied by the knowledge that ${his} genetic abnormality will keep ${his} breasts growing for the rest of ${his} life.`);
 				} else if (V.geneticMappingUpgrade >= 1 && (slave.geneticQuirks.gigantomastia === 2 || slave.geneticQuirks.macromastia === 2)) {
@@ -1433,13 +1432,13 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				} else if (slave.drugs === "intensive breast injections" || slave.drugs === "hyper breast injections") {
 					r.push(`${His} paraphilia makes ${him} feel <span class="trust inc">fulfilled to be a sex slave</span> if it means breast expansion like this.`);
 					slave.trust += 2;
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.drugs === "breast injections") {
 					r.push(`${His} paraphilia makes breast injections very satisfying for ${him}.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else {
 					r.push(`${He} feels ${his} breasts are shrinking horribly, leaving the growth addict <span class="devotion dec">depressed and anxious.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 					slave.devotion -= 2;
 				}
 				break;
@@ -1462,22 +1461,22 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				}
 				if (slave.assignment === "be your Head Girl") {
 					r.push(`${His} paraphilia is satisfied by ${his} work as your Head Girl.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if ((slave.assignment === "be the Wardeness")) {
 					r.push(`${His} paraphilia is satisfied by ${his} work as your Wardeness.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if ((slave.assignment === "be the Stewardess")) {
 					r.push(`${His} paraphilia is satisfied by ${his} work as the Stewardess.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if ((slave.assignment === "be the Schoolteacher")) {
 					r.push(`${His} paraphilia is satisfied by ${his} work as the Schoolteacher.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (canMove(slave) && (slave.rules.release.slaves === 1 || App.Utils.hasFamilySex(slave)) && V.universalRulesConsent === 0) {
 					r.push(`${His} paraphilia makes pinning down and raping other slaves very satisfying.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else {
 					r.push(`${He} gets few chances to indulge ${his} need to hold others down as ${he} fucks them, leaving ${him} <span class="devotion dec">depressed and anxious.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 					slave.devotion -= 2;
 				}
 				break;
@@ -1500,16 +1499,16 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				}
 				if (slave.assignment === "be your Head Girl") {
 					r.push(`${His} paraphilia is satisfied by ${his} work as your Head Girl.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if ((slave.assignment === "be the Wardeness")) {
 					r.push(`${His} paraphilia is satisfied by ${his} work as your Wardeness.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (canMove(slave) && (slave.rules.release.slaves === 1 || App.Utils.hasFamilySex(slave)) && V.universalRulesConsent === 0) {
 					r.push(`${His} paraphilia makes pinning down and brutally raping other slaves very satisfying.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else {
 					r.push(`${He} gets few chances to indulge ${his} need to subject others to sexual anguish, leaving ${him} <span class="devotion dec">depressed and anxious.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 					slave.devotion -= 2;
 				}
 				break;
@@ -1533,19 +1532,19 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				const dom = (slave.assignment === "be a subordinate slave" && slave.subTarget > 0) ? getSlave(slave.subTarget) : null;
 				if (slave.assignment === "work in the dairy" && V.dairyRestraintsSetting >= 2) {
 					r.push(`${His} paraphilia is satisfied by ${his} horrible life as a producer of useful fluids and a receptacle for machine rape.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (["be confined in the arcade", "work a glory hole"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by ${his} horrible life as a helpless hole for an infinite bag of dicks.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (dom && ["abusive", "malicious"].includes(dom.sexualFlaw)) {
 					r.push(`${His} paraphilia is satisfied by the constant mistreatment ${he} receives from ${his} dom, ${dom.slaveName}.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.trust < -50) {
 					r.push(`${His} paraphilia is satisfied by ${his} constant terror.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else {
 					r.push(`${He} doesn't seem to feel ${he}'s treated poorly enough, leaving the self hating slut <span class="devotion dec">depressed and anxious.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 					slave.devotion -= 2;
 				}
 				break;
@@ -1569,16 +1568,16 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				}
 				if (["be confined in the arcade", "serve in the club", "serve the public", "whore", "work a glory hole", "work in the brothel", "work as a servant", "be the Attendant", "be the Milkmaid"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by how ${he}'s expected to serve others' sexual needs at work.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (["be your Concubine", "please you", "serve in the master suite"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by how ${he}'s expected to serve your sexual needs at work.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.assignment === "be a subordinate slave") {
 					r.push(`${His} paraphilia is satisfied by how ${he}'s expected to serve other slaves' sexual needs.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else {
 					r.push(`${He} doesn't seem to feel ${he}'s serving others' sexual needs enough, leaving ${him} <span class="devotion dec">depressed and anxious.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 					slave.devotion -= 2;
 				}
 				break;
@@ -1614,38 +1613,38 @@ App.SlaveAssignment.longTermMentalEffects = (function() {
 				}
 				if (slave.broodmother > 0 && slave.pregKnown === 1) {
 					r.push(`${He} knows ${he} will be pregnant until ${his} body gives out, and <span class="devotion inc">${he} couldn't be happier.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 					slave.devotion += 5;
 				} else if (slave.pregControl === "labor suppressors" && slave.preg >= slave.pregData.normalBirth) {
 					r.push(`Under the effects of labor suppression drugs, ${he} knows ${he} will be pregnant until you decided to allow ${his} birth. <span class="devotion inc">${He} couldn't be happier.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 					slave.devotion += 5;
 				} else if (slave.pregType >= 10 && slave.pregKnown === 1) {
 					r.push(`${His} growing hyperpregnancy feeds ${his} paraphilia and <span class="devotion inc">fulfills ${his} deepest fantasies.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 					slave.devotion += 3;
 				} else if (slave.pregKnown === 1) {
 					r.push(`${His} paraphilia is satisfied by ${his} pregnancy.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (canGetPregnant(slave) && V.PC.dick !== 0 && slave.toyHole === "pussy" && slave.mpreg !== 1 && ["be your Concubine", "please you", "serve in the master suite"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by constant unprotected vaginal sex with you.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (canGetPregnant(slave) && V.PC.dick !== 0 && slave.toyHole === "ass" && slave.mpreg === 1 && ["be your Concubine", "please you", "serve in the master suite"].includes(slave.assignment)) {
 					r.push(`${His} paraphilia is satisfied by constant unprotected anal sex with you.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (slave.bellyImplant >= 60000) {
 					r.push(`${His} paraphilia is satisfied by ${his} overfilled belly implant.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else if (setup.fakeBellies.includes(slave.bellyAccessory)) {
 					r.push(`${He} <span class="devotion dec">loathes</span> being forced to carry a fake pregnancy.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 					slave.devotion -= 3;
 				} else if (slave.pregWeek < 0) {
 					r.push(`${His} paraphilia is temporarily sated by ${his} recent pregnancy, though ${he} anxiously counts the days until ${he} can get pregnant again.`);
-					App.EndWeek.saVars.paraphiliaSatisfied = 1;
+					slave.paraphiliaSatisfied = 1;
 				} else {
 					r.push(`${He} isn't pregnant, leaving the breeder slut <span class="devotion dec">depressed and anxious.</span>`);
-					App.EndWeek.saVars.paraphiliaSatisfied = -1;
+					slave.paraphiliaSatisfied = -1;
 					slave.devotion -= 2;
 				}
 				break;
diff --git a/src/endWeek/saLongTermPhysicalEffects.js b/src/endWeek/saLongTermPhysicalEffects.js
index eff87fd7819..f4a8327855d 100644
--- a/src/endWeek/saLongTermPhysicalEffects.js
+++ b/src/endWeek/saLongTermPhysicalEffects.js
@@ -16,7 +16,7 @@ App.SlaveAssignment.longTermPhysicalEffects = (function() {
 	return saLongTermPhysicalEffects;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {string}
 	 */
 	function saLongTermPhysicalEffects(slave) {
@@ -957,7 +957,7 @@ App.SlaveAssignment.longTermPhysicalEffects = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function geneticQuirkEffects(slave) {
@@ -1001,8 +1001,7 @@ App.SlaveAssignment.longTermPhysicalEffects = (function() {
 				slave.boobs += 10;
 			}
 		}
-		if (slave.geneticQuirks.galactorrhea === 2 && App.EndWeek.saVars.inappropriateLactation === 1) {
-			App.EndWeek.saVars.inappropriateLactation = 0;
+		if (slave.geneticQuirks.galactorrhea === 2 && slave.inappropriateLactation === 1) {
 			if (V.geneticMappingUpgrade >= 1) {
 				r.push(`${His} galactorrhea has caused ${him} to <span class="change positive">begin lactating.</span>`);
 			} else {
@@ -1190,7 +1189,7 @@ App.SlaveAssignment.longTermPhysicalEffects = (function() {
 		} else if (slave.nipples === "flat" && (slave.boobsImplant / slave.boobs < 0.75)) {
 			r.push(`With ${his} breasts no longer being overstretched by implants, ${his} flat nipples regain a more normal shape. They now <span class="change positive">protrude hugely.</span>`);
 			slave.nipples = "huge";
-		} else if (slave.boobShape === "spherical" && slave.nipples !== "flat" && slave.lactation === 0 && slave.nipplesPiercings === 0) { // Lactation and piercings discourage flattening and convert flat nipples to huge ones.
+		} else if (slave.boobShape === "spherical" && slave.nipples !== "flat" && slave.lactation === 0 && slave.nipplesPiercing === 0) { // Lactation and piercings discourage flattening and convert flat nipples to huge ones.
 			r.push(`With the skin of ${his} breasts stretched so thin by ${his} implants, it's only natural that ${his} nipples are soon <span class="change negative">pulled flat</span> as well.`);
 			slave.nipples = "flat";
 		}
diff --git a/src/endWeek/saPregnancy.js b/src/endWeek/saPregnancy.js
index 9373cec6d5a..5162a6e4678 100644
--- a/src/endWeek/saPregnancy.js
+++ b/src/endWeek/saPregnancy.js
@@ -16,7 +16,7 @@ App.SlaveAssignment.pregnancy = (function() {
 	return saPregnancy;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {string}
 	 */
 	function saPregnancy(slave) {
@@ -46,7 +46,7 @@ App.SlaveAssignment.pregnancy = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function pregnancyEffects(slave) {
@@ -263,7 +263,7 @@ App.SlaveAssignment.pregnancy = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function pregnancyAdjustments(slave) {
@@ -274,7 +274,7 @@ App.SlaveAssignment.pregnancy = (function() {
 			slave.geneticQuirks.macromastia = 2;
 		}
 		if (slave.geneticQuirks.galactorrhea === 2 && random(1, 100) < slave.hormoneBalance && slave.lactation === 0) {
-			App.EndWeek.saVars.inappropriateLactation = 1;
+			slave.inappropriateLactation = 1;
 		}
 		if (slave.preg > slave.pregData.normalBirth / 2) {
 			if (slave.belly >= 300000) {
diff --git a/src/endWeek/saRelationships.js b/src/endWeek/saRelationships.js
index 13ebd05336e..f95e9d16086 100644
--- a/src/endWeek/saRelationships.js
+++ b/src/endWeek/saRelationships.js
@@ -12,7 +12,7 @@ App.SlaveAssignment.relationships = (function() {
 	return saRelationships;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {string}
 	 */
 	function saRelationships(slave) {
@@ -46,7 +46,7 @@ App.SlaveAssignment.relationships = (function() {
 	}
 
 	/** Can this slave possibly be a friend?
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @param {App.Entity.SlaveState} potentialFriend
 	 * @returns {boolean}
 	 */
@@ -76,7 +76,7 @@ App.SlaveAssignment.relationships = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function generateRelationship(slave) {
@@ -341,7 +341,7 @@ App.SlaveAssignment.relationships = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function existingRelationship(slave) {
@@ -870,7 +870,7 @@ App.SlaveAssignment.relationships = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @param {App.Entity.SlaveState} relative
 	 */
 	function incestReactions(slave, relative) {
@@ -956,7 +956,7 @@ App.SlaveAssignment.relationships = (function() {
 				if (slave.bellyPreg >= 1500 && slave.pregSource === relative.ID) {
 					r.push(`<span class="reputation inc">The effect is greatly enhanced</span> by ${slave.slaveName}'s pureblooded pregnancy.`);
 					repX((V.FSSingleSlaveRep * (V.arcologies[0].FSEgyptianRevivalist / V.FSLockinLevel)), repType, slave);
-					V.arcologies[0].FSEgyptianRevivalist += (0.05 * V.FSSingleSlaveRep * App.EndWeek.saVars.pornFameBonus);
+					V.arcologies[0].FSEgyptianRevivalist += (0.05 * V.FSSingleSlaveRep * slave.pornFameBonus);
 				}
 			} else if (V.arcologies[0].FSEgyptianRevivalistIncestPolicy === 1) {
 				r.push(`Society <span class="reputation inc">enjoys</span> ${whose} incestuous relationship since incest is currently trendy.`);
@@ -970,7 +970,7 @@ App.SlaveAssignment.relationships = (function() {
 	}
 
 	/** LONG TERM RELATIONSHIP EFFECTS
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 *
 	 */
 	function consummateRelationship(slave) {
diff --git a/src/endWeek/saRules.js b/src/endWeek/saRules.js
index 000a5c72763..a18f98a2a3f 100644
--- a/src/endWeek/saRules.js
+++ b/src/endWeek/saRules.js
@@ -1,6 +1,6 @@
 /**
  *
- * @param {App.Entity.SlaveState} slave
+ * @param {FC.ReportSlave} slave
  * @returns {DocumentFragment}
  */
 App.SlaveAssignment.rules = function(slave) {
@@ -80,9 +80,8 @@ App.SlaveAssignment.rules = function(slave) {
 					slave.devotion += 1;
 					slave.trust += 1;
 
-					if (V.slaveUsedRest) {
+					if (slave.slaveUsedRest) {
 						r.push(`${He} is permitted to take short breaks throughout the week to help manage ${his} building exhaustion, though it does restrict ${his} non-essential activities.`);
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -220,7 +219,7 @@ App.SlaveAssignment.rules = function(slave) {
 							r.push(`${He} appreciates having a weekly day off and takes it as a sign that ${he} has a <span class="mediumaquamarine">caring ${getWrittenTitle(slave)}.</span>`);
 							slave.trust += 1;
 						}
-					} else if (V.slaveUsedRest) {
+					} else if (slave.slaveUsedRest) {
 						if (slave.rules.rest === "permissive") {
 							if (slave.devotion <= 20) {
 								r.push(`${He}'s permitted to rest whenever ${he} feels even the slightest bit tired; <span class="mediumaquamarine">a privilege not lost on ${him}.</span>`);
@@ -254,7 +253,6 @@ App.SlaveAssignment.rules = function(slave) {
 								slave.devotion -= 2;
 							}
 						}
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -317,9 +315,8 @@ App.SlaveAssignment.rules = function(slave) {
 					slave.devotion += 1;
 					slave.trust += 1;
 
-					if (V.slaveUsedRest) {
+					if (slave.slaveUsedRest) {
 						r.push(`${He} is permitted to take short breaks throughout the week to help manage ${his} building exhaustion, though it does restrict ${his} non-essential activities.`);
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -415,7 +412,7 @@ App.SlaveAssignment.rules = function(slave) {
 							r.push(`${He} appreciates having a weekly day off and takes it as a sign that ${he} has a <span class="mediumaquamarine">caring ${getWrittenTitle(slave)}.</span>`);
 							slave.trust += 1;
 						}
-					} else if (V.slaveUsedRest) {
+					} else if (slave.slaveUsedRest) {
 						if (slave.rules.rest === "permissive") {
 							if (slave.devotion <= 20) {
 								r.push(`${He}'s permitted to rest whenever ${he} feels even the slightest bit tired; <span class="mediumaquamarine">a privilege not lost on ${him}.</span>`);
@@ -449,7 +446,6 @@ App.SlaveAssignment.rules = function(slave) {
 								slave.devotion -= 2;
 							}
 						}
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -513,9 +509,8 @@ App.SlaveAssignment.rules = function(slave) {
 					slave.devotion += 1;
 					slave.trust += 1;
 
-					if (V.slaveUsedRest) {
+					if (slave.slaveUsedRest) {
 						r.push(`${He} is permitted to take short breaks throughout the week to help manage ${his} building exhaustion, though it does restrict ${his} non-essential activities.`);
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -844,9 +839,8 @@ App.SlaveAssignment.rules = function(slave) {
 					slave.devotion += 1;
 					slave.trust += 1;
 
-					if (V.slaveUsedRest) {
+					if (slave.slaveUsedRest) {
 						r.push(`${He} is permitted to take short breaks throughout the week to help manage ${his} building exhaustion, though it does restrict ${his} non-essential activities.`);
-						delete V.slaveUsedRest;
 					}
 
 					if (slave.attrKnown === 0) {
@@ -1433,9 +1427,8 @@ App.SlaveAssignment.rules = function(slave) {
 					slave.devotion += 1;
 					slave.trust += 1;
 
-					if (V.slaveUsedRest) {
+					if (slave.slaveUsedRest) {
 						r.push(`${He} is permitted to take short breaks throughout the week to help manage ${his} building exhaustion, though it does restrict ${his} non-essential activities.`);
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -1594,9 +1587,8 @@ App.SlaveAssignment.rules = function(slave) {
 					slave.devotion += 1;
 					slave.trust += 1;
 
-					if (V.slaveUsedRest) {
+					if (slave.slaveUsedRest) {
 						r.push(`${He} is permitted to take short breaks throughout the week to help manage ${his} building exhaustion, though it does restrict ${his} non-essential activities.`);
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -1772,7 +1764,7 @@ App.SlaveAssignment.rules = function(slave) {
 							r.push(`${He} appreciates having a weekly day off and takes it as a sign that ${he} has a <span class="mediumaquamarine">caring ${getWrittenTitle(slave)}.</span>`);
 							slave.trust += 1;
 						}
-					} else if (V.slaveUsedRest) {
+					} else if (slave.slaveUsedRest) {
 						if (slave.rules.rest === "permissive") {
 							if (slave.devotion <= 20) {
 								r.push(`${He}'s permitted to rest whenever ${he} feels even the slightest bit tired; <span class="mediumaquamarine">a privilege not lost on ${him}.</span>`);
@@ -1806,7 +1798,6 @@ App.SlaveAssignment.rules = function(slave) {
 								slave.devotion -= 2;
 							}
 						}
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -1854,9 +1845,8 @@ App.SlaveAssignment.rules = function(slave) {
 					slave.devotion += 1;
 					slave.trust += 1;
 
-					if (V.slaveUsedRest) {
+					if (slave.slaveUsedRest) {
 						r.push(`${He} is permitted to take short breaks throughout the week to help manage ${his} building exhaustion, though it does restrict ${his} non-essential activities.`);
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -2084,7 +2074,7 @@ App.SlaveAssignment.rules = function(slave) {
 								r.push(`${He} appreciates having a weekly day off and takes it as a sign that ${he} has a <span class="mediumaquamarine">caring ${getWrittenTitle(slave)}.</span>`);
 								slave.trust += 1;
 							}
-						} else if (V.slaveUsedRest) {
+						} else if (slave.slaveUsedRest) {
 							if (slave.rules.rest === "permissive") {
 								if (slave.devotion <= 20) {
 									r.push(`${He}'s permitted to rest whenever ${he} feels even the slightest bit tired; <span class="mediumaquamarine">a privilege not lost on ${him}.</span>`);
@@ -2118,7 +2108,6 @@ App.SlaveAssignment.rules = function(slave) {
 									slave.devotion -= 2;
 								}
 							}
-							delete V.slaveUsedRest;
 						}
 
 						r.push(App.EndWeek.Rules.consentRules(slave));
@@ -2155,9 +2144,8 @@ App.SlaveAssignment.rules = function(slave) {
 					slave.devotion += 1;
 					slave.trust += 1;
 
-					if (V.slaveUsedRest) {
+					if (slave.slaveUsedRest) {
 						r.push(`${He} is permitted to take short breaks throughout the week to help manage ${his} building exhaustion, though it does restrict impact ${his} effectiveness.`);
-						delete V.slaveUsedRest;
 					}
 
 					r.push(App.EndWeek.Rules.consentRules(slave));
@@ -2708,7 +2696,7 @@ App.SlaveAssignment.rules = function(slave) {
 								r.push(`${He} appreciates having a weekly day off and takes it as a sign that ${he} has a <span class="mediumaquamarine">caring ${getWrittenTitle(slave)}.</span>`);
 								slave.trust += 1;
 							}
-						} else if (V.slaveUsedRest) {
+						} else if (slave.slaveUsedRest) {
 							if (slave.rules.rest === "permissive") {
 								if (slave.devotion <= 20) {
 									r.push(`${He}'s permitted to rest whenever ${he} feels even the slightest bit tired; <span class="mediumaquamarine">a privilege not lost on ${him}.</span>`);
@@ -2742,7 +2730,6 @@ App.SlaveAssignment.rules = function(slave) {
 									slave.devotion -= 2;
 								}
 							}
-							delete V.slaveUsedRest;
 						}
 					}
 
diff --git a/src/endWeek/saServeYourOtherSlaves.js b/src/endWeek/saServeYourOtherSlaves.js
index fc24c16e7cb..f76a5c12ac6 100644
--- a/src/endWeek/saServeYourOtherSlaves.js
+++ b/src/endWeek/saServeYourOtherSlaves.js
@@ -38,7 +38,7 @@ App.SlaveAssignment.serveYourOtherSlaves = (function() {
 	return saServeYourOtherSlaves;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {string}
 	 */
 	function saServeYourOtherSlaves(slave) {
@@ -1637,7 +1637,7 @@ App.SlaveAssignment.serveYourOtherSlaves = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * */
 	function physicalEffects(slave) {
 		if (slave.health.illness > 0 || slave.health.tired > 60) {
diff --git a/src/endWeek/saSharedVariables.js b/src/endWeek/saSharedVariables.js
index 8186fe68787..d7c81566664 100644
--- a/src/endWeek/saSharedVariables.js
+++ b/src/endWeek/saSharedVariables.js
@@ -34,22 +34,6 @@ App.EndWeek.SASharedVariables = class {
 		this.slaveArt = null;
 	}
 
-	/**
-	 * Reset slave-specific report variables.  Declare members that need to be reset between slaves here.
-	 * @todo call this from all the facility reports (the slave loops are broken up by facility)
-	 */
-	nextSlave() {
-		/** Is this slave's paraphilia satisfied? (1: satisfied, 0: no paraphilia; -1: unsatisfied) */
-		this.paraphiliaSatisfied = 0;
-		/** A slave with a lot of porn viewers will have a stronger effect on societal norms. This is her multiplier for those effects. */
-		this.pornFameBonus = 1;
-		/** Used to condense all the possible galactorrhea lactation start points to a single line of text in saLongTermPhysicalEffects. */
-		this.inappropriateLactation = 0;
-		/** Used limit a slave to a single fetish change per week. */
-		this.fetishChanged = 0;
-		/** TODO: move V.slaveUsedRest here after saRules is converted, and find others */
-	}
-
 	/** Compute shared subslave ratio (subslaves per ordinary slave) */
 	get subSlaveRatio() {
 		const subSlaves = this.subSlaveMap.get(0);
diff --git a/src/endWeek/saSocialEffects.js b/src/endWeek/saSocialEffects.js
index c42351cb826..be05b5c49d2 100644
--- a/src/endWeek/saSocialEffects.js
+++ b/src/endWeek/saSocialEffects.js
@@ -1,5 +1,5 @@
 /** Apply and return description of social effects
- * @param {App.Entity.SlaveState} slave
+ * @param {FC.ReportSlave} slave
  * @returns {DocumentFragment}
  */
 App.SlaveAssignment.saSocialEffects = function(slave) {
@@ -806,10 +806,10 @@ App.SlaveAssignment.saSocialEffects = function(slave) {
 					`Society <span class="green">approves</span> of ${his} intense fetish; the expectation that everyone's deepest desires should be fulfilled grows.`));
 			}
 			// paraphiliaSatisfied is set in saLongTermMentalEffects.js
-			if (App.EndWeek.saVars.paraphiliaSatisfied > 0) {
+			if (slave.paraphiliaSatisfied > 0) {
 				t.push(new SocialEffect("Hedonistic", 1, `Satisfied paraphilia`,
 					`Society <span class="green">is pleased</span> that ${he} is allowed to fully indulge ${his} paraphilia.`));
-			} else if (App.EndWeek.saVars.paraphiliaSatisfied < 0) {
+			} else if (slave.paraphiliaSatisfied < 0) {
 				t.push(new SocialEffect("Hedonistic", -2, `Unsatisfied paraphilia`,
 					`Society <span class="red">frowns</span> upon ${him} not being allowed to indulge in ${his} paraphilia.`));
 			}
@@ -890,7 +890,7 @@ App.SlaveAssignment.saSocialEffects = function(slave) {
 
 		for (const effect of socialEffects) {
 			if (effect.FS) { // combined rep & FS
-				const repChange = FutureSocieties.Change(effect.FS, effect.magnitude, App.EndWeek.saVars.pornFameBonus);
+				const repChange = FutureSocieties.Change(effect.FS, effect.magnitude, slave.pornFameBonus);
 				if (effect.creditFacility) {
 					applyFacilityCredit(repChange);
 				}
@@ -973,10 +973,9 @@ App.SlaveAssignment.saSocialEffects = function(slave) {
 
 	let socialEffects = [];
 	if (V.FSAnnounced > 0) {
-		App.EndWeek.saVars.pornFameBonus = 1; // TODO: once the slave part of saVars is properly reinitialized for every slave, delete this line.
 		if (V.studio === 1) {
 			if (slave.porn.viewerCount > 0) {
-				App.EndWeek.saVars.pornFameBonus += (Math.ceil(slave.porn.viewerCount/100000));
+				slave.pornFameBonus += (Math.ceil(slave.porn.viewerCount/100000));
 				if (slave.porn.viewerCount >= 100000) {
 					frag.append(`${His} near-ubiquitous presence in arcology pornography greatly increases ${his} impact on society. `);
 				} else if ((slave.porn.viewerCount >= 10000)) {
diff --git a/src/endWeek/saWhore.js b/src/endWeek/saWhore.js
index e817101e792..b7c80135853 100644
--- a/src/endWeek/saWhore.js
+++ b/src/endWeek/saWhore.js
@@ -24,7 +24,7 @@ App.SlaveAssignment.whore = (function() {
 	return saWhore;
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 * @returns {string}
 	 */
 	function saWhore(slave) {
@@ -319,7 +319,7 @@ App.SlaveAssignment.whore = (function() {
 	}
 
 	/**
-	 * @param {App.Entity.SlaveState} slave
+	 * @param {FC.ReportSlave} slave
 	 */
 	function physicalEffects(slave) {
 		let injury = 0;
diff --git a/src/endWeek/slaveAssignmentReport.js b/src/endWeek/slaveAssignmentReport.js
index 66e04ff3a74..522a6ee067c 100644
--- a/src/endWeek/slaveAssignmentReport.js
+++ b/src/endWeek/slaveAssignmentReport.js
@@ -310,9 +310,6 @@ App.EndWeek.slaveAssignmentReport = function() {
 	}
 
 	for (const facSubArr of facListArr) {
-		// TODO: this call should be in the individual reports' slave loops so slaves don't leak data to their coworkers if someone fucks up
-		App.EndWeek.saVars.nextSlave();
-
 		// @ts-ignore - the first element of the subarray is always callable but TS isn't smart enough to figure that out
 		const reportContent = App.UI.DOM.makeElement("div", facSubArr[0]());
 
diff --git a/src/endWeek/standardSlaveReport.js b/src/endWeek/standardSlaveReport.js
index a5d6800111c..4bd31d4a942 100644
--- a/src/endWeek/standardSlaveReport.js
+++ b/src/endWeek/standardSlaveReport.js
@@ -1,7 +1,7 @@
 /**
  * Generates (and returns if not silent) a standard slave report
  * This is the part after the slave's job in most facilities.
- * @param {App.Entity.SlaveState} slave
+ * @param {FC.ReportSlave} slave
  * @param {boolean} silent
  * @returns {DocumentFragment|null}
  */
@@ -21,7 +21,7 @@ App.SlaveAssignment.standardSlaveReport = function(slave, silent=false) {
 /**
  * Generates the main part of the standard slave report for an individual slave.
  * This is the section that's identical for all slaves regardless of facility.
- * @param {App.Entity.SlaveState} slave
+ * @param {FC.ReportSlave} slave
  * @returns {Array<DocumentFragment|string>}
  */
 App.SlaveAssignment.individualSlaveReport = function(slave) {
diff --git a/src/js/SlaveState.js b/src/js/SlaveState.js
index 00d2ef785c5..879e7b183a4 100644
--- a/src/js/SlaveState.js
+++ b/src/js/SlaveState.js
@@ -953,6 +953,7 @@ App.Entity.SlaveState = class SlaveState {
 		 * * "torpedo-shaped"
 		 * * "downward-facing"
 		 * * "wide-set"
+		 * * "spherical"
 		 * @type {FC.BreastShape}
 		 */
 		this.boobShape = "normal";
@@ -965,6 +966,7 @@ App.Entity.SlaveState = class SlaveState {
 		 * * "cute"
 		 * * "partially inverted"
 		 * * "fuckable"
+		 * * "flat"
 		 * @type {FC.NippleShape}
 		 */
 		this.nipples = "cute";
diff --git a/src/js/utilsSlave.js b/src/js/utilsSlave.js
index 5fe7731b0a6..d20a85176e9 100644
--- a/src/js/utilsSlave.js
+++ b/src/js/utilsSlave.js
@@ -2062,7 +2062,7 @@ globalThis.newSlave = function(slave) {
 };
 
 /**
- * @param {App.Entity.SlaveState} slave
+ * @param {App.Entity.SlaveState|FC.ReportSlave} slave
  * @returns {number}
  */
 globalThis.fetishChangeChance = function(slave) {
@@ -2070,7 +2070,7 @@ globalThis.fetishChangeChance = function(slave) {
 		fetish = (slave.fetishStrength / 4),
 		sex = 0;
 
-	if (slave.clitSetting !== slave.fetish && !(App.EndWeek.saVars && App.EndWeek.saVars.fetishChanged === 1)) {
+	if (slave.clitSetting !== slave.fetish && !('fetishChanged' in slave && slave.fetishChanged === 1)) {
 		// fetish should be more uncertain leading towards puberty and then steadily become more set in stone afterwards
 		if (slave.balls) {
 			if (V.potencyAge >= slave.actualAge) {
-- 
GitLab