Files
benilla-octo/crates/benilla/assets/ui/GroupLootFrame.xml
T
SamandClaude Fable 5 2ad0043523 benilla: initial public release
A from-scratch World of Warcraft 1.12.1 client in Rust + Bevy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:27:01 +07:00

479 lines
28 KiB
XML

<Ui>
<!--
benilla's group-loot roll window (decision 0591) — the Need/Greed/Pass dialog: four stacked
`GroupLootFrame`s, transcribed from the real 1.12 client (`LootFrame.xml` l.243-533,
`LootFrame.lua` l.246-296, `UIParent.lua` l.513-515/1577 — all extracted, scratchpad
`WoW/_extracted_framexml/`). Geometry, art paths, and behavior below are QUOTED from those
(line citations inline); the Lua is transcribed logic turned onto our own `loot_roll` engine
seam (`benilla-ui/src/script/loot_roll.rs`, decision 0591) and its app feed
(`crates/benilla/src/ui_loot_roll.rs`).
FOUR STACKED POPUPS, NOT A UIPANEL. Unlike LootFrame.xml, this window is a real 1.12
`frameStrata="DIALOG"`/`toplevel="true"` popup family — never registered in UiPanels.xml, no
pushable slot. `GroupLootFrame1` sits at the ref's own hardcoded anchor (BOTTOM,
+0,60 — ref l.498-506); frames 2-4 each stack on the PREVIOUS frame's TOP +15 (ref l.507-533).
`GroupLootFrame_OpenNewFrame` (ref LootFrame.lua l.246-258) claims the first currently-hidden
of the four on every `START_LOOT_ROLL`, so up to 4 concurrent rolls each get their own frame,
stacking upward; a 5th simultaneous roll finds none free and is silently dropped — the
reference's own ceiling (`NUM_GROUP_LOOT_FRAMES = 4`, LootFrame.lua l.2), not a benilla gap.
THE FOUR INSTANCES KEEP THE REFERENCE'S BARE NAMES (`GroupLootFrame1`..`4`), deliberately —
the one place the house `Benilla`-prefix convention is NOT applied, for the same reason
`CastingBarFrame` keeps its bare name (CastingBar.xml's POSITION note). `UIParent.xml` (l.70)
already carries the ref's `UIPARENT_MANAGED_FRAME_POSITIONS["GroupLootFrame1"]` row (baseY 60,
+42 for a shown bottom multibar, +42 for the pet/stance bar, +9 for the rep watch bar), and
`UIParent_ManageFramePositions` finds its frames by a literal `getglobal(name)` — no prefix
awareness. UIParent.xml's own comment lists `GroupLootFrame1` among the rows that "no-op
through the ref's own `if ( frame )` guard and self-activate if the frames later land": this
file is that landing, so the bare name is what makes the row engage.
It matters concretely, not theoretically: with benilla's always-on bottom multibars the
managed pass puts frame 1 at y=102 (and y=144 while the stance bar shows). Under a prefixed
name the row would never fire and the roll dialogs would sit permanently at y=60 — squarely on
top of the action bars. Bare names are also what a real 1.12 addon expects to find (0068's
Era-addon target), so this costs nothing elsewhere. The template, the driver, and this file's
own Lua functions stay `Benilla`-prefixed: nothing in the reference keys on those.
NO CENTRAL UIParent EVENT ROUTER. The reference's `START_LOOT_ROLL` dispatch (`UIParent.lua`
l.513-515: `GroupLootFrame_OpenNewFrame(arg1, arg2)`) rides the monolithic `UIParent_OnEvent`
this engine doesn't ship (`UIParent.xml`'s own note: "not ours to ship - no consumer yet").
Rather than claim UIParent's single OnEvent slot (which a later, more general router would then
have to fight over) or special-case ONE of the four peer frames, a small dedicated hidden
driver frame (`BenillaGroupLootFrameDriver`, below — the same shape as `DeathFrame.xml`'s
`BenillaDeathDriver`) owns exactly this one registration, keeping all four
`BenillaGroupLootFrame`s byte-identical instances of the same template (each registers only
`CANCEL_LOOT_ROLL` on itself, ref l.487-489/493-495, verbatim).
NO DRESSING-ROOM / CHAT-LINK INSERT (CraftFrame.xml's/TradeSkillFrame.xml's own identical
deviation). The ref icon button's Ctrl-click `DressUpItemLink`/Shift-click
`ChatFrameEditBox:Insert` (ref l.353-360) and its `this.hasItem = 1` OnLoad flag (ref l.339,
read only by UIParent.lua's own generic Ctrl-click dressing-room handler) are dropped — no
dressing room exists; a real, now-inert vestige, not a benilla omission. Likewise the ref's
`CursorUpdate()`/`ResetCursor()`/`CursorOnUpdate()` hover-cursor calls (ref l.344,348,351) have
no engine counterpart and are omitted — LootFrame.xml's own row template
(`BenillaLootButtonTemplate`) already established this same omission for item-row hover.
THE ITEM TOOLTIP uses `GameTooltip:SetItemById(itemId, name, quality)` (LootFrame.xml's own
`BenillaLootItem_OnEnter` idiom), not the reference's `SetLootRollItem`/`GetLootRollItemLink`
(neither exists here) — `itemId` is the benilla-extension 6th return of `GetLootRollItemInfo`
(see `loot_roll.rs`), always populated once a roll is known (unlike name/texture/quality, which
may be `nil` while the item template is still in flight).
`toplevel="true"` (ref l.243) IS OMITTED — `SetToplevel` isn't in the v1 object model yet
(`loader/geometry.rs`'s `apply_attrs`: a warn-once "gap", same as `movable`/`resizable`); other
benilla toplevel popups (BuffFrame.xml, CastingBar.xml) carry the attribute anyway and simply
eat the warning, but it has ZERO engine effect either way today, so keeping this file's own
load warning-free (this assignment's own bar) costs nothing real — trivially re-added the day
`SetToplevel` lands.
NAMED FONT OBJECTS ARE SUPPORTED on this branch (the loader's top-level `<Font>` handling,
`loader/mod.rs`'s `do_font`, plus the full `Fonts.xml` transcription, both landed since
LootFrame.xml's own "not implemented yet" caveat was written) — `$parentName`'s
`inherits="GameFontNormalSmall"` below resolves for real; no stale caveat needed here.
IN-FLIGHT ITEMS: `GetLootRollItemInfo`'s `name`/`texture`/`quality` are `nil` while the item
template query hasn't landed yet (`loot_roll.rs`). `BenillaGroupLootFrame_OnShow` falls back to
`BENILLA_FALLBACK_ICON` / an empty name / common (quality 1) — the same fallback shape
`BenillaLootFrame_Update` uses for an in-flight loot row.
The Era API this drives (`benilla-ui/src/script/loot_roll.rs`, decision 0591):
`GetLootRollItemInfo(rollID)` -> texture,name,count,quality,bindOnPickUp,itemID;
`GetLootRollTimeLeft(rollID)` -> ms remaining; `RollOnLoot(rollID, rollType)` (0 Pass / 1 Need /
2 Greed). Events: `START_LOOT_ROLL(rollID, rollTime)` claims a frame; `CANCEL_LOOT_ROLL(rollID)`
hides the one that owns it (`crates/benilla/src/ui_loot_roll.rs` fires both).
-->
<Script><![CDATA[
-- LootFrame.lua l.2's NUM_GROUP_LOOT_FRAMES, renamed to the house BENILLA_ prefix (the same
-- treatment LootFrame.xml gave LOOTFRAME_NUMBUTTONS -> BENILLA_LOOT_NUMBUTTONS).
BENILLA_NUM_GROUP_LOOT_FRAMES = 4
-- The bind-on-pickup confirm (ref StaticPopup.lua l.1371-1382, verbatim bar the TEXT()
-- indirection this house dialect drops). Need/Greed on a BoP roll never reaches the wire
-- directly: the seam diverts it to CONFIRM_LOOT_ROLL, the driver below raises this popup,
-- and only OnAccept's ConfirmLootRoll re-enters past the gate (decision 0594, VERIFIED in
-- the 5875 binary — the gate lives in the C RollOnLoot, not in the Lua). Keyed BARE, like
-- every other StaticPopupDialogs entry: the key is the StaticPopup_Show argument, not a
-- frame name. `id`/`rollType` arrive as the dialog's data/data2.
-- The three strings quoted verbatim from the real 1.12 GlobalStrings.lua (patch-2.MPQ,
-- Interface\FrameXML\GlobalStrings.lua l.2612/2818/465), following UiPanels.xml's
-- DELETE_ITEM idiom rather than reading the globals: GlobalStrings is loaded from the
-- PATCH CHAIN at runtime, so a bare global is nil under test and any format() over it
-- errors — and an error here aborts the whole chunk, taking every function in this file
-- with it.
local LOOT_NO_DROP_TEXT = "Looting this item will bind it to you." -- LOOT_NO_DROP
local OKAY_TEXT = "Okay" -- OKAY
local CANCEL_TEXT = "Cancel" -- CANCEL
StaticPopupDialogs["CONFIRM_LOOT_ROLL"] = {
text = LOOT_NO_DROP_TEXT,
button1 = OKAY_TEXT,
button2 = CANCEL_TEXT,
OnAccept = function(id, rollType)
ConfirmLootRoll(id, rollType)
end,
timeout = 0,
whileDead = 1,
exclusive = 1,
hideOnEscape = 1
}
-- GroupLootFrame_OpenNewFrame (ref LootFrame.lua l.246-258): claim the first currently-hidden
-- of the four frames for a freshly opened roll, seed its rollID/rollTime, and prime the
-- Timer StatusBar's max before showing it (fields set BEFORE Show(), so OnShow below can
-- already read frame.rollID).
function BenillaGroupLootFrame_OpenNewFrame(rollId, rollTime)
for i = 1, BENILLA_NUM_GROUP_LOOT_FRAMES do
local frame = getglobal("GroupLootFrame" .. i)
if frame and not frame:IsVisible() then
frame.rollID = rollId
frame.rollTime = rollTime
getglobal(frame:GetName() .. "Timer"):SetMinMaxValues(0, rollTime)
frame:Show()
return
end
end
-- All 4 already claimed: the reference has no overflow handling either (a 5th
-- simultaneous roll simply finds no free frame) — its own ceiling, not a benilla gap.
end
-- GroupLootFrame_OnShow's body (ref l.260-277): resolve the roll's display fields and paint
-- the icon/name/backdrop. name/texture/quality may be nil while the item template query is
-- still in flight (loot_roll.rs) — fall back to the fallback icon / blank name / common (1)
-- quality rather than erroring, the same fallback shape BenillaLootFrame_Update uses for an
-- in-flight loot row (LootFrame.xml).
--
-- SPLIT OUT OF OnShow, unlike the reference, because it must be re-runnable: the ref's
-- `GetLootRollItemInfo` reads live C state that is already populated when START_LOOT_ROLL
-- fires, whereas ours reads a *pushed snapshot* that by construction does not yet contain a
-- roll opening this frame (loot_roll.rs `feed_loot_rolls`, and the late item template on top
-- of that). `UPDATE_LOOT_ROLL` re-enters here; the paint is idempotent.
function BenillaGroupLootFrame_Paint(frame)
local texture, name, count, quality, bindOnPickUp, itemId = GetLootRollItemInfo(frame.rollID)
frame.itemId = itemId
if bindOnPickUp then
frame:SetBackdrop({
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background",
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
tile = true, tileSize = 32, edgeSize = 32,
insets = { left = 11, right = 12, top = 12, bottom = 11 },
})
getglobal(frame:GetName() .. "Corner"):SetTexture("Interface\\DialogFrame\\UI-DialogBox-Gold-Corner")
getglobal(frame:GetName() .. "Decoration"):Show()
else
frame:SetBackdrop({
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
tile = true, tileSize = 32, edgeSize = 32,
insets = { left = 11, right = 12, top = 12, bottom = 11 },
})
getglobal(frame:GetName() .. "Corner"):SetTexture("Interface\\DialogFrame\\UI-DialogBox-Corner")
getglobal(frame:GetName() .. "Decoration"):Hide()
end
getglobal(frame:GetName() .. "IconFrameIcon"):SetTexture(texture or BENILLA_FALLBACK_ICON)
local nameText = getglobal(frame:GetName() .. "Name")
nameText:SetText(name or "")
local color = ITEM_QUALITY_COLORS[quality] or ITEM_QUALITY_COLORS[1]
nameText:SetVertexColor(color.r, color.g, color.b)
end
function BenillaGroupLootFrame_OnShow(frame)
BenillaGroupLootFrame_Paint(frame)
end
-- Per-instance CANCEL_LOOT_ROLL (ref l.487-489 OnLoad, l.279-285/493-495 OnEvent): each of the
-- four frames registers and checks its OWN rollID, hiding only itself. UPDATE_LOOT_ROLL is
-- the benilla extension alongside it (see BenillaGroupLootFrame_Paint) and takes the same
-- per-instance shape: arg1 is the rollID whose display identity changed.
function BenillaGroupLootFrame_OnLoad(frame)
frame:RegisterEvent("CANCEL_LOOT_ROLL")
frame:RegisterEvent("UPDATE_LOOT_ROLL")
end
function BenillaGroupLootFrame_OnEvent(frame)
if arg1 ~= frame.rollID then
return
end
if event == "CANCEL_LOOT_ROLL" then
frame:Hide()
elseif event == "UPDATE_LOOT_ROLL" then
BenillaGroupLootFrame_Paint(frame)
end
end
-- GroupLootFrame_OnUpdate (ref l.287-296): poll the remaining time each tick, clamped to the
-- bar's own [min,max] exactly as the reference does (an out-of-range read — e.g. an unknown
-- rollID's 0 — clamps to min rather than erroring). Bound to the Timer bar itself so
-- `bar:IsVisible()` follows its (hidden) parent frame, matching the ref's `this:IsVisible()`.
function BenillaGroupLootFrame_Timer_OnUpdate(bar)
if bar:IsVisible() then
local left = GetLootRollTimeLeft(bar:GetParent().rollID)
local min, max = bar:GetMinMaxValues()
if left < min or left > max then
left = min
end
bar:SetValue(left)
end
end
-- Pass/Need/Greed (ref $parentPassButton/$parentRollButton/$parentGreedButton OnClick,
-- l.374/398/425): one shared handler, rollType 0 Pass / 1 Need / 2 Greed.
function BenillaGroupLootFrame_Roll_OnClick(button, rollType)
RollOnLoot(button:GetParent().rollID, rollType)
end
function BenillaGroupLootFrame_Roll_OnEnter(button, text)
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
GameTooltip:SetText(text)
end
function BenillaGroupLootFrame_Roll_OnLeave()
GameTooltip:Hide()
end
-- The item icon's hover tooltip (ref $parentIconFrame OnEnter/OnLeave, l.341-349, minus the
-- CursorUpdate/ResetCursor calls this engine has no counterpart for — see the header). Uses
-- the LootFrame.xml row idiom (SetItemById + the benilla itemId extension) rather than the
-- reference's SetLootRollItem, which doesn't exist here.
function BenillaGroupLootFrame_Icon_OnEnter(button)
local frame = button:GetParent()
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
local _, name, _, quality, _, itemId = GetLootRollItemInfo(frame.rollID)
if itemId then
GameTooltip:SetItemById(itemId, name, quality)
end
end
function BenillaGroupLootFrame_Icon_OnLeave()
GameTooltip:Hide()
end
]]></Script>
<!--
The template (ref GroupLootFrameTemplate, l.243-497): 243x84, DIALOG strata, toplevel, hidden
by default. Geometry/art below is QUOTED verbatim, INCLUDING dropping the stray `d` character
inside ref l.292's `<Anchor point="TOPLEFT">d` (a typo in Blizzard's own shipped file — not
transcribed).
-->
<Frame name="BenillaGroupLootFrameTemplate" frameStrata="DIALOG" hidden="true" virtual="true">
<Size><AbsDimension x="243" y="84"/></Size>
<Layers>
<Layer level="ARTWORK">
<!-- The item slot plate (ref l.249-260). -->
<Texture name="$parentSlotTexture" file="Interface\Buttons\UI-EmptySlot">
<Size><AbsDimension x="64" y="64"/></Size>
<Anchors>
<Anchor point="TOPLEFT"><Offset><AbsDimension x="3" y="-3"/></Offset></Anchor>
</Anchors>
</Texture>
<!-- The parchment name plate (ref l.261-272). -->
<Texture name="$parentNameFrame" file="Interface\MerchantFrame\UI-Merchant-LabelSlots">
<Size><AbsDimension x="128" y="64"/></Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentSlotTexture" relativePoint="RIGHT">
<Offset><AbsDimension x="-9" y="-10"/></Offset>
</Anchor>
</Anchors>
</Texture>
<!-- The item name (ref l.273-284): GameFontNormalSmall, LEFT. -->
<FontString name="$parentName" inherits="GameFontNormalSmall" text="Item Name" justifyH="LEFT">
<Size><AbsDimension x="90" y="30"/></Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentSlotTexture" relativePoint="RIGHT">
<Offset><AbsDimension x="-5" y="5"/></Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
<Layer level="OVERLAY">
<!-- The gold BoP dragon flourish (ref l.287-298): hidden by default, shown only for a
bind-on-pickup roll (BenillaGroupLootFrame_OnShow). -->
<Texture name="$parentDecoration" file="Interface\DialogFrame\UI-DialogBox-Gold-Dragon" hidden="true">
<Size><AbsDimension x="120" y="120"/></Size>
<Anchors>
<Anchor point="TOPLEFT"><Offset><AbsDimension x="-30" y="15"/></Offset></Anchor>
</Anchors>
</Texture>
<!-- The dialog-box corner (ref l.299-310): swapped plain/gold in OnShow. -->
<Texture name="$parentCorner" file="Interface\DialogFrame\UI-DialogBox-Corner">
<Size><AbsDimension x="32" y="32"/></Size>
<Anchors>
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-6" y="-7"/></Offset></Anchor>
</Anchors>
</Texture>
</Layer>
</Layers>
<Frames>
<!-- The item icon (ref $parentIconFrame, l.314-363): hover-tooltip only here — the ref's
Ctrl/Shift dressing-room/chat-link branch and hasItem OnLoad flag are dropped (header). -->
<Button name="$parentIconFrame" enableMouse="true">
<Size><AbsDimension x="34" y="34"/></Size>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentSlotTexture">
<Offset><AbsDimension x="15" y="-15"/></Offset>
</Anchor>
</Anchors>
<Layers>
<Layer level="OVERLAY">
<Texture name="$parentIcon">
<Size><AbsDimension x="34" y="34"/></Size>
<Anchors><Anchor point="TOPLEFT"/></Anchors>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnEnter>BenillaGroupLootFrame_Icon_OnEnter(self)</OnEnter>
<OnLeave>BenillaGroupLootFrame_Icon_OnLeave()</OnLeave>
</Scripts>
</Button>
<!-- Pass (ref $parentPassButton, l.364-384): the ref inherits UIPanelCloseButton, which
this engine ships no template for — reconstructed on the same minimize-button art
BenillaLootFrame's own close button uses (LootFrame.xml's identical "no
UIPanelCloseButton template ships" precedent), at the ref's own 32x32/position. -->
<Button name="$parentPassButton">
<Size><AbsDimension x="32" y="32"/></Size>
<Anchors>
<Anchor point="TOPRIGHT" relativeTo="$parentCorner" relativePoint="TOPRIGHT">
<Offset><AbsDimension x="5" y="5"/></Offset>
</Anchor>
</Anchors>
<NormalTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Up"/>
<PushedTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Down"/>
<HighlightTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Highlight" alphaMode="ADD"/>
<Scripts>
<OnClick>BenillaGroupLootFrame_Roll_OnClick(self, 0)</OnClick>
<OnEnter>BenillaGroupLootFrame_Roll_OnEnter(self, PASS)</OnEnter>
<OnLeave>BenillaGroupLootFrame_Roll_OnLeave()</OnLeave>
</Scripts>
</Button>
<!-- Need (the dice, ref $parentRollButton, l.385-411). -->
<Button name="$parentRollButton">
<Size><AbsDimension x="32" y="32"/></Size>
<Anchors>
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-37" y="-14"/></Offset></Anchor>
</Anchors>
<NormalTexture file="Interface\Buttons\UI-GroupLoot-Dice-Up"/>
<HighlightTexture file="Interface\Buttons\UI-GroupLoot-Dice-Highlight" alphaMode="ADD"/>
<PushedTexture file="Interface\Buttons\UI-GroupLoot-Dice-Down"/>
<Scripts>
<OnClick>BenillaGroupLootFrame_Roll_OnClick(self, 1)</OnClick>
<OnEnter>BenillaGroupLootFrame_Roll_OnEnter(self, NEED)</OnEnter>
<OnLeave>BenillaGroupLootFrame_Roll_OnLeave()</OnLeave>
</Scripts>
</Button>
<!-- Greed (the coin, ref $parentGreedButton, l.412-438). -->
<Button name="$parentGreedButton">
<Size><AbsDimension x="32" y="32"/></Size>
<Anchors>
<Anchor point="TOP" relativeTo="$parentRollButton" relativePoint="BOTTOM">
<Offset><AbsDimension x="-2" y="2"/></Offset>
</Anchor>
</Anchors>
<NormalTexture file="Interface\Buttons\UI-GroupLoot-Coin-Up"/>
<HighlightTexture file="Interface\Buttons\UI-GroupLoot-Coin-Highlight" alphaMode="ADD"/>
<PushedTexture file="Interface\Buttons\UI-GroupLoot-Coin-Down"/>
<Scripts>
<OnClick>BenillaGroupLootFrame_Roll_OnClick(self, 2)</OnClick>
<OnEnter>BenillaGroupLootFrame_Roll_OnEnter(self, GREED)</OnEnter>
<OnLeave>BenillaGroupLootFrame_Roll_OnLeave()</OnLeave>
</Scripts>
</Button>
<!-- The 1-minute countdown bar (ref $parentTimer, l.439-473): 152x10, [0,60000] ms,
yellow UI-Character-Skills-Bar fill + its border overlay. -->
<StatusBar name="$parentTimer" drawLayer="BACKGROUND" minValue="0" maxValue="60000" defaultValue="0">
<Size><AbsDimension x="152" y="10"/></Size>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentSlotTexture" relativePoint="BOTTOMLEFT">
<Offset><AbsDimension x="13" y="10"/></Offset>
</Anchor>
</Anchors>
<Layers>
<Layer level="OVERLAY">
<Texture file="Interface\PaperDollInfoFrame\UI-Character-Skills-BarBorder">
<Size><AbsDimension x="156" y="20"/></Size>
<Anchors>
<Anchor point="TOP"><Offset><AbsDimension x="0" y="5"/></Offset></Anchor>
</Anchors>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnUpdate>BenillaGroupLootFrame_Timer_OnUpdate(self)</OnUpdate>
</Scripts>
<BarTexture name="$parentBar" file="Interface\PaperDollInfoFrame\UI-Character-Skills-Bar"/>
<BarColor r="1.0" g="1.0" b="0"/>
</StatusBar>
</Frames>
<!-- The plain dialog plate (ref l.475-485); swapped to the gold variant in OnShow for a BoP
roll. -->
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
<BackgroundInsets><AbsInset left="11" right="12" top="12" bottom="11"/></BackgroundInsets>
<TileSize><AbsValue val="32"/></TileSize>
<EdgeSize><AbsValue val="32"/></EdgeSize>
</Backdrop>
<Scripts>
<OnLoad>BenillaGroupLootFrame_OnLoad(self)</OnLoad>
<OnShow>BenillaGroupLootFrame_OnShow(self)</OnShow>
<OnEvent>BenillaGroupLootFrame_OnEvent(self)</OnEvent>
</Scripts>
</Frame>
<!-- The four instances (ref l.498-533): frame 1 at the ref's own hardcoded BOTTOM+60; each next
frame stacks on the previous one's TOP+15. -->
<Frame name="GroupLootFrame1" inherits="BenillaGroupLootFrameTemplate" id="1">
<Anchors>
<Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="60"/></Offset></Anchor>
</Anchors>
</Frame>
<Frame name="GroupLootFrame2" inherits="BenillaGroupLootFrameTemplate" id="2">
<Anchors>
<Anchor point="BOTTOM" relativeTo="GroupLootFrame1" relativePoint="TOP">
<Offset><AbsDimension x="0" y="15"/></Offset>
</Anchor>
</Anchors>
</Frame>
<Frame name="GroupLootFrame3" inherits="BenillaGroupLootFrameTemplate" id="3">
<Anchors>
<Anchor point="BOTTOM" relativeTo="GroupLootFrame2" relativePoint="TOP">
<Offset><AbsDimension x="0" y="15"/></Offset>
</Anchor>
</Anchors>
</Frame>
<Frame name="GroupLootFrame4" inherits="BenillaGroupLootFrameTemplate" id="4">
<Anchors>
<Anchor point="BOTTOM" relativeTo="GroupLootFrame3" relativePoint="TOP">
<Offset><AbsDimension x="0" y="15"/></Offset>
</Anchor>
</Anchors>
</Frame>
<!-- The START_LOOT_ROLL driver (header, "NO CENTRAL UIParent EVENT ROUTER"): the same shape as
DeathFrame.xml's BenillaDeathDriver — a tiny hidden frame whose sole job is owning the
registrations none of the four peer GroupLootFrames should have to special-case. -->
<Frame name="BenillaGroupLootFrameDriver" hidden="true">
<Size><AbsDimension x="1" y="1"/></Size>
<Anchors><Anchor point="TOPLEFT"/></Anchors>
<Scripts>
<OnLoad>
self:RegisterEvent("START_LOOT_ROLL")
self:RegisterEvent("CONFIRM_LOOT_ROLL")
</OnLoad>
<OnEvent>
if event == "START_LOOT_ROLL" then
BenillaGroupLootFrame_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
</OnEvent>
</Scripts>
</Frame>
</Ui>