From bd8ac3e4b01d899a9afff59f4e66eef5aef0f09a Mon Sep 17 00:00:00 2001 From: Salikh Gurgenidze Date: Tue, 23 Dec 2025 03:56:36 +0400 Subject: [PATCH] feat: track items for grinding --- Core/Database.lua | 8 ++ Core/Init.lua | 1 + Core/Main.lua | 18 ++++ Guda.toc | 1 + UI/ItemButton.lua | 53 +++++++++++ UI/ItemButton.xml | 8 ++ UI/SettingsPopup.lua | 34 +++++++ UI/SettingsPopup.xml | 19 ++++ UI/TrackedItemBar.lua | 207 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 349 insertions(+) create mode 100644 UI/TrackedItemBar.lua diff --git a/Core/Database.lua b/Core/Database.lua index 279673e..5f192eb 100644 --- a/Core/Database.lua +++ b/Core/Database.lua @@ -45,6 +45,8 @@ function DB:Initialize() hoverBagline = false, hideFooter = false, bgTransparency = 0.15, + showTrackedItems = false, + trackedItems = {}, }, } end @@ -67,6 +69,12 @@ function DB:Initialize() if Guda_CharDB.settings.showQuestBar == nil then Guda_CharDB.settings.showQuestBar = true end + if Guda_CharDB.settings.showTrackedItems == nil then + Guda_CharDB.settings.showTrackedItems = false + end + if Guda_CharDB.settings.trackedItems == nil then + Guda_CharDB.settings.trackedItems = {} + end if not Guda_CharDB.settings.bagColumns then Guda_CharDB.settings.bagColumns = 10 end diff --git a/Core/Init.lua b/Core/Init.lua index da08e48..8944e2e 100644 --- a/Core/Init.lua +++ b/Core/Init.lua @@ -108,6 +108,7 @@ addon.Modules = { BagFrame = {}, BankFrame = {}, QuestItemBar = {}, + TrackedItemBar = {}, SettingsPopup = {}, } diff --git a/Core/Main.lua b/Core/Main.lua index 5ac2448..ef066a6 100644 --- a/Core/Main.lua +++ b/Core/Main.lua @@ -40,6 +40,15 @@ function Main:Initialize() addon:Error("QuestItemBar module file failed to load (isLoaded is nil)!") end end + + addon:Debug("Checking TrackedItemBar module...") + if addon.Modules.TrackedItemBar and addon.Modules.TrackedItemBar.isLoaded then + addon:Debug("TrackedItemBar module found and loaded, initializing...") + local success, err = pcall(function() addon.Modules.TrackedItemBar:Initialize() end) + if not success then + addon:Error("Failed to initialize TrackedItemBar: %s", tostring(err)) + end + end addon.Modules.SettingsPopup:Initialize() @@ -114,6 +123,14 @@ function Main:SetupSlashCommands() addon.Modules.QuestItemBar:Update() addon:Print("Quest bar: %s", show and "ON" or "OFF") + elseif msg == "track" then + -- Toggle tracked items + local show = not addon.Modules.DB:GetSetting("showTrackedItems") + addon.Modules.DB:SetSetting("showTrackedItems", show) + if addon.Modules.TrackedItemBar then addon.Modules.TrackedItemBar:Update() end + if addon.Modules.BagFrame then addon.Modules.BagFrame:Update() end + addon:Print("Track items: %s", show and "ON" or "OFF") + elseif msg == "cleanup" then -- Cleanup old characters addon.Modules.DB:CleanupOldCharacters() @@ -125,6 +142,7 @@ function Main:SetupSlashCommands() addon:Print("/guda bank - Toggle bank") addon:Print("/guda sort - Sort bags") addon:Print("/guda sortbank - Sort bank") + addon:Print("/guda track - Toggle item tracking") addon:Print("/guda debug - Toggle debug mode") addon:Print("/guda cleanup - Remove old characters") diff --git a/Guda.toc b/Guda.toc index e6ff4e8..c1add05 100644 --- a/Guda.toc +++ b/Guda.toc @@ -26,6 +26,7 @@ UI\ItemButton.lua UI\BagFrame.lua UI\BankFrame.lua UI\QuestItemBar.lua +UI\TrackedItemBar.lua UI\SettingsPopup.lua UI\ItemButton.xml UI\BagFrame.xml diff --git a/UI/ItemButton.lua b/UI/ItemButton.lua index 90ff141..0cb7e18 100644 --- a/UI/ItemButton.lua +++ b/UI/ItemButton.lua @@ -540,6 +540,27 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha end end + -- Update tracking checkmark + local check = getglobal(self:GetName().."_Check") + if check then + local isTracked = false + if self.hasItem and addon.Modules.DB:GetSetting("showTrackedItems") then + local itemID = addon.Modules.Utils:ExtractItemID(self.itemData and self.itemData.link) + if itemID then + local trackedItems = addon.Modules.DB:GetSetting("trackedItems") or {} + if trackedItems[itemID] then + isTracked = true + end + end + end + + if isTracked then + check:Show() + else + check:Hide() + end + end + -- Resize empty slot background to match icon size (slightly larger to ensure coverage) if emptySlotBg then emptySlotBg:ClearAllPoints() @@ -746,6 +767,38 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha end end + -- Handle tracking toggle on click + if not self.isReadOnly and not self.otherChar then + local old_OnClick = self:GetScript("OnClick") + self:SetScript("OnClick", function() + if IsControlKeyDown() and addon.Modules.DB:GetSetting("showTrackedItems") then + local itemID = addon.Modules.Utils:ExtractItemID(GetContainerItemLink(this:GetParent():GetID(), this:GetID())) + if itemID then + local trackedItems = addon.Modules.DB:GetSetting("trackedItems") or {} + if trackedItems[itemID] then + trackedItems[itemID] = nil + else + trackedItems[itemID] = true + end + addon.Modules.DB:SetSetting("trackedItems", trackedItems) + + -- Update all item buttons + if Guda.Modules.BagFrame and Guda.Modules.BagFrame.Update then + Guda.Modules.BagFrame:Update() + end + if Guda.Modules.BankFrame and Guda.Modules.BankFrame.Update then + Guda.Modules.BankFrame:Update() + end + if Guda.Modules.TrackedItemBar and Guda.Modules.TrackedItemBar.Update then + Guda.Modules.TrackedItemBar:Update() + end + end + elseif old_OnClick then + old_OnClick() + end + end) + end + self:Show() else self.hasItem = false diff --git a/UI/ItemButton.xml b/UI/ItemButton.xml index cc0affb..f2de72a 100644 --- a/UI/ItemButton.xml +++ b/UI/ItemButton.xml @@ -28,6 +28,14 @@ + diff --git a/UI/SettingsPopup.lua b/UI/SettingsPopup.lua index c2ab35e..a0f7039 100644 --- a/UI/SettingsPopup.lua +++ b/UI/SettingsPopup.lua @@ -65,6 +65,10 @@ function Guda_SettingsPopup_OnShow(self) if hoverBagline == nil then hoverBagline = false end + local showTrackedItems = Guda.Modules.DB:GetSetting("showTrackedItems") + if showTrackedItems == nil then + showTrackedItems = false + end local bgTransparency = Guda.Modules.DB:GetSetting("bgTransparency") or 0.15 -- Update sliders and checkboxes @@ -81,6 +85,7 @@ function Guda_SettingsPopup_OnShow(self) local showSearchBarCheckbox = getglobal("Guda_SettingsPopup_ShowSearchBarCheckbox") local showQuestBarCheckbox = getglobal("Guda_SettingsPopup_ShowQuestBarCheckbox") local hoverBaglineCheckbox = getglobal("Guda_SettingsPopup_HoverBaglineCheckbox") + local showTrackedItemsCheckbox = getglobal("Guda_SettingsPopup_ShowTrackedItemsCheckbox") if bagSlider then bagSlider:SetValue(bagColumns) @@ -134,6 +139,10 @@ function Guda_SettingsPopup_OnShow(self) hoverBaglineCheckbox:SetChecked(hoverBagline and 1 or 0) end + if showTrackedItemsCheckbox then + showTrackedItemsCheckbox:SetChecked(showTrackedItems and 1 or 0) + end + -- Update display (might be too tall for current frame size) local frame = getglobal("Guda_SettingsPopup") if frame then @@ -809,3 +818,28 @@ end function SettingsPopup:Initialize() Guda:Debug("Settings popup initialized") end + +-- Show Tracked Items Checkbox OnLoad +function Guda_SettingsPopup_ShowTrackedItemsCheckbox_OnLoad(self) + getglobal(self:GetName().."Text"):SetText("Track items") + local currentValue = Guda.Modules.DB:GetSetting("showTrackedItems") + if currentValue == nil then + currentValue = false + end + self:SetChecked(currentValue and 1 or 0) +end + +-- Show Tracked Items Checkbox OnClick +function Guda_SettingsPopup_ShowTrackedItemsCheckbox_OnClick(self) + local isChecked = self:GetChecked() + Guda.Modules.DB:SetSetting("showTrackedItems", isChecked == 1) + + if Guda.Modules.TrackedItemBar and Guda.Modules.TrackedItemBar.Update then + Guda.Modules.TrackedItemBar:Update() + end + + -- Refresh bag frame to show/hide checkmarks + if Guda.Modules.BagFrame and Guda.Modules.BagFrame.Update then + Guda.Modules.BagFrame:Update() + end +end diff --git a/UI/SettingsPopup.xml b/UI/SettingsPopup.xml index 267ac5a..44d6a00 100644 --- a/UI/SettingsPopup.xml +++ b/UI/SettingsPopup.xml @@ -342,6 +342,25 @@ + + + + + + + + + + + + + Guda_SettingsPopup_ShowTrackedItemsCheckbox_OnLoad(this) + + + Guda_SettingsPopup_ShowTrackedItemsCheckbox_OnClick(this) + + + diff --git a/UI/TrackedItemBar.lua b/UI/TrackedItemBar.lua new file mode 100644 index 0000000..df60234 --- /dev/null +++ b/UI/TrackedItemBar.lua @@ -0,0 +1,207 @@ +-- Guda Tracked Item Bar +-- Displays tracked items with their total bag count + +local addon = Guda +local TrackedItemBar = addon.Modules.TrackedItemBar +if not TrackedItemBar then + TrackedItemBar = {} + addon.Modules.TrackedItemBar = TrackedItemBar +end + +local buttons = {} +local trackedItemsInfo = {} + +-- Create a hidden tooltip for scanning if needed (though we mostly use itemID) +local scanTooltip +local function GetScanTooltip() + if not scanTooltip then + scanTooltip = CreateFrame("GameTooltip", "Guda_TrackedBarScanTooltip", nil, "GameTooltipTemplate") + scanTooltip:SetOwner(WorldFrame, "ANCHOR_NONE") + end + return scanTooltip +end + +-- Scan bags for tracked items and calculate total counts +function TrackedItemBar:ScanForTrackedItems() + trackedItemsInfo = {} + local trackedIDs = addon.Modules.DB:GetSetting("trackedItems") or {} + + local itemCounts = {} + local itemTextures = {} + local itemLinks = {} + local itemOrder = {} + + -- Scan backpack and 4 bags + for bagID = 0, 4 do + local numSlots = GetContainerNumSlots(bagID) + for slotID = 1, numSlots do + local texture, count = GetContainerItemInfo(bagID, slotID) + if texture then + local link = GetContainerItemLink(bagID, slotID) + local id = addon.Modules.Utils:ExtractItemID(link) + if id and trackedIDs[id] then + if not itemCounts[id] then + itemCounts[id] = 0 + itemTextures[id] = texture + itemLinks[id] = link + table.insert(itemOrder, id) + end + itemCounts[id] = itemCounts[id] + count + end + end + end + end + + for _, id in ipairs(itemOrder) do + table.insert(trackedItemsInfo, { + itemID = id, + texture = itemTextures[id], + count = itemCounts[id], + link = itemLinks[id] + }) + end +end + +-- Update the bar buttons +function TrackedItemBar:Update() + local showTrackedItems = addon.Modules.DB:GetSetting("showTrackedItems") + local frame = Guda_TrackedItemBar + + if showTrackedItems == false then + if frame then frame:Hide() end + return + end + + if not frame then return end + frame:Show() + + self:ScanForTrackedItems() + + local buttonSize = 37 + local spacing = 2 + local xOffset = 5 + + -- Hide all buttons initially + for _, btn in ipairs(buttons) do + btn:Hide() + end + + for i, info in ipairs(trackedItemsInfo) do + local button = buttons[i] + if not button then + button = CreateFrame("Button", "Guda_TrackedItemBarButton" .. i, frame, "Guda_ItemButtonTemplate") + table.insert(buttons, button) + + button:RegisterForDrag("LeftButton") + button:SetScript("OnDragStart", function() + if IsShiftKeyDown() then + this:GetParent():StartMoving() + this:GetParent().isMoving = true + end + end) + button:SetScript("OnDragStop", function() + local parent = this:GetParent() + if parent.isMoving then + parent:StopMovingOrSizing() + parent.isMoving = false + local point, _, relativePoint, x, y = parent:GetPoint() + addon.Modules.DB:SetSetting("trackedBarPosition", {point = point, relativePoint = relativePoint, x = x, y = y}) + end + end) + end + + button.hasItem = true + button.itemData = { link = info.link } + button.isReadOnly = true -- Don't allow regular clicks/interaction like usage? + -- Actually user didn't specify usage, but "action bar type" suggests it might be usable. + -- But "tracked items" usually means materials or currencies. + + local icon = getglobal(button:GetName() .. "IconTexture") + icon:SetTexture(info.texture) + icon:SetVertexColor(1.0, 1.0, 1.0, 1.0) + + local countText = getglobal(button:GetName() .. "Count") + countText:SetText(info.count) + countText:Show() + + button:SetScript("OnClick", function() + if IsControlKeyDown() then + -- Un-track item + local trackedIDs = addon.Modules.DB:GetSetting("trackedItems") or {} + trackedIDs[info.itemID] = nil + addon.Modules.DB:SetSetting("trackedItems", trackedIDs) + + -- Update everything + if Guda.Modules.BagFrame and Guda.Modules.BagFrame.Update then + Guda.Modules.BagFrame:Update() + end + TrackedItemBar:Update() + end + end) + + button:SetScript("OnEnter", function() + Guda_ItemButton_OnEnter(this) + end) + + button:SetScript("OnLeave", function() + Guda_ItemButton_OnLeave(this) + end) + + button:ClearAllPoints() + button:SetPoint("LEFT", frame, "LEFT", xOffset + (i-1) * (buttonSize + spacing), 0) + button:Show() + end + + local numItems = table.getn(trackedItemsInfo) + if numItems > 0 then + local newWidth = xOffset * 2 + numItems * (buttonSize + spacing) - spacing + frame:SetWidth(newWidth) + frame:Show() + else + frame:Hide() + end +end + +function TrackedItemBar:Initialize() + local frame = CreateFrame("Frame", "Guda_TrackedItemBar", UIParent) + frame:SetWidth(40) + frame:SetHeight(45) + frame:SetPoint("BOTTOM", UIParent, "BOTTOM", 0, 200) -- Default above quest bar + frame:EnableMouse(true) + frame:SetMovable(true) + frame:SetClampedToScreen(true) + + addon:ApplyBackdrop(frame, "DEFAULT_FRAME") + + -- Handle dragging + frame:RegisterForDrag("LeftButton") + frame:SetScript("OnDragStart", function() + this:StartMoving() + end) + frame:SetScript("OnDragStop", function() + this:StopMovingOrSizing() + local point, _, relativePoint, x, y = this:GetPoint() + addon.Modules.DB:SetSetting("trackedBarPosition", {point = point, relativePoint = relativePoint, x = x, y = y}) + end) + + -- Restore position + local pos = addon.Modules.DB:GetSetting("trackedBarPosition") + if pos and pos.point then + frame:ClearAllPoints() + frame:SetPoint(pos.point, UIParent, pos.relativePoint or pos.point, pos.x, pos.y) + end + + -- Register for events + addon.Modules.Events:Register("BAG_UPDATE", function() + TrackedItemBar:Update() + end, "TrackedItemBar") + + addon.Modules.Events:Register("PLAYER_ENTERING_WORLD", function() + TrackedItemBar:Update() + end, "TrackedItemBar") + + TrackedItemBar:Update() + addon:Debug("TrackedItemBar initialized") +end + +TrackedItemBar.isLoaded = true