Skip to content

Add Boss Frames (portrait, HP/power/cast/auras, per-mode settings)#39

Open
Timikana wants to merge 2 commits into
DanderBot:mainfrom
Timikana:feature/boss-frames
Open

Add Boss Frames (portrait, HP/power/cast/auras, per-mode settings)#39
Timikana wants to merge 2 commits into
DanderBot:mainfrom
Timikana:feature/boss-frames

Conversation

@Timikana
Copy link
Copy Markdown

@Timikana Timikana commented Apr 23, 2026

Adds a replacement for Blizzard's default boss target frames, with a full native GUI category and per-mode (Party / Raid) settings.

What it adds

A new top-level Boss Frames category in the options GUI with 5 sub-pages (Layout, Bars, Cast Bar, Text, Auras). Settings are split per mode, and a Copy from other mode button is provided.

Area What
Portrait 2D Blizzard-style face icon; left / right / hidden; thin border
Health Reaction color (red/yellow/green), Class color, or Static; background alpha; LSM texture
Power Height, texture, background alpha; auto-hides when unit has no power
Cast bar Integrated below the power bar, or detached relative to each frame (anchor + X/Y + custom width); icon left/right; LSM texture; spark anchored to StatusBar texture
Text 9-point anchor + X/Y offsets + name max length for name, health text, power text, raid target icon, auras
Raid target icon 9-point anchor + size + alpha (centered by default)
Auras 1-8 icons, cooldown swipe, stack count, countdown text (inside/below/above), source filter (All / Mine / Hide mine / Boss-cast only), harmful/helpful
Test Integrated with the global Test button; dedicated Boss section in the test panel with Boss Count slider + per-feature toggles
Mover Integrated with global Unlock; standalone `/dfbf` slash commands as fallback

Settings are stored in a new `DandersFramesDB_v2.boss.{party,raid}` block with automatic migration from any pre-existing flat `boss` table.

Module layout

File Role
`Frames/Boss.lua` Core frames, HP/power, portrait, mover, test mode (HP drain + simulated casts)
`Frames/BossCastBar.lua` Cast bar with `UNIT_SPELLCAST_*` events
`Frames/BossAuras.lua` Pooled aura icons with source filter
`Frames/BossOptionsGUI.lua` Integrates with the existing `SetupGUIPages` flow via `DF:SetupBossPages`
`Frames/BossOptions.lua` Standalone `/dfbf config` panel fallback

TOC adds them after `Frames/Pets.lua`. `Options/Options.lua` gets a one-line hook (`if DF.SetupBossPages then DF:SetupBossPages(GUI, CreateCategory, CreateSubTab, BuildPage) end`) and `boss` added to `CategoryOrder`. `TestMode/TestMode.lua` gets a new "Boss Frames" section. `enUS.lua` gets new keys in the `--@do-not-package@` block so the BigWigs Packager `-S` flag uploads them to CurseForge localization.

WoW 12.0 / Midnight secret-value handling

Retail Midnight now returns secret values from a lot of unit APIs for hostile / boss units. I've gone through every read of:

`UnitHealth`, `UnitPower`, `UnitPowerMax`, `UnitName`, `UnitCastingInfo`, `UnitChannelInfo`, `UnitIsUnit`, `GetRaidTargetIndex`, `aura.sourceUnit`, `aura.isBossAura`, `aura.applications`, `aura.expirationTime` — all guarded with `pcall` and appropriate fallbacks.

Notable workarounds:

  • Cast bar animates via `SetValue(GetTime()*1000)` against secret min/max (StatusBar clamps internally). Spark is anchored to the StatusBar texture's right edge so it follows the fill without any arithmetic.
  • Power text falls back to "visual percent" computed from `GetStatusBarTexture():GetWidth() / GetWidth()` when `UnitPower` arithmetic is blocked.
  • Frame visibility uses `RegisterStateDriver` (`[@bossn,exists]show;hide`), so new bosses appear even when they engage mid-combat (Show/Hide on a SecureUnitButton is otherwise blocked in combat).

Combat safety

`ApplyLayout` (which does `SetSize`/`SetPoint`/`SetScale` on secure frames) is gated on `InCombatLockdown`; it sets a `_pendingLayout` flag and replays on `PLAYER_REGEN_ENABLED`. Hooks on `DF:ToggleTestMode`, `DF:UnlockFrames`, `DF:LockFrames`, `DF:UnlockRaidFrames`, `DF:LockRaidFrames`, and `DF.GUI:RefreshCurrentPage` are installed lazily once the GUI is built.

Proposal for follow-up (not in this PR)

