From 5ff421bd095de13a301496d8938444944e9198f4 Mon Sep 17 00:00:00 2001 From: dfj Date: Wed, 17 Jun 2026 20:14:28 +0200 Subject: [PATCH] Add spec-aware stats panel, top upgrades display, and wider source column --- Amibis/UI/ComparisonFrame.lua | 247 ++++++++++++++++++++++++---------- 1 file changed, 178 insertions(+), 69 deletions(-) diff --git a/Amibis/UI/ComparisonFrame.lua b/Amibis/UI/ComparisonFrame.lua index 44b1100..e3f2c40 100644 --- a/Amibis/UI/ComparisonFrame.lua +++ b/Amibis/UI/ComparisonFrame.lua @@ -17,7 +17,6 @@ local COLOR_EMPTY = { 0.6, 0.6, 0.6 } local MainFrame = nil local TitleText = nil local SummaryText = nil -local UpgradeText = nil local ScrollFrame = nil local SlotRows = {} local MAX_VISIBLE_ROWS = 17 @@ -26,7 +25,7 @@ local ROW_SPACING = 24 local function CreateMainFrame() local frame = CreateFrame("Frame", "AmibisMainFrame", UIParent, "BackdropTemplate") - frame:SetSize(480, 680) + frame:SetSize(640, 680) frame:SetFrameStrata("MEDIUM") frame:SetFrameLevel(10) @@ -113,13 +112,7 @@ local function CreateSummaryBar(parent, anchor) summaryText:SetPoint("LEFT", bar, "LEFT", 8, 0) summaryText:SetTextColor(0.8, 0.8, 0.8, 1) - local upgradeText = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") - 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 + return bar, summaryText end local function CreateColumnHeaders(parent, anchor) @@ -165,8 +158,8 @@ local function CreateColumnHeaders(parent, anchor) enchantHeader:SetTextColor(0.7, 0.7, 0.7, 1) local sourceHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + sourceHeader:SetPoint("LEFT", enchantHeader, "RIGHT", 5, 0) sourceHeader:SetPoint("RIGHT", header, "RIGHT", -8, 0) - sourceHeader:SetWidth(70) sourceHeader:SetJustifyH("RIGHT") sourceHeader:SetText("Source") sourceHeader:SetTextColor(0.7, 0.7, 0.7, 1) @@ -209,15 +202,14 @@ local function CreateSlotRows(parent, anchor) row.enchantText:SetJustifyH("LEFT") 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:SetWidth(70) row.sourceText:SetJustifyH("RIGHT") - row.sourceText:SetWordWrap(true) row:SetScript("OnEnter", function(self) if self.bisLink then GameTooltip:SetOwner(self, "ANCHOR_RIGHT") - GameTooltip:SetHyperlink(self.bisLink) + pcall(GameTooltip.SetHyperlink, GameTooltip, self.bisLink) GameTooltip:Show() end end) @@ -245,22 +237,72 @@ local StatsPanel = nil local StatsPanelTitle = nil local StatLabels = {} local StatValues = {} +local UpgradeLabels = {} -local STAT_DISPLAY = { - { key = "healing", label = "+Healing" }, - { key = "spellPower", label = "+Spell Power" }, - { key = "intellect", label = "Intellect" }, - { key = "spirit", label = "Spirit" }, - { key = "mp5", label = "MP5" }, - { key = "haste", label = "Haste" }, - { key = "crit", label = "Crit" }, +local STAT_LABELS = { + healing = "+Healing", + spellDamage = "+Spell Damage", + spellPower = "+Spell Power", + intellect = "Intellect", + spirit = "Spirit", + mp5 = "MP5", + 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 panel = CreateFrame("Frame", nil, parent, "BackdropTemplate") panel:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -8) panel:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -8) - panel:SetHeight(#STAT_DISPLAY * 16 + 24) + panel:SetHeight(24) panel:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", @@ -277,70 +319,109 @@ local function CreateStatsPanel(parent, anchor) title:SetTextColor(1, 0.82, 0, 1) 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") - currentLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", currentX, -4) - currentLabel:SetWidth(colW) + currentLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_CURRENT_X, -4) + currentLabel:SetWidth(STATS_COL_W) currentLabel:SetJustifyH("CENTER") currentLabel:SetText("Current") currentLabel:SetTextColor(0.7, 0.7, 0.7, 1) local bisLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") - bisLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", bisX, -4) - bisLabel:SetWidth(colW) + bisLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_BIS_X, -4) + bisLabel:SetWidth(STATS_COL_W) bisLabel:SetJustifyH("CENTER") bisLabel:SetText("BIS") bisLabel:SetTextColor(0.7, 0.7, 0.7, 1) local diffLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") - diffLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", diffX, -4) - diffLabel:SetWidth(colW) + diffLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_DIFF_X, -4) + diffLabel:SetWidth(STATS_COL_W) diffLabel:SetJustifyH("CENTER") diffLabel:SetText("Diff") diffLabel:SetTextColor(0.7, 0.7, 0.7, 1) - for i, stat in ipairs(STAT_DISPLAY) do - local y = -(i - 1) * 16 - 22 + local separator = panel:CreateTexture(nil, "ARTWORK") + 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") label:SetPoint("TOPLEFT", panel, "TOPLEFT", 8, y) - label:SetWidth(labelW) + label:SetWidth(STATS_LABEL_W) label:SetJustifyH("RIGHT") - label:SetText(stat.label) + label:SetText(labelText) label:SetTextColor(0.6, 0.6, 0.6, 1) local current = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") - current:SetPoint("TOPLEFT", panel, "TOPLEFT", currentX, y) - current:SetWidth(colW) + current:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_CURRENT_X, y) + current:SetWidth(STATS_COL_W) current:SetJustifyH("CENTER") current:SetText("0") current:SetTextColor(1, 0.5, 0.5, 1) local bis = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") - bis:SetPoint("TOPLEFT", panel, "TOPLEFT", bisX, y) - bis:SetWidth(colW) + bis:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_BIS_X, y) + bis:SetWidth(STATS_COL_W) bis:SetJustifyH("CENTER") bis:SetText("0") bis:SetTextColor(0, 1, 0, 1) local diff = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") - diff:SetPoint("TOPLEFT", panel, "TOPLEFT", diffX, y) - diff:SetWidth(colW) + diff:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_DIFF_X, y) + diff:SetWidth(STATS_COL_W) diff:SetJustifyH("CENTER") diff:SetText("0") diff:SetTextColor(1, 1, 1, 1) - StatLabels[stat.key] = label - StatValues[stat.key] = { current = current, bis = bis, diff = diff } + StatLabels[statKey] = label + StatValues[statKey] = { current = current, bis = bis, diff = diff } end - StatsPanel = panel - return panel + panel:SetHeight(#statKeys * 16 + 24) +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 local function InitializeUI() @@ -350,9 +431,8 @@ local function InitializeUI() local titleBar, title = CreateTitleBar(MainFrame) TitleText = title - local summaryBar, summary, upgrade = CreateSummaryBar(MainFrame, titleBar) + local summaryBar, summary = CreateSummaryBar(MainFrame, titleBar) SummaryText = summary - UpgradeText = upgrade local header = CreateColumnHeaders(MainFrame, summaryBar) local slotContainer = CreateSlotRows(MainFrame, header) @@ -398,7 +478,11 @@ function ns.UI.RefreshUI() 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)) - UpgradeText:SetText("") + for i = 1, 3 do + if UpgradeLabels[i] then + UpgradeLabels[i]:SetText("") + end + end for i = 1, MAX_VISIBLE_ROWS do SlotRows[i].slotText: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)) - 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 local row = SlotRows[i] local slotData = data.slots[i] @@ -492,14 +565,20 @@ function ns.UI.RefreshUI() end 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 StatsPanelTitle then StatsPanelTitle:SetText("Stats Comparison |cff888888(loading...)|r") end - for _, stat in ipairs(STAT_DISPLAY) do - local vals = StatValues[stat.key] + for _, statKey in ipairs(statKeys) do + local vals = StatValues[statKey] if vals then - local current = data.equippedStats[stat.key] or 0 + local current = data.equippedStats[statKey] or 0 vals.current:SetText(current) vals.bis:SetText("|cff888888...|r") vals.diff:SetText("") @@ -525,11 +604,11 @@ function ns.UI.RefreshUI() if StatsPanelTitle then StatsPanelTitle:SetText("Stats Comparison") end - for _, stat in ipairs(STAT_DISPLAY) do - local vals = StatValues[stat.key] + for _, statKey in ipairs(statKeys) do + local vals = StatValues[statKey] if vals then - local current = data.equippedStats[stat.key] or 0 - local bis = data.bisStats[stat.key] or 0 + local current = data.equippedStats[statKey] or 0 + local bis = data.bisStats[statKey] or 0 local diff = bis - current vals.current:SetText(current) @@ -548,6 +627,36 @@ function ns.UI.RefreshUI() 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