1023 lines
36 KiB
Lua
1023 lines
36 KiB
Lua
--------------------------------------------------------------------------------
|
||
-- Nanami-UI: Loot Display (拾取界面 + 已拾取提示)
|
||
--------------------------------------------------------------------------------
|
||
|
||
SFrames = SFrames or {}
|
||
SFrames.LootDisplay = SFrames.LootDisplay or {}
|
||
|
||
local LD = SFrames.LootDisplay
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Constants
|
||
--------------------------------------------------------------------------------
|
||
local ROW_HEIGHT = 32
|
||
local ROW_WIDTH = 180
|
||
local ROW_GAP = 2
|
||
local ICON_SIZE = 26
|
||
local TITLE_HEIGHT = 22
|
||
|
||
local ALERT_WIDTH = 240
|
||
local ALERT_HEIGHT = 32
|
||
local ALERT_GAP = 3
|
||
local ALERT_ICON = 24
|
||
local ALERT_FADE_DUR = 0.6
|
||
local ALERT_FLOAT = 22
|
||
local ALERT_HOLD = 3.5
|
||
local ALERT_STAGGER = 0.25
|
||
local MAX_ALERTS = 10
|
||
|
||
local QUALITY_COLORS = {
|
||
[0] = { 0.62, 0.62, 0.62 },
|
||
[1] = { 0.92, 0.92, 0.88 },
|
||
[2] = { 0.12, 1.00, 0.00 },
|
||
[3] = { 0.00, 0.44, 0.87 },
|
||
[4] = { 0.64, 0.21, 0.93 },
|
||
[5] = { 1.00, 0.50, 0.00 },
|
||
[6] = { 0.90, 0.80, 0.50 },
|
||
}
|
||
|
||
-- Shared rounded backdrop template (matches rest of Nanami-UI)
|
||
local ROUND_BACKDROP = {
|
||
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 },
|
||
}
|
||
|
||
local ROUND_BACKDROP_SMALL = {
|
||
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 },
|
||
}
|
||
|
||
local ROUND_BACKDROP_SHADOW = {
|
||
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 },
|
||
}
|
||
|
||
local ICON_BACKDROP = {
|
||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||
tile = true, tileSize = 16, edgeSize = 10,
|
||
insets = { left = 2, right = 2, top = 2, bottom = 2 },
|
||
}
|
||
|
||
local ITEMS_PER_PAGE = 4
|
||
local PAGE_BAR_H = 20
|
||
|
||
local lootRows = {}
|
||
local activeAlerts = {}
|
||
local alertAnchor = nil
|
||
local alertPool = {}
|
||
|
||
local origLootFrameUpdate = nil
|
||
local ShowLootPage
|
||
local HideBagFullWarning
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Helpers
|
||
--------------------------------------------------------------------------------
|
||
local function T()
|
||
return SFrames.ActiveTheme or {}
|
||
end
|
||
|
||
local function Font()
|
||
return (SFrames.GetFont and SFrames:GetFont()) or "Fonts\\ARIALN.TTF"
|
||
end
|
||
|
||
local function GetDB()
|
||
if not SFramesDB then SFramesDB = {} end
|
||
if type(SFramesDB.lootDisplay) ~= "table" then
|
||
SFramesDB.lootDisplay = {
|
||
enable = true,
|
||
alertEnable = true,
|
||
alertFadeDelay = ALERT_HOLD,
|
||
scale = 1.0,
|
||
followCursor = false,
|
||
}
|
||
end
|
||
if SFramesDB.lootDisplay.followCursor == nil then
|
||
SFramesDB.lootDisplay.followCursor = false
|
||
end
|
||
return SFramesDB.lootDisplay
|
||
end
|
||
|
||
local function QColor(quality)
|
||
local q = tonumber(quality) or 1
|
||
local c = QUALITY_COLORS[q]
|
||
if c then return c[1], c[2], c[3] end
|
||
return 0.92, 0.92, 0.88
|
||
end
|
||
|
||
local function ColorHex(r, g, b)
|
||
return string.format("%02x%02x%02x", r * 255, g * 255, b * 255)
|
||
end
|
||
|
||
local function GetItemTexture(itemIdOrLink)
|
||
if not itemIdOrLink then return nil end
|
||
local a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 = GetItemInfo(itemIdOrLink)
|
||
if a10 and type(a10) == "string" then return a10 end
|
||
if a9 and type(a9) == "string" and string.find(a9, "Interface") then return a9 end
|
||
if a8 and type(a8) == "string" and string.find(a8, "Interface") then return a8 end
|
||
return nil
|
||
end
|
||
|
||
local function ParseItemLink(link)
|
||
if not link then return nil end
|
||
local _, _, colorHex, itemId, itemName = string.find(link, "|c(%x+)|Hitem:(%d+).-|h%[(.-)%]|h|r")
|
||
if not itemName then return nil end
|
||
local id = tonumber(itemId) or 0
|
||
local _, _, quality = GetItemInfo(id)
|
||
return itemName, quality or 1, id
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- ▸ LOOT FRAME (拾取窗口)
|
||
--------------------------------------------------------------------------------
|
||
local lootFrame = nil
|
||
|
||
local function CreateLootFrame()
|
||
if lootFrame then return lootFrame end
|
||
|
||
local th = T()
|
||
local bg = th.panelBg or { 0.06, 0.05, 0.09, 0.95 }
|
||
local bd = th.panelBorder or { 0.30, 0.25, 0.42, 0.90 }
|
||
local acc = th.accent or { 1, 0.5, 0.8, 0.98 }
|
||
|
||
lootFrame = CreateFrame("Frame", "NanamiLootFrame", UIParent)
|
||
lootFrame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||
lootFrame:SetFrameLevel(50)
|
||
lootFrame:SetWidth(ROW_WIDTH + 14)
|
||
lootFrame:SetHeight(TITLE_HEIGHT + 3 * (ROW_HEIGHT + ROW_GAP) + 10)
|
||
lootFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 50, -200)
|
||
lootFrame:SetClampedToScreen(true)
|
||
lootFrame:SetMovable(true)
|
||
lootFrame:EnableMouse(false)
|
||
|
||
-- Shadow
|
||
local shadow = CreateFrame("Frame", nil, lootFrame)
|
||
shadow:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", -5, 5)
|
||
shadow:SetPoint("BOTTOMRIGHT", lootFrame, "BOTTOMRIGHT", 5, -5)
|
||
shadow:SetFrameLevel(math.max(lootFrame:GetFrameLevel() - 1, 0))
|
||
shadow:SetBackdrop(ROUND_BACKDROP_SHADOW)
|
||
shadow:SetBackdropColor(0, 0, 0, 0.55)
|
||
shadow:SetBackdropBorderColor(0, 0, 0, 0.40)
|
||
shadow:EnableMouse(false)
|
||
|
||
-- Background blocker: prevents clicks passing through to frames behind the loot window
|
||
local blocker = CreateFrame("Frame", nil, lootFrame)
|
||
blocker:SetAllPoints(lootFrame)
|
||
blocker:SetFrameLevel(lootFrame:GetFrameLevel())
|
||
blocker:EnableMouse(true)
|
||
|
||
-- Main panel (rounded)
|
||
lootFrame:SetBackdrop(ROUND_BACKDROP)
|
||
lootFrame:SetBackdropColor(bg[1], bg[2], bg[3], bg[4] or 0.95)
|
||
lootFrame:SetBackdropBorderColor(bd[1], bd[2], bd[3], bd[4] or 0.90)
|
||
|
||
-- Top accent line
|
||
local acLine = lootFrame:CreateTexture(nil, "ARTWORK")
|
||
acLine:SetTexture("Interface\\Buttons\\WHITE8x8")
|
||
acLine:SetHeight(2)
|
||
acLine:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", 5, -5)
|
||
acLine:SetPoint("TOPRIGHT", lootFrame, "TOPRIGHT", -5, -5)
|
||
acLine:SetVertexColor(acc[1], acc[2], acc[3], 0.65)
|
||
|
||
-- Title bar: handles dragging the entire loot frame
|
||
local titleBar = CreateFrame("Frame", nil, lootFrame)
|
||
titleBar:SetHeight(TITLE_HEIGHT)
|
||
titleBar:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", 0, 0)
|
||
titleBar:SetPoint("TOPRIGHT", lootFrame, "TOPRIGHT", 0, 0)
|
||
titleBar:SetFrameLevel(lootFrame:GetFrameLevel() + 1)
|
||
titleBar:EnableMouse(true)
|
||
titleBar:RegisterForDrag("LeftButton")
|
||
titleBar:SetScript("OnDragStart", function() lootFrame:StartMoving() end)
|
||
titleBar:SetScript("OnDragStop", function() lootFrame:StopMovingOrSizing() end)
|
||
|
||
-- Title text
|
||
local titleFS = titleBar:CreateFontString(nil, "OVERLAY")
|
||
titleFS:SetFont(Font(), 11, "OUTLINE")
|
||
titleFS:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", 10, -8)
|
||
local tc = th.title or { 1, 0.88, 1 }
|
||
titleFS:SetTextColor(tc[1], tc[2], tc[3], 0.95)
|
||
titleFS:SetText("拾取")
|
||
lootFrame._title = titleFS
|
||
|
||
-- Close button
|
||
local closeBtn = CreateFrame("Button", nil, lootFrame)
|
||
closeBtn:SetWidth(18)
|
||
closeBtn:SetHeight(18)
|
||
closeBtn:SetPoint("TOPRIGHT", lootFrame, "TOPRIGHT", -5, -5)
|
||
closeBtn:SetFrameLevel(lootFrame:GetFrameLevel() + 5)
|
||
closeBtn:RegisterForClicks("LeftButtonUp")
|
||
closeBtn:SetBackdrop(ROUND_BACKDROP_SMALL)
|
||
local cbg = th.buttonBg or { 0.35, 0.08, 0.12, 0.85 }
|
||
local cbd = th.buttonBorder or { 0.50, 0.18, 0.22, 0.80 }
|
||
closeBtn:SetBackdropColor(cbg[1], cbg[2], cbg[3], cbg[4] or 0.85)
|
||
closeBtn:SetBackdropBorderColor(cbd[1], cbd[2], cbd[3], cbd[4] or 0.80)
|
||
local closeFS = closeBtn:CreateFontString(nil, "OVERLAY")
|
||
closeFS:SetFont(Font(), 10, "OUTLINE")
|
||
closeFS:SetPoint("CENTER", 0, 0)
|
||
closeFS:SetText("×")
|
||
closeFS:SetTextColor(0.9, 0.65, 0.65, 1)
|
||
closeBtn:SetScript("OnClick", function() CloseLoot() end)
|
||
closeBtn:SetScript("OnEnter", function()
|
||
this:SetBackdropColor(0.55, 0.12, 0.15, 0.95)
|
||
this:SetBackdropBorderColor(0.9, 0.30, 0.35, 1)
|
||
closeFS:SetTextColor(1, 1, 1, 1)
|
||
end)
|
||
closeBtn:SetScript("OnLeave", function()
|
||
this:SetBackdropColor(cbg[1], cbg[2], cbg[3], cbg[4] or 0.85)
|
||
this:SetBackdropBorderColor(cbd[1], cbd[2], cbd[3], cbd[4] or 0.80)
|
||
closeFS:SetTextColor(0.9, 0.65, 0.65, 1)
|
||
end)
|
||
|
||
-- Page controls (visible only when > ITEMS_PER_PAGE items)
|
||
local pageBar = CreateFrame("Frame", nil, lootFrame)
|
||
pageBar:SetHeight(PAGE_BAR_H)
|
||
pageBar:SetPoint("BOTTOMLEFT", lootFrame, "BOTTOMLEFT", 7, 4)
|
||
pageBar:SetPoint("BOTTOMRIGHT", lootFrame, "BOTTOMRIGHT", -7, 4)
|
||
pageBar:SetFrameLevel(lootFrame:GetFrameLevel() + 3)
|
||
pageBar:EnableMouse(false)
|
||
pageBar:Hide()
|
||
lootFrame._pageBar = pageBar
|
||
|
||
local pageFS = pageBar:CreateFontString(nil, "OVERLAY")
|
||
pageFS:SetFont(Font(), 9, "OUTLINE")
|
||
pageFS:SetPoint("CENTER", pageBar, "CENTER", 0, 0)
|
||
pageFS:SetTextColor(0.75, 0.75, 0.80, 0.95)
|
||
lootFrame._pageText = pageFS
|
||
|
||
local dim = th.dimText or { 0.55, 0.55, 0.60 }
|
||
|
||
local prevBtn = CreateFrame("Button", nil, pageBar)
|
||
prevBtn:SetWidth(22)
|
||
prevBtn:SetHeight(16)
|
||
prevBtn:SetPoint("RIGHT", pageFS, "LEFT", -8, 0)
|
||
prevBtn:SetFrameLevel(pageBar:GetFrameLevel() + 1)
|
||
prevBtn:RegisterForClicks("LeftButtonUp")
|
||
prevBtn:SetBackdrop(ROUND_BACKDROP_SMALL)
|
||
prevBtn:SetBackdropColor(0.10, 0.09, 0.14, 0.80)
|
||
prevBtn:SetBackdropBorderColor(0.25, 0.22, 0.35, 0.60)
|
||
local prevFS2 = prevBtn:CreateFontString(nil, "OVERLAY")
|
||
prevFS2:SetFont(Font(), 10, "OUTLINE")
|
||
prevFS2:SetPoint("CENTER", 0, 0)
|
||
prevFS2:SetText("<")
|
||
prevFS2:SetTextColor(dim[1], dim[2], dim[3], 0.90)
|
||
prevBtn:SetScript("OnClick", function()
|
||
if lootFrame._page and lootFrame._page > 1 then
|
||
lootFrame._page = lootFrame._page - 1
|
||
ShowLootPage()
|
||
end
|
||
end)
|
||
prevBtn:SetScript("OnEnter", function()
|
||
this:SetBackdropBorderColor(acc[1], acc[2], acc[3], 0.70)
|
||
end)
|
||
prevBtn:SetScript("OnLeave", function()
|
||
this:SetBackdropBorderColor(0.25, 0.22, 0.35, 0.60)
|
||
end)
|
||
lootFrame._prevBtn = prevBtn
|
||
|
||
local nextBtn = CreateFrame("Button", nil, pageBar)
|
||
nextBtn:SetWidth(22)
|
||
nextBtn:SetHeight(16)
|
||
nextBtn:SetPoint("LEFT", pageFS, "RIGHT", 8, 0)
|
||
nextBtn:SetFrameLevel(pageBar:GetFrameLevel() + 1)
|
||
nextBtn:RegisterForClicks("LeftButtonUp")
|
||
nextBtn:SetBackdrop(ROUND_BACKDROP_SMALL)
|
||
nextBtn:SetBackdropColor(0.10, 0.09, 0.14, 0.80)
|
||
nextBtn:SetBackdropBorderColor(0.25, 0.22, 0.35, 0.60)
|
||
local nextFS2 = nextBtn:CreateFontString(nil, "OVERLAY")
|
||
nextFS2:SetFont(Font(), 10, "OUTLINE")
|
||
nextFS2:SetPoint("CENTER", 0, 0)
|
||
nextFS2:SetText(">")
|
||
nextFS2:SetTextColor(dim[1], dim[2], dim[3], 0.90)
|
||
nextBtn:SetScript("OnClick", function()
|
||
if lootFrame._page and lootFrame._totalPages and lootFrame._page < lootFrame._totalPages then
|
||
lootFrame._page = lootFrame._page + 1
|
||
ShowLootPage()
|
||
end
|
||
end)
|
||
nextBtn:SetScript("OnEnter", function()
|
||
this:SetBackdropBorderColor(acc[1], acc[2], acc[3], 0.70)
|
||
end)
|
||
nextBtn:SetScript("OnLeave", function()
|
||
this:SetBackdropBorderColor(0.25, 0.22, 0.35, 0.60)
|
||
end)
|
||
lootFrame._nextBtn = nextBtn
|
||
|
||
-- Bag-full warning (hidden by default)
|
||
local bagFullFS = lootFrame:CreateFontString(nil, "OVERLAY")
|
||
bagFullFS:SetFont(Font(), 9, "OUTLINE")
|
||
bagFullFS:SetPoint("LEFT", titleFS, "RIGHT", 6, 0)
|
||
bagFullFS:SetTextColor(1.0, 0.30, 0.30, 1.0)
|
||
bagFullFS:Hide()
|
||
lootFrame._bagFullText = bagFullFS
|
||
|
||
-- Escape key closes our loot frame
|
||
table.insert(UISpecialFrames, "NanamiLootFrame")
|
||
|
||
lootFrame:SetScript("OnHide", function()
|
||
if not this._closingLoot then
|
||
CloseLoot()
|
||
end
|
||
end)
|
||
|
||
lootFrame:Hide()
|
||
return lootFrame
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Loot row
|
||
--------------------------------------------------------------------------------
|
||
local function CreateLootRow(parent, index)
|
||
local th = T()
|
||
local slotBg = th.slotBg or { 0.07, 0.06, 0.10, 0.85 }
|
||
local slotBd = th.slotBorder or { 0.18, 0.16, 0.28, 0.60 }
|
||
local hoverBd = th.slotHover or { 0.38, 0.40, 0.90 }
|
||
local acc = th.accent or { 1, 0.5, 0.8 }
|
||
|
||
local row = CreateFrame("Button", "NanamiLootRow" .. index, parent)
|
||
row:SetWidth(ROW_WIDTH)
|
||
row:SetHeight(ROW_HEIGHT)
|
||
row:SetFrameLevel(parent:GetFrameLevel() + 2)
|
||
row:RegisterForClicks("LeftButtonUp")
|
||
|
||
row:SetBackdrop(ROUND_BACKDROP_SMALL)
|
||
row:SetBackdropColor(slotBg[1], slotBg[2], slotBg[3], slotBg[4] or 0.85)
|
||
row:SetBackdropBorderColor(slotBd[1], slotBd[2], slotBd[3], slotBd[4] or 0.60)
|
||
|
||
-- Left quality accent bar
|
||
local qBar = row:CreateTexture(nil, "OVERLAY")
|
||
qBar:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||
qBar:SetWidth(2)
|
||
qBar:SetPoint("TOPLEFT", row, "TOPLEFT", 3, -3)
|
||
qBar:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 3, 3)
|
||
qBar:SetVertexColor(1, 1, 1, 0.6)
|
||
row.qBar = qBar
|
||
|
||
-- Icon frame (rounded border)
|
||
local iconFrame = CreateFrame("Frame", nil, row)
|
||
iconFrame:SetWidth(ICON_SIZE + 4)
|
||
iconFrame:SetHeight(ICON_SIZE + 4)
|
||
iconFrame:SetPoint("LEFT", row, "LEFT", 7, 0)
|
||
iconFrame:SetFrameLevel(row:GetFrameLevel() + 1)
|
||
iconFrame:SetBackdrop(ICON_BACKDROP)
|
||
iconFrame:SetBackdropColor(0, 0, 0, 0.60)
|
||
iconFrame:SetBackdropBorderColor(slotBd[1], slotBd[2], slotBd[3], 0.70)
|
||
iconFrame:EnableMouse(false)
|
||
row.iconFrame = iconFrame
|
||
|
||
local icon = iconFrame:CreateTexture(nil, "ARTWORK")
|
||
icon:SetPoint("TOPLEFT", iconFrame, "TOPLEFT", 2, -2)
|
||
icon:SetPoint("BOTTOMRIGHT", iconFrame, "BOTTOMRIGHT", -2, 2)
|
||
icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
||
row.icon = icon
|
||
|
||
-- Name
|
||
local nameFS = row:CreateFontString(nil, "OVERLAY")
|
||
nameFS:SetFont(Font(), 10, "OUTLINE")
|
||
nameFS:SetPoint("LEFT", iconFrame, "RIGHT", 4, 0)
|
||
nameFS:SetPoint("RIGHT", row, "RIGHT", -6, 0)
|
||
nameFS:SetJustifyH("LEFT")
|
||
row.nameFS = nameFS
|
||
|
||
-- Count (bottom-right of icon)
|
||
local countFS = row:CreateFontString(nil, "OVERLAY")
|
||
countFS:SetFont(Font(), 8, "OUTLINE")
|
||
countFS:SetPoint("BOTTOMRIGHT", iconFrame, "BOTTOMRIGHT", -2, 2)
|
||
countFS:SetJustifyH("RIGHT")
|
||
countFS:SetTextColor(1, 1, 1, 0.95)
|
||
row.countFS = countFS
|
||
|
||
row._slotBg = slotBg
|
||
row._slotBd = slotBd
|
||
row._hoverBd = hoverBd
|
||
row._acc = acc
|
||
row:EnableMouse(false)
|
||
|
||
row:Hide()
|
||
return row
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Bag-full warning helpers
|
||
--------------------------------------------------------------------------------
|
||
local function ShowBagFullWarning()
|
||
if not lootFrame or not lootFrame:IsShown() then return end
|
||
if lootFrame._bagFullText then
|
||
lootFrame._bagFullText:SetText("背包已满")
|
||
lootFrame._bagFullText:Show()
|
||
end
|
||
end
|
||
|
||
HideBagFullWarning = function()
|
||
if lootFrame and lootFrame._bagFullText then
|
||
lootFrame._bagFullText:Hide()
|
||
end
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Show current page
|
||
--------------------------------------------------------------------------------
|
||
ShowLootPage = function()
|
||
if not lootFrame then return end
|
||
|
||
local numItems = lootFrame._numItems or 0
|
||
local page = lootFrame._page or 1
|
||
local totalPages = lootFrame._totalPages or 1
|
||
|
||
local startSlot = (page - 1) * ITEMS_PER_PAGE + 1
|
||
local endSlot = startSlot + ITEMS_PER_PAGE - 1
|
||
if endSlot > numItems then endSlot = numItems end
|
||
local slotsOnPage = endSlot - startSlot + 1
|
||
if slotsOnPage < 0 then slotsOnPage = 0 end
|
||
|
||
while table.getn(lootRows) < ITEMS_PER_PAGE do
|
||
local idx = table.getn(lootRows) + 1
|
||
lootRows[idx] = CreateLootRow(lootFrame, idx)
|
||
end
|
||
|
||
for i = 1, table.getn(lootRows) do lootRows[i]:Hide() end
|
||
for i = 1, ITEMS_PER_PAGE do
|
||
local nb = _G["LootButton" .. i]
|
||
if nb then nb:Hide() end
|
||
end
|
||
|
||
local hasPages = totalPages > 1
|
||
local bottomPad = hasPages and (PAGE_BAR_H + 6) or 6
|
||
local totalH = TITLE_HEIGHT + (slotsOnPage * (ROW_HEIGHT + ROW_GAP)) + bottomPad + 4
|
||
lootFrame:SetHeight(totalH)
|
||
|
||
-- Build visual rows
|
||
for btnIdx = 1, slotsOnPage do
|
||
local slotIdx = startSlot + btnIdx - 1
|
||
local row = lootRows[btnIdx]
|
||
if not row then break end
|
||
|
||
row:ClearAllPoints()
|
||
row:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", 7,
|
||
-(TITLE_HEIGHT + 2 + (btnIdx - 1) * (ROW_HEIGHT + ROW_GAP)))
|
||
row:SetWidth(ROW_WIDTH)
|
||
row.slotIndex = slotIdx
|
||
|
||
local texture, itemName, quantity, quality = GetLootSlotInfo(slotIdx)
|
||
|
||
if texture then
|
||
row.icon:SetTexture(texture)
|
||
local r, g, b = QColor(quality)
|
||
row._qualColor = { r, g, b }
|
||
row.qBar:SetVertexColor(r, g, b, 0.90)
|
||
row.iconFrame:SetBackdropBorderColor(r, g, b, 0.65)
|
||
row:SetBackdropBorderColor(r, g, b, 0.30)
|
||
row:SetBackdropColor(row._slotBg[1], row._slotBg[2], row._slotBg[3], row._slotBg[4] or 0.85)
|
||
row.iconFrame:SetAlpha(1)
|
||
row.nameFS:SetText("|cff" .. ColorHex(r, g, b) .. (itemName or "") .. "|r")
|
||
if quantity and quantity > 1 then
|
||
row.countFS:SetText(tostring(quantity))
|
||
else
|
||
row.countFS:SetText("")
|
||
end
|
||
else
|
||
row._qualColor = nil
|
||
row.icon:SetTexture("")
|
||
row.iconFrame:SetAlpha(0.25)
|
||
row.qBar:SetVertexColor(0.3, 0.3, 0.3, 0.30)
|
||
row.nameFS:SetText("")
|
||
row.countFS:SetText("")
|
||
row:SetBackdropColor(0.04, 0.04, 0.06, 0.40)
|
||
row:SetBackdropBorderColor(0.12, 0.12, 0.18, 0.25)
|
||
row.iconFrame:SetBackdropBorderColor(0.15, 0.15, 0.20, 0.30)
|
||
end
|
||
|
||
row:Show()
|
||
end
|
||
|
||
-- Let the ORIGINAL Blizzard LootFrame_Update run so that native
|
||
-- LootButton1-4 get their IDs, slot data, and OnClick set up
|
||
-- through the trusted native code path (required for LootSlot).
|
||
if LootFrame then
|
||
LootFrame.page = page
|
||
if not LootFrame:IsShown() then LootFrame:Show() end
|
||
end
|
||
if origLootFrameUpdate then origLootFrameUpdate() end
|
||
|
||
-- Now reposition the native buttons on top of our visual rows
|
||
for btnIdx = 1, ITEMS_PER_PAGE do
|
||
local nb = _G["LootButton" .. btnIdx]
|
||
local row = lootRows[btnIdx]
|
||
if nb and row and row:IsShown() and row._qualColor then
|
||
nb:ClearAllPoints()
|
||
nb:SetPoint("TOPLEFT", row, "TOPLEFT", 0, 0)
|
||
nb:SetPoint("BOTTOMRIGHT", row, "BOTTOMRIGHT", 0, 0)
|
||
nb:SetFrameStrata("FULLSCREEN_DIALOG")
|
||
nb:SetFrameLevel(row:GetFrameLevel() + 10)
|
||
nb:SetAlpha(0)
|
||
nb:EnableMouse(true)
|
||
nb:Show()
|
||
|
||
nb._nanamiRow = row
|
||
nb:SetScript("OnEnter", function()
|
||
local slot = this:GetID()
|
||
if slot then
|
||
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
||
GameTooltip:SetLootItem(slot)
|
||
if CursorUpdate then CursorUpdate() end
|
||
end
|
||
local r2 = this._nanamiRow
|
||
if r2 and r2._qualColor then
|
||
local qc = r2._qualColor
|
||
r2:SetBackdropBorderColor(qc[1], qc[2], qc[3], 0.70)
|
||
r2:SetBackdropColor(qc[1]*0.15, qc[2]*0.15, qc[3]*0.15, 0.90)
|
||
end
|
||
end)
|
||
nb:SetScript("OnLeave", function()
|
||
GameTooltip:Hide()
|
||
local r2 = this._nanamiRow
|
||
if r2 then
|
||
if r2._qualColor then
|
||
local qc = r2._qualColor
|
||
r2:SetBackdropBorderColor(qc[1], qc[2], qc[3], 0.30)
|
||
else
|
||
r2:SetBackdropBorderColor(r2._slotBd[1], r2._slotBd[2],
|
||
r2._slotBd[3], r2._slotBd[4] or 0.60)
|
||
end
|
||
r2:SetBackdropColor(r2._slotBg[1], r2._slotBg[2],
|
||
r2._slotBg[3], r2._slotBg[4] or 0.85)
|
||
end
|
||
end)
|
||
else
|
||
if nb then nb:Hide() end
|
||
end
|
||
end
|
||
|
||
if hasPages then
|
||
lootFrame._pageText:SetText(page .. "/" .. totalPages)
|
||
lootFrame._pageBar:Show()
|
||
else
|
||
lootFrame._pageBar:Hide()
|
||
end
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Update loot frame (direct slot mapping, no compaction)
|
||
--------------------------------------------------------------------------------
|
||
local function UpdateLootFrame()
|
||
local db = GetDB()
|
||
if not db.enable then return end
|
||
|
||
local numItems = GetNumLootItems()
|
||
if not numItems or numItems == 0 then
|
||
if lootFrame then lootFrame:Hide() end
|
||
return
|
||
end
|
||
|
||
CreateLootFrame()
|
||
|
||
lootFrame._numItems = numItems
|
||
lootFrame._totalPages = math.ceil(numItems / ITEMS_PER_PAGE)
|
||
|
||
if not lootFrame._page or lootFrame._page > lootFrame._totalPages then
|
||
lootFrame._page = 1
|
||
end
|
||
|
||
lootFrame:SetWidth(ROW_WIDTH + 14)
|
||
lootFrame:SetScale(db.scale or 1.0)
|
||
|
||
ShowLootPage()
|
||
|
||
if db.followCursor then
|
||
-- 跟随鼠标:每次打开都定位到鼠标附近
|
||
local cx, cy = GetCursorPosition()
|
||
local uiS = UIParent:GetEffectiveScale()
|
||
lootFrame:ClearAllPoints()
|
||
lootFrame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", cx / uiS - 30, cy / uiS + 16)
|
||
else
|
||
-- 固定位置:使用保存的位置或默认位置
|
||
if not lootFrame._posApplied then
|
||
local hasSaved = false
|
||
if SFrames.Movers and SFrames.Movers.ApplyPosition then
|
||
hasSaved = SFrames.Movers:ApplyPosition("LootFrame", lootFrame,
|
||
"TOPLEFT", "UIParent", "TOPLEFT", 50, -200)
|
||
end
|
||
if hasSaved then
|
||
lootFrame._posApplied = true
|
||
end
|
||
end
|
||
if not lootFrame._posApplied then
|
||
local cx, cy = GetCursorPosition()
|
||
local uiS = UIParent:GetEffectiveScale()
|
||
lootFrame:ClearAllPoints()
|
||
lootFrame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", cx / uiS - 30, cy / uiS + 16)
|
||
end
|
||
end
|
||
|
||
lootFrame:Show()
|
||
end
|
||
|
||
local function CloseLootFrame()
|
||
if lootFrame then
|
||
lootFrame._closingLoot = true
|
||
lootFrame:Hide()
|
||
lootFrame._closingLoot = nil
|
||
end
|
||
for i = 1, ITEMS_PER_PAGE do
|
||
local nb = _G["LootButton" .. i]
|
||
if nb then nb:Hide() end
|
||
end
|
||
for i = 1, table.getn(lootRows) do lootRows[i]:Hide() end
|
||
HideBagFullWarning()
|
||
if LootFrame then LootFrame:Hide() end
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- ▸ LOOT ALERTS (已拾取提示)
|
||
--------------------------------------------------------------------------------
|
||
local function CreateAlertAnchor()
|
||
if alertAnchor then return alertAnchor end
|
||
|
||
alertAnchor = CreateFrame("Frame", "NanamiLootAlertAnchor", UIParent)
|
||
alertAnchor:SetWidth(ALERT_WIDTH)
|
||
alertAnchor:SetHeight(ALERT_HEIGHT)
|
||
alertAnchor:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", 40, 340)
|
||
alertAnchor:EnableMouse(false)
|
||
|
||
if SFrames.Movers and SFrames.Movers.ApplyPosition then
|
||
SFrames.Movers:ApplyPosition("LootAlert", alertAnchor,
|
||
"BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 40, 340)
|
||
end
|
||
return alertAnchor
|
||
end
|
||
|
||
local function CreateAlertFrame()
|
||
local th = T()
|
||
local idx = table.getn(alertPool) + 1
|
||
local bg = th.panelBg or { 0.06, 0.05, 0.09, 0.92 }
|
||
local bd = th.panelBorder or { 0.30, 0.25, 0.42, 0.80 }
|
||
|
||
local f = CreateFrame("Frame", "NanamiLootAlert" .. idx, UIParent)
|
||
f:SetFrameStrata("HIGH")
|
||
f:SetFrameLevel(20)
|
||
f:SetWidth(ALERT_WIDTH)
|
||
f:SetHeight(ALERT_HEIGHT)
|
||
|
||
-- Rounded backdrop matching UI theme
|
||
f:SetBackdrop(ROUND_BACKDROP_SMALL)
|
||
f:SetBackdropColor(bg[1], bg[2], bg[3], bg[4] or 0.92)
|
||
f:SetBackdropBorderColor(bd[1], bd[2], bd[3], bd[4] or 0.80)
|
||
|
||
-- Left quality accent bar
|
||
local qBar = f:CreateTexture(nil, "OVERLAY")
|
||
qBar:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||
qBar:SetWidth(2)
|
||
qBar:SetPoint("TOPLEFT", f, "TOPLEFT", 3, -3)
|
||
qBar:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 3, 3)
|
||
qBar:SetVertexColor(1, 1, 1, 0.7)
|
||
f.qBar = qBar
|
||
|
||
-- Icon with rounded border
|
||
local iconFrame = CreateFrame("Frame", nil, f)
|
||
iconFrame:SetWidth(ALERT_ICON + 4)
|
||
iconFrame:SetHeight(ALERT_ICON + 4)
|
||
iconFrame:SetPoint("LEFT", f, "LEFT", 7, 0)
|
||
iconFrame:SetFrameLevel(f:GetFrameLevel() + 1)
|
||
iconFrame:SetBackdrop(ICON_BACKDROP)
|
||
iconFrame:SetBackdropColor(0, 0, 0, 0.55)
|
||
iconFrame:SetBackdropBorderColor(0.25, 0.22, 0.30, 0.6)
|
||
f.iconFrame = iconFrame
|
||
|
||
local icon = iconFrame:CreateTexture(nil, "ARTWORK")
|
||
icon:SetPoint("TOPLEFT", iconFrame, "TOPLEFT", 2, -2)
|
||
icon:SetPoint("BOTTOMRIGHT", iconFrame, "BOTTOMRIGHT", -2, 2)
|
||
icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
||
f.icon = icon
|
||
|
||
-- Name
|
||
local nameFS = f:CreateFontString(nil, "OVERLAY")
|
||
nameFS:SetFont(Font(), 10, "OUTLINE")
|
||
nameFS:SetPoint("LEFT", iconFrame, "RIGHT", 5, 0)
|
||
nameFS:SetPoint("RIGHT", f, "RIGHT", -30, 0)
|
||
nameFS:SetJustifyH("LEFT")
|
||
f.nameFS = nameFS
|
||
|
||
-- Count (right side)
|
||
local countFS = f:CreateFontString(nil, "OVERLAY")
|
||
countFS:SetFont(Font(), 10, "OUTLINE")
|
||
countFS:SetPoint("RIGHT", f, "RIGHT", -6, 0)
|
||
countFS:SetJustifyH("RIGHT")
|
||
local dim = th.dimText or { 0.55, 0.55, 0.60 }
|
||
countFS:SetTextColor(dim[1], dim[2], dim[3], 0.95)
|
||
f.countFS = countFS
|
||
|
||
f:Hide()
|
||
table.insert(alertPool, f)
|
||
return f
|
||
end
|
||
|
||
local function GetAlertFrame()
|
||
for i = 1, table.getn(alertPool) do
|
||
if not alertPool[i]._inUse then return alertPool[i] end
|
||
end
|
||
return CreateAlertFrame()
|
||
end
|
||
|
||
local function LayoutAlerts()
|
||
CreateAlertAnchor()
|
||
for i = 1, table.getn(activeAlerts) do
|
||
local af = activeAlerts[i]
|
||
if af._fadeState ~= "fading" then
|
||
af:ClearAllPoints()
|
||
af:SetPoint("BOTTOMLEFT", alertAnchor, "BOTTOMLEFT", 0, (i - 1) * (ALERT_HEIGHT + ALERT_GAP))
|
||
end
|
||
end
|
||
end
|
||
|
||
local function RemoveAlert(frame)
|
||
frame._inUse = false
|
||
frame:SetAlpha(0)
|
||
frame:Hide()
|
||
frame:SetScript("OnUpdate", nil)
|
||
local newActive = {}
|
||
for i = 1, table.getn(activeAlerts) do
|
||
if activeAlerts[i] ~= frame then
|
||
table.insert(newActive, activeAlerts[i])
|
||
end
|
||
end
|
||
activeAlerts = newActive
|
||
LayoutAlerts()
|
||
end
|
||
|
||
local function StartAlertFade(frame, delay)
|
||
frame._fadeState = "waiting"
|
||
frame._fadeElapsed = 0
|
||
frame._fadeDelay = delay
|
||
|
||
frame:SetScript("OnUpdate", function()
|
||
this._fadeElapsed = (this._fadeElapsed or 0) + arg1
|
||
|
||
if this._fadeState == "waiting" then
|
||
if this._fadeElapsed >= this._fadeDelay then
|
||
this._fadeState = "fading"
|
||
this._fadeElapsed = 0
|
||
this._baseY = 0
|
||
for idx = 1, table.getn(activeAlerts) do
|
||
if activeAlerts[idx] == this then
|
||
this._baseY = (idx - 1) * (ALERT_HEIGHT + ALERT_GAP)
|
||
break
|
||
end
|
||
end
|
||
end
|
||
elseif this._fadeState == "fading" then
|
||
local p = this._fadeElapsed / ALERT_FADE_DUR
|
||
if p >= 1 then
|
||
RemoveAlert(this)
|
||
else
|
||
this:SetAlpha(1 - p)
|
||
this:ClearAllPoints()
|
||
this:SetPoint("BOTTOMLEFT", alertAnchor, "BOTTOMLEFT",
|
||
0, this._baseY + p * ALERT_FLOAT)
|
||
end
|
||
end
|
||
end)
|
||
end
|
||
|
||
local function PruneAlerts()
|
||
while table.getn(activeAlerts) > MAX_ALERTS do
|
||
RemoveAlert(activeAlerts[1])
|
||
end
|
||
end
|
||
|
||
local function ShowLootAlert(texture, name, quality, quantity, link)
|
||
local db = GetDB()
|
||
if not db.alertEnable then return end
|
||
|
||
for i = 1, table.getn(activeAlerts) do
|
||
local af = activeAlerts[i]
|
||
if af._itemName == name and af._fadeState == "waiting" then
|
||
af._quantity = (af._quantity or 1) + (quantity or 1)
|
||
if af._quantity > 1 then
|
||
af.countFS:SetText("x" .. af._quantity)
|
||
end
|
||
af._fadeElapsed = 0
|
||
return
|
||
end
|
||
end
|
||
|
||
PruneAlerts()
|
||
CreateAlertAnchor()
|
||
|
||
local f = GetAlertFrame()
|
||
f._inUse = true
|
||
f._itemName = name
|
||
f._quantity = quantity or 1
|
||
f._link = link
|
||
|
||
-- Set icon texture
|
||
local iconTex = texture or "Interface\\Icons\\INV_Misc_QuestionMark"
|
||
f.icon:SetTexture(iconTex)
|
||
|
||
local r, g, b = QColor(quality)
|
||
f.qBar:SetVertexColor(r, g, b, 0.90)
|
||
f.iconFrame:SetBackdropBorderColor(r, g, b, 0.60)
|
||
|
||
f.nameFS:SetText("|cff" .. ColorHex(r, g, b) .. (name or "???") .. "|r")
|
||
|
||
if f._quantity > 1 then
|
||
f.countFS:SetText("x" .. f._quantity)
|
||
else
|
||
f.countFS:SetText("")
|
||
end
|
||
|
||
-- Re-apply theme backdrop colors (pool reuse)
|
||
local th = T()
|
||
local bg = th.panelBg or { 0.06, 0.05, 0.09, 0.92 }
|
||
local bd = th.panelBorder or { 0.30, 0.25, 0.42, 0.80 }
|
||
f:SetBackdropColor(bg[1], bg[2], bg[3], bg[4] or 0.92)
|
||
f:SetBackdropBorderColor(bd[1], bd[2], bd[3], bd[4] or 0.80)
|
||
|
||
f:SetAlpha(1)
|
||
f:Show()
|
||
|
||
table.insert(activeAlerts, f)
|
||
LayoutAlerts()
|
||
|
||
local hold = db.alertFadeDelay or ALERT_HOLD
|
||
local stagger = table.getn(activeAlerts) * ALERT_STAGGER
|
||
StartAlertFade(f, hold + stagger)
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Parse CHAT_MSG_LOOT
|
||
--------------------------------------------------------------------------------
|
||
local function ParseLootMessage(msg)
|
||
if not msg then return end
|
||
|
||
local _, _, link, countStr = string.find(msg, "(|c%x+|Hitem.-%[.-%]|h|r)x(%d+)")
|
||
if not link then
|
||
_, _, link = string.find(msg, "(|c%x+|Hitem.-%[.-%]|h|r)")
|
||
end
|
||
|
||
if link then
|
||
local itemName, quality, itemId = ParseItemLink(link)
|
||
if itemName then
|
||
local count = tonumber(countStr) or 1
|
||
-- Try full link first (most reliable), then itemId, then itemString
|
||
local tex = GetItemTexture(link)
|
||
if not tex and itemId and itemId > 0 then
|
||
tex = GetItemTexture(itemId)
|
||
end
|
||
if not tex and itemId and itemId > 0 then
|
||
tex = GetItemTexture("item:" .. itemId .. ":0:0:0")
|
||
end
|
||
ShowLootAlert(tex, itemName, quality, count, link)
|
||
end
|
||
return
|
||
end
|
||
|
||
-- Money
|
||
local isMoney = false
|
||
if string.find(msg, "铜") or string.find(msg, "银") or string.find(msg, "金")
|
||
or string.find(msg, "[Cc]opper") or string.find(msg, "[Ss]ilver") or string.find(msg, "[Gg]old") then
|
||
if string.find(msg, "拾取") or string.find(msg, "获得") or string.find(msg, "loot") or string.find(msg, "receive") then
|
||
isMoney = true
|
||
end
|
||
end
|
||
|
||
if isMoney then
|
||
local cleanMsg = string.gsub(msg, "|c%x+", "")
|
||
cleanMsg = string.gsub(cleanMsg, "|r", "")
|
||
local _, _, moneyPart = string.find(cleanMsg, "[::]%s*(.+)$")
|
||
if not moneyPart then
|
||
_, _, moneyPart = string.find(cleanMsg, "loot%s+(.+)$")
|
||
end
|
||
if not moneyPart then
|
||
_, _, moneyPart = string.find(cleanMsg, "获得了?%s*(.+)$")
|
||
end
|
||
if moneyPart then
|
||
moneyPart = string.gsub(moneyPart, "[%.。]+$", "")
|
||
ShowLootAlert("Interface\\Icons\\INV_Misc_Coin_01", moneyPart, 1, 1, nil)
|
||
end
|
||
end
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Initialize
|
||
--------------------------------------------------------------------------------
|
||
function LD:Initialize()
|
||
local db = GetDB()
|
||
if not db.enable then return end
|
||
|
||
CreateLootFrame()
|
||
CreateAlertAnchor()
|
||
|
||
if SFrames.Movers and SFrames.Movers.ApplyPosition then
|
||
local applied = SFrames.Movers:ApplyPosition("LootFrame", lootFrame,
|
||
"TOPLEFT", "UIParent", "TOPLEFT", 50, -200)
|
||
if applied then lootFrame._posApplied = true end
|
||
|
||
SFrames.Movers:ApplyPosition("LootAlert", alertAnchor,
|
||
"BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 40, 340)
|
||
end
|
||
|
||
if SFrames.Movers and SFrames.Movers.RegisterMover then
|
||
SFrames.Movers:RegisterMover("LootFrame", lootFrame, "拾取窗口",
|
||
"TOPLEFT", "UIParent", "TOPLEFT", 50, -200)
|
||
SFrames.Movers:RegisterMover("LootAlert", alertAnchor, "已拾取提示",
|
||
"BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 40, 340)
|
||
end
|
||
|
||
SFrames:RegisterEvent("LOOT_OPENED", function()
|
||
if GetDB().enable then
|
||
if lootFrame then lootFrame._page = 1 end
|
||
HideBagFullWarning()
|
||
UpdateLootFrame()
|
||
end
|
||
end)
|
||
|
||
SFrames:RegisterEvent("LOOT_SLOT_CLEARED", function()
|
||
if GetDB().enable and lootFrame and lootFrame:IsShown() then
|
||
HideBagFullWarning()
|
||
UpdateLootFrame()
|
||
end
|
||
end)
|
||
|
||
SFrames:RegisterEvent("UI_ERROR_MESSAGE", function()
|
||
if lootFrame and lootFrame:IsShown() then
|
||
local msg = arg1
|
||
if msg == ERR_INV_FULL
|
||
or (INVENTORY_FULL and msg == INVENTORY_FULL)
|
||
or (msg and (string.find(msg, "背包已满")
|
||
or string.find(msg, "Inventory is full"))) then
|
||
ShowBagFullWarning()
|
||
end
|
||
end
|
||
end)
|
||
|
||
SFrames:RegisterEvent("LOOT_CLOSED", function()
|
||
CloseLootFrame()
|
||
end)
|
||
|
||
SFrames:RegisterEvent("LOOT_BIND_CONFIRM", function()
|
||
local slot = arg1
|
||
if slot then ConfirmLootSlot(slot) end
|
||
end)
|
||
|
||
SFrames:RegisterEvent("CHAT_MSG_LOOT", function()
|
||
local playerName = UnitName("player")
|
||
if not playerName then return end
|
||
local msg = arg1 or ""
|
||
if string.find(msg, playerName) or string.find(msg, "你获得") or string.find(msg, "你拾取") or string.find(msg, "You receive") then
|
||
ParseLootMessage(msg)
|
||
end
|
||
end)
|
||
|
||
-- Save the original LootFrame_Update so ShowLootPage can call it
|
||
-- to let native code set up LootButton IDs and OnClick handlers.
|
||
origLootFrameUpdate = LootFrame_Update
|
||
|
||
if LootFrame then
|
||
-- Prevent the XML-defined OnHide from calling CloseLoot()
|
||
LootFrame:SetScript("OnHide", function() end)
|
||
|
||
-- Keep LootFrame shown but invisible while our UI is active
|
||
local origShow = LootFrame.Show
|
||
LootFrame.Show = function(self)
|
||
origShow(self)
|
||
self:SetAlpha(0)
|
||
self:EnableMouse(false)
|
||
end
|
||
|
||
-- Block native LootFrame from hiding while we are looting
|
||
local origHide = LootFrame.Hide
|
||
LootFrame.Hide = function(self)
|
||
if lootFrame and lootFrame:IsShown() then
|
||
return
|
||
end
|
||
origHide(self)
|
||
end
|
||
end
|
||
|
||
-- After the native LootFrame_Update runs (called by the engine or
|
||
-- by us), reposition native buttons onto our visual rows.
|
||
LootFrame_Update = function()
|
||
if origLootFrameUpdate then origLootFrameUpdate() end
|
||
if not (lootFrame and lootFrame:IsShown()) then return end
|
||
for i = 1, ITEMS_PER_PAGE do
|
||
local nb = _G["LootButton" .. i]
|
||
local row = lootRows[i]
|
||
if nb and row and row:IsShown() and row._qualColor then
|
||
nb:ClearAllPoints()
|
||
nb:SetPoint("TOPLEFT", row, "TOPLEFT", 0, 0)
|
||
nb:SetPoint("BOTTOMRIGHT", row, "BOTTOMRIGHT", 0, 0)
|
||
nb:SetFrameStrata("FULLSCREEN_DIALOG")
|
||
nb:SetFrameLevel(row:GetFrameLevel() + 10)
|
||
nb:SetAlpha(0)
|
||
nb:EnableMouse(true)
|
||
end
|
||
end
|
||
end
|
||
end
|