Fix: incorrect path rebuilding in RebuildWayPointsForGroupPath(), incorrect GroupAtFinalDestination() detection (by sun_alf)

*  RebuildWayPointsForGroupPath(): incorrect manipulations with 'iOldDelta' and 'iDelta' lead to skipping a node in 'pHeadOfPath' and to assertion failure as a result:
   AssertMsg( FALSE, String( "Invalid DIAGONAL waypoint being added for groupID %d. AM-0", pGroup->ubGroupID ) );
* GroupAtFinalDestination(): should take into account the amount of WayPoints, otherwise multiple visiting of a sector is not possible (group end up in that sector at first entrance):
   if( ( pGroup->ubSectorX == wp->x ) && ( pGroup->ubSectorY == wp->y ) )

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@9348 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
rftr
2022-03-26 21:00:13 +00:00
parent 90850826bb
commit bd5b14358d
4 changed files with 51 additions and 33 deletions
+1 -1
View File
@@ -4783,7 +4783,7 @@ BOOLEAN GroupAtFinalDestination( GROUP *pGroup )
} }
// if we're there // if we're there
if( ( pGroup->ubSectorX == wp->x ) && ( pGroup->ubSectorY == wp->y ) ) if( ( GetLengthOfPath(pGroup->pWaypoints) <= 1 ) && ( pGroup->ubSectorX == wp->x ) && ( pGroup->ubSectorY == wp->y ) )
{ {
return TRUE; return TRUE;
} }
+45 -31
View File
@@ -1658,9 +1658,6 @@ void VerifyAllMercsInGroupAreOnSameSquad( GROUP *pGroup )
void RebuildWayPointsForGroupPath( PathStPtr pHeadOfPath, INT16 sMvtGroup ) void RebuildWayPointsForGroupPath( PathStPtr pHeadOfPath, INT16 sMvtGroup )
{ {
INT32 iDelta = 0;
INT32 iOldDelta = 0;
BOOLEAN fFirstNode = TRUE;
PathStPtr pNode = pHeadOfPath; PathStPtr pNode = pHeadOfPath;
GROUP *pGroup = NULL; GROUP *pGroup = NULL;
WAYPOINT *wp = NULL; WAYPOINT *wp = NULL;
@@ -1700,7 +1697,7 @@ void RebuildWayPointsForGroupPath( PathStPtr pHeadOfPath, INT16 sMvtGroup )
// if group has no path planned at all // if group has no path planned at all
if( ( pNode == NULL ) || ( pNode->pNext == NULL ) ) if ( pNode == NULL )
{ {
// and it's a player group, and it's between sectors // and it's a player group, and it's between sectors
// NOTE: AI groups never reverse direction between sectors, Kris cheats & teleports them back to their current sector! // NOTE: AI groups never reverse direction between sectors, Kris cheats & teleports them back to their current sector!
@@ -1714,44 +1711,36 @@ void RebuildWayPointsForGroupPath( PathStPtr pHeadOfPath, INT16 sMvtGroup )
} }
// if we're currently between sectors UINT32 uiCurrentSectorId = CALCULATE_STRATEGIC_INDEX(pGroup->ubSectorX, pGroup->ubSectorY);
if( pGroup->fBetweenSectors ) UINT32 uiTargetSectorId = pGroup->fBetweenSectors ? CALCULATE_STRATEGIC_INDEX(pGroup->ubNextX, pGroup->ubNextY) : INVALID_STRATEGIC_INDEX;
{ UINT32 uiPrevNodeSectorId = INVALID_STRATEGIC_INDEX; // relates to path node, not to the group we work with
// figure out which direction we're already going in (Otherwise iOldDelta starts at 0)
iOldDelta = CALCULATE_STRATEGIC_INDEX( pGroup->ubNextX, pGroup->ubNextY ) - CALCULATE_STRATEGIC_INDEX( pGroup->ubSectorX, pGroup->ubSectorY );
}
// build a brand new list of waypoints, one for initial direction, and another for every "direction change" thereafter // build a brand new list of waypoints, one for initial direction, and another for every "direction change" thereafter
while( pNode->pNext ) while (pNode != NULL)
{ {
iDelta = pNode->pNext->uiSectorId - pNode->uiSectorId; Assert(uiPrevNodeSectorId != pNode->uiSectorId);
Assert( iDelta != 0 ); // same sector should never repeat in the path list uiPrevNodeSectorId = pNode->uiSectorId;
// Waypoints are only added at "pivot points" - whenever there is a change in orthogonal direction. // if we are between sectors, we have to skip the first waypoint to the place we are already going to.
// If we're NOT currently between sectors, iOldDelta will start off at 0, which means that the first node can't be if (pGroup->fBetweenSectors && pNode->uiSectorId == uiTargetSectorId)
// added as a waypoint. This is what we want - for stationary mercs, the first node in a path is the CURRENT sector.
if( ( iOldDelta != 0 ) && ( iDelta != iOldDelta ) )
{ {
// add this strategic sector as a waypoint uiTargetSectorId = INVALID_STRATEGIC_INDEX; // reset to invalid so that it won't enter this branch anymore
AddWaypointStrategicIDToPGroup( pGroup, pNode->uiSectorId ); }
else if (pNode->uiSectorId == uiCurrentSectorId) // also skip this first waypoint as we are already in
{
uiCurrentSectorId = INVALID_STRATEGIC_INDEX; // reset to invalid so that it won't enter this branch anymore
}
else // everything is OK, add this strategic sector as a waypoint
{
AddWaypointStrategicIDToPGroup(pGroup, pNode->uiSectorId);
} }
// remember this delta
iOldDelta = iDelta;
pNode = pNode->pNext; pNode = pNode->pNext;
fFirstNode = FALSE;
} }
// there must have been at least one next node, or we would have bailed out on "no path" earlier
Assert( !fFirstNode );
// the final destination sector - always add a waypoint for it
AddWaypointStrategicIDToPGroup( pGroup, pNode->uiSectorId );
// at this point, the final sector in the path must be identical to this group's last waypoint // at this point, the final sector in the path must be identical to this group's last waypoint
wp = GetFinalWaypoint( pGroup ); wp = GetFinalWaypoint( pGroup );
pNode = GetLastNodeOfPath( pHeadOfPath );
AssertMsg( wp, "Path exists, but no waypoints were added! AM-0" ); AssertMsg( wp, "Path exists, but no waypoints were added! AM-0" );
AssertMsg( pNode->uiSectorId == ( UINT32 ) CALCULATE_STRATEGIC_INDEX( wp->x, wp->y ), "Last waypoint differs from final path sector! AM-0" ); AssertMsg( pNode->uiSectorId == ( UINT32 ) CALCULATE_STRATEGIC_INDEX( wp->x, wp->y ), "Last waypoint differs from final path sector! AM-0" );
@@ -1951,6 +1940,17 @@ INT32 GetLengthOfPath( PathStPtr pHeadPath )
return( iLength ); return( iLength );
} }
INT32 GetLengthOfPath( WAYPOINT* pHeadWaypoint )
{
INT32 iLength = 0;
while (pHeadWaypoint)
{
pHeadWaypoint = pHeadWaypoint->next;
iLength++;
}
return iLength;
}
INT32 GetLengthOfMercPath( SOLDIERTYPE *pSoldier ) INT32 GetLengthOfMercPath( SOLDIERTYPE *pSoldier )
{ {
PathStPtr pNode = NULL; PathStPtr pNode = NULL;
@@ -2218,3 +2218,17 @@ void AddSectorToFrontOfMercPath( PathStPtr *ppMercPath, UINT8 ubSectorX, UINT8 u
*ppMercPath = pNode; *ppMercPath = pNode;
} }
PathStPtr GetLastNodeOfPath(PathStPtr pNode)
{
if (pNode)
{
while (pNode->pNext)
{
pNode = pNode->pNext;
}
}
return pNode;
}
+3
View File
@@ -113,6 +113,7 @@ BOOLEAN MoveGroupToOriginalSector( UINT8 ubGroupID );
// get length of path // get length of path
INT32 GetLengthOfPath( PathStPtr pHeadPath ); INT32 GetLengthOfPath( PathStPtr pHeadPath );
INT32 GetLengthOfPath( WAYPOINT* pHeadWaypoint );
INT32 GetLengthOfMercPath( SOLDIERTYPE *pSoldier ); INT32 GetLengthOfMercPath( SOLDIERTYPE *pSoldier );
// is the path empty? // is the path empty?
@@ -121,6 +122,8 @@ BOOLEAN CheckIfPathIsEmpty( PathStPtr pHeadPath );
PathStPtr GetSoldierMercPathPtr( SOLDIERTYPE *pSoldier ); PathStPtr GetSoldierMercPathPtr( SOLDIERTYPE *pSoldier );
PathStPtr GetGroupMercPathPtr( GROUP *pGroup ); PathStPtr GetGroupMercPathPtr( GROUP *pGroup );
PathStPtr GetLastNodeOfPath( PathStPtr pNode );
UINT8 GetSoldierGroupId( SOLDIERTYPE *pSoldier ); UINT8 GetSoldierGroupId( SOLDIERTYPE *pSoldier );
// clears this groups strategic movement (mercpaths and waypoints), include those in the vehicle structs(!) // clears this groups strategic movement (mercpaths and waypoints), include those in the vehicle structs(!)
+2 -1
View File
@@ -74,9 +74,10 @@ extern BOOLEAN gfUseAlternateMap;
#define CHECK_DIR_Y_DELTA ( WORLD_TILE_Y * 10 ) #define CHECK_DIR_Y_DELTA ( WORLD_TILE_Y * 10 )
// get index into aray // get index into aray
#define CALCULATE_STRATEGIC_INDEX( x, y ) ( x + ( y * MAP_WORLD_X ) ) #define CALCULATE_STRATEGIC_INDEX( x, y ) ( x + ( y * MAP_WORLD_X ) )
#define GET_X_FROM_STRATEGIC_INDEX( i ) ( i % MAP_WORLD_X ) #define GET_X_FROM_STRATEGIC_INDEX( i ) ( i % MAP_WORLD_X )
#define GET_Y_FROM_STRATEGIC_INDEX( i ) ( i / MAP_WORLD_X ) #define GET_Y_FROM_STRATEGIC_INDEX( i ) ( i / MAP_WORLD_X )
#define INVALID_STRATEGIC_INDEX ( 0 )
// macros to convert between the 2 different sector numbering systems // macros to convert between the 2 different sector numbering systems
#define SECTOR_INFO_TO_STRATEGIC_INDEX( i ) ( CALCULATE_STRATEGIC_INDEX ( SECTORX( i ), SECTORY( i ) ) ) #define SECTOR_INFO_TO_STRATEGIC_INDEX( i ) ( CALCULATE_STRATEGIC_INDEX ( SECTORX( i ), SECTORY( i ) ) )