From dee33db0aa337978f83a1203a67f79676f3eb03c Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 17 Mar 2026 16:42:19 -0700 Subject: [PATCH] feat: show gem socket slots and socket bonus in chat item link tooltips Item tooltips shown when hovering chat links already displayed all stats, spells, and flavor text, but gem sockets were missing. Add the same socket rendering used in the inventory tooltip: - Iterate socketColor[0..2]; for each non-zero slot show a colored label (Meta / Red / Yellow / Blue Socket) in the socket's faction color - Lazy-load SpellItemEnchantment.dbc to resolve the socketBonus enchant name; fall back to "(id N)" when the record is not found - Consistent with InventoryScreen::renderItemTooltip formatting --- src/ui/game_screen.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index fdf2f3d2..bef79214 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -1512,6 +1512,54 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) { ImGui::TextColored(green, "+%d %s", es.statValue, nm); } } + // Gem sockets (WotLK only — socketColor != 0 means socket present) + // socketColor bitmask: 1=Meta, 2=Red, 4=Yellow, 8=Blue + { + static const struct { uint32_t mask; const char* label; ImVec4 col; } kSocketTypes[] = { + { 1, "Meta Socket", { 0.7f, 0.7f, 0.9f, 1.0f } }, + { 2, "Red Socket", { 1.0f, 0.3f, 0.3f, 1.0f } }, + { 4, "Yellow Socket", { 1.0f, 0.9f, 0.3f, 1.0f } }, + { 8, "Blue Socket", { 0.3f, 0.6f, 1.0f, 1.0f } }, + }; + bool hasSocket = false; + for (int s = 0; s < 3; ++s) { + if (info->socketColor[s] == 0) continue; + if (!hasSocket) { ImGui::Spacing(); hasSocket = true; } + for (const auto& st : kSocketTypes) { + if (info->socketColor[s] & st.mask) { + ImGui::TextColored(st.col, "%s", st.label); + break; + } + } + } + if (hasSocket && info->socketBonus != 0) { + // Socket bonus ID maps to SpellItemEnchantment.dbc — lazy-load names + static std::unordered_map s_enchantNames; + static bool s_enchantNamesLoaded = false; + if (!s_enchantNamesLoaded && assetMgr) { + s_enchantNamesLoaded = true; + auto dbc = assetMgr->loadDBC("SpellItemEnchantment.dbc"); + if (dbc && dbc->isLoaded()) { + const auto* lay = pipeline::getActiveDBCLayout() + ? pipeline::getActiveDBCLayout()->getLayout("SpellItemEnchantment") : nullptr; + uint32_t nameField = lay ? lay->field("Name") : 8u; + if (nameField == 0xFFFFFFFF) nameField = 8; + uint32_t fc = dbc->getFieldCount(); + for (uint32_t r = 0; r < dbc->getRecordCount(); ++r) { + uint32_t eid = dbc->getUInt32(r, 0); + if (eid == 0 || nameField >= fc) continue; + std::string ename = dbc->getString(r, nameField); + if (!ename.empty()) s_enchantNames[eid] = std::move(ename); + } + } + } + auto enchIt = s_enchantNames.find(info->socketBonus); + if (enchIt != s_enchantNames.end()) + ImGui::TextColored(ImVec4(0.5f, 0.8f, 0.5f, 1.0f), "Socket Bonus: %s", enchIt->second.c_str()); + else + ImGui::TextColored(ImVec4(0.5f, 0.8f, 0.5f, 1.0f), "Socket Bonus: (id %u)", info->socketBonus); + } + } // Item spell effects (Use / Equip / Chance on Hit / Teaches) for (const auto& sp : info->spells) { if (sp.spellId == 0) continue;