diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index f51143556..d64f8abd2 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -2202,6 +2202,19 @@ static int lib_pExplodeMissile(lua_State *L)
 	return 0;
 }
 
+static int lib_pMobjTouchingSectorSpecial(lua_State *L)
+{
+	mobj_t *mo = *((mobj_t**)luaL_checkudata(L, 1, META_MOBJ));
+	INT32 section = (INT32)luaL_checkinteger(L, 2);
+	INT32 number = (INT32)luaL_checkinteger(L, 3);
+	//HUDSAFE
+	INLEVEL
+	if (!mo)
+		return LUA_ErrInvalid(L, "mobj_t");
+	LUA_PushUserdata(L, P_MobjTouchingSectorSpecial(mo, section, number), META_SECTOR);
+	return 1;
+}
+
 static int lib_pPlayerTouchingSectorSpecial(lua_State *L)
 {
 	player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@@ -2353,17 +2366,6 @@ static int lib_pFadeLight(lua_State *L)
 	return 0;
 }
 
-static int lib_pThingOnSpecial3DFloor(lua_State *L)
-{
-	mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	NOHUD
-	INLEVEL
-	if (!mo)
-		return LUA_ErrInvalid(L, "mobj_t");
-	LUA_PushUserdata(L, P_ThingOnSpecial3DFloor(mo), META_SECTOR);
-	return 1;
-}
-
 static int lib_pIsFlagAtBase(lua_State *L)
 {
 	mobjtype_t flag = luaL_checkinteger(L, 1);
@@ -4056,6 +4058,7 @@ static luaL_Reg lib[] = {
 	{"P_SetMobjStateNF",lib_pSetMobjStateNF},
 	{"P_DoSuperTransformation",lib_pDoSuperTransformation},
 	{"P_ExplodeMissile",lib_pExplodeMissile},
+	{"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial},
 	{"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial},
 	{"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding},
 	{"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding},
@@ -4068,7 +4071,6 @@ static luaL_Reg lib[] = {
 	{"P_LinedefExecute",lib_pLinedefExecute},
 	{"P_SpawnLightningFlash",lib_pSpawnLightningFlash},
 	{"P_FadeLight",lib_pFadeLight},
-	{"P_ThingOnSpecial3DFloor",lib_pThingOnSpecial3DFloor},
 	{"P_IsFlagAtBase",lib_pIsFlagAtBase},
 	{"P_SetupLevelSky",lib_pSetupLevelSky},
 	{"P_SetSkyboxMobj",lib_pSetSkyboxMobj},
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 2c6315271..d0af3112e 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -9611,13 +9611,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
 		break;
 	case MT_BLUEFLAG:
 	case MT_REDFLAG:
-	{
-		sector_t* sec2;
-		sec2 = P_ThingOnSpecial3DFloor(mobj);
-		if ((sec2 && GETSECSPECIAL(sec2->special, 4) == 2) || (GETSECSPECIAL(mobj->subsector->sector->special, 4) == 2))
+		if (P_MobjTouchingSectorSpecial(mobj, 4, 2))
 			mobj->fuse = 1; // Return to base.
 		break;
-	}
 	case MT_SPINDUST: // Spindash dust
 		mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000
 		mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same
diff --git a/src/p_spec.c b/src/p_spec.c
index 49ba3adaf..265cba2b5 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -3926,6 +3926,99 @@ boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec)
 	}
 }
 
+static sector_t *P_MobjTouching3DFloorSpecial(mobj_t *mo, sector_t *sector, INT32 section, INT32 number)
+{
+	ffloor_t *rover;
+
+	for (rover = sector->ffloors; rover; rover = rover->next)
+	{
+		if (GETSECSPECIAL(rover->master->frontsector->special, section) != number)
+			continue;
+
+		if (!(rover->flags & FF_EXISTS))
+			continue;
+
+		if (!P_IsMobjTouching3DFloor(mo, rover, sector))
+			continue;
+
+		// This FOF has the special we're looking for, but are we allowed to touch it?
+		if (sector == mo->subsector->sector
+			|| (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH))
+			return rover->master->frontsector;
+	}
+
+	return NULL;
+}
+
+static sector_t *P_MobjTouchingPolyobjSpecial(mobj_t *mo, INT32 section, INT32 number)
+{
+	polyobj_t *po;
+	sector_t *polysec;
+	boolean touching = false;
+	boolean inside = false;
+
+	for (po = mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next))
+	{
+		if (po->flags & POF_NOSPECIALS)
+			continue;
+
+		polysec = po->lines[0]->backsector;
+
+		if (GETSECSPECIAL(polysec->special, section) != number)
+			continue;
+
+		touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo);
+		inside = P_MobjInsidePolyobj(po, mo);
+
+		if (!(inside || touching))
+			continue;
+
+		if (!P_IsMobjTouchingPolyobj(mo, po, polysec))
+			continue;
+
+		return polysec;
+	}
+
+	return NULL;
+}
+
+sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number)
+{
+	msecnode_t *node;
+	sector_t *result;
+
+	result = P_MobjTouching3DFloorSpecial(mo, mo->subsector->sector, section, number);
+	if (result)
+		return result;
+
+	result = P_MobjTouchingPolyobjSpecial(mo, section, number);
+	if (result)
+		return result;
+
+	if (GETSECSPECIAL(mo->subsector->sector->special, section) == number)
+		return mo->subsector->sector;
+
+	for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
+	{
+		if (node->m_sector == mo->subsector->sector) // Don't duplicate
+			continue;
+
+		result = P_MobjTouching3DFloorSpecial(mo, node->m_sector, section, number);
+		if (result)
+			return result;
+
+		//TODO: Check polyobjects in node->m_sector
+
+		if (!(node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH))
+			continue;
+
+		if (GETSECSPECIAL(mo->subsector->sector->special, section) == number)
+			return node->m_sector;
+	}
+
+	return NULL;
+}
+
 //
 // P_PlayerTouchingSectorSpecial
 //
@@ -3939,63 +4032,10 @@ boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec)
 //
 sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number)
 {
-	msecnode_t *node;
-	ffloor_t *rover;
-
 	if (!player->mo)
 		return NULL;
 
-	// Check default case first
-	if (GETSECSPECIAL(player->mo->subsector->sector->special, section) == number)
-		return player->mo->subsector->sector;
-
-	// Hmm.. maybe there's a FOF that has it...
-	for (rover = player->mo->subsector->sector->ffloors; rover; rover = rover->next)
-	{
-		if (GETSECSPECIAL(rover->master->frontsector->special, section) != number)
-			continue;
-
-		if (!(rover->flags & FF_EXISTS))
-			continue;
-
-		if (!P_IsMobjTouching3DFloor(player->mo, rover, player->mo->subsector->sector))
-			continue;
-
-		// This FOF has the special we're looking for!
-		return rover->master->frontsector;
-	}
-
-	for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next)
-	{
-		if (GETSECSPECIAL(node->m_sector->special, section) == number)
-		{
-			// This sector has the special we're looking for, but
-			// are we allowed to touch it?
-			if (node->m_sector == player->mo->subsector->sector
-				|| (node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH))
-				return node->m_sector;
-		}
-
-		// Hmm.. maybe there's a FOF that has it...
-		for (rover = node->m_sector->ffloors; rover; rover = rover->next)
-		{
-			if (GETSECSPECIAL(rover->master->frontsector->special, section) != number)
-				continue;
-
-			if (!(rover->flags & FF_EXISTS))
-				continue;
-
-			if (!P_IsMobjTouching3DFloor(player->mo, rover, node->m_sector))
-				continue;
-
-			// This FOF has the special we're looking for, but are we allowed to touch it?
-			if (node->m_sector == player->mo->subsector->sector
-				|| (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH))
-				return rover->master->frontsector;
-		}
-	}
-
-	return NULL;
+	return P_MobjTouchingSectorSpecial(player->mo, section, number);
 }
 
 static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line_t *sourceline)
@@ -4874,35 +4914,6 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
 	}
 }
 
-/** Checks if an object is standing on or is inside a special 3D floor.
-  * If so, the sector is returned.
-  *
-  * \param mo Object to check.
-  * \return Pointer to the sector with a special type, or NULL if no special 3D
-  *         floors are being contacted.
-  * \sa P_PlayerOnSpecial3DFloor
-  */
-sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo)
-{
-	ffloor_t *rover;
-
-	for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next)
-	{
-		if (!rover->master->frontsector->special)
-			continue;
-
-		if (!(rover->flags & FF_EXISTS))
-			continue;
-
-		if (!P_IsMobjTouching3DFloor(mo, rover, mo->subsector->sector))
-			continue;
-
-		return rover->master->frontsector;
-	}
-
-	return NULL;
-}
-
 #define TELEPORTED(mo) (mo->subsector->sector != originalsector)
 
 /** Checks if a player is standing on or is inside a 3D floor (e.g. water) and
diff --git a/src/p_spec.h b/src/p_spec.h
index 79cd4a6f4..2ff2cd64c 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -320,6 +320,7 @@ void P_SpawnSpecials(boolean fromnetsave);
 
 // every tic
 void P_UpdateSpecials(void);
+sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number);
 sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number);
 void P_PlayerInSpecialSector(player_t *player);
 void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec);
@@ -922,6 +923,4 @@ void T_PlaneDisplace(planedisplace_t *pd);
 
 void P_CalcHeight(player_t *player);
 
-sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo);
-
 #endif