code:
{
	class PLimbInterface2 extends App.Medicine.Surgery.Reaction {
		get key() { return "PLimb interface2"; }

		reaction(slave, diff) {
			const reaction = super.reaction(slave, diff);
			const {He, he, His, his, him, hers} = getPronouns(slave);
			const r = [];

			r.push(`When ${he} is carried out of surgery ${he}`);
			if (canSee(slave)) {
				r.push(`cranes ${his} neck to better see the ports`);
			} else {
				r.push(`wiggles ${his} stumps trying to feel the ports`);
			}
			r.push(`installed in ${his} stumps. ${His} stumps twitch slightly as the software begins configuring. Recovery will be significant, since the surgical implantation of anchor points for the limbs themselves and the installation of nerve bridges constituted major surgery.`);
			if (this._hasEmotion(slave)) {
				if (slave.devotion > 20) {
					r.push(`Nevertheless, ${he}'s overwhelmed with gratitude, and thanks you profusely the first chance ${he} gets. ${He} follows the acclimation program diligently, doing ${his} best to learn how to be a good slave despite, or sometimes even because of, ${his} disability. ${He} places more trust in you, too, since you obviously have ${his} best interests at heart.`);
					reaction.devotion += 5;
					reaction.trust += 5;
				} else if (slave.devotion >= -20) {
					r.push(`${He}'s overwhelmed with gratitude, in part because ${he} didn't think you'd do something like this for ${him}. ${He} thanks you profusely the first chance ${he} gets, and follows the acclimation program diligently, trying to deserve the expense you went to. ${He} places more trust in you, too, since you seem to have a plan for ${him}.`);
					reaction.devotion += 5;
					reaction.trust += 5;
				} else {
					r.push(`Despite ${his} hatred of you, ${he} can't help but trust you a bit more, since you clearly have a plan that involves putting a good deal of value into ${him}. Your goals might not be ${hers}, but at least ${he} has an indication that you're not toying with ${him}.`);
					reaction.trust += 5;
				}
			}

			V.prostheticsConfig = "interface";
			r.push(App.UI.prostheticsConfigPassage(slave));
			V.nextLink = "Remote Surgery";

			reaction.longReaction.push(r);
			return reaction;
		}
	}

	new PLimbInterface2();
}


code:
{
	class PLimbInterface3 extends App.Medicine.Surgery.Reaction {
		get key() { return "PLimb interface3"; }

		reaction(slave, diff) {
			const reaction = super.reaction(slave, diff);
			const {He, he, His, his, him, hers, himself} = getPronouns(slave);
			const r = [];

			r.push(`When ${he} is carried out of surgery ${he}`);
			if (canSee(slave)) {
				r.push(`cranes ${his} neck to better see the ports`);
			} else {
				r.push(`wiggles ${his} stumps trying to feel the ports`);
			}
			r.push(`installed in ${his} stumps. ${His} stumps twitch slightly as the software begins configuring. Since ${he} already had anchors installed in previous surgery this procedure was less invasive and thus ${his} health has been only slightly affected.`);
			if (slave.fetish !== "mindbroken" && slave.fuckdoll === 0) {
				if (slave.devotion > 20) {
					r.push(`${He} is overjoyed when ${he} finds out this upgrade will allow ${him} to feel with ${his} limbs again and thanks you profusely the first chance ${he} gets. ${He} places more trust in you, too, since you obviously have ${his} best interests at heart.`);
				} else if (slave.devotion >= -20) {
					r.push(`${He}'s overwhelmed with joy and gratitude, when ${he} finds out this upgrade will allow ${him} to feel with ${his} limbs again, in part because ${he} didn't think you'd do something like this for ${him}. ${He} thanks you profusely the first chance ${he} gets and is determined to prove ${himself} worthy of the expense you went to for ${him}. ${He} places more trust in you, too, since you seem to have a plan for ${him}.`);
				} else {
					r.push(`Despite ${his} hatred of you, ${he} can't help but feel some trust and gratitude, towards you, since you clearly have a plan that involves putting a good deal of value into ${him}. Your goals might not be ${hers}, but at least ${he} has an indication that you're not toying with ${him}.`);
				}
				reaction.devotion += 5;
				reaction.trust += 5;
			}

			V.prostheticsConfig = "interface";
			r.push(App.UI.prostheticsConfigPassage(slave));
			V.nextLink = "Remote Surgery";

			reaction.longReaction.push(r);
			return reaction;
		}
	}

	new PLimbInterface3();
}

repo_name: Pecanus/fc

license: mit


code:
{
	class PLimbInterface4 extends App.Medicine.Surgery.Reaction {
		get key() { return "PLimb interface4"; }

		reaction(slave, diff) {
			const reaction = super.reaction(slave, diff);
			const {He, he, His, his, him} = getPronouns(slave);
			const r = [];

			r.push(`When ${he} is carried out of surgery ${he}`);
			if (canSee(slave)) {
				r.push(`cranes ${his} neck to better see the ports`);
			} else {
				r.push(`wiggles ${his} stumps trying to feel the ports`);
			}
			r.push(`installed in ${his} stumps. ${His} stumps twitch slightly as the software begins configuring. Since ${he} already had anchors installed in previous surgery this procedure was less invasive and thus ${his} health has been only slightly affected.`);
			if (slave.fetish !== "mindbroken" && slave.fuckdoll === 0) {
				if (slave.devotion > 20) {
					r.push(`${He} trusts you enough to be not be put off by your explanation of what kind of prosthetic limbs will fit ${his} new interface. Thinking that maybe being a pet won't be so bad.`);
				} else if (slave.devotion >= -20) {
					r.push(`${He}'s <span class="devotion inc">apprehensive</span> when ${he} finds out this interface will make ${him} quadrupedal like a animal.`);
					reaction.devotion -= 5;
					reaction.trust -= 5;
				} else {
					r.push(`The flicker of gratefulness towards you is quickly replaced by hatred when ${he} finds out that this new interface will force her to walk like an animal. ${His} impression of you becomes worse now that ${he} knows that you plan to turn ${him} into a pet.`);
					reaction.devotion -= 25;
					reaction.trust -= 25;
				}
			}

			V.prostheticsConfig = "interface";
			r.push(App.UI.prostheticsConfigPassage(slave));
			V.nextLink = "Remote Surgery";

			reaction.longReaction.push(r);
			return reaction;
		}
	}

	new PLimbInterface4();
}


code:
{
	class PLimbInterface5 extends App.Medicine.Surgery.Reaction {
		get key() { return "PLimb interface5"; }

		reaction(slave, diff) {
			const reaction = super.reaction(slave, diff);
			const {He, he, his, him} = getPronouns(slave);
			const r = [];

			r.push(`When ${he} is carried out of surgery ${he}`);
			if (canSee(slave)) {
				r.push(`cranes ${his} neck to better see the ports`);
			} else {
				r.push(`wiggles ${his} stumps trying to feel the ports`);
			}
			r.push(`installed in ${his} stumps. Recovery will be significant, since the surgical implantation of anchor points for the limbs themselves and the installation of nerve impulse detectors constituted major surgery.`);
			if (this._hasEmotion(slave)) {
				if (slave.devotion > 20) {
					r.push(`Even after learning what kind of prosthetics will fit ${him}, ${he}'s still filled with gratitude, and thanks you the first chance ${he} gets. ${He} follows the acclimation program diligently, doing ${his} best to learn how to be a good pet for you. ${He} places more trust in you, too, since you gave ${him} the ability to move on ${his} own again.`);
					reaction.devotion += 5;
					reaction.trust += 5;
				} else if (slave.devotion >= -20) {
					r.push(`After learning what kind of prosthetics are awaiting ${him}, ${he}'s still relatively grateful to you, because ${he} didn't think ${he}'d ever move on ${his} own again. ${He} thanks you sincerely, and follows the acclimation program diligently, looking forward to being able to move on ${his} own again. ${He} places more trust in you, since you don't seem to have bad things planned for ${him}.`);
					reaction.trust += 5;
				} else {
					r.push(`The slight joy of being able to have limbs again is greatly dampened when ${he} learns what kind of limbs are awaiting ${him}, ${he}'s only comforted by the thought of being able to walk on ${his} own again. The already bad impression of you worsens, now that ${he} has feels like you're toying with ${him}.`);
					reaction.devotion -= 5;
					reaction.trust -= 5;
				}
			}

			V.prostheticsConfig = "interface";
			r.push(App.UI.prostheticsConfigPassage(slave));
			V.nextLink = "Remote Surgery";

			reaction.longReaction.push(r);
			return reaction;
		}
	}

	new PLimbInterface5();
}


code:
{
	class TailInterface extends App.Medicine.Surgery.Reaction {
		get key() { return "tailInterface"; }

		reaction(slave, diff) {
			const reaction = super.reaction(slave, diff);
			const {his} = getPronouns(slave);
			const r = [];

			r.push(`Implanting a tail socket and interfacing it with ${his} spinal column is delicate and invasive procedure <span class="health dec">${his} health has been greatly affected.</span>`);

			reaction.longReaction.push(r);
			return reaction;
		}
	}

	new TailInterface();
}


code:
App.Medicine.Surgery.Reactions.Amputate = class extends App.Medicine.Surgery.SimpleReaction {
	/**
	 * @param {FC.LimbsState}oldLimbs
	 */
	constructor(oldLimbs) {
		super();
		this.oldLimbs = oldLimbs;
	}

	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const r = [];

		r.push(App.Medicine.Limbs.amputate(slave, this.oldLimbs));

		reaction.longReaction.push(r);
		return reaction;
	}

	outro(slave, diff, previousReaction) {
		const reaction = super.outro(slave, diff, previousReaction);
		const {He, him} = getPronouns(slave);

		if (slave.behavioralFlaw === "arrogant") {
			reaction.longReaction.last()
				.push(`<span class="flaw break">${He} can hardly be arrogant relying on others to feed, bathe and carry ${him}.</span>`);
			slave.behavioralFlaw = "none";
		}

		return reaction;
	}
};

