diff --git a/Core/Utils.lua b/Core/Utils.lua index 0693e38..b862dbc 100644 --- a/Core/Utils.lua +++ b/Core/Utils.lua @@ -323,8 +323,7 @@ function Utils:IsSoulBag(bagID) return false end --- Get specialized bag type (for sorting priority) --- Returns: "soul", "herb", "quiver", "ammo", or nil +-- Returns: "soul", "herb", "enchant", "quiver", "ammo", or nil function Utils:GetSpecializedBagType(bagID) -- Skip backpack, bank, and keyring if bagID == 0 or bagID == -1 or bagID == -2 then @@ -362,6 +361,11 @@ function Utils:GetSpecializedBagType(bagID) return "herb" end + -- Enchanting Bag + if string.find(typeLower, "enchanting bag") then + return "enchant" + end + -- Quiver if string.find(typeLower, "quiver") then return "quiver" @@ -379,10 +383,12 @@ end -- Get container priority for sorting (higher = more important) function Utils:GetContainerPriority(bagID) local bagType = self:GetSpecializedBagType(bagID) - if bagType == "soul" then - return 40 + if bagType == "enchant" then + return 50 elseif bagType == "herb" then - return 35 + return 45 + elseif bagType == "soul" then + return 40 elseif bagType == "quiver" then return 30 elseif bagType == "ammo" then @@ -423,7 +429,7 @@ function Utils:IsAmmo(itemType) end -- Get preferred container type for an item --- Returns: "soul", "herb", "quiver", "ammo", or nil +-- Returns: "soul", "herb", "enchant", "quiver", "ammo", or nil function Utils:GetItemPreferredContainer(itemLink) if not itemLink then return nil end @@ -453,6 +459,11 @@ function Utils:GetItemPreferredContainer(itemLink) return "herb" end + -- Route enchanting materials to enchanting bags + if self:IsEnchantingItem(itemLink) then + return "enchant" + end + return nil end @@ -510,5 +521,79 @@ function Utils:IsHerbItem(itemLink) return true end + return false +end + +-- Determine if an item is an enchanting material (for routing to enchanting bags) +-- Rules: +-- 1) itemCategory == "Trade Goods" +-- 2) (itemSubType == "Enchanting") OR texture contains "INV_Enchant" (case-insensitive) +function Utils:IsEnchantingItem(itemLink) + if not itemLink then return false end + + local itemID = self:ExtractItemID(itemLink) + if not itemID then return false end + + local name, _, quality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture = self:GetItemInfoSafe(itemID) + + if itemCategory ~= "Trade Goods" then + -- Some private servers may report Enchanting directly as type + if itemType ~= "Enchanting" and itemSubType ~= "Enchanting" then + return false + end + end + + -- If explicit Enchanting subtype/type, accept immediately + if itemType == "Enchanting" or itemSubType == "Enchanting" then + return true + end + + if not itemTexture then + return false + end + + -- Normalize and check texture name + local tex = string.lower(itemTexture) + tex = string.gsub(tex, "^interface\\\\icons\\\\", "") + + if string.find(tex, "inv_enchant") or string.find(tex, "enchant") then + return true + end + + return false +end + +-- Check if a bag is Enchanting Bag (parallel to IsHerbBag) +function Utils:IsEnchantBag(bagID) + -- Skip backpack, bank, and keyring + if bagID == 0 or bagID == -1 or bagID == -2 then + return false + end + + local invSlot = ContainerIDToInventoryID(bagID) + if not invSlot then return false end + + local link = GetInventoryItemLink("player", invSlot) + if not link then return false end + + -- Prefer specialized type detection + local bagType = self:GetSpecializedBagType(bagID) + if bagType == "enchant" then return true end + + -- Fallback: tooltip scan for "Enchanting Bag" + local tooltip = GetScanTooltip() + tooltip:ClearLines() + tooltip:SetInventoryItem("player", invSlot) + + for i = 1, tooltip:NumLines() do + local line = getglobal("GudaBagScanTooltipTextLeft" .. i) + if line then + local text = line:GetText() + if text and string.find(string.lower(text), "enchanting bag") then + return true + end + end + end + return false end \ No newline at end of file diff --git a/Data/BagScanner.lua b/Data/BagScanner.lua index 192619c..8d16f7c 100644 --- a/Data/BagScanner.lua +++ b/Data/BagScanner.lua @@ -24,14 +24,7 @@ end -- Scan a single bag function BagScanner:ScanBag(bagID) -- Determine bag type - local bagType = "regular" - if addon.Modules.Utils:IsSoulBag(bagID) then - bagType = "soul" - elseif addon.Modules.Utils:IsHerbBag(bagID) then - bagType = "herb" - elseif addon.Modules.Utils:IsAmmoQuiverBag(bagID) then - bagType = "ammo" - end + local bagType = addon.Modules.Utils:GetSpecializedBagType(bagID) or "regular" local bag = { slots = {}, diff --git a/Data/BankScanner.lua b/Data/BankScanner.lua index a525eeb..9eb1a39 100644 --- a/Data/BankScanner.lua +++ b/Data/BankScanner.lua @@ -32,6 +32,8 @@ function BankScanner:ScanBankBag(bagID) bagType = "soul" elseif addon.Modules.Utils:IsHerbBag(bagID) then bagType = "herb" + elseif addon.Modules.Utils:IsEnchantBag(bagID) then + bagType = "enchant" elseif addon.Modules.Utils:IsAmmoQuiverBag(bagID) then bagType = "ammo" end diff --git a/Sorting/SortEngine.lua b/Sorting/SortEngine.lua index 86bc6d0..56765c5 100644 --- a/Sorting/SortEngine.lua +++ b/Sorting/SortEngine.lua @@ -175,6 +175,7 @@ local function DetectSpecializedBags(bagIDs) local containers = { soul = {}, herb = {}, + enchant = {}, quiver = {}, ammo = {}, regular = {} @@ -186,6 +187,8 @@ local function DetectSpecializedBags(bagIDs) table.insert(containers.soul, bagID) elseif bagType == "herb" then table.insert(containers.herb, bagID) + elseif bagType == "enchant" then + table.insert(containers.enchant, bagID) elseif bagType == "quiver" then table.insert(containers.quiver, bagID) elseif bagType == "ammo" then @@ -753,7 +756,7 @@ function SortEngine:AnalyzeContainer(bagIDs, containerType) local totalItems = 0 -- Analyze specialized bags separately - for _, bagType in ipairs({"soul", "herb", "quiver", "ammo"}) do + for _, bagType in ipairs({"enchant", "herb", "soul", "quiver", "ammo"}) do local specialBags = containers[bagType] for _, bagID in ipairs(specialBags) do local items = CollectItems({bagID}) @@ -873,9 +876,9 @@ function SortEngine:SortBagsPass() -- Phase 3: Consolidate stacks in ALL bags (including specialized) local consolidateCount = ConsolidateStacks(bagIDs) - -- Phase 4: Sort items WITHIN each specialized bag (soul, herb, quiver, ammo) + -- Phase 4: Sort items WITHIN each specialized bag (enchant, herb, soul, quiver, ammo) local specializedMoves = 0 - for _, bagType in ipairs({"soul", "herb", "quiver", "ammo"}) do + for _, bagType in ipairs({"enchant", "herb", "soul", "quiver", "ammo"}) do local specialBags = containers[bagType] for _, bagID in ipairs(specialBags) do local items = CollectItems({bagID}) @@ -927,9 +930,9 @@ function SortEngine:SortBags() -- Phase 3: Consolidate stacks in ALL bags (including specialized) local consolidateCount = ConsolidateStacks(bagIDs) - -- Phase 4: Sort items WITHIN each specialized bag (soul, herb, quiver, ammo) + -- Phase 4: Sort items WITHIN each specialized bag (enchant, herb, soul, quiver, ammo) local specializedMoves = 0 - for _, bagType in ipairs({"soul", "herb", "quiver", "ammo"}) do + for _, bagType in ipairs({"enchant", "herb", "soul", "quiver", "ammo"}) do local specialBags = containers[bagType] for _, bagID in ipairs(specialBags) do -- Sort items within this single specialized bag @@ -1000,7 +1003,7 @@ function SortEngine:SortBankPass() -- Phase 4: Sort items WITHIN each specialized bag (single pass) local specializedMoves = 0 - for _, bagType in ipairs({"soul", "herb", "quiver", "ammo"}) do + for _, bagType in ipairs({"enchant", "herb", "soul", "quiver", "ammo"}) do local specialBags = containers[bagType] for _, bagID in ipairs(specialBags) do local items = CollectItems({bagID}) @@ -1056,7 +1059,7 @@ function SortEngine:SortBank() -- Phase 4: Sort items WITHIN each specialized bag (multi-pass to avoid mid-bag holes) local specializedMoves = 0 - for _, bagType in ipairs({"soul", "herb", "quiver", "ammo"}) do + for _, bagType in ipairs({"enchant", "herb", "soul", "quiver", "ammo"}) do local specialBags = containers[bagType] for _, bagID in ipairs(specialBags) do local maxPasses = 4 diff --git a/UI/BagFrame.lua b/UI/BagFrame.lua index a615106..8c9943f 100644 --- a/UI/BagFrame.lua +++ b/UI/BagFrame.lua @@ -236,68 +236,76 @@ function BagFrame:DisplayItems(bagData, isOtherChar, charName) local perRow = addon.Modules.DB:GetSetting("bagColumns") or 10 local itemContainer = getglobal("Guda_BagFrame_ItemContainer") - -- Separate bags into regular, soul, herb, and ammo/quiver types + -- Separate bags into regular, enchant, herb, soul, quiver, and ammo types local regularBags = {} - local soulBags = {} + local enchantBags = {} local herbBags = {} - local ammoQuiverBags = {} + local soulBags = {} + local quiverBags = {} + local ammoBags = {} for _, bagID in ipairs(addon.Constants.BAGS) do -- Skip hidden bags if not hiddenBags[bagID] then - local bagType - if isOtherChar then - -- For other characters, use saved bag type - local bag = bagData[bagID] - bagType = bag and bag.bagType or "regular" - else - -- For current character, detect bag type in real-time - if addon.Modules.Utils:IsSoulBag(bagID) then - bagType = "soul" - elseif addon.Modules.Utils:IsHerbBag(bagID) then - bagType = "herb" - elseif addon.Modules.Utils:IsAmmoQuiverBag(bagID) then - bagType = "ammo" - else - bagType = "regular" - end + local bagType + if isOtherChar then + -- For other characters, use saved bag type + local bag = bagData[bagID] + bagType = bag and bag.bagType or "regular" + else + -- For current character, detect bag type in real-time using unified detector + bagType = addon.Modules.Utils:GetSpecializedBagType(bagID) or "regular" end - if bagType == "soul" then - table.insert(soulBags, bagID) + if bagType == "enchant" then + table.insert(enchantBags, bagID) elseif bagType == "herb" then table.insert(herbBags, bagID) + elseif bagType == "soul" then + table.insert(soulBags, bagID) + elseif bagType == "quiver" then + table.insert(quiverBags, bagID) elseif bagType == "ammo" then - table.insert(ammoQuiverBags, bagID) + table.insert(ammoBags, bagID) else table.insert(regularBags, bagID) end end end - -- Build display order: regular bags -> soul bags -> herb bags -> ammo/quiver bags -> keyring + -- Build display order: regular -> enchant -> herb -> soul -> quiver -> ammo -> keyring local bagsToShow = {} for _, bagID in ipairs(regularBags) do table.insert(bagsToShow, {bagID = bagID, needsSpacing = false}) end - -- Add soul bags with spacing marker - if table.getn(soulBags) > 0 then - for i, bagID in ipairs(soulBags) do + -- Enchant + if table.getn(enchantBags) > 0 then + for i, bagID in ipairs(enchantBags) do table.insert(bagsToShow, {bagID = bagID, needsSpacing = (i == 1)}) end end - - -- Add herb bags with spacing marker + -- Herb if table.getn(herbBags) > 0 then for i, bagID in ipairs(herbBags) do table.insert(bagsToShow, {bagID = bagID, needsSpacing = (i == 1)}) end end - - -- Add ammo/quiver bags with spacing marker - if table.getn(ammoQuiverBags) > 0 then - for i, bagID in ipairs(ammoQuiverBags) do + -- Soul + if table.getn(soulBags) > 0 then + for i, bagID in ipairs(soulBags) do + table.insert(bagsToShow, {bagID = bagID, needsSpacing = (i == 1)}) + end + end + -- Quiver + if table.getn(quiverBags) > 0 then + for i, bagID in ipairs(quiverBags) do + table.insert(bagsToShow, {bagID = bagID, needsSpacing = (i == 1)}) + end + end + -- Ammo + if table.getn(ammoBags) > 0 then + for i, bagID in ipairs(ammoBags) do table.insert(bagsToShow, {bagID = bagID, needsSpacing = (i == 1)}) end end @@ -311,7 +319,7 @@ function BagFrame:DisplayItems(bagData, isOtherChar, charName) local bagID = bagInfo.bagID local bag = bagData[bagID] - -- Add spacing before soul, herb, ammo/quiver, or keyring sections + -- Add spacing before enchant, herb, soul, quiver, ammo, or keyring sections if bagInfo.needsSpacing then if col > 0 then -- Move to next row if not at start of row diff --git a/UI/BankFrame.lua b/UI/BankFrame.lua index 688cd91..a0e9c7b 100644 --- a/UI/BankFrame.lua +++ b/UI/BankFrame.lua @@ -196,11 +196,13 @@ function BankFrame:DisplayItems(bankData, isOtherChar, charName) local perRow = addon.Modules.DB:GetSetting("bankColumns") or 10 local itemContainer = getglobal("Guda_BankFrame_ItemContainer") - -- Separate bank bags into regular, soul, herb, and ammo/quiver types + -- Separate bank bags into regular, enchant, herb, soul, quiver, and ammo types local regularBags = {} - local soulBags = {} + local enchantBags = {} local herbBags = {} - local ammoQuiverBags = {} + local soulBags = {} + local quiverBags = {} + local ammoBags = {} for _, bagID in ipairs(addon.Constants.BANK_BAGS) do if not hiddenBankBags[bagID] then @@ -210,37 +212,33 @@ function BankFrame:DisplayItems(bankData, isOtherChar, charName) local bagSaved = bankData and bankData[bagID] bagType = bagSaved and bagSaved.bagType or "regular" else - -- Live detection for current character when bank is open - if addon.Modules.Utils:IsSoulBag(bagID) then - bagType = "soul" - elseif addon.Modules.Utils:IsHerbBag(bagID) then - bagType = "herb" - elseif addon.Modules.Utils:IsAmmoQuiverBag(bagID) then - bagType = "ammo" - else - bagType = "regular" - end + -- Unified live detection for current character when bank is open + bagType = addon.Modules.Utils:GetSpecializedBagType(bagID) or "regular" end - if bagType == "soul" then - table.insert(soulBags, bagID) + if bagType == "enchant" then + table.insert(enchantBags, bagID) elseif bagType == "herb" then table.insert(herbBags, bagID) + elseif bagType == "soul" then + table.insert(soulBags, bagID) + elseif bagType == "quiver" then + table.insert(quiverBags, bagID) elseif bagType == "ammo" then - table.insert(ammoQuiverBags, bagID) + table.insert(ammoBags, bagID) else table.insert(regularBags, bagID) end end end - -- Build display order: regular -> soul -> herb -> ammo/quiver + -- Build display order: regular -> enchant -> herb -> soul -> quiver -> ammo local bagsToShow = {} for _, bagID in ipairs(regularBags) do table.insert(bagsToShow, { bagID = bagID, needsSpacing = false }) end - if table.getn(soulBags) > 0 then - for i, bagID in ipairs(soulBags) do + if table.getn(enchantBags) > 0 then + for i, bagID in ipairs(enchantBags) do table.insert(bagsToShow, { bagID = bagID, needsSpacing = (i == 1) }) end end @@ -249,8 +247,18 @@ function BankFrame:DisplayItems(bankData, isOtherChar, charName) table.insert(bagsToShow, { bagID = bagID, needsSpacing = (i == 1) }) end end - if table.getn(ammoQuiverBags) > 0 then - for i, bagID in ipairs(ammoQuiverBags) do + if table.getn(soulBags) > 0 then + for i, bagID in ipairs(soulBags) do + table.insert(bagsToShow, { bagID = bagID, needsSpacing = (i == 1) }) + end + end + if table.getn(quiverBags) > 0 then + for i, bagID in ipairs(quiverBags) do + table.insert(bagsToShow, { bagID = bagID, needsSpacing = (i == 1) }) + end + end + if table.getn(ammoBags) > 0 then + for i, bagID in ipairs(ammoBags) do table.insert(bagsToShow, { bagID = bagID, needsSpacing = (i == 1) }) end end