diff --git a/Core/CategoryManager.lua b/Core/CategoryManager.lua index 9b8b9fc..de0bbc4 100644 --- a/Core/CategoryManager.lua +++ b/Core/CategoryManager.lua @@ -625,7 +625,11 @@ function CategoryManager:EvaluateRule(rule, itemData, bagID, slotID, isOtherChar elseif ruleType == "isJunk" then -- Junk items: gray items (quality 0) OR white equippable items (quality 1 + Weapon/Armor) - -- EXCLUDES: profession tools (skinning knife, mining pick, fishing poles, etc.) + -- EXCLUDES: + -- 1. Trinkets, Rings, Necklaces (these typically have special effects) + -- 2. Profession tools (skinning knife, mining pick, fishing poles, etc.) + -- 3. Items with yellow description text (Use:, Equip:, Chance on hit: effects) + -- 4. Items with green description text (set bonuses, special properties) local quality = itemData.quality local isGray = false local isWhiteEquip = false @@ -642,9 +646,25 @@ function CategoryManager:EvaluateRule(rule, itemData, bagID, slotID, isOtherChar if quality == 1 then local itemClass = itemData.class or "" local itemSubclass = itemData.subclass or "" - addon:Debug("isJunk check: quality=%s, class='%s', subclass='%s', name='%s'", tostring(quality), tostring(itemClass), tostring(itemSubclass), tostring(itemData.name)) if itemClass == "Weapon" or itemClass == "Armor" then + -- In Turtle WoW, equip slot info is in itemSubType, not itemEquipLoc + local itemSubclass = itemData.subclass or "" + addon:Debug("isJunk check: name='%s', subclass='%s', class='%s'", + tostring(itemData.name), tostring(itemSubclass), tostring(itemClass)) + + -- EXCLUDE: Trinkets, Rings, Necklaces, Tabards, Shirts - these typically have special effects or are cosmetic + -- Check by itemSubType which contains INVTYPE_* values in Turtle WoW + local isSpecialSlot = (itemSubclass == "INVTYPE_TRINKET" or + itemSubclass == "INVTYPE_FINGER" or + itemSubclass == "INVTYPE_NECK" or + itemSubclass == "INVTYPE_TABARD" or + itemSubclass == "INVTYPE_BODY") + if isSpecialSlot then + addon:Debug("isJunk: EXCLUDED (trinket/ring/neck/tabard/shirt) - %s (subclass=%s)", tostring(itemData.name), tostring(itemSubclass)) + return false == ruleValue + end + -- Check if this is a profession tool (should NOT be junk) local isProfessionTool = false @@ -663,7 +683,19 @@ function CategoryManager:EvaluateRule(rule, itemData, bagID, slotID, isOtherChar addon:Debug("isJunk: PROFESSION TOOL (by subtype) - %s", tostring(itemData.name)) end - if not isProfessionTool then + -- Check for special tooltip text (yellow/green descriptions) + -- These items have Use:, Equip:, or special effects and should NOT be junk + local hasSpecialText = false + if not isProfessionTool and not isOtherChar then + if addon.Modules.Utils and addon.Modules.Utils.HasSpecialTooltipText then + hasSpecialText = addon.Modules.Utils:HasSpecialTooltipText(bagID, slotID, itemData.link) + if hasSpecialText then + addon:Debug("isJunk: HAS SPECIAL TEXT (Use:/Equip:/green) - %s", tostring(itemData.name)) + end + end + end + + if not isProfessionTool and not hasSpecialText then isWhiteEquip = true addon:Debug("isJunk: WHITE EQUIP DETECTED - %s", tostring(itemData.name)) end diff --git a/Core/Constants.lua b/Core/Constants.lua index ac33706..8fcf178 100644 --- a/Core/Constants.lua +++ b/Core/Constants.lua @@ -37,20 +37,48 @@ C.HEARTHSTONE_ID = 6948 -- Profession tool item IDs that should NOT be marked as junk -- even though they are white quality equippable items C.PROFESSION_TOOL_IDS = { + -- Skinning [7005] = true, -- Skinning Knife [7812] = true, -- Simple Skinning Knife + [12709] = true, -- Finkle's Skinner + [19901] = true, -- Zulian Slicer + + -- Mining [2901] = true, -- Mining Pick + [778] = true, -- Kobold Mining Shovel + [1959] = true, -- Cold Iron Pick + [9465] = true, -- Digmaster 5000 + + -- Blacksmithing [5956] = true, -- Blacksmith Hammer - [6219] = true, -- Arclight Spanner (Engineering) - [10498] = true, -- Gyromatic Micro-Adjuster (Engineering) - [11590] = true, -- Mechanical Repair Kit (Engineering) - [6218] = true, -- Runed Copper Rod (Enchanting) - [6339] = true, -- Runed Silver Rod (Enchanting) - [11130] = true, -- Runed Golden Rod (Enchanting) - [11145] = true, -- Runed Truesilver Rod (Enchanting) - [16207] = true, -- Runed Arcanite Rod (Enchanting) - [55155] = true, -- Jewelers Kit (Jewelcrafting) - [41328] = true, -- Precision Jewelry Kit (Jewelcrafting) + + -- Engineering + [6219] = true, -- Arclight Spanner + [10498] = true, -- Gyromatic Micro-Adjuster + [11590] = true, -- Mechanical Repair Kit + + -- Enchanting Rods + [6218] = true, -- Runed Copper Rod + [6339] = true, -- Runed Silver Rod + [11130] = true, -- Runed Golden Rod + [11145] = true, -- Runed Truesilver Rod + [16207] = true, -- Runed Arcanite Rod + + -- Fishing (by ID, in case subtype detection fails) + [6256] = true, -- Fishing Pole + [6365] = true, -- Strong Fishing Pole + [6366] = true, -- Darkwood Fishing Pole + [6367] = true, -- Big Iron Fishing Pole + [12225] = true, -- Blump Family Fishing Pole + [19022] = true, -- Nat Pagle's Extreme Angler FC-5000 + [19970] = true, -- Arcanite Fishing Pole + [84660] = true, -- Pandaren Fishing Pole (Turtle WoW) + + -- Jewelcrafting (if applicable) + [55155] = true, -- Jewelers Kit + [41328] = true, -- Precision Jewelry Kit + [20815] = true, -- Jeweler's Kit + [20824] = true, -- Simple Grinder } -- Weapon subtypes that should NOT be marked as junk diff --git a/Core/Main.lua b/Core/Main.lua index 0154442..cff657f 100644 --- a/Core/Main.lua +++ b/Core/Main.lua @@ -145,6 +145,16 @@ function Main:SetupSlashCommands() end end + elseif msg == "settings" or msg == "options" or msg == "config" then + -- Open settings window + if Guda_OpenSettings then + Guda_OpenSettings() + elseif addon.Modules.SettingsPopup and addon.Modules.SettingsPopup.Toggle then + addon.Modules.SettingsPopup:Toggle() + else + addon:Print("Settings window not available") + end + elseif msg == "cleanup" then -- Cleanup old characters addon.Modules.DB:CleanupOldCharacters() @@ -170,6 +180,7 @@ function Main:SetupSlashCommands() addon:Print("/guda - Toggle bags") addon:Print("/guda bank - Toggle bank") addon:Print("/guda mail - Toggle mailbox") + addon:Print("/guda settings - Open settings") addon:Print("/guda sort - Sort bags") addon:Print("/guda sortbank - Sort bank") addon:Print("/guda track - Toggle item tracking") diff --git a/Core/Utils.lua b/Core/Utils.lua index dc8e353..9af3214 100644 --- a/Core/Utils.lua +++ b/Core/Utils.lua @@ -462,6 +462,154 @@ local function GetScanTooltip() return scanTooltip end +-- Helper: Check if a color is yellow/gold (Use:, Equip:, Chance on hit: effects) +-- Yellow in WoW tooltips can be various shades: +-- Gold: RGB ~(1, 0.82, 0) or (255, 209, 0) +-- Yellow: RGB ~(1, 1, 0) +-- Light gold: RGB ~(1, 0.85, 0.1) +local function IsYellowColor(r, g, b) + if not r or not g or not b then return false end + -- Yellow/Gold: high red (>0.8), medium-high green (>0.5), low blue (<0.4) + return r > 0.8 and g > 0.5 and b < 0.4 +end + +-- Helper: Check if a color is green (set bonuses, special properties) +-- Green in WoW tooltips is typically RGB ~(0, 1, 0) or (0.12, 1, 0) +local function IsGreenColor(r, g, b) + if not r or not g or not b then return false end + -- Green: low red (<0.4), high green (>0.7), low blue (<0.4) + return r < 0.4 and g > 0.7 and b < 0.4 +end + +-- Patterns that indicate an item has special functionality (not junk) +local SPECIAL_TEXT_PATTERNS = { + -- Use effects + "use:", + "use :", + -- Equip effects + "equip:", + "equip :", + -- Proc effects + "chance on hit:", + "chance on hit :", + "chance to", + "chance on", + -- Stat effects + "increases", + "improves", + "restores", + "regenerate", + "generates", + "absorbs", + "reduces", + "grants", + "gives", + -- Learning + "teaches", + "learn", + -- Special actions + "creates", + "summons", + "teleports", + "opens", + "activates", + -- Resistance/stats + "resistance", + "armor", + "damage", + "healing", + "mana", + "health", + "spirit", + "intellect", + "stamina", + "strength", + "agility", +} + +-- Check if an item's tooltip contains yellow or green description text +-- This indicates the item has a use effect, equip effect, or special property +-- Returns: hasSpecialText (boolean), textType ("yellow", "green", or nil) +function Utils:HasSpecialTooltipText(bagID, slotID, itemLink) + bagID = tonumber(bagID) + slotID = tonumber(slotID) + + local tooltip = GetScanTooltip() + if not tooltip then return false, nil end + + tooltip:ClearLines() + + -- Set the tooltip to the item + if bagID and slotID then + tooltip:SetBagItem(bagID, slotID) + elseif itemLink then + local _, _, itemString = string.find(itemLink, "(item:%d+:%d+:%d+:%d+)") + if itemString then + tooltip:SetHyperlink(itemString) + else + return false, nil + end + else + return false, nil + end + + local numLines = tooltip:NumLines() or 0 + if numLines == 0 then return false, nil end + + -- Scan tooltip lines for yellow or green text + for i = 2, numLines do -- Start from line 2 (skip item name on line 1) + local leftLine = getglobal("GudaBagScanTooltipTextLeft" .. i) + if leftLine and leftLine:IsShown() then + local text = leftLine:GetText() + local r, g, b = leftLine:GetTextColor() + + if text and r and g and b then + local textLower = string.lower(text) + + -- Check for yellow/gold text (Use:, Equip:, Chance on hit:, etc.) + if IsYellowColor(r, g, b) then + -- Check if it matches any special text pattern + for _, pattern in ipairs(SPECIAL_TEXT_PATTERNS) do + if string.find(textLower, pattern) then + addon:Debug("HasSpecialTooltipText: YELLOW match '%s' in: %s", pattern, text) + return true, "yellow" + end + end + end + + -- Check for green text (set bonuses, enchants, special properties) + -- Green text is ALWAYS considered special (no pattern check needed) + if IsGreenColor(r, g, b) then + addon:Debug("HasSpecialTooltipText: Found GREEN text: %s (r=%.2f g=%.2f b=%.2f)", text, r, g, b) + return true, "green" + end + + -- Also check for "Use:" or "Equip:" regardless of color (some items may have different colors) + if string.find(textLower, "^use:") or string.find(textLower, "^equip:") then + addon:Debug("HasSpecialTooltipText: Found Use/Equip text: %s", text) + return true, "yellow" + end + end + end + + -- Also check right side of tooltip + local rightLine = getglobal("GudaBagScanTooltipTextRight" .. i) + if rightLine and rightLine:IsShown() then + local text = rightLine:GetText() + local r, g, b = rightLine:GetTextColor() + + if text and r and g and b then + if IsYellowColor(r, g, b) or IsGreenColor(r, g, b) then + addon:Debug("HasSpecialTooltipText: Found special text (right): %s", text) + return true, IsYellowColor(r, g, b) and "yellow" or "green" + end + end + end + end + + return false, nil +end + -- Check if an item is a quest item by scanning its tooltip (internal helper) -- Returns: isQuestItem, isQuestStarter local function ScanTooltipForQuest(tooltip, tooltipName) diff --git a/Sorting/SortEngine.lua b/Sorting/SortEngine.lua index 43f3614..8a11caf 100644 --- a/Sorting/SortEngine.lua +++ b/Sorting/SortEngine.lua @@ -274,6 +274,33 @@ local function GetQualityFromLink(link) return 1 end +-- Check if an item is a profession tool (should NOT be treated as junk) +local function IsProfessionTool(itemLink, itemSubclass) + -- Check by item ID + if itemLink then + local itemID = GetItemID(itemLink) + if itemID and addon.Constants.PROFESSION_TOOL_IDS and addon.Constants.PROFESSION_TOOL_IDS[itemID] then + return true + end + end + + -- Check by subtype (e.g., Fishing Pole) + if itemSubclass and addon.Constants.PROFESSION_TOOL_SUBTYPES and addon.Constants.PROFESSION_TOOL_SUBTYPES[itemSubclass] then + return true + end + + return false +end + +-- Check if an item has special tooltip text (Use:, Equip:, green text) +-- These items should NOT be treated as junk +local function HasSpecialTooltipText(bagID, slotID, itemLink) + if addon.Modules.Utils and addon.Modules.Utils.HasSpecialTooltipText then + return addon.Modules.Utils:HasSpecialTooltipText(bagID, slotID, itemLink) + end + return false +end + -- Extract texture pattern for grouping similar items local function GetTexturePattern(textureName) if not textureName then return "" end @@ -551,7 +578,6 @@ local function AddSortKeys(items) local itemType = d.type local itemSubType = d.subclass local itemTexture = d.texture - local itemEquipLoc = d.equipLoc local itemStackSize = d.stackSize or 1 item.itemName = itemName or "" @@ -594,8 +620,46 @@ local function AddSortKeys(items) -- 1. Gray items (quality 0) -- 2. Items with gray tooltip -- 3. White equippable items (quality 1 Weapon/Armor) - vendor trash + -- EXCLUDES from junk: + -- - Trinkets, Rings, Necklaces (these typically have special effects) + -- - Profession tools (skinning knife, mining pick, fishing poles, etc.) + -- - Items with yellow description text (Use:, Equip:, Chance on hit: effects) + -- - Items with green description text (set bonuses, special properties) local isGrayItem = itemRarity == 0 or IsItemGrayTooltip(item.bagID, item.slot, item.data.link) - local isWhiteEquip = (itemRarity == 1) and (itemCategory == "Weapon" or itemCategory == "Armor") + local isWhiteEquip = false + + if itemRarity == 1 and (itemCategory == "Weapon" or itemCategory == "Armor") then + -- In Turtle WoW, equip slot info is in itemSubType, not itemEquipLoc + addon:Debug("SortEngine isJunk: name='%s', subclass='%s', class='%s'", + tostring(itemName), tostring(itemSubType), tostring(itemCategory)) + + -- EXCLUDE: Trinkets, Rings, Necklaces, Tabards, Shirts - these typically have special effects or are cosmetic + -- Check by itemSubType which contains INVTYPE_* values in Turtle WoW + local isSpecialSlot = (itemSubType == "INVTYPE_TRINKET" or + itemSubType == "INVTYPE_FINGER" or + itemSubType == "INVTYPE_NECK" or + itemSubType == "INVTYPE_TABARD" or + itemSubType == "INVTYPE_BODY") + + if isSpecialSlot then + addon:Debug("SortEngine: EXCLUDED (special slot) - %s (subclass=%s)", tostring(itemName), tostring(itemSubType)) + end + + if not isSpecialSlot then + -- Check exclusions for white equippable items + local isProfTool = IsProfessionTool(item.data.link, itemSubType) + local hasSpecialText = false + + if not isProfTool then + hasSpecialText = HasSpecialTooltipText(item.bagID, item.slot, item.data.link) + end + + -- Only mark as junk if NOT a profession tool AND NOT has special text + if not isProfTool and not hasSpecialText then + isWhiteEquip = true + end + end + end if isGrayItem or isWhiteEquip then item.sortedClass = CATEGORY_ORDER["Junk"] or 99 @@ -1051,6 +1115,11 @@ end -- Split a list of collected items into non-junk and junk items -- Junk includes: gray items (quality 0), gray tooltip items, white equippable items (quality 1 Weapon/Armor) +-- EXCLUDES from junk: +-- 1. Trinkets, Rings, Necklaces (these typically have special effects) +-- 2. Profession tools (skinning knife, mining pick, fishing poles, etc.) +-- 3. Items with yellow description text (Use:, Equip:, Chance on hit: effects) +-- 4. Items with green description text (set bonuses, special properties) local function SplitGreyItems(items) local nonGreys, greys = {}, {} for _, item in ipairs(items) do @@ -1059,7 +1128,42 @@ local function SplitGreyItems(items) local isGray = quality == 0 or IsItemGrayTooltip(item.bagID, item.slot, item.data.link) -- White equippable items (Weapon/Armor) are also treated as junk local itemClass = item.class or "" - local isWhiteEquip = (quality == 1) and (itemClass == "Weapon" or itemClass == "Armor") + local itemSubclass = item.data and item.data.subclass or "" + local itemLink = item.data and item.data.link + local isWhiteEquip = false + + if quality == 1 and (itemClass == "Weapon" or itemClass == "Armor") then + -- In Turtle WoW, equip slot info is in itemSubType (stored as subclass), not equipLoc + addon:Debug("SplitGreyItems isJunk: name='%s', subclass='%s', class='%s'", + tostring(item.data and item.data.name), tostring(itemSubclass), tostring(itemClass)) + + -- EXCLUDE: Trinkets, Rings, Necklaces, Tabards, Shirts - these typically have special effects or are cosmetic + -- Check by subclass which contains INVTYPE_* values in Turtle WoW + local isSpecialSlot = (itemSubclass == "INVTYPE_TRINKET" or + itemSubclass == "INVTYPE_FINGER" or + itemSubclass == "INVTYPE_NECK" or + itemSubclass == "INVTYPE_TABARD" or + itemSubclass == "INVTYPE_BODY") + + if isSpecialSlot then + addon:Debug("SplitGreyItems: EXCLUDED (special slot) - %s (subclass='%s')", tostring(item.data and item.data.name), tostring(itemSubclass)) + end + + if not isSpecialSlot then + -- Check exclusions for white equippable items + local isProfTool = IsProfessionTool(itemLink, itemSubclass) + local hasSpecialText = false + + if not isProfTool then + hasSpecialText = HasSpecialTooltipText(item.bagID, item.slot, itemLink) + end + + -- Only mark as junk if NOT a profession tool AND NOT has special text + if not isProfTool and not hasSpecialText then + isWhiteEquip = true + end + end + end if isGray or isWhiteEquip then table.insert(greys, item) diff --git a/UI/ItemButton.lua b/UI/ItemButton.lua index cc820da..86642a2 100644 --- a/UI/ItemButton.lua +++ b/UI/ItemButton.lua @@ -1270,10 +1270,7 @@ function Guda_ItemButton_OnEnter(self) GameTooltip:Show() - -- TESTING: Print item info to console for debugging - --local name, link, itemQuality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice = addon.Modules.Utils:GetItemInfo(self.itemData.link) - --addon:Print("name:" .. tostring(name) .. " link:" .. tostring(link) .. " quality:" .. tostring(itemQuality) .. " iLevel:" .. tostring(iLevel) .. " category:" .. tostring(itemCategory) .. " type:" .. tostring(itemType) .. " subType:" .. tostring(itemSubType) .. " stackCount:" .. tostring(itemStackCount) .. " equipLoc:" .. tostring(itemEquipLoc) .. " sellPrice:" .. tostring(itemSellPrice)) - + -- Debug: Print item info including equipSlot when debug mode is enabled -- Handle merchant sell cursor (same approach as BagShui) if MerchantFrame:IsShown() and not self.isBank and not self.otherChar and self.hasItem then ShowContainerSellCursor(self.bagID, self.slotID)