From 52d46c56d219104476c2259811122ef0f762cd70 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Sun, 15 Feb 2026 19:05:51 +0100 Subject: [PATCH 1/4] bugfix(pathfinder): Fix uninitialized variable in Pathfinder::tightenPathCallback to prevent mismatches. --- .../Code/GameEngine/Include/GameLogic/AIPathfind.h | 2 +- .../GameEngine/Source/GameLogic/AI/AIPathfind.cpp | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h index a7ab136c909..15bad46cd59 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h @@ -767,7 +767,7 @@ class Pathfinder : PathfindServicesInterface, public Snapshot Bool checkForPossible(Bool isCrusher, Int fromZone, Bool center, const LocomotorSet& locomotorSet, Int cellX, Int cellY, PathfindLayerEnum layer, Coord3D *dest, Bool startingInObstacle) ; void getRadiusAndCenter(const Object *obj, Int &iRadius, Bool ¢er); - void adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coord3D &pos, PathfindLayerEnum layer); + static void adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coord3D &pos, PathfindLayerEnum layer); Bool checkDestination(const Object *obj, Int cellX, Int cellY, PathfindLayerEnum layer, Int iRadius, Bool centerInCell); Bool checkForMovement(const Object *obj, TCheckMovementInfo &info); Bool segmentIntersectsTallBuilding(const PathNode *curNode, PathNode *nextNode, diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp index f6f4c98fc5d..baab26ab261 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp @@ -8367,7 +8367,18 @@ struct TightenPathStruct if (d->layer != to->getLayer()) { return 0; // abort. } + + // TheSuperHackers @todo Caball009 15/02/2026 This is an incomplete workaround to initialize the variable, + // and needs to be replaced with a proper opt-in mechanism. The fix may introduce too many new mismatches to enable unconditionally, + // and the uninitialized values vary too much to imitate. Coord3D pos; +#if RETAIL_COMPATIBLE_PATHFINDING + if (s_useFixedPathfinding) +#endif + { + adjustCoordToCell(to_x, to_y, d->center, pos, to->getLayer()); + } + if (!TheAI->pathfinder()->checkForAdjust(d->obj, *d->locomotorSet, true, to_x, to_y, to->getLayer(), d->radius, d->center, &pos, nullptr)) { return 0; // bail early @@ -8977,7 +8988,7 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet } -void Pathfinder::adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coord3D &pos, PathfindLayerEnum layer) +/*static*/ void Pathfinder::adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coord3D& pos, PathfindLayerEnum layer) { if (centerInCell) { pos.x = ((Real)cellX + 0.5f) * PATHFIND_CELL_SIZE_F; From 5846b50f327a53d2c682e7b954e0010d32076055 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:47:04 +0100 Subject: [PATCH 2/4] Changed destination logic. --- .../Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp index baab26ab261..acb329ff0b2 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp @@ -8356,7 +8356,8 @@ struct TightenPathStruct Int radius; Bool center; Bool foundDest; - Coord3D destPos; + Coord3D orgDestPos; + Coord3D newDestPos; }; @@ -8376,7 +8377,7 @@ struct TightenPathStruct if (s_useFixedPathfinding) #endif { - adjustCoordToCell(to_x, to_y, d->center, pos, to->getLayer()); + pos = d->orgDestPos; } if (!TheAI->pathfinder()->checkForAdjust(d->obj, *d->locomotorSet, true, to_x, to_y, to->getLayer(), d->radius, d->center, &pos, nullptr)) @@ -8384,7 +8385,7 @@ struct TightenPathStruct return 0; // bail early } d->foundDest = true; - d->destPos = pos; + d->newDestPos = pos; return 0; // keep going } @@ -8400,9 +8401,10 @@ void Pathfinder::tightenPath(Object *obj, const LocomotorSet& locomotorSet, Coor info.obj = obj; info.locomotorSet = &locomotorSet; info.foundDest = false; + info.orgDestPos = *to; iterateCellsAlongLine(*from, *to, info.layer, tightenPathCallback, &info); if (info.foundDest) { - *from = info.destPos; + *from = info.newDestPos; } } From 3eb91ef0b98a197e911dd896eac3193e3fcd6e32 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Tue, 17 Feb 2026 18:57:20 +0100 Subject: [PATCH 3/4] Removed static from Pathfinder::adjustCoordToCell function declaration. --- GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h | 2 +- GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h index 15bad46cd59..a7ab136c909 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h @@ -767,7 +767,7 @@ class Pathfinder : PathfindServicesInterface, public Snapshot Bool checkForPossible(Bool isCrusher, Int fromZone, Bool center, const LocomotorSet& locomotorSet, Int cellX, Int cellY, PathfindLayerEnum layer, Coord3D *dest, Bool startingInObstacle) ; void getRadiusAndCenter(const Object *obj, Int &iRadius, Bool ¢er); - static void adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coord3D &pos, PathfindLayerEnum layer); + void adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coord3D &pos, PathfindLayerEnum layer); Bool checkDestination(const Object *obj, Int cellX, Int cellY, PathfindLayerEnum layer, Int iRadius, Bool centerInCell); Bool checkForMovement(const Object *obj, TCheckMovementInfo &info); Bool segmentIntersectsTallBuilding(const PathNode *curNode, PathNode *nextNode, diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp index acb329ff0b2..79f9dca7696 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp @@ -8990,7 +8990,7 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet } -/*static*/ void Pathfinder::adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coord3D& pos, PathfindLayerEnum layer) +void Pathfinder::adjustCoordToCell(Int cellX, Int cellY, Bool centerInCell, Coord3D &pos, PathfindLayerEnum layer) { if (centerInCell) { pos.x = ((Real)cellX + 0.5f) * PATHFIND_CELL_SIZE_F; From 2fa625dfadcecd7d96c7ffa38a6590ef514976f2 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Tue, 17 Feb 2026 19:12:48 +0100 Subject: [PATCH 4/4] Improved EA code comments for return statements. --- .../Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp index 79f9dca7696..570515e7182 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp @@ -8366,7 +8366,7 @@ struct TightenPathStruct TightenPathStruct* d = (TightenPathStruct*)userData; if (from == nullptr || to==nullptr) return 0; if (d->layer != to->getLayer()) { - return 0; // abort. + return 0; // failure } // TheSuperHackers @todo Caball009 15/02/2026 This is an incomplete workaround to initialize the variable, @@ -8382,12 +8382,12 @@ struct TightenPathStruct if (!TheAI->pathfinder()->checkForAdjust(d->obj, *d->locomotorSet, true, to_x, to_y, to->getLayer(), d->radius, d->center, &pos, nullptr)) { - return 0; // bail early + return 0; // failure } d->foundDest = true; d->newDestPos = pos; - return 0; // keep going + return 0; // success but keep going } /* Returns the cost, which is in the same units as coord3d distance. */