Skip to content

Repository files navigation

EllesmereUI - Moonfire Tracker (EllesmereUIMoonfire)

A small, combat-safe companion addon for World of Warcraft Retail — Midnight 12.1.x (Interface 120100, Lua 5.1) that shows, on every applicable hostile EllesmereUI nameplate, whether your Druid's Moonfire is currently active.

RED            = my Moonfire needs applying
Moonfire icon  = my Moonfire is active  (Blizzard covers the red)

It integrates with EllesmereUI's integrated nameplates and reuses EllesmereUI's 12.1 AuraKit managed-AuraContainer engine. It does not modify EllesmereUI and does not replace or duplicate the nameplates.

Screenshots

Moonfire not applied Moonfire active
Nameplate showing the red "needs Moonfire" indicator Nameplate showing the managed Moonfire icon covering the red

Left: the static RED indicator sits left of the health bar — my Moonfire is not on the target. Right: Blizzard's managed Moonfire icon is rendered over the red because my Moonfire matches. No addon Lua reads or decides the state.


The one idea that makes this legal under 12.1

WoW 12.1 makes enemy aura state secret during restricted content (Mythic+, raid, combat, PvP). Ordinary addon Lua therefore must not decide hasMoonfire = true/false.

So this addon never decides. Instead:

  • A static RED background is always present under the indicator for an applicable enemy plate. It does not mean "Lua detected missing".
  • A Blizzard-managed AuraContainer slot sits on top of the red. Its filter string (HARMFUL | PLAYER) and Moonfire spell-id candidate list are evaluated by Blizzard in C. When — and only when — your Moonfire matches, Blizzard renders the opaque Moonfire icon, which physically covers the red.

No addon code changes between the two states, and nothing in Lua is ever told the result. If normal addon Lua could answer "does nameplate5 have my Moonfire?", the design would be wrong — and it can't.

EllesmereUI nameplate
      │
      └── EllesmereUIMoonfire holder  (left of the health bar)
               ├── static RED background        ← always shown
               └── EllesmereUI.AuraKit container
                        └── one AuraSlot
                             filter          = HARMFUL | PLAYER   (C-evaluated, secret-safe)
                             includeSpellIDs = { 164812, 155625, 8921 }
                             style           = "EllesmereUIMoonfire" (icon + purple border, click-off)
                        → Blizzard shows the Moonfire icon over RED on a match; else RED shows.

Analysis of EllesmereUI (integration points actually used)

Determined by reading the EllesmereGaming/EllesmereUI source, not from assumptions. Source column paths and line numbers are repo-relative (branch main).

# Finding Source
1 Nameplates are a manager frame handling NAME_PLATE_UNIT_ADDED/REMOVED; attackable units get a pooled plate frame. EllesmereUINameplates/EllesmereUINameplates.lua (manager, ~L8038, L8272)
2 Enemy plates are pooled Frames from frameCache, mixed with NameplateFrame. same, frameCache L2489
3 ns.plates[unitToken] = plate — keyed by unit token. L8328
4 _G.EllesmereNameplates_NS = ns exposes ns.plates; _G.EllesmereUI is a real global. L68 / EllesmereUI.lua L1435
5 Anchor target: plate.health (a StatusBar, SetClipsChildren(false)). No plate-creation callback API is exported. L2491
6–8 EllesmereUI.AuraKit wraps Blizzard's CustomAuraContainerTemplate. AK.CreateContainer(parent, unit, spec) builds a shell, adds slots/groups, then SetUnit+UpdateAllAuras last. AK.AddSlotToContainercontainer:AddAuraSlot(key, AK.Filter(...), { candidateFilters, initializeFrame }). EllesmereUI_AuraKit.lua L1232, L1253
9–10 Ownership/polarity live in the filter string (C-evaluated); spell narrowing lives in candidateFilters = { includeSpellIDs = {...} }. EllesmereUI's own player-owned nameplate group uses filter = { "HARMFUL", "PLAYER", ... } + includeSpellIDs. Never a Lua sourceUnit check. EUI_Nameplates_AuraContainers.lua L815, comment L878
11–12 AK.MakeInitializer decorates the button in the engine's initializeFrame window and calls pcall(button.SetMouseClickEnabled, button, false) for non-cancel styles — the nameplate click-through mechanism. Child regions are EnableMouse(false). EllesmereUI_AuraKit.lua L867, L947
13 Plate frames and aura bundles are pooled; containers are never destroyed, only re-SetUnit. L1389 / L1431
14 There is no exported "attach my own managed aura display" API and no plate lifecycle callback — so we use the standard NAME_PLATE_UNIT_* events + ns.plates.
15 AuraKit is reachable (EllesmereUI.AuraKit) and AK.styles is a plain table, so a companion addon can use it. It is EllesmereUI-internal, not a documented stable contract, and depends on EllesmereUI module state (EllesmereUI.PP, fonts). We therefore use it defensively: feature-detect every function, pcall engine calls, register our own style key, and stay dormant if anything is missing. file header L2–6

