Skip to content

feat(forever): threat % text on nameplates and target/focus frames - #2263

Merged
EllesmereGaming merged 3 commits into
EllesmereGaming:mainfrom
dfrisone:feat/forever-nameplate-threat-pct
Sep 27, 2026
Merged

EllesmereGaming merged 3 commits into
EllesmereGaming:mainfrom
dfrisone:feat/forever-nameplate-threat-pct

Conversation

@dfrisone

@dfrisone dfrisone commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds an optional threat percentage readout for WoW Forever, requested by Gingi, with the unit frame part added at Ellesmere's request:

  • Enemy nameplates: your threat % on each enemy you are in combat with.
  • Target and focus frames: your threat % on the unit, drawn inside the health bar.

Both are set from a new THREAT % TEXT section on the Forever Essentials > Threat page. Each has an on/off toggle, a Position dropdown (Inside Right / Left / Center), and a cog with Color by Threat, Size and X/Y offsets. The nameplate toggle is also available at the bottom of Enemy Nameplates > Threat Colors, since both write the same profile keys.

The number is the scaled threat percent, the same value the Threat Meter shows as Pull % (100% takes aggro).

Notes for review:

  • Forever only (EllesmereUI.IS_FOREVER). The options rows are hidden on retail, and the runtime never shows the text there, even from a profile shared by a Forever character.
  • On Forever, UnitDetailedThreatSituation returns the percent and the status as secret values for nameplateN tokens, while target and focus come back readable. The percent is therefore never read or compared in Lua; it goes straight to FontString:SetFormattedText.
  • Nameplate coloring cannot use the four status colors, because the status is secret. It folds the isTanking flag through C_CurveUtil.EvaluateColorValueFromBoolean (the same approach as the existing off-tank color), so nameplates show the has-aggro color or the low-threat color. Target and focus use all four GetThreatStatusColor colors. With Color by Threat off, the text is white.
  • Default position is Inside Right. That overlaps the health % text on Forever's default layout, so players who keep health % on the right will want Inside Center or a Y offset.

Implementation:

  • Nameplates: the text is updated inside UpdateHealthColor, which the existing per-plate UNIT_THREAT_LIST_UPDATE already drives, so no new events. The FontString is created the first time a plate shows threat %, the same way as the focus letter (ns.EnsureThreatPctText), and ClearUnit only hides it on recycle if it was shown.
  • Unit frames: a lazy watcher shaped like the Player Threat border: UNIT_THREAT_LIST_UPDATE for target/focus, PLAYER_TARGET_CHANGED, PLAYER_FOCUS_CHANGED and PLAYER_REGEN_ENABLED. It is registered only while the option is on, and restored at login only on Forever.

How was it tested?

WoW Forever client, open world, solo, tanking mobs:

  • Nameplate threat % appears on mobs in combat with you and is red while you hold aggro.
  • The target frame shows threat % with the four-color status coloring.
  • Color by Threat off gives white text on both.
  • Position, Size and X/Y update live.
  • Turning either option off clears the text.
  • Probed in game with issecretvalue: status and percent are secret on nameplate units, and readable on target.
  • Retested on Forever after the review changes (lazy nameplate text, Forever-only login restore).

Not yet tested:

  • the focus frame
  • dungeons and raids
  • a group, where the nameplate has-aggro vs low-threat color flip needs a second player
  • the retail client (the feature is inert there)

Screenshots

WoW Forever, open world, solo tanking, both readouts at Inside Right. The nameplate shows 100% under the health %, and the target frame shows 100% beside it, both in the has-aggro color.

Threat % on the nameplate and target frame

There is no before image, since this adds a new element.

Checklist

  • New settings default OFF (no behavior change without opt-in)
  • Zero cost while disabled: no events registered, no polling, no hooks doing work, no frames built. Nameplates cost one field read in the existing UpdateHealthColor, and no FontString exists until a plate first shows threat %. Unit frames build and register nothing until enabled.
  • Cheap while enabled: event-driven (no polling, no timer-based logic, no per-frame allocations)
  • No writes onto Blizzard-owned frames (weak-table pattern used); HookScript/hooksecurefunc only, never SetScript on Blizzard frames. All state lives on EUI's own plate and unit frames.
  • Tested in-game on live; no version gates or pre-Midnight APIs added. Tested on the WoW Forever client only, as the feature is Forever-only. No version gates or pre-Midnight APIs.

Shows your own threat percentage on enemy nameplates and on the target
and focus unit frames, set from the Forever Essentials Threat page (the
nameplate row is also on the Enemy Nameplates page). Off by default,
Forever only.

Forever returns the percent and status secret for nameplate units, so
the percent goes straight to SetFormattedText and the color comes from
the isTanking flag through the curve boolean fold. Target and focus
values are readable and use all four threat status colors.
dfrisone added a commit to dfrisone/EllesmereUI that referenced this pull request Sep 27, 2026
@dfrisone

Copy link
Copy Markdown
Contributor Author

Both addressed in e405d85:

  • Nameplates: the threat % FontString is now created on first use by ns.EnsureThreatPctText, a clone of ns.EnsureFocusLetter, called at the top of ns.ApplyThreatPctPos. The pool constructor no longer builds it, and ClearUnit only hides it when _tptShown says it was shown.
  • Unit Frames: the login restore is now EllesmereUI.IS_FOREVER and ....

Also merged upstream/main to keep the locale keys current. Retested on Forever.

@EllesmereGaming
EllesmereGaming merged commit e7ef3e8 into EllesmereGaming:main Sep 27, 2026
1 check passed
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.

2 participants