Mercurial > wow > inventory
view Scanner.lua @ 81:58617c7827fa
Item refilling should now be working. Probably very slow if your bags, bank or guild bank is filled with over 200 unique items or so (needs some real testing, but know that it is a known (possible) issue).
author | Zerotorescue |
---|---|
date | Thu, 06 Jan 2011 01:01:25 +0100 |
parents | c0bf2ddb5288 |
children | f885805da5d6 |
line wrap: on
line source
local addon = select(2, ...); local mod = addon:NewModule("Scanner", "AceEvent-3.0"); addon.Locations = { Bag = 0, Bank = 1, Guild = 2, }; local Mover, paused; local itemCache = {}; local function GetItemID(link) return tonumber(link:match("|Hitem:([-0-9]+):")); end function mod:ClearCache() table.wipe(itemCache); end function mod:CacheLocation(location, remember) if location == addon.Locations.Bag or location == addon.Locations.Bank then -- Reset cache just in case it was filled self:ClearCache(); local start, stop; if location == addon.Locations.Bag then start = 0; stop = NUM_BAG_SLOTS; else -- If we requested the bank then we don't want the bag info start = ( NUM_BAG_SLOTS + 1 ); stop = ( NUM_BAG_SLOTS + NUM_BANKBAGSLOTS ); end -- Go through all our bags, including the backpack for i = start, ((location == addon.Locations.Bag and stop) or (location == addon.Locations.Bank and (stop + 1))) do -- if scanning bags stop at normal bag slot, if scanning bank, stop one later to allow BANK_CONTAINER to be scanned too -- Scan the default 100 slots whenever we're at a non-existing index local bagId = (i == (stop + 1) and BANK_CONTAINER) or i; local slotId = GetContainerNumSlots(bagId); while slotId ~= 0 do -- A not equal-comparison should be quicker than a larger than-comparison local itemId = GetContainerItemID(bagId, slotId); local itemCount = itemId and select(2, GetContainerItemInfo(bagId, slotId)); if itemId and itemCount and itemCount > 0 then local itemMove; if not itemCache[itemId] then -- If this is the first time we see this item, make a new object itemMove = addon.ContainerItem:New(); itemCache[itemId] = itemMove; else -- If we had this item in another slot too itemMove = itemCache[itemId]; end itemMove:AddLocation(bagId, slotId, itemCount); end -- Continue scanning a different slot slotId = (slotId - 1); end end elseif location == addon.Locations.Guild then -- Reset cache before we scan self:ClearCache(); local tabId = GetCurrentGuildBankTab(); local slotId = (MAX_GUILDBANK_SLOTS_PER_TAB or 98); -- start by scanning the last slot if tabId == nil or tabId < 1 then return; end while slotId ~= 0 do -- A not equal-comparison should be quicker than a larger than-comparison -- If there is actually an item in this slot local itemLink = GetGuildBankItemLink(tabId, slotId); local itemId = itemLink and GetItemId(itemLink); local itemCount = itemLink and select(2, GetGuildBankItemInfo(tabId, slotId)); if itemLink and itemId and itemCount and itemCount > 0 then local itemMove; if not itemCache[itemId] then -- If this is the first time we see this item, make a new object itemMove = addon.ContainerItem:New(); itemCache[itemId] = itemMove; else -- If we had this item in another slot too itemMove = itemCache[itemId]; end itemMove:AddLocation(tabId, slotId, itemCount); end -- Continue scanning a different slot slotId = (slotId - 1); end else error("Invalid location provided for the local _GetItemCount. Must be Bank or Guild."); end if not remember then -- Copy the table as clearing the cache wipes it empty (and tables are passed by reference) local cacheCopy = CopyTable(itemCache); self:ClearCache(); return cacheCopy; end end function mod:Scan(location) -- We might pause the scanning when we invoke moves ourself if paused then return; end local playerName = UnitName("player"); self:CacheLocation(location, true); -- Go through all groups for groupName, values in pairs(addon.db.profile.groups) do local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters"); if values.items and trackAt[playerName] then -- Is this character interested in this data? local minLocalStock = addon:GetOptionByKey(groupName, "minLocalStock"); -- Go through all items for itemId, _ in pairs(values.items) do -- Check if we have enough items local (but only do so if this location also has enough available) local missingItems = itemCache[itemId] and (minLocalStock - addon:GetLocalItemCount(itemId, groupName)); if itemCache[itemId] and missingItems > 0 then -- Check how many are available local availableItems = ((itemCache[itemId] and itemCache[itemId].totalCount) or 0); if availableItems > 0 then print("Insufficient " .. select(2, GetItemInfo(itemId)) .. " but this location has " .. availableItems .. " (moving " .. missingItems .. ")"); Mover:AddMove(itemId, missingItems); else print("Insufficient " .. IdToItemLink(itemId)); end end end end end self:ClearCache(); if Mover:HasMoves() then StaticPopupDialogs["InventoriumRefill"] = { text = "There are items that can be refilled from this location, do you wish to proceed?", button1 = YES, button2 = NO, OnAccept = function() mod:Pause(); Mover:BeginMove(location, self.Unpause); end, timeout = 0, whileDead = 1, hideOnEscape = 1, }; StaticPopup_Show("InventoriumRefill"); end end local function BANKFRAME_CLOSED() addon:Debug("Scanner:BANKFRAME_CLOSED"); mod:UnregisterEvent("BANKFRAME_CLOSED"); StaticPopup_Hide("InventoriumRefill"); end local function BANKFRAME_OPENED() addon:Debug("Scanner:BANKFRAME_OPENED"); mod:RegisterEvent("BANKFRAME_CLOSED", BANKFRAME_CLOSED); -- Scan once when the bank is opened, but no need to scan after mod:Scan(addon.Locations.Bank); end -- Remember which tabs were scanned and don't scan them again local guildBankTabsScanned = {}; local function GUILDBANKFRAME_CLOSED() addon:Debug("Scanner:GUILDBANKFRAME_CLOSED"); table.wipe(guildBankTabsScanned); mod:UnregisterEvent("GUILDBANKFRAME_CLOSED"); mod:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED"); StaticPopup_Hide("InventoriumRefill"); end local function GUILDBANKBAGSLOTS_CHANGED() if not guildBankTabsScanned[GetCurrentGuildBankTab()] then addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - scanning"); mod:Scan(addon.Locations.Guild); guildBankTabsScanned[GetCurrentGuildBankTab()] = true; else addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - not scanning"); end end local function GUILDBANKFRAME_OPENED() addon:Debug("Scanner:GUILDBANKFRAME_OPENED"); table.wipe(guildBankTabsScanned); mod:RegisterEvent("GUILDBANKFRAME_CLOSED", GUILDBANKFRAME_CLOSED); mod:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED", GUILDBANKBAGSLOTS_CHANGED); end function mod:OnEnable() -- Scan once when the bankframe is opened mod:RegisterEvent("BANKFRAME_OPENED", BANKFRAME_OPENED); mod:RegisterEvent("GUILDBANKFRAME_OPENED", GUILDBANKFRAME_OPENED); Mover = addon:GetModule("Mover"); end function mod:OnDisable() Mover = nil; -- Bank mod:UnregisterEvent("BANKFRAME_OPENED"); -- Guild GUILDBANKFRAME_CLOSED(); mod:UnregisterEvent("GUILDBANKFRAME_OPENED"); end function mod:Pause() paused = true; end function mod:Unpause() paused = nil; end