blob: 603dc5c1ee9851872edee14e491c97a0446455c0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#include "RandomItemTable.h"
#include "port/Game.h"
extern "C" {
#include "math_util.h"
}
RandomItemTable::RandomItemTable() {
mDistanceEnabled = false;
}
bool RandomItemTable::Add(const std::string& resourceName, uint32_t rank, uint32_t weight, float distance) {
const ItemInfo* info = gItemRegistry.GetInfo(resourceName);
if (!info) {
printf("[ItemTables] Failed to add %s to table,\n item name passed into resourceName does not exist!\n", resourceName.c_str());
return false;
}
if (rank >= mTable.size()) {
if (rank >= NUM_PLAYERS) {
printf("[ItemTables] Failed to add item table, rank value too high!\n");
return false;
}
mTable.resize(rank + 1);
}
// Check if already exists
for (const ItemEntry& entry : mTable[rank]) {
if (entry.Id == info->Id) {
printf("[ItemTables] %s already exists for this rank, skipping...\n", resourceName.c_str());
return false;
}
}
mTable[rank].push_back(ItemEntry{info->Id, weight, distance});
return true;
}
uint8_t RandomItemTable::Roll(uint32_t rank) const {
if (rank >= mTable.size()) {
printf("[ItemTables] [Roll] Invalid rank input %d. Giving player a none item\n", rank);
return ITEM_NONE;
}
// Items that could be selected for this rank
const std::vector<ItemEntry>& itemList = mTable.at(rank);
if (itemList.empty()) {
printf("[ItemTables] [Roll] itemList empty. Giving player a none item\n");
return ITEM_NONE;
}
// Calculate total weight
uint32_t totalWeight = 0;
for (const ItemEntry& entry : itemList) {
if (this->IsBlacklisted(entry.Id)) {
continue;
}
totalWeight += entry.Weight;
}
// Avoid division by zero
if (totalWeight == 0) {
printf("[ItemTables] [Roll] No items to give out for this rank. Giving player a none item\n");
return ITEM_NONE;
}
// Pick a random number from zero to (totalWeight - 1)
uint32_t rand = random_int(totalWeight - 1);
// Cumulative sum over weights
uint32_t accumulated = 0;
for (const ItemEntry& entry : itemList) {
if (this->IsBlacklisted(entry.Id)) {
continue;
}
accumulated += entry.Weight;
if (rand < accumulated) {
return static_cast<uint8_t>(entry.Id);
}
}
// Fallback (should not happen)
printf("[ItemTables] [Roll] Reached unreachable code\n");
[[unlikely]] return ITEM_NONE;
}
void RandomItemTable::Blacklist(const std::string& resourceName) {
const ItemInfo* info = gItemRegistry.GetInfo(resourceName);
if (!info) {
return;
}
mBlacklist.insert(info->Id);
}
bool RandomItemTable::IsBlacklisted(uint32_t itemId) const {
//return mBlacklist.contains(itemId);
return mBlacklist.find(itemId) != mBlacklist.end();
}
void RandomItemTable::ClearBlacklist() {
mBlacklist.clear();
}
|