diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h
index 978e1cc20..c36768701 100644
--- a/source/games/duke/src/duke3d.h
+++ b/source/games/duke/src/duke3d.h
@@ -85,7 +85,7 @@ struct Dispatcher
 	bool (*checkhitceiling)(sectortype* sn);
 	void (*checkhitsprite)(DDukeActor* i, DDukeActor* sn);
 	void (*checksectors)(int low);
-	DDukeActor* (*spawninit)(DDukeActor* actj, DDukeActor* act);
+	DDukeActor* (*spawninit)(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>* actors);
 
 	bool (*ceilingspace)(sectortype* sectp);
 	bool (*floorspace)(sectortype* sectp);
diff --git a/source/games/duke/src/dukeactor.h b/source/games/duke/src/dukeactor.h
index 4f4a902f6..66cc9ae1a 100644
--- a/source/games/duke/src/dukeactor.h
+++ b/source/games/duke/src/dukeactor.h
@@ -8,7 +8,6 @@ BEGIN_DUKE_NS
 using DukeStatIterator = TStatIterator<DDukeActor>;
 using DukeSectIterator = TSectIterator<DDukeActor>;
 using DukeSpriteIterator = TSpriteIterator<DDukeActor>;
-using DukeLinearSpriteIterator = TLinearSpriteIterator<DDukeActor>;
 
 inline DDukeActor* player_struct::GetActor()
 {
diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h
index a5aba7736..c7424dfa4 100644
--- a/source/games/duke/src/funct.h
+++ b/source/games/duke/src/funct.h
@@ -180,14 +180,14 @@ void checkplayerhurt_d(struct player_struct* p, const Collision& coll);
 void checkplayerhurt_r(struct player_struct* p, const Collision& coll);
 DDukeActor* dospawnsprite(DDukeActor* actj, int pn);
 
-void spriteinit_d(int);
-void spriteinit_r(int);
-DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act);
-DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act);
+void spriteinit_d(DDukeActor*);
+void spriteinit_r(DDukeActor*);
+DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>* actors);
+DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>* actors);
 
 void addspritetodelete(int spnum=0);
 void checkavailinven(struct player_struct* p);
-int initspriteforspawn(int spn, const std::initializer_list<int> &excludes);
+bool initspriteforspawn(DDukeActor* spn, const std::initializer_list<int> &excludes);
 void spawninitdefault(DDukeActor* actj, DDukeActor* act);
 void spawntransporter(DDukeActor* actj, DDukeActor* acti, bool beam);
 int spawnbloodpoolpart1(DDukeActor* acti);
@@ -196,7 +196,7 @@ void initshell(DDukeActor* actj, DDukeActor* acti, bool isshell);
 void initcrane(DDukeActor* actj, DDukeActor* acti, int CRANEPOLE);
 void initwaterdrip(DDukeActor* actj, DDukeActor* acti);
 int initreactor(DDukeActor* actj, DDukeActor* acti, bool isrecon);
-void spawneffector(DDukeActor* actor);
+void spawneffector(DDukeActor* actor, TArray<DDukeActor*>* actors);
 int startrts(int lumpNum, int localPlayer);
 
 void pickrandomspot(int pn);
@@ -224,8 +224,8 @@ void setgamepalette(int palid);
 void resetmys();
 void resettimevars();
 bool setnextmap(bool checksecretexit);
-void prelevel_d(int g);
-void prelevel_r(int g);
+void prelevel_d(int g, TArray<DDukeActor*>&);
+void prelevel_r(int g, TArray<DDukeActor*>&);
 void e4intro(const CompletionFunc& completion);
 void exitlevel(MapRecord *next);
 void enterlevel(MapRecord* mi, int gm);
diff --git a/source/games/duke/src/premap.cpp b/source/games/duke/src/premap.cpp
index bc0b9ea07..972a26f99 100644
--- a/source/games/duke/src/premap.cpp
+++ b/source/games/duke/src/premap.cpp
@@ -929,6 +929,23 @@ static void SpawnPortals()
 	mergePortals();
 }
 
+//---------------------------------------------------------------------------
+//
+// this is just a dummy for now to provide the intended setup.
+//
+//---------------------------------------------------------------------------
+
+static TArray<DDukeActor*> spawnactors(SpawnSpriteDef& spawns)
+{
+	insertAllSprites(spawns);
+	TArray<DDukeActor*> actorlist;
+	for(unsigned i = 0; i < spawns.sprites.Size(); i++)
+	{
+		if (hittype[i].exists()) actorlist.Push(&hittype[i]);
+	}
+	return actorlist;
+}
+
 //---------------------------------------------------------------------------
 //
 //
