From 5f3bc79653fada36667add35e55008a91c698e84 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 18 Mar 2026 04:34:36 -0700 Subject: [PATCH] feat: show queued spell icon in cast bar and expose getQueuedSpellId() When a spell is queued in the 400ms window before the current cast ends, render its icon dimmed (0.8 alpha) to the right of the cast bar progress, with a "Queued: " tooltip. The progress bar shrinks to accommodate the icon when one is present. Also exposes getQueuedSpellId() as a public const accessor on GameHandler so the UI can observe the spell queue state without friend access. --- include/game/game_handler.hpp | 3 +++ src/ui/game_screen.cpp | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index 1a40d5d8..b1d732ef 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -807,6 +807,9 @@ public: int getCraftQueueRemaining() const { return craftQueueRemaining_; } uint32_t getCraftQueueSpellId() const { return craftQueueSpellId_; } + // 400ms spell-queue window: next spell to cast when current finishes + uint32_t getQueuedSpellId() const { return queuedSpellId_; } + // Unit cast state (tracked per GUID for target frame + boss frames) struct UnitCastState { bool casting = false; diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index 0e74ab18..b81405cc 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -9732,13 +9732,32 @@ void GameScreen::renderCastBar(game::GameHandler& gameHandler) { } } + // Queued spell icon (right edge): the next spell queued to fire within 400ms. + uint32_t queuedId = gameHandler.getQueuedSpellId(); + VkDescriptorSet queuedTex = (queuedId != 0 && assetMgr) + ? getSpellIcon(queuedId, assetMgr) : VK_NULL_HANDLE; + + const float iconSz = 20.0f; + const float reservedRight = (queuedTex) ? (iconSz + 4.0f) : 0.0f; + if (iconTex) { // Spell icon to the left of the progress bar - ImGui::Image((ImTextureID)(uintptr_t)iconTex, ImVec2(20, 20)); + ImGui::Image((ImTextureID)(uintptr_t)iconTex, ImVec2(iconSz, iconSz)); ImGui::SameLine(0, 4); - ImGui::ProgressBar(progress, ImVec2(-1, 20), overlay); + ImGui::ProgressBar(progress, ImVec2(-reservedRight - 1.0f, iconSz), overlay); } else { - ImGui::ProgressBar(progress, ImVec2(-1, 20), overlay); + ImGui::ProgressBar(progress, ImVec2(-reservedRight - 1.0f, iconSz), overlay); + } + // Draw queued-spell icon on the right with a ">" arrow prefix tooltip. + if (queuedTex) { + ImGui::SameLine(0, 4); + ImGui::Image((ImTextureID)(uintptr_t)queuedTex, ImVec2(iconSz, iconSz), + ImVec2(0,0), ImVec2(1,1), + ImVec4(1,1,1,0.8f), ImVec4(0,0,0,0)); // slightly dimmed + if (ImGui::IsItemHovered()) { + const std::string& qn = gameHandler.getSpellName(queuedId); + ImGui::SetTooltip("Queued: %s", qn.empty() ? "Unknown" : qn.c_str()); + } } ImGui::PopStyleColor(); }