From 371a1851e334ea96fc4b84847602a2878c5aa439 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 16 May 2020 10:24:06 +0200
Subject: [PATCH] Polyobject waypoint movement: Prevent infinite loop if all
 waypoints are in the same location

---
 src/doomstat.h  |  1 +
 src/p_polyobj.c |  8 ++++++++
 src/p_setup.c   | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 41 insertions(+)

diff --git a/src/doomstat.h b/src/doomstat.h
index c283c56746..57ea3e0496 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -631,6 +631,7 @@ mobj_t *P_GetLastWaypoint(UINT8 sequence);
 mobj_t *P_GetPreviousWaypoint(mobj_t *current, boolean wrap);
 mobj_t *P_GetNextWaypoint(mobj_t *current, boolean wrap);
 mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo);
+boolean P_IsDegeneratedWaypointSequence(UINT8 sequence);
 
 // =====================================
 // Internal parameters, used for engine.
diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 9958b19c91..3b6195285b 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -2173,6 +2173,14 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
 		return false;
 	}
 
+	// Sanity check: If all waypoints are in the same location,
+	// don't allow the movement to be continuous so we don't get stuck in an infinite loop.
+	if (th->continuous && P_IsDegeneratedWaypointSequence(th->sequence))
+	{
+		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: All waypoints are in the same location!\n");
+		th->continuous = false;
+	}
+
 	th->pointnum = first->health;
 
 	return true;
diff --git a/src/p_setup.c b/src/p_setup.c
index f454bc1fd3..84e89d7463 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -239,6 +239,38 @@ mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo)
 	return result;
 }
 
+// Return true if all waypoints are in the same location
+boolean P_IsDegeneratedWaypointSequence(UINT8 sequence)
+{
+	mobj_t *first, *waypoint;
+	UINT8 wp;
+
+	if (numwaypoints[sequence] <= 1)
+		return true;
+
+	first = waypoints[sequence][0];
+
+	for (wp = 1; wp < numwaypoints[sequence]; wp++)
+	{
+		waypoint = waypoints[sequence][wp];
+
+		if (!waypoint)
+			continue;
+
+		if (waypoint->x != first->x)
+			return false;
+
+		if (waypoint->y != first->y)
+			return false;
+
+		if (waypoint->z != first->z)
+			return false;
+	}
+
+	return true;
+}
+
+
 /** Logs an error about a map being corrupt, then terminate.
   * This allows reporting highly technical errors for usefulness, without
   * confusing a novice map designer who simply needs to run ZenNode.
-- 
GitLab