diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg
index f97da48cc26da6cb9d5d88d60563e1f920e1a35d..b04b5e16a50d4b3e1f8b2fafa6a7048b732e04f2 100644
--- a/extras/conf/udb/Includes/SRB222_linedefs.cfg
+++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg
@@ -2772,6 +2772,7 @@ udmf
 				title = "Return delay";
 			}
 		}
+
 		481
 		{
 			title = "Door Swing";
@@ -2787,7 +2788,7 @@ udmf
 			}
 			arg2
 			{
-				title = "Angle distance";
+				title = "Rotation";
 				type = 8;
 			}
 			arg3
@@ -2795,6 +2796,63 @@ udmf
 				title = "Return delay";
 			}
 		}
+
+		482
+		{
+			title = "Move";
+			prefix = "(482)";
+			arg0
+			{
+				title = "PolyObject ID";
+				type = 14;
+			}
+			arg1
+			{
+				title = "Speed";
+			}
+			arg2
+			{
+				title = "Distance";
+			}
+			arg3
+			{
+				title = "Override?";
+				type = 11;
+				enum = "noyes";
+			}
+		}
+
+		484
+		{
+			title = "Rotate";
+			prefix = "(484)";
+			arg0
+			{
+				title = "PolyObject ID";
+				type = 14;
+			}
+			arg1
+			{
+				title = "Speed";
+			}
+			arg2
+			{
+				title = "Rotation";
+				type = 8;
+			}
+			arg3
+			{
+				title = "Flags";
+				type = 12;
+				enum
+				{
+					1 = "Don't turn others";
+					2 = "Turn players";
+					4 = "Continuous rotation";
+					8 = "Override";
+				}
+			}
+		}
 	}
 
 	scrollpush
diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c
index 5d76a912de0c06948dee8ecbb8039bfb356033ec..87dfad7f68cff40041c16bf28a005c294b06d8eb 100644
--- a/src/lua_polyobjlib.c
+++ b/src/lua_polyobjlib.c
@@ -244,13 +244,14 @@ static int lib_polyobj_rotate(lua_State *L)
 {
 	polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
 	angle_t delta = luaL_checkangle(L, 2);
-	UINT8 turnthings = (UINT8)luaL_optinteger(L, 3, 0); // don't turn anything by default? (could change this if not desired)
-	boolean checkmobjs = lua_opttrueboolean(L, 4);
+	boolean turnplayers = lua_opttrueboolean(L, 3);
+	boolean turnothers = lua_opttrueboolean(L, 4);
+	boolean checkmobjs = lua_opttrueboolean(L, 5);
 	NOHUD
 	INLEVEL
 	if (!po)
 		return LUA_ErrInvalid(L, "polyobj_t");
-	lua_pushboolean(L, Polyobj_rotate(po, delta, turnthings, checkmobjs));
+	lua_pushboolean(L, Polyobj_rotate(po, delta, turnplayers, turnothers, checkmobjs));
 	return 1;
 }
 
diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 6431e46248f0f426de801e2c2e95d9835ab07ff0..47327c94921b5364d2d3ae8ceb3e4d461f4b4521 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -1089,7 +1089,7 @@ static void Polyobj_rotateLine(line_t *ld)
 }
 
 // Causes objects resting on top of the rotating polyobject to 'ride' with its movement.
-static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, UINT8 turnthings)
+static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, boolean turnplayers, boolean turnothers)
 {
 	static INT32 pomovecount = 10000;
 	INT32 x, y;
@@ -1151,7 +1151,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
 
 					Polyobj_slideThing(mo, newxoff, newyoff);
 
-					if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
+					if ((turnplayers && mo->player) || (turnothers && !mo->player)) {
 						mo->angle += delta;
 						if (mo->player)
 							P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta);
@@ -1163,7 +1163,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
 }
 
 // Rotates a polyobject around its start point.
-boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs)
+boolean Polyobj_rotate(polyobj_t *po, angle_t delta, boolean turnplayers, boolean turnothers, boolean checkmobjs)
 {
 	size_t i;
 	angle_t angle;
@@ -1201,7 +1201,7 @@ boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean c
 		for (i = 0; i < po->numLines; ++i)
 			hitflags |= Polyobj_clipThings(po, po->lines[i]);
 
-		Polyobj_rotateThings(po, origin, delta, turnthings);
+		Polyobj_rotateThings(po, origin, delta, turnplayers, turnothers);
 	}
 
 	if (hitflags & 2)
@@ -1409,7 +1409,7 @@ void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y)
 	fixed_t dx, dy;
 
 	// first, rotate to the saved angle
-	Polyobj_rotate(po, angle, false, false);
+	Polyobj_rotate(po, angle, false, false, false);
 
 	// determine component distances to translate
 	dx = x - po->spawnSpot.x;
@@ -1452,7 +1452,7 @@ void T_PolyObjRotate(polyrotate_t *th)
 
 	// rotate by 'speed' angle per frame
 	// if distance == -1, this polyobject rotates perpetually
-	if (Polyobj_rotate(po, th->speed, th->turnobjs, true) && th->distance != -1)
+	if (Polyobj_rotate(po, th->speed, th->turnobjs & PTF_PLAYERS, th->turnobjs & PTF_OTHERS, true) && th->distance != -1)
 	{
 		INT32 avel = abs(th->speed);
 
@@ -1854,7 +1854,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th)
 
 	// rotate by 'speed' angle per frame
 	// if distance == -1, this polyobject rotates perpetually
-	if (Polyobj_rotate(po, th->speed, false, true) && th->distance != -1)
+	if (Polyobj_rotate(po, th->speed, false, false, true) && th->distance != -1)
 	{
 		INT32 avel = abs(th->speed);
 
@@ -1985,7 +1985,7 @@ void T_PolyObjRotDisplace(polyrotdisplace_t *th)
 
 	rotangle = FixedMul(th->rotscale, delta);
 
-	if (Polyobj_rotate(po, FixedAngle(rotangle), th->turnobjs, true))
+	if (Polyobj_rotate(po, FixedAngle(rotangle), th->turnobjs & PTF_PLAYERS, th->turnobjs & PTF_OTHERS, true))
 		th->oldHeights = newheights;
 }
 
@@ -2014,7 +2014,7 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata)
 		return false;
 
 	// check for override if this polyobj already has a thinker
-	if (po->thinker && !prdata->overRide)
+	if (po->thinker && !(prdata->flags & TMPR_OVERRIDE))
 		return false;
 
 	// create a new thinker
@@ -2029,10 +2029,10 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata)
 	// use Hexen-style byte angles for speed and distance
 	th->speed = Polyobj_AngSpeed(prdata->speed * prdata->direction);
 
-	if (prdata->distance == 360)    // 360 means perpetual
+	if (prdata->flags & TMPR_CONTINUOUS)
 		th->distance = -1;
-	else if (prdata->distance == 0) // 0 means 360 degrees
-		th->distance = 0xffffffff - 1;
+	else if (prdata->distance == 360)
+		th->distance = ANGLE_MAX - 1;
 	else
 		th->distance = FixedAngle(prdata->distance*FRACUNIT);
 
@@ -2047,7 +2047,11 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata)
 
 	oldpo = po;
 
-	th->turnobjs = prdata->turnobjs;
+	th->turnobjs = 0;
+	if (!(prdata->flags & TMPR_DONTROTATEOTHERS))
+		th->turnobjs |= PTF_OTHERS;
+	if (prdata->flags & TMPR_ROTATEPLAYERS)
+		th->turnobjs |= PTF_PLAYERS;
 
 	// apply action to mirroring polyobjects as well
 	start = 0;
diff --git a/src/p_polyobj.h b/src/p_polyobj.h
index 7c814e0bf14766bf6f6cf2af134675389d0f8797..9c80940284d03848184913d342cb0e4703fd5b60 100644
--- a/src/p_polyobj.h
+++ b/src/p_polyobj.h
@@ -137,7 +137,7 @@ typedef struct polyrotate_s
 	INT32 polyObjNum;    // numeric id of polyobject (avoid C pointers here)
 	INT32 speed;         // speed of movement per frame
 	INT32 distance;      // distance to move
-	UINT8 turnobjs;      // turn objects? 0=no, 1=everything but players, 2=everything
+	UINT8 turnobjs;      // turn objects? PTF_ flags
 } polyrotate_t;
 
 typedef struct polymove_s
@@ -247,14 +247,27 @@ typedef struct polyfade_s
 // Line Activation Data Structures
 //
 
+typedef enum
+{
+	TMPR_DONTROTATEOTHERS = 1,
+	TMPR_ROTATEPLAYERS    = 1<<1,
+	TMPR_CONTINUOUS       = 1<<2,
+	TMPR_OVERRIDE         = 1<<3,
+} textmappolyrotate_t;
+
+typedef enum
+{
+	PTF_PLAYERS = 1,    // Turn players with movement
+	PTF_OTHERS = 1<<1, // Turn other mobjs with movement
+} polyturnflags_e;
+
 typedef struct polyrotdata_s
 {
 	INT32 polyObjNum;   // numeric id of polyobject to affect
 	INT32 direction;    // direction of rotation
 	INT32 speed;        // angular speed
 	INT32 distance;     // distance to move
-	UINT8 turnobjs;     // rotate objects being carried?
-	UINT8 overRide;     // if true, will override any action on the object
+	UINT8 flags;        // TMPR_ flags
 } polyrotdata_t;
 
 typedef struct polymovedata_s
@@ -337,7 +350,7 @@ typedef struct polyfadedata_s
 //
 
 boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs);
-boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs);
+boolean Polyobj_rotate(polyobj_t *po, angle_t delta, boolean turnplayers, boolean turnothers, boolean checkmobjs);
 polyobj_t *Polyobj_GetForNum(INT32 id);
 void Polyobj_InitLevel(void);
 void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y);
diff --git a/src/p_setup.c b/src/p_setup.c
index 947ec8a1e842f5b3dd105951b602d79f7ade6422..7617e863f900a1a069f96ea2d2f7bd4bac900a56 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -3671,6 +3671,35 @@ static void P_ConvertBinaryMap(void)
 			if (lines[i].sidenum[1] != 0xffff)
 				lines[i].args[3] = sides[lines[i].sidenum[1]].textureoffset >> FRACBITS;
 			break;
+		case 482: //Polyobject - move
+		case 483: //Polyobject - move, override
+			lines[i].args[0] = tag;
+			lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS;
+			lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS;
+			lines[i].args[3] = lines[i].special == 483;
+			lines[i].special = 482;
+			break;
+		case 484: //Polyobject - rotate right
+		case 485: //Polyobject - rotate right, override
+		case 486: //Polyobject - rotate left
+		case 487: //Polyobject - rotate left, override
+			lines[i].args[0] = tag;
+			lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS;
+			lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS;
+			if (lines[i].args[2] == 360)
+				lines[i].args[3] |= TMPR_CONTINUOUS;
+			else if (lines[i].args[2] == 0)
+				lines[i].args[2] = 360;
+			if (lines[i].special < 486)
+				lines[i].args[2] *= -1;
+			if (lines[i].flags & ML_NOCLIMB)
+				lines[i].args[3] |= TMPR_DONTROTATEOTHERS;
+			else if (lines[i].flags & ML_EFFECT4)
+				lines[i].args[3] |= TMPR_ROTATEPLAYERS;
+			if (lines[i].special % 2 == 1)
+				lines[i].args[3] |= TMPR_OVERRIDE;
+			lines[i].special = 484;
+			break;
 		case 500: //Scroll front wall left
 		case 501: //Scroll front wall right
 			lines[i].args[0] = 0;
diff --git a/src/p_spec.c b/src/p_spec.c
index e167d454ee6ab086fe2f2a01b7b7d93bb48c97df..6434a55d7afac78db7ce786ed07ad8d71855335d 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1016,17 +1016,17 @@ static boolean PolyDoor(line_t *line)
 	return EV_DoPolyDoor(&pdd);
 }
 
-// Parses arguments for parameterized polyobject move specials
+// Parses arguments for parameterized polyobject move special
 static boolean PolyMove(line_t *line)
 {
 	polymovedata_t pmd;
 
-	pmd.polyObjNum = Tag_FGet(&line->tags);
-	pmd.speed      = sides[line->sidenum[0]].textureoffset / 8;
+	pmd.polyObjNum = line->args[0];
+	pmd.speed      = line->args[1] << (FRACBITS - 3);
 	pmd.angle      = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y);
-	pmd.distance   = sides[line->sidenum[0]].rowoffset;
+	pmd.distance   = line->args[2] << FRACBITS;
 
-	pmd.overRide = (line->special == 483); // Polyobj_OR_Move
+	pmd.overRide = !!line->args[3]; // Polyobj_OR_Move
 
 	return EV_DoPolyObjMove(&pmd);
 }
@@ -1200,27 +1200,16 @@ static boolean PolyWaypoint(line_t *line)
 	return EV_DoPolyObjWaypoint(&pwd);
 }
 
-// Parses arguments for parameterized polyobject rotate specials
+// Parses arguments for parameterized polyobject rotate special
 static boolean PolyRotate(line_t *line)
 {
 	polyrotdata_t prd;
 
-	prd.polyObjNum = Tag_FGet(&line->tags);
-	prd.speed      = sides[line->sidenum[0]].textureoffset >> FRACBITS; // angular speed
-	prd.distance   = sides[line->sidenum[0]].rowoffset >> FRACBITS; // angular distance
-
-	// Polyobj_(OR_)RotateRight have dir == -1
-	prd.direction = (line->special == 484 || line->special == 485) ? -1 : 1;
-
-	// Polyobj_OR types have override set to true
-	prd.overRide  = (line->special == 485 || line->special == 487);
-
-	if (line->flags & ML_NOCLIMB)
-		prd.turnobjs = 0;
-	else if (line->flags & ML_EFFECT4)
-		prd.turnobjs = 2;
-	else
-		prd.turnobjs = 1;
+	prd.polyObjNum = line->args[0];
+	prd.speed      = line->args[1]; // angular speed
+	prd.distance   = abs(line->args[2]); // angular distance
+	prd.direction  = (line->args[2] < 0) ? -1 : 1;
+	prd.flags      = line->args[3];
 
 	return EV_DoPolyObjRotate(&prd);
 }
@@ -1272,9 +1261,9 @@ static boolean PolyRotDisplace(line_t *line)
 	if (line->flags & ML_NOCLIMB)
 		pdd.turnobjs = 0;
 	else if (line->flags & ML_EFFECT4)
-		pdd.turnobjs = 2;
+		pdd.turnobjs = PTF_PLAYERS|PTF_OTHERS;
 	else
-		pdd.turnobjs = 1;
+		pdd.turnobjs = PTF_OTHERS;
 
 	return EV_DoPolyObjRotDisplace(&pdd);
 }
@@ -3906,13 +3895,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			PolyDoor(line);
 			break;
 		case 482: // Polyobj_Move
-		case 483: // Polyobj_OR_Move
 			PolyMove(line);
 			break;
 		case 484: // Polyobj_RotateRight
-		case 485: // Polyobj_OR_RotateRight
-		case 486: // Polyobj_RotateLeft
-		case 487: // Polyobj_OR_RotateLeft
 			PolyRotate(line);
 			break;
 		case 488: // Polyobj_Waypoint