Mercurial > wow > inventory
diff Scanner.lua @ 80:c0bf2ddb5288
Added initial item refilling from the bank/guild. Not yet fully functional.
author | Zerotorescue |
---|---|
date | Wed, 05 Jan 2011 13:05:15 +0100 |
parents | |
children | 58617c7827fa |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Scanner.lua Wed Jan 05 13:05:15 2011 +0100 @@ -0,0 +1,236 @@ +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 _GetItemCount(itemId, location) + if location == addon.Locations.Bank then + -- No longer using GetItemCount as this includes equiped items and containers (e.g. bank bags) + --return (GetItemCount(itemId, true) - GetItemCount(itemId, false)); -- GetItemCount(X, true) provides count for bag+bank, GetItemCount(X, false) provides just bag, so (GetItemCount(X, true) - GetItemCount(X, false)) = just bank + return ((itemCache[itemId] and itemCache[itemId].totalCount) or 0); + elseif location == addon.Locations.Guild then + return ((itemCache[itemId] and itemCache[itemId].totalCount) or 0); + else + error("Invalid location provided for the local _GetItemCount. Must be Bag or Bank."); + end +end + +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, ((addon.Locations.Bag and stop) or (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.ItemMove:New(); + 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.ItemMove:New(); + 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 + local missingItems = (minLocalStock - addon:GetLocalItemCount(itemId, groupName)); + + if missingItems > 0 then + -- Check how many are available + local availableItems = _GetItemCount(itemId, location); + + if availableItems > 0 then + print("Insufficient " .. select(2, GetItemInfo(itemId)) .. " but this location has " .. availableItems .. " (moving " .. missingItems .. ")"); + + Mover:AddMove(itemId, missingItems); + else + print("Insufficient " .. select(2, GetItemInfo(itemId))); + end + end + end + end + end + + self:ClearCache(); + + self:Pause(); + Mover:BeginMove(location, self.Unpause); +end + +local function BANKFRAME_OPENED() + -- Scan once when the bank is opened, but no need to scan after + mod:Scan(addon.Locations.Bank); + + addon:Debug("Scanner:BANKFRAME_OPENED"); +end + +-- Remember which tabs were scanned and don't scan them again +local guildBankTabsScanned = {}; + +local function GUILDBANKFRAME_CLOSED() + mod:UnregisterEvent("GUILDBANKFRAME_CLOSED"); + mod:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED"); + + table.wipe(guildBankTabsScanned); + + addon:Debug("Scanner:GUILDBANKFRAME_CLOSED"); +end + +local function GUILDBANKBAGSLOTS_CHANGED() + if not guildBankTabsScanned[GetCurrentGuildBankTab()] then + mod:Scan(addon.Locations.Guild); + guildBankTabsScanned[GetCurrentGuildBankTab()] = true; + + addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - scanning"); + else + addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - not scanning"); + end +end + +local function GUILDBANKFRAME_OPENED() + table.wipe(guildBankTabsScanned); + + mod:RegisterEvent("GUILDBANKFRAME_CLOSED", GUILDBANKFRAME_CLOSED); + mod:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED", GUILDBANKBAGSLOTS_CHANGED); + + addon:Debug("Scanner:GUILDBANKFRAME_OPENED"); +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