feat: show rich spell tooltip on action bar hover

Expose SpellbookScreen::renderSpellInfoTooltip() as a public method,
then use it in the action bar slot tooltip. Action bar spell tooltips
now show the same full tooltip as the spellbook: spell school (colored),
mana/rage/energy cost, cast time, range, cooldown, and description.

Falls back to a plain spell name if DBC data is not yet loaded.
Hearthstone location note is appended after the rich body.
Cooldown text moved inside each branch for consistent styling.
This commit is contained in:
Kelsi 2026-03-10 19:31:46 -07:00
parent 7bbf2c7769
commit caf0d18393
3 changed files with 41 additions and 12 deletions

View file

@ -44,6 +44,11 @@ public:
// Spell name lookup — triggers DBC load if needed, used by action bar tooltips
std::string lookupSpellName(uint32_t spellId, pipeline::AssetManager* assetManager);
// Rich tooltip — renders a full spell tooltip (inside an already-open BeginTooltip block).
// Triggers DBC load if needed. Returns true if spell data was found.
bool renderSpellInfoTooltip(uint32_t spellId, game::GameHandler& gameHandler,
pipeline::AssetManager* assetManager);
// Drag-and-drop state for action bar assignment
bool isDraggingSpell() const { return draggingSpell_; }
uint32_t getDragSpellId() const { return dragSpellId_; }

View file

@ -4141,9 +4141,15 @@ void GameScreen::renderActionBar(game::GameHandler& gameHandler) {
// Tooltip
if (ImGui::IsItemHovered() && !slot.isEmpty() && slot.id != 0) {
ImGui::BeginTooltip();
if (slot.type == game::ActionBarSlot::SPELL) {
ImGui::Text("%s", getSpellName(slot.id).c_str());
// Use the spellbook's rich tooltip (school, cost, cast time, range, description).
// Falls back to the simple name if DBC data isn't loaded yet.
ImGui::BeginTooltip();
bool richOk = spellbookScreen.renderSpellInfoTooltip(slot.id, gameHandler, assetMgr);
if (!richOk) {
ImGui::Text("%s", getSpellName(slot.id).c_str());
}
// Hearthstone: add location note after the spell tooltip body
if (slot.id == 8690) {
uint32_t mapId = 0; glm::vec3 pos;
if (gameHandler.getHomeBind(mapId, pos)) {
@ -4156,25 +4162,34 @@ void GameScreen::renderActionBar(game::GameHandler& gameHandler) {
}
ImGui::TextColored(ImVec4(0.8f, 0.9f, 1.0f, 1.0f), "Home: %s", mapName);
}
ImGui::TextDisabled("Use: Teleport home");
}
if (onCooldown) {
float cd = slot.cooldownRemaining;
if (cd >= 60.0f)
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
"Cooldown: %d min %d sec", (int)cd/60, (int)cd%60);
else
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "Cooldown: %.1f sec", cd);
}
ImGui::EndTooltip();
} else if (slot.type == game::ActionBarSlot::ITEM) {
ImGui::BeginTooltip();
if (barItemDef && !barItemDef->name.empty())
ImGui::Text("%s", barItemDef->name.c_str());
else if (!itemNameFromQuery.empty())
ImGui::Text("%s", itemNameFromQuery.c_str());
else
ImGui::Text("Item #%u", slot.id);
if (onCooldown) {
float cd = slot.cooldownRemaining;
if (cd >= 60.0f)
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
"Cooldown: %d min %d sec", (int)cd/60, (int)cd%60);
else
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "Cooldown: %.1f sec", cd);
}
ImGui::EndTooltip();
}
if (onCooldown) {
float cd = slot.cooldownRemaining;
if (cd >= 60.0f)
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f),
"Cooldown: %d min %d sec", (int)cd/60, (int)cd%60);
else
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Cooldown: %.1f sec", cd);
}
ImGui::EndTooltip();
}
// Cooldown overlay: WoW-style clock-sweep + time text

View file

@ -184,6 +184,15 @@ void SpellbookScreen::loadSpellDBC(pipeline::AssetManager* assetManager) {
dbcLoaded = !spellData.empty();
}
bool SpellbookScreen::renderSpellInfoTooltip(uint32_t spellId, game::GameHandler& gameHandler,
pipeline::AssetManager* assetManager) {
if (!dbcLoadAttempted) loadSpellDBC(assetManager);
const SpellInfo* info = getSpellInfo(spellId);
if (!info) return false;
renderSpellTooltip(info, gameHandler);
return true;
}
std::string SpellbookScreen::lookupSpellName(uint32_t spellId, pipeline::AssetManager* assetManager) {
if (!dbcLoadAttempted) {
loadSpellDBC(assetManager);