mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-09-22 15:46:59 +00:00
464 lines
12 KiB
Lua
464 lines
12 KiB
Lua
-- ============================================================
|
|
-- Bag Ammo Labels — standalone overlay for bag & bank ammo slots
|
|
-- Uses globals from zButtonAmmo.lua:
|
|
-- zButtonAmmo_ShortArrowLabels, zButtonAmmo_ShortBulletLabels,
|
|
-- zButtonAmmo_GetQualityColor, zButtonAmmo_GetColorGradient,
|
|
-- zButtonAmmo_GetKnownAmmoTypes
|
|
-- Uses DPS data from MTH_DS_AmmoItems[id].dps
|
|
-- ============================================================
|
|
|
|
-- Saved variable cache (per-character, stored in "general" module)
|
|
local cache = {} -- bagAmmoLabels, bankAmmoLabels, bagAmmoDamage
|
|
|
|
local function GetStore()
|
|
return MTH and MTH.GetModuleCharSavedVariables and MTH:GetModuleCharSavedVariables("general")
|
|
end
|
|
|
|
local function GetCached(key, default)
|
|
if cache[key] == nil then
|
|
local store = GetStore()
|
|
if type(store) == "table" and store[key] ~= nil then
|
|
cache[key] = store[key] and true or false
|
|
else
|
|
cache[key] = default or false
|
|
end
|
|
end
|
|
return cache[key]
|
|
end
|
|
|
|
local function SetCached(key, enabled)
|
|
cache[key] = enabled and true or false
|
|
local store = GetStore()
|
|
if type(store) == "table" then
|
|
store[key] = cache[key]
|
|
end
|
|
end
|
|
|
|
-- Public getters/setters
|
|
function MTH_BagAmmoLabels_GetEnabled()
|
|
return GetCached("bagAmmoLabels")
|
|
end
|
|
function MTH_BagAmmoLabels_SetEnabled(enabled)
|
|
SetCached("bagAmmoLabels", enabled)
|
|
MTH_BagAmmoLabels_RefreshAll()
|
|
end
|
|
|
|
function MTH_BankAmmoLabels_GetEnabled()
|
|
return GetCached("bankAmmoLabels")
|
|
end
|
|
function MTH_BankAmmoLabels_SetEnabled(enabled)
|
|
SetCached("bankAmmoLabels", enabled)
|
|
MTH_BagAmmoLabels_RefreshAllBank()
|
|
end
|
|
|
|
function MTH_BagAmmoDamage_GetEnabled()
|
|
return GetCached("bagAmmoDamage")
|
|
end
|
|
function MTH_BagAmmoDamage_SetEnabled(enabled)
|
|
SetCached("bagAmmoDamage", enabled)
|
|
MTH_BagAmmoLabels_RefreshAll()
|
|
MTH_BagAmmoLabels_RefreshAllBank()
|
|
end
|
|
|
|
-- Heat color: red (7.5 DPS) → yellow → green (20.5 DPS); below 7.5 = grey
|
|
local DPS_MIN = 7.5
|
|
local DPS_MAX = 20.5
|
|
|
|
local function GetDpsHeatColor(dps)
|
|
if not dps then return 1, 1, 1 end
|
|
if dps < DPS_MIN then return 0.6, 0.6, 0.6 end
|
|
local perc = (dps - DPS_MIN) / (DPS_MAX - DPS_MIN)
|
|
return zButtonAmmo_GetColorGradient(perc)
|
|
end
|
|
|
|
-- Look up DPS from MTH_DS_AmmoItems by numeric item ID
|
|
local function GetAmmoDps(numericId)
|
|
if not MTH_DS_AmmoItems then return nil end
|
|
local entry = MTH_DS_AmmoItems[numericId]
|
|
return entry and entry.dps
|
|
end
|
|
|
|
-- Detect whether pfUI bags are active
|
|
local function HasPfUI()
|
|
return pfUI and pfUI.bags and pfUI.bag and true or false
|
|
end
|
|
|
|
-- Is this bagID a bank bag?
|
|
local BANK_BAGS = { [-1] = true, [5] = true, [6] = true, [7] = true, [8] = true, [9] = true, [10] = true, [11] = true }
|
|
|
|
local function IsBankBag(bagID)
|
|
return BANK_BAGS[bagID] or false
|
|
end
|
|
|
|
-- Apply or clear labels on a single bag-slot button
|
|
local function UpdateButton(button, bagID, slot, showName, showDmg)
|
|
if not button then return end
|
|
|
|
-- Lazy-create name label (TOPLEFT)
|
|
if not button._mthAmmoLabel then
|
|
button._mthAmmoLabel = button:CreateFontString(nil, "OVERLAY")
|
|
button._mthAmmoLabel:SetPoint("TOPLEFT", button, "TOPLEFT", 1, -1)
|
|
button._mthAmmoLabel:SetFont("Fonts\\ARIALN.ttf", 9, "OUTLINE")
|
|
button._mthAmmoLabel:Hide()
|
|
end
|
|
-- Lazy-create damage label (CENTER, large + bold)
|
|
if not button._mthAmmoDmgLabel then
|
|
button._mthAmmoDmgLabel = button:CreateFontString(nil, "OVERLAY")
|
|
button._mthAmmoDmgLabel:SetPoint("CENTER", button, "CENTER", 0, 0)
|
|
button._mthAmmoDmgLabel:SetFont("Fonts\\ARIALN.ttf", 10, "THICKOUTLINE")
|
|
button._mthAmmoDmgLabel:Hide()
|
|
end
|
|
|
|
local nameLabel = button._mthAmmoLabel
|
|
local dmgLabel = button._mthAmmoDmgLabel
|
|
|
|
if not showName and not showDmg then
|
|
nameLabel:Hide()
|
|
dmgLabel:Hide()
|
|
return
|
|
end
|
|
|
|
local link = GetContainerItemLink(bagID, slot)
|
|
if not link then
|
|
nameLabel:Hide()
|
|
dmgLabel:Hide()
|
|
return
|
|
end
|
|
|
|
local _, _, id = string.find(link, "Hitem:(%d+)")
|
|
if not id then
|
|
nameLabel:Hide()
|
|
dmgLabel:Hide()
|
|
return
|
|
end
|
|
|
|
local numericId = tonumber(id)
|
|
local itemName, _, itemQuality, _, _, _, _, _, itemSlot = GetItemInfo(id)
|
|
if not itemName then
|
|
nameLabel:Hide()
|
|
dmgLabel:Hide()
|
|
return
|
|
end
|
|
|
|
local isAmmo = (itemSlot == "INVTYPE_AMMO")
|
|
if not isAmmo then
|
|
local knownAmmo = zButtonAmmo_GetKnownAmmoTypes and zButtonAmmo_GetKnownAmmoTypes()
|
|
isAmmo = knownAmmo and knownAmmo[itemName]
|
|
end
|
|
if not isAmmo then
|
|
nameLabel:Hide()
|
|
dmgLabel:Hide()
|
|
return
|
|
end
|
|
|
|
-- Name label
|
|
if showName then
|
|
local shortText = zButtonAmmo_ShortArrowLabels[itemName]
|
|
or zButtonAmmo_ShortBulletLabels[itemName]
|
|
if shortText then
|
|
local cr, cg, cb = zButtonAmmo_GetQualityColor(itemQuality)
|
|
nameLabel:SetTextColor(cr, cg, cb, 1)
|
|
nameLabel:SetText(shortText)
|
|
nameLabel:Show()
|
|
else
|
|
nameLabel:Hide()
|
|
end
|
|
else
|
|
nameLabel:Hide()
|
|
end
|
|
|
|
-- Damage label
|
|
if showDmg then
|
|
local dps = GetAmmoDps(numericId)
|
|
if dps then
|
|
local cr, cg, cb = GetDpsHeatColor(dps)
|
|
dmgLabel:SetTextColor(cr, cg, cb, 1)
|
|
dmgLabel:SetText(dps)
|
|
dmgLabel:Show()
|
|
else
|
|
dmgLabel:Hide()
|
|
end
|
|
else
|
|
dmgLabel:Hide()
|
|
end
|
|
end
|
|
|
|
-- Clear both labels on a button
|
|
local function ClearButton(button)
|
|
if not button then return end
|
|
if button._mthAmmoLabel then button._mthAmmoLabel:Hide() end
|
|
if button._mthAmmoDmgLabel then button._mthAmmoDmgLabel:Hide() end
|
|
end
|
|
|
|
-- Forward declaration
|
|
local RefreshAllVisibleFrames
|
|
|
|
-- Refresh labels on a single bag (works for any bagID)
|
|
local function RefreshBag(bagID, showName, showDmg)
|
|
local numSlots = GetContainerNumSlots(bagID)
|
|
if numSlots == 0 then return end
|
|
|
|
-- pfUI path
|
|
if HasPfUI() then
|
|
local pfBag = pfUI.bags[bagID]
|
|
if not pfBag or not pfBag.slots then return end
|
|
for slot = 1, numSlots do
|
|
local slotData = pfBag.slots[slot]
|
|
local button = slotData and slotData.frame
|
|
if button then
|
|
if showName or showDmg then
|
|
UpdateButton(button, bagID, slot, showName, showDmg)
|
|
else
|
|
ClearButton(button)
|
|
end
|
|
end
|
|
end
|
|
return
|
|
end
|
|
|
|
-- Default UI path
|
|
|
|
-- Main bank (bagID -1): buttons are BankFrameItem1..28
|
|
if bagID == -1 then
|
|
for slot = 1, numSlots do
|
|
local button = getglobal("BankFrameItem" .. slot)
|
|
if button then
|
|
if showName or showDmg then
|
|
UpdateButton(button, -1, slot, showName, showDmg)
|
|
else
|
|
ClearButton(button)
|
|
end
|
|
end
|
|
end
|
|
return
|
|
end
|
|
|
|
-- All other bags (0-4 and 5-11): search all ContainerFrames
|
|
for ci = 1, 13 do
|
|
local frame = getglobal("ContainerFrame" .. ci)
|
|
if frame and frame:IsVisible() and frame:GetID() == bagID then
|
|
local frameName = frame:GetName()
|
|
-- Visual button i = API slot (numSlots - i + 1)
|
|
for i = 1, numSlots do
|
|
local button = getglobal(frameName .. "Item" .. i)
|
|
local apiSlot = numSlots - i + 1
|
|
if button then
|
|
if showName or showDmg then
|
|
UpdateButton(button, bagID, apiSlot, showName, showDmg)
|
|
else
|
|
ClearButton(button)
|
|
end
|
|
end
|
|
end
|
|
-- Clear stale labels on any buttons beyond numSlots
|
|
for slot = numSlots + 1, 24 do
|
|
local button = getglobal(frameName .. "Item" .. slot)
|
|
if not button then break end
|
|
ClearButton(button)
|
|
end
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Public: refresh all inventory bags (0-4)
|
|
function MTH_BagAmmoLabels_RefreshAll()
|
|
RefreshAllVisibleFrames()
|
|
end
|
|
|
|
-- Public: refresh all bank bags (-1, 5-11)
|
|
function MTH_BagAmmoLabels_RefreshAllBank()
|
|
RefreshAllVisibleFrames()
|
|
end
|
|
|
|
-- Refresh all visible default UI ContainerFrames (frame-centric: no bagID lookup)
|
|
RefreshAllVisibleFrames = function()
|
|
local bagShowName = MTH_BagAmmoLabels_GetEnabled()
|
|
local bankShowName = MTH_BankAmmoLabels_GetEnabled()
|
|
local showDmg = MTH_BagAmmoDamage_GetEnabled()
|
|
|
|
if HasPfUI() then
|
|
-- pfUI: refresh via pfUI bag structure
|
|
for bagID = 0, 4 do
|
|
RefreshBag(bagID, bagShowName, showDmg)
|
|
end
|
|
local bankBags = { -1, 5, 6, 7, 8, 9, 10, 11 }
|
|
for _, bagID in ipairs(bankBags) do
|
|
RefreshBag(bagID, bankShowName, showDmg)
|
|
end
|
|
return
|
|
end
|
|
|
|
-- Default UI: iterate all visible ContainerFrames
|
|
for ci = 1, 13 do
|
|
local cf = getglobal("ContainerFrame" .. ci)
|
|
if cf and cf:IsVisible() then
|
|
local bagID = cf:GetID()
|
|
local showName = IsBankBag(bagID) and bankShowName or bagShowName
|
|
local numSlots = GetContainerNumSlots(bagID)
|
|
local fname = cf:GetName()
|
|
-- Visual button i = API slot (numSlots - i + 1)
|
|
for i = 1, numSlots do
|
|
local button = getglobal(fname .. "Item" .. i)
|
|
local apiSlot = numSlots - i + 1
|
|
if button then
|
|
if showName or showDmg then
|
|
UpdateButton(button, bagID, apiSlot, showName, showDmg)
|
|
else
|
|
ClearButton(button)
|
|
end
|
|
end
|
|
end
|
|
for slot = numSlots + 1, 24 do
|
|
local button = getglobal(fname .. "Item" .. slot)
|
|
if not button then break end
|
|
ClearButton(button)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Bank bag -1: BankFrameItem buttons
|
|
if bankShowName or showDmg then
|
|
local numSlots = GetContainerNumSlots(-1)
|
|
for slot = 1, numSlots do
|
|
local button = getglobal("BankFrameItem" .. slot)
|
|
if button then
|
|
UpdateButton(button, -1, slot, bankShowName, showDmg)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Event-driven refresh: coalesce with a short delay
|
|
do
|
|
local frame = CreateFrame("Frame", "MTH_BagAmmoLabelsFrame", UIParent)
|
|
local needsRefresh = false
|
|
local elapsed = 0
|
|
|
|
frame:RegisterEvent("BAG_UPDATE")
|
|
frame:RegisterEvent("PLAYERBANKSLOTS_CHANGED")
|
|
frame:RegisterEvent("PLAYERBANKBAGSLOTS_CHANGED")
|
|
frame:RegisterEvent("BANKFRAME_OPENED")
|
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
|
|
frame:SetScript("OnEvent", function()
|
|
if event == "PLAYER_ENTERING_WORLD" then
|
|
-- After login/reload, delay 1s for item cache to populate
|
|
elapsed = -0.95
|
|
needsRefresh = true
|
|
frame:Show()
|
|
return
|
|
end
|
|
|
|
if event == "BANKFRAME_OPENED" then
|
|
if MTH_BankAmmoLabels_GetEnabled() or MTH_BagAmmoDamage_GetEnabled() then
|
|
needsRefresh = true
|
|
if not frame:IsShown() then
|
|
elapsed = 0
|
|
frame:Show()
|
|
end
|
|
end
|
|
return
|
|
end
|
|
|
|
if event == "PLAYERBANKSLOTS_CHANGED" or event == "PLAYERBANKBAGSLOTS_CHANGED" then
|
|
if MTH_BankAmmoLabels_GetEnabled() or MTH_BagAmmoDamage_GetEnabled() then
|
|
needsRefresh = true
|
|
if not frame:IsShown() then
|
|
elapsed = 0
|
|
frame:Show()
|
|
end
|
|
end
|
|
return
|
|
end
|
|
|
|
-- BAG_UPDATE
|
|
local bagID = arg1
|
|
if not bagID then return end
|
|
if IsBankBag(bagID) then
|
|
if not MTH_BankAmmoLabels_GetEnabled() and not MTH_BagAmmoDamage_GetEnabled() then return end
|
|
else
|
|
if not MTH_BagAmmoLabels_GetEnabled() and not MTH_BagAmmoDamage_GetEnabled() then return end
|
|
end
|
|
needsRefresh = true
|
|
if not frame:IsShown() then
|
|
elapsed = 0
|
|
frame:Show()
|
|
end
|
|
end)
|
|
|
|
frame:SetScript("OnUpdate", function()
|
|
elapsed = elapsed + (arg1 or 0.016)
|
|
if elapsed < 0.05 then return end
|
|
needsRefresh = false
|
|
frame:Hide()
|
|
RefreshAllVisibleFrames()
|
|
end)
|
|
frame:Hide()
|
|
|
|
-- Hook ContainerFrame OnShow: trigger a refresh when a bag becomes visible
|
|
if not HasPfUI() then
|
|
for ci = 1, 13 do
|
|
local cf = getglobal("ContainerFrame" .. ci)
|
|
if cf then
|
|
local origOnShow = cf:GetScript("OnShow")
|
|
cf:SetScript("OnShow", function()
|
|
if origOnShow then origOnShow() end
|
|
needsRefresh = true
|
|
if not frame:IsShown() then
|
|
elapsed = 0
|
|
frame:Show()
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Post-hook ContainerFrame_Update for default UI (synchronous update)
|
|
if type(ContainerFrame_Update) == "function" then
|
|
local origCFU = ContainerFrame_Update
|
|
ContainerFrame_Update = function(cf)
|
|
origCFU(cf)
|
|
if cf and cf:IsVisible() then
|
|
local bagID = cf:GetID()
|
|
local showDmg = MTH_BagAmmoDamage_GetEnabled()
|
|
local showName
|
|
if IsBankBag(bagID) then
|
|
showName = MTH_BankAmmoLabels_GetEnabled()
|
|
else
|
|
showName = MTH_BagAmmoLabels_GetEnabled()
|
|
end
|
|
if showName or showDmg then
|
|
local numSlots = GetContainerNumSlots(bagID)
|
|
local fname = cf:GetName()
|
|
-- Visual button i = API slot (numSlots - i + 1)
|
|
for i = 1, numSlots do
|
|
local button = getglobal(fname .. "Item" .. i)
|
|
local apiSlot = numSlots - i + 1
|
|
if button then
|
|
UpdateButton(button, bagID, apiSlot, showName, showDmg)
|
|
end
|
|
end
|
|
for slot = numSlots + 1, 24 do
|
|
local button = getglobal(fname .. "Item" .. slot)
|
|
if not button then break end
|
|
ClearButton(button)
|
|
end
|
|
end
|
|
else
|
|
-- Frame hidden: clear all labels
|
|
if cf then
|
|
local fname = cf:GetName()
|
|
if fname then
|
|
for slot = 1, 24 do
|
|
local button = getglobal(fname .. "Item" .. slot)
|
|
if not button then break end
|
|
ClearButton(button)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|