code:
/** Update custom slave orders (customSlave/huskSlave).
 * @param {App.Entity.CustomSlaveOrder} customSlaveOrder
 */
App.Update.CustomSlaveOrder = function(customSlaveOrder) {
	if (!customSlaveOrder.hasOwnProperty("leg")) {
		if (jsDef(customSlaveOrder.amp) && customSlaveOrder.amp === 1) {
			customSlaveOrder.leg = {left: null, right: null};
		} else {
			customSlaveOrder.leg = {left: new App.Entity.LimbState(), right: new App.Entity.LimbState()};
		}
	}

	if (!customSlaveOrder.hasOwnProperty("arm")) {
		if (jsDef(customSlaveOrder.amp) && customSlaveOrder.amp === 1) {
			customSlaveOrder.arm = {left: null, right: null};
		} else {
			customSlaveOrder.arm = {left: new App.Entity.LimbState(), right: new App.Entity.LimbState()};
		}
	}

	if (customSlaveOrder.hasOwnProperty("amp")) {
		delete customSlaveOrder.amp;
	}

	if (!customSlaveOrder.hasOwnProperty("skill")) {
		customSlaveOrder.skill = {whore: 15, combat: 0};
	}

	if (customSlaveOrder.hasOwnProperty("whoreSkills")) {
		customSlaveOrder.skill.whore = customSlaveOrder.whoreSkills;
		delete customSlaveOrder.whoreSkills;
	}

	if (customSlaveOrder.hasOwnProperty("combatSkills")) {
		customSlaveOrder.skill.combat = customSlaveOrder.combatSkills;
		delete customSlaveOrder.combatSkills;
	}

	if (V.releaseID < 1059) {
		customSlaveOrder.eye = new App.Entity.EyeState();
		delete customSlaveOrder.eyes;
	}
};

license: mit


