diff --git a/src/events/nonRandom/mercs/pMercenaries.js b/src/events/nonRandom/mercs/pMercenaries.js
new file mode 100644
index 0000000000000000000000000000000000000000..293e696e3b8991fe79d4919d2cd6889ac7416c1d
--- /dev/null
+++ b/src/events/nonRandom/mercs/pMercenaries.js
@@ -0,0 +1,82 @@
+App.Events.PMercenaries = class PMercenaries extends App.Events.BaseEvent {
+	eventPrerequisites() {
+		return [
+			() => V.mercenaries === 0
+		];
+	}
+
+	execute(node) {
+		V.nextButton = "Continue";
+		V.mercenaries = 0;
+		V.mercenariesTitle = "mercenaries";
+
+		let _price;
+		if (V.PC.skill.warfare >= 100) {
+			_price = 2500;
+		} else if (V.PC.skill.warfare >= 50) {
+			_price = 3725;
+		} else {
+			_price = 5000;
+		}
+
+
+		App.Events.addParagraph(node, [`Another wave of security hysteria is sweeping the Free Cities. And this time, it's not based on rumor and alarmism. On the other side of the globe, a Free City was sacked by an old world army today. The Free City's handful of high-technology defenders and multitude of drones caused heavy casualties among the attackers, but eventually sheer weight of numbers wore them down.`]);
+
+		App.Events.addParagraph(node, [`Your Free City is on good terms with the nations that border it, unlike the unfortunate sacked city, which was next to a nation suffering total collapse and looking for a convenient target. However, there's no telling how long this will last. The situation in the small, troubled country close to the arcology you've been monitoring grows worse by the day${(V.nationHate > 0) ? ", and if rumor of your enslavement of some of their vulnerable citizens got out, its people may have cause to hate you" : ""}.`]);
+
+		App.Events.addParagraph(node, [
+			`The budgetary difficulty many old world countries are in has resulted in unemployed soldiers looking for mercenary work. You could easily hire some of them to protect the arcology and fight in the militia if necessary.`,
+			App.UI.DOM.makeElement("span", "This is a unique opportunity.", "bold"),
+			`Without this security scare, it's unlikely you could convince any of your free-spirited tenants to even stay near a permanent armed presence.`
+		]);
+		const discount = (V.PC.skill.warfare >= 50 || V.PC.career === "arcology owner");
+		const choices = [];
+		choices.push(new App.Events.Result(
+			`Quarter a squad in the arcology`, quarter,
+			`This will cost ${cashFormat(_price)} ${discount ?
+				`and some upkeep, <span class="springgreen">reduced by your mercenary contacts</span>` :
+				`and incur significant upkeep costs`}`
+		));
+		choices.push(new App.Events.Result(
+			`Quarter a platoon in the arcology`, platoon,
+			`This will cost ${cashFormat(_price * 2)} ${discount ?
+				`and some upkeep, <span class="springgreen">reduced by your mercenary contacts</span>` :
+				`and incur significant upkeep costs`}`
+		));
+		choices.push(new App.Events.Result(`Do not quarter troops in your arcology`, plead3rd));
+		App.Events.addResponses(node, choices);
+
+		function quarter() {
+			const frag = new DocumentFragment();
+			let r = [];
+			r.push(`You hire some reputable mercenaries, kit them in excellent gear, and quarter them in ${V.arcologies[0].name}. The sight of armed men on patrol has <span class="red">offended some of the more free-spirited citizens</span> of V.arcologies[0].name.`);
+			repX(-100, "event");
+			cashX(forceNeg(_price), "mercenaries");
+			V.mercenaries = 1;
+			if (V.secExpEnabled > 0) {
+				V.SecExp.units.mercs.free = 15;
+			}
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+
+		function platoon() {
+			const frag = new DocumentFragment();
+			let r = [];
+			r.push(`You hire a full platoon of reputable mercenaries with a veteran officer to command them, kit them in excellent gear, and quarter them in ${V.arcologies[0].name}. The sight of many armed men on patrol has <span class="red">deeply offended some of the more free-spirited citizens</span> of ${V.arcologies[0].name}.`);
+			repX(-500, "event");
+			cashX(forceNeg((_price * 2)), "mercenaries");
+			V.mercenaries = 3;
+			if (V.secExpEnabled > 0) {
+				V.SecExp.units.mercs.free = 30;
+			}
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+
+		function plead3rd() {
+			V.mercenaries = 0;
+			return `Having armed men on permanent watch is a step too far. ${V.arcologies[0].name}'s security systems are formidable and will have to serve.`;
+		}
+	}
+};
diff --git a/src/events/nonRandom/mercs/pMercenaries.tw b/src/events/nonRandom/mercs/pMercenaries.tw
deleted file mode 100644
index 93733b26a4cc460fa021bca2e21ca0524ac82771..0000000000000000000000000000000000000000
--- a/src/events/nonRandom/mercs/pMercenaries.tw
+++ /dev/null
@@ -1,55 +0,0 @@
-:: P mercenaries [nobr]
-
-<<set $nextButton = "Continue", $mercenaries = 0, $mercenariesTitle = "mercenaries">>
-
-<<if ($PC.skill.warfare >= 100)>>
-	<<set _price = 2500>>
-<<elseif ($PC.skill.warfare >= 50)>>
-	<<set _price = 3725>>
-<<else>>
-	<<set _price = 5000>>
-<</if>>
-
-Another wave of security hysteria is sweeping the Free Cities. And this time, it's not based on rumor and alarmism. On the other side of the globe, a Free City was sacked by an old world army today. The Free City's handful of high-technology defenders and multitude of drones caused heavy casualties among the attackers, but eventually sheer weight of numbers wore them down.
-
-<br><br>
-
-Your Free City is on good terms with the nations that border it, unlike the unfortunate sacked city, which was next to a nation suffering total collapse and looking for a convenient target. However, there's no telling how long this will last. The situation in the small, troubled country close to the arcology you've been monitoring grows worse by the day<<if $nationHate > 0>>, and if rumor of your enslavement of some of their vulnerable citizens got out, its people may have cause to hate you.<</if>>
-
-<br><br>
-
-The budgetary difficulty many old world countries are in has resulted in unemployed soldiers looking for mercenary work. You could easily hire some of them to protect the arcology and fight in the militia if necessary. ''This is a unique opportunity.'' Without this security scare, it's unlikely you could convince any of your free-spirited tenants to even stay near a permanent armed presence.
-
-<br><br>
-
-<span id="result">
-/* the ordering here is bothering me - I feel like it should go from greatest to least */
-<<link "Quarter a squad in the arcology">>
-	<<replace "#result">>
-	You hire some reputable mercenaries, kit them in excellent gear, and quarter them in $arcologies[0].name. The sight of armed men on patrol has @@.red;offended some of the more free-spirited citizens@@ of $arcologies[0].name.
-	<<run repX(-100, "event")>>
-	<<run cashX(forceNeg(_price), "mercenaries")>>
-	<<set $mercenaries = 1>>
-	<<if ($secExpEnabled > 0)>>
-		<<set $SecExp.units.mercs.free = 15>>
-	<</if>>
-	<</replace>>
-<</link>> <<if ($PC.skill.warfare >= 50) || ($PC.career == "arcology owner")>>//This will cost <<print cashFormat(_price)>> and some upkeep, @@.springgreen;reduced by your mercenary contacts@@//<<else>>//This will cost <<print cashFormat(5000)>> and incur significant upkeep costs//<</if>>
-<br><<link "Install a full platoon">>
-	<<replace "#result">>
-	You hire a full platoon of reputable mercenaries with a veteran officer to command them, kit them in excellent gear, and quarter them in $arcologies[0].name. The sight of many armed men on patrol has @@.red;deeply offended some of the more free-spirited citizens@@ of $arcologies[0].name.
-	<<run repX(-500, "event")>>
-	<<run cashX(forceNeg((_price*2)), "mercenaries")>>
-	<<set $mercenaries = 3>>
-	<<if ($secExpEnabled > 0)>>
-		<<set $SecExp.units.mercs.free = 30>>
-	<</if>>
-	<</replace>>
-<</link>> <<if ($PC.skill.warfare >= 50) || ($PC.career == "arcology owner")>>//This will cost <<print cashFormat((_price*2))>> and some upkeep, @@.springgreen;reduced by your mercenary contacts@@//<<else>>//This will cost <<print cashFormat(10000)>> and incur significant upkeep costs//<</if>>
-<br><<link "Do not quarter troops in your arcology">>
-	<<replace "#result">>
-		Having armed men on permanent watch is a step too far. $arcologies[0].name's security systems are formidable and will have to serve.
-		<<set $mercenaries = 0>>
-	<</replace>>
-<</link>>
-</span>
diff --git a/src/events/nonRandom/mercs/pMercenaryRomeo.js b/src/events/nonRandom/mercs/pMercenaryRomeo.js
new file mode 100644
index 0000000000000000000000000000000000000000..0d08afcb97d2808ab086dc9639eb832046104861
--- /dev/null
+++ b/src/events/nonRandom/mercs/pMercenaryRomeo.js
@@ -0,0 +1,190 @@
+App.Events.PMercenaryRomeo = class PMercenaryRomeo extends App.Events.BaseEvent {
+	eventPrerequisites() {
+		return [
+			() => App.Events.effectiveWeek() >= 44,
+			() => V.mercenaries > 0,
+			() => V.mercRomeo !== 1,
+		];
+	}
+
+	execute(node) {
+		let r = [];
+		V.nextButton = "Continue";
+		V.nextLink = "Random Nonindividual Event";
+		/** @type {FC.Zeroable<string>} */
+		let name = 0;
+		let _slaveCost;
+		let juliet;
+
+		let _romeoSlaves = V.slaves.filter(function(s) { return s.fetish !== "mindbroken" && s.fuckdoll === 0 && ["serve in the club", "serve the public", "whore", "work in the brothel"].includes(s.assignment); });
+		if (_romeoSlaves.length === 0) {
+			_romeoSlaves = V.slaves.filter(function(s) { return (s.counter.publicUse > 0) && (s.newGamePlus === 0) && (s.relationship > -3) && !["be your Concubine", "serve in the master suite"].includes(s.assignment); });
+			if (_romeoSlaves.length === 0) {
+				name = setup.whiteAmericanSlaveNames.random();
+			} else {
+				juliet = _romeoSlaves.random();
+			}
+		} else {
+			juliet = _romeoSlaves.random();
+		}
+		if (juliet === undefined) {
+			name = setup.whiteAmericanSlaveNames.random();
+		}
+
+		if (name === 0) {
+			_slaveCost = slaveCost(juliet);
+			_slaveCost = (random(60, 70) * Math.trunc(_slaveCost / 100));
+			_slaveCost = 100 * Math.trunc(_slaveCost / 100);
+		}
+		const {
+			He, His,
+			he, his, him, girl
+		} = getPronouns(juliet ? juliet : {pronoun: App.Data.Pronouns.Kind.neutral});
+		const {
+			heU, hisU, himU, girlU
+		} = getNonlocalPronouns(V.seeDicks).appendSuffix("U");
+
+		r.push(`One of your mercenaries requests an interview. He's a worn, grey-haired tank of a man, made bulkier still by heavy ceramic plate armor and lots of ammunition and gear. The murderous submachine gun favored for city fighting looks like a toy in his hands. But as he sits at your invitation and accepts a`);
+		if (V.PC.refreshmentType === 1) {
+			r.push(`glass of ${V.PC.refreshment}`);
+		} else if (V.PC.refreshmentType === 2) {
+			r.push(`a plate of ${V.PC.refreshment}`);
+		} else if (V.PC.refreshmentType === 3) {
+			r.push(`line of ${V.PC.refreshment}`);
+		} else if (V.PC.refreshmentType === 4) {
+			r.push(`syringe of ${V.PC.refreshment}`);
+		} else if (V.PC.refreshmentType === 5) {
+			r.push(`pill of ${V.PC.refreshment}`);
+		} else if (V.PC.refreshmentType === 6) {
+			r.push(`tab of ${V.PC.refreshment}`);
+		} else {
+			r.push(V.PC.refreshment);
+		}
+		r.push(`proffered by an attentive slave ${girlU}, he seems almost bashful.`);
+
+		App.Events.addParagraph(node, r);
+		r = [];
+
+
+		r.push(`"${properTitle()}, I'll say this straight. I'd like to buy one of your slaves.`);
+		if (name !== 0) {
+			r.push(`I've been seeing ${name} a lot, and ${heU} makes the years sit a little lighter on me. I've scraped together what I can, and I can pay ${cashFormat(50000)}." It's a huge sum for a mercenary; it's probably his entire savings, but there is a slight problem; the slave he is looking for isn't one of yours. "Well then," he says in embarrassment, "Have to say this is a little awkward." He gives a fake cough, "You wouldn't happen to, you know, know who ${hisU} owner is?" You shake your head. A run in with a ${girlU} named ${name} isn't much to go by and it really isn't your problem. "Ah well, I'm sure I'll see ${himU} around again. Anyway, that was a fine victory the other day, ${properTitle()}; come down to the bar and join the boys and I. We'll buy you a drink. Devil knows, thanks to you we can afford to. Hell, maybe you'll even get to meet ${name} too, get to see just how much of a looker ${heU} is."`);
+		} else {
+			if (["serve in the club", "serve the public", "whore", "work in the brothel"].includes(juliet.assignment)) {
+				r.push(
+					`I've been seeing`,
+					App.UI.DOM.slaveDescriptionDialog(juliet),
+					`a lot, and ${he} makes the years sit a little lighter on me.`
+				);
+			} else {
+				r.push(
+					`I've seen`,
+					App.UI.DOM.slaveDescriptionDialog(juliet),
+					`here and there and I can't stop thinking about ${him}. I feel ${he}'d make the years sit a little lighter on me.`
+				);
+			}
+			r.push(`I've scraped together what I can, and I can pay ${cashFormat(_slaveCost)}." It's a decent price, probably a little less than you could get at auction. It's a huge sum for a mercenary; it's probably his entire savings. You ask what he would do with ${him}. "Well," he says, actually blushing, "I'd free ${him}. And marry ${him}, if ${he}'d have me."`);
+
+			App.Events.addParagraph(node, r);
+			const choices = [];
+			choices.push(new App.Events.Result(`Decline, and tell ${him} not to see him`, declineAndForbid));
+			choices.push(new App.Events.Result(`Politely decline`, declinePolitely));
+			choices.push(new App.Events.Result(`Accept`, accept));
+			choices.push(new App.Events.Result(`Give ${him} to him as a gift`, gift));
+
+			App.Events.addResponses(node, choices);
+
+			App.UI.DOM.appendNewElement("h3", node, `${His} records...`);
+			App.UI.DOM.appendNewElement("div", node, `${His} current task is to ${juliet.assignment}${(V.assignmentRecords[juliet.ID]) ? `, and before that to ${V.assignmentRecords[juliet.ID]}` : ""}.`, "indent");
+			node.append(slaveImpactLongTerm(juliet));
+		}
+		function declineAndForbid() {
+			const frag = new DocumentFragment();
+			let r = [];
+			r.push(`${juliet.slaveName} obeys your orders not to see the old mercenary.Though neither he or ${juliet.slaveName} says a word about it, his squadmates are not so closemouthed. Soon the tragic story of The Mercenary and the slave${girl} is being told in bars and brothels across the Free City, with you naturally playing <span class="reputation dec"> the role of the villain.</span>`);
+			repX(-1000, "event");
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+		function declinePolitely() {
+			const frag = new DocumentFragment();
+			let r = [];
+			r.push(`"Ah well," he says, "didn't think you would, but I had to ask. If you'd be so kind as to keep ${him} assigned so's I can see ${him}, I would be grateful. That was a fine victory, ${properTitle()}; come down to the bar and join the boys and I. We'll buy you a drink. Devil knows, thanks to you we can afford to."`);
+			if (juliet.relationship === -3 && juliet.fetish !== "mindbroken" && juliet.devotion + juliet.trust > 190) {
+				r.push(`${juliet.slaveName} politely thanks you for not letting him take ${him} away.`);
+			}
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+
+		function accept() {
+			const frag = new DocumentFragment();
+			let r = [];
+			r.push(`The mercenary leaves to collect his purchase. On the video feeds, you see that${juliet.slaveName} can hardly believe what's`);
+			if (juliet.relationship === -3 && juliet.fetish !== "mindbroken" && juliet.devotion + juliet.trust > 190) {
+				r.push(`happening. You can't hear what he says as he takes out a ring, but ${his} reaction speaks clearly. ${He} says "No."`);
+				if (canWalk(juliet) && hasAnyArms(juliet)) {
+					r.push(`${He} points back into your penthouse and returns to ${his} home.`);
+				} else {
+					r.push(`${He} gestures towards the nearest camera and he helps ${him} back into your penthouse.`);
+				}
+				r.push(`The only thing ${he} wants after being freed is to return to your side. "I thought I was giving ${him} a better life... But ${he} already had everything ${he} wanted. I'm sorry for putting you in such a position." You can hear the sadness in his voice. "Thank you for your time. I'm sorry to have bothered you." Since ${he} returned to slavery, it's only fair to return the credits he paid for ${him}. He thanks you hollowly before heading on his way.`);
+			} else {
+				r.push(`happened.`);
+				if (hasAnyArms(juliet) && hasBothLegs(juliet)) {
+					r.push(`${He} hugs him, sobbing into his shoulder. As they walk hand in hand down towards his quarters,`);
+				} else {
+					r.push(`As he`);
+					if (!isAmputee(juliet)) {
+						r.push(`gives`);
+					} else {
+						r.push(`picks up ${his} limbless form to give`);
+					}
+					r.push(`${him} a hug,`);
+				}
+				r.push(`${he} gives the nearest camera a little nod and silently mouths the words "Thank you, ${getWrittenTitle(juliet)}." Soon the romantic story of The Mercenary and the slave${girl} is being told in bars and brothels across the Free City, with you naturally playing <span class="reputation inc">a supporting role.</span>`);
+				// TODO: uh, actually increase rep?
+				cashX(_slaveCost, "slaveTransfer");
+				removeSlave(juliet);
+			}
+
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+
+		function gift() {
+			const frag = new DocumentFragment();
+			let r = [];
+			r.push(`The mercenary cannot believe his ears. After you repeat yourself twice, he leaves to collect your gift, thanking you clumsily. On the video feeds, you see that${juliet.slaveName} can hardly believe what's`);
+			if (juliet.relationship === -3 && juliet.fetish !== "mindbroken" && juliet.devotion + juliet.trust > 190) {
+				r.push(`happening. You can't hear what he says as he takes out a ring, but ${his} reaction speaks clearly. ${He} says "No."`);
+				if (canWalk(juliet) && hasAnyArms(juliet)) {
+					r.push(`${He} points back into your penthouse and returns to ${his} home.`);
+				} else {
+					r.push(`${He} gestures towards the nearest camera and he helps ${him} back into your penthouse.`);
+				}
+				r.push(`The only thing ${he} wants after being freed is to return to your side. "I thought I was giving ${him} a better life... But ${he} already had everything ${he} wanted. I'm sorry for putting you in such a position." You can hear the sadness in his voice. "Thank you for your time. I'm sorry to have bothered you."`);
+			} else {
+				r.push(`happened.`);
+				if (hasAnyArms(juliet) && hasAnyLegs(juliet)) {
+					r.push(`${He} hugs him, sobbing into his shoulder. As they walk hand in hand down towards his quarters,`);
+				} else {
+					r.push(`As he`);
+					if (!isAmputee(juliet)) {
+						r.push(`gives`);
+					} else {
+						r.push(`picks up ${his} limbless form to give`);
+					}
+					r.push(`${him} a hug,`);
+				}
+				r.push(`${he} gives the nearest camera a little nod and silently mouths the words "Thank you, ${getWrittenTitle(juliet)}." You smile to yourself; when they get there they'll find flowers and a paid reservation at the arcology's best restaurant. Soon the story is being told in bars and brothels across the Free City, with you naturally playing <span class="reputation inc">a starring role.</span> Some days later, you hear a dramatization is being filmed, with an aging action star playing the mercenary, a rising starlet playing ${juliet.slaveName}, and a noted character actor playing you.`);
+				repX(15000, "event");
+				V.trinkets.push(`a poster for the movie that was made about the love between one of your mercenaries and ${juliet.slaveName}`);
+				removeSlave(juliet);
+			}
+
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+	}
+};
diff --git a/src/events/nonRandom/mercs/pMercenaryRomeo.tw b/src/events/nonRandom/mercs/pMercenaryRomeo.tw
deleted file mode 100644
index 2d13a021be44b21263987b3f78e91cdbc9c50ad5..0000000000000000000000000000000000000000
--- a/src/events/nonRandom/mercs/pMercenaryRomeo.tw
+++ /dev/null
@@ -1,138 +0,0 @@
-:: P mercenary romeo [nobr]
-
-<<set $nextButton = "Continue", $nextLink = "Random Nonindividual Event", _name = 0>>
-
-<<set _romeoSlaves = $slaves.filter(function(s) { return s.fetish != "mindbroken" && s.fuckdoll == 0 && ["serve in the club", "serve the public", "whore", "work in the brothel"].includes(s.assignment); })>>
-<<if _romeoSlaves.length == 0>>
-	<<set _romeoSlaves = $slaves.filter(function(s) { return (s.counter.publicUse > 0) && (s.newGamePlus == 0) && (s.relationship > -3) && !["be your Concubine", "serve in the master suite"].includes(s.assignment); })>>
-	<<if _romeoSlaves.length == 0>>
-		<<set _name = setup.whiteAmericanSlaveNames.random()>>
-	<<else>>
-		<<set _juliet = _romeoSlaves.random()>>
-	<</if>>
-<<else>>
-	<<set _juliet = _romeoSlaves.random()>>
-<</if>>
-<<if ndef _juliet>>
-	<<set _name = setup.whiteAmericanSlaveNames.random()>>
-<</if>>
-
-<<if _name == 0>>
-	<<set _slaveCost = slaveCost(_juliet)>>
-	<<set _slaveCost = (random(60,70)*Math.trunc(_slaveCost/100))>>
-	<<set _slaveCost = 100*Math.trunc(_slaveCost/100)>>
-	<<setLocalPronouns _juliet>>
-<</if>>
-<<setNonlocalPronouns $seeDicks>>
-
-One of your mercenaries requests an interview. He's a worn, grey-haired tank of a man, made bulkier still by heavy ceramic plate armor and lots of ammunition and gear. The murderous submachine gun favored for city fighting looks like a toy in his hands. But as he sits at your invitation and accepts a
-<<if $PC.refreshmentType == 0>>
-	$PC.refreshment
-<<elseif $PC.refreshmentType == 1>>
-	glass of $PC.refreshment
-<<elseif $PC.refreshmentType == 2>>
-	a plate of $PC.refreshment
-<<elseif $PC.refreshmentType == 3>>
-	line of $PC.refreshment
-<<elseif $PC.refreshmentType == 4>>
-	syringe of $PC.refreshment
-<<elseif $PC.refreshmentType == 5>>
-	pill of $PC.refreshment
-<<elseif $PC.refreshmentType == 6>>
-	tab of $PC.refreshment
-<</if>>
-proffered by an attentive slave _girlU, he seems almost bashful.
-
-<br><br>
-
-"<<= properTitle()>>, I'll say this straight. I'd like to buy one of your slaves.
-<<if _name != 0>>
-	<<setNonlocalPronouns $seeDicks>>
-	I've been seeing _name a lot, and _heU makes the years sit a little lighter on me. I've scraped together what I can, and I can pay <<print cashFormat(50000)>>." It's a huge sum for a mercenary; it's probably his entire savings, but there is a slight problem; the slave he is looking for isn't one of yours. "Well then," he says in embarrassment, "Have to say this is a little awkward." He gives a fake cough, "You wouldn't happen to, you know, know who _hisU owner is?" You shake your head. A run in with a _girlU named _name isn't much to go by and it really isn't your problem. "Ah well, I'm sure I'll see _himU around again. Anyway, that was a fine victory the other day, <<= properTitle()>>; come down to the bar and join the boys and I. We'll buy you a drink. Devil knows, thanks to you we can afford to. Hell, maybe you'll even get to meet _name too, get to see just how much of a looker _heU is."
-<<else>>
-	<<if ["serve in the club", "serve the public", "whore", "work in the brothel"].includes(_juliet.assignment)>>
-		I've been seeing <<= App.UI.slaveDescriptionDialog(_juliet)>> a lot, and $he makes the years sit a little lighter on me.
-	<<else>>
-		I've seen <<= App.UI.slaveDescriptionDialog(_juliet)>> here and there and I can't stop thinking about $him. I feel $he'd make the years sit a little lighter on me.
-	<</if>>
-	I've scraped together what I can, and I can pay <<print cashFormat(_slaveCost)>>." It's a decent price, probably a little less than you could get at auction. It's a huge sum for a mercenary; it's probably his entire savings. You ask what he would do with $him. "Well," he says, actually blushing, "I'd free $him. And marry $him, if $he'd have me."
-
-	<br><br>
-
-	<span id="result">
-	<<link "Decline, and tell $him not to see him">>
-		<<replace "#result">>
-			_juliet.slaveName obeys your orders not to see the old mercenary. Though neither he or _juliet.slaveName says a word about it, his squadmates are not so closemouthed. Soon the tragic story of The Mercenary and the Slave $Girl is being told in bars and brothels across the Free City, with you naturally playing @@.red;the role of the villain.@@
-			<<run repX(-1000, "event")>>
-		<</replace>>
-	<</link>>
-	<br><<link "Politely decline">>
-		<<replace "#result">>
-			"Ah well," he says, "didn't think you would, but I had to ask. If you'd be so kind as to keep $him assigned so's I can see $him, I would be grateful. That was a fine victory, <<= properTitle()>>; come down to the bar and join the boys and I. We'll buy you a drink. Devil knows, thanks to you we can afford to."
-			<<if _juliet.relationship == -3 && _juliet.fetish != "mindbroken" && _juliet.devotion+_juliet.trust > 190>>_juliet.slaveName politely thanks you for not letting him take $him away.<</if>>
-		<</replace>>
-	<</link>>
-	<br><<link "Accept">>
-		<<replace "#result">>
-			The mercenary leaves to collect his purchase. On the video feeds, you see that _juliet.slaveName can hardly believe what's
-			<<if _juliet.relationship == -3 && _juliet.fetish != "mindbroken" && _juliet.devotion+_juliet.trust > 190>>
-				happening. You can't hear what he says as he takes out a ring, but $his reaction speaks clearly. $He says "No."
-				<<if canWalk(_juliet) && hasAnyArms(_juliet)>>
-					$He points back into your penthouse and returns to $his home.
-				<<else>>
-					$He gestures towards the nearest camera and he helps $him back into your penthouse.
-				<</if>>
-				The only thing $he wants after being freed is to return to your side.
-				"I thought I was giving $him a better life... But $he already had everything $he wanted. I'm sorry for putting you in such a position." You can hear the sadness in his voice. "Thank you for your time. I'm sorry to have bothered you."
-				Since $he returned to slavery, it's only fair to return the credits he paid for $him. He thanks you hollowly before heading on his way.
-			<<else>>
-				happened.
-				<<if hasAnyArms(_juliet) && hasBothLegs(_juliet)>>
-					$He hugs him, sobbing into his shoulder. As they walk hand in hand down towards his quarters,
-				<<else>>
-					As he <<if !isAmputee(_juliet)>>gives<<else>>picks up $his limbless form to give<</if>> $him a hug,
-				<</if>>
-				$he gives the nearest camera a little nod and silently mouths the words "Thank you, <<= getWrittenTitle(_juliet)>>." Soon the romantic story of The Mercenary and the Slave $Girl is being told in bars and brothels across the Free City, with you naturally playing @@.green;a supporting role.@@
-				<<run cashX(_slaveCost, "slaveTransfer")>>
-				<<run removeSlave(_juliet)>>
-			<</if>>
-		<</replace>>
-	<</link>>
-	<br><<link "Give $him to him as a gift">>
-		<<replace "#result">>
-			The mercenary cannot believe his ears. After you repeat yourself twice, he leaves to collect your gift, thanking you clumsily. On the video feeds, you see that _juliet.slaveName can hardly believe what's
-			<<if _juliet.relationship == -3 && _juliet.fetish != "mindbroken" && _juliet.devotion+_juliet.trust > 190>>
-				happening. You can't hear what he says as he takes out a ring, but $his reaction speaks clearly. $He says "No."
-				<<if canWalk(_juliet) && hasAnyArms(_juliet)>>
-					$He points back into your penthouse and returns to $his home.
-				<<else>>
-					$He gestures towards the nearest camera and he helps $him back into your penthouse.
-				<</if>>
-				The only thing $he wants after being freed is to return to your side.
-				"I thought I was giving $him a better life... But $he already had everything $he wanted. I'm sorry for putting you in such a position." You can hear the sadness in his voice. "Thank you for your time. I'm sorry to have bothered you."
-			<<else>>
-				happened.
-				<<if hasAnyArms(_juliet) && hasAnyLegs(_juliet)>>
-					$He hugs him, sobbing into his shoulder. As they walk hand in hand down towards his quarters,
-				<<else>>
-					As he <<if !isAmputee(_juliet)>>gives<<else>>picks up $his limbless form to give<</if>> $him a hug,
-				<</if>>
-				$he gives the nearest camera a little nod and silently mouths the words "Thank you, <<= getWrittenTitle(_juliet)>>." You smile to yourself; when they get there they'll find flowers and a paid reservation at the arcology's best restaurant. Soon the story is being told in bars and brothels across the Free City, with you naturally playing @@.green;a starring role.@@ Some days later, you hear a dramatization is being filmed, with an aging action star playing the mercenary, a rising starlet playing _juliet.slaveName, and a noted character actor playing you.
-				<<run repX(15000, "event")>>
-				<<set _poster = "a poster for the movie that was made about the love between one of your mercenaries and " + _juliet.slaveName>>
-				<<set $trinkets.push(_poster)>>
-				<<run removeSlave(_juliet)>>
-			<</if>>
-		<</replace>>
-	<</link>>
-	</span>
-
-	<h3>$His records...</h3>
-	<div class="note">
-		<div class="indent">
-			$His current task is to <<print _juliet.assignment>><<if $assignmentRecords[_juliet.ID]>>, and before that to <<print $assignmentRecords[_juliet.ID]>><</if>>.
-		</div>
-		<<includeDOM slaveImpactLongTerm(_juliet)>>
-	</div>
-
-<</if>>
diff --git a/src/events/nonRandom/mercs/pMercsHelpCorp.js b/src/events/nonRandom/mercs/pMercsHelpCorp.js
new file mode 100644
index 0000000000000000000000000000000000000000..c7e4f1cf6d3810dc79bb533833ee3dfa3846fbc9
--- /dev/null
+++ b/src/events/nonRandom/mercs/pMercsHelpCorp.js
@@ -0,0 +1,91 @@
+App.Events.PMercsHelpCorp = class PMercsHelpCorp extends App.Events.BaseEvent {
+	eventPrerequisites() {
+		return [
+			() => V.corp.Incorporated > 0,
+			() => V.rivalOwnerEnslaved > 0,
+			() => V.mercenaries >= 3,
+			() => V.mercenariesHelpCorp === 0,
+			() => V.corp.DivExtra > 0,
+			() => App.Events.effectiveWeek() > 70,
+		];
+	}
+
+	execute(node) {
+		let r = [];
+		V.nextButton = "Decline"; /* hide button until user makes a selection */
+		V.nextLink = "Random Nonindividual Event";
+		V.mercenariesHelpCorp = -1;
+
+		r.push(`Your weekly meeting with your V.mercenariesTitle commander finishes with unusual speed. With the arcology owner who set the Daughters on you enslaved, all other immediate threats defused or smashed,`);
+		if (V.arcologies[0].FSRomanRevivalistLaw > 0) {
+			r.push(`your citizens serving in the urban cohorts with enthusiasm,`);
+		}
+		if (V.arcologies[0].FSNeoImperialistLaw1 > 0) {
+			r.push(`your Knights vigilantly watching the streets for any possible threat,`);
+		}
+		r.push(`and the ${V.mercenariesTitle} in excellent fighting condition, there just weren't enough concerns from either of your perspectives to fill the time. You sit across your desk from each other, discussing the global situation over V.PC.refreshment.`);
+
+		App.Events.addParagraph(node, r);
+		r = [];
+
+
+		r.push(`"You know, ${properTitle()}," the scarred man says thoughtfully. "Threat board's pretty sparse these days. I mean, not for those poor bastards." He`);
+		if (V.PC.refreshmentType === 0) {
+			r.push(`waves his ${V.PC.refreshment}`);
+		} else if (V.PC.refreshmentType === 1) {
+			r.push(`uses his glass to point`);
+		} else if (V.PC.refreshmentType === 2) {
+			r.push(`points a piece of ${V.PC.refreshment}`);
+		} else if (V.PC.refreshmentType === 3) {
+			r.push(`finishes arranging a line before pointing`);
+		} else if (V.PC.refreshmentType === 4) {
+			r.push(`using his syringe to point`);
+		} else if (V.PC.refreshmentType === 5) {
+			r.push(`shaking the bottle of ${V.PC.refreshment}`);
+		} else if (V.PC.refreshmentType === 6) {
+			r.push(`using the sheet of ${V.PC.refreshment} to point`);
+		}
+		r.push(`at a screen showing a live news feed from a war on the other side of the world. A huge cloud in an unmistakable, malevolent shape, a broad rising head atop a dirty column of vapor, is towering above a large city.`);
+
+		App.Events.addParagraph(node, r);
+		r = [];
+
+		r.push(`"But in our immediate area, there's just not much that can threaten us. Most trouble on the horizon's going to come from economics and supply and the climate, but that stuff doesn't shoot back. I think we can afford a little dispersal of military effort. Why don't I second squads to your corporation, when we've got the availability? Your corporate guys are already pulling meat out of the conflict zones. No offense to them, they're pretty good, but they're not quite at the level of my boys and girls. And don't worry, I'd keep 'em clear of shit like that." He indicates the on-screen mushroom cloud again.`);
+
+		App.Events.addParagraph(node, r);
+		r = [];
+
+		r.push(
+			App.UI.DOM.makeElement("span", "This is a unique opportunity", "bold"),
+			`and will not reoccur.`
+		);
+		App.Events.addParagraph(node, r);
+
+		App.Events.addResponses(node, [
+			new App.Events.Result(`Decline`, decline),
+			new App.Events.Result(`Make it so`, makeItSo)
+		]);
+
+		function decline() {
+			const frag = new DocumentFragment();
+			let r = [];
+			r.push(`Best to keep the ${V.mercenariesTitle} in reserve. You decline, and the commander chuckles. "Well ${properTitle()} , if you insist, I suppose we could find ways to keep busy around the arcology. I mean, we're a little starved for`);
+			if (V.seeDicks !== 0) {
+				r.push(`female`);
+			} else {
+				r.push(`intimate`);
+			}
+			r.push(`company here, but we can make do."`);
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+
+		function makeItSo() {
+			V.nextButton = "Continue";
+			App.Utils.updateUserButton();
+			const {girlU, heU} = getNonlocalPronouns(V.seeDicks).appendSuffix("U");
+			V.mercenariesHelpCorp = 1;
+			return `It's a fine idea, and you agree. The commander looks so enthused that you feel obliged to ask that he not risk himself unduly. He laughs. "There are no old, bold mercs, ${properTitle()}, and I am sure as hell old. I'll be sure to grow even older under contract with you. Now, unless there's anything else, I've just bought a nice ${girlU} to add to the commander's suite, and ${heU} makes me feel a bit younger."`;
+		}
+	}
+};
diff --git a/src/events/nonRandom/mercs/pMercsHelpCorp.tw b/src/events/nonRandom/mercs/pMercsHelpCorp.tw
deleted file mode 100644
index fd44127bd355b7b16b398293a79b8ee5e162b2bc..0000000000000000000000000000000000000000
--- a/src/events/nonRandom/mercs/pMercsHelpCorp.tw
+++ /dev/null
@@ -1,35 +0,0 @@
-:: P Mercs Help Corp [nobr]
-
-<<set $nextButton = "Decline", $nextLink = "Random Nonindividual Event", $mercenariesHelpCorp = -1>> /* hide button until user makes a selection */
-
-Your weekly meeting with your $mercenariesTitle commander finishes with unusual speed. With the arcology owner who set the Daughters on you enslaved, all other immediate threats defused or smashed,<<if $arcologies[0].FSRomanRevivalistLaw > 0>> your citizens serving in the urban cohorts with enthusiasm,<</if>><<if $arcologies[0].FSNeoImperialistLaw1 > 0>> your Knights vigilantly watching the streets for any possible threat,<</if>> and the $mercenariesTitle in excellent fighting condition, there just weren't enough concerns from either of your perspectives to fill the time. You sit across your desk from each other, discussing the global situation over $PC.refreshment.
-
-<br><br>
-
-"You know, <<= properTitle()>>," the scarred man says thoughtfully. "Threat board's pretty sparse these days. I mean, not for those poor bastards." He <<if $PC.refreshmentType == 0>>waves his $PC.refreshment<<elseif $PC.refreshmentType == 1>>uses his glass to point<<elseif $PC.refreshmentType == 2>>points a piece of $PC.refreshment<<elseif $PC.refreshmentType == 3>>finishes arranging a line before pointing<<elseif $PC.refreshmentType == 4>>using his syringe to point<<elseif $PC.refreshmentType == 5>>shaking the bottle of $PC.refreshment<<elseif $PC.refreshmentType == 6>>using the sheet of $PC.refreshment to point<</if>> at a screen showing a live news feed from a war on the other side of the world. A huge cloud in an unmistakable, malevolent shape, a broad rising head atop a dirty column of vapor, is towering above a large city.
-
-<br><br>
-
-"But in our immediate area, there's just not much that can threaten us. Most trouble on the horizon's going to come from economics and supply and the climate, but that stuff doesn't shoot back. I think we can afford a little dispersal of military effort. Why don't I second squads to your corporation, when we've got the availability? Your corporate guys are already pulling meat out of the conflict zones. No offense to them, they're pretty good, but they're not quite at the level of my boys and girls. And don't worry, I'd keep 'em clear of shit like that." He indicates the on-screen mushroom cloud again.
-
-<br><br>
-
-''This is a unique opportunity'' and will not reoccur.
-
-<br><br>
-
-<span id="result">
-<<link "Decline">>
-	<<replace "#result">>
-	Best to keep the $mercenariesTitle in reserve. You decline, and the commander chuckles. "Well <<= properTitle()>>, if you insist, I suppose we could find ways to keep busy around the arcology. I mean, we're a little starved for <<if $seeDicks != 0>>female<<else>>intimate<</if>> company here, but we can make do."
-	<</replace>>
-<</link>>
-<br><<link "Make it so">>
-	<<set $nextButton = "Continue">><<run App.Utils.updateUserButton()>>
-	<<replace "#result">>
-	<<setNonlocalPronouns $seeDicks>>
-	It's a fine idea, and you agree. The commander looks so enthused that you feel obliged to ask that he not risk himself unduly. He laughs. "There are no old, bold mercs, <<= properTitle()>>, and I am sure as hell old. I'll be sure to grow even older under contract with you. Now, unless there's anything else, I've just bought a nice _girlU to add to the commander's suite, and _heU makes me feel a bit younger."
-	<<set $mercenariesHelpCorp = 1>>
-	<</replace>>
-<</link>>
-</span>
diff --git a/src/events/nonRandom/mercs/pRaidInvitation.js b/src/events/nonRandom/mercs/pRaidInvitation.js
new file mode 100644
index 0000000000000000000000000000000000000000..f5a5ff4ced2b57af4683e4bd40a0db138cfcd9d5
--- /dev/null
+++ b/src/events/nonRandom/mercs/pRaidInvitation.js
@@ -0,0 +1,61 @@
+App.Events.PRaidInvitation = class PRaidInvitation extends App.Events.BaseEvent {
+	eventPrerequisites() {
+		return [
+			() => V.mercenaries === 0
+		];
+	}
+
+	execute(node) {
+		V.nextButton = "Continue";
+
+		V.eventResults.raid = 0;
+		V.eventResults.raidTarget = 0;
+		App.Events.addParagraph(node, [
+			`The former country whose citizens launched the ultimately futile attack on the arcology has continued to degenerate. After a series of civil disturbances and minor natural disasters, the nearest major city is being abandoned by its few remaining residents. A regional warlord is threatening the area, so they are streaming in small parties towards another city that is not yet under his shadow.`
+		]);
+
+		App.Events.addParagraph(node, [
+			`The citizens of ${V.arcologies[0].name} view their discomfiture without much pity. These people almost certainly would have abused them just as much as they are now in danger of being abused themselves, had the attack on the Free City been a success. There would be little to no criticism if you and your mercenary contingent were to take this unique opportunity to corral one of the refugee groups. They are refugees, after all; no one will miss them.`
+		]);
+
+		const raidCost = 5000;
+		App.Events.addParagraph(node, [`Fund a quick raid on the refugees with ${cashFormat(raidCost)}, targeting:`]);
+
+		const choices = [];
+		if (V.cash > raidCost) {
+			choices.push(new App.Events.Result(`Ex-soldiers`, exSoldiers));
+			choices.push(new App.Events.Result(`Healthy civilians`, healthyCiv));
+			choices.push(new App.Events.Result(`The largest possible group of slaves`, slaveDotMax));
+		} else {
+			choices.push(new App.Events.Result(null, null, `You can't even afford ${cashFormat(raidCost)}`));
+		}
+		choices.push(new App.Events.Result(`Or, just let them go`, free));
+		App.Events.addResponses(node, choices);
+
+		function exSoldiers() {
+			cashX(-raidCost, "war");
+			V.eventResults.raid = 1;
+			V.eventResults.raidTarget = 1;
+			return `Your mercenaries probably would have been enthusiastic even before the recent combat, but now they're positively eager. The split agreed upon is that they keep the proceeds from the sale of anything that isn't sex slave material, while you keep anything that is.`;
+		}
+
+		function healthyCiv() {
+			cashX(-raidCost, "war");
+			V.eventResults.raid = 1;
+			V.eventResults.raidTarget = 2;
+			return `Your mercenaries probably would have been enthusiastic even before the recent combat, but now they're positively eager. The split agreed upon is that they keep the proceeds from the sale of anything that isn't sex slave material, while you keep anything that is.`;
+		}
+
+		function slaveDotMax() {
+			cashX(-raidCost, "war");
+			V.eventResults.raid = 1;
+			V.eventResults.raidTarget = 3;
+			return `Your mercenaries probably would have been enthusiastic even before the recent combat, but now they're positively eager. The split agreed upon is that they keep the proceeds from the sale of anything that isn't sex slave material, while you keep anything that is.`;
+		}
+
+		function free() {
+			return `Some of the refugees make it to safety. Some do not.`;
+		}
+	}
+};
+
diff --git a/src/events/nonRandom/mercs/pRaidInvitation.tw b/src/events/nonRandom/mercs/pRaidInvitation.tw
deleted file mode 100644
index df14811aef9d73760dc997a0916f3f9531225c99..0000000000000000000000000000000000000000
--- a/src/events/nonRandom/mercs/pRaidInvitation.tw
+++ /dev/null
@@ -1,43 +0,0 @@
-:: P raid invitation [nobr]
-
-<<set $nextButton = "Continue">>
-
-<<set $eventResults.raid = 0, $eventResults.raidTarget = 0>>
-
-The former country whose citizens launched the ultimately futile attack on the arcology has continued to degenerate. After a series of civil disturbances and minor natural disasters, the nearest major city is being abandoned by its few remaining residents. A regional warlord is threatening the area, so they are streaming in small parties towards another city that is not yet under his shadow.
-<br><br>
-The citizens of $arcologies[0].name view their discomfiture without much pity. These people almost certainly would have abused them just as much as they are now in danger of being abused themselves, had the attack on the Free City been a success. There would be little to no criticism if you and your mercenary contingent were to take this unique opportunity to corral one of the refugee groups. They are refugees, after all; no one will miss them.
-<br><br>
-<span id="result">
-Fund a quick raid on the refugees with <<print cashFormat(5000)>>, targeting:
-<br>&nbsp;&nbsp;&nbsp;&nbsp;<<link "Ex-soldiers">>
-	<<replace "#result">>
-	Your mercenaries probably would have been enthusiastic even before the recent combat, but now they're positively eager. The split agreed upon is that they keep the proceeds from the sale of anything that isn't sex slave material, while you keep anything that is.
-	<<run cashX(-5000, "war")>>
-	<<set $eventResults.raid = 1>>
-	<<set $eventResults.raidTarget = 1>>
-	<</replace>>
-<</link>>
-<br>&nbsp;&nbsp;&nbsp;&nbsp;<<link "Healthy civilians">>
-	<<replace "#result">>
-	Your mercenaries probably would have been enthusiastic even before the recent combat, but now they're positively eager. The split agreed upon is that they keep the proceeds from the sale of anything that isn't sex slave material, while you keep anything that is.
-	<<run cashX(-5000, "war")>>
-	<<set $eventResults.raid = 1>>
-	<<set $eventResults.raidTarget = 2>>
-	<</replace>>
-<</link>>
-<br>&nbsp;&nbsp;&nbsp;&nbsp;<<link "The largest possible group of slaves">>
-	<<replace "#result">>
-	Your mercenaries probably would have been enthusiastic even before the recent combat, but now they're positively eager. The split agreed upon is that they keep the proceeds from the sale of anything that isn't sex slave material, while you keep anything that is.
-	<<run cashX(-5000, "war")>>
-	<<set $eventResults.raid = 1>>
-	<<set $eventResults.raidTarget = 3>>
-	<</replace>>
-<</link>>
-<br>Or, simply:
-<br>&nbsp;&nbsp;&nbsp;&nbsp;<<link "Let them go">>
-	<<replace "#result">>
-	Some of the refugees make it to safety. Some do not.
-	<</replace>>
-<</link>>
-</span>
diff --git a/src/events/nonRandom/mercs/pRaidResult.js b/src/events/nonRandom/mercs/pRaidResult.js
new file mode 100644
index 0000000000000000000000000000000000000000..a0503b03e76be7a7f8ba38527b0c0c845f3b8070
--- /dev/null
+++ b/src/events/nonRandom/mercs/pRaidResult.js
@@ -0,0 +1,95 @@
+App.Events.PRaidResult = class PRaidResult extends App.Events.BaseEvent {
+	eventPrerequisites() {
+		return [
+			() => V.eventResults.raid === 1,
+		];
+	}
+
+	execute(node) {
+		let r = [];
+
+		V.nextButton = "Continue";
+		V.nextLink = "Random Nonindividual Event";
+
+		V.eventResults.raid = 0;
+		App.Events.addParagraph(node, [`As your VTOL craft carries you and your mercenaries out towards an area ideal for a quick raid on the refugee bands, the sensors begin to reveal that there are actually many more bands than you originally suspected. The single aircraft does not carry enough mercenaries to target more than one group, or have the cargo capacity to haul more than one back to the arcology before they disperse. Your mercenary commander makes a selection based on your instructions.`]);
+
+		App.Events.addParagraph(node, [`Out ahead of the main body of refugees there is a small knot moving quickly and in good order, carrying weapons. Farther back, there is a larger group separated from the main body who could be easily isolated. And finally, it seems a group of sick and injured refugees have clustered around a tent where there must be medical assistance of some kind.`]);
+
+		const _newSlaves = [];
+		if (V.eventResults.raidTarget === 1) {
+			r.push(`Under orders to target resistance, your mercenaries target the leading group. They even manage to direct a little small arms fire at the VTOL craft as it circles them, dropping mercenaries and plying its nonlethal weapons, but they are of course rapidly defeated. Your share is two slaves in good physical condition, who prove to have been survivors of the defeated attack on the arcology. The mercenaries find after a data search that one of the prisoners whose part of their share was a minor leader in the anti-Free Cities movement. After a quick consultation over their radios, the mercenaries decide that a summary execution out here would be too quick for the wretch, and bring their prize back to the arcology for more thorough punishment. Between the successful raid and the capture of this public enemy, <span class="green">the citizens are quite impressed by you.</span>`);
+			repX(2500, "event");
+			for (let _prr = 0; _prr < 3; _prr++) {
+				if (V.seeDicks > 0) {
+					const _slave = GenerateNewSlave("XY");
+					_slave.origin = "${He} is an enslaved refugee who participated in the defeated attack on your arcology.";
+					_newSlaves.push(_slave);
+				} else {
+					const _slave = GenerateNewSlave("XX");
+					_slave.origin = "${He} is an enslaved refugee who participated in the defeated attack on your arcology.";
+					_newSlaves.push(_slave);
+				}
+			}
+		} else if (V.eventResults.raidTarget === 2) {
+			r.push(`Under orders to target civilians, your mercenaries head for the isolated group. When the VTOL descends to circle around the large group of refugees, it becomes obvious that it won't even be necessary to expend nonlethal ammunition. A few of the refugees throw themselves down in bitterness, but most just subside into the catatonia of helplessness. They stand quiescent as they are searched, tagged, and loaded onto the VTOL like the wretched human refuse they are. The successful raid <span class="green">is the talk of the Free City.</span>`);
+			repX(1000, "event");
+			for (let _prr = 0; _prr < 4; _prr++) {
+				const _slave = GenerateNewSlave();
+				_slave.origin = "$He is an enslaved refugee.";
+				_newSlaves.push(_slave);
+			}
+		} else {
+			const {
+				heU, hisU, himU
+			} = getNonlocalPronouns(V.seeDicks === 100 ? 100 : 0).appendSuffix("U"); /* nurse gender is female unless seeDicks is 100 */
+			r.push(`Under orders to target the largest possible group of people, your mercenaries head for the sick and injured. As the VTOL settles, it becomes apparent that most of the injuries are from combat, almost certainly in the defeat at ${V.arcologies[0].name}. The tent proves to contain a harassed nurse, almost without medical supplies and at the end of ${hisU} rope. When ${heU} sees the mercenaries push through the tent flap, ${heU} heaves a sigh of mixed defeat and relief and wordlessly offers ${hisU} wrists. The mercenaries give you a larger share of the other slaves in return for ${himU}: they tell you in confidence that ${heU}'ll be a medical asset to them as well as the usual amusement. The successful raid <span class="green">is the talk of the Free City.</span>`);
+			V.eventResults.slaveMedic = 1;
+			repX(1000, "event");
+			for (let _prr = 0; _prr < 5; _prr++) {
+				const _slave = GenerateNewSlave();
+				_slave.origin = "$He is an enslaved refugee who was wounded in the defeated attack on your arcology.";
+				setHealth(_slave, jsRandom(-50, 40), normalRandInt(20, 3), normalRandInt(15, 3), Math.max(normalRandInt(0, 1), 0), jsRandom(40, 80));
+				_newSlaves.push(_slave);
+			}
+		}
+		App.Events.addParagraph(node, r);
+
+		const choices = [];
+		choices.push(new App.Events.Result(`Sell your prisoners immediately`, sell));
+		choices.push(new App.Events.Result(`Give your prisoners to citizens injured in the recent invasion`, give));
+		choices.push(new App.Events.Result(`Enslave all of the refugees`, enslave));
+		App.Events.addResponses(node, choices);
+
+		function sell() {
+			for (const slave of _newSlaves) {
+				const _slaveCost = slaveCost(slave);
+				cashX(_slaveCost, "slaveTransfer");
+			}
+			return `Prisoners sold.`;
+		}
+
+		function give() {
+			const frag = new DocumentFragment();
+			let r = [];
+			for (const slave of _newSlaves) {
+				const _slaveCost = slaveCost(slave);
+				repX(Math.trunc(_slaveCost / 10), "event");
+			}
+			r.push(`Prisoners <span class= "reputation inc"> given away.</span>`);
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+
+		function enslave() {
+			const frag = new DocumentFragment();
+			let r = [];
+			for (const slave of _newSlaves) {
+				newSlave(slave);
+			}
+			r.push(`You simply enslave all of the refugees yourself. They would have been worse off had you not intervened.`);
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+	}
+};
diff --git a/src/events/nonRandom/mercs/pRaidResult.tw b/src/events/nonRandom/mercs/pRaidResult.tw
deleted file mode 100644
index 715eb8b8b747af6b90b851500672d506bfbcfba0..0000000000000000000000000000000000000000
--- a/src/events/nonRandom/mercs/pRaidResult.tw
+++ /dev/null
@@ -1,77 +0,0 @@
-:: P raid result [nobr]
-
-<<set $nextButton = "Continue", $nextLink = "Random Nonindividual Event">>
-
-<<set $eventResults.raid = 0>>
-
-As your VTOL craft carries you and your mercenaries out towards an area ideal for a quick raid on the refugee bands, the sensors begin to reveal that there are actually many more bands than you originally suspected. The single aircraft does not carry enough mercenaries to target more than one group, or have the cargo capacity to haul more than one back to the arcology before they disperse. Your mercenary commander makes a selection based on your instructions.
-<br><br>
-Out ahead of the main body of refugees there is a small knot moving quickly and in good order, carrying weapons. Farther back, there is a larger group separated from the main body who could be easily isolated. And finally, it seems a group of sick and injured refugees have clustered around a tent where there must be medical assistance of some kind.
-<br><br>
-
-<<set _newSlaves = []>>
-<<if $eventResults.raidTarget == 1>>
-	Under orders to target resistance, your mercenaries target the leading group. They even manage to direct a little small arms fire at the VTOL craft as it circles them, dropping mercenaries and plying its nonlethal weapons, but they are of course rapidly defeated. Your share is two slaves in good physical condition, who prove to have been survivors of the defeated attack on the arcology. The mercenaries find after a data search that one of the prisoners whose part of their share was a minor leader in the anti-Free Cities movement. After a quick consultation over their radios, the mercenaries decide that a summary execution out here would be too quick for the wretch, and bring their prize back to the arcology for more thorough punishment. Between the successful raid and the capture of this public enemy, @@.green;the citizens are quite impressed by you.@@
-	<<run repX(2500, "event")>>
-	<<for _prr = 0; _prr < 3; _prr++>>
-		<<if ($seeDicks > 0)>>
-			<<set _slave = GenerateNewSlave("XY")>>
-			<<set _slave.origin = "$He is an enslaved refugee who participated in the defeated attack on your arcology.">>
-			<<set _newSlaves.push(_slave)>>
-		<<else>>
-			<<set _slave = GenerateNewSlave("XX")>>
-			<<set _slave.origin = "$He is an enslaved refugee who participated in the defeated attack on your arcology.">>
-			<<set _newSlaves.push(_slave)>>
-		<</if>>
-	<</for>>
-<<elseif $eventResults.raidTarget == 2>>
-	Under orders to target civilians, your mercenaries head for the isolated group. When the VTOL descends to circle around the large group of refugees, it becomes obvious that it won't even be necessary to expend nonlethal ammunition. A few of the refugees throw themselves down in bitterness, but most just subside into the catatonia of helplessness. They stand quiescent as they are searched, tagged, and loaded onto the VTOL like the wretched human refuse they are. The successful raid @@.green;is the talk of the Free City.@@
-	<<run repX(1000, "event")>>
-	<<for _prr = 0; _prr < 4; _prr++>>
-		<<set _slave = GenerateNewSlave()>>
-		<<set _slave.origin = "$He is an enslaved refugee.">>
-		<<set _newSlaves.push(_slave)>>
-	<</for>>
-<<else>>
-	<<set _nurseGender = $seeDicks == 100 ? 100 : 0>> /* nurse gender is female unless seeDicks is 100 */
-	<<setNonlocalPronouns $seeDicks>>
-	Under orders to target the largest possible group of people, your mercenaries head for the sick and injured. As the VTOL settles, it becomes apparent that most of the injuries are from combat, almost certainly in the defeat at $arcologies[0].name. The tent proves to contain a harassed nurse, almost without medical supplies and at the end of _hisU rope. When _heU sees the mercenaries push through the tent flap, _heU heaves a sigh of mixed defeat and relief and wordlessly offers _hisU wrists. The mercenaries give you a larger share of the other slaves in return for _himU: they tell you in confidence that _heU'll be a medical asset to them as well as the usual amusement. The successful raid @@.green;is the talk of the Free City.@@
-	<<set $eventResults.slaveMedic = 1>>
-	<<run repX(1000, "event")>>
-	<<for _prr = 0; _prr < 5; _prr++>>
-		<<set _slave = GenerateNewSlave()>>
-		<<set _slave.origin = "$He is an enslaved refugee who was wounded in the defeated attack on your arcology.">>
-		<<run setHealth(_slave, jsRandom(-50, 40), normalRandInt(20, 3), normalRandInt(15, 3), Math.max(normalRandInt(0, 1), 0), jsRandom(40, 80))>>
-		<<set _newSlaves.push(_slave)>>
-	<</for>>
-<</if>>
-<br><br>
-
-<span id="result">
-<<link "Sell your prisoners immediately">>
-	<<replace "#result">>
-	<<for _prr = 0; _prr < _newSlaves.length; _prr++>>
-		<<set _slaveCost = slaveCost(_newSlaves[_prr])>>
-		<<run cashX(_slaveCost, "slaveTransfer")>>
-	<</for>>
-	Prisoners sold.
-	<</replace>>
-<</link>>
-<br><<link "Give your prisoners to citizens injured in the recent invasion">>
-	<<replace "#result">>
-	<<for _prr = 0; _prr < _newSlaves.length; _prr++>>
-		<<set _slaveCost = slaveCost(_newSlaves[_prr])>>
-		<<run repX(Math.trunc(_slaveCost/10), "event")>>
-	<</for>>
-	Prisoners @@.green;given away.@@
-	<</replace>>
-<</link>>
-<br><<link "Enslave all of the refugees">>
-	<<replace "#result">>
-	<<for _prr = 0; _prr < _newSlaves.length; _prr++>>
-		<<run newSlave(_newSlaves[_prr])>> /* skip New Slave Intro */
-	<</for>>
-	You simply enslave all of the refugees yourself. They would have been worse off had you not intervened.
-	<</replace>>
-<</link>>
-</span>
\ No newline at end of file
diff --git a/src/events/nonRandom/mercs/pSlaveMedic.js b/src/events/nonRandom/mercs/pSlaveMedic.js
new file mode 100644
index 0000000000000000000000000000000000000000..0ee83b1e92b2960b4b1fe05ba12153cdcf827cb7
--- /dev/null
+++ b/src/events/nonRandom/mercs/pSlaveMedic.js
@@ -0,0 +1,152 @@
+App.Events.PSlaveMedic = class PSlaveMedic extends App.Events.BaseEvent {
+	eventPrerequisites() {
+		return [
+			() => V.eventResults.slaveMedic > 0
+		];
+	}
+
+	execute(node) {
+		let r = [];
+
+		V.nextButton = "Continue";
+		V.nextLink = "Random Nonindividual Event";
+
+		V.eventResults.slaveMedic = 0;
+
+		const minAge = (V.pedo_mode === 1) ? V.minimumSlaveAge : 18;
+		const maxAge = (V.pedo_mode === 1) ? 25 : 42;
+
+		const genParam = {minAge: minAge, maxAge: maxAge, disableDisability: 1};
+		let slave;
+		if (V.seeDicks >= 100) {
+			slave = GenerateNewSlave("XY", genParam);
+			slave.dick = 5;
+			slave.foreskin = 0;
+			slave.balls = 3;
+			slave.scrotum = 3;
+			slave.butt = 3;
+			slave.attrXY = 70;
+		} else {
+			slave = GenerateNewSlave("XX", genParam);
+			slave.vagina = 2;
+			slave.preg = -1;
+			slave.ovaries = 1;
+			slave.skill.vaginal = 35;
+		}
+		if (V.pedo_mode === 1) {
+			slave.sexualQuirk = "caring";
+			slave.intelligenceImplant = 15;
+			if (slave.physicalAge >= 12) {
+				slave.teeth = "cosmetic braces";
+			}
+			if (V.seeDicks < 100) {
+				slave.hips = 1;
+				slave.boobs = 2000;
+				slave.boobShape = "perky";
+				slave.geneticQuirks.macromastia = 2;
+				slave.butt = 4;
+				slave.voice = 3;
+			} else {
+				slave.geneticQuirks.wellHung = 2;
+			}
+		} else {
+			slave.anusTat = "bleached";
+			slave.height = random(165, 190);
+			slave.intelligenceImplant = 30;
+			slave.teeth = "normal";
+			if (V.seeDicks < 100) {
+				slave.boobs += 400;
+				slave.butt += 1;
+				slave.stampTat = either("flowers", "tribal patterns");
+			}
+		}
+		slave.origin = "$He was captured while caring for those injured in a failed attack on the Free City.";
+		slave.career = "a nurse";
+		slave.custom.desc = "$He has a faint air of fatigue about $him, and strength too: that of a survivor.";
+		slave.sexualFlaw = "none";
+		slave.behavioralFlaw = "none";
+		slave.devotion = random(30, 40);
+		slave.trust = slave.devotion - 20;
+		slave.oldDevotion = slave.devotion;
+		slave.muscles = random(20, 50);
+		slave.skill.oral = 35;
+		slave.skill.anal = 15;
+		slave.skill.whoring = 0;
+		slave.skill.entertainment = 15;
+		slave.intelligence = random(51, 95);
+		slave.anus = 2;
+		slave.hStyle = "neat";
+		slave.hLength = 35;
+		setHealth(slave, jsRandom(20, 40));
+		if (V.mercenaries >= 3) {
+			slave.counter.publicUse += 39;
+		} else {
+			slave.counter.publicUse += 13;
+		}
+
+		App.Events.drawEventArt(node, slave);
+		const {
+			He,
+			he, his, him, himself, girl,
+		} = getPronouns(slave);
+
+		if (V.pedo_mode === 1 && V.seeDicks < 100) {
+			r.push(`You make a habit of dropping in on your mercenaries whenever you get the chance. You have regular meetings with their grizzled captain, of course, but turning up unannounced to get to know them is simply a matter of self-preservation. The better they like you, the more likely they are to think of more than their pay when deciding how to hazard themselves on your behalf. When you enter the lounge of their`);
+			if (V.barracks) {
+				r.push(`barracks`);
+			} else {
+				r.push(`main living area`);
+			}
+			r.push(`, you see ${slave.slaveName} kneeling next to a mercenary with most of his armor stripped off. ${He}'s the ${aNational(slave.nationality)} nurse they captured and enslaved, and ${he} seems to be doing pretty well in ${his} new life. ${He} seems to be checking the sutures on a minor wound to the man's flank. "Don't squirm!" ${he} says with an annoyed tone. "I'll get you off when I've checked this." He chuckles and holds still; ${he} redresses the wound, stands up, and strips off ${his} tank top, allowing ${his} huge tits to swing free. ${He}'s quite young, but ${his} _slave.skin body is appealingly curvy. As ${he} swings one leg across the seated mercenary, ${he} continues, "Please sit still and let me do the work. You need to take it easy for a day or two or you'll pop those sutures." Using ${his} hands, ${he} gently caresses his stiff prick with ${his} pillowy breasts, eliciting a grunt. ${He}'s a strong ${girl}, and pleasures him without letting any of ${his} weight rest on his body at all. When he climaxes, ${he} leans in to clean him with ${his} mouth and then heads off to wash out ${his} cleavage.`);
+		} else {
+			r.push(`You make a habit of dropping in on your mercenaries whenever you get the chance. You have regular meetings with their grizzled captain, of course, but turning up unannounced to get to know them is simply a matter of self-preservation. The better they like you, the more likely they are to think of more than their pay when deciding how to hazard themselves on your behalf.`);
+
+			r.push(`When you enter the lounge of their`);
+			if (V.barracks) {
+				r.push(`barracks`);
+			} else {
+				r.push(`main living area`);
+			}
+			r.push(`, you see ${slave.slaveName} bending over a mercenary with most of his armor stripped off. ${He}'s the ${aNational(slave.nationality)} nurse they captured and enslaved, and ${he} seems to be doing pretty well in ${his} new life. ${He} seems to be checking the sutures on a minor wound to the man's flank. "Don't  squirm," ${he} says quietly. "I'll get you off when I've checked this." He chuckles and holds still; ${he} redresses the wound, stands up, and strips off ${his} fatigue pants.`);
+			if (V.pedo_mode === 1) {
+				r.push(`${He}'s quite youthful, nimble and knows just how to manage ${his} impressive asset without it touching ${his} charge.`);
+			} else {
+				r.push(`${He}'s no longer young, but ${his} ${slave.skin} legs are pretty enough.`);
+			}
+			r.push(`As ${he} swings one leg across the seated mercenary, ${he} continues, "Please sit still and let me do the work. You need to take it easy for a day or two or you'll pop those sutures." Using a hand, ${he} guides ${himself} down onto his stiff prick, eliciting a grunt. ${He}'s a strong ${girl}, and rides him without letting any of ${his} weight rest on his hips at all. When he climaxes, ${he} kneels to clean him with ${his} mouth and then heads off to wash.`);
+		}
+
+		App.Events.addParagraph(node, r);
+
+		const lowBid = 10000;
+		const highBid = 25000;
+		const choices = [];
+		if (V.cash > lowBid) {
+			choices.push(new App.Events.Result(`Offer ${cashFormat(lowBid)} for ${him}"`, offerLow));
+			if (V.cash > highBid) {
+				choices.push(new App.Events.Result(`Offer a very generous  ${cashFormat(highBid)} for ${him}"`, offerHigh));
+			} else {
+				choices.push(new App.Events.Result(null, null, `Cannot afford even a generous bid of ${cashFormat(highBid)}`));
+			}
+		} else {
+			choices.push(new App.Events.Result(null, null, `Cannot afford even a low bid of ${cashFormat(lowBid)}`));
+		}
+
+		App.Events.addResponses(node, choices);
+
+		function offerLow() {
+			return `The mercenary laughs at your offered price. "No offense, ${properTitle()}, but no. Even if I wanted to sell ${him} on everyone's behalf for that price, my buddies would kill me for that. ${He}'s popular, that ${slave.slaveName}."`;
+		}
+
+		function offerHigh() {
+			const frag = new DocumentFragment();
+			let r = [];
+			cashX(-offerHigh, "slaveTransfer", slave);
+			r.push(`"Huh," says the mercenary. "${He}'s popular, but for that we could probably buy two of ${him}. Might be fun to train a couple of new nurses. Let me ask the boys and girls." He speaks into his helmet for a few minutes, and then turns back to you. "Sold. Enjoy, ${he}'s a good fuck."`);
+			r.push(App.UI.newSlaveIntro(slave));
+
+			App.Events.addParagraph(frag, r);
+			return frag;
+		}
+	}
+};
diff --git a/src/events/nonRandom/mercs/pSlaveMedic.tw b/src/events/nonRandom/mercs/pSlaveMedic.tw
deleted file mode 100644
index da0287741c90fbf1e0be474915f90ca8cba1ee41..0000000000000000000000000000000000000000
--- a/src/events/nonRandom/mercs/pSlaveMedic.tw
+++ /dev/null
@@ -1,129 +0,0 @@
-:: P slave medic [nobr]
-
-<<set $nextButton = "Continue", $nextLink = "Random Nonindividual Event", $returnTo = "Random Nonindividual Event">>
-
-<<set $eventResults.slaveMedic = 0>>
-
-<<if $pedo_mode == 1>>
-	<<set _minAge = $minimumSlaveAge>>
-	<<set _maxAge = 18>>
-<<else>>
-	<<set _minAge = 25>>
-	<<set _maxAge = 42>>
-<</if>>
-<<set _genParam = {minAge: _minAge, maxAge: _maxAge, disableDisability: 1}>>
-<<if $seeDicks >= 100>>
-	<<set _slave = GenerateNewSlave("XY", _genParam)>>
-	<<set _slave.dick = 5>>
-	<<set _slave.foreskin = 0>>
-	<<set _slave.balls = 3>>
-	<<set _slave.scrotum = 3>>
-	<<set _slave.butt = 3>>
-	<<set _slave.attrXY = 70>>
-<<else>>
-	<<set _slave = GenerateNewSlave("XX", _genParam)>>
-	<<set _slave.vagina = 2>>
-	<<set _slave.preg = -1>>
-	<<set _slave.ovaries = 1>>
-	<<set _slave.skill.vaginal = 35>>
-<</if>>
-<<if $pedo_mode == 1>>
-	<<set _slave.sexualQuirk = "caring">>
-	<<set _slave.intelligenceImplant = 15>>
-	<<if _slave.physicalAge >= 12>>
-		<<set _slave.teeth = "cosmetic braces">>
-	<</if>>
-	<<if $seeDicks < 100>>
-		<<set _slave.hips = 1>>
-		<<set _slave.boobs = 2000>>
-		<<set _slave.boobShape = "perky">>
-		<<set _slave.geneticQuirks.macromastia = 2>>
-		<<set _slave.butt = 4>>
-		<<set _slave.voice = 3>>
-	<<else>>
-		<<set _slave.geneticQuirks.wellHung = 2>>
-	<</if>>
-<<else>>
-	<<set _slave.anusTat = "bleached">>
-	<<set _slave.height = random(165,190)>>
-	<<set _slave.intelligenceImplant = 30>>
-	<<set _slave.teeth = "normal">>
-	<<if $seeDicks < 100>>
-		<<set _slave.boobs += 400>>
-		<<set _slave.butt += 1>>
-		<<set _slave.stampTat = either("flowers", "tribal patterns")>>
-	<</if>>
-<</if>>
-<<set _slave.origin = "$He was captured while caring for those injured in a failed attack on the Free City.">>
-<<set _slave.career = "a nurse">>
-<<set _slave.custom.desc = "$He has a faint air of fatigue about $him, and strength too: that of a survivor.">>
-<<set _slave.sexualFlaw = "none">>
-<<set _slave.behavioralFlaw = "none">>
-<<set _slave.devotion = random(30,40)>>
-<<set _slave.trust = _slave.devotion-20>>
-<<set _slave.oldDevotion = _slave.devotion>>
-<<set _slave.muscles = random(20,50)>>
-<<set _slave.skill.oral = 35>>
-<<set _slave.skill.anal = 15>>
-<<set _slave.skill.whoring = 0>>
-<<set _slave.skill.entertainment = 15>>
-<<set _slave.intelligence = random(51,95)>>
-<<set _slave.anus = 2>>
-<<set _slave.hStyle = "neat">>
-<<set _slave.hLength = 35>>
-<<run setHealth(_slave, jsRandom(20, 40))>>
-<<if $mercenaries >= 3>>
-	<<set _slave.counter.publicUse += 39>>
-<<else>>
-	<<set _slave.counter.publicUse += 13>>
-<</if>>
-
-<span id="art-frame">
-	/* 000-250-006 */
-	<<if $seeImages == 1>>
-		<<if $imageChoice == 1>>
-			<div class="imageRef lrgVector"><div class="mask">&nbsp;</div><<SlaveArt _slave 3 0>></div>
-		<<else>>
-			<div class="imageRef lrgRender"><div class="mask">&nbsp;</div><<SlaveArt _slave 3 0>></div>
-		<</if>>
-	<</if>>
-	/* 000-250-006 */
-</span>
-
-<<run App.Utils.setLocalPronouns(_slave)>>
-<<run Enunciate(_slave)>>
-
-<<if $pedo_mode == 1 && $seeDicks < 100>>
-	You make a habit of dropping in on your mercenaries whenever you get the chance. You have regular meetings with their grizzled captain, of course, but turning up unannounced to get to know them is simply a matter of self-preservation. The better they like you, the more likely they are to think of more than their pay when deciding how to hazard themselves on your behalf.
-
-	When you enter the lounge of their <<if $barracks>>barracks<<else>>main living area<</if>>, you see _slave.slaveName kneeling next to a mercenary with most of his armor stripped off. $He's the <<print aNational(_slave.nationality)>> nurse they captured and enslaved, and $he seems to be doing pretty well in $his new life. $He seems to be checking the sutures on a minor wound to the man's flank.
-
-	"Don't <<s>>quirm!" $he says with an annoyed tone. "I'll get you off when I've checked thi<<s>>." He chuckles and holds still; $he redresses the wound, stands up, and strips off $his tank top, allowing $his huge tits to swing free. $He's quite young, but $his _slave.skin body is appealingly curvy. As $he swings one leg across the seated mercenary, $he continues, "Plea<<s>>e <<s>>it <<s>>till and let me do the work. You need to take it ea<<s>>y for a day or two or you'll pop tho<<s>>e <<s>>uture<<s>>." Using $his hands, $he gently caresses his stiff prick with $his pillowy breasts, eliciting a grunt. $He's a strong $girl, and pleasures him without letting any of $his weight rest on his body at all. When he climaxes, $he leans in to clean him with $his mouth and then heads off to wash out $his cleavage.
-<<else>>
-	You make a habit of dropping in on your mercenaries whenever you get the chance. You have regular meetings with their grizzled captain, of course, but turning up unannounced to get to know them is simply a matter of self-preservation. The better they like you, the more likely they are to think of more than their pay when deciding how to hazard themselves on your behalf.
-
-	When you enter the lounge of their <<if $barracks>>barracks<<else>>main living area<</if>>, you see _slave.slaveName bending over a mercenary with most of his armor stripped off. $He's the <<print aNational(_slave.nationality)>> nurse they captured and enslaved, and $he seems to be doing pretty well in $his new life. $He seems to be checking the sutures on a minor wound to the man's flank.
-
-	"Don't <<s>>quirm," $he says quietly. "I'll get you off when I've checked thi<<s>>." He chuckles and holds still; $he redresses the wound, stands up, and strips off $his fatigue pants.
-	<<if $pedo_mode == 1>>
-		$He's quite youthful, nimble and knows just how to manage $his impressive asset without it touching $his charge.
-	<<else>>
-		$He's no longer young, but $his _slave.skin legs are pretty enough.
-	<</if>>
-	As $he swings one leg across the seated mercenary, $he continues, "Please <<s>>it <<s>>till and let me do the work. You need to take it ea<<s>>y for a day or two or you'll pop tho<<s>>e <<s>>uture<<s>>." Using a hand, $he guides $himself down onto his stiff prick, eliciting a grunt. $He's a strong $girl, and rides him without letting any of $his weight rest on his hips at all. When he climaxes, $he kneels to clean him with $his mouth and then heads off to wash.
-<</if>>
-
-<span id="result">
-<br><br><<link "Offer <<print cashFormat(10000)>> for $him">>
-	<<replace "#result">>
-		The mercenary laughs at your offered price. "No offense, <<= properTitle()>>, but no. Even if I wanted to sell $him on everyone's behalf for that price, my buddies would kill me for that. $He's popular, that _slave.slaveName."
-	<</replace>>
-<</link>>
-<br><<link "Offer a very generous <<print cashFormat(25000)>> for $him">>
-	<<replace "#result">>
-	<<run cashX(-25000, "slaveTransfer", _slave)>>
-		"Huh," says the mercenary. "$He's popular, but for that we could probably buy two of $him. Might be fun to train a couple of new nurses. Let me ask the boys and girls." He speaks into his helmet for a few minutes, and then turns back to you. "Sold. Enjoy, $he's a good fuck."
-		<<includeDOM App.UI.newSlaveIntro(_slave)>>
-	<</replace>>
-<</link>>
-</span>
diff --git a/src/events/nonRandom/mercs/pSnatchAndGrab.js b/src/events/nonRandom/mercs/pSnatchAndGrab.js
new file mode 100644
index 0000000000000000000000000000000000000000..8a894641db1b38edda9fcdc96a9acf4e9ac99999
--- /dev/null
+++ b/src/events/nonRandom/mercs/pSnatchAndGrab.js
@@ -0,0 +1,100 @@
+App.Events.PSnatchAndGrab = class PSnatchAndGrab extends App.Events.BaseEvent {
+	eventPrerequisites() {
+		return [
+			() => V.mercenaries > 0
+		];
+	}
+
+	execute(node) {
+		let r = [];
+		V.nextButton = "Continue";
+		V.eventResults.snatch = 0;
+
+		App.Events.addParagraph(node, [`${capFirstChar(V.assistant.name)} forwards a discreet message from the leader of your mercenaries.`]);
+
+		r.push(`"${properTitle()}, I've just become aware of a... business opportunity through some old friends. There's an unregistered lab doing illegal gene therapy work. At least two agencies are onto them, which is how I heard of it. Word is, they're packing up and moving out. I believe me and my people can appropriate that shipment. Catch is, to make this work I need to pay some serious bribes, and I need to pay them today. We'll cut you in as an equal partner for ${cashFormat(10000)} cash, right now. One share should come to one of the lab rats, more or less. Are you in or out?"`);
+		if (V.assistant.personality === 1) {
+			const {
+				HeA,
+				heA, hisA, himselfA
+			} = getPronouns(assistant.pronouns().main).appendSuffix("A");
+			App.Events.addParagraph(node, r);
+			r = [];
+			r.push(`${capFirstChar(V.assistant.name)}'s ${V.assistant.appearance} avatar appears on your desk next to the message.`);
+			switch (V.assistant.appearance) {
+				case "monstergirl":
+					r.push(`"I vote yes. Even though whatever that lab is producing can't possibly be as interesting as me," ${heA} says haughtily, and twirls a strand of tentacle hair.`);
+					break;
+				case "shemale":
+					r.push(`"I vote yes," ${heA} says sweetly. "Whatever they're doing, it's probably interesting. I'd love to fuck something interesting."`);
+					break;
+				case "amazon":
+					r.push(`"I vote yes!" ${heA} shouts. "Whatever they're doing, their girls are probably valuable. And everything's more fun if you loot it instead of buying it."`);
+					break;
+				case "businesswoman":
+					r.push(`"I vote yes," ${heA} says. "The likelihood that the lab is producing something valuable is overwhelming. The potential profits are," and ${heA} pauses to fan ${himselfA}, "exciting."`);
+					break;
+				case "fairy":
+				case "pregnant fairy":
+					r.push(`"I vote yes," ${heA} says. "They could be up to something really cool!"`);
+					break;
+				case "goddess":
+					r.push(`"I vote yes," ${heA} says. "Whatever is in that lab deserves some loving attention and... more variety is always appreciated."`);
+					break;
+				case "hypergoddess":
+					r.push(`"I vote yes," ${heA} says. "Whatever is in that lab deserves some loving attention and... more variety is always appreciated."`);
+					break;
+				case "loli":
+					r.push(`"I vote yeah," ${heA} says. "I wanna see what's inside!"`);
+					break;
+				case "preggololi":
+					r.push(`"I vote yeah," ${heA} says. "I wanna see what's inside!"`);
+					break;
+				case "schoolgirl":
+					r.push(`"I vote yeah," ${heA} says. "I just wanna see what that lab is doing. Could be cool!"`);
+					break;
+				case "angel":
+					r.push(`"I vote yes," ${heA} says. "Whatever is in that lab deserves a better life under your care."`);
+					break;
+				case "cherub":
+					r.push(`"I vote yeah," ${heA} says. "I'm really curious what could be inside."`);
+					break;
+				case "incubus":
+					r.push(`"I vote yes," ${heA} says. "I can't wait to get my dick in it!"`);
+					break;
+				case "succubus":
+					r.push(`"I vote no," ${heA} says. "You're all mine!"`);
+					break;
+				case "imp":
+					r.push(`"I vote yeah," ${heA} says. "I can't wait to tease and torment whatever's inside!"`);
+					break;
+				case "witch":
+					r.push(`"I vote yes," ${heA} says. "It can't be worse than some of my fuckups."`);
+					break;
+				case "ERROR_1606_APPEARANCE_FILE_CORRUPT":
+					r.push(`${HeA} doesn't comment, though a large, toothy grin spreads across the entirety of ${hisA} head revealing ${hisA} thoughts on the subject.`);
+					break;
+				default:
+					r.push(`"I would suggest agreement," ${heA} says. "Even if the prize does not appeal to you personally, it's likely to be quite valuable. Selling it could net you quite a profit."`);
+			}
+		}
+
+		App.Events.addParagraph(node, r);
+
+		const choices = [
+			new App.Events.Result(`Bankroll the snatch and grab`, bankroll),
+			new App.Events.Result(`Politely decline`, decline)
+		];
+		App.Events.addResponses(node, choices);
+
+		function bankroll() {
+			cashX(-10000, "slaveTransfer");
+			V.eventResults.snatch = 1;
+			return `You receive no response whatsoever. Twenty minutes later, however, a liaison VTOL aircraft that the mercenaries sometimes hire arrives, loads a party of armed men and women, and leaves.`;
+		}
+
+		function decline() {
+			return `You receive no response whatsoever. That's how it is with professionals: the offer was never made, you never declined, and no further discussion is necessary or desired.`;
+		}
+	}
+};
diff --git a/src/events/nonRandom/mercs/pSnatchAndGrab.tw b/src/events/nonRandom/mercs/pSnatchAndGrab.tw
deleted file mode 100644
index df7f2b0f84146748d5981b2d0b5704f19a0343db..0000000000000000000000000000000000000000
--- a/src/events/nonRandom/mercs/pSnatchAndGrab.tw
+++ /dev/null
@@ -1,69 +0,0 @@
-:: P snatch and grab [nobr]
-
-<<set $nextButton = "Continue">>
-
-<<set $eventResults.snatch = 0>>
-<<setAssistantPronouns>>
-
-<<= capFirstChar($assistant.name)>> forwards a discreet message from the leader of your mercenaries.
-<br><br>
-"<<= properTitle()>>, I've just become aware of a... business opportunity through some old friends. There's an unregistered lab doing illegal gene therapy work. At least two agencies are onto them, which is how I heard of it. Word is, they're packing up and moving out. I believe me and my people can appropriate that shipment. Catch is, to make this work I need to pay some serious bribes, and I need to pay them today. We'll cut you in as an equal partner for <<print cashFormat(10000)>> cash, right now. One share should come to one of the lab rats, more or less. Are you in or out?"
-<<if $assistant.personality == 1>>
-	<br><br>
-	<<= capFirstChar($assistant.name)>>'s $assistant.appearance avatar appears on your desk next to the message.
-	<<switch $assistant.appearance>>
-	<<case "monstergirl">>
-		"I vote yes. Even though whatever that lab is producing can't possibly be as interesting as me," _heA says haughtily, and twirls a strand of tentacle hair.
-	<<case "shemale">>
-		"I vote yes," _heA says sweetly. "Whatever they're doing, it's probably interesting. I'd love to fuck something interesting."
-	<<case "amazon">>
-		"I vote yes!" _heA shouts. "Whatever they're doing, their girls are probably valuable. And everything's more fun if you loot it instead of buying it."
-	<<case "businesswoman">>
-		"I vote yes," _heA says. "The likelihood that the lab is producing something valuable is overwhelming. The potential profits are," and _heA pauses to fan _himselfA, "exciting."
-	<<case "fairy" "pregnant fairy">>
-		"I vote yes," _heA says. "They could be up to something really cool!"
-	<<case "goddess">>
-		"I vote yes," _heA says. "Whatever is in that lab deserves some loving attention and... more variety is always appreciated."
-	<<case "hypergoddess">>
-		"I vote yes," _heA says. "Whatever is in that lab deserves some loving attention and... more variety is always appreciated."
-	<<case "loli">>
-		"I vote yeah," _heA says. "I wanna see what's inside!"
-	<<case "preggololi">>
-		"I vote yeah," _heA says. "I wanna see what's inside!"
-	<<case "schoolgirl">>
-		"I vote yeah," _heA says. "I just wanna see what that lab is doing. Could be cool!"
-	<<case "angel">>
-		"I vote yes," _heA says. "Whatever is in that lab deserves a better life under your care."
-	<<case "cherub">>
-		"I vote yeah," _heA says. "I'm really curious what could be inside."
-	<<case "incubus">>
-		"I vote yes," _heA says. "I can't wait to get my dick in it!"
-	<<case "succubus">>
-		"I vote no," _heA says. "You're all mine!"
-	<<case "imp">>
-		"I vote yeah," _heA says. "I can't wait to tease and torment whatever's inside!"
-	<<case "witch">>
-		"I vote yes," _heA says. "It can't be worse than some of my fuckups."
-	<<case "ERROR_1606_APPEARANCE_FILE_CORRUPT">>
-		_HeA doesn't comment, though a large, toothy grin spreads across the entirety of _hisA head revealing _hisA thoughts on the subject.
-	<<default>>
-		"I would suggest agreement," _heA says. "Even if the prize does not appeal to you personally, it's likely to be quite valuable. Selling it could net you quite a profit."
-	<</switch>>
-<</if>>
-
-<br><br>
-
-<span id="result">
-<<link "Bankroll the snatch and grab">>
-	<<replace "#result">>
-	You receive no response whatsoever. Twenty minutes later, however, a liaison VTOL aircraft that the mercenaries sometimes hire arrives, loads a party of armed men and women, and leaves.
-	<<run cashX(-10000, "slaveTransfer")>>
-	<<set $eventResults.snatch = 1>>
-	<</replace>>
-<</link>>
-<br><<link "Politely decline">>
-	<<replace "#result">>
-		You receive no response whatsoever. That's how it is with professionals: the offer was never made, you never declined, and no further discussion is necessary or desired.
-	<</replace>>
-<</link>>
-</span>
diff --git a/src/events/nonRandom/mercs/pSnatchAndGrabResult.js b/src/events/nonRandom/mercs/pSnatchAndGrabResult.js
new file mode 100644
index 0000000000000000000000000000000000000000..540ac0778f0c60b4526c2983e61afbd7506dc4e2
--- /dev/null
+++ b/src/events/nonRandom/mercs/pSnatchAndGrabResult.js
@@ -0,0 +1,122 @@
+App.Events.PSnatchAndGrabResult = class PSnatchAndGrabResult extends App.Events.BaseEvent {
+	eventPrerequisites() {
+		return [
+			() => V.eventResults.snatch === 1
+		];
+	}
+
+	execute(node) {
+		let r = [];
+
+		V.nextButton = "Continue";
+		V.nextLink = "Random Nonindividual Event";
+		V.eventResults.snatch = 0;
+
+		const snatched = GenerateNewSlave("XX", {maxAge: (V.pedo_mode === 1 ? V.minimumSlaveAge : 18), disableDisability: 1});
+		if (V.pedo_mode === 1) {
+			snatched.boobShape = "saggy";
+			snatched.nipples = "partially inverted";
+			snatched.areolae = 3;
+			snatched.lips = 15;
+			snatched.voice = 2;
+			snatched.weight = 60;
+			snatched.muscles = 0;
+			snatched.shoulders = -2;
+			snatched.hips = 0;
+			snatched.waist = 10;
+		} else {
+			if (snatched.lips < 10) {
+				snatched.lips += 5;
+			}
+			snatched.height = Height.random(snatched, {skew: 1, limitMult: [0, 2]});
+			snatched.weight = 0;
+			snatched.muscles = 20;
+			snatched.waist = -75;
+		}
+
+		snatched.faceShape = (V.pedo_mode === 1 ? "exotic" : "androgynous");
+		snatched.anus = 0;
+		if (V.seeDicks !== 100) {
+			snatched.vagina = 0;
+			snatched.ovaries = 1;
+		}
+		if (V.seeDicks === 0) {
+			snatched.dick = 0;
+			snatched.balls = 0;
+			snatched.scrotum = 0;
+		} else if (V.seeDicks > 75) {
+			snatched.dick = (V.pedo_mode === 1 ? 2 : 6);
+			if (snatched.foreskin > 0) {
+				snatched.foreskin = snatched.dick;
+			}
+			snatched.balls = 1;
+			snatched.scrotum = snatched.balls;
+		} else {
+			snatched.dick = 1;
+			snatched.foreskin = 1;
+			snatched.balls = 1;
+			snatched.scrotum = snatched.balls;
+		}
+
+		snatched.boobs += (V.pedo_mode === 1 ? 6000 : 200);
+		snatched.butt += (V.pedo_mode === 1 ? 1 : 2);
+		snatched.origin = "$He is your share of a raid on an illegal laboratory by your mercenaries.";
+		snatched.career = "a slave";
+		snatched.devotion = 100;
+		snatched.trust = 100;
+		setHealth(snatched, 250, 0, 0, 0, 0);
+		snatched.face = 15;
+		snatched.skill.vaginal = 0;
+		snatched.skill.oral = 0;
+		snatched.skill.anal = 0;
+		snatched.skill.whoring = 0;
+		snatched.skill.entertainment = 0;
+		snatched.birthWeek = 0;
+		snatched.hStyle = "shaved";
+		snatched.hLength = 0;
+		snatched.custom.desc = "$His skin is unnaturally perfect, totally without blemishes. $He radiates unnatural health and resilience.";
+		snatched.custom.tattoo = "$He has a barcode tattooed on the top of $his head.";
+		snatched.behavioralFlaw = "odd";
+		snatched.fetish = "none";
+		snatched.energy = 100;
+		snatched.fetishKnown = 1;
+		snatched.attrKnown = 1;
+		if (snatched.physicalAge >= 12) {
+			snatched.teeth = "normal";
+		}
+		snatched.pubicHStyle = "hairless";
+		snatched.underArmHStyle = "hairless";
+
+		snatched.slaveCost = -10000;
+
+		const {
+			he, himself
+		} = getPronouns(snatched);
+
+		r.push(`In the middle of the night, there is a polite knock on your penthouse door. You are alerted by ${V.assistant.name}, who observes`);
+		if (V.assistant.personality === 1) {
+			r.push(`with some irritation`);
+		}
+		r.push(`that the mercenary who knocked has gone, has left a large case outside the door, and has satisfied the security systems that the case contains nothing hazardous.`);
+
+		r.push(`The case prompts you for a handprint code; your hand works just fine. It contains a naked, hairless, perfectly healthy young body in the fetal position. This person awakens as the case opens, looks you confidently in the eye, and says "Are you my`);
+		if (V.PC.title !== 0) {
+			r.push(`Master?"`);
+		} else {
+			r.push(`Mistress?"`);
+		}
+
+		r.push(`When you state that, apparently, you are, ${he} climbs out of the case, prostrates ${himself} in the hall before you, and says reverentially into the floor, "I love you,`);
+		if (V.PC.title !== 0) {
+			r.push(`Master."`);
+		} else {
+			r.push(`Mistress."`);
+		}
+
+		App.Events.addParagraph(node, r);
+		r = [];
+		node.append(App.Desc.longSlave(snatched));
+
+		node.append(App.UI.newSlaveIntro(snatched));
+	}
+};
diff --git a/src/events/nonRandom/mercs/pSnatchAndGrabResult.tw b/src/events/nonRandom/mercs/pSnatchAndGrabResult.tw
deleted file mode 100644
index 62aa7e337844cc3c93b96081b8fbf66ddad4bcb9..0000000000000000000000000000000000000000
--- a/src/events/nonRandom/mercs/pSnatchAndGrabResult.tw
+++ /dev/null
@@ -1,90 +0,0 @@
-:: P snatch and grab result [nobr]
-
-<<set $nextButton = "Continue", $nextLink = "Random Nonindividual Event", $returnTo = "Random Nonindividual Event", $eventResults.snatch = 0>>
-
-<<set _snatched = GenerateNewSlave("XX", {maxAge: ($pedo_mode === 1 ? $minimumSlaveAge : 18), disableDisability: 1})>>
-<<if $pedo_mode == 1>>
-	<<set _snatched.boobShape = "saggy">>
-	<<set _snatched.nipples = "partially inverted">>
-	<<set _snatched.areolae = 3>>
-	<<set _snatched.lips = 15>>
-	<<set _snatched.voice = 2>>
-	<<set _snatched.weight = 60>>
-	<<set _snatched.muscles = 0>>
-	<<set _snatched.shoulders = -2>>
-	<<set _snatched.hips = 0>>
-	<<set _snatched.waist = 10>>
-<<else>>
-	<<if _snatched.lips < 10>>
-		<<set _snatched.lips += 5>>
-	<</if>>
-	<<set _snatched.height = Height.random(_snatched, {skew: 1, limitMult: [0, 2]})>>
-	<<set _snatched.weight = 0>>
-	<<set _snatched.muscles = 20>>
-	<<set _snatched.waist = -75>>
-<</if>>
-
-<<set _snatched.faceShape = ($pedo_mode === 1 ? "exotic" : "androgynous")>>
-<<set _snatched.anus = 0>>
-<<if $seeDicks != 100>>
-	<<set _snatched.vagina = 0>>
-	<<set _snatched.ovaries = 1>>
-<</if>>
-<<if $seeDicks == 0>>
-	<<set _snatched.dick = 0>>
-	<<set _snatched.balls = 0>>
-	<<set _snatched.scrotum = 0>>
-<<elseif $seeDicks > 75>>
-	<<set _snatched.dick = ($pedo_mode === 1 ? 2 : 6)>>
-	<<if _snatched.foreskin > 0>><<set _snatched.foreskin = _snatched.dick>><</if>>
-	<<set _snatched.balls = 1>>
-	<<set _snatched.scrotum = _snatched.balls>>
-<<else>>
-	<<set _snatched.dick = 1>>
-	<<set _snatched.foreskin = 1>>
-	<<set _snatched.balls = 1>>
-	<<set _snatched.scrotum = _snatched.balls>>
-<</if>>
-
-<<set _snatched.boobs += ($pedo_mode === 1 ? 6000 : 200)>>
-<<set _snatched.butt += ($pedo_mode === 1 ? 1 : 2)>>
-<<set _snatched.origin = "$He is your share of a raid on an illegal laboratory by your mercenaries.">>
-<<set _snatched.career = "a slave">>
-<<set _snatched.devotion = 100>>
-<<set _snatched.trust = 100>>
-<<run setHealth(_snatched, 250, 0, 0, 0, 0)>>
-<<set _snatched.face = 15>>
-<<set _snatched.skill.vaginal = 0>>
-<<set _snatched.skill.oral = 0>>
-<<set _snatched.skill.anal = 0>>
-<<set _snatched.skill.whoring = 0>>
-<<set _snatched.skill.entertainment = 0>>
-<<set _snatched.birthWeek = 0>>
-<<set _snatched.hStyle = "shaved bald">>
-<<set _snatched.hLength = 0>>
-<<set _snatched.custom.desc = "$His skin is unnaturally perfect, totally without blemishes. $He radiates unnatural health and resilience.">>
-<<set _snatched.custom.tattoo = "$He has a barcode tattooed on the top of $his head.">>
-<<set _snatched.behavioralFlaw = "odd">>
-<<set _snatched.fetish = "none">>
-<<set _snatched.energy = 100>>
-<<set _snatched.fetishKnown = 1>>
-<<set _snatched.attrKnown = 1>>
-<<if _snatched.physicalAge >= 12>>
-	<<set _snatched.teeth = "normal">>
-<</if>>
-<<set _snatched.pubicHStyle = "hairless">>
-<<set _snatched.underArmHStyle = "hairless">>
-
-<<setLocalPronouns _snatched>>
-<<set _snatched.slaveCost = -10000>>
-
-In the middle of the night, there is a polite knock on your penthouse door. You are alerted by $assistant.name, who observes <<if $assistant.personality == 1>>with some irritation <</if>>that the mercenary who knocked has gone, has left a large case outside the door, and has satisfied the security systems that the case contains nothing hazardous.
-
-The case prompts you for a handprint code; your hand works just fine. It contains a naked, hairless, perfectly healthy young body in the fetal position. This person awakens as the case opens, looks you confidently in the eye, and says "Are you my <<if $PC.title != 0>>Master<<else>>Mistress<</if>>?"
-
-When you state that, apparently, you are, $he climbs out of the case, prostrates $himself in the hall before you, and says reverentially into the floor, "I love you, <<if $PC.title != 0>>Master<<else>>Mistress<</if>>."
-
-<br><br>
-<<includeDOM App.Desc.longSlave(_snatched)>>
-
-<<includeDOM App.UI.newSlaveIntro(_snatched)>>
diff --git a/src/events/nonRandomEvent.js b/src/events/nonRandomEvent.js
index 6019c492ce19878f04ca488b06e193a572960b46..04e80345a676b913f0e14c2dfa3e2547501cbf98 100644
--- a/src/events/nonRandomEvent.js
+++ b/src/events/nonRandomEvent.js
@@ -102,6 +102,11 @@ App.Events.getNonrandomEvents = function() {
 		new App.Events.secExpSmilingMan3(),
 
 		new App.Events.PEPitFight(),
+		new App.Events.PMercsHelpCorp(),
+		new App.Events.PMercenaryRomeo(),
+		new App.Events.PRaidResult(),
+		new App.Events.PSlaveMedic(),
+		new App.Events.PSnatchAndGrabResult(),
 	];
 };
 
@@ -254,14 +259,6 @@ globalThis.nonRandomEvent = function() {
 			V.assholeKnight = 1;
 			V.imperialEventWeek = effectiveWeek;
 			setTimeout(() => Engine.play("SE assholeknight"), Engine.minDomActionDelay);
-		} else if ((effectiveWeek >= 44) && (V.mercenaries > 0) && V.mercRomeo !== 1) {
-			const valid = V.slaves.find(function(s) { return (["serve the public", "serve in the club", "whore", "work in the brothel"].includes(s.assignment) || s.counter.publicUse >= 50) && s.fetish !== "mindbroken" && s.fuckdoll === 0; });
-			V.mercRomeo = 1;
-			if (valid) {
-				setTimeout(() => Engine.play("P mercenary romeo"), Engine.minDomActionDelay);
-			} else {
-				setTimeout(() => Engine.play("Nonrandom Event"), Engine.minDomActionDelay);
-			}
 		} else if (effectiveWeek === 54 && (V.peacekeepers) && V.peacekeepers.attitude >= 0) {
 			setTimeout(() => Engine.play("P peacekeepers deficit"), Engine.minDomActionDelay);
 		} else if (V.SF.Toggle && V.SF.Active === -1 && effectiveWeek >= 72) {
@@ -276,8 +273,6 @@ globalThis.nonRandomEvent = function() {
 			setTimeout(() => Engine.play("P peacekeepers intro"), Engine.minDomActionDelay);
 		} else if (V.arcologies[0].prosperity > 80 && App.Utils.schoolCounter() === 0 && V.schoolSuggestion === 0) {
 			setTimeout(() => Engine.play("P school suggestion"), Engine.minDomActionDelay);
-		} else if (effectiveWeek > 70 && V.corp.Incorporated > 0 && V.rivalOwnerEnslaved > 0 && V.mercenaries >= 3 && V.mercenariesHelpCorp === 0 && V.corp.DivExtra > 0) {
-			setTimeout(() => Engine.play("P Mercs Help Corp"), Engine.minDomActionDelay);
 		} else if (effectiveWeek > 75 && (V.peacekeepers) && V.peacekeepers.strength < 50 && V.rivalOwner === 0 && V.peacekeepersFate !== 1) {
 			setTimeout(() => Engine.play("P peacekeepers independence"), Engine.minDomActionDelay);
 		} else if ((V.peacekeepers) && V.peacekeepers.strength >= 50 && V.peacekeepers.influenceAnnounced === 0) {
@@ -296,12 +291,6 @@ globalThis.nonRandomEvent = function() {
 			}
 		} else if ((V.arcologies[0].FSPaternalistDecoration === 100) && (V.swanSong === 2) && (V.week - V.swanSongWeek >= 3)) {
 			setTimeout(() => Engine.play("RE The Siren Strikes Back"), Engine.minDomActionDelay);
-		} else if (V.eventResults.snatch === 1) {
-			setTimeout(() => Engine.play("P snatch and grab result"), Engine.minDomActionDelay);
-		} else if (V.eventResults.raid === 1) {
-			setTimeout(() => Engine.play("P raid result"), Engine.minDomActionDelay);
-		} else if (V.eventResults.slaveMedic > 0) {
-			setTimeout(() => Engine.play("P slave medic"), Engine.minDomActionDelay);
 		} else if ((effectiveWeek >= 37) && (V.arcologies[0].FSNeoImperialistLaw1 === 1) && (V.arcologies[0].FSNeoImperialistLaw2 === 1) && V.poorKnight !== 1 && effectiveWeek >= V.imperialEventWeek + 3) {
 			V.poorKnight = 1;
 			V.imperialEventWeek = effectiveWeek;
diff --git a/src/events/timeGatedPlotEvent.js b/src/events/timeGatedPlotEvent.js
index 664bd5114f44def78979fe5c7ac53ef5e04080d4..6a6719fd72e9e1a7117acc378816a1526cc7626c 100644
--- a/src/events/timeGatedPlotEvent.js
+++ b/src/events/timeGatedPlotEvent.js
@@ -13,16 +13,10 @@ App.Events.TimeGatedPlotEvent = class TimeGatedPlotEvent extends App.Events.Base
 		this.events[17] = new App.Events.PShootInvitation();
 		this.events[20] = new App.Events.PSlaveFood();
 		this.events[24] = new App.Events.PMilitia();
-		this.events[31] = new App.Events.TwineEvent().wrapPassage([
-			() => V.mercenaries === 0
-		], "P mercenaries");
-		this.events[35] = new App.Events.TwineEvent().wrapPassage([
-			() => V.mercenaries > 0
-		], "P snatch and grab");
+		this.events[31] = new App.Events.PMercenaries();
+		this.events[35] = new App.Events.PSnatchAndGrab();
 		this.events[43] = new App.Events.TwineEvent().wrapPassage([], "P invasion");
-		this.events[46] = new App.Events.TwineEvent().wrapPassage([
-			() => V.mercenaries > 0
-		], "P raid invitation");
+		this.events[46] = new App.Events.PRaidInvitation();
 		this.events[56] = new App.Events.PUndergroundRailroad();
 		this.events[58] = new App.Events.PBombing();
 		this.events[61] = new App.Events.PTraitorMessage();