Why use AuraKit rather than raw Blizzard APIs: it already solves the hard 12.1 problems — click-through on managed buttons, secret-value-safe styling, duration binding, and combat-legal creation. Re-implementing it would duplicate a large amount of safety code and is explicitly discouraged by the source.


Verified Moonfire aura IDs

The candidate filter needs the debuff aura id that appears on the target, not the cast spell id.

ID Meaning Why included
164812 Moonfire (Spell Power version) Balance / Guardian / Restoration DoT applied to the target. Confirmed on Wowhead: "burns the enemy for (…% of Spell Power) Arcane damage … over 18 sec … Generates Astral Power".
155625 Moonfire (Attack Power version) Feral cat-form Moonfire via the Lunar Inspiration talent. Confirmed: "(…% of Attack Power) Arcane damage over 18 sec. Awards 1 combo point."
8921 Moonfire base/cast spell id Harmless fallback. If the live target aura is one of the two above it simply never matches; costs nothing.

Because Blizzard evaluates HARMFUL | PLAYER in C, another Druid's Moonfire can never light your indicator — only your own. Talents that apply Moonfire to several targets at once light each of their plates independently, because each plate has its own managed container.


Files

EllesmereUIMoonfire/
├── EllesmereUIMoonfire.toc   Interface 120100, RequiredDeps EllesmereUI + EllesmereUINameplates
├── Core.lua                namespace, SavedVariables, Druid gate, deps, slash commands, debug
├── MoonfireAura.lua        AuraKit style + managed Moonfire container/slot builder
├── Nameplates.lua          plate lifecycle, widget pool, static RED indicator, attach/detach
└── README.md
  • Druid only: at login UnitClass("player") is checked; a non-Druid stays fully dormant (the nameplate system is never created).
  • Hostile only: attaches only where UnitCanAttack("player", unit) and the unit is not the player. UNIT_FACTION is watched so mid-fight faction / mind control transitions attach or detach correctly.
  • Recycling-safe: per-plate widgets live in a weak-keyed (__mode="k") external table keyed by the pooled plate frame; no custom fields are written onto EllesmereUI/Blizzard frames. Unit→plate mappings hold frame refs and tokens only — never aura or combat state.

SavedVariables (EllesmereUIMoonfireDB) — configuration only

EllesmereUIMoonfireDB = {
    enabled       = true,
    indicator     = { size = 18, x = -4, y = 0 },  -- x negative = further left of the health bar
    missingColour = { r = 1, g = 0, b = 0, a = 1 }, -- the static RED
    purpleBorder  = true,   -- managed purple border around the Moonfire icon
    showDuration  = true,   -- Blizzard-rendered, secret-safe countdown on the icon
    debug         = false,
}

No GUIDs, Moonfire targets, aura state, expiration times, combat state or enemy databases are ever stored.


Slash commands

/emf              show status
/emf help         command list
/emf enable       enable the tracker
/emf disable      disable the tracker
/emf debug        toggle debug messages
/emf reset        restore default settings
/emf size <n>     indicator size in px
/emf x <n>        indicator X offset
/emf y <n>        indicator Y offset