@@ -956,10 +973,10 @@ static int LoadTheMap(MapRecord *mi, struct player_struct *p, int gamemode)
 
 	memset(gotpic, 0, sizeof(gotpic));
 
-	insertAllSprites(sprites);
+	auto actorlist = spawnactors(sprites);
 	
-	if (isRR()) prelevel_r(gamemode);
-	else prelevel_d(gamemode);
+	if (isRR()) prelevel_r(gamemode, actorlist);
+	else prelevel_d(gamemode, actorlist);
 
 	SpawnPortals();
 
diff --git a/source/games/duke/src/premap_d.cpp b/source/games/duke/src/premap_d.cpp
index 95ee1563a..6945a8b71 100644
--- a/source/games/duke/src/premap_d.cpp
+++ b/source/games/duke/src/premap_d.cpp
@@ -269,13 +269,13 @@ void cacheit_d(void)
 //
 //
 //---------------------------------------------------------------------------
-void spriteinit_d(int i)
+void spriteinit_d(DDukeActor* actor, TArray<DDukeActor*>& actors)
 {
-	i = initspriteforspawn(i, { CRACK1, CRACK2, CRACK3, CRACK4, SPEAKER, LETTER, DUCK, TARGET, TRIPBOMB, VIEWSCREEN, VIEWSCREEN2 });
-	if ((i & 0x1000000)) spawninit_d(nullptr, &hittype[i&0xffffff]);
+	bool res = initspriteforspawn(actor, { CRACK1, CRACK2, CRACK3, CRACK4, SPEAKER, LETTER, DUCK, TARGET, TRIPBOMB, VIEWSCREEN, VIEWSCREEN2 });
+	if (res) spawninit_d(nullptr, actor, &actors);
 }
 
-void prelevel_d(int g)
+void prelevel_d(int g, TArray<DDukeActor*>& actors)
 {
 	int i, j, lotaglist;
 	short lotags[65];
@@ -316,32 +316,32 @@ void prelevel_d(int g)
 	}
 
 
-	for (i = 0; i < MAXSPRITES; i++)
+	for (auto actor : actors)
 	{
-		auto spr = &sprite[i];
-		if (spr->statnum < MAXSTATUS)
+		if (actor->exists())
 		{
+			auto spr = actor->s;
 			if (spr->picnum == SECTOREFFECTOR && spr->lotag == SE_14_SUBWAY_CAR)
 				continue;
-			spriteinit_d(i);
+			spriteinit_d(actor, actors);
 		}
 	}
 
-	for (i = 0; i < MAXSPRITES; i++)
+	for (auto actor : actors)
 	{
-		auto spr = &sprite[i];
-		if (spr->statnum < MAXSTATUS)
+		if (actor->exists())
 		{
+			auto spr = actor->s;
 			if (spr->picnum == SECTOREFFECTOR && spr->lotag == SE_14_SUBWAY_CAR)
-				spriteinit_d(i);
+				spriteinit_d(actor, actors);
 		}
 	}
 	lotaglist = 0;
 
 	it.Reset(STAT_DEFAULT);
-	while ((i = it.NextIndex()) >= 0)
+	while (auto actor = it.Next())
 	{
-		auto spr = &sprite[i];
+		auto spr = actor->s;
 		switch (spr->picnum)
 		{
 		case DIPSWITCH + 1:
diff --git a/source/games/duke/src/premap_r.cpp b/source/games/duke/src/premap_r.cpp
index 390791c00..d9fe80e30 100644
--- a/source/games/duke/src/premap_r.cpp
+++ b/source/games/duke/src/premap_r.cpp
@@ -407,13 +407,13 @@ void cacheit_r(void)
 //
 //---------------------------------------------------------------------------
 
-void spriteinit_r(int i)
+void spriteinit_r(DDukeActor* actor, TArray<DDukeActor*>& actors)
 {
-	i = initspriteforspawn(i, { CRACK1, CRACK2, CRACK3, CRACK4 });
-	if ((i & 0x1000000)) spawninit_r(nullptr, &hittype[i & 0xffffff]);
+	bool res = initspriteforspawn(actor, { CRACK1, CRACK2, CRACK3, CRACK4 });
+	if (res) spawninit_r(nullptr, actor, &actors);
 }
 
-void prelevel_r(int g)
+void prelevel_r(int g, TArray<DDukeActor*>& actors)
 {
 	struct player_struct* p;
 	int i;
@@ -433,14 +433,14 @@ void prelevel_r(int g)
 
 	if (isRRRA())
 	{
-
-		for (j = 0; j < MAXSPRITES; j++)
+		for(auto actor : actors)
 		{
-			auto spr = &sprite[j];
+			if (!actor->exists()) continue;
+			auto spr = actor->s;
 			if (spr->pal == 100)
 			{
 				if (numplayers > 1)
-					deletesprite(j);
+					deletesprite(actor);
 				else
 					spr->pal = 0;
 			}
@@ -449,7 +449,7 @@ void prelevel_r(int g)
 				spr->extra = 0;
 				spr->hitag = 1;
 				spr->pal = 0;
-				changespritestat(j, 118);
+				ChangeActorStat(actor, 118);
 			}
 		}
 	}
@@ -600,9 +600,10 @@ void prelevel_r(int g)
 		}
 	}
 
-	for (i = 0; i < MAXSPRITES; i++)
+	for (auto actor : actors)
 	{
-		auto spr = &sprite[i];
+		if (!actor->exists()) continue;
+		auto spr = actor->s;
 		if (spr->picnum == RRTILE19)
 		{
 			if (geocnt > 64)
@@ -610,10 +611,10 @@ void prelevel_r(int g)
 			if (spr->hitag == 0)
 			{
 				geosector[geocnt] = spr->sector();
-				for (j = 0; j < MAXSPRITES; j++)
+				for (auto actor2 : actors)
 				{
-					auto spj = &sprite[j];
-					if (spr->lotag == spj->lotag && j != i && spj->picnum == RRTILE19)
+					auto spj = actor2->s;
+					if (spr->lotag == spj->lotag && actor2 != actor && spj->picnum == RRTILE19)
 					{
 						if (spj->hitag == 1)
 						{
@@ -636,31 +637,31 @@ void prelevel_r(int g)
 		}
 	}
 
-	for (i = 0; i < MAXSPRITES; i++)
+	for (auto actor : actors)
 	{
-		auto spr = &sprite[i];
-		if (spr->statnum < MAXSTATUS)
+		if (actor->exists())
 		{
+			auto spr = actor->s;
 			if (spr->picnum == SECTOREFFECTOR && spr->lotag == SE_14_SUBWAY_CAR)
 				continue;
-			spriteinit_r(i);
+			spriteinit_r(actor, actors);
 		}
 	}
 
-	for (i = 0; i < MAXSPRITES; i++)
+	for (auto actor : actors)
 	{
-		auto spr = &sprite[i];
-		if (spr->statnum < MAXSTATUS)
+		if (actor->exists())
 		{
+			auto spr = actor->s;
 			if (spr->picnum == SECTOREFFECTOR && spr->lotag == SE_14_SUBWAY_CAR)
-				spriteinit_r(i);
-		}
-		if (spr->picnum == RRTILE19)
-			deletesprite(i);
-		if (spr->picnum == RRTILE34)
-		{
-			spr->sector()->keyinfo = uint8_t(spr->lotag);
-			deletesprite(i);
+				spriteinit_r(actor, actors);
+			if (spr->picnum == RRTILE19)
+				deletesprite(actor);
+			if (spr->picnum == RRTILE34)
+			{
+				spr->sector()->keyinfo = uint8_t(spr->lotag);
+				deletesprite(actor);
+			}
 		}
 	}
 
diff --git a/source/games/duke/src/sectors_d.cpp b/source/games/duke/src/sectors_d.cpp
index f56f87e6b..078950011 100644
--- a/source/games/duke/src/sectors_d.cpp
+++ b/source/games/duke/src/sectors_d.cpp
@@ -726,7 +726,7 @@ void checkhitwall_d(DDukeActor* spr, walltype* wal, int x, int y, int z, int atw
 					auto spawned = EGS(sptr, x, y, z, SECTOREFFECTOR, 0, 0, 0, ps[0].angle.ang.asbuild(), 0, 0, spr, 3);
 					if (spawned)
 					{
-							spawned->s->lotag = 128;
+						spawned->s->lotag = SE_128_GLASS_BREAKING;
 						spawned->temp_data[1] = 5;
 						spawned->temp_walls[0] = wal;
 						S_PlayActorSound(GLASS_BREAKING, spawned);
diff --git a/source/games/duke/src/sectors_r.cpp b/source/games/duke/src/sectors_r.cpp
index 10e669991..3246b934b 100644
--- a/source/games/duke/src/sectors_r.cpp
+++ b/source/games/duke/src/sectors_r.cpp
@@ -790,7 +790,7 @@ bool checkhitswitch_r(int snum, walltype* wwal, DDukeActor* act)
 					DDukeActor* switches[3];
 					int switchcount = 0, j;
 					S_PlaySound3D(SWITCH_ON, act, &v);
-					DukeLinearSpriteIterator it;
+					DukeSpriteIterator it;
 					while (auto actt = it.Next())
 					{
 						int jpn = actt->s->picnum;
@@ -806,6 +806,11 @@ bool checkhitswitch_r(int snum, walltype* wwal, DDukeActor* act)
 					}
 					if (switchcount == 3)
 					{
+						// This once was a linear search over sprites[] so bring things back in order, just to be safe.
+						if (switches[0]->GetIndex() > switches[1]->GetIndex()) std::swap(switches[0], switches[1]);
+						if (switches[0]->GetIndex() > switches[2]->GetIndex()) std::swap(switches[0], switches[2]);
+						if (switches[1]->GetIndex() > switches[2]->GetIndex()) std::swap(switches[1], switches[2]);
+
 						S_PlaySound3D(78, act, &v);
 						for (j = 0; j < switchcount; j++)
 						{
@@ -1038,7 +1043,7 @@ void checkhitwall_r(DDukeActor* spr, walltype* wal, int x, int y, int z, int atw
 					auto spawned = EGS(sptr, x, y, z, SECTOREFFECTOR, 0, 0, 0, ps[0].angle.ang.asbuild(), 0, 0, spr, 3);
 					if (spawned)
 					{
-						spawned->s->lotag = 128;
+						spawned->s->lotag = SE_128_GLASS_BREAKING;
 						spawned->temp_walls[0] = wal;
 						S_PlayActorSound(GLASS_BREAKING, spawned);
 					}
@@ -1059,7 +1064,7 @@ void checkhitwall_r(DDukeActor* spr, walltype* wal, int x, int y, int z, int atw
 					auto spawned = EGS(sptr, x, y, z, SECTOREFFECTOR, 0, 0, 0, ps[0].angle.ang.asbuild(), 0, 0, spr, 3);
 					if (spawned)
 					{
-						spawned->s->lotag = 128;
+						spawned->s->lotag = SE_128_GLASS_BREAKING;
 						spawned->temp_data[1] = 2;
 						spawned->temp_walls[0] = wal;
 						S_PlayActorSound(GLASS_BREAKING, spawned);
diff --git a/source/games/duke/src/spawn.cpp b/source/games/duke/src/spawn.cpp
index 1d269e79c..c47d10e8b 100644
--- a/source/games/duke/src/spawn.cpp
+++ b/source/games/duke/src/spawn.cpp
@@ -137,9 +137,8 @@ DDukeActor* EGS(sectortype* whatsectp, int s_x, int s_y, int s_z, int s_pn, int8
 //
 //---------------------------------------------------------------------------
 
-int initspriteforspawn(int i, const std::initializer_list<int> &excludes)
+bool initspriteforspawn(DDukeActor* act, const std::initializer_list<int> &excludes)
 {
-	auto act = &hittype[i];
 	auto sp = act->s;
 	auto t = act->temp_data;
 
@@ -168,7 +167,7 @@ int initspriteforspawn(int i, const std::initializer_list<int> &excludes)
 	if (sp->cstat & 48)
 		if (!isIn(sp->picnum, excludes) && (sp->cstat & 48))
 		{
-			if (sp->shade == 127) return i;
+			if (sp->shade == 127) return false;
 			if (wallswitchcheck(act) && (sp->cstat & 16))
 			{
 				if (sp->picnum != TILE_ACCESSSWITCH && sp->picnum != TILE_ACCESSSWITCH2 && sp->pal)
@@ -177,21 +176,21 @@ int initspriteforspawn(int i, const std::initializer_list<int> &excludes)
 					{
 						sp->xrepeat = sp->yrepeat = 0;
 						sp->cstat = sp->lotag = sp->hitag = 0;
-						return i;
+						return false;
 					}
 				}
 				sp->cstat |= 257;
 				if (sp->pal && sp->picnum != TILE_ACCESSSWITCH && sp->picnum != TILE_ACCESSSWITCH2)
 					sp->pal = 0;
-				return i;
+				return false;
 			}
 
 			if (sp->hitag)
 			{
-				changespritestat(i, 12);
+				ChangeActorStat(act, 12);
 				sp->cstat |= 257;
 				sp->extra = gs.impact_damage;
-				return i;
+				return false;
 			}
 		}
 
@@ -209,7 +208,7 @@ int initspriteforspawn(int i, const std::initializer_list<int> &excludes)
 			sp->hitag = s3;
 	}
 	else t[1] = t[4] = 0;
-	return i | 0x1000000;
+	return true;
 }
 
 //---------------------------------------------------------------------------
@@ -226,7 +225,7 @@ DDukeActor* spawn(DDukeActor* actj, int pn)
 		if (spawned)
 		{
 			spawned->picnum = actj->s->picnum;
-			return fi.spawninit(actj, spawned);
+			return fi.spawninit(actj, spawned, nullptr);
 		}
 	}
 	return nullptr;
@@ -619,7 +618,7 @@ int initreactor(DDukeActor* actj, DDukeActor* actor, bool isrecon)
 //
 //---------------------------------------------------------------------------
 
-void spawneffector(DDukeActor* actor)
+void spawneffector(DDukeActor* actor, TArray<DDukeActor*>* actors)
 {
 	auto sp = actor->s;
 	auto sectp = sp->sector();
@@ -637,18 +636,18 @@ void spawneffector(DDukeActor* actor)
 			break;
 		case SE_7_TELEPORT: // Transporters!!!!
 		case SE_23_ONE_WAY_TELEPORT:// XPTR END
-			if (sp->lotag != SE_23_ONE_WAY_TELEPORT)
+			if (sp->lotag != SE_23_ONE_WAY_TELEPORT && actors)
 			{
-				DukeLinearSpriteIterator it;
-				while (auto act2 = it.Next())
-					{
+				
+				for(auto act2 : *actors)
+				{
 					if (act2->s->statnum < MAXSTATUS && act2->s->picnum == SECTOREFFECTOR && (act2->s->lotag == SE_7_TELEPORT || act2->s->lotag == SE_23_ONE_WAY_TELEPORT) && 
 						actor != act2 && act2->s->hitag == sp->hitag)
 					{
 						actor->SetOwner(act2);
 						break;
 					}
-			}
+				}
 			}
 			else actor->SetOwner(actor);
 
@@ -943,9 +942,9 @@ void spawneffector(DDukeActor* actor)
 					sectp->hitag = ActorToScriptIndex(actor);
 				}
 
-				DukeLinearSpriteIterator it;
+				
 				bool found = false;
-				while (auto act2 = it.Next())
+				if (actors) for(auto act2 : *actors)
 				{
 					auto spr = act2->s;
 					if (spr->statnum < MAXSTATUS)
diff --git a/source/games/duke/src/spawn_d.cpp b/source/games/duke/src/spawn_d.cpp
index 47a09d70a..b045526d4 100644
--- a/source/games/duke/src/spawn_d.cpp
+++ b/source/games/duke/src/spawn_d.cpp
@@ -41,7 +41,7 @@ source as it is released.
 BEGIN_DUKE_NS
 
 
-DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act)
+DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>* actors)
 {
 	auto sp = act->s;
 	auto spj = actj == nullptr ? nullptr : actj->s;
@@ -1125,7 +1125,7 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act)
 		break;
 
 	case SECTOREFFECTOR:
-		spawneffector(act);
+		spawneffector(act, actors);
 
 		break;
 
diff --git a/source/games/duke/src/spawn_r.cpp b/source/games/duke/src/spawn_r.cpp
index 877c59165..b70a5c4f2 100644
--- a/source/games/duke/src/spawn_r.cpp
+++ b/source/games/duke/src/spawn_r.cpp
@@ -35,7 +35,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
 
 BEGIN_DUKE_NS
 
-DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act)
+DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>* actors)
 {
 	auto sp = act->s;
 	auto spj = actj == nullptr ? nullptr : actj->s;
@@ -1371,7 +1371,7 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act)
 		ChangeActorStat(act, STAT_STANDABLE);
 		break;
 	case SECTOREFFECTOR:
-		spawneffector(act);
+		spawneffector(act, actors);
 		break;
 
 	case SEENINE:
diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h
index ef483c897..7010e0696 100644
--- a/source/games/duke/src/types.h
+++ b/source/games/duke/src/types.h
@@ -45,9 +45,10 @@ struct DDukeActor : public DCoreActor
 
 	static DDukeActor* array();	// this is necessary to allow define inline functions referencing the global array inside the definition itself.
 
-	DDukeActor() : s(&sprite[this - array()]) 
+	DDukeActor()
 	{
 		index = int(this - array());
+		s = &DCoreActor::s();
 	}
 	DDukeActor(const DDukeActor& other) = delete;				// we also do not want to allow copies.
 	DDukeActor& operator=(const DDukeActor& other) = delete;