eqemu-server/zone/zone_loot.cpp
Chris Miles 4215a3b9d6
[Loot] Consolidate filtering logic (#4280)
* [Loot] Consolidate filtering logic

* Log category
2024-04-20 21:17:38 -05:00

303 lines
6.7 KiB
C++

#include <vector>
#include "zone.h"
#include "../common/repositories/loottable_repository.h"
#include "../common/repositories/loottable_entries_repository.h"
#include "../common/repositories/lootdrop_repository.h"
#include "../common/repositories/lootdrop_entries_repository.h"
void Zone::LoadLootTables(const std::vector<uint32> in_loottable_ids)
{
BenchTimer timer;
// copy loottable_ids
std::vector<uint32> loottable_ids = in_loottable_ids;
// check if table is already loaded
std::vector<uint32> loaded_tables = {};
for (const auto &e: loottable_ids) {
for (const auto &f: m_loottables) {
if (e == f.id) {
LogLootDetail("Loottable [{}] already loaded", e);
loaded_tables.push_back(e);
}
}
}
// remove loaded tables from loottable_ids
for (const auto &e: loaded_tables) {
loottable_ids.erase(
std::remove(
loottable_ids.begin(),
loottable_ids.end(),
e
),
loottable_ids.end()
);
}
if (loottable_ids.empty()) {
LogLootDetail("No loottables to load");
return;
}
auto loottables = LoottableRepository::GetWhere(
content_db,
fmt::format(
"id IN ({})",
Strings::Join(loottable_ids, ",")
)
);
auto loottable_entries = LoottableEntriesRepository::GetWhere(
content_db,
fmt::format(
"loottable_id IN ({})",
Strings::Join(loottable_ids, ",")
)
);
std::vector<uint32> lootdrop_ids;
for (const auto &e: loottable_entries) {
if (std::find(
lootdrop_ids.begin(),
lootdrop_ids.end(),
e.lootdrop_id
) == lootdrop_ids.end()) {
lootdrop_ids.push_back(e.lootdrop_id);
}
}
if (lootdrop_ids.empty()) {
LogLoot("No lootdrops to load for loottable(s) [{}]", Strings::Join(loottable_ids, ","));
return;
}
auto lootdrops = LootdropRepository::GetWhere(
content_db,
fmt::format(
"id IN ({})",
Strings::Join(lootdrop_ids, ",")
)
);
auto lootdrop_entries = LootdropEntriesRepository::GetWhere(
content_db,
fmt::format(
"lootdrop_id IN ({})",
Strings::Join(lootdrop_ids, ",")
)
);
// emplace back tables to m_loottables if not exists
for (const auto &e: loottables) {
bool has_table = false;
for (const auto &l: m_loottables) {
if (e.id == l.id) {
has_table = true;
break;
}
}
bool has_entry = false;
if (!has_table) {
// add loottable
m_loottables.emplace_back(e);
// add loottable entries
for (const auto &f: loottable_entries) {
if (e.id == f.loottable_id) {
// check if loottable entry already exists in memory
has_entry = false;
for (const auto &g: m_loottable_entries) {
if (f.loottable_id == g.loottable_id && f.lootdrop_id == g.lootdrop_id) {
has_entry = true;
break;
}
}
if (!has_entry) {
m_loottable_entries.emplace_back(f);
}
// add lootdrop
for (const auto &g: lootdrops) {
if (f.lootdrop_id == g.id) {
// check if lootdrop already exists in memory
has_entry = false;
for (const auto &h: m_lootdrops) {
if (g.id == h.id) {
has_entry = true;
break;
}
}
if (!has_entry) {
m_lootdrops.emplace_back(g);
}
// add lootdrop entries
for (const auto &h: lootdrop_entries) {
if (g.id == h.lootdrop_id) {
// check if lootdrop entry already exists in memory
has_entry = false;
for (const auto &i: m_lootdrop_entries) {
if (h.lootdrop_id == i.lootdrop_id && h.item_id == i.item_id) {
has_entry = true;
break;
}
}
if (!has_entry) {
m_lootdrop_entries.emplace_back(h);
}
}
}
}
}
}
}
}
}
if (loottable_ids.size() > 1) {
LogInfo("Loaded [{}] loottables ({}s)", m_loottables.size(), std::to_string(timer.elapsed()));
}
}
void Zone::LoadLootTable(const uint32 loottable_id)
{
if (loottable_id == 0) {
return;
}
LoadLootTables({loottable_id});
}
void Zone::ClearLootTables()
{
m_loottables.clear();
m_loottable_entries.clear();
m_lootdrops.clear();
m_lootdrop_entries.clear();
}
void Zone::ReloadLootTables()
{
ClearLootTables();
std::vector<uint32> loottable_ids = {};
for (const auto& n : entity_list.GetNPCList()) {
// only add loottable if it's not already in the list
if (n.second->GetLoottableID() != 0) {
if (std::find(
loottable_ids.begin(),
loottable_ids.end(),
n.second->GetLoottableID()
) == loottable_ids.end()) {
loottable_ids.push_back(n.second->GetLoottableID());
}
}
}
LoadLootTables(loottable_ids);
}
LoottableRepository::Loottable *Zone::GetLootTable(const uint32 loottable_id)
{
for (auto &e: m_loottables) {
if (e.id == loottable_id) {
if (!content_service.DoesPassContentFiltering(
ContentFlags{
.min_expansion = e.min_expansion,
.max_expansion = e.max_expansion,
.content_flags = e.content_flags,
.content_flags_disabled = e.content_flags_disabled
}
)) {
LogLootDetail(
"Loot table [{}] does not pass content filtering",
loottable_id
);
continue;
}
return &e;
}
}
return nullptr;
}
std::vector<LoottableEntriesRepository::LoottableEntries> Zone::GetLootTableEntries(const uint32 loottable_id) const
{
std::vector<LoottableEntriesRepository::LoottableEntries> entries = {};
for (const auto &e: m_loottable_entries) {
if (e.loottable_id == loottable_id) {
entries.emplace_back(e);
}
}
return entries;
}
LootdropRepository::Lootdrop Zone::GetLootdrop(const uint32 lootdrop_id) const
{
for (const auto &e: m_lootdrops) {
if (e.id == lootdrop_id) {
if (!content_service.DoesPassContentFiltering(
ContentFlags{
.min_expansion = e.min_expansion,
.max_expansion = e.max_expansion,
.content_flags = e.content_flags,
.content_flags_disabled = e.content_flags_disabled
}
)) {
LogLootDetail(
"Lootdrop table [{}] does not pass content filtering",
lootdrop_id
);
continue;
}
return e;
}
}
return {};
}
std::vector<LootdropEntriesRepository::LootdropEntries> Zone::GetLootdropEntries(const uint32 lootdrop_id) const
{
std::vector<LootdropEntriesRepository::LootdropEntries> entries = {};
for (const auto &e: m_lootdrop_entries) {
if (e.lootdrop_id == lootdrop_id) {
if (!content_service.DoesPassContentFiltering(
ContentFlags{
.min_expansion = e.min_expansion,
.max_expansion = e.max_expansion,
.content_flags = e.content_flags,
.content_flags_disabled = e.content_flags_disabled
}
)) {
LogLootDetail(
"Lootdrop [{}] Item [{}] ({}) does not pass content filtering",
lootdrop_id,
e.item_id,
database.GetItem(e.item_id) ? database.GetItem(e.item_id)->Name : "Unknown"
);
continue;
}
entries.emplace_back(e);
}
}
return entries;
}