From a62d949f308b6124aa6368fda9d8c8619bcfbf26 Mon Sep 17 00:00:00 2001 From: Salikh Gurgenidze Date: Sat, 27 Dec 2025 18:13:04 +0400 Subject: [PATCH] fix: item list --- Core/Tooltip.lua | 108 +++++++++++++++++++++++++++++++++++++--- Data/MailboxScanner.lua | 66 +++++++++++++++++------- UI/MailboxFrame.lua | 27 +--------- 3 files changed, 152 insertions(+), 49 deletions(-) diff --git a/Core/Tooltip.lua b/Core/Tooltip.lua index 8663ce8..26aa665 100644 --- a/Core/Tooltip.lua +++ b/Core/Tooltip.lua @@ -13,6 +13,7 @@ end local function CountCurrentCharacterItems(itemID) local bagCount = 0 local bankCount = 0 + local mailCount = 0 local equippedCount = 0 -- Count current character's bags in real-time @@ -83,6 +84,51 @@ local function CountCurrentCharacterItems(itemID) end end + -- Count current character's mailbox in real-time if mailbox is open + if addon.Modules.MailboxScanner and addon.Modules.MailboxScanner:IsMailboxOpen() then + local numInboxItems = GetInboxNumItems() + for i = 1, numInboxItems do + local _, _, _, _, _, _, _, hasItem = GetInboxHeaderInfo(i) + if hasItem then + for j = 1, 12 do -- Turtle WoW supports up to 12 attachments + local name, _, count = GetInboxItem(i, j) + if name then + local itemLink = addon.Modules.Utils:GetInboxItemLink(i, j) + if itemLink then + local slotItemID = GetItemIDFromLink(itemLink) + if slotItemID == itemID then + mailCount = mailCount + (count or 1) + end + end + end + end + end + end + else + -- Mailbox not open - use saved data + local playerName = addon.Modules.DB:GetPlayerFullName() + local charData = Guda_DB and Guda_DB.characters and Guda_DB.characters[playerName] + if charData and charData.mailbox and type(charData.mailbox) == "table" then + for _, mail in ipairs(charData.mailbox) do + if mail.items then + for _, item in ipairs(mail.items) do + if item.link then + local slotItemID = GetItemIDFromLink(item.link) + if slotItemID == itemID then + mailCount = mailCount + (item.count or 1) + end + end + end + elseif mail.item and mail.item.link then -- Fallback for single item data structure + local slotItemID = GetItemIDFromLink(mail.item.link) + if slotItemID == itemID then + mailCount = mailCount + (mail.item.count or 1) + end + end + end + end + end + -- Count equipped items in real-time for slotID = 1, 19 do -- All equipment slots local link = GetInventoryItemLink("player", slotID) @@ -94,7 +140,7 @@ local function CountCurrentCharacterItems(itemID) end end - return bagCount, bankCount, equippedCount + return bagCount, bankCount, equippedCount, mailCount end -- Count items for a specific character with real-time data for current character @@ -107,6 +153,7 @@ local function CountItemsForCharacter(itemID, characterData, isCurrentChar) -- For other characters, use saved data local bagCount = 0 local bankCount = 0 + local mailCount = 0 local equippedCount = 0 -- Count bags from saved data @@ -141,6 +188,27 @@ local function CountItemsForCharacter(itemID, characterData, isCurrentChar) end end + -- Count mailbox from saved data + if characterData.mailbox and type(characterData.mailbox) == "table" then + for _, mail in ipairs(characterData.mailbox) do + if mail.items then + for _, item in ipairs(mail.items) do + if item.link then + local slotItemID = GetItemIDFromLink(item.link) + if slotItemID == itemID then + mailCount = mailCount + (item.count or 1) + end + end + end + elseif mail.item and mail.item.link then -- Fallback for single item data structure + local slotItemID = GetItemIDFromLink(mail.item.link) + if slotItemID == itemID then + mailCount = mailCount + (mail.item.count or 1) + end + end + end + end + -- Count equipped items from saved data if characterData.equipped and type(characterData.equipped) == "table" then for slotName, itemData in pairs(characterData.equipped) do @@ -153,7 +221,7 @@ local function CountItemsForCharacter(itemID, characterData, isCurrentChar) end end - return bagCount, bankCount, equippedCount + return bagCount, bankCount, equippedCount, mailCount end @@ -189,6 +257,7 @@ function Tooltip:AddInventoryInfo(tooltip, link) local totalBags = 0 local totalBank = 0 + local totalMail = 0 local totalEquipped = 0 local characterCounts = {} local hasAnyItems = false @@ -201,18 +270,20 @@ function Tooltip:AddInventoryInfo(tooltip, link) -- Ensure charData is actually a table and on current realm if type(charData) == "table" and charData.realm == currentRealm then local isCurrentChar = (charName == currentPlayerName) - local bagCount, bankCount, equippedCount = CountItemsForCharacter(itemID, charData, isCurrentChar) + local bagCount, bankCount, equippedCount, mailCount = CountItemsForCharacter(itemID, charData, isCurrentChar) - if bagCount > 0 or bankCount > 0 or equippedCount > 0 then + if bagCount > 0 or bankCount > 0 or equippedCount > 0 or mailCount > 0 then hasAnyItems = true totalBags = totalBags + bagCount totalBank = totalBank + bankCount + totalMail = totalMail + mailCount totalEquipped = totalEquipped + equippedCount table.insert(characterCounts, { name = charData.name or charName, classToken = charData.classToken, bagCount = bagCount, bankCount = bankCount, + mailCount = mailCount, equippedCount = equippedCount, isCurrent = isCurrentChar }) @@ -221,7 +292,7 @@ function Tooltip:AddInventoryInfo(tooltip, link) -- If charData is not a table (string, number, etc.), just skip it end - local totalCount = totalBags + totalBank + totalEquipped + local totalCount = totalBags + totalBank + totalMail + totalEquipped if hasAnyItems then @@ -233,7 +304,16 @@ function Tooltip:AddInventoryInfo(tooltip, link) -- Total line with cyan label and white count local totalText = "|cFF00FFFFTotal|r: |cFFFFFFFF" .. totalCount .. "|r" - local breakdownText = "(|cFF00FFFFBags|r: |cFFFFFFFF" .. totalBags .. "|r | |cFF00FFFFBank|r: |cFFFFFFFF" .. totalBank .. "|r)" + local breakdownParts = {} + if totalBags > 0 then table.insert(breakdownParts, "|cFF00FFFFBags|r: |cFFFFFFFF" .. totalBags .. "|r") end + if totalBank > 0 then table.insert(breakdownParts, "|cFF00FFFFBank|r: |cFFFFFFFF" .. totalBank .. "|r") end + if totalMail > 0 then table.insert(breakdownParts, "|cFF00FFFFMail|r: |cFFFFFFFF" .. totalMail .. "|r") end + if totalEquipped > 0 then table.insert(breakdownParts, "|cFF00FFFFEquipped|r: |cFFFFFFFF" .. totalEquipped .. "|r") end + + local breakdownText = "" + if table.getn(breakdownParts) > 0 then + breakdownText = "(" .. table.concat(breakdownParts, " | ") .. ")" + end tooltip:AddDoubleLine(totalText, breakdownText, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0) -- Sort with current character first @@ -254,6 +334,9 @@ function Tooltip:AddInventoryInfo(tooltip, link) if charInfo.bankCount > 0 then table.insert(parts, "|cFF00FFFFBank|r: |cFFFFFFFF" .. charInfo.bankCount .. "|r") end + if charInfo.mailCount > 0 then + table.insert(parts, "|cFF00FFFFMail|r: |cFFFFFFFF" .. charInfo.mailCount .. "|r") + end if charInfo.equippedCount > 0 then table.insert(parts, "|cFF00FFFFEquipped|r: |cFFFFFFFF" .. charInfo.equippedCount .. "|r") end @@ -453,6 +536,19 @@ function Tooltip:Initialize() end) end + -- Hook SetInboxItem for mailbox + local oldSetInboxItem = GameTooltip.SetInboxItem + function GameTooltip:SetInboxItem(index, itemIndex) + return WithDeferredMoney(self, function() + local ret = oldSetInboxItem(self, index, itemIndex) + local link = addon.Modules.Utils:GetInboxItemLink(index, itemIndex) + if link then + Tooltip:AddInventoryInfo(self, link) + end + return ret + end) + end + -- Hook SetTradeSkillItem for profession reagents and items local oldSetTradeSkillItem = GameTooltip.SetTradeSkillItem function GameTooltip:SetTradeSkillItem(skillIndex, reagentIndex) diff --git a/Data/MailboxScanner.lua b/Data/MailboxScanner.lua index 0c2e982..747a146 100644 --- a/Data/MailboxScanner.lua +++ b/Data/MailboxScanner.lua @@ -19,20 +19,25 @@ function MailboxScanner:ScanMailbox() local numItems = GetInboxNumItems() for i = 1, numItems do - mailboxData[i] = self:ScanMailItem(i) + local mailRows = self:ScanMailItemRows(i) + for _, row in ipairs(mailRows) do + table.insert(mailboxData, row) + end end return mailboxData end --- Scan a single mail item -function MailboxScanner:ScanMailItem(index) +-- Scan a single mail into one or more rows (flattened) +function MailboxScanner:ScanMailItemRows(index) -- GetInboxHeaderInfo(index) returns: packageIcon, stationeryIcon, sender, subject, money, CODAmount, daysLeft, hasItem, wasRead, wasReturned, textCreated, canReply, isGM local packageIcon, stationeryIcon, sender, subject, money, CODAmount, daysLeft, hasItem, wasRead, wasReturned, textCreated, canReply, isGM = GetInboxHeaderInfo(index) - local items = {} + local rows = {} + if hasItem then -- Turtle WoW supports up to 12 attachments per mail + -- GetInboxItem(index, itemIndex) returns: name, texture, count, quality, canUse local name, texture, count, quality, canUse = GetInboxItem(index, itemIndex) if name then @@ -60,22 +65,41 @@ function MailboxScanner:ScanMailItem(index) if itemTexture then itemData.texture = itemTexture end end end - table.insert(items, itemData) + + table.insert(rows, { + sender = sender, + subject = subject, + money = (itemIndex == 1) and money or 0, -- Attach money only to the first row of this mail + CODAmount = (itemIndex == 1) and CODAmount or 0, + daysLeft = daysLeft, + hasItem = true, + item = itemData, + mailIndex = index, + itemIndex = itemIndex, + wasRead = wasRead, + packageIcon = packageIcon, + }) end end - return { - sender = sender, - subject = subject, - money = money, - CODAmount = CODAmount, - daysLeft = daysLeft, - hasItem = (table.getn(items) > 0), - item = items[1], - items = items, - wasRead = wasRead, - packageIcon = packageIcon, - } + -- If no items found but there is money or it's just a letter + if table.getn(rows) == 0 then + table.insert(rows, { + sender = sender, + subject = subject, + money = money, + CODAmount = CODAmount, + daysLeft = daysLeft, + hasItem = false, + item = nil, + mailIndex = index, + itemIndex = 1, + wasRead = wasRead, + packageIcon = packageIcon, + }) + end + + return rows end -- Save current mailbox to database @@ -118,6 +142,14 @@ function MailboxScanner:Initialize() end end, "MailboxScanner") + -- Register for MAIL_INBOX_UPDATE to detect when mail content changes + addon.Modules.Events:Register("MAIL_INBOX_UPDATE", function() + if mailboxOpen then + addon:Debug("MAIL_INBOX_UPDATE: Refreshing mailbox") + MailboxScanner:SaveToDatabase() + end + end, "MailboxScanner") + -- Register for UI_ERROR_MESSAGE to handle "item not found" situations if needed -- (Some items might not be in cache and fail silently otherwise) diff --git a/UI/MailboxFrame.lua b/UI/MailboxFrame.lua index 465f01a..163e4ec 100644 --- a/UI/MailboxFrame.lua +++ b/UI/MailboxFrame.lua @@ -123,38 +123,13 @@ function MailboxFrame:Update() matchesSearch = true elseif mail.subject and string.find(string.lower(mail.subject), searchText) then matchesSearch = true - elseif mail.items then - for _, item in ipairs(mail.items) do - if item.name and string.find(string.lower(item.name), searchText) then - matchesSearch = true - break - end - end elseif mail.item and mail.item.name and string.find(string.lower(mail.item.name), searchText) then matchesSearch = true end end if matchesSearch then - -- Flatten mails with multiple items so they all show up in the grid - if mail.items and table.getn(mail.items) > 1 then - for itemIndex, item in ipairs(mail.items) do - local mailCopy = {} - for k, v in pairs(mail) do mailCopy[k] = v end - mailCopy.item = item - mailCopy.mailIndex = i - mailCopy.itemIndex = itemIndex - -- Clear items list in copy to avoid recursive flattening - mailCopy.items = nil - table.insert(filteredItems, mailCopy) - end - else - local mailCopy = {} - for k, v in pairs(mail) do mailCopy[k] = v end - mailCopy.mailIndex = i - mailCopy.itemIndex = 1 - table.insert(filteredItems, mailCopy) - end + table.insert(filteredItems, mail) end end