diff --git a/Source/items.cpp b/Source/items.cpp index b77e95263..04b711eef 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -324,8 +324,16 @@ int premiumLvlAddHellfire[] = { bool IsItemAvailable(int i) { + if (gbIsSpawn) { + if (i >= 62 && i <= 71) + return false; // Medium and heavy armors + if (i == 105 || i == 107 || i == 108 || i == 110 || i == 111 || i == 113) + return false; // Unavailable scrolls + } + if (gbIsHellfire) return true; + return ( i != IDI_MAPOFDOOM // Cathedral Map && i != IDI_LGTFORGE // Bovine Plate @@ -481,7 +489,7 @@ void AddInitItems() static void items_42390F() { int id; - + switch (currlevel) { case 22: id = IDI_NOTE2; diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 6548bbcfc..c7f771e80 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -281,6 +281,9 @@ static void LoadItemData(LoadHelper *file, ItemStruct *pItem) file->skip(1); // Alignment pItem->_iStatFlag = file->nextBool32(); pItem->IDidx = file->nextLE(); + if (gbIsSpawn) { + pItem->IDidx = RemapItemIdxFromSpawn(pItem->IDidx); + } if (!gbIsHellfireSaveGame) { pItem->IDidx = RemapItemIdxFromDiablo(pItem->IDidx); } @@ -829,6 +832,60 @@ int RemapItemIdxToDiablo(int i) return i; } +int RemapItemIdxFromSpawn(int i) +{ + if (i >= 62) { + i += 9; // Medium and heavy armors + } + if (i >= 96) { + i += 1; // Scroll of Stone Curse + } + if (i >= 98) { + i += 1; // Scroll of Guardian + } + if (i >= 99) { + i += 1; // Scroll of ... + } + if (i >= 101) { + i += 1; // Scroll of Golem + } + if (i >= 102) { + i += 1; // Scroll of None + } + if (i >= 104) { + i += 1; // Scroll of Apocalypse + } + + return i; +} + +int RemapItemIdxToSpawn(int i) +{ + if (i >= 104) { + i -= 1; // Scroll of Apocalypse + } + if (i >= 102) { + i -= 1; // Scroll of None + } + if (i >= 101) { + i -= 1; // Scroll of Golem + } + if (i >= 99) { + i -= 1; // Scroll of ... + } + if (i >= 98) { + i -= 1; // Scroll of Guardian + } + if (i >= 96) { + i -= 1; // Scroll of Stone Curse + } + if (i >= 71) { + i -= 9; // Medium and heavy armors + } + + return i; +} + bool IsHeaderValid(uint32_t magicNumber) { gbIsHellfireSaveGame = false; @@ -1188,6 +1245,8 @@ static void SaveItem(SaveHelper *file, ItemStruct *pItem) int idx = pItem->IDidx; if (!gbIsHellfire) idx = RemapItemIdxToDiablo(idx); + if (gbIsSpawn) + idx = RemapItemIdxToSpawn(idx); int iType = pItem->_itype; if (idx == -1) { idx = 0; diff --git a/Source/loadsave.h b/Source/loadsave.h index 253abe4db..ce7d75ee0 100644 --- a/Source/loadsave.h +++ b/Source/loadsave.h @@ -15,6 +15,8 @@ extern uint8_t giNumberOfLevels; void RemoveInvalidItem(ItemStruct *pItem); int RemapItemIdxFromDiablo(int i); int RemapItemIdxToDiablo(int i); +int RemapItemIdxFromSpawn(int i); +int RemapItemIdxToSpawn(int i); bool IsHeaderValid(uint32_t magicNumber); void LoadHotkeys(); void LoadHeroItems(PlayerStruct &pPlayer); diff --git a/Source/pack.cpp b/Source/pack.cpp index adf5fe8d6..e04a015f8 100644 --- a/Source/pack.cpp +++ b/Source/pack.cpp @@ -21,6 +21,9 @@ void PackItem(PkItemStruct *id, const ItemStruct *is) if (!gbIsHellfire) { idx = RemapItemIdxToDiablo(idx); } + if (gbIsSpawn) { + idx = RemapItemIdxToSpawn(idx); + } id->idx = SDL_SwapLE16(idx); if (is->IDidx == IDI_EAR) { id->iCreateInfo = is->_iName[8] | (is->_iName[7] << 8); @@ -126,6 +129,9 @@ void UnPackItem(const PkItemStruct *is, ItemStruct *id, bool isHellfire) return; } + if (gbIsSpawn) { + idx = RemapItemIdxFromSpawn(idx); + } if (!isHellfire) { idx = RemapItemIdxFromDiablo(idx); } diff --git a/Source/pfile.cpp b/Source/pfile.cpp index 8f81dff82..f2cd92806 100644 --- a/Source/pfile.cpp +++ b/Source/pfile.cpp @@ -37,7 +37,7 @@ std::string GetSavePath(uint32_t save_num) if (gbIsSpawn) { if (!gbIsMultiplayer) { - path.append("spawn"); + path.append("spawn_"); } else { path.append("share_"); } diff --git a/test/pack_test.cpp b/test/pack_test.cpp index 7bd1daea6..2381d97e0 100644 --- a/test/pack_test.cpp +++ b/test/pack_test.cpp @@ -333,6 +333,8 @@ TEST(pack, UnPackItem_diablo) gbIsHellfire = false; gbIsMultiplayer = false; + gbIsSpawn = false; + plr[myplr]._pMaxManaBase = 125 << 6; plr[myplr]._pMaxHPBase = 125 << 6; @@ -352,6 +354,7 @@ TEST(pack, UnPackItem_diablo_unique_bug) gbIsHellfire = false; gbIsMultiplayer = false; + gbIsSpawn = false; ItemStruct id; UnPackItem(&pkItemBug, &id, false); @@ -378,6 +381,43 @@ TEST(pack, UnPackItem_diablo_unique_bug) ComparePackedItems(&is, &pkItem); } +const PkItemStruct PackedSpawnItems[] = { + // clang-format off + // iSeed, iCreateInfo, idx, bId, bDur, bMDur, bCh, bMCh, wValue, dwBuff + { 2060036013, 257, 131, 0, 11, 25, 50, 50, 0, 0 }, // Staff of Firebolt + { 81574809, 258, 94, 0, 0, 0, 0, 0, 0, 0 }, // Book of Holy Bolt + // clang-format on +}; + +const TestItemStruct SpawnItems[] = { + // clang-format off + //_iIName, _itype, _iClass, _iCurs, _iIvalue, _iMinDam, _iMaxDam, _iAC, _iFlags, _iMiscId, _iSpell, _iCharges, _iMaxCharges, _iDurability, _iMaxDur, _iPLDam, _iPLToHit, _iPLAC, _iPLStr, _iPLMag, _iPLDex, _iPLVit, _iPLFR, _iPLLR, _iPLMR, _iPLMana, _iPLHP, _iPLDamMod, _iPLGetHit, _iPLLight, _iSplLvlAdd, _iUid, _iFMinDam, _iFMaxDam, _iLMinDam, _iLMaxDam, _iPrePower, _iSufPower, _iMinStr, _iMinMag, _iMinDex, IDidx ); + { "Staff of Firebolt", 10, 1, 109, 1, 2, 4, 0, 0, 23, 1, 50, 50, 11, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 15, 0, 151 }, + { "Book of Holy Bolt", 0, 3, 86, 1000, 0, 0, 0, 0, 24, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 20, 0, 114 }, + // clang-format on +}; + +TEST(pack, UnPackItem_spawn) +{ + ItemStruct id; + PkItemStruct is; + + gbIsHellfire = false; + gbIsMultiplayer = false; + gbIsSpawn = true; + + plr[myplr]._pMaxManaBase = 125 << 6; + plr[myplr]._pMaxHPBase = 125 << 6; + + for (size_t i = 0; i < sizeof(PackedSpawnItems) / sizeof(*PackedSpawnItems); i++) { + UnPackItem(&PackedSpawnItems[i], &id, false); + CompareItems(&id, &SpawnItems[i]); + + PackItem(&is, &id); + ComparePackedItems(&is, &PackedSpawnItems[i]); + } +} + const PkItemStruct PackedDiabloMPItems[] = { // clang-format off // iSeed, iCreateInfo, idx, bId, bDur, bMDur, bCh, bMCh, wValue, dwBuff @@ -408,6 +448,8 @@ TEST(pack, UnPackItem_diablo_multiplayer) gbIsHellfire = false; gbIsMultiplayer = true; + gbIsSpawn = false; + plr[myplr]._pMaxManaBase = 125 << 6; plr[myplr]._pMaxHPBase = 125 << 6; @@ -609,6 +651,8 @@ TEST(pack, UnPackItem_hellfire) gbIsHellfire = true; gbIsMultiplayer = false; + gbIsSpawn = false; + plr[myplr]._pMaxManaBase = 125 << 6; plr[myplr]._pMaxHPBase = 125 << 6; @@ -629,6 +673,7 @@ TEST(pack, UnPackItem_diablo_strip_hellfire_items) gbIsHellfire = false; gbIsMultiplayer = false; + gbIsSpawn = false; UnPackItem(&is, &id, true);