mirror of
https://github.com/brues-code/SuperCleveRoidMacros.git
synced 2026-09-16 03:38:00 +00:00
reduce bag event usage for lag and fix macro calling within macros
This commit is contained in:
@@ -105,7 +105,7 @@ do
|
||||
if type(fn) == "function" then
|
||||
local b2, e2 = string.find(text, "^%s*/" .. k .. "%s+[!%[%{%?~]")
|
||||
if b2 then
|
||||
local msg2 = string.gsub(string.sub(text, e2 + 1), "^%s+", "")
|
||||
local msg2 = string.gsub(string.sub(text, e2), "^%s+", "")
|
||||
pcall(fn, msg2)
|
||||
return true -- IMPORTANT
|
||||
end
|
||||
|
||||
+138
-130
@@ -164,6 +164,112 @@ function CleveRoids.InvalidateEquipmentCache()
|
||||
_equipmentCacheValid = false
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- PERFORMANCE: Unified item location lookup using CleveRoids.Items cache
|
||||
-- Returns: { type="inventory"|"bag", inventoryID=N } or { type="bag", bag=N, slot=N }
|
||||
-- Returns nil if item not found
|
||||
-- ============================================================================
|
||||
local string_lower = string.lower
|
||||
local string_find = string.find
|
||||
|
||||
-- Fast item lookup using cache - O(1) instead of O(n) scan
|
||||
-- @param item: item ID (number) or item name (string)
|
||||
-- @return table with location info, or nil if not found
|
||||
function CleveRoids.FindItemLocation(item)
|
||||
local Items = CleveRoids.Items
|
||||
if not Items then return nil end
|
||||
|
||||
local itemData = nil
|
||||
|
||||
-- Case 1: Numeric item ID
|
||||
local numericItem = tonumber(item)
|
||||
if numericItem then
|
||||
-- Check if it's an equipment slot (1-19)
|
||||
if numericItem >= 1 and numericItem <= 19 then
|
||||
local link = GetInventoryItemLink("player", numericItem)
|
||||
if link then
|
||||
return { type = "inventory", inventoryID = numericItem }
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Look up by item ID in cache (Items[id] = name)
|
||||
local itemName = Items[numericItem]
|
||||
if itemName then
|
||||
itemData = Items[itemName]
|
||||
end
|
||||
else
|
||||
-- Case 2: String item name
|
||||
if type(item) == "string" and item ~= "" then
|
||||
-- Try exact match first, then lowercase
|
||||
itemData = Items[item]
|
||||
if not itemData or type(itemData) == "string" then
|
||||
local lowerItem = string_lower(item)
|
||||
local resolved = Items[lowerItem]
|
||||
if type(resolved) == "string" then
|
||||
itemData = Items[resolved]
|
||||
elseif type(resolved) == "table" then
|
||||
itemData = resolved
|
||||
end
|
||||
elseif type(itemData) == "string" then
|
||||
-- Resolve indirection (lowercase -> canonical name)
|
||||
itemData = Items[itemData]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not itemData or type(itemData) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Return location info
|
||||
if itemData.inventoryID then
|
||||
return { type = "inventory", inventoryID = itemData.inventoryID, itemData = itemData }
|
||||
elseif itemData.bagID and itemData.slot then
|
||||
return { type = "bag", bag = itemData.bagID, slot = itemData.slot, itemData = itemData }
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Fast item existence check using cache
|
||||
-- @param item: item ID (number) or item name (string)
|
||||
-- @return boolean
|
||||
function CleveRoids.HasItemCached(item)
|
||||
return CleveRoids.FindItemLocation(item) ~= nil
|
||||
end
|
||||
|
||||
-- Fast item cooldown lookup using cache
|
||||
-- @param item: item ID (number) or item name (string)
|
||||
-- @return remainingSeconds, totalDuration, enabled
|
||||
function CleveRoids.GetItemCooldownCached(item)
|
||||
local location = CleveRoids.FindItemLocation(item)
|
||||
if not location then
|
||||
return 0, 0, 0
|
||||
end
|
||||
|
||||
local start, duration, enable
|
||||
if location.type == "inventory" then
|
||||
start, duration, enable = GetInventoryItemCooldown("player", location.inventoryID)
|
||||
else
|
||||
start, duration, enable = GetContainerItemCooldown(location.bag, location.slot)
|
||||
end
|
||||
|
||||
-- Normalize cooldown values
|
||||
start = tonumber(start) or 0
|
||||
duration = tonumber(duration) or 0
|
||||
enable = tonumber(enable) or 0
|
||||
|
||||
if duration <= 0 or start <= 0 then
|
||||
return 0, 0, enable
|
||||
end
|
||||
|
||||
local remaining = (start + duration) - GetTime()
|
||||
if remaining < 0 then remaining = 0 end
|
||||
|
||||
return remaining, duration, enable
|
||||
end
|
||||
|
||||
--This table maps stat keys to the functions that retrieve their values.
|
||||
local stat_checks = {
|
||||
-- Base Stats (Corrected to use the 'effective' stat with gear)
|
||||
@@ -1862,82 +1968,35 @@ end
|
||||
|
||||
-- Check if an item exists in bags or equipped
|
||||
-- Returns: true if found, false otherwise
|
||||
-- PERFORMANCE: Uses CleveRoids.Items cache for O(1) lookup, with fallback for substring matches
|
||||
function CleveRoids.HasItem(item)
|
||||
-- Case A: numeric value passed
|
||||
local numericItem = tonumber(item)
|
||||
if numericItem then
|
||||
-- Is it an inventory slot?
|
||||
if numericItem >= 1 and numericItem <= 19 then
|
||||
local link = GetInventoryItemLink("player", numericItem)
|
||||
return link ~= nil
|
||||
end
|
||||
|
||||
-- Otherwise, treat it as an item ID - search equipped items first
|
||||
for slot = 0, 19 do
|
||||
local link = GetInventoryItemLink("player", slot)
|
||||
if link then
|
||||
local _, _, id = string.find(link, "item:(%d+)")
|
||||
if id and tonumber(id) == numericItem then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Then search bags for the item ID
|
||||
for bag = 0, 4 do
|
||||
local size = GetContainerNumSlots(bag)
|
||||
if size and size > 0 then
|
||||
for slotIndex = 1, size do
|
||||
local link = GetContainerItemLink(bag, slotIndex)
|
||||
if link then
|
||||
local _, _, id = string.find(link, "item:(%d+)")
|
||||
if id and tonumber(id) == numericItem then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Item ID not found
|
||||
return false
|
||||
-- Fast path: check cache first (O(1) lookup)
|
||||
if CleveRoids.HasItemCached(item) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Case B: string item name -> try equipped slots first
|
||||
-- Slow path fallback: only needed for substring matching on strings
|
||||
-- The cache handles exact matches by ID and name, but not partial/substring matches
|
||||
if type(item) == "string" and item ~= "" then
|
||||
local itemLower = string.lower(item)
|
||||
|
||||
-- Check equipped slots
|
||||
local slots = { 13, 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19 } -- trinkets first
|
||||
for i = 1, table.getn(slots) do
|
||||
local s = slots[i]
|
||||
local link = GetInventoryItemLink("player", s)
|
||||
-- Check equipped slots for substring match
|
||||
for slot = 0, 19 do
|
||||
local link = GetInventoryItemLink("player", slot)
|
||||
if link then
|
||||
-- Extract item name from link using pattern [ItemName]
|
||||
local _, _, linkName = string.find(link, "%[(.+)%]")
|
||||
if linkName and string.lower(linkName) == itemLower then
|
||||
return true
|
||||
end
|
||||
-- Fallback: simple substring match
|
||||
if string.find(string.lower(link), itemLower, 1, true) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Search bags for the named item
|
||||
-- Check bags for substring match
|
||||
for bag = 0, 4 do
|
||||
local size = GetContainerNumSlots(bag)
|
||||
if size and size > 0 then
|
||||
for slotIndex = 1, size do
|
||||
local link = GetContainerItemLink(bag, slotIndex)
|
||||
if link then
|
||||
-- Extract item name from link using pattern [ItemName]
|
||||
local _, _, linkName = string.find(link, "%[(.+)%]")
|
||||
if linkName and string.lower(linkName) == itemLower then
|
||||
return true
|
||||
end
|
||||
-- Fallback: simple substring match
|
||||
if string.find(string.lower(link), itemLower, 1, true) then
|
||||
return true
|
||||
end
|
||||
@@ -1947,16 +2006,15 @@ function CleveRoids.HasItem(item)
|
||||
end
|
||||
end
|
||||
|
||||
-- Item not found
|
||||
return false
|
||||
end
|
||||
|
||||
-- TODO: Look into https://github.com/Stanzilla/WoWUIBugs/issues/47 if needed
|
||||
-- Hardened item cooldown resolver (Vanilla 1.12.1 / Lua 5.0)
|
||||
-- Returns: remainingSeconds, totalDuration, enabled
|
||||
-- PERFORMANCE: Uses CleveRoids.Items cache for O(1) lookup, with fallback for substring matches
|
||||
function CleveRoids.GetItemCooldown(item)
|
||||
local start, duration, enable = nil, nil, nil
|
||||
|
||||
-- Helper to normalize cooldown values
|
||||
local function _norm(s, d, e)
|
||||
s = tonumber(s) or 0
|
||||
d = tonumber(d) or 0
|
||||
@@ -1969,94 +2027,44 @@ function CleveRoids.GetItemCooldown(item)
|
||||
return rem, d, e
|
||||
end
|
||||
|
||||
-- Helper: Check if a numeric value is a valid inventory slot (1-19)
|
||||
local function _isInventorySlot(num)
|
||||
return num and num >= 1 and num <= 19
|
||||
-- Fast path: check cache first (O(1) lookup)
|
||||
local remaining, duration, enable = CleveRoids.GetItemCooldownCached(item)
|
||||
if duration > 0 or remaining > 0 then
|
||||
return remaining, duration, enable
|
||||
end
|
||||
|
||||
-- Case A: numeric value passed
|
||||
local numericItem = tonumber(item)
|
||||
if numericItem then
|
||||
-- Is it an inventory slot?
|
||||
if _isInventorySlot(numericItem) then
|
||||
start, duration, enable = GetInventoryItemCooldown("player", numericItem)
|
||||
return _norm(start, duration, enable)
|
||||
end
|
||||
-- If cache found the item but cooldown is 0, that's a valid result
|
||||
local location = CleveRoids.FindItemLocation(item)
|
||||
if location then
|
||||
return 0, 0, enable or 0
|
||||
end
|
||||
|
||||
-- Otherwise, treat it as an item ID - search equipped items first
|
||||
-- Slow path fallback: only needed for substring matching on strings
|
||||
if type(item) == "string" and item ~= "" then
|
||||
local itemLower = string.lower(item)
|
||||
local start, dur, en
|
||||
|
||||
-- Check equipped slots for substring match
|
||||
for slot = 0, 19 do
|
||||
local link = GetInventoryItemLink("player", slot)
|
||||
if link then
|
||||
local _, _, id = string.find(link, "item:(%d+)")
|
||||
if id and tonumber(id) == numericItem then
|
||||
start, duration, enable = GetInventoryItemCooldown("player", slot)
|
||||
return _norm(start, duration, enable)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Then search bags for the item ID
|
||||
for bag = 0, 4 do
|
||||
local size = GetContainerNumSlots(bag)
|
||||
if size and size > 0 then
|
||||
for slotIndex = 1, size do
|
||||
local link = GetContainerItemLink(bag, slotIndex)
|
||||
if link then
|
||||
local _, _, id = string.find(link, "item:(%d+)")
|
||||
if id and tonumber(id) == numericItem then
|
||||
start, duration, enable = GetContainerItemCooldown(bag, slotIndex)
|
||||
return _norm(start, duration, enable)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Item ID not found in inventory or bags
|
||||
return 0, 0, 0
|
||||
end
|
||||
|
||||
-- Case B: string item name -> try equipped slots first
|
||||
if type(item) == "string" and item ~= "" then
|
||||
local itemLower = string.lower(item)
|
||||
|
||||
-- scan a few common equipment slots; expand if your engine needs more
|
||||
local slots = { 13, 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19 } -- trinkets first
|
||||
for i = 1, table.getn(slots) do
|
||||
local s = slots[i]
|
||||
local link = GetInventoryItemLink("player", s)
|
||||
if link then
|
||||
-- Extract item name from link using pattern [ItemName]
|
||||
local _, _, linkName = string.find(link, "%[(.+)%]")
|
||||
if linkName and string.lower(linkName) == itemLower then
|
||||
start, duration, enable = GetInventoryItemCooldown("player", s)
|
||||
return _norm(start, duration, enable)
|
||||
end
|
||||
-- Fallback: simple substring match
|
||||
if string.find(string.lower(link), itemLower, 1, true) then
|
||||
start, duration, enable = GetInventoryItemCooldown("player", s)
|
||||
return _norm(start, duration, enable)
|
||||
start, dur, en = GetInventoryItemCooldown("player", slot)
|
||||
return _norm(start, dur, en)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Case C: search bags for the named item
|
||||
-- Check bags for substring match
|
||||
for bag = 0, 4 do
|
||||
local size = GetContainerNumSlots(bag)
|
||||
if size and size > 0 then
|
||||
for slotIndex = 1, size do
|
||||
local link = GetContainerItemLink(bag, slotIndex)
|
||||
if link then
|
||||
-- Extract item name from link using pattern [ItemName]
|
||||
local _, _, linkName = string.find(link, "%[(.+)%]")
|
||||
if linkName and string.lower(linkName) == itemLower then
|
||||
start, duration, enable = GetContainerItemCooldown(bag, slotIndex)
|
||||
return _norm(start, duration, enable)
|
||||
end
|
||||
-- Fallback: simple substring match
|
||||
if string.find(string.lower(link), itemLower, 1, true) then
|
||||
start, duration, enable = GetContainerItemCooldown(bag, slotIndex)
|
||||
return _norm(start, duration, enable)
|
||||
start, dur, en = GetContainerItemCooldown(bag, slotIndex)
|
||||
return _norm(start, dur, en)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -523,34 +523,74 @@ local function CRM_GetBagScanTip()
|
||||
end
|
||||
|
||||
-- Return total in *bags only* (not bank), by id when possible; fallback to name
|
||||
-- PERFORMANCE: Uses CleveRoids.Items cache for O(1) lookup when available
|
||||
function CleveRoids.GetReagentCount(reagentName)
|
||||
if not reagentName or reagentName == "" then return 0 end
|
||||
|
||||
-- Fast path: check cache first
|
||||
local Items = CleveRoids.Items
|
||||
if Items then
|
||||
local wantId = _ReagentIdByName[reagentName]
|
||||
|
||||
-- Try by ID first if we have a mapping
|
||||
if wantId then
|
||||
local itemName = Items[wantId]
|
||||
if itemName then
|
||||
local itemData = Items[itemName]
|
||||
if itemData and itemData.count and not itemData.inventoryID then
|
||||
-- Item is in bags (not equipped), return cached count
|
||||
return itemData.count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Try by name
|
||||
local itemData = Items[reagentName]
|
||||
if type(itemData) == "string" then
|
||||
itemData = Items[itemData] -- Resolve indirection
|
||||
end
|
||||
if itemData and type(itemData) == "table" and itemData.count and not itemData.inventoryID then
|
||||
return itemData.count
|
||||
end
|
||||
|
||||
-- Try lowercase
|
||||
local lowerName = string.lower(reagentName)
|
||||
local resolved = Items[lowerName]
|
||||
if type(resolved) == "string" then
|
||||
itemData = Items[resolved]
|
||||
elseif type(resolved) == "table" then
|
||||
itemData = resolved
|
||||
end
|
||||
if itemData and type(itemData) == "table" and itemData.count and not itemData.inventoryID then
|
||||
return itemData.count
|
||||
end
|
||||
end
|
||||
|
||||
-- Slow path fallback: full bag scan (only when cache miss)
|
||||
local wantId = _ReagentIdByName[reagentName]
|
||||
local total = 0
|
||||
|
||||
for bag = 0, 4 do
|
||||
local slots = GetContainerNumSlots(bag) or 0
|
||||
for slot = 1, slots do
|
||||
local _, count = GetContainerItemInfo(bag, slot)
|
||||
count = count or 0
|
||||
-- Prefer link → id when available
|
||||
local link = (GetContainerItemLink and GetContainerItemLink(bag, slot)) or nil
|
||||
local _, count = GetContainerItemInfo(bag, slot)
|
||||
count = count or 0
|
||||
local link = GetContainerItemLink and GetContainerItemLink(bag, slot)
|
||||
if link then
|
||||
local _, _, idstr = string.find(link, "item:(%d+)")
|
||||
local id = idstr and tonumber(idstr) or nil
|
||||
local _, _, idstr = string.find(link, "item:(%d+)")
|
||||
local id = idstr and tonumber(idstr) or nil
|
||||
if (wantId and id == wantId) or (not wantId and string.find(link, "%["..reagentName.."%]")) then
|
||||
total = total + (count or 0)
|
||||
total = total + count
|
||||
end
|
||||
else
|
||||
-- Fallback: scan bag slot tooltip for the name
|
||||
-- Fallback: scan bag slot tooltip for the name (expensive, only when no link)
|
||||
local tip = CRM_GetBagScanTip()
|
||||
tip:ClearLines()
|
||||
tip:SetBagItem(bag, slot)
|
||||
local left1 = _G[tip:GetName().."TextLeft1"]
|
||||
local name = left1 and left1:GetText()
|
||||
if name and name == reagentName then
|
||||
total = total + (count or 0)
|
||||
total = total + count
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2410,44 +2450,28 @@ function CleveRoids.DoUse(msg)
|
||||
return
|
||||
end
|
||||
|
||||
-- NEW: Try to interpret as an item ID (numeric but > 19)
|
||||
if slotId and slotId > 19 then
|
||||
-- Search equipped slots for this item ID
|
||||
for slot = 0, 19 do
|
||||
local link = GetInventoryItemLink("player", slot)
|
||||
if link then
|
||||
local _, _, id = string.find(link, "item:(%d+)")
|
||||
if id and tonumber(id) == slotId then
|
||||
ClearCursor()
|
||||
UseInventoryItem(slot)
|
||||
return
|
||||
end
|
||||
-- PERFORMANCE: Try cache lookup first (O(1) instead of O(n) scan)
|
||||
local location = CleveRoids.FindItemLocation(msg)
|
||||
if location then
|
||||
ClearCursor()
|
||||
if location.type == "inventory" then
|
||||
if CleveRoids.equipDebugLog then
|
||||
CleveRoids.Print("|cff888888[UseLog] /use " .. msg .. " via UseInventoryItem(" .. location.inventoryID .. ") [cached]|r")
|
||||
end
|
||||
end
|
||||
|
||||
-- Search bags for this item ID
|
||||
for bag = 0, 4 do
|
||||
local size = GetContainerNumSlots(bag) or 0
|
||||
for bagSlot = 1, size do
|
||||
local link = GetContainerItemLink(bag, bagSlot)
|
||||
if link then
|
||||
local _, _, id = string.find(link, "item:(%d+)")
|
||||
if id and tonumber(id) == slotId then
|
||||
ClearCursor()
|
||||
UseContainerItem(bag, bagSlot)
|
||||
return
|
||||
end
|
||||
end
|
||||
UseInventoryItem(location.inventoryID)
|
||||
else
|
||||
if CleveRoids.equipDebugLog then
|
||||
CleveRoids.Print("|cff888888[UseLog] /use " .. msg .. " via UseContainerItem(" .. location.bag .. "," .. location.slot .. ") [cached]|r")
|
||||
end
|
||||
UseContainerItem(location.bag, location.slot)
|
||||
end
|
||||
|
||||
-- Item ID not found
|
||||
return
|
||||
end
|
||||
|
||||
-- Search equipped inventory slots first (for trinkets, etc.)
|
||||
-- Slow path fallback: full scan for substring matches or cache miss
|
||||
local qname = string_lower(msg)
|
||||
|
||||
-- Search equipped inventory slots first (for trinkets, etc.)
|
||||
for slot = 0, 19 do
|
||||
local link = GetInventoryItemLink("player", slot)
|
||||
if link then
|
||||
@@ -2463,7 +2487,7 @@ function CleveRoids.DoUse(msg)
|
||||
end
|
||||
end
|
||||
|
||||
-- Then search bags - no cache, no Nampower API (causes crashes)
|
||||
-- Then search bags
|
||||
for bag = 0, 4 do
|
||||
local numSlots = GetContainerNumSlots(bag) or 0
|
||||
for bagSlot = 1, numSlots do
|
||||
@@ -2472,7 +2496,7 @@ function CleveRoids.DoUse(msg)
|
||||
local _, _, nm = string_find(link, "|h%[(.-)%]|h")
|
||||
if nm and string_lower(nm) == qname then
|
||||
if CleveRoids.equipDebugLog then
|
||||
CleveRoids.Print("|cff888888[EquipLog] /equip " .. msg .. " via UseContainerItem(" .. bag .. "," .. bagSlot .. ")|r")
|
||||
CleveRoids.Print("|cff888888[UseLog] /use " .. msg .. " via UseContainerItem(" .. bag .. "," .. bagSlot .. ")|r")
|
||||
end
|
||||
ClearCursor()
|
||||
UseContainerItem(bag, bagSlot)
|
||||
@@ -2813,6 +2837,12 @@ function CleveRoids.OnUpdate(self)
|
||||
return
|
||||
end
|
||||
|
||||
-- PERFORMANCE: Delayed WDB warmup after login (ensures GetItemInfo works after WDB clear)
|
||||
if CleveRoids.wdbWarmupTime and time >= CleveRoids.wdbWarmupTime then
|
||||
CleveRoids.wdbWarmupTime = nil
|
||||
CleveRoids.DoWDBWarmup()
|
||||
end
|
||||
|
||||
-- PERFORMANCE: Cache refresh rate calculation (avoid per-frame division)
|
||||
local refreshRate = CleveRoids.cachedRefreshRate
|
||||
if not refreshRate then
|
||||
@@ -3550,6 +3580,59 @@ function CleveRoids.Frame:PLAYER_LOGIN()
|
||||
CleveRoids.IndexPetSpells()
|
||||
CleveRoids.initializationTimer = GetTime() + 1.5
|
||||
CRM_SM_InstallHook()
|
||||
|
||||
-- Schedule delayed WDB warmup (loads items into client cache via tooltip scan)
|
||||
-- This ensures GetItemInfo() works for all inventory items after a WDB clear
|
||||
CleveRoids.wdbWarmupTime = GetTime() + 3.0 -- 3 second delay after login
|
||||
end
|
||||
|
||||
-- PERFORMANCE: WDB warmup - tooltip scan all bag items to ensure they're cached
|
||||
-- This prevents GetItemInfo() returning nil for items after a WDB clear
|
||||
function CleveRoids.DoWDBWarmup()
|
||||
if CleveRoids.wdbWarmupDone then return end
|
||||
CleveRoids.wdbWarmupDone = true
|
||||
|
||||
-- Create a hidden tooltip for scanning if it doesn't exist
|
||||
local tip = CleveRoidsWDBTip
|
||||
if not tip then
|
||||
tip = CreateFrame("GameTooltip", "CleveRoidsWDBTip", UIParent, "GameTooltipTemplate")
|
||||
tip:SetOwner(WorldFrame, "ANCHOR_NONE")
|
||||
end
|
||||
|
||||
local scanned = 0
|
||||
|
||||
-- Scan all bag slots
|
||||
for bag = 0, 4 do
|
||||
local slots = GetContainerNumSlots(bag) or 0
|
||||
for slot = 1, slots do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
if link then
|
||||
-- Tooltip scan loads the item into WDB
|
||||
tip:ClearLines()
|
||||
tip:SetBagItem(bag, slot)
|
||||
scanned = scanned + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Scan equipped items
|
||||
for slot = 0, 19 do
|
||||
local link = GetInventoryItemLink("player", slot)
|
||||
if link then
|
||||
tip:ClearLines()
|
||||
tip:SetInventoryItem("player", slot)
|
||||
scanned = scanned + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Now trigger a full item index to populate the cache with valid data
|
||||
if CleveRoids.IndexItems then
|
||||
CleveRoids.IndexItems()
|
||||
end
|
||||
|
||||
if CleveRoids.debug then
|
||||
CleveRoids.Print("|cff88ff88[WDB Warmup]|r Scanned " .. scanned .. " items into cache")
|
||||
end
|
||||
end
|
||||
|
||||
function CleveRoids.Frame:ADDON_LOADED(addon)
|
||||
|
||||
@@ -219,10 +219,44 @@ function CleveRoids.IndexEquipSlot(inventoryID)
|
||||
end
|
||||
|
||||
|
||||
-- PERFORMANCE: Persistent cache for GetItemInfo results (survives between IndexItems calls)
|
||||
-- This prevents repeated GetItemInfo calls for the same itemID
|
||||
local _itemInfoCache = {}
|
||||
local _itemInfoCacheSize = 0
|
||||
local _ITEM_INFO_CACHE_MAX = 500 -- Limit cache size
|
||||
|
||||
local function GetCachedItemInfo(itemID)
|
||||
local cached = _itemInfoCache[itemID]
|
||||
if cached then
|
||||
return cached.name, cached.link, cached.quality, cached.level, cached.type, cached.subType, cached.stackCount, cached.equipLoc, cached.texture
|
||||
end
|
||||
|
||||
local name, link, quality, level, itemType, subType, stackCount, equipLoc, texture = GetItemInfo(itemID)
|
||||
if name then
|
||||
-- Cache the result
|
||||
if _itemInfoCacheSize < _ITEM_INFO_CACHE_MAX then
|
||||
_itemInfoCache[itemID] = {
|
||||
name = name, link = link, quality = quality, level = level,
|
||||
type = itemType, subType = subType, stackCount = stackCount,
|
||||
equipLoc = equipLoc, texture = texture
|
||||
}
|
||||
_itemInfoCacheSize = _itemInfoCacheSize + 1
|
||||
end
|
||||
end
|
||||
return name, link, quality, level, itemType, subType, stackCount, equipLoc, texture
|
||||
end
|
||||
|
||||
function CleveRoids.IndexItems()
|
||||
local items = {}
|
||||
local NUM_BAG_SLOTS = NUM_BAG_SLOTS -- Upvalue for bag constant
|
||||
|
||||
-- PERFORMANCE: Local function references
|
||||
local GetContainerNumSlots = GetContainerNumSlots
|
||||
local GetContainerItemLink = GetContainerItemLink
|
||||
local GetContainerItemInfo = GetContainerItemInfo
|
||||
local GetInventoryItemLink = GetInventoryItemLink
|
||||
local GetInventoryItemCount = GetInventoryItemCount
|
||||
|
||||
-- Scan bags (reverse order to prefer first stack)
|
||||
for bagID = 0, NUM_BAG_SLOTS do
|
||||
local numSlots = GetContainerNumSlots(bagID)
|
||||
@@ -230,12 +264,22 @@ function CleveRoids.IndexItems()
|
||||
local link = GetContainerItemLink(bagID, slot)
|
||||
if link then
|
||||
local _, _, itemID = string_find(link, "item:(%d+)")
|
||||
local name, itemLink, _, _, itemType, itemSubType, _, _, texture = GetItemInfo(itemID)
|
||||
|
||||
if name then
|
||||
-- PERFORMANCE: Try to extract name from link first to check for duplicates
|
||||
local _, _, linkName = string_find(link, "%[(.+)%]")
|
||||
local existing = linkName and items[linkName]
|
||||
|
||||
if existing then
|
||||
-- Item already seen - just update count and add bag slot (skip GetItemInfo)
|
||||
local _, count = GetContainerItemInfo(bagID, slot)
|
||||
local existing = items[name]
|
||||
if not existing then
|
||||
existing.count = (existing.count or 0) + (count or 0)
|
||||
table_insert(existing.bagSlots, {bagID, slot})
|
||||
else
|
||||
-- New item - need full info
|
||||
local name, itemLink, _, _, itemType, itemSubType, _, _, texture = GetCachedItemInfo(itemID)
|
||||
|
||||
if name then
|
||||
local _, count = GetContainerItemInfo(bagID, slot)
|
||||
items[name] = {
|
||||
bagID = bagID,
|
||||
slot = slot,
|
||||
@@ -253,9 +297,6 @@ function CleveRoids.IndexItems()
|
||||
if lowerName ~= name then
|
||||
items[lowerName] = name
|
||||
end
|
||||
else
|
||||
existing.count = (existing.count or 0) + (count or 0)
|
||||
table_insert(existing.bagSlots, {bagID, slot})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -267,11 +308,21 @@ function CleveRoids.IndexItems()
|
||||
local link = GetInventoryItemLink("player", inventoryID)
|
||||
if link then
|
||||
local _, _, itemID = string_find(link, "item:(%d+)")
|
||||
local name, itemLink, _, _, itemType, itemSubType, _, _, texture = GetItemInfo(itemID)
|
||||
if name then
|
||||
|
||||
-- PERFORMANCE: Try to extract name from link first
|
||||
local _, _, linkName = string_find(link, "%[(.+)%]")
|
||||
local existing = linkName and items[linkName]
|
||||
|
||||
if existing then
|
||||
-- Item in bags AND equipped - update existing entry
|
||||
existing.inventoryID = inventoryID
|
||||
local count = GetInventoryItemCount("player", inventoryID)
|
||||
local existing = items[name]
|
||||
if not existing then
|
||||
existing.count = (existing.count or 0) + (count or 0)
|
||||
else
|
||||
-- New equipped-only item
|
||||
local name, itemLink, _, _, itemType, itemSubType, _, _, texture = GetCachedItemInfo(itemID)
|
||||
if name then
|
||||
local count = GetInventoryItemCount("player", inventoryID)
|
||||
items[name] = {
|
||||
inventoryID = inventoryID,
|
||||
id = itemID,
|
||||
@@ -285,9 +336,6 @@ function CleveRoids.IndexItems()
|
||||
if lowerName ~= name then
|
||||
items[lowerName] = name
|
||||
end
|
||||
else
|
||||
existing.inventoryID = inventoryID
|
||||
existing.count = (existing.count or 0) + (count or 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user