diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index 58d73e37..c8b20983 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -2064,6 +2064,10 @@ public: /// Returns true if the spell can be interrupted by abilities like Kick/Counterspell. /// False for spells with SPELL_ATTR_EX_NOT_INTERRUPTIBLE (attrEx bit 4 = 0x10). bool isSpellInterruptible(uint32_t spellId) const; + /// Returns the school bitmask for the spell from Spell.dbc + /// (0x01=Physical, 0x02=Holy, 0x04=Fire, 0x08=Nature, 0x10=Frost, 0x20=Shadow, 0x40=Arcane). + /// Returns 0 if unknown. + uint32_t getSpellSchoolMask(uint32_t spellId) const; struct TrainerTab { std::string name; diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index f760f050..aee5d91e 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -21576,6 +21576,13 @@ bool GameHandler::isSpellInterruptible(uint32_t spellId) const { return (it->second.attrEx & 0x00000010u) == 0; } +uint32_t GameHandler::getSpellSchoolMask(uint32_t spellId) const { + if (spellId == 0) return 0; + const_cast(this)->loadSpellNameCache(); + auto it = spellNameCache_.find(spellId); + return (it != spellNameCache_.end()) ? it->second.schoolMask : 0; +} + const std::string& GameHandler::getSkillLineName(uint32_t spellId) const { auto slIt = spellToSkillLine_.find(spellId); if (slIt == spellToSkillLine_.end()) return EMPTY_STRING; diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index a580fab3..cd4d0589 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -8616,9 +8616,20 @@ void GameScreen::renderCastBar(game::GameHandler& gameHandler) { ? (1.0f - gameHandler.getCastProgress()) : gameHandler.getCastProgress(); - ImVec4 barColor = channeling - ? ImVec4(0.3f, 0.6f, 0.9f, 1.0f) // blue for channels - : ImVec4(0.8f, 0.6f, 0.2f, 1.0f); // gold for casts + // Color by spell school for cast identification; channels always blue + ImVec4 barColor; + if (channeling) { + barColor = ImVec4(0.3f, 0.6f, 0.9f, 1.0f); // blue for channels + } else { + uint32_t school = (currentSpellId != 0) ? gameHandler.getSpellSchoolMask(currentSpellId) : 0; + if (school & 0x04) barColor = ImVec4(0.95f, 0.40f, 0.10f, 1.0f); // Fire: orange-red + else if (school & 0x10) barColor = ImVec4(0.30f, 0.65f, 0.95f, 1.0f); // Frost: icy blue + else if (school & 0x20) barColor = ImVec4(0.55f, 0.15f, 0.70f, 1.0f); // Shadow: purple + else if (school & 0x40) barColor = ImVec4(0.65f, 0.30f, 0.85f, 1.0f); // Arcane: violet + else if (school & 0x08) barColor = ImVec4(0.20f, 0.75f, 0.25f, 1.0f); // Nature: green + else if (school & 0x02) barColor = ImVec4(0.90f, 0.80f, 0.30f, 1.0f); // Holy: golden + else barColor = ImVec4(0.80f, 0.60f, 0.20f, 1.0f); // Physical/default: gold + } ImGui::PushStyleColor(ImGuiCol_PlotHistogram, barColor); char overlay[96];