feat: enchanting bags

This commit is contained in:
Salikh Gurgenidze
2025-12-19 03:01:09 +04:00
parent 02c42717aa
commit cfdc641811
6 changed files with 174 additions and 75 deletions
+91 -6
View File
@@ -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
+1 -8
View File
@@ -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 = {},
+2
View File
@@ -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
+10 -7
View File
@@ -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
+41 -33
View File
@@ -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
+29 -21
View File
@@ -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