diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp
index 3d1194493..31e325c6c 100644
--- a/source/games/duke/src/actors_d.cpp
+++ b/source/games/duke/src/actors_d.cpp
@@ -705,30 +705,12 @@ void movestandables_d(void)
 		if (!act->insector() || actorflag(act, SFLAG2_DIENOW))
 		{
 			act->Destroy();
-			continue;
 		}
-
-		if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
+		else if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
 		{
 			CallTick(act);
-			continue;
 		}
-
-		else if (isIn(picnum,
-				EXPLODINGBARREL,
-				WOODENHORSE,
-				HORSEONSIDE,
-				FLOORFLAME,
-				FIREBARREL,
-				FIREVASE,
-				NUKEBARREL,
-				NUKEBARRELDENTED,
-				NUKEBARRELLEAKED,
-				TOILETWATER,
-				RUBBERCAN,
-				STEAM,
-				CEILINGSTEAM,
-				WATERBUBBLEMAKER))
+		else if (actorflag(act, SFLAG3_FORCERUNCON))
 		{
 			double x;
 			int p = findplayer(act, &x);
@@ -751,24 +733,16 @@ void moveweapons_d(void)
 		if (!act->insector() || actorflag(act, SFLAG2_DIENOW))
 		{
 			act->Destroy();
-			continue;
 		}
-
-		if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
+		else if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
 		{
 			CallTick(act);
-			continue;
 		}
-
-		switch(act->spr.picnum)
-		{
-		case SHOTSPARK1:
+		else if (actorflag(act, SFLAG3_FORCERUNCON))
 		{
 			double x;
 			int p = findplayer(act, &x);
 			execute(act, p, x);
-			break;
-		}
 		}
 	}
 }
@@ -1179,40 +1153,29 @@ void moveactors_d(void)
 	DukeStatIterator it(STAT_ACTOR);
 	while (auto act = it.Next())
 	{
-		if (act->spr.picnum == QUEBALL)
-		{
-			int a = 0;
-		}
-		auto sectp = act->sector();
-
-		if (act->spr.scale.X == 0 || sectp == nullptr || actorflag(act, SFLAG2_DIENOW))
+		if (act->spr.scale.X == 0 || act->spr.sectp == nullptr || actorflag(act, SFLAG2_DIENOW))
 		{ 
 			act->Destroy();
+		}
+		else if (monsterCheatCheck(act) && badguy(act))
+		{
 			continue;
 		}
-
-		int *t = &act->temp_data[0];
-
-		if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
+		else if (isWorldTour() && act->spr.picnum == FLAMETHROWERFLAME)
+		{
+			flamethrowerflame(act);
+		}
+		else if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
 		{
 			CallTick(act);
 			continue;
 		}
-		else switch (act->spr.picnum)
+		else
 		{
-		case FLAMETHROWERFLAME:
-			if (isWorldTour()) flamethrowerflame(act);
-			continue;
+			double xx;
+			p = findplayer(act, &xx);
+			execute(act, p, xx);
 		}
-		if (monsterCheatCheck(act) && badguy(act))
-		{
-			continue;
-		}
-
-		double xx;
-		p = findplayer(act, &xx);
-
-		execute(act, p, xx);
 	}
 
 }
@@ -1267,54 +1230,22 @@ void moveexplosions_d(void)  // STATNUM 5
 	DukeStatIterator it(STAT_MISC);
 	while (auto act = it.Next())
 	{
-		if (!act->insector() || act->spr.scale.X == 0) 
+		if (act->spr.scale.X == 0 || act->spr.sectp == nullptr || actorflag(act, SFLAG2_DIENOW))
 		{
 			act->Destroy();
-			continue;
 		}
-
-		if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
+		else if (isWorldTour() && act->spr.picnum == FIREFLYFLYINGEFFECT)
+		{
+			fireflyflyingeffect(act);
+		}
+		else if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
 		{
 			CallTick(act);
-			continue;
 		}
-
-
-		auto sectp = act->sector();
-
-		switch (act->spr.picnum)
+		else if (actorflag(act, SFLAG3_FORCERUNCON))
 		{
-		case FIREFLYFLYINGEFFECT:
-			if (isWorldTour()) fireflyflyingeffect(act);
-			continue;
-
-		case LAVAPOOL:
-		case ONFIRE:
-		case ONFIRESMOKE:
-		case BURNEDCORPSE:
-		case LAVAPOOLBUBBLE:
-		case WHISPYSMOKE:
-			if (!isWorldTour())
-				continue;
-			[[fallthrough]];
-
-		case BURNING:
-		case BURNING2:
-		case FECES:
-		case WATERBUBBLE:
-		case SMALLSMOKE:
-		case EXPLOSION2:
-		case SHRINKEREXPLOSION:
-		case EXPLOSION2BOT:
-		case BLOOD:
-		case LASERSITE:
-		case FORCERIPPLE:
-		case TRANSPORTERSTAR:
-		case TRANSPORTERBEAM:
 			p = findplayer(act, &xx);
 			execute(act, p, xx);
-			continue;
-
 		}
 	}
 }
diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp
index 8f15df38a..400b7d4f5 100644
--- a/source/games/duke/src/actors_r.cpp
+++ b/source/games/duke/src/actors_r.cpp
@@ -565,28 +565,12 @@ void movestandables_r(void)
 		if (!act->insector() || actorflag(act, SFLAG2_DIENOW))
 		{
 			act->Destroy();
-			continue;
 		}
-
-		if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
+		else if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
 		{
 			CallTick(act);
-			continue;
 		}
-
-		else if (isIn(picnum,
-				EXPLODINGBARREL,
-				WOODENHORSE,
-				HORSEONSIDE,
-				FIREBARREL,
-				FIREVASE,
-				NUKEBARREL,
-				NUKEBARRELDENTED,
-				NUKEBARRELLEAKED,
-				TOILETWATER,
-				RUBBERCAN,
-				STEAM,
-				CEILINGSTEAM))
+		else if (actorflag(act, SFLAG3_FORCERUNCON))
 		{
 			double x;
 			int p = findplayer(act, &x);
@@ -604,29 +588,21 @@ void movestandables_r(void)
 void moveweapons_r(void)
 {
 	DukeStatIterator it(STAT_PROJECTILE);
-	while (auto proj = it.Next())
+	while (auto act = it.Next())
 	{
-		if (!proj->insector() || actorflag(proj, SFLAG2_DIENOW))
+		if (!act->insector() || actorflag(act, SFLAG2_DIENOW))
 		{
-			proj->Destroy();
-			continue;
+			act->Destroy();
 		}
-
-		if (proj->GetClass() != RUNTIME_CLASS(DDukeActor))
+		else if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
 		{
-			CallTick(proj);
-			continue;
+			CallTick(act);
 		}
-
-		switch (proj->spr.picnum)
-		{
-		case SHOTSPARK1:
+		else if (actorflag(act, SFLAG3_FORCERUNCON))
 		{
 			double x;
-			int p = findplayer(proj, &x);
-			execute(proj, p, x);
-			continue;
-		}
+			int p = findplayer(act, &x);
+			execute(act, p, x);
 		}
 	}
 }
@@ -1144,6 +1120,10 @@ void moveactors_r(void)
 			act->Destroy();
 			continue;
 		}
+		if (monsterCheatCheck(act) && badguy(act))
+		{
+			continue;
+		}
 
 		auto sectp = act->sector();
 
@@ -1181,10 +1161,6 @@ void moveactors_r(void)
 		}
 
 
-		if (monsterCheatCheck(act) && badguy(act))
-		{
-			continue;
-		}
 
 		p = findplayer(act, &xx);
 
@@ -1201,55 +1177,24 @@ void moveactors_r(void)
 
 void moveexplosions_r(void)  // STATNUM 5
 {
-	int p;
-	int * t;
-	double xx;
-
 
 	DukeStatIterator it(STAT_MISC);
 	while (auto act = it.Next())
 	{
-		if (act->time == 959)
-		{
-			int a = 0;
-		}
-		t = &act->temp_data[0];
-		auto sectp = act->sector();
-
-		if (!act->insector() || act->spr.scale.X == 0) 
+		if (act->spr.scale.X == 0 || act->spr.sectp == nullptr || actorflag(act, SFLAG2_DIENOW))
 		{
 			act->Destroy();
-			continue;
 		}
-
-		if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
+		else if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
 		{
 			CallTick(act);
-			continue;
 		}
-
-		switch (act->spr.picnum)
+		else if (actorflag(act, SFLAG3_FORCERUNCON))
 		{
-		case SHOTGUNSPRITE:
-			if (act->sector()->lotag == 800)
-				if (act->spr.pos.Z >= act->sector()->floorz - 8)
-				{
-					act->Destroy();
-					continue;
-				}
-			break;
-		case BURNING:
-		case WATERBUBBLE:
-		case SMALLSMOKE:
-		case EXPLOSION2:
-		case EXPLOSION3:
-		case BLOOD:
-		case FORCERIPPLE:
-		case TRANSPORTERSTAR:
-		case TRANSPORTERBEAM:
+			int p;
+			double xx;
 			p = findplayer(act, &xx);
 			execute(act, p, xx);
-			continue;
 		}
 	}
 }
diff --git a/source/games/duke/src/constants.h b/source/games/duke/src/constants.h
index d4d2d76a9..da26fc3ed 100644
--- a/source/games/duke/src/constants.h
+++ b/source/games/duke/src/constants.h
@@ -399,6 +399,7 @@ enum sflags3_t
 	SFLAG3_BLOODY = 0x00000002,
 	SFLAG3_BROWNBLOOD = 0x00000004,
 	SFLAG3_LIGHTDAMAGE = 0x00000008,
+	SFLAG3_FORCERUNCON = 0x00000010,	// by default only STAT_ACTOR runs CON - this enables it for other statnums as well, provided they run Tick()
 
 };
 
diff --git a/source/games/duke/src/flags_d.cpp b/source/games/duke/src/flags_d.cpp
index bcffc5d97..9a46c8de1 100644
--- a/source/games/duke/src/flags_d.cpp
+++ b/source/games/duke/src/flags_d.cpp
@@ -81,6 +81,37 @@ void initactorflags_d()
 			RAT,
 			ROTATEGUN });
 
+	// non-STAT_ACTOR classes that need CON support. For compatibility this must be explicitly enabled.
+	setflag(SFLAG3_FORCERUNCON, {
+			EXPLODINGBARREL,
+			WOODENHORSE,
+			HORSEONSIDE,
+			FLOORFLAME,
+			FIREBARREL,
+			FIREVASE,
+			NUKEBARREL,
+			NUKEBARRELDENTED,
+			NUKEBARRELLEAKED,
+			TOILETWATER,
+			RUBBERCAN,
+			STEAM,
+			CEILINGSTEAM,
+			WATERBUBBLEMAKER,
+			SHOTSPARK1,
+			BURNING,
+			BURNING2,
+			FECES,
+			WATERBUBBLE,
+			SMALLSMOKE,
+			EXPLOSION2,
+			SHRINKEREXPLOSION,
+			EXPLOSION2BOT,
+			BLOOD,
+			LASERSITE,
+			FORCERIPPLE,
+			TRANSPORTERSTAR,
+			TRANSPORTERBEAM
+		});
 	// Some flags taken from RedNukem's init code. This is a good start as any to reduce the insane dependency on tile numbers for making decisions in the play code. A lot more will be added here later.
 	setflag(SFLAG_NODAMAGEPUSH, { TANK, BOSS1, BOSS2, BOSS3, BOSS4, RECON, ROTATEGUN });
 	setflag(SFLAG_BOSS, { BOSS1, BOSS2, BOSS3, BOSS4, BOSS4STAYPUT, BOSS1STAYPUT });
@@ -133,6 +164,7 @@ void initactorflags_d()
 	{
 		setflag(SFLAG_INTERNAL_BADGUY, { FIREFLY });
 		setflag(SFLAG_INTERNAL_BADGUY|SFLAG_NODAMAGEPUSH|SFLAG_BOSS, { BOSS5 });
+		setflag(SFLAG3_FORCERUNCON, { LAVAPOOL, ONFIRE, ONFIRESMOKE, BURNEDCORPSE, LAVAPOOLBUBBLE, WHISPYSMOKE });
 	}
 
 	setflag(SFLAG_INVENTORY, {
diff --git a/source/games/duke/src/flags_r.cpp b/source/games/duke/src/flags_r.cpp
index 99cc2bb68..e9cf93cb6 100644
--- a/source/games/duke/src/flags_r.cpp
+++ b/source/games/duke/src/flags_r.cpp
@@ -155,6 +155,32 @@ void initactorflags_r()
 		NUKEBARRELLEAKED
 		});
 
+	// non-STAT_ACTOR classes that need CON support. For compatibility this must be explicitly enabled.
+	setflag(SFLAG3_FORCERUNCON, {
+			EXPLODINGBARREL,
+			WOODENHORSE,
+			HORSEONSIDE,
+			FIREBARREL,
+			FIREVASE,
+			NUKEBARREL,
+			NUKEBARRELDENTED,
+			NUKEBARRELLEAKED,
+			TOILETWATER,
+			RUBBERCAN,
+			STEAM,
+			CEILINGSTEAM,
+			SHOTSPARK1,
+			BURNING,
+			WATERBUBBLE,
+			SMALLSMOKE,
+			EXPLOSION2,
+			EXPLOSION3,
+			BLOOD,
+			FORCERIPPLE,
+			TRANSPORTERSTAR,
+			TRANSPORTERBEAM
+		});
+
 	setflag(SFLAG_NOINTERPOLATE, { CRANEPOLE });
 	setflag(SFLAG_FALLINGFLAMMABLE, { BOX });
 	setflag(SFLAG_INFLAME, { RADIUSEXPLOSION, RPG, FIRELASER, HYDRENT, DYNAMITE, POWDERKEG, VIXENSHOT, OWHIP, UWHIP });
diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp
index 907674b23..2e25977bf 100644
--- a/source/games/duke/src/vmexports.cpp
+++ b/source/games/duke/src/vmexports.cpp
@@ -628,12 +628,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, spritewidth, duke_spw)
 	ACTION_RETURN_INT(duke_spw(self));
 }
 
-DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, monsterCheatCheck, monsterCheatCheck)
-{
-	PARAM_SELF_PROLOGUE(DDukeActor);
-	ACTION_RETURN_INT(monsterCheatCheck(self));
-}
-
 void DukeActor_shoot(DDukeActor* act, int intname)
 {
 	int picnum = PicForName(intname);
diff --git a/wadsrc/static/zscript/games/duke/actors/greenslime.zs b/wadsrc/static/zscript/games/duke/actors/greenslime.zs
index b6f480b1c..8f2d2292e 100644
--- a/wadsrc/static/zscript/games/duke/actors/greenslime.zs
+++ b/wadsrc/static/zscript/games/duke/actors/greenslime.zs
@@ -25,8 +25,6 @@ class DukeGreenSlime : DukeActor
 		let sectp = self.sector;
 		int j;
 
-		if (self.monsterCheatCheck()) return;
-
 		self.temp_data[1] += 128;
 
 		if (sectp.floorstat & CSTAT_SECTOR_SKY)
diff --git a/wadsrc/static/zscript/games/duke/actors/recon.zs b/wadsrc/static/zscript/games/duke/actors/recon.zs
index ef134125a..495ce0716 100644
--- a/wadsrc/static/zscript/games/duke/actors/recon.zs
+++ b/wadsrc/static/zscript/games/duke/actors/recon.zs
@@ -64,8 +64,6 @@ class DukeRecon : DukeActor
 		if (self.pos.Z < sectp.ceilingz + 32)
 			self.pos.Z = sectp.ceilingz + 32;
 
-		if (self.monsterCheatCheck()) return;
-		
 		if (self.ifhitbyweapon() >= 0)
 		{
 			if (self.extra < 0 && self.temp_data[0] != -1)
diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs
index f8257708f..018f0e01b 100644
--- a/wadsrc/static/zscript/games/duke/dukeactor.zs
+++ b/wadsrc/static/zscript/games/duke/dukeactor.zs
@@ -211,7 +211,6 @@ class DukeActor : CoreActor native
 	native double gutsoffset();
 	native int movesprite(Vector3 move, int clipmask);
 	native int movesprite_ex(Vector3 move, int clipmask, CollisionData coll);
-	native int monsterCheatCheck();
 	native void shoot(Name spawnclass);
 	native void setClipDistFromTile();
 	native void insertspriteq();