code:
App.Facilities.MilkmaidSelect = function() {
	const f = document.createDocumentFragment();

	if (S.Milkmaid) {
		f.append(`${SlaveFullName(S.Milkmaid)} is working as your Milkmaid, looking after your livestock, helping them give milk${V.seeDicks > 0 ? ' and semen' : ''}. `);
		f.append(App.UI.DOM.link("Remove Milkmaid", () => {
			removeJob(S.Milkmaid, Job.MILKMAID);
		},
		[], "Dairy"
		));
	} else {
		f.append(`No Milkmaid assigned, appoint one from your devoted slaves.`);
	}

	f.append(App.UI.SlaveList.facilityManagerSelection(App.Entity.facilities.dairy, "Dairy"));
	return f;
};


code:
App.Data.Facilities.dairy = {
	baseName: "dairy",
	genericName: null,
	jobs: {
		cow: {
			position: "cow",
			assignment: Job.DAIRY,
			publicSexUse: false,
			fuckdollAccepted: false
		}
	},
	defaultJob: "cow",
	manager: {
		position: "milkmaid",
		assignment: Job.MILKMAID,
		careers: App.Data.Careers.Leader.milkmaid,
		skill: "milkmaid",
		publicSexUse: false,
		fuckdollAccepted: false,
		broodmotherAccepted: false,
		shouldWalk: true,
		shouldHold: true,
		shouldSee: true,
		shouldHear: true,
		shouldTalk: false,
		shouldThink: true,
		requiredDevotion: 21
	},
	decorated: true
};

App.Entity.Facilities.DairyCowJob = class extends App.Entity.Facilities.FacilitySingleJob {
	/**
	 * @override
	 * @returns {string}
	 */
	get assignment() {
		return `be milked in ${this.facility.name}`;
	}

	/**
	 * @param {App.Entity.SlaveState} slave
	 * @returns {string[]}
	 */
	checkRequirements(slave) {
		let r = super.checkRequirements(slave);

		if ((slave.indentureRestrictions > 0) && (V.dairyRestraintsSetting > 1)) {
			r.push(`${slave.slaveName}'s indenture forbids extractive Dairy service.`);
		}
		if ((slave.indentureRestrictions > 1) && (V.dairyRestraintsSetting > 0)) {
			r.push(`${slave.slaveName}'s indenture allows only free range milking.`);
		}
		if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset" && V.dairyRestraintsSetting > 0) {
			r.push(`${slave.slaveName} may only be a free range cow.`);
		}
		if ((V.dairyPregSetting > 0) && ((slave.bellyImplant !== -1) || (slave.broodmother !== 0))) {
			r.push(`${slave.slaveName}'s womb cannot accommodate current machine settings.`);
		}

		if (!isAmputee(slave) && (this.facility.option("RestraintsUpgrade") !== 1) &&
			!App.Entity.Facilities.Job._isBrokenEnough(slave, 20, -50, -20, -50)) {
			r.push(`${slave.slaveName} must be obedient in order to be milked at ${this.facility.name}.`);
		}

		if ((slave.lactation === 0) && (slave.balls === 0)) {
			// the slave does not produce useful liquids now. Let's find out can the dairy make it lactate
			if ((V.dairySlimMaintainUpgrade !== 1 && V.dairySlimMaintain <= 0) && V.dairyImplantsSetting !== 1 && V.dairyImplantsSetting !== 3) {
				// dairy settings disallow any procedures
				r.push(`${slave.slaveName} is not lactating ` + ((V.seeDicks > 0) ? 'or producing semen ' : '') + `and ${this.facility.name}'s current settings forbid the automatic implantation of lactation inducing drugs or manual stimulation to induce it, and thus cannot be a cow.`);
			} else if (slave.boobs <= 300) {
				r.push(`${slave.slaveName} is not lactating ` + ((V.seeDicks > 0) ? 'or producing semen ' : '') + 'and have not enough breast tissue to induce lactation.');
			}
		}
		if ((V.dairyStimulatorsSetting >= 2) && (slave.anus <= 2) && (V.dairyPrepUpgrade !== 1)) {
			r.push(`${slave.slaveName}'s anus cannot accommodate current machine settings.`);
		}
		if ((V.dairyPregSetting >= 2) && (slave.vagina <= 2) && (slave.ovaries !== 0) && (V.dairyPrepUpgrade !== 1)) {
			r.push(`${slave.slaveName}'s vagina cannot accommodate current machine settings.`);
		}

		return r;
	}
};

App.Entity.Facilities.Dairy = class extends App.Entity.Facilities.SingleJobFacility {
	constructor() {
		super(App.Data.Facilities.dairy,
			{
				cow: new App.Entity.Facilities.DairyCowJob()
			});
	}

	/** @override */
	get nonEmployeeOccupantsCount() {
		return V.bioreactorsXY + V.bioreactorsXX + V.bioreactorsHerm + V.bioreactorsBarren;
	}
};

App.Entity.facilities.dairy = new App.Entity.Facilities.Dairy();

repo_name: Elohiem/fc

license: mit


code:
App.Facilities.Dairy.inflation = function() {
	const inflatedSlaves = {
		milk: 0,
		cum: 0
	};
	for (const s of V.slaves) {
		if (s.inflationMethod === 1 || s.inflationMethod === 2) {
			if (s.inflationType === "milk") {
				inflatedSlaves.milk++;
			} else if (s.inflationType === "cum") {
				inflatedSlaves.cum++;
			}
		}
	}
	return inflatedSlaves;
};


