code:
App.Mods.DinnerParty.Prep = function() {
	const t = new DocumentFragment();
	let r = [];

	r.push("Hosting of high society dinner parties will increase your prestige significantly and it is expected for someone of your station.");
	r.push("Since there is a lack of animal meat, human meat is served at these events to illustrate the wealth and power of the host.");
	r.push("The success of the evening is judged by how well the human offering is prepared.");
	r.push("Guests to these events are encouraged to rate the dishes and special dishes are expected.");
	r.push(`If the host receives 5 stars on all the dishes, they will receive the coveted title "${V.PC.title ? 'Master' : 'Mistress'} of The Culinary Arts".`);
	r.push(`You ask ${V.assistant.name} to show you a list of cooking instructions for those dishes.`);
	App.Events.addNode(t, r, "div");

	App.Events.addNode(t, ["Cooking Instructions and Recipes:"], "h1");

	r = [];
	r.push(App.UI.DOM.makeElement("span", "Roast Long Pig", ["bold"]));
	r.push("– Made with the meat of a human roasted on a spit. Young meat is better than old meat.");
	r.push("There should be some amount of fat to make the meat juicy, but not too much fat that makes the meat greasy.");
	r.push("Muscles affect the texture of the meat. Meat without muscles lacks texture while an excess will be tough and hard to chew. Remember that you can't eat silicone, and virgin meat is highly sought after.");
	if (V.seePreg !== 0) {
		r.push("If the human is pregnant, a veal dish can also be made from the fetus.");
	}
	App.Events.addNode(t, r, "div");

	r = [];
	r.push(App.UI.DOM.makeElement("span", "Dicky Roll", ["bold"]));
	r.push("– An erect penis made into a spring roll. For best results, harvest the penis at the moment of ejaculation.");
	r.push("The size of the penis and the amount of accumulated ejaculate all affect the quality of the dish. Too big of a dick and too thin of semen can both ruin a dish.");
	App.Events.addNode(t, r, "p");

	App.Events.addNode(t, [App.UI.DOM.makeElement("span", "Testy Meat Balls", ["bold"]), "– Testicles made into meat balls served with a sauce. Size matters."], "p");

	r = [];
	r.push(App.UI.DOM.makeElement("span", "Titty Tartare", ["bold"]));
	r.push("– Made from finely chopped breasts, mixed with onions, capers, and seasonings, and served raw.");
	r.push("Big breasts make the best quality meat for this dish. To add a hint of creamy taste, make sure the breasts are lactating. Remember that you can't eat silicone.");
	App.Events.addNode(t, r, "p");

	App.Events.addNode(t, [App.UI.DOM.makeElement("span", "Camel Toe à l'Orange", ["bold"]), "– Pussy grilled like a steak. A big clit and big labia will improve the quality of the dish."], "p");

	App.Events.addNode(t, ["Your assistant will take care of the invitations and all the arrangements; all you need to do is pick the meat."], "p");

	App.Events.addNode(t, ["Select Your Meat:"], "div", ["underline"]);

	t.append(App.UI.SlaveList.slaveSelectionList(
		s => assignmentVisible(s) && s.fuckdoll === 0,
		App.UI.SlaveList.SlaveInteract.stdInteract,
		null,
		(s) => {
			const p = getPronouns(s);
			return App.UI.DOM.passageLink(`Make ${p.him} the main course`, "Dinner Party Execution",
				() => { V.AS = s.ID; });
		}
	));
	return t;
};

App.Mods.DinnerParty.Execution = function() {
	// To MOD: insert the following code into the passage PC Name and Title
	// <<if $MOD_DinnerPartyTitleAchievement == 1>><<if $PC.title > 0>><<set $titles.push("Master of the Culinary Arts")>><<else>><<set $titles.push("Mistress of the Culinary Arts")>><</if>><</if>>
	const t = new DocumentFragment();
	const slave = getSlave(V.AS);
	const {His, He, his, he, him} = getPronouns(slave);
	App.Events.drawEventArt(t, slave);
	const appetizers = new Map([
		["Dicky Roll", slave.dick > 0],
		["Testy Meat Balls", slave.balls > 0],
		["Camel Toe steak", slave.vagina !== -1],
		["Baby Veal Ragout", slave.preg >= slave.pregData.normalBirth/4],
		["Titty Tartare", true],
		["Roast Long Pig", true],
	]);

	let r;
	let dinnerRating = 0;
	cashX(-1000, "event");

	r = [];
	r.push(`${slave.slaveName} is carried out by four slaves on a huge platter and placed on the dining table.`);
	if (slave.fetish === Fetish.MINDBROKEN) {
		r.push(`${His} mind is broken. ${He} does not understand what's about happen, so there is little need to restrain ${him}.`);
	} else if (slave.devotion > 90) {
		r.push(`${He} worships you and considers it an honor to be chosen for sacrifice. There is no need to restrain ${him}.`);
	} else {
		r.push(`${He} understands ${he} is about to be slaughtered liked an animal. Tears stream down ${his} face as ${he} struggles against ${his} bindings.`);
	}

	// This needs to be rewritten. Take into account FS tastes and the fact that the player might not have a dick
	r.push(`${He} is lying on ${his} back with an apple in ${his} mouth. You lift ${his} ${hasBothLegs(slave) ? 'legs' : 'waist'} up in the air, exposing ${his} nethers.`);
	r.push(`You penetrate ${him} with your ${V.PC.dick !== 0 ? 'throbbing dick' : 'strap-on'} , fucking ${him} roughly and cumming quickly.`);
	r.push(`Your guests form a line behind you, and do the same to ${his} ass. Some of your guests take particular pleasure being rough with ${slave.slaveName}.`);
	r.push(`They enjoy making ${him} squeal like a pig, knowing they are about to enjoy ${his} flesh in a short while.`);
	r.push(`After all of your guests had a turn with the little piggy, ${his} ass is dripping with cum and a hint of blood.`);
	r.push(`It seems your guests greatly`, App.UI.DOM.makeElement("span", "enjoy", ["green"]), `themselves. You stand over ${him} with a ceremonial dagger,`);
	repX(5000, "event");

	r.push(`looking into ${his}`);
	if (slave.fetish === Fetish.MINDBROKEN) {
		r.push(`dull eyes.`);
	} else if (slave.devotion > 90) {
		r.push(`proud eyes.`);
	} else {
		r.push(`terrified eyes begging for mercy.`);
	}

	r.push(`You give the signal for your slaves to begin the ceremony. The four slaves hold ${slave.slaveName} down on the platter. A fifth slave starts to give ${him} oral sex.`);
	r.push(`${slave.slaveName} moans with the apple in ${his} mouth. When ${he} is on the edge of climax you plunge the ceremonial dagger into ${his} chest.`);
	r.push(`The pain causes ${him} to bite down on the apple deeply. Tears mixed with the juices of the apple flow down ${his} face. With a twist of your hand, you carve out ${his} beating heart.`);
	if (slave.fetish === Fetish.MINDBROKEN || slave.devotion > 90) {
		r.push(`Your guests`, App.UI.DOM.makeElement("span", "applaud", ["green"]), `your slave's willingness to die for ${his} ${getWrittenTitle(slave)}, a credit to your training.`);
	} else {
		r.push(`Your guests`, App.UI.DOM.makeElement("span", "snicker", ["red"]), `at your inability to provide a willing sacrifice.`);
	}
	repX((slave.fetish === Fetish.MINDBROKEN || slave.devotion > 90 ? 2500 : -100), "event");
	r.push(`Your slaves carry the carcass to the kitchen for cooking preparations. With all the ingredients for the special dishes harvested, the carcass is placed on a spit slowly rotating over an open fire.`);
	r.push(`You mingle with your guests while ${slave.slaveName} is slowly being cooked.`);
	App.Events.addNode(t, r, "p");

	App.Events.addNode(t, [`Your slaves begin to serve the appetizer...`], "p");
	for (const [name] of Array.from(appetizers).filter(s => s[1] === true)) {
		t.append(getDish(name));
	}

	// End of Dinner. Total of main dishes each can earn 5 stars total 25, getting 12 stars means a successful evening
	r = [];
	if (dinnerRating >= 12) { // successful evening
		r.push(`The party is in full swing. Your guests enjoy eating ${slave.slaveName} and make good use of the slaves you provided for their pleasure.`);
		r.push(`Sounds of an orgy of food drink and sex echoes through your dining hall. Your guests ate, drank and fucked their fill.`);
		r.push(`As the evening draw to a close, there isn't a single morsel of ${slave.slaveName} left to be found. Some of your slaves show signs of teeth marks on their skin. Perhaps some guests got confused about what's for eating and what's for fucking?`);
		r.push(`The evening was a`, App.UI.DOM.makeElement("span", "success.", ["green"]));
		App.Events.addNode(t, r, "div");
		repX((dinnerRating * 500), "event");

		if (dinnerRating >= 20) {
			App.Events.addNode(t, [`You have earned the 20 stars required for the title of`, App.UI.DOM.makeElement("span", `${V.PC.title > 0 ? 'Master' : 'Mistress'} of The Culinary Arts.`, ["yellow"])], "p");
			// V.MOD_DinnerPartyTitleAchievement = 1;
		}

		App.Events.addNode(t, [], "p");
		// Clean up and slaves reactions
		App.Events.addNode(t, ["When the last of your guests has stumbled drunkenly out your door, your slaves begin the daunting task of cleanup."], "div");
		for (const aliveSlave of V.slaves.filter(s => s.fetish !== Fetish.MINDBROKEN && s.devotion < 50)) {
			let relation;
			let feeling;
			const {his3, sister3, daughter3, He3} = getPronouns(aliveSlave).appendSuffix("3");
			if (slave.mother === aliveSlave.ID || slave.father === aliveSlave.ID) {
				relation = `${daughter3}`;
				feeling = "distraught";
				aliveSlave.devotion -= (slave.mother === aliveSlave.ID ? 20 : 10);
				aliveSlave.trust -= (slave.mother === aliveSlave.ID ? 20 : 10);
			}
			if (slave.ID === aliveSlave.father || slave.ID === aliveSlave.mother) {
				relation = (slave.ID === aliveSlave.father ? "father" : "mother");
				feeling = "grieved";
				aliveSlave.devotion -= (slave.ID === aliveSlave.father ? 10 : 20);
				aliveSlave.trust -= (slave.ID === aliveSlave.father ? 10 : 20);
			}
			switch (areSisters(slave, aliveSlave)) {
				case 1:
					relation = "twin";
					feeling = "devastated";
					aliveSlave.devotion -= 30;
					aliveSlave.trust -= 30;
					break;
				case 2:
					relation = `${sister3}`;
					feeling = "grieved";
					aliveSlave.devotion -= 20;
					aliveSlave.trust -= 20;
					break;
				case 3:
					relation = `half-${sister3}`;
					feeling = "disheartened";
					aliveSlave.devotion -= 10;
					aliveSlave.trust -= 10;
					break;
			}
			if (relation) {
				App.Events.addNode(t, [`${aliveSlave.slaveName} is`, App.UI.DOM.makeElement("span", feeling, ["mediumorchid"]), `that you ate ${his3} ${relation} and also`, App.UI.DOM.makeElement("span", "fears", ["gold"]), `that ${his3} turn will be next.`], "div");
			}
		}

		for (const aliveSlave of V.slaves.filter(s => s.fetish !== Fetish.MINDBROKEN && s.devotion >= 85)) {
			let relation;
			let feeling;
			const {his3, sister3, daughter3, He3} = getPronouns(aliveSlave).appendSuffix("3");
			if (slave.mother === aliveSlave.ID || slave.father === aliveSlave.ID) {
				relation = `${daughter3}`;
				feeling = "honored";
				aliveSlave.devotion += (slave.mother === aliveSlave.ID ? 20 : 10);
				aliveSlave.trust += (slave.mother === aliveSlave.ID ? 20 : 10);
			}
			if (slave.ID === aliveSlave.father || slave.ID === aliveSlave.mother) {
				relation = (slave.ID === aliveSlave.father ? "father" : "mother");
				feeling = "honored";
				aliveSlave.devotion += (slave.ID === aliveSlave.father ? 10 : 20);
				aliveSlave.trust += (slave.ID === aliveSlave.father ? 10 : 20);
			}
			switch (areSisters(slave, aliveSlave)) {
				case 1:
					relation = "twin";
					feeling = "honored";
					aliveSlave.devotion += 30;
					aliveSlave.trust += 30;
					break;
				case 2:
					relation = `${sister3}`;
					feeling = "honored";
					aliveSlave.devotion += 20;
					aliveSlave.trust += 20;
					break;
				case 3:
					relation = `half-${sister3}`;
					feeling = "honored";
					aliveSlave.devotion += 10;
					aliveSlave.trust += 10;
					break;
			}
			if (relation) {
				App.Events.addNode(t, [`${aliveSlave.slaveName} is your faithful slut she's`, App.UI.DOM.makeElement("span", feeling, ["hotpink"]), `that you ate ${his3} ${relation} and also`, App.UI.DOM.makeElement("span", "pray", ["mediumaquamarine"]), `that ${his3} turn be next to prove her devotion.`], "div");
			}
		}

		let aliveSlave = V.slaves.find(s => s.ID === slave.relationshipTarget && s.fetish !== Fetish.MINDBROKEN);
		if (slave.relationship !== 0 && aliveSlave) {
			const {his3} = getPronouns(aliveSlave).appendSuffix("3");
			App.Events.addNode(t, [`${aliveSlave.slaveName} is`, App.UI.DOM.makeElement("span", "distraught", ["mediumorchid"]), `that you ate ${his3} best source of comfort and companionship in a life of bondage.`], "div");
			aliveSlave.devotion -= aliveSlave.relationship * 5;
			aliveSlave.devotion -= 20;
		}

		aliveSlave = V.slaves.find(s => s.ID === slave.rivalryTarget && s.fetish !== Fetish.MINDBROKEN);
		if (slave.rivalry !== 0 && aliveSlave) {
			const {his3, He3} = getPronouns(aliveSlave).appendSuffix("3");
			App.Events.addNode(t, [`${aliveSlave.slaveName} is`, App.UI.DOM.makeElement("span", "pleased", ["hotpink"]), `that ${He3} won't have to see ${his3} rival any more.`], "div");
			aliveSlave.devotion += aliveSlave.rivalry * 5;
		}

		r = [];
		r.push(`The slaves who do not already worship you`, App.UI.DOM.makeElement("span", "resent", ["mediumorchid"]), "your monstrous appetite and", App.UI.DOM.makeElement("span", "fear", ["mediumaquamarine"]), "a similar fate awaits them.");
		r.push(`The fat slaves are`, App.UI.DOM.makeElement("span", "worried", ["gold"]), "they are being fattened for consumption.");
		r.push(`But your worshipful chattel are`, App.UI.DOM.makeElement("span", "pleased", ["hotpink"]), "that you could find a use for them even in death and", App.UI.DOM.makeElement("span", "hope", ["mediumaquamarine"]), "a similar fate awaits them.");
		App.Events.addNode(t, r, "p");
		for (const aliveSlave of V.slaves.filter(s => s.fetish !== Fetish.MINDBROKEN && s.devotion < 50)) {
			aliveSlave.devotion -= 5;
			aliveSlave.trust -= (aliveSlave.diet === "fattening" || aliveSlave.weight > 10 ? 10 : 5);
		}

		for (const aliveSlave of V.slaves.filter(s => s.fetish !== Fetish.MINDBROKEN && s.devotion >= 85)) {
			aliveSlave.devotion += 5;
			aliveSlave.trust += 5;
		}

		if (isShelterSlave(slave)) {
			V.shelterAbuse++;
		}
		removeSlave(slave);
		/*
		if (generateEnemies === 1) {
			V.MOD_enemyList = V.MOD_enemyList || [];
			for (let i = 0; i < 6; i++) {
					const pram = {minAge: 38, maxAge: 44, ageOverridesPedoMode: 1, disableDisability: 1};
					slave = GenerateNewSlave(V.seeDicks === 0 ? "XX" : "XY", pram);
					slave.devotion = -20;
					slave.trust = -2;
					slave.oldDevotion = -20;
					slave.origin = "$He was once an arcology owner like yourself, who made the mistake of insulting you.";
					slave.career = "a slave";
					slave.prestige = 3;
					slave.prestigeDesc = "You stormed $his arcology, killed $his guards, and enslaved $him in revenge for insulting you at a dinner party.";
					setHealth(_slave, 20, random(5, 15), 0, 0, 0);
					slave.dick = 5;
					slave.balls = 5;
					slave.intelligenceImplant = 1;
					V.MOD_enemy = {leader: 0, numSlave: 0, slaveTotalHP: 0, numDrone: 0, droneTotalHP: 0, numMerc: 0, mercTotalHP: 0, weekCreated: 0, enemyIndex: -1, hostility: 0};
					V.MOD_enemy.leader = _slave;
					V.MOD_enemy.weekCreated = V.week;
					V.MOD_enemy.numSlave = random(Math.trunc(V.slaves.length * 0.7), Math.trunc(V.slaves.length * 1.3));
					V.MOD_enemy.numDrone = random(25, 75);
					V.MOD_enemy.numMerc = random(10, 60);
					V.MOD_enemyList.push(V.MOD_enemy);
			}
		}
		*/
	} else { // failed evening
		r.push(`With most of your dishes earning a poor rating, your guests are`, App.UI.DOM.makeElement("span", "dissatisfied.", ["red"]));
		r.push(`They take out their frustrations on your slaves. Your slaves are being fucked roughly and abused. Cries of pain and pleads of mercy echoes through your dining hall. You decide to allow the abuse to continue as you do not want to antagonize your guests further. You watch with a forced smile as your favorite slaves are being slapped, whipped, choked and burned with cigarettes.`);
		r.push(`Some of your unlucky slaves had their health`, App.UI.DOM.makeElement("span", "reduced.", ["red"]));
		r.push(`All of your slaves`, App.UI.DOM.makeElement("span", "respect you less", ["mediumorchid"]), "and", App.UI.DOM.makeElement("span", "fear", ["gold"]), "you more as you place your reputation above their wellbeing.");
		App.Events.addNode(t, r, "p");

		repX(forceNeg(dinnerRating * 100), "event");
		for (const aliveSlave of V.slaves) {
			if (random(0, 1) > 0) {
				healthDamage(aliveSlave, 10);
			}
			aliveSlave.devotion -= 5;
			aliveSlave.trust -= 5;
		}

		if (V.HeadGirlID !== 0 && slave.assignment !== "be your Head Girl") {
			const {His2, He2, his2, he2, him2, girl2, himself2} = getPronouns(S.HeadGirl).appendSuffix("2");
			r = [];
			r.push(`You notice a group of guests corner your Head Girl. The group consists of some very powerful people. Most of them arcology owners themselves, some of them have more powerful arcologies than yours.`);
			r.push(`${S.HeadGirl.slaveName} tries to slip away, but ${he2} was grabbed at the neck by the leader of the pack. He pulls ${him2} down to the ground forcefully.`);
			r.push(`${S.HeadGirl.slaveName} knows better than to resist, ${he2} is still a slave despite ${his2} position as your Head Girl. A slave does not raise their hand against a Master, even one that's not ${his2} own.`);
			r.push(`The leader rips off ${his2} dress, exposing ${his2} bare chest. Your Head Girl is frozen in terror when ${he2} is lifted onto the hastily cleared dining hall table by several of the men. ${His2} eyes desperately search for you.`);
			r.push(`You are the only one who can stop this. All that's required is a single word from you.`);
			r.push(`${S.HeadGirl.slaveName}'s eyes meets yours; the look of relief on ${his2} face is soon replaced by the sad realization that you will not intervene.`);
			r.push(`${His2} mouth just barely forms the word "${getWrittenTitle(S.HeadGirl)}" as you shake your head, so ${He2} closes ${his2} mouth and resigns ${himself2} to ${his2} fate.`);
			App.Events.addNode(t, r, "div");

			r = [];
			r.push(`Your Head Girl is placed across the corner of the dining hall table face-down, ${his2} arm${hasBothArms(S.HeadGirl) ? 's' : ''} and leg${hasBothLegs(S.HeadGirl) ? 's' : ''} held down by four men. ${He2} finds a hand on ${his2} ass, groping roughly, then another hand on the other cheek, roughly parting ${his2} globes to get better access.`);
			if (S.HeadGirl.vagina >= 0 && canDoVaginal(S.HeadGirl)) {
				r.push(`A finger traces along ${his2} slit, finding the source of that moisture and pressing its way in. Another finger was added and the hand began to finger fuck ${him2} roughly. After a few seconds a third finger was added and then a fourth, stretching ${his2} pussy.`);
				r.push(`${S.HeadGirl.slaveName} screams loudly as the entire hand was shoved up ${his2} cunt without warning.`);
				r.push(`${his2} pussy has`, App.UI.DOM.makeElement("span", "loosened", ["lime"]));
				S.HeadGirl.vagina++;
			}
			r.push(`One man moves to the head of ${S.HeadGirl.slaveName} and shoved his cock into ${his2} mouth, fucking ${his2} throat roughly. He buries his cock deep down ${his2} throat all the way to his balls.`);
			r.push(`He places both hands around ${his2} neck and squeezes with every stroke. Your Head Girl's face turns red and ${He2} gags uncontrollably. ${his2} eyes roll back as another man shoves his hard cock in ${his2} asshole, sodomizing ${him2} with no mercy.`);
			r.push(`As your Head Girl makes squeaking noises in pain, several guests pick up forks and jab it at ${his2} butt and ${his2} back, chanting "More meat... More meat..." and "Squeal, piggy, squeal." You slump over your chair at the head of the table. Gulping down your drink, you suppress the urge to order your security drones to open fire on those men.`);
			r.push(`You know they would never dare to harm your Head Girl, not permanently, at least not anything your remote surgery couldn't fix. It's not as if you haven't done worse to your slaves, but the message is clear; the attack on your Head Girl was meant as disrespect and an insult towards you. Raping your Head Girl is like raping you.`);
			r.push(`You stare at the group of men gang raping your Head Girl at the end of your own dining table, burning their`, App.UI.DOM.makeElement("span", "names and their faces", ["yellow"]), `into your memory as they take turns fucking ${him2}. They make use of ${his2} every hole. When they are done, ${He2} is left on the floor, battered and bruised, covered in cum and blood from superficial wounds.`);
			r.push(`The leader of the pack pulls out his half erect cock and`);
			if (V.seePee === 1) {
				r.push(`pees on your Head Girl as a final insult towards you. The poor ${girl2} is so spent that ${He2} doesn't even flinch at the urine hitting ${his2} face. He finishes showering your Head Girl, then`);
			} else {
				r.push(`ejaculates all over your Head Girl's face, clearly and intentionally aiming for ${his2} eyes. The poor ${girl2} is so spent that ${He2} doesn't even flinch from this final insult towards you. When he's done, he`);
			}
			r.push(`turns towards you and says smilingly:`);
			App.Events.addNode(t, r, "div");

			r = [];
			r.push(App.UI.DOM.makeElement("span", `"I must congratulate you ${V.PC.title > 0 ? 'sir' : 'madam'},`, ["note"]));
			r.push(App.UI.DOM.makeElement("span", `you trained a fine obedient slave. ${He2} certainly understands ${his2} position well."`, ['note']));
			r.push(`You grit your teeth faking a smile, mentally repeating the old adage:`, App.UI.DOM.makeElement("span", "revenge is dish best served cold.", ["yellow"]), `You have made some enemies tonight; you begin to plan a military conquest of them all. You will enjoy storming their arcologies and making them pay for this insult.`);
			App.Events.addNode(t, r, "p");

			App.Events.addNode(t, [`The abuse your Head Girl suffers had`, App.UI.DOM.makeElement("span", `decreased ${his2} health`, ["health", "dec"]), `${his2} and ${He2} is`, App.UI.DOM.makeElement("span", "less devoted", ["mediumorchid"]), `to you, as you allowed ${him2} to be abused.`], "div");
			healthDamage(S.HeadGirl, 20);
			S.HeadGirl.devotion -= 20;
		}

		App.Events.addNode(t, [], "p");
		// Clean up and slaves reactions
		App.Events.addNode(t, ["When the last of your guests has stumbled drunkenly out your door, your slaves begin the daunting task of cleanup."], "div");
		for (const aliveSlave of V.slaves.filter(s => s.fetish !== Fetish.MINDBROKEN && s.devotion < 50)) {
			let relation;
			let feeling;
			const {his3, sister3, daughter3, He3} = getPronouns(aliveSlave).appendSuffix("3");
			if (slave.mother === aliveSlave.ID || slave.father === aliveSlave.ID) {
				relation = `${daughter3}`;
				feeling = "distraught";
				aliveSlave.devotion -= (slave.mother === aliveSlave.ID ? 20 : 10);
				aliveSlave.trust -= (slave.mother === aliveSlave.ID ? 20 : 10);
			}
			if (slave.ID === aliveSlave.father || slave.ID === aliveSlave.mother) {
				relation = (slave.ID === aliveSlave.father ? "father" : "mother");
				feeling = "grieved";
				aliveSlave.devotion -= (slave.ID === aliveSlave.father ? 10 : 20);
				aliveSlave.trust -= (slave.ID === aliveSlave.father ? 10 : 20);
			}
			switch (areSisters(slave, aliveSlave)) {
				case 1:
					relation = "twin";
					feeling = "devastated";
					aliveSlave.devotion -= 30;
					aliveSlave.trust -= 30;
					break;
				case 2:
					relation = `${sister3}`;
					feeling = "grieved";
					aliveSlave.devotion -= 20;
					aliveSlave.trust -= 20;
					break;
				case 3:
					relation = `half-${sister3}`;
					feeling = "disheartened";
					aliveSlave.devotion -= 10;
					aliveSlave.trust -= 10;
					break;
			}
			if (relation) {
				App.Events.addNode(t, [`${aliveSlave.slaveName} is`, App.UI.DOM.makeElement("span", feeling, ["mediumorchid"]), `that you ate ${his3} ${relation} and also`, App.UI.DOM.makeElement("span", "fears", ["gold"]), `that ${his3} turn will be next.`], "div");
			}
		}

		for (const aliveSlave of V.slaves.filter(s => s.fetish !== Fetish.MINDBROKEN && s.devotion >= 85)) {
			let relation;
			let feeling;
			const {his3, sister3, daughter3, He3} = getPronouns(aliveSlave).appendSuffix("3");
			if (slave.mother === aliveSlave.ID || slave.father === aliveSlave.ID) {
				relation = `${daughter3}`;
				feeling = "honored";
				aliveSlave.devotion += (slave.mother === aliveSlave.ID ? 20 : 10);
				aliveSlave.trust += (slave.mother === aliveSlave.ID ? 20 : 10);
			}
			if (slave.ID === aliveSlave.father || slave.ID === aliveSlave.mother) {
				relation = (slave.ID === aliveSlave.father ? "father" : "mother");
				feeling = "honored";
				aliveSlave.devotion += (slave.ID === aliveSlave.father ? 10 : 20);
				aliveSlave.trust += (slave.ID === aliveSlave.father ? 10 : 20);
			}
			switch (areSisters(slave, aliveSlave)) {
				case 1:
					relation = "twin";
					feeling = "honored";
					aliveSlave.devotion += 30;
					aliveSlave.trust += 30;
					break;
				case 2:
					relation = `${sister3}`;
					feeling = "honored";
					aliveSlave.devotion += 20;
					aliveSlave.trust += 20;
					break;
				case 3:
					relation = `half-${sister3}`;
					feeling = "honored";
					aliveSlave.devotion += 10;
					aliveSlave.trust += 10;
					break;
			}
			if (relation) {
				App.Events.addNode(t, [`${aliveSlave.slaveName} is your faithful slut she's`, App.UI.DOM.makeElement("span", feeling, ["hotpink"]), `that you ate ${his3} ${relation} and also`, App.UI.DOM.makeElement("span", "pray", ["mediumaquamarine"]), `that ${his3} turn be next to prove her devotion.`], "div");
			}
		}

		let aliveSlave = V.slaves.find(s => s.ID === slave.relationshipTarget && s.fetish !== Fetish.MINDBROKEN);
		if (slave.relationship !== 0 && aliveSlave) {
			const {his3} = getPronouns(aliveSlave).appendSuffix("3");
			App.Events.addNode(t, [`${aliveSlave.slaveName} is`, App.UI.DOM.makeElement("span", "distraught", ["mediumorchid"]), `that you ate ${his3} best source of comfort and companionship in a life of bondage.`], "div");
			aliveSlave.devotion -= aliveSlave.relationship * 5;
			aliveSlave.devotion -= 20;
		}

		aliveSlave = V.slaves.find(s => s.ID === slave.rivalryTarget && s.fetish !== Fetish.MINDBROKEN);
		if (slave.rivalry !== 0 && aliveSlave) {
			const {his3, He3} = getPronouns(aliveSlave).appendSuffix("3");
			App.Events.addNode(t, [`${aliveSlave.slaveName} is`, App.UI.DOM.makeElement("span", "pleased", ["hotpink"]), `that ${He3} won't have to see ${his3} rival any more.`], "div");
			aliveSlave.devotion += aliveSlave.rivalry * 5;
		}

		r = [];
		r.push(`The slaves who do not already worship you`, App.UI.DOM.makeElement("span", "resent", ["mediumorchid"]), "your monstrous appetite and", App.UI.DOM.makeElement("span", "fear", ["mediumaquamarine"]), "a similar fate awaits them.");
		r.push(`The fat slaves are`, App.UI.DOM.makeElement("span", "worried", ["gold"]), "they are being fattened for consumption.");
		r.push(`But your worshipful chattel are`, App.UI.DOM.makeElement("span", "pleased", ["hotpink"]), "that you could find a use for them even in death and", App.UI.DOM.makeElement("span", "hope", ["mediumaquamarine"]), "a similar fate awaits them.");
		App.Events.addNode(t, r, "p");
		for (const aliveSlave of V.slaves.filter(s => s.fetish !== Fetish.MINDBROKEN && s.devotion < 50)) {
			aliveSlave.devotion -= 5;
			aliveSlave.trust -= (aliveSlave.diet === "fattening" || aliveSlave.weight > 10 ? 10 : 5);
		}

		for (const aliveSlave of V.slaves.filter(s => s.fetish !== Fetish.MINDBROKEN && s.devotion >= 85)) {
			aliveSlave.devotion += 5;
			aliveSlave.trust += 5;
		}

		if (isShelterSlave(slave)) {
			V.shelterAbuse++;
		}
		removeSlave(slave);
		/*
		if (generateEnemies === 1) {
			V.MOD_enemyList = V.MOD_enemyList || [];
			for (let i = 0; i < 6; i++) {
					const pram = {minAge: 38, maxAge: 44, ageOverridesPedoMode: 1, disableDisability: 1};
					slave = GenerateNewSlave(V.seeDicks === 0 ? "XX" : "XY", pram);
					slave.devotion = -20;
					slave.trust = -2;
					slave.oldDevotion = -20;
					slave.origin = "$He was once an arcology owner like yourself, who made the mistake of insulting you.";
					slave.career = "a slave";
					slave.prestige = 3;
					slave.prestigeDesc = "You stormed $his arcology, killed $his guards, and enslaved $him in revenge for insulting you at a dinner party.";
					setHealth(_slave, 20, random(5, 15), 0, 0, 0);
					slave.dick = 5;
					slave.balls = 5;
					slave.intelligenceImplant = 1;
					V.MOD_enemy = {leader: 0, numSlave: 0, slaveTotalHP: 0, numDrone: 0, droneTotalHP: 0, numMerc: 0, mercTotalHP: 0, weekCreated: 0, enemyIndex: -1, hostility: 0};
					V.MOD_enemy.leader = _slave;
					V.MOD_enemy.weekCreated = V.week;
					V.MOD_enemy.numSlave = random(Math.trunc(V.slaves.length * 0.7), Math.trunc(V.slaves.length * 1.3));
					V.MOD_enemy.numDrone = random(25, 75);
					V.MOD_enemy.numMerc = random(10, 60);
					V.MOD_enemyList.push(V.MOD_enemy);
			}
		}
		*/
	}

	return t;
	/**
	 * @param {string} name title of dish
	 */
	function getDish(name) {
		const t = new DocumentFragment();
		let r = [];
		let dishRating = 5;
		let override;

		if (name !== "Roast Long Pig") {
			r.push(`The next course is ${name === "Baby Veal Ragout" ? `a bonus dish` : ``}`);
		} else {
			r.push('Your slaves begin to serve the main course,');
		}
		r.push(App.UI.DOM.makeElement("span", `${name}:`, ["bold", "note"]));

		switch (name) {
			case "Dicky Roll":
				dishRating = slave.dick; // the dick is numbered from 0 to 5 - this isn't a problem at all
				r.push(`${slave.slaveName}'s penis is wrapped in a spring roll wrapper, deep fried and placed on a plate. Green lettuce decorates the plate along with a side of dipping sauce.`);
				if (slave.dick >= 5) {
					r.push(`The massive length and girth of the penis impressed your guests greatly and have them all salivating at the sight of the dish.`);
				} else if (slave.dick >= 4) {
					r.push(`The large size of the penis impressed your guests and have them salivating at the sight of the dish.`);
				} else if (slave.dick >= 3) {
					r.push(`The regular size of the penis did not impress your guests much. Nevertheless they are looking forward to tasting the delicacy.`);
				} else if (slave.dick >= 2) {
					r.push(`The small size of the penis had your guests disappointed at the size of the dish.`);
				} else {
					r.push(`The tiny size of the penis had your guests laughing at the disappointing dish.`);
				}
				if (slave.balls >= 5) {
					r.push(`As you bite into the dick your palate is treated with a rich salty taste at the center of your dicky roll. You smile as you know this is the taste of cum trapped in the shaft of the penis at the moment of death. Your guests also greatly enjoy this exotic taste.`);
				} else if (slave.balls >= 4) {
					r.push(`As you bite into the dick your palate is treated with a distinct salty taste at the center of your dicky roll. You smile as you know this is the taste of cum trapped in the shaft of the penis at the moment of death. Your guests also enjoy this exotic taste.`);
					dishRating -= 0.5;
				} else if (slave.balls >= 3) {
					r.push(`As you bite into the dick your palate is treated with a faint salty taste at the center of your dicky roll. You smile as you know this is the taste of cum trapped in the shaft of the penis at the moment of death. Your guests also enjoy this exotic taste.`);
					dishRating--;
				} else if (slave.balls >= 2) {
					r.push(`As you bite into the dick your palate is treated with a hint of salty taste at the center of your dicky roll. You smile as you know this is the taste of cum trapped in the shaft of the penis at the moment of death. Your guests also enjoy this exotic taste.`);
					dishRating -= 1.5;
				} else if (slave.balls >= 1) {
					r.push(`As you bite into the dick your palate is treated with barely a hint of salty taste at the center of your dicky roll. You smile as you know this is the taste of cum trapped in the shaft of the penis at the moment of death. Your guests also enjoy this exotic taste.`);
					dishRating -= 2;
				} else {
					r.push(`As you bite into the dick you feel as if this dish is missing something. A certain 'je ne sais quoi'.`);
					dishRating -= 2.5;
				}
				break;
			case "Testy Meat Balls":
				dishRating = slave.balls; // I give up. Each and every dish will need a rework and score redesign. Definitely some crazy potential with FSs to do some interesting things.
				App.Events.addNode(t, [`${slave.slaveName}'s balls are coated in olive oil and sautéed.`]);
				break;
			case "Camel Toe steak":
				r.push(`${slave.slaveName}'s pussy is grilled like a steak.`);
				if (slave.clit >= 2) { // These would all need to take into account clitoral hoods
					r.push(`${His} huge clit sticking out of the camel toe is the cherry on top for this dish.`);
				} else if (slave.clit >= 1) {
					r.push(`${His} large clit sticking out of the camel toe makes this dish aesthetically pleasing.`);
					dishRating -= 0.5;
				} else if (slave.dick >= 5) {
					r.push(`${His} large cock head cut in two and positioned on each side of the camel toe makes it the cherry on top for this dish.`);
				} else if (slave.dick < 5) {
					r.push(`${His} tiny cock head cut in two and positioned on each side of the camel toe makes this dish aesthetically pleasing.`);
					dishRating -= 0.5;
				} else {
					r.push(`${His} small clit is hiding inside of the camel toe. It does not add to the scheme of this dish.`);
					dishRating -= 2;
				}
				if (slave.labia >= 2) {
					r.push(`${His} huge labia taste delicious.`);
				} else if (slave.labia >= 1) {
					r.push(`${His} large labia is tasty.`);
					dishRating -= 0.5;
				} else {
					r.push(`${His} small labia leave you and your guests wanting more.`);
					dishRating -= 2;
				}
				break;
			case "Baby Veal Ragout":
				override = true;
				r.push(`${slave.slaveName} was pregnant so ${he} has a special bonus dish to offer your guests. ${His} fetus is boiled in a vinegar stock and stewed in butter.`);
				if (slave.preg >= slave.pregData.normalBirth/1.6) {
					r.push(`Your guests are pleased with the huge size of the dish.`);
				} else if (slave.preg >= slave.pregData.normalBirth/2) {
					r.push(`Your guests are pleased with the large size of the dish.`);
					dishRating--;
				} else if (slave.preg >= slave.pregData.normalBirth/2.66) {
					r.push(`Your guests are satisfied with the decent size of the dish.`);
					dishRating -= 2;
				} else {
					r.push(`Your guests are a little disappointed with the small size of the dish.`);
					dishRating -= 3;
				}
				break;
			case "Titty Tartare":
				r.push(`${slave.slaveName}'s tits are chopped into tiny cube size pieces mixed with onions, capers and seasoning. It is served raw with an egg yolk on top and a side of French fries.`);
				if (slave.boobsImplant > 0) {
					r.push(`As you and your guests take your first bite of the tartare you immediately spit out the meat. Who would have thought silicone is not edible.`);
					r.push(`You have neglected to remove ${his} breast implants before serving the titty tartare. The dish is now ruined. Your guests are`, App.UI.DOM.makeElement("span", "displeased", ["red"]), `by your lack of attention to detail.`);
					dishRating = 0;
					repX(-500, "event");
				} else {
					if (slave.boobs >= 4800) {
						r.push(`${His} monstrous boobs are very tender and juicy. There are also enough servings to keep all of your guests satisfied.`);
					} else if (slave.boobs >= 2400) {
						r.push(`${His} massive boobs are tender and juicy. Your guests are satisfied with the generous portions.`);
						dishRating--;
					} else if (slave.boobs >= 1600) {
						r.push(`${His} huge boobs are tender. Your guests are satisfied with the portions.`);
						dishRating -= 2;
					} else if (slave.boobs >= 800) {
						r.push(`${His} big boobs are tender and tasty. Your guests are satisfied with the portions, but wished for more.`);
						dishRating -= 3;
					} else if (slave.boobs >= 500) {
						r.push(`${His} small boobs are tender. Your guests are disappointed with their portions.`);
						dishRating -= 4;
					} else {
						r.push(`${His} non-existent boobs leaves your guests disappointed.`);
						dishRating -= 5;
					}
					if (slave.lactation >= 2) {
						r.push(`As you and your guests enjoy your tartare, suddenly you hear a loud crunch coming from the guest sitting right next to you.`);
						r.push(`You see blood spewing from his mouth as he spits out his chipped tooth along with a lactation implant.`);
						r.push(`You apologize profusely and pay the man ${num(10000)} as compensation.`);
						r.push(`The rest of your guests are`, App.UI.DOM.makeElement("span", "not happy", ["red"]), `that you serve them drugged meat.`);
						dishRating = 0;
						repX(-1000, "event");
						cashX(-10000, "event");
					} else if (slave.lactation > 0) {
						r.push(`You detect a hint of creamy taste to your tartare. The clearly lactating breast earns the dish an extra star.`);
						dishRating++;
					}
				}
				break;
			case "Roast Long Pig":
				r.push(`${slave.slaveName} is carried out with ${his} carcass roasted to a perfect golden brown color. ${He} is coated with BBQ sauce and dripping in ${his} own juices. The apple is still in ${his} mouth.`);
				if (slave.vagina === 0) {
					r.push(`${slave.slaveName} was a virgin. Eating of maiden meat is thought to be highly prestigious. It earns you an extra star for this dish.`);
					dishRating++;
				}
				if (slave.physicalAge >= 60) {
					r.push(`${slave.slaveName} was old. ${His} meat is tough and leathery.`);
					dishRating -= 2;
				} else if (slave.physicalAge >= 40) {
					r.push(`${slave.slaveName} was middle aged. ${His} meat is stringy.`);
					dishRating--;
				} else if (slave.physicalAge >= 20) {
					r.push(`${slave.slaveName} was young. ${His} meat is tender.`);
				} else {
					r.push(`${slave.slaveName} was very young. ${His} meat is very tender.`);
					dishRating++;
				}
				if (slave.weight > 95) {
					r.push(`${slave.slaveName} was too fat. It made the dish taste very greasy.`);
					dishRating -= 2;
				} else if (slave.weight > 30) {
					r.push(`${slave.slaveName} was fat. It made the dish taste greasy.`);
					dishRating--;
				} else if (slave.weight > 10) {
					r.push(`${slave.slaveName} was juicy and yet not greasy. ${He} is a prime piece of meat.`);
					dishRating += 0.5;
				} else if (slave.weight >= -10) {
					r.push(`${slave.slaveName} was lean. ${He} is a good piece of meat.`);
				} else if (slave.weight >= -30) {
					r.push(`${slave.slaveName} was thin. ${He} does not provide enough meat for you and your guests.`);
					dishRating -= 0.5;
				} else if (slave.weight >= -95) {
					r.push(`${slave.slaveName} was too skinny. ${He} has very little meat on the bones.`);
					dishRating--;
				} else {
					r.push(`${slave.slaveName} was emaciated. ${He} has only bones and skin.`);
					dishRating -= 2;
				}
				if (slave.muscles > 95) {
					r.push(`${slave.slaveName} has too much muscle and sinew. ${His} meat is too chewy.`);
					dishRating -= 0.5;
				} else if (slave.muscles > 50) {
					r.push(`${slave.slaveName} has strong muscles. It gives ${his} meat a very tasty texture.`);
					dishRating += 0.5;
				} else if (slave.muscles > 5) {
					r.push(`${slave.slaveName} has toned muscles. It gives ${his} meat a tasty texture.`);
				} else {
					r.push(`${slave.slaveName} has no muscles. It gives ${his} meat a plain texture.`);
					dishRating--;
				}
				if (slave.lipsImplant > 0) {
					r.push(`All of sudden one of your guests' face turns red, then purple. It is clear he is choking on something.`);
					r.push(`You leap out of your seat, rush over to him and start the Heimlich maneuver.`);
					r.push(`On your third thrust into his abdominal, a piece of lip implants flies out of his mouth and hits another guest square in the face.`);
					r.push(`You apologize profusely for your carelessness in selecting the meat. The rest of your guests had a great laugh at your`, App.UI.DOM.makeElement("span", "expense.", ["red"]));
					dishRating -= 5;
					repX(-500, "event");
				} else if (slave.buttImplant > 0) {
					r.push(`All of sudden one of your guests clutches his chest. His face turns pale as a ghost, foaming at the mouth falls over onto the table.`);
					r.push(`You rush over to him, it is clear he is not breathing. You don't know what's wrong with him.`);
					r.push(`It could not have been poison, since any toxins in the food would have been detected by your personal assistant. You order your slave to rush the man to the nearest emergency clinic.`);
					r.push(`You were informed later that he had died from ingesting a silicone butt implant. Your reputation`, App.UI.DOM.makeElement("span", "suffers", ["red"]), `greatly due to this incident.`);
					dishRating -= 10;
					repX(-5000, "event");
				}
				break;
		}
		App.Events.addNode(t, r, "div");

		dishRating = Math.clamp(dishRating, 0, 5);
		dinnerRating += dishRating;

		r = [];
		r.push(`This dish earned a score of ${dishRating} out of 5 stars. Your reputation has`);
		r.push(App.UI.DOM.makeElement("span", (dishRating >= 2 || override ? "increased." : "decreased."), [dishRating >= 2 || override ? "green" : "red"]));
		if (dishRating >= 2 || override) {
			repX(dishRating * 100, "event");
		} else {
			repX(forceNeg(dishRating >= 0 ? (dishRating * 20) : 100), "event");
		}
		App.Events.addNode(t, r, "div");

		return App.UI.DOM.makeElement("p", t);
	}
};


code:
App.Mods.SecExp.BC = (function() {
	return {
		propHub,
		riotCenter,
		barracks,
		weaponsManufacturing,
		transportHub,
		secHub
	};

	function propHub() {
		if (V.SecExp.buildings.pr === null) {
			delete V.SecExp.buildings.pr;
		}
		if (V.SecExp.buildings.pr) {
			V.SecExp.buildings.propHub = V.SecExp.buildings.pr;
			delete V.SecExp.buildings.pr;
		}

		if (V.SecExp.buildings.propHub) {
			delete V.SecExp.buildings.propHub.active;
		}
		if (V.SecExp.buildings.propHub && Object.entries(V.SecExp.buildings.propHub).length === 0) {
			delete V.SecExp.buildings.propHub;
		} else if (V.propHub || (V.SecExp.buildings.propHub && Object.entries(V.SecExp.buildings.propHub).length > 0)) {
			V.SecExp.buildings.propHub = V.SecExp.buildings.propHub || {};
			V.SecExp.buildings.propHub.upgrades = V.SecExp.buildings.propHub.upgrades || {};
			V.SecExp.buildings.propHub.recruiterOffice = V.SecExp.buildings.propHub.recruiterOffice || V.SecExp.buildings.propHub.recuriterOffice || V.recuriterOffice || V.RecuriterOffice || 0;
			delete V.SecExp.buildings.propHub.recuriterOffice;

			V.SecExp.buildings.propHub.upgrades.campaign = V.SecExp.buildings.propHub.upgrades.campaign || V.SecExp.buildings.propHub.campaign || V.propCampaign || 0;
			delete V.SecExp.buildings.propHub.campaign;
			V.SecExp.buildings.propHub.upgrades.miniTruth = V.SecExp.buildings.propHub.upgrades.miniTruth || V.SecExp.buildings.propHub.miniTruth || V.miniTruth || 0;
			delete V.SecExp.buildings.propHub.miniTruth;

			V.SecExp.buildings.propHub.upgrades.secretService = V.SecExp.buildings.propHub.upgrades.secretService || V.SecExp.buildings.propHub.secretService || V.SecExp.buildings.propHub.SS || V.secretService || 0;
			delete V.SecExp.buildings.propHub.secretService;
			delete V.SecExp.buildings.propHub.SS;

			V.SecExp.buildings.propHub.focus = V.SecExp.buildings.propHub.focus || "social engineering";
			if (V.propFocus && V.propFocus !== "none") {
				V.SecExp.buildings.propHub.focus = V.propFocus;
			}

			V.SecExp.buildings.propHub.upgrades.fakeNews = V.SecExp.buildings.propHub.upgrades.fakeNews || V.SecExp.buildings.propHub.fakeNews || V.fakeNews || 0;
			delete V.SecExp.buildings.propHub.fakeNews;

			V.SecExp.buildings.propHub.upgrades.controlLeaks = V.SecExp.buildings.propHub.upgrades.controlLeaks || V.SecExp.buildings.propHub.controlLeaks || V.controlLeaks || 0;
			delete V.SecExp.buildings.propHub.controlLeaks;

			V.SecExp.buildings.propHub.upgrades.marketInfiltration = V.SecExp.buildings.propHub.upgrades.marketInfiltration || V.SecExp.buildings.propHub.marketInfiltration || V.marketInfiltration || 0;
			delete V.SecExp.buildings.propHub.marketInfiltration;

			V.SecExp.buildings.propHub.upgrades.blackOps = V.SecExp.buildings.propHub.upgrades.blackOps || V.SecExp.buildings.propHub.blackOps || V.blackOps || 0;
			delete V.SecExp.buildings.propHub.blackOps;
		}
	}

	function riotCenter() {
		if (V.riotCenter || (V.SecExp.buildings.riotCenter && Object.entries(V.SecExp.buildings.riotCenter).length > 0)) {
			V.SecExp.buildings.riotCenter = V.SecExp.buildings.riotCenter || {};
			V.SecExp.buildings.riotCenter.upgrades = V.SecExp.buildings.riotCenter.upgrades || V.riotUpgrades || {};
			V.SecExp.buildings.riotCenter.fort = V.SecExp.buildings.riotCenter.fort || V.fort || {};

			V.SecExp.buildings.riotCenter.upgrades.freeMedia = V.SecExp.buildings.riotCenter.upgrades.freeMedia || 0;
			V.SecExp.buildings.riotCenter.upgrades.rapidUnit = V.SecExp.buildings.riotCenter.upgrades.rapidUnit || 0;
			V.SecExp.buildings.riotCenter.upgrades.rapidUnitSpeed = V.SecExp.buildings.riotCenter.upgrades.rapidUnitSpeed || 0;

			V.SecExp.buildings.riotCenter.fort.reactor = V.SecExp.buildings.riotCenter.fort.reactor || 0;
			V.SecExp.buildings.riotCenter.fort.waterway = V.SecExp.buildings.riotCenter.fort.waterway || 0;
			V.SecExp.buildings.riotCenter.fort.assistant = V.SecExp.buildings.riotCenter.fort.assistant || 0;

			V.SecExp.buildings.riotCenter.sentUnitCooldown = V.SecExp.buildings.riotCenter.sentUnitCooldown || V.sentUnitCooldown || 0;
			V.SecExp.buildings.riotCenter.advancedRiotEquip = V.SecExp.buildings.riotCenter.advancedRiotEquip || V.advancedRiotEquip || 0;
			V.SecExp.buildings.riotCenter.brainImplant = V.SecExp.buildings.riotCenter.brainImplant || -1;
			if (jsDef(V.brainImplant)) {
				V.SecExp.buildings.riotCenter.brainImplant = V.brainImplant;
			}
			V.SecExp.buildings.riotCenter.brainImplantProject = V.SecExp.buildings.riotCenter.brainImplantProject || V.brainImplantProject || 0;
		}
	}

	function barracks() {
		if (V.SecExp.buildings.barracks) {
			delete V.SecExp.buildings.barracks.active;
		}
		if (V.SecExp.buildings.barracks && Object.entries(V.SecExp.buildings.barracks).length === 0) {
			delete V.SecExp.buildings.barracks;
		} else if (V.secBarracks || (V.SecExp.buildings.barracks && Object.entries(V.SecExp.buildings.barracks).length > 0)) {
			V.SecExp.buildings.barracks = V.SecExp.buildings.barracks || V.secBarracksUpgrades || {};
			V.SecExp.buildings.barracks.size = V.SecExp.buildings.barracks.size || 0;
			V.SecExp.buildings.barracks.luxury = V.SecExp.buildings.barracks.luxury || 0;
			V.SecExp.buildings.barracks.training = V.SecExp.buildings.barracks.training || 0;
			V.SecExp.buildings.barracks.loyaltyMod = V.SecExp.buildings.barracks.loyaltyMod || 0;
			if (V.SecExp.buildings.barracks.upgrades) {
				V.SecExp.buildings.barracks.size = V.SecExp.buildings.barracks.upgrades.size;
				V.SecExp.buildings.barracks.luxury = V.SecExp.buildings.barracks.upgrades.luxury;
				V.SecExp.buildings.barracks.training = V.SecExp.buildings.barracks.upgrades.training;
				V.SecExp.buildings.barracks.loyaltyMod = V.SecExp.buildings.barracks.upgrades.loyaltyMod;
				delete V.SecExp.buildings.barracks.upgrades;
			}
		}
	}

	function weaponsManufacturing() {
		if (V.weapManu || (V.SecExp.buildings.weapManu && Object.entries(V.SecExp.buildings.weapManu).length > 0)) {
			V.SecExp.buildings.weapManu = V.SecExp.buildings.weapManu || {};
			V.SecExp.buildings.weapManu.space = V.SecExp.buildings.weapManu.space || 500;
			V.SecExp.buildings.weapManu.menials = V.SecExp.buildings.weapManu.menials || V.weapMenials || V.weapHelots || 0;
			V.SecExp.buildings.weapManu.productivity = V.SecExp.buildings.weapManu.productivity || V.weapProductivity || 1;
			V.SecExp.buildings.weapManu.lab = V.SecExp.buildings.weapManu.lab || V.weapLab || 1;
			V.SecExp.buildings.weapManu.sellTo = V.SecExp.buildings.weapManu.sellTo || V.sellTo || {};
			if (!jsDef(V.SecExp.buildings.weapManu.sellTo.citizen)) {
				V.SecExp.buildings.weapManu.sellTo.citizen = 1;
			}
			if (!jsDef(V.SecExp.buildings.weapManu.sellTo.raiders)) {
				V.SecExp.buildings.weapManu.sellTo.raiders = 1;
			}
			if (!jsDef(V.SecExp.buildings.weapManu.sellTo.oldWorld)) {
				V.SecExp.buildings.weapManu.sellTo.oldWorld = 1;
			}
			if (!jsDef(V.SecExp.buildings.weapManu.sellTo.FC)) {
				V.SecExp.buildings.weapManu.sellTo.FC = 1;
			}

			V.SecExp.buildings.weapManu.upgrades = V.SecExp.buildings.weapManu.upgrades || {};
			V.SecExp.buildings.weapManu.upgrades.completed = V.SecExp.buildings.weapManu.upgrades.completed || V.completedUpgrades || [];
			if (!App.Mods.SecExp.weapManu.completed()) {
				V.SecExp.buildings.weapManu.upgrades.queue = V.SecExp.buildings.weapManu.upgrades.queue || [];
				if (jsDef(V.currentUpgrade)) {
					if (!jsDef(V.currentUpgrade.ID)) {
						if (V.currentUpgrade.name === "magnetic based ballistic weaponry") {
							V.currentUpgrade.ID = 0;
						} else if (V.currentUpgrade.name === "ceramo-metallic alloys") {
							V.currentUpgrade.ID = 1;
						} else if (V.currentUpgrade.name === "rapid action stimulants") {
							V.currentUpgrade.ID = 2;
						} else if (V.currentUpgrade.name === "fast response neural stimulant") {
							V.currentUpgrade.ID = 3;
						} else if (V.currentUpgrade.name === "universal cyber enhancements") {
							V.currentUpgrade.ID = 4;
						} else if (V.currentUpgrade.name === "remote neural links") {
							V.currentUpgrade.ID = 5;
						} else if (V.currentUpgrade.name === "combined training regimens with the special force") {
							V.currentUpgrade.ID = 6;
						} else if (V.currentUpgrade.name === "a variant of the stimulant cocktail that the special force created") {
							V.currentUpgrade.ID = 7;
						} else if (V.currentUpgrade.name === "a mesh network based off the custom network of the special force") {
							V.currentUpgrade.ID = 8;
						} else if (V.currentUpgrade.name === "dynamic battle aware AI") {
							V.currentUpgrade.ID = -1;
						} else if (V.currentUpgrade.name === "adaptive armored frames") {
							V.currentUpgrade.ID = -2;
						} else if (V.currentUpgrade.name === "advanced synthetic alloys") {
							V.currentUpgrade.ID = -3;
						}
					}
					V.SecExp.buildings.weapManu.upgrades.queue.push({ID: V.currentUpgrade.ID, time: V.currentUpgrade.time});
				}

				if (jsDef(V.SecExp.buildings.weapManu.upgrades.current)) {
					if (V.SecExp.buildings.weapManu.upgrades.current.time > 0) {
						V.SecExp.buildings.weapManu.upgrades.queue.push(V.SecExp.buildings.weapManu.upgrades.current);
					}
					delete V.SecExp.buildings.weapManu.upgrades.current;
				}
			} else {
				delete V.SecExp.buildings.weapManu.upgrades.queue;
			}
		}
	}

	function transportHub() {
		if (V.transportHub || (V.SecExp.buildings.transportHub && Object.entries(V.SecExp.buildings.transportHub).length > 0)) {
			V.SecExp.buildings.transportHub = V.SecExp.buildings.transportHub || {};
			V.SecExp.buildings.transportHub.airport = V.SecExp.buildings.transportHub.airport || V.airport || 1;
			V.SecExp.buildings.transportHub.security = V.SecExp.buildings.transportHub.security || V.hubSecurity || 1;
			V.SecExp.buildings.transportHub.surfaceTransport = V.SecExp.buildings.transportHub.surfaceTransport || 1;
			if (V.releaseID < 1093) {
				if (V.terrain !== "oceanic" && V.terrain !== "marine") {
					V.SecExp.buildings.transportHub.surfaceTransport = V.railway || 1;
				} else {
					V.SecExp.buildings.transportHub.surfaceTransport = V.docks || 1;
				}
			}
		}
	}

	function secHub() {
		if (V.secHQ || (V.SecExp.buildings.secHub && Object.entries(V.SecExp.buildings.secHub).length > 0)) {
			V.SecExp.buildings.secHub = V.SecExp.buildings.secHub || {};
			V.SecExp.buildings.secHub.menials = V.SecExp.buildings.secHub.menials || V.secMenials || V.secHelots || 0;
			V.SecExp.buildings.secHub.coldstorage = V.SecExp.buildings.secHub.coldstorage || 0;

			V.SecExp.buildings.secHub.upgrades = V.SecExp.buildings.secHub.upgrades || {};
			V.SecExp.buildings.secHub.upgrades.security = V.SecExp.buildings.secHub.upgrades.security || {};
			if (V.secUpgrades) {
				V.SecExp.buildings.secHub.coldstorage = V.secUpgrades.coldstorage;
				V.SecExp.buildings.secHub.upgrades.security = {
					nanoCams: V.secUpgrades.nanoCams,
					cyberBots: V.secUpgrades.cyberBots,
					eyeScan: V.secUpgrades.eyeScan,
					cryptoAnalyzer: V.secUpgrades.cryptoAnalyzer,
				};
			}
			V.SecExp.buildings.secHub.upgrades.crime = V.SecExp.buildings.secHub.upgrades.crime || V.crimeUpgrades || {};
			V.SecExp.buildings.secHub.upgrades.intel = V.SecExp.buildings.secHub.upgrades.intel || V.intelUpgrades || {};
			V.SecExp.buildings.secHub.upgrades.readiness = V.SecExp.buildings.secHub.upgrades.readiness || V.readinessUpgrades || {};

			V.SecExp.buildings.secHub.upgrades.security.nanoCams = V.SecExp.buildings.secHub.upgrades.security.nanoCams || 0;
			V.SecExp.buildings.secHub.upgrades.security.cyberBots = V.SecExp.buildings.secHub.upgrades.security.cyberBots || 0;
			V.SecExp.buildings.secHub.upgrades.security.eyeScan = V.SecExp.buildings.secHub.upgrades.security.eyeScan || 0;
			V.SecExp.buildings.secHub.upgrades.security.cryptoAnalyzer = V.SecExp.buildings.secHub.upgrades.security.cryptoAnalyzer || 0;

			V.SecExp.buildings.secHub.upgrades.crime.autoTrial = V.SecExp.buildings.secHub.upgrades.crime.autoTrial || 0;
			V.SecExp.buildings.secHub.upgrades.crime.autoArchive = V.SecExp.buildings.secHub.upgrades.crime.autoArchive || 0;
			V.SecExp.buildings.secHub.upgrades.crime.worldProfiler = V.SecExp.buildings.secHub.upgrades.crime.worldProfiler || 0;
			V.SecExp.buildings.secHub.upgrades.crime.advForensic = V.SecExp.buildings.secHub.upgrades.crime.advForensic || 0;

			V.SecExp.buildings.secHub.upgrades.intel.sensors = V.SecExp.buildings.secHub.upgrades.intel.sensors || 0;
			V.SecExp.buildings.secHub.upgrades.intel.radar = V.SecExp.buildings.secHub.upgrades.intel.radar || 0;
			V.SecExp.buildings.secHub.upgrades.intel.signalIntercept = V.SecExp.buildings.secHub.upgrades.intel.signalIntercept || 0;

			V.SecExp.buildings.secHub.upgrades.readiness.earlyWarn = V.SecExp.buildings.secHub.upgrades.readiness.earlyWarn || 0;
			V.SecExp.buildings.secHub.upgrades.readiness.rapidPlatforms = V.SecExp.buildings.secHub.upgrades.readiness.rapidPlatforms || 0;
			V.SecExp.buildings.secHub.upgrades.readiness.pathways = V.SecExp.buildings.secHub.upgrades.readiness.pathways || 0;
			V.SecExp.buildings.secHub.upgrades.readiness.rapidVehicles = V.SecExp.buildings.secHub.upgrades.readiness.rapidVehicles || 0;
		}
	}
})();

