Files
source/TileEngine/Map Edgepoints.cpp
T
Overhaul 7a27e7105d New attack busy system
Added missing #includes

Added LUA scripting and console

Changed the way tracers are visualized, so they work more like real tracers instead of a light fountain

Fixed signedness of many grid variables used in GetMouseMapPos calls

Fixed enemy weapon choosing:  Sometimes a mortar is chosen but later rejected, but the grenade class was not reset.  Caused assertion failure

Added checks so enemies don't try to chuck RPG grenades with their hands

Now possible to shoot a someone in the head if he's in water

Fixed InitSightArrays to also clear soldier interrupt duel points.  This was causing an assertion failure elsewhere in the code because the interrupt list still had soldiers on it sometimes when this function was called.

Soldiers are much less willing to forfeit their turn over an attempt to use more APs than they have

Removed early setting of muzzle flash.  This would allow enemies to get an interrupt before you even fired.

Fixed item dropping by AI.  If AI tried to drop something while standing it would cause deadlock

Change to greatly speed up closing the sector inventory window in an unloaded sector

Added conditional compile flag to always give robot weapon ready advantage, even for 360 degree sighting


Check builddefines.h for the conditional flags.  Of greatest interest might be LUA_CONSOLE.  This will cause the game to bring up a command console when run.  However this console is severely lacking in many areas.  If anybody knows of an open-source terminal/console that could be used instead, it would be appreciated.  The existing console does bad things when you try to close it, and since it counts as a separate app, it pauses the game while it has focus.

LUA scripting is very limited, basically just proof of concept.  There is one global variable, the Soldiers array.  An array index gives you the soldier in that slot in the currently loaded sector.  The soldier has a few things that can be accessed:  name (short name); fullname (long name); grid (current grid #, can be changed); walkto(grid) (function to walk to another grid); runto(grid) (function to run to another grid)


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@924 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2007-06-09 09:01:04 +00:00

1899 lines
65 KiB
C++

#ifdef PRECOMPILEDHEADERS
#include "TileEngine All.h"
#else
#include <memory.h>
#include "Map Edgepoints.h"
#include "Soldier Control.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
//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;
memset( &Soldier, 0, sizeof( SOLDIERTYPE ) );
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;
memset( &Soldier, 0, sizeof( SOLDIERTYPE ) );
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];
UINT8 gubSaveNPCAPBudget=0;
UINT8 gubSaveNPCDistLimit=0;
//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 (GetTerrainType(psArray[ i ]) == MED_WATER || GetTerrainType(psArray[ i ]) == DEEP_WATER)
{
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->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->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;
memset( &Soldier, 0, sizeof( SOLDIERTYPE ) );
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