diff --git a/source/games/duke/src/dispatch.cpp b/source/games/duke/src/dispatch.cpp
index eebc1e17c..d8f31f59d 100644
--- a/source/games/duke/src/dispatch.cpp
+++ b/source/games/duke/src/dispatch.cpp
@@ -84,8 +84,6 @@ void checktimetosleep_d(DDukeActor* actor);
 void checktimetosleep_r(DDukeActor* actor);
 void move_d(DDukeActor* i, int g_p, int g_x);
 void move_r(DDukeActor* i, int g_p, int g_x);
-int spawn_d(int j, int pn);
-int spawn_r(int j, int pn);
 void incur_damage_d(struct player_struct* p);
 void incur_damage_r(struct player_struct* p);
 void shoot_d(DDukeActor* i, int atwith);
diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h
index bb9caa779..f6389be0c 100644
--- a/source/games/duke/src/duke3d.h
+++ b/source/games/duke/src/duke3d.h
@@ -99,7 +99,6 @@ struct Dispatcher
 	void (*respawnhitag)(DDukeActor* g_sp);
 	void (*checktimetosleep)(DDukeActor* actor);
 	void (*move)(DDukeActor* i, int g_p, int g_x);
-	int (*spawn)(int j, int pn);
 
 	// player
 	void (*incur_damage)(struct player_struct* p);
diff --git a/source/games/duke/src/dukeactor.h b/source/games/duke/src/dukeactor.h
index 89750179e..f13329cbc 100644
--- a/source/games/duke/src/dukeactor.h
+++ b/source/games/duke/src/dukeactor.h
@@ -157,11 +157,6 @@ inline int S_PlaySound3D(int num, DDukeActor * spriteNum, const vec3_t* pos, int
 	return S_PlaySound3D(num, spriteNum ? spriteNum->GetIndex() : -1, pos, channel, flags);
 }
 
-inline DDukeActor* EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s, signed char s_xr, signed char s_yr, short s_a, short s_ve, int s_zv, DDukeActor* Owner, signed char s_ss)
-{
-	return &hittype[EGS(whatsect, s_x, s_y, s_z, s_pn, s_s, s_xr, s_yr, s_a, s_ve, s_zv, Owner ? Owner->GetIndex() : -1, s_ss)];
-}
-
 inline int ActorToScriptIndex(DDukeActor* a)
 {
 	if (!a) return -1;
@@ -180,9 +175,12 @@ inline bool wallswitchcheck(DDukeActor* s)
 	return !!(tileinfo[s->s.picnum].flags & TFLAG_WALLSWITCH);
 }
 
+int spawn_d(int j, int pn);
+int spawn_r(int j, int pn);
+
 inline DDukeActor* spawn(DDukeActor* spawner, int type)
 {
-	int i = fi.spawn(spawner ? spawner->GetIndex() : -1, type);
+	int i = (isRR()? spawn_r : spawn_d)(spawner ? spawner->GetIndex() : -1, type);
 	return i == -1 ? nullptr : &hittype[i];
 }
 
diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h
index fd4d589d2..e452fb25b 100644
--- a/source/games/duke/src/funct.h
+++ b/source/games/duke/src/funct.h
@@ -175,7 +175,7 @@ int furthestangle(DDukeActor* snum, int angDiv);
 void getglobalz(DDukeActor* s);
 void OnEvent(int id, int pnum = -1, DDukeActor* snum = nullptr, int dist = -1);
 
-short EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s, signed char s_xr, signed char s_yr, short s_a, short s_ve, int s_zv, short s_ow, signed char s_ss);
+DDukeActor* EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s, signed char s_xr, signed char s_yr, short s_a, short s_ve, int s_zv, DDukeActor* s_ow, signed char s_ss);
 void ceilingglass(DDukeActor* snum, int sectnum, int cnt);
 void spriteglass(DDukeActor* snum, int cnt);
 void lotsofcolourglass(DDukeActor* snum, int wallNum, int cnt);
