diff --git a/src/js/utilJS.js b/src/js/utilJS.js
index da0039ff2f05f11d98a2ae2f6ec8d6a41e5267b7..c7c75937b564057d75f646d676695b9f831a3e9c 100644
--- a/src/js/utilJS.js
+++ b/src/js/utilJS.js
@@ -1,57 +1,57 @@
 /* eslint-disable no-unused-vars */
 /*
- * Height.mean(nationality, race, genes, age) - returns the mean height for the given combination and age in years (>=2)
- * Height.mean(nationality, race, genes) - returns the mean adult height for the given combination
- * Height.mean(slave) - returns the mean (expected) height for the given slave
- *
- * Height.random(nationality, race, genes, age) - returns a random height using the skew-normal distribution
- *													around the mean height for the given arguments
- * Height.random(nationality, race, genes) - returns a random height for the given combination of an adult, as above
- * Height.random(slave[, options]) - returns a random height for the given slave, as above.
- *										The additional options object can modify how the values are generated
- *										in the same way setting them as global configuration would, but only for this
- *										specific generation.
- *
- *										Example: Only generate above-average heights based on $activeSlave:
- *										Height.random($activeSlave, {limitMult: [0, 5]})
- *
- * Height.forAge(height, age, genes) - returns the height adapted to the age and genes
- * Height.forAge(height, slave) - returns the height adapted to the slave's age and genes
- *
- * Height.config(configuration) - configures the random height generator globally and returns the current configuration
- *	The options and their default values are:
- *	limitMult: [-3, 3] - Limit to the values the underlying (normal) random generator returns.
- *						In normal use, the values are almost never reached; only 0.27% of values are
- *						outside this range and need to be regenerated. With higher skew (see below),
- *						this might change.
- *	spread: 0.05 - The random values generated are multiplied by this and added to 1 to generate
- *					the final height multiplier. The default value together with the default limitMult
- *					means that the generated height will always fall within (1 - 0.05 * 3) = 85% and
- *					(1 + 0.05 * 3) = 115% of the mean height.
- *					Minimum value: 0.001; maximum value: 0.5
- *	skew: 0 - How much the height distribution skews to the right (positive) or left (negative) side
- *				of the height.
- *				Minimum value: -1000, maximum value: 1000
- *	limitHeight: [0, 999] - Limit the resulting height range. Warning: A small height limit range
- *							paired with a high spread value results in the generator having to
- *							do lots of work generating and re-generating random heights until
- *							one "fits".
- *
- * Anon's explanation:
- * limitMult: [0, -30]
- *
- * This specifies a range going up from 0 to -30. It needs to go [-30, 0] instead. Same thing with [0, -5] two lines down. note: technically, this isn't true, because for some bizarre reason Height.random reverses the numbers for you if you get them wrong. But it's important to establish good habits, so.
- *
- * Skew, spread, limitMult: These are statistics things. BTW, a gaussian distribution is a normal distribution. Just a naming thing.
- *
- * Skew: The shape parameter of a skew-normal distribution. See http://azzalini.stat.unipd.it/SN/Intro/intro.html for more details. Basically a measure of how asymmetrical the curve is. It doesn't move the main mass of the distribution. Rather, it's more like it moves mass from one of the tails into the main mass of the distribution.
- *
- * Spread: Changes the average distance from the mean, making the graph wider and shorter. Moves "mass" from the center to the tail. It's basically standard deviation, but named funny because FC codebase. Changing this can have dramatic effects. It's advised to keep this at or below 0.1 for usual height generation.
- *
- * limitMult: A clamp, expressed in z-score. (z=1 is one standard dev above mean, for ex.) If it excludes too much of the distribution the other parameters describe, you're going to spend lots of CPU making and throwing away heights. Don't worry about this unless you run into it.
- *
- * There's also limitHeight which you're not using. It's basically limitMult in different units.
- */
+* Height.mean(nationality, race, genes, age) - returns the mean height for the given combination and age in years (>=2)
+* Height.mean(nationality, race, genes) - returns the mean adult height for the given combination
+* Height.mean(slave) - returns the mean (expected) height for the given slave
+*
+* Height.random(nationality, race, genes, age) - returns a random height using the skew-normal distribution
+*													around the mean height for the given arguments
+* Height.random(nationality, race, genes) - returns a random height for the given combination of an adult, as above
+* Height.random(slave[, options]) - returns a random height for the given slave, as above.
+*										The additional options object can modify how the values are generated
+*										in the same way setting them as global configuration would, but only for this
+*										specific generation.
+*
+*										Example: Only generate above-average heights based on $activeSlave:
+*										Height.random($activeSlave, {limitMult: [0, 5]})
+*
+* Height.forAge(height, age, genes) - returns the height adapted to the age and genes
+* Height.forAge(height, slave) - returns the height adapted to the slave's age and genes
+*
+* Height.config(configuration) - configures the random height generator globally and returns the current configuration
+*	The options and their default values are:
+*	limitMult: [-3, 3] - Limit to the values the underlying (normal) random generator returns.
+*						In normal use, the values are almost never reached; only 0.27% of values are
+*						outside this range and need to be regenerated. With higher skew (see below),
+*						this might change.
+*	spread: 0.05 - The random values generated are multiplied by this and added to 1 to generate
+*					the final height multiplier. The default value together with the default limitMult
+*					means that the generated height will always fall within (1 - 0.05 * 3) = 85% and
+*					(1 + 0.05 * 3) = 115% of the mean height.
+*					Minimum value: 0.001; maximum value: 0.5
+*	skew: 0 - How much the height distribution skews to the right (positive) or left (negative) side
+*				of the height.
+*				Minimum value: -1000, maximum value: 1000
+*	limitHeight: [0, 999] - Limit the resulting height range. Warning: A small height limit range
+*							paired with a high spread value results in the generator having to
+*							do lots of work generating and re-generating random heights until
+*							one "fits".
+*
+* Anon's explanation:
+* limitMult: [0, -30]
+*
+* This specifies a range going up from 0 to -30. It needs to go [-30, 0] instead. Same thing with [0, -5] two lines down. note: technically, this isn't true, because for some bizarre reason Height.random reverses the numbers for you if you get them wrong. But it's important to establish good habits, so.
+*
+* Skew, spread, limitMult: These are statistics things. BTW, a gaussian distribution is a normal distribution. Just a naming thing.
+*
+* Skew: The shape parameter of a skew-normal distribution. See http://azzalini.stat.unipd.it/SN/Intro/intro.html for more details. Basically a measure of how asymmetrical the curve is. It doesn't move the main mass of the distribution. Rather, it's more like it moves mass from one of the tails into the main mass of the distribution.
+*
+* Spread: Changes the average distance from the mean, making the graph wider and shorter. Moves "mass" from the center to the tail. It's basically standard deviation, but named funny because FC codebase. Changing this can have dramatic effects. It's advised to keep this at or below 0.1 for usual height generation.
+*
+* limitMult: A clamp, expressed in z-score. (z=1 is one standard dev above mean, for ex.) If it excludes too much of the distribution the other parameters describe, you're going to spend lots of CPU making and throwing away heights. Don't worry about this unless you run into it.
+*
+* There's also limitHeight which you're not using. It's basically limitMult in different units.
+*/
 window.Height = (function() {
 	"use strict";
 
@@ -691,36 +691,36 @@ window.Height = (function() {
 })();
 
 /*
- *  Intelligence.random(options) - returns a random intelligence. If no options are passed, the generated number
- *									will be on a normal distribution with mean 0 and standard deviation 45.
- *
- *										Example: Only generate above-average intelligence based on $activeSlave:
- *										Intelligence.random({limitIntelligence: [0, 100]})
- *
- *  Intelligence.config(configuration) - configures the random height generator globally and returns the current configuration
- *
- *	The options and their default values are:
- *	mean: 0 - What the average intelligence will be. Increasing this will make it more likely
- *				to generate a smart slave, but will not guarantee it.
- *				Minimum value: -100, maximum value: 100
- *	limitMult: [-3, 3] - Limit to this many standard deviations from the mean.
- *						In normal use, the values are almost never reached; only 0.27% of values are
- *						outside this range and need to be regenerated. With higher skew (see below),
- *						this might change.
- *	spread: 45 - The random standard deviation of the calculated distribution. A higher value
- *				will make it more likely to have extreme values, a lower value will make any
- *				generated values cluster around the mean. If spread is 0, it will always return the mean.
- *	skew: 0 - How much the height distribution skews to the right (positive) or left (negative) side
- *				of the height. Unless you have a very specific reason, you should not need to change this.
- *				Minimum value: -1000, maximum value: 1000
- *	limitIntelligence: [-100,100] - Limit the resulting height range.
- *									Warning: A small intelligence limit range not containing the
- *									mean, and with a low spread value results in the generator
- *									having to do lots of work generating and re-generating random
- *									intelligences until one "fits".
- *
- *  This was modeled using the Height generator above. For some more information, see the comments for that.
- */
+*  Intelligence.random(options) - returns a random intelligence. If no options are passed, the generated number
+*									will be on a normal distribution with mean 0 and standard deviation 45.
+*
+*										Example: Only generate above-average intelligence based on $activeSlave:
+*										Intelligence.random({limitIntelligence: [0, 100]})
+*
+*  Intelligence.config(configuration) - configures the random height generator globally and returns the current configuration
+*
+*	The options and their default values are:
+*	mean: 0 - What the average intelligence will be. Increasing this will make it more likely
+*				to generate a smart slave, but will not guarantee it.
+*				Minimum value: -100, maximum value: 100
+*	limitMult: [-3, 3] - Limit to this many standard deviations from the mean.
+*						In normal use, the values are almost never reached; only 0.27% of values are
+*						outside this range and need to be regenerated. With higher skew (see below),
+*						this might change.
+*	spread: 45 - The random standard deviation of the calculated distribution. A higher value
+*				will make it more likely to have extreme values, a lower value will make any
+*				generated values cluster around the mean. If spread is 0, it will always return the mean.
+*	skew: 0 - How much the height distribution skews to the right (positive) or left (negative) side
+*				of the height. Unless you have a very specific reason, you should not need to change this.
+*				Minimum value: -1000, maximum value: 1000
+*	limitIntelligence: [-100,100] - Limit the resulting height range.
+*									Warning: A small intelligence limit range not containing the
+*									mean, and with a low spread value results in the generator
+*									having to do lots of work generating and re-generating random
+*									intelligences until one "fits".
+*
+*  This was modeled using the Height generator above. For some more information, see the comments for that.
+*/
 window.Intelligence = (function() {
 	"use strict";
 
@@ -890,6 +890,11 @@ window.Categorizer.prototype.cat = function(val, def) {
 	return result;
 };
 
+/**
+ * Returns numbers as text, e.g. 10 as "ten".
+ * @param {number} x
+ * @returns {string}
+ */
 window.num = function(x) {
 	const V = State.variables;
 	const max = V.showNumbersMax;
@@ -908,12 +913,20 @@ window.num = function(x) {
 
 	const SCALES = ["thousand", "million", "billion", "trillion"];
 
-	// helper function for use with Array.filter
+	/**
+	 * helper function for use with Array.filter
+	 * @param {any} item
+	 * @returns {boolean}
+	 */
 	function isTruthy(item) {
 		return !!item;
 	}
 
-	// convert a number into "chunks" of 0-999
+	/**
+	 * convert a number into "chunks" of 0-999
+	 * @param {number} number
+	 * @returns {number[]}
+	 */
 	function chunk(number) {
 		const thousands = [];
 
@@ -925,7 +938,11 @@ window.num = function(x) {
 		return thousands;
 	}
 
-	// translate a number from 1-999 into English
+	/**
+	 * translate a number from 1-999 into English
+	 * @param {number} number
+	 * @returns {string}
+	 */
 	function inEnglish(number) {
 		let hundreds;
 		let tens;
@@ -954,7 +971,12 @@ window.num = function(x) {
 		return words.filter(isTruthy).join(" ");
 	}
 
-	// append the word for a scale. Made for use with Array.map
+	/**
+	 * append the word for a scale. Made for use with Array.map
+	 * @param {string} chunk
+	 * @param {number} exp
+	 * @returns {string}
+	 */
 	function appendScale(chunk, exp) {
 		let scale;
 		if (!chunk) {
@@ -964,12 +986,16 @@ window.num = function(x) {
 		return [chunk, scale].filter(isTruthy).join(" ");
 	}
 
+	/**
+	 * @param {number} s
+	 * @returns {string}
+	 */
 	function commaNum(s) {
 		if (!s) {
-			return 0;
+			return "0";
 		}
 		if (State.variables.formatNumbers !== 1) {
-			return s;
+			return s.toString();
 		} else {
 			return s.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 		}
@@ -980,7 +1006,7 @@ window.num = function(x) {
 			return "zero";
 		}
 
-		let string = chunk(x)
+		let numberAsString = chunk(x)
 			.map(inEnglish)
 			.map(appendScale)
 			.filter(isTruthy)
@@ -990,18 +1016,18 @@ window.num = function(x) {
 		if (V.showNumbers === 1) {
 			if (x <= max) {
 				if (x > 0) {
-					return string;
+					return numberAsString;
 				} else {
-					return `negative ${string}`;
+					return `negative ${numberAsString}`;
 				}
 			} else {
 				return commaNum(x);
 			}
 		} else {
 			if (x > 0) {
-				return string;
+				return numberAsString;
 			} else {
-				return `negative ${string}`;
+				return `negative ${numberAsString}`;
 			}
 		}
 	} else {
@@ -1009,6 +1035,10 @@ window.num = function(x) {
 	}
 };
 
+/**
+ * @param {number} s
+ * @returns {string}
+ */
 window.cashFormat = function(s) {
 	if (!s) {
 		s = 0;
@@ -1022,6 +1052,10 @@ window.cashFormat = function(s) {
 	}
 };
 
+/**
+ * @param {number} s
+ * @returns {string}
+ */
 window.repFormat = function(s) {
 	const V = State.variables;
 	/* if (!s) { s = 0; }*/
@@ -1063,6 +1097,10 @@ window.repFormat = function(s) {
 	}
 };
 
+/**
+ * @param {number} s
+ * @returns {string}
+ */
 window.massFormat = function(s) {
 	if (!s) {
 		s = 0;
@@ -1079,6 +1117,11 @@ window.massFormat = function(s) {
 	}
 };
 
+/**
+ * @param {string} category
+ * @param {string} title
+ * @returns {string}
+ */
 window.budgetLine = function(category, title) {
 	let income;
 	let expenses;
@@ -1130,14 +1173,28 @@ window.budgetLine = function(category, title) {
 	}
 };
 
+/**
+ * @param {number} n
+ * @returns {boolean}
+ */
 window.isFloat = function(n) {
 	return Number.isFinite(n) && Math.floor(n) !== n;
 };
 
+/**
+ * @param {number} min
+ * @param {number} max
+ * @returns {number}
+ */
 window.jsRandom = function(min, max) {
 	return Math.floor(Math.random() * (max - min + 1) + min);
 };
 
+/**
+ * @param {number[]} arr
+ * @param {number} count
+ * @returns {number[]}
+ */
 window.jsRandomMany = function(arr, count) {
 	let result = [];
 	let _tmp = arr.slice();
@@ -1148,7 +1205,12 @@ window.jsRandomMany = function(arr, count) {
 	return result;
 };
 
-// accepts both an array and a list, returns undefined if nothing is passed.
+/**
+ * Accepts both an array and a list, returns undefined if nothing is passed.
+ * @param {number|string|number[]|string[]} choices
+ * @param {...(number|string|number[]|string[])} otherChoices
+ * @returns {number|string|number[]|string[]|undefined}
+ */
 window.jsEither = function(choices, ...otherChoices) {
 	if (otherChoices.length === 0 && Array.isArray(choices)) {
 		return choices[Math.floor(Math.random() * choices.length)];
@@ -1172,6 +1234,10 @@ if(typeof Categorizer === 'function') {
 */
 jQuery(document).trigger("categorizer.ready");
 
+/**
+ * @param {number[]} obj
+ * @returns {number}
+ */
 window.hashChoice = function hashChoice(obj) {
 	let randint = Math.floor(Math.random() * hashSum(obj));
 	let ret;
@@ -1187,6 +1253,10 @@ window.hashChoice = function hashChoice(obj) {
 	return ret;
 };
 
+/**
+ * @param {number[]} obj
+ * @returns {number}
+ */
 window.hashSum = function hashSum(obj) {
 	let sum = 0;
 	Object.keys(obj).forEach((key) => {
@@ -1195,6 +1265,10 @@ window.hashSum = function hashSum(obj) {
 	return sum;
 };
 
+/**
+ * @param {Array} arr
+ * @returns {Object}
+ */
 window.arr2obj = function arr2obj(arr) {
 	const obj = {};
 	arr.forEach((item) => {
@@ -1219,10 +1293,16 @@ window.weightedArray2HashMap = function weightedArray2HashMap(arr) {
 	return obj;
 };
 
-
+/**
+ * Determines if a is between low and high
+ * @param {number} a
+ * @param {number} low
+ * @param {number} high
+ * @returns {boolean}
+ */
 window.between = function between(a, low, high) {
-	if (low === null) low = -Infinity;
-	if (high === null) high = Infinity;
+	if (low === null) { low = -Infinity; }
+	if (high === null) { high = Infinity; }
 	return (a > low && a < high);
 };
 
@@ -1237,6 +1317,11 @@ window.generateNewID = function generateNewID() {
 	return uuid;
 };
 
+/**
+ * @param {Array} array
+ * @param {number} a
+ * @param {number} b
+ */
 window.arraySwap = function arraySwap(array, a, b) {
 	const tmp = array[a];
 	array[a] = array[b];
@@ -1254,7 +1339,11 @@ window.html5passage = function html5passage(passageFunction) {
 	});
 };
 
-// If you want to include a SugarCube passage in a JS function use this. The result must be printed using the <<print>> macro. passageTitle must be a string.
+/**
+ * If you want to include a SugarCube passage in a JS function use this. The result must be printed using the <<print>> macro.
+ * @param {string} passageTitle
+ * @returns {string}
+ */
 window.jsInclude = function(passageTitle) {
 	if (Story.has(passageTitle)) {
 		return Story.get(passageTitle).processText();
@@ -1263,27 +1352,35 @@ window.jsInclude = function(passageTitle) {
 	}
 };
 
+/**
+ * @param {string} string
+ * @returns {string}
+ */
 window.capFirstChar = function capFirstChar(string) {
 	return string.charAt(0).toUpperCase() + string.substr(1);
 };
 
+/**
+ * @param {string} word
+ * @returns {string}
+ */
 window.addA = function(word) {
 	let vocal = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'];
 	if (vocal.includes(word.charAt(0))) {
-		return "an " + word;
+		return `an ${word}`;
 	}
-	return "a " + word;
+	return `a ${word}`;
 };
 
 /**
- * @param {App.Entity.SlaveState} slave
- * @returns {string}
- */
+* @param {App.Entity.SlaveState} slave
+* @returns {string}
+*/
 window.getSlaveDevotionClass = function(slave) {
 	if ((!slave) || (!State)) {
 		return undefined;
 	}
-	if ("mindbroken" === slave.fetish) {
+	if (slave.fetish === "mindbroken") {
 		return "mindbroken";
 	}
 	if (slave.devotion < -95) {
@@ -1304,15 +1401,15 @@ window.getSlaveDevotionClass = function(slave) {
 };
 
 /**
- * @param {App.Entity.SlaveState} slave
- * @returns {string}
- */
+* @param {App.Entity.SlaveState} slave
+* @returns {string}
+*/
 window.getSlaveTrustClass = function(slave) {
 	if ((!slave) || (!State)) {
 		return undefined;
 	}
 
-	if ("mindbroken" === slave.fetish) {
+	if (slave.fetish === "mindbroken") {
 		return "";
 	}
 
@@ -1336,16 +1433,20 @@ window.getSlaveTrustClass = function(slave) {
 	}
 };
 
-// takes an integer e.g. $activeSlave.hLength, returns a string in the format 10 inches
+/**
+ * Takes an integer e.g. $activeSlave.hLength, returns a string in the format 10 inches
+* @param {number} s
+* @returns {string}
+*/
 window.cmToInchString = function(s) {
-	let inches = Math.round(s / 2.54);
-	if (inches === 0) {
+	let inches = (Math.round(s / 2.54)).toString();
+	if (inches === "0") {
 		if (s === 0) {
 			inches += " inches";
 		} else {
 			inches = "less than an inch";
 		}
-	} else if (inches === 1) {
+	} else if (inches === "1") {
 		inches += " inch";
 	} else {
 		inches += " inches";
@@ -1353,7 +1454,11 @@ window.cmToInchString = function(s) {
 	return inches;
 };
 
-// takes an integer e.g. $activeSlave.height, returns a string in the format 6'5"
+/**
+ * takes an integer e.g. $activeSlave.height, returns a string in the format 6'5"
+ * @param {number} s
+ * @returns {string}
+ */
 window.cmToFootInchString = function(s) {
 	if (Math.round(s / 2.54) < 12) {
 		return cmToInchString(s);
@@ -1361,12 +1466,20 @@ window.cmToFootInchString = function(s) {
 	return `${Math.trunc(Math.round(s/2.54)/12)}'${Math.round(s/2.54)%12}"`;
 };
 
-// takes a dick value e.g. $activeSlave.dick, returns a string in the format 6 inches
+/**
+ * takes a dick value e.g. $activeSlave.dick, returns a string in the format 6 inches
+ * @param {number} s
+ * @returns {string}
+ */
 window.dickToInchString = function(s) {
 	return cmToInchString(dickToCM(s));
 };
 
-// takes a dick value e.g. $activeSlave.dick, returns an int of the dick length in cm
+/**
+ * takes a dick value e.g. $activeSlave.dick, returns an int of the dick length in cm
+ * @param {number} s
+ * @returns {number}
+ */
 window.dickToCM = function(s) {
 	if (s < 9) {
 		return s * 5;
@@ -1453,9 +1566,9 @@ window.removeDuplicates = function removeDuplicates(array) {
 };
 
 /**
- * @param {App.Entity.SlaveState} slave
- * @returns {string}
- */
+* @param {App.Entity.SlaveState} slave
+* @returns {string}
+*/
 window.induceLactation = function induceLactation(slave) {
 	let pronouns = getPronouns(slave);
 	let His = capFirstChar(pronouns.possessive);
@@ -1496,9 +1609,9 @@ window.ResearchLabStockPile = function() {
 };
 
 /**
- * @param {App.Entity.SlaveState} slave
- * @returns {string}
- */
+* @param {App.Entity.SlaveState} slave
+* @returns {string}
+*/
 window.originPronounReplace = function(slave) {
 	let r = slave.origin;
 	switch (r) {
@@ -1622,21 +1735,21 @@ window.opentab = function(evt, tabName) {
 };
 
 /**
- * Creates a HTML element with custom SugarCube attributes which works as a passage link
- *
- * The result works in the same way as the wiki markup in the SugarCube
- * @see https://www.motoslave.net/sugarcube/2/docs/#markup-html-attribute
- * @param {string} linkText link text
- * @param {string} passage the passage name to link to
- * @param {string} [setter=''] setter tet (optional)
- * @param {string} [elementType='a'] element type (optional) default is 'a'.
- * Could be any of 'a', 'audio', img', 'source', 'video'
- * @returns {string} element text
- *
- * @example
- * // equal to [[Go to town|Town]]
- * App.UI.passageLink("Go to town", "Town")
- */
+* Creates a HTML element with custom SugarCube attributes which works as a passage link
+*
+* The result works in the same way as the wiki markup in the SugarCube
+* @see https://www.motoslave.net/sugarcube/2/docs/#markup-html-attribute
+* @param {string} linkText link text
+* @param {string} passage the passage name to link to
+* @param {string} [setter=''] setter tet (optional)
+* @param {string} [elementType='a'] element type (optional) default is 'a'.
+* Could be any of 'a', 'audio', img', 'source', 'video'
+* @returns {string} element text
+*
+* @example
+* // equal to [[Go to town|Town]]
+* App.UI.passageLink("Go to town", "Town")
+*/
 App.UI.passageLink = function(linkText, passage, setter, elementType) {
 	if (!elementType) elementType = "a";
 
@@ -1926,7 +2039,7 @@ window.jsDef = function(input) {
 /* Return a career at random that would be suitable for the given slave.
 
 	Currently only considers their age
- */
+*/
 window.randomCareer = function(slave) {
 	if (slave.actualAge < 16) {
 		return setup.veryYoungCareers.random();
@@ -2230,11 +2343,11 @@ window.FSDecorLevel = function(value) {
 
 
 /**
- * Creates a span for an link with tooltip containing the reasons why it is disabled
- * @param {string} link
- * @param {string[]} reasons
- * @returns {string}
- */
+* Creates a span for an link with tooltip containing the reasons why it is disabled
+* @param {string} link
+* @param {string[]} reasons
+* @returns {string}
+*/
 App.UI.disabledLink = function(link, reasons) {
 	const tooltips = reasons.length === 1 ?
 		`<span class="tooltip">${reasons}</span>`:
@@ -2243,27 +2356,27 @@ App.UI.disabledLink = function(link, reasons) {
 };
 
 /**
- * Expression for SugarCube for referencing a slave by index
- * @param {number} i slave array index or -1 for activeSlave
- * @returns {string}
- */
+* Expression for SugarCube for referencing a slave by index
+* @param {number} i slave array index or -1 for activeSlave
+* @returns {string}
+*/
 App.Utils.slaveRefString = function(i) {
 	return i >= 0 ? `$slaves[${i}]` : '$activeSlave';
 };
 
 /**
- * Returns slave by index in the slave array, Accepts -1 for the activeSlave
- * @param {number} i slave array index or -1 for activeSlave
- * @returns {App.Entity.SlaveState}
- */
+* Returns slave by index in the slave array, Accepts -1 for the activeSlave
+* @param {number} i slave array index or -1 for activeSlave
+* @returns {App.Entity.SlaveState}
+*/
 App.Utils.slaveByIndex = function(i) {
 	return i === -1 ? State.variables.activeSlave : State.variables.slaves[i];
 };
 
 /**
- * Sets active slave to the slave with the given index. Does nothing if index < 0
- * @param {number} index
- */
+* Sets active slave to the slave with the given index. Does nothing if index < 0
+* @param {number} index
+*/
 App.Utils.setActiveSlaveByIndex = function(index) {
 	if (index >= 0) {
 		State.variables.activeSlave = State.variables.slaves[index];