Zerotorescue@80
|
1 local addon = select(2, ...);
|
Zerotorescue@80
|
2 local mod = addon:NewModule("Scanner", "AceEvent-3.0");
|
Zerotorescue@80
|
3
|
Zerotorescue@80
|
4 addon.Locations = {
|
Zerotorescue@80
|
5 Bag = 0,
|
Zerotorescue@80
|
6 Bank = 1,
|
Zerotorescue@80
|
7 Guild = 2,
|
Zerotorescue@80
|
8 };
|
Zerotorescue@80
|
9
|
Zerotorescue@80
|
10 local Mover, paused;
|
Zerotorescue@80
|
11 local itemCache = {};
|
Zerotorescue@80
|
12
|
Zerotorescue@80
|
13 local function _GetItemCount(itemId, location)
|
Zerotorescue@80
|
14 if location == addon.Locations.Bank then
|
Zerotorescue@80
|
15 -- No longer using GetItemCount as this includes equiped items and containers (e.g. bank bags)
|
Zerotorescue@80
|
16 --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
|
Zerotorescue@80
|
17 return ((itemCache[itemId] and itemCache[itemId].totalCount) or 0);
|
Zerotorescue@80
|
18 elseif location == addon.Locations.Guild then
|
Zerotorescue@80
|
19 return ((itemCache[itemId] and itemCache[itemId].totalCount) or 0);
|
Zerotorescue@80
|
20 else
|
Zerotorescue@80
|
21 error("Invalid location provided for the local _GetItemCount. Must be Bag or Bank.");
|
Zerotorescue@80
|
22 end
|
Zerotorescue@80
|
23 end
|
Zerotorescue@80
|
24
|
Zerotorescue@80
|
25 local function GetItemID(link)
|
Zerotorescue@80
|
26 return tonumber(link:match("|Hitem:([-0-9]+):"));
|
Zerotorescue@80
|
27 end
|
Zerotorescue@80
|
28
|
Zerotorescue@80
|
29 function mod:ClearCache()
|
Zerotorescue@80
|
30 table.wipe(itemCache);
|
Zerotorescue@80
|
31 end
|
Zerotorescue@80
|
32
|
Zerotorescue@80
|
33 function mod:CacheLocation(location, remember)
|
Zerotorescue@80
|
34 if location == addon.Locations.Bag or location == addon.Locations.Bank then
|
Zerotorescue@80
|
35 -- Reset cache just in case it was filled
|
Zerotorescue@80
|
36 self:ClearCache();
|
Zerotorescue@80
|
37
|
Zerotorescue@80
|
38 local start, stop;
|
Zerotorescue@80
|
39 if location == addon.Locations.Bag then
|
Zerotorescue@80
|
40 start = 0;
|
Zerotorescue@80
|
41 stop = NUM_BAG_SLOTS;
|
Zerotorescue@80
|
42 else
|
Zerotorescue@80
|
43 -- If we requested the bank then we don't want the bag info
|
Zerotorescue@80
|
44 start = ( NUM_BAG_SLOTS + 1 );
|
Zerotorescue@80
|
45 stop = ( NUM_BAG_SLOTS + NUM_BANKBAGSLOTS );
|
Zerotorescue@80
|
46 end
|
Zerotorescue@80
|
47
|
Zerotorescue@80
|
48 -- Go through all our bags, including the backpack
|
Zerotorescue@80
|
49 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
|
Zerotorescue@80
|
50 -- Scan the default 100 slots whenever we're at a non-existing index
|
Zerotorescue@80
|
51 local bagId = (i == (stop + 1) and BANK_CONTAINER) or i;
|
Zerotorescue@80
|
52 local slotId = GetContainerNumSlots(bagId);
|
Zerotorescue@80
|
53
|
Zerotorescue@80
|
54 while slotId ~= 0 do
|
Zerotorescue@80
|
55 -- A not equal-comparison should be quicker than a larger than-comparison
|
Zerotorescue@80
|
56
|
Zerotorescue@80
|
57 local itemId = GetContainerItemID(bagId, slotId);
|
Zerotorescue@80
|
58 local itemCount = itemId and select(2, GetContainerItemInfo(bagId, slotId));
|
Zerotorescue@80
|
59
|
Zerotorescue@80
|
60 if itemId and itemCount and itemCount > 0 then
|
Zerotorescue@80
|
61 local itemMove;
|
Zerotorescue@80
|
62 if not itemCache[itemId] then
|
Zerotorescue@80
|
63 -- If this is the first time we see this item, make a new object
|
Zerotorescue@80
|
64 itemMove = addon.ItemMove:New();
|
Zerotorescue@80
|
65 else
|
Zerotorescue@80
|
66 -- If we had this item in another slot too
|
Zerotorescue@80
|
67 itemMove = itemCache[itemId];
|
Zerotorescue@80
|
68 end
|
Zerotorescue@80
|
69
|
Zerotorescue@80
|
70 itemMove.AddLocation(bagId, slotId, itemCount);
|
Zerotorescue@80
|
71 end
|
Zerotorescue@80
|
72
|
Zerotorescue@80
|
73 -- Continue scanning a different slot
|
Zerotorescue@80
|
74 slotId = (slotId - 1);
|
Zerotorescue@80
|
75 end
|
Zerotorescue@80
|
76 end
|
Zerotorescue@80
|
77 elseif location == addon.Locations.Guild then
|
Zerotorescue@80
|
78 -- Reset cache before we scan
|
Zerotorescue@80
|
79 self:ClearCache();
|
Zerotorescue@80
|
80
|
Zerotorescue@80
|
81 local tabId = GetCurrentGuildBankTab();
|
Zerotorescue@80
|
82 local slotId = (MAX_GUILDBANK_SLOTS_PER_TAB or 98); -- start by scanning the last slot
|
Zerotorescue@80
|
83
|
Zerotorescue@80
|
84 if tabId == nil or tabId < 1 then return; end
|
Zerotorescue@80
|
85
|
Zerotorescue@80
|
86 while slotId ~= 0 do
|
Zerotorescue@80
|
87 -- A not equal-comparison should be quicker than a larger than-comparison
|
Zerotorescue@80
|
88
|
Zerotorescue@80
|
89 -- If there is actually an item in this slot
|
Zerotorescue@80
|
90
|
Zerotorescue@80
|
91 local itemLink = GetGuildBankItemLink(tabId, slotId);
|
Zerotorescue@80
|
92 local itemId = itemLink and GetItemId(itemLink);
|
Zerotorescue@80
|
93 local itemCount = itemLink and select(2, GetGuildBankItemInfo(tabId, slotId));
|
Zerotorescue@80
|
94
|
Zerotorescue@80
|
95 if itemLink and itemId and itemCount and itemCount > 0 then
|
Zerotorescue@80
|
96 local itemMove;
|
Zerotorescue@80
|
97 if not itemCache[itemId] then
|
Zerotorescue@80
|
98 -- If this is the first time we see this item, make a new object
|
Zerotorescue@80
|
99 itemMove = addon.ItemMove:New();
|
Zerotorescue@80
|
100 else
|
Zerotorescue@80
|
101 -- If we had this item in another slot too
|
Zerotorescue@80
|
102 itemMove = itemCache[itemId];
|
Zerotorescue@80
|
103 end
|
Zerotorescue@80
|
104
|
Zerotorescue@80
|
105 itemMove.AddLocation(tabId, slotId, itemCount);
|
Zerotorescue@80
|
106 end
|
Zerotorescue@80
|
107
|
Zerotorescue@80
|
108 -- Continue scanning a different slot
|
Zerotorescue@80
|
109 slotId = (slotId - 1);
|
Zerotorescue@80
|
110 end
|
Zerotorescue@80
|
111 else
|
Zerotorescue@80
|
112 error("Invalid location provided for the local _GetItemCount. Must be Bank or Guild.");
|
Zerotorescue@80
|
113 end
|
Zerotorescue@80
|
114
|
Zerotorescue@80
|
115 if not remember then
|
Zerotorescue@80
|
116 -- Copy the table as clearing the cache wipes it empty (and tables are passed by reference)
|
Zerotorescue@80
|
117 local cacheCopy = CopyTable(itemCache);
|
Zerotorescue@80
|
118
|
Zerotorescue@80
|
119 self:ClearCache();
|
Zerotorescue@80
|
120
|
Zerotorescue@80
|
121 return cacheCopy;
|
Zerotorescue@80
|
122 end
|
Zerotorescue@80
|
123 end
|
Zerotorescue@80
|
124
|
Zerotorescue@80
|
125 function mod:Scan(location)
|
Zerotorescue@80
|
126 -- We might pause the scanning when we invoke moves ourself
|
Zerotorescue@80
|
127 if paused then
|
Zerotorescue@80
|
128 return;
|
Zerotorescue@80
|
129 end
|
Zerotorescue@80
|
130
|
Zerotorescue@80
|
131 local playerName = UnitName("player");
|
Zerotorescue@80
|
132
|
Zerotorescue@80
|
133 self:CacheLocation(location, true);
|
Zerotorescue@80
|
134
|
Zerotorescue@80
|
135 -- Go through all groups
|
Zerotorescue@80
|
136 for groupName, values in pairs(addon.db.profile.groups) do
|
Zerotorescue@80
|
137 local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters");
|
Zerotorescue@80
|
138
|
Zerotorescue@80
|
139 if values.items and trackAt[playerName] then
|
Zerotorescue@80
|
140 -- Is this character interested in this data?
|
Zerotorescue@80
|
141
|
Zerotorescue@80
|
142 local minLocalStock = addon:GetOptionByKey(groupName, "minLocalStock");
|
Zerotorescue@80
|
143
|
Zerotorescue@80
|
144 -- Go through all items
|
Zerotorescue@80
|
145 for itemId, _ in pairs(values.items) do
|
Zerotorescue@80
|
146
|
Zerotorescue@80
|
147 -- Check if we have enough items local
|
Zerotorescue@80
|
148 local missingItems = (minLocalStock - addon:GetLocalItemCount(itemId, groupName));
|
Zerotorescue@80
|
149
|
Zerotorescue@80
|
150 if missingItems > 0 then
|
Zerotorescue@80
|
151 -- Check how many are available
|
Zerotorescue@80
|
152 local availableItems = _GetItemCount(itemId, location);
|
Zerotorescue@80
|
153
|
Zerotorescue@80
|
154 if availableItems > 0 then
|
Zerotorescue@80
|
155 print("Insufficient " .. select(2, GetItemInfo(itemId)) .. " but this location has " .. availableItems .. " (moving " .. missingItems .. ")");
|
Zerotorescue@80
|
156
|
Zerotorescue@80
|
157 Mover:AddMove(itemId, missingItems);
|
Zerotorescue@80
|
158 else
|
Zerotorescue@80
|
159 print("Insufficient " .. select(2, GetItemInfo(itemId)));
|
Zerotorescue@80
|
160 end
|
Zerotorescue@80
|
161 end
|
Zerotorescue@80
|
162 end
|
Zerotorescue@80
|
163 end
|
Zerotorescue@80
|
164 end
|
Zerotorescue@80
|
165
|
Zerotorescue@80
|
166 self:ClearCache();
|
Zerotorescue@80
|
167
|
Zerotorescue@80
|
168 self:Pause();
|
Zerotorescue@80
|
169 Mover:BeginMove(location, self.Unpause);
|
Zerotorescue@80
|
170 end
|
Zerotorescue@80
|
171
|
Zerotorescue@80
|
172 local function BANKFRAME_OPENED()
|
Zerotorescue@80
|
173 -- Scan once when the bank is opened, but no need to scan after
|
Zerotorescue@80
|
174 mod:Scan(addon.Locations.Bank);
|
Zerotorescue@80
|
175
|
Zerotorescue@80
|
176 addon:Debug("Scanner:BANKFRAME_OPENED");
|
Zerotorescue@80
|
177 end
|
Zerotorescue@80
|
178
|
Zerotorescue@80
|
179 -- Remember which tabs were scanned and don't scan them again
|
Zerotorescue@80
|
180 local guildBankTabsScanned = {};
|
Zerotorescue@80
|
181
|
Zerotorescue@80
|
182 local function GUILDBANKFRAME_CLOSED()
|
Zerotorescue@80
|
183 mod:UnregisterEvent("GUILDBANKFRAME_CLOSED");
|
Zerotorescue@80
|
184 mod:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED");
|
Zerotorescue@80
|
185
|
Zerotorescue@80
|
186 table.wipe(guildBankTabsScanned);
|
Zerotorescue@80
|
187
|
Zerotorescue@80
|
188 addon:Debug("Scanner:GUILDBANKFRAME_CLOSED");
|
Zerotorescue@80
|
189 end
|
Zerotorescue@80
|
190
|
Zerotorescue@80
|
191 local function GUILDBANKBAGSLOTS_CHANGED()
|
Zerotorescue@80
|
192 if not guildBankTabsScanned[GetCurrentGuildBankTab()] then
|
Zerotorescue@80
|
193 mod:Scan(addon.Locations.Guild);
|
Zerotorescue@80
|
194 guildBankTabsScanned[GetCurrentGuildBankTab()] = true;
|
Zerotorescue@80
|
195
|
Zerotorescue@80
|
196 addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - scanning");
|
Zerotorescue@80
|
197 else
|
Zerotorescue@80
|
198 addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - not scanning");
|
Zerotorescue@80
|
199 end
|
Zerotorescue@80
|
200 end
|
Zerotorescue@80
|
201
|
Zerotorescue@80
|
202 local function GUILDBANKFRAME_OPENED()
|
Zerotorescue@80
|
203 table.wipe(guildBankTabsScanned);
|
Zerotorescue@80
|
204
|
Zerotorescue@80
|
205 mod:RegisterEvent("GUILDBANKFRAME_CLOSED", GUILDBANKFRAME_CLOSED);
|
Zerotorescue@80
|
206 mod:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED", GUILDBANKBAGSLOTS_CHANGED);
|
Zerotorescue@80
|
207
|
Zerotorescue@80
|
208 addon:Debug("Scanner:GUILDBANKFRAME_OPENED");
|
Zerotorescue@80
|
209 end
|
Zerotorescue@80
|
210
|
Zerotorescue@80
|
211 function mod:OnEnable()
|
Zerotorescue@80
|
212 -- Scan once when the bankframe is opened
|
Zerotorescue@80
|
213 mod:RegisterEvent("BANKFRAME_OPENED", BANKFRAME_OPENED);
|
Zerotorescue@80
|
214 mod:RegisterEvent("GUILDBANKFRAME_OPENED", GUILDBANKFRAME_OPENED);
|
Zerotorescue@80
|
215
|
Zerotorescue@80
|
216 Mover = addon:GetModule("Mover");
|
Zerotorescue@80
|
217 end
|
Zerotorescue@80
|
218
|
Zerotorescue@80
|
219 function mod:OnDisable()
|
Zerotorescue@80
|
220 Mover = nil;
|
Zerotorescue@80
|
221
|
Zerotorescue@80
|
222 -- Bank
|
Zerotorescue@80
|
223 mod:UnregisterEvent("BANKFRAME_OPENED");
|
Zerotorescue@80
|
224
|
Zerotorescue@80
|
225 -- Guild
|
Zerotorescue@80
|
226 GUILDBANKFRAME_CLOSED();
|
Zerotorescue@80
|
227 mod:UnregisterEvent("GUILDBANKFRAME_OPENED");
|
Zerotorescue@80
|
228 end
|
Zerotorescue@80
|
229
|
Zerotorescue@80
|
230 function mod:Pause()
|
Zerotorescue@80
|
231 paused = true;
|
Zerotorescue@80
|
232 end
|
Zerotorescue@80
|
233
|
Zerotorescue@80
|
234 function mod:Unpause()
|
Zerotorescue@80
|
235 paused = nil;
|
Zerotorescue@80
|
236 end
|