From 116b729abe20a40d98b4aa3db5e92239783b0cd2 Mon Sep 17 00:00:00 2001
From: ezsh <ezsh.junk@gmail.com>
Date: Sun, 9 Aug 2020 01:11:43 +0200
Subject: [PATCH] Another bunch of TS-based fixes

This time for the FCTV code.
---
 src/pregmod/FCTV/FCTV.js      | 29 ++++++-------
 src/pregmod/FCTV/FCTVshows.js | 77 +++++++++++++++++------------------
 2 files changed, 51 insertions(+), 55 deletions(-)

diff --git a/src/pregmod/FCTV/FCTV.js b/src/pregmod/FCTV/FCTV.js
index d2a769c5a5f..5fdf17baca0 100644
--- a/src/pregmod/FCTV/FCTV.js
+++ b/src/pregmod/FCTV/FCTV.js
@@ -23,14 +23,10 @@ globalThis.FCTV = (function() {
 	};
 
 	/** Produce an array of numbers representing all available channels in App.Data.FCTV.channels
-	 * @returns {Array}
+	 * @returns {number[]}
 	 */
 	function channels() {
-		const array = [];
-		for (const channel in App.Data.FCTV.channels) {
-			array.push(parseInt(channel, 10));
-		}
-		return array;
+		return Object.keys(App.Data.FCTV.channels).map(chStr => parseInt(chStr, 10));
 	}
 
 	function initChannels() {
@@ -161,7 +157,7 @@ globalThis.FctvDisplay = function({usedRemote = 0, seeAll = 0, selectedChannel =
 		return jQuery("#FctvWatch").empty().append(frag);
 
 		/** Creates a remote control for FCTV
-		 * @returns {node}
+		 * @returns {HTMLParagraphElement}
 		 */
 		function createRemote() {
 			const p = document.createElement("p");
@@ -175,7 +171,7 @@ globalThis.FctvDisplay = function({usedRemote = 0, seeAll = 0, selectedChannel =
 					if (selectedChannel !== i) { // Selected button
 						buttons.push(
 							App.UI.DOM.link(
-								i,
+								i.toFixed(0),
 								() => {
 									watch({usedRemote: 1, seeAll: seeAll, selectedChannel: i});
 								}
@@ -187,7 +183,7 @@ globalThis.FctvDisplay = function({usedRemote = 0, seeAll = 0, selectedChannel =
 						span.style.fontWeight = "bold";
 						span.append(
 							App.UI.DOM.link(
-								i,
+								i.toFixed(0),
 								() => {
 									watch({usedRemote: 1, seeAll: seeAll, selectedChannel: i});
 								},
@@ -200,7 +196,7 @@ globalThis.FctvDisplay = function({usedRemote = 0, seeAll = 0, selectedChannel =
 					}
 				} else { // Channel you cannot choose
 					buttons.push(
-						App.UI.DOM.disabledLink(i, [showChannel(i).text])
+						App.UI.DOM.disabledLink(i.toFixed(0), [showChannel(i).text])
 					);
 				}
 			}
@@ -302,7 +298,7 @@ globalThis.FctvDisplay = function({usedRemote = 0, seeAll = 0, selectedChannel =
 		/**
 		 * Text to frame if content won't work due to tags.
 		 * @param {string} text Reason this channel/episode can't be shown
-		 * @returns {node}
+		 * @returns {Node}
 		 */
 		function channelFailed(text) {
 			const frag = new DocumentFragment;
@@ -314,7 +310,7 @@ globalThis.FctvDisplay = function({usedRemote = 0, seeAll = 0, selectedChannel =
 
 		/**
 		 * Displays just the channel itself, including art
-		 * @returns {node}
+		 * @returns {Node}
 		 */
 		function displayShow() {
 			const frag = new DocumentFragment();
@@ -343,11 +339,12 @@ globalThis.FctvDisplay = function({usedRemote = 0, seeAll = 0, selectedChannel =
 			if (channel.intro) {
 				$(frag).append(channel.intro);
 			}
-			if (channel.episode[epToShow].text) {
-				if (typeof channel.episode[epToShow].text === 'function') {
-					$(frag).append(channel.episode[epToShow].text(slave));
+			const episodeText = channel.episode[epToShow].text;
+			if (episodeText) {
+				if (typeof episodeText === 'function') {
+					$(frag).append(episodeText(slave));
 				} else {
-					$(frag).append(channel.episode[epToShow].text);
+					$(frag).append(episodeText);
 				}
 			}
 			if (channel.outro) {
diff --git a/src/pregmod/FCTV/FCTVshows.js b/src/pregmod/FCTV/FCTVshows.js
index e2a55380f31..2d46cd0628f 100644
--- a/src/pregmod/FCTV/FCTVshows.js
+++ b/src/pregmod/FCTV/FCTVshows.js
@@ -1,8 +1,4 @@
-/**
- * @typedef {object<string, App.Entity.SlaveState>} FctvActor
- */
-
-/** @type {object.<string, FctvActor>} */
+/** @type {Object.<string, App.Entity.SlaveState>} */
 App.Data.FCTV.actors = {
 	get millie() {
 		const slave = BaseSlave();
@@ -109,7 +105,7 @@ App.Data.FCTV.actors = {
 	},
 	get premiumVirgin() {
 		let slave = GenerateNewSlave("XX", {
-			disableDisability: 1, slaveOneTimeMinAge: (V.fertilityAge + 2), slaveOneTimeMaxAge: 18, ageOverridesPedoMode: 1
+			disableDisability: 1, minAge: (V.fertilityAge + 2), maxAge: 18, ageOverridesPedoMode: 1
 		});
 		slave.devotion = jsRandom(60, 90);
 		slave.weight = jsRandom(-10, 10);
@@ -154,7 +150,7 @@ App.Data.FCTV.actors = {
 	},
 	get hyperPregnant() {
 		let slave = GenerateNewSlave("XX", {
-			disableDisability: 1, slaveOneTimeMinAge: (V.fertilityAge + 3), slaveOneTimeMaxAge: 20, ageOverridesPedoMode: 1
+			disableDisability: 1, minAge: (V.fertilityAge + 3), maxAge: 20, ageOverridesPedoMode: 1
 		});
 		slave.weight = jsRandom(10, 20);
 		slave.waist = jsRandom(-25, 25);
@@ -203,7 +199,7 @@ App.Data.FCTV.actors = {
 	},
 	get superfetation() { // superfetation
 		let slave = GenerateNewSlave("XX", {
-			disableDisability: 1, slaveOneTimeMinAge: (V.fertilityAge + 4), slaveOneTimeMaxAge: 24, ageOverridesPedoMode: 1
+			disableDisability: 1, minAge: (V.fertilityAge + 4), maxAge: 24, ageOverridesPedoMode: 1
 		});
 
 		slave.weight = jsRandom(20, 40);
@@ -246,7 +242,7 @@ App.Data.FCTV.actors = {
 	},
 	get MILF() { // MILF
 		let slave = GenerateNewSlave("XX", {
-			disableDisability: 1, slaveOneTimeMinAge: 36, slaveOneTimeMaxAge: 40, ageOverridesPedoMode: 1
+			disableDisability: 1, minAge: 36, maxAge: 40, ageOverridesPedoMode: 1
 		});
 		slave.weight = jsRandom(20, 90);
 		slave.waist = jsRandom(-45, 45);
@@ -284,7 +280,7 @@ App.Data.FCTV.actors = {
 		return slave;
 	},
 	get youngHottie() { // discount young hottie
-		let slave = GenerateNewSlave("XX", {disableDisability: 1, slaveOneTimeMaxAge: 25, ageOverridesPedoMode: 1});
+		let slave = GenerateNewSlave("XX", {disableDisability: 1, maxAge: 25, ageOverridesPedoMode: 1});
 
 		slave.face = jsRandom(70, 100);
 		slave.weight = jsRandom(-5, 10);
@@ -318,7 +314,7 @@ App.Data.FCTV.actors = {
 		return slave;
 	},
 	get hugeBalls() { // huge balls
-		let slave = GenerateNewSlave("XY", {disableDisability: 1, slaveOneTimeMaxAge: 25, ageOverridesPedoMode: 1});
+		let slave = GenerateNewSlave("XY", {disableDisability: 1, maxAge: 25, ageOverridesPedoMode: 1});
 
 		slave.anus = 2;
 		slave.balls = jsRandom(20, 35);
@@ -334,7 +330,7 @@ App.Data.FCTV.actors = {
 		return slave;
 	},
 	get mpreg() { // mpreg dickgirl
-		let slave = GenerateNewSlave("XY", {disableDisability: 1, slaveOneTimeMaxAge: 22, ageOverridesPedoMode: 1});
+		let slave = GenerateNewSlave("XY", {disableDisability: 1, maxAge: 22, ageOverridesPedoMode: 1});
 		slave.anus = 2;
 		slave.vagina = 1;
 		slave.ovaries = 0;
@@ -409,14 +405,14 @@ App.Data.FCTV.actors = {
 	},
 	get hostess() {
 		const gender = (V.seeDicks === 100) ? "XY" : "XX";
-		let races = 0;
+		let races = [];
 		if (V.arcologies[0].FSSupremacistLawME === 1) {
-			races = V.arcologies[0].FSSupremacistRace;
+			races = [V.arcologies[0].FSSupremacistRace];
 		} else if (V.arcologies[0].FSSubjugationistLawME === 1) {
 			races = setup.filterRacesLowercase.filter(race => race !== V.arcologies[0].FSSubjugationistRace);
 		}
 		const slave = GenerateNewSlave(gender, {
-			ageOverridesPedoMode: 1, oneTimeDisableDisability: 1, slaveOneTimeMinAge: 25, slaveOneTimeMaxAge: 35, fixedRace: races.jsRandom()
+			ageOverridesPedoMode: 1, disableDisability: 1, minAge: 25, maxAge: 35, race: races.random()
 		});
 		slave.devotion = 45;
 		slave.trust = 55;
@@ -438,14 +434,14 @@ App.Data.FCTV.actors = {
 	},
 	get scientist() {
 		const gender = (V.seeDicks === 0) ? "XY" : "XX";
-		let races = 0;
+		let races = [];
 		if (V.arcologies[0].FSSupremacistLawME === 1) {
-			races = V.arcologies[0].FSSupremacistRace;
+			races = [V.arcologies[0].FSSupremacistRace];
 		} else if (V.arcologies[0].FSSubjugationistLawME === 1) {
 			races = setup.filterRacesLowercase.filter(race => race !== V.arcologies[0].FSSubjugationistRace);
 		}
 		const slave = GenerateNewSlave(gender, {
-			ageOverridesPedoMode: 1, oneTimeDisableDisability: 1, slaveOneTimeMinAge: 25, slaveOneTimeMaxAge: 35, fixedRace: races.jsRandom()
+			ageOverridesPedoMode: 1, disableDisability: 1, minAge: 25, maxAge: 35, race: races.random()
 		});
 
 		slave.devotion = 0;
@@ -470,18 +466,18 @@ App.Data.FCTV.actors = {
 	},
 	get nun() {
 		const gender = (V.seeDicks === 100) ? "XY" : "XX";
-		let races = 0;
+		let races = [];
 		if (V.arcologies[0].FSSupremacistLawME === 1) {
-			races = V.arcologies[0].FSSupremacistRace;
+			races = [V.arcologies[0].FSSupremacistRace];
 		} else if (V.arcologies[0].FSSubjugationistLawME === 1) {
 			races = setup.filterRacesLowercase.filter(race => race !== V.arcologies[0].FSSubjugationistRace);
 		}
 		const slave = GenerateNewSlave(gender, {
-			ageOverridesPedoMode: 1, oneTimeDisableDisability: 1, slaveOneTimeMinAge: 25, slaveOneTimeMaxAge: 35, fixedRace: races.jsRandom()
+			ageOverridesPedoMode: 1, disableDisability: 1, minAge: 25, maxAge: 35, race: races.random()
 		});
 
 		slave.devotion = jsRandom(45, 60);
-		slave.trust = jsRandom(-10);
+		slave.trust = jsRandom(-10, 0);
 		slave.muscles = 30;
 		slave.hLength = 1;
 		slave.hStyle = "buzzcut";
@@ -517,17 +513,18 @@ App.Data.FCTV.actors = {
 /**
  * @typedef {object} FctvChannel
  * @property {FctvTags} [tags]
+ * @property {boolean} [disableSelection]
  * @property {boolean} loop After an initial viewing, should the episodes continue to play in order?
- * @property {string} intro
+ * @property {string} [intro]
  * @property {FctvEpisode[]} episode
- * @property {function(App.Entity.SlaveState, [number]):string} outro Takes slave and episode number
+ * @property {function(App.Entity.SlaveState, number):string | Node} [outro] Takes slave and episode number
  */
 
 /**
  * @typedef {object} FctvEpisode
  * @property {FctvTags} [tags]
  * @property {App.Entity.SlaveState[]} [slaves]
- * @property {string} text HTML embedded
+ * @property {(function(App.Entity.SlaveState):string) | string} text HTML embedded
  */
 
 /**
@@ -537,9 +534,10 @@ App.Data.FCTV.actors = {
  * @property {boolean} [loli]
  * @property {boolean} [extreme]
  * @property {boolean} [dicks]
+ * @property {boolean} [incest]
  */
 
-/** @type {object.<number, FctvChannel>} */
+/** @type {Object.<number, FctvChannel>} */
 App.Data.FCTV.channels = {
 	0: { // News
 		tags: {},
@@ -662,17 +660,17 @@ App.Data.FCTV.channels = {
 					r.push(`<p>The montage is overlaid with a narrator's voice: "12 of Canadia Arcology's most attractive women are all competing for the privilege of having the arcology owner's children. Clint Miles has desirable genes, and these ladies are determined to prove their worth as gestators. And here in Canadia, there are no restrictions on fertility drugs for the winner, so the competition this season is fierce! ${V.FCTV.channel.two} ladies have already been sent packing, who will be Canadia's... Next Top Breeder!?" The title finally pops up, redundantly labeling the show as 'Next Top Breeder: Canadia'.`);
 					if (MSL >= 1) {
 						r.push(`</p><p>You don't spend very much time actually watching the show; the randy opening, perverted competitions, and constant talk of creampies quickly has`);
-						if (MSL >= 1 && S.Concubine !== 0) {
+						if (MSL >= 1 && S.Concubine) {
 							r.push(`<span class="pink">${S.Concubine.slaveName}</span> eager for some attention from ${getPronouns(S.Concubine).possessive} own arcology owner. Of course, the same could be said for the other eager slaves living in your bedroom, and the situation quickly devolves into a lust-filled`);
 							if (MSL > 1) {
 								r.push(`orgy.`);
 							} else {
 								r.push(`threesome.`);
 							}
-						} else if (MSL === 0 && S.Concubine !== 0) {
+						} else if (MSL === 0 && S.Concubine) {
 							const {his2, him2, he2} = getPronouns(S.Concubine).appendSuffix(`2`);
 							r.push(`<span class="pink">${S.Concubine.slaveName}</span> eager for some attention from ${his2} own arcology owner. You've trained ${him2} well, and ${he2} knows exactly how to please you. You spend the rest of the evening doing something a lot more fun than watching reality TV.`);
-						} else if (MSL >= 1 && S.Concubine === 0) {
+						} else if (MSL >= 1 && !S.Concubine) {
 							r.push(`the pleasure slaves in your bed eager for some attention from their own arcology owner. You spend the rest of the evening doing something a lot more fun than watching reality TV.`);
 						}
 					}
@@ -1169,6 +1167,7 @@ App.Data.FCTV.channels = {
 		intro: `which is currently showing a preview of the how-to series "Extreme Gestation for Fun and Profit", hosted by Millie. It seems like the show's going to cover topics ranging from hyper-pregnancy to broodmother implants, and even hints and some sort of medical technique to allow anal pregnancy in males.`,
 		episode: [
 			{
+				text: null,
 				slaves: [
 					App.Data.FCTV.actors.millie
 				],
@@ -1501,8 +1500,8 @@ App.Data.FCTV.channels = {
 				},
 				get text() {
 					const r = [];
-					const {his} = S.Concubine ? getPronouns(S.Concubine) : {};
-					const {title: Master} = canTalk(S.Concubine) ? getEnunciation(S.Concubine) : {};
+					const {He = '', him = '', his = ''} = S.Concubine ? getPronouns(S.Concubine) : {};
+					const {title: Master = ''} = canTalk(S.Concubine) ? getEnunciation(S.Concubine) : {};
 
 					if (FCTV.channelCount(11, 1, 'gt')) {
 						r.push(`, once again,`);
@@ -1510,7 +1509,7 @@ App.Data.FCTV.channels = {
 					r.push(`which is currently showing an infomercial attempting to sell a product named "sag-B-gone" that claims to be able to prevent breasts from naturally sagging under their own weight.</p><p>`);
 					if (V.purchasedSagBGone === 1) {
 						r.push(`You've already made the mistake of ordering the sham of a product. While it gave you a great excuse to fondle breasts, it's not like you needed one in the first place.</p>`);
-						if (S.Concubine !== 0 && canTalk(S.Concubine)) {
+						if (S.Concubine && canTalk(S.Concubine)) {
 							r.push(`<p>`);
 							r.push(Spoken(S.Concubine, `"I told you it wouldn't work, ${Master}. Plus you know you can touch these anytime!"`));
 							r.push(`${S.Concubine.slaveName} shakes ${his} chest at you.</p>`);
@@ -1526,7 +1525,7 @@ App.Data.FCTV.channels = {
 							if (V.PC.dick !== 0) {
 								r.push(`At the very least it should make for some decent lubricant for a titfuck.`);
 							}
-							if (S.Concubine !== 0) {
+							if (S.Concubine) {
 								r.push(`</p><p>`);
 								if (S.Concubine.boobs > 2000 && S.Concubine.boobShape === "saggy") {
 									r.push(S.Concubine.slaveName);
@@ -2008,26 +2007,26 @@ App.Data.FCTV.channels = {
 						r.push(`appreciating the life growing within you and what future prospects may await it.</p>`);
 					} else if (V.PC.dick >= 1) {
 						r.push(`<p>Stunned and fully erect, you inexplicably feel the urge to creampie a pussy, so you`);
-						if (S.Concubine !== 0 && S.Concubine.vagina > 0 && canDoVaginal(S.Concubine)) {
+						if (S.Concubine && S.Concubine.vagina > 0 && canDoVaginal(S.Concubine)) {
 							const {him} = getPronouns(S.Concubine);
 							r.push(`grab ${S.Concubine.slaveName} and recreate the entire ending with ${him}.`);
 							S.Concubine.counter.vaginal++;
 							V.vaginalTotal++;
 							if (canImpreg(S.Concubine, V.PC)) {
-								r.push(knockMeUp(S.Concubine, 10, 0, -1, 1));
+								r.push(knockMeUp(S.Concubine, 10, 0, -1, true));
 							}
 						} else if (V.fuckSlaves > 0) {
 							r.push(`grab the nearest slave watching with you, who is overjoyed to recreate the entire ending with you.`);
 						} else {
-							r.push(`make your way to the slave dormitory and pick out the perfect ${slave}.`);
+							r.push(`make your way to the slave dormitory and pick out the perfect slave.`);
 						}
 						r.push(`You've never had a more hope-filled orgasm.</p>`);
 					} else if (V.PC.vagina >= 1) {
 						r.push(`<p>Stunned and soaking wet, you hurry to`);
-						if (S.Concubine !== 0 && canPenetrate(S.Concubine) && canImpreg(V.PC, S.Concubine) && (V.policies.sexualOpenness === 1 || S.Concubine.toyHole === "dick")) {
+						if (S.Concubine && canPenetrate(S.Concubine) && canImpreg(V.PC, S.Concubine) && (V.policies.sexualOpenness === 1 || S.Concubine.toyHole === "dick")) {
 							const {him} = getPronouns(S.Concubine);
 							r.push(`get ${S.Concubine.slaveName} nice and hard before recreating the entire ending with ${him}. You've never had a more hope-filled orgasm.`);
-							r.push(knockMeUp(V.PC, 10, 0, S.Concubine.ID, 1));
+							r.push(knockMeUp(V.PC, 10, 0, S.Concubine.ID, true));
 							S.Concubine.counter.penetrative++;
 							V.penetrativeTotal++;
 						} else if (V.policies.sexualOpenness === 1) {
@@ -2113,7 +2112,7 @@ App.Data.FCTV.channels = {
 			// All actors are at least 18
 			const r = [];
 			r.push(`<p>As you snuggle in for the night`);
-			if (S.Concubine !== 0) {
+			if (S.Concubine) {
 				r.push(`with your concubine, you`);
 			} else {
 				r.push(`you`);
-- 
GitLab