700 lines
21 KiB
Lua
700 lines
21 KiB
Lua
-- Guda Utility Functions
|
|
|
|
local addon = Guda
|
|
|
|
local Utils = {}
|
|
addon.Modules.Utils = Utils
|
|
|
|
-- Format money (copper to gold/silver/copper string) - WoW 1.12.1 version
|
|
function Utils:FormatMoney(copper, showZero, useColors)
|
|
if not copper or copper == 0 then
|
|
if useColors then
|
|
return "|cFFFFFFFF" .. "0" .. "|r" .. "|cFFEDA55F" .. "c" .. "|r"
|
|
else
|
|
return "0c"
|
|
end
|
|
end
|
|
|
|
local gold = math.floor(copper / 10000)
|
|
local silver = math.floor(mod(copper, 10000) / 100)
|
|
local bronze = mod(copper, 100)
|
|
|
|
local str = ""
|
|
|
|
if useColors then
|
|
-- Colored version for tooltips - white numbers, colored g/s/c letters
|
|
if gold > 0 then
|
|
str = str .. "|cFFFFFFFF" .. gold .. "|r" .. "|cFFFFD700" .. "g" .. "|r "
|
|
end
|
|
if silver > 0 or gold > 0 then
|
|
str = str .. "|cFFFFFFFF" .. silver .. "|r" .. "|cFFC7C7CF" .. "s" .. "|r "
|
|
end
|
|
str = str .. "|cFFFFFFFF" .. bronze .. "|r" .. "|cFFEDA55F" .. "c" .. "|r"
|
|
else
|
|
-- Plain text version
|
|
if gold > 0 then
|
|
str = str .. gold .. "g "
|
|
end
|
|
if silver > 0 or gold > 0 then
|
|
str = str .. silver .. "s "
|
|
end
|
|
str = str .. bronze .. "c"
|
|
end
|
|
|
|
return str
|
|
end
|
|
|
|
-- Get item info with caching
|
|
local itemCache = {}
|
|
|
|
-- Extract itemID from itemLink (Lua 5.0 compatible)
|
|
-- Returns: itemID as number, or nil if extraction fails
|
|
function Utils:ExtractItemID(itemLink)
|
|
if not itemLink then return nil end
|
|
local _, _, itemID = string.find(itemLink, "item:(%d+)")
|
|
return itemID and tonumber(itemID) or nil
|
|
end
|
|
|
|
-- Get item info with error handling (does not cache)
|
|
-- Turtle WoW GetItemInfo signature:
|
|
-- itemName, itemLink, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice
|
|
function Utils:GetItemInfoSafe(itemID)
|
|
if not itemID then
|
|
addon:Debug("GetItemInfoSafe: nil itemID")
|
|
return nil
|
|
end
|
|
|
|
local itemName, itemLink, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice = GetItemInfo(itemID)
|
|
|
|
if not itemName then
|
|
addon:Debug("GetItemInfoSafe: GetItemInfo failed for itemID %d", itemID)
|
|
return nil
|
|
end
|
|
|
|
return itemName, itemLink, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice
|
|
end
|
|
|
|
-- Get item info with caching (wrapper for backward compatibility)
|
|
function Utils:GetItemInfo(itemLink)
|
|
if not itemLink then return nil end
|
|
|
|
if itemCache[itemLink] then
|
|
return unpack(itemCache[itemLink])
|
|
end
|
|
|
|
local itemID = self:ExtractItemID(itemLink)
|
|
if not itemID then return nil end
|
|
|
|
local itemName, retLink, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice = self:GetItemInfoSafe(itemID)
|
|
|
|
if itemName then
|
|
itemCache[itemLink] = {itemName, retLink, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice}
|
|
return itemName, retLink, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
-- Create a hidden tooltip for scanning
|
|
local scanTooltip = CreateFrame("GameTooltip", "GudaBagScanTooltip", nil, "GameTooltipTemplate")
|
|
scanTooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
|
|
|
|
-- Get item link from mailbox attachment (WoW 1.12.1 workaround)
|
|
function Utils:GetInboxItemLink(index, itemIndex)
|
|
-- In 1.12.1, GameTooltip:GetHyperlink() does not exist.
|
|
-- Actually, in 1.12.1, there's no official API to get the link from a mailbox item
|
|
-- if GetInboxItemLink(index) is not available (it's often NOT available in Vanilla).
|
|
|
|
-- Let's try to use GetItemInfo(name) as the primary way.
|
|
local name = GetInboxItem(index, itemIndex)
|
|
if name then
|
|
local _, link = GetItemInfo(name)
|
|
if link then
|
|
return link
|
|
end
|
|
end
|
|
|
|
-- Fallback: If we still don't have it, we might try to scan the tooltip for the name
|
|
-- but GetInboxItem already gave us the name.
|
|
|
|
return nil
|
|
end
|
|
|
|
-- Get quality color
|
|
function Utils:GetQualityColor(quality)
|
|
local color = addon.Constants.QUALITY_COLORS[quality] or addon.Constants.QUALITY_COLORS[1]
|
|
return color.r, color.g, color.b
|
|
end
|
|
|
|
-- Create colored text
|
|
function Utils:ColorText(text, r, g, b)
|
|
local red = math.floor(r * 255)
|
|
local green = math.floor(g * 255)
|
|
local blue = math.floor(b * 255)
|
|
return string.format("|cFF%02X%02X%02X%s|r", red, green, blue, text)
|
|
end
|
|
|
|
-- Deep copy table
|
|
function Utils:DeepCopy(orig)
|
|
local orig_type = type(orig)
|
|
local copy
|
|
if orig_type == 'table' then
|
|
copy = {}
|
|
for orig_key, orig_value in next, orig, nil do
|
|
copy[Utils:DeepCopy(orig_key)] = Utils:DeepCopy(orig_value)
|
|
end
|
|
setmetatable(copy, Utils:DeepCopy(getmetatable(orig)))
|
|
else
|
|
copy = orig
|
|
end
|
|
return copy
|
|
end
|
|
|
|
-- Get class color
|
|
function Utils:GetClassColor(class)
|
|
local colors = {
|
|
WARRIOR = {r = 0.78, g = 0.61, b = 0.43},
|
|
PALADIN = {r = 0.96, g = 0.55, b = 0.73},
|
|
HUNTER = {r = 0.67, g = 0.83, b = 0.45},
|
|
ROGUE = {r = 1.00, g = 0.96, b = 0.41},
|
|
PRIEST = {r = 1.00, g = 1.00, b = 1.00},
|
|
SHAMAN = {r = 0.00, g = 0.44, b = 0.87},
|
|
MAGE = {r = 0.41, g = 0.80, b = 0.94},
|
|
WARLOCK = {r = 0.58, g = 0.51, b = 0.79},
|
|
DRUID = {r = 1.00, g = 0.49, b = 0.04},
|
|
}
|
|
return colors[class] or {r = 0.5, g = 0.5, b = 0.5}
|
|
end
|
|
|
|
-- Format time ago
|
|
function Utils:FormatTimeAgo(timestamp)
|
|
local diff = time() - timestamp
|
|
if diff < 60 then
|
|
return "Just now"
|
|
elseif diff < 3600 then
|
|
return math.floor(diff / 60) .. "m ago"
|
|
elseif diff < 86400 then
|
|
return math.floor(diff / 3600) .. "h ago"
|
|
else
|
|
return math.floor(diff / 86400) .. "d ago"
|
|
end
|
|
end
|
|
|
|
-- Create hidden tooltip for scanning (only once)
|
|
local function GetScanTooltip()
|
|
return scanTooltip
|
|
end
|
|
|
|
-- Check if an item is a quest item by scanning its tooltip
|
|
function Utils:IsQuestItemTooltip(bagID, slotID)
|
|
if not bagID or not slotID then return false end
|
|
|
|
local tooltip = GetScanTooltip()
|
|
tooltip:ClearLines()
|
|
tooltip:SetBagItem(bagID, slotID)
|
|
|
|
-- Check tooltip lines for explicit quest-related phrases (case-insensitive)
|
|
for i = 1, tooltip:NumLines() do
|
|
local line = getglobal("GudaBagScanTooltipTextLeft" .. i)
|
|
if line then
|
|
local text = line:GetText()
|
|
if text then
|
|
local tl = string.lower(text)
|
|
-- Only match explicit quest markers to avoid misclassifying consumables/recipes
|
|
if string.find(tl, "quest starter") or
|
|
string.find(tl, "this item begins a quest") or
|
|
string.find(tl, "starts a quest") or
|
|
string.find(tl, "quest item") then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Check if an item has a gray title in its tooltip or link
|
|
function Utils:IsItemGrayTooltip(bagID, slotID, itemLink)
|
|
-- Check link first if provided (works for other characters too)
|
|
if itemLink and string.find(itemLink, "|cff9d9d9d") then
|
|
return true
|
|
end
|
|
|
|
if not bagID or not slotID then return false end
|
|
|
|
local tooltip = GetScanTooltip()
|
|
tooltip:ClearLines()
|
|
tooltip:SetBagItem(bagID, slotID)
|
|
|
|
local line = getglobal("GudaBagScanTooltipTextLeft1")
|
|
if line then
|
|
local text = line:GetText()
|
|
if text then
|
|
-- Poor quality color code is |cff9d9d9d
|
|
if string.find(text, "|cff9d9d9d") then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Get bag slot count
|
|
function Utils:GetBagSlotCount(bagID)
|
|
if bagID == -1 then
|
|
-- Bank has 24 slots in vanilla
|
|
return 24
|
|
elseif bagID == -2 then
|
|
-- Keyring - vanilla WoW has 12-32 slots depending on version
|
|
local slots = GetContainerNumSlots(bagID)
|
|
if not slots or slots == 0 then
|
|
-- Fallback: keyring typically has 12 slots in vanilla
|
|
return 12
|
|
end
|
|
return slots
|
|
else
|
|
return GetContainerNumSlots(bagID) or 0
|
|
end
|
|
end
|
|
|
|
-- Check if bag is valid
|
|
function Utils:IsBagValid(bagID)
|
|
if bagID == 0 or bagID == -1 or bagID == -2 then
|
|
return true
|
|
end
|
|
return GetContainerNumSlots(bagID) and GetContainerNumSlots(bagID) > 0
|
|
end
|
|
|
|
-- Truncate text to length
|
|
function Utils:TruncateText(text, maxLen)
|
|
if not text then return "" end
|
|
if string.len(text) <= maxLen then
|
|
return text
|
|
end
|
|
return string.sub(text, 1, maxLen - 3) .. "..."
|
|
end
|
|
|
|
function Utils:IsAmmoQuiverBag(bagID)
|
|
-- Skip backpack, bank, and keyring
|
|
if bagID == 0 or bagID == -1 or bagID == -2 then
|
|
return false
|
|
end
|
|
|
|
-- Get the bag item
|
|
local invSlot = ContainerIDToInventoryID(bagID)
|
|
if not invSlot then
|
|
return false
|
|
end
|
|
|
|
local link = GetInventoryItemLink("player", invSlot)
|
|
if not link then
|
|
return false
|
|
end
|
|
|
|
-- Use tooltip scanning to get item class (more reliable in 1.12.1)
|
|
local tooltip = GetScanTooltip()
|
|
tooltip:ClearLines()
|
|
tooltip:SetInventoryItem("player", invSlot)
|
|
|
|
-- Scan tooltip lines for "Quiver" or "Ammo Pouch"
|
|
for i = 1, tooltip:NumLines() do
|
|
local line = getglobal("GudaBagScanTooltipTextLeft" .. i)
|
|
if line then
|
|
local text = line:GetText()
|
|
if text then
|
|
-- Check if the line contains "Quiver" or "Ammo Pouch"
|
|
if string.find(text, "Quiver") or string.find(text, "Ammo Pouch") then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-- Check if a bag is Herb Bag
|
|
function Utils:IsHerbBag(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 == "herb" then return true end
|
|
|
|
-- Fallback: tooltip scan for "Herb 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), "herb bag") then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-- Check if a bag is Soul Bag
|
|
function Utils:IsSoulBag(bagID)
|
|
-- Skip backpack, bank, and keyring
|
|
if bagID == 0 or bagID == -1 or bagID == -2 then
|
|
return false
|
|
end
|
|
|
|
-- Get the bag item
|
|
local invSlot = ContainerIDToInventoryID(bagID)
|
|
if not invSlot then
|
|
return false
|
|
end
|
|
|
|
local link = GetInventoryItemLink("player", invSlot)
|
|
if not link then
|
|
return false
|
|
end
|
|
|
|
-- First try GetSpecializedBagType
|
|
local bagType = self:GetSpecializedBagType(bagID)
|
|
if bagType == "soul" then
|
|
return true
|
|
end
|
|
|
|
-- Fallback: Use tooltip scanning (more reliable in 1.12.1)
|
|
local tooltip = GetScanTooltip()
|
|
tooltip:ClearLines()
|
|
tooltip:SetInventoryItem("player", invSlot)
|
|
|
|
-- Scan tooltip lines for "Soul Bag" or "Soul Pouch"
|
|
for i = 1, tooltip:NumLines() do
|
|
local line = getglobal("GudaBagScanTooltipTextLeft" .. i)
|
|
if line then
|
|
local text = line:GetText()
|
|
if text then
|
|
-- Check if the line contains "Soul Bag" or "Soul Pouch" or just "Soul" in bag name
|
|
local textLower = string.lower(text)
|
|
if string.find(textLower, "soul bag") or string.find(textLower, "soul pouch") or
|
|
(string.find(textLower, "soul") and (string.find(textLower, "bag") or string.find(textLower, "pouch"))) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-- 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
|
|
return nil
|
|
end
|
|
|
|
-- Get the bag item
|
|
local invSlot = ContainerIDToInventoryID(bagID)
|
|
if not invSlot then
|
|
return nil
|
|
end
|
|
|
|
local link = GetInventoryItemLink("player", invSlot)
|
|
if not link then
|
|
return nil
|
|
end
|
|
|
|
local itemID = self:ExtractItemID(link)
|
|
if not itemID then
|
|
return nil
|
|
end
|
|
|
|
local itemName, _, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType = self:GetItemInfoSafe(itemID)
|
|
if itemType then
|
|
-- Check for exact subtype matches
|
|
local typeLower = string.lower(itemType)
|
|
|
|
-- Soul Bag / Soul Pouch
|
|
if string.find(typeLower, "soul bag") or string.find(typeLower, "soul pouch") then
|
|
return "soul"
|
|
end
|
|
|
|
-- Herb Bag
|
|
if string.find(typeLower, "herb bag") then
|
|
return "herb"
|
|
end
|
|
|
|
-- Enchanting Bag
|
|
if string.find(typeLower, "enchanting bag") then
|
|
return "enchant"
|
|
end
|
|
|
|
-- Quiver
|
|
if string.find(typeLower, "quiver") then
|
|
return "quiver"
|
|
end
|
|
|
|
-- Ammo Pouch
|
|
if string.find(typeLower, "ammo pouch") then
|
|
return "ammo"
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
-- Get container priority for sorting (higher = more important)
|
|
function Utils:GetContainerPriority(bagID)
|
|
local bagType = self:GetSpecializedBagType(bagID)
|
|
if bagType == "enchant" then
|
|
return 50
|
|
elseif bagType == "herb" then
|
|
return 45
|
|
elseif bagType == "soul" then
|
|
return 40
|
|
elseif bagType == "quiver" then
|
|
return 30
|
|
elseif bagType == "ammo" then
|
|
return 20
|
|
else
|
|
return 10 -- Regular bag
|
|
end
|
|
end
|
|
|
|
-- Soul Shard item ID
|
|
local SOUL_SHARD_ID = 6265
|
|
|
|
-- Check if item is a Soul Shard
|
|
function Utils:IsSoulShard(itemLink)
|
|
if not itemLink then return false end
|
|
local itemID = self:ExtractItemID(itemLink)
|
|
return itemID == SOUL_SHARD_ID
|
|
end
|
|
|
|
-- Extract hyperlink from item link for tooltip scanning
|
|
local function ExtractHyperlink(itemLink)
|
|
if not itemLink then return nil end
|
|
local _, _, hyperlink = string.find(itemLink, "|H(.+)|h")
|
|
return hyperlink
|
|
end
|
|
|
|
-- Detect if a consumable has 'Use: Restores' or mentions 'while eating'/'while drinking'
|
|
function Utils:GetConsumableRestoreTag(bagID, slotID)
|
|
if not bagID or not slotID then return nil end
|
|
local tooltip = GetScanTooltip()
|
|
tooltip:ClearLines()
|
|
tooltip:SetBagItem(bagID, slotID)
|
|
local tag = nil
|
|
for i = 1, tooltip:NumLines() do
|
|
local line = getglobal("GudaBagScanTooltipTextLeft" .. i)
|
|
if line then
|
|
local text = line:GetText()
|
|
if text then
|
|
local tl = string.lower(text)
|
|
if string.find(tl, "while eating") then
|
|
tag = "eat"
|
|
break
|
|
elseif string.find(tl, "while drinking") then
|
|
tag = "drink"
|
|
break
|
|
elseif string.find(tl, "use: restores") then
|
|
tag = "restore"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return tag
|
|
end
|
|
|
|
-- Check if item is Arrow or Bullet (for Quiver routing)
|
|
function Utils:IsArrowOrBullet(itemType)
|
|
if not itemType then return false end
|
|
-- Exact matching only
|
|
return itemType == "Arrow" or itemType == "Bullet"
|
|
end
|
|
|
|
-- Check if item is Ammo (any type - for Ammo Pouch)
|
|
function Utils:IsAmmo(itemType)
|
|
if not itemType then return false end
|
|
return itemType == "Arrow" or itemType == "Bullet"
|
|
end
|
|
|
|
-- Get preferred container type for an item
|
|
-- Returns: "soul", "herb", "enchant", "quiver", "ammo", or nil
|
|
function Utils:GetItemPreferredContainer(itemLink)
|
|
if not itemLink then return nil end
|
|
|
|
-- Check for soul shards first
|
|
if self:IsSoulShard(itemLink) then
|
|
return "soul"
|
|
end
|
|
|
|
-- Get item info using utility function
|
|
local itemID = self:ExtractItemID(itemLink)
|
|
if not itemID then return nil end
|
|
|
|
local itemName, _, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture = self:GetItemInfoSafe(itemID)
|
|
if not itemType then return nil end
|
|
|
|
-- Only route PROJECTILE category items that are specifically arrows or bullets
|
|
if itemCategory == "Projectile" then
|
|
if itemType == "Arrow" then
|
|
return "quiver"
|
|
elseif itemType == "Bullet" then
|
|
return "ammo"
|
|
end
|
|
end
|
|
|
|
-- Route herbs to herb bags (robust: category/subtype OR texture pattern fallback)
|
|
if self:IsHerbItem(itemLink) then
|
|
return "herb"
|
|
end
|
|
|
|
-- Route enchanting materials to enchanting bags
|
|
if self:IsEnchantingItem(itemLink) then
|
|
return "enchant"
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
-- Check if an item is equipment (armor, weapon, or other equippable)
|
|
-- Returns: true if item is equipment, false otherwise
|
|
function Utils:IsEquipment(itemLink)
|
|
if not itemLink then return false end
|
|
|
|
local itemID = self:ExtractItemID(itemLink)
|
|
if not itemID then return false end
|
|
|
|
local itemName, _, itemRarity, itemLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc = self:GetItemInfoSafe(itemID)
|
|
|
|
-- Check if item has an equip location (most reliable method)
|
|
if itemEquipLoc and itemEquipLoc ~= "" and itemEquipLoc ~= "INVTYPE_BAG" then
|
|
return true
|
|
end
|
|
|
|
-- Fallback: Check category (in case itemEquipLoc is not set)
|
|
if itemCategory then
|
|
local categoryLower = string.lower(itemCategory)
|
|
if categoryLower == "armor" or categoryLower == "weapon" then
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-- Determine if an item is a herb (for routing to herb bags)
|
|
-- NEW rule (per request): require BOTH
|
|
-- 1) itemCategory == "Trade Goods"
|
|
-- 2) texture contains "INV_Misc_Herb" (case-insensitive; prefix tolerated)
|
|
function Utils:IsHerbItem(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
|
|
return false
|
|
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_misc_herb") or string.find(tex, "misc_herb") then
|
|
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 |