Files
benilla-octo/crates/benilla-app/assets/ui/BankFrame.xml
T
SamandClaude Fable 5 67315143f9 the bag windows are the real 1.12 files, and /walk actually walks
- the bag windows are the reference's own `ContainerFrame.xml` running off the player's patch chain — decision 1751 makes the stock 1.12 UI off the install the end state and `assets/ui` scaffolding that retires file-by-file (86 files against the 99-file stock corpus, 72% of the 1128-function global surface already built) — via one ordered manifest, `benilla.toc`, where a bare name is a file we ship and an `Interface\FrameXML\` path is the player's own file; the windows on screen are `ContainerFrame1..12`, the bank's six copy-pasted popouts fold into them at ids 5..10, net −750 lines, and the swap forced real engine verbs into being rather than stubs (`SetBagPortaitTexture` with its id-0 no-texture arm, `GameTooltip:AppendText`, `SetButtonPulse`, and a `<Model>` whose file is the cooldown indicator materializing as the native sweep, which three corpus addons inherit)
- the 1.12 walk toggle lands: `TOGGLERUN` latches one bit with `ToggleRun`'s own silent refusal chain (dead, rooted, on a live server spline), and the walk animation was never missing at all — the flag reaches it through exactly one channel, the speed (`0x5fd100` picks Walk over Run on `speed > 2 × walkSpeed`); pinning it caught our remote extrapolator with the two min rungs backwards — `min(walk, run)` runs BEFORE the backward min, so a walking backpedaller moves at 2.5 yd/s where we would have played them the Run clip at 4.5 — and one shared `current_speed` now keeps the local controller and the extrapolator from ever disagreeing about it
- the instance and raid lockout messages exist — six packets that were dropped as unknown opcodes now land, four of them as the CHAT_MSG_SYSTEM lines the client composes itself, which is why no Lua handler ever surfaced them — plus `IsInInstance`, `ResetInstances`, and the unit popup's "Reset all instances" row behind the reference's own predicate; where the binary contradicts vmangos: the ownership flag means "any instance bind" but vmangos only ever names raid binds, so the row was dead for every character without a raid lockout — term 1 is now also satisfied by our own eyes, walking out of a party dungeon the server itself bound us to
- opening the world map showed 3D world at the sheet's margins: `BlackoutWorld` was parented to the very `UIParent` a fullscreen panel hides, and three more frames had crossed the same boundary — the shared dropdown lists (so the map's continent and zone pickers answered a click with nothing at all), the master-looter menu, and the screenshot confirmation, which could never appear during a cinematic; `frame_flag_gate` now checks the parent seat against the reference both ways a frame acquires one (the attribute, template-inherited included, and `<Frames>` nesting), and its first harvest took 30 divergences down to three accepted ones

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 20:17:25 +07:00

890 lines
60 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<Ui>
<!--
benilla's bank window (decision 0604 phase 4): the vault is already streamed (the 24 bank
slots + 6 bank bags ride the descriptor at login, exactly like the backpack — see the
decision's "pinned mechanism"), so this file is purely the window over the existing
container/cursor plumbing. Geometry/art below are QUOTED from the real `BankFrame.xml`
(`WoW/_extracted_framexml/BankFrame.xml`/`.lua`, read this session — line-cited inline),
turned onto OUR house idioms per decision 0068/0084: no `ItemButtonTemplate`/
`SmallMoneyFrameTemplate`/`UIPanelButtonTemplate` ship, so every one of those is either a
cross-file `inherits` of a benilla template that already reconstructs the real art
(`BenillaBagSlotTemplate`, now in this file — see the kit banner below) or a local redraw
(the Purchase button, `UI-Panel-Button-*`, the house convention every NPC window already
uses — TrainerFrame.xml/QuestFrame.xml &c.).
MAXIMAL REUSE, per the phase-4 brief: the 24 generic slots (container `-1`) are 24
`BenillaBagSlotTemplate` buttons — the SAME click/drag/tooltip/stack-split/lock/cooldown
chain the bag windows use, just parented under a frame carrying `id="-1"` (this window
itself) so `button:GetParent():GetID()` resolves to `BANK_CONTAINER`.
THE SIX BANK-BAG WINDOWS ARE NO LONGER HERE (decision 1751). They were
`BenillaBankBagFrame1..6`, six copies of `BagFrame.xml`'s window template, and the reason
given at the time was that "this engine has no `ToggleBag`/`CloseBag` globals (grepped;
none exist)". It has them now — the reference's own, off the player's chain — and the bank
bags are what decision 0604 already said they were in the real client: **ordinary
ContainerFrames at ids NUM_BAG_SLOTS+1 .. +NUM_BANKBAGSLOTS**. So the 601 lines that copied
a window six times are gone and the bag buttons call `ToggleBag`, exactly as
`BankFrameItemButtonBag_OnClick` does. What this file still owes the reference's file is
`NUM_BAG_SLOTS` and `UpdateBagButtonHighlight`, which live where BankFrame.lua puts them.
DEVIATIONS from the raw reference quote (each load-bearing, none silent):
- The 24 generic slots reuse `BenillaBagSlot_Update`'s `physIndex` chain-resolution
(`slot = size - physIndex + 1`) rather than a bespoke direct mapping, so slot i's
button is loaded with `BenillaBagSlot_OnLoad(self, 25 - i)` — container `-1` is a FIXED
24 slots (never resized, decision 0604), so this reversal is a stable constant, not a
live recompute; it buys the exact same click/drag/split/lock/cooldown chain the bag
windows get for free, at the cost of the physIndex arithmetic reading backwards from
the reference's direct `id=i` (the reference's `BankFrameItem<i>` has no chain at all
since a real ContainerFrame's `id~=0` slot count is genuinely fixed at generation time —
our shared function always resolves dynamically, so the reversal is what makes button i
show slot i).
- The Purchase confirm popup (`CONFIRM_BUY_BANK_SLOT`) shows TEXT ONLY, no embedded cost —
the house's `StaticPopup` engine (`UiPanels.xml`) has no money-frame variant (the
`hasMoneyFrame` field the reference dialog carries is inert), the same accepted gap
`MailFrame.xml`'s `SEND_MONEY`/`DELETE_MONEY` popups already live with (that file's own
header note). The row's own Cost: coins (visible before you ever open the popup) carry
the affordability information instead.
- The close button is the house's `UI-Panel-MinimizeButton` at TOPRIGHT(-30,-8) — the
Merchant/Trainer/Mail convention — rather than the reference's CENTER-relative offset
against ITS OWN `UI-BankFrame` art's button recess (which our re-skin doesn't reproduce
pixel-for-pixel).
- ESC / `CloseAllWindows` closes the MAIN bank window (registered in `UiPanels.xml`'s
`UIPanelWindows`, which drives the whole chain generically) and its `OnHide` explicitly
closes every open bank-bag popout with it — but a popout is NOT independently in
`CloseAllWindows`'s hardcoded bag list (`UiPanels.xml`), so it would survive an ESC
press that DIDN'T close the bank frame itself (impossible today: nothing else occupies
the left slot while the bank is open without closing it first, so this is a latent gap,
not a reachable bug).
Money: reuses `BenillaMoney_Set`/`_SetColor` (`MerchantFrame.xml`, loaded first — the
established cross-window reuse `TrainerFrame.xml`/`BagFrame.xml` already lean on).
-->
<Script><![CDATA[
-- NUM_BAG_SLOTS is this file's in the reference too (BankFrame.lua:2), and it is read from
-- outside it: the sourced `ContainerFrame.lua` (1751) branches on it in
-- `ContainerFrame_OnShow` to tell an equipped bag from a bank bag, and `updateContainer
-- FrameAnchors` measures against `BankFrame`. Lua resolves at CALL time, so this file
-- sitting far below ContainerFrame.xml in the manifest is fine — but the ownership is the
-- reference's, not a convenience.
NUM_BAG_SLOTS = 4 -- (ref BankFrame.lua:2)
NUM_BANKGENERIC_SLOTS = 24 -- (ref BankFrame.lua:3)
NUM_BANKBAGSLOTS = 6 -- (ref BankFrame.lua:4)
-- ══ THE CONTAINER-SLOT KIT — moved here from BagFrame.xml with decision 1751's bag swap ══
--
-- `BenillaBagSlotTemplate` and the `BenillaBagSlot_*` bodies below were the bag WINDOWS'
-- slot machinery, and this window borrowed them for its 24 vault slots. The bag windows are
-- now the reference's own `ContainerFrame1..12`, executed off the player's chain (1751), and
-- their slots are the reference's `ContainerFrameItemButtonTemplate`. That leaves this
-- window as the kit's ONLY consumer, so the kit lives here — where the next migration
-- (BankFrame's own stock files, whose `BankItemButtonTemplate`/`BankFrameItemButton_*`
-- replace all of it) deletes it in one piece.
--
-- Names unchanged on purpose: 144 `inherits=` sites and ~145 `<OnLoad>` calls in this file
-- write them, and a rename would be churn on code whose whole future is deletion.
--
-- Fully generic over `button:GetParent():GetID()`, which is why the move is a move and not
-- a rewrite — this window carries `id="-1"` (BANK_CONTAINER) and its buttons resolve their
-- container from it exactly as a bag window's did from theirs.
-- BenillaBagSlot_OnLoad(button, physIndex): physIndex is the button's CHAIN position (1 =
-- bottom-right, growing up-and-left — the anchor order below), not the game slot. The ref's
-- own formula (index = size - j + 1, ContainerFrame.lua:426/446) maps chain position → game
-- slot dynamically in BenillaBagSlot_Update, so slot 1 always reads top-left regardless of
-- how many of the window's slots are actually occupied — recomputed every Update (the ref
-- only computes it once, at window generation; recomputing is a strict robustness win for
-- the rare live bag-swap case, not a behavior change for a size that never moves).
function BenillaBagSlot_OnLoad(button, physIndex)
button.physIndex = physIndex
button.icon = getglobal(button:GetName() .. "Icon")
button.count = getglobal(button:GetName() .. "Count")
-- Both buttons must reach OnClick (the default set is LeftButtonUp only): LEFT-click is the
-- pickup gesture (PickupContainerItem — pick up / place / swap on the cursor); RIGHT-click
-- cancels a held cursor, else uses the slot (the C side sells it when a merchant is open —
-- our container drain forks).
button:RegisterForClicks("LeftButtonUp", "RightButtonUp")
-- The drag trio (decision 0216 §3): click-carry and drag are ONE code path in the
-- reference (ContainerFrame.xml:40-55 routes OnDragStart/OnReceiveDrag to the same
-- OnClick("LeftButton", ignoreModifiers=1) the plain click uses) — see
-- BenillaBagSlot_OnClick below for the identical routing (its own `ignoreModifiers`
-- suppresses the shift-split fork, the reference's own contract for drag/receive).
button:RegisterForDrag("LeftButton")
BenillaBagSlot_Update(button)
end
function BenillaBagSlot_OnClick(button, mouseButton, ignoreModifiers)
if button.slot == nil then return end -- a hidden button (physIndex past the bag's size)
local bagId = button:GetParent():GetID()
if mouseButton == "LeftButton" then
-- The reference's own five returns (ContainerFrame.lua:241) — decision 1199
-- put this binding back on its 1.12 shape.
local texture, itemCount, locked, quality, readable =
GetContainerItemInfo(bagId, button.slot)
-- The modifier fork, the reference's own order (ContainerFrame.lua:563-579;
-- BankFrame.lua:141-152 for a bank slot, which is this same handler at container
-- -1). `ignoreModifiers` (the drag-trio calls, both true) suppresses it whole —
-- the reference's drag/receive contract.
--
-- CTRL: preview the item on your own character in the dressing room (decision 1060).
if IsControlKeyDown() and not ignoreModifiers then
DressUpItemLink(GetContainerItemLink(bagId, button.slot))
return
end
-- SHIFT: post the item's link into the chat edit box if it's open, ELSE split the
-- stack. The ref's own `else` (l.567-577) — and note it gates on `IsShown()` here
-- where its siblings use `IsVisible()`; ours are the same thing (the edit box's only
-- parent is UIParent), so the ref's own word is quoted at each site.
if IsShiftKeyDown() and not ignoreModifiers then
-- The visibility test is the REF'S fork, not the helper's: with chat open this
-- arm never splits, even in the one benilla state where nothing can be posted
-- (an unresolved template — `BenillaChatEdit_InsertLink`'s own note).
if ChatFrameEditBox and ChatFrameEditBox:IsShown() then
BenillaChatEdit_InsertLink(GetContainerItemLink(bagId, button.slot))
return
end
if texture ~= nil and not locked and (itemCount or 1) >= 2 then
button.SplitStack = function(btn, n)
SplitContainerItem(bagId, btn.slot, n)
BenillaBankFrame_RepaintItems()
end
-- Ref ContainerFrameItemButton_OnLoad/_OnClick (ContainerFrame.lua:558-560,
-- 573-576): the owner's own SplitStack closure carries the bag/slot so
-- StackSplitFrameOkay_Click's generic `owner.SplitStack(owner, split)` call
-- needs no window-specific knowledge. SplitContainerItem lives in cursor.rs
-- rather than container.rs — it is the one container-named verb whose
-- payload is the cursor's, not a bag's — but like every container verb it is
-- a plain top-level global (decision 1198).
OpenStackSplitFrame(itemCount, button, "BOTTOMRIGHT", "TOPRIGHT")
end
return
end
-- A plain click hides any open split frame (ref ContainerFrame.lua:581) before the
-- ordinary pickup/place proceeds.
local split = getglobal("StackSplitFrame")
if split then split:Hide() end
-- PickupContainerItem is the single drag entry point (real client): an empty cursor
-- picks this slot up; a held cursor places/swaps into it (same slot = cancel). Hide the
-- hover tooltip (the item just left the slot for the cursor) and repaint so the picked
-- slot dims / un-dims immediately — the swap itself settles when the server answers.
PickupContainerItem(bagId, button.slot)
GameTooltip:Hide()
BenillaBankFrame_RepaintItems()
elseif mouseButton == "RightButton" then
-- A held cursor cancels (client-side, nothing sent); otherwise use/equip/sell the slot.
if CursorHasItem() then
ClearCursor()
BenillaBankFrame_RepaintItems()
else
UseContainerItem(bagId, button.slot)
end
end
end
-- Hover: the era-true GameTooltip:SetBagItem(bag, slot) — the ENGINE renders the full
-- item tooltip from the template store and owns the sell-price money law (real instance
-- + merchant open + repair off ⇒ OnTooltipAddMoney(SellPrice × stack), or the
-- ITEM_UNSELLABLE line — wow-re ui/scratch/tooltip-money.md's byte-verified gate,
-- decision 0274 P1). The durability-adjusted damaged price is deferred until durability
-- damage reaches the feed (a pristine item reduces to SellPrice × stack, the case we
-- ship). Nothing shows while the template is in flight — the OnUpdate re-enter fills it.
function BenillaBagSlot_OnEnter(button)
if button.slot == nil then return end
local bagId = button:GetParent():GetID()
local texture, itemCount, locked, quality, readable =
GetContainerItemInfo(bagId, button.slot)
-- An emptied slot drops its tooltip (ref ContainerFrame_Update's texture-nil branch,
-- ContainerFrame.lua:281-283) — without this the OnUpdate re-enter below would leave
-- a stale tooltip up after the item is sold or moved out from under the hover.
if not texture then
if GameTooltip:IsOwned(button) then GameTooltip:Hide() end
return
end
-- Ref ContainerFrameItemButton_OnEnter (ContainerFrame.lua:602-612) verbatim: a slot
-- in the RIGHT half of the screen hangs its tooltip LEFT, so it never runs off the
-- edge (the bag lives at the bottom-right — this is the ref's own screen-edge answer,
-- a side-pick, not a clamp).
if (button:GetRight() or 0) >= (GetScreenWidth() / 2) then
GameTooltip:SetOwner(button, "ANCHOR_LEFT")
else
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
end
GameTooltip:SetBagItem(bagId, button.slot)
-- The pouch/magnifier cursor (ref ContainerFrameItemButton_OnEnter tail,
-- ContainerFrame.lua l.636-642): merchant open on the MERCHANT tab and not repair
-- mode → the sell cursor over this slot; else a readable item (a mail letter copy —
-- right-click opens the reader) → the Inspect magnifier; anything else restores the
-- base cursor. The OnUpdate re-enter keeps it current while hovering (the ref's own
-- loop). The ref's `IsControlKeyDown() and hasItem` magnifier arm (l.638) is the
-- dress-up preview's own cursor tell — it landed with the dressing room (decision
-- 1060); `info` is non-nil above, which is the ref's `hasItem`.
if MerchantFrame and MerchantFrame:IsShown()
and MerchantFrame.selectedTab == 1 and not InRepairMode() then
ShowContainerSellCursor(bagId, button.slot)
elseif readable or IsControlKeyDown() then
ShowInspectCursor()
else
ResetCursor()
end
GameTooltip:Show()
end
function BenillaBagSlot_OnLeave(button)
GameTooltip:Hide()
-- Ref ItemButton OnLeave (ContainerFrame.xml): the hover's sell cursor drops with it.
ResetCursor()
end
-- Ref ContainerFrameItemButton_OnUpdate (ContainerFrame.lua:645-660): while the tooltip
-- is ours, re-run OnEnter every frame — the ref ships this loop UNTHROTTLED (its
-- updateTooltip throttle is commented out in 1.12). It is the real client's own refresh
-- mechanism: a tooltip set while the item template was still in flight fills itself in
-- the moment the answer lands, no re-hover.
function BenillaBagSlot_OnUpdate(button)
if GameTooltip:IsOwned(button) then
BenillaBagSlot_OnEnter(button)
end
end
-- The item's use-cooldown sweep (ref ContainerFrame_UpdateCooldown,
-- ContainerFrame.lua:295-299, verbatim shape over our container dialect).
function BenillaBagSlot_UpdateCooldown(button, bagId)
local cooldown = getglobal(button:GetName() .. "Cooldown")
local start, duration, enable = GetContainerItemCooldown(bagId, button.slot)
CooldownFrame_SetTimer(cooldown, start, duration, enable)
end
-- The physIndex → game-slot resolution (the module doc above) + the paint (ref
-- ContainerFrame_Update, ContainerFrame.lua:234-293). Shared by every window's slot
-- buttons. The occupied/empty fork drives the cooldown exactly as the ref does
-- (l.248-253: occupied → UpdateCooldown, empty → Cooldown:Hide()).
function BenillaBagSlot_Update(button)
local bagId = button:GetParent():GetID()
local size = GetContainerNumSlots(bagId)
if button.physIndex > size then
button.slot = nil
button:Hide()
return
end
button.slot = size - button.physIndex + 1
button:Show()
local texture, itemCount, locked = GetContainerItemInfo(bagId, button.slot)
if texture ~= nil or itemCount ~= nil then
BenillaBagSlot_UpdateCooldown(button, bagId)
button.icon:SetTexture(texture or BENILLA_FALLBACK_ICON)
-- A locked slot (its item is up on the cursor, or a send is still pending
-- server-side, decision 0216 §4/0218 §3) dims, the real client's drag feedback.
if locked then
button.icon:SetVertexColor(0.4, 0.4, 0.4)
else
button.icon:SetVertexColor(1, 1, 1)
end
if (itemCount or 1) > 1 then
button.count:SetText(itemCount)
else
button.count:SetText("")
end
else
button.icon:SetTexture(nil)
button.count:SetText("")
getglobal(button:GetName() .. "Cooldown"):Hide()
end
end
function BankFrame_OnLoad()
local frame = this
-- Named directly rather than through `$parent .. "Portrait"`: the reference's bank
-- portrait is the UNPREFIXED global `BankPortraitTexture` (ref BankFrame.xml l.93),
-- one of the reference's own naming inconsistencies, and it is the name addons write.
-- `Bagnon_Core/Events.lua:41` does `SetPortraitTexture(BankPortraitTexture, "npc")`
-- when its "show Bagnon's bank instead" option is off, and against a nil first argument
-- that binding raises. Same standing lesson as `ToggleBackpack` / `CharacterBag0Slot`:
-- the name an addon reaches for is the reference's, not ours.
SetPortraitTexture(BankPortraitTexture, "npc")
frame:RegisterEvent("BANKFRAME_OPENED")
frame:RegisterEvent("BANKFRAME_CLOSED")
frame:RegisterEvent("PLAYERBANKSLOTS_CHANGED")
frame:RegisterEvent("PLAYERBANKBAGSLOTS_CHANGED")
frame:RegisterEvent("PLAYER_MONEY")
-- Container -1 is a container like any other: the same lock/cooldown maintenance
-- events a bag window registers (the reference's `ContainerFrame_OnLoad`), handled
-- below by BankFrame_OnEvent directly: this window's 24 slots are its own, painted by
-- BenillaBankFrame_RepaintItems over the slot kit above.
frame:RegisterEvent("ITEM_LOCK_CHANGED")
frame:RegisterEvent("BAG_UPDATE_COOLDOWN")
end
-- The banker's name arrives as arg1 of BANKFRAME_OPENED (the app resolves the banker guid
-- through the NameCache — the merchant/trainer feed's own ask-once pattern); nil/empty
-- until it lands, or if this ever fires with no name, falls back to "Banker".
function BenillaBankFrame_SetTitle(name)
if name == nil or name == "" then
name = "Banker"
end
getglobal("BankFrameTitleText"):SetText(name)
end
-- Repaint every one of the 24 generic slots (PLAYERBANKSLOTS_CHANGED names ONE slot; the
-- spec allows repainting all 24 — cheap, and spares tracking a slot->button map).
function BenillaBankFrame_RepaintItems()
for i = 1, NUM_BANKGENERIC_SLOTS do
local button = getglobal("BankItem" .. i)
if button then BenillaBagSlot_Update(button) end
end
end
-- The bag row (ref UpdateBagSlotStatus, BankFrame.lua:81-117): each button's icon from the
-- app-resolved BenillaGetBankBagTexture feed (falling back to the empty paper-doll bag
-- slot art), tinted white when purchased / red when not; the purchase row's cost coins +
-- afford color; the whole row hidden once GetNumBankSlots() reports `full`.
function BenillaBankFrame_UpdateBagRow()
local numSlots, full = GetNumBankSlots()
for i = 1, NUM_BANKBAGSLOTS do
local button = getglobal("BankBagButton" .. i)
if button then
local texture = BenillaGetBankBagTexture(i)
button.icon:SetTexture(texture or "Interface\\PaperDoll\\UI-PaperDoll-Slot-Bag")
if i <= numSlots then
button.icon:SetVertexColor(1.0, 1.0, 1.0)
button.tooltipText = "Bag Slot" -- BANK_BAG
else
button.icon:SetVertexColor(1.0, 0.1, 0.1)
button.tooltipText = "Purchasable Bag Slot" -- BANK_BAG_PURCHASE
end
end
end
local cost = GetBankSlotCost(numSlots)
BankFrame.nextSlotCost = cost
BenillaMoney_Set("BankFrameCostMoney", cost, true)
if GetMoney() >= cost then
BenillaMoney_SetColor("BankFrameCostMoney", 1.0, 1.0, 1.0)
else
BenillaMoney_SetColor("BankFrameCostMoney", 1.0, 0.1, 0.1)
end
local purchaseFrame = getglobal("BankFramePurchaseInfo")
if full then
purchaseFrame:Hide()
else
purchaseFrame:Show()
end
end
-- `UpdateBagSlotStatus()` — THE REFERENCE'S NAME for the pass above, published for the same
-- standing reason `ToggleBackpack` and `BagSlotButton_OnEnter` are: an addon calls the
-- client's global, and it must exist and do the job. `Bagnon_Core/Events.lua:46` calls it
-- from its own `ShowBlizBank()`, two lines after `SetPortraitTexture(BankPortraitTexture, …)`
-- above — the path taken whenever a player turns Bagnon's "show Bagnon at the bank" option
-- OFF and gets the stock window instead. It was nil, so that whole handler died there.
--
-- The reference's own body walks its `BankFrameBag1..6` and repaints
-- `BankFrameDetailMoneyFrame`; ours is the same pass over our own bag row and cost frame,
-- which is exactly what the reference's does for its window (it is not a shim: it is this
-- window's real update, under the name the client publishes it as).
function UpdateBagSlotStatus()
BenillaBankFrame_UpdateBagRow()
end
function BankFrame_OnEvent(event)
local frame = this
if event == "BANKFRAME_OPENED" then
BenillaBankFrame_SetTitle(arg1)
BenillaBankFrame_RepaintItems()
BenillaBankFrame_UpdateBagRow()
ShowUIPanel(frame)
elseif event == "BANKFRAME_CLOSED" then
HideUIPanel(frame)
elseif event == "PLAYERBANKSLOTS_CHANGED" then
BenillaBankFrame_RepaintItems()
elseif event == "PLAYERBANKBAGSLOTS_CHANGED" then
BenillaBankFrame_UpdateBagRow()
elseif event == "PLAYER_MONEY" then
BenillaMoney_Set("BankFrameMoney", GetMoney())
BenillaBankFrame_UpdateBagRow() -- the cost coins' afford color can flip too
elseif event == "ITEM_LOCK_CHANGED" then
if arg1 == -1 then
BenillaBankFrame_RepaintItems()
end
elseif event == "BAG_UPDATE_COOLDOWN" then
-- No bag argument (ref l.243-253's own shape) — BenillaBagSlot_Update's occupied
-- leg re-runs the cooldown sweep as part of the full 24-slot repaint.
BenillaBankFrame_RepaintItems()
end
end
function BenillaBankFrame_CloseButton_OnClick()
CloseBankFrame()
HideUIPanel(getglobal("BankFrame"))
end
-- CloseBankBagFrames (ref BankFrame.lua:119-123) — now VERBATIM, because the bank bags are
-- ordinary ContainerFrames again (1751): ids NUM_BAG_SLOTS+1 .. +NUM_BANKBAGSLOTS, closed
-- through the reference's own `CloseBag`. The button's lit ring follows from
-- `ContainerFrame_OnHide`, which calls `UpdateBagButtonHighlight` for every id above
-- NUM_BAG_SLOTS — so this no longer unchecks the buttons itself.
function CloseBankBagFrames()
for i = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do
CloseBag(i)
end
end
-- UpdateBagButtonHighlight(id) — ref BankFrame.lua:171-185, and the reference's own callers
-- are the sourced `ContainerFrame_OnShow`/`_OnHide`: every container id above NUM_BAG_SLOTS
-- routes its lit-state here instead of to a `CharacterBag<N>Slot`. Without it, opening a
-- bank bag raises inside the reference's file.
--
-- ONE DIVERGENCE, in the art and not the rule: the reference lights a dedicated
-- `BankFrameBag<n>HighlightFrameTexture` that its bag button carries; ours is a CheckButton
-- whose CheckedTexture is that highlight (this file's own lit-ring convention, shared with
-- the equipped-bag bar). So the same question — "is this bag's window open?" — writes
-- `SetChecked` rather than showing a texture, and `IsBagOpen` asks it instead of the
-- reference's open-coded ContainerFrame scan, which is the same scan under a name the
-- reference itself publishes.
function UpdateBagButtonHighlight(id)
local button = getglobal("BankBagButton" .. (id - NUM_BAG_SLOTS))
if not button then
return
end
button:SetChecked(IsBagOpen(id) and 1 or nil)
end
-- ── The 6 bag buttons (ref BankFrameItemButtonBag_OnClick/_OnShiftClick, BankFrame.lua:
-- 171-204): NOT container slots (they hold a whole BAG item, not a stack) — the doll
-- pickup idiom BagFrame.xml's BenillaBagBarSlot_* already established for the equipped
-- bag slots, reused verbatim here over BankButtonIDToInvSlotID's bag arm (id 1..6 ->
-- live 64..69). A held cursor item always PLACES; an empty cursor toggles the button's
-- popout window instead (ref: PutItemInBag first, ToggleBag only if that failed). ──
function BenillaBankBagButton_OnLoad(button, id)
button:SetID(id)
button.icon = getglobal(button:GetName() .. "Icon")
-- Both buttons, ref-verbatim (BankItemButtonBagTemplate's OnLoad runs
-- BankFrameBagButton_OnLoad -> BankFrameBaseButton_OnLoad, BankFrame.lua:12); the vault
-- slots get the same pair through BenillaBagSlot_OnLoad. The OnClick below reads no
-- button — right-click places/opens exactly as left does.
button:RegisterForClicks("LeftButtonUp", "RightButtonUp")
button:RegisterForDrag("LeftButton")
end
function BenillaBankBagButton_Place(button)
PickupInventoryItem(BankButtonIDToInvSlotID(button:GetID(), 1))
PlaySound("BAGMENUBUTTONPRESS")
end
function BenillaBankBagButton_OnClick(button)
if CursorHasItem() then
BenillaBankBagButton_Place(button)
return
end
-- A bank bag's window is a ContainerFrame like any other now (1751), at container id
-- NUM_BAG_SLOTS + <slot> — the reference's own arrangement, and the one decision 0604
-- quoted ("the reference reuses ContainerFrames for bank bags identically") before this
-- engine had `ToggleBag` to reuse them with. So the whole popout fork below is the
-- reference's single call, and `ToggleBag`'s own `size > 0` guard is the "only a slot
-- holding a bag opens" rule this file used to spell out.
local id = NUM_BAG_SLOTS + button:GetID()
PlaySound("BAGMENUBUTTONPRESS")
ToggleBag(id)
-- The lit ring: `ContainerFrame_OnShow`/`_OnHide` route here for a bank id, so this
-- tail is the ref's own (BankFrameItemButtonBag_OnClick l.195) and covers the case
-- ToggleBag declined — a bagless or unpurchased slot leaves the button unlit.
UpdateBagButtonHighlight(id)
end
function BenillaBankBagButton_OnEnter(button)
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
GameTooltip:SetText(button.tooltipText or "Bag Slot")
GameTooltip:Show()
end
-- The Purchase button (ref BankFramePurchaseButton OnClick, BankFrame.xml:478-482) + its
-- confirm popup (ref StaticPopup.lua CONFIRM_BUY_BANK_SLOT, l.47-58 — text-only here, see
-- the header's money-frame note). Accept queues PurchaseSlot(); the descriptor's byte-2
-- delta is the only success signal (decision 0604) — PLAYERBANKBAGSLOTS_CHANGED repaints.
function BenillaBankFramePurchaseButton_OnClick()
PlaySound("igMainMenuOption")
StaticPopup_Show("CONFIRM_BUY_BANK_SLOT")
end
StaticPopupDialogs["CONFIRM_BUY_BANK_SLOT"] = {
text = "Do you want to purchase a bank slot for:", -- CONFIRM_BUY_BANK_SLOT
button1 = "Yes",
button2 = "No",
OnAccept = function() PurchaseSlot() end,
timeout = 0,
hideOnEscape = 1,
}
]]></Script>
<!-- The container-slot BUTTON — see the kit banner in the script block above. Moved here from
BagFrame.xml with 1751's bag swap; this window's 24 vault slots are its only consumer. -->
<Button name="BenillaBagSlotTemplate" virtual="true">
<Size><AbsDimension x="37" y="37"/></Size>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentIcon"/>
</Layer>
<Layer level="OVERLAY">
<FontString name="$parentCount" inherits="NumberFontNormal" justifyH="RIGHT">
<Anchors>
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-5" y="2"/></Offset></Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<!-- The item's use-cooldown sweep (ref ContainerFrame.xml:13 — $parentCooldown
inherits CooldownFrameTemplate; ours is the native Cooldown widget, same as the
action buttons'). Driven by BenillaBagSlot_Update / BAG_UPDATE_COOLDOWN via
GetContainerItemCooldown + CooldownFrame_SetTimer (ActionBar.xml's transcription,
loaded before this file). -->
<Cooldown name="$parentCooldown" hidden="true">
<Size><AbsDimension x="36" y="36"/></Size>
<Anchors>
<Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor>
</Anchors>
</Cooldown>
</Frames>
<NormalTexture file="Interface\Buttons\UI-Quickslot2">
<Size><AbsDimension x="64" y="64"/></Size>
<Anchors>
<Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor>
</Anchors>
</NormalTexture>
<PushedTexture file="Interface\Buttons\UI-Quickslot-Depress"/>
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
<Scripts>
<OnClick>BenillaBagSlot_OnClick(self, arg1)</OnClick>
<OnEnter>BenillaBagSlot_OnEnter(self)</OnEnter>
<OnLeave>BenillaBagSlot_OnLeave(self)</OnLeave>
<OnUpdate>BenillaBagSlot_OnUpdate(self)</OnUpdate>
<!-- The drag trio (decision 0216 §3): both route to the SAME left-click path the
reference uses for both gestures (ContainerFrame.xml:40-55) — "LeftButton" hardcoded,
exactly as the reference calls it, since RegisterForDrag above only ever arms Left —
`true` (ignoreModifiers) suppresses the shift-split fork, matching the ref's own
ignoreModifiers contract for a drag/receive. -->
<OnDragStart>BenillaBagSlot_OnClick(self, "LeftButton", true)</OnDragStart>
<OnReceiveDrag>BenillaBagSlot_OnClick(self, "LeftButton", true)</OnReceiveDrag>
</Scripts>
</Button>
<!--
One bank-bag BUTTON (ref BankItemButtonBagTemplate, BankFrame.xml:46-74): the 37×37
UI-Quickslot2 ring, a CheckButton so it lights (CheckedTexture) while its popout is open —
the same lit-ring convention BagFrame.xml's BenillaBagBarSlot uses for the equipped bags.
-->
<CheckButton name="BenillaBankBagButtonTemplate" virtual="true">
<Size><AbsDimension x="37" y="37"/></Size>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentIcon"/>
</Layer>
</Layers>
<NormalTexture file="Interface\Buttons\UI-Quickslot2">
<Size><AbsDimension x="64" y="64"/></Size>
<Anchors><Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors>
</NormalTexture>
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
<Scripts>
<OnClick>BenillaBankBagButton_OnClick(self)</OnClick>
<OnEnter>BenillaBankBagButton_OnEnter(self)</OnEnter>
<OnLeave>GameTooltip:Hide()</OnLeave>
<OnDragStart>BenillaBankBagButton_Place(self)</OnDragStart>
<OnReceiveDrag>BenillaBankBagButton_Place(self)</OnReceiveDrag>
</Scripts>
</CheckButton>
<Frame name="BankFrame" enableMouse="true" toplevel="true" parent="UIParent" id="-1" hidden="true">
<!-- The real 384×512 window (ref l.77-90), with the reference's own default anchor.
ShowUIPanel/SetLeftFrame still SetPoints this to whichever slot it opens in (the NPC
session convention Merchant/Trainer/Mail share), and TOPLEFT (0,-104) is exactly what
the manager writes for the centre slot — so this changes nothing about where the window
lands, and everything about the window while it is HIDDEN.
It was `No <Anchors>` until decision 1751, and that was a real divergence with a real
consequence: an unanchored frame never resolves, so `BankFrame:GetRight()` answered nil
forever. The reference's own `updateContainerFrameAnchors` reads exactly that, on every
bag open and close (ContainerFrame.lua l.505), to decide whether the bags must shrink
to clear the bank — so with the bags now running off the player's chain, a bank window
with no rect took the whole bag layout down with it.
id="-1" = BANK_CONTAINER: the 24 item buttons below read it via GetParent():GetID(), the
SAME resolution the slot kit above uses for every other container. -->
<Size><AbsDimension x="384" y="512"/></Size>
<Anchors>
<Anchor point="TOPLEFT"><Offset><AbsDimension x="0" y="-104"/></Offset></Anchor>
</Anchors>
<Layers>
<Layer level="BACKGROUND">
<!-- NPC portrait 60×60 TOPLEFT (7,-6) (ref l.93-104), bound in OnLoad via
SetPortraitTexture(region, "npc"). The name is the REFERENCE'S, unprefixed —
its bank frame breaks the $parentPortrait convention every other window here
follows, and addons write the name the reference gave them. -->
<Texture name="BankPortraitTexture">
<Size><AbsDimension x="60" y="60"/></Size>
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="7" y="-6"/></Offset></Anchor></Anchors>
</Texture>
</Layer>
<Layer level="ARTWORK">
<!-- The whole window art, one 512×512 texture (ref l.107-114 — unlike Merchant/
Trainer's 4-quadrant re-skin, the reference Bank window is a single slab). -->
<Texture file="Interface\BankFrame\UI-BankFrame">
<Size><AbsDimension x="512" y="512"/></Size>
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
</Texture>
<!-- Title: the banker's name (ref BankFrameTitleText l.115-123, GameFontHighlight,
CENTER (6,233)); "Banker" until BANKFRAME_OPENED's arg1 lands. -->
<FontString name="BankFrameTitleText" inherits="GameFontHighlight" justifyH="CENTER" text="Banker">
<Anchors><Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="6" y="233"/></Offset></Anchor></Anchors>
</FontString>
<!-- Section labels (ref l.124-141: ITEMSLOTTEXT/BAGSLOTTEXT, GameFontNormal, CENTER
(-11,195) / (-11,-5)). -->
<FontString inherits="GameFontNormal" text="Item Slots" justifyH="CENTER">
<Anchors><Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="-11" y="195"/></Offset></Anchor></Anchors>
</FontString>
<FontString inherits="GameFontNormal" text="Bag Slots" justifyH="CENTER">
<Anchors><Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="-11" y="-5"/></Offset></Anchor></Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<!-- Close X: the house minimize-button convention (Merchant/Trainer/Mail), TOPRIGHT
(-30,-8) — see the header's deviation note on the reference's own offset. -->
<Button name="BankFrameCloseButton">
<Size><AbsDimension x="32" y="32"/></Size>
<Anchors><Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="-30" y="-8"/></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>BenillaBankFrame_CloseButton_OnClick()</OnClick></Scripts>
</Button>
<!-- The 24 generic item slots (ref BankFrameItem1..24, l.154-369): 6 cols × 4 rows,
TOPLEFT(40,-73), 12px column gap, -7px row gap — QUOTED verbatim. Each is a
BenillaBagSlotTemplate button (BagFrame.xml) read against container -1; physIndex
is `25 - i` so button i resolves to slot i (see the header's deviation note). -->
<Button name="BankItem1" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="40" y="-73"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 24)</OnLoad></Scripts>
</Button>
<Button name="BankItem2" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem1" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 23)</OnLoad></Scripts>
</Button>
<Button name="BankItem3" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem2" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 22)</OnLoad></Scripts>
</Button>
<Button name="BankItem4" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem3" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 21)</OnLoad></Scripts>
</Button>
<Button name="BankItem5" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem4" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 20)</OnLoad></Scripts>
</Button>
<Button name="BankItem6" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem5" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 19)</OnLoad></Scripts>
</Button>
<Button name="BankItem7" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-7"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 18)</OnLoad></Scripts>
</Button>
<Button name="BankItem8" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem7" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 17)</OnLoad></Scripts>
</Button>
<Button name="BankItem9" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem8" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 16)</OnLoad></Scripts>
</Button>
<Button name="BankItem10" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem9" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 15)</OnLoad></Scripts>
</Button>
<Button name="BankItem11" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem10" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 14)</OnLoad></Scripts>
</Button>
<Button name="BankItem12" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem11" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 13)</OnLoad></Scripts>
</Button>
<Button name="BankItem13" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem7" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-7"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 12)</OnLoad></Scripts>
</Button>
<Button name="BankItem14" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem13" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 11)</OnLoad></Scripts>
</Button>
<Button name="BankItem15" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem14" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 10)</OnLoad></Scripts>
</Button>
<Button name="BankItem16" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem15" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 9)</OnLoad></Scripts>
</Button>
<Button name="BankItem17" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem16" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 8)</OnLoad></Scripts>
</Button>
<Button name="BankItem18" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem17" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 7)</OnLoad></Scripts>
</Button>
<Button name="BankItem19" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem13" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-7"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 6)</OnLoad></Scripts>
</Button>
<Button name="BankItem20" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem19" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 5)</OnLoad></Scripts>
</Button>
<Button name="BankItem21" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem20" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 4)</OnLoad></Scripts>
</Button>
<Button name="BankItem22" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem21" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 3)</OnLoad></Scripts>
</Button>
<Button name="BankItem23" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem22" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 2)</OnLoad></Scripts>
</Button>
<Button name="BankItem24" inherits="BenillaBagSlotTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem23" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 1)</OnLoad></Scripts>
</Button>
<!-- The 6 bag buttons (ref BankFrameBag1..6 id=5..10, l.372-425): under item19, 12px
column gap. Button id = the bag-button number (1..6, what BankButtonIDToInvSlotID
and BenillaGetBankBagTexture expect) — NOT the container id (5..10), which the
popout windows below carry instead via their own `id=`. -->
<CheckButton name="BankBagButton1" inherits="BenillaBankBagButtonTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankItem19" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-32"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBankBagButton_OnLoad(self, 1)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BankBagButton2" inherits="BenillaBankBagButtonTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankBagButton1" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBankBagButton_OnLoad(self, 2)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BankBagButton3" inherits="BenillaBankBagButtonTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankBagButton2" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBankBagButton_OnLoad(self, 3)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BankBagButton4" inherits="BenillaBankBagButtonTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankBagButton3" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBankBagButton_OnLoad(self, 4)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BankBagButton5" inherits="BenillaBankBagButtonTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankBagButton4" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBankBagButton_OnLoad(self, 5)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BankBagButton6" inherits="BenillaBankBagButtonTemplate">
<Anchors><Anchor point="TOPLEFT" relativeTo="BankBagButton5" relativePoint="TOPRIGHT"><Offset><AbsDimension x="12" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaBankBagButton_OnLoad(self, 6)</OnLoad></Scripts>
</CheckButton>
<!-- The purchase row (ref BankFramePurchaseInfo, l.426-500): 300×72, CENTER of the
window (-15,-105). House coin rig (BenillaMoney_Set) in place of the reference's
SmallMoneyFrameTemplate; the Purchase button is a local UI-Panel-Button redraw (no
UIPanelButtonTemplate ships — the house convention every NPC window uses). -->
<Frame name="BankFramePurchaseInfo">
<Size><AbsDimension x="300" y="72"/></Size>
<Anchors><Anchor point="CENTER" relativeTo="BankFrame" relativePoint="CENTER"><Offset><AbsDimension x="-15" y="-105"/></Offset></Anchor></Anchors>
<Layers>
<Layer level="BACKGROUND">
<FontString inherits="GameFontHighlight" text="Do you wish to purchase space for an additional bag?" justifyH="LEFT">
<Size><AbsDimension x="280" y="0"/></Size>
<Anchors><Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="10" y="20"/></Offset></Anchor></Anchors>
</FontString>
<FontString name="BankFrameCostLabel" inherits="GameFontNormal" text="Cost:" justifyH="LEFT">
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="30" y="-10"/></Offset></Anchor></Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<Frame name="BankFrameCostMoneyCoin1">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="LEFT" relativeTo="BankFrameCostLabel" relativePoint="RIGHT"><Offset><AbsDimension x="4" y="0"/></Offset></Anchor></Anchors>
<Layers><Layer level="OVERLAY">
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons"><Size><AbsDimension x="13" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors><TexCoords left="0" right="0.25" top="0" bottom="1"/></Texture>
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT"><Size><AbsDimension x="20" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors></FontString>
</Layer></Layers>
</Frame>
<Frame name="BankFrameCostMoneyCoin2">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="LEFT" relativeTo="BankFrameCostMoneyCoin1" relativePoint="RIGHT"><Offset><AbsDimension x="4" y="0"/></Offset></Anchor></Anchors>
<Layers><Layer level="OVERLAY">
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons"><Size><AbsDimension x="13" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors><TexCoords left="0.25" right="0.5" top="0" bottom="1"/></Texture>
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT"><Size><AbsDimension x="20" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors></FontString>
</Layer></Layers>
</Frame>
<Frame name="BankFrameCostMoneyCoin3">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="LEFT" relativeTo="BankFrameCostMoneyCoin2" relativePoint="RIGHT"><Offset><AbsDimension x="4" y="0"/></Offset></Anchor></Anchors>
<Layers><Layer level="OVERLAY">
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons"><Size><AbsDimension x="13" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors><TexCoords left="0.5" right="0.75" top="0" bottom="1"/></Texture>
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT"><Size><AbsDimension x="20" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors></FontString>
</Layer></Layers>
</Frame>
<Button name="BankFramePurchaseButton" text="Purchase">
<Size><AbsDimension x="124" y="21"/></Size>
<Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-20" y="-10"/></Offset></Anchor></Anchors>
<NormalFont inherits="GameFontNormal"/>
<HighlightFont inherits="GameFontHighlight"/>
<DisabledFont inherits="GameFontDisable"/>
<NormalTexture file="Interface\Buttons\UI-Panel-Button-Up"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></NormalTexture>
<PushedTexture file="Interface\Buttons\UI-Panel-Button-Down"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></PushedTexture>
<DisabledTexture file="Interface\Buttons\UI-Panel-Button-Disabled"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></DisabledTexture>
<HighlightTexture file="Interface\Buttons\UI-Panel-Button-Highlight" alphaMode="ADD"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></HighlightTexture>
<Scripts><OnClick>BenillaBankFramePurchaseButton_OnClick()</OnClick></Scripts>
</Button>
</Frames>
</Frame>
<!-- The player's own money (ref BankFrameMoneyFrame, l.501-509: BOTTOMRIGHT(-38,102)).
Same right-to-left coin chain as MerchantFrame's purse — copper-first, right-flush
off Coin1 (BenillaMoney_Set's own module doc, MerchantFrame.xml). -->
<Frame name="BankFrameMoneyCoin1">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-51" y="102"/></Offset></Anchor></Anchors>
<Layers><Layer level="OVERLAY">
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons"><Size><AbsDimension x="13" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors><TexCoords left="0.5" right="0.75" top="0" bottom="1"/></Texture>
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT"><Size><AbsDimension x="20" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors></FontString>
</Layer></Layers>
</Frame>
<Frame name="BankFrameMoneyCoin2">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="RIGHT" relativeTo="BankFrameMoneyCoin1" relativePoint="LEFT"><Offset><AbsDimension x="-4" y="0"/></Offset></Anchor></Anchors>
<Layers><Layer level="OVERLAY">
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons"><Size><AbsDimension x="13" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors><TexCoords left="0.25" right="0.5" top="0" bottom="1"/></Texture>
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT"><Size><AbsDimension x="20" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors></FontString>
</Layer></Layers>
</Frame>
<Frame name="BankFrameMoneyCoin3">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="RIGHT" relativeTo="BankFrameMoneyCoin2" relativePoint="LEFT"><Offset><AbsDimension x="-4" y="0"/></Offset></Anchor></Anchors>
<Layers><Layer level="OVERLAY">
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons"><Size><AbsDimension x="13" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors><TexCoords left="0" right="0.25" top="0" bottom="1"/></Texture>
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT"><Size><AbsDimension x="20" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors></FontString>
</Layer></Layers>
</Frame>
</Frames>
<Scripts>
<OnLoad>BankFrame_OnLoad()</OnLoad>
<OnEvent>BankFrame_OnEvent(event)</OnEvent>
<!-- OnShow/OnHide (ref l.518-526): OpenBackpack/CloseBackpack per the 0561 contract
(MerchantFrame.xml's own placement is the model); the reference OnHide order
(CloseBankBagFrames(); CloseBankFrame(); PlaySound(...)) kept exactly, with
CloseBackpack folded in at the Merchant convention's spot. -->
<OnShow>OpenBackpack(); PlaySound("igMainMenuOpen")</OnShow>
<OnHide>CloseBankBagFrames(); CloseBankFrame(); CloseBackpack(); PlaySound("igMainMenuClose")</OnHide>
</Scripts>
</Frame>
</Ui>