#ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #include "Enemy Soldier Save.h" #else #include "Types.h" #include "MemMan.h" #include "message.h" #include "Items.h" #include "Handle Items.h" #include "StrategicMap.h" #include "Tactical Save.h" #include #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" #endif #include "Animation Control.h" #include BOOLEAN gfWasInMeanwhile = FALSE; //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; /////////////////////////////////////////////////////////////// // // 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 ); 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 void SynchronizeItemTempFileVisbleItemsToSectorInfoVisbleItems( INT16 sMapX, INT16 sMapY, INT8 bMapZ, BOOLEAN fLoadingGame ); 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 the current sectors open temp files to the disk // SaveCurrentSectorsItemsToTempItemFile(); // //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; INT16 sMapX; INT16 sMapY; UINT32 uiPercentage; UINT32 iCounter = 0; // HACK FOR GABBY if ( (gTacticalStatus.uiFlags & LOADING_SAVED_GAME) && guiCurrentSaveGameVersion < 81 ) { 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; } } } // //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( sMapY=1; sMapY<=16; sMapY++ ) { for( sMapX=1; sMapX<=16; 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; //sync up the temp file data to the sector structure data SynchronizeItemTempFileVisbleItemsToSectorInfoVisbleItems( sMapX, sMapY, 0, TRUE ); if (guiCurrentSaveGameVersion != SAVE_GAME_VERSION) { for (int z = 0; z < 4; ++z) { UpdateWorldItemsTempFile(sMapX, sMapY, z); } } } 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 ( (gTacticalStatus.uiFlags & LOADING_SAVED_GAME) && guiCurrentSaveGameVersion < 78 ) { 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 SynchronizeItemTempFileVisbleItemsToSectorInfoVisbleItems( TempNode->ubSectorX, TempNode->ubSectorY, TempNode->ubSectorZ, TRUE ); } 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 ( (gTacticalStatus.uiFlags & LOADING_SAVED_GAME) && guiCurrentSaveGameVersion < 78 ) { 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 UpdateWorldItemsTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) { UINT32 uiTotalNumberOfItems=0; std::vector pTotalSectorList;//dnl ch75 271013 BOOLEAN fReturn = GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, &( uiTotalNumberOfItems ), FALSE ); if (fReturn == false) { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("GetNumberOfWorldItemsFromTempItemFile failed" ) ); Assert( fReturn ); } if( uiTotalNumberOfItems > 0 ) { // allocate space for the list pTotalSectorList.resize(uiTotalNumberOfItems);//dnl ch75 271013 LoadWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, pTotalSectorList ); int backup = guiCurrentSaveGameVersion; guiCurrentSaveGameVersion = SAVE_GAME_VERSION; SaveWorldItemsToTempItemFile( sMapX, sMapY, bMapZ, uiTotalNumberOfItems, pTotalSectorList); guiCurrentSaveGameVersion = backup; } 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& pData, BOOLEAN fUpdateVisibleItems )//dnl ch75 271013 { 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 ); if( fUpdateVisibleItems )//dnl ch75 311013 SynchronizeItemTempFileVisbleItemsToSectorInfoVisbleItems( sMapX, sMapY, bMapZ, FALSE ); return( TRUE ); } BOOLEAN LoadWorldItemsFromTempItemFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, std::vector& 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 ]; UINT32 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 ); } BOOLEAN AddItemsToUnLoadedSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ, INT32 sGridNo, UINT32 uiNumberOfItemsToAdd, OBJECTTYPE *pObject, UINT8 ubLevel, UINT16 usFlags, INT8 bRenderZHeightAboveLevel, INT8 bVisible, BOOLEAN fReplaceEntireFile ) { UINT32 uiNumberOfItems=0; std::vector pWorldItems;//dnl ch75 271013 UINT32 cnt; UINT32 uiLoop1=0; if ( uiNumberOfItemsToAdd == 0 && fReplaceEntireFile == FALSE ) { //Moa: nothing to do, so get out of here! return( TRUE ); } if( !GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, &uiNumberOfItems, TRUE ) ) { //Errror getting the numbers of the items from the sector return( FALSE ); } //Allocate memeory for the item pWorldItems.resize(uiNumberOfItems); //Load in the sectors Item Info if( !LoadWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, pWorldItems ) ) { //error reading in the items from the Item mod file return( FALSE ); } //if we are to replace the entire file if( fReplaceEntireFile ) { //first loop through and mark all entries that they dont exists for( cnt=0; cntdata.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; } } //Save the Items to the the file SaveWorldItemsToTempItemFile( 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 ); //Save the Items to the the file if( !SaveWorldItemsToTempItemFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, guiNumWorldItems, gWorldItems ) ) { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in SaveWorldItemsToTempItemFile()" ) ); EnableModifiedFileSetCache(cacheResetValue); return( FALSE ); } //Save the rotting corpse array to the temp rotting corpse file if( !SaveRottingCorpsesToTempCorpseFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) ) { 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 ) { //If there is a file, load in the Items array if( DoesTempFileExistsForMap( SF_ITEM_TEMP_FILE_EXISTS, 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 file, load in the Items array if( DoesTempFileExistsForMap( SF_ITEM_TEMP_FILE_EXISTS, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) ) { fUsedTempFile = TRUE; 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 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 ); } //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 pWorldItems;//dnl ch75 271013 UINT32 cnt; INT32 sNewGridNo; //Get the number of items from the file if( !GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, &uiNumberOfItems, TRUE ) ) { //Error getting the numbers of the items from the sector return( FALSE ); } if( uiNumberOfItems ) { pWorldItems.resize(uiNumberOfItems);//dnl ch75 271013 } else { //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(); //Add each item to the pool, handle below, outside of the if } //there are no items in the file return( TRUE ); } //Load the World Items from the file if( !LoadWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, pWorldItems ) ) { return( FALSE ); } //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 for( 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; } //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 ) { #ifndef USE_VFS UINT32 uiRetVal; //If the Map Temp directory exists, removes the temp files uiRetVal = FileGetAttributes( MAPS_DIR ); if( uiRetVal != 0xFFFFFFFF ) { if( uiRetVal & FILE_ATTRIBUTES_DIRECTORY ) { //Erase the directory if( !EraseDirectory( MAPS_DIR ) ) { //error erasing the temporary maps directory } } } else { if( !MakeFileManDirectory( MAPS_DIR ) ) { //Erro creating the temp map directory AssertMsg( 0, "Error creating the Temp Directory."); } } #else EraseDirectory( MAPS_DIR ); #endif if( fCreateTempDir ) { //Create the initial temp file for the Npc Quote Info InitTempNpcQuoteInfoForNPCFromTempFile(); } return( TRUE ); } BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) { HWFILE hFile; UINT32 uiNumBytesWritten=0; // CHAR8 zTempName[ 128 ]; CHAR8 zMapName[ 128 ]; UINT32 uiNumberOfCorpses=0; INT32 iCount; /* //Convert the current sector location into a file name GetMapFileName( sMapX,sMapY, bMapZ, zTempName, FALSE ); //add the 'r' for 'Rotting Corpses' to the front of the map name sprintf( zMapName, "%s\\r_%s", MAPS_DIR, zTempName); */ 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 ); } //Determine how many rotting corpses there are for(iCount=0; iCount < giNumRottingCorpse; iCount++) { if( gRottingCorpse[iCount].fActivated == TRUE ) uiNumberOfCorpses++; } //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(iCount=0; iCount < giNumRottingCorpse; iCount++) { if( gRottingCorpse[iCount].fActivated == TRUE ) { //Save the RottingCorpse info array FileWrite( hFile, &gRottingCorpse[iCount].def, 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 // SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags |= SF_ROTTING_CORPSE_TEMP_FILE_EXISTS; SetSectorFlag( sMapX, sMapY, bMapZ, SF_ROTTING_CORPSE_TEMP_FILE_EXISTS ); return( TRUE ); } BOOLEAN DeleteTempItemMapFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) { UINT8 bSectorId = 0; // CHAR8 zTempName[ 128 ]; CHAR8 zMapName[ 128 ]; // grab the sector id bSectorId = SECTOR( sMapX, sMapY ); /* //Convert the current sector location into a file name GetMapFileName( sMapX,sMapY, bMapZ, zTempName, FALSE ); sprintf( zMapName, "%s\\r_%s", MAPS_DIR, zTempName); */ 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 ); } // 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 zTempName[ 128 ]; CHAR8 zMapName[ 128 ]; UINT32 uiNumberOfCorpses=0; UINT32 cnt; ROTTING_CORPSE_DEFINITION def; BOOLEAN fDontAddCorpse = FALSE; INT8 bTownId; //Delete the existing rotting corpse array RemoveCorpses( ); /* //Convert the current sector location into a file name GetMapFileName( sMapX,sMapY, bMapZ, zTempName, FALSE ); sprintf( zMapName, "%s\\r_%s", MAPS_DIR, zTempName); */ 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= 30 ) { fDontAddCorpse = TRUE; } } } } } if ( !fDontAddCorpse ) { //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 ); } // Rewritten to load the temp file once, update with the list, and then write it. This was getting insane as items piled up in sectors. // A few dozen read, update, writes was okay but a few hundred is pushing it. BOOLEAN AddWorldItemsToUnLoadedSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ, INT32 sGridNo, UINT32 uiNumberOfItemsToAdd, std::vector& pWorldItem, BOOLEAN fOverWrite )//dnl ch75 271013 { UINT32 uiLoop; UINT32 uiLastItemPos; UINT32 uiNumberOfItems; std::vector pWorldItems;//dnl ch75 271013 if( !GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, &uiNumberOfItems, TRUE ) ) { //Errror getting the numbers of the items from the sector return( FALSE ); } //Allocate memory for the item pWorldItems.resize(uiNumberOfItems);//dnl ch75 271013 //Load in the sectors Item Info if( !LoadWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, pWorldItems ) ) { //error reading in the items from the Item mod file return( FALSE ); } //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; cntubProfile != 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; cntubQuoteActionID = 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 GetNumberOfActiveWorldItemsFromTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, UINT32 *pNumberOfData ) { UINT32 uiNumberOfItems=0; std::vector pWorldItems;//dnl ch75 271013 UINT32 cnt; UINT32 uiNumberOfActive=0; BOOLEAN fFileLoaded = FALSE; UNDERGROUND_SECTORINFO *TempNode = gpUndergroundSectorInfoHead; // // Load in the sectors ITems // //If there is a file, load in the Items array if( bMapZ == 0 ) { if( SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags & SF_ITEM_TEMP_FILE_EXISTS ) fFileLoaded = TRUE; } else { while( TempNode ) { if( TempNode->ubSectorX == sMapX && TempNode->ubSectorY == sMapY && TempNode->ubSectorZ == bMapZ ) { if( TempNode->uiFlags & SF_ITEM_TEMP_FILE_EXISTS ) fFileLoaded = TRUE; break; } TempNode = TempNode->next; } } if( fFileLoaded ) { //Get the number of items from the file if( !GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, &uiNumberOfItems, TRUE ) ) { //Error getting the numbers of the items from the sector return( FALSE ); } //If there items in the data file if( uiNumberOfItems != 0 ) { pWorldItems.resize(uiNumberOfItems);//dnl ch75 271013 //Load the World Items from the file if( !LoadWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, pWorldItems ) ) return( FALSE ); uiNumberOfActive = 0; for( cnt=0; cntubSectorX == sMapX && TempNode->ubSectorY == sMapY && TempNode->ubSectorZ == bMapZ ) { return( (TempNode->uiFlags & uiType ) ? 1 : 0 ); } TempNode = TempNode->next; } } return( FALSE ); } INT16 GetSoldierIDFromAnyMercID(UINT8 ubMercID) { UINT16 cnt; UINT8 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; ubCntubSectorX == (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 ( UINT8 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 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 ) { // if not a player soldier if ( pSoldier->bTeam != gbPlayerNum ) { // this percent of the time, they don't drop stuff they would've dropped in tactical... if ( Random( 100 ) < 75 ) { // 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 ( Item[pSoldier->inv[i].usItem].damageable ) // Madd: drop crappier items on higher difficulty levels { pSoldier->inv[i][0]->data.objectStatus -= (gGameOptions.ubDifficultyLevel - 1) * Random(20); 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! Corpse.ubBodyType = pSoldier->ubBodyType; Corpse.sGridNo = sGridNo; ConvertGridNoToXY( sGridNo, &sXPos, &sYPos ); Corpse.dXPos = (FLOAT)( CenterX( sXPos ) ); Corpse.dYPos = (FLOAT)( CenterY( 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 ) { UNDERGROUND_SECTORINFO *pSector=NULL; //if the sector is above ground if( bMapZ == 0 ) { SectorInfo[ SECTOR( sMapX, sMapY ) ].uiNumberOfWorldItemsInTempFileThatCanBeSeenByPlayer = uiNumberOfItems; } else { //find the underground sector pSector = FindUnderGroundSector( sMapX, sMapY, bMapZ ); if( pSector != NULL ) { //get the number of items pSector->uiNumberOfWorldItemsInTempFileThatCanBeSeenByPlayer = uiNumberOfItems ; } } } //Moa 09/19/13: changed loop upperbound from uiTotalNumberOfRealItems to uiTotalNumberOfItems, // this effectivly removes one entire loop in GetNumberOfActiveWorldItemsFromTempFile and 2 file reads. // also changed type of iCounter from INT32 to UINT32 and for in if-clauses from true to TRUE to get rid of unneccessary casts. void SynchronizeItemTempFileVisbleItemsToSectorInfoVisbleItems( INT16 sMapX, INT16 sMapY, INT8 bMapZ, BOOLEAN fLoadingGame ) { UINT32 uiTotalNumberOfItems = 0;//, uiTotalNumberOfRealItems = 0; std::vector pTotalSectorList;//dnl ch75 271013 UINT32 uiItemCount = 0; UINT32 iCounter = 0; BOOLEAN fReturn; /* // get total number, visable and invisible fReturn = GetNumberOfActiveWorldItemsFromTempFile( sMapX, sMapY, bMapZ, &( uiTotalNumberOfRealItems ) ); if (fReturn == TRUE) { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("GetNumberOfActiveWorldItemsFromTempFile failed" ) ); Assert( fReturn ); }*/ fReturn = GetNumberOfWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, &( uiTotalNumberOfItems ), FALSE ); if (fReturn == TRUE) { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("GetNumberOfWorldItemsFromTempItemFile failed" ) ); Assert( fReturn ); } if( uiTotalNumberOfItems > 0 ) { // allocate space for the list pTotalSectorList.resize(uiTotalNumberOfItems);//dnl ch75 271013 // now load into mem LoadWorldItemsFromTempItemFile( sMapX, sMapY, bMapZ, pTotalSectorList ); } // now run through list and //for( iCounter = 0; ( UINT32 )( iCounter )< uiTotalNumberOfRealItems; iCounter++ ) for( iCounter = 0; iCounter < uiTotalNumberOfItems; iCounter++ ) { // if visible to player, then state fact if( IsMapScreenWorldItemVisibleInMapInventory( &pTotalSectorList[ iCounter ] ) ) { uiItemCount += pTotalSectorList[ iCounter ].object.ubNumberOfObjects; } } #ifdef JA2BETAVERSION if( fLoadingGame && guiCurrentSaveGameVersion >= 86 ) { UINT32 uiReported = GetNumberOfVisibleWorldItemsFromSectorStructureForSector( sMapX, sMapY, bMapZ ); if( uiItemCount != uiReported ) ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"SynchronizeItemTempFile() Error! Reported %d, should be %d", uiReported, uiItemCount ); } #endif //record the number of items SetNumberOfVisibleWorldItemsInSectorStructureForSector( sMapX, sMapY, bMapZ, uiItemCount ); } 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 ); }