repo_name: Arkerthan/fc

license: mit


code:
App.Mods.SecExp.propHub = (function() {
	return {
		init,
		GUI
	};

	function init() {
		V.SecExp.buildings.propHub = {
			recruiterOffice: 0,
			upgrades: {
				campaign: 0,
				miniTruth: 0,
				fakeNews: 0,
				controlLeaks: 0,
				secretService: 0,
				blackOps: 0,
				marketInfiltration: 0,
			},
			focus: "social engineering",
		};
	}

	function GUI() {
		const node = new DocumentFragment();
		V.nextButton = "Back";
		V.nextLink = "Main";
		let r = [];

		node.append("The propaganda hub is a surprisingly inconspicuous building, dimly lit from the outside. You are well aware however of its role and its importance. You confidently enter its unassuming doorway and calmly review the work being done here.");
		if (V.RecruiterID !== 0) {
			App.Events.addParagraph(node, []);
			const hasOffice = V.SecExp.buildings.propHub.recruiterOffice === 1;
			node.append(App.UI.DOM.link(
				`${hasOffice ? "Deny" : "Grant"} ${SlaveFullName(S.Recruiter)} office privileges`,
				() => {
					V.SecExp.buildings.propHub.recruiterOffice = (hasOffice ? 0 : 1);
					App.UI.reload();
				}
			));
			App.UI.DOM.appendNewElement("div", node, "Providing them with an office will help boost your chosen campaign. This also stacks with the campaign boost edict.", "note");
		}
		App.Events.addParagraph(node, []);

		if (V.SecExp.buildings.propHub.upgrades.campaign === 0) {
			node.append(makeLink(
				`Set up a propaganda campaign to align your citizens with your goals`,
				5000,
				"Will provide the focused resource each week, but will cost reputation in upkeep.",
				"campaign"
			));
		} else {
			const focusOptions = ["social engineering", "immigration", "enslavement"];
			App.UI.DOM.appendNewElement("div", node, "You have set up a team of trained slaves and expert propagandists, ready to spread the message of your choosing to the population.");
			if (V.SecExp.edicts.defense.militia >= 1) {
				focusOptions.push("recruitment");
			}

			for (const focus of focusOptions) {
				if (V.SecExp.buildings.propHub.focus === focus) {
					r.push(focus);
				} else {
					r.push(App.UI.DOM.link(
						`${focus}`,
						() => {
							V.SecExp.buildings.propHub.focus = focus;
							App.UI.reload();
						}
					));
				}
			}
			node.append("Focus on: ", App.UI.DOM.generateLinksStrip(r));

			r = ["You are concentrating your propaganda efforts towards"];
			switch (V.SecExp.buildings.propHub.focus) {
				case "social engineering":
					r.push("increasing the acceptance of your chosen future societies.");
					break;
				case "immigration":
					r.push("convincing more people to immigrate to your arcology.");
					break;
				case "enslavement":
					r.push("convincing more people to voluntarily enslave themselves.");
					break;
				case "recruitment":
					r.push("convincing more citizens to enter the militia.");
					break;
			}
			App.UI.DOM.appendNewElement("div", node, r.join(" "));

			if (V.SecExp.buildings.propHub.upgrades.campaign < 5) {
				App.UI.DOM.appendNewElement("div", node, makeLink(
					`Invest more resources into the project to increase its effectiveness`,
					5000,
					"Will provide more of the focused resource each week but increase reputation upkeep.",
					"campaign",
					true
				));
			} else {
				App.UI.DOM.appendNewElement("div", node, "You have upgraded your propaganda machine to its limits.");
			}
		}
		App.Events.addParagraph(node, []);

		if (V.SecExp.buildings.propHub.upgrades.miniTruth === 0) {
			node.append(makeLink(
				`Set up the authenticity department`,
				5000,
				"Will provide authority and unlock special upgrades, but will increase upkeep.",
				"miniTruth",
				false,
				"Set up a department tasked with guaranteeing the authenticity of all information available in the arcology. Of course if reality is against what is best for the arcology, then it should be redacted as well"
			));
		} else {
			if (V.SecExp.buildings.propHub.upgrades.miniTruth < 5) {
				node.append(makeLink(
					"Enlarge the authenticity department",
					5000,
					"Will provide more authority each week, but increases upkeep.",
					"miniTruth",
					false,
					"Invest more resources into the project to increase its effectiveness.",
				));
			} else {
				node.append("You have upgraded the authenticity department to its maximum.");
			}

			if (V.SecExp.buildings.propHub.upgrades.fakeNews === 0) {
				App.UI.DOM.appendNewElement("div", node, makeLink(
					"Install a news generator",
					10000,
					"The authenticity dept. now provides a small amount of reputation as well as authority, but increases upkeep.",
					"fakeNews",
					false,
					"Install an automatic news generator, able to fabricate thousands of plausible sounding news every day."
				));
			} else {
				App.UI.DOM.appendNewElement("div", node);
				node.append(
					"You have installed an automatic news generator. ",
					App.UI.DOM.link(
						"Remove news generator",
						() => {
							V.SecExp.buildings.propHub.upgrades.fakeNews = 0;
							App.UI.reload();
						}
					)
				);
			}

			if (V.SecExp.buildings.propHub.upgrades.controlLeaks === 0) {
				App.UI.DOM.appendNewElement("div", node, makeLink(
					"Institute controlled leaks protocols",
					10000,
					"The authenticity dept. now provides a small amount of reputation as well as authority, but increases upkeep.",
					"controlLeaks",
					true,
					"Institute a system able to release erroneous, but plausible, information about your business, leading your competitors to prepared financial traps. "
				));
			} else {
				App.UI.DOM.appendNewElement("div", node);
				node.append(
					"You have instituted controlled leaks protocols, able to create fabricated leaks of sensible information. ",
					App.UI.DOM.link(
						"Shut down leak protocols",
						() => {
							V.SecExp.buildings.propHub.upgrades.controlLeaks = 0;
							App.UI.reload();
						}
					)
				);
			}
		}
		App.Events.addParagraph(node, []);

		if (V.SecExp.buildings.propHub.upgrades.secretService === 0) {
			node.append(makeLink(
				"Set up personal secret service",
				10000,
				"Will provide authority and unlock special upgrades, but will increase upkeep.",
				"secretService",
				false,
				"Set up a department tasked with the protection of your person, as well as operations requiring a delicate approach."
			));
		} else {
			if (V.SecExp.buildings.propHub.upgrades.secretService < 5 && V.rep >= (V.SecExp.buildings.propHub.upgrades.secretService * 1000) + 5000) {
				node.append(makeLink(
					"Expand the secret service",
					5000,
					"Will provide more authority each week, but increases upkeep.",
					"secretService",
					false,
					"Invest more resources into the project to increase its effectiveness."
				));
			} else if (V.SecExp.buildings.propHub.upgrades.secretService < 5) {
				node.append("You lack the reputation to further expand operations.");
			} else {
				node.append("You have upgraded the secret service to its maximum.");
			}

			if (V.SecExp.buildings.propHub.upgrades.blackOps === 0) {
				App.UI.DOM.appendNewElement("div", node, makeLink(
					"Create a black ops team",
					10000,
					"The secret services now provides security as well as authority, but increases upkeep.",
					"blackOps",
					false,
					"Create a black ops team, ready to carry out corporate sabotage and sensitive operations to further your goals."
				));
			} else {
				App.UI.DOM.appendNewElement("div", node, "You have created a black ops team.");
			}

			if (V.SecExp.buildings.propHub.upgrades.marketInfiltration === 0) {
				App.UI.DOM.appendNewElement("div", node, makeLink(
					"Infiltrate the black market in order to manipulate it",
					10000,
					"The secret services now provides cash as well as authority each week, but will increase crime growth",
					"marketInfiltration"
				));
			} else {
				App.UI.DOM.appendNewElement("div", node);
				node.append(
					"You have infiltrated the black market and are now in partial control of it. ",
					App.UI.DOM.link(
						"Withdraw from the black market",
						() => {
							V.SecExp.buildings.propHub.upgrades.marketInfiltration = 0;
							App.UI.reload();
						}
					)
				);
			}
		}

		return node;

		function makeLink(text, price, note, type, applyHacking = true, message = null) {
			const r = new DocumentFragment();
			r.append(App.UI.DOM.link(text,
				() => {
					cashX(forceNeg(getCost()), "capEx");
					if (applyHacking) {
						V.PC.skill.hacking++;
					}
					V.SecExp.buildings.propHub.upgrades[type]++;
					if (V.SecExp.buildings.propHub.upgrades.campaign === 1) {
						V.SecExp.buildings.propHub.focus = "social engineering";
					}
					App.UI.reload();
				},
			));
			if (message) {
				App.UI.DOM.appendNewElement("div", r, `${message}`);
			}
			App.UI.DOM.appendNewElement("div", r, `Costs ${cashFormat(getCost())}. ${note}`, "note");
			return r;

			function getCost() {
				const HistoryDiscount = ["capitalist", "celebrity", "wealth"].includes(V.PC.career) ? 0.5 : 1;
				return Math.trunc(price * V.upgradeMultiplierArcology * (V.SecExp.buildings.propHub.upgrades[type] + 1) * HistoryDiscount * (applyHacking ? V.HackingSkillMultiplier : 1));
			}
		}
	}
})();


code:
App.Mods.SecExp.riotCenter = (function() {
	return {
		init,
		GUI
	};

	function init() {
		V.SecExp.buildings.riotCenter = {
			upgrades: {
				freeMedia: 0,
				rapidUnit: 0,
				rapidUnitSpeed: 0,
			},
			fort: {
				reactor: 0,
				waterway: 0,
				assistant: 0,
			},
			sentUnitCooldown: 0,
			advancedRiotEquip: 0,
			brainImplant: -1,
			brainImplantProject: 0,
		};
	}

	function GUI() {
		const node = new DocumentFragment();
		V.nextButton = "Back";
		V.nextLink = "Main";
		node.append("The riot control center opens its guarded doors to you. The great chamber inside is dominated by massive screens filled with vital information and propaganda being tested.");
		App.Events.addParagraph(node, []);

		if (V.SecExp.rebellions.tension <= 33) {
			node.append("Tensions in the arcology are low. Political and ideological opposition against the arcology owner is almost unheard of.");
		} else if (V.SecExp.rebellions.tension <= 66) {
			node.append("Tensions in the arcology are rising; political and ideological opposition against the arcology owner are becoming a part of the daily life of the arcology.");
		} else {
			node.append("Tensions are high. Opposition to the arcology owner is a sentiment shared by many and armed resistance is on the rise.");
		}

		if (V.SecExp.buildings.riotCenter.upgrades.freeMedia === 0) {
			App.UI.DOM.appendNewElement("div", node,
				makeLink(
					"Provide free media access in all the arcology",
					5000,
					"Will slowly lower tensions in the arcology, but will incur in upkeep costs.",
					"freeMedia"
				)
			);
		} else {
			App.UI.DOM.appendNewElement("div", node, "You are providing free access to many mass media in the arcology.");
			if (V.SecExp.buildings.riotCenter.upgrades.freeMedia < 5) {
				App.UI.DOM.appendNewElement("div", node,
					makeLink(
						"Invest more resources in the free media project to increase its effectiveness",
						5000,
						"Will accelerate the tension decay, but will increase upkeep costs.",
						"freeMedia",
						true
					)
				);
			} else {
				App.UI.DOM.appendNewElement("div", node, "You upgraded your free media scheme to its limits.");
			}
		}
		App.Events.addParagraph(node, []);

		node.append(progressReport("slave"));
		App.UI.DOM.appendNewElement("div", node, progressReport("citizen"));
		App.Events.addParagraph(node, []);

		if (V.SecExp.buildings.riotCenter.upgrades.rapidUnit === 0) {
			node.append(
				makeLink(
					"Create rapid deployment riot units",
					7500,
					"Will allow spending authority or reputation to lower the progress of rebellions.",
					"rapidUnit"
				)
			);
		} else {
			node.append("You created a rapid deployment riot unit.");
			if (V.SecExp.buildings.riotCenter.upgrades.rapidUnit < 5) {
				App.UI.DOM.appendNewElement("div", node,
					makeLink(
						"Invest more resources in the rapid deployment unit",
						5000,
						"Will lower action costs.",
						"rapidUnit"
					)
				);
			} else {
				App.UI.DOM.appendNewElement("div", node, "You upgraded your rapid deployment unit to its limits.");
			}

			if (V.SecExp.buildings.riotCenter.upgrades.rapidUnitSpeed < 2) {
				App.UI.DOM.appendNewElement("div", node,
					makeLink(
						"Enhance the internal informants network",
						5000,
						"Will reduce cooldown of the rapid deployment riot unit.",
						"rapidUnitSpeed"
					)
				);
			} else {
				App.UI.DOM.appendNewElement("div", node, "You enhanced your informants network to its limits.");
			}

			App.Events.addParagraph(node, []);
			if (V.SecExp.buildings.riotCenter.sentUnitCooldown === 0) {
				App.UI.DOM.appendNewElement("div", node, deployUnit());
			} else {
				App.UI.DOM.appendNewElement("div", node, `The unit cannot be deployed again for ${V.SecExp.buildings.riotCenter.sentUnitCooldown} weeks.`);
			}
		}
		App.Events.addParagraph(node, []);

		if (V.SecExp.buildings.riotCenter.brainImplant < 106) {
			if (V.SecExp.buildings.riotCenter.brainImplantProject === 0) {
				node.append(
					makeLink(
						"Start secretly installing brain implants in your citizens and resident slaves",
						0,
						`Will take weeks of work and will cost ${cashFormat(5000)} each week, but once finished rebellions will progress a lot slower.`,
						"brainImplantStart"
					)
				);
			} else if (V.SecExp.buildings.riotCenter.brainImplantProject < 5) {
				node.append(
					makeLink(
						"Invest more resources into the project to increase its speed",
						50000,
						"Will shorten the time required to complete the project.",
						"brainImplantProject",
						true
					)
				);
			} else {
				node.append("You sped up the project to its maximum.");
			}
			if (V.SecExp.buildings.riotCenter.brainImplant !== -1) {
				App.UI.DOM.appendNewElement("div", node, `The great brain implant project is underway. Estimated time to completion: ${years(Math.trunc((100 - V.SecExp.buildings.riotCenter.brainImplant) / V.SecExp.buildings.riotCenter.brainImplantProject))}`);
			}
		} else {
			node.append("The great brain implant project is completed, rebellions against you will be extremely difficult to organize.");
		}
		App.Events.addParagraph(node, []);

		if (V.SecExp.buildings.riotCenter.advancedRiotEquip === 0) {
			node.append(
				makeLink(
					"Develop advanced anti-riot equipment",
					30000,
					"Will allow the selection of advanced riot equipment in case of a rebellion, which will let your troops fight at full effectiveness while doing reduced collateral damage.",
					"advancedRiotEquip"
				)
			);
		} else {
			node.append("You developed advanced riot equipment, which allows your troops to fight within the confines of your arcology without the fear of doing major collateral damage.");
		}

		if (V.SecExp.buildings.riotCenter.fort.reactor === 0) {
			App.UI.DOM.appendNewElement("div", node,
				makeLink(
					"Reinforce the reactor complex",
					10000,
					"Will add protection to the reactor building, making it less likely to be damaged and speeding up repairs if our defensive efforts should fail.",
					"reactor"
				)
			);
		} else {
			App.UI.DOM.appendNewElement("div", node, "You have installed additional protection layers and redundant systems in the reactor complex.");
		}

		if (V.SecExp.buildings.riotCenter.fort.waterway === 0) {
			App.UI.DOM.appendNewElement("div", node,
				makeLink(
					"Reinforce the waterways",
					10000,
					"Will add protection to the waterways, making it less likely to be damaged and speeding up repairs if our defensive efforts should fail.",
					"waterway"
				)
			);
		} else {
			App.UI.DOM.appendNewElement("div", node, "You have installed additional protection layers and redundant systems in the waterways.");
		}

		if (V.SecExp.buildings.riotCenter.fort.assistant === 0) {
			App.UI.DOM.appendNewElement("div", node,
				makeLink(
					"Reinforce the assistant CPU core",
					10000,
					"Will add protection to the assistant CPU core, making it less likely to be damaged and speeding up repairs if our defensive efforts should fail.",
					"assistant"
				)
			);
		} else {
			App.UI.DOM.appendNewElement("div", node, "You have installed additional protection layers and redundant systems in the assistant CPU core.");
		}

		if (V.SF.Toggle && V.SF.Active >= 1) {
			if (V.SecExp.edicts.SFSupportLevel >= 4 && V.SF.Squad.Armoury >= 8 && !V.SecExp.rebellions.sfArmor) {
				const cost = Math.ceil(500000 * App.Mods.SF.env() * (1.15 + (V.SF.Squad.Armoury/10) ));
				App.UI.DOM.appendNewElement("div", node, makePurchase(
					`Give the riot unit access to the combat armor suits of ${V.SF.Lower}.`, cost, "capEx",
					{handler: () => { V.SecExp.rebellions.sfArmor = 1; }}
				));
			} else {
				App.UI.DOM.appendNewElement("div", node, `You have given the riot unit access to the combat armor suits of ${V.SF.Lower}.`);
			}
		}
		return node;

		function deployUnit() {
			const deploy = document.createElement("span");
			const r = [];
			App.UI.DOM.appendNewElement("div", deploy, "You can send out the squad to slow down the progress of hostile groups within the arcology.");
			for (const type of ["authority", "reputation"]) {
				r.push(App.UI.DOM.link(
					`${capFirstChar(type)}`,
					() => {
						App.UI.DOM.replace(deploy, menu(type));
					}
				));
			}
			deploy.append("Spend: ", App.UI.DOM.generateLinksStrip(r));
			return deploy;
			/**
			 * @param {string} cost
			 * @returns {HTMLSpanElement}
			 */
			function menu(cost) {
				const text = document.createElement("span");
				App.UI.DOM.appendNewElement("div", text, `Your ${cost} will be leveraged to suppress the rebels.`);
				for (const type of ["slave", "citizen"]) {
					App.UI.DOM.appendNewElement("div", text, App.UI.DOM.link(
						`Deploy the unit against ${type} rebel leaders`,
						() => {
							const price = forceNeg(1000 + 50 * V.SecExp.buildings.riotCenter.upgrades.rapidUnit);
							(function() { cost === "reputation" ? repX(price, "war") : App.Mods.SecExp.authorityX(price); })();
							const change = random(15) + random(1, 2) * V.SecExp.buildings.riotCenter.upgrades.rapidUnit;
							V.SecExp.rebellions[type + "Progress"] = Math.clamp(V.SecExp.rebellions[type + "Progress"] - change, 0, 100);
							V.SecExp.buildings.riotCenter.sentUnitCooldown = 3 - V.SecExp.buildings.riotCenter.upgrades.rapidUnitSpeed;
							App.UI.DOM.replace(text, `${capFirstChar(type)} rebellion progress set back by ${change}%. The unit will be able to deployed again in ${V.SecExp.buildings.riotCenter.sentUnitCooldown} weeks.`);
						}
					));
				}
				return text;
			}
		}
		function makeLink(text, price, note, type, applyHacking=false) {
			const r = new DocumentFragment();
			r.append(App.UI.DOM.link(text,
				() => {
					cashX(-getCost(), "capEx");
					if (applyHacking) {
						V.PC.skill.hacking++;
					}
					switch (type) {
						case "freeMedia":
						case "rapidUnit":
						case "rapidUnitSpeed":
							V.SecExp.buildings.riotCenter.upgrades[type]++;
							break;
						case "brainImplantStart":
							V.SecExp.buildings.riotCenter.brainImplantProject = 1;
							V.SecExp.buildings.riotCenter.brainImplant = 0;
							break;
						case "brainImplantProject":
						case "advancedRiotEquip":
							V.SecExp.buildings.riotCenter[type]++;
							break;
						case "reactor":
						case "waterway":
						case "assistant":
							V.SecExp.buildings.riotCenter.fort[type]++;
					}
					App.UI.reload();
				},
			));

			if (type !== "brainImplantProject") {
				App.UI.DOM.appendNewElement("div", r, `Costs ${cashFormat(getCost())}. ${note}`, "note");
			} else {
				App.UI.DOM.appendNewElement("div", r, `One-time cost of ${cashFormat(getCost())} with an additional ${cashFormat(5000)} each week in maintenance. ${note}`, "note");
			}
			return r;

			function getCost() {
				if (["freeMedia", "rapidUnit", "rapidUnitSpeed"].includes(type)) {
					return Math.trunc(price * V.upgradeMultiplierArcology * (V.SecExp.buildings.riotCenter.upgrades[type] + 1) * (applyHacking ? V.HackingSkillMultiplier : 1));
				} else if (type === "brainImplantProject") {
					return Math.trunc(price * V.upgradeMultiplierArcology * (V.SecExp.buildings.riotCenter.brainImplantProject) * (applyHacking ? V.HackingSkillMultiplier : 1));
				} else if (type !== "advancedRiotEquip") {
					return Math.trunc(price * V.upgradeMultiplierArcology * (applyHacking ? V.HackingSkillMultiplier : 1));
				} else {
					return Math.trunc(price * V.upgradeMultiplierTrade);
				}
			}
		}
		function progressReport(type) {
			if (V.SecExp.rebellions[type + "Progress"] <= 25) {
				return `There is very low unrest between the ${type + 's'} of the arcology. The chances of a rebellion igniting are extremely low.`;
			} else if (V.SecExp.rebellions[type + "Progress"] <= 50) {
				return `There is some unrest between the ${type + 's'}. No major movement is forming yet, but it might be time to consider preventive measures.`;
			} else if (V.SecExp.rebellions[type + "Progress"] <= 75 ) {
				return `Unrest is getting high between the ${type + 's'} of the arcology. Preventive measures are necessary if we want to prevent a violent rebellion.`;
			}
			return `Unrest is extremely high between ${type + 's'}. The chances of a rebellion happening in the near future are extremely high.`;
		}
	}
})();


