From 0b7989b65acd62b8710fa7aed748d548ded93aaa Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 3 Sep 2024 02:00:13 +0200 Subject: [PATCH] d3: fix game crash in Retribution level 12's big matcen room When activating switches in the room with 6 matcens, this happens after a short while: ``` Assertion failure at TERRAIN_REGION (Descent3/terrain.h:218), triggered 1 time: 'x != -1 && "invalid/unset room number (-1)!"' f0 TERRAIN_REGION (x=-1) at Descent3/terrain.h:222 f1 AIPathAllocPath (obj=0x3d304b0 , ai_info=0x520000444080, goal_ptr=0x520000444250, start_room=0x3d304cc , start_pos=0x3d304d0 , end_room=0x7fb115dbe830, end_pos=0x52000044427c, rad=0, flags=0, handle=28822, ignore_obj=-1) at Descent3/aipath.cpp:1066 f2 GoalDoFrame (obj=0x3d304b0 ) at Descent3/AIGoal.cpp:823 f3 AIDoFrame (obj=0x3d304b0 ) at Descent3/AImain.cpp:6214 f4 ObjDoFrame (obj=0x3d304b0 ) at Descent3/object.cpp:2674 f5 ObjDoFrameAll () at Descent3/object.cpp:2988 f6 GameFrame () at Descent3/GameLoop.cpp:2981 f7 GameSequencer () at Descent3/gamesequence.cpp:1221 f8 PlayGame () at Descent3/game.cpp:834 f9 MainLoop () at Descent3/descent.cpp:550 f10 Descent3 () at Descent3/descent.cpp:508 f11 oeD3LnxApp::run (this=0x7fb115a0db50) at Descent3/sdlmain.cpp:151 (gdb) up start_room=0x3d304cc , start_pos=0x3d304d0 , end_room=0x7fb115dbe830, end_pos=0x52000044427c, rad=0, flags=0, handle=28822, ignore_obj=-1) at Descent3/aipath.cpp:1066 1066 } else if (BOA_Array[BOA_INDEX(*start_room)][BOA_INDEX(*end_room)] & BOAF_TOO_SMALL_FOR_ROBOT) { (gdb) p *start_room $2 = 171 (gdb) p *end_room $3 = -1 ``` The return type of ``BOA_GetNextPath`` is int; but inside the function, ``false`` is returned, which does not fit the scheme. Judging from callsites, ``BOA_NO_PATH`` is expected instead. In some functions related to AI pathfinding, add handling or assertions for invalid room numbers. --- Descent3/BOA.cpp | 8 +++++--- Descent3/aipath.cpp | 2 ++ Descent3/bnode.cpp | 5 +++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Descent3/BOA.cpp b/Descent3/BOA.cpp index 79cb11c1b..bb95f9b9c 100644 --- a/Descent3/BOA.cpp +++ b/Descent3/BOA.cpp @@ -329,6 +329,8 @@ int BOA_DetermineStartRoomPortal(int start_room, vector *start_pos, int end_room bool f_making_robot_path_invalid_list, int *blocked_portal) { int i; + if (start_room == -1 || end_room == -1) + return -1; if (start_room > Highest_room_index && end_room > Highest_room_index) return -1; @@ -566,12 +568,12 @@ int BOA_GetNextRoom(int start_room, int end_room) { int e_index = end_room; if (start_room == -1 || end_room == -1) { - return false; + return BOA_NO_PATH; } if ((!ROOMNUM_OUTSIDE(s_index)) && s_index <= Highest_room_index) { if (!Rooms[s_index].used) { - return false; + return BOA_NO_PATH; } } else if (ROOMNUM_OUTSIDE(s_index)) { s_index = TERRAIN_REGION(start_room) + Highest_room_index + 1; @@ -581,7 +583,7 @@ int BOA_GetNextRoom(int start_room, int end_room) { if ((!ROOMNUM_OUTSIDE(e_index)) && e_index <= Highest_room_index) { if (!Rooms[e_index].used) { - return false; + return BOA_NO_PATH; } } else if (ROOMNUM_OUTSIDE(e_index)) { e_index = TERRAIN_REGION(end_room) + Highest_room_index + 1; diff --git a/Descent3/aipath.cpp b/Descent3/aipath.cpp index fd53ff795..5e77c2d7f 100644 --- a/Descent3/aipath.cpp +++ b/Descent3/aipath.cpp @@ -60,6 +60,8 @@ static void AIUpdatePathInfo(q_item **node_list, int start, int end) { // Ok to use Highest_room_index offset stuff bool AIFindAltPath(object *obj, int i, int j, float *dist) { + if (i == -1 || j == -1) + return false; i = BOA_INDEX(i); j = BOA_INDEX(j); diff --git a/Descent3/bnode.cpp b/Descent3/bnode.cpp index 1e9ad7d89..e3191c1fe 100644 --- a/Descent3/bnode.cpp +++ b/Descent3/bnode.cpp @@ -210,6 +210,8 @@ static void BNode_UpdatePathInfo(pq_item **node_list, int start, int end) { // Ok to use Highest_room_index offset stuff bool BNode_FindPath(int start_room, int i, int j, float rad) { + if (start_room == -1) + return false; bpq PQPath; int counter; pq_item *start_node = new pq_item(i, -1, 0.0f); @@ -311,6 +313,8 @@ int BNode_FindDirLocalVisibleBNode(int roomnum, vector *pos, vector *fvec, float } bn_list *bnlist = BNode_GetBNListPtr(roomnum); + if (bnlist == nullptr) + return -1; retry: @@ -402,6 +406,7 @@ int BNode_FindClosestLocalVisibleBNode(int roomnum, vector *pos, float rad) { } bn_list *bnlist = BNode_GetBNListPtr(roomnum); + ASSERT(bnlist); retry: