From 3db1dee2118b31eaaf898f96ff3c37e86eda79d4 Mon Sep 17 00:00:00 2001
From: Blank_Alt <12406-Blank_Alt@users.noreply.gitgud.io>
Date: Mon, 14 Jun 2021 05:46:51 +0000
Subject: [PATCH] Cleanup pool

---
 devNotes/jsEventCreationGuide.md           |  27 ++--
 devNotes/usefulJSFunctionDocumentation.txt |  12 +-
 devTools/types/FC/SecExp.d.ts              |   5 +-
 src/Mods/SecExp/js/Unit.js                 | 151 +++++++++++----------
 4 files changed, 109 insertions(+), 86 deletions(-)

diff --git a/devNotes/jsEventCreationGuide.md b/devNotes/jsEventCreationGuide.md
index 1f5b9da3a6a..a9bb5483d32 100644
--- a/devNotes/jsEventCreationGuide.md
+++ b/devNotes/jsEventCreationGuide.md
@@ -1,5 +1,7 @@
 # Creating your event
 
+It would be useful to have the [JS functions Documentation](devNotes/usefulJSFunctionDocumentation.txt) open and in particular the "Core Slave Functions" section.
+
 First decide your events name e.g. MyEvent
 ```
 App.Events.MyEvent = class MyEvent extends App.Events.BaseEvent {
@@ -9,7 +11,7 @@ App.Events.MyEvent = class MyEvent extends App.Events.BaseEvent {
 			return [
 				() => V.plot === 1
 			];
-			
+
 			// empty example
 			return [];
 	}
@@ -25,7 +27,7 @@ App.Events.MyEvent = class MyEvent extends App.Events.BaseEvent {
 				s => s.trust <= 20
 			]
 		];
-		
+
 		// Dual slave
 		return [
 			[ // here's the first actor, just like above
@@ -41,7 +43,7 @@ App.Events.MyEvent = class MyEvent extends App.Events.BaseEvent {
 
 		// Wants one actor, but "any slave will do"
 		return [[]];
-		
+
 		// Empty (no actors at all)
 		return [];
 	}
@@ -55,7 +57,7 @@ App.Events.MyEvent = class MyEvent extends App.Events.BaseEvent {
 		const {
 			HeU, heU, hisU, himU, himselfU
 		} = getNonlocalPronouns(V.seeDicks).appendSuffix('U');
-		
+
 		// V.nextButton is shown to the user on the side bar, e.g. V.nextButton = "Continue";
 		// V.nextLink is the next passge that will be executed, e.g. V.nextLink = "Economics";
 
@@ -63,9 +65,9 @@ App.Events.MyEvent = class MyEvent extends App.Events.BaseEvent {
 		App.Events.drawEventArt(node, eventSlave, "no clothing");
 
 		let t = [];
-		
+
 		t.push(`Event info text goes here`)
-		
+
 		App.Events.addParagraph(node, t);
 
 		// Event branches
@@ -89,11 +91,18 @@ App.Events.MyEvent = class MyEvent extends App.Events.BaseEvent {
 	}
 };
 ```
+# Dealling with lisping
+
+`Enunciate($activeSlave)/getWrittenTitle($activeSlave)/<<say>>s/that'<<s>>/<<Master>>`
+Can be converted to
+`const {say, title: Master} = getEnunciation(eventSlave);`
+Master can just be template literalled into spoken() and it'll convert it itself.
+
 # Adding your event to the pool
 
 Now that your event has been created it needs to be added to the pool of possible events for it's type which for most
- events, as well as for our example, is random individual event. 
-This pool can be found at src/events/randomEvent.js. 
+ events, as well as for our example, is random individual event.
+This pool can be found at src/events/randomEvent.js.
 Simply add your event to the array in App.Events.getIndividualEvents.
 
 # Testing
@@ -103,7 +112,7 @@ Then go to the Debug & cheating tab and enable CheatMode.
 Once you get to "Random Individual Event" select any slave and at the bottom under DEBUG: there should be
  a input box with "Check Prerequisites and Casting" link next to it.
 Per the example under it, place your event's full name into it e.g. App.Events.myEvent and then hit said link.
-If everything works as intended you should see output 
+If everything works as intended you should see output
 
 ## Examples
 
diff --git a/devNotes/usefulJSFunctionDocumentation.txt b/devNotes/usefulJSFunctionDocumentation.txt
index 0108b253a8c..9e003755217 100644
--- a/devNotes/usefulJSFunctionDocumentation.txt
+++ b/devNotes/usefulJSFunctionDocumentation.txt
@@ -160,6 +160,12 @@ properTitle() - Returns the player's proper title. (customTitle, Sir, Ma'am)
 
 properMaster() - Returns the slave's title for Master when WrittenMaster() is inappropriate. (customTitle, Master, Mistress)
 
+WrittenMaster(slave) - Returns a slave's title for the player and sets lisping. Returns $activeSlave if not given an argument.
+
+Enunciate(slave) - Syncs lisp widgets with slave.
+
+Spoken(slave, speech) - Returns speech with lisp if slave lisps. Replaces `<<say>>s` with Spoken(slave, "says").
+
 SlaveFullName(slave) - Returns the slave's full name.
 
 PlayerName() - Returns the player's full name.
@@ -248,9 +254,7 @@ getSlave(ID) - Returns the slave object with the matching ID.
 
 getPronouns(slave) - Returns an object containing a slave's pronouns.
 
-WrittenMaster(slave) - Returns a slave's title for the player and sets lisping. Returns $activeSlave if not given an argument.
-
-Enunciate(slave) - Syncs lisp widgets with slave.
+generatePronouns(slave) - Sets slave's pronouns.
 
 fetishChangeChance(slave) - Returns an int between 0,100 as the chance of a slave's fetish shifting to a new one.
 
@@ -272,8 +276,6 @@ removeActiveSlave() - Removes $activeSlave from $slaves. Do not use without care
 
 SetBellySize(slave) - Sets slave's belly size.(pregnancy+inflation+implant)
 
-generatePronouns(slave) - Sets slave's pronouns.
-
 SoftenBehavioralFlaw(slave) - Replaces the slave's behavioral flaw with the corresponding quirk.
 
 SoftenSexualFlaw(slave) - Replaces the slave's sexual flaw with the corresponding quirk.
diff --git a/devTools/types/FC/SecExp.d.ts b/devTools/types/FC/SecExp.d.ts
index f49f3d62296..1aae726cbe2 100644
--- a/devTools/types/FC/SecExp.d.ts
+++ b/devTools/types/FC/SecExp.d.ts
@@ -20,10 +20,11 @@ declare namespace FC {
 			cyber: number,
 			medics: number,
 			SF: number,
-			commissars: number
+			commissars: number,
+			battlesFought: number,
 		}
 
-		type PlayerHumanUnitType = "bots" | "citizens" | "mercenary" | "slave" | "SF";
+		type PlayerHumanUnitType = "bots" | "slaves" | "militia" | "mercs" | "SF";
 		type EnemyUnitType = "raiders" | "free city" | "old world" | "freedom fighters";
 	}
 }
