comparison Modules/Scanner.lua @ 110:67bd5057ecb7

Implemented vendor restocking with the mover. Comitting so I can always review this working version, but I?ll be disabling all part of it as it is not going to work properly without seriously compromising the code structure. Debug messages are now appended with ?Inventorium? (my MailOpener addon was making stuff difficult). Now properly removing the refill window from the displayed static popup windows list so new popups won?t be aligned at odd locations. Changed ?CreateMoverFrame? to not contain any scenario-specific info. All settings can be set with SetFrameSettings. Items that belong to speciality bags are now put there. Other items now ignore spaciality bags. Implemented test code for mailbox refill support. It has been disabled due to some issues but may be introduced later. The guild withdrawal limit is now taken into consideration. Queue is now reset before scanning again.
author Zerotorescue
date Fri, 14 Jan 2011 23:25:05 +0100
parents 3bbad0429d87
children 41f0689dfda1
comparison
equal deleted inserted replaced
109:3bbad0429d87 110:67bd5057ecb7
1 local addon = select(2, ...); 1 local addon = select(2, ...);
2 local mod = addon:NewModule("Scanner", "AceEvent-3.0", "AceTimer-3.0"); 2 local mod = addon:NewModule("Scanner", "AceEvent-3.0", "AceTimer-3.0");
3 3
4 addon.Locations = {
5 Bag = 0,
6 Bank = 1,
7 Guild = 2,
8 Mailbox = 3,
9 };
10
11 local Mover, paused, currentLocation; 4 local Mover, paused, currentLocation;
12 local itemCache = {}; 5 local itemCache = {};
13 6
14 local function OnMoveAccept(this) 7 local function OnMoveAccept()
15 mod:Pause(); 8 mod:Pause();
16 Mover:BeginMove(currentLocation, mod.Unpause); 9 Mover:BeginMove(currentLocation, mod.Unpause);
17 10
18 InventoriumItemMover:Hide(); 11 InventoriumItemMover:Hide();
19 end 12 end
20 13
21 local function OnMoveCancel(this) 14 local function OnMoveCancel()
22 Mover:ResetQueue(); 15 Mover:ResetQueue();
23 currentLocation = nil; 16 currentLocation = nil;
24 17
25 InventoriumItemMover:Hide(); 18 InventoriumItemMover:Hide();
19 end
20
21 local function UseStorageRefillST(withPrices)
22 local frame = InventoriumItemMover; -- both for speed as code-consistency
23
24 -- Scrolling table with a list of items to be moved
25 local scrollTableWidth = ( frame.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size
26 local headers = {
27 {
28 ["name"] = "Item",
29 ["width"] = (scrollTableWidth * ((withPrices and .5) or .60)),
30 ["defaultsort"] = "asc",
31 ["comparesort"] = function(this, aRow, bRow, column)
32 local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId);
33 local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId);
34 local template = "%d%s";
35 aName = template:format((10 - (aRarity or 10)), (aName or ""):lower());
36 bName = template:format((10 - (bRarity or 10)), (bName or ""):lower());
37
38 if this.cols[column].sort == "dsc" then
39 return aName > bName;
40 else
41 return aName < bName;
42 end
43 end,
44 ["sort"] = "asc", -- when the data is set, use this column so sort the default data
45 ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Item"),
46 ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by item quality then item name."),
47 },
48 {
49 ["name"] = "Moving",
50 ["width"] = (scrollTableWidth * .15),
51 ["align"] = "RIGHT",
52 ["defaultsort"] = "dsc",
53 ["sortnext"] = 1,
54 ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Moving"),
55 ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by the amount of movable items."),
56 },
57 {
58 ["name"] = "Available",
59 ["width"] = (scrollTableWidth * ((withPrices and .2) or .25)),
60 ["align"] = "RIGHT",
61 ["defaultsort"] = "dsc",
62 ["sortnext"] = 1,
63 ["comparesort"] = function(this, aRow, bRow, column)
64 local aAvailablePercent = (this:GetRow(aRow).rowData.available / this:GetRow(aRow).rowData.missing);
65 local bAvailablePercent = (this:GetRow(bRow).rowData.available / this:GetRow(bRow).rowData.missing);
66
67 if this.cols[column].sort == "dsc" then
68 return aAvailablePercent > bAvailablePercent;
69 else
70 return aAvailablePercent < bAvailablePercent;
71 end
72 end,
73 ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Item"),
74 ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by the availibility percentage."),
75 },
76 };
77 if withPrices then
78 table.insert(headers, {
79 ["name"] = "Price",
80 ["width"] = (scrollTableWidth * .15),
81 ["align"] = "RIGHT",
82 ["defaultsort"] = "dsc",
83 ["sortnext"] = 1,
84 ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Price"),
85 ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by the price of this item at this vendor."),
86 });
87 end
88
89 local proceedButton = {
90 text = "Move Items",
91 tooltipTitle = (not addon.db.profile.defaults.hideHelp and "Move Items"),
92 tooltip = (not addon.db.profile.defaults.hideHelp and "Start moving these items from the bank."),
93 onClick = OnMoveAccept,
94 };
95 local cancelButton = {
96 text = "Cancel",
97 tooltipTitle = (not addon.db.profile.defaults.hideHelp and "Cancel"),
98 tooltip = (not addon.db.profile.defaults.hideHelp and "Do not move anything and close the window."),
99 onClick = OnMoveCancel,
100 };
101
102 addon:SetFrameSettings("Inventorium Bank Refill", "The items listed below can be refilled from this location, do you wish to move them to your bags?", proceedButton, cancelButton, headers);
26 end 103 end
27 104
28 function mod:ClearCache() 105 function mod:ClearCache()
29 table.wipe(itemCache); 106 table.wipe(itemCache);
30 end 107 end
74 slotId = (slotId - 1); 151 slotId = (slotId - 1);
75 end 152 end
76 end 153 end
77 elseif location == addon.Locations.Guild then 154 elseif location == addon.Locations.Guild then
78 for tabId = 1, GetNumGuildBankTabs() do 155 for tabId = 1, GetNumGuildBankTabs() do
79 local isViewable = select(3, GetGuildBankTabInfo(tabId)); 156 local _, _, isViewable, _, _, remainingWithdrawals = GetGuildBankTabInfo(tabId);
80 157
81 if isViewable == 1 then 158 if isViewable and (remainingWithdrawals > 0 or remainingWithdrawals == -1) then
82 local slotId = (MAX_GUILDBANK_SLOTS_PER_TAB or 98); -- start by scanning the last slot 159 local slotId = (MAX_GUILDBANK_SLOTS_PER_TAB or 98); -- start by scanning the last slot
83 160
84 while slotId ~= 0 do 161 while slotId ~= 0 do
85 -- A not equal-comparison should be quicker than a larger than-comparison 162 -- A not equal-comparison should be quicker than a larger than-comparison
86 163
106 -- Continue scanning a different slot 183 -- Continue scanning a different slot
107 slotId = (slotId - 1); 184 slotId = (slotId - 1);
108 end 185 end
109 end 186 end
110 end 187 end
188 elseif location == addon.Locations.Mailbox then
189 for mailIndex = 1, GetInboxNumItems() do
190 -- All mail items
191
192 for attachIndex = 1, ATTACHMENTS_MAX_RECEIVE do
193 -- All attachments
194
195 local itemLink = GetInboxItemLink(mailIndex, attachIndex);
196 local itemId = itemLink and addon:GetItemId(itemLink);
197 local itemCount = itemLink and select(3, GetInboxItem(mailIndex, attachIndex));
198
199 if itemLink and itemId and itemCount and itemCount > 0 then
200 local itemMove;
201 if not itemCache[itemId] then
202 -- If this is the first time we see this item, make a new object
203 itemMove = addon.ContainerItem:New();
204 itemCache[itemId] = itemMove;
205 else
206 -- If we had this item in another slot too
207 itemMove = itemCache[itemId];
208 end
209
210 itemMove:AddLocation(mailIndex, attachIndex, itemCount);
211 end
212 end
213 end
214 elseif location == addon.Locations.Merchant then
215 for itemIndex = 1, GetMerchantNumItems() do
216 -- All merchant items
217
218 local itemLink = GetMerchantItemLink(itemIndex);
219 local itemId = itemLink and addon:GetItemId(itemLink);
220 local _, _, vendorValue, _, numAvailable, _, extendedCost = GetMerchantItemInfo(index);
221
222 if itemLink and itemId and numAvailable ~= 0 and not extendedCost then
223 local itemMove;
224 if not itemCache[itemId] then
225 -- If this is the first time we see this item, make a new object
226 itemMove = addon.ContainerItem:New();
227 itemCache[itemId] = itemMove;
228 else
229 -- If we had this item in another slot too
230 itemMove = itemCache[itemId];
231 end
232
233 itemMove:AddLocation(1, itemIndex, numAvailable, vendorValue);
234 end
235 end
111 else 236 else
112 error("Invalid location provided for CacheLocation. Must be Bank or Guild."); 237 error("Invalid location provided for CacheLocation. Must be Bank or Guild.");
113 end 238 end
114 239
115 if not remember then 240 if not remember then
123 end 248 end
124 249
125 function mod:Scan(location) 250 function mod:Scan(location)
126 -- We might pause the scanning when we invoke moves ourself 251 -- We might pause the scanning when we invoke moves ourself
127 if paused then 252 if paused then
253 addon:Debug("Not scanning; paused...");
128 return; 254 return;
129 end 255 end
130 256
131 local playerName = UnitName("player"); 257 local playerName = UnitName("player");
132 258
133 currentLocation = location; 259 currentLocation = location;
134 self:CacheLocation(location, true); 260 self:CacheLocation(location, true);
261
262 -- Ensure previous queue isn't remaining
263 Mover:ResetQueue();
135 264
136 -- Go through all groups 265 -- Go through all groups
137 for groupName, values in pairs(addon.db.profile.groups) do 266 for groupName, values in pairs(addon.db.profile.groups) do
138 local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters"); 267 local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters");
139 local localItemData = addon:GetOptionByKey(groupName, "localItemData"); 268 local localItemData = addon:GetOptionByKey(groupName, "localItemData");
151 280
152 if itemCache[itemId] and missingItems > 0 then 281 if itemCache[itemId] and missingItems > 0 then
153 -- Check how many are available 282 -- Check how many are available
154 local availableItems = ((itemCache[itemId] and itemCache[itemId].totalCount) or 0); 283 local availableItems = ((itemCache[itemId] and itemCache[itemId].totalCount) or 0);
155 -- Calculate how many we'll be moving (less missing than available? use missing, otherwise use available) 284 -- Calculate how many we'll be moving (less missing than available? use missing, otherwise use available)
156 local moving = (((missingItems <= availableItems) and missingItems) or availableItems); 285 local moving = (((availableItems == -1 or missingItems <= availableItems) and missingItems) or availableItems);
157 286
158 if availableItems > 0 then 287 if availableItems ~= 0 then
159 --addon:Print("Insufficient " .. IdToItemLink(itemId) .. " but this location has " .. availableItems .. " (moving " .. moving .. ")"); 288 addon:Debug("Insufficient %s but this location has %s (moving %d)", IdToItemLink(itemId), ((availableItems == -1 and "unlimited") or availableItems), moving);
160 289
161 Mover:AddMove(itemId, moving, missingItems, availableItems); 290 Mover:AddMove(itemId, moving, missingItems, availableItems, itemCache[itemId]:GetVendorPrice());
162 else
163 --addon:Print("Insufficient " .. IdToItemLink(itemId));
164 end 291 end
165 end 292 end
166 end 293 end
167 end 294 end
168 end 295 end
169 296
170 self:ClearCache(); 297 self:ClearCache();
171 298
172 if Mover:HasMoves() then 299 if Mover:HasMoves() then
173 if addon.db.profile.defaults.autoRefillSkipConfirm then 300 if addon.db.profile.defaults.autoRefillSkipConfirm then
174 OnMoveAccept(true); 301 OnMoveAccept();
175 else 302 else
303 UseStorageRefillST((location == addon.Locations.Merchant));
304
176 -- This table is never copied, just referenced. It is the same for every row. 305 -- This table is never copied, just referenced. It is the same for every row.
177 local columns = { 306 local columns = {
178 { 307 {
179 value = function(data, cols, realrow, column, table) 308 ["value"] = function(data, cols, realrow, column, table)
180 return IdToItemLink(data[realrow].rowData.id); 309 return IdToItemLink(data[realrow].rowData.itemId);
181 end, 310 end,
182 }, -- item 311 }, -- item
183 { 312 {
184 value = function(data, cols, realrow, column, table) 313 ["value"] = function(data, cols, realrow, column, table)
185 return data[realrow].rowData.num; 314 return data[realrow].rowData.num;
186 end, 315 end,
187 }, -- moving 316 }, -- moving
188 { 317 {
189 value = function(data, cols, realrow, column, table) 318 ["value"] = function(data, cols, realrow, column, table)
190 return addon:DisplayItemCount(data[realrow].rowData.available, data[realrow].rowData.missing); -- available / missing 319 return addon:DisplayItemCount(data[realrow].rowData.available, data[realrow].rowData.missing); -- available / missing
191 end, 320 end,
192 color = function(data, cols, realrow, column, table) 321 ["color"] = function(data, cols, realrow, column, table)
193 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 }; 322 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 };
194 end, 323 end,
195 }, -- missing / available 324 }, -- missing / available
196 }; 325 };
326 if location == addon.Locations.Merchant then
327 table.insert(columns, {
328 ["value"] = function(data, cols, realrow, column, table)
329 return GetCoinTextureString(data[realrow].rowData.price * data[realrow].rowData.num);
330 end,
331 });
332 end
197 333
198 -- Store the list with rows in this 334 -- Store the list with rows in this
199 local data = {}; 335 local data = {};
200 336
201 for i, move in pairs(Mover:GetMoves()) do 337 for i, move in pairs(Mover:GetMoves()) do
277 413
278 scanned = nil; 414 scanned = nil;
279 415
280 -- Get the contents for every tab into our cache 416 -- Get the contents for every tab into our cache
281 for tabId = 1, GetNumGuildBankTabs() do 417 for tabId = 1, GetNumGuildBankTabs() do
282 local isViewable = select(3, GetGuildBankTabInfo(tabId)); 418 local _, _, isViewable, _, _, remainingWithdrawals = GetGuildBankTabInfo(tabId);
283 if isViewable == 1 then 419
420 if isViewable and (remainingWithdrawals > 0 or remainingWithdrawals == -1) then
284 QueryGuildBankTab(tabId); 421 QueryGuildBankTab(tabId);
285 end 422 end
286 end 423 end
287 424
288 self:RegisterEvent("GUILDBANKFRAME_CLOSED"); 425 self:RegisterEvent("GUILDBANKFRAME_CLOSED");
289 self:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED"); 426 self:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED");
290 end 427 end
428
429 function mod:MERCHANT_SHOW()
430 addon:Debug("Scanner:MERCHANT_SHOW");
431
432 self:RegisterEvent("MERCHANT_CLOSED");
433
434 self:Scan(addon.Locations.Merchant);
435 end
436
437 function mod:MERCHANT_CLOSED()
438 addon:Debug("Scanner:MERCHANT_CLOSED");
439
440 self:ClearCache();
441
442 self:UnregisterEvent("MERCHANT_CLOSED");
443
444 InventoriumItemMover:Hide();
445 Mover:ResetQueue();
446 end
447
448 --local previousMailCount;
449 --function mod:MAIL_SHOW()
450 -- addon:Debug("Scanner:MAIL_SHOW");
451 --
452 -- self:RegisterEvent("MAIL_INBOX_UPDATE");
453 -- self:RegisterEvent("MAIL_CLOSED");
454 --
455 -- scanned = nil;
456 -- previousMailCount = nil;
457 --
458 -- self:Scan(addon.Locations.Mailbox);
459 --end
460
461 --function mod:MAIL_INBOX_UPDATE()
462 -- if not scanned then
463 -- addon:Debug("Scanner:MAIL_INBOX_UPDATE");
464 --
465 -- local current, total = GetInboxNumItems();
466 --
467 -- if not previousMailCount or current > previousMailCount then
468 -- -- New mail received
469 --
470 -- scanned = true;
471 --
472 -- self:Scan(addon.Locations.Mailbox);
473 -- end
474 --
475 -- -- Also remember the new mailcount when losing items, otherwise deleting item 50 and getting to 50 again wouldn't trigger a re-scan
476 -- previousMailCount = current;
477 -- else
478 -- addon:Debug("Scanner:MAIL_INBOX_UPDATE skipped, already scanned");
479 -- end
480 --end
481
482 --function mod:MAIL_CLOSED()
483 -- addon:Debug("Scanner:MAIL_CLOSED");
484 --
485 -- previousMailCount = nil;
486 -- scanned = nil;
487 -- self:ClearCache();
488 --
489 -- self:UnregisterEvent("MAIL_INBOX_UPDATE");
490 -- self:UnregisterEvent("MAIL_CLOSED");
491 --
492 -- InventoriumItemMover:Hide();
493 -- Mover:ResetQueue();
494 --end
291 495
292 function mod:OnEnable() 496 function mod:OnEnable()
293 -- Scan once when the bankframe is opened 497 -- Scan once when the bankframe is opened
294 self:RegisterEvent("BANKFRAME_OPENED"); 498 self:RegisterEvent("BANKFRAME_OPENED");
295 self:RegisterEvent("GUILDBANKFRAME_OPENED"); 499 self:RegisterEvent("GUILDBANKFRAME_OPENED");
500 -- self:RegisterEvent("MAIL_SHOW");
501 self:RegisterEvent("MERCHANT_SHOW");
296 502
297 Mover = addon:GetModule("Mover"); 503 Mover = addon:GetModule("Mover");
298 504
299 if not InventoriumItemMover then 505 if not InventoriumItemMover then
300 addon:CreateMoverFrame(OnMoveAccept, OnMoveCancel); 506 addon:CreateMoverFrame(OnMoveAccept, OnMoveCancel);
305 Mover = nil; 511 Mover = nil;
306 currentLocation = nil; 512 currentLocation = nil;
307 paused = nil; 513 paused = nil;
308 514
309 -- Bank 515 -- Bank
516 self:BANKFRAME_CLOSED();
310 self:UnregisterEvent("BANKFRAME_OPENED"); 517 self:UnregisterEvent("BANKFRAME_OPENED");
311 518
312 -- Guild 519 -- Guild
313 self:GUILDBANKFRAME_CLOSED(); 520 self:GUILDBANKFRAME_CLOSED();
314 self:UnregisterEvent("GUILDBANKFRAME_OPENED"); 521 self:UnregisterEvent("GUILDBANKFRAME_OPENED");
522
523 -- -- Mailbox
524 -- self:MAIL_CLOSED();
525 -- self:UnregisterEvent("MAIL_SHOW");
315 end 526 end
316 527
317 function mod:Pause() 528 function mod:Pause()
318 paused = true; 529 paused = true;
319 end 530 end