App.Medicine.Surgery.Procedures.Amputate = class extends App.Medicine.Surgery.Procedure {
	/**
	 * @param {App.Entity.SlaveState} slave
	 * @param {boolean} leftArm
	 * @param {boolean} rightArm
	 * @param {boolean} leftLeg
	 * @param {boolean} rightLeg
	 */
	constructor(slave, leftArm, rightArm, leftLeg, rightLeg) {
		super(slave);
		this.leftArm = leftArm;
		this.rightArm = rightArm;
		this.leftLeg = leftLeg;
		this.rightLeg = rightLeg;
		this.count = (leftArm ? 1 : 0) + (rightArm ? 1 : 0) + (leftLeg ? 1 : 0) + (rightLeg ? 1 : 0);
	}

	get name() {
		if (this.count === 0) {
			return "Amputate limb(s)";
		} else if (this.count === 1) {
			return "Amputate limb";
		} else {
			return "Amputate limbs";
		}
	}

	get description() {
		const {him} = getPronouns(this.originalSlave);
		return `this will greatly restrict ${him}`;
	}

	get disabledReasons() {
		if (this.count > 0) {
			return [];
		}
		return ["No limb selected"];
	}

	get healthCost() {
		return this.count * 10;
	}

	get cost() {
		return super.cost * this.count;
	}

	apply(cheat) {
		const oldLimbs = App.Medicine.Limbs.currentLimbs(this._slave);

		if (this.leftArm) {
			removeLimbs(this._slave, "left arm");
		}
		if (this.rightArm) {
			removeLimbs(this._slave, "right arm");
		}
		if (this.leftLeg) {
			removeLimbs(this._slave, "left leg");
		}
		if (this.rightLeg) {
			removeLimbs(this._slave, "right leg");
		}

		if (!hasAnyArms(this._slave)) {
			this._slave.rules.release.masturbation = 0;
		}

		return this._assemble(new App.Medicine.Surgery.Reactions.Amputate(oldLimbs));
	}
};


code:
App.Medicine.Surgery.Reactions.ShortenTendons = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, His, his, him} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} exits the surgery on all fours, unable to stand due to the changes to ${his} legs. A whorish pair of heels are slipped onto ${him} and ${he} is forced to ${his} feet to show that ${he} can indeed walk comfortably while wearing them. As with all surgery ${his} health has been slightly affected.`);
		} else if (slave.devotion > 50) {
			r.push(`${He} exits the surgery on all fours, unable to stand due to the changes to ${his} legs. ${He} finds a whorish pair of heels waiting for ${him} and eagerly puts them on, gingerly standing to find that ${he} can indeed walk comfortably while wearing them. ${He} struts back and forth experimentally and then offers`);
			if (canSee(slave)) {
				r.push(`the mirror`);
			} else {
				r.push(`you`);
			}
			r.push(`${his} asshole to check to see that ${his} ability to take a standing buttfuck hasn't been affected. ${He} has become more submissive due to your radical reshaping of ${his} body. As with all surgery ${his} health has been slightly affected.`);
			reaction.devotion += 4;
		} else if (slave.devotion > 20) {
			r.push(`${He} exits the surgery on all fours, unable to stand due to the changes to ${his} legs. ${He} finds a whorish pair of heels waiting for ${him} and obediently puts them on, gingerly standing to find that ${he} can indeed walk comfortably while wearing them. After a while ${he} realizes that ${he}'ll never walk without looking like a stripper again, but ${he} accepts it. ${He} isn't much affected mentally. As with all surgery ${his} health has been slightly affected.`);
		} else {
			r.push(`${He} exits the surgery on all fours, unable to stand due to the changes to ${his} legs. ${He} finds a whorish pair of heels waiting for ${him}, but obstinately ignores them. After some time, ${he} realizes that the situation isn't changing and puts them on, gingerly standing to find that ${he} can indeed walk comfortably while wearing them. ${His}`);
			if (canSee(slave)) {
				r.push(`eyes are`);
			} else {
				r.push(`face is`);
			}
			r.push(`filled with hatred when ${he}`);
			if (canSee(slave)) {
				r.push(`sees ${his} new and permanent appearance in the mirror.`);
			} else {
				r.push(`discovers this is the only way ${he}'ll be able to stand now.`);
			}
			r.push(`The surgical invasion has filled ${him} with horror and anger. As with all surgery ${his} health has been slightly affected. ${He} is terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 10;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Reactions.ReplaceTendons = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} exits the surgery on ${his} own two feet. ${He}'s still sore, but the modern surgery is fast and effective, and ${he} can use ${his} restored legs immediately. ${He} gingerly stands on one foot, then the other; and even takes a few little hops. ${He} obviously confused, but will get used to it soon enough. As with all surgery ${his} health has been slightly affected.`);
		} else if (slave.devotion >= -20) {
			r.push(`${He} exits the surgery on ${his} own two feet. ${He}'s still sore, but the modern surgery is fast and effective, and ${he} can use ${his} restored legs immediately. ${He} gingerly stands on one foot, then the other; and even takes a few little hops. ${He}'s grinning like a fool the whole time. ${He} has become more obedient due to gratitude. As with all surgery ${his} health has been slightly affected.`);
			reaction.devotion += 4;
		} else {
			r.push(`${He} exits the surgery on ${his} own two feet. ${He}'s still sore, but the modern surgery is fast and effective, and ${he} can use ${his} restored legs immediately. ${He} gingerly stands on one foot, then the other; and even takes a few little hops. ${He} obviously confused, finding it surprising that you would go to the expense and trouble of repairing ${him}. As with all surgery ${his} health has been slightly affected.`);
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.ShortenTendons = class extends App.Medicine.Surgery.Procedure {
	get name() { return "Shorten tendons"; }

	get description() {
		const {him} = getPronouns(this._slave);
		return `Prevents ${him} from walking in anything but very high heels`;
	}

	get healthCost() { return 20; }

	apply(cheat) {
		this._slave.heels = 1;
		this._slave.shoes = "heels";
		return this._assemble(new App.Medicine.Surgery.Reactions.ShortenTendons());
	}
};

App.Medicine.Surgery.Procedures.ReplaceTendons = class extends App.Medicine.Surgery.Procedure {
	get name() { return "Replace tendons"; }

	get healthCost() { return 10; }

	apply(cheat) {
		this._slave.heels = 0;
		this._slave.shoes = "none";
		return this._assemble(new App.Medicine.Surgery.Reactions.ReplaceTendons());
	}
};


code:
App.Medicine.Surgery.Reactions.Height = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} exits the surgery very slowly, since ${he}'s terribly sore and isn't yet used to the novel lengths of the legs ${he} walks on. ${He}'ll be clumsy for some time. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else if (slave.devotion > 50) {
			r.push(`${He} exits the surgery very cautiously, since ${he}'s terribly sore and isn't yet used to the novel lengths of the legs ${he} walks on. ${He}'ll be clumsy and hesitant for some time, but ${he}'s happy with ${his} new body. ${He} has become more submissive due to your radical reshaping of ${his} body. Since the surgery was invasive, ${his} health has been greatly affected.`);
			reaction.devotion += 4;
		} else if (slave.devotion > 20) {
			r.push(`${He} exits the surgery very cautiously, since ${he}'s terribly sore and isn't yet used to the novel lengths of the legs ${he} walks on. ${He}'ll be clumsy and hesitant for some time, but ${he}'s accepted ${his} new body. ${He} isn't much affected mentally. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else {
			r.push(`${He} exits the surgery very cautiously, since ${he}'s terribly sore and isn't yet used to the novel lengths of the legs ${he} walks on. ${He}'ll be clumsy and hesitant for some time, and ${he} refuses to accept that this new body is really what ${he}'s been condemned to. The surgical invasion has filled ${him} with horror and anger. Since the surgery was invasive, ${his} health has been greatly affected. ${He} is terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 10;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.IncreaseHeight = class extends App.Medicine.Surgery.Procedure {
	get name() {
		if (this._slave.heightImplant === 0) {
			return "Lengthen major bones";
		} else if (this._slave.heightImplant >= 1) {
			return "Advanced height gain surgery";
		} else if (this._slave.heightImplant === -1) {
			return "Reverse existing height surgery";
		} else {
			return "Revert a stage of existing height surgery";
		}
	}

	get healthCost() { return 40; }

	apply(cheat) {
		this._slave.heightImplant += 1;
		this._slave.height += 10;
		return this._assemble(new App.Medicine.Surgery.Reactions.ShortenTendons());
	}
};

App.Medicine.Surgery.Procedures.DecreaseHeight = class extends App.Medicine.Surgery.Procedure {
	get name() {
		if (this._slave.heightImplant === 0) {
			return "Shorten major bones";
		} else if (this._slave.heightImplant <= -1) {
			return "Advanced height reduction surgery";
		} else if (this._slave.heightImplant === 1) {
			return "Reverse existing height surgery";
		} else {
			return "Revert a stage of existing height surgery";
		}
	}

	get healthCost() { return 40; }

	apply(cheat) {
		this._slave.heightImplant -= 1;
		this._slave.height -= 10;
		return this._assemble(new App.Medicine.Surgery.Reactions.ShortenTendons());
	}
};


code:
App.Medicine.Surgery.Reactions.Hips = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} exits the surgery very slowly, since ${he}'s still in considerable pain and isn't yet used to the way ${his} pelvis now fits together with the rest of ${his} body. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else if (slave.devotion > 50) {
			r.push(`${He} exits the surgery very cautiously, since ${he}'s still in considerable pain and isn't yet used to the way ${his} pelvis now fits together with the rest of ${his} body. ${He}'ll be clumsy and hesitant for some time, but ${he}'s happy with ${his} new hips. ${He} has become more submissive due to your radical reshaping of ${his} body. Since the surgery was invasive, ${his} health has been greatly affected.`);
			reaction.devotion += 4;
		} else if (slave.devotion > 20) {
			r.push(`${He} exits the surgery very cautiously, since ${he}'s still in considerable pain and isn't yet used to the way ${his} pelvis now fits together with the rest of ${his} body. ${He}'ll be clumsy and hesitant for some time, but ${he}'s accepted ${his} new hips. ${He} isn't much affected mentally. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else {
			r.push(`${He} exits the surgery very cautiously, since ${he}'s still in considerable pain and isn't yet used to the way ${his} pelvis now fits together with the rest of ${his} body. ${He}'ll be clumsy and hesitant for some time, and ${he} refuses to accept that you are both willing and able to reshape ${him} down to ${his} very bones. The surgical invasion has filled ${him} with horror and anger. Since the surgery was invasive, ${his} health has been greatly affected. ${He} is terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 10;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.BroadenPelvis = class extends App.Medicine.Surgery.Procedure {
	get name() { return this._slave.shouldersImplant === 0 ? "Broaden pelvis" : "Advanced pelvis broadening"; }

	get healthCost() { return 40; }

	apply(cheat) {
		this._slave.hipsImplant++;
		this._slave.hips++;
		return this._assemble(new App.Medicine.Surgery.Reactions.Hips());
	}
};

App.Medicine.Surgery.Procedures.NarrowPelvis = class extends App.Medicine.Surgery.Procedure {
	get name() { return this._slave.shouldersImplant === 0 ? "Narrow pelvis" : "Advanced pelvis narrowing"; }

	get healthCost() { return 40; }

	apply(cheat) {
		this._slave.hipsImplant--;
		this._slave.hips--;
		return this._assemble(new App.Medicine.Surgery.Reactions.Hips());
	}
};


code:
App.Medicine.Surgery.Reactions.Shoulders = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} exits the surgery gingerly, since the changes of proportion in ${his} upper body have seriously affected ${his} sense of balance. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else if (slave.devotion > 50) {
			r.push(`${He} exits the surgery gingerly, since the changes of proportion in ${his} upper body have seriously affected ${his} sense of balance, albeit temporarily. ${He}'ll be clumsy and hesitant for some time, but ${he}'s happy with ${his} new shoulders. ${He} has become more submissive due to your radical reshaping of ${his} body. Since the surgery was invasive, ${his} health has been greatly affected.`);
			reaction.devotion += 4;
		} else if (slave.devotion > 20) {
			r.push(`${He} exits the surgery gingerly, since the changes of proportion in ${his} upper body have seriously affected ${his} sense of balance, albeit temporarily. ${He}'ll be clumsy and hesitant for some time, but ${he}'s accepted ${his} new shoulders. ${He} isn't much affected mentally. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else {
			r.push(`${He} exits the surgery gingerly, since the changes of proportion in ${his} upper body have seriously affected ${his} sense of balance, albeit temporarily. ${He}'ll be clumsy and hesitant for some time, and ${he} refuses to accept that you are both willing and able to reshape ${him} down to ${his} very bones. The surgical invasion has filled ${him} with horror and anger. Since the surgery was invasive, ${his} health has been greatly affected. ${He} is terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 10;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.BroadenShoulders = class extends App.Medicine.Surgery.Procedure {
	get name() { return this._slave.shouldersImplant === 0 ? "Restructure shoulders more broadly" : "Advanced shoulder broadening surgery"; }

	get healthCost() { return 40; }

	apply(cheat) {
		this._slave.shouldersImplant++;
		this._slave.shoulders++;
		return this._assemble(new App.Medicine.Surgery.Reactions.Shoulders());
	}
};

App.Medicine.Surgery.Procedures.NarrowShoulders = class extends App.Medicine.Surgery.Procedure {
	get name() { return this._slave.shouldersImplant === 0 ? "Restructure shoulders more narrowly" : "Advanced shoulder narrowing surgery"; }

	get healthCost() { return 40; }

	apply(cheat) {
		this._slave.shouldersImplant--;
		this._slave.shoulders--;
		return this._assemble(new App.Medicine.Surgery.Reactions.Shoulders());
	}
};


code:
App.Medicine.Surgery.Reactions.Braces = class extends App.Medicine.Surgery.SimpleReaction {
	get invasive() {
		return false;
	}

	get permanentChanges() {
		return false;
	}

	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, His, his, him, himself} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} is quite quick to realize ${his} teeth now have something on them. What its purpose is is beyond ${him}, though.`);
		} else if (slave.teeth === "straightening braces") {
			r.push(`Quite aware that ${his} crooked, aching teeth are now in braces,`);
			if (slave.devotion > 50) {
				r.push(`${He} smiles tentatively at`);
				if (canSee(slave)) {
					r.push(`${himself} in the mirror.`);
				} else {
					r.push(`you.`);
				}
				r.push(`${He}'s experiencing considerable discomfort, but ${he} knows it will <span class="devotion inc">make ${him} prettier for you,</span> and resolves to do ${his} best to put up with it.`);
				reaction.devotion += 4;
			} else if (slave.devotion > 20) {
				r.push(`${He} pulls ${his} lips back to`);
				if (canSee(slave)) {
					r.push(`check them out.`);
				} else {
					r.push(`feel them.`);
				}
				r.push(`${He}'s experiencing considerable discomfort, but ${he} knows it will <span class="devotion inc">make ${him} prettier,</span> and ${he} accepts that the pain is for ${his} own good.`);
				reaction.devotion += 2;
			} else {
				r.push(`${He} pulls ${his} lips back to`);
				if (canSee(slave)) {
					r.push(`check them out.`);
				} else {
					r.push(`feel them.`);
				}
				r.push(`${He}'s experiencing considerable discomfort, and ${his} feelings are mixed. ${He} knows that straightening teeth is expensive, and in different circumstances ${he} would probably be glad to be given free braces. However, ${he}'s very aware that ${he}'s being beautified because ${he}'s a sex slave.`);
			}
		} else if (slave.teeth === "cosmetic braces") {
			r.push(`Quite aware that ${his} aching teeth are now in braces,`);
			if (slave.devotion > 50) {
				r.push(`${he} smiles tentatively at`);
				if (canSee(slave)) {
					r.push(`${himself} in the mirror.`);
				} else {
					r.push(`you.`);
				}
				r.push(`${His} teeth are already quite straight, so ${he} doesn't understand why you've done this. ${He}'s not unwilling to put up with inexplicable things you command, however, so ${he} resolves to put up with this, too.`);
			} else if (slave.devotion > 20) {
				r.push(`${he} pulls ${his} lips back to`);
				if (canSee(slave)) {
					r.push(`check them out.`);
				} else {
					r.push(`feel them.`);
				}
				r.push(`The discomfort is limited by the fact that ${his} teeth are already straight. ${He} doesn't understand why you've given ${his} braces anyway, so ${his} reaction is limited to vague confusion.`);
			} else {
				r.push(`${he} pulls ${his} lips back to`);
				if (canSee(slave)) {
					r.push(`check them out.`);
				} else {
					r.push(`feel them.`);
				}
				r.push(`${His} teeth are already straight, limiting the discomfort but confusing ${him} greatly. ${He}'s not a little relieved that the autosurgery's attention to ${his} mouth only left ${him} with pointless braces, and is only mildly angered by the strange intrusion.`);
				reaction.devotion -= 2;
			}
		}
		r.push(`Though unpleasant, orthodontia isn't particularly harmful; ${his} health is unaffected.`);

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Reactions.RemoveBraces = class extends App.Medicine.Surgery.SimpleReaction {
	get invasive() {
		return false;
	}

	get permanentChanges() {
		return false;
	}

	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him, himself} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} is quite quick to realize ${his} teeth are missing something.`);
		} else {
			r.push(`Quite aware that ${his} teeth are now free of ${his} braces,`);
			if (slave.devotion > 50) {
				r.push(`${he} smiles tentatively`);
				if (canSee(slave)) {
					r.push(`at ${himself} in the mirror`);
				} else {
					r.push(`and runs ${his} tongue across ${his} teeth`);
				}
				r.push(`only to find they are as crooked as ever. ${He} immediately shuts ${his} mouth, ${his} opinion of you souring, and carries on as if you had never put them on ${him} in the first place.`);
				reaction.devotion -= 4;
			} else if (slave.devotion > 20) {
				r.push(`${he} pulls ${his} lips back to`);
				if (canSee(slave)) {
					r.push(`check them out`);
				} else {
					r.push(`feel them`);
				}
				r.push(`only to find they are as crooked as ever. ${He} immediately shuts ${his} mouth, ${his} opinion of you souring, and carries on as if you had never put them on ${him} in the first place.`);
				reaction.devotion -= 2;
			} else {
				r.push(`${he} pulls ${his} lips back to`);
				if (canSee(slave)) {
					r.push(`check them out.`);
				} else {
					r.push(`feel them.`);
				}
				r.push(`${He} knows that straightening teeth is expensive and sighs, feeling that ${he}'s not worth the expense. No matter what ${he} thought of you, ${he} felt ${he} would at least benefit from having nice teeth, and now it's clear to ${him}: You don't care.`);
				reaction.devotion -= 5;
				reaction.trust -= 5;
			}
		}
		r.push(`Though unpleasant, orthodontia isn't particularly harmful; ${his} health is unaffected.`);

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Reactions.RemoveCosmeticBraces = class extends App.Medicine.Surgery.SimpleReaction {
	get invasive() {
		return false;
	}

	get permanentChanges() {
		return false;
	}

	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} is quite quick to realize ${his} teeth are missing something.`);
		} else {
			r.push(`Quite aware that ${his} teeth are now free of ${his} braces,`);
			if (slave.devotion > 50) {
				r.push(`${he} smiles tentatively`);
			} else {
				r.push(`${he} pulls ${his} lips back to`);
			}
			if (canSee(slave)) {
				r.push(`check them out`);
			} else {
				r.push(`feel them`);
			}
			r.push(`and finds they are now back to normal.`);
		}
		r.push(`Though unpleasant, orthodontia isn't particularly harmful; ${his} health is unaffected.`);

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.ApplyBraces = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Apply Braces";
	}

	apply(cheat) {
		this._slave.teeth = "straightening braces";
		return this._assemble(new App.Medicine.Surgery.Reactions.Braces());
	}
};

