- the vendor window is the reference's own `MerchantFrame.xml`, which took three things in order: the vendor cursor, the coin kit's move, and `GameTooltip:SetMerchantCompareItem` — where `offset` is the ordinal among CANDIDATE slots (empty ones skipped without decrementing) and a candidate matches by item CLASS and never by entry (two of four RE workers read it as an entry match, which would have fired the compare tooltip only when you already wear the identical item, i.e. never, with the window looking finished); two visible changes ride with the reference's rows — the coin columns take `SmallMoneyFrameTemplate`'s own geometry, and only the ICON takes the mouse, so hovering a row's name shows nothing, which is the client's behaviour - the gossip window is the reference's own, and its deferral was wrong: the "2px rows" were a harness gap (a bare test VM with no text measurer, while the app always installs one), not an engine one; four things the reference does that ours did not are pinned — a hidden SPACER row between the quest groups, coded options are NOT greyed (a coded row is clickable, and the send path's missing code is named as its own gap), the row label is the Button's own text, and the scroll child is not grown - the CAMP/QUIT dialogs and the PARTY_INVITE dialog move to `StaticPopup`'s home — the fourth such rehome of a dialog that had lived in whichever window first needed it — and moving them found a real bug: `button1 = CANCEL` captured a nil at load because `CANCEL` was declared below the insertion point, so the popup engine fell back and put "Yes" on the camp dialog's cancel button - three instruments: the gap report stops counting commented-out calls (`ShowInventorySellCursor` blocked the character sheet on three commented lines — a whole RE round spent on an over-report), it runs the load itself and answers in ONE table (29 "free" became 24 actually unblocked), and a shadow report predicts which swaps will fail by intersecting the names our files define with the names the chain files in our own manifest define — 38 collisions across 5 files, ours winning every one Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
361 lines
20 KiB
XML
361 lines
20 KiB
XML
<Ui>
|
|
<!--
|
|
The party member frames + the group-invite popup (decision 0434 phase 3). Geometry, art
|
|
paths and behavior laws are MEASURED against the reference client's own FrameXML, extracted
|
|
through the full MPQ patch chain (decision 0246; survey 2026-07-17):
|
|
PartyFrame.xml, PartyFrameTemplates.xml, PartyMemberFrame.lua, StaticPopup.lua ("PARTY_INVITE"),
|
|
UIParent.lua (the PARTY_INVITE_REQUEST wiring) — the code below is our own. Data flow is
|
|
ours too: the app feeds
|
|
party1..party4 unit snapshots + the PartyState roster (crates/benilla/src/ui_party.rs) and
|
|
fires the PARTY_* events; the popup's Accept/Decline queue PartyRequests the app drains.
|
|
|
|
THE CASCADE. The ref anchors frames 2-4 to the PREVIOUS frame's PetFrame bottom-left at
|
|
(-23,-10) — spacing rides the pet frame, which sits at (23,-27) when hidden (26 tall), so
|
|
the no-pet stride is TOPLEFT->BOTTOMLEFT (0,-10). Pet frames land in phase 4; until then
|
|
the cascade uses that no-pet stride directly, which is byte-identical to the ref's layout
|
|
for petless parties (the only kind phase 3 renders).
|
|
|
|
DEVIATIONS / DEFERRED (phase 4+, decision 0434):
|
|
- Pet frames, the 4 debuff buttons (48,-32 +2px chain), the 16/8 buff hover panel, and the
|
|
dispellable-debuff Status ring: they need the party aura/pet feed (phase 4).
|
|
(The PVP icon landed with decision 0646 — UnitFactionGroup exists now.)
|
|
- HIDE_PARTY_INTERFACE (hide-in-raid uvar): waits for the raid UI slice.
|
|
- Portrait: our high-res model bake (decision 0105), same as every unit frame.
|
|
- The ref's low-health portrait pulse flips alpha 127/255<->255/255 on 0.5 s half-cycles
|
|
(PartyMemberFrame.lua's sign-flip counter); transcribed as the same triangle wave.
|
|
|
|
DOUBLE-DECLINE, KEPT: the ref's popup calls DeclineGroup() in OnCancel AND again in OnHide
|
|
(only OnAccept sets the inviteAccepted guard), so a clicked Decline sends two
|
|
CMSG_GROUP_DECLINE. vmangos silently ignores the second (no pending invite -> early
|
|
return). Matched rather than "fixed" - the wire tolerates it and the guard's
|
|
real job is the timeout/override/escape paths.
|
|
-->
|
|
<Script><![CDATA[
|
|
-- MAX_RAID_MEMBERS / NUM_RAID_GROUPS / MEMBERS_PER_RAID_GROUP moved out. They were
|
|
-- declared here on the stated grounds that "we ship no RaidFrame.xml", which stopped being
|
|
-- true — RaidFrame.xml declares all three, which is the reference's own home for them
|
|
-- (RaidFrame.lua l.2-4). Nothing between the two manifest positions reads them at load.
|
|
-- The party's own bound (ref PartyMemberFrame.lua l.1) — four *other* members, so a full
|
|
-- party sweep that includes the player runs `1, MAX_PARTY_MEMBERS+1`, which is exactly how
|
|
-- GroupLootDropDown_Initialize walks the master-loot candidates (LootFrame.lua l.219).
|
|
-- Published for the same reason as its raid siblings: the addon corpus reads it.
|
|
MAX_PARTY_MEMBERS = 4
|
|
|
|
-- The PARTY_INVITE dialog and its PARTY_INVITE_REQUEST/_CANCEL driver MOVED OUT, to
|
|
-- UiPanels.xml — the reference's own homes for both (StaticPopup.lua l.526, UIParent.lua).
|
|
-- They were here only because this is where they were first needed; 1751 walked them back,
|
|
-- so this file is that much smaller when it follows them onto the chain.
|
|
|
|
-- ref PartyMemberFrame.lua's OnLoad: cache children, register, first paint.
|
|
function BenillaPartyFrame_OnLoad(frame)
|
|
local id = frame:GetID()
|
|
local name = frame:GetName()
|
|
local tf = name .. "TextureFrame"
|
|
frame.unit = "party" .. id
|
|
frame.portrait = getglobal(name .. "Portrait")
|
|
frame.healthbar = getglobal(name .. "HealthBar")
|
|
frame.manabar = getglobal(name .. "ManaBar")
|
|
-- The recessed-bar look, the reference's own mechanism (ref-TargetFrame.lua l.32-34):
|
|
-- push the bars one frame level BELOW the art's TextureFrame. Frame level is the only
|
|
-- key term above the draw layer (decision 0884), so this is the only thing that can hold
|
|
-- the BACKGROUND party art over the ARTWORK bar fills. See the LAYERING note below.
|
|
local textureFrameLevel = getglobal(tf):GetFrameLevel()
|
|
frame.healthbar:SetFrameLevel(textureFrameLevel - 1)
|
|
frame.manabar:SetFrameLevel(textureFrameLevel - 1)
|
|
frame.nameText = getglobal(tf .. "Name")
|
|
frame.leaderIcon = getglobal(tf .. "LeaderIcon")
|
|
frame.masterIcon = getglobal(tf .. "MasterIcon")
|
|
frame.disconnect = getglobal(tf .. "Disconnect")
|
|
frame.pvpIcon = getglobal(tf .. "PVPIcon")
|
|
frame.flashTimer = 0
|
|
SetPortraitTexture(frame.portrait, frame.unit)
|
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
frame:RegisterEvent("PARTY_MEMBERS_CHANGED")
|
|
frame:RegisterEvent("PARTY_LEADER_CHANGED")
|
|
frame:RegisterEvent("PARTY_LOOT_METHOD_CHANGED")
|
|
frame:RegisterEvent("UNIT_HEALTH")
|
|
frame:RegisterEvent("UNIT_MAXHEALTH")
|
|
frame:RegisterEvent("UNIT_POWER_UPDATE")
|
|
frame:RegisterEvent("UNIT_MAXPOWER")
|
|
frame:RegisterEvent("UNIT_DISPLAYPOWER")
|
|
frame:RegisterEvent("UNIT_NAME_UPDATE")
|
|
frame:RegisterEvent("UNIT_FACTION")
|
|
frame:EnableMouse(true)
|
|
BenillaPartyFrame_Update(frame)
|
|
end
|
|
|
|
function BenillaPartyFrame_OnEvent(frame)
|
|
-- UNIT_* events name their unit in arg1; other units' updates are not ours.
|
|
if string.sub(event, 1, 5) == "UNIT_" and arg1 ~= frame.unit then
|
|
return
|
|
end
|
|
BenillaPartyFrame_Update(frame)
|
|
end
|
|
|
|
-- ref PartyMemberHealthCheck: the portrait recolor law + the disconnect override.
|
|
function BenillaPartyFrame_HealthCheck(frame)
|
|
local unit = frame.unit
|
|
if not UnitIsConnected(unit) then
|
|
-- Disconnected: bar forced full and grey, portrait desaturated, icon on.
|
|
frame.healthbar:SetMinMaxValues(0, 1)
|
|
frame.healthbar:SetValue(1)
|
|
frame.healthbar:SetStatusBarColor(0.5, 0.5, 0.5)
|
|
SetDesaturation(frame.portrait, 1)
|
|
frame.disconnect:Show()
|
|
return
|
|
end
|
|
SetDesaturation(frame.portrait, nil)
|
|
frame.disconnect:Hide()
|
|
frame.healthbar:SetStatusBarColor(0.0, 1.0, 0.0)
|
|
local hp, hpMax = UnitHealth(unit), UnitHealthMax(unit)
|
|
if UnitIsDead(unit) then
|
|
frame.portrait:SetVertexColor(0.35, 0.35, 0.35, 1.0)
|
|
elseif UnitIsGhost(unit) then
|
|
frame.portrait:SetVertexColor(0.2, 0.2, 0.75, 1.0)
|
|
elseif hpMax > 0 and hp / hpMax <= 0.2 then
|
|
frame.portrait:SetVertexColor(1.0, 0.0, 0.0, 1.0)
|
|
else
|
|
frame.portrait:SetVertexColor(1.0, 1.0, 1.0, 1.0)
|
|
end
|
|
end
|
|
|
|
function BenillaPartyFrame_Update(frame)
|
|
local unit = frame.unit
|
|
if not UnitExists(unit) then
|
|
frame:Hide()
|
|
return
|
|
end
|
|
frame:Show()
|
|
|
|
frame.nameText:SetText(UnitName(unit) or "Unknown")
|
|
|
|
frame.healthbar:SetMinMaxValues(0, UnitHealthMax(unit))
|
|
frame.healthbar:SetValue(UnitHealth(unit))
|
|
|
|
local maxPower = UnitManaMax(unit)
|
|
if maxPower > 0 then
|
|
frame.manabar:Show()
|
|
local _, token = UnitPowerType(unit)
|
|
local c = BENILLA_POWER_COLORS[token] or BENILLA_POWER_COLORS.MANA
|
|
frame.manabar:SetStatusBarColor(c.r, c.g, c.b)
|
|
frame.manabar:SetMinMaxValues(0, maxPower)
|
|
frame.manabar:SetValue(UnitMana(unit))
|
|
else
|
|
frame.manabar:Hide()
|
|
end
|
|
|
|
-- Leader + master-looter icons (ref: GetPartyLeaderIndex / GetLootMethod vs own id).
|
|
local id = frame:GetID()
|
|
if GetPartyLeaderIndex() == id then
|
|
frame.leaderIcon:Show()
|
|
else
|
|
frame.leaderIcon:Hide()
|
|
end
|
|
local lootMethod, masterId = GetLootMethod()
|
|
if lootMethod == "master" and masterId == id then
|
|
frame.masterIcon:Show()
|
|
else
|
|
frame.masterIcon:Hide()
|
|
end
|
|
|
|
BenillaPartyFrame_HealthCheck(frame)
|
|
BenillaPartyFrame_UpdatePvP(frame)
|
|
end
|
|
|
|
-- ref PartyMemberFrame_UpdatePvPStatus (PartyMemberFrame.lua l.116-130), verbatim: the
|
|
-- same three branches the unit frames run, but the faction leg draws the GroupFrame art
|
|
-- (UI-Group-PVP-<group>) — only the FFA skull is shared with the big frames, because no
|
|
-- UI-Group-PVP-FFA ships. Decision 0646 §4; closes 0434's named deferral (the icon waited
|
|
-- on UnitFactionGroup, which the app now feeds).
|
|
function BenillaPartyFrame_UpdatePvP(frame)
|
|
local unit = frame.unit
|
|
local factionGroup = UnitFactionGroup(unit)
|
|
if UnitIsPVPFreeForAll(unit) then
|
|
frame.pvpIcon:SetTexture("Interface\\TargetingFrame\\UI-PVP-FFA")
|
|
frame.pvpIcon:Show()
|
|
elseif factionGroup and UnitIsPVP(unit) then
|
|
frame.pvpIcon:SetTexture("Interface\\GroupFrame\\UI-Group-PVP-" .. factionGroup)
|
|
frame.pvpIcon:Show()
|
|
else
|
|
frame.pvpIcon:Hide()
|
|
end
|
|
end
|
|
|
|
-- The ref's <=20% portrait alpha pulse: a 0.5 s-per-leg triangle between 127/255 and 1.
|
|
function BenillaPartyFrame_OnUpdate(frame, elapsed)
|
|
local unit = frame.unit
|
|
if not UnitExists(unit) or not UnitIsConnected(unit) then
|
|
return
|
|
end
|
|
local hp, hpMax = UnitHealth(unit), UnitHealthMax(unit)
|
|
if hpMax > 0 and hp > 0 and hp / hpMax <= 0.2 then
|
|
local t = mod(frame.flashTimer + elapsed, 1.0)
|
|
frame.flashTimer = t
|
|
local a
|
|
if t < 0.5 then
|
|
a = 1.0 - t * (1.0 - 127 / 255) * 2
|
|
else
|
|
a = 127 / 255 + (t - 0.5) * (1.0 - 127 / 255) * 2
|
|
end
|
|
frame.portrait:SetAlpha(a)
|
|
elseif frame.flashTimer ~= 0 then
|
|
frame.flashTimer = 0
|
|
frame.portrait:SetAlpha(1.0)
|
|
end
|
|
end
|
|
|
|
-- The hover tooltip: same law as the unit frames (default corner anchor + SetUnit).
|
|
function BenillaPartyFrame_OnEnter(frame)
|
|
if not UnitExists(frame.unit) then return end
|
|
GameTooltip_SetDefaultAnchor(GameTooltip, frame)
|
|
if GameTooltip:SetUnit(frame.unit) then
|
|
getglobal("GameTooltipTextLeft1"):SetTextColor(GameTooltip_UnitColor(frame.unit))
|
|
end
|
|
end
|
|
|
|
|
|
-- The right-click dropdown (decision 0434 phase 5; ref PartyMemberFrame.lua l.369-381)
|
|
-- + the ref's click law (l.226-237): left targets the member, right opens the PARTY
|
|
-- menu seated at the frame's (47, 15).
|
|
function PartyFrameDropDown_OnLoad()
|
|
UIDropDownMenu_Initialize(this, PartyFrameDropDown_Initialize, "MENU")
|
|
end
|
|
|
|
function PartyFrameDropDown_Initialize()
|
|
local dropdown
|
|
if UIDROPDOWNMENU_OPEN_MENU then
|
|
dropdown = getglobal(UIDROPDOWNMENU_OPEN_MENU)
|
|
else
|
|
dropdown = this
|
|
end
|
|
UnitPopup_ShowMenu(dropdown, "PARTY", "party" .. dropdown:GetParent():GetID())
|
|
end
|
|
|
|
function BenillaPartyFrame_OnClick(frame, button)
|
|
if button == "LeftButton" then
|
|
TargetUnit(frame.unit)
|
|
elseif button == "RightButton" then
|
|
ToggleDropDownMenu(1, nil, getglobal(frame:GetName() .. "DropDown"), frame:GetName(), 47, 15)
|
|
end
|
|
end
|
|
]]></Script>
|
|
|
|
<!-- The shared member-frame template — ref PartyFrameTemplates.xml, 128x53 over the 128x64
|
|
UI-PartyFrame art at (0,-2) (the art hangs 13 px below the frame rect, as authored).
|
|
|
|
LAYERING (the ref's law): the ref nests the frame art two anonymous child frames deep so it
|
|
draws OVER the status bars — the bars show through the art's semi-transparent tube windows,
|
|
inset, their ends clipped by the rails. Ours is the UnitFrames.xml idiom, which reaches the
|
|
same place by the ref's OTHER route (its TargetFrame's): a $parentTextureFrame child, with
|
|
OnLoad pushing the bars one frame level BELOW it. Both spend a frame LEVEL, which is the
|
|
point — level is the one key term above the draw layer (decision 0884). Until then this file
|
|
instead leaned on declaring the TextureFrame after the bars, and the old draw key's
|
|
insertion-order tie-break; 0884 pinned the layer as bucket-wide and above the frame, which
|
|
put the bars' ARTWORK fills straight over the BACKGROUND art. Do not go back to declaration
|
|
order. The name and the leader/master/disconnect icons ride in the TextureFrame too (the ref
|
|
keeps them in that nested frame; left below the art, the ring would swallow the leader
|
|
crown). -->
|
|
<!-- frameStrata LOW is the ref's own (`PartyFrameTemplates.xml` l.194) and it is load-bearing,
|
|
not decoration. The panel windows (loot, character, merchant, quest log, …) are MEDIUM, and
|
|
the party frames share the top-left corner with the left-slot panel. Left in the default
|
|
MEDIUM, a party frame's nested HealthBar/ManaBar/TextureFrame children land one frame LEVEL
|
|
above a panel's background region — and level outranks insertion order in the draw key, so
|
|
the party frame draws straight *through* the loot window no matter which was shown last.
|
|
Nothing about raising could have saved it: a raise only reorders within one stratum (wow-re
|
|
`system/ui/scratch/toplevel-raise.md`, dispatched for exactly this). Decision 0597. -->
|
|
<Frame name="BenillaPartyMemberTemplate" virtual="true" hidden="true" frameStrata="LOW">
|
|
<Size><AbsDimension x="128" y="53"/></Size>
|
|
<Layers>
|
|
<Layer level="BACKGROUND">
|
|
<!-- Portrait at the bottom of the stack; the art's round window shows it through. -->
|
|
<Texture name="$parentPortrait">
|
|
<Size><AbsDimension x="37" y="37"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="7" y="-6"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
</Layer>
|
|
</Layers>
|
|
<Frames>
|
|
<StatusBar name="$parentHealthBar">
|
|
<Size><AbsDimension x="70" y="8"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="47" y="-12"/></Offset></Anchor></Anchors>
|
|
<BarTexture file="Interface\TargetingFrame\UI-StatusBar"/>
|
|
<BarColor r="0" g="1.0" b="0"/>
|
|
</StatusBar>
|
|
<StatusBar name="$parentManaBar">
|
|
<Size><AbsDimension x="70" y="8"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="47" y="-21"/></Offset></Anchor></Anchors>
|
|
<BarTexture file="Interface\TargetingFrame\UI-StatusBar"/>
|
|
<BarColor r="0" g="0" b="1.0"/>
|
|
</StatusBar>
|
|
<!-- The PARTY-menu dropdown host (ref $parentDropDown): hidden state-holder only —
|
|
the list anchors to the member frame by name. -->
|
|
<Frame name="$parentDropDown" inherits="UIDropDownMenuTemplate" hidden="true">
|
|
<Size><AbsDimension x="10" y="10"/></Size>
|
|
<Anchors><Anchor point="TOP"><Offset><AbsDimension x="-20" y="-10"/></Offset></Anchor></Anchors>
|
|
<Scripts>
|
|
<OnLoad>PartyFrameDropDown_OnLoad()</OnLoad>
|
|
</Scripts>
|
|
</Frame>
|
|
<Frame name="$parentTextureFrame">
|
|
<Size><AbsDimension x="128" y="53"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
|
<Layers>
|
|
<Layer level="BACKGROUND">
|
|
<Texture name="$parentTexture" file="Interface\TargetingFrame\UI-PartyFrame">
|
|
<Size><AbsDimension x="128" y="64"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
</Layer>
|
|
<Layer level="OVERLAY">
|
|
<FontString name="$parentName" inherits="GameFontNormalSmall" justifyH="LEFT">
|
|
<Anchors><Anchor point="BOTTOMLEFT"><Offset><AbsDimension x="50" y="43"/></Offset></Anchor></Anchors>
|
|
</FontString>
|
|
<Texture name="$parentLeaderIcon" file="Interface\GroupFrame\UI-Group-LeaderIcon" hidden="true">
|
|
<Size><AbsDimension x="16" y="16"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
|
</Texture>
|
|
<Texture name="$parentMasterIcon" file="Interface\GroupFrame\UI-Group-MasterLooter" hidden="true">
|
|
<Size><AbsDimension x="16" y="16"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="32" y="0"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
<!-- The group PvP icon, 32x32 TOPLEFT (-9,-15) (ref PartyFrameTemplates.xml
|
|
l.298-309). Texture chosen at runtime — decision 0646 §4. -->
|
|
<Texture name="$parentPVPIcon" hidden="true">
|
|
<Size><AbsDimension x="32" y="32"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="-9" y="-15"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
<Texture name="$parentDisconnect" file="Interface\CharacterFrame\Disconnect-Icon" hidden="true">
|
|
<Size><AbsDimension x="64" y="64"/></Size>
|
|
<Anchors><Anchor point="LEFT"><Offset><AbsDimension x="-7" y="-1"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
</Layer>
|
|
</Layers>
|
|
</Frame>
|
|
</Frames>
|
|
<Scripts>
|
|
<OnLoad>BenillaPartyFrame_OnLoad(this)</OnLoad>
|
|
<OnEvent>BenillaPartyFrame_OnEvent(this)</OnEvent>
|
|
<OnUpdate>BenillaPartyFrame_OnUpdate(this, arg1)</OnUpdate>
|
|
<OnEnter>BenillaPartyFrame_OnEnter(this)</OnEnter>
|
|
<OnLeave>GameTooltip:FadeOut()</OnLeave>
|
|
<OnClick>BenillaPartyFrame_OnClick(this, arg1)</OnClick>
|
|
</Scripts>
|
|
</Frame>
|
|
|
|
<!-- The four instances — frame 1 at the ref's (10,-128); 2-4 cascade at the no-pet stride
|
|
(see the header note; the pet-frame anchor law returns with phase 4). -->
|
|
<Frame name="PartyMemberFrame1" inherits="BenillaPartyMemberTemplate" toplevel="true" parent="UIParent" id="1">
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-128"/></Offset></Anchor></Anchors>
|
|
</Frame>
|
|
<Frame name="PartyMemberFrame2" inherits="BenillaPartyMemberTemplate" toplevel="true" parent="UIParent" id="2">
|
|
<Anchors><Anchor point="TOPLEFT" relativeTo="PartyMemberFrame1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-10"/></Offset></Anchor></Anchors>
|
|
</Frame>
|
|
<Frame name="PartyMemberFrame3" inherits="BenillaPartyMemberTemplate" toplevel="true" parent="UIParent" id="3">
|
|
<Anchors><Anchor point="TOPLEFT" relativeTo="PartyMemberFrame2" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-10"/></Offset></Anchor></Anchors>
|
|
</Frame>
|
|
<Frame name="PartyMemberFrame4" inherits="BenillaPartyMemberTemplate" toplevel="true" parent="UIParent" id="4">
|
|
<Anchors><Anchor point="TOPLEFT" relativeTo="PartyMemberFrame3" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-10"/></Offset></Anchor></Anchors>
|
|
</Frame>
|
|
|
|
</Ui>
|