From 8c6b420c0c2c771e68eff32c7ed3cd6d6029ce49 Mon Sep 17 00:00:00 2001
From: lowercasedonkey <lowercasedonkey@gmail.com>
Date: Tue, 29 Dec 2020 18:21:39 -0500
Subject: [PATCH] move unlock to be a part of a new fs object in data

---
 js/003-data/slaveWearData.js  | 86 +++++++++++++++++++----------------
 src/interaction/siWardrobe.js | 56 +++++++++++++++++------
 src/js/itemAvailability.js    | 10 ++--
 3 files changed, 94 insertions(+), 58 deletions(-)

diff --git a/js/003-data/slaveWearData.js b/js/003-data/slaveWearData.js
index 1189a411fd9..a8d755dffc0 100644
--- a/js/003-data/slaveWearData.js
+++ b/js/003-data/slaveWearData.js
@@ -1,8 +1,18 @@
+/**
+ * @typedef {object} itemFS
+ * @property {FC.FutureSociety} unlocks
+ * @property {Set<FC.FutureSociety>} [fsLoves] FS loves to see this outfit.
+ * @property {Set<FC.FutureSociety>} [fsTolerates] FS tolerates this outfit.
+ * @property {Set<FC.FutureSociety>} [fsHates] FS hates to see this outfit.
+ */
+
 /**
  * @typedef {object} clothes
  * @property {string} name
- * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS.
+ * @property {itemFS} [fs] Automatically unlocked with this FS.
  * @property {Set<FC.FutureSociety>} [fsLoves] FS loves to see this outfit.
+ * @property {Set<FC.FutureSociety>} [fsTolerates] FS tolerates this outfit.
+ * @property {Set<FC.FutureSociety>} [fsHates] FS hates to see this outfit.
  * @property {boolean} [requirements]
  * @property {0|1|2|3|4} [exposure] 0: Modest, 1: Acceptable, 2: Slutty, 3: Humiliating (exposes genitals), 4: Might as well be nude
  * @property {boolean} [harsh]
@@ -16,7 +26,7 @@ App.Data.clothes = new Map([
 	["attractive lingerie for a pregnant woman",
 		{
 			name: "Maternity lingerie",
-			fs: "FSRepopulationFocus",
+			fs: {unlocks: "FSRepopulationFocus"},
 			fsLoves: new Set(["FSIntellectualDependency"]),
 			get requirements() { return V.boughtItem.clothing.maternityLingerie === 1; },
 			exposure: 2
@@ -25,7 +35,7 @@ App.Data.clothes = new Map([
 	["a bunny outfit",
 		{
 			name: "Bunny outfit",
-			fs: "FSGenderFundamentalist",
+			fs: {unlocks: "FSGenderFundamentalist"},
 			fsLoves: new Set(["FSGenderFundamentalist"]),
 			get requirements() { return V.boughtItem.clothing.bunny === 1; },
 			exposure: 1
@@ -34,7 +44,7 @@ App.Data.clothes = new Map([
 	["body oil",
 		{
 			name: "Body oil",
-			fs: "FSPhysicalIdealist",
+			fs: {unlocks: "FSPhysicalIdealist"},
 			fsLoves: new Set(["FSPhysicalIdealist"]),
 			get requirements() { return V.boughtItem.clothing.oil === 1; },
 			exposure: 4
@@ -43,7 +53,7 @@ App.Data.clothes = new Map([
 	["a chattel habit",
 		{
 			name: "Chattel habit",
-			fs: "FSChattelReligionist",
+			fs: {unlocks: "FSChattelReligionist"},
 			fsLoves: new Set(["FSChattelReligionist"]),
 			get requirements() { return V.boughtItem.clothing.habit === 1; },
 			exposure: 3
@@ -52,7 +62,7 @@ App.Data.clothes = new Map([
 	["conservative clothing",
 		{
 			name: "Conservative clothing",
-			fs: "FSPaternalist",
+			fs: {unlocks: "FSPaternalist"},
 			fsLoves: new Set(["FSPaternalist"]),
 			get requirements() { return V.boughtItem.clothing.conservative === 1; },
 			exposure: 0
@@ -61,7 +71,7 @@ App.Data.clothes = new Map([
 	["harem gauze",
 		{
 			name: "Harem gauze",
-			fs: "FSArabianRevivalist",
+			fs: {unlocks: "FSArabianRevivalist"},
 			fsLoves: new Set(["FSArabianRevivalist"]),
 			get requirements() { return V.boughtItem.clothing.harem === 1; },
 			exposure: 1
@@ -70,7 +80,7 @@ App.Data.clothes = new Map([
 	["a huipil",
 		{
 			name: "Huipil",
-			fs: "FSAztecRevivalist",
+			fs: {unlocks: "FSAztecRevivalist"},
 			fsLoves: new Set(["FSAztecRevivalist"]),
 			get requirements() { return V.boughtItem.clothing.huipil === 1; },
 			exposure: 0
@@ -79,7 +89,7 @@ App.Data.clothes = new Map([
 	["a kimono",
 		{
 			name: "Kimono",
-			fs: "FSEdoRevivalist",
+			fs: {unlocks: "FSEdoRevivalist"},
 			fsLoves: new Set(["FSEdoRevivalist"]),
 			get requirements() { return (V.boughtItem.clothing.kimono === 1 || V.continent === "Japan"); },
 			exposure: 0
@@ -88,7 +98,7 @@ App.Data.clothes = new Map([
 	["a maternity dress",
 		{
 			name: "Maternity dress",
-			fs: "FSRepopulationFocus",
+			fs: {unlocks: "FSRepopulationFocus"},
 			get requirements() { return V.boughtItem.clothing.maternityDress === 1; },
 			exposure: 0,
 		}
@@ -96,7 +106,7 @@ App.Data.clothes = new Map([
 	["a slutty qipao",
 		{
 			name: "Qipao (slutty)",
-			fs: "FSChineseRevivalist",
+			fs: {unlocks: "FSChineseRevivalist"},
 			fsLoves: new Set(["FSChineseRevivalist"]),
 			get requirements() { return V.boughtItem.clothing.qipao === 1; },
 			exposure: 2
@@ -105,7 +115,7 @@ App.Data.clothes = new Map([
 	["a long qipao",
 		{
 			name: "Qipao (long)",
-			fs: "FSChineseRevivalist",
+			fs: {unlocks: "FSChineseRevivalist"},
 			get requirements() { return V.boughtItem.clothing.cultural === 1; },
 			exposure: 0
 		}
@@ -113,7 +123,7 @@ App.Data.clothes = new Map([
 	["Imperial Plate",
 		{
 			name: "Imperial Plate",
-			fs: "FSNeoImperialist",
+			fs: {unlocks: "FSNeoImperialist"},
 			get requirements() { return V.boughtItem.clothing.imperialarmor === 1; },
 			exposure: 0
 		}
@@ -121,7 +131,7 @@ App.Data.clothes = new Map([
 	["a tight Imperial bodysuit",
 		{
 			name: "Imperial Bodysuit",
-			fs: "FSNeoImperialist",
+			fs: {unlocks: "FSNeoImperialist"},
 			get requirements() { return V.boughtItem.clothing.imperialsuit === 1; },
 			exposure: 2
 		}
@@ -129,7 +139,7 @@ App.Data.clothes = new Map([
 	["stretch pants and a crop-top",
 		{
 			name: "Stretch pants and a crop-top",
-			fs: "FSHedonisticDecadence",
+			fs: {unlocks: "FSHedonisticDecadence"},
 			get requirements() { return V.boughtItem.clothing.lazyClothes === 1; },
 			exposure: 0
 		}
@@ -137,7 +147,7 @@ App.Data.clothes = new Map([
 	["a toga",
 		{
 			name: "Toga",
-			fs: "FSRomanRevivalist",
+			fs: {unlocks: "FSRomanRevivalist"},
 			fsLoves: new Set(["FSRomanRevivalist"]),
 			get requirements() { return V.boughtItem.clothing.toga === 1; },
 			exposure: 1
@@ -146,7 +156,7 @@ App.Data.clothes = new Map([
 	["Western clothing",
 		{
 			name: "Western clothing",
-			fs: "FSPastoralist",
+			fs: {unlocks: "FSPastoralist"},
 			fsLoves: new Set(["FSPastoralist"]),
 			get requirements() { return V.boughtItem.clothing.western === 1; },
 			exposure: 3
@@ -155,7 +165,7 @@ App.Data.clothes = new Map([
 	["a courtesan dress",
 		{
 			name: "Courtesan dress",
-			fs: "FSSlaveProfessionalism",
+			fs: {unlocks: "FSSlaveProfessionalism"},
 			fsLoves: new Set(["FSSlaveProfessionalism"]),
 			get requirements() { return V.boughtItem.clothing.courtesan === 1; },
 			exposure: 1
@@ -164,7 +174,7 @@ App.Data.clothes = new Map([
 	["a bimbo outfit",
 		{
 			name: "Bimbo outfit",
-			fs: "FSIntellectualDependency",
+			fs: {unlocks: "FSIntellectualDependency"},
 			fsLoves: new Set(["FSIntellectualDependency"]),
 			get requirements() { return V.boughtItem.clothing.bimbo === 1; },
 			exposure: 2
@@ -173,7 +183,7 @@ App.Data.clothes = new Map([
 	["petite admi outfit",
 		{
 			name: "Petite admi outfit",
-			fs: "FSPetiteAdmiration",
+			fs: {unlocks: "FSPetiteAdmiration"},
 			get requirements() { return V.boughtItem.clothing.petite === 1; },
 			exposure: 0
 		}
@@ -805,7 +815,7 @@ App.Data.clothes = new Map([
 	["chains",
 		{
 			name: "Chains",
-			fs: "FSDegradationist",
+			fs: {unlocks: "FSDegradationist"},
 			fsLoves: new Set(["FSDegradationist"]),
 			get requirements() { return V.boughtItem.clothing.chains === 1; },
 			exposure: 4,
@@ -855,7 +865,7 @@ App.Data.clothes = new Map([
 /**
  * @typedef {object} slaveWear
  * @property {string} name
- * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS.
+ * @property {itemFS} [fs] Automatically unlocked with this FS.
  * @property {boolean} [requirements]
  * @property {boolean} [harsh]
  */
