diff --git a/crates/benilla-app/assets/ui/CharacterFrame.xml b/crates/benilla-app/assets/ui/CharacterFrame.xml index 4a12958e..b165280c 100644 --- a/crates/benilla-app/assets/ui/CharacterFrame.xml +++ b/crates/benilla-app/assets/ui/CharacterFrame.xml @@ -366,7 +366,7 @@ getglobal("CharacterNameText"):SetText(UnitName("player")) if ShowTextStatusBarText then -- engine tests load file subsets ShowTextStatusBarText(PlayerFrameHealthBar) - ShowTextStatusBarText(PlayerFramePowerBar) + ShowTextStatusBarText(PlayerFrameManaBar) ShowTextStatusBarText(MainMenuExpBar) ShowTextStatusBarText(PetFrameHealthBar) ShowTextStatusBarText(PetFrameManaBar) @@ -394,7 +394,7 @@ PlaySound("igCharacterInfoClose") if HideTextStatusBarText then -- engine tests load file subsets HideTextStatusBarText(PlayerFrameHealthBar) - HideTextStatusBarText(PlayerFramePowerBar) + HideTextStatusBarText(PlayerFrameManaBar) HideTextStatusBarText(MainMenuExpBar) HideTextStatusBarText(PetFrameHealthBar) HideTextStatusBarText(PetFrameManaBar) diff --git a/crates/benilla-app/assets/ui/Fonts.xml b/crates/benilla-app/assets/ui/Fonts.xml index 57337815..cbacae2e 100644 --- a/crates/benilla-app/assets/ui/Fonts.xml +++ b/crates/benilla-app/assets/ui/Fonts.xml @@ -50,6 +50,11 @@ RED_FONT_COLOR_CODE = "|cffff2020" -- l.10 GREEN_FONT_COLOR_CODE = "|cff20ff20" -- l.11 GRAY_FONT_COLOR_CODE = "|cff808080" -- l.12 + -- l.13, and it was the ONE line of this block that was missing — the comments beside it + -- even skipped from `l.12` to `l.14`. `aux-addon.lua:7` concatenates it at file scope + -- (`LIGHTYELLOW_FONT_COLOR_CODE .. "aux: " ..`), so its absence was not a wrong colour, it + -- was the addon dying on its own first line. + LIGHTYELLOW_FONT_COLOR_CODE = "|cffffff9a" -- l.13 FONT_COLOR_CODE_CLOSE = "|r" -- l.14 NORMAL_FONT_COLOR = { r = 1.0, g = 0.82, b = 0 } -- l.15 HIGHLIGHT_FONT_COLOR = { r = 1.0, g = 1.0, b = 1.0 } -- l.16 diff --git a/crates/benilla-app/assets/ui/PartyFrame.xml b/crates/benilla-app/assets/ui/PartyFrame.xml index a327fc8d..1c935b11 100644 --- a/crates/benilla-app/assets/ui/PartyFrame.xml +++ b/crates/benilla-app/assets/ui/PartyFrame.xml @@ -120,15 +120,15 @@ local tf = name .. "TextureFrame" frame.unit = "party" .. id frame.portrait = getglobal(name .. "Portrait") - frame.healthBar = getglobal(name .. "HealthBar") - frame.manaBar = getglobal(name .. "ManaBar") + frame.healthbar = getglobal(name .. "HealthBar") + frame.manabar = getglobal(name .. "ManaBar") -- The recessed-bar look, the reference's own mechanism (ref-TargetFrame.lua l.32-34): -- push the bars one frame level BELOW the art's TextureFrame. Frame level is the only -- key term above the draw layer (decision 0884), so this is the only thing that can hold -- the BACKGROUND party art over the ARTWORK bar fills. See the LAYERING note below. local textureFrameLevel = getglobal(tf):GetFrameLevel() - frame.healthBar:SetFrameLevel(textureFrameLevel - 1) - frame.manaBar:SetFrameLevel(textureFrameLevel - 1) + frame.healthbar:SetFrameLevel(textureFrameLevel - 1) + frame.manabar:SetFrameLevel(textureFrameLevel - 1) frame.nameText = getglobal(tf .. "Name") frame.leaderIcon = getglobal(tf .. "LeaderIcon") frame.masterIcon = getglobal(tf .. "MasterIcon") @@ -164,16 +164,16 @@ local unit = frame.unit if not UnitIsConnected(unit) then -- Disconnected: bar forced full and grey, portrait desaturated, icon on. - frame.healthBar:SetMinMaxValues(0, 1) - frame.healthBar:SetValue(1) - frame.healthBar:SetStatusBarColor(0.5, 0.5, 0.5) + frame.healthbar:SetMinMaxValues(0, 1) + frame.healthbar:SetValue(1) + frame.healthbar:SetStatusBarColor(0.5, 0.5, 0.5) SetDesaturation(frame.portrait, 1) frame.disconnect:Show() return end SetDesaturation(frame.portrait, nil) frame.disconnect:Hide() - frame.healthBar:SetStatusBarColor(0.0, 1.0, 0.0) + frame.healthbar:SetStatusBarColor(0.0, 1.0, 0.0) local hp, hpMax = UnitHealth(unit), UnitHealthMax(unit) if UnitIsDead(unit) then frame.portrait:SetVertexColor(0.35, 0.35, 0.35, 1.0) @@ -196,19 +196,19 @@ frame.nameText:SetText(UnitName(unit) or "Unknown") - frame.healthBar:SetMinMaxValues(0, UnitHealthMax(unit)) - frame.healthBar:SetValue(UnitHealth(unit)) + frame.healthbar:SetMinMaxValues(0, UnitHealthMax(unit)) + frame.healthbar:SetValue(UnitHealth(unit)) local maxPower = UnitManaMax(unit) if maxPower > 0 then - frame.manaBar:Show() + frame.manabar:Show() local _, token = UnitPowerType(unit) local c = BENILLA_POWER_COLORS[token] or BENILLA_POWER_COLORS.MANA - frame.manaBar:SetStatusBarColor(c.r, c.g, c.b) - frame.manaBar:SetMinMaxValues(0, maxPower) - frame.manaBar:SetValue(UnitMana(unit)) + frame.manabar:SetStatusBarColor(c.r, c.g, c.b) + frame.manabar:SetMinMaxValues(0, maxPower) + frame.manabar:SetValue(UnitMana(unit)) else - frame.manaBar:Hide() + frame.manabar:Hide() end -- Leader + master-looter icons (ref: GetPartyLeaderIndex / GetLootMethod vs own id). diff --git a/crates/benilla-app/assets/ui/UnitFrames.xml b/crates/benilla-app/assets/ui/UnitFrames.xml index 92261ae5..5c709785 100644 --- a/crates/benilla-app/assets/ui/UnitFrames.xml +++ b/crates/benilla-app/assets/ui/UnitFrames.xml @@ -14,7 +14,7 @@ The ref gets this with a child `TargetFrameTextureFrame` (ring art) and `SetFrameLevel(bar, textureFrame-1)` to push the bars beneath it, and we do the same, in BenillaUnitFrame_OnLoad: the parent holds trough + portrait (+ target's name plate) in BACKGROUND; the - `$parentHealthBar`/`$parentPowerBar` StatusBars sit at the PARENT's frame level; and + `$parentHealthBar`/`$parentManaBar` StatusBars sit at the PARENT's frame level; and `$parentTextureFrame` (232×100, filling the parent) holds the ring art (BACKGROUND) + name/level/dead text (OVERLAY) one level ABOVE them, so it draws over the bar edges and the portrait. @@ -29,7 +29,8 @@ band with transparent corners (not an opaque surround), so the square is hidden by the portrait itself — set via SetPortraitToTexture, masked to its inscribed circle (the client's portraits are always round: a model render or a circular-cropped icon), so no corner reaches the ring's gap. The - text lives under the TextureFrame, so its globals carry the `…TextureFrame…` name prefix (OnLoad). + text lives under the TextureFrame, but its GLOBAL names are the reference's flat ones + (`PlayerName`, `TargetDeadText`, …), not `$parent`-derived — see OnLoad's `short` prefix. The shared black `…Background` trough sits behind the unfilled bar portion. DATA FLOW UNCHANGED (pin: re-anchor + re-skin, don't rewrite the eventing): BenillaUnitFrame_* @@ -138,13 +139,31 @@ NEWBIE_TOOLTIP_PARTYOPTIONS = NEWBIE_TOOLTIP_PARTYOPTIONS or "If you belong to a party, you can right-click your portrait to bring up the Party Options menu. This menu will allow you to quit the party or see what looting rules the party is using. A party leader can add or remove party members, as well as change the party's looting rules." NEWBIE_TOOLTIP_PLAYEROPTIONS = NEWBIE_TOOLTIP_PLAYEROPTIONS or "Right-click to bring up special commands for interacting with another player. You can inspect their equipment, issue a party invite, initiate a trade, or challenge a player to a duel. A group leader can promote or remove that player from the group." - -- The client's PowerBarColor values, keyed by the UnitPowerType token. + -- ── ManaBarColor (ref UnitFrame.lua l.1-6, verbatim) ──────────────────────────────── + -- The reference's own table: keyed by the NUMERIC power type `UnitPowerType` returns, each + -- row carrying the `prefix` its bar's text is labelled with. **8 addons in the top-20 root + -- read `ManaBarColor` by name**, which is why it is the published one rather than a + -- benilla-private table — we used to keep the same five colours under + -- `BENILLA_POWER_COLORS`, keyed by token string and carrying no prefix, so every one of + -- those reads found nil. + -- + -- One table, not two: the token map below is DERIVED from it rather than restated, so a + -- colour can never differ between what an addon reads and what our own bars paint. + ManaBarColor = {} + ManaBarColor[0] = { r = 0.00, g = 0.00, b = 1.00, prefix = MANA or "Mana" } + ManaBarColor[1] = { r = 1.00, g = 0.00, b = 0.00, prefix = RAGE_POINTS or "Rage" } + ManaBarColor[2] = { r = 1.00, g = 0.50, b = 0.25, prefix = FOCUS_POINTS or "Focus" } + ManaBarColor[3] = { r = 1.00, g = 1.00, b = 0.00, prefix = ENERGY_POINTS or "Energy" } + ManaBarColor[4] = { r = 0.00, g = 1.00, b = 1.00, prefix = HAPPINESS_POINTS or "Happiness" } + + -- Our own bars look colours up by the TOKEN `UnitPowerType` also returns (its 2nd value), + -- so this maps token → the row above. Same objects, so `ManaBarColor` is the only source. BENILLA_POWER_COLORS = { - MANA = { r = 0.0, g = 0.0, b = 1.0 }, - RAGE = { r = 1.0, g = 0.0, b = 0.0 }, - FOCUS = { r = 1.0, g = 0.5, b = 0.25 }, - ENERGY = { r = 1.0, g = 1.0, b = 0.0 }, - HAPPINESS = { r = 0.0, g = 1.0, b = 1.0 }, + MANA = ManaBarColor[0], + RAGE = ManaBarColor[1], + FOCUS = ManaBarColor[2], + ENERGY = ManaBarColor[3], + HAPPINESS = ManaBarColor[4], } -- ── The raid-target mark atlas (ref TargetFrame.lua l.460-463 + l.475-484) ────────────── @@ -202,18 +221,25 @@ function BenillaUnitFrame_OnLoad(frame, unit) frame.unit = unit local name = frame:GetName() - frame.healthBar = getglobal(name .. "HealthBar") - frame.powerBar = getglobal(name .. "PowerBar") - -- The name/level/dead text live inside $parentTextureFrame (so they draw over the ring art - -- that draws over the bars), so their global names carry the TextureFrame prefix. + frame.healthbar = getglobal(name .. "HealthBar") + frame.manabar = getglobal(name .. "ManaBar") + -- TWO prefixes, both the reference's own. The bars are named off the FRAME + -- (`PlayerFrameHealthBar`, ref-PlayerFrame.xml l.288) but the art, text and icons are + -- named off the UNIT (`PlayerName` l.58, `PlayerPortrait` l.35, `TargetDeadText` + -- ref-TargetFrame.xml l.173) — flat globals, which is what an addon reaches for. + -- `short` is the frame name minus its trailing "Frame". + local short = string.sub(name, 1, string.len(name) - 5) + -- Our ring art rides a $parentTextureFrame child (the reference nests two ANONYMOUS + -- frames there instead, ref-PlayerFrame.xml l.49-51), so the frame whose level the bars + -- are pushed under is still named off the frame. local tf = name .. "TextureFrame" -- The recessed-bar look, the reference's own mechanism (ref-TargetFrame.lua l.32-34): -- push the bars one frame level BELOW the ring art's TextureFrame. Frame level is the -- only key term above the draw layer (decision 0884), so this is the only thing that can -- hold a BACKGROUND ring texture over an ARTWORK bar fill. See the LAYERING note up top. local textureFrameLevel = getglobal(tf):GetFrameLevel() - frame.healthBar:SetFrameLevel(textureFrameLevel - 1) - frame.powerBar:SetFrameLevel(textureFrameLevel - 1) + frame.healthbar:SetFrameLevel(textureFrameLevel - 1) + frame.manabar:SetFrameLevel(textureFrameLevel - 1) -- The on-bar numerals (TextStatusBar.xml, decision 1082; the switch that shows them -- is 1140's Status Bar Text). Wiring is unconditional — a frame with no text regions -- gets a no-op, since SetTextStatusBarText drops a nil text and UpdateTextString skips @@ -223,13 +249,13 @@ -- and the XP bar, and on nothing else, which is exactly why Status Bar Text pins your -- own numbers and your pet's but never the target's (decision 1143). if TextStatusBar_Initialize then -- engine tests load file subsets - TextStatusBar_Initialize(frame.healthBar) - TextStatusBar_Initialize(frame.powerBar) - SetTextStatusBarText(frame.healthBar, getglobal(tf .. "HealthBarText")) - SetTextStatusBarText(frame.powerBar, getglobal(tf .. "PowerBarText")) + TextStatusBar_Initialize(frame.healthbar) + TextStatusBar_Initialize(frame.manabar) + SetTextStatusBarText(frame.healthbar, getglobal(name .. "HealthBarText")) + SetTextStatusBarText(frame.manabar, getglobal(name .. "ManaBarText")) if unit == "player" then - frame.healthBar.textLockable = 1 - frame.powerBar.textLockable = 1 + frame.healthbar.textLockable = 1 + frame.manabar.textLockable = 1 end end -- The hover seam (1146): who this bar belongs to, and what its click means. @@ -237,16 +263,16 @@ if unit == "player" then click = PlayerFrame_OnClick end - frame.healthBar.owner = frame - frame.powerBar.owner = frame - frame.healthBar.ownerClick = click - frame.powerBar.ownerClick = click - frame.nameText = getglobal(tf .. "NameText") - frame.levelText = getglobal(tf .. "LevelText") - frame.deadText = getglobal(tf .. "DeadText") + frame.healthbar.owner = frame + frame.manabar.owner = frame + frame.healthbar.ownerClick = click + frame.manabar.ownerClick = click + frame.nameText = getglobal(short .. "Name") + frame.levelText = getglobal(short .. "LevelText") + frame.deadText = getglobal(short .. "DeadText") -- Target-only (the "??" skull on the level slot); getglobal returns nil for the -- player, guarded at use. - frame.highLevel = getglobal(tf .. "HighLevelTexture") + frame.highLevel = getglobal(short .. "HighLevelTexture") -- Target-only (the level/name plate); getglobal returns nil for the player, guarded at use. frame.nameBackground = getglobal(name .. "NameBackground") -- The live model portrait (the real API's global, ref-UnitFrame.lua): bind the portrait @@ -256,11 +282,11 @@ -- model change), which is why the ref's UNIT_PORTRAIT_UPDATE re-call isn't needed here (the -- event joins the surface when addon parity wants it). Until a bake lands (no unit / model -- still loading) the circle is simply empty. - frame.portrait = getglobal(name .. "Portrait") + frame.portrait = getglobal(short .. "Portrait") SetPortraitTexture(frame.portrait, unit) -- The PvP flag icon (decision 0646), under the TextureFrame like the ring art it -- draws over — see BenillaUnitFrame_UpdatePvP. - frame.pvpIcon = getglobal(tf .. "PVPIcon") + frame.pvpIcon = getglobal(short .. "PVPIcon") frame:RegisterEvent("PLAYER_ENTERING_WORLD") frame:RegisterEvent("UNIT_HEALTH") frame:RegisterEvent("UNIT_MAXHEALTH") @@ -283,26 +309,26 @@ if unit == "target" then frame:RegisterEvent("UNIT_AURA") frame:RegisterEvent("UNIT_CLASSIFICATION_CHANGED") - frame.frameTexture = getglobal(tf .. "Texture") + frame.frameTexture = getglobal(name .. "Texture") end -- The portrait hit indicator (decision 0576): only the player frame registers -- UNIT_COMBAT in 1.12 (ref PlayerFrame_OnLoad — the target frame has no feedback -- text). Ref: CombatFeedback_Initialize(PlayerHitIndicator, 30). if unit == "player" then - frame.feedbackText = getglobal(tf .. "HitIndicator") + frame.feedbackText = getglobal(short .. "HitIndicator") frame.feedbackFontHeight = 30 frame:RegisterEvent("UNIT_COMBAT") -- The status flash (ref PlayerFrame_OnLoad, decision 1082): the resting zzz / -- auto-attack swords under the portrait, the gold/red ring, and the pulse -- counters. Handles cached like pvpIcon above; their presence is what gates -- PlayerFrame_UpdateStatus in the shared Update. - frame.statusTexture = getglobal(tf .. "StatusTexture") - frame.attackBackground = getglobal(tf .. "AttackBackground") - frame.restIcon = getglobal(tf .. "RestIcon") - frame.attackIcon = getglobal(tf .. "AttackIcon") - frame.statusGlow = getglobal(name .. "StatusGlow") - frame.restGlow = getglobal(name .. "StatusGlowRestGlow") - frame.attackGlow = getglobal(name .. "StatusGlowAttackGlow") + frame.statusTexture = getglobal(short .. "StatusTexture") + frame.attackBackground = getglobal(short .. "AttackBackground") + frame.restIcon = getglobal(short .. "RestIcon") + frame.attackIcon = getglobal(short .. "AttackIcon") + frame.statusGlow = getglobal(short .. "StatusGlow") + frame.restGlow = getglobal(short .. "RestGlow") + frame.attackGlow = getglobal(short .. "AttackGlow") frame.statusCounter = 0 frame.statusSign = -1 frame.attackBackground:SetVertexColor(0.8, 0.1, 0.1) @@ -320,8 +346,8 @@ -- shared Update exactly like statusTexture above — the target frame declares -- neither texture, so it never runs the law, and the party member frames run -- their own (PartyFrame.xml, a different predicate: an INDEX comparison). - frame.leaderIcon = getglobal(tf .. "LeaderIcon") - frame.masterIcon = getglobal(tf .. "MasterIcon") + frame.leaderIcon = getglobal(short .. "LeaderIcon") + frame.masterIcon = getglobal(short .. "MasterIcon") frame:RegisterEvent("PARTY_MEMBERS_CHANGED") frame:RegisterEvent("PARTY_LEADER_CHANGED") frame:RegisterEvent("PARTY_LOOT_METHOD_CHANGED") @@ -694,7 +720,7 @@ -- plate on (the reference has no such art for the others and leaves an empty rail drawn). -- -- The bars are ARGUMENTS rather than fields: the player and target frames call theirs - -- `powerBar` and the pet frame calls its `manaBar`, following the reference's own two names + -- `manabar` and the pet frame calls its `manabar`, following the reference's own two names -- for one rail, and a helper that reached for a field would have to pick a side. -- -- NO label on the power bar. 1.12 names the resource there (ref UnitFrame_UpdateManaType @@ -703,20 +729,20 @@ -- day: bare numbers read better on these bars (decision 1147). The mechanism stays — -- SetTextStatusBarTextPrefix is live and one call brings any label back — only the calls -- are gone. - function BenillaUnitFrame_PaintBars(healthBar, powerBar, unit) - healthBar:SetMinMaxValues(0, UnitHealthMax(unit)) - healthBar:SetValue(UnitHealth(unit)) + function BenillaUnitFrame_PaintBars(healthbar, manabar, unit) + healthbar:SetMinMaxValues(0, UnitHealthMax(unit)) + healthbar:SetValue(UnitHealth(unit)) local maxPower = UnitManaMax(unit) if maxPower <= 0 then - powerBar:Hide() + manabar:Hide() return false end - powerBar:Show() + manabar:Show() local _, powerToken = UnitPowerType(unit) local swatch = BENILLA_POWER_COLORS[powerToken] or BENILLA_POWER_COLORS.MANA - powerBar:SetStatusBarColor(swatch.r, swatch.g, swatch.b) - powerBar:SetMinMaxValues(0, maxPower) - powerBar:SetValue(UnitMana(unit)) + manabar:SetStatusBarColor(swatch.r, swatch.g, swatch.b) + manabar:SetMinMaxValues(0, maxPower) + manabar:SetValue(UnitMana(unit)) return true end @@ -729,7 +755,7 @@ end frame:Show() - BenillaUnitFrame_PaintBars(frame.healthBar, frame.powerBar, unit) + BenillaUnitFrame_PaintBars(frame.healthbar, frame.manabar, unit) frame.nameText:SetText(UnitName(unit) or "Unknown") @@ -1173,7 +1199,7 @@ frame LEVEL, and nothing else in this layer overlaps the portrait's square, so the two are indistinguishable here — left alone rather than churned inside a bug fix). Texture set in OnLoad via SetPortraitToTexture (circle-masked). --> - + @@ -1202,7 +1228,7 @@ - + @@ -1229,7 +1255,7 @@ - + @@ -1247,35 +1273,43 @@ number rode ON the badge (director report, 2026-08-07); decision 1093. --> - + The NAME is the reference's own, literally — and so is every other + art/text/icon region in the three unit frames. They used to derive + from `$parent`, which published `PlayerFrameTextureFrameNameText` and + left `PlayerName` (PlayerFrame.xml:58), `TargetName` + (TargetFrame.xml:152) and `PetName` (PetFrame.xml:69) — the names an + addon actually reaches for — nil. See BenillaUnitFrame_OnLoad's + `short` prefix for how the shared binder composes them now. + + **This was tried once and REJECTED, and the rejection was right on + its evidence** — the block that stood here argued: (i) not free, since + `UnitFrame_OnLoad` composes these names inside `getglobal`, so a text + search finds nothing and the rename breaks every unit frame (it broke + 40 tests); and (ii) buys nothing, since a "why" read-back over the + 218-addon corpus matched ZERO error rows for `TargetName`, its one + syntactic caller being a `` in an addon that dies + earlier anyway. It closed "revisit if a row ever names it" (1222's + clause: a shadowed name with no observable caller is building against + a guess). + + What changed (1719): the condition it named was met, and its cost + premise expired. A grep of the top-20 root gives `ManaBarColor` 8 + readers, `PlayerFrameManaBar` 3, `PlayerFrameTexture`/ + `TargetFrameTexture`/`PlayerStatusTexture`/`TargetFrameManaBar` 2 + each, and `PlayerName`/`TargetName`/`PetName` 1 each. ShaguTweaks + dies on `TargetFrameManaBar` at `health-numbers.lua:22`. **Fifteen of + the twenty-two renames still have zero measured readers** and were + kept for consistency with the reference and because the cost was + already paid, NOT because demand was shown — say the word and they go + back. --> + - + @@ -1295,12 +1329,12 @@ They draw over the bar FILL because the whole TextureFrame outranks the bars by a frame level. Empty until Status Bar Text is on or (later) the bar is hovered — TextStatusBar.xml owns that decision, not this file. --> - + - + @@ -1311,7 +1345,7 @@ ref-PlayerFrame.xml l.124-135) — ARTWORK over the BACKGROUND ring art, like the ref's. Texture chosen at runtime (decision 0646 §4); the ref's PlayerPVPIconHitArea is deliberately OUT (see the header). --> - - + @@ -1565,7 +1599,7 @@ - + @@ -1577,7 +1611,7 @@ - - + - + @@ -1601,7 +1635,7 @@ - + @@ -1613,7 +1647,7 @@ key never reaches the screen. `hidden` like the ToT twin below, a deliberate divergence: the reference leaves the region shown and relies on CheckDead landing before the frame does. --> -