Files
source/TileEngine/Map Edgepoints.cpp
T

1899 lines
64 KiB
C++

#ifdef PRECOMPILEDHEADERS
#include "TileEngine All.h"
#else
#include <memory.h>
#include "Map Edgepoints.h"
#include "pathai.h"
#include "ai.h"
#include "Map Information.h"
#include "renderworld.h"
#include "Isometric Utils.h"
#include "debug.h"
#include "Random.h"
#include "strategic.h"
#include "Animation Control.h"
#include "Render Fun.h"
#include "strategicmap.h"
#include "environment.h"
#include "worldman.h"
#endif
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
//dynamic arrays that contain the valid gridno's for each edge
INT16 *gps1stNorthEdgepointArray = NULL;
INT16 *gps1stEastEdgepointArray = NULL;
INT16 *gps1stSouthEdgepointArray = NULL;
INT16 *gps1stWestEdgepointArray = NULL;
//contains the size for each array
UINT16 gus1stNorthEdgepointArraySize = 0;
UINT16 gus1stEastEdgepointArraySize = 0;
UINT16 gus1stSouthEdgepointArraySize = 0;
UINT16 gus1stWestEdgepointArraySize = 0;
//contains the index value for the first array index of the second row of each edgepoint array.
//Because each edgepoint side has two rows, the outside most row is calculated first, then the inside row.
//For purposes of AI, it may become necessary to avoid this.
UINT16 gus1stNorthEdgepointMiddleIndex = 0;
UINT16 gus1stEastEdgepointMiddleIndex = 0;
UINT16 gus1stSouthEdgepointMiddleIndex = 0;
UINT16 gus1stWestEdgepointMiddleIndex = 0;
//dynamic arrays that contain the valid gridno's for each edge
INT16 *gps2ndNorthEdgepointArray = NULL;
INT16 *gps2ndEastEdgepointArray = NULL;
INT16 *gps2ndSouthEdgepointArray = NULL;
INT16 *gps2ndWestEdgepointArray = NULL;
//contains the size for each array
UINT16 gus2ndNorthEdgepointArraySize = 0;
UINT16 gus2ndEastEdgepointArraySize = 0;
UINT16 gus2ndSouthEdgepointArraySize = 0;
UINT16 gus2ndWestEdgepointArraySize = 0;
//contains the index value for the first array index of the second row of each edgepoint array.
//Because each edgepoint side has two rows, the outside most row is calculated first, then the inside row.
//For purposes of AI, it may become necessary to avoid this.
UINT16 gus2ndNorthEdgepointMiddleIndex = 0;
UINT16 gus2ndEastEdgepointMiddleIndex = 0;
UINT16 gus2ndSouthEdgepointMiddleIndex = 0;
UINT16 gus2ndWestEdgepointMiddleIndex = 0;
BOOLEAN gfEdgepointsExist = FALSE;
BOOLEAN gfGeneratingMapEdgepoints = FALSE;
INT16 gsTLGridNo = 13286;
INT16 gsTRGridNo = 1043;
INT16 gsBLGridNo = 24878;
INT16 gsBRGridNo = 12635;
BOOLEAN VerifyEdgepoint( SOLDIERTYPE *pSoldier, INT16 sEdgepoint );
BOOLEAN EdgepointsClose( SOLDIERTYPE *pSoldier, INT16 sEdgepoint1, INT16 sEdgepoint2 );
extern UINT8 gubTacticalDirection;
void TrashMapEdgepoints()
{
//Primary edgepoints
if( gps1stNorthEdgepointArray )
MemFree( gps1stNorthEdgepointArray );
if( gps1stEastEdgepointArray )
MemFree( gps1stEastEdgepointArray );
if( gps1stSouthEdgepointArray )
MemFree( gps1stSouthEdgepointArray );
if( gps1stWestEdgepointArray )
MemFree( gps1stWestEdgepointArray );
gps1stNorthEdgepointArray = NULL;
gps1stEastEdgepointArray = NULL;
gps1stSouthEdgepointArray = NULL;
gps1stWestEdgepointArray = NULL;
gus1stNorthEdgepointArraySize = 0;
gus1stEastEdgepointArraySize = 0;
gus1stSouthEdgepointArraySize = 0;
gus1stWestEdgepointArraySize = 0;
gus1stNorthEdgepointMiddleIndex = 0;
gus1stEastEdgepointMiddleIndex = 0;
gus1stSouthEdgepointMiddleIndex = 0;
gus1stWestEdgepointMiddleIndex = 0;
//Secondary edgepoints
if( gps2ndNorthEdgepointArray )
MemFree( gps2ndNorthEdgepointArray );
if( gps2ndEastEdgepointArray )
MemFree( gps2ndEastEdgepointArray );
if( gps2ndSouthEdgepointArray )
MemFree( gps2ndSouthEdgepointArray );
if( gps2ndWestEdgepointArray )
MemFree( gps2ndWestEdgepointArray );
gps2ndNorthEdgepointArray = NULL;
gps2ndEastEdgepointArray = NULL;
gps2ndSouthEdgepointArray = NULL;
gps2ndWestEdgepointArray = NULL;
gus2ndNorthEdgepointArraySize = 0;
gus2ndEastEdgepointArraySize = 0;
gus2ndSouthEdgepointArraySize = 0;
gus2ndWestEdgepointArraySize = 0;
gus2ndNorthEdgepointMiddleIndex = 0;
gus2ndEastEdgepointMiddleIndex = 0;
gus2ndSouthEdgepointMiddleIndex = 0;
gus2ndWestEdgepointMiddleIndex = 0;
}
//This final step eliminates some edgepoints which actually don't path directly to the edge of the map.
//Cases would include an area that is close to the edge, but a fence blocks it from direct access to the edge
//of the map.
void ValidateEdgepoints()
{
INT32 i;
UINT16 usValidEdgepoints;
SOLDIERTYPE Soldier;
Soldier.bTeam = 1;
//north
usValidEdgepoints = 0;
for( i = 0; i < gus1stNorthEdgepointArraySize; i++ )
{
if( VerifyEdgepoint( &Soldier, gps1stNorthEdgepointArray[ i ] ) )
{
gps1stNorthEdgepointArray[ usValidEdgepoints ] = gps1stNorthEdgepointArray[ i ];
if( i == gus1stNorthEdgepointMiddleIndex )
{ //adjust the middle index to the new one.
gus1stNorthEdgepointMiddleIndex = usValidEdgepoints;
}
usValidEdgepoints++;
}
else if( i == gus1stNorthEdgepointMiddleIndex )
{ //increment the middle index because it's edgepoint is no longer valid.
gus1stNorthEdgepointMiddleIndex++;
}
}
gus1stNorthEdgepointArraySize = usValidEdgepoints;
//East
usValidEdgepoints = 0;
for( i = 0; i < gus1stEastEdgepointArraySize; i++ )
{
if( VerifyEdgepoint( &Soldier, gps1stEastEdgepointArray[ i ] ) )
{
gps1stEastEdgepointArray[ usValidEdgepoints ] = gps1stEastEdgepointArray[ i ];
if( i == gus1stEastEdgepointMiddleIndex )
{ //adjust the middle index to the new one.
gus1stEastEdgepointMiddleIndex = usValidEdgepoints;
}
usValidEdgepoints++;
}
else if( i == gus1stEastEdgepointMiddleIndex )
{ //increment the middle index because it's edgepoint is no longer valid.
gus1stEastEdgepointMiddleIndex++;
}
}
gus1stEastEdgepointArraySize = usValidEdgepoints;
//South
usValidEdgepoints = 0;
for( i = 0; i < gus1stSouthEdgepointArraySize; i++ )
{
if( VerifyEdgepoint( &Soldier, gps1stSouthEdgepointArray[ i ] ) )
{
gps1stSouthEdgepointArray[ usValidEdgepoints ] = gps1stSouthEdgepointArray[ i ];
if( i == gus1stSouthEdgepointMiddleIndex )
{ //adjust the middle index to the new one.
gus1stSouthEdgepointMiddleIndex = usValidEdgepoints;
}
usValidEdgepoints++;
}
else if( i == gus1stSouthEdgepointMiddleIndex )
{ //increment the middle index because it's edgepoint is no longer valid.
gus1stSouthEdgepointMiddleIndex++;
}
}
gus1stSouthEdgepointArraySize = usValidEdgepoints;
//West
usValidEdgepoints = 0;
for( i = 0; i < gus1stWestEdgepointArraySize; i++ )
{
if( VerifyEdgepoint( &Soldier, gps1stWestEdgepointArray[ i ] ) )
{
gps1stWestEdgepointArray[ usValidEdgepoints ] = gps1stWestEdgepointArray[ i ];
if( i == gus1stWestEdgepointMiddleIndex )
{ //adjust the middle index to the new one.
gus1stWestEdgepointMiddleIndex = usValidEdgepoints;
}
usValidEdgepoints++;
}
else if( i == gus1stWestEdgepointMiddleIndex )
{ //increment the middle index because it's edgepoint is no longer valid.
gus1stWestEdgepointMiddleIndex++;
}
}
gus1stWestEdgepointArraySize = usValidEdgepoints;
//north
usValidEdgepoints = 0;
for( i = 0; i < gus2ndNorthEdgepointArraySize; i++ )
{
if( VerifyEdgepoint( &Soldier, gps2ndNorthEdgepointArray[ i ] ) )
{
gps2ndNorthEdgepointArray[ usValidEdgepoints ] = gps2ndNorthEdgepointArray[ i ];
if( i == gus2ndNorthEdgepointMiddleIndex )
{ //adjust the middle index to the new one.
gus2ndNorthEdgepointMiddleIndex = usValidEdgepoints;
}
usValidEdgepoints++;
}
else if( i == gus2ndNorthEdgepointMiddleIndex )
{ //increment the middle index because it's edgepoint is no longer valid.
gus2ndNorthEdgepointMiddleIndex++;
}
}
gus2ndNorthEdgepointArraySize = usValidEdgepoints;
//East
usValidEdgepoints = 0;
for( i = 0; i < gus2ndEastEdgepointArraySize; i++ )
{
if( VerifyEdgepoint( &Soldier, gps2ndEastEdgepointArray[ i ] ) )
{
gps2ndEastEdgepointArray[ usValidEdgepoints ] = gps2ndEastEdgepointArray[ i ];
if( i == gus2ndEastEdgepointMiddleIndex )
{ //adjust the middle index to the new one.
gus2ndEastEdgepointMiddleIndex = usValidEdgepoints;
}
usValidEdgepoints++;
}
else if( i == gus2ndEastEdgepointMiddleIndex )
{ //increment the middle index because it's edgepoint is no longer valid.
gus2ndEastEdgepointMiddleIndex++;
}
}
gus2ndEastEdgepointArraySize = usValidEdgepoints;
//South
usValidEdgepoints = 0;
for( i = 0; i < gus2ndSouthEdgepointArraySize; i++ )
{
if( VerifyEdgepoint( &Soldier, gps2ndSouthEdgepointArray[ i ] ) )
{
gps2ndSouthEdgepointArray[ usValidEdgepoints ] = gps2ndSouthEdgepointArray[ i ];
if( i == gus2ndSouthEdgepointMiddleIndex )
{ //adjust the middle index to the new one.
gus2ndSouthEdgepointMiddleIndex = usValidEdgepoints;
}
usValidEdgepoints++;
}
else if( i == gus2ndSouthEdgepointMiddleIndex )
{ //increment the middle index because it's edgepoint is no longer valid.
gus2ndSouthEdgepointMiddleIndex++;
}
}
gus2ndSouthEdgepointArraySize = usValidEdgepoints;
//West
usValidEdgepoints = 0;
for( i = 0; i < gus2ndWestEdgepointArraySize; i++ )
{
if( VerifyEdgepoint( &Soldier, gps2ndWestEdgepointArray[ i ] ) )
{
gps2ndWestEdgepointArray[ usValidEdgepoints ] = gps2ndWestEdgepointArray[ i ];
if( i == gus2ndWestEdgepointMiddleIndex )
{ //adjust the middle index to the new one.
gus2ndWestEdgepointMiddleIndex = usValidEdgepoints;
}
usValidEdgepoints++;
}
else if( i == gus2ndWestEdgepointMiddleIndex )
{ //increment the middle index because it's edgepoint is no longer valid.
gus2ndWestEdgepointMiddleIndex++;
}
}
gus2ndWestEdgepointArraySize = usValidEdgepoints;
}
void CompactEdgepointArray( INT16 **psArray, UINT16 *pusMiddleIndex, UINT16 *pusArraySize )
{
INT32 i;
UINT16 usArraySize, usValidIndex = 0;
usArraySize = *pusArraySize;
for( i = 0; i < usArraySize; i++ )
{
if( (*psArray)[ i ] == -1 )
{
(*pusArraySize)--;
if( i < *pusMiddleIndex )
{
(*pusMiddleIndex)--;
}
}
else
{
if( usValidIndex != i )
{
(*psArray)[ usValidIndex ] = (*psArray)[ i ];
}
usValidIndex++;
}
}
*psArray = (INT16*)MemRealloc( *psArray, *pusArraySize * sizeof( INT16) );
Assert( *psArray );
}
void InternallyClassifyEdgepoints( SOLDIERTYPE *pSoldier, INT16 sGridNo,
INT16 **psArray1, UINT16 *pusMiddleIndex1, UINT16 *pusArraySize1,
INT16 **psArray2, UINT16 *pusMiddleIndex2, UINT16 *pusArraySize2 )
{
INT32 i;
UINT16 us1stBenchmarkID, us2ndBenchmarkID;
us1stBenchmarkID = us2ndBenchmarkID = 0xffff;
if( !(*psArray2) )
{
*psArray2 = (INT16*)MemAlloc( sizeof( INT16 ) * 400 );
}
for( i = 0; i < *pusArraySize1; i++ )
{
if( sGridNo == (*psArray1)[ i ] )
{
if( i < *pusMiddleIndex1 )
{ //in the first half of the array
us1stBenchmarkID = (UINT16)i;
//find the second benchmark
for( i = *pusMiddleIndex1; i < *pusArraySize1; i++ )
{
if( EdgepointsClose( pSoldier, (*psArray1)[ us1stBenchmarkID ], (*psArray1)[ i ] ) )
{
us2ndBenchmarkID = (UINT16)i;
break;
}
}
}
else
{ //in the second half of the array
us2ndBenchmarkID = (UINT16)i;
//find the first benchmark
for( i = 0; i < *pusMiddleIndex1; i++ )
{
if( EdgepointsClose( pSoldier, (*psArray1)[ us2ndBenchmarkID ], (*psArray1)[ i ] ) )
{
us1stBenchmarkID = (UINT16)i;
break;
}
}
}
break;
}
}
//Now we have found the two benchmarks, so go in both directions for each one to determine which entrypoints
//are going to be used in the primary array. All rejections will be positioned in the secondary array for
//use for isolated entry when tactically traversing.
if( us1stBenchmarkID != 0xffff )
{
for( i = us1stBenchmarkID; i > 0; i-- )
{
if( !EdgepointsClose( pSoldier, (*psArray1)[ i ], (*psArray1)[ i-1 ] ) )
{ //All edgepoints from index 0 to i-1 are rejected.
while( i )
{
i--;
(*psArray2)[ *pusArraySize2 ] = (*psArray1)[ i ];
(*pusMiddleIndex2)++;
(*pusArraySize2)++;
(*psArray1)[ i ] = -1;
}
break;
}
}
for( i = us1stBenchmarkID; i < *pusMiddleIndex1 - 1; i++ )
{
if( !EdgepointsClose( pSoldier, (*psArray1)[ i ], (*psArray1)[ i+1 ] ) )
{ //All edgepoints from index i+1 to 1st middle index are rejected.
while( i < *pusMiddleIndex1 - 1 )
{
i++;
(*psArray2)[ *pusArraySize2 ] = (*psArray1)[ i ];
(*pusMiddleIndex2)++;
(*pusArraySize2)++;
(*psArray1)[ i ] = -1;
}
break;
}
}
}
if( us2ndBenchmarkID != 0xffff )
{
for( i = us2ndBenchmarkID; i > *pusMiddleIndex1; i-- )
{
if( !EdgepointsClose( pSoldier, (*psArray1)[ i ], (*psArray1)[ i-1 ] ) )
{ //All edgepoints from 1st middle index to i-1 are rejected.
while( i > *pusMiddleIndex1 )
{
i--;
(*psArray2)[ *pusArraySize2 ] = (*psArray1)[ i ];
(*pusArraySize2)++;
(*psArray1)[ i ] = -1;
}
break;
}
}
for( i = us2ndBenchmarkID; i < *pusArraySize1 - 1; i++ )
{
if( !EdgepointsClose( pSoldier, (*psArray1)[ i ], (*psArray1)[ i+1 ] ) )
{ //All edgepoints from index 0 to i-1 are rejected.
while( i < *pusArraySize1 - 1 )
{
i++;
(*psArray2)[ (*pusArraySize2) ] = (*psArray1)[ i ];
(*pusArraySize2)++;
(*psArray1)[ i ] = -1;
}
break;
}
}
}
//Now compact the primary array, because some edgepoints have been removed.
CompactEdgepointArray( psArray1, pusMiddleIndex1, pusArraySize1 );
(*psArray2) = (INT16*)MemRealloc( (*psArray2), *pusArraySize2 * sizeof( INT16 ) );
}
void ClassifyEdgepoints()
{
SOLDIERTYPE Soldier;
INT16 sGridNo = -1;
Soldier.bTeam = 1;
//north
if( gMapInformation.sNorthGridNo != -1 )
{
sGridNo = FindNearestEdgepointOnSpecifiedEdge( gMapInformation.sNorthGridNo, NORTH_EDGEPOINT_SEARCH );
if( sGridNo != NOWHERE )
{
InternallyClassifyEdgepoints( &Soldier, sGridNo,
&gps1stNorthEdgepointArray, &gus1stNorthEdgepointMiddleIndex, &gus1stNorthEdgepointArraySize,
&gps2ndNorthEdgepointArray, &gus2ndNorthEdgepointMiddleIndex, &gus2ndNorthEdgepointArraySize );
}
}
//east
if( gMapInformation.sEastGridNo != -1 )
{
sGridNo = FindNearestEdgepointOnSpecifiedEdge( gMapInformation.sEastGridNo, EAST_EDGEPOINT_SEARCH );
if( sGridNo != NOWHERE )
{
InternallyClassifyEdgepoints( &Soldier, sGridNo,
&gps1stEastEdgepointArray, &gus1stEastEdgepointMiddleIndex, &gus1stEastEdgepointArraySize,
&gps2ndEastEdgepointArray, &gus2ndEastEdgepointMiddleIndex, &gus2ndEastEdgepointArraySize );
}
}
//south
if( gMapInformation.sSouthGridNo != -1 )
{
sGridNo = FindNearestEdgepointOnSpecifiedEdge( gMapInformation.sSouthGridNo, SOUTH_EDGEPOINT_SEARCH );
if( sGridNo != NOWHERE )
{
InternallyClassifyEdgepoints( &Soldier, sGridNo,
&gps1stSouthEdgepointArray, &gus1stSouthEdgepointMiddleIndex, &gus1stSouthEdgepointArraySize,
&gps2ndSouthEdgepointArray, &gus2ndSouthEdgepointMiddleIndex, &gus2ndSouthEdgepointArraySize );
}
}
//west
if( gMapInformation.sWestGridNo != -1 )
{
sGridNo = FindNearestEdgepointOnSpecifiedEdge( gMapInformation.sWestGridNo, WEST_EDGEPOINT_SEARCH );
if( sGridNo != NOWHERE )
{
InternallyClassifyEdgepoints( &Soldier, sGridNo,
&gps1stWestEdgepointArray, &gus1stWestEdgepointMiddleIndex, &gus1stWestEdgepointArraySize,
&gps2ndWestEdgepointArray, &gus2ndWestEdgepointMiddleIndex, &gus2ndWestEdgepointArraySize );
}
}
}
void GenerateMapEdgepoints()
{
INT32 i=-1;
INT16 sGridNo=-1;
INT16 sVGridNo[400];
//Get rid of the current edgepoint lists.
TrashMapEdgepoints();
gfGeneratingMapEdgepoints = TRUE;
if( gMapInformation.sNorthGridNo != -1 )
sGridNo = gMapInformation.sNorthGridNo;
else if( gMapInformation.sEastGridNo != -1 )
sGridNo = gMapInformation.sEastGridNo;
else if( gMapInformation.sSouthGridNo != -1 )
sGridNo = gMapInformation.sSouthGridNo;
else if( gMapInformation.sWestGridNo != -1 )
sGridNo = gMapInformation.sWestGridNo;
else if( gMapInformation.sCenterGridNo != -1 )
sGridNo = gMapInformation.sCenterGridNo;
else
return;
GlobalReachableTest( sGridNo );
//Calculate the north edges
if( gMapInformation.sNorthGridNo != -1 )
{
//1st row
sGridNo = gsTLGridNo;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stNorthEdgepointArraySize++ ] = sGridNo;
while( sGridNo > gsTRGridNo )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stNorthEdgepointArraySize++ ] = sGridNo;
sGridNo -= 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stNorthEdgepointArraySize++ ] = sGridNo;
}
//2nd row
gus1stNorthEdgepointMiddleIndex = gus1stNorthEdgepointArraySize;
sGridNo = gsTLGridNo + 161;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stNorthEdgepointArraySize++ ] = sGridNo;
while( sGridNo > gsTRGridNo + 161 )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stNorthEdgepointArraySize++ ] = sGridNo;
sGridNo -= 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stNorthEdgepointArraySize++ ] = sGridNo;
}
if( gus1stNorthEdgepointArraySize )
{
//Allocate and copy over the valid gridnos.
gps1stNorthEdgepointArray = (INT16*)MemAlloc( gus1stNorthEdgepointArraySize * sizeof( INT16) );
for( i = 0; i < gus1stNorthEdgepointArraySize; i++ )
gps1stNorthEdgepointArray[ i ] = sVGridNo[ i ];
}
}
//Calculate the east edges
if( gMapInformation.sEastGridNo != -1 )
{
//1st row
sGridNo = gsTRGridNo;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stEastEdgepointArraySize++ ] = sGridNo;
while( sGridNo < gsBRGridNo )
{
sGridNo += 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stEastEdgepointArraySize++ ] = sGridNo;
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stEastEdgepointArraySize++ ] = sGridNo;
}
//2nd row
gus1stEastEdgepointMiddleIndex = gus1stEastEdgepointArraySize;
sGridNo = gsTRGridNo + 159;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stEastEdgepointArraySize++ ] = sGridNo;
while( sGridNo < gsBRGridNo + 159 )
{
sGridNo += 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stEastEdgepointArraySize++ ] = sGridNo;
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stEastEdgepointArraySize++ ] = sGridNo;
}
if( gus1stEastEdgepointArraySize )
{ //Allocate and copy over the valid gridnos.
gps1stEastEdgepointArray = (INT16*)MemAlloc( gus1stEastEdgepointArraySize * sizeof( INT16) );
for( i = 0; i < gus1stEastEdgepointArraySize; i++ )
gps1stEastEdgepointArray[ i ] = sVGridNo[ i ];
}
}
//Calculate the south edges
if( gMapInformation.sSouthGridNo != -1 )
{
//1st row
sGridNo = gsBLGridNo;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stSouthEdgepointArraySize++ ] = sGridNo;
while( sGridNo > gsBRGridNo )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stSouthEdgepointArraySize++ ] = sGridNo;
sGridNo -= 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stSouthEdgepointArraySize++ ] = sGridNo;
}
//2nd row
gus1stSouthEdgepointMiddleIndex = gus1stSouthEdgepointArraySize;
sGridNo = gsBLGridNo - 161;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stSouthEdgepointArraySize++ ] = sGridNo;
while( sGridNo > gsBRGridNo - 161 )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stSouthEdgepointArraySize++ ] = sGridNo;
sGridNo -= 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stSouthEdgepointArraySize++ ] = sGridNo;
}
if( gus1stSouthEdgepointArraySize )
{ //Allocate and copy over the valid gridnos.
gps1stSouthEdgepointArray = (INT16*)MemAlloc( gus1stSouthEdgepointArraySize * sizeof( INT16) );
for( i = 0; i < gus1stSouthEdgepointArraySize; i++ )
gps1stSouthEdgepointArray[ i ] = sVGridNo[ i ];
}
}
//Calculate the west edges
if( gMapInformation.sWestGridNo != -1 )
{
//1st row
sGridNo = gsTLGridNo;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stWestEdgepointArraySize++ ] = sGridNo;
while( sGridNo < gsBLGridNo )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stWestEdgepointArraySize++ ] = sGridNo;
sGridNo += 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stWestEdgepointArraySize++ ] = sGridNo;
}
//2nd row
gus1stWestEdgepointMiddleIndex = gus1stWestEdgepointArraySize;
sGridNo = gsTLGridNo - 159;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stWestEdgepointArraySize++ ] = sGridNo;
while( sGridNo < gsBLGridNo - 159 )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stWestEdgepointArraySize++ ] = sGridNo;
sGridNo += 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus1stWestEdgepointArraySize++ ] = sGridNo;
}
if( gus1stWestEdgepointArraySize )
{ //Allocate and copy over the valid gridnos.
gps1stWestEdgepointArray = (INT16*)MemAlloc( gus1stWestEdgepointArraySize * sizeof( INT16) );
for( i = 0; i < gus1stWestEdgepointArraySize; i++ )
gps1stWestEdgepointArray[ i ] = sVGridNo[ i ];
}
}
//CHECK FOR ISOLATED EDGEPOINTS (but only if the entrypoint is ISOLATED!!!)
if( gMapInformation.sIsolatedGridNo != -1 && !(gpWorldLevelData[ gMapInformation.sIsolatedGridNo ].uiFlags & MAPELEMENT_REACHABLE) )
{
GlobalReachableTest( gMapInformation.sIsolatedGridNo );
if( gMapInformation.sNorthGridNo != -1 )
{
//1st row
sGridNo = gsTLGridNo;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndNorthEdgepointArraySize++ ] = sGridNo;
while( sGridNo > gsTRGridNo )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndNorthEdgepointArraySize++ ] = sGridNo;
sGridNo -= 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndNorthEdgepointArraySize++ ] = sGridNo;
}
//2nd row
gus2ndNorthEdgepointMiddleIndex = gus2ndNorthEdgepointArraySize;
sGridNo = gsTLGridNo + 161;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndNorthEdgepointArraySize++ ] = sGridNo;
while( sGridNo > gsTRGridNo + 161 )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndNorthEdgepointArraySize++ ] = sGridNo;
sGridNo -= 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndNorthEdgepointArraySize++ ] = sGridNo;
}
if( gus2ndNorthEdgepointArraySize )
{
//Allocate and copy over the valid gridnos.
gps2ndNorthEdgepointArray = (INT16*)MemAlloc( gus2ndNorthEdgepointArraySize * sizeof( INT16) );
for( i = 0; i < gus2ndNorthEdgepointArraySize; i++ )
gps2ndNorthEdgepointArray[ i ] = sVGridNo[ i ];
}
}
//Calculate the east edges
if( gMapInformation.sEastGridNo != -1 )
{
//1st row
sGridNo = gsTRGridNo;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndEastEdgepointArraySize++ ] = sGridNo;
while( sGridNo < gsBRGridNo )
{
sGridNo += 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndEastEdgepointArraySize++ ] = sGridNo;
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndEastEdgepointArraySize++ ] = sGridNo;
}
//2nd row
gus2ndEastEdgepointMiddleIndex = gus2ndEastEdgepointArraySize;
sGridNo = gsTRGridNo + 159;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndEastEdgepointArraySize++ ] = sGridNo;
while( sGridNo < gsBRGridNo + 159 )
{
sGridNo += 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndEastEdgepointArraySize++ ] = sGridNo;
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndEastEdgepointArraySize++ ] = sGridNo;
}
if( gus2ndEastEdgepointArraySize )
{ //Allocate and copy over the valid gridnos.
gps2ndEastEdgepointArray = (INT16*)MemAlloc( gus2ndEastEdgepointArraySize * sizeof( INT16) );
for( i = 0; i < gus2ndEastEdgepointArraySize; i++ )
gps2ndEastEdgepointArray[ i ] = sVGridNo[ i ];
}
}
//Calculate the south edges
if( gMapInformation.sSouthGridNo != -1 )
{
//1st row
sGridNo = gsBLGridNo;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndSouthEdgepointArraySize++ ] = sGridNo;
while( sGridNo > gsBRGridNo )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndSouthEdgepointArraySize++ ] = sGridNo;
sGridNo -= 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndSouthEdgepointArraySize++ ] = sGridNo;
}
//2nd row
gus2ndSouthEdgepointMiddleIndex = gus2ndSouthEdgepointArraySize;
sGridNo = gsBLGridNo - 161;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndSouthEdgepointArraySize++ ] = sGridNo;
while( sGridNo > gsBRGridNo - 161 )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndSouthEdgepointArraySize++ ] = sGridNo;
sGridNo -= 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndSouthEdgepointArraySize++ ] = sGridNo;
}
if( gus2ndSouthEdgepointArraySize )
{ //Allocate and copy over the valid gridnos.
gps2ndSouthEdgepointArray = (INT16*)MemAlloc( gus2ndSouthEdgepointArraySize * sizeof( INT16) );
for( i = 0; i < gus2ndSouthEdgepointArraySize; i++ )
gps2ndSouthEdgepointArray[ i ] = sVGridNo[ i ];
}
}
//Calculate the west edges
if( gMapInformation.sWestGridNo != -1 )
{
//1st row
sGridNo = gsTLGridNo;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndWestEdgepointArraySize++ ] = sGridNo;
while( sGridNo < gsBLGridNo )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndWestEdgepointArraySize++ ] = sGridNo;
sGridNo += 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndWestEdgepointArraySize++ ] = sGridNo;
}
//2nd row
gus2ndWestEdgepointMiddleIndex = gus2ndWestEdgepointArraySize;
sGridNo = gsTLGridNo - 159;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndWestEdgepointArraySize++ ] = sGridNo;
while( sGridNo < gsBLGridNo - 159 )
{
sGridNo++;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndWestEdgepointArraySize++ ] = sGridNo;
sGridNo += 160;
if( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE &&
(!gubWorldRoomInfo[ sGridNo ] || gfBasement) )
sVGridNo[ gus2ndWestEdgepointArraySize++ ] = sGridNo;
}
if( gus2ndWestEdgepointArraySize )
{ //Allocate and copy over the valid gridnos.
gps2ndWestEdgepointArray = (INT16*)MemAlloc( gus2ndWestEdgepointArraySize * sizeof( INT16) );
for( i = 0; i < gus2ndWestEdgepointArraySize; i++ )
gps2ndWestEdgepointArray[ i ] = sVGridNo[ i ];
}
}
}
//Eliminates any edgepoints not accessible to the edge of the world. This is done to the primary edgepoints
ValidateEdgepoints();
//Second step is to process the primary edgepoints and determine if any of the edgepoints aren't accessible from
//the associated entrypoint. These edgepoints that are rejected are placed in the secondary list.
if( gMapInformation.sIsolatedGridNo != -1 )
{ //only if there is an isolated gridno in the map. There is a flaw in the design of this system. The classification
//process will automatically assign areas to be isolated if there is an obstacle between one normal edgepoint and another
//causing a 5 tile connection check to fail. So, all maps with isolated edgepoints will need to be checked manually to
//make sure there are no obstacles causing this to happen (except for obstacles between normal areas and the isolated area)
//Good thing most maps don't have isolated sections. This is one expensive function to call! Maybe 200MI!
ClassifyEdgepoints();
}
gfGeneratingMapEdgepoints = FALSE;
}
void SaveMapEdgepoints( HWFILE fp )
{
//1st priority edgepoints -- for common entry -- tactical placement gui uses only these points.
FileWrite( fp, &gus1stNorthEdgepointArraySize, 2, NULL );
FileWrite( fp, &gus1stNorthEdgepointMiddleIndex, 2, NULL );
if( gus1stNorthEdgepointArraySize )
FileWrite( fp, gps1stNorthEdgepointArray, gus1stNorthEdgepointArraySize * sizeof( INT16 ), NULL );
FileWrite( fp, &gus1stEastEdgepointArraySize, 2, NULL );
FileWrite( fp, &gus1stEastEdgepointMiddleIndex, 2, NULL );
if( gus1stEastEdgepointArraySize )
FileWrite( fp, gps1stEastEdgepointArray, gus1stEastEdgepointArraySize * sizeof( INT16 ), NULL );
FileWrite( fp, &gus1stSouthEdgepointArraySize, 2, NULL );
FileWrite( fp, &gus1stSouthEdgepointMiddleIndex, 2, NULL );
if( gus1stSouthEdgepointArraySize )
FileWrite( fp, gps1stSouthEdgepointArray, gus1stSouthEdgepointArraySize * sizeof( INT16 ), NULL );
FileWrite( fp, &gus1stWestEdgepointArraySize, 2, NULL );
FileWrite( fp, &gus1stWestEdgepointMiddleIndex, 2, NULL );
if( gus1stWestEdgepointArraySize )
FileWrite( fp, gps1stWestEdgepointArray, gus1stWestEdgepointArraySize * sizeof( INT16 ), NULL );
//2nd priority edgepoints -- for isolated areas. Okay to be zero
FileWrite( fp, &gus2ndNorthEdgepointArraySize, 2, NULL );
FileWrite( fp, &gus2ndNorthEdgepointMiddleIndex, 2, NULL );
if( gus2ndNorthEdgepointArraySize )
FileWrite( fp, gps2ndNorthEdgepointArray, gus2ndNorthEdgepointArraySize * sizeof( INT16 ), NULL );
FileWrite( fp, &gus2ndEastEdgepointArraySize, 2, NULL );
FileWrite( fp, &gus2ndEastEdgepointMiddleIndex, 2, NULL );
if( gus2ndEastEdgepointArraySize )
FileWrite( fp, gps2ndEastEdgepointArray, gus2ndEastEdgepointArraySize * sizeof( INT16 ), NULL );
FileWrite( fp, &gus2ndSouthEdgepointArraySize, 2, NULL );
FileWrite( fp, &gus2ndSouthEdgepointMiddleIndex, 2, NULL );
if( gus2ndSouthEdgepointArraySize )
FileWrite( fp, gps2ndSouthEdgepointArray, gus2ndSouthEdgepointArraySize * sizeof( INT16 ), NULL );
FileWrite( fp, &gus2ndWestEdgepointArraySize, 2, NULL );
FileWrite( fp, &gus2ndWestEdgepointMiddleIndex, 2, NULL );
if( gus2ndWestEdgepointArraySize )
FileWrite( fp, gps2ndWestEdgepointArray, gus2ndWestEdgepointArraySize * sizeof( INT16 ), NULL );
}
void OldLoadMapEdgepoints( INT8 **hBuffer )
{
LOADDATA( &gus1stNorthEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus1stNorthEdgepointMiddleIndex, *hBuffer, 2 );
if( gus1stNorthEdgepointArraySize )
{
gps1stNorthEdgepointArray = (INT16*)MemAlloc( gus1stNorthEdgepointArraySize * sizeof( INT16 ) );
Assert( gps1stNorthEdgepointArray );
LOADDATA( gps1stNorthEdgepointArray, *hBuffer, gus1stNorthEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus1stEastEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus1stEastEdgepointMiddleIndex, *hBuffer, 2 );
if( gus1stEastEdgepointArraySize )
{
gps1stEastEdgepointArray = (INT16*)MemAlloc( gus1stEastEdgepointArraySize * sizeof( INT16 ) );
Assert( gps1stEastEdgepointArray );
LOADDATA( gps1stEastEdgepointArray, *hBuffer, gus1stEastEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus1stSouthEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus1stSouthEdgepointMiddleIndex, *hBuffer, 2 );
if( gus1stSouthEdgepointArraySize )
{
gps1stSouthEdgepointArray = (INT16*)MemAlloc( gus1stSouthEdgepointArraySize * sizeof( INT16 ) );
Assert( gps1stSouthEdgepointArray );
LOADDATA( gps1stSouthEdgepointArray, *hBuffer, gus1stSouthEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus1stWestEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus1stWestEdgepointMiddleIndex, *hBuffer, 2 );
if( gus1stWestEdgepointArraySize )
{
gps1stWestEdgepointArray = (INT16*)MemAlloc( gus1stWestEdgepointArraySize * sizeof( INT16 ) );
Assert( gps1stWestEdgepointArray );
LOADDATA( gps1stWestEdgepointArray, *hBuffer, gus1stWestEdgepointArraySize * sizeof( INT16 ) );
}
}
BOOLEAN LoadMapEdgepoints( INT8 **hBuffer )
{
TrashMapEdgepoints();
if( gMapInformation.ubMapVersion < 17 )
{ //To prevent invalidation of older maps, which only used one layer of edgepoints, and a UINT8 for
//containing the size, we will preserve that paradigm, then kill the loaded edgepoints and
//regenerate them.
OldLoadMapEdgepoints( hBuffer );
TrashMapEdgepoints();
return FALSE;
}
LOADDATA( &gus1stNorthEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus1stNorthEdgepointMiddleIndex, *hBuffer, 2 );
if( gus1stNorthEdgepointArraySize )
{
gps1stNorthEdgepointArray = (INT16*)MemAlloc( gus1stNorthEdgepointArraySize * sizeof( INT16 ) );
Assert( gps1stNorthEdgepointArray );
LOADDATA( gps1stNorthEdgepointArray, *hBuffer, gus1stNorthEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus1stEastEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus1stEastEdgepointMiddleIndex, *hBuffer, 2 );
if( gus1stEastEdgepointArraySize )
{
gps1stEastEdgepointArray = (INT16*)MemAlloc( gus1stEastEdgepointArraySize * sizeof( INT16 ) );
Assert( gps1stEastEdgepointArray );
LOADDATA( gps1stEastEdgepointArray, *hBuffer, gus1stEastEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus1stSouthEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus1stSouthEdgepointMiddleIndex, *hBuffer, 2 );
if( gus1stSouthEdgepointArraySize )
{
gps1stSouthEdgepointArray = (INT16*)MemAlloc( gus1stSouthEdgepointArraySize * sizeof( INT16 ) );
Assert( gps1stSouthEdgepointArray );
LOADDATA( gps1stSouthEdgepointArray, *hBuffer, gus1stSouthEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus1stWestEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus1stWestEdgepointMiddleIndex, *hBuffer, 2 );
if( gus1stWestEdgepointArraySize )
{
gps1stWestEdgepointArray = (INT16*)MemAlloc( gus1stWestEdgepointArraySize * sizeof( INT16 ) );
Assert( gps1stWestEdgepointArray );
LOADDATA( gps1stWestEdgepointArray, *hBuffer, gus1stWestEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus2ndNorthEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus2ndNorthEdgepointMiddleIndex, *hBuffer, 2 );
if( gus2ndNorthEdgepointArraySize )
{
gps2ndNorthEdgepointArray = (INT16*)MemAlloc( gus2ndNorthEdgepointArraySize * sizeof( INT16 ) );
Assert( gps2ndNorthEdgepointArray );
LOADDATA( gps2ndNorthEdgepointArray, *hBuffer, gus2ndNorthEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus2ndEastEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus2ndEastEdgepointMiddleIndex, *hBuffer, 2 );
if( gus2ndEastEdgepointArraySize )
{
gps2ndEastEdgepointArray = (INT16*)MemAlloc( gus2ndEastEdgepointArraySize * sizeof( INT16 ) );
Assert( gps2ndEastEdgepointArray );
LOADDATA( gps2ndEastEdgepointArray, *hBuffer, gus2ndEastEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus2ndSouthEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus2ndSouthEdgepointMiddleIndex, *hBuffer, 2 );
if( gus2ndSouthEdgepointArraySize )
{
gps2ndSouthEdgepointArray = (INT16*)MemAlloc( gus2ndSouthEdgepointArraySize * sizeof( INT16 ) );
Assert( gps2ndSouthEdgepointArray );
LOADDATA( gps2ndSouthEdgepointArray, *hBuffer, gus2ndSouthEdgepointArraySize * sizeof( INT16 ) );
}
LOADDATA( &gus2ndWestEdgepointArraySize, *hBuffer, 2 );
LOADDATA( &gus2ndWestEdgepointMiddleIndex, *hBuffer, 2 );
if( gus2ndWestEdgepointArraySize )
{
gps2ndWestEdgepointArray = (INT16*)MemAlloc( gus2ndWestEdgepointArraySize * sizeof( INT16 ) );
Assert( gps2ndWestEdgepointArray );
LOADDATA( gps2ndWestEdgepointArray, *hBuffer, gus2ndWestEdgepointArraySize * sizeof( INT16 ) );
}
if( gMapInformation.ubMapVersion < 22 )
{ //regenerate them.
TrashMapEdgepoints();
return FALSE;
}
return TRUE;
}
UINT16 ChooseMapEdgepoint( UINT8 ubStrategicInsertionCode )
{
INT16 *psArray=NULL;
UINT16 usArraySize=0;
static INT32 randomVal=0;
//First validate and get access to the correct array based on strategic direction.
//We will use the selected array to choose insertion gridno's.
switch( ubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH:
psArray = gps1stNorthEdgepointArray;
usArraySize = gus1stNorthEdgepointArraySize;
break;
case INSERTION_CODE_EAST:
psArray = gps1stEastEdgepointArray;
usArraySize = gus1stEastEdgepointArraySize;
break;
case INSERTION_CODE_SOUTH:
psArray = gps1stSouthEdgepointArray;
usArraySize = gus1stSouthEdgepointArraySize;
break;
case INSERTION_CODE_WEST:
psArray = gps1stWestEdgepointArray;
usArraySize = gus1stWestEdgepointArraySize;
break;
default:
AssertMsg( 0, "ChooseMapEdgepoints: Failed to pass a valid strategic insertion code." );
break;
}
if( !usArraySize )
{
return NOWHERE;
}
return psArray[ Random( usArraySize ) ];
}
void ChooseMapEdgepoints( MAPEDGEPOINTINFO *pMapEdgepointInfo, UINT8 ubStrategicInsertionCode, UINT8 ubNumDesiredPoints )
{
INT16 *psArray=NULL;
UINT16 usArraySize=0;
INT32 i=-1;
UINT16 usSlots, usCurrSlot;
INT16 *psTempArray = NULL;
AssertMsg( ubNumDesiredPoints > 0 && ubNumDesiredPoints <= 32,
String( "ChooseMapEdgepoints: Desired points = %d, valid range is 1-32", ubNumDesiredPoints ) );
//First validate and get access to the correct array based on strategic direction.
//We will use the selected array to choose insertion gridno's.
switch( ubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH:
psArray = gps1stNorthEdgepointArray;
usArraySize = gus1stNorthEdgepointArraySize;
break;
case INSERTION_CODE_EAST:
psArray = gps1stEastEdgepointArray;
usArraySize = gus1stEastEdgepointArraySize;
break;
case INSERTION_CODE_SOUTH:
psArray = gps1stSouthEdgepointArray;
usArraySize = gus1stSouthEdgepointArraySize;
break;
case INSERTION_CODE_WEST:
psArray = gps1stWestEdgepointArray;
usArraySize = gus1stWestEdgepointArraySize;
break;
default:
AssertMsg( 0, "ChooseMapEdgepoints: Failed to pass a valid strategic insertion code." );
break;
}
pMapEdgepointInfo->ubStrategicInsertionCode = ubStrategicInsertionCode;
#ifdef JA2BETAVERSION
if( !psArray || !usArraySize )
{
if( gMapInformation.sNorthGridNo == -1 && gMapInformation.sEastGridNo == -1 &&
gMapInformation.sSouthGridNo == -1 && gMapInformation.sWestGridNo == -1 &&
gMapInformation.sCenterGridNo == -1 )
{
if( gbWorldSectorZ )
{
AssertMsg( 0,
String( "Map %c%d_b%d(_a) doesn't have ANY entry points which means that it is impossible to generate map edgepoints. (LC : 1)",
gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
}
else
{
AssertMsg( 0,
String( "Map %c%d(_a) doesn't have ANY entry points which means that it is impossible to generate map edgepoints. (LC : 1)",
gWorldSectorY + 'A' - 1, gWorldSectorX ) );
}
}
else switch( ubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH:
AssertMsg( 0, "This map doesn't have any north mapedgepoints. Possibly because there is no north entry point. (LC : 1)" );
break;
case INSERTION_CODE_EAST:
AssertMsg( 0, "This map doesn't have any east mapedgepoints. Possibly because there is no east entry point. (LC : 1)" );
break;
case INSERTION_CODE_SOUTH:
AssertMsg( 0, "This map doesn't have any south mapedgepoints. Possibly because there is no south entry point. (LC : 1)" );
break;
case INSERTION_CODE_WEST:
AssertMsg( 0, "This map doesn't have any west mapedgepoints. Possibly because there is no west entry point. NOTE: Teleportation always uses the west entrypoint. Some maps shouldn't have west entrypoints. (LC : 1)" );
break;
}
}
#endif
if( !usArraySize )
{
pMapEdgepointInfo->ubNumPoints = 0;
return;
}
// JA2 Gold: don't place people in the water.
// If any of the waypoints is on a water spot, we're going to have to remove it
psTempArray = (INT16 *) MemAlloc( sizeof(INT16) * usArraySize );
memcpy(psTempArray, psArray, sizeof(INT16) * usArraySize );
psArray = psTempArray;
for (i = 0; i < usArraySize; i++)
{
if (TERRAIN_IS_HIGH_WATER( GetTerrainType(psArray[ i ]) ) )
{
if (i == usArraySize - 1)
{
// just axe it and we're done.
psArray[ i ] = 0;
usArraySize--;
break;
}
else
{
// replace this element in the array with the LAST element in the array, then decrement
// the array size
psArray[ i ] = psArray[usArraySize-1];
usArraySize--;
// we're going to have to check the array element we just copied into this spot, too
i--;
}
}
}
if( ubNumDesiredPoints >= usArraySize )
{ //We don't have enough points for everyone, return them all.
pMapEdgepointInfo->ubNumPoints = (UINT8)usArraySize;
for( i = 0; i < usArraySize; i++ )
pMapEdgepointInfo->sGridNo[i] = psArray[i];
// JA2Gold: free the temp array
MemFree(psTempArray);
return;
}
//We have more points, so choose them randomly.
usSlots = usArraySize;
usCurrSlot = 0;
pMapEdgepointInfo->ubNumPoints = ubNumDesiredPoints;
for( i = 0; i < usArraySize; i++ )
{
if( Random( usSlots ) < ubNumDesiredPoints )
{
pMapEdgepointInfo->sGridNo[ usCurrSlot++ ] = psArray[ i ];
ubNumDesiredPoints--;
}
usSlots--;
}
// JA2Gold: free the temp array
MemFree(psTempArray);
}
INT16 *gpReservedGridNos = NULL;
INT16 gsReservedIndex = 0;
void BeginMapEdgepointSearch()
{
INT16 sGridNo;
//Create the reserved list
AssertMsg( !gpReservedGridNos, "Attempting to BeginMapEdgepointSearch that has already been created." );
gpReservedGridNos = (INT16*)MemAlloc( 20 * sizeof( INT16 ) );
Assert( gpReservedGridNos );
gsReservedIndex = 0;
if( gMapInformation.sNorthGridNo != -1 )
sGridNo = gMapInformation.sNorthGridNo;
else if( gMapInformation.sEastGridNo != -1 )
sGridNo = gMapInformation.sEastGridNo;
else if( gMapInformation.sSouthGridNo != -1 )
sGridNo = gMapInformation.sSouthGridNo;
else if( gMapInformation.sWestGridNo != -1 )
sGridNo = gMapInformation.sWestGridNo;
else
return;
GlobalReachableTest( sGridNo );
//Now, we have the path values calculated. Now, we can check for closest edgepoints.
}
void EndMapEdgepointSearch()
{
AssertMsg( gpReservedGridNos, "Attempting to EndMapEdgepointSearch that has already been removed." );
MemFree( gpReservedGridNos );
gpReservedGridNos = NULL;
gsReservedIndex = 0;
}
//THIS CODE ISN'T RECOMMENDED FOR TIME CRITICAL AREAS.
INT16 SearchForClosestPrimaryMapEdgepoint( INT16 sGridNo, UINT8 ubInsertionCode )
{
INT32 i, iDirectionLoop;
INT16 *psArray=NULL;
INT16 sRadius, sDistance, sDirection, sOriginalGridNo;
UINT16 usArraySize=0;
BOOLEAN fReserved;
if( gsReservedIndex >= 20 )
{ //Everything is reserved.
AssertMsg( 0, "All closest map edgepoints have been reserved. We should only have 20 soldiers maximum...");
}
switch( ubInsertionCode )
{
case INSERTION_CODE_NORTH:
psArray = gps1stNorthEdgepointArray;
usArraySize = gus1stNorthEdgepointArraySize;
if( !usArraySize )
AssertMsg( 0, String( "Sector %c%d level %d doesn't have any north mapedgepoints. LC:1",
gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
break;
case INSERTION_CODE_EAST:
psArray = gps1stEastEdgepointArray;
usArraySize = gus1stEastEdgepointArraySize;
if( !usArraySize )
AssertMsg( 0, String( "Sector %c%d level %d doesn't have any east mapedgepoints. LC:1",
gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
break;
case INSERTION_CODE_SOUTH:
psArray = gps1stSouthEdgepointArray;
usArraySize = gus1stSouthEdgepointArraySize;
if( !usArraySize )
AssertMsg( 0, String( "Sector %c%d level %d doesn't have any south mapedgepoints. LC:1",
gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
break;
case INSERTION_CODE_WEST:
psArray = gps1stWestEdgepointArray;
usArraySize = gus1stWestEdgepointArraySize;
if( !usArraySize )
AssertMsg( 0, String( "Sector %c%d level %d doesn't have any west mapedgepoints. LC:1",
gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
break;
}
if( !usArraySize )
{
return NOWHERE;
}
//Check the initial gridno, to see if it is available and an edgepoint.
fReserved = FALSE;
for( i = 0; i < gsReservedIndex; i++ )
{
if( gpReservedGridNos[ i ] == sGridNo )
{
fReserved = TRUE;
break;
}
}
if( !fReserved )
{ //Not reserved, so see if we can find this gridno in the edgepoint array.
for( i = 0 ; i < usArraySize; i++ )
{
if( psArray[ i ] == sGridNo )
{ //Yes, the gridno is in the edgepoint array.
gpReservedGridNos[ gsReservedIndex ] = sGridNo;
gsReservedIndex++;
return sGridNo;
}
}
}
//spiral outwards, until we find an unreserved mapedgepoint.
//
// 09 08 07 06
// 10 01 00 05
// 11 02 03 04
// 12 13 14 15 ..
sRadius = 1;
sDirection = WORLD_COLS;
sOriginalGridNo = sGridNo;
while( sRadius < (INT16)(gbWorldSectorZ ? 30 : 10) )
{
sGridNo = sOriginalGridNo + (-1 - WORLD_COLS)*sRadius; //start at the TOP-LEFT gridno
for( iDirectionLoop = 0; iDirectionLoop < 4; iDirectionLoop++ )
{
switch( iDirectionLoop )
{
case 0: sDirection = WORLD_COLS; break;
case 1: sDirection = 1; break;
case 2: sDirection = -WORLD_COLS; break;
case 3: sDirection = -1; break;
}
sDistance = sRadius * 2;
while( sDistance-- )
{
sGridNo += sDirection;
if( sGridNo < 0 || sGridNo >= WORLD_MAX )
continue;
//Check the gridno, to see if it is available and an edgepoint.
fReserved = FALSE;
for( i = 0; i < gsReservedIndex; i++ )
{
if( gpReservedGridNos[ i ] == sGridNo )
{
fReserved = TRUE;
break;
}
}
if( !fReserved )
{ //Not reserved, so see if we can find this gridno in the edgepoint array.
for( i = 0 ; i < usArraySize; i++ )
{
if( psArray[ i ] == sGridNo )
{ //Yes, the gridno is in the edgepoint array.
gpReservedGridNos[ gsReservedIndex ] = sGridNo;
gsReservedIndex++;
return sGridNo;
}
}
}
}
}
sRadius++;
}
return NOWHERE ;
}
INT16 SearchForClosestSecondaryMapEdgepoint( INT16 sGridNo, UINT8 ubInsertionCode )
{
INT32 i, iDirectionLoop;
INT16 *psArray=NULL;
INT16 sRadius, sDistance, sDirection, sOriginalGridNo;
UINT16 usArraySize=0;
BOOLEAN fReserved;
if( gsReservedIndex >= 20 )
{ //Everything is reserved.
AssertMsg( 0, "All closest map edgepoints have been reserved. We should only have 20 soldiers maximum...");
}
switch( ubInsertionCode )
{
case INSERTION_CODE_NORTH:
psArray = gps2ndNorthEdgepointArray;
usArraySize = gus2ndNorthEdgepointArraySize;
if( !usArraySize )
AssertMsg( 0, String( "Sector %c%d level %d doesn't have any isolated north mapedgepoints. KM:1",
gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
break;
case INSERTION_CODE_EAST:
psArray = gps2ndEastEdgepointArray;
usArraySize = gus2ndEastEdgepointArraySize;
if( !usArraySize )
AssertMsg( 0, String( "Sector %c%d level %d doesn't have any isolated east mapedgepoints. KM:1",
gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
break;
case INSERTION_CODE_SOUTH:
psArray = gps2ndSouthEdgepointArray;
usArraySize = gus2ndSouthEdgepointArraySize;
if( !usArraySize )
AssertMsg( 0, String( "Sector %c%d level %d doesn't have any isolated south mapedgepoints. KM:1",
gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
break;
case INSERTION_CODE_WEST:
psArray = gps2ndWestEdgepointArray;
usArraySize = gus2ndWestEdgepointArraySize;
if( !usArraySize )
AssertMsg( 0, String( "Sector %c%d level %d doesn't have any isolated west mapedgepoints. KM:1",
gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
break;
}
if( !usArraySize )
{
return NOWHERE;
}
//Check the initial gridno, to see if it is available and an edgepoint.
fReserved = FALSE;
for( i = 0; i < gsReservedIndex; i++ )
{
if( gpReservedGridNos[ i ] == sGridNo )
{
fReserved = TRUE;
break;
}
}
if( !fReserved )
{ //Not reserved, so see if we can find this gridno in the edgepoint array.
for( i = 0 ; i < usArraySize; i++ )
{
if( psArray[ i ] == sGridNo )
{ //Yes, the gridno is in the edgepoint array.
gpReservedGridNos[ gsReservedIndex ] = sGridNo;
gsReservedIndex++;
return sGridNo;
}
}
}
//spiral outwards, until we find an unreserved mapedgepoint.
//
// 09 08 07 06
// 10 01 00 05
// 11 02 03 04
// 12 13 14 15 ..
sRadius = 1;
sDirection = WORLD_COLS;
sOriginalGridNo = sGridNo;
while( sRadius < (INT16)(gbWorldSectorZ ? 30 : 10) )
{
sGridNo = sOriginalGridNo + (-1 - WORLD_COLS)*sRadius; //start at the TOP-LEFT gridno
for( iDirectionLoop = 0; iDirectionLoop < 4; iDirectionLoop++ )
{
switch( iDirectionLoop )
{
case 0: sDirection = WORLD_COLS; break;
case 1: sDirection = 1; break;
case 2: sDirection = -WORLD_COLS; break;
case 3: sDirection = -1; break;
}
sDistance = sRadius * 2;
while( sDistance-- )
{
sGridNo += sDirection;
if( sGridNo < 0 || sGridNo >= WORLD_MAX )
continue;
//Check the gridno, to see if it is available and an edgepoint.
fReserved = FALSE;
for( i = 0; i < gsReservedIndex; i++ )
{
if( gpReservedGridNos[ i ] == sGridNo )
{
fReserved = TRUE;
break;
}
}
if( !fReserved )
{ //Not reserved, so see if we can find this gridno in the edgepoint array.
for( i = 0 ; i < usArraySize; i++ )
{
if( psArray[ i ] == sGridNo )
{ //Yes, the gridno is in the edgepoint array.
gpReservedGridNos[ gsReservedIndex ] = sGridNo;
gsReservedIndex++;
return sGridNo;
}
}
}
}
}
sRadius++;
}
return NOWHERE ;
}
#define EDGE_OF_MAP_SEARCH 5
BOOLEAN VerifyEdgepoint( SOLDIERTYPE * pSoldier, INT16 sEdgepoint )
{
INT32 iSearchRange;
INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset;
INT16 sGridNo;
INT8 bDirection;
pSoldier->sGridNo = sEdgepoint;
iSearchRange = EDGE_OF_MAP_SEARCH;
// determine maximum horizontal limits
sMaxLeft = min( iSearchRange, (pSoldier->sGridNo % MAXCOL));
//NumMessage("sMaxLeft = ",sMaxLeft);
sMaxRight = min( iSearchRange, MAXCOL - ((pSoldier->sGridNo % MAXCOL) + 1));
//NumMessage("sMaxRight = ",sMaxRight);
// determine maximum vertical limits
sMaxUp = min( iSearchRange, (pSoldier->sGridNo / MAXROW));
//NumMessage("sMaxUp = ",sMaxUp);
sMaxDown = min( iSearchRange, MAXROW - ((pSoldier->sGridNo / MAXROW) + 1));
// Call FindBestPath to set flags in all locations that we can
// walk into within range. We have to set some things up first...
// set the distance limit of the square region
gubNPCDistLimit = EDGE_OF_MAP_SEARCH;
// reset the "reachable" flags in the region we're looking at
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
{
for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++)
{
sGridNo = sEdgepoint + sXOffset + (MAXCOL * sYOffset);
gpWorldLevelData[sGridNo].uiFlags &= ~(MAPELEMENT_REACHABLE);
}
}
FindBestPath( pSoldier, NOWHERE, pSoldier->pathing.bLevel, WALKING, COPYREACHABLE, PATH_THROUGH_PEOPLE );
// Turn off the "reachable" flag for the current location
// so we don't consider it
//gpWorldLevelData[sEdgepoint].uiFlags &= ~(MAPELEMENT_REACHABLE);
// SET UP DOUBLE-LOOP TO STEP THROUGH POTENTIAL GRID #s
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
{
for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++)
{
// calculate the next potential gridno
sGridNo = sEdgepoint + sXOffset + (MAXCOL * sYOffset);
if (!(gpWorldLevelData[sGridNo].uiFlags & MAPELEMENT_REACHABLE))
{
continue;
}
if (GridNoOnEdgeOfMap( sGridNo, &bDirection ) )
{
// ok!
return TRUE;
}
}
}
// no spots right on edge of map within 5 tiles
return FALSE;
}
BOOLEAN EdgepointsClose( SOLDIERTYPE *pSoldier, INT16 sEdgepoint1, INT16 sEdgepoint2 )
{
INT32 iSearchRange;
INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset;
INT16 sGridNo;
pSoldier->sGridNo = sEdgepoint1;
if( gWorldSectorX == 14 && gWorldSectorY == 9 && !gbWorldSectorZ )
{ //BRUTAL CODE -- special case map.
iSearchRange = 250;
}
else
{
iSearchRange = EDGE_OF_MAP_SEARCH;
}
// determine maximum horizontal limits
sMaxLeft = min( iSearchRange, (pSoldier->sGridNo % MAXCOL));
//NumMessage("sMaxLeft = ",sMaxLeft);
sMaxRight = min( iSearchRange, MAXCOL - ((pSoldier->sGridNo % MAXCOL) + 1));
//NumMessage("sMaxRight = ",sMaxRight);
// determine maximum vertical limits
sMaxUp = min( iSearchRange, (pSoldier->sGridNo / MAXROW));
//NumMessage("sMaxUp = ",sMaxUp);
sMaxDown = min( iSearchRange, MAXROW - ((pSoldier->sGridNo / MAXROW) + 1));
// Call FindBestPath to set flags in all locations that we can
// walk into within range. We have to set some things up first...
// set the distance limit of the square region
gubNPCDistLimit = (UINT8)iSearchRange;
// reset the "reachable" flags in the region we're looking at
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
{
for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++)
{
sGridNo = sEdgepoint1 + sXOffset + (MAXCOL * sYOffset);
gpWorldLevelData[sGridNo].uiFlags &= ~(MAPELEMENT_REACHABLE);
}
}
if( FindBestPath( pSoldier, sEdgepoint2, pSoldier->pathing.bLevel, WALKING, COPYREACHABLE, PATH_THROUGH_PEOPLE ) )
{
return TRUE;
}
return FALSE;
}
UINT8 CalcMapEdgepointClassInsertionCode( INT16 sGridNo )
{
SOLDIERTYPE Soldier;
INT32 iLoop;
INT16 *psEdgepointArray1, *psEdgepointArray2;
INT32 iEdgepointArraySize1, iEdgepointArraySize2;
INT16 sClosestSpot1 = NOWHERE, sClosestDist1 = 0x7FFF, sTempDist;
INT16 sClosestSpot2 = NOWHERE, sClosestDist2 = 0x7FFF;
BOOLEAN fPrimaryValid = FALSE, fSecondaryValid = FALSE;
Soldier.bTeam = 1;
Soldier.sGridNo = sGridNo;
if( gMapInformation.sIsolatedGridNo == -1 )
{ //If the map has no isolated area, then all edgepoints are primary.
return INSERTION_CODE_PRIMARY_EDGEINDEX;
}
switch( gubTacticalDirection )
{
case NORTH:
psEdgepointArray1 = gps1stNorthEdgepointArray;
iEdgepointArraySize1 = gus1stNorthEdgepointArraySize;
psEdgepointArray2 = gps2ndNorthEdgepointArray;
iEdgepointArraySize2 = gus2ndNorthEdgepointArraySize;
break;
case EAST:
psEdgepointArray1 = gps1stEastEdgepointArray;
iEdgepointArraySize1 = gus1stEastEdgepointArraySize;
psEdgepointArray2 = gps2ndEastEdgepointArray;
iEdgepointArraySize2 = gus2ndEastEdgepointArraySize;
break;
case SOUTH:
psEdgepointArray1 = gps1stSouthEdgepointArray;
iEdgepointArraySize1 = gus1stSouthEdgepointArraySize;
psEdgepointArray2 = gps2ndSouthEdgepointArray;
iEdgepointArraySize2 = gus2ndSouthEdgepointArraySize;
break;
case WEST:
psEdgepointArray1 = gps1stWestEdgepointArray;
iEdgepointArraySize1 = gus1stWestEdgepointArraySize;
psEdgepointArray2 = gps2ndWestEdgepointArray;
iEdgepointArraySize2 = gus2ndWestEdgepointArraySize;
break;
default:
// WTF???
return INSERTION_CODE_PRIMARY_EDGEINDEX;
}
// Do a 2D search to find the closest map edgepoint and
// try to create a path there
for ( iLoop = 0; iLoop < iEdgepointArraySize1; iLoop++ )
{
sTempDist = PythSpacesAway( sGridNo, psEdgepointArray1[ iLoop ] );
if ( sTempDist < sClosestDist1 )
{
sClosestDist1 = sTempDist;
sClosestSpot1 = psEdgepointArray1[ iLoop ];
}
}
for ( iLoop = 0; iLoop < iEdgepointArraySize2; iLoop++ )
{
sTempDist = PythSpacesAway( sGridNo, psEdgepointArray2[ iLoop ] );
if ( sTempDist < sClosestDist2 )
{
sClosestDist2 = sTempDist;
sClosestSpot2 = psEdgepointArray2[ iLoop ];
}
}
// set the distance limit of the square region
gubNPCDistLimit = 15;
if( !sClosestDist1 || FindBestPath( &Soldier, sClosestSpot1, 0, WALKING, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) )
{
fPrimaryValid = TRUE;
}
if( !sClosestDist2 || FindBestPath( &Soldier, sClosestSpot2, 0, WALKING, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) )
{
fSecondaryValid = TRUE;
}
if( fPrimaryValid == fSecondaryValid )
{
if( sClosestDist2 < sClosestDist1 )
{
return INSERTION_CODE_SECONDARY_EDGEINDEX;
}
return INSERTION_CODE_PRIMARY_EDGEINDEX;
}
if( fPrimaryValid )
{
return INSERTION_CODE_PRIMARY_EDGEINDEX;
}
return INSERTION_CODE_SECONDARY_EDGEINDEX;
}
#ifdef JA2BETAVERSION
#include "worldman.h"
#include "message.h"
void ShowMapEdgepoints()
{
INT32 i, usIllegal1 = 0, usIllegal2 = 0;
for( i = 0 ; i < gus1stNorthEdgepointArraySize; i++ )
{
if( gps1stNorthEdgepointArray[ i ] != -1 )
{
AddTopmostToTail( gps1stNorthEdgepointArray[ i ], FIRSTPOINTERS5 );
}
else
{
usIllegal1++;
}
}
for( i = 0 ; i < gus1stEastEdgepointArraySize; i++ )
{
if( gps1stEastEdgepointArray[ i ] != -1 )
{
AddTopmostToTail( gps1stEastEdgepointArray[ i ], FIRSTPOINTERS5 );
}
else
{
usIllegal1++;
}
}
for( i = 0 ; i < gus1stSouthEdgepointArraySize; i++ )
{
if( gps1stSouthEdgepointArray[ i ] != -1 )
{
AddTopmostToTail( gps1stSouthEdgepointArray[ i ], FIRSTPOINTERS5 );
}
else
{
usIllegal1++;
}
}
for( i = 0 ; i < gus1stWestEdgepointArraySize; i++ )
{
if( gps1stWestEdgepointArray[ i ] != -1 )
{
AddTopmostToTail( gps1stWestEdgepointArray[ i ], FIRSTPOINTERS5 );
}
else
{
usIllegal1++;
}
}
for( i = 0 ; i < gus2ndNorthEdgepointArraySize; i++ )
{
if( gps2ndNorthEdgepointArray[ i ] != -1 )
{
AddTopmostToTail( gps2ndNorthEdgepointArray[ i ], FIRSTPOINTERS6 );
}
else
{
usIllegal2++;
}
}
for( i = 0 ; i < gus2ndEastEdgepointArraySize; i++ )
{
if( gps2ndEastEdgepointArray[ i ] != -1 )
{
AddTopmostToTail( gps2ndEastEdgepointArray[ i ], FIRSTPOINTERS6 );
}
else
{
usIllegal2++;
}
}
for( i = 0 ; i < gus2ndSouthEdgepointArraySize; i++ )
{
if( gps2ndSouthEdgepointArray[ i ] != -1 )
{
AddTopmostToTail( gps2ndSouthEdgepointArray[ i ], FIRSTPOINTERS6 );
}
else
{
usIllegal2++;
}
}
for( i = 0 ; i < gus2ndWestEdgepointArraySize; i++ )
{
if( gps2ndWestEdgepointArray[ i ] != -1 )
{
AddTopmostToTail( gps2ndWestEdgepointArray[ i ], FIRSTPOINTERS6 );
}
else
{
usIllegal2++;
}
}
if( !usIllegal1 && !usIllegal2 )
{
ScreenMsg( 0, MSG_TESTVERSION, L"Showing display of map edgepoints" );
}
else
{
ScreenMsg( 0, MSG_TESTVERSION, L"Showing display of map edgepoints (%d illegal primary, %d illegal secondary)" );
}
ScreenMsg( 0, MSG_TESTVERSION, L"N:%d:%d E:%d:%d S:%d:%d W:%d:%d",
gus1stNorthEdgepointArraySize, gus2ndNorthEdgepointArraySize,
gus1stEastEdgepointArraySize, gus2ndEastEdgepointArraySize,
gus1stSouthEdgepointArraySize, gus2ndSouthEdgepointArraySize,
gus1stWestEdgepointArraySize, gus2ndWestEdgepointArraySize );
}
void HideMapEdgepoints()
{
INT32 i;
ScreenMsg( 0, MSG_TESTVERSION, L"Removing display of map edgepoints" );
for( i = 0 ; i < gus1stNorthEdgepointArraySize; i++ )
{
if( gps1stNorthEdgepointArray[ i ] != -1 )
{
RemoveAllTopmostsOfTypeRange( gps1stNorthEdgepointArray[ i ], FIRSTPOINTERS, FIRSTPOINTERS );
}
}
for( i = 0 ; i < gus1stEastEdgepointArraySize; i++ )
{
if( gps1stEastEdgepointArray[ i ] != -1 )
{
RemoveAllTopmostsOfTypeRange( gps1stEastEdgepointArray[ i ], FIRSTPOINTERS, FIRSTPOINTERS );
}
}
for( i = 0 ; i < gus1stSouthEdgepointArraySize; i++ )
{
if( gps1stSouthEdgepointArray[ i ] != -1 )
{
RemoveAllTopmostsOfTypeRange( gps1stSouthEdgepointArray[ i ], FIRSTPOINTERS, FIRSTPOINTERS );
}
}
for( i = 0 ; i < gus1stWestEdgepointArraySize; i++ )
{
if( gps1stWestEdgepointArray[ i ] != -1 )
{
RemoveAllTopmostsOfTypeRange( gps1stWestEdgepointArray[ i ], FIRSTPOINTERS, FIRSTPOINTERS );
}
}
for( i = 0 ; i < gus2ndNorthEdgepointArraySize; i++ )
{
if( gps2ndNorthEdgepointArray[ i ] != -1 )
{
RemoveAllTopmostsOfTypeRange( gps2ndNorthEdgepointArray[ i ], FIRSTPOINTERS, FIRSTPOINTERS );
}
}
for( i = 0 ; i < gus2ndEastEdgepointArraySize; i++ )
{
if( gps2ndEastEdgepointArray[ i ] != -1 )
{
RemoveAllTopmostsOfTypeRange( gps2ndEastEdgepointArray[ i ], FIRSTPOINTERS, FIRSTPOINTERS );
}
}
for( i = 0 ; i < gus2ndSouthEdgepointArraySize; i++ )
{
if( gps2ndSouthEdgepointArray[ i ] != -1 )
{
RemoveAllTopmostsOfTypeRange( gps2ndSouthEdgepointArray[ i ], FIRSTPOINTERS, FIRSTPOINTERS );
}
}
for( i = 0 ; i < gus2ndWestEdgepointArraySize; i++ )
{
if( gps2ndWestEdgepointArray[ i ] != -1 )
{
RemoveAllTopmostsOfTypeRange( gps2ndWestEdgepointArray[ i ], FIRSTPOINTERS, FIRSTPOINTERS );
}
}
}
#endif