diff --git a/CHANGELOG.md b/CHANGELOG.md index 14a9e43..c1f1fea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,49 @@ # Changelog -## 1.4.4 (2026-09-05) +## 1.4.4.1 (2026-09-06) + +Buff tracking & class spells update. Fixes buff clock icons (Divine Spirit, etc.) not appearing next to the health bar, adds group buff alternate matching, and completes the spell selection lists across all healer classes with buffs, utility and rez spells. + +### English + +**Fixed** + +- **Buff tracking & Tooltip scanning.** In Vanilla 1.12.1, `ClearLines()` on the hidden scan tooltip (`FBHealBoxScanTip`) does not clear hidden text lines. Because `FBPredict_TooltipText` did not check `fs:IsShown()`, leftover lines from previously scanned heal spells (e.g. "Heals a friendly target...") lingered and were read when inspecting buff tooltips like *Divine Spirit*. This erroneously flagged `info.isHeal = true`, skipping buff duration detection (`info.buff`) and causing *Divine Spirit* not to display its clock icon and timer in the plate UI. +- **Group buff alternate detection.** `FBPredict_BuildWatch` and `FBPredict_ScanUnit` now track group buff variants (`altTex`). When a group buff is applied or present (*Prayer of Fortitude*, *Prayer of Spirit*, *Gift of the Wild*, *Greater Blessings*), the addon correctly recognises the aura, confirms pending casts, and displays the buff clock icon. +- **Buff watch textures.** `FBLoadSpellData` now flags all spells in `FBBuffWatchSpells` as addon spells (`isHealBoxSpell = true`), ensuring their textures and ranks are gathered and monitored even if they are not yet assigned to a heal button. +- **Drag & drop instant sync.** Dropping a spell onto a button now immediately calls `FBPredict_BuildWatch()`, updating tracked buffs and predictions without requiring a `/reload`. + +**New & Changed** + +- **Expanded class spell lists.** Greatly expanded `Spell.Name` for all classes so that all relevant buffs, utility spells, dispels, and resurrections appear in the cascading spell menus: + - **Priest:** Added *Power Word: Fortitude*, *Prayer of Fortitude*, *Divine Spirit*, *Prayer of Spirit*, *Shadow Protection*, *Prayer of Shadow Protection*, *Fear Ward*, *Power Infusion*, *Resurrection*. + - **Druid:** Added *Mark of the Wild*, *Gift of the Wild*, *Thorns*, *Tranquility*, *Innervate*, *Rebirth*, *Cure Poison*. + - **Paladin:** Added all normal and Greater Blessings (*Wisdom, Might, Kings, Salvation, Light, Sanctuary*), *Blessing of Freedom*, *Blessing of Sacrifice*, *Redemption*, *Divine Intervention*. + - **Shaman:** Added *Ancestral Spirit*, *Purge*, *Water Walking*, *Water Breathing*, *Water Shield*. + - Added optional support for **Mage** (*Remove Lesser Curse*, *Arcane Intellect*, *Arcane Brilliance*, *Dampen Magic*, *Amplify Magic*) and **Warlock** (*Unending Breath*, *Detect Invisibility*). +- **Fear Ward in Buff Watch.** Added *Fear Ward* to `FBBuffWatchSpells` for Priests. + +### Deutsch + +**Behoben** + +- **Buff-Erkennung & Tooltip-Scan.** Im 1.12.1-Client leert `ClearLines()` auf dem versteckten Scan-Tooltip (`FBHealBoxScanTip`) ausgeblendete Textzeilen nicht. Da `FBPredict_TooltipText` nicht pruefte, ob eine Zeile sichtbar ist (`fs:IsShown()`), wurden Textzeilen zuvor gescannter Heilzauber (z. B. „Heals a friendly target...") faelschlicherweise auch bei Buff-Tooltips wie *Goettlicher Willen* (*Divine Spirit*) mitgelesen. Dadurch wurde fehlerhaft `isHeal = true` gesetzt, was die Erkennung der Buff-Laufzeit (`info.buff`) verhinderte und dazu fuehrte, dass das Buff-Icon links am Lebensbalken nicht erschien. +- **Erkennung von Gruppen-Buffs.** `FBPredict_BuildWatch` und `FBPredict_ScanUnit` unterstuetzen nun Gruppenversionen (`altTex`). Gruppen-Buffs (*Gebet der Seelenstaerke*, *Gebet der Willenskraft*, *Gabe der Wildnis*, *Grosse Segen*) werden nun zuverlaessig bestaetigt und mit Laufzeit/Icon dargestellt. +- **Buff-Wache Texturen.** `FBLoadSpellData` markiert nun alle Zauber aus `FBBuffWatchSpells` automatisch als Addon-Zauber (`isHealBoxSpell = true`), sodass ihre Texturen und Daten auch dann geladen und getrackt werden, wenn sie noch auf keinem Button liegen. +- **Drag & Drop Sofort-Synchronisation.** Das Ablegen eines Zaubers auf einen Button ruft nun direkt `FBPredict_BuildWatch()` auf, sodass neue Buffs und Vorhersagen ohne `/reload` sofort aktiv sind. + +**Neu & Geaendert** + +- **Vollstaendige Klassen-Zauberlisten.** `Spell.Name` fuer alle Heilerklassen stark erweitert, sodass saemtliche Heiler-Buffs, Gruppen-Buffs, Hilfszauber und Wiederbelebungen in den Auswahlmenues verfuegbar sind: + - **Priester:** *Machtwort: Seelenstaerke*, *Gebet der Seelenstaerke*, *Goettlicher Willen*, *Gebet der Willenskraft*, *Schattenschutz*, *Gebet des Schattenschutzes*, *Furchtzauberschutz*, *Seele der Macht*, *Auferstehung* hinzugefuegt. + - **Druide:** *Mal der Wildnis*, *Gabe der Wildnis*, *Dornen*, *Gelassenheit*, *Anregen*, *Wiedergeburt*, *Vergiftung heilen* hinzugefuegt. + - **Paladin:** Alle normalen und Grossen Segen (*Weisheit, Macht, Koenige, Rettung, Licht, Schutz*), *Segen der Freiheit*, *Segen der Opferung*, *Erloesung*, *Goettliches Eingreifen* hinzugefuegt. + - **Schamane:** *Geist der Ahnen*, *Reinigen*, *Wasserwandeln*, *Wasseratmung*, *Wasserschild* hinzugefuegt. + - Zusaetzliche Unterstuetzung fuer **Magier** (*Geringen Fluch aufheben*, *Arkane Intelligenz*, *Arkane Brillanz*, *Magie daempfen*, *Magie verstaerken*) und **Hexenmeister** (*Unendlicher Atem*, *Unsichtbarkeit entdecken*) ergaenzt. +- **Furchtzauberschutz in Buff-Wache.** *Fear Ward* fuer Priester in `FBBuffWatchSpells` aufgenommen. + + +## 1.4.4 (2026-09-06) Performance pass. No feature was added or changed; every visible behaviour is meant to be identical. A simulated five-second raid fight (40 players, aura and health events, mana changes, combat log, 60 frames per second) went from about 63,900 API and widget calls to about 14,450, a reduction of 77 %. diff --git a/FBHealBox.lua b/FBHealBox.lua index 016e783..2c16372 100644 --- a/FBHealBox.lua +++ b/FBHealBox.lua @@ -17,16 +17,17 @@ -- Anzeige, Debuff-Icon mit Stackzahl -- * v1.4.2: Hook-Schnittstelle fuer Module (FBHealBox_RegisterHook, -- FBHealBox_AddOptionsTab). Der Raidmodus lebt in FBHealBox_Raid.lua. --- * v1.4.4: Leistungsdurchgang ohne Funktionsaenderung: zentrale Button- --- Zustaende statt 260 Event-Handler, Anzeige-Zwischenspeicher, Aura-Scan --- je Frame nur einmal, Event-Salven zusammengefasst, Ticker per Event --- gesteuert, Combatlog-Parser nach Eventklasse. Details im CHANGELOG. -- * v1.4.3: Mana-Ticker-Modul (FBHealBox_Ticker.lua), Smart-Damage-Modul -- (FBHealBox_Damage.lua, Abrangen von Angriffszaubern), Reiterknoepfe -- schmaler, damit vier Reiter ins Optionsfenster passen, Smart Healing -- (automatisches Abrangen je Ziel, standardmaessig aus), Cooldown-Uhr auf den Buttons, roter Rahmen fuer -- "wer wird angegriffen", HoT- und Schild-Restzeit auf dem jeweiligen -- Button (inkl. Geschwaechte Seele). +-- * v1.4.4: Leistungsdurchgang ohne Funktionsaenderung: zentrale Button- +-- Zustaende statt 260 Event-Handler, Anzeige-Zwischenspeicher, Aura-Scan +-- je Frame nur einmal, Event-Salven zusammengefasst, Ticker per Event +-- gesteuert, Combatlog-Parser nach Eventklasse. Details im CHANGELOG. +-- * v1.4.4.1: Spells hinzugefügt, Bugfixes -- -- Ehre wem Ehre gebuehrt: Aufbau, Namensplaketten und Grundidee stammen -- aus dem Original. @@ -77,7 +78,7 @@ HealBox = { -- feuert ADDON_LOADED fuer uns. FBADDON_NAME = "Heal Box Vanilla"; FBADDON_FOLDER = "FBHealBox"; -HealBoxVersion = "|cFFFFFF00v1.4.4|r"; +HealBoxVersion = "|cFFFFFF00v1.4.4.1|r"; -- ========================================================================== -- [ Lokalisierung / Localization ] @@ -819,7 +820,7 @@ end -- gelernten erscheinen im Menue) und welche Gruppenversion dasselbe zaehlt. FBBuffWatchSpells = { Priest = { "Power Word: Fortitude", "Prayer of Fortitude", "Divine Spirit", "Prayer of Spirit", - "Shadow Protection", "Prayer of Shadow Protection", "Renew", "Power Word: Shield" }, + "Shadow Protection", "Prayer of Shadow Protection", "Fear Ward", "Renew", "Power Word: Shield", "Inner Fire" }, Druid = { "Mark of the Wild", "Gift of the Wild", "Thorns", "Rejuvenation", "Regrowth" }, Paladin = { "Blessing of Wisdom", "Greater Blessing of Wisdom", "Blessing of Might", "Greater Blessing of Might", "Blessing of Kings", "Greater Blessing of Kings", "Blessing of Salvation", "Greater Blessing of Salvation", @@ -1029,50 +1030,106 @@ Spell = { }; if (FBClass == "Druid") then - Spell.Name[1] = "Rejuvenation"; - Spell.Name[2] = "Regrowth"; - Spell.Name[3] = "Lifebloom"; - Spell.Name[4] = "Healing Touch"; - Spell.Name[5] = "Swiftmend"; - Spell.Name[6] = "Remove Curse"; - Spell.Name[7] = "Abolish Poison"; + -- Heilung + Spell.Name[1] = "Healing Touch"; + Spell.Name[2] = "Regrowth"; + Spell.Name[3] = "Rejuvenation"; + Spell.Name[4] = "Swiftmend"; + Spell.Name[5] = "Tranquility"; + Spell.Name[6] = "Lifebloom"; -- TBC / Vanilla+ + -- Reinigung + Spell.Name[7] = "Abolish Poison"; + Spell.Name[8] = "Cure Poison"; + Spell.Name[9] = "Remove Curse"; + -- Buffs & Rezz + Spell.Name[10] = "Mark of the Wild"; + Spell.Name[11] = "Gift of the Wild"; + Spell.Name[12] = "Thorns"; + Spell.Name[13] = "Innervate"; + Spell.Name[14] = "Rebirth"; end if (FBClass == "Priest") then - Spell.Name[1] = "Renew"; - Spell.Name[2] = "Flash Heal"; - Spell.Name[3] = "Lesser Heal"; - Spell.Name[4] = "Heal"; - Spell.Name[5] = "Greater Heal"; - Spell.Name[6] = "Binding Heal"; - Spell.Name[7] = "Prayer of Healing"; - Spell.Name[8] = "Prayer of Mending"; - Spell.Name[9] = "Circle of Healing"; - Spell.Name[10] = "Power Word: Shield"; - Spell.Name[11] = "Abolish Disease"; - Spell.Name[12] = "Cure Disease"; - Spell.Name[13] = "Dispel Magic"; -end - -if (FBClass == "Shaman") then - Spell.Name[1] = "Lesser Healing Wave"; - Spell.Name[2] = "Healing Wave"; - Spell.Name[3] = "Chain Heal"; - Spell.Name[4] = "Earth Shield"; - Spell.Name[5] = "Cure Poison"; - Spell.Name[6] = "Cure Disease"; + Spell.Name[1] = "Lesser Heal"; + Spell.Name[2] = "Heal"; + Spell.Name[3] = "Flash Heal"; + Spell.Name[4] = "Greater Heal"; + Spell.Name[5] = "Renew"; + Spell.Name[6] = "Power Word: Shield"; + Spell.Name[7] = "Prayer of Healing"; + Spell.Name[8] = "Binding Heal"; -- TBC / Vanilla+ + Spell.Name[9] = "Prayer of Mending"; -- TBC / Vanilla+ + Spell.Name[10] = "Circle of Healing"; -- TBC / Vanilla+ + Spell.Name[11] = "Dispel Magic"; + Spell.Name[12] = "Abolish Disease"; + Spell.Name[13] = "Cure Disease"; + Spell.Name[14] = "Power Word: Fortitude"; + Spell.Name[15] = "Prayer of Fortitude"; + Spell.Name[16] = "Divine Spirit"; + Spell.Name[17] = "Prayer of Spirit"; + Spell.Name[18] = "Shadow Protection"; + Spell.Name[19] = "Prayer of Shadow Protection"; + Spell.Name[20] = "Fear Ward"; + Spell.Name[21] = "Inner Fire"; + Spell.Name[22] = "Power Infusion"; + Spell.Name[23] = "Resurrection"; end if (FBClass == "Paladin") then - Spell.Name[1] = "Flash of Light"; - Spell.Name[2] = "Holy Light"; - Spell.Name[3] = "Holy Shock"; - Spell.Name[4] = "Lay on Hands"; - Spell.Name[5] = "Purify"; - Spell.Name[6] = "Cleanse"; - Spell.Name[7] = "Blessing of Protection"; + Spell.Name[1] = "Flash of Light"; + Spell.Name[2] = "Holy Light"; + Spell.Name[3] = "Holy Shock"; + Spell.Name[4] = "Lay on Hands"; + Spell.Name[5] = "Cleanse"; + Spell.Name[6] = "Purify"; + Spell.Name[7] = "Blessing of Protection"; + Spell.Name[8] = "Blessing of Freedom"; + Spell.Name[9] = "Blessing of Sacrifice"; + Spell.Name[10] = "Redemption"; + Spell.Name[11] = "Divine Intervention"; + Spell.Name[12] = "Blessing of Wisdom"; + Spell.Name[13] = "Blessing of Might"; + Spell.Name[14] = "Blessing of Kings"; + Spell.Name[15] = "Blessing of Salvation"; + Spell.Name[16] = "Blessing of Light"; + Spell.Name[17] = "Blessing of Sanctuary"; + Spell.Name[18] = "Greater Blessing of Wisdom"; + Spell.Name[19] = "Greater Blessing of Might"; + Spell.Name[20] = "Greater Blessing of Kings"; + Spell.Name[21] = "Greater Blessing of Salvation"; + Spell.Name[22] = "Greater Blessing of Light"; + Spell.Name[23] = "Greater Blessing of Sanctuary"; end +if (FBClass == "Shaman") then + Spell.Name[1] = "Lesser Healing Wave"; + Spell.Name[2] = "Healing Wave"; + Spell.Name[3] = "Chain Heal"; + Spell.Name[4] = "Earth Shield"; -- TBC / Vanilla+ + Spell.Name[5] = "Water Shield"; -- TBC / Vanilla+ + Spell.Name[6] = "Cure Poison"; + Spell.Name[7] = "Cure Disease"; + Spell.Name[8] = "Purge"; + Spell.Name[9] = "Ancestral Spirit"; + Spell.Name[10] = "Water Walking"; + Spell.Name[11] = "Water Breathing"; +end + +if (FBClass == "Mage") then + Spell.Name[1] = "Remove Lesser Curse"; + Spell.Name[2] = "Arcane Intellect"; + Spell.Name[3] = "Arcane Brilliance"; + Spell.Name[4] = "Dampen Magic"; + Spell.Name[5] = "Amplify Magic"; +end + +if (FBClass == "Warlock") then + Spell.Name[1] = "Unending Breath"; + Spell.Name[2] = "Detect Invisibility"; + Spell.Name[3] = "Detect Lesser Invisibility"; + Spell.Name[4] = "Detect Greater Invisibility"; +end + MaxButtonCount = 10; -- Speichert alle verfügbaren Zauber und Ränge @@ -1201,13 +1258,14 @@ function FBLoadSpellData() break; end end - -- Buff-Wache: Textur des Zaubers merken (rangunabhaengig) + -- Buff-Wache: Textur des Zaubers merken (rangunabhaengig) und als Addon-Zauber erfassen for _, v in ipairs(FBBuffWatchSpells[FBClass] or {}) do if (v == spellName) then FBBuffSpells[spellName] = { icon = GetSpellTexture(i, BOOKTYPE_SPELL) }; + isHealBoxSpell = true; break; end - end + end if isHealBoxSpell then if not FBPlayerSpells[spellName] then @@ -2129,6 +2187,7 @@ function FBHealBox_DropSpell(btnIndex, side) local _, _, _, _, savedTable = FBChoiceTables(side); savedTable[btnIndex] = castString; FBApplySpellChoice(btnIndex, castString, side); + FBPredict_BuildWatch(); FBHealBoxButtonsChanged(); local key = "DROP_SET"; @@ -4162,7 +4221,7 @@ function FBPredict_TooltipText(bookID) local i = 1; while (i <= 30) do local fs = getglobal("FBHealBoxScanTipTextLeft"..i); - if (not fs) then break; end + if (not fs or not fs:IsShown()) then break; end local line = fs:GetText(); if (line) then txt = txt.." "..line; end i = i + 1; @@ -4350,8 +4409,11 @@ function FBPredict_BuildWatch() local top = ranks[table.getn(ranks)]; local info = FBPredict_GetSpellInfo(top.id, spellName); if (info) then + local alt = FBBuffAlternates[spellName]; + local altTex = alt and FBBuffSpells[alt] and strupper(FBBuffSpells[alt].icon or ""); FBPredictWatch[spellName] = { tex = strupper(top.icon or ""), + altTex = altTex, bookID = top.id, rank = top.rank, hasDirect = (info.direct ~= nil), @@ -4683,7 +4745,7 @@ function FBPredict_ScanUnit(unit) -- ein Refresh (Nachcasten) die Uhr neu stellt. if (FBPredictPending and FBPredictPending.target == name) then local w = FBPredictWatch[FBPredictPending.spell]; - if (w and textures[w.tex]) then + if (w and (textures[w.tex] or (w.altTex and textures[w.altTex]))) then if (w.hasHoT) then dirty = FBPredict_StartHoT(name, FBPredictPending.spell, FBPredictPending.rank, FBPredictPending.bookID, true) or dirty; @@ -4705,14 +4767,12 @@ function FBPredict_ScanUnit(unit) if (not FBBuffPresent[name]) then FBBuffPresent[name] = {}; end for spellName, w in pairs(FBPredictWatch) do if (w.hasBuff) then - local present = textures[w.tex]; + local present = textures[w.tex] or (w.altTex and textures[w.altTex]); if (FBBuffPresent[name][spellName] ~= present) then FBBuffIconsDirty = true; end FBBuffPresent[name][spellName] = present; local tracked = FBBuffTimers[name] and FBBuffTimers[name][spellName]; if (present and unit == "player") then - -- beim Spieler bei jedem Scan neu aus der Buff-API lesen: so - -- stellt auch ein Neucast per Aktionsleiste die Uhr auf voll - local left = FBPredict_PlayerBuffTimeLeft(w.tex); + local left = FBPredict_PlayerBuffTimeLeft(w.tex) or (w.altTex and FBPredict_PlayerBuffTimeLeft(w.altTex)); if (left) then FBPredict_StartBuff(name, spellName, left); end elseif (tracked and not present) then FBBuffTimers[name][spellName] = nil; diff --git a/FBHealBox.toc b/FBHealBox.toc index 8dcfd08..8179410 100644 --- a/FBHealBox.toc +++ b/FBHealBox.toc @@ -1,9 +1,9 @@ ## Interface: 11200 -## Title: Heal Box Vanilla |cFFFFFF00v1.4.4|r +## Title: Heal Box Vanilla |cFFFFFF00v1.4.4.1|r ## Notes: Party, pet and self heal display with quick-cast buttons for healers. Ported to client 1.12.1 (optional SuperWoW). Up to 10 buttons per row, mana bar inside the health bar, class colours, buff watch, range fading, adjustable spacing, test mode with ghost players, optional raid mode for 20 and 40 players, mana ticker with five-second rule, smart damage ranking for attack spells. Heal prediction for direct heals, HoT ticks and absorb shields, self-correcting from the combat log. HealComm sync with Puppeteer, pfUI and others. German/English. Original by Dourd, ported to Vanilla and extended 09/2026 by Mquadrat. ## Notes-deDE: Party-, Begleiter- und Selbst-Heilanzeige mit Schnellzugriff-Buttons fuer Heiler. Portiert fuer Client 1.12.1 (optional SuperWoW). Bis zu 10 Buttons pro Reihe, Manabalken im Lebensbalken, Klassenfarben, Buff-Wache, Reichweiten-Fading, einstellbare Abstaende, Testmodus mit Geisterspielern, optionaler Raidmodus fuer 20 und 40 Spieler, Mana-Ticker mit Fuenf-Sekunden-Regel, Smart Damage fuer Angriffszauber. Heal-Prediction fuer Direktheilung, HoT-Ticks und Absorb-Schilde, selbstkorrigierend ueber den Combatlog. HealComm-Sync mit Puppeteer, pfUI und Co. Deutsch/Englisch. Original von Dourd, Vanilla-Portierung und Erweiterung 09/2026 von Mquadrat. ## Author: Dourd (Argent Dawn EU) | Vanilla-Port & Erweiterung 09/2026: Mquadrat -## Version: 1.4.4 +## Version: 1.4.4.1 ## SavedVariablesPerCharacter: HealBox ## OptionalDeps: SuperWoW