code:
App.Update.Slave = function(slave) {

	slave.geneticQuirks = Object.assign({macromastia: 0, gigantomastia: 0, fertility: 0, hyperFertility: 0, superfetation: 0, gigantism: 0, dwarfism: 0, pFace: 0, uFace: 0, albinism: 0, heterochromia: 0, rearLipedema: 0, wellHung: 0, wGain: 0, wLoss: 0, mGain: 0, mLoss: 0, androgyny: 0, girlsOnly: 0}, slave.geneticQuirks);

	WombInit(slave);

	if (slave.earShape === undefined) { slave.earShape = "normal"; }
	if (slave.earT === undefined) { slave.earT = "none"; }
	if (slave.earTColor === undefined) { slave.earTColor = "hairless"; }
	if (slave.horn === undefined) { slave.horn = "none"; }
	if (slave.hornColor === undefined) { slave.hornColor = "none"; }
	if (slave.tail === undefined) { slave.tail = "none"; }
	if (slave.tailShape === undefined) { slave.tailShape = "none"; }
	if (slave.tailColor === undefined) { slave.tailColor = "none"; }
	if (slave.prostateImplant !== undefined) {
		if (slave.prostateImplant === 1) {
			slave.prostate = 3;
		}
		delete slave.prostateImplant;
	}
	if (slave.daughters === undefined) { slave.daughters = 0; }
	if (slave.sisters === undefined) { slave.sisters = 0; }
	if (slave.pregGenerator !== undefined) { delete slave.pregGenerator; }
	if (slave.pregAdaptation === undefined) {
		if (slave.physicalAge <= 3) {
			slave.pregAdaptation = 10;
		} else if (slave.physicalAge <= 12 || slave.genes === "XY") {
			slave.pregAdaptation = 20;
		} else if (slave.physicalAge <= 17) {
			slave.pregAdaptation = 30;
		} else {
			slave.pregAdaptation = 50;
		}
	}
	if (slave.pregKnown === undefined) {
		if (slave.preg > 0) {
			slave.pregKnown = 1;
		} else {
			slave.pregKnown = 0;
		}
	}
	if (slave.pregWeek === undefined) {
		if (slave.preg > 0) {
			slave.pregWeek = slave.preg;
		} else {
			slave.pregWeek = 0;
		}
	}
	if (slave.pubertyXX === undefined) {
		if (slave.physicalAge >= slave.pubertyAgeXX) {
			slave.pubertyXX = 1;
			slave.fertKnown = 1;
		} else {
			slave.pubertyXX = 0;
			slave.fertKnown = 0;
		}
	}
	if (slave.pubertyXY === undefined) {
		if (slave.physicalAge >= slave.pubertyAgeXY) {
			slave.pubertyXY = 1;
		} else {
			slave.pubertyXY = 0;
		}
	}
	if (slave.genetics === undefined) { slave.genetics = {}; }
	if (slave.geneMods === undefined) { geneMods = {NCS: 0, rapidCellGrowth: 0}; }
	if (slave.inducedNCS !== undefined) {
		slave.geneMods.NCS = slave.inducedNCS;
		delete slave.inducedNCS;
	}
	if (slave.PCSlutContacts !== undefined) { delete slave.PCSlutContacts; }
	if (slave.wombImplant === undefined) { slave.wombImplant = "none"; }
	if (slave.superfetation !== undefined) { delete slave.superfetation; }
	if (slave.lactationDuration === undefined) {
		if (slave.lactation === 0) {
			slave.lactationDuration = 0;
		} else {
			slave.lactationDuration = 2;
		}
	}
	if (slave.induceLactation === undefined) { slave.induceLactation = 0; }
	if (slave.weightDirection === undefined) { slave.weightDirection = 0; }
	if (V.releaseID < 1036) {
		for (let pmw = 0; pmw < slave.womb.length; pmw++) {
			if (slave.womb[pmw].genetics.mother !== slave.womb[pmw].motherID || slave.womb[pmw].genetics.father !== slave.womb[pmw].fatherID) {
				slave.womb[pmw].genetics = generateGenetics(slave, slave.womb[pmw].fatherID, pmw);
			}
		}
	}
	if (slave.clone === undefined) { slave.clone = 0; }
	if (slave.abortionTat === undefined) { slave.abortionTat = -1; }
	if (slave.birthsTat === undefined) { slave.birthsTat = -1; }
	if (slave.reservedChildren !== undefined) { delete slave.reservedChildren; }
	if (slave.origin !== undefined && slave.origin !== 0) { slave.origin = pronounReplacer(slave.origin); }
	if (slave.custom !== undefined) {
		if (slave.custom.desc !== undefined && slave.custom.desc !== "") {
			slave.custom.desc = pronounReplacer(slave.custom.desc);
		}
		if (slave.custom.tattoo !== undefined && slave.custom.tattoo !== "") {
			slave.custom.tattoo = pronounReplacer(slave.custom.tattoo);
		}
	}
	if (slave.prestigeDesc !== undefined && slave.prestigeDesc !== 0) { slave.prestigeDesc = pronounReplacer(slave.prestigeDesc); }
	if (slave.pornPrestigeDesc !== undefined && slave.pornPrestigeDesc !== 0) { // This must be defined first, hence the previous line.
		if (V.releaseID < 1050 && slave.prestigeDesc !== undefined && slave.prestigeDesc !== 0) { /* BC absolutely FUCKED this */
			const genre = App.Porn.getGenreByFameName(slave.pornFameType);
			if (jsDef(genre)) {
				if (slave.pornPrestige === 1) {
					slave.pornPrestigeDesc = `$He has a following in slave pornography. ${genre.prestigeDesc1}.`;
				} else if (slave.pornPrestige === 2) {
					slave.pornPrestigeDesc = `$He is well known from $his career in slave pornography. ${genre.prestigeDesc2}.`;
				} else if (slave.pornPrestige === 3) {
					slave.pornPrestigeDesc = `$He is world famous for $his career in slave pornography. ${genre.prestigeDesc3}.`;
				} else {
					slave.pornPrestigeDesc = 0;
				}
			} else {
				slave.pornPrestigeDesc = 0;
			}
		} else {
			slave.pornPrestigeDesc = pronounReplacer(slave.pornPrestigeDesc);
		}
	}

	if (slave.amp !== undefined) {
		if (slave.amp === 1) {
			slave.arm = {left: null, right: null};
			slave.leg = {left: null, right: null};
		} else {
			const newID = ((slave.amp * -1) + 1);
			slave.arm = {
				left: new App.Entity.LimbState(),
				right: new App.Entity.LimbState()
			};
			slave.leg = {
				left: new App.Entity.LimbState(),
				right: new App.Entity.LimbState()
			};
			slave.arm.left.type = newID;
			slave.arm.right.type = newID;
			slave.leg.left.type = newID;
			slave.leg.right.type = newID;
			/* no need to check partial amputation, since it is not possible to create prior to this */
		}
		delete slave.amp;
		delete slave.missingLegs;
		delete slave.missingArms;
	} else if (slave.arm === undefined) {
		slave.arm = {
			left: new App.Entity.LimbState(),
			right: new App.Entity.LimbState()
		};
		slave.leg = {
			left: new App.Entity.LimbState(),
			right: new App.Entity.LimbState()
		};
	}

	if (hasAnyProstheticLimbs(slave)) {
		slave.PLimb = 1;
		if (getLimbCount(slave, 6) > 0) {
			slave.PLimb = 2;
		}
	}

	if (slave.eyeball !== undefined) { delete slave.eyeball; }

	if (slave.auricle !== undefined) { delete slave.auricle; }

	if (slave.readyProsthetics === undefined) { slave.readyProsthetics = []; }
	if (slave.readyLimbs !== undefined) {
		for (let k = 0; k < slave.readyLimbs.length; k++) {
			switch (slave.readyLimbs[k].type) {
				case -1:
					addProsthetic(slave, "basicL");
					break;
				case -2:
					addProsthetic(slave, "sexL");
					break;
				case -3:
					addProsthetic(slave, "beautyL");
					break;
				case -4:
					addProsthetic(slave, "combatL");
					break;
				case -5:
					addProsthetic(slave, "cyberneticL");
					break;
			}
		}
	}

	if (V.releaseID < 1052) {
		const prosthetics = slave.readyProsthetics;
		slave.readyProsthetics = [];
		for (const p of prosthetics) {
			addProsthetic(slave, p.id);
		}
	}

	if (V.releaseID < 1058) {
		if (slave.albinism === 2) {
			let temp;
			temp = slave.origSkin;
			slave.origSkin = slave.albinismOverride.skin;
			slave.albinismOverride.skin = temp;
			temp = slave.origEye;
			slave.origEye = slave.albinismOverride.eyeColor;
			slave.albinismOverride.eyeColor = temp;
			temp = slave.origHColor;
			slave.origHColor = slave.albinismOverride.hColor;
			slave.albinismOverride.hColor = temp;
		}
	}

	if (V.releaseID < 1059) {
		slave.eye = new App.Entity.EyeState();
		setGeneticEyeColor(slave, slave.origEye);
		if (slave.eyes === -4) {
			eyeSurgery(slave, "both", "remove");
		} else {
			if (slave.eyesImplant === 1) {
				eyeSurgery(slave, "both", "cybernetic");
			}
			if (slave.eyes === -3) {
				eyeSurgery(slave, "both", "glass");
			} else if (slave.eyes === -2) {
				eyeSurgery(slave, "both", "blind");
			} else if (slave.eyes === -1) {
				eyeSurgery(slave, "both", "blur");
			}
			setEyeColorFull(slave, slave.eyeColor, slave.pupil, slave.sclerae, "both");
			if (typeof slave.geneticQuirks.heterochromia === "string") {
				setEyeColor(slave.geneticQuirks.heterochromia, "left");
			}
		}
		delete slave.eyes;
		delete slave.eyesImplant;
		delete slave.eyeColor;
		delete slave.origEye;
		delete slave.pupil;
		delete slave.sclerae;
	}

	if (slave.eyes !== undefined) {delete slave.eyes;}
	if (slave.eyeColor !== undefined) {delete slave.eyeColor;}
	if (slave.eyesImplant !== undefined) {delete slave.eyesImplant;}
	if (slave.origEye !== undefined) {delete slave.origEye;}
	if (slave.pupil !== undefined) {delete slave.pupil;}
	if (slave.sclerae !== undefined) {delete slave.sclerae;}

	if (slave.origin === "Shortly after birth, $he was sealed in an aging tank until $he was of age. $He knows only of the terror that awaits $him should $he not obey $his master.") {
		slave.tankBaby = 2;
	} else if (slave.origin === "Shortly after birth, $he was sealed in an aging tank until $he was of age. $He knows nothing of the world outside of what the tank imprinted $him with.") {
		slave.tankBaby = 1;
	} else if (slave.tankBaby === undefined) {
		slave.tankBaby = 0;
	}

	if (slave.origin === "$He sold $himself into slavery to feed $himself and $his growing brood.") {
		if (slave.pregAdaptation < 750) {
			slave.pregAdaptation = 750;
		}
	}

	let backwardsCompatibility;
	if (slave.rivalry !== 0) {
		backwardsCompatibility = V.slaveIndices[slave.rivalryTarget];
		if (backwardsCompatibility === undefined) {
			slave.rivalry = 0;
			slave.rivalryTarget = 0;
		}
	}
	if (slave.relationship > 0) {
		backwardsCompatibility = V.slaveIndices[slave.relationshipTarget];
		if (backwardsCompatibility === undefined) {
			slave.relationship = 0;
			slave.relationshipTarget = 0;
		}
	}
	if (V.familyTesting === 0 && slave.relation !== 0) {
		backwardsCompatibility = V.slaveIndices[slave.relationTarget];
		if (backwardsCompatibility === undefined) {
			slave.relation = 0;
			slave.relationTarget = 0;
		}
	}

	if (slave.race === "surgically altered to look amerindian") {
		slave.race = "amerindian";
	} else if (slave.race === "surgically altered to look asian") {
		slave.race = "asian";
	} else if (slave.race === "surgically altered to look black") {
		slave.race = "black";
	} else if (slave.race === "surgically altered to look indo-aryan") {
		slave.race = "indo-aryan";
	} else if (slave.race === "surgically altered to look latina") {
		slave.race = "latina";
	} else if (slave.race === "surgically altered to look malay") {
		slave.race = "malay";
	} else if (slave.race === "surgically altered to look middle eastern") {
		slave.race = "middle eastern";
	} else if (slave.race === "surgically altered to look mixed race" || slave.race === "surgically altered to look mixed") {
		slave.race = "mixed race";
	} else if (slave.race === "surgically altered to look pacific islander" || slave.race === "surgically altered to look like a pacific islander") {
		slave.race = "pacific islander";
	} else if (slave.race === "surgically altered to look southern european" || slave.race === "southern European") {
		slave.race = "southern european";
	} else if (slave.race === "surgically altered to look semitic") {
		slave.race = "semitic";
	} else if (slave.race === "surgically altered to look white") {
		slave.race = "white";
	}

	/* eslint-disable camelcase */
	if (slave.override_Race === undefined) { slave.override_Race = 0; }
	if (slave.override_Skin === undefined) { slave.override_Skin = 0; }
	if (slave.override_Eye_Color === undefined) { slave.override_Eye_Color = 0; }
	if (slave.override_H_Color === undefined) { slave.override_H_Color = 0; }
	if (slave.override_Pubic_H_Color === undefined) { slave.override_Pubic_H_Color = 0; }
	if (slave.override_Arm_H_Color === undefined) { slave.override_Arm_H_Color = 0; }
	/* eslint-enable camelcase */

	switch (slave.skin) {
		case "red dyed":
			slave.skin = "dyed red";
			break;
		case "green dyed":
			slave.skin = "dyed green";
			break;
		case "blue dyed":
			slave.skin = "dyed blue";
			break;
		case "tanned":
			slave.skin = "tan";
			break;
		case "lightened":
			slave.skin = "light";
			break;
		case "bronzed":
			slave.skin = "bronze";
			break;
		case "darkened":
			slave.skin = "dark";
			break;
	}

	switch (slave.origSkin) {
		case "blue dyed":
		case "dyed blue":
		case "dyed green":
		case "dyed red":
		case "green dyed":
		case "red dyed":
			slave.origSkin = randomRaceSkin(slave.origRace);
			break;
		case "tanned":
			slave.origSkin = "tan";
			break;
		case "lightened":
			slave.origSkin = "light";
			break;
		case "bronzed":
			slave.origSkin = "bronze";
			break;
		case "darkened":
			slave.origSkin = "dark";
			break;
	}

	if (slave.markings === "heavily") {
		slave.markings = "heavily freckled";
	} else if (slave.markings === "beauty") {
		slave.markings = "beauty mark";
	}

	if (slave.genes === undefined) {
		if (slave.ovaries === 1) {
			slave.genes = "XX";
		} else {
			slave.genes = "XY";
		}
	}

	if (V.releaseID < 1000) {
		if (slave.face === -3) {
			slave.face = -100;
		} else if (slave.face === -2) {
			slave.face = -50;
		} else if (slave.face === -1) {
			slave.face = -20;
		} else if (slave.face === 0) {
			slave.face = 0;
		} else if (slave.face === 1) {
			slave.face = 20;
		} else if (slave.face === 2) {
			slave.face = 50;
		} else {
			slave.face = 100;
		}
	}
	if (V.releaseID < 1031) {
		if (slave.intelligence === -3) {
			slave.intelligence = -100;
		} else if (slave.intelligence === -2) {
			slave.intelligence = -60;
		} else if (slave.intelligence === -1) {
			slave.intelligence = -30;
		} else if (slave.intelligence === 0) {
			slave.intelligence = 0;
		} else if (slave.intelligence === 1) {
			slave.intelligence = 30;
		} else if (slave.intelligence === 2) {
			slave.intelligence = 60;
		} else {
			slave.intelligence = 99;
		}
		if (slave.intelligenceImplant === 1) {
			slave.intelligenceImplant = 30;
		}
	}

	if (slave.teeth === 0) {
		slave.teeth = "normal";
	} else if (slave.teeth === "straightening") {
		slave.teeth = "straightening braces";
	} else if (slave.teeth === "cosmetic") {
		slave.teeth = "cosmetic braces";
	}

	if (slave.areolaeShape === undefined) {
		if (slave.areolae === 4) {
			slave.areolaeShape = "heart";
			slave.areolae = 3;
		} else if (slave.areolae === 5) {
			slave.areolaeShape = "star";
			slave.areolae = 3;
		} else {
			slave.areolaeShape = "circle";
		}
	}

	if (V.releaseID < 1059) {
		if (slave.eyeColor === undefined) {
			slave.eyeColor = slave.eyes;
			slave.eyes = 1;
			if (slave.eyeColor === undefined) {
				slave.eyeColor = "brown";
			}
		}

		if (slave.pupil === undefined) {
			if (slave.eyeColor === "catlike") {
				slave.pupil = "catlike";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "serpent-like") {
				slave.pupil = "serpent-like";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "devilish") {
				slave.pupil = "devilish";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "demonic") {
				slave.pupil = "demonic";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "hypnotic") {
				slave.pupil = "hypnotic";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "heart-shaped") {
				slave.pupil = "heart-shaped";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "wide-eyed") {
				slave.pupil = "wide-eyed";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "almond-shaped") {
				slave.pupil = "almond-shaped";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "bright") {
				slave.pupil = "bright";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "teary") {
				slave.pupil = "teary";
				slave.eyeColor = "brown";
			} else if (slave.eyeColor === "vacant") {
				slave.pupil = "vacant";
				slave.eyeColor = "brown";
			} else {
				slave.pupil = "circular";
			}
		}
	}

	if (slave.pitkills !== undefined) { delete slave.pitkills; }
	if (slave.penetrationCount !== undefined) { delete slave.penetrationCount; }
	if (slave.oralTotal !== undefined) { delete slave.oralTotal; }
	if (slave.vaginaCount !== undefined) { delete slave.vaginaCount; }

	if (((V.ver.startsWith("0.6") && !V.ver.startsWith("10.6")) || (V.ver.startsWith("0.7")) || (V.ver.startsWith("0.8"))) && (!V.ver.startsWith("0.8.9")) && (!V.ver.startsWith("0.8.10")) && (!V.ver.startsWith("0.8.11")) && (!V.ver.startsWith("0.8.12"))) {
		if (slave.attrXX === 2) {
			slave.attrXX = 90;
		} else if (slave.attrXX === 1) {
			slave.attrXX = 70;
		} else if (slave.attrXX === 0) {
			slave.attrXX = 50;
		} else if (slave.attrXX === -1) {
			slave.attrXX = 30;
		} else {
			slave.attrXX = 10;
		}
		if (slave.attrXY === 2) {
			slave.attrXY = 90;
		} else if (slave.attrXY === 1) {
			slave.attrXY = 70;
		} else if (slave.attrXY === 0) {
			slave.attrXY = 50;
		} else if (slave.attrXY === -1) {
			slave.attrXY = 30;
		} else {
			slave.attrXY = 10;
		}
	}

	if ((V.ver.startsWith("0.6") && !V.ver.startsWith("10.6")) || (V.ver.startsWith("0.7")) || (V.ver.startsWith("0.8"))) {
		if (slave.health <= -9) {
			slave.health = -90;
		} else if (slave.health <= -7) {
			slave.health = jsRandom(-89, -70);
		} else if (slave.health <= -5) {
			slave.health = jsRandom(-69, -50);
		} else if (slave.health <= -3) {
			slave.health = jsRandom(-49, -30);
		} else if (slave.health <= -1) {
			slave.health = jsRandom(-29, -10);
		} else if (slave.health <= 1) {
			slave.health = jsRandom(-9, 10);
		} else if (slave.health <= 3) {
			slave.health = jsRandom(11, 30);
		} else if (slave.health <= 5) {
			slave.health = jsRandom(31, 50);
		} else if (slave.health <= 7) {
			slave.health = jsRandom(51, 70);
		} else if (slave.health <= 8) {
			slave.health = jsRandom(71, 80);
		} else if (slave.health <= 9) {
			slave.health = jsRandom(81, 90);
		} else if (slave.health <= 10) {
			slave.health = jsRandom(91, 100);
		} else if (slave.health <= 15) {
			slave.health = jsRandom(101, 150);
		} else if (slave.health <= 20) {
			slave.health = jsRandom(151, 200);
		} else if (slave.health >= 50) {
			slave.health = 500;
		} else if (slave.health > 20) {
			slave.health = 205;
		}

		slave.devotion = (slave.devotion * 5);
		slave.oldDevotion = (slave.oldDevotion * 5);
		slave.trust = (slave.trust * 5);
		slave.oldTrust = (slave.oldTrust * 5);

		if (slave.fetishStrength === 0) {
			slave.fetishStrength = jsRandom(0, 60);
		} else if (slave.fetishStrength === 1) {
			slave.fetishStrength = jsRandom(61, 80);
		} else if (slave.fetishStrength === 2) {
			slave.fetishStrength = jsRandom(96, 100);
		}

		if (slave.weight === -3) {
			slave.weight = jsRandom(-110, -96);
		} else if (slave.weight === -2) {
			slave.weight = jsRandom(-95, -31);
		} else if (slave.weight === -1) {
			slave.weight = jsRandom(-30, -11);
		} else if (slave.weight === 0) {
			slave.weight = jsRandom(-11, 10);
		} else if (slave.weight === 1) {
			slave.weight = jsRandom(11, 30);
		} else if (slave.weight === 2) {
			slave.weight = jsRandom(31, 95);
		} else if (slave.weight === 3) {
			slave.weight = jsRandom(96, 110);
		}

		if (slave.lips !== 0) {
			if (slave.lips === 3) {
				slave.lips = 85;
			} else if (slave.lips === 2) {
				slave.lips = 55;
			} else if (slave.lips === 1) {
				slave.lips = 35;
			}
		}
	}

	if (((V.ver.startsWith("0.6") && !V.ver.startsWith("10.6")) || (V.ver.startsWith("0.7")) || (V.ver.startsWith("0.8")) || (V.ver.startsWith("0.9"))) && (!V.ver.startsWith("0.9.5")) && (!V.ver.startsWith("0.9.6")) && (!V.ver.startsWith("0.9.7")) && (!V.ver.startsWith("0.9.8")) && (!V.ver.startsWith("0.9.9")) && (!V.ver.startsWith("0.9.10"))) {
		if (slave.skill === undefined) {
			if (slave.oralSkill > 0) {
				if (slave.oralSkill === 3) {
					slave.oralSkill = 100;
				} else if (slave.oralSkill === 2) {
					slave.oralSkill = 65;
				} else {
					slave.oralSkill = 35;
				}
			}
			if (slave.vaginalSkill > 0) {
				if (slave.vaginalSkill === 3) {
					slave.vaginalSkill = 100;
				} else if (slave.vaginalSkill === 2) {
					slave.vaginalSkill = 65;
				} else {
					slave.vaginalSkill = 35;
				}
			}
			if (slave.analSkill > 0) {
				if (slave.analSkill === 3) {
					slave.analSkill = 100;
				} else if (slave.analSkill === 2) {
					slave.analSkill = 65;
				} else {
					slave.analSkill = 35;
				}
			}
			if (slave.whoreSkill > 0) {
				if (slave.whoreSkill === 3) {
					slave.whoreSkill = 100;
				} else if (slave.whoreSkill === 2) {
					slave.whoreSkill = 65;
				} else {
					slave.whoreSkill = 35;
				}
			}
			if (slave.entertainSkill > 0) {
				if (slave.entertainSkill === 3) {
					slave.entertainSkill = 100;
				} else if (slave.entertainSkill === 2) {
					slave.entertainSkill = 65;
				} else {
					slave.entertainSkill = 35;
				}
			}
		}

		if (V.ver !== "0.9.4") {
			slave.aphrodisiacs = 0;
			if (slave.drugs === "curatives") {
				slave.curatives = 2;
				slave.drugs = "no drugs";
			} else if (slave.drugs === "preventatives") {
				slave.curatives = 1;
				slave.drugs = "no drugs";
			} else if (slave.drugs === "aphrodisiacs") {
				slave.aphrodisiacs = 1;
				slave.drugs = "no drugs";
			} else if (slave.drugs === "extreme aphrodisiacs") {
				slave.aphrodisiacs = 2;
				slave.drugs = "no drugs";
			}
			if (slave.muscles >= 3) {
				slave.muscles = 100;
			} else if (slave.muscles >= 2) {
				slave.muscles = 50;
			} else if (slave.muscles >= 1) {
				slave.muscles = 20;
			} else {
				slave.muscles = 0;
			}
		}
	}

	switch (slave.boobsTat) {
		case "floral designs":
			slave.boobsTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.boobsTat = "rude words";
			break;
		case "lewd scenes":
			slave.boobsTat = "scenes";
			break;
		case "degrading language":
			slave.boobsTat = "degradation";
			break;
		case "slutty advertisements":
			slave.boobsTat = "advertisements";
			break;
	}

	switch (slave.buttTat) {
		case "floral designs":
			slave.buttTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.buttTat = "rude words";
			break;
		case "lewd scenes":
			slave.buttTat = "scenes";
			break;
		case "degrading language":
			slave.buttTat = "degradation";
			break;
		case "slutty advertisements":
			slave.buttTat = "advertisements";
			break;
	}

	switch (slave.vaginaTat) {
		case "floral designs":
			slave.vaginaTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.vaginaTat = "rude words";
			break;
		case "lewd scenes":
			slave.vaginaTat = "scenes";
			break;
		case "degrading language":
			slave.vaginaTat = "degradation";
			break;
		case "slutty advertisements":
			slave.vaginaTat = "advertisements";
			break;
	}

	switch (slave.dickTat) {
		case "floral designs":
			slave.dickTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.dickTat = "rude words";
			break;
		case "lewd scenes":
			slave.dickTat = "scenes";
			break;
		case "degrading language":
			slave.dickTat = "degradation";
			break;
		case "slutty advertisements":
			slave.dickTat = "advertisements";
			break;
	}

	switch (slave.anusTat) {
		case "floral designs":
			slave.anusTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.anusTat = "rude words";
			break;
		case "lewd scenes":
			slave.anusTat = "scenes";
			break;
		case "degrading language":
			slave.anusTat = "degradation";
			break;
		case "slutty advertisements":
			slave.anusTat = "advertisements";
			break;
	}

	switch (slave.backTat) {
		case "floral designs":
			slave.backTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.backTat = "rude words";
			break;
		case "lewd scenes":
			slave.backTat = "scenes";
			break;
		case "degrading language":
			slave.backTat = "degradation";
			break;
		case "slutty advertisements":
			slave.backTat = "advertisements";
			break;
	}

	switch (slave.shouldersTat) {
		case "floral designs":
			slave.shouldersTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.shouldersTat = "rude words";
			break;
		case "lewd scenes":
			slave.shouldersTat = "scenes";
			break;
		case "degrading language":
			slave.shouldersTat = "degradation";
			break;
		case "slutty advertisements":
			slave.shouldersTat = "advertisements";
			break;
	}

	switch (slave.armsTat) {
		case "floral designs":
			slave.armsTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.armsTat = "rude words";
			break;
		case "lewd scenes":
			slave.armsTat = "scenes";
			break;
		case "degrading language":
			slave.armsTat = "degradation";
			break;
		case "slutty advertisements":
			slave.armsTat = "advertisements";
			break;
	}

	switch (slave.legsTat) {
		case "floral designs":
			slave.legsTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.legsTat = "rude words";
			break;
		case "lewd scenes":
			slave.legsTat = "scenes";
			break;
		case "degrading language":
			slave.legsTat = "degradation";
			break;
		case "slutty advertisements":
			slave.legsTat = "advertisements";
			break;
	}

	switch (slave.stampTat) {
		case "floral designs":
			slave.stampTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.stampTat = "rude words";
			break;
		case "lewd scenes":
			slave.stampTat = "scenes";
			break;
		case "degrading language":
			slave.stampTat = "degradation";
			break;
		case "slutty advertisements":
			slave.stampTat = "advertisements";
			break;
	}

	switch (slave.lipsTat) {
		case "floral designs":
			slave.lipsTat = "flowers";
			break;
		case "demeaning inscriptions":
			slave.lipsTat = "rude words";
			break;
		case "lewd scenes":
			slave.lipsTat = "scenes";
			break;
		case "degrading language":
			slave.lipsTat = "degradation";
			break;
		case "slutty advertisements":
			slave.lipsTat = "advertisements";
			break;
	}

	if (slave.currentRules === undefined || slave.currentRules.length < 1) {
		slave.currentRules = [];
	}

	if (slave.height < -1) {
		slave.height = jsRandom(140, 149);
	} else if (slave.height < 0) {
		slave.height = jsRandom(150, 159);
	} else if (slave.height < 1) {
		slave.height = jsRandom(160, 169);
	} else if (slave.height < 2) {
		slave.height = jsRandom(170, 184);
	} else if (slave.height <= 3) {
		slave.height = jsRandom(185, 200);
	}

	if (V.releaseID < 1059) {
		if (slave.eyeColor === "no default value") {
			slave.eyeColor = slave.origEye;
		}
	}

	if (slave.birthSurname === undefined) { slave.birthSurname = 0; }
	if (slave.slaveSurname === undefined) { slave.slaveSurname = 0; }

	if (slave.faceImplant === 1) {
		slave.faceImplant = 15;
	} else if (slave.faceImplant === 2) {
		slave.faceImplant = 65;
	}

	if (slave.areoleaPiercing !== undefined) { delete slave.areoleaPiercing; }
	if (slave.pregControl === undefined) { slave.pregControl = "none"; }
	if (slave.pregControl === "labor supressors") {
		slave.pregControl = "labor suppressors";
	}

	if (slave.chastityAnus === undefined || slave.chastityPenis === undefined || slave.chastityVagina === undefined) {
		if (slave.dickAccessory === "combined chastity") {
			slave.chastityAnus = 1;
			slave.chastityPenis = 1;
			slave.dickAccessory = "none";
		} else if (slave.vaginalAccessory === "combined chastity") {
			slave.chastityAnus = 1;
			slave.chastityVagina = 1;
			slave.vaginalAccessory = "none";
		} else if (slave.dickAccessory === "anal chastity" || slave.vaginalAccessory === "anal chastity") {
			slave.chastityAnus = 1;
			slave.dickAccessory = "none";
			slave.vaginalAccessory = "none";
		} else if (slave.dickAccessory === "chastity") {
			slave.chastityPenis = 1;
			slave.dickAccessory = "none";
		} else if (slave.vaginalAccessory === "chastity belt") {
			slave.chastityVagina = 1;
			slave.vaginalAccessory = "none";
		} else {
			slave.chastityAnus = 0;
			slave.chastityPenis = 0;
			slave.chastityVagina = 0;
		}
	}
};