@@ -893,7 +903,7 @@ App.Data.slaveWear = {
 		["bowtie",
 			{
 				name: "Bowtie collar",
-				fs: "FSGenderFundamentalist",
+				fs: {unlocks: "FSGenderFundamentalist"},
 				get requirements() {
 					return V.boughtItem.clothing.bunny === 1;
 				}
@@ -902,7 +912,7 @@ App.Data.slaveWear = {
 		["neck tie",
 			{
 				name: "Neck tie",
-				fs: "FSPaternalist",
+				fs: {unlocks: "FSPaternalist"},
 				get requirements() {
 					return V.boughtItem.clothing.conservative === 1;
 				}
@@ -911,7 +921,7 @@ App.Data.slaveWear = {
 		["ancient Egyptian",
 			{
 				name: "Ancient Egyptian",
-				fs: "FSEgyptianRevivalist",
+				fs: {unlocks: "FSEgyptianRevivalist"},
 				get requirements() {
 					return V.boughtItem.clothing.egypt === 1;
 				}
@@ -981,7 +991,7 @@ App.Data.slaveWear = {
 		["a small empathy belly",
 			{
 				name: "1st Trimester belly",
-				fs: "FSRepopulationFocus",
+				fs: {unlocks: "FSRepopulationFocus"},
 				get requirements() {
 					return V.boughtItem.clothing.belly === 1;
 				}
@@ -990,7 +1000,7 @@ App.Data.slaveWear = {
 		["a medium empathy belly",
 			{
 				name: "2nd Trimester belly",
-				fs: "FSRepopulationFocus",
+				fs: {unlocks: "FSRepopulationFocus"},
 				get requirements() {
 					return V.boughtItem.clothing.belly === 1;
 				}
@@ -999,7 +1009,7 @@ App.Data.slaveWear = {
 		["a large empathy belly",
 			{
 				name: "3rd Trimester belly",
-				fs: "FSRepopulationFocus",
+				fs: {unlocks: "FSRepopulationFocus"},
 				get requirements() {
 					return V.boughtItem.clothing.belly === 1;
 				}
@@ -1008,7 +1018,7 @@ App.Data.slaveWear = {
 		["a huge empathy belly",
 			{
 				name: "3rd Trimester twins belly",
-				fs: "FSRepopulationFocus",
+				fs: {unlocks: "FSRepopulationFocus"},
 				get requirements() {
 					return V.boughtItem.clothing.belly === 1;
 				}
@@ -1088,7 +1098,7 @@ App.Data.slaveWear = {
 /**
  * @typedef {object} slaveShoes
  * @property {string} name
- * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS.
+ * @property {itemFS} [fs] Automatically unlocked with this FS.
  * @property {boolean} [requirements]
  * @property {boolean} [harsh]
  * @property {number} heelHeight height in cm.  Over 4cm they may totter.  21cm and over (8 inch heels) will be painful/extreme
@@ -1144,7 +1154,7 @@ App.Data.shoes = new Map([ // TODO: add lift property
 	["platform shoes",
 		{
 			name: "Platforms",
-			fs: "FSStatuesqueGlorification",
+			fs: {unlocks: "FSStatuesqueGlorification"},
 			get requirements() {
 				return (V.boughtItem.shoes.heels === 1);
 			},
@@ -1155,7 +1165,7 @@ App.Data.shoes = new Map([ // TODO: add lift property
 	["platform heels",
 		{
 			name: "Platform heels",
-			fs: "FSStatuesqueGlorification",
+			fs: {unlocks: "FSStatuesqueGlorification"},
 			get requirements() {
 				return (V.boughtItem.shoes.heels === 1);
 			},
@@ -1166,7 +1176,7 @@ App.Data.shoes = new Map([ // TODO: add lift property
 	["extreme platform heels",
 		{
 			name: "Painfully extreme platform heels",
-			fs: "FSStatuesqueGlorification",
+			fs: {unlocks: "FSStatuesqueGlorification"},
 			get requirements() {
 				return (V.boughtItem.shoes.heels === 1);
 			},
@@ -1179,7 +1189,7 @@ App.Data.shoes = new Map([ // TODO: add lift property
 /**
  * @typedef {object} slaveButtplugs
  * @property {string} name
- * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS.
+ * @property {itemFS} [fs] Automatically unlocked with this FS.
  * @property {boolean} [requirements]
  * @property {0|1|2|3} width
  * @property {0|1|2} length
@@ -1251,7 +1261,7 @@ App.Data.buttplug = new Map([
 /**
  * @typedef {object} vaginalAccessories
  * @property {string} name
- * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS.
+ * @property {itemFS} [fs] Automatically unlocked with this FS.
  * @property {boolean} [requirements]
  * @property {0|1|2|3} width
  * @property {0|1|2} length
@@ -1347,7 +1357,7 @@ App.Data.vaginalAccessory = new Map([
  * @typedef {object} slaveWearChastity
  * @property {string} name
  * @property {object} updateSlave
- * @property {FC.FutureSociety} [fs]
+ * @property {itemFS} [fs]
  */
 
 /** @type {Map<string, slaveWearChastity>} */
@@ -1444,7 +1454,7 @@ App.Data.chastity = new Map([
 	["choose own chastity",
 		{
 			name: "Choose own chastity",
-			fs: "FSRestart",
+			fs: {unlocks: "FSRestart"},
 			updateSlave: {
 				choosesOwnChastity: 1
 			},
@@ -1453,7 +1463,7 @@ App.Data.chastity = new Map([
 	["revoke choosing own chastity",
 		{
 			name: "Revoke choosing own chastity",
-			fs: "FSRestart",
+			fs: {unlocks: "FSRestart"},
 			updateSlave: {
 				choosesOwnChastity: 0
 			},
diff --git a/src/interaction/siWardrobe.js b/src/interaction/siWardrobe.js
index 6d72f7debae..54e5e503409 100644
--- a/src/interaction/siWardrobe.js
+++ b/src/interaction/siWardrobe.js
@@ -161,9 +161,11 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 				const reshapedItem = {
 					text: object.name,
 					updateSlave: {clothes: key, choosesOwnClothes: 0},
-					FS: object.fs,
 					exposure: object.exposure,
 				};
+				if (object.fs) {
+					reshapedItem.FS = object.fs.unlocks;
+				}
 				array.push(reshapedItem);
 			}
 
@@ -193,8 +195,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 				const reshapedItem = {
 					text: object.name,
 					updateSlave: {collar: key},
-					FS: object.fs,
 				};
+				if (object.fs) {
+					reshapedItem.FS = object.fs.unlocks;
+				}
 				array.push(reshapedItem);
 			}
 
@@ -235,8 +239,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {faceAccessory: key},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			array.push(reshapedItem);
 		}
 
@@ -289,8 +295,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {mouthAccessory: key},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			array.push(reshapedItem);
 		}
 
@@ -364,8 +372,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {shoes: key},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			optionsArray.push(reshapedItem);
 		}
 
@@ -436,8 +446,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {bellyAccessory: key},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			optionsArray.push(reshapedItem);
 		}
 
@@ -504,8 +516,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {buttplug: key},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			if (object.length > 1) {
 				longArray.push(reshapedItem);
 			} else {
@@ -526,8 +540,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 				const reshapedItem = {
 					text: object.name,
 					updateSlave: {buttplug: key},
-					FS: object.fs,
 				};
+				if (object.fs) {
+					reshapedItem.FS = object.fs.unlocks;
+				}
 				customArray.push(reshapedItem);
 			}
 			App.UI.DOM.appendNewElement("div", el, generateRows(customArray, "buttplug", false), "choices");
@@ -566,8 +582,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {buttplugAttachment: key},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			optionsArray.push(reshapedItem);
 		}
 
@@ -614,8 +632,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {vaginalAccessory: key},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			if (object.width === 0) {
 				bulletArray.push(reshapedItem);
 			} else if (object.length > 1) {
@@ -666,8 +686,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {vaginalAttachment: key},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			optionsArray.push(reshapedItem);
 		}
 
@@ -710,8 +732,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {dickAccessory: key},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			optionsArray.push(reshapedItem);
 		}
 
@@ -785,8 +809,10 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			const reshapedItem = {
 				text: object.name,
 				updateSlave: {},
-				FS: object.fs,
 			};
+			if (object.fs) {
+				reshapedItem.FS = object.fs.unlocks;
+			}
 			// FIXME: Property 'updateSlave' does not exist on type 'slaveWear | slaveWearChastity'.
 			Object.assign(reshapedItem.updateSlave, object.updateSlave);
 			optionsArray.push(reshapedItem);
@@ -1073,8 +1099,8 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 			return Cloth + ". " + (desc || "");
 		}
 	}
-	/** @typedef RowItem
-	 * @type {object}
+	/**
+	 * @typedef {object} RowItem
 	 * @property {FC.FutureSociety} [FS] - FS requirement, if any
 	 * @property {string} [text] - link text
 	 * @property {object} [updateSlave] - properties to be merged onto the slave
diff --git a/src/js/itemAvailability.js b/src/js/itemAvailability.js
index 3159e900e4d..edf3a1ff09f 100644
--- a/src/js/itemAvailability.js
+++ b/src/js/itemAvailability.js
@@ -37,7 +37,7 @@ globalThis.isItemAccessible = (function() {
 				continue;
 			}
 			if (V.cheatMode || isAvailable(obj)) {
-				const name = (obj.fs) ? `${obj.name} (FS)` : obj.name;
+				const name = (obj.fs.unlocks) ? `${obj.name} (FS)` : obj.name;
 				array.push([name, key]);
 			}
 		}
@@ -58,7 +58,7 @@ globalThis.isItemAccessible = (function() {
 				return slaveResults;
 			}
 		}
-		if (!(item.hasOwnProperty("fs")) && !(item.hasOwnProperty("requirements"))) {
+		if (!(item.hasOwnProperty("fs") && item.fs.hasOwnProperty("unlocks")) && !(item.hasOwnProperty("requirements"))) {
 			// No restriction, this clothing item is available to everyone
 			return true;
 		}
@@ -67,8 +67,8 @@ globalThis.isItemAccessible = (function() {
 				return true;
 			}
 		}
-		if (item.hasOwnProperty("fs")) {
-			if (V.arcologies[0][item.fs] > 0) {
+		if (item.hasOwnProperty("fs") && item.fs.hasOwnProperty("unlocks")) {
+			if (V.arcologies[0][item.fs.unlocks] > 0) {
 				return true;
 			}
 		}
@@ -319,7 +319,7 @@ globalThis.limbToProsthetic = function(limb) {
 globalThis.clothingLovedByAnFS = function(FS) {
 	const clothingOptions = [];
 	for (const [key, value] of App.Data.clothes) {
-		if (value.fsLoves && value.fsLoves.has(FS)) {
+		if (value.fs.fsLoves && value.fs.fsLoves.has(FS)) {
 			clothingOptions.push(key);
 		}
 	}
-- 
GitLab