Debug output is limited to lifecycle facts (NAME_PLATE_UNIT_ADDED/REMOVED, "presentation attached/recycled", dependency detection). It never prints aura state, managed-button visibility or durations.


Test procedures

Run all testing with client script errors visible:

/console scriptErrors 1

1. Training dummy (baseline)

  1. Log in on a Druid. /emf should report enabled (running) and detect EllesmereUI / EllesmereUINameplates / AuraKit (enable /emf debug to see the detection lines).
  2. Target a training dummy — its EllesmereUI plate should show a small RED square just left of the health bar.
  3. Cast Moonfire. The RED must be replaced by the Moonfire icon (with the purple border and, if enabled, a countdown). This transition is produced by Blizzard, not by addon Lua.
  4. Let Moonfire expire → the icon disappears and RED returns.
  5. Confirm you can still click the dummy's plate to target it while the icon is shown (click-through).
  6. Verify no Lua errors.

2. Multiple enemies / open world

  1. Pull several enemies. Each attackable plate gets its own indicator.
  2. Moonfire a few of them — only those show the icon; the rest stay RED.
  3. Move so plates recycle (walk away / back). Indicators must follow the correct units, never "stick" to the wrong enemy (relies on plate pooling + weak-keyed widgets).

3. Mythic+ (mandatory)

  1. Enter a key; /emf debug on for the first pull if you want lifecycle traces.
  2. On a large pull (10–20+ plates) confirm:
    • EllesmereUI nameplates keep working normally;
    • RED / Moonfire icon state is correct in combat;
    • multi-target Moonfire lights each affected plate;
    • expiry returns plates to RED;
    • clicking / target-switching / mouseover / camera all behave normally;
    • no "secret value" / forbidden-object errors, no taint, no blocked-action popups, no measurable FPS impact.
  3. Have a second Druid in the group apply Moonfire to a mob you have not Moonfired → it must stay RED for you. Apply yours → icon appears.

4. Raid encounter (mandatory)

Repeat the Mythic+ checks during a real raid boss encounter. Do not consider the feature complete just because it works on a dummy or out of combat.


What WoW 12.1 does and does not allow here

  • Allowed / how it works: presence of your Moonfire is shown purely by Blizzard's managed AuraContainer painting an icon over a static background. The countdown (when enabled) is a Blizzard duration binding — rendered by the engine, never read by Lua.
  • Deliberately impossible: the addon cannot, and does not, tell you in Lua whether a given enemy has your Moonfire. It uses no UnitAura / C_UnitAuras / AuraUtil, no combat log, no target database, no OnUpdate polling, and never inspects the managed button (IsShown/GetAlpha/OnShow etc.). This is a design guarantee, not a limitation to work around.
  • Known minor limitation: changing /emf size during restricted combat resizes the RED background immediately while the managed icon is resized asynchronously (AuraKit defers button geometry until the aura restriction lifts). A brief red rim can appear until then. Resize out of combat to avoid it.
  • Pandemic display: Blizzard's managed system exposes no secret-safe pandemic/refresh-window signal to addons, so a Lua-driven pandemic recolour would require reading the (secret) remaining duration and is intentionally not implemented. If a future Blizzard build adds an engine-side pandemic curve to the duration binding, it could be wired into the style's duration colour without ever exposing the value to Lua.

Code-review checklist

Question Answer
Does normal addon Lua determine whether Moonfire is active? NO
Does it scan enemy auras? NO
Does it query managed AuraButton visibility? NO
Does it use combat-log reconstruction? NO
Does it maintain a Moonfire target database? NO
Does Blizzard's managed AuraContainer make the aura decision? YES
Does it reuse EllesmereUI's actual 12.1 implementation where appropriate? YES
Was that implementation determined from the EllesmereUI source? YES
Does it integrate with EllesmereUI rather than replacing the nameplates? YES
Is all code Lua 5.1 compatible? YES

Version 0.1.0 · Requires EllesmereUI + EllesmereUINameplates.

About

Combat-safe Moonfire status indicator for EllesmereUI nameplates (Druid)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages