From 656915683abee5d7eee8d20f76b619c2f2c9c4d3 Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Sat, 22 Feb 2025 21:03:44 -0500
Subject: [PATCH 1/4] Don't reuse seeds improperly.

---
 src/npc/generate/generateNewSlaveJS.js | 28 ++++++++++----------------
 1 file changed, 11 insertions(+), 17 deletions(-)

diff --git a/src/npc/generate/generateNewSlaveJS.js b/src/npc/generate/generateNewSlaveJS.js
index 9ecec833664..d60cdb885f8 100644
--- a/src/npc/generate/generateNewSlaveJS.js
+++ b/src/npc/generate/generateNewSlaveJS.js
@@ -1633,36 +1633,31 @@ globalThis.GenerateNewSlave = (function() {
 				break;
 		}
 		slave.lips = jsRandom(lips.min, lips.max, undefined, getSeed());
-		let seed = getSeed();
-		slave.origSkin = (seed) ? jsSeededEither(seed, origSkins) : jsSeededEither(getSeed(), origSkins);
-		seed = getSeed();
-		slave.origHColor = (seed) ? jsSeededEither(seed, origHColors) : jsSeededEither(getSeed(), origHColors);
-		seed = getSeed();
-		slave.hStyle = (seed) ? jsSeededEither(seed, hStyles) : jsSeededEither(getSeed(), hStyles);
+		slave.origSkin = jsSeededEither(getSeed(), origSkins);
+		slave.origHColor = jsSeededEither(getSeed(), origHColors);
+		slave.hStyle = jsSeededEither(getSeed(), hStyles);
 		eyeColor(eyeColors, heteroOnly);
 		if (slave.origHColor === "red") {
-			seed = getSeed();
 			origHColors = ["chestnut", "auburn", "auburn", "auburn", "auburn", "ginger", "ginger", "copper", "copper", "red"];
-			slave.origHColor = (seed) ? jsSeededEither(seed, origHColors) : jsSeededEither(getSeed(), origHColors);
+			slave.origHColor = jsSeededEither(getSeed(), origHColors);
 		}
 		if (jsRandom(1, 100, undefined, getSeed()) <= V.seeRandomHair) {
 			origHColors = ["amber", "auburn", "black", "blazing red", "blonde", "blue-violet", "blue", "brown", "burgundy", "chestnut", "chocolate brown", "copper", "dark blue", "dark brown", "dark orchid", "deep red", "ginger", "golden", "green-yellow", "green", "grey", "hazel", "jet black", "neon blue", "neon green", "neon pink", "pink", "platinum blonde", "purple", "rainbow", "red", "sea green", "silver", "strawberry-blonde", "white"];
-			slave.origHColor = (seed) ? jsSeededEither(seed, origHColors) : jsSeededEither(getSeed(), origHColors);
+			slave.origHColor = jsSeededEither(getSeed(), origHColors);
 			if (jsRandom(1, 3, undefined, getSeed()) === 1) {
 				slave.eyebrowHColor = slave.origHColor;
 			}
 		}
-		seed = getSeed();
 		if ((skinToneLevel(slave.origSkin) > 5) && (skinToneLevel(slave.origSkin) < 10)) { // pale to fair
-			if (jsRandom(1, 4, undefined, seed) === 1) {
+			if (jsRandom(1, 4, undefined, getSeed()) === 1) {
 				/** @type {FC.Markings[]} */
 				let markings = ["beauty mark", "beauty mark", "birthmark", "birthmark", "freckles", "freckles", "freckles", "heavily freckled"];
-				slave.markings = (seed) ? jsSeededEither(seed, markings) : jsSeededEither(getSeed(), markings);
+				slave.markings = jsSeededEither(getSeed(), markings);
 			}
-		} else if (jsRandom(1, 8, undefined, seed) === 1) {
+		} else if (jsRandom(1, 8, undefined, getSeed()) === 1) {
 			/** @type {FC.Markings[]} */
 			let markings = ["beauty mark", "birthmark"];
-			slave.markings = (seed) ? jsSeededEither(seed, markings) : jsSeededEither(getSeed(), markings);
+			slave.markings = jsSeededEither(getSeed(), markings);
 		}
 
 		/**
@@ -1670,12 +1665,11 @@ globalThis.GenerateNewSlave = (function() {
 		 * @param {boolean} [heteroOnly]
 		 */
 		function eyeColor(colors, heteroOnly = false) {
-			let seed = getSeed();
 			if (!heteroOnly) {
-				setGeneticEyeColor(slave, (seed) ? jsSeededEither(seed, colors) : jsSeededEither(getSeed(), colors));
+				setGeneticEyeColor(slave, jsSeededEither(getSeed(), colors));
 			}
 			if (slave.geneticQuirks.heterochromia === 2) {
-				setGeneticEyeColor(slave, (seed) ? jsSeededEither(seed, colors) : jsSeededEither(getSeed(), colors), true);
+				setGeneticEyeColor(slave, jsSeededEither(getSeed(), colors), true);
 			}
 		}
 	}
-- 
GitLab


From cda827d57a17e834349dda4d4efd872cb5cc4aa2 Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Sat, 22 Feb 2025 21:04:15 -0500
Subject: [PATCH 2/4] fix type error

---
 src/events/scheduled/seRecruiterSuccess.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/events/scheduled/seRecruiterSuccess.js b/src/events/scheduled/seRecruiterSuccess.js
index 762c29e2816..91deb9eeb03 100644
--- a/src/events/scheduled/seRecruiterSuccess.js
+++ b/src/events/scheduled/seRecruiterSuccess.js
@@ -210,7 +210,7 @@ App.Events.SERecruiterSuccess = class SERecruiterSuccess extends App.Events.Base
 
 		/** @returns {FC.PiercingType} */
 		function pierceMe() {
-			return random(0, 1);
+			return either(0, 1);
 		}
 	}
 };
