diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 7e1097ceda8dea4cd9ab342960f078b2a3958b90..f74314c70f9fc3e2d93f4236d9e3d3851ca60e87 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -158,7 +158,6 @@ enum vertex_e {
 	vertex_valid = 0,
 	vertex_x,
 	vertex_y,
-	vertex_z,
 	vertex_floorz,
 	vertex_floorzset,
 	vertex_ceilingz,
@@ -169,7 +168,6 @@ static const char *const vertex_opt[] = {
 	"valid",
 	"x",
 	"y",
-	"z",
 	"floorz",
 	"floorzset",
 	"ceilingz",
@@ -978,9 +976,6 @@ static int vertex_get(lua_State *L)
 	case vertex_y:
 		lua_pushfixed(L, vertex->y);
 		return 1;
-	case vertex_z:
-		lua_pushfixed(L, vertex->z);
-		return 1;
 	case vertex_floorzset:
 		lua_pushboolean(L, vertex->floorzset);
 		return 1;
diff --git a/src/p_maputl.c b/src/p_maputl.c
index f598595e2a22b1b49756ebd51d76beab0840fb33..afa0205042a5d6b9394660b48a24cbc2ee2aa805 100644
--- a/src/p_maputl.c
+++ b/src/p_maputl.c
@@ -78,68 +78,37 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result)
 	return;
 }
 
-//
-// P_ClosestPointOnLine3D
-// Finds the closest point on a given line to the supplied point IN 3D!!!
-//
-void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result)
+/// Similar to FV3_ClosestPointOnLine() except it actually works.
+void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *Line, vector3_t *result)
 {
-	fixed_t startx = line->v1->x;
-	fixed_t starty = line->v1->y;
-	fixed_t startz = line->v1->z;
-	fixed_t dx = line->dx;
-	fixed_t dy = line->dy;
-	fixed_t dz = line->v2->z - line->v1->z;
+	const vector3_t* v1 = &Line[0];
+	const vector3_t* v2 = &Line[1];
+	vector3_t c, V, n;
+	fixed_t t, d;
+	FV3_SubEx(v2, v1, &V);
+	FV3_SubEx(p, v1, &c);
 
-	// Determine t (the length of the vector from �Line[0]� to �p�)
-	fixed_t cx, cy, cz;
-	fixed_t vx, vy, vz;
-	fixed_t magnitude;
-	fixed_t t;
+	d = R_PointToDist2(0, v2->z, R_PointToDist2(v2->x, v2->y, v1->x, v1->y), v1->z);
+	FV3_Copy(&n, &V);
+	FV3_Divide(&n, d);
 
-	//Sub (p, &Line[0], &c);
-	cx = x - startx;
-	cy = y - starty;
-	cz = z - startz;
-
-	//Sub (&Line[1], &Line[0], &V);
-	vx = dx;
-	vy = dy;
-	vz = dz;
-
-	//Normalize (&V, &V);
-	magnitude = R_PointToDist2(0, line->v2->z, R_PointToDist2(line->v2->x, line->v2->y, startx, starty), startz);
-	vx = FixedDiv(vx, magnitude);
-	vy = FixedDiv(vy, magnitude);
-	vz = FixedDiv(vz, magnitude);
-
-	t = (FixedMul(vx, cx) + FixedMul(vy, cy) + FixedMul(vz, cz));
+	t = FV3_Dot(&n, &c);
 
 	// Set closest point to the end if it extends past -Red
 	if (t <= 0)
 	{
-		result->x = line->v1->x;
-		result->y = line->v1->y;
-		result->z = line->v1->z;
+		FV3_Copy(result, v1);
 		return;
 	}
-	else if (t >= magnitude)
+	else if (t >= d)
 	{
-		result->x = line->v2->x;
-		result->y = line->v2->y;
-		result->z = line->v2->z;
+		FV3_Copy(result, v2);
 		return;
 	}
 
-	// Return the point between �Line[0]� and �Line[1]�
-	vx = FixedMul(vx, t);
-	vy = FixedMul(vy, t);
-	vz = FixedMul(vz, t);
+	FV3_Mul(&n, t);
 
-	//Add (&Line[0], &V, out);
-	result->x = startx + vx;
-	result->y = starty + vy;
-	result->z = startz + vz;
+	FV3_AddEx(v1, &n, result);
 	return;
 }
 
diff --git a/src/p_maputl.h b/src/p_maputl.h
index 2ca7187794d5fa741623d6c789e73d6926667d95..16cfc834e0e0341f5e93fb0dd090828700ef6c14 100644
--- a/src/p_maputl.h
+++ b/src/p_maputl.h
@@ -43,7 +43,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
 
 FUNCMATH fixed_t P_AproxDistance(fixed_t dx, fixed_t dy);
 void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result);
-void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result);
+void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *line, vector3_t *result);
 INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line);
 void P_MakeDivline(line_t *li, divline_t *dl);
 void P_CameraLineOpening(line_t *plinedef);
diff --git a/src/p_setup.c b/src/p_setup.c
index a1aaeb4ba87ac514235029e815e7778c5cd4f3ec..2819cb5708d73f3d38205f4b18444ce45a026337 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -846,7 +846,6 @@ static void P_LoadVertices(UINT8 *data)
 	{
 		v->x = SHORT(mv->x)<<FRACBITS;
 		v->y = SHORT(mv->y)<<FRACBITS;
-		v->z = 0;
 	}
 }
 
@@ -1585,7 +1584,6 @@ static void P_LoadTextmap(void)
 	{
 		// Defaults.
 		vt->x = vt->y = INT32_MAX;
-		vt->z = 0;
 		vt->floorzset = vt->ceilingzset = false;
 		vt->floorz = vt->ceilingz = 0;
 
diff --git a/src/p_spec.c b/src/p_spec.c
index a97d1f92ffd467389da8834a951b6c278c25558e..00a71602ba21cb94c9a1e179557131e3866930cb 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -5038,8 +5038,7 @@ DoneSection2:
 				mobj_t *waypointlow = NULL;
 				mobj_t *mo2;
 				mobj_t *closest = NULL;
-				line_t junk;
-				vertex_t v1, v2, resulthigh, resultlow;
+				vector3_t p, line[2], resulthigh, resultlow;
 				mobj_t *highest = NULL;
 
 				if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG)
@@ -5186,38 +5185,34 @@ DoneSection2:
 				// Next, we need to find the closest point on the line between each set, and determine which one we're
 				// closest to.
 
+				p.x = player->mo->x;
+				p.y = player->mo->y;
+				p.z = player->mo->z;
+
 				// Waypointmid and Waypointlow:
 				if (waypointlow)
 				{
-					v1.x = waypointmid->x;
-					v1.y = waypointmid->y;
-					v1.z = waypointmid->z;
-					v2.x = waypointlow->x;
-					v2.y = waypointlow->y;
-					v2.z = waypointlow->z;
-					junk.v1 = &v1;
-					junk.v2 = &v2;
-					junk.dx = v2.x - v1.x;
-					junk.dy = v2.y - v1.y;
+					line[0].x = waypointmid->x;
+					line[0].y = waypointmid->y;
+					line[0].z = waypointmid->z;
+					line[1].x = waypointlow->x;
+					line[1].y = waypointlow->y;
+					line[1].z = waypointlow->z;
 
-					P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resultlow);
+					P_ClosestPointOnLine3D(&p, line, &resultlow);
 				}
 
 				// Waypointmid and Waypointhigh:
 				if (waypointhigh)
 				{
-					v1.x = waypointmid->x;
-					v1.y = waypointmid->y;
-					v1.z = waypointmid->z;
-					v2.x = waypointhigh->x;
-					v2.y = waypointhigh->y;
-					v2.z = waypointhigh->z;
-					junk.v1 = &v1;
-					junk.v2 = &v2;
-					junk.dx = v2.x - v1.x;
-					junk.dy = v2.y - v1.y;
-
-					P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resulthigh);
+					line[0].x = waypointmid->x;
+					line[0].y = waypointmid->y;
+					line[0].z = waypointmid->z;
+					line[1].x = waypointhigh->x;
+					line[1].y = waypointhigh->y;
+					line[1].z = waypointhigh->z;
+
+					P_ClosestPointOnLine3D(&p, line, &resulthigh);
 				}
 
 				// 3D support now available. Disregard the previous notice here. -Red
diff --git a/src/r_defs.h b/src/r_defs.h
index 5f96958c925033ac6c5e45473e66f45e1d98981b..823e0e6cddcb07501186c753f5c50bfdac240535 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -83,7 +83,7 @@ typedef struct extracolormap_s
   */
 typedef struct
 {
-	fixed_t x, y, z;
+	fixed_t x, y;
 	boolean floorzset, ceilingzset;
 	fixed_t floorz, ceilingz;
 } vertex_t;