From 79f423191c48db78b785f4572dd93852ff7b277a Mon Sep 17 00:00:00 2001 From: obligaron Date: Tue, 29 Nov 2022 21:13:27 +0100 Subject: [PATCH] Introduce GetItemIndexForDroppableItem --- Source/items.cpp | 172 +++++++++++++++-------------------------------- 1 file changed, 54 insertions(+), 118 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index f80b7381f..fdc7279f9 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1307,37 +1307,24 @@ void GetItemBonus(const Player &player, Item &item, int minlvl, int maxlvl, bool } } -_item_indexes RndUItem(Monster *monster) +_item_indexes GetItemIndexForDroppableItem(bool considerDropRate, tl::function_ref isItemOkay) { - static std::array<_item_indexes, 512> ril; + static std::array<_item_indexes, IDI_LAST * 2> ril; - int curlv = ItemsGetCurrlevel(); size_t ri = 0; for (std::underlying_type_t<_item_indexes> i = IDI_GOLD; i <= IDI_LAST; i++) { if (!IsItemAvailable(i)) continue; - - bool okflag = true; - if (AllItemsList[i].iRnd == IDROP_NEVER) - okflag = false; - if (monster != nullptr) { - if (monster->level(sgGameInitInfo.nDifficulty) < AllItemsList[i].iMinMLvl) - okflag = false; - } else { - if (2 * curlv < AllItemsList[i].iMinMLvl) - okflag = false; - } - if (AllItemsList[i].itype == ItemType::Misc) - okflag = false; - if (AllItemsList[i].itype == ItemType::Gold) - okflag = false; - if (AllItemsList[i].iMiscId == IMISC_BOOK) - okflag = true; - if (AllItemsList[i].iSpell == SPL_RESURRECT && !gbIsMultiplayer) - okflag = false; - if (AllItemsList[i].iSpell == SPL_HEALOTHER && !gbIsMultiplayer) - okflag = false; - if (okflag && ri < ril.size()) { + const ItemData &item = AllItemsList[i]; + if (item.iRnd == IDROP_NEVER) + continue; + if (IsAnyOf(item.iSpell, SPL_RESURRECT, SPL_HEALOTHER) && !gbIsMultiplayer) + continue; + if (!isItemOkay(item)) + continue; + ril[ri] = static_cast<_item_indexes>(i); + ri++; + if (item.iRnd == IDROP_DOUBLE && considerDropRate) { ril[ri] = static_cast<_item_indexes>(i); ri++; } @@ -1346,55 +1333,47 @@ _item_indexes RndUItem(Monster *monster) return ril[GenerateRnd(static_cast(ri))]; } +_item_indexes RndUItem(Monster *monster) +{ + int itemMaxLevel = ItemsGetCurrlevel() * 2; + if (monster != nullptr) + itemMaxLevel = monster->level(sgGameInitInfo.nDifficulty); + return GetItemIndexForDroppableItem(false, [&itemMaxLevel](const ItemData &item) { + if (item.itype == ItemType::Misc && item.iMiscId == IMISC_BOOK) + return true; + if (itemMaxLevel < item.iMinMLvl) + return false; + if (IsAnyOf(item.itype, ItemType::Gold, ItemType::Misc)) + return false; + return true; + }); +} + _item_indexes RndAllItems() { if (GenerateRnd(100) > 25) return IDI_GOLD; - static std::array<_item_indexes, 512> ril; - - int curlv = ItemsGetCurrlevel(); - size_t ri = 0; - for (std::underlying_type_t<_item_indexes> i = IDI_GOLD; i <= IDI_LAST; i++) { - if (!IsItemAvailable(i)) - continue; - if (IsAnyOf(AllItemsList[i].iSpell, SPL_RESURRECT, SPL_HEALOTHER) && !gbIsMultiplayer) - continue; - - if (AllItemsList[i].iRnd != IDROP_NEVER && 2 * curlv >= AllItemsList[i].iMinMLvl && ri < ril.size()) { - ril[ri] = static_cast<_item_indexes>(i); - ri++; - } - } - - return ril[GenerateRnd(static_cast(ri))]; + int itemMaxLevel = ItemsGetCurrlevel() * 2; + return GetItemIndexForDroppableItem(false, [&itemMaxLevel](const ItemData &item) { + if (itemMaxLevel < item.iMinMLvl) + return false; + return true; + }); } _item_indexes RndTypeItems(ItemType itemType, int imid, int lvl) { - static std::array<_item_indexes, 512> ril; - - size_t ri = 0; - for (std::underlying_type_t<_item_indexes> i = IDI_GOLD; i <= IDI_LAST; i++) { - if (!IsItemAvailable(i)) - continue; - - bool okflag = true; - if (AllItemsList[i].iRnd == IDROP_NEVER) - okflag = false; - if (lvl * 2 < AllItemsList[i].iMinMLvl) - okflag = false; - if (AllItemsList[i].itype != itemType) - okflag = false; - if (imid != -1 && AllItemsList[i].iMiscId != imid) - okflag = false; - if (okflag && ri < ril.size()) { - ril[ri] = static_cast<_item_indexes>(i); - ri++; - } - } - - return ril[GenerateRnd(static_cast(ri))]; + int itemMaxLevel = lvl * 2; + return GetItemIndexForDroppableItem(false, [&itemMaxLevel, &itemType, &imid](const ItemData &item) { + if (itemMaxLevel < item.iMinMLvl) + return false; + if (item.itype != itemType) + return false; + if (imid != -1 && item.iMiscId != imid) + return false; + return true; + }); } _unique_items CheckUnique(Item &item, int lvl, int uper, bool recreate) @@ -1873,34 +1852,13 @@ bool SmithItemOk(const Player &player, const ItemData &item) template _item_indexes RndVendorItem(const Player &player, int minlvl, int maxlvl) { - static std::array<_item_indexes, 512> ril; - - size_t ri = 0; - for (std::underlying_type_t<_item_indexes> i = IDI_WARRIOR; i <= IDI_LAST; i++) { - if (!IsItemAvailable(i)) - continue; - if (AllItemsList[i].iRnd == IDROP_NEVER) - continue; - if (!Ok(player, AllItemsList[i])) - continue; - if (AllItemsList[i].iMinMLvl < minlvl || AllItemsList[i].iMinMLvl > maxlvl) - continue; - - ril[ri] = static_cast<_item_indexes>(i); - ri++; - if (ri >= ril.size()) - break; - - if (!ConsiderDropRate || AllItemsList[i].iRnd != IDROP_DOUBLE) - continue; - - ril[ri] = static_cast<_item_indexes>(i); - ri++; - if (ri >= ril.size()) - break; - } - - return ril[GenerateRnd(static_cast(ri))]; + return GetItemIndexForDroppableItem(ConsiderDropRate, [&player, &minlvl, &maxlvl](const ItemData &item) { + if (!Ok(player, item)) + return false; + if (item.iMinMLvl < minlvl || item.iMinMLvl > maxlvl) + return false; + return true; + }); } _item_indexes RndSmithItem(const Player &player, int lvl) @@ -2232,31 +2190,9 @@ _item_indexes RndItemForMonsterLevel(int8_t monsterLevel) if (GenerateRnd(100) > 25) return IDI_GOLD; - static std::array<_item_indexes, 512> ril; - - size_t ri = 0; - for (std::underlying_type_t<_item_indexes> i = IDI_GOLD; i <= IDI_LAST; i++) { - if (!IsItemAvailable(i)) - continue; - - if (AllItemsList[i].iRnd == IDROP_DOUBLE && monsterLevel >= AllItemsList[i].iMinMLvl - && ri < ril.size()) { - ril[ri] = static_cast<_item_indexes>(i); - ri++; - } - if (AllItemsList[i].iRnd != IDROP_NEVER && monsterLevel >= AllItemsList[i].iMinMLvl - && ri < ril.size()) { - ril[ri] = static_cast<_item_indexes>(i); - ri++; - } - if (AllItemsList[i].iSpell == SPL_RESURRECT && !gbIsMultiplayer) - ri--; - if (AllItemsList[i].iSpell == SPL_HEALOTHER && !gbIsMultiplayer) - ri--; - } - - int r = GenerateRnd(static_cast(ri)); - return ril[r]; + return GetItemIndexForDroppableItem(true, [&monsterLevel](const ItemData &item) { + return item.iMinMLvl <= monsterLevel; + }); } } // namespace