/** * @file loadsave.cpp * * Implementation of save game functionality. */ #include "all.h" DEVILUTION_BEGIN_NAMESPACE BYTE *tbuff; bool gbIsHellfireSaveGame; int giNumberOfLevels; int giNumberQuests; int giNumberOfSmithPremiumItems; static char BLoad() { return *tbuff++; } #define WLoad ILoad static int ILoad() { int rv = *tbuff++ << 24; rv |= *tbuff++ << 16; rv |= *tbuff++ << 8; rv |= *tbuff++; return rv; } static bool LoadBool8() { if (*tbuff++ == TRUE) return TRUE; else return FALSE; } static bool LoadBool32() { Uint32 buf; memcpy(&buf, tbuff, 4); tbuff += 4; return buf != 0; } static void CopyBytes(const void *src, const int n, void *dst) { memcpy(dst, src, n); tbuff += n; } static void CopyChar(const void *src, void *dst) { *(char *)dst = *(char *)src; tbuff += 1; } static void CopyShort(const void *src, void *dst) { unsigned short buf; memcpy(&buf, src, 2); buf = SwapLE16(buf); memcpy(dst, &buf, 2); tbuff += 2; } static void CopyShorts(const void *src, const int n, void *dst) { const unsigned short *s = reinterpret_cast(src); unsigned short *d = reinterpret_cast(dst); for (int i = 0; i < n; i++) { CopyShort(s, d); ++d; ++s; } } static void CopyInt(const void *src, void *dst) { unsigned int buf; memcpy(&buf, src, 4); buf = SwapLE32(buf); memcpy(dst, &buf, 4); tbuff += 4; } static void CopyInts(const void *src, const int n, void *dst) { const unsigned int *s = reinterpret_cast(src); const unsigned int *d = reinterpret_cast(dst); for (int i = 0; i < n; i++) { CopyInt(s, (void *)d); ++d; ++s; } } static void CopyInt64(const void *src, void *dst) { unsigned long long buf; memcpy(&buf, src, 8); buf = SDL_SwapLE64(buf); memcpy(dst, &buf, 8); tbuff += 8; } static void LoadItemData(ItemStruct *pItem) { CopyInt(tbuff, &pItem->_iSeed); CopyShort(tbuff, &pItem->_iCreateInfo); tbuff += 2; // Alignment CopyInt(tbuff, &pItem->_itype); CopyInt(tbuff, &pItem->_ix); CopyInt(tbuff, &pItem->_iy); CopyInt(tbuff, &pItem->_iAnimFlag); tbuff += 4; // Skip pointer _iAnimData CopyInt(tbuff, &pItem->_iAnimLen); CopyInt(tbuff, &pItem->_iAnimFrame); CopyInt(tbuff, &pItem->_iAnimWidth); CopyInt(tbuff, &pItem->_iAnimWidth2); CopyInt(tbuff, &pItem->_iDelFlag); CopyChar(tbuff, &pItem->_iSelFlag); tbuff += 3; // Alignment CopyInt(tbuff, &pItem->_iPostDraw); CopyInt(tbuff, &pItem->_iIdentified); CopyChar(tbuff, &pItem->_iMagical); CopyBytes(tbuff, 64, &pItem->_iName); CopyBytes(tbuff, 64, &pItem->_iIName); CopyChar(tbuff, &pItem->_iLoc); CopyChar(tbuff, &pItem->_iClass); tbuff += 1; // Alignment CopyInt(tbuff, &pItem->_iCurs); CopyInt(tbuff, &pItem->_ivalue); CopyInt(tbuff, &pItem->_iIvalue); CopyInt(tbuff, &pItem->_iMinDam); CopyInt(tbuff, &pItem->_iMaxDam); CopyInt(tbuff, &pItem->_iAC); CopyInt(tbuff, &pItem->_iFlags); CopyInt(tbuff, &pItem->_iMiscId); CopyInt(tbuff, &pItem->_iSpell); CopyInt(tbuff, &pItem->_iCharges); CopyInt(tbuff, &pItem->_iMaxCharges); CopyInt(tbuff, &pItem->_iDurability); CopyInt(tbuff, &pItem->_iMaxDur); CopyInt(tbuff, &pItem->_iPLDam); CopyInt(tbuff, &pItem->_iPLToHit); CopyInt(tbuff, &pItem->_iPLAC); CopyInt(tbuff, &pItem->_iPLStr); CopyInt(tbuff, &pItem->_iPLMag); CopyInt(tbuff, &pItem->_iPLDex); CopyInt(tbuff, &pItem->_iPLVit); CopyInt(tbuff, &pItem->_iPLFR); CopyInt(tbuff, &pItem->_iPLLR); CopyInt(tbuff, &pItem->_iPLMR); CopyInt(tbuff, &pItem->_iPLMana); CopyInt(tbuff, &pItem->_iPLHP); CopyInt(tbuff, &pItem->_iPLDamMod); CopyInt(tbuff, &pItem->_iPLGetHit); CopyInt(tbuff, &pItem->_iPLLight); CopyChar(tbuff, &pItem->_iSplLvlAdd); CopyChar(tbuff, &pItem->_iRequest); tbuff += 2; // Alignment CopyInt(tbuff, &pItem->_iUid); CopyInt(tbuff, &pItem->_iFMinDam); CopyInt(tbuff, &pItem->_iFMaxDam); CopyInt(tbuff, &pItem->_iLMinDam); CopyInt(tbuff, &pItem->_iLMaxDam); CopyInt(tbuff, &pItem->_iPLEnAc); CopyChar(tbuff, &pItem->_iPrePower); CopyChar(tbuff, &pItem->_iSufPower); tbuff += 2; // Alignment CopyInt(tbuff, &pItem->_iVAdd1); CopyInt(tbuff, &pItem->_iVMult1); CopyInt(tbuff, &pItem->_iVAdd2); CopyInt(tbuff, &pItem->_iVMult2); CopyChar(tbuff, &pItem->_iMinStr); CopyChar(tbuff, &pItem->_iMinMag); CopyChar(tbuff, &pItem->_iMinDex); tbuff += 1; // Alignment CopyInt(tbuff, &pItem->_iStatFlag); CopyInt(tbuff, &pItem->IDidx); if (!gbIsHellfireSaveGame) { pItem->IDidx = RemapItemIdxFromDiablo(pItem->IDidx); } CopyInt(tbuff, &pItem->offs016C); if (gbIsHellfireSaveGame) CopyInt(tbuff, &pItem->_iDamAcFlags); else pItem->_iDamAcFlags = 0; } static void LoadItems(const int n, ItemStruct *pItem) { for (int i = 0; i < n; i++) { LoadItemData(&pItem[i]); } } static void LoadPlayer(int i) { PlayerStruct *pPlayer = &plr[i]; CopyInt(tbuff, &pPlayer->_pmode); CopyBytes(tbuff, MAX_PATH_LENGTH, pPlayer->walkpath); CopyBytes(tbuff, 1, &pPlayer->plractive); tbuff += 2; // Alignment CopyInt(tbuff, &pPlayer->destAction); CopyInt(tbuff, &pPlayer->destParam1); CopyInt(tbuff, &pPlayer->destParam2); CopyInt(tbuff, &pPlayer->destParam3); CopyInt(tbuff, &pPlayer->destParam4); CopyInt(tbuff, &pPlayer->plrlevel); CopyInt(tbuff, &pPlayer->_px); CopyInt(tbuff, &pPlayer->_py); CopyInt(tbuff, &pPlayer->_pfutx); CopyInt(tbuff, &pPlayer->_pfuty); CopyInt(tbuff, &pPlayer->_ptargx); CopyInt(tbuff, &pPlayer->_ptargy); CopyInt(tbuff, &pPlayer->_pownerx); CopyInt(tbuff, &pPlayer->_pownery); CopyInt(tbuff, &pPlayer->_poldx); CopyInt(tbuff, &pPlayer->_poldy); CopyInt(tbuff, &pPlayer->_pxoff); CopyInt(tbuff, &pPlayer->_pyoff); CopyInt(tbuff, &pPlayer->_pxvel); CopyInt(tbuff, &pPlayer->_pyvel); CopyInt(tbuff, &pPlayer->_pdir); CopyInt(tbuff, &pPlayer->_nextdir); CopyInt(tbuff, &pPlayer->_pgfxnum); tbuff += 4; // Skip pointer _pAnimData CopyInt(tbuff, &pPlayer->_pAnimDelay); CopyInt(tbuff, &pPlayer->_pAnimCnt); CopyInt(tbuff, &pPlayer->_pAnimLen); CopyInt(tbuff, &pPlayer->_pAnimFrame); CopyInt(tbuff, &pPlayer->_pAnimWidth); CopyInt(tbuff, &pPlayer->_pAnimWidth2); tbuff += 4; // Skip _peflag CopyInt(tbuff, &pPlayer->_plid); CopyInt(tbuff, &pPlayer->_pvid); CopyInt(tbuff, &pPlayer->_pSpell); CopyChar(tbuff, &pPlayer->_pSplType); CopyChar(tbuff, &pPlayer->_pSplFrom); tbuff += 2; // Alignment CopyInt(tbuff, &pPlayer->_pTSpell); CopyChar(tbuff, &pPlayer->_pTSplType); tbuff += 3; // Alignment CopyInt(tbuff, &pPlayer->_pRSpell); CopyChar(tbuff, &pPlayer->_pRSplType); tbuff += 3; // Alignment CopyInt(tbuff, &pPlayer->_pSBkSpell); CopyChar(tbuff, &pPlayer->_pSBkSplType); CopyBytes(tbuff, 64, &pPlayer->_pSplLvl); tbuff += 7; // Alignment CopyInt64(tbuff, &pPlayer->_pMemSpells); CopyInt64(tbuff, &pPlayer->_pAblSpells); CopyInt64(tbuff, &pPlayer->_pScrlSpells); CopyChar(tbuff, &pPlayer->_pSpellFlags); tbuff += 3; // Alignment CopyInts(tbuff, 4, &pPlayer->_pSplHotKey); CopyBytes(tbuff, 4, &pPlayer->_pSplTHotKey); CopyInt(tbuff, &pPlayer->_pwtype); CopyChar(tbuff, &pPlayer->_pBlockFlag); CopyChar(tbuff, &pPlayer->_pInvincible); CopyChar(tbuff, &pPlayer->_pLightRad); CopyChar(tbuff, &pPlayer->_pLvlChanging); CopyBytes(tbuff, PLR_NAME_LEN, &pPlayer->_pName); CopyChar(tbuff, &pPlayer->_pClass); tbuff += 3; // Alignment CopyInt(tbuff, &pPlayer->_pStrength); CopyInt(tbuff, &pPlayer->_pBaseStr); CopyInt(tbuff, &pPlayer->_pMagic); CopyInt(tbuff, &pPlayer->_pBaseMag); CopyInt(tbuff, &pPlayer->_pDexterity); CopyInt(tbuff, &pPlayer->_pBaseDex); CopyInt(tbuff, &pPlayer->_pVitality); CopyInt(tbuff, &pPlayer->_pBaseVit); CopyInt(tbuff, &pPlayer->_pStatPts); CopyInt(tbuff, &pPlayer->_pDamageMod); CopyInt(tbuff, &pPlayer->_pBaseToBlk); if (pPlayer->_pBaseToBlk == 0) { pPlayer->_pBaseToBlk = ToBlkTbl[pPlayer->_pClass]; } CopyInt(tbuff, &pPlayer->_pHPBase); CopyInt(tbuff, &pPlayer->_pMaxHPBase); CopyInt(tbuff, &pPlayer->_pHitPoints); CopyInt(tbuff, &pPlayer->_pMaxHP); CopyInt(tbuff, &pPlayer->_pHPPer); CopyInt(tbuff, &pPlayer->_pManaBase); CopyInt(tbuff, &pPlayer->_pMaxManaBase); CopyInt(tbuff, &pPlayer->_pMana); CopyInt(tbuff, &pPlayer->_pMaxMana); CopyInt(tbuff, &pPlayer->_pManaPer); CopyChar(tbuff, &pPlayer->_pLevel); CopyChar(tbuff, &pPlayer->_pMaxLvl); tbuff += 2; // Alignment CopyInt(tbuff, &pPlayer->_pExperience); CopyInt(tbuff, &pPlayer->_pMaxExp); CopyInt(tbuff, &pPlayer->_pNextExper); CopyChar(tbuff, &pPlayer->_pArmorClass); CopyChar(tbuff, &pPlayer->_pMagResist); CopyChar(tbuff, &pPlayer->_pFireResist); CopyChar(tbuff, &pPlayer->_pLghtResist); CopyInt(tbuff, &pPlayer->_pGold); CopyInt(tbuff, &pPlayer->_pInfraFlag); CopyInt(tbuff, &pPlayer->_pVar1); CopyInt(tbuff, &pPlayer->_pVar2); CopyInt(tbuff, &pPlayer->_pVar3); CopyInt(tbuff, &pPlayer->_pVar4); CopyInt(tbuff, &pPlayer->_pVar5); CopyInt(tbuff, &pPlayer->_pVar6); CopyInt(tbuff, &pPlayer->_pVar7); CopyInt(tbuff, &pPlayer->_pVar8); CopyBytes(tbuff, giNumberOfLevels, &pPlayer->_pLvlVisited); CopyBytes(tbuff, giNumberOfLevels, &pPlayer->_pSLvlVisited); tbuff += 2; // Alignment CopyInt(tbuff, &pPlayer->_pGFXLoad); tbuff += 4 * 8; // Skip pointers _pNAnim CopyInt(tbuff, &pPlayer->_pNFrames); CopyInt(tbuff, &pPlayer->_pNWidth); tbuff += 4 * 8; // Skip pointers _pWAnim CopyInt(tbuff, &pPlayer->_pWFrames); CopyInt(tbuff, &pPlayer->_pWWidth); tbuff += 4 * 8; // Skip pointers _pAAnim CopyInt(tbuff, &pPlayer->_pAFrames); CopyInt(tbuff, &pPlayer->_pAWidth); CopyInt(tbuff, &pPlayer->_pAFNum); tbuff += 4 * 8; // Skip pointers _pLAnim tbuff += 4 * 8; // Skip pointers _pFAnim tbuff += 4 * 8; // Skip pointers _pTAnim CopyInt(tbuff, &pPlayer->_pSFrames); CopyInt(tbuff, &pPlayer->_pSWidth); CopyInt(tbuff, &pPlayer->_pSFNum); tbuff += 4 * 8; // Skip pointers _pHAnim CopyInt(tbuff, &pPlayer->_pHFrames); CopyInt(tbuff, &pPlayer->_pHWidth); tbuff += 4 * 8; // Skip pointers _pDAnim CopyInt(tbuff, &pPlayer->_pDFrames); CopyInt(tbuff, &pPlayer->_pDWidth); tbuff += 4 * 8; // Skip pointers _pBAnim CopyInt(tbuff, &pPlayer->_pBFrames); CopyInt(tbuff, &pPlayer->_pBWidth); LoadItems(NUM_INVLOC, pPlayer->InvBody); LoadItems(NUM_INV_GRID_ELEM, pPlayer->InvList); CopyInt(tbuff, &pPlayer->_pNumInv); CopyBytes(tbuff, NUM_INV_GRID_ELEM, pPlayer->InvGrid); LoadItems(MAXBELTITEMS, pPlayer->SpdList); LoadItemData(&pPlayer->HoldItem); CopyInt(tbuff, &pPlayer->_pIMinDam); CopyInt(tbuff, &pPlayer->_pIMaxDam); CopyInt(tbuff, &pPlayer->_pIAC); CopyInt(tbuff, &pPlayer->_pIBonusDam); CopyInt(tbuff, &pPlayer->_pIBonusToHit); CopyInt(tbuff, &pPlayer->_pIBonusAC); CopyInt(tbuff, &pPlayer->_pIBonusDamMod); tbuff += 4; // Alignment CopyInt64(tbuff, &pPlayer->_pISpells); CopyInt(tbuff, &pPlayer->_pIFlags); CopyInt(tbuff, &pPlayer->_pIGetHit); CopyChar(tbuff, &pPlayer->_pISplLvlAdd); CopyChar(tbuff, &pPlayer->_pISplCost); tbuff += 2; // Alignment CopyInt(tbuff, &pPlayer->_pISplDur); CopyInt(tbuff, &pPlayer->_pIEnAc); CopyInt(tbuff, &pPlayer->_pIFMinDam); CopyInt(tbuff, &pPlayer->_pIFMaxDam); CopyInt(tbuff, &pPlayer->_pILMinDam); CopyInt(tbuff, &pPlayer->_pILMaxDam); CopyInt(tbuff, &pPlayer->_pOilType); CopyChar(tbuff, &pPlayer->pTownWarps); CopyChar(tbuff, &pPlayer->pDungMsgs); CopyChar(tbuff, &pPlayer->pLvlLoad); if (gbIsHellfireSaveGame) { CopyChar(tbuff, &pPlayer->pDungMsgs2); pPlayer->pBattleNet = false; } else { pPlayer->pDungMsgs2 = 0; CopyChar(tbuff, &pPlayer->pBattleNet); } CopyChar(tbuff, &pPlayer->pManaShield); if (gbIsHellfireSaveGame) { CopyChar(tbuff, &pPlayer->pOriginalCathedral); } else { tbuff += 1; pPlayer->pOriginalCathedral = true; } CopyBytes(tbuff, 2, &pPlayer->bReserved); CopyShort(tbuff, &pPlayer->wReflections); CopyShorts(tbuff, 7, &pPlayer->wReserved); CopyInt(tbuff, &pPlayer->pDiabloKillLevel); CopyInt(tbuff, &pPlayer->pDifficulty); CopyInt(tbuff, &pPlayer->pDamAcFlags); CopyInts(tbuff, 5, &pPlayer->dwReserved); // Omit pointer _pNData // Omit pointer _pWData // Omit pointer _pAData // Omit pointer _pLData // Omit pointer _pFData // Omit pointer _pTData // Omit pointer _pHData // Omit pointer _pDData // Omit pointer _pBData // Omit pointer pReserved } static void LoadMonster(int i) { MonsterStruct *pMonster = &monster[i]; CopyInt(tbuff, &pMonster->_mMTidx); CopyInt(tbuff, &pMonster->_mmode); CopyChar(tbuff, &pMonster->_mgoal); tbuff += 3; // Alignment CopyInt(tbuff, &pMonster->_mgoalvar1); CopyInt(tbuff, &pMonster->_mgoalvar2); CopyInt(tbuff, &pMonster->_mgoalvar3); CopyInt(tbuff, &pMonster->field_18); CopyChar(tbuff, &pMonster->_pathcount); tbuff += 3; // Alignment CopyInt(tbuff, &pMonster->_mx); CopyInt(tbuff, &pMonster->_my); CopyInt(tbuff, &pMonster->_mfutx); CopyInt(tbuff, &pMonster->_mfuty); CopyInt(tbuff, &pMonster->_moldx); CopyInt(tbuff, &pMonster->_moldy); CopyInt(tbuff, &pMonster->_mxoff); CopyInt(tbuff, &pMonster->_myoff); CopyInt(tbuff, &pMonster->_mxvel); CopyInt(tbuff, &pMonster->_myvel); CopyInt(tbuff, &pMonster->_mdir); CopyInt(tbuff, &pMonster->_menemy); CopyChar(tbuff, &pMonster->_menemyx); CopyChar(tbuff, &pMonster->_menemyy); CopyShort(tbuff, &pMonster->falign_52); tbuff += 4; // Skip pointer _mAnimData CopyInt(tbuff, &pMonster->_mAnimDelay); CopyInt(tbuff, &pMonster->_mAnimCnt); CopyInt(tbuff, &pMonster->_mAnimLen); CopyInt(tbuff, &pMonster->_mAnimFrame); tbuff += 4; // Skip _meflag CopyInt(tbuff, &pMonster->_mDelFlag); CopyInt(tbuff, &pMonster->_mVar1); CopyInt(tbuff, &pMonster->_mVar2); CopyInt(tbuff, &pMonster->_mVar3); CopyInt(tbuff, &pMonster->_mVar4); CopyInt(tbuff, &pMonster->_mVar5); CopyInt(tbuff, &pMonster->_mVar6); CopyInt(tbuff, &pMonster->_mVar7); CopyInt(tbuff, &pMonster->_mVar8); CopyInt(tbuff, &pMonster->_mmaxhp); CopyInt(tbuff, &pMonster->_mhitpoints); CopyChar(tbuff, &pMonster->_mAi); CopyChar(tbuff, &pMonster->_mint); CopyShort(tbuff, &pMonster->falign_9A); CopyInt(tbuff, &pMonster->_mFlags); CopyChar(tbuff, &pMonster->_msquelch); tbuff += 3; // Alignment CopyInt(tbuff, &pMonster->falign_A4); CopyInt(tbuff, &pMonster->_lastx); CopyInt(tbuff, &pMonster->_lasty); CopyInt(tbuff, &pMonster->_mRndSeed); CopyInt(tbuff, &pMonster->_mAISeed); CopyInt(tbuff, &pMonster->falign_B8); CopyChar(tbuff, &pMonster->_uniqtype); CopyChar(tbuff, &pMonster->_uniqtrans); CopyChar(tbuff, &pMonster->_udeadval); CopyChar(tbuff, &pMonster->mWhoHit); CopyChar(tbuff, &pMonster->mLevel); tbuff += 1; // Alignment CopyShort(tbuff, &pMonster->mExp); tbuff += 1; // Skip mHit as it's already initialized CopyChar(tbuff, &pMonster->mMinDamage); CopyChar(tbuff, &pMonster->mMaxDamage); tbuff += 1; // Skip mHit2 as it's already initialized CopyChar(tbuff, &pMonster->mMinDamage2); CopyChar(tbuff, &pMonster->mMaxDamage2); CopyChar(tbuff, &pMonster->mArmorClass); CopyChar(tbuff, &pMonster->falign_CB); CopyShort(tbuff, &pMonster->mMagicRes); tbuff += 2; // Alignment CopyInt(tbuff, &pMonster->mtalkmsg); CopyChar(tbuff, &pMonster->leader); CopyChar(tbuff, &pMonster->leaderflag); CopyChar(tbuff, &pMonster->packsize); CopyChar(tbuff, &pMonster->mlid); if (pMonster->mlid == plr[myplr]._plid) pMonster->mlid = NO_LIGHT; // Correct incorect values in old saves // Omit pointer mName; // Omit pointer MType; // Omit pointer MData; SyncMonsterAnim(i); } static void LoadMissile(int i) { MissileStruct *pMissile = &missile[i]; CopyInt(tbuff, &pMissile->_mitype); CopyInt(tbuff, &pMissile->_mix); CopyInt(tbuff, &pMissile->_miy); CopyInt(tbuff, &pMissile->_mixoff); CopyInt(tbuff, &pMissile->_miyoff); CopyInt(tbuff, &pMissile->_mixvel); CopyInt(tbuff, &pMissile->_miyvel); CopyInt(tbuff, &pMissile->_misx); CopyInt(tbuff, &pMissile->_misy); CopyInt(tbuff, &pMissile->_mitxoff); CopyInt(tbuff, &pMissile->_mityoff); CopyInt(tbuff, &pMissile->_mimfnum); CopyInt(tbuff, &pMissile->_mispllvl); CopyInt(tbuff, &pMissile->_miDelFlag); CopyChar(tbuff, &pMissile->_miAnimType); tbuff += 3; // Alignment CopyInt(tbuff, &pMissile->_miAnimFlags); tbuff += 4; // Skip pointer _miAnimData CopyInt(tbuff, &pMissile->_miAnimDelay); CopyInt(tbuff, &pMissile->_miAnimLen); CopyInt(tbuff, &pMissile->_miAnimWidth); CopyInt(tbuff, &pMissile->_miAnimWidth2); CopyInt(tbuff, &pMissile->_miAnimCnt); CopyInt(tbuff, &pMissile->_miAnimAdd); CopyInt(tbuff, &pMissile->_miAnimFrame); CopyInt(tbuff, &pMissile->_miDrawFlag); CopyInt(tbuff, &pMissile->_miLightFlag); CopyInt(tbuff, &pMissile->_miPreFlag); CopyInt(tbuff, &pMissile->_miUniqTrans); CopyInt(tbuff, &pMissile->_mirange); CopyInt(tbuff, &pMissile->_misource); CopyInt(tbuff, &pMissile->_micaster); CopyInt(tbuff, &pMissile->_midam); CopyInt(tbuff, &pMissile->_miHitFlag); CopyInt(tbuff, &pMissile->_midist); CopyInt(tbuff, &pMissile->_mlid); CopyInt(tbuff, &pMissile->_mirnd); CopyInt(tbuff, &pMissile->_miVar1); CopyInt(tbuff, &pMissile->_miVar2); CopyInt(tbuff, &pMissile->_miVar3); CopyInt(tbuff, &pMissile->_miVar4); CopyInt(tbuff, &pMissile->_miVar5); CopyInt(tbuff, &pMissile->_miVar6); CopyInt(tbuff, &pMissile->_miVar7); CopyInt(tbuff, &pMissile->_miVar8); } static void LoadObject(int i) { ObjectStruct *pObject = &object[i]; CopyInt(tbuff, &pObject->_otype); CopyInt(tbuff, &pObject->_ox); CopyInt(tbuff, &pObject->_oy); CopyInt(tbuff, &pObject->_oLight); CopyInt(tbuff, &pObject->_oAnimFlag); tbuff += 4; // Skip pointer _oAnimData CopyInt(tbuff, &pObject->_oAnimDelay); CopyInt(tbuff, &pObject->_oAnimCnt); CopyInt(tbuff, &pObject->_oAnimLen); CopyInt(tbuff, &pObject->_oAnimFrame); CopyInt(tbuff, &pObject->_oAnimWidth); CopyInt(tbuff, &pObject->_oAnimWidth2); CopyInt(tbuff, &pObject->_oDelFlag); CopyChar(tbuff, &pObject->_oBreak); tbuff += 3; // Alignment CopyInt(tbuff, &pObject->_oSolidFlag); CopyInt(tbuff, &pObject->_oMissFlag); CopyChar(tbuff, &pObject->_oSelFlag); tbuff += 3; // Alignment CopyInt(tbuff, &pObject->_oPreFlag); CopyInt(tbuff, &pObject->_oTrapFlag); CopyInt(tbuff, &pObject->_oDoorFlag); CopyInt(tbuff, &pObject->_olid); CopyInt(tbuff, &pObject->_oRndSeed); CopyInt(tbuff, &pObject->_oVar1); CopyInt(tbuff, &pObject->_oVar2); CopyInt(tbuff, &pObject->_oVar3); CopyInt(tbuff, &pObject->_oVar4); CopyInt(tbuff, &pObject->_oVar5); CopyInt(tbuff, &pObject->_oVar6); CopyInt(tbuff, &pObject->_oVar7); CopyInt(tbuff, &pObject->_oVar8); } static void LoadItem(int i) { LoadItemData(&item[i]); GetItemFrm(i); } static void LoadPremium(int i) { LoadItemData(&premiumitem[i]); } static void LoadQuest(int i) { QuestStruct *pQuest = &quests[i]; CopyChar(tbuff, &pQuest->_qlevel); CopyChar(tbuff, &pQuest->_qtype); CopyChar(tbuff, &pQuest->_qactive); CopyChar(tbuff, &pQuest->_qlvltype); CopyInt(tbuff, &pQuest->_qtx); CopyInt(tbuff, &pQuest->_qty); CopyChar(tbuff, &pQuest->_qslvl); CopyChar(tbuff, &pQuest->_qidx); if (gbIsHellfireSaveGame) { tbuff += 2; // Alignment CopyInt(tbuff, &pQuest->_qmsg); } else { Uint8 tmp; CopyChar(tbuff, &tmp); pQuest->_qmsg = tmp; } CopyChar(tbuff, &pQuest->_qvar1); CopyChar(tbuff, &pQuest->_qvar2); tbuff += 2; // Alignment if (!gbIsHellfireSaveGame) tbuff += 1; // Alignment pQuest->_qlog = LoadBool32(); ReturnLvlX = WLoad(); ReturnLvlY = WLoad(); ReturnLvl = WLoad(); ReturnLvlT = WLoad(); DoomQuestState = WLoad(); } static void LoadLighting(int i) { LightListStruct *pLight = &LightList[i]; CopyInt(tbuff, &pLight->_lx); CopyInt(tbuff, &pLight->_ly); CopyInt(tbuff, &pLight->_lradius); CopyInt(tbuff, &pLight->_lid); CopyInt(tbuff, &pLight->_ldel); CopyInt(tbuff, &pLight->_lunflag); CopyInt(tbuff, &pLight->field_18); CopyInt(tbuff, &pLight->_lunx); CopyInt(tbuff, &pLight->_luny); CopyInt(tbuff, &pLight->_lunr); CopyInt(tbuff, &pLight->_xoff); CopyInt(tbuff, &pLight->_yoff); CopyInt(tbuff, &pLight->_lflags); } static void LoadVision(int i) { LightListStruct *pVision = &VisionList[i]; CopyInt(tbuff, &pVision->_lx); CopyInt(tbuff, &pVision->_ly); CopyInt(tbuff, &pVision->_lradius); CopyInt(tbuff, &pVision->_lid); CopyInt(tbuff, &pVision->_ldel); CopyInt(tbuff, &pVision->_lunflag); CopyInt(tbuff, &pVision->field_18); CopyInt(tbuff, &pVision->_lunx); CopyInt(tbuff, &pVision->_luny); CopyInt(tbuff, &pVision->_lunr); CopyInt(tbuff, &pVision->_xoff); CopyInt(tbuff, &pVision->_yoff); CopyInt(tbuff, &pVision->_lflags); } static void LoadPortal(int i) { PortalStruct *pPortal = &portal[i]; CopyInt(tbuff, &pPortal->open); CopyInt(tbuff, &pPortal->x); CopyInt(tbuff, &pPortal->y); CopyInt(tbuff, &pPortal->level); CopyInt(tbuff, &pPortal->ltype); CopyInt(tbuff, &pPortal->setlvl); } int RemapItemIdxFromDiablo(int i) { if (i == IDI_SORCEROR) { return 166; } if (i >= 156) { i += 5; // Hellfire exclusive items } if (i >= 88) { i += 1; // Scroll of Search } if (i >= 83) { i += 4; // Oils } return i; } int RemapItemIdxToDiablo(int i) { if (i == 166) { return IDI_SORCEROR; } if ((i >= 83 && i <= 86) || i == 92 || i >= 161) { return -1; // Hellfire exclusive items } if (i >= 93) { i -= 1; // Scroll of Search } if (i >= 87) { i -= 4; // Oils } return i; } bool IsHeaderValid(int magicNumber) { gbIsHellfireSaveGame = false; if (magicNumber == 'SHAR') { return true; } else if (magicNumber == 'SHLF') { gbIsHellfireSaveGame = true; return true; } else if (!gbIsSpawn && magicNumber == 'RETL') { return true; } else if (!gbIsSpawn && magicNumber == 'HELF') { gbIsHellfireSaveGame = true; return true; } return false; } /** * @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; BYTE *LoadBuff; int _ViewX, _ViewY, _nummonsters, _numitems, _nummissiles, _nobjects; FreeGameMem(); pfile_remove_temp_files(); LoadBuff = pfile_read("game", &dwLen); tbuff = LoadBuff; if (!IsHeaderValid(ILoad())) app_fatal("Invalid save file"); if (gbIsHellfireSaveGame) { giNumberOfLevels = 25; giNumberQuests = 24; giNumberOfSmithPremiumItems = 15; } else { // Todo initialize additional levels and quests if we are running Hellfire giNumberOfLevels = 17; giNumberQuests = 16; giNumberOfSmithPremiumItems = 6; } setlevel = LoadBool8(); setlvlnum = WLoad(); currlevel = WLoad(); leveltype = WLoad(); _ViewX = WLoad(); _ViewY = WLoad(); invflag = LoadBool8(); chrflag = LoadBool8(); _nummonsters = WLoad(); _numitems = WLoad(); _nummissiles = WLoad(); _nobjects = WLoad(); for (i = 0; i < giNumberOfLevels; i++) { glSeedTbl[i] = ILoad(); gnLevelTypeTbl[i] = WLoad(); } LoadPlayer(myplr); gnDifficulty = plr[myplr].pDifficulty; if (gnDifficulty < DIFF_NORMAL || gnDifficulty > DIFF_HELL) gnDifficulty = DIFF_NORMAL; for (i = 0; i < giNumberQuests; 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] = LoadBool8(); 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(); } 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] = LoadBool8(); } for (j = 0; j < MAXDUNY; j++) { for (i = 0; i < MAXDUNX; i++) dMissile[i][j] = BLoad(); } } numpremium = WLoad(); premiumlevel = WLoad(); for (i = 0; i < giNumberOfSmithPremiumItems; i++) LoadPremium(i); if (gbIsHellfire && !gbIsHellfireSaveGame) SpawnPremium(myplr); automapflag = LoadBool8(); AutoMapScale = WLoad(); mem_free_dbg(LoadBuff); AutomapZoomReset(); ResyncQuests(); if (leveltype != DTYPE_TOWN) ProcessLightList(); RedoPlayerVision(); ProcessVisionList(); missiles_process_charge(); ResetPal(); SetCursor_(CURSOR_HAND); gbProcessPlayers = TRUE; gbIsHellfireSaveGame = gbIsHellfire; } 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 SaveBool8(bool v) { if (v != false) *tbuff++ = 1; else *tbuff++ = 0; } static void SaveBool32(bool value) { Uint32 buf = value ? 1 : 0; buf = SwapLE32(buf); memcpy(tbuff, &buf, 4); tbuff += 4; } static void SaveItem(ItemStruct *pItem) { int idx = RemapItemIdxToDiablo(pItem->IDidx); int iType = pItem->_itype; if (idx == -1) { idx = 0; iType = ITYPE_NONE; } CopyInt(&pItem->_iSeed, tbuff); CopyShort(&pItem->_iCreateInfo, tbuff); tbuff += 2; // Alignment CopyInt(&iType, tbuff); CopyInt(&pItem->_ix, tbuff); CopyInt(&pItem->_iy, tbuff); CopyInt(&pItem->_iAnimFlag, tbuff); tbuff += 4; // Skip pointer _iAnimData CopyInt(&pItem->_iAnimLen, tbuff); CopyInt(&pItem->_iAnimFrame, tbuff); CopyInt(&pItem->_iAnimWidth, tbuff); CopyInt(&pItem->_iAnimWidth2, tbuff); CopyInt(&pItem->_iDelFlag, tbuff); CopyChar(&pItem->_iSelFlag, tbuff); tbuff += 3; // Alignment CopyInt(&pItem->_iPostDraw, tbuff); CopyInt(&pItem->_iIdentified, tbuff); CopyChar(&pItem->_iMagical, tbuff); CopyBytes(&pItem->_iName, 64, tbuff); CopyBytes(&pItem->_iIName, 64, tbuff); CopyChar(&pItem->_iLoc, tbuff); CopyChar(&pItem->_iClass, tbuff); tbuff += 1; // Alignment CopyInt(&pItem->_iCurs, tbuff); CopyInt(&pItem->_ivalue, tbuff); CopyInt(&pItem->_iIvalue, tbuff); CopyInt(&pItem->_iMinDam, tbuff); CopyInt(&pItem->_iMaxDam, tbuff); CopyInt(&pItem->_iAC, tbuff); CopyInt(&pItem->_iFlags, tbuff); CopyInt(&pItem->_iMiscId, tbuff); CopyInt(&pItem->_iSpell, tbuff); CopyInt(&pItem->_iCharges, tbuff); CopyInt(&pItem->_iMaxCharges, tbuff); CopyInt(&pItem->_iDurability, tbuff); CopyInt(&pItem->_iMaxDur, tbuff); CopyInt(&pItem->_iPLDam, tbuff); CopyInt(&pItem->_iPLToHit, tbuff); CopyInt(&pItem->_iPLAC, tbuff); CopyInt(&pItem->_iPLStr, tbuff); CopyInt(&pItem->_iPLMag, tbuff); CopyInt(&pItem->_iPLDex, tbuff); CopyInt(&pItem->_iPLVit, tbuff); CopyInt(&pItem->_iPLFR, tbuff); CopyInt(&pItem->_iPLLR, tbuff); CopyInt(&pItem->_iPLMR, tbuff); CopyInt(&pItem->_iPLMana, tbuff); CopyInt(&pItem->_iPLHP, tbuff); CopyInt(&pItem->_iPLDamMod, tbuff); CopyInt(&pItem->_iPLGetHit, tbuff); CopyInt(&pItem->_iPLLight, tbuff); CopyChar(&pItem->_iSplLvlAdd, tbuff); CopyChar(&pItem->_iRequest, tbuff); tbuff += 2; // Alignment CopyInt(&pItem->_iUid, tbuff); CopyInt(&pItem->_iFMinDam, tbuff); CopyInt(&pItem->_iFMaxDam, tbuff); CopyInt(&pItem->_iLMinDam, tbuff); CopyInt(&pItem->_iLMaxDam, tbuff); CopyInt(&pItem->_iPLEnAc, tbuff); CopyChar(&pItem->_iPrePower, tbuff); CopyChar(&pItem->_iSufPower, tbuff); tbuff += 2; // Alignment CopyInt(&pItem->_iVAdd1, tbuff); CopyInt(&pItem->_iVMult1, tbuff); CopyInt(&pItem->_iVAdd2, tbuff); CopyInt(&pItem->_iVMult2, tbuff); CopyChar(&pItem->_iMinStr, tbuff); CopyChar(&pItem->_iMinMag, tbuff); CopyChar(&pItem->_iMinDex, tbuff); tbuff += 1; // Alignment CopyInt(&pItem->_iStatFlag, tbuff); CopyInt(&idx, tbuff); CopyInt(&pItem->offs016C, tbuff); if (gbIsHellfire) CopyInt(&pItem->_iDamAcFlags, tbuff); } static void SaveItems(ItemStruct *pItem, const int n) { for (int i = 0; i < n; i++) { SaveItem(&pItem[i]); } } static void SavePlayer(int i) { PlayerStruct *pPlayer = &plr[i]; CopyInt(&pPlayer->_pmode, tbuff); CopyBytes(&pPlayer->walkpath, MAX_PATH_LENGTH, tbuff); CopyBytes(&pPlayer->plractive, 1, tbuff); tbuff += 2; // Alignment CopyInt(&pPlayer->destAction, tbuff); CopyInt(&pPlayer->destParam1, tbuff); CopyInt(&pPlayer->destParam2, tbuff); CopyInt(&pPlayer->destParam3, tbuff); CopyInt(&pPlayer->destParam4, tbuff); CopyInt(&pPlayer->plrlevel, tbuff); CopyInt(&pPlayer->_px, tbuff); CopyInt(&pPlayer->_py, tbuff); CopyInt(&pPlayer->_pfutx, tbuff); CopyInt(&pPlayer->_pfuty, tbuff); CopyInt(&pPlayer->_ptargx, tbuff); CopyInt(&pPlayer->_ptargy, tbuff); CopyInt(&pPlayer->_pownerx, tbuff); CopyInt(&pPlayer->_pownery, tbuff); CopyInt(&pPlayer->_poldx, tbuff); CopyInt(&pPlayer->_poldy, tbuff); CopyInt(&pPlayer->_pxoff, tbuff); CopyInt(&pPlayer->_pyoff, tbuff); CopyInt(&pPlayer->_pxvel, tbuff); CopyInt(&pPlayer->_pyvel, tbuff); CopyInt(&pPlayer->_pdir, tbuff); CopyInt(&pPlayer->_nextdir, tbuff); CopyInt(&pPlayer->_pgfxnum, tbuff); tbuff += 4; // Skip pointer _pAnimData CopyInt(&pPlayer->_pAnimDelay, tbuff); CopyInt(&pPlayer->_pAnimCnt, tbuff); CopyInt(&pPlayer->_pAnimLen, tbuff); CopyInt(&pPlayer->_pAnimFrame, tbuff); CopyInt(&pPlayer->_pAnimWidth, tbuff); CopyInt(&pPlayer->_pAnimWidth2, tbuff); tbuff += 4; // Skip _peflag CopyInt(&pPlayer->_plid, tbuff); CopyInt(&pPlayer->_pvid, tbuff); CopyInt(&pPlayer->_pSpell, tbuff); CopyChar(&pPlayer->_pSplType, tbuff); CopyChar(&pPlayer->_pSplFrom, tbuff); tbuff += 2; // Alignment CopyInt(&pPlayer->_pTSpell, tbuff); CopyChar(&pPlayer->_pTSplType, tbuff); tbuff += 3; // Alignment CopyInt(&pPlayer->_pRSpell, tbuff); CopyChar(&pPlayer->_pRSplType, tbuff); tbuff += 3; // Alignment CopyInt(&pPlayer->_pSBkSpell, tbuff); CopyChar(&pPlayer->_pSBkSplType, tbuff); CopyBytes(&pPlayer->_pSplLvl, 64, tbuff); tbuff += 7; // Alignment CopyInt64(&pPlayer->_pMemSpells, tbuff); CopyInt64(&pPlayer->_pAblSpells, tbuff); CopyInt64(&pPlayer->_pScrlSpells, tbuff); CopyChar(&pPlayer->_pSpellFlags, tbuff); tbuff += 3; // Alignment CopyInts(&pPlayer->_pSplHotKey, 4, tbuff); CopyBytes(&pPlayer->_pSplTHotKey, 4, tbuff); CopyInt(&pPlayer->_pwtype, tbuff); CopyChar(&pPlayer->_pBlockFlag, tbuff); CopyChar(&pPlayer->_pInvincible, tbuff); CopyChar(&pPlayer->_pLightRad, tbuff); CopyChar(&pPlayer->_pLvlChanging, tbuff); CopyBytes(&pPlayer->_pName, PLR_NAME_LEN, tbuff); CopyChar(&pPlayer->_pClass, tbuff); tbuff += 3; // Alignment CopyInt(&pPlayer->_pStrength, tbuff); CopyInt(&pPlayer->_pBaseStr, tbuff); CopyInt(&pPlayer->_pMagic, tbuff); CopyInt(&pPlayer->_pBaseMag, tbuff); CopyInt(&pPlayer->_pDexterity, tbuff); CopyInt(&pPlayer->_pBaseDex, tbuff); CopyInt(&pPlayer->_pVitality, tbuff); CopyInt(&pPlayer->_pBaseVit, tbuff); CopyInt(&pPlayer->_pStatPts, tbuff); CopyInt(&pPlayer->_pDamageMod, tbuff); CopyInt(&pPlayer->_pBaseToBlk, tbuff); CopyInt(&pPlayer->_pHPBase, tbuff); CopyInt(&pPlayer->_pMaxHPBase, tbuff); CopyInt(&pPlayer->_pHitPoints, tbuff); CopyInt(&pPlayer->_pMaxHP, tbuff); CopyInt(&pPlayer->_pHPPer, tbuff); CopyInt(&pPlayer->_pManaBase, tbuff); CopyInt(&pPlayer->_pMaxManaBase, tbuff); CopyInt(&pPlayer->_pMana, tbuff); CopyInt(&pPlayer->_pMaxMana, tbuff); CopyInt(&pPlayer->_pManaPer, tbuff); CopyChar(&pPlayer->_pLevel, tbuff); CopyChar(&pPlayer->_pMaxLvl, tbuff); tbuff += 2; // Alignment CopyInt(&pPlayer->_pExperience, tbuff); CopyInt(&pPlayer->_pMaxExp, tbuff); CopyInt(&pPlayer->_pNextExper, tbuff); CopyChar(&pPlayer->_pArmorClass, tbuff); CopyChar(&pPlayer->_pMagResist, tbuff); CopyChar(&pPlayer->_pFireResist, tbuff); CopyChar(&pPlayer->_pLghtResist, tbuff); CopyInt(&pPlayer->_pGold, tbuff); CopyInt(&pPlayer->_pInfraFlag, tbuff); CopyInt(&pPlayer->_pVar1, tbuff); CopyInt(&pPlayer->_pVar2, tbuff); CopyInt(&pPlayer->_pVar3, tbuff); CopyInt(&pPlayer->_pVar4, tbuff); CopyInt(&pPlayer->_pVar5, tbuff); CopyInt(&pPlayer->_pVar6, tbuff); CopyInt(&pPlayer->_pVar7, tbuff); CopyInt(&pPlayer->_pVar8, tbuff); CopyBytes(&pPlayer->_pLvlVisited, giNumberOfLevels, tbuff); CopyBytes(&pPlayer->_pSLvlVisited, giNumberOfLevels, tbuff); // only 10 used tbuff += 2; // Alignment CopyInt(&pPlayer->_pGFXLoad, tbuff); tbuff += 4 * 8; // Skip pointers _pNAnim CopyInt(&pPlayer->_pNFrames, tbuff); CopyInt(&pPlayer->_pNWidth, tbuff); tbuff += 4 * 8; // Skip pointers _pWAnim CopyInt(&pPlayer->_pWFrames, tbuff); CopyInt(&pPlayer->_pWWidth, tbuff); tbuff += 4 * 8; // Skip pointers _pAAnim CopyInt(&pPlayer->_pAFrames, tbuff); CopyInt(&pPlayer->_pAWidth, tbuff); CopyInt(&pPlayer->_pAFNum, tbuff); tbuff += 4 * 8; // Skip pointers _pLAnim tbuff += 4 * 8; // Skip pointers _pFAnim tbuff += 4 * 8; // Skip pointers _pTAnim CopyInt(&pPlayer->_pSFrames, tbuff); CopyInt(&pPlayer->_pSWidth, tbuff); CopyInt(&pPlayer->_pSFNum, tbuff); tbuff += 4 * 8; // Skip pointers _pHAnim CopyInt(&pPlayer->_pHFrames, tbuff); CopyInt(&pPlayer->_pHWidth, tbuff); tbuff += 4 * 8; // Skip pointers _pDAnim CopyInt(&pPlayer->_pDFrames, tbuff); CopyInt(&pPlayer->_pDWidth, tbuff); tbuff += 4 * 8; // Skip pointers _pBAnim CopyInt(&pPlayer->_pBFrames, tbuff); CopyInt(&pPlayer->_pBWidth, tbuff); SaveItems(pPlayer->InvBody, NUM_INVLOC); SaveItems(pPlayer->InvList, NUM_INV_GRID_ELEM); CopyInt(&pPlayer->_pNumInv, tbuff); CopyBytes(pPlayer->InvGrid, NUM_INV_GRID_ELEM, tbuff); SaveItems(pPlayer->SpdList, MAXBELTITEMS); SaveItem(&pPlayer->HoldItem); CopyInt(&pPlayer->_pIMinDam, tbuff); CopyInt(&pPlayer->_pIMaxDam, tbuff); CopyInt(&pPlayer->_pIAC, tbuff); CopyInt(&pPlayer->_pIBonusDam, tbuff); CopyInt(&pPlayer->_pIBonusToHit, tbuff); CopyInt(&pPlayer->_pIBonusAC, tbuff); CopyInt(&pPlayer->_pIBonusDamMod, tbuff); tbuff += 4; // Alignment CopyInt64(&pPlayer->_pISpells, tbuff); CopyInt(&pPlayer->_pIFlags, tbuff); CopyInt(&pPlayer->_pIGetHit, tbuff); CopyChar(&pPlayer->_pISplLvlAdd, tbuff); CopyChar(&pPlayer->_pISplCost, tbuff); tbuff += 2; // Alignment CopyInt(&pPlayer->_pISplDur, tbuff); CopyInt(&pPlayer->_pIEnAc, tbuff); CopyInt(&pPlayer->_pIFMinDam, tbuff); CopyInt(&pPlayer->_pIFMaxDam, tbuff); CopyInt(&pPlayer->_pILMinDam, tbuff); CopyInt(&pPlayer->_pILMaxDam, tbuff); CopyInt(&pPlayer->_pOilType, tbuff); CopyChar(&pPlayer->pTownWarps, tbuff); CopyChar(&pPlayer->pDungMsgs, tbuff); CopyChar(&pPlayer->pLvlLoad, tbuff); if (gbIsHellfire) CopyChar(&pPlayer->pDungMsgs2, tbuff); else CopyChar(&pPlayer->pBattleNet, tbuff); CopyChar(&pPlayer->pManaShield, tbuff); CopyChar(&pPlayer->pOriginalCathedral, tbuff); CopyBytes(&pPlayer->bReserved, 2, tbuff); CopyShort(&pPlayer->wReflections, tbuff); CopyShorts(&pPlayer->wReserved, 7, tbuff); CopyInt(&pPlayer->pDiabloKillLevel, tbuff); CopyInt(&pPlayer->pDifficulty, tbuff); CopyInt(&pPlayer->pDamAcFlags, tbuff); CopyInts(&pPlayer->dwReserved, 5, tbuff); // Omit pointer _pNData // Omit pointer _pWData // Omit pointer _pAData // Omit pointer _pLData // Omit pointer _pFData // Omit pointer _pTData // Omit pointer _pHData // Omit pointer _pDData // Omit pointer _pBData // Omit pointer pReserved } static void SaveMonster(int i) { MonsterStruct *pMonster = &monster[i]; char tempChar; CopyInt(&pMonster->_mMTidx, tbuff); CopyInt(&pMonster->_mmode, tbuff); CopyChar(&pMonster->_mgoal, tbuff); tbuff += 3; // Alignment CopyInt(&pMonster->_mgoalvar1, tbuff); CopyInt(&pMonster->_mgoalvar2, tbuff); CopyInt(&pMonster->_mgoalvar3, tbuff); CopyInt(&pMonster->field_18, tbuff); CopyChar(&pMonster->_pathcount, tbuff); tbuff += 3; // Alignment CopyInt(&pMonster->_mx, tbuff); CopyInt(&pMonster->_my, tbuff); CopyInt(&pMonster->_mfutx, tbuff); CopyInt(&pMonster->_mfuty, tbuff); CopyInt(&pMonster->_moldx, tbuff); CopyInt(&pMonster->_moldy, tbuff); CopyInt(&pMonster->_mxoff, tbuff); CopyInt(&pMonster->_myoff, tbuff); CopyInt(&pMonster->_mxvel, tbuff); CopyInt(&pMonster->_myvel, tbuff); CopyInt(&pMonster->_mdir, tbuff); CopyInt(&pMonster->_menemy, tbuff); CopyChar(&pMonster->_menemyx, tbuff); CopyChar(&pMonster->_menemyy, tbuff); CopyShort(&pMonster->falign_52, tbuff); tbuff += 4; // Skip pointer _mAnimData CopyInt(&pMonster->_mAnimDelay, tbuff); CopyInt(&pMonster->_mAnimCnt, tbuff); CopyInt(&pMonster->_mAnimLen, tbuff); CopyInt(&pMonster->_mAnimFrame, tbuff); tbuff += 4; // Skip _meflag CopyInt(&pMonster->_mDelFlag, tbuff); CopyInt(&pMonster->_mVar1, tbuff); CopyInt(&pMonster->_mVar2, tbuff); CopyInt(&pMonster->_mVar3, tbuff); CopyInt(&pMonster->_mVar4, tbuff); CopyInt(&pMonster->_mVar5, tbuff); CopyInt(&pMonster->_mVar6, tbuff); CopyInt(&pMonster->_mVar7, tbuff); CopyInt(&pMonster->_mVar8, tbuff); CopyInt(&pMonster->_mmaxhp, tbuff); CopyInt(&pMonster->_mhitpoints, tbuff); CopyChar(&pMonster->_mAi, tbuff); CopyChar(&pMonster->_mint, tbuff); CopyShort(&pMonster->falign_9A, tbuff); CopyInt(&pMonster->_mFlags, tbuff); CopyChar(&pMonster->_msquelch, tbuff); tbuff += 3; // Alignment CopyInt(&pMonster->falign_A4, tbuff); CopyInt(&pMonster->_lastx, tbuff); CopyInt(&pMonster->_lasty, tbuff); CopyInt(&pMonster->_mRndSeed, tbuff); CopyInt(&pMonster->_mAISeed, tbuff); CopyInt(&pMonster->falign_B8, tbuff); CopyChar(&pMonster->_uniqtype, tbuff); CopyChar(&pMonster->_uniqtrans, tbuff); CopyChar(&pMonster->_udeadval, tbuff); CopyChar(&pMonster->mWhoHit, tbuff); CopyChar(&pMonster->mLevel, tbuff); tbuff += 1; // Alignment CopyShort(&pMonster->mExp, tbuff); // Write mHit for backwards compatibility tempChar = pMonster->mHit < SCHAR_MAX ? pMonster->mHit : SCHAR_MAX; CopyChar(&tempChar, tbuff); CopyChar(&pMonster->mMinDamage, tbuff); CopyChar(&pMonster->mMaxDamage, tbuff); // Write mHit2 for backwards compatibility tempChar = pMonster->mHit2 < SCHAR_MAX ? pMonster->mHit2 : SCHAR_MAX; CopyChar(&tempChar, tbuff); CopyChar(&pMonster->mMinDamage2, tbuff); CopyChar(&pMonster->mMaxDamage2, tbuff); CopyChar(&pMonster->mArmorClass, tbuff); CopyChar(&pMonster->falign_CB, tbuff); CopyShort(&pMonster->mMagicRes, tbuff); tbuff += 2; // Alignment CopyInt(&pMonster->mtalkmsg, tbuff); CopyChar(&pMonster->leader, tbuff); CopyChar(&pMonster->leaderflag, tbuff); CopyChar(&pMonster->packsize, tbuff); CopyChar(&pMonster->mlid, tbuff); // Omit pointer mName; // Omit pointer MType; // Omit pointer MData; } static void SaveMissile(int i) { MissileStruct *pMissile = &missile[i]; CopyInt(&pMissile->_mitype, tbuff); CopyInt(&pMissile->_mix, tbuff); CopyInt(&pMissile->_miy, tbuff); CopyInt(&pMissile->_mixoff, tbuff); CopyInt(&pMissile->_miyoff, tbuff); CopyInt(&pMissile->_mixvel, tbuff); CopyInt(&pMissile->_miyvel, tbuff); CopyInt(&pMissile->_misx, tbuff); CopyInt(&pMissile->_misy, tbuff); CopyInt(&pMissile->_mitxoff, tbuff); CopyInt(&pMissile->_mityoff, tbuff); CopyInt(&pMissile->_mimfnum, tbuff); CopyInt(&pMissile->_mispllvl, tbuff); CopyInt(&pMissile->_miDelFlag, tbuff); CopyChar(&pMissile->_miAnimType, tbuff); tbuff += 3; // Alignment CopyInt(&pMissile->_miAnimFlags, tbuff); tbuff += 4; // Skip pointer _miAnimData CopyInt(&pMissile->_miAnimDelay, tbuff); CopyInt(&pMissile->_miAnimLen, tbuff); CopyInt(&pMissile->_miAnimWidth, tbuff); CopyInt(&pMissile->_miAnimWidth2, tbuff); CopyInt(&pMissile->_miAnimCnt, tbuff); CopyInt(&pMissile->_miAnimAdd, tbuff); CopyInt(&pMissile->_miAnimFrame, tbuff); CopyInt(&pMissile->_miDrawFlag, tbuff); CopyInt(&pMissile->_miLightFlag, tbuff); CopyInt(&pMissile->_miPreFlag, tbuff); CopyInt(&pMissile->_miUniqTrans, tbuff); CopyInt(&pMissile->_mirange, tbuff); CopyInt(&pMissile->_misource, tbuff); CopyInt(&pMissile->_micaster, tbuff); CopyInt(&pMissile->_midam, tbuff); CopyInt(&pMissile->_miHitFlag, tbuff); CopyInt(&pMissile->_midist, tbuff); CopyInt(&pMissile->_mlid, tbuff); CopyInt(&pMissile->_mirnd, tbuff); CopyInt(&pMissile->_miVar1, tbuff); CopyInt(&pMissile->_miVar2, tbuff); CopyInt(&pMissile->_miVar3, tbuff); CopyInt(&pMissile->_miVar4, tbuff); CopyInt(&pMissile->_miVar5, tbuff); CopyInt(&pMissile->_miVar6, tbuff); CopyInt(&pMissile->_miVar7, tbuff); CopyInt(&pMissile->_miVar8, tbuff); } static void SaveObject(int i) { ObjectStruct *pObject = &object[i]; CopyInt(&pObject->_otype, tbuff); CopyInt(&pObject->_ox, tbuff); CopyInt(&pObject->_oy, tbuff); CopyInt(&pObject->_oLight, tbuff); CopyInt(&pObject->_oAnimFlag, tbuff); tbuff += 4; // Skip pointer _oAnimData CopyInt(&pObject->_oAnimDelay, tbuff); CopyInt(&pObject->_oAnimCnt, tbuff); CopyInt(&pObject->_oAnimLen, tbuff); CopyInt(&pObject->_oAnimFrame, tbuff); CopyInt(&pObject->_oAnimWidth, tbuff); CopyInt(&pObject->_oAnimWidth2, tbuff); CopyInt(&pObject->_oDelFlag, tbuff); CopyChar(&pObject->_oBreak, tbuff); tbuff += 3; // Alignment CopyInt(&pObject->_oSolidFlag, tbuff); CopyInt(&pObject->_oMissFlag, tbuff); CopyChar(&pObject->_oSelFlag, tbuff); tbuff += 3; // Alignment CopyInt(&pObject->_oPreFlag, tbuff); CopyInt(&pObject->_oTrapFlag, tbuff); CopyInt(&pObject->_oDoorFlag, tbuff); CopyInt(&pObject->_olid, tbuff); CopyInt(&pObject->_oRndSeed, tbuff); CopyInt(&pObject->_oVar1, tbuff); CopyInt(&pObject->_oVar2, tbuff); CopyInt(&pObject->_oVar3, tbuff); CopyInt(&pObject->_oVar4, tbuff); CopyInt(&pObject->_oVar5, tbuff); CopyInt(&pObject->_oVar6, tbuff); CopyInt(&pObject->_oVar7, tbuff); CopyInt(&pObject->_oVar8, tbuff); } static void SavePremium(int i) { SaveItem(&premiumitem[i]); } static void SaveQuest(int i) { QuestStruct *pQuest = &quests[i]; CopyChar(&pQuest->_qlevel, tbuff); CopyChar(&pQuest->_qtype, tbuff); CopyChar(&pQuest->_qactive, tbuff); CopyChar(&pQuest->_qlvltype, tbuff); CopyInt(&pQuest->_qtx, tbuff); CopyInt(&pQuest->_qty, tbuff); CopyChar(&pQuest->_qslvl, tbuff); CopyChar(&pQuest->_qidx, tbuff); if (gbIsHellfire) { tbuff += 2; // Alignment CopyInt(&pQuest->_qmsg, tbuff); } else { Uint8 tmp = pQuest->_qmsg; CopyChar(&tmp, tbuff); } CopyChar(&pQuest->_qvar1, tbuff); CopyChar(&pQuest->_qvar2, tbuff); tbuff += 2; // Alignment if (!gbIsHellfire) tbuff += 1; // Alignment SaveBool32(pQuest->_qlog); WSave(ReturnLvlX); WSave(ReturnLvlY); WSave(ReturnLvl); WSave(ReturnLvlT); WSave(DoomQuestState); } static void SaveLighting(int i) { LightListStruct *pLight = &LightList[i]; CopyInt(&pLight->_lx, tbuff); CopyInt(&pLight->_ly, tbuff); CopyInt(&pLight->_lradius, tbuff); CopyInt(&pLight->_lid, tbuff); CopyInt(&pLight->_ldel, tbuff); CopyInt(&pLight->_lunflag, tbuff); CopyInt(&pLight->field_18, tbuff); CopyInt(&pLight->_lunx, tbuff); CopyInt(&pLight->_luny, tbuff); CopyInt(&pLight->_lunr, tbuff); CopyInt(&pLight->_xoff, tbuff); CopyInt(&pLight->_yoff, tbuff); CopyInt(&pLight->_lflags, tbuff); } static void SaveVision(int i) { LightListStruct *pVision = &VisionList[i]; CopyInt(&pVision->_lx, tbuff); CopyInt(&pVision->_ly, tbuff); CopyInt(&pVision->_lradius, tbuff); CopyInt(&pVision->_lid, tbuff); CopyInt(&pVision->_ldel, tbuff); CopyInt(&pVision->_lunflag, tbuff); CopyInt(&pVision->field_18, tbuff); CopyInt(&pVision->_lunx, tbuff); CopyInt(&pVision->_luny, tbuff); CopyInt(&pVision->_lunr, tbuff); CopyInt(&pVision->_xoff, tbuff); CopyInt(&pVision->_yoff, tbuff); CopyInt(&pVision->_lflags, tbuff); } static void SavePortal(int i) { PortalStruct *pPortal = &portal[i]; CopyInt(&pPortal->open, tbuff); CopyInt(&pPortal->x, tbuff); CopyInt(&pPortal->y, tbuff); CopyInt(&pPortal->level, tbuff); CopyInt(&pPortal->ltype, tbuff); CopyInt(&pPortal->setlvl, tbuff); } void SaveGame() { int i, j; DWORD dwLen = codec_get_encoded_len(FILEBUFF); BYTE *SaveBuff = DiabloAllocPtr(dwLen); tbuff = SaveBuff; if (gbIsSpawn && !gbIsHellfire) ISave('SHAR'); else if (gbIsSpawn && gbIsHellfire) ISave('SHLF'); else if (!gbIsSpawn && gbIsHellfire) ISave('HELF'); else if (!gbIsSpawn && !gbIsHellfire) ISave('RETL'); else app_fatal("Invalid game state"); if (gbIsHellfire) { giNumberOfLevels = 25; giNumberQuests = 24; giNumberOfSmithPremiumItems = 15; } else { giNumberOfLevels = 17; giNumberQuests = 16; giNumberOfSmithPremiumItems = 6; } SaveBool8(setlevel); WSave(setlvlnum); WSave(currlevel); WSave(leveltype); WSave(ViewX); WSave(ViewY); SaveBool8(invflag); SaveBool8(chrflag); WSave(nummonsters); WSave(numitems); WSave(nummissiles); WSave(nobjects); for (i = 0; i < giNumberOfLevels; i++) { ISave(glSeedTbl[i]); WSave(gnLevelTypeTbl[i]); } plr[myplr].pDifficulty = gnDifficulty; SavePlayer(myplr); for (i = 0; i < giNumberQuests; 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(&item[itemactive[i]]); for (i = 0; i < 128; i++) SaveBool8(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]); } 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++) SaveBool8(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 < giNumberOfSmithPremiumItems; i++) SavePremium(i); SaveBool8(automapflag); WSave(AutoMapScale); dwLen = codec_get_encoded_len(tbuff - SaveBuff); pfile_write_save_file("game", 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; DoUnVision(plr[myplr]._px, plr[myplr]._py, plr[myplr]._pLightRad); // fix for vision staying on the level 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(&item[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++) SaveBool8(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(); } SetDead(); } 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] = LoadBool8(); } 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); } DEVILUTION_END_NAMESPACE