3 Commits
aas .. a

Author SHA1 Message Date
Relationship 021a103dbc Add files via upload 2026-07-13 19:29:56 +01:00
Relationship 1d9d713476 Add files via upload 2026-07-12 12:44:17 +01:00
Relationship 885846b676 Add files via upload 2026-07-11 11:34:17 +01:00
3 changed files with 139 additions and 70 deletions
+101 -34
View File
@@ -47,6 +47,17 @@ local ARENA_IDS = {
local MARKS_WIN = 3 local MARKS_WIN = 3
local MARKS_LOSS = 1 local MARKS_LOSS = 1
-- TurtleWoW / OctoWoW (Patch 1.18.1+) use an accumulative honor system.
-- The value reported on the battleground scoreboard (honorGained from
-- GetBattlefieldScore) is the old-style number, but only 10% of it is
-- actually credited to the player as spendable Honor currency. Costs of
-- gear/items were reduced to match. So spendable = floor(scoreboard * 0.10).
local HONOR_SPEND_FACTOR = 0.10
local function SpendableHonor(h)
return math.floor((h or 0) * HONOR_SPEND_FACTOR)
end
local currentBG = nil local currentBG = nil
local endReported = {} local endReported = {}
@@ -63,7 +74,7 @@ local totalRow = nil
--------------------------------------------------------------- ---------------------------------------------------------------
local function NewStatBlock() local function NewStatBlock()
return { return {
wins = 0, losses = 0, wins = 0, draws = 0, losses = 0,
kills = 0, deaths = 0, hk = 0, kills = 0, deaths = 0, hk = 0,
marks = 0, honor = 0, marks = 0, honor = 0,
bestKB = 0, streak = 0, bestStreak = 0, bestKB = 0, streak = 0, bestStreak = 0,
@@ -84,6 +95,7 @@ local function EnsureDB()
if s.bestStreak == nil then s.bestStreak = 0 end if s.bestStreak == nil then s.bestStreak = 0 end
if s.hk == nil then s.hk = 0 end if s.hk == nil then s.hk = 0 end
if s.marks == nil then s.marks = 0 end if s.marks == nil then s.marks = 0 end
if s.draws == nil then s.draws = 0 end
db.stats[k] = s db.stats[k] = s
end end
return db return db
@@ -309,9 +321,18 @@ local function RecordEnd(key, index)
if not s then return end if not s then return end
local playerWon = false local playerWon = false
local isDraw = false
local winner = GetBattlefieldWinner() local winner = GetBattlefieldWinner()
if winner then if winner then
local myFaction = UnitFactionGroup("player") local myFaction = UnitFactionGroup("player")
-- Some server builds (incl. Turtle/Octo) report a draw as a winner
-- value that is neither 0 (Horde) nor 1 (Alliance). Treat anything
-- else as a draw so it isn't miscounted as a loss.
isDraw = (winner ~= 0 and winner ~= 1)
if isDraw then
s.draws = s.draws + 1
s.streak = 0
else
local wonAsAlliance = (winner == 1 and myFaction == "Alliance") local wonAsAlliance = (winner == 1 and myFaction == "Alliance")
local wonAsHorde = (winner == 0 and myFaction == "Horde") local wonAsHorde = (winner == 0 and myFaction == "Horde")
playerWon = wonAsAlliance or wonAsHorde playerWon = wonAsAlliance or wonAsHorde
@@ -323,8 +344,10 @@ local function RecordEnd(key, index)
s.losses = s.losses + 1 s.losses = s.losses + 1
s.streak = 0 s.streak = 0
end end
end
local isBG = (key == "AV" or key == "WSG" or key == "AB") local isBG = (key == "AV" or key == "WSG" or key == "AB")
if isBG then if isBG then
-- Draws award the loss-tier mark count.
s.marks = s.marks + (playerWon and MARKS_WIN or MARKS_LOSS) s.marks = s.marks + (playerWon and MARKS_WIN or MARKS_LOSS)
end end
end end
@@ -352,9 +375,15 @@ local function RecordEnd(key, index)
if key == "AV" or key == "WSG" or key == "AB" then if key == "AV" or key == "WSG" or key == "AB" then
marksMsg = " +" .. (playerWon and MARKS_WIN or MARKS_LOSS) .. " marks" marksMsg = " +" .. (playerWon and MARKS_WIN or MARKS_LOSS) .. " marks"
end end
Print(BG_NAMES[key] .. " recorded (" local outcomeStr
.. (playerWon and "|cff66ff66win|r" or "|cffff6666loss|r") if isDraw then
.. marksMsg .. ").") outcomeStr = "|cffffff66draw|r"
elseif playerWon then
outcomeStr = "|cff66ff66win|r"
else
outcomeStr = "|cffff6666loss|r"
end
Print(BG_NAMES[key] .. " recorded (" .. outcomeStr .. marksMsg .. ").")
end end
--------------------------------------------------------------- ---------------------------------------------------------------
@@ -362,41 +391,71 @@ end
--------------------------------------------------------------- ---------------------------------------------------------------
-- Auto-close the Blizzard PvP panels if they pop up as a side effect -- Auto-close the Blizzard PvP panels if they pop up as a side effect
-- of the arena / BG queueing calls. -- of the arena / BG queueing calls.
-- NOTE: We deliberately do NOT call HideUIPanel() here. HideUIPanel on a
-- frame that Blizzard's UI panel system has slotted into a left/center
-- slot triggers a slot reflow, which is what caused Character / Friends /
-- Spellbook panels to jump to the middle of the screen after the PvP
-- panel was opened. Directly calling :Hide() bypasses the slot manager
-- entirely; the slot suppression below (SuppressUIPanelWindows) ensures
-- Blizzard never registered a slot for these frames to begin with.
local function HidePvPPanels() local function HidePvPPanels()
if BattlefieldFrame and BattlefieldFrame:IsVisible() then HideUIPanel(BattlefieldFrame) end if BattlefieldFrame and BattlefieldFrame:IsVisible() then BattlefieldFrame:Hide() end
if PVPBattlegroundFrame and PVPBattlegroundFrame:IsVisible() then HideUIPanel(PVPBattlegroundFrame) end if PVPBattlegroundFrame and PVPBattlegroundFrame:IsVisible() then PVPBattlegroundFrame:Hide() end
if PVPFrame and PVPFrame:IsVisible() then HideUIPanel(PVPFrame) end if PVPFrame and PVPFrame:IsVisible() then PVPFrame:Hide() end
if HonorFrame and HonorFrame:IsVisible() then HideUIPanel(HonorFrame) end if HonorFrame and HonorFrame:IsVisible() then HonorFrame:Hide() end
end end
-- Suppress the PvP panel entirely while we are auto-queueing. Reference-counted -- Suppress the PvP panel entirely while we are auto-queueing. Reference-counted
-- so nested queues (Queue All BGs) do not release too early. -- so nested queues (Queue All BGs) do not release too early.
--
-- IMPORTANT: We previously hijacked BattlefieldFrame.Show / PVPBattlegroundFrame.Show
-- to no-op during suppression. That was the source of the "Character / Friends
-- panels jump to the middle of the screen" bug: Blizzard's ShowUIPanel() first
-- allocates a UI panel slot (left / center / doublewide) via UIPanelWindows,
-- THEN calls frame:Show(). Silently dropping :Show() left the slot reserved by
-- an invisible frame, so the next panel the user opened (Character, Friends,
-- Spellbook, ...) got shoved into a different slot -> centered.
--
-- The correct approach on 1.12 is to temporarily remove these frames from
-- UIPanelWindows while suppressing, so ShowUIPanel treats them as plain
-- frames and never allocates a slot. When suppression ends, the original
-- UIPanelWindows entries are restored so normal Blizzard UI behaviour is
-- preserved for the rest of the session.
local suppressPanels = 0 local suppressPanels = 0
local suppressHooked = false local savedUIPanelEntries = nil
local origBattlefieldShow, origPVPBGShow
local function InstallPanelSuppressor() local SUPPRESSED_PANEL_NAMES = {
if suppressHooked then return end "BattlefieldFrame",
suppressHooked = true "PVPBattlegroundFrame",
if BattlefieldFrame then "PVPFrame",
origBattlefieldShow = BattlefieldFrame.Show "HonorFrame",
BattlefieldFrame.Show = function(self, ...) }
if suppressPanels > 0 then return end
origBattlefieldShow(self) local function SuppressUIPanelWindows()
end if savedUIPanelEntries then return end
end savedUIPanelEntries = {}
if PVPBattlegroundFrame then if type(UIPanelWindows) ~= "table" then return end
origPVPBGShow = PVPBattlegroundFrame.Show for i = 1, table.getn(SUPPRESSED_PANEL_NAMES) do
PVPBattlegroundFrame.Show = function(self, ...) local name = SUPPRESSED_PANEL_NAMES[i]
if suppressPanels > 0 then return end savedUIPanelEntries[name] = UIPanelWindows[name]
origPVPBGShow(self) UIPanelWindows[name] = nil
end
end end
end end
local function RestoreUIPanelWindows()
if not savedUIPanelEntries then return end
if type(UIPanelWindows) == "table" then
for i = 1, table.getn(SUPPRESSED_PANEL_NAMES) do
local name = SUPPRESSED_PANEL_NAMES[i]
UIPanelWindows[name] = savedUIPanelEntries[name]
end
end
savedUIPanelEntries = nil
end
local function BeginSuppress() local function BeginSuppress()
InstallPanelSuppressor()
suppressPanels = suppressPanels + 1 suppressPanels = suppressPanels + 1
SuppressUIPanelWindows()
HidePvPPanels() HidePvPPanels()
end end
@@ -404,6 +463,9 @@ local function EndSuppress()
suppressPanels = suppressPanels - 1 suppressPanels = suppressPanels - 1
if suppressPanels < 0 then suppressPanels = 0 end if suppressPanels < 0 then suppressPanels = 0 end
HidePvPPanels() HidePvPPanels()
if suppressPanels == 0 then
RestoreUIPanelWindows()
end
end end
-- Central pending-queue state. `pendingQueue` is a FIFO of items: -- Central pending-queue state. `pendingQueue` is a FIFO of items:
@@ -763,10 +825,10 @@ end
--------------------------------------------------------------- ---------------------------------------------------------------
-- UI: build row FontStrings inside the stats panel -- UI: build row FontStrings inside the stats panel
--------------------------------------------------------------- ---------------------------------------------------------------
local COL_X = { 14, 158, 208, 258, 308, 354, 400, 446, 496, 550, 614 } local COL_X = { 14, 158, 208, 258, 308, 358, 408, 454, 500, 550, 604, 664, 744 }
local COL_W = { 140, 46, 46, 46, 46, 46, 46, 46, 50, 60, 58 } local COL_W = { 140, 46, 46, 46, 46, 46, 46, 46, 46, 50, 56, 76, 56 }
local COL_J = { "LEFT", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER" } local COL_J = { "LEFT", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER", "CENTER" }
local COL_NAMES = { "bg", "games", "win", "loss", "ratio", "kb", "hk", "dth", "kd", "honor", "mk" } local COL_NAMES = { "bg", "games", "win", "draw", "loss", "ratio", "kb", "hk", "dth", "kd", "honor", "spend", "mk" }
local ROW_HEIGHT = 22 local ROW_HEIGHT = 22
local ROW_TOP = -34 local ROW_TOP = -34
@@ -776,7 +838,7 @@ local function MakeRow(panel, tag, yOff, striped)
if striped then if striped then
local bg = panel:CreateTexture("RPVPRowBG"..tag, "BACKGROUND") local bg = panel:CreateTexture("RPVPRowBG"..tag, "BACKGROUND")
bg:SetTexture(1, 1, 1, 0.04) bg:SetTexture(1, 1, 1, 0.04)
bg:SetWidth(660); bg:SetHeight(ROW_HEIGHT - 2) bg:SetWidth(786); bg:SetHeight(ROW_HEIGHT - 2)
bg:SetPoint("TOPLEFT", panel, "TOPLEFT", 14, yOff + 2) bg:SetPoint("TOPLEFT", panel, "TOPLEFT", 14, yOff + 2)
end end
for c = 1, table.getn(COL_NAMES) do for c = 1, table.getn(COL_NAMES) do
@@ -812,7 +874,7 @@ local function BuildStatsRows()
local totalY = ROW_TOP - n * ROW_HEIGHT - 4 local totalY = ROW_TOP - n * ROW_HEIGHT - 4
local div = panel:CreateTexture("RPVPTotalDivider", "ARTWORK") local div = panel:CreateTexture("RPVPTotalDivider", "ARTWORK")
div:SetTexture(1, 1, 1, 0.25) div:SetTexture(1, 1, 1, 0.25)
div:SetWidth(660); div:SetHeight(1) div:SetWidth(786); div:SetHeight(1)
div:SetPoint("TOPLEFT", panel, "TOPLEFT", 14, totalY + 2) div:SetPoint("TOPLEFT", panel, "TOPLEFT", 14, totalY + 2)
totalRow = MakeRow(panel, "TOTAL", totalY - 6, false) totalRow = MakeRow(panel, "TOTAL", totalY - 6, false)
@@ -847,7 +909,8 @@ local function FormatQueueLine()
end end
local function FillRow(r, s) local function FillRow(r, s)
local games = s.wins + s.losses local draws = s.draws or 0
local games = s.wins + draws + s.losses
local pct = 0 local pct = 0
if games > 0 then pct = math.floor((s.wins / games) * 100 + 0.5) end if games > 0 then pct = math.floor((s.wins / games) * 100 + 0.5) end
local kd = "-" local kd = "-"
@@ -859,6 +922,7 @@ local function FillRow(r, s)
r.games:SetText(games) r.games:SetText(games)
r.win:SetText(s.wins) r.win:SetText(s.wins)
r.draw:SetText(draws)
r.loss:SetText(s.losses) r.loss:SetText(s.losses)
r.ratio:SetText(pct .. "%") r.ratio:SetText(pct .. "%")
r.kb:SetText(s.kills) r.kb:SetText(s.kills)
@@ -866,6 +930,7 @@ local function FillRow(r, s)
r.dth:SetText(s.deaths) r.dth:SetText(s.deaths)
r.kd:SetText(kd) r.kd:SetText(kd)
r.honor:SetText(FormatNumber(s.honor)) r.honor:SetText(FormatNumber(s.honor))
r.spend:SetText(FormatNumber(SpendableHonor(s.honor)))
r.mk:SetText(s.marks) r.mk:SetText(s.marks)
if games == 0 then if games == 0 then
@@ -892,6 +957,7 @@ function RelationshipsPVP_Refresh()
if r then FillRow(r, s) end if r then FillRow(r, s) end
totals.wins = totals.wins + s.wins totals.wins = totals.wins + s.wins
totals.draws = totals.draws + (s.draws or 0)
totals.losses = totals.losses + s.losses totals.losses = totals.losses + s.losses
totals.kills = totals.kills + s.kills totals.kills = totals.kills + s.kills
totals.hk = totals.hk + s.hk totals.hk = totals.hk + s.hk
@@ -909,6 +975,7 @@ function RelationshipsPVP_Refresh()
"|cffffd200Best win streak:|r " .. totals.bestStreak "|cffffd200Best win streak:|r " .. totals.bestStreak
.. " |cffffd200Best KBs (single match):|r " .. totals.bestKB .. " |cffffd200Best KBs (single match):|r " .. totals.bestKB
.. " |cffffd200Total honor:|r " .. FormatNumber(totals.honor) .. " |cffffd200Total honor:|r " .. FormatNumber(totals.honor)
.. " |cffffd200Spendable honor:|r " .. FormatNumber(SpendableHonor(totals.honor))
) )
end end
+1 -1
View File
@@ -2,7 +2,7 @@
## Title: Relationships PVP ## Title: Relationships PVP
## Notes: PvP panel with per-battleground and per-arena stats, marks, kills/deaths, honor, K/D, and queue controls. Supports the Battleground Finder and Arena on OctoWoW. ## Notes: PvP panel with per-battleground and per-arena stats, marks, kills/deaths, honor, K/D, and queue controls. Supports the Battleground Finder and Arena on OctoWoW.
## Author: Relationship ## Author: Relationship
## Version: 1.0 ## Version: 1.3
## SavedVariablesPerCharacter: RelationshipsPVPCharDB ## SavedVariablesPerCharacter: RelationshipsPVPCharDB
RelationshipsPVP.xml RelationshipsPVP.xml
+28 -26
View File
@@ -6,7 +6,7 @@
============================================================ --> ============================================================ -->
<Frame name="RelationshipsPVPFrame" parent="UIParent" toplevel="true" movable="true" enableMouse="true" hidden="true" frameStrata="HIGH"> <Frame name="RelationshipsPVPFrame" parent="UIParent" toplevel="true" movable="true" enableMouse="true" hidden="true" frameStrata="HIGH">
<Size> <Size>
<AbsDimension x="740" y="740"/> <AbsDimension x="864" y="740"/>
</Size> </Size>
<Anchors> <Anchors>
<Anchor point="CENTER"/> <Anchor point="CENTER"/>
@@ -74,7 +74,7 @@
<!-- ================= Stats Panel ================= --> <!-- ================= Stats Panel ================= -->
<Frame name="RelationshipsPVPStatsPanel"> <Frame name="RelationshipsPVPStatsPanel">
<Size><AbsDimension x="692" y="266"/></Size> <Size><AbsDimension x="816" y="266"/></Size>
<Anchors> <Anchors>
<Anchor point="TOPLEFT"> <Anchor point="TOPLEFT">
<Offset><AbsDimension x="24" y="-72"/></Offset> <Offset><AbsDimension x="24" y="-72"/></Offset>
@@ -99,47 +99,55 @@
<Size><AbsDimension x="46" y="14"/></Size> <Size><AbsDimension x="46" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="208" y="-10"/></Offset></Anchor></Anchors> <Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="208" y="-10"/></Offset></Anchor></Anchors>
</FontString> </FontString>
<FontString name="RPVPHdrLoss" inherits="GameFontNormalSmall" text="Loss" justifyH="CENTER"> <FontString name="RPVPHdrDraw" inherits="GameFontNormalSmall" text="Draw" justifyH="CENTER">
<Size><AbsDimension x="46" y="14"/></Size> <Size><AbsDimension x="46" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="258" y="-10"/></Offset></Anchor></Anchors> <Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="258" y="-10"/></Offset></Anchor></Anchors>
</FontString> </FontString>
<FontString name="RPVPHdrRatio" inherits="GameFontNormalSmall" text="Win%" justifyH="CENTER"> <FontString name="RPVPHdrLoss" inherits="GameFontNormalSmall" text="Loss" justifyH="CENTER">
<Size><AbsDimension x="46" y="14"/></Size> <Size><AbsDimension x="46" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="308" y="-10"/></Offset></Anchor></Anchors> <Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="308" y="-10"/></Offset></Anchor></Anchors>
</FontString> </FontString>
<FontString name="RPVPHdrRatio" inherits="GameFontNormalSmall" text="Win%" justifyH="CENTER">
<Size><AbsDimension x="46" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="358" y="-10"/></Offset></Anchor></Anchors>
</FontString>
<FontString name="RPVPHdrKB" inherits="GameFontNormalSmall" text="KB" justifyH="CENTER"> <FontString name="RPVPHdrKB" inherits="GameFontNormalSmall" text="KB" justifyH="CENTER">
<Size><AbsDimension x="46" y="14"/></Size> <Size><AbsDimension x="46" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="354" y="-10"/></Offset></Anchor></Anchors> <Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="408" y="-10"/></Offset></Anchor></Anchors>
</FontString> </FontString>
<FontString name="RPVPHdrHK" inherits="GameFontNormalSmall" text="HK" justifyH="CENTER"> <FontString name="RPVPHdrHK" inherits="GameFontNormalSmall" text="HK" justifyH="CENTER">
<Size><AbsDimension x="46" y="14"/></Size> <Size><AbsDimension x="46" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="400" y="-10"/></Offset></Anchor></Anchors> <Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="454" y="-10"/></Offset></Anchor></Anchors>
</FontString> </FontString>
<FontString name="RPVPHdrDth" inherits="GameFontNormalSmall" text="Deaths" justifyH="CENTER"> <FontString name="RPVPHdrDth" inherits="GameFontNormalSmall" text="Deaths" justifyH="CENTER">
<Size><AbsDimension x="46" y="14"/></Size> <Size><AbsDimension x="46" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="446" y="-10"/></Offset></Anchor></Anchors> <Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="500" y="-10"/></Offset></Anchor></Anchors>
</FontString> </FontString>
<FontString name="RPVPHdrKD" inherits="GameFontNormalSmall" text="K/D" justifyH="CENTER"> <FontString name="RPVPHdrKD" inherits="GameFontNormalSmall" text="K/D" justifyH="CENTER">
<Size><AbsDimension x="50" y="14"/></Size> <Size><AbsDimension x="50" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="496" y="-10"/></Offset></Anchor></Anchors>
</FontString>
<FontString name="RPVPHdrHonor" inherits="GameFontNormalSmall" text="Honor" justifyH="CENTER">
<Size><AbsDimension x="60" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="550" y="-10"/></Offset></Anchor></Anchors> <Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="550" y="-10"/></Offset></Anchor></Anchors>
</FontString> </FontString>
<FontString name="RPVPHdrHonor" inherits="GameFontNormalSmall" text="Honor" justifyH="CENTER">
<Size><AbsDimension x="56" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="604" y="-10"/></Offset></Anchor></Anchors>
</FontString>
<FontString name="RPVPHdrSpend" inherits="GameFontNormalSmall" text="Spendable" justifyH="CENTER">
<Size><AbsDimension x="76" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="664" y="-10"/></Offset></Anchor></Anchors>
</FontString>
<FontString name="RPVPHdrMk" inherits="GameFontNormalSmall" text="Marks" justifyH="CENTER"> <FontString name="RPVPHdrMk" inherits="GameFontNormalSmall" text="Marks" justifyH="CENTER">
<Size><AbsDimension x="58" y="14"/></Size> <Size><AbsDimension x="56" y="14"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="614" y="-10"/></Offset></Anchor></Anchors> <Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="744" y="-10"/></Offset></Anchor></Anchors>
</FontString> </FontString>
<Texture name="RPVPHdrDivider" file="Interface\Tooltips\UI-Tooltip-Background"> <Texture name="RPVPHdrDivider" file="Interface\Tooltips\UI-Tooltip-Background">
<Size><AbsDimension x="664" y="1"/></Size> <Size><AbsDimension x="786" y="1"/></Size>
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="14" y="-28"/></Offset></Anchor></Anchors> <Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="14" y="-28"/></Offset></Anchor></Anchors>
<Color r="0.6" g="0.6" b="0.6" a="0.6"/> <Color r="0.6" g="0.6" b="0.6" a="0.6"/>
</Texture> </Texture>
<FontString name="RelationshipsPVPExtrasText" inherits="GameFontHighlightSmall" justifyH="LEFT"> <FontString name="RelationshipsPVPExtrasText" inherits="GameFontHighlightSmall" justifyH="LEFT">
<Size><AbsDimension x="664" y="16"/></Size> <Size><AbsDimension x="786" y="16"/></Size>
<Anchors> <Anchors>
<Anchor point="BOTTOMLEFT"><Offset><AbsDimension x="14" y="10"/></Offset></Anchor> <Anchor point="BOTTOMLEFT"><Offset><AbsDimension x="14" y="10"/></Offset></Anchor>
</Anchors> </Anchors>
@@ -150,7 +158,7 @@
<!-- ================= Queue Status Panel ================= --> <!-- ================= Queue Status Panel ================= -->
<Frame name="RelationshipsPVPQueuePanel"> <Frame name="RelationshipsPVPQueuePanel">
<Size><AbsDimension x="692" y="84"/></Size> <Size><AbsDimension x="816" y="84"/></Size>
<Anchors> <Anchors>
<Anchor point="TOPLEFT"> <Anchor point="TOPLEFT">
<Offset><AbsDimension x="24" y="-368"/></Offset> <Offset><AbsDimension x="24" y="-368"/></Offset>
@@ -164,7 +172,7 @@
<Layers> <Layers>
<Layer level="ARTWORK"> <Layer level="ARTWORK">
<FontString name="RelationshipsPVPQueueText" inherits="GameFontHighlightSmall" justifyH="LEFT" justifyV="TOP"> <FontString name="RelationshipsPVPQueueText" inherits="GameFontHighlightSmall" justifyH="LEFT" justifyV="TOP">
<Size><AbsDimension x="664" y="70"/></Size> <Size><AbsDimension x="786" y="70"/></Size>
<Anchors> <Anchors>
<Anchor point="TOPLEFT"><Offset><AbsDimension x="14" y="-10"/></Offset></Anchor> <Anchor point="TOPLEFT"><Offset><AbsDimension x="14" y="-10"/></Offset></Anchor>
</Anchors> </Anchors>
@@ -173,15 +181,9 @@
</Layers> </Layers>
</Frame> </Frame>
<!-- ================= Action Panel ================= <!-- ================= Action Panel ================= -->
Layout math (panel width 692, side padding 24 → usable 644):
Row 1 (3 BGs) : 3 × 200w + 2 × 22gap = 644
Row 2 (4 arena) : 4 × 149w + 3 × 16gap = 596 + 48 = 644
Row 4 (4 utility) : 4 × 149w + 3 × 16gap = 644
All rows share x=24 left edge and end at x=668 right edge.
-->
<Frame name="RelationshipsPVPActionPanel"> <Frame name="RelationshipsPVPActionPanel">
<Size><AbsDimension x="692" y="230"/></Size> <Size><AbsDimension x="816" y="230"/></Size>
<Anchors> <Anchors>
<Anchor point="TOPLEFT"> <Anchor point="TOPLEFT">
<Offset><AbsDimension x="24" y="-472"/></Offset> <Offset><AbsDimension x="24" y="-472"/></Offset>
@@ -280,7 +282,7 @@
</Scripts> </Scripts>
</CheckButton> </CheckButton>
<!-- Row 4: Utility buttons (4 equal-width columns matching arena row) --> <!-- Row 4: Utility buttons -->
<Button name="RelationshipsPVPLeave" inherits="UIPanelButtonTemplate" text="Leave / Cancel Queue"> <Button name="RelationshipsPVPLeave" inherits="UIPanelButtonTemplate" text="Leave / Cancel Queue">
<Size><AbsDimension x="149" y="30"/></Size> <Size><AbsDimension x="149" y="30"/></Size>
<Anchors> <Anchors>