From 371a1851e334ea96fc4b84847602a2878c5aa439 Mon Sep 17 00:00:00 2001 From: MascaraSnake 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 c283c5674..57ea3e049 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 9958b19c9..3b6195285 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 f454bc1fd..84e89d746 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.