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
This commit is contained in:
Kelsi 2026-03-17 16:42:19 -07:00
parent 973db16658
commit dee33db0aa

View file

@ -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<uint32_t, std::string> 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;