Skip to content

Commit

Permalink
Fix Item Validation (#6723)
Browse files Browse the repository at this point in the history
Co-authored-by: staphen <[email protected]>
  • Loading branch information
kphoenix137 and StephenCWills authored Oct 19, 2023
1 parent 4467b84 commit dac2e03
Showing 1 changed file with 54 additions and 6 deletions.
60 changes: 54 additions & 6 deletions Source/pack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,41 +87,49 @@ bool IsCreationFlagComboValid(uint16_t iCreateInfo)
const bool isPregenItem = (iCreateInfo & CF_PREGEN) != 0;
const bool isUsefulItem = (iCreateInfo & CF_USEFUL) == CF_USEFUL;

if (isPregenItem)
if (isPregenItem) {
// Pregen flags are discarded when an item is picked up, therefore impossible to have in the inventory
return false;
}
if (isUsefulItem && (iCreateInfo & ~CF_USEFUL) != 0)
return false;
if (isTownItem && hasMultipleFlags(iCreateInfo))
if (isTownItem && hasMultipleFlags(iCreateInfo)) {
// Items from town can only have 1 towner flag
return false;
}
return true;
}

bool IsTownItemValid(uint16_t iCreateInfo, const Player &player)
{
const uint8_t level = iCreateInfo & CF_LEVEL;
const bool isBoyItem = (iCreateInfo & CF_BOY) != 0;
const uint8_t maxTownItemLevel = 30;

// Wirt items in multiplayer are equal to the level of the player, therefore they cannot exceed the max character level
if (isBoyItem && level <= player.getMaxCharacterLevel())
return true;

return level <= 30;
return level <= maxTownItemLevel;
}

bool IsUniqueMonsterItemValid(uint16_t iCreateInfo, uint32_t dwBuff)
{
const uint8_t level = iCreateInfo & CF_LEVEL;
const bool isHellfireItem = (dwBuff & CF_HELLFIRE) != 0;

// Check all unique monster levels to see if they match the item level
for (int i = 0; UniqueMonstersData[i].mName != nullptr; i++) {
const auto &uniqueMonsterData = UniqueMonstersData[i];
const auto &uniqueMonsterLevel = static_cast<uint8_t>(MonstersData[uniqueMonsterData.mtype].level);

if (!isHellfireItem && IsAnyOf(uniqueMonsterData.mtype, MT_HORKDMN, MT_DEFILER, MT_NAKRUL)) {
// These monsters don't appear in Diablo
if (IsAnyOf(uniqueMonsterData.mtype, MT_DEFILER, MT_NAKRUL, MT_HORKDMN)) {
// These monsters don't use their mlvl for item generation
continue;
}

if (level == uniqueMonsterLevel) {
// If the ilvl matches the mlvl, we confirm the item is legitimate
return true;
}
}
Expand All @@ -134,24 +142,62 @@ bool IsDungeonItemValid(uint16_t iCreateInfo, uint32_t dwBuff)
const uint8_t level = iCreateInfo & CF_LEVEL;
const bool isHellfireItem = (dwBuff & CF_HELLFIRE) != 0;

// Check all monster levels to see if they match the item level
for (int16_t i = 0; i < static_cast<int16_t>(NUM_MTYPES); i++) {
const auto &monsterData = MonstersData[i];
auto monsterLevel = static_cast<uint8_t>(monsterData.level);

if (i != MT_DIABLO && monsterData.availability == MonsterAvailability::Never) {
// Skip monsters that are unable to appear in the game
continue;
}

if (i == MT_DIABLO && !isHellfireItem) {
// Adjust The Dark Lord's mlvl if the item isn't a Hellfire item to match the Diablo mlvl
monsterLevel -= 15;
}

if (level == monsterLevel) {
// If the ilvl matches the mlvl, we confirm the item is legitimate
return true;
}
}

return level <= 30;
if (isHellfireItem) {
uint8_t hellfireMaxDungeonLevel = 24;

// Hellfire adjusts the currlevel minus 7 in dungeon levels 20-24 for generating items
hellfireMaxDungeonLevel -= 7;
return level <= (hellfireMaxDungeonLevel * 2);
}

uint8_t diabloMaxDungeonLevel = 16;

// Diablo doesn't have containers that drop items in dungeon level 16, therefore we decrement by 1
diabloMaxDungeonLevel--;
return level <= (diabloMaxDungeonLevel * 2);
}

bool RecreateHellfireSpellBook(const Player &player, const ItemNetPack &packedItem, Item &item)
{
Item spellBook {};
RecreateItem(player, packedItem.item, spellBook);

// Hellfire uses the spell book level when generating items via CreateSpellBook()
int spellBookLevel = GetSpellBookLevel(spellBook._iSpell);

// CreateSpellBook() adds 1 to the spell level for ilvl
spellBookLevel++;

if (spellBookLevel >= 1 && (spellBook._iCreateInfo & CF_LEVEL) == spellBookLevel * 2) {
// The ilvl matches the result for a spell book drop, so we confirm the item is legitimate
item = spellBook;
return true;
}

ValidateFields(spellBook._iCreateInfo, spellBook.dwBuff, IsDungeonItemValid(spellBook._iCreateInfo, spellBook.dwBuff));
item = spellBook;
return true;
}

} // namespace
Expand Down Expand Up @@ -491,6 +537,8 @@ bool UnPackNetItem(const Player &player, const ItemNetPack &packedItem, Item &it
ValidateField(creationFlags, IsTownItemValid(creationFlags, player));
else if ((creationFlags & CF_USEFUL) == CF_UPER15)
ValidateFields(creationFlags, dwBuff, IsUniqueMonsterItemValid(creationFlags, dwBuff));
else if ((dwBuff & CF_HELLFIRE) != 0 && AllItemsList[idx].iMiscId == IMISC_BOOK)
return RecreateHellfireSpellBook(player, packedItem, item);
else
ValidateFields(creationFlags, dwBuff, IsDungeonItemValid(creationFlags, dwBuff));

Expand Down

0 comments on commit dac2e03

Please sign in to comment.