Add files via upload

This commit is contained in:
QbiXibQ
2026-09-05 08:20:50 +02:00
committed by GitHub
parent 68d956e838
commit 4149328e01
6 changed files with 1633 additions and 39 deletions
+50
View File
@@ -1,5 +1,55 @@
# Changelog
## 1.4.2 (2026-09-05)
### English
**New: raid mode** (module `FBHealBox_Raid.lua`, on by default, switches in automatically from 11 raid members; *Raid view from N players* is adjustable)
- Compact grid for 20 and 40 player raids: one cell per member in blocks of five per raid group, blocks arranged in rows (*Groups per row*). Empty groups collapse, so a 20-player raid is a single row.
- Each cell: name in class colour, health bar with shield and incoming-heal layers, 3 px mana strip, HP percent or deficit, dispel colouring, dead/ghost/offline text, range fading, line-of-sight eye, buff-watch border.
- Up to four mini buttons per cell, wired to Button 1 to N from the Buttons tab (right-click spells included). Click on a cell targets the unit (or unit menu / move / nothing, as configured for plates).
- Own options tab *Raid mode* with size, spacing, scale, headers, mana strip, HP text mode, title bar, hide-empty-groups and hide-party-plates switches.
- Raid test with 20 or 40 ghosts covering every visual state. `/fbp raid`, `/fbp raidtest 20|40|off`, raid line in `/fbp`.
- Grid position and scale are saved separately from the party plates. Party plates are hidden while the grid is up (switchable).
**New: drag and drop.** Spells can be dragged from the spellbook onto any heal button, raid mini button or options field. Right mouse button fills the right-click side when that option is on. Spells outside the class list are accepted.
**Fixed**
- **Double loading.** The `.xml` included `FBHealBox.lua` a second time on top of the `.toc`. Every frame, hook and the options window existed twice. Visible effects: the raid tab was missing (added to the first, overwritten options window), Escape could crash the client (the second hook called itself), and learned absorb values were doubled (two prediction frames counted every absorb line). The `.xml` no longer loads scripts, and both Lua files refuse to run twice.
- Escape hook stores the original in a local upvalue, is installed at most once, and no longer uses a tail call.
- Learned absorb values above 1.5 times the tooltip are dropped on load; doubled values from earlier versions clean themselves up.
**Changed**
- Core gained a hook interface (`FBHealBox_RegisterHook`, `FBHealBox_AddOptionsTab`) so modules can attach without editing the core. No behaviour change for the party display.
- `.toc` now loads `FBHealBox_Raid.lua` after the core; removing that line disables raid mode entirely.
### Deutsch
**Neu: Raidmodus** (Modul `FBHealBox_Raid.lua`, standardmaessig an, schaltet ab 11 Raidmitgliedern automatisch um; *Raid-Ansicht ab N Spielern* ist einstellbar)
- Kompaktes Raster fuer 20er- und 40er-Raids: eine Zelle je Mitglied in Fuenferbloecken je Gruppe, die Bloecke in Zeilen (*Gruppen je Zeile*). Leere Gruppen fallen weg, ein 20er-Raid ist also eine einzige Zeile.
- Jede Zelle: Name in Klassenfarbe, Lebensbalken mit Schild- und Vorhersage-Schicht, 3 px Manastreifen, HP-Prozent oder Defizit, Dispel-Faerbung, Tot/Geist/Offline, Reichweiten-Fading, Sichtlinien-Auge, Buff-Wache-Rahmen.
- Bis zu vier Mini-Buttons je Zelle, belegt wie Button 1 bis N aus dem Reiter Buttons (Rechtsklick-Zauber inklusive). Klick auf die Zelle visiert an (oder Einheitenmenue / Verschieben / Nichts, wie fuer Plaketten eingestellt).
- Eigener Options-Reiter *Raidmodus* mit Groesse, Abstaenden, Skalierung, Gruppenkoepfen, Manastreifen, HP-Text-Modus, Titelleiste, Leere-Gruppen- und Plaketten-Ausblenden-Schaltern.
- Raid-Test mit 20 oder 40 Geistern, die jeden Anzeigezustand abdecken. `/fbp raid`, `/fbp raidtest 20|40|off`, Raid-Zeile in `/fbp`.
- Position und Skalierung des Rasters werden getrennt von den Plaketten gespeichert. Die Gruppenplaketten sind ausgeblendet, solange das Raster steht (abschaltbar).
**Neu: Drag & Drop.** Zauber lassen sich aus dem Zauberbuch auf jeden Heil-Button, Raid-Mini-Button oder jedes Optionsfeld ziehen. Die rechte Maustaste fuellt die Rechtsklick-Seite, wenn die Option an ist. Zauber ausserhalb der Klassenliste werden angenommen.
**Behoben**
- **Doppeltes Laden.** Die `.xml` band `FBHealBox.lua` zusaetzlich zur `.toc` ein zweites Mal ein. Jeder Frame, jeder Hook und das Optionsfenster existierten doppelt. Sichtbare Folgen: der Raid-Reiter fehlte (an das erste, ueberschriebene Optionsfenster gehaengt), Escape konnte den Client zum Absturz bringen (der zweite Hook rief sich selbst auf), und gelernte Absorb-Werte waren verdoppelt (zwei Vorhersage-Frames zaehlten jede Absorb-Zeile). Die `.xml` laedt keine Skripte mehr, beide Lua-Dateien verweigern einen zweiten Durchlauf.
- Der Escape-Hook haelt das Original in einem lokalen Upvalue, wird hoechstens einmal gesetzt und nutzt keinen Tail-Call mehr.
- Gelernte Absorb-Werte ueber dem 1,5-fachen des Tooltips werden beim Laden verworfen; verdoppelte Werte aus frueheren Versionen bereinigen sich selbst.
**Geaendert**
- Der Kern hat eine Hook-Schnittstelle bekommen (`FBHealBox_RegisterHook`, `FBHealBox_AddOptionsTab`), damit Module andocken koennen, ohne den Kern zu aendern. Kein Verhaltensunterschied fuer die Gruppenanzeige.
- Die `.toc` laedt `FBHealBox_Raid.lua` nach dem Kern; wer die Zeile entfernt, hat keinen Raidmodus.
## 1.4.1 (2026-09-04)
### English
+236 -20
View File
@@ -15,11 +15,19 @@
-- Buff-Wache (oranger Rahmen bei fehlendem Buff), Reichweiten-Fading,
-- Optionsfenster mit Tabs, Rechtsklick-Zweitzauber, Tot/Geist/Offline-
-- Anzeige, Debuff-Icon mit Stackzahl
-- * v1.4.2: Hook-Schnittstelle fuer Module (FBHealBox_RegisterHook,
-- FBHealBox_AddOptionsTab). Der Raidmodus lebt in FBHealBox_Raid.lua.
--
-- Ehre wem Ehre gebuehrt: Aufbau, Namensplaketten und Grundidee stammen
-- aus dem Original.
-- ==========================================================================
-- Schutz gegen doppeltes Laden (z. B. .toc und .xml binden dieselbe Datei
-- ein). Ein zweiter Durchlauf wuerde alle Frames, Hooks und das
-- Optionsfenster erneut anlegen.
if (FBHealBox_CoreLoaded) then return; end
FBHealBox_CoreLoaded = true;
FBHasSuperWoW = (SUPERWOW_VERSION ~= nil);
FBClass = UnitClass("player");
@@ -53,7 +61,7 @@ HealBox = {
-- feuert ADDON_LOADED fuer uns.
FBADDON_NAME = "Heal Box Vanilla";
FBADDON_FOLDER = "FBHealBox";
HealBoxVersion = "|cFFFFFF00v1.4.1|r";
HealBoxVersion = "|cFFFFFF00v1.4.2|r";
-- ==========================================================================
-- [ Lokalisierung / Localization ]
@@ -93,6 +101,9 @@ FBLocale["enUS"] = {
RIGHTCLICK = "Right-click spell",
RIGHTCLICK_TIP = "Gives every button a second spell on right click (e.g. Flash Heal left, Greater Heal right). Off by default. When on, a second column appears above and a small icon in the corner of each button shows the right-click spell.",
TT_RIGHT = "Right click",
DROP_SET = "Button %d: |cFFFFFFFF%s|r (dragged from the spellbook)",
DROP_SET_R = "Button %d, right click: |cFFFFFFFF%s|r (dragged from the spellbook)",
DROP_UNKNOWN = "Could not identify the dragged spell.",
STATE_DEAD = "Dead",
STATE_GHOST = "Ghost",
STATE_OFFLINE = "Offline",
@@ -195,6 +206,9 @@ FBLocale["deDE"] = {
RIGHTCLICK = "Rechtsklick-Zauber",
RIGHTCLICK_TIP = "Gibt jedem Button einen zweiten Zauber per Rechtsklick (z. B. Blitzheilung links, Grosse Heilung rechts). Standardmaessig aus. Eingeschaltet erscheint oben eine zweite Spalte, und ein kleines Icon in der Ecke jedes Buttons zeigt den Rechtsklick-Zauber.",
TT_RIGHT = "Rechtsklick",
DROP_SET = "Button %d: |cFFFFFFFF%s|r (aus dem Zauberbuch gezogen)",
DROP_SET_R = "Button %d, Rechtsklick: |cFFFFFFFF%s|r (aus dem Zauberbuch gezogen)",
DROP_UNKNOWN = "Der gezogene Zauber liess sich nicht erkennen.",
STATE_DEAD = "Tot",
STATE_GHOST = "Geist",
STATE_OFFLINE = "Offline",
@@ -301,6 +315,34 @@ function FBSetLocale(code, apply)
end
FBL = FBLocale[FBDetectLocale()];
-- ==========================================================================
-- [ Hooks fuer Module ]
--
-- Module (z. B. FBHealBox_Raid.lua) haengen sich hier ein, statt den
-- Kern zu aendern. Aufrufpunkte: Defaults, SyncOptions, ApplyLocale,
-- UpdateNames, RefreshAllBars, ButtonsChanged, ActiveToggle, Status, Loaded
-- und Slash (Slash-Hooks geben true zurueck, wenn sie den Befehl verarbeitet
-- haben).
-- ==========================================================================
FBHookRegistry = {};
function FBHealBox_RegisterHook(name, fn)
if (not FBHookRegistry[name]) then FBHookRegistry[name] = {}; end
table.insert(FBHookRegistry[name], fn);
end
function FBHealBox_RunHook(name, a1, a2, a3)
local list = FBHookRegistry[name];
if (not list) then return false; end
local handled = false;
for _, fn in ipairs(list) do
if (fn(a1, a2, a3)) then handled = true; end
end
return handled;
end
LowHP = 0.6;
VeryLowHP = 0.3;
NamePlateWidth = 120;
@@ -663,6 +705,7 @@ function FBHealBox_ApplyDefaults()
if (HealBox.BuffWatchPets == nil) then HealBox.BuffWatchPets = 0; end
if (not FBPlateActionName[HealBox.PlateLeft or ""]) then HealBox.PlateLeft = "target"; end
if (not FBPlateActionName[HealBox.PlateRight or ""]) then HealBox.PlateRight = "target"; end
FBHealBox_RunHook("Defaults");
end
-- Optionsfenster an die gespeicherten Werte angleichen
@@ -685,6 +728,7 @@ function FBHealBox_SyncOptions()
FBHealBox_UpdateBuffWatchLabel();
FBHealBox_UpdatePlateActionLabels();
FBHealBox_ApplyRightClickLayout();
FBHealBox_RunHook("SyncOptions");
end
function FBUnitGUID(unit)
@@ -699,11 +743,22 @@ end
function FBLoadSpellData()
FBPlayerSpells = {};
FBBuffSpells = {};
-- Zauber, die per Drag & Drop belegt wurden, koennen ausserhalb der
-- Klassenliste liegen: ihre Namen aus der gespeicherten Belegung mitnehmen
local extra = {};
for _, tbl in ipairs({ HealBox.SpellChoice or {}, HealBox.SpellChoiceR or {} }) do
for _, cast in pairs(tbl) do
if (type(cast) == "string") then
local base = FBPredict_SplitCast(cast);
if (base) then extra[base] = true; end
end
end
end
local i = 1;
while true do
local spellName, spellRank = GetSpellName(i, BOOKTYPE_SPELL);
if not spellName then break; end
local isHealBoxSpell = false;
local isHealBoxSpell = (extra[spellName] == true);
for _, v in ipairs(Spell.Name) do
if v == spellName then
isHealBoxSpell = true;
@@ -730,6 +785,8 @@ function FBLoadSpellData()
-- Tooltips auswerten: welche dieser Zauber sind HoTs bzw. Absorb-Schilde?
FBPredict_BuildWatch();
-- Doppelt gezaehlte Absorb-Lernwerte (Versionen vor 1.4.2) verwerfen
FBPredict_SanitizeMemory();
if (not HealBox.SpellChoiceR) then HealBox.SpellChoiceR = {}; end
for _, side in ipairs({ "L", "R" }) do
@@ -1236,6 +1293,7 @@ function FBHealBox_OnEvent(event, arg1)
if ((event == "ADDON_LOADED") and (arg1 == FBADDON_FOLDER)) then
FBHealBox_ApplyDefaults();
FBSetLocale(HealBox.Locale, 1);
FBHealBox_RunHook("Loaded"); -- Module melden sich im Chat
FBHealBox_SyncOptions();
HealBoxAttachMode(HealBox.AttachMode);
FBHealBox_ApplyButtonSpacing();
@@ -1540,6 +1598,91 @@ function FBHealBoxCreateFrame(FrameName,ParentFrame,FrameTexture,FrameWidth,Fram
return f;
end
-- ==========================================================================
-- [ Drag & Drop aus dem Zauberbuch ]
--
-- 1.12 kennt kein GetCursorInfo(). Das Zauberbuch ruft beim Ziehen
-- PickupSpell(id, book) auf; ein Vor-Hook merkt sich diese beiden Werte.
-- Loslassen auf einem Heil-Button (OnReceiveDrag oder Klick mit Zauber am
-- Cursor) belegt den Button: Linksklick-Feld, bei aktiviertem Rechtsklick-
-- Zauber und rechter Maustaste das Rechtsklick-Feld. Auch die Felder im
-- Optionsfenster nehmen Zauber an.
-- ==========================================================================
FBDragSpell = nil; -- { id, book } des zuletzt aufgenommenen Zaubers
function FBHealBox_HookSpellPickup()
if (FBHealBox_PickupHooked) then return; end
FBHealBox_PickupHooked = true;
if (PickupSpell) then
local origPickup = PickupSpell;
PickupSpell = function(id, book)
FBDragSpell = { id = id, book = book or BOOKTYPE_SPELL };
origPickup(id, book);
end
end
if (ClearCursor) then
local origClear = ClearCursor;
ClearCursor = function()
FBDragSpell = nil;
origClear();
end
end
end
-- Zauber am Cursor: name, rank, id, book oder nil
function FBHealBox_CursorSpell()
if (not FBDragSpell) then return nil; end
if (CursorHasSpell and not CursorHasSpell()) then
FBDragSpell = nil;
return nil;
end
local name, rank = GetSpellName(FBDragSpell.id, FBDragSpell.book);
if (not name) then return nil; end
return name, rank, FBDragSpell.id, FBDragSpell.book;
end
-- Zauber vom Cursor auf Button btnIndex legen. side = "L" oder "R".
-- true, wenn etwas belegt wurde.
function FBHealBox_DropSpell(btnIndex, side)
if (not btnIndex) then return false; end
local name, rank, id, book = FBHealBox_CursorSpell();
if (not name) then
if (FBDragSpell) then
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00"..FBADDON_NAME..":|r "..FBT("DROP_UNKNOWN"));
end
return false;
end
side = side or "L";
if (side == "R" and HealBox.RightClick ~= 1) then side = "L"; end
-- Zauber in die Rangliste aufnehmen, falls er nicht aus der Klassenliste stammt
if (not FBPlayerSpells[name]) then FBPlayerSpells[name] = {}; end
local known = false;
for _, sd in ipairs(FBPlayerSpells[name]) do
if (sd.rank == rank) then known = true; break; end
end
if (not known) then
table.insert(FBPlayerSpells[name], { rank = rank, id = id, icon = GetSpellTexture(id, book) });
end
local castString = name;
if (rank and rank ~= "") then castString = name.."("..rank..")"; end
local _, _, _, _, savedTable = FBChoiceTables(side);
savedTable[btnIndex] = castString;
FBApplySpellChoice(btnIndex, castString, side);
FBHealBoxButtonsChanged();
local key = "DROP_SET";
if (side == "R") then key = "DROP_SET_R"; end
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00"..FBADDON_NAME..":|r "..format(FBT(key), btnIndex, castString));
FBDragSpell = nil;
if (ClearCursor) then ClearCursor(); end
return true;
end
-- Zauber castString auf das Ziel des Buttons wirken (Links- oder Rechtsklick)
function FBHealBox_CastOn(button, castString)
if (not castString) then return; end
@@ -1643,10 +1786,19 @@ function FBHealBoxCreateButton(FBButtonName, FBParentFrame, xoffset, yoffset, te
button:RegisterForClicks("LeftButtonUp");
button:SetScript("OnClick", function()
-- Zauber am Cursor: belegen statt casten
if (FBDragSpell and button.btnIndex) then
local side = "L";
if (arg1 == "RightButton") then side = "R"; end
if (FBHealBox_DropSpell(button.btnIndex, side)) then return; end
end
local castString = button.spellName;
if (arg1 == "RightButton") then castString = button.spellNameR; end
FBHealBox_CastOn(button, castString);
end);
button:SetScript("OnReceiveDrag", function()
if (button.btnIndex) then FBHealBox_DropSpell(button.btnIndex, "L"); end
end);
button:RegisterEvent("SPELL_UPDATE_USABLE");
button:SetScript("OnEvent", HealBoxButton_OnEvent);
@@ -1677,6 +1829,7 @@ function FBHealBox_RefreshAllBars()
local unit = FBPartyUnit[p];
if (FBUnitExists(unit)) then FBHealBox_UpdateUnit(unit, FBPartyFrame[p]); end
end
FBHealBox_RunHook("RefreshAllBars");
end
-- Ist dieser Slot gerade anzuzeigen? (Begleiter nur mit ShowPets)
@@ -1727,6 +1880,7 @@ function FBUpdateNames()
FBHealBox_CheckRangeAll();
FBHealBox_CheckLOSAll();
FBHealBox_RefreshAllBars();
FBHealBox_RunHook("UpdateNames");
end
-- Name in Klassenfarbe (Spieler) bzw. Pet-Farbe (Begleiter)
@@ -2003,8 +2157,9 @@ function FBHealBox_ApplyLocale()
if (r and not FBDropDownButtonR[i]) then r.text:SetText(FBT("SELECT_SPELL")); end
end
if (panel.tabButtons) then
panel.tabButtons[1].text:SetText(FBT("TAB_BUTTONS"));
panel.tabButtons[2].text:SetText(FBT("TAB_GENERAL"));
for i, btn in ipairs(panel.tabButtons) do
btn.text:SetText(FBT(panel.tabLabelKeys[i] or ""));
end
end
if (panel.colLeft) then
panel.colLeft:SetText(FBT("COL_LEFT"));
@@ -2068,6 +2223,7 @@ function FBHealBox_ApplyLocale()
if (FBLangBtn) then
FBLangBtn.text:SetText(FBT("LANGUAGE") .. ": |cFFFFFFFF" .. FBT("LANG_NAME"));
end
FBHealBox_RunHook("ApplyLocale");
end
-- [ Options-Fenster ] --
@@ -2135,6 +2291,22 @@ function FBHealBox_CreateTabButton(name, parent, x, index)
return t;
end
-- Neuen Reiter anlegen (auch fuer Module). Liefert den Inhalts-Frame, der
-- die Panelgroesse hat; Koordinaten wie im Panel, Inhalt ab FBOPT_CONTENT_Y.
function FBHealBox_AddOptionsTab(labelKey)
if (not panel) or (not panel.tabs) then return nil; end
local i = table.getn(panel.tabs) + 1;
local tab = CreateFrame("Frame", "HealBoxOptionsTab"..i, panel);
tab:SetAllPoints(panel);
tab:Hide();
panel.tabs[i] = tab;
panel.tabLabelKeys[i] = labelKey;
panel.tabButtons[i] = FBHealBox_CreateTabButton("HealBoxOptionsTabButton"..i, panel, 25 + (i - 1) * 116, i);
panel.tabButtons[i].text:SetText(FBT(labelKey));
if (panel.activeTab) then FBHealBox_ShowTab(panel.activeTab); end
return tab;
end
function FBHealBox_ShowTab(index)
if (not panel) or (not panel.tabs) then return; end
FBMenu_CloseAll();
@@ -2196,6 +2368,7 @@ function FBHealBoxCreateAddonOptionFrame()
table.insert(UISpecialFrames, "HealBoxOptionsFrame");
end
FBHealBox_HookEscape();
FBHealBox_HookSpellPickup();
panel.CloseButton = CreateFrame("Button", "HealBoxOptionsFrameClose", panel, "UIPanelCloseButton");
panel.CloseButton:SetPoint("TOPRIGHT", -5, -5);
@@ -2226,15 +2399,9 @@ function FBHealBoxCreateAddonOptionFrame()
-- [ Reiter ] ------------------------------------------------------------
panel.tabs = {};
panel.tabButtons = {};
for i = 1, 2 do
local tab = CreateFrame("Frame", "HealBoxOptionsTab"..i, panel);
tab:SetAllPoints(panel);
tab:Hide();
panel.tabs[i] = tab;
panel.tabButtons[i] = FBHealBox_CreateTabButton("HealBoxOptionsTabButton"..i, panel, 25 + (i - 1) * 116, i);
end
local tabButtons = panel.tabs[1];
local tabGeneral = panel.tabs[2];
panel.tabLabelKeys = {};
local tabButtons = FBHealBox_AddOptionsTab("TAB_BUTTONS");
local tabGeneral = FBHealBox_AddOptionsTab("TAB_GENERAL");
-- Trennlinie unter den Reitern
panel.tabLine = panel:CreateTexture(nil, "ARTWORK");
@@ -2272,17 +2439,21 @@ function FBHealBoxCreateAddonOptionFrame()
btn.label:SetJustifyH("RIGHT");
btn.label:SetText(FBT("BUTTON") .. " " .. i);
btn:SetScript("OnClick", function()
if (FBDragSpell and FBHealBox_DropSpell(btnIndex, "L")) then return; end
PlaySound("igMainMenuOptionCheckBoxOn");
FBMenu_OpenSpellMenu(btnIndex, btn, "L");
end);
btn:SetScript("OnReceiveDrag", function() FBHealBox_DropSpell(btnIndex, "L"); end);
FBSpellBtns[i] = btn;
local btnR = FBHealBox_CreatePickButton("FBHealBoxBtnR"..i, tabButtons, xRight, yPos, fieldW, 28, 20);
btnR.text:SetText(FBT("SELECT_SPELL"));
btnR:SetScript("OnClick", function()
if (FBDragSpell and FBHealBox_DropSpell(btnIndex, "R")) then return; end
PlaySound("igMainMenuOptionCheckBoxOn");
FBMenu_OpenSpellMenu(btnIndex, btnR, "R");
end);
btnR:SetScript("OnReceiveDrag", function() FBHealBox_DropSpell(btnIndex, "R"); end);
btnR:Hide();
FBSpellBtnsR[i] = btnR;
end
@@ -2501,17 +2672,21 @@ end
-- ESC: ToggleGameMenu abfangen, solange das Optionsfenster offen ist.
-- Ist das Spielmenue selbst offen (ESC darueber gedrueckt), bleibt alles
-- beim Original; sonst schliesst ESC zuerst unser Fenster und verpufft.
FBHealBox_OrigToggleGameMenu = nil;
-- Das Original liegt in einem lokalen Upvalue (nie in einer globalen
-- Variablen, die ein zweiter Ladevorgang ueberschreiben koennte), der
-- Hook wird hoechstens einmal gesetzt, und der Aufruf ist bewusst kein
-- Tail-Call (return f()), weil Lua 5.0 im 1.12-Client damit Probleme hat.
function FBHealBox_HookEscape()
if (FBHealBox_OrigToggleGameMenu) or (not ToggleGameMenu) then return; end
FBHealBox_OrigToggleGameMenu = ToggleGameMenu;
if (FBHealBox_EscHooked) or (not ToggleGameMenu) then return; end
FBHealBox_EscHooked = true;
local origToggleGameMenu = ToggleGameMenu;
ToggleGameMenu = function(clicked)
local gameMenuOpen = (GameMenuFrame and GameMenuFrame:IsVisible());
if (panel and panel:IsVisible() and not gameMenuOpen) then
panel:Hide();
return;
end
return FBHealBox_OrigToggleGameMenu(clicked);
origToggleGameMenu(clicked);
end
end
@@ -2561,6 +2736,7 @@ function FBHealBoxButtons()
local name = "FBHealBoxSlot"..p.."Btn"..i;
FBPartyTable[p][i] = FBHealBoxCreateButton(name, anchor, HealBox.ButtonSpacing or 2, 0,
FBDropDownButtonIcon[i], FBDropDownButton[i], unit, FBActiveSpellIDs[i]);
FBPartyTable[p][i].btnIndex = i;
end
prevButton = FBPartyTable[p][i];
end
@@ -2608,6 +2784,7 @@ function FBHealBoxButtonsChanged()
end
end
end
FBHealBox_RunHook("ButtonsChanged");
end
-- Buttons neu verketten: erster Button haengt an der Plakette, jeder weitere
@@ -2711,6 +2888,7 @@ function CreateMiniMapButton()
if (IsShiftKeyDown()) then
HealBox.Active = 1 - HealBox.Active;
if (HealBox.Active == 1) then FBHealBox1:Show(); else FBHealBox1:Hide(); end
FBHealBox_RunHook("ActiveToggle");
else
FBHealBox_ToggleOptions();
end
@@ -3030,6 +3208,31 @@ end
-- [ Lernspeicher (wandert in die SavedVariables) ] --------------------------
FBPREDICT_ABSORB_MAX_FACTOR = 1.5;
-- Unplausible Absorb-Lernwerte verwerfen (etwa doppelt gezaehlte aus
-- aelteren Versionen). Laeuft nach dem Einlesen der Zauber.
function FBPredict_SanitizeMemory()
if (not HealBox) or (not HealBox.PredictMemory) then return; end
local drop = {};
for key, value in pairs(HealBox.PredictMemory) do
local _, _, spell, rank = string.find(key, "^absorb|([^|]+)|(.*)$");
if (spell) then
local bookID = FBPredict_FindBookID(spell, rank);
local info = bookID and FBPredict_GetSpellInfo(bookID, spell);
if (info and info.shield and value > info.shield.amount * FBPREDICT_ABSORB_MAX_FACTOR) then
table.insert(drop, key);
end
end
end
for _, key in ipairs(drop) do
HealBox.PredictMemory[key] = nil;
if (FBPredictDebug) then
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[FBP]|r memory dropped: "..key);
end
end
end
function FBPredict_MemKey(kind, spell, rank)
return kind.."|"..spell.."|"..(rank or "");
end
@@ -3093,11 +3296,17 @@ function FBPredict_StartShield(unitName, spellName, rank, bookID, rankKnown)
local info = FBPredict_GetSpellInfo(bookID, spellName);
if (not info) or (not info.shield) then return false; end
local amount = FBPredict_Remembered("absorb", spellName, rank) or info.shield.amount;
-- Gelernter Wert nur, wenn er plausibel ist (hoechstens das
-- FBPREDICT_ABSORB_MAX_FACTOR-fache des Tooltips); sonst Tooltip.
local amount = FBPredict_Remembered("absorb", spellName, rank);
if (not amount) or (amount > info.shield.amount * FBPREDICT_ABSORB_MAX_FACTOR) then
amount = info.shield.amount;
end
FBShields[unitName] = {
spell = spellName,
rank = rank,
rankKnown = rankKnown,
tooltip = info.shield.amount,
max = amount,
absorbed = 0,
expires = GetTime() + info.shield.duration,
@@ -3427,9 +3636,12 @@ function FBPredict_OnAbsorb(unitName, amount)
s.absorbed = s.absorbed + amount;
if (s.absorbed > s.max) then
-- mehr absorbiert als der Tooltip hergibt (+Heilung) -> anheben
-- mehr absorbiert als der Tooltip hergibt (+Heilung) -> anheben.
-- Dauerhaft gemerkt wird nur ein plausibler Wert: PW:S skaliert in
-- Vanilla mit rund 10 % der Heilkraft, mehr als das
-- FBPREDICT_ABSORB_MAX_FACTOR-fache des Tooltips ist ein Zaehlfehler.
s.max = s.absorbed;
if (s.rankKnown) then
if (s.rankKnown and s.tooltip and s.max <= s.tooltip * FBPREDICT_ABSORB_MAX_FACTOR) then
FBPredict_Remember("absorb", s.spell, s.rank, s.max);
end
end
@@ -3822,6 +4034,9 @@ end
SLASH_FBHEALPREDICT1 = "/fbp";
SlashCmdList["FBHEALPREDICT"] = function(msg)
-- Module zuerst (z. B. /fbp raid)
if (FBHealBox_RunHook("Slash", msg)) then return; end
if (msg == "debug") then
FBPredictDebug = not FBPredictDebug;
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[FBP]|r "..FBT("FBP_DEBUG").." "..tostring(FBPredictDebug));
@@ -3907,6 +4122,7 @@ SlashCmdList["FBHEALPREDICT"] = function(msg)
end
end
end
FBHealBox_RunHook("Status");
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[FBP]|r "..FBT("FBP_COMMANDS"));
end
+5 -4
View File
@@ -1,11 +1,12 @@
## Interface: 11200
## Title: Heal Box Vanilla |cFFFFFF00v1.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. 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. 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.
## Title: Heal Box Vanilla |cFFFFFF00v1.4.2|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. 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. 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.1
## Version: 1.4.2
## SavedVariablesPerCharacter: HealBox
## OptionalDeps: SuperWoW
FBHealBox.lua
FBHealBox_Raid.lua
FBHealBox.xml
+3 -1
View File
@@ -4,7 +4,9 @@
Original: "Heal Box" von Dourd (Argent Dawn EU) - UI Overhauled.
Vanilla-Portierung und Funktionserweiterung 09/2026 von Mquadrat.
-->
<Script file="FBHealBox.lua"/>
<!-- Die Lua-Dateien laedt ausschliesslich die .toc (FBHealBox.lua,
FBHealBox_Raid.lua). Ein <Script file="..."/> hier wuerde den Kern
ein zweites Mal ausfuehren. -->
<Frame name="FBHealBoxEventFrame" parent="UIParent">
<Scripts>
+1227
View File
File diff suppressed because it is too large Load Diff
+112 -14
View File
@@ -1,29 +1,24 @@
# Heal Box Vanilla
ADDON DOCUMENTATION · VERSION 1.4.1 · World of Warcraft CLIENT 1.12.1
ADDON DOCUMENTATION · VERSION 1.4.2 · World of Warcraft CLIENT 1.12.1
Party, pet and self heal display with quick-cast buttons for healers. One name plate with a health bar per group slot, plus one for every pet in the group directly below its owner, and next to it up to ten freely assignable spell buttons. A thin mana bar sits inside the health bar for everyone who actually uses mana. On top of that a complete heal prediction (direct heals, remaining HoT ticks and absorb shields) that corrects itself from the combat log and shares its numbers with other healers in the HealComm format. The interface is available in **English and German**, switchable in the options window.
**The short version:** click the minimap button (or type `/fbp config`) → options window → pick a spell for each button → done. Everything else happens on its own. `/fbp` tells you at any time what the prediction currently believes. **New in 1.4.1:** tick *Test mode* to fill the display with ghost players and arrange everything without a group.
<img width="585" height="441" alt="Screenshot 2026-09-05 003418" src="https://github.com/user-attachments/assets/38d3a8d6-8a41-4bb3-8cba-661341b6a99d" />
<img width="846" height="1104" alt="Screenshot 2026-09-05 003500" src="https://github.com/user-attachments/assets/000ba234-6837-4078-82eb-336b7dc23901" />
<img width="842" height="1106" alt="Screenshot 2026-09-05 003510" src="https://github.com/user-attachments/assets/474fd9c4-ce5b-413d-b179-21219b950bba" />
\---
## Installation
Download zip, unpack into your Addons folder.
The folder under `Interface\\AddOns` is called **`FBHealBox`** and holds four files:
The folder under `Interface\\AddOns` is called **`FBHealBox`** and holds five files:
|File|Contents|
|-|-|
|`FBHealBox.toc`|Metadata, load order, saved variables|
|`FBHealBox.lua`|The entire addon code|
|`FBHealBox.lua`|The core: party and pet display, prediction, HealComm, options|
|`FBHealBox_Raid.lua`|The raid mode module (see [Raid mode](#raid-mode)). Remove it from the `.toc` and the core runs exactly as in 1.4.1|
|`FBHealBox.xml`|Only the event frame that calls `FBHealBox\_OnLoad` and `FBHealBox\_OnEvent`|
|`CHANGELOG.md`|What changed in which version|
@@ -89,6 +84,8 @@ The thresholds for the HP colours are `LowHP` (0.6) and `VeryLowHP` (0.3) near t
Up to ten buttons sit next to each plate, each showing its spell's icon. A **left click** casts that spell on exactly this group member, no matter who you currently have targeted.
**Assigning by drag and drop.** Open the spellbook, drag a spell and drop it on any heal button, on a raid mini button, or on a field in the *Buttons* tab; that button number takes the spell on every plate. With the right-click spell enabled, dropping with the right mouse button fills the right-click side. Spells outside the class list (Dispel Magic, say) are accepted too and keep their icon after a reload. Vanilla has no `GetCursorInfo()`, so the addon remembers what `PickupSpell` last put on the cursor.
**Right-click spell (optional).** Each button can carry a second spell for **right click** (Flash Heal left, Greater Heal right, say), which doubles the density without adding buttons. This is off by default and is enabled only through the switch on the *Buttons* tab. When on, a second column appears in the assignment and a small icon in the bottom-right corner of every button shows its right-click spell; the tooltip lists it as well. Switching it off keeps the assignments, it just stops the buttons from reacting to right click.
**Dead, ghost, offline.** Instead of `0 %` the bar shows *Dead*, *Ghost* or *Offline*, empty and grey, with no mana strip.
@@ -108,6 +105,48 @@ Hovering shows the full spell tooltip plus the line *Heal Box Vanilla Target: `<
\---
## Raid mode
Raid mode is an addon within the addon: it lives in its own file `FBHealBox_Raid.lua`, hooks into the core only through `FBHealBox\_RegisterHook` and `FBHealBox\_AddOptionsTab`, and is on by default. It does nothing until it is needed: the grid appears on its own once you are in a raid with **at least 11 players** (*Raid view from N players*, adjustable from 2 to 40); smaller raids keep the party display, which shows your own subgroup. The *Raid mode* switch is only an emergency off. Everything described above keeps working unchanged.
**Installing the module:** `FBHealBox_Raid.lua` must sit next to `FBHealBox.lua`, the `.toc` must list it (the shipped `.toc` does), and the game client must be **restarted** once. A `/reload` does not pick up files newly added to a `.toc`. When the module is active, the login lines in the chat include *Raid mode module loaded*, and the options window shows a third tab.
### What it shows
Once the raid reaches the threshold, a compact **grid** appears: one **cell** per member, grouped in **blocks of five** by raid group, the blocks arranged in rows. Each cell (70 by 22 px by default) shows the name in class colour, the health bar with the same shield and incoming-heal layers as the party plates, a 3 px mana strip for mana users, the HP percentage or the missing health, dispel colouring, *Dead* / *Ghost* / *Offline* text, range fading, the line-of-sight eye and the orange buff-watch border. To the right of every cell sit up to four **mini buttons** that cast the spells of Button 1 to N from the *Buttons* tab, right-click spells included. A click on the cell itself does what *Left click on plate* / *Right click on plate* says (target by default; the unit menu comes from Blizzard's raid frame).
Group blocks are laid out with *Groups per row* (default 4): a 40-player raid is two rows of four blocks, about 450 by 270 px with two buttons per cell. **Empty groups take no space**, so a 20-player raid is a single row. The whole grid scales independently of the party plates and remembers its position.
While the grid is shown the five party plates are hidden (option *Hide party plates in raid*), so the screen is never filled twice.
### Tab *Raid mode*
|Setting|Effect|
|-|-|
|Raid mode|Master switch (emergency off). On by default|
|Raid view from N players|Threshold for switching from the party display to the grid. Default 11, that is more than 10 players|
|Hide party plates in raid|Hide the party display while the grid is up. On|
|Group headers|Group number above each block. On|
|Mana strip|3 px mana bar in the cell. On|
|Hide empty groups|Groups without members collapse. On|
|Title bar|Thin bar above the grid to drag it by. Without it, Shift + drag any cell. On|
|HP text|none, percent or deficit (missing health as a negative number)|
|Raid test|Fills the grid with 20 or 40 ghosts: dead, offline, ghost, debuffed, out of range, out of sight, missing buff, shield and incoming heal are all represented. Not saved|
|Groups per row|1 to 8. Default 4|
|Raid scale|0.5 to 1.5|
|Cell width / height|50 to 120 px / 14 to 32 px|
|Buttons per unit|0 to 4 mini buttons. Default 2|
|Button size|12 to 28 px|
|Cell spacing / Group spacing|0 to 10 px / 0 to 20 px|
All raid settings live in `HealBox.Raid`. `/fbp raidtest 20`, `/fbp raidtest 40` and `/fbp raidtest off` switch the raid test from the chat line; `/fbp` reports the raid state.
### How it hooks in
The core exposes `FBHealBox\_RegisterHook(name, fn)` and runs the hooks at fixed points: `Defaults`, `SyncOptions`, `ApplyLocale`, `UpdateNames`, `RefreshAllBars`, `ButtonsChanged`, `ActiveToggle`, `Status` and `Slash`. `FBHealBox\_AddOptionsTab(labelKey)` adds a tab to the options window. The raid module registers its roster refresh on `UpdateNames`, its cell refresh on `RefreshAllBars` (so the heal prediction reaches raid cells for free), and its slash commands on `Slash`. Raid units are added to `FBPredictUnits`, which lets HoT and shield confirmation via `UNIT\_AURA` work for `raid1` to `raid40`. Pets are not shown in raid mode.
\---
## Options window
Opened through the **minimap button**:
@@ -280,6 +319,8 @@ On receive, your own messages are filtered by sender name, and since HealComm st
|`/fbp reset`|Discards all learned values and re-reads the tooltips|
|`/fbp test`|Toggles test mode (same as the checkbox)|
|`/fbp config`|Opens or closes the options window (same as the minimap button)|
|`/fbp raid`|Toggles raid mode|
|`/fbp raidtest 20` · `40` · `off`|Raid test with 20 or 40 ghosts, or off|
`/fbp` is the first place to look when something is not displayed: if a spell is not listed there, the tooltip parser did not recognise it; the display is not at fault.
@@ -312,6 +353,7 @@ Everything lives in the `HealBox` table, saved **per character**:
|`WatchBuff`|Spell name of the buff watch, or nil|
|`BuffWatchPets`|1 = buff watch also on pets, 0 = players only (default)|
|`PosX` · `PosY`|Top-left corner of the player plate in screen pixels|
|`Raid`|Sub-table with every raid-mode setting (see [Raid mode](#raid-mode)), including `PosX` / `PosY` of the grid|
|`PredictMemory`|Learned heal values per spell and rank|
Missing keys, for example in an old `HealBox` table from 1.4, are filled in by `FBHealBox\_ApplyDefaults()` on load. Test mode is deliberately **not** saved.
@@ -374,6 +416,7 @@ Every knob is a global at the top of its own section and can be changed without
|`FBHealBox\_DispelType(unit)`|First debuff your class can remove: type, texture, stacks, or nil|
|`FBHealBox\_UpdateDebuffIcon(frame, tex, count)`|Debuff icon and stack count|
|`FBHealBox\_CastOn(button, castString)`|Casts a button's spell (left or right) on its target|
|`FBHealBox\_DropSpell(btnIndex, side)` · `FBHealBox\_CursorSpell()`|Drag and drop from the spellbook|
|`FBHealBox\_ShowTab(n)` · `FBHealBox\_ApplyRightClickLayout()`|Options tabs; show/hide the right-click column|
|`FBHealBox\_PlateMouseDown(f)` · `FBHealBox\_PlateMouseUp(f)` · `FBHealBox\_RunPlateAction(f, action)`|Click and drag on a plate|
|`FBHealBox\_RefreshAllBars()`|Updates all ten|
@@ -483,6 +526,8 @@ The four functions that feed the bars. All of them expect a **player name**, not
**A spell does not appear in the menu.** It is not in your class's spell list (`Spell.Name` near the top of the file), or not learned yet. The list can be extended freely.
**Learned absorb values are capped.** A remembered absorb larger than 1.5 times the tooltip value is treated as a counting error and dropped on load (`FBPredict\_SanitizeMemory`); values from versions before 1.4.2 that were doubled by the old double load clean themselves up this way.
**No prediction for a particular spell.** Run `/fbp`: if the spell is not among the spells read, the tooltip parser did not recognise it. Wording can differ on custom servers; the patterns all sit in `FBPredict\_GetSpellInfo`.
**Combat log corrections do not take.** The patterns are built from the client's global strings (`PERIODICAURAHEALOTHERSELF`, `HEALEDSELFOTHER`, `ABSORB\_TRAILER`) and otherwise fall back to English defaults. `/fbp debug` shows whether corrections arrive.
@@ -520,18 +565,19 @@ Entries that do not exist do no harm: if the spellbook scan does not find them,
* heal prediction for direct heals, remaining HoT ticks and absorb shields, self-correcting from the combat log
* HealComm sync with Puppeteer, pfUI, Luna and others, without any Ace libraries
* English / German localization, switchable in game
* 1.4.2: raid mode as a separate module (`FBHealBox_Raid.lua`) with a compact 20/40 grid, mini buttons, own options tab and raid test; hook interface in the core
* 1.4.1: pet plates, mana bar inside the health bar, adjustable button and row spacing, test mode with ghost players, saved plate position, class colours, buff watch, range fading, tabbed options, right-click spell, dead/ghost/offline text, debuff icon. See CHANGELOG.md.
\---
Heal Box Vanilla v1.4.1 · original by Dourd, UI Overhauled · ported to Vanilla and extended 09/2026 by Mquadrat
Heal Box Vanilla v1.4.2 · original by Dourd, UI Overhauled · ported to Vanilla and extended 09/2026 by Mquadrat
_______________________________________________________________________
GERMAN
# Heal Box Vanilla
ADDON-DOKUMENTATION · VERSION 1.4.1 · CLIENT 1.12.1
ADDON-DOKUMENTATION · VERSION 1.4.2 · CLIENT 1.12.1
Party-, Begleiter- und Selbst-Heilanzeige mit Schnellzugriff-Buttons für Heiler. Für jeden Gruppenplatz eine Namensplakette mit Lebensbalken, dazu eine für jeden Begleiter in der Gruppe direkt unter seinem Besitzer, daneben bis zu zehn frei belegbare Zauber-Buttons. Ein schmaler Manabalken liegt im Lebensbalken, bei allen, die tatsächlich Mana nutzen. Dazu eine vollständige Heilvorhersage (Direktheilung, HoT-Restticks und Absorb-Schilde), die sich über den Combatlog selbst korrigiert und ihre Werte im HealComm-Format mit anderen Heilern teilt. Die Oberfläche gibt es auf **Deutsch und Englisch**, umschaltbar im Optionsfenster.
@@ -541,12 +587,13 @@ Party-, Begleiter- und Selbst-Heilanzeige mit Schnellzugriff-Buttons für Heiler
## Installation
Der Ordner unter `Interface\\AddOns` heißt **`FBHealBox`** und enthält vier Dateien:
Der Ordner unter `Interface\\AddOns` heißt **`FBHealBox`** und enthält fünf Dateien:
|Datei|Inhalt|
|-|-|
|`FBHealBox.toc`|Metadaten, Ladereihenfolge, SavedVariables|
|`FBHealBox.lua`|Der komplette Addon-Code|
|`FBHealBox.lua`|Der Kern: Gruppen- und Begleiteranzeige, Vorhersage, HealComm, Optionen|
|`FBHealBox_Raid.lua`|Das Raidmodus-Modul (siehe [Raidmodus](#raidmodus)). Aus der `.toc` entfernt, läuft der Kern genau wie in 1.4.1|
|`FBHealBox.xml`|Nur der Event-Frame, der `FBHealBox\_OnLoad` und `FBHealBox\_OnEvent` aufruft|
|`CHANGELOG.md`|Was sich in welcher Version geaendert hat|
@@ -612,6 +659,8 @@ Die Schwellwerte für die HP-Farben stehen als `LowHP` (0.6) und `VeryLowHP` (0.
Rechts neben jeder Plakette liegen bis zu zehn Buttons, jeder mit dem Icon seines Zaubers. Ein **Linksklick** wirkt den Zauber auf genau dieses Gruppenmitglied, unabhängig davon, wen du gerade im Ziel hast.
**Belegen per Drag & Drop.** Zauberbuch öffnen, einen Zauber ziehen und auf einen beliebigen Heil-Button, einen Raid-Mini-Button oder ein Feld im Reiter *Buttons* fallen lassen; diese Buttonnummer übernimmt den Zauber auf allen Plaketten. Ist der Rechtsklick-Zauber aktiv, füllt ein Ablegen mit der rechten Maustaste die Rechtsklick-Seite. Auch Zauber außerhalb der Klassenliste (etwa Magie bannen) werden angenommen und behalten ihr Icon über einen Reload. Vanilla hat kein `GetCursorInfo()`, deshalb merkt sich das Addon, was `PickupSpell` zuletzt an den Cursor gehängt hat.
**Rechtsklick-Zauber (optional).** Jeder Button kann einen zweiten Zauber für **Rechtsklick** tragen (etwa Blitzheilung links, Große Heilung rechts), was die Anzeige verdichtet, ohne Buttons hinzuzufügen. Das ist standardmäßig aus und wird ausschließlich über den Schalter im Reiter *Buttons* eingeschaltet. Eingeschaltet erscheint eine zweite Spalte in der Belegung, und ein kleines Icon unten rechts auf jedem Button zeigt seinen Rechtsklick-Zauber; der Tooltip nennt ihn ebenfalls. Ausschalten behält die Belegung, die Buttons reagieren nur nicht mehr auf Rechtsklick.
**Tot, Geist, Offline.** Statt `0 %` zeigt der Balken *Tot*, *Geist* oder *Offline*, leer und grau, ohne Manastreifen.
@@ -631,6 +680,48 @@ Beim Überfahren erscheint der komplette Zaubertooltip plus die Zeile *Heal Box
\---
## Raidmodus
Der Raidmodus ist ein Addon im Addon: Er lebt in der eigenen Datei `FBHealBox_Raid.lua`, hängt sich nur über `FBHealBox\_RegisterHook` und `FBHealBox\_AddOptionsTab` in den Kern ein und ist standardmäßig an. Er tut nichts, bis er gebraucht wird: Das Raster erscheint von selbst, sobald du in einem Schlachtzug mit **mindestens 11 Spielern** bist (*Raid-Ansicht ab N Spielern*, einstellbar von 2 bis 40); kleinere Raids behalten die Gruppenanzeige, die deine eigene Untergruppe zeigt. Der Schalter *Raidmodus* ist nur ein Notaus. Alles oben Beschriebene funktioniert unverändert weiter.
**Modul installieren:** `FBHealBox_Raid.lua` muss neben `FBHealBox.lua` liegen, die `.toc` muss sie auflisten (die mitgelieferte tut das), und der Spielclient muss einmal **neu gestartet** werden. Ein `/reload` übernimmt keine neu in eine `.toc` eingetragenen Dateien. Ist das Modul aktiv, steht beim Login *Raidmodus-Modul geladen* im Chat, und das Optionsfenster zeigt einen dritten Reiter.
### Was er zeigt
Erreicht der Raid die Schwelle, erscheint ein kompaktes **Raster**: eine **Zelle** je Mitglied, in **Fünferblöcken** nach Gruppe geordnet, die Blöcke in Zeilen. Jede Zelle (standardmäßig 70 mal 22 px) zeigt den Namen in Klassenfarbe, den Lebensbalken mit denselben Schild- und Vorhersage-Schichten wie die Plaketten, einen 3 px hohen Manastreifen bei Mana-Nutzern, die Lebensprozente oder die fehlenden Lebenspunkte, die Dispel-Färbung, *Tot* / *Geist* / *Offline*, das Reichweiten-Fading, das Sichtlinien-Auge und den orangen Buff-Wache-Rahmen. Rechts an jeder Zelle sitzen bis zu vier **Mini-Buttons**, die die Zauber von Button 1 bis N aus dem Reiter *Buttons* wirken, Rechtsklick-Zauber inklusive. Ein Klick auf die Zelle selbst tut, was *Linksklick auf Plakette* / *Rechtsklick auf Plakette* vorgibt (Standard Anvisieren; das Einheitenmenü kommt aus Blizzards Raid-Fenster).
Die Gruppenblöcke stehen mit *Gruppen je Zeile* (Standard 4) im Raster: Ein 40er-Raid sind zwei Zeilen zu vier Blöcken, etwa 450 mal 270 px bei zwei Buttons je Zelle. **Leere Gruppen brauchen keinen Platz**, ein 20er-Raid ist also eine einzige Zeile. Das ganze Raster skaliert unabhängig von den Plaketten und merkt sich seine Position.
Solange das Raster zu sehen ist, werden die fünf Gruppenplaketten ausgeblendet (Option *Gruppenplaketten im Raid ausblenden*), damit der Bildschirm nie doppelt belegt ist.
### Reiter *Raidmodus*
|Einstellung|Wirkung|
|-|-|
|Raidmodus|Hauptschalter (Notaus). Standardmäßig an|
|Raid-Ansicht ab N Spielern|Schwelle für den Wechsel von der Gruppenanzeige zum Raster. Standard 11, also mehr als 10 Spieler|
|Gruppenplaketten im Raid ausblenden|Gruppenanzeige verstecken, solange das Raster steht. An|
|Gruppenköpfe|Gruppennummer über jedem Block. An|
|Manastreifen|3 px Manabalken in der Zelle. An|
|Leere Gruppen ausblenden|Gruppen ohne Mitglieder fallen weg. An|
|Titelleiste|Schmale Leiste über dem Raster zum Ziehen. Ohne sie: Shift + eine beliebige Zelle ziehen. An|
|HP-Text|keiner, Prozent oder Defizit (fehlende Lebenspunkte als negative Zahl)|
|Raid-Test|Füllt das Raster mit 20 oder 40 Geistern: tot, offline, Geist, Debuff, außer Reichweite, außer Sicht, fehlender Buff, Schild und eingehende Heilung sind alle vertreten. Wird nicht gespeichert|
|Gruppen je Zeile|1 bis 8. Standard 4|
|Raid-Skalierung|0.5 bis 1.5|
|Zellenbreite / -höhe|50 bis 120 px / 14 bis 32 px|
|Buttons je Einheit|0 bis 4 Mini-Buttons. Standard 2|
|Buttongröße|12 bis 28 px|
|Zellenabstand / Gruppenabstand|0 bis 10 px / 0 bis 20 px|
Alle Raid-Einstellungen liegen in `HealBox.Raid`. `/fbp raidtest 20`, `/fbp raidtest 40` und `/fbp raidtest off` schalten den Raid-Test aus der Chatzeile; `/fbp` meldet den Raid-Zustand.
### Wie er andockt
Der Kern bietet `FBHealBox\_RegisterHook(name, fn)` und ruft die Hooks an festen Stellen: `Defaults`, `SyncOptions`, `ApplyLocale`, `UpdateNames`, `RefreshAllBars`, `ButtonsChanged`, `ActiveToggle`, `Status` und `Slash`. `FBHealBox\_AddOptionsTab(labelKey)` legt einen Reiter im Optionsfenster an. Das Raid-Modul hängt sein Roster-Update an `UpdateNames`, sein Zellen-Update an `RefreshAllBars` (so erreicht die Heilvorhersage die Raid-Zellen ohne Zusatzaufwand) und seine Slash-Befehle an `Slash`. Die Raid-Einheiten werden in `FBPredictUnits` eingetragen, damit die HoT- und Schild-Bestätigung über `UNIT\_AURA` auch für `raid1` bis `raid40` greift. Begleiter werden im Raidmodus nicht angezeigt.
\---
## Optionsfenster
Zu öffnen über den **Minimap-Button**:
@@ -801,6 +892,8 @@ Beim Empfang werden eigene Nachrichten über den Absendernamen gefiltert, und da
|`/fbp reset`|Verwirft alle gelernten Werte und liest die Tooltips neu ein|
|`/fbp test`|Testmodus an/aus (wie der Haken in den Optionen)|
|`/fbp config`|Optionsfenster auf/zu (wie der Minimap-Button)|
|`/fbp raid`|Raidmodus an/aus|
|`/fbp raidtest 20` · `40` · `off`|Raid-Test mit 20 oder 40 Geistern, oder aus|
`/fbp` ist die erste Anlaufstelle, wenn etwas nicht angezeigt wird: Steht ein Zauber dort nicht drin, hat der Tooltip-Parser ihn nicht erkannt und nicht die Anzeige versagt.
@@ -833,6 +926,7 @@ Alles liegt in der Tabelle `HealBox`, gespeichert **pro Charakter**:
|`WatchBuff`|Zaubername der Buff-Wache oder nil|
|`BuffWatchPets`|1 = Buff-Wache auch für Pets, 0 = nur Spieler (Standard)|
|`PosX` · `PosY`|Linke obere Ecke der Spielerplakette in Bildschirmpixeln|
|`Raid`|Untertabelle mit allen Raidmodus-Einstellungen (siehe [Raidmodus](#raidmodus)), einschließlich `PosX` / `PosY` des Rasters|
|`PredictMemory`|Gelernte Heilwerte je Zauber und Rang|
Fehlende Schlüssel, etwa in einer alten `HealBox`-Tabelle aus 1.4, zieht `FBHealBox\_ApplyDefaults()` beim Laden nach. Der Testmodus wird bewusst **nicht** gespeichert.
@@ -892,6 +986,7 @@ Alle Stellschrauben stehen als Globals oben in ihrem jeweiligen Abschnitt und la
|`FBHealBox\_DispelType(unit)`|Erster von der eigenen Klasse entfernbarer Debuff: Typ, Textur, Stacks, sonst nil|
|`FBHealBox\_UpdateDebuffIcon(frame, tex, count)`|Debuff-Icon und Stackzahl|
|`FBHealBox\_CastOn(button, castString)`|Wirkt den Zauber eines Buttons (links oder rechts) auf sein Ziel|
|`FBHealBox\_DropSpell(btnIndex, side)` · `FBHealBox\_CursorSpell()`|Drag & Drop aus dem Zauberbuch|
|`FBHealBox\_ShowTab(n)` · `FBHealBox\_ApplyRightClickLayout()`|Options-Reiter; Rechtsklick-Spalte ein-/ausblenden|
|`FBHealBox\_PlateMouseDown(f)` · `FBHealBox\_PlateMouseUp(f)` · `FBHealBox\_RunPlateAction(f, action)`|Klick und Ziehen auf einer Plakette|
|`FBHealBox\_RefreshAllBars()`|Aktualisiert alle zehn|
@@ -990,6 +1085,8 @@ Die vier Funktionen, die die Balken speisen. Alle erwarten einen **Spielernamen*
**Ein Zauber taucht im Menü nicht auf.** Er steht nicht in der Zauberliste deiner Klasse (`Spell.Name` am Dateianfang) oder ist noch nicht gelernt. Die Liste lässt sich frei erweitern.
**Gelernte Absorb-Werte sind gedeckelt.** Ein gemerkter Absorb über dem 1,5-fachen des Tooltipwerts gilt als Zählfehler und wird beim Laden verworfen (`FBPredict\_SanitizeMemory`); die durch die alte Doppelladung verdoppelten Werte aus Versionen vor 1.4.2 räumen sich so von selbst auf.
**Keine Vorhersage für einen bestimmten Zauber.** `/fbp` aufrufen: Steht der Zauber nicht in der Liste der ausgelesenen Zauber, hat der Tooltip-Parser ihn nicht erkannt. Auf abweichenden Servern können die Formulierungen abweichen; die Muster sitzen gebündelt in `FBPredict\_GetSpellInfo`.
**Combatlog-Korrekturen greifen nicht.** Die Muster werden aus den GlobalStrings des Clients gebaut (`PERIODICAURAHEALOTHERSELF`, `HEALEDSELFOTHER`, `ABSORB\_TRAILER`) und fallen sonst auf englische Vorgaben zurück. `/fbp debug` zeigt, ob Korrekturen ankommen.
@@ -1027,9 +1124,10 @@ Nicht vorhandene Einträge stören nicht: Findet der Zauberbuch-Scan sie nicht,
* Heilvorhersage für Direktheilung, HoT-Restticks und Absorb-Schilde, selbstkorrigierend über den Combatlog
* HealComm-Sync mit Puppeteer, pfUI, Luna und Co., ohne Ace-Bibliotheken
* Lokalisierung Deutsch / Englisch, im laufenden Spiel umschaltbar
* 1.4.2: Raidmodus als eigenes Modul (`FBHealBox_Raid.lua`) mit kompaktem 20/40-Raster, Mini-Buttons, eigenem Options-Reiter und Raid-Test; Hook-Schnittstelle im Kern
* 1.4.1: Begleiter-Plaketten, Manabalken im Lebensbalken, einstellbare Button- und Zeilenabstände, Testmodus mit Geisterspielern, gespeicherte Plattenposition, Klassenfarben, Buff-Wache, Reichweiten-Fading, Optionen in Reitern, Rechtsklick-Zauber, Tot/Geist/Offline-Text, Debuff-Icon. Siehe CHANGELOG.md.
\---
Heal Box Vanilla v1.4.1 · Original von Dourd, UI Overhauled · Vanilla-Portierung und Erweiterung 09/2026 von Mquadrat
Heal Box Vanilla v1.4.2 · Original von Dourd, UI Overhauled · Vanilla-Portierung und Erweiterung 09/2026 von Mquadrat