feat: display charges on item
This commit is contained in:
@@ -12,6 +12,7 @@ addon.Modules.ItemDetection = ItemDetection
|
|||||||
-- Caches tooltip scan results to avoid repeated scans
|
-- Caches tooltip scan results to avoid repeated scans
|
||||||
--=====================================================
|
--=====================================================
|
||||||
local detectionCache = {}
|
local detectionCache = {}
|
||||||
|
local chargesCache = {} -- Keyed by "bagID:slotID" (charges vary per-slot, not per-link)
|
||||||
local cacheHits = 0
|
local cacheHits = 0
|
||||||
local cacheMisses = 0
|
local cacheMisses = 0
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ local cacheMisses = 0
|
|||||||
-- For simple item moves, use InvalidateItem() or don't invalidate at all
|
-- For simple item moves, use InvalidateItem() or don't invalidate at all
|
||||||
function ItemDetection:ClearCache()
|
function ItemDetection:ClearCache()
|
||||||
detectionCache = {}
|
detectionCache = {}
|
||||||
|
chargesCache = {}
|
||||||
cacheHits = 0
|
cacheHits = 0
|
||||||
cacheMisses = 0
|
cacheMisses = 0
|
||||||
end
|
end
|
||||||
@@ -447,6 +449,17 @@ local function DetectUnusable(lines)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Detect item charges (e.g. "5 Charges" on Wizard Oil, Mana Oil, etc.)
|
||||||
|
local function DetectCharges(lines)
|
||||||
|
for _, line in ipairs(lines) do
|
||||||
|
local _, _, num = string.find(line.leftLower, "^(%d+) charges?$")
|
||||||
|
if num then
|
||||||
|
return tonumber(num)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--=====================================================
|
--=====================================================
|
||||||
-- Public API - Cached Detection
|
-- Public API - Cached Detection
|
||||||
--=====================================================
|
--=====================================================
|
||||||
@@ -497,6 +510,11 @@ function ItemDetection:GetItemProperties(itemData, bagID, slotID)
|
|||||||
local isJunk = DetectJunk(lines, itemData)
|
local isJunk = DetectJunk(lines, itemData)
|
||||||
local isUnusable = DetectUnusable(lines)
|
local isUnusable = DetectUnusable(lines)
|
||||||
|
|
||||||
|
-- Store charges in per-slot cache during property scan (avoids double tooltip scan)
|
||||||
|
if bagID and slotID and tooltipLooksComplete then
|
||||||
|
chargesCache[bagID .. ":" .. slotID] = DetectCharges(lines)
|
||||||
|
end
|
||||||
|
|
||||||
-- Debug: log junk detection for gray items
|
-- Debug: log junk detection for gray items
|
||||||
if addon.DEBUG then
|
if addon.DEBUG then
|
||||||
local quality = tonumber(itemData.quality)
|
local quality = tonumber(itemData.quality)
|
||||||
@@ -563,6 +581,37 @@ function ItemDetection:IsUnusable(itemData, bagID, slotID)
|
|||||||
return props.isUnusable
|
return props.isUnusable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function ItemDetection:GetCharges(itemData, bagID, slotID)
|
||||||
|
if not bagID or not slotID then return nil end
|
||||||
|
local slotKey = bagID .. ":" .. slotID
|
||||||
|
-- Use per-slot cache if available
|
||||||
|
if chargesCache[slotKey] ~= nil then
|
||||||
|
return chargesCache[slotKey]
|
||||||
|
end
|
||||||
|
-- Otherwise scan tooltip fresh
|
||||||
|
local itemLink = itemData and itemData.link
|
||||||
|
local lines = ScanTooltipLines(bagID, slotID, itemLink)
|
||||||
|
local charges = DetectCharges(lines)
|
||||||
|
if table.getn(lines) >= 2 then
|
||||||
|
chargesCache[slotKey] = charges
|
||||||
|
end
|
||||||
|
return charges
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Invalidate charges cache for a specific bag (called on BAG_UPDATE)
|
||||||
|
function ItemDetection:InvalidateCharges(bagID)
|
||||||
|
if bagID then
|
||||||
|
local prefix = bagID .. ":"
|
||||||
|
for key in pairs(chargesCache) do
|
||||||
|
if string.find(key, "^" .. prefix) then
|
||||||
|
chargesCache[key] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
chargesCache = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--=====================================================
|
--=====================================================
|
||||||
-- Initialization
|
-- Initialization
|
||||||
--=====================================================
|
--=====================================================
|
||||||
@@ -573,5 +622,10 @@ function ItemDetection:Initialize()
|
|||||||
self:ClearCache()
|
self:ClearCache()
|
||||||
end, "ItemDetection")
|
end, "ItemDetection")
|
||||||
|
|
||||||
|
-- Invalidate charges cache on bag updates (charges change per-slot)
|
||||||
|
addon.Modules.Events:Register("BAG_UPDATE", function()
|
||||||
|
self:InvalidateCharges(arg1)
|
||||||
|
end, "ItemDetection_Charges")
|
||||||
|
|
||||||
addon:Debug("ItemDetection module initialized")
|
addon:Debug("ItemDetection module initialized")
|
||||||
end
|
end
|
||||||
|
|||||||
+1
-1
@@ -2451,7 +2451,7 @@ function Guda_BagFrame_Sort()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Restack and Clean (for category view) - merges stacks and refreshes view
|
-- Restack and Clean (for category view) - merges stacks and refreshes view
|
||||||
-- Queue-based approach like BagShui
|
-- Queue-based approach
|
||||||
function Guda_BagFrame_MergeStacks()
|
function Guda_BagFrame_MergeStacks()
|
||||||
if currentViewChar then
|
if currentViewChar then
|
||||||
addon:Print("Cannot restack for another character!")
|
addon:Print("Cannot restack for another character!")
|
||||||
|
|||||||
+1
-1
@@ -123,7 +123,7 @@
|
|||||||
<OnLoad>
|
<OnLoad>
|
||||||
local icon = getglobal(this:GetName().."_Icon")
|
local icon = getglobal(this:GetName().."_Icon")
|
||||||
if icon then
|
if icon then
|
||||||
-- BagShui approach: no file extension, WoW finds .blp automatically
|
-- No file extension, WoW finds .blp automatically
|
||||||
icon:SetTexture("Interface\\AddOns\\Guda\\Assets\\Sorting")
|
icon:SetTexture("Interface\\AddOns\\Guda\\Assets\\Sorting")
|
||||||
icon:SetTexCoord(0, 1, 0, 1)
|
icon:SetTexCoord(0, 1, 0, 1)
|
||||||
end
|
end
|
||||||
|
|||||||
+1
-1
@@ -1686,7 +1686,7 @@ function Guda_BankFrame_Sort()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Restack and Clean (for category view) - merges stacks and refreshes view
|
-- Restack and Clean (for category view) - merges stacks and refreshes view
|
||||||
-- Queue-based approach like BagShui
|
-- Queue-based approach
|
||||||
function Guda_BankFrame_MergeStacks()
|
function Guda_BankFrame_MergeStacks()
|
||||||
if isReadOnlyMode or currentViewChar then
|
if isReadOnlyMode or currentViewChar then
|
||||||
addon:Print("Cannot restack in read-only mode!")
|
addon:Print("Cannot restack in read-only mode!")
|
||||||
|
|||||||
+1
-1
@@ -76,7 +76,7 @@
|
|||||||
<OnLoad>
|
<OnLoad>
|
||||||
local icon = getglobal(this:GetName().."_Icon")
|
local icon = getglobal(this:GetName().."_Icon")
|
||||||
if icon then
|
if icon then
|
||||||
-- BagShui approach: no file extension, WoW finds .blp automatically
|
-- No file extension, WoW finds .blp automatically
|
||||||
icon:SetTexture("Interface\\AddOns\\Guda\\Assets\\Sorting")
|
icon:SetTexture("Interface\\AddOns\\Guda\\Assets\\Sorting")
|
||||||
icon:SetTexCoord(0, 1, 0, 1)
|
icon:SetTexCoord(0, 1, 0, 1)
|
||||||
end
|
end
|
||||||
|
|||||||
+38
-2
@@ -1334,6 +1334,8 @@ local function ResetButtonVisualState(self)
|
|||||||
if self.unusableOverlay then self.unusableOverlay:Hide() end
|
if self.unusableOverlay then self.unusableOverlay:Hide() end
|
||||||
HideJunkIcon(self)
|
HideJunkIcon(self)
|
||||||
if self.categoryMarkIcon then self.categoryMarkIcon:Hide() end
|
if self.categoryMarkIcon then self.categoryMarkIcon:Hide() end
|
||||||
|
local chargesText = getglobal(self:GetName().."_Charges")
|
||||||
|
if chargesText then chargesText:Hide() end
|
||||||
|
|
||||||
-- Clear cooldown overlay
|
-- Clear cooldown overlay
|
||||||
local cd = getglobal(self:GetName().."Cooldown") or self.cooldown
|
local cd = getglobal(self:GetName().."Cooldown") or self.cooldown
|
||||||
@@ -1634,6 +1636,8 @@ local function ClearItemButton(self, emptySlotBg, countText, bagID)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if countText then countText:Hide() end
|
if countText then countText:Hide() end
|
||||||
|
local chargesText = getglobal(self:GetName().."_Charges")
|
||||||
|
if chargesText then chargesText:Hide() end
|
||||||
|
|
||||||
ResetSlotBorder(self)
|
ResetSlotBorder(self)
|
||||||
HideInnerShadow(self.innerShadow)
|
HideInnerShadow(self.innerShadow)
|
||||||
@@ -1681,6 +1685,7 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha
|
|||||||
|
|
||||||
-- Get UI elements
|
-- Get UI elements
|
||||||
local countText = getglobal(self:GetName().."Count")
|
local countText = getglobal(self:GetName().."Count")
|
||||||
|
local chargesText = getglobal(self:GetName().."_Charges")
|
||||||
local emptySlotBg = getglobal(self:GetName().."_EmptySlotBg")
|
local emptySlotBg = getglobal(self:GetName().."_EmptySlotBg")
|
||||||
local Utils = addon and addon.Modules and addon.Modules.Utils
|
local Utils = addon and addon.Modules and addon.Modules.Utils
|
||||||
|
|
||||||
@@ -1827,6 +1832,23 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Apply icon font size setting to charges text (positioned above stack count)
|
||||||
|
if chargesText and chargesText.GetFont then
|
||||||
|
local font, _, flags = chargesText:GetFont()
|
||||||
|
local fontSize = 12
|
||||||
|
if Utils and Utils.SafeCall then
|
||||||
|
fontSize = Utils:SafeCall("DB", "GetSetting", "iconFontSize") or fontSize
|
||||||
|
end
|
||||||
|
chargesText:SetFont(font, fontSize, flags)
|
||||||
|
chargesText:SetTextColor(1, 0.82, 0)
|
||||||
|
chargesText:ClearAllPoints()
|
||||||
|
if iconSize < 44 then
|
||||||
|
chargesText:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -1, 1)
|
||||||
|
else
|
||||||
|
chargesText:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -3, 3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Get live metadata if in live mode (quality, link, lock status)
|
-- Get live metadata if in live mode (quality, link, lock status)
|
||||||
local itemQuality, itemLink, isLocked
|
local itemQuality, itemLink, isLocked
|
||||||
if not self.isReadOnly and bagID and slotID and self.hasItem then
|
if not self.isReadOnly and bagID and slotID and self.hasItem then
|
||||||
@@ -1896,7 +1918,7 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha
|
|||||||
if self.hasItem then
|
if self.hasItem then
|
||||||
-- Icon already set above based on mode (live vs cached)
|
-- Icon already set above based on mode (live vs cached)
|
||||||
|
|
||||||
-- Gray out locked items (being traded, mailed, or auctioned) - BagShui style
|
-- Gray out locked items (being traded, mailed, or auctioned)
|
||||||
-- Don't desaturate items from other characters since they're read-only anyway
|
-- Don't desaturate items from other characters since they're read-only anyway
|
||||||
if not self.otherChar and not self.isReadOnly then
|
if not self.otherChar and not self.isReadOnly then
|
||||||
SetItemButtonDesaturated(self, isLocked, 0.5, 0.5, 0.5)
|
SetItemButtonDesaturated(self, isLocked, 0.5, 0.5, 0.5)
|
||||||
@@ -2060,6 +2082,20 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Show/hide charges text (e.g. "x5" for Wizard Oil)
|
||||||
|
if chargesText then
|
||||||
|
local charges = nil
|
||||||
|
if itemData and addon.Modules.ItemDetection then
|
||||||
|
charges = addon.Modules.ItemDetection:GetCharges(itemData, bagID, slotID)
|
||||||
|
end
|
||||||
|
if charges and charges > 0 then
|
||||||
|
chargesText:SetText("x" .. charges)
|
||||||
|
chargesText:Show()
|
||||||
|
else
|
||||||
|
chargesText:Hide()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Handle tracking toggle on click
|
-- Handle tracking toggle on click
|
||||||
-- Note: Tracking toggle is now handled in the main OnClick script above to avoid conflicts
|
-- Note: Tracking toggle is now handled in the main OnClick script above to avoid conflicts
|
||||||
-- and unified with QuestItemBar pinning logic.
|
-- and unified with QuestItemBar pinning logic.
|
||||||
@@ -2369,7 +2405,7 @@ function Guda_ItemButton_OnEnter(self)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handle merchant sell cursor (same approach as BagShui)
|
-- Handle merchant sell cursor
|
||||||
if MerchantFrame:IsShown() and not self.isBank and not self.otherChar and self.hasItem then
|
if MerchantFrame:IsShown() and not self.isBank and not self.otherChar and self.hasItem then
|
||||||
ShowContainerSellCursor(self.bagID, self.slotID)
|
ShowContainerSellCursor(self.bagID, self.slotID)
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -37,6 +37,16 @@
|
|||||||
</Anchor>
|
</Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
</FontString>
|
</FontString>
|
||||||
|
<FontString name="$parent_Charges" inherits="NumberFontNormal" justifyH="RIGHT" hidden="true">
|
||||||
|
<Color r="1" g="0.82" b="0"/>
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="BOTTOMRIGHT">
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="-8" y="20"/>
|
||||||
|
</Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
</FontString>
|
||||||
<Texture name="$parent_Check" file="Interface\Buttons\UI-CheckBox-Check" hidden="true">
|
<Texture name="$parent_Check" file="Interface\Buttons\UI-CheckBox-Check" hidden="true">
|
||||||
<Size>
|
<Size>
|
||||||
<AbsDimension x="24" y="24"/>
|
<AbsDimension x="24" y="24"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user