From a10139284d31eb8d1a9219178279648746623ffd Mon Sep 17 00:00:00 2001 From: Kelsi Date: Thu, 12 Mar 2026 13:08:41 -0700 Subject: [PATCH] feat: show spell tooltip text instead of name in item spell effects Item "Equip:" and "Use:" spell effects now display the spell's description text from Spell.dbc (e.g. "Increases your Spell Power by 30.") rather than the internal spell name (e.g. "Mana Spring Totem"). Falls back to the name when description is unavailable (e.g. older DBCs). Adds getSpellDescription() to GameHandler, backed by the existing loadSpellNameCache() pass which now reads the Tooltip field. --- include/game/game_handler.hpp | 4 +++- src/game/game_handler.cpp | 18 +++++++++++++++++- src/ui/inventory_screen.cpp | 21 +++++++++++++++------ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index efc8553d..a2cf3a6b 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -1679,6 +1679,8 @@ public: void closeTrainer(); const std::string& getSpellName(uint32_t spellId) const; const std::string& getSpellRank(uint32_t spellId) const; + /// Returns the tooltip/description text from Spell.dbc (empty if unknown or has no text). + const std::string& getSpellDescription(uint32_t spellId) const; const std::string& getSkillLineName(uint32_t spellId) const; /// Returns the DispelType for a spell (0=none,1=magic,2=curse,3=disease,4=poison,5+=other) uint8_t getSpellDispelType(uint32_t spellId) const; @@ -2598,7 +2600,7 @@ private: // Trainer bool trainerWindowOpen_ = false; TrainerListData currentTrainerList_; - struct SpellNameEntry { std::string name; std::string rank; uint32_t schoolMask = 0; uint8_t dispelType = 0; }; + struct SpellNameEntry { std::string name; std::string rank; std::string description; uint32_t schoolMask = 0; uint8_t dispelType = 0; }; std::unordered_map spellNameCache_; bool spellNameCacheLoaded_ = false; diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 7576561e..3439ffc1 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -17161,6 +17161,13 @@ void GameHandler::loadSpellNameCache() { if (f != 0xFFFFFFFF && f < dbc->getFieldCount()) { dispelField = f; hasDispelField = true; } } + // Tooltip/description field + uint32_t tooltipField = 0xFFFFFFFF; + if (spellL) { + uint32_t f = spellL->field("Tooltip"); + if (f != 0xFFFFFFFF && f < dbc->getFieldCount()) tooltipField = f; + } + uint32_t count = dbc->getRecordCount(); for (uint32_t i = 0; i < count; ++i) { uint32_t id = dbc->getUInt32(i, spellL ? (*spellL)["ID"] : 0); @@ -17168,7 +17175,10 @@ void GameHandler::loadSpellNameCache() { std::string name = dbc->getString(i, spellL ? (*spellL)["Name"] : 136); std::string rank = dbc->getString(i, spellL ? (*spellL)["Rank"] : 153); if (!name.empty()) { - SpellNameEntry entry{std::move(name), std::move(rank), 0, 0}; + SpellNameEntry entry{std::move(name), std::move(rank), {}, 0, 0}; + if (tooltipField != 0xFFFFFFFF) { + entry.description = dbc->getString(i, tooltipField); + } if (hasSchoolMask) { entry.schoolMask = dbc->getUInt32(i, schoolMaskField); } else if (hasSchoolEnum) { @@ -17373,6 +17383,12 @@ const std::string& GameHandler::getSpellRank(uint32_t spellId) const { return (it != spellNameCache_.end()) ? it->second.rank : EMPTY_STRING; } +const std::string& GameHandler::getSpellDescription(uint32_t spellId) const { + const_cast(this)->loadSpellNameCache(); + auto it = spellNameCache_.find(spellId); + return (it != spellNameCache_.end()) ? it->second.description : EMPTY_STRING; +} + uint8_t GameHandler::getSpellDispelType(uint32_t spellId) const { const_cast(this)->loadSpellNameCache(); auto it = spellNameCache_.find(spellId); diff --git a/src/ui/inventory_screen.cpp b/src/ui/inventory_screen.cpp index bc19f557..acce3a27 100644 --- a/src/ui/inventory_screen.cpp +++ b/src/ui/inventory_screen.cpp @@ -2233,10 +2233,13 @@ void InventoryScreen::renderItemTooltip(const game::ItemDef& item, const game::I default: break; } if (!trigger) continue; - const std::string& spName = gameHandler_->getSpellName(sp.spellId); - if (!spName.empty()) { + const std::string& spDesc = gameHandler_->getSpellDescription(sp.spellId); + const std::string& spText = spDesc.empty() ? gameHandler_->getSpellName(sp.spellId) : spDesc; + if (!spText.empty()) { + ImGui::PushTextWrapPos(ImGui::GetCursorPosX() + 320.0f); ImGui::TextColored(ImVec4(0.0f, 0.8f, 1.0f, 1.0f), - "%s: %s", trigger, spName.c_str()); + "%s: %s", trigger, spText.c_str()); + ImGui::PopTextWrapPos(); } else { ImGui::TextColored(ImVec4(0.0f, 0.8f, 1.0f, 1.0f), "%s: Spell #%u", trigger, sp.spellId); @@ -2521,11 +2524,17 @@ void InventoryScreen::renderItemTooltip(const game::ItemQueryResponseData& info, } if (!trigger) continue; if (gameHandler_) { - const std::string& spName = gameHandler_->getSpellName(sp.spellId); - if (!spName.empty()) + // Prefer the spell's tooltip text (the actual effect description). + // Fall back to the spell name if the description is empty. + const std::string& spDesc = gameHandler_->getSpellDescription(sp.spellId); + const std::string& spName = spDesc.empty() ? gameHandler_->getSpellName(sp.spellId) : spDesc; + if (!spName.empty()) { + ImGui::PushTextWrapPos(ImGui::GetCursorPosX() + 320.0f); ImGui::TextColored(ImVec4(0.0f, 0.8f, 1.0f, 1.0f), "%s: %s", trigger, spName.c_str()); - else + ImGui::PopTextWrapPos(); + } else { ImGui::TextColored(ImVec4(0.0f, 0.8f, 1.0f, 1.0f), "%s: Spell #%u", trigger, sp.spellId); + } } }