diff --git a/src/data/backwardsCompatibility/datatypeCleanup.js b/src/data/backwardsCompatibility/datatypeCleanup.js
index 6c747999a1efdcf08bf950f35cb13c77f66a18a0..dc90d89df371cd6010074b6819cac478d0874617 100644
--- a/src/data/backwardsCompatibility/datatypeCleanup.js
+++ b/src/data/backwardsCompatibility/datatypeCleanup.js
@@ -2073,10 +2073,13 @@ App.Entity.Utils.RARuleDatatypeCleanup = function() {
 
 	return ruleCleanup;
 
-	/** @param {FC.RA.Rule} rule */
+	/**
+	 * @param {FC.RA.Rule} rule
+	 * @returns {FC.RA.Rule}
+	 */
 	function ruleCleanup(rule) {
 		// ensure rule has all required properties
-		let newRule = App.RA.ruleDeepAssign(emptyDefaultRule(), rule);
+		let newRule = App.RA.ruleDeepAssign(emptyDefaultRule(), rule, {}, "");
 		cleanupConditions(newRule.condition);
 		cleanupSetters(newRule.set);
 		return newRule;
diff --git a/src/js/DefaultRules.js b/src/js/DefaultRules.js
index ea6789ee623f4e3b2650696473c34e7abfd50534..4cb6389756cfd5a2feb4633a40df5db1fd2312a0 100644
--- a/src/js/DefaultRules.js
+++ b/src/js/DefaultRules.js
@@ -9,7 +9,7 @@ globalThis.DefaultRules = function(slave) {
 	}
 
 	const slaveReadOnly = createReadonlyProxy(slave);
-	const {rule, ruleIds} = runWithReadonlyProxy(() => ProcessSlaveRules(slaveReadOnly));
+	const {rule, ruleIds, sourceRecord} = runWithReadonlyProxy(() => ProcessSlaveRules(slaveReadOnly));
 	slave.currentRules = ruleIds;
 	if (ruleIds.length === 0) {
 		return ""; // no rules apply
@@ -85,19 +85,23 @@ globalThis.DefaultRules = function(slave) {
 
 	/**
 	 * @param {App.Entity.SlaveState} slave
-	 * @returns {{ruleIds: string[], rule: FC.RA.RuleSetters}}}
+	 * @returns {{ruleIds: string[], rule: FC.RA.RuleSetters, sourceRecord: object}}
 	 */
 	function ProcessSlaveRules(slave) {
 		// merge all rules applying on a slave into one big rule
 		/** @type {FC.RA.Rule[]} */
 		const rules = V.defaultRules.filter((rule) => ruleAppliesP(rule, slave));
 		const ruleIds = [];
+		/**
+		 * @type {Array<[FC.RA.RuleSetters, string]>}
+		 */
 		const assignments = [];
 		for (const rule of rules) {
 			ruleIds.push(rule.ID);
-			assignments.push(ProcessAssignments(slave, Object.assign({}, rule.set)));
+			assignments.push([ProcessAssignments(slave, Object.assign({}, rule.set)), rule.name]);
 		}
-		return {ruleIds, rule: mergeRules(assignments)};
+		const [combinedRule, sourceRecord] = mergeRules(assignments);
+		return {ruleIds, rule: combinedRule, sourceRecord};
 	}
 
 	/**
@@ -191,16 +195,16 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.clothes !== rule.clothes) {
 				slave.clothes = rule.clothes;
 				slave.choosesOwnClothes = 0;
-				r += `<br>${slave.slaveName} is now wearing ${slave.clothes}.`;
+				message(`${slave.slaveName} is now wearing ${slave.clothes}.`, sourceRecord.clothes);
 			}
 		}
 		if ((rule.choosesOwnClothes !== undefined) && (rule.choosesOwnClothes !== null)) {
 			if (slave.choosesOwnClothes !== rule.choosesOwnClothes) {
 				slave.choosesOwnClothes = rule.choosesOwnClothes;
 				if (slave.choosesOwnClothes) {
-					r += `<br>${slave.slaveName} is now allowed to choose ${his} own clothes.`;
+					message(`${slave.slaveName} is now allowed to choose ${his} own clothes.`, sourceRecord.choosesOwnClothes);
 				} else {
-					r += `<br>${slave.slaveName} is now forbidden from choosing ${his} own clothes.`;
+					message(`${slave.slaveName} is now forbidden from choosing ${his} own clothes.`, sourceRecord.choosesOwnClothes);
 				}
 			}
 		}
@@ -214,21 +218,21 @@ globalThis.DefaultRules = function(slave) {
 		// apply collar to slave
 		if ((rule.collar !== undefined) && (rule.collar !== null)) {
 			if (slave.collar !== rule.collar) {
-				r += "<br>";
+				let m = "";
 				if (rule.collar === "preg biometrics" && slave.preg <= -1 && slave.ovaries === 0 && slave.mpreg === 0) {
 					slave.collar = "none";
-					r += `${slave.slaveName} cannot utilize preg biometrics. `;
+					m = `${slave.slaveName} cannot utilize preg biometrics. `;
 				} else {
 					slave.collar = rule.collar;
 				}
 				if (slave.collar === "none") {
-					r += `${slave.slaveName} has been given no collar.`;
+					message(`${m}${slave.slaveName} has been given no collar.`, sourceRecord.collar);
 				} else if (slave.collar === "pretty jewelry") {
-					r += `${slave.slaveName} has been given ${slave.collar}.`;
+					message(`${m}${slave.slaveName} has been given ${slave.collar}.`, sourceRecord.collar);
 				} else if ((["bell collar", "bowtie", "neck corset", "neck tie"].includes(slave.collar))) {
-					r += `${slave.slaveName} has been given a ${slave.collar}.`;
+					message(`${m}${slave.slaveName} has been given a ${slave.collar}.`, sourceRecord.collar);
 				} else {
-					r += `${slave.slaveName} has been given a ${slave.collar} collar.`;
+					message(`${m}${slave.slaveName} has been given a ${slave.collar} collar.`, sourceRecord.collar);
 				}
 			}
 		}
@@ -242,12 +246,11 @@ globalThis.DefaultRules = function(slave) {
 		// apply faceAccessory to slave
 		if ((rule.faceAccessory !== undefined) && (rule.faceAccessory !== null)) {
 			if (slave.faceAccessory !== rule.faceAccessory) {
-				r += "<br>";
 				slave.faceAccessory = rule.faceAccessory;
 				if (slave.faceAccessory === "none") {
-					r += `${slave.slaveName} has had their mask removed.`;
+					message(`${slave.slaveName} has had their mask removed.`, sourceRecord.faceAccessory);
 				} else {
-					r += `${slave.slaveName} has been given a ${slave.faceAccessory}.`;
+					message(`${slave.slaveName} has been given a ${slave.faceAccessory}.`, sourceRecord.faceAccessory);
 				}
 			}
 		}
@@ -261,17 +264,17 @@ globalThis.DefaultRules = function(slave) {
 		// apply mouthAccessory to slave
 		if ((rule.mouthAccessory !== undefined) && (rule.mouthAccessory !== null)) {
 			if (slave.mouthAccessory !== rule.mouthAccessory) {
-				r += "<br>";
+				let m = "";
 				if (rule.mouthAccessory === "massive dildo gag" && slave.skill.oral <= 50) {
 					slave.mouthAccessory = "none";
-					r += `${slave.slaveName} lacks the oral skill to successfully keep the massive dildo gag in ${his} throat. `;
+					m = `${slave.slaveName} lacks the oral skill to successfully keep the massive dildo gag in ${his} throat. `;
 				} else {
 					slave.mouthAccessory = rule.mouthAccessory;
 				}
 				if (slave.mouthAccessory === "none") {
-					r += `${slave.slaveName} has been given no gag.`;
+					message(`${m}}${slave.slaveName} has been given no gag.`, sourceRecord.mouthAccessory);
 				} else {
-					r += `${slave.slaveName} has been given a ${slave.mouthAccessory}.`;
+					message(`${m}}${slave.slaveName} has been given a ${slave.mouthAccessory}.`, sourceRecord.mouthAccessory);
 				}
 			}
 		}
@@ -290,12 +293,12 @@ globalThis.DefaultRules = function(slave) {
 						if (slave.eyewear !== "corrective glasses") {
 							slave.eyewear = "corrective glasses";
 							cashX(forceNeg(V.modCost), "slaveMod", slave);
-							r += `<br>${slave.slaveName} has been given corrective glasses.`;
+							message(`${slave.slaveName} has been given corrective glasses.`, sourceRecord.eyewear);
 						}
 					} else {
 						if (slave.eyewear !== "none") {
 							slave.eyewear = "none";
-							r += `<br>${slave.slaveName}'s eyewear has been removed.`;
+							message(`${slave.slaveName}'s eyewear has been removed.`, sourceRecord.eyewear);
 						}
 					}
 					break;
@@ -305,12 +308,12 @@ globalThis.DefaultRules = function(slave) {
 						if (slave.eyewear !== "corrective contacts") {
 							slave.eyewear = "corrective contacts";
 							cashX(forceNeg(V.modCost), "slaveMod", slave);
-							r += `<br>${slave.slaveName} has been given corrective contacts.`;
+							message(`${slave.slaveName} has been given corrective contacts.`, sourceRecord.eyewear);
 						}
 					} else {
 						if (slave.eyewear !== "none") {
 							slave.eyewear = "none";
-							r += `<br>${slave.slaveName}'s eyewear has been removed.`;
+							message(`${slave.slaveName}'s eyewear has been removed.`, sourceRecord.eyewear);
 						}
 					}
 					break;
@@ -320,12 +323,12 @@ globalThis.DefaultRules = function(slave) {
 						if (slave.eyewear !== "blurring glasses") {
 							slave.eyewear = "blurring glasses";
 							cashX(forceNeg(V.modCost), "slaveMod", slave);
-							r += `<br>${slave.slaveName} has been given blurring glasses.`;
+							message(`${slave.slaveName} has been given blurring glasses.`, sourceRecord.eyewear);
 						}
 					} else {
 						if (slave.eyewear !== "none") {
 							slave.eyewear = "none";
-							r += `<br>${slave.slaveName}'s eyewear has been removed.`;
+							message(`${slave.slaveName}'s eyewear has been removed.`, sourceRecord.eyewear);
 						}
 					}
 					break;
@@ -335,12 +338,12 @@ globalThis.DefaultRules = function(slave) {
 						if (slave.eyewear !== "blurring contacts") {
 							slave.eyewear = "blurring contacts";
 							cashX(forceNeg(V.modCost), "slaveMod", slave);
-							r += `<br>${slave.slaveName} has been given blurring contacts.`;
+							message(`${slave.slaveName} has been given blurring contacts.`, sourceRecord.eyewear);
 						}
 					} else {
 						if (slave.eyewear !== "none") {
 							slave.eyewear = "none";
-							r += `<br>${slave.slaveName}'s eyewear has been removed.`;
+							message(`${slave.slaveName}'s eyewear has been removed.`, sourceRecord.eyewear);
 						}
 					}
 					break;
@@ -350,13 +353,13 @@ globalThis.DefaultRules = function(slave) {
 						if (slave.eyewear !== "corrective glasses") {
 							slave.eyewear = "corrective glasses";
 							cashX(forceNeg(V.modCost), "slaveMod", slave);
-							r += `<br>${slave.slaveName} has been given corrective glasses.`;
+							message(`${slave.slaveName} has been given corrective glasses.`, sourceRecord.eyewear);
 						}
 					} else {
 						if (slave.eyewear !== "glasses") {
 							slave.eyewear = "glasses";
 							cashX(forceNeg(V.modCost), "slaveMod", slave);
-							r += `<br>${slave.slaveName} has been given decorative glasses.`;
+							message(`${slave.slaveName} has been given decorative glasses.`, sourceRecord.eyewear);
 						}
 					}
 					break;
@@ -364,7 +367,7 @@ globalThis.DefaultRules = function(slave) {
 				default:
 					if (slave.eyewear !== "none") {
 						slave.eyewear = "none";
-						r += `<br>${slave.slaveName}'s eyewear has been removed.`;
+						message(`${slave.slaveName}'s eyewear has been removed.`, sourceRecord.eyewear);
 					}
 					break;
 			}
@@ -384,12 +387,12 @@ globalThis.DefaultRules = function(slave) {
 						if (slave.earwear !== "hearing aids") {
 							slave.earwear = "hearing aids";
 							cashX(forceNeg(V.modCost), "slaveMod", slave);
-							r += `<br>${slave.slaveName} has been given hearing aids.`;
+							message(`${slave.slaveName} has been given hearing aids.`, sourceRecord.earwear);
 						}
 					} else {
 						if (slave.earwear !== "none") {
 							slave.earwear = "none";
-							r += `<br>${slave.slaveName}'s earwear has been removed.`;
+							message(`${slave.slaveName}'s earwear has been removed.`, sourceRecord.earwear);
 						}
 					}
 					break;
@@ -399,12 +402,12 @@ globalThis.DefaultRules = function(slave) {
 						if (slave.earwear !== "muffling ear plugs") {
 							slave.earwear = "muffling ear plugs";
 							cashX(forceNeg(V.modCost), "slaveMod", slave);
-							r += `<br>${slave.slaveName} has been given muffling ear plugs.`;
+							message(`${slave.slaveName} has been given muffling ear plugs.`, sourceRecord.earwear);
 						}
 					} else {
 						if (slave.earwear !== "none") {
 							slave.earwear = "none";
-							r += `<br>${slave.slaveName}'s earwear has been removed.`;
+							message(`${slave.slaveName}'s earwear has been removed.`, sourceRecord.earwear);
 						}
 					}
 					break;
@@ -414,12 +417,12 @@ globalThis.DefaultRules = function(slave) {
 						if (slave.earwear !== "deafening ear plugs") {
 							slave.earwear = "deafening ear plugs";
 							cashX(forceNeg(V.modCost), "slaveMod", slave);
-							r += `<br>${slave.slaveName} has been given deafening ear plugs.`;
+							message(`${slave.slaveName} has been given deafening ear plugs.`, sourceRecord.earwear);
 						}
 					} else {
 						if (slave.earwear !== "none") {
 							slave.earwear = "none";
-							r += `<br>${slave.slaveName}'s earwear has been removed.`;
+							message(`${slave.slaveName}'s earwear has been removed.`, sourceRecord.earwear);
 						}
 					}
 					break;
@@ -427,7 +430,7 @@ globalThis.DefaultRules = function(slave) {
 				default:
 					if (slave.earwear !== "none") {
 						slave.earwear = "none";
-						r += `<br>${slave.slaveName}'s earwear has been removed.`;
+						message(`${slave.slaveName}'s earwear has been removed.`, sourceRecord.earwear);
 					}
 					break;
 			}
@@ -461,50 +464,50 @@ globalThis.DefaultRules = function(slave) {
 				slave.vaginalAccessory = rule.virginAccessory;
 				switch (slave.vaginalAccessory) {
 					case "huge dildo":
-						r += `<br>${slave.slaveName} is a virgin and has been given a `;
+						const m = `${slave.slaveName} is a virgin and has been given a`;
 						if (slave.vagina >= 2) {
-							r += `massive dildo to permanently gape ${his} cunt.`;
+							message(`${m} massive dildo to permanently gape ${his} cunt.`, sourceRecord.virginAccessory);
 						} else {
-							r += `large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`;
+							message(`${m} large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`, sourceRecord.virginAccessory);
 							slave.vaginalAccessory = "large dildo";
 						}
 						break;
 
 					case "long dildo":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length dildo for ${his} pussy.`;
+							message(`Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length dildo for ${his} pussy.`, sourceRecord.virginAccessory);
 							slave.vaginalAccessory = "dildo";
 						}
 						break;
 
 					case "long, large dildo":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length large dildo for ${his} pussy.`;
+							message(`Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length large dildo for ${his} pussy.`, sourceRecord.virginAccessory);
 							slave.vaginalAccessory = "large dildo";
 						}
 						break;
 
 					case "long, huge dildo":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length huge dildo for ${his} pussy.`;
+							message(`Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length huge dildo for ${his} pussy.`, sourceRecord.virginAccessory);
 							slave.vaginalAccessory = "huge dildo";
 						} else {
-							r += `<br>${slave.slaveName} is a virgin and has been given a `;
+							const m = `${slave.slaveName} is a virgin and has been given a`;
 							if (slave.vagina >= 2) {
-								r += `massive and oversized dildo to permanently gape ${his} cunt.`;
+								message(`${m} massive and oversized dildo to permanently gape ${his} cunt.`, sourceRecord.virginAccessory);
 							} else {
-								r += `long, large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`;
+								message(`${m} long, large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`, sourceRecord.virginAccessory);
 								slave.vaginalAccessory = "long, large dildo";
 							}
 						}
 						break;
 
 					case "none":
-						r += `<br>${slave.slaveName} is a virgin and has been instructed not to use a vaginal accessory.`;
+						message(`${slave.slaveName} is a virgin and has been instructed not to use a vaginal accessory.`, sourceRecord.virginAccessory);
 						break;
 
 					default:
-						r += `<br>${slave.slaveName} is a virgin and has been given a ${slave.vaginalAccessory} for ${his} pussy.`;
+						message(`${slave.slaveName} is a virgin and has been given a ${slave.vaginalAccessory} for ${his} pussy.`, sourceRecord.virginAccessory);
 						break;
 				}
 			}
@@ -522,50 +525,50 @@ globalThis.DefaultRules = function(slave) {
 				slave.vaginalAccessory = rule.aVirginAccessory;
 				switch (slave.vaginalAccessory) {
 					case "huge dildo":
-						r += `<br>${slave.slaveName} is a virgin and has been given a `;
+						const m = `${slave.slaveName} is a virgin and has been given a`;
 						if (slave.vagina >= 2) {
-							r += `massive dildo to permanently gape ${his} cunt.`;
+							message(`${m} massive dildo to permanently gape ${his} cunt.`, sourceRecord.aVirginAccessory);
 						} else {
-							r += `large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`;
+							message(`${m} large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`, sourceRecord.aVirginAccessory);
 							slave.vaginalAccessory = "large dildo";
 						}
 						break;
 
 					case "long dildo":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length dildo for ${his} pussy.`;
+							message(`Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length dildo for ${his} pussy.`, sourceRecord.aVirginAccessory);
 							slave.vaginalAccessory = "dildo";
 						}
 						break;
 
 					case "long, large dildo":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length large dildo for ${his} pussy.`;
+							message(`Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length large dildo for ${his} pussy.`, sourceRecord.aVirginAccessory);
 							slave.vaginalAccessory = "large dildo";
 						}
 						break;
 
 					case "long, huge dildo":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length huge dildo for ${his} pussy.`;
+							message(`Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so the virgin ${slave.slaveName} has been given a standard length huge dildo for ${his} pussy.`, sourceRecord.aVirginAccessory);
 							slave.vaginalAccessory = "huge dildo";
 						} else {
-							r += `<br>${slave.slaveName} is a virgin and has been given a `;
+							const m = `${slave.slaveName} is a virgin and has been given a`;
 							if (slave.vagina >= 2) {
-								r += `massive and oversized dildo to permanently gape ${his} cunt.`;
+								message(`${m} massive and oversized dildo to permanently gape ${his} cunt.`, sourceRecord.aVirginAccessory);
 							} else {
-								r += `long, large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`;
+								message(`${m} long, large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`, sourceRecord.aVirginAccessory);
 								slave.vaginalAccessory = "long, large dildo";
 							}
 						}
 						break;
 
 					case "none":
-						r += `<br>${slave.slaveName} is a virgin and has been instructed not to use a vaginal accessory.`;
+						message(`${slave.slaveName} is a virgin and has been instructed not to use a vaginal accessory.`, sourceRecord.aVirginAccessory);
 						break;
 
 					default:
-						r += `<br>${slave.slaveName} is a virgin and has been given a ${slave.vaginalAccessory} for ${his} pussy.`;
+						message(`${slave.slaveName} is a virgin and has been given a ${slave.vaginalAccessory} for ${his} pussy.`, sourceRecord.aVirginAccessory);
 						break;
 				}
 			}
@@ -583,49 +586,49 @@ globalThis.DefaultRules = function(slave) {
 				slave.vaginalAccessory = rule.vaginalAccessory;
 				switch (slave.vaginalAccessory) {
 					case "huge dildo":
-						r += `<br>${slave.slaveName} has been given a `;
+						const m = `${slave.slaveName} has been given a`;
 						if (slave.vagina >= 2) {
-							r += `massive dildo to permanently gape ${his} cunt.`;
+							message(`${m} massive dildo to permanently gape ${his} cunt.`, sourceRecord.vaginalAccessory);
 						} else {
-							r += `large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`;
+							message(`${m} large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`, sourceRecord.vaginalAccessory);
 							slave.vaginalAccessory = "large dildo";
 						}
 						break;
 
 					case "long dildo":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so ${slave.slaveName} has been given a standard length dildo for ${his} pussy.`;
+							message(`Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so ${slave.slaveName} has been given a standard length dildo for ${his} pussy.`, sourceRecord.vaginalAccessory);
 							slave.vaginalAccessory = "dildo";
 						}
 						break;
 
 					case "long, large dildo":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so ${slave.slaveName} has been given a standard length large dildo for ${his} pussy.`;
+							message(`Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so ${slave.slaveName} has been given a standard length large dildo for ${his} pussy.`, sourceRecord.vaginalAccessory);
 							slave.vaginalAccessory = "large dildo";
 						}
 						break;
 
 					case "long, huge dildo":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so ${slave.slaveName} has been given a standard length huge dildo for ${his} pussy.`;
+							message(`Breeding regulations forbid the use of cervix penetrating dildos on marked slaves, so ${slave.slaveName} has been given a standard length huge dildo for ${his} pussy.`, sourceRecord.vaginalAccessory);
 							slave.vaginalAccessory = "huge dildo";
 						} else {
-							r += `<br>${slave.slaveName} has been given a `;
+							const m = `${slave.slaveName} has been given a`;
 							if (slave.vagina >= 2) {
-								r += `massive and oversized dildo to permanently gape ${his} cunt.`;
+								message(`${m} massive and oversized dildo to permanently gape ${his} cunt.`, sourceRecord.vaginalAccessory);
 							} else {
-								r += `long, large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`;
+								message(`${m} long, large dildo for ${his} pussy, since it must be stretched before it can accommodate a huge one.`, sourceRecord.vaginalAccessory);
 								slave.vaginalAccessory = "long, large dildo";
 							}
 						}
 						break;
 					case "none":
-						r += `<br>${slave.slaveName} has been instructed not to use a vaginal accessory.`;
+						message(`${slave.slaveName} has been instructed not to use a vaginal accessory.`, sourceRecord.vaginalAccessory);
 						break;
 
 					default:
-						r += `<br>${slave.slaveName} has been given a ${slave.vaginalAccessory} for ${his} pussy.`;
+						message(`${slave.slaveName} has been given a ${slave.vaginalAccessory} for ${his} pussy.`, sourceRecord.vaginalAccessory);
 						break;
 				}
 			}
@@ -646,29 +649,29 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.vaginalAccessory !== "none") {
 					switch (slave.vaginalAttachment) {
 						case "none":
-							r += `<br>${slave.slaveName} has been instructed not to use an attachment for ${his} dildo.`;
+							message(`${slave.slaveName} has been instructed not to use an attachment for ${his} dildo.`, sourceRecord.vaginalAttachment);
 							break;
 
 						case "vibrator":
-							r += `<br>${slave.slaveName}'s dildo has been replaced with a vibrating model.`;
+							message(`${slave.slaveName}'s dildo has been replaced with a vibrating model.`, sourceRecord.vaginalAttachment);
 							break;
 
 						case "smart vibrator":
-							r += `<br>${slave.slaveName}'s dildo has been replaced with a smart vibrating model.`;
+							message(`${slave.slaveName}'s dildo has been replaced with a smart vibrating model.`, sourceRecord.vaginalAttachment);
 							break;
 
 						default:
-							r += `<br>${slave.slaveName} has been given a ${slave.vaginalAttachment}.`;
+							message(`${slave.slaveName} has been given a ${slave.vaginalAttachment}.`, sourceRecord.vaginalAttachment);
 							break;
 					}
 				} else {
 					switch (slave.vaginalAttachment) {
 						case "none":
-							r += `<br>${slave.slaveName} has been instructed not to use any vaginal accessories.`;
+							message(`${slave.slaveName} has been instructed not to use any vaginal accessories.`, sourceRecord.vaginalAttachment);
 							break;
 
 						default:
-							r += `<br>${slave.slaveName} has been given a ${slave.vaginalAttachment}.`;
+							message(`${slave.slaveName} has been given a ${slave.vaginalAttachment}.`, sourceRecord.vaginalAttachment);
 							break;
 					}
 				}
@@ -688,9 +691,9 @@ globalThis.DefaultRules = function(slave) {
 					if (slave.dickAccessory !== rule.aVirginDickAccessory) {
 						slave.dickAccessory = rule.aVirginDickAccessory;
 						if (slave.dickAccessory === "none") {
-							r += `<br>${slave.slaveName} is a virgin and has been instructed not to wear a dick accessory.`;
+							message(`${slave.slaveName} is a virgin and has been instructed not to wear a dick accessory.`, sourceRecord.aVirginDickAccessory);
 						} else {
-							r += `<br>${slave.slaveName} is a virgin and has been given a ${slave.dickAccessory} accessory for ${his} cock.`;
+							message(`${slave.slaveName} is a virgin and has been given a ${slave.dickAccessory} accessory for ${his} cock.`, sourceRecord.aVirginDickAccessory);
 						}
 					}
 				}
@@ -699,9 +702,9 @@ globalThis.DefaultRules = function(slave) {
 					if (slave.dickAccessory !== rule.dickAccessory) {
 						slave.dickAccessory = rule.dickAccessory;
 						if (slave.dickAccessory === "none") {
-							r += `<br>${slave.slaveName} has been instructed not to wear a dick accessory.`;
+							message(`${slave.slaveName} has been instructed not to wear a dick accessory.`, sourceRecord.aVirginDickAccessory);
 						} else {
-							r += `<br>${slave.slaveName} has been given a ${slave.dickAccessory} accessory for ${his} cock.`;
+							message(`${slave.slaveName} has been given a ${slave.dickAccessory} accessory for ${his} cock.`, sourceRecord.aVirginDickAccessory);
 						}
 					}
 				}
@@ -720,9 +723,9 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.chastityVagina !== rule.chastityVagina) {
 					slave.chastityVagina = rule.chastityVagina;
 					if (rule.chastityVagina === 1) {
-						r += `<br>${slave.slaveName} has been given a chastity belt to wear.`;
+						message(`${slave.slaveName} has been given a chastity belt to wear.`, sourceRecord.chastityVagina);
 					} else {
-						r += `<br>${slave.slaveName}'s vaginal chastity has been removed.`;
+						message(`${slave.slaveName}'s vaginal chastity has been removed.`, sourceRecord.chastityVagina);
 					}
 				}
 			}
@@ -732,9 +735,9 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.chastityPenis !== rule.chastityPenis) {
 					slave.chastityPenis = rule.chastityPenis;
 					if (rule.chastityPenis === 1) {
-						r += `<br>${slave.slaveName} has been given a chastity cage to wear.`;
+						message(`${slave.slaveName} has been given a chastity cage to wear.`, sourceRecord.chastityPenis);
 					} else {
-						r += `<br>${slave.slaveName}'s chastity cage has been removed.`;
+						message(`${slave.slaveName}'s chastity cage has been removed.`, sourceRecord.chastityPenis);
 					}
 				}
 			}
@@ -743,9 +746,9 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.chastityAnus !== rule.chastityAnus) {
 				slave.chastityAnus = rule.chastityAnus;
 				if (rule.chastityAnus === 1) {
-					r += `<br>${slave.slaveName} has been given anal chastity to wear.`;
+					message(`${slave.slaveName} has been given anal chastity to wear.`, sourceRecord.chastityAnus);
 				} else {
-					r += `<br>${slave.slaveName}'s anal chastity has been removed.`;
+					message(`${slave.slaveName}'s anal chastity has been removed.`, sourceRecord.chastityAnus);
 				}
 			}
 		}
@@ -761,7 +764,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.shoes !== rule.shoes) {
 				if (hasAnyLegs(slave)) {
 					slave.shoes = rule.shoes;
-					r += `<br>${slave.slaveName}'s shoes have been set to ${slave.shoes}.`;
+					message(`${slave.slaveName}'s shoes have been set to ${slave.shoes}.`, sourceRecord.shoes);
 				}
 			}
 		}
@@ -776,14 +779,14 @@ globalThis.DefaultRules = function(slave) {
 		if ((rule.bellyAccessory !== undefined) && (rule.bellyAccessory !== null)) {
 			if (slave.bellyAccessory !== rule.bellyAccessory) {
 				if ((slave.belly >= 1500 || slave.weight >= 130) && App.Data.misc.fakeBellies.includes(rule.bellyAccessory)) {
-					r += `<br>${slave.slaveName}'s natural belly is too big to properly wear an empathy belly.`;
+					message(`${slave.slaveName}'s natural belly is too big to properly wear an empathy belly.`, sourceRecord.bellyAccessory);
 					slave.bellyAccessory = "none";
 				} else {
 					slave.bellyAccessory = rule.bellyAccessory;
 					if (slave.bellyAccessory === "none") {
-						r += `<br>${slave.slaveName} has been instructed not to wear a torso accessory.`;
+						message(`${slave.slaveName} has been instructed not to wear a torso accessory.`, sourceRecord.bellyAccessory);
 					} else {
-						r += `<br>${slave.slaveName} has been given ${slave.bellyAccessory} to wear.`;
+						message(`${slave.slaveName} has been given ${slave.bellyAccessory} to wear.`, sourceRecord.bellyAccessory);
 					}
 				}
 			}
@@ -797,7 +800,7 @@ globalThis.DefaultRules = function(slave) {
 	function ProcessArmAccessory(slave, rule) {
 		if (rule.armAccessory !== undefined && rule.armAccessory !== null && hasAnyArms(slave) && slave.armAccessory !== rule.armAccessory) {
 			slave.armAccessory = rule.armAccessory;
-			r += `<br>${slave.slaveName}'s arm accessory was set to ${rule.armAccessory}.`;
+			message(`${slave.slaveName}'s arm accessory was set to ${rule.armAccessory}.`, sourceRecord.armAccessory);
 		}
 	}
 
@@ -808,7 +811,7 @@ globalThis.DefaultRules = function(slave) {
 	function ProcessLegAccessory(slave, rule) {
 		if (rule.legAccessory !== undefined && rule.legAccessory !== null && hasAnyLegs(slave) && slave.legAccessory !== rule.legAccessory) {
 			slave.legAccessory = rule.legAccessory;
-			r += `<br>${slave.slaveName}'s leg accessory was set to ${rule.legAccessory}.`;
+			message(`${slave.slaveName}'s leg accessory was set to ${rule.legAccessory}.`, sourceRecord.legAccessory);
 		}
 	}
 
@@ -839,50 +842,50 @@ globalThis.DefaultRules = function(slave) {
 				slave.buttplug = rule.aVirginButtplug;
 				switch (slave.buttplug) {
 					case "huge plug":
-						r += `<br>${slave.slaveName} is an anal virgin and has been given a `;
+						const m = `${slave.slaveName} is an anal virgin and has been given a`;
 						if (slave.anus >= 2) {
-							r += `massive plug to permanently gape ${his} asshole.`;
+							message(`${m} massive plug to permanently gape ${his} asshole.`, sourceRecord.aVirginButtplug);
 						} else {
 							slave.buttplug = "large plug";
-							r += `large buttplug for ${his} asshole, since it must be stretched before it can accommodate a huge one.`;
+							message(`${m} large buttplug for ${his} asshole, since it must be stretched before it can accommodate a huge one.`, sourceRecord.aVirginButtplug);
 						}
 						break;
 
 					case "long plug":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so the anal virgin ${slave.slaveName} has been given a standard length plug for ${his} anus.`;
+							message(`Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so the anal virgin ${slave.slaveName} has been given a standard length plug for ${his} anus.`, sourceRecord.aVirginButtplug);
 							slave.buttplug = "plug";
 						}
 						break;
 
 					case "long, large plug":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so the anal virgin ${slave.slaveName} has been given a standard length large plug for ${his} anus.`;
+							message(`Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so the anal virgin ${slave.slaveName} has been given a standard length large plug for ${his} anus.`, sourceRecord.aVirginButtplug);
 							slave.buttplug = "large plug";
 						}
 						break;
 
 					case "long, huge plug":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so the anal virgin ${slave.slaveName} has been given a standard length huge plug for ${his} anus.`;
+							message(`Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so the anal virgin ${slave.slaveName} has been given a standard length huge plug for ${his} anus.`, sourceRecord.aVirginButtplug);
 							slave.buttplug = "huge plug";
 						} else {
-							r += `<br>${slave.slaveName} is an anal virgin and has been given a `;
+							const m = `${slave.slaveName} is an anal virgin and has been given a`;
 							if (slave.anus >= 2) {
-								r += `massive and oversized plug to permanently gape ${his} asshole.`;
+								message(`${m} massive and oversized plug to permanently gape ${his} asshole.`, sourceRecord.aVirginButtplug);
 							} else {
-								r += `long, large buttplug for ${his} asshole, since it must be stretched before it can accommodate a huge one.`;
+								message(`${m} long, large buttplug for ${his} asshole, since it must be stretched before it can accommodate a huge one.`, sourceRecord.aVirginButtplug);
 								slave.buttplug = "long, large plug";
 							}
 						}
 						break;
 
 					case "none":
-						r += `<br>${slave.slaveName} is an anal virgin and has been instructed not to use an anal accessory.`;
+						message(`${slave.slaveName} is an anal virgin and has been instructed not to use an anal accessory.`, sourceRecord.aVirginButtplug);
 						break;
 
 					default:
-						r += `<br>${slave.slaveName} is an anal virgin and has been given a ${slave.buttplug} for ${his} asshole.`;
+						message(`${slave.slaveName} is an anal virgin and has been given a ${slave.buttplug} for ${his} asshole.`, sourceRecord.aVirginButtplug);
 						break;
 				}
 			}
@@ -900,50 +903,50 @@ globalThis.DefaultRules = function(slave) {
 				slave.buttplug = rule.buttplug;
 				switch (slave.buttplug) {
 					case "huge plug":
-						r += `<br>${slave.slaveName} has been given a `;
+						const m = `${slave.slaveName} has been given a`;
 						if (slave.anus >= 2) {
-							r += `massive plug to permanently gape ${his} asshole.`;
+							message(`${m} massive plug to permanently gape ${his} asshole.`, sourceRecord.buttplug);
 						} else {
 							slave.buttplug = "large plug";
-							r += `large buttplug for ${his} asshole, since it must be stretched before it can accommodate a huge one.`;
+							message(`${m} large buttplug for ${his} asshole, since it must be stretched before it can accommodate a huge one.`, sourceRecord.buttplug);
 						}
 						break;
 
 					case "long plug":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so ${slave.slaveName} has been given a standard length plug for ${his} anus.`;
+							message(`Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so ${slave.slaveName} has been given a standard length plug for ${his} anus.`, sourceRecord.buttplug);
 							slave.buttplug = "plug";
 						}
 						break;
 
 					case "long, large plug":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so ${slave.slaveName} has been given a standard length large plug for ${his} anus.`;
+							message(`Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so ${slave.slaveName} has been given a standard length large plug for ${his} anus.`, sourceRecord.buttplug);
 							slave.buttplug = "large plug";
 						}
 						break;
 
 					case "long, huge plug":
 						if (slave.breedingMark === 1 && V.propOutcome === 1 && V.eugenicsFullControl !== 1 && V.arcologies[0].FSRestart !== "unset") {
-							r += `<br>Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so ${slave.slaveName} has been given a standard length huge plug for ${his} anus.`;
+							message(`Breeding regulations forbid the use of anal plugs that can damage a growing fetus on marked slaves, so ${slave.slaveName} has been given a standard length huge plug for ${his} anus.`, sourceRecord.buttplug);
 							slave.buttplug = "huge plug";
 						} else {
-							r += `<br>${slave.slaveName} has been given a `;
+							const m = `${slave.slaveName} has been given a`;
 							if (slave.anus >= 2) {
-								r += `massive and oversized plug to permanently gape ${his} asshole.`;
+								message(`${m} massive and oversized plug to permanently gape ${his} asshole.`, sourceRecord.buttplug);
 							} else {
-								r += `long, large buttplug for ${his} asshole, since it must be stretched before it can accommodate a huge one.`;
+								message(`${m} long, large buttplug for ${his} asshole, since it must be stretched before it can accommodate a huge one.`, sourceRecord.buttplug);
 								slave.buttplug = "long, large plug";
 							}
 						}
 						break;
 
 					case "none":
-						r += `<br>${slave.slaveName} has been instructed not to use an anal accessory.`;
+						message(`${slave.slaveName} has been instructed not to use an anal accessory.`, sourceRecord.buttplug);
 						break;
 
 					default:
-						r += `<br>${slave.slaveName} has been given a ${slave.buttplug} for ${his} asshole.`;
+						message(`${slave.slaveName} has been given a ${slave.buttplug} for ${his} asshole.`, sourceRecord.buttplug);
 						break;
 				}
 			}
@@ -965,11 +968,11 @@ globalThis.DefaultRules = function(slave) {
 				slave.buttplugAttachment = rule.buttplugAttachment;
 				switch (slave.buttplugAttachment) {
 					case "none":
-						r += `<br>${slave.slaveName} has been instructed not to use an attachment for ${his} anal accessory.`;
+						message(`${slave.slaveName} has been instructed not to use an attachment for ${his} anal accessory.`, sourceRecord.buttplugAttachment);
 						break;
 
 					default:
-						r += `<br>${slave.slaveName} has been given a ${slave.buttplugAttachment} to attach to ${his} buttplug.`;
+						message(`${slave.slaveName} has been given a ${slave.buttplugAttachment} to attach to ${his} buttplug.`, sourceRecord.buttplugAttachment);
 						break;
 				}
 			}
@@ -984,30 +987,29 @@ globalThis.DefaultRules = function(slave) {
 		// Here is belly implant size control, it's used in Surgery Degradation passage to set up devotion and trust changes.
 		// silent calls to surgery degradation have been replaced with a js function, which is less hacky
 		if ((rule.bellyImplantVol !== undefined) && slave.bellyImplant >= 0 && rule.bellyImplantVol >= 0) {
-			r += "<br>";
 			if (slave.health.condition > -10) {
 				let diff = rule.bellyImplantVol - slave.bellyImplant;
 				if (diff >= 5000 && slave.bellyPain === 0 && slave.health.condition > 50) {
-					r += `${slave.slaveName}'s belly is way too small, so ${he} has been directed to have intensive belly implant filling procedures throughout this week.`;
+					message(`${slave.slaveName}'s belly is way too small, so ${he} has been directed to have intensive belly implant filling procedures throughout this week.`, sourceRecord.bellyImplantVol);
 					slave.bellyImplant += 1000;
 					slave.bellyPain += 2;
 					BellySurgery(slave, diff);
 				} else if (diff >= 500 && slave.bellyPain < 2) {
-					r += `${slave.slaveName}'s belly has not reached the desired size, so ${he} has been directed to have belly implant filling procedures throughout this week.`;
+					message(`${slave.slaveName}'s belly has not reached the desired size, so ${he} has been directed to have belly implant filling procedures throughout this week.`, sourceRecord.bellyImplantVol);
 					slave.bellyImplant += 500;
 					slave.bellyPain += 1;
 					BellySurgery(slave, diff);
 				} else if (diff <= -5000) {
-					r += `${slave.slaveName}'s belly is way too big, so ${he} has been directed to have intensive belly implant draining procedures throughout this week.`;
+					message(`${slave.slaveName}'s belly is way too big, so ${he} has been directed to have intensive belly implant draining procedures throughout this week.`, sourceRecord.bellyImplantVol);
 					slave.bellyImplant -= 1000;
 					BellySurgery(slave, diff);
 				} else if (diff <= -500) {
-					r += `${slave.slaveName}'s belly is too big, so ${he} has been directed to have belly implant draining procedures throughout this week.`;
+					message(`${slave.slaveName}'s belly is too big, so ${he} has been directed to have belly implant draining procedures throughout this week.`, sourceRecord.bellyImplantVol);
 					slave.bellyImplant -= 500;
 					BellySurgery(slave, diff);
 				}
 			} else {
-				r += `${slave.slaveName} is not healthy enough to safely adjust ${his} belly implant.`;
+				message(`${slave.slaveName} is not healthy enough to safely adjust ${his} belly implant.`, sourceRecord.bellyImplantVol);
 			}
 		}
 	}
@@ -1065,10 +1067,10 @@ globalThis.DefaultRules = function(slave) {
 	function ProcessContraceptives(slave, rule) {
 		if ((rule.preg !== undefined) && (rule.preg !== null)) {
 			if (rule.preg === true && slave.preg === 0 && slave.pubertyXX === 1) {
-				r += `<br>${slave.slaveName} is being given contraceptives.`;
+				message(`${slave.slaveName} is being given contraceptives.`, sourceRecord.preg);
 				slave.preg = -1;
 			} else if (slave.preg === -1 && rule.preg === false) {
-				r += `<br>${slave.slaveName} is no longer being put on contraceptives.`;
+				message(`${slave.slaveName} is no longer being put on contraceptives.`, sourceRecord.preg);
 				slave.preg = 0;
 			}
 		}
@@ -1103,34 +1105,34 @@ globalThis.DefaultRules = function(slave) {
 			for (const ar of rule.abortion) {
 				if (ar === "all") {
 					if (slave.preg < 4 || (slave.fetish === "mindbroken" || slave.fuckdoll !== 0)) {
-						r += `<br>${slave.slaveName}'s pregnancy has been terminated.`;
+						message(`${slave.slaveName}'s pregnancy has been terminated.`, sourceRecord.abortion);
 					} else {
-						r += `<br>${slave.slaveName}'s pregnancy has been terminated; `;
+						const m = `${slave.slaveName}'s pregnancy has been terminated;`;
 						if (slave.sexualFlaw === "breeder") {
-							r += `it broke ${his} mind.`;
+							message(`${m} it broke ${his} mind.`, sourceRecord.abortion);
 							applyMindbroken(slave);
 						} else if (slave.devotion < -50) {
-							r += `${he} did not handle it well.`;
+							message(`${m} ${he} did not handle it well.`, sourceRecord.abortion);
 							slave.trust -= 10;
 							slave.devotion -= 25;
 						} else if (slave.devotion < -20) {
-							r += `${he} did not handle it well.`;
+							message(`${m} ${he} did not handle it well.`, sourceRecord.abortion);
 							slave.trust -= 10;
 							slave.devotion -= 10;
 						} else if (slave.fetish === "pregnancy") {
-							r += `${he} did not handle it well.`;
+							message(`${m} ${he} did not handle it well.`, sourceRecord.abortion);
 							let fetishModifier = slave.fetishStrength / 2;
 							slave.devotion -= fetishModifier;
 							slave.trust -= fetishModifier;
 						} else if (slave.devotion <= 20) {
-							r += `${he} did not handle it well.`;
+							message(`${m} ${he} did not handle it well.`, sourceRecord.abortion);
 							slave.trust -= 10;
 							slave.devotion -= 5;
 						} else if (slave.devotion <= 50) {
-							r += `${he} did not handle it well.`;
+							message(`${m} ${he} did not handle it well.`, sourceRecord.abortion);
 							slave.trust -= 10;
 						} else {
-							r += "it had little mental effect.";
+							message(`${m} it had little mental effect.`, sourceRecord.abortion);
 						}
 					}
 
@@ -1147,16 +1149,16 @@ globalThis.DefaultRules = function(slave) {
 					actX(slave, "abortions");
 				} else if (ar === "male") {
 					if (conditionalTermination(slave, fetus => fetus.genetics.gender === "XY")) {
-						r += `<br>${slave.slaveName}'s male fetuses have been terminated.`;
+						message(`${slave.slaveName}'s male fetuses have been terminated.`, sourceRecord.abortion);
 					}
 				} else if (ar === "female") {
 					if (conditionalTermination(slave, fetus => fetus.genetics.gender === "XX")) {
-						r += `<br>${slave.slaveName}'s female fetuses have been terminated.`;
+						message(`${slave.slaveName}'s female fetuses have been terminated.`, sourceRecord.abortion);
 					}
 				} else if (ar.startsWith("race:")) { // ar is the race name in the notation "race:<lowercase_race_name>"
 					const race = ar.substr("race:".length);
 					if (conditionalTermination(slave, fetus => fetus.genetics.race === race)) {
-						r += `<br>${slave.slaveName}'s ${race} fetuses have been terminated.`;
+						message(`${slave.slaveName}'s ${race} fetuses have been terminated.`, sourceRecord.abortion);
 					}
 				}
 				SetBellySize(slave);
@@ -1174,7 +1176,7 @@ globalThis.DefaultRules = function(slave) {
 			return;
 		}
 		if ((slave.drugs === "super fertility drugs" || slave.drugs === "fertility drugs") && isFertile(slave)) {
-			r += `<br>${slave.slaveName} is on ${slave.drugs} and will not be considered for drug enhancement until that regime is complete.`;
+			message(`${slave.slaveName} is on ${slave.drugs} and will not be considered for drug enhancement until that regime is complete.`);
 			ProcessOtherDrugs(slave, rule);
 			return;
 		} else if (
@@ -1257,10 +1259,11 @@ globalThis.DefaultRules = function(slave) {
 		 * @param {App.Entity.SlaveState} slave
 		 * @param {FC.SizableBodyPart} asset
 		 * @param {FC.RA.ExpressiveNumericTarget} target
-		 * @param {{drug: FC.Drug, weight: number}[]} priorities
+		 * @param {{drug: FC.Drug, weight: number, source:string}[]} priorities
 		 * @param {number} step
+		 * @param {string} source
 		 */
-		function drugs(slave, asset, target, priorities, step) {
+		function drugs(slave, asset, target, priorities, step, source) {
 			if (target === null || (growDrugs[asset] === null && shrinkDrugs[asset] === null)) {
 				return;
 			}
@@ -1271,71 +1274,71 @@ globalThis.DefaultRules = function(slave) {
 				if (V.debugMode) {
 					console.log(asset + " expression for '" + slave.slaveName + "' resolves to " + newVal.toString());
 				}
-				return drugsImpl(slave, asset, {cond: target.cond, val: newVal}, priorities, step);
+				drugsImpl(slave, asset, {cond: target.cond, val: newVal}, priorities, step, source);
+			} else {
+				drugsImpl(slave, asset, {cond: target.cond, val: target.val}, priorities, step, source);
 			}
-
-			return drugsImpl(slave, asset, {cond: target.cond, val: target.val}, priorities, step);
 		}
 
 		/**
 		 * @param {App.Entity.SlaveState} slave
 		 * @param {FC.SizableBodyPart} asset
 		 * @param {FC.RA.NumericTarget} target
-		 * @param {{drug: FC.Drug, weight: number}[]} priorities
+		 * @param {{drug: FC.Drug, weight: number, source:string}[]} priorities
 		 * @param {number} step
+		 * @param {string} source
 		 */
-		function drugsImpl(slave, asset, target, priorities, step) {
+		function drugsImpl(slave, asset, target, priorities, step, source) {
 			const flesh = App.Medicine.fleshSize(slave, asset);
 			if (growDrugs[asset] !== null && App.RA.shallGrow(flesh, target, step) && App.Medicine.maxAssetSize(asset) > slave[asset]) {
 				priorities.push({
-					drug: growDrugs[asset],
-					weight: 1.0 - (flesh / target.val)
+					drug: growDrugs[asset], weight: 1.0 - (flesh / target.val), source
 				});
 			} else if (shrinkDrugs[asset] !== null && App.RA.shallShrink(flesh, target, step)) {
 				priorities.push({
-					drug: shrinkDrugs[asset],
-					weight: flesh / target.val - 1.0
+					drug: shrinkDrugs[asset], weight: flesh / target.val - 1.0, source
 				});
 			}
 		}
 
-		/** @type {{drug: FC.Drug, weight: number}[]} */
+		/** @type {{drug: FC.Drug, weight: number, source:string}[]} */
 		let priorities = [];
-		drugs(slave, "boobs", rule.growth.boobs, priorities, 200);
-		drugs(slave, "butt", rule.growth.butt, priorities, 1);
-		drugs(slave, "lips", rule.growth.lips, priorities, 1);
-		drugs(slave, "dick", rule.growth.dick, priorities, 1);
-		drugs(slave, "balls", rule.growth.balls, priorities, 1);
+		drugs(slave, "boobs", rule.growth.boobs, priorities, 200, sourceRecord.growth.boobs);
+		drugs(slave, "butt", rule.growth.butt, priorities, 1, sourceRecord.growth.butt);
+		drugs(slave, "lips", rule.growth.lips, priorities, 1, sourceRecord.growth.lips);
+		drugs(slave, "dick", rule.growth.dick, priorities, 1, sourceRecord.growth.dick);
+		drugs(slave, "balls", rule.growth.balls, priorities, 1, sourceRecord.growth.balls);
 
 		if (priorities.length > 0) {
 			const action = priorities.reduce((acc, cur) => (acc.weight > cur.weight) ? acc : cur);
 			if (slave.drugs !== action.drug) {
 				slave.drugs = action.drug;
-				r += `<br>${slave.slaveName} has been put on ${slave.drugs}, since `;
+				let m = `${slave.slaveName} has been put on ${slave.drugs}, since `;
 				if (action.drug.startsWith("intensive")) {
-					r += `${he}'s healthy enough to take them, and `;
+					m += `${he}'s healthy enough to take them, and `;
 				}
 				if (priorities.length > 1) {
-					r += `that part of ${his} body is `;
+					m += `that part of ${his} body is `;
 					if (!isNaN(action.weight)) {
-						r += `${Math.trunc(action.weight * 100)}% `;
+						m += `${Math.trunc(action.weight * 100)}% `;
 					}
 					if (action.weight < 1) {
-						r += "below ";
+						m += "below ";
 					} else {
-						r += "above ";
+						m += "above ";
 					}
-					r += "the targeted size.";
+					m += "the targeted size.";
 				} else {
-					r += `that is the only part of ${his} body that does not meet the targeted size.`;
+					m += `that is the only part of ${his} body that does not meet the targeted size.`;
 				}
+				message(m, action.source);
 			}
 		} else if (slave.drugs !== rule.drug) {
 			if (growthDrugs.has(slave.drugs)) {
-				r += `<br>${slave.slaveName}'s body has met all relevant growth targets, so ${his} pharmaceutical regime has been ended.`;
+				message(`${slave.slaveName}'s body has met all relevant growth targets, so ${his} pharmaceutical regime has been ended.`, sourceRecord.drug);
 				if (rule.drug === null) {
 					slave.drugs = "no drugs";
-					r += `<br>${slave.slaveName} has been defaulted to ${slave.drugs}`;
+					message(`${slave.slaveName} has been defaulted to ${slave.drugs}`, sourceRecord.drug);
 				}
 			}
 			ProcessOtherDrugs(slave, rule);
@@ -1520,10 +1523,10 @@ globalThis.DefaultRules = function(slave) {
 			}
 			if (flag) {
 				slave.drugs = rule.drug;
-				r += `<br>${slave.slaveName} has been put on ${slave.drugs}.`;
+				message(`${slave.slaveName} has been put on ${slave.drugs}.`, sourceRecord.drug);
 			} else if (slave.drugs !== "no drugs") {
 				slave.drugs = "no drugs";
-				r += `<br>${slave.slaveName} cannot benefit from ${his} assigned drug and has been defaulted to ${slave.drugs}`;
+				message(`${slave.slaveName} cannot benefit from ${his} assigned drug and has been defaulted to ${slave.drugs}`, sourceRecord.drug);
 			}
 		}
 	}
@@ -1536,12 +1539,12 @@ globalThis.DefaultRules = function(slave) {
 		if ((rule.inflationType !== undefined) && (rule.inflationType !== null)) {
 			if (slave.inflationType !== rule.inflationType) {
 				if ((slave.inflationType === "curative" && slave.health.condition > 90) || (slave.inflationType === "tightener" && slave.anus <= 1 && slave.vagina <= 1)) {
-					r += `<br>${slave.slaveName} cannot benefit from ${his} assigned enema and has been defaulted to none.`;
+					message(`${slave.slaveName} cannot benefit from ${his} assigned enema and has been defaulted to none.`, sourceRecord.inflationType);
 					deflate(slave);
 				} else if ((rule.inflationType === "curative" && slave.health.condition > 90) || (rule.inflationType === "tightener" && slave.anus <= 1 && slave.vagina <= 1)) {
 					// empty block
 				} else {
-					r += `<br>${slave.slaveName}'s current enema regimen has been set to ${rule.inflationType}.`;
+					message(`${slave.slaveName}'s current enema regimen has been set to ${rule.inflationType}.`, sourceRecord.inflationType);
 					slave.inflation = 1;
 					slave.inflationType = rule.inflationType;
 					slave.inflationMethod = 2;
@@ -1551,11 +1554,11 @@ globalThis.DefaultRules = function(slave) {
 				}
 			}
 			if (slave.inflationType !== "none" && slave.inflation > 1 && slave.health.condition < -50) {
-				r += `<br>${slave.slaveName}'s current enema regimen risks death, so it has been reduced to a less threatening level.`;
+				message(`${slave.slaveName}'s current enema regimen risks death, so it has been reduced to a less threatening level.`, sourceRecord.inflationType);
 				slave.inflation = 1;
 				SetBellySize(slave);
 			} else if (slave.inflation > 1 && (slave.bellyPreg >= 1500 || slave.bellyImplant >= 1500)) {
-				r += `<br>${slave.slaveName}'s current enema is too much for ${his} body, so it has been reduced.`;
+				message(`${slave.slaveName}'s current enema is too much for ${his} body, so it has been reduced.`, sourceRecord.inflationType);
 				slave.inflation = 1;
 				SetBellySize(slave);
 			} else if (slave.inflationType === "none") {
@@ -1574,15 +1577,15 @@ globalThis.DefaultRules = function(slave) {
 				if (rule.pitRules === 0) {
 					if (App.Entity.facilities.pit.isHosted(slave)) {
 						removeJob(slave, Job.PIT, true);
-						r += `<br>${slave.slaveName} has been removed from the pit.`;
+						message(`${slave.slaveName} has been removed from the pit.`, sourceRecord.pitRules);
 					}
 				} else {
 					if (App.Entity.facilities.pit.job().checkRequirements(slave).length !== 0) {
 						removeJob(slave, Job.PIT, true);
-						r += `<br>${slave.slaveName} is not eligible to fight.`;
+						message(`${slave.slaveName} is not eligible to fight.`, sourceRecord.pitRules);
 					} else if (!App.Entity.facilities.pit.isHosted(slave)) {
 						assignJob(slave, Job.PIT);
-						r += `<br>${slave.slaveName} has been automatically assigned to fight in the pit.`;
+						message(`${slave.slaveName} has been automatically assigned to fight in the pit.`, sourceRecord.pitRules);
 					}
 				}
 			}
@@ -1607,17 +1610,17 @@ globalThis.DefaultRules = function(slave) {
 				if (((slave.weight > 95) || ((slave.weight > 30) && (slave.hips < 2)))) {
 					if (slave.diet !== "restricted") {
 						slave.diet = "restricted";
-						r += `<br>${slave.slaveName} is unreasonably fat so ${his} diet has been set to restricted.`;
+						message(`${slave.slaveName} is unreasonably fat so ${his} diet has been set to restricted.`, sourceRecord.diet);
 						dietPills(slave);
 					}
 				} else if (((slave.weight < -95) || ((slave.weight < -30) && (slave.hips > -2)))) {
 					if (slave.diet !== "fattening") {
 						slave.diet = "fattening";
-						r += `<br>${slave.slaveName} is unreasonably skinny so ${his} diet has been set to fattening.`;
+						message(`${slave.slaveName} is unreasonably skinny so ${his} diet has been set to fattening.`, sourceRecord.diet);
 						dietPills(slave);
 					}
 				} else if (["restricted", "fattening"].includes(slave.diet)) {
-					r += `<br>${slave.slaveName} is at an acceptable weight, so ${his} diet has been normalized.`;
+					message(`${slave.slaveName} is at an acceptable weight, so ${his} diet has been normalized.`, sourceRecord.diet);
 					slave.diet = "healthy";
 					dietPills(slave);
 					muscleRule(slave, rule);
@@ -1628,17 +1631,17 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.weight > rule.weight.max) {
 					if (slave.diet !== "restricted") {
 						slave.diet = "restricted";
-						r += `<br>${slave.slaveName} is too fat so ${his} diet has been set to restricted.`;
+						message(`${slave.slaveName} is too fat so ${his} diet has been set to restricted.`, sourceRecord.weight.max);
 						dietPills(slave);
 					}
 				} else if (slave.weight < rule.weight.min) {
 					if (slave.diet !== "fattening") {
 						slave.diet = "fattening";
-						r += `<br>${slave.slaveName} is too skinny so ${his} diet has been set to fattening.`;
+						message(`${slave.slaveName} is too skinny so ${his} diet has been set to fattening.`, sourceRecord.weight.min);
 						dietPills(slave);
 					}
 				} else if (["restricted", "fattening"].includes(slave.diet)) {
-					r += `<br>${slave.slaveName} is at the target weight, so ${his} diet has been normalized.`;
+					message(`${slave.slaveName} is at the target weight, so ${his} diet has been normalized.`, [sourceRecord.weight.max, sourceRecord.weight.min]);
 					slave.diet = "healthy";
 					dietPills(slave);
 					muscleRule(slave, rule);
@@ -1652,15 +1655,15 @@ globalThis.DefaultRules = function(slave) {
 			if (!isAmputee(slave) && App.RA.shallShrink(slave.muscles, rule.muscles, 8)) {
 				if (slave.diet !== "slimming") {
 					slave.diet = "slimming";
-					r += `<br>${slave.slaveName} has been put on a slimming exercise regime.`;
+					message(`${slave.slaveName} has been put on a slimming exercise regime.`, sourceRecord.muscles);
 				}
 			} else if (!isAmputee(slave) && App.RA.shallGrow(slave.muscles, rule.muscles, 2)) {
 				if (slave.diet !== "muscle building") {
 					slave.diet = "muscle building";
-					r += `<br>${slave.slaveName} has been put on a muscle building exercise regime.`;
+					message(`${slave.slaveName} has been put on a muscle building exercise regime.`, sourceRecord.muscles);
 				}
 			} else if (!isAmputee(slave) && ["slimming", "muscle building"].includes(slave.diet)) {
-				r += `<br>${slave.slaveName} is at the target musculature, so ${his} diet has been normalized.`;
+				message(`${slave.slaveName} is at the target musculature, so ${his} diet has been normalized.`, sourceRecord.muscles);
 				dietRule(slave, rule);
 			} else {
 				dietRule(slave, rule);
@@ -1670,56 +1673,56 @@ globalThis.DefaultRules = function(slave) {
 		function dietRule(slave, rule) {
 			if (rule.diet === "healthy" && slave.diet !== "healthy") {
 				slave.diet = "healthy";
-				r += `<br>${slave.slaveName} has been assigned to a healthy diet.`;
+				message(`${slave.slaveName} has been assigned to a healthy diet.`, sourceRecord.diet);
 			} else if ((slave.boobs >= 1600) && (slave.muscles > 5) && (slave.diet === "muscle building") && ((rule.muscles === null) || (rule.muscles.val < 5))) {
 				slave.diet = "healthy";
-				r += `<br>${slave.slaveName} has huge boobs, but ${he} already has the back muscles to bear them, so ${he}'s been assigned to stop working out so hard.`;
+				message(`${slave.slaveName} has huge boobs, but ${he} already has the back muscles to bear them, so ${he}'s been assigned to stop working out so hard.`, sourceRecord.diet);
 			} else if ((rule.dietGrowthSupport === 1) && ((slave.drugs === "breast injections") || (slave.drugs === "butt injections")) && (slave.weight <= 95)) {
 				if (slave.diet !== "fattening") {
 					slave.diet = "fattening";
-					r += `<br>${slave.slaveName} is on drugs designed to expand major body parts, so ${he}'s been put on a fattening diet to provide ${his} body as much fuel for growth as possible.`;
+					message(`${slave.slaveName} is on drugs designed to expand major body parts, so ${he}'s been put on a fattening diet to provide ${his} body as much fuel for growth as possible.`, sourceRecord.diet);
 				}
 			} else if (rule.diet === "XX") {
 				if (slave.diet !== "XX") {
 					slave.diet = "XX";
-					r += `<br>${slave.slaveName} has been put on a diet that favors feminine development.`;
+					message(`${slave.slaveName} has been put on a diet that favors feminine development.`, sourceRecord.diet);
 				}
 			} else if (rule.diet === "XY") {
 				if (slave.diet !== "XY") {
 					slave.diet = "XY";
-					r += `<br>${slave.slaveName} has been put on a diet that favors masculine development.`;
+					message(`${slave.slaveName} has been put on a diet that favors masculine development.`, sourceRecord.diet);
 				}
 			} else if (rule.diet === "XXY") {
 				if (slave.balls > 0 && (slave.ovaries === 1 || slave.mpreg === 1)) {
 					if (slave.diet !== "XXY") {
 						slave.diet = "XXY";
-						r += `<br>${slave.slaveName} has been put on a diet that enhances a herm's unique sexuality.`;
+						message(`${slave.slaveName} has been put on a diet that enhances a herm's unique sexuality.`, sourceRecord.diet);
 					}
 				} else {
 					if (slave.diet !== "healthy") {
 						slave.diet = "healthy";
-						r += `<br>${slave.slaveName} has been put on a standard diet since ${he} is not a hermaphrodite.`;
+						message(`${slave.slaveName} has been put on a standard diet since ${he} is not a hermaphrodite.`, sourceRecord.diet);
 					}
 				}
 			} else if (V.dietCleanse === 1 && (rule.diet === "cleansing")) {
 				if (slave.diet !== "cleansing") {
 					slave.diet = "cleansing";
-					r += `<br>${slave.slaveName} has been put on a diet of cleansers.`;
+					message(`${slave.slaveName} has been put on a diet of cleansers.`, sourceRecord.diet);
 				}
 			} else if (rule.diet === "fertility") {
 				if ((isFertile(slave) && slave.preg === 0) || (slave.geneticQuirks.superfetation === 2 && canGetPregnant(slave) && V.geneticMappingUpgrade !== 0)) {
 					if (slave.diet !== "fertility") {
 						slave.diet = "fertility";
-						r += `<br>${slave.slaveName} has been put on a diet to enhance fertility.`;
+						message(`${slave.slaveName} has been put on a diet to enhance fertility.`, sourceRecord.diet);
 					}
 				} else {
 					if (slave.diet !== "healthy") {
 						slave.diet = "healthy";
 						if (slave.pregKnown === 0 && slave.preg > 0) {
-							r += `<br>${slave.slaveName} has been put on a standard diet since tests reveal ${he} has become pregnant.`;
+							message(`${slave.slaveName} has been put on a standard diet since tests reveal ${he} has become pregnant.`, sourceRecord.diet);
 							slave.pregKnown = 1;
 						} else {
-							r += `<br>${slave.slaveName} has been put on a standard diet since ${he} is currently unable to become pregnant.`;
+							message(`${slave.slaveName} has been put on a standard diet since ${he} is currently unable to become pregnant.`, sourceRecord.diet);
 						}
 					}
 				}
@@ -1727,18 +1730,18 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.balls > 0) {
 					if (slave.diet !== "cum production") {
 						slave.diet = "cum production";
-						r += `<br>${slave.slaveName} has been put on a diet to promote cum production.`;
+						message(`${slave.slaveName} has been put on a diet to promote cum production.`, sourceRecord.diet);
 					}
 				} else {
 					if (slave.diet !== "healthy") {
 						slave.diet = "healthy";
-						r += `<br>${slave.slaveName} has been put on a standard diet since ${he} is no longer able to produce cum.`;
+						message(`${slave.slaveName} has been put on a standard diet since ${he} is no longer able to produce cum.`, sourceRecord.diet);
 					}
 				}
 			} else {
 				if (slave.diet !== "healthy") {
 					slave.diet = "healthy";
-					r += `<br>${slave.slaveName} has been put on a standard diet.`;
+					message(`${slave.slaveName} has been put on a standard diet.`, sourceRecord.diet);
 				}
 			}
 		}
@@ -1756,10 +1759,10 @@ globalThis.DefaultRules = function(slave) {
 		function dietPills(slave) {
 			if (slave.drugs === "appetite suppressors" && slave.diet !== "restricted") {
 				slave.drugs = "no drugs";
-				r += `<br>${slave.slaveName} no longer needs to lose weight, so ${he}'s no longer being given appetite suppressors.`;
+				message(`${slave.slaveName} no longer needs to lose weight, so ${he}'s no longer being given appetite suppressors.`, [sourceRecord.diet, sourceRecord.weight.max, sourceRecord.weight.min]);
 			} else if (slave.diet === "restricted" && V.arcologies[0].FSSlimnessEnthusiastResearch === 1 && slave.drugs === "no drugs") {
 				slave.drugs = "appetite suppressors";
-				r += `<br>${slave.slaveName} needs to lose weight, so ${he} will be given weight loss pills.`;
+				message(`${slave.slaveName} needs to lose weight, so ${he} will be given weight loss pills.`, [sourceRecord.diet, sourceRecord.weight.max, sourceRecord.weight.min]);
 			}
 		}
 	}
@@ -1774,15 +1777,15 @@ globalThis.DefaultRules = function(slave) {
 				if (rule.curatives === 2) {
 					if (slave.health.condition > 100) {
 						if (slave.curatives !== 1) {
-							r += `<br>${slave.slaveName} has been put on preventatives, since curatives cannot improve ${his} health further.`;
+							message(`${slave.slaveName} has been put on preventatives, since curatives cannot improve ${his} health further.`, sourceRecord.curatives);
 							slave.curatives = 1;
 						}
 					} else {
-						r += `<br>${slave.slaveName} has been put on curatives.`;
+						message(`${slave.slaveName} has been put on curatives.`, sourceRecord.curatives);
 						slave.curatives = rule.curatives;
 					}
 				} else {
-					r += `<br>${slave.slaveName} has been ${rule.curatives > 0 ? "put on preventatives" : "taken off health drugs"}`;
+					message(`${slave.slaveName} has been ${rule.curatives > 0 ? "put on preventatives" : "taken off health drugs"}`, sourceRecord.curatives);
 					slave.curatives = rule.curatives;
 				}
 			}
@@ -1796,7 +1799,7 @@ globalThis.DefaultRules = function(slave) {
 	function ProcessAphrodisiacs(slave, rule) {
 		if ((rule.aphrodisiacs !== undefined) && (rule.aphrodisiacs !== null)) {
 			if (slave.aphrodisiacs !== rule.aphrodisiacs) {
-				r += `<br>${slave.slaveName} has been ${rule.aphrodisiacs > 0 ? "put on the proper" : "taken off"} aphrodisiacs.`;
+				message(`${slave.slaveName} has been ${rule.aphrodisiacs > 0 ? "put on the proper" : "taken off"} aphrodisiacs.`, sourceRecord.aphrodisiacs);
 				slave.aphrodisiacs = rule.aphrodisiacs;
 			}
 		}
@@ -1806,13 +1809,14 @@ globalThis.DefaultRules = function(slave) {
 	 * @param {FC.SlaveState} slave
 	 * @param {number} hormones
 	 * @param {string} slaveClass
+	 * @param {string} source
 	 */
-	function applyHormones(slave, hormones, slaveClass) {
+	function applyHormones(slave, hormones, slaveClass, source) {
 		if (!_.isNil(hormones)) {
 			const newHormones = slave.indentureRestrictions >= 2 ? Math.clamp(hormones, -1, 1) : hormones;
 			if (slave.hormones !== newHormones) {
 				slave.hormones = newHormones;
-				r += `<br>${slave.slaveName} is ${slaveClass}, so ${he} has been put on the appropriate hormonal regime.`;
+				message(`${slave.slaveName} is ${slaveClass}, so ${he} has been put on the appropriate hormonal regime.`, source);
 			}
 		}
 	}
@@ -1824,9 +1828,9 @@ globalThis.DefaultRules = function(slave) {
 	function ProcessPenisHormones(slave, rule) {
 		if (slave.dick > 0) {
 			if (slave.balls === 0) {
-				applyHormones(slave, rule.gelding, "a gelding");
+				applyHormones(slave, rule.gelding, "a gelding", sourceRecord.gelding);
 			} else if (slave.balls > 0) {
-				applyHormones(slave, rule.XY, "a shemale");
+				applyHormones(slave, rule.XY, "a shemale", sourceRecord.XY);
 			}
 		}
 	}
@@ -1837,7 +1841,7 @@ globalThis.DefaultRules = function(slave) {
 	 */
 	function ProcessFemaleHormones(slave, rule) {
 		if ((slave.vagina > -1) && (slave.dick === 0)) {
-			applyHormones(slave, rule.XX, "a female");
+			applyHormones(slave, rule.XX, "a female", sourceRecord.XX);
 		}
 	}
 
@@ -1849,25 +1853,25 @@ globalThis.DefaultRules = function(slave) {
 		if (slave.pregKnown === 1 && rule.pregSpeed !== null && (slave.breedingMark !== 1 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset") && slave.indentureRestrictions < 1 && slave.broodmother === 0) {
 			if (rule.pregSpeed === "slow" && slave.preg < slave.pregData.normalBirth) {
 				slave.pregControl = "slow gestation";
-				r += `<br>${slave.slaveName} is pregnant, so ${he} has been put on the gestation slowing agents.`;
+				message(`${slave.slaveName} is pregnant, so ${he} has been put on the gestation slowing agents.`, sourceRecord.pregSpeed);
 			} else if (rule.pregSpeed === "fast" && slave.preg < slave.pregData.normalBirth && slave.health.condition > -50) {
 				slave.pregControl = "speed up";
-				r += `<br>${slave.slaveName} is pregnant, so ${he} has been put on rapid gestation agents. CAUTION! Can be dangerous. Clinic supervision is recommended.`;
+				message(`${slave.slaveName} is pregnant, so ${he} has been put on rapid gestation agents. CAUTION! Can be dangerous. Clinic supervision is recommended.`, sourceRecord.pregSpeed);
 			} else if (rule.pregSpeed === "suppress" && slave.preg >= slave.pregData.minLiveBirth && slave.health.condition > -50) {
 				slave.pregControl = "labor suppressors";
-				r += `<br>${slave.slaveName} is ready to birth, so ${he} has been put on labor suppressing agents.`;
+				message(`${slave.slaveName} is ready to birth, so ${he} has been put on labor suppressing agents.`, sourceRecord.pregSpeed);
 			} else if (rule.pregSpeed === "stimulate" && slave.preg > slave.pregData.normalBirth - 2 && slave.preg > slave.pregData.minLiveBirth && slave.health.condition > -50) {
 				induce(slave);
-				r += `<br>${slave.slaveName} is ready to birth, so ${his} labor has been stimulated.`;
+				message(`${slave.slaveName} is ready to birth, so ${his} labor has been stimulated.`, sourceRecord.pregSpeed);
 			} else if (rule.pregSpeed === "fast" && slave.pregControl === "speed up" && slave.health.condition <= -50) {
 				slave.pregControl = "none";
-				r += `<br>${slave.slaveName} is on rapid gestation agents and dangerously unhealthy, so ${his} agent regimen has been stopped.`;
+				message(`${slave.slaveName} is on rapid gestation agents and dangerously unhealthy, so ${his} agent regimen has been stopped.`, sourceRecord.pregSpeed);
 			} else if (rule.pregSpeed === "suppress" && slave.pregControl === "labor suppressors" && slave.health.condition <= -50) {
 				slave.pregControl = "none";
-				r += `<br>${slave.slaveName} is on labor suppression agents and unhealthy, so ${his} agent regimen has been stopped.`;
+				message(`${slave.slaveName} is on labor suppression agents and unhealthy, so ${his} agent regimen has been stopped.`, sourceRecord.pregSpeed);
 			} else if (rule.pregSpeed === "none" && slave.pregControl !== "none") {
 				slave.pregControl = "none";
-				r += `<br>${slave.slaveName}'s pregnancy control regimen has been stopped.`;
+				message(`${slave.slaveName}'s pregnancy control regimen has been stopped.`, sourceRecord.pregSpeed);
 			}
 		}
 	}
@@ -1880,26 +1884,26 @@ globalThis.DefaultRules = function(slave) {
 		if (rule.livingRules !== undefined && rule.livingRules !== null && slave.rules.living !== rule.livingRules) {
 			if (App.Data.misc.facilityCareers.includes(slave.assignment)) {
 				// Handled in Rules tab of SI now.
-				// r += `<br>${slave.slaveName}'s living standards are controlled by ${his} assignment.`;
+				// message(`${slave.slaveName}'s living standards are controlled by ${his} assignment.`);
 			} else if (((slave.assignment === Job.HEADGIRL) && (V.HGSuite === 1)) || ((slave.assignment === Job.BODYGUARD) && (V.dojo > 1))) {
-				// r += `<br>${slave.slaveName} has a private room.`;
+				// message(`${slave.slaveName} has a private room.`);
 			} else if (slave.fetish === "mindbroken") {
 				if (slave.rules.living !== "spare") {
 					slave.rules.living = "spare";
-					r += `<br>Since ${slave.slaveName} is mindbroken, ${his} living standard has been set to spare.`;
+					message(`Since ${slave.slaveName} is mindbroken, ${his} living standard has been set to spare.`, sourceRecord.livingRules);
 				}
 			} else {
 				if (rule.livingRules === "luxurious") {
 					if (canMoveToRoom(slave)) {
 						slave.rules.living = rule.livingRules;
-						r += `<br>${slave.slaveName}'s living standard has been set to ${rule.livingRules}.`;
+						message(`${slave.slaveName}'s living standard has been set to ${rule.livingRules}.`, sourceRecord.livingRules);
 					} else {
 						slave.rules.living = "normal";
-						r += `<br>${slave.slaveName}'s living standard has been set to normal, since there is no room for ${him} to occupy.`;
+						message(`${slave.slaveName}'s living standard has been set to normal, since there is no room for ${him} to occupy.`, sourceRecord.livingRules);
 					}
 				} else {
 					slave.rules.living = rule.livingRules;
-					r += `<br>${slave.slaveName}'s living standard has been set to ${rule.livingRules}.`;
+					message(`${slave.slaveName}'s living standard has been set to ${rule.livingRules}.`, sourceRecord.livingRules);
 				}
 			}
 			penthouseCensus();
@@ -1917,7 +1921,7 @@ globalThis.DefaultRules = function(slave) {
 					// These assignments enforce "restrictive", do not let RA attempt to change it.
 				} else {
 					slave.rules.rest = rule.restRules;
-					r += `<br>${slave.slaveName}'s resting time has been set to ${rule.restRules}.`;
+					message(`${slave.slaveName}'s resting time has been set to ${rule.restRules}.`, sourceRecord.restRules);
 				}
 			}
 		}
@@ -1932,27 +1936,27 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.fetish === "mindbroken") {
 				if (slave.rules.speech !== "restrictive") {
 					slave.rules.speech = "restrictive";
-					r += `<br>Since ${slave.slaveName} is mindbroken, ${his} speech rules have been set to restrictive.`;
+					message(`Since ${slave.slaveName} is mindbroken, ${his} speech rules have been set to restrictive.`, sourceRecord.speechRules);
 				}
 			} else if (slave.accent === 4) {
 				if ((rule.speechRules === "accent elimination" || rule.speechRules === "permissive") && slave.rules.speech !== "language lessons") {
 					slave.rules.speech = "language lessons";
-					r += `<br>Since ${slave.slaveName} does not know how to talk, ${his} speech rules have been set to language learning.`;
+					message(`Since ${slave.slaveName} does not know how to talk, ${his} speech rules have been set to language learning.`, sourceRecord.speechRules);
 				} else if (slave.rules.speech !== "language lessons" && slave.rules.speech !== "restrictive") {
 					slave.rules.speech = "restrictive";
-					r += `<br>Since ${slave.slaveName} does not know how to talk, ${his} speech rules have been set to restrictive.`;
+					message(`Since ${slave.slaveName} does not know how to talk, ${his} speech rules have been set to restrictive.`, sourceRecord.speechRules);
 				}
 			} else if (rule.speechRules === "accent elimination") {
 				if (slave.accent > 0) {
 					slave.rules.speech = "accent elimination";
-					r += `<br>${slave.slaveName}'s speech rules have been set to ${rule.speechRules}.`;
+					message(`${slave.slaveName}'s speech rules have been set to ${rule.speechRules}.`, sourceRecord.speechRules);
 				} else {
 					slave.rules.speech = "restrictive";
-					r += `<br>Since ${slave.slaveName} has no accent, ${his} speech rules have been set to restrictive.`;
+					message(`Since ${slave.slaveName} has no accent, ${his} speech rules have been set to restrictive.`, sourceRecord.speechRules);
 				}
 			} else if (slave.rules.speech !== rule.speechRules) {
 				slave.rules.speech = rule.speechRules;
-				r += `<br>${slave.slaveName}'s speech rules have been set to ${rule.speechRules}.`;
+				message(`${slave.slaveName}'s speech rules have been set to ${rule.speechRules}.`, sourceRecord.speechRules);
 			}
 		}
 	}
@@ -1966,7 +1970,7 @@ globalThis.DefaultRules = function(slave) {
 			if ((rule.relationshipRules !== undefined) && (rule.relationshipRules !== null)) {
 				if (slave.rules.relationship !== rule.relationshipRules) {
 					slave.rules.relationship = rule.relationshipRules;
-					r += `<br>${slave.slaveName}'s relationship rules have been set to ${rule.relationshipRules}.`;
+					message(`${slave.slaveName}'s relationship rules have been set to ${rule.relationshipRules}.`, sourceRecord.relationshipRules);
 				}
 			}
 		}
@@ -1985,21 +1989,24 @@ globalThis.DefaultRules = function(slave) {
 			'slaves',
 			'master',
 		];
-		if ((rule.releaseRules !== undefined) && (rule.releaseRules !== null) && processReleaseProp(releaseProperties)) {
-			r += `<br>${slave.slaveName}'s release rules have been set to: ${App.Utils.releaseSummaryLong(slave)}.`;
+		if ((rule.releaseRules !== undefined) && (rule.releaseRules !== null)) {
+			const source = processReleaseProp(releaseProperties);
+			if (source !== "") {
+				message(`${slave.slaveName}'s release rules have been set to: ${App.Utils.releaseSummaryLong(slave)}.`, source);
+			}
 		}
 
 		function processReleaseProp(releaseProperties) {
-			let changed = false;
+			let source = "";
 			for (const property of releaseProperties) {
 				if (rule.releaseRules[property] !== undefined && rule.releaseRules[property] !== null) {
 					if (slave.rules.release[property] !== rule.releaseRules[property]) {
 						slave.rules.release[property] = rule.releaseRules[property];
-						changed = true;
+						source = sourceRecord.releaseRules[property];
 					}
 				}
 			}
-			return changed;
+			return source;
 		}
 	}
 
@@ -2012,7 +2019,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.rules.lactation !== rule.lactationRules) {
 				if ((rule.lactationRules === "induce" && slave.lactation === 0) || (rule.lactationRules === "maintain" && slave.lactation === 1) || (rule.lactationRules === "none")) {
 					slave.rules.lactation = rule.lactationRules;
-					r += `<br>${slave.slaveName}'s lactation rules have been set to ${rule.lactationRules}.`;
+					message(`${slave.slaveName}'s lactation rules have been set to ${rule.lactationRules}.`, sourceRecord.lactationRules);
 				}
 			}
 		}
@@ -2026,7 +2033,7 @@ globalThis.DefaultRules = function(slave) {
 		if ((rule.mobilityRules !== undefined) && (rule.mobilityRules !== null)) {
 			if (slave.rules.mobility !== rule.mobilityRules) {
 				slave.rules.mobility = rule.mobilityRules;
-				r += `<br>${slave.slaveName}'s usage of mobility aids has been set to ${rule.mobilityRules}.`;
+				message(`${slave.slaveName}'s usage of mobility aids has been set to ${rule.mobilityRules}.`, sourceRecord.mobilityRules);
 			}
 		}
 	}
@@ -2039,7 +2046,7 @@ globalThis.DefaultRules = function(slave) {
 		if ((rule.standardPunishment !== undefined) && (rule.standardPunishment !== null)) {
 			if (slave.rules.punishment !== rule.standardPunishment) {
 				slave.rules.punishment = rule.standardPunishment;
-				r += `<br>${slave.slaveName}'s typical punishment has been updated to ${rule.standardPunishment}.`;
+				message(`${slave.slaveName}'s typical punishment has been updated to ${rule.standardPunishment}.`, sourceRecord.standardPunishment);
 			}
 		}
 	}
@@ -2052,7 +2059,7 @@ globalThis.DefaultRules = function(slave) {
 		if ((rule.standardReward !== undefined) && (rule.standardReward !== null)) {
 			if (slave.rules.reward !== rule.standardReward) {
 				slave.rules.reward = rule.standardReward;
-				r += `<br>${slave.slaveName}'s typical reward has been updated to ${rule.standardReward}.`;
+				message(`${slave.slaveName}'s typical reward has been updated to ${rule.standardReward}.`, sourceRecord.standardReward);
 			}
 		}
 	}
@@ -2066,30 +2073,30 @@ globalThis.DefaultRules = function(slave) {
 			if (rule.toyHole === "pussy") {
 				if (slave.vagina > 0 && canDoVaginal(slave)) {
 					slave.toyHole = rule.toyHole;
-					r += `<br>${slave.slaveName} has been instructed to use ${his} ${rule.toyHole} to please you.`;
+					message(`${slave.slaveName} has been instructed to use ${his} ${rule.toyHole} to please you.`, sourceRecord.toyHole);
 				} else if (slave.toyHole !== "all her holes") {
 					slave.toyHole = "all her holes";
-					r += `<br>${slave.slaveName}'s hole preference has defaulted to all ${his} holes.`;
+					message(`${slave.slaveName}'s hole preference has defaulted to all ${his} holes.`, sourceRecord.toyHole);
 				}
 			} else if (rule.toyHole === "ass") {
 				if (slave.anus > 0 && canDoAnal(slave)) {
 					slave.toyHole = rule.toyHole;
-					r += `<br>${slave.slaveName} has been instructed to use ${his} ${rule.toyHole} to please you.`;
+					message(`${slave.slaveName} has been instructed to use ${his} ${rule.toyHole} to please you.`, sourceRecord.toyHole);
 				} else if (slave.toyHole !== "all her holes") {
 					slave.toyHole = "all her holes";
-					r += `<br>${slave.slaveName}'s hole preference has defaulted to all ${his} holes.`;
+					message(`${slave.slaveName}'s hole preference has defaulted to all ${his} holes.`, sourceRecord.toyHole);
 				}
 			} else if (rule.toyHole === "dick") {
 				if (slave.dick > 0 && canPenetrate(slave)) {
 					slave.toyHole = rule.toyHole;
-					r += `<br>${slave.slaveName} has been instructed to use ${his} ${rule.toyHole} to please you.`;
+					message(`${slave.slaveName} has been instructed to use ${his} ${rule.toyHole} to please you.`, sourceRecord.toyHole);
 				} else if (slave.toyHole !== "all her holes") {
 					slave.toyHole = "all her holes";
-					r += `<br>${slave.slaveName}'s hole preference has defaulted to all ${his} holes.`;
+					message(`${slave.slaveName}'s hole preference has defaulted to all ${his} holes.`, sourceRecord.toyHole);
 				}
 			} else {
 				slave.toyHole = rule.toyHole;
-				r += `<br>${slave.slaveName} has been instructed to use ${his} ${rule.toyHole} to please you.`;
+				message(`${slave.slaveName} has been instructed to use ${his} ${rule.toyHole} to please you.`, sourceRecord.toyHole);
 			}
 		}
 	}
@@ -2103,12 +2110,12 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.dietCum !== rule.dietCum) {
 				slave.dietCum = rule.dietCum;
 				if (slave.dietCum === 2) {
-					r += `<br>${slave.slaveName} has been put on a diet based on cum.`;
+					message(`${slave.slaveName} has been put on a diet based on cum.`, sourceRecord.dietCum);
 					slave.dietMilk = 0;
 				} else if (slave.dietCum === 1) {
-					r += `<br>${slave.slaveName} has had cum added to ${his} diet.`;
+					message(`${slave.slaveName} has had cum added to ${his} diet.`, sourceRecord.dietCum);
 				} else {
-					r += `<br>${slave.slaveName} has had cum removed from ${his} diet.`;
+					message(`${slave.slaveName} has had cum removed from ${his} diet.`, sourceRecord.dietCum);
 				}
 			}
 		}
@@ -2123,12 +2130,12 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.dietMilk !== rule.dietMilk) {
 				slave.dietMilk = rule.dietMilk;
 				if (slave.dietMilk === 2) {
-					r += `<br>${slave.slaveName} has been put on a diet based on human milk.`;
+					message(`${slave.slaveName} has been put on a diet based on human milk.`, sourceRecord.dietMilk);
 					slave.dietCum = 0;
 				} else if (slave.dietMilk === 1) {
-					r += `<br>${slave.slaveName} has had human milk added to ${his} diet.`;
+					message(`${slave.slaveName} has had human milk added to ${his} diet.`, sourceRecord.dietMilk);
 				} else {
-					r += `<br>${slave.slaveName} has had human milk removed from ${his} diet.`;
+					message(`${slave.slaveName} has had human milk removed from ${his} diet.`, sourceRecord.dietMilk);
 				}
 			}
 		}
@@ -2143,9 +2150,9 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.onDiet !== rule.onDiet) {
 				slave.onDiet = rule.onDiet;
 				if (slave.onDiet === 1) {
-					r += `<br>${slave.slaveName} is not permitted to eat the solid slave food.`;
+					message(`${slave.slaveName} is not permitted to eat the solid slave food.`, sourceRecord.onDiet);
 				} else {
-					r += `<br>${slave.slaveName} is permitted to eat the solid slave food.`;
+					message(`${slave.slaveName} is permitted to eat the solid slave food.`, sourceRecord.onDiet);
 				}
 			}
 		}
@@ -2161,36 +2168,36 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.teeth === "crooked") {
 					slave.teeth = "straightening braces";
 					cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave);
-					r += `<br>${slave.slaveName} has been given braces for ${his} crooked teeth.`;
+					message(`${slave.slaveName} has been given braces for ${his} crooked teeth.`, sourceRecord.teeth);
 				} else if (slave.teeth === "gapped") {
 					slave.teeth = "straightening braces";
 					cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave);
-					r += `<br>${slave.slaveName} has been given braces to close the gap in ${his} teeth.`;
+					message(`${slave.slaveName} has been given braces to close the gap in ${his} teeth.`, sourceRecord.teeth);
 				} else if (slave.teeth === "normal") {
 					slave.teeth = "cosmetic braces";
 					cashX(forceNeg(V.modCost), "slaveSurgery", slave);
-					r += `<br>${slave.slaveName} has been given cosmetic braces.`;
+					message(`${slave.slaveName} has been given cosmetic braces.`, sourceRecord.teeth);
 				}
 			} else if (rule.teeth === "straighten") {
 				if (slave.teeth === "crooked") {
 					slave.teeth = "straightening braces";
 					cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave);
-					r += `<br>${slave.slaveName} has been given braces for ${his} crooked teeth.`;
+					message(`${slave.slaveName} has been given braces for ${his} crooked teeth.`, sourceRecord.teeth);
 				} else if (slave.teeth === "gapped") {
 					slave.teeth = "straightening braces";
 					cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave);
-					r += `<br>${slave.slaveName} has been given braces to close the gap in ${his} teeth.`;
+					message(`${slave.slaveName} has been given braces to close the gap in ${his} teeth.`, sourceRecord.teeth);
 				} else if (slave.teeth === "cosmetic braces") {
 					slave.teeth = "normal";
-					r += `<br>${slave.slaveName} has had ${his} braces removed, since ${his} teeth are straight.`;
+					message(`${slave.slaveName} has had ${his} braces removed, since ${his} teeth are straight.`, sourceRecord.teeth);
 				}
 			} else if (rule.teeth === "none") {
 				if (slave.teeth === "straightening braces") {
 					slave.teeth = "crooked";
-					r += `<br>${slave.slaveName} has had ${his} braces removed.`;
+					message(`${slave.slaveName} has had ${his} braces removed.`, sourceRecord.teeth);
 				} else if (slave.teeth === "cosmetic braces") {
 					slave.teeth = "normal";
-					r += `<br>${slave.slaveName} has had ${his} braces removed.`;
+					message(`${slave.slaveName} has had ${his} braces removed.`, sourceRecord.teeth);
 				}
 			}
 		}
@@ -2268,7 +2275,7 @@ globalThis.DefaultRules = function(slave) {
 				}
 			}
 			const lens = toSentence(lensDesc);
-			r += `<br>${slave.slaveName} has been given ${hasBothEyes(slave) ? `contact lenses` : `a contact lens`} with ${lens}.`;
+			message(`${slave.slaveName} has been given ${hasBothEyes(slave) ? `contact lenses` : `a contact lens`} with ${lens}.`, [sourceRecord.iris, sourceRecord.pupil, sourceRecord.sclera]);
 		}
 	}
 
@@ -2283,7 +2290,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.makeup !== rule.makeup) {
 				slave.makeup = rule.makeup;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName} has been assigned the standard makeup.`;
+				message(`${slave.slaveName} has been assigned the standard makeup.`, sourceRecord.makeup);
 			}
 		}
 
@@ -2292,7 +2299,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.nails !== rule.nails) {
 					slave.nails = rule.nails;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName} has been assigned the standard nails.`;
+					message(`${slave.slaveName} has been assigned the standard nails.`, sourceRecord.nails);
 				}
 			}
 		}
@@ -2302,7 +2309,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.hColor !== rule.hColor) {
 					slave.hColor = rule.hColor;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s hair has been dyed ${rule.hColor}.`;
+					message(`${slave.slaveName}'s hair has been dyed ${rule.hColor}.`, sourceRecord.hColor);
 				}
 			}
 		}
@@ -2312,7 +2319,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.hornColor !== rule.hornColor) {
 					slave.hornColor = rule.hornColor;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s horns has been dyed ${rule.hornColor}.`;
+					message(`${slave.slaveName}'s horns has been dyed ${rule.hornColor}.`, sourceRecord.hornColor);
 				}
 			}
 		}
@@ -2324,20 +2331,20 @@ globalThis.DefaultRules = function(slave) {
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
 					if (rule.hStyle === "shaved") {
 						slave.hLength = 0;
-						r += `<br>${slave.slaveName}'s hair has been shaved.`;
+						message(`${slave.slaveName}'s hair has been shaved.`, sourceRecord.hStyle);
 					} else {
-						r += `<br>${slave.slaveName}'s hair has been restyled`;
+						let m = `${slave.slaveName}'s hair has been restyled`;
 						// Cut hair if needed
 						for (const style of App.Medicine.Modification.hairStyles.Cut) {
 							if (style.value === rule.hStyle) {
 								if (slave.hLength > style.hLength) {
 									slave.hLength = style.hLength;
-									r += ` and shortened`;
+									m += ` and shortened`;
 								}
 								break;
 							}
 						}
-						r += `.`;
+						message(`${m}.`, sourceRecord.hStyle);
 					}
 				}
 			}
