Add spec-aware stats panel, top upgrades display, and wider source column

This commit is contained in:
dfj
2026-06-17 20:14:28 +02:00
parent 0e7a0c909a
commit 5ff421bd09

View File

@@ -17,7 +17,6 @@ local COLOR_EMPTY = { 0.6, 0.6, 0.6 }
local MainFrame = nil local MainFrame = nil
local TitleText = nil local TitleText = nil
local SummaryText = nil local SummaryText = nil
local UpgradeText = nil
local ScrollFrame = nil local ScrollFrame = nil
local SlotRows = {} local SlotRows = {}
local MAX_VISIBLE_ROWS = 17 local MAX_VISIBLE_ROWS = 17
@@ -26,7 +25,7 @@ local ROW_SPACING = 24
local function CreateMainFrame() local function CreateMainFrame()
local frame = CreateFrame("Frame", "AmibisMainFrame", UIParent, "BackdropTemplate") local frame = CreateFrame("Frame", "AmibisMainFrame", UIParent, "BackdropTemplate")
frame:SetSize(480, 680) frame:SetSize(640, 680)
frame:SetFrameStrata("MEDIUM") frame:SetFrameStrata("MEDIUM")
frame:SetFrameLevel(10) frame:SetFrameLevel(10)
@@ -113,13 +112,7 @@ local function CreateSummaryBar(parent, anchor)
summaryText:SetPoint("LEFT", bar, "LEFT", 8, 0) summaryText:SetPoint("LEFT", bar, "LEFT", 8, 0)
summaryText:SetTextColor(0.8, 0.8, 0.8, 1) summaryText:SetTextColor(0.8, 0.8, 0.8, 1)
local upgradeText = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") return bar, summaryText
upgradeText:SetPoint("BOTTOMLEFT", bar, "TOPLEFT", 8, 2)
upgradeText:SetPoint("BOTTOMRIGHT", bar, "TOPRIGHT", -8, 2)
upgradeText:SetJustifyH("LEFT")
upgradeText:SetTextColor(COLOR_UPGRADE[1], COLOR_UPGRADE[2], COLOR_UPGRADE[3], 1)
return bar, summaryText, upgradeText
end end
local function CreateColumnHeaders(parent, anchor) local function CreateColumnHeaders(parent, anchor)
@@ -165,8 +158,8 @@ local function CreateColumnHeaders(parent, anchor)
enchantHeader:SetTextColor(0.7, 0.7, 0.7, 1) enchantHeader:SetTextColor(0.7, 0.7, 0.7, 1)
local sourceHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") local sourceHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
sourceHeader:SetPoint("LEFT", enchantHeader, "RIGHT", 5, 0)
sourceHeader:SetPoint("RIGHT", header, "RIGHT", -8, 0) sourceHeader:SetPoint("RIGHT", header, "RIGHT", -8, 0)
sourceHeader:SetWidth(70)
sourceHeader:SetJustifyH("RIGHT") sourceHeader:SetJustifyH("RIGHT")
sourceHeader:SetText("Source") sourceHeader:SetText("Source")
sourceHeader:SetTextColor(0.7, 0.7, 0.7, 1) sourceHeader:SetTextColor(0.7, 0.7, 0.7, 1)
@@ -209,15 +202,14 @@ local function CreateSlotRows(parent, anchor)
row.enchantText:SetJustifyH("LEFT") row.enchantText:SetJustifyH("LEFT")
row.sourceText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") row.sourceText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
row.sourceText:SetPoint("LEFT", row.enchantText, "RIGHT", 5, 0)
row.sourceText:SetPoint("RIGHT", row, "RIGHT", -8, 0) row.sourceText:SetPoint("RIGHT", row, "RIGHT", -8, 0)
row.sourceText:SetWidth(70)
row.sourceText:SetJustifyH("RIGHT") row.sourceText:SetJustifyH("RIGHT")
row.sourceText:SetWordWrap(true)
row:SetScript("OnEnter", function(self) row:SetScript("OnEnter", function(self)
if self.bisLink then if self.bisLink then
GameTooltip:SetOwner(self, "ANCHOR_RIGHT") GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetHyperlink(self.bisLink) pcall(GameTooltip.SetHyperlink, GameTooltip, self.bisLink)
GameTooltip:Show() GameTooltip:Show()
end end
end) end)
@@ -245,22 +237,72 @@ local StatsPanel = nil
local StatsPanelTitle = nil local StatsPanelTitle = nil
local StatLabels = {} local StatLabels = {}
local StatValues = {} local StatValues = {}
local UpgradeLabels = {}
local STAT_DISPLAY = { local STAT_LABELS = {
{ key = "healing", label = "+Healing" }, healing = "+Healing",
{ key = "spellPower", label = "+Spell Power" }, spellDamage = "+Spell Damage",
{ key = "intellect", label = "Intellect" }, spellPower = "+Spell Power",
{ key = "spirit", label = "Spirit" }, intellect = "Intellect",
{ key = "mp5", label = "MP5" }, spirit = "Spirit",
{ key = "haste", label = "Haste" }, mp5 = "MP5",
{ key = "crit", label = "Crit" }, haste = "Haste",
crit = "Crit",
} }
local STAT_DISPLAY_NAME = {
healing = "healing",
spellDamage = "spell damage",
spellPower = "spell power",
intellect = "intellect",
spirit = "spirit",
mp5 = "mp5",
haste = "haste",
crit = "crit",
}
local STATS_COL_W = 60
local STATS_LABEL_W = 80
local STATS_CURRENT_X = STATS_LABEL_W + 16
local STATS_BIS_X = STATS_CURRENT_X + STATS_COL_W
local STATS_DIFF_X = STATS_BIS_X + STATS_COL_W
local currentStatKeys = {}
local function GetStatDisplayName(key)
return STAT_DISPLAY_NAME[key] or key
end
local function FormatUpgradeEntry(idx, upgrade)
local text = string.format("%d. %s: ", idx, upgrade.slot)
if not upgrade.equipped then
return text .. "|cff888888(empty slot)|r"
end
if not next(upgrade.statDiffs) then
return text .. "|cff888888(no stat gain)|r"
end
local sorted = {}
for statKey, diff in pairs(upgrade.statDiffs) do
table.insert(sorted, { key = statKey, diff = diff })
end
table.sort(sorted, function(a, b) return a.diff > b.diff end)
local parts = {}
local maxShow = math.min(2, #sorted)
for i = 1, maxShow do
table.insert(parts, string.format("+%d %s", sorted[i].diff, GetStatDisplayName(sorted[i].key)))
end
return text .. table.concat(parts, ", ")
end
local function CreateStatsPanel(parent, anchor) local function CreateStatsPanel(parent, anchor)
local panel = CreateFrame("Frame", nil, parent, "BackdropTemplate") local panel = CreateFrame("Frame", nil, parent, "BackdropTemplate")
panel:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -8) panel:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -8)
panel:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -8) panel:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -8)
panel:SetHeight(#STAT_DISPLAY * 16 + 24) panel:SetHeight(24)
panel:SetBackdrop({ panel:SetBackdrop({
bgFile = "Interface\\Buttons\\WHITE8x8", bgFile = "Interface\\Buttons\\WHITE8x8",
@@ -277,70 +319,109 @@ local function CreateStatsPanel(parent, anchor)
title:SetTextColor(1, 0.82, 0, 1) title:SetTextColor(1, 0.82, 0, 1)
StatsPanelTitle = title StatsPanelTitle = title
local colW = 60
local labelW = 80
local currentX = labelW + 16
local bisX = currentX + colW
local diffX = bisX + colW
local currentLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") local currentLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
currentLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", currentX, -4) currentLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_CURRENT_X, -4)
currentLabel:SetWidth(colW) currentLabel:SetWidth(STATS_COL_W)
currentLabel:SetJustifyH("CENTER") currentLabel:SetJustifyH("CENTER")
currentLabel:SetText("Current") currentLabel:SetText("Current")
currentLabel:SetTextColor(0.7, 0.7, 0.7, 1) currentLabel:SetTextColor(0.7, 0.7, 0.7, 1)
local bisLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") local bisLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
bisLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", bisX, -4) bisLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_BIS_X, -4)
bisLabel:SetWidth(colW) bisLabel:SetWidth(STATS_COL_W)
bisLabel:SetJustifyH("CENTER") bisLabel:SetJustifyH("CENTER")
bisLabel:SetText("BIS") bisLabel:SetText("BIS")
bisLabel:SetTextColor(0.7, 0.7, 0.7, 1) bisLabel:SetTextColor(0.7, 0.7, 0.7, 1)
local diffLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") local diffLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
diffLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", diffX, -4) diffLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_DIFF_X, -4)
diffLabel:SetWidth(colW) diffLabel:SetWidth(STATS_COL_W)
diffLabel:SetJustifyH("CENTER") diffLabel:SetJustifyH("CENTER")
diffLabel:SetText("Diff") diffLabel:SetText("Diff")
diffLabel:SetTextColor(0.7, 0.7, 0.7, 1) diffLabel:SetTextColor(0.7, 0.7, 0.7, 1)
for i, stat in ipairs(STAT_DISPLAY) do local separator = panel:CreateTexture(nil, "ARTWORK")
local y = -(i - 1) * 16 - 22 separator:SetTexture("Interface\\Buttons\\WHITE8x8")
separator:SetVertexColor(0.2, 0.2, 0.2, 1)
separator:SetPoint("TOPLEFT", panel, "TOPLEFT", 290, 4)
separator:SetPoint("BOTTOMLEFT", panel, "BOTTOMLEFT", 290, -4)
separator:SetWidth(1)
local upgradesTitle = panel:CreateFontString(nil, "OVERLAY", "GameFontNormal")
upgradesTitle:SetPoint("TOPLEFT", panel, "TOPLEFT", 300, -4)
upgradesTitle:SetText("Top Upgrades")
upgradesTitle:SetTextColor(1, 0.82, 0, 1)
for i = 1, 3 do
local y = -22 - (i - 1) * 16
local label = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
label:SetPoint("TOPLEFT", panel, "TOPLEFT", 300, y)
label:SetWidth(320)
label:SetJustifyH("LEFT")
label:SetText("")
label:SetTextColor(COLOR_UPGRADE[1], COLOR_UPGRADE[2], COLOR_UPGRADE[3], 1)
UpgradeLabels[i] = label
end
StatsPanel = panel
return panel
end
local function RebuildStatRows(panel, statKeys)
for _, vals in pairs(StatValues) do
vals.label:Hide()
vals.current:Hide()
vals.bis:Hide()
vals.diff:Hide()
end
StatLabels = {}
StatValues = {}
for i, statKey in ipairs(statKeys) do
local y = -22 - (i - 1) * 16
local labelText = STAT_LABELS[statKey] or statKey
local label = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") local label = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
label:SetPoint("TOPLEFT", panel, "TOPLEFT", 8, y) label:SetPoint("TOPLEFT", panel, "TOPLEFT", 8, y)
label:SetWidth(labelW) label:SetWidth(STATS_LABEL_W)
label:SetJustifyH("RIGHT") label:SetJustifyH("RIGHT")
label:SetText(stat.label) label:SetText(labelText)
label:SetTextColor(0.6, 0.6, 0.6, 1) label:SetTextColor(0.6, 0.6, 0.6, 1)
local current = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") local current = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
current:SetPoint("TOPLEFT", panel, "TOPLEFT", currentX, y) current:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_CURRENT_X, y)
current:SetWidth(colW) current:SetWidth(STATS_COL_W)
current:SetJustifyH("CENTER") current:SetJustifyH("CENTER")
current:SetText("0") current:SetText("0")
current:SetTextColor(1, 0.5, 0.5, 1) current:SetTextColor(1, 0.5, 0.5, 1)
local bis = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") local bis = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
bis:SetPoint("TOPLEFT", panel, "TOPLEFT", bisX, y) bis:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_BIS_X, y)
bis:SetWidth(colW) bis:SetWidth(STATS_COL_W)
bis:SetJustifyH("CENTER") bis:SetJustifyH("CENTER")
bis:SetText("0") bis:SetText("0")
bis:SetTextColor(0, 1, 0, 1) bis:SetTextColor(0, 1, 0, 1)
local diff = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") local diff = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
diff:SetPoint("TOPLEFT", panel, "TOPLEFT", diffX, y) diff:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_DIFF_X, y)
diff:SetWidth(colW) diff:SetWidth(STATS_COL_W)
diff:SetJustifyH("CENTER") diff:SetJustifyH("CENTER")
diff:SetText("0") diff:SetText("0")
diff:SetTextColor(1, 1, 1, 1) diff:SetTextColor(1, 1, 1, 1)
StatLabels[stat.key] = label StatLabels[statKey] = label
StatValues[stat.key] = { current = current, bis = bis, diff = diff } StatValues[statKey] = { current = current, bis = bis, diff = diff }
end end
StatsPanel = panel panel:SetHeight(#statKeys * 16 + 24)
return panel end
local function StatKeysEqual(a, b)
if #a ~= #b then return false end
for i, key in ipairs(a) do
if b[i] ~= key then return false end
end
return true
end end
local function InitializeUI() local function InitializeUI()
@@ -350,9 +431,8 @@ local function InitializeUI()
local titleBar, title = CreateTitleBar(MainFrame) local titleBar, title = CreateTitleBar(MainFrame)
TitleText = title TitleText = title
local summaryBar, summary, upgrade = CreateSummaryBar(MainFrame, titleBar) local summaryBar, summary = CreateSummaryBar(MainFrame, titleBar)
SummaryText = summary SummaryText = summary
UpgradeText = upgrade
local header = CreateColumnHeaders(MainFrame, summaryBar) local header = CreateColumnHeaders(MainFrame, summaryBar)
local slotContainer = CreateSlotRows(MainFrame, header) local slotContainer = CreateSlotRows(MainFrame, header)
@@ -398,7 +478,11 @@ function ns.UI.RefreshUI()
if not data.hasBISList then if not data.hasBISList then
SummaryText:SetText(string.format("|cffff6666No BIS list available for %s %s in %s|r", data.class, data.spec or "Unknown", data.phase)) SummaryText:SetText(string.format("|cffff6666No BIS list available for %s %s in %s|r", data.class, data.spec or "Unknown", data.phase))
UpgradeText:SetText("") for i = 1, 3 do
if UpgradeLabels[i] then
UpgradeLabels[i]:SetText("")
end
end
for i = 1, MAX_VISIBLE_ROWS do for i = 1, MAX_VISIBLE_ROWS do
SlotRows[i].slotText:SetText("") SlotRows[i].slotText:SetText("")
SlotRows[i].equippedText:SetText("") SlotRows[i].equippedText:SetText("")
@@ -412,17 +496,6 @@ function ns.UI.RefreshUI()
SummaryText:SetText(string.format("BIS: %d/%d slots", data.bisCount, data.totalSlots)) SummaryText:SetText(string.format("BIS: %d/%d slots", data.bisCount, data.totalSlots))
if data.biggestUpgrade then
local bu = data.biggestUpgrade
if bu.equipped then
UpgradeText:SetText(string.format("Biggest upgrade: %s -> %s (%s)", bu.equipped.name, bu.bis.name, bu.bis.source))
else
UpgradeText:SetText(string.format("Empty slot: %s -> %s (%s)", bu.slot, bu.bis.name, bu.bis.source))
end
else
UpgradeText:SetText("|cff00ff00All slots are BIS!|r")
end
for i = 1, MAX_VISIBLE_ROWS do for i = 1, MAX_VISIBLE_ROWS do
local row = SlotRows[i] local row = SlotRows[i]
local slotData = data.slots[i] local slotData = data.slots[i]
@@ -492,14 +565,20 @@ function ns.UI.RefreshUI()
end end
if data.equippedStats and data.bisStats then if data.equippedStats and data.bisStats then
local statKeys = Amibis:GetStatKeysForSpec(data.class, data.spec)
if not StatKeysEqual(currentStatKeys, statKeys) then
RebuildStatRows(StatsPanel, statKeys)
currentStatKeys = statKeys
end
if not data.statsComplete then if not data.statsComplete then
if StatsPanelTitle then if StatsPanelTitle then
StatsPanelTitle:SetText("Stats Comparison |cff888888(loading...)|r") StatsPanelTitle:SetText("Stats Comparison |cff888888(loading...)|r")
end end
for _, stat in ipairs(STAT_DISPLAY) do for _, statKey in ipairs(statKeys) do
local vals = StatValues[stat.key] local vals = StatValues[statKey]
if vals then if vals then
local current = data.equippedStats[stat.key] or 0 local current = data.equippedStats[statKey] or 0
vals.current:SetText(current) vals.current:SetText(current)
vals.bis:SetText("|cff888888...|r") vals.bis:SetText("|cff888888...|r")
vals.diff:SetText("") vals.diff:SetText("")
@@ -525,11 +604,11 @@ function ns.UI.RefreshUI()
if StatsPanelTitle then if StatsPanelTitle then
StatsPanelTitle:SetText("Stats Comparison") StatsPanelTitle:SetText("Stats Comparison")
end end
for _, stat in ipairs(STAT_DISPLAY) do for _, statKey in ipairs(statKeys) do
local vals = StatValues[stat.key] local vals = StatValues[statKey]
if vals then if vals then
local current = data.equippedStats[stat.key] or 0 local current = data.equippedStats[statKey] or 0
local bis = data.bisStats[stat.key] or 0 local bis = data.bisStats[statKey] or 0
local diff = bis - current local diff = bis - current
vals.current:SetText(current) vals.current:SetText(current)
@@ -548,6 +627,36 @@ function ns.UI.RefreshUI()
end end
end end
end end
if not data.statsComplete then
if UpgradeLabels[1] then
UpgradeLabels[1]:SetText("|cff888888Loading...|r")
end
for i = 2, 3 do
if UpgradeLabels[i] then
UpgradeLabels[i]:SetText("")
end
end
elseif data.topUpgrades and #data.topUpgrades > 0 then
for i = 1, 3 do
if UpgradeLabels[i] then
if data.topUpgrades[i] then
UpgradeLabels[i]:SetText(FormatUpgradeEntry(i, data.topUpgrades[i]))
else
UpgradeLabels[i]:SetText("")
end
end
end
else
if UpgradeLabels[1] then
UpgradeLabels[1]:SetText("|cff00ff00All slots are BIS!|r")
end
for i = 2, 3 do
if UpgradeLabels[i] then
UpgradeLabels[i]:SetText("")
end
end
end
end end
end end