Files
Adrestie ca2b78e217 Remove every debug command
/fui keeps edit mode, reset and list. The thirty diagnostic and tuning
functions behind the other subcommands (bar, bags, character, tabs, close,
model, minimap, mouse, map, questlog, chat, chatlines, tabard...) go with
them, with Panes.Report, the bags read-back and the 205 texts they alone used.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 13:39:35 +02:00

440 lines
14 KiB
Lua

-- Battlegrounds in the right pane of the PvP tab: the list at the top, win and loss rewards
-- at the bottom, and the Join as Party / Join Battle buttons (no Cancel). Camelot has no such
-- screen, so it follows WotLK's PVPBattlegroundFrame and BattlefieldFrame (.lua/.xml),
-- styled like the arena teams (PvPArena.lua).
local ForeverUI = ForeverUI or {}
_G.ForeverUI = ForeverUI
local L = ForeverUI.L
local B = {}
ForeverUI.PvPBattlegrounds = B
local SEP = string.char(92)
local PVP = "Interface" .. SEP .. "PVPFrame" .. SEP
local STATE_ICON = "Interface" .. SEP .. "CharacterFrame" .. SEP .. "UI-StateIcon"
-- Layout of the two boxes (list and rewards), built on Camelot's InsetFrameTemplate
local MARGIN = 12 -- box to pane edge
local FRAME_BOX_TOP = -12
local INNER = 4 -- rows to box edge
local MAX_ROWS = 8
local ROW_H = 20
local STATE_SIDE, STATE_X = 16, 2
local NAME_X = 22
local HOVER_ALPHA, SELECTED_ALPHA = 0.10, 0.20
local BUTTON_H, BUTTON_GAP, BUTTONS_BOTTOM = 22, 4, 14
local REWARD_H, REWARDS_GAP, REWARDS_ABOVE_BUTTONS = 36, 2, 8
-- Plate contents never truncate: columns are sized from the measured texts (GetStringWidth),
-- the same for both plates so symbols and amounts line up. If the whole overflows the plate
-- (long labels in another language, large amounts), the next smaller font is used.
local PLATE_EDGE = 8 -- plate edge to text
local COLUMN_GAP = 8 -- between two columns
local SYMBOL_GAP = 3 -- symbol to its amount
local SYMBOL_SIZE = 20
local FONTS = {
{ tag = "GameFontNormal", amount = "NumberFontNormal" },
{ tag = "GameFontNormalSmall", amount = "NumberFontNormalSmall" },
}
-- Each reward row is Camelot's list plate (common-button-list-collapseexpand, nine-slice,
-- corner 12, as on the arena cards); the label carries the color: Win in the client's green,
-- Loss in its red (GREEN_FONT_COLOR, RED_FONT_COLOR). GREEN and RED are fallbacks.
local ATLAS_PLATE = "common-button-list-collapseexpand"
local PLATE_CORNER = 12
local GREEN = { 0.1, 1.0, 0.1 }
local RED = { 1.0, 0.1, 0.1 }
local frame, rows, rewards, join, joinAsGroup
local selected
local function faction()
return (UnitFactionGroup and UnitFactionGroup("player")) or "Alliance"
end
-- --------------------------------------------------------------- Session
-- The instance info request goes out on the next frame: the client frames the tab hides
-- (PVPFrame, PVPBattlegroundFrame) call CloseBattlefield in their OnHide, which would close
-- our session if they hid after the request.
local deferred = CreateFrame("Frame")
deferred:Hide()
deferred:SetScript("OnUpdate", function(self)
self:Hide()
if frame and frame:IsVisible() and selected then
RequestBattlegroundInstanceInfo(selected)
end
end)
local function request()
deferred:Show()
end
B.deferred = deferred
-- --------------------------------------------------------------- Box
-- Camelot's InsetFrameTemplate: ForeverUI.CreateInset (AtlasUtil)
local function frameBox(name)
return ForeverUI.CreateInset(frame, name)
end
-- ------------------------------------------------------------------ List
local function createRow(n)
local list = B.list
local l = CreateFrame("Button", "ForeverUIBattlegroundRow" .. n, list)
l:SetHeight(ROW_H)
l:SetPoint("TOPLEFT", list, "TOPLEFT", INNER, -INNER - (n - 1) * ROW_H)
l:SetPoint("TOPRIGHT", list, "TOPRIGHT", -INNER, -INNER - (n - 1) * ROW_H)
l.hover = ForeverUI.PvPArena.createHover(l)
local state = CreateFrame("Frame", nil, l)
state:SetWidth(STATE_SIDE)
state:SetHeight(STATE_SIDE)
state:SetPoint("LEFT", l, "LEFT", STATE_X, 0)
state:EnableMouse(true)
state.texture = state:CreateTexture(nil, "ARTWORK")
state.texture:SetAllPoints(state)
state:SetScript("OnEnter", function(self)
if self.tooltip then
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText(self.tooltip)
GameTooltip:Show()
end
end)
state:SetScript("OnLeave", function() GameTooltip:Hide() end)
state:Hide()
l.state = state
l.name = l:CreateFontString(nil, "ARTWORK", "GameFontNormal")
l.name:SetJustifyH("LEFT")
l.name:SetPoint("LEFT", l, "LEFT", NAME_X, 0)
l.name:SetPoint("RIGHT", l, "RIGHT", -4, 0)
l:SetScript("OnEnter", function(self)
if self.index ~= selected then
self.hover:SetAlpha(HOVER_ALPHA)
end
end)
l:SetScript("OnLeave", function(self)
if self.index ~= selected then
self.hover:SetAlpha(0)
end
end)
-- PVPBattlegroundButton_OnClick. The server answers RequestBattlegroundInstanceInfo with
-- PVPQUEUE_ANYWHERE_SHOW; GetBattlefieldInfo then gives the maximum group size.
l:SetScript("OnClick", function(self)
if not self.index or self.index == selected then
return
end
selected = self.index
B.update()
RequestBattlegroundInstanceInfo(selected)
PlaySound("igMainMenuOptionCheckBoxOn")
end)
return l
end
-- PVPBattleground_UpdateQueueStatus
local function updateStates()
for _, l in ipairs(rows) do
l.state:Hide()
end
local maxQueues = MAX_BATTLEFIELD_QUEUES or 3
for i = 1, maxQueues do
local status, mapName = GetBattlefieldStatus(i)
if status and status ~= "none" then
for _, l in ipairs(rows) do
if l:IsShown() and l.mapName == mapName then
if status == "queued" then
l.state.texture:SetTexture(PVP .. "PVP-Currency-" .. faction())
l.state.texture:SetTexCoord(0, 1, 0, 1)
l.state.tooltip = BATTLEFIELD_QUEUE_STATUS
l.state:Show()
elseif status == "confirm" then
l.state.texture:SetTexture(STATE_ICON)
l.state.texture:SetTexCoord(0.45, 0.95, 0.0, 0.5)
l.state.tooltip = BATTLEFIELD_CONFIRM_STATUS
l.state:Show()
end
end
end
end
end
end
-- PVPBattleground_UpdateBattlegrounds
local function updateList()
local rank = 0
for i = 1, GetNumBattlegroundTypes() do
local name, canEnter, holiday = GetBattlegroundInfo(i)
if name and canEnter and rank < MAX_ROWS then
rank = rank + 1
local l = rows[rank]
l.index = i
l.mapName = name
if not selected then
selected = i
end
if holiday then
l.name:SetText(name .. " (" .. BATTLEGROUND_HOLIDAY .. ")")
else
l.name:SetText(name)
end
l.hover:SetAlpha(i == selected and SELECTED_ALPHA or 0)
l:Show()
end
end
for n = rank + 1, MAX_ROWS do
rows[n].index = nil
rows[n].mapName = nil
rows[n]:Hide()
end
updateStates()
end
-- ------------------------------------------------------------ Rewards
-- One reward plate. tag: label text; clientColor: name of the client color global;
-- color: fallback RGB
local function createReward(tag, clientColor, color)
local r = CreateFrame("Frame", nil, B.rewardsFrame)
r:SetHeight(REWARD_H)
r.plate = ForeverUI.CreateNineSlice(r, ATLAS_PLATE, PLATE_CORNER,
{ 0, 0, 0, 0 }, "BACKGROUND") or {}
r.tag = r:CreateFontString(nil, "ARTWORK", FONTS[1].tag)
r.tag:SetJustifyH("LEFT")
r.tag:SetPoint("LEFT", r, "LEFT", PLATE_EDGE, 0)
r.tag:SetText(tag)
local c = _G[clientColor]
if c then
r.tag:SetTextColor(c.r, c.g, c.b)
else
r.tag:SetTextColor(color[1], color[2], color[3])
end
r.honorSymbol = r:CreateTexture(nil, "ARTWORK")
r.honorSymbol:SetWidth(SYMBOL_SIZE)
r.honorSymbol:SetHeight(SYMBOL_SIZE)
r.honor = r:CreateFontString(nil, "ARTWORK", FONTS[1].amount)
r.honor:SetJustifyH("LEFT")
r.honor:SetPoint("LEFT", r.honorSymbol, "RIGHT", SYMBOL_GAP, 0)
r.arenaSymbol = r:CreateTexture(nil, "ARTWORK")
r.arenaSymbol:SetTexture(PVP .. "PVP-ArenaPoints-Icon")
r.arenaSymbol:SetWidth(SYMBOL_SIZE)
r.arenaSymbol:SetHeight(SYMBOL_SIZE)
r.arena = r:CreateFontString(nil, "ARTWORK", FONTS[1].amount)
r.arena:SetJustifyH("LEFT")
r.arena:SetPoint("LEFT", r.arenaSymbol, "RIGHT", SYMBOL_GAP, 0)
return r
end
-- Show an amount and its symbol, or hide both when the amount is zero
local function placeAmount(symbol, text, amount)
if amount and amount ~= 0 then
text:SetText(amount)
symbol:Show()
text:Show()
else
symbol:Hide()
text:Hide()
end
end
-- Columns of both plates, sized from what their texts measure.
local function shownWidth(fs)
return fs:IsShown() and (fs:GetStringWidth() or 0) or 0
end
local function placeColumns()
local plates = { rewards.win, rewards.defeat }
local width = (frame:GetWidth() or 0) - 2 * MARGIN - 2 * INNER
if width <= 0 then
width = 233 - 2 * MARGIN - 2 * INNER
end
local tag, honor, arena, total
for rank, font in ipairs(FONTS) do
for _, r in ipairs(plates) do
r.tag:SetFontObject(_G[font.tag] or font.tag)
r.honor:SetFontObject(_G[font.amount] or font.amount)
r.arena:SetFontObject(_G[font.amount] or font.amount)
end
tag, honor, arena = 0, 0, 0
for _, r in ipairs(plates) do
tag = math.max(tag, r.tag:GetStringWidth() or 0)
honor = math.max(honor, shownWidth(r.honor))
arena = math.max(arena, shownWidth(r.arena))
end
total = PLATE_EDGE + tag + COLUMN_GAP + SYMBOL_SIZE + SYMBOL_GAP
+ honor + COLUMN_GAP + SYMBOL_SIZE + SYMBOL_GAP + arena + PLATE_EDGE
B.font = rank
if total <= width then
break
end
end
local honorX = PLATE_EDGE + tag + COLUMN_GAP
local arenaX = honorX + SYMBOL_SIZE + SYMBOL_GAP + honor + COLUMN_GAP
for _, r in ipairs(plates) do
r.honorSymbol:ClearAllPoints()
r.honorSymbol:SetPoint("LEFT", r, "LEFT", honorX, 0)
r.arenaSymbol:ClearAllPoints()
r.arenaSymbol:SetPoint("LEFT", r, "LEFT", arenaX, 0)
end
B.rewardsWidth = total
end
-- PVPQueue_UpdateRandomInfo. Only random and holiday battlegrounds have rewards; for the
-- others WotLK shows the map description, which is not shown here.
local function updateRewards()
local _, _, holiday, random = GetBattlegroundInfo(selected or 0)
if not (random or holiday) then
B.rewardsFrame:Hide()
return
end
local _, winHonor, winArena, lossHonor, lossArena
if random then
_, winHonor, winArena, lossHonor, lossArena = GetRandomBGHonorCurrencyBonuses()
else
_, winHonor, winArena, lossHonor, lossArena = GetHolidayBGHonorCurrencyBonuses()
end
local symbol = PVP .. "PVP-Currency-" .. faction()
rewards.win.honorSymbol:SetTexture(symbol)
rewards.defeat.honorSymbol:SetTexture(symbol)
placeAmount(rewards.win.honorSymbol, rewards.win.honor, winHonor)
placeAmount(rewards.win.arenaSymbol, rewards.win.arena, winArena)
placeAmount(rewards.defeat.honorSymbol, rewards.defeat.honor, lossHonor)
placeAmount(rewards.defeat.arenaSymbol, rewards.defeat.arena, lossArena)
placeColumns()
B.rewardsFrame:Show()
end
-- ---------------------------------------------------------------- Buttons
-- PVPBattleground_UpdateJoinButton and PVPBattlegroundFrame_UpdateGroupAvailable.
-- maxGroupSize is MaxGroupSize in BattlemasterList.dbc: 5 (party only) for Alterac, Isle of
-- Conquest and random; 10 or 15 (a raid can join) for the others.
local function updateButtons()
local _, _, maxGroupSize = GetBattlefieldInfo()
if maxGroupSize and maxGroupSize == 5 then
joinAsGroup:SetText(JOIN_AS_PARTY)
else
joinAsGroup:SetText(JOIN_AS_GROUP)
end
if ((GetNumPartyMembers() > 0) or (GetNumRaidMembers() > 0)) and IsPartyLeader() then
joinAsGroup:Enable()
joinAsGroup:SetAlpha(1)
else
joinAsGroup:Disable()
joinAsGroup:SetAlpha(0.5)
end
end
function B.update()
if not frame then
return
end
updateList()
updateRewards()
updateButtons()
end
-- ------------------------------------------------------------ Build
-- Build the screen once. pane: the right pane of the PvP tab
function B.build(pane)
if frame or not pane then
return
end
frame = pane
-- List box at the top of the pane, tall enough for eight rows.
B.list = frameBox("ForeverUIBattlegroundList")
B.list:SetPoint("TOPLEFT", frame, "TOPLEFT", MARGIN, FRAME_BOX_TOP)
B.list:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -MARGIN, FRAME_BOX_TOP)
B.list:SetHeight(MAX_ROWS * ROW_H + 2 * INNER)
rows = {}
for n = 1, MAX_ROWS do
rows[n] = createRow(n)
end
local width = (pane:GetWidth() or 0)
if width < 100 then
width = 233
end
local buttonW = math.floor((width - 2 * MARGIN - BUTTON_GAP) / 2)
joinAsGroup = ForeverUI.PvPArena.panelButton(frame,
BATTLEFIELD_GROUP_JOIN, buttonW, BUTTON_H)
joinAsGroup:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", MARGIN, BUTTONS_BOTTOM)
joinAsGroup:SetScript("OnClick", function()
if selected then
JoinBattlefield(0, true)
end
end)
join = ForeverUI.PvPArena.panelButton(frame,
BATTLEFIELD_JOIN, buttonW, BUTTON_H)
join:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -MARGIN, BUTTONS_BOTTOM)
join:SetScript("OnClick", function()
if selected then
JoinBattlefield(0)
end
end)
B.join, B.joinAsGroup = join, joinAsGroup
-- Rewards box above the buttons: two plates.
B.rewardsFrame = frameBox("ForeverUIBattlegroundRewards")
B.rewardsFrame:SetPoint("BOTTOMLEFT", joinAsGroup, "TOPLEFT", 0, REWARDS_ABOVE_BUTTONS)
B.rewardsFrame:SetPoint("BOTTOMRIGHT", join, "TOPRIGHT", 0, REWARDS_ABOVE_BUTTONS)
B.rewardsFrame:SetHeight(2 * REWARD_H + REWARDS_GAP + 2 * INNER)
rewards = {}
rewards.win = createReward(WIN, "GREEN_FONT_COLOR", GREEN)
rewards.win:SetPoint("TOPLEFT", B.rewardsFrame, "TOPLEFT", INNER, -INNER)
rewards.win:SetPoint("TOPRIGHT", B.rewardsFrame, "TOPRIGHT", -INNER, -INNER)
rewards.defeat = createReward(LOSS, "RED_FONT_COLOR", RED)
rewards.defeat:SetPoint("TOPLEFT", rewards.win, "BOTTOMLEFT", 0, -REWARDS_GAP)
rewards.defeat:SetPoint("TOPRIGHT", rewards.win, "BOTTOMRIGHT", 0, -REWARDS_GAP)
B.rewards = rewards
-- PVPBattlegroundFrame_OnShow / _OnHide
frame:HookScript("OnShow", function()
if SortBGList then
SortBGList()
end
B.update()
request()
end)
frame:HookScript("OnHide", function()
deferred:Hide()
CloseBattlefield()
end)
B.update()
if frame:IsVisible() then
request()
end
end
-- PVPBattlegroundFrame_OnEvent
local listener = CreateFrame("Frame")
listener:RegisterEvent("PVPQUEUE_ANYWHERE_SHOW")
listener:RegisterEvent("UPDATE_BATTLEFIELD_STATUS")
listener:RegisterEvent("PVPQUEUE_ANYWHERE_UPDATE_AVAILABLE")
listener:RegisterEvent("PARTY_MEMBERS_CHANGED")
listener:RegisterEvent("RAID_ROSTER_UPDATE")
listener:SetScript("OnEvent", function(self, event)
if not frame then
return
end
if event == "UPDATE_BATTLEFIELD_STATUS" then
updateStates()
elseif event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" then
updateButtons()
elseif event == "PVPQUEUE_ANYWHERE_UPDATE_AVAILABLE" then
-- Level brackets may have changed: rebuild the list
selected = nil
B.update()
request()
else
B.update()
end
end)