Files
devilution/Source/loadsave.cpp
qndel 1c9256d5d5 rename SetDead (#2249)
* rename SetDead

* rename in comparer
2021-08-21 03:04:37 -05:00

726 lines
16 KiB
C++

/**
* @file loadsave.cpp
*
* Implementation of save game functionality.
*/
#include "all.h"
BYTE *tbuff;
static char BLoad()
{
return *tbuff++;
}
static int WLoad()
{
int rv = *tbuff++ << 24;
rv |= *tbuff++ << 16;
rv |= *tbuff++ << 8;
rv |= *tbuff++;
return rv;
}
static int ILoad()
{
int rv = *tbuff++ << 24;
rv |= *tbuff++ << 16;
rv |= *tbuff++ << 8;
rv |= *tbuff++;
return rv;
}
static BOOL OLoad()
{
if (*tbuff++ == TRUE)
return TRUE;
else
return FALSE;
}
static void LoadPlayer(int i)
{
memcpy(&plr[i], tbuff, sizeof(*plr) - (10 * sizeof(void *)));
tbuff += sizeof(*plr) - (10 * sizeof(void *)); // omit last 10 pointers
}
static void LoadMonster(int i)
{
memcpy(&monster[i], tbuff, sizeof(*monster) - (3 * sizeof(void *)));
tbuff += sizeof(*monster) - (3 * sizeof(void *)); // omit last 3 pointers
SyncMonsterAnim(i);
}
static void LoadMissile(int i)
{
memcpy(&missile[i], tbuff, sizeof(*missile));
tbuff += sizeof(*missile);
}
static void LoadObject(int i)
{
memcpy(&object[i], tbuff, sizeof(*object));
tbuff += sizeof(*object);
}
static void LoadItem(int i)
{
memcpy(&item[i], tbuff, sizeof(*item));
tbuff += sizeof(*item);
GetItemFrm(i);
}
static void LoadPremium(int i)
{
memcpy(&premiumitem[i], tbuff, sizeof(*premiumitem));
tbuff += sizeof(*premiumitem);
}
static void LoadQuest(int i)
{
memcpy(&quests[i], tbuff, sizeof(*quests));
tbuff += sizeof(*quests);
ReturnLvlX = WLoad();
ReturnLvlY = WLoad();
ReturnLvl = WLoad();
ReturnLvlT = WLoad();
DoomQuestState = WLoad();
}
static void LoadLighting(int i)
{
memcpy(&LightList[i], tbuff, sizeof(*LightList));
tbuff += sizeof(*LightList);
}
static void LoadVision(int i)
{
memcpy(&VisionList[i], tbuff, sizeof(*VisionList));
tbuff += sizeof(*VisionList);
}
static void LoadPortal(int i)
{
memcpy(&portal[i], tbuff, sizeof(*portal));
tbuff += sizeof(*portal);
}
/**
* @brief Load game state
* @param firstflag Can be set to false if we are simply reloading the current game
*/
void LoadGame(BOOL firstflag)
{
int i, j;
DWORD dwLen;
char szName[MAX_PATH];
BYTE *LoadBuff;
int _ViewX, _ViewY, _nummonsters, _numitems, _nummissiles, _nobjects;
FreeGameMem();
pfile_remove_temp_files();
pfile_get_game_name(szName);
LoadBuff = pfile_read(szName, &dwLen);
tbuff = LoadBuff;
#ifdef HELLFIRE
if (ILoad() != 'HELF')
#elif defined(SPAWN)
if (ILoad() != 'SHAR')
#else
if (ILoad() != 'RETL')
#endif
app_fatal("Invalid save file");
setlevel = OLoad();
setlvlnum = WLoad();
currlevel = WLoad();
leveltype = WLoad();
_ViewX = WLoad();
_ViewY = WLoad();
invflag = OLoad();
chrflag = OLoad();
_nummonsters = WLoad();
_numitems = WLoad();
_nummissiles = WLoad();
_nobjects = WLoad();
for (i = 0; i < NUMLEVELS; i++) {
glSeedTbl[i] = ILoad();
gnLevelTypeTbl[i] = WLoad();
}
LoadPlayer(myplr);
#ifdef HELLFIRE
gnDifficulty = plr[myplr].pDifficulty;
if (gnDifficulty < DIFF_NORMAL || gnDifficulty > DIFF_HELL)
gnDifficulty = DIFF_NORMAL;
#endif
for (i = 0; i < MAXQUESTS; i++)
LoadQuest(i);
for (i = 0; i < MAXPORTAL; i++)
LoadPortal(i);
LoadGameLevel(firstflag, ENTRY_LOAD);
SyncInitPlr(myplr);
SyncPlrAnim(myplr);
ViewX = _ViewX;
ViewY = _ViewY;
nummonsters = _nummonsters;
numitems = _numitems;
nummissiles = _nummissiles;
nobjects = _nobjects;
for (i = 0; i < MAXMONSTERS; i++)
monstkills[i] = ILoad();
if (leveltype != DTYPE_TOWN) {
for (i = 0; i < MAXMONSTERS; i++)
monstactive[i] = WLoad();
for (i = 0; i < nummonsters; i++)
LoadMonster(monstactive[i]);
for (i = 0; i < MAXMISSILES; i++)
missileactive[i] = BLoad();
for (i = 0; i < MAXMISSILES; i++)
missileavail[i] = BLoad();
for (i = 0; i < nummissiles; i++)
LoadMissile(missileactive[i]);
for (i = 0; i < MAXOBJECTS; i++)
objectactive[i] = BLoad();
for (i = 0; i < MAXOBJECTS; i++)
objectavail[i] = BLoad();
for (i = 0; i < nobjects; i++)
LoadObject(objectactive[i]);
for (i = 0; i < nobjects; i++)
SyncObjectAnim(objectactive[i]);
numlights = WLoad();
for (i = 0; i < MAXLIGHTS; i++)
lightactive[i] = BLoad();
for (i = 0; i < numlights; i++)
LoadLighting(lightactive[i]);
visionid = WLoad();
numvision = WLoad();
for (i = 0; i < numvision; i++)
LoadVision(i);
}
for (i = 0; i < MAXITEMS; i++)
itemactive[i] = BLoad();
for (i = 0; i < MAXITEMS; i++)
itemavail[i] = BLoad();
for (i = 0; i < numitems; i++)
LoadItem(itemactive[i]);
for (i = 0; i < 128; i++)
UniqueItemFlag[i] = OLoad();
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dLight[i][j] = BLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dFlags[i][j] = BLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dPlayer[i][j] = BLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dItem[i][j] = BLoad();
}
if (leveltype != DTYPE_TOWN) {
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dMonster[i][j] = WLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dDead[i][j] = BLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dObject[i][j] = BLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dLight[i][j] = BLoad(); // BUGFIX: dLight got loaded already
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dPreLight[i][j] = BLoad();
}
for (j = 0; j < DMAXY; j++) {
for (i = 0; i < DMAXX; i++)
automapview[i][j] = OLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dMissile[i][j] = BLoad();
}
}
numpremium = WLoad();
premiumlevel = WLoad();
for (i = 0; i < SMITH_PREMIUM_ITEMS; i++)
LoadPremium(i);
automapflag = OLoad();
AutoMapScale = WLoad();
mem_free_dbg(LoadBuff);
AutomapZoomReset();
ResyncQuests();
if (leveltype != DTYPE_TOWN)
ProcessLightList();
RedoPlayerVision();
ProcessVisionList();
missiles_process_charge();
ResetPal();
SetCursor_(CURSOR_HAND);
gbProcessPlayers = TRUE;
}
static void BSave(char v)
{
*tbuff++ = v;
}
static void WSave(int v)
{
*tbuff++ = v >> 24;
*tbuff++ = v >> 16;
*tbuff++ = v >> 8;
*tbuff++ = v;
}
static void ISave(int v)
{
*tbuff++ = v >> 24;
*tbuff++ = v >> 16;
*tbuff++ = v >> 8;
*tbuff++ = v;
}
static void OSave(BOOL v)
{
if (v != FALSE)
*tbuff++ = TRUE;
else
*tbuff++ = FALSE;
}
static void SavePlayer(int i)
{
memcpy(tbuff, &plr[i], sizeof(*plr) - (10 * sizeof(void *)));
tbuff += sizeof(*plr) - (10 * sizeof(void *)); // omit last 10 pointers
}
static void SaveMonster(int i)
{
memcpy(tbuff, &monster[i], sizeof(*monster) - (3 * sizeof(void *)));
tbuff += sizeof(*monster) - (3 * sizeof(void *)); // omit last 3 pointers
}
static void SaveMissile(int i)
{
memcpy(tbuff, &missile[i], sizeof(*missile));
tbuff += sizeof(*missile);
}
static void SaveObject(int i)
{
memcpy(tbuff, &object[i], sizeof(*object));
tbuff += sizeof(*object);
}
static void SaveItem(int i)
{
memcpy(tbuff, &item[i], sizeof(*item));
tbuff += sizeof(*item);
}
static void SavePremium(int i)
{
memcpy(tbuff, &premiumitem[i], sizeof(*premiumitem));
tbuff += sizeof(*premiumitem);
}
static void SaveQuest(int i)
{
memcpy(tbuff, &quests[i], sizeof(*quests));
tbuff += sizeof(*quests);
WSave(ReturnLvlX);
WSave(ReturnLvlY);
WSave(ReturnLvl);
WSave(ReturnLvlT);
WSave(DoomQuestState);
}
static void SaveLighting(int i)
{
memcpy(tbuff, &LightList[i], sizeof(*LightList));
tbuff += sizeof(*LightList);
}
static void SaveVision(int i)
{
memcpy(tbuff, &VisionList[i], sizeof(*VisionList));
tbuff += sizeof(*VisionList);
}
static void SavePortal(int i)
{
memcpy(tbuff, &portal[i], sizeof(*portal));
tbuff += sizeof(*portal);
}
void SaveGame()
{
int i, j;
char szName[MAX_PATH];
DWORD dwLen = codec_get_encoded_len(FILEBUFF);
BYTE *SaveBuff = DiabloAllocPtr(dwLen);
tbuff = SaveBuff;
#ifdef HELLFIRE
ISave('HELF');
#elif defined(SPAWN)
ISave('SHAR');
#else
ISave('RETL');
#endif
OSave(setlevel);
WSave(setlvlnum);
WSave(currlevel);
WSave(leveltype);
WSave(ViewX);
WSave(ViewY);
OSave(invflag);
OSave(chrflag);
WSave(nummonsters);
WSave(numitems);
WSave(nummissiles);
WSave(nobjects);
for (i = 0; i < NUMLEVELS; i++) {
ISave(glSeedTbl[i]);
WSave(gnLevelTypeTbl[i]);
}
#ifdef HELLFIRE
plr[myplr].pDifficulty = gnDifficulty;
#endif
SavePlayer(myplr);
for (i = 0; i < MAXQUESTS; i++)
SaveQuest(i);
for (i = 0; i < MAXPORTAL; i++)
SavePortal(i);
for (i = 0; i < MAXMONSTERS; i++)
ISave(monstkills[i]);
if (leveltype != DTYPE_TOWN) {
for (i = 0; i < MAXMONSTERS; i++)
WSave(monstactive[i]);
for (i = 0; i < nummonsters; i++)
SaveMonster(monstactive[i]);
for (i = 0; i < MAXMISSILES; i++)
BSave(missileactive[i]);
for (i = 0; i < MAXMISSILES; i++)
BSave(missileavail[i]);
for (i = 0; i < nummissiles; i++)
SaveMissile(missileactive[i]);
for (i = 0; i < MAXOBJECTS; i++)
BSave(objectactive[i]);
for (i = 0; i < MAXOBJECTS; i++)
BSave(objectavail[i]);
for (i = 0; i < nobjects; i++)
SaveObject(objectactive[i]);
WSave(numlights);
for (i = 0; i < MAXLIGHTS; i++)
BSave(lightactive[i]);
for (i = 0; i < numlights; i++)
SaveLighting(lightactive[i]);
WSave(visionid);
WSave(numvision);
for (i = 0; i < numvision; i++)
SaveVision(i);
}
for (i = 0; i < MAXITEMS; i++)
BSave(itemactive[i]);
for (i = 0; i < MAXITEMS; i++)
BSave(itemavail[i]);
for (i = 0; i < numitems; i++)
SaveItem(itemactive[i]);
for (i = 0; i < 128; i++)
OSave(UniqueItemFlag[i]);
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dLight[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dFlags[i][j] & ~(BFLAG_MISSILE | BFLAG_VISIBLE | BFLAG_DEAD_PLAYER));
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dPlayer[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dItem[i][j]);
}
if (leveltype != DTYPE_TOWN) {
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
WSave(dMonster[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dDead[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dObject[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dLight[i][j]); // BUGFIX: dLight got saved already
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dPreLight[i][j]);
}
for (j = 0; j < DMAXY; j++) {
for (i = 0; i < DMAXX; i++)
OSave(automapview[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dMissile[i][j]);
}
}
WSave(numpremium);
WSave(premiumlevel);
for (i = 0; i < SMITH_PREMIUM_ITEMS; i++)
SavePremium(i);
OSave(automapflag);
WSave(AutoMapScale);
pfile_get_game_name(szName);
dwLen = codec_get_encoded_len(tbuff - SaveBuff);
pfile_write_save_file(szName, SaveBuff, tbuff - SaveBuff, dwLen);
mem_free_dbg(SaveBuff);
gbValidSaveFile = TRUE;
pfile_rename_temp_to_perm();
pfile_write_hero();
}
void SaveLevel()
{
int i, j;
char szName[MAX_PATH];
int dwLen;
BYTE *SaveBuff;
if (currlevel == 0)
glSeedTbl[0] = GetRndSeed();
dwLen = codec_get_encoded_len(FILEBUFF);
SaveBuff = DiabloAllocPtr(dwLen);
tbuff = SaveBuff;
if (leveltype != DTYPE_TOWN) {
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dDead[i][j]);
}
}
WSave(nummonsters);
WSave(numitems);
WSave(nobjects);
if (leveltype != DTYPE_TOWN) {
for (i = 0; i < MAXMONSTERS; i++)
WSave(monstactive[i]);
for (i = 0; i < nummonsters; i++)
SaveMonster(monstactive[i]);
for (i = 0; i < MAXOBJECTS; i++)
BSave(objectactive[i]);
for (i = 0; i < MAXOBJECTS; i++)
BSave(objectavail[i]);
for (i = 0; i < nobjects; i++)
SaveObject(objectactive[i]);
}
for (i = 0; i < MAXITEMS; i++)
BSave(itemactive[i]);
for (i = 0; i < MAXITEMS; i++)
BSave(itemavail[i]);
for (i = 0; i < numitems; i++)
SaveItem(itemactive[i]);
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dFlags[i][j] & ~(BFLAG_MISSILE | BFLAG_VISIBLE | BFLAG_DEAD_PLAYER));
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dItem[i][j]);
}
if (leveltype != DTYPE_TOWN) {
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
WSave(dMonster[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dObject[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dLight[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dPreLight[i][j]);
}
for (j = 0; j < DMAXY; j++) {
for (i = 0; i < DMAXX; i++)
OSave(automapview[i][j]);
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
BSave(dMissile[i][j]);
}
}
GetTempLevelNames(szName);
dwLen = codec_get_encoded_len(tbuff - SaveBuff);
pfile_write_save_file(szName, SaveBuff, tbuff - SaveBuff, dwLen);
mem_free_dbg(SaveBuff);
if (!setlevel)
plr[myplr]._pLvlVisited[currlevel] = TRUE;
else
plr[myplr]._pSLvlVisited[setlvlnum] = TRUE;
}
void LoadLevel()
{
int i, j;
DWORD dwLen;
char szName[MAX_PATH];
BYTE *LoadBuff;
GetPermLevelNames(szName);
LoadBuff = pfile_read(szName, &dwLen);
tbuff = LoadBuff;
if (leveltype != DTYPE_TOWN) {
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dDead[i][j] = BLoad();
}
SyncUniqDead();
}
nummonsters = WLoad();
numitems = WLoad();
nobjects = WLoad();
if (leveltype != DTYPE_TOWN) {
for (i = 0; i < MAXMONSTERS; i++)
monstactive[i] = WLoad();
for (i = 0; i < nummonsters; i++)
LoadMonster(monstactive[i]);
for (i = 0; i < MAXOBJECTS; i++)
objectactive[i] = BLoad();
for (i = 0; i < MAXOBJECTS; i++)
objectavail[i] = BLoad();
for (i = 0; i < nobjects; i++)
LoadObject(objectactive[i]);
for (i = 0; i < nobjects; i++)
SyncObjectAnim(objectactive[i]);
}
for (i = 0; i < MAXITEMS; i++)
itemactive[i] = BLoad();
for (i = 0; i < MAXITEMS; i++)
itemavail[i] = BLoad();
for (i = 0; i < numitems; i++)
LoadItem(itemactive[i]);
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dFlags[i][j] = BLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dItem[i][j] = BLoad();
}
if (leveltype != DTYPE_TOWN) {
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dMonster[i][j] = WLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dObject[i][j] = BLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dLight[i][j] = BLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dPreLight[i][j] = BLoad();
}
for (j = 0; j < DMAXY; j++) {
for (i = 0; i < DMAXX; i++)
automapview[i][j] = OLoad();
}
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++)
dMissile[i][j] = 0; /// BUGFIX: supposed to load saved missiles with "BLoad()"?
}
}
AutomapZoomReset();
ResyncQuests();
SyncPortals();
dolighting = TRUE;
for (i = 0; i < MAX_PLRS; i++) {
if (plr[i].plractive && currlevel == plr[i].plrlevel)
LightList[plr[i]._plid]._lunflag = TRUE;
}
mem_free_dbg(LoadBuff);
}