diff --git a/Data/expansions/tbc/dbc_layouts.json b/Data/expansions/tbc/dbc_layouts.json index 9ada081b..7929446f 100644 --- a/Data/expansions/tbc/dbc_layouts.json +++ b/Data/expansions/tbc/dbc_layouts.json @@ -100,5 +100,15 @@ }, "SpellItemEnchantment": { "ID": 0, "Name": 8 + }, + "ItemSet": { + "ID": 0, "Name": 1, + "Item0": 18, "Item1": 19, "Item2": 20, "Item3": 21, "Item4": 22, + "Item5": 23, "Item6": 24, "Item7": 25, "Item8": 26, "Item9": 27, + "Spell0": 28, "Spell1": 29, "Spell2": 30, "Spell3": 31, "Spell4": 32, + "Spell5": 33, "Spell6": 34, "Spell7": 35, "Spell8": 36, "Spell9": 37, + "Threshold0": 38, "Threshold1": 39, "Threshold2": 40, "Threshold3": 41, + "Threshold4": 42, "Threshold5": 43, "Threshold6": 44, "Threshold7": 45, + "Threshold8": 46, "Threshold9": 47 } } diff --git a/Data/expansions/turtle/dbc_layouts.json b/Data/expansions/turtle/dbc_layouts.json index beaa0c6c..c5a3948e 100644 --- a/Data/expansions/turtle/dbc_layouts.json +++ b/Data/expansions/turtle/dbc_layouts.json @@ -98,5 +98,15 @@ }, "SpellItemEnchantment": { "ID": 0, "Name": 8 + }, + "ItemSet": { + "ID": 0, "Name": 1, + "Item0": 10, "Item1": 11, "Item2": 12, "Item3": 13, "Item4": 14, + "Item5": 15, "Item6": 16, "Item7": 17, "Item8": 18, "Item9": 19, + "Spell0": 20, "Spell1": 21, "Spell2": 22, "Spell3": 23, "Spell4": 24, + "Spell5": 25, "Spell6": 26, "Spell7": 27, "Spell8": 28, "Spell9": 29, + "Threshold0": 30, "Threshold1": 31, "Threshold2": 32, "Threshold3": 33, + "Threshold4": 34, "Threshold5": 35, "Threshold6": 36, "Threshold7": 37, + "Threshold8": 38, "Threshold9": 39 } } diff --git a/Data/expansions/wotlk/dbc_layouts.json b/Data/expansions/wotlk/dbc_layouts.json index 3c4ec125..c8287a29 100644 --- a/Data/expansions/wotlk/dbc_layouts.json +++ b/Data/expansions/wotlk/dbc_layouts.json @@ -101,5 +101,15 @@ }, "SpellItemEnchantment": { "ID": 0, "Name": 8 + }, + "ItemSet": { + "ID": 0, "Name": 1, + "Item0": 18, "Item1": 19, "Item2": 20, "Item3": 21, "Item4": 22, + "Item5": 23, "Item6": 24, "Item7": 25, "Item8": 26, "Item9": 27, + "Spell0": 28, "Spell1": 29, "Spell2": 30, "Spell3": 31, "Spell4": 32, + "Spell5": 33, "Spell6": 34, "Spell7": 35, "Spell8": 36, "Spell9": 37, + "Threshold0": 38, "Threshold1": 39, "Threshold2": 40, "Threshold3": 41, + "Threshold4": 42, "Threshold5": 43, "Threshold6": 44, "Threshold7": 45, + "Threshold8": 46, "Threshold9": 47 } } diff --git a/include/game/world_packets.hpp b/include/game/world_packets.hpp index 2cb47fe1..24d795f7 100644 --- a/include/game/world_packets.hpp +++ b/include/game/world_packets.hpp @@ -1597,6 +1597,7 @@ struct ItemQueryResponseData { // Gem socket slots (WotLK/TBC): 0=no socket; color mask: 1=Meta,2=Red,4=Yellow,8=Blue std::array socketColor{}; uint32_t socketBonus = 0; // enchantmentId of socket bonus; 0=none + uint32_t itemSetId = 0; // ItemSet.dbc entry; 0=not part of a set bool valid = false; }; diff --git a/src/game/world_packets.cpp b/src/game/world_packets.cpp index abfa5929..dd7dc33f 100644 --- a/src/game/world_packets.cpp +++ b/src/game/world_packets.cpp @@ -2936,8 +2936,11 @@ bool ItemQueryResponseParser::parse(network::Packet& packet, ItemQueryResponseDa // TotemCategory(4) = 48 bytes before sockets constexpr size_t kPreSocketSkip = 48; if (packet.getReadPos() + kPreSocketSkip + 28 <= packet.getSize()) { - for (size_t i = 0; i < kPreSocketSkip / 4; ++i) - packet.readUInt32(); + // LockID(0), Material(1), Sheath(2), RandomProperty(3), RandomSuffix(4), Block(5) + for (size_t i = 0; i < 6; ++i) packet.readUInt32(); + data.itemSetId = packet.readUInt32(); // ItemSet(6) + // MaxDurability(7), Area(8), Map(9), BagFamily(10), TotemCategory(11) + for (size_t i = 0; i < 5; ++i) packet.readUInt32(); // 3 socket slots: socketColor (4 bytes each) data.socketColor[0] = packet.readUInt32(); data.socketColor[1] = packet.readUInt32(); diff --git a/src/ui/inventory_screen.cpp b/src/ui/inventory_screen.cpp index fc9bd564..fbe5fbfc 100644 --- a/src/ui/inventory_screen.cpp +++ b/src/ui/inventory_screen.cpp @@ -2536,6 +2536,36 @@ void InventoryScreen::renderItemTooltip(const game::ItemQueryResponseData& info, } } + // Item set membership + if (info.itemSetId != 0) { + // Lazy-load ItemSet.dbc name table + static std::unordered_map s_setNames; + static bool s_setNamesLoaded = false; + if (!s_setNamesLoaded && assetManager_) { + s_setNamesLoaded = true; + auto dbc = assetManager_->loadDBC("ItemSet.dbc"); + if (dbc && dbc->isLoaded()) { + const auto* layout = pipeline::getActiveDBCLayout() + ? pipeline::getActiveDBCLayout()->getLayout("ItemSet") : nullptr; + uint32_t idF = layout ? (*layout)["ID"] : 0; + uint32_t nameF = layout ? (*layout)["Name"] : 1; + for (uint32_t r = 0; r < dbc->getRecordCount(); ++r) { + uint32_t id = dbc->getUInt32(r, idF); + if (!id) continue; + std::string nm = dbc->getString(r, nameF); + if (!nm.empty()) s_setNames[id] = std::move(nm); + } + } + } + auto setIt = s_setNames.find(info.itemSetId); + const char* setName = (setIt != s_setNames.end()) ? setIt->second.c_str() : nullptr; + ImGui::Spacing(); + if (setName) + ImGui::TextColored(ImVec4(1.0f, 0.82f, 0.0f, 1.0f), "%s", setName); + else + ImGui::TextColored(ImVec4(1.0f, 0.82f, 0.0f, 1.0f), "Set (id %u)", info.itemSetId); + } + if (info.startQuestId != 0) { ImGui::TextColored(ImVec4(1.0f, 0.82f, 0.0f, 1.0f), "Begins a Quest"); }