Zerotorescue@80: local addon = select(2, ...); Zerotorescue@84: local mod = addon:NewModule("Scanner", "AceEvent-3.0", "AceTimer-3.0"); Zerotorescue@80: Zerotorescue@122: local _G = _G; Zerotorescue@122: local select, pairs = _G.select, _G.pairs; Zerotorescue@122: local twipe, tinsert, mceil = _G.table.wipe, _G.table.insert, _G.math.ceil; Zerotorescue@122: Zerotorescue@101: local Mover, paused, currentLocation; Zerotorescue@80: local itemCache = {}; Zerotorescue@80: Zerotorescue@110: local function OnMoveAccept() Zerotorescue@101: mod:Pause(); Zerotorescue@101: Mover:BeginMove(currentLocation, mod.Unpause); Zerotorescue@101: Zerotorescue@142: if InventoriumItemMover then Zerotorescue@142: InventoriumItemMover:Hide(); Zerotorescue@142: end Zerotorescue@101: end Zerotorescue@101: Zerotorescue@110: local function OnMoveCancel() Zerotorescue@101: Mover:ResetQueue(); Zerotorescue@101: currentLocation = nil; Zerotorescue@101: Zerotorescue@142: if InventoriumItemMover then Zerotorescue@142: InventoriumItemMover:Hide(); Zerotorescue@142: end Zerotorescue@101: end Zerotorescue@101: Zerotorescue@119: local function GetSmallCoinTextureString(coins) Zerotorescue@119: if coins >= 10000000 then Zerotorescue@119: -- When we have1000g, hide silver and copper Zerotorescue@122: coins = (mceil(coins / 10000) * 10000); Zerotorescue@119: elseif coins >= 10000 then Zerotorescue@119: -- When we have 1g, hide copper Zerotorescue@122: coins = (mceil(coins / 100) * 100); Zerotorescue@119: end Zerotorescue@119: Zerotorescue@119: return GetCoinTextureString(coins); Zerotorescue@119: end Zerotorescue@119: Zerotorescue@119: -- Refill moves window: refill form storage such as the bank, guild bank and mailbox Zerotorescue@111: local function UseStorageRefillST() Zerotorescue@142: if not InventoriumItemMover then Zerotorescue@142: addon:CreateMoverFrame(); Zerotorescue@142: end Zerotorescue@142: Zerotorescue@110: local frame = InventoriumItemMover; -- both for speed as code-consistency Zerotorescue@110: Zerotorescue@110: -- Scrolling table with a list of items to be moved Zerotorescue@110: local scrollTableWidth = ( frame.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size Zerotorescue@110: local headers = { Zerotorescue@110: { Zerotorescue@110: ["name"] = "Item", Zerotorescue@111: ["width"] = (scrollTableWidth * .60), Zerotorescue@110: ["defaultsort"] = "asc", Zerotorescue@110: ["comparesort"] = function(this, aRow, bRow, column) Zerotorescue@110: local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId); Zerotorescue@110: local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId); Zerotorescue@110: local template = "%d%s"; Zerotorescue@110: aName = template:format((10 - (aRarity or 10)), (aName or ""):lower()); Zerotorescue@110: bName = template:format((10 - (bRarity or 10)), (bName or ""):lower()); Zerotorescue@110: Zerotorescue@110: if this.cols[column].sort == "dsc" then Zerotorescue@110: return aName > bName; Zerotorescue@110: else Zerotorescue@110: return aName < bName; Zerotorescue@110: end Zerotorescue@110: end, Zerotorescue@110: ["sort"] = "asc", -- when the data is set, use this column so sort the default data Zerotorescue@144: ["tooltipTitle"] = "Item", Zerotorescue@144: ["tooltip"] = "Click to sort the list by item quality then item name.", Zerotorescue@110: }, Zerotorescue@110: { Zerotorescue@110: ["name"] = "Moving", Zerotorescue@110: ["width"] = (scrollTableWidth * .15), Zerotorescue@110: ["align"] = "RIGHT", Zerotorescue@110: ["defaultsort"] = "dsc", Zerotorescue@110: ["sortnext"] = 1, Zerotorescue@144: ["tooltipTitle"] = "Moving", Zerotorescue@144: ["tooltip"] = "Click to sort the list by the amount of movable items.", Zerotorescue@110: }, Zerotorescue@110: { Zerotorescue@110: ["name"] = "Available", Zerotorescue@111: ["width"] = (scrollTableWidth * .25), Zerotorescue@110: ["align"] = "RIGHT", Zerotorescue@110: ["defaultsort"] = "dsc", Zerotorescue@110: ["sortnext"] = 1, Zerotorescue@110: ["comparesort"] = function(this, aRow, bRow, column) Zerotorescue@110: local aAvailablePercent = (this:GetRow(aRow).rowData.available / this:GetRow(aRow).rowData.missing); Zerotorescue@110: local bAvailablePercent = (this:GetRow(bRow).rowData.available / this:GetRow(bRow).rowData.missing); Zerotorescue@110: Zerotorescue@110: if this.cols[column].sort == "dsc" then Zerotorescue@110: return aAvailablePercent > bAvailablePercent; Zerotorescue@110: else Zerotorescue@110: return aAvailablePercent < bAvailablePercent; Zerotorescue@110: end Zerotorescue@110: end, Zerotorescue@144: ["tooltipTitle"] = "Item", Zerotorescue@144: ["tooltip"] = "Click to sort the list by the availibility percentage.", Zerotorescue@110: }, Zerotorescue@110: }; Zerotorescue@110: Zerotorescue@110: local proceedButton = { Zerotorescue@110: text = "Move Items", Zerotorescue@144: tooltipTitle = "Move Items", Zerotorescue@144: tooltip = "Start moving these items from the bank.", Zerotorescue@110: onClick = OnMoveAccept, Zerotorescue@110: }; Zerotorescue@110: local cancelButton = { Zerotorescue@110: text = "Cancel", Zerotorescue@144: tooltipTitle = "Cancel", Zerotorescue@144: tooltip = "Do not move anything and close the window.", Zerotorescue@110: onClick = OnMoveCancel, Zerotorescue@110: }; Zerotorescue@110: Zerotorescue@132: addon:SetMoverFrameSettings("Inventorium Storage Refill", "The items listed below can be refilled from this location, do you wish to move them to your bags?", proceedButton, cancelButton, headers); Zerotorescue@119: end Zerotorescue@119: Zerotorescue@119: -- Merchant restock window: restock from a merchant by buying items needed Zerotorescue@119: local function UseMerchantRestockST(totalCost) Zerotorescue@142: if not InventoriumItemMover then Zerotorescue@142: addon:CreateMoverFrame(); Zerotorescue@142: end Zerotorescue@142: Zerotorescue@119: local frame = InventoriumItemMover; -- both for speed as code-consistency Zerotorescue@119: Zerotorescue@119: -- Scrolling table with a list of items to be moved Zerotorescue@119: local scrollTableWidth = ( frame.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size Zerotorescue@119: local headers = { Zerotorescue@119: { Zerotorescue@119: ["name"] = "Item", Zerotorescue@119: ["width"] = (scrollTableWidth * .60), Zerotorescue@119: ["defaultsort"] = "asc", Zerotorescue@119: ["comparesort"] = function(this, aRow, bRow, column) Zerotorescue@119: local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId); Zerotorescue@119: local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId); Zerotorescue@119: local template = "%d%s"; Zerotorescue@119: aName = template:format((10 - (aRarity or 10)), (aName or ""):lower()); Zerotorescue@119: bName = template:format((10 - (bRarity or 10)), (bName or ""):lower()); Zerotorescue@119: Zerotorescue@119: if this.cols[column].sort == "dsc" then Zerotorescue@119: return aName > bName; Zerotorescue@119: else Zerotorescue@119: return aName < bName; Zerotorescue@119: end Zerotorescue@119: end, Zerotorescue@119: ["sort"] = "asc", -- when the data is set, use this column so sort the default data Zerotorescue@144: ["tooltipTitle"] = "Item", Zerotorescue@144: ["tooltip"] = "Click to sort the list by item quality then item name.", Zerotorescue@119: }, Zerotorescue@119: { Zerotorescue@119: ["name"] = "Buying", Zerotorescue@119: ["width"] = (scrollTableWidth * .20), Zerotorescue@119: ["align"] = "RIGHT", Zerotorescue@119: ["defaultsort"] = "dsc", Zerotorescue@119: ["sortnext"] = 1, Zerotorescue@144: ["tooltipTitle"] = "Buying", Zerotorescue@144: ["tooltip"] = "Click to sort the list by the amount of purchasable items.", Zerotorescue@119: }, Zerotorescue@119: { Zerotorescue@119: ["name"] = "Cost", Zerotorescue@119: ["width"] = (scrollTableWidth * .20), Zerotorescue@119: ["align"] = "RIGHT", Zerotorescue@119: ["defaultsort"] = "dsc", Zerotorescue@119: ["sortnext"] = 1, Zerotorescue@144: ["tooltipTitle"] = "Cost", Zerotorescue@144: ["tooltip"] = "Click to sort the list by the total cost of buying all these items.", Zerotorescue@119: }, Zerotorescue@119: }; Zerotorescue@119: Zerotorescue@119: local proceedButton = { Zerotorescue@119: text = "Purchase Items", Zerotorescue@144: tooltipTitle = "Purchase Items", Zerotorescue@144: tooltip = "Start purchasing these items from this merchant.", Zerotorescue@119: onClick = OnMoveAccept, Zerotorescue@119: }; Zerotorescue@119: local cancelButton = { Zerotorescue@119: text = "Cancel", Zerotorescue@144: tooltipTitle = "Cancel", Zerotorescue@144: tooltip = "Do not purchase anything and close the window.", Zerotorescue@119: onClick = OnMoveCancel, Zerotorescue@119: }; Zerotorescue@119: Zerotorescue@132: addon:SetMoverFrameSettings("Inventorium Merchant Restock", ("The following items can be restocked from this merchant for a total of %s. Do you wish to proceed?"):format(GetSmallCoinTextureString(totalCost)), proceedButton, cancelButton, headers); Zerotorescue@110: end Zerotorescue@110: Zerotorescue@80: function mod:ClearCache() Zerotorescue@122: twipe(itemCache); Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: function mod:CacheLocation(location, remember) Zerotorescue@89: -- Reset cache just in case it was filled Zerotorescue@89: self:ClearCache(); Zerotorescue@89: Zerotorescue@80: if location == addon.Locations.Bag or location == addon.Locations.Bank then Zerotorescue@80: local start, stop; Zerotorescue@80: if location == addon.Locations.Bag then Zerotorescue@80: start = 0; Zerotorescue@80: stop = NUM_BAG_SLOTS; Zerotorescue@80: else Zerotorescue@80: -- If we requested the bank then we don't want the bag info Zerotorescue@80: start = ( NUM_BAG_SLOTS + 1 ); Zerotorescue@80: stop = ( NUM_BAG_SLOTS + NUM_BANKBAGSLOTS ); Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: -- Go through all our bags, including the backpack Zerotorescue@81: 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 Zerotorescue@80: -- Scan the default 100 slots whenever we're at a non-existing index Zerotorescue@80: local bagId = (i == (stop + 1) and BANK_CONTAINER) or i; Zerotorescue@80: local slotId = GetContainerNumSlots(bagId); Zerotorescue@80: Zerotorescue@80: while slotId ~= 0 do Zerotorescue@80: -- A not equal-comparison should be quicker than a larger than-comparison Zerotorescue@80: Zerotorescue@80: local itemId = GetContainerItemID(bagId, slotId); Zerotorescue@80: local itemCount = itemId and select(2, GetContainerItemInfo(bagId, slotId)); Zerotorescue@80: Zerotorescue@80: if itemId and itemCount and itemCount > 0 then Zerotorescue@119: local containerItem; Zerotorescue@80: if not itemCache[itemId] then Zerotorescue@80: -- If this is the first time we see this item, make a new object Zerotorescue@119: containerItem = addon.ContainerItem:New(); Zerotorescue@119: itemCache[itemId] = containerItem; Zerotorescue@80: else Zerotorescue@80: -- If we had this item in another slot too Zerotorescue@119: containerItem = itemCache[itemId]; Zerotorescue@80: end Zerotorescue@80: Zerotorescue@119: containerItem:AddLocation(bagId, slotId, itemCount); Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: -- Continue scanning a different slot Zerotorescue@80: slotId = (slotId - 1); Zerotorescue@80: end Zerotorescue@80: end Zerotorescue@80: elseif location == addon.Locations.Guild then Zerotorescue@84: for tabId = 1, GetNumGuildBankTabs() do Zerotorescue@110: local _, _, isViewable, _, _, remainingWithdrawals = GetGuildBankTabInfo(tabId); Zerotorescue@80: Zerotorescue@110: if isViewable and (remainingWithdrawals > 0 or remainingWithdrawals == -1) then Zerotorescue@84: local slotId = (MAX_GUILDBANK_SLOTS_PER_TAB or 98); -- start by scanning the last slot Zerotorescue@80: Zerotorescue@84: while slotId ~= 0 do Zerotorescue@84: -- A not equal-comparison should be quicker than a larger than-comparison Zerotorescue@84: Zerotorescue@84: local itemLink = GetGuildBankItemLink(tabId, slotId); Zerotorescue@95: local itemId = itemLink and addon:GetItemId(itemLink); Zerotorescue@84: local itemCount = itemLink and select(2, GetGuildBankItemInfo(tabId, slotId)); Zerotorescue@84: Zerotorescue@84: if itemLink and itemId and itemCount and itemCount > 0 then Zerotorescue@84: -- If there is actually an item in this slot Zerotorescue@119: local containerItem; Zerotorescue@84: if not itemCache[itemId] then Zerotorescue@84: -- If this is the first time we see this item, make a new object Zerotorescue@119: containerItem = addon.ContainerItem:New(); Zerotorescue@119: itemCache[itemId] = containerItem; Zerotorescue@84: else Zerotorescue@84: -- If we had this item in another slot too Zerotorescue@119: containerItem = itemCache[itemId]; Zerotorescue@84: end Zerotorescue@84: Zerotorescue@119: containerItem:AddLocation(tabId, slotId, itemCount); Zerotorescue@84: end Zerotorescue@84: Zerotorescue@84: -- Continue scanning a different slot Zerotorescue@84: slotId = (slotId - 1); Zerotorescue@80: end Zerotorescue@80: end Zerotorescue@80: end Zerotorescue@110: elseif location == addon.Locations.Mailbox then Zerotorescue@110: for mailIndex = 1, GetInboxNumItems() do Zerotorescue@110: -- All mail items Zerotorescue@110: Zerotorescue@110: for attachIndex = 1, ATTACHMENTS_MAX_RECEIVE do Zerotorescue@110: -- All attachments Zerotorescue@110: Zerotorescue@110: local itemLink = GetInboxItemLink(mailIndex, attachIndex); Zerotorescue@110: local itemId = itemLink and addon:GetItemId(itemLink); Zerotorescue@110: local itemCount = itemLink and select(3, GetInboxItem(mailIndex, attachIndex)); Zerotorescue@110: Zerotorescue@110: if itemLink and itemId and itemCount and itemCount > 0 then Zerotorescue@119: local containerItem; Zerotorescue@110: if not itemCache[itemId] then Zerotorescue@110: -- If this is the first time we see this item, make a new object Zerotorescue@119: containerItem = addon.ContainerItem:New(); Zerotorescue@119: itemCache[itemId] = containerItem; Zerotorescue@110: else Zerotorescue@110: -- If we had this item in another slot too Zerotorescue@119: containerItem = itemCache[itemId]; Zerotorescue@110: end Zerotorescue@110: Zerotorescue@119: containerItem:AddLocation(mailIndex, attachIndex, itemCount); Zerotorescue@110: end Zerotorescue@110: end Zerotorescue@110: end Zerotorescue@119: elseif location == addon.Locations.Merchant then Zerotorescue@119: for itemIndex = 1, GetMerchantNumItems() do Zerotorescue@119: -- All merchant items Zerotorescue@119: Zerotorescue@119: local itemLink = GetMerchantItemLink(itemIndex); Zerotorescue@119: local itemId = itemLink and addon:GetItemId(itemLink); Zerotorescue@119: local _, _, vendorValue, quantity, numAvailable, _, extendedCost = GetMerchantItemInfo(itemIndex); Zerotorescue@119: Zerotorescue@119: if itemLink and itemId and numAvailable ~= 0 and not extendedCost then Zerotorescue@119: local containerItem; Zerotorescue@119: if not itemCache[itemId] then Zerotorescue@119: -- If this is the first time we see this item, make a new object Zerotorescue@119: containerItem = addon.ContainerItem:New(); Zerotorescue@119: containerItem.price = (vendorValue / quantity); -- remember the price for this item. We assume it's the same for this entire item id Zerotorescue@119: Zerotorescue@119: itemCache[itemId] = containerItem; Zerotorescue@119: else Zerotorescue@119: -- If we had this item in another slot too Zerotorescue@119: containerItem = itemCache[itemId]; Zerotorescue@119: end Zerotorescue@119: Zerotorescue@119: containerItem:AddLocation(1, itemIndex, numAvailable); Zerotorescue@119: end Zerotorescue@119: end Zerotorescue@80: else Zerotorescue@119: error("Invalid location provided for CacheLocation."); Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: if not remember then Zerotorescue@80: -- Copy the table as clearing the cache wipes it empty (and tables are passed by reference) Zerotorescue@80: local cacheCopy = CopyTable(itemCache); Zerotorescue@80: Zerotorescue@80: self:ClearCache(); Zerotorescue@80: Zerotorescue@80: return cacheCopy; Zerotorescue@80: end Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: function mod:Scan(location) Zerotorescue@80: -- We might pause the scanning when we invoke moves ourself Zerotorescue@80: if paused then Zerotorescue@110: addon:Debug("Not scanning; paused..."); Zerotorescue@80: return; Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: local playerName = UnitName("player"); Zerotorescue@80: Zerotorescue@101: currentLocation = location; Zerotorescue@80: self:CacheLocation(location, true); Zerotorescue@80: Zerotorescue@110: -- Ensure previous queue isn't remaining Zerotorescue@110: Mover:ResetQueue(); Zerotorescue@110: Zerotorescue@119: -- Restock = obtaining more, refill = merely moving local. IsRestock = are we buying/making more? Zerotorescue@119: local isRestock = (location == addon.Locations.Merchant); Zerotorescue@119: Zerotorescue@80: -- Go through all groups Zerotorescue@80: for groupName, values in pairs(addon.db.profile.groups) do Zerotorescue@119: -- Settings Zerotorescue@80: local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters"); Zerotorescue@84: local localItemData = addon:GetOptionByKey(groupName, "localItemData"); Zerotorescue@218: local requiredItems, bonusQueue, priceThreshold, minCraftingQueue, isRefillEnabled; Zerotorescue@123: if isRestock then Zerotorescue@123: requiredItems = addon:GetOptionByKey(groupName, "restockTarget"); Zerotorescue@123: bonusQueue = addon:GetOptionByKey(groupName, "bonusQueue"); Zerotorescue@218: priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold"); Zerotorescue@123: minCraftingQueue = floor( addon:GetOptionByKey(groupName, "minCraftingQueue") * requiredItems ); -- If the minCraftingQueue is 5% and restockTarget is 60, this will result in 3 Zerotorescue@123: else Zerotorescue@123: isRefillEnabled = addon:GetOptionByKey(groupName, "autoRefill"); Zerotorescue@123: requiredItems = addon:GetOptionByKey(groupName, "minLocalStock"); Zerotorescue@123: end Zerotorescue@80: Zerotorescue@119: local isTracked = (trackAt and trackAt[playerName]); -- Is this character interested in this data? Zerotorescue@119: local isConsideredLocal = (localItemData and localItemData[location]); -- if this location was checked as local storage, don't refill from it Zerotorescue@119: Zerotorescue@123: if values.items and isTracked and (isRestock or isRefillEnabled) and not isConsideredLocal then Zerotorescue@119: addon:Debug("Scanning |cff00ff00%s|r", groupName); Zerotorescue@80: Zerotorescue@80: for itemId, _ in pairs(values.items) do Zerotorescue@119: -- Find this item in the source Zerotorescue@119: local containerItem = itemCache[itemId]; Zerotorescue@80: Zerotorescue@119: if containerItem then Zerotorescue@119: -- Only do all the CPU intensive checks if this item is available Zerotorescue@80: Zerotorescue@119: -- When restocking use the global item count, when refilling use the local Zerotorescue@119: local currentItemCount = ((isRestock and addon:GetItemCount(itemId, groupName)) or addon:GetLocalItemCount(itemId, groupName)); Zerotorescue@119: Zerotorescue@119: -- Check if we have enough items local (but only do so if this location also has enough available) Zerotorescue@119: local missingItems = (requiredItems - currentItemCount); Zerotorescue@119: Zerotorescue@123: if isRestock and currentItemCount == 0 and bonusQueue and bonusQueue > 0 then Zerotorescue@123: -- If we have none left and the bonus queue is enabled, modify the amount to be queued Zerotorescue@123: Zerotorescue@123: missingItems = floor( ( missingItems * ( bonusQueue + 1 ) ) + .5 ); -- round Zerotorescue@123: end Zerotorescue@123: Zerotorescue@123: if missingItems > 0 and (not isRestock or missingItems >= minCraftingQueue) then Zerotorescue@218: Zerotorescue@218: -- Get auction value when it is relevant Zerotorescue@218: local value = (isRestock and priceThreshold ~= 0 and addon:GetAuctionValue(IdToItemLink(itemId), groupName)); Zerotorescue@80: Zerotorescue@218: if not isRestock or priceThreshold == 0 or value == -1 or value >= priceThreshold then Zerotorescue@218: -- Check how many are available Zerotorescue@218: local availableItems = ((containerItem.totalCount) or 0); Zerotorescue@218: -- Calculate how many we'll be moving (less missing than available? use missing, otherwise use available) Zerotorescue@218: -- -1 available items indicates unlimited amount, in that case we must cap at missing items Zerotorescue@218: local moving = (((availableItems == -1 or missingItems <= availableItems) and missingItems) or availableItems); Zerotorescue@119: Zerotorescue@218: if availableItems == -1 or availableItems > 0 then Zerotorescue@218: addon:Debug("Insufficient %s but this location has %d (moving %d)", IdToItemLink(itemId), availableItems, moving); Zerotorescue@218: Zerotorescue@218: Mover:AddMove(itemId, moving, missingItems, availableItems, containerItem.price); Zerotorescue@218: end Zerotorescue@119: end Zerotorescue@80: end Zerotorescue@80: end Zerotorescue@80: end Zerotorescue@80: end Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: self:ClearCache(); Zerotorescue@80: Zerotorescue@81: if Mover:HasMoves() then Zerotorescue@101: if addon.db.profile.defaults.autoRefillSkipConfirm then Zerotorescue@110: OnMoveAccept(); Zerotorescue@101: else Zerotorescue@119: local moves = Mover:GetMoves(); Zerotorescue@110: Zerotorescue@106: -- This table is never copied, just referenced. It is the same for every row. Zerotorescue@119: local columns; Zerotorescue@119: Zerotorescue@119: if isRestock then Zerotorescue@119: local totalCost = 0; Zerotorescue@119: for _, move in pairs(moves) do Zerotorescue@119: totalCost = (totalCost + (move.cost * move.num)); Zerotorescue@119: end Zerotorescue@119: UseMerchantRestockST(totalCost); Zerotorescue@119: Zerotorescue@119: columns = { Zerotorescue@119: { Zerotorescue@119: ["value"] = function(data, cols, realrow, column, table) Zerotorescue@119: return IdToItemLink(data[realrow].rowData.itemId); Zerotorescue@119: end, Zerotorescue@119: }, -- item Zerotorescue@119: { Zerotorescue@119: ["value"] = function(data, cols, realrow, column, table) Zerotorescue@119: return data[realrow].rowData.num; Zerotorescue@119: end, Zerotorescue@119: }, -- buying Zerotorescue@119: { Zerotorescue@119: ["value"] = function(data, cols, realrow, column, table) Zerotorescue@119: return GetSmallCoinTextureString((data[realrow].rowData.cost * data[realrow].rowData.num)); Zerotorescue@119: end, Zerotorescue@119: }, -- cost Zerotorescue@119: }; Zerotorescue@119: else Zerotorescue@119: UseStorageRefillST(); Zerotorescue@119: Zerotorescue@119: columns = { Zerotorescue@119: { Zerotorescue@119: ["value"] = function(data, cols, realrow, column, table) Zerotorescue@119: return IdToItemLink(data[realrow].rowData.itemId); Zerotorescue@119: end, Zerotorescue@119: }, -- item Zerotorescue@119: { Zerotorescue@119: ["value"] = function(data, cols, realrow, column, table) Zerotorescue@119: return data[realrow].rowData.num; Zerotorescue@119: end, Zerotorescue@119: }, -- moving Zerotorescue@119: { Zerotorescue@119: ["value"] = function(data, cols, realrow, column, table) Zerotorescue@119: return addon:DisplayItemCount(data[realrow].rowData.available, data[realrow].rowData.missing); -- available / missing Zerotorescue@119: end, Zerotorescue@119: ["color"] = function(data, cols, realrow, column, table) Zerotorescue@119: return ((data[realrow].rowData.available < data[realrow].rowData.missing) and { r = 1, g = 0, b = 0, a = 1 }) or { r = 1, g = 1, b = 1, a = 1 }; Zerotorescue@119: end, Zerotorescue@119: }, -- missing / available Zerotorescue@119: }; Zerotorescue@119: end Zerotorescue@101: Zerotorescue@106: -- Store the list with rows in this Zerotorescue@106: local data = {}; Zerotorescue@101: Zerotorescue@119: for i, move in pairs(moves) do Zerotorescue@122: tinsert(data, { Zerotorescue@106: ["rowData"] = move, -- this is not a key usually found in a row item and ignored by the library Zerotorescue@101: ["cols"] = columns, Zerotorescue@106: }); Zerotorescue@101: end Zerotorescue@101: Zerotorescue@101: addon:SetMoverFrameData(data); Zerotorescue@101: end Zerotorescue@81: end Zerotorescue@81: end Zerotorescue@81: Zerotorescue@84: Zerotorescue@84: Zerotorescue@84: -- Events Zerotorescue@84: Zerotorescue@84: -- Player bank Zerotorescue@84: Zerotorescue@84: function mod:BANKFRAME_OPENED() Zerotorescue@84: addon:Debug("Scanner:BANKFRAME_OPENED"); Zerotorescue@84: Zerotorescue@84: mod:RegisterEvent("BANKFRAME_CLOSED"); Zerotorescue@84: Zerotorescue@84: -- Scan once when the bank is opened, but no need to scan after Zerotorescue@84: mod:Scan(addon.Locations.Bank); Zerotorescue@84: end Zerotorescue@84: Zerotorescue@84: function mod:BANKFRAME_CLOSED() Zerotorescue@81: addon:Debug("Scanner:BANKFRAME_CLOSED"); Zerotorescue@81: Zerotorescue@89: self:ClearCache(); Zerotorescue@89: Zerotorescue@81: mod:UnregisterEvent("BANKFRAME_CLOSED"); Zerotorescue@81: Zerotorescue@137: if InventoriumItemMover then Zerotorescue@137: InventoriumItemMover:Hide(); Zerotorescue@137: end Zerotorescue@101: Mover:ResetQueue(); Zerotorescue@80: end Zerotorescue@80: Zerotorescue@84: -- Guild bank Zerotorescue@84: Zerotorescue@84: local tmrScanGuild, scanned; Zerotorescue@84: function mod:GUILDBANKBAGSLOTS_CHANGED() Zerotorescue@84: -- This event is spammed the first time the guild bank is opened Zerotorescue@84: if not scanned then Zerotorescue@84: self:CancelTimer(tmrScanGuild, true); -- silent Zerotorescue@84: tmrScanGuild = self:ScheduleTimer("DoScanGuild", 1); Zerotorescue@84: end Zerotorescue@80: end Zerotorescue@80: Zerotorescue@84: function mod:DoScanGuild() Zerotorescue@84: if not scanned then Zerotorescue@89: addon:Debug("Scanner:DoScanGuild"); Zerotorescue@84: Zerotorescue@84: scanned = true; Zerotorescue@84: Zerotorescue@84: self:Scan(addon.Locations.Guild); Zerotorescue@84: end Zerotorescue@84: end Zerotorescue@80: Zerotorescue@84: function mod:GUILDBANKFRAME_CLOSED() Zerotorescue@81: addon:Debug("Scanner:GUILDBANKFRAME_CLOSED"); Zerotorescue@81: Zerotorescue@84: scanned = nil; Zerotorescue@89: self:ClearCache(); Zerotorescue@81: Zerotorescue@84: self:UnregisterEvent("GUILDBANKFRAME_CLOSED"); Zerotorescue@84: self:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED"); Zerotorescue@84: Zerotorescue@84: self:CancelTimer(tmrScanGuild, true); -- silent Zerotorescue@80: Zerotorescue@137: if InventoriumItemMover then Zerotorescue@137: InventoriumItemMover:Hide(); Zerotorescue@137: end Zerotorescue@101: Mover:ResetQueue(); Zerotorescue@80: end Zerotorescue@80: Zerotorescue@84: function mod:GUILDBANKFRAME_OPENED() Zerotorescue@81: addon:Debug("Scanner:GUILDBANKFRAME_OPENED"); Zerotorescue@81: Zerotorescue@84: scanned = nil; Zerotorescue@80: Zerotorescue@84: -- Get the contents for every tab into our cache Zerotorescue@84: for tabId = 1, GetNumGuildBankTabs() do Zerotorescue@110: local _, _, isViewable, _, _, remainingWithdrawals = GetGuildBankTabInfo(tabId); Zerotorescue@110: Zerotorescue@110: if isViewable and (remainingWithdrawals > 0 or remainingWithdrawals == -1) then Zerotorescue@84: QueryGuildBankTab(tabId); Zerotorescue@84: end Zerotorescue@84: end Zerotorescue@84: Zerotorescue@84: self:RegisterEvent("GUILDBANKFRAME_CLOSED"); Zerotorescue@84: self:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED"); Zerotorescue@80: end Zerotorescue@80: Zerotorescue@119: function mod:MERCHANT_SHOW() Zerotorescue@119: addon:Debug("Scanner:MERCHANT_SHOW"); Zerotorescue@119: Zerotorescue@119: self:RegisterEvent("MERCHANT_CLOSED"); Zerotorescue@119: Zerotorescue@119: self:Scan(addon.Locations.Merchant); Zerotorescue@119: end Zerotorescue@119: Zerotorescue@119: function mod:MERCHANT_CLOSED() Zerotorescue@119: addon:Debug("Scanner:MERCHANT_CLOSED"); Zerotorescue@119: Zerotorescue@119: self:ClearCache(); Zerotorescue@119: Zerotorescue@119: self:UnregisterEvent("MERCHANT_CLOSED"); Zerotorescue@119: Zerotorescue@137: if InventoriumItemMover then Zerotorescue@137: InventoriumItemMover:Hide(); Zerotorescue@137: end Zerotorescue@119: Mover:ResetQueue(); Zerotorescue@119: end Zerotorescue@119: Zerotorescue@117: local previousMailCount; Zerotorescue@117: function mod:MAIL_SHOW() Zerotorescue@117: addon:Debug("Scanner:MAIL_SHOW"); Zerotorescue@117: Zerotorescue@117: self:RegisterEvent("MAIL_INBOX_UPDATE"); Zerotorescue@117: self:RegisterEvent("MAIL_CLOSED"); Zerotorescue@117: Zerotorescue@117: scanned = nil; Zerotorescue@117: previousMailCount = nil; Zerotorescue@117: Zerotorescue@117: self:Scan(addon.Locations.Mailbox); Zerotorescue@117: end Zerotorescue@110: Zerotorescue@117: function mod:MAIL_INBOX_UPDATE() Zerotorescue@117: if not scanned then Zerotorescue@117: addon:Debug("Scanner:MAIL_INBOX_UPDATE"); Zerotorescue@117: Zerotorescue@117: local current, total = GetInboxNumItems(); Zerotorescue@117: Zerotorescue@117: if not previousMailCount or current > previousMailCount then Zerotorescue@117: -- New mail received Zerotorescue@117: Zerotorescue@117: scanned = true; Zerotorescue@117: Zerotorescue@117: self:Scan(addon.Locations.Mailbox); Zerotorescue@117: end Zerotorescue@117: Zerotorescue@117: -- Also remember the new mailcount when losing items, otherwise deleting item 50 and getting to 50 again wouldn't trigger a re-scan Zerotorescue@117: previousMailCount = current; Zerotorescue@117: else Zerotorescue@117: addon:Debug("Scanner:MAIL_INBOX_UPDATE skipped, already scanned"); Zerotorescue@117: end Zerotorescue@117: end Zerotorescue@110: Zerotorescue@117: function mod:MAIL_CLOSED() Zerotorescue@117: addon:Debug("Scanner:MAIL_CLOSED"); Zerotorescue@117: Zerotorescue@117: previousMailCount = nil; Zerotorescue@117: scanned = nil; Zerotorescue@117: self:ClearCache(); Zerotorescue@117: Zerotorescue@117: self:UnregisterEvent("MAIL_INBOX_UPDATE"); Zerotorescue@117: self:UnregisterEvent("MAIL_CLOSED"); Zerotorescue@117: Zerotorescue@137: if InventoriumItemMover then Zerotorescue@137: InventoriumItemMover:Hide(); Zerotorescue@137: end Zerotorescue@117: Mover:ResetQueue(); Zerotorescue@117: end Zerotorescue@110: Zerotorescue@80: function mod:OnEnable() Zerotorescue@80: -- Scan once when the bankframe is opened Zerotorescue@84: self:RegisterEvent("BANKFRAME_OPENED"); Zerotorescue@84: self:RegisterEvent("GUILDBANKFRAME_OPENED"); Zerotorescue@117: self:RegisterEvent("MAIL_SHOW"); Zerotorescue@119: self:RegisterEvent("MERCHANT_SHOW"); Zerotorescue@80: Zerotorescue@80: Mover = addon:GetModule("Mover"); Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: function mod:OnDisable() Zerotorescue@80: Mover = nil; Zerotorescue@101: currentLocation = nil; Zerotorescue@101: paused = nil; Zerotorescue@80: Zerotorescue@80: -- Bank Zerotorescue@110: self:BANKFRAME_CLOSED(); Zerotorescue@84: self:UnregisterEvent("BANKFRAME_OPENED"); Zerotorescue@80: Zerotorescue@80: -- Guild Zerotorescue@84: self:GUILDBANKFRAME_CLOSED(); Zerotorescue@84: self:UnregisterEvent("GUILDBANKFRAME_OPENED"); Zerotorescue@110: Zerotorescue@117: -- Mailbox Zerotorescue@117: self:MAIL_CLOSED(); Zerotorescue@117: self:UnregisterEvent("MAIL_SHOW"); Zerotorescue@119: Zerotorescue@119: -- Merchant Zerotorescue@119: self:MERCHANT_CLOSED(); Zerotorescue@119: self:UnregisterEvent("MERCHANT_SHOW"); Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: function mod:Pause() Zerotorescue@80: paused = true; Zerotorescue@80: end Zerotorescue@80: Zerotorescue@80: function mod:Unpause() Zerotorescue@80: paused = nil; Zerotorescue@80: end