Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for item drop rates up to 255 #7533

Merged
merged 2 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions Source/itemdat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ std::vector<PLStruct> ItemSuffixes;

namespace {

tl::expected<item_drop_rate, std::string> ParseItemDropRate(std::string_view value)
{
if (value == "Never") return IDROP_NEVER;
if (value == "Regular") return IDROP_REGULAR;
if (value == "Double") return IDROP_DOUBLE;
return tl::make_unexpected("Unknown enum value");
}

tl::expected<item_class, std::string> ParseItemClass(std::string_view value)
{
if (value == "None") return ICLASS_NONE;
Expand Down Expand Up @@ -534,7 +526,7 @@ void LoadItemDat()
RecordReader reader { record, filename };
ItemData &item = AllItemsList.emplace_back();
reader.advance(); // Skip the first column (item ID).
reader.read("dropRate", item.iRnd, ParseItemDropRate);
reader.readInt("dropRate", item.dropRate);
reader.read("class", item.iClass, ParseItemClass);
reader.read("equipType", item.iLoc, ParseItemEquipType);
reader.read("cursorGraphic", item.iCurs, ParseItemCursorGraphic);
Expand Down
8 changes: 1 addition & 7 deletions Source/itemdat.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,6 @@ enum _item_indexes : int16_t { // TODO defines all indexes in AllItemsList
IDI_NONE = -1,
};

enum item_drop_rate : uint8_t {
IDROP_NEVER,
IDROP_REGULAR,
IDROP_DOUBLE,
};

enum item_class : uint8_t {
ICLASS_NONE,
ICLASS_WEAPON,
Expand Down Expand Up @@ -489,7 +483,7 @@ enum item_misc_id : int8_t {
};

struct ItemData {
enum item_drop_rate iRnd;
uint8_t dropRate;
enum item_class iClass;
enum item_equip_type iLoc;
enum item_cursor_graphic iCurs;
Expand Down
24 changes: 13 additions & 11 deletions Source/items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1350,30 +1350,32 @@ void GetItemBonus(const Player &player, Item &item, int minlvl, int maxlvl, bool
}
}

struct WeightedItemIndex {
_item_indexes index;
unsigned cumulativeWeight;
};

_item_indexes GetItemIndexForDroppableItem(bool considerDropRate, tl::function_ref<bool(const ItemData &item)> isItemOkay)
{
static std::array<_item_indexes, IDI_LAST * 2> ril;
static std::vector<WeightedItemIndex> ril;
ril.clear();

size_t ri = 0;
unsigned cumulativeWeight = 0;
for (std::underlying_type_t<_item_indexes> i = IDI_GOLD; i <= IDI_LAST; i++) {
if (!IsItemAvailable(i))
continue;
const ItemData &item = AllItemsList[i];
if (item.iRnd == IDROP_NEVER)
if (item.dropRate == 0)
continue;
if (IsAnyOf(item.iSpell, SpellID::Resurrect, SpellID::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++;
}
cumulativeWeight += considerDropRate ? item.dropRate : 1;
ril.push_back({ static_cast<_item_indexes>(i), cumulativeWeight });
}

return ril[GenerateRnd(static_cast<int>(ri))];
unsigned targetWeight = static_cast<unsigned>(RandomIntLessThan(static_cast<int>(cumulativeWeight)));
return std::upper_bound(ril.begin(), ril.end(), targetWeight, [](unsigned target, const WeightedItemIndex &value) { return target < value.cumulativeWeight; })->index;
}

_item_indexes RndUItem(Monster *monster)
Expand Down
2 changes: 1 addition & 1 deletion Source/objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4353,7 +4353,7 @@ void ObjChangeMapResync(int x1, int y1, int x2, int y2)
_item_indexes ItemMiscIdIdx(item_misc_id imiscid)
{
std::underlying_type_t<_item_indexes> i = IDI_GOLD;
while (AllItemsList[i].iRnd == IDROP_NEVER || AllItemsList[i].iMiscId != imiscid) {
while (AllItemsList[i].dropRate == 0 || AllItemsList[i].iMiscId != imiscid) {
i++;
}

Expand Down
Loading
Loading