code:
App.Data.Pronouns = {};

/**
 * @readonly
 * @enum {number}
 */
App.Data.Pronouns.Kind = Object.freeze({
	female: 0,
	male: 1,
	neutral: 2,
	toy: 2,
	epicene: 3,
	plural: 3,
	ai: 4,
	custom: 1000
});

/**
 * @param {string} pronoun
 * @param {string} possessive
 * @param {string} possessivePronoun
 * @param {string} object
 * @param {string} objectReflexive
 * @param {string} noun
 * @returns {App.Data.Pronouns.Definition}
 */
App.Data.Pronouns.makePronounsData = function(
	pronoun, possessive, possessivePronoun, object, objectReflexive, noun) {
	return {
		pronoun: pronoun,
		possessive: possessive,
		possessivePronoun: possessivePronoun,
		object: object,
		objectReflexive: objectReflexive,
		noun: noun
	};
};

App.Data.Pronouns.Std = {
	0: App.Data.Pronouns.makePronounsData("she", "her", "hers", "her", "herself", "girl"),
	1: App.Data.Pronouns.makePronounsData("he", "his", "his", "him", "himself", "boy"),
	2: App.Data.Pronouns.makePronounsData("it", "its", "its", "it", "itself", "toy"),
	3: App.Data.Pronouns.makePronounsData("they", "their", "theirs", "them", "themselves", "toys"),
	4: App.Data.Pronouns.makePronounsData("it", "its", "its", "it", "itself", "program"),
};


code:
/* eslint-disable no-empty */
/* eslint-disable no-var */
/*
Given an object, this will return an array where for each property of the original object, we include the object
{variable: property, oldVal: _oldDiff.property, newVal: _newDiff.property}
*/
window.generateDiffArray = function generateDiffArray(obj) {
	let diffArray = Object.keys(obj).map(function(key) {
		return {variable: key, oldVal: State.temporary.oldDiff[key], newVal: State.temporary.newDiff[key]};
	});
	return diffArray;
};

/*
Shamelessly copied from https://codereview.stackexchange.com/a/11580
Finds and returns the difference between two objects. Potentially will have arbitrary nestings of objects.
*/
window.difference = function difference(o1, o2) {
	let k, kDiff, diff = {};
	for (k in o1) {
		if (!o1.hasOwnProperty(k)) {
		} else if (typeof o1[k] !== 'object' || typeof o2[k] !== 'object') {
			if (!(k in o2) || o1[k] !== o2[k]) {
				diff[k] = o2[k];
			}
		} else {
			kDiff = difference(o1[k], o2[k]);
			if (kDiff) {
				diff[k] = kDiff;
			}
		}
	}
	for (k in o2) {
		if (o2.hasOwnProperty(k) && !(k in o1)) {
			diff[k] = o2[k];
		}
	}
	for (k in diff) {
		if (diff.hasOwnProperty(k)) {
			return diff;
		}
	}
	return false;
};

/*
Shamelessly copied from https://stackoverflow.com/a/19101235
Flattens an object while concatenating property names.
For example {id: {number: 4, name: "A"}} --> {id.number: 4, id.name: "A"}
*/
window.diffFlatten = function diffFlatten(data) {
	let result = {};
	function recurse(cur, prop) {
		if (Object(cur) !== cur) {
			result[prop] = cur;
		} else if (Array.isArray(cur)) {
			// eslint-disable-next-line no-var
			for (var i=0, l=cur.length; i<l; i++) { // don't change the "var" to "let"
				recurse(cur[i], prop + "[" + i + "]");
			}
			// eslint-disable-next-line block-scoped-var
			if (l === 0) { result[prop] = []; }
		} else {
			let isEmpty = true;
			for (let p in cur) {
				isEmpty = false;
				recurse(cur[p], prop ? prop+"."+p : p);
			}
			if (isEmpty && prop) { result[prop] = {}; }
		}
	}
	recurse(data, "");
	return result;
};

/*
Finds all NaN values anywhere in the State.variables object. Returns an array with the names of the NaNed variables.
*/
window.findNaN = function findNan() {
	const flatV = diffFlatten(State.variables);
	let result = [];
	for (let key in flatV) {
		if (Number.isNaN(flatV[key])) {
			result.push('$$'+key); /* double dollar signs to escape sugarcube markup */
		}
	}
	return result;
};

/* no-usedOnce*/
/**
 * Dumps game save as a readable JSON to the browser for saving in a file
 */
App.Debug.dumpGameState = function() {
	// helper to download a blob
	// borrowed from stackexchange
	function downloadToFile(content, fileName, contentType) {
		let a = document.createElement("a");
		let file = new Blob([content], {
			type: contentType
		});
		a.href = URL.createObjectURL(file);
		a.download = fileName;
		a.click();
	}

	// we will replace SugarCube onSave handler
	let oldHandler = SugarCube.Config.saves.onSave;
	try {
		SugarCube.Config.saves.onSave = function(save) {
			if (oldHandler) {
				oldHandler(save);
			}
			downloadToFile(JSON.stringify(save, null, 2), save.id + ".json", "text/plain");
		};
		SugarCube.Save.serialize();
	} finally {
		SugarCube.Config.saves.onSave = oldHandler;
	}
};

App.Debug.slaveSummaryText = function(idx) {
	let span = document.createElement("span");
	span.appendChild(SlaveSummaryUncached(State.variables.slaves[idx]));
	return span.outerHTML;
};


code:
:: Debug Widgets [widget nobr]

/*
This widget will find which properties were changed in a specific passage (State.bottom.title to be precise), and display their original values and current values.
It's somewhat awkward if a stored variable changes types to/from an object or array.
The included "Go Back" link is intended to replace the usual NextButton.
*/
<<widget "displayDifferences">>
<<set _oldVariables = clone(State.bottom.variables)>>
<<set _newVariables = clone(State.variables)>>
<<set _newDiff = diffFlatten(difference(_oldVariables,_newVariables))>> /* Returns a flattened object containing the names of the changed variables, and the new values of those variables. */
<<set _oldDiff = diffFlatten(difference(_newVariables,_oldVariables))>> /* Returns a flattened object containing the names of the changed variables, and the old values of those variables. */
<<set _diffArrayFromNew = generateDiffArray(_newDiff)>> /* This function requires the existence of the specific variables _newDiff AND _oldDiff to work. */
<<set _diffArrayFromOld = generateDiffArray(_oldDiff)>>
<<link "Go Back">>
	<>
<</link>>

Differences:
<<if _diffArrayFromNew.length > 0>>
	<<for _i = 0; _i < _diffArrayFromNew.length; _i++>> /* Print variable names, and changed values. Will output the new values correctly, may not output old values correctly */
		<<if _diffArrayFromNew[_i].variable != "nextButton" && _diffArrayFromNew[_i].variable != "nextLink" && _diffArrayFromNew[_i].variable != "args">>

    Variable: <<print _diffArrayFromNew[_i].variable>>, Original Value: <<print _diffArrayFromNew[_i].oldVal>>, New Value: <<print _diffArrayFromNew[_i].newVal>>
		<</if>>
	<</for>>

	<<link "Show more">>
		<<replace "#extraInfo">>
			Alternate display:
			<<for _i = 0; _i < _diffArrayFromOld.length; _i++>> /* Print variable names, and changed values. Will output the old values correctly, may not output new values correctly */
				<<if _diffArrayFromOld[_i].variable != "nextButton" && _diffArrayFromOld[_i].variable != "nextLink" && _diffArrayFromOld[_i].variable != "args">>

    Variable: <<print _diffArrayFromOld[_i].variable>>, Original Value: <<print _diffArrayFromOld[_i].oldVal>>, New Value: <<print _diffArrayFromOld[_i].newVal>>
				<</if>>
			<</for>>
		<</replace>>
	<</link>>// This should only be necessary if a variable changes type to/from an object or array. In that case this will display the correct original value, but incorrect current value.//

<<else>>

    Nothing changed!

<</if>>
<<link "Go Back">>
	<>
<</link>>
<</widget>>


code:
/* This is a terrible hack, but it actually seems to yield decent results, so...yay? */

window.ProfileInclude = (function() {
	let stack = [];
	let tally = new Map();
	let builtinIncludeHandler = null;

	class TallyElement {
		constructor(passage) {
			this.passage = passage;
			this.cumulativeTime = 0.0;
			this.calls = 0;
			this.children = new Map();
		}
		get totalChildTime() {
			return Array.from(this.children.values(), (x) => x.cumulativeTime).reduce((sum, current) => { return sum + current; }, 0.0);
		}
		outputBreakdown() {
			if (this.children.size === 0) {
				// no breakdown needed if there are no children, so return an empty fragment
				return document.createDocumentFragment();
			}

			const selfTime = this.cumulativeTime - this.totalChildTime;
			const selfTimePercent = (selfTime / this.cumulativeTime) * 100;
			const selfTimePerCall = selfTime / this.calls;

			let childList = document.createElement("ul");
			let selfListItem = document.createElement("li");
			childList.appendChild(selfListItem);
			selfListItem.appendChild(document.createTextNode(`<self>: ${selfTime.toFixed(0)}ms (${selfTimePercent.toFixed(2)}%); ${selfTimePerCall.toFixed(0)}ms per call over ${this.calls.toFixed(0)} calls`));
			for (const [, child] of this.children) {
				const childTimePercent = (child.cumulativeTime / this.cumulativeTime) * 100;
				const childTimePerCall = child.cumulativeTime / child.calls;
				let childListItem = document.createElement("li");
				childListItem.appendChild(document.createTextNode(`${child.passage}: ${child.cumulativeTime.toFixed(0)}ms (${childTimePercent.toFixed(2)}%); ${childTimePerCall.toFixed(0)}ms per call over ${child.calls.toFixed(0)} calls`));
				childListItem.appendChild(child.outputBreakdown());
				childList.appendChild(childListItem);
			}
			return childList;
		}
	}

	class StackElement {
		constructor(passage) {
			this.passage = passage;
			this.startTime = Date.now();
		}
	}

	function Push(passage) {
		stack.push(new StackElement(passage));
	}

	function PopAndTally() {
		const el = stack.pop();
		const stopTime = Date.now();

		/* traverse the tally tree, ensuring that it has nodes for every frame still in the stack */
		let parentMap = tally;
		for (const child of stack) {
			if (!parentMap.has(child.passage)) {
				parentMap.set(child.passage, new TallyElement(child.passage));
			}
			parentMap = parentMap.get(child.passage).children;
		}

		/* add the popped stack frame's time to the correct child of the tally tree node corresponding with the top of the stack */
		if (!parentMap.has(el.passage)) {
			parentMap.set(el.passage, new TallyElement(el.passage));
		}
		let tallyEl = parentMap.get(el.passage);
		tallyEl.cumulativeTime += stopTime - el.startTime;
		tallyEl.calls++;
	}

	function IncludeBegins(passage) {
		Push(passage);
	}

	function IncludeEnds() {
		PopAndTally();
	}

	$(document).on(':passagestart', function() {
		if (V.profiler && !ProfileInclude.IsEnabled()) {
			ProfileInclude.Start();
		} else if (!V.profiler && ProfileInclude.IsEnabled()) {
			ProfileInclude.Stop();
		}

		tally.clear();

		if (ProfileInclude.IsEnabled()) {
			Push(passage()); // put the "host" passage at the bottom of the stack
		}
	});

	$(document).on(':passagedisplay', function() {
		if (ProfileInclude.IsEnabled()) {
			PopAndTally(); // tally the "host" passage too

			let header = document.createElement("h2");
			header.appendChild(document.createTextNode("Profile Data:"));
			let rootList = document.createElement("ul");
			let rootItem = document.createElement("li");
			let rootData = tally.values().next().value; // should be just the one item in the map at this level
			rootItem.appendChild(document.createTextNode(`${rootData.passage}: ${rootData.cumulativeTime.toFixed(0)}ms (100.00%)`));
			rootItem.appendChild(rootData.outputBreakdown());
			rootList.appendChild(rootItem);
			$("#passages").append(header).append(rootList);
		}
	});

	return {
		Start: function() {
			/* save off the builtin handler for the include macro, delete said macro, then re-register it with instrumentation */
			if (!this.IsEnabled() && Macro.has('include')) {
				builtinIncludeHandler = Macro.get('include').handler;
				Macro.delete('include');
				Macro.add('include', {handler() {
					IncludeBegins(this.args[0]);
					builtinIncludeHandler.call(this);
					IncludeEnds();
				}});
			}
		},

		IsEnabled: function() {
			return (builtinIncludeHandler !== null);
		},

		Stop: function() {
			/* restore the original include macro handler */
			if (this.IsEnabled())	{
				Macro.delete('include');
				Macro.add('include', {handler: builtinIncludeHandler});
				builtinIncludeHandler = null;
			}
		}
	};
})();


