mirror of
https://github.com/QbiXibQ/FBHealBox.git
synced 2026-10-07 14:40:01 +00:00
Add files via upload
This commit is contained in:
+37
-2
@@ -1,8 +1,43 @@
|
||||
# Changelog
|
||||
|
||||
## 1.4.6 (2026-10-06)
|
||||
|
||||
Performance pass over the display loop, with no change in behaviour: only the units that actually changed are redrawn, and two loops that ran empty five times a second now stop early.
|
||||
|
||||
### English
|
||||
|
||||
**Performance**
|
||||
|
||||
- **Only the units that changed are redrawn.** The 0.2 second pass used to set a single dirty flag: if any heal over time ticked anywhere, everything was redrawn, which in a full raid meant forty cells plus ten plates although exactly one unit had changed. The pass now collects the affected unit names in a reused table and hands them to `FBHealBox_RefreshUnitsByName`, and the raid module picks up the same list through the new `RefreshNames` hook. With several HoTs running this turns three to five full sweeps a second into at most one plus a handful of single-unit updates.
|
||||
- **A full sweep stays as a safety net.** At most once a second, and only while something is actually changing, the old full refresh still runs, so a name that does not match a plate for any reason can never leave a stale bar behind for longer than that.
|
||||
- **Empty leftovers are cleared.** When the last heal over time or the last foreign heal on a unit expires, the now-empty sub-table is removed instead of being left behind. Several places read `FBHoTs[name]` as "is anything running on this unit", and an empty table answered yes.
|
||||
- **Raid spell timers skip cells with nothing to show.** The intent to skip was already in the code but the result was thrown away two lines later, so the button loop ran anyway: in a full raid that was 160 do-nothing calls five times a second. The cell is now skipped outright, exactly as the plates already did.
|
||||
- **Spell timers get an early out.** When no heal over time and no shield of yours is running anywhere, the plate loop no longer asks every slot for its unit and name five times a second; it only looks where a timer still has to be cleared. Classes without HoTs and the time between fights benefit.
|
||||
|
||||
**Checked and left alone**
|
||||
|
||||
- The three `OnUpdate` loops do no unnecessary work. The prediction checks three dirty flags and two counters per frame, the mana ticker leaves at its gate (a full mana bar means no pass at all), and the raid ghost ticker is hidden outside test mode. Event handling filters unit events through a lookup table rather than walking every frame.
|
||||
- The global cooldown has been drawn as a sweep since 1.4.5.1, which means every visible button gets a fresh sweep after every cast. That is the intended behaviour and the animation runs in the client, not in Lua, so it stays. Should it ever feel heavy in a dense raid, `FBCD_SHOW_MIN` set to 2 limits the sweep to real cooldowns again.
|
||||
|
||||
### Deutsch
|
||||
|
||||
**Leistung**
|
||||
|
||||
- **Nur noch die Einheiten neu zeichnen, bei denen sich etwas geaendert hat.** Der 0,2-Sekunden-Takt setzte bisher ein einziges Dirty-Flag: Lief irgendwo ein HoT-Tick ab, wurde alles neu gezeichnet, im Vierzigerraid also vierzig Zellen und zehn Plaketten, obwohl sich bei genau einer Einheit etwas geaendert hatte. Der Takt sammelt die betroffenen Namen jetzt in einer wiederverwendeten Tabelle und reicht sie an `FBHealBox_RefreshUnitsByName`; das Raidmodul bekommt dieselbe Liste ueber den neuen Hook `RefreshNames`. Mit mehreren laufenden HoTs werden aus drei bis fuenf vollen Durchlaeufen je Sekunde hoechstens einer plus eine Handvoll Einzel-Updates.
|
||||
- **Der volle Durchlauf bleibt als Sicherheitsnetz.** Hoechstens einmal je Sekunde, und nur solange sich ueberhaupt etwas aendert, laeuft er weiterhin. Ein Name, der aus irgendeinem Grund zu keiner Plakette passt, kann so nie laenger als eine Sekunde einen alten Balken stehen lassen.
|
||||
- **Leere Reste werden weggeraeumt.** Laeuft der letzte HoT oder die letzte fremde Heilung auf einer Einheit ab, verschwindet die nun leere Untertabelle, statt liegen zu bleiben. Mehrere Stellen lesen `FBHoTs[name]` als "laeuft da ueberhaupt etwas", und eine leere Tabelle hat darauf mit ja geantwortet.
|
||||
- **Raid-Zaubertimer ueberspringen Zellen ohne Anzeige.** Die Absicht zu ueberspringen stand schon im Code, das Ergebnis wurde aber zwei Zeilen spaeter wieder verworfen, sodass die Buttonschleife trotzdem lief: im Vierzigerraid 160 Leeraufrufe fuenfmal je Sekunde. Die Zelle wird jetzt wirklich uebersprungen, genau wie es die Plaketten laengst machen.
|
||||
- **Zaubertimer steigen frueher aus.** Laeuft nirgends ein eigener HoT und kein eigener Schild, fragt die Plakettenschleife nicht mehr fuenfmal je Sekunde jeden Slot nach Einheit und Namen, sondern schaut nur noch dort hinein, wo ein Timer wegzuraeumen ist. Davon profitieren Klassen ohne HoTs und die Zeit zwischen den Kaempfen.
|
||||
|
||||
**Geprueft und so gelassen**
|
||||
|
||||
- Die drei `OnUpdate`-Schleifen arbeiten nicht unnoetig. Die Vorhersage prueft je Frame drei Dirty-Flags und zwei Zaehler, der Mana-Ticker steigt am Torwaechter aus (voller Manabalken heisst gar kein Durchlauf), und der Geister-Ticker im Raid ist ausserhalb des Testmodus versteckt. Die Ereignisverarbeitung filtert Unit-Events ueber eine Nachschlagetabelle, statt je Frame zu suchen.
|
||||
- Der globale Cooldown laeuft seit 1.4.5.1 als Uhr mit, das heisst nach jedem Zauber bekommt jeder sichtbare Button eine neue Uhr gesetzt. Das ist das gewollte Verhalten, und die Animation laeuft im Client, nicht in Lua, deshalb bleibt es so. Sollte es im dichten Raid doch schwer wirken, beschraenkt `FBCD_SHOW_MIN` auf 2 die Uhr wieder auf echte Abklingzeiten.
|
||||
|
||||
|
||||
## 1.4.5.3 (2026-10-05)
|
||||
|
||||
A readability option suggested by a user has been added: the area behind the bars can be given a solid background, so the game world no longer shows through where health is missing.
|
||||
A readability option suggested by a user: the area behind the bars can be given a solid background, so the game world no longer shows through where health is missing.
|
||||
|
||||
### English
|
||||
|
||||
@@ -24,7 +59,7 @@ A readability option suggested by a user has been added: the area behind the bar
|
||||
- **Wo die Flaeche haengt.** Die Textur sitzt auf der untersten der vier gestapelten Balken, der Heilvorhersage, auf der Ebene `BACKGROUND`. Damit liegt sie unter Vorhersage, Schild, Leben und Mana, und sie wird zusammen mit ihnen ein- und ausgeblendet; auf einer leeren oder im Anheftmodus versteckten Plakette bleibt also nichts stehen. Bei 0 Prozent wird gar keine Textur gesetzt statt einer voellig durchsichtigen.
|
||||
- **Raidzellen brauchen nichts.** Sie haben bereits ihren eigenen Hintergrund mit 80 Prozent Schwarz, dort scheint keine Welt durch; der Regler fasst bewusst nur die Plaketten an.
|
||||
|
||||
**Danke**
|
||||
**Dank**
|
||||
|
||||
- Idee und ein lauffaehiger Patch kamen von einem Nutzer, dem der durchscheinende Balken schlecht lesbar ist. Der Patch benutzte `WHITE8X8` mit `SetVertexColor`; hier ausgeliefert wird `SetTexture(r, g, b, a)`, das in 1.12 direkt eine Vollfarbe erzeugt und genau das ist, was der Manastreifen ohnehin schon macht. Gleiches Ergebnis, ohne Texturdatei.
|
||||
|
||||
|
||||
+76
-7
@@ -44,6 +44,9 @@
|
||||
-- anfliegende Heilung.
|
||||
-- * v1.4.5.3: Einstellbarer Hintergrund hinter den Balken der Plaketten
|
||||
-- (Regler "Balkenhintergrund", Standard 0 = wie bisher durchscheinend).
|
||||
-- * v1.4.6: Leistungsdurchgang ohne Funktionsaenderung: nur geaenderte
|
||||
-- Einheiten werden neu gezeichnet (FBHealBox_RefreshUnitsByName, Hook
|
||||
-- "RefreshNames"), Zaubertimer steigen frueher aus.
|
||||
--
|
||||
-- Ehre wem Ehre gebuehrt: Aufbau, Namensplaketten und Grundidee stammen
|
||||
-- aus dem Original.
|
||||
@@ -159,7 +162,7 @@ HealBox = {
|
||||
-- feuert ADDON_LOADED fuer uns.
|
||||
FBADDON_NAME = "Heal Box Vanilla";
|
||||
FBADDON_FOLDER = "FBHealBox";
|
||||
HealBoxVersion = "|cFFFFFF00v1.4.5.3|r";
|
||||
HealBoxVersion = "|cFFFFFF00v1.4.6|r";
|
||||
|
||||
-- ==========================================================================
|
||||
-- [ Lokalisierung / Localization ]
|
||||
@@ -2968,6 +2971,26 @@ function FBHealBox_RefreshAllBars()
|
||||
FBHealBox_RunHook("RefreshAllBars");
|
||||
end
|
||||
|
||||
-- Nur die Plaketten auffrischen, deren Einheit in der Namensliste steht.
|
||||
--
|
||||
-- Der 0,2-Sekunden-Takt setzte frueher ein einziges Dirty-Flag: Lief
|
||||
-- irgendwo ein HoT-Tick ab, wurde alles neu gezeichnet, im Vierzigerraid
|
||||
-- also vierzig Zellen, obwohl sich bei genau einer Einheit etwas geaendert
|
||||
-- hatte. Jetzt sammelt der Takt die betroffenen Namen ein und nur die werden
|
||||
-- angefasst. Die Schleife selbst bleibt, sie kostet nur einen Tabellen-
|
||||
-- zugriff je Plakette; teuer war immer die Aktualisierung dahinter.
|
||||
function FBHealBox_RefreshUnitsByName(names)
|
||||
if (not FBHealBox1) or (not FBHealBox1.ShieldBar) or (not names) then return; end
|
||||
for p = 1, FBSlotCount do
|
||||
local unit = FBPartyUnit[p];
|
||||
if (FBUnitExists(unit)) then
|
||||
local n = FBUnitName(unit);
|
||||
if (n and names[n]) then FBHealBox_UpdateUnit(unit, FBPartyFrame[p]); end
|
||||
end
|
||||
end
|
||||
FBHealBox_RunHook("RefreshNames", names);
|
||||
end
|
||||
|
||||
-- Ist dieser Slot gerade anzuzeigen? (Begleiter nur mit ShowPets)
|
||||
function FBSlotActive(p)
|
||||
if (p == 1) then return true; end
|
||||
@@ -3321,10 +3344,17 @@ end
|
||||
function FBHealBox_UpdateSpellTimers()
|
||||
local now = GetTime();
|
||||
local on = (HealBox.SpellTimers == 1);
|
||||
-- Laeuft ueberhaupt ein eigener HoT oder Schild? Wenn nicht, gibt es auf
|
||||
-- den Plaketten nichts anzuzeigen, und die Schleife braucht nur noch dort
|
||||
-- hineinzuschauen, wo noch ein Timer wegzuraeumen ist. Spart bei Klassen
|
||||
-- ohne HoT und zwischen den Kaempfen zehn Namensabfragen fuenfmal je
|
||||
-- Sekunde. next() ist wahr, sobald die Tabelle einen Eintrag hat; leere
|
||||
-- Untertabellen raeumt der Takt in FBPredict_OnUpdate weg.
|
||||
local tracked = FBTestMode or (next(FBHoTs) ~= nil) or (next(FBShields) ~= nil);
|
||||
for p = 1, FBSlotCount do
|
||||
local f = FBPartyFrame[p];
|
||||
local unit = FBPartyUnit[p];
|
||||
if (f and FBPartyTable[p]) then
|
||||
if (f and FBPartyTable[p] and (tracked or f.timersShown)) then
|
||||
local shown = on and f:IsShown() and FBUnitExists(unit);
|
||||
local name = shown and FBUnitName(unit);
|
||||
local g = shown and FBTest_Ghost(unit);
|
||||
@@ -6019,6 +6049,8 @@ end);
|
||||
|
||||
FBNamesDirty = false;
|
||||
FBBlizzPartyDirty = false;
|
||||
FBDirtyNames = {}; -- im Takt betroffene Einheitennamen (wiederverwendet)
|
||||
FBFullRefreshAccum = 0; -- Sekunden seit dem letzten vollen Durchlauf
|
||||
FBBtnStatesDirty = nil;
|
||||
FBBuffIconsDirty = true;
|
||||
FBBuffIconsAccum = 0;
|
||||
@@ -6069,39 +6101,60 @@ function FBPredict_OnUpdate(elapsed)
|
||||
|
||||
local now = GetTime();
|
||||
local dirty = false;
|
||||
local full = false;
|
||||
|
||||
for _, spells in pairs(FBHoTs) do
|
||||
-- Betroffene Einheiten einsammeln statt pauschal alles neu zu zeichnen.
|
||||
-- Die Tabelle wird wiederverwendet und nur geleert, damit je Durchlauf
|
||||
-- keine neue entsteht.
|
||||
local names = FBDirtyNames;
|
||||
for k in pairs(names) do names[k] = nil; end
|
||||
|
||||
for uname, spells in pairs(FBHoTs) do
|
||||
local anyLeft = false;
|
||||
for spellName, e in pairs(spells) do
|
||||
if (now >= e.expires) then
|
||||
spells[spellName] = nil;
|
||||
names[uname] = true;
|
||||
dirty = true;
|
||||
else
|
||||
anyLeft = true;
|
||||
local n = FBPredict_TicksLeft(e, now);
|
||||
if (n ~= e.lastTicks) then
|
||||
e.lastTicks = n;
|
||||
names[uname] = true;
|
||||
dirty = true;
|
||||
end
|
||||
end
|
||||
end
|
||||
-- leere Untertabelle wegraeumen: andernorts wird FBHoTs[name] als
|
||||
-- "laeuft da ein HoT?" gelesen, und eine leere Tabelle ist wahr
|
||||
if (not anyLeft) then FBHoTs[uname] = nil; end
|
||||
end
|
||||
|
||||
for name, s in pairs(FBShields) do
|
||||
if (now >= s.expires) then
|
||||
FBShields[name] = nil;
|
||||
names[name] = true;
|
||||
dirty = true;
|
||||
end
|
||||
end
|
||||
|
||||
for _, casters in pairs(FBCommHeals) do
|
||||
for uname, casters in pairs(FBCommHeals) do
|
||||
local anyLeft = false;
|
||||
for caster, info in pairs(casters) do
|
||||
if (now >= info.expires) then
|
||||
casters[caster] = nil;
|
||||
names[uname] = true;
|
||||
dirty = true;
|
||||
else
|
||||
anyLeft = true;
|
||||
end
|
||||
end
|
||||
if (not anyLeft) then FBCommHeals[uname] = nil; end
|
||||
end
|
||||
|
||||
if (FBPredictDirect and now > FBPredictDirect.finish) then
|
||||
if (FBPredictDirect.target) then names[FBPredictDirect.target] = true; end
|
||||
FBPredictDirect = nil;
|
||||
dirty = true;
|
||||
end
|
||||
@@ -6110,10 +6163,26 @@ function FBPredict_OnUpdate(elapsed)
|
||||
FBPredictPending = nil;
|
||||
end
|
||||
|
||||
-- Testmodus: die Geister atmen, im Takt der Vorhersage neu zeichnen
|
||||
if (FBTestMode) then dirty = true; end
|
||||
-- Testmodus: die Geister atmen, da muss alles mit
|
||||
if (FBTestMode) then dirty = true; full = true; end
|
||||
|
||||
if (dirty) then FBHealBox_RefreshAllBars(); end
|
||||
-- Sicherheitsnetz: hoechstens einmal je Sekunde doch der volle Durchlauf,
|
||||
-- falls ein Name einmal zu keiner Plakette passt. Kostet gegenueber
|
||||
-- frueher immer noch nur einen Bruchteil, weil es vorher mehrmals je
|
||||
-- Sekunde passierte.
|
||||
if (dirty) then
|
||||
FBFullRefreshAccum = FBFullRefreshAccum + FBPREDICT_THROTTLE;
|
||||
if (FBFullRefreshAccum >= 1.0) then
|
||||
FBFullRefreshAccum = 0;
|
||||
full = true;
|
||||
end
|
||||
end
|
||||
|
||||
if (full) then
|
||||
FBHealBox_RefreshAllBars();
|
||||
elseif (dirty) then
|
||||
FBHealBox_RefreshUnitsByName(names);
|
||||
end
|
||||
end
|
||||
|
||||
FBPredict_InitPatterns();
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
## Interface: 11200
|
||||
## Title: Heal Box Vanilla |cFFFFFF00v1.4.5.3|r
|
||||
## Title: Heal Box Vanilla |cFFFFFF00v1.4.6|r
|
||||
## Notes: Heal/raid frame addon like Healium, with quick-cast buttons, heal prediction, mana ticker and more.
|
||||
## Notes-deDE: Heal/Raidframe Addon aehnlich Healium, mit Schnellzugriff Buttons, Heal Prediction und Mana Ticker und mehr.
|
||||
## Author: Dourd (Argent Dawn EU) | Vanilla-Port & Erweiterung 09/2026: Mquadrat
|
||||
## Version: 1.4.5.3
|
||||
## Version: 1.4.6
|
||||
## SavedVariablesPerCharacter: HealBox
|
||||
## OptionalDeps: SuperWoW
|
||||
|
||||
|
||||
+32
-13
@@ -1093,21 +1093,24 @@ function FBRaid_UpdateSpellTimers(now)
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c) then
|
||||
-- ohne verfolgten HoT/Schild auf der Einheit nur einmal ausblenden
|
||||
local shown = on and c.unit and c:IsShown() and (c.ghost or FBHoTs[c.name] or FBShields[c.name]);
|
||||
if (not shown and not c.timersShown) then shown = nil; end
|
||||
c.timersShown = shown and true or false;
|
||||
if (shown == nil) then shown = false; end
|
||||
for i = 1, FBRAID_MAX_BUTTONS do
|
||||
local b = c.buttons[i];
|
||||
if (shown and b:IsShown()) then
|
||||
local text, color = FBHealBox_SpellTimerFor(b.spellBase, c.name, now, c.ghost, i);
|
||||
if (not text and b.spellBaseR) then
|
||||
text, color = FBHealBox_SpellTimerFor(b.spellBaseR, c.name, now, nil, i);
|
||||
-- Nichts anzuzeigen und nichts mehr wegzuraeumen: Zelle
|
||||
-- ueberspringen. Vorher lief die Buttonschleife auch dann
|
||||
-- durch, im Vierzigerraid 160 Leeraufrufe fuenfmal je
|
||||
-- Sekunde. Der Kern macht es bei den Plaketten genauso.
|
||||
if (shown or c.timersShown) then
|
||||
c.timersShown = (shown and true) or false;
|
||||
for i = 1, FBRAID_MAX_BUTTONS do
|
||||
local b = c.buttons[i];
|
||||
if (shown and b:IsShown()) then
|
||||
local text, color = FBHealBox_SpellTimerFor(b.spellBase, c.name, now, c.ghost, i);
|
||||
if (not text and b.spellBaseR) then
|
||||
text, color = FBHealBox_SpellTimerFor(b.spellBaseR, c.name, now, nil, i);
|
||||
end
|
||||
FBHealBox_SetButtonTimer(b, text, color);
|
||||
else
|
||||
FBHealBox_SetButtonTimer(b, nil);
|
||||
end
|
||||
FBHealBox_SetButtonTimer(b, text, color);
|
||||
else
|
||||
FBHealBox_SetButtonTimer(b, nil);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1583,6 +1586,22 @@ FBHealBox_RegisterHook("ActiveToggle", function()
|
||||
FBRaid_UpdateVisibility();
|
||||
return true;
|
||||
end);
|
||||
-- Nur die Zellen anfassen, deren Einheit sich geaendert hat. Der Kern
|
||||
-- schickt die Namensliste mit; eine Zelle, die nicht drinsteht, kostet
|
||||
-- einen Tabellenzugriff statt einer vollen Aktualisierung.
|
||||
FBHealBox_RegisterHook("RefreshNames", function(names)
|
||||
if (not FBRaid_IsActive()) or (not names) then return true; end
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c and c.unit and c.name and names[c.name]) then FBRaid_UpdateCell(c); end
|
||||
end
|
||||
end
|
||||
end
|
||||
return true;
|
||||
end);
|
||||
|
||||
FBHealBox_RegisterHook("RefreshAllBars", function()
|
||||
FBRaid_RefreshAll();
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user