
Source code release, imported from: https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code All text files were converted to Unix format.
1374 lines
No EOL
32 KiB
C
1374 lines
No EOL
32 KiB
C
#include "3dc.h"
|
|
|
|
#include "inline.h"
|
|
#include "module.h"
|
|
#include "stratdef.h"
|
|
#include "gamedef.h"
|
|
#include "bh_types.h"
|
|
#include "comp_shp.h"
|
|
#include "dynblock.h"
|
|
|
|
#include "bh_alien.h"
|
|
#include "pvisible.h"
|
|
#include "bh_pred.h"
|
|
#include "bh_xeno.h"
|
|
#include "bh_paq.h"
|
|
#include "bh_queen.h"
|
|
#include "bh_marin.h"
|
|
#include "bh_fhug.h"
|
|
#include "bh_debri.h"
|
|
#include "bh_plachier.h"
|
|
#include "plat_shp.h"
|
|
#include "psnd.h"
|
|
#include "lighting.h"
|
|
#include "pldnet.h"
|
|
#include "bh_dummy.h"
|
|
#include "bh_videoscreen.h"
|
|
#include "bh_plift.h"
|
|
#include "bh_ldoor.h"
|
|
#include "AvP_Menus.h"
|
|
#include "game_statistics.h"
|
|
#include "AvP_UserProfile.h"
|
|
|
|
#include "savegame.h"
|
|
#include "huffman.hpp"
|
|
#include "smacker.h"
|
|
|
|
#define UseLocalAssert Yes
|
|
#include "ourasert.h"
|
|
|
|
static struct
|
|
{
|
|
char* BufferStart;
|
|
char* BufferPos;
|
|
int BufferSize;
|
|
int BufferSpaceLeft;
|
|
int BufferSpaceUsed;
|
|
|
|
} SaveInfo = {0,0,0,0,0};
|
|
|
|
static struct
|
|
{
|
|
char* BufferStart;
|
|
char* BufferPos;
|
|
int BufferSize;
|
|
int BufferSpaceLeft;
|
|
|
|
} LoadInfo = {0,0,0,0};
|
|
|
|
|
|
int LoadGameRequest = SAVELOAD_REQUEST_NONE; //slot number of game to be loaded
|
|
int SaveGameRequest = SAVELOAD_REQUEST_NONE; //slot number of game to be saved
|
|
|
|
|
|
#define NUM_SAVES_FOR_EASY_MODE 8
|
|
#define NUM_SAVES_FOR_MEDIUM_MODE 4
|
|
#define NUM_SAVES_FOR_HARD_MODE 2
|
|
|
|
int NumberOfSavesLeft;
|
|
|
|
|
|
|
|
static void SaveStrategies();
|
|
static void LoadStrategy(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
|
|
static void SaveDeadStrategies();
|
|
static void LoadDeadStrategy(SAVE_BLOCK_HEADER* block);
|
|
|
|
|
|
static void LoadMiscGlobalStuff(SAVE_BLOCK_HEADER* header);
|
|
static void SaveMiscGlobalStuff();
|
|
|
|
/*---------------------------------------------**
|
|
** externs for all the load and save functions **
|
|
**---------------------------------------------*/
|
|
extern void LoadStrategy_LiftDoor(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_LiftDoor(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_ProxDoor(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_ProxDoor(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_SwitchDoor(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_SwitchDoor(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_PlatformLift(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_PlatformLift(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_BinarySwitch(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_BinarySwitch(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_LinkSwitch(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_LinkSwitch(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Generator(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Generator(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadHiveSettings(SAVE_BLOCK_HEADER* header);
|
|
extern void SaveHiveSettings();
|
|
|
|
extern void LoadStrategy_InanimateObject(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_InanimateObject(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_LightFx(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_LightFx(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_PlacedSound(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_PlacedSound(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Message(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Message(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_MissionComplete(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_MissionComplete(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_TrackObject(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_TrackObject(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Fan(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Fan(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_PlacedLight(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_PlacedLight(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_VideoScreen(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_VideoScreen(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_DeathVolume(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_DeathVolume(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_ParticleGenerator(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_ParticleGenerator(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_SelfDestruct(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_SelfDestruct(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Alien(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Alien(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Corpse(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Corpse(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_FaceHugger(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_FaceHugger(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Marine(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Marine(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadMarineSquadState(SAVE_BLOCK_HEADER* header);
|
|
extern void SaveMarineSquadState();
|
|
|
|
extern void LoadStrategy_PlacedHierarchy(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_PlacedHierarchy(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Predator(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Predator(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Xenoborg(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Xenoborg(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Queen(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Queen(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Player(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Player(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Autogun(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Autogun(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_HierarchicalDebris(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_HierarchicalDebris(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void Load_Decals(SAVE_BLOCK_HEADER* header);
|
|
extern void Save_Decals();
|
|
|
|
extern void Load_Particles(SAVE_BLOCK_HEADER* header);
|
|
extern void Save_Particles();
|
|
|
|
extern void Load_VolumetricExplosions(SAVE_BLOCK_HEADER* header);
|
|
extern void Save_VolumetricExplosions();
|
|
|
|
extern void Load_PheromoneTrails(SAVE_BLOCK_HEADER* header);
|
|
extern void Save_PheromoneTrails();
|
|
|
|
extern void Load_LightElements(SAVE_BLOCK_HEADER* header);
|
|
extern void Save_LightElements();
|
|
|
|
extern void Load_MessageHistory(SAVE_BLOCK_HEADER* header);
|
|
extern void Save_MessageHistory();
|
|
|
|
extern void LoadStrategy_Grenade(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Grenade(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_FlareGrenade(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_FlareGrenade(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_ProxGrenade(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_ProxGrenade(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Rocket(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Rocket(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_PPPlasmaBolt(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_PPPlasmaBolt(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_PredatorEnergyBolt(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_PredatorEnergyBolt(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_PulseGrenade(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_PulseGrenade(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_ClusterGrenade(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_ClusterGrenade(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Molotov(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Molotov(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_PredatorDisc(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_PredatorDisc(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_SpearBolt(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_SpearBolt(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Grapple(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Grapple(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_Debris(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Debris(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadLevelHeader(SAVE_BLOCK_HEADER* header);
|
|
extern void SaveLevelHeader();
|
|
|
|
extern void Load_WeaponsCGlobals(SAVE_BLOCK_HEADER* header);
|
|
extern void Save_WeaponsCGlobals();
|
|
|
|
extern void Load_SoundState_NoRef(SAVE_BLOCK_HEADER* header);
|
|
extern void Save_SoundsWithNoReference();
|
|
|
|
extern void LoadStrategy_Frisbee(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_Frisbee(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern void LoadStrategy_FrisbeeEnergyBolt(SAVE_BLOCK_STRATEGY_HEADER* header);
|
|
extern void SaveStrategy_FrisbeeEnergyBolt(STRATEGYBLOCK* sbPtr);
|
|
|
|
extern int DebuggingCommandsActive;
|
|
|
|
/*-----------------------------------------------------**
|
|
** end of externs for all the load and save functions **
|
|
**-----------------------------------------------------*/
|
|
|
|
extern void DisplaySavesLeft();
|
|
|
|
/*
|
|
Functions for converting between ai modules and their indeces.
|
|
They don't really belong here , but they are only used by loading/saving at
|
|
the moment.
|
|
*/
|
|
|
|
struct aimodule * GetPointerFromAIModuleIndex(int index)
|
|
{
|
|
|
|
if(index>=0 && index<AIModuleArraySize)
|
|
{
|
|
return &AIModuleArray[index];
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
int GetIndexFromAIModulePointer(struct aimodule* module)
|
|
{
|
|
if(module)
|
|
return module->m_index;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void* GetPointerForSaveBlock(unsigned int size)
|
|
{
|
|
void* retPointer;
|
|
|
|
//see if we need to enlarge the buffer to allow for this block
|
|
if(size > SaveInfo.BufferSpaceLeft)
|
|
{
|
|
//need more space
|
|
int spaceNeeded = SaveInfo.BufferSpaceUsed + size;
|
|
//buffer incremented in lots of 100000 bytes (more or less)
|
|
int newBufferSize = ((spaceNeeded /100000)+1)*100000;
|
|
|
|
//allocate the memory
|
|
SaveInfo.BufferStart = (char*) realloc(SaveInfo.BufferStart,newBufferSize);
|
|
|
|
//correct the position etc.
|
|
SaveInfo.BufferPos = SaveInfo.BufferStart + SaveInfo.BufferSpaceUsed;
|
|
SaveInfo.BufferSpaceLeft += (newBufferSize - SaveInfo.BufferSize);
|
|
SaveInfo.BufferSize = newBufferSize;
|
|
|
|
}
|
|
|
|
//get the pointer to the next part of the save buffer
|
|
retPointer = (void*)SaveInfo.BufferPos;
|
|
|
|
SaveInfo.BufferSpaceUsed += size;
|
|
SaveInfo.BufferSpaceLeft -= size;
|
|
SaveInfo.BufferPos += size;
|
|
|
|
return retPointer;
|
|
}
|
|
|
|
|
|
|
|
static void InitSaveGame()
|
|
{
|
|
SaveInfo.BufferPos = SaveInfo.BufferStart;
|
|
SaveInfo.BufferSpaceLeft = SaveInfo.BufferSize;
|
|
SaveInfo.BufferSpaceUsed = 0;
|
|
|
|
}
|
|
|
|
|
|
static BOOL SaveGameAllowed()
|
|
{
|
|
PLAYER_STATUS *playerStatusPtr;
|
|
|
|
//can't save in multiplayer (or skirmish)
|
|
if(AvP.Network != I_No_Network) return FALSE;
|
|
|
|
//check player's state
|
|
if(!Player) return FALSE;
|
|
if(!Player->ObStrategyBlock) return FALSE;
|
|
if(!Player->ObStrategyBlock->SBdataptr) return FALSE;
|
|
|
|
playerStatusPtr = (PLAYER_STATUS*)Player->ObStrategyBlock->SBdataptr;
|
|
|
|
//player must be alive , and not face hugged
|
|
if(!playerStatusPtr->IsAlive) return FALSE;
|
|
if(playerStatusPtr->MyFaceHugger) return FALSE;
|
|
|
|
//cheating?
|
|
if(DebuggingCommandsActive || CheatMode_Active!=CHEATMODE_NONACTIVE)
|
|
{
|
|
NewOnScreenMessage(GetTextString(TEXTSTRING_SAVEGAME_NOTALLOWED));
|
|
return FALSE;
|
|
}
|
|
|
|
//now check the number of saves left
|
|
//first some validation
|
|
|
|
if(NumberOfSavesLeft<0) NumberOfSavesLeft =0;
|
|
switch(AvP.Difficulty)
|
|
{
|
|
case I_Easy :
|
|
if(NumberOfSavesLeft > NUM_SAVES_FOR_EASY_MODE)
|
|
NumberOfSavesLeft = NUM_SAVES_FOR_EASY_MODE;
|
|
break;
|
|
case I_Medium :
|
|
if(NumberOfSavesLeft > NUM_SAVES_FOR_MEDIUM_MODE)
|
|
NumberOfSavesLeft = NUM_SAVES_FOR_MEDIUM_MODE;
|
|
break;
|
|
case I_Hard :
|
|
case I_Impossible :
|
|
if(NumberOfSavesLeft > NUM_SAVES_FOR_HARD_MODE)
|
|
NumberOfSavesLeft = NUM_SAVES_FOR_HARD_MODE;
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
if(!NumberOfSavesLeft)
|
|
{
|
|
NewOnScreenMessage(GetTextString(TEXTSTRING_SAVEGAME_NOSAVESLEFT));
|
|
return FALSE;
|
|
}
|
|
|
|
NumberOfSavesLeft--;
|
|
|
|
|
|
//saving is allowed then
|
|
return TRUE;
|
|
|
|
|
|
}
|
|
|
|
void SaveGame()
|
|
{
|
|
char filename[100];
|
|
HANDLE file;
|
|
DWORD bytes_written;
|
|
int headerLength;
|
|
HuffmanPackage *packagePtr;
|
|
|
|
//make sure there is a save request
|
|
if(SaveGameRequest == SAVELOAD_REQUEST_NONE) return;
|
|
|
|
if(SaveGameRequest<0 || SaveGameRequest>=NUMBER_OF_SAVE_SLOTS)
|
|
{
|
|
SaveGameRequest = SAVELOAD_REQUEST_NONE;
|
|
return;
|
|
}
|
|
|
|
//check that we are allowed to save at this point
|
|
if(!SaveGameAllowed())
|
|
{
|
|
//cancel request
|
|
SaveGameRequest = SAVELOAD_REQUEST_NONE;
|
|
return;
|
|
}
|
|
|
|
InitSaveGame();
|
|
|
|
SaveLevelHeader();
|
|
|
|
headerLength = SaveInfo.BufferSpaceUsed;
|
|
|
|
SaveDeadStrategies();
|
|
|
|
SaveStrategies();
|
|
|
|
SaveHiveSettings();
|
|
|
|
SaveMarineSquadState();
|
|
|
|
SaveMiscGlobalStuff();
|
|
|
|
Save_SoundsWithNoReference();
|
|
|
|
//save particles etc.
|
|
Save_Decals();
|
|
Save_Particles();
|
|
Save_VolumetricExplosions();
|
|
Save_PheromoneTrails();
|
|
Save_LightElements();
|
|
|
|
Save_MessageHistory();
|
|
|
|
Save_WeaponsCGlobals();
|
|
|
|
|
|
//get the filename
|
|
GetFilenameForSaveSlot(SaveGameRequest,filename);
|
|
|
|
//clear the save request
|
|
SaveGameRequest = SAVELOAD_REQUEST_NONE;
|
|
|
|
//write the file
|
|
file = CreateFile(filename,GENERIC_WRITE, 0, 0, CREATE_ALWAYS,FILE_FLAG_RANDOM_ACCESS, 0);
|
|
|
|
if (file == INVALID_HANDLE_VALUE)
|
|
{
|
|
GLOBALASSERT("Error saving file"==0);
|
|
return;
|
|
}
|
|
|
|
WriteFile(file,SaveInfo.BufferStart,headerLength,&bytes_written,0);
|
|
|
|
packagePtr = HuffmanCompression(SaveInfo.BufferStart+headerLength,SaveInfo.BufferSpaceUsed-headerLength);
|
|
|
|
WriteFile(file,packagePtr,packagePtr->CompressedDataSize+sizeof(HuffmanPackage),&bytes_written,0);
|
|
|
|
CloseHandle(file);
|
|
|
|
|
|
NewOnScreenMessage(GetTextString(TEXTSTRING_SAVEGAME_GAMESAVED));
|
|
DisplaySavesLeft();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void EndLoadGame()
|
|
{
|
|
if(LoadInfo.BufferStart)
|
|
{
|
|
DeallocateMem(LoadInfo.BufferStart);
|
|
}
|
|
LoadInfo.BufferStart = NULL;
|
|
LoadInfo.BufferPos = NULL;
|
|
LoadInfo.BufferSize = 0;
|
|
LoadInfo.BufferSpaceLeft = 0;
|
|
|
|
}
|
|
|
|
extern SAVE_SLOT_HEADER SaveGameSlot[];
|
|
|
|
extern int AlienEpisodeToPlay;
|
|
extern int MarineEpisodeToPlay;
|
|
extern int PredatorEpisodeToPlay;
|
|
BOOL ValidateLevelForLoadGameRequest(SAVE_SLOT_HEADER* save_slot)
|
|
{
|
|
//see if we will need to change level
|
|
if(save_slot->Species != AvP.PlayerType) return FALSE;
|
|
|
|
//probably need to reload if in cheat mode
|
|
if(CheatMode_Active!=CHEATMODE_NONACTIVE) return FALSE;
|
|
|
|
switch(save_slot->Species)
|
|
{
|
|
case I_Marine :
|
|
if(save_slot->Episode != MarineEpisodeToPlay) return FALSE;;
|
|
break;
|
|
|
|
case I_Alien :
|
|
if(save_slot->Episode != AlienEpisodeToPlay) return FALSE;
|
|
break;
|
|
|
|
case I_Predator :
|
|
if(save_slot->Episode != PredatorEpisodeToPlay) return FALSE;
|
|
break;
|
|
}
|
|
//certainly need to change level if in multiplayer (or skirmish)
|
|
if(AvP.Network != I_No_Network) return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void LoadSavedGame()
|
|
{
|
|
SAVE_SLOT_HEADER* save_slot;
|
|
char filename[100];
|
|
HANDLE file;
|
|
BOOL terminal_error = FALSE;
|
|
unsigned int bytes_read;
|
|
|
|
if(LoadGameRequest == SAVELOAD_REQUEST_NONE) return;
|
|
|
|
if(LoadGameRequest<0 || LoadGameRequest>=NUMBER_OF_SAVE_SLOTS)
|
|
{
|
|
LoadGameRequest = SAVELOAD_REQUEST_NONE;
|
|
return;
|
|
}
|
|
|
|
|
|
//get the save_slot
|
|
save_slot = &SaveGameSlot[LoadGameRequest];
|
|
|
|
//make sure the slot is being used
|
|
ScanSaveSlots();
|
|
if(!save_slot->SlotUsed) return;
|
|
|
|
///make sure we're on the right level etc.
|
|
if(!ValidateLevelForLoadGameRequest(save_slot))
|
|
{
|
|
AvP.MainLoopRunning = FALSE;
|
|
return;
|
|
}
|
|
{
|
|
extern int GlobalFrameCounter;
|
|
if(!GlobalFrameCounter) return;
|
|
}
|
|
//set the difficulty level and restart the level
|
|
AvP.Difficulty = save_slot->Difficulty;
|
|
RestartLevel();
|
|
|
|
//get the filename for the save slot
|
|
GetFilenameForSaveSlot(LoadGameRequest,filename);
|
|
|
|
//we can now clear the load request
|
|
LoadGameRequest = SAVELOAD_REQUEST_NONE;
|
|
|
|
//load the file
|
|
file = CreateFile(filename,GENERIC_READ, 0, 0, OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS, 0);
|
|
|
|
|
|
if(file==INVALID_HANDLE_VALUE)
|
|
{
|
|
//failed to load
|
|
EndLoadGame();
|
|
return;
|
|
}
|
|
|
|
LoadInfo.BufferSize = GetFileSize(file,0);
|
|
if(!LoadInfo.BufferSize)
|
|
{
|
|
CloseHandle(file);
|
|
EndLoadGame();
|
|
return;
|
|
}
|
|
|
|
//allocate buffer , and read file into memory
|
|
LoadInfo.BufferStart = (char*) AllocateMem(LoadInfo.BufferSize);
|
|
ReadFile(file,LoadInfo.BufferStart,LoadInfo.BufferSize,(LPDWORD)&bytes_read,0);
|
|
CloseHandle(file);
|
|
|
|
|
|
|
|
LoadInfo.BufferPos = LoadInfo.BufferStart;
|
|
LoadInfo.BufferSpaceLeft = LoadInfo.BufferSize;
|
|
|
|
// attempt to access level header
|
|
{
|
|
//read the next header
|
|
SAVE_BLOCK_HEADER* header = (SAVE_BLOCK_HEADER*) LoadInfo.BufferPos;
|
|
|
|
if(header->size>LoadInfo.BufferSpaceLeft)
|
|
{
|
|
//oh dear, dodgy file
|
|
GLOBALASSERT("Invalid save game header size"==0);
|
|
terminal_error = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//go to the next header
|
|
LoadInfo.BufferPos += header->size;
|
|
LoadInfo.BufferSpaceLeft -= header->size;
|
|
|
|
switch(header->type)
|
|
{
|
|
case SaveBlock_MainHeader :
|
|
LoadLevelHeader(header);
|
|
break;
|
|
default:
|
|
GLOBALASSERT("Unrecognized save block type"==0);
|
|
terminal_error = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!terminal_error)
|
|
{
|
|
if (!strncmp (LoadInfo.BufferPos, "REBCRIF1", 8))
|
|
{
|
|
char *uncompressedBufferPtr = (char*)HuffmanDecompress((HuffmanPackage*)(LoadInfo.BufferPos));
|
|
LoadInfo.BufferSpaceLeft = ((HuffmanPackage*)LoadInfo.BufferPos)->UncompressedDataSize;
|
|
DeallocateMem(LoadInfo.BufferStart);
|
|
LoadInfo.BufferStart=uncompressedBufferPtr;
|
|
LoadInfo.BufferPos = LoadInfo.BufferStart;
|
|
}
|
|
else
|
|
{
|
|
terminal_error = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
//go through loading things
|
|
while(LoadInfo.BufferSpaceLeft && !terminal_error)
|
|
{
|
|
//read the next header
|
|
SAVE_BLOCK_HEADER* header = (SAVE_BLOCK_HEADER*) LoadInfo.BufferPos;
|
|
|
|
if(header->size>LoadInfo.BufferSpaceLeft)
|
|
{
|
|
//oh dear, dodgy file
|
|
GLOBALASSERT("Invalid save game header size"==0);
|
|
terminal_error = TRUE;
|
|
break;
|
|
}
|
|
|
|
//go to the next header
|
|
LoadInfo.BufferPos += header->size;
|
|
LoadInfo.BufferSpaceLeft -= header->size;
|
|
|
|
|
|
switch(header->type)
|
|
{
|
|
case SaveBlock_MainHeader :
|
|
LoadLevelHeader(header);
|
|
break;
|
|
|
|
case SaveBlock_DeadStrategy :
|
|
LoadDeadStrategy(header);
|
|
break;
|
|
|
|
case SaveBlock_Strategy :
|
|
LoadStrategy((SAVE_BLOCK_STRATEGY_HEADER*) header);
|
|
break;
|
|
|
|
case SaveBlock_Track :
|
|
//all these should be used up by the various strategy loaders
|
|
GLOBALASSERT("Unexpected track save block"==0);
|
|
break;
|
|
|
|
case SaveBlock_Hierarchy :
|
|
//all these should be used up by the various strategy loaders
|
|
GLOBALASSERT("Unexpected hierarchy save block"==0);
|
|
break;
|
|
|
|
case SaveBlock_HierarchySection :
|
|
//all these should be used up by the various strategy loaders
|
|
GLOBALASSERT("Unexpected hierarchy section save block"==0);
|
|
break;
|
|
|
|
case SaveBlock_HierarchyTween :
|
|
//all these should be used up by the various strategy loaders
|
|
GLOBALASSERT("Unexpected hierarchy tween save block"==0);
|
|
break;
|
|
|
|
case SaveBlock_HierarchyDecals :
|
|
//all these should be used up by the various strategy loaders
|
|
GLOBALASSERT("Unexpected hierarchy decal save block"==0);
|
|
break;
|
|
|
|
case SaveBlock_HierarchyDelta :
|
|
//all these should be used up by the various strategy loaders
|
|
GLOBALASSERT("Unexpected hierarchy delta save block"==0);
|
|
break;
|
|
|
|
case SaveBlock_GlobalHive :
|
|
LoadHiveSettings(header);
|
|
break;
|
|
|
|
case SaveBlock_MiscGlobal :
|
|
LoadMiscGlobalStuff(header);
|
|
break;
|
|
|
|
case SaveBlock_MarineSquad :
|
|
LoadMarineSquadState(header);
|
|
break;
|
|
|
|
case SaveBlock_Particles :
|
|
Load_Particles(header);
|
|
break;
|
|
|
|
case SaveBlock_Decals :
|
|
Load_Decals(header);
|
|
break;
|
|
|
|
case SaveBlock_PheromoneTrail :
|
|
Load_PheromoneTrails(header);
|
|
break;
|
|
|
|
case SaveBlock_VolumetricExplosions :
|
|
Load_VolumetricExplosions(header);
|
|
break;
|
|
|
|
case SaveBlock_LightElements :
|
|
Load_LightElements(header);
|
|
break;
|
|
|
|
case SaveBlock_MessageHistory :
|
|
Load_MessageHistory(header);
|
|
break;
|
|
|
|
case SaveBlock_WeaponsCGlobals :
|
|
Load_WeaponsCGlobals(header);
|
|
break;
|
|
|
|
case SaveBlock_SoundState :
|
|
Load_SoundState_NoRef(header);
|
|
break;
|
|
|
|
|
|
default :
|
|
GLOBALASSERT("Unrecognized save block type"==0);
|
|
terminal_error = TRUE;
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if(terminal_error)
|
|
{
|
|
//the save file was screwed , restart the level to be on the safe side
|
|
RestartLevel();
|
|
NewOnScreenMessage(GetTextString(TEXTSTRING_SAVEGAME_ERRORLOADING));
|
|
}
|
|
|
|
EndLoadGame();
|
|
|
|
RemoveDestroyedStrategyBlocks();
|
|
|
|
//make sure all the containing modules are set properly
|
|
{
|
|
extern int NumActiveStBlocks;
|
|
extern STRATEGYBLOCK *ActiveStBlockList[];
|
|
|
|
int sbIndex = 0;
|
|
STRATEGYBLOCK *sbPtr;
|
|
|
|
/* loop thro' the strategy block list, looking for objects that need to have
|
|
their visibilities managed ... */
|
|
while(sbIndex < NumActiveStBlocks)
|
|
{
|
|
sbPtr = ActiveStBlockList[sbIndex++];
|
|
if(sbPtr->maintainVisibility && sbPtr->DynPtr)
|
|
{
|
|
MODULE* newModule;
|
|
newModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), (sbPtr->containingModule));
|
|
|
|
if(newModule) sbPtr->containingModule = newModule;
|
|
}
|
|
}
|
|
}
|
|
|
|
AllNewModuleHandler();
|
|
|
|
DoObjectVisibilities();
|
|
|
|
ResetFrameCounter();
|
|
|
|
if(!terminal_error)
|
|
{
|
|
NewOnScreenMessage(GetTextString(TEXTSTRING_SAVEGAME_GAMELOADED));
|
|
DisplaySavesLeft();
|
|
}
|
|
|
|
}
|
|
|
|
SAVE_BLOCK_HEADER* GetNextBlockIfOfType(SAVE_BLOCK_TYPE type)
|
|
{
|
|
SAVE_BLOCK_HEADER* header;
|
|
|
|
GLOBALASSERT(LoadInfo.BufferPos);
|
|
|
|
if(LoadInfo.BufferSpaceLeft==0)
|
|
{
|
|
//no more blocks left
|
|
return 0;
|
|
}
|
|
|
|
//look at the next header in the buffer
|
|
header = (SAVE_BLOCK_HEADER*) LoadInfo.BufferPos;
|
|
if(header->size>LoadInfo.BufferSpaceLeft)
|
|
{
|
|
//oh dear, dodgy file
|
|
GLOBALASSERT("Invalid save game header size"==0);
|
|
return 0;
|
|
}
|
|
|
|
//see if the header is of the type that we are after
|
|
if(header->type == type)
|
|
{
|
|
//okay , advance the buffer position , and return this header
|
|
LoadInfo.BufferPos += header->size;
|
|
LoadInfo.BufferSpaceLeft -= header->size;
|
|
|
|
return header;
|
|
}
|
|
else
|
|
{
|
|
//out of luck
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
static void SaveStrategies()
|
|
{
|
|
int i;
|
|
|
|
for(i=0;i<NumActiveStBlocks;i++)
|
|
{
|
|
STRATEGYBLOCK* sbPtr = ActiveStBlockList[i];
|
|
|
|
switch(sbPtr->I_SBtype)
|
|
{
|
|
case I_BehaviourMarinePlayer :
|
|
SaveStrategy_Player(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourLiftDoor :
|
|
SaveStrategy_LiftDoor(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourProximityDoor :
|
|
SaveStrategy_ProxDoor(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourSwitchDoor :
|
|
SaveStrategy_SwitchDoor(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourPlatform :
|
|
SaveStrategy_PlatformLift(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourBinarySwitch :
|
|
SaveStrategy_BinarySwitch(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourLinkSwitch :
|
|
SaveStrategy_LinkSwitch(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourGenerator :
|
|
SaveStrategy_Generator(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourInanimateObject :
|
|
SaveStrategy_InanimateObject(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourLightFX :
|
|
SaveStrategy_LightFx(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourPlacedSound :
|
|
SaveStrategy_PlacedSound(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourMessage :
|
|
SaveStrategy_Message(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourMissionComplete :
|
|
SaveStrategy_MissionComplete(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourTrackObject :
|
|
SaveStrategy_TrackObject(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourFan :
|
|
SaveStrategy_Fan(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourPlacedLight :
|
|
SaveStrategy_PlacedLight(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourVideoScreen :
|
|
SaveStrategy_VideoScreen(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourSelfDestruct :
|
|
SaveStrategy_SelfDestruct(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourParticleGenerator :
|
|
SaveStrategy_ParticleGenerator(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourDeathVolume :
|
|
SaveStrategy_DeathVolume(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourAlien :
|
|
SaveStrategy_Alien(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourNetCorpse :
|
|
SaveStrategy_Corpse(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourFaceHugger :
|
|
SaveStrategy_FaceHugger(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourMarine :
|
|
SaveStrategy_Marine(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourPlacedHierarchy :
|
|
SaveStrategy_PlacedHierarchy(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourPredator :
|
|
SaveStrategy_Predator(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourXenoborg :
|
|
SaveStrategy_Xenoborg(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourQueenAlien :
|
|
SaveStrategy_Queen(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourAutoGun :
|
|
SaveStrategy_Autogun(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourHierarchicalFragment :
|
|
SaveStrategy_HierarchicalDebris(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourGrenade :
|
|
SaveStrategy_Grenade(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourFlareGrenade :
|
|
SaveStrategy_FlareGrenade(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourProximityGrenade :
|
|
SaveStrategy_ProxGrenade(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourRocket :
|
|
SaveStrategy_Rocket(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourPPPlasmaBolt :
|
|
SaveStrategy_PPPlasmaBolt(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourPredatorEnergyBolt :
|
|
SaveStrategy_PredatorEnergyBolt(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourFrisbeeEnergyBolt :
|
|
SaveStrategy_FrisbeeEnergyBolt(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourPulseGrenade :
|
|
SaveStrategy_PulseGrenade(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourClusterGrenade :
|
|
SaveStrategy_ClusterGrenade(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourMolotov :
|
|
SaveStrategy_Molotov(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourPredatorDisc_SeekTrack :
|
|
SaveStrategy_PredatorDisc(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourSpeargunBolt :
|
|
SaveStrategy_SpearBolt(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourGrapplingHook :
|
|
SaveStrategy_Grapple(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourFragment :
|
|
SaveStrategy_Debris(sbPtr);
|
|
break;
|
|
|
|
case I_BehaviourFrisbee :
|
|
SaveStrategy_Frisbee(sbPtr);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void LoadStrategy(SAVE_BLOCK_STRATEGY_HEADER* header)
|
|
{
|
|
switch(header->bhvr_type)
|
|
{
|
|
case I_BehaviourMarinePlayer :
|
|
LoadStrategy_Player(header);
|
|
break;
|
|
|
|
case I_BehaviourLiftDoor :
|
|
LoadStrategy_LiftDoor(header);
|
|
break;
|
|
|
|
case I_BehaviourProximityDoor :
|
|
LoadStrategy_ProxDoor(header);
|
|
break;
|
|
|
|
case I_BehaviourSwitchDoor :
|
|
LoadStrategy_SwitchDoor(header);
|
|
break;
|
|
|
|
case I_BehaviourPlatform :
|
|
LoadStrategy_PlatformLift(header);
|
|
break;
|
|
|
|
case I_BehaviourBinarySwitch :
|
|
LoadStrategy_BinarySwitch(header);
|
|
break;
|
|
|
|
case I_BehaviourLinkSwitch :
|
|
LoadStrategy_LinkSwitch(header);
|
|
break;
|
|
|
|
case I_BehaviourGenerator :
|
|
LoadStrategy_Generator(header);
|
|
break;
|
|
|
|
case I_BehaviourInanimateObject :
|
|
LoadStrategy_InanimateObject(header);
|
|
break;
|
|
|
|
case I_BehaviourLightFX :
|
|
LoadStrategy_LightFx(header);
|
|
break;
|
|
|
|
case I_BehaviourPlacedSound :
|
|
LoadStrategy_PlacedSound(header);
|
|
break;
|
|
|
|
case I_BehaviourMessage :
|
|
LoadStrategy_Message(header);
|
|
break;
|
|
|
|
case I_BehaviourMissionComplete :
|
|
LoadStrategy_MissionComplete(header);
|
|
break;
|
|
|
|
case I_BehaviourTrackObject :
|
|
LoadStrategy_TrackObject(header);
|
|
break;
|
|
|
|
case I_BehaviourFan :
|
|
LoadStrategy_Fan(header);
|
|
break;
|
|
|
|
case I_BehaviourPlacedLight :
|
|
LoadStrategy_PlacedLight(header);
|
|
break;
|
|
|
|
case I_BehaviourVideoScreen :
|
|
LoadStrategy_VideoScreen(header);
|
|
break;
|
|
|
|
case I_BehaviourSelfDestruct :
|
|
LoadStrategy_SelfDestruct(header);
|
|
break;
|
|
|
|
case I_BehaviourParticleGenerator :
|
|
LoadStrategy_ParticleGenerator(header);
|
|
break;
|
|
|
|
case I_BehaviourDeathVolume :
|
|
LoadStrategy_DeathVolume(header);
|
|
break;
|
|
|
|
case I_BehaviourAlien :
|
|
LoadStrategy_Alien(header);
|
|
break;
|
|
|
|
case I_BehaviourNetCorpse :
|
|
LoadStrategy_Corpse(header);
|
|
break;
|
|
|
|
case I_BehaviourFaceHugger :
|
|
LoadStrategy_FaceHugger(header);
|
|
break;
|
|
|
|
case I_BehaviourMarine :
|
|
LoadStrategy_Marine(header);
|
|
break;
|
|
|
|
case I_BehaviourPlacedHierarchy :
|
|
LoadStrategy_PlacedHierarchy(header);
|
|
break;
|
|
|
|
case I_BehaviourPredator :
|
|
LoadStrategy_Predator(header);
|
|
break;
|
|
|
|
case I_BehaviourXenoborg :
|
|
LoadStrategy_Xenoborg(header);
|
|
break;
|
|
|
|
case I_BehaviourQueenAlien :
|
|
LoadStrategy_Queen(header);
|
|
break;
|
|
|
|
case I_BehaviourAutoGun :
|
|
LoadStrategy_Autogun(header);
|
|
break;
|
|
|
|
case I_BehaviourHierarchicalFragment :
|
|
LoadStrategy_HierarchicalDebris(header);
|
|
break;
|
|
|
|
case I_BehaviourGrenade :
|
|
LoadStrategy_Grenade(header);
|
|
break;
|
|
|
|
case I_BehaviourFlareGrenade :
|
|
LoadStrategy_FlareGrenade(header);
|
|
break;
|
|
|
|
case I_BehaviourProximityGrenade :
|
|
LoadStrategy_ProxGrenade(header);
|
|
break;
|
|
|
|
case I_BehaviourRocket :
|
|
LoadStrategy_Rocket(header);
|
|
break;
|
|
|
|
case I_BehaviourPPPlasmaBolt :
|
|
LoadStrategy_PPPlasmaBolt(header);
|
|
break;
|
|
|
|
case I_BehaviourPredatorEnergyBolt :
|
|
LoadStrategy_PredatorEnergyBolt(header);
|
|
break;
|
|
|
|
case I_BehaviourFrisbeeEnergyBolt :
|
|
LoadStrategy_FrisbeeEnergyBolt(header);
|
|
break;
|
|
|
|
case I_BehaviourPulseGrenade :
|
|
LoadStrategy_PulseGrenade(header);
|
|
break;
|
|
|
|
case I_BehaviourClusterGrenade :
|
|
LoadStrategy_ClusterGrenade(header);
|
|
break;
|
|
|
|
case I_BehaviourMolotov :
|
|
LoadStrategy_Molotov(header);
|
|
break;
|
|
|
|
case I_BehaviourPredatorDisc_SeekTrack :
|
|
LoadStrategy_PredatorDisc(header);
|
|
break;
|
|
|
|
case I_BehaviourSpeargunBolt :
|
|
LoadStrategy_SpearBolt(header);
|
|
break;
|
|
|
|
case I_BehaviourGrapplingHook :
|
|
LoadStrategy_Grapple(header);
|
|
break;
|
|
|
|
case I_BehaviourFragment :
|
|
LoadStrategy_Debris(header);
|
|
break;
|
|
|
|
case I_BehaviourFrisbee :
|
|
LoadStrategy_Frisbee(header);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*------------------------------------**
|
|
** Loading and saving dead strategies **
|
|
**------------------------------------*/
|
|
|
|
typedef struct dead_strategy_save_block
|
|
{
|
|
SAVE_BLOCK_HEADER header;
|
|
char SBname[SB_NAME_LENGTH];
|
|
|
|
}DEAD_STRATEGY_SAVE_BLOCK;
|
|
|
|
static void SaveDeadStrategies()
|
|
{
|
|
extern STRATEGYBLOCK FreeStBlockData[];
|
|
int i;
|
|
STRATEGYBLOCK* sbPtr = &FreeStBlockData[0];
|
|
|
|
//search for all the strategies that existed at the start , and have been destroyed
|
|
for(i=0;i<maxstblocks;i++ , sbPtr++)
|
|
{
|
|
if(sbPtr->SBflags.destroyed_but_preserved)
|
|
{
|
|
DEAD_STRATEGY_SAVE_BLOCK* block;
|
|
GET_SAVE_BLOCK_POINTER(block);
|
|
|
|
block->header.type = SaveBlock_DeadStrategy;
|
|
block->header.size = sizeof(*block);
|
|
|
|
COPY_NAME(block->SBname,sbPtr->SBname);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
static void LoadDeadStrategy(SAVE_BLOCK_HEADER* header)
|
|
{
|
|
DEAD_STRATEGY_SAVE_BLOCK* block = (DEAD_STRATEGY_SAVE_BLOCK*) header;
|
|
|
|
STRATEGYBLOCK* sbPtr = FindSBWithName(block->SBname);
|
|
if(sbPtr)
|
|
{
|
|
DestroyAnyStrategyBlock(sbPtr);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------------------**
|
|
** Loading and saving miscellaneos global rubbish that has nowhere else to live **
|
|
**--------------------------------------------------------------------------------*/
|
|
|
|
extern unsigned int IncrementalSBname;
|
|
extern int PlayersMaxHeightWhilstNotInContactWithGround;
|
|
|
|
|
|
typedef struct misc_global_save_block
|
|
{
|
|
SAVE_BLOCK_HEADER header;
|
|
|
|
unsigned int IncrementalSBname;
|
|
AvP_GameStats CurrentGameStatistics;
|
|
int PlayersMaxHeightWhilstNotInContactWithGround;
|
|
int NumberOfSavesLeft;
|
|
|
|
int FMV_MessageNumber;
|
|
int FMV_FrameNumber;
|
|
|
|
}MISC_GLOBAL_SAVE_BLOCK;
|
|
|
|
static void LoadMiscGlobalStuff(SAVE_BLOCK_HEADER* header)
|
|
{
|
|
MISC_GLOBAL_SAVE_BLOCK* block;
|
|
block = (MISC_GLOBAL_SAVE_BLOCK*) header;
|
|
|
|
if(block->header.size != sizeof(*block)) return;
|
|
|
|
IncrementalSBname = block->IncrementalSBname;
|
|
CurrentGameStatistics = block->CurrentGameStatistics;
|
|
PlayersMaxHeightWhilstNotInContactWithGround = block->PlayersMaxHeightWhilstNotInContactWithGround;
|
|
NumberOfSavesLeft = block-> NumberOfSavesLeft;
|
|
|
|
StartFMVAtFrame(block->FMV_MessageNumber,block->FMV_FrameNumber);
|
|
}
|
|
|
|
static void SaveMiscGlobalStuff()
|
|
{
|
|
MISC_GLOBAL_SAVE_BLOCK* block;
|
|
block = GetPointerForSaveBlock(sizeof(*block));
|
|
|
|
//fill in the header
|
|
block->header.type = SaveBlock_MiscGlobal;
|
|
block->header.size = sizeof(*block);
|
|
|
|
block->IncrementalSBname = IncrementalSBname;
|
|
block->CurrentGameStatistics = CurrentGameStatistics;
|
|
block->PlayersMaxHeightWhilstNotInContactWithGround = PlayersMaxHeightWhilstNotInContactWithGround;
|
|
block->NumberOfSavesLeft = NumberOfSavesLeft;
|
|
|
|
GetFMVInformation(&block->FMV_MessageNumber,&block->FMV_FrameNumber);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern void DisplaySavesLeft()
|
|
{
|
|
char text [100];
|
|
|
|
sprintf(text, "%s: %d",GetTextString(TEXTSTRING_SAVEGAME_SAVESLEFT),NumberOfSavesLeft);
|
|
|
|
NewOnScreenMessage(text);
|
|
}
|
|
|
|
|
|
|
|
|
|
extern void ResetNumberOfSaves()
|
|
{
|
|
switch(AvP.Difficulty)
|
|
{
|
|
case I_Easy :
|
|
NumberOfSavesLeft = NUM_SAVES_FOR_EASY_MODE;
|
|
break;
|
|
case I_Medium :
|
|
NumberOfSavesLeft = NUM_SAVES_FOR_MEDIUM_MODE;
|
|
break;
|
|
case I_Hard :
|
|
case I_Impossible :
|
|
NumberOfSavesLeft = NUM_SAVES_FOR_HARD_MODE;
|
|
break;
|
|
|
|
}
|
|
} |