code:
App.Facilities.Dairy.freeRangeAssignmentScene = function(slave) {
	/* This scene wants V.dairyRestraintsSetting === 0 && slave.devotion > 0 && slave.fetish !== "mindbroken" */
	const node = new DocumentFragment();

	V.nextButton = "Continue";
	V.nextLink = V.returnTo;
	let r = [];
	const {
		He, His,
		he, him, his, himself
	} = getPronouns(slave);

	App.UI.DOM.drawOneSlaveRight(node, slave);

	r.push(`${slave.slaveName} reports to the dairy.`);
	if (slave.energy > 90 ) {
		r.push(`${He} rejoices since ${he} is actually eager to be milked.`);
	}
	App.Events.addParagraph(node, r);
	r = [];

	/* AROUSAL WHEN ENTERING */
	let aroused = false;
	if (App.Entity.facilities.dairy.employeesIDs().size > 1 && canSee(slave)) {
		r.push(`While`);
		if (canWalk(slave)) {
			r.push(`walking`);
		} else if (canMove(slave)) {
			r.push(`being helped`);
		} else {
			r.push(`being carried`);
		}
		r.push(`to ${his} designated stall, ${he} passes the other cows currently at their milking machines. Not being hurried, ${he} occasionally watches a cow in detail.`);
		App.Events.addParagraph(node, r);
		r = [];
		if (slave.fetish === "boobs") {
			/* TODO: check if there actually are lactating cows at the dairy */
			aroused = true;
			r.push(`${He} cannot help but to feel aroused at the view of all those udders being thoroughly milked.`);
			if (slave.sexualFlaw === "breast growth") {
				r.push(`${He} is already fantasizing of having ${his} breasts expanded to ridiculous proportions${(slave.lactation > 0) ? ` so ${he} can produce even more milk` : ""}.`);
			}
		} else if (slave.fetish === "pregnancy" && V.dairyPregSetting === 1) {
			aroused = true;
			r.push(`The automatic impregnators are currently active. They are not running on an industrial setting, but on a gentler one. Every fertile cow's pussy is filled with a dildo attached on a mechanical arm. There is a wide range of sizes. Some dildos are small and provide expert stimulation for the sensitive areas. Other cows seem to prefer forearm-length horse-cocks for more intense stimulation. The automatic thrusting speeds vary, too, but all of them fill the slave completely so not a drop of sperm can leak out. Some cows are currently asleep. Their respective stimulators are comfortably resting deeply buried in their vaginas, keeping the loads right where they belong. Whenever a cow reaches climax, the sodomizers can thrust at ridiculous speeds to encourage fertilization. The sight of all those lovely baby bumps arouses ${slave.slaveName}.`);
			if (slave.sexualFlaw === "breeder" && isFertile(slave)) {
				r.push(`${He} cannot wait to get impregnated too.`);
			}
		} else if (slave.fetish === "buttslut" && V.dairyStimulatorsSetting === 1) {
			aroused = true;
			r.push(`The automatic sodomizers are currently active. They are not running on an industrial setting, but on a gentler one. Every cow's anus is filled with a dildo attached on a mechanical arm. There is a wide range of sizes. Some dildos are small and provide expert stimulation for the sensitive areas. Other cows seem to prefer forearm-length horse-cocks for more intense stimulation. The automatic thrusting speeds vary, too. Some cows are currently asleep. Their respective stimulators are comfortably resting deeply buried in their behinds. Whenever a cow reaches climax, the sodomizers can thrust at ridiculous speeds. Good thing they provide not only nutrition, but lubrication, too. The sight of all those lovely rear-ends relentlessly reamed arouses ${slave.slaveName}.`);
			if (slave.sexualFlaw === "anal addict") {
				r.push(`${He} cannot wait to be sodomized, too.`);
			}
		}
		App.Events.addParagraph(node, r);
		r = [];

		const cow = V.slaves.find(s => s.assignment === "work in the dairy" && s.ID !== V.AS && s.balls >= 10 && s.dick > 0);
		if (cow) {
			const {
				He2, His2,
				he2, his2, him2,
			} = getPronouns(cow).appendSuffix("2");
			aroused = true;
			App.UI.DOM.drawOneSlaveRight(node, cow);
			r.push(`The hyper-endowed cum-cow ${cow.slaveName} is the pride of ${V.dairyName}. ${He2} is limply hanging on ${his2} milking chair, panting heavily because of the constant suction on ${his2} dick. ${He2} is obviously nearing climax. Soon,`);
			if (hasAnyNaturalEyes(cow)) {
				r.push(his2);
				if (hasBothNaturalEyes(cow)) {
					r.push(`eyes bulge`);
				} else {
					r.push(`eye bulges`);
				}
				r.push(`and`);
			}
			r.push(`${his2} muscles tense.`);
			if (V.dairyStimulatorsSetting === 1) {
				if (cow.prostate !== 0) {
					r.push(`${His2} anus clenches around the dildo in ${his2} rear. The automatic sodomizer speeds up to give ${his2} prostate a helpful pounding.`);
				} else {
					r.push(`${He2} lacks a prostate, so the automatic sodomizer is forced to pound ${him2} mercilessly to make ${him2} cum.`);
				}
			} else if (V.MilkmaidID !== 0 && S.Milkmaid.dick > 4 && canPenetrate(S.Milkmaid)) {
				r.push(`${S.Milkmaid.slaveName} quickly steps in and penetrates ${his2} rear to push ${him2} powerfully over the edge.`);
			} else {
				r.push(`${His2} butthole opens and closes.`);
			}
			r.push(`${His2} cock twitches as it begins to unload. Inhumanly large amounts of semen spurt into the receptacle which encases ${his2} dick. ${His2} orgasm does not seem to end for minutes. The milking machine keeps ${him2} cumming longer than naturally possible. Only primal moans escape ${his2} throat. As ${his2} orgasm finally subsides, ${he2} slumps back, grinning in post-orgasmic bliss. All things considered, ${cow.slaveName} seems to be very happy with being a cow.`);
			if (cow.dickTat === "bovine patterns" ) {
				r.push(`Even ${his2} dick is tattooed to look like a bull's.`);
			}
			App.Events.addParagraph(node, r);
			r = [];
			App.UI.DOM.appendNewElement("div", node, `"Moo," ${he2} moans lustily, imitating a cow.`);
		}
	/* TODO: watch a specific cow, e.g. lover or relative or huge-titted */
	}

	if (aroused) {
		r.push(`All this lewd display turns ${slave.slaveName} on and ${he} is almost overcome by lust. ${He} realizes ${he} probably should not have taken so much interest in the other cows.`);
		if (slave.dick > 0) {
			r.push(`${He} feels ${his} blood rush into ${his}`);
			if (slave.dick > 8) {
				r.push(`gargantuan`);
			} else if (slave.dick > 6) {
				r.push(`huge`);
			} else if (slave.dick > 2) {
				r.push(`fair-sized`);
			} else {
				r.push(`small`);
			}
			r.push(`dick.`);
		}
		if (slave.vagina > -1 ) {
			r.push(`${His} pussy moistens.`);
		}
		if (slave.lactation > 0) {
			if (slave.nipples === "fuckable") {
				r.push(`Milk begins to leak out of ${his} nipplecunts.`);
			} else {
				r.push(`${His} milk-dripping nipples stiffen.`);
			}
		}
	} /* AROUSAL WHEN ENTERING END*/
	App.Events.addParagraph(node, r);
	r = [];

	/* GETTING IN */
	r.push(`Eventually, ${slave.slaveName} arrives at ${his} designated milking stall.`);
	let assayedSlave = randomRelatedSlave(slave, s => s.assignment === Job.DAIRY);
	let assayType;
	if (assayedSlave) {
		assayType = relativeTerm(slave, assayedSlave);
	} else if (slave.relationship > 0) {
		assayedSlave = getSlave(slave.relationshipTarget);
		if (assayedSlave && assayedSlave.assignment === Job.DAIRY) {
			switch (slave.relationship) {
				case 1:
					assayType = "friend";
					break;
				case 2:
					assayType = "best friend";
					break;
				case 3:
					assayType = "fuckbuddy";
					break;
				case 4:
					assayType = "lover";
					break;
				case 5:
					assayType = "slave wife";
					break;
			}
		}
	}
	if (assayType) {
		const {
			He2
		} = getPronouns(assayedSlave).appendSuffix("2");
		App.UI.DOM.drawOneSlaveRight(node, assayedSlave);
		r.push(`${His} ${assayType} ${assayedSlave.slaveName} is at the dairy, too. ${He2} is in the adjacent stall. The two of them are going to be milked right next to each other.`);
	}
	App.Events.addParagraph(node, r);
	r = [];

	App.UI.DOM.drawOneSlaveRight(node, S.Milkmaid);
	r.push(`The only "furniture" in the stall looks like a dentist's chair. Despite the medical appearance, when ${he}`);
	if (slave.devotion > 90) {
		r.push(`eagerly`);
	} else if (slave.slaveName < 40) {
		r.push(`hesitantly`);
	}
	r.push(`gets into the chair it turns out to be quite comfortable.`);
	if (V.MilkmaidID === 0) {
		r.push(`Automated machinery springs to life, preparing ${him} for milking.`);
	} else {
		r.push(`Your appointed milkmaid ${S.Milkmaid.slaveName} helps ${slave.slaveName} with installing the milking devices.`);
	}
	if (slave.lactation > 0 ) {
		r.push(`Suction cups are attached`);
		if (slave.nipples === "fuckable" || slave.nipples === "flat") {
			r.push(`over`);
		} else {
			r.push(`to`);
		}
		r.push(`${his} nipples.`);
	}
	if (slave.balls > 0) {
		if (slave.dick > 8) {
			r.push(`A huge receptacle is attached to ${his} over-sized member.`);
		} else if (slave.dick > 6) {
			r.push(`A large cock-milker is attached to ${his} huge dick.`);
		} else if (slave.dick > 2) {
			r.push(`A special cock-milker is attached to ${his} dick.`);
		} else if (slave.dick > 0) {
			r.push(`A suction cup is attached to ${his} small dicklet. Due to the embarrassingly small size of ${his} penis, the very kind of cup is used that normally goes on nipples.`);
		} else {
			r.push(`A suction cup is attached over ${his} hidden cumhole.`);
		}
	}
	App.Events.addParagraph(node, r);
	r = [];
	if (V.dairyFeedersSetting === 1) {
		r.push(`Near the headrest of the chair, an artificial phallus is installed. The cow can easily reach it with ${his} mouth. The phallus provides hydration and nutrition when sucked. The supplement consists of excess or low-quality milk and cum from the dairy itself as well as aphrodisiacs and hormones enhancing lactation and semen production.`);
		if (slave.sexualFlaw === "cum addict" || slave.fetish === "cumslut") {
			r.push(`${slave.slaveName}`);
			r.push(`eagerly shoves the artificial phallus into ${his} mouth. ${He} gives it an experimental suckle. To ${his} joy, ${he} soon is rewarded with a fresh spurt of semen-like nutrition supplement. Then ${he} readjusts the holder to keep the phallus lodged in ${his} mouth, effectively forcing ${himself} to keep sucking the artificial dick.`);
		}
	}
	App.Events.addParagraph(node, r);
	r = [];
	r.push(`The milking chair comes with a small screen, providing mental stimulation for the cow. It is highly pornographic, of course. It also includes live-streams of close-ups from the cows being milked or their orifices being penetrated. ${slave.slaveName} selects ${his} favorite program`);
	if (canSee(slave)) {
		r.push(`to watch.`);
	} else if (canHear(slave)) {
		r.push(`to listen to.`);
	} else {
		r.push(`to feel the vibrations from.`);
	}
	r.push(`It features`);
	if (slave.attrXY > slave.attrXX || slave.behavioralQuirk === "adores men") {
		r.push(`men`);
	} else {
		r.push(`women`);
	}
	if (slave.fetish === "submissive") {
		r.push(`submitting to their sexual partners.`);
	} else if (slave.fetish === "cumslut") {
		if (slave.attrXY > slave.attrXX || slave.behavioralQuirk === "adores men") {
			r.push(`jacking off directly into the camera.`);
		} else {
			r.push(`sucking dick for all it's worth.`);
		}
		if (V.dairyFeedersSetting === 1 ) {
			r.push(`The dairy feeders ejaculations are synced with the events in the video. ${slave.slaveName} receives a load of cum-like nutrition every time a dick shoots. It really draws ${him} into the pornography.`);
		}
	} else if (slave.fetish === "humiliation") {
		r.push(`being humiliated.`);
	} else if (slave.fetish === "buttslut") {
		r.push(`being fucked in the ass.`);
		if (V.dairyStimulatorsSetting === 1) {
			r.push(`The dairy stimulators are synced to the videos. The automatic sodomizers thrust in exactly the same way as the dicks or dildos in the video. ${slave.slaveName} is amazed by this advanced pornography. It feels like it was ${him} being fucked in the videos all over.`);
		}
	} else if (slave.fetish === "dom") {
		r.push(`dominating their sexual partners.`);
	} else if (slave.fetish === "masochist") {
		r.push(`being flogged.`);
	} else if (slave.fetish === "sadist") {
		r.push(`abusing their sexual partners.`);
	} else if (slave.fetish === "pregnancy") {
		if (slave.attrXY > slave.attrXX || slave.behavioralQuirk === "adores men") {
			r.push(`fucking pregnant women.`);
		} else {
			r.push(`being fucked while pregnant.`);
			if (V.dairyPregSetting > 0) {
				r.push(`The dairy stimulators are synced to the videos. The impregnating dildo thrusts in exactly the same way as the dicks or dildos in the video. ${slave.slaveName} is amazed by this advanced pornography. It feels like it was ${him} being fucked and cummed inside in the videos all over.`);
			}
		}
	} else {
		r.push(`engaging in vanilla intercourse.`);
	}
	App.Events.addParagraph(node, r);
	r = [];

	r.push(`Sexual stimulation increases product output.`);
	if (V.MilkmaidID === 0 && V.dairyStimulatorsSetting === 0) {
		r.push(`Unfortunately, there is neither a milkmaid providing personal assistance nor automatic sodomizers installed in your dairy.`);
	} else {
		if (V.MilkmaidID !== 0) {
			const {
				He2,
				he2, his2
			} = getPronouns(S.Milkmaid).appendSuffix("2");
			r.push(`Your milkmaid ${S.Milkmaid.slaveName} is working in the dairy. Whenever a cow needs ${his2} assistance, ${he2} is happy to help.`);
			if (S.Milkmaid.dick > 1 && canPenetrate(S.Milkmaid)) {
				r.push(`Most often, ${he2} uses ${his2} cock to penetrate the cows.`);
			} else {
				r.push(`Lacking penile equipment of appropriate size, ${he2} relies on ${his2} tongue to stimulate the cow's sexual organs.`);
			}
			r.push(`${He2} is quite skilled in giving mammary massages and handjobs, too.`);
			if (V.milkmaidImpregnates === 1 && canPenetrate(S.Milkmaid) && S.Milkmaid.pubertyXY === 1 && S.Milkmaid.ballType === "human") {
				r.push(`If at all possible, it is ${his2} duty to thoroughly knock up ${his2} charges.`);
			}
			App.Events.addParagraph(node, r);
			r = [];
		}
		if (V.dairyStimulatorsSetting > 0) {
			r.push(`Automated sodomizers help the cows produce by penetrating their anuses. The milking chairs built-in sensors measure ${slave.slaveName}'s anal capacity.`);

			if (slave.anus === 0 ) {
				r.push(`The machine detects an unused rear-end. In order to protect ${his} anal virginity, the automatic sodomizer stays inactive.`);
			} else {
				r.push(`In order to provide adequate stimulation for ${his}`);
				if (slave.anus > 3) {
					r.push(`gaping anus, the automatic sodomizer is equipped with a gigantic horse-like phallus. It wobbles menacingly.`);
				} else if (slave.anus > 2) {
					r.push(`well-used rear-end, the automatic sodomizer is equipped with a large phallus. It is nicely ribbed for extra stimulation.`);
				} else {
					r.push(`anus, the automatic sodomizer is equipped with a fair-sized silicone phallus.`);
				}
				r.push(`Lubrication spurts from a hole at the tip, giving the artificial phallus a very lifelike pre-dripping look. Gently, the mechanical arm pushes the phallus into ${slave.slaveName}'s behind.`);

				if (slave.fetish === "buttslut" || slave.sexualFlaw === "anal addict") {
					r.push(`${He} shudders with joy.`);
				}
				r.push(`Soon, the automatic sodomizer pumps the dildo in and out of ${his} butt-hole.`);
				if (slave.balls > 0 && slave.scrotum > 0) {
					r.push(`${His}`);
					if (slave.balls > 5 ) {
						r.push(`massive`);
					}
					r.push(`balls swing back and forth.`);
				}
				if (slave.dick > 0 ) {
					if (slave.prostate !== 0) {
						r.push(`The dildo stimulates ${his} prostate perfectly. Pre-cum begins to leak from ${his} cock.`);
					}
					/* TODO: the next lines feel non-canon */
					r.push(`The milking machine remains at this setting for longer than normal. Pre-cum is considered a delicacy and is harvested as much as possible before having a negative impact on cum production.`);
				}
			}
			App.Events.addParagraph(node, r);
			r = [];
		}
		if (V.dairyPregSetting > 0) {
			r.push(`Ejaculate squirting dildos keep the slave's wombs stuffed with seed until they are confirmed pregnant and aid in preparing them for childbirth.`);
			if (isFertile(slave)) {
				r.push(`Since ${he} is quite fertile, it springs to life.`);
				if (slave.vagina === 0) {
					r.push(`The machine detects a virgin pussy. In order to protect ${his} virginity, the automatic dildo returns to its housing.`);
				} else {
					r.push(`In order to provide adequate stimulation for ${his}`);
					if (slave.vagina > 3) {
						r.push(`gaping vagina, the automatic dildo is equipped with a gigantic horse-like phallus. It wobbles menacingly.`);
					} else if (slave.vagina > 2) {
						r.push(`well-used rear-end, the automatic dildo is equipped with a large phallus. It is nicely ribbed for extra stimulation.`);
					} else {
						r.push(`vagina, the automatic dildo is equipped with a fair-sized silicone phallus.`);
					}
					r.push(`Lubrication spurts from a hole at the tip, giving the artificial phallus a very lifelike pre-dripping look. Gently, the mechanical arm pushes the phallus into ${slave.slaveName}'s pussy.`);

					if (slave.fetish === "pregnancy" || slave.sexualFlaw === "breeder") {
						r.push(`${He} shudders with joy.`);
					}
					r.push(`Soon, the automatic impregnator pumps the dildo in and out of ${his} body, frequently releasing large loads of potent cum directly into ${his} womb.`);
				}
			}
		}
	}
	/* GETTING IN END */
	App.Events.addParagraph(node, r);
	r = [];

	/* MILKING ROUTINE */
	if (slave.lactation > 0) {
		r.push(`The milking cups`);
		if (slave.nipples === "fuckable" || slave.nipples === "flat") {
			r.push(`over`);
		} else {
			r.push(`on`);
		}
		r.push(`${his} nipples begin to pulse rhythmically. Soon, a steady flow of breast-milk is sucked away into the storage tanks.`);
	}
	if (slave.dick > 0) {
		r.push(`The milking machine uses suction to draw ${his} dick into the receptacle.`);
		if (slave.dick > 10) {
			r.push(`${His} dick is too large to even consider getting hard again, so it just attaches firmly to the tip.`);
		} else if (slave.dick > 8) {
			r.push(`${He} is on the verge of passing out as most of ${his} blood volume rushes into ${his} dick. ${He} cannot possibly reach a full erection without the machine's help. ${He} fights to stay awake so ${he} can enjoy ${his} inhuman cock at throbbing hardness.`);
		} else if (slave.dick > 6) {
			r.push(`${He} feels dizzy as most of ${his} blood volume rushes into ${his} dick. It is not easy for ${his} body to maintain an erection. But with the machine's help, ${he} can produce a full throbbing hard-on.`);
		} else {
			r.push(`It brings ${him} to a full, throbbing erection within seconds.`);
		}
		r.push(`The machine strokes ${his} dick mechanically, but very pleasurably.`);
	}
	r.push(`It does not take long for ${slave.slaveName} to reach ${his} first orgasm of many. ${His} muscles tense.`);
	if (slave.dick > 0) {
		r.push(`${His}`);
		if (slave.balls > 5 ) {
			r.push(`cum-engorged`);
		}
		r.push(`balls draw up.`);
		r.push(`${His}`);
		if (slave.dick > 8 ) {
			r.push(`gargantuan member`);
		} else if (slave.dick > 6 ) {
			r.push(`huge cock`);
		} else {
			r.push(`dick`);
		}
		r.push(`twitches and flexes within its receptacle.`);
		if (slave.balls >= 50) {
			r.push(`A special tank beneath ${him} holds ${his} monolithic balls' endless ejaculate while the machine struggles to suck it away.`);
		} else if (slave.balls >= 37) {
			r.push(`A special tank attached to the hose holds ${his} titanic balls' near endless ejaculate while the machine struggles to suck it away.`);
		} else if (slave.balls >= 25) {
			r.push(`A special reservoir attached to the hose holds ${his} massive balls' ridiculous ejaculate while the machine struggles to suck it away.`);
		} else if (slave.balls >= 10) {
			r.push(`The machine strains to suck down the giant load from ${his} huge balls.`);
		} else if (slave.balls > 5) {
			r.push(`The copious ejaculation from ${his} over-sized balls give the machine something to work on.`);
		} else if (slave.balls > 0) {
			r.push(`${His} ejaculate is quickly sucked away.`);
		} else {
			r.push(`${His} ballslessness impedes cum-production, but ejaculating feels nice, anyway.`);
		}
	}
	if (slave.dick < 1 && slave.balls > 0 && slave.prostate > 0) {
		r.push(`Cum splashes from ${his} urethra and is quickly sucked away.`);
	}
	if (slave.lactation > 0) {
		App.Events.addParagraph(node, r);
		r = [];
		r.push(`The milking cups`);
		if (slave.nipples === "fuckable" || slave.nipples === "flat") {
			r.push(`over`);
		} else {
			r.push(`on`);
		}
		r.push(`${his} nipples switch from rhythmic pulsing into intense suction. Aided by ${his} orgasm, milk spurts from ${his} nipples`);
		if (slave.boobs > 20000) {
			r.push(`in obscenely massive amounts. ${His} immense breasts seem to never empty.`);
		} else if (slave.boobs > 10000) {
			r.push(`in absurdly large amounts. ${His} gargantuan breasts do not seem to get less milk-laden for a long time.`);
		} else if (slave.boobs > 5000) {
			r.push(`in powerful jets. ${His} huge breasts can provide multiple liters of milk.`);
		} else if (slave.boobs > 1000) {
			r.push(`for quite some time. ${His} large breasts can store an impressive volume of milk.`);
		} else if (slave.boobs > 700) {
			r.push(`until there is enough for whitening a cup of coffee. ${His} average breasts cannot store much more milk.`);
		} else if (V.arcologies[0].FSSlimnessEnthusiast > 80) {
			r.push(`for a surprisingly long time. Your arcology succeeded in optimized the milking process for small breasts.`);
		} else {
			r.push(`for a short time. ${His} small tits cannot dispense much milk at once.`);
		}
	}
	App.Events.addParagraph(node, r);
	r = [];
	if (slave.prostate !== 0 && slave.dick === 0 && slave.balls === 0) {
		r.push(`${slave.slaveName}`);
		r.push(`has no cock, but a functional prostate gland. It's attached to ${his} urethra, so ${he} squirts`);
		if (slave.prostate > 2) {
			r.push(`massively`);
		} else {
			r.push(`copiously`);
		}
		r.push(`while ${he} orgasms. The exotic fluid is caught by a basin positioned under ${his}`);
		if (slave.vagina >= 0 ) {
			r.push(`dripping pussy.`);
		} else {
			r.push(`featureless crotch.`);
		}
	}
	App.Events.addParagraph(node, r);
	r = [];
	r.push(`With the first milking cycle being over, ${slave.slaveName} drifts into a relaxing slumber.`);
	if (V.dairyFeedersSetting === 1 && (slave.sexualFlaw === "cum addict" || slave.fetish === "cumslut")) {
		r.push(`${He} grins madly around the phallus ${he} stuffed in ${his} mouth.`);
	}
	if (V.dairyPregSetting > 0 && isFertile(slave) && slave.vagina > 0) {
		r.push(`${He} gets comfortable around ${his} cum-bloated belly as the impregnator continues its task.`);
	}
	if (slave.lactation > 0) {
		r.push(`The milking cups`);
		if (slave.nipples === "fuckable" || slave.nipples === "flat") {
			r.push(`over`);
		} else {
			r.push(`on`);
		}
		r.push(`${his} nipples pulse slower and with less vigor. The lactation never fully subsides. The steady but gentle suction helps increasing milk production without actually draining the breasts.`);
		slave.lactationDuration = 2;
		slave.boobs -= slave.boobsMilk;
		slave.boobsMilk = 0;
	}
	if (slave.dick > 0) {
		r.push(`The suction on ${his} dick stops, allowing ${his} abused member to go soft and have some rest.`);
	}
	if (slave.balls > 0 && slave.scrotum > 0) {
		r.push(`${His} balls rest, dangling down and relieved. They have already started to produce more cum. They seem to wait for their next chance to unload.`);
	}
	App.Events.addParagraph(node, r);
	App.Events.addParagraph(node, [`The next milking cycle will start soon.`]);
	/* MILKING ROUTINE END */
	return node;
};