@@ -2348,10 +2355,10 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.hLength !== rule.hLength) {
 					if (slave.hLength > rule.hLength) {
 						cashX(forceNeg(V.modCost), "slaveMod", slave);
-						r += `<br>${slave.slaveName}'s hair has been cut; it `;
+						message(`${slave.slaveName}'s hair has been cut; it `, sourceRecord.hLength);
 					} else {
 						cashX(forceNeg(V.modCost * Math.trunc((rule.hLength - slave.hLength) / 10)), "slaveMod", slave);
-						r += `<br>${slave.slaveName} has been given extensions; ${his} hair `;
+						message(`${slave.slaveName} has been given extensions; ${his} hair `, sourceRecord.hLength);
 					}
 					r += `is now ${lengthToEitherUnit(rule.hLength)} long.`;
 					slave.hLength = rule.hLength;
@@ -2362,10 +2369,10 @@ globalThis.DefaultRules = function(slave) {
 		if (rule.haircuts !== undefined && (rule.haircuts !== null)) {
 			if (slave.bald !== 1) {
 				if (rule.haircuts === 1 && slave.haircuts !== 1) {
-					r += `<br>${slave.slaveName}'s hair will now be maintained at ${lengthToEitherUnit(slave.hLength)} long.`;
+					message(`${slave.slaveName}'s hair will now be maintained at ${lengthToEitherUnit(slave.hLength)} long.`, sourceRecord.haircuts);
 					slave.haircuts = 1;
 				} else if (rule.haircuts === 0 && slave.haircuts !== 0) {
-					r += `<br>${slave.slaveName}'s hair length will no longer be maintained.`;
+					message(`${slave.slaveName}'s hair length will no longer be maintained.`, sourceRecord.haircuts);
 					slave.haircuts = 0;
 				}
 			}
@@ -2376,7 +2383,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.eyebrowHColor !== rule.eyebrowHColor) {
 					slave.eyebrowHColor = rule.eyebrowHColor;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s eyebrow hair, if present, has been dyed ${rule.eyebrowHColor}.`;
+					message(`${slave.slaveName}'s eyebrow hair, if present, has been dyed ${rule.eyebrowHColor}.`, sourceRecord.eyebrowHColor);
 				}
 			}
 		}
@@ -2386,7 +2393,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.eyebrowHStyle !== rule.eyebrowHStyle) {
 					slave.eyebrowHStyle = rule.eyebrowHStyle;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s eyebrow hair has been restyled; they are now ${rule.eyebrowHStyle}.`;
+					message(`${slave.slaveName}'s eyebrow hair has been restyled; they are now ${rule.eyebrowHStyle}.`, sourceRecord.eyebrowHStyle);
 				}
 			}
 		}
@@ -2396,7 +2403,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.eyebrowFullness !== rule.eyebrowFullness) {
 					slave.eyebrowFullness = rule.eyebrowFullness;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s eyebrow hair thickness has been adjusted; they are now ${rule.eyebrowFullness}.`;
+					message(`${slave.slaveName}'s eyebrow hair thickness has been adjusted; they are now ${rule.eyebrowFullness}.`, sourceRecord.eyebrowFullness);
 				}
 			}
 		}
@@ -2406,7 +2413,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.pubicHColor !== rule.pubicHColor) {
 					slave.pubicHColor = rule.pubicHColor;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s pubic hair, if present, has been dyed ${rule.pubicHColor}.`;
+					message(`${slave.slaveName}'s pubic hair, if present, has been dyed ${rule.pubicHColor}.`, sourceRecord.pubicHColor);
 				}
 			}
 		}
@@ -2416,7 +2423,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.pubicHStyle !== rule.pubicHStyle) {
 					slave.pubicHStyle = rule.pubicHStyle;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s pubic hair has been restyled; it is now ${rule.pubicHStyle}.`;
+					message(`${slave.slaveName}'s pubic hair has been restyled; it is now ${rule.pubicHStyle}.`, sourceRecord.pubicHStyle);
 				}
 			}
 		}
@@ -2426,7 +2433,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.underArmHColor !== rule.underArmHColor) {
 					slave.underArmHColor = rule.underArmHColor;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s underarm hair, if present, has been dyed ${rule.underArmHColor}.`;
+					message(`${slave.slaveName}'s underarm hair, if present, has been dyed ${rule.underArmHColor}.`, sourceRecord.underArmHColor);
 				}
 			}
 		}
@@ -2436,7 +2443,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.underArmHStyle !== rule.underArmHStyle) {
 					slave.underArmHStyle = rule.underArmHStyle;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s underarm hair has been restyled; it is now ${rule.underArmHStyle}.`;
+					message(`${slave.slaveName}'s underarm hair has been restyled; it is now ${rule.underArmHStyle}.`, sourceRecord.underArmHStyle);
 				}
 			}
 		}
@@ -2446,7 +2453,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.eyebrowHColor !== rule.eyebrowHColor) {
 					slave.eyebrowHColor = rule.eyebrowHColor;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s eyebrow hair, if present, has been dyed ${rule.eyebrowHColor}.`;
+					message(`${slave.slaveName}'s eyebrow hair, if present, has been dyed ${rule.eyebrowHColor}.`, sourceRecord.eyebrowHColor);
 				}
 			}
 		}
@@ -2456,7 +2463,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.eyebrowHStyle !== rule.eyebrowHStyle) {
 					slave.eyebrowHStyle = rule.eyebrowHStyle;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s eyebrow hair has been restyled; it is now ${rule.eyebrowHStyle}.`;
+					message(`${slave.slaveName}'s eyebrow hair has been restyled; it is now ${rule.eyebrowHStyle}.`, sourceRecord.eyebrowHStyle);
 				}
 			}
 		}
@@ -2466,19 +2473,19 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.eyebrowFullness !== rule.eyebrowFullness) {
 					slave.eyebrowFullness = rule.eyebrowFullness;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s eyebrow hair has been reshaped; it is now ${rule.eyebrowFullness}.`;
+					message(`${slave.slaveName}'s eyebrow hair has been reshaped; it is now ${rule.eyebrowFullness}.`, sourceRecord.eyebrowFullness);
 				}
 			}
 		}
 
 		if (rule.markings !== undefined && (rule.markings !== null)) {
 			if (slave.markings === "beauty mark" && (rule.markings === "remove beauty marks" || rule.markings === "remove both")) {
-				r += `<br>${slave.slaveName}'s beauty mark has been removed.`;
+				message(`${slave.slaveName}'s beauty mark has been removed.`, sourceRecord.markings);
 				slave.markings = "none";
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
 			}
 			if (slave.markings === "birthmark" && (rule.markings === "remove birthmarks" || rule.markings === "remove both")) {
-				r += `<br>${slave.slaveName}'s birthmark has been bleached away.`;
+				message(`${slave.slaveName}'s birthmark has been bleached away.`, sourceRecord.markings);
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
 				slave.markings = "none";
 			}
@@ -2488,11 +2495,11 @@ globalThis.DefaultRules = function(slave) {
 			if (rule.skinColor === "natural") {
 				if (slave.skin !== slave.origSkin) {
 					slave.skin = slave.origSkin;
-					r += `<br>${slave.slaveName}'s skin color has been returned to ${slave.origSkin}.`;
+					message(`${slave.slaveName}'s skin color has been returned to ${slave.origSkin}.`, sourceRecord.skinColor);
 				}
 			} else {
 				slave.skin = rule.skinColor;
-				r += `<br>${slave.slaveName}'s skin color has been set to ${rule.skinColor}.`;
+				message(`${slave.slaveName}'s skin color has been set to ${rule.skinColor}.`, sourceRecord.skinColor);
 			}
 		}
 	}
@@ -2506,13 +2513,13 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.nipple.weight !== rule.piercing.nipple.weight) {
 				if (rule.piercing.nipple.weight === 0) {
 					slave.piercing.nipple.weight = 0;
-					r += `<br>${slave.slaveName}'s nipple piercings have been removed.`;
+					message(`${slave.slaveName}'s nipple piercings have been removed.`, sourceRecord.piercing.nipple.weight);
 				} else if (slave.nipples !== "fuckable") {
 					slave.piercing.nipple.weight = rule.piercing.nipple.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s nipples have been pierced.`;
+					message(`${slave.slaveName}'s nipples have been pierced.`, sourceRecord.piercing.nipple.weight);
 				} else {
-					r += `<br>${slave.slaveName}'s nipples are inverted and cannot be pierced.`;
+					message(`${slave.slaveName}'s nipples are inverted and cannot be pierced.`, sourceRecord.piercing.nipple.weight);
 				}
 			}
 		}
@@ -2521,11 +2528,11 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.areola.weight !== rule.piercing.areola.weight) {
 				if (rule.piercing.areola.weight === 0) {
 					slave.piercing.areola.weight = 0;
-					r += `<br>${slave.slaveName}'s areolae piercings have been removed.`;
+					message(`${slave.slaveName}'s areolae piercings have been removed.`, sourceRecord.piercing.areola.weight);
 				} else {
 					slave.piercing.areola.weight = rule.piercing.areola.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s areolae have been given stud piercings.`;
+					message(`${slave.slaveName}'s areolae have been given stud piercings.`, sourceRecord.piercing.areola.weight);
 				}
 			}
 		}
@@ -2536,17 +2543,17 @@ globalThis.DefaultRules = function(slave) {
 					slave.piercing.genitals.weight = 0;
 					slave.piercing.genitals.smart = false;
 					if (slave.dick > 0) {
-						r += `<br>${slave.slaveName}'s frenulum piercing has been removed.`;
+						message(`${slave.slaveName}'s frenulum piercing has been removed.`, sourceRecord.piercing.genitals.weight);
 					} else {
-						r += `<br>${slave.slaveName}'s clit piercing has been removed.`;
+						message(`${slave.slaveName}'s clit piercing has been removed.`, sourceRecord.piercing.genitals.weight);
 					}
 				} else if ((slave.vagina !== -1) || (slave.dick !== 0)) {
 					slave.piercing.genitals.weight = rule.piercing.genitals.weight;
 					cashX(forceNeg(V.SPcost), "slaveMod", slave);
 					if (slave.dick > 0) {
-						r += `<br>${slave.slaveName}'s frenulum has been pierced.`;
+						message(`${slave.slaveName}'s frenulum has been pierced.`, sourceRecord.piercing.genitals.weight);
 					} else {
-						r += `<br>${slave.slaveName}'s clit has been pierced.`;
+						message(`${slave.slaveName}'s clit has been pierced.`, sourceRecord.piercing.genitals.weight);
 					}
 				}
 			}
@@ -2557,11 +2564,11 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.piercing.vagina.weight !== rule.piercing.vagina.weight) {
 					if (rule.piercing.vagina.weight === 0) {
 						slave.piercing.vagina.weight = 0;
-						r += `<br>${slave.slaveName}'s labia piercings have been removed.`;
+						message(`${slave.slaveName}'s labia piercings have been removed.`, sourceRecord.piercing.vagina.weight);
 					} else {
 						slave.piercing.vagina.weight = rule.piercing.vagina.weight;
 						cashX(forceNeg(V.modCost), "slaveMod", slave);
-						r += `<br>${slave.slaveName}'s pussylips have been pierced.`;
+						message(`${slave.slaveName}'s pussylips have been pierced.`, sourceRecord.piercing.vagina.weight);
 					}
 				}
 			}
@@ -2572,11 +2579,11 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.piercing.dick.weight !== rule.piercing.dick.weight) {
 					if (rule.piercing.dick.weight === 0) {
 						slave.piercing.dick.weight = 0;
-						r += `<br>${slave.slaveName}'s shaft piercings have been removed.`;
+						message(`${slave.slaveName}'s shaft piercings have been removed.`, sourceRecord.piercing.dick.weight);
 					} else {
 						slave.piercing.dick.weight = rule.piercing.dick.weight;
 						cashX(forceNeg(V.modCost), "slaveMod", slave);
-						r += `<br>${slave.slaveName}'s shaft has been pierced.`;
+						message(`${slave.slaveName}'s shaft has been pierced.`, sourceRecord.piercing.dick.weight);
 					}
 				}
 			}
@@ -2587,12 +2594,12 @@ globalThis.DefaultRules = function(slave) {
 				if (rule.piercing.genitals.smart === false) {
 					slave.piercing.genitals.smart = false;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s ${slave.dick > 0 ? "frenulum" : "clit"} piercing's smart vibe capability has been removed.`;
+					message(`${slave.slaveName}'s ${slave.dick > 0 ? "frenulum" : "clit"} piercing's smart vibe capability has been removed.`, sourceRecord.piercing.genitals.smart);
 				} else if (slave.piercing.genitals.weight) {
 					slave.piercing.genitals.smart = true;
 					cashX(forceNeg(V.SPcost), "slaveMod", slave);
 					slave.clitSetting = "all";
-					r += `<br>${slave.slaveName}'s ${slave.dick > 0 ? "frenulum" : "clit"} piercing has been upgraded with smart vibe functionality.`;
+					message(`${slave.slaveName}'s ${slave.dick > 0 ? "frenulum" : "clit"} piercing has been upgraded with smart vibe functionality.`, sourceRecord.piercing.genitals.smart);
 				}
 			}
 		}
@@ -2601,11 +2608,11 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.anus.weight !== rule.piercing.anus.weight) {
 				if (rule.piercing.anus.weight === 0) {
 					slave.piercing.anus.weight = 0;
-					r += `<br>${slave.slaveName}'s asshole piercings have been removed.`;
+					message(`${slave.slaveName}'s asshole piercings have been removed.`, sourceRecord.piercing.anus.weight);
 				} else {
 					slave.piercing.anus.weight = rule.piercing.anus.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s asshole has been pierced.`;
+					message(`${slave.slaveName}'s asshole has been pierced.`, sourceRecord.piercing.anus.weight);
 				}
 			}
 		}
@@ -2614,11 +2621,11 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.lips.weight !== rule.piercing.lips.weight) {
 				if (rule.piercing.lips.weight === 0) {
 					slave.piercing.lips.weight = 0;
-					r += `<br>${slave.slaveName}'s lip piercings have been removed.`;
+					message(`${slave.slaveName}'s lip piercings have been removed.`, sourceRecord.piercing.lips.weight);
 				} else {
 					slave.piercing.lips.weight = rule.piercing.lips.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s lips have been pierced.`;
+					message(`${slave.slaveName}'s lips have been pierced.`, sourceRecord.piercing.lips.weight);
 				}
 			}
 		}
@@ -2627,11 +2634,11 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.tongue.weight !== rule.piercing.tongue.weight) {
 				if (rule.piercing.tongue.weight === 0) {
 					slave.piercing.tongue.weight = 0;
-					r += `<br>${slave.slaveName}'s tongue piercings have been removed.`;
+					message(`${slave.slaveName}'s tongue piercings have been removed.`, sourceRecord.piercing.tongue.weight);
 				} else {
 					slave.piercing.tongue.weight = rule.piercing.tongue.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s tongue has been pierced.`;
+					message(`${slave.slaveName}'s tongue has been pierced.`, sourceRecord.piercing.tongue.weight);
 				}
 			}
 		}
@@ -2640,11 +2647,11 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.ear.weight !== rule.piercing.ear.weight) {
 				if (rule.piercing.ear.weight === 0) {
 					slave.piercing.ear.weight = 0;
-					r += `<br>${slave.slaveName}'s ear piercings have been removed.`;
+					message(`${slave.slaveName}'s ear piercings have been removed.`, sourceRecord.piercing.ear.weight);
 				} else {
 					slave.piercing.ear.weight = rule.piercing.ear.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s ears have been pierced.`;
+					message(`${slave.slaveName}'s ears have been pierced.`, sourceRecord.piercing.ear.weight);
 				}
 			}
 		}
@@ -2653,11 +2660,11 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.nose.weight !== rule.piercing.nose.weight) {
 				if (rule.piercing.nose.weight === 0) {
 					slave.piercing.nose.weight = 0;
-					r += `<br>${slave.slaveName}'s nose piercing has been removed.`;
+					message(`${slave.slaveName}'s nose piercing has been removed.`, sourceRecord.piercing.nose.weight);
 				} else {
 					slave.piercing.nose.weight = rule.piercing.nose.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s nose has been pierced.`;
+					message(`${slave.slaveName}'s nose has been pierced.`, sourceRecord.piercing.nose.weight);
 				}
 			}
 		}
@@ -2666,11 +2673,11 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.eyebrow.weight !== rule.piercing.eyebrow.weight) {
 				if (rule.piercing.eyebrow.weight === 0) {
 					slave.piercing.eyebrow.weight = 0;
-					r += `<br>${slave.slaveName}'s eyebrow piercings have been removed.`;
+					message(`${slave.slaveName}'s eyebrow piercings have been removed.`, sourceRecord.piercing.eyebrow.weight);
 				} else {
 					slave.piercing.eyebrow.weight = rule.piercing.eyebrow.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s eyebrows have been pierced.`;
+					message(`${slave.slaveName}'s eyebrows have been pierced.`, sourceRecord.piercing.eyebrow.weight);
 				}
 			}
 		}
@@ -2679,11 +2686,11 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.navel.weight !== rule.piercing.navel.weight) {
 				if (rule.piercing.navel.weight === 0) {
 					slave.piercing.navel.weight = 0;
-					r += `<br>${slave.slaveName}'s navel piercing have been removed.`;
+					message(`${slave.slaveName}'s navel piercing have been removed.`, sourceRecord.piercing.navel.weight);
 				} else {
 					slave.piercing.navel.weight = rule.piercing.navel.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s navel has been pierced.`;
+					message(`${slave.slaveName}'s navel has been pierced.`, sourceRecord.piercing.navel.weight);
 				}
 			}
 		}
@@ -2692,11 +2699,11 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.piercing.corset.weight !== rule.piercing.corset.weight) {
 				if (rule.piercing.corset.weight === 0) {
 					slave.piercing.corset.weight = 0;
-					r += `<br>${slave.slaveName}'s corset piercings have been removed.`;
+					message(`${slave.slaveName}'s corset piercings have been removed.`, sourceRecord.piercing.corset.weight);
 				} else {
 					slave.piercing.corset.weight = rule.piercing.corset.weight;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName} has been given a set of corset piercings.`;
+					message(`${slave.slaveName} has been given a set of corset piercings.`, sourceRecord.piercing.corset.weight);
 				}
 			}
 		}
@@ -2706,9 +2713,9 @@ globalThis.DefaultRules = function(slave) {
 				if (rule.piercing[p].desc !== undefined && (rule.piercing[p].desc !== null)) {
 					if (slave.piercing[p].desc !== rule.piercing[p].desc) {
 						if (rule.piercing[p].desc === "") {
-							r += `<br>${slave.slaveName}'s ${p} piercings will use the default design.`;
+							message(`${slave.slaveName}'s ${p} piercings will use the default design.`, sourceRecord.piercing[p].desc);
 						} else {
-							r += `<br>${slave.slaveName}'s ${p} piercings have been updated to a different design.`;
+							message(`${slave.slaveName}'s ${p} piercings have been updated to a different design.`, sourceRecord.piercing[p].desc);
 						}
 						slave.piercing[p].desc = rule.piercing[p].desc;
 					}
@@ -2735,7 +2742,7 @@ globalThis.DefaultRules = function(slave) {
 					// Set the smart thingy to the correct fetish
 					if (slave.clitSetting !== fetish) {
 						slave.clitSetting = fetish;
-						r += `<br>${slave.slaveName}'s ${smartThing} has been set to ${slave.clitSetting}.`;
+						message(`${slave.slaveName}'s ${smartThing} has been set to ${slave.clitSetting}.`, sourceRecord.clitSetting);
 					}
 					// We haven't reached full fetish yet, don't allow changing to something else
 					return;
@@ -2744,13 +2751,13 @@ globalThis.DefaultRules = function(slave) {
 			if (rule.clitSettingEnergy !== undefined && (rule.clitSettingEnergy !== null)) {
 				if (slave.energy < rule.clitSettingEnergy) {
 					if (slave.clitSetting !== "all") {
-						r += `<br>${slave.slaveName}'s ${smartThing} has been set to enhance libido.`;
+						message(`${slave.slaveName}'s ${smartThing} has been set to enhance libido.`, sourceRecord.clitSettingEnergy);
 					}
 					slave.clitSetting = "all";
 					return;
 				} else if (slave.energy >= rule.clitSettingEnergy + 10 && rule.clitSettingEnergy <= 90) {
 					if (slave.clitSetting !== "none") {
-						r += `<br>${slave.slaveName}'s ${smartThing} has been set to suppress libido.`;
+						message(`${slave.slaveName}'s ${smartThing} has been set to suppress libido.`, sourceRecord.clitSettingEnergy);
 					}
 					slave.clitSetting = "none";
 					return;
@@ -2759,13 +2766,13 @@ globalThis.DefaultRules = function(slave) {
 			if (rule.clitSettingXY !== undefined && (rule.clitSettingXY !== null)) {
 				if (slave.attrXY < rule.clitSettingXY) {
 					if (slave.clitSetting !== "men") {
-						r += `<br>${slave.slaveName}'s ${smartThing} has been set to encourage attraction to men.`;
+						message(`${slave.slaveName}'s ${smartThing} has been set to encourage attraction to men.`, sourceRecord.clitSettingXY);
 					}
 					slave.clitSetting = "men";
 					return;
 				} else if (slave.attrXY >= rule.clitSettingXY + 10 && rule.clitSettingXY <= 90) {
 					if (slave.clitSetting !== "anti-men") {
-						r += `<br>${slave.slaveName}'s ${smartThing} has been set to discourage attraction to men.`;
+						message(`${slave.slaveName}'s ${smartThing} has been set to discourage attraction to men.`, sourceRecord.clitSettingXY);
 					}
 					slave.clitSetting = "anti-men";
 					return;
@@ -2774,13 +2781,13 @@ globalThis.DefaultRules = function(slave) {
 			if (rule.clitSettingXX !== undefined && (rule.clitSettingXX !== null)) {
 				if (slave.attrXX < rule.clitSettingXX) {
 					if (slave.clitSetting !== "women") {
-						r += `<br>${slave.slaveName}'s ${smartThing} has been set to encourage attraction to women.`;
+						message(`${slave.slaveName}'s ${smartThing} has been set to encourage attraction to women.`, sourceRecord.clitSettingXX);
 					}
 					slave.clitSetting = "women";
 					return;
 				} else if (slave.attrXX >= rule.clitSettingXX + 10 && rule.clitSettingXX <= 90) {
 					if (slave.clitSetting !== "anti-women") {
-						r += `<br>${slave.slaveName}'s ${smartThing} has been set to discourage attraction to women.`;
+						message(`${slave.slaveName}'s ${smartThing} has been set to discourage attraction to women.`, sourceRecord.clitSettingXX);
 					}
 					slave.clitSetting = "anti-women";
 					return;
@@ -2798,7 +2805,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.boobsTat !== rule.boobsTat) {
 				slave.boobsTat = rule.boobsTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s chest has been tattooed.`;
+				message(`${slave.slaveName}'s chest has been tattooed.`, sourceRecord.boobsTat);
 			}
 		}
 
@@ -2806,7 +2813,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.buttTat !== rule.buttTat) {
 				slave.buttTat = rule.buttTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s butt has been tattooed.`;
+				message(`${slave.slaveName}'s butt has been tattooed.`, sourceRecord.buttTat);
 			}
 		}
 
@@ -2814,7 +2821,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.vaginaTat !== rule.vaginaTat) {
 				slave.vaginaTat = rule.vaginaTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s abdomen has been tattooed.`;
+				message(`${slave.slaveName}'s abdomen has been tattooed.`, sourceRecord.vaginaTat);
 			}
 		}
 
@@ -2823,7 +2830,7 @@ globalThis.DefaultRules = function(slave) {
 				if (slave.dickTat !== rule.dickTat) {
 					slave.dickTat = rule.dickTat;
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s dick has been tattooed.`;
+					message(`${slave.slaveName}'s dick has been tattooed.`, sourceRecord.dickTat);
 				}
 			}
 		}
@@ -2832,7 +2839,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.lipsTat !== rule.lipsTat) {
 				slave.lipsTat = rule.lipsTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s face has been tattooed.`;
+				message(`${slave.slaveName}'s face has been tattooed.`, sourceRecord.lipsTat);
 			}
 		}
 
@@ -2840,7 +2847,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.anusTat !== rule.anusTat) {
 				slave.anusTat = rule.anusTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s asshole has been modded.`;
+				message(`${slave.slaveName}'s asshole has been modded.`, sourceRecord.anusTat);
 			}
 		}
 
@@ -2848,7 +2855,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.backTat !== rule.backTat) {
 				slave.backTat = rule.backTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s back has been tattooed.`;
+				message(`${slave.slaveName}'s back has been tattooed.`, sourceRecord.backTat);
 			}
 		}
 
@@ -2856,21 +2863,21 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.shouldersTat !== rule.shouldersTat) {
 				slave.shouldersTat = rule.shouldersTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s shoulders have been tattooed.`;
+				message(`${slave.slaveName}'s shoulders have been tattooed.`, sourceRecord.shouldersTat);
 			}
 		}
 
 		if (rule.armsTat !== undefined && (rule.armsTat !== null)) {
-			if (slave.armsTat !== rule.armsTat) {
+			if (hasAnyArms(slave) && slave.armsTat !== rule.armsTat) {
 				slave.armsTat = rule.armsTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s `;
+				let m = `${slave.slaveName}'s `;
 				if (hasBothArms(slave)) {
-					r += `arms have`;
+					m += `arms have`;
 				} else {
-					r += `arm has`;
+					m += `arm has`;
 				}
-				r += ` been tattooed.`;
+				message(`${m} been tattooed.`, sourceRecord.armsTat);
 			}
 		}
 
@@ -2878,7 +2885,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.legsTat !== rule.legsTat) {
 				slave.legsTat = rule.legsTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s legs have been tattooed.`;
+				message(`${slave.slaveName}'s legs have been tattooed.`, sourceRecord.legsTat);
 			}
 		}
 
@@ -2886,21 +2893,21 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.stampTat !== rule.stampTat) {
 				slave.stampTat = rule.stampTat;
 				cashX(forceNeg(V.modCost), "slaveMod", slave);
-				r += `<br>${slave.slaveName}'s lower back has been tattooed.`;
+				message(`${slave.slaveName}'s lower back has been tattooed.`, sourceRecord.stampTat);
 			}
 		}
 		if (rule.birthsTat !== undefined && (rule.birthsTat !== null)) {
 			if (rule.birthsTat === "remove") {
 				if (slave.birthsTat > 0) {
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s birth tallies have been removed.`;
+					message(`${slave.slaveName}'s birth tallies have been removed.`, sourceRecord.birthsTat);
 				} else if (slave.birthsTat > -1) {
-					r += `<br>${slave.slaveName} will no longer be tattooed with each birth.`;
+					message(`${slave.slaveName} will no longer be tattooed with each birth.`, sourceRecord.birthsTat);
 				}
 				slave.birthsTat = -1;
 			} else if (rule.birthsTat === "tally") {
 				if (slave.birthsTat < 0) {
-					r += `<br>${slave.slaveName} will be tattooed with each birth.`;
+					message(`${slave.slaveName} will be tattooed with each birth.`, sourceRecord.birthsTat);
 					slave.birthsTat = 0;
 				}
 			}
@@ -2909,14 +2916,14 @@ globalThis.DefaultRules = function(slave) {
 			if (rule.abortionTat === "remove") {
 				if (slave.abortionTat > 0) {
 					cashX(forceNeg(V.modCost), "slaveMod", slave);
-					r += `<br>${slave.slaveName}'s abortion tallies have been removed.`;
+					message(`${slave.slaveName}'s abortion tallies have been removed.`, sourceRecord.abortionTat);
 				} else if (slave.abortionTat > -1) {
-					r += `<br>${slave.slaveName} will no longer be tattooed with each abortion and miscarriage.`;
+					message(`${slave.slaveName} will no longer be tattooed with each abortion and miscarriage.`, sourceRecord.abortionTat);
 				}
 				slave.abortionTat = -1;
 			} else if (rule.abortionTat === "tally") {
 				if (slave.abortionTat < 0) {
-					r += `<br>${slave.slaveName} will be tattooed with each abortion and miscarriage.`;
+					message(`${slave.slaveName} will be tattooed with each abortion and miscarriage.`, sourceRecord.abortionTat);
 					slave.abortionTat = 0;
 				}
 			}
@@ -3040,18 +3047,18 @@ globalThis.DefaultRules = function(slave) {
 				// Apply brands:
 				if (["left", "right", "anywhere"].includes(brandPlace)) {
 					healthDamage(slave, 10);
-					r += `<br>${slave.slaveName} has been branded on the `;
+					let m = `${slave.slaveName} has been branded on the `;
 					if (brandPlace === "left") {
 						App.Medicine.Modification.addBrand(slave, left, rule.brandDesign);
-						r += `${left}`;
+						m += `${left}`;
 					} else if (brandPlace === "right") {
 						App.Medicine.Modification.addBrand(slave, right, rule.brandDesign);
-						r += `${right}`;
+						m += `${right}`;
 					} else if (brandPlace === "anywhere") {
 						App.Medicine.Modification.addBrand(slave, rule.brandTarget, rule.brandDesign);
-						r += `${rule.brandTarget}`;
+						m += `${rule.brandTarget}`;
 					}
-					r += `, with <span class="trust dec">fear</span>${slave.devotion < 18 ? `, <span class="devotion dec">regard,</span>` : ``} and <span class="health dec">health</span> consequences.`;
+					message(`${m}, with <span class="trust dec">fear</span>${slave.devotion < 18 ? `, <span class="devotion dec">regard,</span>` : ``} and <span class="health dec">health</span> consequences.`, sourceRecord.brandDesign);
 					if (slave.devotion < 18) {
 						slave.devotion -= 5;
 					}
@@ -3060,7 +3067,7 @@ globalThis.DefaultRules = function(slave) {
 					App.Medicine.Modification.addBrand(slave, left, rule.brandDesign);
 					App.Medicine.Modification.addBrand(slave, right, rule.brandDesign);
 					healthDamage(slave, 20);
-					r += `<br>${slave.slaveName} has been branded on both ${rule.brandTarget}, with <span class="trust dec">fear</span>${slave.devotion < 18 ? `, <span class="devotion dec">regard,</span>` : ``} and <span class="health dec">health</span> consequences.`;
+					message(`${slave.slaveName} has been branded on both ${rule.brandTarget}, with <span class="trust dec">fear</span>${slave.devotion < 18 ? `, <span class="devotion dec">regard,</span>` : ``} and <span class="health dec">health</span> consequences.`, sourceRecord.brandDesign);
 					if (slave.devotion < 18) {
 						slave.devotion -= 10;
 					}
@@ -3086,7 +3093,7 @@ globalThis.DefaultRules = function(slave) {
 		if (slave.porn.feed === 0) {
 			slave.porn.spending = 0;
 		}
-		r += `<br>Highlights of ${slave.slaveName}'s sex life ${yesno} being released.`;
+		message(`Highlights of ${slave.slaveName}'s sex life ${yesno} being released.`, sourceRecord.pornFeed);
 	}
 
 	/** @param {App.Entity.SlaveState} slave
@@ -3097,7 +3104,7 @@ globalThis.DefaultRules = function(slave) {
 			if (slave.porn.prestige < 3) {
 				if (slave.porn.spending !== rule.pornFameSpending) {
 					slave.porn.spending = rule.pornFameSpending;
-					r += `<br>${slave.slaveName}'s porn publicity has been corrected.`;
+					message(`${slave.slaveName}'s porn publicity has been corrected.`, sourceRecord.pornFameSpending);
 				}
 			}
 		}
@@ -3109,15 +3116,15 @@ globalThis.DefaultRules = function(slave) {
 	 */
 	function ProcessLabel(slave, rule) {
 		// mass removal of old tags, variant from '*' mask.
-		if (rule.removeLabel !== null && rule.removeLabel !== '' && rule.removeLabel === '*') {
+		if (rule.removeLabel !== null && rule.removeLabel === '*') {
 			slave.custom.label = slave.custom.label.replace(/(?:\[.+\])+/, "");
-			r += `<br>All of ${slave.slaveName}'s tags have been removed.`;
+			message(`All of ${slave.slaveName}'s tags have been removed.`, sourceRecord.removeLabel);
 		}
 
 		// mass removal of old tags, variant from GUI switch.
 		if (rule.labelTagsClear === true) {
 			slave.custom.label = slave.custom.label.replace(/(?:\[.+\])+/, "");
-			r += `<br>All of ${slave.slaveName}'s tags have been removed.`;
+			message(`All of ${slave.slaveName}'s tags have been removed.`, sourceRecord.removeLabel);
 		}
 
 		// removing tags selected for removal.
@@ -3130,7 +3137,7 @@ globalThis.DefaultRules = function(slave) {
 		for (i in tags) {
 			if (tags[i] !== null && tags[i] !== '' && slave.custom.label.includes(`[${tags[i]}]`)) {
 				slave.custom.label = slave.custom.label.replace(`[${tags[i]}]`, "");
-				r += `<br>${slave.slaveName}'s tag [${tags[i]}] is removed.`;
+				message(`${slave.slaveName}'s tag [${tags[i]}] is removed.`, sourceRecord.removeLabel);
 			}
 		}
 
@@ -3143,7 +3150,7 @@ globalThis.DefaultRules = function(slave) {
 		for (i in tags) {
 			if (tags[i] != null && tags[i] !== '' && !slave.custom.label.includes(`[${tags[i]}]`)) {
 				slave.custom.label = `${slave.custom.label}[${tags[i]}]`;
-				r += `<br>${slave.slaveName} has been tagged as ${tags[i]}`;
+				message(`${slave.slaveName} has been tagged as ${tags[i]}`, sourceRecord.label);
 			}
 		}
 	}
@@ -3153,8 +3160,26 @@ globalThis.DefaultRules = function(slave) {
 			slave.pronoun = rule.pronoun;
 		}
 	}
+
+	/**
+	 * @param {string} text
+	 * @param {string|string[]} [origin]
+	 */
+	function message(text, origin = null) {
+		r += "<br>";
+		if (origin) {
+			if (_.isArray(origin)) {
+				origin = removeDuplicates(origin);
+			}
+			r += `[${origin}] `;
+		} else {
+			r += "[Default] ";
+		}
+		r += text;
+	}
 };
 
+
 /**
  * @param {App.Entity.SlaveState} slave
  */
diff --git a/src/js/rulesAssistant.js b/src/js/rulesAssistant.js
index c247619be5f65642ac3fad48be8fef87ac24ab7f..418306d23c7d3c34f6bd07c918b3e0b5309e05e1 100644
--- a/src/js/rulesAssistant.js
+++ b/src/js/rulesAssistant.js
@@ -65,20 +65,21 @@ globalThis.rulesDemandContraceptives = function(slave, rules) {
 };
 
 /**
- * @param {FC.RA.RuleSetters[]} rules
- * @returns {FC.RA.RuleSetters}
+ * @param {Array<[FC.RA.RuleSetters, string]>} rules
+ * @returns {[FC.RA.RuleSetters,object]}
  */
 globalThis.mergeRules = function(rules) {
 	if (rules.length === 0) {
-		return emptyDefaultRule().set;
+		return [App.RA.newRule.setters(), {}];
 	}
 
-	const combinedRule = emptyDefaultRule().set;
+	const combinedRule = App.RA.newRule.setters();
+	const sourceRecord = {};
 
 	rules.forEach(rule => {
-		App.RA.ruleDeepAssign(combinedRule, rule);
+		App.RA.ruleDeepAssign(combinedRule, rule[0], sourceRecord, rule[1]);
 	});
-	return combinedRule;
+	return [combinedRule, sourceRecord];
 };
 
 /**
@@ -406,7 +407,16 @@ App.RA.shallShrink = function(current, target, step = 1) {
 		(current === target.val && target.cond === '<'));
 };
 
-App.RA.ruleDeepAssign = function deepAssign(target, source) {
+/**
+ * @template {object} T
+ * @param {object} target Rule or rule part
+ * @param {T} source Rule or rule part, describes the same part as target
+ * @param {object} sourceRecord record what was overwritten. Overwrites are located the same as in target, marked with
+ * sourceName. Describes the same rule(part) as target.
+ * @param {string} sourceName Name for the source object.
+ * @returns {T}
+ */
+App.RA.ruleDeepAssign = function deepAssign(target, source, sourceRecord, sourceName) {
 	function isObject(o) {
 		return (o !== undefined && o !== null && typeof o === 'object' && !Array.isArray(o));
 	}
@@ -419,13 +429,18 @@ App.RA.ruleDeepAssign = function deepAssign(target, source) {
 			if (!target.hasOwnProperty(key) || target[key] === null) {
 				target[key] = {};
 			}
-			deepAssign(target[key], source[key]);
+			if (!sourceRecord.hasOwnProperty(key)) {
+				sourceRecord[key] = {};
+			}
+			deepAssign(target[key], source[key], sourceRecord[key], sourceName);
 		} else if (key === "label" || key === "removeLabel") {
 			if (source[key] != null) {
 				if (target[key] != null) {
 					target[key] += "|" + source[key];
+					sourceRecord[key] += "+" + sourceName;
 				} else {
 					target[key] = source[key];
+					sourceRecord[key] = sourceName;
 				}
 			}
 		} else {
@@ -439,6 +454,9 @@ App.RA.ruleDeepAssign = function deepAssign(target, source) {
 				(key !== "autoBrand" && source[key] !== null));
 			if (overrides) {
 				target[key] = source[key];
+				if (source[key] !== null) {
+					sourceRecord[key] = sourceName;
+				}
 			}
 		}
 	}