Files
source/TileEngine/worlddef.cpp
T
2025-07-23 15:11:03 +03:00

4447 lines
131 KiB
C++

#include "builddefines.h"
#include "worlddef.h"
#include "worlddat.h"
#include "wcheck.h"
#include "debug.h"
#include "worldman.h"
#include "sys globals.h"
#include "Render Fun.h"
#include "lighting.h"
#include "Interactive Tiles.h"
#include "utilities.h"
#include "overhead.h"
#include "opplist.h"
#include "renderworld.h"
#include "Radar Screen.h"
#include "Exit Grids.h"
#include "tile surface.h"
#include "rotting corpses.h"
#include "Keys.h"
#include "Map Information.h"
#include "Animated ProgressBar.h"
#include "pathai.h"
#include "EditorBuildings.h"
#include "Map Edgepoints.h"
#include "Shade Table Util.h"
#include "Structure Wrap.h"
#include "Scheduling.h"
#include "EditorMapInfo.h"
#include "pits.h"
#include "Game Clock.h"
#include "Buildings.h"
#include "strategicmap.h"
#include "overhead map.h"
#include "SmokeEffects.h"
#include "LightEffects.h"
#include "meanwhile.h"
#include "LoadScreen.h"//dnl ch30 150909
#include "Interface Cursors.h"
#include "Simple Render Utils.h"//dnl ch54 111009
#include "Interface.h"
///ddd
#include "gamesettings.h"
#include "editscreen.h"
#include "Editor Taskbar Utils.h"
#ifdef JA2EDITOR
#include "Summary Info.h"
#include "Button Defines.h"
#include "Animation Data.h"
#endif
#define SET_MOVEMENTCOST( a, b, c, d ) ( ( gubWorldMovementCosts[ a ][ b ][ c ] < d ) ? ( gubWorldMovementCosts[ a ][ b ][ c ] = d ) : 0 );
#define FORCE_SET_MOVEMENTCOST( a, b, c, d ) ( gubWorldMovementCosts[ a ][ b ][ c ] = d )
#define SET_CURRMOVEMENTCOST( a, b ) SET_MOVEMENTCOST( usGridNo, a, 0, b )
#define TEMP_FILE_FOR_TILESET_CHANGE "jatileS34.dat"
#define MAP_FULLSOLDIER_SAVED 0x00000001
#define MAP_WORLDONLY_SAVED 0x00000002
#define MAP_WORLDLIGHTS_SAVED 0x00000004
#define MAP_WORLDITEMS_SAVED 0x00000008
#define MAP_EXITGRIDS_SAVED 0x00000010
#define MAP_DOORTABLE_SAVED 0x00000020
#define MAP_EDGEPOINTS_SAVED 0x00000040
#define MAP_AMBIENTLIGHTLEVEL_SAVED 0x00000080
#define MAP_NPCSCHEDULES_SAVED 0x00000100
#ifdef JA2EDITOR
extern BOOLEAN gfErrorCatch;
extern CHAR16 gzErrorCatchString[256];
#endif
//dnl ch43 290909
//<SB> variable map size
INT32 guiWorldCols = OLD_WORLD_COLS;
INT32 guiWorldRows = OLD_WORLD_ROWS;
// size must be multiple of 8
//SB: resize all service array due to tactical map size change
extern UINT8 *gubGridNoMarkers;
extern UINT8 *gubFOVDebugInfoInfo;
extern INT16 gsFullTileDirections[MAX_FULLTILE_DIRECTIONS];
extern INT32 dirDelta[8];
extern INT16 DirIncrementer[8];
extern INT16 *gsCoverValue;
extern INT32 gsTempActionGridNo;
extern INT32 gsOverItemsGridNo;
extern INT32 gsOutOfRangeGridNo;
//</SB>
CHAR8 gubFilename[200];
// TEMP
BOOLEAN gfForceLoadPlayers = FALSE;
CHAR8 gzForceLoadFile[100 ];
BOOLEAN gfForceLoad = FALSE;
UINT8 gubCurrentLevel;
INT32 giCurrentTilesetID = 0;
CHAR8 gzLastLoadedFile[ 260 ];
UINT32 gCurrentBackground = FIRSTTEXTURE;
// From memman.c in SGP
extern UINT32 guiMemTotal;
CHAR8 TileSurfaceFilenames[NUMBEROFTILETYPES][32];
INT8 gbNewTileSurfaceLoaded[ NUMBEROFTILETYPES ];
void SetAllNewTileSurfacesLoaded( BOOLEAN fNew )
{
memset( gbNewTileSurfaceLoaded, fNew, sizeof( gbNewTileSurfaceLoaded ) );
}
BOOLEAN gfInitAnimateLoading = FALSE;
// Local Functions
BOOLEAN LoadTileSurfaces( char pTileSurfaceFilenames[][32], UINT8 ubTilesetID );
BOOLEAN AddTileSurface( SGPFILENAME cFilename, UINT32 ubType, UINT8 ubTilesetID, BOOLEAN fGetFromRoot );
void DestroyTileSurfaces( void );
void ProcessTilesetNamesForBPP(void);
BOOLEAN IsRoofVisibleForWireframe( INT32 sMapPos );
#ifdef JA2UBMAPS
INT32 giOldTilesetUsed;
#endif
INT8 IsHiddenTileMarkerThere( INT32 sGridNo );
extern void SetInterfaceHeightLevel( );
extern void GetRootName( STR8 pDestStr, const STR8 pSrcStr );
void SaveMapLights( HWFILE hfile );
void LoadMapLights( INT8 **hBuffer );
// Global Variables
MAP_ELEMENT *gpWorldLevelData;
INT32 *gpDirtyData;
UINT32 gSurfaceMemUsage;
//UINT8 gubWorldMovementCosts[ WORLD_MAX ][MAXDIR][2];
UINT8 (*gubWorldMovementCosts)[MAXDIR][2] = NULL;//dnl ch43 260909
//ddd to speed up search of illuminated tiles in PATH AI
BOOLEAN gubWorldTileInLight[ MAX_ALLOWED_WORLD_MAX ];
BOOLEAN gubIsCorpseThere[ MAX_ALLOWED_WORLD_MAX ];
INT32 gubMerkCanSeeThisTile[ MAX_ALLOWED_WORLD_MAX ];
//ddd
// set to nonzero (locs of base gridno of structure are good) to have it defined by structure code
INT16 gsRecompileAreaTop = 0;
INT16 gsRecompileAreaLeft = 0;
INT16 gsRecompileAreaRight = 0;
INT16 gsRecompileAreaBottom = 0;
//TIMER TESTING STUFF
#ifdef JA2TESTVERSION
extern UINT32 uiLoadWorldTime;
extern UINT32 uiTrashWorldTime;
extern UINT32 uiLoadMapTilesetTime;
extern UINT32 uiLoadMapLightsTime;
extern UINT32 uiBuildShadeTableTime;
extern UINT32 uiNumTablesLoaded;
extern UINT32 uiNumTablesSaved;
extern UINT32 uiNumImagesReloaded;
#endif
BOOLEAN DoorAtGridNo( INT32 iMapIndex )
{
STRUCTURE *pStruct;
pStruct = gpWorldLevelData[ iMapIndex ].pStructureHead;
while( pStruct )
{
if( pStruct->fFlags & STRUCTURE_ANYDOOR )
return TRUE;
pStruct = pStruct->pNext;
}
return FALSE;
}
BOOLEAN OpenableAtGridNo( INT32 iMapIndex )
{
STRUCTURE *pStruct;
pStruct = gpWorldLevelData[ iMapIndex ].pStructureHead;
while( pStruct )
{
if( pStruct->fFlags & STRUCTURE_OPENABLE )
return TRUE;
pStruct = pStruct->pNext;
}
return FALSE;
}
BOOLEAN FloorAtGridNo( INT32 iMapIndex )
{
LEVELNODE *pLand;
UINT32 uiTileType;
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
// Look through all objects and Search for type
while( pLand )
{
if ( pLand->usIndex != NO_TILE )
{
GetTileType( pLand->usIndex, &uiTileType );
if ( uiTileType >= FIRSTFLOOR && uiTileType <= LASTFLOOR )
{
return TRUE;
}
pLand = pLand->pNext;
}
}
return FALSE;
}
BOOLEAN GridNoIndoors( INT32 iMapIndex )
{
if( gfBasement || gfCaves )
return TRUE;
if( FloorAtGridNo( iMapIndex ) )
return TRUE;
return FALSE;
}
void DOIT( )
{
// LEVELNODE * pLand;
//LEVELNODE * pObject;
LEVELNODE * pStruct, *pNewStruct;
//LEVELNODE * pShadow;
INT32 uiLoop;
// first level
for( uiLoop = 0; uiLoop < WORLD_MAX; uiLoop++ )
{
pStruct = gpWorldLevelData[ uiLoop ].pStructHead;
while ( pStruct != NULL )
{
pNewStruct = pStruct->pNext;
if ( pStruct->usIndex >= DEBRISWOOD1 && pStruct->usIndex <= DEBRISWEEDS10 )
{
AddObjectToHead( uiLoop, pStruct->usIndex );
RemoveStruct( uiLoop, pStruct->usIndex );
}
pStruct = pNewStruct;
}
}
}
BOOLEAN InitializeWorld( )
{
gTileDatabaseSize = 0;
gSurfaceMemUsage = 0;
giCurrentTilesetID = -1;
#ifdef JA2UBMAPS
giOldTilesetUsed = -1;
#endif
SetNumberOfTiles();
// DB Adds the _8 to the names if we're in 8 bit mode.
//ProcessTilesetNamesForBPP();
// Memset tileset list
memset( TileSurfaceFilenames, '\0', sizeof( TileSurfaceFilenames ) );
// ATE: MEMSET LOG HEIGHT VALUES
memset( gTileTypeLogicalHeight, 1, sizeof( gTileTypeLogicalHeight) );
// Memset tile database
memset( gTileDatabase, 0, sizeof(gTileDatabase) );
// Init surface list
memset( gTileSurfaceArray, 0, sizeof( gTileSurfaceArray ) );
// Init default surface list
memset( gbDefaultSurfaceUsed, 0, sizeof( gbDefaultSurfaceUsed ) );
// Init same surface list
memset( gbSameAsDefaultSurfaceUsed, 0, sizeof( gbSameAsDefaultSurfaceUsed ) );
// Initialize world data
gpWorldLevelData = (MAP_ELEMENT *)MemAlloc( WORLD_MAX * sizeof( MAP_ELEMENT ) );
CHECKF( gpWorldLevelData );
// Zero world
memset( gpWorldLevelData, 0, WORLD_MAX * sizeof( MAP_ELEMENT ) );
// Init room database
InitRoomDatabase( );
// INit tilesets
InitEngineTilesets( );
return( TRUE );
}
//dnl ch43 290909
void DeinitializeWorld()
{
TrashWorld();
if(gubGridNoMarkers)
MemFree(gubGridNoMarkers);
if(gsCoverValue)
MemFree(gsCoverValue);
if(gubBuildingInfo)
MemFree(gubBuildingInfo);
if(gusWorldRoomInfo)
MemFree(gusWorldRoomInfo);
if(gubWorldMovementCosts)
MemFree(gubWorldMovementCosts);
if(gpWorldLevelData)
MemFree(gpWorldLevelData);
#ifdef _DEBUG
if(gubFOVDebugInfoInfo)
MemFree(gubFOVDebugInfoInfo);
#endif
if(gpDirtyData)
MemFree(gpDirtyData);
DestroyTileSurfaces();
FreeAllStructureFiles();
DeallocateTileDatabase();
ShutdownRoomDatabase();
}
BOOLEAN ReloadTilesetSlot( INT32 iSlot )
{
return(TRUE);
}
BOOLEAN LoadTileSurfaces( char ppTileSurfaceFilenames[][32], UINT8 ubTilesetID )
{
SGPFILENAME cTemp;
UINT32 uiLoop;
UINT32 uiPercentage;
//UINT32 uiLength;
//UINT16 uiFillColor;
STRING512 ExeDir;
STRING512 INIFile;
// Get Executable Directory
GetExecutableDirectory( ExeDir );
// Adjust Current Dir
// CHECK IF DEFAULT INI OVERRIDE FILE EXISTS
sprintf( INIFile, "%s\\engine.ini", ExeDir );
if ( !FileExists( INIFile ) )
{
// USE PER TILESET BASIS
sprintf( INIFile, "%s\\engine%d.ini", ExeDir, ubTilesetID );
}
// If no Tileset filenames are given, return error
if (ppTileSurfaceFilenames == NULL)
{
return( FALSE );
}
else
{
for (uiLoop = 0; uiLoop < (UINT32)giNumberOfTileTypes; uiLoop++)
strcpy( TileSurfaceFilenames[uiLoop], ppTileSurfaceFilenames[uiLoop] );//(ppTileSurfaceFilenames + (65 * uiLoop)) );
}
//uiFillColor = Get16BPPColor(FROMRGB(223, 223, 223));
//StartFrameBufferRender( );
//ColorFillVideoSurfaceArea( FRAME_BUFFER, 20, 399, 622, 420, uiFillColor );
//ColorFillVideoSurfaceArea( FRAME_BUFFER, 21, 400, 621, 419, 0 );
//EndFrameBufferRender( );
//uiFillColor = Get16BPPColor(FROMRGB( 100, 0, 0 ));
// load the tile surfaces
SetRelativeStartAndEndPercentage( 0, 1, 35, L"Tile Surfaces" );
for (uiLoop = 0; uiLoop < (UINT32)giNumberOfTileTypes; uiLoop++)
{
// ATE: Set flag indicating to use another default
// tileset
#ifdef JA2UBMAPS
// 1 ) If we are going from JA2 to JA25
if ( giOldTilesetUsed < DEFAULT_JA25_TILESET && ubTilesetID >= DEFAULT_JA25_TILESET )
{
gbDefaultSurfaceUsed[ uiLoop ] = FALSE;
}
// 2) From JA25 to JA2
if ( ( giOldTilesetUsed >= DEFAULT_JA25_TILESET || giOldTilesetUsed == -1 ) && ubTilesetID < DEFAULT_JA25_TILESET )
{
gbDefaultSurfaceUsed[ uiLoop ] = FALSE;
}
#endif
uiPercentage = (uiLoop * 100) / (giNumberOfTileTypes-1);
RenderProgressBar( 0, uiPercentage );
//uiFillColor = Get16BPPColor(FROMRGB( 100 + uiPercentage , 0, 0 ));
//ColorFillVideoSurfaceArea( FRAME_BUFFER, 22, 401, 22 + uiLength, 418, uiFillColor );
//InvalidateRegion( 0, 399, 640, 420 );
//EndFrameBufferRender( );
// The cost of having to do this check each time through the loop,
// thus about 20 times, seems better than having to maintain two
// almost completely identical functions
if (ppTileSurfaceFilenames == NULL)
{
GetPrivateProfileString( "TileSurface Filenames", gTileSurfaceName[uiLoop], "", cTemp, SGPFILENAME_LEN, INIFile );
if (*cTemp != '\0')
{
strcpy( TileSurfaceFilenames[uiLoop], cTemp );
if (AddTileSurface( cTemp, uiLoop, ubTilesetID, TRUE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
else
{
// Use default
if (AddTileSurface( TileSurfaceFilenames[uiLoop], uiLoop, ubTilesetID, FALSE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
}
else
{
GetPrivateProfileString( "TileSurface Filenames", gTileSurfaceName[uiLoop], "", cTemp, SGPFILENAME_LEN, INIFile );
if (*cTemp != '\0')
{
strcpy( TileSurfaceFilenames[uiLoop], cTemp );
if (AddTileSurface( cTemp, uiLoop, ubTilesetID, TRUE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
else
{
if (*(ppTileSurfaceFilenames[uiLoop]) != '\0')
{
if (AddTileSurface( ppTileSurfaceFilenames[uiLoop], uiLoop, ubTilesetID, FALSE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
else
{
// USE FIRST TILESET VALUE!
// ATE: If here, don't load default surface if already loaded...
if ( !gbDefaultSurfaceUsed[ uiLoop ] )
{
#ifdef JA2UBMAPS
if( ubTilesetID < DEFAULT_JA25_TILESET && uiLoop != SPECIALTILES )
{
strcpy( TileSurfaceFilenames[uiLoop], gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[uiLoop] );//(char *)(ppTileSurfaceFilenames + (65 * uiLoop)) );
if (AddTileSurface( gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[uiLoop], uiLoop, TLS_GENERIC_1, FALSE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
else
{
if ( uiLoop == 123 )
{
strcpy( TileSurfaceFilenames[123], gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[123] );//(char *)(ppTileSurfaceFilenames + (65 * uiLoop)) );
if (AddTileSurface( gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[123], 123, TLS_GENERIC_1, FALSE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
else if ( uiLoop == 124 )
{
strcpy( TileSurfaceFilenames[124], gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[124] );//(char *)(ppTileSurfaceFilenames + (65 * uiLoop)) );
if (AddTileSurface( gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[124], 124, TLS_GENERIC_1, FALSE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
else if ( uiLoop == 125 )
{
strcpy( TileSurfaceFilenames[125], gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[125] );//(char *)(ppTileSurfaceFilenames + (65 * uiLoop)) );
if (AddTileSurface( gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[125], 125, TLS_GENERIC_1, FALSE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
else if ( uiLoop == 127 )
{
strcpy( TileSurfaceFilenames[127], gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[127] );//(char *)(ppTileSurfaceFilenames + (65 * uiLoop)) );
if (AddTileSurface( gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[127], 127, TLS_GENERIC_1, FALSE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
else
{
strcpy( TileSurfaceFilenames[uiLoop], gTilesets[ DEFAULT_JA25_TILESET ].TileSurfaceFilenames[uiLoop] );//(char *)(ppTileSurfaceFilenames + (65 * uiLoop)) );
if (AddTileSurface( gTilesets[ DEFAULT_JA25_TILESET ].TileSurfaceFilenames[uiLoop], uiLoop, DEFAULT_JA25_TILESET, FALSE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
}
}
#else
strcpy( TileSurfaceFilenames[uiLoop], gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[uiLoop] );//(ppTileSurfaceFilenames + (65 * uiLoop)) );
if (AddTileSurface( gTilesets[ TLS_GENERIC_1 ].TileSurfaceFilenames[uiLoop], uiLoop, TLS_GENERIC_1, FALSE ) == FALSE)
{
DestroyTileSurfaces( );
return( FALSE );
}
#endif
}
else
{
gbSameAsDefaultSurfaceUsed[ uiLoop ] = TRUE;
}
}
}
}
}
return( TRUE );
}
BOOLEAN AddTileSurface( STR8 cFilename, UINT32 ubType, UINT8 ubTilesetID, BOOLEAN fGetFromRoot )
{
// Add tile surface
PTILE_IMAGERY TileSurf;
CHAR8 cFileBPP[128];
CHAR8 cAdjustedFile[ 128 ];
// Delete the surface first!
if ( gTileSurfaceArray[ ubType ] != NULL )
{
DeleteTileSurface( gTileSurfaceArray[ ubType ] );
gTileSurfaceArray[ ubType ] = NULL;
}
// Adjust flag for same as default used...
gbSameAsDefaultSurfaceUsed[ ubType ] = FALSE;
// Adjust for BPP
FilenameForBPP(cFilename, cFileBPP);
if ( !fGetFromRoot )
{
// Adjust for tileset position
sprintf( cAdjustedFile, "TILESETS\\%d\\%s", ubTilesetID, cFileBPP );
}
else
{
sprintf( cAdjustedFile, "%s", cFileBPP );
}
TileSurf = LoadTileSurface( cAdjustedFile );
if ( TileSurf == NULL )
return( FALSE );
TileSurf->fType = ubType;
SetRaisedObjectFlag( cAdjustedFile, TileSurf );
gTileSurfaceArray[ ubType ] = TileSurf;
// OK, if we were not the default tileset, set value indicating that!
#ifdef JA2UBMAPS
// OK, if we were not the default tileset, set value indicating that!
if ( ubTilesetID != TLS_GENERIC_1 && ubTilesetID != 0 )
{
gbDefaultSurfaceUsed[ ubType ] = FALSE;
}
else
{
gbDefaultSurfaceUsed[ ubType ] = TRUE;
}
#else
if ( ubTilesetID != TLS_GENERIC_1 )
{
gbDefaultSurfaceUsed[ ubType ] = FALSE;
}
else
{
gbDefaultSurfaceUsed[ ubType ] = TRUE;
}
#endif
gbNewTileSurfaceLoaded[ ubType ] = TRUE;
return( TRUE );
}
extern BOOLEAN gfLoadShadeTablesFromTextFile;
void BuildTileShadeTables( )
{
// BF
//STRING512 DataDir;
//STRING512 ShadeTableDir;
UINT32 uiLoop;
CHAR8 cRootFile[ 128 ];
BOOLEAN fForceRebuildForSlot = FALSE;
#ifdef JA2TESTVERSION
UINT32 uiStartTime;
#endif
static UINT8 ubLastRed = 255, ubLastGreen = 255, ubLastBlue = 255;
#ifdef JA2TESTVERSION
uiNumTablesLoaded = 0;
uiNumTablesSaved = 0;
uiNumImagesReloaded = 0;
uiStartTime = GetJA2Clock();
#endif
// BF : adjust filename, instead of changing current directory (doesn't make sence with a VFS)
//////////////Set the directory to the shadetable directory
////////////GetFileManCurrentDirectory( DataDir );
////////////sprintf( ShadeTableDir, "%s\\ShadeTables", DataDir );
////////////if( !SetFileManCurrentDirectory( ShadeTableDir ) )
////////////{
//////////// AssertMsg( 0, "Can't set the directory to Data\\ShadeTable. Kris' big problem!" );
////////////}
CHAR8 sIgnoreShadeTables[50];
sprintf( sIgnoreShadeTables, "%s\\%s", "ShadeTables", "IgnoreShadeTables.txt");
//hfile = FileOpen( sIgnoreShadeTables, FILE_ACCESS_READ, FALSE );
//if( hfile )
//{
// FileClose( hfile );
if(FileExists(sIgnoreShadeTables))
{
gfForceBuildShadeTables = TRUE;
}
else
{
gfForceBuildShadeTables = FALSE;
}
//now, determine if we are using specialized colors.
if( gpLightColors[0].peRed || gpLightColors[0].peGreen || gpLightColors[0].peBlue )
{ //we are, which basically means we force build the shadetables. However, the one
//exception is if we are loading another map and the colors are the same.
if( gpLightColors[0].peRed != ubLastRed ||
gpLightColors[0].peGreen != ubLastGreen ||
gpLightColors[0].peBlue != ubLastBlue )
{ //Same tileset, but colors are different, so set things up to regenerate the shadetables.
gfForceBuildShadeTables = TRUE;
}
else
{ //same colors, same tileset, so don't rebuild shadetables -- much faster!
gfForceBuildShadeTables = FALSE;
}
}
if( gfLoadShadeTablesFromTextFile )
{ //Because we're tweaking the RGB values in the text file, always force rebuild the shadetables
//so that the user can tweak them in the same exe session.
memset( gbNewTileSurfaceLoaded, 1, sizeof( gbNewTileSurfaceLoaded ) );
}
for (uiLoop = 0; uiLoop < (UINT32)giNumberOfTileTypes; uiLoop++)
{
if ( gTileSurfaceArray[ uiLoop ] != NULL )
{
// Don't Create shade tables if default were already used once!
#ifdef JA2EDITOR
if( gbNewTileSurfaceLoaded[ uiLoop ] || gfEditorForceShadeTableRebuild )
#else
if( gbNewTileSurfaceLoaded[ uiLoop ] )
#endif
{
fForceRebuildForSlot = FALSE;
GetRootName( cRootFile, TileSurfaceFilenames[ uiLoop ] );
if ( strcmp( cRootFile, "grass2" ) == 0 )
{
fForceRebuildForSlot = TRUE;
}
#ifdef JA2TESTVERSION
uiNumImagesReloaded++;
#endif
RenderProgressBar( 0, uiLoop * 100 / giNumberOfTileTypes );
CreateTilePaletteTables( gTileSurfaceArray[ uiLoop ]->vo, uiLoop, fForceRebuildForSlot );
}
}
}
// BF : see above
////Restore the data directory once we are finished.
//SetFileManCurrentDirectory( DataDir );
ubLastRed = gpLightColors[0].peRed;
ubLastGreen = gpLightColors[0].peGreen;
ubLastBlue = gpLightColors[0].peBlue;
#ifdef JA2TESTVERSION
uiBuildShadeTableTime = GetJA2Clock() - uiStartTime;
#endif
}
void DestroyTileShadeTables( )
{
UINT32 uiLoop;
for (uiLoop = 0; uiLoop < (UINT32)giNumberOfTileTypes; uiLoop++)
{
if ( gTileSurfaceArray[ uiLoop ] != NULL )
{
// Don't Delete shade tables if default are still being used...
#ifdef JA2EDITOR
if( gbNewTileSurfaceLoaded[ uiLoop ] || gfEditorForceShadeTableRebuild )
{
DestroyObjectPaletteTables( gTileSurfaceArray[ uiLoop ]->vo );
}
#else
if( gbNewTileSurfaceLoaded[ uiLoop ] )
{
DestroyObjectPaletteTables( gTileSurfaceArray[ uiLoop ]->vo );
}
#endif
}
}
}
void DestroyTileSurfaces( )
{
UINT32 uiLoop;
for (uiLoop = 0; uiLoop < (UINT32)giNumberOfTileTypes; uiLoop++)
{
if ( gTileSurfaceArray[ uiLoop ] != NULL )
{
DeleteTileSurface( gTileSurfaceArray[ uiLoop ] );
gTileSurfaceArray[ uiLoop ] = NULL;
}
}
}
void CompileWorldTerrainIDs( void )
{
INT32 sGridNo;
INT32 sTempGridNo;
LEVELNODE *pNode;
TILE_ELEMENT *pTileElement;
UINT8 ubLoop;
for( sGridNo = 0; sGridNo < WORLD_MAX; sGridNo++ )
{
if (GridNoOnVisibleWorldTile( sGridNo ))
{
// Check if we have anything in object layer which has a terrain modifier
pNode = gpWorldLevelData[ sGridNo ].pObjectHead;
// ATE: CRAPOLA! Special case stuff here for the friggen pool since art was fu*ked up
#ifdef JA2UBMAPS
if ( giCurrentTilesetID == TEMP_19 )
#else
if ( giCurrentTilesetID == TLS_BALIME_MUSEUM )
#endif
{
// Get ID
if ( pNode != NULL )
{
if ( pNode->usIndex == ANOTHERDEBRIS4 || pNode->usIndex == ANOTHERDEBRIS6 ||pNode->usIndex == ANOTHERDEBRIS7 )
{
gpWorldLevelData[sGridNo].ubTerrainID = LOW_WATER;
continue;
}
}
}
if (pNode == NULL || pNode->usIndex >= giNumberOfTiles || gTileDatabase[ pNode->usIndex ].ubTerrainID == NO_TERRAIN)
{ // Try terrain instead!
pNode = gpWorldLevelData[ sGridNo ].pLandHead;
}
pTileElement = &(gTileDatabase[ pNode->usIndex ]);
if (pTileElement->ubNumberOfTiles > 1)
{
for (ubLoop = 0; ubLoop < pTileElement->ubNumberOfTiles; ubLoop++)
{
sTempGridNo = sGridNo + pTileElement->pTileLocData[ubLoop].bTileOffsetX + pTileElement->pTileLocData[ubLoop].bTileOffsetY * WORLD_COLS;
gpWorldLevelData[sTempGridNo].ubTerrainID = pTileElement->ubTerrainID;
}
}
else
{
gpWorldLevelData[sGridNo].ubTerrainID = pTileElement->ubTerrainID;
}
}
}
}
BOOLEAN IsNotRestrictedWindow(STRUCTURE * pStructure)
{
if ( (pStructure->fFlags & STRUCTURE_WALLNWINDOW) && gGameExternalOptions.fCanJumpThroughWindows
&& !(pStructure->fFlags & STRUCTURE_SPECIAL)
&& (pStructure->fFlags & STRUCTURE_OPEN)
&& (pStructure->pDBStructureRef->pDBStructure->bPartnerDelta == NO_PARTNER_STRUCTURE) )
{
//manual check for closed (unbreakable?) windows
//build_13.sti - closed ( shielded ) windows index:
LEVELNODE *pNode = NULL;// STRUCTURE *pBase=NULL;
UINT32 uiTileType=0;
//pBase = FindStructure( pStructure->sGridNo, STRUCTURE_WALLNWINDOW );
//if(pBase!= NULL)
pNode = FindLevelNodeBasedOnStructure( pStructure->sGridNo, pStructure );
//pNode = gpWorldLevelData[ pStructure->sGridNo ].pStructHead;
if(pNode != NULL)
GetTileType( pNode->usIndex, &uiTileType );
UINT16 RestrSubIndex;
Assert(pNode);
GetSubIndexFromTileIndex( pNode->usIndex, (UINT16 *)&RestrSubIndex );
//this type of window is not present in tileset 0, checking tileset 0 is not necessary in this case
if ( _stricmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], "build_13.sti" ) == 0
//&& ( pNode->usIndex == 814 || pNode->usIndex == 816 || pNode->usIndex == 817 || pNode->usIndex == 823) - restricts only in particular tileset, doesn't work with others
&& (RestrSubIndex == 40 || RestrSubIndex == 41 || RestrSubIndex == 37 || RestrSubIndex == 38
|| RestrSubIndex == 43 || RestrSubIndex == 44 || RestrSubIndex == 46 || RestrSubIndex == 47) //frame numbers in STI
)
return FALSE;
return TRUE;
}
return FALSE;
}
void CompileTileMovementCosts( INT32 usGridNo )
{
UINT8 ubTerrainID;
TILE_ELEMENT TileElem;
LEVELNODE * pLand;
STRUCTURE * pStructure;
BOOLEAN fStructuresOnRoof;
UINT8 ubDirLoop;
if ( GridNoOnVisibleWorldTile( usGridNo ) )
{
// check for land of a different height in adjacent locations
for ( ubDirLoop = 0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop )
{
if ( gpWorldLevelData[ usGridNo ].sHeight !=
gpWorldLevelData[ usGridNo + DirectionInc( ubDirLoop ) ].sHeight )
{
SET_CURRMOVEMENTCOST( ubDirLoop, TRAVELCOST_OBSTACLE );
}
}
// check for exit grids
if ( ExitGridAtGridNo( usGridNo ) )
{
for ( ubDirLoop = 0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop )
{
SET_CURRMOVEMENTCOST( ubDirLoop, TRAVELCOST_EXITGRID );
}
// leave the roof alone, and continue, so that we can get values for the roof if traversable
}
}
else
{
for ( ubDirLoop = 0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop )
{
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 0, TRAVELCOST_OFF_MAP );
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 1, TRAVELCOST_OFF_MAP );
}
if (gpWorldLevelData[usGridNo].pStructureHead == NULL)
{
return;
}
}
if (gpWorldLevelData[usGridNo].pStructureHead != NULL)
{
// structures in tile
// consider the land
pLand = gpWorldLevelData[ usGridNo ].pLandHead;
if ( pLand != NULL )
{
// Set TEMPORARY cost here
// Get from tile database
TileElem = gTileDatabase[ pLand->usIndex ];
// Get terrain type
ubTerrainID = gpWorldLevelData[usGridNo].ubTerrainID; // = GetTerrainType( (INT16)usGridNo );
for (ubDirLoop=0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop)
{
SET_CURRMOVEMENTCOST( ubDirLoop, gTileTypeMovementCost[ ubTerrainID ] );
}
}
// now consider all structures
pStructure = gpWorldLevelData[usGridNo].pStructureHead;
fStructuresOnRoof = FALSE;
do
{
if (pStructure->sCubeOffset == STRUCTURE_ON_GROUND)
{
if (pStructure->fFlags & STRUCTURE_PASSABLE)
{
if (pStructure->fFlags & STRUCTURE_WIREFENCE && pStructure->fFlags & STRUCTURE_OPEN)
{
// prevent movement along the fence but allow in all other directions
switch( pStructure->ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( EAST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( SOUTHEAST, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( SOUTH, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_NOT_STANDING );
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( EAST, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( SOUTHEAST, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( SOUTH, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_NOT_STANDING );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_NOT_STANDING );
break;
}
}
// all other passable structures do not block movement in any way
}
else if (pStructure->fFlags & STRUCTURE_BLOCKSMOVES)
{
if ( (pStructure->fFlags & STRUCTURE_FENCE) && !(pStructure->fFlags & STRUCTURE_SPECIAL) )
{
// jumpable!
switch( pStructure->ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
// can be jumped north and south
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_FENCE );
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( EAST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( SOUTHEAST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( SOUTH, TRAVELCOST_FENCE );
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
// set values for the tiles EXITED from this location
// silversurfer: make sure that there is no obstacle in the target tile!
if ( gubWorldMovementCosts[ usGridNo - WORLD_COLS ][ NORTH ][ 0 ] < TRAVELCOST_BLOCKED )
{
FORCE_SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTH, 0, TRAVELCOST_NONE );
}
SET_MOVEMENTCOST( usGridNo - WORLD_COLS + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
if ( gubWorldMovementCosts[ usGridNo + WORLD_COLS ][ SOUTH ][ 0 ] < TRAVELCOST_BLOCKED )
{
FORCE_SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_NONE );
}
SET_MOVEMENTCOST( usGridNo + WORLD_COLS - 1, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo - 1, WEST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS - 1, NORTHWEST, 0, TRAVELCOST_OBSTACLE );
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
// can be jumped east and west
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( EAST, TRAVELCOST_FENCE );
SET_CURRMOVEMENTCOST( SOUTHEAST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( SOUTH, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_FENCE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
// set values for the tiles EXITED from this location
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTH, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
// make sure no obstacle costs exists before changing path cost to 0
if ( gubWorldMovementCosts[ usGridNo + 1 ][ EAST ][ 0 ] < TRAVELCOST_BLOCKED )
{
FORCE_SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_NONE );
}
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS - 1, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
if ( gubWorldMovementCosts[ usGridNo - 1 ][ WEST ][ 0 ] < TRAVELCOST_BLOCKED )
{
FORCE_SET_MOVEMENTCOST( usGridNo - 1, WEST, 0, TRAVELCOST_NONE );
}
SET_MOVEMENTCOST( usGridNo - WORLD_COLS - 1, NORTHWEST, 0, TRAVELCOST_OBSTACLE );
break;
default:
// corners aren't jumpable
for (ubDirLoop=0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop)
{
SET_CURRMOVEMENTCOST( ubDirLoop, TRAVELCOST_OBSTACLE );
}
break;
}
}
else if ( pStructure->pDBStructureRef->pDBStructure->ubArmour == MATERIAL_SANDBAG && StructureHeight( pStructure ) <= 2 )
{
for (ubDirLoop=0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop)
{
SET_CURRMOVEMENTCOST( ubDirLoop, TRAVELCOST_OBSTACLE );
}
if ( FindStructure( (usGridNo - WORLD_COLS), STRUCTURE_OBSTACLE ) == FALSE && FindStructure( (usGridNo + WORLD_COLS), STRUCTURE_OBSTACLE ) == FALSE )
{
FORCE_SET_MOVEMENTCOST( usGridNo, NORTH, 0, TRAVELCOST_FENCE );
FORCE_SET_MOVEMENTCOST( usGridNo, SOUTH, 0, TRAVELCOST_FENCE );
}
if ( FindStructure( (usGridNo - 1), STRUCTURE_OBSTACLE ) == FALSE && FindStructure( (usGridNo + 1), STRUCTURE_OBSTACLE ) == FALSE )
{
FORCE_SET_MOVEMENTCOST( usGridNo, EAST, 0, TRAVELCOST_FENCE );
FORCE_SET_MOVEMENTCOST( usGridNo, WEST, 0, TRAVELCOST_FENCE );
}
}
else if ( (pStructure->fFlags & STRUCTURE_CAVEWALL ) )
{
for (ubDirLoop=0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop)
{
SET_CURRMOVEMENTCOST( ubDirLoop, TRAVELCOST_CAVEWALL );
}
}
else
{
for (ubDirLoop=0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop)
{
SET_CURRMOVEMENTCOST( ubDirLoop, TRAVELCOST_OBSTACLE );
}
}
}
else if (pStructure->fFlags & STRUCTURE_ANYDOOR) /*&& (pStructure->fFlags & STRUCTURE_OPEN))*/
{ // NB closed doors are treated just like walls, in the section after this
if (pStructure->fFlags & STRUCTURE_DDOOR_LEFT && (pStructure->ubWallOrientation == INSIDE_TOP_RIGHT || pStructure->ubWallOrientation == OUTSIDE_TOP_RIGHT) )
{
// double door, left side (as you look on the screen)
switch( pStructure->ubWallOrientation )
{
case OUTSIDE_TOP_RIGHT:
if (pStructure->fFlags & STRUCTURE_BASE_TILE)
{ // doorpost
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_DOOR_CLOSED_W );
SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_WALL );
// corner
SET_MOVEMENTCOST( usGridNo + 1 + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_WALL );
}
else
{ // door
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_DOOR_OPEN_W );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_DOOR_OPEN_W );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_DOOR_OPEN_NW );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_DOOR_OPEN_NW );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_DOOR_OPEN_W_W );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_DOOR_OPEN_NW_W );
}
break;
case INSIDE_TOP_RIGHT:
// doorpost
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1,NORTHEAST, 0, TRAVELCOST_WALL );
// door
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_DOOR_OPEN_HERE );
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_DOOR_OPEN_HERE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_DOOR_OPEN_N );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_DOOR_OPEN_N );
SET_MOVEMENTCOST( usGridNo - 1, NORTHWEST, 0, TRAVELCOST_DOOR_OPEN_E );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS - 1, SOUTHWEST, 0, TRAVELCOST_DOOR_OPEN_NE );
break;
default:
// door with no orientation specified!?
break;
}
}
else if (pStructure->fFlags & STRUCTURE_DDOOR_RIGHT && (pStructure->ubWallOrientation == INSIDE_TOP_LEFT || pStructure->ubWallOrientation == OUTSIDE_TOP_LEFT) )
{
// double door, right side (as you look on the screen)
switch( pStructure->ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
if (pStructure->fFlags & STRUCTURE_BASE_TILE)
{ // doorpost
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_DOOR_CLOSED_N )
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_WALL ); ;
// corner
SET_MOVEMENTCOST( usGridNo + 1 ,NORTHEAST, 0, TRAVELCOST_WALL );
}
else
{ // door
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_DOOR_OPEN_N );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_DOOR_OPEN_N );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_DOOR_OPEN_NW );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_DOOR_OPEN_NW );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_DOOR_OPEN_N_N );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_DOOR_OPEN_NW_N );
}
break;
case INSIDE_TOP_LEFT:
// doorpost
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_WALL );
// corner
SET_MOVEMENTCOST( usGridNo + 1 ,NORTHEAST, 0, TRAVELCOST_WALL );
// door
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_DOOR_OPEN_HERE );
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_DOOR_OPEN_HERE );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_DOOR_OPEN_W );
SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_DOOR_OPEN_W );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTHWEST, 0, TRAVELCOST_DOOR_OPEN_S );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS + 1, NORTHEAST, 0, TRAVELCOST_DOOR_OPEN_SW );
break;
default:
// door with no orientation specified!?
break;
}
}
else if (pStructure->fFlags & STRUCTURE_SLIDINGDOOR && pStructure->pDBStructureRef->pDBStructure->ubNumberOfTiles > 1)
{
switch( pStructure->ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
// doorframe post in one corner of each of the tiles
if (pStructure->fFlags & STRUCTURE_BASE_TILE)
{
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_DOOR_CLOSED_N );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_DOOR_CLOSED_N );
}
else
{
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_DOOR_CLOSED_N);
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_DOOR_CLOSED_N);
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_WALL );
}
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
// doorframe post in one corner of each of the tiles
if (pStructure->fFlags & STRUCTURE_BASE_TILE)
{
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_DOOR_CLOSED_W );
SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_DOOR_CLOSED_W );
}
else
{
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_DOOR_CLOSED_W );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_DOOR_CLOSED_W );
SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_WALL );
}
break;
}
}
else
{
// standard door
switch( pStructure->ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
if (pStructure->fFlags & STRUCTURE_BASE_TILE)
{ // doorframe
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_DOOR_CLOSED_N );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_WALL );
// DO CORNERS
SET_MOVEMENTCOST( usGridNo - 1, NORTHWEST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS - 1, SOUTHWEST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_WALL );
//SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_OBSTACLE );
//SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
//SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
//SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
// corner
//SET_MOVEMENTCOST( usGridNo + 1 ,NORTHEAST, 0, TRAVELCOST_OBSTACLE );
}
else if (!(pStructure->fFlags & STRUCTURE_SLIDINGDOOR))
{ // door
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( EAST, TRAVELCOST_DOOR_OPEN_N );
SET_MOVEMENTCOST( usGridNo - 1, WEST, 0, TRAVELCOST_DOOR_OPEN_NE );
SET_MOVEMENTCOST( usGridNo - 1, NORTHWEST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_DOOR_OPEN_N_N );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS - 1, SOUTHWEST, 0, TRAVELCOST_DOOR_OPEN_NE_N );
}
break;
case INSIDE_TOP_LEFT:
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_DOOR_CLOSED_N );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
// DO CORNERS
SET_MOVEMENTCOST( usGridNo - 1, NORTHWEST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS - 1, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
// doorframe
//SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_OBSTACLE );
//SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
//SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
//SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
// corner
//SET_MOVEMENTCOST( usGridNo + 1 ,NORTHEAST, 0, TRAVELCOST_OBSTACLE );
// door
if (!(pStructure->fFlags & STRUCTURE_SLIDINGDOOR))
{
SET_CURRMOVEMENTCOST( EAST, TRAVELCOST_DOOR_OPEN_HERE );
SET_CURRMOVEMENTCOST( SOUTHEAST, TRAVELCOST_DOOR_OPEN_HERE );
SET_MOVEMENTCOST( usGridNo - 1, WEST, 0, TRAVELCOST_DOOR_OPEN_E );
SET_MOVEMENTCOST( usGridNo - 1, SOUTHWEST, 0, TRAVELCOST_DOOR_OPEN_E );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTHEAST, 0, TRAVELCOST_DOOR_OPEN_S );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS - 1, NORTHWEST, 0, TRAVELCOST_DOOR_OPEN_SE );
}
break;
case OUTSIDE_TOP_RIGHT:
if (pStructure->fFlags & STRUCTURE_BASE_TILE)
{ // doorframe
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_DOOR_CLOSED_W );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
// DO CORNERS
SET_MOVEMENTCOST( usGridNo - WORLD_COLS + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTHWEST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
//SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_OBSTACLE );
//SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
//SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
//SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
// corner
//SET_MOVEMENTCOST( usGridNo + 1 + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
}
else if (!(pStructure->fFlags & STRUCTURE_SLIDINGDOOR))
{ // door
SET_CURRMOVEMENTCOST( SOUTH, TRAVELCOST_DOOR_OPEN_W );
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_DOOR_OPEN_W );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTH, 0, TRAVELCOST_DOOR_OPEN_SW );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTHWEST, 0, TRAVELCOST_DOOR_OPEN_SW );
SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_DOOR_OPEN_W_W );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS + 1, NORTHEAST, 0, TRAVELCOST_DOOR_OPEN_SW_W );
}
break;
case INSIDE_TOP_RIGHT:
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_DOOR_CLOSED_W );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
// DO CORNERS
SET_MOVEMENTCOST( usGridNo - WORLD_COLS + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTHWEST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
// doorframe
/*
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1,SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1,NORTHEAST, 0, TRAVELCOST_OBSTACLE );
// corner
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTHWEST, 0, TRAVELCOST_OBSTACLE );
*/
if (!(pStructure->fFlags & STRUCTURE_SLIDINGDOOR))
{
// door
SET_CURRMOVEMENTCOST( SOUTH, TRAVELCOST_DOOR_OPEN_HERE );
SET_CURRMOVEMENTCOST( SOUTHEAST, TRAVELCOST_DOOR_OPEN_HERE );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTH, 0, TRAVELCOST_DOOR_OPEN_S );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTHEAST, 0, TRAVELCOST_DOOR_OPEN_S );
SET_MOVEMENTCOST( usGridNo - 1, SOUTHWEST, 0, TRAVELCOST_DOOR_OPEN_E );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS - 1, NORTHWEST, 0, TRAVELCOST_DOOR_OPEN_SE );
}
break;
default:
// door with no orientation specified!?
break;
}
}
/*
switch( pStructure->ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_DOOR_CLOSED_N );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
// DO CORNERS
SET_MOVEMENTCOST( usGridNo - 1, NORTHWEST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS - 1, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_OBSTACLE );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_DOOR_CLOSED_HERE );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_DOOR_CLOSED_W );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
// DO CORNERS
SET_MOVEMENTCOST( usGridNo - WORLD_COLS + 1, NORTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTHWEST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_OBSTACLE );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_OBSTACLE );
break;
default:
// wall with no orientation specified!?
break;
}
*/
}
else if (pStructure->fFlags & STRUCTURE_WALLSTUFF )
{
//ATE: IF a closed door, set to door value
switch( pStructure->ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
SET_CURRMOVEMENTCOST( NORTHEAST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( NORTH, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHEAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTH, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_WALL );
// DO CORNERS
SET_MOVEMENTCOST( usGridNo - 1, NORTHWEST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS - 1, SOUTHWEST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_WALL );
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
SET_CURRMOVEMENTCOST( SOUTHWEST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( WEST, TRAVELCOST_WALL );
SET_CURRMOVEMENTCOST( NORTHWEST, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1, SOUTHEAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1, EAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + 1, NORTHEAST, 0, TRAVELCOST_WALL );
// DO CORNERS
SET_MOVEMENTCOST( usGridNo - WORLD_COLS + 1, NORTHEAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo - WORLD_COLS, NORTHWEST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS + 1, SOUTHEAST, 0, TRAVELCOST_WALL );
SET_MOVEMENTCOST( usGridNo + WORLD_COLS, SOUTHWEST, 0, TRAVELCOST_WALL );
break;
default:
// wall with no orientation specified!?
break;
}
}
}
else
{
if (!(pStructure->fFlags & STRUCTURE_PASSABLE || pStructure->fFlags & STRUCTURE_NORMAL_ROOF))
{
// DNS: Try a fix to prevent people from "permanently" blocking the roof
if (!(pStructure->fFlags & STRUCTURE_PERSON))
{
fStructuresOnRoof = TRUE;
}
}
}
pStructure = pStructure->pNext;
} while (pStructure != NULL);
// HIGHEST LAYER
if ((gpWorldLevelData[ usGridNo ].pRoofHead != NULL))
{
if (!fStructuresOnRoof)
{
for ( ubDirLoop = 0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop )
{
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 1, TRAVELCOST_FLAT );
}
}
else
{
for ( ubDirLoop = 0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop )
{
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 1, TRAVELCOST_OBSTACLE );
}
}
}
else
{
for ( ubDirLoop = 0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop )
{
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 1, TRAVELCOST_OBSTACLE );
}
}
}
else
{
// NO STRUCTURES IN TILE
// consider just the land
// Get terrain type
ubTerrainID = gpWorldLevelData[usGridNo].ubTerrainID; // = GetTerrainType( (INT16)usGridNo );
for ( ubDirLoop = 0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop )
{
SET_MOVEMENTCOST( usGridNo ,ubDirLoop, 0, gTileTypeMovementCost[ ubTerrainID ] );
}
/*
pLand = gpWorldLevelData[ usGridNo ].pLandHead;
if ( pLand != NULL )
{
// Set cost here
// Get from tile database
TileElem = gTileDatabase[ pLand->usIndex ];
// Get terrain type
ubTerrainID = GetTerrainType( (INT16)usGridNo );
for (ubDirLoop=0; ubDirLoop < 8; ubDirLoop++)
{
SET_MOVEMENTCOST( usGridNo ,ubDirLoop, 0, gTileTypeMovementCost[ ubTerrainID ] );
}
}
*/
// HIGHEST LEVEL
if (gpWorldLevelData[ usGridNo ].pRoofHead != NULL)
{
for ( ubDirLoop = 0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop )
{
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 1, TRAVELCOST_FLAT );
}
}
else
{
for ( ubDirLoop = 0; ubDirLoop < NUM_WORLD_DIRECTIONS; ++ubDirLoop )
{
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 1, TRAVELCOST_OBSTACLE );
}
}
}
}
#define LOCAL_RADIUS 4
void RecompileLocalMovementCosts( INT32 sCentreGridNo )
{
INT32 usGridNo;
INT16 sGridX, sGridY;
INT16 sCentreGridX, sCentreGridY;
INT8 bDirLoop;
ConvertGridNoToXY( sCentreGridNo, &sCentreGridX, &sCentreGridY );
for( sGridY = sCentreGridY - LOCAL_RADIUS; sGridY < sCentreGridY + LOCAL_RADIUS; sGridY++ )
{
for( sGridX = sCentreGridX - LOCAL_RADIUS; sGridX < sCentreGridX + LOCAL_RADIUS; sGridX++ )
{
usGridNo = MAPROWCOLTOPOS( sGridY, sGridX );
// times 2 for 2 levels, times 2 for UINT16s
// memset( &(gubWorldMovementCosts[usGridNo]), 0, MAXDIR * 2 * 2 );
if (usGridNo < WORLD_MAX)
{
for( bDirLoop = 0; bDirLoop < MAXDIR; bDirLoop++)
{
gubWorldMovementCosts[usGridNo][bDirLoop][0] = 0;
gubWorldMovementCosts[usGridNo][bDirLoop][1] = 0;
}
}
}
}
// note the radius used in this loop is larger, to guarantee that the
// edges of the recompiled areas are correct (i.e. there could be spillover)
for( sGridY = sCentreGridY - LOCAL_RADIUS - 1; sGridY < sCentreGridY + LOCAL_RADIUS + 1; sGridY++ )
{
for( sGridX = sCentreGridX - LOCAL_RADIUS - 1; sGridX < sCentreGridX + LOCAL_RADIUS + 1; sGridX++ )
{
usGridNo = MAPROWCOLTOPOS( sGridY, sGridX );
if (usGridNo < WORLD_MAX)
{
CompileTileMovementCosts( usGridNo );
}
}
}
}
void RecompileLocalMovementCostsFromRadius( INT32 sCentreGridNo, INT8 bRadius )
{
INT32 usGridNo;
INT16 sGridX, sGridY;
INT16 sCentreGridX, sCentreGridY;
INT8 bDirLoop;
ConvertGridNoToXY( sCentreGridNo, &sCentreGridX, &sCentreGridY );
if (bRadius == 0)
{
// one tile check only
for( bDirLoop = 0; bDirLoop < MAXDIR; bDirLoop++)
{
gubWorldMovementCosts[sCentreGridNo][bDirLoop][0] = 0;
gubWorldMovementCosts[sCentreGridNo][bDirLoop][1] = 0;
}
CompileTileMovementCosts( sCentreGridNo );
}
else
{
for( sGridY = sCentreGridY - bRadius; sGridY < sCentreGridY + bRadius; sGridY++ )
{
for( sGridX = sCentreGridX - bRadius; sGridX < sCentreGridX + bRadius; sGridX++ )
{
usGridNo = MAPROWCOLTOPOS( sGridY, sGridX );
// times 2 for 2 levels, times 2 for UINT16s
// memset( &(gubWorldMovementCosts[usGridNo]), 0, MAXDIR * 2 * 2 );
if (usGridNo < WORLD_MAX)
{
for( bDirLoop = 0; bDirLoop < MAXDIR; bDirLoop++)
{
gubWorldMovementCosts[usGridNo][bDirLoop][0] = 0;
gubWorldMovementCosts[usGridNo][bDirLoop][1] = 0;
}
}
}
}
// note the radius used in this loop is larger, to guarantee that the
// edges of the recompiled areas are correct (i.e. there could be spillover)
for( sGridY = sCentreGridY - bRadius - 1; sGridY < sCentreGridY + bRadius + 1; sGridY++ )
{
for( sGridX = sCentreGridX - bRadius - 1; sGridX < sCentreGridX + bRadius + 1; sGridX++ )
{
usGridNo = MAPROWCOLTOPOS( sGridY, sGridX );
if (usGridNo < WORLD_MAX)
{
CompileTileMovementCosts( usGridNo );
}
}
}
}
}
void AddTileToRecompileArea( INT32 sGridNo )
{
INT32 sCheckGridNo;
INT16 sCheckX;
INT16 sCheckY;
// Set flag to wipe and recompile MPs in this tile
if (sGridNo < 0 || sGridNo >= WORLD_MAX)
{
return;
}
gpWorldLevelData[ sGridNo ].ubExtFlags[0] |= MAPELEMENT_EXT_RECALCULATE_MOVEMENT;
// check Top/Left of recompile region
sCheckGridNo = NewGridNo( sGridNo, DirectionInc( NORTHWEST ) );
sCheckX = sCheckGridNo % WORLD_COLS;
sCheckY = sCheckGridNo / WORLD_COLS;
if ( sCheckX < gsRecompileAreaLeft )
{
gsRecompileAreaLeft = sCheckX;
}
if ( sCheckY < gsRecompileAreaTop )
{
gsRecompileAreaTop = sCheckY;
}
// check Bottom/Right
sCheckGridNo = NewGridNo( sGridNo, DirectionInc( SOUTHEAST ) );
sCheckX = sCheckGridNo % WORLD_COLS;
sCheckY = sCheckGridNo / WORLD_COLS;
if ( sCheckX > gsRecompileAreaRight )
{
gsRecompileAreaRight = sCheckX;
}
if ( sCheckY > gsRecompileAreaBottom )
{
gsRecompileAreaBottom = sCheckY;
}
}
void RecompileLocalMovementCostsInAreaWithFlags( void )
{
INT32 usGridNo;
INT16 sGridX, sGridY;
INT8 bDirLoop;
for( sGridY = gsRecompileAreaTop; sGridY <= gsRecompileAreaBottom; sGridY++ )
{
for( sGridX = gsRecompileAreaLeft; sGridX < gsRecompileAreaRight; sGridX++ )
{
usGridNo = MAPROWCOLTOPOS( sGridY, sGridX );
if ( usGridNo < WORLD_MAX && gpWorldLevelData[ usGridNo ].ubExtFlags[0] & MAPELEMENT_EXT_RECALCULATE_MOVEMENT )
{
// wipe MPs in this tile!
for( bDirLoop = 0; bDirLoop < MAXDIR; bDirLoop++)
{
gubWorldMovementCosts[usGridNo][bDirLoop][0] = 0;
gubWorldMovementCosts[usGridNo][bDirLoop][1] = 0;
}
// reset flag
gpWorldLevelData[ usGridNo ].ubExtFlags[0] &= (~MAPELEMENT_EXT_RECALCULATE_MOVEMENT);
}
}
}
for( sGridY = gsRecompileAreaTop; sGridY <= gsRecompileAreaBottom; sGridY++ )
{
for( sGridX = gsRecompileAreaLeft; sGridX <= gsRecompileAreaRight; sGridX++ )
{
usGridNo = MAPROWCOLTOPOS( sGridY, sGridX );
if (usGridNo < WORLD_MAX)
{
CompileTileMovementCosts( usGridNo );
}
}
}
}
void RecompileLocalMovementCostsForWall( INT32 sGridNo, UINT8 ubOrientation )
{
INT8 bDirLoop;
INT16 sUp, sDown, sLeft, sRight;
INT16 sX, sY;
INT32 sTempGridNo;
switch( ubOrientation )
{
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
sUp = -1;
sDown = 1;
sLeft = 0;
sRight = 1;
break;
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
sUp = 0;
sDown = 1;
sLeft = -1;
sRight = 1;
break;
default:
return;
}
for ( sY = sUp; sY <= sDown; sY++ )
{
for ( sX = sLeft; sX <= sRight; sX++ )
{
sTempGridNo = sGridNo + sX + sY * WORLD_COLS;
for( bDirLoop = 0; bDirLoop < MAXDIR; bDirLoop++)
{
gubWorldMovementCosts[sTempGridNo][bDirLoop][0] = 0;
gubWorldMovementCosts[sTempGridNo][bDirLoop][1] = 0;
}
CompileTileMovementCosts( sTempGridNo );
}
}
}
// GLOBAL WORLD MANIPULATION FUNCTIONS
void CompileWorldMovementCosts(void)//dnl ch56 151009
{
memset(gubWorldMovementCosts, 0, sizeof(UINT8)*WORLD_MAX*MAXDIR*2);
CompileWorldTerrainIDs();
for(INT32 usGridNo=0; usGridNo<WORLD_MAX; usGridNo++)
CompileTileMovementCosts(usGridNo);
}
// SAVING CODE
BOOLEAN SaveWorld(const STR8 puiFilename, FLOAT dMajorMapVersion, UINT8 ubMinorMapVersion)//dnl ch33 150909
{
#ifdef JA2EDITOR
INT32 cnt;
UINT32 uiSoldierSize;
UINT32 uiType;
UINT32 uiFlags;
UINT32 uiBytesWritten;
UINT32 uiNumWarningsCaught = 0;
HWFILE hfile;
LEVELNODE *pLand;
LEVELNODE *pObject;
LEVELNODE *pStruct;
LEVELNODE *pShadow;
LEVELNODE *pRoof;
LEVELNODE *pOnRoof;
LEVELNODE *pTailLand=NULL;
UINT16 usNumExitGrids = 0;
UINT16 usTypeSubIndex;
UINT8 LayerCount;
UINT8 ObjectCount;
UINT8 StructCount;
UINT8 ShadowCount;
UINT8 RoofCount;
UINT8 OnRoofCount;
UINT8 ubType;
UINT8 ubTypeSubIndex;
UINT8 ubTest = 1;
CHAR8 aFilename[2*FILENAME_BUFLEN];//dnl ch81 021213
UINT8 ubCombine;
// UINT8 bCounts[ WORLD_MAX ][8];
UINT8** bCounts = NULL;
INT32 i;
bCounts = (UINT8**)MemAlloc(WORLD_MAX*sizeof(UINT8*));
for(i = 0; i<WORLD_MAX; i++)
bCounts[i] = (UINT8*)MemAlloc(8);
sprintf( aFilename, "MAPS\\%s", puiFilename );
FileDelete(aFilename);// If file exist FileOpen will not truncate, so delete.
// Open file
hfile = FileOpen( aFilename, FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
if ( !hfile )
{
return( FALSE );
}
//dnl ch33 150909
FileWrite(hfile, &dMajorMapVersion, sizeof(FLOAT), &uiBytesWritten);
if(dMajorMapVersion >= 4.00)
FileWrite(hfile, &ubMinorMapVersion, sizeof(UINT8), &uiBytesWritten);
if(!(dMajorMapVersion == VANILLA_MAJOR_MAP_VERSION && ubMinorMapVersion == VANILLA_MINOR_MAP_VERSION))
{
FileWrite(hfile, &WORLD_ROWS, sizeof(INT32), &uiBytesWritten);
FileWrite(hfile, &WORLD_COLS, sizeof(INT32), &uiBytesWritten);
}
// Write FLAGS FOR WORLD
//uiFlags = MAP_WORLDONLY_SAVED;
uiFlags = 0;
uiFlags |= MAP_FULLSOLDIER_SAVED;
uiFlags |= MAP_EXITGRIDS_SAVED;
uiFlags |= MAP_WORLDLIGHTS_SAVED;
uiFlags |= MAP_DOORTABLE_SAVED;
uiFlags |= MAP_WORLDITEMS_SAVED;
uiFlags |= MAP_EDGEPOINTS_SAVED;
if( gfBasement || gfCaves )
uiFlags |= MAP_AMBIENTLIGHTLEVEL_SAVED;
uiFlags |= MAP_NPCSCHEDULES_SAVED;
FileWrite( hfile, &uiFlags, sizeof( INT32 ), &uiBytesWritten );
// Write tileset ID
FileWrite( hfile, &giCurrentTilesetID, sizeof( INT32 ), &uiBytesWritten );
// WDS - Clean up inventory handling
// Write SOLDIER CONTROL SIZE
uiSoldierSize = SIZEOF_SOLDIERTYPE_POD; //SIZEOF_SOLDIERTYPE;
FileWrite( hfile, &uiSoldierSize, sizeof( INT32 ), &uiBytesWritten );
// REMOVE WORLD VISIBILITY TILES
RemoveWorldWireFrameTiles( );
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
// Write out height values
FileWrite( hfile, &gpWorldLevelData[ cnt ].sHeight, sizeof( INT16 ), &uiBytesWritten );
}
// Write out # values - we'll have no more than 15 per level!
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
// Determine number of land
pLand = gpWorldLevelData[ cnt ].pLandHead;
LayerCount = 0;
while( pLand != NULL )
{
LayerCount++;
pLand = pLand->pNext;
}
if( LayerCount > 15 )
{
swprintf( gzErrorCatchString, L"SAVE ABORTED! Land count too high (%d) for gridno %d."
L" Need to fix before map can be saved! There are %d additional warnings.",
LayerCount, cnt, uiNumWarningsCaught );
gfErrorCatch = TRUE;
FileClose( hfile );
return FALSE;
}
if( LayerCount > 10 )
{
uiNumWarningsCaught++;
gfErrorCatch = TRUE;
swprintf( gzErrorCatchString, L"Warnings %d -- Last warning: Land count warning of %d for gridno %d.",
uiNumWarningsCaught, LayerCount, cnt );
}
bCounts[ cnt ][ 0 ] = LayerCount;
// Combine # of land layers with worlddef flags ( first 4 bits )
ubCombine = (UINT8)( ( LayerCount&0xf ) | ( (gpWorldLevelData[ cnt ].uiFlags&0xf)<<4 ) );
// Write combination
FileWrite( hfile, &ubCombine, sizeof( ubCombine ), &uiBytesWritten );
// Determine # of objects
pObject = gpWorldLevelData[ cnt ].pObjectHead;
ObjectCount = 0;
while( pObject != NULL )
{
// DON'T WRITE ANY ITEMS
if ( !(pObject->uiFlags & ( LEVELNODE_ITEM ) ) )
{
UINT32 uiTileType;
//Make sure this isn't a UI Element
GetTileType( pObject->usIndex, &uiTileType );
if( uiTileType < FIRSTPOINTERS )
ObjectCount++;
}
pObject = pObject->pNext;
}
if( ObjectCount > 15 )
{
swprintf( gzErrorCatchString, L"SAVE ABORTED! Object count too high (%d) for gridno %d."
L" Need to fix before map can be saved! There are %d additional warnings.",
ObjectCount, cnt, uiNumWarningsCaught );
gfErrorCatch = TRUE;
FileClose( hfile );
return FALSE;
}
if( ObjectCount > 10 )
{
uiNumWarningsCaught++;
gfErrorCatch = TRUE;
swprintf( gzErrorCatchString, L"Warnings %d -- Last warning: Object count warning of %d for gridno %d.",
uiNumWarningsCaught, ObjectCount, cnt );
}
bCounts[ cnt ][ 1 ] = ObjectCount;
// Determine # of structs
pStruct = gpWorldLevelData[ cnt ].pStructHead;
StructCount = 0;
while( pStruct != NULL )
{
// DON'T WRITE ANY ITEMS
if ( !(pStruct->uiFlags & ( LEVELNODE_ITEM ) ) )
{
StructCount++;
}
pStruct = pStruct->pNext;
}
if( StructCount > 15 )
{
swprintf( gzErrorCatchString, L"SAVE ABORTED! Struct count too high (%d) for gridno %d."
L" Need to fix before map can be saved! There are %d additional warnings.",
StructCount, cnt, uiNumWarningsCaught );
gfErrorCatch = TRUE;
FileClose( hfile );
return FALSE;
}
if( StructCount > 10 )
{
uiNumWarningsCaught++;
gfErrorCatch = TRUE;
swprintf( gzErrorCatchString, L"Warnings %d -- Last warning: Struct count warning of %d for gridno %d.",
uiNumWarningsCaught, StructCount, cnt );
}
bCounts[ cnt ][ 2 ] = StructCount;
ubCombine = (UINT8)( ( ObjectCount&0xf ) | ( (StructCount&0xf)<<4 ) );
// Write combination
FileWrite( hfile, &ubCombine, sizeof( ubCombine ), &uiBytesWritten );
// Determine # of shadows
pShadow = gpWorldLevelData[ cnt ].pShadowHead;
ShadowCount = 0;
while( pShadow != NULL )
{
// Don't write any shadowbuddys or exit grids
if ( !(pShadow->uiFlags & ( LEVELNODE_BUDDYSHADOW | LEVELNODE_EXITGRID ) ) )
{
ShadowCount++;
}
pShadow = pShadow->pNext;
}
if( ShadowCount > 15 )
{
swprintf( gzErrorCatchString, L"SAVE ABORTED! Shadow count too high (%d) for gridno %d."
L" Need to fix before map can be saved! There are %d additional warnings.",
ShadowCount, cnt, uiNumWarningsCaught );
gfErrorCatch = TRUE;
FileClose( hfile );
return FALSE;
}
if( ShadowCount > 10 )
{
uiNumWarningsCaught++;
gfErrorCatch = TRUE;
swprintf( gzErrorCatchString, L"Warnings %d -- Last warning: Shadow count warning of %d for gridno %d.",
uiNumWarningsCaught, ShadowCount, cnt );
}
bCounts[ cnt ][ 3 ] = ShadowCount;
// Determine # of Roofs
pRoof = gpWorldLevelData[ cnt ].pRoofHead;
RoofCount = 0;
while( pRoof != NULL )
{
// ATE: Don't save revealed roof info...
if ( pRoof->usIndex != SLANTROOFCEILING1 )
{
RoofCount++;
}
pRoof = pRoof->pNext;
}
if( RoofCount > 15 )
{
swprintf( gzErrorCatchString, L"SAVE ABORTED! Roof count too high (%d) for gridno %d."
L" Need to fix before map can be saved! There are %d additional warnings.",
RoofCount, cnt, uiNumWarningsCaught );
gfErrorCatch = TRUE;
FileClose( hfile );
return FALSE;
}
if( RoofCount > 10 )
{
uiNumWarningsCaught++;
gfErrorCatch = TRUE;
swprintf( gzErrorCatchString, L"Warnings %d -- Last warning: Roof count warning of %d for gridno %d.",
uiNumWarningsCaught, RoofCount, cnt );
}
bCounts[ cnt ][ 4 ] = RoofCount;
ubCombine = (UINT8)( ( ShadowCount&0xf ) | ( (RoofCount&0xf)<<4 ) );
// Write combination
FileWrite( hfile, &ubCombine, sizeof( ubCombine ), &uiBytesWritten );
// Write OnRoof layer
// Determine # of OnRoofs
pOnRoof = gpWorldLevelData[ cnt ].pOnRoofHead;
OnRoofCount = 0;
while( pOnRoof != NULL )
{
OnRoofCount++;
pOnRoof = pOnRoof->pNext;
}
if( OnRoofCount > 15 )
{
swprintf( gzErrorCatchString, L"SAVE ABORTED! OnRoof count too high (%d) for gridno %d."
L" Need to fix before map can be saved! There are %d additional warnings.",
OnRoofCount, cnt, uiNumWarningsCaught );
gfErrorCatch = TRUE;
FileClose( hfile );
return FALSE;
}
if( OnRoofCount > 10 )
{
uiNumWarningsCaught++;
gfErrorCatch = TRUE;
swprintf( gzErrorCatchString, L"Warnings %d -- Last warning: OnRoof count warning of %d for gridno %d.",
uiNumWarningsCaught, OnRoofCount, cnt );
}
bCounts[ cnt ][ 5 ] = RoofCount;
// Write combination of onroof and nothing...
ubCombine = (UINT8)( ( OnRoofCount&0xf ) );
// Write combination
FileWrite( hfile, &ubCombine, sizeof( ubCombine ), &uiBytesWritten );
}
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
if ( bCounts[ cnt ][ 0 ] == 0 )
{
FileWrite( hfile, &ubTest, sizeof( UINT8 ), &uiBytesWritten );
FileWrite( hfile, &ubTest, sizeof( UINT8 ), &uiBytesWritten );
}
else
{
// Write land layers
// Write out land peices backwards so that they are loaded properly
pLand = gpWorldLevelData[ cnt ].pLandHead;
// GET TAIL
while( pLand != NULL )
{
pTailLand = pLand;
pLand = pLand->pNext;
}
while( pTailLand != NULL )
{
// Write out object type and sub-index
GetTileType( pTailLand->usIndex, &uiType );
ubType = (UINT8)uiType;
GetTypeSubIndexFromTileIndexChar( uiType, pTailLand->usIndex, &ubTypeSubIndex );
FileWrite( hfile, &ubType, sizeof( UINT8 ), &uiBytesWritten );
FileWrite( hfile, &ubTypeSubIndex, sizeof( UINT8 ), &uiBytesWritten );
pTailLand = pTailLand->pPrevNode;
}
}
}
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
// Write object layer
pObject = gpWorldLevelData[ cnt ].pObjectHead;
while( pObject != NULL )
{
// DON'T WRITE ANY ITEMS
if ( !(pObject->uiFlags & ( LEVELNODE_ITEM ) ) )
{
// Write out object type and sub-index
GetTileType( pObject->usIndex, &uiType );
//Make sure this isn't a UI Element
if( uiType < FIRSTPOINTERS )
{
//We are writing 2 bytes for the type subindex in the object layer because the
//ROADPIECES slot contains more than 256 subindices.
ubType = (UINT8)uiType;
GetTypeSubIndexFromTileIndex( uiType, pObject->usIndex, &usTypeSubIndex );
FileWrite( hfile, &ubType, sizeof( UINT8 ), &uiBytesWritten );
FileWrite( hfile, &usTypeSubIndex, sizeof( UINT16 ), &uiBytesWritten );
}
}
pObject = pObject->pNext;
}
}
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
// Write struct layer
pStruct = gpWorldLevelData[ cnt ].pStructHead;
while( pStruct != NULL )
{
// DON'T WRITE ANY ITEMS
if ( !(pStruct->uiFlags & ( LEVELNODE_ITEM ) ) )
{
// Write out object type and sub-index
GetTileType( pStruct->usIndex, &uiType );
ubType = (UINT8)uiType;
GetTypeSubIndexFromTileIndexChar( uiType, pStruct->usIndex, &ubTypeSubIndex );
FileWrite( hfile, &ubType, sizeof( UINT8 ), &uiBytesWritten );
FileWrite( hfile, &ubTypeSubIndex, sizeof( UINT8 ), &uiBytesWritten );
}
pStruct = pStruct->pNext;
}
}
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
// Write shadows
pShadow = gpWorldLevelData[ cnt ].pShadowHead;
while( pShadow != NULL )
{
// Dont't write any buddys or exit grids
if ( !(pShadow->uiFlags & ( LEVELNODE_BUDDYSHADOW | LEVELNODE_EXITGRID ) ) )
{
// Write out object type and sub-index
// Write out object type and sub-index
GetTileType( pShadow->usIndex, &uiType );
ubType = (UINT8)uiType;
GetTypeSubIndexFromTileIndexChar( uiType, pShadow->usIndex, &ubTypeSubIndex );
FileWrite( hfile, &ubType, sizeof( UINT8 ), &uiBytesWritten );
FileWrite( hfile, &ubTypeSubIndex, sizeof( UINT8 ), &uiBytesWritten );
}
else if( pShadow->uiFlags & LEVELNODE_EXITGRID )
{ //count the number of exitgrids
usNumExitGrids++;
}
pShadow = pShadow->pNext;
}
}
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
pRoof = gpWorldLevelData[ cnt ].pRoofHead;
while( pRoof != NULL )
{
// ATE: Don't save revealed roof info...
if ( pRoof->usIndex != SLANTROOFCEILING1 )
{
// Write out object type and sub-index
GetTileType( pRoof->usIndex, &uiType );
ubType = (UINT8)uiType;
GetTypeSubIndexFromTileIndexChar( uiType, pRoof->usIndex, &ubTypeSubIndex );
FileWrite( hfile, &ubType, sizeof( UINT8 ), &uiBytesWritten );
FileWrite( hfile, &ubTypeSubIndex, sizeof( UINT8 ), &uiBytesWritten );
}
pRoof = pRoof->pNext;
}
}
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
// Write OnRoofs
pOnRoof = gpWorldLevelData[ cnt ].pOnRoofHead;
while( pOnRoof != NULL )
{
// Write out object type and sub-index
GetTileType( pOnRoof->usIndex, &uiType );
ubType = (UINT8)uiType;
GetTypeSubIndexFromTileIndexChar( uiType, pOnRoof->usIndex, &ubTypeSubIndex );
FileWrite( hfile, &ubType, sizeof( UINT8 ), &uiBytesWritten );
FileWrite( hfile, &ubTypeSubIndex, sizeof( UINT8 ), &uiBytesWritten );
pOnRoof = pOnRoof->pNext;
}
}
// Write out room information
if(ubMinorMapVersion < 29){
UINT8 tmproom;
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
tmproom = (UINT8)gusWorldRoomInfo[ cnt ];
FileWrite( hfile, &tmproom, sizeof( UINT8 ), &uiBytesWritten );
}
}else{
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
FileWrite( hfile, &gusWorldRoomInfo[ cnt ], sizeof( UINT16 ), &uiBytesWritten );
}
}
if ( uiFlags & MAP_WORLDITEMS_SAVED )
{
// Write out item information
SaveWorldItemsToMap(hfile, dMajorMapVersion, ubMinorMapVersion);//dnl ch33 150909
}
if( uiFlags & MAP_AMBIENTLIGHTLEVEL_SAVED )
{
FileWrite( hfile, &gfBasement, 1, &uiBytesWritten );
FileWrite( hfile, &gfCaves, 1, &uiBytesWritten );
FileWrite( hfile, &ubAmbientLightLevel, 1, &uiBytesWritten );
}
if( uiFlags & MAP_WORLDLIGHTS_SAVED )
{
SaveMapLights( hfile );
}
gMapInformation.ubMapVersion = ubMinorMapVersion;//dnl ch74 241013 all this years MapInfo saves incorrect version :-(
SaveMapInformation(hfile, dMajorMapVersion, ubMinorMapVersion);//dnl ch33 150909
if( uiFlags & MAP_FULLSOLDIER_SAVED )
{
SaveSoldiersToMap(hfile, dMajorMapVersion, ubMinorMapVersion);//dnl ch33 150909
}
if( uiFlags & MAP_EXITGRIDS_SAVED )
{
SaveExitGrids(hfile, usNumExitGrids, dMajorMapVersion, ubMinorMapVersion);//dnl ch33 240909
}
if( uiFlags & MAP_DOORTABLE_SAVED )
{
SaveDoorTableToMap(hfile, dMajorMapVersion, ubMinorMapVersion);//dnl ch33 240909
}
if( uiFlags & MAP_EDGEPOINTS_SAVED )
{
CompileWorldMovementCosts();
GenerateMapEdgepoints(TRUE);//dnl ch43 290909
SaveMapEdgepoints(hfile, dMajorMapVersion, ubMinorMapVersion);//dnl ch33 240909
}
if( uiFlags & MAP_NPCSCHEDULES_SAVED )
{
SaveSchedules(hfile, dMajorMapVersion, ubMinorMapVersion);//dnl ch33 240909
}
FileClose( hfile );
sprintf( gubFilename, puiFilename );
for(i = 0; i<WORLD_MAX; i++)
MemFree(bCounts[i]);
MemFree(bCounts);
#endif //JA2EDITOR
return( TRUE );
}
#define NUM_DIR_SEARCHES 5
INT8 bDirectionsForShadowSearch[ NUM_DIR_SEARCHES ] =
{
WEST,
SOUTHWEST,
SOUTH,
SOUTHEAST,
EAST
};
void OptimizeMapForShadows( )
{
INT32 cnt, dir;
INT32 sNewGridNo;
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
// CHECK IF WE ARE A TREE HERE
if ( IsTreePresentAtGridNo( cnt ) )
{
// CHECK FOR A STRUCTURE A FOOTPRINT AWAY
for ( dir = 0; dir < NUM_DIR_SEARCHES; dir++ )
{
sNewGridNo = NewGridNo( cnt, (UINT16)DirectionInc( bDirectionsForShadowSearch[ dir ] ) );
if ( gpWorldLevelData[ sNewGridNo ].pStructureHead == NULL )
{
break;
}
}
// If we made it here, remove shadow!
// We're full of structures
if ( dir == NUM_DIR_SEARCHES )
{
RemoveAllShadows( cnt );
// Display message to effect
}
}
}
}
void SetBlueFlagFlags( void )
{
INT32 cnt;
LEVELNODE * pNode;
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
pNode = gpWorldLevelData[ cnt ].pStructHead;
while ( pNode )
{
if ( pNode->usIndex == BLUEFLAG_GRAPHIC)
{
gpWorldLevelData[ cnt ].uiFlags |= MAPELEMENT_PLAYER_MINE_PRESENT;
break;
}
pNode = pNode->pNext;
}
}
}
void InitLoadedWorld( )
{
#ifndef JA2EDITOR//dnl ch85 030214 editor allows to load any map so rather skip this check
//if the current sector is not valid, dont init the world
if( gWorldSectorX == 0 || gWorldSectorY == 0 )
{
return;
}
#endif
// COMPILE MOVEMENT COSTS
CompileWorldMovementCosts( );
// COMPILE INTERACTIVE TILES
CompileInteractiveTiles( );
// COMPILE WORLD VISIBLIY TILES
CalculateWorldWireFrameTiles( TRUE );
LightSpriteRenderAll();
OptimizeMapForShadows( );
SetInterfaceHeightLevel( );
// ATE: if we have a slide location, remove it!
gTacticalStatus.sSlideTarget = NOWHERE;
SetBlueFlagFlags();
}
#ifdef JA2EDITOR
//This is a specialty function that is very similar to LoadWorld, except that it
//doesn't actually load the world, it instead evaluates the map and generates summary
//information for use within the summary editor. The header is defined in Summary Info.h,
//not worlddef.h -- though it's not likely this is going to be used anywhere where it would
//matter.
extern double MasterStart, MasterEnd;
extern BOOLEAN gfUpdatingNow;
//dnl ch28 250909
BOOLEAN EvaluateWorld(STR8 pSector, UINT8 ubLevel)
{
FLOAT dMajorMapVersion;
SUMMARYFILE *pSummary;
HWFILE hfile;
INT8 *pBuffer, *pBufferHead;
UINT32 uiFlags, uiFileSize, uiBytesRead;
INT32 i, cnt, iTilesetID;
CHAR16 str[2*FILENAME_BUFLEN];
CHAR8 szDirFilename[2*FILENAME_BUFLEN], szFilename[2*FILENAME_BUFLEN];//dnl ch81 021213
UINT8 ubCombine, ubMinorMapVersion;
UINT8 (*bCounts)[8] = NULL;
// Make sure the file exists... if not, then return false
sprintf(szFilename, pSector);
if(ubLevel % 4)
sprintf(szFilename+strlen(szFilename), "_b%d", ubLevel%4);
if(ubLevel >= 4)
strcat(szFilename, "_a");
strcat(szFilename, ".dat");
CHAR16 szFileName[FILENAME_BUFLEN];//dnl ch81 021213
swprintf(szFileName, L"%S", pSector);
if(ValidMapFileName(szFileName))
strcpy(szFilename, pSector);
sprintf(szDirFilename, "MAPS\\%s", szFilename);
if(guiCurrentScreen == LOADSAVE_SCREEN)
hfile = FileOpen(szDirFilename, FILE_ACCESS_READ, FALSE, gzProfileName);
else
hfile = FileOpen(szDirFilename, FILE_ACCESS_READ);
if(!hfile)
return(FALSE);
uiFileSize = FileGetSize(hfile);
pBuffer = (INT8*)MemAlloc(uiFileSize);
pBufferHead = pBuffer;
FileRead(hfile, pBuffer, uiFileSize, &uiBytesRead);
FileClose(hfile);
swprintf(str, L"Analyzing map %S", szFilename);
if(!gfUpdatingNow)
SetRelativeStartAndEndPercentage(0, 0, 100, str);
else
SetRelativeStartAndEndPercentage(0, (UINT16)MasterStart, (UINT16)MasterEnd, str);
RenderProgressBar(0, 0);
//clear the summary file info
pSummary = (SUMMARYFILE*)MemAlloc(sizeof(SUMMARYFILE));
Assert(pSummary);
memset(pSummary, 0, sizeof(SUMMARYFILE));
pSummary->ubSummaryVersion = GLOBAL_SUMMARY_VERSION;
LOADDATA(&dMajorMapVersion, pBuffer, sizeof(FLOAT));
pSummary->dMajorMapVersion = dMajorMapVersion;
if(dMajorMapVersion >= 4.00)
LOADDATA(&ubMinorMapVersion, pBuffer, sizeof(UINT8));
INT32 iCurRowSize = WORLD_ROWS;
INT32 iCurColSize = WORLD_COLS;
if(dMajorMapVersion < 7.00)
{
WORLD_ROWS = OLD_WORLD_ROWS;
WORLD_COLS = OLD_WORLD_COLS;
}
else
{
INT32 iRowSize, iColSize;
LOADDATA(&iRowSize, pBuffer, sizeof(INT32));
LOADDATA(&iColSize, pBuffer, sizeof(INT32));
WORLD_ROWS = iRowSize;
WORLD_COLS = iColSize;
}
gMapTrn.DisableTrn();//dnl ch44 290909
// Read FLAGS FOR WORLD
LOADDATA(&uiFlags, pBuffer, sizeof(INT32));
// Read tilesetID
LOADDATA(&iTilesetID, pBuffer, sizeof(INT32));
pSummary->ubTilesetID = iTilesetID;
// Skip soldier size
pBuffer += sizeof(INT32);
// Skip height values
pBuffer += sizeof(INT16) * WORLD_MAX;
bCounts = (UINT8(*)[8])MemAlloc(WORLD_MAX*8);
memset(bCounts, 0, sizeof(UINT8)*WORLD_MAX*8);
// Read layer counts
for(cnt=0; cnt<WORLD_MAX; cnt++)
{
if(!(cnt % 2560))
RenderProgressBar(0, (cnt/2560)+1);// 1 - 10
// Read combination of land/world flags
LOADDATA(&ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][0] = (UINT8)(ubCombine & 0x0F);
UINT16 uiFlags = (UINT8)((ubCombine & 0xF0) >> 4);//gpWorldLevelData[cnt].uiFlags |= (UINT8)((ubCombine & 0xF0) >> 4);
// Read #objects, structs
LOADDATA( &ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][1] = (UINT8)(ubCombine & 0x0F);
bCounts[cnt][2] = (UINT8)((ubCombine & 0xF0) >> 4);
// Read shadows, roof
LOADDATA(&ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][3] = (UINT8)(ubCombine & 0x0F);
bCounts[cnt][4] = (UINT8)((ubCombine & 0xF0) >> 4);
// Read OnRoof, nothing
LOADDATA(&ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][5] = (UINT8)(ubCombine & 0x0F);
bCounts[cnt][6] = bCounts[cnt][0] + bCounts[cnt][1] + bCounts[cnt][2] + bCounts[cnt][3] + bCounts[cnt][4] + bCounts[cnt][5];
}
// Skip all layers
for(cnt = 0; cnt<WORLD_MAX; cnt++)
{
if(!(cnt % 320))
RenderProgressBar(0, (cnt/320)+11);// 11 - 90
pBuffer += sizeof(UINT16) * bCounts[cnt][6];
pBuffer += bCounts[cnt][1];
}
// Extract highest room number
//DBrot: More Rooms
UINT8 ubRoomNum;
UINT16 usRoomNum;
if(ubMinorMapVersion < 29){
for(cnt=0; cnt<WORLD_MAX; cnt++)
{
LOADDATA(&ubRoomNum, pBuffer, sizeof(ubRoomNum));
if(ubRoomNum > pSummary->ubNumRooms)
pSummary->ubNumRooms = ubRoomNum;
}
}else{
for(cnt=0; cnt<WORLD_MAX; cnt++)
{
LOADDATA(&usRoomNum, pBuffer, sizeof(usRoomNum));
if(usRoomNum > pSummary->ubNumRooms)
pSummary->ubNumRooms = usRoomNum;
}
}
if(uiFlags & MAP_WORLDITEMS_SAVED)
{
RenderProgressBar(0, 91);
// Get number of items
UINT32 temp;
LOADDATA(&temp, pBuffer, 4);
pSummary->usNumItems = temp;
pSummary->uiNumItemsPosition = pBuffer - pBufferHead - 4;
// Skip the contents of the world items
WORLDITEM dummyItem;
for(i=0; i<(INT32)pSummary->usNumItems; i++)
dummyItem.Load(&pBuffer, dMajorMapVersion, ubMinorMapVersion);
}
if(uiFlags & MAP_AMBIENTLIGHTLEVEL_SAVED)
pBuffer += 3;
if(uiFlags & MAP_WORLDLIGHTS_SAVED)
{
RenderProgressBar(0, 92);
// Skip number of light palette entries
UINT8 ubTemp;
LOADDATA(&ubTemp, pBuffer, sizeof(UINT8));
pBuffer += sizeof(SGPPaletteEntry) * ubTemp;
// Get number of lights
UINT16 usNumLights;
LOADDATA(&usNumLights, pBuffer, sizeof(UINT16));
pSummary->usNumLights = usNumLights;
// Skip the light loading
for(cnt=0; cnt<(INT32)pSummary->usNumLights; cnt++)
{
UINT8 ubStrLen;
pBuffer += sizeof(LIGHT_SPRITE);
LOADDATA(&ubStrLen, pBuffer, sizeof(UINT8));
if(ubStrLen)
pBuffer += ubStrLen;
}
}
// Read Map Information
pSummary->MapInfo.Load(&pBuffer, dMajorMapVersion);
if(pSummary->MapInfo.ubMapVersion != ubMinorMapVersion)//dnl ch74 241013 stupid fix because MapInfo is incorrectly saved in all previous mapeditor if you edit existing map
pSummary->MapInfo.ubMapVersion = ubMinorMapVersion;
if(uiFlags & MAP_FULLSOLDIER_SAVED)
{
RenderProgressBar(0, 94);
BASIC_SOLDIERCREATE_STRUCT basic;
SOLDIERCREATE_STRUCT priority;
TEAMSUMMARY *pTeam = NULL;
pSummary->uiEnemyPlacementPosition = pBuffer - pBufferHead;
for(i=0; i<pSummary->MapInfo.ubNumIndividuals ; i++)
{
basic.Load(&pBuffer, dMajorMapVersion);
switch(basic.bTeam)
{
case ENEMY_TEAM:
pTeam = &pSummary->EnemyTeam;
break;
case CREATURE_TEAM:
pTeam = &pSummary->CreatureTeam;
break;
case MILITIA_TEAM:
pTeam = &pSummary->RebelTeam;
break;
case CIV_TEAM:
pTeam = &pSummary->CivTeam;
break;
}
if(basic.bOrders == RNDPTPATROL || basic.bOrders == POINTPATROL)
{
//make sure the placement has at least one waypoint.
if(!basic.bPatrolCnt)
pSummary->ubEnemiesReqWaypoints++;
}
else if(basic.bPatrolCnt)
pSummary->ubEnemiesHaveWaypoints++;
if(basic.fPriorityExistance)
pTeam->ubExistance++;
switch(basic.bRelativeAttributeLevel)
{
case 0:
pTeam->ubBadA++;
break;
case 1:
pTeam->ubPoorA++;
break;
case 2:
pTeam->ubAvgA++;
break;
case 3:
pTeam->ubGoodA++;
break;
case 4:
pTeam->ubGreatA++;
break;
}
switch(basic.bRelativeEquipmentLevel)
{
case 0:
pTeam->ubBadE++;
break;
case 1:
pTeam->ubPoorE++;
break;
case 2:
pTeam->ubAvgE++;
break;
case 3:
pTeam->ubGoodE++;
break;
case 4:
pTeam->ubGreatE++;
break;
}
if(basic.fDetailedPlacement)
{
// Skip static priority placement, Clean up inventory handling
priority.Load(&pBuffer, dMajorMapVersion, ubMinorMapVersion);
if(priority.ubProfile != NO_PROFILE)
pTeam->ubProfile++;
else
pTeam->ubDetailed++;
if(basic.bTeam == CIV_TEAM)
{
if(priority.ubScheduleID)
pSummary->ubCivSchedules++;
if(priority.ubBodyType == COW)
pSummary->ubCivCows++;
else if(priority.ubBodyType == BLOODCAT)
pSummary->ubCivBloodcats++;
}
}
if(basic.bTeam == ENEMY_TEAM)
{
switch(basic.ubSoldierClass)
{
case SOLDIER_CLASS_ADMINISTRATOR:
pSummary->ubNumAdmins++;
if(basic.fPriorityExistance)
pSummary->ubAdminExistance++;
if(basic.fDetailedPlacement)
{
if(priority.ubProfile != NO_PROFILE)
pSummary->ubAdminProfile++;
else
pSummary->ubAdminDetailed++;
}
break;
case SOLDIER_CLASS_ELITE:
pSummary->ubNumElites++;
if(basic.fPriorityExistance)
pSummary->ubEliteExistance++;
if(basic.fDetailedPlacement)
{
if(priority.ubProfile != NO_PROFILE)
pSummary->ubEliteProfile++;
else
pSummary->ubEliteDetailed++;
}
break;
case SOLDIER_CLASS_ARMY:
pSummary->ubNumTroops++;
if(basic.fPriorityExistance)
pSummary->ubTroopExistance++;
if(basic.fDetailedPlacement)
{
if(priority.ubProfile != NO_PROFILE)
pSummary->ubTroopProfile++;
else
pSummary->ubTroopDetailed++;
}
break;
}
}
else if(basic.bTeam == CREATURE_TEAM)
{
if(basic.ubBodyType == BLOODCAT)
pTeam->ubNumAnimals++;
}
pTeam->ubTotal++;
}
RenderProgressBar(0, 96);
}
if(uiFlags & MAP_EXITGRIDS_SAVED)
{
RenderProgressBar(0, 98);
BOOLEAN fExitGridFound;
UINT16 usNumExitGrids;
UINT32 usMapIndex;
EXITGRID ExitGrid;
LOADDATA(&usNumExitGrids, pBuffer, sizeof(usNumExitGrids));
for(i=0; i<usNumExitGrids; i++)
{
if(dMajorMapVersion < 7.0)
{
UINT16 usOldMapIndex;
LOADDATA(&usOldMapIndex, pBuffer, sizeof(usOldMapIndex));
usMapIndex = usOldMapIndex;
}
else
LOADDATA(&usMapIndex, pBuffer, sizeof(usMapIndex));
ExitGrid.Load(&pBuffer, dMajorMapVersion);
fExitGridFound = FALSE;
for(cnt=0; cnt<pSummary->ubNumExitGridDests; cnt++)
{
if(pSummary->ExitGrid[cnt].usGridNo == ExitGrid.usGridNo && pSummary->ExitGrid[cnt].ubGotoSectorX == ExitGrid.ubGotoSectorX && pSummary->ExitGrid[cnt].ubGotoSectorY == ExitGrid.ubGotoSectorY && pSummary->ExitGrid[cnt].ubGotoSectorZ == ExitGrid.ubGotoSectorZ)
{
// Same destination
pSummary->usExitGridSize[cnt]++;
fExitGridFound = TRUE;
break;
}
}
if(!fExitGridFound)
{
if(cnt >= 4)
pSummary->fTooManyExitGridDests = TRUE;
else
{
pSummary->ubNumExitGridDests++;
pSummary->usExitGridSize[cnt]++;
pSummary->ExitGrid[cnt].usGridNo = ExitGrid.usGridNo;
pSummary->ExitGrid[cnt].ubGotoSectorX = ExitGrid.ubGotoSectorX;
pSummary->ExitGrid[cnt].ubGotoSectorY = ExitGrid.ubGotoSectorY;
pSummary->ExitGrid[cnt].ubGotoSectorZ = ExitGrid.ubGotoSectorZ;
if(pSummary->ExitGrid[cnt].ubGotoSectorX != ExitGrid.ubGotoSectorX || pSummary->ExitGrid[cnt].ubGotoSectorY != ExitGrid.ubGotoSectorY)
pSummary->fInvalidDest[cnt] = TRUE;
}
}
}
}
if(uiFlags & MAP_DOORTABLE_SAVED)
{
DOOR Door;
UINT8 ubNumDoors;
LOADDATA(&ubNumDoors, pBuffer, sizeof(gubNumDoors));
pSummary->ubNumDoors = ubNumDoors;
for(cnt=0; cnt<pSummary->ubNumDoors; cnt++)
{
Door.Load(&pBuffer, dMajorMapVersion);
if(Door.ubTrapID && Door.ubLockID)
pSummary->ubNumDoorsLockedAndTrapped++;
else if(Door.ubLockID)
pSummary->ubNumDoorsLocked++;
else if(Door.ubTrapID)
pSummary->ubNumDoorsTrapped++;
}
}
RenderProgressBar(0, 100);
MemFree(pBufferHead);
MemFree(bCounts);
WriteSectorSummaryUpdate(szFilename, ubLevel, pSummary);
WORLD_ROWS = iCurRowSize;
WORLD_COLS = iCurColSize;
return(TRUE);
}
#endif
extern UINT8 GetCurrentSummaryVersion();
extern void LoadShadeTablesFromTextFile();
BOOLEAN LoadWorld(const STR8 puiFilename, FLOAT* pMajorMapVersion, UINT8* pMinorMapVersion)//dnl ch44 290909
{
HWFILE hfile;
FLOAT dMajorMapVersion;
UINT32 uiFlags;
UINT32 uiBytesRead;
UINT32 uiSoldierSize;
UINT32 uiFileSize;
#ifdef JA2TESTVERSION
UINT32 uiStartTime;
UINT32 uiLoadWorldStartTime;
#endif
INT32 cnt, cnt2;
INT32 iTilesetID;
UINT16 usTileIndex;
UINT16 usTypeSubIndex;
UINT8 ubType;
UINT8 ubSubIndex;
CHAR8 aFilename[2*FILENAME_BUFLEN];//dnl ch81 021213
UINT8 ubCombine;
UINT8 (*bCounts)[8] = NULL;
INT8 *pBuffer;
INT8 *pBufferHead;
BOOLEAN fGenerateEdgePoints = FALSE;
UINT8 ubMinorMapVersion;
INT32 i;
#ifdef JA2TESTVERSION
uiLoadWorldStartTime = GetJA2Clock();
#endif
LoadShadeTablesFromTextFile();
// Append exension to filename!
if(gfForceLoad)
sprintf(aFilename, "MAPS\\%s", gzForceLoadFile);
else
sprintf(aFilename, "MAPS\\%s", puiFilename);
// Open file
#ifdef JA2EDITOR
if(guiCurrentScreen == LOADSAVE_SCREEN)
hfile = FileOpen(aFilename, FILE_ACCESS_READ, FALSE, gzProfileName);
else
hfile = FileOpen(aFilename, FILE_ACCESS_READ);
#else
hfile = FileOpen(aFilename, FILE_ACCESS_READ);
#endif
if(!hfile)
{
#ifndef JA2EDITOR
SET_ERROR("Could not load map file %S", aFilename);
#endif
return(FALSE);
}
// Get the file size and alloc one huge buffer for it. We will use this buffer to transfer all of the data from.
uiFileSize = FileGetSize(hfile);
pBuffer = (INT8*)MemAlloc(uiFileSize);
pBufferHead = pBuffer;
FileRead(hfile, pBuffer, uiFileSize, &uiBytesRead);
FileClose(hfile);
// RESET FLAGS FOR OUTDOORS/INDOORS
gfBasement = FALSE;
gfCaves = FALSE;
// Flugente: select loadscreen hint
if(!gfEditMode)//dnl ch74 211013
SetNewLoadScreenHint();
SetRelativeStartAndEndPercentage(0, 0, 1, L"Trashing world...");
#ifdef JA2TESTVERSION
uiStartTime = GetJA2Clock();
#endif
TrashWorld();
#ifdef JA2TESTVERSION
uiTrashWorldTime = GetJA2Clock() - uiStartTime;
#endif
LightReset();
// Read JA2 Version ID
LOADDATA(&dMajorMapVersion, pBuffer, sizeof(FLOAT));
LOADDATA(&ubMinorMapVersion, pBuffer, sizeof(UINT8));
if(pMajorMapVersion && pMinorMapVersion)//dnl ch79 291113
{
*pMajorMapVersion = dMajorMapVersion;
*pMinorMapVersion = ubMinorMapVersion;
}
INT32 iRowSize = OLD_WORLD_ROWS;
INT32 iColSize = OLD_WORLD_COLS;
if(dMajorMapVersion >= 7.00)
{
LOADDATA(&iRowSize, pBuffer, sizeof(INT32));
LOADDATA(&iColSize, pBuffer, sizeof(INT32));
}
// Actual world size of the map we loaded!
INT32 iWorldSize = iRowSize * iColSize;
#ifdef JA2EDITOR
// TODO.MAP: Make a new checkbox "Lock Rows & Cols". If set, load the map like it is now, with the set ROWS and COLS
// If not set, load the map with the original rows and cols
// WANNE: Only resize the map, when the checkbox is set
if(gfResizeMapOnLoading && gMapTrn.SetTrnPar(iRowSize, iColSize, iNewMapWorldRows, iNewMapWorldCols))
{
// We enlarge the map
SetWorldSize(iNewMapWorldRows, iNewMapWorldCols);
// Uncheck "vanilla map saving", because it is not allowed on maps > 160x160
gfVanillaMode = FALSE;//dnl ch74 191013
UnclickEditorButton(OPTIONS_VANILLA_MODE);
// Reset
gfResizeMapOnLoading = FALSE;
}
else
{
// Mapsize has not changed
SetWorldSize(iRowSize, iColSize);
// We still have the "normal" map size AND the map is saved in vanilla format
if ((iRowSize <= OLD_WORLD_ROWS && iColSize <= OLD_WORLD_COLS) && (dMajorMapVersion == VANILLA_MAJOR_MAP_VERSION && ubMinorMapVersion == VANILLA_MINOR_MAP_VERSION))
{
// Check "vanilla map saving"
gfVanillaMode = TRUE;//dnl ch74 191013
ClickEditorButton(OPTIONS_VANILLA_MODE);
}
else
{
// Uncheck "vanilla map saving"
gfVanillaMode = FALSE;//dnl ch74 191013
UnclickEditorButton(OPTIONS_VANILLA_MODE);
}
}
// Always reset to unchecked!
UnclickEditorButton(OPTIONS_RESIZE_MAP_ON_LOADING);
#else
SetWorldSize(iRowSize, iColSize);
#endif
bCounts = (UINT8(*)[8])MemAlloc(WORLD_MAX*8);
memset(bCounts, 0, sizeof(UINT8)*WORLD_MAX*8);
// Read FLAGS FOR WORLD
LOADDATA(&uiFlags, pBuffer, sizeof(INT32));
LOADDATA(&iTilesetID, pBuffer, sizeof(INT32));
#ifdef JA2TESTVERSION
uiStartTime = GetJA2Clock();
#endif
Assert(LoadMapTileset(iTilesetID));
#ifdef JA2TESTVERSION
uiLoadMapTilesetTime = GetJA2Clock() - uiStartTime;
#endif
// Load soldier size
LOADDATA(&uiSoldierSize, pBuffer, sizeof(INT32));
// Set land index
for(cnt=0; cnt<WORLD_MAX; cnt++)
{
if(!gMapTrn.IsTrn())
break;
if(GetTerrainType(cnt) == NO_TERRAIN)
AddLandToHead(cnt, (UINT16)(rand()%10));
}
// Read height values
for(i=0; i<iWorldSize; i++)
{
gMapTrn.GetTrnCnt(cnt=i);
LOADDATA(&gpWorldLevelData[cnt].sHeight, pBuffer, sizeof(INT16));
// Remove all land from position where old map will be loaded
if(gMapTrn.IsTrn())
RemoveAllLandsOfTypeRange(cnt, FIRSTTEXTURE, DEEPWATERTEXTURE);
}
SetRelativeStartAndEndPercentage(0, 35, 40, L"Counting layers...");
RenderProgressBar(0, 100);
// Read layer counts
for(i=0; i<iWorldSize; i++)
{
gMapTrn.GetTrnCnt(cnt=i);
// Read combination of land/world flags
LOADDATA(&ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][0] = (UINT8)(ubCombine & 0x0F);
gpWorldLevelData[cnt].uiFlags |= (UINT8)((ubCombine & 0xF0) >> 4);
// Read #objects, structs
LOADDATA( &ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][1] = (UINT8)(ubCombine & 0x0F);
bCounts[cnt][2] = (UINT8)((ubCombine & 0xF0) >> 4);
// Read shadows, roof
LOADDATA( &ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][3] = (UINT8)(ubCombine & 0x0F);
bCounts[cnt][4] = (UINT8)((ubCombine & 0xF0) >> 4);
// Read OnRoof, nothing
LOADDATA(&ubCombine, pBuffer, sizeof(UINT8));
// Split
bCounts[cnt][5] = (UINT8)(ubCombine & 0x0F);
}
SetRelativeStartAndEndPercentage(0, 40, 43, L"Loading land layers...");
RenderProgressBar(0, 100);
for(i=0; i<iWorldSize; i++)
{
gMapTrn.GetTrnCnt(cnt=i);
// Read new values
for(cnt2=0; cnt2<bCounts[cnt][0]; cnt2++)
{
LOADDATA(&ubType, pBuffer, sizeof(UINT8));
LOADDATA(&ubSubIndex, pBuffer, sizeof(UINT8));
// Get tile index
GetTileIndexFromTypeSubIndex(ubType, ubSubIndex, &usTileIndex);
// Add layer
AddLandToHead(cnt, usTileIndex);
}
}
SetRelativeStartAndEndPercentage(0, 43, 46, L"Loading object layer...");
RenderProgressBar(0, 100);
// New load require UINT16 for the type subindex due to the fact that ROADPIECES contain over 300 type subindices.
for(i=0; i<iWorldSize; i++)
{
gMapTrn.GetTrnCnt(cnt=i);
// Set objects
for(cnt2=0; cnt2<bCounts[cnt][1]; cnt2++)
{
LOADDATA(&ubType, pBuffer, sizeof(UINT8));
LOADDATA(&usTypeSubIndex, pBuffer, sizeof(UINT16));
if(ubType >= FIRSTPOINTERS)
continue;
// Get tile index
GetTileIndexFromTypeSubIndex(ubType, usTypeSubIndex, &usTileIndex);
// Add layer
AddObjectToTail(cnt, usTileIndex);
}
}
SetRelativeStartAndEndPercentage(0, 46, 49, L"Loading struct layer...");
RenderProgressBar(0, 100);
for(i=0; i<iWorldSize; i++)
{
gMapTrn.GetTrnCnt(cnt=i);
// Set structs
for(cnt2=0; cnt2<bCounts[cnt][2]; cnt2++)
{
LOADDATA(&ubType, pBuffer, sizeof(UINT8));
LOADDATA(&ubSubIndex, pBuffer, sizeof(UINT8));
// Get tile index
GetTileIndexFromTypeSubIndex(ubType, ubSubIndex, &usTileIndex);
if(ubMinorMapVersion <= 25)
{
// Check patching for phantom menace struct data...
if(gTileDatabase[usTileIndex].uiFlags & UNDERFLOW_FILLER)
GetTileIndexFromTypeSubIndex(ubType, 1, &usTileIndex);
}
// Add layer
AddStructToTail(cnt, usTileIndex);
}
}
SetRelativeStartAndEndPercentage(0, 49, 52, L"Loading shadow layer...");
RenderProgressBar(0, 100);
for(i=0; i<iWorldSize; i++)
{
gMapTrn.GetTrnCnt(cnt=i);
for(cnt2=0; cnt2<bCounts[cnt][3]; cnt2++)
{
LOADDATA(&ubType, pBuffer, sizeof(UINT8));
LOADDATA(&ubSubIndex, pBuffer, sizeof(UINT8));
// Get tile index
GetTileIndexFromTypeSubIndex(ubType, ubSubIndex, &usTileIndex);
// Add layer
AddShadowToTail(cnt, usTileIndex);
}
}
SetRelativeStartAndEndPercentage(0, 52, 55, L"Loading roof layer...");
RenderProgressBar(0, 100);
for(i=0; i<iWorldSize; i++)
{
gMapTrn.GetTrnCnt(cnt=i);
for(cnt2=0; cnt2<bCounts[cnt][4]; cnt2++)
{
LOADDATA(&ubType, pBuffer, sizeof(UINT8));
LOADDATA(&ubSubIndex, pBuffer, sizeof(UINT8));
// Get tile index
GetTileIndexFromTypeSubIndex(ubType, ubSubIndex, &usTileIndex);
// Add layer
AddRoofToTail(cnt, usTileIndex);
}
}
SetRelativeStartAndEndPercentage(0, 55, 58, L"Loading on roof layer...");
RenderProgressBar(0, 100);
for(i=0; i<iWorldSize; i++)
{
gMapTrn.GetTrnCnt(cnt=i);
for(cnt2=0; cnt2<bCounts[cnt][5]; cnt2++)
{
LOADDATA(&ubType, pBuffer, sizeof(UINT8));
LOADDATA(&ubSubIndex, pBuffer, sizeof(UINT8));
// Get tile index
GetTileIndexFromTypeSubIndex(ubType, ubSubIndex, &usTileIndex);
// Add layer
AddOnRoofToTail(cnt, usTileIndex);
}
}
// For old Russian Maps which have version 6.0
if(dMajorMapVersion == 6.00 && ubMinorMapVersion < 27)
{
UINT32 uiNums[37];
LOADDATA(uiNums, pBuffer, sizeof(INT32)*37);
dMajorMapVersion = 5.00;
}
// For new maps
else if(dMajorMapVersion == 6.00 && ubMinorMapVersion < 27 && MAJOR_MAP_VERSION == 6.00)
{
UINT32 uiNums[37];
LOADDATA(uiNums, pBuffer, sizeof(UINT32)*37);
}
//now the data is discarded and when saved, as 6.27, you won't have this problem!
SetRelativeStartAndEndPercentage(0, 58, 59, L"Loading room information...");
RenderProgressBar(0, 100);
#ifdef JA2EDITOR
gusMaxRoomNumber = 0;
//DBrot: More Rooms
for(i=0; i<iWorldSize; i++)
{
gMapTrn.GetTrnCnt(cnt=i);
// Read room information, 2 byte for new files
if(ubMinorMapVersion < 29){
LOADDATA(&gusWorldRoomInfo[cnt], pBuffer, sizeof(INT8));
}else{
LOADDATA(&gusWorldRoomInfo[cnt], pBuffer, sizeof(UINT16));
}
// Got to set the max room number
if(gusWorldRoomInfo[cnt] > gusMaxRoomNumber)
gusMaxRoomNumber = gusWorldRoomInfo[cnt];
}
if(gusMaxRoomNumber < 65535)
gusMaxRoomNumber++;
#else
for(i=0; i<iWorldSize; i++){
gMapTrn.GetTrnCnt(cnt=i);
// Read room information, 2 byte for new files
if(ubMinorMapVersion < 29){
LOADDATA(&gusWorldRoomInfo[cnt], pBuffer, sizeof(INT8));
}else{
LOADDATA(&gusWorldRoomInfo[cnt], pBuffer, sizeof(UINT16));
}
}
//LOADDATA(gubWorldRoomInfo, pBuffer, sizeof(INT8)*WORLD_MAX);
#endif
memset(gubWorldRoomHidden, TRUE, sizeof(gubWorldRoomHidden));
SetRelativeStartAndEndPercentage(0, 59, 61, L"Loading items...");
RenderProgressBar(0, 100);
if(uiFlags & MAP_WORLDITEMS_SAVED)
{
// Load out item information
gfLoadPitsWithoutArming = TRUE;
LoadWorldItemsFromMap(&pBuffer, dMajorMapVersion, ubMinorMapVersion);
gfLoadPitsWithoutArming = FALSE;
}
SetRelativeStartAndEndPercentage(0, 62, 85, L"Loading lights...");
RenderProgressBar(0, 0);
if(uiFlags & MAP_AMBIENTLIGHTLEVEL_SAVED)
{
//Ambient light levels are only saved in underground levels
LOADDATA(&gfBasement, pBuffer, sizeof(BOOLEAN));
LOADDATA(&gfCaves, pBuffer, sizeof(BOOLEAN));
LOADDATA(&ubAmbientLightLevel, pBuffer, sizeof(UINT8));
}
else
{
//We are above ground.
gfBasement = FALSE;
gfCaves = FALSE;
if(!gfEditMode && guiCurrentScreen != MAPUTILITY_SCREEN)
ubAmbientLightLevel = GetTimeOfDayAmbientLightLevel();
else
ubAmbientLightLevel = 4;
}
#ifdef JA2TESTVERSION
uiStartTime = GetJA2Clock();
#endif
if(uiFlags & MAP_WORLDLIGHTS_SAVED)
LoadMapLights(&pBuffer);
else
{
// Set some default value for lighting
SetDefaultWorldLightingColors();
}
LightSetBaseLevel(ubAmbientLightLevel);
#ifdef JA2TESTVERSION
uiLoadMapLightsTime = GetJA2Clock() - uiStartTime;
#endif
SetRelativeStartAndEndPercentage(0, 85, 86, L"Loading map information...");
RenderProgressBar(0, 0);
LoadMapInformation(&pBuffer, dMajorMapVersion);
// Translation routine for map grid numbers
gMapTrn.GetTrnCnt(gMapInformation.sCenterGridNo);
gMapTrn.GetTrnCnt(gMapInformation.sIsolatedGridNo);
gMapTrn.GetTrnCnt(gMapInformation.sNorthGridNo);
gMapTrn.GetTrnCnt(gMapInformation.sEastGridNo);
gMapTrn.GetTrnCnt(gMapInformation.sWestGridNo);
gMapTrn.GetTrnCnt(gMapInformation.sSouthGridNo);
if(uiFlags & MAP_FULLSOLDIER_SAVED)
{
SetRelativeStartAndEndPercentage(0, 86, 87, L"Loading placements...");
RenderProgressBar(0, 0);
LoadSoldiersFromMap(&pBuffer, dMajorMapVersion, ubMinorMapVersion);
}
if(uiFlags & MAP_EXITGRIDS_SAVED)
{
SetRelativeStartAndEndPercentage(0, 87, 88, L"Loading exit grids...");
RenderProgressBar(0, 0);
LoadExitGrids(&pBuffer, dMajorMapVersion);
}
if(uiFlags & MAP_DOORTABLE_SAVED)
{
SetRelativeStartAndEndPercentage(0, 89, 90, L"Loading door tables...");
RenderProgressBar(0, 0);
LoadDoorTableFromMap(&pBuffer, dMajorMapVersion);
}
if(uiFlags & MAP_EDGEPOINTS_SAVED)
{
SetRelativeStartAndEndPercentage(0, 90, 91, L"Loading edgepoints...");
RenderProgressBar(0, 0);
if(!LoadMapEdgepoints(&pBuffer, dMajorMapVersion))
fGenerateEdgePoints = TRUE;// Only if the map had the older edgepoint system
//dnl ch44 290909 Map Edge points must be recreated they cannot be translated, so trash them.
if(gMapTrn.IsTrn())
{
TrashMapEdgepoints();
fGenerateEdgePoints = TRUE;
}
}
else
fGenerateEdgePoints = TRUE;
if(uiFlags & MAP_NPCSCHEDULES_SAVED)
{
SetRelativeStartAndEndPercentage(0, 91, 92, L"Loading NPC schedules...");
RenderProgressBar(0, 0);
LoadSchedules(&pBuffer, dMajorMapVersion);
}
ValidateAndUpdateMapVersionIfNecessary();
SetRelativeStartAndEndPercentage(0, 93, 94, L"Init Loaded World...");
RenderProgressBar(0, 0);
InitLoadedWorld();
if(fGenerateEdgePoints)
{
SetRelativeStartAndEndPercentage(0, 94, 95, L"Generating map edgepoints...");
RenderProgressBar(0, 0);
CompileWorldMovementCosts();
GenerateMapEdgepoints();
}
RenderProgressBar(0, 20);
SetRelativeStartAndEndPercentage(0, 95, 100, L"General initialization...");
// RESET AI!
InitOpponentKnowledgeSystem();
RenderProgressBar(0, 40);
// Reset some override flags
gfForceLoadPlayers = FALSE;
gfForceLoad = FALSE;
// CHECK IF OUR SELECTED GUY IS GONE!
if(gusSelectedSoldier != NOBODY)
{
if(MercPtrs[gusSelectedSoldier]->bActive == FALSE)
gusSelectedSoldier = NOBODY;
}
AdjustSoldierCreationStartValues();
RenderProgressBar(0, 60);
InvalidateWorldRedundency();
// SAVE FILENAME
strcpy(gzLastLoadedFile, puiFilename);
LoadRadarScreenBitmap(puiFilename);
RenderProgressBar(0, 80);
sprintf(gubFilename, puiFilename);
gfWorldLoaded = TRUE;
#ifdef JA2TESTVERSION
uiLoadWorldTime = GetJA2Clock() - uiLoadWorldStartTime;
#endif
// ATE: Not while updating maps!
if(guiCurrentScreen != MAPUTILITY_SCREEN)
GenerateBuildings();
RenderProgressBar(0, 100);
DequeueAllKeyBoardEvents();
// Remove this rather large chunk of memory from the system now!
MemFree(pBufferHead);
MemFree(bCounts);
return(TRUE);
}
//****************************************************************************************
//
// Deletes everything then re-creates the world with simple ground tiles
//
//****************************************************************************************
BOOLEAN NewWorld( INT32 nMapRows, INT32 nMapCols )
{
UINT16 NewIndex;
INT32 cnt;
gusSelectedSoldier = gusOldSelectedSoldier = NOBODY;
AdjustSoldierCreationStartValues( );
TrashWorld();
//SB
SetWorldSize(nMapRows, nMapCols);
// Create world randomly from tiles
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
// Set land index
NewIndex = (UINT16)(rand( ) % 10);
AddLandToHead( cnt, NewIndex );
}
InitRoomDatabase( );
gfWorldLoaded = TRUE;
return( TRUE );
}
void TrashWorld( void )
{
MAP_ELEMENT *pMapTile;
LEVELNODE *pLandNode;
LEVELNODE *pObjectNode;
LEVELNODE *pStructNode;
LEVELNODE *pShadowNode;
LEVELNODE *pMercNode;
LEVELNODE *pRoofNode;
LEVELNODE *pOnRoofNode;
LEVELNODE *pTopmostNode;
// STRUCTURE *pStructureNode;
INT32 cnt;
SOLDIERTYPE *pSoldier;
if( !gfWorldLoaded )
return;
// REMOVE ALL ITEMS FROM WORLD
TrashWorldItems( );
// Trash the overhead map
TrashOverheadMap( );
//Reset the smoke effects.
ResetSmokeEffects();
//Reset the light effects
ResetLightEffects();
// Set soldiers to not active!
//ATE: FOR NOW, ONLY TRASH FROM NPC UP!!!!
//cnt = gTacticalStatus.Team[ gbPlayerNum ].bLastID + 1;
cnt = 0;
for ( pSoldier = MercPtrs[ cnt ]; cnt < MAX_NUM_SOLDIERS; pSoldier++, cnt++ )
{
if ( pSoldier->bActive )
{
if ( pSoldier->bTeam == gbPlayerNum )
{
// Just delete levelnode
pSoldier->pLevelNode = NULL;
}
else
{
// Delete from world
TacticalRemoveSoldier( (UINT16)cnt );
}
}
}
// Reset attack busy since a militia might have been in the middle of radioing
gTacticalStatus.ubAttackBusyCount = 0;
RemoveCorpses( );
// Remove all ani tiles...
DeleteAniTiles( );
//Kill both soldier init lists.
UseEditorAlternateList();
KillSoldierInitList();
UseEditorOriginalList();
KillSoldierInitList();
//Remove the schedules
DestroyAllSchedules();
#ifdef JA2UB
//Ja25 no meanwhiles
#else
// on trash world sheck if we have to set up the first meanwhile
HandleFirstMeanWhileSetUpWithTrashWorld( );
#endif
// Create world randomly from tiles
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
pMapTile = &gpWorldLevelData[ cnt ];
// Free the memory associated with the map tile link lists
pLandNode = pMapTile->pLandHead;
while ( pLandNode != NULL )
{
pMapTile->pLandHead = pLandNode->pNext;
MemFree( pLandNode );
pLandNode = pMapTile->pLandHead;
}
pObjectNode = pMapTile->pObjectHead;
while ( pObjectNode != NULL )
{
pMapTile->pObjectHead = pObjectNode->pNext;
MemFree( pObjectNode );
pObjectNode = pMapTile->pObjectHead;
}
pStructNode = pMapTile->pStructHead;
while ( pStructNode != NULL )
{
pMapTile->pStructHead = pStructNode->pNext;
MemFree( pStructNode );
pStructNode = pMapTile->pStructHead;
}
pShadowNode = pMapTile->pShadowHead;
while ( pShadowNode != NULL )
{
pMapTile->pShadowHead = pShadowNode->pNext;
MemFree( pShadowNode );
pShadowNode = pMapTile->pShadowHead;
}
pMercNode = pMapTile->pMercHead;
while ( pMercNode != NULL )
{
pMapTile->pMercHead = pMercNode->pNext;
MemFree( pMercNode );
pMercNode = pMapTile->pMercHead;
}
pRoofNode = pMapTile->pRoofHead;
while ( pRoofNode != NULL )
{
pMapTile->pRoofHead = pRoofNode->pNext;
MemFree( pRoofNode );
pRoofNode = pMapTile->pRoofHead;
}
pOnRoofNode = pMapTile->pOnRoofHead;
while ( pOnRoofNode != NULL )
{
pMapTile->pOnRoofHead = pOnRoofNode->pNext;
MemFree( pOnRoofNode );
pOnRoofNode = pMapTile->pOnRoofHead;
}
pTopmostNode = pMapTile->pTopmostHead;
while ( pTopmostNode != NULL )
{
pMapTile->pTopmostHead = pTopmostNode->pNext;
MemFree( pTopmostNode );
pTopmostNode = pMapTile->pTopmostHead;
}
while (pMapTile->pStructureHead != NULL)
{
if (DeleteStructureFromWorld( pMapTile->pStructureHead ) == FALSE)
{
// ERROR!!!!!!
break;
}
}
}
// Zero world
memset( gpWorldLevelData, 0, WORLD_MAX * sizeof( MAP_ELEMENT ) );
// Set some default flags
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
gpWorldLevelData[ cnt ].uiFlags |= MAPELEMENT_RECALCULATE_WIREFRAMES;
}
TrashDoorTable();
TrashMapEdgepoints();
TrashDoorStatusArray();
TrashExitGridTable();//dnl ch86 170214
//gfBlitBattleSectorLocator = FALSE;
gfWorldLoaded = FALSE;
sprintf( gubFilename, "none" );
}
void TrashMapTile(INT16 MapTile)
{
MAP_ELEMENT *pMapTile;
LEVELNODE *pLandNode;
LEVELNODE *pObjectNode;
LEVELNODE *pStructNode;
LEVELNODE *pShadowNode;
LEVELNODE *pMercNode;
LEVELNODE *pRoofNode;
LEVELNODE *pOnRoofNode;
LEVELNODE *pTopmostNode;
pMapTile = &gpWorldLevelData[ MapTile ];
// Free the memory associated with the map tile link lists
pLandNode = pMapTile->pLandHead;
while ( pLandNode != NULL )
{
pMapTile->pLandHead = pLandNode->pNext;
MemFree( pLandNode );
pLandNode = pMapTile->pLandHead;
}
pMapTile->pLandHead = pMapTile->pLandStart = NULL;
pObjectNode = pMapTile->pObjectHead;
while ( pObjectNode != NULL )
{
pMapTile->pObjectHead = pObjectNode->pNext;
MemFree( pObjectNode );
pObjectNode = pMapTile->pObjectHead;
}
pMapTile->pObjectHead = NULL;
pStructNode = pMapTile->pStructHead;
while ( pStructNode != NULL )
{
pMapTile->pStructHead = pStructNode->pNext;
MemFree( pStructNode );
pStructNode = pMapTile->pStructHead;
}
pMapTile->pStructHead = NULL;
pShadowNode = pMapTile->pShadowHead;
while ( pShadowNode != NULL )
{
pMapTile->pShadowHead = pShadowNode->pNext;
MemFree( pShadowNode );
pShadowNode = pMapTile->pShadowHead;
}
pMapTile->pShadowHead = NULL;
pMercNode = pMapTile->pMercHead;
while ( pMercNode != NULL )
{
pMapTile->pMercHead = pMercNode->pNext;
MemFree( pMercNode );
pMercNode = pMapTile->pMercHead;
}
pMapTile->pMercHead = NULL;
pRoofNode = pMapTile->pRoofHead;
while ( pRoofNode != NULL )
{
pMapTile->pRoofHead = pRoofNode->pNext;
MemFree( pRoofNode );
pRoofNode = pMapTile->pRoofHead;
}
pMapTile->pRoofHead = NULL;
pOnRoofNode = pMapTile->pOnRoofHead;
while ( pOnRoofNode != NULL )
{
pMapTile->pOnRoofHead = pOnRoofNode->pNext;
MemFree( pOnRoofNode );
pOnRoofNode = pMapTile->pOnRoofHead;
}
pMapTile->pOnRoofHead = NULL;
pTopmostNode = pMapTile->pTopmostHead;
while ( pTopmostNode != NULL )
{
pMapTile->pTopmostHead = pTopmostNode->pNext;
MemFree( pTopmostNode );
pTopmostNode = pMapTile->pTopmostHead;
}
pMapTile->pTopmostHead = NULL;
while (pMapTile->pStructureHead != NULL)
{
DeleteStructureFromWorld( pMapTile->pStructureHead );
}
pMapTile->pStructureHead = pMapTile->pStructureTail = NULL;
}
BOOLEAN LoadMapTileset( INT32 iTilesetID )
{
#ifdef JA2UBMAPS
giOldTilesetUsed = giCurrentTilesetID;
#endif
if ( iTilesetID >= gubNumSets )
{
return( FALSE );
}
// Init tile surface used values
memset( gbNewTileSurfaceLoaded, 0, sizeof( gbNewTileSurfaceLoaded ) );
if( iTilesetID == giCurrentTilesetID )
{
return( TRUE );
}
// Get free memory value nere
gSurfaceMemUsage = guiMemTotal;
// LOAD SURFACES
CHECKF( LoadTileSurfaces( &(gTilesets[ iTilesetID ].TileSurfaceFilenames[0] ), (UINT8)iTilesetID ) != FALSE );
// SET TERRAIN COSTS
if ( gTilesets[ iTilesetID ].MovementCostFnc != NULL )
{
gTilesets[ iTilesetID ].MovementCostFnc( );
}
else
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Tileset %d has no callback function for movement costs. Using default.", iTilesetID) );
SetTilesetOneTerrainValues( );
}
// RESET TILE DATABASE
DeallocateTileDatabase( );
CreateTileDatabase( iTilesetID );
// SET GLOBAL ID FOR TILESET ( FOR SAVING! )
giCurrentTilesetID = iTilesetID;
return( TRUE );
}
BOOLEAN SaveMapTileset( INT32 iTilesetID )
{
// FILE *hTSet;
HWFILE hTSet;
char zTilesetName[65];
int cnt;
UINT32 uiBytesWritten;
// Are we trying to save the default tileset?
if ( iTilesetID == 0 )
return( TRUE );
sprintf( zTilesetName, "TSET%04d.SET", iTilesetID );
// Open file
hTSet = FileOpen( zTilesetName, FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
if ( !hTSet )
{
return( FALSE );
}
// Save current tile set in map file.
for ( cnt = 0; cnt < giNumberOfTileTypes; cnt++ )
FileWrite( hTSet, TileSurfaceFilenames[cnt], 65, &uiBytesWritten );
FileClose( hTSet );
return( TRUE );
}
void SetLoadOverrideParams( BOOLEAN fForceLoad, BOOLEAN fForceFile, CHAR8 *zLoadName )
{
gfForceLoadPlayers = fForceLoad;
gfForceLoad = fForceFile;
if ( zLoadName != NULL )
{
strcpy( gzForceLoadFile, zLoadName );
}
}
void AddWireFrame( INT32 sGridNo, UINT16 usIndex, BOOLEAN fForced )
{
LEVELNODE *pTopmost, *pTopmostTail;
pTopmost = gpWorldLevelData[ sGridNo ].pTopmostHead;
while ( pTopmost != NULL )
{
// Check if one of the samer type exists!
if ( pTopmost->usIndex == usIndex )
{
return;
}
pTopmost = pTopmost->pNext;
}
pTopmostTail = AddTopmostToTail( sGridNo, usIndex );
if ( fForced )
{
pTopmostTail->uiFlags |= LEVELNODE_WIREFRAME;
}
}
UINT16 GetWireframeGraphicNumToUseForWall( INT32 sGridNo, STRUCTURE *pStructure )
{
LEVELNODE *pNode = NULL;
UINT8 ubWallOrientation;
UINT16 usValue = 0;
UINT16 usSubIndex;
STRUCTURE *pBaseStructure;
ubWallOrientation = pStructure->ubWallOrientation;
pBaseStructure = FindBaseStructure( pStructure );
if ( pBaseStructure )
{
// Find levelnode...
pNode = gpWorldLevelData[sGridNo].pStructHead;
while( pNode != NULL )
{
if (pNode->pStructureData == pBaseStructure)
{
break;
}
pNode = pNode->pNext;
}
if ( pNode != NULL )
{
// Get Subindex for this wall...
GetSubIndexFromTileIndex( pNode->usIndex, &usSubIndex );
// Check for broken peices...
if ( usSubIndex == 48 || usSubIndex == 52 )
{
return( WIREFRAMES12 );
}
else if ( usSubIndex == 49 || usSubIndex == 53 )
{
return( WIREFRAMES13 );
}
else if ( usSubIndex == 50 || usSubIndex == 54 )
{
return( WIREFRAMES10 );
}
else if ( usSubIndex == 51 || usSubIndex == 55 )
{
return( WIREFRAMES11 );
}
}
}
switch( ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
usValue = WIREFRAMES6;
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
usValue = WIREFRAMES5;
break;
}
return( usValue );
}
void CalculateWorldWireFrameTiles( BOOLEAN fForce )
{
INT32 cnt;
STRUCTURE *pStructure;
INT32 sGridNo;
UINT8 ubWallOrientation;
INT8 bHiddenVal;
INT8 bNumWallsSameGridNo;
INT32 usWireFrameIndex;
// Create world randomly from tiles
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
if ( gpWorldLevelData[ cnt ].uiFlags & MAPELEMENT_RECALCULATE_WIREFRAMES || fForce )
{
if ( cnt == 8377 )
{
int i = 0;
}
// Turn off flag
gpWorldLevelData[ cnt ].uiFlags &= (~MAPELEMENT_RECALCULATE_WIREFRAMES );
// Remove old ones
RemoveWireFrameTiles( cnt );
bNumWallsSameGridNo = 0;
// Check our gridno, if we have a roof over us that has not beenr evealed, no need for a wiereframe
if ( IsRoofVisibleForWireframe( cnt ) && !( gpWorldLevelData[ cnt ].uiFlags & MAPELEMENT_REVEALED ) )
{
continue;
}
pStructure = gpWorldLevelData[ cnt ].pStructureHead;
while ( pStructure != NULL )
{
// Check for doors
if ( pStructure->fFlags & STRUCTURE_ANYDOOR )
{
// ATE: need this additional check here for hidden doors!
if ( pStructure->fFlags & STRUCTURE_OPENABLE )
{
// Does the gridno we are over have a non-visible tile?
// Based on orientation
ubWallOrientation = pStructure->ubWallOrientation;
switch( ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
// Get gridno
sGridNo = NewGridNo( cnt, DirectionInc( SOUTH ) );
if ( IsRoofVisibleForWireframe( sGridNo ) && !( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) )
{
AddWireFrame( cnt, WIREFRAMES4, (BOOLEAN)( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) != 0 ) );
}
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
// Get gridno
sGridNo = NewGridNo( cnt, DirectionInc( EAST ) );
if ( IsRoofVisibleForWireframe( sGridNo ) && !( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) )
{
AddWireFrame( cnt, WIREFRAMES3 , (BOOLEAN)( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) != 0 ) );
}
break;
}
}
}
// Check for windows
else
{
if ( pStructure->fFlags & STRUCTURE_WALLNWINDOW )
{
// Does the gridno we are over have a non-visible tile?
// Based on orientation
ubWallOrientation = pStructure->ubWallOrientation;
switch( ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
// Get gridno
sGridNo = NewGridNo( cnt, DirectionInc( SOUTH ) );
if ( IsRoofVisibleForWireframe( sGridNo ) && !( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) )
{
AddWireFrame( cnt, WIREFRAMES2, (BOOLEAN)( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) != 0 ) );
}
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
// Get gridno
sGridNo = NewGridNo( cnt, DirectionInc( EAST ) );
if ( IsRoofVisibleForWireframe( sGridNo ) && !( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) )
{
AddWireFrame( cnt, WIREFRAMES1, (BOOLEAN)( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) != 0 ) );
}
break;
}
}
// Check for walls
if ( pStructure->fFlags & STRUCTURE_WALLSTUFF )
{
// Does the gridno we are over have a non-visible tile?
// Based on orientation
ubWallOrientation = pStructure->ubWallOrientation;
usWireFrameIndex = GetWireframeGraphicNumToUseForWall( cnt, pStructure );
switch( ubWallOrientation )
{
case OUTSIDE_TOP_LEFT:
case INSIDE_TOP_LEFT:
// Get gridno
sGridNo = NewGridNo( cnt, DirectionInc( SOUTH ) );
if ( IsRoofVisibleForWireframe( sGridNo ) )
{
bNumWallsSameGridNo++;
AddWireFrame( cnt, usWireFrameIndex, (BOOLEAN)( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) != 0 ) );
// Check along our direction to see if we are a corner
sGridNo = NewGridNo( cnt, DirectionInc( WEST ) );
sGridNo = NewGridNo( sGridNo, DirectionInc( SOUTH ) );
bHiddenVal = IsHiddenTileMarkerThere( sGridNo );
// If we do not exist ( -1 ) or are revealed ( 1 )
if ( bHiddenVal == -1 || bHiddenVal == 1 )
{
// Place corner!
AddWireFrame( cnt, WIREFRAMES9, (BOOLEAN)( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) != 0 ) );
}
}
break;
case OUTSIDE_TOP_RIGHT:
case INSIDE_TOP_RIGHT:
// Get gridno
sGridNo = NewGridNo( cnt, DirectionInc( EAST ) );
if ( IsRoofVisibleForWireframe( sGridNo ) )
{
bNumWallsSameGridNo++;
AddWireFrame( cnt, usWireFrameIndex, (BOOLEAN)( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) != 0 ) );
// Check along our direction to see if we are a corner
sGridNo = NewGridNo( cnt, DirectionInc( NORTH ) );
sGridNo = NewGridNo( sGridNo, DirectionInc( EAST ) );
bHiddenVal = IsHiddenTileMarkerThere( sGridNo );
// If we do not exist ( -1 ) or are revealed ( 1 )
if ( bHiddenVal == -1 || bHiddenVal == 1 )
{
// Place corner!
AddWireFrame( cnt, WIREFRAMES8, (BOOLEAN)( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) != 0 ) );
}
}
break;
}
// Check for both walls
if ( bNumWallsSameGridNo == 2 )
{
sGridNo = NewGridNo( cnt, DirectionInc( EAST ) );
sGridNo = NewGridNo( sGridNo, DirectionInc( SOUTH ) );
AddWireFrame( cnt, WIREFRAMES7, (BOOLEAN)( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) != 0 ) );
}
}
}
pStructure = pStructure->pNext;
}
}
}
}
void RemoveWorldWireFrameTiles( )
{
INT32 cnt;
// Create world randomly from tiles
for ( cnt = 0; cnt < WORLD_MAX; cnt++ )
{
RemoveWireFrameTiles( cnt );
}
}
void RemoveWireFrameTiles( INT32 sGridNo )
{
LEVELNODE *pTopmost, *pNewTopmost;
TILE_ELEMENT * pTileElement;
pTopmost = gpWorldLevelData[ sGridNo ].pTopmostHead;
while ( pTopmost != NULL )
{
pNewTopmost = pTopmost->pNext;
if ( pTopmost->usIndex < giNumberOfTiles )
{
pTileElement = &(gTileDatabase[ pTopmost->usIndex ]);
if ( pTileElement->fType == WIREFRAMES )
{
RemoveTopmost( sGridNo, pTopmost->usIndex );
}
}
pTopmost = pNewTopmost;
}
}
INT8 IsHiddenTileMarkerThere( INT32 sGridNo )
{
STRUCTURE * pStructure;
if ( !gfBasement )
{
pStructure = FindStructure( sGridNo, STRUCTURE_ROOF );
if ( pStructure != NULL )
{
//if ( !( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) )
{
return( 2 );
}
// if we are here, a roof exists but has been revealed
return( 1 );
}
}
else
{
//if ( InARoom( sGridNo, &ubRoom ) )
{
//if ( !( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) )
{
return( 2 );
}
return( 1 );
}
}
return( -1 );
}
void ReloadTileset( UINT8 ubID )
{
CHAR8 aFilename[ 255 ];
INT32 iCurrTilesetID = giCurrentTilesetID;
// Set gloabal
giCurrentTilesetID = ubID;
// Save Map
SaveWorld( TEMP_FILE_FOR_TILESET_CHANGE );
//IMPORTANT: If this is not set, the LoadTileset() will assume that
//it is loading the same tileset and ignore it...
giCurrentTilesetID = iCurrTilesetID;
// Load Map with new tileset
LoadWorld( TEMP_FILE_FOR_TILESET_CHANGE );
// Delete file
sprintf( aFilename, "MAPS\\%s", TEMP_FILE_FOR_TILESET_CHANGE );
FileDelete( aFilename );
}
void SaveMapLights( HWFILE hfile )
{
SOLDIERTYPE *pSoldier;
SGPPaletteEntry LColors[3];
UINT8 ubNumColors;
BOOLEAN fSoldierLight;
UINT16 usNumLights = 0;
UINT16 cnt, cnt2;
UINT8 ubStrLen;
UINT32 uiBytesWritten;
ubNumColors = LightGetColors( LColors );
// Save the current light colors!
FileWrite( hfile, &ubNumColors, 1, &uiBytesWritten );
FileWrite( hfile, LColors, sizeof(SGPPaletteEntry)*ubNumColors, &uiBytesWritten );
//count number of non-merc lights.
for( cnt = 0; cnt < MAX_LIGHT_SPRITES; cnt++ )
{
if( LightSprites[ cnt ].uiFlags & LIGHT_SPR_ACTIVE )
{ //found an active light. Check to make sure it doesn't belong to a merc.
fSoldierLight = FALSE;
for ( cnt2 = 0; cnt2 < MAX_NUM_SOLDIERS && !fSoldierLight; cnt2++ )
{
if( GetSoldier( &pSoldier, cnt2 ) )
{
if ( pSoldier->iLight == (INT32)cnt )
fSoldierLight = TRUE;
}
}
if( !fSoldierLight )
usNumLights++;
}
}
//save the number of lights.
FileWrite( hfile, &usNumLights, 2, &uiBytesWritten );
for( cnt = 0; cnt < MAX_LIGHT_SPRITES; cnt++ )
{
if( LightSprites[ cnt ].uiFlags & LIGHT_SPR_ACTIVE )
{ //found an active light. Check to make sure it doesn't belong to a merc.
fSoldierLight = FALSE;
for ( cnt2 = 0; cnt2 < MAX_NUM_SOLDIERS && !fSoldierLight; cnt2++ )
{
if ( GetSoldier( &pSoldier, cnt2 ) )
{
if ( pSoldier->iLight == (INT32)cnt )
fSoldierLight = TRUE;
}
}
if( !fSoldierLight )
{ //save the light
FileWrite( hfile, &LightSprites[ cnt ], sizeof( LIGHT_SPRITE ), &uiBytesWritten );
ubStrLen = strlen( pLightNames[LightSprites[cnt].iTemplate] ) + 1 ;
FileWrite( hfile, &ubStrLen, 1, &uiBytesWritten );
FileWrite( hfile, pLightNames[LightSprites[cnt].iTemplate], ubStrLen, &uiBytesWritten );
}
}
}
}
void LoadMapLights( INT8 **hBuffer )
{
SGPPaletteEntry LColors[3];
UINT8 ubNumColors;
UINT16 usNumLights;
INT32 cnt;
CHAR8 str[30];
UINT8 ubStrLen;
LIGHT_SPRITE TmpLight;
INT32 iLSprite;
UINT32 uiHour;
BOOLEAN fPrimeTime = FALSE, fNightTime = FALSE;
//reset the lighting system, so that any current lights are toasted.
LightReset();
// read in the light colors!
LOADDATA( &ubNumColors, *hBuffer, 1 );
LOADDATA( LColors, *hBuffer, sizeof(SGPPaletteEntry)*ubNumColors );
LOADDATA( &usNumLights, *hBuffer, 2 );
ubNumColors = 1;
// ATE: OK, only regenrate if colors are different.....
//if ( LColors[0].peRed != gpLightColors[0].peRed ||
// LColors[0].peGreen != gpLightColors[0].peGreen ||
// LColors[0].peBlue != gpLightColors[0].peBlue )
{
LightSetColors( LColors, ubNumColors );
}
//Determine which lights are valid for the current time.
if( !gfEditMode )
{
uiHour = GetWorldHour();
if( uiHour >= NIGHT_TIME_LIGHT_START_HOUR || uiHour < NIGHT_TIME_LIGHT_END_HOUR )
{
fNightTime = TRUE;
}
if( uiHour >= PRIME_TIME_LIGHT_START_HOUR )
{
fPrimeTime = TRUE;
}
}
for( cnt = 0; cnt < usNumLights; cnt++ )
{
LOADDATA( &TmpLight, *hBuffer, sizeof( LIGHT_SPRITE ) );
LOADDATA( &ubStrLen, *hBuffer, 1 );
//dnl ch44 280909 LIGHT_SPRITE translation
gMapTrn.GetTrnXY(TmpLight.iOldX, TmpLight.iOldY);
gMapTrn.GetTrnXY(TmpLight.iX, TmpLight.iY);
if( ubStrLen )
{
LOADDATA( str, *hBuffer, ubStrLen );
}
str[ ubStrLen ] = 0;
iLSprite = LightSpriteCreate( str, TmpLight.uiLightType );
//if this fails, then we will ignore the light.
// ATE: Don't add ANY lights of mapscreen util is on
if( iLSprite != -1/* && guiCurrentScreen != MAPUTILITY_SCREEN*/ )//dnl ch79 301113 lights will be reset in map utility screen
{
if( !gfCaves || gfEditMode )
{
if( gfEditMode ||
TmpLight.uiFlags & LIGHT_PRIMETIME && fPrimeTime ||
TmpLight.uiFlags & LIGHT_NIGHTTIME && fNightTime ||
!(TmpLight.uiFlags & (LIGHT_PRIMETIME | LIGHT_NIGHTTIME)) )
{
//power only valid lights.
LightSpritePower( iLSprite, TRUE );
}
}
LightSpritePosition( iLSprite, TmpLight.iX, TmpLight.iY );
if( TmpLight.uiFlags & LIGHT_PRIMETIME )
LightSprites[ iLSprite ].uiFlags |= LIGHT_PRIMETIME;
else if( TmpLight.uiFlags & LIGHT_NIGHTTIME )
LightSprites[ iLSprite ].uiFlags |= LIGHT_NIGHTTIME;
}
}
}
BOOLEAN IsRoofVisibleForWireframe( INT32 sMapPos )
{
STRUCTURE * pStructure;
if ( !gfBasement )
{
pStructure = FindStructure( sMapPos, STRUCTURE_ROOF );
if ( pStructure != NULL )
{
return( TRUE );
}
}
else
{
//if ( InARoom( sMapPos, &ubRoom ) )
{
//if ( !( gpWorldLevelData[ sMapPos ].uiFlags & MAPELEMENT_REVEALED ) )
{
return( TRUE );
}
}
}
return( FALSE );
}
//dnl ch43 260909
void SetWorldSize(INT32 nWorldRows, INT32 nWorldCols)
{
gMapTrn.ResizeTrnCfg(WORLD_ROWS, WORLD_COLS, nWorldRows, nWorldCols);//dnl ch45 011009
INT32 o_WORLD_MAX = WORLD_MAX;
WORLD_ROWS = nWorldRows;
WORLD_COLS = nWorldCols;
ResetScrollOverheadMap();//dnl ch45 031009
CenterScreenAtMapIndex(MAPROWCOLTOPOS(WORLD_ROWS/2, WORLD_COLS/2));//dnl ch54 111009
if(gubGridNoMarkers)
MemFree(gubGridNoMarkers);
gubGridNoMarkers = (UINT8*)MemAlloc(WORLD_MAX);
memset(gubGridNoMarkers, 0, sizeof(UINT8)*WORLD_MAX);
if(gsCoverValue)
MemFree(gsCoverValue);
gsCoverValue = (INT16*)MemAlloc(sizeof(INT16)*WORLD_MAX);
memset(gsCoverValue, 0x7F, sizeof(INT16)*WORLD_MAX);
// Init building structures and variables
if(gubBuildingInfo)
MemFree(gubBuildingInfo);
gubBuildingInfo = (UINT8*)MemAlloc(WORLD_MAX);
memset(gubBuildingInfo, 0, sizeof(UINT8)*WORLD_MAX);
// Init room numbers
//DBrot: More Rooms
if(gusWorldRoomInfo)
MemFree(gusWorldRoomInfo);
gusWorldRoomInfo = (UINT16*)MemAlloc(sizeof(UINT16)*WORLD_MAX);
memset(gusWorldRoomInfo, 0, sizeof(UINT16)*WORLD_MAX);
if(gubWorldMovementCosts)
MemFree(gubWorldMovementCosts);
gubWorldMovementCosts = (UINT8(*)[MAXDIR][2])MemAlloc(WORLD_MAX*MAXDIR*2);
memset(gubWorldMovementCosts, 0, sizeof(UINT8)*WORLD_MAX*MAXDIR*2);
if(gpWorldLevelData != NULL)
MemFree(gpWorldLevelData);
// Initialize world data
gpWorldLevelData = (MAP_ELEMENT*)MemAlloc(sizeof(MAP_ELEMENT)*WORLD_MAX);
// Zero world
memset(gpWorldLevelData, 0, sizeof(MAP_ELEMENT)*WORLD_MAX);
ShutDownPathAI();
InitPathAI();
#ifdef _DEBUG
if(gubFOVDebugInfoInfo)
MemFree(gubFOVDebugInfoInfo);
gubFOVDebugInfoInfo = (UINT8*)MemAlloc(WORLD_MAX);
#endif
dirDelta[0]= -WORLD_COLS;
dirDelta[1]= 1-WORLD_COLS;
dirDelta[3]= 1+WORLD_COLS;
dirDelta[4]= WORLD_ROWS;
dirDelta[5]= WORLD_ROWS-1;
dirDelta[7]= -WORLD_ROWS-1;
DirIncrementer[0] = -WORLD_ROWS;
DirIncrementer[1] = 1-WORLD_ROWS;
DirIncrementer[3] = 1+WORLD_ROWS;
DirIncrementer[4] = WORLD_ROWS;
DirIncrementer[5] = WORLD_ROWS-1;
DirIncrementer[6] = -1;
DirIncrementer[7] = -WORLD_ROWS-1;
gsTempActionGridNo = NOWHERE;
gsOverItemsGridNo = NOWHERE;
gsOutOfRangeGridNo = NOWHERE;
gsUITargetShotGridNo = NOWHERE;
gsUIHandleShowMoveGridLocation = NOWHERE;
gusCurMousePos = 0;
}
//dnl ch44 290909 Translation routine
MAPTRANSLATION gMapTrn;
MAPTRANSLATION::MAPTRANSLATION()
{
fTrn = FALSE;
iTrnFromRows = OLD_WORLD_ROWS;
iTrnFromCols = OLD_WORLD_COLS;
iTrnToRows = OLD_WORLD_ROWS;
iTrnToCols = OLD_WORLD_COLS;
iResizeTrnFromRows = OLD_WORLD_ROWS;
iResizeTrnFromCols = OLD_WORLD_COLS;
iResizeTrnToRows = OLD_WORLD_ROWS;
iResizeTrnToCols = OLD_WORLD_COLS;
}
MAPTRANSLATION::~MAPTRANSLATION()
{
;
}
void MAPTRANSLATION::GetTrnCnt(INT32& cnt)
{
if(!fTrn || cnt < 0)
return;
INT32 y = cnt / iTrnFromCols;
INT32 x = cnt - y * iTrnFromCols;
cnt = (x + (iTrnToCols - iTrnFromCols) / 2) + (y + (iTrnToRows - iTrnFromRows) / 2) * iTrnToCols;
}
void MAPTRANSLATION::GetTrnXY(INT16& x, INT16& y)
{
if(!fTrn || x < 0 || y < 0)
return;
x += (iTrnToCols - iTrnFromCols) / 2;
y += (iTrnToRows - iTrnFromRows) / 2;
}
void MAPTRANSLATION::ResizeTrnCfg(INT32 iFromRows, INT32 iFromCols, INT32 iToRows, INT32 iToCols)
{
iResizeTrnFromRows = iFromRows;
iResizeTrnFromCols = iFromCols;
iResizeTrnToRows = iToRows;
iResizeTrnToCols = iToCols;
}
void MAPTRANSLATION::ResizeTrnCnt(INT32& cnt)
{
INT32 y = cnt / iResizeTrnFromCols;
INT32 x = cnt - y * iResizeTrnFromCols;
cnt = (x * iResizeTrnToCols / iResizeTrnFromCols) + (y * iResizeTrnToRows / iResizeTrnFromRows) * iResizeTrnToCols;
}
BOOLEAN MAPTRANSLATION::SetTrnPar(INT32 iFromRows, INT32 iFromCols, INT32 iToRows, INT32 iToCols)
{
// WANNE: Only enlarging works currently, making the make small does not work
if(iFromRows < iToRows && iFromCols < iToCols)
{
fTrn = TRUE;
iTrnFromRows = iFromRows;
iTrnFromCols = iFromCols;
iTrnToRows = iToRows;
iTrnToCols = iToCols;
}
else
fTrn = FALSE;
return(fTrn);
}