code:
App.Facilities.Dairy.industrialAssignmentScene = function(slave) {
	const node = new DocumentFragment();

	V.nextButton = "Continue";
	V.nextLink = V.returnTo;
	let r = [];
	const {
		He, His,
		he, him, his, himself
	} = getPronouns(slave);
	const {
		say:say, title: Master
	} = getEnunciation(slave);

	App.Events.drawEventArt(node, slave);

	r.push(`When ${slave.slaveName} reports to the dairy, it's to the`);
	if (canSee(slave)) {
		r.push(`sight of an unoccupied milking machine waiting for ${him},`);
	} else {
		r.push(`cold embrace of an unoccupied milking machine,`);
	}
	r.push(`its straps ready to immure ${him} in what is to be ${his} new home.`);

	if (slave.sexualFlaw === "self hating") { /* GETTING IN */
		r.push(`As ${he} realizes ${his} fate, a kind of peace comes over the self hating slut.`);
		if (!canTalk(slave)) {
			r.push(`${He}`);
			if (!hasAnyArms(slave)) {
				r.push(`mouths`);
			} else {
				r.push(`gestures`);
			}
			r.push(`${his} thanks dreamily.`);
		} else {
			r.push(
				Spoken(slave, `"Thank you, ${Master},"`),
				`${he} ${say}s simply.`,
				Spoken(slave, `"I deserve this,"`),
				`${he} adds quietly, half to ${himself}.`
			);
		}
		r.push(`Then ${he} falls silent and`);
		if (canSee(slave)) {
			r.push(`stares at`);
		} else {
			r.push(`faces`);
		}
		r.push(`the machine. Though ${he} hates ${himself} and looks forward to the release of being unable to do anything but get fucked, that doesn't mean ${he} isn't afraid.`);
		if (hasAnyArms(slave)) {
			if (V.dairyStimulatorsSetting > 1) {
				r.push(`${He} gauges the size of the sodomizer with ${his} hand, finding that it's wider than ${his} fist, and then presses the fist against ${his} own anus. Realizing what's about to happen, ${he} gives a little shudder.`);
				if (V.dairyPregSetting > 1 && isFertile(slave) && slave.mpreg !== 1) {
					r.push(`${He} does the same with the dildo that will keep ${him} pregnant and ${his} pussy, and ${his} lower lip starts to quiver.`);
				}
			} else {
				if (V.dairyPregSetting > 1 && isFertile(slave) && slave.mpreg !== 1) {
					r.push(`${He} gauges the size of the dildo that will keep ${him} pregnant with ${his} hand, finding that it's wider than ${his} fist, and then presses the fist against ${his} pussy. Realizing what's about to happen, ${he} gives a little shudder.`);
				}
			}
			if (V.dairyFeedersSetting > 1) {
				if (canSee(slave)) {
					r.push(`Looking at`);
				} else {
					r.push(`As ${he} wraps ${his} lips around`);
				}
				r.push(`the phallus that will feed ${him}, ${he} begins to cry softly.`);
			}
		}
		App.Events.addParagraph(node, r);
		r = [];
		if (hasAnyArms(slave)) {
			r.push(`${He} strips and climbs into the machine's embrace,`);
		} else {
			r.push(`Another slave helps ${him} strip and lays ${him} in the machine,`);
		}
		r.push(`${his} tears pattering onto the uncaring metal. When ${he}'s in place, ${his} shoulders slump as ${he} gives up completely.`);
		if (!canTalk(slave)) {
			r.push(`${He} mouths 'Goodbye.'`);
		} else if (SlaveStatsChecker.checkForLisp(slave)) {
			r.push(
				Spoken(slave, `"'Bye,"`),
				`${he} lisps.`
			);
		} else {
			r.push(
				Spoken(slave, `"'Bye,"`),
				`${he} whispers.`
			);
		}
	} else if ((slave.sexualFlaw === "breeder") && isFertile(slave) && slave.mpreg !== 1) {
		r.push(`As ${he} realizes what's about to happen, ${he} begins to cry openly. A curious mix of arousal, joy, and abject horror is obvious on ${his} face, and ${he} deals with the conflicting feelings by sobbing.`);
		if (!canTalk(slave)) {
			r.push(`${He}`);
			if (!hasAnyArms(slave)) {
				r.push(`mouths`);
			} else {
				r.push(`gestures`);
			}
			r.push(`${his} thanks shakily.`);
		} else {
			r.push(
				Spoken(slave, `"Th-thank you, ${Master},"`),
				`${he} ${say}s through ${his} tears.`,
				Spoken(slave, `"I love you."`)
			);
		}
		r.push(`Then ${he} falls silent and`);
		if (canSee(slave)) {
			r.push(`stares at`);
		} else if (hasAnyArms(slave)) {
			r.push(`reaches out to touch`);
		} else {
			r.push(`faces`);
		}
		r.push(`the machine. ${He}'s probably imagined this a thousand times, but the prospect is still frightening.`);
		if (hasAnyArms(slave)) {
			if (V.dairyStimulatorsSetting > 1) {
				r.push(`${He} gauges the size of the sodomizer with ${his} hand, finding that it's wider than ${his} fist, and then presses the fist against ${his} own anus. Realizing that ${his} anus is about to be permanently gaped, ${he} looks doubtful, but then visibly reassures ${himself}. ${He}'ll need both ${his} mouth and ${his} ass to eat enough.`);
			}
			if (V.dairyFeedersSetting > 1) {
				if (canSee(slave)) {
					r.push(`Looking at`);
				} else {
					r.push(`Turning to`);
				}
				r.push(`the phallus that will feed ${him}, ${he} inserts a finger into its faux urethra, measuring how fast it can pour nutrition in ${him}.`);
			}
			r.push(`${He} strokes the dildo that will keep ${him} pregnant like a lover, which, of course, it's about to be.`);
		}
		App.Events.addParagraph(node, r);
		r = [];
		if (hasAnyArms(slave)) {
			r.push(`${He} strips and climbs into the machine's embrace, shaking with nerves.`);
		} else {
			r.push(`Another slave helps ${him} strip and lays ${him} in the machine. ${He} shakes with nerves.`);
		}
		if (slave.pregKnown === 1) {
			r.push(`${He}`);
			if (canSee(slave)) {
				r.push(`cranes around to look at`);
			} else {
				r.push(`runs a hand down`);
			}
			r.push(`${his} already-pregnant belly, and looks impatient.`);
			if (canTalk(slave)) {
				r.push(
					Spoken(slave, `"Hurry up, I need the room,"`),
					`${he} whispers.`
				);
			} else {
				r.push(`${He} mouths 'hurry up, I need room.'`);
			}
		} else {
			r.push(`${He}`);
			if (canSee(slave)) {
				r.push(`cranes around to look at`);
			} else {
				r.push(`runs a hand down`);
			}
			r.push(`${his} belly, and looks impatient.`);
			if (!canTalk(slave)) {
				r.push(`${He} mouths 'come on, I'm ready.'`);
			} else {
				r.push(
					Spoken(slave, `"Come on, I'm ready,"`),
					`${he} whispers.`
				);
			}
		}
	} else if (slave.devotion > 95) { /* GETTING IN */
		r.push(`As ${he} realizes ${his} fate, the worshipful slave squares ${his} shoulders, steeling ${himself}.`);
		if (canTalk(slave)) {
			r.push(
				Spoken(slave, `"${Master},"`),
				`${he} ${say}s,`,
				Spoken(slave, `"I will do my best to serve you."`)
			);
		} else {
			r.push(`${He} gestures that ${he}'ll do ${his} best for you.`);
		}
		if (canWalk(slave)) {
			r.push(`${He} steps over to the machine.`);
		}
		if (canSee(slave)) {
			r.push(`${He} looks it over clinically,`);
		} else if (hasAnyArms(slave)) {
			r.push(`${He} runs a hand over it exploratively,`);
		} else {
			r.push(`${He} takes a deep breath,`);
		}
		r.push(`getting ${himself} into the right mindset.`);
		if (hasAnyArms(slave)) {
			if (V.dairyStimulatorsSetting > 1) {
				r.push(`${He} gauges the size of the massive phallus that will soon penetrate ${his} anus. It's broader than ${his} fist.`);
				if (canTalk(slave)) {
					r.push(Spoken(slave, `"I think I can take this. It'll be tough, but I'll need all the hydration I can get."`));
				} else {
					r.push(`${He} nods ${his} head, understanding that it will need to fit to keep ${him} hydrated.`);
				}
			}
			if (V.dairyPregSetting > 1 && isFertile(slave) && slave.mpreg !== 1) {
				r.push(`${He} considers the enormous dildo that will fill ${him} with cum when ${he}'s fertile, and switch to ejaculating drugs when ${he} conceives.`);
				if (canTalk(slave)) {
					r.push(
						Spoken(slave, `"I'll be a mother to a whole generation of slaves,"`),
						`${he} ${say}s proudly, taking strength from it.`
					);
				} else {
					r.push(`${He} takes strength in knowing that ${he}'ll birth a whole generation of new slaves.`);
				}
			}
			if (V.dairyFeedersSetting > 1) {
				r.push(`${He} moves ${his} hand to the dildo that will occupy ${his} throat, feeding ${him}.`);
				if (canTalk(slave)) {
					r.push(
						Spoken(slave, `"I will need my mouth to take in as much food as I can,"`),
						`${he} ${say}s.`,
						Spoken(slave, `"I won't be able to talk. So, I'll say it one last time, ${Master}: I love you."`)
					);
				} else {
					r.push(`${He} focuses on just how much time ${he}'ll need to spend with ${his} mouth full, so ${he} blows you one final kiss to show ${his} love.`);
				}
			}
		}
		App.Events.addParagraph(node, r);
		r = [];
		if (hasAnyArms(slave)) {
			r.push(`${He} strips and climbs into the machine's embrace.`);
		} else {
			r.push(`Another slave helps ${him} strip and lays ${him} in the machine.`);
		}
		r.push(`${He} does not hesitate or`);
		if (canSee(slave)) {
			r.push(`glance back at`);
		} else {
			r.push(`show any resistance to`);
		}
		r.push(`you. You stand by as the straps automatically tighten, robbing ${him} of the ability to move.`);
		if (canTalk(slave)) {
			r.push(
				Spoken(slave, `"${Master},"`),
				`${he} ${say}s quietly,`,
				Spoken(slave, `"I will try to be strong enough to stand up to this. But if I'm not, and I forget too much, please leave me in here so I can be useful."`)
			);
		} else {
			r.push(`${He} swears to you that ${he} will try ${his} best, but implores you to leave ${him} to the machine should ${his} mind fade.`);
		}
	} else if (slave.devotion > 60) {
		r.push(`As ${he} realizes ${his} fate, the tears come quickly.`);
		if (canTalk(slave)) {
			r.push(
				Spoken(slave, `"${Master},"`),
				`${he} ${say}s quietly, "is this for me?"`
			);
		} else {
			r.push(`${He} shakily gestures if this is where ${he} will be staying.`);
		}
		if (canSee(slave)) {
			r.push(`You nod, and ${he}`);
			if (canWalk(slave)) {
				r.push(`steps over to the machine.`);
			} else {
				r.push(`accepts ${his} fate.`);
			}
		} else if (canHear(slave)) {
			r.push(`You tell ${him} it is as ${he}`);
			if (canWalk(slave)) {
				r.push(`steps over to the machine.`);
			} else {
				r.push(`accepts ${his} fate.`);
			}
		} else {
			r.push(`place a hand on ${his} shoulder in confirmation and guide ${him} to the machine.`);
		}
		if (hasAnyArms(slave)) {
			r.push(`${He} lightly traces its gleaming metal, looking wistful.`);
			if (V.dairyStimulatorsSetting > 1) {
				r.push(`${He} gently touches the head of the massive phallus that will soon penetrate ${his} anus. It's broader than ${his} fist.`);
				if (canTalk(slave)) {
					r.push(Spoken(slave, `"M-my butthole isn't going to be any good for anal after this."`));
				} else {
					r.push(`${He} gestures jokingly that nothing will fit ${his} rear hole after this.`);
				}
			}
			if (V.dairyPregSetting > 1 && isFertile(slave) && slave.mpreg !== 1) {
				r.push(`${He} considers the enormous dildo that will fill ${him} with cum when ${he}'s fertile, and switch to ejaculating drugs when ${he} conceives.`);
				if (canTalk(slave)) {
					r.push(Spoken(slave, `"I guess that thing won't have any trouble reaching my cervix."`));
				} else {
					r.push(`${He} knows it won't have any trouble getting ${him} pregnant.`);
				}
			}
			if (V.dairyFeedersSetting > 1) {
				r.push(`${He} moves ${his} hand to the dildo that will occupy ${his} throat, feeding ${him}.`);
				if (canTalk(slave)) {
					r.push(
						Spoken(slave, `"I-I won't be able to t-talk m-much,"`),
						`${he} ${say}s sadly.`,
						Spoken(slave, `"S-so, I'll say it one last time, ${Master}: I love you."`)
					);
				} else {
					r.push(`${He} knows ${he} won't have another chance at this, so ${he} gives you one last tearful 'I love you'.`);
				}
			}
		}
		App.Events.addParagraph(node, r);
		r = [];
		if (hasAnyArms(slave)) {
			r.push(`${He}`);
			if (slave.clothes !== "no clothing") {
				r.push(`strips and`);
			}
			r.push(`climbs into the machine's embrace.`);
		} else {
			r.push(`Another slave helps ${him}`);
			if (slave.clothes !== "no clothing") {
				r.push(`strip and lays ${him} in`);
			} else {
				r.push(`into`);
			}
			r.push(`the machine.`);
		}
		if (canTalk(slave)) {
			r.push(
				Spoken(slave, `"${Master},"`),
				`${he} gasps out, the tears coming fast now.`,
				Spoken(slave, `"C-can you`)
			);
			if (hasAnyArms(slave)) {
				r.push(
					Spoken(slave, `h-hold my h-hand while it a-activates? Please?"`),
					`You take ${his} hand as the straps automatically tighten, robbing ${him} of the ability to move. ${He} grips your hand tightly.`
				);
			} else {
				r.push(
					Spoken(slave, `S-stay with me while it activates? Please?"`),
					`You stand by as the straps automatically tighten, robbing ${him} of the ability to move.`
				);
			}
		} else {
			r.push(`You can tell by the tears streaming down ${his} face that ${he} doesn't want to leave you so soon.`);
			if (hasAnyArms(slave)) {
				r.push(`You take ${his} hand as the straps automatically tighten, robbing ${him} of the ability to move. ${He} grips your hand tightly.`);
			} else {
				r.push(`You stand by as the straps automatically tighten, robbing ${him} of the ability to move.`);
			}
		}
	} else if (slave.devotion > 20) {
		r.push(`${He} desperately tries to be brave and obey, but as ${his} fate dawns on ${him}, ${his} courage and conditioning fail ${him}.`);
		if (!hasAnyLegs(slave)) {
			r.push(`${He} tries to wriggle away from the machine, so`);
		} else {
			r.push(`${He} turns and tries to run, so`);
		}
		if (V.MilkmaidID !== 0) {
			r.push(`${S.Milkmaid.slaveName} is`);
		} else {
			r.push(`you are`);
		}
		r.push(`obliged to`);
		if (!isAmputee(slave)) {
			r.push(`subdue ${him} and strap ${him},`);
		} else {
			r.push(`place ${him},`);
		}
		r.push(`begging and sobbing, into the machine's embrace.`);
		if (canTalk(slave)) {
			r.push(
				Spoken(slave, `"Please, ${Master}!"`),
				`${he} begs.`,
				Spoken(slave, `"Please no!`)
			);
			if (V.dairyStimulatorsSetting > 1) {
				r.push(Spoken(slave, `I-it'll fuck my b-butthole so wide I'll be useless for anal!`));
			}
			if (V.dairyPregSetting > 2 && isFertile(slave) && slave.mpreg !== 1) {
				r.push(Spoken(slave, `My w-womb c-c-can't take it! I'll b-burst! And m-my c-c-cunt will be ruined from the dildo and birthing!`));
			} else if ((V.dairyPregSetting > 1) && isFertile(slave) && slave.mpreg !== 1) {
				r.push(Spoken(slave, `M-my c-c-cunt will be s-so stretched from the dildo and birthing!`));
			}
			r.push(Spoken(slave, `I'll d-do anything!"`));
		} else {
			r.push(`${He} pitifully begs for anything but this, even going as far as trying to convey what the machine will do to ${him}, but it will do ${him} no good.`);
		}
	} else {
		r.push(`${He} starts to weep as soon as ${he} realizes ${his} fate.`);
		if (slave.trust >= -20) {
			r.push(`${He} is afraid of you, but not afraid enough that ${he} will not resist this.`);
		}
		if (hasAnyLegs(slave)) {
			r.push(`${He} tries to wriggle away from the machine, so`);
		} else {
			r.push(`${He} turns and tries to run, so`);
		}
		if (V.MilkmaidID !== 0) {
			r.push(`${S.Milkmaid.slaveName} is`);
		} else {
			r.push(`you are`);
		}
		r.push(`obliged to`);
		if (!isAmputee(slave)) {
			r.push(`subdue ${him} and strap ${him},`);
		} else {
			r.push(`place ${him},`);
		}
		r.push(`begging and sobbing, into the machine's embrace.`);

		if (canTalk(slave)) {
			r.push(
				Spoken(slave, `"Please, ${Master}!"`),
				`${he} begs.`,
				Spoken(slave, `"Please no!`)
			);
			if (V.dairyStimulatorsSetting > 1) {
				r.push(Spoken(slave, `I-it'll fuck my b-butthole so loose I'll be useless for anal! I p-promise I'll be a good little bitch from now on!`));
			}
			if (V.dairyPregSetting > 2 && isFertile(slave) && slave.mpreg !== 1) {
				r.push(Spoken(slave, `My w-womb c-c-can't take that many babies>>! I'll b-burst! M-my c-c-cunt can't t-take that dildo either! I d-don't want to g-get p-pregnant over and over...`));
			} else if ((V.dairyPregSetting > 1) && isFertile(slave) && slave.mpreg !== 1) {
				r.push(Spoken(slave, `M-my c-c-cunt can't t-take that dildo! I d-don't want to g-get p-pregnant over and over...`));
			}
			r.push(Spoken(slave, `I'll d-do anything!"`));
		} else {
			r.push(`${He} pitifully begs for to have mercy on ${him} and not subject ${him} to the machines 'features', but it will do ${him} no good.`);
		}
	}

	if (slave.lactation > 0) {
		r.push(`A big soft cup attaches itself`);
		if (slave.nipples === "fuckable" || slave.nipples === "flat") {
			r.push(`over`);
		} else {
			r.push(`to`);
		}
		r.push(`each of ${his} nipples.`);
		if (slave.nipples === "inverted") {
			r.push(`${He} gasps with pain as suction unceremoniously hauls ${his} inverted nipples down into the cups.`);
		} else if (slave.nipples === "fuckable") {
			r.push(`${He} gasps with surprise as a phallic rods unceremoniously slip into ${his} nipples to better harvest ${his} milk.`);
		}
	}
	if (slave.balls > 0) {
		if (slave.dick > 0) {
			r.push(`The first drugs hiss into ${him},`);
			if (slave.dick > 8) {
				r.push(`and ${his} eyes roll back as much of ${his} blood volume rushes into ${his} dick, though it remains soft.`);
			} else if (slave.dick > 6) {
				r.push(`and ${he} goes limp as much of ${his} blood volume rushes to bring ${him} to half mast.`);
			} else {
				r.push(`bringing ${him} to a full erection.`);
			}
			r.push(`${He} gasps as the warm, wet receptacle surrounds ${his} cock.`);
		} else {
			if (slave.lactation > 0) {
				r.push(`Another`);
			} else {
				r.push(`A big soft`);
			}
			r.push(`cup is placed against ${his} little front cumhole.`);
		}
	}
	r.push(`A visor lowers onto ${his} face to keep ${his} mind at least minimally stimulated.`);
	if (canHear(slave) && !canSee(slave)) {
		r.push(`It will play audio from`);
	} else {
		r.push(`It will display garish`);
	}
	r.push(`hardcore pornography featuring`);
	if (V.dairyFeedersSetting > 1) {
		r.push(`throatfucking, cum swallowing,`);
	}
	if (V.dairyPregSetting > 1 && isFertile(slave) && slave.mpreg !== 1) {
		r.push(`bareback vaginal sex, pregnancy, childbirth,`);
	}
	if (slave.balls > 0) {
		r.push(`cumming cocks, anal stimulation,`);
	}
	if (slave.lactation > 0) {
		r.push(`breast expansion, women being milked,`);
	}
	r.push(`and brutal sodomy.`);
	if (!canHear(slave) && !canSee(slave)) {
		r.push(`Of course, ${he} won't enjoy any of that and will be left entirely at the mercy of the sensations running through ${his} flesh.`);
	}
	App.Events.addParagraph(node, r);
	r = [];

	if (slave.anus < 3 || (slave.vagina < 3 && slave.vagina > -1)) {
		slave.anus = 3;
		if (slave.vagina > -1) {
			slave.vagina = 3;
		}
		r.push(`The machine detects that ${he} requires the attention of the preparatory raper before it can penetrate ${him} successfully, and holds ${him} in place while the raper slides along its track in the ceiling. It comes to rest above the slave's defenseless body and extends its implements towards ${him}. ${He} can't see or hear it, but ${he} senses that something's happening and shivers.`);
		if (V.dairyPregSetting > 1 && V.dairyPregSetting > 1 && isFertile(slave) && slave.vagina < 3 && slave.mpreg !== 1) { // TODO: Correct one of the identical sub-expressions on both sides of operator "&&"
			r.push(`${His} pussy is nowhere near ready to accept the passage of drugs and cum in and new slaves out. The new machine lubes ${him} thoroughly and then`);
			if (slave.vagina === 0) {
				r.push(`takes ${his} virginity`);
			} else {
				r.push(`starts to fuck ${him}`);
			}
			r.push(`with a reasonably sized dildo.`);
		}
		if (V.dairyStimulatorsSetting > 1 && slave.anus < 3) {
			r.push(`${He}'ll be drinking through ${his} mouth almost constantly, but that won't be enough. ${He}'ll have to absorb hydration and nutrition from both ends to keep up with the outflow ${he}'ll produce.`);
			if (V.dairyPregSetting > 1 && V.dairyPregSetting > 1 && isFertile(slave) && slave.vagina < 3 && slave.mpreg !== 1) { // TODO: Correct one of the identical sub-expressions on both sides of operator "&&"
				r.push(`It`);
			} else {
				r.push(`The new machine`);
			}
			r.push(`fills ${his} ass with lube and then penetrates ${his}`);
			if (slave.anus === 0) {
				r.push(`virgin anus`);
			} else {
				r.push(`rectum`);
			}
			r.push(`gently.`);
		}
		r.push(`${He}'s worked in gradually, but every time ${he}'s loosened just slightly, the now-inadequate dildo is replaced by a larger one, and eventually more than one.`);
		if (V.dairyPregSetting > 1 && isFertile(slave) && slave.vagina < 3 && slave.mpreg !== 1) {
			if (V.dairyStimulatorsSetting > 1 && slave.anus < 3) {
				r.push(`${He} goes from a dildo in the pussy and a dildo in the ass, through numerous interesting combinations of double penetration, until ${he}'s got two porn star sized dildos sliding in and out of ${his} pussy and two more fucking ${his} ass.`);
			} else {
				r.push(`${His} womanhood goes from a normal dildo to a big dildo to two dildos, and so on, until ${he}'s taking the equivalent of two porn star cocks.`);
			}
		} else {
			r.push(`${His} asshole goes from a normal dildo to a big dildo to two dildos, and so on, until ${he}'s taking the equivalent of two porn star cocks up the butt.`);
		}
		r.push(`This is a long process, and though`);
		if (slave.devotion > 95) {
			r.push(`${he} started out getting off on it,`);
		} else if (slave.devotion > 60) {
			r.push(`${he} did ${his} best to enjoy ${himself} for a while,`);
		} else if (slave.devotion > 20) {
			r.push(`${he} tried to relax and make it easier on ${himself} at the start,`);
		} else {
			r.push(`${he} cried and tried to break loose for a while,`);
		}
		r.push(`${he}'s slumped against the machine from sheer exhaustion by the end. Its work completed, the preparatory raper withdraws and lets the milking machine begin its work. It's only been a few hours since ${slave.slaveName}'s ordeal began, but now ${he}'s ready to begin giving back. The machine revives ${him} with a hit of pharmaceuticals.`);

		App.Events.addParagraph(node, r);
		r = [];
	}

	if (V.dairyPregSetting > 1 && isFertile(slave) && slave.mpreg !== 1) {
		r.push(`${His} vagina goes first. ${He} relaxes ${his} loose cunt for the elephantine dildo, but despite ${his} best efforts, it forces a gasp out of ${him} as it slides in. It remains stationary for now, but ${slave.slaveName} know it's just the beginning, and ${he} already feels full to bursting.`);
		if (slave.devotion > 95) {
			r.push(`${He} takes more deep breaths, doing ${his} best to remain calm.`);
		} else if (slave.devotion > 60) {
			r.push(`Terrified, ${he} cries harder.`);
		} else if (slave.devotion > 20) {
			r.push(`Terrified, ${he} cries harder.`);
		} else {
			r.push(`Terrified, ${he} starts to`);
			if (!canTalk(slave)) {
				r.push(`soundlessly`);
			}
			r.push(`scream and cry.`);
		}
	} else if (V.dairyPregSetting > 0 && isFertile(slave) && slave.mpreg !== 1) {
		if (slave.devotion > 95) {
			r.push(`${He} moans with pleasure`);
		} else if (slave.devotion > 60) {
			r.push(`${He} gasps`);
		} else if (slave.devotion > 20) {
			r.push(`${He} moans with fear`);
		} else {
			r.push(`${He} moans with anguish`);
		}
		r.push(`as the machine inserts a warm, lubricated dildo into ${his} vagina.`);
	}
	if (V.dairyStimulatorsSetting > 1) {
		r.push(`${His} anus is next. An auxiliary dildo the size of the largest human cocks goes first, assraping ${him} so hard ${he}'d probably be injured if ${he} wasn't already very loose.`);
		if (slave.devotion > 95) {
			r.push(`${He} relaxes and does ${his} best to enjoy ${himself}, ${his} cheeks flushing with arousal. Once ${his} sphincter is well stretched, the machine withdraws the dildo, and before ${his} anus can begin to close, the machine replaces it with the main instrument. Despite the preparation, it's so huge that ${he} moans with fear ${he} feels the head touch ${his} buttocks. The moan becomes a long low groan as ${his} butthole accommodates the enormous thing. When it's all the way in, the dildo begins to withdraw for its first stroke, and ${he}`);
			if (canTalk(slave)) {
				r.push(`whispers, "${Master}, it's s-so b-big." ${He} relaxes and recollects ${himself}, and then adds, "I can do this."`);
			} else {
				r.push(`begins distressing over its size before relaxing and recollecting ${himself}. ${He} smiles to show you ${he} can do this.`);
			}
		} else if (slave.devotion > 60) {
			r.push(`${He} tries to`);
			if (slave.skill.anal > 10) {
				r.push(`apply ${his} anal training,`);
			} else {
				r.push(`relax,`);
			}
			r.push(`but it fucks ${his} butt so mercilessly that ${he} eventually gives up and relaxes completely. This is what the machine was aiming for; it withdraws the dildo, and before ${his} sphincter can close, it replaces it with the main instrument. Despite the preparation, it's so huge that ${he} begins to`);
			if (!canTalk(slave)) {
				r.push(`silently`);
			}
			r.push(`scream in terror as ${he} feels the head touch ${his} buttocks. ${His}`);
			if (canTalk(slave)) {
				r.push(`yelling becomes a drawn-out shriek`);
			} else {
				r.push(`pointless yelling turns to struggling`);
			}
			r.push(`as ${his} butthole accommodates the enormous thing. When ${he} finally runs out of breath and slumps within ${his} restraints, the dildo begins to withdraw for its first stroke, and ${he}`);
			if (canTalk(slave)) {
				r.push(`whispers, "${Master}, it's too b-big. It hu-hurts."`);
			} else {
				r.push(`attempts to tell you that it is too big for ${his} hole.`);
			}
		} else if (slave.devotion > 20) {
			r.push(`Crying, ${he} tries to`);
			if (slave.skill.anal > 10) {
				r.push(`apply ${his} anal training,`);
			} else {
				r.push(`relax,`);
			}
			r.push(`but it fucks ${his} butt so mercilessly that ${he} eventually gives up and relaxes completely. This is what the machine was aiming for; it withdraws the dildo, and before ${his} sphincter can close, it replaces it with the main instrument. Despite the preparation, it's so huge that ${he} begins to beg desperately as ${he} feels the head touch ${his} buttocks. ${His}`);
			if (canTalk(slave)) {
				r.push(`whining becomes a drawn-out shriek`);
			} else {
				r.push(`soundless whining turns to struggling`);
			}
			r.push(`as ${his} butthole accommodates the enormous thing. When ${he} finally runs out of breath and slumps within ${his} restraints, the dildo begins to withdraw for its first stroke, and ${he} is racked with sobs.`);
		} else {
			r.push(`${He} obviously thinks this is what ${his} butt will suffer, and doesn't like it. ${He}'s tragically wrong. When ${he} finally relaxes, the machine withdraws the dildo, and before ${his} sphincter can close, it replaces it with the main instrument.`);
			if (canTalk(slave)) {
				r.push(`${He} screams with the horror of realization and begins to beg desperately as ${he} feels its head touch ${his} buttocks. ${His} cries become a drawn-out shriek as ${his} butthole accommodates the enormous thing.`);
			} else {
				r.push(`${He} attempts to fling ${himself} from the machine with the horror of realization begins to flail desperately as ${he} feels its head touch ${his} buttocks. ${His} efforts double as ${his} butthole accommodates the enormous thing.`);
			}
			r.push(`When ${he} finally runs out of breath and slumps within ${his} restraints, the dildo begins to withdraw for its first stroke, and ${he} is racked with weeping.`);
		}
		if (V.dairyPregSetting > 1 && isFertile(slave) && slave.mpreg !== 1) {
			r.push(`The dildo in ${his} vagina begins to fuck ${him} as well. Between ${his} terribly broadened holes, ${his} stretched perineum is barely visible at all.`);
		}
	} else if (V.dairyStimulatorsSetting > 0) {
		if (slave.devotion > 95) {
			r.push(`${He} groans as the machine pushes a big dildo up ${his} butt and begins to sodomize ${him} powerfully.`);
		} else if (slave.devotion > 60) {
			r.push(`${He} sobs as the machine pushes a big dildo up ${his} butt and begins to sodomize ${him} powerfully.`);
		} else if (slave.devotion > 20) {
			r.push(`${He} sobs as the machine pushes a big dildo up ${his} butt and begins to sodomize ${him} powerfully.`);
		} else {
			r.push(`${He} cries as the machine pushes a big dildo up ${his} butt and begins to sodomize ${him} powerfully.`);
		}
	}
	if (V.dairyFeedersSetting > 1) {
		if (slave.devotion > 95) {
			r.push(`A manipulator prods ${his} jaw open and a phallus slides into ${his} throat, working around for a while to find the optimal position for maximum penetration where ${he} can still breathe through ${his} nose. There is a hiss as the food begins rushing through the phallus and down ${his} throat.`);
		} else if (slave.devotion > 60) {
			if (canTalk(slave)) {
				r.push(`${He} tries to say something, but ${he} left it too late.`);
			}
			r.push(`A manipulator forces ${his} jaw open and a phallus slides into ${his} throat, working around for a while to find the optimal position for maximum penetration where ${he} can still breathe through ${his} nose. There is a hiss as the food begins rushing through the phallus and down ${his} throat.`);
		} else if (slave.devotion > 20) {
			r.push(`${His} crying is abruptly cut off as a manipulator forces ${his} jaw open and a phallus slides into ${his} throat, working around for a while to find the optimal position for maximum penetration where ${he} can still breathe through ${his} nose.`);
		} else {
			r.push(`${He} cries hopelessly,`);
			if (canTalk(slave)) {
				r.push(
					Spoken(slave, `"I'm n-never going t-to leave h-here, am I, —"`),
					`${His} noise`
				);
			} else {
				r.push(`until ${his} sobbing`);
			}
			r.push(`is abruptly cut off as a manipulator forces ${his} jaw open and a phallus slides into ${his} throat, working around for a while to find the optimal position for maximum penetration where ${he} can still breathe through ${his} nose.`);
		}
	} else if (V.dairyFeedersSetting > 0) {
		if (slave.devotion > 95) {
			r.push(`The machine gives ${him} a phallus to suck on.`);
		} else if (slave.devotion > 60) {
			if (canTalk(slave)) {
				r.push(`${He} tries to say something, but ${he} left it too late.`);
			}
			r.push(`The machine gives ${him} a phallus to suck on.`);
		} else if (slave.devotion > 20) {
			r.push(`${His} crying is abruptly cut off as the machine gives ${him} a phallus to suck on.`);
		} else {
			r.push(`${He} cries hopelessly,`);
			if (canTalk(slave)) {
				r.push(
					Spoken(slave, `"I'm n-never going t-to leave h-here, am I, —"`),
					`${His} noise`
				);
			} else {
				r.push(`until ${his} sobbing`);
			}
			r.push(`is abruptly cut off as the machine forces a phallus into ${his} mouth.`);
		}
	}

	App.Events.addParagraph(node, r);
	r = [];
	r.push(`With its various applicators inserted and working, the machine begins to ejaculate necessary fluids into ${his} body. You cannot see much direct evidence, but the inrush of fluids is clear from the draining reservoirs scattered around the machine.`);
	if (V.dairyStimulatorsSetting > 1) {
		r.push(`The gargantuan phallus fucking ${his} butthole ejaculates industrial lubricant, hydration, nutrition, and medication, to be absorbed by ${his} lower intestines.`);
	} else if (V.dairyStimulatorsSetting > 0) {
		r.push(`The phallus fucking ${his} ass ejaculates hydration, nutrition, and medication, to be absorbed by ${his} colon.`);
	}
	if (V.dairyPregSetting > 1 && isFertile(slave) && slave.mpreg !== 1) {
		r.push(`The dildo in ${his} vagina ejaculates cum, fertility drugs, and medication designed to cause uncontrollable natural lubrication, so it will not damage ${him} too severely.`);
	} else if (V.dairyPregSetting > 0 && isFertile(slave) && slave.mpreg !== 1) {
		r.push(`The dildo in ${his} vagina ejaculates cum and fertility drugs.`);
	}
	if (V.dairyFeedersSetting > 0) {
		r.push(`There is a hiss as still more fluid containing hydration, nutrition, and medication begins rushing through the phallus in ${his} mouth and down ${his} throat.`);
	}
	r.push(`Finally, multiple drug injectors attach themselves to ${him} and begin to use hypersonic jets to drive pharmaceuticals into ${him} without needles.`);
	if (slave.devotion > 95) {
		r.push(`${His} eyes fly wide as ${he}`);
		if (canHear(slave)) {
			r.push(`hears and`);
		}
		r.push(`feels the number of injections. ${He} knows these drugs are not without side effects, and ${he}'s being injected with a normal day's dose every minute. ${He} musters ${his} resolve and relaxes again, relying on ${his} knowledge that you want ${him} to accept this fate.`);
	} else if (slave.devotion > 60) {
		r.push(`${His} eyes fly wide and ${he} stiffens with fear as ${he}`);
		if (canHear(slave)) {
			r.push(`hears and`);
		}
		r.push(`feels the number of injections. ${He} knows these drugs are not without side effects, and ${he}'s being injected with a normal day's dose every minute. ${He} visibly tries to accept it, knowing that you want ${him} to submit to this fate.`);
	} else if (slave.devotion > 20) {
		r.push(`The tears streaming out of ${his} eyes come faster as ${he}`);
		if (canHear(slave)) {
			r.push(`hears and`);
		}
		r.push(`feels the number of injections. ${He} knows these drugs are not without side effects, and ${he}'s being injected with a normal day's dose every minute.`);
	} else {
		r.push(`${He} begins to struggle desperately as ${he}`);
		if (canHear(slave)) {
			r.push(`hears and`);
		}
		r.push(`feels the number of injections. ${He} knows these drugs are not without side effects, and ${he}'s being injected with a normal day's dose every minute.`);
	}
	App.Events.addParagraph(node, r);
	r = [];
	r.push(`Fluids begin to come out of ${him}. The drugs are strong, and despite everything ${he} experiences an orgasm so powerful that it's clear why the straps that bind ${him} are reinforced.`);
	if (slave.balls > 0) {
		if (slave.dick > 0) {
			r.push(`The anal dildo fucks ${him} even harder,`);
		} else {
			r.push(`If ${he} had a dick, it would be caressed by a nice warm receptacle, but ${he} doesn't. The milker is forced to rape ${his} ass without mercy to force ${him} to cum,`);
		}
		r.push(`and ${he} tries to scream around the dildo in ${his} mouth.`);
		if (slave.scrotum > 0) {
			r.push(`${His} balls tighten as ${he}`);
		} else {
			r.push(`${He}`);
		}
		r.push(`shoots rope after rope of semen into the machine.`);
	}
	if (slave.vagina > -1) {
		r.push(`${He} gives the machine a nice gush of femcum.`);
	}
	if (slave.lactation > 0) {
		r.push(`The cups sucking ${his} nipples work away ceaselessly, ${his} milk whitening the clear piping running into the machine.`);
		slave.lactationDuration = 2;
		slave.boobs -= slave.boobsMilk;
		slave.boobsMilk = 0;
	}
	r.push(`The machine continues fucking ${him} despite ${his} climax.`);
	if (slave.devotion > 95) {
		r.push(`Though it's difficult to tell, it's possible ${he}'s smiling around the dildo in ${his} mouth. ${He} may be such a well-broken sex slave that ${he} can stand up to a life of nothing but drugs, milking, and an endless string of orgasms. To ease ${his} acclimation to ${his} new life, the drug cocktail is adjusted as ${his} orgasm fades,`);
	} else if (slave.devotion > 60) {
		r.push(`Despite ${his} attempt to be brave, tears begin to leak out from behind ${his} visor as ${he} realizes that there will be no respite from the penetration. The drug cocktail is adjusted as ${his} orgasm fades,`);
	} else if (slave.devotion > 20) {
		r.push(`To ease ${his} acclimation to ${his} new life, the drug cocktail is adjusted as ${his} orgasm fades,`);
	} else {
		r.push(`To allow ${him} some rest despite ${his} terror, the drug cocktail is adjusted as ${his} orgasm fades,`);
	}
	r.push(`to put ${him} to sleep. ${He} slumps against the machine as ${he} drops off.`);
	if (hasAnyArms(slave)) {
		r.push(`${His} painfully tight grip on your hand finally loosens.`);
	}
	if (V.dairyStimulatorsSetting > 1) {
		r.push(`${His} anus has not yet stretched to take the necessary full power setting, so ${he} is gently sodomized as ${he} sleeps to get ${his} sphincter used to its permanent occupier.`);
	}
	if (slave.belly < 1500) {
		r.push(`${His} belly has already begun to distend from the mass of fluid ejaculated down ${his} throat and into ${his} stomach,`);
		if (slave.ovaries === 1) {
			r.push(`inside ${his} womanhood and into ${his} womb, and`);
		}
		r.push(`up ${his} butt and into ${his} lower intestine.`);
	}

	r.push(`Silence returns to the dairy.`);
	App.Events.addParagraph(node, r);
	return node;
};


code:
App.Facilities.FarmerSelect = function() {
	const f = document.createDocumentFragment();

	if (S.Farmer) {
		f.append(`Farmer: ${SlaveFullName(S.Farmer)}, tends to your crops and animals. `);
		f.append(App.UI.DOM.link("Remove Farmer", () => {
			removeJob(S.Farmer, Job.FARMER);
		},
		[], "Farmyard"
		));
	} else {
		f.append(`No Farmer assigned, appoint one from your devoted slaves.`);
	}

	f.append(App.UI.SlaveList.facilityManagerSelection(App.Entity.facilities.farmyard, "Farmyard"));
	return f;
};


code:
/** The base animal class. */
App.Entity.Animal = class {
	/**
	 * @param {string} name
	 * @param {string} species
	 * @param {'canine'|'hooved'|'feline'} type
	 * @param {'domestic'|'exotic'} rarity
	 */
	constructor(name, species, type, rarity) {
		this.name = name;
		this.species = species;
		this.type = type;
		this.rarity = rarity;
		this.articleAn = 'a';
		this.dick = {
			/** Corresponds directly to the sizes in SlaveState. */
			size: this.species === 'cat' ? 2 : 4,
			desc: this.species === 'cat' ? 'little' : 'large',
		};
		this.deadliness = this.type === 'feline' ? this.species === 'cat' ? 1 : 4 : 3;
	}

	/** @returns {boolean} */
	get purchased() {
		return V[this.type].includes(this);
	}

	/** @returns {boolean} */
	get isActive() {
		return V.active[this.type].name === this.name;
	}

	/** @returns {string} */
	get ballType() {
		return this.species;
	}

	/** @returns {this} */
	purchase() {
		V[this.type].push(this);

		return this;
	}

	/** @param {string} name */
	setName(name) {
		this.name = name;

		return this;
	}

	/** @param {string} species */
	setSpecies(species) {
		this.species = species;

		return this;
	}

	/** @param {'canine'|'hooved'|'feline'} type */
	setType(type) {
		this.type = type;

		return this;
	}

	/** @param {'domestic'|'exotic'} rarity */
	setRarity(rarity) {
		this.rarity = rarity;

		return this;
	}

	/** @returns {this} */
	setActive() {
		V.active[this.type] = this;

		return this;
	}

	/** @param {'a'|'an'} setter */
	setArticle(setter) {
		this.articleAn = setter;

		return this;
	}

	/**
	 * @param {number} size
	 * @param {string} desc
	 */
	setDick(size = 2, desc = null) {
		this.dick.size = size;
		this.dick.desc = desc;

		return this;
	}

	/** @param {number} setter */
	setDeadliness(setter) {
		this.deadliness = setter;

		return this;
	}
};

App.Facilities.Farmyard.animals = function() {
	App.Facilities.Farmyard.animals.init();

	const frag = new DocumentFragment();

	const domesticDiv = App.UI.DOM.appendNewElement("div", frag, null, 'margin-bottom');
	const exoticDiv = App.UI.DOM.appendNewElement("div", frag, null, 'margin-bottom');

	const hrMargin = '0';

	const canine = 'canine';
	const hooved = 'hooved';
	const feline = 'feline';
	const exotic = 'exotic';
	const domestic = 'domestic';

	V.nextButton = "Back";
	V.nextLink = "Farmyard";
	V.returnTo = "Farmyard Animals";
	V.encyclopedia = "Farmyard";

	App.UI.DOM.appendNewElement("span", domesticDiv, 'Domestic Animals', ['uppercase', 'bold']);

	if (V.farmyardKennels > 1 || V.farmyardStables > 1 || V.farmyardCages > 1) {
		App.UI.DOM.appendNewElement("span", exoticDiv, 'Exotic Animals', ['uppercase', 'bold']);
	}

	domesticDiv.append(
		domesticCanines(),
		domesticHooved(),
		domesticFelines(),
	);

	exoticDiv.append(
		exoticCanines(),
		exoticHooved(),
		exoticFelines(),
	);

	if (V.debugMode || V.cheatMode) {
		frag.append(addAnimal());
	}

	return frag;

	// Domestic Animals

	function domesticCanines() {
		if (V.farmyardKennels) {
			const div = App.UI.DOM.makeElement("div", null, 'margin-bottom');
			const hr = document.createElement("hr");

			hr.style.margin = hrMargin;

			App.UI.DOM.appendNewElement("span", div, 'Dogs', ['bold']);

			div.append(hr, animalList(canine, domestic, 5000, canine));

			return div;
		}

		return document.createElement("div");
	}

	function domesticHooved() {
		if (V.farmyardStables) {
			const div = App.UI.DOM.makeElement("div", null, 'margin-bottom');
			const hr = document.createElement("hr");

			hr.style.margin = hrMargin;

			App.UI.DOM.appendNewElement("span", div, 'Hooved Animals', ['bold']);

			div.append(hr, animalList(hooved, domestic, 20000, hooved));

			return div;
		}

		return document.createElement("div");
	}

	function domesticFelines() {
		if (V.farmyardCages) {
			const div = App.UI.DOM.makeElement("div", null, 'margin-bottom');
			const hr = document.createElement("hr");

			hr.style.margin = hrMargin;

			App.UI.DOM.appendNewElement("span", div, 'Cats', ['bold']);

			div.append(hr, animalList(feline, domestic, 1000, feline));

			return div;
		}

		return document.createElement("div");
	}

	// Exotic Animals

	function exoticCanines() {
		if (V.farmyardKennels > 1) {
			const div = App.UI.DOM.makeElement("div", null, 'margin-bottom');
			const hr = document.createElement("hr");

			hr.style.margin = hrMargin;

			App.UI.DOM.appendNewElement("span", div, 'Canines', ['bold']);

			div.append(hr, animalList(canine, exotic, 50000, canine));

			return div;
		}

		return document.createElement("div");
	}

	function exoticHooved() {
		if (V.farmyardStables > 1) {
			const div = App.UI.DOM.makeElement("div", null, 'margin-bottom');
			const hr = document.createElement("hr");

			hr.style.margin = hrMargin;

			App.UI.DOM.appendNewElement("span", div, 'Hooved Animals', ['bold']);

			div.append(hr, animalList(hooved, exotic, 75000, hooved));

			return div;
		}

		return document.createElement("div");
	}

	function exoticFelines() {
		if (V.farmyardCages > 1) {
			const div = App.UI.DOM.makeElement("div", null, 'margin-bottom');
			const hr = document.createElement("hr");

			hr.style.margin = hrMargin;

			App.UI.DOM.appendNewElement("span", div, 'Felines', ['bold']);

			div.append(hr, animalList(feline, exotic, 100000, feline));

			return div;
		}

		return document.createElement("div");
	}

	// Helper Functions

	/**
	 * Creates either a link or note text depending on parameters given
	 * @param {object} param
	 * @param {App.Entity.Animal} param.animal
	 * @param {string} param.active
	 * @param {string} param.type
	 * @param {number} param.price
	 * @param {function():void} param.setActiveHandler
	 * @param {function():void} param.purchaseHandler
	 * @returns {string|HTMLElement}
	 */
	function animalLink({animal, active, type, price, setActiveHandler, purchaseHandler}) {
		if (animal.purchased) {
			if (V.active[active] && V.active[active].name === animal.name) {
				return App.UI.DOM.makeElement("span", `Set as active ${type}`, "note");
			} else {
				return App.UI.DOM.link(`Set as active ${type}`, setActiveHandler);
			}
		} else {
			return App.UI.DOM.link(
				`Purchase`,
				purchaseHandler,
				[], '', `Costs ${cashFormat(price)} and will incur upkeep costs.`
			);
		}
	}

	/**
	 * Creates a list of the specified animal type from the main animal array.
	 * @param {'canine'|'hooved'|'feline'} type One of 'canine', 'hooved', or 'feline', also used to determine the active animal type.
	 * @param {'domestic'|'exotic'} rarity One of 'domestic' or 'exotic'.
	 * @param {number} price
	 * @param {string} active The name of the current active animal of the given type.
	 * @returns {HTMLDivElement}
	 */
	function animalList(type, rarity, price, active) {
		const mainDiv = document.createElement("div");
		const filteredArray = App.Data.animals.filter(animal => animal.rarity === rarity && animal.type === type);

		filteredArray.forEach(animal => {
			const animalDiv = document.createElement("div");
			const optionSpan = document.createElement("span");

			const args = {
				animal: animal,
				active: active,
				type: type,
				price: price,
				setActiveHandler() {
					animal.setActive();
					App.UI.DOM.replace(mainDiv, animalList(type, rarity, price, active));
				},
				purchaseHandler() {
					cashX(forceNeg(price), "farmyard");
					animal.purchase();
					App.UI.DOM.replace(mainDiv, animalList(type, rarity, price, active));
				}
			};

			optionSpan.append(animalLink(args));

			animalDiv.append(capFirstChar(animal.name), ' ', optionSpan);

			mainDiv.appendChild(animalDiv);
		});

		return mainDiv;
	}

	function addAnimal() {
		const addAnimalDiv = document.createElement("div");
		const dickDiv = document.createElement("div");
		const deadlinessDiv = document.createElement("div");
		const addDiv = App.UI.DOM.makeElement("div", null, ['animal-add']);

		const animal = new App.Entity.Animal(null, null, "canine", "domestic");

		App.UI.DOM.appendNewElement("div", addAnimalDiv, `Add a New Animal`, ['uppercase', 'bold']);

		addAnimalDiv.append(
			name(),
			species(),
			type(),
			rarity(),
			article(),
			dick(),
			deadliness(),
			add(),
		);

		return addAnimalDiv;

		function name() {
			const nameDiv = document.createElement("div");

			nameDiv.append(
				`Name: `,
				App.UI.DOM.makeTextBox(animal.name || '', value => {
					animal.setName(value);

					App.UI.DOM.replace(nameDiv, name);
					App.UI.DOM.replace(dickDiv, dick);
					App.UI.DOM.replace(deadlinessDiv, deadliness);
					App.UI.DOM.replace(addDiv, add);
				}),
			);

			return nameDiv;
		}

		function species() {
			const speciesDiv = document.createElement("div");

			speciesDiv.append(
				`Species: `,
				App.UI.DOM.makeTextBox(animal.species || '', value => {
					animal.setSpecies(value);

					App.UI.DOM.replace(speciesDiv, species);
					App.UI.DOM.replace(addDiv, add);
				}),
			);

			return speciesDiv;
		}

		function type() {
			const typeDiv = document.createElement("div");

			const typeLinks = [];

			if (animal.type === "canine") {
				typeLinks.push(
					App.UI.DOM.disabledLink(`Canine`, [`Already selected.`]),
					App.UI.DOM.link(`Hooved`, () => {
						animal.setType('hooved');

						App.UI.DOM.replace(typeDiv, type);
					}),
					App.UI.DOM.link(`Feline`, () => {
						animal.setType("feline");

						App.UI.DOM.replace(typeDiv, type);
					}),
				);
			} else if (animal.type === "hooved") {
				typeLinks.push(
					App.UI.DOM.link(`Canine`, () => {
						animal.setType("canine");

						App.UI.DOM.replace(typeDiv, type);
					}),
					App.UI.DOM.disabledLink(`Hooved`, [`Already selected.`]),
					App.UI.DOM.link(`Feline`, () => {
						animal.setType("feline");

						App.UI.DOM.replace(typeDiv, type);
					}),
				);
			} else {
				typeLinks.push(
					App.UI.DOM.link(`Canine`, () => {
						animal.setType("canine");

						App.UI.DOM.replace(typeDiv, type);
					}),
					App.UI.DOM.link(`Hooved`, () => {
						animal.setType("hooved");

						App.UI.DOM.replace(typeDiv, type);
					}),
					App.UI.DOM.disabledLink(`Feline`, [`Already selected.`]),
				);
			}

			typeDiv.append(`Type: `, App.UI.DOM.generateLinksStrip(typeLinks));

			return typeDiv;
		}

		function rarity() {
			const rarityDiv = document.createElement("div");

			const rarityLinks = [];

			if (animal.rarity === "domestic") {
				rarityLinks.push(
					App.UI.DOM.disabledLink(`Domestic`, [`Already selected.`]),
					App.UI.DOM.link(`Exotic`, () => {
						animal.setRarity('exotic');

						App.UI.DOM.replace(rarityDiv, rarity);
					}),
				);
			} else {
				rarityLinks.push(
					App.UI.DOM.link(`Domestic`, () => {
						animal.setRarity('domestic');

						App.UI.DOM.replace(rarityDiv, rarity);
					}),
					App.UI.DOM.disabledLink(`Exotic`, [`Already selected.`]),
				);
			}

			rarityDiv.append(`Rarity: `, App.UI.DOM.generateLinksStrip(rarityLinks));

			return rarityDiv;
		}

		function article() {
			const articleDiv = document.createElement("div");

			const articleLinks = [];

			if (animal.articleAn === 'a') {
				articleLinks.push(
					App.UI.DOM.link("Yes", () => {
						animal.articleAn = 'an';

						App.UI.DOM.replace(articleDiv, article);
						App.UI.DOM.replace(dickDiv, dick);
						App.UI.DOM.replace(deadlinessDiv, deadliness);
					}),
					App.UI.DOM.disabledLink("No", [`Already selected.`]),
				);
			} else {
				articleLinks.push(
					App.UI.DOM.disabledLink("Yes", [`Already selected.`]),
					App.UI.DOM.link("No", () => {
						animal.articleAn = 'a';

						App.UI.DOM.replace(articleDiv, article);
						App.UI.DOM.replace(dickDiv, dick);
						App.UI.DOM.replace(deadlinessDiv, deadliness);
					}),
				);
			}

			articleDiv.append(`Is this animal's name preceded by an 'an'? `, App.UI.DOM.generateLinksStrip(articleLinks));

			return articleDiv;
		}

		function dick() {
			dickDiv.append(dickSize(), dickDesc());

			return dickDiv;

			function dickSize() {
				const dickSizeDiv = document.createElement("div");

				dickSizeDiv.append(
					`How large is ${animal.name ? `${animal.articleAn} male ${animal.name}` : `a male`}'s penis? `,
					App.UI.DOM.makeTextBox(animal.dick.size || 2, value => {
						animal.setDick(value, animal.dick.desc || null);

						App.UI.DOM.replace(dickSizeDiv, dickSize);
					}, true),
					App.UI.DOM.makeElement("span", `1 is smallest, and default is 2. `, ['note']),
				);

				return dickSizeDiv;
			}

			function dickDesc() {
				const dickDescDiv = document.createElement("div");

				dickDescDiv.append(
					`What does it look like? `,
					App.UI.DOM.makeTextBox(animal.dick.desc || '', value => {
						animal.setDick(animal.dick.size || 2, value);

						App.UI.DOM.replace(dickDescDiv, dickDesc);
					}),
					App.UI.DOM.makeElement("span", `Default is 'large'. `, ['note']),
				);

				return dickDescDiv;
			}
		}

		function deadliness() {
			deadlinessDiv.append(
				`How deadly is ${animal.name ? `${animal.articleAn} ${animal.name}` : `the animal`}? `,
				App.UI.DOM.makeTextBox(5, value => {
					animal.setDick(value);
				}, true),
				App.UI.DOM.makeElement("span", `Default is 5. `, ['note']),
			);

			return deadlinessDiv;
		}

		function add() {
			const disabledReasons = [];

			let link;

			if (!animal.name) {
				disabledReasons.push(`Animal must have a name.`);
			}

			if (!animal.species) {
				disabledReasons.push(`Animal must have a species.`);
			}

			if (disabledReasons.length > 0) {
				link = App.UI.DOM.disabledLink(`Add`, disabledReasons);
			} else {
				link = App.UI.DOM.link(`Add`, () => {
					App.Data.animals.push(animal);

					App.UI.DOM.replace(addAnimalDiv, addAnimal);
				});
			}

			addDiv.appendChild(link);

			return addDiv;
		}
	}
};

