Files
ShaguTweaks-ClassicAPI/mods/item-colors.lua
T

723 lines
25 KiB
Lua

local _G = ShaguTweaks.GetGlobalEnv()
local T = ShaguTweaks.T
local API = ShaguTweaks.API
local AddBorder = ShaguTweaks.AddBorder
local HookScript = ShaguTweaks.HookScript
local hooksecurefunc = ShaguTweaks.hooksecurefunc
local HookAddonOrVariable = ShaguTweaks.HookAddonOrVariable
local borderModule = ShaguTweaks:register({
title = T["Item Rarity Borders"],
description = T["Show item rarity as colored borders on bags, bank, character, inspect, merchant, quest, mail, trade, craft, tradeskill and loot frames."],
expansions = { ["vanilla"] = true },
category = T["Tooltip & Items"],
enabled = true,
})
local glowModule = ShaguTweaks:register({
title = T["Item Rarity Glows"],
description = T["Show a rarity-colored glow on item buttons independently from Item Rarity Borders."],
expansions = { ["vanilla"] = true },
category = T["Tooltip & Items"],
enabled = nil,
})
local Engine = ShaguTweaks.ItemRarityEngine or {}
ShaguTweaks.ItemRarityEngine = Engine
Engine.borders = Engine.borders or false
Engine.glows = Engine.glows or false
Engine.installed = Engine.installed or false
Engine.glowTextures = Engine.glowTextures or {}
local paperdollSlots = {
[0] = "AmmoSlot", "HeadSlot", "NeckSlot", "ShoulderSlot", "ShirtSlot",
"ChestSlot", "WaistSlot", "LegsSlot", "FeetSlot", "WristSlot", "HandsSlot",
"Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot", "BackSlot",
"MainHandSlot", "SecondaryHandSlot", "RangedSlot", "TabardSlot",
}
local inspectSlots = {
"HeadSlot", "NeckSlot", "ShoulderSlot", "ShirtSlot", "ChestSlot",
"WaistSlot", "LegsSlot", "FeetSlot", "WristSlot", "HandsSlot",
"Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot", "BackSlot",
"MainHandSlot", "SecondaryHandSlot", "RangedSlot", "TabardSlot",
}
-- These option/color tables are immutable and reused across refreshes. Item
-- frames can update very frequently on 1.12, so avoid creating short-lived
-- Lua tables for every visible slot on every event.
local emptyOptions = {}
local defaultColor = { r = .5, g = .5, b = .46 }
local equipmentOptions = {
default = { r = .5, g = .5, b = .5 },
borderMin = 0,
glowMin = 2,
}
local bagOptions = { borderMin = 0, glowMin = 2 }
local bankOptions = { borderMin = 2, glowMin = 2 }
local weaponOptions = {
default = { r = .2, g = .2, b = .2 },
borderMin = 0,
glowMin = 2,
}
local transparentOptions = { borderMin = 2, glowMin = 2, defaultAlpha = 0 }
local mailTradeOptions = {
borderMin = 0, glowMin = 2, defaultAlpha = 0, quest = false, mailTrade = true,
}
local icon14Options = {
borderInset = 2, glowInset = 14, borderMin = 2, glowMin = 2,
defaultAlpha = 0,
}
local icon12Options = {
borderInset = 2, glowInset = 12, borderMin = 2, glowMin = 2,
defaultAlpha = 0,
}
local lootOptions = { borderMin = 1, glowMin = 2, defaultAlpha = 0 }
local function Quality(itemID)
if not itemID then return end
return API.GetItemQualityByID(itemID)
end
-- Cold metadata needs one retry when ClassicAPI's cache reply arrives. Store
-- identities only: the refresh rereads live slots instead of repainting a
-- recycled button with an old item's reply. No polling while waiting.
local pendingItems = {}
local itemEvents, itemRefreshQueued
local function StopItemEventsIfIdle()
if itemEvents and not next(pendingItems) then
itemEvents:UnregisterEvent("GET_ITEM_INFO_RECEIVED")
end
end
local function RetryItemColors()
itemRefreshQueued = nil
if Engine.borders or Engine.glows then
if Engine.RefreshAll then Engine:RefreshAll() end
end
end
local function TrackColdItem(button, itemID, quality)
if not itemID or quality ~= nil or not (Engine.borders or Engine.glows)
or not button.IsVisible or not button:IsVisible() then
if pendingItems[button] then
pendingItems[button] = nil
StopItemEventsIfIdle()
end
return
end
if not API.eventutils or not _G.C_EventUtils
or not _G.C_EventUtils.IsEventValid("GET_ITEM_INFO_RECEIVED") then return end
if not itemEvents then
itemEvents = CreateFrame("Frame")
itemEvents:SetScript("OnEvent", function()
local refresh
for slot, id in pairs(pendingItems) do
if not slot:IsVisible() then
pendingItems[slot] = nil
elseif id == arg1 then
pendingItems[slot] = nil
if arg2 and arg2 ~= 0 then refresh = true end
end
end
StopItemEventsIfIdle()
if refresh and not itemRefreshQueued then
itemRefreshQueued = true
if API.timer then API.Defer(RetryItemColors)
else ShaguTweaks.QueueFunction(RetryItemColors) end
end
end)
end
if not button.stItemCacheHideHook then
button.stItemCacheHideHook = true
HookScript(button, "OnHide", function()
pendingItems[button] = nil
StopItemEventsIfIdle()
end)
end
pendingItems[button] = itemID
itemEvents:RegisterEvent("GET_ITEM_INFO_RECEIVED")
end
local function IsQuestItem(itemID)
if not itemID then return false end
local _, _, _, _, _, classID = API.GetItemInfoInstant(itemID)
return classID == 12
end
local function NormalizeInsets(inset)
if type(inset) == "table" then
local top, right, bottom, left = unpack(inset)
return left and -left or 0, top or 0, right or 0, bottom and -bottom or 0
end
inset = inset or 0
return -inset, inset, inset, -inset
end
local function EnsureGlow(button, inset)
if not button then return end
if button.ShaguTweaks_itemRarityGlow then return button.ShaguTweaks_itemRarityGlow end
local left, top, right, bottom = NormalizeInsets(inset or 14)
local texture = button:CreateTexture(nil, "OVERLAY")
texture:SetTexture("Interface\\Buttons\\UI-ActionButton-Border")
texture:SetBlendMode("ADD")
texture:SetPoint("TOPLEFT", button, "TOPLEFT", left, top)
texture:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", right, bottom)
texture:Hide()
button.ShaguTweaks_itemRarityGlow = texture
table.insert(Engine.glowTextures, texture)
return texture
end
local function SetVisualColor(button, itemID, opts, knownQuality)
if not button then return end
opts = opts or emptyOptions
local default = opts.default or defaultColor
local quality = knownQuality
if quality == nil then quality = Quality(itemID) end
TrackColdItem(button, itemID, quality)
local quest = opts.quest ~= false and IsQuestItem(itemID)
local r, g, b
local hasRarity = false
if quest then
r, g, b = 1, 1, 0
hasRarity = true
elseif quality ~= nil and quality >= (opts.borderMin or 0) then
r, g, b = GetItemQualityColor(quality)
hasRarity = true
end
if Engine.borders then
local border = AddBorder(button, opts.borderInset or 3, default)
if border then
-- Common items must stay white even under a global UI palette.
border.stPreserveRarityColor = opts.mailTrade or nil
if hasRarity then
border:SetBackdropBorderColor(r, g, b, 1)
else
border:SetBackdropBorderColor(default.r, default.g, default.b, opts.defaultAlpha or 1)
end
end
elseif opts.mailTrade and button.ShaguTweaks_border then
button.ShaguTweaks_border.stPreserveRarityColor = nil
button.ShaguTweaks_border:SetBackdropBorderColor(default.r, default.g, default.b, 0)
end
if Engine.glows then
local glow = EnsureGlow(button, opts.glowInset or 14)
if glow then
local glowRarity = quest or (quality ~= nil and quality >= (opts.glowMin or 2))
if glowRarity then
if not quest then r, g, b = GetItemQualityColor(quality) end
glow:SetVertexColor(r, g, b, .7)
glow:Show()
else
glow:Hide()
end
end
end
end
local function ReanchorToIcon(button, icon, borderInset, glowInset)
if not button or not icon then return end
if Engine.borders and button.ShaguTweaks_border then
local border = button.ShaguTweaks_border
border:ClearAllPoints()
border:SetPoint("TOPLEFT", icon, "TOPLEFT", -(borderInset or 2), borderInset or 2)
border:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", borderInset or 2, -(borderInset or 2))
end
if Engine.glows and button.ShaguTweaks_itemRarityGlow then
local glow = button.ShaguTweaks_itemRarityGlow
glow:ClearAllPoints()
glow:SetPoint("TOPLEFT", icon, "TOPLEFT", -(glowInset or 14), glowInset or 14)
glow:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", glowInset or 14, -(glowInset or 14))
end
end
local function ApplyIconButton(button, icon, itemID, opts)
SetVisualColor(button, itemID, opts)
ReanchorToIcon(button, icon, opts and opts.borderInset or 2, opts and opts.glowInset or 14)
end
function Engine:Install()
if self.installed then return end
self.installed = true
local function RefreshPaperdoll()
for slotID, slotName in pairs(paperdollSlots) do
local button = _G["Character" .. slotName]
if button then
SetVisualColor(button, API.GetInventoryItemID("player", slotID), equipmentOptions)
end
end
end
local function RefreshInspect()
for slotID, slotName in pairs(inspectSlots) do
local button = _G["Inspect" .. slotName]
if button then
SetVisualColor(button, API.GetInventoryItemID("target", slotID), equipmentOptions)
end
end
end
local function RefreshBags(bagID)
bagID = bagID and tonumber(bagID) or nil
for frameIndex = 1, 12 do
local frame = _G["ContainerFrame" .. frameIndex]
if frame and frame:IsShown() then
local id = frame:GetID()
if not bagID or id == bagID then
local name = frame:GetName()
for slot = 1, MAX_CONTAINER_ITEMS do
local button = _G[name .. "Item" .. slot]
if button and button:IsShown() then
SetVisualColor(button, API.GetContainerItemID(id, button:GetID()), bagOptions)
end
end
end
end
end
for bag = 0, 3 do
local button = _G["CharacterBag" .. bag .. "Slot"]
if button then
local inventorySlot = bag + 20
SetVisualColor(button, API.GetInventoryItemID("player", inventorySlot), bagOptions)
end
end
end
local function RefreshBank()
for slot = 1, 28 do
local button = _G["BankFrameItem" .. slot]
if button then
SetVisualColor(button, API.GetContainerItemID(-1, slot), bankOptions)
end
end
end
local function RefreshWeapons()
local mainID = API.GetInventoryItemID("player", TempEnchant1:GetID())
local offID = API.GetInventoryItemID("player", TempEnchant2:GetID())
SetVisualColor(TempEnchant1, mainID, weaponOptions)
SetVisualColor(TempEnchant2, offID, weaponOptions)
if TempEnchant1Border then TempEnchant1Border:SetAlpha(0) end
if TempEnchant2Border then TempEnchant2Border:SetAlpha(0) end
end
local function RefreshMerchant()
if not MerchantFrame or not MerchantFrame:IsShown() then return end
if MerchantFrame.selectedTab == 1 then
local page = MerchantFrame.page or 1
local perPage = MERCHANT_ITEMS_PER_PAGE or 10
local startIndex = (page - 1) * perPage + 1
for i = 1, perPage do
local button = _G["MerchantItem" .. i .. "ItemButton"]
if button then
local index = startIndex + i - 1
local itemID
if index <= GetMerchantNumItems() then itemID = API.GetMerchantItemID(index) end
SetVisualColor(button, itemID, transparentOptions)
end
end
local buybackButton = _G["MerchantBuyBackItemItemButton"]
if buybackButton then
local count = GetNumBuybackItems()
local itemID = count > 0 and API.GetBuybackItemID(count) or nil
SetVisualColor(buybackButton, itemID, transparentOptions)
end
else
local perPage = MERCHANT_ITEMS_PER_PAGE or 10
for i = 1, perPage do
local button = _G["MerchantItem" .. i .. "ItemButton"]
if button then
SetVisualColor(button, API.GetBuybackItemID(i), transparentOptions)
end
end
end
end
local function QuestButtonItemID(i)
local choices = GetNumQuestChoices() or 0
local rewards = GetNumQuestRewards() or 0
if i <= choices then return API.GetQuestItemID("choice", i) end
if i <= choices + rewards then return API.GetQuestItemID("reward", i - choices) end
end
local function RefreshQuest()
for i = 1, 4 do
local itemID = QuestButtonItemID(i)
local detail = _G["QuestDetailItem" .. i]
local detailIcon = _G["QuestDetailItem" .. i .. "IconTexture"]
if detail and detailIcon then
ApplyIconButton(detail, detailIcon, itemID, icon14Options)
end
local reward = _G["QuestRewardItem" .. i]
local rewardIcon = _G["QuestRewardItem" .. i .. "IconTexture"]
if reward and rewardIcon then
ApplyIconButton(reward, rewardIcon, itemID, icon14Options)
end
end
end
local function RefreshQuestLog()
if not QuestLogFrame or not QuestLogFrame:IsShown() then return end
for i = 1, 4 do
local itemID = API.GetQuestLogItemID("reward", i)
or API.GetQuestLogItemID("choice", i)
local button = _G["QuestLogItem" .. i]
local icon = _G["QuestLogItem" .. i .. "IconTexture"]
if button and icon then
ApplyIconButton(button, icon, itemID, icon14Options)
end
end
end
local function RefreshMail()
-- The inbox list uses seven 37x37 MailItemXButton frames. Their native
-- slot texture is colored only by read/unread state, so apply our rarity
-- border/glow directly to those item buttons after Blizzard refreshes them.
if InboxFrame then
local page = InboxFrame.pageNum or 1
local numItems = GetInboxNumItems() or 0
for row = 1, 7 do
local button = _G["MailItem" .. row .. "Button"]
local icon = _G["MailItem" .. row .. "ButtonIcon"]
local absolute = (page - 1) * 7 + row
local itemID
if absolute <= numItems then
itemID = API.GetInboxItemID(absolute)
end
if button and icon then
ApplyIconButton(button, icon, itemID, icon12Options)
end
end
end
-- Keep the opened-mail attachment colored as well.
local openButton = _G.OpenMailPackageButton
if openButton then
local mailID = InboxFrame and InboxFrame.openMailID
local itemID = mailID and mailID > 0 and API.GetInboxItemID(mailID) or nil
SetVisualColor(openButton, itemID, transparentOptions)
end
end
local function RefreshSendMail()
local opts = mailTradeOptions
local button = _G.SendMailPackageButton
if button then
local itemID
if type(_G.GetSendMailItemLink) == "function" then
itemID = API.GetItemIDFromLink(_G.GetSendMailItemLink())
end
local quality
if type(_G.GetSendMailItem) == "function" then
local name, texture, count, value = _G.GetSendMailItem()
if name then quality = value end
end
SetVisualColor(button, itemID, opts, quality)
end
-- TurtleMail stores each attachment's source bag and slot on its button.
-- Stop at the first missing button; no dependency on its private constants.
local i = 1
while _G["MailAttachment" .. i] do
button = _G["MailAttachment" .. i]
local item = button.item
local itemID = item and API.GetContainerItemID(item[1], item[2])
SetVisualColor(button, itemID, opts)
i = i + 1
end
end
-- Share one callback across a burst of show/item events. Direct TurtleMail
-- attachment hooks below still color the individual slot immediately.
local sendMailRefreshPending
local function RunSendMailRefresh()
sendMailRefreshPending = nil
if MailFrame and MailFrame:IsShown() then RefreshSendMail() end
end
local function QueueSendMailRefresh()
if sendMailRefreshPending then return end
sendMailRefreshPending = true
if API.timer then
API.Defer(RunSendMailRefresh)
else
ShaguTweaks.QueueFunction(RunSendMailRefresh)
end
end
local function PaintTradeSlot(button, name, link)
local opts = mailTradeOptions
-- The live client returns valid trade links but no GetItemInfo(link)
-- quality. Resolve their IDs through the same capability-aware quality
-- lookup used successfully for mail attachments.
local itemID = name and link and API.GetItemIDFromLink(link)
SetVisualColor(button, itemID, opts)
end
local function RefreshPlayerTradeSlot(index)
local button = _G["TradePlayerItem" .. index .. "ItemButton"]
if button then
local name = GetTradePlayerItemInfo(index)
local link = name and GetTradePlayerItemLink(index)
PaintTradeSlot(button, name, link)
end
end
local function RefreshTargetTradeSlot(index)
local button = _G["TradeRecipientItem" .. index .. "ItemButton"]
if button then
local name = GetTradeTargetItemInfo(index)
local link = name and GetTradeTargetItemLink(index)
PaintTradeSlot(button, name, link)
end
end
local function RefreshTrade()
for i = 1, 7 do
RefreshPlayerTradeSlot(i)
RefreshTargetTradeSlot(i)
end
end
-- TurtleMail replaces SendMailFrame_Update at PLAYER_LOGIN, after our
-- global hook may have been installed. Its buttons always set their normal
-- texture when adding/removing an attachment, so hook that stable boundary.
local function RefreshAttachmentTexture(button, texture)
local opts = mailTradeOptions
local item = texture and button.item
local itemID = item and API.GetContainerItemID(item[1], item[2])
SetVisualColor(button, itemID, opts)
end
local function HookAttachmentTextures()
local i = 1
while _G["MailAttachment" .. i] do
local button = _G["MailAttachment" .. i]
if not button.stRarityTextureHook then
button.stRarityTextureHook = true
hooksecurefunc(button, "SetNormalTexture", RefreshAttachmentTexture)
end
i = i + 1
end
end
local function RefreshTradeSkill()
if not TradeSkillFrame or not TradeSkillFrame:IsShown() then return end
local id = TradeSkillFrame.selectedSkill
if not id then return end
local output = _G.TradeSkillSkillIcon
if output then
SetVisualColor(output, API.GetTradeSkillItemID(id), transparentOptions)
end
local num = GetTradeSkillNumReagents(id) or 0
for i = 1, num do
local button = _G["TradeSkillReagent" .. i]
local icon = _G["TradeSkillReagent" .. i .. "IconTexture"]
if button and icon then
ApplyIconButton(button, icon, API.GetTradeSkillReagentItemID(id, i), icon12Options)
end
end
end
local function RefreshCraft()
if not CraftFrame or not CraftFrame:IsShown() then return end
local id = GetCraftSelectionIndex()
if not id or id <= 0 then return end
local output = _G.CraftIcon
if output then
local name = GetCraftInfo(id)
local link = name and ShaguTweaks.GetItemLinkByName and ShaguTweaks.GetItemLinkByName(name)
local itemID = link and API.GetItemIDFromLink(link)
SetVisualColor(output, itemID, transparentOptions)
end
local num = GetCraftNumReagents(id) or 0
for i = 1, num do
local button = _G["CraftReagent" .. i]
local icon = _G["CraftReagent" .. i .. "IconTexture"]
if button and icon then
ApplyIconButton(button, icon, API.GetCraftReagentItemID(id, i), icon12Options)
end
end
end
local function RefreshLoot()
if not LootFrame or not LootFrame:IsShown() then return end
local numLoot = GetNumLootItems() or 0
local page = LootFrame.page or 1
local perPage = numLoot <= 4 and 4 or 3
local startSlot = (page - 1) * perPage + 1
for buttonIndex = 1, 4 do
local button = _G["LootButton" .. buttonIndex]
local slot = startSlot + buttonIndex - 1
local itemID = slot <= numLoot and API.GetLootSlotItemID(slot) or nil
if button then
SetVisualColor(button, itemID, lootOptions)
end
end
end
self.RefreshAll = function()
RefreshPaperdoll()
if InspectFrame and InspectFrame:IsShown() then RefreshInspect() end
RefreshWeapons()
RefreshBags()
if BankFrame and BankFrame:IsShown() then RefreshBank() end
if MerchantFrame and MerchantFrame:IsShown() then RefreshMerchant() end
if QuestFrame and QuestFrame:IsShown() then RefreshQuest() end
if QuestLogFrame and QuestLogFrame:IsShown() then RefreshQuestLog() end
if TradeFrame and TradeFrame:IsShown() then RefreshTrade() end
if MailFrame and MailFrame:IsShown() then
RefreshMail()
RefreshSendMail()
end
if LootFrame and LootFrame:IsShown() then RefreshLoot() end
if TradeSkillFrame and TradeSkillFrame:IsShown() then RefreshTradeSkill() end
if CraftFrame and CraftFrame:IsShown() then RefreshCraft() end
end
local paperdoll = CreateFrame("Frame", nil, CharacterFrame)
paperdoll:RegisterEvent("UNIT_INVENTORY_CHANGED")
paperdoll:SetScript("OnEvent", function()
if not arg1 or arg1 == "player" then
RefreshPaperdoll()
RefreshWeapons()
end
end)
paperdoll:SetScript("OnShow", RefreshPaperdoll)
HookAddonOrVariable("Blizzard_InspectUI", function()
hooksecurefunc("InspectPaperDollItemSlotButton_Update", RefreshInspect)
if InspectFrame then HookScript(InspectFrame, "OnShow", RefreshInspect) end
end)
local bags = CreateFrame("Frame", nil, ContainerFrame1)
bags:RegisterEvent("BAG_UPDATE")
bags:SetScript("OnEvent", function() RefreshBags(arg1) end)
hooksecurefunc("ContainerFrame_OnShow", function()
RefreshBags(this and this:GetID())
end)
local bank = CreateFrame("Frame", nil, BankFrame)
bank:RegisterEvent("PLAYERBANKSLOTS_CHANGED")
bank:SetScript("OnEvent", RefreshBank)
bank:SetScript("OnShow", RefreshBank)
local merchant = CreateFrame("Frame", nil, MerchantFrame)
merchant:RegisterEvent("MERCHANT_SHOW")
merchant:RegisterEvent("MERCHANT_UPDATE")
merchant:SetScript("OnEvent", RefreshMerchant)
hooksecurefunc("MerchantFrame_Update", RefreshMerchant)
local quest = CreateFrame("Frame", nil, QuestFrame)
quest:RegisterEvent("QUEST_DETAIL")
quest:RegisterEvent("QUEST_COMPLETE")
quest:SetScript("OnEvent", function() ShaguTweaks.QueueFunction(RefreshQuest) end)
quest:SetScript("OnShow", function() ShaguTweaks.QueueFunction(RefreshQuest) end)
if QuestLogFrame then
HookScript(QuestLogFrame, "OnShow", function() ShaguTweaks.QueueFunction(RefreshQuestLog) end)
end
hooksecurefunc("QuestLog_Update", RefreshQuestLog)
if MailFrame then
HookScript(MailFrame, "OnShow", function()
ShaguTweaks.QueueFunction(RefreshMail)
QueueSendMailRefresh()
end)
end
-- These native refresh functions already run for inbox changes, page changes
-- and opening a message. Post-hook them so rarity state always wins after
-- Blizzard has updated the reused mail buttons.
hooksecurefunc("InboxFrame_Update", RefreshMail)
hooksecurefunc("OpenMail_Update", RefreshMail)
HookAttachmentTextures()
HookAddonOrVariable("TurtleMail", HookAttachmentTextures)
hooksecurefunc("SendMailFrame_Update", QueueSendMailRefresh)
if SendMailFrame then
HookScript(SendMailFrame, "OnShow", QueueSendMailRefresh)
end
-- Run after Blizzard updates the corresponding visible column, rather than
-- racing TradeFrame's handler on the same TRADE_* event.
hooksecurefunc("TradeFrame_UpdatePlayerItem", RefreshPlayerTradeSlot)
hooksecurefunc("TradeFrame_UpdateTargetItem", RefreshTargetTradeSlot)
-- TradeFrame_Update already calls both per-slot update functions for all
-- seven slots; hooking it too would repeat the entire rarity pass.
if TradeFrame then
HookScript(TradeFrame, "OnHide", function()
for i = 1, 7 do
PaintTradeSlot(_G["TradePlayerItem" .. i .. "ItemButton"], nil)
PaintTradeSlot(_G["TradeRecipientItem" .. i .. "ItemButton"], nil)
end
end)
end
HookAddonOrVariable("Blizzard_TradeSkillUI", function()
hooksecurefunc("TradeSkillFrame_Update", RefreshTradeSkill)
if TradeSkillFrame then HookScript(TradeSkillFrame, "OnShow", RefreshTradeSkill) end
end)
HookAddonOrVariable("Blizzard_CraftUI", function()
hooksecurefunc("CraftFrame_Update", RefreshCraft)
if CraftFrame then HookScript(CraftFrame, "OnShow", RefreshCraft) end
end)
local loot = CreateFrame("Frame", nil, LootFrame)
loot:RegisterEvent("LOOT_OPENED")
loot:RegisterEvent("LOOT_SLOT_CLEARED")
loot:RegisterEvent("LOOT_CLOSED")
loot:SetScript("OnEvent", function()
if event == "LOOT_CLOSED" then
for i = 1, 4 do
local button = _G["LootButton" .. i]
if button then SetVisualColor(button, nil, lootOptions) end
end
else
ShaguTweaks.QueueFunction(RefreshLoot)
end
end)
hooksecurefunc("LootFrame_Update", RefreshLoot)
self:RefreshAll()
end
borderModule.enable = function(self)
Engine.borders = true
Engine:Install()
if Engine.RefreshAll then Engine:RefreshAll() end
end
glowModule.enable = function(self)
Engine.glows = true
Engine:Install()
if Engine.RefreshAll then Engine:RefreshAll() end
end