@@ -187,9 +187,9 @@ void addspritetodelete(int spnum=0);
 void checkavailinven(struct player_struct* p);
 int initspriteforspawn(int j, int pn, const std::initializer_list<int> &excludes);
 void spawninitdefault(DDukeActor* actj, DDukeActor* act);
-void spawntransporter(int j, int i, bool beam);
-int spawnbloodpoolpart1(int j, int i);
-void initfootprint(int j, int i);
+void spawntransporter(DDukeActor* actj, DDukeActor* acti, bool beam);
+int spawnbloodpoolpart1(DDukeActor* actj, DDukeActor* acti);
+void initfootprint(DDukeActor* actj, DDukeActor* acti);
 void initshell(int j, int i, bool isshell);
 void initcrane(int j, int i, int CRANEPOLE);
 void initwaterdrip(int j, int i);
diff --git a/source/games/duke/src/premap_d.cpp b/source/games/duke/src/premap_d.cpp
index d4eb575e5..e07263069 100644
--- a/source/games/duke/src/premap_d.cpp
+++ b/source/games/duke/src/premap_d.cpp
@@ -317,7 +317,7 @@ void prelevel_d(int g)
 		{
 			if (spr->picnum == SECTOREFFECTOR && spr->lotag == SE_14_SUBWAY_CAR)
 				continue;
-			fi.spawn(-1, i);
+			spawn(nullptr, i);
 		}
 	}
 
@@ -327,7 +327,7 @@ void prelevel_d(int g)
 		if (spr->statnum < MAXSTATUS)
 		{
 			if (spr->picnum == SECTOREFFECTOR && spr->lotag == SE_14_SUBWAY_CAR)
-				fi.spawn(-1, i);
+				spawn(nullptr, i);
 		}
 	}
 	lotaglist = 0;
