code:
/**
 * Returns a string describing the effects of the slave putting on shows.
 * To see full effects, see farmyardShows.js
 * @param {FC.SlaveState} slave
 * @returns {string}
 */
App.Facilities.Farmyard.putOnShows = function(slave) {
	const {he, him, his, hers, He, His} = getPronouns(slave);
	const incomeStats = getSlaveStatisticData(slave, V.facility.farmyard);
	const arcology = V.arcologies[0];
	const beautyString = beautiful(slave);
	const prettyString = pretty(slave);

	const heavyMods = SlaveStatsChecker.modScore(slave).total > 20;

	const text = [];

	if (V.seeBestiality) {
		seX(slave, "bestiality", "animal", "bestiality", random(35, 65));
	}

	text.push(
		`${He} ${V.farmyardShows < 2 ? `also ` : ``}puts on shows with animals this week.`,
		FSEffects(),
		virginity(),
		careers(),
		prestige(),
		health(),
		face(),
		devotion(),
		weight(),
		muscles(),
		eyesight(),
		hearing(),
		pregnancy(),
		tiredness(),
		intelligence(),
		energy(),
		fetish(),
		behavioralFlaw(),
		behavioralQuirk(),
		sexualFlaw(),
		sexualQuirk(),
		openness(),
		rival(),
	);

	incomeStats.income += Math.trunc(App.Facilities.Farmyard.farmShowsIncome(slave));

	return text.join(' ');

	function FSEffects() {
		const text = [];

		if (FutureSocieties.isActive('FSSupremacist', arcology)) {
			if (isSuperiorRace(slave)) {
				if (V.seeBestiality) {
					text.push(`Society <span class="reputation dec">disapproves</span> of your allowing a member of the elite race to be degraded in such a fashion, and thus ${he} didn't earn as much.`);
				} else {
					text.push(`Since ${arcology.FSSupremacistRace} slaves are in fashion, ${he} attracts a little more attention than if ${he} wasn't ${arcology.FSSupremacistRace}.`);
				}
			} else {
				text.push(`Society doesn't disapprove of ${him} not being ${arcology.FSSupremacistRace}, but ${he} doesn't earn as much as ${he} would if ${he} was.`);
			}
		}

		if (FutureSocieties.isActive('FSSubjugationist', arcology)) {
			if (isInferiorRace(slave)) {
				if (V.seeBestiality) {
					text.push(`Society <span class="reputation inc">approves</span> of the degradation you submit your ${arcology.FSSubjugationistRace} slaves to, and so ${he} earns you a bit more.`);
				} else {
					// FIXME: Type 'FC.NoObject' is not assignable to type 'string'.
					text.push(`Fewer people want to go see ${addA(arcology.FSSubjugationistRace)} slave put on a show, and so ${he} doesn't earn as much as ${he} otherwise could.`);
				}
			} else {
				if (V.seeBestiality) {
					text.push(`Society doesn't disapprove of ${him} not being ${arcology.FSSubjugationistRace}, but ${he} doesn't earn as much as ${he} would if ${he} was.`);
				}
			}
		}

		if (FutureSocieties.isActive('FSRepopulationFocus', arcology)) {
			if (isPreg(slave)) {
				if (slave.eggType === "human") {
					text.push(`Society <span class="reputation inc">greatly approves</span> of your having pregnant slaves ${V.seeBestiality ? `have sex` : `put on shows`} with animals.`);
				} else {
					text.push(`Society is <span class="reputation dec">disgusted</span> by ${his} pregnancy when they realize that what it is in ${his} womb is not human.`);
				}
			}
		}

		if (FutureSocieties.isActive('FSRestart', arcology)) {
			if (isPreg(slave)) {
				if (isEliteBreeder(slave)) {
					if (slave.eggType === "human") {
						text.push(`Society is horrified by the fact that you would dare defile a slave deemed fit for humanity's revival in such a manner, especially one that is carrying the future of the planet.`);
					} else {
						text.push(`Society is absolutely repulsed by the fact that you would dare defile a slave deemed fit for humanity's revival in such a manner, especially when they learn that what is in ${his} womb is not even human.`);
					}
				} else {
					if (slave.eggType === "human") {
						text.push(`Society is <span class="reputation dec">extremely disgusted</span> by ${his} pregnancy and the fact that you would have ${him} ${V.seeBestiality ? `have sex` : `put on shows`} with animals while sporting a baby bump.`);
					} else {
						text.push(`Society is disgusted by ${his} pregnancy until they learn that what is in ${his} womb is not human.`);
					}
				}
			} else {
				if (V.seeBestiality && isEliteBreeder(slave)) {
					text.push(`Society is <span class="reputation dec">heavily disapproving</span> of the fact that you would dare defile a slave deemed fit for humanity's revival in such a manner.`);
				}
			}
		}

		if (FutureSocieties.isActive('FSGenderRadicalist', arcology)) {
			if (slave.dick > 0) {
				text.push(`${His} patrons <span class="reputation inc">approve</span> of the fact that ${he} has a dick.`);
			} else {
				text.push(`${His} patrons <span class="reputation dec">are disappointed</span> that ${he} doesn't have a dick.`);
			}
		}

		if (FutureSocieties.isActive('FSGenderFundamentalist', arcology)) {
			if (isPreg(slave) || App.Data.misc.fakeBellies.includes(slave.bellyAccessory)) {
				text.push(`${His} viewers <span class="reputation inc">approve</span> of the fact that ${he} is sporting a baby bump${App.Data.misc.fakeBellies.includes(slave.bellyAccessory) ? `, even though ${hers} isn't real` : ``}.`);
			} else {
				text.push(`${His} viewers <span class="reputation dec">are disappointed</span> that ${he} isn't pregnant.`);
			}
		}

		if (FutureSocieties.isActive('FSPaternalist', arcology)) {
			if (V.seeBestiality) {
				if (V.policies.bestialityOpenness) {
					text.push(`Your citizens would normally disapprove of your using slaves as toys for your animals, but the policy you enacted encouraging bestiality, combined with some clever, subtle advertising, leads them to see nothing wrong with it.`);
					if (slave.devotion > 50) {
						text.push(`That ${slave.slaveName} seems to be enjoying ${him}self so thoroughly also <span class="reputation inc">helps put their minds at ease.</span>`);
					}
				} else {
					if (V.farmyardBreeding) {
						if (V.farmyardRestraints) {
							text.push(`Your citizens are <span class="reputation dec">extremely disapproving</span> of the fact that you would allow your slaves to be treated as nothing more than a bound breeding toy for your animals.`);
						} else {
							text.push(`Your citizens are <span class="reputation dec">highly disapproving</span> of the fact that you would allow your slaves to be treated as nothing more than a breeding toy for your animals.`);
						}
					} else {
						if (V.farmyardRestraints) {
							text.push(`Your citizens are <span class="reputation dec">very disapproving</span> of the fact that you would allow your slaves to be treated as nothing more than a bound toy for your animals.`);
						} else {
							text.push(`Your citizens are <span class="reputation dec">disapproving</span> of the fact that you would allow your slaves to be treated as nothing more than a toy for your animals.`);
						}
					}
				}
			}
		}

		if (FutureSocieties.isActive('FSDegradationist', arcology)) {
			if (V.seeBestiality) {
				if (V.farmyardBreeding) {
					if (V.farmyardRestraints) {
						text.push(`Your citizens are <span class="reputation inc">extremely approving</span> of the fact that you would allow your slaves to be treated as nothing more than a bound breeding toy for your animals.`);
					} else {
						text.push(`Your citizens are <span class="reputation inc">highly approving</span> of the fact that you would allow your slaves to be treated as nothing more than a breeding toy for your animals.`);
					}
				} else {
					if (V.farmyardRestraints) {
						text.push(`Your citizens are <span class="reputation inc">very approving</span> of the fact that you would allow your slaves to be treated as nothing more than a bound toy for your animals.`);
					} else {
						text.push(`Your citizens are <span class="reputation inc">approving</span> of the fact that you would allow your slaves to be treated as nothing more than a toy for your animals.`);
					}
				}
			}
		}

		if (FutureSocieties.isActive('FSBodyPurist', arcology)) {
			if (SlaveStatsChecker.isModded(slave)) {
				text.push(`The members of the audience <span class="reputation dec">disapprove</span> that you would use a slave with ${heavyMods ? `such heavy` : ``} modifications to put on shows.`);
			}
		}

		if (FutureSocieties.isActive('FSTransformationFetishist', arcology)) {
			if (SlaveStatsChecker.isModded(slave)) {
				text.push(`The members of the audience <span class="reputation inc">approve</span> that you would use a slave with ${heavyMods ? `such heavy` : ``} modifications to put on shows.`);
			}
		}

		if (FutureSocieties.isActive('FSYouthPreferentialist', arcology)) {
			if (isYoung(slave)) {
				text.push(`${arcology.name}'s citizens <span class="reputation inc">approve</span> of your using young slaves to put on shows.`);
			} else {
				text.push(`${arcology.name}'s citizens <span class="reputation dec">disapprove</span> of your using such old slaves to put on shows.`);
			}
		}

		if (FutureSocieties.isActive('FSMaturityPreferentialist', arcology)) {
			if (isYoung(slave)) {
				text.push(`${arcology.name}'s citizens <span class="reputation inc">approve</span> of your using mature slaves to put on shows.`);
			} else {
				text.push(`${arcology.name}'s citizens <span class="reputation dec">disapprove</span> of your using such young slaves to put on shows.`);
			}
		}

		if (FutureSocieties.isActive('FSSlimnessEnthusiast', arcology)) {
			if (isSlim(slave)) {
				text.push(`${His} slim body <span class="reputation inc">attracts a wider audience.</span>`);
			} else {
				text.push(`Society finds your using a slave with such a flabby body <span class="reputation dec">disgusting.</span>`);
			}
		}

		if (FutureSocieties.isActive('FSAssetExpansionist', arcology)) {
			if (isStacked(slave)) {
				text.push(`Society <span class="reputation inc">approves</span> of the fact that you respect their ideals in using a slave with larger assets.`);
			}
		}

		if (FutureSocieties.isActive('FSPastoralist', arcology)) {
			if (slave.boobs >= 1000) {
				text.push(`The fact that ${slave.slaveName} has such large udders <span class="reputation inc">pleases your citizens.</span>`);
			}

			if (slave.lactation > 0) {
				text.push(`Your citizens ${slave.boobs >= 1000 ? `also ` : ``}approve of the fact that ${he} is visibly lactating.`);
			}
		}

		if (FutureSocieties.isActive('FSPhysicalIdealist', arcology)) {
			if (genderLawPass(slave)) {
				text.push(`The fact that ${slave.slaveName} has what is considered the ideal form also <span class="reputation inc">helps ${him} attract attention,</span> and so ${he} earns a bit more.`);
			} else {
				text.push(`${His} form isn't exactly what ${arcology.name}'s citizens consider ideal, and so ${he} doesn't <span class="reputation dec">earn as much</span> as ${he} could have otherwise.`);
			}
		}

		if (FutureSocieties.isActive('FSHedonisticDecadence', arcology)) {
			if (slave.weight > 10) {
				text.push(`Since ${slave.slaveName} is large enough to please ${arcology.name}'s citizens, ${he} earns slightly more.`);
			} else {
				text.push(`${He} doesn't earn quite as much ${he} would have if ${he} was a bit larger in size.`);
			}
		}

		if (FutureSocieties.isActive('FSPetiteAdmiration', arcology)) {
			if (heightPass(slave)) {
				text.push(`The fact that you are using such small slaves <span class="reputation inc">pleases your citizens.</span>`);
			} else {
				text.push(`The fact that you are using such tall slaves <span class="reputation dec">displeases your citizens.</span>`);
			}
		}

		if (FutureSocieties.isActive('FSStatuesqueGlorification', arcology)) {
			if (heightPass(slave)) {
				text.push(`Your citizens <span class="reputation inc">approve</span> of your using such statuesque slaves for putting on shows.`);
			} else {
				text.push(`Your citizens <span class="reputation dec">disapprove</span> of your not using taller slaves for putting on shows.`);
			}
		}

		return text.join(' ');
	}

	function virginity() {
		if (V.seeBestiality) {
			if (slave.devotion > 50 && canBeDeflowered(slave)) {
				return `${slave.slaveName} promised the crowd ${he} would allow one of your animals to deflower ${him} onstage if they all donated enough ¤, and ${he} stayed true to ${his} word – ${his} tight little ${slave.vagina === 0 ? `pussy` : `ass`} has been broken in.`;
			}
		}
	}

	function careers() {
		const text = [];

		if (App.Data.Careers.General.entertainment.includes(slave.career)) {
			text.push(`${He} has experience with putting on shows from ${his} life before ${he} was a slave, making ${him} more effective at putting on shows.`);
		}

		if (App.Data.Careers.Leader.farmer.includes(slave.career)) {
			text.push(`${He} ${App.Data.Careers.General.entertainment.includes(slave.career) ? `also` : ``} has experience in working with animals from ${his} life before ${he} was a slave, making ${him} more effective at putting on shows.`);
		}

		return text.join(' ');
	}

	function prestige() {
		const text = [];

		if (slave.prestige === 1) {
			text.push(`Your citizens are so eager to see someone they recognize ${V.seeBestiality ? `be ${V.farmyardBreeding ? `bred` : `rutted`} by an animal` : `put on shows with an animal`} that they are willing to pay a bit more.`);
		} else if (slave.prestige === 2) {
			text.push(`Your citizens are so eager to see someone well-known ${V.seeBestiality ? `be ${V.farmyardBreeding ? `bred` : `rutted`} by an animal` : `put on shows with an animal`} that they are willing to pay a fair bit more.`);
		} else if (slave.prestige === 3) {
			text.push(`Your citizens are so eager to see someone so famous ${V.seeBestiality ? `be ${V.farmyardBreeding ? `bred` : `rutted`} by an animal` : `put on shows with an animal`} that they are willing to pay much more.`);
		}

		if (slave.porn.prestige === 1) {
			text.push(`${He} earns a bit more because some of your citizens already know ${him} from porn.`);
		} else if (slave.porn.prestige === 2) {
			text.push(`${He} earns quite a bit more because a lot of your citizens already know ${him} from porn.`);
		} else if (slave.porn.prestige === 3) {
			text.push(`${He} earns a lot more because ${he} is so famous from porn.`);
		}

		return text.join(' ');
	}

	function health() {
		if (slave.health.condition > 50) {
			return `${He} is in such excellent health that ${he} is able to put on longer and more energetic shows, earning you more.`;
		} else if (slave.health.condition < -20) {
			return `${His} poor health negatively affects ${his} ability to put on good shows, cutting into your profits.`;
		}
	}

	// TODO: add checks for family and relationships
	function face() {
		if (slave.face > 40) {
			return `${He} is so ${beautyString} that ${his} audience is willing to pay more to watch ${him} put on shows.`;
		} else if (slave.face > 10) {
			return `${He} is so ${prettyString} that ${his} audience is willing to pay more to watch ${him} put on shows.`;
		} else if (slave.face < -10) {
			return `${His} audience isn't willing to pay as much because of how unattractive ${his} face is.`;
		} else if (slave.face < -40) {
			return `${His} audience isn't willing to pay as much because of how hard ${his} face is to look at.`;
		}
	}

	// TODO: incorporate seeBestiality, breeding, and restraints
	function devotion() {
		if (slave.devotion > 50) {
			if (slave.trust > 50) {
				return `${He} is so devoted that ${he} works ${his} hardest to make ${his} show a good one.`;
			} else if (slave.trust < -50) {
				return `${He} is both devoted to you and terrified of you, so ${he} tries ${his} best to make ${his} show a good one.`;
			}
		} else if (slave.devotion < -50) {
			if (slave.trust > 50) {
				return `${slave.slaveName} purposefully does the bare minimum ${he} can get away with to spite you.`;
			} else if (slave.trust < -50) {
				return `${slave.slaveName} refuses to do anything without punishment, which is evident from ${his} meager earnings.`;
			}
		}
	}

	function weight() {
		if (slave.weight > 30) {
			if (!FutureSocieties.isActive('FSHedonisticDecadence', arcology)) {
				return `Your citizens are not willing to pay as much to see such a fat slave put on shows, so ${he} loses some income.`;
			}
		} else if (slave.weight < -30) {
			return `Your citizens don't like watching such a sickly-looking slaves put on shows, so ${he} loses some income.`;
		}
	}

	function muscles() {
		if (slave.muscles < -30) {
			return `${slave.slaveName} is so weak that ${he} cannot even properly handle the animals ${he}'s assigned to ${V.seeBestiality ? `fuck` : `work with`}, and isn't able to put on any sort of meaningful show.`;
		}
	}

	function eyesight() {
		if (!canSeePerfectly(slave)) {
			return `${His} ${!canSee(slave) ? `blindness makes it impossible` : `nearsightedness makes it harder`} for ${him} to see what ${he}'s doing, affecting ${his} ability to put on a good show.`;
		}
	}

	function hearing() {
		if (slave.hears < 0) {
			return `${His} ${slave.hears < -1 ? `lack of` : `poor`} hearing makes it difficult for ${him} to hear what ${his} audience wants from ${him}, which really affects ${his} earnings.`;
		}
	}

	function pregnancy() {
		if (isPreg(slave)) {
			return `${His}${slave.bellyPreg > 100000 ? ` advanced` : ``} pregnancy makes it more difficult for ${him} to effectively put on a good show.`;
		}
	}

	function tiredness() {
		if (slave.health.tired > 60) {
			return `${He} is so tired that the energy in ${his} shows is basically nonexistent, affecting ${his} profits.`;
		}
	}

	function intelligence() {
		if (slave.intelligence > 50) {
			return `Because ${he} is so intelligent, ${he} is able to tailor ${his} shows to ${his} audience, helping ${him} bring in more in profits.`;
		} else if (slave.intelligence < -50) {
			return `${He} is so slow that all ${he} can really do is just ${V.seeBestiality ? `lie there and take it` : `put on the most basic of moves`}, which your audience finds dull and uninteresting.`;
		}
	}

	function energy() {
		if (V.seeBestiality) {
			if (slave.energy > 95) {
				return `The fact that ${he} is a nymphomaniac helps ${him} to go for longer, allowing ${him} to really put on an amazing show.`;
			} else if (slave.energy > 80) {
				return `The fact that ${his} sex drive is so powerful helps ${him} to really put on good shows.`;
			} else if (slave.energy > 60) {
				return `The fact that ${his} sex drive is so good helps ${him} to put on good shows.`;
			} else if (slave.energy > 40) {
				return `${His} average sex drive allows ${him} to put on a decent show.`;
			} else if (slave.energy > 20) {
				return `The fact that ${his} sex drive is so poor affects ${his} performance.`;
			} else {
				return `The fact that ${his} sex drive is nonexistent really hinders ${his} ability to put on a decent show.`;
			}
		}
	}

	function fetish() {
		switch (slave.fetish) {
			case "submissive":
				if (V.seeBestiality) {
					if (slave.fetishKnown) {
						return `${He} is so submissive that ${he} willingly accepts ${his} position as an animal's fucktoy and <span class="reputation inc">is able to put on a decent show.</span>`;
					} else {
						return `${S.HeadGirl ? `${S.HeadGirl.slaveName} notices` : `You notice`} that ${slave.slaveName} seems to really have taken to ${his} position as a fucktoy for animals. <span class="lightcoral">${He}'s a submissive!</span>`;
					}
				} else {
					if (slave.fetishKnown) {
						return `Being a submissive, ${he} <span class="reputation dec">doesn't have the confidence required</span> to really put on a good show.`;
					} else {
						return `${slave.slaveName} doesn't seem to have the type of fortitude needed to put on a show, and after some probing, you discover why - it turns out <span class="lightcoral">${he}'s a submissive!</span>`;
					}
				}
			case "humiliation":
				if (V.seeBestiality) {
					if (slave.fetishKnown) {
						return `${slave.slaveName} uses the most of this humiliating experience to really put on a show, to <span class="reputation inc">the approval of ${his} audience.</span>`;
					}
				}
		}
	}

	function behavioralFlaw() {
		switch (slave.behavioralFlaw) {
			case "arrogant":
				return `${He} tries ${his} hardest to avoid ${V.seeBestiality ? `fucking animals` : `putting on shows`} because of ${his} arrogance, <span class="cash dec">which affects ${his} profits</span> and <span class="reputation dec">your reputation.</span>`;

			case "devout":
				return `${He} often prays ${V.seeBestiality ? ` while getting fucked by animals` : ` during ${his} shows`}, which your citizens <span class="reputation dec">find off-putting.</span>`;
		}
	}

	function behavioralQuirk() {
		switch (slave.behavioralQuirk) {
			case "sinful":
				return `${He} relishes in ${his} ability to do something so sinful and depraved, and <span class="reputation inc">really puts on a show.</span>`;
		}
	}

	function sexualFlaw() {
		switch (slave.sexualFlaw) {
			case "shamefast":
				return `${His} crippling shamefastness <span class="reputation dec">limits ${his} ability</span> to put on a decent show.`;
		}
	}

	function sexualQuirk() {
		switch (slave.sexualQuirk) {
			case "perverted":
				return `${His} shows are a <span class="reputation inc">real spectacle,</span> since ${he} is so perverted that ${he} is willing to go far beyond the bare minimum.`;
		}
	}

	function openness() {
		if (V.policies.bestialityOpenness > 0) {
			return `Society's acceptance of and enthusiasm towards bestiality earns ${him} quite a bit more than ${he} would have made otherwise.`;
		}
	}

	function rival() {
		if (slave.rivalry > 0 && V.seeBestiality && V.farmyardShows !== 0) {
			return `${getSlave(slave.rivalryTarget).slaveName} hates ${him} and is glad to see that ${he}'s been assigned to fuck animals all day.`;
		}
	}
};


code:
App.UI.geneLab = function() {
	const node = new DocumentFragment();
	const PCSkillCheck = Math.min(V.upgradeMultiplierMedicine, V.HackingSkillMultiplier);

	App.UI.DOM.appendNewElement("h1", node, `The Gene Lab`);

	if (V.geneticMappingUpgrade === 2) {
		App.UI.DOM.appendNewElement("div", node, `The gene lab is fully operational. It is capable of mapping a slave's genes, identifying genetic traits and abnormalities. It can be used to modify a slave's genome should you obtain the data necessary to adjust it.`, ["note"]);
		const cost = Math.trunc(500000 * V.upgradeMultiplierArcology);
		App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
			"Upgrade the genome mapper",
			() => {
				cashX(forceNeg(cost), "capEx");
				V.geneticMappingUpgrade = 3;
				App.UI.reload();
			}, [], "",
			`Costs ${cashFormat(cost)}`
		));
	} else if (V.geneticMappingUpgrade === 3) {
		App.UI.DOM.appendNewElement("div", node, `The gene lab is fully operational. It is capable of fully mapping a slave's genes, identifying genetic traits and abnormalities. It can be used to correct (or flaw) a slave's genome, as well as modify it should you obtain the data necessary to adjust it.`, ["note"]);
	}

	App.UI.DOM.appendNewElement("h2", node, `Genetic Modification`);
	const immortalityCost = 50000000;
	const flavoringCost = 150000;
	const enhancedProductionFormulaCost = 150000 * PCSkillCheck;
	if (V.dispensaryUpgrade === 0) {
		App.UI.DOM.appendNewElement("div", node, `The fabricator must be upgraded before it can produce treatments to alter genes`, ["note"]);
	} else {
		App.UI.DOM.appendNewElement("div", node, `The fabricator is capable of producing treatments to alter a slave's genetic code.`);
		if (V.arcologies[0].childhoodFertilityInducedNCSResearch === 1) {
			App.UI.DOM.appendNewElement("div", node, `The fabricator is capable of producing treatments to induce NCS.`);
		}
		if (V.RapidCellGrowthFormula === 1) {
			App.UI.DOM.appendNewElement("div", node, `The fabricator is capable of producing treatments to accelerate cellular reproduction.`);
		}
		if (V.enhancedProductionFormula === 1) {
			App.UI.DOM.appendNewElement("div", node, `The fabricator is capable of producing treatments to permanently enhance the production of harvestable resources from dairy slaves. Side effects include, but are not limited to, increased appetite, weight gain, dehydration, and other complications related to overproduction of fluids.`);
		} else if (V.cash >= enhancedProductionFormulaCost) {
			App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
				"Purchase designs for optimizing dairy slaves",
				() => {
					cashX(forceNeg(enhancedProductionFormulaCost), "capEx");
					V.enhancedProductionFormula = 1;
					App.UI.reload();
				}, [], "",
				`Costs ${cashFormat(enhancedProductionFormulaCost)}. Will boost production of harvestable slave resources`
			));
		}
		if (V.immortalityFormula === 1) {
			App.UI.DOM.appendNewElement("div", node, `The fabricator is capable of producing treatments to permanently reverse aging.`);
		} else if (V.cash >= immortalityCost) {
			App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
				"Fund the immortality project",
				() => {
					cashX(forceNeg(immortalityCost), "capEx");
					V.immortalityFormula = 1;
					App.UI.reload();
				}, [], "",
				`Costs ${cashFormat(immortalityCost)}. Will keep a slave at their prime physical age`
			));
		}
		if (V.geneticMappingUpgrade >= 2) {
			if (V.geneticFlawLibrary !== 1) {
				const anomaliesCost = 100000 * PCSkillCheck;
				App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
					"Purchase designs for inducing genetic anomalies",
					() => {
						cashX(forceNeg(anomaliesCost), "capEx");
						V.geneticFlawLibrary = 1;
						App.UI.reload();
					}, [], "",
					`Costs ${cashFormat(anomaliesCost)}. Will allow genetic flaws and quirks to be injected into a slave's genome`
				));
			} else {
				App.UI.DOM.appendNewElement("div", node, `The fabricator is capable of producing treatments to induce various genetic anomalies.`);
			}

			if (V.bioEngineeredFlavoringResearch === 1) {
				App.UI.DOM.appendNewElement("div", node, `The fabricator is capable of producing treatments to change the flavor of a slave's milk.`);
			} else if (V.cash >= flavoringCost) {
				App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
					"Fund research into bio-engineered human milk flavoring",
					() => {
						cashX(forceNeg(flavoringCost), "capEx");
						V.bioEngineeredFlavoringResearch = 1;
						App.UI.reload();
					}, [], "",
					`Costs ${cashFormat(flavoringCost)}. This will allow changing the flavor of a slave's milk`
				));
			}
		}
		if (V.seeCats === 1) {
			let r = [];
			if (V.geneticMappingUpgrade >= 2 && V.projectN.status === 0) {
				const catCost = 150000 * PCSkillCheck;
				App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
					"Hire a team of renowned bioengineers and geneticists to splice the human genome with cat DNA and fulfill the destiny of mankind - creating catgirls",
					() => {
						cashX(forceNeg(catCost), "capEx");
						V.projectN.status = 1;
						App.UI.reload();
					}, [], "",
					`Costs ${cashFormat(catCost)}. Will begin a long-term project to push the boundaries of science and genetically engineer the world's first catgirl`
				));
			} else if (V.projectN.status === 1) {
				App.UI.DOM.appendNewElement("div", node, `You've started to get into contact with a number of renowned old-world biologists and genetic engineers to pursue the creation of a biological catgirl. They should be arriving soon.`);
			} else if (V.projectN.status === 2) {
				App.UI.DOM.appendNewElement("div", node, `You've gathered together a team of some of the old world's foremost scientific minds in the fields of genetic engineering, who've turned your gene lab into a workplace for what they've dubbed "Project N", or the "Cat Project". One white-bearded man looks up from a large computer screen showing a series of complicated genetic sequences as you enter.`);
			} else if (V.projectN.status === 3) {
				App.UI.DOM.appendNewElement("div", node, `The geneticist team has started to make serious progress on project N. In a central tube filled with thick green liquid, a small mass of pinkish material floats in suspended animation, referred to by the biologists as "Subject Delta". A series of screens next to the tube read out low-functioning vitals and other essential information.`);
			} else if (V.projectN.status === 4) {
				App.UI.DOM.appendNewElement("div", node, `The pinkish blob of flesh has become a small, hairless humanoid body with twitchy cat ears atop its head, unconsciously floating while suspended in the green tube. You've tentatively named the growing catgirl ${V.subjectDeltaName}, and she occasionally kicks around slightly in the tube, producing a little stream of floating bubbles. The Project N bioengineers carefully monitor her vitals at all times, aided by the lab's integrated AI.`);
			} else if (V.projectN.status === 5) {
				App.UI.DOM.appendNewElement("div", node, `${V.subjectDeltaName} looks like an almost fully grown catgirl now, complete with a thin but soft layer of pure white fur that puffs up in the thick green liquid of her tube. The Project N geneticists seem a little rattled after the attack by the Sons of Sekhmet, but they're more determined than ever to finish their job and ensure that subject Delta makes it out of this tube and into the real world, a possibility that looks closer day by day.`);
			} else if (V.projectN.status === 6) {
				App.UI.DOM.appendNewElement("div", node, `Project N is complete. Dr. Nieskowitz and his team are currently monitoring various functions of the genetic laboratory, though you could set them to work engineering another catgirl if you give them the funding to do so. It will take approximately a month to create another catgirl. The genetic engineering tube is currently empty.`);
				const engineerCatCost = 20000 * PCSkillCheck;
				App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
					"Engineer me a Catgirl",
					() => {
						cashX(forceNeg(engineerCatCost), "capEx");
						V.projectN.status = 7;
						V.growingNewCat = 4;
						App.UI.reload();
					}, [], "",
					`Costs ${cashFormat(engineerCatCost)}`
				));
				App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
					"Engineer me a Catboy",
					() => {
						cashX(forceNeg(engineerCatCost), "capEx");
						V.projectN.status = 8;
						V.growingNewCat = 4;
						App.UI.reload();
					}, [], "",
					`Costs ${cashFormat(engineerCatCost)}`
				));
			} else if (V.projectN.status === 7) {
				r.push(`Dr. Nieskowitz and his team are currently hard at working growing you another catgirl, who rapidly develops in the central tube of thick green liquid you once used to create ${V.subjectDeltaName}. Nieskowitz assures you that he'll have your new catgirl finished`);
				if (V.growingNewCat >= 2) {
					r.push(`in ${V.growingNewCat} weeks.`);
				}
				if (V.growingNewCat <= 1) {
					r.push(`by next week.`);
				}
			} else if (V.projectN.status === 8) {
				r.push(`Dr. Nieskowitz and his team are currently hard at working growing you another catboy, who rapidly develops in the central tube of thick green liquid you once used to create ${V.subjectDeltaName}. Nieskowitz assures you that he'll have your new catboy finished`);
				if (V.growingNewCat >= 2) {
					r.push(`in ${V.growingNewCat} weeks.`);
				}
				if (V.growingNewCat <= 1) {
					r.push(`by next week.`);
				}
			} else if (V.projectN.status === 9) {
				r.push(`The bomb set by the Sons of Sekhmet destroyed large parts of the gene lab and killed most of the personnel, including ${V.subjectDeltaName}'s tube. After the death of Doctor Nieskowitz, you haven't just lost ${V.subjectDeltaName} herself, but also the knowledge used to create her. It's doubtful that there's anyone left in the world who can finish what he started.`);
			}
			App.Events.addParagraph(node, r);
		}
	}

	App.UI.DOM.appendNewElement("h2", node, `Genetic Harvesting`);

	const humanCloning = 100000 * PCSkillCheck;
	if (V.cloningSystem === 0) {
		if (V.rep <= 18000 * PCSkillCheck) {
			if (V.rep >= 20_000) {
				App.UI.DOM.appendNewElement("div", node, `You have heard rumors of human cloning, but such technology is too advanced for your understanding. Perhaps you should invest into your own education.`, ["note"]);
			} else {
				App.UI.DOM.appendNewElement("div", node, `You lack the reputation needed to access methods for human cloning`, ["note"]);
			}
		} else {
			if (V.organFarmUpgrade === 0) {
				App.UI.DOM.appendNewElement("div", node, `An organ farm is needed to grow the blank embryo to serve as a clone base`, ["note"]);
			} else {
				App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
					"Purchase methods for human cloning",
					() => {
						cashX(forceNeg(humanCloning), "capEx");
						V.cloningSystem = 1;
						App.UI.reload();
					}, [], "",
					`Costs ${cashFormat(humanCloning)}. Will allow children to be created with identical base genetics as the source DNA`
				));
			}
		}
	} else if (V.cloningSystem > 0) {
		App.UI.DOM.appendNewElement("div", node, `The gene lab is capable of implanting a slave's genetic sequence into a blank embryo to produce a basic clone.`);
		App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link(
			"Make a clone",
			() => {
				V.donatrix = 0;
				V.receptrix = 0;
			}, [], "Cloning Workaround",
		));
	}
	return node;
};

repo_name: Nithhogg/fc

license: mit


code:
App.Facilities.HGSuite.headGirlSuite = class HeadGirlSuite extends App.Facilities.Facility {
	constructor() {
		const headGirlSuite = App.Entity.facilities.headGirlSuite;
		const decommissionHandler = () => {
			V.HGSuite = 0;
		};

		super(
			headGirlSuite,
			decommissionHandler,
		);

		V.nextButton = "Back to Main";
		V.nextLink = "Main";
		App.UI.StoryCaption.encyclopedia = "Head Girl Suite";

		this.subSlave = this.facility.employees()[0];
	}

	/** @returns {string} */
	get intro() {
		const text = [];

		if (!S.HeadGirl) {
			text.push(`You have no Head Girl appointed to live in ${V.HGSuiteName}.`);
		} else {
			const {him, his} = getPronouns(S.HeadGirl);

			if (this.facility.hasEmployees) {
				text.push(`Your Head Girl ${S.HeadGirl.slaveName} has ${this.subSlave.slaveName} living in ${V.HGSuiteName} with ${him}, as ${his} servant, assistant, and sexual appliance.`);
			} else {
				text.push(`Your Head Girl ${S.HeadGirl.slaveName} lives alone in ${his} handsome suite.`);
			}

			text.push(`Any slave assigned to live with your Head Girl will become, for all intents and purposes, ${his} slave.`);
		}

		return text.join(' ');
	}

	/** @returns {FC.Facilities.Expand} */
	get expand() {
		return {
			maximum: 1,
			unexpandable: true,
		};
	}

	/** @returns {FC.Facilities.Rule[]} */
	get rules() {
		if (S.HeadGirl) {	// only display rules if a Headgirl is assigned
			const {He, his} = getPronouns(S.HeadGirl);

			return [
				{
					property: "HGSuiteEquality",
					prereqs: [],
					options: [
						{
							get text() { return `The current Head Girl will remain Head Girl.`; },
							link: `Don't alternate`,
							value: 0,
						},
						{
							get text() { return `The two slaves living in ${V.HGSuiteName} are equals, and will alternate weeks as Head Girl and Head Girl's bitch.`; },
							link: `Have them alternate`,
							value: 1,
							handler: () => {
								V.HGSuiteSurgery = 0;
								V.HGSuiteDrugs = 0;
								V.HGSuiteAbortion = 0;
								V.HGSuiteHormones = 0;
							},
							note: `This will only take effect if the other slave is an appropriate candidate.`,
						},
					],
				},
				{
					property: "HGSuiteSurgery",
					prereqs: [
						!V.HGSuiteEquality,
					],
					options: [
						{
							get text() { return `${He} is not allowed to use surgical modification on ${his} slave.`; },
							link: `Forbid`,
							value: 0,
						},
						{
							get text() { return `${He} is allowed to use surgical modification on ${his} slave.`; },
							link: `Allow`,
							value: 1,
						},
					],
				},
				{
					property: "HGSuiteAbortion",
					prereqs: [
						!V.HGSuiteEquality,
					],
					options: [
						{
							get text() { return `${He} is not allowed to terminate unwanted pregnancies in ${his} slave.`; },
							link: `Forbid`,
							value: 0,
						},
						{
							get text() { return `${He} is allowed to terminate unwanted pregnancies in ${his} slave.`; },
							link: `Allow`,
							value: 1,
						},
					],
				},
				{
					property: "HGSuiteDrugs",
					prereqs: [
						!V.HGSuiteEquality,
					],
					options: [
						{
							get text() { return `${He} is not allowed to use growth hormones on ${his} slave.`; },
							link: `Forbid`,
							value: 0,
						},
						{
							get text() { return `${He} is allowed to use growth hormones on ${his} slave.`; },
							link: `Allow`,
							value: 1,
						},
					],
				},
				{
					property: "HGSuiteHormones",
					prereqs: [
						!V.HGSuiteEquality,
					],
					options: [
						{
							get text() { return `${He} is not allowed to customize ${his} slave with hormone treatments.`; },
							link: `Forbid`,
							value: 0,
						},
						{
							get text() { return `${He} is allowed to customize ${his} slave with hormone treatments.`; },
							link: `Allow`,
							value: 1,
						},
					],
				},
			];
		}

		return [];
	}
};


code:
/** @type {FC.FacilityFramework} */
App.Data.Facilities.headGirlSuite = {
	baseName: "HGSuite",
	genericName: null,
	jobs: {
		HGToy: {
			position: "Head Girl's toy",
			assignment: Job.HEADGIRLSUITE,
			publicSexUse: true,
			fuckdollAccepted: false
		}
	},
	defaultJob: "HGToy",
	manager: {
		position: "Head Girl",
		assignment: Job.HEADGIRL,
		careers: App.Data.Careers.Leader.HG,
		skill: "headGirl",
		publicSexUse: false,
		fuckdollAccepted: false,
		broodmotherAccepted: false,
		shouldWalk: true,
		shouldHold: true,
		shouldSee: true,
		shouldHear: true,
		shouldTalk: true,
		shouldThink: true,
		requiredDevotion: 51
	},
	decorated: false,
	penthouseFacility: true
};

App.Entity.Facilities.HeadGirlSuite = class extends App.Entity.Facilities.SingleJobFacility {
	constructor() {
		super(App.Data.Facilities.headGirlSuite);
	}

	/** @override */
	occupancyReport(long) {
		return this.manager.currentEmployee
			? `HG${this.hostedSlaves() ? long
				? ` and ${getPronouns(this.manager.currentEmployee).his} slave`
				: ", 1" : ""}`
			: "";
	}
};

