diff --git a/.gitignore b/.gitignore index a8e5e95aaf38882c899baf4745d843619fbed5fe..443b678cc403fdbb5010386d8564041f96cb421d 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,6 @@ TODO.txt temp.* *.temp src/002-config/fc-version.js.commitHash.js + +# macOS devices +*.icloud diff --git a/js/003-data/slaveWearData.js b/js/003-data/slaveWearData.js index 2f8b6e4374e123e50e6cec791162894b4f484e77..c52b04062e51b860eab09c30c50d5aedf6508222 100644 --- a/js/003-data/slaveWearData.js +++ b/js/003-data/slaveWearData.js @@ -1,7 +1,15 @@ +/** + * @typedef {object} itemFS + * @property {FC.FutureSociety} [unlocks] Automatically unlocked with this FS. + * @property {Set<FC.FutureSociety>} [loves] FS loves to see this outfit. + * @property {Set<FC.FutureSociety>} [tolerates] FS tolerates this outfit. + * @property {Set<FC.FutureSociety>} [hates] FS hates to see this outfit. + */ + /** * @typedef {object} clothes * @property {string} name - * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS. + * @property {itemFS} [fs] * @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] @@ -15,7 +23,10 @@ App.Data.clothes = new Map([ ["attractive lingerie for a pregnant woman", { name: "Maternity lingerie", - fs: "FSRepopulationFocus", + fs: { + unlocks: "FSRepopulationFocus", + loves: new Set(["FSIntellectualDependency", "FSRepopulationFocus"]), + }, get requirements() { return V.boughtItem.clothing.maternityLingerie === 1; }, exposure: 2 } @@ -23,7 +34,11 @@ App.Data.clothes = new Map([ ["a bunny outfit", { name: "Bunny outfit", - fs: "FSGenderFundamentalist", + fs: { + unlocks: "FSGenderFundamentalist", + loves: new Set(["FSGenderFundamentalist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.bunny === 1; }, exposure: 1 } @@ -31,7 +46,11 @@ App.Data.clothes = new Map([ ["body oil", { name: "Body oil", - fs: "FSPhysicalIdealist", + fs: { + unlocks: "FSPhysicalIdealist", + loves: new Set(["FSPhysicalIdealist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.oil === 1; }, exposure: 4 } @@ -39,7 +58,10 @@ App.Data.clothes = new Map([ ["a chattel habit", { name: "Chattel habit", - fs: "FSChattelReligionist", + fs: { + unlocks: "FSChattelReligionist", + loves: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.habit === 1; }, exposure: 3 } @@ -47,7 +69,11 @@ App.Data.clothes = new Map([ ["conservative clothing", { name: "Conservative clothing", - fs: "FSPaternalist", + fs: { + unlocks: "FSPaternalist", + loves: new Set(["FSPaternalist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.conservative === 1; }, exposure: 0 } @@ -55,7 +81,10 @@ App.Data.clothes = new Map([ ["harem gauze", { name: "Harem gauze", - fs: "FSArabianRevivalist", + fs: { + unlocks: "FSArabianRevivalist", + loves: new Set(["FSArabianRevivalist"]), + }, get requirements() { return V.boughtItem.clothing.harem === 1; }, exposure: 1 } @@ -63,7 +92,11 @@ App.Data.clothes = new Map([ ["a huipil", { name: "Huipil", - fs: "FSAztecRevivalist", + fs: { + unlocks: "FSAztecRevivalist", + loves: new Set(["FSAztecRevivalist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.huipil === 1; }, exposure: 0 } @@ -71,7 +104,11 @@ App.Data.clothes = new Map([ ["a kimono", { name: "Kimono", - fs: "FSEdoRevivalist", + fs: { + unlocks: "FSEdoRevivalist", + loves: new Set(["FSEdoRevivalist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return (V.boughtItem.clothing.kimono === 1 || V.continent === "Japan"); }, exposure: 0 } @@ -79,7 +116,10 @@ App.Data.clothes = new Map([ ["a maternity dress", { name: "Maternity dress", - fs: "FSRepopulationFocus", + fs: { + unlocks: "FSRepopulationFocus", + loves: new Set(["FSRepopulationFocus"]), + }, get requirements() { return V.boughtItem.clothing.maternityDress === 1; }, exposure: 0, } @@ -87,7 +127,11 @@ App.Data.clothes = new Map([ ["a slutty qipao", { name: "Qipao (slutty)", - fs: "FSChineseRevivalist", + fs: { + unlocks: "FSChineseRevivalist", + loves: new Set(["FSChineseRevivalist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.qipao === 1; }, exposure: 2 } @@ -95,7 +139,10 @@ App.Data.clothes = new Map([ ["a long qipao", { name: "Qipao (long)", - fs: "FSChineseRevivalist", + fs: { + unlocks: "FSChineseRevivalist", + loves: new Set(["FSChineseRevivalist"]), + }, get requirements() { return V.boughtItem.clothing.cultural === 1; }, exposure: 0 } @@ -103,7 +150,11 @@ App.Data.clothes = new Map([ ["Imperial Plate", { name: "Imperial Plate", - fs: "FSNeoImperialist", + fs: { + unlocks: "FSNeoImperialist", + loves: new Set(["FSNeoImperialist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.imperialarmor === 1; }, exposure: 0 } @@ -111,7 +162,11 @@ App.Data.clothes = new Map([ ["a tight Imperial bodysuit", { name: "Imperial Bodysuit", - fs: "FSNeoImperialist", + fs: { + unlocks: "FSNeoImperialist", + loves: new Set(["FSNeoImperialist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.imperialsuit === 1; }, exposure: 2 } @@ -119,7 +174,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 } @@ -127,7 +182,11 @@ App.Data.clothes = new Map([ ["a toga", { name: "Toga", - fs: "FSRomanRevivalist", + fs: { + unlocks: "FSRomanRevivalist", + loves: new Set(["FSRomanRevivalist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.toga === 1; }, exposure: 1 } @@ -135,7 +194,10 @@ App.Data.clothes = new Map([ ["Western clothing", { name: "Western clothing", - fs: "FSPastoralist", + fs: { + unlocks: "FSPastoralist", + loves: new Set(["FSPastoralist"]), + }, get requirements() { return V.boughtItem.clothing.western === 1; }, exposure: 3 } @@ -143,7 +205,10 @@ App.Data.clothes = new Map([ ["a courtesan dress", { name: "Courtesan dress", - fs: "FSSlaveProfessionalism", + fs: { + unlocks: "FSSlaveProfessionalism", + loves: new Set(["FSSlaveProfessionalism"]), + }, get requirements() { return V.boughtItem.clothing.courtesan === 1; }, exposure: 1 } @@ -151,7 +216,10 @@ App.Data.clothes = new Map([ ["a bimbo outfit", { name: "Bimbo outfit", - fs: "FSIntellectualDependency", + fs: { + unlocks: "FSIntellectualDependency", + loves: new Set(["FSIntellectualDependency"]), + }, get requirements() { return V.boughtItem.clothing.bimbo === 1; }, exposure: 2 } @@ -159,7 +227,10 @@ App.Data.clothes = new Map([ ["petite admi outfit", { name: "Petite admi outfit", - fs: "FSPetiteAdmiration", + fs: { + unlocks: "FSPetiteAdmiration", + loves: new Set(["FSPetiteAdmiration"]), + }, get requirements() { return V.boughtItem.clothing.petite === 1; }, exposure: 0 } @@ -174,6 +245,9 @@ App.Data.clothes = new Map([ ["a military uniform", { name: "Military uniform", + fs: { + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.military === 1; }, exposure: 0 } @@ -230,6 +304,9 @@ App.Data.clothes = new Map([ ["a burqa", { name: "Burqa", + fs: { + loves: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.middleEastern === 1 || V.continent === "the Middle East"; }, exposure: 0 } @@ -237,6 +314,9 @@ App.Data.clothes = new Map([ ["a niqab and abaya", { name: "Niqab and abaya", + fs: { + loves: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.middleEastern === 1 || V.continent === "the Middle East"; }, exposure: 0 } @@ -244,6 +324,9 @@ App.Data.clothes = new Map([ ["a hijab and blouse", { name: "Hijab and blouse", + fs: { + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return (V.boughtItem.clothing.conservative === 1 || V.continent === "the Middle East"); }, exposure: 0 } @@ -294,12 +377,19 @@ App.Data.clothes = new Map([ { name: "Nice business attire", get requirements() { return V.boughtItem.clothing.career === 1; }, - exposure: 0 + exposure: 0, + fs: { + loves: new Set(["FSMaturityPreferentialist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, } ], ["a nice nurse outfit", { name: "Nurse (nice)", + fs: { + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.career === 1; }, exposure: 0 } @@ -315,7 +405,11 @@ App.Data.clothes = new Map([ { name: "Maid (nice)", get requirements() { return V.boughtItem.clothing.career === 1 || V.PC.career === "servant" || V.PC.career === "handmaiden" || V.PC.career === "child servant"; }, - exposure: 0 + exposure: 0, + fs: { + loves: new Set(["FSMaturityPreferentialist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, } ], ["a ball gown", @@ -492,6 +586,9 @@ App.Data.clothes = new Map([ ["a skimpy loincloth", { name: "Skimpy loincloth", + fs: { + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.underwear === 1; }, exposure: 3 } @@ -630,13 +727,15 @@ App.Data.clothes = new Map([ ["slutty jewelry", { name: "Bangles", - exposure: 3 + exposure: 3, + fs: {loves: new Set(["FSEgyptianRevivalist"])} } ], ["clubslut netting", { name: "Clubslut netting", - exposure: 3 + exposure: 3, + fs: {loves: new Set(["FSBodyPurist", "FSIntellectualDependency"])}, } ], ["cutoffs and a t-shirt", @@ -648,37 +747,47 @@ App.Data.clothes = new Map([ ["a comfortable bodysuit", { name: "Bodysuit", - exposure: 1 + exposure: 1, + fs: {loves: new Set(["FSBodyPurist"])}, } ], ["a cheerleader outfit", { name: "Cheerleader", - exposure: 2 + exposure: 2, + fs: {loves: new Set(["FSGenderFundamentalist", "FSYouthPreferentialist"])}, } ], ["a fallen nuns habit", { name: "Fallen nun", + fs: { + loves: new Set(["FSChattelReligionist"]), + }, exposure: 3 } ], ["a hijab and abaya", { name: "Hijab and abaya", + fs: { + loves: new Set(["FSChattelReligionist"]), + }, exposure: 0 } ], ["a leotard", { name: "Leotard", - exposure: 1 + exposure: 1, + fs: {loves: new Set(["FSBodyPurist"])}, } ], ["a slutty maid outfit", { name: "Maid (slutty)", - exposure: 2 + exposure: 2, + fs: {loves: new Set(["FSSlaveProfessionalism", "FSIntellectualDependency"])}, } ], ["a mini dress", @@ -721,13 +830,15 @@ App.Data.clothes = new Map([ ["a schoolgirl outfit", { name: "Schoolgirl", - exposure: 1 + exposure: 1, + fs: {loves: new Set(["FSGenderFundamentalist", "FSYouthPreferentialist"])}, } ], ["a slutty outfit", { name: "Slutty outfit", - exposure: 2 + exposure: 2, + fs: {loves: new Set(["FSIntellectualDependency"])}, } ], ["spats and a tank top", @@ -739,12 +850,16 @@ App.Data.clothes = new Map([ ["a string bikini", { name: "String bikini", - exposure: 3 + exposure: 3, + fs: {loves: new Set(["FSBodyPurist", "FSIntellectualDependency"])}, } ], ["a succubus outfit", { name: "Succubus costume", + fs: { + loves: new Set(["FSChattelReligionist"]), + }, exposure: 3 } ], @@ -752,6 +867,9 @@ App.Data.clothes = new Map([ { name: "Suit (slutty)", exposure: 2, + fs: { + loves: new Set(["FSMaturityPreferentialist", "FSSlaveProfessionalism"]) + }, } ], @@ -765,19 +883,25 @@ App.Data.clothes = new Map([ ["a halter top dress", { name: "Haltertop dress", - exposure: 0 + exposure: 0, + fs: {loves: new Set(["FSBodyPurist", "FSSlaveProfessionalism"])}, } ], ["a slave gown", { name: "Slave gown", - exposure: 0 + exposure: 0, + fs: {loves: new Set(["FSBodyPurist"])}, } ], ["chains", { name: "Chains", - fs: "FSDegradationist", + fs: { + unlocks: "FSDegradationist", + loves: new Set(["FSDegradationist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, get requirements() { return V.boughtItem.clothing.chains === 1; }, exposure: 4, harsh: true @@ -787,12 +911,19 @@ App.Data.clothes = new Map([ { name: "Go naked", exposure: 4, - harsh: true + harsh: true, + fs: { + loves: new Set(["FSPhysicalIdealist", "FSIntellectualDependency"]), + tolerates: new Set(["FSChattelReligionist"]), + }, } ], ["a penitent nuns habit", { name: "Penitent nun", + fs: { + loves: new Set(["FSChattelReligionist"]), + }, exposure: 0, harsh: true } @@ -801,28 +932,37 @@ App.Data.clothes = new Map([ { name: "Restrictive latex", exposure: 3, - harsh: true + harsh: true, + fs: {loves: new Set(["FSBodyPurist"])}, } ], ["shibari ropes", { name: "Shibari ropes", exposure: 4, - harsh: true + harsh: true, + fs: { + loves: new Set(["FSDegradationist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, } ], ["uncomfortable straps", { name: "Uncomfortable straps", exposure: 3, - harsh: true + harsh: true, + fs: { + loves: new Set(["FSDegradationist"]), + tolerates: new Set(["FSChattelReligionist"]), + }, } ] ]); /** * @typedef {object} slaveWear * @property {string} name - * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS. + * @property {itemFS} [fs] * @property {boolean} [requirements] * @property {boolean} [harsh] */ @@ -860,7 +1000,10 @@ App.Data.slaveWear = { ["bowtie", { name: "Bowtie collar", - fs: "FSGenderFundamentalist", + fs: { + unlocks: "FSGenderFundamentalist", + loves: new Set(["FSGenderFundamentalist"]), + }, get requirements() { return V.boughtItem.clothing.bunny === 1; } @@ -869,7 +1012,10 @@ App.Data.slaveWear = { ["neck tie", { name: "Neck tie", - fs: "FSPaternalist", + fs: { + unlocks: "FSPaternalist", + loves: new Set(["FSPaternalist"]), + }, get requirements() { return V.boughtItem.clothing.conservative === 1; } @@ -878,7 +1024,10 @@ App.Data.slaveWear = { ["ancient Egyptian", { name: "Ancient Egyptian", - fs: "FSEgyptianRevivalist", + fs: { + unlocks: "FSEgyptianRevivalist", + loves: new Set(["FSEgyptianRevivalist"]), + }, get requirements() { return V.boughtItem.clothing.egypt === 1; } @@ -887,12 +1036,18 @@ App.Data.slaveWear = { ["tight steel", { name: "Tight steel", + fs: { + loves: new Set(["FSChattelReligionist"]) + }, harsh: true } ], ["cruel retirement counter", { name: "Cruel retirement counter", + fs: { + loves: new Set(["FSChattelReligionist"]) + }, get requirements() { return V.seeAge === 1; }, @@ -902,6 +1057,9 @@ App.Data.slaveWear = { ["uncomfortable leather", { name: "Uncomfortable leather", + fs: { + loves: new Set(["FSChattelReligionist"]) + }, harsh: true } ], @@ -948,7 +1106,10 @@ App.Data.slaveWear = { ["a small empathy belly", { name: "1st Trimester belly", - fs: "FSRepopulationFocus", + fs: { + unlocks: "FSRepopulationFocus", + loves: new Set(["FSRepopulationFocus"]) + }, get requirements() { return V.boughtItem.clothing.belly === 1; } @@ -957,7 +1118,10 @@ App.Data.slaveWear = { ["a medium empathy belly", { name: "2nd Trimester belly", - fs: "FSRepopulationFocus", + fs: { + unlocks: "FSRepopulationFocus", + loves: new Set(["FSRepopulationFocus"]) + }, get requirements() { return V.boughtItem.clothing.belly === 1; } @@ -966,7 +1130,10 @@ App.Data.slaveWear = { ["a large empathy belly", { name: "3rd Trimester belly", - fs: "FSRepopulationFocus", + fs: { + unlocks: "FSRepopulationFocus", + loves: new Set(["FSRepopulationFocus"]) + }, get requirements() { return V.boughtItem.clothing.belly === 1; } @@ -975,7 +1142,10 @@ App.Data.slaveWear = { ["a huge empathy belly", { name: "3rd Trimester twins belly", - fs: "FSRepopulationFocus", + fs: { + unlocks: "FSRepopulationFocus", + loves: new Set(["FSRepopulationFocus"]) + }, get requirements() { return V.boughtItem.clothing.belly === 1; } @@ -1055,7 +1225,7 @@ App.Data.slaveWear = { /** * @typedef {object} slaveShoes * @property {string} name - * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS. + * @property {itemFS} [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 @@ -1111,7 +1281,10 @@ App.Data.shoes = new Map([ // TODO: add lift property ["platform shoes", { name: "Platforms", - fs: "FSStatuesqueGlorification", + fs: { + unlocks: "FSStatuesqueGlorification", + loves: new Set(["FSStatuesqueGlorification"]) + }, get requirements() { return (V.boughtItem.shoes.heels === 1); }, @@ -1122,7 +1295,10 @@ App.Data.shoes = new Map([ // TODO: add lift property ["platform heels", { name: "Platform heels", - fs: "FSStatuesqueGlorification", + fs: { + unlocks: "FSStatuesqueGlorification", + loves: new Set(["FSStatuesqueGlorification"]) + }, get requirements() { return (V.boughtItem.shoes.heels === 1); }, @@ -1133,7 +1309,10 @@ App.Data.shoes = new Map([ // TODO: add lift property ["extreme platform heels", { name: "Painfully extreme platform heels", - fs: "FSStatuesqueGlorification", + fs: { + unlocks: "FSStatuesqueGlorification", + loves: new Set(["FSStatuesqueGlorification"]) + }, get requirements() { return (V.boughtItem.shoes.heels === 1); }, @@ -1146,7 +1325,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] * @property {boolean} [requirements] * @property {0|1|2|3} width * @property {0|1|2} length @@ -1218,7 +1397,7 @@ App.Data.buttplug = new Map([ /** * @typedef {object} vaginalAccessories * @property {string} name - * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS. + * @property {itemFS} [fs] * @property {boolean} [requirements] * @property {0|1|2|3} width * @property {0|1|2} length @@ -1314,7 +1493,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>} */ @@ -1411,7 +1590,7 @@ App.Data.chastity = new Map([ ["choose own chastity", { name: "Choose own chastity", - fs: "FSRestart", + fs: {unlocks: "FSRestart"}, updateSlave: { choosesOwnChastity: 1 }, @@ -1420,7 +1599,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/endWeek/saChoosesOwnClothes.js b/src/endWeek/saChoosesOwnClothes.js index 592f0142ad90bbb87905326e5c9f92afd589eec2..f543bbbefb4971072caf3589a42d781aa179a59d 100644 --- a/src/endWeek/saChoosesOwnClothes.js +++ b/src/endWeek/saChoosesOwnClothes.js @@ -91,7 +91,6 @@ App.SlaveAssignment.choosesOwnClothes = (function() { */ function todaysOutfit(slave) { const clothing = []; - let chosenClothing; const wardrobeAssignment = []; const wardrobeFS = []; const wardrobeTastes = []; @@ -101,105 +100,80 @@ App.SlaveAssignment.choosesOwnClothes = (function() { if (V.arcologies[0].FSChattelReligionist > 0) { selection = {text: `${he} commonly sees others wearing chattel habits and is drawn to doing so ${himself}.`, clothes: "a chattel habit"}; } else { - clothing.push("panties"); - if (V.arcologies[0].FSEgyptianRevivalist > 0) { - clothing.push("egyptian"); - } else if (V.arcologies[0].FSRomanRevivalist > 0) { - clothing.push("roman"); - } else if (V.arcologies[0].FSAztecRevivalist > 0) { - clothing.push("aztec"); - } else if (V.arcologies[0].FSEdoRevivalist > 0) { - clothing.push("edo"); - } else if (V.arcologies[0].FSArabianRevivalist > 0) { - clothing.push("arabic"); - } else if (V.arcologies[0].FSChineseRevivalist > 0) { - clothing.push("chinese"); - } - if (V.arcologies[0].FSGenderFundamentalist > 0) { - clothing.push("genderFund"); - } - if (V.arcologies[0].FSPaternalist > 0) { - clothing.push("paternalist"); - } else if (V.arcologies[0].FSDegradationist > 0) { - clothing.push("degradationist"); - } - if (V.arcologies[0].FSMaturityPreferentialist > 0) { - clothing.push("mature"); - } else if (V.arcologies[0].FSYouthPreferentialist > 0) { - clothing.push("youth"); - } - if (V.arcologies[0].FSPhysicalIdealist > 0) { - clothing.push("physicalIdealist"); - } - if (V.arcologies[0].FSPastoralist > 0) { - clothing.push("pastoralist"); - } - if (V.arcologies[0].FSBodyPurist > 0) { - clothing.push("bodyPurist"); - } - if (V.arcologies[0].FSSlaveProfessionalism > 0) { - clothing.push("professional"); - } else if (V.arcologies[0].FSIntellectualDependency > 0) { - clothing.push("bimbo"); + /** @type {Array<FC.FutureSociety>} */ + const clothingFS = []; + clothingFS.push("panties"); + for (const FS of App.Data.FutureSociety.fsNames) { + if (V.arcologies[0][FS] > 0) { + clothingFS.push(FS); + } } - chosenClothing = jsEither(clothing); + /** @type {FC.FutureSociety} */ + const chosenClothing = jsEither(clothingFS); switch (chosenClothing) { - case "egyptian": - selection = {text: `${he} commonly sees others wearing nothing but jewelry and is drawn to doing so ${himself}.`, clothes: "slutty jewelry"}; + case "FSEgyptianRevivalist": + selection = {text: `${he} commonly sees others wearing nothing but jewelry and is drawn to doing so ${himself}.`}; break; - case "roman": - selection = {text: `${he} commonly sees others wearing togas and is drawn to doing so ${himself}.`, clothes: "a toga"}; + case "FSRomanRevivalist": + selection = {text: `${he} commonly sees others wearing togas and is drawn to doing so ${himself}.`}; break; - case "aztec": - selection = {text: `${he} commonly sees others wearing huipils and is drawn to doing so ${himself}.`, clothes: "a huipil"}; + case "FSAztecRevivalist": + selection = {text: `${he} commonly sees others wearing huipils and is drawn to doing so ${himself}.`}; break; - case "edo": - selection = {text: `${he} commonly sees others wearing kimonos and is drawn to doing so ${himself}.`, clothes: "a kimono"}; + case "FSEdoRevivalist": + selection = {text: `${he} commonly sees others wearing kimonos and is drawn to doing so ${himself}.`}; break; - case "arabic": - selection = {text: `${he} commonly sees others wearing silk and is drawn to doing so ${himself}.`, clothes: "harem gauze"}; + case "FSArabianRevivalist": + selection = {text: `${he} commonly sees others wearing silk and is drawn to doing so ${himself}.`}; break; - case "chinese": - selection = {text: `${he} commonly sees others wearing qipaos and is drawn to doing so ${himself}.`, clothes: "a slutty qipao"}; + case "FSChineseRevivalist": + selection = {text: `${he} commonly sees others wearing qipaos and is drawn to doing so ${himself}.`}; break; - case "genderFund": - if (jsRandom(1, 2) === 1) { - selection = {text: `${he} commonly sees cheerleaders around and instinctively follows along.`, clothes: jsEither(["a cheerleader outfit", "a schoolgirl outfit"])}; - } else { - selection = {text: `${he} commonly sees bunnies around and instinctively follows along.`, clothes: "a bunny outfit"}; - } + case "FSGenderFundamentalist": + selection = {text: `${he} commonly sees cheerleaders and bunnies around and instinctively follows along.`}; break; - case "paternalist": - selection = {text: `${he} commonly sees others wearing normal clothing and is drawn to doing so ${himself}.`, clothes: "conservative clothing"}; + case "FSPaternalist": + selection = {text: `${he} commonly sees others wearing normal clothingFS and is drawn to doing so ${himself}.`}; break; - case "degradationist": - selection = {text: `${he} commonly sees others wearing chains and is drawn to doing so ${himself}.`, clothes: jsEither(["chains", "shibari ropes", "uncomfortable straps"])}; + case "FSDegradationist": + selection = {text: `${he} commonly sees others wearing chains and is drawn to doing so ${himself}.`}; break; - case "mature": - selection = {text: `${he} commonly sees others wearing suits and is drawn to doing so ${himself}.`, clothes: jsEither(["a nice maid outfit", "nice business attire", "slutty business attire"])}; + case "FSMaturityPreferentialist": + selection = {text: `${he} commonly sees others wearing suits and is drawn to doing so ${himself}.`}; break; - case "youth": - selection = {text: `${he} commonly sees schoolgirls around and instinctively follows along.`, clothes: jsEither(["a cheerleader outfit", "a schoolgirl outfit"])}; + case "FSYouthPreferentialist": + selection = {text: `${he} commonly sees schoolgirls around and instinctively follows along.`}; break; - case "physicalIdealist": - selection = {text: `${he} commonly sees naked girls around and seldom realizes they are coated in oil.`, clothes: jsEither(["body oil", "no clothing", "no clothing"])}; + case "FSPhysicalIdealist": + selection = {text: `${he} commonly sees naked girls around and seldom realizes they are coated in oil.`}; break; - case "pastoralist": - selection = {text: `${he} commonly sees cowgirls around and instinctively follows along.`, clothes: "Western clothing"}; + case "FSPastoralist": + selection = {text: `${he} commonly sees cowgirls around and instinctively follows along.`}; break; - case "bodyPurist": - selection = {text: `${he} commonly sees others wearing tight, form-fitting clothes and is drawn to doing so ${himself}.`, clothes: jsEither(["a comfortable bodysuit", "a halter top dress", "a leotard", "a leotard", "a slave gown", "a string bikini", "clubslut netting", "restrictive latex"])}; + case "FSBodyPurist": + selection = {text: `${he} commonly sees others wearing tight, form-fitting clothes and is drawn to doing so ${himself}.`}; break; - case "professional": - selection = {text: `${he} commonly sees others wearing complicated clothing and is drawn to doing so ${himself}.`, clothes: jsEither(["a slutty maid outfit", "slutty business attire", "a halter top dress", "a courtesan dress"])}; + case "FSSlaveProfessionalism": + selection = {text: `${he} commonly sees others wearing complicated clothingFS and is drawn to doing so ${himself}.`}; break; - case "bimbo": - selection = {text: `${he} commonly sees others showing skin is drawn to doing so ${himself}.`, clothes: jsEither(["a bimbo outfit", "a slutty outfit", "a string bikini", "attractive lingerie", "clubslut netting", "slutty jewelry", "no clothing"])}; + case "FSIntellectualDependency": + selection = {text: `${he} commonly sees others showing skin is drawn to doing so ${himself}.`}; break; default: - selection = {text: `${he} chooses to put on underwear, the reasons lost to ${him}, and moves on.`, clothes: jsEither(["attractive lingerie", "panties"])}; + selection = {text: `${he} chooses to put on underwear, the reasons lost to ${him}, and moves on.`}; break; } + if (chosenClothing === "panties") { + selection.clothes = jsEither(["attractive lingerie", "panties"]); + } else { + selection.clothes = jsEither(clothingLovedByAnFS(chosenClothing)); + if (!selection.clothes) { + selection = { + text: `${he} chooses to put on underwear, as it seems you don't have any clothing available for ${App.Data.FutureSociety.records[chosenClothing].noun}.`, + clothes: jsEither(["attractive lingerie", "panties"]) + }; + } + } } } else if (slave.devotion <= 20) { clothing.push({text: `${He} uses the ability to select outfits to cover up with comfortable cutoffs and a t-shirt.`, clothes: "cutoffs and a t-shirt"}); diff --git a/src/endWeek/saRecruitGirls.js b/src/endWeek/saRecruitGirls.js index c93602efdfc5e9cbfc3f0a9fc72358a2a4569b74..5dd158c0dcb84eaeb06bd3ae542d2b3c16a50403 100644 --- a/src/endWeek/saRecruitGirls.js +++ b/src/endWeek/saRecruitGirls.js @@ -1469,9 +1469,10 @@ App.SlaveAssignment.recruitGirls = (function() { FSdefend++; } } + const clothes = App.Data.clothes.get(slave.clothes); if (arcology.FSChattelReligionist !== "unset") { if (slaveInt > 15 && (slave.devotion > 95 || slave.trust > 95)) { - if (slave.clothes === "a chattel habit" || slave.clothes === "a fallen nuns habit" || slave.clothes === "a penitent nuns habit" || slave.clothes === "a hijab and abaya") { + if (clothes.fs && clothes.fs.loves && clothes.fs.loves.has("FSChattelReligionist")) { pushFS(`Clad in ${his} holy garb, ${slave.slaveName} preaches to the atrium with a powerful appeal to the new morality, in which ${his} absolute faith in your revelations is unmistakable.`); seed += 1; } else if (arcology.FSNeoImperialist !== "unset" && slave.clothes === "a tight Imperial bodysuit") { @@ -1506,7 +1507,7 @@ App.SlaveAssignment.recruitGirls = (function() { seed += ((slave.skill.entertainment / 30) * arcology.FSNull / 10); } if (arcology.FSRomanRevivalist !== "unset") { - if (slave.clothes === "a toga") { + if ((clothes.fs && clothes.fs.loves && clothes.fs.loves.has("FSRomanRevivalist"))) { if (slave.face > 10 && slave.counter.pitKills > 0) { pushFS(`${He} thrills audiences by recounting tales of ${his} exploits as a beautiful and deadly gladiatrix-<span style="italic">slash</span>-love-slave for the First Citizen of the Eternal City reborn.`); // protip: it doesn't have to be YOUR pit diff --git a/src/endWeek/saSocialEffects.js b/src/endWeek/saSocialEffects.js index 7d88d05484f749356cb2592bbdcf990b148403c6..fb3e0e7cc1ba2a08424f36305402eae007a1af3b 100644 --- a/src/endWeek/saSocialEffects.js +++ b/src/endWeek/saSocialEffects.js @@ -816,14 +816,17 @@ App.SlaveAssignment.saSocialEffects = function(slave) { } if (V.arcologies[0].FSChattelReligionist !== "unset") { - if (["cruel retirement counter", "tight steel", "uncomfortable leather"].includes(slave.collar)) { + const collar = App.Data.slaveWear.collar.get(slave.collar); + if (collar.fs && collar.fs.loves && collar.fs.loves.has("FSChattelReligionist")) { t.push(new SocialEffect("Chattel Religionist", 1, `Punishing collar`, `Society <span class="green">approves</span> of ${slave.slaveName}'s collar as an expression of the old ideal of mortification of the flesh, advancing the combination of religious originalism and modern slavery.`)); } - if (["a burqa", "a chattel habit", "a fallen nuns habit", "a hijab and abaya", "a niqab and abaya", "a penitent nuns habit", "a succubus outfit"].includes(slave.clothes)) { + const clothes = App.Data.clothes.get(slave.clothes); + + if (clothes.fs && clothes.fs.loves && clothes.fs.loves.has("FSChattelReligionist")) { t.push(new SocialEffect("Chattel Religionist", 1, `Religious clothing`, `Society <span class="green">approves</span> of ${his} religiously themed clothing, strengthening the connection between sexual servitude and faith.`)); - } else if (["a bunny outfit", "a hijab and blouse", "a huipil", "a kimono", "a military uniform", "a nice maid outfit", "a nice nurse outfit", "a skimpy loincloth", "a slutty qipao", "a toga", "Imperial Plate", "a tight Imperial bodysuit", "body oil", "chains", "conservative clothing", "nice business attire", "no clothing", "shibari ropes", "uncomfortable straps"].includes(slave.clothes)) { + } else if (clothes.fs && clothes.fs.tolerates && clothes.fs.tolerates.has("FSChattelReligionist")) { t.push(new SocialEffect("Chattel Religionist", 0, `Spartan clothing`, `Society accepts ${his} spartan clothing, seeing it as permissible under the new religious mores.`)); } else if (slave.fuckdoll === 0) { diff --git a/src/interaction/siWardrobe.js b/src/interaction/siWardrobe.js index 6d72f7debae4cd83bfd2f0754b8018d06c59c557..17ab18418f72d72efd052fec5ff59b55e31c2560 100644 --- a/src/interaction/siWardrobe.js +++ b/src/interaction/siWardrobe.js @@ -86,6 +86,29 @@ App.UI.SlaveInteract.wardrobe = function(slave) { } el.append(span); + + const FSFilters = new Map([]); + for (const FS of App.Data.FutureSociety.fsNames) { + if (V.arcologies[0][FS] > 0) { + FSFilters.set(FS, App.Data.FutureSociety.records[FS].noun); + } + } + span = document.createElement("span"); + span.classList.add("button-group"); + for (const [num, string] of FSFilters) { + const button = App.UI.DOM.makeElement("button", string); + if (filters.FSLoves === num) { + button.classList.add("selected", "disabled"); + } else { + button.onclick = () => { + filters.FSLoves = num; + refresh(); + }; + } + span.append(button); + } + el.append(span); + // clear filters const resetButton = App.UI.DOM.makeElement("button", "Reset Filters"); resetButton.onclick = () => { @@ -158,12 +181,17 @@ App.UI.SlaveInteract.wardrobe = function(slave) { if (filters.hasOwnProperty("harsh") && ((filters.harsh === false && object.harsh) || (filters.harsh === true && !object.harsh))) { continue; } + if (filters.hasOwnProperty("FSLoves") && !(object.fs && object.fs.loves && object.fs.loves.has(filters.FSLoves))) { + continue; + } 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 +221,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 +265,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 +321,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 +398,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 +472,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 +542,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 +566,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 +608,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 +658,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 +712,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 +758,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 +835,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); @@ -855,38 +907,63 @@ App.UI.SlaveInteract.wardrobe = function(slave) { * Also accepting is a bit weird for ones above, I think I've seen obedient being used instead. */ function clothTooltip(cloth) { - let Cloth = capFirstChar(cloth); - let desc; - + if (cloth === "none") { + return "No effect one way or another."; + } + let desc = []; + const clothingData = App.Data.clothes.get(cloth); + if (clothingData) { + switch (clothingData.exposure) { + case 4: + desc.push("Might as well be naked."); + break; + case 3: + desc.push("Humiliating."); + break; + case 2: + desc.push("Slutty."); + break; + case 1: + desc.push("Normal."); + break; + case 0: + desc.push("Modest."); + break; + default: + if (!clothingData.harsh) { + desc.push("Only nice (meaning non-obedients lose devotion and fear while obedients gain devotion and trust)"); + } + } + } switch (cloth) { /* nice clothes without specific effects(besides FS or being slutty/humiliating/modest) are handled at the end */ case "choosing her own clothes": case "choosing his own clothes": - desc = "Increases or greatly reduces devotion based on whether the slave is obedient(devotion at accepting or higher)."; + desc.push("Increases or greatly reduces devotion based on whether the slave is obedient(devotion at accepting or higher)."); break; case "no clothing": - desc = "Increases devotion for resistant humiliations fetishists and nymphos."; + desc.push("Increases devotion for resistant humiliations fetishists and nymphos."); break; case "a penitent nuns habit": - desc = "Increases devotion and fear but damages health, may cause masochism."; + desc.push("Increases devotion and fear but damages health, may cause masochism."); break; case "restrictive latex": - desc = "Increases fear and devotion for resistant slaves and just devotion for obedient, non-terrified submissives."; + desc.push("Increases fear and devotion for resistant slaves and just devotion for obedient, non-terrified submissives."); break; case "shibari ropes": - desc = "Increases fear and devotion for resistant slaves and just devotion for obedient, non-terrified submissives."; + desc.push("Increases fear and devotion for resistant slaves and just devotion for obedient, non-terrified submissives."); break; case "uncomfortable straps": - desc = "Increases devotion and fear for slaves who are disobedient and not terrified. Masochists who are at least ambivalent gain devotion, may also cause masochism."; + desc.push("Increases devotion and fear for slaves who are disobedient and not terrified. Masochists who are at least ambivalent gain devotion, may also cause masochism."); break; case "chains": - desc = "Increases devotion and fear for slaves who are disobedient and not terrified. Masochists who are at least ambivalent gain devotion, may also cause masochism."; + desc.push("Increases devotion and fear for slaves who are disobedient and not terrified. Masochists who are at least ambivalent gain devotion, may also cause masochism."); break; case "an apron": - desc = "Increases just devotion for submissives, humiliation fetishists and visibly pregnant pregnancy fetishists regardless of devotion level."; + desc.push("Increases just devotion for submissives, humiliation fetishists and visibly pregnant pregnancy fetishists regardless of devotion level."); break; case "a monokini": - desc = "Boob fetishists enjoy."; + desc.push("Boob fetishists enjoy."); break; case "heavy gold": case "ancient Egyptian": @@ -897,184 +974,170 @@ App.UI.SlaveInteract.wardrobe = function(slave) { case "satin choker": case "silk ribbon": case "stylish leather": - desc = "On obedient slaves reduces fear, on non-obedient ones reduces fear a lot and devotion somewhat."; + desc.push("On obedient slaves reduces fear, on non-obedient ones reduces fear a lot and devotion somewhat."); break; case "preg biometrics": - desc = "Increases devotion for those who have pregnancy fetish while fertile or a humiliation fetish. For others obedient ones gain devotion, ambivalent ones gain fear and devotion and resistant ones lose devotion and gain fear."; + desc.push("Increases devotion for those who have pregnancy fetish while fertile or a humiliation fetish. For others obedient ones gain devotion, ambivalent ones gain fear and devotion and resistant ones lose devotion and gain fear."); break; case "bell collar": - desc = "On non-obedient slaves reduces fear a lot and devotion somewhat."; + desc.push("On non-obedient slaves reduces fear a lot and devotion somewhat."); break; case "leather with cowbell": - desc = "On obedient slaves with boob fetish increases devotion, on disobedient slaves reduces fear a lot and devotion somewhat."; + desc.push("On obedient slaves with boob fetish increases devotion, on disobedient slaves reduces fear a lot and devotion somewhat."); break; case "tight steel": case "uncomfortable leather": case "neck corset": case "cruel retirement counter": - desc = "Increases fear for non-obedient slaves."; + desc.push("Increases fear for non-obedient slaves."); break; case "shock punishment": - desc = "For non-obedient slaves increases fear a great deal and reduces devotion, for resistant non-odd slaves it affects both much more a single time and gives the odd flaw."; + desc.push("For non-obedient slaves increases fear a great deal and reduces devotion, for resistant non-odd slaves it affects both much more a single time and gives the odd flaw."); break; case "cat ears": - desc = "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."; + desc.push("Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."); break; case "porcelain mask": - desc = "Obscures the face, increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."; + desc.push("Obscures the face, increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."); break; case "ball gag": case "bit gag": case "ring gag": - desc = "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."; + desc.push("Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."); break; case "dildo gag": case "massive dildo gag": - desc = "Increases oral skill up to a point and causes fear for disobedient slaves."; + desc.push("Increases oral skill up to a point and causes fear for disobedient slaves."); break; case "hand gloves": case "elbow gloves": - desc = "Have no effect one way or another."; + desc.push("Have no effect one way or another."); break; case "flats": - desc = "Have no effect one way or another."; + desc.push("Have no effect one way or another."); break; case "heels": case "boots": case "platform heels": - desc = "Increases height, resistant slaves with natural legs resent wearing them."; + desc.push("Increases height, resistant slaves with natural legs resent wearing them."); break; case "pumps": case "platform shoes": - desc = "Increases height."; + desc.push("Increases height."); break; case "extreme heels": case "extreme platform heels": - desc = "Increases height, slaves with natural legs who are resistant resent and fear wearing them while non-resistant ones become more fearful(unless masochistic) and obedient."; + desc.push("Increases height, slaves with natural legs who are resistant resent and fear wearing them while non-resistant ones become more fearful(unless masochistic) and obedient."); break; case "short stockings": case "long stockings": - desc = "Have no effect one way or another."; + desc.push("Have no effect one way or another."); break; case "a tight corset": - desc = "Slowly narrows the waist into wispy one."; + desc.push("Slowly narrows the waist into wispy one."); break; case "an extreme corset": - desc = "Narrows the waist up to absurd level, painfully, if waist is feminine or wider(scaring and increasing obedience on resistant slaves), but risks miscarriage if a pregnant belly becomes too big"; + desc.push("Narrows the waist up to absurd level, painfully, if waist is feminine or wider(scaring and increasing obedience on resistant slaves), but risks miscarriage if a pregnant belly becomes too big"); break; case "a supportive band": - desc = "Reduces chance of miscarriage."; + desc.push("Reduces chance of miscarriage."); break; case "a small empathy belly": case "a medium empathy belly": case "a large empathy belly": case "a huge empathy belly": - desc = "Strengthens or removes(a weak) pregnancy fetish and affects devotion in various ways depending on devotion, fertility and having a pregnancy fetish or breeder flaw."; + desc.push("Strengthens or removes(a weak) pregnancy fetish and affects devotion in various ways depending on devotion, fertility and having a pregnancy fetish or breeder flaw."); break; case "bullet vibrator": - desc = "Increases devotion but weakens fetish and libido."; + desc.push("Increases devotion but weakens fetish and libido."); break; case "smart bullet vibrator": - desc = "Increases devotion and affects a specific fetish, attraction or sex drive."; + desc.push("Increases devotion and affects a specific fetish, attraction or sex drive."); break; case "dildo": - desc = "Stretches vagina from virgin to tight, might remove hatred of penetration."; + desc.push("Stretches vagina from virgin to tight, might remove hatred of penetration."); break; case "long dildo": - desc = "Stretches vagina from virgin to tight, might remove hatred of penetration. Makes size queens happy while others less trusting."; + desc.push("Stretches vagina from virgin to tight, might remove hatred of penetration. Makes size queens happy while others less trusting."); break; case "large dildo": case "long, large dildo": - desc = "Stretches vagina into a loose one, on a tight vagina increases obedience and fear."; + desc.push("Stretches vagina into a loose one, on a tight vagina increases obedience and fear."); break; case "huge dildo": case "long, huge dildo": - desc = "Stretches vagina into a cavernous one, on smaller vaginas size queens get much more devoted, masochists and submissives much more devoted and fearful and anyone else becomes much less devoted and trusting. Might cause miscarriage."; + desc.push("Stretches vagina into a cavernous one, on smaller vaginas size queens get much more devoted, masochists and submissives much more devoted and fearful and anyone else becomes much less devoted and trusting. Might cause miscarriage."); break; case "vibrator": case "smart vibrator": - desc = ""; + desc.push(""); break; case "plug": - desc = "Stretches butthole from virgin to tight, might remove hatred of anal."; + desc.push("Stretches butthole from virgin to tight, might remove hatred of anal."); break; case "long plug": - desc = "Stretches vagina from virgin to tight, might remove hatred of penetration. Makes size queens happy."; + desc.push("Stretches vagina from virgin to tight, might remove hatred of penetration. Makes size queens happy."); break; case "large plug": case "long, large plug": - desc = "Stretches vagina into a loose one, on a tight vagina increases obedience and fear."; + desc.push("Stretches vagina into a loose one, on a tight vagina increases obedience and fear."); break; case "huge plug": case "long, huge plug": - desc = "Stretches vagina into a cavernous one, on smaller vaginas size queens get much more devoted, masochists and submissives much more devoted and fearful and anyone else becomes much less devoted and trusting. Might cause miscarriage."; + desc.push("Stretches vagina into a cavernous one, on smaller vaginas size queens get much more devoted, masochists and submissives much more devoted and fearful and anyone else becomes much less devoted and trusting. Might cause miscarriage."); break; case "tail": case "fox tail": case "cat tail": case "cow tail": - desc = "Makes it more scary to wear a plug but might give humiliation fetish,"; + desc.push("Makes it more scary to wear a plug but might give humiliation fetish,"); break; case "anal chastity": - desc = "Prevents losing anal virginity."; + desc.push("Prevents losing anal virginity."); break; case "chastity belt": - desc = "Prevents losing virginity, has various effects, obedient virgins, buttsluts and ones with relatively high sex drive are most affected."; + desc.push("Prevents losing virginity, has various effects, obedient virgins, buttsluts and ones with relatively high sex drive are most affected."); break; case "combined chastity belt": - desc = "Prevents losing virginities, has various effects, obedient virgins, buttsluts and ones with relatively high sex drive are most affected."; + desc.push("Prevents losing virginities, has various effects, obedient virgins, buttsluts and ones with relatively high sex drive are most affected."); break; case "chastity cage": - desc = "Prevents using penis, has various effects, devotion, trust and sex drive of unresistant slaves with healthy sex drive all suffer from wearing one unless they're a masochist, nympho, neglectful, buttslut, sterile or lack balls."; + desc.push("Prevents using penis, has various effects, devotion, trust and sex drive of unresistant slaves with healthy sex drive all suffer from wearing one unless they're a masochist, nympho, neglectful, buttslut, sterile or lack balls."); break; case "combined chastity cage": - desc = "Protects both penis and anus from sex, has various effects, devotion and trust and sex drive of unresistant slaves with healthy sex drive all suffer from wearing one unless they're a masochist, nympho, neglectful, buttslut, sterile or lack balls."; + desc.push("Protects both penis and anus from sex, has various effects, devotion and trust and sex drive of unresistant slaves with healthy sex drive all suffer from wearing one unless they're a masochist, nympho, neglectful, buttslut, sterile or lack balls."); break; case "genital chastity": - desc = "Protects both penis and vagina from sex, has various effects."; + desc.push("Protects both penis and vagina from sex, has various effects."); break; case "full chastity": - desc = "Protects penis, vagina and anus, has various effects."; - break; - case "choosing her own chastity": - case "choosing his own chastity": - case "choose own chastity": - case "revoke choosing own chastity": - desc = ""; + desc.push("Protects penis, vagina and anus, has various effects."); break; } - if (cloth === "none") { - return "No effect one way or another."; - } else { - const clothingData = App.Data.clothes.get(cloth); - if (clothingData) { - switch (clothingData.exposure) { - case 4: - Cloth += ", might as well be naked"; - break; - case 3: - Cloth += ", it's humiliating"; - break; - case 2: - Cloth += ", it's slutty"; - break; - case 1: - Cloth += ", it's normal"; - break; - case 0: - Cloth += ", it's modest"; - break; - default: - if (!clothingData.harsh) { - Cloth += ", it's only nice (meaning non-obedients lose devotion and fear while obedients gain devotion and trust)"; + if (clothingData) { + if (clothingData.fs) { + const reactions = new Map([ + ["loves", "like"], + ["tolerates", "tolerate"], + ["hates", "hate"], + ]); + for (const [key, value] of reactions) { + if (clothingData.fs[key]) { + const lovers = []; + for (const FS of clothingData.fs[key]) { + lovers.push(App.Data.FutureSociety.records[FS].noun); + } + if (lovers.length > 0) { + desc.push(`${arrayToSentence(lovers)} will ${value} this look.`); // TODO: Please move tooltip to array when that becomes possible } + } } } - return Cloth + ". " + (desc || ""); } + return desc.join(" "); } - /** @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 88c30da783e1db0cffa0fa171930d404468a8773..30db1b41bb2de334068479900a4c8a21d6e5bdd3 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 && 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; } } @@ -310,3 +310,18 @@ globalThis.limbToProsthetic = function(limb) { return ""; } }; + +/** + * + * @param {FC.FutureSociety} FS + * @returns {Array} + */ +globalThis.clothingLovedByAnFS = function(FS) { + const clothingOptions = []; + for (const [key, value] of App.Data.clothes) { + if (value.fs && value.fs.loves && value.fs.loves.has(FS)) { + clothingOptions.push(key); + } + } + return clothingOptions; +}; diff --git a/src/npc/startingGirls/startingGirls.js b/src/npc/startingGirls/startingGirls.js index 68a7b5c4a16e33fd562169d777b805234d83f896..e4ed9091a95702c5a82330846b5fb420efbc5079 100644 --- a/src/npc/startingGirls/startingGirls.js +++ b/src/npc/startingGirls/startingGirls.js @@ -788,8 +788,20 @@ App.StartingGirls.physical = function(slave) { options.addOption("Butt", "butt", slave) .addValueList([["Flat", 0], ["Small", 1], ["Plump", 2], ["Big", 3], ["Huge", 4], ["Enormous", 5], ["Gigantic", 6], ["Massive", 7]]); + const oldAnus = slave.anus; options.addOption("Anus", "anus", slave) - .addValueList([["Virgin", 0], ["Normal", 1], ["Veteran", 2], ["Gaping", 3]]); + .addValue("Virgin", 0, () => { + slave.analArea = 1; + }) + .addValue("Normal", 1, () => { + slave.analArea = Math.clamp(slave.analArea + (1 - oldAnus), 1, 3); + }) + .addValue("Veteran", 2, () => { + slave.analArea = Math.clamp(slave.analArea + (2 - oldAnus), 2, 4); + }) + .addValue("Gaping", 3, () => { + slave.analArea = Math.clamp(slave.analArea + (3 - oldAnus), 3, 5); + }); if (slave.anus > 0) { let comment; @@ -800,11 +812,11 @@ App.StartingGirls.physical = function(slave) { } else { comment = "Very broad."; } - options.addOption("External anus appearance", "anus", slave) + options.addOption("External anus appearance", "analArea", slave) .addValueList([ - ["Recently stretched", slave.analArea = slave.anus], - ["Used to current size", slave.analArea = slave.anus+1], - ["Very broad", slave.analArea = slave.anus+2], + ["Recently stretched", slave.anus], + ["Used to current size", slave.anus + 1], + ["Very broad", slave.anus + 2], ]).addComment(comment); }