-- 
GitLab


From ce7907fd89f1f7dc620003f52030a1f9045e301e Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Sat, 22 Feb 2025 21:44:41 -0500
Subject: [PATCH 3/4] Make all the slaves in `V.slaves` pass an `isSlave` check
 as part of the Main Menu's sanity checking.

---
 src/js/main.js | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/js/main.js b/src/js/main.js
index effa918da4f..ad724bc6f2f 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -180,6 +180,25 @@ App.MainView.full = function() {
 			V.huskSlave = new App.Entity.CustomSlaveOrder();
 		}
 
+		// check whether all the slaves are actually slaves
+		const badSlaves = getSlaves().filter(s => !isSlave(s));
+		if (badSlaves.size > 0) {
+			const getSafeSlaveIdentifier = (s) => {
+				try {
+					const name = SlaveFullName(s);
+					return name;
+				} catch {
+					try {
+						const ID = String(s.ID);
+						return ID;
+					} catch {
+						return 'unknown';
+					}
+				}
+			};
+			newError().append(App.UI.DOM.makeElement("span", `ERROR: the following entries in the slave list don't seem to be valid slaves: ${toSentence(badSlaves.map(s => getSafeSlaveIdentifier(s)))}. Try running Backwards Compatibility and report this error if it continues to occur.`));
+		}
+
 		return fragment;
 	}
 
-- 
GitLab


From 0882c65aec203997856e53cc29135c97178160f0 Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Sat, 22 Feb 2025 21:49:10 -0500
Subject: [PATCH 4/4] Improve the robustness of isDevelopmentFacilityLeader. It
 really shouldn't ever be passed `null` but it's well-defined and consistent
 to say that a null slave is NOT a development facility leader.

---
 src/js/releaseRules.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/js/releaseRules.js b/src/js/releaseRules.js
index 7feb6b1a95c..4797e689e83 100644
--- a/src/js/releaseRules.js
+++ b/src/js/releaseRules.js
@@ -118,11 +118,11 @@ App.Utils.releaseRestricted = function releaseRestricted(slave) {
  * @returns {boolean}
  */
 App.Utils.isDevelopmentFacilityLeader = function(employee, leader) {
-	if (!App.Data.misc.sexFromDevelopmentLeaders.includes(leader.assignment)) {
+	if (!App.Data.misc.sexFromDevelopmentLeaders.includes(leader?.assignment)) {
 		return false;
 	}
 	try {
-		const manager = App.Utils.jobForAssignment(employee.assignment)?.facility?.manager?.currentEmployee;
+		const manager = App.Utils.jobForAssignment(employee?.assignment)?.facility?.manager?.currentEmployee;
 		return (!!manager && leader.ID === manager.ID);
 	} catch {
 		return false; // could mean no job for assignment, or facility does not have a manager assigned...doesn't matter, we're only interested in matches
-- 
GitLab