diff --git a/devTools/types/SugarCubeExtensions.d.ts b/devTools/types/SugarCubeExtensions.d.ts index 52eaed4fd5f7094d7ace8765ef0f122992e8e563..e8709b836aec7898ad34082c2a5df7c74d817d19 100644 --- a/devTools/types/SugarCubeExtensions.d.ts +++ b/devTools/types/SugarCubeExtensions.d.ts @@ -26,9 +26,6 @@ declare module "twine-sugarcube" { filterRegions: string[]; heightBoostingShoes: string[]; highHeels: string[]; - humiliatingClothes: string[]; - modestClothes: string[]; - sluttyClothes: string[]; pregData: Record<string, FC.PregnancyData>; diff --git a/js/003-data/miscData.js b/js/003-data/miscData.js index 11a4116e3d8df59fa7a7444e0e59b9a122549610..a79da32e166af927ed42553ce4657dad7e8fb6fd 100644 --- a/js/003-data/miscData.js +++ b/js/003-data/miscData.js @@ -1551,13 +1551,6 @@ App.Data.misc = { fakeBellies: ["a huge empathy belly", "a large empathy belly", "a medium empathy belly", "a small empathy belly"], /* lets fake bellies be separated from other .bellyAccessory */ - modestClothes: ["a ball gown", "a biyelgee costume", "a bunny outfit", "a burkini", "a burqa", "a comfortable bodysuit", "a cybersuit", "a dirndl", "a gothic lolita dress", "a halter top dress", "a hanbok", "a hijab and abaya", "a hijab and blouse", "a huipil", "a kimono", "a klan robe", "a latex catsuit", "a leotard", "a long qipao", "a maternity dress", "a military uniform", "a mini dress", "a mounty outfit", "a nice maid outfit", "a nice nurse outfit", "a niqab and abaya", "a one-piece swimsuit", "a penitent nuns habit", "a police uniform", "a red army uniform", "a schoolgirl outfit", "a schutzstaffel uniform", "a slave gown", "a slutty maid outfit", "a slutty nurse outfit", "a slutty qipao", "a sweater and cutoffs", "a t-shirt and jeans", "a toga", "an oversized t-shirt and boyshorts", "battlearmor", "battledress", "conservative clothing", "cutoffs and a t-shirt", "leather pants and a tube top", "lederhosen", "nice business attire", "restrictive latex", "slutty business attire", "spats and a tank top", "sport shorts and a sports bra", "sport shorts and a t-shirt", "stretch pants and a crop-top", "Imperial Plate"], - - sluttyClothes: ["a bimbo outfit", "a chattel habit", "a cheerleader outfit", "a fallen nuns habit", "a schoolgirl outfit", "a skimpy loincloth", "a slutty klan robe", "a slutty maid outfit", "a slutty nurse outfit", "a slutty outfit", "a slutty pony outfit", "a slutty qipao", "a slutty schutzstaffel uniform", "a string bikini", "a succubus outfit", "a t-shirt and panties", "a t-shirt and thong", "a tank-top and panties", "a tube top and thong", "attractive lingerie", "attractive lingerie for a pregnant woman", "clubslut netting", "kitty lingerie", "leather pants and a tube top", "leather pants and pasties", "panties and pasties", "pasties", "slutty business attire", "slutty jewelry", "sport shorts and a sports bra", "striped underwear", "a tight Imperial bodysuit"], - - /* stuff that reveals genitals */ - humiliatingClothes: ["a bra", "a button-up shirt", "a chattel habit", "a fallen nuns habit", "a skimpy loincloth", "a sports bra", "a string bikini", "a striped bra", "a succubus outfit", "a sweater", "a t-shirt", "a tank-top", "a thong", "a tube top", "clubslut netting", "pasties", "restrictive latex", "shibari ropes", "slutty jewelry", "uncomfortable straps", "Western clothing"], - highHeels: ["boots", "extreme heels", "extreme platform heels", "heels", "platform heels"], heightBoostingShoes: ["extreme heels", "extreme platform heels", "heels", "platform heels", "platform shoes", "pumps"], diff --git a/js/003-data/slaveWearData.js b/js/003-data/slaveWearData.js index 0d1d044b570a3ec5e7b02945f9d3a87ac51e7c1f..99bc1487b357f448c8d37dcbc431a25c7e311c6d 100644 --- a/js/003-data/slaveWearData.js +++ b/js/003-data/slaveWearData.js @@ -1,633 +1,1278 @@ /** - * @typedef {object} slaveWear + * @typedef {object} clothes * @property {string} name - * @property {string} value - * @property {string} [fs] + * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS. * @property {boolean} [requirements] + * @property {0|1|2|3} [exposure] 0: Modest, 1: Normal, 2: Slutty, 3: Humiliating (exposes genitals) + * @property {boolean} [harsh] */ /** - * @typedef {Array<slaveWear>|Array<slaveWearChastity>} slaveWearCategory + * @type {Map.<string, clothes>} The string here will be what is applied to the relevant slave property. Slave.clothes = "a bunny outfit", not "Bunny outfit". */ - -/** @type {Object.<string, slaveWearCategory>} */ -App.Data.slaveWear = { - - niceClothes: [ +App.Data.clothes = new Map([ + ["attractive lingerie for a pregnant woman", { name: "Maternity lingerie", - value: "attractive lingerie for a pregnant woman", fs: "FSRepopulationFocus", - get requirements() { return V.boughtItem.clothing.maternityLingerie === 1; } - }, + get requirements() { return V.boughtItem.clothing.maternityLingerie === 1; }, + exposure: 2 + } + ], + ["a bunny outfit", { name: "Bunny outfit", - value: "a bunny outfit", fs: "FSGenderFundamentalist", - get requirements() { return V.boughtItem.clothing.bunny === 1; } - }, + get requirements() { return V.boughtItem.clothing.bunny === 1; }, + exposure: 0 + } + ], + ["body oil", { name: "Body oil", - value: "body oil", fs: "FSPhysicalIdealist", - get requirements() { return V.boughtItem.clothing.oil === 1; } - }, + get requirements() { return V.boughtItem.clothing.oil === 1; }, + exposure: 3 + } + ], + ["a chattel habit", { name: "Chattel habit", - value: "a chattel habit", fs: "FSChattelReligionist", - get requirements() { return V.boughtItem.clothing.habit === 1; } - }, + get requirements() { return V.boughtItem.clothing.habit === 1; }, + exposure: 3 + } + ], + ["conservative clothing", { name: "Conservative clothing", - value: "conservative clothing", fs: "FSPaternalist", - get requirements() { return V.boughtItem.clothing.conservative === 1; } - }, + get requirements() { return V.boughtItem.clothing.conservative === 1; }, + exposure: 0 + } + ], + ["harem gauze", { name: "Harem gauze", - value: "harem gauze", fs: "FSArabianRevivalist", - get requirements() { return V.boughtItem.clothing.harem === 1; } - }, + get requirements() { return V.boughtItem.clothing.harem === 1; }, + exposure: 3 + } + ], + ["a huipil", { name: "Huipil", - value: "a huipil", fs: "FSAztecRevivalist", - get requirements() { return V.boughtItem.clothing.huipil === 1; } - }, + get requirements() { return V.boughtItem.clothing.huipil === 1; }, + exposure: 0 + } + ], + ["a kimono", { name: "Kimono", - value: "a kimono", fs: "FSEdoRevivalist", - get requirements() { return (V.boughtItem.clothing.kimono === 1 || V.continent === "Japan"); } - }, + get requirements() { return (V.boughtItem.clothing.kimono === 1 || V.continent === "Japan"); }, + exposure: 0 + } + ], + ["a maternity dress", { name: "Maternity dress", - value: "a maternity dress", fs: "FSRepopulationFocus", - get requirements() { return V.boughtItem.clothing.maternityDress === 1; } - }, + get requirements() { return V.boughtItem.clothing.maternityDress === 1; }, + exposure: 0, + } + ], + ["a slutty qipao", { name: "Qipao (slutty)", - value: "a slutty qipao", fs: "FSChineseRevivalist", - get requirements() { return V.boughtItem.clothing.qipao === 1; } - }, + get requirements() { return V.boughtItem.clothing.qipao === 1; }, + exposure: 2 + } + ], + ["a long qipao", { name: "Qipao (long)", - value: "a long qipao", fs: "FSChineseRevivalist", - get requirements() { return V.boughtItem.clothing.cultural === 1; } - }, + get requirements() { return V.boughtItem.clothing.cultural === 1; }, + exposure: 0 + } + ], + ["Imperial Plate", { name: "Imperial Plate", - value: "Imperial Plate", fs: "FSNeoImperialist", - get requirements() { return V.boughtItem.clothing.imperialarmor === 1; } - }, + get requirements() { return V.boughtItem.clothing.imperialarmor === 1; }, + exposure: 0 + } + ], + ["a tight Imperial bodysuit", { name: "Imperial Bodysuit", - value: "a tight Imperial bodysuit", fs: "FSNeoImperialist", - get requirements() { return V.boughtItem.clothing.imperialsuit === 1; } - }, + get requirements() { return V.boughtItem.clothing.imperialsuit === 1; }, + exposure: 2 + } + ], + ["stretch pants and a crop-top", { name: "Stretch pants and a crop-top", - value: "stretch pants and a crop-top", fs: "FSHedonisticDecadence", - get requirements() { return V.boughtItem.clothing.lazyClothes === 1; } - }, + get requirements() { return V.boughtItem.clothing.lazyClothes === 1; }, + exposure: 0 + } + ], + ["a toga", { name: "Toga", - value: "a toga", fs: "FSRomanRevivalist", - get requirements() { return V.boughtItem.clothing.toga === 1; } - }, + get requirements() { return V.boughtItem.clothing.toga === 1; }, + exposure: 0 + } + ], + ["Western clothing", { name: "Western clothing", - value: "Western clothing", fs: "FSPastoralist", - get requirements() { return V.boughtItem.clothing.western === 1; } - }, + get requirements() { return V.boughtItem.clothing.western === 1; }, + exposure: 3 + } + ], + ["a courtesan dress", { name: "Courtesan dress", - value: "a courtesan dress", fs: "FSSlaveProfessionalism", - get requirements() { return V.boughtItem.clothing.courtesan === 1; } - }, + get requirements() { return V.boughtItem.clothing.courtesan === 1; }, + exposure: 0 + } + ], + ["a bimbo outfit", { name: "Bimbo outfit", - value: "a bimbo outfit", fs: "FSIntellectualDependency", - get requirements() { return V.boughtItem.clothing.bimbo === 1; } - }, + get requirements() { return V.boughtItem.clothing.bimbo === 1; }, + exposure: 2 + } + ], + ["petite admi outfit", { name: "Petite admi outfit", - value: "petite admi outfit", fs: "FSPetiteAdmiration", - get requirements() { return V.boughtItem.clothing.petite === 1; } - }, - {name: "Battlearmor", value: "battlearmor", get requirements() { return V.boughtItem.clothing.military === 1; }}, - {name: "Military uniform", value: "a military uniform", get requirements() { return V.boughtItem.clothing.military === 1; }}, - {name: "Red Army uniform", value: "a red army uniform", get requirements() { return V.boughtItem.clothing.military === 1; }}, - {name: "Battledress", value: "battledress", get requirements() { return V.boughtItem.clothing.military === 1; }}, - {name: "Biyelgee costume", value: "a biyelgee costume", get requirements() { return V.boughtItem.clothing.cultural === 1; }}, - {name: "Dirndl", value: "a dirndl", get requirements() { return V.boughtItem.clothing.cultural === 1; }}, - {name: "Lederhosen", value: "lederhosen", get requirements() { return V.boughtItem.clothing.cultural === 1; }}, - {name: "Mounty outfit", value: "a mounty outfit", get requirements() { return V.boughtItem.clothing.cultural === 1; }}, - {name: "Hanbok", value: "a hanbok", get requirements() { return V.boughtItem.clothing.cultural === 1; }}, + get requirements() { return V.boughtItem.clothing.petite === 1; }, + exposure: 0 + } + ], + ["battlearmor", + { + name: "Battlearmor", + get requirements() { return V.boughtItem.clothing.military === 1; }, + exposure: 0 + } + ], + ["a military uniform", + { + name: "Military uniform", + get requirements() { return V.boughtItem.clothing.military === 1; }, + exposure: 0 + } + ], + ["a red army uniform", + { + name: "Red Army uniform", + get requirements() { return V.boughtItem.clothing.military === 1; }, + exposure: 0 + } + ], + ["battledress", + { + name: "Battledress", + get requirements() { return V.boughtItem.clothing.military === 1; }, + exposure: 0 + } + ], + ["a biyelgee costume", + { + name: "Biyelgee costume", + get requirements() { return V.boughtItem.clothing.cultural === 1; }, + exposure: 0 + } + ], + ["a dirndl", + { + name: "Dirndl", + get requirements() { return V.boughtItem.clothing.cultural === 1; }, + exposure: 0 + } + ], + ["lederhosen", + { + name: "Lederhosen", + get requirements() { return V.boughtItem.clothing.cultural === 1; }, + exposure: 0 + } + ], + ["a mounty outfit", + { + name: "Mounty outfit", + get requirements() { return V.boughtItem.clothing.cultural === 1; }, + exposure: 0 + } + ], + ["a hanbok", + { + name: "Hanbok", + get requirements() { return V.boughtItem.clothing.cultural === 1; }, + exposure: 0 + } + ], + ["a burqa", { name: "Burqa", - value: "a burqa", - get requirements() { return V.boughtItem.clothing.middleEastern === 1 || V.continent === "the Middle East"; } - }, + get requirements() { return V.boughtItem.clothing.middleEastern === 1 || V.continent === "the Middle East"; }, + exposure: 0 + } + ], + ["a niqab and abaya", { name: "Niqab and abaya", - value: "a niqab and abaya", - get requirements() { return V.boughtItem.clothing.middleEastern === 1 || V.continent === "the Middle East"; } - }, + get requirements() { return V.boughtItem.clothing.middleEastern === 1 || V.continent === "the Middle East"; }, + exposure: 0 + } + ], + ["a hijab and blouse", { name: "Hijab and blouse", - value: "a hijab and blouse", - get requirements() { return (V.boughtItem.clothing.conservative === 1 || V.continent === "the Middle East"); } - }, + get requirements() { return (V.boughtItem.clothing.conservative === 1 || V.continent === "the Middle East"); }, + exposure: 0 + } + ], + ["a burkini", { name: "Burkini", - value: "a burkini", - get requirements() { return V.boughtItem.clothing.swimwear === 1 && (V.boughtItem.clothing.swimwear === 1 || V.continent === "the Middle East"); } - }, - {name: "Santa dress", value: "a Santa dress", get requirements() { return V.boughtItem.clothing.costume === 1; }}, + get requirements() { return V.boughtItem.clothing.swimwear === 1 && (V.boughtItem.clothing.swimwear === 1 || V.continent === "the Middle East"); }, + exposure: 0 + } + ], + ["a Santa dress", + { + name: "Santa dress", + get requirements() { return V.boughtItem.clothing.costume === 1; }, + exposure: 2 + } + ], - {name: "Klan robe", value: "a klan robe", get requirements() { return V.boughtItem.clothing.pol === 1; }}, - {name: "Slutty klan robe", value: "a slutty klan robe", get requirements() { return V.boughtItem.clothing.pol === 1; }}, - {name: "Schutzstaffel uniform", value: "a schutzstaffel uniform", get requirements() { return V.boughtItem.clothing.pol === 1; }}, - {name: "Slutty schutzstaffel uniform", value: "a slutty schutzstaffel uniform", get requirements() { return V.boughtItem.clothing.pol === 1; }}, + ["a klan robe", + { + name: "Klan robe", + get requirements() { return V.boughtItem.clothing.pol === 1; }, + exposure: 0 + } + ], + ["a slutty klan robe", + { + name: "Slutty klan robe", + get requirements() { return V.boughtItem.clothing.pol === 1; }, + exposure: 2 + } + ], + ["a schutzstaffel uniform", + { + name: "Schutzstaffel uniform", + get requirements() { return V.boughtItem.clothing.pol === 1; }, + exposure: 0 + } + ], + ["a slutty schutzstaffel uniform", + { + name: "Slutty schutzstaffel uniform", + get requirements() { return V.boughtItem.clothing.pol === 1; }, + exposure: 2 + } + ], - {name: "Nice business attire", value: "nice business attire", get requirements() { return V.boughtItem.clothing.career === 1; }}, - {name: "Nurse (nice)", value: "a nice nurse outfit", get requirements() { return V.boughtItem.clothing.career === 1; }}, - {name: "Police uniform", value: "a police uniform", get requirements() { return V.boughtItem.clothing.career === 1; }}, + ["nice business attire", + { + name: "Nice business attire", + get requirements() { return V.boughtItem.clothing.career === 1; }, + exposure: 0 + } + ], + ["a nice nurse outfit", + { + name: "Nurse (nice)", + get requirements() { return V.boughtItem.clothing.career === 1; }, + exposure: 0 + } + ], + ["a police uniform", + { + name: "Police uniform", + get requirements() { return V.boughtItem.clothing.career === 1; }, + exposure: 0 + } + ], + ["a nice maid outfit", { name: "Maid (nice)", - value: "a nice maid outfit", - get requirements() { return V.boughtItem.clothing.career === 1 || V.PC.career === "servant" || V.PC.career === "handmaiden" || V.PC.career === "child servant"; } - }, - - {name: "Ballgown", value: "a ball gown", get requirements() { return V.boughtItem.clothing.dresses === 1; }}, - {name: "Gothic lolita dress", value: "a gothic lolita dress", get requirements() { return V.boughtItem.clothing.dresses === 1; }}, - - {name: "Cybersuit", value: "a cybersuit", get requirements() { return V.boughtItem.clothing.bodysuits === 1; }}, - {name: "Latex catsuit", value: "a latex catsuit", get requirements() { return V.boughtItem.clothing.bodysuits === 1; }}, - - {name: "Button-up shirt and panties", value: "a button-up shirt and panties", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Button-up shirt", value: "a button-up shirt", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Cutoffs", value: "cutoffs", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Jeans", value: "jeans", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Leather pants and a tube top", value: "leather pants and a tube top", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Leather pants", value: "leather pants", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Oversized t-shirt", value: "an oversized t-shirt", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Sweater and cutoffs", value: "a sweater and cutoffs", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Sweater and panties", value: "a sweater and panties", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Sweater", value: "a sweater", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "T-shirt and jeans", value: "a t-shirt and jeans", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "T-shirt and panties", value: "a t-shirt and panties", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "T-shirt", value: "a t-shirt", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Tank-top and panties", value: "a tank-top and panties", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Tank-top", value: "a tank-top", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - {name: "Tube top", value: "a tube top", get requirements() { return V.boughtItem.clothing.casual === 1; }}, - - {name: "Boyshorts", value: "boyshorts", get requirements() { return V.boughtItem.clothing.underwear === 1; }}, - {name: "Bra", value: "a bra", get requirements() { return V.boughtItem.clothing.underwear === 1; }}, - {name: "Kitty lingerie", value: "kitty lingerie", get requirements() { return V.boughtItem.clothing.underwear === 1; }}, - {name: "Panties and pasties", value: "panties and pasties", get requirements() { return V.boughtItem.clothing.underwear === 1; }}, - {name: "Skimpy loincloth", value: "a skimpy loincloth", get requirements() { return V.boughtItem.clothing.underwear === 1; }}, - {name: "Thong", value: "a thong", get requirements() { return V.boughtItem.clothing.underwear === 1; }}, - {name: "Pasties", value: "pasties", get requirements() { return V.boughtItem.clothing.underwear === 1; }}, - + get requirements() { return V.boughtItem.clothing.career === 1 || V.PC.career === "servant" || V.PC.career === "handmaiden" || V.PC.career === "child servant"; }, + exposure: 0 + } + ], + ["a ball gown", + { + name: "Ballgown", + get requirements() { return V.boughtItem.clothing.dresses === 1; }, + exposure: 0 + } + ], + ["a gothic lolita dress", + { + name: "Gothic lolita dress", + get requirements() { return V.boughtItem.clothing.dresses === 1; }, + exposure: 0 + } + ], + ["a cybersuit", + { + name: "Cybersuit", + get requirements() { return V.boughtItem.clothing.bodysuits === 1; }, + exposure: 0 + } + ], + ["a latex catsuit", + { + name: "Latex catsuit", + get requirements() { return V.boughtItem.clothing.bodysuits === 1; }, + exposure: 0 + } + ], + ["a button-up shirt and panties", + { + name: "Button-up shirt and panties", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 2 + } + ], + ["a button-up shirt", + { + name: "Button-up shirt", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 3 + } + ], + ["cutoffs", + { + name: "Cutoffs", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 0 + } + ], + ["jeans", + { + name: "Jeans", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 2 + } + ], + ["leather pants and a tube top", + { + name: "Leather pants and a tube top", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 0 + } + ], + ["leather pants", + { + name: "Leather pants", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 2 + } + ], + ["an oversized t-shirt", + { + name: "Oversized t-shirt", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 2 + } + ], + ["a sweater and cutoffs", + { + name: "Sweater and cutoffs", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 0 + } + ], + ["a sweater and panties", + { + name: "Sweater and panties", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 2 + } + ], + ["a sweater", + { + name: "Sweater", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 3 + } + ], + ["a t-shirt and jeans", + { + name: "T-shirt and jeans", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 0 + } + ], + ["a t-shirt and panties", + { + name: "T-shirt and panties", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 2 + } + ], + ["a t-shirt", + { + name: "T-shirt", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 3 + } + ], + ["a tank-top and panties", + { + name: "Tank-top and panties", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 2 + } + ], + ["a tank-top", + { + name: "Tank-top", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 3 + } + ], + ["a tube top", + { + name: "Tube top", + get requirements() { return V.boughtItem.clothing.casual === 1; }, + exposure: 3 + } + ], + ["boyshorts", + { + name: "Boyshorts", + get requirements() { return V.boughtItem.clothing.underwear === 1; }, + exposure: 2 + } + ], + ["a bra", + { + name: "Bra", + get requirements() { return V.boughtItem.clothing.underwear === 1; }, + exposure: 3 + } + ], + ["kitty lingerie", + { + name: "Kitty lingerie", + get requirements() { return V.boughtItem.clothing.underwear === 1; }, + exposure: 2 + } + ], + ["panties and pasties", + { + name: "Panties and pasties", + get requirements() { return V.boughtItem.clothing.underwear === 1; }, + exposure: 2 + } + ], + ["a skimpy loincloth", + { + name: "Skimpy loincloth", + get requirements() { return V.boughtItem.clothing.underwear === 1; }, + exposure: 3 + } + ], + ["a thong", + { + name: "Thong", + get requirements() { return V.boughtItem.clothing.underwear === 1; }, + exposure: 3 + } + ], + ["pasties", + { + name: "Pasties", + get requirements() { return V.boughtItem.clothing.underwear === 1; }, + exposure: 3 + } + ], + ["leather pants and pasties", { name: "Leather pants and pasties", - value: "leather pants and pasties", - get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; } - }, + get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; }, + exposure: 2, + } + ], + ["a t-shirt and thong", { name: "T-shirt and thong", - value: "a t-shirt and thong", - get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; } - }, + get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; }, + exposure: 2, + } + ], + ["a tube top and thong", { name: "Tube top and thong", - value: "a tube top and thong", - get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; } - }, + get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; }, + exposure: 2, + } + ], + ["an oversized t-shirt and boyshorts", { name: "Oversized t-shirt and boyshorts", - value: "an oversized t-shirt and boyshorts", - get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; } - }, - {name: "Sport shorts and a sports bra", value: "sport shorts and a sports bra", get requirements() { return V.boughtItem.clothing.sports === 1; }}, - {name: "Sport shorts", value: "sport shorts", get requirements() { return V.boughtItem.clothing.sports === 1; }}, - {name: "Sports bra", value: "a sports bra", get requirements() { return V.boughtItem.clothing.sports === 1; }}, + get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; }, + exposure: 0, + } + ], + ["sport shorts and a sports bra", + { + name: "Sport shorts and a sports bra", + get requirements() { return V.boughtItem.clothing.sports === 1; }, + exposure: 2, + } + ], + ["sport shorts", + { + name: "Sport shorts", + get requirements() { return V.boughtItem.clothing.sports === 1; }, + exposure: 2 + } + ], + ["a sports bra", + { + name: "Sports bra", + get requirements() { return V.boughtItem.clothing.sports === 1; }, + exposure: 3 + } + ], + ["sport shorts and a t-shirt", { name: "Sport shorts and a t-shirt", - value: "sport shorts and a t-shirt", - get requirements() { return V.boughtItem.clothing.sports === 1 && V.boughtItem.clothing.casual === 1; } - }, - {name: "Pony outfit (nice)", value: "a nice pony outfit", get requirements() { return V.boughtItem.clothing.pony === 1; }}, - {name: "Pony outfit (slutty)", value: "a slutty pony outfit", get requirements() { return V.boughtItem.clothing.pony === 1; }}, - - {name: "Monokini", value: "a monokini", get requirements() { return V.boughtItem.clothing.swimwear === 1; }}, - {name: "One-piece swimsuit", value: "a one-piece swimsuit", get requirements() { return V.boughtItem.clothing.swimwear === 1; }}, - + get requirements() { return V.boughtItem.clothing.sports === 1 && V.boughtItem.clothing.casual === 1; }, + exposure: 0 + } + ], + ["a nice pony outfit", + { + name: "Pony outfit (nice)", + get requirements() { return V.boughtItem.clothing.pony === 1; }, + exposure: 0 + } + ], + ["a slutty pony outfit", + { + name: "Pony outfit (slutty)", + get requirements() { return V.boughtItem.clothing.pony === 1; }, + exposure: 2 + } + ], + ["a monokini", + { + name: "Monokini", + get requirements() { return V.boughtItem.clothing.swimwear === 1; }, + exposure: 3 + } + ], + ["a one-piece swimsuit", + { + name: "One-piece swimsuit", + get requirements() { return V.boughtItem.clothing.swimwear === 1; }, + exposure: 0 + } + ], + ["a striped bra", { name: "Striped bra", - value: "a striped bra", - get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; } - }, + get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; }, + exposure: 3 + } + ], + ["striped panties", { name: "Striped panties", - value: "striped panties", - get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; } - }, + get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; }, + exposure: 2, + } + ], + ["striped underwear", { name: "Striped underwear", - value: "striped underwear", - get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; } - }, - - // "Normal" things: - {name: "Apron", value: "an apron"}, - {name: "Bangles", value: "slutty jewelry"}, - {name: "Clubslut netting", value: "clubslut netting"}, - {name: "Cutoffs and a t-shirt", value: "cutoffs and a t-shirt"}, - {name: "Bodysuit", value: "a comfortable bodysuit"}, - {name: "Cheerleader", value: "a cheerleader outfit"}, - {name: "Fallen nun", value: "a fallen nuns habit"}, - {name: "Hijab and abaya", value: "a hijab and abaya"}, - {name: "Leotard", value: "a leotard"}, - {name: "Maid (slutty)", value: "a slutty maid outfit"}, - {name: "Mini dress", value: "a mini dress"}, - {name: "Nice lingerie", value: "attractive lingerie"}, - {name: "Nurse (slutty)", value: "a slutty nurse outfit"}, - {name: "Overalls", value: "overalls"}, - {name: "Panties", value: "panties"}, - {name: "Scalemail bikini", value: "a scalemail bikini"}, - {name: "Schoolgirl", value: "a schoolgirl outfit"}, - {name: "Slutty outfit", value: "a slutty outfit"}, - {name: "Spats and a tank top", value: "spats and a tank top"}, - {name: "String bikini", value: "a string bikini"}, - {name: "Succubus costume", value: "a succubus outfit"}, - {name: "Suit (slutty)", value: "slutty business attire"}, - - // {name: "Let them choose", value: "choosing her own clothes"}, - {name: "Haltertop dress", value: "a halter top dress"}, - {name: "Slave gown", value: "a slave gown"} + get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; }, + exposure: 2, + } ], - harshClothes: [ + // "Normal" things: + ["an apron", { - name: "Chains", - value: "chains", - fs: "FSDegradationist", - get requirements() { return V.boughtItem.clothing.chains === 1; } - }, - {name: "Go naked", value: "no clothing"}, - {name: "Penitent nun", value: "a penitent nuns habit"}, - {name: "Restrictive latex", value: "restrictive latex"}, - {name: "Shibari ropes", value: "shibari ropes"}, - {name: "Uncomfortable straps", value: "uncomfortable straps"} + name: "Apron", + exposure: 2, + } ], - - niceCollars: [ - {name: "Stylish leather", value: "stylish leather"}, - {name: "Satin choker", value: "satin choker"}, - {name: "Silken ribbon", value: "silk ribbon"}, - {name: "Heavy gold", value: "heavy gold"}, - {name: "Pretty jewelry", value: "pretty jewelry"}, - {name: "Nice retirement counter", value: "nice retirement counter", get requirements() { return V.seeAge === 1; }}, - {name: "Pregnancy biometrics", value: "preg biometrics", get requirements() { return V.seePreg === 1; }}, - {name: "Bell", value: "bell collar"}, - {name: "Cowbell", value: "leather with cowbell"}, - { - name: "Bowtie collar", - value: "bowtie", - fs: "FSGenderFundamentalist", - get requirements() { return V.boughtItem.clothing.bunny === 1; } - }, + ["slutty jewelry", { - name: "Neck tie", - value: "neck tie", - fs: "FSPaternalist", - get requirements() { return V.boughtItem.clothing.conservative === 1; } - }, - { - name: "Ancient Egyptian", - value: "ancient Egyptian", - fs: "FSEgyptianRevivalist", - get requirements() { return V.boughtItem.clothing.egypt === 1; } - }, + name: "Bangles", + exposure: 3 + } ], - - harshCollars: [ - {name: "Tight steel", value: "tight steel"}, - {name: "Cruel retirement counter", value: "cruel retirement counter", get requirements() { return V.seeAge === 1; }}, - {name: "Uncomfortable leather", value: "uncomfortable leather"}, - {name: "Shock punishment", value: "shock punishment"}, - {name: "Neck corset", value: "neck corset"}, + ["clubslut netting", + { + name: "Clubslut netting", + exposure: 3 + } ], - - faceAccessory: [ - {name: "Porcelain mask", value: "porcelain mask"}, - {name: "Cat ears", value: "cat ears"}, + ["cutoffs and a t-shirt", + { + name: "Cutoffs and a t-shirt", + exposure: 0 + } ], - - mouthAccessory: [ - {name: "Ball gag", value: "ball gag"}, - {name: "Bit gag", value: "bit gag"}, - {name: "Ring gag", value: "ring gag"}, + ["a comfortable bodysuit", { - name: "Massive dildo gag", - value: "massive dildo gag", - get requirements() { return V.boughtItem.toys.gags === 1; } - }, - {name: "Dildo gag", value: "dildo gag"}, + name: "Bodysuit", + exposure: 0 + } ], - - shoes: [ - {name: "Barefoot", value: "none"}, - {name: "Flats", value: "flats"}, - {name: "Heels", value: "heels"}, - {name: "Pumps", value: "pumps"}, - {name: "Thigh boots", value: "boots"}, - {name: "Painfully extreme heels", value: "extreme heels"}, - { - name: "Platforms", - value: "platform shoes", - fs: "FSStatuesqueGlorification", - get requirements() { return (V.boughtItem.shoes.heels === 1); } - }, - { - name: "Platform heels", - value: "platform heels", - fs: "FSStatuesqueGlorification", - get requirements() { return (V.boughtItem.shoes.heels === 1); } - }, - { - name: "Painfully extreme platform heels", - value: "extreme platform heels", - fs: "FSStatuesqueGlorification", - get requirements() { return (V.boughtItem.shoes.heels === 1); } + ["a cheerleader outfit", + { + name: "Cheerleader", + exposure: 2 } ], - - bellyAccessories: [ - {name: "None", value: "none"}, - {name: "Tight corset", value: "a corset"}, - {name: "Extreme corset", value: "an extreme corset"}, - {name: "Supportive band", value: "a support band"}, - { - name: "1st Trimester belly", - value: "a small empathy belly", - fs: "FSRepopulationFocus", - get requirements() { return V.boughtItem.clothing.belly === 1; } - }, + ["a fallen nuns habit", { - name: "2nd Trimester belly", - value: "a medium empathy belly", - fs: "FSRepopulationFocus", - get requirements() { return V.boughtItem.clothing.belly === 1; } - }, + name: "Fallen nun", + exposure: 3 + } + ], + ["a hijab and abaya", { - name: "3rd Trimester belly", - value: "a large empathy belly", - fs: "FSRepopulationFocus", - get requirements() { return V.boughtItem.clothing.belly === 1; } - }, + name: "Hijab and abaya", + exposure: 0 + } + ], + ["a leotard", { - name: "3rd Trimester twins belly", - value: "a huge empathy belly", - fs: "FSRepopulationFocus", - get requirements() { return V.boughtItem.clothing.belly === 1; } + name: "Leotard", + exposure: 0 } ], - - vaginalAccessories: [ + ["a slutty maid outfit", { - name: "None", - value: "none" - }, + name: "Maid (slutty)", + exposure: 2 + } + ], + ["a mini dress", { - name: "Bullet vibrator", - value: "bullet vibrator" - }, + name: "Mini dress", + exposure: 0 + } + ], + ["attractive lingerie", { - name: "Smart bullet vibrator", - value: "smart bullet vibrator", - get requirements() { return V.boughtItem.toys.smartVibes === 1; } - }, + name: "Nice lingerie", + exposure: 2 + } + ], + ["a slutty nurse outfit", { - name: "Dildo", - value: "dildo" - }, + name: "Nurse (slutty)", + exposure: 2 + } + ], + ["overalls", { - name: "Long dildo", - value: "long dildo", - get requirements() { return V.boughtItem.toys.dildos === 1; } - }, + name: "Overalls", + exposure: 0 + } + ], + ["panties", { - name: "Large dildo", - value: "large dildo" - }, + name: "Panties", + exposure: 2 + } + ], + ["a scalemail bikini", { - name: "Long, large dildo", - value: "long, large dildo", - get requirements() { return V.boughtItem.toys.dildos === 1; } - }, + name: "Scalemail bikini", + exposure: 2 + } + ], + ["a schoolgirl outfit", { - name: "Huge dildo", - value: "huge dildo", - get requirements() { return V.boughtItem.toys.dildos === 1; } - }, + name: "Schoolgirl", + exposure: 2 + } + ], + ["a slutty outfit", { - name: "Long, huge dildo", - value: "long, huge dildo", - get requirements() { return V.boughtItem.toys.dildos === 1; } + name: "Slutty outfit", + exposure: 2 } ], - - vaginalAttachments: [ - {name: "None", value: "none"}, + ["spats and a tank top", { - name: "Vibrating attachment", - value: "vibrator", - get requirements() { return V.boughtItem.toys.vaginalAttachments === 1; } - }, + name: "Spats and a tank top", + exposure: 0 + } + ], + ["a string bikini", { - name: "Smart vibrating attachment", - value: "smart vibrator", - get requirements() { return V.boughtItem.toys.smartVaginalAttachments === 1; } + name: "String bikini", + exposure: 3 } ], - - dickAccessories: [ - {name: "None", value: "none"}, + ["a succubus outfit", { - name: "Bullet vibrator", - value: "bullet vibrator" - }, + name: "Succubus costume", + exposure: 3 + } + ], + ["slutty business attire", { - name: "Smart bullet vibrator", - value: "smart bullet vibrator", - get requirements() { return V.boughtItem.toys.smartVibes === 1; } + name: "Suit (slutty)", + exposure: 2, } ], - buttplugs: [ - { - name: "None", - value: "none" - }, + /* + ["choosing her own clothes", +{ + name: "Let them choose", + } +], + */ + ["a halter top dress", + { + name: "Haltertop dress", + exposure: 0 + } + ], + ["a slave gown", { - name: "Standard plug", - value: "plug" - }, + name: "Slave gown", + exposure: 0 + } + ], + ["chains", { - name: "Long plug", - value: "long plug", - get requirements() { return V.boughtItem.toys.buttPlugs === 1; } - }, + name: "Chains", + fs: "FSDegradationist", + get requirements() { return V.boughtItem.clothing.chains === 1; }, + exposure: 3, + harsh: true + } + ], + ["no clothing", { - name: "Large plug", - value: "large plug" - }, + name: "Go naked", + exposure: 3, + harsh: true + } + ], + ["a penitent nuns habit", { - name: "Long, large plug", - value: "long, large plug", - get requirements() { return V.boughtItem.toys.buttPlugs === 1; } - }, + name: "Penitent nun", + exposure: 2, + harsh: true + } + ], + ["restrictive latex", { - name: "Huge plug", - value: "huge plug", - }, + name: "Restrictive latex", + exposure: 3 + } + ], + ["shibari ropes", { - name: "Long, huge plug", - value: "long, huge plug", - get requirements() { return V.boughtItem.toys.buttPlugs === 1; } + name: "Shibari ropes", + exposure: 3, + harsh: true } ], + ["uncomfortable straps", + { + name: "Uncomfortable straps", + exposure: 3, + harsh: true + } + ] +]); +/** + * @typedef {object} slaveWear + * @property {string} name + * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS. + * @property {boolean} [requirements] + * @property {boolean} [harsh] + */ + +/** + * @typedef {Map<string, slaveWear|slaveWearChastity>} slaveWearCategory + */ + +/** @type {Object.<string, slaveWearCategory>} */ +App.Data.slaveWear = { + collars: new Map([ + ["stylish leather", {name: "Stylish leather"}], + ["satin choker", {name: "Satin choker"}], + ["silk ribbon", {name: "Silken ribbon"}], + ["heavy gold", {name: "Heavy gold"}], + ["pretty jewelry", {name: "Pretty jewelry"}], + ["nice retirement counter", + { + name: "Nice retirement counter", + get requirements() { + return V.seeAge === 1; + } + } + ], + ["preg biometrics", + { + name: "Pregnancy biometrics", + get requirements() { + return V.seePreg === 1; + } + } + ], + ["bell collar", {name: "Bell"}], + ["leather with cowbell", {name: "Cowbell"}], + ["bowtie", + { + name: "Bowtie collar", + fs: "FSGenderFundamentalist", + get requirements() { + return V.boughtItem.clothing.bunny === 1; + } + } + ], + ["neck tie", + { + name: "Neck tie", + fs: "FSPaternalist", + get requirements() { + return V.boughtItem.clothing.conservative === 1; + } + } + ], + ["ancient Egyptian", + { + name: "Ancient Egyptian", + fs: "FSEgyptianRevivalist", + get requirements() { + return V.boughtItem.clothing.egypt === 1; + } + } + ], + ["tight steel", + { + name: "Tight steel", + harsh: true + } + ], + ["cruel retirement counter", + { + name: "Cruel retirement counter", + get requirements() { + return V.seeAge === 1; + }, + harsh: true + } + ], + ["uncomfortable leather", + { + name: "Uncomfortable leather", + harsh: true + } + ], + ["shock punishment", + { + name: "Shock punishment", + harsh: true + } + ], + ["neck corset", + { + name: "Neck corset", + harsh: true + } + ], + ]), + + faceAccessory: new Map([ + ["porcelain mask", {name: "Porcelain mask"}], + ["cat ears", {name: "Cat ears"}], + ]), + + mouthAccessory: new Map([ + ["ball gag", {name: "Ball gag"}], + ["bit gag", {name: "Bit gag"}], + ["ring gag", {name: "Ring gag"}], + ["massive dildo gag", + { + name: "Massive dildo gag", + get requirements() { + return V.boughtItem.toys.gags === 1; + } + } + ], + ["dildo gag", {name: "Dildo gag"} + ], + ]), + + shoes: new Map([ + ["none", {name: "Barefoot"}], + ["flats", {name: "Flats"}], + ["heels", {name: "Heels"}], + ["pumps", {name: "Pumps"}], + ["boots", {name: "Thigh boots"}], + ["extreme heels", {name: "Painfully extreme heels"}], + ["platform shoes", + { + name: "Platforms", + fs: "FSStatuesqueGlorification", + get requirements() { + return (V.boughtItem.shoes.heels === 1); + } + } + ], + ["platform heels", + { + name: "Platform heels", + fs: "FSStatuesqueGlorification", + get requirements() { + return (V.boughtItem.shoes.heels === 1); + } + } + ], + ["extreme platform heels", + { + name: "Painfully extreme platform heels", + fs: "FSStatuesqueGlorification", + get requirements() { + return (V.boughtItem.shoes.heels === 1); + } + } + ], + ]), + + bellyAccessories: new Map([ + ["none", {name: "None"}], + ["a corset", {name: "Tight corset"}], + ["an extreme corset", {name: "Extreme corset"}], + ["a support band", {name: "Supportive band"}], + ["a small empathy belly", + { + name: "1st Trimester belly", + fs: "FSRepopulationFocus", + get requirements() { + return V.boughtItem.clothing.belly === 1; + } + } + ], + ["a medium empathy belly", + { + name: "2nd Trimester belly", + fs: "FSRepopulationFocus", + get requirements() { + return V.boughtItem.clothing.belly === 1; + } + } + ], + ["a large empathy belly", + { + name: "3rd Trimester belly", + fs: "FSRepopulationFocus", + get requirements() { + return V.boughtItem.clothing.belly === 1; + } + } + ], + ["a huge empathy belly", + { + name: "3rd Trimester twins belly", + fs: "FSRepopulationFocus", + get requirements() { + return V.boughtItem.clothing.belly === 1; + } + } + ] + ]), + + vaginalAccessories: new Map([ + ["none", {name: "None"}], + ["bullet vibrator", {name: "Bullet vibrator"}], + ["smart bullet vibrator", + { + name: "Smart bullet vibrator", + get requirements() { + return V.boughtItem.toys.smartVibes === 1; + } + } + ], + ["dildo", {name: "Dildo"}], + ["long dildo", + { + name: "Long dildo", + get requirements() { + return V.boughtItem.toys.dildos === 1; + } + } + ], + ["large dildo", {name: "Large dildo"}], + ["long, large dildo", + { + name: "Long, large dildo", + get requirements() { + return V.boughtItem.toys.dildos === 1; + } + } + ], + ["huge dildo", + { + name: "Huge dildo", + get requirements() { + return V.boughtItem.toys.dildos === 1; + } + } + ], + ["long, huge dildo", + { + name: "Long, huge dildo", + get requirements() { + return V.boughtItem.toys.dildos === 1; + } + } + ] + ]), + + vaginalAttachments: new Map([ + ["none", {name: "None"}], + ["vibrator", + { + name: "Vibrating attachment", + get requirements() { + return V.boughtItem.toys.vaginalAttachments === 1; + } + } + ], + ["smart vibrator", + { + name: "Smart vibrating attachment", + get requirements() { + return V.boughtItem.toys.smartVaginalAttachments === 1; + } + } + ] + ]), + + dickAccessories: new Map([ + ["none", {name: "None"}], + ["bullet vibrator", {name: "Bullet vibrator"}], + ["smart bullet vibrator", + { + name: "Smart bullet vibrator", + get requirements() { + return V.boughtItem.toys.smartVibes === 1; + } + } + ] + ]), - buttplugAttachments: [ - {name: "None", value: "none"}, - {name: "Tail", value: "tail", get requirements() { return V.boughtItem.toys.buttPlugTails === 1; }}, - {name: "Fox tail", value: "fox tail", get requirements() { return V.boughtItem.toys.buttPlugTails === 1; }}, - {name: "Cat tail", value: "cat tail", get requirements() { return V.boughtItem.toys.buttPlugTails === 1; }}, - {name: "Cow tail", value: "cow tail", get requirements() { return V.boughtItem.toys.buttPlugTails === 1; }} - ], - /** - * @typedef {object} slaveWearChastity - * @property {string} name - * @property {string} value - * @property {object} updateSlave - * @property {string} [fs] - */ + buttplugs: new Map([ + ["none", {name: "None"}], + ["plug", {name: "Standard plug"}], + ["long plug", + { + name: "Long plug", + get requirements() { + return V.boughtItem.toys.buttPlugs === 1; + } + } + ], + ["large plug", {name: "Large plug"}], + ["long, large plug", + { + name: "Long, large plug", + get requirements() { + return V.boughtItem.toys.buttPlugs === 1; + } + } + ], + ["huge plug", {name: "Huge plug"}], + ["long, huge plug", + { + name: "Long, huge plug", + get requirements() { + return V.boughtItem.toys.buttPlugs === 1; + } + } + ] + ]), - /** @type {Array<slaveWearChastity>} */ - chastityDevices: [ - // '.value' must be a string, so using update slave so I can update multiple values. + buttplugAttachments: new Map([ + ["none", {name: "None"}], + ["tail", + { + name: "Tail", + get requirements() { + return V.boughtItem.toys.buttPlugTails === 1; + } + } + ], + ["fox tail", + { + name: "Fox tail", + get requirements() { + return V.boughtItem.toys.buttPlugTails === 1; + } + } + ], + ["cat tail", + { + name: "Cat tail", + get requirements() { + return V.boughtItem.toys.buttPlugTails === 1; + } + } + ], + ["cow tail", + { + name: "Cow tail", + get requirements() { + return V.boughtItem.toys.buttPlugTails === 1; + } + } + ] + ]), +}; +/** + * @typedef {object} slaveWearChastity + * @property {string} name + * @property {string} value + * @property {object} updateSlave + * @property {FC.FutureSociety} [fs] + */ + +/** @type {Map<string, slaveWearChastity>} */ +App.Data.slaveWear.chastityDevices = new Map([ + // '.value' must be a string, so using update slave so I can update multiple values. + ["none", { name: "None", - value: "none", updateSlave: { choosesOwnChastity: 0, chastityAnus: 0, chastityPenis: 0, chastityVagina: 0 }, - }, + } + ], + ["anal chastity", { name: "Anal chastity", - value: "anal chastity", updateSlave: { choosesOwnChastity: 0, chastityAnus: 1, chastityPenis: 0, chastityVagina: 0 } - }, + } + ], + ["chastity belt", { name: "Chastity belt", - value: "chastity belt", updateSlave: { choosesOwnChastity: 0, chastityAnus: 0, chastityPenis: 0, chastityVagina: 1 }, - }, + } + ], + ["combined chastity belt", { name: "Combined chastity belt", - value: "combined chastity belt", updateSlave: { choosesOwnChastity: 0, chastityAnus: 1, chastityPenis: 0, chastityVagina: 1 }, - }, + } + ], + ["chastity cage", { name: "Chastity cage", - value: "chastity cage", updateSlave: { choosesOwnChastity: 0, chastityAnus: 0, chastityPenis: 1, chastityVagina: 0 }, - }, + } + ], + ["combined chastity cage", { name: "Combined chastity cage", - value: "combined chastity cage", updateSlave: { choosesOwnChastity: 0, chastityAnus: 1, chastityPenis: 1, chastityVagina: 0 }, - }, + } + ], + ["genital chastity", { name: "Genital chastity", - value: "genital chastity", updateSlave: { choosesOwnChastity: 0, chastityAnus: 0, chastityPenis: 1, chastityVagina: 1 }, - }, + } + ], + ["full chastity", { name: "Full chastity", - value: "full chastity", updateSlave: { choosesOwnChastity: 0, chastityAnus: 1, chastityPenis: 1, chastityVagina: 1 }, - }, + } + ], + ["choose own chastity", { name: "Choose own chastity", - value: "choose own chastity", fs: "FSRestart", updateSlave: { choosesOwnChastity: 1 }, - }, + } + ], + ["revoke choosing own chastity", { name: "Revoke choosing own chastity", - value: "revoke choosing own chastity", fs: "FSRestart", updateSlave: { choosesOwnChastity: 0 }, - }, - ], -}; + } + ] +]); diff --git a/src/endWeek/saClothes.js b/src/endWeek/saClothes.js index bf925dfc8df15fe35d7c4b68fc87a66406214d2f..8ab1e6d4839e9d8342dc111bb497ccd9e3111348 100644 --- a/src/endWeek/saClothes.js +++ b/src/endWeek/saClothes.js @@ -287,7 +287,7 @@ App.SlaveAssignment.clothes = (function() { r.push(`${He} pretends to be embarrassed by ${his} clearly exposed breasts but <span class="hotpink">secretly gets off on it.</span>`); slave.devotion += 1; } - } else if (slave.fetish === "humiliation" && setup.humiliatingClothes.includes(slave.clothes)) { + } else if (slave.fetish === "humiliation" && App.Data.clothes.get(slave.clothes).exposure === 3) { if (slave.fetishKnown === 0) { r.push(`${He} pretends to be embarrassed by ${his} extremely revealing clothing but seems to get off on it. <span class="lightcoral">${He}'s into humiliation.</span>`); slave.fetishKnown = 1; @@ -324,7 +324,7 @@ App.SlaveAssignment.clothes = (function() { // humiliating clothing effects if (slave.fetishKnown === 0 || slave.fetish === "none") { - if (setup.humiliatingClothes.includes(slave.clothes)) { + if (App.Data.clothes.get(slave.clothes).exposure === 3) { if (fetishChangeChance(slave) > jsRandom(0, 100)) { r.push(`Surprisingly, ${he} takes to ${his} extremely revealing clothing, and gets an obvious thrill from it. <span class="lightcoral">${He}'s become a humiliation fetishist!</span>`); slave.fetish = "humiliation"; diff --git a/src/events/eventUtils.js b/src/events/eventUtils.js index 6a117d3f283b325621417b3d09bd237fd7d42943..b8a9df8934acf8860d3ed8b22d143739862bb0ac 100644 --- a/src/events/eventUtils.js +++ b/src/events/eventUtils.js @@ -1,5 +1,5 @@ App.Events.drawEventArt = (function() { - const validSingleOutfits = App.Data.slaveWear.niceClothes.map(c => c.value).concat(App.Data.slaveWear.harshClothes.map(c => c.value)); + const validSingleOutfits = Array.from(App.Data.clothes.keys()); /** draw event art, with the option to dress the slave in a particular way * @param {Node} node - DOM node to attach art to diff --git a/src/facilities/wardrobe/wardrobeShopping.js b/src/facilities/wardrobe/wardrobeShopping.js index c25b749e9cc0ed36c0033ca3664b8ba9fabc0e29..c1aa035e680c1476eb3d57537a7c0d7ffcdbdffb 100644 --- a/src/facilities/wardrobe/wardrobeShopping.js +++ b/src/facilities/wardrobe/wardrobeShopping.js @@ -7,10 +7,8 @@ App.UI.WardrobeShopping = function() { let r = []; r.push(`The room containing all the clothes and accessories you have available to dress your slaves in, as well as the supplies and tools your tailor needs to resize them to better fit your slaves. Several mirrors are set up for a slave to try on outfits should they be allowed to dress themselves. The selection includes`); - const ownItAll = ( - App.Data.slaveWear.niceClothes.every((i) => isItemAccessible.entry(i.value, "clothing")) && - App.Data.slaveWear.harshClothes.every((i) => isItemAccessible.entry(i.value, "clothing")) - ); + const ownItAll = Array.from(App.Data.clothes.keys()).every((key) => isItemAccessible.entry(key, "clothing")); + if (ownItAll) { r.push(`outfits from all manner of cultures and societies; not a single style eludes you.`); } else { diff --git a/src/interaction/siWardrobe.js b/src/interaction/siWardrobe.js index 805960ad548f48fe4506a1b74bc8dd37a5336de8..167dbaa3b3eaaa7957b0a73107b87fb0b3bc4177 100644 --- a/src/interaction/siWardrobe.js +++ b/src/interaction/siWardrobe.js @@ -1,35 +1,34 @@ App.UI.SlaveInteract.wardrobe = function(slave) { const { // eslint-disable-next-line no-unused-vars - he, him, his, } = getPronouns(slave); - const el = new DocumentFragment(); - el.append(clothes()); + const frag = new DocumentFragment(); + frag.append(clothes()); if (slave.fuckdoll === 0) { - el.append(collar()); - el.append(mask()); - el.append(mouth()); - el.append(armAccessory()); - el.append(shoes()); - el.append(legAccessory()); - el.append(bellyAccessory()); - el.append(buttplug()); - el.append(buttplugAttachment()); - el.append(vaginalAccessory()); - el.append(vaginalAttachment()); - el.append(dickAccessory()); - el.append(chastity()); + frag.append(collar()); + frag.append(mask()); + frag.append(mouth()); + frag.append(armAccessory()); + frag.append(shoes()); + frag.append(legAccessory()); + frag.append(bellyAccessory()); + frag.append(buttplug()); + frag.append(buttplugAttachment()); + frag.append(vaginalAccessory()); + frag.append(vaginalAttachment()); + frag.append(dickAccessory()); + frag.append(chastity()); } - App.UI.DOM.appendNewElement("h3", el, `Shopping`); - el.append(shopping()); + App.UI.DOM.appendNewElement("h3", frag, `Shopping`); + frag.append(shopping()); - return el; + return frag; function clothes() { - let el = document.createElement('div'); + const el = document.createElement('div'); let links; if (slave.fuckdoll === 0) { let label = document.createElement('div'); @@ -43,7 +42,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { if (slave.clothes !== `choosing her own clothes`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: ` Let ${him} choose`, updateSlave: {clothes: `choosing her own clothes`, choosesOwnClothes: 1}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "clothes", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "clothes", false)); } el.appendChild(label); @@ -51,54 +50,40 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let niceOptionsArray = []; let harshOptionsArray = []; - let clothingOption; - // Nice clothes - App.Data.slaveWear.niceClothes.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {clothes: item.value, choosesOwnClothes: 0}, - FS: item.fs - }; - niceOptionsArray.push(clothingOption); - }); - // Harsh clothes - App.Data.slaveWear.harshClothes.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {clothes: item.value, choosesOwnClothes: 0}, - FS: item.fs + for (const [key, object] of App.Data.clothes) { + if (key === "choosing her own clothes") { + continue; + } + const reshapedItem = { + text: object.name, + updateSlave: {clothes: key, choosesOwnClothes: 0}, + FS: object.fs, + exposure: object.exposure, }; - if (item.value !== "choosing her own clothes") { - harshOptionsArray.push(clothingOption); + if (object.harsh) { + harshOptionsArray.push(reshapedItem); + } else { + niceOptionsArray.push(reshapedItem); } - }); + } // Sort niceOptionsArray = niceOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); harshOptionsArray = harshOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); // Nice options - links = document.createElement('div'); - links.className = "choices"; - links.append(`Nice: `); - links.appendChild(App.UI.SlaveInteract.generateRows(niceOptionsArray, slave, "clothes", true, refresh)); - el.appendChild(links); + links = App.UI.DOM.appendNewElement("div", el, "Nice: ", "choices"); + links.appendChild(generateRows(niceOptionsArray, "clothes", true)); // Harsh options - links = document.createElement('div'); - links.className = "choices"; - links.append(`Harsh: `); - links.appendChild(App.UI.SlaveInteract.generateRows(harshOptionsArray, slave, "clothes", true, refresh)); - el.appendChild(links); + links = App.UI.DOM.appendNewElement("div", el, "Harsh: ", "choices"); + links.appendChild(generateRows(harshOptionsArray, "clothes", true)); } if (slave.fuckdoll !== 0 || slave.clothes === "restrictive latex" || slave.clothes === "a latex catsuit" || slave.clothes === "a cybersuit" || slave.clothes === "a comfortable bodysuit") { if (V.seeImages === 1 && V.imageChoice === 1) { // Color options - links = document.createElement('div'); - links.className = "choices"; - links.append(`Color: `); + links = App.UI.DOM.appendNewElement("div", el, "Color: ", "choices"); links.appendChild(colorOptions("clothingBaseColor")); - el.appendChild(links); } } @@ -106,9 +91,9 @@ App.UI.SlaveInteract.wardrobe = function(slave) { } function collar() { - let el = document.createElement('div'); + const el = document.createElement('div'); - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Collar: `); let choice = App.UI.DOM.disabledLink(`${slave.collar}`, [clothTooltip(`${slave.collar}`)]); @@ -119,7 +104,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { if (slave.collar !== `none`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: ` None`, updateSlave: {collar: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "collar", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "collar", false)); } el.appendChild(label); @@ -127,25 +112,18 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let niceOptionsArray = []; let harshOptionsArray = []; - let clothingOption; - // Nice collar - App.Data.slaveWear.niceCollars.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {collar: item.value}, - FS: item.fs + for (const [key, object] of App.Data.slaveWear.collars) { + const reshapedItem = { + text: object.name, + updateSlave: {collar: key}, + FS: object.fs, }; - niceOptionsArray.push(clothingOption); - }); - // Harsh collar - App.Data.slaveWear.harshCollars.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {collar: item.value}, - FS: item.fs - }; - harshOptionsArray.push(clothingOption); - }); + if (object.harsh) { + harshOptionsArray.push(reshapedItem); + } else { + niceOptionsArray.push(reshapedItem); + } + } // Sort niceOptionsArray = niceOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); @@ -155,23 +133,23 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let links = document.createElement('div'); links.className = "choices"; links.append(`Nice: `); - links.appendChild(App.UI.SlaveInteract.generateRows(niceOptionsArray, slave, "collar", true, refresh)); + links.appendChild(generateRows(niceOptionsArray, "collar", true)); el.appendChild(links); // Harsh options links = document.createElement('div'); links.className = "choices"; links.append(`Harsh: `); - links.appendChild(App.UI.SlaveInteract.generateRows(harshOptionsArray, slave, "collar", true, refresh)); + links.appendChild(generateRows(harshOptionsArray, "collar", true)); el.appendChild(links); return el; } function mask() { - let el = document.createElement('div'); + const el = document.createElement('div'); - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Mask: `); let choice = App.UI.DOM.disabledLink(`${slave.faceAccessory} `, [clothTooltip(`${slave.faceAccessory}`)]); @@ -182,29 +160,28 @@ App.UI.SlaveInteract.wardrobe = function(slave) { if (slave.faceAccessory !== `none`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: ` None`, updateSlave: {faceAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "faceAccessory", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "faceAccessory", false)); } el.appendChild(label); let array = []; - let clothingOption; - App.Data.slaveWear.faceAccessory.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {faceAccessory: item.value}, - FS: item.fs + for (const [key, object] of App.Data.slaveWear.faceAccessory) { + const reshapedItem = { + text: object.name, + updateSlave: {faceAccessory: key}, + FS: object.fs, }; - array.push(clothingOption); - }); + array.push(reshapedItem); + } // Sort array = array.sort((a, b) => (a.text > b.text) ? 1 : -1); let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "faceAccessory", true, refresh)); + links.appendChild(generateRows(array, "faceAccessory", true)); el.appendChild(links); if (slave.eyewear === "corrective glasses" || slave.eyewear === "glasses" || slave.eyewear === "blurring glasses" || slave.faceAccessory === "porcelain mask") { @@ -224,9 +201,9 @@ App.UI.SlaveInteract.wardrobe = function(slave) { } function mouth() { - let el = document.createElement('div'); + const el = document.createElement('div'); - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Gag: `); let choice = App.UI.DOM.disabledLink(`${slave.mouthAccessory}`, [clothTooltip(`${slave.mouthAccessory}`)]); @@ -237,40 +214,38 @@ App.UI.SlaveInteract.wardrobe = function(slave) { if (slave.mouthAccessory !== `none`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: ` None`, updateSlave: {mouthAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "mouthAccessory", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "mouthAccessory", false)); } el.appendChild(label); let array = []; - let clothingOption; - // mouthAccessory - App.Data.slaveWear.mouthAccessory.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {mouthAccessory: item.value}, - FS: item.fs + for (const [key, object] of App.Data.slaveWear.mouthAccessory) { + const reshapedItem = { + text: object.name, + updateSlave: {mouthAccessory: key}, + FS: object.fs, }; - array.push(clothingOption); - }); + array.push(reshapedItem); + } // Sort array = array.sort((a, b) => (a.text > b.text) ? 1 : -1); let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "mouthAccessory", true, refresh)); + links.appendChild(generateRows(array, "mouthAccessory", true)); el.appendChild(links); return el; } function armAccessory() { - let el = document.createElement('div'); + const el = document.createElement('div'); // App.Desc.armwear(slave) - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Arm accessory: `); let choice = App.UI.DOM.disabledLink(`${slave.armAccessory}`, [clothTooltip(`${slave.armAccessory}`)]); @@ -282,7 +257,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Choose her own if (slave.armAccessory !== "none") { array.push({text: ` None`, updateSlave: {armAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "armAccessory", false, refresh)); + label.appendChild(generateRows(array, "armAccessory", false)); } el.appendChild(label); @@ -293,16 +268,16 @@ App.UI.SlaveInteract.wardrobe = function(slave) { {text: "Hand gloves", updateSlave: {armAccessory: "hand gloves"}}, {text: "Elbow gloves", updateSlave: {armAccessory: "elbow gloves"}} ]; - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "armAccessory", false, refresh)); + links.appendChild(generateRows(array, "armAccessory", false)); el.appendChild(links); return el; } function shoes() { - let el = document.createElement('div'); + const el = document.createElement('div'); - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Shoes: `); let choice = App.UI.DOM.disabledLink(`${slave.shoes}`, [clothTooltip(`${slave.shoes}`)]); @@ -314,22 +289,21 @@ App.UI.SlaveInteract.wardrobe = function(slave) { if (slave.shoes !== `none`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: `None`, updateSlave: {shoes: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "shoes", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "shoes", false)); } */ el.appendChild(label); let optionsArray = []; - let clothingOption; - App.Data.slaveWear.shoes.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {shoes: item.value}, - FS: item.fs + for (const [key, object] of App.Data.slaveWear.shoes) { + const reshapedItem = { + text: object.name, + updateSlave: {shoes: key}, + FS: object.fs, }; - optionsArray.push(clothingOption); - }); + optionsArray.push(reshapedItem); + } // Sort // No sort here since we want light -> advanced. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); @@ -337,7 +311,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Options let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "shoes", true, refresh)); + links.appendChild(generateRows(optionsArray, "shoes", true)); el.appendChild(links); if (V.seeImages === 1 && V.imageChoice === 1 && slave.shoes !== "none") { @@ -353,12 +327,12 @@ App.UI.SlaveInteract.wardrobe = function(slave) { } function legAccessory() { - let el = document.createElement('div'); + const el = document.createElement('div'); - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Leg accessory: `); - let choice = App.UI.DOM.disabledLink(`${slave.legAccessory}`, [clothTooltip(`${slave.legAccessory}`)]); + const choice = App.UI.DOM.disabledLink(`${slave.legAccessory}`, [clothTooltip(`${slave.legAccessory}`)]); choice.style.fontWeight = "bold"; label.appendChild(choice); @@ -367,7 +341,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Choose her own if (slave.legAccessory !== "none") { array.push({text: ` None`, updateSlave: {legAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "legAccessory", false, refresh)); + label.appendChild(generateRows(array, "legAccessory", false)); } el.appendChild(label); @@ -378,7 +352,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { {text: "Short stockings", updateSlave: {legAccessory: "short stockings"}}, {text: "Long stockings", updateSlave: {legAccessory: "long stockings"}} ]; - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "legAccessory", false, refresh)); + links.appendChild(generateRows(array, "legAccessory", false)); el.appendChild(links); return el; @@ -390,18 +364,19 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let optionsArray = []; - let clothingOption; - App.Data.slaveWear.bellyAccessories.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {bellyAccessory: item.value}, - FS: item.fs - }; - if (item.value !== "none") { + for (const [key, object] of App.Data.slaveWear.bellyAccessories) { + if (key === "none") { // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); + continue; } - }); + const reshapedItem = { + text: object.name, + updateSlave: {bellyAccessory: key}, + FS: object.fs, + }; + optionsArray.push(reshapedItem); + } + // Sort // No sort here since we want small -> large.optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); @@ -416,7 +391,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Choose her own if (slave.bellyAccessory !== `none`) { - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "bellyAccessory", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "bellyAccessory", false)); } el.appendChild(label); @@ -424,7 +399,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Options let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "bellyAccessory", true, refresh)); + links.appendChild(generateRows(optionsArray, "bellyAccessory", true)); if (slave.pregKnown === 1) { let note = document.createElement('span'); note.className = "note"; @@ -438,9 +413,9 @@ App.UI.SlaveInteract.wardrobe = function(slave) { function buttplug() { // App.Desc.buttplug(slave) - let el = document.createElement('div'); + const el = document.createElement('div'); - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Anal accessory: `); let choice = App.UI.DOM.disabledLink(`${slave.buttplug}`, [clothTooltip(`${slave.buttplug}`)]); @@ -450,24 +425,24 @@ App.UI.SlaveInteract.wardrobe = function(slave) { if (slave.buttplug !== `none`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: ` None`, updateSlave: {buttplug: `none`, buttplugAttachment: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "buttplug", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "buttplug", false)); } el.appendChild(label); let optionsArray = []; - let clothingOption; - App.Data.slaveWear.buttplugs.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {buttplug: item.value}, - FS: item.fs - }; - if (item.value !== "none") { + for (const [key, object] of App.Data.slaveWear.buttplugs) { + if (key === "none") { // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); + continue; } - }); + const reshapedItem = { + text: object.name, + updateSlave: {buttplug: key}, + FS: object.fs, + }; + optionsArray.push(reshapedItem); + } // Sort // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); @@ -475,46 +450,46 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Options let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "buttplug", true, refresh)); + links.appendChild(generateRows(optionsArray, "buttplug", true)); el.appendChild(links); return el; } function buttplugAttachment() { - let el = document.createElement('div'); + const el = document.createElement('div'); if (slave.buttplug === "none") { return el; } - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Anal accessory attachment: `); - let choice = App.UI.DOM.disabledLink(`${slave.buttplugAttachment}`, [clothTooltip(`${slave.buttplugAttachment}`)]); + const choice = App.UI.DOM.disabledLink(`${slave.buttplugAttachment}`, [clothTooltip(`${slave.buttplugAttachment}`)]); choice.style.fontWeight = "bold"; label.appendChild(choice); if (slave.buttplugAttachment !== `none`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: ` None`, updateSlave: {buttplugAttachment: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "buttplugAttachment", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "buttplugAttachment", false)); } el.appendChild(label); let optionsArray = []; - let clothingOption; - App.Data.slaveWear.buttplugAttachments.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {buttplugAttachment: item.value}, - FS: item.fs - }; - if (item.value !== "none") { + for (const [key, object] of App.Data.slaveWear.buttplugAttachment) { + if (key === "none") { // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); + continue; } - }); + const reshapedItem = { + text: object.name, + updateSlave: {buttplugAttachment: key}, + FS: object.fs, + }; + optionsArray.push(reshapedItem); + } // Sort optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); @@ -522,7 +497,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Options let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "buttplugAttachment", true, refresh)); + links.appendChild(generateRows(optionsArray, "buttplugAttachment", true)); el.appendChild(links); return el; @@ -531,9 +506,9 @@ App.UI.SlaveInteract.wardrobe = function(slave) { function vaginalAccessory() { // <<vaginalAccessoryDescription>> - let el = document.createElement('div'); + const el = document.createElement('div'); - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Vaginal accessory: `); let choice = App.UI.DOM.disabledLink(`${slave.vaginalAccessory}`, [clothTooltip(`${slave.vaginalAccessory}`)]); @@ -543,24 +518,24 @@ App.UI.SlaveInteract.wardrobe = function(slave) { if (slave.vaginalAccessory !== `none`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: ` None`, updateSlave: {vaginalAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "vaginalAccessory", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "vaginalAccessory", false)); } el.appendChild(label); let optionsArray = []; - let clothingOption; - App.Data.slaveWear.vaginalAccessories.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {vaginalAccessory: item.value}, - FS: item.fs - }; - if (item.value !== "none") { + for (const [key, object] of App.Data.slaveWear.vaginalAccessories) { + if (key === "none") { // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); + continue; } - }); + const reshapedItem = { + text: object.name, + updateSlave: {vaginalAccessory: key}, + FS: object.fs, + }; + optionsArray.push(reshapedItem); + } // Sort // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); @@ -568,7 +543,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Options let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "vaginalAccessory", true, refresh)); + links.appendChild(generateRows(optionsArray, "vaginalAccessory", true)); el.appendChild(links); return el; @@ -590,24 +565,24 @@ App.UI.SlaveInteract.wardrobe = function(slave) { if (slave.vaginalAttachment !== `none`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: ` None`, updateSlave: {vaginalAttachment: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "vaginalAttachment", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "vaginalAttachment", false)); } el.appendChild(label); let optionsArray = []; - let clothingOption; - App.Data.slaveWear.vaginalAttachments.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {vaginalAttachment: item.value}, - FS: item.fs - }; - if (item.value !== "none") { + for (const [key, object] of App.Data.slaveWear.vaginalAttachments) { + if (key === "none") { // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); + continue; } - }); + const reshapedItem = { + text: object.name, + updateSlave: {vaginalAttachments: key}, + FS: object.fs, + }; + optionsArray.push(reshapedItem); + } // Sort optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); @@ -615,43 +590,43 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Options let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "vaginalAttachment", true, refresh)); + links.appendChild(generateRows(optionsArray, "vaginalAttachment", true)); el.appendChild(links); return el; } function dickAccessory() { - let el = document.createElement('div'); + const el = document.createElement('div'); - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Dick accessory: `); - let choice = App.UI.DOM.disabledLink(`${slave.dickAccessory}`, [clothTooltip(`${slave.dickAccessory}`)]); + const choice = App.UI.DOM.disabledLink(`${slave.dickAccessory}`, [clothTooltip(`${slave.dickAccessory}`)]); choice.style.fontWeight = "bold"; label.appendChild(choice); if (slave.dickAccessory !== `none`) { let choiceOptionsArray = []; choiceOptionsArray.push({text: ` None`, updateSlave: {dickAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "dickAccessory", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "dickAccessory", false)); } el.appendChild(label); let optionsArray = []; - let clothingOption; - App.Data.slaveWear.dickAccessories.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {dickAccessory: item.value}, - FS: item.fs - }; - if (item.value !== "none") { + for (const [key, object] of App.Data.slaveWear.dickAccessories) { + if (key === "none") { // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); + continue; } - }); + const reshapedItem = { + text: object.name, + updateSlave: {dickAccessory: key}, + FS: object.fs, + }; + optionsArray.push(reshapedItem); + } // Sort // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); @@ -659,16 +634,16 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Options let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "dickAccessory", true, refresh)); + links.appendChild(generateRows(optionsArray, "dickAccessory", true)); el.appendChild(links); return el; } function chastity() { - let el = document.createElement('div'); + const el = document.createElement('div'); - let label = document.createElement('div'); + const label = document.createElement('div'); label.append(`Chastity devices: `); let chasCho = ""; @@ -709,25 +684,26 @@ App.UI.SlaveInteract.wardrobe = function(slave) { chastityVagina: 0 } }); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "chastity", false, refresh)); + label.appendChild(generateRows(choiceOptionsArray, "chastity", false)); } el.appendChild(label); let optionsArray = []; - let clothingOption; - App.Data.slaveWear.chastityDevices.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {}, - FS: item.fs - }; - Object.assign(clothingOption.updateSlave, item.updateSlave); - if (item.value !== "none") { + for (const [key, object] of App.Data.slaveWear.chastityDevices) { + if (key === "none") { // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); + continue; } - }); + const reshapedItem = { + text: object.name, + updateSlave: {}, + FS: object.fs, + }; + Object.assign(reshapedItem.updateSlave, object.updateSlave); + optionsArray.push(reshapedItem); + } + // Sort // skip sort for this one too. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); @@ -735,7 +711,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { // Options let links = document.createElement('div'); links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "chastity", true, refresh)); + links.appendChild(generateRows(optionsArray, "chastity", true)); el.appendChild(links); return el; @@ -753,8 +729,8 @@ App.UI.SlaveInteract.wardrobe = function(slave) { * @returns {Node} */ function colorOptions(update) { - let el = new DocumentFragment(); - let colorChoice = App.UI.DOM.colorInput( + const el = new DocumentFragment(); + const colorChoice = App.UI.DOM.colorInput( slave[update], v => { slave[update] = v; @@ -785,7 +761,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { /** * Figure out a tooltip text to use based on clothing name. * Described effects are mainly from saClothes.js some are from saLongTermMentalEffects.js or saLongTermPhysicalEffects.js - * Potential fetish relevations are not mentioned. + * Potential fetish revelations are not mentioned. * Chastity options could mention that at least fucktoys can appreciate maintaining their virginity but I assume just choosing a hole to focus on has the same effect so it's not really a clothing effect. * what's the word for below 20 devotion slaves? Disobedient? * Also accepting is a bit weird for ones above, I think I've seen obedient being used instead. @@ -889,7 +865,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { case "a medium empathy belly": case "a large empathy belly": case "a huge empathy belly": - return Cloth + " strenghtens or removes(a weak) pregnancy fetish and affects devotion in various ways depending on devotion, fertility and having a pregnancy fetish or breeder flaw."; + return Cloth + " 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."; case "bullet vibrator": return Cloth + " increases devotion but weakens fetish and libido."; @@ -898,7 +874,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { case "dildo": return Cloth + " stretches vagina from virgin to tight, might remove hatred of penetration."; case "long dildo": - return Cloth + " stretches vagina from virging to tight, might remove hatred of penetration. Makes size queens happy while others less trusting."; + return Cloth + " stretches vagina from virgin to tight, might remove hatred of penetration. Makes size queens happy while others less trusting."; case "large dildo": case "long, large dildo": return Cloth + " stretches vagina into a loose one, on a tight vagina increases obedience and fear."; @@ -914,7 +890,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { case "plug": return Cloth + " stretches butthole from virgin to tight, might remove hatred of anal."; case "long plug": - return Cloth + " stretches vagina from virging to tight, might remove hatred of penetration. Makes size queens happy."; + return Cloth + " stretches vagina from virgin to tight, might remove hatred of penetration. Makes size queens happy."; case "large plug": case "long, large plug": return Cloth + " stretches vagina into a loose one, on a tight vagina increases obedience and fear."; @@ -955,16 +931,19 @@ App.UI.SlaveInteract.wardrobe = function(slave) { /* assuming nice clothes, could actually add some sort of check to make sure. */ /* which clothes have these is decided in miscData.js */ let clothTooltip = Cloth + ""; - if (setup.humiliatingClothes.includes(cloth)) { - clothTooltip += ", it's humiliating"; - } - if (setup.sluttyClothes.includes(cloth)) { - clothTooltip += ", it's slutty"; + switch (App.Data.clothes.get(slave.clothes).exposure) { + case 3: + clothTooltip += ", it's humiliating"; + break; + case 2: + clothTooltip += ", it's slutty"; + break; + case 0: + clothTooltip += ", it's modest"; + break; } - if (setup.modestClothes.includes(cloth)) { - clothTooltip += ", it's modest"; - } - if (clothTooltip === Cloth + "") { + + if (clothTooltip === Cloth + "") { clothTooltip += ", it's only nice(meaning non-obedients lose devotion and fear while obedients gain devotion and trust)."; } clothTooltip += "."; @@ -972,4 +951,75 @@ App.UI.SlaveInteract.wardrobe = function(slave) { } } } + /** @typedef RowItem + * @type {object} + * @property {FC.FutureSociety} [FS] - FS requirement, if any + * @property {string} [text] - link text + * @property {object} [updateSlave] - properties to be merged onto the slave + * @property {object} [update] - properties to be merged into global state + * @property {string} [note] + * @property {string} [slutty] + * @property {string} [humiliating] + */ + + /** Generate a row of choices + * @param {RowItem[]} array + * @param {string} [category] - should be in the form of slave.category, the thing we want to update. + * @param {boolean} [accessCheck=false] + * @returns {HTMLUListElement} + */ + function generateRows(array, category, accessCheck = false) { + const linkArray = []; + for (const item of array) { + let link; + // Some items will never be in App.Data.slaveWear, especially "none" if it falls in between harsh and nice data sets. Trying to look it up would cause an error, which is what access check works around. + const itemName = (category === "chastity") ? item.text.toLowerCase() : item.updateSlave[category]; // Yucky. Category name does not match for chastity (since it sets multiple kinds of chastity at once). Compare using a lowercase name instead. + const unlocked = (accessCheck === true) ? isItemAccessible.entry(itemName, category, slave) : false; + if (accessCheck === false || unlocked) { + if (typeof unlocked === 'string') { // is it just text? + link = App.UI.DOM.disabledLink(item.text, [unlocked]); + } else { + link = document.createElement('span'); + + // Set up the link + link.appendChild( + App.UI.DOM.link( + `${item.text} `, + () => { click(item); }, + [], + "", + clothTooltip(itemName) + ) + ); + + if (item.FS) { + let FS = App.UI.DOM.disabledLink(`FS`, [FutureSocieties.displayAdj(item.FS)]); + FS.style.fontStyle = "italic"; + link.appendChild(FS); + } + + // add a note node if required + if (item.note) { + link.appendChild(App.UI.DOM.makeElement('span', ` ${item.note}`, 'note')); + } + } + linkArray.push(link); + } + } + + return App.UI.DOM.generateLinksStrip(linkArray); + + /** @param {RowItem} arrayOption */ + function click(arrayOption) { + if (arrayOption.updateSlave) { + for (const slaveProperty in arrayOption.updateSlave) { + _.set(slave, slaveProperty, arrayOption.updateSlave[slaveProperty]); + } + } + if (arrayOption.update) { + Object.assign(V, arrayOption.update); + } + refresh(); + } + } }; diff --git a/src/js/eventSelectionJS.js b/src/js/eventSelectionJS.js index 7a00f5433c4aabedea6a2bb705ce690216ac285b..f499e6bbae627abe658d7a6cf3658ea320beaf01 100644 --- a/src/js/eventSelectionJS.js +++ b/src/js/eventSelectionJS.js @@ -618,7 +618,7 @@ globalThis.generateRandomEventPoolStandard = function(eventSlave) { if (eventSlave.trust > 20) { if (eventSlave.rules.speech !== "restrictive") { if (eventSlave.choosesOwnClothes !== 1) { - if (setup.modestClothes.includes(eventSlave.clothes)) { + if (App.Data.clothes.get(eventSlave.clothes).exposure === 0) { V.RESSevent.push("modest clothes"); } } diff --git a/src/js/itemAvailability.js b/src/js/itemAvailability.js index f0c5fc0cb1f13e86ed1266dd6d4e060240306d8a..1a23c13bead242b88d7c04815a8a1ee07f40ad03 100644 --- a/src/js/itemAvailability.js +++ b/src/js/itemAvailability.js @@ -15,51 +15,45 @@ globalThis.isItemAccessible = (function() { if (V.cheatMode === 1) { return true; } - let niceDB = []; - let harshDB = []; + let selectedDB; switch (category) { case "clothing": case "clothes": - niceDB = App.Data.slaveWear.niceClothes; - harshDB = App.Data.slaveWear.harshClothes; + selectedDB = App.Data.clothes; break; case "collar": - niceDB = App.Data.slaveWear.niceCollars; - harshDB = App.Data.slaveWear.harshCollars; + selectedDB = App.Data.slaveWear.collars; break; case "bellyAccessory": - niceDB = App.Data.slaveWear.bellyAccessories; + selectedDB = App.Data.slaveWear.bellyAccessories; break; case "buttplug": - niceDB = App.Data.slaveWear.buttplugs; + selectedDB = App.Data.slaveWear.buttplugs; break; case "buttplugAttachment": - niceDB = App.Data.slaveWear.buttplugAttachments; + selectedDB = App.Data.slaveWear.buttplugAttachments; break; case "vaginalAccessory": - niceDB = App.Data.slaveWear.vaginalAccessories; + selectedDB = App.Data.slaveWear.vaginalAccessories; break; case "vaginalAttachment": - niceDB = App.Data.slaveWear.vaginalAttachments; + selectedDB = App.Data.slaveWear.vaginalAttachments; break; case "dickAccessory": - niceDB = App.Data.slaveWear.vaginalAccessories; + selectedDB = App.Data.slaveWear.dickAccessories; break; case "shoes": - niceDB = App.Data.slaveWear.shoes; + selectedDB = App.Data.slaveWear.shoes; break; case "chastity": - niceDB = App.Data.slaveWear.chastityDevices; + selectedDB = App.Data.slaveWear.chastityDevices; break; default: console.log(`made a category for ${category} automatically, may need to define this by hand`); - niceDB = App.Data.slaveWear[category]; + selectedDB = App.Data.slaveWear[category]; break; } - let item = niceDB.find((i) => i.value === string); - if (!item && (typeof harshDB !== 'undefined')) { - item = harshDB.find((i) => i.value === string); - } + const item = selectedDB.get(string); if (!item) { console.log(`${string} is not a registered piece of clothing! Check App.Data.slaveWear.${category}`); return false; /* couldn't be found */ @@ -68,20 +62,22 @@ globalThis.isItemAccessible = (function() { } /** * Returns array of wearable clothing in format [name, value], basically player facing / game data. - * @param {Array} db Array to look in (such as App.Data.slaveWear.niceClothes) + * @param {Map} map Map to look in (such as App.Data.clothes) + * @param {string} [filter] for example, if we want to filer clothing data by the "harsh" property, pass harsh as the parameter here. + * @param {any} [filterValue] remove any clothing where the .filter property does not match this value. Function will evaluate undefined as false. * @returns {Array} */ - function array(db) { + function array(map, filter, filterValue) { const array = []; - db.forEach((i) => { - if (V.cheatMode || isAvailable(i)) { - let name = i.name; - if (i.fs) { - name = `${i.name} (FS)`; - } - array.push([name, i.value]); + for (const [key, obj] of map) { + if (filter && filterValue !== (obj[filter] || false)) { + continue; } - }); + if (V.cheatMode || isAvailable(obj)) { + const name = (obj.fs) ? `${obj.name} (FS)` : obj.name; + array.push([name, obj.value]); + } + } return array; } diff --git a/src/js/rulesAssistantOptions.js b/src/js/rulesAssistantOptions.js index ccc8b24aa8fafc3d015748080a818e4239f2212b..084ea51d06e2220cd9c20c1cf637a6927c7576f7 100644 --- a/src/js/rulesAssistantOptions.js +++ b/src/js/rulesAssistantOptions.js @@ -1806,11 +1806,11 @@ globalThis.rulesAssistantOptions = (function() { ]; super("Clothes", items); - const nClothes = isItemAccessible.array(App.Data.slaveWear.niceClothes); + const nClothes = isItemAccessible.array(App.Data.clothes, "harsh", false); nClothes.sort(function(a, b) { if (a[0] < b[0]) { return -1; } if (a[0] > b[0]) { return 1; } return 0; }); this._nice = new ListSubSection(this, "Nice", nClothes); - const hClothes = isItemAccessible.array(App.Data.slaveWear.harshClothes); + const hClothes = isItemAccessible.array(App.Data.clothes, "harsh", true); hClothes.sort(function(a, b) { if (a[0] < b[0]) { return -1; } if (a[0] > b[0]) { return 1; } return 0; }); this._harsh = new ListSubSection(this, "Harsh", hClothes); @@ -1833,11 +1833,11 @@ globalThis.rulesAssistantOptions = (function() { ]; super("Collar", items); - const niceCollars = isItemAccessible.array(App.Data.slaveWear.niceCollars); + const niceCollars = isItemAccessible.array(App.Data.slaveWear.collars, "harsh", false); niceCollars.sort(function(a, b) { if (a[0] < b[0]) { return -1; } if (a[0] > b[0]) { return 1; } return 0; }); this._nice = new ListSubSection(this, "Nice", niceCollars); - const harshCollars = isItemAccessible.array(App.Data.slaveWear.harshCollars); + const harshCollars = isItemAccessible.array(App.Data.slaveWear.collars, "harsh", true); harshCollars.sort(function(a, b) { if (a[0] < b[0]) { return -1; } if (a[0] > b[0]) { return 1; } return 0; }); this._harsh = new ListSubSection(this, "Harsh", harshCollars); diff --git a/src/js/statsChecker/statsChecker.js b/src/js/statsChecker/statsChecker.js index 461e30fdb1421aad863e3782e08c782694da47d0..4c94e5f40860ef9dda5431f208eab3e8fae95033 100644 --- a/src/js/statsChecker/statsChecker.js +++ b/src/js/statsChecker/statsChecker.js @@ -472,7 +472,7 @@ globalThis.bimboScore = function(slave) { if (slave.skin === "sun tanned" || slave.skin === "spray tanned") { degree++; } - if (setup.sluttyClothes.includes(slave.clothes)) { + if (App.Data.clothes.get(slave.clothes).exposure === 2) { degree++; } diff --git a/src/js/utilsFC.js b/src/js/utilsFC.js index 779c965102fff7ef801041666187948cecb7d077..ff6d0c4e524222a00017bf18f4d4e6397c2e8f64 100644 --- a/src/js/utilsFC.js +++ b/src/js/utilsFC.js @@ -3084,3 +3084,4 @@ App.Utils.alphabetizeIterable = function(iterable) { const clonedArray = (Array.from(iterable)); return clonedArray.sort(compare); }; +