App.Medicine.Surgery.Procedures.RemoveBraces = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Remove Braces";
	}

	apply(cheat) {
		this._slave.teeth = "crooked";
		return this._assemble(new App.Medicine.Surgery.Reactions.RemoveBraces());
	}
};

App.Medicine.Surgery.Procedures.AddCosmeticBraces = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Unnecessary braces";
	}

	apply(cheat) {
		this._slave.teeth = "cosmetic braces";
		return this._assemble(new App.Medicine.Surgery.Reactions.RemoveCosmeticBraces());
	}
};

App.Medicine.Surgery.Procedures.RemoveCosmeticBraces = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Remove Braces";
	}

	apply(cheat) {
		this._slave.teeth = "normal";
		return this._assemble(new App.Medicine.Surgery.Reactions.RemoveCosmeticBraces());
	}
};


code:
App.Medicine.Surgery.Reactions.DentalImplant = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, himself} = getPronouns(slave);
		const r = [];

		r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. ${He}`);
		if (canSee(slave)) {
			r.push(`checks ${himself} in the mirror`);
		} else {
			r.push(`runs ${his} tongue over ${his} teeth`);
		}
		r.push(`repeatedly before accepting that nothing too unusual has happened, and that ${he} now appears to have a fully functional set of normal teeth. Though ${he}'s surprised that nothing outlandish has been done, ${he} carries on as usual. Since the surgery was moderately invasive, ${his} health has been somewhat affected.`);

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.DentalImplant = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Normal dental implants";
	}

	get healthCost() {
		return 10;
	}

	apply(cheat) {
		this._slave.teeth = "normal";
		return this._assemble(new App.Medicine.Surgery.Reactions.Template());
	}
};


code:
App.Medicine.Surgery.Reactions.FangImplant = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him, himself} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw, yet fails to understand that ${his} teeth have changed shape. Since the surgery was moderately invasive, ${his} health has been somewhat affected.`);
		} else if (slave.devotion > 50) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} now has a fang. ${He} seems doubtful,`);
			if (slave.lips <= 50) {
				r.push(`but then closes ${his} mouth and finds that it hangs cutely over ${his} lip. ${He} giggles at the absurdity of it.`);
			} else {
				r.push(`especially when he tries to close ${his} mouth only to find ${his} fat lip keeps meeting the tip of ${his} tooth.`);
			}
			r.push(`Since the surgery was moderately invasive, <span class="health dec">${his} health has been somewhat affected.</span>`);
		} else if (slave.devotion > 20) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} now has a fang. ${He} gasps with shock, but eventually ${his} shoulders slump and ${he} tries to carry on. ${He} isn't much affected mentally. Since the surgery was moderately invasive, ${his} health has been somewhat affected.`);
		} else {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} now has a fang ${He} gasps with shock, accidentally gets ${his} lip in the way in ${his} anguish, bites ${himself}, and starts gagging and spitting blood. The surgical invasion has filled ${him} with horror and anger. Since the surgery was moderately invasive, ${his} health has been somewhat affected. ${He} is terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 10;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.FangImplant = class extends App.Medicine.Surgery.Procedure {
	get name() {
		if (this.originalSlave.teeth === "fangs") {
			return "Remove a fang";
		} else {
			return "Add a fang";
		}
	}

	get healthCost() {
		return 20;
	}

	apply(cheat) {
		this._slave.teeth = "fang";
		return this._assemble(new App.Medicine.Surgery.Reactions.FangImplant());
	}
};


code:
App.Medicine.Surgery.Reactions.FangsImplant = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him, himself} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw, yet fails to understand that ${his} teeth have changed shape. Since the surgery was moderately invasive, ${his} health has been somewhat affected.`);
		} else if (slave.devotion > 50) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} now has a pair of fangs. ${He} seems doubtful, but then works up ${his} courage and bares them`);
			if (canSee(slave)) {
				r.push(`at a mirror.`);
			} else {
				r.push(`so you may see.`);
			}
			r.push(`${He} menaces`);
			if (canSee(slave)) {
				r.push(`${himself}`);
			}
			r.push(`for a while before laughing quietly. Since the surgery was moderately invasive, <span class="health dec">${his} health has been somewhat affected.</span>`);
		} else if (slave.devotion > 20) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} now has teeth fit for a carnivore. ${He} gasps with shock, but eventually ${his} shoulders slump and ${he} tries to carry on. ${He} isn't much affected mentally. Since the surgery was moderately invasive, ${his} health has been somewhat affected.`);
		} else {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} now has a pair of fangs. ${He} gasps with shock, accidentally gets ${his} lip in the way in ${his} anguish, bites ${himself}, and starts gagging and spitting blood. The surgical invasion has filled ${him} with horror and anger. Since the surgery was moderately invasive, ${his} health has been somewhat affected. ${He} is terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 10;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.FangsImplant = class extends App.Medicine.Surgery.Procedure {
	get name() {
		if (this.originalSlave.teeth === "fang") {
			return "Add another fang";
		} else {
			return "Replace them with fangs";
		}
	}

	get healthCost() {
		return 20;
	}

	apply(cheat) {
		this._slave.teeth = "fangs";
		return this._assemble(new App.Medicine.Surgery.Reactions.FangsImplant());
	}
};


code:
App.Medicine.Surgery.Reactions.SharpTeeth = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him, himself} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw, yet fails to understand that ${his} teeth have changed shape. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else if (slave.devotion > 50) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} now has teeth fit for a carnivore. ${He} seems doubtful, but then works up ${his} courage and bares them`);
			if (canSee(slave)) {
				r.push(`at a mirror.`);
			} else {
				r.push(`so you may see.`);
			}
			r.push(`${He} menaces`);
			if (canSee(slave)) {
				r.push(`${himself}`);
			}
			r.push(`for a while before laughing quietly. ${He} has become more submissive due to your radical reshaping of ${his} body. Since the surgery was invasive, ${his} health has been greatly affected.`);
			reaction.devotion += 4;
		} else if (slave.devotion > 20) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} now has teeth fit for a carnivore. ${He} gasps with shock, but eventually ${his} shoulders slump and ${he} tries to carry on. ${He} isn't much affected mentally. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} now has teeth fit for a carnivore. ${He} gasps with shock, accidentally gets ${his} tongue in the way in ${his} anguish, bites ${himself}, and starts gagging and spitting blood. The surgical invasion has filled ${him} with horror and anger. Since the surgery was invasive, ${his} health has been greatly affected. ${He} is terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 10;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.SharpTeeth = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Replace them with sharp teeth";
	}

	get healthCost() {
		return 20;
	}

	apply(cheat) {
		this._slave.teeth = "pointy";
		return this._assemble(new App.Medicine.Surgery.Reactions.SharpTeeth());
	}
};


code:
App.Medicine.Surgery.Reactions.Teeth = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him, himself} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw, yet fails to understand ${his} teeth are now fake. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else if (slave.devotion > 50) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} is wearing prosthetic teeth that ${he} can remove. ${He} gasps with shock, but figures out the idea quickly enough by experimentally`);
			if (hasAnyArms(slave)) {
				r.push(`sucking on two fingers.`);
			} else {
				r.push(`simulating oral sex with ${his} own tongue.`);
			}
			r.push(`${He} has become more submissive due to your radical reshaping of ${his} body. Since the surgery was invasive, ${his} health has been greatly affected.`);
			reaction.devotion += 4;
		} else if (slave.devotion > 20) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} is wearing prosthetic teeth that ${he} can remove. ${He} gasps with shock, but eventually ${his} shoulders slump and ${he} tries to carry on. ${He} isn't much affected mentally. Since the surgery was invasive, ${his} health has been greatly affected.`);
		} else {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} jaw. It takes a good while for ${him} to figure out what has happened, but eventually ${he} gets enough sensation in ${his} mouth to realize that ${he} is wearing prosthetic teeth that ${he} can remove. ${He} gasps with shock, gags, spits out the prosthetics,`);
			if (canSee(slave)) {
				r.push(`looks at ${himself} in the mirror,`);
			} else {
				r.push(`runs ${his} tongue across ${his} empty gums,`);
			}
			r.push(`and sobs. The surgical invasion has filled ${him} with horror and anger. Since the surgery was invasive, ${his} health has been greatly affected. ${He} is terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 10;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.RemovableTeeth = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Replace them with removable prosthetics";
	}

	get healthCost() {
		return 20;
	}

	apply(cheat) {
		this._slave.teeth = "removable";
		return this._assemble(new App.Medicine.Surgery.Reactions.Teeth());
	}
};


