mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- Fix random item problems, add automatic maps conversion, fix some exceptions. Details: - Random items are now converted to proper real item if added through mapeditor as world or merc item. However random item will be permanently deleted after map is loaded if randomitemcoolnessmodificator not met expected game progress conditions rather then remain as random item. - Add command line option -DOMAPSCNV to mapeditor which will automatically create radarmaps and convert all maps to the latest map version, all maps will be written to profile MAPS directory so be sure this folder is empty as any existing maps will be overwritten. - Fix some exceptions for missing GAP files and strange CTD when we pass command line arguments through VS2010. - Fix not opening items selection from merc inventory if we first do left and then right click for item choosing. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6668 3b4a5df2-a311-0410-b5c6-a8a6f20db521
4457 lines
132 KiB
C++
4457 lines
132 KiB
C++
#include "builddefines.h"
|
|
|
|
#ifdef PRECOMPILEDHEADERS
|
|
#include "TileEngine All.h"
|
|
#include "PreBattle Interface.h"
|
|
#else
|
|
#include "worlddef.h"
|
|
#include "worlddat.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "wcheck.h"
|
|
#include "stdlib.h"
|
|
#include "time.h"
|
|
#include "video.h"
|
|
#include "debug.h"
|
|
#include "worldman.h"
|
|
#include "mousesystem.h"
|
|
#include "sys globals.h"
|
|
#include "screenids.h"
|
|
#include "Render Fun.h"
|
|
#include "font control.h"
|
|
#include "lighting.h"
|
|
#include "structure.h"
|
|
#include "vobject.h"
|
|
#include "Soldier Control.h"
|
|
#include "isometric utils.h"
|
|
#include "Interactive Tiles.h"
|
|
#include "utilities.h"
|
|
#include "overhead.h"
|
|
#include "Event Pump.h"
|
|
#include "Handle UI.h"
|
|
#include "opplist.h"
|
|
#include "shading.h"
|
|
#include "Animation Control.h"
|
|
#include "World Items.h"
|
|
#include "renderworld.h"
|
|
#include "Radar Screen.h"
|
|
#include "soldier create.h"
|
|
#include "Soldier Init List.h"
|
|
#include "Exit Grids.h"
|
|
#include "tile surface.h"
|
|
#include "rotting corpses.h"
|
|
#include "Keys.h"
|
|
#include "Map Information.h"
|
|
#include "Exit Grids.h"
|
|
#include "Summary Info.h"
|
|
#include "Animated ProgressBar.h"
|
|
#include "pathai.h"
|
|
#include "EditorBuildings.h"
|
|
#include "FileMan.h"
|
|
#include "Map Edgepoints.h"
|
|
#include "environment.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
|
|
///ddd
|
|
#include "gamesettings.h"
|
|
#include "editscreen.h"
|
|
#include "Button Defines.h"
|
|
#include "Editor Taskbar Utils.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;
|
|
// ðàçìåðû äîëæíû áûòü ïðîèçâåäåíèåì 8
|
|
// 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 äëÿ óáûñòðåíèÿ ïîèñêà îñâåùåííûõ ó÷àñòêîâ â ïàòõàè.
|
|
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) )
|
|
{
|
|
//ðó÷íàÿ ïðîâåðêà íà çàêîëî÷åíûå îêíà ;( {
|
|
//build_13.sti - çàêîëî÷åííûå îêíà íäåêñ:
|
|
|
|
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 );
|
|
|
|
//ýòîò òèï îêîí íå ñîäåðæèòñÿ â 0 òàéëñåòå, ïðîâåðêà íóëåâîãî òàéëñåòà â ýòîì ñëó÷àå íå íóæíà
|
|
if ( _stricmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], "build_13.sti" ) == 0
|
|
//&& ( pNode->usIndex == 814 || pNode->usIndex == 816 || pNode->usIndex == 817 || pNode->usIndex == 823) -çàïðåùàåò òîëüêî â êîíêðåòíîì òàéëñåòå ;( â äðóãîì íå ñðàáîòàåò
|
|
&& (RestrSubIndex == 40 || RestrSubIndex == 41 || RestrSubIndex == 37 || RestrSubIndex == 38
|
|
|| RestrSubIndex == 43 || RestrSubIndex == 44 || RestrSubIndex == 46 || RestrSubIndex == 47) //íîìåðà ôðåéìîâ â ñòèøêå
|
|
|
|
)
|
|
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 < 8; 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 < 8; 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 < 8; 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
|
|
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 );
|
|
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 < 8; ubDirLoop++)
|
|
{
|
|
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 1, TRAVELCOST_FLAT );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ubDirLoop=0; ubDirLoop < 8; ubDirLoop++)
|
|
{
|
|
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 1, TRAVELCOST_OBSTACLE );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ubDirLoop=0; ubDirLoop < 8; 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 < 8; 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 < 8; ubDirLoop++)
|
|
{
|
|
SET_MOVEMENTCOST( usGridNo, ubDirLoop, 1, TRAVELCOST_FLAT );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ubDirLoop=0; ubDirLoop < 8; 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[ 255 ];
|
|
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 );
|
|
}
|
|
#if 0//dnl ch74 191013 from 050611 Scheinworld reported problem with basement levels and similar maps which doesn't need entry points so decide to remove this check completely
|
|
if(gMapInformation.sCenterGridNo == -1 || gMapInformation.ubEditorSmoothingType == SMOOTHING_NORMAL && (gMapInformation.sNorthGridNo == -1 && gMapInformation.sEastGridNo == -1 && gMapInformation.sSouthGridNo == -1 && gMapInformation.sWestGridNo == -1))//dnl ch17 290909
|
|
{
|
|
swprintf(gzErrorCatchString, L"SAVE ABORTED! Center and at least one of (N,S,E,W) entry point should be set.");
|
|
gfErrorCatch = TRUE;
|
|
FileClose(hfile);
|
|
return(FALSE);
|
|
}
|
|
#endif
|
|
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( )
|
|
{
|
|
//if the current sector is not valid, dont init the world
|
|
if( gWorldSectorX == 0 || gWorldSectorY == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 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[FILENAME_BUFLEN];
|
|
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[40];
|
|
swprintf(szFileName, L"%S", pSector);
|
|
if(ValidMapFileName(szFileName))
|
|
strcpy(szFilename, pSector);
|
|
sprintf(szDirFilename, "MAPS\\%s", szFilename);
|
|
hfile = FileOpen(szDirFilename, FILE_ACCESS_READ, FALSE);
|
|
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.bBodyType == COW)
|
|
pSummary->ubCivCows++;
|
|
else if(priority.bBodyType == 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.bBodyType == 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[50];
|
|
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
|
|
hfile = FileOpen(aFilename, FILE_ACCESS_READ, FALSE);
|
|
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 && iRowSize <= 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();
|
|
#if (defined 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();
|
|
|
|
//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( );
|
|
|
|
// 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 )
|
|
{
|
|
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);
|
|
}
|
|
|