diff --git a/src/doomdef.h b/src/doomdef.h
index a978e047ba3ecad97cbebbbfd44cb57273b158f6..ad45f497b8a4d4d9376cd9cbcad31f5c8a78d3ab 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -453,7 +453,7 @@ extern const char *compdate, *comptime, *comprevision;
 //#define CHAOSISNOTDEADYET
 
 ///	Polyobject fake flat code
-//#define POLYOBJECTS_PLANES
+#define POLYOBJECTS_PLANES
 
 ///	Blue spheres for future use.
 ///	\todo	Remove this define.
diff --git a/src/r_bsp.c b/src/r_bsp.c
index 5a90f1fca7e6c1266b16f98ac5e1ad4e106ce278..cfd628b5c5f53e419f7b1c416706da6077810e1a 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -683,6 +683,33 @@ void R_SortPolyObjects(subsector_t *sub)
 	}
 }
 
+//
+// R_PolysegCompare
+//
+// Callback for qsort to sort the segs of a polyobject. Returns such that the
+// closer one is sorted first. I sure hope this doesn't break anything. -Red
+//
+static int R_PolysegCompare(const void *p1, const void *p2)
+{
+	const seg_t *seg1 = *(const seg_t * const *)p1;
+	const seg_t *seg2 = *(const seg_t * const *)p2;
+	fixed_t dist1, dist2;
+
+	// TODO might be a better way to get distance?
+#define vxdist(v) FixedMul(R_PointToDist(v->x, v->y), FINECOSINE((R_PointToAngle(v->x, v->y)-viewangle)>>ANGLETOFINESHIFT))+0xFFFFFFF
+
+	dist1 = min(vxdist(seg1->v1), vxdist(seg1->v2));
+	dist2 = min(vxdist(seg2->v1), vxdist(seg2->v2));
+
+	if (dist1 == dist2) { // Segs connect toward the front, so use the back verts to determine order!
+		dist1 = max(vxdist(seg1->v1), vxdist(seg1->v2));
+		dist2 = max(vxdist(seg2->v1), vxdist(seg2->v2));
+	}
+#undef vxdist
+
+	return dist1-dist2;
+}
+
 //
 // R_AddPolyObjects
 //
@@ -709,6 +736,7 @@ static void R_AddPolyObjects(subsector_t *sub)
 	// render polyobjects
 	for (i = 0; i < numpolys; ++i)
 	{
+		qsort(po_ptrs[i]->segs, po_ptrs[i]->segCount, sizeof(seg_t *), R_PolysegCompare);
 		for (j = 0; j < po_ptrs[i]->segCount; ++j)
 			R_AddLine(po_ptrs[i]->segs[j]);
 	}
@@ -909,15 +937,28 @@ static void R_Subsector(size_t num)
 				&& polysec->floorheight >= frontsector->floorheight
 				&& (viewz < polysec->floorheight))
 			{
+				fixed_t xoff, yoff;
+				xoff = polysec->floor_xoffs;
+				yoff = polysec->floor_yoffs;
+
+				if (po->angle != 0) {
+					angle_t fineshift = po->angle >> ANGLETOFINESHIFT;
+
+					xoff -= FixedMul(FINECOSINE(fineshift), po->centerPt.x)+FixedMul(FINESINE(fineshift), po->centerPt.y);
+					yoff -= FixedMul(FINESINE(fineshift), po->centerPt.x)-FixedMul(FINECOSINE(fineshift), po->centerPt.y);
+				} else {
+					xoff -= po->centerPt.x;
+					yoff += po->centerPt.y;
+				}
+
 				light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
 				light = 0;
 				ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
-						polysec->lightlevel, polysec->floor_xoffs,
-						polysec->floor_yoffs,
-						polysec->floorpic_angle,
+						polysec->lightlevel, xoff, yoff,
+						polysec->floorpic_angle-po->angle,
 						NULL,
 						NULL);
-				ffloor[numffloors].plane->polyobj = true;
+				ffloor[numffloors].plane->polyobj = po;
 
 				ffloor[numffloors].height = polysec->floorheight;
 				ffloor[numffloors].polyobj = po;
@@ -934,12 +975,27 @@ static void R_Subsector(size_t num)
 				&& polysec->ceilingheight <= frontsector->ceilingheight
 				&& (viewz > polysec->ceilingheight))
 			{
+				fixed_t xoff, yoff;
+				xoff = polysec->ceiling_xoffs;
+				yoff = polysec->ceiling_yoffs;
+
+				if (po->angle != 0) {
+					angle_t fineshift = po->angle >> ANGLETOFINESHIFT;
+
+					xoff -= FixedMul(FINECOSINE(fineshift), po->centerPt.x)+FixedMul(FINESINE(fineshift), po->centerPt.y);
+					yoff -= FixedMul(FINESINE(fineshift), po->centerPt.x)-FixedMul(FINECOSINE(fineshift), po->centerPt.y);
+				} else {
+					xoff -= po->centerPt.x;
+					yoff += po->centerPt.y;
+				}
+
 				light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight);
 				light = 0;
 				ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
-					polysec->lightlevel, polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle,
+					polysec->lightlevel, xoff, yoff, polysec->ceilingpic_angle-po->angle,
 					NULL, NULL);
-				ffloor[numffloors].plane->polyobj = true;
+				ffloor[numffloors].plane->polyobj = po;
+
 				ffloor[numffloors].polyobj = po;
 				ffloor[numffloors].height = polysec->ceilingheight;
 //				ffloor[numffloors].ffloor = rover;
diff --git a/src/r_plane.c b/src/r_plane.c
index 7e1764fc549dfee930a2bc910209051e551e2ee6..5833bf6d50ea2a1234e8d2a24de9ee288ae02095 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -409,6 +409,10 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 
 	for (check = visplanes[hash]; check; check = check->next)
 	{
+#ifdef POLYOBJECTS_PLANES
+		if (check->polyobj && pfloor)
+			continue;
+#endif
 		if (height == check->height && picnum == check->picnum
 			&& lightlevel == check->lightlevel
 			&& xoff == check->xoffs && yoff == check->yoffs
@@ -434,6 +438,9 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 	check->viewz = viewz;
 	check->viewangle = viewangle + plangle;
 	check->plangle = plangle;
+#ifdef POLYOBJECTS_PLANES
+	check->polyobj = NULL;
+#endif
 
 	memset(check->top, 0xff, sizeof (check->top));
 	memset(check->bottom, 0x00, sizeof (check->bottom));
@@ -666,6 +673,42 @@ void R_DrawSinglePlane(visplane_t *pl)
 	itswater = false;
 #endif
 	spanfunc = basespanfunc;
+
+#ifdef POLYOBJECTS_PLANES
+	if (pl->polyobj && pl->polyobj->translucency != 0) {
+		spanfunc = R_DrawTranslucentSpan_8;
+
+		// Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red)
+		if (pl->polyobj->translucency >= 10)
+			return; // Don't even draw it
+		else if (pl->polyobj->translucency == 9)
+			ds_transmap = ((tr_trans90)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else if (pl->polyobj->translucency == 8)
+			ds_transmap = ((tr_trans80)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else if (pl->polyobj->translucency == 7)
+			ds_transmap = ((tr_trans70)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else if (pl->polyobj->translucency == 6)
+			ds_transmap = ((tr_trans60)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else if (pl->polyobj->translucency == 5)
+			ds_transmap = ((tr_trans50)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else if (pl->polyobj->translucency == 4)
+			ds_transmap = ((tr_trans40)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else if (pl->polyobj->translucency == 3)
+			ds_transmap = ((tr_trans30)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else if (pl->polyobj->translucency == 2)
+			ds_transmap = ((tr_trans20)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else if (pl->polyobj->translucency == 1)
+			ds_transmap = ((tr_trans10)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else // Opaque, but allow transparent flat pixels
+			spanfunc = splatfunc;
+
+		if (pl->extra_colormap && pl->extra_colormap->fog)
+			light = (pl->lightlevel >> LIGHTSEGSHIFT);
+		else
+		light = LIGHTLEVELS-1;
+
+	} else
+#endif
 	if (pl->ffloor)
 	{
 		// Don't draw planes that shouldn't be drawn.
diff --git a/src/r_plane.h b/src/r_plane.h
index 1f046588f3941748d6815484d02b4f5d4f1f19ee..bd0df27c08f1fcb6f195055f8ccb69983f80ffc3 100644
--- a/src/r_plane.h
+++ b/src/r_plane.h
@@ -59,7 +59,7 @@ typedef struct visplane_s
 
 	struct ffloor_s *ffloor;
 #ifdef POLYOBJECTS_PLANES
-	boolean polyobj;
+	polyobj_t *polyobj;
 #endif
 } visplane_t;
 
diff --git a/src/r_segs.c b/src/r_segs.c
index 1070bff7c01e896d288f2b1f5bc554b060e32c76..a3da0f3cab93e1aae888ae7324896a80b4519eff 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -589,7 +589,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 				// draw the texture
 				col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
 
-#ifdef POLYOBJECTS_PLANES
+//#ifdef POLYOBJECTS_PLANES
+#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red
 				if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES))
 				{
 					fixed_t my_topscreen;
@@ -611,7 +612,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 
 						for (i = 0; i < numffloors; i++)
 						{
-							if (!ffloor[i].polyobj)
+							if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)
 								continue;
 
 							if (ffloor[i].height < viewz)
@@ -1120,8 +1121,16 @@ static void R_RenderSegLoop (void)
 			for (i = 0; i < numffloors; i++)
 			{
 #ifdef POLYOBJECTS_PLANES
-				if (curline->polyseg && !ffloor[i].polyobj)
-					continue;
+				//if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
+					//continue; // Causes issues with FOF planes in The Wall -Red
+
+				// FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red
+				if (curline->polyseg) {
+					if (ffloor[i].plane->minx > rw_x)
+						ffloor[i].plane->minx = rw_x;
+					else if (ffloor[i].plane->maxx < rw_x)
+						ffloor[i].plane->maxx = rw_x;
+				}
 #endif
 
 				if (ffloor[i].height < viewz)
@@ -1135,6 +1144,13 @@ static void R_RenderSegLoop (void)
 					if (bottom_w > bottom)
 						bottom_w = bottom;
 
+#ifdef POLYOBJECTS_PLANES
+					// Polyobject-specific hack to fix plane leaking -Red
+					if (curline->polyseg && ffloor[i].polyobj && ffloor[i].polyobj == curline->polyseg && top_w >= bottom_w) {
+						ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF;
+					} else
+#endif
+
 					if (top_w <= bottom_w)
 					{
 						ffloor[i].plane->top[rw_x] = (INT16)top_w;
@@ -1152,6 +1168,13 @@ static void R_RenderSegLoop (void)
 					if (bottom_w > bottom)
 						bottom_w = bottom;
 
+#ifdef POLYOBJECTS_PLANES
+					// Polyobject-specific hack to fix plane leaking -Red
+					if (curline->polyseg && ffloor[i].polyobj && ffloor[i].polyobj == curline->polyseg && top_w >= bottom_w) {
+						ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF;
+					} else
+#endif
+
 					if (top_w <= bottom_w)
 					{
 						ffloor[i].plane->top[rw_x] = (INT16)top_w;
@@ -1327,9 +1350,9 @@ static void R_RenderSegLoop (void)
 
 		for (i = 0; i < numffloors; i++)
 		{
-#ifdef POLYOBJECTS_PLANES
-			if (curline->polyseg && !ffloor[i].polyobj)
-				continue;
+#if 0 //#ifdef POLYOBJECTS_PLANES
+			if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
+				continue; // Causes issues with FOF planes in The Wall -Red
 #endif
 
 			ffloor[i].f_frac += ffloor[i].f_step;
@@ -1339,9 +1362,9 @@ static void R_RenderSegLoop (void)
 		{
 			INT32 y_w;
 
-#ifdef POLYOBJECTS_PLANES
-			if (curline->polyseg && !ffloor[i].polyobj)
-				continue;
+#if 0 //#ifdef POLYOBJECTS_PLANES
+			if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
+				continue; // Causes issues with FOF planes in The Wall -Red
 #endif
 			y_w = ffloor[i].b_frac >> HEIGHTBITS;
 
@@ -1488,9 +1511,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	{
 		for (i = 0; i < numffloors; i++)
 		{
-#ifdef POLYOBJECTS_PLANES
-			if (ds_p->curline->polyseg && !ffloor[i].polyobj)
-					continue;
+#if 0 //#ifdef POLYOBJECTS_PLANES
+			if (ds_p->curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != ds_p->curline->polyseg))
+				continue; // Causes issues with FOF planes in The Wall -Red
 #endif
 			ffloor[i].f_pos = ffloor[i].height - viewz;
 		}
@@ -1989,8 +2012,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	{
 		for (i = 0; i < numffloors; i++)
 		{
-//			if (curline->polyseg && !ffloor[i].polyobj)
-//					continue;
+#if 0 //#ifdef POLYOBJECTS_PLANES
+			if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
+				continue; // Causes issues with FOF planes in The Wall -Red
+#endif
 
 			ffloor[i].f_pos >>= 4;
 			ffloor[i].f_step = FixedMul(-rw_scalestep, ffloor[i].f_pos);
diff --git a/src/r_things.c b/src/r_things.c
index c0f33dafb7af18dd6af78491301b1579c92e97ab..4fc785773d666770ba15063cca13e0038a34ad50 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1830,6 +1830,20 @@ static void R_CreateDrawNodes(void)
 			}
 			else if (r2->seg)
 			{
+#ifdef POLYOBJECTS_PLANES
+				if (r2->seg->curline->polyseg && rover->mobj && P_MobjInsidePolyobj(r2->seg->curline->polyseg, rover->mobj)) {
+					// Determine if we need to sort in front of the polyobj, based on the planes. This fixes the issue where
+					// polyobject planes render above the object standing on them. (A bit hacky... but it works.) -Red
+					mobj_t *mo = rover->mobj;
+					sector_t *po = r2->seg->curline->backsector;
+
+					if (po->ceilingheight < viewz && mo->z+mo->height > po->ceilingheight)
+						continue;
+
+					if (po->floorheight > viewz && mo->z < po->floorheight)
+						continue;
+				}
+#endif
 				if (rover->x1 > r2->seg->x2 || rover->x2 < r2->seg->x1)
 					continue;