If `IsInRaid()` flips Party↔Raid mid-combat (e.g. a 6th player joins), the group watcher currently calls `RefreshAll` which triggers `ApplyLayout` and hits the `_pendingLayout` path. Extending the group watcher to check `InCombatLockdown` explicitly and set `_pendingLayout` without calling `RefreshAll` would be a ~3 line change and would avoid any redundant non-secure work during combat. Happy to add it if you'd like, or leave it to you.

Test plan

  • `/dfbf test 5` — 5 simulated bosses with HP drain, fake casts, raid target icons, debuff stacks climbing 1→40
  • Tested live in a raid: HP / mana (when present) / cast bar / auras / raid icon all update; no secret-value errors
  • Party ↔ Raid tab switch re-applies each mode's position/size independently
  • Global Test button activates boss test + party/raid test together
  • Global Unlock button unlocks boss mover + party/raid frames together
  • Name truncation (default 16 chars, 0 = off)
  • Translations work: all new strings registered in `enUS.lua` `--@do-not-package@` block

Timikana added 2 commits April 23, 2026 13:46
New top-level category in the options GUI ("Boss Frames") with 5 sub-pages
(Layout, Bars, Cast Bar, Text, Auras). Settings are split per mode (Party
and Raid) with a "Copy from other mode" button. Integrates with the global
Test and Unlock buttons.

Module layout:
- Frames/Boss.lua            core frames, health/power, portrait, mover,
                             test mode with HP drain + simulated casts
- Frames/BossCastBar.lua     integrated or detached cast bar, UNIT_SPELLCAST_*
                             events, spark anchored to StatusBar texture
- Frames/BossAuras.lua       pooled aura icons (buffs/debuffs), cooldown
                             swipe, stacks + timer, Source filter
                             (All / Mine / Hide mine / Boss-only)
- Frames/BossOptionsGUI.lua  integrates with the native SetupGUIPages flow
                             (plugs via DF:SetupBossPages)
- Frames/BossOptions.lua     standalone /dfbf config panel (fallback)

Boss settings:
- New DandersFramesDB_v2.boss.{party,raid} block with seamless migration
  from the pre-split flat table
- DF:GetBossDB(mode), DF:GetActiveBossDB(), DF:GetRenderBossDB() helpers
- DF:CopyBossSettings(from, to) for the copy button

Feature set:
- Portrait 2D (Blizzard-style) or 3D (animated model), left/right/hidden,
  with thin border
- Health bar: Reaction (Blizzard-style red/yellow/green) / Class / Static
  color, background alpha, LSM texture
- Power bar with configurable height, texture, background alpha, and
  position/format for the power text. Hides when the unit has no power.
- Cast bar integrated or detached relative to the frame. Icon left/right,
  LSM texture, background alpha slider.
- 9-point anchors + X/Y offsets + name max length (default 16, 0=off)
  for name, health text, power text, raid target icon, auras.
- Raid target icon (skull/cross/...) centered by default, alpha slider.
- Auras: max 1-8 icons, size, spacing, timer placement (inside/below/
  above), stack 9-point anchor, source filter, filter harmful/helpful.
- Test mode integrated with the global Test button; dedicated Boss Frames
  section in the test panel with Boss Count slider + per-feature toggles.

Slash commands: /dfbf (mover), /dfbf test N, /dfbf config, /dfbf refresh.

Defaults + upstream compatibility:
- Hides the Blizzard BossTargetFrameContainer + individual Boss*TargetFrame
  (togglable via "Hide Blizzard").
- All new locale keys registered in enUS.lua --@do-not-package@ block so
  BigWigs Packager -S auto-uploads them to the CurseForge portal.
- Integrates via the existing SetupGUIPages hook + state drivers for
  combat-safe visibility.

WoW 12.0 / Midnight secret-value compatibility:
- All unit APIs that may return secret values (UnitHealth, UnitPower,
  UnitPowerMax, UnitName, UnitCastingInfo, UnitChannelInfo, UnitIsUnit,
  GetRaidTargetIndex, aura sourceUnit / isBossAura / applications /
  expirationTime) are read through pcall guards.
- Cast bar animation uses SetValue(GetTime()*1000) against secret
  min/max; spark anchored to the StatusBar texture (non-secret width).
- Power text falls back to visual percent via StatusBar texture width
  when UnitPower arithmetic is blocked.
- Frame visibility uses RegisterStateDriver so new bosses appear even
  when engaged mid-combat (Show/Hide on a SecureUnitButton is blocked).

Known limitation (proposed, not implemented):
- If Party <-> Raid state flips mid-combat, ApplyLayout already flags
  _pendingLayout and reapplies on PLAYER_REGEN_ENABLED. The same guard
  could be extended to the group watcher's call to RefreshAll so drag /
  attribute changes never fire during InCombatLockdown. Left to the
  maintainer's preference.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant