promotional bannermobile promotional banner

Enemy List

A list of enemies, their target and the aggro on them as well as a unit grid for the raid.

File Details

EnemyList 1.8.185.zip

  • R
  • May 21, 2026
  • 356.89 KB
  • 42
  • 2.5.5
  • Classic TBC

File Name

EnemyList 1.8.185.zip

Supported Versions

  • 2.5.5

[1.8.185]

Changed — new shipped defaults

User supplied an EL1! share-string of their preferred configuration; merged into the central defaults table at the top of EnemyListUI.lua and embedded as the Default preset's encoded field in EnemyListPresets.lua. Fresh installs now boot into this configuration; users who run /el preset default get the same state.

Highlights of the new defaults (compared to the previous):

  • Compact single-column rows by default (compactRow = true, singleColumn = true).
  • Aggro/other rows capped at 2 each so the list is short by default (was 10).
  • Party frames on by default with vertical orientation, role icon, incoming heals, incoming rez, player buffs, low-HP / low-mana flash, debuff strip, and HP-deficit text all enabled.
  • HP bar on the left, mana bar on the right of party frames (vertical layout).
  • Unit name shown centered with -1/-10 offset and 0.6 font scale (small, mid-frame label).
  • Aggro count digit offset to -5 / -14 with a magenta-ish color (1, 0, 0.251) for visibility against the bar fill.
  • Nameplate list mirror on, threat overlay off (mirror is the bigger feature; threat color is opt-in).
  • Nameplate "2nd on threat" distinct color on.
  • Runner-up threat bar on with 2 slots (was off).
  • Predictive damage bar mode with 65 % alpha, height 8, position "left", bar color overridden to black so the segment reads as a "shadow" rather than competing with the HP fill.
  • predictiveShowPartyText = false (visual only, no minus-number text).

Position state (x, y, point, relPoint, minimapButtonAngle) intentionally kept neutral in both the central defaults and the Default preset — applying the preset on another character won't teleport the frame to the source character's coordinates.

EXPORT_SKIP updated to filter x, y, point, relPoint, minimapButtonAngle so any future /el export / share-string round-trip strips position state too.

Fixed — Profiles tab no scrollbar with many entries

The Profiles tab scroll-child used a static baseH = 260 estimate for content above the saved-profiles list. The actual content (title + intro + active label + group line + auto-switch + 4 buttons in 2 rows + saved header + saved hint + save-row) is closer to 330 px — so scroll-child height undercounted by ~70 px and the bottom of the cross-character snapshot list got clipped below the scrollable region (the scrollbar appeared to "stop early" because there was no scroll target beyond the calculated bottom).

Two-stage fix:

  1. Estimate refined: baseH is now measured from saveRow's actual on-screen GetTop() relative to scrollChild5's top, with a 330 px conservative fallback if positions aren't ready yet.
  2. Post-layout measurement: refreshCrossCharRows now applies the estimate immediately (so the scrollbar isn't zero between frames), then schedules a C_Timer.After(0, ...) callback that walks every visible child of scrollChild5, finds the lowest pixel any of them occupies, and sets the scroll-child height to span + 40 px bottom padding. Robust to any future additions to the tab — no more guess-and-pray height math.

[1.8.184]

Diagnostic — settings revert on /reload

User reported "checkbox settings revert every /reload" (specifically the role-icon checkbox on the Party tab). Code review found no obvious bug — every write path I traced should persist correctly through SavedVariables. To make the next round of debugging tractable, this release adds a diagnostic command + a defensive guard.

/el debugsave (new diagnostic command)

Prints the current saved-state of EnemyListDB to chat so you can see exactly what's in memory:

  • activeProfileName value.
  • Whether profiles table exists.
  • Whether profiles[active] slot exists.
  • For ~15 common boolean settings: top-level value, profile-slot value, and whether they match.

Run it before toggling a setting, after toggling, and after /reload — comparing the three outputs will pinpoint whether the issue is:

  • The write didn't happen (top-level still false after toggle),
  • The save didn't persist (was true after toggle, nil after reload),
  • A profile-load is wiping the change (top-level true after toggle, profile-slot still false, profile-load runs at reload and uses stale slot).

Defensive guard in profileWrite

Added a safety hatch: if a profileWrite updates an inactive profile's slot and the matching top-level value is nil, seed top-level from the active profile's slot so a subsequent save doesn't write nil for a key the user set. This is a no-op in the common case; it only kicks in when the write paths and active-profile state are out of sync (a class of corner case that's hard to repro from the code alone).

How to use

If the user can reproduce the revert, the most useful followup is to run /el debugsave at three points and paste the chat output:

  1. Right after toggling the offending setting (before any /reload).
  2. Right after the next /reload (before touching anything).
  3. After re-opening the config window (to see what state the widget read).

That sequence will tell us exactly which step is dropping the value, and the fix becomes targeted instead of speculative.


[1.8.183]

Added — share-by-string + built-in starter presets

Three intertwined features in one release.

1. Import / export share-strings

  • New format EL1!<base64-of-lua-source> — chat-pasteable, no special-character issues.
  • Encoded with a deterministic Lua-table serializer (stable key order, no functions / userdata) so the same settings always produce the same string.
  • Decoded via sandboxed loadstring + empty environment (no global access; can't call functions or touch the filesystem). Returns (table, nil) on success or (nil, err) on failure.
  • EnemyList.Presets.Apply(t) writes the decoded table onto EnemyListDB (respecting the export skip-set so user positions / per-character flags / debug state / profile machinery are never trampled) and cascades every relevant live-refresh helper so the UI updates without a reload.

2. Built-in starter presets

  • New module file EnemyListPresets.lua. Ships with five starters: Default, Healer, Tank, DPS, Minimal. Each entry is just { id, name, description, settings = { … } } — adding a preset is a single table entry.
  • Entries can also use encoded = "EL1!…" instead of a raw settings table. The author can mass-add presets by chat-pasting their /el export string into a new encoded = field.
  • EnemyList.Presets.GetById(id) resolves either form (decodes lazily, caches the result).

3. New Presets config tab (#12)

  • New file EnemyListConfigTabPresets.lua adds tab Presets to the config window's nav.
  • Layout: title + description, Built-in presets list (one row per preset with name + description + Apply button), Import section (multi-line scroll edit-box → Apply pasted button + status text), Export section (Generate button fills an edit-box you can select-all + copy).
  • Apply asks for confirmation via StaticPopup so a misclick doesn't nuke the user's tuning.

Added — setup wizard quick-start preset row

  • New section on page 1 of the setup wizard between "Copy from another character" and the layout chooser. Up to 5 compact preset buttons (one per built-in preset) with hover-tooltips showing the preset's description. Click → apply → refresh every wizard widget so the user can preview before committing.
  • Frame height grew 620 → 680 px to fit the new row.

Added — slash commands

  • /el export — prints current settings as an EL1! string (chat-copyable).
  • /el exportlua — prints current settings as a raw Lua-table source. Used for adding new built-in presets to the file: configure the addon however you like, run /el exportlua, paste the chat output into a new BUILTIN[#BUILTIN + 1] = { id = "...", name = "...", description = "...", settings = <paste here> } entry. Same form is paste-able into the central defaults table if the author wants to ship updated defaults.
  • /el import <EL1!...> — applies a share-string in-place from chat.
  • /el preset <id> — applies a built-in preset by id. /el preset or /el preset list shows the available ids.

Locale

  • 23 new strings — tab title, section headers / hints, every confirmation / status message, slash-command hints, wizard preset header / hint.

Implementation

  • All persistence goes through the existing EnemyListDB + EnemyListDB.profiles[activeProfileName] writes, so a preset survives the next auto-switch between Party / Raid.
  • Decoder uses setfenv(fn, {}) so a malicious string can't read globals or call functions. Worst case a hostile string can construct a (huge) table to DoS the client; same threat surface as every other share-string addon (WeakAuras, ElvUI profiles, etc.).
  • Configurable export filter (EXPORT_SKIP) so user-positioning data (window XY, frame width/height), per-character flags (setupWizardCompleted, testMode, minimapButtonHidden), debug state, and the recursive profiles table are never included.
  • gridLayout IS exported (it's a layout setting, not state) so preset authors can ship a custom grid-element arrangement as part of a preset.

For future maintenance

To update the default settings later: configure the addon how you want defaults to be, run /el exportlua in chat, copy the printed table, and either:

  • Replace the settings = { } block in the "Default" preset entry in EnemyListPresets.lua (recommended — keeps the addon's central defaults clean and gives users a one-click "factory reset" path), or
  • Paste each key-value into the central defaults = { ... } table at the top of EnemyListUI.lua if you want them to be the hard-coded defaults for fresh installs that don't run the setup wizard.