code:
App.Mods.SecExp.barracks = (function() {
	return {
		init,
		GUI
	};

	function init() {
		V.SecExp.buildings.barracks = {
			size: 0,
			luxury: 0,
			training: 0,
			loyaltyMod: 0
		};
	}

	function GUI() {
		const node = new DocumentFragment();
		V.nextButton = "Back";
		V.nextLink = "Main";
		let r = [];
		let cost;
		let text;

		node.append(`While this is a sore sight for many citizens of ${V.arcologies[0].name}, the barracks stand proud before you. `);
		App.UI.DOM.appendNewElement("h1", node, "Upgrades", ["underline"]);
		switch (V.SecExp.buildings.barracks.size) {
			case 0: r.push("The building is relatively small and able to house a limited number of units."); break;
			case 1: r.push("The building has been expanded and can now house more units comfortably."); break;
			case 2: r.push("The building has been further expanded and can now house a high number of units."); break;
			case 3: r.push("The building has been greatly expanded and can now house a sizable military."); break;
			case 4: r.push("The building has been greatly expanded and can now house a small army."); break;
			case 5: r.push("The building has been greatly expanded and can now house an army worthy of an old world nation."); break;
		}
		App.UI.DOM.appendNewElement("div", node, toSentence(r, " ", " "));
		r = [];

		if (V.SecExp.buildings.barracks.luxury === 0) {
			node.append("The barracks are a spartan building, with little to make the day to day lives of your soldiers pleasant.");
		} else {
			r.push("The barracks have been made more comfortable by");
			if (V.SecExp.buildings.barracks.luxury >= 1) {
				r.push("installing high tech furniture");
			}
			if (V.SecExp.buildings.barracks.luxury >= 2) {
				r.push("and advanced kitchen facilities");
			}
			if (V.SecExp.buildings.barracks.luxury >= 3) {
				r.push("It also provides free access to any digital media");
			}
			if (V.SecExp.buildings.barracks.luxury >= 4) {
				r.push("A small limited-access brothel has been added to the structure");
			}
			App.UI.DOM.appendNewElement("div", node, toSentence(r));
		}

		if (V.SecExp.buildings.barracks.training === 0) {
			App.UI.DOM.appendNewElement("div", node, "The building lacks the space and the equipment to train your units.");
		} else if (V.SecExp.buildings.barracks.training === 1) {
			App.UI.DOM.appendNewElement("div", node, "A training facility has been set up, allowing your units to better their skills with time.");
		} else {
			App.UI.DOM.appendNewElement("div", node, "The training facility has been filled with specialized equipment and skilled trainers.");
		}

		if (V.SecExp.buildings.barracks.loyaltyMod === 0) {
			App.UI.DOM.appendNewElement("div", node, "The barracks lack an indoctrination facility.");
		} else if (V.SecExp.buildings.barracks.loyaltyMod === 1) {
			App.UI.DOM.appendNewElement("div", node, "The barracks have been fitted with an indoctrination facility.");
		} else {
			App.UI.DOM.appendNewElement("div", node, "The barracks have been fitted with an advanced indoctrination facility.");
		}
		App.Events.addParagraph(node, []);

		if (V.SecExp.buildings.barracks.size < 5) {
			cost = Math.trunc(5000 * (V.SecExp.buildings.barracks.size + 1) * V.upgradeMultiplierArcology);
			node.append(App.UI.DOM.link("Increase the size of the barracks", () => {
				cashX(-cost, "capEx");
				V.SecExp.buildings.barracks.size++;
				App.UI.reload();
			}
			));
			App.UI.DOM.appendNewElement("div", node, `Costs ${cashFormat(cost)} and will increase the maximum number of units by 2`, ["note"]);
		} else {
			const activeSF = V.SF.Toggle && V.SF.Active >= 1;
			const sectionSF = activeSF && V.SF.Squad.Firebase > 5 && V.SecExp.edicts.SFSupportLevel >= 4 && App.Mods.SecExp.battle.maxUnits() === 18 && App.Mods.SecExp.battle.deploySpeed() <= 10;
			const reasons = [];
			if (activeSF) {
				if (V.SF.Squad.Firebase < 5) {
					reasons.push('the Firebase is expanded');
				}
				if (V.SecExp.edicts.SFSupportLevel < 4) {
					reasons.push('the scope of the support contract/edict is increased');
				}
			}

			if (reasons.length > 0 || sectionSF) {
				const capSF = capFirstChar(V.SF.Lower || "the Special Force");
				if (reasons.length > 0) {
					App.UI.DOM.appendNewElement("div", node, `The Colonel says that ${capSF} may be able to provide assistance if ${toSentence(reasons)}.`);
				}
				cost = Math.trunc( (750000 * (1.15 + (App.Mods.SF.upgrades.total() / 1000)) * (1.15 + (V.SF.Squad.Firebase / 10))) * App.Mods.SF.env() );
				if (sectionSF && !V.SecExp.sectionInFirebase) {
					node.append(App.UI.DOM.link(`Direct the ${capSF} to provide the security force with their own section in the Firebase `, () => {
						V.SecExp.sectionInFirebase = 1;
						cashX(-cost, "specialForcesCap");
						App.UI.reload();
					}
					));
					App.UI.DOM.appendNewElement("span", node, `Costs ${cashFormat(cost)}`, ["cash", "dec"]);
				}
			} else {
				App.UI.DOM.appendNewElement("div", node, "You've expanded the barracks to their maximum.");
			}
		}

		if (V.SecExp.buildings.barracks.luxury < 4) {
			switch (V.SecExp.buildings.barracks.luxury) {
				case 0:
					cost = Math.trunc(5000 * V.upgradeMultiplierTrade);
					text = "Increase the quality of life of your soldiers by installing high tech furniture and appliances";
					break;
				case 1:
					cost = Math.trunc(10000 * V.upgradeMultiplierTrade);
					text = "Further increase the quality of life of your soldiers by installing advanced kitchen equipment and hiring skilled chefs";
					break;
				case 2:
					cost = Math.trunc(10000 * V.upgradeMultiplierTrade);
					text = "Further increase the quality of life of your soldiers by providing high speed, free access to digital media";
					break;
				case 3:
					cost = Math.trunc(15000 * V.upgradeMultiplierTrade);
					text = "Further increase the quality of life of your soldiers by adding and staffing an exclusive brothel to the structure";
			}

			App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(text, () => {
				cashX(forceNeg(cost), "capEx");
				V.SecExp.buildings.barracks.luxury++;
				App.UI.reload();
			}
			));
			App.UI.DOM.appendNewElement(
				"div",
				node,
				`Costs ${cashFormat(cost)} and will provide a 5% bonus to morale${V.SecExp.buildings.barracks.luxury === 0 ? "." : ` for a total of +${(V.SecExp.buildings.barracks.luxury + 1) * 5}.`}`,
				["note"]
			);
		} else {
			App.UI.DOM.appendNewElement("div", node, "You've made life in your barracks as good as it can get.");
		}

		if (V.SecExp.buildings.barracks.training < 2) {
			switch (V.SecExp.buildings.barracks.training) {
				case 0:
					cost = Math.trunc(10000 * V.upgradeMultiplierArcology);
					text = "Add a training facility to the barracks";
					break;
				case 1:
					cost = Math.trunc(20000 * V.upgradeMultiplierTrade);
					text = "Improve the training facility with modern equipment and skilled personnel";
			}

			App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(text, () => {
				cashX(forceNeg(cost), "capEx");
				V.SecExp.buildings.barracks.training++;
				App.UI.reload();
			}
			));
			App.UI.DOM.appendNewElement("div", node, `Costs ${cashFormat(cost)} and will allow units to accumulate ${V.SecExp.buildings.barracks.training === 0 ? "some" : "additional"} experience each week.`, ["note"]);
		} else {
			App.UI.DOM.appendNewElement("div", node, "You have improved the training facility to the limit.");
		}

		if (V.SecExp.buildings.barracks.loyaltyMod < 2) {
			switch (V.SecExp.buildings.barracks.loyaltyMod) {
				case 0:
					cost = Math.trunc(10000 * V.upgradeMultiplierArcology);
					text = "Add an indoctrination facility to the barracks";
					break;
				case 1:
					cost = Math.trunc(20000 * V.upgradeMultiplierTrade);
					text = "Improve the indoctrination facility with advanced equipment and skilled personnel";
			}

			App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(text, () => {
				cashX(forceNeg(cost), "capEx");
				V.SecExp.buildings.barracks.loyaltyMod++;
				App.UI.reload();
			}
			));
			App.UI.DOM.appendNewElement("div", node, `Costs ${cashFormat(cost)} and will ${V.SecExp.buildings.barracks.loyaltyMod === 0 ? "slowly raise loyalty of all units" : "raise loyalty of all units faster"}.`, "note");
		} else {
			App.UI.DOM.appendNewElement("div", node, "You have improved the indoctrination facility to the limit.");
		}

		App.UI.DOM.appendNewElement("h1", node, "Units", "underline");
		node.append(`${App.Mods.SecExp.battle.activeUnits()}/${App.Mods.SecExp.battle.maxUnits()} are active, totalling ${num(App.Mods.SecExp.unit.squads().reduce((acc, t) => acc += t.troops, 0))} troops `);
		if (App.Mods.SecExp.battle.activeUnits() <= 2 * App.Mods.SecExp.battle.deploySpeed()) {
			node.append(`and all can be deployed.`);
		} else {
			node.append(`however only ${2 * App.Mods.SecExp.battle.deploySpeed()} units can be deployed due to low readiness.`);
		}
		if (V.SecExp.buildings.barracks.luxury > 0) {
			node.append(` The barracks provides ${V.SecExp.buildings.barracks.luxury * 5}% bonus morale when battle occurs.`);
		}
		if (V.SecExp.buildings.barracks.training > 0) {
			node.append(" The training facility will increase the effectiveness of your units with time.");
		}

		const options = new App.UI.OptionsGroup();
		options.addOption("Unit descriptions are", "unitDescriptions", V.SecExp.settings)
			.addValue("Abbreviated", 1).on().addValue("Summarized", 0).off();
		node.append(options.render());
		if (App.Mods.SecExp.battle.activeUnits() >= App.Mods.SecExp.battle.maxUnits()) {
			App.UI.DOM.appendNewElement("div", node, "You have reached the maximum number of units. You'll have to disband one or enlarge the barracks before forming a new unit.");
		}
		node.append(App.Mods.SecExp.unit.replenishAll());

		const tabBar = new App.UI.Tabs.TabBar("SecExpBarracks");
		for (const [unit, data] of App.Mods.SecExp.unit.list()) {
			if (data.unlock) {
				tabBar.addTab(`${capFirstChar(data.name || unit)}: ${(V.SecExp.units[unit].squads.length)}`, unit, page(unit));
			} else {
				App.UI.DOM.appendNewElement("div", node, data.lockedText);
			}
		}
		node.append(tabBar.render());
		return node;

		function page(u) {
			const r = new DocumentFragment();
			switch (u) {
				case "slaves":
					App.UI.DOM.appendNewElement("div", r, `You are free to organize your menial slaves into fighting units. Currently you have ${num(V.menials)} slaves available, while ${num(App.Mods.SecExp.Manpower.employedSlave)} are already employed as soldiers. During all your battles you lost a total of ${num(V.SecExp.units.slaves.dead)}.`);
					break;
				case "militia":
					App.UI.DOM.appendNewElement("div", r, `You founded the ${V.arcologies[0].name} free militia. You are now able to organize your citizens into fighting units.`);
					switch (V.SecExp.edicts.defense.militia) {
						case 2:
							App.UI.DOM.appendNewElement("div", r, `The militia is composed entirely of volunteers, your manpower is ${num(App.Mods.SecExp.militiaCap()*100)}% of the citizens population of your arcology.`);
							break;
						case 3:
							App.UI.DOM.appendNewElement("div", r, `With the establishment of conscription, your available manpower has increased to now ${num(App.Mods.SecExp.militiaCap()*100)}% of the arcology's citizens population.`);
							break;
						case 4:
							App.UI.DOM.appendNewElement("div", r, `By establishing obligatory military service to obtain citizenship you have enlarged your manpower pool to be ${num(App.Mods.SecExp.militiaCap()*100)}% of the arcology's citizens population.`);
							break;
						case 5:
							App.UI.DOM.appendNewElement("div", r, `With the adoption of a militarized society, your available manpower has swelled to be ${num(App.Mods.SecExp.militiaCap()*100)}% of the arcology's citizens population.`);
					}
					App.UI.DOM.appendNewElement("div", r, `Your current total manpower is ${num(App.Mods.SecExp.Manpower.totalMilitia)}, of which ${num(App.Mods.SecExp.Manpower.employedMilitia)} is in active duty. You lost in total ${num(V.SecExp.units.militia.dead)} citizens, leaving you with ${num(V.SecExp.units.militia.free)} available citizens.`);
					break;
				case "mercs":
					App.UI.DOM.appendNewElement("div", r, `With the installation of a mercenary company in the arcology, many other are attracted to your free city, hoping to land a contract with you.`);
					App.UI.DOM.appendNewElement("div", r, `You are able to organize them in units to use in the defense of the arcology. Excluding the defense force you set up, there are ${num(App.Mods.SecExp.Manpower.totalMerc)} mercenaries in your arcology, of which ${num(App.Mods.SecExp.Manpower.employedMerc)} actively employed and ${num(V.SecExp.units.mercs.free)} not yet under contract. In total ${num(V.SecExp.units.mercs.dead)} mercenaries have died defending your arcology.`);
					break;
			}

			App.UI.DOM.appendNewElement("div", r, App.Mods.SecExp.unit.barracksList(u));
			return r;
		}
	}
})();