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); + } } }