code:
App.Medicine.Surgery.Reactions.Electrolarynx = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, but ${he} fails to recall that. ${He} doesn't notice any difference.`);
		} else if (slave.voice === 0) {
			if (slave.devotion > 50) {
				r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, so ${he} knows that ${his} voice has been restored. When you come in to check on ${him} late in the process, though, ${he} does ${his} best to communicate adoration with ${his}`);
				if (canSee(slave)) {
					r.push(`eyes`);
				} else {
					r.push(`face`);
				}
				r.push(`alone. Finally, the accelerated healing process reaches the time when ${he}'s to test ${his} new vocal organs. ${He}`);
				if (canSee(slave)) {
					r.push(`looks at`);
				} else {
					r.push(`turns to`);
				}
				r.push(`you shyly, and`);
				if (hasAnyArms(slave)) {
					r.push(`meekly beckons to you from where ${he}'s still`);
				} else {
					r.push(`meekly mouths a request that you come over to where ${he}'s`);
				}
				r.push(`restrained by the autosurgery. When you're near, ${he} clears ${his} sore throat gingerly and then whispers, "I love you, ${getWrittenTitle(slave)}." ${He} is far more trusting of your plans for ${him} in the future.`);

				reaction.trust += 5;
				reaction.devotion += 5;
			} else if (slave.devotion >= -20) {
				r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, so ${he} knows that ${his} voice has been restored. When you come in to check on ${him} late in the process, though, ${he} does ${his} best to communicate gratitude with ${his}`);
				if (canSee(slave)) {
					r.push(`eyes`);
				} else {
					r.push(`face`);
				}
				r.push(`alone. Finally, the accelerated healing process reaches the time when ${he}'s to test ${his} new vocal organs. ${He}`);
				if (canSee(slave)) {
					r.push(`looks at`);
				} else {
					r.push(`turns to`);
				}
				r.push(`you shyly, and hesitantly`);
				if (hasAnyArms(slave)) {
					r.push(`beckons to you from where ${he}'s still`);
				} else {
					r.push(`mouths a request that you come over to where ${he}'s`);
				}
				r.push(`restrained by the autosurgery. When you're near, ${he} clears ${his} sore throat gingerly and then whispers, "Thank you, ${getWrittenTitle(slave)}." ${He} has a much higher regard for you due to this display of care for ${him}.`);
				reaction.devotion += 10;
			} else {
				r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, so ${he} knows that ${his} voice has been restored. When you come in to check on ${him} late in the process, though, ${he}`);
				if (canSee(slave)) {
					r.push(`stares at`);
				} else {
					r.push(`faces`);
				}
				r.push(`you for a long moment before turning away from you, towards the wall, and beginning to cry quietly. It seems ${he}'s surprised that you would do this for ${him}, and does not understand how to deal with the situation. In any case, ${he} hates you far less than ${he} once did.`);
				reaction.devotion += 10;
			}
		} else {
			if (slave.devotion > 50) {
				r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but it gains strength gradually. While ${he} first believes nothing has changed,`);
				if (canHear(slave)) {
					r.push(`${he} soon notices a slight synthetic tone to ${his} voice and realizes ${he} has been given a mechanical larynx.`);
				} else {
					r.push(`the autosurgery informs ${him} in no uncertain terms that ${he} has implanted with a mechanical larynx.`);
				}
				r.push(`${He} is <span class="devotion inc">appreciative</span> of ${his} new implant, and knowing how much you invested in ${him} makes ${him} <span class="trust inc">trust you more</span> as well.`);
				reaction.devotion += 10;
				reaction.trust += 10;
			} else if (slave.devotion > 20) {
				r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but it gains strength gradually. While ${he} first believes nothing has changed,`);
				if (canHear(slave)) {
					r.push(`${he} soon notices a slight synthetic tone to ${his} voice and realizes ${he} has been given a mechanical larynx.`);
				} else {
					r.push(`the autosurgery informs ${him} in no uncertain terms that ${he} has implanted with a mechanical larynx.`);
				}
				r.push(`${He} has mixed feelings about this development, but ${he}'s aware how valuable such implants are, and ${he} already accepted that you have complete control over ${his} body.`);
				reaction.devotion += 5;
				reaction.trust += 10;
			} else {
				r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but it gains strength gradually. While ${he} first believes nothing has changed,`);
				if (canHear(slave)) {
					r.push(`${he} soon notices a slight synthetic tone to ${his} voice and realizes ${he} has been given a mechanical larynx.`);
				} else {
					r.push(`the autosurgery informs ${him} in no uncertain terms that ${he} has implanted with a mechanical larynx.`);
				}
				r.push(`${He} is <span class="trust dec">disturbed</span> that you replaced ${his} larynx with an artificial one and afraid of increased control over ${him} that such device grants.`);
				reaction.devotion -= 5;
			}
		}
		r.push(`As with all surgery <span class="health dec">${his} health has been slightly affected.</span>`);

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.Electrolarynx = class extends App.Medicine.Surgery.Procedure {
	get name() {
		const {him} = getPronouns(this.originalSlave);
		return `Give ${him} an electrolarynx`;
	}

	get healthCost() {
		return 20;
	}

	apply(cheat) {
		this._slave.electrolarynx = 1;
		this._slave.voice = 2;
		return this._assemble(new App.Medicine.Surgery.Reactions.Electrolarynx());
	}
};


code:
App.Medicine.Surgery.Reactions.Mute = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him, himself} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} larynx. It takes a good while for ${him} to figure out what has happened, but eventually ${he} tries to speak and makes no sound. ${He} simply keeps trying for some time before accepting this is how things are. As with all surgery ${his} health has been slightly affected.`);
		} else if (slave.devotion > 50) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} larynx. It takes a good while for ${him} to figure out what has happened, but eventually ${he} tries to speak and makes no sound. ${He} panics, but manages to control ${himself} at length and begins to think.`);
			if (canSee(slave)) {
				r.push(`Seeing`);
			} else {
				r.push(`Finding`);
			}
			r.push(`you, ${he} tries to ask you for instruction and realizes ${he} cannot.`);
			if (hasBothLegs(slave)) {
				r.push(`After more thought, ${he} simply gets on ${his} knees facing away from you and spreads ${his} buttocks to offer ${himself} to you.`);
			} else {
				r.push(`After more thought, ${he} simply rolls over facing away from you and winks ${his} asshole to offer ${himself} to you.`);
			}
			r.push(`${He} has become more submissive due to your radical reshaping of ${his} being. As with all surgery ${his} health has been slightly affected.`);
			reaction.devotion += 4;
		} else if (slave.devotion > 20) {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} larynx. It takes a good while for ${him} to figure out what has happened, but eventually ${he} tries to speak and makes no sound. ${He} panics, trying to scream or protest but only managing to cry. Eventually ${he} pulls ${himself} together. ${He} will struggle with ${his} medically created disability. As with all surgery ${his} health has been slightly affected. ${He} is terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 10;
		} else {
			r.push(`${He} clearly feels quite normal except for a vague ache around ${his} larynx. It takes a good while for ${him} to figure out what has happened, but eventually ${he} tries to speak and makes no sound. ${He} panics, trying to scream or protest but only managing to cry. As long as ${he} remains unbent to your will, ${he} will have a constant, inescapable reminder of who and what you are. The surgical invasion has filled ${him} with horror and anger. As with all surgery ${his} health has been slightly affected. ${He} is cripplingly afraid of your total power over ${his} body.`);
			reaction.trust -= 20;
			reaction.devotion -= 50;
		}

		reaction.longReaction.push(r);
		return reaction;
	}

	outro(slave, diff, previousReaction) {
		const reaction = super.outro(slave, diff, previousReaction);
		const {He} = getPronouns(slave);

		if (slave.behavioralFlaw === "bitchy") {
			reaction.longReaction.last()
				.push(`<span class="green">${He} can hardly make sharp remarks without a voice.</span>`);
			slave.behavioralFlaw = "none";
		}

		return reaction;
	}
};

App.Medicine.Surgery.Procedures.Mute = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Remove vocal cords";
	}

	get healthCost() {
		return 10;
	}

	apply(cheat) {
		surgeryAmp(this._slave, "voicebox");
		return this._assemble(new App.Medicine.Surgery.Reactions.Mute());
	}
};


code:
App.Medicine.Surgery.Reactions.NewVoice = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, but ${he} fails to recall that. ${He} doesn't notice anything different, though.`);
		} else {
			r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but as it gradually gains strength ${he} notices that it sounds more natural and human than ${his} old electrolarynx.`);
		}
		r.push(`As with all surgery <span class="health dec">${his} health has been slightly affected.</span>`);

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.OFNewVoice = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Replace";
	}

	get description() {
		return "remove electrolarynx and implant organic vocal cords";
	}

	get healthCost() {
		return 20;
	}

	apply(cheat) {
		this._slave.electrolarynx = 0;
		if (this._slave.ovaries === 1 && this._slave.hormoneBalance >= 200) {
			this._slave.voice = 3;
		} else if (this._slave.balls > 0 || this._slave.hormoneBalance < -20) {
			this._slave.voice = 1;
		} else {
			this._slave.voice = 2;
		}

		return this._assemble(new App.Medicine.Surgery.Reactions.NewVoice());
	}
};


code:
App.Medicine.Surgery.Reactions.RestoreVoice = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, but ${he} fails to recall that. ${He} doesn't any effort to speak either, though.`);
		} else if (slave.devotion > 50) {
			r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, so ${he} knows that ${his} voice has been restored. When you come in to check on ${him} late in the process, though, ${he} does ${his} best to communicate adoration with ${his}`);
			if (canSee(slave)) {
				r.push(`eyes`);
			} else {
				r.push(`face`);
			}
			r.push(`alone. Finally, the accelerated healing process reaches the time when ${he}'s to test ${his} new vocal organs. ${He}`);
			if (canSee(slave)) {
				r.push(`looks at`);
			} else {
				r.push(`turns to`);
			}
			r.push(`you shyly, and`);
			if (hasAnyArms(slave)) {
				r.push(`meekly beckons to you from where ${he}'s still`);
			} else {
				r.push(`meekly mouths a request that you come over to where ${he}'s`);
			}
			r.push(`restrained by the autosurgery. When you're near, ${he} clears ${his} sore throat gingerly and then whispers, "I love you, ${getWrittenTitle(slave)}." ${He} is far more trusting of your plans for ${him} in the future.`);

			reaction.trust += 5;
			reaction.devotion += 5;
		} else if (slave.devotion >= -20) {
			r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, so ${he} knows that ${his} voice has been restored. When you come in to check on ${him} late in the process, though, ${he} does ${his} best to communicate gratitude with ${his}`);
			if (canSee(slave)) {
				r.push(`eyes`);
			} else {
				r.push(`face`);
			}
			r.push(`alone. Finally, the accelerated healing process reaches the time when ${he}'s to test ${his} new vocal organs. ${He}`);
			if (canSee(slave)) {
				r.push(`looks at`);
			} else {
				r.push(`turns to`);
			}
			r.push(`you shyly, and hesitantly`);
			if (hasAnyArms(slave)) {
				r.push(`beckons to you from where ${he}'s still`);
			} else {
				r.push(`mouths a request that you come over to where ${he}'s`);
			}
			r.push(`restrained by the autosurgery. When you're near, ${he} clears ${his} sore throat gingerly and then whispers, "Thank you, ${getWrittenTitle(slave)}." ${He} has a much higher regard for you due to this display of care for ${him}.`);
			reaction.devotion += 10;
		} else {
			r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, so ${he} knows that ${his} voice has been restored. When you come in to check on ${him} late in the process, though, ${he}`);
			if (canSee(slave)) {
				r.push(`stares at`);
			} else {
				r.push(`faces`);
			}
			r.push(`you for a long moment before turning away from you, towards the wall, and beginning to cry quietly. It seems ${he}'s surprised that you would do this for ${him}, and does not understand how to deal with the situation. In any case, ${he} hates you far less than ${he} once did.`);
			reaction.devotion += 10;
		}
		r.push(`As with all surgery <span class="health dec">${his} health has been slightly affected.</span>`);

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.OFRestoreVoice = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Implant";
	}

	get healthCost() {
		return 10;
	}

	apply(cheat) {
		if (this._slave.ovaries === 1 && this._slave.hormoneBalance >= 200) {
			this._slave.voice = 3;
		} else if (this._slave.balls > 0 || this._slave.hormoneBalance < -20) {
			this._slave.voice = 1;
		} else {
			this._slave.voice = 2;
		}
		return this._assemble(new App.Medicine.Surgery.Reactions.RestoreVoice());
	}
};