App.Facilities.Farmyard.animals.init = function() {
	if (App.Data.animals.length === 0) {
		class Animal extends App.Entity.Animal {}

		const dog = 'dog';
		const cat = 'cat';
		const canine = 'canine';
		const hooved = 'hooved';
		const feline = 'feline';
		const domestic = 'domestic';
		const exotic = 'exotic';
		const an = 'an';

		/** @type {Animal[]} */
		App.Data.animals = [
			new Animal("beagle", dog, canine, domestic)
				.setDeadliness(2),
			new Animal("bulldog", dog, canine, domestic),
			new Animal("French bulldog", dog, canine, domestic)
				.setDeadliness(2),
			new Animal("German shepherd", dog, canine, domestic),
			new Animal("golden retriever", dog, canine, domestic),
			new Animal("labrador retriever", dog, canine, domestic),
			new Animal("poodle", dog, canine, domestic)
				.setDeadliness(2),
			new Animal("rottweiler", dog, canine, domestic),
			new Animal("Siberian husky", dog, canine, domestic),
			new Animal("Yorkshire terrier", dog, canine, domestic)
				.setDeadliness(2),

			new Animal("dingo", "dingo", canine, exotic),
			new Animal("fox", "fox", canine, exotic),
			new Animal("jackal", "jackal", canine, exotic),
			new Animal("wolf", "wolf", canine, exotic)
				.setDeadliness(4),

			new Animal("bull", "bull", hooved, domestic)
				.setDick(5, 'huge'),
			new Animal("horse", "horse", hooved, domestic)
				.setDick(5, 'huge'),
			new Animal("pig", "pig", hooved, domestic),

			new Animal("zebra", "zebra", hooved, exotic)
				.setDick(5, 'huge'),
			new Animal("elephant", "elephant", hooved, exotic)
				.setArticle(an)
				.setDick(6, 'enormous'),	// not exactly true to life, but more interesting

			new Animal("Abbysinian", cat, feline, domestic)
				.setArticle(an),
			new Animal("Bengal", cat, feline, domestic),
			new Animal("Birman", cat, feline, domestic),
			new Animal("Maine coon", cat, feline, domestic),
			new Animal("Oriental shorthair", cat, feline, domestic)
				.setArticle(an),
			new Animal("Persian", cat, feline, domestic),
			new Animal("Ragdoll", cat, feline, domestic),
			new Animal("Russian blue", cat, feline, domestic),
			new Animal("Siamese", cat, feline, domestic),
			new Animal("Sphynx", cat, feline, domestic),

			new Animal("cougar", "cougar", feline, exotic),
			new Animal("jaguar", "jaguar", feline, exotic),
			new Animal("leopard", "leopard", feline, exotic),
			new Animal("lion", "lion", feline, exotic),
			new Animal("lynx", "lynx", feline, exotic),
			new Animal("puma", "puma", feline, exotic),
			new Animal("tiger", "tiger", feline, exotic),
		];
	}
};

/** @type {App.Entity.Animal[]} */
App.Data.animals = App.Data.animals || [];