code:
/**
 * @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} clothingDescription
 * @property {function(App.Entity.SlaveState):string} [summary] General description of the outfit, tailored to the slave, but not hyper focused on a body part like boobs or butt.
 * @property {function(App.Entity.SlaveState):string} [upperFace]
 * @property {function(App.Entity.SlaveState):string} [hStyle]
 * @property {function(App.Entity.SlaveState):string} [earPiercing]
 * @property {function(App.Entity.SlaveState):string} [corsetPiercing]
 * @property {function(App.Entity.SlaveState):string} [bellyImplant]
 * @property {function(App.Entity.SlaveState):string} [belly]
 * @property {function(App.Entity.SlaveState):string} [inflation]
 * @property {function(App.Entity.SlaveState):string} [crotch]
 * @property {function(App.Entity.SlaveState):string} [butt]
 * @property {function(App.Entity.SlaveState):string} [buttplug]
 * @property {function(App.Entity.SlaveState):string} [clothingCorset]
 * @property {function(App.Entity.SlaveState):string} [boobs]
 */

/**
 * @typedef {object} clothes
 * @property {string} name
 * @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]
 * @property {boolean} [topless]
 * @property {boolean} [fuckdoll]
 * @property {string} [note]
 * @property {clothingDescription} [desc]
 */