diff --git a/source/games/duke/src/sectors_d.cpp b/source/games/duke/src/sectors_d.cpp
index 3560ad414..1581423ca 100644
--- a/source/games/duke/src/sectors_d.cpp
+++ b/source/games/duke/src/sectors_d.cpp
@@ -187,7 +187,7 @@ void animatewalls_d(void)
 
 void operaterespawns_d(int low)
 {
-	int i, j;
+	int i;
 
 	StatIterator it(STAT_FX);
 	while ((i = it.NextIndex()) >= 0)
@@ -197,8 +197,8 @@ void operaterespawns_d(int low)
 		case RESPAWN:
 			if (badguypic(sprite[i].hitag) && ud.monsters_off) break;
 
-			j = fi.spawn(i, TRANSPORTERSTAR);
-			sprite[j].z -= (32 << 8);
+			auto j = spawn(&hittype[i], TRANSPORTERSTAR);
+			j->s.z -= (32 << 8);
 
 			sprite[i].extra = 66 - 12;   // Just a way to killit
 			break;
diff --git a/source/games/duke/src/sectors_r.cpp b/source/games/duke/src/sectors_r.cpp
index f4a841a72..cbec5aa24 100644
--- a/source/games/duke/src/sectors_r.cpp
+++ b/source/games/duke/src/sectors_r.cpp
@@ -302,7 +302,7 @@ void animatewalls_r(void)
 
 void operaterespawns_r(int low)
 {
-	int i, j;
+	int i;
 
 	StatIterator it(STAT_FX);
 	while ((i = it.NextIndex()) >= 0)
@@ -310,13 +310,15 @@ void operaterespawns_r(int low)
 		if (sprite[i].lotag == low) switch (sprite[i].picnum)
 		{
 		case RESPAWN:
+		{
 			if (badguypic(sprite[i].hitag) && ud.monsters_off) break;
 
-			j = fi.spawn(i, TRANSPORTERSTAR);
-			sprite[j].z -= (32 << 8);
+			auto j = spawn(&hittype[i], TRANSPORTERSTAR);
+			j->s.z -= (32 << 8);
 
 			sprite[i].extra = 66 - 12;   // Just a way to killit
 			break;
+		}
 		case RRTILE7424:
 			if (isRRRA() && !ud.monsters_off)
 				changespritestat(i, 119);
diff --git a/source/games/duke/src/spawn.cpp b/source/games/duke/src/spawn.cpp
index 9373d8c02..e6112a3c5 100644
--- a/source/games/duke/src/spawn.cpp
+++ b/source/games/duke/src/spawn.cpp
@@ -48,7 +48,7 @@ BEGIN_DUKE_NS
 //
 //---------------------------------------------------------------------------
 
-short EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s, signed char s_xr, signed char s_yr, short s_a, short s_ve, int s_zv, short s_ow, signed char s_ss) 
+DDukeActor* EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s, signed char s_xr, signed char s_yr, short s_a, short s_ve, int s_zv, DDukeActor* s_ow, signed char s_ss) 
 {
 	//if (isRR() && s_ow < 0 && !force)	// should never happen, the only owner-less spawn outside of map start is for the Holoduke, which is Duke only
 		//return 0;
@@ -77,7 +77,6 @@ short EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s
 	s->ang = s_a;
 	s->xvel = s_ve;
 	s->zvel = s_zv;
-	s->owner = s_ow;
 	s->xoffset = 0;
 	s->yoffset = 0;
 	s->yvel = 0;
@@ -85,21 +84,26 @@ short EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s
 	s->pal = 0;
 	s->lotag = 0;
 
-	act->picnum = sprite[s_ow].picnum;
-
 	act->lastvx = 0;
 	act->lastvy = 0;
 
 	act->timetosleep = 0;
 	act->actorstayput = -1;
 	act->extra = -1;
-	act->owner = s_ow;
 	act->cgg = 0;
 	act->movflag = 0;
 	act->tempang = 0;
 	act->dispicnum = 0;
-	act->floorz = hittype[s_ow].floorz;
-	act->ceilingz = hittype[s_ow].ceilingz;
+	act->SetHitOwner(s_ow);
+	act->SetOwner(s_ow);
+
+	if (s_ow)
+	{
+		act->picnum = s_ow->s.picnum;
+		act->floorz = s_ow->floorz;
+		act->ceilingz = s_ow->ceilingz;
+	}
+
 	memset(act->temp_data, 0, sizeof(act->temp_data));
 	if (actorinfo[s_pn].scriptaddress)
 	{
@@ -121,7 +125,7 @@ short EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s
 	spriteext[i] = {};
 	spritesmooth[i] = {};
 
-	return(i);
+	return act;
 }
 
 
@@ -133,16 +137,17 @@ short EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s
 
 int initspriteforspawn(int j, int pn, const std::initializer_list<int> &excludes)
 {
-	int i;
 	spritetype* sp;
 	int* t;
+	int i;
 
 	if (j >= 0)
 	{
-		i = EGS(sprite[j].sectnum, sprite[j].x, sprite[j].y, sprite[j].z, pn, 0, 0, 0, 0, 0, 0, j, 0);
-		hittype[i].picnum = sprite[j].picnum;
-		sp = &sprite[i];
-		t = hittype[i].temp_data;
+		auto spawned = EGS(sprite[j].sectnum, sprite[j].x, sprite[j].y, sprite[j].z, pn, 0, 0, 0, 0, 0, 0, &hittype[j], 0);
+		spawned->picnum = sprite[j].picnum;
+		sp = &spawned->s;
+		t = spawned->temp_data;
+		i = spawned->GetIndex();
 	}
 	else
 	{
@@ -293,11 +298,11 @@ void spawninitdefault(DDukeActor* actj, DDukeActor *act)
 //
 //---------------------------------------------------------------------------
 
-void spawntransporter(int j, int i, bool beam)
+void spawntransporter(DDukeActor *actj, DDukeActor* acti, bool beam)
 {
-	if (j == -1) return;
-	auto sp = &sprite[i];
-	auto spj = &sprite[j];
+	if (actj == nullptr) return;
+	auto sp = &acti->s;
+	auto spj = &actj->s;
 	if (beam)
 	{
 		sp->xrepeat = 31;
@@ -325,9 +330,9 @@ void spawntransporter(int j, int i, bool beam)
 	sp->ang = spj->ang;
 
 	sp->xvel = 128;
-	changespritestat(i, STAT_MISC);
-	ssp(i, CLIPMASK0);
-	setsprite(i, sp->x, sp->y, sp->z);
+	changespritestat(acti, STAT_MISC);
+	ssp(acti, CLIPMASK0);
+	setsprite(acti, sp->x, sp->y, sp->z);
 }
 
 //---------------------------------------------------------------------------
@@ -336,9 +341,9 @@ void spawntransporter(int j, int i, bool beam)
 //
 //---------------------------------------------------------------------------
 
-int spawnbloodpoolpart1(int j, int i)
+int spawnbloodpoolpart1(DDukeActor *actj, DDukeActor* acti)
 {
-	auto sp = &sprite[i];
+	auto sp = &acti->s;
 	short s1 = sp->sectnum;
 
 	updatesector(sp->x + 108, sp->y + 108, &s1);
@@ -353,18 +358,18 @@ int spawnbloodpoolpart1(int j, int i)
 				updatesector(sp->x - 108, sp->y + 108, &s1);
 				if (s1 >= 0 && sector[s1].floorz != sector[sp->sectnum].floorz)
 				{
-					sp->xrepeat = sp->yrepeat = 0; changespritestat(i, STAT_MISC); return true;
+					sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return true;
 				}
 			}
-			else { sp->xrepeat = sp->yrepeat = 0; changespritestat(i, STAT_MISC); return true; }
+			else { sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return true; }
 		}
-		else { sp->xrepeat = sp->yrepeat = 0; changespritestat(i, STAT_MISC); return true; }
+		else { sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return true; }
 	}
-	else { sp->xrepeat = sp->yrepeat = 0; changespritestat(i, STAT_MISC); return true; }
+	else { sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return true; }
 
 	if (sector[sp->sectnum].lotag == 1)
 	{
-		changespritestat(i, STAT_MISC);
+		changespritestat(acti, STAT_MISC);
 		return true;
 	}
 	return false;
@@ -376,11 +381,11 @@ int spawnbloodpoolpart1(int j, int i)
 //
 //---------------------------------------------------------------------------
 
-void initfootprint(int j, int i)
+void initfootprint(DDukeActor* actj, DDukeActor* acti)
 {
-	auto sp = &sprite[i];
+	auto sp = &acti->s;
 	int sect = sp->sectnum;
-	if (j >= 0)
+	if (actj)
 	{
 		short s1;
 		s1 = sp->sectnum;
@@ -397,7 +402,7 @@ void initfootprint(int j, int i)
 					updatesector(sp->x - 84, sp->y + 84, &s1);
 					if (s1 >= 0 && sector[s1].floorz != sector[sp->sectnum].floorz)
 					{
-						sp->xrepeat = sp->yrepeat = 0; changespritestat(i, STAT_MISC); return;
+						sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return;
 					}
 				}
 				else { sp->xrepeat = sp->yrepeat = 0; return; }
@@ -406,16 +411,16 @@ void initfootprint(int j, int i)
 		}
 		else { sp->xrepeat = sp->yrepeat = 0; return; }
 
-		sp->cstat = 32 + ((ps[sprite[j].yvel].footprintcount & 1) << 2);
-		sp->ang = sprite[j].ang;
+		sp->cstat = 32 + ((ps[actj->s.yvel].footprintcount & 1) << 2);
+		sp->ang = actj->s.ang;
 	}
 
 	sp->z = sector[sect].floorz;
 	if (sector[sect].lotag != 1 && sector[sect].lotag != 2)
 		sp->xrepeat = sp->yrepeat = 32;
 
-	insertspriteq(&hittype[i]);
-	changespritestat(i, STAT_MISC);
+	insertspriteq(acti);
+	changespritestat(acti, STAT_MISC);
 }
 
 //---------------------------------------------------------------------------
@@ -1107,7 +1112,7 @@ void lotsofglass(int i, int wallnum, int n)
 		for (j = n - 1; j >= 0; j--)
 		{
 			a = sp->ang - 256 + (krand() & 511) + 1024;
-			EGS(sp->sectnum, sp->x, sp->y, sp->z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), 1024 - (krand() & 1023), i, 5);
+			EGS(sp->sectnum, sp->x, sp->y, sp->z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), 1024 - (krand() & 1023), &hittype[j], 5);
 		}
 		return;
 	}
@@ -1138,7 +1143,7 @@ void lotsofglass(int i, int wallnum, int n)
 			if (z < -(32 << 8) || z >(32 << 8))
 				z = sp->z - (32 << 8) + (krand() & ((64 << 8) - 1));
 			a = sp->ang - 1024;
-			EGS(sp->sectnum, x1, y1, z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), -(krand() & 1023), i, 5);
+			EGS(sp->sectnum, x1, y1, z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), -(krand() & 1023), &hittype[i], 5);
 		}
 	}
 }
diff --git a/source/games/duke/src/spawn_d.cpp b/source/games/duke/src/spawn_d.cpp
index b4bc0782b..2562cafb4 100644
--- a/source/games/duke/src/spawn_d.cpp
+++ b/source/games/duke/src/spawn_d.cpp
@@ -221,7 +221,7 @@ int spawn_d(int j, int pn)
                 break;
             case TRANSPORTERSTAR:
             case TRANSPORTERBEAM:
-				spawntransporter(j, i, sp->picnum == TRANSPORTERBEAM);
+				spawntransporter(actj, act, sp->picnum == TRANSPORTERBEAM);
                 break;
 
             case FRAMEEFFECT1:
@@ -281,7 +281,7 @@ int spawn_d(int j, int pn)
 
             case BLOODPOOL:
             case PUKE:
-				if (spawnbloodpoolpart1(j, i)) break;
+				if (spawnbloodpoolpart1(actj, act)) break;
 
                 if(j >= 0 && sp->picnum != PUKE)
                 {
@@ -464,7 +464,7 @@ int spawn_d(int j, int pn)
             case FOOTPRINTS2:
             case FOOTPRINTS3:
             case FOOTPRINTS4:
-				initfootprint(j, i);
+				initfootprint(actj, act);
                 break;
 
             case FEM1:
diff --git a/source/games/duke/src/spawn_r.cpp b/source/games/duke/src/spawn_r.cpp
index e7d0b0dd5..1c3c87c33 100644
--- a/source/games/duke/src/spawn_r.cpp
+++ b/source/games/duke/src/spawn_r.cpp
@@ -300,7 +300,7 @@ int spawn_r(int j, int pn)
 				break;
 			case TRANSPORTERSTAR:
 			case TRANSPORTERBEAM:
-				spawntransporter(j, i, sp->picnum == TRANSPORTERBEAM);
+				spawntransporter(actj, act, sp->picnum == TRANSPORTERBEAM);
 				break;
 
 			case FRAMEEFFECT1:
@@ -337,7 +337,7 @@ int spawn_r(int j, int pn)
 				changespritestat(i, STAT_MISC);
 				break;
 			case BLOODPOOL:
-				if (spawnbloodpoolpart1(j, i)) break;
+				if (spawnbloodpoolpart1(actj, act)) break;
 
 				if(j >= 0)
 				{
@@ -438,7 +438,7 @@ int spawn_r(int j, int pn)
 			case FOOTPRINTS2:
 			case FOOTPRINTS3:
 			case FOOTPRINTS4:
-				initfootprint(j, i);
+				initfootprint(actj, act);
 				break;
 			case FEM10:
 			case NAKED1: