diff --git a/include/ui/action_bar_panel.hpp b/include/ui/action_bar_panel.hpp index 18f256d1..60ee6384 100644 --- a/include/ui/action_bar_panel.hpp +++ b/include/ui/action_bar_panel.hpp @@ -62,6 +62,7 @@ public: // Action bar error-flash: spellId → wall-clock time (seconds) when the flash ends std::unordered_map actionFlashEndTimes_; + std::unordered_map itemSpellCooldownTotals_; static constexpr float kActionFlashDuration = 0.5f; // Action bar drag state (-1 = not dragging) diff --git a/src/ui/action_bar_panel.cpp b/src/ui/action_bar_panel.cpp index 402e733b..061be57a 100644 --- a/src/ui/action_bar_panel.cpp +++ b/src/ui/action_bar_panel.cpp @@ -304,6 +304,30 @@ void ActionBarPanel::renderActionBar(game::GameHandler& gameHandler, const auto& slot = bar[absSlot]; bool onCooldown = !slot.isReady(); + // Item cooldowns are frequently reported against the item's on-use spell + // (especially on Wrath) rather than against the action-slot item ID. + // Resolve that shared spell cooldown just as macro buttons do. + float itemCooldownRemaining = 0.0f; + float itemCooldownTotal = 0.0f; + if (slot.type == game::ActionBarSlot::ITEM && slot.id != 0 && !onCooldown) { + if (const auto* item = gameHandler.getItemInfo(slot.id); item && item->valid) { + for (const auto& itemSpell : item->spells) { + if (itemSpell.spellId == 0 || + (itemSpell.spellTrigger != 0 && itemSpell.spellTrigger != 5)) continue; + const float cooldown = gameHandler.getSpellCooldown(itemSpell.spellId); + if (cooldown > itemCooldownRemaining) itemCooldownRemaining = cooldown; + } + } + if (itemCooldownRemaining > 0.0f) { + float& rememberedTotal = itemSpellCooldownTotals_[slot.id]; + rememberedTotal = std::max(rememberedTotal, itemCooldownRemaining); + itemCooldownTotal = rememberedTotal; + onCooldown = true; + } else { + itemSpellCooldownTotals_.erase(slot.id); + } + } + // Macro cooldown: check the cached primary spell's cooldown. float macroCooldownRemaining = 0.0f; float macroCooldownTotal = 0.0f; @@ -744,8 +768,12 @@ void ActionBarPanel::renderActionBar(game::GameHandler& gameHandler, auto* dl = ImGui::GetWindowDrawList(); // For macros, use the resolved primary spell cooldown instead of the slot's own. - float effCdTotal = (macroCooldownTotal > 0.0f) ? macroCooldownTotal : slot.cooldownTotal; - float effCdRemaining = (macroCooldownRemaining > 0.0f) ? macroCooldownRemaining : slot.cooldownRemaining; + float effCdTotal = (macroCooldownTotal > 0.0f) ? macroCooldownTotal + : (itemCooldownTotal > 0.0f) ? itemCooldownTotal + : slot.cooldownTotal; + float effCdRemaining = (macroCooldownRemaining > 0.0f) ? macroCooldownRemaining + : (itemCooldownRemaining > 0.0f) ? itemCooldownRemaining + : slot.cooldownRemaining; float total = (effCdTotal > 0.0f) ? effCdTotal : 1.0f; float elapsed = total - effCdRemaining; float elapsedFrac = std::min(1.0f, std::max(0.0f, elapsed / total)); diff --git a/src/ui/game_screen_hud.cpp b/src/ui/game_screen_hud.cpp index 8d516b29..087a6143 100644 --- a/src/ui/game_screen_hud.cpp +++ b/src/ui/game_screen_hud.cpp @@ -691,17 +691,14 @@ void GameScreen::renderQuestObjectiveTracker(game::GameHandler& gameHandler) { constexpr float TRACKER_W = 220.0f; constexpr float RIGHT_MARGIN = 10.0f; - constexpr int MAX_QUESTS = 5; - // Build display list: tracked quests only, or all quests if none tracked const auto& trackedIds = gameHandler.getTrackedQuestIds(); std::vector toShow; - toShow.reserve(MAX_QUESTS); + toShow.reserve(questLog.size()); if (!trackedIds.empty()) { for (const auto& q : questLog) { if (q.questId == 0) continue; if (trackedIds.count(q.questId)) toShow.push_back(&q); - if (static_cast(toShow.size()) >= MAX_QUESTS) break; } } // Fallback: show all quests if nothing is tracked @@ -709,7 +706,6 @@ void GameScreen::renderQuestObjectiveTracker(game::GameHandler& gameHandler) { for (const auto& q : questLog) { if (q.questId == 0) continue; toShow.push_back(&q); - if (static_cast(toShow.size()) >= MAX_QUESTS) break; } } if (toShow.empty()) return; @@ -731,7 +727,6 @@ void GameScreen::renderQuestObjectiveTracker(game::GameHandler& gameHandler) { ImGui::SetNextWindowSize(questTrackerSize_, ImGuiCond_FirstUseEver); ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoBringToFrontOnFocus;