From e810e40a67ece6e21da3f14288c5878cf367f315 Mon Sep 17 00:00:00 2001 From: Salikh Gurgenidze Date: Thu, 22 Jan 2026 03:41:18 +0400 Subject: [PATCH] feat: track quest items in questItemBar --- Core/Utils.lua | 43 ++++++++++++++++++++++ UI/ItemButton.lua | 18 +++++++--- UI/SettingsPopup.lua | 58 +++++++++++++++++++++++++++--- UI/SettingsPopup.xml | 26 ++++++++++++-- UI/TrackedItemBar.lua | 83 +++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 213 insertions(+), 15 deletions(-) diff --git a/Core/Utils.lua b/Core/Utils.lua index 5875a54..29a9b9a 100644 --- a/Core/Utils.lua +++ b/Core/Utils.lua @@ -692,6 +692,49 @@ function Utils:IsBindOnEquip(bagID, slotID, itemLink) return false end +-- Check if an item is "Unique" by scanning its tooltip +function Utils:IsUniqueItem(bagID, slotID, itemLink) + if not bagID or not slotID then return false end + + local tooltip = GetScanTooltip() + if not tooltip then return false end + + tooltip:ClearLines() + + -- Try SetBagItem first (works for regular bags and bank when open) + tooltip:SetBagItem(bagID, slotID) + + local numLines = tooltip:NumLines() + + -- If no lines and we have itemLink, try SetHyperlink with itemString as fallback + if (not numLines or numLines == 0) and itemLink then + local _, _, itemString = string.find(itemLink, "(item:%d+:%d+:%d+:%d+)") + if itemString then + tooltip:ClearLines() + tooltip:SetHyperlink(itemString) + numLines = tooltip:NumLines() + end + end + + if not numLines or numLines == 0 then return false end + + -- Check tooltip lines for "Unique" (but not "Unique-Equipped") + for i = 1, numLines do + local line = getglobal("GudaBagScanTooltipTextLeft" .. i) + if line then + local text = line:GetText() + if text then + local textLower = string.lower(text) + -- Match "unique" but not "unique-equipped" + if textLower == "unique" or string.find(textLower, "^unique$") or string.find(textLower, "^unique%s") then + return true + end + end + end + end + return false +end + -- Check if an item is equipment (armor, weapon, or other equippable) -- Returns: true if item is equipment, false otherwise function Utils:IsEquipment(itemLink) diff --git a/UI/ItemButton.lua b/UI/ItemButton.lua index 95bcef4..cc820da 100644 --- a/UI/ItemButton.lua +++ b/UI/ItemButton.lua @@ -304,11 +304,15 @@ function Guda_ItemButton_OnLoad(self) local itemID = addon.Modules.Utils:ExtractItemID(link) if itemID then local isQuest = IsQuestItem(this.bagID, this.slotID, this.isBank) - if isQuest and addon.Modules.QuestItemBar and addon.Modules.QuestItemBar.PinItem then + local isUnique = addon.Modules.Utils:IsUniqueItem(this.bagID, this.slotID, link) + + -- Only pin to QuestItemBar if it's a unique quest item + if isQuest and isUnique and addon.Modules.QuestItemBar and addon.Modules.QuestItemBar.PinItem then addon.Modules.QuestItemBar:PinItem(itemID) return end - + + -- Track non-unique quest items and regular items in TrackedItemBar local trackedItems = addon.Modules.DB:GetSetting("trackedItems") or {} if trackedItems[itemID] then trackedItems[itemID] = nil @@ -316,7 +320,7 @@ function Guda_ItemButton_OnLoad(self) 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() @@ -929,8 +933,12 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha -- Search filtering and junk opacity if matchesFilter then if isJunk then - -- Junk items: 60% opacity - self:SetAlpha(0.6) + -- Junk items: configurable opacity (default 60%) + local junkOpacity = 0.6 + if addon.Modules.DB and addon.Modules.DB.GetSetting then + junkOpacity = addon.Modules.DB:GetSetting("junkOpacity") or 0.6 + end + self:SetAlpha(junkOpacity) else -- Normal items: full opacity (1.0) self:SetAlpha(1.0) diff --git a/UI/SettingsPopup.lua b/UI/SettingsPopup.lua index 9304b71..601b4b8 100644 --- a/UI/SettingsPopup.lua +++ b/UI/SettingsPopup.lua @@ -36,11 +36,7 @@ function Guda_SettingsPopup_OnLoad(self) "Left Click on an item in the bar to use it.\n" .. "Alt + Left Click on an item in the bar to untrack it.\n\n" .. "|cffffd100Moving Bars:|r\n" .. - "Shift + Left Click and drag any item on the Quest Item Bar or Tracked Item Bar to move the bar.\n" .. - "You can also drag the bar background if it's visible.\n\n" .. - "|cffffd100Quest Item Bar:|r\n" .. - "Alt + Left Click on a quest item in your bags to pin it.\n" .. - "Alt + Right Click on an item in the bar to unpin it." + "Shift + Left Click and drag any item on the Quest Item Bar or Tracked Item Bar to move the bar.\n" instructions:SetText(text) end @@ -132,6 +128,7 @@ function Guda_SettingsPopup_OnShow(self) local bankViewType = Guda.Modules.DB:GetSetting("bankViewType") or "single" local questBarSize = Guda.Modules.DB:GetSetting("questBarSize") or 36 local trackedBarSize = Guda.Modules.DB:GetSetting("trackedBarSize") or 36 + local junkOpacity = Guda.Modules.DB:GetSetting("junkOpacity") or 0.6 -- Update sliders and checkboxes local bagSlider = getglobal("Guda_SettingsPopup_BagColumnsSlider") @@ -142,6 +139,7 @@ function Guda_SettingsPopup_OnShow(self) local bgTransparencySlider = getglobal("Guda_SettingsPopup_BgTransparencySlider") local questBarSizeSlider = getglobal("Guda_SettingsPopup_QuestBarSizeSlider") local trackedBarSizeSlider = getglobal("Guda_SettingsPopup_TrackedBarSizeSlider") + local junkOpacitySlider = getglobal("Guda_SettingsPopup_JunkOpacitySlider") local lockCheckbox = getglobal("Guda_SettingsPopup_LockBagsCheckbox") local hideBordersCheckbox = getglobal("Guda_SettingsPopup_HideBordersCheckbox") local qualityBorderEquipmentCheckbox = getglobal("Guda_SettingsPopup_QualityBorderEquipmentCheckbox") @@ -191,6 +189,10 @@ function Guda_SettingsPopup_OnShow(self) trackedBarSizeSlider:SetValue(trackedBarSize) end + if junkOpacitySlider then + junkOpacitySlider:SetValue(junkOpacity) + end + if lockCheckbox then lockCheckbox:SetChecked(lockBags and 1 or 0) end @@ -1046,6 +1048,52 @@ function Guda_SettingsPopup_ShowTooltipCountsCheckbox_OnClick(self) end end +-- Junk Opacity Slider OnLoad +function Guda_SettingsPopup_JunkOpacitySlider_OnLoad(self) + getglobal(self:GetName().."Low"):SetText("10%") + getglobal(self:GetName().."High"):SetText("100%") + + local text = getglobal(self:GetName().."Text") + text:SetText("Junk item opacity") + + -- Increase font size + local font, _, flags = text:GetFont() + if font then + text:SetFont(font, 12, flags) + end + + self:SetMinMaxValues(0.1, 1.0) + self:SetValueStep(0.05) + + local currentValue = Guda.Modules.DB:GetSetting("junkOpacity") or 0.6 + self:SetValue(currentValue) +end + +-- Junk Opacity Slider OnValueChanged +function Guda_SettingsPopup_JunkOpacitySlider_OnValueChanged(self) + local value = self:GetValue() + -- Round to 2 decimal places + value = math.floor(value * 100 + 0.5) / 100 + + -- Update display text + getglobal(self:GetName().."Text"):SetText("Junk item opacity: " .. math.floor(value * 100) .. "%") + + -- Save setting + Guda.Modules.DB:SetSetting("junkOpacity", value) + + -- Update bag frame if visible + local bagFrame = getglobal("Guda_BagFrame") + if bagFrame and bagFrame:IsShown() then + Guda.Modules.BagFrame:Update() + end + + -- Update bank frame if visible + local bankFrame = getglobal("Guda_BankFrame") + if bankFrame and bankFrame:IsShown() then + Guda.Modules.BankFrame:Update() + end +end + -- Mark Unusable Items Checkbox OnLoad function Guda_SettingsPopup_MarkUnusableCheckbox_OnLoad(self) local text = getglobal(self:GetName().."Text") diff --git a/UI/SettingsPopup.xml b/UI/SettingsPopup.xml index 7866654..4a26cd7 100644 --- a/UI/SettingsPopup.xml +++ b/UI/SettingsPopup.xml @@ -3,7 +3,7 @@ - + @@ -554,10 +554,32 @@ + + + + + + + + + + + + + + + Guda_SettingsPopup_JunkOpacitySlider_OnLoad(this) + + + Guda_SettingsPopup_JunkOpacitySlider_OnValueChanged(this) + + + + - + diff --git a/UI/TrackedItemBar.lua b/UI/TrackedItemBar.lua index d3a227e..a42416c 100644 --- a/UI/TrackedItemBar.lua +++ b/UI/TrackedItemBar.lua @@ -21,15 +21,25 @@ local function GetScanTooltip() return scanTooltip end +-- Check if an item is a quest item by scanning tooltip +local function IsQuestItem(bagID, slotID) + if addon.Modules.Utils and addon.Modules.Utils.IsQuestItem then + return addon.Modules.Utils:IsQuestItem(bagID, slotID, nil, false, false) + end + return false, false +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 = {} + local itemIsQuest = {} + local itemIsQuestStarter = {} -- Scan backpack and 4 bags for bagID = 0, 4 do @@ -46,6 +56,10 @@ function TrackedItemBar:ScanForTrackedItems() itemLinks[id] = link itemCounts[id .. "_bag"] = bagID itemCounts[id .. "_slot"] = slotID + -- Check if quest item + local isQuest, isStarter = IsQuestItem(bagID, slotID) + itemIsQuest[id] = isQuest + itemIsQuestStarter[id] = isStarter table.insert(itemOrder, id) end itemCounts[id] = itemCounts[id] + count @@ -61,7 +75,9 @@ function TrackedItemBar:ScanForTrackedItems() count = itemCounts[id], link = itemLinks[id], bagID = itemCounts[id .. "_bag"], - slotID = itemCounts[id .. "_slot"] + slotID = itemCounts[id .. "_slot"], + isQuest = itemIsQuest[id], + isQuestStarter = itemIsQuestStarter[id] }) end end @@ -92,7 +108,32 @@ function TrackedItemBar:Update() if not button then button = CreateFrame("Button", "Guda_TrackedItemBarButton" .. i, frame, "Guda_ItemButtonTemplate") table.insert(buttons, button) - + + -- Create quest border (golden) + local questBorder = CreateFrame("Frame", nil, button) + questBorder:SetFrameLevel(button:GetFrameLevel() + 6) + questBorder:SetBackdrop({ + bgFile = nil, + edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", + edgeSize = 12, + insets = {left = 4, right = 4, top = 4, bottom = 4} + }) + questBorder:SetBackdropBorderColor(1.0, 0.82, 0, 1) + questBorder:Hide() + button.questBorder = questBorder + + -- Create quest icon (question mark in corner) + local questIcon = CreateFrame("Frame", nil, button) + questIcon:SetFrameLevel(button:GetFrameLevel() + 7) + questIcon:SetWidth(16) + questIcon:SetHeight(16) + local iconTex = questIcon:CreateTexture(nil, "OVERLAY") + iconTex:SetAllPoints(questIcon) + iconTex:SetTexture("Interface\\GossipFrame\\ActiveQuestIcon") + iconTex:SetTexCoord(0, 1, 0, 1) + questIcon:Hide() + button.questIcon = questIcon + button:RegisterForDrag("LeftButton") button:SetScript("OnDragStart", function() end) button:SetScript("OnReceiveDrag", function() end) @@ -190,6 +231,42 @@ function TrackedItemBar:Update() emptyBg:SetHeight(buttonSize) end + -- Position and show/hide quest border + if button.questBorder then + button.questBorder:ClearAllPoints() + button.questBorder:SetPoint("TOPLEFT", icon, "TOPLEFT", -2, 2) + button.questBorder:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", 2, -2) + if info.isQuest then + button.questBorder:Show() + else + button.questBorder:Hide() + end + end + + -- Position and show/hide quest icon + if button.questIcon then + local questIconSize = math.max(12, math.min(20, buttonSize * 0.35)) + button.questIcon:SetWidth(questIconSize) + button.questIcon:SetHeight(questIconSize) + button.questIcon:ClearAllPoints() + button.questIcon:SetPoint("TOPRIGHT", button, "TOPRIGHT", 1, 0) + + if info.isQuest then + -- Set appropriate texture based on quest type + local tex = button.questIcon:GetRegions() + if tex and tex.SetTexture then + if info.isQuestStarter then + tex:SetTexture("Interface\\GossipFrame\\AvailableQuestIcon") + else + tex:SetTexture("Interface\\GossipFrame\\ActiveQuestIcon") + end + end + button.questIcon:Show() + else + button.questIcon:Hide() + end + end + button:Show() end