forever-addons/EquippedItemLevel/EquippedItemLevel.lua

266 lines
6.9 KiB
Lua
Executable File

local addonName = ...
local EquippedItemLevel = CreateFrame("Frame")
_G[addonName] = EquippedItemLevel
local slots = {
{ id = 1, frame = "CharacterHeadSlot" },
{ id = 2, frame = "CharacterNeckSlot" },
{ id = 3, frame = "CharacterShoulderSlot" },
{ id = 5, frame = "CharacterChestSlot" },
{ id = 6, frame = "CharacterWaistSlot" },
{ id = 7, frame = "CharacterLegsSlot" },
{ id = 8, frame = "CharacterFeetSlot" },
{ id = 9, frame = "CharacterWristSlot" },
{ id = 10, frame = "CharacterHandsSlot" },
{ id = 11, frame = "CharacterFinger0Slot" },
{ id = 12, frame = "CharacterFinger1Slot" },
{ id = 13, frame = "CharacterTrinket0Slot" },
{ id = 14, frame = "CharacterTrinket1Slot" },
{ id = 15, frame = "CharacterBackSlot" },
{ id = 16, frame = "CharacterMainHandSlot" },
{ id = 17, frame = "CharacterSecondaryHandSlot" },
}
local itemLevels = {}
local updateQueued = false
local characterFrameHooked = false
local bagFrameHooks = {}
local equippedLowest, equippedHighest
local function GetCachedItemInfo(itemLink)
if C_Item and C_Item.GetItemInfo then
return C_Item.GetItemInfo(itemLink)
end
if GetItemInfo then
return GetItemInfo(itemLink)
end
return nil
end
local function GetItemLevel(itemLink)
if not itemLink then
return nil
end
if C_Item and C_Item.GetDetailedItemLevelInfo then
local level = C_Item.GetDetailedItemLevelInfo(itemLink)
if level and level > 0 then
return level
end
end
local _, _, _, level = GetCachedItemInfo(itemLink)
return level
end
local function GetGradientColor(level, lowest, highest)
if lowest == highest then
return 0, 1, 0
end
local progress = (level - lowest) / (highest - lowest)
progress = math.max(0, math.min(1, progress))
if progress <= 0.5 then
return 1, progress * 2, 0
end
return 2 - progress * 2, 1, 0
end
local function IsGearItem(itemLink)
if not itemLink then
return false
end
local _, _, _, _, _, _, _, _, equipLocation = GetCachedItemInfo(itemLink)
return equipLocation
and equipLocation ~= ""
and equipLocation ~= "INVTYPE_NON_EQUIP"
and equipLocation ~= "INVTYPE_NON_EQUIP_IGNORE"
and equipLocation ~= "INVTYPE_BAG"
and equipLocation ~= "INVTYPE_TABARD"
end
local function CreateLabel(slot)
local button = _G[slot.frame]
if not button or button.EquippedItemLevelLabel then
return
end
local label = button:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
label:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 2)
label:SetFont("Fonts\\FRIZQT__.TTF", 12, "OUTLINE")
label:SetJustifyH("RIGHT")
label:Hide()
button.EquippedItemLevelLabel = label
end
function EquippedItemLevel:Update()
updateQueued = false
local lowest, highest
for _, slot in ipairs(slots) do
CreateLabel(slot)
local itemLink = GetInventoryItemLink("player", slot.id)
local level = GetItemLevel(itemLink)
itemLevels[slot.id] = level
if level then
lowest = not lowest and level or math.min(lowest, level)
highest = not highest and level or math.max(highest, level)
end
end
equippedLowest, equippedHighest = lowest, highest
for _, slot in ipairs(slots) do
local button = _G[slot.frame]
local label = button and button.EquippedItemLevelLabel
local level = itemLevels[slot.id]
if label and level and lowest and highest then
local red, green, blue = GetGradientColor(level, lowest, highest)
label:SetText(string.format("%.0f", level))
label:SetTextColor(red, green, blue)
label:Show()
elseif label then
label:Hide()
end
end
self:UpdateBagLabels()
end
function EquippedItemLevel:QueueUpdate()
if updateQueued then
return
end
updateQueued = true
C_Timer.After(0.1, function()
EquippedItemLevel:Update()
end)
end
function EquippedItemLevel:HookCharacterFrame()
if characterFrameHooked or not CharacterFrame then
return
end
CharacterFrame:HookScript("OnShow", function()
EquippedItemLevel:QueueUpdate()
end)
characterFrameHooked = true
end
function EquippedItemLevel:UpdateBagButton(button)
if not button or not button.GetBagID then
return
end
local label = button.EquippedItemLevelBagLabel
if not label then
label = button:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
label:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 2)
label:SetFont("Fonts\\FRIZQT__.TTF", 11, "OUTLINE")
label:SetJustifyH("RIGHT")
button.EquippedItemLevelBagLabel = label
end
local bag, slot = button:GetBagID(), button:GetID()
local itemLink = bag and slot and C_Container.GetContainerItemLink(bag, slot)
local level = GetItemLevel(itemLink)
if not level or not IsGearItem(itemLink) or not equippedLowest or not equippedHighest then
label:Hide()
return
end
local red, green, blue = GetGradientColor(level, equippedLowest, equippedHighest)
label:SetText(string.format("%.0f", level))
label:SetTextColor(red, green, blue)
label:Show()
end
function EquippedItemLevel:UpdateContainerFrame(frame)
if not frame then
return
end
if frame.EnumerateValidItems then
for _, button in frame:EnumerateValidItems() do
self:UpdateBagButton(button)
end
elseif frame.Items then
for _, button in ipairs(frame.Items) do
self:UpdateBagButton(button)
end
end
end
function EquippedItemLevel:HookBagFrame(frame)
if not frame or bagFrameHooks[frame] or not frame.Update then
return
end
hooksecurefunc(frame, "Update", function(updatedFrame)
EquippedItemLevel:UpdateContainerFrame(updatedFrame)
end)
bagFrameHooks[frame] = true
end
function EquippedItemLevel:UpdateBagLabels()
local index = 1
local frame = _G["ContainerFrame" .. index]
while frame do
self:HookBagFrame(frame)
self:UpdateContainerFrame(frame)
index = index + 1
frame = _G["ContainerFrame" .. index]
end
if ContainerFrameCombinedBags then
self:HookBagFrame(ContainerFrameCombinedBags)
self:UpdateContainerFrame(ContainerFrameCombinedBags)
end
end
local function AddTooltipItemLevel(tooltip, data)
-- The same data is supplied for normal and comparison tooltips, including
-- comparison panes that do not implement GameTooltip:GetItem().
local itemReference = data and (data.hyperlink or data.id)
if not itemReference or not IsGearItem(itemReference) then
return
end
local level = GetItemLevel(itemReference)
if not level then
return
end
local red, green, blue = GetGradientColor(level, equippedLowest or level, equippedHighest or level)
tooltip:AddDoubleLine("Item level", string.format("%.0f", level), 1, 0.82, 0, red, green, blue)
tooltip:Show()
end
function EquippedItemLevel:OnEvent(event)
if event == "PLAYER_LOGIN" then
TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, AddTooltipItemLevel)
end
self:HookCharacterFrame()
self:QueueUpdate()
end
EquippedItemLevel:RegisterEvent("PLAYER_LOGIN")
EquippedItemLevel:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
EquippedItemLevel:RegisterEvent("GET_ITEM_INFO_RECEIVED")
EquippedItemLevel:RegisterEvent("PLAYER_ENTERING_WORLD")
EquippedItemLevel:RegisterEvent("ADDON_LOADED")
EquippedItemLevel:RegisterEvent("BAG_UPDATE_DELAYED")
EquippedItemLevel:SetScript("OnEvent", EquippedItemLevel.OnEvent)