File Details
EpicDamageMeter v.2.4.15
- R
- May 23, 2026
- 431.84 KB
- 560
- 12.0.7+14
- Classic TBC + 4
File Name
EpicDamageMeter.zip
Supported Versions
- 12.0.7
- 12.0.5
- 12.0.1
- 5.5.4
- 5.5.3
- 4.4.2
- 4.4.1
- 3.80.1
- 3.80.0
- 3.4.5
- 3.4.4
- 2.5.5
- 2.5.4
- 1.15.8
- 1.15.7
EpicDamageMeter - Changelog
============================
Version 2.4.15
--------------
Light-Mode Fix + ESC-Menu Button + Arena Theme
LIGHT MODE
- Fixed: section headers were unreadable in light mode — the dark
accent-tinted gradient overlay I added in 2.4.13 dominated the
card colour and inverted the page (light bg + dark headers with
dark text). Now adapts per theme:
light → very subtle accent-tint that fades to zero
dark → keeps the moody accent depth gradient
- Text outline + shadow disabled in light mode (was creating a
black halo around dark text on light bg).
ESC MENU BUTTON
- The in-game ESC menu now has an "Epic DM" entry, the same way
SUI and Arena Core surface their settings. Tries the modern
Menu.ModifyMenu API first (Midnight 12.0 dropdown menu) and
falls back to a GameMenuButtonTemplate button on older clients.
Clicking it opens the EDM settings panel and dismisses the
game menu.
ARENA THEME (NEW)
- New "arena" theme variant, inspired by Arena Core's deep purple
aesthetic. Cycle with the sun/moon button: dark → light → arena
→ dark. While in arena mode the icon tints purple to signal the
third state.
- Palette: near-black panels, saturated purple accent, yellow
hover on nav items (matches Arena Core's yellow glow on active
category).
- Section headers in arena mode get a thicker 2px purple border,
heavier wash gradient, and BOLD UPPERCASE titles in accent
purple instead of the standard text colour — the "section card"
feel from the reference.
Version 2.4.14
--------------
Tracker / Details Polish + Display Bug Fixes
TRACKER
- Title bar no longer duplicates the mode name. Previously the
title showed "Epic DM Verursachter Schaden" while the toolbar
button directly below also said "Verursachter Schaden" — visual
redundancy that pushed the brand off-screen on narrow windows.
Title is now just the brand (+ enemy indicator when active);
mode lives exclusively in the toolbar button.
DETAIL WINDOW
- Fixed: header pills still showed "0 DPS / 0 HPS" while spell rows
rendered correct per-second values. Root cause: the previous
fallback divided by the DB segment duration which is clamped to
1s after a segment is reset — producing absurd values OR being
short-circuited by a SecretValue rate that resolved to a tiny
non-zero number. Now reads `session.durationSeconds` from
C_DamageMeter (the duration the meter actually measured) as the
primary divisor, with a session-level fallback when the per-source
data doesn't carry it, and treats any rate <= 0 as "missing" so
the fallback always kicks in for the bad cases.
- Fixed: spell rows below 1000 DPS displayed raw IEEE-754 floats
("777.76580810547 DPS"). The Abbr helper short-circuited around
Utils.ResolveNumber for SecretValues and routed them through
Blizzard's AbbreviateNumbers, which doesn't round low values.
Both Abbr helpers in DetailWindow now go through ResolveNumber
first, then Utils.FormatNumber — guaranteed clean integers.
- Spell-row depth: the gloss / shadow overlays added in 2.4.10
weren't actually visible because they sat on the bar parent
while the StatusBar child rendered above them. Moved both to
bar.statusBar at OVERLAY layer so they paint on top of the
colored fill. Added a 2px right-edge highlight texture (hidden
by default, ready for show* code to position).
Version 2.4.13
--------------
Pill Look Goes System-Wide
TOOLBAR SPACING
- Fixed: in the meter toolbar, the mode label ("Verursachter Schaden"),
the Team/Enemy toggle ("Team"), and the segment label ("Aktuell")
visually fused into each other on long localised strings. Root
cause: mode button was a fixed 90px wide and the German label
overflows beyond that width, bleeding into the next button.
- Mode button now auto-fits its label width (clamped 60-220px) via
a new `Instance:ResizeModeBtn()` method that's called on init
and on every SetMode. Gaps between mode/enemy/divider/segment
bumped from 3-4px to 7-8px so labels stay visually separate.
PILL DESIGN — REUSABLE WIDGETS
- Extracted the Detail Window header pill into
EDM.Widgets:CreateStatPill(parent, opts) so the same dark-card +
top thin / bottom thick / left vertical accent stripes + accent-
tinted depth gradient style can be reused across the addon.
Returns a frame with :SetValue(value, sub, isZero) for live updates.
- Added EDM.Widgets:CreateSectionBar(parent, opts) — a wider
horizontal sibling for section headers (single-line title + meta).
Same accent palette, same lit-from-top feel.
SETTINGS PANEL
- Settings section headers (Config:CreateSection) adopt the pill
look: dark backdrop, horizontal accent-tinted depth gradient,
top + bottom + left-vertical accent stripes in the theme's
ACCENT colour. Section title outlined for better legibility on
the new gradient bg, chevron is now accent-coloured.
- Hover state intensifies all three accent stripes plus the border
rather than just dimming the bg — clear visual feedback that the
section is interactive/collapsible.
Version 2.4.12
--------------
Detail Window Pass 2 — Pills, Targets, DPS
PILLS
- Split the confusing "INT / DSP" combo pill into two separate pills:
"INTERRUPTS" and "DISPELS". User feedback was that "INT / DSP"
read like a DPS abbreviation. Each pill now has its own label,
accent colour, and dim-when-zero state.
- Added a second (thicker) bottom accent stripe and a subtle
accent-tinted depth gradient on each pill. Active pills feel
more "lit" while zero-valued pills clearly recede.
- Default window grew from 460x560 to 520x580 so the new 6-pill
row doesn't truncate the "INTERRUPTS" label.
HEADER DPS / HPS FALLBACK
- Fixed: header pills showed "0 DPS" and "0 HPS" while the spell
rows showed correct DPS values (e.g. "Göttlicher Hammer 7.1K
DPS"). C_DamageMeter's amountPerSecond is sometimes nil / 0 /
SecretValue even when totalAmount is populated — happens on
Overall sessions, post-combat snapshots and expired sessions.
- Header now computes rate = total / duration as a fallback when
the session-provided rate is missing, so DPS/HPS stays in sync
with the spell rows.
TARGETS TAB
- Fixed: "Ziele" tab was empty on Retail because we removed CLEU
registration in 2.4.8 (12.0 moved combat events to EventRegistry
and forbade CLEU for addons). actor.targets had no data.
- Now inverts C_DamageMeter's EnemyDamageTaken view: each enemy
session has combatSources listing the players who damaged it.
Walking those and matching the actor's GUID gives "what targets
did THIS player damage, and for how much". SecretValue-safe
matching via pcall'd equality.
- Target rows now show "Damage DPS · X.X%" in the same compact
layout the spell rows use, plus the gold/silver/bronze rank
badge on the top 3 targets.
Version 2.4.11
--------------
Bug Fixes + Debug Console + Detail Window Polish
BAR TOOLTIP — STALE SPELL CACHE
- Fixed: bar tooltip on hover showed spells from the wrong player.
Repro: hovering Toilettegodx (Monk) in the Healing window showed
Warlock spells like Drain Soul / Dark Pact / Healthstone — those
were Méuw's (a Warlock who occupied that bar slot earlier).
- Root cause: bars are pooled and recycled across actors / modes /
segments. `bar._cachedSpells` (populated by UpdateBars for the
tooltip) had no invalidation key, so a bar that previously showed
Player A and was later reassigned to Player B kept serving A's
spells. The bug also surfaced when switching segments or modes on
the same window.
- Fix: every cache write now tags the bar with a composite key
(`actor.guid | mode | segmentIndex`). Both the cache-write paths
(UpdateBars and GetTooltipSpells lazy fetch) set the key, and
every cache read checks it. Mismatch → drop and re-fetch.
- Also fixed a second SecretValue arithmetic site at MainFrame.lua:
1938 (cache build during UpdateBars) — same `tonumber(secret)`
taint leak we fixed at line 2918 last release.
CRASH / TAINT
- Fixed: 14x "attempt to perform arithmetic on local 'amt' (a secret
number value)" at MainFrame.lua:2916 (GetTooltipSpells). The bar
tooltip's spell loop called `tonumber(sp.totalAmount)` which on a
SecretValue returns the still-secret value, then `spellTotal + amt`
blew up. Now uses Utils.ResolveNumber which handles SecretValues
via the byte-rebuild slow path.
- Fixed: Utils.ResolveNumber fast-path silently passed SecretValues
through. `tonumber(secret) > 0` doesn't throw and the comparison
reports ok, so the wrapper assumed the value was clean and returned
it. Subsequent arithmetic / format calls then leaked taint or
produced raw float strings. Added an explicit issecretvalue() check
before the fast path so SecretValues always take the byte-rebuild
route.
- Fixed: 6x "attempt to call a nil value" at DebugConsole.lua:671
when running `/mem`. Midnight 12.0 moved GetNumAddOns, GetAddOnInfo,
IsAddOnLoaded, GetAddOnMemoryUsage, UpdateAddOnMemoryUsage under
C_AddOns. The command now resolves through C_AddOns first and
falls back to the legacy globals where they still exist.
DETAIL WINDOW
- Fixed: spell row DPS showed raw floats like "687.46350097656 DPS"
for values below 1000. Root cause was the same ResolveNumber leak
above — perSecond is a SecretValue on Retail and slipped past
the rounding. The Utils.ResolveNumber fix resolves this generically,
and the row layout was rewritten:
* Value (top-right, big) : amount only, e.g. "41K"
* Detail (bottom-right) : "687 DPS · 26.1%" (rate + share)
* Subtext (bottom-left) : "5 hits · 2 crits (40%)"
Eye lands on the big number, then drops to the rate+share line.
- Header pills: zero-valued pills now dim themselves (value muted,
border faded, accent strip dimmed) so the eye skips empty stats.
- Removed redundant "I / D" sub-label under Int/Dsp pill — the
pill's main label already says "INT / DSP".
DEBUG CONSOLE
- Fixed: errors captured by the in-addon console showed up as
"Runtime: table: 0x..." with no actual message. BugGrabber-format
error objects use the field name `.msg` (not `.message` which the
old extractor expected). The extractor now probes multiple field
names — msg, message, error, errorMessage, text, what, desc,
reason — and falls back to serialising primitive table fields so
you always see something concrete instead of an opaque table id.
- Stack trace shown bumped from 3 to 6 lines (3 was too short to
see where the error actually came from).
- NEW console command: `/edm console` -> `last` (also `error last`)
dumps the full last captured error: message, full stack trace,
and the first 12 lines of locals. No more BugSack required for
basic debugging — though BugSack still works on top if installed.
--------------
Detail Window Redesign
- Reworked the Player Detail window UI top-to-bottom while keeping all
existing functionality, signatures and data flow intact.
HEADER (was: cramped text rows separated by pipes)
* Default window grew from 420×520 to 460×560 for breathing room.
* Larger class icon (54px, was 48), framed with class-tinted border.
* Big soft class-color halo glow behind the icon.
* Class-color top accent band runs across the entire header.
* Player name now in 16px outlined class color (was 13).
* Class subtitle line under the name (small, muted).
* "Dmg / DPS | Heal / HPS | Deaths | Interrupts | Dispels | Absorbs"
one-line text block REPLACED by a row of five stat PILLS:
DAMAGE - big total + small "X DPS" sub
HEALING - big total + small "X HPS" sub
ABSORBS - big total
DEATHS - big number (greys out when zero)
INT/DSP - combined interrupts/dispels as "12 / 3"
Each pill has its own colored top accent (red/green/gold/purple/blue).
* Pills flex-resize on window resize.
TABS (was: text-only with thin underline)
* Now a segmented control: 30px tall, gradient bg, top accent strip,
bottom indicator. Each tab carries its own type color (Damage red,
Healing green, Targets orange, Damage Taken crimson).
* Hover state subtly tints the bg toward the tab's accent.
* Active tab gets a stronger tinted gradient + full-color top accent
bar + bottom indicator line.
ABILITY BARS (was: flat red statusbar, tiny icon)
* Layered rendering: dark base + vertical depth gradient + status bar
(skin-aware texture) + top gloss highlight + bottom shadow.
* Slightly larger icon with 1px dark border (separates from bg).
* Spell name jumped from 10px to 11px outlined; value text bolder.
* Hits/crits sub-line now in its own field (was crammed in tiny text).
* Top 3 entries get a gold/silver/bronze rank badge on the icon.
* Subtle row divider for cleaner list rhythm.
All show* functions (ShowDamageAbilities, ShowHealingAbilities,
ShowTargets, ShowDamageTaken, ShowSpellList, ShowSpellTooltip,
ShowSpellDetail) and the live C_DamageMeter integration are unchanged.
Backward-compat shims keep self.header.stats1/stats2 callable as
no-ops in case any code path still touches them.
Version 2.4.9
-------------
Bug Fix
- Fixed: hovering a player bar during combat on Retail showed 0/0/0
in the tooltip; the right values only appeared after combat ended.
Root cause: UpdateBarsFromDamageMeter writes a zero-initialised
actor stub into bar.actorData (the bars get their width directly
from C_DamageMeter session values, the stub is for spell-cache
lazy loading). The tooltip read those zeros instead of asking
C_DamageMeter itself. After combat, OnCombatEnd imports session
totals back into the database actor, which is why post-combat
worked.
- Tooltip:ShowActorTooltip now queries C_DamageMeter live for the
hovered source's damage / healing / absorbs / damage-taken /
interrupts / dispels across multiple session enums, picking the
freshest available value and falling back to the database actor
only when live data is missing. Duration is taken from the
session itself so it matches what the bars are rendering.
- SecretValue-safe throughout: GUID/name comparisons go through a
pcalled equality wrapper, formatting routes secret numbers through
AbbreviateNumbers, division skipped entirely for secret damage.
Theme Pack + Animation Framework
- NEW: 8 new skins, expanding the catalogue from 23 -> 31. Each
one targets a stylistic gap the existing themes don't cover:
* Terminal — retro CRT phosphor green on near-black, monospace
font, scanline overlay, sharp edges. For DOS nostalgia.
* Sakura — soft rose pastel on dark wine background, gentle
gradients, cherry-blossom palette. Daytime / lighter mood.
* Bloodforge — Death Knight runic aesthetic, crimson on iron,
gothic Morpheus serif, runic accent borders.
* Vaporwave — Y2K sunset: magenta/cyan/violet on twilight grid.
Dreamy gradients, neon-with-soft-edges (NOT Cyberpunk's harsh
industrial; this is Lisa Frank / Macintosh Plus).
* Newsprint — anti-color skin. Cream paper, black ink, serif.
Class colors intentionally muted so typography does the
talking. For anyone tired of the class-color rainbow.
* Tactical — military HUD: amber on dark olive, monospace,
crosshair-style accents. Reads like a cockpit display.
* Brutalist — architecture-inspired heavy minimalism. Raw
concrete grays, oversized typography, 3px black borders,
yellow alert accents. Nothing soft, nothing decorated.
* Glitch — broken-LCD aesthetic with chromatic aberration.
Red shadow on cyan text, RGB-tinted edges. Pixel statusbar
texture. For when you want the UI to feel slightly wrong.
- NEW: Procedural statusbar palettes (Skins:CreateProceduralBar) —
Lua-generated gradients registered as LSM statusbars, no .tga
artwork needed. Ships with Sunset, Ocean, Toxic, Ember, Aurora
ready-made palettes for quick custom-theming.
- NEW: UI/Animations.lua module with reusable effects:
* A:Pulse(frame, opts) — breathing opacity loop
* A:Glow(frame, opts) — one-shot glow burst with scale
* A:CountUp(fs, from, to, opts) — number-tween FontString with
ease-out / linear / ease-in
* A:Shimmer(frame, opts) — light-band slides across (good
for #1 rank highlight)
* A:RecordFlash(frame, opts) — celebratory flash for new bests
* A:Shake(frame, opts) — damped oscillation for emphasis
* A:CancelAll(frame) — cleanup all anims on a frame
* A.FormatBig(v) — formats 1234567 -> "1.23M"
All self-cleaning: starting a new anim on the same frame cancels
the previous one to avoid stacking.
- NEW: Animations wired into Bars.lua. Each bar now reacts to its
data live:
* CountUp on the value FontString when DPS changes by ≥100
(deltas below that snap to avoid micro-tween churn)
* Glow burst in class color when the bar climbs a rank
* Continuous Shimmer band sliding across the #1 bar
* Gold RecordFlash the first time a bar takes #1 in the
current (actor, mode) — celebrates breaking through
Per-bar state tracking (peak value, last rank, shimmer flag,
ever-was-first flag) makes the triggers idempotent — they
don't refire on every refresh during a single rank streak.
Anim state is reset on bar recycling (ReleaseBar) and on theme
changes (ApplySettings) so nothing leaks between segments.
- NEW: Settings hooks bars.useAnimations (master toggle) and
bars.animOptOut = { CountUp = true, Glow = true, ... } for
per-anim opt-out. Default: all on. Defaults can be wired into
Config.lua's Bars tab in a follow-up.
Version 2.4.8
-------------
Retail (Midnight 12.0) — ADDON_ACTION_FORBIDDEN fix
- Root cause: Midnight 12.0 migrated combat / unit / roster
events from the legacy Frame:RegisterEvent API to the new
global EventRegistry (CallbackRegistryMixin). The legacy path
now fires ADDON_ACTION_FORBIDDEN for these events; only
lifecycle events (ADDON_LOADED, PLAYER_LOGIN) still work,
which is why AceAddon kept loading fine while combat tracking
stayed silently broken.
- Solution: register every restricted event through
EventRegistry:RegisterFrameEventAndCallback(event, fn, owner).
Callback signature is (ownerID, ...eventArgs) — no event-name
arg, which differs from the OnEvent script style. DAMAGE_METER_*
events are custom (not real frame events) so they use
EventRegistry:RegisterCallback instead.
- COMBAT_LOG_EVENT_UNFILTERED is NO LONGER registered on Retail —
Blizzard removed addon CLEU access entirely in 12.0. Damage
data flows through C_DamageMeter exclusively (the server-combat
ticker in OnEnable polls C_DamageMeter.GetCombatSessionFromType
each tick and UpdateFromDamageMeter renders from it).
- ENCOUNTER_STATE_CHANGED dropped — it is a custom callback on
EncounterJournal, not a real frame event. ENCOUNTER_START /
ENCOUNTER_END (real events, registered via EventRegistry) cover
the encounter-tracking need.
- TOC: bumped Interface 120001 -> 120005 and Version 2.4.3 -> 2.4.8.
- Applied to Core_Retail.lua (10 frame events + 3 C_DamageMeter
callbacks) and Parser_Retail.lua (6 frame events).
- OnDisable now unregisters via EventRegistry:UnregisterFrameEventAndCallback
and UnregisterCallback so a /reload doesn't double-register.
- Core:RegisterEvents() and Parser:RegisterEvents() are now
no-op stubs (kept for API compatibility).
Known follow-up: BroadcasterTools.lua and ArenaSummary.lua still
use legacy RegisterEvent for UNIT_SPELLCAST_*, COMBAT_LOG_EVENT_*,
PVP_MATCH_COMPLETE. Those features (Action Tracker, Event Tracker,
Arena Summary) will hit the same restriction when activated.
Migration to EventRegistry planned for next release.
Note: earlier 2.4.8 attempts (pcall wrap, dedicated frame,
C_Timer.After defer, file-load registration, Interface bump,
Frame:RegisterEventCallback) all failed because they fixed the
wrong layer. RegisterEventCallback is a CallbackRegistryMixin
method whose event set is closed and mixin-local — it rejects
raw frame events like PLAYER_REGEN_DISABLED. EventRegistry is
the right entry point.
Version 2.4.7
-------------
Broadcaster Tools (Retail only)
- NEW: Action Tracker overlay — shows your spell casts in a scrolling bar
list. Cast bars fill as you cast; instant casts show a 1.2s decay. Tracks
UNIT_SPELLCAST_* events for full cast state (start, success, interrupt,
channel). Enable/Disable from Broadcaster Tools settings tab.
- NEW: Event Tracker overlay — shows nearby combat events: defensive
cooldowns, offensive cooldowns (90s+), crowd control, and spell interrupts.
Events appear as color-coded rows with a 1-second fill animation.
Built-in curated spell database covering all classes.
- NEW: Arena DPS Bar — split bar comparing your team's damage vs the enemy
team in arena. 5-second rolling window with 100ms sampling. Activates
automatically when entering an arena zone.
- Broadcaster Tools tab is now Retail-only (hidden on Classic/TBC/Wrath/MoP).
- Config UI: Enable/Disable + Options buttons for each tracker (like Details).
- "Disable Mythic+ Stuff" toggle now finds the Mythic Dungeon button
dynamically instead of hardcoding index [4].
Easter Egg
- NEW: Snake minigame in Settings sidebar! Click the Snake tab,
click the grid, and use Arrow keys or WASD to play. Space to
pause, R to restart. Speed increases as you eat. High score
saved per profile. A little something for raid downtime.
- Fixed Snake game freezing / becoming unresponsive after a while.
Root cause: EditBox keyboard capture lost focus (ESC, clicking
elsewhere, combat lockdown) with no recovery path. Now auto-pauses
on focus loss with a clear "Click to resume" overlay. Click or
press R to restart after Game Over without needing keyboard focus.
- Fixed Snake grid clipped on left side. Grid was offset by
-SIDEBAR_WIDTH/2 from the scroll child center; now centred at 0.
- Fixed Click to Play — clicking the grid now immediately starts
the game (snake moves right). Previously only keyboard worked.
- Fixed Snake 180-degree turn death: direction checks now use the
queued direction instead of the current one, preventing instant
self-collision from fast opposite-key presses.
- Snake visual overhaul:
- Animated effects: death flash (red overlay fade-out), screen
shake on death, floating "+10" score popups that rise and fade,
golden level-up flash when ranking up.
- Rank system: Worm → Snake → Serpent → Viper → Python → Wyrm
(WoW item-quality colours: green/blue/purple/orange/red/gold).
- Speed bar in header showing current game speed percentage.
- Animated score counter that smoothly counts up on eat.
- Persistent stats: games played, total food eaten, longest snake.
- Golden shimmering food with dual-frequency pulse.
- Brighter snake head, distinct neck, smoother body gradient.
- Dimmed overlay backgrounds for all states with 3 text lines.
- Red-tinted grid on death, darker grid during play.
- Outer glow border on grid, icon in title.
- Footer: high score (gold), stats, controls hint.
- Proper cleanup (OnUpdate + EditBox) when switching tabs.
Debug Console & Debug Parity
- NEW: In-game Debug Console — CMD-like window showing debug output,
errors, and system messages in real-time. Color-coded by category
(CORE=green, COMBAT=orange, ERROR=red, DATA=cyan, PVP=magenta,
PERF=teal, EVENT=blue, WARN=orange). 500-line ring buffer,
copy-pasteable text. Toggle with /edm console. All clients.
- Console toolbar: one-click buttons for Clear, Diag, Errors, Mem, GC.
- Console filter tabs: click category tabs (CORE, COMBAT, DATA, ERROR,
PVP, UI, PARSER, EVENT, SYSTEM) to show/hide specific log categories.
"All" button resets filters.
- Console Tab-completion: press Tab to autocomplete commands.
- Console commands: help, clear, diag, errors, log [n] [cat], debug
on|off, info, events, mem, gc, segments, search <text>, fps,
profile, api, lua <code>, reset, reload.
- Console "lua" command: execute arbitrary Lua in a sandboxed env with
EDM namespace access. Useful for live addon inspection.
- Console "api" command: checks availability of all relevant WoW APIs.
- Console "segments" command: shows current + stored segment details.
- Console "search" command: find matching lines in console history.
- Console "fps" command: shows framerate and network latency.
- Console "profile" command: shows active profile and available list.
- NEW: Dedicated "Debug" tab in Settings sidebar — full diagnostic
panel with inline pass/fail results, error log viewer (last 15
errors with timestamps), system info panel (addon version, TOC,
client, memory, FPS, latency, segments, profile), WoW API
availability checker (13 APIs), and quick-action buttons (Open
Console, Run Diagnostic, Show Errors).
- Debug/Record Timeline toggles moved from Advanced section into the
new Debug tab's General section.
- Debug Console now embedded directly in the Settings Debug tab:
scrollable output area, toolbar buttons (Clear, Diag, Errors, Mem,
Info), command input with > prompt, Tab-completion, and command
history (Up/Down arrows). Matches the addon's own design language.
Live-refresh: output updates automatically as new log entries arrive.
/edm console now opens Settings on the Debug tab instead of a popup.
Standalone BugSack-style window still available via DC:Toggle().
- Fixed Unicode square characters in diagnostic output and settings.
Replaced checkmark (U+2713) and cross (U+2717) with ASCII "OK"/"X"
— WoW's game fonts lack these glyphs, causing visible squares.
- Hardcoded SelectTab(6) for Profiles tab replaced with dynamic
FindTabIndex("BuildProfilesTab") lookup — tab indices no longer
break when new tabs are added.
- Classic debug parity: /edm diag, /edm errors, /edm log [n] [cat],
and /edm console now available on Classic Era, TBC Anniversary,
MoP Classic, and Wrath Titan Forged (previously Retail-only).
Arena Summary (Retail only)
- Fixed Arena Summary showing wrong/missing data compared to WoW's
default scoreboard. Enemy team was empty, friendly team showed tiny
numbers (e.g. 45K instead of 915K). Root cause: CLEU combat log data
is restricted in WoW 12.x arenas. Switched primary data source to
C_PvP.GetScoreInfo() — the same API WoW's own scoreboard uses.
Falls back to CLEU segment data on older clients.
- NEW: Arena match history — matches are saved persistently (up to 50)
in your profile. Browse past matches with Prev/Next navigation
buttons after the arena has ended. Each saved match stores team
rosters, damage, healing, deaths, kills, rating, and rating change.
- NEW: Rating change display — shows +/- rating in green/red next to
player names when available from the scoreboard API.
- NEW: Data source indicator — label shows whether data comes from
"Scoreboard" (C_PvP API), "Combat Log" (CLEU fallback), or
"No data" so you know the source at a glance.
- NEW: Date/time shown in subtitle for saved matches when browsing
history.
Spell Casts Tracking
- NEW: "Casts" column in spell tooltip — hover any player bar (Damage,
Healing, DPS, etc.) to see how many times each spell was cast. Shown
alongside the existing Total / DPS / % columns in a light blue color.
Cast data comes from SPELL_CAST_SUCCESS events via CLEU.
- NEW: "Casts" display mode — dedicated bar view ranking players by total
spell casts. Cycles alongside existing modes in the menu and rotation.
Tooltip shows per-spell cast breakdown with count and percentage.
- Pet casts are attributed to owners via GetEffectiveSource mapping.
- Works on all clients (Retail, Classic, TBC, Wrath, MoP).
Bug Fixes
- Fixed Action Tracker entries disappearing immediately after cast
completes. Entries now stay visible in their final state (green for
success, red for interrupted) with a gentle fade, and are only
removed when pushed off by newer casts. Channels and instants also
persist instead of vanishing after 1.2-2s.
- Fixed "cannot be indexed with secret keys" errors in arena/PvP.
UnitGUID() returns tainted secret values for arena/nameplate units
in WoW 12.x. Added SafeGUID/SafeName wrappers with issecretvalue()
guards in Parser_Retail (NAME_PLATE_UNIT_ADDED, AddPetForUnit,
UpdatePetMapping) and ArenaSummary (BuildRosterMaps).
- Debug Console now captures real Lua runtime errors (not just
manual LogError calls). Hooks into BugGrabber if installed,
otherwise wraps the global error handler via seterrorhandler().
Only shows errors from EpicDamageMeter files. Errors include
stack traces (first 3 frames) and occurrence count.
- Fixed DPS/HPS colored bars invisible during combat. Bar width used
amountPerSecond (rate, e.g. 8.9K) against topValue=session.maxAmount
(total, e.g. 890K), producing ~1% fill. Now always uses totalAmount
for bar width — proportions are identical since all actors share the
same combat duration.
- Fixed 5 diagnostic FAIL results (Constants, MainFrame, Config UI,
Graph, DetailWindow). RunDiagnostic was checking wrong namespace
paths (EDM.C, EDM.UI.MainFrame, EDM.UI.Config, EDM.UI.Graph,
EDM.UI.DetailWindow). Corrected to actual paths (EDM.Constants,
EDM.UI, EDM.Config, EDM.Graph, EDM.DetailWindow).
Version 2.4.6
-------------
Full Compatibility Audit — Retail + Classic/TBC
- Fixed ADDON_ACTION_FORBIDDEN error spam (6x) on TBC Anniversary Edition.
AceEvent frame was named, causing Blizzard taint tracking to block
RegisterEvent during combat. Changed to unnamed frame. Also defers event
registration if the addon loads during combat (InCombatLockdown guard).
- Fixed ADDON_ACTION_BLOCKED on mode menu open: SetPropagateKeyboardInput
is a protected function on Retail/TBC Anniversary. Replaced with
UISpecialFrames for ESCAPE-to-close (standard non-protected pattern).
- Fixed Overhealing and Threat modes showing no data on TBC Anniversary.
Root cause: ADDON_ACTION_FORBIDDEN blocked CLEU event registration →
parser never received combat log events → database stayed empty.
- Fixed DPS/HPS bar display to match Damage Done/Healing Done format.
Now shows "52.3K (476 DPS) 43.4%" instead of "476/s 43.4%".
- Fixed "table index is nil" crash at Parser_Classic.lua:506 when taking
fall damage (ENVIRONMENTAL_DAMAGE). sourceGUID is nil for environmental
events — can't be used as a table key. Now uses "Environment" fallback.
- Fixed SetGradient API crash on Classic and TBC Anniversary. The wrapper
now auto-probes at first call: tries new 2-arg CreateColor form, if it
errors falls back to old 7-arg form. Previous detection via GetBuildInfo
TOC version was unreliable on TBC Anniversary (Retail client, but
reported Classic-like version). All 60+ SetGradient calls across
MainFrame, Config, DetailWindow, Graph, Skins, Widgets, ArenaSummary,
DeathRecap now go through the wrapper.
- Fixed ColorPickerFrame:SetupColorPickerAndShow() crash on Classic/TBC.
This API is Retail 10.2.5+ only. Added compat path using legacy
ColorPickerFrame direct-property method for Classic clients.
- Fixed SecretValue arithmetic crash in Threat mode (Retail PvP). The
threat value can be wrapped by WoW 12.0+ SecretValue. Now washed
through tonumber(tostring()) before arithmetic.
- Fixed mode menu ESCAPE-to-close broken by OnShow overwrite. Two
SetScript("OnShow") handlers were registered on the same frame —
the second killed the first (which enabled keyboard propagation).
Merged into a single OnShow handler.
- Fixed Database.lua nil crash when profile.combat sub-table is nil.
All 5 occurrences of EDM.db.profile.combat.X now have full nil-guard
chain.
- Fixed C_DamageMeter session fetch crash on Retail. GetCombatSessionFrom
Type/ID calls can throw if the session is tainted. Now wrapped in pcall.
- Fixed duplicate "Max Spells" slider in tooltip settings (one with wrong
range 3-15 and default 6 vs correct 3-30 default 30). Removed duplicate.
- Fixed Skins.list nil crash in Setup Wizard Step 2 when Skins module
hasn't loaded yet.
- Improved client detection: granular per-expansion flags (isVanilla, isTBC,
isWrath, isCata, isMoP) instead of binary isRetail/isClassic. isRetail is
now strictly Midnight (12.x+). Added hasMythicPlus flag (Retail only).
- Mythic Dungeon settings tab now hidden on non-Retail clients (Classic Era,
TBC Anniversary, Wrath, MoP). Config sidebar dynamically filters categories
based on client capabilities.
Version 2.4.5
-------------
Classic/TBC Font + Settings Visibility Fix
- Fixed "FontString:SetText(): Font not set" error spam (70x per combat)
on TBC Anniversary and Classic servers. SetFont() can silently fail on
Classic clients — pcall returns true but the font is internally nil.
Added Utils.SafeSetFont() (shared) that verifies GetFont() after SetFont
and falls back to FRIZQT__.TTF. Applied to ALL FontStrings across the
entire addon: MainFrame bars/statusbar/titlebar/tooltip, Config settings
panel (75 labels), DetailWindow, Graph, Widgets, Bars, Tooltip, Skins,
Core_Classic, Core_Retail. Zero raw :SetFont() calls remain in addon code.
- Fixed Settings panel text completely invisible on TBC Anniversary.
All 75 label/header/button FontStrings in Config.lua now use the safe
font wrapper. Sidebar was visible because it used different frame timing;
right panel labels were created with silently-failed fonts.
- Fixed missing icons in mode dropdown on TBC Anniversary. DPS icon
(ability_hunter_focusfire) and Enemy Damage Taken icon
(achievement_boss_lichking) are MoP/WotLK-only textures that don't
exist in Classic/TBC. Replaced with Classic-safe alternatives:
ability_warrior_innerrage (DPS) and ability_warrior_decisivestrike
(Enemy Damage Taken).
Version 2.4.4
-------------
Theme Toggle Fix + DPS Display Fix + Expanded Debug System
- Fixed DPS showing "1 DPS" or "0 DPS" on the first tick of a new
combat session (C_DamageMeter path). The Blizzard API's
amountPerSecond field can return stale/wrong values before the
session's internal timer stabilises. DPS text is now computed from
totalAmount / durationSeconds for plain values, matching the actual
data. SecretValue (PvP) path still uses API's amountPerSecond.
- Fixed tooltip showing "No spell data available" after combat ends.
C_DamageMeter session persists briefly after PLAYER_REGEN_ENABLED,
so UpdateBarsFromDamageMeter still renders bars — but with a minimal
actorData (empty abilities). GetTooltipSpells now has a third fallback:
lazy fetch from C_DamageMeter on hover, trying Current session first,
then expired session via stored blzSessionId. Result is cached for
subsequent hovers. Details! equivalent: CallSpellAPI fall-through.
- Fixed theme toggle button showing as a square in settings title bar.
Unicode ☀/☽ characters aren't supported by WoW's game fonts.
Replaced FontString with texture-based icons: golden circle with rays
(sun) and silver crescent (moon) drawn from WoW's built-in
TempPortraitAlphaMask texture. Icons highlight to accent blue on hover.
- Expanded debug system with categorised logging (CORE, COMBAT, DATA,
PVP, UI, GRAPH, PARSER, ERROR). Each category has its own colour code
and timestamp. Debug messages stored in a 500-entry ring buffer.
- NEW: /edm diag — full system diagnostic scan. Checks all modules,
WoW API availability, current segment state, SecretValue taint status,
and error log. Prints a pass/fail checklist to chat.
- NEW: /edm errors — shows the last 25 captured errors. Errors are
silently logged even when debug mode is off, so you can check after
something breaks without needing to reproduce it.
- NEW: /edm log [count] [category] — shows the debug log buffer.
Filter by category (e.g. /edm log 20 PVP) to isolate specific systems.
- Utils.LogError() now captures errors silently (always stored, printed
only in debug mode). Event callbacks, UI updates, and SafeCall all
route through the error log for post-mortem analysis.
- Utils.ValidateNum() helper: validates and washes values in one call —
checks nil, NaN, SecretValue taint. Returns (washed_number, ok).
Version 2.4.3
-------------
Live Combat Updates Fix + Enemy Data Toggle
- Fixed data only appearing after combat ends (PvE and PvP).
Root cause 1: Parser_Retail.lua was replacing Parser_Classic.lua's
CLEU handler with a no-op, preventing database population during
PvE combat. Parser_Retail.lua now extends Parser_Classic instead
of replacing it, preserving the CLEU handler for PvE data collection.
Root cause 2: CLEU event lookup tables (DAMAGE_EVENTS, HEAL_EVENTS,
etc.) were only defined on Classic, causing Parser_Classic's CLEU
handler to error on every event on Retail. Tables are now defined
on both clients. CLEU works in PvE on 12.0 — only PvP restricts
the data values (safeNum silently skips SecretValues).
- Rendering pipeline now always tries C_DamageMeter first (like
Details! ShouldUseGameData), regardless of combat state. Fallback
to database path kicks in only when C_DamageMeter has no data.
- Default refresh rate lowered from 0.5s to 0.3s (matches Details!).
Minimum clamp lowered from 0.5s to 0.1s for users who want faster.
- Enemy Damage Taken and Avoidable Damage Taken modes now use
C_DamageMeter (Enum.DamageMeterType.EnemyDamageTaken /
AvoidableDamageTaken) for live arena/BG rendering.
- DAMAGE_METER event handlers always trigger C_DamageMeter rendering
(previously gated on combat state, missing boundary updates).
- Added debug logging at each C_DamageMeter failure point.
- NEW: Team/Enemy toggle button in toolbar. Click "Team" to switch
to "Enemy" view — shows enemy player data (damage taken by each
enemy) during PvP via C_DamageMeter.EnemyDamageTaken. Works live
during arena and BG combat. Title bar shows [Enemy] indicator.
- Existing profiles with refreshRate 0.5s auto-migrated to 0.3s.
- Complete settings panel UI/UX redesign: Inzoi-style light translucent
desktop GUI. Frosted-glass light-gray panels, white card sections,
coral/pink slider thumbs, iOS-green toggle switches with white knobs,
thin 2px tracks, minimal sidebar navigation with accent bar, generous
spacing. Setup Wizard matches new light style. All existing
functionality preserved — zero feature loss.
- NEW: Dark / Light mode toggle for settings panel. Click the
sun/moon icon in the title bar to switch themes. Choice is
saved per profile. Dark mode features Discord/VS Code-inspired
charcoal panels with brighter accent colors. All ~40 palette
variables and ~60 inline color sites consolidated into a
centralized theme system (ApplyTheme mutates tables in-place).
- Fixed SecretValue taint crash in PvP arenas: Utils.FormatTime,
Utils.FormatPercent, Graph.lua FormatTime/FormatValue, and
Database:GetSegmentDuration now wash values through
tonumber(tostring()) to strip SecretValue wrappers before
numeric comparisons. Graph data feeding also washes
segment.totalDamage/totalHealing and _graphDPS/_graphHPS.
- Fixed DPS/HPS values showing excessive decimal places (e.g.
"628.85714285714" instead of "629") when values are below 1K.
Blizzard's AbbreviateNumbers doesn't round small numbers; now
uses Utils.FormatNumber for plain values and AbbreviateNumbers
only for SecretValues. Fixed in MainFrame and DetailWindow.
Version 2.4.2
-------------
PvP / Arena / Battleground Rendering Fix
- Fixed bars not displaying during arena/BG combat. Root cause: the
rendering pipeline lacked server-side combat detection and could
silently error when processing SecretValues from C_DamageMeter.
- Server combat detection ticker (like Details! control.lua):
C_Timer.NewTicker(0) polls C_DamageMeter every frame to detect
server-side combat state via issecretvalue(session.totalAmount).
Ensures bars render even when PLAYER_REGEN events are delayed or
the server-side combat session outlives the client-side flag.
- Parser_Retail.lua now loads on Retail (added to TOC). Replaces
Parser_Classic.lua on Retail with better arena/BG GUID tracking
(nameplate scanning, arena opponent scanning, BG detection).
- DPS and HPS display modes now use correct Blizzard enum types
(Enum.DamageMeterType.Dps / .Hps) instead of DamageDone/HealingDone,
matching Details! behavior for proper sort order from the API.
- Secret bar rendering uses Enum.StatusBarInterpolation.ExponentialEaseOut
(matching Details! UpdateBarApocalypseWow) for smooth bar transitions.
- isSecret detection now checks session.maxAmount and session.totalAmount
in addition to sources[1].totalAmount, catching edge cases where the
first source is plain but the session-level values are still secret.
- Arena names use Ambiguate(name, "short") for SecretValue names
(same technique as Details! class_damage.lua).
- Status bar total now shows AbbreviateNumbers(session.totalAmount)
during PvP combat instead of just the player count.
- Duration uses session.durationSeconds from C_DamageMeter when
available, matching Details! behavior.
- UpdateBarsFromDamageMeter errors are now logged via Utils.Debug
instead of being silently swallowed by pcall.
Version 2.4.1
-------------
PvP / Arena / Battleground Fixes
- Full PvP support for WoW 12.0+ Retail: arenas and battlegrounds now
track damage, healing, interrupts, dispels and deaths correctly.
- CLEU parser (Parser_Classic.lua) is now SecretValue-aware: all
CombatLogGetCurrentEventInfo() values are checked with safeNum/safeStr
before arithmetic or string comparison. Events with secret amounts
are gracefully skipped instead of causing taint errors.
- Smart post-combat sync inspired by Details! WaitServerDropCombat:
after combat ends, polls C_DamageMeter session data every 0.3s until
SecretValues resolve (up to 9s). In PvE this resolves instantly; in
PvP it waits for the server to drop the restriction state.
- Uses C_RestrictedActions.GetAddOnRestrictionState to detect PvP
restriction state (Combat + PvPMatch flags) before attempting sync.
- IsSessionStillSecret() checks whether the C_DamageMeter session
still contains SecretValue fields, preventing premature sync.
- specIconID → GUID cache: when syncing C_DamageMeter data, specIconID
is cached to GUID mapping, allowing tooltip/detail resolution when
sourceGUID is a SecretValue (same technique as Details! guidCache).
- SyncFromDamageMeter now falls back to name-based GUID lookup via
group/arena/nameplate units when sourceGUID is still secret.
- Parser_Retail.lua registers NAME_PLATE_UNIT_ADDED event for live
GUID tracking in battlegrounds.
- ScanBattlegroundNameplates() added to Parser_Retail.lua for opponent
GUID resolution in large-scale PvP.
- Parser_Retail.lua now detects BG instance type and scans nameplates
during UpdateGroupGUIDs.
Version 2.4.0
-------------
New Features
- Window-group lock icon redesign — small chain-link button at the
bottom-right of each meter window, well above the footer/status bar.
Left-click + drag to reposition anywhere inside the frame; position
persists per character. The icon fades out while the cursor is over
the meter window so it doesn't get in the way of clicking bars, then
reappears when the cursor leaves. Clamped to the frame so it can't
be dragged outside the visible area. Click = detach this window from
its group; Shift-Click = dissolve the entire group.
Tweaks
- Window-group snap distance bumped from 14px to 22px for a more
magnetic feel when sliding two meter windows close together.
Bug Fixes
- Threat module SecretValue taint on retail. The CoerceNum helper had
an `if type(v) == "number" then return v end` early-return which
short-circuits SecretValue numbers (those are typed as number too,
so the check was a no-op for them). actor.threat ended up storing
the raw SecretValue, then any subsequent comparison
(`actor.threat > 0` in ClearThreat, `(actor.threat or 0) > topValue`
in MainFrame) tainted the whole call frame. Fix:
* CoerceNum now always washes through string.format + tonumber
and bails to nil when issecretvalue(v) is true.
* ClearThreat resets unconditionally (no comparison).
* Threat:Update re-coerces at the assignment boundary.
* MainFrame threat-bar compare is pcall-guarded.
Resolves the "attempt to compare field 'threat' (a secret number
value, while execution tainted by 'EpicDamageMeter')" error in
retail dungeons / raids.
- Reverted live-bar-render-path regressions introduced in 2.3.9
(valueText SetWidth(64) + SetWordWrap(false), spell-cache plainGUID
gate change with pcall, abilities mirror block, status-bar / title-
text / mode-button width caps and word-wrap blocks). The render path
now matches the working pre-regression behaviour again. Locale-aware
font fallback, threat-module SecretValue hardening, and the
Current→Expired session fallback in SyncFromDamageMeter are kept.
----
Version 2.3.9
-------------
New Features
- Mode Picker rebuilt as a 3-column Details-style grid (modeled on
Details\frames\window_main.lua mode menu): right-click the mode button to
open a Damage / Healing / Other column layout with Blizzard spell icons per
entry, violet → blue hover gradient, and a left stripe + brightened label
to mark the active mode. Two new modes are wired up:
* Avoidable Damage — heuristic detection in Parser_Classic.lua
(ENVIRONMENTAL_DAMAGE or any source outside the group counts as
avoidable) so floor damage / boss mechanics show up without curating
a per-spell list.
* Potions — SPELL_CAST_SUCCESS dispatches into ProcessPotion which keys
a curated POTION_SPELLS table covering TWW (431416/431473/431932/
431930), DF, SL, BFA, Legion/WoD, MoP, Cata, Wrath, TBC and Vanilla.
Database.lua's CreateActorData stores avoidableDamageTaken,
enemyDamageTaken, potionsUsed and a per-spell potionList so the new modes
sort correctly via GetSortedActors. Constants.lua adds DISPLAY_MODE
entries 19/20 plus order entries for both Retail and Classic, and Retail
now also lists Overhealing in the menu order. CalculateTotals dispatches
the new modes alongside the existing ones.
- Language Selector — a new "Language" tab on the right of the Settings
sidebar lets you pick the addon language independently of the WoW client
locale. Locale files no longer gate themselves on GetLocale(); each one
registers into a shared EpicDamageMeter_LocaleData[code] registry, and a
new Locales/_Apply.lua (loaded last in every TOC) builds the active
EpicDamageMeter_Locale by merging the chosen overlay onto the English
base. Choices are Auto / English / Deutsch / Español / Italiano /
Русский / 繁體中文; "Auto" follows GetLocale(). Switching live calls
EpicDamageMeter_ApplyLocale to refresh the table in place; a /reload
button is provided for full UI re-translation. Comprehensive L("…")
wrapping across MainFrame, ArenaSummary, DeathRecap, DetailWindow,
Tooltip, Graph, WindowGroup, Core slash output, and the entire Config
panel (tab labels, every section header, every row label via the row
helpers themselves, every dropdown option). German overlay covers
~270 strings each across all six locales (enUS, deDE, esES, itIT, ruRU,
zhTW) — Profiles tab fully covered (Switch/Create/Copy/Delete sections,
static popups). Any not-yet-translated key still falls back through
key-as-value to English. Setter on the Language dropdown rebuilds
sidebar labels and re-runs the active tab's BuildXTab so the change is
visible immediately without /reload.
- Locale-aware font picker (Locales/_FontMap.lua) — resolves a font
path that can render the active addon-language's glyphs. Probes
candidates with FontString:SetFont + GetFont:
ruRU: FRIZQT___CYR.TTF → ARIALN.TTF → FRIZQT__.TTF
zhTW: ARKai_T.TTF → ARHei.TTF → bHEI01B.ttf → FRIZQT__.TTF
Latin locales stay on FRIZQT__.TTF
If the user drops Interface\AddOns\EpicDamageMeter\Fonts\addon.ttf,
that pan-Unicode override wins for every locale. Wiring:
* Core/Utils.lua exposes EDM_F() / Utils.GetFont() globally
* MainFrame's ApplyBarFont overrides the skin/profile font with
the locale font when a non-Latin font was actually resolved
(skin font kept on Western locales)
* UI:RefreshLocaleFonts() walks every active instance and re-sets
titleText / modeBtn / segmentBtn / status-bar / bar-pool fonts
* Config.lua's local FONT re-resolves on every SelectTab so the
Settings panel picks up the right font even after the saved
language overrides the parse-time default
* Hooked into the Language dropdown setter so the change takes
effect immediately, without /reload
Note: this only helps when the resolved font actually exists on
disk. A German WoW client has no Cyrillic-capable font shipped, so
for full ruRU/zhTW rendering on a Western client the user must
drop their own TTF at the override path.
- Setup Wizard fully localized across all six locales — every step
title, every section header, every toggle label and description, the
Welcome / Theme / Font / Display / Layout / Colors / Behavior / Done
step labels, and the summary card lines (Theme: / Font: / Bars: /
Format: / Window:) all go through L() and are translated. WizSection
/ WizToggle / MakeSelectCard helpers auto-translate their first label
argument so future wizard rows are translated for free. Roughly 120
new wizard-specific keys per locale.
- Sounds promoted to a dedicated sidebar tab — moved out of the inline
Sounds section that lived under Settings, and given its own left-rail
entry between Settings and Profiles. Four sub-sections inside: Sound
Cues (master enable + Use-Custom-Files), Events (per-cue toggles for
combat start, combat end, new record, reset), Preview (four ▶ test
buttons), About (info card). Sidebar SelectTab dispatch shifted
Profiles/Language/Credits to indices 5/6/7; the four C_Timer.After
SelectTab(4) calls inside BuildProfilesTab were updated to (5).
- Sound cues — Core/Sounds.lua module fires on combat start, combat
end, a new personal-best player DPS, and on /edm reset. Three-tier
source resolution: LibSharedMedia entry (if profile.sounds.lsm[event]
is set) → custom OGG in Sounds\<file>.ogg if present → Blizzard built-
in FileDataID (defaults: UI_Bnet_Toast 567432, PVPFlagTaken 569883,
RaidWarning 8959, MapPing 8454). PlaySoundFile returns willPlay=false
silently when a custom file is missing, so the fallback FileDataID
always plays without any user-supplied audio. Personal-record check
walks the segment's actor list at combat-end +1s, finds the player
by UnitName, computes damage/duration, and only plays the cue when
the new DPS strictly beats db.profile.records.bestDPS (skips the
very first combat). Master toggle + per-event toggles + four ▶
preview buttons added under Settings → Sounds.
- Window Groups (modeled on Details' snap system in
Details\frames\window_main.lua): drag any two windows so their edges
come within 14 px of each other and they snap into a group — from
that moment they move together. Groups form a transitive closure, so
three or more windows can be chained horizontally, vertically, or in
L-shapes. A chain-link pill button appears top-right on every window
that belongs to a multi-member group; click it to detach just that
window, Shift-Click to dissolve the entire group. Snap relationships
survive reload — the snap set is persisted in SavedVariables alongside
position/size and cleanup runs automatically when a window is destroyed.
- Death Recap overlay (modeled on Details\frames\window_deathrecap.lua):
a styled panel that replaces Blizzard's stock death recap when it opens.
Hooks DeathRecap_LoadUI so DeathRecapFrame_OpenRecap is intercepted,
hides Blizzard's Recap1-5 lines, then reads DeathRecap_GetEvents(recapID)
and renders up to five gradient-pill rows with spell icon, time delta,
spell name, damage (crit = gold, normal = red), source class color, and
HP% at time of hit. Matches the Settings redesign palette (ACCENT blue
+ ACCENT_HOT violet). /edm dr to preview.
- Arena Summary window (modeled on Details\frames\window_arenasummary.lua):
on PVP_MATCH_COMPLETE inside an arena, after a 0.5s settle, freezes a
snapshot of the current segment and renders a two-column scoreboard —
your team (blue stripe) vs enemy team (red stripe), sorted by damage,
each row showing damage + DPS, healing + HPS, and a compact misc strip
for deaths / interrupts / dispels. Footer totals team damage and team
healing. Outcome badge reads VICTORY / DEFEAT / DRAW from
C_PvP.GetActiveMatchWinner vs GetBattlefieldArenaFaction. Classification
is GUID-based: group members = friendly, arena1-5 = enemy. Lighter than
Details' 1285-line implementation (no long-term archive, no compressed
save), but covers the core use case. /edm arena to preview.
- Threat display mode (modeled on Details! Tiny Threat): right-click the mode button
and pick Threat under Utility. Resolves a reference mob (boss1-5, target, focus,
mouseover, or targettarget) and polls UnitDetailedThreatSituation for every group
member on UNIT_THREAT_LIST_UPDATE and PLAYER_TARGET_CHANGED. Percent column shows
the scaled threat% (100 = aggro threshold); bars are color-coded by threat status:
red = tanking, orange = about to pull, yellow = getting close, class color = safe.
Creates actor entries on the fly so non-damaging group members still appear.
Bug Fixes
- Hardened Threat module against Retail 12.0 SecretValue boolean taint: every WoW API
return that could be a SecretValue (UnitExists, UnitIsDeadOrGhost, UnitCanAttack,
UnitDetailedThreatSituation's isTanking) is now either pcall-guarded or coerced
through tostring before any boolean test. Queries the 5 return values of
UnitDetailedThreatSituation inside a pcall closure so isTanking is dropped at the
pcall boundary and can never reach a Lua boolean expression. Also forces
actor.threatIsTank to a strict true/false Lua boolean. Fixes the
"attempt to perform boolean test on local 'isTanking' (a secret boolean value
tainted by 'EpicDamageMeter')" error spam on new-patch raid/instance content
(e.g., Windrunner Spire, Seat of the Triumvirate). (Thanks to ursiDEE and
MrPapaBear for reporting)
- Fixed detail window showing "No damage data" when clicking an enemy arena
player or battleground opponent. Two fixes, based on how Details handles
the same case:
(1) Removed the blanket SecretValue-GUID rejection in CallSpellAPI.
Details\boot.lua:328 (Details222.B.GetSpells) and
Details\core\parser_nocleu1.lua:552 (getSpells) both pass the raw
sourceGUID from C_DamageMeter.combatSources directly to
GetCombatSessionSourceFromType / GetCombatSessionSourceFromID — no
SecretValue filtering. We now do the same (still wrapped in pcall
for safety), so arena/BG opponents whose GUIDs arrive as
SecretValues reach the API and return their spell breakdown.
(2) MainFrame's plain-GUID map now also covers arena1-5 + their pets
and walks C_NamePlate.GetNamePlates to pick up battleground
opponents via nameplate unit tokens — UnitGUID on those returns
plain strings, giving us a guaranteed-plain fallback if the
session-source GUID path ever stumbles.
(Thanks to tidgey for reporting)
- Fixed overkill damage being counted in damage done/DPS totals. Effective damage is now
tracked (amount - overkill), matching how Details and other meters handle it.
(Thanks to Undercover for reporting)
- Fixed PvP combat data being wiped when leaving arena or battleground. Zone change auto-reset
now only triggers when entering a new dungeon or raid, not when returning to the open world.
(Thanks to user_myc0mwa16b49mnts for reporting)
- Fixed meter disappearing after PvP combat ends due to aggressive zone-change reset logic.
- Fixed Threat module crashing on Retail 12.0 with "attempt to perform boolean test on
a secret boolean value". Rewrote the module to use the same patterns as Details! does
in unitframe.lua and plugins_statusbar.lua: `local _, status, ...` discards isTanking
at the call site, and tank state is read from UnitGroupRolesAssigned instead of the
SecretValue return. No pcall wrapper needed — Details has shipped this pattern for
years without taint issues. (Thanks to ursiDEE for reporting)
UI Redesign
- Settings panel got a full visual overhaul (not just a polish pass):
- New "glass indigo" palette: vivid sky-blue accent plus a violet secondary used
for gradients and highlights, deeper panel body, tighter contrast ladder between
sidebar, content, section cards, and rows.
- Panel resized to 860x640 (from 820x620); sidebar widened to 180px so longer
category labels (and future ones) breathe.
- Title bar is now a premium header (54px): deep vertical gradient base with a
horizontal violet→blue accent wash layered on top, a two-segment rainbow top
line (violet → blue → cyan), bottom separator tinted with the accent gradient,
and a soft drop shadow for clear separation from the body.
- New emblem logo: 26x26 rounded square with a violet→blue vertical gradient,
inner sheen on the top half, soft horizontal halo behind it, and a white "E"
glyph with outline + shadow. Paired with a larger 16pt wordmark (cyan-teal
"Epic" / gold "Damage" / soft-red "Meter") and a breadcrumb-style subtitle
("/ Settings" in dim text).
- Setup Wizard button is a gradient pill: violet→blue fill, top sheen, white
icon + outlined bold label, decorative sparkle dots on the right, and an
outer halo glow that fades in on hover (plus a brighter gradient + sheen
shift). The border brightens from 28% to 55% white on hover.
- Section headers became card-style: flat dark card with 1px inner border, chunky
accent→violet vertical pill on the left, soft glow around the pill, larger 13pt
outline title, right-aligned + / − collapse chevron (instead of v / >).
- Rows redesigned from the ground up: no more alternating background stripes,
no per-row left accent edge — just flat rows with a 1px hairline divider at the
bottom and an accent-tinted hover fill. Rows are taller (32px toggle/color,
34px dropdown, 48px slider) with more breathing room.
- Sliders got a custom track: thin 4px dark pill with an accent-to-violet
horizontal-gradient fill that grows from the left as you drag. Default WoW
slider track graphics are hidden, keeping only the handle.
- Dropdowns are now pill-shaped, with an accent left-stripe inside the button
that brightens on hover, plus an accent-colored chevron.
- Every interactive element now uses the same "gradient pill + halo" language
as the Setup Wizard button, giving the panel a coherent premium look:
- Sidebar nav active tab: violet→blue horizontal gradient fill, top sheen
band, outer halo glow bleeding out of the button, left accent pill in
violet→blue vertical gradient, outlined bold label with shadow.
- Reset Data / Reload UI buttons: gradient pill style with per-button
brand colors (red for Reset, green for Reload), halo that fades in on
hover, top sheen, outlined 12pt label. Slightly taller (34px).
- Toggle switches: gradient fill (violet→blue) + outer halo when ON,
flat neutral when OFF. Knob is pure white on, dim gray off.
- Dropdowns: gradient fill + top sheen + hover halo + violet→blue left
accent stripe that brightens on hover. Border switches from neutral to
accent-blue on hover. The opened menu has an accent gradient top line
and an accent-tinted border.
- Sidebar has a subtle vertical violet wash layered on top of its dark base,
and its right divider is now a vertical accent gradient line.
- Content area has its own subtle violet top-down wash for depth.
- Toggle switches are slightly larger (40x18).
- Setup Wizard now speaks the exact same premium visual language as the main
settings panel:
- Frame border picks up an accent-tinted color instead of the old grey edge.
- Title bar rebuilt to match settings (54px): vertical gradient base + violet
→blue horizontal wash, top sheen band, two-segment rainbow top line
(violet → blue → cyan), accent-gradient bottom separator. Hosts the same
26x26 emblem logo with "E" glyph + halo, 15pt wordmark, breadcrumb "/",
and subtitle reading "Setup Wizard / step name".
- Skip button is a proper pill now: dark gradient fill, top sheen, 1px
border, outlined SKIP label — hovers into a warm red border + halo glow
+ brighter fill instead of the old text-with-underline look.
- Progress bar sized up to 30px with a violet wash, accent-gradient
bottom divider, 8px step dots, and a violet→blue horizontal gradient
track that fills from the first to the last completed step. Active step
now uses a pure white 10x10 dot with white outlined label; completed
steps shift to the accent color; upcoming stays dim.
- Bottom nav bar redesigned (56px): violet wash + accent-gradient top
divider. Back / Next are full gradient pill buttons with halo, fill,
sheen, and outlined label — primary (Next) in violet→blue, secondary
(Back) in dark with an accent hover border + subtle halo.
- Section headers use the same violet→blue vertical pill (3x12) +
outlined 11pt title + accent gradient underline as the main panel.
- Selection cards (theme / layout picker) are now gradient pill cards
with a halo glow and a left violet→blue stripe when selected, a pure
white checkmark, and an accent-border hover state when unselected.
- Wizard content area is now scrollable (mouse wheel). Fixes the Behavior
step rendering its last toggles underneath the Back / Next buttons on
smaller wizard heights. Scroll position resets to top on step change.
- Wizard toggle rows match the main toggle rows: flat row with hairline
divider, accent-tinted hover wash, and the premium 40x18 gradient
switch (violet→blue fill + halo when ON, white knob; neutral dark
when OFF, dim gray knob).
Code Quality
- Removed AI-generated comment patterns (section separators, marketing language, obvious
state-the-obvious comments) across all UI and Core files.
- Headers now describe file contents without adjectives or version markers.
Version 2.3.8
-------------
Bug Fixes (Community Reports)
- Fixed ALL dropdown menus not saving selections: CreateDropdownRow passed numeric array
index to setter instead of string value. Affected every dropdown in settings (Skin,
Combat Behavior, Font Face, Bar Texture, etc.). Arrays now preserve intended order.
(Thanks to Undercover for reporting the symptom on MoP Classic)
- Fixed "Combat Behavior" changes not applying immediately: Selecting a mode now calls
UpdateVisibility right away instead of waiting for next combat event.
- Fixed visibility features (Hide in Combat, Only in Group, Combat Alpha, etc.) completely
missing on MoP, TBC, and Classic Era: Added defaults, UpdateVisibility(), and per-instance
ShowWindow/HideWindow to all clients.
- Fixed segments not separating between fights on MoP/TBC/Classic Era: Added auto-segment
logic with configurable "Segment Gap" setting (default 3s). Retail threshold reduced from
hardcoded 10s to use the same setting.
- Fixed class/spec icons not showing on bars: Replaced string-path icon lookup with
fileDataID-based table for all 13 classes + special types. Fixes nil dirty-check bypass.
Version 2.3.6
-------------
New Features
- Setup Wizard: 7-step first-run experience (Welcome, Theme, Font, Display, Layout, Behavior, Done).
Appears automatically on first login. Features: step progress bar with labeled dots, skin cards
with mini-bar previews, font list with live Cyrillic preview, bar overlay/format/info toggles,
window size/scale/opacity sliders, visibility & combat behavior toggles, summary card on finish.
All changes apply live. Skip button cleanly placed in title bar.
- Per-skin unique bar effects: Each of the 23 themes now has its own distinct visual identity beyond
just colors. Each skin defines unique overlays, accent lines, inner glow, spark color/intensity,
animation easing, and hover behavior:
• Overlay types: topShine, bottomFade, innerGlow, duoTone, scanline, holographic, glossy, shadow
• Accent lines: per-skin colored top/bottom/left edge accents
• Inner glow: gradient glow strips from top/bottom edges (neon, cyberpunk, midnight, etc.)
• Spark: per-skin spark color and intensity at bar leading edge
• Animation: smooth (exponential), snappy (instant), elastic (bouncy overshoot) per skin
• Hover styles: glow, brighten, neonPulse, borderFlash, ember, frost, arcane, subtle
• Flash color: per-skin crit flash tint
- Per-skin bar layout system: Each theme defines a complete bar design beyond just effects:
• Icon shape: square (default), round (with minimap ring border), or hidden per skin
• Value position: right (standard), overlay (on bar fill), or stacked (vertical name+value)
• Rank style: number (#1, #2), colored dot (●), or hidden per skin
• Background style: gradient, solid, dark (dimmed), or none per skin
• Background direction: VERTICAL or HORIZONTAL gradient per skin
New Features
- Enemy Damage Taken display mode: Shows damage taken per enemy NPC/boss. Hover to see
which players dealt the most damage to that target. Useful for tracking add damage and
identifying who's slacking on priority targets. Available in mode dropdown under Damage.
- Hide in Combat visibility mode: Opposite of "Auto-Hide OOC" — hides the meter when
entering combat and shows it when leaving. Perfect for overlapping with a threat meter
so both share the same screen space with opposing visibility rules.
(Thanks to Undercover for the suggestion)
- Separate combat alpha: New "Combat Alpha" toggle with independent In-Combat and
Out-of-Combat opacity sliders (0-100%). Can be used instead of hide/show for a
smooth fade-based approach to combat visibility control.
Bug Fixes (Community Reports)
- Fixed pet damage not merging with owner on MoP, Classic, and TBC clients: Parser was
reading from wrong config path (profile.general.mergePets instead of profile.combat.mergePlayerPets).
Treants, Water Elementals, and all other pets now correctly merge with owner.
(Thanks to pawnzee for the detailed report)
Visual Improvements
- All per-skin effects boosted to be clearly visible (overlays, accents, glow strips, spark 2-3× stronger)
- Accent lines widened to 2px (top/bottom) and 3px (left) for clear visibility
- Inner glow strips now cover 60% of bar height (was 40%)
- More layout variety: Glass, Midnight, Ocean, Warcraft now use stacked text; Toxic uses overlay text
Bug Fixes
- Fixed name text disappearing on skins with hidden rank/icon (ElvUI, Minimal, Shadow, Toxic):
rankText had no anchor after ClearAllPoints when rankStyle="none", causing nameText to vanish.
Now nameText anchors directly to icon when rank is hidden.
- Fixed name text appearing right-aligned on some skins (missing SetJustifyH after ClearAllPoints)
- Removed "stacked" text layout (name+value vertical) — caused text overlap on bars under 28px
- Fixed critical bug: profile settings (theme, fonts, scale, opacity, title bar visibility, etc.)
were lost on every reload/login. The custom AceDB-3.0-EDM library's copyTable() unconditionally
overwrote saved profile values with hardcoded defaults from Constants.lua each time db.profile
was first accessed. Now only missing keys are filled in, preserving user changes across sessions.
(Thanks to Pentara [Mind] for the detailed bug report identifying Constants.lua as the culprit.)
- Fixed crash spam "attempt to compare local 'str' (a secret string value tainted)" in Parser_Classic.lua:96
(safeStr() now uses issecretvalue() to bail out before comparing tainted WoW 12.0 strings)
- Fixed Settings crash "attempt to call upvalue 'setValue' (a nil value)" — Minimap Icon toggle on Retail
was missing the tooltip nil arg, causing the getter to land in the tooltip slot and setValue to be nil
- Removed "Enable Addon" toggle from Settings (the addon is always enabled when loaded)
- Fixed /edm slash command not working on Retail (AceConsole-3.0-EDM lib name didn't match the
"AceConsole-3.0" mixin string in NewAddon, so RegisterChatCommand silently no-op'd; added
direct SlashCmdList fallback to match Classic)
- Fixed misleading login hint: "/edm for options" now correctly says "/edm config for settings"
(in all 5 locales — bare /edm shows the main window, /edm config opens Settings)
- Font dropdowns now only show fonts with full Cyrillic AND special character (äöüéèàñß) support —
player names with accents or Cyrillic letters no longer appear as missing-glyph boxes. Detection
uses width-ratio tests (Cyrillic "Ж" must be ≥ 1.5× wider than "I"; accented Latin chars must
differ from uniform notdef boxes). Currently-saved fonts that don't pass remain visible with a
"(missing glyphs)" hint so users can change them.
Settings Panel Redesign (visual only — no functional changes)
- Larger, more readable section headers with bottom divider line and breathing room between groups
- Section titles now use mixed case + larger 12pt outlined font (was 9pt uppercase)
- Sidebar nav: bigger tabs (42px), larger icons + labels, animated hover state, glow + accent strip on selected
- Title bar redesigned: 42px tall, gradient accent glow line, logo dot, separate subtitle
- Reset Data / Reload UI buttons larger and more polished (32px, gradient hover)
- Slightly wider panel (820x620) for better content density
- Row heights and label fonts bumped for readability (toggles 28px, sliders 42px, dropdowns 30px, colors 28px)
- Softer alternating row backgrounds — less visual noise
- Universal row hover highlight on every row (toggle/slider/dropdown/color/dual)
- Each row has a subtle blue left-edge accent that ties section content together visually
- Larger toggle switches (34x16) and color swatches (40x18)
- Color swatches now glow with accent border on hover
- Dropdown buttons highlight with accent border on hover
- Slider value labels now outlined for better visibility
- Wider dropdowns (180px) with more legible 10pt text
Version 2.2
-------------
Profile System
- Simplified profile UI (Details-style: dropdown switch, create, copy, delete — no collapsible sections)
- Profiles now save/restore window position, size, scale and display mode per instance
- Multiple windows fully supported: each window remembers its own layout per profile
- Fixed "Profile not found" error (dropdown passed array index instead of profile name)
- Reset Profile preserves window positions
Font System
- Font Face and Font Style changes now trigger a confirmation popup + UI reload (required for WoW to apply)
- Font validation: only fonts that actually render text are shown in the dropdown
- Runtime font discovery from Blizzard font objects (WoW 12.0+ compatible — no more hardcoded broken paths)
- Fonts apply correctly to all bars including new bars created during combat (cached font system)
- Removed broken font registrations (2002, Morpheus, Skurri paths that no longer exist in TWW)
Names & Display
- Fixed names not showing on bars (dirty-check was skipping name updates when values unchanged)
- Fixed realm names showing on bars ("Player-Realm" now correctly stripped to "Player")
- Fixed special characters in names breaking color formatting (switched from string.format %s to concatenation)
- NickTag nickname support (Details-compatible — shows nicknames set in Details, configurable toggle)
Pets
- Merge Pet Damage option now only available on Classic/TBC/Wrath/MoP (toggle ON/OFF)
- Retail always merges pet damage (Blizzard's C_DamageMeter API pre-merges pets — cannot be separated)
- Classic: pet damage correctly merged into owner or shown separately depending on setting
Graph
- Graph v3: Premium visual redesign with layered glow effects, live pulse dot, gradient fills, bottom info bar
- Graph now reads data directly from the tracker (same data source as bars — fixes Retail SecretValue issue)
- Graph data buffer uses batch trim instead of repeated table.remove (performance fix)
Data Persistence
- Fixed damage data disappearing after combat ends (C_DamageMeter sync no longer zeroes out segment when API returns empty)
- Damage bars now persist between fights, only reset when new combat begins
Stability & Internals
- Removed all debug print() statements from production code (converted to Utils.Debug)
- Profile errors now show popup dialogs instead of chat messages
- Profile success messages removed (silent operation)
- Database nil guards: safe instance info lookup, timeline nil check
- Database timeline buffer uses batch trim (same as Graph)
- DetailWindow C_DamageMeter API calls wrapped in pcall (prevents errors on expired sessions)
- Font test FontString reused instead of leaking a new one each time
- Event registration wrapped in SafeRegisterEvent with debug logging on failure
- WotLK Reforged support (new TOC file, Interface: 30800)
- TOC versions updated to 2.2 across all game versions
Version 2.1
-------------
- Fixed window width/height not applying on login (ApplySettings now called after UI initialize)
- All font SetFont calls protected with pcall fallback (prevents broken text on invalid font paths)
Version 2.0
-------------
- Unified addon: Single folder supports Retail (12.0.1), Classic (1.15.8), TBC Anniversary (2.5.5), MoP Classic (5.5.3)
- Multi-TOC architecture with runtime API detection
- Retail WoW 12.0 support: C_DamageMeter API integration with Secret Values handling
- Real-time combat data display on Retail (renders directly from C_DamageMeter during combat)
- Fixed font, font size, and font flag changes not applying to bars
- Fixed Show Percent toggle not working
- Fixed Show Rank toggle not working
- Fixed graph not displaying data on Retail (now queries C_DamageMeter for totals)
- Fixed window scale not applying on reload (value saved but not rendered — reported on TBCA)
- Scale now saved per-character and re-applied in ApplySettings
- Fixed Current/Overall tabs both showing overall data
- Fixed combat timer stuck at 0:01
- Fixed left-click toggle window not working
- Fixed combat duration not accumulating across multiple combat phases
- Show Fight Duration toggle now works in status bar
- Separated DPS from Damage Done display (DPS shows per-second + percent, Damage Done shows total + DPS)
- Separated HPS from Healing Done display (same distinction)
- Fixed sorting not updating during combat (insertion sort with per-comparison pcall for secret values)
- Detail window opens on bar click with spell breakdown
- Mouseover tooltips on bars showing DPS/HPS and top abilities
- Graph anchors to main window instead of UIParent
- Graph collects data during combat even when hidden
- Isolated Ace3 libraries (-EDM suffix) for all clients
- Updated Twitch link to twitch.tv/JugoBetrugoTV
- Removed interface version from config display
- Performance: Rewrote Retail combat rendering to use GetCombatSessionFromType (1 API call for all players)
- Performance: Eliminated per-player roster building and per-GUID API queries (40→1 calls in BGs)
- Performance: Uses amountPerSecond from API for DPS/HPS (no manual division needed)
- Performance: Uses session.maxAmount + SetMinMaxValues for secret-safe bar proportions
- Performance: Spec icons from API (specIconID, NeverSecret) instead of generic class icons
- Performance: isLocalPlayer (NeverSecret) for player highlight instead of UnitName comparison
- Performance: Dirty-check rendering (skip GPU calls when bar data unchanged)
- Performance: Cached settings per update cycle (avoid per-bar profile lookups)
- Performance: Insertion sort for secret values during combat (per-comparison pcall)
- Performance: Roster cache with 3s TTL (avoid rebuilding raid roster every tick)
- Performance: Minimum 0.5s refresh rate clamp (prevents excessive update frequency)
- Performance: LayoutBars skip when bar count/scroll/height unchanged
- Performance: Color/texture updates only on class or rank change
- Performance: Name text updates only on actor name change
- Performance: Icon texture updates only on class change
- Performance: C_Timer polyfill, bit-lib compatibility, tainted value detection
Version 1.1.0
-------------
- Added multi-client support (Retail, Classic Era, MoP Remix)
- Interface versions: 110207 (Retail), 11508 (Classic), 50503 (MoP)
- Fixed Damage Taken mode to correctly show damage received
- Fixed DPS display calculations
- Improved click handler for damage bars
- Enhanced graph smoothing with Catmull-Rom spline interpolation
- Performance optimizations:
- Localized globals across all modules for faster lookups
- Added UI update throttling (100ms) to reduce CPU usage
- Implemented table reuse to reduce garbage collection
- Pre-computed bit masks for flag checks
- Added class color caching
Version 1.0.0
-------------
- Initial release
- Real-time damage and healing tracking
- Beautiful graph visualization with animations
- Skin system support
- Detail window with spell breakdown
- Minimap button integration
- Combat segment tracking