App.Entity.facilities.headGirlSuite = new App.Entity.Facilities.HeadGirlSuite();


code:
App.UI.implantManufactory = function() {
	const node = new DocumentFragment();

	const PCSkillCheck = Math.min(V.upgradeMultiplierMedicine, V.HackingSkillMultiplier);

	/**
	 * @param {ParentNode} node
	 * @param {number} reputationReqBase
	 * @param {string} label
	 * @param {string[]} notes
	 * @param {number} costsBase
	 * @param {function(): void} handler
	 * @param {string} [lackRepSubject]
	 */
	const upgradeOption = (node, reputationReqBase, label, notes, costsBase, handler, lackRepSubject = '') => {
		const lackRepText = () => lackRepSubject ? lackRepSubject : `access ${label}`;

		if (V.rep < reputationReqBase * PCSkillCheck) {
			App.UI.DOM.appendNewElement('div', node, `You lack the reputation to ${lackRepText()}.`, ['note']);
		} else {
			node.appendChild(makePurchase(`Purchase ${label}`, costsBase * PCSkillCheck, "capEx", {
				notes,
				handler,
			}));
		}
	};

	App.UI.DOM.appendNewElement("h1", node, "The Implant Manufactory");

	App.UI.DOM.appendNewElement("p", node, `The implant manufactory is running smoothly. It can cheaply produce advanced implants and has freed you from relying on outside sources for specialty implants. It can easily produce more complex implants should you obtain the schematics necessary to build them.`, ["scene-intro"]);

	App.UI.DOM.appendNewElement("h2", node, "Implant Production");

	App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of producing customized fillable implants.");

	if (V.meshImplants > 0) {
		App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of producing supportive mesh breast implants.");
	} else {
		upgradeOption(node, 10_000, "plans for supportive mesh breast implants", ["will allow the construction of organic and supportive mesh breast implants."],
			40_000, () => { V.meshImplants = 1; });
	}

	if (V.UterineRestraintMesh === 1) {
		App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of producing supportive mesh uterine implants.");
	}

	if (V.bellyImplants === 0) {
		upgradeOption(node, 2000, "schematics for fillable abdominal implants", ["will allow the construction of fillable abdominal implants for the autosurgery."],
			30_000, () => { V.bellyImplants = 1; },
			"access experimental schematics for fillable abdominal implants");
	} else if (V.bellyImplants > 0) {
		App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of crafting fillable abdominal implants.");
		if (V.bellyImplants === 1 && V.cervixImplants === 0) { /* show only after belly implants already researched */
			/* nanotech like technology much more impressive and costly than simple implant */
			upgradeOption(node, 6000, "schematics for cervix filter micropumps", ["will allow the construction of cervix filter micropumps for fillable abdominal implants using the autosurgery."],
				70_000, () => { V.cervixImplants = 1; },
				"access experimental cervix filter micropumps schematics for abdominal implants");
		} else if (V.cervixImplants === 1) {
			App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of crafting cervix filter micropumps for fillable abdominal implants.");
			upgradeOption(node, 8_000, "conversion kits for rectal filter micropumps", ["will allow the construction of the anal equivalent of the cervix micropumps using the autosurgery."],
				60_000, () => { V.cervixImplants = 2; },
				"obtain conversion kits for rectal filter micropumps"
			);
		} else if (V.cervixImplants > 1) {
			App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of crafting cervix and rectal filter micropumps for fillable abdominal implants.");
		}
		if (V.cervixImplantUpgrade !== 1 && V.cervixImplants > 0) {
			upgradeOption(node, 6000, "micropump system extension", ["will allow micropumps to be upgraded to transfer filler to other fillable implants"],
				120000, () => { V.cervixImplantUpgrade = 1; },
				"obtain schematics for a filler circulation system"
			);
		} else if (V.cervixImplantUpgrade) {
			App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of crafting a network of tubes and pumps capable of moving inert filler to fillable implants.");
		}
	}

	if (V.seePreg !== 0) {
		App.UI.DOM.appendNewElement("h2", node, "Fertility Implants");

		if (V.fertilityImplant === 1) {
			App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of crafting fertility enhancing implants for ovaries.");
		} else {
			upgradeOption(node, 3_000, "fertility enhancing ovarian implants", ["will allow the construction of implants that encourage multiple eggs being released during ovulation."],
				10_000, () => { V.fertilityImplant = 1; },
				"access fertility boosting ovarian implants"
			);
		}

		if (V.sympatheticOvaries === 1) {
			App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of crafting implants that synchronize ovum release.");
		}

		if (V.seeHyperPreg === 1 && V.seeExtreme === 1) {
			if (V.permaPregImplant === 0) {
				upgradeOption(node, 4_000, "schematics for an experimental implantable pregnancy generator", ["will allow the construction of implants that force perpetual pregnancy."],
					40_000, () => { V.permaPregImplant = 1; },
					"access experimental pregnancy generator schematics");
			} else if (V.permaPregImplant > 0) {
				App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of crafting pregnancy generators.");
			}
			if (V.PGHack === 1) {
				App.UI.DOM.appendNewElement("div", node, "The tools required to hack the firmware of basic pregnancy generator implants have been produced by the manufactory for use in the remote surgery.");
			}
		}
	}

	App.UI.DOM.appendNewElement("h2", node, "Fluid Production Implants");

	if (V.prostateImplants !== 1) {
		upgradeOption(node, 3_000, "plans for ejaculation enhancing prostate implants",
			["will allow the construction of a prostate implant designed to stimulate fluid production for massive ejaculations. Beware of leaking and dehydration."],
			30_000, () => { V.prostateImplants = 1; },
			"access plans for prostate implants"
		);
	} else if (V.prostateImplants > 0) {
		App.UI.DOM.appendNewElement("div", node, "The manufactory is capable of producing ejaculation enhancing prostate implants.");
	}
	return node;
};


code:
/** @type {FC.FacilityFramework} */
App.Data.Facilities.incubator = {
	baseName: "incubator",
	genericName: null,
	jobs: {
		tank: {
			position: "tank",
			assignment: Job.TANK,
			publicSexUse: false,
			fuckdollAccepted: false
		}
	},
	defaultJob: "tank",
	manager: null,
	decorated: false,
	penthouseFacility: true
};

App.Entity.Facilities.IncubatorTankJob = class extends App.Entity.Facilities.Job {
	/**
	 * @override
	 * @returns {FC.TankSlaveState[]}
	 */
	employees() {
		return getTankSlaves().asArray();
	}

	/** @override */
	employeesIDs() {
		return new Set(this.employees().map(s => s.ID));
	}
};

App.Entity.Facilities.Incubator = class extends App.Entity.Facilities.Facility {
	constructor() {
		super(App.Data.Facilities.incubator, {
			tank: new App.Entity.Facilities.IncubatorTankJob()
		});
	}
};

App.Entity.facilities.incubator = new App.Entity.Facilities.Incubator();