diff --git a/src/Mods/SecExp/js/Unit.js b/src/Mods/SecExp/js/Unit.js
index 3c2eac9a765..dcc0198149d 100644
--- a/src/Mods/SecExp/js/Unit.js
+++ b/src/Mods/SecExp/js/Unit.js
@@ -10,36 +10,9 @@ App.SecExp.unit = (function() {
 		humanSquads,
 		genID,
 		replenish
+		// unitFree - helper function
 	};
 
-	function base(string, operation = 'print', value = 0) {
-		let target, x = string.toLowerCase();
-
-		if (x === "slaves") {
-			target = V.menials;
-		} else if (x === "militia") {
-			target = V.SecExp.units.militia.free;
-		} else if (x === "mercs") {
-			target = V.SecExp.units.mercs.free;
-		}
-
-		if (operation === 'print') {
-			return target;
-		} else if (operation === 'add') {
-			return target += value;
-		} else if (operation === 'remove') {
-			return target -= value;
-		} else if (operation === 'set') {
-			return target = value;
-		} else if (operation === 'can upgrade') {
-			if (string === 'bots') {
-				return V.cash >= 500;
-			} else {
-				return target > 0;
-			}
-		}
-	}
-
 	/** Lists all potential military units as an array.
 	 *
 	 */
@@ -56,15 +29,12 @@ App.SecExp.unit = (function() {
 		let el = document.createElement("a");
 
 		function upgradeUnit(x) {
+			x.equip = 3;
 			Object.assign(x, {
-				maxTroops: 50, equip: 3, commissars: 2,
+				maxTroops: 50, commissars: 2,
 				cyber: 1, medics: 1
 			});
-			if (V.SF.Active >= 1) {
-				x.SF = 1;
-			} else {
-				x.SF = 0;
-			}
+			x.SF = (V.SF.Toggle && V.SF.Active >= 1 ? 1 : 0);
 		}
 
 		function getCost(x) {
@@ -73,9 +43,7 @@ App.SecExp.unit = (function() {
 			if (x.maxTroops < 50) {
 				cost -= 5000 + (((50 - x.maxTroops) /10) * equipUpgradeCost * (x.equip + x.commissars + x.cyber + x.SF));
 			}
-			if (x.equip < 3) {
-				cost -= (equipUpgradeCost * x.maxTroops + 1000) * (3 - x.equip);
-			}
+
 			if (x.commissars < 2) {
 				cost -= (equipUpgradeCost * x.maxTroops + 1000) * (2 - x.commissars);
 			}
@@ -88,6 +56,9 @@ App.SecExp.unit = (function() {
 			if (V.SF.Toggle && V.SF.Active >= 1 && x.SF === 0) {
 				cost -= equipUpgradeCost * x.maxTroops + 5000;
 			}
+			if (x.equip < 3) {
+				cost -= (equipUpgradeCost * x.maxTroops + 1000) * (3 - x.equip);
+			}
 			return Math.ceil(cost * 1.1);
 		}
 
@@ -133,12 +104,13 @@ App.SecExp.unit = (function() {
 			ID: -1, equip: 0, active: 1, isDeployed: 0, maxTroops: 30, troops: 30
 		};
 		if (type !== "bots") {
+			V.SecExp.units[type].created++;
 			Object.assign(newUnit, {
 				training: 0, cyber: 0, medics: 0,
 				SF: 0, commissars: 0, battlesFought: 0,
 				loyalty: jsRandom(40, 60),
 				ID: genID(),
-				platoonName: `${ordinalSuffix(++V.SecExp.units[type].created)} ` + V.SecExp.units[type].defaultName
+				platoonName: `${ordinalSuffix(V.SecExp.units[type].created)} ${V.SecExp.units[type].defaultName}`
 			});
 
 			if (type === "slaves") {
@@ -152,6 +124,10 @@ App.SecExp.unit = (function() {
 		return newUnit;
 	}
 
+	/** Prints a list of upgrades that can be applied to the passed human unit.
+	 * @param {FC.SecExp.PlayerHumanUnitData} input the human unit to be checked.
+	 * @returns {HTMLDivElement}
+	 */
 	function humanUpgradeList(input) {
 		const equipUpgradeCost = 250;
 		let el = document.createElement("div"), options = document.createElement("div");
@@ -266,7 +242,7 @@ App.SecExp.unit = (function() {
 
 		for (const unit of list().slice(1)) {
 			for (const squad of V.SecExp.units[unit].squads) {
-				if (!woundedUnit.contains(unit) && squad.troops < squad.maxTroops && base(unit, 'can upgrade')) {
+				if (!woundedUnit.contains(unit) && squad.troops < squad.maxTroops && unitFree(unit, 'can upgrade')) {
 					woundedUnit.push(unit);
 				}
 			}
@@ -274,14 +250,11 @@ App.SecExp.unit = (function() {
 
 		if (woundedUnit.length > 0) {
 			el.append(App.UI.DOM.link("Replenish all units", () => {
-				for (const unit of woundedUnit) {
-					if (unit === 'bots') {
-						cashX(-((V.SecExp.units.bots.maxTroops - V.SecExp.units.bots.troops) * 500), "securityExpansion");
-						V.SecExp.units.bots.troops = V.SecExp.units.bots.maxTroops;
+				for (const u of woundedUnit) {
+					if (u === 'bots') {
+						replenish(V.SecExp.units.bots, u);
 					} else {
-						for (const squad of V.SecExp.units[unit].squads) {
-							replenish(squad, unit);
-						}
+						V.SecExp.units[u].squads.forEach(s => replenish(s, u));
 					}
 				}
 				App.UI.reload();
@@ -298,7 +271,10 @@ App.SecExp.unit = (function() {
 	}
 
 	/**
-	 * @param {FC.SecExp.PlayerUnitData} input
+	 * @param {FC.SecExp.PlayerHumanUnitData} input
+	 * @param {FC.SecExp.PlayerHumanUnitType} unitType
+	 * @param {boolean} inBattle - if true appends a deply/recall link to the description, allowing for [input] to be deployed/recalled.
+	 * @returns {HTMLDivElement}
 	 */
 	function describe(input, unitType, inBattle = false) {
 		const brief = V.SecExp.settings.unitDescriptions;
@@ -475,9 +451,6 @@ App.SecExp.unit = (function() {
 		return el;
 	}
 
-	/** Prints a list of upgrades that can be applied to the passed human unit.
-	 * @param {FC.SecExp.PlayerHumanUnitData} input the human unit to be checked.
-	 */
 	function humanSquads() {
 		let array = [];
 		for (const unit of list().slice(1)) {
@@ -497,32 +470,70 @@ App.SecExp.unit = (function() {
 		) + 1;
 	}
 
+	/** Replenishes a unit if needed
+     * @param {FC.SecExp.PlayerHumanUnitData} squad.
+     * @param {FC.SecExp.PlayerHumanUnitType} type
+	 */
 	function replenish(squad, type) {
 		const oldTroops = squad.troops;
 
-		if (base(type) >= squad.maxTroops - squad.troops) {
-			if (type === "slaves") {
-				V.menials -= (squad.maxTroops - squad.troops);
-			} else if (type === "militia") {
-				V.SecExp.units.militia.free -= (squad.maxTroops - squad.troops);
-			} else if (type === "mercs") {
-				V.SecExp.units.mercs.free -= (squad.maxTroops - squad.troops);
+		if (type !== "bots") {
+			if (unitFree(type) >= squad.maxTroops - squad.troops) {
+				unitFree(type, 'remove', (squad.maxTroops - squad.troops));
+				squad.troops = squad.maxTroops;
+			} else {
+				squad.troops += unitFree(type);
+				unitFree(type, 'set');
 			}
-			squad.troops = squad.maxTroops;
+			const expLoss = (squad.troops - oldTroops) / squad.troops;
+			squad.training -= squad.training * expLoss;
 		} else {
-			if (type === "slaves") {
-				squad.troops += V.menials;
-				V.menials = 0;
-			} else if (type === "militia") {
-				squad.troops += V.SecExp.units.militia.free;
-				V.SecExp.units.militia.free = 0;
-			} else if (type === "mercs") {
-				squad.troops += V.SecExp.units.mercs.free;
-				V.SecExp.units.mercs.free = 0;
-			}
+			cashX(-((squad.maxTroops - squad.troops) * 500), "securityExpansion");
+			squad.troops = squad.maxTroops;
+		}
+	}
+
+	/** performs operations on a unit
+	 * helper function, not callable externally
+	 * @param {FC.SecExp.PlayerHumanUnitType} type
+	 * @param {string} [operation] action to perform
+	 * @param {number} [value] amount to add/substract
+	 */
+	function unitFree(type, operation = 'print', value = 0) {
+		switch(type) {
+			case "bots":
+				if (operation === "can upgrade") {
+					return V.cash >= 500;
+				}
+				break;
+			case "slaves":
+				if (operation === 'add') {
+					V.menials += value;
+				} else if (operation === 'remove') {
+					V.menials -= value;
+				} else if (operation === 'set') {
+					V.menials = value;
+				} else if (operation === 'can upgrade') {
+					return V.menials > 0;
+				} else {
+					return V.menials;
+				}
+				break;
+			case "militia":
+			case "mercs":
+				if (operation === 'add') {
+					V.SecExp.units[type].free += value;
+				} else if (operation === 'remove') {
+					V.SecExp.units[type].free -= value;
+				} else if (operation === 'set') {
+					V.SecExp.units[type].free = value;
+				} else if (operation === 'can upgrade') {
+					return V.SecExp.units[type].free > 0;
+				} else {
+					return V.SecExp.units[type].free;
+				}
+				break;
 		}
-		const expLoss = (squad.troops - oldTroops) / squad.troops;
-		squad.training -= squad.training * expLoss;
 	}
 })();
 
-- 
GitLab