1 /**
2 * @file loadsave.cpp
3 *
4 * Implementation of save game functionality.
5 */
6 #include "all.h"
7
8 DEVILUTION_BEGIN_NAMESPACE
9
10 bool gbIsHellfireSaveGame;
11 int giNumberOfLevels;
12 int giNumberQuests;
13 int giNumberOfSmithPremiumItems;
14
15 namespace {
16
17 template <class T>
SwapLE(T in)18 T SwapLE(T in)
19 {
20 switch (sizeof(T)) {
21 case 2:
22 return SDL_SwapLE16(in);
23 case 4:
24 return SDL_SwapLE32(in);
25 case 8:
26 return SDL_SwapLE64(in);
27 default:
28 return in;
29 }
30 }
31
32 template <class T>
SwapBE(T in)33 T SwapBE(T in)
34 {
35 switch (sizeof(T)) {
36 case 2:
37 return SDL_SwapBE16(in);
38 case 4:
39 return SDL_SwapBE32(in);
40 case 8:
41 return SDL_SwapBE64(in);
42 default:
43 return in;
44 }
45 }
46
47 class LoadHelper {
48 Uint8 *m_buffer;
49 Uint32 m_bufferPtr = 0;
50 Uint32 m_bufferLen;
51
52 template <class T>
next()53 T next()
54 {
55 const auto size = sizeof(T);
56 if (!isValid(size))
57 return 0;
58
59 T value;
60 memcpy(&value, &m_buffer[m_bufferPtr], size);
61 m_bufferPtr += size;
62
63 return value;
64 }
65
66 public:
LoadHelper(const char * szFileName)67 LoadHelper(const char *szFileName)
68 {
69 m_buffer = pfile_read(szFileName, &m_bufferLen);
70 }
71
isValid(Uint32 size=1)72 bool isValid(Uint32 size = 1)
73 {
74 return m_buffer != nullptr
75 && m_bufferLen >= (m_bufferPtr + size);
76 }
77
skip(Uint32 size)78 void skip(Uint32 size)
79 {
80 m_bufferPtr += size;
81 }
82
nextBytes(void * bytes,size_t size)83 void nextBytes(void *bytes, size_t size)
84 {
85 if (!isValid(size))
86 return;
87
88 memcpy(bytes, &m_buffer[m_bufferPtr], size);
89 m_bufferPtr += size;
90 }
91
92 template <class T>
nextLE()93 T nextLE()
94 {
95 return SwapLE(next<T>());
96 }
97
98 template <class T>
nextBE()99 T nextBE()
100 {
101 return SwapBE(next<T>());
102 }
103
nextBool8()104 bool nextBool8()
105 {
106 return next<Uint8>() != 0;
107 }
108
nextBool32()109 bool nextBool32()
110 {
111 return next<Uint32>() != 0;
112 }
113
~LoadHelper()114 ~LoadHelper()
115 {
116 mem_free_dbg(m_buffer);
117 }
118 };
119
120 class SaveHelper {
121 const char *m_szFileName;
122 Uint8 *m_buffer;
123 Uint32 m_bufferPtr = 0;
124 Uint32 m_bufferLen;
125
126 public:
SaveHelper(const char * szFileName,size_t bufferLen)127 SaveHelper(const char *szFileName, size_t bufferLen)
128 {
129 m_szFileName = szFileName;
130 m_bufferLen = bufferLen;
131 m_buffer = DiabloAllocPtr(codec_get_encoded_len(m_bufferLen));
132 }
133
isValid(Uint32 len=1)134 bool isValid(Uint32 len = 1)
135 {
136 return m_buffer != nullptr
137 && m_bufferLen >= (m_bufferPtr + len);
138 }
139
skip(Uint32 len)140 void skip(Uint32 len)
141 {
142 m_bufferPtr += len;
143 }
144
writeBytes(const void * bytes,size_t len)145 void writeBytes(const void *bytes, size_t len)
146 {
147 if (!isValid(len))
148 return;
149
150 memcpy(&m_buffer[m_bufferPtr], bytes, len);
151 m_bufferPtr += len;
152 }
153
154 template <class T>
writeLE(T value)155 void writeLE(T value)
156 {
157 value = SwapLE(value);
158 writeBytes(&value, sizeof(value));
159 }
160
161 template <class T>
writeBE(T value)162 void writeBE(T value)
163 {
164 value = SwapBE(value);
165 writeBytes(&value, sizeof(value));
166 }
167
flush()168 void flush()
169 {
170 if (m_buffer == nullptr)
171 return;
172
173 pfile_write_save_file(m_szFileName, m_buffer, m_bufferPtr, codec_get_encoded_len(m_bufferPtr));
174 mem_free_dbg(m_buffer);
175 m_buffer = nullptr;
176 }
177
~SaveHelper()178 ~SaveHelper()
179 {
180 flush();
181 }
182 };
183
184 }
185
RemoveInvalidItem(ItemStruct * pItem)186 void RemoveInvalidItem(ItemStruct *pItem)
187 {
188 bool isInvalid = !IsItemAvailable(pItem->IDidx) || !IsUniqueAvailable(pItem->_iUid);
189
190 if (!gbIsHellfire) {
191 isInvalid = isInvalid || (pItem->_itype == ITYPE_STAFF && GetSpellStaffLevel(pItem->_iSpell) == -1);
192 isInvalid = isInvalid || (pItem->_iMiscId == IMISC_BOOK && GetSpellBookLevel(pItem->_iSpell) == -1);
193 isInvalid = isInvalid || pItem->_iDamAcFlags != 0;
194 isInvalid = isInvalid || pItem->_iPrePower > IDI_LASTDIABLO;
195 isInvalid = isInvalid || pItem->_iSufPower > IDI_LASTDIABLO;
196 }
197
198 if (isInvalid) {
199 pItem->_itype = ITYPE_NONE;
200 }
201 }
202
LoadItemData(LoadHelper * file,ItemStruct * pItem)203 static void LoadItemData(LoadHelper *file, ItemStruct *pItem)
204 {
205 pItem->_iSeed = file->nextLE<Sint32>();
206 pItem->_iCreateInfo = file->nextLE<Uint16>();
207 file->skip(2); // Alignment
208 pItem->_itype = (item_type)file->nextLE<Uint32>();
209 pItem->_ix = file->nextLE<Sint32>();
210 pItem->_iy = file->nextLE<Sint32>();
211 pItem->_iAnimFlag = file->nextBool32();
212 file->skip(4); // Skip pointer _iAnimData
213 pItem->_iAnimLen = file->nextLE<Sint32>();
214 pItem->_iAnimFrame = file->nextLE<Sint32>();
215 pItem->_iAnimWidth = file->nextLE<Sint32>();
216 pItem->_iAnimWidth2 = file->nextLE<Sint32>();
217 file->skip(4); // Unused since 1.02
218 pItem->_iSelFlag = file->nextLE<Uint8>();
219 file->skip(3); // Alignment
220 pItem->_iPostDraw = file->nextBool32();
221 pItem->_iIdentified = file->nextBool32();
222 pItem->_iMagical = file->nextLE<Sint8>();
223 file->nextBytes(pItem->_iName, 64);
224 file->nextBytes(pItem->_iIName, 64);
225 pItem->_iLoc = (item_equip_type)file->nextLE<Sint8>();
226 pItem->_iClass = (item_class)file->nextLE<Uint8>();
227 file->skip(1); // Alignment
228 pItem->_iCurs = file->nextLE<Sint32>();
229 pItem->_ivalue = file->nextLE<Sint32>();
230 pItem->_iIvalue = file->nextLE<Sint32>();
231 pItem->_iMinDam = file->nextLE<Sint32>();
232 pItem->_iMaxDam = file->nextLE<Sint32>();
233 pItem->_iAC = file->nextLE<Sint32>();
234 pItem->_iFlags = file->nextLE<Sint32>();
235 pItem->_iMiscId = (item_misc_id)file->nextLE<Sint32>();
236 pItem->_iSpell = (spell_id)file->nextLE<Sint32>();
237 pItem->_iCharges = file->nextLE<Sint32>();
238 pItem->_iMaxCharges = file->nextLE<Sint32>();
239 pItem->_iDurability = file->nextLE<Sint32>();
240 pItem->_iMaxDur = file->nextLE<Sint32>();
241 pItem->_iPLDam = file->nextLE<Sint32>();
242 pItem->_iPLToHit = file->nextLE<Sint32>();
243 pItem->_iPLAC = file->nextLE<Sint32>();
244 pItem->_iPLStr = file->nextLE<Sint32>();
245 pItem->_iPLMag = file->nextLE<Sint32>();
246 pItem->_iPLDex = file->nextLE<Sint32>();
247 pItem->_iPLVit = file->nextLE<Sint32>();
248 pItem->_iPLFR = file->nextLE<Sint32>();
249 pItem->_iPLLR = file->nextLE<Sint32>();
250 pItem->_iPLMR = file->nextLE<Sint32>();
251 pItem->_iPLMana = file->nextLE<Sint32>();
252 pItem->_iPLHP = file->nextLE<Sint32>();
253 pItem->_iPLDamMod = file->nextLE<Sint32>();
254 pItem->_iPLGetHit = file->nextLE<Sint32>();
255 pItem->_iPLLight = file->nextLE<Sint32>();
256 pItem->_iSplLvlAdd = file->nextLE<Sint8>();
257 pItem->_iRequest = file->nextLE<Sint8>();
258 file->skip(2); // Alignment
259 pItem->_iUid = file->nextLE<Sint32>();
260 pItem->_iFMinDam = file->nextLE<Sint32>();
261 pItem->_iFMaxDam = file->nextLE<Sint32>();
262 pItem->_iLMinDam = file->nextLE<Sint32>();
263 pItem->_iLMaxDam = file->nextLE<Sint32>();
264 pItem->_iPLEnAc = file->nextLE<Sint32>();
265 pItem->_iPrePower = (item_effect_type)file->nextLE<Sint8>();
266 pItem->_iSufPower = (item_effect_type)file->nextLE<Sint8>();
267 file->skip(2); // Alignment
268 pItem->_iVAdd1 = file->nextLE<Sint32>();
269 pItem->_iVMult1 = file->nextLE<Sint32>();
270 pItem->_iVAdd2 = file->nextLE<Sint32>();
271 pItem->_iVMult2 = file->nextLE<Sint32>();
272 pItem->_iMinStr = file->nextLE<Sint8>();
273 pItem->_iMinMag = file->nextLE<Uint8>();
274 pItem->_iMinDex = file->nextLE<Sint8>();
275 file->skip(1); // Alignment
276 pItem->_iStatFlag = file->nextBool32();
277 pItem->IDidx = file->nextLE<Sint32>();
278 if (!gbIsHellfireSaveGame) {
279 pItem->IDidx = RemapItemIdxFromDiablo(pItem->IDidx);
280 }
281 pItem->dwBuff = file->nextLE<Uint32>();
282 if (gbIsHellfireSaveGame)
283 pItem->_iDamAcFlags = file->nextLE<Sint32>();
284 else
285 pItem->_iDamAcFlags = 0;
286
287 RemoveInvalidItem(pItem);
288 }
289
LoadItems(LoadHelper * file,const int n,ItemStruct * pItem)290 static void LoadItems(LoadHelper *file, const int n, ItemStruct *pItem)
291 {
292 for (int i = 0; i < n; i++) {
293 LoadItemData(file, &pItem[i]);
294 }
295 }
296
LoadPlayer(LoadHelper * file,int p)297 static void LoadPlayer(LoadHelper *file, int p)
298 {
299 PlayerStruct *pPlayer = &plr[p];
300
301 pPlayer->_pmode = (PLR_MODE)file->nextLE<Sint32>();
302
303 for (int i = 0; i < MAX_PATH_LENGTH; i++) {
304 pPlayer->walkpath[i] = file->nextLE<Sint8>();
305 }
306 pPlayer->plractive = file->nextBool8();
307 file->skip(2); // Alignment
308 pPlayer->destAction = (action_id)file->nextLE<Sint32>();
309 pPlayer->destParam1 = file->nextLE<Sint32>();
310 pPlayer->destParam2 = file->nextLE<Sint32>();
311 pPlayer->destParam3 = (direction)file->nextLE<Sint32>();
312 pPlayer->destParam4 = file->nextLE<Sint32>();
313 pPlayer->plrlevel = file->nextLE<Sint32>();
314 pPlayer->_px = file->nextLE<Sint32>();
315 pPlayer->_py = file->nextLE<Sint32>();
316 pPlayer->_pfutx = file->nextLE<Sint32>();
317 pPlayer->_pfuty = file->nextLE<Sint32>();
318 pPlayer->_ptargx = file->nextLE<Sint32>();
319 pPlayer->_ptargy = file->nextLE<Sint32>();
320 pPlayer->_pownerx = file->nextLE<Sint32>();
321 pPlayer->_pownery = file->nextLE<Sint32>();
322 pPlayer->_poldx = file->nextLE<Sint32>();
323 pPlayer->_poldy = file->nextLE<Sint32>();
324 pPlayer->_pxoff = file->nextLE<Sint32>();
325 pPlayer->_pyoff = file->nextLE<Sint32>();
326 pPlayer->_pxvel = file->nextLE<Sint32>();
327 pPlayer->_pyvel = file->nextLE<Sint32>();
328 pPlayer->_pdir = (direction)file->nextLE<Sint32>();
329 file->skip(4); // Unused
330 pPlayer->_pgfxnum = file->nextLE<Sint32>();
331 file->skip(4); // Skip pointer _pAnimData
332 pPlayer->_pAnimDelay = file->nextLE<Sint32>();
333 pPlayer->_pAnimCnt = file->nextLE<Sint32>();
334 pPlayer->_pAnimLen = file->nextLE<Sint32>();
335 pPlayer->_pAnimFrame = file->nextLE<Sint32>();
336 pPlayer->_pAnimWidth = file->nextLE<Sint32>();
337 pPlayer->_pAnimWidth2 = file->nextLE<Sint32>();
338 file->skip(4); // Skip _peflag
339 pPlayer->_plid = file->nextLE<Sint32>();
340 pPlayer->_pvid = file->nextLE<Sint32>();
341
342 pPlayer->_pSpell = (spell_id)file->nextLE<Sint32>();
343 pPlayer->_pSplType = (spell_type)file->nextLE<Sint8>();
344 pPlayer->_pSplFrom = file->nextLE<Sint8>();
345 file->skip(2); // Alignment
346 pPlayer->_pTSpell = (spell_id)file->nextLE<Sint32>();
347 pPlayer->_pTSplType = (spell_type)file->nextLE<Sint8>();
348 file->skip(3); // Alignment
349 pPlayer->_pRSpell = (spell_id)file->nextLE<Sint32>();
350 pPlayer->_pRSplType = (spell_type)file->nextLE<Sint8>();
351 file->skip(3); // Alignment
352 pPlayer->_pSBkSpell = (spell_id)file->nextLE<Sint32>();
353 pPlayer->_pSBkSplType = (spell_type)file->nextLE<Sint8>();
354 for (int i = 0; i < 64; i++)
355 pPlayer->_pSplLvl[i] = file->nextLE<Sint8>();
356 file->skip(7); // Alignment
357 pPlayer->_pMemSpells = file->nextLE<Uint64>();
358 pPlayer->_pAblSpells = file->nextLE<Uint64>();
359 pPlayer->_pScrlSpells = file->nextLE<Uint64>();
360 pPlayer->_pSpellFlags = file->nextLE<Uint8>();
361 file->skip(3); // Alignment
362 for (int i = 0; i < 4; i++)
363 pPlayer->_pSplHotKey[i] = (spell_id)file->nextLE<Sint32>();
364 for (int i = 0; i < 4; i++)
365 pPlayer->_pSplTHotKey[i] = (spell_type)file->nextLE<Sint8>();
366
367 pPlayer->_pwtype = (player_weapon_type)file->nextLE<Sint32>();
368 pPlayer->_pBlockFlag = file->nextBool8();
369 pPlayer->_pInvincible = file->nextBool8();
370 pPlayer->_pLightRad = file->nextLE<Sint8>();
371 pPlayer->_pLvlChanging = file->nextBool8();
372
373 file->nextBytes(pPlayer->_pName, PLR_NAME_LEN);
374 pPlayer->_pClass = (plr_class)file->nextLE<Sint8>();
375 file->skip(3); // Alignment
376 pPlayer->_pStrength = file->nextLE<Sint32>();
377 pPlayer->_pBaseStr = file->nextLE<Sint32>();
378 pPlayer->_pMagic = file->nextLE<Sint32>();
379 pPlayer->_pBaseMag = file->nextLE<Sint32>();
380 pPlayer->_pDexterity = file->nextLE<Sint32>();
381 pPlayer->_pBaseDex = file->nextLE<Sint32>();
382 pPlayer->_pVitality = file->nextLE<Sint32>();
383 pPlayer->_pBaseVit = file->nextLE<Sint32>();
384 pPlayer->_pStatPts = file->nextLE<Sint32>();
385 pPlayer->_pDamageMod = file->nextLE<Sint32>();
386 pPlayer->_pBaseToBlk = file->nextLE<Sint32>();
387 if (pPlayer->_pBaseToBlk == 0)
388 pPlayer->_pBaseToBlk = ToBlkTbl[pPlayer->_pClass];
389 pPlayer->_pHPBase = file->nextLE<Sint32>();
390 pPlayer->_pMaxHPBase = file->nextLE<Sint32>();
391 pPlayer->_pHitPoints = file->nextLE<Sint32>();
392 pPlayer->_pMaxHP = file->nextLE<Sint32>();
393 pPlayer->_pHPPer = file->nextLE<Sint32>();
394 pPlayer->_pManaBase = file->nextLE<Sint32>();
395 pPlayer->_pMaxManaBase = file->nextLE<Sint32>();
396 pPlayer->_pMana = file->nextLE<Sint32>();
397 pPlayer->_pMaxMana = file->nextLE<Sint32>();
398 pPlayer->_pManaPer = file->nextLE<Sint32>();
399 pPlayer->_pLevel = file->nextLE<Sint8>();
400 pPlayer->_pMaxLvl = file->nextLE<Sint8>();
401 file->skip(2); // Alignment
402 pPlayer->_pExperience = file->nextLE<Sint32>();
403 pPlayer->_pMaxExp = file->nextLE<Sint32>();
404 pPlayer->_pNextExper = file->nextLE<Sint32>();
405 pPlayer->_pArmorClass = file->nextLE<Sint8>();
406 pPlayer->_pMagResist = file->nextLE<Sint8>();
407 pPlayer->_pFireResist = file->nextLE<Sint8>();
408 pPlayer->_pLghtResist = file->nextLE<Sint8>();
409 pPlayer->_pGold = file->nextLE<Sint32>();
410
411 pPlayer->_pInfraFlag = file->nextBool32();
412 pPlayer->_pVar1 = file->nextLE<Sint32>();
413 pPlayer->_pVar2 = file->nextLE<Sint32>();
414 pPlayer->_pVar3 = (direction)file->nextLE<Sint32>();
415 pPlayer->_pVar4 = file->nextLE<Sint32>();
416 pPlayer->_pVar5 = file->nextLE<Sint32>();
417 pPlayer->_pVar6 = file->nextLE<Sint32>();
418 pPlayer->_pVar7 = file->nextLE<Sint32>();
419 pPlayer->_pVar8 = file->nextLE<Sint32>();
420 for (int i = 0; i < giNumberOfLevels; i++)
421 pPlayer->_pLvlVisited[i] = file->nextBool8();
422 for (int i = 0; i < giNumberOfLevels; i++)
423 pPlayer->_pSLvlVisited[i] = file->nextBool8();
424
425 file->skip(2); // Alignment
426
427 pPlayer->_pGFXLoad = file->nextLE<Sint32>();
428 file->skip(4 * 8); // Skip pointers _pNAnim
429 pPlayer->_pNFrames = file->nextLE<Sint32>();
430 pPlayer->_pNWidth = file->nextLE<Sint32>();
431 file->skip(4 * 8); // Skip pointers _pWAnim
432 pPlayer->_pWFrames = file->nextLE<Sint32>();
433 pPlayer->_pWWidth = file->nextLE<Sint32>();
434 file->skip(4 * 8); // Skip pointers _pAAnim
435 pPlayer->_pAFrames = file->nextLE<Sint32>();
436 pPlayer->_pAWidth = file->nextLE<Sint32>();
437 pPlayer->_pAFNum = file->nextLE<Sint32>();
438 file->skip(4 * 8); // Skip pointers _pLAnim
439 file->skip(4 * 8); // Skip pointers _pFAnim
440 file->skip(4 * 8); // Skip pointers _pTAnim
441 pPlayer->_pSFrames = file->nextLE<Sint32>();
442 pPlayer->_pSWidth = file->nextLE<Sint32>();
443 pPlayer->_pSFNum = file->nextLE<Sint32>();
444 file->skip(4 * 8); // Skip pointers _pHAnim
445 pPlayer->_pHFrames = file->nextLE<Sint32>();
446 pPlayer->_pHWidth = file->nextLE<Sint32>();
447 file->skip(4 * 8); // Skip pointers _pDAnim
448 pPlayer->_pDFrames = file->nextLE<Sint32>();
449 pPlayer->_pDWidth = file->nextLE<Sint32>();
450 file->skip(4 * 8); // Skip pointers _pBAnim
451 pPlayer->_pBFrames = file->nextLE<Sint32>();
452 pPlayer->_pBWidth = file->nextLE<Sint32>();
453
454 LoadItems(file, NUM_INVLOC, pPlayer->InvBody);
455 LoadItems(file, NUM_INV_GRID_ELEM, pPlayer->InvList);
456 pPlayer->_pNumInv = file->nextLE<Sint32>();
457 for (int i = 0; i < NUM_INV_GRID_ELEM; i++)
458 pPlayer->InvGrid[i] = file->nextLE<Sint8>();
459 LoadItems(file, MAXBELTITEMS, pPlayer->SpdList);
460 LoadItemData(file, &pPlayer->HoldItem);
461
462 pPlayer->_pIMinDam = file->nextLE<Sint32>();
463 pPlayer->_pIMaxDam = file->nextLE<Sint32>();
464 pPlayer->_pIAC = file->nextLE<Sint32>();
465 pPlayer->_pIBonusDam = file->nextLE<Sint32>();
466 pPlayer->_pIBonusToHit = file->nextLE<Sint32>();
467 pPlayer->_pIBonusAC = file->nextLE<Sint32>();
468 pPlayer->_pIBonusDamMod = file->nextLE<Sint32>();
469 file->skip(4); // Alignment
470
471 pPlayer->_pISpells = file->nextLE<Uint64>();
472 pPlayer->_pIFlags = file->nextLE<Sint32>();
473 pPlayer->_pIGetHit = file->nextLE<Sint32>();
474 pPlayer->_pISplLvlAdd = file->nextLE<Sint8>();
475 file->skip(1); // Unused
476 file->skip(2); // Alignment
477 pPlayer->_pISplDur = file->nextLE<Sint32>();
478 pPlayer->_pIEnAc = file->nextLE<Sint32>();
479 pPlayer->_pIFMinDam = file->nextLE<Sint32>();
480 pPlayer->_pIFMaxDam = file->nextLE<Sint32>();
481 pPlayer->_pILMinDam = file->nextLE<Sint32>();
482 pPlayer->_pILMaxDam = file->nextLE<Sint32>();
483 pPlayer->_pOilType = (item_misc_id)file->nextLE<Sint32>();
484 pPlayer->pTownWarps = file->nextLE<Uint8>();
485 pPlayer->pDungMsgs = file->nextLE<Uint8>();
486 pPlayer->pLvlLoad = file->nextLE<Uint8>();
487
488 if (gbIsHellfireSaveGame) {
489 pPlayer->pDungMsgs2 = file->nextLE<Uint8>();
490 pPlayer->pBattleNet = false;
491 } else {
492 pPlayer->pDungMsgs2 = 0;
493 pPlayer->pBattleNet = file->nextBool8();
494 }
495 pPlayer->pManaShield = file->nextBool8();
496 if (gbIsHellfireSaveGame) {
497 pPlayer->pOriginalCathedral = file->nextBool8();
498 } else {
499 file->skip(1);
500 pPlayer->pOriginalCathedral = true;
501 }
502 file->skip(2); // Available bytes
503 pPlayer->wReflections = file->nextLE<Uint16>();
504 file->skip(14); // Available bytes
505
506 pPlayer->pDiabloKillLevel = file->nextLE<Uint32>();
507 pPlayer->pDifficulty = file->nextLE<Uint32>();
508 pPlayer->pDamAcFlags = file->nextLE<Uint32>();
509 file->skip(20); // Available bytes
510 CalcPlrItemVals(p, FALSE);
511
512 // Omit pointer _pNData
513 // Omit pointer _pWData
514 // Omit pointer _pAData
515 // Omit pointer _pLData
516 // Omit pointer _pFData
517 // Omit pointer _pTData
518 // Omit pointer _pHData
519 // Omit pointer _pDData
520 // Omit pointer _pBData
521 // Omit pointer pReserved
522 }
523
524 bool gbSkipSync = false;
525
LoadMonster(LoadHelper * file,int i)526 static void LoadMonster(LoadHelper *file, int i)
527 {
528 MonsterStruct *pMonster = &monster[i];
529
530 pMonster->_mMTidx = file->nextLE<Sint32>();
531 pMonster->_mmode = (MON_MODE)file->nextLE<Sint32>();
532 pMonster->_mgoal = file->nextLE<Uint8>();
533 file->skip(3); // Alignment
534 pMonster->_mgoalvar1 = file->nextLE<Sint32>();
535 pMonster->_mgoalvar2 = file->nextLE<Sint32>();
536 pMonster->_mgoalvar3 = file->nextLE<Sint32>();
537 file->skip(4); // Unused
538 pMonster->_pathcount = file->nextLE<Uint8>();
539 file->skip(3); // Alignment
540 pMonster->_mx = file->nextLE<Sint32>();
541 pMonster->_my = file->nextLE<Sint32>();
542 pMonster->_mfutx = file->nextLE<Sint32>();
543 pMonster->_mfuty = file->nextLE<Sint32>();
544 pMonster->_moldx = file->nextLE<Sint32>();
545 pMonster->_moldy = file->nextLE<Sint32>();
546 pMonster->_mxoff = file->nextLE<Sint32>();
547 pMonster->_myoff = file->nextLE<Sint32>();
548 pMonster->_mxvel = file->nextLE<Sint32>();
549 pMonster->_myvel = file->nextLE<Sint32>();
550 pMonster->_mdir = file->nextLE<Sint32>();
551 pMonster->_menemy = file->nextLE<Sint32>();
552 pMonster->_menemyx = file->nextLE<Uint8>();
553 pMonster->_menemyy = file->nextLE<Uint8>();
554 file->skip(2); // Unused
555
556 file->skip(4); // Skip pointer _mAnimData
557 pMonster->_mAnimDelay = file->nextLE<Sint32>();
558 pMonster->_mAnimCnt = file->nextLE<Sint32>();
559 pMonster->_mAnimLen = file->nextLE<Sint32>();
560 pMonster->_mAnimFrame = file->nextLE<Sint32>();
561 file->skip(4); // Skip _meflag
562 pMonster->_mDelFlag = file->nextBool32();
563 pMonster->_mVar1 = file->nextLE<Sint32>();
564 pMonster->_mVar2 = file->nextLE<Sint32>();
565 pMonster->_mVar3 = file->nextLE<Sint32>();
566 pMonster->_mVar4 = file->nextLE<Sint32>();
567 pMonster->_mVar5 = file->nextLE<Sint32>();
568 pMonster->_mVar6 = file->nextLE<Sint32>();
569 pMonster->_mVar7 = file->nextLE<Sint32>();
570 pMonster->_mVar8 = file->nextLE<Sint32>();
571 pMonster->_mmaxhp = file->nextLE<Sint32>();
572 pMonster->_mhitpoints = file->nextLE<Sint32>();
573
574 pMonster->_mAi = (_mai_id)file->nextLE<Uint8>();
575 pMonster->_mint = file->nextLE<Uint8>();
576 file->skip(2); // Alignment
577 pMonster->_mFlags = file->nextLE<Uint32>();
578 pMonster->_msquelch = file->nextLE<Uint8>();
579 file->skip(3); // Alignment
580 file->skip(4); // Unused
581 pMonster->_lastx = file->nextLE<Sint32>();
582 pMonster->_lasty = file->nextLE<Sint32>();
583 pMonster->_mRndSeed = file->nextLE<Sint32>();
584 pMonster->_mAISeed = file->nextLE<Sint32>();
585 file->skip(4); // Unused
586
587 pMonster->_uniqtype = file->nextLE<Uint8>();
588 pMonster->_uniqtrans = file->nextLE<Uint8>();
589 pMonster->_udeadval = file->nextLE<Sint8>();
590
591 pMonster->mWhoHit = file->nextLE<Sint8>();
592 pMonster->mLevel = file->nextLE<Sint8>();
593 file->skip(1); // Alignment
594 pMonster->mExp = file->nextLE<Uint16>();
595
596 file->skip(1); // Skip mHit as it's already initialized
597 pMonster->mMinDamage = file->nextLE<Uint8>();
598 pMonster->mMaxDamage = file->nextLE<Uint8>();
599 file->skip(1); // Skip mHit2 as it's already initialized
600 pMonster->mMinDamage2 = file->nextLE<Uint8>();
601 pMonster->mMaxDamage2 = file->nextLE<Uint8>();
602 pMonster->mArmorClass = file->nextLE<Uint8>();
603 file->skip(1); // Alignment
604 pMonster->mMagicRes = file->nextLE<Uint16>();
605 file->skip(2); // Alignment
606
607 pMonster->mtalkmsg = file->nextLE<Sint32>();
608 pMonster->leader = file->nextLE<Uint8>();
609 pMonster->leaderflag = file->nextLE<Uint8>();
610 pMonster->packsize = file->nextLE<Uint8>();
611 pMonster->mlid = file->nextLE<Sint8>();
612 if (pMonster->mlid == plr[myplr]._plid)
613 pMonster->mlid = NO_LIGHT; // Correct incorect values in old saves
614
615 // Omit pointer mName;
616 // Omit pointer MType;
617 // Omit pointer MData;
618
619 if (gbSkipSync)
620 return;
621
622 SyncMonsterAnim(i);
623 }
624
LoadMissile(LoadHelper * file,int i)625 static void LoadMissile(LoadHelper *file, int i)
626 {
627 MissileStruct *pMissile = &missile[i];
628
629 pMissile->_mitype = file->nextLE<Sint32>();
630 pMissile->_mix = file->nextLE<Sint32>();
631 pMissile->_miy = file->nextLE<Sint32>();
632 pMissile->_mixoff = file->nextLE<Sint32>();
633 pMissile->_miyoff = file->nextLE<Sint32>();
634 pMissile->_mixvel = file->nextLE<Sint32>();
635 pMissile->_miyvel = file->nextLE<Sint32>();
636 pMissile->_misx = file->nextLE<Sint32>();
637 pMissile->_misy = file->nextLE<Sint32>();
638 pMissile->_mitxoff = file->nextLE<Sint32>();
639 pMissile->_mityoff = file->nextLE<Sint32>();
640 pMissile->_mimfnum = file->nextLE<Sint32>();
641 pMissile->_mispllvl = file->nextLE<Sint32>();
642 pMissile->_miDelFlag = file->nextBool32();
643 pMissile->_miAnimType = file->nextLE<Uint8>();
644 file->skip(3); // Alignment
645 pMissile->_miAnimFlags = file->nextLE<Sint32>();
646 file->skip(4); // Skip pointer _miAnimData
647 pMissile->_miAnimDelay = file->nextLE<Sint32>();
648 pMissile->_miAnimLen = file->nextLE<Sint32>();
649 pMissile->_miAnimWidth = file->nextLE<Sint32>();
650 pMissile->_miAnimWidth2 = file->nextLE<Sint32>();
651 pMissile->_miAnimCnt = file->nextLE<Sint32>();
652 pMissile->_miAnimAdd = file->nextLE<Sint32>();
653 pMissile->_miAnimFrame = file->nextLE<Sint32>();
654 pMissile->_miDrawFlag = file->nextBool32();
655 pMissile->_miLightFlag = file->nextBool32();
656 pMissile->_miPreFlag = file->nextBool32();
657 pMissile->_miUniqTrans = file->nextLE<Uint32>();
658 pMissile->_mirange = file->nextLE<Sint32>();
659 pMissile->_misource = file->nextLE<Sint32>();
660 pMissile->_micaster = file->nextLE<Sint32>();
661 pMissile->_midam = file->nextLE<Sint32>();
662 pMissile->_miHitFlag = file->nextBool32();
663 pMissile->_midist = file->nextLE<Sint32>();
664 pMissile->_mlid = file->nextLE<Sint32>();
665 pMissile->_mirnd = file->nextLE<Sint32>();
666 pMissile->_miVar1 = file->nextLE<Sint32>();
667 pMissile->_miVar2 = file->nextLE<Sint32>();
668 pMissile->_miVar3 = file->nextLE<Sint32>();
669 pMissile->_miVar4 = file->nextLE<Sint32>();
670 pMissile->_miVar5 = file->nextLE<Sint32>();
671 pMissile->_miVar6 = file->nextLE<Sint32>();
672 pMissile->_miVar7 = file->nextLE<Sint32>();
673 pMissile->_miVar8 = file->nextLE<Sint32>();
674 }
675
LoadObject(LoadHelper * file,int i)676 static void LoadObject(LoadHelper *file, int i)
677 {
678 ObjectStruct *pObject = &object[i];
679
680 pObject->_otype = file->nextLE<Sint32>();
681 pObject->_ox = file->nextLE<Sint32>();
682 pObject->_oy = file->nextLE<Sint32>();
683 pObject->_oLight = file->nextBool32();
684 pObject->_oAnimFlag = file->nextLE<Uint32>();
685 file->skip(4); // Skip pointer _oAnimData
686 pObject->_oAnimDelay = file->nextLE<Sint32>();
687 pObject->_oAnimCnt = file->nextLE<Sint32>();
688 pObject->_oAnimLen = file->nextLE<Sint32>();
689 pObject->_oAnimFrame = file->nextLE<Sint32>();
690 pObject->_oAnimWidth = file->nextLE<Sint32>();
691 pObject->_oAnimWidth2 = file->nextLE<Sint32>();
692 pObject->_oDelFlag = file->nextBool32();
693 pObject->_oBreak = file->nextLE<Sint8>();
694 file->skip(3); // Alignment
695 pObject->_oSolidFlag = file->nextBool32();
696 pObject->_oMissFlag = file->nextBool32();
697
698 pObject->_oSelFlag = file->nextLE<Sint8>();
699 file->skip(3); // Alignment
700 pObject->_oPreFlag = file->nextBool32();
701 pObject->_oTrapFlag = file->nextBool32();
702 pObject->_oDoorFlag = file->nextBool32();
703 pObject->_olid = file->nextLE<Sint32>();
704 pObject->_oRndSeed = file->nextLE<Sint32>();
705 pObject->_oVar1 = file->nextLE<Sint32>();
706 pObject->_oVar2 = file->nextLE<Sint32>();
707 pObject->_oVar3 = file->nextLE<Sint32>();
708 pObject->_oVar4 = file->nextLE<Sint32>();
709 pObject->_oVar5 = file->nextLE<Sint32>();
710 pObject->_oVar6 = file->nextLE<Sint32>();
711 pObject->_oVar7 = (_speech_id)file->nextLE<Sint32>();
712 pObject->_oVar8 = file->nextLE<Sint32>();
713 }
714
LoadItem(LoadHelper * file,int i)715 static void LoadItem(LoadHelper *file, int i)
716 {
717 LoadItemData(file, &item[i]);
718 GetItemFrm(i);
719 }
720
LoadPremium(LoadHelper * file,int i)721 static void LoadPremium(LoadHelper *file, int i)
722 {
723 LoadItemData(file, &premiumitem[i]);
724 }
725
LoadQuest(LoadHelper * file,int i)726 static void LoadQuest(LoadHelper *file, int i)
727 {
728 QuestStruct *pQuest = &quests[i];
729
730 pQuest->_qlevel = file->nextLE<Uint8>();
731 pQuest->_qtype = file->nextLE<Uint8>();
732 pQuest->_qactive = file->nextLE<Uint8>();
733 pQuest->_qlvltype = (dungeon_type)file->nextLE<Uint8>();
734 pQuest->_qtx = file->nextLE<Sint32>();
735 pQuest->_qty = file->nextLE<Sint32>();
736 pQuest->_qslvl = file->nextLE<Uint8>();
737 pQuest->_qidx = file->nextLE<Uint8>();
738 if (gbIsHellfireSaveGame) {
739 file->skip(2); // Alignment
740 pQuest->_qmsg = file->nextLE<Sint32>();
741 } else {
742 pQuest->_qmsg = file->nextLE<Uint8>();
743 }
744 pQuest->_qvar1 = file->nextLE<Uint8>();
745 pQuest->_qvar2 = file->nextLE<Uint8>();
746 file->skip(2); // Alignment
747 if (!gbIsHellfireSaveGame)
748 file->skip(1); // Alignment
749 pQuest->_qlog = file->nextBool32();
750
751 ReturnLvlX = file->nextBE<Sint32>();
752 ReturnLvlY = file->nextBE<Sint32>();
753 ReturnLvl = file->nextBE<Sint32>();
754 ReturnLvlT = (dungeon_type)file->nextBE<Sint32>();
755 DoomQuestState = file->nextBE<Sint32>();
756 }
757
LoadLighting(LoadHelper * file,LightListStruct * pLight)758 static void LoadLighting(LoadHelper *file, LightListStruct *pLight)
759 {
760 pLight->_lx = file->nextLE<Sint32>();
761 pLight->_ly = file->nextLE<Sint32>();
762 pLight->_lradius = file->nextLE<Sint32>();
763 pLight->_lid = file->nextLE<Sint32>();
764 pLight->_ldel = file->nextBool32();
765 pLight->_lunflag = file->nextBool32();
766 file->skip(4); // Unused
767 pLight->_lunx = file->nextLE<Sint32>();
768 pLight->_luny = file->nextLE<Sint32>();
769 pLight->_lunr = file->nextLE<Sint32>();
770 pLight->_xoff = file->nextLE<Sint32>();
771 pLight->_yoff = file->nextLE<Sint32>();
772 pLight->_lflags = file->nextBool32();
773 }
774
LoadPortal(LoadHelper * file,int i)775 static void LoadPortal(LoadHelper *file, int i)
776 {
777 PortalStruct *pPortal = &portal[i];
778
779 pPortal->open = file->nextBool32();
780 pPortal->x = file->nextLE<Sint32>();
781 pPortal->y = file->nextLE<Sint32>();
782 pPortal->level = file->nextLE<Sint32>();
783 pPortal->ltype = (dungeon_type)file->nextLE<Sint32>();
784 pPortal->setlvl = file->nextBool32();
785 }
786
RemapItemIdxFromDiablo(int i)787 int RemapItemIdxFromDiablo(int i)
788 {
789 if (i == IDI_SORCERER) {
790 return 166;
791 }
792 if (i >= 156) {
793 i += 5; // Hellfire exclusive items
794 }
795 if (i >= 88) {
796 i += 1; // Scroll of Search
797 }
798 if (i >= 83) {
799 i += 4; // Oils
800 }
801
802 return i;
803 }
804
RemapItemIdxToDiablo(int i)805 int RemapItemIdxToDiablo(int i)
806 {
807 if (i == 166) {
808 return IDI_SORCERER;
809 }
810 if ((i >= 83 && i <= 86) || i == 92 || i >= 161) {
811 return -1; // Hellfire exclusive items
812 }
813 if (i >= 93) {
814 i -= 1; // Scroll of Search
815 }
816 if (i >= 87) {
817 i -= 4; // Oils
818 }
819
820 return i;
821 }
822
IsHeaderValid(Uint32 magicNumber)823 bool IsHeaderValid(Uint32 magicNumber)
824 {
825 gbIsHellfireSaveGame = false;
826 if (magicNumber == LOAD_LE32("SHAR")) {
827 return true;
828 } else if (magicNumber == LOAD_LE32("SHLF")) {
829 gbIsHellfireSaveGame = true;
830 return true;
831 } else if (!gbIsSpawn && magicNumber == LOAD_LE32("RETL")) {
832 return true;
833 } else if (!gbIsSpawn && magicNumber == LOAD_LE32("HELF")) {
834 gbIsHellfireSaveGame = true;
835 return true;
836 }
837
838 return false;
839 }
840
ConvertLevels()841 static void ConvertLevels()
842 {
843 // Backup current level state
844 bool _setlevel = setlevel;
845 int _setlvlnum = setlvlnum;
846 int _currlevel = currlevel;
847 dungeon_type _leveltype = leveltype;
848
849 gbSkipSync = true;
850
851 setlevel = false; // Convert regular levels
852 for (int i = 0; i < giNumberOfLevels; i++) {
853 currlevel = i;
854 if (!LevelFileExists())
855 continue;
856
857 leveltype = gnLevelTypeTbl[i];
858
859 LoadLevel();
860 SaveLevel();
861 }
862
863 setlevel = true; // Convert quest levels
864 for (int i = 0; i < MAXQUESTS; i++) {
865 if (quests[i]._qactive == QUEST_NOTAVAIL) {
866 continue;
867 }
868
869 leveltype = quests[i]._qlvltype;
870 if (leveltype == DTYPE_NONE) {
871 continue;
872 }
873
874 setlvlnum = quests[i]._qslvl;
875 if (!LevelFileExists())
876 continue;
877
878 LoadLevel();
879 SaveLevel();
880 }
881
882 gbSkipSync = false;
883
884 // Restor current level state
885 setlevel = _setlevel;
886 setlvlnum = _setlvlnum;
887 currlevel = _currlevel;
888 leveltype = _leveltype;
889 }
890
LoadHotkeys()891 void LoadHotkeys()
892 {
893 LoadHelper file("hotkeys");
894 if (!file.isValid())
895 return;
896
897 const size_t nHotkeyTypes = sizeof(plr[myplr]._pSplHotKey) / sizeof(plr[myplr]._pSplHotKey[0]);
898 const size_t nHotkeySpells = sizeof(plr[myplr]._pSplTHotKey) / sizeof(plr[myplr]._pSplTHotKey[0]);
899
900 for (size_t i = 0; i < nHotkeyTypes; i++) {
901 plr[myplr]._pSplHotKey[i] = (spell_id)file.nextLE<Sint32>();
902 }
903 for (size_t i = 0; i < nHotkeySpells; i++) {
904 plr[myplr]._pSplTHotKey[i] = (spell_type)file.nextLE<Sint8>();
905 }
906 plr[myplr]._pRSpell = (spell_id)file.nextLE<Sint32>();
907 plr[myplr]._pRSplType = (spell_type)file.nextLE<Sint8>();
908 }
909
SaveHotkeys()910 void SaveHotkeys()
911 {
912 const size_t nHotkeyTypes = sizeof(plr[myplr]._pSplHotKey) / sizeof(plr[myplr]._pSplHotKey[0]);
913 const size_t nHotkeySpells = sizeof(plr[myplr]._pSplTHotKey) / sizeof(plr[myplr]._pSplTHotKey[0]);
914
915 SaveHelper file("hotkeys", (nHotkeyTypes * 4) + nHotkeySpells + 4 + 1);
916
917 for (size_t i = 0; i < nHotkeyTypes; i++) {
918 file.writeLE<Sint32>(plr[myplr]._pSplHotKey[i]);
919 }
920 for (size_t i = 0; i < nHotkeySpells; i++) {
921 file.writeLE<Uint8>(plr[myplr]._pSplTHotKey[i]);
922 }
923 file.writeLE<Sint32>(plr[myplr]._pRSpell);
924 file.writeLE<Uint8>(plr[myplr]._pRSplType);
925 }
926
LoadMatchingItems(LoadHelper * file,const int n,ItemStruct * pItem)927 static void LoadMatchingItems(LoadHelper *file, const int n, ItemStruct *pItem)
928 {
929 ItemStruct tempItem;
930
931 for (int i = 0; i < n; i++) {
932 LoadItemData(file, &tempItem);
933 if (pItem[i].isEmpty() || tempItem.isEmpty())
934 continue;
935 if (pItem[i]._iSeed != tempItem._iSeed)
936 continue;
937 pItem[i] = tempItem;
938 }
939 }
940
LoadHeroItems(PlayerStruct * pPlayer)941 void LoadHeroItems(PlayerStruct *pPlayer)
942 {
943 LoadHelper file("heroitems");
944 if (!file.isValid())
945 return;
946
947 gbIsHellfireSaveGame = file.nextBool8();
948
949 LoadMatchingItems(&file, NUM_INVLOC, pPlayer->InvBody);
950 LoadMatchingItems(&file, NUM_INV_GRID_ELEM, pPlayer->InvList);
951 LoadMatchingItems(&file, MAXBELTITEMS, pPlayer->SpdList);
952
953 gbIsHellfireSaveGame = gbIsHellfire;
954 }
955
RemoveEmptyInventory(int pnum)956 void RemoveEmptyInventory(int pnum)
957 {
958 for (int i = NUM_INV_GRID_ELEM; i > 0; i--) {
959 int idx = plr[pnum].InvGrid[i - 1];
960 if (idx > 0 && plr[pnum].InvList[idx - 1].isEmpty()) {
961 RemoveInvItem(pnum, idx - 1);
962 }
963 };
964 }
965
RemoveEmptyLevelItems()966 void RemoveEmptyLevelItems()
967 {
968 for (int i = numitems; i > 0; i--) {
969 int ii = itemactive[i];
970 if (item[ii].isEmpty()) {
971 dItem[item[ii]._ix][item[ii]._iy] = 0;
972 DeleteItem(ii, i);
973 }
974 }
975 }
976
977 /**
978 * @brief Load game state
979 * @param firstflag Can be set to false if we are simply reloading the current game
980 */
LoadGame(BOOL firstflag)981 void LoadGame(BOOL firstflag)
982 {
983 FreeGameMem();
984 pfile_remove_temp_files();
985
986 LoadHelper file("game");
987 if (!file.isValid())
988 app_fatal("Unable to open save file archive");
989
990 if (!IsHeaderValid(file.nextLE<Uint32>()))
991 app_fatal("Invalid save file");
992
993 if (gbIsHellfireSaveGame) {
994 giNumberOfLevels = 25;
995 giNumberQuests = 24;
996 giNumberOfSmithPremiumItems = 15;
997 } else {
998 // Todo initialize additional levels and quests if we are running Hellfire
999 giNumberOfLevels = 17;
1000 giNumberQuests = 16;
1001 giNumberOfSmithPremiumItems = 6;
1002 }
1003
1004 setlevel = file.nextBool8();
1005 setlvlnum = file.nextBE<Uint32>();
1006 currlevel = file.nextBE<Uint32>();
1007 leveltype = (dungeon_type)file.nextBE<Uint32>();
1008 if (!setlevel)
1009 leveltype = gnLevelTypeTbl[currlevel];
1010 int _ViewX = file.nextBE<Sint32>();
1011 int _ViewY = file.nextBE<Sint32>();
1012 invflag = file.nextBool8();
1013 chrflag = file.nextBool8();
1014 int _nummonsters = file.nextBE<Sint32>();
1015 int _numitems = file.nextBE<Sint32>();
1016 int _nummissiles = file.nextBE<Sint32>();
1017 int _nobjects = file.nextBE<Sint32>();
1018
1019 if (!gbIsHellfire && currlevel > 17)
1020 app_fatal("Player is on a Hellfire only level");
1021
1022 for (int i = 0; i < giNumberOfLevels; i++) {
1023 glSeedTbl[i] = file.nextBE<Uint32>();
1024 file.skip(4); // Skip loading gnLevelTypeTbl
1025 }
1026
1027 LoadPlayer(&file, myplr);
1028
1029 gnDifficulty = plr[myplr].pDifficulty;
1030 if (gnDifficulty < DIFF_NORMAL || gnDifficulty > DIFF_HELL)
1031 gnDifficulty = DIFF_NORMAL;
1032
1033 for (int i = 0; i < giNumberQuests; i++)
1034 LoadQuest(&file, i);
1035 for (int i = 0; i < MAXPORTAL; i++)
1036 LoadPortal(&file, i);
1037
1038 if (gbIsHellfireSaveGame != gbIsHellfire) {
1039 ConvertLevels();
1040 RemoveEmptyInventory(myplr);
1041 }
1042
1043 LoadGameLevel(firstflag, ENTRY_LOAD);
1044 SyncInitPlr(myplr);
1045 SyncPlrAnim(myplr);
1046
1047 ViewX = _ViewX;
1048 ViewY = _ViewY;
1049 nummonsters = _nummonsters;
1050 numitems = _numitems;
1051 nummissiles = _nummissiles;
1052 nobjects = _nobjects;
1053
1054 for (int i = 0; i < MAXMONSTERS; i++)
1055 monstkills[i] = file.nextBE<Sint32>();
1056
1057 if (leveltype != DTYPE_TOWN) {
1058 for (int i = 0; i < MAXMONSTERS; i++)
1059 monstactive[i] = file.nextBE<Sint32>();
1060 for (int i = 0; i < nummonsters; i++)
1061 LoadMonster(&file, monstactive[i]);
1062 for (int i = 0; i < MAXMISSILES; i++)
1063 missileactive[i] = file.nextLE<Sint8>();
1064 for (int i = 0; i < MAXMISSILES; i++)
1065 missileavail[i] = file.nextLE<Sint8>();
1066 for (int i = 0; i < nummissiles; i++)
1067 LoadMissile(&file, missileactive[i]);
1068 for (int i = 0; i < MAXOBJECTS; i++)
1069 objectactive[i] = file.nextLE<Sint8>();
1070 for (int i = 0; i < MAXOBJECTS; i++)
1071 objectavail[i] = file.nextLE<Sint8>();
1072 for (int i = 0; i < nobjects; i++)
1073 LoadObject(&file, objectactive[i]);
1074 for (int i = 0; i < nobjects; i++)
1075 SyncObjectAnim(objectactive[i]);
1076
1077 numlights = file.nextBE<Sint32>();
1078
1079 for (int i = 0; i < MAXLIGHTS; i++)
1080 lightactive[i] = file.nextLE<Uint8>();
1081 for (int i = 0; i < numlights; i++)
1082 LoadLighting(&file, &LightList[lightactive[i]]);
1083
1084 visionid = file.nextBE<Sint32>();
1085 numvision = file.nextBE<Sint32>();
1086
1087 for (int i = 0; i < numvision; i++)
1088 LoadLighting(&file, &VisionList[i]);
1089 }
1090
1091 for (int i = 0; i < MAXITEMS; i++)
1092 itemactive[i] = file.nextLE<Sint8>();
1093 for (int i = 0; i < MAXITEMS; i++)
1094 itemavail[i] = file.nextLE<Sint8>();
1095 for (int i = 0; i < numitems; i++)
1096 LoadItem(&file, itemactive[i]);
1097 for (int i = 0; i < 128; i++)
1098 UniqueItemFlag[i] = file.nextBool8();
1099
1100 for (int j = 0; j < MAXDUNY; j++) {
1101 for (int i = 0; i < MAXDUNX; i++)
1102 dLight[i][j] = file.nextLE<Sint8>();
1103 }
1104 for (int j = 0; j < MAXDUNY; j++) {
1105 for (int i = 0; i < MAXDUNX; i++)
1106 dFlags[i][j] = file.nextLE<Sint8>();
1107 }
1108 for (int j = 0; j < MAXDUNY; j++) {
1109 for (int i = 0; i < MAXDUNX; i++)
1110 dPlayer[i][j] = file.nextLE<Sint8>();
1111 }
1112 for (int j = 0; j < MAXDUNY; j++) {
1113 for (int i = 0; i < MAXDUNX; i++)
1114 dItem[i][j] = file.nextLE<Sint8>();
1115 }
1116
1117 if (leveltype != DTYPE_TOWN) {
1118 for (int j = 0; j < MAXDUNY; j++) {
1119 for (int i = 0; i < MAXDUNX; i++)
1120 dMonster[i][j] = file.nextBE<Sint32>();
1121 }
1122 for (int j = 0; j < MAXDUNY; j++) {
1123 for (int i = 0; i < MAXDUNX; i++)
1124 dDead[i][j] = file.nextLE<Sint8>();
1125 }
1126 for (int j = 0; j < MAXDUNY; j++) {
1127 for (int i = 0; i < MAXDUNX; i++)
1128 dObject[i][j] = file.nextLE<Sint8>();
1129 }
1130 for (int j = 0; j < MAXDUNY; j++) {
1131 for (int i = 0; i < MAXDUNX; i++)
1132 dLight[i][j] = file.nextLE<Sint8>();
1133 }
1134 for (int j = 0; j < MAXDUNY; j++) {
1135 for (int i = 0; i < MAXDUNX; i++)
1136 dPreLight[i][j] = file.nextLE<Sint8>();
1137 }
1138 for (int j = 0; j < DMAXY; j++) {
1139 for (int i = 0; i < DMAXX; i++)
1140 automapview[i][j] = file.nextBool8();
1141 }
1142 for (int j = 0; j < MAXDUNY; j++) {
1143 for (int i = 0; i < MAXDUNX; i++)
1144 dMissile[i][j] = file.nextLE<Sint8>();
1145 }
1146 }
1147
1148 numpremium = file.nextBE<Sint32>();
1149 premiumlevel = file.nextBE<Sint32>();
1150
1151 for (int i = 0; i < giNumberOfSmithPremiumItems; i++)
1152 LoadPremium(&file, i);
1153 if (gbIsHellfire && !gbIsHellfireSaveGame)
1154 SpawnPremium(myplr);
1155
1156 automapflag = file.nextBool8();
1157 AutoMapScale = file.nextBE<Sint32>();
1158 AutomapZoomReset();
1159 ResyncQuests();
1160
1161 if (leveltype != DTYPE_TOWN)
1162 ProcessLightList();
1163
1164 RedoPlayerVision();
1165 ProcessVisionList();
1166 missiles_process_charge();
1167 ResetPal();
1168 SetCursor_(CURSOR_HAND);
1169 gbProcessPlayers = TRUE;
1170
1171 if (gbIsHellfireSaveGame != gbIsHellfire) {
1172 RemoveEmptyLevelItems();
1173 SaveGame();
1174 }
1175
1176 gbIsHellfireSaveGame = gbIsHellfire;
1177 }
1178
SaveItem(SaveHelper * file,ItemStruct * pItem)1179 static void SaveItem(SaveHelper *file, ItemStruct *pItem)
1180 {
1181 int idx = pItem->IDidx;
1182 if (!gbIsHellfire)
1183 idx = RemapItemIdxToDiablo(idx);
1184 int iType = pItem->_itype;
1185 if (idx == -1) {
1186 idx = 0;
1187 iType = ITYPE_NONE;
1188 }
1189
1190 file->writeLE<Sint32>(pItem->_iSeed);
1191 file->writeLE<Sint16>(pItem->_iCreateInfo);
1192 file->skip(2); // Alignment
1193 file->writeLE<Sint32>(iType);
1194 file->writeLE<Sint32>(pItem->_ix);
1195 file->writeLE<Sint32>(pItem->_iy);
1196 file->writeLE<Uint32>(pItem->_iAnimFlag);
1197 file->skip(4); // Skip pointer _iAnimData
1198 file->writeLE<Sint32>(pItem->_iAnimLen);
1199 file->writeLE<Sint32>(pItem->_iAnimFrame);
1200 file->writeLE<Sint32>(pItem->_iAnimWidth);
1201 file->writeLE<Sint32>(pItem->_iAnimWidth2);
1202 file->skip(4); // Unused since 1.02
1203 file->writeLE<Uint8>(pItem->_iSelFlag);
1204 file->skip(3); // Alignment
1205 file->writeLE<Uint32>(pItem->_iPostDraw);
1206 file->writeLE<Uint32>(pItem->_iIdentified);
1207 file->writeLE<Sint8>(pItem->_iMagical);
1208 file->writeBytes(pItem->_iName, 64);
1209 file->writeBytes(pItem->_iIName, 64);
1210 file->writeLE<Sint8>(pItem->_iLoc);
1211 file->writeLE<Uint8>(pItem->_iClass);
1212 file->skip(1); // Alignment
1213 file->writeLE<Sint32>(pItem->_iCurs);
1214 file->writeLE<Sint32>(pItem->_ivalue);
1215 file->writeLE<Sint32>(pItem->_iIvalue);
1216 file->writeLE<Sint32>(pItem->_iMinDam);
1217 file->writeLE<Sint32>(pItem->_iMaxDam);
1218 file->writeLE<Sint32>(pItem->_iAC);
1219 file->writeLE<Sint32>(pItem->_iFlags);
1220 file->writeLE<Sint32>(pItem->_iMiscId);
1221 file->writeLE<Sint32>(pItem->_iSpell);
1222 file->writeLE<Sint32>(pItem->_iCharges);
1223 file->writeLE<Sint32>(pItem->_iMaxCharges);
1224 file->writeLE<Sint32>(pItem->_iDurability);
1225 file->writeLE<Sint32>(pItem->_iMaxDur);
1226 file->writeLE<Sint32>(pItem->_iPLDam);
1227 file->writeLE<Sint32>(pItem->_iPLToHit);
1228 file->writeLE<Sint32>(pItem->_iPLAC);
1229 file->writeLE<Sint32>(pItem->_iPLStr);
1230 file->writeLE<Sint32>(pItem->_iPLMag);
1231 file->writeLE<Sint32>(pItem->_iPLDex);
1232 file->writeLE<Sint32>(pItem->_iPLVit);
1233 file->writeLE<Sint32>(pItem->_iPLFR);
1234 file->writeLE<Sint32>(pItem->_iPLLR);
1235 file->writeLE<Sint32>(pItem->_iPLMR);
1236 file->writeLE<Sint32>(pItem->_iPLMana);
1237 file->writeLE<Sint32>(pItem->_iPLHP);
1238 file->writeLE<Sint32>(pItem->_iPLDamMod);
1239 file->writeLE<Sint32>(pItem->_iPLGetHit);
1240 file->writeLE<Sint32>(pItem->_iPLLight);
1241 file->writeLE<Sint8>(pItem->_iSplLvlAdd);
1242 file->writeLE<Sint8>(pItem->_iRequest);
1243 file->skip(2); // Alignment
1244 file->writeLE<Sint32>(pItem->_iUid);
1245 file->writeLE<Sint32>(pItem->_iFMinDam);
1246 file->writeLE<Sint32>(pItem->_iFMaxDam);
1247 file->writeLE<Sint32>(pItem->_iLMinDam);
1248 file->writeLE<Sint32>(pItem->_iLMaxDam);
1249 file->writeLE<Sint32>(pItem->_iPLEnAc);
1250 file->writeLE<Sint8>(pItem->_iPrePower);
1251 file->writeLE<Sint8>(pItem->_iSufPower);
1252 file->skip(2); // Alignment
1253 file->writeLE<Sint32>(pItem->_iVAdd1);
1254 file->writeLE<Sint32>(pItem->_iVMult1);
1255 file->writeLE<Sint32>(pItem->_iVAdd2);
1256 file->writeLE<Sint32>(pItem->_iVMult2);
1257 file->writeLE<Sint8>(pItem->_iMinStr);
1258 file->writeLE<Uint8>(pItem->_iMinMag);
1259 file->writeLE<Sint8>(pItem->_iMinDex);
1260 file->skip(1); // Alignment
1261 file->writeLE<Uint32>(pItem->_iStatFlag);
1262 file->writeLE<Sint32>(idx);
1263 file->writeLE<Uint32>(pItem->dwBuff);
1264 if (gbIsHellfire)
1265 file->writeLE<Uint32>(pItem->_iDamAcFlags);
1266 }
1267
SaveItems(SaveHelper * file,ItemStruct * pItem,const int n)1268 static void SaveItems(SaveHelper *file, ItemStruct *pItem, const int n)
1269 {
1270 for (int i = 0; i < n; i++) {
1271 SaveItem(file, &pItem[i]);
1272 }
1273 }
1274
SavePlayer(SaveHelper * file,int p)1275 static void SavePlayer(SaveHelper *file, int p)
1276 {
1277 PlayerStruct *pPlayer = &plr[p];
1278
1279 file->writeLE<Sint32>(pPlayer->_pmode);
1280 for (int i = 0; i < MAX_PATH_LENGTH; i++)
1281 file->writeLE<Sint8>(pPlayer->walkpath[i]);
1282 file->writeLE<Uint8>(pPlayer->plractive);
1283 file->skip(2); // Alignment
1284 file->writeLE<Sint32>(pPlayer->destAction);
1285 file->writeLE<Sint32>(pPlayer->destParam1);
1286 file->writeLE<Sint32>(pPlayer->destParam2);
1287 file->writeLE<Sint32>(pPlayer->destParam3);
1288 file->writeLE<Sint32>(pPlayer->destParam4);
1289 file->writeLE<Sint32>(pPlayer->plrlevel);
1290 file->writeLE<Sint32>(pPlayer->_px);
1291 file->writeLE<Sint32>(pPlayer->_py);
1292 file->writeLE<Sint32>(pPlayer->_pfutx);
1293 file->writeLE<Sint32>(pPlayer->_pfuty);
1294 file->writeLE<Sint32>(pPlayer->_ptargx);
1295 file->writeLE<Sint32>(pPlayer->_ptargy);
1296 file->writeLE<Sint32>(pPlayer->_pownerx);
1297 file->writeLE<Sint32>(pPlayer->_pownery);
1298 file->writeLE<Sint32>(pPlayer->_poldx);
1299 file->writeLE<Sint32>(pPlayer->_poldy);
1300 file->writeLE<Sint32>(pPlayer->_pxoff);
1301 file->writeLE<Sint32>(pPlayer->_pyoff);
1302 file->writeLE<Sint32>(pPlayer->_pxvel);
1303 file->writeLE<Sint32>(pPlayer->_pyvel);
1304 file->writeLE<Sint32>(pPlayer->_pdir);
1305 file->skip(4); // Unused
1306 file->writeLE<Sint32>(pPlayer->_pgfxnum);
1307 file->skip(4); // Skip pointer _pAnimData
1308 file->writeLE<Sint32>(pPlayer->_pAnimDelay);
1309 file->writeLE<Sint32>(pPlayer->_pAnimCnt);
1310 file->writeLE<Sint32>(pPlayer->_pAnimLen);
1311 file->writeLE<Sint32>(pPlayer->_pAnimFrame);
1312 file->writeLE<Sint32>(pPlayer->_pAnimWidth);
1313 file->writeLE<Sint32>(pPlayer->_pAnimWidth2);
1314 file->skip(4); // Skip _peflag
1315 file->writeLE<Sint32>(pPlayer->_plid);
1316 file->writeLE<Sint32>(pPlayer->_pvid);
1317
1318 file->writeLE<Sint32>(pPlayer->_pSpell);
1319 file->writeLE<Sint8>(pPlayer->_pSplType);
1320 file->writeLE<Sint8>(pPlayer->_pSplFrom);
1321 file->skip(2); // Alignment
1322 file->writeLE<Sint32>(pPlayer->_pTSpell);
1323 file->writeLE<Sint8>(pPlayer->_pTSplType);
1324 file->skip(3); // Alignment
1325 file->writeLE<Sint32>(pPlayer->_pRSpell);
1326 file->writeLE<Sint8>(pPlayer->_pRSplType);
1327 file->skip(3); // Alignment
1328 file->writeLE<Sint32>(pPlayer->_pSBkSpell);
1329 file->writeLE<Sint8>(pPlayer->_pSBkSplType);
1330 for (int i = 0; i < 64; i++)
1331 file->writeLE<Sint8>(pPlayer->_pSplLvl[i]);
1332 file->skip(7); // Alignment
1333 file->writeLE<Uint64>(pPlayer->_pMemSpells);
1334 file->writeLE<Uint64>(pPlayer->_pAblSpells);
1335 file->writeLE<Uint64>(pPlayer->_pScrlSpells);
1336 file->writeLE<Uint8>(pPlayer->_pSpellFlags);
1337 file->skip(3); // Alignment
1338 for (int i = 0; i < 4; i++)
1339 file->writeLE<Sint32>(pPlayer->_pSplHotKey[i]);
1340 for (int i = 0; i < 4; i++)
1341 file->writeLE<Sint8>(pPlayer->_pSplTHotKey[i]);
1342
1343 file->writeLE<Sint32>(pPlayer->_pwtype);
1344 file->writeLE<Uint8>(pPlayer->_pBlockFlag);
1345 file->writeLE<Uint8>(pPlayer->_pInvincible);
1346 file->writeLE<Sint8>(pPlayer->_pLightRad);
1347 file->writeLE<Uint8>(pPlayer->_pLvlChanging);
1348
1349 file->writeBytes(pPlayer->_pName, PLR_NAME_LEN);
1350 file->writeLE<Sint8>(pPlayer->_pClass);
1351 file->skip(3); // Alignment
1352 file->writeLE<Sint32>(pPlayer->_pStrength);
1353 file->writeLE<Sint32>(pPlayer->_pBaseStr);
1354 file->writeLE<Sint32>(pPlayer->_pMagic);
1355 file->writeLE<Sint32>(pPlayer->_pBaseMag);
1356 file->writeLE<Sint32>(pPlayer->_pDexterity);
1357 file->writeLE<Sint32>(pPlayer->_pBaseDex);
1358 file->writeLE<Sint32>(pPlayer->_pVitality);
1359 file->writeLE<Sint32>(pPlayer->_pBaseVit);
1360 file->writeLE<Sint32>(pPlayer->_pStatPts);
1361 file->writeLE<Sint32>(pPlayer->_pDamageMod);
1362
1363 file->writeLE<Sint32>(pPlayer->_pBaseToBlk);
1364 file->writeLE<Sint32>(pPlayer->_pHPBase);
1365 file->writeLE<Sint32>(pPlayer->_pMaxHPBase);
1366 file->writeLE<Sint32>(pPlayer->_pHitPoints);
1367 file->writeLE<Sint32>(pPlayer->_pMaxHP);
1368 file->writeLE<Sint32>(pPlayer->_pHPPer);
1369 file->writeLE<Sint32>(pPlayer->_pManaBase);
1370 file->writeLE<Sint32>(pPlayer->_pMaxManaBase);
1371 file->writeLE<Sint32>(pPlayer->_pMana);
1372 file->writeLE<Sint32>(pPlayer->_pMaxMana);
1373 file->writeLE<Sint32>(pPlayer->_pManaPer);
1374 file->writeLE<Sint8>(pPlayer->_pLevel);
1375 file->writeLE<Sint8>(pPlayer->_pMaxLvl);
1376 file->skip(2); // Alignment
1377 file->writeLE<Sint32>(pPlayer->_pExperience);
1378 file->writeLE<Sint32>(pPlayer->_pMaxExp);
1379 file->writeLE<Sint32>(pPlayer->_pNextExper);
1380 file->writeLE<Sint8>(pPlayer->_pArmorClass);
1381 file->writeLE<Sint8>(pPlayer->_pMagResist);
1382 file->writeLE<Sint8>(pPlayer->_pFireResist);
1383 file->writeLE<Sint8>(pPlayer->_pLghtResist);
1384 file->writeLE<Sint32>(pPlayer->_pGold);
1385
1386 file->writeLE<Uint32>(pPlayer->_pInfraFlag);
1387 file->writeLE<Sint32>(pPlayer->_pVar1);
1388 file->writeLE<Sint32>(pPlayer->_pVar2);
1389 file->writeLE<Sint32>(pPlayer->_pVar3);
1390 file->writeLE<Sint32>(pPlayer->_pVar4);
1391 file->writeLE<Sint32>(pPlayer->_pVar5);
1392 file->writeLE<Sint32>(pPlayer->_pVar6);
1393 file->writeLE<Sint32>(pPlayer->_pVar7);
1394 file->writeLE<Sint32>(pPlayer->_pVar8);
1395 for (int i = 0; i < giNumberOfLevels; i++)
1396 file->writeLE<Uint8>(pPlayer->_pLvlVisited[i]);
1397 for (int i = 0; i < giNumberOfLevels; i++)
1398 file->writeLE<Uint8>(pPlayer->_pSLvlVisited[i]); // only 10 used
1399
1400 file->skip(2); // Alignment
1401
1402 file->writeLE<Sint32>(pPlayer->_pGFXLoad);
1403 file->skip(4 * 8); // Skip pointers _pNAnim
1404 file->writeLE<Sint32>(pPlayer->_pNFrames);
1405 file->writeLE<Sint32>(pPlayer->_pNWidth);
1406 file->skip(4 * 8); // Skip pointers _pWAnim
1407 file->writeLE<Sint32>(pPlayer->_pWFrames);
1408 file->writeLE<Sint32>(pPlayer->_pWWidth);
1409 file->skip(4 * 8); // Skip pointers _pAAnim
1410 file->writeLE<Sint32>(pPlayer->_pAFrames);
1411 file->writeLE<Sint32>(pPlayer->_pAWidth);
1412 file->writeLE<Sint32>(pPlayer->_pAFNum);
1413 file->skip(4 * 8); // Skip pointers _pLAnim
1414 file->skip(4 * 8); // Skip pointers _pFAnim
1415 file->skip(4 * 8); // Skip pointers _pTAnim
1416 file->writeLE<Sint32>(pPlayer->_pSFrames);
1417 file->writeLE<Sint32>(pPlayer->_pSWidth);
1418 file->writeLE<Sint32>(pPlayer->_pSFNum);
1419 file->skip(4 * 8); // Skip pointers _pHAnim
1420 file->writeLE<Sint32>(pPlayer->_pHFrames);
1421 file->writeLE<Sint32>(pPlayer->_pHWidth);
1422 file->skip(4 * 8); // Skip pointers _pDAnim
1423 file->writeLE<Sint32>(pPlayer->_pDFrames);
1424 file->writeLE<Sint32>(pPlayer->_pDWidth);
1425 file->skip(4 * 8); // Skip pointers _pBAnim
1426 file->writeLE<Sint32>(pPlayer->_pBFrames);
1427 file->writeLE<Sint32>(pPlayer->_pBWidth);
1428
1429 SaveItems(file, pPlayer->InvBody, NUM_INVLOC);
1430 SaveItems(file, pPlayer->InvList, NUM_INV_GRID_ELEM);
1431 file->writeLE<Sint32>(pPlayer->_pNumInv);
1432 for (int i = 0; i < NUM_INV_GRID_ELEM; i++)
1433 file->writeLE<Sint8>(pPlayer->InvGrid[i]);
1434 SaveItems(file, pPlayer->SpdList, MAXBELTITEMS);
1435 SaveItem(file, &pPlayer->HoldItem);
1436
1437 file->writeLE<Sint32>(pPlayer->_pIMinDam);
1438 file->writeLE<Sint32>(pPlayer->_pIMaxDam);
1439 file->writeLE<Sint32>(pPlayer->_pIAC);
1440 file->writeLE<Sint32>(pPlayer->_pIBonusDam);
1441 file->writeLE<Sint32>(pPlayer->_pIBonusToHit);
1442 file->writeLE<Sint32>(pPlayer->_pIBonusAC);
1443 file->writeLE<Sint32>(pPlayer->_pIBonusDamMod);
1444 file->skip(4); // Alignment
1445
1446 file->writeLE<Uint64>(pPlayer->_pISpells);
1447 file->writeLE<Sint32>(pPlayer->_pIFlags);
1448 file->writeLE<Sint32>(pPlayer->_pIGetHit);
1449
1450 file->writeLE<Sint8>(pPlayer->_pISplLvlAdd);
1451 file->skip(1); // Unused
1452 file->skip(2); // Alignment
1453 file->writeLE<Sint32>(pPlayer->_pISplDur);
1454 file->writeLE<Sint32>(pPlayer->_pIEnAc);
1455 file->writeLE<Sint32>(pPlayer->_pIFMinDam);
1456 file->writeLE<Sint32>(pPlayer->_pIFMaxDam);
1457 file->writeLE<Sint32>(pPlayer->_pILMinDam);
1458 file->writeLE<Sint32>(pPlayer->_pILMaxDam);
1459 file->writeLE<Sint32>(pPlayer->_pOilType);
1460 file->writeLE<Uint8>(pPlayer->pTownWarps);
1461 file->writeLE<Uint8>(pPlayer->pDungMsgs);
1462 file->writeLE<Uint8>(pPlayer->pLvlLoad);
1463 if (gbIsHellfire)
1464 file->writeLE<Uint8>(pPlayer->pDungMsgs2);
1465 else
1466 file->writeLE<Uint8>(pPlayer->pBattleNet);
1467 file->writeLE<Uint8>(pPlayer->pManaShield);
1468 file->writeLE<Uint8>(pPlayer->pOriginalCathedral);
1469 file->skip(2); // Available bytes
1470 file->writeLE<Uint16>(pPlayer->wReflections);
1471 file->skip(14); // Available bytes
1472
1473 file->writeLE<Uint32>(pPlayer->pDiabloKillLevel);
1474 file->writeLE<Uint32>(pPlayer->pDifficulty);
1475 file->writeLE<Uint32>(pPlayer->pDamAcFlags);
1476 file->skip(20); // Available bytes
1477
1478 // Omit pointer _pNData
1479 // Omit pointer _pWData
1480 // Omit pointer _pAData
1481 // Omit pointer _pLData
1482 // Omit pointer _pFData
1483 // Omit pointer _pTData
1484 // Omit pointer _pHData
1485 // Omit pointer _pDData
1486 // Omit pointer _pBData
1487 // Omit pointer pReserved
1488 }
1489
SaveMonster(SaveHelper * file,int i)1490 static void SaveMonster(SaveHelper *file, int i)
1491 {
1492 MonsterStruct *pMonster = &monster[i];
1493
1494 file->writeLE<Sint32>(pMonster->_mMTidx);
1495 file->writeLE<Sint32>(pMonster->_mmode);
1496 file->writeLE<Uint8>(pMonster->_mgoal);
1497 file->skip(3); // Alignment
1498 file->writeLE<Sint32>(pMonster->_mgoalvar1);
1499 file->writeLE<Sint32>(pMonster->_mgoalvar2);
1500 file->writeLE<Sint32>(pMonster->_mgoalvar3);
1501 file->skip(4); // Unused
1502 file->writeLE<Uint8>(pMonster->_pathcount);
1503 file->skip(3); // Alignment
1504 file->writeLE<Sint32>(pMonster->_mx);
1505 file->writeLE<Sint32>(pMonster->_my);
1506 file->writeLE<Sint32>(pMonster->_mfutx);
1507 file->writeLE<Sint32>(pMonster->_mfuty);
1508 file->writeLE<Sint32>(pMonster->_moldx);
1509 file->writeLE<Sint32>(pMonster->_moldy);
1510 file->writeLE<Sint32>(pMonster->_mxoff);
1511 file->writeLE<Sint32>(pMonster->_myoff);
1512 file->writeLE<Sint32>(pMonster->_mxvel);
1513 file->writeLE<Sint32>(pMonster->_myvel);
1514 file->writeLE<Sint32>(pMonster->_mdir);
1515 file->writeLE<Sint32>(pMonster->_menemy);
1516 file->writeLE<Uint8>(pMonster->_menemyx);
1517 file->writeLE<Uint8>(pMonster->_menemyy);
1518 file->skip(2); // Unused
1519
1520 file->skip(4); // Skip pointer _mAnimData
1521 file->writeLE<Sint32>(pMonster->_mAnimDelay);
1522 file->writeLE<Sint32>(pMonster->_mAnimCnt);
1523 file->writeLE<Sint32>(pMonster->_mAnimLen);
1524 file->writeLE<Sint32>(pMonster->_mAnimFrame);
1525 file->skip(4); // Skip _meflag
1526 file->writeLE<Uint32>(pMonster->_mDelFlag);
1527 file->writeLE<Sint32>(pMonster->_mVar1);
1528 file->writeLE<Sint32>(pMonster->_mVar2);
1529 file->writeLE<Sint32>(pMonster->_mVar3);
1530 file->writeLE<Sint32>(pMonster->_mVar4);
1531 file->writeLE<Sint32>(pMonster->_mVar5);
1532 file->writeLE<Sint32>(pMonster->_mVar6);
1533 file->writeLE<Sint32>(pMonster->_mVar7);
1534 file->writeLE<Sint32>(pMonster->_mVar8);
1535 file->writeLE<Sint32>(pMonster->_mmaxhp);
1536 file->writeLE<Sint32>(pMonster->_mhitpoints);
1537
1538 file->writeLE<Uint8>(pMonster->_mAi);
1539 file->writeLE<Uint8>(pMonster->_mint);
1540 file->skip(2); // Alignment
1541 file->writeLE<Uint32>(pMonster->_mFlags);
1542 file->writeLE<Uint8>(pMonster->_msquelch);
1543 file->skip(3); // Alignment
1544 file->skip(4); // Unused
1545 file->writeLE<Sint32>(pMonster->_lastx);
1546 file->writeLE<Sint32>(pMonster->_lasty);
1547 file->writeLE<Sint32>(pMonster->_mRndSeed);
1548 file->writeLE<Sint32>(pMonster->_mAISeed);
1549 file->skip(4); // Unused
1550
1551 file->writeLE<Uint8>(pMonster->_uniqtype);
1552 file->writeLE<Uint8>(pMonster->_uniqtrans);
1553 file->writeLE<Sint8>(pMonster->_udeadval);
1554
1555 file->writeLE<Sint8>(pMonster->mWhoHit);
1556 file->writeLE<Sint8>(pMonster->mLevel);
1557 file->skip(1); // Alignment
1558 file->writeLE<Uint16>(pMonster->mExp);
1559
1560 file->writeLE<Uint8>(pMonster->mHit < SCHAR_MAX ? pMonster->mHit : SCHAR_MAX); // For backwards compatibility
1561 file->writeLE<Uint8>(pMonster->mMinDamage);
1562 file->writeLE<Uint8>(pMonster->mMaxDamage);
1563 file->writeLE<Uint8>(pMonster->mHit2 < SCHAR_MAX ? pMonster->mHit2 : SCHAR_MAX); // For backwards compatibility
1564 file->writeLE<Uint8>(pMonster->mMinDamage2);
1565 file->writeLE<Uint8>(pMonster->mMaxDamage2);
1566 file->writeLE<Uint8>(pMonster->mArmorClass);
1567 file->skip(1); // Alignment
1568 file->writeLE<Uint16>(pMonster->mMagicRes);
1569 file->skip(2); // Alignment
1570
1571 file->writeLE<Sint32>(pMonster->mtalkmsg);
1572 file->writeLE<Uint8>(pMonster->leader);
1573 file->writeLE<Uint8>(pMonster->leaderflag);
1574 file->writeLE<Uint8>(pMonster->packsize);
1575 file->writeLE<Sint8>(pMonster->mlid);
1576
1577 // Omit pointer mName;
1578 // Omit pointer MType;
1579 // Omit pointer MData;
1580 }
1581
SaveMissile(SaveHelper * file,int i)1582 static void SaveMissile(SaveHelper *file, int i)
1583 {
1584 MissileStruct *pMissile = &missile[i];
1585
1586 file->writeLE<Sint32>(pMissile->_mitype);
1587 file->writeLE<Sint32>(pMissile->_mix);
1588 file->writeLE<Sint32>(pMissile->_miy);
1589 file->writeLE<Sint32>(pMissile->_mixoff);
1590 file->writeLE<Sint32>(pMissile->_miyoff);
1591 file->writeLE<Sint32>(pMissile->_mixvel);
1592 file->writeLE<Sint32>(pMissile->_miyvel);
1593 file->writeLE<Sint32>(pMissile->_misx);
1594 file->writeLE<Sint32>(pMissile->_misy);
1595 file->writeLE<Sint32>(pMissile->_mitxoff);
1596 file->writeLE<Sint32>(pMissile->_mityoff);
1597 file->writeLE<Sint32>(pMissile->_mimfnum);
1598 file->writeLE<Sint32>(pMissile->_mispllvl);
1599 file->writeLE<Uint32>(pMissile->_miDelFlag);
1600 file->writeLE<Uint8>(pMissile->_miAnimType);
1601 file->skip(3); // Alignment
1602 file->writeLE<Sint32>(pMissile->_miAnimFlags);
1603 file->skip(4); // Skip pointer _miAnimData
1604 file->writeLE<Sint32>(pMissile->_miAnimDelay);
1605 file->writeLE<Sint32>(pMissile->_miAnimLen);
1606 file->writeLE<Sint32>(pMissile->_miAnimWidth);
1607 file->writeLE<Sint32>(pMissile->_miAnimWidth2);
1608 file->writeLE<Sint32>(pMissile->_miAnimCnt);
1609 file->writeLE<Sint32>(pMissile->_miAnimAdd);
1610 file->writeLE<Sint32>(pMissile->_miAnimFrame);
1611 file->writeLE<Uint32>(pMissile->_miDrawFlag);
1612 file->writeLE<Uint32>(pMissile->_miLightFlag);
1613 file->writeLE<Uint32>(pMissile->_miPreFlag);
1614 file->writeLE<Uint32>(pMissile->_miUniqTrans);
1615 file->writeLE<Sint32>(pMissile->_mirange);
1616 file->writeLE<Sint32>(pMissile->_misource);
1617 file->writeLE<Sint32>(pMissile->_micaster);
1618 file->writeLE<Sint32>(pMissile->_midam);
1619 file->writeLE<Uint32>(pMissile->_miHitFlag);
1620 file->writeLE<Sint32>(pMissile->_midist);
1621 file->writeLE<Sint32>(pMissile->_mlid);
1622 file->writeLE<Sint32>(pMissile->_mirnd);
1623 file->writeLE<Sint32>(pMissile->_miVar1);
1624 file->writeLE<Sint32>(pMissile->_miVar2);
1625 file->writeLE<Sint32>(pMissile->_miVar3);
1626 file->writeLE<Sint32>(pMissile->_miVar4);
1627 file->writeLE<Sint32>(pMissile->_miVar5);
1628 file->writeLE<Sint32>(pMissile->_miVar6);
1629 file->writeLE<Sint32>(pMissile->_miVar7);
1630 file->writeLE<Sint32>(pMissile->_miVar8);
1631 }
1632
SaveObject(SaveHelper * file,int i)1633 static void SaveObject(SaveHelper *file, int i)
1634 {
1635 ObjectStruct *pObject = &object[i];
1636
1637 file->writeLE<Sint32>(pObject->_otype);
1638 file->writeLE<Sint32>(pObject->_ox);
1639 file->writeLE<Sint32>(pObject->_oy);
1640 file->writeLE<Uint32>(pObject->_oLight);
1641 file->writeLE<Uint32>(pObject->_oAnimFlag);
1642 file->skip(4); // Skip pointer _oAnimData
1643 file->writeLE<Sint32>(pObject->_oAnimDelay);
1644 file->writeLE<Sint32>(pObject->_oAnimCnt);
1645 file->writeLE<Sint32>(pObject->_oAnimLen);
1646 file->writeLE<Sint32>(pObject->_oAnimFrame);
1647 file->writeLE<Sint32>(pObject->_oAnimWidth);
1648 file->writeLE<Sint32>(pObject->_oAnimWidth2);
1649 file->writeLE<Uint32>(pObject->_oDelFlag);
1650 file->writeLE<Sint8>(pObject->_oBreak);
1651 file->skip(3); // Alignment
1652 file->writeLE<Uint32>(pObject->_oSolidFlag);
1653 file->writeLE<Uint32>(pObject->_oMissFlag);
1654
1655 file->writeLE<Sint8>(pObject->_oSelFlag);
1656 file->skip(3); // Alignment
1657 file->writeLE<Uint32>(pObject->_oPreFlag);
1658 file->writeLE<Uint32>(pObject->_oTrapFlag);
1659 file->writeLE<Uint32>(pObject->_oDoorFlag);
1660 file->writeLE<Sint32>(pObject->_olid);
1661 file->writeLE<Sint32>(pObject->_oRndSeed);
1662 file->writeLE<Sint32>(pObject->_oVar1);
1663 file->writeLE<Sint32>(pObject->_oVar2);
1664 file->writeLE<Sint32>(pObject->_oVar3);
1665 file->writeLE<Sint32>(pObject->_oVar4);
1666 file->writeLE<Sint32>(pObject->_oVar5);
1667 file->writeLE<Sint32>(pObject->_oVar6);
1668 file->writeLE<Sint32>(pObject->_oVar7);
1669 file->writeLE<Sint32>(pObject->_oVar8);
1670 }
1671
SavePremium(SaveHelper * file,int i)1672 static void SavePremium(SaveHelper *file, int i)
1673 {
1674 SaveItem(file, &premiumitem[i]);
1675 }
1676
SaveQuest(SaveHelper * file,int i)1677 static void SaveQuest(SaveHelper *file, int i)
1678 {
1679 QuestStruct *pQuest = &quests[i];
1680
1681 file->writeLE<Uint8>(pQuest->_qlevel);
1682 file->writeLE<Uint8>(pQuest->_qtype);
1683 file->writeLE<Uint8>(pQuest->_qactive);
1684 file->writeLE<Uint8>(pQuest->_qlvltype);
1685 file->writeLE<Sint32>(pQuest->_qtx);
1686 file->writeLE<Sint32>(pQuest->_qty);
1687 file->writeLE<Uint8>(pQuest->_qslvl);
1688 file->writeLE<Uint8>(pQuest->_qidx);
1689 if (gbIsHellfire) {
1690 file->skip(2); // Alignment
1691 file->writeLE<Sint32>(pQuest->_qmsg);
1692 } else {
1693 file->writeLE<Uint8>(pQuest->_qmsg);
1694 }
1695 file->writeLE<Uint8>(pQuest->_qvar1);
1696 file->writeLE<Uint8>(pQuest->_qvar2);
1697 file->skip(2); // Alignment
1698 if (!gbIsHellfire)
1699 file->skip(1); // Alignment
1700 file->writeLE<Uint32>(pQuest->_qlog);
1701
1702 file->writeBE<Sint32>(ReturnLvlX);
1703 file->writeBE<Sint32>(ReturnLvlY);
1704 file->writeBE<Sint32>(ReturnLvl);
1705 file->writeBE<Sint32>(ReturnLvlT);
1706 file->writeBE<Sint32>(DoomQuestState);
1707 }
1708
SaveLighting(SaveHelper * file,LightListStruct * pLight)1709 static void SaveLighting(SaveHelper *file, LightListStruct *pLight)
1710 {
1711 file->writeLE<Sint32>(pLight->_lx);
1712 file->writeLE<Sint32>(pLight->_ly);
1713 file->writeLE<Sint32>(pLight->_lradius);
1714 file->writeLE<Sint32>(pLight->_lid);
1715 file->writeLE<Uint32>(pLight->_ldel);
1716 file->writeLE<Uint32>(pLight->_lunflag);
1717 file->skip(4); // Unused
1718 file->writeLE<Sint32>(pLight->_lunx);
1719 file->writeLE<Sint32>(pLight->_luny);
1720 file->writeLE<Sint32>(pLight->_lunr);
1721 file->writeLE<Sint32>(pLight->_xoff);
1722 file->writeLE<Sint32>(pLight->_yoff);
1723 file->writeLE<Uint32>(pLight->_lflags);
1724 }
1725
SavePortal(SaveHelper * file,int i)1726 static void SavePortal(SaveHelper *file, int i)
1727 {
1728 PortalStruct *pPortal = &portal[i];
1729
1730 file->writeLE<Uint32>(pPortal->open);
1731 file->writeLE<Sint32>(pPortal->x);
1732 file->writeLE<Sint32>(pPortal->y);
1733 file->writeLE<Sint32>(pPortal->level);
1734 file->writeLE<Sint32>(pPortal->ltype);
1735 file->writeLE<Uint32>(pPortal->setlvl);
1736 }
1737
1738 const int DiabloItemSaveSize = 368;
1739 const int HellfireItemSaveSize = 372;
1740
SaveHeroItems(PlayerStruct * pPlayer)1741 void SaveHeroItems(PlayerStruct *pPlayer)
1742 {
1743 size_t items = NUM_INVLOC + NUM_INV_GRID_ELEM + MAXBELTITEMS;
1744 SaveHelper file("heroitems", items * (gbIsHellfire ? HellfireItemSaveSize : DiabloItemSaveSize) + sizeof(Uint8));
1745
1746 file.writeLE<Uint8>(gbIsHellfire);
1747
1748 SaveItems(&file, pPlayer->InvBody, NUM_INVLOC);
1749 SaveItems(&file, pPlayer->InvList, NUM_INV_GRID_ELEM);
1750 SaveItems(&file, pPlayer->SpdList, MAXBELTITEMS);
1751 }
1752
SaveGame()1753 void SaveGame()
1754 {
1755 SaveHelper file("game", FILEBUFF);
1756
1757 if (gbIsSpawn && !gbIsHellfire)
1758 file.writeLE<Uint32>(LOAD_LE32("SHAR"));
1759 else if (gbIsSpawn && gbIsHellfire)
1760 file.writeLE<Uint32>(LOAD_LE32("SHLF"));
1761 else if (!gbIsSpawn && gbIsHellfire)
1762 file.writeLE<Uint32>(LOAD_LE32("HELF"));
1763 else if (!gbIsSpawn && !gbIsHellfire)
1764 file.writeLE<Uint32>(LOAD_LE32("RETL"));
1765 else
1766 app_fatal("Invalid game state");
1767
1768 if (gbIsHellfire) {
1769 giNumberOfLevels = 25;
1770 giNumberQuests = 24;
1771 giNumberOfSmithPremiumItems = 15;
1772 } else {
1773 giNumberOfLevels = 17;
1774 giNumberQuests = 16;
1775 giNumberOfSmithPremiumItems = 6;
1776 }
1777
1778 file.writeLE<Uint8>(setlevel);
1779 file.writeBE<Uint32>(setlvlnum);
1780 file.writeBE<Uint32>(currlevel);
1781 file.writeBE<Uint32>(leveltype);
1782 file.writeBE<Sint32>(ViewX);
1783 file.writeBE<Sint32>(ViewY);
1784 file.writeLE<Uint8>(invflag);
1785 file.writeLE<Uint8>(chrflag);
1786 file.writeBE<Sint32>(nummonsters);
1787 file.writeBE<Sint32>(numitems);
1788 file.writeBE<Sint32>(nummissiles);
1789 file.writeBE<Sint32>(nobjects);
1790
1791 for (int i = 0; i < giNumberOfLevels; i++) {
1792 file.writeBE<Uint32>(glSeedTbl[i]);
1793 file.writeBE<Sint32>(gnLevelTypeTbl[i]);
1794 }
1795
1796 plr[myplr].pDifficulty = gnDifficulty;
1797 SavePlayer(&file, myplr);
1798
1799 for (int i = 0; i < giNumberQuests; i++)
1800 SaveQuest(&file, i);
1801 for (int i = 0; i < MAXPORTAL; i++)
1802 SavePortal(&file, i);
1803 for (int i = 0; i < MAXMONSTERS; i++)
1804 file.writeBE<Sint32>(monstkills[i]);
1805
1806 if (leveltype != DTYPE_TOWN) {
1807 for (int i = 0; i < MAXMONSTERS; i++)
1808 file.writeBE<Sint32>(monstactive[i]);
1809 for (int i = 0; i < nummonsters; i++)
1810 SaveMonster(&file, monstactive[i]);
1811 for (int i = 0; i < MAXMISSILES; i++)
1812 file.writeLE<Sint8>(missileactive[i]);
1813 for (int i = 0; i < MAXMISSILES; i++)
1814 file.writeLE<Sint8>(missileavail[i]);
1815 for (int i = 0; i < nummissiles; i++)
1816 SaveMissile(&file, missileactive[i]);
1817 for (int i = 0; i < MAXOBJECTS; i++)
1818 file.writeLE<Sint8>(objectactive[i]);
1819 for (int i = 0; i < MAXOBJECTS; i++)
1820 file.writeLE<Sint8>(objectavail[i]);
1821 for (int i = 0; i < nobjects; i++)
1822 SaveObject(&file, objectactive[i]);
1823
1824 file.writeBE<Sint32>(numlights);
1825
1826 for (int i = 0; i < MAXLIGHTS; i++)
1827 file.writeLE<Uint8>(lightactive[i]);
1828 for (int i = 0; i < numlights; i++)
1829 SaveLighting(&file, &LightList[lightactive[i]]);
1830
1831 file.writeBE<Sint32>(visionid);
1832 file.writeBE<Sint32>(numvision);
1833
1834 for (int i = 0; i < numvision; i++)
1835 SaveLighting(&file, &VisionList[i]);
1836 }
1837
1838 for (int i = 0; i < MAXITEMS; i++)
1839 file.writeLE<Sint8>(itemactive[i]);
1840 for (int i = 0; i < MAXITEMS; i++)
1841 file.writeLE<Sint8>(itemavail[i]);
1842 for (int i = 0; i < numitems; i++)
1843 SaveItem(&file, &item[itemactive[i]]);
1844 for (int i = 0; i < 128; i++)
1845 file.writeLE<Sint8>(UniqueItemFlag[i]);
1846
1847 for (int j = 0; j < MAXDUNY; j++) {
1848 for (int i = 0; i < MAXDUNX; i++)
1849 file.writeLE<Sint8>(dLight[i][j]);
1850 }
1851 for (int j = 0; j < MAXDUNY; j++) {
1852 for (int i = 0; i < MAXDUNX; i++)
1853 file.writeLE<Sint8>(dFlags[i][j] & ~(BFLAG_MISSILE | BFLAG_VISIBLE | BFLAG_DEAD_PLAYER));
1854 }
1855 for (int j = 0; j < MAXDUNY; j++) {
1856 for (int i = 0; i < MAXDUNX; i++)
1857 file.writeLE<Sint8>(dPlayer[i][j]);
1858 }
1859 for (int j = 0; j < MAXDUNY; j++) {
1860 for (int i = 0; i < MAXDUNX; i++)
1861 file.writeLE<Sint8>(dItem[i][j]);
1862 }
1863
1864 if (leveltype != DTYPE_TOWN) {
1865 for (int j = 0; j < MAXDUNY; j++) {
1866 for (int i = 0; i < MAXDUNX; i++)
1867 file.writeBE<Sint32>(dMonster[i][j]);
1868 }
1869 for (int j = 0; j < MAXDUNY; j++) {
1870 for (int i = 0; i < MAXDUNX; i++)
1871 file.writeLE<Sint8>(dDead[i][j]);
1872 }
1873 for (int j = 0; j < MAXDUNY; j++) {
1874 for (int i = 0; i < MAXDUNX; i++)
1875 file.writeLE<Sint8>(dObject[i][j]);
1876 }
1877 for (int j = 0; j < MAXDUNY; j++) {
1878 for (int i = 0; i < MAXDUNX; i++)
1879 file.writeLE<Sint8>(dLight[i][j]);
1880 }
1881 for (int j = 0; j < MAXDUNY; j++) {
1882 for (int i = 0; i < MAXDUNX; i++)
1883 file.writeLE<Sint8>(dPreLight[i][j]);
1884 }
1885 for (int j = 0; j < DMAXY; j++) {
1886 for (int i = 0; i < DMAXX; i++)
1887 file.writeLE<Uint8>(automapview[i][j]);
1888 }
1889 for (int j = 0; j < MAXDUNY; j++) {
1890 for (int i = 0; i < MAXDUNX; i++)
1891 file.writeLE<Sint8>(dMissile[i][j]);
1892 }
1893 }
1894
1895 file.writeBE<Sint32>(numpremium);
1896 file.writeBE<Sint32>(premiumlevel);
1897
1898 for (int i = 0; i < giNumberOfSmithPremiumItems; i++)
1899 SavePremium(&file, i);
1900
1901 file.writeLE<Uint8>(automapflag);
1902 file.writeBE<Sint32>(AutoMapScale);
1903
1904 file.flush();
1905
1906 gbValidSaveFile = TRUE;
1907 pfile_rename_temp_to_perm();
1908 pfile_write_hero();
1909 }
1910
SaveLevel()1911 void SaveLevel()
1912 {
1913 DoUnVision(plr[myplr]._px, plr[myplr]._py, plr[myplr]._pLightRad); // fix for vision staying on the level
1914
1915 if (currlevel == 0)
1916 glSeedTbl[0] = AdvanceRndSeed();
1917
1918 char szName[MAX_PATH];
1919 GetTempLevelNames(szName);
1920 SaveHelper file(szName, FILEBUFF);
1921
1922 if (leveltype != DTYPE_TOWN) {
1923 for (int j = 0; j < MAXDUNY; j++) {
1924 for (int i = 0; i < MAXDUNX; i++)
1925 file.writeLE<Sint8>(dDead[i][j]);
1926 }
1927 }
1928
1929 file.writeBE<Sint32>(nummonsters);
1930 file.writeBE<Sint32>(numitems);
1931 file.writeBE<Sint32>(nobjects);
1932
1933 if (leveltype != DTYPE_TOWN) {
1934 for (int i = 0; i < MAXMONSTERS; i++)
1935 file.writeBE<Sint32>(monstactive[i]);
1936 for (int i = 0; i < nummonsters; i++)
1937 SaveMonster(&file, monstactive[i]);
1938 for (int i = 0; i < MAXOBJECTS; i++)
1939 file.writeLE<Sint8>(objectactive[i]);
1940 for (int i = 0; i < MAXOBJECTS; i++)
1941 file.writeLE<Sint8>(objectavail[i]);
1942 for (int i = 0; i < nobjects; i++)
1943 SaveObject(&file, objectactive[i]);
1944 }
1945
1946 for (int i = 0; i < MAXITEMS; i++)
1947 file.writeLE<Sint8>(itemactive[i]);
1948 for (int i = 0; i < MAXITEMS; i++)
1949 file.writeLE<Sint8>(itemavail[i]);
1950
1951 for (int i = 0; i < numitems; i++)
1952 SaveItem(&file, &item[itemactive[i]]);
1953
1954 for (int j = 0; j < MAXDUNY; j++) {
1955 for (int i = 0; i < MAXDUNX; i++)
1956 file.writeLE<Sint8>(dFlags[i][j] & ~(BFLAG_MISSILE | BFLAG_VISIBLE | BFLAG_DEAD_PLAYER));
1957 }
1958 for (int j = 0; j < MAXDUNY; j++) {
1959 for (int i = 0; i < MAXDUNX; i++)
1960 file.writeLE<Sint8>(dItem[i][j]);
1961 }
1962
1963 if (leveltype != DTYPE_TOWN) {
1964 for (int j = 0; j < MAXDUNY; j++) {
1965 for (int i = 0; i < MAXDUNX; i++)
1966 file.writeBE<Sint32>(dMonster[i][j]);
1967 }
1968 for (int j = 0; j < MAXDUNY; j++) {
1969 for (int i = 0; i < MAXDUNX; i++)
1970 file.writeLE<Sint8>(dObject[i][j]);
1971 }
1972 for (int j = 0; j < MAXDUNY; j++) {
1973 for (int i = 0; i < MAXDUNX; i++)
1974 file.writeLE<Sint8>(dLight[i][j]);
1975 }
1976 for (int j = 0; j < MAXDUNY; j++) {
1977 for (int i = 0; i < MAXDUNX; i++)
1978 file.writeLE<Sint8>(dPreLight[i][j]);
1979 }
1980 for (int j = 0; j < DMAXY; j++) {
1981 for (int i = 0; i < DMAXX; i++)
1982 file.writeLE<Uint8>(automapview[i][j]);
1983 }
1984 for (int j = 0; j < MAXDUNY; j++) {
1985 for (int i = 0; i < MAXDUNX; i++)
1986 file.writeLE<Sint8>(dMissile[i][j]);
1987 }
1988 }
1989
1990 if (!setlevel)
1991 plr[myplr]._pLvlVisited[currlevel] = TRUE;
1992 else
1993 plr[myplr]._pSLvlVisited[setlvlnum] = TRUE;
1994 }
1995
LoadLevel()1996 void LoadLevel()
1997 {
1998 char szName[MAX_PATH];
1999 GetPermLevelNames(szName);
2000 LoadHelper file(szName);
2001 if (!file.isValid())
2002 app_fatal("Unable to open save file archive");
2003
2004 if (leveltype != DTYPE_TOWN) {
2005 for (int j = 0; j < MAXDUNY; j++) {
2006 for (int i = 0; i < MAXDUNX; i++)
2007 dDead[i][j] = file.nextLE<Sint8>();
2008 }
2009 SetDead();
2010 }
2011
2012 nummonsters = file.nextBE<Sint32>();
2013 numitems = file.nextBE<Sint32>();
2014 nobjects = file.nextBE<Sint32>();
2015
2016 if (leveltype != DTYPE_TOWN) {
2017 for (int i = 0; i < MAXMONSTERS; i++)
2018 monstactive[i] = file.nextBE<Sint32>();
2019 for (int i = 0; i < nummonsters; i++)
2020 LoadMonster(&file, monstactive[i]);
2021 for (int i = 0; i < MAXOBJECTS; i++)
2022 objectactive[i] = file.nextLE<Sint8>();
2023 for (int i = 0; i < MAXOBJECTS; i++)
2024 objectavail[i] = file.nextLE<Sint8>();
2025 for (int i = 0; i < nobjects; i++)
2026 LoadObject(&file, objectactive[i]);
2027 if (!gbSkipSync) {
2028 for (int i = 0; i < nobjects; i++)
2029 SyncObjectAnim(objectactive[i]);
2030 }
2031 }
2032
2033 for (int i = 0; i < MAXITEMS; i++)
2034 itemactive[i] = file.nextLE<Sint8>();
2035 for (int i = 0; i < MAXITEMS; i++)
2036 itemavail[i] = file.nextLE<Sint8>();
2037 for (int i = 0; i < numitems; i++)
2038 LoadItem(&file, itemactive[i]);
2039
2040 for (int j = 0; j < MAXDUNY; j++) {
2041 for (int i = 0; i < MAXDUNX; i++)
2042 dFlags[i][j] = file.nextLE<Sint8>();
2043 }
2044 for (int j = 0; j < MAXDUNY; j++) {
2045 for (int i = 0; i < MAXDUNX; i++)
2046 dItem[i][j] = file.nextLE<Sint8>();
2047 }
2048
2049 if (leveltype != DTYPE_TOWN) {
2050 for (int j = 0; j < MAXDUNY; j++) {
2051 for (int i = 0; i < MAXDUNX; i++)
2052 dMonster[i][j] = file.nextBE<Sint32>();
2053 }
2054 for (int j = 0; j < MAXDUNY; j++) {
2055 for (int i = 0; i < MAXDUNX; i++)
2056 dObject[i][j] = file.nextLE<Sint8>();
2057 }
2058 for (int j = 0; j < MAXDUNY; j++) {
2059 for (int i = 0; i < MAXDUNX; i++)
2060 dLight[i][j] = file.nextLE<Sint8>();
2061 }
2062 for (int j = 0; j < MAXDUNY; j++) {
2063 for (int i = 0; i < MAXDUNX; i++)
2064 dPreLight[i][j] = file.nextLE<Sint8>();
2065 }
2066 for (int j = 0; j < DMAXY; j++) {
2067 for (int i = 0; i < DMAXX; i++)
2068 automapview[i][j] = file.nextBool8();
2069 }
2070 for (int j = 0; j < MAXDUNY; j++) {
2071 for (int i = 0; i < MAXDUNX; i++)
2072 dMissile[i][j] = 0; /// BUGFIX: supposed to load saved missiles with "file.nextLE<Sint8>()"?
2073 }
2074 }
2075
2076 if (gbIsHellfireSaveGame != gbIsHellfire) {
2077 RemoveEmptyLevelItems();
2078 }
2079
2080 if (!gbSkipSync) {
2081 AutomapZoomReset();
2082 ResyncQuests();
2083 SyncPortals();
2084 dolighting = TRUE;
2085 }
2086
2087 for (int i = 0; i < MAX_PLRS; i++) {
2088 if (plr[i].plractive && currlevel == plr[i].plrlevel)
2089 LightList[plr[i]._plid]._lunflag = TRUE;
2090 }
2091 }
2092
2093 DEVILUTION_END_NAMESPACE
2094