From eacadadaeadd104d39752e33e3bb584cd7df2770 Mon Sep 17 00:00:00 2001
From: Svornost <11434-svornost@users.noreply.gitgud.io>
Date: Tue, 7 Jan 2020 23:13:17 -0800
Subject: [PATCH] - Add a real constructor for slave order forms
 (customSlave/huskSlave), and call it in all the appropriate places - Document
 the properties of the slave order form and how they differ from the similar
 members in SlaveState - Add a simple check for $customSlave and $huskSlave
 accidentally turning into real slaves, and destroy the objects noisily if
 that happens

---
 src/init/storyInit.tw                       |   4 +-
 src/js/CustomSlave.js                       | 209 ++++++++++++++++++++
 src/uncategorized/BackwardsCompatibility.tw |   2 +-
 src/uncategorized/customSlave.tw            |   2 +-
 src/uncategorized/main.tw                   |   8 +
 5 files changed, 221 insertions(+), 4 deletions(-)
 create mode 100644 src/js/CustomSlave.js

diff --git a/src/init/storyInit.tw b/src/init/storyInit.tw
index 8939b0ec0de..3432747b646 100644
--- a/src/init/storyInit.tw
+++ b/src/init/storyInit.tw
@@ -1366,10 +1366,10 @@ You should have received a copy of the GNU General Public License along with thi
 
 <<set $customSlaveOrdered = 0>>
 /* I am not a slave object! Do not treat me like one! */
-<<set $customSlave = {age: 19, health: 1, muscles: 0, lips: 15, heightMod: "normal", weight: 0, face: 0, race: "white", skin: "left natural", boobs: 500, butt: 3, sex: 1, virgin: 0, dick: 2, balls: 2, clit: 0, labia: 0, vaginaLube: 1, analVirgin: 0, skills: 15, skill: {whore: 15, combat: 0}, intelligence: 0, intelligenceImplant: 0, nationality: "Stateless", leg: {left: new App.Entity.LimbState(), right: new App.Entity.LimbState()}, arm: {left: new App.Entity.LimbState(), right: new App.Entity.LimbState()}, eye: new App.Entity.EyeState(), hears: 0}>>
+<<set $customSlave = new App.Entity.CustomSlaveOrder()>>
 
 <<set $huskSlaveOrdered = 0>>
-<<set $huskSlave = {age: 18, nationality: "Stateless", race: "white", sex: 1, virgin: 0}>>
+<<set $huskSlave = new App.Entity.CustomSlaveOrder()>>
 
 /*non-vanilla shit*/
 
diff --git a/src/js/CustomSlave.js b/src/js/CustomSlave.js
new file mode 100644
index 00000000000..9c9245465f9
--- /dev/null
+++ b/src/js/CustomSlave.js
@@ -0,0 +1,209 @@
+/**
+ * Contains the parameters for the player's custom slave order.
+ * Some members are ignored by huskSlave (particularly mental properties).
+ * NOTE: $customSlave/$huskSlave IS NOT A SLAVE.  Do not treat them like you would treat an instance of SlaveState.
+ */
+App.Entity.CustomSlaveOrder = class CustomSlaveOrder {
+	constructor() {
+		/** desired age, approximately
+		 * Only certain values are valid; check seCustomSlaveDelivery.tw.
+		 * @type {number}
+		 */
+		this.age = 19;
+
+		/** desired health
+		 * 0 = healthy, 1 = extremely healthy
+		 * @type {number}
+		 */
+		this.health = 1;
+
+		/** desired musculature
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.muscles = 0;
+
+		/** desired lips
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.lips = 15;
+
+		/** desired voice
+		 * -1 = unimportant; other values as in SlaveState.
+		 * @type {number}
+		 */
+		this.voice = -1;
+
+		/** desired height category
+		 * "greatly below average", "below average", "normal", "above average", or "greatly above average"
+		 * @type {string}
+		 */
+		this.heightMod = "normal";
+
+		/** desired weight
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.weight = 0;
+
+		/** desired facial attractiveness
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.face = 0;
+
+		/** desired race
+		 * "ethnicity is unimportant" or other values as in SlaveState
+		 * @type {string}
+		 */
+		this.race = "white";
+
+		/** desired skin color
+		 * "left natural" or other values as in SlaveState
+		 * @type {string}
+		 */
+		this.skin = "left natural";
+
+		/** desired boob size
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.boobs = 500;
+
+		/** desired butt size
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.butt = 3;
+
+		/** desired genetic sex and genitalia
+		 * 1 = female (XX), 2 = male (XY), 3 = futanari (XX)
+		 * @type {number}
+		 */
+		this.sex = 1;
+
+		/** virginity required
+		 * 0 = yes, 1 = no (and yes, you are reading that correctly)
+		 * @type {number}
+		 */
+		this.virgin = 0;
+
+		/** desired dick and foreskin size, male and futa only
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.dick = 2;
+
+		/** desired balls and scrotum size, male and futa only
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.balls = 2;
+
+		/** desired clit size, female and futa only
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.clit = 0;
+
+		/** desired labia size, female and futa only
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.labia = 0;
+
+		/** desired vaginal lubrication, female and futa only
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.vaginaLube = 1;
+
+		/** anal virginity required
+		 * 0 = yes, 1 = no (and yes, you are reading that correctly)
+		 * @type {number}
+		 */
+		this.analVirgin = 0;
+
+		/** desired sex skill rating (anal, oral, and vaginal)
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.skills = 15;
+
+		/** desired skills rating (.whore controls both whoring and entertainment, .combat controls combat)
+		 * Values as in SlaveState.
+		 * @type {Object.<number, number>}
+		 */
+		this.skill = {whore: 15, combat: 0};
+
+		/** desired intelligence level
+		 * Range -3 to +3 (NOT the same range as SlaveState!)
+		 * @type {number}
+		 */
+		this.intelligence = 0;
+
+		/** desired education
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.intelligenceImplant = 0;
+
+		/** desired nationality
+		 * "Nationality is unimportant" or other values as in SlaveState.
+		 * @type {number}
+		 */
+		this.nationality = "Stateless";
+
+		/** desired left and right leg state
+		 * @type {Object.<App.Entity.LimbState, App.Entity.LimbState>}
+		 */
+		this.leg = {left: new App.Entity.LimbState(), right: new App.Entity.LimbState()};
+
+		/** desired left and right arm state
+		 * @type {Object.<App.Entity.LimbState, App.Entity.LimbState>}
+		 */
+		this.arm = {left: new App.Entity.LimbState(), right: new App.Entity.LimbState()};
+
+		/** desired eye state
+		 * Only the "vision" property is used, all others are ignored
+		 * @type {Object.<App.Entity.EyeState, App.Entity.EyeState>}
+		 */
+		this.eye = new App.Entity.EyeState();
+
+		/** hearing
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.hears = 0;
+
+		/** sense of smell
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.smells = 0;
+
+		/** sense of taste
+		 * Values as in SlaveState.
+		 * @type {number}
+		 */
+		this.tastes = 0;
+	}
+};
+
+/**
+ * Checks to see if the custom slave has accidentally been turned into an actual slave object.
+ * IF THIS FUNCTION RETURNS TRUE, YOU HAVE PROBABLY FUCKED UP A BACKCOMPAT.  CHANGE YOUR BACKCOMPAT, NOT THIS FUNCTION!
+ * @param {App.Entity.CustomSlaveOrder} slaveOrder
+ * @returns {boolean}
+ */
+App.Utils.IsCustomSlaveMutated = function(slaveOrder) {
+	/* ensure the absence of a few properties that slave orders definitely should not have, but every real slave has */
+	if (slaveOrder.hasOwnProperty("rules") || slaveOrder.hasOwnProperty("pronoun")) {
+		return true;
+	/* ensure the presence of a few properties that slave orders definitely should have, but no real slave should */
+	} else if (!slaveOrder.hasOwnProperty("age") || !slaveOrder.hasOwnProperty("sex")) {
+		return true;
+	}
+	return false;
+};
diff --git a/src/uncategorized/BackwardsCompatibility.tw b/src/uncategorized/BackwardsCompatibility.tw
index d9fefd69958..8f227e8c013 100644
--- a/src/uncategorized/BackwardsCompatibility.tw
+++ b/src/uncategorized/BackwardsCompatibility.tw
@@ -1364,7 +1364,7 @@
 	<<set $huskSlaveOrdered = 0>>
 <</if>>
 <<if ndef $huskSlave>>
-	<<set $huskSlave = {age: 18, nationality: "slave", race: "white", sex: 1, virgin: 0}>>
+	<<set $huskSlave = new App.Entity.CustomSlaveOrder()>>
 <</if>>
 <<if ndef $pedo_mode>>
 	<<set $pedo_mode = 0>>
diff --git a/src/uncategorized/customSlave.tw b/src/uncategorized/customSlave.tw
index 82fa558c14e..ee201053cdc 100644
--- a/src/uncategorized/customSlave.tw
+++ b/src/uncategorized/customSlave.tw
@@ -1345,7 +1345,7 @@ Nationality: $customSlave.nationality.
 <br><br>
 
 <<link "Reset custom order form">>
-	<<set $customSlave = {age: 19, health: 1, muscles: 0, lips: 15, heightMod: "normal", weight: 0, face: 0, race: "white", skin: "left natural", boobs: 500, butt: 3, sex: 1, virgin: 0, dick: 2, balls: 2, clit: 0, labia: 0, vaginaLube: 1, analVirgin: 0, skills: 15, skill: {whore: 15, combat: 0}, intelligence: 0, intelligenceImplant: 0, nationality: "Stateless", leg: {left: new App.Entity.LimbState(), right: new App.Entity.LimbState()}, arm: {left: new App.Entity.LimbState(), right: new App.Entity.LimbState()}, eye: new App.Entity.EyeState(), hears: 0}>>
+	<<set $customSlave = new App.Entity.CustomSlaveOrder()>>
 	<<goto "Custom Slave">>
 <</link>>
 
diff --git a/src/uncategorized/main.tw b/src/uncategorized/main.tw
index d95b3d8505a..192b5bd1dda 100644
--- a/src/uncategorized/main.tw
+++ b/src/uncategorized/main.tw
@@ -38,6 +38,14 @@
 	<<link "Hide NaN variables until next week">><<replace #NaNArray>><<set $NaNArray = []>><</replace>><</link>><br>
 <</if>>
 </span>
+<<if App.Utils.IsCustomSlaveMutated($customSlave)>>
+	<br><br>@@.red;ERROR: Your custom slave order has taken on a mutated life of its own and has been summarily shot. Refile your custom slave order, if necessary, and notify the appropriate authorities if you see this message again.@@<br><br>
+	<<set $customSlave = new App.Entity.CustomSlaveOrder()>>
+<</if>>
+<<if App.Utils.IsCustomSlaveMutated($huskSlave)>>
+	<br><br>@@.red;ERROR: Your husk slave order has taken on a mutated life of its own and has been summarily shot. Refile your husk slave order, if necessary, and notify the appropriate authorities if you see this message again.@@<br><br>
+	<<set $huskSlave = new App.Entity.CustomSlaveOrder()>>
+<</if>>
 /* end extra sanity checks and repair */
 
 <<set _duplicateSlaves = _($slaves).countBy(s => s.ID).pickBy(v => v > 1).keys().map(v => Number(v)).value()>>
-- 
GitLab