mirror of
https://github.com/QbiXibQ/FBHealBox.git
synced 2026-10-18 03:10:51 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84f5f548b8 | ||
|
|
c1a559b21e | ||
|
|
d429360d34 | ||
|
|
cbf7040f2a | ||
|
|
c3a9d50181 |
@@ -1,5 +1,54 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.4.7.1 (2026-10-14)
|
||||||
|
|
||||||
|
Fixes from an external review of 1.4.7.
|
||||||
|
|
||||||
|
### English
|
||||||
|
|
||||||
|
**Fixed**
|
||||||
|
|
||||||
|
- **Buff icons:** one icon per buff and its group version (`FBBuffAlternates`), showing the version the unit carries. Before, each version also matched the other's texture, so Fortitude could show twice. Mark and Gift of the Wild share a texture: on yourself the buff name decides, on others your latest own cast.
|
||||||
|
- **Buff icons:** only buffs on one of your buttons get an icon (left side always, right side with the right-click spell on), as documented. `/fbp buffs` shows which ones do.
|
||||||
|
- **Own buff timer:** recasting the group version on yourself resets the timer again.
|
||||||
|
- **Line of sight:** a click during a cast no longer erases the cast's line of sight check; an error at the end of the cast marks the right unit (`FBLOSCast`, `FBLOSClick`). Clicks held by a client spell queue (Nampower) keep their check; an unanswered click no longer claims a later cast from the action bar.
|
||||||
|
- **Smart Healing:** Heal, Greater Heal, Healing Touch and Healing Wave weight +healing by the base cast time before talents (`FBBaseCastTime`). Unlearned ranks got about a seventh too little bonus.
|
||||||
|
- **Smart Healing:** `FBSmartSkip` and `FBRankLearnLevel` also know the German spell names.
|
||||||
|
- **Crit heals:** crit lines close their cast and are still not learned. A following smaller rank is no longer learned as the button's rank.
|
||||||
|
- **Prayer of Healing:** the prediction shows on every group member HealComm gets, not only on the clicked unit. Every line of the cast counts towards learning.
|
||||||
|
- **Smart Damage:** finds Arcane Shot and Flame Shock (tooltip form "causes X damage"). Aimed Shot left the hunter list.
|
||||||
|
- **Smart Damage:** learns from plain hits only; absorbed, blocked and vulnerability-boosted hits are ignored.
|
||||||
|
- **Raid grid:** cells pick up names that load late (`UNIT_NAME_UPDATE`).
|
||||||
|
|
||||||
|
**Good to know**
|
||||||
|
|
||||||
|
- Buffs on none of your buttons no longer get an icon. Put them on a button to see them.
|
||||||
|
- With the matching talents, first casts of unlearned ranks of the four spells above are estimated slightly higher.
|
||||||
|
- Smart Damage keeps its learned values.
|
||||||
|
|
||||||
|
### Deutsch
|
||||||
|
|
||||||
|
**Behoben**
|
||||||
|
|
||||||
|
- **Buff-Icons:** ein Icon je Buff und seiner Gruppenversion (`FBBuffAlternates`), mit der Fassung, die die Einheit traegt. Vorher passte jede Fassung auch auf die Textur der anderen, Seelenstaerke konnte doppelt erscheinen. Mal und Gabe der Wildnis teilen sich eine Textur: bei dir entscheidet der Buffname, bei anderen dein letzter eigener Cast.
|
||||||
|
- **Buff-Icons:** nur Buffs auf einem deiner Buttons bekommen ein Icon (links immer, rechts mit eingeschaltetem Rechtsklick-Zauber), wie beschrieben. `/fbp buffs` zeigt, welche.
|
||||||
|
- **Eigene Buff-Uhr:** ein Neucast der Gruppenversion auf dich stellt die Uhr wieder zurueck.
|
||||||
|
- **Sichtlinie:** ein Klick waehrend eines Casts loescht dessen Sichtlinien-Pruefung nicht mehr; eine Meldung am Castende markiert die richtige Einheit (`FBLOSCast`, `FBLOSClick`). Klicks in der Zauberwarteschlange eines Clientmods (Nampower) behalten ihre Pruefung; ein unbeantworteter Klick uebernimmt keinen spaeteren Cast von der Aktionsleiste mehr.
|
||||||
|
- **Smart Healing:** Heilen, Grosse Heilung, Heilende Beruehrung und Welle der Heilung gewichten +Heilung nach der Basis-Zauberzeit vor Talenten (`FBBaseCastTime`). Ungelernte Raenge bekamen rund ein Siebtel zu wenig Bonus.
|
||||||
|
- **Smart Healing:** `FBSmartSkip` und `FBRankLearnLevel` kennen auch die deutschen Zaubernamen.
|
||||||
|
- **Crit-Heilungen:** Crit-Zeilen schliessen ihren Cast ab und werden weiterhin nicht gelernt. Ein folgender kleinerer Rang wird nicht mehr als Rang des Buttons gelernt.
|
||||||
|
- **Gebet der Heilung:** die Vorhersage erscheint auf jedem Gruppenmitglied, das HealComm bekommt, nicht nur auf der angeklickten Einheit. Jede Zeile des Casts zaehlt zum Lernen.
|
||||||
|
- **Smart Damage:** findet Arkaner Schuss und Flammenschock (Tooltip-Form "causes X damage"). Gezielter Schuss ist aus der Jaegerliste raus.
|
||||||
|
- **Smart Damage:** lernt nur aus normalen Treffern; absorbierte, geblockte und durch Verwundbarkeit verstaerkte Treffer zaehlen nicht.
|
||||||
|
- **Raidraster:** Zellen uebernehmen spaet geladene Namen (`UNIT_NAME_UPDATE`).
|
||||||
|
|
||||||
|
**Gut zu wissen**
|
||||||
|
|
||||||
|
- Buffs auf keinem deiner Buttons bekommen kein Icon mehr. Leg sie auf einen Button, um sie zu sehen.
|
||||||
|
- Mit den passenden Talenten schaetzt das Addon die ersten Casts ungelernter Raenge der vier Zauber oben etwas hoeher.
|
||||||
|
- Smart Damage behaelt seine gelernten Werte.
|
||||||
|
|
||||||
|
|
||||||
## 1.4.7 (2026-10-08)
|
## 1.4.7 (2026-10-08)
|
||||||
|
|
||||||
The complete code review in one version. Fixes first: Weakened Soul finally shows, other healers' HoTs and shields no longer pass as yours, a click only counts for the cast it started, direct heals are learned, the tooltip scanner reads cast time and range where they actually are, Smart Healing leaves group heals and cooldown spells alone, Smart Damage's minimum damage is safe again, plus line of sight, localized clients, the scale slider and drag and drop in the raid grid. Then performance, robustness and clean-up: redraws collected once per frame, mana events only touch the mana strip, no generic globals any more, modules independent of each other, errors reported instead of swallowed.
|
The complete code review in one version. Fixes first: Weakened Soul finally shows, other healers' HoTs and shields no longer pass as yours, a click only counts for the cast it started, direct heals are learned, the tooltip scanner reads cast time and range where they actually are, Smart Healing leaves group heals and cooldown spells alone, Smart Damage's minimum damage is safe again, plus line of sight, localized clients, the scale slider and drag and drop in the raid grid. Then performance, robustness and clean-up: redraws collected once per frame, mana events only touch the mana strip, no generic globals any more, modules independent of each other, errors reported instead of swallowed.
|
||||||
|
|||||||
+514
-102
@@ -8,7 +8,9 @@
|
|||||||
-- * Heilvorhersage fuer Direktheilung, HoT-Restticks und Absorb-Schilde,
|
-- * Heilvorhersage fuer Direktheilung, HoT-Restticks und Absorb-Schilde,
|
||||||
-- selbstkorrigierend ueber den Combatlog
|
-- selbstkorrigierend ueber den Combatlog
|
||||||
-- * HealComm-Sync mit Puppeteer, pfUI, Luna und Co.
|
-- * HealComm-Sync mit Puppeteer, pfUI, Luna und Co.
|
||||||
-- * Lokalisierung Deutsch / Englisch, im Optionsfenster umschaltbar
|
-- * Lokalisierung Deutsch, Englisch, Spanisch, Franzoesisch und
|
||||||
|
-- Italienisch (die drei letzten seit v1.4.3), im Optionsfenster
|
||||||
|
-- umschaltbar
|
||||||
-- * v1.4.1: Begleiter (Pets) als eigene Plaketten, Manabalken im
|
-- * v1.4.1: Begleiter (Pets) als eigene Plaketten, Manabalken im
|
||||||
-- Lebensbalken, frei waehlbare Button- und Zeilenabstaende, Testmodus
|
-- Lebensbalken, frei waehlbare Button- und Zeilenabstaende, Testmodus
|
||||||
-- mit Geisterspielern, gespeicherte Plattenposition, Klassenfarben,
|
-- mit Geisterspielern, gespeicherte Plattenposition, Klassenfarben,
|
||||||
@@ -59,6 +61,11 @@
|
|||||||
-- Reiter Extras, Hooks geschuetzt, HealComm im Schlachtfeld und mit
|
-- Reiter Extras, Hooks geschuetzt, HealComm im Schlachtfeld und mit
|
||||||
-- Grenzen, Merktabellen begrenzt. Aufgeraeumt: toter Code, doppelte
|
-- Grenzen, Merktabellen begrenzt. Aufgeraeumt: toter Code, doppelte
|
||||||
-- Helfer und Vorgaben, veraltete Texte.
|
-- Helfer und Vorgaben, veraltete Texte.
|
||||||
|
-- * v1.4.7.1: Nachlese zum Review. Buff-Icons nur fuer Buffs auf den
|
||||||
|
-- Buttons, Einzel- und Gruppenbuff teilen sich ein Icon; Sichtlinie
|
||||||
|
-- ueberlebt Spamklicks waehrend eines Casts; +Heilung nach der
|
||||||
|
-- Basis-Zauberzeit vor Talenten; Crit-Zeilen schliessen ihren Cast ab;
|
||||||
|
-- Gebet der Heilung zeigt die Vorhersage auf der ganzen Gruppe.
|
||||||
--
|
--
|
||||||
-- Ehre wem Ehre gebuehrt: Aufbau, Namensplaketten und Grundidee stammen
|
-- Ehre wem Ehre gebuehrt: Aufbau, Namensplaketten und Grundidee stammen
|
||||||
-- aus dem Original.
|
-- aus dem Original.
|
||||||
@@ -209,7 +216,7 @@ for k, v in pairs(FBHealBoxDefaults) do HealBox[k] = FBHealBox_CopyDefault(v); e
|
|||||||
-- feuert ADDON_LOADED fuer uns.
|
-- feuert ADDON_LOADED fuer uns.
|
||||||
FBADDON_NAME = "Heal Box Vanilla";
|
FBADDON_NAME = "Heal Box Vanilla";
|
||||||
FBADDON_FOLDER = "FBHealBox";
|
FBADDON_FOLDER = "FBHealBox";
|
||||||
HealBoxVersion = "|cFFFFFF00v1.4.7|r";
|
HealBoxVersion = "|cFFFFFF00v1.4.7.1|r";
|
||||||
|
|
||||||
-- ==========================================================================
|
-- ==========================================================================
|
||||||
-- [ Lokalisierung / Localization ]
|
-- [ Lokalisierung / Localization ]
|
||||||
@@ -277,7 +284,7 @@ FBLocale["enUS"] = {
|
|||||||
AGGRO = "Mark who is attacked",
|
AGGRO = "Mark who is attacked",
|
||||||
AGGRO_TIP = "Red border on the plate or cell of the member your hostile target is currently targeting. Checked five times a second.",
|
AGGRO_TIP = "Red border on the plate or cell of the member your hostile target is currently targeting. Checked five times a second.",
|
||||||
BUFFICONS = "Buff icons left of the bar",
|
BUFFICONS = "Buff icons left of the bar",
|
||||||
BUFFICONS_TIP = "Buffs with a duration that sit on your buttons (Fortitude, Divine Spirit, Fear Ward, ...) appear as small icons on the outer left side of the plate while they are up. As the time runs out, the icon turns black and white and darker from the top down, in 32 small steps: full colour when fresh, top half grey at half time, top three quarters grey at a quarter left. Exact on yourself, counted from your own cast on others; a buff cast by someone else stays fully coloured (time unknown). /fbp buffs shows what is tracked.",
|
BUFFICONS_TIP = "Buffs with a duration that sit on your buttons (Fortitude, Divine Spirit, Fear Ward, ...) appear as small icons on the outer left side of the plate while they are up. A buff and its group version (Fortitude and Prayer of Fortitude, Blessing and Greater Blessing) share one icon. As the time runs out, the icon turns black and white and darker from the top down, in 32 small steps: full colour when fresh, top half grey at half time, top three quarters grey at a quarter left. Exact on yourself, counted from your own cast on others; a buff cast by someone else stays fully coloured (time unknown). /fbp buffs shows what is tracked.",
|
||||||
TIMERS = "HoT and shield timers",
|
TIMERS = "HoT and shield timers",
|
||||||
TIMERS_TIP = "Each button shows the remaining seconds of your own HoT or shield of that spell on that unit: green for HoTs, blue for the shield, red for Weakened Soul after the shield. Buffs with a duration are shown as icons in the health bar instead (see Buff icons).",
|
TIMERS_TIP = "Each button shows the remaining seconds of your own HoT or shield of that spell on that unit: green for HoTs, blue for the shield, red for Weakened Soul after the shield. Buffs with a duration are shown as icons in the health bar instead (see Buff icons).",
|
||||||
DBG_SMARTRANK = "Auto-downrank: %s -> %s (missing %d, expected %d)",
|
DBG_SMARTRANK = "Auto-downrank: %s -> %s (missing %d, expected %d)",
|
||||||
@@ -361,6 +368,7 @@ FBLocale["enUS"] = {
|
|||||||
DBG_CAST = "Cast %s on %s: %d",
|
DBG_CAST = "Cast %s on %s: %d",
|
||||||
DBG_TICK = "Tick corrected: %s = %d",
|
DBG_TICK = "Tick corrected: %s = %d",
|
||||||
DBG_HEAL = "Heal %s = %d (estimate now %d)",
|
DBG_HEAL = "Heal %s = %d (estimate now %d)",
|
||||||
|
DBG_HEAL_CRIT = "Heal %s = %d critical, not learned",
|
||||||
DBG_ABSORB = "Absorb %d on %s (%d left)",
|
DBG_ABSORB = "Absorb %d on %s (%d left)",
|
||||||
DBG_SMART_HOT = "Smart Healing skipped: %s is a heal over time",
|
DBG_SMART_HOT = "Smart Healing skipped: %s is a heal over time",
|
||||||
DBG_SMART_SKIP = "Smart Healing skipped: %s is a group heal or has a cooldown",
|
DBG_SMART_SKIP = "Smart Healing skipped: %s is a group heal or has a cooldown",
|
||||||
@@ -435,7 +443,7 @@ FBLocale["deDE"] = {
|
|||||||
AGGRO = "Angegriffenen markieren",
|
AGGRO = "Angegriffenen markieren",
|
||||||
AGGRO_TIP = "Roter Rahmen auf der Plakette oder Zelle des Mitglieds, das dein feindliches Ziel gerade im Ziel hat. Fuenfmal je Sekunde geprueft.",
|
AGGRO_TIP = "Roter Rahmen auf der Plakette oder Zelle des Mitglieds, das dein feindliches Ziel gerade im Ziel hat. Fuenfmal je Sekunde geprueft.",
|
||||||
BUFFICONS = "Buff-Icons links am Balken",
|
BUFFICONS = "Buff-Icons links am Balken",
|
||||||
BUFFICONS_TIP = "Buffs mit Laufzeit, die auf deinen Buttons liegen (Seelenstaerke, Goettlicher Willen, Furchtzauberschutz, ...), erscheinen als kleine Icons aussen links neben der Plakette, solange sie wirken. Mit ablaufender Zeit wird das Icon in 32 kleinen Stufen von oben nach unten schwarzweiss und dunkler: frisch ganz farbig, bei halber Zeit die obere Haelfte grau, bei einem Viertel Rest die oberen drei Viertel grau. Exakt bei dir selbst, ab deinem eigenen Cast bei anderen; ein fremd gewirkter Buff bleibt ganz farbig (Zeit unbekannt). /fbp buffs zeigt, was verfolgt wird.",
|
BUFFICONS_TIP = "Buffs mit Laufzeit, die auf deinen Buttons liegen (Seelenstaerke, Goettlicher Willen, Furchtzauberschutz, ...), erscheinen als kleine Icons aussen links neben der Plakette, solange sie wirken. Ein Buff und seine Gruppenversion (Seelenstaerke und Gebet der Seelenstaerke, Segen und Grosser Segen) teilen sich ein Icon. Mit ablaufender Zeit wird das Icon in 32 kleinen Stufen von oben nach unten schwarzweiss und dunkler: frisch ganz farbig, bei halber Zeit die obere Haelfte grau, bei einem Viertel Rest die oberen drei Viertel grau. Exakt bei dir selbst, ab deinem eigenen Cast bei anderen; ein fremd gewirkter Buff bleibt ganz farbig (Zeit unbekannt). /fbp buffs zeigt, was verfolgt wird.",
|
||||||
TIMERS = "HoT- und Schild-Timer",
|
TIMERS = "HoT- und Schild-Timer",
|
||||||
TIMERS_TIP = "Jeder Button zeigt die Restsekunden deines eigenen HoTs oder Schilds dieses Zaubers auf dieser Einheit: gruen fuer HoTs, blau fuer den Schild, rot fuer Geschwaechte Seele nach dem Schild. Buffs mit Laufzeit erscheinen stattdessen als Icons im Lebensbalken (siehe Buff-Icons).",
|
TIMERS_TIP = "Jeder Button zeigt die Restsekunden deines eigenen HoTs oder Schilds dieses Zaubers auf dieser Einheit: gruen fuer HoTs, blau fuer den Schild, rot fuer Geschwaechte Seele nach dem Schild. Buffs mit Laufzeit erscheinen stattdessen als Icons im Lebensbalken (siehe Buff-Icons).",
|
||||||
DBG_SMARTRANK = "Abrangen: %s -> %s (fehlend %d, erwartet %d)",
|
DBG_SMARTRANK = "Abrangen: %s -> %s (fehlend %d, erwartet %d)",
|
||||||
@@ -519,6 +527,7 @@ FBLocale["deDE"] = {
|
|||||||
DBG_CAST = "Cast %s auf %s: %d",
|
DBG_CAST = "Cast %s auf %s: %d",
|
||||||
DBG_TICK = "Tick korrigiert: %s = %d",
|
DBG_TICK = "Tick korrigiert: %s = %d",
|
||||||
DBG_HEAL = "Heilung %s = %d (Schaetzung jetzt %d)",
|
DBG_HEAL = "Heilung %s = %d (Schaetzung jetzt %d)",
|
||||||
|
DBG_HEAL_CRIT = "Heilung %s = %d kritisch, nicht gelernt",
|
||||||
DBG_ABSORB = "Absorb %d auf %s (Rest %d)",
|
DBG_ABSORB = "Absorb %d auf %s (Rest %d)",
|
||||||
DBG_SMART_HOT = "Smart Healing uebersprungen: %s ist Heilung ueber Zeit",
|
DBG_SMART_HOT = "Smart Healing uebersprungen: %s ist Heilung ueber Zeit",
|
||||||
DBG_SMART_SKIP = "Smart Healing uebersprungen: %s ist eine Gruppenheilung oder hat eine Abklingzeit",
|
DBG_SMART_SKIP = "Smart Healing uebersprungen: %s ist eine Gruppenheilung oder hat eine Abklingzeit",
|
||||||
@@ -618,7 +627,7 @@ FBLocale["esES"] = {
|
|||||||
AGGRO = "Marcar al atacado",
|
AGGRO = "Marcar al atacado",
|
||||||
AGGRO_TIP = "Borde rojo en la placa o celda del miembro al que tu objetivo hostil está apuntando. Se comprueba cinco veces por segundo.",
|
AGGRO_TIP = "Borde rojo en la placa o celda del miembro al que tu objetivo hostil está apuntando. Se comprueba cinco veces por segundo.",
|
||||||
BUFFICONS = "Iconos de beneficios (izq.)",
|
BUFFICONS = "Iconos de beneficios (izq.)",
|
||||||
BUFFICONS_TIP = "Los beneficios con duración que están en tus botones (Entereza, Espíritu divino, Custodia contra el miedo, ...) aparecen como pequeños iconos en el lado exterior izquierdo de la placa mientras están activos. A medida que se agota el tiempo, el icono se vuelve blanco y negro y más oscuro de arriba abajo, en 32 pequeños pasos: todo en color al principio, mitad superior gris a mitad de tiempo, tres cuartos superiores grises cuando queda un cuarto. Exacto en ti mismo, contado desde tu propio lanzamiento en los demás; un beneficio lanzado por otro se queda en color (tiempo desconocido). /fbp buffs muestra qué se sigue.",
|
BUFFICONS_TIP = "Los beneficios con duración que están en tus botones (Entereza, Espíritu divino, Custodia contra el miedo, ...) aparecen como pequeños iconos en el lado exterior izquierdo de la placa mientras están activos. Un beneficio y su versión de grupo (Entereza y Rezo de entereza, Bendición y Bendición superior) comparten un icono. A medida que se agota el tiempo, el icono se vuelve blanco y negro y más oscuro de arriba abajo, en 32 pequeños pasos: todo en color al principio, mitad superior gris a mitad de tiempo, tres cuartos superiores grises cuando queda un cuarto. Exacto en ti mismo, contado desde tu propio lanzamiento en los demás; un beneficio lanzado por otro se queda en color (tiempo desconocido). /fbp buffs muestra qué se sigue.",
|
||||||
TIMERS = "Temporizadores HoT y escudo",
|
TIMERS = "Temporizadores HoT y escudo",
|
||||||
TIMERS_TIP = "Cada botón muestra los segundos restantes de tu propio HoT o escudo de ese hechizo en esa unidad: verde para HoT, azul para el escudo, rojo para Alma debilitada tras el escudo. Los beneficios con duración se muestran como iconos en la barra de vida (ver Iconos de beneficios).",
|
TIMERS_TIP = "Cada botón muestra los segundos restantes de tu propio HoT o escudo de ese hechizo en esa unidad: verde para HoT, azul para el escudo, rojo para Alma debilitada tras el escudo. Los beneficios con duración se muestran como iconos en la barra de vida (ver Iconos de beneficios).",
|
||||||
DBG_SMARTRANK = "Reducción de rango: %s -> %s (faltan %d, esperado %d)",
|
DBG_SMARTRANK = "Reducción de rango: %s -> %s (faltan %d, esperado %d)",
|
||||||
@@ -696,6 +705,7 @@ FBLocale["esES"] = {
|
|||||||
DBG_CAST = "Lanzamiento %s sobre %s: %d",
|
DBG_CAST = "Lanzamiento %s sobre %s: %d",
|
||||||
DBG_TICK = "Pulso corregido: %s = %d",
|
DBG_TICK = "Pulso corregido: %s = %d",
|
||||||
DBG_HEAL = "Curación %s = %d (estimación ahora %d)",
|
DBG_HEAL = "Curación %s = %d (estimación ahora %d)",
|
||||||
|
DBG_HEAL_CRIT = "Curación %s = %d crítica, no se aprende",
|
||||||
DBG_ABSORB = "Absorción %d en %s (quedan %d)",
|
DBG_ABSORB = "Absorción %d en %s (quedan %d)",
|
||||||
DBG_SMART_HOT = "Smart Healing omitido: %s es curación con el tiempo",
|
DBG_SMART_HOT = "Smart Healing omitido: %s es curación con el tiempo",
|
||||||
DBG_SMART_SKIP = "Smart Healing omitido: %s es una curación de grupo o tiene reutilización",
|
DBG_SMART_SKIP = "Smart Healing omitido: %s es una curación de grupo o tiene reutilización",
|
||||||
@@ -767,7 +777,7 @@ FBLocale["frFR"] = {
|
|||||||
AGGRO = "Marquer la cible attaquée",
|
AGGRO = "Marquer la cible attaquée",
|
||||||
AGGRO_TIP = "Bordure rouge sur la plaque ou la cellule du membre que votre cible hostile vise actuellement. Vérifié cinq fois par seconde.",
|
AGGRO_TIP = "Bordure rouge sur la plaque ou la cellule du membre que votre cible hostile vise actuellement. Vérifié cinq fois par seconde.",
|
||||||
BUFFICONS = "Icônes de buffs (gauche)",
|
BUFFICONS = "Icônes de buffs (gauche)",
|
||||||
BUFFICONS_TIP = "Les buffs à durée présents sur vos boutons (Robustesse, Esprit divin, Gardien de peur, ...) apparaissent sous forme de petites icônes sur le côté extérieur gauche de la plaque tant qu'ils sont actifs. Au fur et à mesure que le temps s'écoule, l'icône passe en noir et blanc et s'assombrit de haut en bas, en 32 petites étapes : entièrement en couleur au début, moitié supérieure grise à mi-temps, trois quarts supérieurs gris quand il reste un quart. Exact sur vous-même, compté depuis votre propre lancement sur les autres ; un buff lancé par quelqu'un d'autre reste en couleur (temps inconnu). /fbp buffs montre ce qui est suivi.",
|
BUFFICONS_TIP = "Les buffs à durée présents sur vos boutons (Robustesse, Esprit divin, Gardien de peur, ...) apparaissent sous forme de petites icônes sur le côté extérieur gauche de la plaque tant qu'ils sont actifs. Un buff et sa version de groupe (Robustesse et Prière de robustesse, Bénédiction et Bénédiction supérieure) partagent une icône. Au fur et à mesure que le temps s'écoule, l'icône passe en noir et blanc et s'assombrit de haut en bas, en 32 petites étapes : entièrement en couleur au début, moitié supérieure grise à mi-temps, trois quarts supérieurs gris quand il reste un quart. Exact sur vous-même, compté depuis votre propre lancement sur les autres ; un buff lancé par quelqu'un d'autre reste en couleur (temps inconnu). /fbp buffs montre ce qui est suivi.",
|
||||||
TIMERS = "Minuteurs HoT et bouclier",
|
TIMERS = "Minuteurs HoT et bouclier",
|
||||||
TIMERS_TIP = "Chaque bouton affiche les secondes restantes de votre propre HoT ou bouclier de ce sort sur cette unité : vert pour les HoT, bleu pour le bouclier, rouge pour Âme affaiblie après le bouclier. Les buffs à durée sont affichés sous forme d'icônes dans la barre de vie (voir Icônes de buffs).",
|
TIMERS_TIP = "Chaque bouton affiche les secondes restantes de votre propre HoT ou bouclier de ce sort sur cette unité : vert pour les HoT, bleu pour le bouclier, rouge pour Âme affaiblie après le bouclier. Les buffs à durée sont affichés sous forme d'icônes dans la barre de vie (voir Icônes de buffs).",
|
||||||
DBG_SMARTRANK = "Rang abaissé : %s -> %s (manque %d, attendu %d)",
|
DBG_SMARTRANK = "Rang abaissé : %s -> %s (manque %d, attendu %d)",
|
||||||
@@ -845,6 +855,7 @@ FBLocale["frFR"] = {
|
|||||||
DBG_CAST = "Lancement %s sur %s : %d",
|
DBG_CAST = "Lancement %s sur %s : %d",
|
||||||
DBG_TICK = "Tick corrigé : %s = %d",
|
DBG_TICK = "Tick corrigé : %s = %d",
|
||||||
DBG_HEAL = "Soin %s = %d (estimation maintenant %d)",
|
DBG_HEAL = "Soin %s = %d (estimation maintenant %d)",
|
||||||
|
DBG_HEAL_CRIT = "Soin %s = %d critique, non appris",
|
||||||
DBG_ABSORB = "Absorption %d sur %s (reste %d)",
|
DBG_ABSORB = "Absorption %d sur %s (reste %d)",
|
||||||
DBG_SMART_HOT = "Smart Healing ignoré : %s est un soin sur la durée",
|
DBG_SMART_HOT = "Smart Healing ignoré : %s est un soin sur la durée",
|
||||||
DBG_SMART_SKIP = "Smart Healing ignoré : %s est un soin de groupe ou a un temps de recharge",
|
DBG_SMART_SKIP = "Smart Healing ignoré : %s est un soin de groupe ou a un temps de recharge",
|
||||||
@@ -916,7 +927,7 @@ FBLocale["itIT"] = {
|
|||||||
AGGRO = "Segnala chi è attaccato",
|
AGGRO = "Segnala chi è attaccato",
|
||||||
AGGRO_TIP = "Bordo rosso sulla targhetta o sulla cella del membro che il tuo bersaglio ostile sta puntando. Controllato cinque volte al secondo.",
|
AGGRO_TIP = "Bordo rosso sulla targhetta o sulla cella del membro che il tuo bersaglio ostile sta puntando. Controllato cinque volte al secondo.",
|
||||||
BUFFICONS = "Icone benefici (sinistra)",
|
BUFFICONS = "Icone benefici (sinistra)",
|
||||||
BUFFICONS_TIP = "I benefici con durata presenti sui tuoi pulsanti (Tempra, Spirito Divino, Protezione dalla Paura, ...) compaiono come piccole icone sul lato esterno sinistro della targhetta finché sono attivi. Man mano che il tempo scorre, l'icona diventa in bianco e nero e più scura dall'alto verso il basso, in 32 piccoli passi: tutta a colori all'inizio, metà superiore grigia a metà tempo, i tre quarti superiori grigi quando ne resta un quarto. Esatta su te stesso, contata dal tuo lancio sugli altri; un beneficio lanciato da altri resta a colori (tempo sconosciuto). /fbp buffs mostra cosa viene seguito.",
|
BUFFICONS_TIP = "I benefici con durata presenti sui tuoi pulsanti (Tempra, Spirito Divino, Protezione dalla Paura, ...) compaiono come piccole icone sul lato esterno sinistro della targhetta finché sono attivi. Un beneficio e la sua versione di gruppo (Tempra e Preghiera della Tempra, Benedizione e Benedizione Superiore) condividono un'icona. Man mano che il tempo scorre, l'icona diventa in bianco e nero e più scura dall'alto verso il basso, in 32 piccoli passi: tutta a colori all'inizio, metà superiore grigia a metà tempo, i tre quarti superiori grigi quando ne resta un quarto. Esatta su te stesso, contata dal tuo lancio sugli altri; un beneficio lanciato da altri resta a colori (tempo sconosciuto). /fbp buffs mostra cosa viene seguito.",
|
||||||
TIMERS = "Timer HoT e scudo",
|
TIMERS = "Timer HoT e scudo",
|
||||||
TIMERS_TIP = "Ogni pulsante mostra i secondi rimanenti del tuo HoT o scudo di quell'incantesimo su quell'unità: verde per gli HoT, blu per lo scudo, rosso per Anima Indebolita dopo lo scudo. I benefici con durata vengono mostrati come icone nella barra della salute (vedi Icone dei benefici).",
|
TIMERS_TIP = "Ogni pulsante mostra i secondi rimanenti del tuo HoT o scudo di quell'incantesimo su quell'unità: verde per gli HoT, blu per lo scudo, rosso per Anima Indebolita dopo lo scudo. I benefici con durata vengono mostrati come icone nella barra della salute (vedi Icone dei benefici).",
|
||||||
DBG_SMARTRANK = "Rango ridotto: %s -> %s (mancano %d, previsti %d)",
|
DBG_SMARTRANK = "Rango ridotto: %s -> %s (mancano %d, previsti %d)",
|
||||||
@@ -994,6 +1005,7 @@ FBLocale["itIT"] = {
|
|||||||
DBG_CAST = "Lancio %s su %s: %d",
|
DBG_CAST = "Lancio %s su %s: %d",
|
||||||
DBG_TICK = "Tick corretto: %s = %d",
|
DBG_TICK = "Tick corretto: %s = %d",
|
||||||
DBG_HEAL = "Cura %s = %d (stima ora %d)",
|
DBG_HEAL = "Cura %s = %d (stima ora %d)",
|
||||||
|
DBG_HEAL_CRIT = "Cura %s = %d critica, non appresa",
|
||||||
DBG_ABSORB = "Assorbimento %d su %s (restano %d)",
|
DBG_ABSORB = "Assorbimento %d su %s (restano %d)",
|
||||||
DBG_SMART_HOT = "Smart Healing saltato: %s è una cura nel tempo",
|
DBG_SMART_HOT = "Smart Healing saltato: %s è una cura nel tempo",
|
||||||
DBG_SMART_SKIP = "Smart Healing saltato: %s è una cura di gruppo o ha un tempo di recupero",
|
DBG_SMART_SKIP = "Smart Healing saltato: %s è una cura di gruppo o ha un tempo di recupero",
|
||||||
@@ -2879,10 +2891,15 @@ end
|
|||||||
-- verbraucht ein kleiner Rang die volle Abklingzeit. Zauber mit Abklingzeit
|
-- verbraucht ein kleiner Rang die volle Abklingzeit. Zauber mit Abklingzeit
|
||||||
-- erkennt FBHealBox_SmartSkipped zusaetzlich am Tooltip; die Liste deckt die
|
-- erkennt FBHealBox_SmartSkipped zusaetzlich am Tooltip; die Liste deckt die
|
||||||
-- bekannten Faelle ab, auch wenn ein Tooltip keine Abklingzeit nennt.
|
-- bekannten Faelle ab, auch wenn ein Tooltip keine Abklingzeit nennt.
|
||||||
|
-- Die deutschen Namen stehen dabei wie in FBHoTSpells und FBHealChains. Sie
|
||||||
|
-- greifen erst, wenn auch der Tooltip gelesen werden kann; der Leser kennt
|
||||||
|
-- bisher nur englische Tooltips (siehe README, Fehlersuche).
|
||||||
FBSmartSkip = {
|
FBSmartSkip = {
|
||||||
["Prayer of Healing"] = true, ["Chain Heal"] = true, ["Binding Heal"] = true,
|
["Prayer of Healing"] = true, ["Chain Heal"] = true, ["Binding Heal"] = true,
|
||||||
["Circle of Healing"] = true, ["Prayer of Mending"] = true, ["Holy Nova"] = true,
|
["Circle of Healing"] = true, ["Prayer of Mending"] = true, ["Holy Nova"] = true,
|
||||||
["Holy Shock"] = true, ["Lay on Hands"] = true,
|
["Holy Shock"] = true, ["Lay on Hands"] = true,
|
||||||
|
["Gebet der Heilung"] = true, ["Kettenheilung"] = true, ["Heilige Nova"] = true,
|
||||||
|
["Heiliger Schock"] = true, ["Handauflegung"] = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
-- Laesst Smart Healing diesen Zauber in Ruhe?
|
-- Laesst Smart Healing diesen Zauber in Ruhe?
|
||||||
@@ -3409,6 +3426,17 @@ function FBHealBox_BuffName(unit, index)
|
|||||||
return nil;
|
return nil;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Name eines eigenen Buffs ueber den Scan-Tooltip (id aus GetPlayerBuff)
|
||||||
|
function FBHealBox_PlayerBuffName(id)
|
||||||
|
if (not FBPredictTip) or (not FBPredictTip.SetPlayerBuff) then return nil; end
|
||||||
|
FBPredictTip:SetOwner(UIParent, "ANCHOR_NONE");
|
||||||
|
FBPredictTip:ClearLines();
|
||||||
|
FBPredictTip:SetPlayerBuff(id);
|
||||||
|
local fs = getglobal("FBHealBoxScanTipTextLeft1");
|
||||||
|
if (fs) then return fs:GetText(); end
|
||||||
|
return nil;
|
||||||
|
end
|
||||||
|
|
||||||
-- true, wenn die Einheit den ueberwachten Buff (oder die Gruppenversion) traegt
|
-- true, wenn die Einheit den ueberwachten Buff (oder die Gruppenversion) traegt
|
||||||
function FBHealBox_HasWatchBuff(unit)
|
function FBHealBox_HasWatchBuff(unit)
|
||||||
local want = HealBox.WatchBuff;
|
local want = HealBox.WatchBuff;
|
||||||
@@ -3662,17 +3690,28 @@ end
|
|||||||
|
|
||||||
FBLOSFlags = {}; -- [Name] = Ablaufzeit der Markierung (Fallback-Weg)
|
FBLOSFlags = {}; -- [Name] = Ablaufzeit der Markierung (Fallback-Weg)
|
||||||
|
|
||||||
-- Kandidat fuer eine Sichtlinien-Meldung: das Ziel des letzten Klicks auf
|
-- Kandidaten fuer eine Sichtlinien-Meldung. Die Sicht prueft der Server beim
|
||||||
-- einen Button, bis dessen Cast entschieden ist. Die Sicht prueft der Server
|
-- Start eines Casts und noch einmal an seinem Ende. Deshalb zwei Plaetze:
|
||||||
-- beim Start und noch einmal am Ende eines Casts; laeuft der geklickte Zauber
|
--
|
||||||
-- an, gilt das Ziel deshalb bis Castende plus Spielraum. Abgeraeumt wird es,
|
-- FBLOSClick: das Ziel des letzten Klicks auf einen Button, bis der Server
|
||||||
-- sobald der Cast durchgeht (SPELLCAST_STOP), unterbrochen wird, ein anderer
|
-- ihn beantwortet hat { name, spell, t, untilT }. Laeuft der geklickte
|
||||||
-- Zauber anlaeuft oder eine andere Fehlermeldung den Klick beantwortet. Eine
|
-- Zauber mit Zauberzeit an, wandert das Ziel nach FBLOSCast. Ein
|
||||||
-- spaetere Meldung (etwa nach einem Angriffszauber von der Aktionsleiste)
|
-- Sofortzauber, der durchgeht (SPELLCAST_STOP), ein anderer Zauber, der
|
||||||
-- gehoert dann nicht mehr zu diesem Ziel.
|
-- anlaeuft, oder eine Fehlermeldung, die den Klick beantwortet, raeumt ihn
|
||||||
FBLOSCandidate = nil;
|
-- ab. Das Ende eines laufenden Casts nicht: Ein Klick ohne Antwort waehrend
|
||||||
FBLOSCandidateSpell = nil;
|
-- des Casts ist vorgemerkt und geht erst danach hinaus (FBLOS_CastDone).
|
||||||
FBLOSCandidateUntil = 0;
|
-- FBLOSCast: das Ziel des laufenden Zaubers mit Zauberzeit bis Castende plus
|
||||||
|
-- Spielraum { name, endT, untilT, seq }. Ein weiterer Klick waehrend des
|
||||||
|
-- Casts legt nur einen neuen FBLOSClick an, und seine Antwort ("Another
|
||||||
|
-- action is in progress") laesst den laufenden Cast in Ruhe. Bis 1.4.7 gab
|
||||||
|
-- es nur einen Platz: Ein Spamklick ueberschrieb das Ziel, seine
|
||||||
|
-- Fehlermeldung loeschte es, und die Sichtlinien-Meldung am Castende ging
|
||||||
|
-- verloren.
|
||||||
|
--
|
||||||
|
-- Eine spaetere Meldung (etwa nach einem Angriffszauber von der Aktionsleiste)
|
||||||
|
-- gehoert zu keinem der beiden und markiert niemanden.
|
||||||
|
FBLOSClick = nil;
|
||||||
|
FBLOSCast = nil;
|
||||||
FBLOS_ERROR_WINDOW = 1.0; -- Sek. Spielraum fuer die Antwort des Servers
|
FBLOS_ERROR_WINDOW = 1.0; -- Sek. Spielraum fuer die Antwort des Servers
|
||||||
|
|
||||||
function FBLOS_HasUnitXP()
|
function FBLOS_HasUnitXP()
|
||||||
@@ -3742,23 +3781,109 @@ function FBUnitLOSBlocked(unit)
|
|||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Fehlermeldung "nicht in Sichtlinie": Ziel des gerade geklickten Buttons
|
-- Klick auf einen Button: Ziel als Kandidat merken. Ist der laufende Cast
|
||||||
-- markieren. Frueher fiel die Zuordnung auf das letzte Button-Ziel der
|
-- laut Zauberzeit schon vorbei, gehoert ein neuer Klick nicht mehr zu ihm;
|
||||||
-- letzten zwei Sekunden, das freundliche Ziel oder den Spieler selbst
|
-- dessen Spielraum fuer eine spaete Meldung endet dann hier.
|
||||||
-- zurueck. Ein Angriffszauber ohne Sicht kurz nach einem Heilklick markierte
|
function FBLOS_NoteClick(targetName, spell, now)
|
||||||
-- so den geheilten Mitspieler, ohne Heilklick die eigene Raidzelle.
|
if (FBLOSCast and now > FBLOSCast.endT) then FBLOSCast = nil; end
|
||||||
|
FBLOSClick = { name = targetName, spell = spell, t = now, untilT = now + FBLOS_ERROR_WINDOW };
|
||||||
|
end
|
||||||
|
|
||||||
|
-- SPELLCAST_START: Laeuft der geklickte Zauber an, wird sein Ziel zum
|
||||||
|
-- Kandidaten des laufenden Casts; ein anderer Zauber gehoert nicht zu dem
|
||||||
|
-- Klick, ein Klick von vor mehr als FBPREDICT_CLICK_TIME Sekunden auch
|
||||||
|
-- nicht (dieselbe Frist wie FBPredict_TakeClick). Sonst uebernahm ein Klick,
|
||||||
|
-- der ohne Antwort verpufft war, Sekunden spaeter denselben Zauber von der
|
||||||
|
-- Aktionsleiste auf ein ganz anderes Ziel. Ein neuer Castbeginn beendet in
|
||||||
|
-- jedem Fall den vorigen Cast.
|
||||||
|
function FBLOS_CastStart(spell, castMs)
|
||||||
|
FBLOSCast = nil;
|
||||||
|
local c = FBLOSClick;
|
||||||
|
FBLOSClick = nil;
|
||||||
|
local now = GetTime();
|
||||||
|
if (c and spell == c.spell and now <= c.t + FBPREDICT_CLICK_TIME) then
|
||||||
|
local endT = now + (castMs or 0) / 1000;
|
||||||
|
FBLOSCast = { name = c.name, endT = endT, untilT = endT + FBLOS_ERROR_WINDOW, seq = FBPredictClickSeq };
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- SPELLCAST_DELAYED: Pushback schiebt das Castende hinaus
|
||||||
|
function FBLOS_CastDelayed(ms)
|
||||||
|
local c = FBLOSCast;
|
||||||
|
if (not c) then return; end
|
||||||
|
local d = (tonumber(ms) or 0) / 1000;
|
||||||
|
c.endT = c.endT + d;
|
||||||
|
c.untilT = c.untilT + d;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- SPELLCAST_INTERRUPTED: beide Kandidaten sind beantwortet
|
||||||
|
function FBLOS_Reset()
|
||||||
|
FBLOSClick = nil;
|
||||||
|
FBLOSCast = nil;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- SPELLCAST_STOP: Ein Zauber ist durchgegangen, die Sicht war da. Lief ein
|
||||||
|
-- Zauber mit Zauberzeit, ist das sein Ende. Ein Klick, der waehrenddessen
|
||||||
|
-- kam und keine Antwort bekam, ist ein vorgemerkter naechster Versuch (die
|
||||||
|
-- Zauberwarteschlange eines Clientmods wie Nampower); ohne Warteschlange
|
||||||
|
-- haette ihn "Another action is in progress" schon abgeraeumt. Er geht erst
|
||||||
|
-- jetzt hinaus, also beginnen seine Fristen hier, und er bleibt Kandidat
|
||||||
|
-- fuer den naechsten Castbeginn, so wie FBPredictClick bei
|
||||||
|
-- FBPredict_ClickDone. Ohne laufenden Cast war es ein Sofortzauber, und der
|
||||||
|
-- Klick ist beantwortet. Raeumte das Castende beide ab, markierte der
|
||||||
|
-- vorgemerkte Zauber bei fehlender Sicht niemanden.
|
||||||
|
function FBLOS_CastDone()
|
||||||
|
local now = GetTime();
|
||||||
|
local cast, click = FBLOSCast, FBLOSClick;
|
||||||
|
FBLOSCast = nil;
|
||||||
|
if (cast and now <= cast.untilT and click) then
|
||||||
|
click.t = now;
|
||||||
|
click.untilT = now + FBLOS_ERROR_WINDOW;
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
FBLOSClick = nil;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fehlermeldung "nicht in Sichtlinie": das Ziel markieren, dem die Meldung
|
||||||
|
-- gilt. Frueher fiel die Zuordnung auf das letzte Button-Ziel der letzten
|
||||||
|
-- zwei Sekunden, das freundliche Ziel oder den Spieler selbst zurueck. Ein
|
||||||
|
-- Angriffszauber ohne Sicht kurz nach einem Heilklick markierte so den
|
||||||
|
-- geheilten Mitspieler, ohne Heilklick die eigene Raidzelle.
|
||||||
function FBLOS_OnError(msg)
|
function FBLOS_OnError(msg)
|
||||||
if (not msg) then return; end
|
if (not msg) then return; end
|
||||||
-- Jede Fehlermeldung beantwortet den letzten Klick. War es eine andere
|
local now = GetTime();
|
||||||
-- (Reichweite, Mana, "Another action is in progress"), kommt fuer ihn
|
local cast = FBLOSCast;
|
||||||
-- keine Sichtlinien-Meldung mehr.
|
if (cast and now > cast.untilT) then cast = nil; FBLOSCast = nil; end
|
||||||
local name = FBLOSCandidate;
|
local click = FBLOSClick;
|
||||||
FBLOSCandidate = nil;
|
if (click and now > click.untilT) then click = nil; FBLOSClick = nil; end
|
||||||
local losText = SPELL_FAILED_LINE_OF_SIGHT or "Target not in line of sight";
|
local losText = SPELL_FAILED_LINE_OF_SIGHT or "Target not in line of sight";
|
||||||
if (msg ~= losText) then return; end
|
|
||||||
if (not name) or (GetTime() > FBLOSCandidateUntil) then return; end
|
if (msg ~= losText) then
|
||||||
if (name == UnitName("player")) then return; end
|
-- Eine andere Meldung (Reichweite, Mana, "Another action is in
|
||||||
FBLOSFlags[name] = GetTime() + FBLOS_TIMEOUT;
|
-- progress") beantwortet den juengsten Versuch. Gab es seit dem
|
||||||
|
-- Castbeginn keinen neuen, ist das der laufende Cast; sonst der neue
|
||||||
|
-- Versuch, und der laufende Cast bleibt Kandidat fuer sein Ende.
|
||||||
|
if (cast and FBPredictClickSeq == cast.seq) then
|
||||||
|
FBLOSCast = nil;
|
||||||
|
else
|
||||||
|
FBLOSClick = nil;
|
||||||
|
end
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Waehrend ein Zauber mit Zauberzeit laeuft, lehnt der Client jeden
|
||||||
|
-- neuen Versuch mit "Another action is in progress" ab; eine
|
||||||
|
-- Sichtlinien-Meldung in dieser Zeit gilt deshalb dem laufenden Cast.
|
||||||
|
local name = nil;
|
||||||
|
if (cast) then
|
||||||
|
name = cast.name;
|
||||||
|
FBLOSCast = nil;
|
||||||
|
elseif (click) then
|
||||||
|
name = click.name;
|
||||||
|
FBLOSClick = nil;
|
||||||
|
end
|
||||||
|
if (not name) or (name == UnitName("player")) then return; end
|
||||||
|
FBLOSFlags[name] = now + FBLOS_TIMEOUT;
|
||||||
FBHealBox_CheckLOSAll();
|
FBHealBox_CheckLOSAll();
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3931,11 +4056,56 @@ function FBHealBox_SpellCastSeconds(id)
|
|||||||
return FBSpellCastCache[id] or nil;
|
return FBSpellCastCache[id] or nil;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Basis-Zauberzeit vor Talenten. Der Anteil am +Heilung-Bonus haengt in
|
||||||
|
-- Vanilla an der Zauberzeit, die der Zauber ohne Talente hat. Der Tooltip
|
||||||
|
-- zeigt aber die verkuerzte Zeit: Mit Goettlichem Furor steht bei Grosser
|
||||||
|
-- Heilung "2.5 sec cast", mit Naturalist bei Heilender Beruehrung 3.0 statt
|
||||||
|
-- 3.5 Sekunden, mit Verbesserter Welle der Heilung 2.5 statt 3.0. Bis 1.4.7
|
||||||
|
-- rechnete das Addon mit der Tooltipzeit und unterschaetzte den Bonus
|
||||||
|
-- ungelernter Raenge dieser vier Zauber um ein Siebtel. Hier stehen die
|
||||||
|
-- Zauber, deren Zauberzeit ein Talent verkuerzt: eine Zahl gilt fuer alle
|
||||||
|
-- Raenge, eine Liste je Rang (hinter ihrem Ende gilt der letzte Wert).
|
||||||
|
-- Alles andere nimmt weiter die Zeit aus dem Tooltip.
|
||||||
|
FBBaseCastTime = {
|
||||||
|
["Heal"] = 3.0,
|
||||||
|
["Greater Heal"] = 3.0,
|
||||||
|
["Healing Touch"] = { 1.5, 2.0, 2.5, 3.0, 3.5 },
|
||||||
|
["Healing Wave"] = { 1.5, 2.0, 2.5, 3.0 },
|
||||||
|
-- deutsche Zaubernamen, Sonderzeichen einmal Latin-1, einmal UTF-8
|
||||||
|
["Heilen"] = 3.0,
|
||||||
|
["Gro\223e Heilung"] = 3.0,
|
||||||
|
["Gro\195\159e Heilung"] = 3.0,
|
||||||
|
["Heilende Ber\252hrung"] = { 1.5, 2.0, 2.5, 3.0, 3.5 },
|
||||||
|
["Heilende Ber\195\188hrung"] = { 1.5, 2.0, 2.5, 3.0, 3.5 },
|
||||||
|
["Welle der Heilung"] = { 1.5, 2.0, 2.5, 3.0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
-- Rangnummer aus "Rank 3" / "Rang 3", oder nil
|
||||||
|
function FBHealBox_RankNumber(rank)
|
||||||
|
if (not rank) then return nil; end
|
||||||
|
local _, _, n = string.find(rank, "(%d+)");
|
||||||
|
return n and tonumber(n);
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Zauberzeit fuer die Gewichtung des Bonus: Basiswert aus FBBaseCastTime,
|
||||||
|
-- sonst die Zeit aus dem Tooltip (0 = Instant, nil = unlesbar)
|
||||||
|
function FBHealBox_BaseCastSeconds(spellName, rank, bookID)
|
||||||
|
local base = spellName and FBBaseCastTime[spellName];
|
||||||
|
if (type(base) == "number") then return base; end
|
||||||
|
if (type(base) == "table") then
|
||||||
|
local n = FBHealBox_RankNumber(rank);
|
||||||
|
local last = base[table.getn(base)];
|
||||||
|
if (n and base[n]) then return base[n]; end
|
||||||
|
return last;
|
||||||
|
end
|
||||||
|
return FBHealBox_SpellCastSeconds(bookID);
|
||||||
|
end
|
||||||
|
|
||||||
-- Anteil des +Heilung-Werts, der auf diesen Zauber entfaellt
|
-- Anteil des +Heilung-Werts, der auf diesen Zauber entfaellt
|
||||||
function FBHealBox_HealBonusFor(bookID)
|
function FBHealBox_HealBonusFor(bookID, spellName, rank)
|
||||||
local bonus = FBHealBox_HealingBonus();
|
local bonus = FBHealBox_HealingBonus();
|
||||||
if (bonus <= 0) then return 0; end
|
if (bonus <= 0) then return 0; end
|
||||||
local secs = FBHealBox_SpellCastSeconds(bookID);
|
local secs = FBHealBox_BaseCastSeconds(spellName, rank, bookID);
|
||||||
if (not secs) then secs = 2.5; end -- Zauberzeit unlesbar: mittlerer Wert
|
if (not secs) then secs = 2.5; end -- Zauberzeit unlesbar: mittlerer Wert
|
||||||
if (secs <= 0) then secs = 1.5; end -- Instants rechnen mit 1,5 Sekunden
|
if (secs <= 0) then secs = 1.5; end -- Instants rechnen mit 1,5 Sekunden
|
||||||
if (secs > 3.5) then secs = 3.5; end
|
if (secs > 3.5) then secs = 3.5; end
|
||||||
@@ -3948,21 +4118,28 @@ end
|
|||||||
-- API verraet die Lernstufe eines Rangs nicht, deshalb stehen hier die Raenge
|
-- API verraet die Lernstufe eines Rangs nicht, deshalb stehen hier die Raenge
|
||||||
-- der Einzelzielheilungen, die unter Stufe 20 liegen (Stufe je Rang). Ohne
|
-- der Einzelzielheilungen, die unter Stufe 20 liegen (Stufe je Rang). Ohne
|
||||||
-- diesen Abschlag hielt Smart Healing kleine Raenge mit viel +Heilung fuer
|
-- diesen Abschlag hielt Smart Healing kleine Raenge mit viel +Heilung fuer
|
||||||
-- deutlich staerker, als sie sind, und rangte zu tief ab.
|
-- deutlich staerker, als sie sind, und rangte zu tief ab. Die deutschen
|
||||||
|
-- Namen stehen dabei wie in FBHealChains.
|
||||||
FBRankLearnLevel = {
|
FBRankLearnLevel = {
|
||||||
["Lesser Heal"] = { 1, 4, 10 },
|
["Lesser Heal"] = { 1, 4, 10 },
|
||||||
["Heal"] = { 16 },
|
["Heal"] = { 16 },
|
||||||
["Healing Touch"] = { 1, 8, 14 },
|
["Healing Touch"] = { 1, 8, 14 },
|
||||||
["Healing Wave"] = { 1, 6, 12, 18 },
|
["Healing Wave"] = { 1, 6, 12, 18 },
|
||||||
["Holy Light"] = { 1, 6, 14 },
|
["Holy Light"] = { 1, 6, 14 },
|
||||||
|
["Geringes Heilen"] = { 1, 4, 10 },
|
||||||
|
["Heilen"] = { 16 },
|
||||||
|
["Heilende Ber\252hrung"] = { 1, 8, 14 },
|
||||||
|
["Heilende Ber\195\188hrung"] = { 1, 8, 14 },
|
||||||
|
["Welle der Heilung"] = { 1, 6, 12, 18 },
|
||||||
|
["Heiliges Licht"] = { 1, 6, 14 },
|
||||||
};
|
};
|
||||||
|
|
||||||
-- Faktor auf den Bonusanteil eines Rangs (1 = voller Anteil)
|
-- Faktor auf den Bonusanteil eines Rangs (1 = voller Anteil)
|
||||||
function FBHealBox_LowRankFactor(spellName, rank)
|
function FBHealBox_LowRankFactor(spellName, rank)
|
||||||
local levels = spellName and FBRankLearnLevel[spellName];
|
local levels = spellName and FBRankLearnLevel[spellName];
|
||||||
if (not levels) or (not rank) then return 1; end
|
if (not levels) then return 1; end
|
||||||
local _, _, n = string.find(rank, "(%d+)");
|
local n = FBHealBox_RankNumber(rank);
|
||||||
local lvl = n and levels[tonumber(n)];
|
local lvl = n and levels[n];
|
||||||
if (not lvl) or (lvl >= 20) then return 1; end
|
if (not lvl) or (lvl >= 20) then return 1; end
|
||||||
return 1 - (20 - lvl) * 0.0375;
|
return 1 - (20 - lvl) * 0.0375;
|
||||||
end
|
end
|
||||||
@@ -3973,7 +4150,7 @@ function FBPredict_ExpectedDirect(spellName, rank, info, bookID)
|
|||||||
local learned = FBPredict_Remembered("direct", spellName, rank);
|
local learned = FBPredict_Remembered("direct", spellName, rank);
|
||||||
if (learned) then return learned; end
|
if (learned) then return learned; end
|
||||||
if (not info) or (not info.direct) then return nil; end
|
if (not info) or (not info.direct) then return nil; end
|
||||||
return info.direct + FBHealBox_HealBonusFor(bookID) * FBHealBox_LowRankFactor(spellName, rank);
|
return info.direct + FBHealBox_HealBonusFor(bookID, spellName, rank) * FBHealBox_LowRankFactor(spellName, rank);
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Reichweite eines Zaubers in Metern oder nil. Sie steht im Tooltip rechts
|
-- Reichweite eines Zaubers in Metern oder nil. Sie steht im Tooltip rechts
|
||||||
@@ -5017,6 +5194,8 @@ end
|
|||||||
|
|
||||||
function FBHealBoxButtonsChanged()
|
function FBHealBoxButtonsChanged()
|
||||||
FBHealBox_InvalidateRangeSpell();
|
FBHealBox_InvalidateRangeSpell();
|
||||||
|
-- Buff-Icons folgen der Belegung (nur Buffs auf den Buttons)
|
||||||
|
FBPredict_BuildBuffOrder();
|
||||||
local rightOn = (HealBox.RightClick == 1);
|
local rightOn = (HealBox.RightClick == 1);
|
||||||
for p = 1, FBSlotCount do
|
for p = 1, FBSlotCount do
|
||||||
local unit = FBPartyUnit[p];
|
local unit = FBPartyUnit[p];
|
||||||
@@ -5850,12 +6029,15 @@ function FBPredict_GetSpellInfo(bookID, spellName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Nach jedem Zauberbuch-Scan: was koennen die gelernten Zauber ueberhaupt?
|
-- Nach jedem Zauberbuch-Scan: was koennen die gelernten Zauber ueberhaupt?
|
||||||
FBPredictWatchBuffOrder = {}; -- Buff-Zauber alphabetisch (fuer die Icon-Reihenfolge)
|
FBPredictBuffSpells = {}; -- alle verfolgten Buffs mit Laufzeit (Zaubernamen, sortiert)
|
||||||
|
FBPredictWatchBuffOrder = {}; -- Buff-Familien mit Icon, sortiert (FBPredict_BuildBuffOrder)
|
||||||
|
FBPredictBuffFamily = {}; -- [Familie] = { Variante, ... } (Einzel- und Gruppenbuff)
|
||||||
|
FBPredictBuffShown = {}; -- [Zaubername] = Familie, wenn die Familie ein Icon bekommt
|
||||||
|
|
||||||
function FBPredict_BuildWatch()
|
function FBPredict_BuildWatch()
|
||||||
FBPredictWatch = {};
|
FBPredictWatch = {};
|
||||||
FBPredictInfo = {};
|
FBPredictInfo = {};
|
||||||
FBPredictWatchBuffOrder = {};
|
FBPredictBuffSpells = {};
|
||||||
|
|
||||||
for spellName, ranks in pairs(FBPlayerSpells) do
|
for spellName, ranks in pairs(FBPlayerSpells) do
|
||||||
local top = ranks[table.getn(ranks)];
|
local top = ranks[table.getn(ranks)];
|
||||||
@@ -5875,10 +6057,63 @@ function FBPredict_BuildWatch()
|
|||||||
buffSecs = info.buff and info.buff.duration,
|
buffSecs = info.buff and info.buff.duration,
|
||||||
icon = top.icon,
|
icon = top.icon,
|
||||||
};
|
};
|
||||||
if (info.buff) then table.insert(FBPredictWatchBuffOrder, spellName); end
|
if (info.buff) then table.insert(FBPredictBuffSpells, spellName); end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(FBPredictBuffSpells);
|
||||||
|
FBPredict_BuildBuffOrder();
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Zaubernamen auf den Buttons: linke Seite immer, die rechte nur mit
|
||||||
|
-- eingeschaltetem Rechtsklick-Zauber (sonst traegt der Button sie nicht).
|
||||||
|
-- Gezaehlt werden alle zehn Belegungen, denn die Mini-Buttons im Raid
|
||||||
|
-- nutzen Button 1 bis 4 unabhaengig davon, wie viele die Plaketten zeigen.
|
||||||
|
function FBPredict_ButtonSpells()
|
||||||
|
local set = {};
|
||||||
|
local sides = { HealBox.SpellChoice };
|
||||||
|
if (HealBox.RightClick == 1) then table.insert(sides, HealBox.SpellChoiceR); end
|
||||||
|
for _, tbl in ipairs(sides) do
|
||||||
|
if (tbl) then
|
||||||
|
for i = 1, FBMaxButtonCount do
|
||||||
|
local cast = tbl[i];
|
||||||
|
if (type(cast) == "string") then
|
||||||
|
local base = FBPredict_SplitCast(cast);
|
||||||
|
if (base) then set[base] = true; end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return set;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Welche Buffs bekommen ein Icon? Nur die, die auf einem Button liegen, so
|
||||||
|
-- wie es Tooltip und README immer gesagt haben. Ein Buff und seine
|
||||||
|
-- Gruppenversion (FBBuffAlternates) bilden eine Familie mit einem einzigen
|
||||||
|
-- Icon; es zeigt die Variante, die die Einheit gerade traegt. Bis 1.4.7
|
||||||
|
-- bekam jeder gelernte Buff ein Icon, und weil Einzel- und Gruppenbuff
|
||||||
|
-- einander ueber die Textur des anderen fanden, sah ein Priester mit
|
||||||
|
-- Seelenstaerke und Gebet der Seelenstaerke jedes Fortitude-Icon doppelt.
|
||||||
|
-- Laeuft nach jedem Zauberbuch-Scan und nach jeder Umbelegung der Buttons.
|
||||||
|
function FBPredict_BuildBuffOrder()
|
||||||
|
FBPredictWatchBuffOrder = {};
|
||||||
|
FBPredictBuffFamily = {};
|
||||||
|
FBPredictBuffShown = {};
|
||||||
|
local onButtons = FBPredict_ButtonSpells();
|
||||||
|
for _, spellName in ipairs(FBPredictBuffSpells) do
|
||||||
|
local alt = FBBuffAlternates[spellName];
|
||||||
|
local fam = spellName;
|
||||||
|
if (alt and alt < spellName) then fam = alt; end
|
||||||
|
if (onButtons[spellName] or (alt and onButtons[alt])) then
|
||||||
|
if (not FBPredictBuffFamily[fam]) then
|
||||||
|
FBPredictBuffFamily[fam] = {};
|
||||||
|
table.insert(FBPredictWatchBuffOrder, fam);
|
||||||
|
end
|
||||||
|
table.insert(FBPredictBuffFamily[fam], spellName);
|
||||||
|
FBPredictBuffShown[spellName] = fam;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.sort(FBPredictWatchBuffOrder);
|
table.sort(FBPredictWatchBuffOrder);
|
||||||
|
FBBuffIconsDirty = true;
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Buff per eigenem Button auf ein Ziel neu gewirkt, das ihn schon traegt:
|
-- Buff per eigenem Button auf ein Ziel neu gewirkt, das ihn schon traegt:
|
||||||
@@ -5896,10 +6131,17 @@ function FBPredict_ConfirmBuffRefresh()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Buff-Laufzeit auf einer Einheit vermerken
|
-- Buff-Laufzeit auf einer Einheit vermerken. Einzel- und Gruppenbuff
|
||||||
|
-- ersetzen einander, die Einheit traegt also nur noch diese Variante: Die
|
||||||
|
-- Uhr der anderen (FBBuffAlternates) faellt weg. Liefe sie weiter, gaelte
|
||||||
|
-- sie bei Mal und Gabe der Wildnis nie als verschwunden, denn beide haben
|
||||||
|
-- dieselbe Textur: Nach Gabe der Wildnis auf ein Ziel mit eigenem Mal
|
||||||
|
-- zeigte das Icon weiter das Mal mit seiner alten Restzeit.
|
||||||
function FBPredict_StartBuff(unitName, spellName, secs)
|
function FBPredict_StartBuff(unitName, spellName, secs)
|
||||||
if (not unitName) or (not spellName) or (not secs) then return; end
|
if (not unitName) or (not spellName) or (not secs) then return; end
|
||||||
if (not FBBuffTimers[unitName]) then FBBuffTimers[unitName] = {}; end
|
if (not FBBuffTimers[unitName]) then FBBuffTimers[unitName] = {}; end
|
||||||
|
local alt = FBBuffAlternates[spellName];
|
||||||
|
if (alt) then FBBuffTimers[unitName][alt] = nil; end
|
||||||
local t = FBBuffTimers[unitName][spellName];
|
local t = FBBuffTimers[unitName][spellName];
|
||||||
if (t) then t.expires = GetTime() + secs; else FBBuffTimers[unitName][spellName] = { expires = GetTime() + secs }; end
|
if (t) then t.expires = GetTime() + secs; else FBBuffTimers[unitName][spellName] = { expires = GetTime() + secs }; end
|
||||||
FBBuffIconsDirty = true;
|
FBBuffIconsDirty = true;
|
||||||
@@ -5912,6 +6154,7 @@ end
|
|||||||
-- je Sekunde. Jetzt wird die Liste einmal je Frame gelesen und alle Wachen
|
-- je Sekunde. Jetzt wird die Liste einmal je Frame gelesen und alle Wachen
|
||||||
-- bedienen sich daraus; der Zeitstempel arbeitet wie bei FBHealBox_UnitBuffs.
|
-- bedienen sich daraus; der Zeitstempel arbeitet wie bei FBHealBox_UnitBuffs.
|
||||||
FBPlayerBuffLeft = {};
|
FBPlayerBuffLeft = {};
|
||||||
|
FBPlayerBuffIndex = {}; -- [TEXTUR] = Buff-Index dazu (fuer den Namen im Tooltip)
|
||||||
FBPlayerBuffStamp = nil;
|
FBPlayerBuffStamp = nil;
|
||||||
|
|
||||||
function FBPredict_ScanPlayerBuffTimes()
|
function FBPredict_ScanPlayerBuffTimes()
|
||||||
@@ -5919,6 +6162,7 @@ function FBPredict_ScanPlayerBuffTimes()
|
|||||||
if (FBPlayerBuffStamp == now) then return FBPlayerBuffLeft; end
|
if (FBPlayerBuffStamp == now) then return FBPlayerBuffLeft; end
|
||||||
FBPlayerBuffStamp = now;
|
FBPlayerBuffStamp = now;
|
||||||
for k in pairs(FBPlayerBuffLeft) do FBPlayerBuffLeft[k] = nil; end
|
for k in pairs(FBPlayerBuffLeft) do FBPlayerBuffLeft[k] = nil; end
|
||||||
|
for k in pairs(FBPlayerBuffIndex) do FBPlayerBuffIndex[k] = nil; end
|
||||||
if (not GetPlayerBuff) or (not GetPlayerBuffTexture) or (not GetPlayerBuffTimeLeft) then
|
if (not GetPlayerBuff) or (not GetPlayerBuffTexture) or (not GetPlayerBuffTimeLeft) then
|
||||||
return FBPlayerBuffLeft;
|
return FBPlayerBuffLeft;
|
||||||
end
|
end
|
||||||
@@ -5934,6 +6178,7 @@ function FBPredict_ScanPlayerBuffTimes()
|
|||||||
-- gleiche Textur mehrfach (etwa gestapelte Buffs): laengste Zeit
|
-- gleiche Textur mehrfach (etwa gestapelte Buffs): laengste Zeit
|
||||||
if (not FBPlayerBuffLeft[up]) or (left > FBPlayerBuffLeft[up]) then
|
if (not FBPlayerBuffLeft[up]) or (left > FBPlayerBuffLeft[up]) then
|
||||||
FBPlayerBuffLeft[up] = left;
|
FBPlayerBuffLeft[up] = left;
|
||||||
|
FBPlayerBuffIndex[up] = id;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -5948,6 +6193,59 @@ function FBPredict_PlayerBuffTimeLeft(tex)
|
|||||||
return FBPredict_ScanPlayerBuffTimes()[tex];
|
return FBPredict_ScanPlayerBuffTimes()[tex];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Name des eigenen Buffs mit dieser Textur, per Scan-Tooltip gelesen. Je
|
||||||
|
-- Anwendung nur einmal: Solange das Ablaufende (jetzt + Restzeit) gleich
|
||||||
|
-- bleibt, ist es derselbe Buff; ein Neucast oder ein anderer Buff mit
|
||||||
|
-- derselben Textur verschiebt es und loest ein neues Lesen aus.
|
||||||
|
FBPlayerBuffNameMemo = {}; -- [TEXTUR] = { name, endT }
|
||||||
|
function FBPredict_PlayerBuffName(tex, left)
|
||||||
|
local endT = GetTime() + left;
|
||||||
|
local m = FBPlayerBuffNameMemo[tex];
|
||||||
|
if (m and math.abs(m.endT - endT) < 1.5) then return m.name; end
|
||||||
|
if (not m) then m = {}; FBPlayerBuffNameMemo[tex] = m; end
|
||||||
|
local id = FBPlayerBuffIndex[tex];
|
||||||
|
m.name = id and FBHealBox_PlayerBuffName(id);
|
||||||
|
m.endT = endT;
|
||||||
|
return m.name;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Restlaufzeit eines eigenen Buffs, aber nur, wenn du genau diese Variante
|
||||||
|
-- traegst; sonst nil. Mal und Gabe der Wildnis haben dieselbe Textur, die
|
||||||
|
-- Restzeit allein trennt sie nicht: 1800 Sekunden sind ein frisches Mal
|
||||||
|
-- oder eine halb abgelaufene Gabe. Bekaemen beide die Uhr, spraenge das
|
||||||
|
-- Icon, sobald die Gabe unter 30 Minuten faellt, aufs Mal und wieder auf
|
||||||
|
-- ganz farbig. Den Ausschlag gibt deshalb der Name im Tooltip. Ist
|
||||||
|
-- die Gruppenversion nicht gelernt, ist ihre Textur unbekannt; auch dann
|
||||||
|
-- entscheidet der Name, damit eine fremde Gabe nicht als Mal mit Uhr gilt.
|
||||||
|
-- Ohne lesbaren Namen entscheidet die Dauer: eine Restzeit, die nur eine
|
||||||
|
-- Variante fasst, gehoert ihr; sonst bleibt die laufende Uhr, und ohne Uhr
|
||||||
|
-- gilt die kuerzere Variante. Zweiter Rueckgabewert true: Du traegst laut
|
||||||
|
-- Tooltip die andere Variante, eine Uhr dieser hier ist hinfaellig.
|
||||||
|
function FBPredict_PlayerBuffLeft(spellName, w)
|
||||||
|
local left = FBPredict_PlayerBuffTimeLeft(w.tex);
|
||||||
|
if (not left) then return nil; end
|
||||||
|
local alt = FBBuffAlternates[spellName];
|
||||||
|
if (not alt) then return left; end
|
||||||
|
local aw = FBPredictWatch[alt];
|
||||||
|
if (aw and aw.tex ~= w.tex) then return left; end -- eigene Textur: eindeutig
|
||||||
|
|
||||||
|
local carried = FBPredict_PlayerBuffName(w.tex, left);
|
||||||
|
if (carried == spellName) then return left; end
|
||||||
|
if (carried == alt) then return nil, true; end
|
||||||
|
if (not aw) then return left; end
|
||||||
|
|
||||||
|
local secs, altSecs = (w.buffSecs or 0), (aw.buffSecs or 0);
|
||||||
|
local fits, altFits = (secs + 1 >= left), (altSecs + 1 >= left);
|
||||||
|
if (fits and not altFits) then return left; end
|
||||||
|
if (altFits and not fits) then return nil; end
|
||||||
|
local timers = FBBuffTimers[UnitName("player")];
|
||||||
|
local now = GetTime();
|
||||||
|
if (timers and timers[spellName] and timers[spellName].expires > now) then return left; end
|
||||||
|
if (timers and timers[alt] and timers[alt].expires > now) then return nil; end
|
||||||
|
if (secs < altSecs) or (secs == altSecs and spellName < alt) then return left; end
|
||||||
|
return nil;
|
||||||
|
end
|
||||||
|
|
||||||
-- [ Lernspeicher (wandert in die SavedVariables) ] --------------------------
|
-- [ Lernspeicher (wandert in die SavedVariables) ] --------------------------
|
||||||
|
|
||||||
FBPREDICT_ABSORB_MAX_FACTOR = 1.5;
|
FBPREDICT_ABSORB_MAX_FACTOR = 1.5;
|
||||||
@@ -6111,11 +6409,44 @@ function FBGetHoTHeal(unitName)
|
|||||||
return sum;
|
return sum;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Trifft ein Direktcast diese Einheit? Gruppenheilungen (FBCommGroupHeal)
|
||||||
|
-- tragen ihre Ziele in d.targets, alle anderen haben genau d.target.
|
||||||
|
function FBPredict_CastHits(d, unitName)
|
||||||
|
if (not d) or (not unitName) then return false; end
|
||||||
|
if (d.targets) then return (d.targets[unitName] == true); end
|
||||||
|
return (d.target == unitName);
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Alle Ziele eines Direktcasts zum Neuzeichnen vormerken
|
||||||
|
function FBPredict_MarkCastDirty(d)
|
||||||
|
if (not d) then return; end
|
||||||
|
if (d.targets) then
|
||||||
|
for n in pairs(d.targets) do FBHealBox_MarkDirty(n); end
|
||||||
|
end
|
||||||
|
FBHealBox_MarkDirty(d.target);
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Ziele einer Gruppenheilung: man selbst und die Gruppenmitglieder in
|
||||||
|
-- Reichweite. Im Schlachtzug sind party1 bis party4 die eigene Untergruppe,
|
||||||
|
-- genau die heilt Gebet der Heilung. Dieselbe Liste geht ueber HealComm raus.
|
||||||
|
function FBPredict_GroupTargets()
|
||||||
|
local list = {};
|
||||||
|
local me = UnitName("player");
|
||||||
|
if (me) then table.insert(list, me); end
|
||||||
|
for i = 1, 4 do
|
||||||
|
local u = "party"..i;
|
||||||
|
if (UnitExists(u) and CheckInteractDistance(u, 4)) then
|
||||||
|
local n = UnitName(u);
|
||||||
|
if (n) then table.insert(list, n); end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return list;
|
||||||
|
end
|
||||||
|
|
||||||
-- Laufender Direktcast auf diese Einheit
|
-- Laufender Direktcast auf diese Einheit
|
||||||
function FBGetDirectHeal(unitName)
|
function FBGetDirectHeal(unitName)
|
||||||
local d = FBPredictDirect;
|
local d = FBPredictDirect;
|
||||||
if (not d) or (not unitName) then return 0; end
|
if (not FBPredict_CastHits(d, unitName)) then return 0; end
|
||||||
if (d.target ~= unitName) then return 0; end
|
|
||||||
if (GetTime() > d.finish) then return 0; end
|
if (GetTime() > d.finish) then return 0; end
|
||||||
return d.amount;
|
return d.amount;
|
||||||
end
|
end
|
||||||
@@ -6149,9 +6480,7 @@ function FBPredict_NoteCast(castString, targetName)
|
|||||||
FBPredictClickSeq = FBPredictClickSeq + 1;
|
FBPredictClickSeq = FBPredictClickSeq + 1;
|
||||||
local base, rank = FBPredict_SplitCast(castString);
|
local base, rank = FBPredict_SplitCast(castString);
|
||||||
-- Ziel fuer eine moegliche Sichtlinien-Meldung zu genau diesem Klick
|
-- Ziel fuer eine moegliche Sichtlinien-Meldung zu genau diesem Klick
|
||||||
FBLOSCandidate = targetName;
|
FBLOS_NoteClick(targetName, base, now);
|
||||||
FBLOSCandidateSpell = base;
|
|
||||||
FBLOSCandidateUntil = now + FBLOS_ERROR_WINDOW;
|
|
||||||
|
|
||||||
-- Ziel und Rang braucht nur ein verfolgter Zauber. Jeder Klick ersetzt
|
-- Ziel und Rang braucht nur ein verfolgter Zauber. Jeder Klick ersetzt
|
||||||
-- aber den vorigen, auch einer auf einen anderen Zauber.
|
-- aber den vorigen, auch einer auf einen anderen Zauber.
|
||||||
@@ -6325,8 +6654,20 @@ function FBPredict_CastStart(spellName, castMs)
|
|||||||
local amount = FBPredict_ExpectedDirect(spellName, rank, info, bookID) or info.direct;
|
local amount = FBPredict_ExpectedDirect(spellName, rank, info, bookID) or info.direct;
|
||||||
FBLOS_Clear(target); -- Cast laeuft an: Sichtlinie ist da
|
FBLOS_Clear(target); -- Cast laeuft an: Sichtlinie ist da
|
||||||
|
|
||||||
|
-- Gruppenheilung: Die Vorhersage gilt fuer die ganze eigene Gruppe in
|
||||||
|
-- Reichweite, nicht fuer die eine angeklickte Einheit. Bis 1.4.7 stand
|
||||||
|
-- sie nur dort, im Raid also womoeglich in einer fremden Gruppe, obwohl
|
||||||
|
-- HealComm schon die richtige Liste bekam.
|
||||||
|
local groupList, targets = nil, nil;
|
||||||
|
if (FBCommGroupHeal[spellName]) then
|
||||||
|
groupList = FBPredict_GroupTargets();
|
||||||
|
targets = {};
|
||||||
|
for _, n in ipairs(groupList) do targets[n] = true; end
|
||||||
|
end
|
||||||
|
|
||||||
FBPredictDirect = {
|
FBPredictDirect = {
|
||||||
target = target,
|
target = target,
|
||||||
|
targets = targets,
|
||||||
spell = spellName,
|
spell = spellName,
|
||||||
rank = rank,
|
rank = rank,
|
||||||
rankKnown = rankKnown,
|
rankKnown = rankKnown,
|
||||||
@@ -6340,9 +6681,9 @@ function FBPredict_CastStart(spellName, castMs)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- an andere Heiler funken (Puppeteer & Co. lesen mit)
|
-- an andere Heiler funken (Puppeteer & Co. lesen mit)
|
||||||
FBComm_SendHealStart(spellName, FBPredictDirect.target, amount, castMs);
|
FBComm_SendHealStart(spellName, FBPredictDirect.target, amount, castMs, groupList);
|
||||||
|
|
||||||
FBHealBox_MarkDirty(FBPredictDirect.target);
|
FBPredict_MarkCastDirty(FBPredictDirect);
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Castende. Nach einem erfolgreichen Cast (SPELLCAST_STOP) bleibt die
|
-- Castende. Nach einem erfolgreichen Cast (SPELLCAST_STOP) bleibt die
|
||||||
@@ -6357,7 +6698,7 @@ function FBPredict_CastEnd(success)
|
|||||||
d.ended = GetTime();
|
d.ended = GetTime();
|
||||||
FBPredictLastDirect = d;
|
FBPredictLastDirect = d;
|
||||||
end
|
end
|
||||||
FBHealBox_MarkDirty(d.target);
|
FBPredict_MarkCastDirty(d);
|
||||||
end
|
end
|
||||||
|
|
||||||
-- [ Aura-Scan: Anwendung bestaetigen, Wegfall erkennen ] --------------------
|
-- [ Aura-Scan: Anwendung bestaetigen, Wegfall erkennen ] --------------------
|
||||||
@@ -6408,22 +6749,31 @@ function FBPredict_ScanUnit(unit)
|
|||||||
|
|
||||||
-- Buff-Laufzeiten: beim Spieler exakt aus der Spielerbuff-API, bei
|
-- Buff-Laufzeiten: beim Spieler exakt aus der Spielerbuff-API, bei
|
||||||
-- anderen nur eigene Casts (oben); weg ist weg. Praesenz merken, damit
|
-- anderen nur eigene Casts (oben); weg ist weg. Praesenz merken, damit
|
||||||
-- die Plakette auch fremde Buffs (ohne Uhr) zeigen kann.
|
-- die Plakette auch fremde Buffs (ohne Uhr) zeigen kann. Jede Variante
|
||||||
|
-- zaehlt nur mit ihrer eigenen Textur; Einzel- und Gruppenbuff fasst erst
|
||||||
|
-- die Anzeige zusammen (FBPredict_BuildBuffOrder). Bis 1.4.7 galt der
|
||||||
|
-- Einzelbuff auch ueber die Textur des Gruppenbuffs als vorhanden und
|
||||||
|
-- umgekehrt, beide Icons erschienen nebeneinander.
|
||||||
if (not FBBuffPresent[name]) then FBBuffPresent[name] = {}; end
|
if (not FBBuffPresent[name]) then FBBuffPresent[name] = {}; end
|
||||||
for spellName, w in pairs(FBPredictWatch) do
|
for _, spellName in ipairs(FBPredictBuffSpells) do
|
||||||
if (w.hasBuff) then
|
local w = FBPredictWatch[spellName];
|
||||||
local present = textures[w.tex] or (w.altTex and textures[w.altTex]);
|
local present = textures[w.tex];
|
||||||
if (FBBuffPresent[name][spellName] ~= present) then FBBuffIconsDirty = true; end
|
if (FBBuffPresent[name][spellName] ~= present) then FBBuffIconsDirty = true; end
|
||||||
FBBuffPresent[name][spellName] = present;
|
FBBuffPresent[name][spellName] = present;
|
||||||
local tracked = FBBuffTimers[name] and FBBuffTimers[name][spellName];
|
local tracked = FBBuffTimers[name] and FBBuffTimers[name][spellName];
|
||||||
if (present and unit == "player") then
|
if (present and unit == "player") then
|
||||||
local left = FBPredict_PlayerBuffTimeLeft(w.tex) or (w.altTex and FBPredict_PlayerBuffTimeLeft(w.altTex));
|
-- nur die Variante, die du wirklich traegst (geteilte Textur)
|
||||||
if (left) then FBPredict_StartBuff(name, spellName, left); end
|
local left, other = FBPredict_PlayerBuffLeft(spellName, w);
|
||||||
|
if (left) then
|
||||||
|
FBPredict_StartBuff(name, spellName, left);
|
||||||
|
elseif (other and tracked) then
|
||||||
|
FBBuffTimers[name][spellName] = nil;
|
||||||
|
FBBuffIconsDirty = true;
|
||||||
|
end
|
||||||
elseif (tracked and not present) then
|
elseif (tracked and not present) then
|
||||||
FBBuffTimers[name][spellName] = nil;
|
FBBuffTimers[name][spellName] = nil;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
-- 2) Generischer Abgleich: Buff da / Buff weg
|
-- 2) Generischer Abgleich: Buff da / Buff weg
|
||||||
for spellName, w in pairs(FBPredictWatch) do
|
for spellName, w in pairs(FBPredictWatch) do
|
||||||
@@ -6508,13 +6858,22 @@ function FBPredict_InitPatterns()
|
|||||||
-- "You gain %d health from your %s."
|
-- "You gain %d health from your %s."
|
||||||
FBPredictPatHoTSelf = FBPredict_ToPattern(PERIODICAURAHEALSELFSELF, true)
|
FBPredictPatHoTSelf = FBPredict_ToPattern(PERIODICAURAHEALSELFSELF, true)
|
||||||
or "^You gain (%d+) health from your (.+)%.$";
|
or "^You gain (%d+) health from your (.+)%.$";
|
||||||
-- "Your %s heals %s for %d." (Crits haben eine eigene Formulierung und
|
-- "Your %s heals %s for %d."
|
||||||
-- laufen deshalb ins Leere, genau so gewollt)
|
|
||||||
FBPredictPatHealOther = FBPredict_ToPattern(HEALEDSELFOTHER, true)
|
FBPredictPatHealOther = FBPredict_ToPattern(HEALEDSELFOTHER, true)
|
||||||
or "^Your (.+) heals (.+) for (%d+)%.$";
|
or "^Your (.+) heals (.+) for (%d+)%.$";
|
||||||
-- "Your %s heals you for %d."
|
-- "Your %s heals you for %d."
|
||||||
FBPredictPatHealSelf = FBPredict_ToPattern(HEALEDSELFSELF, true)
|
FBPredictPatHealSelf = FBPredict_ToPattern(HEALEDSELFSELF, true)
|
||||||
or "^Your (.+) heals you for (%d+)%.$";
|
or "^Your (.+) heals you for (%d+)%.$";
|
||||||
|
-- Crits: "Your %s critically heals %s for %d." und "... heals you for %d."
|
||||||
|
-- Sie werden vor den normalen Mustern geprueft, denn die passen auf diese
|
||||||
|
-- Zeilen ebenfalls, nur mit "Flash Heal critically" als Zaubername. Bis
|
||||||
|
-- 1.4.7 lief ein Crit deshalb ins Leere, und der Cast wartete weiter auf
|
||||||
|
-- seine Zeile: Die naechste Heilung desselben Zaubers auf dasselbe Ziel,
|
||||||
|
-- etwa ein kleiner Rang von der Aktionsleiste, wurde ihm zugeschrieben.
|
||||||
|
FBPredictPatCritOther = FBPredict_ToPattern(HEALEDCRITSELFOTHER, true)
|
||||||
|
or "^Your (.+) critically heals (.+) for (%d+)%.$";
|
||||||
|
FBPredictPatCritSelf = FBPredict_ToPattern(HEALEDCRITSELFSELF, true)
|
||||||
|
or "^Your (.+) critically heals you for (%d+)%.$";
|
||||||
-- " (%d absorbed)"
|
-- " (%d absorbed)"
|
||||||
FBPredictPatAbsorb = FBPredict_ToPattern(ABSORB_TRAILER, false)
|
FBPredictPatAbsorb = FBPredict_ToPattern(ABSORB_TRAILER, false)
|
||||||
or "%((%d+) absorbed%)";
|
or "%((%d+) absorbed%)";
|
||||||
@@ -6524,6 +6883,7 @@ function FBPredict_InitPatterns()
|
|||||||
-- beiden gleich. Ein aus der Fremd-Vorlage geschnittenes " gains " wuerde
|
-- beiden gleich. Ein aus der Fremd-Vorlage geschnittenes " gains " wuerde
|
||||||
-- die eigenen Ticks aussperren.
|
-- die eigenen Ticks aussperren.
|
||||||
FBPRED_WORD_HEAL = FBPredict_PlainPart(HEALEDSELFOTHER, " heals ");
|
FBPRED_WORD_HEAL = FBPredict_PlainPart(HEALEDSELFOTHER, " heals ");
|
||||||
|
FBPRED_WORD_CRIT = FBPredict_PlainPart(HEALEDCRITSELFOTHER, " critically heals ");
|
||||||
FBPRED_WORD_TICK = FBPredict_PlainPart(PERIODICAURAHEALSELFSELF, " health from your ");
|
FBPRED_WORD_TICK = FBPredict_PlainPart(PERIODICAURAHEALSELFSELF, " health from your ");
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -6604,22 +6964,35 @@ function FBPredict_OnTick(unitName, amount, spellName)
|
|||||||
FBHealBox_MarkDirty(unitName);
|
FBHealBox_MarkDirty(unitName);
|
||||||
end
|
end
|
||||||
|
|
||||||
function FBPredict_OnDirectHeal(spellName, targetName, amount)
|
-- Eine Zeile hat ein Ziel des Casts erreicht. Einzelziel: der Cast ist
|
||||||
|
-- erledigt (true). Gruppenheilung: nur dieses Ziel faellt aus der Liste,
|
||||||
|
-- erledigt ist der Cast erst, wenn alle Ziele ihre Zeile hatten.
|
||||||
|
function FBPredict_CastLanded(d, targetName)
|
||||||
|
if (not d.targets) then return true; end
|
||||||
|
d.targets[targetName] = nil;
|
||||||
|
return (next(d.targets) == nil);
|
||||||
|
end
|
||||||
|
|
||||||
|
-- crit = true: Die Zeile schliesst ihren Cast ab wie jede andere, ihr Betrag
|
||||||
|
-- wird aber nicht gelernt (er wuerde die Vorhersage dauerhaft aufblasen).
|
||||||
|
function FBPredict_OnDirectHeal(spellName, targetName, amount, crit)
|
||||||
if (not spellName) or (not amount) then return; end
|
if (not spellName) or (not amount) then return; end
|
||||||
FBLOS_Clear(targetName);
|
FBLOS_Clear(targetName);
|
||||||
local w = FBPredictWatch[spellName];
|
local w = FBPredictWatch[spellName];
|
||||||
if (not w) then return; end -- faengt auch die Crit-Formulierung ab
|
if (not w) then return; end
|
||||||
|
|
||||||
-- Zu welchem Cast gehoert die Zeile? Meist steht sie erst nach dem
|
-- Zu welchem Cast gehoert die Zeile? Meist steht sie erst nach dem
|
||||||
-- Castende (SPELLCAST_STOP) im Combatlog, dann wartet der Cast noch als
|
-- Castende (SPELLCAST_STOP) im Combatlog, dann wartet der Cast noch als
|
||||||
-- FBPredictLastDirect. Kommt sie vorher, ist es der laufende Cast. Bis
|
-- FBPredictLastDirect. Kommt sie vorher, ist es der laufende Cast. Bis
|
||||||
-- 1.4.6 zaehlte nur der laufende, die Selbstkorrektur der
|
-- 1.4.6 zaehlte nur der laufende, die Selbstkorrektur der
|
||||||
-- Direktheilungen griff deshalb kaum.
|
-- Direktheilungen griff deshalb kaum. Beim Castbeginn wird
|
||||||
|
-- FBPredictLastDirect bewusst nicht geleert: Die Zeile des vorigen Casts
|
||||||
|
-- kommt oft erst, wenn der naechste schon laeuft.
|
||||||
local d = FBPredictLastDirect;
|
local d = FBPredictLastDirect;
|
||||||
local fromLast = (d ~= nil) and d.spell == spellName and d.target == targetName
|
local fromLast = (d ~= nil) and d.spell == spellName and FBPredict_CastHits(d, targetName)
|
||||||
and (GetTime() - d.ended) <= FBPREDICT_CLICK_TIME;
|
and (GetTime() - d.ended) <= FBPREDICT_CLICK_TIME;
|
||||||
if (fromLast) then
|
if (fromLast) then
|
||||||
FBPredictLastDirect = nil;
|
if (FBPredict_CastLanded(d, targetName)) then FBPredictLastDirect = nil; end
|
||||||
else
|
else
|
||||||
d = FBPredictDirect;
|
d = FBPredictDirect;
|
||||||
if (d and d.spell ~= spellName) then d = nil; end
|
if (d and d.spell ~= spellName) then d = nil; end
|
||||||
@@ -6628,7 +7001,12 @@ function FBPredict_OnDirectHeal(spellName, targetName, amount)
|
|||||||
-- Nur lernen, wenn der gecastete Rang gesichert ist (Button-Cast).
|
-- Nur lernen, wenn der gecastete Rang gesichert ist (Button-Cast).
|
||||||
-- Ein Downrank von der Aktionsleiste wuerde sonst dem Maximalrang
|
-- Ein Downrank von der Aktionsleiste wuerde sonst dem Maximalrang
|
||||||
-- zugeschrieben und die Vorhersage nach unten ziehen.
|
-- zugeschrieben und die Vorhersage nach unten ziehen.
|
||||||
if (d and d.rankKnown) then
|
if (d and d.rankKnown and crit) then
|
||||||
|
if (FBPredictDebug) then
|
||||||
|
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00[FBP]|r "..format(FBT("DBG_HEAL_CRIT"),
|
||||||
|
spellName, amount));
|
||||||
|
end
|
||||||
|
elseif (d and d.rankKnown) then
|
||||||
local rank = d.rank;
|
local rank = d.rank;
|
||||||
-- Heilungen streuen innerhalb einer Spanne -> sanft einpendeln
|
-- Heilungen streuen innerhalb einer Spanne -> sanft einpendeln
|
||||||
local old = FBPredict_Remembered("direct", spellName, rank);
|
local old = FBPredict_Remembered("direct", spellName, rank);
|
||||||
@@ -6642,8 +7020,10 @@ function FBPredict_OnDirectHeal(spellName, targetName, amount)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (not fromLast) and FBPredictDirect and (FBPredictDirect.target == targetName) then
|
-- Zeile vor dem Castende: Der laufende Cast hat dieses Ziel erreicht
|
||||||
FBPredictDirect = nil;
|
local run = FBPredictDirect;
|
||||||
|
if (not fromLast) and run and run.spell == spellName and FBPredict_CastHits(run, targetName) then
|
||||||
|
if (FBPredict_CastLanded(run, targetName)) then FBPredictDirect = nil; end
|
||||||
end
|
end
|
||||||
FBHealBox_MarkDirty(targetName);
|
FBHealBox_MarkDirty(targetName);
|
||||||
end
|
end
|
||||||
@@ -6702,7 +7082,20 @@ function FBPredict_ParseCombat(event, msg)
|
|||||||
-- Argument true = einfache Suche ohne Musterlogik). Fremde Heilungen und
|
-- Argument true = einfache Suche ohne Musterlogik). Fremde Heilungen und
|
||||||
-- fremde Ticks fallen so nach einem Vergleich raus statt nach vier
|
-- fremde Ticks fallen so nach einem Vergleich raus statt nach vier
|
||||||
-- Musterlaeufen; im Raid sind das die meisten Meldungen.
|
-- Musterlaeufen; im Raid sind das die meisten Meldungen.
|
||||||
if (string.find(msg, FBPRED_WORD_HEAL, 1, true)) then
|
if (string.find(msg, FBPRED_WORD_HEAL, 1, true) or string.find(msg, FBPRED_WORD_CRIT, 1, true)) then
|
||||||
|
-- Crits zuerst, sonst halten die normalen Muster "Flash Heal
|
||||||
|
-- critically" fuer den Zaubernamen
|
||||||
|
local _, _, spellC, amtC = string.find(msg, FBPredictPatCritSelf);
|
||||||
|
if (spellC and amtC) then
|
||||||
|
FBPredict_OnDirectHeal(spellC, UnitName("player"), tonumber(amtC), true);
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
local _, _, spellD, whoD, amtD = string.find(msg, FBPredictPatCritOther);
|
||||||
|
if (spellD and whoD and amtD) then
|
||||||
|
FBPredict_OnDirectHeal(spellD, whoD, tonumber(amtD), true);
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
-- Direktheilung auf mich: "Your Flash Heal heals you for 1240."
|
-- Direktheilung auf mich: "Your Flash Heal heals you for 1240."
|
||||||
-- Zuerst pruefen: Das Muster fuer andere passt auf diese Zeile
|
-- Zuerst pruefen: Das Muster fuer andere passt auf diese Zeile
|
||||||
-- ebenfalls und lieferte bis 1.4.6 "you" als Ziel. Die eigene
|
-- ebenfalls und lieferte bis 1.4.6 "you" als Ziel. Die eigene
|
||||||
@@ -6799,19 +7192,13 @@ FBPredictFrame:SetScript("OnEvent", function()
|
|||||||
-- Der geklickte Zauber laeuft an: Die Sicht kann noch am Castende
|
-- Der geklickte Zauber laeuft an: Die Sicht kann noch am Castende
|
||||||
-- fehlen, sein Ziel bleibt bis dahin Kandidat. Ein anderer Zauber
|
-- fehlen, sein Ziel bleibt bis dahin Kandidat. Ein anderer Zauber
|
||||||
-- gehoert nicht zu diesem Klick.
|
-- gehoert nicht zu diesem Klick.
|
||||||
if (FBLOSCandidate) then
|
FBLOS_CastStart(arg1, tonumber(arg2));
|
||||||
if (arg1 == FBLOSCandidateSpell) then
|
|
||||||
FBLOSCandidateUntil = GetTime() + (tonumber(arg2) or 0) / 1000 + FBLOS_ERROR_WINDOW;
|
|
||||||
else
|
|
||||||
FBLOSCandidate = nil;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
FBPredict_CastStart(arg1, tonumber(arg2));
|
FBPredict_CastStart(arg1, tonumber(arg2));
|
||||||
|
|
||||||
elseif (event == "SPELLCAST_STOP") then
|
elseif (event == "SPELLCAST_STOP") then
|
||||||
-- Erfolgreich beendet: HealComm-Empfaenger lassen den Eintrag
|
-- Erfolgreich beendet: HealComm-Empfaenger lassen den Eintrag
|
||||||
-- selbst auslaufen, hier wird bewusst kein Healstop gefunkt.
|
-- selbst auslaufen, hier wird bewusst kein Healstop gefunkt.
|
||||||
FBLOSCandidate = nil; -- Cast ging durch, die Sicht war da
|
FBLOS_CastDone(); -- Cast ging durch, die Sicht war da
|
||||||
FBPredict_ClickDone();
|
FBPredict_ClickDone();
|
||||||
FBPredict_ConfirmBuffRefresh();
|
FBPredict_ConfirmBuffRefresh();
|
||||||
FBPredict_CastEnd(true);
|
FBPredict_CastEnd(true);
|
||||||
@@ -6819,15 +7206,13 @@ FBPredictFrame:SetScript("OnEvent", function()
|
|||||||
elseif (event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED") then
|
elseif (event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED") then
|
||||||
-- Nach FAILED kann die Sichtlinien-Meldung noch folgen, nach einer
|
-- Nach FAILED kann die Sichtlinien-Meldung noch folgen, nach einer
|
||||||
-- Unterbrechung (Bewegung, Unterbrechungszauber) nicht mehr
|
-- Unterbrechung (Bewegung, Unterbrechungszauber) nicht mehr
|
||||||
if (event == "SPELLCAST_INTERRUPTED") then FBLOSCandidate = nil; end
|
if (event == "SPELLCAST_INTERRUPTED") then FBLOS_Reset(); end
|
||||||
FBPredict_ClickFailed(event == "SPELLCAST_INTERRUPTED");
|
FBPredict_ClickFailed(event == "SPELLCAST_INTERRUPTED");
|
||||||
if (FBPredictDirect) then FBComm_SendHealStop(); end
|
if (FBPredictDirect) then FBComm_SendHealStop(); end
|
||||||
FBPredict_CastEnd(false);
|
FBPredict_CastEnd(false);
|
||||||
|
|
||||||
elseif (event == "SPELLCAST_DELAYED") then
|
elseif (event == "SPELLCAST_DELAYED") then
|
||||||
if (FBLOSCandidate and arg1) then
|
if (arg1) then FBLOS_CastDelayed(arg1); end
|
||||||
FBLOSCandidateUntil = FBLOSCandidateUntil + (tonumber(arg1) or 0) / 1000;
|
|
||||||
end
|
|
||||||
if (FBPredictCastUntil > 0 and arg1) then
|
if (FBPredictCastUntil > 0 and arg1) then
|
||||||
FBPredictCastUntil = FBPredictCastUntil + (tonumber(arg1) or 0) / 1000;
|
FBPredictCastUntil = FBPredictCastUntil + (tonumber(arg1) or 0) / 1000;
|
||||||
end
|
end
|
||||||
@@ -6990,7 +7375,7 @@ function FBPredict_Expire()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (FBPredictDirect and now > FBPredictDirect.finish) then
|
if (FBPredictDirect and now > FBPredictDirect.finish) then
|
||||||
FBHealBox_MarkDirty(FBPredictDirect.target);
|
FBPredict_MarkCastDirty(FBPredictDirect);
|
||||||
FBPredictDirect = nil;
|
FBPredictDirect = nil;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
end
|
end
|
||||||
@@ -7109,7 +7494,9 @@ end
|
|||||||
|
|
||||||
-- [ Senden ] ---------------------------------------------------------------
|
-- [ Senden ] ---------------------------------------------------------------
|
||||||
|
|
||||||
function FBComm_SendHealStart(spellName, target, amount, castMs)
|
-- groupList: Ziele einer Gruppenheilung, wie sie FBPredict_CastStart schon
|
||||||
|
-- fuer die eigene Vorhersage bestimmt hat (sonst hier ermittelt)
|
||||||
|
function FBComm_SendHealStart(spellName, target, amount, castMs, groupList)
|
||||||
if (not FBComm_Enabled()) or (not target) then return; end
|
if (not FBComm_Enabled()) or (not target) then return; end
|
||||||
|
|
||||||
amount = math.floor(amount or 0);
|
amount = math.floor(amount or 0);
|
||||||
@@ -7118,12 +7505,9 @@ function FBComm_SendHealStart(spellName, target, amount, castMs)
|
|||||||
|
|
||||||
if (FBCommGroupHeal[spellName]) then
|
if (FBCommGroupHeal[spellName]) then
|
||||||
-- Gruppenheilung: alle Ziele in Reichweite mitschicken
|
-- Gruppenheilung: alle Ziele in Reichweite mitschicken
|
||||||
local names = UnitName("player").."/";
|
local names = "";
|
||||||
for i = 1, 4 do
|
for _, n in ipairs(groupList or FBPredict_GroupTargets()) do
|
||||||
local u = "party"..i;
|
names = names..n.."/";
|
||||||
if (UnitExists(u) and CheckInteractDistance(u, 4)) then
|
|
||||||
names = names..UnitName(u).."/";
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
FBCommSentGroup = true;
|
FBCommSentGroup = true;
|
||||||
FBComm_Send("GrpHeal/"..amount.."/"..castMs.."/"..names);
|
FBComm_Send("GrpHeal/"..amount.."/"..castMs.."/"..names);
|
||||||
@@ -7355,20 +7739,22 @@ SlashCmdList["FBHEALPREDICT"] = function(msg)
|
|||||||
|
|
||||||
if (msg == "buffs") then
|
if (msg == "buffs") then
|
||||||
-- Diagnose: ueberwachte Buffs und ihr Zustand auf dem Spieler
|
-- Diagnose: ueberwachte Buffs und ihr Zustand auf dem Spieler
|
||||||
|
-- icon=ja: der Buff (oder seine Gruppenversion) liegt auf einem
|
||||||
|
-- Button und bekommt ein Icon; family nennt die gemeinsame Familie
|
||||||
local me = UnitName("player");
|
local me = UnitName("player");
|
||||||
local any = false;
|
for _, spellName in ipairs(FBPredictBuffSpells) do
|
||||||
for spellName, w in pairs(FBPredictWatch) do
|
local w = FBPredictWatch[spellName];
|
||||||
if (w.hasBuff) then
|
|
||||||
any = true;
|
|
||||||
local present = FBBuffPresent[me] and FBBuffPresent[me][spellName];
|
local present = FBBuffPresent[me] and FBBuffPresent[me][spellName];
|
||||||
local bt = FBBuffTimers[me] and FBBuffTimers[me][spellName];
|
local bt = FBBuffTimers[me] and FBBuffTimers[me][spellName];
|
||||||
local left = "-";
|
local left = "-";
|
||||||
if (bt) then left = math.floor(bt.expires - GetTime()).."s"; end
|
if (bt) then left = math.floor(bt.expires - GetTime()).."s"; end
|
||||||
|
local fam = FBPredictBuffShown[spellName];
|
||||||
|
local iconInfo = " icon=no";
|
||||||
|
if (fam) then iconInfo = " icon=yes family="..fam; end
|
||||||
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[FBP]|r buff "..spellName.." ("..(w.buffSecs or 0).."s) tex="..tostring(w.tex)
|
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[FBP]|r buff "..spellName.." ("..(w.buffSecs or 0).."s) tex="..tostring(w.tex)
|
||||||
.." present="..tostring(present ~= nil and present or false).." left="..left);
|
.." present="..tostring(present ~= nil and present or false).." left="..left..iconInfo);
|
||||||
end
|
end
|
||||||
end
|
if (table.getn(FBPredictWatchBuffOrder) == 0) then DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[FBP]|r no buff spells on the buttons (assign e.g. Power Word: Fortitude)"); end
|
||||||
if (not any) then DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[FBP]|r no buff spells on the buttons (assign e.g. Power Word: Fortitude)"); end
|
|
||||||
if (FBHealBox1 and FBHealBox1.buffIcons) then
|
if (FBHealBox1 and FBHealBox1.buffIcons) then
|
||||||
for k, ic in ipairs(FBHealBox1.buffIcons) do
|
for k, ic in ipairs(FBHealBox1.buffIcons) do
|
||||||
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[FBP]|r icon "..k..": shown="..tostring(ic:IsShown() and true or false)
|
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[FBP]|r icon "..k..": shown="..tostring(ic:IsShown() and true or false)
|
||||||
@@ -7679,9 +8065,30 @@ function FBHealBox_SetBuffIconProgress(ic, remaining)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Welche Variante einer Buff-Familie zeigt das Icon? Die Einheit traegt in
|
||||||
|
-- Vanilla hoechstens eine davon, denn Einzel- und Gruppenbuff ersetzen
|
||||||
|
-- einander. Manche Paare teilen sich aber die Textur (Mal der Wildnis und
|
||||||
|
-- Gabe der Wildnis), dann gelten beide als vorhanden. Den Ausschlag gibt die
|
||||||
|
-- Uhr: eine Variante mit laufender Uhr, deren Dauer die Restzeit fasst, und
|
||||||
|
-- davon die kuerzeste. Ohne Uhr die erste vorhandene. nil = keine.
|
||||||
|
function FBHealBox_PickBuffVariant(variants, present, timers, now)
|
||||||
|
local first, best, bestSecs = nil, nil, nil;
|
||||||
|
for _, v in ipairs(variants) do
|
||||||
|
if (present[v]) then
|
||||||
|
if (not first) then first = v; end
|
||||||
|
local bt = timers and timers[v];
|
||||||
|
local secs = FBPredictWatch[v].buffSecs or 0;
|
||||||
|
if (bt and bt.expires > now and secs + 1 >= bt.expires - now) then
|
||||||
|
if (not best) or (secs < bestSecs) then best = v; bestSecs = secs; end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return best or first;
|
||||||
|
end
|
||||||
|
|
||||||
-- Zu zeigende Buffs einer Einheit in die Arbeits-Tabelle out schreiben
|
-- Zu zeigende Buffs einer Einheit in die Arbeits-Tabelle out schreiben
|
||||||
-- (wiederverwendet, keine neuen Tabellen je Tick). Liefert die Anzahl.
|
-- (wiederverwendet, keine neuen Tabellen je Tick). Liefert die Anzahl.
|
||||||
-- Reihenfolge: FBPredictWatchBuffOrder (einmal in BuildWatch sortiert).
|
-- Reihenfolge: FBPredictWatchBuffOrder, je Familie ein Icon.
|
||||||
function FBHealBox_BuffIconList(unitName, g, out)
|
function FBHealBox_BuffIconList(unitName, g, out)
|
||||||
local n = 0;
|
local n = 0;
|
||||||
if (g) then
|
if (g) then
|
||||||
@@ -7697,8 +8104,10 @@ function FBHealBox_BuffIconList(unitName, g, out)
|
|||||||
local present = FBBuffPresent[unitName];
|
local present = FBBuffPresent[unitName];
|
||||||
if (not present) then return 0; end
|
if (not present) then return 0; end
|
||||||
local timers = FBBuffTimers[unitName];
|
local timers = FBBuffTimers[unitName];
|
||||||
for _, spellName in ipairs(FBPredictWatchBuffOrder) do
|
local now = GetTime();
|
||||||
if (present[spellName]) then
|
for _, fam in ipairs(FBPredictWatchBuffOrder) do
|
||||||
|
local spellName = FBHealBox_PickBuffVariant(FBPredictBuffFamily[fam], present, timers, now);
|
||||||
|
if (spellName) then
|
||||||
local w = FBPredictWatch[spellName];
|
local w = FBPredictWatch[spellName];
|
||||||
local bt = timers and timers[spellName];
|
local bt = timers and timers[spellName];
|
||||||
n = n + 1;
|
n = n + 1;
|
||||||
@@ -7773,17 +8182,20 @@ function FBPredict_RefreshPlayerBuffs(elapsed)
|
|||||||
local me = UnitName("player");
|
local me = UnitName("player");
|
||||||
if (not me) or (not FBBuffPresent[me]) then return; end
|
if (not me) or (not FBBuffPresent[me]) then return; end
|
||||||
local timers = FBBuffTimers[me];
|
local timers = FBBuffTimers[me];
|
||||||
for _, spellName in ipairs(FBPredictWatchBuffOrder) do
|
for _, spellName in ipairs(FBPredictBuffSpells) do
|
||||||
if (FBBuffPresent[me][spellName]) then
|
if (FBBuffPresent[me][spellName]) then
|
||||||
local w = FBPredictWatch[spellName];
|
local w = FBPredictWatch[spellName];
|
||||||
local left = FBPredict_PlayerBuffTimeLeft(w.tex);
|
local left, other = FBPredict_PlayerBuffLeft(spellName, w);
|
||||||
|
local t = timers and timers[spellName];
|
||||||
if (left) then
|
if (left) then
|
||||||
-- nur uebernehmen, wenn die API mehr als eine Sekunde von der
|
-- nur uebernehmen, wenn die API mehr als eine Sekunde von der
|
||||||
-- eigenen Uhr abweicht (Refresh); sonst kein Dirty-Flag
|
-- eigenen Uhr abweicht (Refresh); sonst kein Dirty-Flag
|
||||||
local t = timers and timers[spellName];
|
|
||||||
if (not t) or (math.abs((t.expires - GetTime()) - left) > 1.0) then
|
if (not t) or (math.abs((t.expires - GetTime()) - left) > 1.0) then
|
||||||
FBPredict_StartBuff(me, spellName, left);
|
FBPredict_StartBuff(me, spellName, left);
|
||||||
end
|
end
|
||||||
|
elseif (other and t) then
|
||||||
|
timers[spellName] = nil;
|
||||||
|
FBBuffIconsDirty = true;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
## Interface: 11200
|
## Interface: 11200
|
||||||
## Title: Heal Box Vanilla |cFFFFFF00v1.4.7|r
|
## Title: Heal Box Vanilla |cFFFFFF00v1.4.7.1|r
|
||||||
## Notes: Heal/raid frame addon like Healium, with quick-cast buttons, heal prediction, mana ticker and more.
|
## 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.
|
## 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
|
## Author: Dourd (Argent Dawn EU) | Vanilla-Port & Erweiterung 09/2026: Mquadrat
|
||||||
## Version: 1.4.7
|
## Version: 1.4.7.1
|
||||||
## SavedVariablesPerCharacter: HealBox
|
## SavedVariablesPerCharacter: HealBox
|
||||||
# SuperWoW ist eine Client-Erweiterung, kein Addon. OptionalDeps wirkt darauf
|
# SuperWoW ist eine Client-Erweiterung, kein Addon. OptionalDeps wirkt darauf
|
||||||
# nicht; das Addon erkennt SuperWoW zur Laufzeit.
|
# nicht; das Addon erkennt SuperWoW zur Laufzeit.
|
||||||
|
|||||||
+57
-18
@@ -19,9 +19,10 @@
|
|||||||
-- gemessen noch geschaetzt: Der Combatlog zeigt den Schaden der anderen
|
-- gemessen noch geschaetzt: Der Combatlog zeigt den Schaden der anderen
|
||||||
-- Raidgruppen nicht vollstaendig, jede Messung fiele dort zu niedrig aus.
|
-- Raidgruppen nicht vollstaendig, jede Messung fiele dort zu niedrig aus.
|
||||||
--
|
--
|
||||||
-- Schaden je Rang: Mindestschaden aus dem Tooltip ("86 to 98 Holy damage"),
|
-- Schaden je Rang: Mindestschaden aus dem Tooltip ("86 to 98 Holy damage",
|
||||||
-- angehoben um den Bonus, den der kleinste eigene Treffer ohne Crit und
|
-- "for 11 Fire damage", "causes 13 Arcane damage"), angehoben um den Bonus,
|
||||||
-- Teilwiderstand beweist (FBDmg_MinDamage). Entscheidung:
|
-- den der kleinste eigene normale Treffer beweist (FBDmg_MinDamage).
|
||||||
|
-- Entscheidung:
|
||||||
-- Mindestschaden >= Ziel-Leben (bei Prozent: Obergrenze) x (1 + Aufschlag).
|
-- Mindestschaden >= Ziel-Leben (bei Prozent: Obergrenze) x (1 + Aufschlag).
|
||||||
-- ==========================================================================
|
-- ==========================================================================
|
||||||
|
|
||||||
@@ -39,7 +40,9 @@ FBDamageDefaults = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
-- Angriffszauber je Klasse (englische Zaubernamen wie im ganzen Addon).
|
-- Angriffszauber je Klasse (englische Zaubernamen wie im ganzen Addon).
|
||||||
-- Kanalisierte, reine DoTs und Flaechenzauber bleiben draussen.
|
-- Kanalisierte, reine DoTs und Flaechenzauber bleiben draussen, ebenso
|
||||||
|
-- Schuesse mit Waffenschaden (Aimed Shot: "increases ranged damage by 70").
|
||||||
|
-- Deren Schaden steht nicht im Tooltip, sondern haengt an der Waffe.
|
||||||
FBDamageSpells = {
|
FBDamageSpells = {
|
||||||
Priest = { "Smite", "Holy Fire", "Mind Blast" },
|
Priest = { "Smite", "Holy Fire", "Mind Blast" },
|
||||||
Druid = { "Wrath", "Starfire", "Moonfire" },
|
Druid = { "Wrath", "Starfire", "Moonfire" },
|
||||||
@@ -47,7 +50,7 @@ FBDamageSpells = {
|
|||||||
Paladin = { "Holy Shock", "Hammer of Wrath", "Exorcism", "Holy Wrath" },
|
Paladin = { "Holy Shock", "Hammer of Wrath", "Exorcism", "Holy Wrath" },
|
||||||
Mage = { "Fireball", "Frostbolt", "Fire Blast", "Scorch", "Pyroblast" },
|
Mage = { "Fireball", "Frostbolt", "Fire Blast", "Scorch", "Pyroblast" },
|
||||||
Warlock = { "Shadow Bolt", "Searing Pain", "Immolate", "Soul Fire", "Conflagrate" },
|
Warlock = { "Shadow Bolt", "Searing Pain", "Immolate", "Soul Fire", "Conflagrate" },
|
||||||
Hunter = { "Arcane Shot", "Aimed Shot" },
|
Hunter = { "Arcane Shot" },
|
||||||
};
|
};
|
||||||
|
|
||||||
-- ==========================================================================
|
-- ==========================================================================
|
||||||
@@ -215,6 +218,17 @@ end
|
|||||||
-- [ Zauberbuch: Raenge und Schaden ]
|
-- [ Zauberbuch: Raenge und Schaden ]
|
||||||
-- ==========================================================================
|
-- ==========================================================================
|
||||||
|
|
||||||
|
-- Fester Schaden in der Form "causes 13 Arcane damage" (Arcane Shot) oder
|
||||||
|
-- "causing 25 Fire damage immediately" (Flame Shock). Beide Tooltips nennen
|
||||||
|
-- weder "X to Y" noch "for X"; bis 1.4.7 fanden sich deshalb fuer den Jaeger
|
||||||
|
-- gar keine Zauber, und Flame Shock fehlte beim Schamanen.
|
||||||
|
function FBDmg_FindCauseAmount(txt)
|
||||||
|
if (not txt) then return nil; end
|
||||||
|
local _, _, n = string.find(txt, "[Cc]aus%a*%s+(%d+)%s+%a+%s+[Dd]amage");
|
||||||
|
if (n) then return tonumber(n); end
|
||||||
|
return nil;
|
||||||
|
end
|
||||||
|
|
||||||
function FBDmg_ScanSpells()
|
function FBDmg_ScanSpells()
|
||||||
FBDmgSpellRanks = {};
|
FBDmgSpellRanks = {};
|
||||||
local wanted = {};
|
local wanted = {};
|
||||||
@@ -227,7 +241,7 @@ function FBDmg_ScanSpells()
|
|||||||
local txt = FBPredict_TooltipText(i) or "";
|
local txt = FBPredict_TooltipText(i) or "";
|
||||||
local lo, hi = FBPredict_FindAmountRange(txt);
|
local lo, hi = FBPredict_FindAmountRange(txt);
|
||||||
if (not lo) then
|
if (not lo) then
|
||||||
lo = FBPredict_FindAmountSingle(txt);
|
lo = FBPredict_FindAmountSingle(txt) or FBDmg_FindCauseAmount(txt);
|
||||||
hi = lo;
|
hi = lo;
|
||||||
end
|
end
|
||||||
local isDamage = (string.find(txt, "[Dd]amage") or string.find(txt, "[Ss]chaden")) ~= nil;
|
local isDamage = (string.find(txt, "[Dd]amage") or string.find(txt, "[Ss]chaden")) ~= nil;
|
||||||
@@ -242,15 +256,24 @@ function FBDmg_ScanSpells()
|
|||||||
FBDmgSpellsDirty = false;
|
FBDmgSpellsDirty = false;
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mindestschaden eines Rangs. Gelernt wird der kleinste eigene Treffer ohne
|
-- Mindestschaden eines Rangs. Gelernt wird der kleinste eigene normale
|
||||||
-- Crit und Teilwiderstand. Jeder Treffer liegt hoechstens beim Hoechstwert
|
-- Treffer (ohne Crit, Teilwiderstand, Absorb, Block und Verwundbarkeits-
|
||||||
-- des Tooltips plus Bonus, der Bonus ist also mindestens Treffer minus
|
-- bonus). Jeder Treffer liegt hoechstens beim Hoechstwert des Tooltips plus
|
||||||
-- Hoechstwert, und so viel liegt sicher auch auf dem Minimum. Der kleinste
|
-- Bonus, der Bonus ist also mindestens Treffer minus Hoechstwert, und so viel
|
||||||
-- Treffer, weil Verstaerker wie Curse of Shadow oder Power Infusion nur
|
-- liegt sicher auch auf dem Minimum. Der kleinste Treffer, weil Verstaerker
|
||||||
-- manche Treffer heben; ein einzelner verstaerkter Treffer darf den Wert
|
-- wie Curse of Shadow oder Power Infusion nur manche Treffer heben; ein
|
||||||
-- nicht dauerhaft hochziehen. Bis 1.4.6 galt der kleinste Treffer selbst als
|
-- einzelner verstaerkter Treffer darf den Wert nicht dauerhaft hochziehen.
|
||||||
-- Mindestschaden; nach einem einzigen hohen Wurf lag er ueber dem echten
|
-- Bis 1.4.6 galt der kleinste Treffer selbst als Mindestschaden; nach einem
|
||||||
-- Minimum, und der gewaehlte Rang toetete nicht.
|
-- einzigen hohen Wurf lag er ueber dem echten Minimum, und der gewaehlte Rang
|
||||||
|
-- toetete nicht.
|
||||||
|
--
|
||||||
|
-- Abgezogen wird die Tooltipspanne genau einmal: Sie steckt im kleinsten
|
||||||
|
-- Treffer nur als unbekannter Wurf. Mit vielen Treffern rutscht der kleinste
|
||||||
|
-- Treffer an Minimum plus Bonus heran, die Grenze liegt dann bis zu einer
|
||||||
|
-- Spanne unter dem echten Minimum (bei Frostbolt Rang 11 sind das 40 von
|
||||||
|
-- rund 750 Punkten). Das ist der Preis dafuer, dass die Grenze bewiesen ist;
|
||||||
|
-- der groesste Treffer gaebe den genaueren Wert, aber ein einziger
|
||||||
|
-- verstaerkter Treffer machte ihn falsch.
|
||||||
function FBDmg_MinDamage(spell, entry)
|
function FBDmg_MinDamage(spell, entry)
|
||||||
local learned = HealBox.DmgMemory and HealBox.DmgMemory[spell.."|"..entry.rank];
|
local learned = HealBox.DmgMemory and HealBox.DmgMemory[spell.."|"..entry.rank];
|
||||||
if (not learned) then return entry.min; end
|
if (not learned) then return entry.min; end
|
||||||
@@ -400,6 +423,22 @@ function FBDmg_ParseLine(msg)
|
|||||||
return nil;
|
return nil;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Nur ein normaler Treffer taugt zum Lernen. Crit und Verwundbarkeitsbonus
|
||||||
|
-- (" (+12 vulnerability bonus)") heben den Treffer an; ein angehobener erster
|
||||||
|
-- Treffer koennte den gelernten Mindestschaden ueber das echte Minimum
|
||||||
|
-- schieben, dann toetete der gewaehlte Rang nicht. Teilwiderstand, Absorb
|
||||||
|
-- und Block senken ihn nur, das ist sicher, aber kein Wurf des Zaubers: die
|
||||||
|
-- Grenze fiele ohne Not. Bis 1.4.7 wurden nur Crit und Teilwiderstand
|
||||||
|
-- ausgeschlossen.
|
||||||
|
FBDmgHitMarks = { "crits", "resisted", "absorbed", "blocked", "vulnerability" };
|
||||||
|
|
||||||
|
function FBDmg_IsPlainHit(msg)
|
||||||
|
for _, mark in ipairs(FBDmgHitMarks) do
|
||||||
|
if (string.find(msg, mark, 1, true)) then return false; end
|
||||||
|
end
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
|
||||||
function FBDmg_OnCombatLog(msg)
|
function FBDmg_OnCombatLog(msg)
|
||||||
-- Nur arbeiten, wenn Smart Damage an ist und es etwas zu lernen gibt
|
-- Nur arbeiten, wenn Smart Damage an ist und es etwas zu lernen gibt
|
||||||
-- (Prozentziel wird vermessen oder ein eigener Cast wartet auf Treffer).
|
-- (Prozentziel wird vermessen oder ein eigener Cast wartet auf Treffer).
|
||||||
@@ -408,11 +447,11 @@ function FBDmg_OnCombatLog(msg)
|
|||||||
local victim, amount, spell, who = FBDmg_ParseLine(msg);
|
local victim, amount, spell, who = FBDmg_ParseLine(msg);
|
||||||
if (not victim) then return; end
|
if (not victim) then return; end
|
||||||
FBDmg_NoteDamage(victim, amount);
|
FBDmg_NoteDamage(victim, amount);
|
||||||
-- Kleinsten Treffer lernen (siehe FBDmg_MinDamage): eigener Zauber, kein
|
-- Kleinsten Treffer lernen (siehe FBDmg_MinDamage): eigener Zauber, nur
|
||||||
-- Crit, kein Teilwiderstand
|
-- ein normaler Treffer
|
||||||
if (who == "self" and spell and FBDmgLastCast and FBDmgLastCast.spell == spell
|
if (who == "self" and spell and FBDmgLastCast and FBDmgLastCast.spell == spell
|
||||||
and (GetTime() - FBDmgLastCast.t) <= FBDMG_LASTCAST_SEC
|
and (GetTime() - FBDmgLastCast.t) <= FBDMG_LASTCAST_SEC
|
||||||
and not string.find(msg, "crits") and not string.find(msg, "resisted")) then
|
and FBDmg_IsPlainHit(msg)) then
|
||||||
local key = spell.."|"..(FBDmgLastCast.rank or "");
|
local key = spell.."|"..(FBDmgLastCast.rank or "");
|
||||||
if (not HealBox.DmgMemory) then HealBox.DmgMemory = {}; end
|
if (not HealBox.DmgMemory) then HealBox.DmgMemory = {}; end
|
||||||
local old = HealBox.DmgMemory[key];
|
local old = HealBox.DmgMemory[key];
|
||||||
|
|||||||
@@ -1261,6 +1261,10 @@ FBRaidEventFrame:RegisterEvent("UNIT_MANA");
|
|||||||
FBRaidEventFrame:RegisterEvent("UNIT_MAXMANA");
|
FBRaidEventFrame:RegisterEvent("UNIT_MAXMANA");
|
||||||
FBRaidEventFrame:RegisterEvent("UNIT_DISPLAYPOWER");
|
FBRaidEventFrame:RegisterEvent("UNIT_DISPLAYPOWER");
|
||||||
FBRaidEventFrame:RegisterEvent("UNIT_AURA");
|
FBRaidEventFrame:RegisterEvent("UNIT_AURA");
|
||||||
|
-- Namen, die beim Laden noch als Unbekannt kamen, reichen nach. Bis 1.4.7
|
||||||
|
-- blieb eine solche Zelle bis zum naechsten Rosterwechsel falsch beschriftet
|
||||||
|
-- und war ueber ihren Namen (FBRaidNameCell, Vorhersage) nicht zu finden.
|
||||||
|
FBRaidEventFrame:RegisterEvent("UNIT_NAME_UPDATE");
|
||||||
-- Wut, Energie und Fokus (nur mit "Wut, Energie, Fokus zeigen" ausgewertet)
|
-- Wut, Energie und Fokus (nur mit "Wut, Energie, Fokus zeigen" ausgewertet)
|
||||||
for ev in pairs(FBPowerEvents) do FBRaidEventFrame:RegisterEvent(ev); end
|
for ev in pairs(FBPowerEvents) do FBRaidEventFrame:RegisterEvent(ev); end
|
||||||
|
|
||||||
@@ -1275,6 +1279,15 @@ FBRaidEventFrame:SetScript("OnEvent", function()
|
|||||||
return;
|
return;
|
||||||
end
|
end
|
||||||
if (FBRaidTestMode > 0) then return; end
|
if (FBRaidTestMode > 0) then return; end
|
||||||
|
if (event == "UNIT_NAME_UPDATE") then
|
||||||
|
-- Nur Raid-Einheiten, und nur wenn sich der Name wirklich geaendert
|
||||||
|
-- hat; der Umbau laeuft wie bei Rosterwechseln im naechsten Frame
|
||||||
|
if (arg1 and string.find(arg1, "^raid%d") and FBRaid_IsActive()) then
|
||||||
|
local cell = FBRaidUnitCell[arg1];
|
||||||
|
if (not cell) or (cell.name ~= UnitName(arg1)) then FBRaidRosterDirty = true; end
|
||||||
|
end
|
||||||
|
return;
|
||||||
|
end
|
||||||
if (FBPowerEvents[event] and HealBox.PowerBar ~= 1) then return; end
|
if (FBPowerEvents[event] and HealBox.PowerBar ~= 1) then return; end
|
||||||
local c = FBRaidUnitCell[arg1];
|
local c = FBRaidUnitCell[arg1];
|
||||||
if (not c) then return; end
|
if (not c) then return; end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Heal Box Vanilla
|
# Heal Box Vanilla
|
||||||
|
|
||||||
ADDON DOCUMENTATION · VERSION 1.4.7 · World of Warcraft CLIENT 1.12.1
|
ADDON DOCUMENTATION · VERSION 1.4.7.1 · 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.
|
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.
|
||||||
|
|
||||||
@@ -10,7 +10,8 @@ Party, pet and self heal display with quick-cast buttons for healers. One name p
|
|||||||
|
|
||||||
<img width="956" height="847" alt="Screenshot 2026-09-05 210241" src="https://github.com/user-attachments/assets/d7508232-eb56-47ef-8f7e-c39ab0c2b434" />
|
<img width="956" height="847" alt="Screenshot 2026-09-05 210241" src="https://github.com/user-attachments/assets/d7508232-eb56-47ef-8f7e-c39ab0c2b434" />
|
||||||
|
|
||||||
<img width="845" height="1105" alt="grafik" src="https://github.com/user-attachments/assets/fef5d825-0c5c-4710-8994-b51e4712ceb2" />
|
<img width="843" height="1105" alt="Screenshot 2026-10-08 165554" src="https://github.com/user-attachments/assets/989adb05-28b3-4eb3-8212-ef01286f81ab" />
|
||||||
|
|
||||||
|
|
||||||
\---
|
\---
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ If your current hostile target is targeting a group member, that member's plate
|
|||||||
|
|
||||||
### Line of sight
|
### Line of sight
|
||||||
|
|
||||||
While a unit is out of your line of sight an **eye badge** (`FBLOS_ICON`, the Blind icon) sits on the top-left corner of its plate. Vanilla has no API for this, so two paths are used: with the **UnitXP SP3** client mod installed the addon asks `UnitXP("inSight", "player", unit)` every half second, live and exact. Without it, the addon watches for the *not in line of sight* error after a click on one of your Heal Box buttons and marks that button's unit for `FBLOS_TIMEOUT` (8) seconds; the mark is cleared as soon as a cast on that unit starts or one of your direct heals lands on it. A tick of your HoT leaves it alone, because ticks need no line of sight. The error has to answer that very click: it counts for up to `FBLOS_ERROR_WINDOW` (1) second after the click, and for a spell with a cast time until one second after the cast ends, because the server checks line of sight again when the cast finishes. A cast that goes through, a cast that is interrupted, another error message or another spell starting ends the wait. Errors from spells on your action bars therefore mark nobody, and your own plate is never marked. `/fbp` reports which path is active. Option *Line of sight*; badge position via `FBLOS_ICON_X/Y`.
|
While a unit is out of your line of sight an **eye badge** (`FBLOS_ICON`, the Blind icon) sits on the top-left corner of its plate. Vanilla has no API for this, so two paths are used: with the **UnitXP SP3** client mod installed the addon asks `UnitXP("inSight", "player", unit)` every half second, live and exact. Without it, the addon watches for the *not in line of sight* error after a click on one of your Heal Box buttons and marks that button's unit for `FBLOS_TIMEOUT` (8) seconds; the mark is cleared as soon as a cast on that unit starts or one of your direct heals lands on it. A tick of your HoT leaves it alone, because ticks need no line of sight. The error has to answer that very click: it counts for up to `FBLOS_ERROR_WINDOW` (1) second after the click, and for a spell with a cast time until one second after the cast ends, because the server checks line of sight again when the cast finishes. A cast that goes through, a cast that is interrupted, another error message or another spell starting ends the wait. A further click while a cast is still running does not: it gets its own wait, and its answer (*Another action is in progress*) leaves the running cast's claim alone, so a line of sight error at the end of that cast still marks its unit. A click that a client spell queue (such as Nampower) holds back gets no answer during the cast; it stays a candidate after the cast ends and waits for its own spell. A click counts for a cast only if that cast starts within `FBPREDICT_CLICK_TIME` (2) seconds. Errors from spells on your action bars therefore mark nobody, and your own plate is never marked. `/fbp` reports which path is active. Option *Line of sight*; badge position via `FBLOS_ICON_X/Y`.
|
||||||
|
|
||||||
### Pets
|
### Pets
|
||||||
|
|
||||||
@@ -139,7 +140,7 @@ What the global cooldown must never do is darken the icons. While it runs, the c
|
|||||||
|
|
||||||
**HoT and shield timers.** The button of a spell shows, for its unit, the remaining seconds of your own HoT (green) or shield (blue) of that spell. When Power Word: Shield is used up, the same button shows Weakened Soul in red until the target can be shielded again. The left-click spell is checked first, then the right-click spell. Only your own effects are tracked: a HoT that the addon only sees as a buff gets its timer once your first tick of it shows up in the combat log, and shield and Weakened Soul follow shields you cast through the Heal Box buttons, since a shield from the action bar cannot be told apart from another priest's (see [Heal over time](#heal-over-time) and [Absorb shields](#absorb-shields)). Option *HoT and shield timers*.
|
**HoT and shield timers.** The button of a spell shows, for its unit, the remaining seconds of your own HoT (green) or shield (blue) of that spell. When Power Word: Shield is used up, the same button shows Weakened Soul in red until the target can be shielded again. The left-click spell is checked first, then the right-click spell. Only your own effects are tracked: a HoT that the addon only sees as a buff gets its timer once your first tick of it shows up in the combat log, and shield and Weakened Soul follow shields you cast through the Heal Box buttons, since a shield from the action bar cannot be told apart from another priest's (see [Heal over time](#heal-over-time) and [Absorb shields](#absorb-shields)). Option *HoT and shield timers*.
|
||||||
|
|
||||||
**Buff icons left of the bar.** Buffs with a duration that sit on your buttons (Fortitude, Divine Spirit, Fear Ward, Inner Fire, left or right click) appear as small 8 px icons on the **outer left side** of the plate while the buff is up, stacked two high: the first at the top next to the plate, the second below it, the third at the top of the next column to the left, and so on. The icon visually tracks remaining time in **32 vertical steps** (`FBBUFFICON_STEPS = 32`): as time runs out, the icon turns black and white and shades darker from top to bottom. Fresh buff: fully coloured. Half time left: top half grey. A quarter left: top three quarters grey. This 32-step vertical wipe provides much higher visual precision (e.g. updating approximately every 56 seconds for a 30-minute buff instead of every 7.5 minutes) while saving performance by using a single dynamically cropped desaturated overlay (`ic.qTex`) and dark wash (`ic.wTex`). Hovering an icon shows the buff name and the remaining time. The remaining time is exact on yourself (buff API, re-read on every `PLAYER_AURAS_CHANGED` and once a second in between, because a refresh of a running buff fires no event; a recast therefore resets the clock) and counted from your own cast on others; a buff cast by someone else stays fully coloured (time unknown). Up to six icons per plate (`FBBUFFICON_MAX`). Option *Buff icons left of the bar*, on by default. Raid cells show the same duration icons outside their left edge at 6 px in a 3 by 4 grid (twelve slots, columns filling from the cell outward), and the grid reserves the room for them between the groups. After a `/reload` or a group change the addon scans all units once, so existing buffs show up without waiting for an aura event. `/fbp buffs` lists the tracked buffs and their state on you.
|
**Buff icons left of the bar.** Buffs with a duration that sit on your buttons (Fortitude, Divine Spirit, Fear Ward, Inner Fire; left click, and right click when the right-click spell is on) appear as small 8 px icons on the **outer left side** of the plate while the buff is up, stacked two high: the first at the top next to the plate, the second below it, the third at the top of the next column to the left, and so on. The icon visually tracks remaining time in **32 vertical steps** (`FBBUFFICON_STEPS = 32`): as time runs out, the icon turns black and white and shades darker from top to bottom. Fresh buff: fully coloured. Half time left: top half grey. A quarter left: top three quarters grey. This 32-step vertical wipe provides much higher visual precision (e.g. updating approximately every 56 seconds for a 30-minute buff instead of every 7.5 minutes) while saving performance by using a single dynamically cropped desaturated overlay (`ic.qTex`) and dark wash (`ic.wTex`). A buff and its group version (Power Word: Fortitude and Prayer of Fortitude, Mark and Gift of the Wild, Blessing and Greater Blessing, list `FBBuffAlternates`) share **one** icon; it shows the version the unit actually carries, and it appears as soon as either version is on a button. Mark and Gift of the Wild share one texture; on yourself the buff name from the tooltip decides which one you carry, on others your latest own cast. Buffs on no button get no icon. Hovering an icon shows the buff name and the remaining time. The remaining time is exact on yourself (buff API, re-read on every `PLAYER_AURAS_CHANGED` and once a second in between, because a refresh of a running buff fires no event; a recast therefore resets the clock) and counted from your own cast on others; a buff cast by someone else stays fully coloured (time unknown). Up to six icons per plate (`FBBUFFICON_MAX`). Option *Buff icons left of the bar*, on by default. Raid cells show the same duration icons outside their left edge at 6 px in a 3 by 4 grid (twelve slots, columns filling from the cell outward), and the grid reserves the room for them between the groups. After a `/reload` or a group change the addon scans all units once, so existing buffs show up without waiting for an aura event. `/fbp buffs` lists the tracked buffs, their state on you and whether they get an icon.
|
||||||
|
|
||||||
**Dead, ghost, offline.** Instead of `0 %` the bar shows *Dead*, *Ghost* or *Offline*, empty and grey, with no mana strip.
|
**Dead, ghost, offline.** Instead of `0 %` the bar shows *Dead*, *Ghost* or *Offline*, empty and grey, with no mana strip.
|
||||||
|
|
||||||
@@ -229,7 +230,7 @@ Rank selection for **attack spells on any action bar**, in its own module `FBHea
|
|||||||
|
|
||||||
### How it works
|
### How it works
|
||||||
|
|
||||||
Every bar and key binding ends in `UseAction(slot)`. The module hooks that function, reads the spell and rank in the slot from a tooltip scan, and decides. Damage per rank is the **minimum** damage from the spell's tooltip ("86 to 98 Holy damage"), raised by the bonus that your smallest normal hit with that rank proves (crits and partial resists are not counted): every hit is at most the tooltip's maximum plus your bonus, so the minimum is at least the tooltip's minimum plus *smallest hit minus maximum*. The smallest hit, because boosts such as Curse of Shadow or Power Infusion only raise some hits; a single boosted hit must not lift the value for good. Up to 1.4.6 the smallest hit itself counted as the minimum, and after a single high roll the chosen rank could fall short. A rank qualifies if its minimum damage covers the target's remaining health plus the *Safety margin* (default 20 %). Macros with `/cast` are not affected.
|
Every bar and key binding ends in `UseAction(slot)`. The module hooks that function, reads the spell and rank in the slot from a tooltip scan, and decides. Damage per rank is the **minimum** damage from the spell's tooltip ("86 to 98 Holy damage", "for 11 Fire damage", "causes 13 Arcane damage"), raised by the bonus that your smallest normal hit with that rank proves (crits, partial resists, absorbed or blocked hits and hits with a vulnerability bonus are not counted): every hit is at most the tooltip's maximum plus your bonus, so the minimum is at least the tooltip's minimum plus *smallest hit minus maximum*. The smallest hit, because boosts such as Curse of Shadow or Power Infusion only raise some hits; a single boosted hit must not lift the value for good. Up to 1.4.6 the smallest hit itself counted as the minimum, and after a single high roll the chosen rank could fall short. The tooltip's spread is subtracted exactly once, as the unknown roll inside that one hit. With many hits the smallest one moves towards minimum plus bonus, and the bound then sits up to one spread below the real minimum (40 of about 750 points for Frostbolt rank 11): the price for a bound that is proven. The largest hit would be closer, but a single boosted hit would make it wrong. A rank qualifies if its minimum damage covers the target's remaining health plus the *Safety margin* (default 20 %). Macros with `/cast` are not affected.
|
||||||
|
|
||||||
The target's remaining health comes from the first source that answers:
|
The target's remaining health comes from the first source that answers:
|
||||||
|
|
||||||
@@ -251,7 +252,7 @@ The target's remaining health comes from the first source that answers:
|
|||||||
|Target health source|Live line: which of the four sources answers for your current target|
|
|Target health source|Live line: which of the four sources answers for your current target|
|
||||||
|Spells|The attack spells found in your spellbook with their rank count|
|
|Spells|The attack spells found in your spellbook with their rank count|
|
||||||
|
|
||||||
Spells per class: Priest Smite, Holy Fire, Mind Blast; Druid Wrath, Starfire, Moonfire; Shaman Lightning Bolt, Chain Lightning, Earth/Flame/Frost Shock; Paladin Holy Shock, Hammer of Wrath, Exorcism, Holy Wrath; Mage Fireball, Frostbolt, Fire Blast, Scorch, Pyroblast; Warlock Shadow Bolt, Searing Pain, Immolate, Soul Fire, Conflagrate; Hunter Arcane Shot, Aimed Shot (list `FBDamageSpells`). `/fbp damage` toggles, `/fbp debug` logs every decision with the health source used. Note for hunters: the addon does not load for that class, so Smart Damage only runs after `/fbp forceload`, see [Which classes it loads for](#which-classes-it-loads-for).
|
Spells per class: Priest Smite, Holy Fire, Mind Blast; Druid Wrath, Starfire, Moonfire; Shaman Lightning Bolt, Chain Lightning, Earth/Flame/Frost Shock; Paladin Holy Shock, Hammer of Wrath, Exorcism, Holy Wrath; Mage Fireball, Frostbolt, Fire Blast, Scorch, Pyroblast; Warlock Shadow Bolt, Searing Pain, Immolate, Soul Fire, Conflagrate; Hunter Arcane Shot (list `FBDamageSpells`). Aimed Shot is not in the list: its tooltip only adds to the weapon's damage, so there is no damage figure to read. `/fbp damage` toggles, `/fbp debug` logs every decision with the health source used. Note for hunters: the addon does not load for that class, so Smart Damage only runs after `/fbp forceload`, see [Which classes it loads for](#which-classes-it-loads-for).
|
||||||
|
|
||||||
While Smart Damage is off, the module listens neither to the combat log nor to the target's health, and it reads the attack spells from the spellbook only when you open the options.
|
While Smart Damage is off, the module listens neither to the combat log nor to the target's health, and it reads the attack spells from the spellbook only when you open the options.
|
||||||
|
|
||||||
@@ -321,7 +322,7 @@ The window has two tabs of its own, *Buttons* and *General*. The modules add *Ra
|
|||||||
|
|
||||||
**HealComm sync**: exchanges heal information with the group, see [HealComm sync](#healcomm-sync). On by default.
|
**HealComm sync**: exchanges heal information with the group, see [HealComm sync](#healcomm-sync). On by default.
|
||||||
|
|
||||||
**Language / Sprache**: switches between English and German. The button opens the same cascading menu as the spell picker. The change takes effect **immediately**: `FBHealBox_ApplyLocale()` relabels the already-built interface, no `/reload` needed. On first start `GetLocale()` decides: German clients start in German, everything else in English. The choice is saved per character.
|
**Language / Sprache**: switches between English, German, Spanish, French and Italian. The button opens the same cascading menu as the spell picker. The change takes effect **immediately**: `FBHealBox_ApplyLocale()` relabels the already-built interface, no `/reload` needed. On first start `GetLocale()` decides: German, Spanish (including Mexican Spanish), French and Italian clients start in their own language, everything else in English. Missing texts fall back to English. The choice is saved per character.
|
||||||
|
|
||||||
**To move the window:** drag its frame. Close it with the X in the top right, with **Escape**, or with `/fbp config`. Escape is caught by a hook on `ToggleGameMenu` (in addition to `UISpecialFrames`), so it works on clients that do not honour that list; when Blizzard's game menu is open, Escape closes that first as usual.
|
**To move the window:** drag its frame. Close it with the X in the top right, with **Escape**, or with `/fbp config`. Escape is caught by a hook on `ToggleGameMenu` (in addition to `UISpecialFrames`), so it works on clients that do not honour that list; when Blizzard's game menu is open, Escape closes that first as usual.
|
||||||
|
|
||||||
@@ -370,6 +371,8 @@ The heart of the addon. Three independent sources feed the bars.
|
|||||||
|
|
||||||
The target is the unit of the Heal Box button you clicked, provided the same spell starts within `FBPREDICT_CLICK_TIME` (2 seconds) after the click; a click made while another spell is still being cast waits for the next start, which also suits the spell queue of client mods. A cast from the action bar or a macro goes to your friendly target, otherwise to yourself. A click counts for one cast only: once its spell has started, gone through or failed, the next cast no longer belongs to it. An error message or a failed cast always answers the latest attempt. To know which one that is, the addon counts every attempt, including those from the action bar, macros and the spellbook; for that it hooks `UseAction`, `CastSpellByName` and `CastSpell`, counts, and passes everything on unchanged. Up to 1.4.6 the target of a click stayed valid for two seconds and its rank for three, for every following cast, even after a failed click.
|
The target is the unit of the Heal Box button you clicked, provided the same spell starts within `FBPREDICT_CLICK_TIME` (2 seconds) after the click; a click made while another spell is still being cast waits for the next start, which also suits the spell queue of client mods. A cast from the action bar or a macro goes to your friendly target, otherwise to yourself. A click counts for one cast only: once its spell has started, gone through or failed, the next cast no longer belongs to it. An error message or a failed cast always answers the latest attempt. To know which one that is, the addon counts every attempt, including those from the action bar, macros and the spellbook; for that it hooks `UseAction`, `CastSpellByName` and `CastSpell`, counts, and passes everything on unchanged. Up to 1.4.6 the target of a click stayed valid for two seconds and its rank for three, for every following cast, even after a failed click.
|
||||||
|
|
||||||
|
Group heals (`FBCommGroupHeal`, Prayer of Healing) show their prediction on you and every party member in range, the same list that goes out over HealComm, whichever plate or raid cell you clicked. In a raid that is your own subgroup, which is exactly who Prayer of Healing heals. Up to 1.4.7 the prediction sat only on the unit you clicked.
|
||||||
|
|
||||||
Instants deliberately get **no** prediction: the healing has landed before a bar could show it.
|
Instants deliberately get **no** prediction: the healing has landed before a bar could show it.
|
||||||
|
|
||||||
### Heal over time
|
### Heal over time
|
||||||
@@ -389,7 +392,7 @@ The tick interval cannot be read from the tooltip in Vanilla and therefore lives
|
|||||||
|
|
||||||
Vanilla spell tooltips show the naked base value, the healing bonus from your gear is not in there. Learned values from the combat log carry it automatically, so the gap only exists for ranks you have never cast. If an API supplies the bonus, the addon closes that gap: the value is weighted the vanilla way, cast time divided by 3.5 and capped at 3.5 seconds, instants counting as 1.5. A 3 second Greater Heal with +700 healing therefore starts out 600 higher than its tooltip, a 1.5 second Flash Heal 300.
|
Vanilla spell tooltips show the naked base value, the healing bonus from your gear is not in there. Learned values from the combat log carry it automatically, so the gap only exists for ranks you have never cast. If an API supplies the bonus, the addon closes that gap: the value is weighted the vanilla way, cast time divided by 3.5 and capped at 3.5 seconds, instants counting as 1.5. A 3 second Greater Heal with +700 healing therefore starts out 600 higher than its tooltip, a 1.5 second Flash Heal 300.
|
||||||
|
|
||||||
The cast time comes from the tooltip of each rank, and so do range and cooldown (`/fbp` lists all three per spell). Ranks learned below level 20 only get part of the bonus, just as in the game: 3.75 per cent less for every level below 20, so Lesser Heal rank 3, learned at level 10, gets 62.5 per cent. The tooltip does not say at which level a rank is learned, so these ranks are listed in `FBRankLearnLevel`. Without that cut Smart Healing would think small ranks with a lot of +healing far stronger than they are.
|
The cast time comes from the tooltip of each rank, and so do range and cooldown (`/fbp` lists all three per spell). For the weighting the game uses the cast time **before talents**, while the tooltip already shows the shortened one: with Divine Fury Greater Heal reads 2.5 seconds, with Naturalist Healing Touch 3.0, with Improved Healing Wave Healing Wave 2.5. The spells whose cast time a talent shortens (Heal, Greater Heal, Healing Touch, Healing Wave) therefore have their base cast time in `FBBaseCastTime`; everything else uses the tooltip. Up to 1.4.7 a talented healer's unlearned ranks of these four spells got a seventh too little of the bonus. Ranks learned below level 20 only get part of the bonus, just as in the game: 3.75 per cent less for every level below 20, so Lesser Heal rank 3, learned at level 10, gets 62.5 per cent. The tooltip does not say at which level a rank is learned, so these ranks are listed in `FBRankLearnLevel`. Without that cut Smart Healing would think small ranks with a lot of +healing far stronger than they are.
|
||||||
|
|
||||||
`GetSpellBonusHealing` is what the addon looks for, plus `GetSpellBonusHeal` and `GetHealingBonus`, first as a global and then inside a `ClassicAPI` table. **ClassicAPI** provides it; without any such API the bonus stays 0 and nothing changes. `/fbp` reports the value found and whether it is being applied, `/fbp healbonus` turns it off. The first learned value for a rank always wins over the estimate.
|
`GetSpellBonusHealing` is what the addon looks for, plus `GetSpellBonusHeal` and `GetHealingBonus`, first as a global and then inside a `ClassicAPI` table. **ClassicAPI** provides it; without any such API the bonus stays 0 and nothing changes. `/fbp` reports the value found and whether it is being applied, `/fbp healbonus` turns it off. The first learned value for a rank always wins over the estimate.
|
||||||
|
|
||||||
@@ -415,7 +418,7 @@ Tooltips in 1.12 only provide base values **without** +healing, and there is no
|
|||||||
|
|
||||||
All of it lands per spell **and rank** in `HealBox.PredictMemory` and survives logout.
|
All of it lands per spell **and rank** in `HealBox.PredictMemory` and survives logout.
|
||||||
|
|
||||||
Two safeguards keep that memory clean. **Crits are not learned**: the crit wording makes the spell name come through the pattern as "Flash Heal critically", which is in no watch list. And learning only happens with a **confirmed rank**, that is on casts through the Heal Box buttons; otherwise a rank 3 cast from the action bar would be attributed to the maximum rank and drag the prediction down. The live display still corrects itself either way; only the persistent memory is protected. The heal usually appears in the combat log only after the cast has ended, so a finished cast waits `FBPREDICT_CLICK_TIME` (2) seconds for its line. Up to 1.4.6 only a cast still running was matched, and direct heals were hardly ever learned.
|
Two safeguards keep that memory clean. **Crits are not learned**: crit lines (`HEALEDCRITSELFOTHER`, `HEALEDCRITSELFSELF`) are recognised on their own; they close their cast like any heal line, but their amount is not remembered. Up to 1.4.7 a crit line slipped through as a spell called "Flash Heal critically" and left its cast waiting, so a smaller rank of the same spell from the action bar within two seconds could be learned as the button rank. And learning only happens with a **confirmed rank**, that is on casts through the Heal Box buttons; otherwise a rank 3 cast from the action bar would be attributed to the maximum rank and drag the prediction down. The live display still corrects itself either way; only the persistent memory is protected. The heal usually appears in the combat log only after the cast has ended, so a finished cast waits `FBPREDICT_CLICK_TIME` (2) seconds for its line. Up to 1.4.6 only a cast still running was matched, and direct heals were hardly ever learned.
|
||||||
|
|
||||||
What a spell can do is decided by its own tooltip, and a spell may be several things at once. Regrowth, for instance, provides an instant portion *and* a HoT, and is treated as both.
|
What a spell can do is decided by its own tooltip, and a spell may be several things at once. Regrowth, for instance, provides an instant portion *and* a HoT, and is treated as both.
|
||||||
|
|
||||||
@@ -436,7 +439,7 @@ HealComm-1.0 broadcasts plain text through `SendAddonMessage` with the prefix `H
|
|||||||
|
|
||||||
Messages go to the raid, otherwise to the party, otherwise nowhere. In a battleground they go over the `BATTLEGROUND` channel, as HealComm-1.0 does it, because `RAID` reaches nobody there. The amounts are the self-corrected combat log values, so arguably more accurate than what a real HealComm estimates with ItemBonusLib.
|
Messages go to the raid, otherwise to the party, otherwise nowhere. In a battleground they go over the `BATTLEGROUND` channel, as HealComm-1.0 does it, because `RAID` reaches nobody there. The amounts are the self-corrected combat log values, so arguably more accurate than what a real HealComm estimates with ItemBonusLib.
|
||||||
|
|
||||||
A few details: on a successful cast end **no** `Healstop` is sent; HealComm receivers expire the entry themselves at cast time. Prayer of Healing correctly goes out as `GrpHeal` with every target in range. And a HoT cast from the action bar is reported after the fact on the first own combat log tick, with the duration still remaining, because only "… from **your** Renew" proves that it is yours. Incoming commands are read regardless of upper and lower case; pfUI, for example, sends `HealStop`.
|
A few details: on a successful cast end **no** `Healstop` is sent; HealComm receivers expire the entry themselves at cast time. Prayer of Healing correctly goes out as `GrpHeal` with every target in range, and your own bars show it on the same members. And a HoT cast from the action bar is reported after the fact on the first own combat log tick, with the duration still remaining, because only "… from **your** Renew" proves that it is yours. Incoming commands are read regardless of upper and lower case; pfUI, for example, sends `HealStop`.
|
||||||
|
|
||||||
On receive, your own messages are filtered by sender name, and since HealComm stores incoming heals per caster nothing can double up, not even when a real HealComm is broadcasting alongside. HoT messages carry only durations and no amounts; HealComm does not count them in its own `getHeal`, and neither does this addon. Values from other addons are capped: amounts at `FBCOMM_MAX_AMOUNT` (20000), cast times and delays at `FBCOMM_MAX_CAST_MS` (10 seconds), so a broken message cannot fill a bar for minutes.
|
On receive, your own messages are filtered by sender name, and since HealComm stores incoming heals per caster nothing can double up, not even when a real HealComm is broadcasting alongside. HoT messages carry only durations and no amounts; HealComm does not count them in its own `getHeal`, and neither does this addon. Values from other addons are capped: amounts at `FBCOMM_MAX_AMOUNT` (20000), cast times and delays at `FBCOMM_MAX_CAST_MS` (10 seconds), so a broken message cannot fill a bar for minutes.
|
||||||
|
|
||||||
@@ -566,6 +569,7 @@ Every knob is a global at the top of its own section and can be changed without
|
|||||||
|`FBHoTSpells`|(table)|Heal over time spells that Smart Healing never downranks|
|
|`FBHoTSpells`|(table)|Heal over time spells that Smart Healing never downranks|
|
||||||
|`FBSmartSkip`|(table)|Group heals and cooldown spells that Smart Healing always casts as assigned (spells with a cooldown in their tooltip are left alone anyway)|
|
|`FBSmartSkip`|(table)|Group heals and cooldown spells that Smart Healing always casts as assigned (spells with a cooldown in their tooltip are left alone anyway)|
|
||||||
|`FBRankLearnLevel`|(table)|Learning level of the ranks below level 20, for the reduced share of +healing|
|
|`FBRankLearnLevel`|(table)|Learning level of the ranks below level 20, for the reduced share of +healing|
|
||||||
|
|`FBBaseCastTime`|(table)|Cast time before talents of the heals a talent speeds up, for the share of +healing|
|
||||||
|`FBBlockedClasses`|`WARRIOR`, `ROGUE`, `HUNTER`|Classes the addon does not load for without `/fbp forceload`|
|
|`FBBlockedClasses`|`WARRIOR`, `ROGUE`, `HUNTER`|Classes the addon does not load for without `/fbp forceload`|
|
||||||
|`FBLocale`|`enUS`, `deDE`, `esES`, `frFR`, `itIT`|Every visible string, per language|
|
|`FBLocale`|`enUS`, `deDE`, `esES`, `frFR`, `itIT`|Every visible string, per language|
|
||||||
|`FBHealBoxDefaults`|(table)|Default of every setting; missing keys are filled in from here|
|
|`FBHealBoxDefaults`|(table)|Default of every setting; missing keys are filled in from here|
|
||||||
@@ -602,13 +606,15 @@ Every knob is a global at the top of its own section and can be changed without
|
|||||||
|`FBHealBox_IsHoT(base, ranks)`|Heal over time? List of names plus tooltip, spell watch and running HoTs. Smart Healing skips these|
|
|`FBHealBox_IsHoT(base, ranks)`|Heal over time? List of names plus tooltip, spell watch and running HoTs. Smart Healing skips these|
|
||||||
|`FBHealBox_HealFamily(base)` · `FBHealBox_DirectAmount(spell, sd)`|The heal chain a spell belongs to; the expected heal of one rank, or nil if the spell is not eligible|
|
|`FBHealBox_HealFamily(base)` · `FBHealBox_DirectAmount(spell, sd)`|The heal chain a spell belongs to; the expected heal of one rank, or nil if the spell is not eligible|
|
||||||
|`FBPredict_ExpectedDirect(spell, rank, info, id)`|Expected direct heal: learned value, otherwise tooltip plus the share of the equipment bonus|
|
|`FBPredict_ExpectedDirect(spell, rank, info, id)`|Expected direct heal: learned value, otherwise tooltip plus the share of the equipment bonus|
|
||||||
|`FBHealBox_ProbeHealBonus()` · `FBHealBox_HealingBonus()` · `FBHealBox_HealBonusFor(id)`|Finds an API for the healing bonus, reads it, and weights it by cast time|
|
|`FBHealBox_ProbeHealBonus()` · `FBHealBox_HealingBonus()` · `FBHealBox_HealBonusFor(id, spell, rank)`|Finds an API for the healing bonus, reads it, and weights it by cast time|
|
||||||
|
|`FBHealBox_BaseCastSeconds(spell, rank, id)`|Cast time for that weighting: from `FBBaseCastTime`, otherwise from the tooltip|
|
||||||
|`FBHealBox_SpellCastSeconds(id)`|Cast time from the tooltip (0 = instant), cached per spellbook slot|
|
|`FBHealBox_SpellCastSeconds(id)`|Cast time from the tooltip (0 = instant), cached per spellbook slot|
|
||||||
|`FBHealBox_ApplyBlizzParty()` · `FBHealBox_HideBlizzPartyActive()`|Hides or restores Blizzard's party frames, including the lock against the attach mode|
|
|`FBHealBox_ApplyBlizzParty()` · `FBHealBox_HideBlizzPartyActive()`|Hides or restores Blizzard's party frames, including the lock against the attach mode|
|
||||||
|`FBHealBox_SetPowerColor(bar, cache, ptype)`|Colours a resource bar for mana, rage, focus or energy|
|
|`FBHealBox_SetPowerColor(bar, cache, ptype)`|Colours a resource bar for mana, rage, focus or energy|
|
||||||
|`FBHealBox_ApplyBarBG(f)` · `FBHealBox_ApplyBarBGAll()`|Sets the background behind a plate's bars from the `BarBG` option|
|
|`FBHealBox_ApplyBarBG(f)` · `FBHealBox_ApplyBarBGAll()`|Sets the background behind a plate's bars from the `BarBG` option|
|
||||||
|`FBHealBox_RefreshUnitsByName(names)`|Redraws only the plates whose unit is in the name set; the raid module gets the same set through the `RefreshNames` hook|
|
|`FBHealBox_RefreshUnitsByName(names)`|Redraws only the plates whose unit is in the name set; the raid module gets the same set through the `RefreshNames` hook|
|
||||||
|`FBPredict_ScanPlayerBuffTimes()`|Reads all of your own buff timers once per frame into a texture-to-seconds map|
|
|`FBPredict_ScanPlayerBuffTimes()`|Reads all of your own buff timers once per frame into a texture-to-seconds map|
|
||||||
|
|`FBPredict_PlayerBuffLeft(spell, w)` · `FBHealBox_PlayerBuffName(id)`|Remaining time of your own buff, only for the version you carry (shared texture: buff name from the tooltip, otherwise by duration)|
|
||||||
|`FBHealBox_ApiFailed()`|Puts range, distance and line of sight back to the protected single call after a sweep threw|
|
|`FBHealBox_ApiFailed()`|Puts range, distance and line of sight back to the protected single call after a sweep threw|
|
||||||
|`FBHealBox_SweepResult(where, ok, err)` · `FBHealBox_ReportError(where, err)`|Evaluates a protected sweep; reports errors once in the chat, further ones with `/fbp debug`|
|
|`FBHealBox_SweepResult(where, ok, err)` · `FBHealBox_ReportError(where, err)`|Evaluates a protected sweep; reports errors once in the chat, further ones with `/fbp debug`|
|
||||||
|`FBHealBox_UpperTex(tex)`|Upper-cased texture path, remembered, so `strupper` does not allocate per call|
|
|`FBHealBox_UpperTex(tex)`|Upper-cased texture path, remembered, so `strupper` does not allocate per call|
|
||||||
@@ -631,6 +637,7 @@ Every knob is a global at the top of its own section and can be changed without
|
|||||||
|`FBHealBox_SetWatchBuff(name)` · `FBHealBox_HasWatchBuff(unit)` · `FBHealBox_CheckWatchBuff(unit, f)`|Buff watch: select, test one unit, colour the border|
|
|`FBHealBox_SetWatchBuff(name)` · `FBHealBox_HasWatchBuff(unit)` · `FBHealBox_CheckWatchBuff(unit, f)`|Buff watch: select, test one unit, colour the border|
|
||||||
|`FBHealBox_UnitInRange(unit)` · `FBHealBox_CheckRangeAll()`|Range fading|
|
|`FBHealBox_UnitInRange(unit)` · `FBHealBox_CheckRangeAll()`|Range fading|
|
||||||
|`FBUnitLOSBlocked(unit)` · `FBLOS_OnError(msg)` · `FBLOS_Clear(name)` · `FBHealBox_CheckLOSAll()`|Line of sight (UnitXP or error-message fallback)|
|
|`FBUnitLOSBlocked(unit)` · `FBLOS_OnError(msg)` · `FBLOS_Clear(name)` · `FBHealBox_CheckLOSAll()`|Line of sight (UnitXP or error-message fallback)|
|
||||||
|
|`FBLOS_NoteClick(name, spell, now)` · `FBLOS_CastStart(spell, ms)` · `FBLOS_CastDelayed(ms)` · `FBLOS_CastDone()` · `FBLOS_Reset()`|Candidates for a line of sight error: the latest click (`FBLOSClick`) and the running cast (`FBLOSCast`); `FBLOS_CastDone` keeps a click queued during the cast|
|
||||||
|`FBMenu_OpenBuffMenu(anchor)`|The buff picker (same cascading menu)|
|
|`FBMenu_OpenBuffMenu(anchor)`|The buff picker (same cascading menu)|
|
||||||
|`HealBoxAttachMode(mode)`|Switch between own plates ↔ default party frames|
|
|`HealBoxAttachMode(mode)`|Switch between own plates ↔ default party frames|
|
||||||
|`HealBoxScale(this, scale)`|Scaling|
|
|`HealBoxScale(this, scale)`|Scaling|
|
||||||
@@ -692,11 +699,13 @@ The four functions that feed the bars. All of them expect a **player name**, not
|
|||||||
|-|-|
|
|-|-|
|
||||||
|`FBPredict_GetSpellInfo(bookID, name)`|Parses the spellbook tooltip (direct / HoT / shield)|
|
|`FBPredict_GetSpellInfo(bookID, name)`|Parses the spellbook tooltip (direct / HoT / shield)|
|
||||||
|`FBPredict_BuildWatch()`|Builds the watch list after every spellbook scan|
|
|`FBPredict_BuildWatch()`|Builds the watch list after every spellbook scan|
|
||||||
|
|`FBPredict_BuildBuffOrder()` · `FBPredict_ButtonSpells()` · `FBHealBox_PickBuffVariant(…)`|Which buffs get an icon (only those on a button, one icon per buff and its group version) and which version an icon shows|
|
||||||
|`FBPredict_NoteCast(castString, target)`|Registers target and rank **before** the cast (`FBPredictClick`)|
|
|`FBPredict_NoteCast(castString, target)`|Registers target and rank **before** the cast (`FBPredictClick`)|
|
||||||
|`FBPredict_TakeClick(spell, castMs)` · `FBPredict_ClickDone()` · `FBPredict_ClickFailed(interrupted)`|What becomes of the click on cast start, cast end and failure (`FBPredictClick`, `FBPredictCastClick`)|
|
|`FBPredict_TakeClick(spell, castMs)` · `FBPredict_ClickDone()` · `FBPredict_ClickFailed(interrupted)`|What becomes of the click on cast start, cast end and failure (`FBPredictClick`, `FBPredictCastClick`)|
|
||||||
|`FBPredict_HookAttempts()`|Counts every cast attempt (`UseAction`, `CastSpellByName`, `CastSpell`) in `FBPredictClickSeq`|
|
|`FBPredict_HookAttempts()`|Counts every cast attempt (`UseAction`, `CastSpellByName`, `CastSpell`) in `FBPredictClickSeq`|
|
||||||
|`FBPredict_ConfirmPending()`|Confirms HoT, shield and buff of a click whose cast went through|
|
|`FBPredict_ConfirmPending()`|Confirms HoT, shield and buff of a click whose cast went through|
|
||||||
|`FBPredict_CastStart(spell, castMs)` · `FBPredict_CastEnd(success)`|Start and end a direct heal; a successful one stays in `FBPredictLastDirect` for its combat log line|
|
|`FBPredict_CastStart(spell, castMs)` · `FBPredict_CastEnd(success)`|Start and end a direct heal; a successful one stays in `FBPredictLastDirect` for its combat log line|
|
||||||
|
|`FBPredict_GroupTargets()` · `FBPredict_CastHits(d, name)` · `FBPredict_CastLanded(d, name)`|Targets of a group heal (you and your party in range); does a cast hit this unit; one target's heal line has arrived|
|
||||||
|`FBPredict_ScanUnit(unit)`|Aura check: confirm application, detect removal|
|
|`FBPredict_ScanUnit(unit)`|Aura check: confirm application, detect removal|
|
||||||
|`FBPredict_StartHoT(…)` · `FBPredict_StartShield(…)`|Arm the tracking|
|
|`FBPredict_StartHoT(…)` · `FBPredict_StartShield(…)`|Arm the tracking|
|
||||||
|`FBPredict_ParseCombat(event, msg)`|Combat log evaluation|
|
|`FBPredict_ParseCombat(event, msg)`|Combat log evaluation|
|
||||||
@@ -737,7 +746,7 @@ 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 (`FBClassSpells.Name` near the top of the file), or not learned yet. The list can be extended freely.
|
**A spell does not appear in the menu.** It is not in your class's spell list (`FBClassSpells.Name` near the top of the file), or not learned yet. The list can be extended freely.
|
||||||
|
|
||||||
**Client in another language.** Class detection, dispel colouring and the class icon work on every client. The spell lists (`FBClassSpells.Name`, buff watch, Smart Damage) hold English spell names, and the prediction reads English tooltips. On a German, French or Spanish client the spell menu therefore stays empty, and the prediction and Smart Healing do not recognise the spells. Spells assigned by drag and drop from the spellbook still work on the buttons.
|
**Client in another language.** Class detection, dispel colouring and the class icon work on every client. The spell lists (`FBClassSpells.Name`, buff watch, Smart Damage) hold English spell names, and the prediction reads English tooltips. On a German, French or Spanish client the spell menu therefore stays empty, and the prediction and Smart Healing do not recognise the spells. Spells assigned by drag and drop from the spellbook still work on the buttons. Some Smart Healing tables (`FBHealChains`, `FBHoTSpells`, `FBSmartSkip`, `FBRankLearnLevel`, `FBBaseCastTime`) already carry the German spell names; they take effect once the tooltips can be read. The HealComm codes (`FBCommHoTCode`, `FBCommGroupHeal`) stay English, as does `FBClassSpells.Name`.
|
||||||
|
|
||||||
**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.
|
**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.
|
||||||
|
|
||||||
@@ -782,6 +791,7 @@ 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
|
* 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
|
* HealComm sync with Puppeteer, pfUI, Luna and others, without any Ace libraries
|
||||||
* English, German, Spanish, French and Italian localization, switchable in game
|
* English, German, Spanish, French and Italian localization, switchable in game
|
||||||
|
* 1.4.7.1: follow-up to an external review. Buff icons only for buffs on your buttons, one icon for a buff and its group version; line of sight survives spam clicks and client spell queues during a cast; +healing weighted by the cast time before talents; crit lines close their cast and are never learned; Prayer of Healing shows its prediction on the whole group; Smart Damage reads Arcane Shot and Flame Shock and learns from plain hits only; raid cells pick up late names; see CHANGELOG
|
||||||
* 1.4.7: the complete code review. Fixes: Weakened Soul visible, other healers' HoTs and shields no longer counted as yours, range and cast time read from the right place in the tooltip, Smart Healing leaves group heals and cooldown spells alone and rates ranks below level 20 correctly, line of sight errors only mark the clicked unit, class tables on every client language, scale slider no longer moves the plates, drag and drop on raid mini buttons fixed, clicks only count for the cast they started, direct heals are learned, Smart Damage's minimum damage is safe again and its own health estimate stays out of raids. Performance: redraws collected once per frame, mana events only redraw the mana strip, range asked once per unit, spellbook re-read once per burst, Smart Damage idle while off. Robustness: generic globals renamed with an `FB` prefix, Smart Damage works without the ticker, errors in modules and sweeps reported, battleground channel and limits for HealComm, dead code and duplicate helpers removed; see CHANGELOG
|
* 1.4.7: the complete code review. Fixes: Weakened Soul visible, other healers' HoTs and shields no longer counted as yours, range and cast time read from the right place in the tooltip, Smart Healing leaves group heals and cooldown spells alone and rates ranks below level 20 correctly, line of sight errors only mark the clicked unit, class tables on every client language, scale slider no longer moves the plates, drag and drop on raid mini buttons fixed, clicks only count for the cast they started, direct heals are learned, Smart Damage's minimum damage is safe again and its own health estimate stays out of raids. Performance: redraws collected once per frame, mana events only redraw the mana strip, range asked once per unit, spellbook re-read once per burst, Smart Damage idle while off. Robustness: generic globals renamed with an `FB` prefix, Smart Damage works without the ticker, errors in modules and sweeps reported, battleground channel and limits for HealComm, dead code and duplicate helpers removed; see CHANGELOG
|
||||||
* 1.4.6: performance pass without functional change (only changed units are redrawn via the `RefreshNames` hook, raid spell timers skip idle cells, spell timers leave early when nothing is running); see CHANGELOG
|
* 1.4.6: performance pass without functional change (only changed units are redrawn via the `RefreshNames` hook, raid spell timers skip idle cells, spell timers leave early when nothing is running); see CHANGELOG
|
||||||
* 1.4.5.3: adjustable background behind the plate bars, so the game world no longer shows through where health is missing; see CHANGELOG
|
* 1.4.5.3: adjustable background behind the plate bars, so the game world no longer shows through where health is missing; see CHANGELOG
|
||||||
@@ -798,16 +808,16 @@ Entries that do not exist do no harm: if the spellbook scan does not find them,
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Heal Box Vanilla v1.4.7 · original by Dourd, UI Overhauled · ported to Vanilla and extended 09/2026 by Mquadrat
|
Heal Box Vanilla v1.4.7.1 · original by Dourd, UI Overhauled · ported to Vanilla and extended 09/2026 by Mquadrat
|
||||||
|
|
||||||
_______________________________________________________________________
|
_______________________________________________________________________
|
||||||
GERMAN
|
GERMAN
|
||||||
|
|
||||||
# Heal Box Vanilla
|
# Heal Box Vanilla
|
||||||
|
|
||||||
ADDON DOKUMENTATION · VERSION 1.4.7 · World of Warcraft CLIENT 1.12.1
|
ADDON DOKUMENTATION · VERSION 1.4.7.1 · World of Warcraft 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.
|
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, Englisch, Spanisch, Französisch und Italienisch**, umschaltbar im Optionsfenster.
|
||||||
|
|
||||||
**Kurzfassung für Ungeduldige:** Minimap-Button anklicken (oder `/fbp config`) → Optionsfenster → für jeden Button einen Zauber wählen → fertig. Alles Weitere passiert von allein. `/fbp` zeigt jederzeit, was die Vorhersage gerade denkt. **Neu in 1.4.1:** *Testmodus* anhaken, dann füllt sich die Anzeige mit Geisterspielern und du kannst alles ohne Gruppe einrichten.
|
**Kurzfassung für Ungeduldige:** Minimap-Button anklicken (oder `/fbp config`) → Optionsfenster → für jeden Button einen Zauber wählen → fertig. Alles Weitere passiert von allein. `/fbp` zeigt jederzeit, was die Vorhersage gerade denkt. **Neu in 1.4.1:** *Testmodus* anhaken, dann füllt sich die Anzeige mit Geisterspielern und du kannst alles ohne Gruppe einrichten.
|
||||||
|
|
||||||
@@ -865,7 +875,7 @@ Hat dein aktuelles feindliches Ziel ein Gruppenmitglied im Ziel, bekommt dessen
|
|||||||
|
|
||||||
### Sichtlinie
|
### Sichtlinie
|
||||||
|
|
||||||
Solange eine Einheit außerhalb deiner Sichtlinie ist, sitzt ein **Augen-Abzeichen** (`FBLOS_ICON`, das Blenden-Icon) auf der linken oberen Ecke ihrer Plakette. Vanilla hat dafür keine API, deshalb zwei Wege: Ist der Client-Mod **UnitXP SP3** installiert, fragt das Addon alle halbe Sekunde `UnitXP("inSight", "player", unit)` ab, live und exakt. Ohne ihn achtet das Addon auf die Fehlermeldung *nicht in Sichtlinie* nach einem Klick auf einen deiner Heal Box Buttons und markiert die Einheit dieses Buttons für `FBLOS_TIMEOUT` (8) Sekunden; die Markierung verschwindet, sobald ein Cast auf sie startet oder eine eigene Direktheilung dort ankommt. Der Tick eines HoTs lässt sie stehen, denn Ticks brauchen keine Sicht. Die Meldung muss genau diesen Klick beantworten: Sie zählt bis `FBLOS_ERROR_WINDOW` (1) Sekunde nach dem Klick, bei einem Zauber mit Zauberzeit bis eine Sekunde nach dem Castende, denn der Server prüft die Sicht am Ende des Casts noch einmal. Ein Cast, der durchgeht, eine Unterbrechung, eine andere Fehlermeldung oder ein anderer Zauber, der anläuft, beendet das Warten. Fehler von Zaubern auf der Aktionsleiste markieren deshalb niemanden, und deine eigene Plakette wird nie markiert. `/fbp` zeigt, welcher Weg aktiv ist. Option *Sichtlinie*; Position des Abzeichens über `FBLOS_ICON_X/Y`.
|
Solange eine Einheit außerhalb deiner Sichtlinie ist, sitzt ein **Augen-Abzeichen** (`FBLOS_ICON`, das Blenden-Icon) auf der linken oberen Ecke ihrer Plakette. Vanilla hat dafür keine API, deshalb zwei Wege: Ist der Client-Mod **UnitXP SP3** installiert, fragt das Addon alle halbe Sekunde `UnitXP("inSight", "player", unit)` ab, live und exakt. Ohne ihn achtet das Addon auf die Fehlermeldung *nicht in Sichtlinie* nach einem Klick auf einen deiner Heal Box Buttons und markiert die Einheit dieses Buttons für `FBLOS_TIMEOUT` (8) Sekunden; die Markierung verschwindet, sobald ein Cast auf sie startet oder eine eigene Direktheilung dort ankommt. Der Tick eines HoTs lässt sie stehen, denn Ticks brauchen keine Sicht. Die Meldung muss genau diesen Klick beantworten: Sie zählt bis `FBLOS_ERROR_WINDOW` (1) Sekunde nach dem Klick, bei einem Zauber mit Zauberzeit bis eine Sekunde nach dem Castende, denn der Server prüft die Sicht am Ende des Casts noch einmal. Ein Cast, der durchgeht, eine Unterbrechung, eine andere Fehlermeldung oder ein anderer Zauber, der anläuft, beendet das Warten. Ein weiterer Klick, während ein Cast noch läuft, tut das nicht: Er wartet für sich, und seine Antwort (*Another action is in progress*) lässt den laufenden Cast in Ruhe; eine Sichtlinien-Meldung am Ende dieses Casts markiert also weiterhin dessen Einheit. Ein Klick, den die Zauberwarteschlange eines Clientmods (etwa Nampower) zurückhält, bekommt während des Casts keine Antwort; er bleibt nach dem Castende Kandidat und wartet auf seinen eigenen Zauber. Ein Klick gilt für einen Cast nur, wenn dieser binnen `FBPREDICT_CLICK_TIME` (2) Sekunden anläuft. Fehler von Zaubern auf der Aktionsleiste markieren deshalb niemanden, und deine eigene Plakette wird nie markiert. `/fbp` zeigt, welcher Weg aktiv ist. Option *Sichtlinie*; Position des Abzeichens über `FBLOS_ICON_X/Y`.
|
||||||
|
|
||||||
### Begleiter
|
### Begleiter
|
||||||
|
|
||||||
@@ -936,7 +946,7 @@ Was der globale Cooldown auf keinen Fall tun darf, ist die Symbole abdunkeln. So
|
|||||||
|
|
||||||
**HoT- und Schild-Timer.** Der Button eines Zaubers zeigt für seine Einheit die Restsekunden deines eigenen HoTs (grün) oder Schilds (blau) dieses Zaubers. Ist Machtwort: Schild verbraucht, zeigt derselbe Button rot die Geschwächte Seele, bis das Ziel wieder schildbar ist. Geprüft wird zuerst der Linksklick-Zauber, dann der Rechtsklick-Zauber. Nur eigene Effekte werden verfolgt: Ein HoT, den das Addon nur als Buff sieht, bekommt seinen Timer, sobald dein erster Tick davon im Combatlog steht, und Schild und Geschwächte Seele folgen den Schilden, die du über die Heal Box Buttons wirkst, denn ein Schild von der Aktionsleiste lässt sich nicht von dem eines anderen Priesters unterscheiden (siehe [Heilung über Zeit](#heilung-über-zeit) und [Absorb-Schilde](#absorb-schilde)). Option *HoT- und Schild-Timer*.
|
**HoT- und Schild-Timer.** Der Button eines Zaubers zeigt für seine Einheit die Restsekunden deines eigenen HoTs (grün) oder Schilds (blau) dieses Zaubers. Ist Machtwort: Schild verbraucht, zeigt derselbe Button rot die Geschwächte Seele, bis das Ziel wieder schildbar ist. Geprüft wird zuerst der Linksklick-Zauber, dann der Rechtsklick-Zauber. Nur eigene Effekte werden verfolgt: Ein HoT, den das Addon nur als Buff sieht, bekommt seinen Timer, sobald dein erster Tick davon im Combatlog steht, und Schild und Geschwächte Seele folgen den Schilden, die du über die Heal Box Buttons wirkst, denn ein Schild von der Aktionsleiste lässt sich nicht von dem eines anderen Priesters unterscheiden (siehe [Heilung über Zeit](#heilung-über-zeit) und [Absorb-Schilde](#absorb-schilde)). Option *HoT- und Schild-Timer*.
|
||||||
|
|
||||||
**Buff-Icons links am Balken.** Buffs mit Laufzeit, die auf deinen Buttons liegen (Seelenstärke, Göttlicher Willen, Furchtzauberschutz, Inneres Feuer, links oder rechts), erscheinen als kleine 8-px-Icons **außen links** neben der Plakette, solange der Buff wirkt, in Zweierstapeln: das erste oben an der Platte, das zweite darunter, das dritte oben in der nächsten Spalte links, und so weiter. Die Restlaufzeit wird visuell in **32 feinen Stufen** (`FBBUFFICON_STEPS = 32`) dargestellt: Mit ablaufender Zeit wird das Icon von oben nach unten schrittweise schwarz-weiß entsättigt und abgedunkelt. Frischer Buff: ganz farbig. Halbe Zeit übrig: obere Hälfte grau. Ein Viertel übrig: obere drei Viertel grau. Diese 32-Stufen-Darstellung bietet eine deutlich höhere Präzision (bei einem 30-Minuten-Buff aktualisiert sich die Anzeige ca. alle 56 Sekunden statt nur alle 7,5 Minuten) und spart gleichzeitig Ressourcen durch den Einsatz einer einzelnen dynamisch beschnittenen Overlay-Textur (`ic.qTex`) und Abdunklung (`ic.wTex`). Mouseover auf ein Icon zeigt Buffname und Restzeit. Die Restzeit ist bei dir selbst exakt (Buff-API, bei jedem `PLAYER_AURAS_CHANGED` und dazwischen einmal je Sekunde neu gelesen, weil ein Refresh eines laufenden Buffs kein Event feuert; ein Neucast stellt die Uhr also zurück) und wird bei anderen ab deinem eigenen Cast gezählt; ein fremd gewirkter Buff bleibt ganz farbig (Zeit unbekannt). Bis zu sechs Icons je Plakette (`FBBUFFICON_MAX`). Option *Buff-Icons links am Balken*, standardmäßig an. Die Raid-Zellen zeigen dieselben Icons außen an ihrer linken Kante mit 6 px in einem 3-mal-4-Raster (zwölf Plätze, Spalten füllen sich von der Zelle nach außen), das Raster hält zwischen den Gruppen Platz dafür frei. Nach einem `/reload` oder Gruppenwechsel scannt das Addon alle Einheiten einmal aktiv, damit vorhandene Buffs sofort erscheinen und nicht erst beim nächsten Aura-Event. `/fbp buffs` listet die verfolgten Buffs und ihren Zustand auf dir.
|
**Buff-Icons links am Balken.** Buffs mit Laufzeit, die auf deinen Buttons liegen (Seelenstärke, Göttlicher Willen, Furchtzauberschutz, Inneres Feuer; Linksklick, und Rechtsklick, wenn der Rechtsklick-Zauber an ist), erscheinen als kleine 8-px-Icons **außen links** neben der Plakette, solange der Buff wirkt, in Zweierstapeln: das erste oben an der Platte, das zweite darunter, das dritte oben in der nächsten Spalte links, und so weiter. Die Restlaufzeit wird visuell in **32 feinen Stufen** (`FBBUFFICON_STEPS = 32`) dargestellt: Mit ablaufender Zeit wird das Icon von oben nach unten schrittweise schwarz-weiß entsättigt und abgedunkelt. Frischer Buff: ganz farbig. Halbe Zeit übrig: obere Hälfte grau. Ein Viertel übrig: obere drei Viertel grau. Diese 32-Stufen-Darstellung bietet eine deutlich höhere Präzision (bei einem 30-Minuten-Buff aktualisiert sich die Anzeige ca. alle 56 Sekunden statt nur alle 7,5 Minuten) und spart gleichzeitig Ressourcen durch den Einsatz einer einzelnen dynamisch beschnittenen Overlay-Textur (`ic.qTex`) und Abdunklung (`ic.wTex`). Ein Buff und seine Gruppenversion (Machtwort: Seelenstärke und Gebet der Seelenstärke, Mal und Gabe der Wildnis, Segen und Großer Segen, Liste `FBBuffAlternates`) teilen sich **ein** Icon; es zeigt die Fassung, die die Einheit tatsächlich trägt, und erscheint, sobald eine der beiden auf einem Button liegt. Mal und Gabe der Wildnis teilen sich eine Textur; bei dir entscheidet der Buffname aus dem Tooltip, welche du trägst, bei anderen dein letzter eigener Cast. Buffs auf keinem Button bekommen kein Icon. Mouseover auf ein Icon zeigt Buffname und Restzeit. Die Restzeit ist bei dir selbst exakt (Buff-API, bei jedem `PLAYER_AURAS_CHANGED` und dazwischen einmal je Sekunde neu gelesen, weil ein Refresh eines laufenden Buffs kein Event feuert; ein Neucast stellt die Uhr also zurück) und wird bei anderen ab deinem eigenen Cast gezählt; ein fremd gewirkter Buff bleibt ganz farbig (Zeit unbekannt). Bis zu sechs Icons je Plakette (`FBBUFFICON_MAX`). Option *Buff-Icons links am Balken*, standardmäßig an. Die Raid-Zellen zeigen dieselben Icons außen an ihrer linken Kante mit 6 px in einem 3-mal-4-Raster (zwölf Plätze, Spalten füllen sich von der Zelle nach außen), das Raster hält zwischen den Gruppen Platz dafür frei. Nach einem `/reload` oder Gruppenwechsel scannt das Addon alle Einheiten einmal aktiv, damit vorhandene Buffs sofort erscheinen und nicht erst beim nächsten Aura-Event. `/fbp buffs` listet die verfolgten Buffs, ihren Zustand auf dir und ob sie ein Icon bekommen.
|
||||||
|
|
||||||
**Tot, Geist, Offline.** Statt `0 %` zeigt der Balken *Tot*, *Geist* oder *Offline*, leer und grau, ohne Manastreifen.
|
**Tot, Geist, Offline.** Statt `0 %` zeigt der Balken *Tot*, *Geist* oder *Offline*, leer und grau, ohne Manastreifen.
|
||||||
|
|
||||||
@@ -1026,7 +1036,7 @@ Rangwahl für **Angriffszauber auf jeder Aktionsleiste**, im eigenen Modul `FBHe
|
|||||||
|
|
||||||
### Wie es arbeitet
|
### Wie es arbeitet
|
||||||
|
|
||||||
Jede Leiste und jedes Tastenkürzel endet in `UseAction(slot)`. Das Modul hängt sich davor, liest Zauber und Rang im Slot per Tooltip-Scan und entscheidet. Der Schaden je Rang ist der **Mindestschaden** aus dem Tooltip („86 to 98 Holy damage"), angehoben um den Bonus, den dein kleinster normaler Treffer mit diesem Rang beweist (Crits und Teilwiderstände zählen nicht): Jeder Treffer liegt höchstens beim Höchstwert des Tooltips plus Bonus, der Mindestschaden also mindestens beim Mindestwert des Tooltips plus *kleinster Treffer minus Höchstwert*. Der kleinste Treffer, weil Verstärker wie Curse of Shadow oder Power Infusion nur manche Treffer heben; ein einzelner verstärkter Treffer darf den Wert nicht dauerhaft anheben. Bis 1.4.6 galt der kleinste Treffer selbst als Mindestschaden, nach einem einzigen hohen Wurf reichte der gewählte Rang dann nicht immer. Ein Rang kommt in Frage, wenn sein Mindestschaden das Restleben des Ziels plus *Sicherheitsaufschlag* (Standard 20 %) deckt. Makros mit `/cast` bleiben unberührt.
|
Jede Leiste und jedes Tastenkürzel endet in `UseAction(slot)`. Das Modul hängt sich davor, liest Zauber und Rang im Slot per Tooltip-Scan und entscheidet. Der Schaden je Rang ist der **Mindestschaden** aus dem Tooltip („86 to 98 Holy damage", „for 11 Fire damage", „causes 13 Arcane damage"), angehoben um den Bonus, den dein kleinster normaler Treffer mit diesem Rang beweist (Crits, Teilwiderstände, absorbierte oder geblockte Treffer und Treffer mit Verwundbarkeitsbonus zählen nicht): Jeder Treffer liegt höchstens beim Höchstwert des Tooltips plus Bonus, der Mindestschaden also mindestens beim Mindestwert des Tooltips plus *kleinster Treffer minus Höchstwert*. Der kleinste Treffer, weil Verstärker wie Curse of Shadow oder Power Infusion nur manche Treffer heben; ein einzelner verstärkter Treffer darf den Wert nicht dauerhaft anheben. Bis 1.4.6 galt der kleinste Treffer selbst als Mindestschaden, nach einem einzigen hohen Wurf reichte der gewählte Rang dann nicht immer. Die Spanne des Tooltips wird genau einmal abgezogen, als unbekannter Wurf in diesem einen Treffer. Mit vielen Treffern rutscht der kleinste an Minimum plus Bonus heran, die Grenze liegt dann bis zu einer Spanne unter dem echten Minimum (40 von rund 750 Punkten bei Frostblitz Rang 11): der Preis für eine bewiesene Grenze. Der größte Treffer läge näher dran, aber ein einziger verstärkter Treffer machte ihn falsch. Ein Rang kommt in Frage, wenn sein Mindestschaden das Restleben des Ziels plus *Sicherheitsaufschlag* (Standard 20 %) deckt. Makros mit `/cast` bleiben unberührt.
|
||||||
|
|
||||||
Das Restleben des Ziels liefert die erste Quelle, die antwortet:
|
Das Restleben des Ziels liefert die erste Quelle, die antwortet:
|
||||||
|
|
||||||
@@ -1048,7 +1058,7 @@ Das Restleben des Ziels liefert die erste Quelle, die antwortet:
|
|||||||
|Lebensquelle des Ziels|Livezeile: welche der vier Quellen für dein aktuelles Ziel antwortet|
|
|Lebensquelle des Ziels|Livezeile: welche der vier Quellen für dein aktuelles Ziel antwortet|
|
||||||
|Zauber|Die im Zauberbuch gefundenen Angriffszauber mit Rangzahl|
|
|Zauber|Die im Zauberbuch gefundenen Angriffszauber mit Rangzahl|
|
||||||
|
|
||||||
Zauber je Klasse: Priester Göttliche Pein, Heiliges Feuer, Gedankenschlag; Druide Zorn, Sternenfeuer, Mondfeuer; Schamane Blitzschlag, Kettenblitzschlag, Erd-/Flammen-/Frostschock; Paladin Heiliger Schock, Hammer des Zorns, Exorzismus, Heiliger Zorn; Magier Feuerball, Frostblitz, Feuerschlag, Versengen, Pyroschlag; Hexenmeister Schattenblitz, Sengender Schmerz, Feuerbrand, Seelenfeuer, Feuersbrunst; Jäger Arkaner Schuss, Gezielter Schuss (Liste `FBDamageSpells`). `/fbp damage` schaltet um, `/fbp debug` protokolliert jede Entscheidung mit der genutzten Lebensquelle. Hinweis für Jäger: Für diese Klasse lädt das Addon nicht, Smart Damage läuft also erst nach `/fbp forceload`, siehe [Für welche Klassen es lädt](#für-welche-klassen-es-lädt).
|
Zauber je Klasse: Priester Göttliche Pein, Heiliges Feuer, Gedankenschlag; Druide Zorn, Sternenfeuer, Mondfeuer; Schamane Blitzschlag, Kettenblitzschlag, Erd-/Flammen-/Frostschock; Paladin Heiliger Schock, Hammer des Zorns, Exorzismus, Heiliger Zorn; Magier Feuerball, Frostblitz, Feuerschlag, Versengen, Pyroschlag; Hexenmeister Schattenblitz, Sengender Schmerz, Feuerbrand, Seelenfeuer, Feuersbrunst; Jäger Arkaner Schuss (Liste `FBDamageSpells`). Gezielter Schuss steht nicht darin: Sein Tooltip legt nur etwas auf den Waffenschaden, eine Schadenszahl gibt es dort nicht zu lesen. `/fbp damage` schaltet um, `/fbp debug` protokolliert jede Entscheidung mit der genutzten Lebensquelle. Hinweis für Jäger: Für diese Klasse lädt das Addon nicht, Smart Damage läuft also erst nach `/fbp forceload`, siehe [Für welche Klassen es lädt](#für-welche-klassen-es-lädt).
|
||||||
|
|
||||||
Solange Smart Damage aus ist, hört das Modul weder auf den Combatlog noch auf das Leben des Ziels, und die Angriffszauber liest es erst aus dem Zauberbuch, wenn du die Optionen öffnest.
|
Solange Smart Damage aus ist, hört das Modul weder auf den Combatlog noch auf das Leben des Ziels, und die Angriffszauber liest es erst aus dem Zauberbuch, wenn du die Optionen öffnest.
|
||||||
|
|
||||||
@@ -1118,7 +1128,7 @@ Das Fenster hat zwei eigene Reiter, *Buttons* und *Allgemein*. Die Module ergän
|
|||||||
|
|
||||||
**HealComm-Sync**: Austausch der Heilinformationen mit der Gruppe, siehe [HealComm-Sync](#healcomm-sync). Standardmäßig an.
|
**HealComm-Sync**: Austausch der Heilinformationen mit der Gruppe, siehe [HealComm-Sync](#healcomm-sync). Standardmäßig an.
|
||||||
|
|
||||||
**Sprache / Language**: schaltet zwischen Deutsch und Englisch um. Der Knopf öffnet dasselbe Kaskadenmenü wie die Zauberwahl. Die Umstellung wirkt **sofort**: `FBHealBox_ApplyLocale()` beschriftet die bereits gebaute Oberfläche neu, ein `/reload` ist nicht nötig. Beim ersten Start entscheidet `GetLocale()`: deutsche Clients starten auf Deutsch, alle anderen auf Englisch. Die Wahl wird pro Charakter gespeichert.
|
**Sprache / Language**: schaltet zwischen Deutsch, Englisch, Spanisch, Französisch und Italienisch um. Der Knopf öffnet dasselbe Kaskadenmenü wie die Zauberwahl. Die Umstellung wirkt **sofort**: `FBHealBox_ApplyLocale()` beschriftet die bereits gebaute Oberfläche neu, ein `/reload` ist nicht nötig. Beim ersten Start entscheidet `GetLocale()`: deutsche, spanische (auch mexikanische), französische und italienische Clients starten in ihrer Sprache, alle anderen auf Englisch. Fehlende Texte fallen auf Englisch zurück. Die Wahl wird pro Charakter gespeichert.
|
||||||
|
|
||||||
**Fenster verschieben:** am Rahmen ziehen. Schließen über das X oben rechts, mit **Escape** oder per `/fbp config`. Escape wird über einen Hook auf `ToggleGameMenu` abgefangen (zusätzlich zu `UISpecialFrames`), damit es auch auf Clients funktioniert, die diese Liste nicht auswerten; ist Blizzards Spielmenü offen, schließt Escape wie gewohnt zuerst dieses.
|
**Fenster verschieben:** am Rahmen ziehen. Schließen über das X oben rechts, mit **Escape** oder per `/fbp config`. Escape wird über einen Hook auf `ToggleGameMenu` abgefangen (zusätzlich zu `UISpecialFrames`), damit es auch auf Clients funktioniert, die diese Liste nicht auswerten; ist Blizzards Spielmenü offen, schließt Escape wie gewohnt zuerst dieses.
|
||||||
|
|
||||||
@@ -1165,6 +1175,8 @@ Der Kern des Addons. Drei unabhängige Quellen speisen die Balken.
|
|||||||
|
|
||||||
Ziel ist die Einheit des angeklickten Heal Box Buttons, sofern derselbe Zauber binnen `FBPREDICT_CLICK_TIME` (2 Sekunden) nach dem Klick anläuft; ein Klick, während noch ein anderer Zauber gewirkt wird, wartet auf den nächsten Castbeginn, das passt auch zur Zauberwarteschlange von Clientmods. Ein Cast von der Aktionsleiste oder aus einem Makro geht an dein freundliches Ziel, sonst an dich selbst. Ein Klick gilt für genau einen Cast: Ist sein Zauber angelaufen, durchgegangen oder gescheitert, gehört der nächste Cast nicht mehr zu ihm. Eine Fehlermeldung oder ein gescheiterter Cast beantwortet immer den jüngsten Versuch. Damit klar ist, welcher das ist, zählt das Addon jeden Versuch mit, auch von der Aktionsleiste, aus Makros und aus dem Zauberbuch; dafür hängt es sich vor `UseAction`, `CastSpellByName` und `CastSpell`, zählt und reicht alles unverändert weiter. Bis 1.4.6 galt das Ziel eines Klicks zwei Sekunden und sein Rang drei Sekunden lang für jeden folgenden Cast, auch nach einem gescheiterten Klick.
|
Ziel ist die Einheit des angeklickten Heal Box Buttons, sofern derselbe Zauber binnen `FBPREDICT_CLICK_TIME` (2 Sekunden) nach dem Klick anläuft; ein Klick, während noch ein anderer Zauber gewirkt wird, wartet auf den nächsten Castbeginn, das passt auch zur Zauberwarteschlange von Clientmods. Ein Cast von der Aktionsleiste oder aus einem Makro geht an dein freundliches Ziel, sonst an dich selbst. Ein Klick gilt für genau einen Cast: Ist sein Zauber angelaufen, durchgegangen oder gescheitert, gehört der nächste Cast nicht mehr zu ihm. Eine Fehlermeldung oder ein gescheiterter Cast beantwortet immer den jüngsten Versuch. Damit klar ist, welcher das ist, zählt das Addon jeden Versuch mit, auch von der Aktionsleiste, aus Makros und aus dem Zauberbuch; dafür hängt es sich vor `UseAction`, `CastSpellByName` und `CastSpell`, zählt und reicht alles unverändert weiter. Bis 1.4.6 galt das Ziel eines Klicks zwei Sekunden und sein Rang drei Sekunden lang für jeden folgenden Cast, auch nach einem gescheiterten Klick.
|
||||||
|
|
||||||
|
Gruppenheilungen (`FBCommGroupHeal`, Gebet der Heilung) zeigen ihre Vorhersage auf dir und jedem Gruppenmitglied in Reichweite, also auf derselben Liste, die über HealComm rausgeht, egal welche Plakette oder Raidzelle du angeklickt hast. Im Raid ist das deine eigene Untergruppe, genau die heilt Gebet der Heilung. Bis 1.4.7 stand die Vorhersage nur auf der angeklickten Einheit.
|
||||||
|
|
||||||
Instants bekommen bewusst **keine** Vorhersage: Die Heilung ist da, bevor ein Balken sie zeigen könnte.
|
Instants bekommen bewusst **keine** Vorhersage: Die Heilung ist da, bevor ein Balken sie zeigen könnte.
|
||||||
|
|
||||||
### Heilung über Zeit
|
### Heilung über Zeit
|
||||||
@@ -1184,7 +1196,7 @@ Das Tickintervall ist in Vanilla nicht aus dem Tooltip lesbar und steht deshalb
|
|||||||
|
|
||||||
Vanilla-Tooltips zeigen den nackten Grundwert, der Heilbonus deiner Ausrüstung steht nicht darin. Gelernte Werte aus dem Combatlog tragen ihn von selbst, die Lücke gibt es also nur bei Rängen, die du nie gewirkt hast. Liefert eine API den Bonus, schließt das Addon diese Lücke: Der Wert wird wie in Vanilla üblich mit Zauberzeit geteilt durch 3,5 gewichtet und bei 3,5 Sekunden gedeckelt, Instants zählen als 1,5. Eine Große Heilung mit 3 Sekunden Zauberzeit startet bei +700 Heilung also 600 über ihrem Tooltip, eine Blitzheilung mit 1,5 Sekunden 300.
|
Vanilla-Tooltips zeigen den nackten Grundwert, der Heilbonus deiner Ausrüstung steht nicht darin. Gelernte Werte aus dem Combatlog tragen ihn von selbst, die Lücke gibt es also nur bei Rängen, die du nie gewirkt hast. Liefert eine API den Bonus, schließt das Addon diese Lücke: Der Wert wird wie in Vanilla üblich mit Zauberzeit geteilt durch 3,5 gewichtet und bei 3,5 Sekunden gedeckelt, Instants zählen als 1,5. Eine Große Heilung mit 3 Sekunden Zauberzeit startet bei +700 Heilung also 600 über ihrem Tooltip, eine Blitzheilung mit 1,5 Sekunden 300.
|
||||||
|
|
||||||
Die Zauberzeit stammt aus dem Tooltip jedes einzelnen Rangs, ebenso Reichweite und Abklingzeit (`/fbp` listet alle drei je Zauber). Ränge, die unter Stufe 20 gelernt werden, bekommen wie im Spiel nur einen Teil des Bonus: je Stufe unter 20 sind es 3,75 Prozent weniger, Geringes Heilen Rang 3 (gelernt mit Stufe 10) erhält also 62,5 Prozent. Der Tooltip verrät die Lernstufe eines Rangs nicht, deshalb stehen diese Ränge in `FBRankLearnLevel`. Ohne diesen Abschlag hielte Smart Healing kleine Ränge mit viel +Heilung für deutlich stärker, als sie sind.
|
Die Zauberzeit stammt aus dem Tooltip jedes einzelnen Rangs, ebenso Reichweite und Abklingzeit (`/fbp` listet alle drei je Zauber). Für die Gewichtung nimmt das Spiel aber die Zauberzeit **vor Talenten**, während der Tooltip schon die verkürzte zeigt: mit Göttlichem Furor steht bei Großer Heilung 2,5 Sekunden, mit Naturalist bei Heilender Berührung 3,0, mit Verbesserter Welle der Heilung bei Welle der Heilung 2,5. Für die Zauber, deren Zauberzeit ein Talent verkürzt (Heilen, Große Heilung, Heilende Berührung, Welle der Heilung), steht die Basis-Zauberzeit deshalb in `FBBaseCastTime`; alle anderen nehmen den Tooltip. Bis 1.4.7 bekamen ungelernte Ränge dieser vier Zauber bei einem geskillten Heiler ein Siebtel zu wenig vom Bonus. Ränge, die unter Stufe 20 gelernt werden, bekommen wie im Spiel nur einen Teil des Bonus: je Stufe unter 20 sind es 3,75 Prozent weniger, Geringes Heilen Rang 3 (gelernt mit Stufe 10) erhält also 62,5 Prozent. Der Tooltip verrät die Lernstufe eines Rangs nicht, deshalb stehen diese Ränge in `FBRankLearnLevel`. Ohne diesen Abschlag hielte Smart Healing kleine Ränge mit viel +Heilung für deutlich stärker, als sie sind.
|
||||||
|
|
||||||
Gesucht wird `GetSpellBonusHealing`, dazu `GetSpellBonusHeal` und `GetHealingBonus`, erst als globale Funktion, dann in einer `ClassicAPI`-Tabelle. **ClassicAPI** bringt das mit; ohne eine solche API bleibt der Bonus 0 und es ändert sich nichts. `/fbp` nennt den gefundenen Wert und ob er angewandt wird, `/fbp healbonus` schaltet ihn ab. Der erste gelernte Wert eines Rangs schlägt die Schätzung immer.
|
Gesucht wird `GetSpellBonusHealing`, dazu `GetSpellBonusHeal` und `GetHealingBonus`, erst als globale Funktion, dann in einer `ClassicAPI`-Tabelle. **ClassicAPI** bringt das mit; ohne eine solche API bleibt der Bonus 0 und es ändert sich nichts. `/fbp` nennt den gefundenen Wert und ob er angewandt wird, `/fbp healbonus` schaltet ihn ab. Der erste gelernte Wert eines Rangs schlägt die Schätzung immer.
|
||||||
|
|
||||||
@@ -1210,7 +1222,7 @@ Tooltips liefern in 1.12 nur Basiswerte **ohne** +Heilung, und eine API für Zau
|
|||||||
|
|
||||||
Alles davon landet pro Zauber **und Rang** in `HealBox.PredictMemory` und übersteht den Logout.
|
Alles davon landet pro Zauber **und Rang** in `HealBox.PredictMemory` und übersteht den Logout.
|
||||||
|
|
||||||
Zwei Schutzregeln halten den Speicher sauber. **Crits werden nicht gelernt**: die Crit-Formulierung lässt den Zaubernamen als „Flash Heal critically" durchs Muster fallen, und der steht in keiner Watchlist. Und gelernt wird nur bei **gesichertem Rang**, also bei Casts über die HealBox-Buttons; sonst würde ein Rang-3-Cast von der Aktionsleiste dem Maximalrang zugeschrieben und die Vorhersage nach unten ziehen. Die laufende Anzeige korrigiert sich trotzdem immer, geschützt ist nur der dauerhafte Speicher. Die Heilung steht meist erst nach dem Castende im Combatlog, ein beendeter Cast wartet deshalb noch `FBPREDICT_CLICK_TIME` (2) Sekunden auf seine Zeile. Bis 1.4.6 zählte nur ein noch laufender Cast, Direktheilungen wurden so kaum gelernt.
|
Zwei Schutzregeln halten den Speicher sauber. **Crits werden nicht gelernt**: Crit-Zeilen (`HEALEDCRITSELFOTHER`, `HEALEDCRITSELFSELF`) werden eigens erkannt; sie schließen ihren Cast ab wie jede Heilzeile, ihr Betrag wird aber nicht gemerkt. Bis 1.4.7 rutschte eine Crit-Zeile als Zauber „Flash Heal critically" durch und ließ ihren Cast weiter warten; ein kleinerer Rang desselben Zaubers von der Aktionsleiste binnen zwei Sekunden konnte so als Rang des Buttons gelernt werden. Und gelernt wird nur bei **gesichertem Rang**, also bei Casts über die HealBox-Buttons; sonst würde ein Rang-3-Cast von der Aktionsleiste dem Maximalrang zugeschrieben und die Vorhersage nach unten ziehen. Die laufende Anzeige korrigiert sich trotzdem immer, geschützt ist nur der dauerhafte Speicher. Die Heilung steht meist erst nach dem Castende im Combatlog, ein beendeter Cast wartet deshalb noch `FBPREDICT_CLICK_TIME` (2) Sekunden auf seine Zeile. Bis 1.4.6 zählte nur ein noch laufender Cast, Direktheilungen wurden so kaum gelernt.
|
||||||
|
|
||||||
Welcher Zauber was kann, entscheidet der Tooltip selbst; ein Zauber darf mehreres sein. Regrowth etwa liefert Sofortheilung *und* HoT und wird auch so behandelt.
|
Welcher Zauber was kann, entscheidet der Tooltip selbst; ein Zauber darf mehreres sein. Regrowth etwa liefert Sofortheilung *und* HoT und wird auch so behandelt.
|
||||||
|
|
||||||
@@ -1231,7 +1243,7 @@ HealComm-1.0 funkt reinen Klartext über `SendAddonMessage` mit dem Prefix `Heal
|
|||||||
|
|
||||||
Gesendet wird ins Raid, sonst in die Gruppe, sonst gar nicht. Im Schlachtfeld geht es über den Kanal `BATTLEGROUND`, wie bei HealComm-1.0, denn über `RAID` erreicht man dort niemanden. Die Beträge sind die selbstkorrigierten Combatlog-Werte, also eher genauer als das, was ein echtes HealComm mit ItemBonusLib schätzt.
|
Gesendet wird ins Raid, sonst in die Gruppe, sonst gar nicht. Im Schlachtfeld geht es über den Kanal `BATTLEGROUND`, wie bei HealComm-1.0, denn über `RAID` erreicht man dort niemanden. Die Beträge sind die selbstkorrigierten Combatlog-Werte, also eher genauer als das, was ein echtes HealComm mit ItemBonusLib schätzt.
|
||||||
|
|
||||||
Ein paar Feinheiten: Bei erfolgreichem Castende geht **kein** `Healstop` raus; HealComm-Empfänger lassen den Eintrag selbst zur Castzeit auslaufen. Prayer of Healing geht korrekt als `GrpHeal` mit allen Zielen in Reichweite raus. Und ein HoT von der Aktionsleiste wird beim ersten eigenen Combatlog-Tick nachgemeldet, mit der dann noch verbleibenden Laufzeit, denn erst „… from **your** Renew" beweist, dass er von dir stammt. Eingehende Befehle liest das Addon unabhängig von großen und kleinen Buchstaben; pfUI etwa schickt `HealStop`.
|
Ein paar Feinheiten: Bei erfolgreichem Castende geht **kein** `Healstop` raus; HealComm-Empfänger lassen den Eintrag selbst zur Castzeit auslaufen. Prayer of Healing geht korrekt als `GrpHeal` mit allen Zielen in Reichweite raus, und deine eigenen Balken zeigen es auf denselben Mitgliedern. Und ein HoT von der Aktionsleiste wird beim ersten eigenen Combatlog-Tick nachgemeldet, mit der dann noch verbleibenden Laufzeit, denn erst „… from **your** Renew" beweist, dass er von dir stammt. Eingehende Befehle liest das Addon unabhängig von großen und kleinen Buchstaben; pfUI etwa schickt `HealStop`.
|
||||||
|
|
||||||
Beim Empfang werden eigene Nachrichten über den Absendernamen gefiltert, und da HealComm eingehende Heilungen pro Caster ablegt, kann sich nichts doppeln, selbst wenn parallel noch ein echtes HealComm mitfunkt. HoT-Nachrichten tragen nur Laufzeiten und keine Beträge; HealComm zählt sie im eigenen `getHeal` nicht mit, hier passiert dasselbe. Werte anderer Addons werden begrenzt: Beträge auf `FBCOMM_MAX_AMOUNT` (20000), Zauberzeiten und Verzögerungen auf `FBCOMM_MAX_CAST_MS` (10 Sekunden). Eine kaputte Nachricht kann so keinen Balken minutenlang füllen.
|
Beim Empfang werden eigene Nachrichten über den Absendernamen gefiltert, und da HealComm eingehende Heilungen pro Caster ablegt, kann sich nichts doppeln, selbst wenn parallel noch ein echtes HealComm mitfunkt. HoT-Nachrichten tragen nur Laufzeiten und keine Beträge; HealComm zählt sie im eigenen `getHeal` nicht mit, hier passiert dasselbe. Werte anderer Addons werden begrenzt: Beträge auf `FBCOMM_MAX_AMOUNT` (20000), Zauberzeiten und Verzögerungen auf `FBCOMM_MAX_CAST_MS` (10 Sekunden). Eine kaputte Nachricht kann so keinen Balken minutenlang füllen.
|
||||||
|
|
||||||
@@ -1359,6 +1371,7 @@ Alle Stellschrauben stehen als Globals oben in ihrem jeweiligen Abschnitt und la
|
|||||||
|`FBHoTSpells`|(Tabelle)|Zauber mit Heilung über Zeit, die Smart Healing nie abrangt|
|
|`FBHoTSpells`|(Tabelle)|Zauber mit Heilung über Zeit, die Smart Healing nie abrangt|
|
||||||
|`FBSmartSkip`|(Tabelle)|Gruppenheilungen und Zauber mit Abklingzeit, die Smart Healing immer wie belegt wirkt (Zauber mit Abklingzeit im Tooltip bleiben ohnehin unberührt)|
|
|`FBSmartSkip`|(Tabelle)|Gruppenheilungen und Zauber mit Abklingzeit, die Smart Healing immer wie belegt wirkt (Zauber mit Abklingzeit im Tooltip bleiben ohnehin unberührt)|
|
||||||
|`FBRankLearnLevel`|(Tabelle)|Lernstufe der Ränge unter Stufe 20, für den gekürzten Anteil an +Heilung|
|
|`FBRankLearnLevel`|(Tabelle)|Lernstufe der Ränge unter Stufe 20, für den gekürzten Anteil an +Heilung|
|
||||||
|
|`FBBaseCastTime`|(Tabelle)|Zauberzeit vor Talenten für die Heilzauber, die ein Talent beschleunigt, für den Anteil an +Heilung|
|
||||||
|`FBBlockedClasses`|`WARRIOR`, `ROGUE`, `HUNTER`|Klassen, für die das Addon ohne `/fbp forceload` nicht lädt|
|
|`FBBlockedClasses`|`WARRIOR`, `ROGUE`, `HUNTER`|Klassen, für die das Addon ohne `/fbp forceload` nicht lädt|
|
||||||
|`FBHealBoxDefaults`|(Tabelle)|Vorgabe jeder Einstellung; fehlende Schlüssel kommen von hier|
|
|`FBHealBoxDefaults`|(Tabelle)|Vorgabe jeder Einstellung; fehlende Schlüssel kommen von hier|
|
||||||
|`FBCOMM_MAX_AMOUNT` · `FBCOMM_MAX_CAST_MS`|20000 · 10000|Grenzen für Beträge und Zauberzeiten (ms) in HealComm-Nachrichten anderer|
|
|`FBCOMM_MAX_AMOUNT` · `FBCOMM_MAX_CAST_MS`|20000 · 10000|Grenzen für Beträge und Zauberzeiten (ms) in HealComm-Nachrichten anderer|
|
||||||
@@ -1394,13 +1407,15 @@ Alle Stellschrauben stehen als Globals oben in ihrem jeweiligen Abschnitt und la
|
|||||||
|`FBHealBox_IsHoT(base, ranks)`|Heilung über Zeit? Namensliste plus Tooltip, Zauberwache und laufende HoTs. Smart Healing lässt diese aus|
|
|`FBHealBox_IsHoT(base, ranks)`|Heilung über Zeit? Namensliste plus Tooltip, Zauberwache und laufende HoTs. Smart Healing lässt diese aus|
|
||||||
|`FBHealBox_HealFamily(base)` · `FBHealBox_DirectAmount(spell, sd)`|Die Heilkette eines Zaubers; die erwartete Heilung eines Rangs, oder nil, wenn der Zauber nicht in Frage kommt|
|
|`FBHealBox_HealFamily(base)` · `FBHealBox_DirectAmount(spell, sd)`|Die Heilkette eines Zaubers; die erwartete Heilung eines Rangs, oder nil, wenn der Zauber nicht in Frage kommt|
|
||||||
|`FBPredict_ExpectedDirect(spell, rank, info, id)`|Erwartete Sofortheilung: gelernter Wert, sonst Tooltip plus Anteil am Ausrüstungsbonus|
|
|`FBPredict_ExpectedDirect(spell, rank, info, id)`|Erwartete Sofortheilung: gelernter Wert, sonst Tooltip plus Anteil am Ausrüstungsbonus|
|
||||||
|`FBHealBox_ProbeHealBonus()` · `FBHealBox_HealingBonus()` · `FBHealBox_HealBonusFor(id)`|Sucht eine API für den Heilbonus, liest sie aus und gewichtet nach Zauberzeit|
|
|`FBHealBox_ProbeHealBonus()` · `FBHealBox_HealingBonus()` · `FBHealBox_HealBonusFor(id, spell, rank)`|Sucht eine API für den Heilbonus, liest sie aus und gewichtet nach Zauberzeit|
|
||||||
|
|`FBHealBox_BaseCastSeconds(spell, rank, id)`|Zauberzeit für diese Gewichtung: aus `FBBaseCastTime`, sonst aus dem Tooltip|
|
||||||
|`FBHealBox_SpellCastSeconds(id)`|Zauberzeit aus dem Tooltip (0 = Instant), je Zauberbuchplatz gemerkt|
|
|`FBHealBox_SpellCastSeconds(id)`|Zauberzeit aus dem Tooltip (0 = Instant), je Zauberbuchplatz gemerkt|
|
||||||
|`FBHealBox_ApplyBlizzParty()` · `FBHealBox_HideBlizzPartyActive()`|Versteckt Blizzards Gruppenfenster oder gibt sie zurück, samt Sperre gegen den Anheftmodus|
|
|`FBHealBox_ApplyBlizzParty()` · `FBHealBox_HideBlizzPartyActive()`|Versteckt Blizzards Gruppenfenster oder gibt sie zurück, samt Sperre gegen den Anheftmodus|
|
||||||
|`FBHealBox_SetPowerColor(bar, cache, ptype)`|Färbt einen Ressourcenbalken für Mana, Wut, Fokus oder Energie|
|
|`FBHealBox_SetPowerColor(bar, cache, ptype)`|Färbt einen Ressourcenbalken für Mana, Wut, Fokus oder Energie|
|
||||||
|`FBHealBox_ApplyBarBG(f)` · `FBHealBox_ApplyBarBGAll()`|Setzt den Hintergrund hinter den Balken einer Plakette nach der Option `BarBG`|
|
|`FBHealBox_ApplyBarBG(f)` · `FBHealBox_ApplyBarBGAll()`|Setzt den Hintergrund hinter den Balken einer Plakette nach der Option `BarBG`|
|
||||||
|`FBHealBox_RefreshUnitsByName(names)`|Zeichnet nur die Plaketten neu, deren Einheit in der Namensliste steht; das Raidmodul bekommt dieselbe Liste über den Hook `RefreshNames`|
|
|`FBHealBox_RefreshUnitsByName(names)`|Zeichnet nur die Plaketten neu, deren Einheit in der Namensliste steht; das Raidmodul bekommt dieselbe Liste über den Hook `RefreshNames`|
|
||||||
|`FBPredict_ScanPlayerBuffTimes()`|Liest alle eigenen Bufflaufzeiten einmal je Frame in eine Tabelle Textur nach Sekunden|
|
|`FBPredict_ScanPlayerBuffTimes()`|Liest alle eigenen Bufflaufzeiten einmal je Frame in eine Tabelle Textur nach Sekunden|
|
||||||
|
|`FBPredict_PlayerBuffLeft(spell, w)` · `FBHealBox_PlayerBuffName(id)`|Restzeit eines eigenen Buffs, nur für die Fassung, die du trägst (geteilte Textur: Buffname aus dem Tooltip, sonst nach Dauer)|
|
||||||
|`FBHealBox_ApiFailed()`|Stellt Reichweite, Abstand und Sichtlinie auf den geschützten Einzelaufruf zurück, wenn ein Durchlauf geworfen hat|
|
|`FBHealBox_ApiFailed()`|Stellt Reichweite, Abstand und Sichtlinie auf den geschützten Einzelaufruf zurück, wenn ein Durchlauf geworfen hat|
|
||||||
|`FBHealBox_SweepResult(where, ok, err)` · `FBHealBox_ReportError(where, err)`|Wertet einen geschützten Durchlauf aus; meldet Fehler einmal im Chat, weitere mit `/fbp debug`|
|
|`FBHealBox_SweepResult(where, ok, err)` · `FBHealBox_ReportError(where, err)`|Wertet einen geschützten Durchlauf aus; meldet Fehler einmal im Chat, weitere mit `/fbp debug`|
|
||||||
|`FBHealBox_UpperTex(tex)`|Groß geschriebener Texturpfad, gemerkt, damit `strupper` nicht je Aufruf zuteilt|
|
|`FBHealBox_UpperTex(tex)`|Groß geschriebener Texturpfad, gemerkt, damit `strupper` nicht je Aufruf zuteilt|
|
||||||
@@ -1423,6 +1438,7 @@ Alle Stellschrauben stehen als Globals oben in ihrem jeweiligen Abschnitt und la
|
|||||||
|`FBHealBox_SetWatchBuff(name)` · `FBHealBox_HasWatchBuff(unit)` · `FBHealBox_CheckWatchBuff(unit, f)`|Buff-Wache: wählen, eine Einheit prüfen, Rahmen färben|
|
|`FBHealBox_SetWatchBuff(name)` · `FBHealBox_HasWatchBuff(unit)` · `FBHealBox_CheckWatchBuff(unit, f)`|Buff-Wache: wählen, eine Einheit prüfen, Rahmen färben|
|
||||||
|`FBHealBox_UnitInRange(unit)` · `FBHealBox_CheckRangeAll()`|Reichweiten-Fading|
|
|`FBHealBox_UnitInRange(unit)` · `FBHealBox_CheckRangeAll()`|Reichweiten-Fading|
|
||||||
|`FBUnitLOSBlocked(unit)` · `FBLOS_OnError(msg)` · `FBLOS_Clear(name)` · `FBHealBox_CheckLOSAll()`|Sichtlinie (UnitXP oder Fehlermeldungs-Fallback)|
|
|`FBUnitLOSBlocked(unit)` · `FBLOS_OnError(msg)` · `FBLOS_Clear(name)` · `FBHealBox_CheckLOSAll()`|Sichtlinie (UnitXP oder Fehlermeldungs-Fallback)|
|
||||||
|
|`FBLOS_NoteClick(name, spell, now)` · `FBLOS_CastStart(spell, ms)` · `FBLOS_CastDelayed(ms)` · `FBLOS_CastDone()` · `FBLOS_Reset()`|Kandidaten für eine Sichtlinien-Meldung: der letzte Klick (`FBLOSClick`) und der laufende Cast (`FBLOSCast`); `FBLOS_CastDone` behält einen während des Casts vorgemerkten Klick|
|
||||||
|`FBMenu_OpenBuffMenu(anchor)`|Die Buff-Auswahl (dasselbe Kaskadenmenü)|
|
|`FBMenu_OpenBuffMenu(anchor)`|Die Buff-Auswahl (dasselbe Kaskadenmenü)|
|
||||||
|`HealBoxAttachMode(mode)`|Umschaltung eigene Plaketten ↔ Standard-Gruppenfenster|
|
|`HealBoxAttachMode(mode)`|Umschaltung eigene Plaketten ↔ Standard-Gruppenfenster|
|
||||||
|`HealBoxScale(this, scale)`|Skalierung|
|
|`HealBoxScale(this, scale)`|Skalierung|
|
||||||
@@ -1482,11 +1498,13 @@ Die vier Funktionen, die die Balken speisen. Alle erwarten einen **Spielernamen*
|
|||||||
|-|-|
|
|-|-|
|
||||||
|`FBPredict_GetSpellInfo(bookID, name)`|Wertet den Zauberbuch-Tooltip aus (Direkt / HoT / Schild)|
|
|`FBPredict_GetSpellInfo(bookID, name)`|Wertet den Zauberbuch-Tooltip aus (Direkt / HoT / Schild)|
|
||||||
|`FBPredict_BuildWatch()`|Baut die Watchlist nach jedem Zauberbuch-Scan|
|
|`FBPredict_BuildWatch()`|Baut die Watchlist nach jedem Zauberbuch-Scan|
|
||||||
|
|`FBPredict_BuildBuffOrder()` · `FBPredict_ButtonSpells()` · `FBHealBox_PickBuffVariant(…)`|Welche Buffs ein Icon bekommen (nur die auf einem Button, ein Icon je Buff und Gruppenversion) und welche Fassung ein Icon zeigt|
|
||||||
|`FBPredict_NoteCast(castString, target)`|Merkt Ziel und Rang **vor** dem Cast vor (`FBPredictClick`)|
|
|`FBPredict_NoteCast(castString, target)`|Merkt Ziel und Rang **vor** dem Cast vor (`FBPredictClick`)|
|
||||||
|`FBPredict_TakeClick(spell, castMs)` · `FBPredict_ClickDone()` · `FBPredict_ClickFailed(interrupted)`|Was aus dem Klick bei Castbeginn, Castende und Fehlschlag wird (`FBPredictClick`, `FBPredictCastClick`)|
|
|`FBPredict_TakeClick(spell, castMs)` · `FBPredict_ClickDone()` · `FBPredict_ClickFailed(interrupted)`|Was aus dem Klick bei Castbeginn, Castende und Fehlschlag wird (`FBPredictClick`, `FBPredictCastClick`)|
|
||||||
|`FBPredict_HookAttempts()`|Zählt jeden Zauberversuch (`UseAction`, `CastSpellByName`, `CastSpell`) in `FBPredictClickSeq`|
|
|`FBPredict_HookAttempts()`|Zählt jeden Zauberversuch (`UseAction`, `CastSpellByName`, `CastSpell`) in `FBPredictClickSeq`|
|
||||||
|`FBPredict_ConfirmPending()`|Bestätigt HoT, Schild und Buff eines Klicks, dessen Cast durchgegangen ist|
|
|`FBPredict_ConfirmPending()`|Bestätigt HoT, Schild und Buff eines Klicks, dessen Cast durchgegangen ist|
|
||||||
|`FBPredict_CastStart(spell, castMs)` · `FBPredict_CastEnd(success)`|Direktheilung starten und beenden; eine erfolgreiche bleibt für ihre Zeile im Combatlog in `FBPredictLastDirect`|
|
|`FBPredict_CastStart(spell, castMs)` · `FBPredict_CastEnd(success)`|Direktheilung starten und beenden; eine erfolgreiche bleibt für ihre Zeile im Combatlog in `FBPredictLastDirect`|
|
||||||
|
|`FBPredict_GroupTargets()` · `FBPredict_CastHits(d, name)` · `FBPredict_CastLanded(d, name)`|Ziele einer Gruppenheilung (du und deine Gruppe in Reichweite); trifft ein Cast diese Einheit; die Heilzeile eines Ziels ist angekommen|
|
||||||
|`FBPredict_ScanUnit(unit)`|Aura-Abgleich: Anwendung bestätigen, Wegfall erkennen|
|
|`FBPredict_ScanUnit(unit)`|Aura-Abgleich: Anwendung bestätigen, Wegfall erkennen|
|
||||||
|`FBPredict_StartHoT(…)` · `FBPredict_StartShield(…)`|Tracking scharfschalten|
|
|`FBPredict_StartHoT(…)` · `FBPredict_StartShield(…)`|Tracking scharfschalten|
|
||||||
|`FBPredict_ParseCombat(event, msg)`|Combatlog-Auswertung|
|
|`FBPredict_ParseCombat(event, msg)`|Combatlog-Auswertung|
|
||||||
@@ -1518,7 +1536,7 @@ 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 (`FBClassSpells.Name` am Dateianfang) oder ist noch nicht gelernt. Die Liste lässt sich frei erweitern.
|
**Ein Zauber taucht im Menü nicht auf.** Er steht nicht in der Zauberliste deiner Klasse (`FBClassSpells.Name` am Dateianfang) oder ist noch nicht gelernt. Die Liste lässt sich frei erweitern.
|
||||||
|
|
||||||
**Client in einer anderen Sprache.** Klassenerkennung, Dispel-Färbung und Klassenicon funktionieren auf jedem Client. Die Zauberlisten (`FBClassSpells.Name`, Buff-Wache, Smart Damage) enthalten englische Zaubernamen, und die Vorhersage liest englische Tooltips. Auf einem deutschen, französischen oder spanischen Client bleibt das Zaubermenü deshalb leer, und Vorhersage und Smart Healing erkennen die Zauber nicht. Zauber, die per Drag & Drop aus dem Zauberbuch belegt werden, funktionieren auf den Buttons trotzdem.
|
**Client in einer anderen Sprache.** Klassenerkennung, Dispel-Färbung und Klassenicon funktionieren auf jedem Client. Die Zauberlisten (`FBClassSpells.Name`, Buff-Wache, Smart Damage) enthalten englische Zaubernamen, und die Vorhersage liest englische Tooltips. Auf einem deutschen, französischen oder spanischen Client bleibt das Zaubermenü deshalb leer, und Vorhersage und Smart Healing erkennen die Zauber nicht. Zauber, die per Drag & Drop aus dem Zauberbuch belegt werden, funktionieren auf den Buttons trotzdem. Einige Tabellen von Smart Healing (`FBHealChains`, `FBHoTSpells`, `FBSmartSkip`, `FBRankLearnLevel`, `FBBaseCastTime`) tragen die deutschen Zaubernamen schon mit; sie greifen, sobald die Tooltips gelesen werden können. Die HealComm-Kürzel (`FBCommHoTCode`, `FBCommGroupHeal`) bleiben englisch, ebenso `FBClassSpells.Name`.
|
||||||
|
|
||||||
**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.
|
**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.
|
||||||
|
|
||||||
@@ -1563,6 +1581,7 @@ 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
|
* Heilvorhersage für Direktheilung, HoT-Restticks und Absorb-Schilde, selbstkorrigierend über den Combatlog
|
||||||
* HealComm-Sync mit Puppeteer, pfUI, Luna und Co., ohne Ace-Bibliotheken
|
* HealComm-Sync mit Puppeteer, pfUI, Luna und Co., ohne Ace-Bibliotheken
|
||||||
* Lokalisierung Deutsch, Englisch, Spanisch, Französisch und Italienisch, im laufenden Spiel umschaltbar
|
* Lokalisierung Deutsch, Englisch, Spanisch, Französisch und Italienisch, im laufenden Spiel umschaltbar
|
||||||
|
* 1.4.7.1: Nachlese zu einem externen Review. Buff-Icons nur für Buffs auf deinen Buttons, ein Icon für Buff und Gruppenversion; die Sichtlinie übersteht Spamklicks und Zauberwarteschlangen von Clientmods während eines Casts; +Heilung nach der Zauberzeit vor Talenten gewichtet; Crit-Zeilen schließen ihren Cast ab und werden nie gelernt; Gebet der Heilung zeigt die Vorhersage auf der ganzen Gruppe; Smart Damage liest Arkaner Schuss und Flammenschock und lernt nur aus normalen Treffern; Raidzellen übernehmen spät geladene Namen; siehe CHANGELOG
|
||||||
* 1.4.7: die vollständige Codeprüfung. Behoben: Geschwächte Seele sichtbar, HoTs und Schilde anderer Heiler zählen nicht mehr als deine, Reichweite und Zauberzeit an der richtigen Stelle im Tooltip gelesen, Smart Healing lässt Gruppenheilungen und Zauber mit Abklingzeit in Ruhe und bewertet Ränge unter Stufe 20 richtig, Sichtlinienfehler markieren nur die angeklickte Einheit, Klassentabellen in jeder Clientsprache, Skalierungsregler verschiebt die Plaketten nicht mehr, Drag & Drop auf die Minibuttons im Raid repariert, ein Klick gilt nur für den Cast, den er auslöst, Direktheilungen werden gelernt, der Mindestschaden von Smart Damage ist wieder sicher, und seine eigene Lebensschätzung bleibt aus Raids heraus. Leistung: Neuzeichnen einmal je Frame gesammelt, Manaereignisse zeichnen nur den Manastreifen, Reichweite einmal je Einheit, Zauberbuch einmal je Salve gelesen, Smart Damage ruht, solange es aus ist. Robustheit: allgemeine Globals mit `FB` versehen, Smart Damage läuft ohne Ticker, Fehler in Modulen und Durchläufen werden gemeldet, Schlachtfeldkanal und Grenzen für HealComm, toter Code und doppelte Helfer entfernt; siehe CHANGELOG
|
* 1.4.7: die vollständige Codeprüfung. Behoben: Geschwächte Seele sichtbar, HoTs und Schilde anderer Heiler zählen nicht mehr als deine, Reichweite und Zauberzeit an der richtigen Stelle im Tooltip gelesen, Smart Healing lässt Gruppenheilungen und Zauber mit Abklingzeit in Ruhe und bewertet Ränge unter Stufe 20 richtig, Sichtlinienfehler markieren nur die angeklickte Einheit, Klassentabellen in jeder Clientsprache, Skalierungsregler verschiebt die Plaketten nicht mehr, Drag & Drop auf die Minibuttons im Raid repariert, ein Klick gilt nur für den Cast, den er auslöst, Direktheilungen werden gelernt, der Mindestschaden von Smart Damage ist wieder sicher, und seine eigene Lebensschätzung bleibt aus Raids heraus. Leistung: Neuzeichnen einmal je Frame gesammelt, Manaereignisse zeichnen nur den Manastreifen, Reichweite einmal je Einheit, Zauberbuch einmal je Salve gelesen, Smart Damage ruht, solange es aus ist. Robustheit: allgemeine Globals mit `FB` versehen, Smart Damage läuft ohne Ticker, Fehler in Modulen und Durchläufen werden gemeldet, Schlachtfeldkanal und Grenzen für HealComm, toter Code und doppelte Helfer entfernt; siehe CHANGELOG
|
||||||
* 1.4.6: Leistungsdurchgang ohne Funktionsänderung (nur geänderte Einheiten werden neu gezeichnet, über den Hook `RefreshNames`, Raid-Zaubertimer überspringen stille Zellen, Zaubertimer steigen früher aus); siehe CHANGELOG
|
* 1.4.6: Leistungsdurchgang ohne Funktionsänderung (nur geänderte Einheiten werden neu gezeichnet, über den Hook `RefreshNames`, Raid-Zaubertimer überspringen stille Zellen, Zaubertimer steigen früher aus); siehe CHANGELOG
|
||||||
* 1.4.5.3: Einstellbarer Hintergrund hinter den Balken der Plaketten, damit die Spielwelt nicht mehr durch fehlendes Leben scheint; siehe CHANGELOG
|
* 1.4.5.3: Einstellbarer Hintergrund hinter den Balken der Plaketten, damit die Spielwelt nicht mehr durch fehlendes Leben scheint; siehe CHANGELOG
|
||||||
@@ -1579,7 +1598,7 @@ Nicht vorhandene Einträge stören nicht: Findet der Zauberbuch-Scan sie nicht,
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Heal Box Vanilla v1.4.7 · Original von Dourd, UI Overhauled · Vanilla-Portierung und Erweiterung 09/2026 von Mquadrat
|
Heal Box Vanilla v1.4.7.1 · Original von Dourd, UI Overhauled · Vanilla-Portierung und Erweiterung 09/2026 von Mquadrat
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1590,3 +1609,4 @@ Heal Box Vanilla v1.4.7 · Original von Dourd, UI Overhauled · Vanilla-Portieru
|
|||||||
**Deutsch:** World of Warcraft Vanilla 1.12.1 Heiler-Addon, Classic WoW Heil-Addon, Heilfenster mit Klick-Buttons, Healium-Alternative für Vanilla, HealComm-kompatibel, Heilvorhersage und eingehende Heilung, Absorb-Schild-Anzeige, HoT-Timer, Machtwort: Schild und Geschwächte Seele, Buff-Timer als Uhr-Icons, Seelenstärke nachbuffen, Dispel-Anzeige, Gruppen- und Begleiterfenster, kompakte Raidframes für 20er und 40er Schlachtzüge, Raid-Raster für Heiler, Mana-Ticker und Fünf-Sekunden-Regel, Regenerations-Tick-Balken, automatisches Abrangen, Smart Healing, Smart Damage, Angriffsziel-Markierung, Sichtlinien-Anzeige, Reichweiten-Fading, Klassenfarben, SuperWoW, UnitXP, MobHealth3 und MobInfo-2, läuft auf Turtle WoW und anderen 1.12-Privatservern, Priester Druide Paladin Schamane Heiler-UI, Lua 5.0 Addon, Deutsch Englisch Spanisch Französisch Italienisch.
|
**Deutsch:** World of Warcraft Vanilla 1.12.1 Heiler-Addon, Classic WoW Heil-Addon, Heilfenster mit Klick-Buttons, Healium-Alternative für Vanilla, HealComm-kompatibel, Heilvorhersage und eingehende Heilung, Absorb-Schild-Anzeige, HoT-Timer, Machtwort: Schild und Geschwächte Seele, Buff-Timer als Uhr-Icons, Seelenstärke nachbuffen, Dispel-Anzeige, Gruppen- und Begleiterfenster, kompakte Raidframes für 20er und 40er Schlachtzüge, Raid-Raster für Heiler, Mana-Ticker und Fünf-Sekunden-Regel, Regenerations-Tick-Balken, automatisches Abrangen, Smart Healing, Smart Damage, Angriffsziel-Markierung, Sichtlinien-Anzeige, Reichweiten-Fading, Klassenfarben, SuperWoW, UnitXP, MobHealth3 und MobInfo-2, läuft auf Turtle WoW und anderen 1.12-Privatservern, Priester Druide Paladin Schamane Heiler-UI, Lua 5.0 Addon, Deutsch Englisch Spanisch Französisch Italienisch.
|
||||||
|
|
||||||
#WoWVanilla #Vanilla112 #WoW1121 #ClassicWoW #TurtleWoW #WoWAddon #VanillaAddon #HealerAddon #HealingAddon #Healium #HealComm #HealPrediction #RaidFrames #PartyFrames #UnitFrames #ClickCasting #ManaTicker #FiveSecondRule #Downranking #SmartHealing #SmartDamage #BuffTimer #HoTTracker #DispelTracker #Priest #Druid #Paladin #Shaman #SuperWoW #UnitXP #MobHealth #Lua50 #HealBoxVanilla
|
#WoWVanilla #Vanilla112 #WoW1121 #ClassicWoW #TurtleWoW #WoWAddon #VanillaAddon #HealerAddon #HealingAddon #Healium #HealComm #HealPrediction #RaidFrames #PartyFrames #UnitFrames #ClickCasting #ManaTicker #FiveSecondRule #Downranking #SmartHealing #SmartDamage #BuffTimer #HoTTracker #DispelTracker #Priest #Druid #Paladin #Shaman #SuperWoW #UnitXP #MobHealth #Lua50 #HealBoxVanilla
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user