Remove uses of Items[] as a temporary for other Item variables (#2924)

This commit is contained in:
Andrew James 2021-11-25 19:34:13 +11:00 committed by GitHub
commit 4a940b1b07
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 265 additions and 284 deletions

View file

@ -1006,13 +1006,9 @@ void CheckNaKrulNotes(Player &player)
}
}
int itemNum = ActiveItems[0];
Item tmp = Items[itemNum];
memset(&Items[itemNum], 0, sizeof(*Items));
GetItemAttrs(Items[itemNum], IDI_FULLNOTE, 16);
SetupItem(Items[itemNum]);
player.HoldItem = Items[itemNum];
Items[itemNum] = tmp;
player.HoldItem = {};
GetItemAttrs(player.HoldItem, IDI_FULLNOTE, 16);
SetupItem(player.HoldItem);
}
void CheckQuestItem(Player &player)
@ -1569,11 +1565,8 @@ bool GoldAutoPlaceInInventorySlot(Player &player, int slotIndex)
void CheckInvSwap(Player &player, inv_body_loc bLoc, int idx, uint16_t wCI, int seed, bool bId, uint32_t dwBuff)
{
auto &item = Items[MAXITEMS];
memset(&item, 0, sizeof(item));
RecreateItem(item, idx, wCI, seed, 0, (dwBuff & CF_HELLFIRE) != 0);
player.HoldItem = item;
player.HoldItem = {};
RecreateItem(player.HoldItem, idx, wCI, seed, 0, (dwBuff & CF_HELLFIRE) != 0);
if (bId) {
player.HoldItem._iIdentified = true;

View file

@ -529,17 +529,17 @@ void CalcPlrItemMin(Player &player)
}
}
void WitchBookLevel(int ii)
void WitchBookLevel(Item &bookItem)
{
if (witchitem[ii]._iMiscId != IMISC_BOOK)
if (bookItem._iMiscId != IMISC_BOOK)
return;
witchitem[ii]._iMinMag = spelldata[witchitem[ii]._iSpell].sMinInt;
int8_t spellLevel = Players[MyPlayerId]._pSplLvl[witchitem[ii]._iSpell];
bookItem._iMinMag = spelldata[bookItem._iSpell].sMinInt;
int8_t spellLevel = Players[MyPlayerId]._pSplLvl[bookItem._iSpell];
while (spellLevel > 0) {
witchitem[ii]._iMinMag += 20 * witchitem[ii]._iMinMag / 100;
bookItem._iMinMag += 20 * bookItem._iMinMag / 100;
spellLevel--;
if (witchitem[ii]._iMinMag + 20 * witchitem[ii]._iMinMag / 100 > 255) {
witchitem[ii]._iMinMag = 255;
if (bookItem._iMinMag + 20 * bookItem._iMinMag / 100 > 255) {
bookItem._iMinMag = 255;
spellLevel = 0;
}
}
@ -563,7 +563,7 @@ void CalcPlrBookVals(Player &player)
{
if (currlevel == 0) {
for (int i = 1; !witchitem[i].isEmpty(); i++) {
WitchBookLevel(i);
WitchBookLevel(witchitem[i]);
witchitem[i]._iStatFlag = StoreStatOk(witchitem[i]);
}
}
@ -2200,11 +2200,10 @@ int RndPremiumItem(int minlvl, int maxlvl)
return RndVendorItem<PremiumItemOk>(minlvl, maxlvl);
}
void SpawnOnePremium(int i, int plvl, int playerId)
void SpawnOnePremium(Item &premiumItem, int plvl, int playerId)
{
int itemValue = 0;
bool keepGoing = false;
Item tempItem = Items[0];
auto &player = Players[playerId];
@ -2221,22 +2220,22 @@ void SpawnOnePremium(int i, int plvl, int playerId)
do {
keepGoing = false;
memset(&Items[0], 0, sizeof(*Items));
Items[0]._iSeed = AdvanceRndSeed();
SetRndSeed(Items[0]._iSeed);
premiumItem = {};
premiumItem._iSeed = AdvanceRndSeed();
SetRndSeed(premiumItem._iSeed);
int itemType = RndPremiumItem(plvl / 4, plvl) - 1;
GetItemAttrs(Items[0], itemType, plvl);
GetItemBonus(Items[0], plvl / 2, plvl, true, !gbIsHellfire);
GetItemAttrs(premiumItem, itemType, plvl);
GetItemBonus(premiumItem, plvl / 2, plvl, true, !gbIsHellfire);
if (!gbIsHellfire) {
if (Items[0]._iIvalue > 140000) {
if (premiumItem._iIvalue > 140000) {
keepGoing = true; // prevent breaking the do/while loop too early by failing hellfire's condition in while
continue;
}
break;
}
switch (Items[0]._itype) {
switch (premiumItem._itype) {
case ItemType::LightArmor:
case ItemType::MediumArmor:
case ItemType::HeavyArmor: {
@ -2258,7 +2257,7 @@ void SpawnOnePremium(int i, int plvl, int playerId)
case ItemType::Ring:
case ItemType::Amulet: {
const auto *const mostValuablePlayerItem = player.GetMostValuableItem(
[](const Item &item) { return item._itype == Items[0]._itype; });
[filterType = premiumItem._itype](const Item &item) { return item._itype == filterType; });
itemValue = mostValuablePlayerItem == nullptr ? 0 : mostValuablePlayerItem->_iIvalue;
break;
@ -2272,17 +2271,15 @@ void SpawnOnePremium(int i, int plvl, int playerId)
count++;
} while (keepGoing
|| ((
Items[0]._iIvalue > 200000
|| Items[0]._iMinStr > strength
|| Items[0]._iMinMag > magic
|| Items[0]._iMinDex > dexterity
|| Items[0]._iIvalue < itemValue)
premiumItem._iIvalue > 200000
|| premiumItem._iMinStr > strength
|| premiumItem._iMinMag > magic
|| premiumItem._iMinDex > dexterity
|| premiumItem._iIvalue < itemValue)
&& count < 150));
premiumitems[i] = Items[0];
premiumitems[i]._iCreateInfo = plvl | CF_SMITHPREMIUM;
premiumitems[i]._iIdentified = true;
premiumitems[i]._iStatFlag = StoreStatOk(premiumitems[i]);
Items[0] = tempItem;
premiumItem._iCreateInfo = plvl | CF_SMITHPREMIUM;
premiumItem._iIdentified = true;
premiumItem._iStatFlag = StoreStatOk(premiumItem);
}
bool WitchItemOk(int i)
@ -2574,14 +2571,12 @@ void InitItemGFX()
void InitItems()
{
memset(&Items[0], 0, sizeof(*Items));
GetItemAttrs(Items[0], IDI_GOLD, 1);
golditem = Items[0];
golditem = {};
GetItemAttrs(golditem, IDI_GOLD, 1);
golditem._iStatFlag = true;
ActiveItemCount = 0;
for (int i = 0; i < MAXITEMS; i++) {
auto &item = Items[i];
for (auto &item : Items) {
item._itype = ItemType::None;
item.position = { 0, 0 };
item._iAnimFlag = false;
@ -3535,7 +3530,7 @@ void CornerstoneSave()
return;
if (!CornerStone.item.isEmpty()) {
ItemPack id;
PackItem(&id, &CornerStone.item);
PackItem(id, CornerStone.item);
const auto *buffer = reinterpret_cast<uint8_t *>(&id);
for (size_t i = 0; i < sizeof(ItemPack); i++) {
snprintf(&sgOptions.Hellfire.szItem[i * 2], 3, "%02hhX", buffer[i]);
@ -3576,7 +3571,7 @@ void CornerstoneLoad(Point position)
dItem[position.x][position.y] = ii + 1;
UnPackItem(&pkSItem, &item, (pkSItem.dwBuff & CF_HELLFIRE) != 0);
UnPackItem(pkSItem, item, (pkSItem.dwBuff & CF_HELLFIRE) != 0);
item.position = position;
RespawnItem(&item, false);
CornerStone.item = item;
@ -4452,9 +4447,6 @@ void SpawnSmith(int lvl)
{
constexpr int PinnedItemCount = 0;
Item holditem;
holditem = Items[0];
int maxValue = 140000;
int maxItems = 20;
if (gbIsHellfire) {
@ -4464,23 +4456,24 @@ void SpawnSmith(int lvl)
int iCnt = GenerateRnd(maxItems - 10) + 10;
for (int i = 0; i < iCnt; i++) {
Item &newItem = smithitem[i];
do {
memset(&Items[0], 0, sizeof(*Items));
Items[0]._iSeed = AdvanceRndSeed();
SetRndSeed(Items[0]._iSeed);
newItem = {};
newItem._iSeed = AdvanceRndSeed();
SetRndSeed(newItem._iSeed);
int itemData = RndSmithItem(lvl) - 1;
GetItemAttrs(Items[0], itemData, lvl);
} while (Items[0]._iIvalue > maxValue);
smithitem[i] = Items[0];
smithitem[i]._iCreateInfo = lvl | CF_SMITH;
smithitem[i]._iIdentified = true;
smithitem[i]._iStatFlag = StoreStatOk(smithitem[i]);
GetItemAttrs(newItem, itemData, lvl);
} while (newItem._iIvalue > maxValue);
newItem._iCreateInfo = lvl | CF_SMITH;
newItem._iIdentified = true;
newItem._iStatFlag = StoreStatOk(newItem);
}
for (int i = iCnt; i < SMITH_ITEMS; i++)
smithitem[i]._itype = ItemType::None;
SortVendor(smithitem + PinnedItemCount);
Items[0] = holditem;
}
void SpawnPremium(int pnum)
@ -4491,7 +4484,7 @@ void SpawnPremium(int pnum)
for (int i = 0; i < maxItems; i++) {
if (premiumitems[i].isEmpty()) {
int plvl = premiumlevel + (gbIsHellfire ? premiumLvlAddHellfire[i] : premiumlvladd[i]);
SpawnOnePremium(i, plvl, pnum);
SpawnOnePremium(premiumitems[i], plvl, pnum);
}
}
numpremium = maxItems;
@ -4501,17 +4494,17 @@ void SpawnPremium(int pnum)
if (gbIsHellfire) {
// Discard first 3 items and shift next 10
std::move(&premiumitems[3], &premiumitems[12] + 1, &premiumitems[0]);
SpawnOnePremium(10, premiumlevel + premiumLvlAddHellfire[10], pnum);
SpawnOnePremium(premiumitems[10], premiumlevel + premiumLvlAddHellfire[10], pnum);
premiumitems[11] = premiumitems[13];
SpawnOnePremium(12, premiumlevel + premiumLvlAddHellfire[12], pnum);
SpawnOnePremium(premiumitems[12], premiumlevel + premiumLvlAddHellfire[12], pnum);
premiumitems[13] = premiumitems[14];
SpawnOnePremium(14, premiumlevel + premiumLvlAddHellfire[14], pnum);
SpawnOnePremium(premiumitems[14], premiumlevel + premiumLvlAddHellfire[14], pnum);
} else {
// Discard first 2 items and shift next 3
std::move(&premiumitems[2], &premiumitems[4] + 1, &premiumitems[0]);
SpawnOnePremium(3, premiumlevel + premiumlvladd[3], pnum);
SpawnOnePremium(premiumitems[3], premiumlevel + premiumlvladd[3], pnum);
premiumitems[4] = premiumitems[5];
SpawnOnePremium(5, premiumlevel + premiumlvladd[5], pnum);
SpawnOnePremium(premiumitems[5], premiumlevel + premiumlvladd[5], pnum);
}
}
}
@ -4522,19 +4515,16 @@ void SpawnWitch(int lvl)
int j = PinnedItemCount;
memset(&Items[0], 0, sizeof(*Items));
GetItemAttrs(Items[0], IDI_MANA, 1);
witchitem[0] = Items[0];
witchitem[0] = {};
GetItemAttrs(witchitem[0], IDI_MANA, 1);
witchitem[0]._iCreateInfo = lvl;
witchitem[0]._iStatFlag = true;
memset(&Items[0], 0, sizeof(*Items));
GetItemAttrs(Items[0], IDI_FULLMANA, 1);
witchitem[1] = Items[0];
witchitem[1] = {};
GetItemAttrs(witchitem[1], IDI_FULLMANA, 1);
witchitem[1]._iCreateInfo = lvl;
witchitem[1]._iStatFlag = true;
memset(&Items[0], 0, sizeof(*Items));
GetItemAttrs(Items[0], IDI_PORTAL, 1);
witchitem[2] = Items[0];
witchitem[2] = {};
GetItemAttrs(witchitem[2], IDI_PORTAL, 1);
witchitem[2]._iCreateInfo = lvl;
witchitem[2]._iStatFlag = true;
@ -4551,17 +4541,18 @@ void SpawnWitch(int lvl)
if (lvl < AllItemsList[i].iMinMLvl)
continue;
memset(&Items[0], 0, sizeof(*Items));
Items[0]._iSeed = AdvanceRndSeed();
SetRndSeed(Items[0]._iSeed);
auto &bookItem = witchitem[j];
bookItem = {};
bookItem._iSeed = AdvanceRndSeed();
SetRndSeed(bookItem._iSeed);
AdvanceRndSeed();
GetItemAttrs(Items[0], i, lvl);
witchitem[j] = Items[0];
witchitem[j]._iCreateInfo = lvl | CF_WITCH;
witchitem[j]._iIdentified = true;
WitchBookLevel(j);
witchitem[j]._iStatFlag = StoreStatOk(witchitem[j]);
GetItemAttrs(bookItem, i, lvl);
bookItem._iCreateInfo = lvl | CF_WITCH;
bookItem._iIdentified = true;
WitchBookLevel(bookItem);
bookItem._iStatFlag = StoreStatOk(bookItem);
j++;
bCnt++;
}
@ -4569,25 +4560,25 @@ void SpawnWitch(int lvl)
int iCnt = GenerateRnd(WITCH_ITEMS - reservedItems) + 10;
for (int i = j; i < iCnt; i++) {
auto &newItem = witchitem[i];
do {
memset(&Items[0], 0, sizeof(*Items));
Items[0]._iSeed = AdvanceRndSeed();
SetRndSeed(Items[0]._iSeed);
newItem = {};
newItem._iSeed = AdvanceRndSeed();
SetRndSeed(newItem._iSeed);
int itemData = RndWitchItem(lvl) - 1;
GetItemAttrs(Items[0], itemData, lvl);
GetItemAttrs(newItem, itemData, lvl);
int maxlvl = -1;
if (GenerateRnd(100) <= 5)
maxlvl = 2 * lvl;
if (maxlvl == -1 && Items[0]._iMiscId == IMISC_STAFF)
if (maxlvl == -1 && newItem._iMiscId == IMISC_STAFF)
maxlvl = 2 * lvl;
if (maxlvl != -1)
GetItemBonus(Items[0], maxlvl / 2, maxlvl, true, true);
} while (Items[0]._iIvalue > maxValue);
witchitem[i] = Items[0];
witchitem[i]._iCreateInfo = lvl | CF_WITCH;
witchitem[i]._iIdentified = true;
WitchBookLevel(i);
witchitem[i]._iStatFlag = StoreStatOk(witchitem[i]);
GetItemBonus(newItem, maxlvl / 2, maxlvl, true, true);
} while (newItem._iIvalue > maxValue);
newItem._iCreateInfo = lvl | CF_WITCH;
newItem._iIdentified = true;
WitchBookLevel(newItem);
newItem._iStatFlag = StoreStatOk(newItem);
}
for (int i = iCnt; i < WITCH_ITEMS; i++)
@ -4616,15 +4607,15 @@ void SpawnBoy(int lvl)
return;
do {
keepgoing = false;
memset(&Items[0], 0, sizeof(*Items));
Items[0]._iSeed = AdvanceRndSeed();
SetRndSeed(Items[0]._iSeed);
boyitem = {};
boyitem._iSeed = AdvanceRndSeed();
SetRndSeed(boyitem._iSeed);
int itype = RndBoyItem(lvl) - 1;
GetItemAttrs(Items[0], itype, lvl);
GetItemBonus(Items[0], lvl, 2 * lvl, true, true);
GetItemAttrs(boyitem, itype, lvl);
GetItemBonus(boyitem, lvl, 2 * lvl, true, true);
if (!gbIsHellfire) {
if (Items[0]._iIvalue > 90000) {
if (boyitem._iIvalue > 90000) {
keepgoing = true; // prevent breaking the do/while loop too early by failing hellfire's condition in while
continue;
}
@ -4633,7 +4624,7 @@ void SpawnBoy(int lvl)
ivalue = 0;
ItemType itemType = Items[0]._itype;
ItemType itemType = boyitem._itype;
switch (itemType) {
case ItemType::LightArmor:
@ -4699,13 +4690,12 @@ void SpawnBoy(int lvl)
}
} while (keepgoing
|| ((
Items[0]._iIvalue > 200000
|| Items[0]._iMinStr > strength
|| Items[0]._iMinMag > magic
|| Items[0]._iMinDex > dexterity
|| Items[0]._iIvalue < ivalue)
boyitem._iIvalue > 200000
|| boyitem._iMinStr > strength
|| boyitem._iMinMag > magic
|| boyitem._iMinDex > dexterity
|| boyitem._iIvalue < ivalue)
&& count < 250));
boyitem = Items[0];
boyitem._iCreateInfo = lvl | CF_BOY;
boyitem._iIdentified = true;
boyitem._iStatFlag = StoreStatOk(boyitem);
@ -4718,22 +4708,19 @@ void SpawnHealer(int lvl)
int srnd;
memset(&Items[0], 0, sizeof(*Items));
GetItemAttrs(Items[0], IDI_HEAL, 1);
healitem[0] = Items[0];
healitem[0] = {};
GetItemAttrs(healitem[0], IDI_HEAL, 1);
healitem[0]._iCreateInfo = lvl;
healitem[0]._iStatFlag = true;
memset(&Items[0], 0, sizeof(*Items));
GetItemAttrs(Items[0], IDI_FULLHEAL, 1);
healitem[1] = Items[0];
healitem[1] = {};
GetItemAttrs(healitem[1], IDI_FULLHEAL, 1);
healitem[1]._iCreateInfo = lvl;
healitem[1]._iStatFlag = true;
if (gbIsMultiplayer) {
memset(&Items[0], 0, sizeof(*Items));
GetItemAttrs(Items[0], IDI_RESURRECT, 1);
healitem[2] = Items[0];
healitem[2] = {};
GetItemAttrs(healitem[2], IDI_RESURRECT, 1);
healitem[2]._iCreateInfo = lvl;
healitem[2]._iStatFlag = true;
@ -4743,15 +4730,15 @@ void SpawnHealer(int lvl)
}
int nsi = GenerateRnd(gbIsHellfire ? 10 : 8) + 10;
for (int i = srnd; i < nsi; i++) {
memset(&Items[0], 0, sizeof(*Items));
Items[0]._iSeed = AdvanceRndSeed();
SetRndSeed(Items[0]._iSeed);
auto &newItem = healitem[i];
newItem = {};
newItem._iSeed = AdvanceRndSeed();
SetRndSeed(newItem._iSeed);
int itype = RndHealerItem(lvl) - 1;
GetItemAttrs(Items[0], itype, lvl);
healitem[i] = Items[0];
healitem[i]._iCreateInfo = lvl | CF_HEALER;
healitem[i]._iIdentified = true;
healitem[i]._iStatFlag = StoreStatOk(healitem[i]);
GetItemAttrs(newItem, itype, lvl);
newItem._iCreateInfo = lvl | CF_HEALER;
newItem._iIdentified = true;
newItem._iStatFlag = StoreStatOk(newItem);
}
for (int i = nsi; i < 20; i++) {
healitem[i]._itype = ItemType::None;
@ -4761,9 +4748,8 @@ void SpawnHealer(int lvl)
void SpawnStoreGold()
{
memset(&Items[0], 0, sizeof(*Items));
GetItemAttrs(Items[0], IDI_GOLD, 1);
golditem = Items[0];
golditem = {};
GetItemAttrs(golditem, IDI_GOLD, 1);
golditem._iStatFlag = true;
}

View file

@ -35,41 +35,41 @@ void VerifyGoldSeeds(Player &player)
} // namespace
void PackItem(ItemPack *id, const Item *is)
void PackItem(ItemPack &packedItem, const Item &item)
{
memset(id, 0, sizeof(*id));
if (is->isEmpty()) {
id->idx = 0xFFFF;
packedItem = {};
if (item.isEmpty()) {
packedItem.idx = 0xFFFF;
} else {
auto idx = is->IDidx;
auto idx = item.IDidx;
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);
id->iSeed = LoadBE32(&is->_iName[9]);
id->bId = is->_iName[13];
id->bDur = is->_iName[14];
id->bMDur = is->_iName[15];
id->bCh = is->_iName[16];
id->bMCh = is->_iName[17];
id->wValue = SDL_SwapLE16(is->_ivalue | (is->_iName[18] << 8) | ((is->_iCurs - ICURS_EAR_SORCERER) << 6));
id->dwBuff = LoadBE32(&is->_iName[19]);
packedItem.idx = SDL_SwapLE16(idx);
if (item.IDidx == IDI_EAR) {
packedItem.iCreateInfo = item._iName[8] | (item._iName[7] << 8);
packedItem.iSeed = LoadBE32(&item._iName[9]);
packedItem.bId = item._iName[13];
packedItem.bDur = item._iName[14];
packedItem.bMDur = item._iName[15];
packedItem.bCh = item._iName[16];
packedItem.bMCh = item._iName[17];
packedItem.wValue = SDL_SwapLE16(item._ivalue | (item._iName[18] << 8) | ((item._iCurs - ICURS_EAR_SORCERER) << 6));
packedItem.dwBuff = LoadBE32(&item._iName[19]);
} else {
id->iSeed = SDL_SwapLE32(is->_iSeed);
id->iCreateInfo = SDL_SwapLE16(is->_iCreateInfo);
id->bId = (is->_iMagical << 1) | (is->_iIdentified ? 1 : 0);
id->bDur = is->_iDurability;
id->bMDur = is->_iMaxDur;
id->bCh = is->_iCharges;
id->bMCh = is->_iMaxCharges;
if (is->IDidx == IDI_GOLD)
id->wValue = SDL_SwapLE16(is->_ivalue);
id->dwBuff = is->dwBuff;
packedItem.iSeed = SDL_SwapLE32(item._iSeed);
packedItem.iCreateInfo = SDL_SwapLE16(item._iCreateInfo);
packedItem.bId = (item._iMagical << 1) | (item._iIdentified ? 1 : 0);
packedItem.bDur = item._iDurability;
packedItem.bMDur = item._iMaxDur;
packedItem.bCh = item._iCharges;
packedItem.bMCh = item._iMaxCharges;
if (item.IDidx == IDI_GOLD)
packedItem.wValue = SDL_SwapLE16(item._ivalue);
packedItem.dwBuff = item.dwBuff;
}
}
}
@ -109,19 +109,19 @@ void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield)
pPack->pSplLvl2[i - 37] = player._pSplLvl[i];
for (int i = 0; i < NUM_INVLOC; i++) {
PackItem(&pPack->InvBody[i], &player.InvBody[i]);
PackItem(pPack->InvBody[i], player.InvBody[i]);
}
pPack->_pNumInv = player._pNumInv;
for (int i = 0; i < pPack->_pNumInv; i++) {
PackItem(&pPack->InvList[i], &player.InvList[i]);
PackItem(pPack->InvList[i], player.InvList[i]);
}
for (int i = 0; i < NUM_INV_GRID_ELEM; i++)
pPack->InvGrid[i] = player.InvGrid[i];
for (int i = 0; i < MAXBELTITEMS; i++) {
PackItem(&pPack->SpdList[i], &player.SpdList[i]);
PackItem(pPack->SpdList[i], player.SpdList[i]);
}
pPack->wReflections = SDL_SwapLE16(player.wReflections);
@ -136,10 +136,9 @@ void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield)
pPack->pManaShield = 0;
}
void UnPackItem(const ItemPack *is, Item *id, bool isHellfire)
void UnPackItem(const ItemPack &packedItem, Item &item, bool isHellfire)
{
auto &item = Items[MAXITEMS];
auto idx = static_cast<_item_indexes>(SDL_SwapLE16(is->idx));
auto idx = static_cast<_item_indexes>(SDL_SwapLE16(packedItem.idx));
if (gbIsSpawn) {
idx = RemapItemIdxFromSpawn(idx);
@ -149,32 +148,31 @@ void UnPackItem(const ItemPack *is, Item *id, bool isHellfire)
}
if (!IsItemAvailable(idx)) {
id->_itype = ItemType::None;
item._itype = ItemType::None;
return;
}
if (idx == IDI_EAR) {
RecreateEar(
item,
SDL_SwapLE16(is->iCreateInfo),
SDL_SwapLE32(is->iSeed),
is->bId,
is->bDur,
is->bMDur,
is->bCh,
is->bMCh,
SDL_SwapLE16(is->wValue),
SDL_SwapLE32(is->dwBuff));
SDL_SwapLE16(packedItem.iCreateInfo),
SDL_SwapLE32(packedItem.iSeed),
packedItem.bId,
packedItem.bDur,
packedItem.bMDur,
packedItem.bCh,
packedItem.bMCh,
SDL_SwapLE16(packedItem.wValue),
SDL_SwapLE32(packedItem.dwBuff));
} else {
memset(&item, 0, sizeof(item));
RecreateItem(item, idx, SDL_SwapLE16(is->iCreateInfo), SDL_SwapLE32(is->iSeed), SDL_SwapLE16(is->wValue), isHellfire);
item._iMagical = static_cast<item_quality>(is->bId >> 1);
item._iIdentified = (is->bId & 1) != 0;
item._iDurability = is->bDur;
item._iMaxDur = is->bMDur;
item._iCharges = is->bCh;
item._iMaxCharges = is->bMCh;
item = {};
RecreateItem(item, idx, SDL_SwapLE16(packedItem.iCreateInfo), SDL_SwapLE32(packedItem.iSeed), SDL_SwapLE16(packedItem.wValue), isHellfire);
item._iMagical = static_cast<item_quality>(packedItem.bId >> 1);
item._iIdentified = (packedItem.bId & 1) != 0;
item._iDurability = packedItem.bDur;
item._iMaxDur = packedItem.bMDur;
item._iCharges = packedItem.bCh;
item._iMaxCharges = packedItem.bMCh;
RemoveInvalidItem(item);
@ -183,7 +181,6 @@ void UnPackItem(const ItemPack *is, Item *id, bool isHellfire)
else
item.dwBuff &= ~CF_HELLFIRE;
}
*id = item;
}
bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync)
@ -257,14 +254,14 @@ bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync)
for (int i = 0; i < NUM_INVLOC; i++) {
auto packedItem = pPack->InvBody[i];
bool isHellfire = netSync ? ((packedItem.dwBuff & CF_HELLFIRE) != 0) : (pPack->bIsHellfire != 0);
UnPackItem(&packedItem, &player.InvBody[i], isHellfire);
UnPackItem(packedItem, player.InvBody[i], isHellfire);
}
player._pNumInv = pPack->_pNumInv;
for (int i = 0; i < player._pNumInv; i++) {
auto packedItem = pPack->InvList[i];
bool isHellfire = netSync ? ((packedItem.dwBuff & CF_HELLFIRE) != 0) : (pPack->bIsHellfire != 0);
UnPackItem(&packedItem, &player.InvList[i], isHellfire);
UnPackItem(packedItem, player.InvList[i], isHellfire);
}
for (int i = 0; i < NUM_INV_GRID_ELEM; i++)
@ -275,7 +272,7 @@ bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync)
for (int i = 0; i < MAXBELTITEMS; i++) {
auto packedItem = pPack->SpdList[i];
bool isHellfire = netSync ? ((packedItem.dwBuff & CF_HELLFIRE) != 0) : (pPack->bIsHellfire != 0);
UnPackItem(&packedItem, &player.SpdList[i], isHellfire);
UnPackItem(packedItem, player.SpdList[i], isHellfire);
}
if (&player == &Players[MyPlayerId]) {

View file

@ -81,16 +81,21 @@ struct PlayerPack {
void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield);
bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync);
void PackItem(ItemPack *id, const Item *is);
/**
* Expand an ItemPack into an Item
* @brief Save the attributes needed to recreate this item into an ItemPack struct
*
* Note: last slot of item[MAXITEMS+1] used as temporary buffer
* find real name reference below, possibly [sizeof(item[])/sizeof(Item)]
* @param is The source packed item
* @param id The destination item
* @param packedItem
* @param item
*/
void PackItem(ItemPack &packedItem, const Item &item);
/**
* Expand a ItemPack in to a Item
*
* @param packedItem The source packed item
* @param item The destination item
*/
void UnPackItem(const ItemPack *is, Item *id, bool isHellfire);
void UnPackItem(const ItemPack &packedItem, Item &item, bool isHellfire);
} // namespace devilution

