promotional bannermobile promotional banner

DodoNameplate

Category-based nameplates with threat colors, cast bar, and a secret-safe enemy aura row, built for Midnight (12.0).

File Details

v0.8.1

  • R
  • Jun 25, 2026
  • 39.26 KB
  • 8
  • 12.0.7
  • Retail

File Name

DodoNameplate-v0.8.1.zip

Supported Versions

  • 12.0.7

DodoNameplate

v0.8.1 (2026-06-25)

Full Changelog Previous Releases

  • Bump version to 0.8.1 (enemy debuff Blizzard-match)
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Hard-wire enemy debuff Blizzard-match (remove mineBlizzard toggle)
    Per request the 'my debuffs' row always mirrors Blizzard's curated set; removed the mineBlizzard config field, the /dnp sub-toggle, and its locale keys. BlizzardDebuffSet still falls back to showing all my debuffs when Blizzard's frame is unavailable.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Match Blizzard's curated enemy debuff set (mineBlizzard)
    The 'my debuffs' row now mirrors exactly what Blizzard's default nameplate shows (e.g. an Unholy DK's 2 diseases) instead of every player-cast debuff. Blizzard's curation flag (nameplateShowPersonal) is secret in instances and INCLUDE_NAME_PLATE_ONLY/isNameplateOnly don't reproduce it, so Auras.lua BlizzardDebuffSet() reads auraInstanceIDs (NeverSecret) off Blizzard's own DebuffListFrame:GetLayoutChildren() and intersects with our list -- the same approach Plater uses on Midnight. Gated by ns.db.auras.mineBlizzard (default on) with a /dnp sub-toggle (en/zh). CC and important(RAID) rows untouched. GOTCHAS S3 documents the mechanism + the two dead ends.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Update PENDING-WORK: CurseForge release + packager status, purge/defensive shipped (untested), emphasis idea shelved
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Add CurseForge packager workflow (GitHub push -> auto-publish)
    release.yml uses BigWigsMods/packager on tag push; .toc gains X-Curse-Project-ID 1587138 so the packager uploads to the right CurseForge project. Ignore list comes from .pkgmeta.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Release prep for CurseForge + enemy buff categories (purgeable / defensive)
    Auras: add a below-bar enemy buff row that routes HELPFUL into purgeable (purple, gated on a client-side player-can-purge check), defensive (white, enemy players only), and generic (green), all via secret-safe Blizzard category filters. Core: per-class purge-spell gate (ns.playerCanPurge) refreshed on login/spec/spell change, plus buff-row defaults. Options + Locale: two new aura toggles (en/zh).
    Release hygiene: public-facing README rewrite, LICENSE (All Rights Reserved), .pkgmeta to strip internal dev docs from the packaged zip, .toc X-License + Notes-zhCN.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • v0.8.0: enemy aura row + config panel, friendly forbidden-plate fix, name-in-bar, PvP base, icon, baked defaults
    Aura row (Auras.lua, groups 5+6): secret-safe category icons mirroring Blizzard (my debuffs / shared CC / important debuffs) via the C_UnitAuras filter path; Blizzard C-side countdown number; shared ns.db.auras + a dedicated Auras sub-page. Per-spellID aura curation is dead under Secret Values. Friendly party/raid plates in PvE instances are forbidden frames -> skipped cleanly (no taint, clean Blizzard default; GOTCHAS S2). Enemy/mob name moved inside the bar (auto-sized). Phase 2 PvP base: enemy-player nameplates (class color + cast bar); cast path hardened for secret names. Addon icon (Media/Dodo.tga); Jerry's live config baked as shipped defaults; language default = English.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • v0.7.1: target arrows, raid-marker instance fix, uninterruptible stripe, elite inside bar
    • Raid target marker centered ABOVE the bar (global size) + FIXED for instances: GetRaidTargetIndex
      is SECRET there -> feed it to the SetRaidTargetIconTexture sink AND pre-set the base raid-icons
      texture (the sink only sets the texcoord). Was being hidden by an IsSecret guard before.
    • Elite/rare icon moved INSIDE the bar (left), auto-sized to the bar height.
    • Uninterruptible ("steel") casts: a tiled gray diagonal-stripe overlay over the fill, below the
      cast text, gated by SetAlphaFromBoolean(notInterruptible). New asset Media/stripe.tga.
    • Cast spell icon sized to the cast bar height.
    • Current-target indicator: two white triangles flanking the bar (size tracks bar height). New
      asset Media/arrow.tga (right-pointing; right side mirrored via SetTexCoord).
    • /dnp test prints raid-mark + plate-mark diagnostics. Added .gitattributes (*.tga binary).
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • v0.7.0: important-cast health recolor, options i18n, per-group cast config, cast-target bar
    • Important casts (hostile) recolor the health bar (default white, configurable) via
      EvaluateColorValueFromBoolean -- secret-safe, works in instances; reverts on cast stop.
    • Options panel is bilingual (en/zh): Locale.lua + ns.L + ns.ApplyLocale; language radio on
      the General page (applies after /reload).
    • All cast-bar settings decoupled per-group (height / text size / colors); cast bar width
      follows the healthbar. Old global cast settings migrated into each group block.
    • Important cast simplified to a clean right-to-left reverse-fill bar (glow + gold-border
      emphasis removed); cast width is no longer configurable.
    • Cast-target bar (hostile): solid class-colored bar + centered target name below the cast
      bar (Midnight UnitSpellTargetName/Class give name+class only, no health). Class color when
      available, else a configurable color.
    • Per-group cast text size; spell name stays left-aligned.
    • Defaults rebaselined to the current live config so a fresh install matches.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • docs: refresh CLAUDE/README/PENDING for current state (Phase 1 implemented, v0.6.2)
    Update the entry router + front page + TODO to reflect that Phase 1 is built (not blueprint-only): code layout, HOME-machine dev workflow, current feature set, and remaining/dropped items. Handoff for a fresh session.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Two-bar reverse-fill: R->L important casts work in instances (v0.6.2)
    Cast bar is now a container Frame with two overlapping fills (forward + reverse). Both get the same SetTimerDuration; the visible one is chosen by SetAlphaFromBoolean(important) -- secret-safe, so important casts fill right-to-left even in instances where spellID is secret. Icon/text/time/target/shield on an overlay above the fills.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Important cast: brighter glow + gold border; confirm spellID secret in instances (v0.6.1)
    Field test (Magisters' Terrace Polymorph): color applied but no R->L flip -> spellID/IsSpellImportant is secret in 12.0.7 instances (SetReverseFill guard skipped). Boosted prominence secret-safely: 7px additive glow + bright gold border on important (EvaluateColorValueFromBoolean). Two-bar reverse-fill trick noted as the way to also flip direction in instances.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Important (golden) casts: color + reverse fill + glow via C_Spell.IsSpellImportant (v0.6.0)
    • C_Spell.IsSpellImportant(spellID) drives the cast bar. Color via C_CurveUtil.EvaluateColorValueFromBoolean (secret-safe); optional glow via SetAlphaFromBoolean; right-to-left fill via SetReverseFill (guarded with issecretvalue, since SetReverseFill is not a secret-safe sink -> flips only where the flag is readable).
    • Normal cast = gold L->R; important = orange + glow + R->L. Options: General > Cast bar (important color + glow toggle).
    • GOTCHAS S3 documents C_Spell.IsSpellImportant.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Drop health amount (keep percent); move level to bar top-right (v0.5.3)
    • Removed all health-amount display (can't K/M-abbreviate under secret); only the percent stays in-bar.
    • Level moved to the bar's top-right (mirrors name top-left), leaving below-bar clear for the cast bar.
    • Options: 'Health text size' -> 'Percent size'.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • docs(GOTCHAS): absolute HP amount unreadable in combat even via newest API
    Researched Plater HEAD (2026-06-20), ThreatPlates feature/midnight, and DetailsFramework unitframe_midnight.lua. The heal-prediction calculator's :GetCurrentHealth() is still secret (only fed to bar sinks); Plater's in-combat abbreviation is still --TODO: MIDNIGHT!!. So K/M abbreviation in combat is not achievable; only percent is readable (via curve). Documented in S2/S3.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Percent: separate static % sign + integer step curve (v0.5.2)
    On 12.0.7 UnitHealthPercent(...,curve) returns a secret -> could only sink it (no % sign, decimals). Now: '%' is a separate static FontString next to the number; the curve is a 0-100 integer step curve so the secret value renders with no decimals. Amount stays raw where health is secret (math blocked).
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Health text: robust percent + K/M abbrev + per-group font sizes (v0.5.1)
    • Percent: direct math -> ScaleTo100 curve -> raw sink (was blank on restricted maps where health is always secret).
    • Amount: custom K/M/B abbreviation (locale AbbreviateNumbers is 万/亿 on zhCN); raw when secret.
    • Per-group font sizes for name / level / health text (sliders on each group sub-page).
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Healthbar text: name(left), level(below-right), HP amount+percent (v0.5.0)
    • Name left-aligned above the bar; level below-right (hidden for friendly NPCs; ?? for boss).
    • HP amount (left, inside) via SetText sink + AbbreviateNumbers when readable; HP percent (right, inside) via UnitHealthPercent(unit,true,CurveConstants.ScaleTo100) -> plain 0-100, the secret-safe path.
    • Refresh name/level on UNIT_NAME_UPDATE / UNIT_LEVEL; health text on UNIT_HEALTH/MAXHEALTH.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Neutral creatures: yellow until engaged, then threat colors (v0.4.2)
    Neutral (UnitReaction == 4) hostile-group creatures show the reaction yellow until you have a threat relationship (UnitThreatSituation non-nil), then switch to the hostile red/blue. Recolors via the existing UNIT_THREAT_* events. Dungeon-validated.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Fix Unknown nameplate name (UNIT_NAME_UPDATE); critter-hide default off (v0.4.1)
    • Name could show UNKNOWNOBJECT when UnitName was not loaded at plate-add; refresh on UNIT_NAME_UPDATE.
    • overlays.hideCritter default -> false (the 'minus' classification test also hid small trivial mobs).
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Elite/rare borders, cast countdown + target, focus highlight (v0.4.0)
    • Classification borders via UnitClassification: gold (elite/boss), silver (rare), black (normal) + elite-dragon atlas icon when available. Unified border priority: target(white) > focus(cyan) > elite(gold)/rare(silver) > normal.
    • Cast bar: right-aligned countdown (duration:GetRemainingDuration, secret-guarded) + cast-target name (UnitSpellTargetName).
    • Focus highlight: cyan border on the focus plate (C_NamePlate frame compare, PLAYER_FOCUS_CHANGED).
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Healthbar/castbar: flat solid fill texture (WHITE8X8)
    Swap the gradient Blizzard UI-StatusBar for a flat white texture so vertex-colored fills render as a clean solid color across all groups.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • All PvE groups + overlays + per-group option sub-pages (v0.3.0)
    • Config -> per-group blocks ns.db.groups[2..5] (migrates old 'hostile' block to groups[5]); global targetScale/castHeight/overlays/threat colors.
    • Plate.lua styles ANY enabled group; color per group: hostile=threat red/blue, party/other players=class color (UnitClassBase+GetClassColor), friendly NPC=reaction (UnitSelectionColor). Disabled = hands off (Blizzard default).
    • Overlays: dim tapped (UnitIsTapDenied), hide critters (UnitClassification 'minus').
    • Options split into Blizzard sub-pages: General + one canvas sub-category per group via Settings.RegisterCanvasLayoutSubcategory. Default: only Hostile enabled.
    • Self(1)=Blizzard personal bar (self-detect secret); enemy player(6)=Phase 2.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Options: drop manual category.ID (use auto ID for OpenToCategory)
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Options: move into Blizzard settings UI (canvas category)
    • Replace the standalone /dnp window with Settings.RegisterCanvasLayoutCategory -> Esc > Options > AddOns > DodoNameplate. Canvas (not vertical-layout list) keeps the color pickers + sections; controls reused unchanged.
    • /dnp now calls Settings.OpenToCategory to jump straight to the page.
    • Registered at PLAYER_LOGIN via ns.InitOptions() (Core calls it once ns.db is ready).
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Add options panel + config-driven rendering (v0.2.0)
    • SavedVariables DodoNameplateDB + ns.defaults (merged at login). Plate.lua reads sizes/colors/toggles from ns.db; Style.RefreshAll re-applies to open plates.
    • Standalone /dnp options panel (Esc-close, draggable; no Settings-API/template dependency). Hand-rolled checkbox/slider/color-swatch (ColorPickerFrame:SetupColorPickerAndShow).
    • Exposed (hostile): healthbar width/height, name size + show, cast-bar show, target scale, and the two threat colors.
    • /dnp opens options; /dnp test = classification probe.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Group 5: add cast bar (spell name/icon, timer, interrupt shield)
    Restores the hostile cast bars that hiding the Blizzard plate had removed.
    • Own cast bar below the healthbar (child of our frame, scales with target highlight).
    • Progress via UnitCastingDuration/UnitChannelDuration -> StatusBar:SetTimerDuration (C-side; casts fill, channels drain). No OnUpdate.
    • Spell name + icon read raw (not secret on Midnight). Interrupt shield via SetAlphaFromBoolean(notInterruptible) (may be secret); INTERRUPTIBLE/NOT_INTERRUPTIBLE toggle it live.
    • Core: register the UNIT_SPELLCAST_* family.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Group 5: target highlight + scale, raid marker, locale font fix
    • Name font -> STANDARD_TEXT_FONT (fixes CJK names showing as tofu boxes).
    • Target highlight: current target's hostile plate scales up + white border; detected via C_NamePlate.GetNamePlateForUnit("target") frame compare (not the secret UnitIsUnit).
    • Raid target marker via GetRaidTargetIndex + SetRaidTargetIconTexture.
    • Core: add PLAYER_TARGET_CHANGED + RAID_TARGET_UPDATE.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Phase 1 step 4-6 (group 5): replace hostile plate, threat-state color
    Hostile (group 5) plates now use our own healthbar + name instead of the Blizzard default.
    • Plate.lua (ns.Style): hide Blizzard UnitFrame (SetAlpha 0 + keep-hidden hooksecurefunc with a recursion lock, mirroring ThreatPlates); custom StatusBar healthbar + always-on name parented to the plate base frame.
    • Health via secret-safe SetMinMaxValues/SetValue; color via GetStatusBarTexture():SetVertexColor (the Midnight way). Role-aware threat color: red = normal for your role, blue = warning (guarded UnitThreatSituation + GetSpecializationRole).
    • Core.lua: drives styling; adds UNIT_HEALTH/MAXHEALTH, UNIT_THREAT_*, PLAYER_SPECIALIZATION_CHANGED; caches role; /dnp shows role.
    • Other groups still Blizzard default; hostile cast bars hidden until step 7.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • docs: log 2026-06-20 decisions; mark skeleton steps 1-3 done
    • Threat-state bar color (red normal / blue warning, role-aware) replaces the health-% gradient for group 5.
    • Plater-default look baseline; Blizzard default font/texture; hostile names always shown; options grouped by section; no minimap icon.
    • DESIGN S2/S3 updated; SESSION-LOG Part A decision + Part B narrative; PENDING steps 1-3 removed (done), step 4+ refreshed; reference now points at the local Plater install.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Phase 1: PvE skeleton (steps 1-3)
    Loadable addon that classifies nameplates into the 6 identity groups. No reskin yet.
    • DodoNameplate.toc: Interface 120007; loads Guards -> Classification -> Core.
    • Guards.lua: issecretvalue/canaccessvalue shim + Bool()/UnitIsUnit() that force false on a secret (mirrors Plater).
    • Classification.lua: ns.Classify(unit) -> group 1-6 via UnitIsPlayer/UnitCanAttack/UnitInParty-Raid; ns.IsTapped overlay.
    • Core.lua: NAME_PLATE_UNIT_ADDED/REMOVED/CREATED + UNIT_FACTION/UNIT_FLAGS hooks; re-classify on flip; /dnp prints the target's group.
      Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Fix addon name spelling: DodoNamplate -> DodoNameplate
    Repo renamed on GitHub to DodoNameplate; update all in-doc references
    (titles, install path, planned .toc/.lua names) to match. Docs-only.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
  • Scaffold DodoNamplate design blueprint (docs only, no code)
    WoW Retail nameplate addon for Midnight 12.0.7. Captures the verified design
    (6 groups + 2 overlays + state layer) and the Secret Values API constraints +
    guard patterns, as a self-contained context handoff for building elsewhere.
    Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com