diff --git a/crates/benilla-app/assets/ui/GroupLootFrame.xml b/crates/benilla-app/assets/ui/GroupLootFrame.xml
deleted file mode 100644
index cf3243bd..00000000
--- a/crates/benilla-app/assets/ui/GroupLootFrame.xml
+++ /dev/null
@@ -1,546 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- BenillaGroupLootFrame_Timer_OnUpdate(self)
-
-
-
-
-
-
-
-
-
-
-
-
- BenillaGroupLootFrame_OnLoad(self)
- GroupLootFrame_OnShow()
- GroupLootFrame_OnEvent()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- self:RegisterEvent("START_LOOT_ROLL")
- self:RegisterEvent("CONFIRM_LOOT_ROLL")
-
-
- if event == "START_LOOT_ROLL" then
- GroupLootFrame_OpenNewFrame(arg1, arg2)
- elseif event == "CONFIRM_LOOT_ROLL" then
- -- Ref UIParent.lua:517-524 verbatim, minus the central router: a Need/Greed on a
- -- BIND-ON-PICKUP roll sends nothing and asks first (decision 0594). arg1 = rollID,
- -- arg2 = rollType; both ride the dialog so OnAccept can re-enter ConfirmLootRoll.
- local dialog = StaticPopup_Show("CONFIRM_LOOT_ROLL")
- if dialog then
- dialog.data = arg1
- dialog.data2 = arg2
- end
- end
-
-
-
-
diff --git a/crates/benilla-app/assets/ui/InspectFrame.xml b/crates/benilla-app/assets/ui/InspectFrame.xml
deleted file mode 100644
index c53bc062..00000000
--- a/crates/benilla-app/assets/ui/InspectFrame.xml
+++ /dev/null
@@ -1,1066 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- self:SetFrameLevel(self:GetFrameLevel() + 1)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- BenillaInspectModel_OnLoad(self)
- BenillaSetBoothTexture(getglobal(self:GetName() .. "Texture"), "inspect")
-
- BenillaInspectModel_OnUpdate(self, arg1)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- BenillaInspectPaperDollFrame_OnLoad(self)
- BenillaInspectPaperDollFrame_OnEvent(self)
- BenillaInspectPaperDollFrame_OnShow()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- BenillaTooltip_AddNewbieTipFor(self, RANK, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b, NEWBIE_TOOLTIP_RANK)
- GameTooltip:Hide()
-
-
-
-
-
-
-
-
-
-
- self:SetFrameLevel(self:GetFrameLevel() - 1)
- BenillaTooltip_AddNewbieTipFor(self, RANK_POSITION, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b, NEWBIE_TOOLTIP_RANK_POSITION)
- GameTooltip:Hide()
-
-
-
-
- self:SetFrameLevel(self:GetFrameLevel() - 1)
-
-
-
-
-
- BenillaInspectHonorFrame_OnLoad(self)
- BenillaInspectHonorFrame_OnEvent()
- BenillaInspectHonorFrame_OnShow()
-
-
-
-
- BenillaInspectFrame_OnLoad(self)
- BenillaInspectFrame_OnEvent(self)
- BenillaInspectFrame_OnShow(self)
- BenillaInspectFrame_OnHide(self)
- BenillaInspectFrame_OnUpdate(self)
-
-
-
diff --git a/crates/benilla-app/assets/ui/MicroMenu.xml b/crates/benilla-app/assets/ui/MicroMenu.xml
index 97666eae..b0c77503 100644
--- a/crates/benilla-app/assets/ui/MicroMenu.xml
+++ b/crates/benilla-app/assets/ui/MicroMenu.xml
@@ -213,7 +213,7 @@
function UpdateMicroButtons()
BenillaMicroButton_SetPushed(CharacterMicroButton, BenillaMicro_PanelShown("CharacterFrame"))
BenillaMicroButton_SetPushed(SpellbookMicroButton, BenillaMicro_PanelShown("SpellBookFrame"))
- BenillaMicroButton_SetPushed(TalentMicroButton, BenillaMicro_PanelShown("BenillaTalentFrame"))
+ BenillaMicroButton_SetPushed(TalentMicroButton, BenillaMicro_PanelShown("TalentFrame"))
BenillaMicroButton_SetPushed(QuestLogMicroButton, BenillaMicro_PanelShown("QuestLogFrame"))
-- ref l.60-64. Missing since the Socials button went live with decision 0668: the
-- window opened but its button never read pushed. Spotted while wiring Help, which is
diff --git a/crates/benilla-app/assets/ui/TalentFrame.xml b/crates/benilla-app/assets/ui/TalentFrame.xml
deleted file mode 100644
index be3c3fed..00000000
--- a/crates/benilla-app/assets/ui/TalentFrame.xml
+++ /dev/null
@@ -1,1248 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- BenillaTalentFrameScrollBar_OnValueChanged(self, arg1)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- BenillaTalentFrameScroll_OnLoad(self)
-
- BenillaScrollBar_Step(getglobal("BenillaTalentFrameScrollBar"), arg1 > 0 and -1 or 1)
-
- getglobal("BenillaTalentFrameScrollBar"):SetValue(arg1)
-
-
-
-
- BenillaTalentFrame_OnLoad(self)
- BenillaTalentFrame_OnShow()
- BenillaTalentFrame_OnHide()
- BenillaTalentFrame_OnEvent(self)
-
-
-
diff --git a/crates/benilla-app/assets/ui/UIParent.xml b/crates/benilla-app/assets/ui/UIParent.xml
index 2f275c91..2b00e59c 100644
--- a/crates/benilla-app/assets/ui/UIParent.xml
+++ b/crates/benilla-app/assets/ui/UIParent.xml
@@ -36,6 +36,8 @@
this:RegisterEvent("MIRROR_TIMER_START")
this:RegisterEvent("PLAYER_ENTERING_WORLD")
this:RegisterEvent("READY_CHECK")
+ this:RegisterEvent("START_LOOT_ROLL")
+ this:RegisterEvent("CONFIRM_LOOT_ROLL")
UIParent_OnEvent(event)
@@ -213,6 +215,41 @@
-- statements on the same event). `MultiActionBar_Update` is existence-guarded because the
-- ~25 per-window harnesses that load this file load no bars; the binding itself is engine
-- level and always installed. Decision 1500.
+ -- ref UIParent.lua:223, whose slot this is — immediately above `UIParent_OnEvent`, the
+ -- same neighbour it has there. It moved here from our own InspectFrame.xml when 1832
+ -- retired that file: the name belongs to UIParent in the reference, and the window it
+ -- opens is now the stock LoadOnDemand `Blizzard_InspectUI` off the player's chain.
+ --
+ -- The reference's body is `InspectFrame_LoadUI()` and then a guarded `InspectFrame_Show`.
+ -- We have no load-on-demand — benilla.toc loads that addon with everything else — so the
+ -- LoadUI call has nothing to do and is left out rather than stubbed (1203). The guard is
+ -- kept exactly as the reference writes it, and it is not decoration: it is what makes this
+ -- safe in the ~25 per-window harnesses that load UIParent.xml without the inspect window.
+ function InspectUnit(unit)
+ if ( InspectFrame_Show ) then
+ InspectFrame_Show(unit);
+ end
+ end
+
+ -- ref UIParent.lua's own `ToggleTalentFrame`, moved here from our TalentFrame.xml when
+ -- 1833 retired that file — the same move `InspectUnit` made just above, for the same
+ -- reason: the reference keeps the opener in UIParent and the window in a LoadOnDemand
+ -- addon, so deleting our window file would have taken the name with it.
+ --
+ -- The LEVEL GATE is the reference's, and it is real behaviour rather than a guard: below
+ -- level 10 the key and the micro button do nothing at all. `TalentFrame_LoadUI` is left
+ -- out (we load the addon eagerly, 1203 — build it or leave it out, never stub it); the
+ -- `TalentFrame_Toggle` guard is kept verbatim, and it is what lets the ~25 harnesses that
+ -- load UIParent.xml without the talent window do so safely.
+ function ToggleTalentFrame()
+ if ( UnitLevel("player") < 10 ) then
+ return;
+ end
+ if ( TalentFrame_Toggle ) then
+ TalentFrame_Toggle();
+ end
+ end
+
function UIParent_OnEvent(event)
-- The reference's own first arm (UIParent.lua l.230-235). `LocalizeFrames` comes from
-- the sourced `Interface\FrameXML\Localization.xml` (1751 window 5) and is the file
@@ -247,6 +284,36 @@
MultiActionBar_Update()
end
end
+ -- The group-roll opener, ref UIParent.lua l.513-515 verbatim. This arm is why our
+ -- own GroupLootFrame.xml existed at all: that file's header explained it was carrying
+ -- a dedicated hidden driver frame *because* "this engine doesn't ship" UIParent's
+ -- monolithic OnEvent. It does now, so the router comes home to the reference's own
+ -- slot and the driver goes with the file (decision 1838).
+ --
+ -- `GroupLootFrame_OpenNewFrame` and the four frames it walks are the CHAIN's, out of
+ -- `Interface\FrameXML\LootFrame.xml` and its `.lua` — already on the manifest, and
+ -- already declaring every name our copy re-declared. Existence-guarded for
+ -- `MultiActionBar_Update`'s reason, not the reference's: the per-window harnesses load
+ -- this file with no loot window behind it.
+ if ( event == "START_LOOT_ROLL" ) then
+ if ( GroupLootFrame_OpenNewFrame ) then
+ GroupLootFrame_OpenNewFrame(arg1, arg2)
+ end
+ return
+ end
+ -- ref UIParent.lua l.517-524, the arm directly below the one above and the second
+ -- router our GroupLootFrame.xml was carrying. The dialog it raises now lives in
+ -- UiPanels.xml beside DELETE_ITEM; `arg1`/`arg2` are the roll id and roll type, and
+ -- `StaticPopup_Show` answering nil (the popup pool being full) is the reference's own
+ -- guarded case, not ours.
+ if ( event == "CONFIRM_LOOT_ROLL" ) then
+ local dialog = StaticPopup_Show("CONFIRM_LOOT_ROLL")
+ if ( dialog ) then
+ dialog.data = arg1
+ dialog.data2 = arg2
+ end
+ return
+ end
-- The ready-check popup's opener (decision 1549), ref UIParent.lua l.570-572. The
-- event is the engine's own `0x218`, fired by the `MSG_RAID_READY_CHECK` open
-- handler; the frame and `ShowReadyCheck` live in RaidFrame.xml, so this is the one
diff --git a/crates/benilla-app/assets/ui/UiPanels.xml b/crates/benilla-app/assets/ui/UiPanels.xml
index b48c6cf0..8b10a808 100644
--- a/crates/benilla-app/assets/ui/UiPanels.xml
+++ b/crates/benilla-app/assets/ui/UiPanels.xml
@@ -110,7 +110,7 @@
-- The inspect window (decision 0631, InspectFrame.xml): the ref's own InspectFrame row
-- (`Blizzard_InspectUI.lua:4` — area "left", pushable 0), so inspecting swaps out whichever
-- left-slot window was open, exactly as the character window does.
- UIPanelWindows["BenillaInspectFrame"] = { area = "left", pushable = 0 }
+ UIPanelWindows["InspectFrame"] = { area = "left", pushable = 0 }
-- The spellbook (decision 0216 §8, SpellBookFrame.xml): the ref's own SpellBookFrame row
-- verbatim (`{ area = "left", pushable = 0, whileDead = 1 }`, UIParent.lua l.21; whileDead
-- carried since 1507) — same left-slot competition as every window above.
@@ -120,7 +120,7 @@
-- pushable 6 one tier above the plain NPC-session/player-state windows' 0. whileDead was
-- omitted here while `UnitIsDead` didn't exist; it is a live unit binding now, so 1507
-- carries the ref's flag on every row that has one.
- UIPanelWindows["BenillaTalentFrame"] = { area = "left", pushable = 6, whileDead = 1 }
+ UIPanelWindows["TalentFrame"] = { area = "left", pushable = 6, whileDead = 1 }
-- The social window (decision 0668) — the ref's own registration line verbatim
-- (`UIPanelWindows["FriendsFrame"] = { area = "left", pushable = 0, whileDead = 1 }`,
-- UIParent.lua l.29). whileDead: a corpse run is exactly when you want to whisper someone.
@@ -1705,6 +1705,36 @@
-- other path → hide) replaces the old bespoke `deleteItemFlow` CURSOR_UPDATE driver.
-- exclusive is v1-inert (engine header note); showAlert is live since 1068 — the ref's
-- own "display the error image" case is this very dialog.
+ -- CONFIRM_LOOT_ROLL — the BoP roll's "this will bind to you" gate, keyed BARE like every
+ -- other entry (the key is `StaticPopup_Show`'s argument, not a frame name).
+ --
+ -- It moved here from our own GroupLootFrame.xml when 1838 retired that file. The reference
+ -- keeps it in `StaticPopup.lua`; we have no counterpart to that file, and our own
+ -- convention is that a dialog whose window has migrated comes to sit beside DELETE_ITEM
+ -- below — the same move `CloseMenus` made when the dropdown kit went to the chain.
+ --
+ -- The C `RollOnLoot` is what diverts a BoP Need/Greed here rather than rolling: the gate
+ -- lives in the binding, not in Lua (decision 0594, verified in the 5875 binary), and only
+ -- `OnAccept`'s `ConfirmLootRoll` re-enters past it. `id`/`rollType` arrive as data/data2,
+ -- set by the `CONFIRM_LOOT_ROLL` arm in UIParent.xml's own OnEvent.
+ --
+ -- The three strings are quoted verbatim rather than read from GlobalStrings, which is this
+ -- file's existing idiom for exactly one reason: a bare global is nil in a harness that has
+ -- not loaded the chain's GlobalStrings, and a `format()` over nil aborts the whole inline
+ -- chunk — taking every function defined after it down with it.
+ StaticPopupDialogs["CONFIRM_LOOT_ROLL"] = {
+ text = "Looting this item will bind it to you.", -- LOOT_NO_DROP
+ button1 = "Okay", -- OKAY
+ button2 = "Cancel", -- CANCEL
+ OnAccept = function(id, rollType)
+ ConfirmLootRoll(id, rollType)
+ end,
+ timeout = 0,
+ whileDead = 1,
+ exclusive = 1,
+ hideOnEscape = 1
+ }
+
StaticPopupDialogs["DELETE_ITEM"] = {
text = DELETE_ITEM,
button1 = YES,
@@ -2322,6 +2352,16 @@
-- ours reads GetStringWidth — the same number once the measure round-trip lands, which is
-- why the caller below re-checks from OnUpdate instead of OnShow.
function PanelTemplates_TabResize(padding, tab, absoluteSize, maxWidth)
+ -- The ref's own opening arm, and it is not defensive: `tab` is OPTIONAL, and a caller
+ -- that omits it is relying on `this`. Ours had only the explicit-`tab` half, so every
+ -- caller in our own files passed one and the gap stayed invisible — until a stock file
+ -- called `PanelTemplates_TabResize(0)` from a tab's OnLoad and threw
+ -- "attempt to index local 'tab' (a nil value)". `Blizzard_MacroUI.xml`'s two tabs do
+ -- exactly that; so do the readiness instrument's two `UiPanels.xml` failures.
+ -- Decision 1835.
+ if ( not tab ) then
+ tab = this
+ end
local name = tab:GetName()
local text = getglobal(name .. "Text")
local sideWidths = 2 * getglobal(name .. "Left"):GetWidth()
diff --git a/crates/benilla-app/assets/ui/benilla.toc b/crates/benilla-app/assets/ui/benilla.toc
index b0a189a6..affdf41b 100644
--- a/crates/benilla-app/assets/ui/benilla.toc
+++ b/crates/benilla-app/assets/ui/benilla.toc
@@ -655,14 +655,36 @@ SkillFrame.xml
# `HonorFrameTemplates.xml` is ``d by `HonorFrame.xml` and inherited by the LoadOnDemand
# `Blizzard_InspectUI`, which loads later still.
Interface\FrameXML\HonorFrame.xml
-# The inspect window (decision 0631): another player's paper doll. Beside the character
-# window it mirrors — it needs the same three (Fonts/UiPanels/GameTooltip) plus
-# `CharacterFrameTabButtonTemplate` from UiPanels.xml, and nothing from CharacterFrame.xml
-# itself (its slot template, handlers, and booth slot are all its own — the two windows
-# share only the reference's art). ONE cross-window dependency does bind, and it is on the
-# entry directly above: this window's honor page inherits HonorFrame.xml's five row templates
-# and calls its two shared painters, the same sharing the reference does.
-InspectFrame.xml
+# ══ THE INSPECT WINDOW — the reference's own, off the player's chain (1751, window 24) ══
+# Another player's paper doll (decision 0631), and the FIRST LoadOnDemand ADDON we take off the
+# chain rather than a FrameXML file. Everything below it in this manifest that names a
+# `Blizzard_*` addon follows the shape set here.
+#
+# **The addon is inside patch.MPQ, not the loose folder.** `Interface\AddOns\Blizzard_InspectUI\`
+# on disk holds one `Blizzard_InspectUI.pub` decoy and nothing else; the real four files sit in
+# the archive, which the chain mounts. Believing the decoy is what kept this window (and Macro,
+# Talent, Raid, Trainer) on a transcription for months.
+#
+# No LoadOnDemand: we list the addon's files here and they load with everything else. The
+# reference reaches them through `InspectUnit` → `InspectFrame_LoadUI`; ours keeps `InspectUnit`
+# (in UIParent.xml, the reference's own home for that name) and drops the LoadUI call.
+#
+# The addon's own toc order, which is load order — the `.xml` files pull their `.lua` siblings
+# through `