diff --git a/game/00-framework-tools/00-namespace/namespace.js b/game/00-framework-tools/00-namespace/namespace.js
index d0194b309988de6c68c3fc340f9be5777a73010f..bc04d45b5da30a2de5c919838b0e7a1e5451217a 100644
--- a/game/00-framework-tools/00-namespace/namespace.js
+++ b/game/00-framework-tools/00-namespace/namespace.js
@@ -24,6 +24,10 @@ window.DOL = {
 	 */
 	Versions: {},
 	Perflog: {},
+	/**
+	 * General purpose call stack containing the widget names as they are called.
+	 */
+	Stack: [],
 
 	/** Patch to make javascript execution more consistent (see comment below) */
 	State: State,
diff --git a/game/01-config/sugarcubeConfig.js b/game/01-config/sugarcubeConfig.js
index 99f6fc8f3b6e455078a126c1a1a2b044a56b0820..987889ed5838c0fb3fdd5723090b84739539d279 100644
--- a/game/01-config/sugarcubeConfig.js
+++ b/game/01-config/sugarcubeConfig.js
@@ -93,6 +93,7 @@ function widgetHandler(widgetName, contents) {
 	let argsCache;
 	trace('declaring fn', widgetName);
 	return function () {
+		DOL.Stack.push(widgetName);
 		const context = devOptions.invocationId
 			? `${State.passage}:${widgetName}:${uniqueInvocation++}`
 			: `${State.passage}:${widgetName}`;
@@ -159,6 +160,7 @@ function widgetHandler(widgetName, contents) {
 		}
 		finally {
 			// Custom code
+			DOL.Stack.pop();
 			vStack.pop();
 			vContext.pop();
 			State.variables[VIRTUAL_CURRENT] = priorFrame
diff --git a/game/03-JavaScript/EventDebug.js b/game/03-JavaScript/EventDebug.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f8c0565dca7c34c826746a0991c1034c3d459ba
--- /dev/null
+++ b/game/03-JavaScript/EventDebug.js
@@ -0,0 +1,117 @@
+/*  Jimmy: Blueprint for event structure, packaged for convenience.
+ *  $event = {
+ *      buffer = [] : EventNPC, refer to below
+ *      schema = 1 : Integer, defines the current version on the save, useful for update tracking.
+ *  }
+ * 
+ *  EventNPC = {
+ *      slot: Where the NPC is positioned in NPCList.   
+ *              EG: 0       $NPCList[0]
+ *      time: The time the NPC was generated.           
+ *              EG: 805     13:48 / 1:48pm
+ *      area: Where it was generated.                   
+ *              EG: ['::Alleyways', 'eventsstreet', 'eventday', 'street8']
+ *                      Passage        Widget 1      Widget 2    Widget 3
+ *  }
+ */
+
+/**
+ * Handles event data for NPC objects for debugging.
+ * @module EventData
+ */
+class EventData {
+    constructor() {
+        this.disable = false;
+    }
+
+    Push(passage, index, time) {
+        if (this.disable) return;
+        V.event = ensure(V.event, {
+            buffer: [],
+            schema: 1
+        });
+        V.event.buffer.push({
+            slot: index, // TODO: Remove in favour of direct insertion. (Nvm)
+            time: time,
+            area: [passage, ...DOL.Stack.slice(0, -1)]
+        });
+    }
+
+    Pop(index) {
+        if (this.disable) return;
+        if (V.event) {
+            V.event.buffer = V.event.buffer.filter(e => e.slot !== index); // TODO: Splice backwards instead.
+            if (V.event.buffer.length === 0) {
+                this.Clear();
+            }
+        }
+    }
+
+    Get(index) {
+        if (V.event) {
+            return V.event.buffer.find(e => e.slot === index);
+        }
+        return undefined;
+    }
+
+    GetEvery(index) {
+        if (V.event) {
+            return V.event.buffer.filter(e => e.slot === index);
+        }
+        return [];
+    }
+
+    Clear()  {
+        if (this.disable) return;
+        delete V.event;
+    }
+
+    Update() {
+        if (V.event == undefined) {
+            return;
+        }
+        // Check if $event contains schema
+        switch (V.event.schema) {
+            case 1:
+                // No need for updates.
+                return;
+            default:
+                // Update to newer schema (1 atm).
+                // .event ['Farm Work', 'Farm Work', 'Farm Work', 'Farm Work'] 
+                // .eventtime [497, 497, 497, 497]
+                // .eventslot [0, 1, 2, 3]
+                const event = [...V.event];
+                V.event = {
+                    buffer: [],
+                    schema: 1
+                };
+                for (let i = 0; i < event.length; i++) {
+                    this.Push(event[i], V.eventslot[i], V.eventtime[i])
+                }
+                delete V.eventtime;
+                delete V.eventslot;
+                return;
+        }
+    }
+
+    IsSlotTaken(index) {
+        if (V.event == undefined) return false;
+        return V.event.buffer.some(e => e.slot === index);
+    }
+
+    get Disable() {
+        return this.disable;
+    }
+
+    set Disable(value) {
+        if (typeof value === 'boolean') {
+            this.disable = value;
+        } else {
+            console.debug('EventData.disable set with unexpected data-type, requires boolean.');
+        }
+    }
+};
+
+// Jimmy: Potentially flawed design style, static class basically.
+// But ends up being just an extended function in reality. (Not actually tho)
+window.EventSystem = new EventData();
diff --git a/game/03-JavaScript/base.js b/game/03-JavaScript/base.js
index cc7dbb21a15338cfcc5e442a6a8de75823307545..0e8b7d179baa53c6917d7152856d37e0851337d1 100644
--- a/game/03-JavaScript/base.js
+++ b/game/03-JavaScript/base.js
@@ -92,9 +92,9 @@ Macro.add('time', {
 	}
 });
 
-window.ensureIsArray = function (x) {
+window.ensureIsArray = function(x, check = false) {
+	if (check) x = ensure(x, []);
 	if (Array.isArray(x)) return x;
-
 	return [x];
 }
 
diff --git a/game/03-JavaScript/eventpool.js b/game/03-JavaScript/eventpool.js
index 315fefd3946f0e19d4afbec5fe3eacf15d014547..5c44c598842e4e54d3572e04d5f4ed9d96d47ccc 100644
--- a/game/03-JavaScript/eventpool.js
+++ b/game/03-JavaScript/eventpool.js
@@ -113,13 +113,20 @@ Macro.add("addevent", {
 Macro.add("runeventpool", {
 	skipArgs: true,
 	handler: function () {
-		if(T.eventpool.includes(V.eventPoolOverride)){
-			var pick = V.eventPoolOverride;
+		let pick = T.eventpool.find(e => e.name === V.eventPoolOverride);
+		if (pick) {
 			delete V.eventPoolOverride;
-		}else{
-			var pick = rollWeightedRandomFromArray(T.eventpool);
+		} else if (T.eventpool.includes(V.eventPoolOverride)) {
+			pick = V.eventPoolOverride;
+			delete V.eventPoolOverride;
+		} else {
+			pick = rollWeightedRandomFromArray(T.eventpool);
 		}
 		if (!pick) throw new Error("Event pool is empty");
+		// Jimmy: For tracking where in the code you may be.
+		// E.G: ['eventAmbient', >>'autumn_anystreet_2'<<, 'generate1']
+		DOL.Stack.push(pick.name);
 		jQuery(this.output).wiki(pick.content);
+		DOL.Stack.pop();
 	}
 });
diff --git a/game/04-Variables/variables-versionUpdate.twee b/game/04-Variables/variables-versionUpdate.twee
index fa9868b57152c4a248be088905be54cf2cdb9097..95cb9c964919748969ce427680f2dbf5d6ccc122 100644
--- a/game/04-Variables/variables-versionUpdate.twee
+++ b/game/04-Variables/variables-versionUpdate.twee
@@ -2654,16 +2654,34 @@
 		<<earnFeat "Morgan the Lost">>
 	<</if>>
 
-	<!-- DefaultActions JS routine for error correction. -->
+	<!-- Jimmy: DefaultActions JS routine for error correction. -->
 	<<run
-		/* Test 1 - If regrab[0] is an object, there was a failure. */
-		let temp = DefaultActions.get('rape', 'Everyone', 'regrab')[0];
-		if (typeof temp === 'object') {
-			/* Reset everything as a final step, the error is consumed. */
-			V.actionDefaults = temp;
-			V.actionDefaults = DefaultActions.check(DefaultActions.setup())
+		/* Perform check for broken default action structures. */
+		if ($actionDefaults != undefined) {
+			/* Test 1 - If regrab[0] is an object, there was a failure. */
+			let temp = DefaultActions.get('rape', 'Everyone', 'regrab')[0];
+			if (typeof temp === 'object') {
+				/* Reset everything as a final step, the error is consumed. */
+				V.actionDefaults = temp;
+				V.actionDefaults = DefaultActions.check(DefaultActions.setup())
+			}
 		}
 	>>
+	
+	<!-- Jimmy: Run updater for EventSystem.
+				Only runs if behind on schema, and if $event exists. -->
+	<<run EventSystem.Update()>>
+
+	<!-- Jimmy: Updater for NNPCs that lack pronouns structures. 
+				Based off of $perNPCFix located in VVU -->
+	<<if $pronounsNPCFix isnot 1>>
+		<<for $_npc range $NPCName>>
+			<<if $_npc.pronouns is undefined>>
+				<<generatePronouns $_npc>>
+			<</if>>
+		<</for>>
+		<<set $pronounsNPCFix = 1>>
+	<</if>>
 
 	<<set $_per_keys to Object.keys($per_npc)>>
 	<<if $_per_keys.length gt 0>>
diff --git a/game/base-combat/beast-generation.twee b/game/base-combat/beast-generation.twee
index 3d9d8042fece667796e752d528a65342368194c6..d7066cfc763795663816cc57534f416da3fadefc 100644
--- a/game/base-combat/beast-generation.twee
+++ b/game/base-combat/beast-generation.twee
@@ -4,10 +4,9 @@
 <!-- Example: <<generateBEAST 1 dog m>> would generate NPC 1 as male dog -->
 <!-- Example: <<generateBEAST 2 wolf f>> would generate NPC 2 as female wolf -->
 
-<!-- Checks if endevent was properly used after the last event -->
-<<checkEventNPC `$args[0] - 1`>>
-
 <<set _n to $args[0]-1>>
+<!-- Checks if endevent was properly used after the last event -->
+<<checkEventNPC _n>>
 <<set _type to $args[1]>>
 <<set _gen to $args[2]>>
 <<set _beast_genitals to $args[3]>>
@@ -49,7 +48,7 @@
 
 <<beastattribute _n _type>>
 
-<<pushEventNPC _n>>
+<<run EventSystem.Push($passage, _n, $time)>>
 <</widget>>
 
 <<widget "beastattribute">>
diff --git a/game/base-combat/end.twee b/game/base-combat/end.twee
index 3696d3e9b9a94a27f8ee2602f73aca6cdf43ad9c..a77bef4a6e0281b0e92355b17ce3ef3ae97b54dd 100644
--- a/game/base-combat/end.twee
+++ b/game/base-combat/end.twee
@@ -462,9 +462,7 @@
 <<set $npcnum.splice(0)>>
 <<set $npcrow.splice(0)>>
 <<if $endeventerror is undefined>>
-	<<unset $event>>
-	<<unset $eventslot>>
-	<<unset $eventtime>>
+	<<run EventSystem.Clear()>>
 <</if>>
 <</widget>>
 
@@ -484,21 +482,14 @@
 <<set $NPCList[_i] to clone(setup.baseNPC)>>
 <<if $enemyno gt 0>>
 	<<set $enemyno -= 1>>
-	<<set $enemynomax -= 1>>
 <</if>>
 <<if $endeventerror is undefined>>
-	<<if $eventslot.indexOf(_i) isnot -1>>
-		<<set $event.splice($eventslot.indexOf(_i), 1)>>
-		<<set $eventtime.splice($eventslot.indexOf(_i), 1)>>
-		<<set $eventslot.splice($eventslot.indexOf(_i), 1)>>
-	<</if>>
+	<<run EventSystem.Pop(_i)>>
 <</if>>
-<<if $enemynomax is 0>>
+<<if $enemyno is 0>>
 	<<set $pronoun to 0>>
 	<<if $endeventerror is undefined>>
-		<<unset $event>>
-		<<unset $eventslot>>
-		<<unset $eventtime>>
+		<<run EventSystem.Clear()>>
 	<</if>>
 <</if>>
 <</widget>>
diff --git a/game/base-combat/init.twee b/game/base-combat/init.twee
index 0337563f8ba8ced660efec9a793c6c1737eca518..77e9f1dc75aa26bdab43171cd45993143630fc37 100644
--- a/game/base-combat/init.twee
+++ b/game/base-combat/init.twee
@@ -210,37 +210,11 @@
 	<span class="red">ERROR: beastNEWinit unknown type</span>
 <</if>>
 
-<!-- Jimmy: Loops over _nn (How many beasts you plan to initiate) 
-			Then loops over the NPCList, currently size of 6.
-			If a slot does not define .type (WIP: Plan to make this standard),
-			generate the beast in that slot ID and break the NPCList loop.
-		Variables:
-			$_i is the current iteration of how many beasts to generate.
-			$_j is the NPCList slot index that is being selected for insertion.
--->
-<<set $_j to 0>>
-<!-- Loop from 0 to the number of beasts to create. -->
-<<for $_i = 0; $_i < _nn; $_i++>>
-	<!-- Attempt to insert each NPC into a slot of NPCList -->
-	<<for $_j = $_j; $_j < 6; $_j++>>
-		<<if $NPCList[$_j].type is undefined>>
-			<<set $_j += 1>>
-			<<generateBEAST $_j _tpe _gnn _beast_genitals _beast_monster>>
-			<<break>>
-		<</if>>
-	<</for>>
-<</for>>
-
-<!-- Jimmy: Old iterator code.
-			This was replaced with above because people could insert NPCs before beasts at higher positions.
-			Typically because the beast has to be by itself in encounter combat (For now)
-<<set _offset to $enemyno + 1>>
-<<for _xx = _offset; _xx < _nn + _offset; _xx++>>
+<<for _xx = 1; _xx < _nn+1; _xx++>>
 	<<generateBEAST _xx _tpe _gnn _beast_genitals _beast_monster>>
 <</for>>
-<<unset _offset>> 
--->
 
+<<set $enemyno to _nn>>
 <<set $enemytype to "beast">>
 
 <!-- NG This means if Beast 1 is a monster, they are all monsters -->
diff --git a/game/base-combat/npc-generation.twee b/game/base-combat/npc-generation.twee
index 44b385b29a69ac3cfed2ec05fb6f8872cd1ff758..02029f7311db9e29cae319195d691c3f86256375 100644
--- a/game/base-combat/npc-generation.twee
+++ b/game/base-combat/npc-generation.twee
@@ -6,10 +6,10 @@
 <!-- Example: <<generateNPC 1 a f h 20>> would generate NPC 1 as adult female/herm "demon" monster type-->
 <!-- Latter two examples can only be called via this widget; they are not autogenerated -->
 
-<!-- Checks if endevent was properly used after the last event -->
-<<checkEventNPC `$args[0] - 1`>>
 
 <<set _n to $args[0]-1>>
+<!-- Checks if endevent was properly used after the last event -->
+<<checkEventNPC _n>>
 <<set _status to $args[1]>> /* "t" for teen or "a" for adult */
 <<set _pronoun to $args[2]>>
 <<set _gender to $args[3]>>
@@ -63,7 +63,7 @@
 
 <<npcattribute _n _gender _lvl>>
 
-<<pushEventNPC _n>>
+<<run EventSystem.Push($passage, _n, $time)>>
 <</widget>>
 
 <<widget "generateRole">>
diff --git a/game/base-debug/debug-events.twee b/game/base-debug/debug-events.twee
index bfcc0d5083f71fa2ea3a67fdb31afee365c083d3..51f1d867b4bc5b1a8405ed388a8e4bceaa64baaa 100644
--- a/game/base-debug/debug-events.twee
+++ b/game/base-debug/debug-events.twee
@@ -1,33 +1,27 @@
 :: Widgets Debug Event [widget]
 
-/*  Any widget with the goal to bug-purge events goes here.
-Since I didn't find an appropriate file to put this in, I decided to make my own.
-Feel free to delete this coment at leisure.
-*/
+<!-- Any widget with the goal to bug-purge events goes here.
+	Since I didn't find an appropriate file to put this in, I decided to make my own.
+	Feel free to delete this coment at leisure. -->
 <<widget "checkEventNPC">>
-	<<if ($eventslot isnot undefined and $eventslot.includes($args[0])) or $enemyno gte 6>>
+	<<if (EventSystem.IsSlotTaken($args[0]) and !EventSystem.Disable) or $enemynomax gte 6 or $enemyno gte 6>>
 		<<set $endeventerror to $lastgenerated>>
-		<<endevent phaseless>>
+		<<clearsinglenpc $args[0]>>
+		<!-- <<endevent phaseless>> -->
 	<</if>>
 	<<set $lastgenerated to $passage>>
-	<!-- <<if $enemyno gte 1 and $args[0] is 1>>
-		<<set $endeventerror to $lastgenerated>>
-		<<endevent phaseless>>
-	<</if>> -->
-<</widget>>
-
-<<widget "pushEventNPC">>
-	<<set $event to ensure($event, [])>>
-	<<set $eventslot to ensure($eventslot, [])>>
-	<<set $eventtime to ensure($eventtime, [])>>
-	<<run 
-		ensureIsArray($event).push($passage);
-		ensureIsArray($eventslot).push($args[0]);
-		ensureIsArray($eventtime).push($time);
-	>>
 <</widget>>
 
 <<widget "eventExtraInfo">>
+<!-- Setup useful variables -->
+<<set $_passages = (V.event is undefined 
+	? [] 
+	: V.event.buffer.reduce((prev, cur) => {
+		prev.pushUnique(cur.area[0]);
+		return prev;
+	}, [])
+)>>
+
 <<if _eventalertmajorarea is true>>
 	<span class="red">You are in a major area, which means an NPC escaped!</span>
 	<<if $cheatdisable is "f">>
@@ -37,14 +31,17 @@ Feel free to delete this coment at leisure.
 	<</if>>
 	<<set _eventreason to true>>
 <<elseif _eventalertmajorarea is false>>
-	<span class="green">This NPC was defined in this passage, and is being tested for Debug.</span><<set _eventreason to true>>
+	<span class="green">This NPC was defined in this passage</span><<set _eventreason to true>>
 <<else>>
 	<<if $passage.includes("Street Stalk")>>
 		<span class="green">You are being stalked. Usually this means everything is in order.</span>
 		<<set _eventreason to true>>
 	<</if>>
 	<<if $event isnot undefined>>
-		<<if $passage.includes($event.toString()) or $event.includes($passage)>>
+		<<if $_passages.includes($passage)>>
+			<span class="green">You are in a passage where NPCs were generated.</span>
+			<<set _eventreason to true>>
+		<<elseif $passage.includes($_passages)>>
 			<span class="green">You are in a subpassage from where NPCs were generated. Usually this means they are still in use.</span>
 			<<set _eventreason to true>>
 		<</if>>
@@ -57,19 +54,18 @@ Feel free to delete this coment at leisure.
 <</if>>
 <br><br>
 <h3>NPC information</h3><br>
-$enemyno NPC<<if $enemyno gt 1>>s are<<else>> is<</if>> currently active. Them being:<br><br>
+$enemyno NPC<<if $enemyno gt 1>>s are<<else>> is<</if>> currently active. Max: $enemynomax. Them being:<br><br>
 
 <div class="debug-event-container">
 <<for $_i to 0; $_i lt $NPCList.length; $_i++>>
-	<<if $NPCList[$_i].fullDescription isnot undefined>>
+	<<set $_npc to $NPCList[$_i]>>
+	<<set $_eventNPC to EventSystem.Get($_i)>>
+	<<if $_npc.type isnot undefined and $_eventNPC isnot undefined>>
 		<div class="debug-event-item debug-event-success">
-			ID: $_i | $NPCList[$_i].fullDescription<br>
-			Sex: $NPCList[$_i].gender | Gender: $NPCList[$_i].pronouns.man<br>
-			Description: $NPCList[$_i].description | Role: $NPCList[$_i].role<br>
-			<<if $event isnot undefined>>
-				<hr>
-				Source: <<print $event[$_i]>>, at: <<ampm `Math.floor($eventtime[$_i]/60)` `$eventtime[$_i]%60`>>.<br>
-			<</if>>
+			ID: $_i | $_npc.fullDescription<br>
+			Sex: $_npc.gender | Gender: $_npc.pronouns.man<br>
+			Description: $_npc.description<<if $_npc.role>> | Role: $_npc.role<</if>><br>
+			Source: <<print $_eventNPC.area[0]>>, at: <<ampm `Math.floor($_eventNPC.time / 60)` `$_eventNPC.time % 60`>>.<br>
 		</div>
 	<<else>>
 		<div class="debug-event-item debug-event-empty">
@@ -81,25 +77,37 @@ $enemyno NPC<<if $enemyno gt 1>>s are<<else>> is<</if>> currently active. Them b
 
 <<if $event isnot undefined>>
 	<br>Extra debugging:<br>
-	<<for $_i to 0; $_i lt $event.length; $_i++>>
-		<<print ensure($NPCList[$eventslot[$_i]]?.fullDescription, "No description.")>><br>
-		Defined in passage <<print $event[$_i]>>, at <<ampm `Math.floor($eventtime[$_i]/60)` `$eventtime[$_i]%60`>>.<br>
-		<<for $_j to 0; $_j lt $event.length; $_j++>>
-			<<if $event[$_j] is $event[$_i] and $_i isnot $_j>>
+	<<for $_i to 0; $_i lt $event.buffer.length; $_i++>>
+		<<set $_eventNPC to $event.buffer[$_i]>>
+		<<print ensure($NPCList[$_eventNPC.slot]?.fullDescription, "No description.")>><br>
+		Defined in passage <<print $_eventNPC.area[0]>>, at <<ampm `Math.floor($_eventNPC.time / 60)` `$_eventNPC.time % 60`>>.<br>
+		<<if $_eventNPC.area.length gt 1>>
+			Widget Stack:
+			<<set $_widgetStack to $_eventNPC.area.slice(1)>>
+			<<for $_iStack = 0; $_iStack lt $_widgetStack.length; $_iStack++>>
+				<<print "<<$_widgetStack[$_iStack]>>">><<if $_iStack isnot $_widgetStack.length - 1>>, <</if>>
+			<</for>>
+			<br>
+		<</if>>
+		<!-- Check other event NPCs for linked passages -->
+		<<for $_j to 0; $_j lt $event.buffer.length; $_j++>>
+			<<set $_eventNPC2 to $event.buffer[$_j]>>
+			<<if $_i isnot $_j and $_eventNPC.area[0] is $_eventNPC2.area[0]>>
 				<<if _eventnumberinpassage is undefined>>
 					<<set _eventnumberinpassage to 0>>
 				<</if>>
 				<<set _eventnumberinpassage += 1>>
 			<</if>>
 		<</for>>
+		<!-- Check other event NPCs for linked passages -->
 		<<if _eventnumberinpassage isnot undefined>>
-			<<print _eventnumberinpassage>> other NPC<<if _eventnumberinpassage isnot 1>>s<</if>> have also been defined in passage <<print $event[$_i]>>.<br>
+			<<print _eventnumberinpassage>> other NPC<<if _eventnumberinpassage isnot 1>>s<</if>> have also been defined in passage <<print $_eventNPC.area[0]>>.<br>
 			<<unset _eventnumberinpassage>>
 		<</if>>
-		Set in slot <<print $eventslot[$_i]>> of $$NPCList.<br>
-		<<for $_j to 0; $_j lt $event.length; $_j++>>
-			<<if $eventslot[$_j] is $eventslot[$_i] and $_i isnot $_j>>
-				<span class="red">This NPC has been overwritten or overwrote another one in slot <<print $eventslot[$eventslot[$_i]]>>!</span><br>
+		Set in slot <<print $_eventNPC.slot>> of $$NPCList.<br>
+		<<for $_j to 0; $_j lt $event.buffer.length; $_j++>>
+			<<if $_i isnot $_j and $_eventNPC.slot is $_eventNPC.slot[$_j]>>
+				<span class="red">This NPC has been overwritten or overwrote another one in slot <<print $event.slot[$_eventNPC.slot]>>!</span><br>
 				<<break>>
 			<</if>>
 		<</for>>
diff --git a/game/base-debug/debug.twee b/game/base-debug/debug.twee
index 77cb3c832cb43203cd4ccf93b4ff51d4852ef43e..60ca3867d4d5b3cf15c3b428950201028965b4ba 100644
--- a/game/base-debug/debug.twee
+++ b/game/base-debug/debug.twee
@@ -762,4 +762,11 @@ Swarm Encounters:
 	<<swarminit "worms" "container" "shaking" "shatter" "steady" 1 9>>
 <</link>>
 <br><br>
+
+Event Debugging:<br>
+<<link [[Test NPC Insertion|NPCInsertionAssert]]>><</link>>
 <</widget>>
+
+:: NPCInsertionAssert
+Generating two NPCs both at slot 0.
+<<generate1>><<generate1>>
\ No newline at end of file
diff --git a/game/base-system/caption.twee b/game/base-system/caption.twee
index 50f011164c303a78e93b27a6c6de3637f224dc91..b33dea3cd86f435ced7cd26e4e94de2ceec36302 100644
--- a/game/base-system/caption.twee
+++ b/game/base-system/caption.twee
@@ -257,13 +257,13 @@
 	<!-- Event debug button - Shows an overlay stored in debug-events.twee. -->
 	<<if $event isnot undefined and $debugdisable is "f">>
 		<<set _temp to "<span class='yellow'>SHOW EVENT INFO</span>">>
-		<<if $event[0] is $passage>>
+		<<if EventSystem.Get(0).area[0] is $passage>>
 			<<set _eventalertmajorarea to false>>
 			<<set _temp to "<span class='green'>EVENT ACTIVE</span>">>
 		<<elseif setup.majorAreas.includes($passage)>>
 			<<set _eventalertmajorarea to true>>
 			<<set _temp to "<span class='red'>EVENT ACTIVE</span>">>
-		<<elseif ensureIsArray($event).length is 1 and ["Forest Cabin", "Eden Cabin", "Eden Clearing"].includes($event[0])>>
+		<<elseif $event.buffer.map(e => e.area[0]).length is 1 and ["Forest Cabin", "Eden Cabin", "Eden Clearing"].includes(EventSystem.Get(0).area[0])>>
 			<<set _temp to "<span class='green'>EVENT ACTIVE</span>">>
 		<</if>>
 		<<button _temp>><<overlayReplace "eventExtraInfo">><</button>>
diff --git a/game/base-system/named-npcs.twee b/game/base-system/named-npcs.twee
index 9fa3b60ebda004bc2efefbbda49822ca277e6ccd..5d1234ee5911d5c99e51ea9d9fe0f9f22c7cfff5 100644
--- a/game/base-system/named-npcs.twee
+++ b/game/base-system/named-npcs.twee
@@ -60,16 +60,12 @@
 		<<set $enemyno -= 1>>
 		<<set $enemynomax -= 1>>
 		<<if $endeventerror is undefined>>
-			<<set $event.splice($eventslot.indexOf(_ii), 1)>>
-			<<set $eventtime.splice($eventslot.indexOf(_ii), 1)>>
-			<<set $eventslot.splice($eventslot.indexOf(_ii), 1)>>
+			<<run EventSystem.Pop(_ii)>>
 		<</if>>
 		<<if $enemyno is 0>>
 			<<set $pronoun to 0>>
 			<<if $endeventerror is undefined>>
-				<<unset $event>>
-				<<unset $eventslot>>
-				<<unset $eventtime>>
+				<<run EventSystem.Clear()>>
 			<</if>>
 		<</if>>
 		<<set $npc.splice(_leindex, 1)>>
@@ -711,18 +707,7 @@ alternative way to write that:
 	<<set $monster to 0>>
 <</if>>
 
-<<if $event is undefined>>
-	<<set $event to []>>
-<</if>>
-<<set $event.push($passage)>>
-<<if $eventslot is undefined>>
-	<<set $eventslot to []>>
-<</if>>
-<<set $eventslot.push(_npcno)>>
-<<if $eventtime is undefined>>
-	<<set $eventtime to []>>
-<</if>>
-<<set $eventtime.push($time)>>
+<<run EventSystem.Push($passage, _npcno, $time)>>
 <<set $index to _npcno>>
 <</widget>>
 
diff --git a/game/base-system/persistent-npcs.twee b/game/base-system/persistent-npcs.twee
index 428be868f71ced53c4e4acd9a67512a78cd81df4..dc3aca224aae2cd6741770e275053ada311cd2ce 100644
--- a/game/base-system/persistent-npcs.twee
+++ b/game/base-system/persistent-npcs.twee
@@ -29,8 +29,7 @@
 	<<else>>
 		<<set $monster to 0>>
 	<</if>>
-	<<pushEventNPC $args[0]>>
-	<<set $enemynomax to $enemyno>>
+	<<run EventSystem.Push($passage, $args[0], $time)>>
 <</if>>
 <</widget>>
 
diff --git a/game/overworld-forest/loc-wolfpack/widgets.twee b/game/overworld-forest/loc-wolfpack/widgets.twee
index 8ce34daab017d7713b43e133f63921935bea5812..4aa27e8548a10eda1fad244e9a2bf45ef20afa99 100644
--- a/game/overworld-forest/loc-wolfpack/widgets.twee
+++ b/game/overworld-forest/loc-wolfpack/widgets.twee
@@ -90,6 +90,7 @@
 				<<destinationwolfcave>>
 			<</addinlineevent>>
 			<<addinlineevent "wolve mating rank">>
+				<<endevent>>
 				<<beastNEWinit 2 wolf>>
 				A low ranking <<print $combatTrain.beastTypes[0]>> approaches you wishing to mate. A more dominant <<print $combatTrain.beastTypes[1]>> tries to steal your attention.
 				<br><br>
diff --git a/game/overworld-town/loc-beach/events.twee b/game/overworld-town/loc-beach/events.twee
index 989b87c234bacc8e31010db5cfe9a1db754255ce..ae521151295d80475a21da69b098fedf8fa1f433 100644
--- a/game/overworld-town/loc-beach/events.twee
+++ b/game/overworld-town/loc-beach/events.twee
@@ -821,19 +821,16 @@ Having come this far, you submit to the collar being placed round your neck. You
 	<br><br>
 	You are led deeper into the dunes. You walk for several minutes, conscious of just how exposed and vulnerable you are. Your captors make no attempt to hide how much they enjoy being in a position of power over you, and constantly leer at your body, knowing there's nothing you can do to stop them.
 	<br><br>
-	<!-- Modified for Monster People -->
-
-	<<saveNPC 0 beach_abduction_dog_1>>
-	<<saveNPC 1 beach_abduction_dog_2>>
-	<<endevent>>
-	<<beastNEWinit 1 dog>>
-
 	<<if $rng gte 51 and ($monster is 1 or $bestialitydisable is "f")>>
-		<<loadNPC 1 beach_abduction_dog_1>>
-		<<loadNPC 2 beach_abduction_dog_2>>
+		<<saveNPC 0 "beach_abduction_dog_1">>
+		<<saveNPC 1 "beach_abduction_dog_2">>
+		<<endevent>>
+		<<loadNPC 1 "beach_abduction_dog_1">>
+		<<loadNPC 2 "beach_abduction_dog_2">>
+		<<clearNPC "beach_abduction_dog_1">>
+		<<clearNPC "beach_abduction_dog_2">>
+		<<beastNEWinit 1 dog>>
 
-		<<clearNPC beach_abduction_dog_1>>
-		<<clearNPC beach_abduction_dog_2>>
 		You come to a relatively flat area, surrounded by dunes on all sides, shielding it from view. In the centre is a <<beasttype>>, <<bhis>> leash tied to a wooden post. At the sight of you <<bhe>> leaps to <<bhis>> feet, straining the leash in a bid to reach you.
 		<<if $monster is 1>>
 			<<bHis>> nude body is on full display for all to see, but <<bhe>> doesn't seem all too phased by it. <<bHe>> seems oddly well-groomed for a <<beasttype>>, despite the state <<bhe>>'s in. <<bHe>> paws at the air in an attempt to reach you, and <<bhe>>'s almost successful.
@@ -849,12 +846,6 @@ Having come this far, you submit to the collar being placed round your neck. You
 		<<link [[Allow yourself to be led over|Beach Abduction Dog]]>><<set $molestationstart to 1>><<set $phase to 1>><</link>>
 		<br>
 	<<else>>
-		<<endevent>>
-		<<loadNPC 0 beach_abduction_dog_1>>
-		<<loadNPC 1 beach_abduction_dog_2>>
-
-		<<clearNPC beach_abduction_dog_1>>
-		<<clearNPC beach_abduction_dog_2>>
 		<<generatey3>><<generatey4>><<generatey5>><<generatey6>>You come to a relatively flat area, surrounded by dunes on all sides, shielding it from view. Four teenagers sit smoking in the centre. Your feelings of humiliation reach a new height as the new pairs of eyes see you in your shameful situation. Their initial shock quickly subsides, leaving a bare and primal lust.
 		<br><br>
 		The <<person2>><<person>> leads you into the middle of the group, their eyes feasting on every inch of your body. "We found this piece of trash near the beach. Can't believe anyone would just leave it laying around, no respect at all," the <<person1>><<person>> <<if $worn.genitals.type.includes("chastity")>>attempts to break<<else>>starts fondling<<set $worn.genitals.integrity -= 50>><</if>> your <<genitals>> in front of everyone, causing your breath to catch in your chest. The rest of the group take the cue. Arms reach out from all around you, each wanting their share.
diff --git a/game/overworld-town/loc-danube-homes/work.twee b/game/overworld-town/loc-danube-homes/work.twee
index e4efaeabba3293d034616918fa29813715fadff5..b06c8dbffd3cbbc0ba084d46aad9cfbbebeddb8e 100644
--- a/game/overworld-town/loc-danube-homes/work.twee
+++ b/game/overworld-town/loc-danube-homes/work.twee
@@ -1385,7 +1385,6 @@ You continue your work. Now wary, you stay far from the denser foliage. After an
 	<<violence 1>>
 	<<neutral 1>>
 	<<molested>>
-	<<beastNEWinit 1 dog>>
 	<<beastCombatInit>>
 	<<set $phase to 3>>
 <</if>>
@@ -1516,9 +1515,9 @@ You continue your work. Now wary, you stay far from the denser foliage. After an
 
 	<<clotheson>>
 
-	A £50 is pressed into your hand.
+	A <<moneyGain 50>> is pressed into your hand.
 	<br>
-	"Brutus needed that. <<moneyGain 50>>'s the going rate for a bitch, so as far I'm concerned we're even. Get out of here."
+	"Brutus needed that. <<moneyGainDisplay 50>>'s the going rate for a bitch, so as far I'm concerned we're even. Get out of here."
 	<br><br>
 
 	You are pushed into the street and the door slams behind. <<tearful>> you gather yourself.
diff --git a/game/overworld-town/loc-docks/main.twee b/game/overworld-town/loc-docks/main.twee
index a7c25bea5d96a0525526cd859d7b3d743eaebf3f..820edee2ec25bf492d32cd5e05e53cac8426bd61 100644
--- a/game/overworld-town/loc-docks/main.twee
+++ b/game/overworld-town/loc-docks/main.twee
@@ -846,7 +846,7 @@ You awaken naked on a chair. Lengths of rope criss-cross your body and tie you d
 <<generate1>><<generate2>><<generate3>><<person2>>"It's not fair," a <<person>> says. <<He>> sits opposite you with <<his>> arms folded. "You set it up wrong."
 <br><br>
 
-A dart thuds into the board. The <<person1>><<person>> who threw it laughs. "Yeah yeah," <<he>> says. "We're all using the same board, if you haven't noticed." <<He>> throws another dart. "I win." <<He>> turns to a <<generate3>><<person3>><<person>>. "Unless you score perfect."
+A dart thuds into the board. The <<person1>><<person>> who threw it laughs. "Yeah yeah," <<he>> says. "We're all using the same board, if you haven't noticed." <<He>> throws another dart. "I win." <<He>> turns to a <<person3>><<person>>. "Unless you score perfect."
 <br><br>
 
 The <<person>> stands and takes <<his>> position in front of the board as the <<person1>><<person>> approaches to retrieve <<his>> darts. "Hey," <<he>> says. "<<pShes>> awake."
diff --git a/game/overworld-town/loc-prison/events.twee b/game/overworld-town/loc-prison/events.twee
index fc1352bfe854021c582c712252649f9dff2f34c5..6b579712f3cd4d5c384bc305e611bd0a6abadcf8 100644
--- a/game/overworld-town/loc-prison/events.twee
+++ b/game/overworld-town/loc-prison/events.twee
@@ -57,7 +57,7 @@ You walk closer. <<person2>><<tattooed_inmate 0 cap>> grabs your arm and pulls y
 You turn away. "Are you deaf <<bitch>>?" <<tattooed_inmate 1>> snarls. "You're coming with us."
 <br><br>
 
-"No <<he>> ain't," says an unfamiliar voice from the side. <<tattooed_inmate 1 cap>> and <<his>> goons spin in alarm. <<scarred_inmate 0 cap>> walks closer, a <<person5>><<person>> and <<person6>><<person>> on either side.
+"No <<pshe>> ain't," says an unfamiliar voice from the side. <<tattooed_inmate 1 cap>> and <<his>> goons spin in alarm. <<scarred_inmate 0 cap>> walks closer, a <<person5>><<person>> and <<person6>><<person>> on either side.
 <br><br>
 
 <<link [[Next|Prison Attention Gangs]]>><</link>>
diff --git a/game/overworld-town/loc-prison/main.twee b/game/overworld-town/loc-prison/main.twee
index 1f0c14eb168d8ee2a2a6991c98e26a99fd618e0c..31c3dfb258cf6fd46b3aee15ef7a174f3cf1578e 100644
--- a/game/overworld-town/loc-prison/main.twee
+++ b/game/overworld-town/loc-prison/main.twee
@@ -1575,7 +1575,6 @@ You close the door behind you, and walk towards the light, emerging on a beach.
 :: Prison Yard Speak
 <<effects>>
 
-
 <<generate_veteran_guard 0>><<person1>>
 <<generate2>>
 <<if $prison.veteran gte 60 and !$NPCList[0].name_known>>
@@ -1639,10 +1638,10 @@ Panting, <<veteran_guard 0>> steps away from the curled <<person2>><<person>>. Y
     <<link [[Next|Prison Spire Intro]]>><<set $prison.spire_intro to 1>><<set $prison.birds to 0>><</link>>
     <br>
 <<else>>
-    <<generate_anxious_guard 0>><<person1>><<beastNEWinit 5 "hawk">>
+    <<beastNEWinit 5 "hawk">><<generate_anxious_guard 5>><<person1>>
     You are in the small cabin atop the spire.
     <<if $prison.schedule is "work">>
-        <<anxious_guard 0 cap>> sits in front of several security monitors, but <<person1>><<his>> eyes follow the <<person2>><<beastsplural 1>> outside.
+        <<anxious_guard 5 cap>> sits in front of several security monitors, but <<person6>><<his>> eyes follow the <<person2>><<beastsplural 1>> outside.
     <<else>>
         You watch the <<person2>><<beastsplural 1>> through a window.
     <</if>>
diff --git a/game/overworld-town/loc-prison/widgets.twee b/game/overworld-town/loc-prison/widgets.twee
index b20c1908bfbdc38ef7d966ea880e86788720d1cd..bb6c695b22498a5777a020a2faeb40e2da3a62c3 100644
--- a/game/overworld-town/loc-prison/widgets.twee
+++ b/game/overworld-town/loc-prison/widgets.twee
@@ -336,31 +336,39 @@
 <</widget>>
 
 <<widget "save_relaxed_guard">>/*The right NPC fill $NPCList[0] slot */
-<<set $NPCList[0].fullDescription to $NPCList[0].name>>
-<<clearNPC "relaxed_guard">>
-<<saveNPC 0 "relaxed_guard">>
-<<prison_feat_check>>
+<<if $NPCList[0].role is "guard">>
+    <<set $NPCList[0].fullDescription to $NPCList[0].name>>
+    <<clearNPC "relaxed_guard">>
+    <<saveNPC 0 "relaxed_guard">>
+    <<prison_feat_check>>
+<</if>>
 <</widget>>
 
 <<widget "save_anxious_guard">>
-<<set $NPCList[0].fullDescription to $NPCList[0].name>>
-<<clearNPC "anxious_guard">>
-<<saveNPC 0 "anxious_guard">>
-<<prison_feat_check>>
+<<if $NPCList[0].role is "guard">>
+    <<set $NPCList[0].fullDescription to $NPCList[0].name>>
+    <<clearNPC "anxious_guard">>
+    <<saveNPC 0 "anxious_guard">>
+    <<prison_feat_check>>
+<</if>>
 <</widget>>
 
 <<widget "save_veteran_guard">>
-<<set $NPCList[0].fullDescription to $NPCList[0].name>>
-<<clearNPC "veteran_guard">>
-<<saveNPC 0 "veteran_guard">>
-<<prison_feat_check>>
+<<if $NPCList[0].role is "guard">>
+    <<set $NPCList[0].fullDescription to $NPCList[0].name>>
+    <<clearNPC "veteran_guard">>
+    <<saveNPC 0 "veteran_guard">>
+    <<prison_feat_check>>
+<</if>>
 <</widget>>
 
 <<widget "save_methodical_guard">>
-<<set $NPCList[0].fullDescription to $NPCList[0].name>>
-<<clearNPC "methodical_guard">>
-<<saveNPC 0 "methodical_guard">>
-<<prison_feat_check>>
+<<if $NPCList[0].role is "guard">>
+    <<set $NPCList[0].fullDescription to $NPCList[0].name>>
+    <<clearNPC "methodical_guard">>
+    <<saveNPC 0 "methodical_guard">>
+    <<prison_feat_check>>
+<</if>>
 <</widget>>
 
 <<widget "save_scarred_inmate">>
diff --git a/game/overworld-town/loc-prison/wren.twee b/game/overworld-town/loc-prison/wren.twee
index 5b78ead8d8f2e98bf4acf4341dc7f976313ffa51..0a7588da0ad6719855fbb1158091e63418c12c30 100644
--- a/game/overworld-town/loc-prison/wren.twee
+++ b/game/overworld-town/loc-prison/wren.twee
@@ -305,7 +305,7 @@ Wren hands you a small hammer, barely the size of your thumb. "Hope you weren't
 <span class="gold">You now have a small hammer.</span>
 <br><br>
 
-<<link [[Next|Prison Yard]]>><</link>>
+<<link [[Next|Prison Yard]]>><<endevent>><</link>>
 <br>
 
 
@@ -318,7 +318,7 @@ Wren hands you a small hammer, barely the size of your thumb. "Hope you weren't
 <span class="gold">You now have a poster on your cell wall.</span>
 <br><br>
 
-<<link [[Next|Prison Yard]]>><</link>>
+<<link [[Next|Prison Yard]]>><<endevent>><</link>>
 <br>
 
 :: Prison Wren Ask
diff --git a/game/overworld-town/loc-school/fame.twee b/game/overworld-town/loc-school/fame.twee
index 9cf6c4143191b4aefc37c928e6b95a4e0f2bb5be..e7226abcb6944475ecb0f1a89a4d03b6d781a12d 100644
--- a/game/overworld-town/loc-school/fame.twee
+++ b/game/overworld-town/loc-school/fame.twee
@@ -59,7 +59,7 @@ Leighton starts tearing them down, but <<he>> puts them in <<his>> own pocket. <
 :: School Fame Blackmail
 <<set $outside to 0>><<set $location to "school">><<schooleffects>><<effects>>
 
-You follow <<npc Leighton>><<person1>> into <<his>> office and stand in front of <<his>> desk while <<he>> takes <<his>> seat. <<He>> reclines and examines you.
+You follow <<person1>> into <<his>> office and stand in front of <<his>> desk while <<he>> takes <<his>> seat. <<He>> reclines and examines you.
 <br><br>
 
 "I have something interesting," <<he>> says, an odd smile on <<his>> face. "Pictures. Of you. Doing such lewd things. Pictures that everyone in school could see." <<He>> leans forward and pulls a camera from a drawer. "Unless you cooperate. All I want is a little photoshoot. No one has to see a thing."
@@ -224,7 +224,7 @@ After a while <<he>> puts down <<his>> camera. "Don't go anywhere just yet," <<h
 Leighton starts tearing them down, but <<he>> puts them in <<his>> own pocket. <<He>> doesn't acknowledge you. <<He>> removes the last of the pictures and leaves you stood alone in the corridor.
 <br><br>
 
-<<link [[Next|Hallways]]>><<set $eventskip to 1>><</link>>
+<<link [[Next|Hallways]]>><<endevent>><<set $eventskip to 1>><</link>>
 <br>
 
 :: School Fame Gangbang Finish
diff --git a/game/overworld-town/loc-school/hallways.twee b/game/overworld-town/loc-school/hallways.twee
index 7fbf2c8b06c41739f1b776c96665c9b7e7b55205..f0b183d9301dd7ade8d5bf3e4d8f51234c016f31 100644
--- a/game/overworld-town/loc-school/hallways.twee
+++ b/game/overworld-town/loc-school/hallways.twee
@@ -1528,5 +1528,5 @@ You give the <<persons>> ass a swift spank as you pass, eliciting laughter from
 	<br><br>
 <</if>>
 
-<<link [[Next|Hallways]]>><<endevent>><</link>>
+<<link [[Next|Hallways]]>><<endevent>><<set $eventskip to 1>><</link>>
 <br>
diff --git a/game/overworld-town/loc-school/widgets-events.twee b/game/overworld-town/loc-school/widgets-events.twee
index 4571fab8207e7fca8a65ed0d4a7af2ffd155f2b7..055e224ad5546deb29c88607c50577f49219b55e 100644
--- a/game/overworld-town/loc-school/widgets-events.twee
+++ b/game/overworld-town/loc-school/widgets-events.twee
@@ -635,7 +635,7 @@ Other students ignore what is happening, or watch in amusement.
 <</widget>>
 
 <<widget "eventsplayground">>
-
+<!-- Jimmy TODO: Convert this to use the macros: <<cleareventpool>>, <<addinlineevent>> and <<runeventpool>>. -->
 <<if $schoolstate isnot "early" and $schoolstate isnot "late" and $schoolstate isnot "earlynoschool" and $schoolstate isnot "latenoschool" and $schoolstate isnot "daynoschool">>
 
 	<<if $exposed gte 1>>
diff --git a/game/overworld-underground/loc-underground/events.twee b/game/overworld-underground/loc-underground/events.twee
index 9d98401b53690b3c8207f062daad861c2f6f4402..f21f7f14743ce767ff428ffcb03903134301bb91 100644
--- a/game/overworld-underground/loc-underground/events.twee
+++ b/game/overworld-underground/loc-underground/events.twee
@@ -774,8 +774,6 @@ You run as fast you can. You hear the <<victimgirls>> scream as they are caught,
 	"Looks like <<bhe 0>> likes you," you hear the <<person>> say as <<he>> catches up. <<He>> is not alone, much of the crowd follows behind <<him>>. "And it's only fair <<bhe 0>> gets to do as <<bhe 0>> likes with <<bhis 0>> quarry." The crowd forms a circle around you.
 	<br><br>
 
-	<<clearsinglenpc 1>>
-
 	<<link [[Next|Underground Hunt Dog]]>><<set $molestationstart to 1>><</link>>
 	<br>
 	<<else>>