diff --git a/src/p_map.c b/src/p_map.c
index 337344b2fec2c966d0774513c02d9397b2974382..d6dcf8436fab5e6441a4c8b14a4f819ae8e28b34 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -2046,7 +2046,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 	tmbbox[BOXRIGHT] = x + tmthing->radius;
 	tmbbox[BOXLEFT] = x - tmthing->radius;
 
-	newsubsec = R_PointInSubsector(x, y);
+	if (thing->x != x || thing->y != y)
+		newsubsec = R_PointInSubsector(x, y);
+	else
+		newsubsec = thing->subsector;
 	ceilingline = blockingline = NULL;
 
 	// The base floor / ceiling is from the subsector
diff --git a/src/p_slopes.c b/src/p_slopes.c
index 12d5afd02fb96d7f19965e6f445de1e5b122a6d9..e7d084e690f71ff56f4692b04db64e1bc29b167f 100644
--- a/src/p_slopes.c
+++ b/src/p_slopes.c
@@ -588,7 +588,7 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
 		vx[i].y = mt->y << FRACBITS;
 		vx[i].z = mt->z << FRACBITS;
 		if (!mt->args[0])
-			vx[i].z += R_PointInSubsector(vx[i].x, vx[i].y)->sector->floorheight;
+			vx[i].z += R_OldPointInSubsector(vx[i].x, vx[i].y)->sector->floorheight;
 	}
 
 	ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]);
diff --git a/src/r_main.c b/src/r_main.c
index f1864a37e5f4fa7a31e56483f505c383dd878728..63a8836a102dc577d80b43cdb37b22bb8af60fba 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -255,7 +255,7 @@ static void FlipCam2_OnChange(void)
 //
 // killough 5/2/98: reformatted
 //
-INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *restrict node)
+INT32 R_OldPointOnSide(fixed_t x, fixed_t y, node_t *restrict node)
 {
 	if (!node->dx)
 		return x <= node->x ? node->dy > 0 : node->dy < 0;
@@ -274,7 +274,7 @@ INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *restrict node)
 }
 
 // killough 5/2/98: reformatted
-INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line)
+INT32 R_OldPointOnSegSide(fixed_t x, fixed_t y, seg_t *line)
 {
 	fixed_t lx = line->v1->x;
 	fixed_t ly = line->v1->y;
@@ -1071,6 +1071,16 @@ boolean R_IsPointInSector(sector_t *sector, fixed_t x, fixed_t y)
 	return passes % 2;
 }
 
+subsector_t *R_OldPointInSubsector(fixed_t x, fixed_t y)
+{
+	size_t nodenum = numnodes-1;
+
+	while (!(nodenum & NF_SUBSECTOR))
+		nodenum = nodes[nodenum].children[R_OldPointOnSide(x, y, nodes+nodenum)];
+
+	return &subsectors[nodenum & ~NF_SUBSECTOR];
+}
+
 //
 // R_PointInSubsector
 //
diff --git a/src/r_main.h b/src/r_main.h
index 360699f722a76bde7beab9c7922d7c8269a4b48a..3ad20fccde4304fcbc4e0a68fe6eeca04843e799 100644
--- a/src/r_main.h
+++ b/src/r_main.h
@@ -71,9 +71,29 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
 // There a 0-31, i.e. 32 LUT in the COLORMAP lump.
 #define NUMCOLORMAPS 32
 
+INT32 R_OldPointOnSide(fixed_t x, fixed_t y, node_t *node);
+INT32 R_OldPointOnSegSide(fixed_t x, fixed_t y, seg_t *line);
+
 // Utility functions.
-INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node);
-INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line);
+static inline INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node)
+{
+	// use cross product to determine side quickly
+	INT64 v = ((INT64)y - node->y) * node->dx - ((INT64)x - node->x) * node->dy;
+	return v >= 0;
+}
+
+static inline INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line)
+{
+	fixed_t lx = line->v1->x;
+	fixed_t ly = line->v1->y;
+	fixed_t ldx = line->v2->x - lx;
+	fixed_t ldy = line->v2->y - ly;
+
+	// use cross product to determine side quickly
+	INT64 v = ((INT64)y - ly) * ldx - ((INT64)x - lx) * ldy;
+	return v >= 0;
+}
+
 angle_t R_PointToAngle(fixed_t x, fixed_t y);
 angle_t R_PointToAngle64(INT64 x, INT64 y);
 angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
@@ -81,6 +101,7 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y);
 fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
 
 boolean R_IsPointInSector(sector_t *sector, fixed_t x, fixed_t y);
+subsector_t *R_OldPointInSubsector(fixed_t x, fixed_t y);
 subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);
 subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y);