code:
App.Medicine.Surgery.Reactions.VoiceLower = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him, himself, hers} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, but ${he} fails to recall that. ${He} doesn't notice anything different. As with all surgery ${his} health has been slightly affected.`);
		} else if (slave.devotion > 50) {
			r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but it gains strength gradually. It comes out`);
			if (slave.voice === 1) {
				r.push(`far`);
			}
			r.push(`lower and more manly than it was before, and ${he} laughs at ${himself} as ${he} gets used to it. ${He} has become more dominant, since this allows ${him} to think of ${himself} as`);
			if (slave.voice === 1) {
				r.push(`an action movie hero.`);
			} else if (slave.voice === 2) {
				r.push(`a mature career woman.`);
			}
			r.push(`As with all surgery <span class="health dec">${his} health has been slightly affected.</span>`);
			reaction.devotion += 4;
		} else if (slave.devotion > 20) {
			r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but it gains strength gradually. It comes out`);
			if (slave.voice === 1) {
				r.push(`far`);
			}
			r.push(`lower and more manly than it was before, and ${he} laughs grimly at ${himself} as ${he} gets used to it. ${He} carries on regardless, accepting it as one more thing to learn to accept. As with all surgery ${his} health has been slightly affected.`);
		} else {
			r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but it gains strength gradually. It comes out`);
			if (slave.voice === 1) {
				r.push(`far`);
			}
			r.push(`lower and more manly than it was before. For now, <span class="devotion dec">${he} feels this`);
			if (slave.voice === 1) {
				r.push(`gravelly`);
			} else if (slave.voice === 2) {
				r.push(`subdued`);
			}
			r.push(`voice is not ${hers}, a cruel mockery. As with all surgery ${his} health has been slightly affected. ${He} is now terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 5;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.VoiceLower = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Perform surgery to lower voice";
	}

	get healthCost() {
		return 10;
	}

	apply(cheat) {
		this._slave.voice -= 1;
		this._slave.voiceImplant -= 1;
		return this._assemble(new App.Medicine.Surgery.Reactions.VoiceLower());
	}
};


code:
App.Medicine.Surgery.Reactions.VoiceRaise = class extends App.Medicine.Surgery.SimpleReaction {
	reaction(slave, diff) {
		const reaction = super.reaction(slave, diff);
		const {He, he, his, him, himself, hers} = getPronouns(slave);
		const r = [];

		if (slave.fetish === "mindbroken") {
			r.push(`The autosurgery instructed ${him} in no uncertain terms not to speak during recovery, but ${he} fails to recall that. ${He} doesn't notice anything different. As with all surgery ${his} health has been slightly affected.`);
		} else if (slave.devotion > 50) {
			r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but it gains strength gradually. It comes out`);
			if (slave.voice === 3) {
				r.push(`far`);
			}
			r.push(`higher and more girly than it was before, and ${he} laughs at ${himself} as ${he} gets used to it. ${He} has become more submissive, since this helps ${him} to think of ${himself} as a`);
			if (slave.voice === 3) {
				r.push(`bimbo slut.`);
			} else {
				r.push(`real woman.`);
			}
			r.push(`As with all surgery <span class="health dec">${his} health has been slightly affected.</span>`);
			reaction.devotion += 4;
		} else if (slave.devotion > 20) {
			r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but it gains strength gradually. It comes out`);
			if (slave.voice === 3) {
				r.push(`far`);
			}
			r.push(`higher and more girly than it was before, and ${he} laughs grimly at ${himself} as ${he} gets used to it. ${He} carries on regardless, accepting it as one more thing to learn to accept. As with all surgery ${his} health has been slightly affected.`);
		} else {
			r.push(`Before surgery, ${he} was warned repeatedly not to try talking for a while, and ${he} obeys. When ${he} finally does, ${his} voice is raspy and weak, but it gains strength gradually. It comes out`);
			if (slave.voice === 3) {
				r.push(`far`);
			}
			r.push(`higher and more girly than it was before. For now, <span class="devotion dec">${he} feels this`);
			if (slave.voice === 3) {
				r.push(`bimbo`);
			} else {
				r.push(`feminine`);
			}
			r.push(`voice is not ${hers}, a cruel mockery. As with all surgery ${his} health has been slightly affected. ${He} is now terribly afraid of your total power over ${his} body.`);
			reaction.trust -= 10;
			reaction.devotion -= 5;
		}

		reaction.longReaction.push(r);
		return reaction;
	}
};

App.Medicine.Surgery.Procedures.VoiceRaise = class extends App.Medicine.Surgery.Procedure {
	get name() {
		return "Perform surgery to raise voice";
	}

	get healthCost() {
		return 10;
	}

	apply(cheat) {
		this._slave.voice += 1;
		this._slave.voiceImplant += 1;
		return this._assemble(new App.Medicine.Surgery.Reactions.VoiceRaise());
	}
};


code:
App.Medicine.OrganFarm.Organ = class {
	/**
	 * @param {Object} params
	 * @param {string} params.name - display name
	 * @param {string|function(App.Entity.SlaveState):string} [params.tooltip] - full sentence, uncapitalized and unpunctuated
	 * @param {number} params.cost - how much it costs to grow the organ
	 * @param {number} params.time - how long it takes to grow the organ (without upgrades)
	 * @param {function(App.Entity.SlaveState):boolean} [params.canGrow]
	 * @param {string[]} [params.dependencies] - organs that are implanted first if possible, use type of other organs as values
	 * @param {App.Medicine.OrganFarm.OrganImplantAction[]} [params.actions]
	 * @param {boolean} [params.displayMultipleActions=false] allow multiple implant links to be displayed
	 */
	constructor({
		name, tooltip = "", cost, time, canGrow = () => true, dependencies = [],
		displayMultipleActions = false, actions = []
	}) {
		this.name = name;
		this.tooltip = tooltip;
		this.cost = cost;
		this.time = time;
		/** @type {function(App.Entity.SlaveState):boolean} */
		this.canGrow = canGrow;
		/** @type {string[]} */
		this.dependencies = dependencies;
		this.displayMultipleActions = displayMultipleActions;
		/** @type {App.Medicine.OrganFarm.OrganImplantAction[]} */
		this.implantActions = actions;
	}
};

App.Medicine.OrganFarm.OrganImplantAction = class {
	/**
	 * @param {object} params
	 * @param {string} params.name - display name, shown when showing error (otherwise shows procedure name)
	 * @param {typeof App.Medicine.Surgery.Procedure} params.surgeryProcedure - surgery reaction to show
	 * @param {Array} [params.surgeryProcedureParams] - parameters for surgeryProcedure, the slave argument will be added to the front automatically
	 * @param {boolean} [params.autoImplant]
	 * @param {function(App.Entity.SlaveState):boolean} params.canImplant
	 * @param {function(App.Entity.SlaveState):string} params.implantError - message to show if this action cannot be used
	 */
	constructor({
		name,
		surgeryProcedure,
		surgeryProcedureParams = [],
		autoImplant = true,
		canImplant,
		implantError
	}) {
		this.name = name;
		this.surgeryProcedure = surgeryProcedure;
		this.surgeryProcedureParams = surgeryProcedureParams;
		this.autoImplant = autoImplant;
		/**
		 * True if this action can implant the organ
		 * @type {function(App.Entity.SlaveState):boolean}
		 */
		this.canImplant = canImplant;
		/**
		 * Error message if the organ cannot be implanted.
		 * @type {function(App.Entity.SlaveState):string}
		 */
		this.implantError = implantError;
	}
};


code:
App.Medicine.OrganFarm.TesticlesImplantAction = class extends App.Medicine.OrganFarm.OrganImplantAction {
	/**
	 * @param {object} params
	 * @param {string} params.name
	 * @param {boolean} params.animal
	 * @param {typeof App.Medicine.Surgery.Procedure} params.surgeryProcedure
	 * @param {Array} [params.surgeryProcedureParams]
	 * @param {boolean} [params.autoImplant]
	 * @param {function(App.Entity.SlaveState):boolean} params.canImplant
	 * @param {function(App.Entity.SlaveState):string} params.implantError
	 */
	constructor({
		name,
		animal,
		surgeryProcedure,
		surgeryProcedureParams,
		autoImplant = true,
		canImplant,
		implantError,
	}) {
		super({
			name: name,
			surgeryProcedure: surgeryProcedure,
			surgeryProcedureParams: surgeryProcedureParams,
			autoImplant: autoImplant,
			canImplant: s => (!this.animal || V.animalTesticles > 0) && canImplant(s),
			implantError: s => (this.animal && V.animalTesticles === 0) ? "" : implantError(s),
		});
		this.animal = animal;
	}
};

App.Medicine.OrganFarm.Testicles = class extends App.Medicine.OrganFarm.Organ {
	/**
	 * @param {Object} params
	 * @param {string} params.name
	 * @param {FC.AnimalType} params.ballType
	 */
	constructor({name, ballType}) {
		super({
			name: name,
			tooltip: "will add a prostate if one is not already present; requires a penis for successful implantation",
			cost: 5000, time: 10,
			canGrow: () => (this.ballType === "human" || V.animalTesticles > 0), dependencies: ["penis"],
			actions: [
				new App.Medicine.OrganFarm.TesticlesImplantAction({
					name: "Implant", animal: ballType !== "human",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFAddBalls,
					surgeryProcedureParams: [ballType],
					canImplant: slave => (slave.balls <= 0 && slave.dick > 0),
					implantError: slave => {
						if (slave.dick === 0) {
							return "This slave lacks the penis necessary to accept testicles.";
						} else {
							return "This slave already has testicles.";
						}
					},
				}),
				new App.Medicine.OrganFarm.TesticlesImplantAction({
					name: "Implant",
					animal: ballType !== "human", autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFAddTesticles,
					surgeryProcedureParams: [ballType],
					canImplant: slave => (slave.dick === 0 && slave.balls <= 0),
					implantError: slave => ((slave.balls > 0) ? "This slave already has testicles." : ""),
				}),
				new App.Medicine.OrganFarm.TesticlesImplantAction({
					name: "Replace",
					animal: ballType !== "human", autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFReplaceTesticles,
					surgeryProcedureParams: [ballType],
					canImplant: slave => (slave.balls > 0 && slave.ballType !== this.ballType),
					implantError: slave => (slave.balls > 0 ? `This slave already has ${this.ballType} testicles.` : ""),

				})
			]
		});
		this.ballType = ballType;
	}
};

App.Medicine.OrganFarm.OvariesImplantAction = class extends App.Medicine.OrganFarm.OrganImplantAction {
	/**
	 * @param {object} params
	 * @param {string} params.name
	 * @param {boolean} params.animal
	 * @param {typeof App.Medicine.Surgery.Procedure} params.surgeryProcedure
	 * @param {Array} [params.surgeryProcedureParams]
	 * @param {boolean} [params.autoImplant]
	 * @param {function(App.Entity.SlaveState):boolean} params.canImplant
	 * @param {function(App.Entity.SlaveState):string} params.implantError
	 */
	constructor({
		name,
		animal,
		surgeryProcedure,
		surgeryProcedureParams,
		autoImplant = true,
		canImplant,
		implantError
	}) {
		super({
			name: name,
			//healthImpact: 20,
			surgeryType: animal ? "addAnimalOvaries" : "addOvaries", autoImplant: autoImplant,
			surgeryProcedure: surgeryProcedure,
			surgeryProcedureParams: surgeryProcedureParams,
			canImplant: s => (!this.animal || V.animalTesticles > 0) && canImplant(s),
			implantError: s => (this.animal && V.animalTesticles === 0) ? "" : implantError(s),
		});
		this.animal = animal;
	}
};

App.Medicine.OrganFarm.Ovaries = class extends App.Medicine.OrganFarm.Organ {
	/**
	 * @param {object} params
	 * @param {string} params.name
	 * @param {FC.AnimalType} params.eggType
	 * @param {string} params.pregData
	 */
	constructor({name, eggType, pregData}) {
		super({
			name: name, tooltip: "requires a vagina for successful implantation",
			cost: 10000, time: 10,
			canGrow: () => (this.eggType === "human" || V.animalOvaries > 0),
			actions: [
				new App.Medicine.OrganFarm.OvariesImplantAction({
					name: "Implant", animal: eggType !== "human",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFAddOvaries,
					surgeryProcedureParams: [eggType, pregData],
					canImplant: s => (s.vagina >= 0 && s.ovaries <= 0 && s.mpreg === 0 && s.bellyImplant === -1),
					implantError: s => {
						if (s.vagina < 0) {
							return "This slave lacks the vagina necessary to accept ovaries.";
						}
						if (s.ovaries > 0 || s.mpreg > 0) {
							return "This slave already has ovaries.";
						}
						return "This slave's body cavity is filled with another organ.";
					},
				}),
				new App.Medicine.OrganFarm.OvariesImplantAction({
					name: "Replace", animal: eggType !== "human",
					autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFReplaceOvaries,
					surgeryProcedureParams: [eggType, pregData],
					canImplant: s => (s.vagina >= 0 && s.mpreg === 0 && s.bellyImplant === -1 && (s.eggType !== this.eggType || s.preg === -3)),
					implantError: s => (s.eggType === this.eggType) ? `This slave already has ${s.eggType} ovaries.` : "",
				})
			]
		});
		this.eggType = eggType;
		this.pregData = pregData;
	}
};

App.Medicine.OrganFarm.AnalWombImplantAction = class extends App.Medicine.OrganFarm.OrganImplantAction {
	/**
	 * @param {object} params
	 * @param {FC.AnimalType} params.eggType
	 * @param {string} params.pregData
	 */
	constructor({eggType, pregData}) {
		super({
			name: "Implant",
			surgeryProcedure: App.Medicine.Surgery.Procedures.OFAddMPreg,
			surgeryProcedureParams: [],
			canImplant: s => ((this.eggType === "human" || V.animalTesticles > 0) && s.ovaries === 0 && s.vagina <= -1 && s.mpreg === 0 && s.bellyImplant < 0),
			implantError: s => {
				if (this.eggType !== "human" && V.animalTesticles === 0) {
					return "";
				}
				if (s.bellyImplant >= 0) {
					return "This slave has a fillable abdominal implant.";
				}
				return "This slave has existing reproductive Organs.";
			},
		});
		this.eggType = eggType;
		this.pregData = pregData;
	}
};

App.Medicine.OrganFarm.AnalWomb = class extends App.Medicine.OrganFarm.Organ {
	/**
	 * @param {object} params
	 * @param {string} params.name
	 * @param {FC.AnimalType} params.eggType
	 * @param {string} params.pregData
	 */
	constructor({name, eggType, pregData}) {
		super({
			name: name,
			tooltip: "the slave must not have female reproductive organs for successful implantation",
			cost: 20000, time: 10,
			canGrow: () => (V.arcologies[0].FSGenderRadicalistResearch === 1 && (eggType === "human" || V.animalMpreg > 0)),
			actions: [
				new App.Medicine.OrganFarm.AnalWombImplantAction({
					eggType: eggType,
					pregData: pregData
				})
			]
		});
	}
};


code:
/**
 * Organs will usually be displayed in this order.
 *
/** @type {Map<string, App.Medicine.OrganFarm.Organ>} */
App.Medicine.OrganFarm.Organs = new Map([
	["penis",
		new App.Medicine.OrganFarm.Organ({
			name: "Penis", cost: 5000, time: 5,
			canGrow: () => V.seeDicks !== 0 || V.makeDicks === 1,
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFAddDick,
					canImplant: slave => slave.dick <= 0,
					implantError: () => "this slave already has a penis",
				})
			]
		})],
	["testicles",
		new App.Medicine.OrganFarm.Testicles({
			name: "Testicles", ballType: "human"
		})],
	["pigTesticles",
		new App.Medicine.OrganFarm.Testicles({
			name: "Pig testicles", ballType: "pig"
		})],
	["dogTesticles",
		new App.Medicine.OrganFarm.Testicles({
			name: "Dog testicles", ballType: "dog"
		})],
	["horseTesticles",
		new App.Medicine.OrganFarm.Testicles({
			name: "Horse testicles", ballType: "horse"
		})],
	["cowTesticles",
		new App.Medicine.OrganFarm.Testicles({
			name: "Cow testicles", ballType: "cow"
		})],
	["scrotum",
		new App.Medicine.OrganFarm.Organ({
			name: "Scrotum", tooltip: "requires balls for successful implantation", cost: 2500, time: 5,
			dependencies: ["testicles", "pigTesticles", "dogTesticles", "horseTesticles", "cowTesticles"],
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Graft on",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFAddScrotum,
					canImplant: slave => slave.scrotum <= 0 && slave.balls > 0,
					implantError: slave => slave.scrotum > 0 ? "This slave already has a scrotum." : "This slave lacks the balls necessary to accept a scrotum.",
				})
			]
		})],
	["foreskin",
		new App.Medicine.OrganFarm.Organ({
			name: "Foreskin", cost: 2500, time: 5,
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Graft on",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFAddForeskin,
					canImplant: slave => slave.foreskin <= 0,
					implantError: slave => `This slave already has a ${slave.dick > 0 ? "foreskin" : "clitoral hood"}.`,
				})
			]
		})],
	["prostate",
		new App.Medicine.OrganFarm.Organ({
			name: "Prostate", cost: 5000, time: 5,
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFAddProstate,
					canImplant: s => s.prostate === 0,
					implantError: () => "This slave already has a prostate.",
				})
			]
		})],
	["ovaries",
		new App.Medicine.OrganFarm.Ovaries({
			name: "Ovaries", eggType: "human", pregData: "human"
		})],
	["freshOvaries",
		new App.Medicine.OrganFarm.Organ({
			name: "Younger Ovaries",
			tooltip: "requires a womb for successful implantation",
			cost: 10000, time: 10,
			canGrow: () => V.youngerOvaries === 1,
			dependencies: ["ovaries", "pigOvaries", "dogOvaries", "horseOvaries", "cowOvaries", "mpreg", "mpregPig", "mpregDog", "mpregHorse", "mpregCow"],
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFFreshOvaries,
					canImplant: s => (s.mpreg !== 0 || s.ovaries !== 0) && s.bellyImplant === -1 && s.physicalAge < 70,
					implantError: s => s.physicalAge >= 70 ? "This slave's body is too old to handle pregnancy." : "This slave lacks a viable womb.",
				})
			]
		})],
	["asexualReproOvaries",
		new App.Medicine.OrganFarm.Organ({
			name: "Asexual reproduction modification",
			tooltip: "requires existing ovaries for successful implantation",
			cost: 10000, time: 10,
			canGrow: () => V.asexualReproduction === 1,
			dependencies: ["ovaries", "pigOvaries", "dogOvaries", "horseOvaries", "cowOvaries", "mpreg", "mpregPig", "mpregDog", "mpregHorse", "mpregCow"],
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFAsexualReproOvaries,
					canImplant: s => s.mpreg !== 0 || s.ovaries !== 0,
					implantError: () => "This slave lacks ovaries.",
				})
			]
		})],
	["pigOvaries",
		new App.Medicine.OrganFarm.Ovaries({
			name: "Pig ovaries", eggType: "pig", pregData: "pig"
		})],
	["dogOvaries",
		new App.Medicine.OrganFarm.Ovaries({
			name: "Dog ovaries", eggType: "dog", pregData: "canineM",
		})],
	["horseOvaries",
		new App.Medicine.OrganFarm.Ovaries({
			name: "Horse ovaries", eggType: "horse", pregData: "equine",
		})],
	["cowOvaries",
		new App.Medicine.OrganFarm.Ovaries({
			name: "Cow ovaries", eggType: "cow", pregData: "cow"
		})],
	["leftEye",
		new App.Medicine.OrganFarm.Organ({
			name: "Left Eye", cost: 5000, time: 10,
			tooltip: s => getLeftEyeVision(s) === 2 ? "would not improve this slave" : "",
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFNewEyes,
					surgeryProcedureParams: ["left"],
					canImplant: s => getLeftEyeVision(s) === 0 && getBestVision(s) !== 0 && getLeftEyeType(s) !== 2,
					implantError: s => getLeftEyeVision(s) !== 0 ? "Slave has a working left eye." : "",
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFUnblind,
					surgeryProcedureParams: ["left"],
					canImplant: s => getBestVision(s) === 0 && getLeftEyeType(s) !== 2,
					implantError: () => "",
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Replace", autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFNewEyes,
					surgeryProcedureParams: ["left"],
					canImplant: s => getLeftEyeType(s) === 2,
					implantError: () => "",
				})
			]
		})],
	["rightEye",
		new App.Medicine.OrganFarm.Organ({
			name: "Right Eye", cost: 5000, time: 10,
			tooltip: s => getRightEyeVision(s) === 2 ? "would not improve this slave" : "",
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFNewEyes,
					surgeryProcedureParams: ["right"],
					canImplant: s => getRightEyeVision(s) === 0 && getBestVision(s) !== 0 && getRightEyeType(s) !== 2,
					implantError: s => getRightEyeVision(s) !== 0 ? "Slave has a working right eye." : "",
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFUnblind,
					surgeryProcedureParams: ["right"],
					canImplant: s => getBestVision(s) === 0 && getRightEyeType(s) !== 2,
					implantError: () => "",
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Replace", autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFNewEyes,
					surgeryProcedureParams: ["right"],
					canImplant: s => getRightEyeType(s) === 2,
					implantError: () => "",
				})
			]
		})],
	["ears",
		new App.Medicine.OrganFarm.Organ({
			name: "Normal Ears", cost: 1000, time: 2,
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Attach",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFImplantEars,
					canImplant: s => s.earShape === "none",
					implantError: () => "This slave already has ears."
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Replace",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFImplantEars,
					autoImplant: false,
					canImplant: s => s.earShape !== "normal",
					implantError: () => "This slave already has normal ears."
				})
			]
		})],
	["topEars",
		new App.Medicine.OrganFarm.Organ({
			name: "Top Ears", cost: 1000, time: 2,
			canGrow: () => V.surgeryUpgrade >= 1,
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Attach",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFImplantTopEars,
					canImplant: s => s.earT === "none",
					implantError: () => "This slave already has ears at the top of the head."
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Replace",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFImplantTopEars,
					autoImplant: false,
					canImplant: s => s.earT !== "normal",
					implantError: () => "This slave already has normal ears at the top of the head."
				})
			]
		})],
	["cochleae",
		new App.Medicine.OrganFarm.Organ({
			name: "Cochleae", cost: 8000, time: 6,
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFUndeafen,
					canImplant: s => s.hears <= -2 && s.earImplant === 0,
					implantError: () => "This slave already has working ears.",
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Replace", autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFNewEars,
					canImplant: s => s.earImplant === 1,
					implantError: () => "",
				})
			]
		})],
	["voicebox",
		new App.Medicine.OrganFarm.Organ({
			name: "Vocal Cords", cost: 5000, time: 5,
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Implant",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFRestoreVoice,
					canImplant: s => s.voice === 0 && s.electrolarynx === 0,
					implantError: () => "This slave is not mute.",
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Replace", autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFNewVoice,
					canImplant: s => s.electrolarynx === 1,
					implantError: () => "",
				})
			]
		})],
	["hair",
		new App.Medicine.OrganFarm.Organ({
			name: "Hair Follicles", cost: 500, time: 2, displayMultipleActions: true,
			actions: [
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Scalp",
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFRestoreHairHead,
					canImplant: s => s.bald !== 0,
					implantError: () => "This slave already has hair.",
				}),
				/* So apparently hair is tracked via the .earTColor variable with no differential between possible hair origin. Not worth the variable, currently.
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Ears", healthImpact: 5,
					surgeryType: "addHairEarsH", autoImplant: false,
					canImplant: s => (s.earTShape !== "normal"),
					implantError: "",
					implant: s => {
						s.earTColor = getGeneticHairColor(s);
					}
				}),
				*/
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Brow", autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFRestoreHairBrow,
					canImplant: s => s.eyebrowHStyle === "bald",
					implantError: () => "",
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Axillary", autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFRestoreHairPits,
					canImplant: s => s.underArmHStyle === "bald" || s.underArmHStyle === "hairless",
					implantError: () => "",
				}),
				new App.Medicine.OrganFarm.OrganImplantAction({
					name: "Pubic", autoImplant: false,
					surgeryProcedure: App.Medicine.Surgery.Procedures.OFRestoreHairPubes,
					canImplant: s => s.pubicHStyle === "bald" || s.pubicHStyle === "hairless",
					implantError: () => "",
				})
			]
		})],
	["mpreg",
		new App.Medicine.OrganFarm.AnalWomb({
			name: "Anal womb and ovaries", eggType: "human", pregData: "human",
		})],
	["mpregPig",
		new App.Medicine.OrganFarm.AnalWomb({
			name: "Anal pig womb and ovaries", eggType: "pig", pregData: "pig",
		})],
	["mpregDog",
		new App.Medicine.OrganFarm.AnalWomb({
			name: "Anal dog womb and ovaries", eggType: "dog", pregData: "canineM",
		})],
	["mpregHorse",
		new App.Medicine.OrganFarm.AnalWomb({
			name: "Anal horse womb and ovaries", eggType: "horse", pregData: "equine",
		})],
	["mpregCow",
		new App.Medicine.OrganFarm.AnalWomb({
			name: "Anal cow womb and ovaries", eggType: "cow", pregData: "cow",
		})],
]);


code:
/**
 * generate two independent Gaussian numbers using Box-Muller transform.
 * mean and deviation specify the desired mean and standard deviation.
 * @param {number} [mean]
 * @param {number} [deviation]
 * @returns {number[]}
 */
function gaussianPair(mean = 0, deviation = 1) {
	const r = Math.sqrt(-2.0 * Math.log(1 - Math.random()));
	const sigma = 2.0 * Math.PI * (1 - Math.random());
	return [r * Math.cos(sigma), r * Math.sin(sigma)].map(val => val * deviation + mean);
}

/**
 * Generate a random integer with a normal distribution between min and max (both inclusive).
 * Default parameters result in truncating the standard normal distribution between -3 and +3.
 * Not specifying min/max results in rerolling val approximately 0.3% of the time.
 * @param {number} [mean]
 * @param {number} [deviation]
 * @param {number} [min]
 * @param {number} [max]
 * @returns {number}
 */
/* exported normalRandInt */
function normalRandInt(mean = 0, deviation = 1, min = mean - 3 * deviation, max = mean + 3 * deviation) {
	let val = gaussianPair(mean, deviation)[0];
	while (val < min || val > max) {
		val = gaussianPair(mean, deviation)[0];
	}
	return Math.round(val);
}

/**
 * Returns a random integer between min and max (both inclusive).
 * If count is defined, chooses that many random numbers between min and max and returns the average. This is an approximation of a normal distribution.
 * @param {number} min
 * @param {number} max
 * @param {number} [count]
 * @returns {number}
 */
/* exported jsRandom */
function jsRandom(min, max, count = 1) {
	function rand() {
		return Math.random() * (max - min + 1) + min;
	}

	if (count === 1) {
		return Math.floor(rand());
	}

	let total = 0;
	for (let i = 0; i < count; i++) {
		total += rand();
	}
	return Math.floor(total / count);
}

/**
 * Chooses multiple random elements of an array.
 * @template {*} T
 * @param {Array<T>} arr
 * @param {number} count
 * @returns {Array<T>}
 */
/* exported jsRandomMany */
function jsRandomMany(arr, count) {
	let result = [];
	let tmp = arr.slice();
	for (let i = 0; i < count; i++) {
		let index = Math.floor(Math.random() * tmp.length);
		result.push(tmp.splice(index, 1)[0]);
	}
	return result;
}

/**
 * Accepts both an array and a list, returns undefined if nothing is passed.
 * @template {*} T
 * @param {Array<T>} choices
 * @param {...T} [otherChoices]
 * @returns {T}
 */
/* exported jsEither */
function jsEither(choices, ...otherChoices) {
	if (otherChoices.length === 0 && Array.isArray(choices)) {
		return choices[Math.floor(Math.random() * choices.length)];
	}
	const allChoices = otherChoices;
	allChoices.push(...choices);
	return allChoices[Math.floor(Math.random() * allChoices.length)];
}