code:
:: Variable Difference [nobr]

<<set $nextButton = " ">> /* disable the nextButton. Forces the user to use the "Go Back" option contained in the widget */

<<displayDifferences>>


code:
/* Condition
	The current physical condition of the slave.
	Any health improvements get added here.
	Short term damage reduces it as it degrades.

Short term damage
	Anything that hurts a slave gets transferred into this.
	At the end of the week 25% of it will be removed and turned into condition damage instead.
	Usage of preventatives or curatives reduces the actual condition damage by 50%.

Long term damage
	Once ageing beyond 30 years old there is a chance of long term damage that increases with time. Calculated on birthday.
		Math.floor((slave.physicalAge - 25 + jsRandom(1, 15)) / 20)
	25% of the actual condition damage taken during a week also gets added to the pool (therefore gets reduced by preventatives and curatives if active).
	Nothing can reduce this value.
	Perhaps the effect can still be reduced through surgical implant with high upkeep.

Carcinogens
	Aside from a source of regular short term damage high levels will also increase the chances for severe illnesses
		3d6 rolls for illness
			illness > 8 -- 1 62.5%
			illness > 6 -- 2 21.3%
			illness > 5 -- 3 11.6%
			illness > 4 -- 4 2.8%
			illness = 3 or 4 -- 5 1.8%
		Carcinogens subtract Math.trunc(chem / 150) from the dice rolls for a max of -6 at >= 90
	There should be a natural decay of carcinogens every week of 10% of the level. But at the price of 0.2 short term damage per point of chem.
	Add carcinogen damage to serious medical procedures due to use of potent pharmaceuticals during them.

Illness
	There is always a chance a slave gets sick. Often they will just get better on their own, but sometimes it can be more serious and require a stay in the clinic.
	Sick slaves work at reduced effectiveness and will see their health lowered.

Tiredness
	Depending on various factors (living conditions, assignment, rewards, muscles, health) a slave may become more or less tired.
	Once tiredness reached 60 there will be negative effects for productivity and at 90 they become even more extreme.
	Being tired or exhausted also reduces a slave's ability to resist the player, increasing devotion and fear.

Health
	The aggregate of condition, short term damage and long term damage to provide an indication of the current overal state of the slave. The slave will die once this reached -100.
*/

/* Getting ill depends on the following factors;
	- current condition
	- long term damage (accumulated through getting old(er) and residual from short term damage)
	- short term damage (accumulated through serious illness, chemical carcinogens, damaging surgeries and other health damage sources) 125%
	- chemical carcinogens (more serious illness chance with high carcinogen levels)
	- age (long term damge takes care of older slaves, the young ones need a specific vulnerability)
	- use of curatives
	- assignment (rest, clinic, spa and master suite less likely, whoring, slutting and goloryholes more likely.)
	- random chance
	Can be blocked with preventatives.
*/

/**
 * @param {App.Entity.SlaveState} slave
 * @returns {string}
 */
window.illness = function illness(slave) {
	const random = jsRandom(1, 100); // high rolls are good
	const H = slave.health;
	let r = ``;
	let assignBonus = 0; // bonus for healthy assignments

	let he, him, his, hers, himself, girl, loli, He, His;
	({
		he, him, his, hers, himself, girl, He, His, loli
	} = getPronouns(slave));
	let sicknessDegree = ["fine", "minor illness", "illness", "bad illness", "severe illness", "life-threatening illness"];

	// On the macro side of things disease could also happen to the acrology's population as the arcology becomes crowded, killing citizens and putting slaves at greater risk of getting ill. Again with upgrades/policies to mitigate the issue made available TODO?
	if (slave.assignment === "live with your agent" || slave.assignment === "be your agent") {
		if (H.illness !== 0) {
			H.illness = 0;
		}
		return r;
	} // Let's make sure agents don't get sick and accidentally die, they should take care of themselves
	if (slave.fuckdoll !== 0) {
		assignBonus += 50;
	} else if (slave.assignment === "get treatment in the clinic") {
		assignBonus += 40;
	} else if (slave.assignment === "rest in the spa" || slave.assignment === "rest") {
		assignBonus += 20;
	} else if ((slave.assignment === "serve in the master suite" || slave.assignment === "please you") && V.PC.skill.medicine >= 40) {
		assignBonus += 10;
	} else if (setup.nurseCareers.includes(slave.career) || slave.skill.nurse >= 100 || slave.intelligence + slave.intelligenceImplant > 95) { // Let slaves with experience or brains use it
		assignBonus += 10;
	}
	if (random < 6) { // There is always a 5% chance of a slave feeling worse or coming in contact with an illness
		if (H.illness > 0) {
			H.illness += 1 + Math.trunc((slave.chem / 10 + jsRandom(1, 50) + 15) / 100); // Illness progresses with 1, unless chem > 350, then there's a chance for 2
			r += ` <span class="red">${His} sickness has progressed.</span>`;
			if (H.illness > 5) {
				healthDamage(slave, 20 * (H.illness - 5)); // Condition penalty for going over maximum illness, very dangerous
				H.illness = 5;
				r += ` ${His} illness <span class="red">makes an attempt to claim ${his} life.</span>`;
			}
		} else {
			getIll(slave);
			if (H.illness > 0) {
				r += ` ${He} has come down with <span class="red">${addA(sicknessDegree[H.illness])}.</span>`;
			}
		}
	} else if (random > 95) { // There is always a 5% chance of a slave getting better
		H.illness -= 1;
		if (H.illness < 0) {
			H.illness = 0;
			improveCondition(slave, 5);
			r += ` <span class="green">${His} sickness has waned</span> and ${he} now feels better.`;
		} else {
			r += ` ${His} immune system <span class="green">fights back</span> against ${his} illness.`;
		}
	} else {
		/* eslint-disable camelcase */
		let nurse_effectiveness = nurseEffectiveness(slave);
		let health_adjusted = H.condition - H.longDamage - H.shortDamage * 1.25;
		let age_modifier = Math.min(Math.trunc((slave.physicalAge - 18) / 3), 0);
		let bonus_modifiers = random + assignBonus + nurse_effectiveness;
		let curativesBonus = (slave.curatives > 1 || slave.inflationType === "curative") ? 2 : 1;

		// When ill, a slave has a 60% chance of getting better the next week at complete default, 70% with a favourable assignment, 80% with curatives, 90% with both measures active and additional benefits depending on the nurse on duty
		if (H.illness > 0 && ((health_adjusted + age_modifier) / 3) + bonus_modifiers > 40 / curativesBonus) {
			if (nurse_effectiveness > 30 && (jsRandom(1, 2) === 2 || slave.assignment === "get treatment in the clinic") && H.illness > 1) { // A particularly effective nurse can improve illness faster
				H.illness -= 2;
				r += ` ${V.Nurse.slaveName} <span class="green">successfully treats</span> ${his} illness.`;
			} else {
				H.illness -= 1;
				r += ` ${His} body <span class="green">fights back</span> against ${his} illness.`;
			}
			if (H.illness === 0) {
				r += ` ${He} no longer <span class="green">shows any signs</span> of ${his} previous sickness.`;
			}
		} else if (H.illness === 0) {
			if (["guard you", "be the DJ", "be the Madam", "be confined in the arcade", "work a glory hole", "serve in the club", "serve the public", "whore", "work in the brothel"].includes(slave.assignment)) { // Limit to outside jobs only
				if (((Math.min(health_adjusted, 50) + age_modifier) / 3) + bonus_modifiers < 30 / Math.min(curativesBonus + 1, 2)) { // Chance of getting ill 30% at complete default, 20% with a favourable assignment, 15% with curatives or preventatives, 10% with both measures active and a small benefit from effective Nurse screening
					getIll(slave);
					r += ` ${He} has come down with <span class="red">${addA(sicknessDegree[H.illness])}.</span>`;
				}
			}
		} else {
			healthDamage(slave, Math.pow(H.illness, 2));
			r += ` ${He} <span class="red">suffers under ${his} ${sicknessDegree[H.illness]}.</span>`;
		}
		/* eslint-enable camelcase */
	}
	return r;
};

/**
 * Once a new illness is rolled this determines how bad it is initially, chem levels seriously increase the chances of a higher initial value. Health also factors in with weakened slaves being more likely to catch ill.
 * @param {App.Entity.SlaveState} slave
 * @returns {void}
 */
window.getIll = function getIll(slave) {
	const H = slave.health;
	const illness = jsRandom(1, 6) + jsRandom(1, 6) + jsRandom(1, 6) - Math.trunc(slave.chem / 150) + Math.trunc(H.condition / 20);
	if (V.seeIllness !== 0) {
		if (slave.curatives !== 1 && slave.inflationType !== "curative") {
			if (slave.assignment !== "get treatment in the clinic") {
				if (illness < 4) {
					H.illness = 5; // 1.8% chance
				} else if (illness < 5) {
					H.illness = 4; // 2.8% chance
				} else if (illness < 6) {
					H.illness = 3; // 11.6% chance
				} else if (illness < 8) {
					H.illness = 2; // 21.3% chance
				} else {
					H.illness = 1; // 62.5% chance
				}
			}
		}
	}
};

/**
 * Attempts to pass illness from slave1 to slave2.
 * @param {App.Entity.SlaveState} slave1
 * @param {App.Entity.SlaveState} slave2
 * @returns {string}
 */
window.passIllness = function passIllness(slave1, slave2) {
	if (V.seeIllness !== 0) {
		if (slave1.curatives !== 1) {
			if (slave1.assignment !== "get treatment in the clinic") {
				slave1.health.illness = ill;
			}
		}
	}
	return ` ${slave1.slaveName} has caught ${slave2.slaveName}'s sickness.`;
};

/**
 * Once a new illness is rolled this determines how bad it is initially, chem levels seriously increase the chances of a higher initial value
 * @param {App.Entity.SlaveState} slave
 * @returns {void}
 */
window.poorHealthNeedReduction = function poorHealthNeedReduction(slave) {
	// Slave .need reduction if ill or tired
	if (slave.energy > 20) {
		slave.need = Math.trunc(slave.need * healthPenalty(slave));
	}
};

/**
 * A better nurse and/or less slaves/patients to look out for makes for a better chance of curing illness
 * @param {App.Entity.SlaveState} slave
 * @returns {number}
 */
window.nurseEffectiveness = function nurseEffectiveness(slave) {
	const H = slave.health;
	const clinicUpgrade = 1; // Creating a purchasable upgrade to increase the amount of slaves the nurse can handle -- TODO
	const clinicScreening = 1; // Assumes the clinic is set to screening all slaves to improve their chances of staying healthy. Turning it off would allow the nurse to focus on just her patients in the clinic -- TODO
	if (V.Nurse !== 0) {
		const nurseSkill = setup.nurseCareers.includes(V.Nurse.career) ? 200 : V.Nurse.skill.nurse;
		let nurseEffectiveness = Math.trunc((nurseSkill * clinicUpgrade / Math.max((V.CliniciIDs.length * 10 + (V.slaves.length * 2) * clinicScreening), 1)) * 20);
		if (H.illness > 1 && slave.assignment === "get treatment in the clinic") {
			if (nurseEffectiveness < 20) {
				return nurseEffectiveness;
			} else if (nurseSkill > 80) {
				return Math.min(nurseEffectiveness, 40);
			} else if (nurseSkill > 40) {
				return Math.min(nurseEffectiveness, 30);
			} else {
				return 20;
			}
		} else if (H.illness < 2) { // reasonably ill slaves get no benefit from the nurse unless they are in the clinic, otherwise she can provide benefits to prevent illness in the first place and clearing up illnesses of level 1
			nurseEffectiveness = Math.trunc(nurseEffectiveness / 4);
			if (nurseEffectiveness < 5) {
				return nurseEffectiveness;
			} else {
				return 5;
			}
		}
	} else {
		return 0;
	}
};

/**
 * Run at the end of the week to take care of health changes
 * @param {App.Entity.SlaveState} slave
 * @returns {void}
 */
window.endWeekHealthDamage = function endWeekHealthDamage(slave) {
	const H = slave.health;
	let chemToShort = 0;
	let shortToCondition = 0;
	let shortToLong = 0;
	let tiredToCondition = 0;

	// Checking if we are dealing with the player
	// Player does not make use of most things slaves deal with, only short to long term damage
	if (slave.ID !== -1) {
		// dealing with carcinogens
		// They decay naturally at a rate of 10%, but at as they decay cause short term damage
		if (slave.chem > 0) {
			if (slave.chem > 10) {
				chemToShort += Math.max(Math.trunc(slave.chem * 0.1), 1);
			} else if (slave.chem > jsRandom(0, 9)) {
				chemToShort += 1;
			}
			slave.chem -= chemToShort;
			H.shortDamage += Math.max(Math.trunc(chemToShort * 0.1), 2);
		}

		// dealing with illness
		if (H.illness > 0) {
			H.shortDamage += Math.trunc(Math.pow(H.illness, 1.52) * 3 + 2); // 5, 10, 17, 26, 36 points of damage per respective level of illness
		}

		// Long term damage due to age calculated on birthdays only
		if (slave.birthWeek === 0 && slave.physicalAge > 29) {
			H.longDamage += Math.trunc((slave.physicalAge - 25 + jsRandom(1, 15)) / 20);
		}
	} else if (H.condition < 100) { // The player gets an automatic 5 condition recovery each weak up to 100
		H.condition = Math.min(H.condition + 5, 100);
	}

	// recovering and transferring short term damage to condition and long term
	if (H.shortDamage > 0) {
		shortToCondition += Math.max(Math.trunc(H.shortDamage * 0.5), 1); // 50% of short term damage gets transferred
		H.shortDamage -= shortToCondition;
		if (slave.assignment === "get treatment in the clinic") {
			H.shortDamage = Math.trunc(H.shortDamage * 0.5); // An aditional 50% of short term damage reduction (75% total) for getting treatment in the clinic
		} else if (slave.assignment === "rest" || slave.assignment === "rest in the spa") {
			H.shortDamage = Math.trunc(H.shortDamage * 0.75); // An additional 25% of short term damage reduction (62.5% total) for resting
		}
		if (slave.curatives > 0 || slave.ID === -1) { // transferred damage is half if on preventatives/curatives or target is the player
			shortToCondition = Math.trunc(shortToCondition * 0.5);
		}
		if (slave.assignment === "get treatment in the clinic") {
			shortToCondition = Math.trunc(shortToCondition * 0.75);
		}
		shortToLong += Math.trunc(shortToCondition * 0.1); // 10% of transferred damage gets added to long term damage, minimum of 20 short term damage before any long term damage is accumulated
		H.longDamage += shortToLong;
	}
	if (V.baseDifficulty === 1) { // Reducing longDamage up to a certain point depending on the difficulty
		if (H.longDamage > 0) {
			H.longDamage -= Math.min(Math.trunc(H.longDamage * 0.1), 1);
		}
	} else if (V.baseDifficulty === 2) {
		if (H.longDamage > 20) {
			H.longDamage -= Math.min(Math.trunc((H.longDamage - 20) * 0.1), 1);
		}
	} else if (V.baseDifficulty === 3) {
		if (H.longDamage > 40) {
			H.longDamage -= Math.min(Math.trunc((H.longDamage - 40) * 0.1), 1);
		}
	} else if (V.baseDifficulty === 4) {
		if (H.longDamage > 60) {
			H.longDamage -= Math.min(Math.trunc((H.longDamage - 60) * 0.1), 1);
		}
	}
	if (V.disableLongDamage) {
		H.longDamage = 0;
	}

	// Making sure condition doesn't get too high
	if (H.condition > 150) {
		H.condition -= Math.trunc(Math.pow(H.condition - 150, 0.5));
	}

	H.health = H.condition - H.longDamage - H.shortDamage;
};

/**
 * Tells if a slave will try to work to death due to mental hangups
 * @param {App.Entity.SlaveState} slave
 * @returns {boolean}
 */
window.willWorkToDeath = function willWorkToDeath(slave) {
	// More to come in the future
	if (slave.trust < -50) { // Maybe lower
		return true;
	} else if (slave.sexualFlaw === "self hating") {
		return true;
	}
	return false;
};

/**
 * Run at the end of the week to take care of tiredness changes
 * @param {App.Entity.SlaveState} slave
 * @returns {void}
 */
window.tired = function tired(slave) {
	const H = slave.health;
	let livingRules = 0;
	let assignment = 0;
	let reward = 0;
	let punishment = 0;
	// let muscles;
	// let health;
	let tiredChange;
	let spaFlag = 0;

	if (!slave.fuckdoll) {
		// Assignment
		if (["rest in the spa"].includes(slave.assignment)) {
			assignment -= 40 * (V.spaUpgrade + 1); // Reduces tired by an average of 40 points while in the spa, double with the upgraded spa
			if (V.Attendant !== 0) {
				let skillBonus;
				if (setup.attendantCareers.includes(V.Attendant.career)) {
					skillBonus = 200;
				} else {
					skillBonus = V.Attendant.skill.attendant;
				}
				assignment -= Math.trunc(skillBonus / 10); // Maximum of 20 extra points of negative tiredness due to attendant skill
			}
		} else if (["rest", "get treatment in the clinic"].includes(slave.assignment)) {
			assignment -= 40; // Major tired reduction due to a solid week of rest
		} else if (["guard you", "be the Attendant", "be the Matron", "be the Stewardess", "be the Milkmaid", "be the Farmer", "be the DJ", "be the Madam", "be the Schoolteacher", "be the Wardeness", "be the Nurse", "be your Head Girl"].includes(slave.assignment)) { // Heads are very busy, but always have luxurious conditions, so it balances out, save for the two exceptions
			assignment += 15;
		} else if (["get milked"].includes(slave.assignment)) {
			if (slave.devotion > 20) {
				assignment += 2;
			} else {
				assignment += 5;
			}
		} else if (["work in the dairy"].includes(slave.assignment)) {
			if (V.dairyRestraintsSetting > 1) {
				// assignment += 100; // Full industrial Dairy is exhausting
			} else if (V.dairyRestraintsSetting > 0) {
				assignment += 10; // Restraining while milking is a little stressful
			} else { // Being a free range cow is relatively relaxing
				if (slave.devotion > 20) {
					assignment += 2;
				} else {
					assignment += 5;
				}
			}
		} else if (["be confined in the arcade"].includes(slave.assignment)) { // Brutal assignments
			// assignment += 50; // We should have a safeguard in place to prevent slave health meltdown while contained in the machine
		} else if (["work a glory hole", "work as a farmhand"].includes(slave.assignment)) { // Hard assignments
			if (!willWorkToDeath(slave)) {
				if (slave.tired > 90) {
					assignment += 1;
				} else if (slave.tired > 60) {
					assignment += 10;
				}
			} else {
				if (slave.devotion > 20) {
					assignment += 15;
				} else {
					assignment += 20;
				}
			}
		} else if (["serve in the club", "serve the public", "whore", "work in the brothel"].includes(slave.assignment)) { // Moderate assignments
			if (!willWorkToDeath(slave)) {
				if (slave.tired > 90) {
					assignment += 1;
				} else if (slave.tired > 70) {
					assignment += 7;
				}
			} else {
				if (slave.devotion > 20) {
					assignment += 10;
				} else {
					assignment += 15;
				}
			}
		} else if (["serve in the master suite", "please you", "live with your Head Girl", "be a servant"].includes(slave.assignment)) { // Easy assignments
			if (slave.tired > 75) {
				assignment += 2;
			} else if (slave.devotion > 20) {
				assignment += 5;
			} else {
				assignment += 10;
			}
		} else if (["learn in the schoolroom", "take classes"].includes(slave.assignment)) { // Trivial assignments
			if (slave.tired > 80) {
				assignment += 2;
			} else if (slave.devotion > 20) {
				assignment += 2;
			} else {
				assignment += 5;
			}
		}

		// Living Conditions
		if (slave.rules.living === "spare") {
			livingRules -= 2; // Barely reduce tiredness while sleeping in spare conditions
			if (V.dormitory < V.dormitoryPopulation) {
				livingRules += 8; // Overcrowding penalty
			}
		} else if (slave.rules.living === "luxurious") {
			livingRules -= 15;
		} else {
			livingRules -= 10;
			if (V.dormitory < V.dormitoryPopulation) {
				livingRules += 17; // Overcrowding penalty
			}
		}

		// Rewards
		if (slave.rules.reward === "drugs") {
			reward -= 4;
		} else if (slave.rules.reward === "relaxation") {
			if (V.spaSpots > 0) {
				reward -= 7;
				spaFlag = 1;
			} else {
				reward -= 5;
			}
		} else if (slave.rules.reward === "situational") {
			if (V.spaSpots > 0) {
				reward -= 4;
				spaFlag = 1;
			} else {
				reward -= 3;
			}
		}
		if (slave.devotion > 50) { // Considering how often the slave gets rewarded
			reward *= 3;
		} else if (slave.devotion > 20) {
			reward *= 2;
		} else if (slave.devotion < -20 || slave.trust >= -20) {
			reward = 0;
		}
		if (spaFlag) {
			V.spaSpots -= Math.abs(reward); // Reducing the available space in the spa depending on how often the slave can be found there
		}
		if (reward > 0) {
			if (spaFlag) {
				reward *= V.spaUpgrade + 1;
			}
		}

		// Punishments
		if (slave.rules.reward === "confinement" && V.cellblock !== 0) {
			punishment -= 2;
		}
		if (slave.devotion > 50) { // Considering how often the slave gets punished
			punishment = 0;
		} else if (slave.devotion >= -20) {
			if (slave.trust >= -20) {
				punishment *= 2;
			}
		} else {
			if (slave.trust >= -50) {
				punishment *= 3;
			}
		}

		/* Disabled for balancing
		// Muscles
		if (slave.muscles < 0) {
			muscles = -Math.trunc((slave.muscles / 10) * (1 + normalRandInt(0, 5) / 100)); // Being weak increases tiredness, building muscles eventually reduces tiredness
		} else {
			muscles = -Math.trunc(5 * (1 + normalRandInt(0, 5) / 100)); // Muscle benefits max out at 50
		}

		// Health
		health = Math.trunc((H.shortDamage / 2 - H.condition / 10) * (1 + normalRandInt(0, 5) / 100)); // Current condition reduces tiredness, health damage increases tiredness
		if (slave.assignment === "rest" || slave.assignment === "get treatment in the clinic" || slave.assignment === "rest in the spa") {
			health = Math.max(0, health); // break vicious cycle - no additional tiredness accumulates from bad health for slaves assigned to rest
		}
		*/

		// Add advanced pregnancy/high .bellyPreg (it is either caused by an advanced pregnancy or high multiples, both draining) tiredness gain gated under preg effects
		// Add pregnancy speed up effects

		tiredChange = livingRules + assignment + reward + punishment; //  + muscles + health
		H.tired += tiredChange;
		// H.tired = Math.clamp(H.tired, 0, 100); Disabled until hacky disabler is removed.
		if (H.tired < 0 || V.disableTiredness) {
			H.tired = 0;
		} else if (H.tired > 100) {
			H.tired = 100;
		}
	} else {
		// fuckdolls get a static tiredness drop due to drugs and suit control
		H.tired -= 30;
		if (H.tired <= 0 || V.disableTiredness) {
			H.tired = 1;
		}
	}
};

/**
 * @param {App.Entity.SlaveState} slave
 * @returns {void}
 */
window.tiredFucks = function tiredFucks(slave) {
	/* temp disable
	if (!slave.fuckdoll && slave.fetish !== "mindbroken") {
		if (slave.assignment === "work a glory hole" || slave.assignment === "be confined in the arcade") {
			let acceptance = 0;
			acceptance += Math.trunc(slave.energy / 10);
			acceptance -= Math.trunc((slave.intelligence + slave.intelligenceImplant) / 10);
			if (slave.fetish === "masochist" || slave.fetish === "humiliation") {
				acceptance += Math.trunc(slave.fetishStrength / 10);
			}
			if ((acceptance > 20 && slave.devotion > 20) || slave.sexualFlaw === "self hating") {
				slave.health.tired += Math.trunc(slave.sexAmount * (1 + normalRandInt(0, 5) / 100) / 100);
			} else {
				slave.health.tired += Math.trunc(slave.sexAmount * (1 + normalRandInt(0, 5) / 100) / 50);
			}
		} else {
			slave.health.tired += Math.trunc(slave.sexAmount * (1 + normalRandInt(0, 5) / 100) / 25);
		}
	}
	*/
};


code:
/**
 * @param {App.Entity.SlaveState} slave
 * @returns {string}
 */
window.minorInjuryResponse = function minorInjuryResponse(slave) {
	const arcology = State.variables.arcologies[0];
	const arcologyUpgrade = State.variables.arcologyUpgrade;
	const {he, himself, He} = getPronouns(slave);
	let r = "";

	if (arcology.FSDegradationist > 20) {
		r += ` ${He} carries on, knowing that in your degradationist arcology, this is accepted behavior.`;
	} else if (arcology.FSPaternalist > 20) {
		if (arcologyUpgrade.drones === 1 && jsRandom(1, 100) > 50) {
			r += ` The security drones successfully detain him and oblige him to pay significant <span class="yellowgreen">compensation,</span> since abusing slaves is discouraged here.`;
			cashX(50, "slaveUpkeep", slave);
		} else if (arcologyUpgrade.grid === 1 && jsRandom(1, 100) > 50) {
			r += ` The computer systems successfully detain him and require him to pay significant <span class="yellowgreen">compensation,</span> since abusing slaves is discouraged here.`;
			cashX(50, "slaveUpkeep", slave);
		} else if (slave.skill.whoring > jsRandom(1, 100)) {
			r += ` ${slave.slaveName} is used to this sort of thing, and convinces him to pay significant <span class="yellowgreen">compensation,</span> since abusing slaves is discouraged here.`;
			cashX(50, "slaveUpkeep", slave);
		} else if (slave.skill.combat > 0) {
			r += ` ${slave.slaveName} can take care of ${himself}, and ${he} successfully forces him to pay significant <span class="yellowgreen">compensation,</span> since abusing slaves is discouraged here.`;
			cashX(50, "slaveUpkeep", slave);
		}
	} else {
		if (arcologyUpgrade.drones === 1 && jsRandom(1, 100) > 50) {
			r += ` The security drones successfully detain him and oblige him to pay minor <span class="yellowgreen">compensation.</span>`;
			cashX(10, "slaveUpkeep", slave);
		} else if (arcologyUpgrade.grid === 1 && jsRandom(1, 100) > 50) {
			r += ` The computer systems successfully detain him and require him to pay minor <span class="yellowgreen">compensation.</span>`;
			cashX(10, "slaveUpkeep", slave);
		} else if (slave.skill.whoring > jsRandom(1, 100)) {
			r += ` ${slave.slaveName} is used to this sort of thing, and convinces him to pay minor <span class="yellowgreen">compensation.</span>`;
			cashX(10, "slaveUpkeep", slave);
		} else if (slave.skill.combat > 0) {
			r += ` ${slave.slaveName} can take care of ${himself}, and ${he} successfully forces him to pay minor <span class="yellowgreen">compensation.</span>`;
			cashX(10, "slaveUpkeep", slave);
		}
	}

	return r;
};