mirror of
https://github.com/QbiXibQ/FBHealBox.git
synced 2026-10-08 15:10:01 +00:00
Add files via upload
This commit is contained in:
+133
@@ -1,5 +1,138 @@
|
||||
# Changelog
|
||||
|
||||
## 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.
|
||||
|
||||
### English
|
||||
|
||||
**Fixed**
|
||||
|
||||
- **Weakened Soul shows up.** The red Weakened Soul timer on the shield button was worked out from the shield entry, and that entry is deleted the moment the shield breaks, which is exactly when Weakened Soul starts to matter. So it hardly ever appeared. It now runs in a table of its own (`FBWeakenedSoul`) for 15 seconds after your own Power Word: Shield, on plates and raid cells alike.
|
||||
- **Other healers' HoTs no longer count as yours.** Every HoT seen only as a buff was entered as your own, with your highest rank and its full duration. It filled the prediction bar and the button timer even when it was another druid's Rejuvenation. Such a HoT is now provisional and counts nowhere until your own first tick (`… from your Rejuvenation.`) confirms it. If none of yours arrives within one tick interval plus `FBPREDICT_HOT_CONFIRM_GRACE` (1.5) seconds, it is dropped and remembered as someone else's for as long as the buff stays. A tick of yours for a HoT that is not tracked at all adds it on the spot. `/fbp` marks provisional HoTs with `(?)`.
|
||||
- **Other priests' shields no longer count as yours.** A shield seen only as a buff used your learned absorb value and showed your timer. It now gets the tooltip value, and only shields cast through the Heal Box buttons get the button timer and start Weakened Soul.
|
||||
- **Smart Healing leaves group heals and cooldown spells alone.** An assigned Prayer of Healing or Chain Heal was downranked by the health missing on the one unit you clicked; over a player at full health that meant rank 1, however the rest of the group looked. Spells with a cooldown such as Holy Shock were downranked as well and then burned the whole cooldown on a small rank. Both are now cast as assigned: the known cases are listed in `FBSmartSkip`, and any spell whose tooltip names a cooldown longer than the global one is left alone too. Within a heal chain they are never picked either. Tooltip help and debug output in all five languages say so.
|
||||
- **Smart Healing rates low ranks correctly.** In vanilla, ranks learned below level 20 only get a reduced share of +healing, 3.75 per cent less for every level below 20. The estimate added the full share, so with a lot of +healing a Lesser Heal rank 3 looked far stronger than it is and Smart Healing picked ranks that fell short. The learning levels of the ranks concerned are in `FBRankLearnLevel` and the bonus is cut accordingly.
|
||||
- **The tooltip scanner reads cast time and range at the right place.** In 1.12 the cast time sits on the left of line 3 and the range on the right of line 2. The scanner looked for the cast time on the right and for the range on the left, exactly the wrong way round. The range was never found, so the exact distance check through UnitXP (used when the client has no `IsSpellInRange`) never ran. The cast time was only found for the highest ranks through a fallback scan, and every other rank weighted the gear bonus with a fallback of 2.5 seconds. Cast time, range and now also the cooldown are read together from both columns of the first five tooltip lines and kept per spellbook slot. The range and mana caches are now also cleared when you learn a new rank, because that moves the slots behind it. `/fbp` lists the three values for every watched spell.
|
||||
- **Line of sight errors only mark the unit you clicked.** Without UnitXP the error went to the last button target of the past two seconds, otherwise to your friendly target, otherwise to yourself. A Smite into a pillar right after a heal greyed out the player you had just healed, and without a heal click your own plate got the eye. Now only the target of the click that caused the error is marked: up to `FBLOS_ERROR_WINDOW` (1) second after the click, and for spells with a cast time until one second after the cast ends, because the server checks line of sight again at the end of a cast. A cast that goes through, an interruption, another error message or another spell starting ends the wait, and your own plate is never marked.
|
||||
- **Class tables work on every client language.** `UnitClass` returns the localized class name first, and that is what the addon kept. All tables keyed by class (spell lists, buff watch, dispel colours, class icon, Smart Damage) use the English name, so on a German, French or Spanish client they stayed empty and dispel colouring did not work at all. The class now comes from the English token; chat lines and the options window still show the localized name (`FBClassLocal`). Spell lists and tooltip patterns remain English, see the README.
|
||||
- **The scale slider no longer moves the display.** `SetScale` reads the anchor offsets in the new scale, so dragging the slider made the plates and the raid grid wander off, and they only jumped back after the next reload or roster change. Both are anchored again right after scaling; the raid grid only when the scale really changed and never while you are dragging it.
|
||||
- **Drag and drop on raid mini buttons.** The click handler of the four mini buttons used the variable of the loop that created them. Lua 5.0, the version inside client 1.12, shares that variable between all functions created in the loop, so every mini button saw its final value and a spell dropped on any of them landed on button 4. The handler now uses the button's own index.
|
||||
- **A click only counts for the cast it started.** Target and rank of a click on a Heal Box button stayed valid for two and three seconds for every following cast, even after a failed click and for casts from the action bar. A Flash Heal from the bar right after a click was booked for the clicked player with the clicked rank and announced that way over HealComm, and after a failed shield click another priest's shield on the same player passed as yours as soon as any aura there changed. A click now belongs only to the spell that starts or goes through right after it (`FBPREDICT_CLICK_TIME`, 2 seconds); a failure, an error message or another spell drops it. A click made while another spell is still being cast waits for the next start, so spam clicking and the spell queue of client mods keep the running cast intact. Error messages and failed casts always answer the latest attempt; to know which one that is, Heal Box now counts every attempt through hooks on `UseAction`, `CastSpellByName` and `CastSpell`, which only count and pass everything on. HoTs, shields and buffs are confirmed only once the cast has gone through.
|
||||
- **Direct heals are learned.** The server usually reports the end of a cast before the heal shows up in the combat log, and by then the cast was already forgotten. The self correction of direct heals therefore hardly ever learned anything. A finished cast now waits up to two seconds for its line.
|
||||
- **Smart Damage's minimum damage is safe again.** The smallest hit seen so far counted as a rank's minimum damage. After a single high roll that was above the real minimum (Smite rank 1 does 13 to 17), and the chosen rank did not kill. The smallest normal hit is still what gets learned, but it now only proves a bonus: hit minus the tooltip's maximum, and only that is added to the tooltip's minimum. It stays the smallest hit, because boosts such as Curse of Shadow or Power Infusion only raise some hits. Saved values keep working unchanged.
|
||||
- **Smart Damage's own health estimate stays out of raids.** There the combat log does not show all damage of the other groups, so every measurement came out too low, and for mob types you only meet in raids the estimate was far too small. In a raid the module now neither measures nor uses its estimate; real values, MobHealth3 and MobInfo-2 still count. Outside raids, damage of friendly players outside your group and other players' damage over time count as well.
|
||||
- **Raid grid.** A cell taken over by a new player kept the red aggro border of the previous one until the next hostile target; the cells now drop that state on every roster change. The *Class colours* and *Buff icons* switches on the *General* tab reach the grid at once instead of with the next roster change. And `/fbp raid` during a raid test no longer leaves the test ghosts breathing in the background, which redrew the grid five times a second until the next reload.
|
||||
- **Blizzard's party frames stay hidden when another addon hid them.** With *Hide Blizzard party frames* off (the default), every group change showed the frames again. Heal Box now only brings back what it hid itself. Saved settings with both this option and the attach mode on locked both switches in the options; the attach mode now wins at login.
|
||||
- **Scale slider in attach mode.** There the buttons hang on Blizzard's party frames at scale 1, yet the slider scaled them anyway, and their offsets grew along with them. In attach mode the slider now only stores its value, which applies once the mode is switched off.
|
||||
- **HoT ticks no longer clear the line of sight mark.** A tick needs no line of sight. Only a cast starting on the unit or a direct heal landing clears the mark.
|
||||
- **pfUI's `HealStop`.** pfUI sends the command with a capital S, Heal Box only knew `Healstop`, so a cancelled pfUI heal stayed on the bar until its cast time ran out. Commands are now compared regardless of upper and lower case.
|
||||
- **Language change, empty buttons, pet spells.** After switching the language, Dead, Ghost and Offline stayed in the old language until the next group change. A button cleared in the options, or holding a spell you no longer know, kept the tint and the cooldown clock of its old spell. A spell dragged from the pet's spellbook was stored by its slot number, which belongs to a different spell in your own spellbook; it is now refused with a note in the chat.
|
||||
|
||||
**Performance**
|
||||
|
||||
- **Redraws are collected once per frame.** Seven places still redrew all ten plates and forty raid cells on every event: every HealComm message from another healer, every tick of your own HoT, every direct heal, every absorb, cast start and cast end, and every aura check with a change. With several HealComm users in a raid that was several full sweeps a second, more than 1.4.6 had saved. These places now only note the affected name; at the end of the frame the collected names are drawn once (`FBHealBox_MarkDirty`, `FBHealBox_FlushDirty`). A burst of ten messages costs one redraw of the units concerned. The raid module looks the cell up by name instead of searching forty cells. The full sweep at most once a second stays as a safety net.
|
||||
- **Mana only redraws the mana strip.** `UNIT_MANA` fires for every mana user in the raid every two seconds, and each one recomputed health, prediction, shield, colour and text of a plate or cell. Now only the strip is updated. Rage, energy and focus are registered as well, so with *Show rage, energy, focus* those strips no longer lag behind.
|
||||
- **Range per unit, not per button.** In a full raid up to 160 buttons asked the range one by one, although nearly all heals reach equally far. Each pass now asks once per unit and range. The red out of range tint moved into the 0.5 second range pass: it was only evaluated on `SPELL_UPDATE_USABLE`, which does not fire at full mana, so a player running out of range stayed untinted.
|
||||
- **Spellbook read once per burst.** At login and when zoning, `PLAYER_ENTERING_WORLD` and several `SPELLS_CHANGED` arrive back to back, and each one read the whole spellbook including every tooltip right away. That now happens once, in the next frame. The full setup at login ran twice (`ADDON_LOADED` and `VARIABLES_LOADED`); it runs once now, unless the saved settings only arrive with the second event.
|
||||
- **Cooldown sweep compares numbers.** Its key was built as a string for every button on every pass, during the global cooldown for every single button. Start and duration are compared as numbers now.
|
||||
- **Smart Damage rests while it is off.** The module listened to the combat log, `UNIT_HEALTH` and target changes even in its default off state, and read the spellbook on every `SPELLS_CHANGED`. Now it registers those events only when switched on, and it reads the spellbook only when switched on or when you open the options.
|
||||
|
||||
**Robustness**
|
||||
|
||||
- **Global names with an `FB` prefix.** `icon` (a missing `local`, never used, now removed), `panel` (the options window, under one of the most common names there are), `Spell`, `ClassIcon`, `LowHP`, `VeryLowHP`, `NamePlateWidth`, `NamePlateHeight`, `MaxButtonCount`, `MMButton` and the option widgets such as `ScaleSlider` and `MaxButtonSlider` were plain globals. Another addon with a global `panel` or `Spell` could break Heal Box. They are now `FBPanel`, `FBClassSpells`, `FBClassIcon`, `FBLowHP`, `FBVeryLowHP`, `FBNamePlateWidth`, `FBNamePlateHeight`, `FBMaxButtonCount`, `FBMinimapButton`, `FBScaleSlider` and so on.
|
||||
- **Modules no longer depend on each other.** Smart Damage looked for the mana ticker's tab and placed itself below it; without the ticker file there were no Smart Damage options at all, although both modules are meant to be removable. The core now manages the shared *Extras* tab (`FBHealBox_ExtrasSection`), and each module gets its own section. The ticker only learned about new cells through `UpdateNames`; when the raid grid rebuilt on a pure `RAID_ROSTER_UPDATE`, for example when crossing the threshold, the spark was missing or ran on someone else's cell. The raid module now fires the new hook `RaidRoster` after every rebuild.
|
||||
- **Errors are no longer swallowed.** An error in a module hook aborted the whole core routine that ran it. Every hook now runs protected; the first error of each hook appears in the chat, further ones with `/fbp debug`. The protected range and line of sight sweeps switched to protected single calls on any error, a future programming error included, without a word. With `/fbp debug` the error now shows, and if the same sweep fails three times in a row, so that the single calls do not help either, it is reported once even without debug mode.
|
||||
- **Button passes run protected.** After the first successful range query the range was asked without protection for every spell, for the buttons as well. If the client threw for one button spell only, the error came back every half second. The button passes of core and raid grid now run protected like the range sweep, and whether the range may be asked without protection is decided per spell: a spell the client throws for takes the fallback on its own, the others keep using `IsSpellInRange`. Smart Damage's hook on `UseAction` is protected too: an error is reported once, and the key press goes through unchanged.
|
||||
- **Combat log templates with numbered placeholders.** If a client wrote its combat log templates with positions such as `%1$s`, the pattern kept the `$` and every search with it threw an error. Numbered placeholders in their natural order are now removed; should a language swap the order, the English fallback applies.
|
||||
- **HealComm in battlegrounds and with limits.** In battlegrounds HealComm-1.0 sends over `BATTLEGROUND`; over `RAID` nobody is reached there. Heal Box now does the same. Amounts and cast times from other addons are capped at 20000 and 10 seconds (`FBCOMM_MAX_AMOUNT`, `FBCOMM_MAX_CAST_MS`), so a broken message cannot fill a bar for a long time.
|
||||
- **Your own heal on yourself.** "Your Flash Heal heals you for 1240." also matched the pattern for heals on others and went to a unit called "you"; your own plate kept its prediction until the cast ended. The pattern for heals on yourself is checked first now.
|
||||
- **Spell button tooltip.** It used `SpellBookFrame.bookType`, so a warlock who last had the pet tab open saw pet spells there. It always shows your own spellbook now.
|
||||
- **Drag and drop remembers less.** The spell last picked up from the spellbook was only forgotten through `ClearCursor`. With an action, a macro or an item on the cursor afterwards, the old spell could still land on a button. Picking up or placing actions, macros and items now clears it as well.
|
||||
- **Minimap button.** The old code passed `math.rad(225)` to `cos` and `sin`, which take degrees in WoW; the button ended up at about four degrees, on the left of the minimap. It stays there, but dragging it with the right mouse button now saves its spot per character (`HealBox.MinimapPos`). Before, it jumped back after every reload.
|
||||
- **Saved data no longer grows without end.** `HealBox.MobHP`, Smart Damage's mob health per type, grew by every mob type and level while leveling. It now keeps at most 400 types (`FBDMG_MOBHP_MAX`) and drops the ones not seen for the longest time. `FBBuffPresent` kept every name ever scanned; after every roster change, names that left the group are dropped now, together with their buff timers and foreign HoT marks.
|
||||
|
||||
**Cleaned up**
|
||||
|
||||
- **Dead code removed:** `FBGetSpellID` (which also read an undefined global `spellRank`), `HealBoxButton_OnEvent`, `FBUnitGUID`, `FBHealBox_UpdateButtonCooldown`, `FBRaid_InRaid`, `FBDropDown`, `FBDropDownButtonValue`, `FBTIMER_COLOR_BUFF`, `FBRaidOptionsTab`, and the second assignment of `FBHealBox2` to `FBHealBoxPet5`; `CreateFrame` with a name already creates these globals.
|
||||
- **Outdated texts fixed:** the *Buff icons* tooltip still described the clock with quadrants in all five languages; since 1.4.4.2 the icon fades from top to bottom in 32 steps. The ticker's load message pointed to a tab called *Ticker*, which is *Extras*. The XML comment named only two of the four scripts. The README spoke of two tabs and did not know the hooks `Suppress`, `ButtonStates`, `BuffIcons` and `RefreshNames`.
|
||||
- **Duplicate logic merged:** the raid module's copies of the bar helpers (`FBRaid_SetValues`, `FBRaid_SetMax`, `FBRaid_SetColor`) are gone, the cells use the core's helpers. The two nearly identical slider factories of ticker and raid module became one, `FBHealBox_CreateSlider`, which Smart Damage now uses instead of its hand built slider as well. The double loop over groups and positions, about ten times in the raid module, became flat lists of cells. The defaults stood twice in the core and had already drifted apart (`HealComm` was missing in one of them); there is one table now, `FBHealBoxDefaults`, filled in by a loop as in the modules.
|
||||
- **Small things:** the comment on ae, oe and ue now says what is true: accents are fine, characters outside Latin-1 are not reliably in the default fonts. That is why the Smart Healing tooltips use the middle dot instead of "•". SuperWoW is detected in one place instead of two. `## OptionalDeps: SuperWoW` is gone from the `.toc`; SuperWoW is a client extension, not an addon, so the line had no effect. The learning branch at a shield break could never run, because the absorb handler raises the maximum beforehand; it is gone.
|
||||
|
||||
**Good to know**
|
||||
|
||||
- A HoT cast from the action bar or a macro now shows its timer and its prediction with your first tick, about three seconds after the cast, instead of right away. Casts through the Heal Box buttons are confirmed immediately, as before.
|
||||
- A shield cast from the action bar can no longer be told apart from another priest's and gets no button timer and no Weakened Soul. Cast it through the buttons to have both.
|
||||
- A HoT, shield or buff cast through the buttons is confirmed once the cast has gone through and its aura appears. A click that fails (out of range, line of sight, global cooldown) leaves nothing behind.
|
||||
- Smart Damage keeps the values it learned with older versions: minimum damage values are read with the new, safe formula, and mob health estimates are still used outside raids.
|
||||
- If you edited the class spell lists or the HP thresholds in your own copy: they are called `FBClassSpells.Name`, `FBLowHP` and `FBVeryLowHP` now.
|
||||
- A red line "Error in …" in the chat means a module or a sweep hit a Lua error. The addon keeps running; the line names the place, which helps with a bug report.
|
||||
|
||||
### Deutsch
|
||||
|
||||
**Behoben**
|
||||
|
||||
- **Geschwaechte Seele wird angezeigt.** Der rote Timer fuer Geschwaechte Seele auf dem Schildbutton wurde aus dem Schildeintrag berechnet, und der wird in dem Moment geloescht, in dem der Schild bricht, also genau dann, wenn die Seele ueberhaupt zaehlt. Zu sehen war sie deshalb so gut wie nie. Sie laeuft jetzt in einer eigenen Tabelle (`FBWeakenedSoul`) 15 Sekunden nach deinem eigenen Machtwort: Schild, auf Plaketten und Raidzellen gleichermassen.
|
||||
- **HoTs anderer Heiler zaehlen nicht mehr als deine.** Jeder HoT, der nur als Buff zu sehen war, wurde als eigener eingetragen, mit deinem hoechsten Rang und voller Laufzeit. Er fuellte Vorhersagebalken und Buttontimer, auch wenn es die Verjuengung eines anderen Druiden war. Ein solcher HoT ist jetzt vorlaeufig und zaehlt nirgends, bis dein eigener erster Tick (`… from your Rejuvenation.`) ihn bestaetigt. Kommt binnen eines Tickintervalls plus `FBPREDICT_HOT_CONFIRM_GRACE` (1,5) Sekunden keiner von dir, wird er verworfen und als fremd gemerkt, solange der Buff bleibt. Ein Tick von dir fuer einen HoT, der gar nicht verfolgt wird, nimmt ihn sofort auf. `/fbp` kennzeichnet vorlaeufige HoTs mit `(?)`.
|
||||
- **Schilde anderer Priester zaehlen nicht mehr als deine.** Ein nur als Buff gesehener Schild bekam deinen gelernten Absorbwert und zeigte deinen Timer. Er bekommt jetzt den Tooltipwert, und nur Schilde, die du ueber die Heal Box Buttons wirkst, bekommen den Buttontimer und starten die Geschwaechte Seele.
|
||||
- **Smart Healing laesst Gruppenheilungen und Zauber mit Abklingzeit in Ruhe.** Ein belegtes Gebet der Heilung oder eine Kettenheilung wurde nach dem fehlenden Leben der einen angeklickten Einheit abgerangt; ueber einem vollen Spieler hiess das Rang 1, egal wie der Rest der Gruppe aussah. Zauber mit Abklingzeit wie Heiliger Schock wurden ebenfalls abgerangt und verbrauchten dann die volle Abklingzeit fuer einen kleinen Rang. Beide gehen jetzt wie belegt raus: Die bekannten Faelle stehen in `FBSmartSkip`, und jeder Zauber, dessen Tooltip eine Abklingzeit ueber dem globalen Cooldown nennt, bleibt ebenfalls unberuehrt. Innerhalb einer Heilkette werden sie auch nie gewaehlt. Tooltiphilfe und Debugausgabe sagen das in allen fuenf Sprachen.
|
||||
- **Smart Healing bewertet niedrige Raenge richtig.** In Vanilla bekommen Raenge, die unter Stufe 20 gelernt werden, nur einen gekuerzten Anteil an +Heilung, je Stufe unter 20 sind es 3,75 Prozent weniger. Die Schaetzung rechnete den vollen Anteil drauf; mit viel +Heilung sah ein Geringes Heilen Rang 3 so deutlich staerker aus, als es ist, und Smart Healing waehlte Raenge, die zu wenig heilten. Die Lernstufen der betroffenen Raenge stehen in `FBRankLearnLevel`, der Bonus wird entsprechend gekuerzt.
|
||||
- **Der Tooltipscanner liest Zauberzeit und Reichweite an der richtigen Stelle.** In 1.12 steht die Zauberzeit links in Zeile 3 und die Reichweite rechts in Zeile 2. Der Scanner suchte die Zauberzeit rechts und die Reichweite links, also genau vertauscht. Die Reichweite fand sich nie, damit lief die genaue Abstandspruefung ueber UnitXP (genutzt, wenn der Client kein `IsSpellInRange` hat) nie. Die Zauberzeit fand sich nur fuer die Hoechstraenge ueber einen Rueckfallscan, alle anderen Raenge gewichteten den Ausruestungsbonus mit dem Ersatzwert 2,5 Sekunden. Zauberzeit, Reichweite und jetzt auch die Abklingzeit werden gemeinsam aus beiden Spalten der ersten fuenf Tooltipzeilen gelesen und je Zauberbuchplatz gemerkt. Die Speicher fuer Reichweite und Manapreis werden jetzt auch geleert, wenn du einen neuen Rang lernst, denn der verschiebt die Plaetze dahinter. `/fbp` nennt die drei Werte fuer jeden beobachteten Zauber.
|
||||
- **Sichtlinienfehler markieren nur die angeklickte Einheit.** Ohne UnitXP ging der Fehler an das letzte Buttonziel der vergangenen zwei Sekunden, sonst an dein freundliches Ziel, sonst an dich selbst. Ein Angriffszauber ohne Sicht direkt nach einer Heilung graute den gerade geheilten Spieler aus, und ohne Heilklick bekam deine eigene Plakette das Auge. Jetzt wird nur das Ziel des Klicks markiert, der den Fehler ausgeloest hat: bis `FBLOS_ERROR_WINDOW` (1) Sekunde nach dem Klick, bei Zaubern mit Zauberzeit bis eine Sekunde nach dem Castende, denn der Server prueft die Sicht am Ende eines Casts noch einmal. Ein Cast, der durchgeht, eine Unterbrechung, eine andere Fehlermeldung oder ein anderer Zauber, der anlaeuft, beendet das Warten, und deine eigene Plakette wird nie markiert.
|
||||
- **Klassentabellen in jeder Clientsprache.** `UnitClass` liefert zuerst den lokalisierten Klassennamen, und genau den hat sich das Addon gemerkt. Alle nach Klasse geschluesselten Tabellen (Zauberlisten, Buff-Wache, Dispelfarben, Klassenicon, Smart Damage) nutzen den englischen Namen; auf einem deutschen, franzoesischen oder spanischen Client blieben sie deshalb leer, und die Dispelfaerbung fiel komplett aus. Die Klasse kommt jetzt aus dem englischen Token; Chatzeilen und Optionsfenster zeigen weiter den lokalisierten Namen (`FBClassLocal`). Zauberlisten und Tooltipmuster bleiben englisch, siehe README.
|
||||
- **Der Skalierungsregler verschiebt die Anzeige nicht mehr.** `SetScale` liest die Ankerversaetze im neuen Massstab, beim Ziehen am Regler wanderten Plaketten und Raidraster deshalb weg und sprangen erst nach dem naechsten Laden oder Rosterwechsel zurueck. Beide werden direkt nach dem Skalieren neu verankert; das Raidraster nur bei echter Aenderung und nie, waehrend du es gerade ziehst.
|
||||
- **Drag & Drop auf die Minibuttons im Raid.** Der Klickhandler der vier Minibuttons benutzte die Variable der Schleife, die sie erzeugt. Lua 5.0, die Version im Client 1.12, teilt diese Variable zwischen allen in der Schleife erzeugten Funktionen; jeder Minibutton sah ihren Endwert, und ein Zauber, egal auf welchen gezogen, landete auf Button 4. Der Handler nimmt jetzt den eigenen Index des Buttons.
|
||||
- **Ein Klick gilt nur fuer den Cast, den er ausloest.** Ziel und Rang eines Klicks auf einen Heal Box Button galten zwei und drei Sekunden lang fuer jeden folgenden Cast, auch nach einem gescheiterten Klick und fuer Casts von der Aktionsleiste. Eine Blitzheilung von der Leiste kurz nach einem Klick wurde fuer den angeklickten Spieler mit dem angeklickten Rang verbucht und so ueber HealComm gemeldet, und nach einem gescheiterten Klick auf den Schild galt der Schild eines anderen Priesters auf demselben Spieler als deiner, sobald sich dort irgendeine Aura aenderte. Ein Klick gehoert jetzt nur zu dem Zauber, der gleich danach anlaeuft oder durchgeht (`FBPREDICT_CLICK_TIME`, 2 Sekunden); ein Fehlschlag, eine Fehlermeldung oder ein anderer Zauber verwirft ihn. Ein Klick, waehrend noch ein anderer Zauber gewirkt wird, wartet auf den naechsten Castbeginn; Spamklicks und die Zauberwarteschlange von Clientmods lassen den laufenden Cast so unberuehrt. Fehlermeldungen und gescheiterte Casts beantworten immer den juengsten Versuch; damit klar ist, welcher das ist, zaehlt Heal Box jetzt jeden Versuch ueber Hooks auf `UseAction`, `CastSpellByName` und `CastSpell`, die nur zaehlen und alles weiterreichen. HoTs, Schilde und Buffs werden erst bestaetigt, wenn der Cast durchgegangen ist.
|
||||
- **Direktheilungen werden gelernt.** Der Server meldet das Castende in der Regel, bevor die Heilung im Combatlog steht, und dann war der Cast schon vergessen. Die Selbstkorrektur der Direktheilungen lernte deshalb so gut wie nie etwas. Ein beendeter Cast wartet jetzt bis zu zwei Sekunden auf seine Zeile.
|
||||
- **Der Mindestschaden von Smart Damage ist wieder sicher.** Als Mindestschaden eines Rangs galt der kleinste bisher gesehene Treffer. Nach einem einzigen hohen Wurf lag er ueber dem echten Minimum (Smite Rang 1 macht 13 bis 17), und der gewaehlte Rang toetete nicht. Gelernt wird weiter der kleinste normale Treffer, er beweist jetzt aber nur einen Bonus: Treffer minus Hoechstwert des Tooltips, und nur der kommt auf das Minimum des Tooltips. Es bleibt beim kleinsten Treffer, weil Verstaerker wie Curse of Shadow oder Power Infusion nur manche Treffer heben. Gespeicherte Werte gelten unveraendert weiter.
|
||||
- **Die eigene Lebensschaetzung von Smart Damage bleibt aus Raids heraus.** Dort zeigt der Combatlog den Schaden der anderen Gruppen nicht vollstaendig, jede Messung fiel zu niedrig aus, und bei Mobtypen, die man nur im Raid trifft, war die Schaetzung viel zu klein. Im Raid misst das Modul jetzt nicht und nutzt seine Schaetzung auch nicht; echte Werte, MobHealth3 und MobInfo-2 gelten weiter. Ausserhalb von Raids zaehlen jetzt auch der Schaden freundlicher Spieler ausserhalb deiner Gruppe und der Schaden ueber Zeit anderer Spieler.
|
||||
- **Raidraster.** Eine Zelle, die ein neuer Spieler uebernahm, behielt den roten Angriffsrahmen ihres Vorgaengers bis zum naechsten feindlichen Ziel; die Zellen legen diesen Zustand jetzt bei jedem Rosterwechsel ab. Die Schalter *Klassenfarben* und *Buff-Icons* im Reiter *Allgemein* erreichen das Raster sofort statt erst beim naechsten Rosterwechsel. Und `/fbp raid` waehrend eines Raidtests laesst die Testgeister nicht mehr im Hintergrund atmen; das Raster wurde dann bis zum naechsten Laden fuenfmal je Sekunde neu gezeichnet.
|
||||
- **Blizzards Gruppenfenster bleiben versteckt, wenn ein anderes Addon sie versteckt hat.** Mit *Blizzard-Gruppenfenster aus* auf aus (die Vorgabe) holte jede Gruppenaenderung die Fenster wieder hervor. Heal Box nimmt jetzt nur zurueck, was es selbst versteckt hat. Gespeicherte Einstellungen mit dieser Option und dem Anheftmodus zugleich sperrten im Optionsfenster beide Schalter; beim Laden gewinnt jetzt der Anheftmodus.
|
||||
- **Skalierungsregler im Anheftmodus.** Dort haengen die Buttons im Massstab 1 an Blizzards Gruppenfenstern, der Regler skalierte sie trotzdem, und ihre Versaetze wuchsen mit. Im Anheftmodus merkt sich der Regler jetzt nur seinen Wert, der gilt, sobald der Modus endet.
|
||||
- **HoT-Ticks loeschen die Sichtlinienmarke nicht mehr.** Ein Tick braucht keine Sicht. Nur ein Cast, der auf der Einheit anlaeuft, oder eine angekommene Direktheilung loescht die Marke.
|
||||
- **`HealStop` von pfUI.** pfUI schickt den Befehl mit grossem S, Heal Box kannte nur `Healstop`; eine abgebrochene Heilung aus pfUI blieb so bis zum Ende ihrer Zauberzeit auf dem Balken. Befehle werden jetzt unabhaengig von grossen und kleinen Buchstaben verglichen.
|
||||
- **Sprachwechsel, leere Buttons, Begleiterzauber.** Nach einem Sprachwechsel blieben Tot, Geist und Offline bis zum naechsten Gruppenwechsel in der alten Sprache. Ein Button, dessen Belegung im Optionsfenster geleert wurde oder dessen Zauber du nicht mehr kennst, behielt Toenung und Abklingzeituhr seines alten Zaubers. Ein Zauber aus dem Zauberbuch des Begleiters wurde mit seiner Platznummer gemerkt, die im eigenen Zauberbuch zu einem anderen Zauber gehoert; er wird jetzt mit einem Hinweis im Chat abgelehnt.
|
||||
|
||||
**Leistung**
|
||||
|
||||
- **Neuzeichnen einmal je Frame gesammelt.** Sieben Stellen zeichneten bei jedem Ereignis noch alle zehn Plaketten und vierzig Raidzellen neu: jede HealComm-Nachricht eines anderen Heilers, jeder Tick deines eigenen HoTs, jede Direktheilung, jeder Absorb, Castbeginn und Castende und jeder Auraabgleich mit Aenderung. Mit mehreren Nutzern von HealComm im Raid waren das mehrere volle Durchlaeufe je Sekunde, mehr als 1.4.6 eingespart hatte. Diese Stellen merken jetzt nur den betroffenen Namen vor; am Ende des Frames werden die gesammelten Namen einmal gezeichnet (`FBHealBox_MarkDirty`, `FBHealBox_FlushDirty`). Eine Salve aus zehn Nachrichten kostet ein Neuzeichnen der betroffenen Einheiten. Das Raidmodul schlaegt die Zelle ueber den Namen nach, statt vierzig Zellen abzusuchen. Der volle Durchlauf hoechstens einmal je Sekunde bleibt als Sicherheitsnetz.
|
||||
- **Mana zeichnet nur noch den Manastreifen.** `UNIT_MANA` feuert im Raid fuer jeden Manabenutzer alle zwei Sekunden, und jedes davon rechnete Leben, Vorhersage, Schild, Farbe und Text einer Plakette oder Zelle neu. Jetzt wird nur der Streifen nachgefuehrt. Wut, Energie und Fokus sind ebenfalls angemeldet, mit *Wut, Energie, Fokus zeigen* hinken diese Streifen nicht mehr hinterher.
|
||||
- **Reichweite je Einheit statt je Button.** Im vollen Raid fragten bis zu 160 Buttons die Reichweite einzeln ab, obwohl fast alle Heilzauber gleich weit reichen. Jeder Durchgang fragt jetzt einmal je Einheit und Reichweite. Die rote Toenung ausser Reichweite laeuft im Reichweitentakt von 0,5 Sekunden mit: Bewertet wurde sie nur bei `SPELL_UPDATE_USABLE`, das bei vollem Mana nicht feuert, ein Mitspieler, der aus der Reichweite lief, blieb dann ungetoent.
|
||||
- **Zauberbuch einmal je Salve gelesen.** Beim Login und beim Zonen kommen `PLAYER_ENTERING_WORLD` und mehrere `SPELLS_CHANGED` kurz hintereinander, und jedes davon las das ganze Zauberbuch samt aller Tooltips sofort. Das geschieht jetzt einmal, im naechsten Frame. Die volle Einrichtung beim Login lief zweimal (`ADDON_LOADED` und `VARIABLES_LOADED`); jetzt laeuft sie einmal, ausser die gespeicherten Einstellungen kommen erst mit dem zweiten Ereignis.
|
||||
- **Cooldown-Uhr vergleicht Zahlen.** Ihr Schluessel wurde je Button und Durchgang als String gebaut, im globalen Cooldown fuer jeden einzelnen Button. Beginn und Dauer werden jetzt als Zahlen verglichen.
|
||||
- **Smart Damage ruht, solange es aus ist.** Das Modul hoerte auch im Standardzustand aus auf Combatlog, `UNIT_HEALTH` und Zielwechsel und las bei jedem `SPELLS_CHANGED` das Zauberbuch. Jetzt meldet es diese Ereignisse erst beim Einschalten an und liest das Zauberbuch erst beim Einschalten oder wenn du die Optionen oeffnest.
|
||||
|
||||
**Robustheit**
|
||||
|
||||
- **Globale Namen mit `FB` versehen.** `icon` (ein fehlendes `local`, nie benutzt, jetzt entfernt), `panel` (das Optionsfenster, unter einem der haeufigsten Namen ueberhaupt), `Spell`, `ClassIcon`, `LowHP`, `VeryLowHP`, `NamePlateWidth`, `NamePlateHeight`, `MaxButtonCount`, `MMButton` und die Bedienelemente wie `ScaleSlider` und `MaxButtonSlider` waren einfache Globals. Ein anderes Addon mit globalem `panel` oder `Spell` konnte Heal Box lahmlegen. Sie heissen jetzt `FBPanel`, `FBClassSpells`, `FBClassIcon`, `FBLowHP`, `FBVeryLowHP`, `FBNamePlateWidth`, `FBNamePlateHeight`, `FBMaxButtonCount`, `FBMinimapButton`, `FBScaleSlider` und so weiter.
|
||||
- **Module haengen nicht mehr voneinander ab.** Smart Damage suchte den Reiter des Mana-Tickers und setzte sich darunter; ohne Tickerdatei gab es gar keine Optionen fuer Smart Damage, obwohl beide Module einzeln entfernbar sein sollen. Den gemeinsamen Reiter *Extras* verwaltet jetzt der Kern (`FBHealBox_ExtrasSection`), und jedes Modul bekommt darin einen eigenen Abschnitt. Der Ticker erfuhr von neuen Zellen nur ueber `UpdateNames`; baute das Raidraster nach einem reinen `RAID_ROSTER_UPDATE` um, etwa beim Ueberschreiten der Schwelle, fehlte der Funke oder lief auf der Zelle eines anderen Spielers. Das Raidmodul ruft jetzt nach jedem Umbau den neuen Hook `RaidRoster`.
|
||||
- **Fehler werden nicht mehr verschluckt.** Ein Fehler in einem Modulhook brach den ganzen Ablauf des Kerns ab, der ihn ausgeloest hatte. Jeder Hook laeuft jetzt geschuetzt; der erste Fehler je Hook erscheint im Chat, weitere mit `/fbp debug`. Die geschuetzten Durchlaeufe fuer Reichweite und Sichtlinie schalteten bei jedem Fehler, auch einem kuenftigen Programmierfehler, wortlos auf geschuetzte Einzelaufrufe um. Mit `/fbp debug` steht der Fehler jetzt im Chat, und scheitert derselbe Durchlauf dreimal in Folge, helfen also auch die Einzelaufrufe nicht, meldet er sich einmal auch ohne Debugmodus.
|
||||
- **Durchlaeufe ueber die Buttons laufen geschuetzt.** Nach der ersten erfolgreichen Abfrage wurde die Reichweite fuer jeden Zauber ungeschuetzt gefragt, auch fuer die Buttons. Warf der Client nur fuer den Zauber eines Buttons, kam der Fehler jede halbe Sekunde wieder. Die Durchlaeufe ueber die Buttons von Kern und Raidraster laufen jetzt geschuetzt wie der Reichweitendurchlauf, und ob die Reichweite ungeschuetzt gefragt werden darf, entscheidet sich je Zauber: Ein Zauber, fuer den der Client wirft, nimmt allein den Rueckfallweg, die anderen fragen weiter `IsSpellInRange`. Auch der Hook von Smart Damage auf `UseAction` ist geschuetzt: Ein Fehler wird einmal gemeldet, und der Tastendruck geht unveraendert durch.
|
||||
- **Combatlogvorlagen mit nummerierten Platzhaltern.** Schrieb ein Client seine Vorlagen mit Positionen wie `%1$s`, blieb das `$` im Muster stehen, und jede Suche damit warf einen Fehler. Nummerierte Platzhalter in natuerlicher Folge werden jetzt entfernt; stellt eine Sprache die Folge um, greift der englische Rueckfall.
|
||||
- **HealComm im Schlachtfeld und mit Grenzen.** Im Schlachtfeld sendet HealComm-1.0 ueber `BATTLEGROUND`; ueber `RAID` erreicht man dort niemanden. Heal Box macht es jetzt genauso. Betraege und Zauberzeiten aus anderen Addons werden auf 20000 und 10 Sekunden begrenzt (`FBCOMM_MAX_AMOUNT`, `FBCOMM_MAX_CAST_MS`); eine kaputte Nachricht kann so keinen Balken lange fuellen.
|
||||
- **Eigene Heilung auf dich selbst.** "Your Flash Heal heals you for 1240." passte auch auf das Muster fuer Heilungen auf andere und ging an eine Einheit namens "you"; deine eigene Plakette behielt ihre Vorhersage dann bis zum Castende. Das Muster fuer Heilungen auf dich wird jetzt zuerst geprueft.
|
||||
- **Tooltip der Zauberbuttons.** Er nahm `SpellBookFrame.bookType`; ein Hexenmeister, der zuletzt den Begleiterreiter offen hatte, sah dort Begleiterzauber. Jetzt immer das eigene Zauberbuch.
|
||||
- **Drag & Drop merkt sich weniger.** Der zuletzt aus dem Zauberbuch genommene Zauber wurde nur ueber `ClearCursor` vergessen. Lag danach eine Aktion, ein Makro oder ein Gegenstand am Cursor, konnte trotzdem der alte Zauber auf einem Button landen. Aufnehmen oder Ablegen von Aktionen, Makros und Gegenstaenden loescht ihn jetzt ebenfalls.
|
||||
- **Minimap-Button.** Der alte Code gab `math.rad(225)` an `cos` und `sin`, die in WoW mit Grad rechnen; der Button landete bei etwa vier Grad, links an der Minimap. Dort bleibt er, aber mit der rechten Maustaste gezogen merkt er sich seine Stelle jetzt je Charakter (`HealBox.MinimapPos`). Vorher sprang er nach jedem Laden zurueck.
|
||||
- **Gespeicherte Daten wachsen nicht mehr endlos.** `HealBox.MobHP`, das Mobleben je Typ fuer Smart Damage, wuchs beim Leveln um jeden Mobtyp und jede Stufe. Jetzt bleiben hoechstens 400 Typen (`FBDMG_MOBHP_MAX`), die am laengsten nicht gesehenen fallen weg. `FBBuffPresent` behielt jeden je gescannten Namen; nach jedem Rosterwechsel fallen Namen, die nicht mehr in der Gruppe sind, jetzt heraus, samt ihrer Bufftimer und Fremdmarken fuer HoTs.
|
||||
|
||||
**Aufgeraeumt**
|
||||
|
||||
- **Toter Code entfernt:** `FBGetSpellID` (das zudem eine undefinierte globale `spellRank` las), `HealBoxButton_OnEvent`, `FBUnitGUID`, `FBHealBox_UpdateButtonCooldown`, `FBRaid_InRaid`, `FBDropDown`, `FBDropDownButtonValue`, `FBTIMER_COLOR_BUFF`, `FBRaidOptionsTab` und die zweite Zuweisung von `FBHealBox2` bis `FBHealBoxPet5`; `CreateFrame` mit Namen legt diese Globals schon an.
|
||||
- **Veraltete Texte korrigiert:** Der Tooltip *Buff-Icons* beschrieb in allen fuenf Sprachen noch die Uhr mit Quadranten; seit 1.4.4.2 blendet das Icon in 32 Stufen von oben nach unten ab. Die Ladezeile des Tickers nannte einen Reiter *Ticker*, er heisst *Extras*. Der Kommentar in der XML nannte nur zwei der vier Skripte. Die README sprach von zwei Reitern und kannte die Hooks `Suppress`, `ButtonStates`, `BuffIcons` und `RefreshNames` nicht.
|
||||
- **Doppelte Logik zusammengelegt:** Die Kopien der Balkenhelfer im Raidmodul (`FBRaid_SetValues`, `FBRaid_SetMax`, `FBRaid_SetColor`) sind weg, die Zellen nutzen die Helfer des Kerns. Aus den zwei fast gleichen Sliderfabriken von Ticker und Raidmodul wurde eine, `FBHealBox_CreateSlider`, die jetzt auch Smart Damage statt seines handgebauten Reglers nutzt. Die doppelte Schleife ueber Gruppen und Plaetze, rund zehnmal im Raidmodul, wurde zu flachen Zellenlisten. Die Vorgaben standen im Kern zweimal und waren schon auseinandergelaufen (`HealComm` fehlte in einer davon); jetzt gibt es eine Tabelle, `FBHealBoxDefaults`, die eine Schleife nachzieht wie in den Modulen.
|
||||
- **Kleinigkeiten:** Der Kommentar zu ae, oe und ue sagt jetzt, was stimmt: Akzente sind kein Problem, Zeichen ausserhalb von Latin-1 sind in den Standardschriften nicht sicher enthalten. Deshalb nutzen die Tooltips von Smart Healing den Mittelpunkt statt "•". SuperWoW wird an einer Stelle erkannt statt an zweien. `## OptionalDeps: SuperWoW` ist aus der `.toc` verschwunden; SuperWoW ist eine Clienterweiterung, kein Addon, die Zeile wirkte nie. Der Lernzweig beim Bruch eines Schildes konnte nie laufen, weil die Absorbauswertung das Maximum schon vorher anhebt; er ist entfernt.
|
||||
|
||||
**Gut zu wissen**
|
||||
|
||||
- Ein HoT von der Aktionsleiste oder aus einem Makro zeigt Timer und Vorhersage jetzt mit deinem ersten Tick, also etwa drei Sekunden nach dem Cast, statt sofort. Casts ueber die Heal Box Buttons sind wie bisher sofort bestaetigt.
|
||||
- Ein Schild von der Aktionsleiste laesst sich nicht mehr von dem eines anderen Priesters unterscheiden und bekommt weder Buttontimer noch Geschwaechte Seele. Ueber die Buttons gewirkt gibt es beides.
|
||||
- Ein HoT, Schild oder Buff ueber die Buttons gilt als bestaetigt, sobald der Cast durchgegangen ist und seine Aura erscheint. Ein gescheiterter Klick (ausser Reichweite, keine Sicht, globaler Cooldown) hinterlaesst nichts.
|
||||
- Smart Damage behaelt, was es mit aelteren Versionen gelernt hat: Mindestschaeden werden mit der neuen, sicheren Rechnung gelesen, Lebensschaetzungen gelten ausserhalb von Raids weiter.
|
||||
- Wer die Zauberlisten der Klassen oder die Lebensschwellen in der eigenen Kopie angepasst hat: Sie heissen jetzt `FBClassSpells.Name`, `FBLowHP` und `FBVeryLowHP`.
|
||||
- Eine rote Zeile "Fehler in …" im Chat bedeutet, dass ein Modul oder ein Durchlauf auf einen Lua-Fehler gestossen ist. Das Addon laeuft weiter; die Zeile nennt die Stelle, das hilft bei einer Fehlermeldung.
|
||||
|
||||
|
||||
## 1.4.6 (2026-10-06)
|
||||
|
||||
Performance pass over the display loop, with no change in behaviour: only the units that actually changed are redrawn, and two loops that ran empty five times a second now stop early.
|
||||
|
||||
+1433
-798
File diff suppressed because it is too large
Load Diff
+4
-3
@@ -1,11 +1,12 @@
|
||||
## Interface: 11200
|
||||
## Title: Heal Box Vanilla |cFFFFFF00v1.4.6.1|r
|
||||
## Title: Heal Box Vanilla |cFFFFFF00v1.4.7|r
|
||||
## Notes: Heal/raid frame addon like Healium, with quick-cast buttons, heal prediction, mana ticker and more.
|
||||
## Notes-deDE: Heal/Raidframe Addon aehnlich Healium, mit Schnellzugriff Buttons, Heal Prediction und Mana Ticker und mehr.
|
||||
## Author: Dourd (Argent Dawn EU) | Vanilla-Port & Erweiterung 09/2026: Mquadrat
|
||||
## Version: 1.4.6.1
|
||||
## Version: 1.4.7
|
||||
## SavedVariablesPerCharacter: HealBox
|
||||
## OptionalDeps: SuperWoW
|
||||
# SuperWoW ist eine Client-Erweiterung, kein Addon. OptionalDeps wirkt darauf
|
||||
# nicht; das Addon erkennt SuperWoW zur Laufzeit.
|
||||
|
||||
FBHealBox.lua
|
||||
FBHealBox_Raid.lua
|
||||
|
||||
+4
-3
@@ -4,9 +4,10 @@
|
||||
Original: "Heal Box" von Dourd (Argent Dawn EU) - UI Overhauled.
|
||||
Vanilla-Portierung und Funktionserweiterung 09/2026 von Mquadrat.
|
||||
-->
|
||||
<!-- Die Lua-Dateien laedt ausschliesslich die .toc (FBHealBox.lua,
|
||||
FBHealBox_Raid.lua). Ein <Script file="..."/> hier wuerde den Kern
|
||||
ein zweites Mal ausfuehren. -->
|
||||
<!-- Die Lua-Dateien laedt ausschliesslich die .toc: FBHealBox.lua (Kern),
|
||||
FBHealBox_Raid.lua, FBHealBox_Ticker.lua und FBHealBox_Damage.lua
|
||||
(Module, einzeln entfernbar). Ein <Script file="..."/> hier wuerde
|
||||
den Kern ein zweites Mal ausfuehren. -->
|
||||
|
||||
<Frame name="FBHealBoxEventFrame" parent="UIParent">
|
||||
<Scripts>
|
||||
|
||||
+160
-51
@@ -12,12 +12,16 @@
|
||||
-- 2) MobHealth3 MobHealth3:GetUnitHealth(unit)
|
||||
-- 3) MobInfo-2 MobHealth_GetTargetCurHP()/MaxHP()
|
||||
-- 4) eigene Schaetzung Lebenspunkte je Prozent aus beobachtetem Schaden
|
||||
-- (eigener, Gruppe, Begleiter) und dem Prozentabfall des Ziels, erst ab
|
||||
-- FBDMG_MIN_DROP Prozent Abfall, Maximum ueber alle Messungen (Fehler
|
||||
-- nur nach oben, also in die sichere Richtung), gemerkt je Name:Stufe.
|
||||
-- (eigener, Gruppe, Begleiter, andere freundliche Spieler, auch deren
|
||||
-- DoTs) und dem Prozentabfall des Ziels, erst ab FBDMG_MIN_DROP Prozent
|
||||
-- Abfall, Maximum ueber alle Messungen (Fehler nur nach oben, also in
|
||||
-- die sichere Richtung), gemerkt je Name:Stufe. Im Raid wird weder
|
||||
-- gemessen noch geschaetzt: Der Combatlog zeigt den Schaden der anderen
|
||||
-- Raidgruppen nicht vollstaendig, jede Messung fiele dort zu niedrig aus.
|
||||
--
|
||||
-- Schaden je Rang: Mindestschaden aus dem Tooltip ("86 to 98 Holy damage"),
|
||||
-- nachgelernt aus eigenen Treffern ohne Teilwiderstand. Entscheidung:
|
||||
-- angehoben um den Bonus, den der kleinste eigene Treffer ohne Crit und
|
||||
-- Teilwiderstand beweist (FBDmg_MinDamage). Entscheidung:
|
||||
-- Mindestschaden >= Ziel-Leben (bei Prozent: Obergrenze) x (1 + Aufschlag).
|
||||
-- ==========================================================================
|
||||
|
||||
@@ -26,6 +30,8 @@ FBHealBox_DamageLoaded = true;
|
||||
|
||||
FBDMG_MIN_DROP = 3; -- Prozent Abfall, ab dem eine Messung zaehlt
|
||||
FBDMG_LASTCAST_SEC = 4; -- Sek., wie lange ein eigener Cast fuers Lernen gilt
|
||||
FBDMG_MOBHP_MAX = 400; -- gemerkte Mobtypen, darueber fallen die aeltesten weg
|
||||
FBDMG_SECTION_H = 180; -- px, Hoehe des Abschnitts im Reiter "Extras"
|
||||
|
||||
FBDamageDefaults = {
|
||||
Enabled = 0, -- Smart Damage an/aus (bewusst aus)
|
||||
@@ -160,6 +166,9 @@ FBDmgAnchorPct = nil; -- Prozent des Ziels beim letzten Messpunkt
|
||||
FBDmgAccum = 0; -- Schaden auf das Ziel seit dem Messpunkt
|
||||
FBDmgTargetName = nil;
|
||||
FBDmgLastCast = nil; -- { spell, rank, t } fuer das Lernen aus dem Combatlog
|
||||
FBDmgActive = false; -- Ereignisse registriert (Smart Damage an)
|
||||
FBDmgSpellsDirty = true; -- Zauberbuch noch nicht (neu) gelesen
|
||||
FBDmgMobCount = 0; -- Eintraege in HealBox.MobHP
|
||||
|
||||
function FBDmg_Cfg()
|
||||
if (not HealBox.Damage) then FBDmg_ApplyDefaults(); end
|
||||
@@ -171,11 +180,37 @@ function FBDmg_ApplyDefaults()
|
||||
for k, v in pairs(FBDamageDefaults) do
|
||||
if (HealBox.Damage[k] == nil) then HealBox.Damage[k] = v; end
|
||||
end
|
||||
if (not HealBox.MobHP) then HealBox.MobHP = {}; end -- [Name:Stufe] = { ppp, n }
|
||||
if (not HealBox.DmgMemory) then HealBox.DmgMemory = {}; end -- [Zauber|Rang] = gelernter Mindestschaden
|
||||
if (not HealBox.MobHP) then HealBox.MobHP = {}; end -- [Name:Stufe] = { ppp, n, seen }
|
||||
if (not HealBox.DmgMemory) then HealBox.DmgMemory = {}; end -- [Zauber|Rang] = kleinster normaler Treffer
|
||||
FBDmg_PruneMobHP();
|
||||
return true;
|
||||
end
|
||||
|
||||
-- Gemerkte Mobtypen begrenzen. HealBox.MobHP wuchs bis 1.4.6 beim Leveln um
|
||||
-- jeden Mobtyp und jede Stufe, ohne je zu schrumpfen. Ueber der Grenze
|
||||
-- fallen die am laengsten nicht gesehenen Eintraege weg, und zwar bis auf
|
||||
-- drei Viertel der Grenze, damit nicht jeder neue Mob eine Sortierung
|
||||
-- ausloest. Eintraege aus aelteren Versionen ohne Zeitstempel gelten als
|
||||
-- die aeltesten.
|
||||
function FBDmg_SeenOf(e)
|
||||
if (type(e) == "table") and e.seen then return e.seen; end
|
||||
return 0;
|
||||
end
|
||||
|
||||
function FBDmg_PruneMobHP()
|
||||
local t = HealBox.MobHP;
|
||||
if (not t) then FBDmgMobCount = 0; return; end
|
||||
local keys = {};
|
||||
for k in pairs(t) do table.insert(keys, k); end
|
||||
local n = table.getn(keys);
|
||||
FBDmgMobCount = n;
|
||||
if (n <= FBDMG_MOBHP_MAX) then return; end
|
||||
table.sort(keys, function(a, b) return FBDmg_SeenOf(t[a]) < FBDmg_SeenOf(t[b]); end);
|
||||
local drop = n - math.floor(FBDMG_MOBHP_MAX * 0.75);
|
||||
for i = 1, drop do t[keys[i]] = nil; end
|
||||
FBDmgMobCount = n - drop;
|
||||
end
|
||||
|
||||
-- ==========================================================================
|
||||
-- [ Zauberbuch: Raenge und Schaden ]
|
||||
-- ==========================================================================
|
||||
@@ -204,13 +239,22 @@ function FBDmg_ScanSpells()
|
||||
i = i + 1;
|
||||
end
|
||||
FBDmgSlotCache = {};
|
||||
FBDmgSpellsDirty = false;
|
||||
end
|
||||
|
||||
-- Mindestschaden eines Rangs: gelernt (Treffer ohne Teilwiderstand), sonst Tooltip
|
||||
-- Mindestschaden eines Rangs. Gelernt wird der kleinste eigene Treffer ohne
|
||||
-- Crit und Teilwiderstand. Jeder Treffer liegt hoechstens beim Hoechstwert
|
||||
-- des Tooltips plus Bonus, der Bonus ist also mindestens Treffer minus
|
||||
-- Hoechstwert, und so viel liegt sicher auch auf dem Minimum. Der kleinste
|
||||
-- Treffer, weil Verstaerker wie Curse of Shadow oder Power Infusion nur
|
||||
-- manche Treffer heben; ein einzelner verstaerkter Treffer darf den Wert
|
||||
-- nicht dauerhaft hochziehen. Bis 1.4.6 galt der kleinste Treffer selbst als
|
||||
-- Mindestschaden; nach einem einzigen hohen Wurf lag er ueber dem echten
|
||||
-- Minimum, und der gewaehlte Rang toetete nicht.
|
||||
function FBDmg_MinDamage(spell, entry)
|
||||
local learned = HealBox.DmgMemory and HealBox.DmgMemory[spell.."|"..entry.rank];
|
||||
if (learned and learned > entry.min) then return learned; end
|
||||
return entry.min;
|
||||
if (not learned) then return entry.min; end
|
||||
return math.max(entry.min, learned - (entry.max - entry.min));
|
||||
end
|
||||
|
||||
-- ==========================================================================
|
||||
@@ -248,10 +292,14 @@ function FBDmg_TargetHP(unit)
|
||||
local ok2, max = pcall(MobHealth_GetTargetMaxHP);
|
||||
if (ok and ok2 and cur and max and max > 100) then return cur, max, "mi2"; end
|
||||
end
|
||||
-- eigene Schaetzung: Prozent-Obergrenze x Lebenspunkte je Prozent
|
||||
-- eigene Schaetzung: Prozent-Obergrenze x Lebenspunkte je Prozent. Nicht
|
||||
-- im Raid: Dort wird nicht gemessen (FBDmg_OnTargetHealth), und was
|
||||
-- fruehere Versionen dort gemessen haben, fiel zu niedrig aus.
|
||||
if (GetNumRaidMembers() > 0) then return nil; end
|
||||
local key = FBDmg_MobKey(unit);
|
||||
local est = key and HealBox.MobHP and HealBox.MobHP[key];
|
||||
if (est and est.ppp and est.ppp > 0) then
|
||||
est.seen = time();
|
||||
local pct = UnitHealth(unit) or 0;
|
||||
return math.ceil((pct + 1) * est.ppp), math.ceil(100 * est.ppp), "est";
|
||||
end
|
||||
@@ -264,6 +312,8 @@ function FBDmg_ResetTarget()
|
||||
FBDmgTargetName = nil;
|
||||
FBDmgAnchorPct = nil;
|
||||
FBDmgAccum = 0;
|
||||
-- Im Raid wird nicht vermessen (siehe Kopf der Datei)
|
||||
if (GetNumRaidMembers() > 0) then FBDmg_UpdateSourceText(); return; end
|
||||
if (UnitExists("target") and UnitCanAttack and UnitCanAttack("player", "target") and not FBDmg_HasRealValues("target")) then
|
||||
FBDmgTargetName = UnitName("target");
|
||||
FBDmgAnchorPct = UnitHealth("target");
|
||||
@@ -281,6 +331,13 @@ end
|
||||
function FBDmg_OnTargetHealth()
|
||||
if (not FBDmgTargetName) or (not FBDmgAnchorPct) then return; end
|
||||
if (FBDmg_HasRealValues("target")) then return; end
|
||||
-- Mitten im Kampf einem Raid beigetreten: Messung verwerfen. Bis 1.4.6
|
||||
-- wurde auch im Raid gemessen; bei Mobtypen, die man nur dort trifft,
|
||||
-- war dann keine Messung sauber und die Schaetzung viel zu niedrig.
|
||||
if (GetNumRaidMembers() > 0) then
|
||||
FBDmgTargetName = nil; FBDmgAnchorPct = nil; FBDmgAccum = 0;
|
||||
return;
|
||||
end
|
||||
local pct = UnitHealth("target") or 0;
|
||||
local drop = FBDmgAnchorPct - pct;
|
||||
if (drop >= FBDMG_MIN_DROP and FBDmgAccum > 0) then
|
||||
@@ -290,12 +347,15 @@ function FBDmg_OnTargetHealth()
|
||||
if (not HealBox.MobHP) then HealBox.MobHP = {}; end
|
||||
local e = HealBox.MobHP[key];
|
||||
if (not e) then
|
||||
HealBox.MobHP[key] = { ppp = ppp, n = 1 };
|
||||
HealBox.MobHP[key] = { ppp = ppp, n = 1, seen = time() };
|
||||
FBDmgMobCount = FBDmgMobCount + 1;
|
||||
if (FBDmgMobCount > FBDMG_MOBHP_MAX) then FBDmg_PruneMobHP(); end
|
||||
else
|
||||
-- Maximum: Fehler nur nach oben (fremder, nicht gezaehlter Schaden
|
||||
-- wuerde die Schaetzung sonst nach unten ziehen)
|
||||
if (ppp > e.ppp) then e.ppp = ppp; end
|
||||
e.n = (e.n or 0) + 1;
|
||||
e.seen = time();
|
||||
end
|
||||
end
|
||||
FBDmgAnchorPct = pct;
|
||||
@@ -326,6 +386,9 @@ function FBDmg_ParseLine(msg)
|
||||
-- "Kobold suffers 50 Shadow damage from your Shadow Word: Pain."
|
||||
_, _, victim, amount = string.find(msg, "^(.-) suffers (%d+) .- damage from your");
|
||||
if (victim) then return victim, tonumber(amount), nil, "self"; end
|
||||
-- "Kobold suffers 50 Shadow damage from Bob's Shadow Word: Pain."
|
||||
_, _, victim, amount = string.find(msg, "^(.-) suffers (%d+) .- damage from .-'s ");
|
||||
if (victim) then return victim, tonumber(amount), nil, "other"; end
|
||||
-- "Bob's Fireball hits Kobold for 200." / crits (Gruppe, Begleiter)
|
||||
_, _, victim, amount = string.find(msg, "^.-'s .- hits (.-) for (%d+)");
|
||||
if (not victim) then _, _, victim, amount = string.find(msg, "^.-'s .- crits (.-) for (%d+)"); end
|
||||
@@ -345,7 +408,8 @@ function FBDmg_OnCombatLog(msg)
|
||||
local victim, amount, spell, who = FBDmg_ParseLine(msg);
|
||||
if (not victim) then return; end
|
||||
FBDmg_NoteDamage(victim, amount);
|
||||
-- Mindestschaden lernen: eigener Zauber, kein Crit, kein Teilwiderstand
|
||||
-- Kleinsten Treffer lernen (siehe FBDmg_MinDamage): eigener Zauber, kein
|
||||
-- Crit, kein Teilwiderstand
|
||||
if (who == "self" and spell and FBDmgLastCast and FBDmgLastCast.spell == spell
|
||||
and (GetTime() - FBDmgLastCast.t) <= FBDMG_LASTCAST_SEC
|
||||
and not string.find(msg, "crits") and not string.find(msg, "resisted")) then
|
||||
@@ -353,7 +417,6 @@ function FBDmg_OnCombatLog(msg)
|
||||
if (not HealBox.DmgMemory) then HealBox.DmgMemory = {}; end
|
||||
local old = HealBox.DmgMemory[key];
|
||||
if (not old) or (amount < old) then
|
||||
-- kleinster beobachteter Volltreffer = sicherer Mindestschaden
|
||||
HealBox.DmgMemory[key] = amount;
|
||||
end
|
||||
end
|
||||
@@ -444,7 +507,15 @@ function FBDmg_HookUseAction()
|
||||
FBHealBox_UseActionHooked = true;
|
||||
local origUseAction = UseAction;
|
||||
UseAction = function(slot, checkCursor, onSelf)
|
||||
if (FBDmg_TryDownrank(slot, checkCursor, onSelf)) then return; end
|
||||
-- Geschuetzt wie die Hooks des Kerns: Ein Fehler in der Rangwahl wird
|
||||
-- gemeldet und darf den Tastendruck nicht verschlucken, der Aufruf
|
||||
-- laeuft dann unveraendert weiter
|
||||
local ok, done = pcall(FBDmg_TryDownrank, slot, checkCursor, onSelf);
|
||||
if (not ok) then
|
||||
FBHealBox_ReportError("Smart Damage", done);
|
||||
done = false;
|
||||
end
|
||||
if (done) then return; end
|
||||
origUseAction(slot, checkCursor, onSelf);
|
||||
end
|
||||
end
|
||||
@@ -454,24 +525,72 @@ end
|
||||
-- ==========================================================================
|
||||
|
||||
FBDmgFrame = CreateFrame("Frame", "FBHealBoxDamageFrame", UIParent);
|
||||
-- Immer: Zauberbuch geaendert. Das kostet nichts, ausgeschaltet wird nur
|
||||
-- vorgemerkt.
|
||||
FBDmgFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
|
||||
FBDmgFrame:RegisterEvent("SPELLS_CHANGED");
|
||||
FBDmgFrame:RegisterEvent("ACTIONBAR_SLOT_CHANGED");
|
||||
FBDmgFrame:RegisterEvent("PLAYER_TARGET_CHANGED");
|
||||
FBDmgFrame:RegisterEvent("UNIT_HEALTH");
|
||||
for _, ev in ipairs({
|
||||
|
||||
-- Nur solange Smart Damage an ist (FBDmg_UpdateActive). Bis 1.4.6 liefen
|
||||
-- Combatlog, UNIT_HEALTH und Zielwechsel auch im Standardzustand aus
|
||||
-- durch dieses Modul.
|
||||
FBDmgActiveEvents = {
|
||||
"ACTIONBAR_SLOT_CHANGED", "PLAYER_TARGET_CHANGED", "UNIT_HEALTH",
|
||||
"CHAT_MSG_SPELL_SELF_DAMAGE", "CHAT_MSG_COMBAT_SELF_HITS",
|
||||
"CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE", "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE",
|
||||
"CHAT_MSG_SPELL_PARTY_DAMAGE", "CHAT_MSG_COMBAT_PARTY_HITS",
|
||||
"CHAT_MSG_SPELL_PET_DAMAGE", "CHAT_MSG_COMBAT_PET_HITS",
|
||||
}) do FBDmgFrame:RegisterEvent(ev); end
|
||||
-- Spieler ausserhalb der Gruppe, die denselben Gegner angreifen
|
||||
"CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE", "CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS",
|
||||
};
|
||||
|
||||
function FBDmg_UpdateActive()
|
||||
local on = (FBDmg_Cfg().Enabled == 1) and (not FBAddonSuppressed);
|
||||
if (on == FBDmgActive) then return; end
|
||||
FBDmgActive = on;
|
||||
for _, ev in ipairs(FBDmgActiveEvents) do
|
||||
if (on) then FBDmgFrame:RegisterEvent(ev); else FBDmgFrame:UnregisterEvent(ev); end
|
||||
end
|
||||
if (on) then
|
||||
-- Was waehrend der Pause auf den Leisten passiert ist, weiss das
|
||||
-- Modul nicht: Slots neu lesen, Zauberbuch bei Bedarf auch.
|
||||
FBDmgSlotCache = {};
|
||||
if (FBDmgSpellsDirty) then FBDmg_ScheduleScan(); end
|
||||
FBDmg_ResetTarget();
|
||||
else
|
||||
FBDmgTargetName = nil; FBDmgAnchorPct = nil; FBDmgAccum = 0;
|
||||
FBDmgLastCast = nil;
|
||||
end
|
||||
end
|
||||
|
||||
-- Zauberbuch im naechsten Frame lesen, einmal je Salve. Beim Login kommen
|
||||
-- PLAYER_ENTERING_WORLD und mehrere SPELLS_CHANGED kurz hintereinander,
|
||||
-- bis 1.4.6 las jedes davon alle Schadenszauber samt Tooltips sofort. Der
|
||||
-- OnUpdate haengt nur, solange etwas ansteht.
|
||||
function FBDmg_ScheduleScan()
|
||||
FBDmgSpellsDirty = true;
|
||||
-- Gelesen wird, wenn das Modul an ist oder jemand die Liste gerade sieht
|
||||
if (FBDmgActive) or (FBPanel and FBPanel:IsVisible()) then
|
||||
FBDmgFrame:SetScript("OnUpdate", FBDmg_OnUpdate);
|
||||
end
|
||||
end
|
||||
|
||||
function FBDmg_OnUpdate()
|
||||
FBDmgFrame:SetScript("OnUpdate", nil);
|
||||
if (FBAddonSuppressed) or (not FBDmgSpellsDirty) then return; end
|
||||
if (FBDmgActive) then
|
||||
FBDmg_ScanSpells();
|
||||
FBDmg_UpdateSpellText();
|
||||
FBDmg_ResetTarget();
|
||||
else
|
||||
-- Ausgeschaltet, Optionen offen: liest bei Bedarf selbst
|
||||
FBDmg_UpdateSpellText();
|
||||
end
|
||||
end
|
||||
|
||||
FBDmgFrame:SetScript("OnEvent", function()
|
||||
if (FBAddonSuppressed) then return; end
|
||||
if (event == "PLAYER_ENTERING_WORLD" or event == "SPELLS_CHANGED") then
|
||||
FBDmg_ScanSpells();
|
||||
FBDmg_UpdateSpellText();
|
||||
FBDmg_ResetTarget();
|
||||
FBDmg_ScheduleScan();
|
||||
elseif (event == "ACTIONBAR_SLOT_CHANGED") then
|
||||
if (arg1) then FBDmgSlotCache[arg1] = nil; else FBDmgSlotCache = {}; end
|
||||
elseif (event == "PLAYER_TARGET_CHANGED") then
|
||||
@@ -503,13 +622,16 @@ end
|
||||
|
||||
function FBDmg_UpdateSourceText()
|
||||
-- nur, wenn das Optionsfenster offen ist (sonst je UNIT_HEALTH des Ziels umsonst)
|
||||
if (FBDmgSourceText and panel and panel:IsVisible()) then
|
||||
if (FBDmgSourceText and FBPanel and FBPanel:IsVisible()) then
|
||||
FBDmgSourceText:SetText(format(FBT("DMG_SRC"), FBDmg_SourceText()));
|
||||
end
|
||||
end
|
||||
|
||||
function FBDmg_UpdateSpellText()
|
||||
if (not FBDmgSpellText) then return; end
|
||||
-- Ausgeschaltet liest das Modul das Zauberbuch erst, wenn jemand die
|
||||
-- Optionen ansieht
|
||||
if (FBDmgSpellsDirty and FBPanel and FBPanel:IsVisible()) then FBDmg_ScanSpells(); end
|
||||
local list = {};
|
||||
for _, n in ipairs(FBDamageSpells[FBClass] or {}) do
|
||||
if (FBDmgSpellRanks[n]) then table.insert(list, n.." ("..table.getn(FBDmgSpellRanks[n])..")"); end
|
||||
@@ -519,16 +641,12 @@ function FBDmg_UpdateSpellText()
|
||||
FBDmgSpellText:SetText(format(FBT("DMG_SPELLS"), shown));
|
||||
end
|
||||
|
||||
function FBDmg_UpdateMarginText()
|
||||
if (FBDmgMarginSlider and FBDmgMarginSlider.Text) then
|
||||
FBDmgMarginSlider.Text:SetText(format(FBT("DMG_MARGIN"), math.floor(FBDmgMarginSlider:GetValue() + 0.5)));
|
||||
end
|
||||
end
|
||||
|
||||
-- Eigener Abschnitt im Reiter "Extras", den der Kern verwaltet. Bis 1.4.6
|
||||
-- suchte das Modul den Reiter des Mana-Tickers und setzte sich 232 px
|
||||
-- darunter; ohne Tickerdatei gab es fuer Smart Damage gar keine Optionen.
|
||||
function FBDmg_BuildOptions()
|
||||
local tab = FBHealBox_FindOptionsTab("TAB_TICKER");
|
||||
local tab, y = FBHealBox_ExtrasSection(FBDMG_SECTION_H);
|
||||
if (not tab) then return; end
|
||||
local y = FBOPT_CONTENT_Y - 232; -- unter dem Ticker-Abschnitt
|
||||
|
||||
FBDmgHeader = tab:CreateFontString(nil, "OVERLAY", "GameFontNormal");
|
||||
FBDmgHeader:SetPoint("TOPLEFT", tab, "TOPLEFT", 35, y);
|
||||
@@ -536,25 +654,12 @@ function FBDmg_BuildOptions()
|
||||
|
||||
FBDmgEnabledCheck = FBHealBox_CreateCheck("FBHealBoxDmgEnabledCheck", tab, 34, y - 20, "DMG_ENABLED", "DMG_ENABLED_TIP", function()
|
||||
FBDmg_Cfg().Enabled = FBDmgEnabledCheck:GetChecked() and 1 or 0;
|
||||
FBDmg_UpdateActive();
|
||||
end);
|
||||
FBDmgEnabledCheck:SetChecked(nil);
|
||||
|
||||
FBDmgMarginSlider = CreateFrame("Slider", "FBDmgMarginSlider", tab, "OptionsSliderTemplate");
|
||||
FBDmgMarginSlider:SetWidth(170);
|
||||
FBDmgMarginSlider:SetHeight(16);
|
||||
FBDmgMarginSlider:SetPoint("TOPLEFT", 268, y - 40);
|
||||
FBDmgMarginSlider:SetMinMaxValues(0, 50);
|
||||
FBDmgMarginSlider:SetValueStep(5);
|
||||
FBDmgMarginSlider:SetValue(FBDmg_Cfg().Margin or 20);
|
||||
FBDmgMarginSlider.Text = FBDmgMarginSlider:CreateFontString(nil, "BACKGROUND", "GameFontNormal");
|
||||
FBDmgMarginSlider.Text:SetPoint("CENTER", 0, 15);
|
||||
getglobal("FBDmgMarginSliderLow"):SetText("0");
|
||||
getglobal("FBDmgMarginSliderHigh"):SetText("50");
|
||||
FBDmgMarginSlider:SetScript("OnValueChanged", function()
|
||||
FBDmg_Cfg().Margin = math.floor(FBDmgMarginSlider:GetValue() + 0.5);
|
||||
FBDmg_UpdateMarginText();
|
||||
end);
|
||||
FBDmg_UpdateMarginText();
|
||||
FBDmgMarginSlider = FBHealBox_CreateSlider("FBDmgMarginSlider", tab, 268, y - 40, "DMG_MARGIN",
|
||||
FBDmg_Cfg, "Margin", 0, 50, 5, false, nil, nil, 170);
|
||||
|
||||
FBDmgSourceText = tab:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall");
|
||||
FBDmgSourceText:SetPoint("TOPLEFT", tab, "TOPLEFT", 40, y - 80);
|
||||
@@ -574,10 +679,11 @@ function FBDmg_BuildOptions()
|
||||
FBDmg_UpdateSpellText();
|
||||
FBDmg_SyncOptions();
|
||||
-- beim Oeffnen des Fensters die Zielzeile auffrischen (Vor-Hook auf OnShow)
|
||||
local prevShow = panel:GetScript("OnShow");
|
||||
panel:SetScript("OnShow", function()
|
||||
local prevShow = FBPanel:GetScript("OnShow");
|
||||
FBPanel:SetScript("OnShow", function()
|
||||
if (prevShow) then prevShow(); end
|
||||
FBDmg_UpdateSourceText();
|
||||
FBDmg_UpdateSpellText();
|
||||
end);
|
||||
end
|
||||
|
||||
@@ -585,6 +691,7 @@ function FBDmg_SyncOptions()
|
||||
local cfg = FBDmg_Cfg();
|
||||
if (FBDmgEnabledCheck) then FBDmgEnabledCheck:SetChecked(cfg.Enabled == 1); end
|
||||
if (FBDmgMarginSlider) then FBDmgMarginSlider:SetValue(cfg.Margin or 20); end
|
||||
FBDmg_UpdateActive();
|
||||
return true;
|
||||
end
|
||||
|
||||
@@ -592,7 +699,7 @@ function FBDmg_ApplyLocale()
|
||||
if (FBDmgHeader) then FBDmgHeader:SetText(FBT("DMG_HEADER")); end
|
||||
if (FBDmgEnabledCheck) then FBDmgEnabledCheck.Text:SetText(FBT("DMG_ENABLED")); FBDmgEnabledCheck.tooltipText = FBT("DMG_ENABLED_TIP"); end
|
||||
if (FBDmgInfoText) then FBDmgInfoText:SetText(FBT("DMG_INFO")); end
|
||||
FBDmg_UpdateMarginText();
|
||||
FBHealBox_SliderText(FBDmgMarginSlider);
|
||||
FBDmg_UpdateSourceText();
|
||||
FBDmg_UpdateSpellText();
|
||||
return true;
|
||||
@@ -604,8 +711,10 @@ end
|
||||
|
||||
FBHealBox_RegisterHook("Loaded", function()
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00"..FBADDON_NAME..":|r "..FBT("DMG_LOADED"));
|
||||
FBDmg_UpdateActive();
|
||||
return true;
|
||||
end);
|
||||
FBHealBox_RegisterHook("Suppress", function() FBDmg_UpdateActive(); return true; end);
|
||||
FBHealBox_RegisterHook("Defaults", function() return FBDmg_ApplyDefaults(); end);
|
||||
FBHealBox_RegisterHook("SyncOptions", function() return FBDmg_SyncOptions(); end);
|
||||
FBHealBox_RegisterHook("ApplyLocale", function() return FBDmg_ApplyLocale(); end);
|
||||
@@ -620,7 +729,7 @@ FBHealBox_RegisterHook("Slash", function(msg)
|
||||
if (msg == "damage" or msg == "dmg") then
|
||||
local cfg = FBDmg_Cfg();
|
||||
if (cfg.Enabled == 1) then cfg.Enabled = 0; else cfg.Enabled = 1; end
|
||||
FBDmg_SyncOptions();
|
||||
FBDmg_SyncOptions(); -- schaltet auch die Ereignisse um
|
||||
local key = "DMG_OFF";
|
||||
if (cfg.Enabled == 1) then key = "DMG_ON"; end
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00"..FBADDON_NAME..":|r "..FBT(key));
|
||||
|
||||
+206
-261
@@ -284,6 +284,11 @@ FBLocale["deDE"].RAID_LOADED = "Raidmodus-Modul geladen: Reiter |cFFFFFFFF
|
||||
FBRaidCells = {}; -- [g][pos] = Zelle
|
||||
FBRaidGroups = {}; -- [g] = Gruppenblock-Frame
|
||||
FBRaidUnitCell = {}; -- ["raid12"] = Zelle (nach jedem Roster-Update neu)
|
||||
-- Flache Listen statt der doppelten Schleife ueber Gruppen und Plaetze, die
|
||||
-- bis 1.4.6 rund zehnmal im Modul stand:
|
||||
FBRaidAllCells = {}; -- jede je erzeugte Zelle (Aufraeumen, Buttons)
|
||||
FBRaidActiveCells = {}; -- belegte Zellen der aktuellen Anzeige
|
||||
FBRaidNameCell = {}; -- [Name] = Zelle (fuer den Hook "RefreshNames")
|
||||
FBRaidMembers = 0; -- Anzahl Mitglieder in der aktuellen Anzeige
|
||||
FBRaidUsedGroups = 0; -- Anzahl belegter Gruppen
|
||||
FBRaidTestMode = 0; -- 0 | 20 | 40
|
||||
@@ -381,12 +386,6 @@ function FBRaid_BuildTestGhosts(count)
|
||||
end
|
||||
end
|
||||
|
||||
function FBRaid_InRaid()
|
||||
local n = GetNumRaidMembers();
|
||||
return (n and n > 0);
|
||||
end
|
||||
|
||||
-- true, wenn das Raster ueberhaupt gezeigt werden soll
|
||||
-- true, wenn das Raster ueberhaupt gezeigt werden soll: Raidmodus an,
|
||||
-- Anzeige an, und entweder Raid-Test oder ein Raid mit mindestens
|
||||
-- MinPlayers Mitgliedern
|
||||
@@ -693,7 +692,11 @@ end
|
||||
|
||||
function FBRaid_GetCell(g, pos)
|
||||
if (not FBRaidCells[g]) then FBRaidCells[g] = {}; end
|
||||
if (not FBRaidCells[g][pos]) then FBRaidCells[g][pos] = FBRaid_CreateCell(g, pos); end
|
||||
if (not FBRaidCells[g][pos]) then
|
||||
local c = FBRaid_CreateCell(g, pos);
|
||||
FBRaidCells[g][pos] = c;
|
||||
table.insert(FBRaidAllCells, c);
|
||||
end
|
||||
return FBRaidCells[g][pos];
|
||||
end
|
||||
|
||||
@@ -741,21 +744,25 @@ function FBRaid_UpdateRoster()
|
||||
FBRaidRosterDirty = false;
|
||||
local cfg = FBRaid_Cfg();
|
||||
FBRaidUnitCell = {};
|
||||
FBRaidActiveCells = {};
|
||||
FBRaidNameCell = {};
|
||||
FBRaidMembers = 0;
|
||||
local perGroup = {};
|
||||
for g = 1, FBRAID_GROUPS do perGroup[g] = 0; end
|
||||
|
||||
-- alle Zellen zuruecksetzen
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
if (FBRaidCells[g] and FBRaidCells[g][pos]) then
|
||||
local c = FBRaidCells[g][pos];
|
||||
c.unit = nil; c.name = nil; c.ghost = nil; c.index = nil;
|
||||
c.dispelKnown = nil; c.lastText = nil; c.lastPct = nil; c.lastDef = nil; c.lastMax = nil; c.colorKey = nil; c.manaShown = nil; c.lastMpMax = nil; c.powerType = nil;
|
||||
c.vHp = nil; c.vShield = nil; c.vInc = nil; c.vMp = nil;
|
||||
c:Hide();
|
||||
end
|
||||
for _, c in ipairs(FBRaidAllCells) do
|
||||
c.unit = nil; c.name = nil; c.ghost = nil; c.index = nil;
|
||||
c.dispelKnown = nil; c.lastText = nil; c.lastPct = nil; c.lastDef = nil; c.lastMax = nil; c.colorKey = nil; c.manaShown = nil; c.lastMpMax = nil; c.powerType = nil;
|
||||
c.vHp = nil; c.vShield = nil; c.vInc = nil; c.vMp = nil;
|
||||
-- Rahmenzustand gehoert dem alten Bewohner. Ohne Reset behielt eine
|
||||
-- wiederverwendete Zelle den roten Angriffsrahmen, und FBRaid_CheckAggro
|
||||
-- sah sie als inaktive Zelle nie wieder an.
|
||||
if (c.underAttack or c.buffMissing) then
|
||||
c.underAttack = nil; c.buffMissing = nil;
|
||||
FBRaid_ApplyBorder(c);
|
||||
end
|
||||
c:Hide();
|
||||
end
|
||||
|
||||
if (FBRaid_IsActive()) then
|
||||
@@ -774,6 +781,8 @@ function FBRaid_UpdateRoster()
|
||||
if (HealBox.ClassColors == 1) then col = FBClassColor(m.class); end
|
||||
if (col) then c.NameText:SetTextColor(col.r, col.g, col.b, 1); else c.NameText:SetTextColor(1, 1, 1, 1); end
|
||||
FBRaidUnitCell[m.unit] = c;
|
||||
table.insert(FBRaidActiveCells, c);
|
||||
if (m.name) then FBRaidNameCell[m.name] = c; end
|
||||
FBRaidMembers = FBRaidMembers + 1;
|
||||
c:Show();
|
||||
end
|
||||
@@ -790,6 +799,11 @@ function FBRaid_UpdateRoster()
|
||||
FBRaid_SyncButtons();
|
||||
FBRaid_RefreshAll();
|
||||
FBRaid_Tick(true);
|
||||
-- Andere Module (Mana-Ticker) sammeln ihre Zellen neu ein. Bis 1.4.6
|
||||
-- erfuhren sie davon nur ueber "UpdateNames"; baute das Raster nach einem
|
||||
-- reinen RAID_ROSTER_UPDATE um (etwa beim Ueberschreiten der Schwelle),
|
||||
-- fehlte der Funke oder lief auf der Zelle eines anderen Spielers.
|
||||
FBHealBox_RunHook("RaidRoster");
|
||||
end
|
||||
|
||||
-- ==========================================================================
|
||||
@@ -824,9 +838,12 @@ function FBRaid_ApplyCellSize(c, cfg)
|
||||
end
|
||||
end
|
||||
|
||||
FBRaidLaidStrip = nil; -- Breite des Streifens fuer die Buff-Icons beim letzten Legen
|
||||
|
||||
function FBRaid_LayoutAll()
|
||||
local cfg = FBRaid_Cfg();
|
||||
local rowW = FBRaid_RowWidth(cfg);
|
||||
FBRaidLaidStrip = FBRaid_BuffStrip(cfg);
|
||||
local headH = 0;
|
||||
if (cfg.Headers == 1) then headH = FBRAID_HEADER_H; end
|
||||
local blockH = headH + FBRAID_PER_GROUP * cfg.CellH + (FBRAID_PER_GROUP - 1) * cfg.CellGap;
|
||||
@@ -922,27 +939,10 @@ end
|
||||
-- [ Zelleninhalt ]
|
||||
-- ==========================================================================
|
||||
|
||||
-- Zellenfarbe / Maxima / Text nur bei Aenderung setzen
|
||||
function FBRaid_SetColor(c, key, r, g, b, a)
|
||||
if (c.colorKey == key) then return; end
|
||||
c.colorKey = key;
|
||||
c.HealthBar:SetStatusBarColor(r, g, b, a);
|
||||
end
|
||||
|
||||
function FBRaid_SetValues(c, hp, shieldTop, incTop)
|
||||
if (c.vHp ~= hp) then c.vHp = hp; c.HealthBar:SetValue(hp); end
|
||||
if (c.vShield ~= shieldTop) then c.vShield = shieldTop; c.ShieldBar:SetValue(shieldTop); end
|
||||
if (c.vInc ~= incTop) then c.vInc = incTop; c.IncHealBar:SetValue(incTop); end
|
||||
end
|
||||
|
||||
function FBRaid_SetMax(c, hpMax)
|
||||
if (c.lastMax == hpMax) then return; end
|
||||
c.lastMax = hpMax;
|
||||
c.HealthBar:SetMinMaxValues(0, hpMax);
|
||||
c.ShieldBar:SetMinMaxValues(0, hpMax);
|
||||
c.IncHealBar:SetMinMaxValues(0, hpMax);
|
||||
end
|
||||
|
||||
-- Farbe, Werte und Maxima der Balken setzen die Helfer des Kerns
|
||||
-- (FBHealBox_SetBarColor, FBHealBox_SetBarValues, FBHealBox_SetBarMax): Die
|
||||
-- Zelle traegt dieselben Felder wie eine Plakette. Bis 1.4.6 standen hier
|
||||
-- Kopien davon. Nur der HP-Text ist eigen, er kann ganz verschwinden.
|
||||
function FBRaid_SetText(c, text)
|
||||
if (c.lastText == text) then return; end
|
||||
c.lastText = text;
|
||||
@@ -963,21 +963,21 @@ function FBRaid_UpdateCell(c, auraChanged)
|
||||
if (state == "offline") then key = "STATE_OFFLINE"; end
|
||||
FBRaid_SetText(c, FBT(key));
|
||||
c.lastPct = nil; c.lastDef = nil; -- Zahlenspeicher gilt nicht mehr
|
||||
FBRaid_SetMax(c, hpMax);
|
||||
FBRaid_SetValues(c, 0, 0, 0);
|
||||
FBRaid_SetColor(c, "state", 0.5, 0.5, 0.5, 1);
|
||||
FBHealBox_SetBarMax(c, hpMax);
|
||||
FBHealBox_SetBarValues(c, 0, 0, 0);
|
||||
FBHealBox_SetBarColor(c, "state", 0.5, 0.5, 0.5, 1);
|
||||
if (c.manaShown ~= false) then c.manaShown = false; c.ManaBar:Hide(); end
|
||||
return;
|
||||
end
|
||||
|
||||
-- Leben und Schichten
|
||||
FBRaid_SetMax(c, hpMax);
|
||||
FBHealBox_SetBarMax(c, hpMax);
|
||||
local inc, shield = FBRaid_Incoming(c);
|
||||
local shieldTop = hp + shield;
|
||||
if (shieldTop > hpMax) then shieldTop = hpMax; end
|
||||
local incTop = shieldTop + inc;
|
||||
if (incTop > hpMax) then incTop = hpMax; end
|
||||
FBRaid_SetValues(c, hp, shieldTop, incTop);
|
||||
FBHealBox_SetBarValues(c, hp, shieldTop, incTop);
|
||||
|
||||
-- HP-Text. Verglichen wird die Zahl, nicht der fertige Text: sonst baut
|
||||
-- jedes UNIT_HEALTH einen String, der meist sofort wieder verworfen wird.
|
||||
@@ -999,15 +999,7 @@ function FBRaid_UpdateCell(c, auraChanged)
|
||||
end
|
||||
|
||||
-- Mana
|
||||
local mp, mpMax, hasMana, ptype = FBRaid_Mana(c);
|
||||
if (cfg.ManaBar == 1 and hasMana and mpMax > 0) then
|
||||
FBHealBox_SetPowerColor(c.ManaBar, c, ptype);
|
||||
if (c.lastMpMax ~= mpMax) then c.lastMpMax = mpMax; c.ManaBar:SetMinMaxValues(0, mpMax); end
|
||||
if (c.vMp ~= mp) then c.vMp = mp; c.ManaBar:SetValue(mp); end
|
||||
if (c.manaShown ~= true) then c.manaShown = true; c.ManaBar:Show(); end
|
||||
elseif (c.manaShown ~= false) then
|
||||
c.manaShown = false; c.ManaBar:Hide();
|
||||
end
|
||||
FBRaid_UpdateCellMana(c, cfg);
|
||||
|
||||
-- Farbe: Dispel schlaegt HP-Stand (Debuff nur bei Aura-Aenderung neu suchen)
|
||||
if (auraChanged or (not c.dispelKnown) or c.ghost) then
|
||||
@@ -1018,16 +1010,39 @@ function FBRaid_UpdateCell(c, auraChanged)
|
||||
local dtype = c.dispelType;
|
||||
if (dtype and FBDispelColors[dtype]) then
|
||||
local col = FBDispelColors[dtype];
|
||||
FBRaid_SetColor(c, dtype, col[1], col[2], col[3], col[4]);
|
||||
elseif (frac > LowHP) then
|
||||
FBRaid_SetColor(c, "green", 0, 1, 0, 1);
|
||||
elseif (frac > VeryLowHP) then
|
||||
FBRaid_SetColor(c, "yellow", 1, 0.9, 0, 1);
|
||||
FBHealBox_SetBarColor(c, dtype, col[1], col[2], col[3], col[4]);
|
||||
elseif (frac > FBLowHP) then
|
||||
FBHealBox_SetBarColor(c, "green", 0, 1, 0, 1);
|
||||
elseif (frac > FBVeryLowHP) then
|
||||
FBHealBox_SetBarColor(c, "yellow", 1, 0.9, 0, 1);
|
||||
else
|
||||
FBRaid_SetColor(c, "red", 1, 0, 0, 1);
|
||||
FBHealBox_SetBarColor(c, "red", 1, 0, 0, 1);
|
||||
end
|
||||
end
|
||||
|
||||
-- Manastreifen einer Zelle. Eigener Weg fuer UNIT_MANA: Das feuert im Raid
|
||||
-- fuer jeden Manabenutzer alle zwei Sekunden, bis 1.4.6 rechnete jedes davon
|
||||
-- die ganze Zelle neu (Leben, Vorhersage, Schild, Farbe, Text).
|
||||
function FBRaid_UpdateCellMana(c, cfg)
|
||||
local mp, mpMax, hasMana, ptype = FBRaid_Mana(c);
|
||||
if (cfg.ManaBar == 1 and hasMana and mpMax > 0) then
|
||||
FBHealBox_SetPowerColor(c.ManaBar, c, ptype);
|
||||
if (c.lastMpMax ~= mpMax) then c.lastMpMax = mpMax; c.ManaBar:SetMinMaxValues(0, mpMax); end
|
||||
if (c.vMp ~= mp) then c.vMp = mp; c.ManaBar:SetValue(mp); end
|
||||
if (c.manaShown ~= true) then c.manaShown = true; c.ManaBar:Show(); end
|
||||
elseif (c.manaShown ~= false) then
|
||||
c.manaShown = false; c.ManaBar:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
-- Schmaler Pfad: nur das Mana, und nur bei lebenden, verbundenen Einheiten
|
||||
-- (Tot, Geist, offline blendet FBRaid_UpdateCell den Streifen aus)
|
||||
function FBRaid_UpdateCellManaOnly(c)
|
||||
if (not c) or (not c.unit) or (not c:IsShown()) then return; end
|
||||
if (FBRaid_State(c)) then return; end
|
||||
FBRaid_UpdateCellMana(c, FBRaid_Cfg());
|
||||
end
|
||||
|
||||
-- Rahmen: Angegriffener (rot) vor Buff-Wache (orange) vor normal
|
||||
function FBRaid_ApplyBorder(c)
|
||||
local col = FBBUFF_NORMAL_COLOR;
|
||||
@@ -1052,24 +1067,17 @@ end
|
||||
function FBRaid_CheckAggro(tt)
|
||||
if (not FBRaid_IsActive()) then return false; end
|
||||
local any = false;
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c and c.unit) then
|
||||
local flag = false;
|
||||
if (HealBox.AggroMark == 1 and c:IsShown()) then
|
||||
if (c.ghost) then flag = (c.ghost.aggro == true);
|
||||
elseif (tt) then flag = FBHealBox_UnitIsAggroFast(c.unit, c.name, tt); end
|
||||
end
|
||||
if (c.underAttack ~= flag) then
|
||||
c.underAttack = flag;
|
||||
FBRaid_ApplyBorder(c);
|
||||
end
|
||||
if (flag) then any = true; end
|
||||
end
|
||||
end
|
||||
for _, c in ipairs(FBRaidActiveCells) do
|
||||
local flag = false;
|
||||
if (HealBox.AggroMark == 1 and c:IsShown()) then
|
||||
if (c.ghost) then flag = (c.ghost.aggro == true);
|
||||
elseif (tt) then flag = FBHealBox_UnitIsAggroFast(c.unit, c.name, tt); end
|
||||
end
|
||||
if (c.underAttack ~= flag) then
|
||||
c.underAttack = flag;
|
||||
FBRaid_ApplyBorder(c);
|
||||
end
|
||||
if (flag) then any = true; end
|
||||
end
|
||||
return any;
|
||||
end
|
||||
@@ -1084,18 +1092,11 @@ end
|
||||
function FBRaid_UpdateBuffIcons()
|
||||
if (not FBRaid_IsActive()) then return; end
|
||||
local on = (FBRaid_Cfg().BuffIcons == 1);
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c) then
|
||||
if (on and c.unit and c:IsShown()) then
|
||||
FBHealBox_UpdateBuffIcons(c, c.name, c.ghost, FBRAID_BUFFICON_SIZE, FBRAID_BUFFICON_ROWS, FBRAID_BUFFICON_MAX);
|
||||
else
|
||||
FBHealBox_UpdateBuffIcons(c, nil, nil, FBRAID_BUFFICON_SIZE, FBRAID_BUFFICON_ROWS, FBRAID_BUFFICON_MAX);
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, c in ipairs(FBRaidAllCells) do
|
||||
if (on and c.unit and c:IsShown()) then
|
||||
FBHealBox_UpdateBuffIcons(c, c.name, c.ghost, FBRAID_BUFFICON_SIZE, FBRAID_BUFFICON_ROWS, FBRAID_BUFFICON_MAX);
|
||||
else
|
||||
FBHealBox_UpdateBuffIcons(c, nil, nil, FBRAID_BUFFICON_SIZE, FBRAID_BUFFICON_ROWS, FBRAID_BUFFICON_MAX);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1103,32 +1104,25 @@ end
|
||||
-- HoT-/Schild-Timer auf den Mini-Buttons (Hook "SpellTimers")
|
||||
function FBRaid_UpdateSpellTimers(now)
|
||||
local on = (HealBox.SpellTimers == 1) and FBRaid_IsActive();
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c) then
|
||||
local shown = on and c.unit and c:IsShown() and (c.ghost or FBHoTs[c.name] or FBShields[c.name]
|
||||
or (FBWeakenedSoul and FBWeakenedSoul[c.name]));
|
||||
-- Nichts anzuzeigen und nichts mehr wegzuraeumen: Zelle
|
||||
-- ueberspringen. Vorher lief die Buttonschleife auch dann
|
||||
-- durch, im Vierzigerraid 160 Leeraufrufe fuenfmal je
|
||||
-- Sekunde. Der Kern macht es bei den Plaketten genauso.
|
||||
if (shown or c.timersShown) then
|
||||
c.timersShown = (shown and true) or false;
|
||||
for i = 1, FBRAID_MAX_BUTTONS do
|
||||
local b = c.buttons[i];
|
||||
if (shown and b:IsShown()) then
|
||||
local text, color = FBHealBox_SpellTimerFor(b.spellBase, c.name, now, c.ghost, i);
|
||||
if (not text and b.spellBaseR) then
|
||||
text, color = FBHealBox_SpellTimerFor(b.spellBaseR, c.name, now, nil, i);
|
||||
end
|
||||
FBHealBox_SetButtonTimer(b, text, color);
|
||||
else
|
||||
FBHealBox_SetButtonTimer(b, nil);
|
||||
end
|
||||
end
|
||||
for _, c in ipairs(FBRaidAllCells) do
|
||||
local shown = on and c.unit and c:IsShown() and (c.ghost or FBHoTs[c.name] or FBShields[c.name]
|
||||
or (FBWeakenedSoul and FBWeakenedSoul[c.name]));
|
||||
-- Nichts anzuzeigen und nichts mehr wegzuraeumen: Zelle
|
||||
-- ueberspringen. Vorher lief die Buttonschleife auch dann
|
||||
-- durch, im Vierzigerraid 160 Leeraufrufe fuenfmal je
|
||||
-- Sekunde. Der Kern macht es bei den Plaketten genauso.
|
||||
if (shown or c.timersShown) then
|
||||
c.timersShown = (shown and true) or false;
|
||||
for i = 1, FBRAID_MAX_BUTTONS do
|
||||
local b = c.buttons[i];
|
||||
if (shown and b:IsShown()) then
|
||||
local text, color = FBHealBox_SpellTimerFor(b.spellBase, c.name, now, c.ghost, i);
|
||||
if (not text and b.spellBaseR) then
|
||||
text, color = FBHealBox_SpellTimerFor(b.spellBaseR, c.name, now, nil, i);
|
||||
end
|
||||
FBHealBox_SetButtonTimer(b, text, color);
|
||||
else
|
||||
FBHealBox_SetButtonTimer(b, nil);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1136,101 +1130,74 @@ function FBRaid_UpdateSpellTimers(now)
|
||||
end
|
||||
|
||||
function FBRaid_UpdateCooldowns()
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c) then
|
||||
for i = 1, FBRAID_MAX_BUTTONS do
|
||||
local b = c.buttons[i];
|
||||
b.cdKey = nil;
|
||||
FBHealBox_UpdateButtonState(b, "SPELL_UPDATE_COOLDOWN");
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, c in ipairs(FBRaidAllCells) do
|
||||
for i = 1, FBRAID_MAX_BUTTONS do
|
||||
local b = c.buttons[i];
|
||||
b.cdStart = nil;
|
||||
FBHealBox_UpdateButtonState(b, "SPELL_UPDATE_COOLDOWN");
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Button-Zustaende der sichtbaren Zellen (Hook "ButtonStates")
|
||||
-- Button-Zustaende der sichtbaren Zellen (Hook "ButtonStates"). Laeuft
|
||||
-- geschuetzt wie der Durchlauf des Kerns, siehe FBHealBox_UpdateButtonStates.
|
||||
function FBRaid_ButtonStates(event)
|
||||
local ok, err = pcall(FBRaid_UpdateButtonStates, event);
|
||||
FBHealBox_SweepResult("FBRaid_UpdateButtonStates", ok, err);
|
||||
end
|
||||
|
||||
function FBRaid_UpdateButtonStates(event)
|
||||
if (not FBRaid_IsActive()) then return; end
|
||||
local nBtn = FBRaid_Cfg().Buttons or 0;
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c and c.unit and c:IsShown()) then
|
||||
for i = 1, nBtn do FBHealBox_UpdateButtonState(c.buttons[i], event); end
|
||||
end
|
||||
end
|
||||
for _, c in ipairs(FBRaidActiveCells) do
|
||||
if (c:IsShown()) then
|
||||
for i = 1, nBtn do FBHealBox_UpdateButtonState(c.buttons[i], event); end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function FBRaid_RefreshAll()
|
||||
if (not FBRaid_IsActive()) then return; end
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c and c.unit) then FBRaid_UpdateCell(c); end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, c in ipairs(FBRaidActiveCells) do FBRaid_UpdateCell(c); end
|
||||
end
|
||||
|
||||
function FBRaid_RefreshBuffBorders()
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c and c.unit) then FBRaid_UpdateBuffBorder(c); end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, c in ipairs(FBRaidActiveCells) do FBRaid_UpdateBuffBorder(c); end
|
||||
end
|
||||
|
||||
-- Buttons einer Zelle an die Belegung angleichen (Icons, Zauber, Rechtsklick)
|
||||
function FBRaid_SyncButtons()
|
||||
local rightOn = (HealBox.RightClick == 1);
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c) then
|
||||
for i = 1, FBRAID_MAX_BUTTONS do
|
||||
local b = c.buttons[i];
|
||||
b.TargetUnit = c.unit;
|
||||
b.spellName = FBDropDownButton[i];
|
||||
b.id = FBActiveSpellIDs[i];
|
||||
if (FBDropDownButtonIcon[i]) then
|
||||
b.icon:SetTexture(FBDropDownButtonIcon[i]);
|
||||
else
|
||||
b.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark");
|
||||
end
|
||||
if (rightOn) then
|
||||
b.spellNameR = FBDropDownButtonR[i];
|
||||
b.idR = FBActiveSpellIDsR[i];
|
||||
else
|
||||
b.spellNameR = nil;
|
||||
b.idR = nil;
|
||||
end
|
||||
if (b.subIcon) then
|
||||
if (b.spellNameR and FBDropDownButtonIconR[i]) then
|
||||
b.subIcon:SetTexture(FBDropDownButtonIconR[i]);
|
||||
b.subIcon:Show();
|
||||
else
|
||||
b.subIcon:Hide();
|
||||
end
|
||||
end
|
||||
b.cdKey = nil;
|
||||
b.colorState = nil;
|
||||
if (b.spellName) then b.spellBase = FBPredict_SplitCast(b.spellName); else b.spellBase = nil; end
|
||||
if (b.spellNameR) then b.spellBaseR = FBPredict_SplitCast(b.spellNameR); else b.spellBaseR = nil; end
|
||||
end
|
||||
for _, c in ipairs(FBRaidAllCells) do
|
||||
for i = 1, FBRAID_MAX_BUTTONS do
|
||||
local b = c.buttons[i];
|
||||
b.TargetUnit = c.unit;
|
||||
b.spellName = FBDropDownButton[i];
|
||||
b.id = FBActiveSpellIDs[i];
|
||||
if (FBDropDownButtonIcon[i]) then
|
||||
b.icon:SetTexture(FBDropDownButtonIcon[i]);
|
||||
else
|
||||
b.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark");
|
||||
end
|
||||
if (rightOn) then
|
||||
b.spellNameR = FBDropDownButtonR[i];
|
||||
b.idR = FBActiveSpellIDsR[i];
|
||||
else
|
||||
b.spellNameR = nil;
|
||||
b.idR = nil;
|
||||
end
|
||||
if (b.subIcon) then
|
||||
if (b.spellNameR and FBDropDownButtonIconR[i]) then
|
||||
b.subIcon:SetTexture(FBDropDownButtonIconR[i]);
|
||||
b.subIcon:Show();
|
||||
else
|
||||
b.subIcon:Hide();
|
||||
end
|
||||
end
|
||||
b.cdStart = nil;
|
||||
b.colorState = nil;
|
||||
if (b.spellName) then b.spellBase = FBPredict_SplitCast(b.spellName); else b.spellBase = nil; end
|
||||
if (b.spellNameR) then b.spellBaseR = FBPredict_SplitCast(b.spellNameR); else b.spellBaseR = nil; end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1243,6 +1210,9 @@ end
|
||||
-- Die Taktdauer ist entsprechend kuerzer, der volle Durchlauf dauert also
|
||||
-- weiterhin FBRAID_TICK Sekunden. force = true macht alles auf einmal.
|
||||
FBRaidTickSlice = 0;
|
||||
-- Fehlerzaehler je Scheibe: Ein Fehler, der nur in einer Scheibe steckt,
|
||||
-- wuerde sonst von den gelingenden anderen immer wieder zurueckgesetzt.
|
||||
FBRaidSweepKey = {};
|
||||
|
||||
-- Der Durchlauf laeuft geschuetzt, aber nur einmal je Tick statt einmal je
|
||||
-- Zelle: im Vierzigerraid ein pcall alle 0,125 Sekunden statt achtzig je
|
||||
@@ -1252,30 +1222,26 @@ function FBRaid_Tick(force)
|
||||
if (not FBRaid_IsActive()) then return; end
|
||||
local slice = FBRaidTickSlice;
|
||||
FBRaidTickSlice = math.mod(FBRaidTickSlice + 1, FBRAID_TICK_SLICES);
|
||||
if (not pcall(FBRaid_TickSweep, slice, force)) then
|
||||
if (FBHealBox_ApiFailed) then FBHealBox_ApiFailed(); end
|
||||
end
|
||||
local ok, err = pcall(FBRaid_TickSweep, slice, force);
|
||||
local key = FBRaidSweepKey[slice];
|
||||
if (not key) then key = "FBRaid_TickSweep "..slice; FBRaidSweepKey[slice] = key; end
|
||||
FBHealBox_SweepResult(key, ok, err);
|
||||
end
|
||||
|
||||
function FBRaid_TickSweep(slice, force)
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) and (force or (math.mod(g - 1, FBRAID_TICK_SLICES) == slice)) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c and c.unit and c:IsShown()) then
|
||||
local faded = false;
|
||||
if (HealBox.RangeFade == 1) then faded = (not FBRaid_InRange(c)); end
|
||||
if (force or c.rangeFaded ~= faded) then
|
||||
c.rangeFaded = faded;
|
||||
if (faded) then c:SetAlpha(FBRANGE_ALPHA); else c:SetAlpha(1); end
|
||||
end
|
||||
local blocked = false;
|
||||
if (HealBox.LOSIcon == 1) then blocked = FBRaid_LOSBlocked(c); end
|
||||
if (force or c.losBlocked ~= blocked) then
|
||||
c.losBlocked = blocked;
|
||||
if (blocked) then c.LOSIcon:Show(); else c.LOSIcon:Hide(); end
|
||||
end
|
||||
end
|
||||
for _, c in ipairs(FBRaidActiveCells) do
|
||||
if (force or (math.mod(c.group - 1, FBRAID_TICK_SLICES) == slice)) and c:IsShown() then
|
||||
local faded = false;
|
||||
if (HealBox.RangeFade == 1) then faded = (not FBRaid_InRange(c)); end
|
||||
if (force or c.rangeFaded ~= faded) then
|
||||
c.rangeFaded = faded;
|
||||
if (faded) then c:SetAlpha(FBRANGE_ALPHA); else c:SetAlpha(1); end
|
||||
end
|
||||
local blocked = false;
|
||||
if (HealBox.LOSIcon == 1) then blocked = FBRaid_LOSBlocked(c); end
|
||||
if (force or c.losBlocked ~= blocked) then
|
||||
c.losBlocked = blocked;
|
||||
if (blocked) then c.LOSIcon:Show(); else c.LOSIcon:Hide(); end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1295,6 +1261,8 @@ FBRaidEventFrame:RegisterEvent("UNIT_MANA");
|
||||
FBRaidEventFrame:RegisterEvent("UNIT_MAXMANA");
|
||||
FBRaidEventFrame:RegisterEvent("UNIT_DISPLAYPOWER");
|
||||
FBRaidEventFrame:RegisterEvent("UNIT_AURA");
|
||||
-- Wut, Energie und Fokus (nur mit "Wut, Energie, Fokus zeigen" ausgewertet)
|
||||
for ev in pairs(FBPowerEvents) do FBRaidEventFrame:RegisterEvent(ev); end
|
||||
|
||||
FBRaidRosterDirty = false;
|
||||
|
||||
@@ -1307,8 +1275,14 @@ FBRaidEventFrame:SetScript("OnEvent", function()
|
||||
return;
|
||||
end
|
||||
if (FBRaidTestMode > 0) then return; end
|
||||
if (FBPowerEvents[event] and HealBox.PowerBar ~= 1) then return; end
|
||||
local c = FBRaidUnitCell[arg1];
|
||||
if (not c) then return; end
|
||||
-- Mana (und Wut, Energie, Fokus): nur der Streifen, nicht die ganze Zelle
|
||||
if (event == "UNIT_MANA" or event == "UNIT_MAXMANA" or FBPowerEvents[event]) then
|
||||
FBRaid_UpdateCellManaOnly(c);
|
||||
return;
|
||||
end
|
||||
FBRaid_UpdateCell(c, (event == "UNIT_AURA"));
|
||||
if (event == "UNIT_AURA") then FBRaid_UpdateBuffBorder(c); end
|
||||
end);
|
||||
@@ -1387,45 +1361,12 @@ end
|
||||
|
||||
FBRaidSliders = {}; -- key -> Slider (fuer Beschriftung und Sync)
|
||||
|
||||
function FBRaid_SliderText(slider)
|
||||
if (not slider or not slider.Text) then return; end
|
||||
local v = slider:GetValue();
|
||||
local shown;
|
||||
if (slider.decimals) then shown = format("%.1f", v); else shown = tostring(math.floor(v + 0.5)); end
|
||||
slider.Text:SetText(format(FBT(slider.labelKey), shown));
|
||||
end
|
||||
|
||||
function FBRaid_CreateSlider(name, parent, x, y, labelKey, cfgKey, minV, maxV, step, decimals, onChange)
|
||||
local s = CreateFrame("Slider", name, parent, "OptionsSliderTemplate");
|
||||
s:SetWidth(128);
|
||||
s:SetHeight(16);
|
||||
s:SetPoint("TOPLEFT", x, y);
|
||||
s:SetMinMaxValues(minV, maxV);
|
||||
s:SetValueStep(step);
|
||||
s.labelKey = labelKey;
|
||||
s.cfgKey = cfgKey;
|
||||
s.decimals = decimals;
|
||||
s.Text = s:CreateFontString(nil, "BACKGROUND", "GameFontNormal");
|
||||
s.Text:SetPoint("CENTER", 0, 15);
|
||||
getglobal(name.."Low"):SetText(tostring(minV));
|
||||
getglobal(name.."High"):SetText(tostring(maxV));
|
||||
s:SetValue(FBRaid_Cfg()[cfgKey] or minV);
|
||||
FBRaid_SliderText(s);
|
||||
s:SetScript("OnValueChanged", function()
|
||||
local v = s:GetValue();
|
||||
if (not s.decimals) then v = math.floor(v + 0.5); end
|
||||
FBRaid_Cfg()[s.cfgKey] = v;
|
||||
FBRaid_SliderText(s);
|
||||
if (onChange) then onChange(); end
|
||||
end);
|
||||
FBRaidSliders[cfgKey] = s;
|
||||
return s;
|
||||
end
|
||||
-- Regler baut der Kern (FBHealBox_CreateSlider); bis 1.4.6 stand hier eine
|
||||
-- fast gleiche Kopie davon, ebenso im Mana-Ticker.
|
||||
|
||||
function FBRaid_BuildOptions()
|
||||
local tab = FBHealBox_AddOptionsTab("TAB_RAID");
|
||||
if (not tab) then return; end
|
||||
FBRaidOptionsTab = tab;
|
||||
local y = FBOPT_CONTENT_Y - 8;
|
||||
|
||||
FBRaidEnabledCheck = FBHealBox_CreateCheck("FBHealBoxRaidEnabledCheck", tab, 40, y, "RAID_ENABLED", "RAID_ENABLED_TIP", function()
|
||||
@@ -1518,16 +1459,16 @@ function FBRaid_BuildOptions()
|
||||
|
||||
-- Schieberegler (Beschriftung sitzt ueber dem Regler)
|
||||
local sy = y - 180;
|
||||
FBRaid_CreateSlider("FBRaidGroupsPerRowSlider", tab, 75, sy, "RAID_GROUPSPERROW", "GroupsPerRow", 1, 8, 1, false, FBRaid_LayoutAll);
|
||||
FBRaid_CreateSlider("FBRaidScaleSlider", tab, 260, sy, "RAID_SCALE", "Scale", 0.5, 1.5, 0.1, true, FBRaid_LayoutAll);
|
||||
FBRaid_CreateSlider("FBRaidCellWSlider", tab, 75, sy - 50, "RAID_CELLW", "CellW", 50, 120, 1, false, FBRaid_LayoutAll);
|
||||
FBRaid_CreateSlider("FBRaidCellHSlider", tab, 260, sy - 50, "RAID_CELLH", "CellH", 14, 32, 1, false, FBRaid_LayoutAll);
|
||||
FBRaid_CreateSlider("FBRaidButtonsSlider", tab, 75, sy - 100, "RAID_BUTTONS", "Buttons", 0, FBRAID_MAX_BUTTONS, 1, false, FBRaid_LayoutAll);
|
||||
FBRaid_CreateSlider("FBRaidBtnSizeSlider", tab, 260, sy - 100, "RAID_BTNSIZE", "ButtonSize", 12, 28, 1, false, FBRaid_LayoutAll);
|
||||
FBRaid_CreateSlider("FBRaidCellGapSlider", tab, 75, sy - 150, "RAID_CELLGAP", "CellGap", 0, 10, 1, false, FBRaid_LayoutAll);
|
||||
FBRaid_CreateSlider("FBRaidGroupGapSlider", tab, 260, sy - 150, "RAID_GROUPGAP", "GroupGap", 0, 20, 1, false, FBRaid_LayoutAll);
|
||||
FBHealBox_CreateSlider("FBRaidGroupsPerRowSlider", tab, 75, sy, "RAID_GROUPSPERROW", FBRaid_Cfg, "GroupsPerRow", 1, 8, 1, false, FBRaid_LayoutAll, FBRaidSliders);
|
||||
FBHealBox_CreateSlider("FBRaidScaleSlider", tab, 260, sy, "RAID_SCALE", FBRaid_Cfg, "Scale", 0.5, 1.5, 0.1, true, FBRaid_LayoutAll, FBRaidSliders);
|
||||
FBHealBox_CreateSlider("FBRaidCellWSlider", tab, 75, sy - 50, "RAID_CELLW", FBRaid_Cfg, "CellW", 50, 120, 1, false, FBRaid_LayoutAll, FBRaidSliders);
|
||||
FBHealBox_CreateSlider("FBRaidCellHSlider", tab, 260, sy - 50, "RAID_CELLH", FBRaid_Cfg, "CellH", 14, 32, 1, false, FBRaid_LayoutAll, FBRaidSliders);
|
||||
FBHealBox_CreateSlider("FBRaidButtonsSlider", tab, 75, sy - 100, "RAID_BUTTONS", FBRaid_Cfg, "Buttons", 0, FBRAID_MAX_BUTTONS, 1, false, FBRaid_LayoutAll, FBRaidSliders);
|
||||
FBHealBox_CreateSlider("FBRaidBtnSizeSlider", tab, 260, sy - 100, "RAID_BTNSIZE", FBRaid_Cfg, "ButtonSize", 12, 28, 1, false, FBRaid_LayoutAll, FBRaidSliders);
|
||||
FBHealBox_CreateSlider("FBRaidCellGapSlider", tab, 75, sy - 150, "RAID_CELLGAP", FBRaid_Cfg, "CellGap", 0, 10, 1, false, FBRaid_LayoutAll, FBRaidSliders);
|
||||
FBHealBox_CreateSlider("FBRaidGroupGapSlider", tab, 260, sy - 150, "RAID_GROUPGAP", FBRaid_Cfg, "GroupGap", 0, 20, 1, false, FBRaid_LayoutAll, FBRaidSliders);
|
||||
-- Schwelle: ab wie vielen Mitgliedern die Raid-Ansicht uebernimmt
|
||||
FBRaid_CreateSlider("FBRaidMinPlayersSlider", tab, 75, sy - 200, "RAID_MINPLAYERS", "MinPlayers", 2, 40, 1, false, function() FBUpdateNames(); end);
|
||||
FBHealBox_CreateSlider("FBRaidMinPlayersSlider", tab, 75, sy - 200, "RAID_MINPLAYERS", FBRaid_Cfg, "MinPlayers", 2, 40, 1, false, function() FBUpdateNames(); end, FBRaidSliders);
|
||||
|
||||
-- Hinweis zu den Buttons
|
||||
FBRaidInfoText = tab:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall");
|
||||
@@ -1565,7 +1506,7 @@ function FBRaid_ApplyLocale()
|
||||
if (FBRaidTitleCheck) then FBRaidTitleCheck.Text:SetText(FBT("RAID_SHOWTITLE")); FBRaidTitleCheck.tooltipText = FBT("RAID_SHOWTITLE_TIP"); end
|
||||
if (FBRaidBuffIconsCheck) then FBRaidBuffIconsCheck.Text:SetText(FBT("RAID_BUFFICONS")); FBRaidBuffIconsCheck.tooltipText = FBT("RAID_BUFFICONS_TIP"); end
|
||||
if (FBRaidInfoText) then FBRaidInfoText:SetText(FBT("RAID_INFO")); end
|
||||
for _, s in pairs(FBRaidSliders) do FBRaid_SliderText(s); end
|
||||
for _, s in pairs(FBRaidSliders) do FBHealBox_SliderText(s); end
|
||||
FBRaid_UpdateHPTextLabel();
|
||||
FBRaid_UpdateTestLabel();
|
||||
if (FBRaidFrame and FBRaidFrame.Title) then FBRaidFrame.Title.text:SetText(FBT("RAID_TITLE").." ("..FBRaidMembers..")"); end
|
||||
@@ -1603,17 +1544,13 @@ FBHealBox_RegisterHook("ActiveToggle", function()
|
||||
return true;
|
||||
end);
|
||||
-- Nur die Zellen anfassen, deren Einheit sich geaendert hat. Der Kern
|
||||
-- schickt die Namensliste mit; eine Zelle, die nicht drinsteht, kostet
|
||||
-- einen Tabellenzugriff statt einer vollen Aktualisierung.
|
||||
-- schickt die Namensliste mit, die Zelle kommt direkt aus FBRaidNameCell:
|
||||
-- Bis 1.4.6 wurden dafuer alle vierzig Zellen abgesucht.
|
||||
FBHealBox_RegisterHook("RefreshNames", function(names)
|
||||
if (not FBRaid_IsActive()) or (not names) then return true; end
|
||||
for g = 1, FBRAID_GROUPS do
|
||||
if (FBRaidCells[g]) then
|
||||
for pos = 1, FBRAID_PER_GROUP do
|
||||
local c = FBRaidCells[g][pos];
|
||||
if (c and c.unit and c.name and names[c.name]) then FBRaid_UpdateCell(c); end
|
||||
end
|
||||
end
|
||||
for name in pairs(names) do
|
||||
local c = FBRaidNameCell[name];
|
||||
if (c) then FBRaid_UpdateCell(c); end
|
||||
end
|
||||
return true;
|
||||
end);
|
||||
@@ -1629,8 +1566,15 @@ end);
|
||||
FBHealBox_RegisterHook("Aggro", function(tt) return FBRaid_CheckAggro(tt); end);
|
||||
FBHealBox_RegisterHook("SpellTimers", function(now) FBRaid_UpdateSpellTimers(now); return true; end);
|
||||
FBHealBox_RegisterHook("Cooldowns", function() FBRaid_UpdateCooldowns(); return true; end);
|
||||
FBHealBox_RegisterHook("ButtonStates", function(ev) FBRaid_UpdateButtonStates(ev); return true; end);
|
||||
FBHealBox_RegisterHook("BuffIcons", function() FBRaid_UpdateBuffIcons(); return true; end);
|
||||
FBHealBox_RegisterHook("ButtonStates", function(ev) FBRaid_ButtonStates(ev); return true; end);
|
||||
FBHealBox_RegisterHook("BuffIcons", function()
|
||||
-- Der Schalter "Buff-Icons" des Kerns aendert die Breite des Streifens
|
||||
-- links der Zellen. Bis 1.4.6 rueckte das Raster erst beim naechsten
|
||||
-- Rosterwechsel nach.
|
||||
if (FBRaidLaidStrip and FBRaid_BuffStrip(FBRaid_Cfg()) ~= FBRaidLaidStrip) then FBRaid_LayoutAll(); end
|
||||
FBRaid_UpdateBuffIcons();
|
||||
return true;
|
||||
end);
|
||||
FBHealBox_RegisterHook("Status", function()
|
||||
local cfg = FBRaid_Cfg();
|
||||
local state = FBT("FBP_STATE_OFF");
|
||||
@@ -1643,7 +1587,8 @@ FBHealBox_RegisterHook("Slash", function(msg)
|
||||
if (msg == "raid") then
|
||||
local cfg = FBRaid_Cfg();
|
||||
if (cfg.Enabled == 1) then cfg.Enabled = 0; else cfg.Enabled = 1; end
|
||||
if (cfg.Enabled == 0 and FBRaidTestMode > 0) then FBRaidTestMode = 0; end
|
||||
-- wie der Schalter im Reiter: SetTest haelt auch die Atmung der Geister an
|
||||
if (cfg.Enabled == 0 and FBRaidTestMode > 0) then FBRaid_SetTest(0); end
|
||||
FBRaid_SyncOptions();
|
||||
FBUpdateNames();
|
||||
return true;
|
||||
|
||||
+18
-50
@@ -46,7 +46,6 @@ FBTickerDefaults = {
|
||||
-- [ Texte ]
|
||||
-- ==========================================================================
|
||||
|
||||
FBLocale["enUS"].TAB_TICKER = "Extras";
|
||||
FBLocale["enUS"].TICK_HEADER = "Mana ticker";
|
||||
FBLocale["enUS"].TICK_ENABLED = "Mana ticker";
|
||||
FBLocale["enUS"].TICK_ENABLED_TIP = "A spark travels across your own mana bar every 2 seconds, in step with the server's mana regeneration tick. Cast right after the spark reaches the end and you lose no regeneration. Needs the mana bar to be on.";
|
||||
@@ -60,11 +59,10 @@ FBLocale["enUS"].TICK_STATUS = "Ticker: %s, next tick in %.1f s%s";
|
||||
FBLocale["enUS"].TICK_SYNCED = "synced";
|
||||
FBLocale["enUS"].TICK_UNSYNCED = "waiting for first tick";
|
||||
FBLocale["enUS"].TICK_STATUS_FSR = ", five-second rule %.1f s";
|
||||
FBLocale["enUS"].TICK_LOADED = "Mana ticker module loaded: tab |cFFFFFFFFTicker|r in the options, /fbp ticker";
|
||||
FBLocale["enUS"].TICK_LOADED = "Mana ticker module loaded: section in tab |cFFFFFFFFExtras|r, /fbp ticker";
|
||||
FBLocale["enUS"].TICK_ON = "Mana ticker |cFF00FF00on|r.";
|
||||
FBLocale["enUS"].TICK_OFF = "Mana ticker |cFFFF0000off|r.";
|
||||
|
||||
FBLocale["deDE"].TAB_TICKER = "Extras";
|
||||
FBLocale["deDE"].TICK_HEADER = "Mana-Ticker";
|
||||
FBLocale["deDE"].TICK_ENABLED = "Mana-Ticker";
|
||||
FBLocale["deDE"].TICK_ENABLED_TIP = "Ein Funke wandert alle 2 Sekunden ueber deinen eigenen Manastreifen, im Takt des Regenerationsticks des Servers. Wer direkt nach dem Funken am Ende castet, verliert keine Regeneration. Braucht den eingeschalteten Manabalken.";
|
||||
@@ -75,7 +73,6 @@ FBLocale["deDE"].TICK_OFFSET = "Tick-Vorlauf: |cFFFFFFFF%s s";
|
||||
|
||||
-- Weitere Sprachen (Spanisch, Franzoesisch, Italienisch)
|
||||
|
||||
FBLocale["esES"].TAB_TICKER = "Extras";
|
||||
FBLocale["esES"].TICK_HEADER = "Ticker de maná";
|
||||
FBLocale["esES"].TICK_ENABLED = "Ticker de maná";
|
||||
FBLocale["esES"].TICK_ENABLED_TIP = "Una chispa recorre tu propia barra de maná cada 2 segundos, al compás del pulso de regeneración de maná del servidor. Lanza justo después de que la chispa llegue al final y no perderás regeneración. Requiere la barra de maná activada.";
|
||||
@@ -93,7 +90,6 @@ FBLocale["esES"].TICK_LOADED = "Módulo de ticker de maná cargado: pesta
|
||||
FBLocale["esES"].TICK_ON = "Ticker de maná |cFF00FF00activado|r.";
|
||||
FBLocale["esES"].TICK_OFF = "Ticker de maná |cFFFF0000desactivado|r.";
|
||||
|
||||
FBLocale["frFR"].TAB_TICKER = "Extras";
|
||||
FBLocale["frFR"].TICK_HEADER = "Ticker de mana";
|
||||
FBLocale["frFR"].TICK_ENABLED = "Ticker de mana";
|
||||
FBLocale["frFR"].TICK_ENABLED_TIP = "Une étincelle parcourt votre propre barre de mana toutes les 2 secondes, au rythme du tick de régénération de mana du serveur. Lancez juste après que l'étincelle atteint la fin et vous ne perdez aucune régénération. Nécessite la barre de mana activée.";
|
||||
@@ -111,7 +107,6 @@ FBLocale["frFR"].TICK_LOADED = "Module ticker de mana chargé : onglet |cF
|
||||
FBLocale["frFR"].TICK_ON = "Ticker de mana |cFF00FF00activé|r.";
|
||||
FBLocale["frFR"].TICK_OFF = "Ticker de mana |cFFFF0000désactivé|r.";
|
||||
|
||||
FBLocale["itIT"].TAB_TICKER = "Extra";
|
||||
FBLocale["itIT"].TICK_HEADER = "Ticker del mana";
|
||||
FBLocale["itIT"].TICK_ENABLED = "Ticker del mana";
|
||||
FBLocale["itIT"].TICK_ENABLED_TIP = "Una scintilla attraversa la tua barra del mana ogni 2 secondi, a tempo con il tick di rigenerazione del mana del server. Lancia subito dopo che la scintilla arriva in fondo e non perdi rigenerazione. Richiede la barra del mana attiva.";
|
||||
@@ -134,7 +129,7 @@ FBLocale["deDE"].TICK_STATUS = "Ticker: %s, naechster Tick in %.1f s%s";
|
||||
FBLocale["deDE"].TICK_SYNCED = "synchron";
|
||||
FBLocale["deDE"].TICK_UNSYNCED = "wartet auf ersten Tick";
|
||||
FBLocale["deDE"].TICK_STATUS_FSR = ", Fuenf-Sekunden-Regel %.1f s";
|
||||
FBLocale["deDE"].TICK_LOADED = "Mana-Ticker-Modul geladen: Reiter |cFFFFFFFFTicker|r in den Optionen, /fbp ticker";
|
||||
FBLocale["deDE"].TICK_LOADED = "Mana-Ticker-Modul geladen: Abschnitt im Reiter |cFFFFFFFFExtras|r, /fbp ticker";
|
||||
FBLocale["deDE"].TICK_ON = "Mana-Ticker |cFF00FF00an|r.";
|
||||
FBLocale["deDE"].TICK_OFF = "Mana-Ticker |cFFFF0000aus|r.";
|
||||
|
||||
@@ -452,53 +447,22 @@ FBTickerFrame:SetScript("OnUpdate", function()
|
||||
end);
|
||||
|
||||
-- ==========================================================================
|
||||
-- [ Options-Reiter "Ticker" ]
|
||||
-- [ Abschnitt im Reiter "Extras" ]
|
||||
--
|
||||
-- Den Reiter verwaltet der Kern (FBHealBox_ExtrasSection); er wird mit
|
||||
-- Smart Damage geteilt, jedes Modul funktioniert aber auch allein.
|
||||
-- ==========================================================================
|
||||
|
||||
FBTickerSliders = {};
|
||||
|
||||
function FBTicker_SliderText(s)
|
||||
if (not s or not s.Text) then return; end
|
||||
local v = s:GetValue();
|
||||
local shown;
|
||||
if (s.decimals) then shown = format("%.1f", v); else shown = tostring(math.floor(v + 0.5)); end
|
||||
s.Text:SetText(format(FBT(s.labelKey), shown));
|
||||
end
|
||||
|
||||
function FBTicker_CreateSlider(name, parent, x, y, labelKey, cfgKey, minV, maxV, step, decimals)
|
||||
local s = CreateFrame("Slider", name, parent, "OptionsSliderTemplate");
|
||||
s:SetWidth(128);
|
||||
s:SetHeight(16);
|
||||
s:SetPoint("TOPLEFT", x, y);
|
||||
s:SetMinMaxValues(minV, maxV);
|
||||
s:SetValueStep(step);
|
||||
s.labelKey = labelKey;
|
||||
s.cfgKey = cfgKey;
|
||||
s.decimals = decimals;
|
||||
s.Text = s:CreateFontString(nil, "BACKGROUND", "GameFontNormal");
|
||||
s.Text:SetPoint("CENTER", 0, 15);
|
||||
getglobal(name.."Low"):SetText(tostring(minV));
|
||||
getglobal(name.."High"):SetText(tostring(maxV));
|
||||
s:SetValue(FBTicker_Cfg()[cfgKey] or minV);
|
||||
FBTicker_SliderText(s);
|
||||
s:SetScript("OnValueChanged", function()
|
||||
local v = s:GetValue();
|
||||
if (s.decimals) then v = math.floor(v * 10 + 0.5) / 10; else v = math.floor(v + 0.5); end
|
||||
FBTicker_Cfg()[s.cfgKey] = v;
|
||||
FBTicker_SliderText(s);
|
||||
end);
|
||||
FBTickerSliders[cfgKey] = s;
|
||||
return s;
|
||||
end
|
||||
FBTICK_SECTION_H = 232; -- px, Hoehe des Abschnitts
|
||||
|
||||
function FBTicker_BuildOptions()
|
||||
local tab = FBHealBox_AddOptionsTab("TAB_TICKER");
|
||||
local tab, top = FBHealBox_ExtrasSection(FBTICK_SECTION_H);
|
||||
if (not tab) then return; end
|
||||
-- Abschnittskopf: der Reiter "Extras" wird mit Smart Damage geteilt
|
||||
FBTickerHeader = tab:CreateFontString(nil, "OVERLAY", "GameFontNormal");
|
||||
FBTickerHeader:SetPoint("TOPLEFT", tab, "TOPLEFT", 35, FBOPT_CONTENT_Y);
|
||||
FBTickerHeader:SetPoint("TOPLEFT", tab, "TOPLEFT", 35, top);
|
||||
FBTickerHeader:SetText(FBT("TICK_HEADER"));
|
||||
local y = FBOPT_CONTENT_Y - 26;
|
||||
local y = top - 26;
|
||||
|
||||
FBTickerEnabledCheck = FBHealBox_CreateCheck("FBHealBoxTickerEnabledCheck", tab, 40, y, "TICK_ENABLED", "TICK_ENABLED_TIP", function()
|
||||
FBTicker_Cfg().Enabled = FBTickerEnabledCheck:GetChecked() and 1 or 0;
|
||||
@@ -511,9 +475,9 @@ function FBTicker_BuildOptions()
|
||||
end);
|
||||
|
||||
local sy = y - 60;
|
||||
FBTicker_CreateSlider("FBTickerToleranceSlider", tab, 75, sy, "TICK_TOLERANCE", "Tolerance", 0.1, 0.6, 0.1, true);
|
||||
FBTicker_CreateSlider("FBTickerOffsetSlider", tab, 260, sy, "TICK_OFFSET", "Offset", 0.0, 0.5, 0.1, true);
|
||||
FBTicker_CreateSlider("FBTickerSparkWSlider", tab, 75, sy - 46, "TICK_SPARKW", "SparkW", 1, 4, 1, false);
|
||||
FBHealBox_CreateSlider("FBTickerToleranceSlider", tab, 75, sy, "TICK_TOLERANCE", FBTicker_Cfg, "Tolerance", 0.1, 0.6, 0.1, true, nil, FBTickerSliders);
|
||||
FBHealBox_CreateSlider("FBTickerOffsetSlider", tab, 260, sy, "TICK_OFFSET", FBTicker_Cfg, "Offset", 0.0, 0.5, 0.1, true, nil, FBTickerSliders);
|
||||
FBHealBox_CreateSlider("FBTickerSparkWSlider", tab, 75, sy - 46, "TICK_SPARKW", FBTicker_Cfg, "SparkW", 1, 4, 1, false, nil, FBTickerSliders);
|
||||
|
||||
FBTickerInfoText = tab:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall");
|
||||
FBTickerInfoText:SetPoint("TOPLEFT", tab, "TOPLEFT", 35, sy - 84);
|
||||
@@ -539,7 +503,7 @@ function FBTicker_ApplyLocale()
|
||||
if (FBTickerEnabledCheck) then FBTickerEnabledCheck.Text:SetText(FBT("TICK_ENABLED")); FBTickerEnabledCheck.tooltipText = FBT("TICK_ENABLED_TIP"); end
|
||||
if (FBTickerFSRCheck) then FBTickerFSRCheck.Text:SetText(FBT("TICK_FSR")); FBTickerFSRCheck.tooltipText = FBT("TICK_FSR_TIP"); end
|
||||
if (FBTickerInfoText) then FBTickerInfoText:SetText(FBT("TICK_INFO")); end
|
||||
for _, s in pairs(FBTickerSliders) do FBTicker_SliderText(s); end
|
||||
for _, s in pairs(FBTickerSliders) do FBHealBox_SliderText(s); end
|
||||
return true;
|
||||
end
|
||||
|
||||
@@ -562,6 +526,10 @@ FBHealBox_RegisterHook("Defaults", function() return FBTicker_ApplyDefaults(); e
|
||||
FBHealBox_RegisterHook("SyncOptions", function() return FBTicker_SyncOptions(); end);
|
||||
FBHealBox_RegisterHook("ApplyLocale", function() return FBTicker_ApplyLocale(); end);
|
||||
FBHealBox_RegisterHook("UpdateNames", function() FBTicker_CollectBars(); FBTicker_UpdateGate(); return true; end);
|
||||
-- Das Raidraster baut auch ohne "UpdateNames" um (reines RAID_ROSTER_UPDATE,
|
||||
-- etwa beim Ueberschreiten der Schwelle). Ohne diesen Hook fehlte der Funke
|
||||
-- dann oder lief auf der Zelle eines anderen Spielers.
|
||||
FBHealBox_RegisterHook("RaidRoster", function() FBTicker_CollectBars(); FBTicker_UpdateGate(); return true; end);
|
||||
FBHealBox_RegisterHook("ActiveToggle", function() FBTicker_UpdateGate(); FBTicker_Draw(); return true; end);
|
||||
FBHealBox_RegisterHook("Status", function()
|
||||
local state = FBT("TICK_UNSYNCED");
|
||||
|
||||
Reference in New Issue
Block a user