diff --git a/Core/Database.lua b/Core/Database.lua index d551830..4c6d227 100644 --- a/Core/Database.lua +++ b/Core/Database.lua @@ -11,210 +11,250 @@ local playerName, playerRealm, playerFaction -- Initialize database function DB:Initialize() - -- Get player info - playerName = UnitName("player") - playerRealm = GetRealmName() - playerFaction = UnitFactionGroup("player") +-- Get player info + playerName = UnitName("player") + playerRealm = GetRealmName() + playerFaction = UnitFactionGroup("player") - local fullName = playerName .. "-" .. playerRealm + local fullName = playerName .. "-" .. playerRealm - -- Initialize global DB - if not Guda_DB then - Guda_DB = { - version = addon.VERSION, - characters = {}, - } - end + -- Initialize global DB + if not Guda_DB then + Guda_DB = { + version = addon.VERSION, + characters = {}, + } + end - -- Initialize character DB - if not Guda_CharDB then - Guda_CharDB = { - settings = { - showBankInBags = true, - showOtherChars = true, - bagColumns = 10, - bankBagColumns = 8, - bankColumns = 10, - sortMethod = "quality", -- quality, name, type - iconSize = 40, - iconSpacing = 0, - iconFontSize = 12, - }, - } - end + -- Initialize character DB + if not Guda_CharDB then + Guda_CharDB = { + settings = { + showBankInBags = true, + showOtherChars = true, + bagColumns = 10, + bankBagColumns = 8, + bankColumns = 10, + sortMethod = "quality", -- quality, name, type + iconSize = 40, + iconSpacing = 0, + iconFontSize = 12, + }, + } + end - -- Ensure new settings exist for existing installations - if not Guda_CharDB.settings.bagColumns then - Guda_CharDB.settings.bagColumns = 10 - end - if not Guda_CharDB.settings.bankBagColumns then - Guda_CharDB.settings.bankBagColumns = 8 - end - if not Guda_CharDB.settings.bankColumns then - Guda_CharDB.settings.bankColumns = 10 - end - if not Guda_CharDB.settings.iconSize then - Guda_CharDB.settings.iconSize = 40 - end - if not Guda_CharDB.settings.iconSpacing then - Guda_CharDB.settings.iconSpacing = 0 - end - if not Guda_CharDB.settings.iconFontSize then - Guda_CharDB.settings.iconFontSize = 12 - end + -- Ensure new settings exist for existing installations + if not Guda_CharDB.settings.bagColumns then + Guda_CharDB.settings.bagColumns = 10 + end + if not Guda_CharDB.settings.bankBagColumns then + Guda_CharDB.settings.bankBagColumns = 8 + end + if not Guda_CharDB.settings.bankColumns then + Guda_CharDB.settings.bankColumns = 10 + end + if not Guda_CharDB.settings.iconSize then + Guda_CharDB.settings.iconSize = 40 + end + if not Guda_CharDB.settings.iconSpacing then + Guda_CharDB.settings.iconSpacing = 0 + end + if not Guda_CharDB.settings.iconFontSize then + Guda_CharDB.settings.iconFontSize = 12 + end - -- Initialize this character's data - if not Guda_DB.characters[fullName] then - local localizedClass, englishClass = UnitClass("player") - Guda_DB.characters[fullName] = { - name = playerName, - realm = playerRealm, - faction = playerFaction, - class = localizedClass, - classToken = englishClass, -- English uppercase token for RAID_CLASS_COLORS - level = UnitLevel("player"), - money = 0, - bags = {}, - bank = {}, - lastUpdate = time(), - } - else - -- Migration: Add classToken to existing characters - local char = Guda_DB.characters[fullName] - if not char.classToken then - local localizedClass, englishClass = UnitClass("player") - char.classToken = englishClass - addon:Debug("Added classToken to existing character") - end - end + -- Initialize this character's data + if not Guda_DB.characters[fullName] then + local localizedClass, englishClass = UnitClass("player") + Guda_DB.characters[fullName] = { + name = playerName, + realm = playerRealm, + faction = playerFaction, + class = localizedClass, + classToken = englishClass, -- English uppercase token for RAID_CLASS_COLORS + level = UnitLevel("player"), + money = 0, + bags = {}, + bank = {}, + equipped = {}, -- Add equipped items storage + character = {}, -- Add character info storage + lastUpdate = time(), + } + else + -- Migration: Add classToken to existing characters + local char = Guda_DB.characters[fullName] + if not char.classToken then + local localizedClass, englishClass = UnitClass("player") + char.classToken = englishClass + addon:Debug("Added classToken to existing character") + end - addon:Debug("Database initialized for %s", fullName) + -- Migration: Add equipped and character fields if they don't exist + if not char.equipped then + char.equipped = {} + addon:Debug("Added equipped field to existing character") + end + if not char.character then + char.character = {} + addon:Debug("Added character field to existing character") + end + end + + addon:Debug("Database initialized for %s", fullName) end -- Get current player's full name function DB:GetPlayerFullName() - return playerName .. "-" .. playerRealm + return playerName .. "-" .. playerRealm end -- Get current character data function DB:GetCurrentCharacter() - local fullName = self:GetPlayerFullName() - return Guda_DB.characters[fullName] + local fullName = self:GetPlayerFullName() + return Guda_DB.characters[fullName] +end + +-- Get current character data (alias for compatibility) +function DB:GetCurrentCharacterData() + return self:GetCurrentCharacter() end -- Save bag data function DB:SaveBags(bagData) - local char = self:GetCurrentCharacter() - if char then - char.bags = bagData - char.lastUpdate = time() - addon:Debug("Saved bag data") - end + local char = self:GetCurrentCharacter() + if char then + char.bags = bagData + char.lastUpdate = time() + addon:Debug("Saved bag data") + end end -- Save bank data function DB:SaveBank(bankData) - local char = self:GetCurrentCharacter() - if char then - char.bank = bankData - char.lastUpdate = time() - addon:Debug("Saved bank data") - end + local char = self:GetCurrentCharacter() + if char then + char.bank = bankData + char.lastUpdate = time() + addon:Debug("Saved bank data") + end +end + +-- Save equipment data +function DB:SaveEquipment(equipmentData) + local char = self:GetCurrentCharacter() + if char then + char.equipped = equipmentData.equipped + char.character = equipmentData.character + char.lastUpdate = time() + addon:Debug("Saved equipment data") + end end -- Save money function DB:SaveMoney(copper) - local char = self:GetCurrentCharacter() - if char then - char.money = copper - char.level = UnitLevel("player") - addon:Debug("Saved money: %d copper", copper) - end + local char = self:GetCurrentCharacter() + if char then + char.money = copper + char.level = UnitLevel("player") + addon:Debug("Saved money: %d copper", copper) + end end -- Get all characters (optionally filter by faction) function DB:GetAllCharacters(sameFactionOnly) - local chars = {} - for fullName, data in pairs(Guda_DB.characters) do - if not sameFactionOnly or data.faction == playerFaction then - table.insert(chars, { - fullName = fullName, - name = data.name, - realm = data.realm, - class = data.class, - classToken = data.classToken, -- English uppercase token for colors - level = data.level, - faction = data.faction, - money = data.money, - lastUpdate = data.lastUpdate, - }) - end - end + local chars = {} + for fullName, data in pairs(Guda_DB.characters) do + if not sameFactionOnly or data.faction == playerFaction then + table.insert(chars, { + fullName = fullName, + name = data.name, + realm = data.realm, + class = data.class, + classToken = data.classToken, -- English uppercase token for colors + level = data.level, + faction = data.faction, + money = data.money, + lastUpdate = data.lastUpdate, + }) + end + end - -- Sort by name - table.sort(chars, function(a, b) - return a.name < b.name - end) + -- Sort by name + table.sort(chars, function(a, b) + return a.name < b.name + end) - return chars + return chars end -- Get character's bags function DB:GetCharacterBags(fullName) - local char = Guda_DB.characters[fullName] - return char and char.bags or {} + local char = Guda_DB.characters[fullName] + return char and char.bags or {} end -- Get character's bank function DB:GetCharacterBank(fullName) - local char = Guda_DB.characters[fullName] - return char and char.bank or {} + local char = Guda_DB.characters[fullName] + return char and char.bank or {} +end + +-- Get character's equipped items +function DB:GetCharacterEquipped(fullName) + local char = Guda_DB.characters[fullName] + return char and char.equipped or {} +end + +-- Get character info +function DB:GetCharacterInfo(fullName) + local char = Guda_DB.characters[fullName] + return char and char.character or {} end -- Get total money across all characters function DB:GetTotalMoney(sameFactionOnly) - local total = 0 - for fullName, data in pairs(Guda_DB.characters) do - if not sameFactionOnly or data.faction == playerFaction then - total = total + (data.money or 0) - end - end - return total + local total = 0 + for fullName, data in pairs(Guda_DB.characters) do + if not sameFactionOnly or data.faction == playerFaction then + total = total + (data.money or 0) + end + end + return total end -- Get character setting function DB:GetSetting(key) - -- SavedVariables may not be initialized yet when some UI OnLoad scripts run - if not Guda_CharDB or not Guda_CharDB.settings then - return nil - end - return Guda_CharDB.settings[key] +-- SavedVariables may not be initialized yet when some UI OnLoad scripts run + if not Guda_CharDB or not Guda_CharDB.settings then + return nil + end + return Guda_CharDB.settings[key] end -- Set character setting function DB:SetSetting(key, value) - -- Ensure tables exist even if called early - if not Guda_CharDB then - Guda_CharDB = { settings = {} } - elseif not Guda_CharDB.settings then - Guda_CharDB.settings = {} - end - Guda_CharDB.settings[key] = value +-- Ensure tables exist even if called early + if not Guda_CharDB then + Guda_CharDB = { settings = {} } + elseif not Guda_CharDB.settings then + Guda_CharDB.settings = {} + end + Guda_CharDB.settings[key] = value end -- Cleanup old characters (not updated in 90 days) function DB:CleanupOldCharacters() - local cutoff = time() - (90 * 24 * 60 * 60) -- 90 days - local removed = 0 + local cutoff = time() - (90 * 24 * 60 * 60) -- 90 days + local removed = 0 - for fullName, data in pairs(Guda_DB.characters) do - if data.lastUpdate and data.lastUpdate < cutoff then - Guda_DB.characters[fullName] = nil - removed = removed + 1 - end - end + for fullName, data in pairs(Guda_DB.characters) do + if data.lastUpdate and data.lastUpdate < cutoff then + Guda_DB.characters[fullName] = nil + removed = removed + 1 + end + end - if removed > 0 then - addon:Print("Cleaned up %d old character(s)", removed) - end -end + if removed > 0 then + addon:Print("Cleaned up %d old character(s)", removed) + end +end \ No newline at end of file diff --git a/Core/Main.lua b/Core/Main.lua index 3b123f6..837fd45 100644 --- a/Core/Main.lua +++ b/Core/Main.lua @@ -37,6 +37,7 @@ function Main:Initialize() addon.Modules.BagScanner:Initialize() addon.Modules.BankScanner:Initialize() addon.Modules.MoneyTracker:Initialize() + addon.Modules.EquipmentScanner:Initialize() -- Initialize UI addon.Modules.BagFrame:Initialize() diff --git a/Core/Tooltip.lua b/Core/Tooltip.lua index 372f72a..82772d8 100644 --- a/Core/Tooltip.lua +++ b/Core/Tooltip.lua @@ -16,6 +16,7 @@ end local function CountItemsForCharacter(itemID, characterData) local bagCount = 0 local bankCount = 0 + local equippedCount = 0 -- Count bags if characterData.bags then @@ -49,7 +50,19 @@ local function CountItemsForCharacter(itemID, characterData) end end - return bagCount, bankCount + -- Count equipped items from EquipmentScanner data + if characterData.equipped then + for slotName, itemData in pairs(characterData.equipped) do + if itemData and itemData.link then + local slotItemID = GetItemIDFromLink(itemData.link) + if slotItemID == itemID then + equippedCount = equippedCount + 1 + end + end + end + end + + return bagCount, bankCount, equippedCount -- FIXED: Now returns all three counts end -- Get class color @@ -60,6 +73,7 @@ local function GetClassColor(classToken) return 1.0, 1.0, 1.0 end +-- Add inventory info to tooltip -- Add inventory info to tooltip function Tooltip:AddInventoryInfo(tooltip, link) if not Guda_DB or not Guda_DB.characters then @@ -77,53 +91,79 @@ function Tooltip:AddInventoryInfo(tooltip, link) local totalBags = 0 local totalBank = 0 + local totalEquipped = 0 local characterCounts = {} + local hasAnyItems = false -- Count items across all characters for charName, charData in pairs(Guda_DB.characters) do - local bagCount, bankCount = CountItemsForCharacter(itemID, charData) - totalBags = totalBags + bagCount - totalBank = totalBank + bankCount - table.insert(characterCounts, { - name = charData.name or charName, - classToken = charData.classToken, - bagCount = bagCount, - bankCount = bankCount - }) - addon:Debug("Found " .. (bagCount + bankCount) .. " items on " .. charName .. " (Bags: " .. bagCount .. ", Bank: " .. bankCount .. ")") - end + local bagCount, bankCount, equippedCount = CountItemsForCharacter(itemID, charData) - local totalCount = totalBags + totalBank - - -- ALWAYS add to tooltip, even if 0 items - addon:Debug("Adding inventory info - Total: " .. totalCount) - - tooltip:AddLine(" ") - tooltip:AddLine("Inventory", 0.7, 0.7, 0.7) - tooltip:AddDoubleLine("Total: " .. totalCount, "(Bags: " .. totalBags .. " | Bank: " .. totalBank .. ")", 1, 1, 1, 0.7, 0.7, 0.7) - - -- Sort characters by name - table.sort(characterCounts, function(a, b) - return a.name < b.name - end) - - -- Add character lines with bag and bank breakdown - for _, charInfo in ipairs(characterCounts) do - local r, g, b = GetClassColor(charInfo.classToken) - local countText = "" - if charInfo.bagCount > 0 and charInfo.bankCount > 0 then - countText = "Bags: " .. charInfo.bagCount .. " | Bank: " .. charInfo.bankCount - elseif charInfo.bagCount > 0 then - countText = "Bags: " .. charInfo.bagCount - else - countText = "Bank: " .. charInfo.bankCount + -- Check if this character has any of this item + if bagCount > 0 or bankCount > 0 or equippedCount > 0 then + hasAnyItems = true + totalBags = totalBags + bagCount + totalBank = totalBank + bankCount + totalEquipped = totalEquipped + equippedCount + table.insert(characterCounts, { + name = charData.name or charName, + classToken = charData.classToken, + bagCount = bagCount, + bankCount = bankCount, + equippedCount = equippedCount + }) + addon:Debug("Found " .. (bagCount + bankCount + equippedCount) .. " items on " .. charName .. " (Bags: " .. bagCount .. ", Bank: " .. bankCount .. ", Equipped: " .. equippedCount .. ")") end - tooltip:AddDoubleLine(charInfo.name, countText, r, g, b, 0.7, 0.7, 0.7) end - tooltip:Show() -end + local totalCount = totalBags + totalBank + totalEquipped + -- Only add to tooltip if we found items on any character + if hasAnyItems then + addon:Debug("Adding inventory info - Total: " .. totalCount) + + tooltip:AddLine(" ") + tooltip:AddLine("Inventory", 0.7, 0.7, 0.7) + + -- Simplified total line - just show total count without breakdown + tooltip:AddDoubleLine("Total: " .. totalCount, "(Bags: " .. totalBags .. " | Bank: " .. totalBank .. ")", 1, 1, 1, 0.7, 0.7, 0.7) + + -- Sort characters by name + table.sort(characterCounts, function(a, b) + return a.name < b.name + end) + + -- Add character lines with bag, bank, and equipped breakdown + for _, charInfo in ipairs(characterCounts) do + local r, g, b = GetClassColor(charInfo.classToken) + local countText = "" + + -- Build count text showing all locations where items are found + local parts = {} + if charInfo.bagCount > 0 then + table.insert(parts, "Bags: " .. charInfo.bagCount) + end + if charInfo.bankCount > 0 then + table.insert(parts, "Bank: " .. charInfo.bankCount) + end + if charInfo.equippedCount > 0 then + table.insert(parts, "Equipped: " .. charInfo.equippedCount) + end + + if getn(parts) > 0 then + countText = table.concat(parts, " | ") + else + countText = "None" + end + + tooltip:AddDoubleLine(charInfo.name, countText, r, g, b, 0.7, 0.7, 0.7) + end + + tooltip:Show() + else + addon:Debug("No items found for ID: " .. itemID .. " on any character") + end +end function Tooltip:Initialize() addon:Print("Initializing tooltip module...") diff --git a/Data/EquipmentScanner.lua b/Data/EquipmentScanner.lua new file mode 100644 index 0000000..f5ed3ef --- /dev/null +++ b/Data/EquipmentScanner.lua @@ -0,0 +1,116 @@ +-- Guda Equipment Scanner +-- Scans and stores character equipment information + +local addon = Guda + +local EquipmentScanner = {} +addon.Modules.EquipmentScanner = EquipmentScanner + +local playerLoggedIn = false + +-- Scan all equipment and return data +function EquipmentScanner:ScanAll() + local equipmentData = { + equipped = self:ScanEquippedItems(), + character = self:ScanCharacterInfo(), + lastUpdated = time() + } + + return equipmentData +end + +-- Scan all equipped items +function EquipmentScanner:ScanEquippedItems() + local equipped = {} + + -- List of equipment slots to scan + local equipmentSlots = { + "HeadSlot", "NeckSlot", "ShoulderSlot", "BackSlot", "ChestSlot", "ShirtSlot", + "TabardSlot", "WristSlot", "HandsSlot", "WaistSlot", "LegsSlot", "FeetSlot", + "Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot", + "MainHandSlot", "SecondaryHandSlot", "RangedSlot", "AmmoSlot" + } + + for _, slotName in ipairs(equipmentSlots) do + local slotID = GetInventorySlotInfo(slotName) + local itemLink = GetInventoryItemLink("player", slotID) + + if itemLink then + local itemName = GetItemInfo(itemLink) + equipped[slotName] = { + link = itemLink, + name = itemName, + texture = GetInventoryItemTexture("player", slotID) + } + end + end + + return equipped +end + +-- Scan character info (level, class, etc.) - Lua 5.0 compatible +function EquipmentScanner:ScanCharacterInfo() + local name = UnitName("player") + local realm = GetRealmName() + + -- Lua 5.0: UnitClass returns multiple values, not a table + local class, classToken = UnitClass("player") + local level = UnitLevel("player") + local race = UnitRace("player") + + return { + name = name, + realm = realm, + class = class, + classToken = classToken, + level = level, + race = race, + lastSeen = time() + } +end + +-- Save current equipment to database +function EquipmentScanner:SaveToDatabase() + if not playerLoggedIn then + return + end + + local equipmentData = self:ScanAll() + addon.Modules.DB:SaveEquipment(equipmentData) + addon:Debug("Equipment data saved") +end + +-- Initialize equipment scanner +function EquipmentScanner:Initialize() + -- Player logged in - save equipment data + addon.Modules.Events:OnPlayerLogin(function() + playerLoggedIn = true + addon:Print("Scanning equipped items...") + + -- Delay scan to ensure character is fully loaded + local frame = CreateFrame("Frame") + local elapsed = 0 + frame:SetScript("OnUpdate", function() + elapsed = elapsed + arg1 + if elapsed >= 2.0 then + frame:SetScript("OnUpdate", nil) + EquipmentScanner:SaveToDatabase() + addon:Print("Equipped items scanned and saved!") + end + end) + end, "EquipmentScanner") + + -- Equipment changed + addon.Modules.Events:Register("PLAYER_EQUIPMENT_CHANGED", function() + if playerLoggedIn then + EquipmentScanner:SaveToDatabase() + end + end, "EquipmentScanner") + + addon:Print("EquipmentScanner initialized successfully") +end + +-- Check if player is logged in +function EquipmentScanner:IsPlayerLoggedIn() + return playerLoggedIn +end \ No newline at end of file diff --git a/Guda.toc b/Guda.toc index 7ad2797..e6fc784 100644 --- a/Guda.toc +++ b/Guda.toc @@ -15,6 +15,7 @@ Core\Tooltip.lua Data\BagScanner.lua Data\BankScanner.lua Data\MoneyTracker.lua +Data\EquipmentScanner.lua Sorting\SortEngine.lua