mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
3184 lines
95 KiB
C++
3184 lines
95 KiB
C++
#include "Types.h"
|
|
#include "MemMan.h"
|
|
#include "message.h"
|
|
#include "Items.h"
|
|
#include "Handle Items.h"
|
|
#include "StrategicMap.h"
|
|
#include "Tactical Save.h"
|
|
#include <stdio.h>
|
|
#include "Campaign Types.h"
|
|
#include "SaveLoadGame.h"
|
|
#include "WorldDef.h"
|
|
#include "rotting corpses.h"
|
|
#include "OverHead.h"
|
|
#include "Keys.h"
|
|
#include "Soldier Create.h"
|
|
#include "Soldier Profile.h"
|
|
#include "Isometric Utils.h"
|
|
#include "Soldier Add.h"
|
|
#include "Npc.h"
|
|
#include "Ai.h"
|
|
#include "Game Clock.h"
|
|
#include "Animation Control.h"
|
|
#include "Map Information.h"
|
|
#include "SaveLoadMap.h"
|
|
#include "debug.h"
|
|
#include "Random.h"
|
|
#include "quests.h"
|
|
#include "Animated ProgressBar.h"
|
|
#include "Text.h"
|
|
#include "meanwhile.h"
|
|
#include "Enemy Soldier Save.h"
|
|
#include "SmokeEffects.h"
|
|
#include "LightEffects.h"
|
|
#include "PATHAI.H"
|
|
#include "GameVersion.h"
|
|
#include "strategic.h"
|
|
#include "Map Screen Interface Map.h"
|
|
#include "Strategic Status.h"
|
|
#include "Soldier macros.h"
|
|
#include "sgp.h"
|
|
#include "MessageBoxScreen.h"
|
|
#include "screenids.h"
|
|
#include "Queen Command.h"
|
|
#include "Map Screen Interface Map Inventory.h"
|
|
#include "Animation Control.h"
|
|
#include <vfs/Core/vfs.h>
|
|
BOOLEAN gfWasInMeanwhile = FALSE;
|
|
|
|
|
|
//forward declarations of common classes to eliminate includes
|
|
class OBJECTTYPE;
|
|
class SOLDIERTYPE;
|
|
extern WorldItems gAllWorldItems;
|
|
void SaveWorldItemsToTempFiles();
|
|
void LoadWorldItemsFromTempFiles(INT16 sMapX, INT16 sMapY, INT8 bMapZ);
|
|
void ClearAllWorldItems(void);
|
|
bool LoadWorldItemsFromSavedGame(HWFILE hFile, INT16 x, INT16 y, INT8 z);
|
|
bool SaveWorldItemsToSavedGame(HWFILE hFile, INT16 x, INT16 y, INT8 z);
|
|
void PruneWorldItems(void);
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
//
|
|
// Global Defines
|
|
//
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
|
|
//dnl ch46 031009
|
|
// It's used for save info from the NPCQuoteInfo class that can change.
|
|
class TempNPCQuoteInfoSave
|
|
{
|
|
public:
|
|
UINT16 usFlags;
|
|
INT16 sRequiredItem;
|
|
INT32 sRequiredGridNo;
|
|
INT32 usGoToGridNo;
|
|
};
|
|
|
|
#define NPC_TEMP_QUOTE_FILE "Temp\\NpcQuote.tmp"
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
//
|
|
// Global Variables
|
|
//
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
|
|
extern NPCQuoteInfo * gpNPCQuoteInfoArray[NUM_PROFILES];
|
|
|
|
extern UINT32 guiJA2EncryptionSet;
|
|
extern UINT8 gubEncryptionArray1[ BASE_NUMBER_OF_ROTATION_ARRAYS * 3 ][ NEW_ROTATION_ARRAY_SIZE ];
|
|
extern UINT8 gubEncryptionArray2[ BASE_NUMBER_OF_ROTATION_ARRAYS * 3 ][ NEW_ROTATION_ARRAY_SIZE ];
|
|
extern UINT8 gubEncryptionArray3[ BASE_NUMBER_OF_ROTATION_ARRAYS * 3 ][ NEW_ROTATION_ARRAY_SIZE ];
|
|
extern UINT8 gubEncryptionArray4[ BASE_NUMBER_OF_ROTATION_ARRAYS * 3 ][ NEW_ROTATION_ARRAY_SIZE ];
|
|
|
|
INT32 giErrorMessageBox = 0;
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
//
|
|
// Function Prototypes
|
|
//
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
void TempFileLoadErrorMessageReturnCallback( UINT8 ubRetVal );
|
|
|
|
BOOLEAN SaveWorldItemsToTempItemFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, UINT32 uiNumberOfItems, WORLDITEM *pData );
|
|
BOOLEAN RetrieveTempFileFromSavedGame( HWFILE hFile, UINT32 uiType, INT16 sMapX, INT16 sMapY, INT8 bMapZ );
|
|
|
|
BOOLEAN AddTempFileToSavedGame( HWFILE hFile, UINT32 uiType, INT16 sMapX, INT16 sMapY, INT8 bMapZ );
|
|
|
|
|
|
BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, std::vector<ROTTING_CORPSE_DEFINITION> aCorpseDefVector );
|
|
BOOLEAN LoadRottingCorpsesFromTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ );
|
|
|
|
void LoadNPCInformationFromProfileStruct();
|
|
void SaveNPCInformationToProfileStruct( );
|
|
|
|
BOOLEAN DoesTempFileExistsForMap( UINT32 uiType, INT16 sMapX, INT16 sMapY, INT8 bMapZ );
|
|
|
|
|
|
INT16 GetSoldierIDFromAnyMercID(UINT8 ubMercID);
|
|
|
|
|
|
BOOLEAN SetUnderGroundSectorFlag( INT16 sSectorX, INT16 sSectorY, UINT8 ubSectorZ, UINT32 uiFlagToSet );
|
|
BOOLEAN GetUnderGroundSectorFlagStatus( INT16 sSectorX, INT16 sSectorY, UINT8 ubSectorZ, UINT32 uiFlagToCheck );
|
|
|
|
BOOLEAN LoadAndAddWorldItemsFromTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ );
|
|
|
|
BOOLEAN InitTempNpcQuoteInfoForNPCFromTempFile();
|
|
BOOLEAN SaveTempNpcQuoteInfoForNPCToTempFile( UINT8 ubNpcId );
|
|
BOOLEAN LoadTempNpcQuoteInfoForNPCFromTempFile( UINT8 ubNpcId );
|
|
UINT32 GetLastTimePlayerWasInSector();
|
|
UINT32 GetLastTimePlayerWasInSector(INT16 sMapX, INT16 sMapY, INT8 sMapZ); // Flugente: get time for another sector
|
|
void SetLastTimePlayerWasInSector();
|
|
void SetLastTimePlayerWasInSector(INT16 sMapX, INT16 sMapY, INT8 sMapZ); // Flugente: set last time sector was visited
|
|
|
|
|
|
extern void InitLoadedWorld( );
|
|
extern void ReduceAmmoDroppedByNonPlayerSoldiers( SOLDIERTYPE *pSoldier, INT32 iInvSlot );
|
|
|
|
extern void StripEnemyDetailedPlacementsIfSectorWasPlayerLiberated();
|
|
|
|
#ifdef JA2BETAVERSION
|
|
extern BOOLEAN ValidateSoldierInitLinks( UINT8 ubCode );
|
|
#endif
|
|
|
|
|
|
UINT32 UpdateLoadedSectorsItemInventory( INT16 sMapX, INT16 sMapY, INT8 bMapZ, UINT32 uiNumberOfItems );
|
|
|
|
//ppp
|
|
///////////////////////////////////////////////////////////////
|
|
//
|
|
// Functions
|
|
//
|
|
///////////////////////////////////////////////////////////////
|
|
// SaveMapTempFilesToSavedGameFile() Looks for and opens all Map Modification files. It add each mod file to the save game file.
|
|
BOOLEAN SaveMapTempFilesToSavedGameFile( HWFILE hFile )
|
|
{
|
|
UNDERGROUND_SECTORINFO *TempNode = gpUndergroundSectorInfoHead;
|
|
INT16 sMapX;
|
|
INT16 sMapY;
|
|
|
|
// Save all the global world items to temp files
|
|
SaveWorldItemsToTempFiles();
|
|
|
|
//
|
|
//Loop though all the array elements to see if there is a data file to be saved
|
|
//
|
|
|
|
// Lesh: try to fix save/reload havok
|
|
//First look through the above ground sectors
|
|
for( sMapY=1; sMapY<=16; sMapY++ )
|
|
{
|
|
for( sMapX=1; sMapX<=16; sMapX++ )
|
|
{
|
|
//Save the Temp Item Files to the saved game file
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_ITEM_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_ITEM_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
// Save the Rotting Corpse Temp file to the saved game file
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_ROTTING_CORPSE_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Save the Map Modifications Temp file to the saved game file
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//Save the Door Table temp file to the saved game file
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_DOOR_TABLE_TEMP_FILES_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_DOOR_TABLE_TEMP_FILES_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//Save the revealed status temp file to the saved game file
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_REVEALED_STATUS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_REVEALED_STATUS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//Save the door status temp file to the saved game file
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_DOOR_STATUS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_DOOR_STATUS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_CIV_PRESERVED_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_CIV_PRESERVED_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//if any other file is to be saved
|
|
}
|
|
}
|
|
|
|
|
|
//then look throught all the underground sectors
|
|
while( TempNode )
|
|
{
|
|
if( TempNode->uiFlags & SF_ITEM_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_ITEM_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_ROTTING_CORPSE_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
// Save the Map Modifications Temp file to the saved game file
|
|
if( TempNode->uiFlags & SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//Save the door table to the saved game file
|
|
if( TempNode->uiFlags & SF_DOOR_TABLE_TEMP_FILES_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_DOOR_TABLE_TEMP_FILES_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//Save the revealed status temp file to the saved game file
|
|
if( TempNode->uiFlags & SF_REVEALED_STATUS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_REVEALED_STATUS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//Save the door status temp file to the saved game file
|
|
if( TempNode->uiFlags & SF_DOOR_STATUS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_DOOR_STATUS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_CIV_PRESERVED_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_CIV_PRESERVED_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !AddTempFileToSavedGame( hFile, SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//ttt
|
|
|
|
|
|
TempNode = TempNode->next;
|
|
}
|
|
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
extern int gEnemyPreservedTempFileVersion[256];
|
|
extern int gCivPreservedTempFileVersion[256];
|
|
|
|
// LoadMapTempFilesFromSavedGameFile() loads all the temp files from the saved game file and writes them into the temp directory
|
|
BOOLEAN LoadMapTempFilesFromSavedGameFile( HWFILE hFile )
|
|
{
|
|
UNDERGROUND_SECTORINFO *TempNode = gpUndergroundSectorInfoHead;
|
|
UINT32 uiPercentage;
|
|
UINT32 iCounter = 0;
|
|
|
|
// HACK FOR GABBY
|
|
if ( guiCurrentSaveGameVersion < 81 && (gTacticalStatus.uiFlags & LOADING_SAVED_GAME) )
|
|
{
|
|
if ( gMercProfiles[ GABBY ].bMercStatus != MERC_IS_DEAD )
|
|
{
|
|
// turn off alternate flags for the sectors he could be in
|
|
// randomly place him in one of the two possible sectors
|
|
SectorInfo[ SECTOR( 14, MAP_ROW_L ) ].uiFlags &= ~SF_USE_ALTERNATE_MAP;
|
|
SectorInfo[ SECTOR( 8, MAP_ROW_L ) ].uiFlags &= ~SF_USE_ALTERNATE_MAP;
|
|
|
|
if ( Random( 2 ) )
|
|
{
|
|
SectorInfo[ SECTOR( 11, MAP_ROW_H ) ].uiFlags |= SF_USE_ALTERNATE_MAP;
|
|
gMercProfiles[ GABBY ].sSectorX = 11;
|
|
gMercProfiles[ GABBY ].sSectorY = MAP_ROW_H;
|
|
}
|
|
else
|
|
{
|
|
SectorInfo[ SECTOR( 4, MAP_ROW_I ) ].uiFlags |= SF_USE_ALTERNATE_MAP;
|
|
gMercProfiles[ GABBY ].sSectorX = 4;
|
|
gMercProfiles[ GABBY ].sSectorY = MAP_ROW_I;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Preparation for loading item temp files
|
|
ClearAllWorldItems();
|
|
//
|
|
//Loop though all the array elements to see if there is a data file to be loaded
|
|
//
|
|
|
|
//First look through the above ground sectors
|
|
for ( INT16 sMapY = 1; sMapY < MAP_WORLD_Y - 1; ++sMapY )
|
|
{
|
|
for ( INT16 sMapX = 1; sMapX < MAP_WORLD_X - 1; ++sMapX )
|
|
{
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_ITEM_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_ITEM_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
// Load world items from map temp files into global struct
|
|
LoadWorldItemsFromTempFiles(sMapX, sMapY, 0);
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_ROTTING_CORPSE_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_DOOR_TABLE_TEMP_FILES_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_DOOR_TABLE_TEMP_FILES_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//Get the revealed status temp file From the saved game file
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_REVEALED_STATUS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_REVEALED_STATUS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//Get the revealed status temp file From the saved game file
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_DOOR_STATUS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_DOOR_STATUS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
gEnemyPreservedTempFileVersion[SECTOR( sMapX,sMapY)] = guiCurrentSaveGameVersion;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_CIV_PRESERVED_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_CIV_PRESERVED_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
|
|
if ( guiCurrentSaveGameVersion < 78 && (gTacticalStatus.uiFlags & LOADING_SAVED_GAME) )
|
|
{
|
|
CHAR8 pMapName[ 128 ];
|
|
|
|
// KILL IT!!! KILL KIT!!!! IT IS CORRUPTED!!!
|
|
GetMapTempFileName( SF_CIV_PRESERVED_TEMP_FILE_EXISTS, pMapName, sMapX, sMapY, 0 );
|
|
FileDelete( pMapName );
|
|
|
|
// turn off the flag
|
|
SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags &= (~SF_CIV_PRESERVED_TEMP_FILE_EXISTS);
|
|
}
|
|
|
|
gCivPreservedTempFileVersion[SECTOR( sMapX,sMapY)] = guiCurrentSaveGameVersion;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS, sMapX, sMapY, 0 ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//if any other file is to be saved
|
|
|
|
++iCounter;
|
|
|
|
//update the progress bar
|
|
uiPercentage = (iCounter * 100) / (255);
|
|
|
|
RenderProgressBar( 0, uiPercentage );
|
|
}
|
|
}
|
|
|
|
//then look throught all the underground sectors
|
|
while( TempNode )
|
|
{
|
|
if( TempNode->uiFlags & SF_ITEM_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_ITEM_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
|
|
//sync up the temp file data to the sector structure data
|
|
LoadWorldItemsFromTempFiles(TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ);
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_ROTTING_CORPSE_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_DOOR_TABLE_TEMP_FILES_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_DOOR_TABLE_TEMP_FILES_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//Get the revealed status temp file From the saved game file
|
|
if( TempNode->uiFlags & SF_REVEALED_STATUS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_REVEALED_STATUS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
//Get the revealed status temp file From the saved game file
|
|
if( TempNode->uiFlags & SF_DOOR_STATUS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_DOOR_STATUS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_CIV_PRESERVED_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_CIV_PRESERVED_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
|
|
if ( guiCurrentSaveGameVersion < 78 && (gTacticalStatus.uiFlags & LOADING_SAVED_GAME) )
|
|
{
|
|
CHAR8 pMapName[ 128 ];
|
|
|
|
// KILL IT!!! KILL KIT!!!! IT IS CORRUPTED!!!
|
|
GetMapTempFileName( SF_CIV_PRESERVED_TEMP_FILE_EXISTS, pMapName, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ );
|
|
FileDelete( pMapName );
|
|
|
|
// turn off the flag
|
|
TempNode->uiFlags &= (~SF_CIV_PRESERVED_TEMP_FILE_EXISTS);
|
|
}
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( TempNode->uiFlags & SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS )
|
|
{
|
|
if ( !RetrieveTempFileFromSavedGame( hFile, SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS, TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ ) )
|
|
return FALSE;
|
|
}
|
|
|
|
TempNode = TempNode->next;
|
|
}
|
|
//ttt
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
BOOLEAN UpdateENEMYTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
NewWayOfSavingEnemyAndCivliansToTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE, TRUE );
|
|
NewWayOfSavingEnemyAndCivliansToTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, FALSE, TRUE );
|
|
LoadWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, pTotalSectorList );
|
|
int backup = guiCurrentSaveGameVersion;
|
|
guiCurrentSaveGameVersion = SAVE_GAME_VERSION;
|
|
SaveWorldItemsToTempItemFile( sMapX, sMapY, bMapZ, uiTotalNumberOfItems, pTotalSectorList);
|
|
guiCurrentSaveGameVersion = backup;
|
|
}
|
|
|
|
|
|
BOOLEAN UpdateCIVTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
LoadWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, pTotalSectorList );
|
|
int backup = guiCurrentSaveGameVersion;
|
|
guiCurrentSaveGameVersion = SAVE_GAME_VERSION;
|
|
SaveWorldItemsToTempItemFile( sMapX, sMapY, bMapZ, uiTotalNumberOfItems, pTotalSectorList);
|
|
guiCurrentSaveGameVersion = backup;
|
|
return TRUE;
|
|
}
|
|
*/
|
|
|
|
BOOLEAN SaveWorldItemsToTempItemFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, UINT32 uiNumberOfItems, std::vector<WORLDITEM>& pData)
|
|
{
|
|
HWFILE hFile;
|
|
UINT32 uiNumBytesWritten=0;
|
|
CHAR8 zMapName[ 128 ];
|
|
|
|
GetMapTempFileName( SF_ITEM_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
//Open the file for writing, Create it if it doesnt exist
|
|
hFile = FileOpen( zMapName, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening map modification file
|
|
return( FALSE );
|
|
}
|
|
|
|
//Save the size of the ITem table
|
|
FileWrite( hFile, &uiNumberOfItems, sizeof( UINT32 ), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof( UINT32 ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
//if there are items to save..
|
|
for (unsigned int x = 0; x < uiNumberOfItems; ++x)
|
|
{
|
|
//Save the ITem array
|
|
if ( !pData[x].Save(hFile, FALSE) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
FileClose( hFile );
|
|
|
|
SetSectorFlag( sMapX, sMapY, bMapZ, SF_ITEM_TEMP_FILE_EXISTS );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN LoadWorldItemsFromTempItemFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, std::vector<WORLDITEM>& pData )//dnl ch75 271013
|
|
{
|
|
UINT32 uiNumBytesRead=0;
|
|
HWFILE hFile;
|
|
CHAR8 zMapName[ 128 ];
|
|
UINT32 uiNumberOfItems=0;
|
|
|
|
GetMapTempFileName( SF_ITEM_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
|
|
//Check to see if the file exists
|
|
if( !FileExists( zMapName ) )
|
|
{
|
|
//If the file doesnt exists, its no problem.
|
|
return( TRUE );
|
|
}
|
|
|
|
//Open the file for reading
|
|
hFile = FileOpen( zMapName, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening map modification file,
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
// Load the size of the World ITem table
|
|
FileRead( hFile, &uiNumberOfItems, sizeof( UINT32 ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( UINT32 ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
// Load the World ITem table
|
|
for (unsigned int x = 0; x < uiNumberOfItems; ++x)
|
|
{
|
|
if ( !pData[x].Load(hFile) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
FileClose( hFile );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN GetNumberOfWorldItemsFromTempItemFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, UINT32 *pSizeOfData, BOOLEAN fIfEmptyCreate )
|
|
{
|
|
UINT32 uiNumBytesRead=0;
|
|
HWFILE hFile;
|
|
CHAR8 zMapName[ 128 ];
|
|
UINT32 uiNumberOfItems=0;
|
|
|
|
GetMapTempFileName( SF_ITEM_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
|
|
//Check if the file DOESNT exists
|
|
if( !FileExistsNoDB( zMapName ) )
|
|
{
|
|
if( fIfEmptyCreate )
|
|
{
|
|
//ADB: I don't know why we are initing 10 WORLDITEMS then saving them, but that's what the code was.
|
|
WORLDITEM TempWorldItems[ 10 ];
|
|
uiNumberOfItems = 10;
|
|
UINT32 uiNumBytesWritten=0;
|
|
|
|
//If the file doesnt exists, create a file that has an initial amount of Items
|
|
hFile = FileOpen( zMapName, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening item modification file
|
|
return( FALSE );
|
|
}
|
|
|
|
//write the the number of item in the maps item file
|
|
FileWrite( hFile, &uiNumberOfItems, sizeof( UINT32 ), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof( UINT32 ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
//write the the number of item in the maps item file
|
|
for (unsigned int x = 0; x < uiNumberOfItems; ++x)
|
|
{
|
|
if ( !TempWorldItems[x].Save(hFile, FALSE) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
//Close the file
|
|
FileClose( hFile );
|
|
}
|
|
else
|
|
{
|
|
// the file doesnt exist
|
|
*pSizeOfData = 0;
|
|
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
//Open the file for reading, if it exists
|
|
hFile = FileOpen( zMapName, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening map modification file
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
// Load the size of the World ITem table
|
|
FileRead( hFile, &uiNumberOfItems, sizeof( UINT32 ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( UINT32 ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
*pSizeOfData = uiNumberOfItems;
|
|
|
|
FileClose( hFile );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
UINT32 GetNumberOfMovableItems( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
// not underground!
|
|
if ( bMapZ )
|
|
return 0;
|
|
|
|
// open the inventory of the sector we are taking stuff from
|
|
SECTORINFO *pSectorInfo_Target = &(SectorInfo[SECTOR( sMapX, sMapY )]);
|
|
UINT32 uiTotalNumberOfRealItems_Target = 0;
|
|
|
|
// use the new map
|
|
std::vector<WORLDITEM> pWorldItem_Target;
|
|
|
|
if ( (gWorldSectorX == sMapX) && (gWorldSectorY == sMapY) && (gbWorldSectorZ == bMapZ) )
|
|
{
|
|
uiTotalNumberOfRealItems_Target = guiNumWorldItems;
|
|
pWorldItem_Target = gWorldItems;
|
|
}
|
|
else
|
|
{
|
|
const auto ii = FindWorldItemSector(sMapX, sMapY, bMapZ);
|
|
if (ii != -1)
|
|
{
|
|
uiTotalNumberOfRealItems_Target = gAllWorldItems.NumItems[ii];
|
|
pWorldItem_Target = gAllWorldItems.Items[ii];
|
|
}
|
|
else
|
|
{
|
|
uiTotalNumberOfRealItems_Target = 0;
|
|
}
|
|
}
|
|
|
|
|
|
UINT32 validitems = 0;
|
|
for ( UINT32 uiCount = 0; uiCount < uiTotalNumberOfRealItems_Target; ++uiCount ) // ... for all items in the world ...
|
|
{
|
|
if ( pWorldItem_Target[uiCount].fExists ) // ... if item exists ...
|
|
{
|
|
// test wether item is reachable and allowed to be moved by this assignment
|
|
if ( (pWorldItem_Target[uiCount].usFlags & WORLD_ITEM_REACHABLE) && !(pWorldItem_Target[uiCount].usFlags & WORLD_ITEM_MOVE_ASSIGNMENT_IGNORE) && pWorldItem_Target[uiCount].bVisible > 0 )
|
|
{
|
|
OBJECTTYPE* pObj = &(pWorldItem_Target[uiCount].object); // ... get pointer for this item ...
|
|
|
|
if ( pObj != NULL && pObj->exists( ) ) // ... if pointer is not obviously useless ...
|
|
{
|
|
++validitems;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return validitems;
|
|
}
|
|
|
|
BOOLEAN AddWorldItemsToUnLoadedSector(INT16 sMapX, INT16 sMapY, INT8 bMapZ, INT32 sGridNo, UINT32 uiNumberOfItemsToAdd, std::vector<WORLDITEM>& pWorldItem, BOOLEAN fOverWrite)
|
|
{
|
|
UINT32 uiLoop;
|
|
UINT32 uiLastItemPos;
|
|
UINT32 uiNumberOfItems;
|
|
std::vector<WORLDITEM> pWorldItems;//dnl ch75 271013
|
|
if (uiNumberOfItemsToAdd == 0 && fOverWrite == FALSE)
|
|
{
|
|
//Moa: nothing to do, so get out of here!
|
|
return(TRUE);
|
|
}
|
|
|
|
const auto i = FindWorldItemSector(sMapX, sMapY, bMapZ);
|
|
if (i == -1)
|
|
{
|
|
// Can't find world item sector, add it
|
|
uiNumberOfItems = uiNumberOfItemsToAdd;
|
|
pWorldItems.resize(uiNumberOfItems);
|
|
}
|
|
else
|
|
{
|
|
uiNumberOfItems = gAllWorldItems.NumItems[i];
|
|
pWorldItems = gAllWorldItems.Items[i];
|
|
}
|
|
|
|
//if we are to replace the entire file
|
|
if (fOverWrite)
|
|
{
|
|
//first loop through and mark all entries that they dont exists
|
|
for (UINT32 cnt = 0; cnt < uiNumberOfItems; ++cnt)
|
|
pWorldItems[cnt].fExists = FALSE;
|
|
}
|
|
|
|
uiLastItemPos = 0;
|
|
|
|
//loop through all the objects to add
|
|
for (uiLoop = 0; uiLoop < uiNumberOfItemsToAdd; ++uiLoop)
|
|
{
|
|
// Flugente: only add an item if it exists. Otherwise we will happily add items that are supposed to have been deleted
|
|
if (!pWorldItem[uiLoop].fExists)
|
|
continue;
|
|
|
|
//Loop through the array to see if there is a free spot to add an item to it
|
|
for (; uiLastItemPos < uiNumberOfItems; ++uiLastItemPos)
|
|
{
|
|
if (pWorldItems[uiLastItemPos].fExists == FALSE)
|
|
{
|
|
//We have found a free spot, break
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (uiLastItemPos == (uiNumberOfItems))
|
|
{
|
|
const auto neededAmount = uiNumberOfItemsToAdd - uiLoop;
|
|
uiNumberOfItems += neededAmount;
|
|
pWorldItems.resize(uiNumberOfItems);
|
|
}
|
|
|
|
pWorldItems[uiLastItemPos].fExists = TRUE;
|
|
pWorldItems[uiLastItemPos].sGridNo = pWorldItem[uiLoop].sGridNo;
|
|
pWorldItems[uiLastItemPos].ubLevel = pWorldItem[uiLoop].ubLevel;
|
|
pWorldItems[uiLastItemPos].usFlags = pWorldItem[uiLoop].usFlags;
|
|
pWorldItems[uiLastItemPos].bVisible = pWorldItem[uiLoop].bVisible;
|
|
pWorldItems[uiLastItemPos].bRenderZHeightAboveLevel = pWorldItem[uiLoop].bRenderZHeightAboveLevel;
|
|
|
|
//Check
|
|
if (TileIsOutOfBounds(pWorldItem[uiLoop].sGridNo) && !(pWorldItems[uiLastItemPos].usFlags & WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT))
|
|
{
|
|
pWorldItems[uiLastItemPos].usFlags |= WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT;
|
|
|
|
// Display warning.....
|
|
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Error: Trying to add item ( %d: %s ) to invalid gridno in unloaded sector. Please Report.", pWorldItems[uiLoop].object.usItem, ItemNames[pWorldItems[uiLoop].object.usItem]);
|
|
}
|
|
|
|
|
|
pWorldItems[uiLastItemPos].object = pWorldItem[uiLoop].object;
|
|
}
|
|
|
|
UpdateWorldItems(sMapX, sMapY, bMapZ, uiNumberOfItems, pWorldItems);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOLEAN AddItemsToUnLoadedSector(INT16 sMapX, INT16 sMapY, INT8 bMapZ, INT32 sGridNo, UINT32 uiNumberOfItemsToAdd, OBJECTTYPE* pObject, UINT8 ubLevel, UINT16 usFlags, INT8 bRenderZHeightAboveLevel, INT8 bVisible, BOOLEAN fReplaceEntireFile)
|
|
{
|
|
if (uiNumberOfItemsToAdd == 0 && fReplaceEntireFile == FALSE)
|
|
{
|
|
//Moa: nothing to do, so get out of here!
|
|
return(TRUE);
|
|
}
|
|
|
|
std::vector<WORLDITEM> pWorldItems;
|
|
UINT32 uiNumberOfItems = 0;
|
|
UINT32 cnt;
|
|
UINT32 uiLoop1 = 0;
|
|
|
|
const auto i = FindWorldItemSector(sMapX, sMapY, bMapZ);
|
|
if (i == -1)
|
|
{
|
|
// Can't find world item sector, add it
|
|
uiNumberOfItems = uiNumberOfItemsToAdd;
|
|
pWorldItems.resize(uiNumberOfItems);
|
|
}
|
|
else
|
|
{
|
|
uiNumberOfItems = gAllWorldItems.NumItems[i];
|
|
pWorldItems = gAllWorldItems.Items[i];
|
|
}
|
|
|
|
if (fReplaceEntireFile)
|
|
{
|
|
//first loop through and mark all entries that they dont exists
|
|
for (cnt = 0; cnt < uiNumberOfItems; cnt++)
|
|
{
|
|
pWorldItems[cnt].fExists = FALSE;
|
|
}
|
|
}
|
|
|
|
UINT16 uiLastFoundSpot = 0;
|
|
//loop through all the objects to add
|
|
for (uiLoop1 = 0; uiLoop1 < uiNumberOfItemsToAdd; uiLoop1++)
|
|
{
|
|
//Loop through the array to see if there is a free spot to add an item to it
|
|
for (cnt = uiLastFoundSpot; cnt < uiNumberOfItems; cnt++)
|
|
{
|
|
if (pWorldItems[cnt].fExists == FALSE)
|
|
{
|
|
// anv: remember first found free spot to not loop through entire inventory again for next added items
|
|
uiLastFoundSpot = cnt;
|
|
//We have found a free spot, break
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cnt == (uiNumberOfItems))
|
|
{
|
|
const auto neededAmount = uiNumberOfItemsToAdd - uiLoop1;
|
|
uiNumberOfItems += neededAmount;
|
|
pWorldItems.resize(uiNumberOfItems);
|
|
}
|
|
|
|
pWorldItems[cnt].fExists = TRUE;
|
|
pWorldItems[cnt].sGridNo = sGridNo;
|
|
pWorldItems[cnt].ubLevel = ubLevel;
|
|
pWorldItems[cnt].usFlags = usFlags;
|
|
pWorldItems[cnt].bVisible = bVisible;
|
|
pWorldItems[cnt].bRenderZHeightAboveLevel = bRenderZHeightAboveLevel;
|
|
|
|
|
|
//Check
|
|
if (TileIsOutOfBounds(sGridNo) && !(pWorldItems[cnt].usFlags & WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT))
|
|
{
|
|
pWorldItems[cnt].usFlags |= WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT;
|
|
|
|
// Display warning.....
|
|
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Error: Trying to add item ( %d: %s ) to invalid gridno in unloaded sector. Please Report.", pWorldItems[cnt].object.usItem, ItemNames[pWorldItems[cnt].object.usItem]);
|
|
}
|
|
|
|
|
|
pWorldItems[cnt].object = pObject[uiLoop1];
|
|
|
|
if ((*pObject)[uiLoop1]->data.sObjectFlag & TAKEN_BY_MILITIA_TABOO_GREEN)
|
|
{
|
|
(*pObject)[uiLoop1]->data.sObjectFlag &= ~TAKEN_BY_MILITIA_TABOO_GREEN;
|
|
pWorldItems[cnt].usFlags |= WORLD_ITEM_TABOO_FOR_MILITIA_EQ_GREEN;
|
|
}
|
|
if ((*pObject)[uiLoop1]->data.sObjectFlag & TAKEN_BY_MILITIA_TABOO_BLUE)
|
|
{
|
|
(*pObject)[uiLoop1]->data.sObjectFlag &= ~TAKEN_BY_MILITIA_TABOO_BLUE;
|
|
pWorldItems[cnt].usFlags |= WORLD_ITEM_TABOO_FOR_MILITIA_EQ_BLUE;
|
|
}
|
|
}
|
|
|
|
UpdateWorldItems(sMapX, sMapY, bMapZ, uiNumberOfItems, pWorldItems);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
extern BOOLEAN gfInMeanwhile;
|
|
extern BOOLEAN EnableModifiedFileSetCache(BOOLEAN value);
|
|
|
|
BOOLEAN SaveCurrentSectorsInformationToTempItemFile( )
|
|
{
|
|
BOOLEAN fShouldBeInMeanwhile = FALSE;
|
|
if( gfWasInMeanwhile )
|
|
{ //Don't save a temp file for the meanwhile scene map.
|
|
gfWasInMeanwhile = FALSE;
|
|
return TRUE;
|
|
}
|
|
#ifdef JA2UB
|
|
//Ja25v No meanwhiles
|
|
#else
|
|
else if( AreInMeanwhile() )
|
|
{
|
|
gfInMeanwhile = FALSE;
|
|
fShouldBeInMeanwhile = TRUE;
|
|
}
|
|
#endif
|
|
//If we havent been to tactical yet
|
|
if( ( gWorldSectorX == 0 ) && ( gWorldSectorY == 0 ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN cacheResetValue = EnableModifiedFileSetCache(TRUE);
|
|
|
|
//Save the Blood, smell and the revealed status for map elements
|
|
SaveBloodSmellAndRevealedStatesFromMapToTempFile();
|
|
|
|
// sevenfm
|
|
SaveMineFlagFromMapToTempFile();
|
|
|
|
// handle all reachable before save
|
|
HandleAllReachAbleItemsInTheSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
|
UpdateWorldItems(gWorldSectorX, gWorldSectorY, gbWorldSectorZ, guiNumWorldItems, gWorldItems);
|
|
PruneWorldItems();
|
|
|
|
std::vector<ROTTING_CORPSE_DEFINITION> corpsedefvector;
|
|
|
|
//Determine how many rotting corpses there are
|
|
for ( INT32 iCount = 0; iCount < giNumRottingCorpse; ++iCount )
|
|
{
|
|
if ( gRottingCorpse[iCount].fActivated )
|
|
corpsedefvector.push_back( gRottingCorpse[iCount].def );
|
|
}
|
|
|
|
//Save the rotting corpse array to the temp rotting corpse file
|
|
if( !SaveRottingCorpsesToTempCorpseFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, corpsedefvector ) )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in SaveRottingCorpsesToTempCorpseFile()" ) );
|
|
EnableModifiedFileSetCache(cacheResetValue);
|
|
return( FALSE );
|
|
}
|
|
|
|
//save the Doortable array to the temp door map file
|
|
if( !SaveDoorTableToDoorTableTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in SaveDoorTableToDoorTableTempFile()" ) );
|
|
EnableModifiedFileSetCache(cacheResetValue);
|
|
return( FALSE );
|
|
}
|
|
|
|
//save the 'revealed'status of the tiles
|
|
if( !SaveRevealedStatusArrayToRevealedTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in SaveRevealedStatusArrayToRevealedTempFile()" ) );
|
|
EnableModifiedFileSetCache(cacheResetValue);
|
|
return( FALSE );
|
|
}
|
|
|
|
//save the door open status to the saved game file
|
|
if( !SaveDoorStatusArrayToDoorStatusTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in SaveDoorStatusArrayToDoorStatusTempFile()" ) );
|
|
EnableModifiedFileSetCache(cacheResetValue);
|
|
return( FALSE );
|
|
}
|
|
|
|
//Save the enemies to the temp file
|
|
if( !NewWayOfSavingEnemyAndCivliansToTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE, FALSE ) )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in NewWayOfSavingEnemyAndCivliansToTempFile( Enemy, Creature Team )" ) );
|
|
EnableModifiedFileSetCache(cacheResetValue);
|
|
return( FALSE );
|
|
}
|
|
|
|
//Save the civilian info to the temp file
|
|
if( !NewWayOfSavingEnemyAndCivliansToTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, FALSE, FALSE ) )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in NewWayOfSavingEnemyAndCivliansToTempFile( Civ Team )" ) );
|
|
EnableModifiedFileSetCache(cacheResetValue);
|
|
return( FALSE );
|
|
}
|
|
|
|
//Save the smoke effects info to the temp file
|
|
if( !SaveSmokeEffectsToMapTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in SaveSmokeEffectsToMapTempFile" ) );
|
|
EnableModifiedFileSetCache(cacheResetValue);
|
|
return( FALSE );
|
|
}
|
|
|
|
//Save the smoke effects info to the temp file
|
|
if( !SaveLightEffectsToMapTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in SaveLightEffectsToMapTempFile" ) );
|
|
EnableModifiedFileSetCache(cacheResetValue);
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
//ttt
|
|
|
|
//Save any other info here
|
|
|
|
|
|
//Save certain information from the NPC's soldier structure to the Merc structure
|
|
SaveNPCInformationToProfileStruct( );
|
|
|
|
//Save the time the player was last in the sector
|
|
SetLastTimePlayerWasInSector();
|
|
|
|
EnableModifiedFileSetCache(cacheResetValue);
|
|
|
|
#ifdef JA2UB
|
|
//Ja25 no meanwhile
|
|
#else
|
|
if( fShouldBeInMeanwhile )
|
|
{
|
|
gfInMeanwhile = TRUE;
|
|
}
|
|
#endif
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
void HandleAllReachAbleItemsInTheSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ )
|
|
{
|
|
// find out which items in the list are reachable
|
|
UINT32 uiCounter = 0;
|
|
UINT8 ubDir, ubMovementCost;
|
|
BOOLEAN fReachable = FALSE;
|
|
INT32 sGridNo = NOWHERE, sGridNo2 = NOWHERE;
|
|
INT32 sNewLoc;
|
|
|
|
SOLDIERTYPE * pSoldier;
|
|
BOOLEAN fSecondary = FALSE;
|
|
|
|
if ( guiNumWorldItems == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( gMapInformation.sCenterGridNo != -1 )
|
|
{
|
|
sGridNo = gMapInformation.sCenterGridNo;
|
|
}
|
|
else if ( gMapInformation.sNorthGridNo != -1 )
|
|
{
|
|
// use any!
|
|
sGridNo = gMapInformation.sNorthGridNo;
|
|
}
|
|
else if ( gMapInformation.sEastGridNo != -1 )
|
|
{
|
|
// use any!
|
|
sGridNo = gMapInformation.sEastGridNo;
|
|
}
|
|
else if ( gMapInformation.sSouthGridNo != -1 )
|
|
{
|
|
// use any!
|
|
sGridNo = gMapInformation.sSouthGridNo;
|
|
}
|
|
else if ( gMapInformation.sWestGridNo != -1 )
|
|
{
|
|
// use any!
|
|
sGridNo = gMapInformation.sWestGridNo;
|
|
}
|
|
else
|
|
{
|
|
AssertMsg( 0, String( "Map %c%d_b%d does not have any entry points!", 'A' + gWorldSectorY - 1, gWorldSectorX, gbWorldSectorZ ) );
|
|
return;
|
|
}
|
|
|
|
if ( gMapInformation.sIsolatedGridNo != -1 )
|
|
{
|
|
sGridNo2 = gMapInformation.sIsolatedGridNo;
|
|
|
|
for( uiCounter = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; uiCounter <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++uiCounter )
|
|
{
|
|
pSoldier = MercPtrs[ uiCounter ];
|
|
if ( pSoldier && pSoldier->bActive && pSoldier->stats.bLife > 0 && pSoldier->sSectorX == sSectorX && pSoldier->sSectorY == sSectorY && pSoldier->bSectorZ == bSectorZ )
|
|
{
|
|
if ( FindBestPath( pSoldier, sGridNo2, pSoldier->pathing.bLevel, WALKING, NO_COPYROUTE, 0 ) )
|
|
{
|
|
fSecondary = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !fSecondary )
|
|
{
|
|
sGridNo2 = NOWHERE;
|
|
}
|
|
}
|
|
|
|
GlobalItemsReachableTest( sGridNo, sGridNo2 );
|
|
|
|
for( uiCounter = 0; uiCounter < guiNumWorldItems; ++uiCounter )
|
|
{
|
|
// reset reachablity
|
|
fReachable = FALSE;
|
|
|
|
// item doesn't exist, ignore it
|
|
if( gWorldItems[ uiCounter ].fExists == FALSE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// if the item is trapped then flag it as unreachable, period
|
|
if ( gWorldItems[ uiCounter ].object[0]->data.bTrap > 0 )
|
|
{
|
|
fReachable = FALSE;
|
|
}
|
|
else if ( ItemTypeExistsAtLocation( gWorldItems[ uiCounter ].sGridNo, OWNERSHIP, gWorldItems[ uiCounter ].ubLevel, NULL ) )
|
|
{
|
|
fReachable = FALSE;
|
|
}
|
|
else if ( gWorldItems[ uiCounter ].object.usItem == CHALICE )
|
|
{
|
|
fReachable = FALSE;
|
|
}
|
|
else if ( gpWorldLevelData[ gWorldItems[ uiCounter ].sGridNo ].uiFlags & MAPELEMENT_REACHABLE )
|
|
{
|
|
// the gridno itself is reachable so the item is reachable
|
|
fReachable = TRUE;
|
|
}
|
|
else if ( gWorldItems[ uiCounter ].ubLevel > 0 )
|
|
{
|
|
// items on roofs are always reachable
|
|
fReachable = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// check the 4 grids around the item, if any is reachable...then the item is reachable
|
|
for ( ubDir = 0; ubDir < NUM_WORLD_DIRECTIONS; ubDir += 2 )
|
|
{
|
|
sNewLoc = NewGridNo( gWorldItems[ uiCounter ].sGridNo, DirectionInc( ubDir ) );
|
|
if ( sNewLoc != gWorldItems[ uiCounter ].sGridNo )
|
|
{
|
|
// then it's a valid gridno, so test it
|
|
// requires non-wall movement cost from one location to the other!
|
|
if ( gpWorldLevelData[ sNewLoc ].uiFlags & MAPELEMENT_REACHABLE )
|
|
{
|
|
ubMovementCost = gubWorldMovementCosts[ gWorldItems[ uiCounter ].sGridNo ][ gOppositeDirection[ ubDir ] ][ 0 ];
|
|
// if we find a door movement cost, if the door is open the gridno should be accessible itself
|
|
if ( ubMovementCost != TRAVELCOST_DOOR && ubMovementCost != TRAVELCOST_WALL )
|
|
{
|
|
fReachable = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( fReachable )
|
|
{
|
|
gWorldItems[ uiCounter ].usFlags |= WORLD_ITEM_REACHABLE;
|
|
}
|
|
else
|
|
{
|
|
gWorldItems[ uiCounter ].usFlags &= ~( WORLD_ITEM_REACHABLE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN LoadCurrentSectorsInformationFromTempItemsFile()
|
|
{
|
|
BOOLEAN fUsedTempFile = FALSE;
|
|
|
|
//
|
|
// Load in the sectors ITems
|
|
//
|
|
#ifdef JA2UB
|
|
//Ja25v no meanwhiles
|
|
#else
|
|
if( AreInMeanwhile() )
|
|
{ //There will never be a temp file for the meanwhile scene, so return TRUE. However,
|
|
//set a flag to not save it either!
|
|
gfWasInMeanwhile = TRUE;
|
|
|
|
// OK - this is true except for interrotations - we need that item temp file to be
|
|
// processed!
|
|
if ( GetMeanwhileID() == INTERROGATION )
|
|
{
|
|
//We no longer use item temp files during gameplay, so check for the sector in gAllWorldItems
|
|
if (SectorIsInWorldItems(gWorldSectorX, gWorldSectorY, gbWorldSectorZ))
|
|
{
|
|
if (!LoadAndAddWorldItemsFromTempFile(gWorldSectorX, gWorldSectorY, gbWorldSectorZ))
|
|
return(FALSE);
|
|
}
|
|
gfWasInMeanwhile = FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
//if we are in an above ground sector
|
|
|
|
//If there is a map modifications file, load the data from the temp file
|
|
if ( DoesTempFileExistsForMap( SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if ( !LoadAllMapChangesFromMapTempFileAndApplyThem() )
|
|
return( FALSE );
|
|
}
|
|
|
|
//We no longer use item temp files during gameplay, so check for the sector in gAllWorldItems
|
|
if (SectorIsInWorldItems(gWorldSectorX, gWorldSectorY, gbWorldSectorZ))
|
|
{
|
|
if (!LoadAndAddWorldItemsFromTempFile(gWorldSectorX, gWorldSectorY, gbWorldSectorZ))
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
//If there is a rotting corpse temp file, load the data from the temp file
|
|
if( DoesTempFileExistsForMap( SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if( !LoadRottingCorpsesFromTempCorpseFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
return( FALSE );
|
|
}
|
|
|
|
//if there is a door table temp file, load the data from the temp file
|
|
if( DoesTempFileExistsForMap( SF_DOOR_TABLE_TEMP_FILES_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if( !LoadDoorTableFromDoorTableTempFile( ) )
|
|
return( FALSE );
|
|
}
|
|
|
|
//if there is a revealed status temp file, load the data from the temp file
|
|
if( DoesTempFileExistsForMap( SF_REVEALED_STATUS_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if( !LoadRevealedStatusArrayFromRevealedTempFile( ) )
|
|
return( FALSE );
|
|
}
|
|
|
|
//if there is a door status temp file, load the data from the temp file
|
|
if( DoesTempFileExistsForMap( SF_DOOR_STATUS_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if( !LoadDoorStatusArrayFromDoorStatusTempFile( ) )
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
//if the save is an older version, use the old way of loading it up
|
|
if( guiCurrentSaveGameVersion < 57 )
|
|
{
|
|
if( DoesTempFileExistsForMap( SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if( !LoadEnemySoldiersFromTempFile( ) )
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
//else use the new way of loading the enemy and civilian placements
|
|
else
|
|
{
|
|
if( DoesTempFileExistsForMap( SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if( !NewWayOfLoadingEnemySoldiersFromTempFile( ) )
|
|
return( FALSE );
|
|
}
|
|
|
|
if( DoesTempFileExistsForMap( SF_CIV_PRESERVED_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if( !NewWayOfLoadingCiviliansFromTempFile( ) )
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
if( DoesTempFileExistsForMap( SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if( !LoadSmokeEffectsFromMapTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
return( FALSE );
|
|
}
|
|
|
|
if( DoesTempFileExistsForMap( SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
{
|
|
fUsedTempFile = TRUE;
|
|
if( !LoadLightEffectsFromMapTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) )
|
|
return( FALSE );
|
|
}
|
|
|
|
//ttt
|
|
|
|
// Check to see if any npc are in this sector, if so load up some saved data for them
|
|
LoadNPCInformationFromProfileStruct();
|
|
|
|
//if we are loading a saved game
|
|
// if( gTacticalStatus.uiFlags & LOADING_SAVED_GAME )
|
|
{
|
|
//Init the world since we have modified the map
|
|
InitLoadedWorld();
|
|
}
|
|
|
|
|
|
// Get the last time the player was in the sector
|
|
guiTimeCurrentSectorWasLastLoaded = GetLastTimePlayerWasInSector();
|
|
|
|
if( fUsedTempFile )
|
|
{
|
|
// ValidateSoldierInitLinks( 3 );
|
|
}
|
|
|
|
|
|
StripEnemyDetailedPlacementsIfSectorWasPlayerLiberated();
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
void SetLastTimePlayerWasInSector()
|
|
{
|
|
if( !gbWorldSectorZ )
|
|
SectorInfo[ SECTOR( gWorldSectorX,gWorldSectorY) ].uiTimeCurrentSectorWasLastLoaded = GetWorldTotalMin();
|
|
else if( gbWorldSectorZ > 0 )
|
|
{
|
|
UNDERGROUND_SECTORINFO *pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
//loop through and look for the right underground sector
|
|
while( pTempNode )
|
|
{
|
|
if( ( pTempNode->ubSectorX == gWorldSectorX ) &&
|
|
( pTempNode->ubSectorY == gWorldSectorY ) &&
|
|
( pTempNode->ubSectorZ == gbWorldSectorZ ) )
|
|
{
|
|
//set the flag indicating that ther is a temp item file exists for the sector
|
|
pTempNode->uiTimeCurrentSectorWasLastLoaded = GetWorldTotalMin();
|
|
return; //break out
|
|
}
|
|
pTempNode = pTempNode->next;
|
|
}
|
|
#ifdef JA2TESTVERSION
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Failed to Set the 'uiTimeCurrentSectorWasLastLoaded' for an underground sector" );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// Flugente: set last time sector was visited
|
|
void SetLastTimePlayerWasInSector(INT16 sMapX, INT16 sMapY, INT8 sMapZ)
|
|
{
|
|
if( !sMapZ )
|
|
SectorInfo[ SECTOR( sMapX,sMapY) ].uiTimeCurrentSectorWasLastLoaded = GetWorldTotalMin();
|
|
else if( sMapZ > 0 )
|
|
{
|
|
UNDERGROUND_SECTORINFO *pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
//loop through and look for the right underground sector
|
|
while( pTempNode )
|
|
{
|
|
if( ( pTempNode->ubSectorX == sMapX ) &&
|
|
( pTempNode->ubSectorY == sMapY ) &&
|
|
( pTempNode->ubSectorZ == sMapZ ) )
|
|
{
|
|
//set the flag indicating that ther is a temp item file exists for the sector
|
|
pTempNode->uiTimeCurrentSectorWasLastLoaded = GetWorldTotalMin();
|
|
return; //break out
|
|
}
|
|
pTempNode = pTempNode->next;
|
|
}
|
|
#ifdef JA2TESTVERSION
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Failed to Set the 'uiTimeCurrentSectorWasLastLoaded' for an underground sector" );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
UINT32 GetLastTimePlayerWasInSector()
|
|
{
|
|
if( !gbWorldSectorZ )
|
|
return( SectorInfo[ SECTOR( gWorldSectorX,gWorldSectorY) ].uiTimeCurrentSectorWasLastLoaded );
|
|
else if( gbWorldSectorZ > 0 )
|
|
{
|
|
UNDERGROUND_SECTORINFO *pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
//loop through and look for the right underground sector
|
|
while( pTempNode )
|
|
{
|
|
if( ( pTempNode->ubSectorX == gWorldSectorX ) &&
|
|
( pTempNode->ubSectorY == gWorldSectorY ) &&
|
|
( pTempNode->ubSectorZ == gbWorldSectorZ ) )
|
|
{
|
|
//set the flag indicating that ther is a temp item file exists for the sector
|
|
return( pTempNode->uiTimeCurrentSectorWasLastLoaded );
|
|
}
|
|
pTempNode = pTempNode->next;
|
|
}
|
|
|
|
#ifdef JA2TESTVERSION
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Failed to Get the 'uiTimeCurrentSectorWasLastLoaded' from an underground sector" );
|
|
#endif
|
|
|
|
return( 0 );
|
|
}
|
|
return( 0 );
|
|
}
|
|
|
|
// Flugente: get time for another sector
|
|
UINT32 GetLastTimePlayerWasInSector(INT16 sMapX, INT16 sMapY, INT8 sMapZ)
|
|
{
|
|
if( !sMapZ )
|
|
return( SectorInfo[ SECTOR( sMapX,sMapY) ].uiTimeCurrentSectorWasLastLoaded );
|
|
else if( sMapZ > 0 )
|
|
{
|
|
UNDERGROUND_SECTORINFO *pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
//loop through and look for the right underground sector
|
|
while( pTempNode )
|
|
{
|
|
if( ( pTempNode->ubSectorX == sMapX ) &&
|
|
( pTempNode->ubSectorY == sMapY ) &&
|
|
( pTempNode->ubSectorZ == sMapZ ) )
|
|
{
|
|
//set the flag indicating that ther is a temp item file exists for the sector
|
|
return( pTempNode->uiTimeCurrentSectorWasLastLoaded );
|
|
}
|
|
pTempNode = pTempNode->next;
|
|
}
|
|
|
|
#ifdef JA2TESTVERSION
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Failed to Get the 'uiTimeCurrentSectorWasLastLoaded' from an underground sector" );
|
|
#endif
|
|
|
|
return( 0 );
|
|
}
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN LoadAndAddWorldItemsFromTempFile(INT16 sMapX, INT16 sMapY, INT8 bMapZ)
|
|
{
|
|
UINT32 uiNumberOfItems = 0;
|
|
std::vector<WORLDITEM> pWorldItems;
|
|
|
|
//Get the number of items from the file
|
|
const auto i = FindWorldItemSector(sMapX, sMapY, bMapZ);
|
|
if (i == -1)
|
|
{
|
|
//Error getting the numbers of the items from the sector. Create placeholder items.
|
|
//This is what the original code did
|
|
uiNumberOfItems = 10;
|
|
pWorldItems.resize(uiNumberOfItems);
|
|
}
|
|
else
|
|
{
|
|
uiNumberOfItems = gAllWorldItems.NumItems[i];
|
|
pWorldItems= gAllWorldItems.Items[i];
|
|
}
|
|
|
|
if (uiNumberOfItems == 0)
|
|
{
|
|
//if there are no items in the temp, the player might have cleared all of them out, check to see
|
|
//If we have already been to the sector
|
|
if (GetSectorFlagStatus(sMapX, sMapY, bMapZ, SF_ALREADY_LOADED))
|
|
{
|
|
//
|
|
//Completly replace the current sectors item table because all the items SHOULD be in the temp file!!
|
|
//
|
|
|
|
//Destroy the current sectors item table
|
|
TrashWorldItems();
|
|
}
|
|
|
|
//there are no items in the file
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
//If we have already been to the sector
|
|
if (GetSectorFlagStatus(sMapX, sMapY, bMapZ, SF_ALREADY_LOADED))
|
|
{
|
|
//
|
|
//Completly replace the current sectors item table because all the items SHOULD be in the temp file!!
|
|
//
|
|
|
|
//Destroy the current sectors item table
|
|
TrashWorldItems();
|
|
|
|
//Add each item to the pool, handle below, outside of the if
|
|
}
|
|
|
|
//
|
|
//Append the items in the file with to the current sectors item table
|
|
//
|
|
|
|
//Loop through all the items loaded from the file
|
|
INT32 sNewGridNo;
|
|
for (UINT32 cnt = 0; cnt < uiNumberOfItems; cnt++)
|
|
{
|
|
//If the item in the array is valid
|
|
if (pWorldItems[cnt].fExists)
|
|
{
|
|
//Check the flags to see if we have to find a gridno to place the items at
|
|
if (pWorldItems[cnt].usFlags & WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO)
|
|
{
|
|
sNewGridNo = FindNearestAvailableGridNoForItem(pWorldItems[cnt].sGridNo, 5);
|
|
|
|
if (TileIsOutOfBounds(sNewGridNo))
|
|
sNewGridNo = FindNearestAvailableGridNoForItem(pWorldItems[cnt].sGridNo, 15);
|
|
|
|
if (!TileIsOutOfBounds(sNewGridNo))
|
|
{
|
|
pWorldItems[cnt].sGridNo = sNewGridNo;
|
|
}
|
|
}
|
|
|
|
//If the item has an invalid gridno, use the maps entry point
|
|
if (pWorldItems[cnt].usFlags & WORLD_ITEM_GRIDNO_NOT_SET_USE_ENTRY_POINT)
|
|
{
|
|
pWorldItems[cnt].sGridNo = gMapInformation.sCenterGridNo;
|
|
|
|
// if we move the item, recalculate the height
|
|
pWorldItems[cnt].bRenderZHeightAboveLevel = -1;
|
|
}
|
|
|
|
//add the item to the world
|
|
AddItemToPool(pWorldItems[cnt].sGridNo, &pWorldItems[cnt].object, pWorldItems[cnt].bVisible, pWorldItems[cnt].ubLevel, pWorldItems[cnt].usFlags, pWorldItems[cnt].bRenderZHeightAboveLevel, pWorldItems[cnt].soldierID);
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN AddTempFileToSavedGame( HWFILE hFile, UINT32 uiType, INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
CHAR8 zMapName[ 128 ];
|
|
|
|
GetMapTempFileName( uiType, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
//Save the map temp file to the saved game file
|
|
if( !SaveFilesToSavedGame( zMapName, hFile ) )
|
|
return( FALSE );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN RetrieveTempFileFromSavedGame( HWFILE hFile, UINT32 uiType, INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
CHAR8 zMapName[ 128 ];
|
|
|
|
GetMapTempFileName( uiType, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
//Load the map temp file from the saved game file
|
|
if( !LoadFilesFromSavedGame( zMapName, hFile ) )
|
|
return( FALSE );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
//Deletes the Temp map Directory
|
|
BOOLEAN InitTacticalSave( BOOLEAN fCreateTempDir )
|
|
{
|
|
EraseDirectory( MAPS_DIR );
|
|
if( fCreateTempDir )
|
|
{
|
|
//Create the initial temp file for the Npc Quote Info
|
|
InitTempNpcQuoteInfoForNPCFromTempFile();
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, std::vector<ROTTING_CORPSE_DEFINITION> aCorpseDefVector )
|
|
{
|
|
HWFILE hFile;
|
|
UINT32 uiNumBytesWritten=0;
|
|
CHAR8 zMapName[ 128 ];
|
|
|
|
// if we have no corpses at all, we have nothing to write - erase the 'corpse file exists flag', the next time we add a corpse, a new file will be created
|
|
if ( aCorpseDefVector.empty() )
|
|
{
|
|
ReSetSectorFlag( sMapX, sMapY, bMapZ, SF_ROTTING_CORPSE_TEMP_FILE_EXISTS );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GetMapTempFileName( SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
//Open the file for writing, Create it if it doesnt exist
|
|
hFile = FileOpen( zMapName, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening map modification file
|
|
return( FALSE );
|
|
}
|
|
|
|
UINT32 uiNumberOfCorpses = aCorpseDefVector.size();
|
|
|
|
//Save the number of the Rotting Corpses array table
|
|
FileWrite( hFile, &uiNumberOfCorpses, sizeof( UINT32 ), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof( UINT32 ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
//Loop through all the carcases in the array and save the active ones
|
|
for( std::vector<ROTTING_CORPSE_DEFINITION>::iterator it = aCorpseDefVector.begin(); it != aCorpseDefVector.end(); ++it )
|
|
{
|
|
//Save the RottingCorpse info array
|
|
FileWrite( hFile, &(*it), sizeof( ROTTING_CORPSE_DEFINITION ), &uiNumBytesWritten );
|
|
if ( uiNumBytesWritten != sizeof( ROTTING_CORPSE_DEFINITION ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
FileClose( hFile );
|
|
|
|
// Set the flag indicating that there is a rotting corpse Temp File
|
|
SetSectorFlag( sMapX, sMapY, bMapZ, SF_ROTTING_CORPSE_TEMP_FILE_EXISTS );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN DeleteTempItemMapFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
CHAR8 zMapName[ 128 ];
|
|
GetMapTempFileName( SF_ITEM_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
//Check to see if the file exists
|
|
if( !FileExists( zMapName ) )
|
|
{
|
|
//If the file doesnt exists, its no problem.
|
|
return( TRUE );
|
|
}
|
|
FileDelete(zMapName);
|
|
|
|
// the sector info flag being reset
|
|
ReSetSectorFlag( sMapX, sMapY, bMapZ, SF_ITEM_TEMP_FILE_EXISTS );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN LoadRottingCorpsesFromTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
HWFILE hFile;
|
|
UINT32 uiNumBytesRead=0;
|
|
CHAR8 zMapName[ 128 ];
|
|
UINT32 uiNumberOfCorpses=0;
|
|
UINT32 cnt;
|
|
ROTTING_CORPSE_DEFINITION def;
|
|
INT8 bTownId;
|
|
|
|
//Delete the existing rotting corpse array
|
|
RemoveCorpses( );
|
|
|
|
GetMapTempFileName( SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
//Check to see if the file exists
|
|
if( !FileExists( zMapName ) )
|
|
{
|
|
//If the file doesnt exists, its no problem.
|
|
return( TRUE );
|
|
}
|
|
|
|
//Open the file for reading
|
|
hFile = FileOpen( zMapName, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening map modification file,
|
|
return( FALSE );
|
|
}
|
|
|
|
// Load the number of Rotting corpses
|
|
FileRead( hFile, &uiNumberOfCorpses, sizeof( UINT32 ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( UINT32 ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
// WANNE: If we get wrong data (very high value) from the temp file, we assume we have wrong value and therefore set corpses to 0 which will not crash the game!
|
|
if (uiNumberOfCorpses > 10000)
|
|
uiNumberOfCorpses = 0;
|
|
|
|
// Get town ID for use later....
|
|
bTownId = GetTownIdForSector( gWorldSectorX, gWorldSectorY );
|
|
|
|
for( cnt=0; cnt<uiNumberOfCorpses; ++cnt )
|
|
{
|
|
// Load the Rotting corpses info
|
|
FileRead( hFile, &def, sizeof( ROTTING_CORPSE_DEFINITION ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( ROTTING_CORPSE_DEFINITION ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
//Check the flags to see if we have to find a gridno to place the rotting corpses at
|
|
if( def.usFlags & ROTTING_CORPSE_FIND_SWEETSPOT_FROM_GRIDNO )
|
|
{
|
|
def.sGridNo = FindNearestAvailableGridNoForCorpse( &def, 5 );
|
|
|
|
if (TileIsOutOfBounds(def.sGridNo))
|
|
{
|
|
def.sGridNo = FindNearestAvailableGridNoForCorpse(&def, 15);
|
|
if (TileIsOutOfBounds(def.sGridNo))
|
|
{
|
|
//shadooow: if we still have invalid gridno skip adding this corpse, it will crash otherwise
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
else if( def.usFlags & ROTTING_CORPSE_USE_NORTH_ENTRY_POINT )
|
|
{
|
|
def.sGridNo = gMapInformation.sNorthGridNo;
|
|
}
|
|
else if( def.usFlags & ROTTING_CORPSE_USE_SOUTH_ENTRY_POINT )
|
|
{
|
|
def.sGridNo = gMapInformation.sSouthGridNo;
|
|
}
|
|
else if( def.usFlags & ROTTING_CORPSE_USE_EAST_ENTRY_POINT )
|
|
{
|
|
def.sGridNo = gMapInformation.sEastGridNo;
|
|
}
|
|
else if( def.usFlags & ROTTING_CORPSE_USE_WEST_ENTRY_POINT )
|
|
{
|
|
def.sGridNo = gMapInformation.sWestGridNo;
|
|
}
|
|
//Recalculate the dx,dy info
|
|
INT16 sX, sY;
|
|
ConvertGridNoToCenterCellXY(def.sGridNo, &sX, &sY);
|
|
def.dXPos = sX;
|
|
def.dYPos = sY;
|
|
// If not from loading a save....
|
|
if( !(gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
|
|
{
|
|
// ATE: Don't place corpses if
|
|
// a ) in a town and b) indoors
|
|
if ( gbWorldSectorZ == 0 )
|
|
{
|
|
if ( bTownId != BLANK_SECTOR )
|
|
{
|
|
// Are we indoors?
|
|
if( FloorAtGridNo( def.sGridNo ) )
|
|
{
|
|
// OK, finally, check TOC vs game time to see if at least some time has passed
|
|
if ( ( GetWorldTotalMin( ) - def.uiTimeOfDeath ) >= 30 )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//add the rotting corpse info
|
|
if( AddRottingCorpse( &def ) == -1 )
|
|
{
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Failed to add a corpse to GridNo # %d", def.sGridNo ) );
|
|
/*
|
|
Assert( 0 );
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
*/
|
|
}
|
|
}
|
|
|
|
FileClose( hFile );
|
|
|
|
//Check to see if we have to start decomposing the corpses
|
|
HandleRottingCorpses( );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
void SaveNPCInformationToProfileStruct( )
|
|
{
|
|
UINT32 cnt;
|
|
SOLDIERTYPE * pSoldier;
|
|
MERCPROFILESTRUCT * pProfile;
|
|
|
|
//Loop through the active NPC's
|
|
|
|
// Only do this on save now... on traversal this is handled in the strategic code
|
|
if ( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
for ( cnt = 0; cnt < guiNumMercSlots; cnt++)
|
|
{
|
|
pSoldier = MercSlots[ cnt ];
|
|
|
|
//if it is an active NPC
|
|
if ( pSoldier && pSoldier->ubProfile != NO_PROFILE && pSoldier->bTeam == CIV_TEAM )
|
|
{
|
|
//Save Temp Npc Quote Info array
|
|
SaveTempNpcQuoteInfoForNPCToTempFile( pSoldier->ubProfile );
|
|
|
|
pProfile = &(gMercProfiles[ pSoldier->ubProfile ]);
|
|
|
|
pProfile->ubQuoteActionID = pSoldier->ubQuoteActionID;
|
|
pProfile->ubQuoteRecord = pSoldier->ubQuoteRecord;
|
|
|
|
// if the merc is NOT added due to flag set, return
|
|
if ( pProfile->ubMiscFlags2 & PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( pProfile->ubMiscFlags3 & PROFILE_MISC_FLAG3_PERMANENT_INSERTION_CODE )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
pProfile->fUseProfileInsertionInfo = TRUE;
|
|
pProfile->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
|
|
//if ( gTacticalStatus.uiFlags & LOADING_SAVED_GAME )
|
|
//{
|
|
// if we are saving the game, save the NPC's current location
|
|
pProfile->usStrategicInsertionData = pSoldier->sGridNo;
|
|
//}
|
|
/*
|
|
else
|
|
{
|
|
// If the NPC is moving, save the final destination, else save the current location
|
|
if ( pSoldier->pathing.sFinalDestination != pSoldier->sGridNo )
|
|
{
|
|
pProfile->usStrategicInsertionData = pSoldier->pathing.sFinalDestination;
|
|
}
|
|
else
|
|
{
|
|
pProfile->usStrategicInsertionData = pSoldier->sGridNo;
|
|
}
|
|
}
|
|
*/
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void EVENT_SetSoldierPositionAndMaybeFinalDestAndMaybeNotDestination( SOLDIERTYPE *pSoldier, FLOAT dNewXPos, FLOAT dNewYPos, BOOLEAN fUpdateDest, BOOLEAN fUpdateFinalDest );
|
|
|
|
void LoadNPCInformationFromProfileStruct()
|
|
{
|
|
//UINT32 cnt;
|
|
//INT16 sSoldierID;
|
|
//SOLDIERTYPE * pSoldier;
|
|
|
|
// CJC: disabled this Dec 21, 1998 as unnecessary (and messing up quote files for recruited/escorted NPCs
|
|
return;
|
|
/* commented out the disabled code (jonathanl)
|
|
for ( cnt = FIRST_RPC; cnt < NUM_PROFILES; cnt++ )
|
|
{
|
|
if ( gMercProfiles[ cnt ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED )
|
|
{
|
|
// don't load
|
|
continue;
|
|
}
|
|
|
|
sSoldierID = GetSoldierIDFromAnyMercID( (UINT8)cnt );
|
|
|
|
//if the soldier is not loaded, return
|
|
if( sSoldierID == -1 )
|
|
continue;
|
|
|
|
//if we cant get a pointer to the soldier, continue
|
|
if( !GetSoldier( &pSoldier, sSoldierID ) )
|
|
continue;
|
|
|
|
// load quote info if it exists
|
|
if ( gMercProfiles[ cnt ].ubMiscFlags & PROFILE_MISC_FLAG_TEMP_NPC_QUOTE_DATA_EXISTS )
|
|
{
|
|
LoadTempNpcQuoteInfoForNPCFromTempFile( (UINT8)cnt );
|
|
}
|
|
|
|
// load insertion info
|
|
//if ( gMercProfiles[ cnt ] )
|
|
//{
|
|
// pSoldier->ubInsertionCode = pProfile->ubStrategicInsertionCode;
|
|
// pSoldier->usInsertionData = pProfile->usStrategicInsertionData;
|
|
//}
|
|
|
|
}
|
|
*/
|
|
|
|
/*
|
|
INT16 sX, sY;
|
|
UINT16 cnt;
|
|
SOLDIERTYPE *pSoldier;
|
|
INT16 sSoldierID;
|
|
INT16 sXPos, sYPos;
|
|
|
|
sXPos = sYPos = 0;
|
|
|
|
//Loop through the active NPC's
|
|
// cnt = gTacticalStatus.Team[ OUR_TEAM ].bLastID + 1;
|
|
for(cnt=FIRST_RPC; cnt<NUM_PROFILES; cnt++)
|
|
{
|
|
if ( gMercProfiles[ cnt ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED )
|
|
{
|
|
// don't load
|
|
continue;
|
|
}
|
|
|
|
sSoldierID = GetSoldierIDFromAnyMercID( (UINT8)cnt );
|
|
|
|
//if the soldier is not loaded, return
|
|
if( sSoldierID == -1 )
|
|
continue;
|
|
|
|
//if we cant get a pointer to the soldier, continue
|
|
if( !GetSoldier( &pSoldier, sSoldierID ) )
|
|
continue;
|
|
|
|
pSoldier->ubQuoteActionID = gMercProfiles[ cnt ].ubQuoteActionID;
|
|
pSoldier->ubQuoteRecord = gMercProfiles[ cnt ].ubQuoteRecord;
|
|
|
|
if( gMercProfiles[ cnt ].fUseProfileInsertionInfo == PROFILE_USE_GRIDNO )
|
|
{
|
|
sX = CenterX( gMercProfiles[ cnt ].sGridNo );
|
|
sY = CenterY( gMercProfiles[ cnt ].sGridNo );
|
|
|
|
//Load the Temp Npc Quote Info array
|
|
|
|
//if the NPC has been recruited, continue
|
|
if( gMercProfiles[ cnt ].ubMiscFlags & PROFILE_MISC_FLAG_TEMP_NPC_QUOTE_DATA_EXISTS )
|
|
LoadTempNpcQuoteInfoForNPCFromTempFile( (UINT8)cnt );
|
|
|
|
//if the NPC has been recruited, continue
|
|
if( gMercProfiles[ cnt ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED )
|
|
continue;
|
|
|
|
//If the NPC was supposed to do something when they reached their target destination
|
|
if( pSoldier->sGridNo == pSoldier->pathing.sFinalDestination )
|
|
{
|
|
if (pSoldier->ubQuoteRecord && pSoldier->ubQuoteActionID == QUOTE_ACTION_ID_CHECKFORDEST )
|
|
{
|
|
//the mercs gridno has to be the same as the final destination
|
|
pSoldier->EVENT_SetSoldierPosition( (FLOAT) sX, (FLOAT) sY );
|
|
|
|
NPCReachedDestination( pSoldier, FALSE );
|
|
}
|
|
}
|
|
|
|
//If the NPC's gridno is not nowhere, set him to that position
|
|
//if( !TileIsOutOfBounds(gMercProfiles[ cnt ].sGridNo) )
|
|
if(!TileIsOutOfBounds(gMercProfiles[ cnt ].sGridNo))
|
|
{
|
|
if( !(gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
|
|
{
|
|
//Set the NPC's destination
|
|
pSoldier->pathing.sDestination = gMercProfiles[ cnt ].sGridNo;
|
|
pSoldier->pathing.sDestXPos = sXPos;
|
|
pSoldier->pathing.sDestYPos = sYPos;
|
|
|
|
// We have moved to a diferent sector and are returning to it, therefore the merc should be in the final dest
|
|
EVENT_SetSoldierPositionAndMaybeFinalDestAndMaybeNotDestination( pSoldier, (FLOAT) sX, (FLOAT) sY, FALSE, TRUE );
|
|
}
|
|
|
|
//else we are saving
|
|
else
|
|
{
|
|
|
|
//Set the NPC's position
|
|
// pSoldier->EVENT_SetSoldierPosition( (FLOAT) sX, (FLOAT) sY );
|
|
EVENT_SetSoldierPositionAndMaybeFinalDestAndMaybeNotDestination( pSoldier, (FLOAT) sX, (FLOAT) sY, FALSE, FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
//else if we are NOT to use the gridno, dont use it but reset the flag
|
|
else if( gMercProfiles[ cnt ].fUseProfileInsertionInfo == PROFILE_DONT_USE_GRIDNO )
|
|
{
|
|
gMercProfiles[ cnt ].fUseProfileInsertionInfo = PROFILE_NOT_SET;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
BOOLEAN DoesTempFileExistsForMap( UINT32 uiType, INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
UNDERGROUND_SECTORINFO *TempNode = gpUndergroundSectorInfoHead;
|
|
|
|
if( bMapZ == 0 )
|
|
{
|
|
return( (SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & uiType) ? 1 : 0 );
|
|
}
|
|
else
|
|
{
|
|
while( TempNode )
|
|
{
|
|
if( TempNode->ubSectorX == sMapX && TempNode->ubSectorY == sMapY && TempNode->ubSectorZ == bMapZ )
|
|
{
|
|
return( (TempNode->uiFlags & uiType ) ? 1 : 0 );
|
|
}
|
|
TempNode = TempNode->next;
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
INT16 GetSoldierIDFromAnyMercID(UINT8 ubMercID)
|
|
{
|
|
UINT16 cnt;
|
|
UINT16 ubLastTeamID;
|
|
SOLDIERTYPE *pTeamSoldier;
|
|
|
|
cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
|
|
|
|
ubLastTeamID = TOTAL_SOLDIERS;
|
|
|
|
// look for all mercs on the same team,
|
|
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= ubLastTeamID; cnt++,pTeamSoldier++)
|
|
{
|
|
if( pTeamSoldier->bActive )
|
|
{
|
|
if ( pTeamSoldier->ubProfile == ubMercID )
|
|
{
|
|
return( cnt );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( -1 );
|
|
}
|
|
|
|
|
|
|
|
|
|
//Initializes the NPC temp array
|
|
BOOLEAN InitTempNpcQuoteInfoForNPCFromTempFile()
|
|
{
|
|
UINT32 uiNumBytesWritten;
|
|
UINT8 ubCnt;
|
|
TempNPCQuoteInfoSave TempNpcQuote[ NUM_NPC_QUOTE_RECORDS ];
|
|
UINT32 uiSizeOfTempArray = sizeof( TempNPCQuoteInfoSave ) * NUM_NPC_QUOTE_RECORDS;
|
|
UINT16 usCnt1;
|
|
HWFILE hFile;
|
|
|
|
|
|
//Open the temp npc file
|
|
hFile = FileOpen( NPC_TEMP_QUOTE_FILE, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening temp npc quote info
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
//loop through all the npc accounts and write the temp array to disk
|
|
//for( usCnt1=0; usCnt1< ( GASTON-FIRST_RPC ); usCnt1++)
|
|
//new profiles by Jazz
|
|
for( usCnt1=0; usCnt1< NUM_PROFILES; usCnt1++)
|
|
{
|
|
|
|
memset( TempNpcQuote, 0, uiSizeOfTempArray );
|
|
|
|
//Loop through and build the temp array to save
|
|
for( ubCnt=0; ubCnt<NUM_NPC_QUOTE_RECORDS; ubCnt++ )
|
|
{
|
|
if( gpNPCQuoteInfoArray[ usCnt1 ] )
|
|
{
|
|
TempNpcQuote[ ubCnt ].usFlags = gpNPCQuoteInfoArray[ usCnt1 ][ ubCnt ].fFlags;
|
|
TempNpcQuote[ ubCnt ].sRequiredItem = gpNPCQuoteInfoArray[ usCnt1 ][ ubCnt ].sRequiredItem;
|
|
TempNpcQuote[ ubCnt ].usGoToGridNo = gpNPCQuoteInfoArray[ usCnt1 ][ ubCnt ].usGoToGridNo;
|
|
}
|
|
}
|
|
|
|
//Save the array to a temp file
|
|
FileWrite( hFile, TempNpcQuote, uiSizeOfTempArray, &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != uiSizeOfTempArray )
|
|
{
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
FileClose( hFile );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN SaveTempNpcQuoteInfoForNPCToTempFile( UINT8 ubNpcId )
|
|
{
|
|
UINT32 uiNumBytesWritten;
|
|
UINT8 ubCnt;
|
|
TempNPCQuoteInfoSave TempNpcQuote[ NUM_NPC_QUOTE_RECORDS ];
|
|
UINT32 uiSizeOfTempArray = sizeof( TempNPCQuoteInfoSave ) * NUM_NPC_QUOTE_RECORDS;
|
|
UINT32 uiSpotInFile = ubNpcId - FIRST_RPC;
|
|
HWFILE hFile=0;
|
|
|
|
//if there are records to save
|
|
if( gpNPCQuoteInfoArray[ ubNpcId ] )
|
|
{
|
|
|
|
hFile = FileOpen( NPC_TEMP_QUOTE_FILE, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening temp npc quote info
|
|
return( FALSE );
|
|
}
|
|
|
|
memset( TempNpcQuote, 0, uiSizeOfTempArray );
|
|
|
|
//Loop through and build the temp array to save
|
|
for( ubCnt=0; ubCnt<NUM_NPC_QUOTE_RECORDS; ubCnt++ )
|
|
{
|
|
TempNpcQuote[ ubCnt ].usFlags = gpNPCQuoteInfoArray[ ubNpcId ][ ubCnt ].fFlags;
|
|
TempNpcQuote[ ubCnt ].sRequiredItem = gpNPCQuoteInfoArray[ ubNpcId ][ ubCnt ].sRequiredItem;
|
|
TempNpcQuote[ ubCnt ].usGoToGridNo = gpNPCQuoteInfoArray[ ubNpcId ][ ubCnt ].usGoToGridNo;
|
|
}
|
|
|
|
//Seek to the correct spot in the file
|
|
FileSeek( hFile, uiSpotInFile * uiSizeOfTempArray, FILE_SEEK_FROM_START );
|
|
|
|
//Save the array to a temp file
|
|
FileWrite( hFile, TempNpcQuote, uiSizeOfTempArray, &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != uiSizeOfTempArray )
|
|
{
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
//Set the fact that the merc has the temp npc quote data
|
|
gMercProfiles[ ubNpcId ].ubMiscFlags |= PROFILE_MISC_FLAG_TEMP_NPC_QUOTE_DATA_EXISTS;
|
|
|
|
FileClose( hFile );
|
|
}
|
|
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN LoadTempNpcQuoteInfoForNPCFromTempFile( UINT8 ubNpcId )
|
|
{
|
|
UINT32 uiNumBytesRead;
|
|
UINT8 ubCnt;
|
|
TempNPCQuoteInfoSave TempNpcQuote[ NUM_NPC_QUOTE_RECORDS ];
|
|
UINT32 uiSizeOfTempArray = sizeof( TempNPCQuoteInfoSave ) * NUM_NPC_QUOTE_RECORDS;
|
|
UINT32 uiSpotInFile = ubNpcId - FIRST_RPC;
|
|
HWFILE hFile;
|
|
|
|
|
|
//Init the array
|
|
memset( TempNpcQuote, 0, uiSizeOfTempArray );
|
|
|
|
|
|
//If there isnt already memory allocated, allocate memory to hold the array
|
|
if( gpNPCQuoteInfoArray[ ubNpcId ] == NULL )
|
|
{
|
|
gpNPCQuoteInfoArray[ ubNpcId ] = (NPCQuoteInfo *) MemAlloc( sizeof( NPCQuoteInfo ) * NUM_NPC_QUOTE_RECORDS );
|
|
if( gpNPCQuoteInfoArray[ ubNpcId ] == NULL )
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
hFile = FileOpen( NPC_TEMP_QUOTE_FILE, FILE_ACCESS_READ | FILE_OPEN_ALWAYS, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening temp npc quote info
|
|
return( FALSE );
|
|
}
|
|
|
|
//Seek to the correct spot in the file
|
|
FileSeek( hFile, uiSpotInFile * uiSizeOfTempArray, FILE_SEEK_FROM_START );
|
|
|
|
//Save the array to a temp file
|
|
FileRead( hFile, TempNpcQuote, uiSizeOfTempArray, &uiNumBytesRead );
|
|
if( uiNumBytesRead != uiSizeOfTempArray )
|
|
{
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
//Loop through and build the temp array to save
|
|
for( ubCnt=0; ubCnt<NUM_NPC_QUOTE_RECORDS; ubCnt++ )
|
|
{
|
|
gpNPCQuoteInfoArray[ ubNpcId ][ ubCnt ].fFlags = TempNpcQuote[ ubCnt ].usFlags;
|
|
gpNPCQuoteInfoArray[ ubNpcId ][ ubCnt ].sRequiredItem = TempNpcQuote[ ubCnt ].sRequiredItem;
|
|
gpNPCQuoteInfoArray[ ubNpcId ][ ubCnt ].usGoToGridNo = TempNpcQuote[ ubCnt ].usGoToGridNo;
|
|
}
|
|
|
|
FileClose( hFile );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ChangeNpcToDifferentSector( UINT8 ubNpcId, INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ )
|
|
{
|
|
if (gMercProfiles[ ubNpcId ].ubMiscFlags2 & PROFILE_MISC_FLAG2_LEFT_COUNTRY)
|
|
{
|
|
// override location, this person is OUTTA here
|
|
sSectorX = 0;
|
|
sSectorY = 0;
|
|
bSectorZ = 0;
|
|
}
|
|
// Carmen no longer traverses out, he is temporarily removed instead
|
|
|
|
gMercProfiles[ ubNpcId ].sSectorX = sSectorX;
|
|
gMercProfiles[ ubNpcId ].sSectorY = sSectorY;
|
|
gMercProfiles[ ubNpcId ].bSectorZ = bSectorZ;
|
|
|
|
gMercProfiles[ ubNpcId ].fUseProfileInsertionInfo = FALSE;
|
|
|
|
/*
|
|
if (!gMercProfiles[ ubNpcId ].ubMiscFlags2 & PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR)
|
|
{
|
|
gMercProfiles[ ubNpcId ].fUseProfileInsertionInfo = PROFILE_DONT_USE_GRIDNO;
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN AddRottingCorpseToUnloadedSectorsRottingCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, ROTTING_CORPSE_DEFINITION *pRottingCorpseDef )
|
|
{
|
|
HWFILE hFile;
|
|
UINT32 uiNumberOfCorpses;
|
|
CHAR8 zMapName[ 128 ];
|
|
UINT32 uiNumBytesRead;
|
|
|
|
ROTTING_CORPSE_DEFINITION def;
|
|
std::vector<ROTTING_CORPSE_DEFINITION> corpsedefvector;
|
|
|
|
// Flugente 2018-08-15: the old method of reading and writing in the same file at the same time is faulty.
|
|
// We instead open the existing file if it exists, take it's contents, and write them with the new corpse to a new file
|
|
|
|
GetMapTempFileName( SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
if ( DoesTempFileExistsForMap( SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, sMapX, sMapY, bMapZ ) && FileExists( zMapName ) )
|
|
{
|
|
//Open the file for reading
|
|
hFile = FileOpen( zMapName, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE );
|
|
if ( hFile == 0 )
|
|
{
|
|
//Error opening map modification file,
|
|
return( FALSE );
|
|
}
|
|
|
|
// Load the number of Rotting corpses
|
|
FileRead( hFile, &uiNumberOfCorpses, sizeof( UINT32 ), &uiNumBytesRead );
|
|
if ( uiNumBytesRead != sizeof( UINT32 ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
// load existing corpses
|
|
for ( UINT32 cnt = 0; cnt < uiNumberOfCorpses; ++cnt )
|
|
{
|
|
// Load the Rotting corpses info
|
|
FileRead( hFile, &def, sizeof( ROTTING_CORPSE_DEFINITION ), &uiNumBytesRead );
|
|
if ( uiNumBytesRead != sizeof( ROTTING_CORPSE_DEFINITION ) )
|
|
{
|
|
//Error Writing size of array to disk
|
|
continue;
|
|
}
|
|
|
|
corpsedefvector.push_back( def );
|
|
}
|
|
|
|
FileClose( hFile );
|
|
}
|
|
|
|
corpsedefvector.push_back( *pRottingCorpseDef );
|
|
|
|
// create the file anew
|
|
SaveRottingCorpsesToTempCorpseFile( sMapX, sMapY, bMapZ, corpsedefvector );
|
|
|
|
// Flugente: update number of corpses in this sector
|
|
if ( !bMapZ )
|
|
{
|
|
SECTORINFO *pSectorInfo = &( SectorInfo[SECTOR( sMapX, sMapY )] );
|
|
|
|
if ( pSectorInfo )
|
|
pSectorInfo->usNumCorpses = corpsedefvector.size();
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN SetUnderGroundSectorFlag( INT16 sSectorX, INT16 sSectorY, UINT8 ubSectorZ, UINT32 uiFlagToSet )
|
|
{
|
|
UNDERGROUND_SECTORINFO *pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
//loop through and look for the right underground sector
|
|
while( pTempNode )
|
|
{
|
|
if( ( pTempNode->ubSectorX == (UINT8)sSectorX ) &&
|
|
( pTempNode->ubSectorY == (UINT8)sSectorY ) &&
|
|
( pTempNode->ubSectorZ == ubSectorZ ) )
|
|
{
|
|
//set the flag indicating that ther is a temp item file exists for the sector
|
|
pTempNode->uiFlags |= uiFlagToSet;
|
|
|
|
return( TRUE );
|
|
}
|
|
pTempNode = pTempNode->next;
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN ReSetUnderGroundSectorFlag( INT16 sSectorX, INT16 sSectorY, UINT8 ubSectorZ, UINT32 uiFlagToSet )
|
|
{
|
|
UNDERGROUND_SECTORINFO *pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
//loop through and look for the right underground sector
|
|
while( pTempNode )
|
|
{
|
|
if( ( pTempNode->ubSectorX == (UINT8)sSectorX ) &&
|
|
( pTempNode->ubSectorY == (UINT8)sSectorY ) &&
|
|
( pTempNode->ubSectorZ == ubSectorZ ) )
|
|
{
|
|
//set the flag indicating that ther is a temp item file exists for the sector
|
|
pTempNode->uiFlags &= ~( uiFlagToSet );
|
|
|
|
return( TRUE );
|
|
}
|
|
pTempNode = pTempNode->next;
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN GetUnderGroundSectorFlagStatus( INT16 sSectorX, INT16 sSectorY, UINT8 ubSectorZ, UINT32 uiFlagToCheck )
|
|
{
|
|
UNDERGROUND_SECTORINFO *pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
pTempNode = gpUndergroundSectorInfoHead;
|
|
|
|
//loop through and look for the right underground sector
|
|
while( pTempNode )
|
|
{
|
|
if( ( pTempNode->ubSectorX == (UINT8)sSectorX ) &&
|
|
( pTempNode->ubSectorY == (UINT8)sSectorY ) &&
|
|
( pTempNode->ubSectorZ == ubSectorZ ) )
|
|
{
|
|
//set the flag indicating that ther is a temp item file exists for the sector
|
|
if( pTempNode->uiFlags & uiFlagToCheck )
|
|
return( TRUE );
|
|
else
|
|
return( FALSE );
|
|
}
|
|
pTempNode = pTempNode->next;
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOLEAN SetSectorFlag( INT16 sMapX, INT16 sMapY, UINT8 bMapZ, UINT32 uiFlagToSet )
|
|
{
|
|
if( uiFlagToSet == SF_ALREADY_VISITED )
|
|
{
|
|
|
|
// HEADROCK HAM 3.5: This is no longer required at all.
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
// HEADROCK HAM 3.4: Externalized. Hidden facilities listed on the facility array will be
|
|
// added to the sector info now, upon the first visit.
|
|
|
|
/*for(UINT32 cnt=0; (gFacilityLocations[cnt].uiSectorID >= 0 && gFacilityLocations[cnt].uiSectorID <= 256); cnt++ )
|
|
{
|
|
// Does the current record match the current sector?
|
|
if (gFacilityLocations[cnt].uiSectorID == SECTOR( sMapX, sMapY ))
|
|
{
|
|
// Is the current record set to be revealed?
|
|
if (gFacilityLocations[cnt].fHidden == 1)
|
|
{
|
|
// Reveal the facility.
|
|
SectorInfo[ SECTOR( sMapX, sMapY) ].uiFacilitiesFlags |= (1 << (gFacilityLocations[cnt].uiFacilityType - 1));
|
|
}
|
|
}
|
|
}*/
|
|
|
|
|
|
// HEADROCK HAM 3.4: Externalized.
|
|
/*
|
|
// do certain things when particular sectors are visited
|
|
if ( ( sMapX == TIXA_SECTOR_X ) && ( sMapY == TIXA_SECTOR_Y ) )
|
|
{
|
|
// Tixa prison (not seen until Tixa visited)
|
|
SectorInfo[ SEC_J9 ].uiFacilitiesFlags |= SFCF_PRISON;
|
|
}
|
|
|
|
if ( ( sMapX == GUN_RANGE_X ) && ( sMapY == GUN_RANGE_Y ) && ( bMapZ == GUN_RANGE_Z ) )
|
|
{
|
|
// Alma shooting range (not seen until sector visited)
|
|
SectorInfo[ SEC_H13 ].uiFacilitiesFlags |= SFCF_GUN_RANGE;
|
|
SectorInfo[ SEC_H14 ].uiFacilitiesFlags |= SFCF_GUN_RANGE;
|
|
SectorInfo[ SEC_I13 ].uiFacilitiesFlags |= SFCF_GUN_RANGE;
|
|
SectorInfo[ SEC_I14 ].uiFacilitiesFlags |= SFCF_GUN_RANGE;
|
|
}*/
|
|
|
|
if ( !GetSectorFlagStatus( sMapX, sMapY, bMapZ, SF_ALREADY_VISITED ) )
|
|
{
|
|
// increment daily counter of sectors visited
|
|
gStrategicStatus.ubNumNewSectorsVisitedToday++;
|
|
if ( gStrategicStatus.ubNumNewSectorsVisitedToday == NEW_SECTORS_EQUAL_TO_ACTIVITY )
|
|
{
|
|
// visited enough to count as an active day
|
|
UpdateLastDayOfPlayerActivity( (UINT16) GetWorldDay() );
|
|
}
|
|
|
|
for ( UINT16 i = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; i <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; i++ )
|
|
{
|
|
if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !(MercPtrs[ i ]->flags.uiStatusFlags & SOLDIER_VEHICLE) && MercPtrs[ i ]->ubProfile != NO_PROFILE &&
|
|
MercPtrs[ i ]->sSectorX == sMapX && MercPtrs[ i ]->sSectorY == sMapY && MercPtrs[ i ]->bSectorZ == bMapZ && !MercPtrs[ i ]->flags.fBetweenSectors &&
|
|
MercPtrs[ i ]->bAssignment != IN_TRANSIT && MercPtrs[ i ]->bAssignment != ASSIGNMENT_DEAD )
|
|
{
|
|
gMercProfiles[ MercPtrs[ i ]->ubProfile ].records.usSectorsDiscovered++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bMapZ == 0 )
|
|
SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags |= uiFlagToSet;
|
|
else
|
|
SetUnderGroundSectorFlag( sMapX, sMapY, bMapZ, uiFlagToSet );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN ReSetSectorFlag( INT16 sMapX, INT16 sMapY, UINT8 bMapZ, UINT32 uiFlagToSet )
|
|
{
|
|
if( bMapZ == 0 )
|
|
SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags &= ~( uiFlagToSet );
|
|
else
|
|
ReSetUnderGroundSectorFlag( sMapX, sMapY, bMapZ, uiFlagToSet );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN GetSectorFlagStatus( INT16 sMapX, INT16 sMapY, UINT8 bMapZ, UINT32 uiFlagToSet )
|
|
{
|
|
if( bMapZ == 0 )
|
|
return( (SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFlags & uiFlagToSet ) ? 1 : 0 );
|
|
else
|
|
return( (GetUnderGroundSectorFlagStatus( sMapX, sMapY, bMapZ, uiFlagToSet ) ) ? 1 : 0 );
|
|
}
|
|
|
|
BOOLEAN AddDeadSoldierToUnLoadedSector( INT16 sMapX, INT16 sMapY, UINT8 bMapZ, SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiFlags )
|
|
{
|
|
UINT32 uiNumberOfItems;
|
|
std::vector<WORLDITEM> pWorldItems;//dnl ch75 271013
|
|
UINT8 i;
|
|
UINT8 bCount=0;
|
|
UINT16 uiFlagsForWorldItems=0;
|
|
UINT16 usFlagsForRottingCorpse=0;
|
|
ROTTING_CORPSE_DEFINITION Corpse;
|
|
INT16 sXPos, sYPos;
|
|
UINT32 uiDeathAnim;
|
|
UINT32 uiPossibleDeathAnims[] = { GENERIC_HIT_DEATH,
|
|
FALLBACK_HIT_DEATH,
|
|
PRONE_HIT_DEATH,
|
|
FLYBACK_HIT_DEATH };
|
|
//setup the flags for the items and the rotting corpses
|
|
if( uiFlags & ADD_DEAD_SOLDIER_USE_GRIDNO )
|
|
{
|
|
uiFlagsForWorldItems = 0;
|
|
usFlagsForRottingCorpse = 0;
|
|
}
|
|
|
|
else if( uiFlags & ADD_DEAD_SOLDIER_TO_SWEETSPOT )
|
|
{
|
|
uiFlagsForWorldItems |= WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO | WORLD_ITEM_REACHABLE;
|
|
usFlagsForRottingCorpse |= ROTTING_CORPSE_FIND_SWEETSPOT_FROM_GRIDNO;
|
|
}
|
|
else
|
|
AssertMsg( 0, "ERROR!! Flag not is Switch statement");
|
|
|
|
//
|
|
//Create an array of objects from the mercs inventory
|
|
//
|
|
|
|
//go through and and find out how many items there are
|
|
uiNumberOfItems = 0;
|
|
UINT8 invsize = pSoldier->inv.size();
|
|
for ( i = 0; i < invsize; ++i )
|
|
{
|
|
if( pSoldier->inv[ i ].exists() == true )
|
|
{
|
|
// Flugente: if we don't want items to drop in autoresolve, this is the place to set that
|
|
if ( pSoldier->bTeam != gbPlayerNum && !gGameExternalOptions.fNPCAutoresolveItemDrop )
|
|
{
|
|
// mark it undroppable...
|
|
pSoldier->inv[i].fFlags |= OBJECT_UNDROPPABLE;
|
|
}
|
|
|
|
//if the item can be dropped
|
|
if( !( pSoldier->inv[ i ].fFlags & OBJECT_UNDROPPABLE ) || pSoldier->bTeam == gbPlayerNum )
|
|
{
|
|
++uiNumberOfItems;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If a robot, don't drop anything...
|
|
if ( AM_A_ROBOT( pSoldier ) )
|
|
{
|
|
uiNumberOfItems = 0;
|
|
}
|
|
|
|
//if there are items to add
|
|
if( uiNumberOfItems )
|
|
{
|
|
//allocate memory for the world item array
|
|
pWorldItems.resize(uiNumberOfItems);//dnl ch75 271013
|
|
|
|
//loop through all the soldiers items and add them to the world item array
|
|
bCount = 0;
|
|
for ( i = 0; i < invsize; ++i )
|
|
{
|
|
if( pSoldier->inv[ i ].exists() == true )
|
|
{
|
|
//if the item can be dropped
|
|
if( !(pSoldier->inv[ i ].fFlags & OBJECT_UNDROPPABLE) || pSoldier->bTeam == gbPlayerNum )
|
|
{
|
|
ReduceAmmoDroppedByNonPlayerSoldiers( pSoldier, i );
|
|
|
|
pWorldItems[ bCount ].fExists = TRUE;
|
|
pWorldItems[ bCount ].sGridNo = sGridNo;
|
|
pWorldItems[ bCount ].ubLevel = (UINT8)pSoldier->pathing.bLevel;
|
|
pWorldItems[ bCount ].usFlags = uiFlagsForWorldItems;
|
|
pWorldItems[ bCount ].bVisible = TRUE;
|
|
pWorldItems[ bCount ].bRenderZHeightAboveLevel = 0;
|
|
|
|
if (ItemIsDamageable(pSoldier->inv[i].usItem)) // Madd: drop crappier items on higher difficulty levels
|
|
{
|
|
// silversurfer: externalized this
|
|
//pSoldier->inv[i][0]->data.objectStatus -= (gGameOptions.ubDifficultyLevel - 1) * Random(20);
|
|
pSoldier->inv[i][0]->data.objectStatus -= Random( zDiffSetting[gGameOptions.ubDifficultyLevel].usLootStatusModifier );
|
|
pSoldier->inv[i][0]->data.objectStatus = max(pSoldier->inv[i][0]->data.objectStatus,1); // never below 1%
|
|
}
|
|
pWorldItems[ bCount ].object = pSoldier->inv[i];
|
|
++bCount;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Add the soldiers items to an unloaded sector
|
|
AddWorldItemsToUnLoadedSector( sMapX, sMapY, bMapZ, sGridNo, uiNumberOfItems, pWorldItems, FALSE );
|
|
|
|
//CHRISL: Now that we've copied the dead soldiers items to pWorldItems, we need to actually remove the items from the dead soldier. Otherwise we have
|
|
// actually duplicated the items and there's a chance that these duplicated items will again find their way to sector.
|
|
for ( i = 0; i < invsize; ++i )
|
|
{
|
|
if( pSoldier->inv[ i ].exists() == true )
|
|
{
|
|
pSoldier->inv[i].initialize();
|
|
}
|
|
}
|
|
}
|
|
|
|
DropKeysInKeyRing( pSoldier, sGridNo, pSoldier->pathing.bLevel, 1, FALSE, 0, TRUE );
|
|
|
|
//
|
|
//Convert the soldier into a rottng corpse
|
|
//
|
|
|
|
memset( &Corpse, 0, sizeof( ROTTING_CORPSE_DEFINITION ) );
|
|
|
|
// Setup some values!
|
|
ConvertGridNoToCenterCellXY(sGridNo, &sXPos, &sYPos);
|
|
|
|
Corpse.ubBodyType = pSoldier->ubBodyType;
|
|
Corpse.sGridNo = sGridNo;
|
|
Corpse.dXPos = (FLOAT)( sXPos );
|
|
Corpse.dYPos = (FLOAT)( sYPos );
|
|
Corpse.sHeightAdjustment = pSoldier->sHeightAdjustment;
|
|
Corpse.bVisible = TRUE;
|
|
|
|
SET_PALETTEREP_ID ( Corpse.HeadPal, pSoldier->HeadPal );
|
|
SET_PALETTEREP_ID ( Corpse.VestPal, pSoldier->VestPal );
|
|
SET_PALETTEREP_ID ( Corpse.SkinPal, pSoldier->SkinPal );
|
|
SET_PALETTEREP_ID ( Corpse.PantsPal, pSoldier->PantsPal );
|
|
|
|
Corpse.ubDirection = pSoldier->ubDirection;
|
|
|
|
// Set time of death
|
|
Corpse.uiTimeOfDeath = GetWorldTotalMin( );
|
|
|
|
//if the dead body shot be the result of a Jfk headshot, set it
|
|
if( uiFlags & ADD_DEAD_SOLDIER__USE_JFK_HEADSHOT_CORPSE )
|
|
uiDeathAnim = JFK_HITDEATH;
|
|
|
|
//else chose a random death sequence
|
|
else
|
|
uiDeathAnim = uiPossibleDeathAnims[ Random( 4 ) ];
|
|
|
|
|
|
// Set type
|
|
Corpse.ubType = (UINT8)gubAnimSurfaceCorpseID[ pSoldier->ubBodyType][ uiDeathAnim ];
|
|
|
|
Corpse.usFlags |= usFlagsForRottingCorpse;
|
|
|
|
//Add the rotting corpse info to the sectors unloaded rotting corpse file
|
|
AddRottingCorpseToUnloadedSectorsRottingCorpseFile( sMapX, sMapY, bMapZ, &Corpse);
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN SaveTempNpcQuoteArrayToSaveGameFile( HWFILE hFile )
|
|
{
|
|
return( SaveFilesToSavedGame( NPC_TEMP_QUOTE_FILE, hFile ) );
|
|
}
|
|
|
|
BOOLEAN LoadTempNpcQuoteArrayToSaveGameFile( HWFILE hFile )
|
|
{
|
|
return( LoadFilesFromSavedGame( NPC_TEMP_QUOTE_FILE, hFile ) );
|
|
}
|
|
|
|
void TempFileLoadErrorMessageReturnCallback( UINT8 ubRetVal )
|
|
{
|
|
gfProgramIsRunning = FALSE;
|
|
}
|
|
|
|
//if you call this function, make sure you return TRUE (if applicable) to make the game
|
|
//think it succeeded the load. This sets up the dialog for the game exit, after the hacker
|
|
//message appears.
|
|
void InitExitGameDialogBecauseFileHackDetected()
|
|
{
|
|
SGPRect CenteringRect= {0, 0, 639, 479 };
|
|
|
|
// do message box and return
|
|
giErrorMessageBox = DoMessageBox( MSG_BOX_BASIC_STYLE, pAntiHackerString[ ANTIHACKERSTR_EXITGAME ],
|
|
GAME_SCREEN, MSG_BOX_FLAG_OK, TempFileLoadErrorMessageReturnCallback, &CenteringRect );
|
|
}
|
|
|
|
// CHRISL: New Checksum for LBENODE
|
|
UINT32 LBENODEChecksum( LBENODE * pNode )
|
|
{
|
|
UINT32 uiChecksum = 1;
|
|
UINT32 uiLoop;
|
|
|
|
uiChecksum += (pNode->lbeClass + 1);
|
|
uiChecksum *= (pNode->lbeIndex +1);
|
|
uiChecksum += (pNode->ubID +1);
|
|
|
|
UINT32 invsize = pNode->inv.size();
|
|
for ( uiLoop = 0; uiLoop < invsize; ++uiLoop )
|
|
{
|
|
uiChecksum += pNode->inv[ uiLoop ].usItem;
|
|
}
|
|
|
|
return( uiChecksum );
|
|
}
|
|
|
|
|
|
//UINT8 gubEncryptionArray4[ BASE_NUMBER_OF_ROTATION_ARRAYS * 3 ][ NEW_ROTATION_ARRAY_SIZE ] =
|
|
UINT8 * GetRotationArray( void )
|
|
{
|
|
// based on guiJA2EncryptionSet
|
|
if ( guiJA2EncryptionSet < BASE_NUMBER_OF_ROTATION_ARRAYS * 6 )
|
|
{
|
|
if ( guiJA2EncryptionSet < BASE_NUMBER_OF_ROTATION_ARRAYS * 3 )
|
|
{
|
|
return( gubEncryptionArray1[ guiJA2EncryptionSet % (BASE_NUMBER_OF_ROTATION_ARRAYS * 3) ]);
|
|
}
|
|
else
|
|
{
|
|
return( gubEncryptionArray2[ guiJA2EncryptionSet % (BASE_NUMBER_OF_ROTATION_ARRAYS * 3) ]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( guiJA2EncryptionSet < BASE_NUMBER_OF_ROTATION_ARRAYS * 9 )
|
|
{
|
|
return( gubEncryptionArray3[ guiJA2EncryptionSet % (BASE_NUMBER_OF_ROTATION_ARRAYS * 3) ]);
|
|
}
|
|
else
|
|
{
|
|
return( gubEncryptionArray4[ guiJA2EncryptionSet % (BASE_NUMBER_OF_ROTATION_ARRAYS * 3) ]);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOLEAN NewJA2EncryptedFileRead( HWFILE hFile, PTR pDest, UINT32 uiBytesToRead, UINT32 *puiBytesRead )
|
|
{
|
|
UINT32 uiLoop;
|
|
UINT8 ubArrayIndex = 0;
|
|
UINT8 ubLastByte = 0;
|
|
UINT8 ubLastByteForNextLoop;
|
|
BOOLEAN fRet;
|
|
UINT8 * pMemBlock;
|
|
UINT8 * pubRotationArray;
|
|
|
|
pubRotationArray = GetRotationArray();
|
|
|
|
fRet = FileRead( hFile, pDest, uiBytesToRead, puiBytesRead );
|
|
if ( fRet )
|
|
{
|
|
pMemBlock = (UINT8 *)pDest;
|
|
for ( uiLoop = 0; uiLoop < *puiBytesRead; uiLoop++ )
|
|
{
|
|
ubLastByteForNextLoop = pMemBlock[ uiLoop ];
|
|
pMemBlock[ uiLoop ] -= (ubLastByte + pubRotationArray[ ubArrayIndex ]);
|
|
ubArrayIndex++;
|
|
if ( ubArrayIndex >= NEW_ROTATION_ARRAY_SIZE )
|
|
{
|
|
ubArrayIndex = 0;
|
|
}
|
|
ubLastByte = ubLastByteForNextLoop;
|
|
}
|
|
}
|
|
|
|
return( fRet );
|
|
}
|
|
|
|
|
|
BOOLEAN NewJA2EncryptedFileWrite( HWFILE hFile, PTR pDest, UINT32 uiBytesToWrite, UINT32 *puiBytesWritten )
|
|
{
|
|
UINT32 uiLoop;
|
|
UINT8 ubArrayIndex = 0;
|
|
UINT8 ubLastByte = 0;//, ubTemp;
|
|
UINT8 * pMemBlock;
|
|
BOOLEAN fRet;
|
|
UINT8 * pubRotationArray;
|
|
|
|
pMemBlock = (UINT8 *) MemAlloc( uiBytesToWrite );
|
|
|
|
if ( !pMemBlock )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
memset( pMemBlock, 0, uiBytesToWrite );
|
|
|
|
pubRotationArray = GetRotationArray();
|
|
|
|
memcpy( pMemBlock, pDest, uiBytesToWrite );
|
|
for ( uiLoop = 0; uiLoop < uiBytesToWrite; uiLoop++ )
|
|
{
|
|
pMemBlock[ uiLoop ] += ubLastByte + pubRotationArray[ ubArrayIndex ];
|
|
ubArrayIndex++;
|
|
if ( ubArrayIndex >= NEW_ROTATION_ARRAY_SIZE )
|
|
{
|
|
ubArrayIndex = 0;
|
|
}
|
|
ubLastByte = pMemBlock[ uiLoop ];
|
|
}
|
|
|
|
fRet = FileWrite( hFile, pMemBlock, uiBytesToWrite, puiBytesWritten );
|
|
|
|
MemFree( pMemBlock );
|
|
|
|
return( fRet );
|
|
|
|
}
|
|
|
|
|
|
#define ROTATION_ARRAY_SIZE 46
|
|
UINT8 ubRotationArray[46] = { 132, 235, 125, 99, 15, 220, 140, 89, 205, 132, 254, 144, 217, 78, 156, 58, 215, 76, 163, 187, 55, 49, 65, 48, 156, 140, 201, 68, 184, 13, 45, 69, 102, 185, 122, 225, 23, 250, 160, 220, 114, 240, 64, 175, 057, 233 };
|
|
|
|
BOOLEAN JA2EncryptedFileRead( HWFILE hFile, PTR pDest, UINT32 uiBytesToRead, UINT32 *puiBytesRead )
|
|
{
|
|
UINT32 uiLoop;
|
|
UINT8 ubArrayIndex = 0;
|
|
//UINT8 ubLastNonBlank = 0;
|
|
UINT8 ubLastByte = 0;
|
|
UINT8 ubLastByteForNextLoop;
|
|
BOOLEAN fRet;
|
|
UINT8 * pMemBlock;
|
|
|
|
fRet = FileRead( hFile, pDest, uiBytesToRead, puiBytesRead );
|
|
if ( fRet )
|
|
{
|
|
pMemBlock = (UINT8 *)pDest;
|
|
for ( uiLoop = 0; uiLoop < *puiBytesRead; uiLoop++ )
|
|
{
|
|
ubLastByteForNextLoop = pMemBlock[ uiLoop ];
|
|
pMemBlock[ uiLoop ] -= (ubLastByte + ubRotationArray[ ubArrayIndex ]);
|
|
ubArrayIndex++;
|
|
if ( ubArrayIndex >= ROTATION_ARRAY_SIZE )
|
|
{
|
|
ubArrayIndex = 0;
|
|
}
|
|
ubLastByte = ubLastByteForNextLoop;
|
|
}
|
|
}
|
|
|
|
return( fRet );
|
|
}
|
|
|
|
|
|
BOOLEAN JA2EncryptedFileWrite( HWFILE hFile, PTR pDest, UINT32 uiBytesToWrite, UINT32 *puiBytesWritten )
|
|
{
|
|
UINT32 uiLoop;
|
|
UINT8 ubArrayIndex = 0;
|
|
//UINT8 ubLastNonBlank = 0;
|
|
UINT8 ubLastByte = 0;//, ubTemp;
|
|
UINT8 * pMemBlock;
|
|
BOOLEAN fRet;
|
|
|
|
pMemBlock = (UINT8 *) MemAlloc( uiBytesToWrite );
|
|
|
|
if ( !pMemBlock )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
memset( pMemBlock, 0, uiBytesToWrite );
|
|
|
|
|
|
memcpy( pMemBlock, pDest, uiBytesToWrite );
|
|
for ( uiLoop = 0; uiLoop < uiBytesToWrite; uiLoop++ )
|
|
{
|
|
//ubTemp = pMemBlock[ uiLoop ];
|
|
pMemBlock[ uiLoop ] += ubLastByte + ubRotationArray[ ubArrayIndex ];
|
|
ubArrayIndex++;
|
|
if ( ubArrayIndex >= ROTATION_ARRAY_SIZE )
|
|
{
|
|
ubArrayIndex = 0;
|
|
}
|
|
ubLastByte = pMemBlock[ uiLoop ];
|
|
/*
|
|
if ( pMemBlock[ uiLoop ] )
|
|
{
|
|
// store last non blank
|
|
ubLastNonBlank = pMemBlock[ uiLoop ];
|
|
|
|
pMemBlock[ uiLoop ] += ubRotationArray[ ubArrayIndex ];
|
|
ubArrayIndex++;
|
|
if ( ubArrayIndex >= ROTATION_ARRAY_SIZE )
|
|
{
|
|
ubArrayIndex = 0;
|
|
}
|
|
}
|
|
else // zero byte
|
|
{
|
|
pMemBlock[ uiLoop ] = ubLastNonBlank + ubRotationArray[ ubArrayIndex ];
|
|
ubArrayIndex++;
|
|
if ( ubArrayIndex >= ROTATION_ARRAY_SIZE )
|
|
{
|
|
ubArrayIndex = 0;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
fRet = FileWrite( hFile, pMemBlock, uiBytesToWrite, puiBytesWritten );
|
|
|
|
MemFree( pMemBlock );
|
|
|
|
return( fRet );
|
|
|
|
}
|
|
|
|
void GetMapTempFileName( UINT32 uiType, STR pMapName, INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
CHAR zTempName[512];
|
|
|
|
//Convert the current sector location into a file name
|
|
GetMapFileName( sMapX,sMapY, bMapZ, zTempName, FALSE, FALSE );
|
|
|
|
switch( uiType )
|
|
{
|
|
case SF_ITEM_TEMP_FILE_EXISTS:
|
|
sprintf( pMapName, "%s\\i_%s", MAPS_DIR, zTempName);
|
|
break;
|
|
|
|
case SF_ROTTING_CORPSE_TEMP_FILE_EXISTS:
|
|
sprintf( pMapName, "%s\\r_%s", MAPS_DIR, zTempName);
|
|
break;
|
|
|
|
case SF_MAP_MODIFICATIONS_TEMP_FILE_EXISTS:
|
|
sprintf( pMapName, "%s\\m_%s", MAPS_DIR, zTempName);
|
|
break;
|
|
|
|
case SF_DOOR_TABLE_TEMP_FILES_EXISTS:
|
|
sprintf( pMapName, "%s\\d_%s", MAPS_DIR, zTempName);
|
|
break;
|
|
|
|
case SF_REVEALED_STATUS_TEMP_FILE_EXISTS:
|
|
sprintf( pMapName, "%s\\v_%s", MAPS_DIR, zTempName);
|
|
break;
|
|
|
|
case SF_DOOR_STATUS_TEMP_FILE_EXISTS:
|
|
sprintf( pMapName, "%s\\ds_%s", MAPS_DIR, zTempName);
|
|
break;
|
|
|
|
case SF_ENEMY_PRESERVED_TEMP_FILE_EXISTS:
|
|
sprintf( pMapName, "%s\\e_%s", MAPS_DIR, zTempName);
|
|
break;
|
|
|
|
case SF_CIV_PRESERVED_TEMP_FILE_EXISTS:
|
|
// NB save game version 0 is "saving game"
|
|
if ( (gTacticalStatus.uiFlags & LOADING_SAVED_GAME) && guiCurrentSaveGameVersion != 0 && guiCurrentSaveGameVersion < 78 )
|
|
{
|
|
sprintf( pMapName, "%s\\c_%s", MAPS_DIR, zTempName);
|
|
}
|
|
else
|
|
{
|
|
sprintf( pMapName, "%s\\cc_%s", MAPS_DIR, zTempName);
|
|
}
|
|
break;
|
|
|
|
case SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS:
|
|
sprintf( pMapName, "%s\\sm_%s", MAPS_DIR, zTempName);
|
|
break;
|
|
|
|
case SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS:
|
|
sprintf( pMapName, "%s\\l_%s", MAPS_DIR, zTempName);
|
|
break;
|
|
|
|
default:
|
|
Assert( 0 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
UINT32 GetNumberOfVisibleWorldItemsFromSectorStructureForSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
UINT32 uiNumberOfItems=0;
|
|
UNDERGROUND_SECTORINFO *pSector=NULL;
|
|
|
|
//if the sector is above ground
|
|
if( bMapZ == 0 )
|
|
{
|
|
uiNumberOfItems = SectorInfo[ SECTOR( sMapX, sMapY ) ].uiNumberOfWorldItemsInTempFileThatCanBeSeenByPlayer;
|
|
}
|
|
else
|
|
{
|
|
//find the underground sector
|
|
pSector = FindUnderGroundSector( sMapX, sMapY, bMapZ );
|
|
if( pSector != NULL )
|
|
{
|
|
//get the number of items
|
|
uiNumberOfItems = pSector->uiNumberOfWorldItemsInTempFileThatCanBeSeenByPlayer;
|
|
}
|
|
}
|
|
|
|
//if there is a sector loaded
|
|
if( gfWorldLoaded )
|
|
{
|
|
//and it is the sector we are interested in
|
|
if( sMapX == gWorldSectorX && sMapY == gWorldSectorY && bMapZ == gbWorldSectorZ )
|
|
{
|
|
//since items might have been added, update
|
|
uiNumberOfItems = UpdateLoadedSectorsItemInventory( sMapX, sMapY, bMapZ, uiNumberOfItems );
|
|
}
|
|
}
|
|
|
|
|
|
return( uiNumberOfItems );
|
|
}
|
|
|
|
void SetNumberOfVisibleWorldItemsInSectorStructureForSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ, UINT32 uiNumberOfItems )
|
|
{
|
|
//if the sector is above ground
|
|
if( bMapZ == 0 )
|
|
{
|
|
SectorInfo[SECTOR( sMapX, sMapY )].uiNumberOfWorldItemsInTempFileThatCanBeSeenByPlayer = uiNumberOfItems;
|
|
}
|
|
else
|
|
{
|
|
//find the underground sector
|
|
UNDERGROUND_SECTORINFO* pSector = FindUnderGroundSector( sMapX, sMapY, bMapZ );
|
|
if( pSector != NULL )
|
|
{
|
|
//get the number of items
|
|
pSector->uiNumberOfWorldItemsInTempFileThatCanBeSeenByPlayer = uiNumberOfItems ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
UINT32 UpdateLoadedSectorsItemInventory( INT16 sMapX, INT16 sMapY, INT8 bMapZ, UINT32 uiNumberOfItems )
|
|
{
|
|
UINT32 uiCounter;
|
|
UINT32 uiItemCounter=0;
|
|
|
|
if( !gfWorldLoaded )
|
|
return( 0 );
|
|
|
|
//loop through all the world items
|
|
for( uiCounter= 0; uiCounter < guiNumWorldItems; uiCounter++ )
|
|
{
|
|
//if the item CAN be visible in mapscreen sector inventory
|
|
if( IsMapScreenWorldItemVisibleInMapInventory( &gWorldItems[ uiCounter ] ) )
|
|
{
|
|
//increment
|
|
uiItemCounter += gWorldItems[ uiCounter ].object.ubNumberOfObjects;
|
|
}
|
|
}
|
|
|
|
//if the item count is DIFFERENT
|
|
if( uiItemCounter != uiNumberOfItems )
|
|
{
|
|
//Update the value in the sector info struct
|
|
SetNumberOfVisibleWorldItemsInSectorStructureForSector( sMapX, sMapY, bMapZ, uiItemCounter );
|
|
}
|
|
|
|
//return the number of items
|
|
return( uiItemCounter );
|
|
}
|
|
|
|
// We no longer use map item temp files except during loading and saving a game to preserve savegame compatibility.
|
|
// LoadWorldItemsFromTempFiles & SaveWorldItemsToTempFiles are used to read and write world items to and from temp files into the global world items struct gAllWorldItems that is used during gameplay
|
|
void LoadWorldItemsFromTempFiles(INT16 sMapX, INT16 sMapY, INT8 bMapZ)
|
|
{
|
|
UINT32 nItems = 0;
|
|
std::vector<WORLDITEM> Items;
|
|
|
|
const BOOLEAN fReturn = GetNumberOfWorldItemsFromTempItemFile(sMapX, sMapY, bMapZ, &(nItems), FALSE);
|
|
if (fReturn == FALSE)
|
|
{
|
|
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("GetNumberOfWorldItemsFromTempItemFile failed"));
|
|
Assert(fReturn);
|
|
}
|
|
|
|
if (nItems > 0)
|
|
{
|
|
Items.resize(nItems);
|
|
LoadWorldItemsFromTempItemFile(sMapX, sMapY, bMapZ, Items);
|
|
UpdateWorldItems(sMapX, sMapY, bMapZ, nItems, Items);
|
|
}
|
|
}
|
|
|
|
void SaveWorldItemsToTempFiles()
|
|
{
|
|
for (size_t i = 0; i < gAllWorldItems.sectors.size(); i++)
|
|
{
|
|
const auto x = gAllWorldItems.sectors[i].x;
|
|
const auto y = gAllWorldItems.sectors[i].y;
|
|
const auto z = gAllWorldItems.sectors[i].z;
|
|
const auto nItems = gAllWorldItems.NumItems[i];
|
|
auto &Items = gAllWorldItems.Items[i];
|
|
|
|
SaveWorldItemsToTempItemFile(x, y, (INT8)z, nItems, Items);
|
|
}
|
|
}
|