diff --git a/zone/gm_commands/lootsim.cpp b/zone/gm_commands/lootsim.cpp index aed6b6eae..b61957f1d 100755 --- a/zone/gm_commands/lootsim.cpp +++ b/zone/gm_commands/lootsim.cpp @@ -116,13 +116,13 @@ void command_lootsim(Client *c, const Seperator *sep) c->Message(Chat::White, fmt::format("# Global Loot Table ID [{}]", id).c_str()); c->SendChatLineBreak(); - loot_table = zone->GetLootTable(loottable_id); + loot_table = zone->GetLootTable(id); if (!loot_table) { c->Message(Chat::Red, fmt::format("Global Loot table not found [{}]", id).c_str()); continue; } - le = zone->GetLootTableEntries(loottable_id); + le = zone->GetLootTableEntries(id); // translate above for loop using loot_table_entries for (auto &e: le) { diff --git a/zone/loot.cpp b/zone/loot.cpp index 670a88c90..a81284c2f 100644 --- a/zone/loot.cpp +++ b/zone/loot.cpp @@ -22,7 +22,7 @@ void NPC::AddLootTable(uint32 loottable_id, bool is_global) if (!npctype_id) { return; } - + if (!is_global) { m_loot_copper = 0; m_loot_silver = 0; @@ -37,6 +37,14 @@ void NPC::AddLootTable(uint32 loottable_id, bool is_global) return; } + LogLootDetail( + "Attempting to load loot [{}] loottable [{}] ({}) is_global [{}]", + GetCleanName(), + loottable_id, + l->name, + is_global + ); + auto content_flags = ContentFlags{ .min_expansion = l->min_expansion, .max_expansion = l->max_expansion, @@ -106,7 +114,12 @@ void NPC::AddLootTable(uint32 loottable_id, bool is_global) } } - LogLootDetail("Loaded [{}] Loot Table [{}]", GetCleanName(), loottable_id); + LogLootDetail( + "Loaded [{}] Loot Table [{}] is_global [{}]", + GetCleanName(), + loottable_id, + is_global + ); } void NPC::AddLootDropTable(uint32 lootdrop_id, uint8 drop_limit, uint8 min_drop) @@ -128,10 +141,28 @@ void NPC::AddLootDropTable(uint32 lootdrop_id, uint8 drop_limit, uint8 min_drop) // if this lootdrop is droplimit=0 and mindrop 0, scan list once and return if (drop_limit == 0 && min_drop == 0) { for (const auto &e: le) { + LogLootDetail( + "-- NPC [{}] Lootdrop [{}] Item [{}] ({}_ Chance [{}] Multiplier [{}]", + GetCleanName(), + lootdrop_id, + database.GetItem(e.item_id)->Name, + e.item_id, + e.chance, + e.multiplier + ); for (int j = 0; j < e.multiplier; ++j) { if (zone->random.Real(0.0, 100.0) <= e.chance && MeetsLootDropLevelRequirements(e, true)) { const EQ::ItemData *database_item = database.GetItem(e.item_id); AddLootDrop(database_item, e); + LogLootDetail( + "---- NPC (Rolled) [{}] Lootdrop [{}] Item [{}] ({}) Chance [{}] Multiplier [{}]", + GetCleanName(), + lootdrop_id, + database_item->Name, + e.item_id, + e.chance, + e.multiplier + ); } } } diff --git a/zone/zone.h b/zone/zone.h index a6eceefba..aa00653e8 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -438,7 +438,7 @@ public: // loot void LoadLootTable(const uint32 loottable_id); - void LoadLootTables(const std::vector& loottable_ids); + void LoadLootTables(const std::vector in_loottable_ids); void ClearLootTables(); void ReloadLootTables(); LoottableRepository::Loottable *GetLootTable(const uint32 loottable_id); diff --git a/zone/zone_loot.cpp b/zone/zone_loot.cpp index 3b2d133f4..27c109f5e 100644 --- a/zone/zone_loot.cpp +++ b/zone/zone_loot.cpp @@ -5,20 +5,36 @@ #include "../common/repositories/lootdrop_repository.h" #include "../common/repositories/lootdrop_entries_repository.h" -void Zone::LoadLootTables(const std::vector &loottable_ids) +void Zone::LoadLootTables(const std::vector in_loottable_ids) { BenchTimer timer; + // copy loottable_ids + std::vector loottable_ids = in_loottable_ids; + // check if table is already loaded + std::vector loaded_tables = {}; for (const auto &e: loottable_ids) { for (const auto &f: m_loottables) { if (e == f.id) { LogLootDetail("Loottable [{}] already loaded", e); - return; + 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; @@ -82,6 +98,9 @@ void Zone::LoadLootTables(const std::vector &loottable_ids) break; } } + + bool has_entry = false; + if (!has_table) { // add loottable m_loottables.emplace_back(e); @@ -89,17 +108,53 @@ void Zone::LoadLootTables(const std::vector &loottable_ids) // add loottable entries for (const auto &f: loottable_entries) { if (e.id == f.loottable_id) { - m_loottable_entries.emplace_back(f); + + // 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) { - m_lootdrops.emplace_back(g); + + // 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) { - m_lootdrop_entries.emplace_back(h); + + // 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); + } } } }