1111 lines
44 KiB
Lua
1111 lines
44 KiB
Lua
--------------------------------------------------------------------------------
|
|
-- Nanami-UI: Merchant UI (Merchant.lua)
|
|
-- Replaces MerchantFrame with Nanami-UI styled interface
|
|
-- Tabs: Merchant / Buyback, 4x5 grid, batch buy, repair
|
|
--------------------------------------------------------------------------------
|
|
|
|
SFrames = SFrames or {}
|
|
SFrames.Merchant = {}
|
|
local MUI = SFrames.Merchant
|
|
SFramesDB = SFramesDB or {}
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Theme (Pink Cat-Paw)
|
|
--------------------------------------------------------------------------------
|
|
local T = SFrames.Theme:Extend({
|
|
moneyGold = { 1, 0.84, 0.0 },
|
|
moneySilver = { 0.78, 0.78, 0.78 },
|
|
moneyCopper = { 0.71, 0.43, 0.18 },
|
|
cantAfford = { 0.80, 0.20, 0.20 },
|
|
unusable = { 1.00, 0.25, 0.25 },
|
|
})
|
|
|
|
local QUALITY_COLORS = {
|
|
[0] = { 0.62, 0.62, 0.62 }, [1] = { 1, 1, 1 },
|
|
[2] = { 0.12, 1, 0 }, [3] = { 0.0, 0.44, 0.87 },
|
|
[4] = { 0.64, 0.21, 0.93 }, [5] = { 1, 0.5, 0 },
|
|
}
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Layout
|
|
--------------------------------------------------------------------------------
|
|
local NUM_COLS = 4
|
|
local NUM_ROWS = 5
|
|
local ITEMS_PER_PAGE = NUM_COLS * NUM_ROWS
|
|
local FRAME_W = 620
|
|
local HEADER_H = 34
|
|
local SIDE_PAD = 14
|
|
local ITEM_W = 138
|
|
local ITEM_H = 42
|
|
local ITEM_GAP_X = 6
|
|
local ITEM_GAP_Y = 4
|
|
local ICON_SIZE = 34
|
|
local BOTTOM_H = 50
|
|
local TAB_AREA_H = 28
|
|
local FRAME_H = HEADER_H + 6 + TAB_AREA_H + (ITEM_H + ITEM_GAP_Y) * NUM_ROWS + 6 + BOTTOM_H
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- State
|
|
--------------------------------------------------------------------------------
|
|
local MainFrame = nil
|
|
local ItemButtons = {}
|
|
local CurrentPage = 1
|
|
local CurrentTab = 1
|
|
local BuyPopup = nil
|
|
local ScanTip = nil
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Helpers
|
|
--------------------------------------------------------------------------------
|
|
local function GetFont()
|
|
if SFrames and SFrames.GetFont then return SFrames:GetFont() end
|
|
return "Fonts\\ARIALN.TTF"
|
|
end
|
|
|
|
local function SetRoundBackdrop(frame)
|
|
frame:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 14,
|
|
insets = { left = 3, right = 3, top = 3, bottom = 3 },
|
|
})
|
|
frame:SetBackdropColor(T.panelBg[1], T.panelBg[2], T.panelBg[3], T.panelBg[4])
|
|
frame:SetBackdropBorderColor(T.panelBorder[1], T.panelBorder[2], T.panelBorder[3], T.panelBorder[4])
|
|
end
|
|
|
|
local function CreateShadow(parent)
|
|
local s = CreateFrame("Frame", nil, parent)
|
|
s:SetPoint("TOPLEFT", parent, "TOPLEFT", -4, 4)
|
|
s:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", 4, -4)
|
|
s:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 16,
|
|
insets = { left = 4, right = 4, top = 4, bottom = 4 },
|
|
})
|
|
s:SetBackdropColor(0, 0, 0, 0.45)
|
|
s:SetBackdropBorderColor(0, 0, 0, 0.6)
|
|
s:SetFrameLevel(math.max(0, parent:GetFrameLevel() - 1))
|
|
return s
|
|
end
|
|
|
|
local function FormatMoney(copper)
|
|
if not copper or copper <= 0 then return 0, 0, 0 end
|
|
local g = math.floor(copper / 10000)
|
|
local s = math.floor(math.mod(copper, 10000) / 100)
|
|
local c = math.mod(copper, 100)
|
|
return g, s, c
|
|
end
|
|
|
|
local function GetBuybackQualityColor(index)
|
|
if not ScanTip then
|
|
ScanTip = CreateFrame("GameTooltip", "SFramesMerchantScanTip", UIParent, "GameTooltipTemplate")
|
|
ScanTip:SetOwner(UIParent, "ANCHOR_NONE")
|
|
end
|
|
ScanTip:ClearLines()
|
|
ScanTip:SetBuybackItem(index)
|
|
local textLine = _G["SFramesMerchantScanTipTextLeft1"]
|
|
if textLine then
|
|
local r, g, b = textLine:GetTextColor()
|
|
if r and g and b then return r, g, b end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Item Stack Helpers
|
|
--------------------------------------------------------------------------------
|
|
local function GetMaxStack(link)
|
|
if not link then return 1 end
|
|
local _, _, _, _, _, _, ms = GetItemInfo(link)
|
|
if ms and ms > 0 then return ms end
|
|
return 1
|
|
end
|
|
|
|
local function GetItemCountInBags(link)
|
|
if not link then return 0 end
|
|
local _, _, searchID = string.find(link, "item:(%d+)")
|
|
if not searchID then return 0 end
|
|
local total = 0
|
|
for bag = 0, 4 do
|
|
local slots = GetContainerNumSlots(bag)
|
|
for slot = 1, slots do
|
|
local bagLink = GetContainerItemLink(bag, slot)
|
|
if bagLink then
|
|
local _, _, bagID = string.find(bagLink, "item:(%d+)")
|
|
if bagID == searchID then
|
|
local _, count = GetContainerItemInfo(bag, slot)
|
|
total = total + (count or 1)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return total
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Rounded Action Button Factory (for popups)
|
|
--------------------------------------------------------------------------------
|
|
local function CreateRoundActionBtn(parent, text, w)
|
|
local btn = CreateFrame("Button", nil, parent)
|
|
btn:SetWidth(w or 100)
|
|
btn:SetHeight(28)
|
|
btn:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 14,
|
|
insets = { left = 3, right = 3, top = 3, bottom = 3 },
|
|
})
|
|
btn:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
btn:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
|
|
|
|
local fs = btn:CreateFontString(nil, "OVERLAY")
|
|
fs:SetFont(GetFont(), 11, "OUTLINE")
|
|
fs:SetPoint("CENTER", 0, 0)
|
|
fs:SetText(text)
|
|
fs:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
|
|
btn.label = fs
|
|
|
|
btn.disabled = false
|
|
function btn:SetDisabled(flag)
|
|
self.disabled = flag
|
|
if flag then
|
|
self.label:SetTextColor(T.btnDisabledText[1], T.btnDisabledText[2], T.btnDisabledText[3])
|
|
self:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], 0.5)
|
|
self:SetBackdropBorderColor(T.slotBorder[1], T.slotBorder[2], T.slotBorder[3], 0.5)
|
|
else
|
|
self.label:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
|
|
self:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
self:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
|
|
end
|
|
end
|
|
|
|
btn:SetScript("OnEnter", function()
|
|
if not this.disabled then
|
|
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
|
|
this:SetBackdropBorderColor(T.btnHoverBd[1], T.btnHoverBd[2], T.btnHoverBd[3], T.btnHoverBd[4])
|
|
this.label:SetTextColor(T.btnActiveText[1], T.btnActiveText[2], T.btnActiveText[3])
|
|
end
|
|
end)
|
|
btn:SetScript("OnLeave", function()
|
|
if not this.disabled then
|
|
this:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
this:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
|
|
this.label:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
|
|
end
|
|
end)
|
|
btn:SetScript("OnMouseDown", function()
|
|
if not this.disabled then
|
|
this:SetBackdropColor(T.btnDownBg[1], T.btnDownBg[2], T.btnDownBg[3], T.btnDownBg[4])
|
|
end
|
|
end)
|
|
btn:SetScript("OnMouseUp", function()
|
|
if not this.disabled then
|
|
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
|
|
end
|
|
end)
|
|
|
|
return btn
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Action Button Factory (matching TrainerUI / QuestUI)
|
|
--------------------------------------------------------------------------------
|
|
local function CreateActionBtn(parent, text, w)
|
|
local btn = CreateFrame("Button", nil, parent)
|
|
btn:SetWidth(w or 100)
|
|
btn:SetHeight(28)
|
|
btn:SetBackdrop({
|
|
bgFile = "Interface\\Buttons\\WHITE8X8",
|
|
edgeFile = "Interface\\Buttons\\WHITE8X8",
|
|
tile = false, tileSize = 0, edgeSize = 1,
|
|
insets = { left = 1, right = 1, top = 1, bottom = 1 },
|
|
})
|
|
btn:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
btn:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
|
|
|
|
local fs = btn:CreateFontString(nil, "OVERLAY")
|
|
fs:SetFont(GetFont(), 12, "OUTLINE")
|
|
fs:SetPoint("CENTER", 0, 0)
|
|
fs:SetText(text)
|
|
fs:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
|
|
btn.label = fs
|
|
|
|
btn.disabled = false
|
|
function btn:SetDisabled(flag)
|
|
self.disabled = flag
|
|
if flag then
|
|
self.label:SetTextColor(T.btnDisabledText[1], T.btnDisabledText[2], T.btnDisabledText[3])
|
|
self:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], 0.5)
|
|
self:SetBackdropBorderColor(0.2, 0.15, 0.18, 0.5)
|
|
else
|
|
self.label:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
|
|
self:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
self:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
|
|
end
|
|
end
|
|
|
|
btn:SetScript("OnEnter", function()
|
|
if not this.disabled then
|
|
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
|
|
this:SetBackdropBorderColor(T.btnHoverBd[1], T.btnHoverBd[2], T.btnHoverBd[3], T.btnHoverBd[4])
|
|
this.label:SetTextColor(T.btnActiveText[1], T.btnActiveText[2], T.btnActiveText[3])
|
|
end
|
|
end)
|
|
btn:SetScript("OnLeave", function()
|
|
if not this.disabled then
|
|
this:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
this:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
|
|
this.label:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
|
|
end
|
|
end)
|
|
btn:SetScript("OnMouseDown", function()
|
|
if not this.disabled then
|
|
this:SetBackdropColor(T.btnDownBg[1], T.btnDownBg[2], T.btnDownBg[3], T.btnDownBg[4])
|
|
end
|
|
end)
|
|
btn:SetScript("OnMouseUp", function()
|
|
if not this.disabled then
|
|
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
|
|
end
|
|
end)
|
|
|
|
return btn
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Tab Button Factory
|
|
--------------------------------------------------------------------------------
|
|
local function CreateTabBtn(parent, text, w)
|
|
local btn = CreateFrame("Button", nil, parent)
|
|
btn:SetWidth(w or 70)
|
|
btn:SetHeight(22)
|
|
btn:SetBackdrop({
|
|
bgFile = "Interface\\Buttons\\WHITE8X8",
|
|
edgeFile = "Interface\\Buttons\\WHITE8X8",
|
|
tile = false, tileSize = 0, edgeSize = 1,
|
|
insets = { left = 1, right = 1, top = 1, bottom = 1 },
|
|
})
|
|
btn:SetBackdropColor(T.tabBg[1], T.tabBg[2], T.tabBg[3], T.tabBg[4])
|
|
btn:SetBackdropBorderColor(T.tabBorder[1], T.tabBorder[2], T.tabBorder[3], 0.5)
|
|
|
|
local fs = btn:CreateFontString(nil, "OVERLAY")
|
|
fs:SetFont(GetFont(), 12, "OUTLINE")
|
|
fs:SetPoint("CENTER", 0, 0)
|
|
fs:SetText(text)
|
|
fs:SetTextColor(T.tabText[1], T.tabText[2], T.tabText[3])
|
|
btn.label = fs
|
|
|
|
btn:SetScript("OnEnter", function()
|
|
if not this.active then
|
|
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
|
|
this:SetBackdropBorderColor(T.btnHoverBd[1], T.btnHoverBd[2], T.btnHoverBd[3], T.btnHoverBd[4])
|
|
end
|
|
end)
|
|
btn:SetScript("OnLeave", function()
|
|
if this.active then
|
|
this:SetBackdropColor(T.tabActiveBg[1], T.tabActiveBg[2], T.tabActiveBg[3], T.tabActiveBg[4])
|
|
this:SetBackdropBorderColor(T.tabActiveBorder[1], T.tabActiveBorder[2], T.tabActiveBorder[3], T.tabActiveBorder[4])
|
|
else
|
|
this:SetBackdropColor(T.tabBg[1], T.tabBg[2], T.tabBg[3], T.tabBg[4])
|
|
this:SetBackdropBorderColor(T.tabBorder[1], T.tabBorder[2], T.tabBorder[3], 0.5)
|
|
end
|
|
end)
|
|
|
|
function btn:SetActive(flag)
|
|
self.active = flag
|
|
if flag then
|
|
self:SetBackdropColor(T.tabActiveBg[1], T.tabActiveBg[2], T.tabActiveBg[3], T.tabActiveBg[4])
|
|
self:SetBackdropBorderColor(T.tabActiveBorder[1], T.tabActiveBorder[2], T.tabActiveBorder[3], T.tabActiveBorder[4])
|
|
self.label:SetTextColor(T.tabActiveText[1], T.tabActiveText[2], T.tabActiveText[3])
|
|
else
|
|
self:SetBackdropColor(T.tabBg[1], T.tabBg[2], T.tabBg[3], T.tabBg[4])
|
|
self:SetBackdropBorderColor(T.tabBorder[1], T.tabBorder[2], T.tabBorder[3], 0.5)
|
|
self.label:SetTextColor(T.tabText[1], T.tabText[2], T.tabText[3])
|
|
end
|
|
end
|
|
|
|
return btn
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Buy Popup (Nanami themed, rounded corners, simple quantity input)
|
|
--------------------------------------------------------------------------------
|
|
local function EnsureBuyPopup()
|
|
if BuyPopup then return end
|
|
|
|
BuyPopup = CreateFrame("Frame", "SFramesMerchantBuyPopup", UIParent)
|
|
BuyPopup:SetWidth(240)
|
|
BuyPopup:SetHeight(110)
|
|
BuyPopup:SetPoint("CENTER", UIParent, "CENTER", 0, 60)
|
|
BuyPopup:SetFrameStrata("DIALOG")
|
|
SetRoundBackdrop(BuyPopup)
|
|
CreateShadow(BuyPopup)
|
|
BuyPopup:Hide()
|
|
|
|
local font = GetFont()
|
|
|
|
local titleFS = BuyPopup:CreateFontString(nil, "OVERLAY")
|
|
titleFS:SetFont(font, 13, "OUTLINE")
|
|
titleFS:SetPoint("TOP", BuyPopup, "TOP", 0, -12)
|
|
titleFS:SetTextColor(T.gold[1], T.gold[2], T.gold[3])
|
|
titleFS:SetText("批量购买")
|
|
BuyPopup.titleFS = titleFS
|
|
|
|
local customLabel = BuyPopup:CreateFontString(nil, "OVERLAY")
|
|
customLabel:SetFont(font, 11, "OUTLINE")
|
|
customLabel:SetPoint("TOP", titleFS, "BOTTOM", -18, -10)
|
|
customLabel:SetTextColor(T.dimText[1], T.dimText[2], T.dimText[3])
|
|
customLabel:SetText("购买数量:")
|
|
|
|
local editbox = CreateFrame("EditBox", "SFramesMerchantBuyEditBox", BuyPopup)
|
|
editbox:SetWidth(60)
|
|
editbox:SetHeight(22)
|
|
editbox:SetPoint("LEFT", customLabel, "RIGHT", 6, 0)
|
|
editbox:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 12,
|
|
insets = { left = 2, right = 2, top = 2, bottom = 2 },
|
|
})
|
|
editbox:SetBackdropColor(T.inputBg[1], T.inputBg[2], T.inputBg[3], T.inputBg[4] or 0.95)
|
|
editbox:SetBackdropBorderColor(T.slotBorder[1], T.slotBorder[2], T.slotBorder[3], 0.8)
|
|
editbox:SetFont(font, 12, "OUTLINE")
|
|
editbox:SetTextColor(T.nameText[1], T.nameText[2], T.nameText[3])
|
|
editbox:SetJustifyH("CENTER")
|
|
editbox:SetNumeric(true)
|
|
editbox:SetAutoFocus(false)
|
|
editbox:SetTextInsets(4, 4, 2, 2)
|
|
|
|
local confirm = CreateRoundActionBtn(BuyPopup, "确定", 75)
|
|
confirm:SetPoint("BOTTOMLEFT", BuyPopup, "BOTTOMLEFT", 28, 12)
|
|
|
|
local cancel = CreateRoundActionBtn(BuyPopup, "取消", 75)
|
|
cancel:SetPoint("BOTTOMRIGHT", BuyPopup, "BOTTOMRIGHT", -28, 12)
|
|
|
|
BuyPopup.index = 1
|
|
BuyPopup.maxPurchase = 100
|
|
BuyPopup.itemLink = nil
|
|
|
|
local function DoBuy()
|
|
local qty = tonumber(editbox:GetText()) or 0
|
|
if qty > 0 then
|
|
if qty > BuyPopup.maxPurchase then qty = BuyPopup.maxPurchase end
|
|
MUI:BuyMultiple(BuyPopup.index, qty)
|
|
end
|
|
BuyPopup:Hide()
|
|
end
|
|
|
|
confirm:SetScript("OnClick", DoBuy)
|
|
cancel:SetScript("OnClick", function() BuyPopup:Hide() end)
|
|
editbox:SetScript("OnEnterPressed", DoBuy)
|
|
editbox:SetScript("OnEscapePressed", function() BuyPopup:Hide() end)
|
|
|
|
BuyPopup.ShowPopup = function(index, maxAfford, itemLink)
|
|
BuyPopup.index = index
|
|
BuyPopup.maxPurchase = math.min(9999, maxAfford)
|
|
BuyPopup.itemLink = itemLink
|
|
editbox:SetText("1")
|
|
|
|
BuyPopup.titleFS:SetText("批量购买")
|
|
|
|
BuyPopup:Show()
|
|
editbox:SetFocus()
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Batch Buy Logic
|
|
--------------------------------------------------------------------------------
|
|
function MUI:BuyMultiple(index, totalAmount)
|
|
if totalAmount <= 0 then return end
|
|
if CurrentTab == 2 then
|
|
BuybackItem(index)
|
|
return
|
|
end
|
|
|
|
local name, _, price, batchQty, numAvailable = GetMerchantItemInfo(index)
|
|
|
|
if numAvailable > -1 and totalAmount > numAvailable then
|
|
totalAmount = numAvailable
|
|
end
|
|
|
|
for i = 1, totalAmount do
|
|
BuyMerchantItem(index, 1)
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Merchant Item Button Factory
|
|
--------------------------------------------------------------------------------
|
|
local function CreateMerchantButton(parent, id)
|
|
local btn = CreateFrame("Button", "SFramesMerchantItem" .. id, parent)
|
|
btn:SetWidth(ITEM_W)
|
|
btn:SetHeight(ITEM_H)
|
|
|
|
local iconFrame = CreateFrame("Button", btn:GetName() .. "Icon", btn)
|
|
iconFrame:SetWidth(ICON_SIZE)
|
|
iconFrame:SetHeight(ICON_SIZE)
|
|
iconFrame:SetPoint("LEFT", btn, "LEFT", 2, 0)
|
|
iconFrame:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
|
iconFrame:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 12,
|
|
insets = { left = 2, right = 2, top = 2, bottom = 2 },
|
|
})
|
|
iconFrame:SetBackdropColor(T.slotBg[1], T.slotBg[2], T.slotBg[3], T.slotBg[4])
|
|
iconFrame:SetBackdropBorderColor(T.slotBorder[1], T.slotBorder[2], T.slotBorder[3], T.slotBorder[4])
|
|
btn.iconFrame = iconFrame
|
|
|
|
local qualGlow = iconFrame:CreateTexture(nil, "OVERLAY")
|
|
qualGlow:SetTexture("Interface\\Buttons\\UI-ActionButton-Border")
|
|
qualGlow:SetBlendMode("ADD")
|
|
qualGlow:SetAlpha(0.7)
|
|
qualGlow:SetWidth(ICON_SIZE * 1.8)
|
|
qualGlow:SetHeight(ICON_SIZE * 1.8)
|
|
qualGlow:SetPoint("CENTER", iconFrame, "CENTER", 0, 0)
|
|
qualGlow:Hide()
|
|
btn.qualGlow = qualGlow
|
|
|
|
function btn:SetQualityBorder(r, g, b)
|
|
self.qualGlow:SetVertexColor(r, g, b)
|
|
self.qualGlow:Show()
|
|
self.iconFrame:SetBackdropBorderColor(r, g, b, 1)
|
|
end
|
|
function btn:ResetBorder()
|
|
self.qualGlow:Hide()
|
|
self.iconFrame:SetBackdropBorderColor(T.slotBorder[1], T.slotBorder[2], T.slotBorder[3], T.slotBorder[4])
|
|
end
|
|
|
|
local icon = iconFrame:CreateTexture(nil, "ARTWORK")
|
|
icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
|
icon:SetPoint("TOPLEFT", iconFrame, "TOPLEFT", 3, -3)
|
|
icon:SetPoint("BOTTOMRIGHT", iconFrame, "BOTTOMRIGHT", -3, 3)
|
|
btn.icon = icon
|
|
|
|
local font = GetFont()
|
|
local nameFS = btn:CreateFontString(nil, "OVERLAY")
|
|
nameFS:SetFont(font, 11, "OUTLINE")
|
|
nameFS:SetPoint("TOPLEFT", iconFrame, "TOPRIGHT", 5, -1)
|
|
nameFS:SetPoint("RIGHT", btn, "RIGHT", -2, 0)
|
|
nameFS:SetJustifyH("LEFT")
|
|
nameFS:SetTextColor(T.nameText[1], T.nameText[2], T.nameText[3])
|
|
btn.nameFS = nameFS
|
|
|
|
btn.gTxt = btn:CreateFontString(nil, "OVERLAY")
|
|
btn.gTxt:SetFont(font, 10, "OUTLINE")
|
|
btn.gTex = btn:CreateTexture(nil, "ARTWORK")
|
|
btn.gTex:SetTexture("Interface\\MoneyFrame\\UI-MoneyIcons")
|
|
btn.gTex:SetTexCoord(0, 0.25, 0, 1)
|
|
btn.gTex:SetWidth(11); btn.gTex:SetHeight(11)
|
|
|
|
btn.sTxt = btn:CreateFontString(nil, "OVERLAY")
|
|
btn.sTxt:SetFont(font, 10, "OUTLINE")
|
|
btn.sTex = btn:CreateTexture(nil, "ARTWORK")
|
|
btn.sTex:SetTexture("Interface\\MoneyFrame\\UI-MoneyIcons")
|
|
btn.sTex:SetTexCoord(0.25, 0.5, 0, 1)
|
|
btn.sTex:SetWidth(11); btn.sTex:SetHeight(11)
|
|
|
|
btn.cTxt = btn:CreateFontString(nil, "OVERLAY")
|
|
btn.cTxt:SetFont(font, 10, "OUTLINE")
|
|
btn.cTex = btn:CreateTexture(nil, "ARTWORK")
|
|
btn.cTex:SetTexture("Interface\\MoneyFrame\\UI-MoneyIcons")
|
|
btn.cTex:SetTexCoord(0.5, 0.75, 0, 1)
|
|
btn.cTex:SetWidth(11); btn.cTex:SetHeight(11)
|
|
|
|
local countFS = iconFrame:CreateFontString(nil, "OVERLAY")
|
|
countFS:SetFont("Fonts\\ARIALN.TTF", 11, "OUTLINE")
|
|
countFS:SetPoint("BOTTOMRIGHT", iconFrame, "BOTTOMRIGHT", -2, 2)
|
|
countFS:SetJustifyH("RIGHT")
|
|
btn.countFS = countFS
|
|
|
|
local highlight = btn:CreateTexture(nil, "HIGHLIGHT")
|
|
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
|
|
highlight:SetBlendMode("ADD")
|
|
highlight:SetAllPoints(btn)
|
|
highlight:SetAlpha(0.15)
|
|
|
|
local function OnEnter()
|
|
if not btn.itemIndex then return end
|
|
btn.iconFrame:SetBackdropBorderColor(T.slotHover[1], T.slotHover[2], T.slotHover[3], T.slotHover[4])
|
|
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
|
if CurrentTab == 1 then
|
|
GameTooltip:SetMerchantItem(btn.itemIndex)
|
|
ShowMerchantSellCursor(btn.itemIndex)
|
|
local _, _, price = GetMerchantItemInfo(btn.itemIndex)
|
|
if price and price > 0 then
|
|
GameTooltip:AddLine(" ")
|
|
GameTooltip:AddLine(">> 本店售价:", 1, 0.8, 0)
|
|
SetTooltipMoney(GameTooltip, price)
|
|
end
|
|
else
|
|
GameTooltip:SetBuybackItem(btn.itemIndex)
|
|
local _, _, price = GetBuybackItemInfo(btn.itemIndex)
|
|
if price and price > 0 then
|
|
GameTooltip:AddLine(" ")
|
|
GameTooltip:AddLine(">> 购回需花费:", 1, 0.5, 0)
|
|
SetTooltipMoney(GameTooltip, price)
|
|
end
|
|
end
|
|
local ttLink = (CurrentTab == 1) and GetMerchantItemLink(btn.itemIndex) or nil
|
|
if not ttLink and CurrentTab == 2 and GetBuybackItemLink then
|
|
ttLink = GetBuybackItemLink(btn.itemIndex)
|
|
end
|
|
if ttLink then
|
|
local ms = GetMaxStack(ttLink)
|
|
if ms and ms > 1 then
|
|
GameTooltip:AddLine(" ")
|
|
GameTooltip:AddLine("最大堆叠: " .. ms, 0.5, 0.8, 1)
|
|
end
|
|
end
|
|
if IsControlKeyDown() then ShowInspectCursor() end
|
|
GameTooltip:Show()
|
|
end
|
|
|
|
local function OnLeave()
|
|
GameTooltip:Hide()
|
|
ResetCursor()
|
|
if btn._qualR then
|
|
btn.iconFrame:SetBackdropBorderColor(btn._qualR, btn._qualG, btn._qualB, 1)
|
|
else
|
|
btn.iconFrame:SetBackdropBorderColor(T.slotBorder[1], T.slotBorder[2], T.slotBorder[3], T.slotBorder[4])
|
|
end
|
|
end
|
|
|
|
iconFrame:SetScript("OnEnter", OnEnter)
|
|
iconFrame:SetScript("OnLeave", OnLeave)
|
|
|
|
iconFrame:SetScript("OnUpdate", function()
|
|
if GameTooltip:IsOwned(this) then
|
|
if IsControlKeyDown() then
|
|
if not this.controlDownLast then
|
|
this.controlDownLast = true
|
|
ShowInspectCursor()
|
|
end
|
|
else
|
|
if this.controlDownLast then
|
|
this.controlDownLast = false
|
|
ResetCursor()
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
iconFrame:SetScript("OnClick", function()
|
|
if not btn.itemIndex then return end
|
|
if IsControlKeyDown() and arg1 == "LeftButton" then
|
|
local link = GetMerchantItemLink(btn.itemIndex)
|
|
if link and DressUpItemLink then
|
|
DressUpItemLink(link)
|
|
return
|
|
end
|
|
end
|
|
if IsShiftKeyDown() then
|
|
if ChatFrameEditBox and ChatFrameEditBox:IsVisible() then
|
|
local link = nil
|
|
if CurrentTab == 1 then link = GetMerchantItemLink(btn.itemIndex) end
|
|
if link then ChatFrameEditBox:Insert(link) end
|
|
else
|
|
if CurrentTab == 1 then
|
|
local name, _, price, quantity, numAvailable = GetMerchantItemInfo(btn.itemIndex)
|
|
if not name then return end
|
|
local popupLink = GetMerchantItemLink(btn.itemIndex)
|
|
local maxCanAfford = 9999
|
|
if price and price > 0 then
|
|
maxCanAfford = math.floor(GetMoney() / price)
|
|
end
|
|
if numAvailable > -1 and numAvailable < maxCanAfford then
|
|
maxCanAfford = numAvailable
|
|
end
|
|
if maxCanAfford < 1 then return end
|
|
EnsureBuyPopup()
|
|
BuyPopup.ShowPopup(btn.itemIndex, maxCanAfford, popupLink)
|
|
else
|
|
BuybackItem(btn.itemIndex)
|
|
end
|
|
end
|
|
elseif arg1 == "RightButton" then
|
|
if CurrentTab == 1 then
|
|
BuyMerchantItem(btn.itemIndex, 1)
|
|
else
|
|
BuybackItem(btn.itemIndex)
|
|
end
|
|
end
|
|
end)
|
|
|
|
return btn
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Money Layout Helper
|
|
--------------------------------------------------------------------------------
|
|
local function LayoutMoney(btn, copper, canBuy)
|
|
btn.gTxt:Hide(); btn.gTex:Hide()
|
|
btn.sTxt:Hide(); btn.sTex:Hide()
|
|
btn.cTxt:Hide(); btn.cTex:Hide()
|
|
|
|
local r, g, b
|
|
if canBuy then
|
|
r, g, b = T.bodyText[1], T.bodyText[2], T.bodyText[3]
|
|
else
|
|
r, g, b = T.cantAfford[1], T.cantAfford[2], T.cantAfford[3]
|
|
end
|
|
|
|
if copper == 0 then
|
|
btn.cTxt:SetText("0")
|
|
btn.cTxt:SetTextColor(r, g, b)
|
|
btn.cTxt:ClearAllPoints()
|
|
btn.cTxt:SetPoint("BOTTOMLEFT", btn.iconFrame, "BOTTOMRIGHT", 5, 2)
|
|
btn.cTxt:Show()
|
|
btn.cTex:ClearAllPoints()
|
|
btn.cTex:SetPoint("LEFT", btn.cTxt, "RIGHT", 1, 0)
|
|
btn.cTex:Show()
|
|
return
|
|
end
|
|
|
|
local vG, vS, vC = FormatMoney(copper)
|
|
local anchor = nil
|
|
|
|
local function AttachPair(txt, tex, val, coinR, coinG, coinB)
|
|
txt:SetText(val)
|
|
txt:SetTextColor(canBuy and coinR or r, canBuy and coinG or g, canBuy and coinB or b)
|
|
txt:ClearAllPoints()
|
|
if not anchor then
|
|
txt:SetPoint("BOTTOMLEFT", btn.iconFrame, "BOTTOMRIGHT", 5, 2)
|
|
else
|
|
txt:SetPoint("LEFT", anchor, "RIGHT", 4, 0)
|
|
end
|
|
txt:Show()
|
|
tex:ClearAllPoints()
|
|
tex:SetPoint("LEFT", txt, "RIGHT", 1, 0)
|
|
tex:Show()
|
|
anchor = tex
|
|
end
|
|
|
|
if vG > 0 then AttachPair(btn.gTxt, btn.gTex, vG, T.moneyGold[1], T.moneyGold[2], T.moneyGold[3]) end
|
|
if vS > 0 then AttachPair(btn.sTxt, btn.sTex, vS, T.moneySilver[1], T.moneySilver[2], T.moneySilver[3]) end
|
|
if vC > 0 then AttachPair(btn.cTxt, btn.cTex, vC, T.moneyCopper[1], T.moneyCopper[2], T.moneyCopper[3]) end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Update
|
|
--------------------------------------------------------------------------------
|
|
function MUI:Update()
|
|
if not MainFrame or not MainFrame:IsVisible() then return end
|
|
|
|
local numItems = (CurrentTab == 1) and GetMerchantNumItems() or GetNumBuybackItems()
|
|
local name = UnitName("NPC") or "商人"
|
|
if CurrentTab == 2 then name = name .. " - 购回" end
|
|
MainFrame.npcNameFS:SetText(name)
|
|
|
|
local totalPages = math.max(1, math.ceil(numItems / ITEMS_PER_PAGE))
|
|
if CurrentPage > totalPages then CurrentPage = totalPages end
|
|
if CurrentPage < 1 then CurrentPage = 1 end
|
|
|
|
MainFrame.pageText:SetText(string.format("第 %d / %d 页", CurrentPage, totalPages))
|
|
MainFrame.prevBtn:SetDisabled(CurrentPage <= 1)
|
|
MainFrame.nextBtn:SetDisabled(CurrentPage >= totalPages)
|
|
|
|
MainFrame.tabMerchant:SetActive(CurrentTab == 1)
|
|
MainFrame.tabBuyback:SetActive(CurrentTab == 2)
|
|
|
|
for i = 1, ITEMS_PER_PAGE do
|
|
local btn = ItemButtons[i]
|
|
local itemIndex = (CurrentPage - 1) * ITEMS_PER_PAGE + i
|
|
|
|
if itemIndex <= numItems then
|
|
local itemName, itemTexture, itemPrice, itemQuantity, numAvailable, isUsable
|
|
local itemLink
|
|
|
|
if CurrentTab == 1 then
|
|
itemName, itemTexture, itemPrice, itemQuantity, numAvailable, isUsable = GetMerchantItemInfo(itemIndex)
|
|
itemLink = GetMerchantItemLink(itemIndex)
|
|
else
|
|
itemName, itemTexture, itemPrice, itemQuantity, numAvailable, isUsable = GetBuybackItemInfo(itemIndex)
|
|
if GetBuybackItemLink then itemLink = GetBuybackItemLink(itemIndex) end
|
|
end
|
|
|
|
btn.itemIndex = itemIndex
|
|
btn.icon:SetTexture(itemTexture)
|
|
btn.nameFS:SetText(itemName)
|
|
btn._qualR = nil; btn._qualG = nil; btn._qualB = nil
|
|
|
|
if CurrentTab == 2 and isUsable == nil then isUsable = true end
|
|
local canAfford = (GetMoney() >= itemPrice)
|
|
local isRequirementBlocked = (CurrentTab == 1 and not isUsable)
|
|
local canBuy = (not isRequirementBlocked) and canAfford
|
|
if canBuy then
|
|
btn.icon:SetVertexColor(1, 1, 1)
|
|
btn.nameFS:SetAlpha(1)
|
|
else
|
|
btn.icon:SetVertexColor(0.5, 0.2, 0.2)
|
|
btn.nameFS:SetAlpha(0.6)
|
|
end
|
|
|
|
LayoutMoney(btn, itemPrice, canBuy)
|
|
|
|
if CurrentTab == 1 and numAvailable and numAvailable > -1 then
|
|
btn.countFS:SetText(numAvailable)
|
|
if numAvailable == 0 then
|
|
btn.countFS:SetTextColor(T.dimText[1], T.dimText[2], T.dimText[3])
|
|
else
|
|
btn.countFS:SetTextColor(T.nameText[1], T.nameText[2], T.nameText[3])
|
|
end
|
|
elseif itemQuantity and itemQuantity > 1 then
|
|
btn.countFS:SetText(itemQuantity)
|
|
btn.countFS:SetTextColor(T.nameText[1], T.nameText[2], T.nameText[3])
|
|
else
|
|
btn.countFS:SetText("")
|
|
end
|
|
|
|
local qr, qg, qb
|
|
local quality
|
|
|
|
if itemLink then
|
|
local _, _, q = GetItemInfo(itemLink)
|
|
quality = q
|
|
if not quality then
|
|
local _, _, itemID = string.find(itemLink, "item:(%d+)")
|
|
if itemID then _, _, quality = GetItemInfo("item:" .. itemID) end
|
|
end
|
|
if quality then
|
|
qr, qg, qb = GetItemQualityColor(quality)
|
|
else
|
|
local _, _, hexColor = string.find(itemLink, "|c(%x%x%x%x%x%x%x%x)|")
|
|
if hexColor then
|
|
qr = tonumber(string.sub(hexColor, 3, 4), 16) / 255
|
|
qg = tonumber(string.sub(hexColor, 5, 6), 16) / 255
|
|
qb = tonumber(string.sub(hexColor, 7, 8), 16) / 255
|
|
end
|
|
end
|
|
elseif CurrentTab == 2 and itemName then
|
|
qr, qg, qb = GetBuybackQualityColor(itemIndex)
|
|
end
|
|
|
|
if isRequirementBlocked then
|
|
-- Level / weapon skill / class requirements not met: always mark red.
|
|
btn.nameFS:SetTextColor(T.unusable[1], T.unusable[2], T.unusable[3])
|
|
btn.nameFS:SetAlpha(1)
|
|
btn.icon:SetVertexColor(0.75, 0.25, 0.25)
|
|
btn:SetQualityBorder(T.unusable[1], T.unusable[2], T.unusable[3])
|
|
btn._qualR = T.unusable[1]; btn._qualG = T.unusable[2]; btn._qualB = T.unusable[3]
|
|
elseif qr then
|
|
btn.nameFS:SetTextColor(qr, qg, qb)
|
|
btn._qualR = qr; btn._qualG = qg; btn._qualB = qb
|
|
if quality and quality > 1 then
|
|
btn:SetQualityBorder(qr, qg, qb)
|
|
else
|
|
local isWhite = (qr > 0.95 and qg > 0.95 and qb > 0.95)
|
|
local isGrey = (qr < 0.7 and qg < 0.7 and qb < 0.7)
|
|
if not isWhite and not isGrey then
|
|
btn:SetQualityBorder(qr, qg, qb)
|
|
else
|
|
btn:ResetBorder()
|
|
btn._qualR = nil; btn._qualG = nil; btn._qualB = nil
|
|
end
|
|
end
|
|
else
|
|
btn.nameFS:SetTextColor(T.nameText[1], T.nameText[2], T.nameText[3])
|
|
btn:ResetBorder()
|
|
end
|
|
|
|
if CurrentTab == 1 and numAvailable and numAvailable == 0 then
|
|
btn.icon:SetVertexColor(0.4, 0.4, 0.4)
|
|
btn.nameFS:SetTextColor(T.dimText[1], T.dimText[2], T.dimText[3])
|
|
btn.nameFS:SetAlpha(0.5)
|
|
btn:ResetBorder()
|
|
btn._qualR = nil; btn._qualG = nil; btn._qualB = nil
|
|
LayoutMoney(btn, itemPrice, false)
|
|
end
|
|
|
|
btn:Show()
|
|
else
|
|
btn.itemIndex = nil
|
|
btn._qualR = nil; btn._qualG = nil; btn._qualB = nil
|
|
btn:ResetBorder()
|
|
btn:Hide()
|
|
end
|
|
end
|
|
|
|
if CanMerchantRepair() then
|
|
MainFrame.repairAllBtn:Show()
|
|
MainFrame.repairItemBtn:Show()
|
|
local repairCost, canRepair = GetRepairAllCost()
|
|
if canRepair and repairCost > 0 and (GetMoney() >= repairCost) then
|
|
MainFrame.repairAllBtn.canClick = true
|
|
if MainFrame.repairAllBtn.iconTex then
|
|
MainFrame.repairAllBtn.iconTex:SetVertexColor(1, 1, 1)
|
|
end
|
|
else
|
|
MainFrame.repairAllBtn.canClick = false
|
|
if MainFrame.repairAllBtn.iconTex then
|
|
MainFrame.repairAllBtn.iconTex:SetVertexColor(0.5, 0.5, 0.5)
|
|
end
|
|
end
|
|
else
|
|
MainFrame.repairAllBtn:Hide()
|
|
MainFrame.repairItemBtn:Hide()
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Initialize
|
|
--------------------------------------------------------------------------------
|
|
function MUI:Initialize()
|
|
if MainFrame then return end
|
|
|
|
MainFrame = CreateFrame("Frame", "SFramesMerchantFrame", UIParent)
|
|
MainFrame:SetWidth(FRAME_W)
|
|
MainFrame:SetHeight(FRAME_H)
|
|
MainFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 12, -104)
|
|
MainFrame:SetFrameStrata("HIGH")
|
|
MainFrame:SetToplevel(true)
|
|
MainFrame:EnableMouse(true)
|
|
MainFrame:SetMovable(true)
|
|
MainFrame:RegisterForDrag("LeftButton")
|
|
MainFrame:SetScript("OnDragStart", function() this:StartMoving() end)
|
|
MainFrame:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
|
|
|
|
SetRoundBackdrop(MainFrame)
|
|
CreateShadow(MainFrame)
|
|
|
|
-- Header
|
|
local header = CreateFrame("Frame", nil, MainFrame)
|
|
header:SetPoint("TOPLEFT", MainFrame, "TOPLEFT", 0, 0)
|
|
header:SetPoint("TOPRIGHT", MainFrame, "TOPRIGHT", 0, 0)
|
|
header:SetHeight(HEADER_H)
|
|
header:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8X8" })
|
|
header:SetBackdropColor(T.headerBg[1], T.headerBg[2], T.headerBg[3], T.headerBg[4])
|
|
|
|
local titleIco = SFrames:CreateIcon(header, "merchant", 16)
|
|
titleIco:SetDrawLayer("OVERLAY")
|
|
titleIco:SetPoint("LEFT", header, "LEFT", SIDE_PAD, 0)
|
|
titleIco:SetVertexColor(T.gold[1], T.gold[2], T.gold[3])
|
|
|
|
local npcNameFS = header:CreateFontString(nil, "OVERLAY")
|
|
npcNameFS:SetFont(GetFont(), 14, "OUTLINE")
|
|
npcNameFS:SetPoint("LEFT", titleIco, "RIGHT", 5, 0)
|
|
npcNameFS:SetPoint("RIGHT", header, "RIGHT", -30, 0)
|
|
npcNameFS:SetJustifyH("LEFT")
|
|
npcNameFS:SetTextColor(T.gold[1], T.gold[2], T.gold[3])
|
|
MainFrame.npcNameFS = npcNameFS
|
|
|
|
local closeBtn = CreateFrame("Button", nil, header)
|
|
closeBtn:SetWidth(20); closeBtn:SetHeight(20)
|
|
closeBtn:SetPoint("RIGHT", header, "RIGHT", -8, 0)
|
|
local closeTex = closeBtn:CreateTexture(nil, "ARTWORK")
|
|
closeTex:SetTexture("Interface\\AddOns\\Nanami-UI\\img\\icon")
|
|
closeTex:SetTexCoord(0.25, 0.375, 0, 0.125)
|
|
closeTex:SetAllPoints()
|
|
closeTex:SetVertexColor(T.dimText[1], T.dimText[2], T.dimText[3])
|
|
closeBtn:SetScript("OnClick", function() MainFrame:Hide() end)
|
|
closeBtn:SetScript("OnEnter", function() closeTex:SetVertexColor(1, 0.6, 0.7) end)
|
|
closeBtn:SetScript("OnLeave", function() closeTex:SetVertexColor(T.dimText[1], T.dimText[2], T.dimText[3]) end)
|
|
|
|
local headerSep = MainFrame:CreateTexture(nil, "ARTWORK")
|
|
headerSep:SetTexture("Interface\\Buttons\\WHITE8X8")
|
|
headerSep:SetHeight(1)
|
|
headerSep:SetPoint("TOPLEFT", MainFrame, "TOPLEFT", 6, -HEADER_H)
|
|
headerSep:SetPoint("TOPRIGHT", MainFrame, "TOPRIGHT", -6, -HEADER_H)
|
|
headerSep:SetVertexColor(T.divider[1], T.divider[2], T.divider[3], T.divider[4])
|
|
|
|
-- Tabs
|
|
local tabMerchant = CreateTabBtn(MainFrame, "商人", 60)
|
|
tabMerchant:SetPoint("TOPLEFT", MainFrame, "TOPLEFT", SIDE_PAD, -(HEADER_H + 6))
|
|
tabMerchant:SetScript("OnClick", function()
|
|
CurrentTab = 1
|
|
CurrentPage = 1
|
|
MUI:Update()
|
|
end)
|
|
MainFrame.tabMerchant = tabMerchant
|
|
|
|
local tabBuyback = CreateTabBtn(MainFrame, "购回", 60)
|
|
tabBuyback:SetPoint("LEFT", tabMerchant, "RIGHT", 4, 0)
|
|
tabBuyback:SetScript("OnClick", function()
|
|
CurrentTab = 2
|
|
CurrentPage = 1
|
|
MUI:Update()
|
|
end)
|
|
MainFrame.tabBuyback = tabBuyback
|
|
|
|
-- Item Grid
|
|
local gridTop = HEADER_H + 6 + 22 + 6
|
|
for i = 1, ITEMS_PER_PAGE do
|
|
local btn = CreateMerchantButton(MainFrame, i)
|
|
local row = math.floor((i - 1) / NUM_COLS)
|
|
local col = math.mod((i - 1), NUM_COLS)
|
|
btn:SetPoint("TOPLEFT", MainFrame, "TOPLEFT",
|
|
SIDE_PAD + col * (ITEM_W + ITEM_GAP_X),
|
|
-(gridTop + row * (ITEM_H + ITEM_GAP_Y)))
|
|
ItemButtons[i] = btn
|
|
end
|
|
|
|
-- Bottom bar separator
|
|
local bottomSep = MainFrame:CreateTexture(nil, "ARTWORK")
|
|
bottomSep:SetTexture("Interface\\Buttons\\WHITE8X8")
|
|
bottomSep:SetHeight(1)
|
|
bottomSep:SetPoint("BOTTOMLEFT", MainFrame, "BOTTOMLEFT", 6, BOTTOM_H)
|
|
bottomSep:SetPoint("BOTTOMRIGHT", MainFrame, "BOTTOMRIGHT", -6, BOTTOM_H)
|
|
bottomSep:SetVertexColor(T.divider[1], T.divider[2], T.divider[3], T.divider[4])
|
|
|
|
-- Page Navigation
|
|
local prevBtn = CreateActionBtn(MainFrame, "<", 28)
|
|
prevBtn:SetHeight(22)
|
|
prevBtn:SetPoint("BOTTOMLEFT", MainFrame, "BOTTOMLEFT", SIDE_PAD, 14)
|
|
prevBtn:SetScript("OnClick", function()
|
|
CurrentPage = CurrentPage - 1
|
|
MUI:Update()
|
|
end)
|
|
MainFrame.prevBtn = prevBtn
|
|
|
|
local nextBtn = CreateActionBtn(MainFrame, ">", 28)
|
|
nextBtn:SetHeight(22)
|
|
nextBtn:SetPoint("LEFT", prevBtn, "RIGHT", 4, 0)
|
|
nextBtn:SetScript("OnClick", function()
|
|
CurrentPage = CurrentPage + 1
|
|
MUI:Update()
|
|
end)
|
|
MainFrame.nextBtn = nextBtn
|
|
|
|
local pageText = MainFrame:CreateFontString(nil, "OVERLAY")
|
|
pageText:SetFont(GetFont(), 11, "OUTLINE")
|
|
pageText:SetPoint("LEFT", nextBtn, "RIGHT", 8, 0)
|
|
pageText:SetTextColor(T.dimText[1], T.dimText[2], T.dimText[3])
|
|
MainFrame.pageText = pageText
|
|
|
|
-- Repair Buttons
|
|
local repairAllBtn = CreateFrame("Button", nil, MainFrame)
|
|
repairAllBtn:SetWidth(32); repairAllBtn:SetHeight(32)
|
|
repairAllBtn:SetPoint("BOTTOMRIGHT", MainFrame, "BOTTOMRIGHT", -(SIDE_PAD), 10)
|
|
repairAllBtn:SetBackdrop({
|
|
bgFile = "Interface\\Buttons\\WHITE8X8",
|
|
edgeFile = "Interface\\Buttons\\WHITE8X8",
|
|
tile = false, tileSize = 0, edgeSize = 1,
|
|
insets = { left = 1, right = 1, top = 1, bottom = 1 },
|
|
})
|
|
repairAllBtn:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
repairAllBtn:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], 0.6)
|
|
|
|
local repairAllIcon = repairAllBtn:CreateTexture(nil, "ARTWORK")
|
|
repairAllIcon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
|
repairAllIcon:SetPoint("TOPLEFT", 3, -3)
|
|
repairAllIcon:SetPoint("BOTTOMRIGHT", -3, 3)
|
|
repairAllIcon:SetTexture("Interface\\Icons\\Trade_BlackSmithing")
|
|
repairAllBtn.iconTex = repairAllIcon
|
|
|
|
repairAllBtn:SetScript("OnClick", function()
|
|
if this.canClick then RepairAllItems() end
|
|
end)
|
|
repairAllBtn:SetScript("OnEnter", function()
|
|
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
|
|
this:SetBackdropBorderColor(T.btnHoverBd[1], T.btnHoverBd[2], T.btnHoverBd[3], T.btnHoverBd[4])
|
|
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
|
GameTooltip:SetText("修理所有物品", 1, 1, 1)
|
|
local repairCost, canRepair = GetRepairAllCost()
|
|
if canRepair and repairCost > 0 then SetTooltipMoney(GameTooltip, repairCost) end
|
|
GameTooltip:Show()
|
|
end)
|
|
repairAllBtn:SetScript("OnLeave", function()
|
|
this:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
this:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], 0.6)
|
|
GameTooltip:Hide()
|
|
end)
|
|
MainFrame.repairAllBtn = repairAllBtn
|
|
|
|
local repairItemBtn = CreateFrame("Button", nil, MainFrame)
|
|
repairItemBtn:SetWidth(32); repairItemBtn:SetHeight(32)
|
|
repairItemBtn:SetPoint("RIGHT", repairAllBtn, "LEFT", -6, 0)
|
|
repairItemBtn:SetBackdrop({
|
|
bgFile = "Interface\\Buttons\\WHITE8X8",
|
|
edgeFile = "Interface\\Buttons\\WHITE8X8",
|
|
tile = false, tileSize = 0, edgeSize = 1,
|
|
insets = { left = 1, right = 1, top = 1, bottom = 1 },
|
|
})
|
|
repairItemBtn:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
repairItemBtn:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], 0.6)
|
|
|
|
local repairItemIcon = repairItemBtn:CreateTexture(nil, "ARTWORK")
|
|
repairItemIcon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
|
repairItemIcon:SetPoint("TOPLEFT", 3, -3)
|
|
repairItemIcon:SetPoint("BOTTOMRIGHT", -3, 3)
|
|
repairItemIcon:SetTexture("Interface\\Icons\\INV_Hammer_20")
|
|
repairItemBtn.iconTex = repairItemIcon
|
|
|
|
repairItemBtn:SetScript("OnClick", function()
|
|
if InRepairMode() then HideRepairCursor() else ShowRepairCursor() end
|
|
end)
|
|
repairItemBtn:SetScript("OnEnter", function()
|
|
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
|
|
this:SetBackdropBorderColor(T.btnHoverBd[1], T.btnHoverBd[2], T.btnHoverBd[3], T.btnHoverBd[4])
|
|
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
|
GameTooltip:SetText("修理一件物品", 1, 1, 1)
|
|
GameTooltip:Show()
|
|
end)
|
|
repairItemBtn:SetScript("OnLeave", function()
|
|
this:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
|
|
this:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], 0.6)
|
|
GameTooltip:Hide()
|
|
end)
|
|
MainFrame.repairItemBtn = repairItemBtn
|
|
|
|
-- Events
|
|
MainFrame:EnableMouseWheel(true)
|
|
MainFrame:SetScript("OnMouseWheel", function()
|
|
local numItems = (CurrentTab == 1) and GetMerchantNumItems() or GetNumBuybackItems()
|
|
local totalPages = math.max(1, math.ceil(numItems / ITEMS_PER_PAGE))
|
|
if arg1 > 0 then
|
|
if CurrentPage > 1 then
|
|
CurrentPage = CurrentPage - 1
|
|
MUI:Update()
|
|
end
|
|
elseif arg1 < 0 then
|
|
if CurrentPage < totalPages then
|
|
CurrentPage = CurrentPage + 1
|
|
MUI:Update()
|
|
end
|
|
end
|
|
end)
|
|
|
|
MainFrame:SetScript("OnHide", function() pcall(CloseMerchant) end)
|
|
MainFrame:SetScript("OnEvent", function()
|
|
if event == "MERCHANT_SHOW" then
|
|
if SFramesDB and SFramesDB.enableMerchant == false then return end
|
|
CurrentTab = 1
|
|
CurrentPage = 1
|
|
MainFrame:Show()
|
|
MUI:Update()
|
|
elseif event == "MERCHANT_UPDATE" then
|
|
if MainFrame:IsVisible() then MUI:Update() end
|
|
elseif event == "MERCHANT_CLOSED" then
|
|
MainFrame:Hide()
|
|
end
|
|
end)
|
|
|
|
MainFrame:RegisterEvent("MERCHANT_SHOW")
|
|
MainFrame:RegisterEvent("MERCHANT_UPDATE")
|
|
MainFrame:RegisterEvent("MERCHANT_CLOSED")
|
|
MainFrame:Hide()
|
|
|
|
if MerchantFrame then
|
|
MerchantFrame:UnregisterEvent("MERCHANT_SHOW")
|
|
end
|
|
tinsert(UISpecialFrames, "SFramesMerchantFrame")
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Bootstrap
|
|
--------------------------------------------------------------------------------
|
|
local f = CreateFrame("Frame")
|
|
f:RegisterEvent("PLAYER_LOGIN")
|
|
f:SetScript("OnEvent", function()
|
|
if event == "PLAYER_LOGIN" then
|
|
if SFramesDB and SFramesDB.enableMerchant == nil then
|
|
SFramesDB.enableMerchant = true
|
|
end
|
|
if SFramesDB and SFramesDB.enableMerchant ~= false then
|
|
MUI:Initialize()
|
|
end
|
|
end
|
|
end)
|