View file

@ -6,39 +6,39 @@
using namespace devilution;
static void ComparePackedItems(const ItemPack *item1, const ItemPack *item2)
static void ComparePackedItems(const ItemPack &item1, const ItemPack &item2)
{
// `ItemPack` is packed, so we copy the unaligned values out before comparing them.
// This avoids the following UBSAN error such as this one:
// runtime error: load of misaligned address for type 'const unsigned int', which requires 4 byte alignment
{
const auto item1_iSeed = item1->iSeed;
const auto item2_iSeed = item2->iSeed;
const auto item1_iSeed = item1.iSeed;
const auto item2_iSeed = item2.iSeed;
EXPECT_EQ(item1_iSeed, item2_iSeed);
}
{
const auto item1_iCreateInfo = item1->iCreateInfo;
const auto item2_iCreateInfo = item2->iCreateInfo;
const auto item1_iCreateInfo = item1.iCreateInfo;
const auto item2_iCreateInfo = item2.iCreateInfo;
EXPECT_EQ(item1_iCreateInfo, item2_iCreateInfo);
}
{
const auto item1_idx = item1->idx;
const auto item2_idx = item2->idx;
const auto item1_idx = item1.idx;
const auto item2_idx = item2.idx;
EXPECT_EQ(item1_idx, item2_idx);
}
EXPECT_EQ(item1->bId, item2->bId);
EXPECT_EQ(item1->bDur, item2->bDur);
EXPECT_EQ(item1->bMDur, item2->bMDur);
EXPECT_EQ(item1->bCh, item2->bCh);
EXPECT_EQ(item1->bMCh, item2->bMCh);
EXPECT_EQ(item1.bId, item2.bId);
EXPECT_EQ(item1.bDur, item2.bDur);
EXPECT_EQ(item1.bMDur, item2.bMDur);
EXPECT_EQ(item1.bCh, item2.bCh);
EXPECT_EQ(item1.bMCh, item2.bMCh);
{
const auto item1_wValue = item1->wValue;
const auto item2_wValue = item2->wValue;
const auto item1_wValue = item1.wValue;
const auto item2_wValue = item2.wValue;
EXPECT_EQ(item1_wValue, item2_wValue);
}
{
const auto item1_dwBuff = item1->dwBuff;
const auto item2_dwBuff = item2->dwBuff;
const auto item1_dwBuff = item1.dwBuff;
const auto item2_dwBuff = item2.dwBuff;
EXPECT_EQ(item1_dwBuff, item2_dwBuff);
}
}
@ -87,50 +87,50 @@ typedef struct TestItemStruct {
int IDidx;
} TestItemStruct;
static void CompareItems(const Item *item1, const TestItemStruct *item2)
static void CompareItems(const Item &item1, const TestItemStruct &item2)
{
ASSERT_STREQ(item1->_iIName, item2->_iIName);
EXPECT_EQ(item1->_itype, item2->_itype);
EXPECT_EQ(item1->_iClass, item2->_iClass);
EXPECT_EQ(item1->_iCurs, item2->_iCurs);
EXPECT_EQ(item1->_iIvalue, item2->_iIvalue);
EXPECT_EQ(item1->_iMinDam, item2->_iMinDam);
EXPECT_EQ(item1->_iMaxDam, item2->_iMaxDam);
EXPECT_EQ(item1->_iAC, item2->_iAC);
EXPECT_EQ(item1->_iFlags, item2->_iFlags);
EXPECT_EQ(item1->_iMiscId, item2->_iMiscId);
EXPECT_EQ(item1->_iSpell, item2->_iSpell);
EXPECT_EQ(item1->_iCharges, item2->_iCharges);
EXPECT_EQ(item1->_iMaxCharges, item2->_iMaxCharges);
EXPECT_EQ(item1->_iDurability, item2->_iDurability);
EXPECT_EQ(item1->_iMaxDur, item2->_iMaxDur);
EXPECT_EQ(item1->_iPLDam, item2->_iPLDam);
EXPECT_EQ(item1->_iPLToHit, item2->_iPLToHit);
EXPECT_EQ(item1->_iPLAC, item2->_iPLAC);
EXPECT_EQ(item1->_iPLStr, item2->_iPLStr);
EXPECT_EQ(item1->_iPLMag, item2->_iPLMag);
EXPECT_EQ(item1->_iPLDex, item2->_iPLDex);
EXPECT_EQ(item1->_iPLVit, item2->_iPLVit);
EXPECT_EQ(item1->_iPLFR, item2->_iPLFR);
EXPECT_EQ(item1->_iPLLR, item2->_iPLLR);
EXPECT_EQ(item1->_iPLMR, item2->_iPLMR);
EXPECT_EQ(item1->_iPLMana, item2->_iPLMana);
EXPECT_EQ(item1->_iPLHP, item2->_iPLHP);
EXPECT_EQ(item1->_iPLDamMod, item2->_iPLDamMod);
EXPECT_EQ(item1->_iPLGetHit, item2->_iPLGetHit);
EXPECT_EQ(item1->_iPLLight, item2->_iPLLight);
EXPECT_EQ(item1->_iSplLvlAdd, item2->_iSplLvlAdd);
EXPECT_EQ(item1->_iUid, item2->_iUid);
EXPECT_EQ(item1->_iFMinDam, item2->_iFMinDam);
EXPECT_EQ(item1->_iFMaxDam, item2->_iFMaxDam);
EXPECT_EQ(item1->_iLMinDam, item2->_iLMinDam);
EXPECT_EQ(item1->_iLMaxDam, item2->_iLMaxDam);
EXPECT_EQ(item1->_iPrePower, item2->_iPrePower);
EXPECT_EQ(item1->_iSufPower, item2->_iSufPower);
EXPECT_EQ(item1->_iMinStr, item2->_iMinStr);
EXPECT_EQ(item1->_iMinMag, item2->_iMinMag);
EXPECT_EQ(item1->_iMinDex, item2->_iMinDex);
EXPECT_EQ(item1->IDidx, item2->IDidx);
ASSERT_STREQ(item1._iIName, item2._iIName);
EXPECT_EQ(item1._itype, item2._itype);
EXPECT_EQ(item1._iClass, item2._iClass);
EXPECT_EQ(item1._iCurs, item2._iCurs);
EXPECT_EQ(item1._iIvalue, item2._iIvalue);
EXPECT_EQ(item1._iMinDam, item2._iMinDam);
EXPECT_EQ(item1._iMaxDam, item2._iMaxDam);
EXPECT_EQ(item1._iAC, item2._iAC);
EXPECT_EQ(item1._iFlags, item2._iFlags);
EXPECT_EQ(item1._iMiscId, item2._iMiscId);
EXPECT_EQ(item1._iSpell, item2._iSpell);
EXPECT_EQ(item1._iCharges, item2._iCharges);
EXPECT_EQ(item1._iMaxCharges, item2._iMaxCharges);
EXPECT_EQ(item1._iDurability, item2._iDurability);
EXPECT_EQ(item1._iMaxDur, item2._iMaxDur);
EXPECT_EQ(item1._iPLDam, item2._iPLDam);
EXPECT_EQ(item1._iPLToHit, item2._iPLToHit);
EXPECT_EQ(item1._iPLAC, item2._iPLAC);
EXPECT_EQ(item1._iPLStr, item2._iPLStr);
EXPECT_EQ(item1._iPLMag, item2._iPLMag);
EXPECT_EQ(item1._iPLDex, item2._iPLDex);
EXPECT_EQ(item1._iPLVit, item2._iPLVit);
EXPECT_EQ(item1._iPLFR, item2._iPLFR);
EXPECT_EQ(item1._iPLLR, item2._iPLLR);
EXPECT_EQ(item1._iPLMR, item2._iPLMR);
EXPECT_EQ(item1._iPLMana, item2._iPLMana);
EXPECT_EQ(item1._iPLHP, item2._iPLHP);
EXPECT_EQ(item1._iPLDamMod, item2._iPLDamMod);
EXPECT_EQ(item1._iPLGetHit, item2._iPLGetHit);
EXPECT_EQ(item1._iPLLight, item2._iPLLight);
EXPECT_EQ(item1._iSplLvlAdd, item2._iSplLvlAdd);
EXPECT_EQ(item1._iUid, item2._iUid);
EXPECT_EQ(item1._iFMinDam, item2._iFMinDam);
EXPECT_EQ(item1._iFMaxDam, item2._iFMaxDam);
EXPECT_EQ(item1._iLMinDam, item2._iLMinDam);
EXPECT_EQ(item1._iLMaxDam, item2._iLMaxDam);
EXPECT_EQ(item1._iPrePower, item2._iPrePower);
EXPECT_EQ(item1._iSufPower, item2._iSufPower);
EXPECT_EQ(item1._iMinStr, item2._iMinStr);
EXPECT_EQ(item1._iMinMag, item2._iMinMag);
EXPECT_EQ(item1._iMinDex, item2._iMinDex);
EXPECT_EQ(item1.IDidx, item2.IDidx);
}
const ItemPack PackedDiabloItems[] = {
@ -340,11 +340,11 @@ TEST(pack, UnPackItem_diablo)
Players[MyPlayerId]._pMaxHPBase = 125 << 6;
for (size_t i = 0; i < sizeof(PackedDiabloItems) / sizeof(*PackedDiabloItems); i++) {
UnPackItem(&PackedDiabloItems[i], &id, false);
CompareItems(&id, &DiabloItems[i]);
UnPackItem(PackedDiabloItems[i], id, false);
CompareItems(id, DiabloItems[i]);
PackItem(&is, &id);
ComparePackedItems(&is, &PackedDiabloItems[i]);
PackItem(is, id);
ComparePackedItems(is, PackedDiabloItems[i]);
}
}
@ -358,7 +358,7 @@ TEST(pack, UnPackItem_diablo_unique_bug)
gbIsSpawn = false;
Item id;
UnPackItem(&pkItemBug, &id, false);
UnPackItem(pkItemBug, id, false);
ASSERT_STREQ(id._iIName, "Veil of Steel");
ASSERT_EQ(id._itype, ItemType::Helm);
ASSERT_EQ(id._iClass, ICLASS_ARMOR);
@ -378,8 +378,8 @@ TEST(pack, UnPackItem_diablo_unique_bug)
ASSERT_EQ(id.IDidx, IDI_STEELVEIL);
ItemPack is;
PackItem(&is, &id);
ComparePackedItems(&is, &pkItem);
PackItem(is, id);
ComparePackedItems(is, pkItem);
}
const ItemPack PackedSpawnItems[] = {
@ -411,11 +411,11 @@ TEST(pack, UnPackItem_spawn)
Players[MyPlayerId]._pMaxHPBase = 125 << 6;
for (size_t i = 0; i < sizeof(PackedSpawnItems) / sizeof(*PackedSpawnItems); i++) {
UnPackItem(&PackedSpawnItems[i], &id, false);
CompareItems(&id, &SpawnItems[i]);
UnPackItem(PackedSpawnItems[i], id, false);
CompareItems(id, SpawnItems[i]);
PackItem(&is, &id);
ComparePackedItems(&is, &PackedSpawnItems[i]);
PackItem(is, id);
ComparePackedItems(is, PackedSpawnItems[i]);
}
}
@ -455,11 +455,11 @@ TEST(pack, UnPackItem_diablo_multiplayer)
Players[MyPlayerId]._pMaxHPBase = 125 << 6;
for (size_t i = 0; i < sizeof(PackedDiabloMPItems) / sizeof(*PackedDiabloMPItems); i++) {
UnPackItem(&PackedDiabloMPItems[i], &id, false);
CompareItems(&id, &DiabloMPItems[i]);
UnPackItem(PackedDiabloMPItems[i], id, false);
CompareItems(id, DiabloMPItems[i]);
PackItem(&is, &id);
ComparePackedItems(&is, &PackedDiabloMPItems[i]);
PackItem(is, id);
ComparePackedItems(is, PackedDiabloMPItems[i]);
}
}
@ -664,12 +664,12 @@ TEST(pack, UnPackItem_hellfire)
Players[MyPlayerId]._pMaxHPBase = 125 << 6;
for (size_t i = 0; i < sizeof(PackedHellfireItems) / sizeof(*PackedHellfireItems); i++) {
UnPackItem(&PackedHellfireItems[i], &id, true);
CompareItems(&id, &HellfireItems[i]);
UnPackItem(PackedHellfireItems[i], id, true);
CompareItems(id, HellfireItems[i]);
PackItem(&is, &id);
PackItem(is, id);
is.dwBuff &= ~CF_HELLFIRE;
ComparePackedItems(&is, &PackedHellfireItems[i]);
ComparePackedItems(is, PackedHellfireItems[i]);
}
}
@ -682,7 +682,7 @@ TEST(pack, UnPackItem_diablo_strip_hellfire_items)
gbIsMultiplayer = false;
gbIsSpawn = false;
UnPackItem(&is, &id, true);
UnPackItem(is, id, true);
ASSERT_EQ(id._itype, ItemType::None);
}
@ -692,7 +692,7 @@ TEST(pack, UnPackItem_empty)
ItemPack is = { 0, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0 };
Item id;
UnPackItem(&is, &id, false);
UnPackItem(is, id, false);
ASSERT_EQ(id._itype, ItemType::None);
}
@ -700,46 +700,46 @@ TEST(pack, UnPackItem_empty)
TEST(pack, PackItem_empty)
{
ItemPack is;
Item id;
Item id = {};
id._itype = ItemType::None;
PackItem(&is, &id);
PackItem(is, id);
ASSERT_EQ(is.idx, 0xFFFF);
}
static void compareGold(const ItemPack *is, int iCurs)
static void compareGold(const ItemPack &is, int iCurs)
{
Item id;
UnPackItem(is, &id, false);
UnPackItem(is, id, false);
ASSERT_EQ(id._iCurs, iCurs);
ASSERT_EQ(id.IDidx, IDI_GOLD);
ASSERT_EQ(id._ivalue, is->wValue);
ASSERT_EQ(id._ivalue, is.wValue);
ASSERT_EQ(id._itype, ItemType::Gold);
ASSERT_EQ(id._iClass, ICLASS_GOLD);
ItemPack is2;
PackItem(&is2, &id);
ComparePackedItems(is, &is2);
PackItem(is2, id);
ComparePackedItems(is, is2);
}
TEST(pack, UnPackItem_gold_small)
{
ItemPack is = { 0, 0, IDI_GOLD, 0, 0, 0, 0, 0, 1000, 0 };
compareGold(&is, ICURS_GOLD_SMALL);
compareGold(is, ICURS_GOLD_SMALL);
}
TEST(pack, UnPackItem_gold_medium)
{
ItemPack is = { 0, 0, IDI_GOLD, 0, 0, 0, 0, 0, 1001, 0 };
compareGold(&is, ICURS_GOLD_MEDIUM);
compareGold(is, ICURS_GOLD_MEDIUM);
}
TEST(pack, UnPackItem_gold_large)
{
ItemPack is = { 0, 0, IDI_GOLD, 0, 0, 0, 0, 0, 2500, 0 };
compareGold(&is, ICURS_GOLD_LARGE);
compareGold(is, ICURS_GOLD_LARGE);
}
TEST(pack, UnPackItem_ear)
@ -747,11 +747,11 @@ TEST(pack, UnPackItem_ear)
ItemPack is = { 1633955154, 17509, 23, 111, 103, 117, 101, 68, 19843, 0 };
Item id;
UnPackItem(&is, &id, false);
UnPackItem(is, id, false);
ASSERT_STREQ(id._iName, "Ear of Dead-RogueDM");
ASSERT_EQ(id._ivalue, 3);
ItemPack is2;
PackItem(&is2, &id);
ComparePackedItems(&is, &is2);
PackItem(is2, id);
ComparePackedItems(is, is2);
}