/** @type {Map.<FC.Clothes, clothes>} The string here will be what is applied to the relevant slave property. Slave.clothes = "a bunny outfit", not "Bunny outfit".*/
App.Data.clothes = (new Map())
	.set("a Fuckdoll suit",
		{
			name: "Fuckdoll suit",
			exposure: 3,
			fuckdoll: true
		}
	)
	.set("attractive lingerie for a pregnant woman",
		{
			name: "Maternity lingerie",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSIntellectualDependency", "FSRepopulationFocus"]),
			},
			get requirements() { return V.boughtItem.clothing.maternityLingerie === 1; },
			exposure: 2
		}
	)
	.set("a bunny outfit",
		{
			name: "Bunny outfit",
			fs: {
				unlocks: "FSGenderFundamentalist",
				loves: new Set(["FSGenderFundamentalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.bunny === 1; },
			exposure: 1
		}
	)
	.set("body oil",
		{
			name: "Body oil",
			fs: {
				unlocks: "FSPhysicalIdealist",
				loves: new Set(["FSPhysicalIdealist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.oil === 1; },
			exposure: 4
		}
	)
	.set("a chattel habit",
		{
			name: "Chattel habit",
			fs: {
				unlocks: "FSChattelReligionist",
				loves: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.habit === 1; },
			exposure: 3
		}
	)
	.set("conservative clothing",
		{
			name: "Conservative clothing",
			fs: {
				unlocks: "FSPaternalist",
				loves: new Set(["FSPaternalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.conservative === 1; },
			exposure: 0
		}
	)
	.set("harem gauze",
		{
			name: "Harem gauze",
			fs: {
				unlocks: "FSArabianRevivalist",
				loves: new Set(["FSArabianRevivalist"]),
			},
			get requirements() { return V.boughtItem.clothing.harem === 1; },
			exposure: 1
		}
	)
	.set("a huipil",
		{
			name: "Huipil",
			fs: {
				unlocks: "FSAztecRevivalist",
				loves: new Set(["FSAztecRevivalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.huipil === 1; },
			exposure: 0
		}
	)
	.set("a kimono",
		{
			name: "Kimono",
			fs: {
				unlocks: "FSEdoRevivalist",
				loves: new Set(["FSEdoRevivalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return (V.boughtItem.clothing.kimono === 1 || V.continent === "Japan"); },
			exposure: 0
		}
	)
	.set("a maternity dress",
		{
			name: "Maternity dress",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"]),
			},
			get requirements() { return V.boughtItem.clothing.maternityDress === 1; },
			exposure: 0,
		}
	)
	.set("a slutty qipao",
		{
			name: "Qipao (slutty)",
			fs: {
				unlocks: "FSChineseRevivalist",
				loves: new Set(["FSChineseRevivalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.qipao === 1; },
			exposure: 2
		}
	)
	.set("a long qipao",
		{
			name: "Qipao (long)",
			fs: {
				unlocks: "FSChineseRevivalist",
				loves: new Set(["FSChineseRevivalist"]),
			},
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("Imperial Plate",
		{
			name: "Imperial Plate",
			fs: {
				unlocks: "FSNeoImperialist",
				loves: new Set(["FSNeoImperialist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.imperialarmor === 1; },
			exposure: 0
		}
	)
	.set("a tight Imperial bodysuit",
		{
			name: "Imperial Bodysuit",
			fs: {
				unlocks: "FSNeoImperialist",
				loves: new Set(["FSNeoImperialist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.imperialsuit === 1; },
			exposure: 2
		}
	)
	.set("stretch pants and a crop-top",
		{
			name: "Stretch pants and a crop-top",
			fs: {unlocks: "FSHedonisticDecadence"},
			get requirements() { return V.boughtItem.clothing.lazyClothes === 1; },
			exposure: 0
		}
	)
	.set("a toga",
		{
			name: "Toga",
			fs: {
				unlocks: "FSRomanRevivalist",
				loves: new Set(["FSRomanRevivalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.toga === 1; },
			exposure: 1
		}
	)
	.set("Western clothing",
		{
			name: "Western clothing",
			fs: {
				unlocks: "FSPastoralist",
				loves: new Set(["FSPastoralist"]),
			},
			get requirements() { return V.boughtItem.clothing.western === 1; },
			exposure: 3
		}
	)
	.set("a courtesan dress",
		{
			name: "Courtesan dress",
			fs: {
				unlocks: "FSSlaveProfessionalism",
				loves: new Set(["FSSlaveProfessionalism"]),
			},
			get requirements() { return V.boughtItem.clothing.courtesan === 1; },
			exposure: 1
		}
	)
	.set("a bimbo outfit",
		{
			name: "Bimbo outfit",
			fs: {
				unlocks: "FSIntellectualDependency",
				loves: new Set(["FSIntellectualDependency"]),
			},
			get requirements() { return V.boughtItem.clothing.bimbo === 1; },
			exposure: 2
		}
	)
	.set("petite admi outfit",
		{
			name: "Petite admi outfit",
			fs: {
				unlocks: "FSPetiteAdmiration",
				loves: new Set(["FSPetiteAdmiration"]),
			},
			get requirements() { return V.boughtItem.clothing.petite === 1; },
			exposure: 0
		}
	)
	.set("battlearmor",
		{
			name: "Battlearmor",
			get requirements() { return V.boughtItem.clothing.military === 1; },
			exposure: 0
		}
	)
	.set("a military uniform",
		{
			name: "Military uniform",
			fs: {
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.military === 1; },
			exposure: 0
		}
	)
	.set("a red army uniform",
		{
			name: "Red Army uniform",
			get requirements() { return V.boughtItem.clothing.military === 1; },
			exposure: 0
		}
	)
	.set("battledress",
		{
			name: "Battledress",
			get requirements() { return V.boughtItem.clothing.military === 1; },
			exposure: 0
		}
	)
	.set("a biyelgee costume",
		{
			name: "Biyelgee costume",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("a dirndl",
		{
			name: "Dirndl",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("lederhosen",
		{
			name: "Lederhosen",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("a mounty outfit",
		{
			name: "Mounty outfit",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("a hanbok",
		{
			name: "Hanbok",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("a burqa",
		{
			name: "Burqa",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.middleEastern === 1 || V.continent === "the Middle East"; },
			exposure: 0
		}
	)
	.set("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
		}
	)
	.set("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
		}
	)
	.set("a burkini",
		{
			name: "Burkini",
			get requirements() { return V.boughtItem.clothing.swimwear === 1 && (V.boughtItem.clothing.swimwear === 1 || V.continent === "the Middle East"); },
			exposure: 1
		}
	)
	.set("a Santa dress",
		{
			name: "Santa dress",
			get requirements() { return V.boughtItem.clothing.costume === 1; },
			exposure: 2
		}
	)
	.set("a klan robe",
		{
			name: "Klan robe",
			get requirements() { return V.boughtItem.clothing.pol === 1; },
			exposure: 0
		}
	)
	.set("a slutty klan robe",
		{
			name: "Slutty klan robe",
			get requirements() { return V.boughtItem.clothing.pol === 1; },
			exposure: 2
		}
	)
	.set("a schutzstaffel uniform",
		{
			name: "Schutzstaffel uniform",
			get requirements() { return V.boughtItem.clothing.pol === 1; },
			exposure: 0
		}
	)
	.set("a slutty schutzstaffel uniform",
		{
			name: "Slutty schutzstaffel uniform",
			get requirements() { return V.boughtItem.clothing.pol === 1; },
			exposure: 2
		}
	)
	.set("nice business attire",
		{
			name: "Nice business attire",
			get requirements() { return V.boughtItem.clothing.career === 1; },
			exposure: 0,
			fs: {
				loves: new Set(["FSMaturityPreferentialist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
		}
	)
	.set("a nice nurse outfit",
		{
			name: "Nurse (nice)",
			fs: {
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.career === 1; },
			exposure: 0
		}
	)
	.set("a police uniform",
		{
			name: "Police uniform",
			get requirements() { return V.boughtItem.clothing.career === 1; },
			exposure: 0
		}
	)
	.set("a nice maid outfit",
		{
			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,
			fs: {
				loves: new Set(["FSMaturityPreferentialist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
		}
	)
	.set("a ball gown",
		{
			name: "Ballgown",
			get requirements() { return V.boughtItem.clothing.dresses === 1; },
			exposure: 0
		}
	)
	.set("a gothic lolita dress",
		{
			name: "Gothic lolita dress",
			get requirements() { return V.boughtItem.clothing.dresses === 1; },
			exposure: 0
		}
	)
	.set("a cybersuit",
		{
			name: "Cybersuit",
			get requirements() { return V.boughtItem.clothing.bodysuits === 1; },
			exposure: 0
		}
	)
	.set("a latex catsuit",
		{
			name: "Latex catsuit",
			get requirements() { return V.boughtItem.clothing.bodysuits === 1; },
			exposure: 1
		}
	)
	.set("a button-up shirt and panties",
		{
			name: "Button-up shirt and panties",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("a button-up shirt",
		{
			name: "Button-up shirt",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("cutoffs",
		{
			name: "Cutoffs",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("jeans",
		{
			name: "Jeans",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2,
			topless: true
		}
	)
	.set("leather pants and a tube top",
		{
			name: "Leather pants and a tube top",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 1
		}
	)
	.set("leather pants",
		{
			name: "Leather pants",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2,
			topless: true
		}
	)
	.set("an oversized t-shirt",
		{
			name: "Oversized t-shirt",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("a sweater and cutoffs",
		{
			name: "Sweater and cutoffs",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 0
		}
	)
	.set("a sweater and panties",
		{
			name: "Sweater and panties",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("a sweater",
		{
			name: "Sweater",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("a t-shirt and jeans",
		{
			name: "T-shirt and jeans",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 0
		}
	)
	.set("a t-shirt and panties",
		{
			name: "T-shirt and panties",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("a t-shirt",
		{
			name: "T-shirt",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("a tank-top and panties",
		{
			name: "Tank-top and panties",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("a tank-top",
		{
			name: "Tank-top",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("a tube top",
		{
			name: "Tube top",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("boyshorts",
		{
			name: "Boyshorts",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 2,
			topless: true
		}
	)
	.set("a bra",
		{
			name: "Bra",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 3
		}
	)
	.set("kitty lingerie",
		{
			name: "Kitty lingerie",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 2
		}
	)
	.set("panties and pasties",
		{
			name: "Panties and pasties",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 2
		}
	)
	.set("a skimpy loincloth",
		{
			name: "Skimpy loincloth",
			fs: {
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 3
		}
	)
	.set("a thong",
		{
			name: "Thong",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 3,
			topless: true
		}
	)
	.set("pasties",
		{
			name: "Pasties",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 3
		}
	)
	.set("leather pants and pasties",
		{
			name: "Leather pants and pasties",
			get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 2,
		}
	)
	.set("a t-shirt and thong",
		{
			name: "T-shirt and thong",
			get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 3,
		}
	)
	.set("a tube top and thong",
		{
			name: "Tube top and thong",
			get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 3,
		}
	)
	.set("an oversized t-shirt and boyshorts",
		{
			name: "Oversized t-shirt and boyshorts",
			get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 0,
		}
	)
	.set("sport shorts and a sports bra",
		{
			name: "Sport shorts and a sports bra",
			get requirements() { return V.boughtItem.clothing.sports === 1; },
			exposure: 1,
		}
	)
	.set("sport shorts",
		{
			name: "Sport shorts",
			get requirements() { return V.boughtItem.clothing.sports === 1; },
			exposure: 2,
			topless: true
		}
	)
	.set("a sports bra",
		{
			name: "Sports bra",
			get requirements() { return V.boughtItem.clothing.sports === 1; },
			exposure: 3
		}
	)
	.set("sport shorts and a t-shirt",
		{
			name: "Sport shorts and a t-shirt",
			get requirements() { return V.boughtItem.clothing.sports === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 0
		}
	)
	.set("a nice pony outfit",
		{
			name: "Pony outfit (nice)",
			get requirements() { return V.boughtItem.clothing.pony === 1; },
			exposure: 1
		}
	)
	.set("a slutty pony outfit",
		{
			name: "Pony outfit (slutty)",
			get requirements() { return V.boughtItem.clothing.pony === 1; },
			exposure: 2
		}
	)
	.set("a monokini",
		{
			name: "Monokini",
			get requirements() { return V.boughtItem.clothing.swimwear === 1; },
			exposure: 3,
			note: "Boob fetishists enjoy."
		}
	)
	.set("a one-piece swimsuit",
		{
			name: "One-piece swimsuit",
			get requirements() { return V.boughtItem.clothing.swimwear === 1; },
			exposure: 1
		}
	)
	.set("a striped bra",
		{
			name: "Striped bra",
			get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; },
			exposure: 3
		}
	)
	.set("striped panties",
		{
			name: "Striped panties",
			get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; },
			exposure: 2,
			topless: true
		}
	)
	.set("striped underwear",
		{
			name: "Striped underwear",
			get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; },
			exposure: 2,
			topless: true
		}
	)

	// "Normal" things:
	.set("an apron",
		{
			name: "Apron",
			exposure: 2,
			note: "Increases just devotion for submissives, humiliation fetishists and visibly pregnant pregnancy fetishists regardless of devotion level."
		}
	)
	.set("slutty jewelry",
		{
			name: "Bangles",
			exposure: 3,
			fs: {loves: new Set(["FSEgyptianRevivalist"])}
		}
	)
	.set("clubslut netting",
		{
			name: "Clubslut netting",
			exposure: 3,
			fs: {loves: new Set(["FSBodyPurist", "FSIntellectualDependency"])},
		}
	)
	.set("cutoffs and a t-shirt",
		{
			name: "Cutoffs and a t-shirt",
			exposure: 0
		}
	)
	.set("a comfortable bodysuit",
		{
			name: "Bodysuit",
			exposure: 1,
			fs: {loves: new Set(["FSBodyPurist"])},
		}
	)
	.set("a cheerleader outfit",
		{
			name: "Cheerleader",
			exposure: 2,
			fs: {loves: new Set(["FSGenderFundamentalist", "FSYouthPreferentialist"])},
		}
	)
	.set("a fallen nuns habit",
		{
			name: "Fallen nun",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			exposure: 3
		}
	)
	.set("a hijab and abaya",
		{
			name: "Hijab and abaya",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			exposure: 0
		}
	)
	.set("a leotard",
		{
			name: "Leotard",
			exposure: 1,
			fs: {loves: new Set(["FSBodyPurist"])},
		}
	)
	.set("a slutty maid outfit",
		{
			name: "Maid (slutty)",
			exposure: 2,
			fs: {loves: new Set(["FSSlaveProfessionalism", "FSIntellectualDependency"])},
		}
	)
	.set("a mini dress",
		{
			name: "Mini dress",
			exposure: 2
		}
	)
	.set("attractive lingerie",
		{
			name: "Nice lingerie",
			exposure: 2
		}
	)
	.set("a slutty nurse outfit",
		{
			name: "Nurse (slutty)",
			exposure: 2
		}
	)
	.set("overalls",
		{
			name: "Overalls",
			exposure: 1
		}
	)
	.set("panties",
		{
			name: "Panties",
			exposure: 2,
			topless: true
		}
	)
	.set("a scalemail bikini",
		{
			name: "Scalemail bikini",
			exposure: 2
		}
	)
	.set("a schoolgirl outfit",
		{
			name: "Schoolgirl",
			exposure: 1,
			fs: {loves: new Set(["FSGenderFundamentalist", "FSYouthPreferentialist"])},
		}
	)
	.set("a slutty outfit",
		{
			name: "Slutty outfit",
			exposure: 2,
			fs: {loves: new Set(["FSIntellectualDependency"])},
		}
	)
	.set("spats and a tank top",
		{
			name: "Spats and a tank top",
			exposure: 0
		}
	)
	.set("a string bikini",
		{
			name: "String bikini",
			exposure: 3,
			fs: {loves: new Set(["FSBodyPurist", "FSIntellectualDependency"])},
		}
	)
	.set("a succubus outfit",
		{
			name: "Succubus costume",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			exposure: 3
		}
	)
	.set("slutty business attire",
		{
			name: "Suit (slutty)",
			exposure: 2,
			fs: {
				loves: new Set(["FSMaturityPreferentialist", "FSSlaveProfessionalism"])
			},
		}
	)
	.set("a halter top dress",
		{
			name: "Haltertop dress",
			exposure: 0,
			fs: {loves: new Set(["FSBodyPurist", "FSSlaveProfessionalism"])},
		}
	)
	.set("chains",
		{
			name: "Chains",
			fs: {
				unlocks: "FSDegradationist",
				loves: new Set(["FSDegradationist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.chains === 1; },
			exposure: 4,
			harsh: true,
			note: "Increases devotion and fear for slaves who are disobedient and not terrified. Masochists who are at least ambivalent gain devotion, may also cause masochism."
		}
	)
	.set("no clothing",
		{
			name: "Naked",
			exposure: 4,
			harsh: true,
			fs: {
				loves: new Set(["FSPhysicalIdealist", "FSIntellectualDependency"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
		}
	)
	.set("a penitent nuns habit",
		{
			name: "Penitent nun",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			exposure: 0,
			harsh: true,
			note: "Increases devotion and fear but damages health, may cause masochism."
		}
	)
	.set("restrictive latex",
		{
			name: "Restrictive latex",
			fs: {loves: new Set(["FSBodyPurist"])},
			exposure: 3,
			harsh: true,
			note: "Increases fear and devotion for resistant slaves and just devotion for obedient, non-terrified submissives."
		}
	)
	.set("shibari ropes",
		{
			name: "Shibari ropes",
			fs: {
				loves: new Set(["FSDegradationist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			exposure: 4,
			harsh: true,
			note: "Increases fear and devotion for resistant slaves and just devotion for obedient, non-terrified submissives."
		}
	)
	.set("uncomfortable straps",
		{
			name: "Uncomfortable straps",
			exposure: 3,
			harsh: true,
			fs: {
				loves: new Set(["FSDegradationist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			note: "Increases devotion and fear for slaves who are disobedient and not terrified. Masochists who are at least ambivalent gain devotion, may also cause masochism."
		}
	);

/**
 * @typedef {object} slaveWear
 * @property {string} name
 * @property {itemFS} [fs]
 * @property {boolean} [requirements]
 * @property {boolean} [harsh]
 * @property {string} [note]
 */

/**
 * @typedef {Map<string, slaveWear>} slaveWearCategory
 */

/** @type {Object.<string, slaveWearCategory>} string should be the slave property being modified.*/
App.Data.slaveWear = {
	collar: 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;
				},
				note: "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."
			}
		],
		["bell collar",
			{
				name: "Bell",
				note: "On non-obedient slaves reduces fear a lot and devotion somewhat."
			},
		],
		["leather with cowbell",
			{
				name: "Cowbell",
				note: "On obedient slaves with boob fetish increases devotion, on disobedient slaves reduces fear a lot and devotion somewhat."
			}
		],
		["bowtie",
			{
				name: "Bowtie collar",
				fs: {
					unlocks: "FSGenderFundamentalist",
					loves: new Set(["FSGenderFundamentalist"]),
				},
				get requirements() {
					return V.boughtItem.clothing.bunny === 1;
				}
			}
		],
		["neck tie",
			{
				name: "Neck tie",
				fs: {
					unlocks: "FSPaternalist",
					loves: new Set(["FSPaternalist"]),
				},
				get requirements() {
					return V.boughtItem.clothing.conservative === 1;
				}
			}
		],
		["ancient Egyptian",
			{
				name: "Ancient Egyptian",
				fs: {
					unlocks: "FSEgyptianRevivalist",
					loves: new Set(["FSEgyptianRevivalist"]),
				},
				get requirements() {
					return V.boughtItem.clothing.egypt === 1;
				}
			}
		],
		["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;
				},
				harsh: true
			}
		],
		["uncomfortable leather",
			{
				name: "Uncomfortable leather",
				fs: {
					loves: new Set(["FSChattelReligionist"])
				},
				harsh: true
			}
		],
		["shock punishment",
			{
				name: "Shock punishment",
				harsh: true,
				note: "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."
			}
		],
		["neck corset",
			{
				name: "Neck corset",
				harsh: true
			}
		],
	]),

	faceAccessory: new Map([
		["porcelain mask",
			{
				name: "Porcelain mask",
				note: "Obscures the face, increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
			}
		],
		["cat ears",
			{
				name: "Cat ears",
				note: "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
			}
		],
	]),

	vaginalAttachment: new Map([
		["none", {name: "None"}],
		["vibrator",
			{
				name: "Vibrating attachment",
				get requirements() {
					return V.boughtItem.toys.vaginalAttachments === 1;
				},
				vibrates: 1
			}
		],
		["smart vibrator",
			{
				name: "Smart vibrating attachment",
				get requirements() {
					return V.boughtItem.toys.smartVaginalAttachments === 1;
				},
				vibrates: 2
			}
		]
	]),

	dickAccessory: 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;
				}
			}
		]
	]),

	buttplugAttachment: 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;
				}
			}
		]
	]),

	armAccessory: new Map([
		// ["none", {name: "None"}],
		["hand gloves", {name: "Hand gloves"}],
		["elbow gloves", {name: "Elbow gloves"}]

	]),

	legAccessory: new Map([
		// ["none", {name: "None"}],
		["short stockings", {name: "Short stockings"}],
		["long stockings", {name: "Long stockings"}]

	]),
};

/**
 * @typedef {object} mouthAccessory
 * @property {string} name
 * @property {boolean} [requirements]
 * @property {string} [note]
 */

/** @type {Map<FC.MouthAccessory, mouthAccessory>} */
App.Data.mouthAccessory = new Map([
	["ball gag",
		{
			name: "Ball gag",
			note: "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
		}
	],
	["bit gag",
		{
			name: "Bit gag",
			note: "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
		}
	],
	["ring gag",
		{
			name: "Ring gag",
			note: "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
		}
	],
	["massive dildo gag",
		{
			name: "Massive dildo gag",
			get requirements() {
				return V.boughtItem.toys.gags === 1;
			},
			note: "Increases oral skill up to a point and causes fear for disobedient slaves."
		}
	],
	["dildo gag",
		{
			name: "Dildo gag",
			note: "Increases oral skill up to a point and causes fear for disobedient slaves."
		}
	],
]);

/**
 * @typedef {object} slaveShoes
 * @property {string} name
 * @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
 * @property {number} platformHeight height in cm. Adds to heel height.
 */

/**
 * @type {Map<FC.Shoes, slaveShoes>} slaveShoesCategory
 */
App.Data.shoes = new Map([ // TODO: add lift property
	["none",
		{
			name: "Barefoot",
			heelHeight: 0,
			platformHeight: 0
		}
	],
	["flats",
		{
			name: "Flats",
			heelHeight: 0,
			platformHeight: 0
		}
	],
	["pumps",
		{
			name: "Pumps",
			heelHeight: 5, // 2 inch heels
			platformHeight: 0
		}
	],
	["heels",
		{
			name: "Heels",
			heelHeight: 13, // 5 inch heels
			platformHeight: 0
		}
	],
	["boots",
		{
			name: "Thigh boots",
			heelHeight: 13, // 5 inch heels
			platformHeight: 0
		}
	],
	["extreme heels",
		{
			name: "Painfully extreme heels",
			heelHeight: 21, // 8 inch heels
			platformHeight: 0
		}
	],
	["platform shoes",
		{
			name: "Platforms",
			fs: {
				unlocks: "FSStatuesqueGlorification",
				loves: new Set(["FSStatuesqueGlorification"])
			},
			get requirements() {
				return (V.boughtItem.shoes.heels === 1);
			},
			heelHeight: 0,
			platformHeight: 8 // 3 inch platform, no heels
		}
	],
	["platform heels",
		{
			name: "Platform heels",
			fs: {
				unlocks: "FSStatuesqueGlorification",
				loves: new Set(["FSStatuesqueGlorification"])
			},
			get requirements() {
				return (V.boughtItem.shoes.heels === 1);
			},
			heelHeight: 13, // 8 inches, but not painful like extremes (3 inch platforms)
			platformHeight: 8
		}
	],
	["extreme platform heels",
		{
			name: "Painfully extreme platform heels",
			fs: {
				unlocks: "FSStatuesqueGlorification",
				loves: new Set(["FSStatuesqueGlorification"])
			},
			get requirements() {
				return (V.boughtItem.shoes.heels === 1);
			},
			heelHeight: 21, // 12 inches! 8 inch heel, 4 inch platform
			platformHeight: 10
		}
	],
]);

/**
 * @typedef {object} slaveButtplugs
 * @property {string} name
 * @property {itemFS} [fs]
 * @property {boolean} [requirements]
 * @property {0|1|2|3} width
 * @property {0|1|2} length
 */

/**
 * @type {Map<string, slaveButtplugs>}
 */
App.Data.buttplug = new Map([
	["none",
		{
			name: "None",
			width: 0,
			length: 0
		}
	],
	["plug",
		{
			name: "Standard plug",
			width: 1,
			length: 1
		}
	],
	["long plug",
		{
			name: "Long plug",
			get requirements() {
				return V.boughtItem.toys.buttPlugs === 1;
			},
			width: 1,
			length: 2
		}
	],
	["large plug",
		{
			name: "Large plug",
			width: 2,
			length: 1
		}
	],
	["long, large plug",
		{
			name: "Long, large plug",
			get requirements() {
				return V.boughtItem.toys.buttPlugs === 1;
			},
			width: 2,
			length: 2
		}
	],
	["huge plug",
		{
			name: "Huge plug",
			width: 3,
			length: 1
		}
	],
	["long, huge plug",
		{
			name: "Long, huge plug",
			get requirements() {
				return V.boughtItem.toys.buttPlugs === 1;
			},
			width: 3,
			length: 2
		}
	]
]);
/**
 * @typedef {object} vaginalAccessories
 * @property {string} name
 * @property {itemFS} [fs]
 * @property {boolean} [requirements]
 * @property {0|1|2|3} width
 * @property {0|1|2} length
 * @property {0|1|2} [vibrates=0] 0: none, 1: standard, 2: "smart" vibe
 */

/**
 * @type {Map<string, vaginalAccessories>}
 */
App.Data.vaginalAccessory = new Map([
	["none",
		{
			name: "None",
			width: 0,
			length: 0
		}
	],
	["bullet vibrator",
		{
			name: "Bullet vibrator",
			width: 0,
			length: 1,
			vibrates: 1
		}
	],
	["smart bullet vibrator",
		{
			name: "Smart bullet vibrator",
			get requirements() {
				return V.boughtItem.toys.smartVibes === 1;
			},
			width: 0,
			length: 1,
			vibrates: 2
		}
	],
	["dildo",
		{
			name: "Dildo",
			width: 1,
			length: 1
		}
	],
	["long dildo",
		{
			name: "Long dildo",
			get requirements() {
				return V.boughtItem.toys.dildos === 1;
			},
			width: 1,
			length: 2
		}
	],
	["large dildo",
		{
			name: "Large dildo",
			width: 2,
			length: 1
		}
	],
	["long, large dildo",
		{
			name: "Long, large dildo",
			get requirements() {
				return V.boughtItem.toys.dildos === 1;
			},
			width: 2,
			length: 2
		}
	],
	["huge dildo",
		{
			name: "Huge dildo",
			get requirements() {
				return V.boughtItem.toys.dildos === 1;
			},
			width: 3,
			length: 1
		}
	],
	["long, huge dildo",
		{
			name: "Long, huge dildo",
			get requirements() {
				return V.boughtItem.toys.dildos === 1;
			},
			width: 3,
			length: 2
		}
	]
]);

/**
 * @typedef {slaveWear} bellyAccessory
 * @property {1|2|3|4} [empathyBelly]
 */
/** @type {Map<string, bellyAccessory>} */
App.Data.bellyAccessory = new Map([
	["none", {name: "None"}],
	["a corset",
		{
			name: "Tight corset",
			note: "Slowly narrows the waist into wispy one."
		}
	],
	["an extreme corset",
		{
			name: "Extreme corset",
			note: "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"
		}
	],
	["a support band",
		{
			name: "Supportive band",
			note: "Reduces chance of miscarriage."
		}
	],
	["a small empathy belly",
		{
			name: "1st Trimester belly",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"])
			},
			get requirements() {
				return V.boughtItem.clothing.belly === 1;
			},
			empathyBelly: 1
		}
	],
	["a medium empathy belly",
		{
			name: "2nd Trimester belly",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"])
			},
			get requirements() {
				return V.boughtItem.clothing.belly === 1;
			},
			empathyBelly: 2
		}
	],
	["a large empathy belly",
		{
			name: "3rd Trimester belly",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"])
			},
			get requirements() {
				return V.boughtItem.clothing.belly === 1;
			},
			empathyBelly: 3
		}
	],
	["a huge empathy belly",
		{
			name: "3rd Trimester twins belly",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"])
			},
			get requirements() {
				return V.boughtItem.clothing.belly === 1;
			},
			empathyBelly: 4
		}
	]
]);
/**
 * @typedef {object} slaveWearChastity
 * @property {string} name
 * @property {object} updateSlave
 * @property {string} [note]
 * @property {itemFS} [fs]
 */

/** @type {Map<string, slaveWearChastity>} */
App.Data.chastity = new Map([
	// '.value' must be a string, so using update slave so I can update multiple values.
	["none",
		{
			name: "None",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 0,
				chastityPenis: 0,
				chastityVagina: 0
			},
		}
	],
	["anal chastity",
		{
			name: "Anal chastity",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 1,
				chastityPenis: 0,
				chastityVagina: 0
			},
			note: "Prevents losing anal virginity."
		}
	],
	["chastity belt",
		{
			name: "Chastity belt",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 0,
				chastityPenis: 0,
				chastityVagina: 1
			},
			note: "Prevents losing virginity, has various effects, obedient virgins, buttsluts and ones with relatively high sex drive are most affected."
		}
	],
	["combined chastity belt",
		{
			name: "Combined chastity belt",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 1,
				chastityPenis: 0,
				chastityVagina: 1
			},
			note: "Prevents losing virginities, has various effects, obedient virgins, buttsluts and ones with relatively high sex drive are most affected."
		}
	],
	["chastity cage",
		{
			name: "Chastity cage",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 0,
				chastityPenis: 1,
				chastityVagina: 0
			},
			note: "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."
		}
	],
	["combined chastity cage",
		{
			name: "Combined chastity cage",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 1,
				chastityPenis: 1,
				chastityVagina: 0
			},
			note: "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."
		}
	],
	["genital chastity",
		{
			name: "Genital chastity",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 0,
				chastityPenis: 1,
				chastityVagina: 1
			},
			note: "Protects both penis and vagina from sex, has various effects."
		}
	],
	["full chastity",
		{
			name: "Full chastity",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 1,
				chastityPenis: 1,
				chastityVagina: 1
			},
			note: "Protects penis, vagina and anus, has various effects."
		}
	],
	["choose own chastity",
		{
			name: "Choose own chastity",
			fs: {unlocks: "FSRestart"},
			updateSlave: {
				choosesOwnChastity: 1
			},
		}
	],
	["revoke choosing own chastity",
		{
			name: "Revoke choosing own chastity",
			fs: {unlocks: "FSRestart"},
			updateSlave: {
				choosesOwnChastity: 0
			},
		}
	]
]);


code:
App.Data.clothes.set("a slave gown",
	{
		name: "Slave gown",
		exposure: 0,
		fs: {loves: new Set(["FSBodyPurist"])},
		desc: {
			summary: function(slave) {
				const r = [];
				const {He, he, his} = getPronouns(slave);
				const bothFeet = hasBothLegs(slave);
				const feet = bothFeet ? "feet" : "foot";

				r.push(`a gorgeous affair`);
				if (isAmputee(slave)) {
					r.push(`tailored to favor ${his} lack of arms and legs.`);
				} else if (!hasAnyLegs(slave)) {
					r.push(`with cuts that offer tantalizing glimpses of delicate flesh.`);
				} else {
					r.push(`with cuts that offer tantalizing glimpses of delicate flesh.`);
					r.push(`${He} completes the look with`);
					switch (slave.shoes) {
						case "flats":
							if (bothFeet) {
								r.push(`a pair of fashionable slingback sandals.`);
							} else {
								r.push(`a fashionable slingback sandal.`);
							}
							break;
						case "boots":
							if (bothFeet) {
								r.push(`elegant worked leather boots.`);
							} else {
								r.push(`an elegant worked leather boot.`);
							}
							break;
						case "heels":
							if (bothFeet) {
								r.push(`kitten heels.`);
							} else {
								r.push(`a kitten heel.`);
							}
							break;
						case "pumps":
							if (bothFeet) {
								r.push(`sleek pumps.`);
							} else {
								r.push(`a sleek heel.`);
							}
							break;
						case "extreme heels":
							if (bothFeet) {
								r.push(`daring spike heels so high ${his} butt is at dick height.`);
							} else {
								r.push(`a daring spike heel so high ${he} can't even stand.`);
							}
							break;
						case "platform shoes":
							if (bothFeet) {
								r.push(`stylish platform shoes.`);
							} else {
								r.push(`a stylish platform shoe.`);
							}
							break;
						case "platform hees":
							if (bothFeet) {
								r.push(`elegant platform heels.`);
							} else {
								r.push(`an elegant platform heel.`);
							}
							break;
						case "extreme platform heels":
							if (bothFeet) {
								r.push(`elegant platform heels so high ${his} butt is at dick height.`);
							} else {
								r.push(`an elegant platform heel so high ${he} can't stand even with assistance.`);
							}
							break;
						default:
							r.push(`nothing on ${his} bare ${feet}.`);
					}
				}
				return r.join(" ");
			},
			upperFace: function(slave) {
				return `nice frameless glasses,`;
			},
			hStyle: function(slave) {
				const r = [];
				const {
					he, his
				} = getPronouns(slave);

				if (slave.fuckdoll === 0) {
					switch (slave.hStyle) {
						case "neat":
							if (slave.hLength > 100) {
								r.push(`cascades gorgeously down ${his} bare back.`);
							} else if (slave.hLength > 30) {
								r.push(`flows fashionably down ${his} bare back.`);
							} else if (slave.hLength > 10) {
								r.push(`follows the latest fashion.`);
							} else {
								r.push(`is gelled into a fashionable wave.`);
							}
							break;
						case "up":
							if (slave.hLength > 100) {
								r.push(`is piled up on ${his} head in a perfect 60's beehive.`);
							} else if (slave.hLength > 30) {
								r.push(`is piled up on ${his} head in a perfect 60's beehive.`);
							} else if (slave.hLength > 10) {
								r.push(`is piled up on ${his} head in a perfect 60's 'do.`);
							} else {
								r.push(`is combed back.`);
							}
							break;
						case "tails":
							if (slave.hLength > 100) {
								r.push(`is combed into beautiful long tails, one of which comes around to run down ${his} chest.`);
							} else if (slave.hLength > 30) {
								r.push(`is combed into beautiful tails, one of which comes around to fall between ${his} breasts.`);
							} else if (slave.hLength > 10) {
								r.push(`is combed into short tails set low at the nape of ${his} neck.`);
							} else {
								r.push(`is too short to be kept in proper tails, so it's simply combed back.`);
							}
							break;
						case "ponytail":
							if (slave.hLength > 100) {
								r.push(`is combed into a beautiful long ponytail, which swooshes as ${he} moves.`);
							} else if (slave.hLength > 30) {
								r.push(`is combed into a beautiful ponytail, which swooshes as ${he} moves.`);
							} else if (slave.hLength > 10) {
								r.push(`is combed into a short ponytail set low at the nape of ${his} neck.`);
							} else {
								r.push(`is too short to be kept in a proper ponytail, so it's simply combed back.`);
							}
							break;
						case "braided":
							if (slave.hLength > 100) {
								r.push(`is combed into beautiful long braids, one of which comes around to run down ${his} chest.`);
							} else if (slave.hLength > 30) {
								r.push(`is in beautiful braids, one of which comes around to fall between ${his} breasts.`);
							} else if (slave.hLength > 10) {
								r.push(`is combed into short braids set low at the nape of ${his} neck.`);
							} else {
								r.push(`is too short to be kept in proper braids, so it's simply combed back.`);
							}
							break;
						case "dreadlocks":
							if (slave.hLength > 100) {
								r.push(`is in dreadlocks, spreading out in many directions and almost reaching the ground.`);
							} else if (slave.hLength > 30) {
								r.push(`is in dreadlocks, spreading out in many directions.`);
							} else if (slave.hLength > 10) {
								r.push(`is in short dreadlocks, spreading around ${his} head.`);
							} else {
								r.push(`is too short to be kept in proper dreadlocks, so it's simply combed back.`);
							}
							break;
						case "curled":
							if (slave.hLength > 100) {
								r.push(`is curled into long flowing locks, almost reaching the ground.`);
							} else if (slave.hLength > 30) {
								r.push(`is curled into long locks, reaching past ${his} shoulders.`);
							} else if (slave.hLength > 10) {
								r.push(`is curled into short locks.`);
							} else {
								r.push(`is in short curls.`);
							}
							break;
						case "permed":
							if (slave.hLength > 100) {
								r.push(`is permed into long flowing curls, almost reaching the ground.`);
							} else if (slave.hLength > 30) {
								r.push(`is permed, reaching past ${his} shoulders.`);
							} else if (slave.hLength > 10) {
								r.push(`is permed into short waves.`);
							} else {
								r.push(`is permed into short curls.`);
							}
							break;
						case "luxurious":
							if (slave.hLength > 100) {
								r.push(`is in luxurious layered locks flowing gorgeously down ${his} bare back.`);
							} else if (slave.hLength > 30) {
								r.push(`is in luxurious layered locks flowing gorgeously down ${his} bare back.`);
							} else if (slave.hLength > 10) {
								r.push(`is in luxuriously styled short locks.`);
							} else {
								r.push(`is in luxuriously styled short locks.`);
							}
							break;
						case "strip":
							if (slave.hLength > 100) {
								r.push(`is shaved into a strip atop ${his} head that cascades magnificently down ${his} back.`);
							} else if (slave.hLength > 30) {
								r.push(`is shaved into a long braided strip.`);
							} else if (slave.hLength > 10) {
								r.push(`is shaved into a strip.`);
							} else {
								r.push(`is shaved into a mohawk.`);
							}
							break;
						case "undercut":
							if (slave.hLength > 100) {
								r.push(`is shaved on one side into a long undercut that falls well past ${his} breasts.`);
							} else if (slave.hLength > 30) {
								r.push(`is shaved to one side, the other half falling down to their neck.`);
							} else if (slave.hLength > 10) {
								r.push(`is shaved to one side, the other half falling just over one eye.`);
							} else {
								r.push(`is shaved to one side in a pixie-like undercut.`);
							}
							break;
						case "bangs":
							if (slave.hLength > 100) {
								r.push(`is cut straight across ${his} face, hiding ${his} eyes.`);
							} else if (slave.hLength > 30) {
								r.push(`is cut straight across ${his} face, partially hiding ${his} eyes.`);
							} else if (slave.hLength > 10) {
								r.push(`is cut straight above ${his} eyebrows.`);
							} else {
								r.push(`is cut straight across ${his} forehead.`);
							}
							break;
						case "hime":
							if (slave.hLength > 100) {
								r.push(`cascades down ${his} bare back in a hime cut with shoulder-length side-locks.`);
							} else if (slave.hLength > 30) {
								r.push(`flows down ${his} bare back in a hime cut with cheek-length side-locks.`);
							} else if (slave.hLength > 10) {
								r.push(`is styled into a hime cut with cheek-length side-locks.`);
							} else {
								r.push(`is styled into a hime cut with cheek-length side-locks.`);
							}
							break;
						case "drills":
							if (slave.hLength > 100) {
								r.push(`is wound into enormous, exquisite coils that come to rest across ${his} chest.`);
							} else if (slave.hLength > 30) {
								r.push(`is wound into large coils which rest atop ${his} breasts.`);
							} else if (slave.hLength > 10) {
								r.push(`is in a pair of short coils.`);
							} else {
								r.push(`is too short to be kept in proper tails, so it's simply combed back.`);
							}
							break;
						case "bald":
							r.push(`is completely bald.`);
					}
				}
				return r.join(" ");
			},
			earPiercing: function(slave) {
				const {He} = getPronouns(slave);
				return `${He}'s wearing lovely diamond earrings; the stones are cut in an alluring, feminine style.`;
			},
			corsetPiercing: function(slave) {
				const {his} = getPronouns(slave);
				return `they're revealed by the swooping back of ${his} gown and laced up with matching silk ribbon.`;
			},
			clothingCorset: function(slave) {
				const r =[];
				const {His, his} = getPronouns(slave);
				if (slave.bellyAccessory === "a corset") {
					r.push(`${His} gown has an elegant integral corset.`);
				} else if (slave.bellyAccessory === "an extreme corset") {
					r.push(`${His} gown has extreme corsetage built into it.`);
				} else if (slave.bellyAccessory === "a support band") {
					r.push(`${His} support band is concealed by ${his} gown.`);
				}
				return r.join(" ");
			},
			boobs: function(slave) {
				const r = [];
				const {his} = getPronouns(slave);
				const noun = App.Desc.boobBits.noun(slave.boobs, false, false);
				const adjNoun = App.Desc.boobBits.noun(slave.boobs, false, true);
				r.push(`${slave.slaveName}'s slave gown`);
				if (slave.boobs > 12000) {
					r.push(`is no longer able to cover ${his} ${adjNoun}. Instead, it has been redesigned to draw the eye to them.`);
				} else if (slave.boobs > 4000) {
					r.push(`is carefully engineered and is somehow able to cover the enormous mass of ${his} breasts.`);
				} else if (slave.boobs > 800) {
					r.push(`is carefully tailored, tastefully covering yet enhancing ${his} ${adjNoun}.`);
				} else if (slave.boobs < 300) {
					r.push(`is carefully tailored to closely hug ${his} flat chest.`);
				} else {
					r.push(`subtly accentuates ${his} ${noun}.`);
				}
				return r.join(" ");
			},
			belly: function(slave) {
				const r = [];
				const {his, him} = getPronouns(slave);
				const isBellyFluidLargest = (slave.bellyFluid >= slave.bellyPreg && slave.bellyFluid >= slave.bellyImplant);

				if (slave.belly >= 1000000) {
					if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material. When not worn, it looks more like a circus tent than something meant to be worn by a human being. On the slave, it gives ${him} a sensual, motherly look as it caresses ${his} unfathomable, hyper-swollen, ${slave.inflationType}-filled belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material, and gives ${him} a sensual, motherly look as it caresses ${his} unfathomable, hyper-swollen, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material, and gives ${him} a sensual, motherly look as it caresses and supports ${his} unfathomable, hyper-swollen pregnant belly. Despite it's size, it still has enough give to allow ${his} unborn children to bulge and squirm as desired.`);
					}
				} else if (slave.belly >= 750000) {
					if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material. When not worn, it looks more like a couch cover than something meant to be worn by a human being. On ${him}, it gives ${him} a sensual, motherly look as it carefully caresses ${his} monolithic, ${slave.inflationType}-filled belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material, and gives ${him} a sensual, motherly look as it carefully caresses ${his} monolithic, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material, and gives ${him} a sensual, motherly look as it carefully caresses and supports ${his} monolithic pregnant belly. It has enough give to allow ${his} unborn children to bulge and squirm as desired.`);
					}
				} else if (slave.belly >= 600000) {
					if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} titanic, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses and supports ${his} titanic bulging pregnant belly.`);
					}
				} else if (slave.belly >= 450000) {
					if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} gigantic, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses and supports ${his} gigantic pregnant belly.`);
					}
				} else if (slave.belly >= 300000) {
					if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} massive, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses and supports ${his} massive pregnant belly.`);
					}
				} else if (slave.belly >= 120000) {
					if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} giant, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses and supports ${his} giant pregnant belly.`);
					}
				} else if (slave.weight > 190) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve and fold of ${his} massively fat belly. Every motion in ${his} impressive gut is elegantly embraced by ${his} gown.`);
				} else if (slave.belly >= 15000 || (slave.bellyAccessory === "a huge empathy belly")) {
					if (slave.bellyAccessory === "a huge empathy belly") {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} huge pregnant belly.`);
					} else if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} huge, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} huge pregnant belly.`);
					}
				} else if (slave.belly >= 10000 || (slave.bellyAccessory === "a huge empathy belly") || (slave.bellyAccessory === "a large empathy belly")) {
					if (slave.bellyAccessory === "a large empathy belly") {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} big pregnant belly.`);
					} else if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, almost motherly look, as it carefully caresses ${his} hugely swollen belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} big, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} big pregnant belly.`);
					}
				} else if (slave.weight > 160) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve and fold of ${his} hugely fat belly.`);
				} else if (slave.weight > 130) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve and fold of ${his} big fat belly.`);
				} else if (slave.belly >= 5000 || (slave.bellyAccessory === "a medium empathy belly")) {
					if (slave.bellyAccessory === "a medium empathy belly") {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} pregnant belly.`);
					} else if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} jiggling ${slave.inflationType}-filled belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} pregnant belly.`);
					}
				} else if (slave.weight > 95) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve of ${his} fat belly.`);
				} else if (slave.belly >= 1500 || slave.bellyAccessory === "a small empathy belly") {
					if (slave.bellyAccessory === "a small empathy belly") {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} small belly.`);
					} else if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual look as it carefully caresses ${his} ${slave.inflationType}-swollen belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual look as it carefully caresses ${his} implant-rounded belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual look as it carefully caresses ${his} growing belly.`);
					}
				} else if (slave.weight > 30) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve of ${his} chubby belly.`);
				} else if (slave.bellyPreg >= 100 || slave.bellyImplant >= 100) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging even the slight bulge to ${his} lower belly.`);
				} else if (slave.muscles > 30) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging ${his} ripped abs.`);
				}
				return r.join(" ");
			},
			crotch: function(slave) {
				const r = [];
				const {his} = getPronouns(slave);
				r.push(`${slave.slaveName}'s`);
				if (slave.dick > 6) {
					r.push(`lovely gown cannot hide the fact that something massive is lurking`);
					if (hasBothLegs(slave)) {
						r.push(`between ${his} legs.`);
					} else {
						r.push(`underneath it.`);
					}
				} else if (slave.dick > 3) {
					r.push(`cock tents the front of ${his} lovely gown.`);
				} else if (slave.dick > 0 && slave.vagina > -1) {
					r.push(`hermaphroditic genitalia are hidden by ${his} lovely gown.`);
				} else if (slave.dick > 0) {
					r.push(`cock is hidden by ${his} lovely gown.`);
				} else if (slave.vagina === -1) {
					r.push(`featureless groin is concealed by ${his} lovely gown.`);
				} else {
					r.push(`pussy is concealed by ${his} lovely gown.`);
				}
				return r.join(" ");
			},
			butt: function(slave) {
				const r = [];
				const {His, his} = getPronouns(slave);
				r.push(`${His} slave gown`);
				if (slave.butt > 10) {
					r.push(`is tailored as tastefully as possible for ${his} inhuman`);
				} else if (slave.butt > 6) {
					r.push(`is tailored as tastefully as possible for ${his} massive`);
				} else if (slave.butt > 3) {
					r.push(`is tailored to flatter ${his} big`);
				} else {
					r.push(`tastefully clings to ${his}`);
				}
				r.push(`buttocks.`);
				return r.join(" ");
			},
			buttplug: function(slave) {
				const r = [];
				const {His, his} = getPronouns(slave);
				if (slave.chastityAnus) {
					r.push(`${His} pretty gown hides ${his} anal chastity accessory underneath.`);
				} else {
					r.push(`Though ${his} gown is very pretty, ${his} asshole is bare beneath it.`);
				}
				return r.join(" ");
			},
		}
	}
);

repo_name: CloudyCoffee/fc

license: mit


code:
/**
 * @type {FC.Rules.LivingFreezed}
 * @enum {string}
 */
globalThis.LivingRule = Object.freeze({LUXURIOUS: 'luxurious', NORMAL: 'normal', SPARE: 'spare'});
/**
 * @type {FC.Rules.RestFreezed}
 * @enum {string}
 */
globalThis.RestRule = Object.freeze({
	MANDATORY: 'mandatory', MAX: 'permissive', MID: 'restrictive', MIN: 'cruel', NONE: 'none'
});
/**
 * @type {FC.AssignmentFreeze}
 * @enum {string}
 */
globalThis.Job = Object.freeze({
	// Penthouse Assignments
	REST: 'rest',
	FUCKTOY: 'please you',
	CLASSES: 'take classes',
	HOUSE: 'be a servant',
	WHORE: 'whore',
	PUBLIC: 'serve the public',
	SUBORDINATE: 'be a subordinate slave',
	MILKED: 'get milked',
	GLORYHOLE: 'work a glory hole',
	CONFINEMENT: 'stay confined',
	// Leadership Assignments
	BODYGUARD: 'guard you',
	HEADGIRL: 'be your Head Girl',
	RECRUITER: 'recruit girls',
	AGENT: 'be your agent',
	AGENTPARTNER: 'live with your agent',
	// Facility Assignments
	ARCADE: 'be confined in the arcade',
	MADAM: 'be the Madam',
	BROTHEL: 'work in the brothel',
	WARDEN: 'be the Wardeness',
	CELLBLOCK: 'be confined in the cellblock',
	DJ: 'be the DJ',
	CLUB: 'serve in the club',
	NURSE: 'be the Nurse',
	CLINIC: 'get treatment in the clinic',
	MILKMAID: 'be the Milkmaid',
	DAIRY: 'work in the dairy',
	FARMER: 'be the Farmer',
	FARMYARD: 'work as a farmhand',
	HEADGIRLSUITE: 'live with your Head Girl',
	CONCUBINE: 'be your Concubine',
	MASTERSUITE: 'serve in the master suite',
	MATRON: 'be the Matron',
	NURSERY: 'work as a nanny',
	TEACHER: 'be the Schoolteacher',
	SCHOOL: 'learn in the schoolroom',
	STEWARD: 'be the Stewardess',
	QUARTER: 'work as a servant',
	ATTENDANT: 'be the Attendant',
	SPA: 'rest in the spa',
	// Does this one exist?
	BABY_FACTORY: 'labor in the production line',
	// Other
	CHOICE: 'choose her own job',
	// Pseudo-jobs
	LURCHER: '@Lurcher',
	PIT: '@Pit',
	IMPORTED: '@be imported',
	TANK: '@lay in tank'
});

/**
 * @enum {string}
 */
globalThis.PersonalAttention = Object.freeze({
	TRADE: 'trading',
	WAR: 'warfare',
	SLAVING: 'slaving',
	ENGINEERING: 'engineering',
	MEDICINE: 'medicine',
	MAID: 'upkeep',
	HACKING: 'hacking',
	SUPPORTHG: 'HG',
	WHORING: 'whoring',
	BUSINESS: 'business',
	SMUGGLING: 'smuggling',
	SURVEY: 'defensive survey',
	DEVELOPMENT: 'development project',
	TECH: 'technical accidents',
	SEX: 'sex',
	PROCLAMATION: 'proclamation',
});

/**
 * @enum {string}
 */
globalThis.DescType = Object.freeze({
	NORMAL: "normal",
	MARKET: "market",
	EVENT: "event",
	SURGERY: "surgery"
});


code:
App.Data.dictionary = {
	"cat": {
		Japanese: "neko"
	},
	"dog": {
		Japanese: "inu"
	},
	"fox": {
		Japanese: "kit"
	},
	"cow": {
		Japanese: "ushi"
	},
	"raccoon": {
		Japanese: "tanuki"
	},
	"rabbit": {
		Japanese: "usagi"
	},
	"squirrel": {
		Japanese: "risu"
	},
	"horse": {
		Japanese: "uma"
	},
};


code:
App.Data.FutureSociety = {
	/**
	 * Each future society contains a record here, along with a noun and adjective form for use in printed text, and the decoration string (normally also an adjective form).
	 * Most of the automatic mechanics for FS adoption, influence, facility decoration, etc, are handled directly from this data; flavor text is not.
	 * @type {Record<FC.FutureSociety, {noun: FC.FutureSocietyNoun, adj: FC.FutureSocietyAdj, deco: FC.FutureSocietyDeco, NPCOnly?: boolean, language?: string, nationality?: string}>} */
	records: ({
		FSSupremacist: {noun: "Racial Supremacism", adj: "Supremacist", deco: "Supremacist"},
		FSSubjugationist: {noun: "Racial Subjugationism", adj: "Subjugationist", deco: "Subjugationist"},
		FSGenderRadicalist: {noun: "Gender Radicalism", adj: "Gender Radicalist", deco: "Gender Radicalist"},
		FSGenderFundamentalist: {noun: "Gender Fundamentalism", adj: "Gender Fundamentalist", deco: "Gender Fundamentalist"},
		FSDegradationist: {noun: "Degradationism", adj: "Degradationist", deco: "Degradationist"},
		FSPaternalist: {noun: "Paternalism", adj: "Paternalist", deco: "Paternalist"},
		FSBodyPurist: {noun: "Body Purism", adj: "Body Purist", deco: "Body Purist"},
		FSTransformationFetishist: {noun: "Transformation Fetishism", adj: "Transformation Fetishist", deco: "Transformation Fetishist"},
		FSYouthPreferentialist: {noun: "Youth Preferentialism", adj: "Youth Preferentialist", deco: "Youth Preferentialist"},
		FSMaturityPreferentialist: {noun: "Maturity Preferentialism", adj: "Maturity Preferentialist", deco: "Maturity Preferentialist"},
		FSSlimnessEnthusiast: {noun: "Slimness Enthusiasm", adj: "Slimness Enthusiast", deco: "Slimness Enthusiast"},
		FSAssetExpansionist: {noun: "Asset Expansionism", adj: "Asset Expansionist", deco: "Asset Expansionist"},
		FSPastoralist: {noun: "Pastoralism", adj: "Pastoralist", deco: "Pastoralist"},
		FSCummunism: {noun: "Cummunism", adj: "Cummunist", deco: "", NPCOnly: true},
		FSPhysicalIdealist: {noun: "Physical Idealism", adj: "Physical Idealist", deco: "Physical Idealist"},
		FSHedonisticDecadence: {noun: "Decadent Hedonism", adj: "Decadent Hedonist", deco: "Hedonistic"},
		FSChattelReligionist: {noun: "Chattel Religionism", adj: "Chattel Religionist", deco: "Chattel Religionist"},
		FSNull: {noun: "Multiculturalism", adj: "Multiculturalist", deco: ""},
		FSIncestFetishist: {noun: "Incest Fetishism", adj: "Incest Fetishist", deco: "", NPCOnly: true},
		FSRomanRevivalist: {
			noun:			"Roman Revivalism",
			adj:			"Roman Revivalist",
			deco:			"Roman Revivalist",
			nationality:	"Roman Revivalist",
			language:		"Latin",
		},
		FSNeoImperialist: {
			noun:			"Neo-Imperialism",
			adj:			"Neo-Imperialist",
			deco:			"Neo-Imperialist",
		},
		FSEgyptianRevivalist: {
			noun:			"Egyptian Revivalism",
			adj:			"Egyptian Revivalist",
			deco:			"Egyptian Revivalist",
			nationality:	"Ancient Egyptian Revivalist",
			language:		"Ancient Egyptian",
		},
		FSEdoRevivalist: {
			noun:			"Edo Revivalism",
			adj:			"Edo Revivalist",
			deco:			"Edo Revivalist",
			nationality:	"Edo Revivalist",
			language:		"Japanese",
		},
		FSArabianRevivalist: {
			noun:			"Arabian Revivalism",
			adj:			"Arabian Revivalist",
			deco:			"Arabian Revivalist",
			nationality:	"Arabian Revivalist",
			language:		"Arabic",
		},
		FSChineseRevivalist: {
			noun:			"Chinese Revivalism",
			adj:			"Chinese Revivalist",
			deco:			"Chinese Revivalist",
			nationality:	"Ancient Chinese Revivalist",
			language:		"Chinese",
		},
		FSAztecRevivalist: {
			noun:			"Aztec Revivalism",
			adj:			"Aztec Revivalist",
			deco:			"Aztec Revivalist",
			nationality:	"Aztec Revivalist",
			language:		"Nahuatl",
		},
		FSRepopulationFocus: {noun: "Repopulation Focus", adj: "Repopulationist", deco: "Repopulationist"},
		FSRestart: {noun: "Eugenics", adj: "Eugenics", deco: "Eugenics"},
		FSIntellectualDependency: {noun: "Intellectual Dependency", adj: "Intellectual Dependency", deco: "Intellectual Dependency"},
		FSSlaveProfessionalism: {noun: "Slave Professionalism", adj: "Slave Professional", deco: "Slave Professionalism"},
		FSPetiteAdmiration: {noun: "Petite Admiration", adj: "Petite Admiration", deco: "Petite Admiration"},
		FSStatuesqueGlorification: {noun: "Statuesque Glorification", adj: "Statuesque Glorification", deco: "Statuesque Glorification"}
	}),

	/** Each subarray in this array contains a set of Future Societies which are to be considered mutually exclusive.
	 * They cannot be adopted at the same time by the same arcology, and if adopted by different arcologies,
	 * will automatically conflict and reduce diplomatic relations. */
	mutexGroups: (/** @returns {FC.FutureSociety[][]} */ function() {
		/* this tiny-but-hideous IIFE is the only way I can get typechecking to work properly here, without a JSDoc equivalent to TS "as const" to prevent literal type widening */
		return [
			["FSSupremacist"],
			["FSSubjugationist"],
			["FSGenderRadicalist", "FSGenderFundamentalist"],
			["FSDegradationist", "FSPaternalist"],
			["FSBodyPurist", "FSTransformationFetishist"],
			["FSYouthPreferentialist", "FSMaturityPreferentialist"],
			["FSSlimnessEnthusiast", "FSAssetExpansionist"],
			["FSPastoralist", "FSCummunism"],
			["FSPhysicalIdealist", "FSHedonisticDecadence"],
			["FSChattelReligionist", "FSNull"],
			["FSIncestFetishist"],
			["FSRomanRevivalist", "FSNeoImperialist", "FSEgyptianRevivalist", "FSEdoRevivalist", "FSArabianRevivalist", "FSChineseRevivalist", "FSAztecRevivalist"],
			["FSRepopulationFocus", "FSRestart"],
			["FSIntellectualDependency", "FSSlaveProfessionalism"],
			["FSPetiteAdmiration", "FSStatuesqueGlorification"]
		];
	})(),

	/** @type {FC.FutureSociety[]} */
	fsNames: [],

	/** @type {FC.FutureSociety[]} */
	playerFSNames: []
};

/* -- auto-populate derived lists from records -- */
App.Data.FutureSociety.fsNames = /** @type {FC.FutureSociety[]} */ (Object.keys(App.Data.FutureSociety.records));
App.Data.FutureSociety.playerFSNames = App.Data.FutureSociety.fsNames.filter(fs => !App.Data.FutureSociety.records[fs].NPCOnly);


code:
// A whitelist for ingame variables. Used to init the game or fill in gaps. Also used as a whitelist. Anything not on this list will be removed on BC.
App.Data.defaultGameStateVariables = {
	// Page
	nextButton: "Continue",
	nextLink: "Alpha disclaimer",
	storedLink: "",

	// Version
	ver: "",
	pmodVer: "",
	releaseID: 0,

	// Slaves
	/** @type {Object.<number, number>} */
	slaveIndices: {},
	genePool: [],
	missingTable: {},
	/** @type {App.Entity.SlaveState[]} */
	slaves: [],

	// PC
	/** @type {App.Entity.PlayerState} */
	PC: null,
	freshPC: 0,
	IsInPrimePC: 3,
	IsPastPrimePC: 5000,
	playerAging: 2,

	// NGP
	saveImported: 0,
	customVariety: 0,
	nationalities: {},

	// Other
	cheater: 0,
	cash: 0,
	cashLastWeek: 0,
	taintedSaveFile: 0,

	// UI content
	UI: {
		slaveSummary: {
			abbreviation: {
				clothes: 2,
				devotion: 2,
				diet: 2,
				drugs: 2,
				genitalia: 2,
				health: 2,
				hormoneBalance: 2,
				mental: 2,
				nationality: 2,
				origins: 2,
				physicals: 2,
				race: 2,
				rules: 2,
				rulesets: 2,
				skills: 2,
			}
		},
		compressSocialEffects: 0
	},
	/** @type {App.Markets.Global|null} */
	market: null,
	FSNamePref: 0,
	HGFormality: 1,
	HGSeverity: 0,
	HGPiercings: 1,
	abbreviateSidebar: 1,
	adamPrinciple: 0,
	allowFamilyTitles: 0,
	allowMaleSlaveNames: false,
	autosave: 1,
	baseDifficulty: 3,
	dangerousPregnancy: 0,
	debugMode: 0,
	debugModeCustomFunction: 0,
	debugModeEventSelection: 0,
	difficultySwitch: 0,
	disableLisping: 0,
	displayAssignments: 1,
	expansionRequestsAllowed: 1,
	extremeUnderage: 0,
	formatNumbers: 1,
	fucktoyInteractionsPosition: 1,
	slaveInteractLongForm: false,
	headGirlSoftensFlaws: 1,
	headGirlTrainsFlaws: 1,
	headGirlOverridesQuirks: 0,
	headGirlTrainsHealth: 1,
	headGirlTrainsObedience: 1,
	headGirlTrainsParaphilias: 1,
	headGirlTrainsSkills: 1,
	imageChoice: 1,
	inbreeding: 1,
	lastBDayEvent: -1,
	lineSeparations: 1,
	endweekSaveWarning: 1,
	limitFamilies: 0,
	makeDicks: 0,
	modRequestsAllowed: 1,
	neighboringArcologies: 3,
	neighborDisplay: "list",
	newDescriptions: 0,
	newModelUI: 1,
	nicknamesAllowed: 1,
	positionMainLinks: -1,
	profiler: 0,
	realRoyalties: 0,
	retainCareer: 1,
	ngpParams: {},
	rulesAssistantAuto: 0,
	rulesAssistantMain: 1,
	seeAge: 1,
	seeArcology: 1,
	seeAvatar: 1,
	seeBestiality: 0,
	seeCircumcision: 1,
	seeDesk: 1,
	seeDetails: 1,
	seeDicks: 25,
	seeDicksAffectsPregnancy: 1,
	seeExtreme: 0,
	seeCats: 0,
	seeFCNN: 1,
	seeFaces: 1,
	seeHeight: 0,
	seeHyperPreg: 0,
	seeIllness: 1,
	seeImages: 0,
	seeIncest: 1,
	seeMainFetishes: 0,
	seeNationality: 1,
	seePee: 1,
	seePreg: 1,
	seeRace: 1,
	seeReportImages: 1,
	seeSummaryImages: 1,
	seeVectorArtHighlights: 1,
	setSuperSampling: 2,
	setZoomSpeed: 1,
	setFaceCulling: false,
	setTextureResolution: 1024,
	showAgeDetail: 1,
	showAppraisal: 1,
	showAssignToScenes: 1,
	showBodyMods: 1,
	showBoobCCs: 1,
	showClothing: 1,
	showDickCMs: 1,
	showDistantRelatives: 0,
	showEWD: 1,
	showEWM: 1,
	showEconomicDetails: 0,
	showHeightCMs: 1,
	showImplantEffects: 1,
	showInches: 1,
	showMissingSlaves: false,
	showMissingSlavesSD: false,
	showNeighborDetails: 1,
	showNumbers: 2,
	showNumbersMax: 20,
	showScores: 1,
	showSexualHistory: 1,
	showTipsFromEncy: 1,
	showVignettes: 1,
	slavePanelStyle: 1,
	sortSlavesBy: "devotion",
	sortSlavesMain: 1,
	sortSlavesOrder: "descending",
	summaryStats: 0,
	surnameArcology: "",
	surnameOrder: 0,
	surnamePCOverride: 0,
	surnameScheme: 0,
	/** @type {Object.<string, string>} */
	tabChoice: {Main: "all"},
	universalRulesAssignsSelfFacility: 0,
	universalRulesBirthing: 0,
	universalRulesCSec: 0,
	universalRulesChildrenBecomeBreeders: 0,
	universalRulesConsent: 0,
	universalRulesFacilityWork: 1,
	universalRulesImmobileSlavesMaintainMuscles: 0,
	universalRulesImpregnation: "none",
	universalRulesNewSlavesRA: 1,
	useAccordion: 1,
	useFSNames: 1,
	useSlaveListInPageJSNavigation: 0,
	useSlaveSummaryOverviewTab: 0,
	useSlaveSummaryTabs: 0,
	useTabs: 0,
	verboseDescriptions: 0,
	verticalizeArcologyLinks: 0,
	weightAffectsAssets: 1,
	curativeSideEffects: 1,
	disableLongDamage: 1,
	// Last-used strings in Locate Slave
	findName: "",
	findBackground: "",
	findData: "",

	// eslint-disable-next-line camelcase
	pedo_mode: 0,
	minimumSlaveAge: 16,
	fertilityAge: 13,
	potencyAge: 13,
	AgePenalty: 1,
	precociousPuberty: 0,
	loliGrow: 0,
	retirementAge: 45,
	customRetirementAge: 45,
	customMenialRetirementAge: 65,
	sortIncubatorList: "Unsorted",
	AgeEffectOnTrainerPricingPC: 1,
	AgeEffectOnTrainerEffectivenessPC: 1,
	AgeTrainingUpperBoundPC: 14,
	AgeTrainingLowerBoundPC: 12,
	childSex: 0,
	showClothingErection: true,

	// Default location
	continent: "North America",
	terrain: "rural",
	language: "English",

	AProsperityCapModified: 0,
	secExpEnabled: 0,
	customItem: {
		/** @type {Map<string, slaveButtplugs>} */
		buttplug: new Map([]),
		/** @type {Map<string, vaginalAccessories>} */
		vaginalAccessory: new Map([]),
	},
};

// Corp data
App.Data.CorpInitData = {
	Announced: 0,
	Incorporated: 0,
	Market: 0,
	Econ: 0,
	CashDividend: 0,
	Div: 0,
	ExpandToken: 0,
	Spec: 0,
	SpecToken: 0,
	SpecRaces: []
};

App.Data.projectN = {
	status: 0,
	public: 0,
	wellFunded: 0,
	poorlyFunded: 0,
	phase1: 0,
	phase2: 0,
	phase3: 0,
	phase4: 0,
	decisionMade: 0,
	techReleased: 0,
};

// Black Market
App.Data.FSWares = [
	"AssetExpansionistResearch",
	"GenderRadicalistResearch",
	"HedonisticDecadenceResearch",
	"SlaveProfessionalismResearch",
	"SlimnessEnthusiastResearch",
	"TransformationFetishistResearch",
	"YouthPreferentialistResearch",
];

App.Data.illegalWares = [
	"AnimalOrgans",
	"asexualReproduction",
	"BlackmarketPregAdaptation",
	"childhoodFertilityInducedNCS",
	"PGHack",
	"RapidCellGrowthFormula",
	"sympatheticOvaries",
	"UterineRestraintMesh",
];

// The other half of the above whitelist. However, entries in this array will be forced to the values set here upon starting NG+.
App.Data.resetOnNGPlus = {
	policies: {
		retirement: {
			sex: 0,
			milk: 0,
			cum: 0,
			births: 0,
			kills: 0,

			/** @type {FC.Zeroable<string>} */
			fate: 0,
			menial2Citizen: 0,
			customAgePolicy: 0,
			physicalAgePolicy: 0
		},
		SMR: {
			basicSMR: 1,
			healthInspectionSMR: 0,
			educationSMR: 0,
			frigiditySMR: 0,
			weightSMR: 0,
			honestySMR: 0,

			beauty: {
				basicSMR: 0,
				qualitySMR: 0
			},
			height: {
				basicSMR: 0,
				advancedSMR: 0
			},
			intelligence: {
				basicSMR: 0,
				qualitySMR: 0
			},
			eugenics: {
				faceSMR: 0,
				heightSMR: 0,
				intelligenceSMR: 0
			}
		},

		childProtectionAct: 1,
		culturalOpenness: 0,
		proRefugees: 0,
		publicFuckdolls: 0,

		proRecruitment: 0,
		cash4Babies: 0,
		regularParties: 0,
		publicPA: 0,
		coursingAssociation: 0,

		raidingMercenaries: 0,
		mixedMarriage: 0,
		goodImageCampaign: 0,
		alwaysSubsidizeRep: 0,
		alwaysSubsidizeGrowth: 0,

		immigrationCash: 0,
		immigrationRep: 0,
		enslavementCash: 0,
		enslavementRep: 0,
		cashForRep: 0,

		oralAppeal: 0,
		vaginalAppeal: 0,
		analAppeal: 0,
		sexualOpenness: 0,
		bestialityOpenness: 0,
		gumjobFetishism: 0,
		gumjobFetishismSMR: 0
	},

	FCTV: {
		receiver: -1,
		channel: {},
		pcViewership: {
			count: 0,
			frequency: 4,
		},
		remote: 0,
		weekEnabled: 0
	},
	/** @type {assistant} */
	assistant: null,
	targetArcology: {fs: /** @type {FC.FutureSociety|"New"} */("New")},

	plot: 1,
	plotEventWeek: 0,
	assignmentRecords: {},
	marrying: [], // array of slave being married this week
	organs: [],
	corp: App.Data.CorpInitData,
	dividendTimer: 0,
	dividendRatio: 0,
	personalShares: 0,
	publicShares: 0,
	SF: {},
	/** @type {FC.Zeroable<Array<string>>} */
	thisWeeksFSWares: 0,
	/** @type {FC.Zeroable<Array<string>>} */
	thisWeeksIllegalWares: 0,
	Sweatshops: 0,

	/** @type {Array<Array<App.Events.BaseEvent>>} */
	eventQueue: [],

	rivalID: 0,
	eliteAuctioned: 0,
	slavesSacrificedThisWeek: 0,

	mercenariesTitle: "",
	FSReminder: 0,
	facility: {},
	boomerangStats: {},
	econAdvantage: 0,

	SecExp: {},

	reminderEntry: "",
	reminderWeek: "",
	currentRule: {},
	costs: 0,
	seeBuilding: 0,
	purchasedSagBGone: 0,
	eliteFail: 0,
	eliteFailTimer: 0,
	nurseryGrowthStimsSetting: 0,
	MadamIgnoresFlaws: 0,
	MadamNoSex: 0,
	farmyardBreeding: 0,
	farmyardRestraints: 0,
	farmyardShows: 0,
	farmyardPregSetting: 0,
	DJignoresFlaws: 0,
	DJnoSex: 0,

	// Budget
	lastWeeksCashIncome: {},
	lastWeeksCashExpenses: {},
	lastWeeksRepIncome: {},
	lastWeeksRepExpenses: {},
	showAllEntries: {costsBudget: 0, repBudget: 0},
	/** @type {string[]} */
	lastWeeksCashErrors: [],
	/** @type {string[]} */
	lastWeeksRepErrors: [],

	econRate: 0,
	/** @type {FC.ArcologyState[]} */
	arcologies: [],
	HackingSkillMultiplier: 0,
	upgradeMultiplierArcology: 0,
	upgradeMultiplierMedicine: 0,
	upgradeMultiplierTrade: 0,
	/** @type {Record<FC.Assignment, Set<number>>} */
	JobIDMap: null,
	averageTrust: 0,
	averageDevotion: 0,
	enduringTrust: 0,
	enduringDevotion: 0,
	/** @type {FC.RA.Rule[]} */
	defaultRules: [],
	/** @type {Object.<string, number[]>} */
	rulesToApplyOnce: {},

	REFeminizationCheckinIDs: [],
	REMILFCheckinIDs: [],
	REOrientationCheckinIDs: [],
	REUglyCheckinIDs: [],
	REButtholeCheckinIDs: [],
	REFutaSisterCheckinIDs: [],
	REReductionCheckinIDs: [],

	deathIDs: {
		health: [],
		overdose: [],
		age: []
	},
	burstIDs: [],
	birthIDs: [],
	induceIDs: [],
	/** @type {FC.SlaveStateOrZero} */
	activeSlave: 0,
	activeChild: 0,
	/** @type {Array<FC.ReminderEntry>} */
	reminders: [],

	/** @type {FC.SlaveStateOrZero} */
	boomerangSlave: 0,
	boomerangWeeks: 0,
	/** @type {FC.Zeroable<string>} */
	boomerangBuyer: 0,

	bioreactorPerfectedID: 0,

	independenceDay: 0,
	invasionVictory: 0,
	daughtersVictory: 0,

	dormitory: 20,
	dormitoryPopulation: 0,
	rooms: 5,
	roomsPopulation: 0,

	/** @type {FC.FutureSocietyDeco} */
	brothelDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	brothelUpgradeDrugs: 0,
	brothelAdsSpending: 0,
	brothelAdsOld: 0,
	brothelAdsModded: 0,
	brothelAdsImplanted: 0,
	brothelAdsStacked: 0,
	brothelAdsPreg: 0,
	brothelAdsXX: 0,
	brothelName: "the Brothel",
	brothel: 0,
	brothelBoost: {
		selected: 0, eligible: 0
	},
	/** @type {FC.FutureSocietyDeco} */
	dairyDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	dairyPrepUpgrade: 0,
	dairyStimulatorsUpgrade: 0,
	dairyStimulatorsSetting: 0,
	dairyStimulatorsSettingChanged: 0,
	dairyFeedersUpgrade: 0,
	dairyFeedersSetting: 0,
	dairyFeedersSettingChanged: 0,
	dairyPregUpgrade: 0,
	dairyPregSetting: 0,
	dairyPregSettingChanged: 0,
	dairyRestraintsUpgrade: 0,
	dairyRestraintsSetting: 0,
	dairySlimMaintainUpgrade: 0,
	dairySlimMaintain: 0,
	dairyHyperPregRemodel: 0,
	dairyWeightSetting: 0,
	dairyHormonesSetting: 0,
	dairyImplantsSetting: 1,
	dairyUpgradeMenials: 0,
	createBioreactors: 0,
	bioreactorsAnnounced: 0,
	bioreactorsHerm: 0,
	bioreactorsXX: 0,
	bioreactorsXY: 0,
	bioreactorsBarren: 0,
	dairyName: "the Dairy",
	dairy: 0,
	/** @type {FC.FutureSocietyDeco} */
	clubDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	clubUpgradePDAs: 0,
	clubAdsSpending: 0,
	clubAdsOld: 0,
	clubAdsModded: 0,
	clubAdsImplanted: 0,
	clubAdsStacked: 0,
	clubAdsPreg: 0,
	clubAdsXX: 0,
	clubName: "the Club",
	club: 0,
	/** @type {FC.FutureSocietyDeco} */
	servantsQuartersDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	servantsQuartersUpgradeMonitoring: 0,
	servantsQuarters: 0,
	servantsQuartersName: "the Servants' Quarters",
	/** @type {FC.FutureSocietyDeco} */
	schoolroomDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	schoolroomUpgradeSkills: 0,
	schoolroomUpgradeLanguage: 0,
	schoolroomUpgradeRemedial: 0,
	schoolroomRemodelBimbo: 0,
	schoolroom: 0,
	schoolroomName: "the Schoolroom",
	/** @type {FC.FutureSocietyDeco} */
	spaDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	spa: 0,
	spaSpots: 0,
	spaUpgrade: 0,
	spaFix: 0,
	spaName: "the Spa",

	incubator: {capacity: 0, tanks: []},

	/** @type {FC.FutureSocietyDeco} */
	clinicDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	clinic: 0,
	clinicUpgradeFilters: 0,
	clinicUpgradeScanner: 0,
	clinicUpgradePathogenSequencer: 0,
	clinicUpgradePurge: 0,
	clinicObservePregnancy: 1,
	clinicInflateBelly: 0,
	clinicRegularCheckups: 1,
	clinicSpeedGestation: 0,
	clinicName: "the Clinic",
	/** @type {FC.FutureSocietyDeco} */
	arcadeDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	arcadeUpgradeInjectors: 0,
	arcadeUpgradeFuckdolls: 0,
	arcadeUpgradeCollectors: 0,
	arcadeUpgradeHealth: -1,
	arcadeName: "the Arcade",
	arcade: 0,
	fuckdollsSold: 0, // TODO: This never increases
	/** @type {FC.FutureSocietyDeco} */
	cellblockDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	cellblockUpgrade: 0,
	cellblock: 0,
	cellblockName: "the Cellblock",
	cellblockWardenCumsInside: 1,
	/** @type {FC.FutureSocietyDeco} */
	masterSuiteDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	masterSuiteUpgradeLuxury: 0,
	masterSuiteUpgradePregnancy: 0,				/* Is the upgrade active? */
	masterSuitePregnancyFertilityDrugs: 0,			/* Are slaves being put on fertility drugs? */
	masterSuitePregnancyFertilitySupplements: 0,	/* Are those drugs being supplemented (health benefits and (even) more multiple pregnancies) */
	masterSuitePregnancySlaveLuxuries: 0,			/* Are the slaves being given some nicer things to reduce stress during preg? (health/devotion/trust benefits) */
	universalHGImpregnateMasterSuiteToggle: 0,		/* Will the HG impregnate fertile slaves in the MS? */
	masterSuiteHyperPregnancy: 0,
	masterSuite: 0,
	masterSuiteName: "the Master Suite",

	// Nursery
	/** Counts the number of children the nursery can support */
	nursery: 0,
	/** Counts the number of nannies the nursery can support */
	nurseryNannies: 0,
	/** Counts the number of children currently in the nursery */
	nurseryChildren: 0,
	/** Check for whether the children are influenced by the nannies */
	nannyInfluence: 0,
	/** @type {FC.FutureSocietyDeco} */
	nurseryDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	nurseryWeight: 0,
	nurseryMuscles: 0,
	nurseryHormones: 0,
	nurseryOrgans: 0,								// not currently in use
	nurseryImprintSetting: 0,
	nurseryWeightSetting: 0,
	nurseryMusclesSetting: 0,
	nurseryHormonesSetting: 0,
	nurseryName: "the Nursery",
	nurserySex: false,
	MatronIgnoresFlaws: false,
	/** Array of children in the Nursery */
	cribs: [],
	cribsIndices: {},
	sortNurseryList: "Unsorted",
	targetAgeNursery: 18,

	// Farmyard Subsection
	farmyard: 0,
	farmyardShowgirls: [],			/* array of farmhands putting on shows */
	farmyardFarmers: [],			/* array of farmhands farming */
	farmMenials: 0,
	farmMenialsSpace: 0,
	/** @type {FC.FutureSocietyDeco} */
	farmyardDecoration: (/** @type {FC.FutureSocietyDeco} */ "standard"),
	farmyardUpgrades: {
		pump: 0,
		fertilizer: 0,
		hydroponics: 0,
		machinery: 0,
		seeds: 0,
	},
	farmyardCrops: 0,
	farmyardStables: 0,
	farmyardKennels: 0,
	farmyardCages: 0,
	active: {
		/** @type {App.Entity.Animal} */
		canine: null,
		/** @type {App.Entity.Animal} */
		hooved: null,
		/** @type {App.Entity.Animal} */
		feline: null,
	},
	canine: [],
	hooved: [],
	feline: [],
	farmyardName: "the Farmyard",

	HGSuite: 0,
	HGSuiteSurgery: 1,
	HGSuiteDrugs: 1,
	HGSuiteAbortion: 1,
	HGSuiteHormones: 1,
	HGSuiteEquality: 0,
	HGSuiteName: "the Head Girl Suite",

	/** @type {FC.Facilities.Pit} */
	pit: null,

	/** Arrays of slaves you've threatened to kill */
	threatened: [
		[],	// this week
		[],	// one week ago
		[],	// two weeks ago
		[],	// three weeks ago
		[], // four weeks ago
	],

	dojo: 0,
	feeder: 0,
	cockFeeder: 0,
	suppository: 0,
	weatherCladding: 0,
	weatherAwareness: 0,
	boobAccessibility: 0,
	servantMilkers: 0,

	studio: 0,
	studioFeed: 0,
	PCSlutContacts: 1,

	/* Porn star counts (prestige 1) and ID's (prestige 3) */
	pornStars: {},

	pregInventor: 0,
	pregInventorID: 0,
	pregInventions: 0,

	FSAnnounced: 0,
	FSGotRepCredits: 0,
	FSCreditCount: 5,
	FSSingleSlaveRep: 10,
	FSSpending: 0,
	FSLockinLevel: 100,

	// new corporation variables
	newCorp: 1,
	vanillaShareSplit: 1,

	/* Slave sexual services and goods variables */
	classSatisfied: {
		lowerClass: 0, middleClass: 0, upperClass: 0, topClass: 0
	},
	whoreBudget: {
		lowerClass: 7, middleClass: 40, upperClass: 200, topClass: 1500
	},
	sexDemandResult: {
		lowerClass: 0, middleClass: 0, upperClass: 0, topClass: 0
	},
	arcadePrice: 2,
	/** @type {App.Entity.SlaveState|number} */
	shelterSlave: 0,
	shelterSlaveBought: 0,
	shelterAbuse: 0,

	pregAccessibility: 0,
	dickAccessibility: 0,
	ballsAccessibility: 0,
	buttAccessibility: 0,
	boughtItem: {
		clothing: {
			// alternate clothing access variables
			bunny: 0,
			conservative: 0,
			chains: 0,
			western: 0,
			oil: 0,
			habit: 0,
			toga: 0,
			huipil: 0,
			kimono: 0,
			harem: 0,
			qipao: 0,
			imperialarmor: 0,
			imperialsuit: 0,
			egypt: 0,
			belly: 0,
			maternityDress: 0,
			maternityLingerie: 0,
			lazyClothes: 0,
			bimbo: 0,
			courtesan: 0,
			petite: 0,
			// non-fs
			military: 0,
			cultural: 0,
			middleEastern: 0,
			pol: 0,
			costume: 0,
			pantsu: 0,
			career: 0,
			dresses: 0,
			bodysuits: 0,
			casual: 0,
			underwear: 0,
			sports: 0,
			pony: 0,
			swimwear: 0,
		},
		shoes: {
			heels: 0,
		},
		toys: {
			enema: 0,
			medicalEnema: 0,
			buckets: 0,
			dildos: 0,
			gags: 0,
			vaginalAttachments: 0,
			buttPlugs: 0,
			buttPlugTails: 0,
			smartVibes: 0,
			smartVaginalAttachments: 0,
		},
	},
	dairyPiping: 0,
	milkPipeline: 0,
	cumPipeline: 0,
	wcPiping: 0,
	/** @type {Map<number, "oldAge"|"overdosed"|"lowHealth">} */
	slaveDeath: new Map(),
	playerBred: 0,
	playerBredTube: 0,
	propOutcome: 0,
	EliteSires: [],
	raped: -1,
	missingParentID: -10000,
	/* animalParts: 0,*/
	pregSpeedControl: 0,
	playerSurgery: 0,
	bodyswapAnnounced: 0,
	surnamesForbidden: 0,
	menstruation: 0,
	FCNNstation: 0,
	swanSong: 0,
	failedElite: 0,
	eugenicsFullControl: 0,
	badC: 0,
	poorKnight: 0,
	imperialEventWeek: 0,
	assholeKnight: 0,
	newBaron: 0,
	badB: 0,

	schoolSuggestion: 0,
	TSS: {
		schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0
	},
	TUO: {
		schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0
	},
	GRI: {
		schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0
	},
	SCP: {
		schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0
	},
	LDE: {
		schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0
	},
	TGA: {
		schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0
	},
	TCR: {
		schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0
	},
	TFS: {
		farmUpgrade: 0, schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0, compromiseWeek: 0
	},
	futaAddiction: 0,
	HA: {
		schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0
	},
	NUL: {
		schoolUpgrade: 0, schoolPresent: 0, schoolProsperity: 0, subsidize: 0, schoolAnnexed: 0, studentsBought: 0, schoolSale: 0
	},

	IDNumber: 1,

	week: 1,

	slaveTutor: {
		HeadGirl: [],
		Recruiter: [],
		Bodyguard: [],
		Madam: [],
		DJ: [],
		Nurse: [],
		Teacher: [],
		Attendant: [],
		Matron: [],
		Stewardess: [],
		Milkmaid: [],
		Farmer: [],
		Wardeness: []
	},

	weddingPlanned: 0,
	/** @type {string|Array<{ID:number, trainingRegimen:string}>} */
	personalAttention: "sex",
	HeadGirlID: 0,
	HGTimeInGrade: 0,
	RecruiterID: 0,
	/** @type {FC.RecruiterTarget} */
	recruiterTarget: "desperate whores",
	/** @type {FC.RecruiterTarget} */
	oldRecruiterTarget: "desperate whores",
	recruiterProgress: 0,
	recruiterIdleRule: "number",
	recruiterIdleNumber: 20,
	recruiterIOUs: 0,
	bodyguardTrains: 1,
	BodyguardID: 0,
	MadamID: 0,
	djID: 0,
	MilkmaidID: 0,
	milkmaidImpregnates: 0,
	FarmerID: 0,
	StewardessID: 0,
	stewardessImpregnates: 0,
	SchoolteacherID: 0,
	AttendantID: 0,
	MatronID: 0,
	NurseID: 0,
	WardenessID: 0,
	ConcubineID: 0,

	justiceEvents: ["slave deal", "slave training", "majority deal", "indenture deal", "virginity deal", "breeding deal"], /* not in setupVars because we remove events from this array as they occur */
	/** @type {Array<FC.SlaveMarketName>} */
	prisonCircuit: ["low tier criminals", "gangs and smugglers", "white collar", "military prison"],
	prisonCircuitIndex: 0,

	ui: "start",
	tooltipsEnabled: 0,

	brandTarget: {primary: "left buttock", secondary: "left buttock", local: "left buttock"},
	brandDesign: {primary: "your initials", official: "your initials", local: "your initials"},

	scarTarget: {primary: "left cheek", secondary: "left cheek", local: "left cheek"},
	scarDesign: {primary: "generic", local: "generic"},

	oralTotal: 0,
	vaginalTotal: 0,
	analTotal: 0,
	mammaryTotal: 0,
	penetrativeTotal: 0,
	milkTotal: 0,
	cumTotal: 0,
	foodTotal: 0,
	birthsTotal: 0,
	abortionsTotal: 0,
	miscarriagesTotal: 0,
	bestialityTotal: 0,
	pitKillsTotal: 0,
	pitFightsTotal: 0,

	collaboration: 0,
	/** @type {FC.SlaveStateOrZero} */
	traitor: 0,
	/** @type {FC.Zeroable<string>} */
	traitorType: 0,
	traitorWeeks: 0,
	/** @type {FC.Zeroable<object>} */
	traitorStats: 0,
	hackerSupport: 0,
	/** @type {FC.SlaveStateOrZero} */
	hostage: 0,
	/** @type {FC.Bool} */
	hostageAnnounced: 0,
	/** @type {FC.Bool} */
	hostageRescued: 0,
	/** @type {FC.Bool} */
	hostageGiveIn: 0, // TODO: Set up code block to set to one. This is already checked in src/endWeek/saDevotion.js
	/** @type {FC.SlaveStateOrZero} */
	hostageWife: 0,
	rivalSet: 0,
	/** @type {FC.Zeroable<FC.FutureSocietyNoun>} */
	rivalryFS: 0,
	/** @type {FC.Bool} */
	rivalryFSAdopted: 0,
	/** @type {FC.Zeroable<FC.Race>} */
	rivalryFSRace: 0,
	rivalOwner: 0,
	rivalOwnerEnslaved: 0,
	rivalryPower: 0,
	rivalryDuration: 0,
	/** @type {FC.Zeroable<FC.Race>} */
	rivalRace: 0,
	rivalGender: 0,
	nationHate: 0,
	eventResults: {},

	dispensary: 0,
	dispensaryUpgrade: 0,
	organFarmUpgrade: 0,
	/** @type {FC.Medicine.OrganFarm.GrowingOrgan[]} */
	completedOrgans: [],
	/** @type {FC.Bool} */
	ImplantProductionUpgrade: 0,
	/** @type {FC.Bool} */
	permaPregImplant: 0,
	/** @type {0|1|2|3} */
	injectionUpgrade: 0,
	/** @type {FC.Bool} */
	hormoneUpgradeMood: 0,
	/** @type {FC.Bool} */
	hormoneUpgradeShrinkage: 0,
	/** @type {FC.Bool} */
	hormoneUpgradePower: 0,
	/** @type {FC.Bool} */
	pubertyHormones: 0,
	/** @type {FC.Bool} */
	dietXXY: 0,
	/** @type {FC.Bool} */
	dietCleanse: 0,
	/** @type {FC.Bool} */
	cumProDiet: 0,
	/** @type {FC.Bool} */
	dietFertility: 0,
	/** @type {FC.Bool} */
	curativeUpgrade: 0,
	/** @type {FC.Bool} */
	growthStim: 0,
	/** @type {FC.Bool} */
	reproductionFormula: 0,
	/** @type {FC.Bool} */
	aphrodisiacUpgrade: 0,
	/** @type {FC.Bool} */
	aphrodisiacUpgradeRefine: 0,
	/** @type {FC.Bool} */
	healthyDrugsUpgrade: 0,
	/** @type {FC.Bool} */
	superFertilityDrugs: 0,
	/** @type {FC.Bool} */
	bellyImplants: 0,
	/** @type {0|1|2} */
	cervixImplants: 0,
	/** @type {FC.Bool} */
	meshImplants: 0,
	/** @type {FC.Bool} */
	prostateImplants: 0,
	/** @type {FC.Bool} */
	youngerOvaries: 0,
	/** @type {FC.Bool} */
	sympatheticOvaries: 0,
	/** @type {FC.Bool} */
	fertilityImplant: 0,
	/** @type {FC.Bool} */
	asexualReproduction: 0,
	/** @type {FC.Bool} */
	animalOvaries: 0, /* {pigOvaries: 0, canineOvaries: 0, horseOvaries: 0, cowOvaries: 0} currently unused*/
	/** @type {FC.Bool} */
	animalTesticles: 0, /* {pigTestes: 0, dogTestes: 0, horseTestes: 0, cowTestes: 0} currently unused*/
	/** @type {FC.Bool} */
	animalMpreg: 0, /* {pigMpreg: 0, dogMpreg: 0, horseMpreg: 0, cowMpreg: 0} currently unused*/
	/** @type {0|1|2} */
	geneticMappingUpgrade: 0,
	toyShop: false,
	/** @type {FC.Bool} */
	pregnancyMonitoringUpgrade: 0,
	/** @type {FC.Bool} */
	cloningSystem: 0,
	/** @type {FC.Bool} */
	geneticFlawLibrary: 0,

	projectN: App.Data.projectN,
	bodyPuristRiot: 0,
	puristsFurious: 0,
	puristRiotDone: 0,
	subjectDeltaName: "Bubbles",
	growingNewCat: 0,
	noDeadShit: 0,

	surgeryUpgrade: 0,

	barracks: 0,
	mercenaries: 0,
	mercenariesHelpCorp: 0,
	personalArms: 0,

	encyclopedia: "How to Play",

	/** @type {string[]} */
	trinkets: [],
	SPcost: 1000,
	debtWarned: 0,
	internationalTrade: 1,
	internationalVariety: 0,
	slaveCostFactor: 0.95,
	menialDemandFactor: 0,
	menialSupplyFactor: 0,
	demandTimer: 0,
	supplyTimer: 0,
	elapsedDemandTimer: 0,
	elapsedSupplyTimer: 0,
	slaveCostRandom: 0,
	deltaDemand: 0,
	deltaDemandOld: 0,
	deltaSupply: 0,
	deltaSupplyOld: 0,
	NPCSexSupply: {
		lowerClass: 3000, middleClass: 3000, upperClass: 3000, topClass: 3000
	},
	NPCMarketShare: {
		lowerClass: 1000, middleClass: 1000, upperClass: 1000, topClass: 1000
	},
	sexSubsidies: {
		lowerClass: 0, middleClass: 0, upperClass: 0, topClass: 0
	},
	sexSupplyBarriers: {
		lowerClass: 0, middleClass: 0, upperClass: 0, topClass: 0
	},
	facilityCost: 100,
	enduringRep: 1000,
	rep: 0,
	repLastWeek: 0,

	arcologyUpgrade: {
		drones: 0, hydro: 0, apron: 0, grid: 0, spire: 0
	},

	economy: 100,
	localEcon: 0,
	drugsCost: 0,
	rulesCost: 0,
	modCost: 0,
	surgeryCost: 0,
	AGrowth: 2,
	ACitizens: 4250,
	lowerClass: 3120,
	LSCBase: 800,
	visitors: 0,
	rentDefaults: {
		lowerClass: 20, middleClass: 50, upperClass: 180, topClass: 650
	},
	rent: {
		lowerClass: 20, middleClass: 50, upperClass: 180, topClass: 650
	},
	rentEffectL: 1,
	middleClass: 890,
	MCBase: 200,
	rentEffectM: 1,
	upperClass: 200,
	UCBase: 40,
	rentEffectU: 1,
	topClass: 40,
	TCBase: 20,
	rentEffectT: 1,
	GDP: 278.6,
	NPCSlaves: 900,
	ASlaves: 900,
	AProsperityCap: 0,

	food: 125000,
	foodLastWeek: 0,
	foodProduced: 0,
	foodStored: 0,
	farmyardFoodCost: 5,
	foodCost: 25,
	foodMarket: 0,
	foodRate: {
		slave: 2, lower: 1.8, middle: 2, upper: 2.2, top: 2.4
	},
	foodConsumption: 0,	/* total amount food consumed per week */
	revealFoodEffects: 0,
	rations: 0,
	/** @type {App.Arcology.Building} */
	building: null,

	menials: 0,
	fuckdolls: 0,
	menialBioreactors: 0,
	prestigeAuctioned: 0,
	slaveMarketLimit: 20,
	slavesSeen: 0,

	slaveOrphanageTotal: 0,
	citizenOrphanageTotal: 0,
	privateOrphanageTotal: 0,
	breederOrphanageTotal: 0,

	LurcherID: 0,
	coursed: 0,
	StudID: 0,
	raided: 0,

	FSSlaveProfLawTrigger: 0,
	citizenRetirementTrigger: 0,
	FSSupLawTrigger: 0,
	FSSubLawTrigger: 0,
	nicaea: {
		announced: 0,
		preparation: 0,
		involvement: -2,
		power: 0,
		held: 0,
		focus: "",
		assignment: "",
		achievement: "",
		name: "",
		influence: 0,
		eventWeek: 0
	},

	/** @type {FC.Zeroable<FC.PeacekeepersState>} */
	peacekeepers: 0,
	peacekeepersFate: 0,
	peacekeepersGone: 0,
	mercRomeo: 0,

	oralUseWeight: 5,
	vaginalUseWeight: 5,
	analUseWeight: 5,
	mammaryUseWeight: 1,
	penetrativeUseWeight: 1,

	weatherToday: {},
	weatherLastWeek: 0,
	weatherType: 0,
	weatherRemaining: 0,

	/**
	 * I am not a slave object! Do not treat me like one!
	 * @type {App.Entity.CustomSlaveOrder}
	 */
	customSlave: null,
	customSlaveOrdered: 0,
	customSlaveReorder: 0,

	/**
	 * I am not a slave object! Do not treat me like one!
	 * @type {App.Entity.CustomSlaveOrder}
	 * */
	huskSlave: null,
	huskSlaveOrdered: 0,

	targetAge: 18, // non-vanilla shit

	/* Job Fulfillment Center */
	JFC: {
		/** @type {FC.Bool} */
		order: 0,
		reorder: 0
	},

	/** @type {FC.Bool} */
	cheatMode: 0,
	cheatModeM: 1,
	experimental: {
		nursery: 0,
		food: 0,
		animalOvaries: 0,
		dinnerParty: 0,
		reportMissingClothing: 0,
		raGrowthExpr: 0,
		sexOverhaul: 0,
	},
	NaNArray: [],

	/* Misc mod variables */
	recruiterEugenics: 0,

	prostheticsUpgrade: 0,
	adjustProstheticsCompleted: 0,
	adjustProsthetics: [], /* format: {id: string, workleft: int, slaveID: int}*/
	/* task: {type: "research"/"craft/craftFit", id: string, workLeft: int, [if constructFit] slaveID: int}*/
	researchLab: {
		level: 0,
		aiModule: 1,
		tasks: [],
		maxSpace: 0,
		hired: 0,
		menials: 0,
	},
	/* prosthetics: {research: int, amount: int} */
	prosthetics: {},

	merchantFSWares: App.Data.FSWares,
	merchantIllegalWares: App.Data.illegalWares,
	RapidCellGrowthFormula: 0,
	immortalityFormula: 0,
	UterineRestraintMesh: 0,
	PGHack: 0,
	BlackmarketPregAdaptation: 0,

	diversePronouns: 0,

	/* Career-skill gain */
	masteredXP: 200,

	/* Weather effect on economy */
	antiWeatherFreeze: 0,
	econWeatherDamage: 0,
	disasterResponse: 0,

	postSexCleanUp: 1,

	sideBarOptions: {
		Cash: 1, Upkeep: 1, SexSlaveCount: 1, roomPop: 1, Rep: 1, GSP: 1, Authority: 1, Security: 1, Crime: 1, confirmWeekEnd: 0,
	},
	DefaultBirthDestination: "individually decided fates",
	heroSlavesPurchased: [],
	/** @type {string[]} */
	fcnn: [],

	murderAttemptWeek: 80,
	illegalDeals: {
		/** @type {FC.Zeroable<{week: number, company: string}>|-1} */
		military: 0,
		/** @type {FC.Zeroable<{week: number, company: string}>|-1} */
		trade: 0,
		menialDrug: 0,
		/** @type {FC.Zeroable<{type: string, week: number, company: string}>|-1} */
		slave: 0
	},
	tempEventToggle: 0,
	/**
	 * Assignments texts for slaves who choose their own assignment, set at during the first pass in App.SlaveAssignment.choosesOwnJob()
	 * @type {Object.<number, string>}
	 */
	choosesOwnAssignmentText: {},
	favorites: []
};