annotate Modules/Mover.lua @ 92:88898c1e9e61

Fixed queueing of items which have none at the AH.
author Zerotorescue
date Fri, 07 Jan 2011 23:14:33 +0100
parents a12d22ef3f39
children 31493364b163
rev   line source
Zerotorescue@80 1 local addon = select(2, ...);
Zerotorescue@80 2 local mod = addon:NewModule("Mover", "AceEvent-3.0", "AceTimer-3.0");
Zerotorescue@80 3
Zerotorescue@80 4 local Scanner;
Zerotorescue@80 5 local queuedMoves = {}; -- table storing all queued moves before BeginMove is called
Zerotorescue@80 6 local combinedMoves = {}; -- table storing all combined moves (with source and target) that is to be processed by the actual mover in the order of the index (1 to #)
Zerotorescue@81 7 local movesSource;
Zerotorescue@80 8
Zerotorescue@80 9 function mod:AddMove(itemId, amount)
Zerotorescue@80 10 table.insert(queuedMoves, {
Zerotorescue@80 11 id = itemId,
Zerotorescue@80 12 num = amount,
Zerotorescue@80 13 });
Zerotorescue@80 14 end
Zerotorescue@80 15
Zerotorescue@81 16 function mod:HasMoves()
Zerotorescue@81 17 return (#queuedMoves ~= 0);
Zerotorescue@81 18 end
Zerotorescue@81 19
Zerotorescue@84 20 if not table.reverse then
Zerotorescue@84 21 table.reverse = function(orig)
Zerotorescue@84 22 local temp = {};
Zerotorescue@84 23 local origLength = #orig;
Zerotorescue@84 24 for i = 1, origLength do
Zerotorescue@84 25 temp[(origLength - i + 1)] = orig[i];
Zerotorescue@84 26 end
Zerotorescue@84 27
Zerotorescue@84 28 -- -- Update the original table (can't do orig = temp as that would change the reference-link instead of the original table)
Zerotorescue@84 29 -- for i, v in pairs(temp) do
Zerotorescue@84 30 -- orig[i] = v;
Zerotorescue@84 31 -- end
Zerotorescue@84 32 return temp; -- for speed we choose to do a return instead
Zerotorescue@84 33 end
Zerotorescue@84 34 end
Zerotorescue@84 35
Zerotorescue@80 36 function mod:BeginMove(location, onFinish)
Zerotorescue@81 37 addon:Debug("BeginMove");
Zerotorescue@80 38
Zerotorescue@80 39 -- Find the outgoing moves
Zerotorescue@80 40 -- We need the source container and slot, find all the requires sources and put them in a list which we go through later to find matching targets
Zerotorescue@80 41
Zerotorescue@80 42 -- Get a list of items in the source container
Zerotorescue@80 43 local sourceContents = Scanner:CacheLocation(location, false);
Zerotorescue@80 44
Zerotorescue@80 45 local outgoingMoves = {};
Zerotorescue@80 46
Zerotorescue@89 47 addon:Debug("%d moves were queued.", #queuedMoves);
Zerotorescue@82 48
Zerotorescue@81 49 for _, singleMove in pairs(queuedMoves) do
Zerotorescue@80 50 local sourceItem = sourceContents[singleMove.id];
Zerotorescue@80 51 if not sourceItem then
Zerotorescue@80 52 print("Can't move " .. IdToItemLink(singleMove.id) .. ", non-existant in source");
Zerotorescue@80 53 else
Zerotorescue@82 54 -- We want to move the smallest stacks first to keep stuff pretty (and minimize space usage, splitting a stack takes 2 slots, moving something only 1)
Zerotorescue@80 55 table.sort(sourceItem.locations, function(a, b)
Zerotorescue@81 56 return a.count < b.count;
Zerotorescue@80 57 end);
Zerotorescue@80 58
Zerotorescue@81 59 for _, itemLocation in pairs(sourceItem.locations) do
Zerotorescue@80 60 -- if this location has more items than we need, only move what we need, otherwise move everything in this stack
Zerotorescue@80 61 local movingNum = ((itemLocation.count > singleMove.num and singleMove.num) or itemLocation.count);
Zerotorescue@80 62
Zerotorescue@80 63 table.insert(outgoingMoves, {
Zerotorescue@80 64 itemId = singleMove.id,
Zerotorescue@82 65 num = movingNum,
Zerotorescue@80 66 container = itemLocation.container,
Zerotorescue@80 67 slot = itemLocation.slot,
Zerotorescue@80 68 });
Zerotorescue@80 69
Zerotorescue@80 70 singleMove.num = (singleMove.num - movingNum);
Zerotorescue@80 71
Zerotorescue@80 72 if singleMove.num == 0 then
Zerotorescue@80 73 -- If we have prepared everything we wanted, go to the next queued move
Zerotorescue@81 74 break; -- stop the locations-loop
Zerotorescue@80 75 end
Zerotorescue@80 76 end
Zerotorescue@80 77 end
Zerotorescue@80 78 end
Zerotorescue@82 79
Zerotorescue@89 80 addon:Debug("%d outgoing moves are possible.", #outgoingMoves);
Zerotorescue@80 81
Zerotorescue@80 82 -- No longer needed
Zerotorescue@80 83 table.wipe(queuedMoves);
Zerotorescue@80 84
Zerotorescue@80 85 -- Process every single outgoing move and find fitting targets
Zerotorescue@80 86
Zerotorescue@80 87 -- Get a list of items already in the target container
Zerotorescue@80 88 local targetContents = Scanner:CacheLocation(addon.Locations.Bag, false);
Zerotorescue@80 89
Zerotorescue@80 90 -- Find all empty slots
Zerotorescue@80 91
Zerotorescue@80 92 local emptySlots = {};
Zerotorescue@80 93
Zerotorescue@80 94 local start = 0;
Zerotorescue@80 95 local stop = NUM_BAG_SLOTS;
Zerotorescue@80 96
Zerotorescue@80 97 -- Go through all our bags, including the backpack
Zerotorescue@80 98 for bagId = start, stop do
Zerotorescue@80 99 -- Go through all our slots
Zerotorescue@80 100 for slotId = 1, GetContainerNumSlots(bagId) do
Zerotorescue@82 101 local itemId = GetContainerItemID(bagId, slotId); -- we're scanning our local bags here, so no need to get messy with guild bank support
Zerotorescue@80 102
Zerotorescue@80 103 if not itemId then
Zerotorescue@80 104 table.insert(emptySlots, {
Zerotorescue@81 105 container = bagId,
Zerotorescue@81 106 slot = slotId,
Zerotorescue@80 107 });
Zerotorescue@80 108 end
Zerotorescue@80 109 end
Zerotorescue@80 110 end
Zerotorescue@82 111
Zerotorescue@89 112 addon:Debug("%d empty slots are available.", #emptySlots);
Zerotorescue@80 113
Zerotorescue@81 114 -- Remember where we're moving from
Zerotorescue@81 115 movesSource = location;
Zerotorescue@81 116
Zerotorescue@84 117 local backup = 0;
Zerotorescue@84 118
Zerotorescue@80 119 while #outgoingMoves ~= 0 do
Zerotorescue@80 120 -- A not equal-comparison should be quicker than a larger/smaller than-comparison
Zerotorescue@80 121
Zerotorescue@81 122 for _, outgoingMove in pairs(outgoingMoves) do
Zerotorescue@80 123 -- itemId will be set to nil when this outgoing move was processed - sanity check
Zerotorescue@80 124 if outgoingMove.itemId then
Zerotorescue@80 125 local targetItem = targetContents[outgoingMove.itemId];
Zerotorescue@80 126
Zerotorescue@80 127 if not targetItem then
Zerotorescue@80 128 -- grab an empty slot
Zerotorescue@80 129 -- make new instance of ItemMove
Zerotorescue@80 130 -- populate targetContents with it so future moves of this item can be put on top of it if this isn't a full stack
Zerotorescue@80 131
Zerotorescue@80 132 local firstAvailableSlot = emptySlots[1];
Zerotorescue@80 133
Zerotorescue@80 134 if not firstAvailableSlot then
Zerotorescue@80 135 print("Bags are full. Skipping " .. IdToItemLink(outgoingMove.itemId) .. ".");
Zerotorescue@80 136
Zerotorescue@82 137 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table
Zerotorescue@80 138 else
Zerotorescue@80 139 table.insert(combinedMoves, {
Zerotorescue@82 140 itemId = outgoingMove.itemId,
Zerotorescue@82 141 num = outgoingMove.num,
Zerotorescue@80 142 sourceContainer = outgoingMove.container,
Zerotorescue@80 143 sourceSlot = outgoingMove.slot,
Zerotorescue@80 144 targetContainer = firstAvailableSlot.container,
Zerotorescue@80 145 targetSlot = firstAvailableSlot.slot,
Zerotorescue@80 146 });
Zerotorescue@80 147
Zerotorescue@80 148 -- We filled an empty slot so the target contents now has one more item,
Zerotorescue@80 149 -- make a new instance of the ItemMove class so any additional items with this id can be stacked on top of it
Zerotorescue@81 150 local itemMove = addon.ContainerItem:New();
Zerotorescue@82 151 itemMove:AddLocation(firstAvailableSlot.container, firstAvailableSlot.slot, outgoingMove.num);
Zerotorescue@80 152 targetContents[outgoingMove.itemId] = itemMove;
Zerotorescue@80 153
Zerotorescue@81 154 table.remove(emptySlots, 1); -- no longer empty
Zerotorescue@80 155
Zerotorescue@82 156 outgoingMove.num = 0; -- nothing remaining - sanity check
Zerotorescue@80 157 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table
Zerotorescue@80 158 end
Zerotorescue@80 159 else
Zerotorescue@80 160 -- Find the maximum stack size for this item
Zerotorescue@80 161 local itemStackCount = select(8, GetItemInfo(outgoingMove.itemId));
Zerotorescue@80 162
Zerotorescue@80 163 -- We want to move to the largest stacks first to keep stuff pretty
Zerotorescue@80 164 table.sort(targetItem.locations, function(a, b)
Zerotorescue@81 165 return a.count > b.count;
Zerotorescue@80 166 end);
Zerotorescue@80 167
Zerotorescue@81 168 for _, itemLocation in pairs(targetItem.locations) do
Zerotorescue@82 169 if itemLocation.count < itemStackCount and outgoingMove.num > 0 then
Zerotorescue@80 170 -- Check if this stack isn't already full (and we still need to move this item)
Zerotorescue@80 171
Zerotorescue@80 172 local remainingSpace = (itemStackCount - itemLocation.count);
Zerotorescue@84 173 if remainingSpace >= outgoingMove.num then
Zerotorescue@80 174 -- Enough room to move this entire stack
Zerotorescue@80 175 -- Deposit this item and then forget this outgoing move as everything in it was processed
Zerotorescue@80 176
Zerotorescue@80 177 table.insert(combinedMoves, {
Zerotorescue@82 178 itemId = outgoingMove.itemId,
Zerotorescue@82 179 num = outgoingMove.num,
Zerotorescue@80 180 sourceContainer = outgoingMove.container,
Zerotorescue@80 181 sourceSlot = outgoingMove.slot,
Zerotorescue@80 182 targetContainer = itemLocation.container,
Zerotorescue@80 183 targetSlot = itemLocation.slot,
Zerotorescue@80 184 });
Zerotorescue@80 185
Zerotorescue@82 186 itemLocation.count = (itemLocation.count + outgoingMove.num);
Zerotorescue@84 187 outgoingMove.num = 0; -- nothing remaining
Zerotorescue@80 188 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table
Zerotorescue@80 189 break; -- stop the locations-loop
Zerotorescue@80 190 else
Zerotorescue@80 191 -- Deposit this item but don't remove the outgoing move as there are some items left to move
Zerotorescue@80 192
Zerotorescue@80 193 table.insert(combinedMoves, {
Zerotorescue@82 194 itemId = outgoingMove.itemId,
Zerotorescue@82 195 num = outgoingMove.num,
Zerotorescue@80 196 sourceContainer = outgoingMove.container,
Zerotorescue@80 197 sourceSlot = outgoingMove.slot,
Zerotorescue@80 198 targetContainer = itemLocation.container,
Zerotorescue@80 199 targetSlot = itemLocation.slot,
Zerotorescue@80 200 });
Zerotorescue@80 201
Zerotorescue@80 202 -- The target will be full when we complete, but the source will still have remaining items left to be moved
Zerotorescue@80 203 itemLocation.count = itemStackCount;
Zerotorescue@82 204 outgoingMove.num = (outgoingMove.num - remainingSpace);
Zerotorescue@80 205 end
Zerotorescue@80 206 end
Zerotorescue@80 207 end
Zerotorescue@80 208
Zerotorescue@82 209 if outgoingMove.num > 0 then
Zerotorescue@80 210 -- We went through all matching items and checked their stack sizes if we could move this there, no room available
Zerotorescue@80 211 -- So forget about the target item (even though it may just have full locations, these are useless anyway) and the next loop move it onto an empty slot
Zerotorescue@84 212 targetContents[outgoingMove.itemId] = nil;
Zerotorescue@80 213 end
Zerotorescue@80 214 end
Zerotorescue@80 215 end
Zerotorescue@80 216 end
Zerotorescue@80 217
Zerotorescue@80 218 -- Loop through the array to find items that should be removed, start with the last element or the loop would break
Zerotorescue@80 219 local numOutgoingMoves = #outgoingMoves; -- since LUA-tables start at an index of 1, this is actually an existing index (outgoingMoves[#outgoingMoves] would return a value)
Zerotorescue@80 220 while numOutgoingMoves ~= 0 do
Zerotorescue@80 221 -- A not equal-comparison should be quicker than a larger/smaller than-comparison
Zerotorescue@80 222
Zerotorescue@80 223 -- Check if the item id is nil, this is set to nil when this outgoing move has been processed
Zerotorescue@84 224 if not outgoingMoves[numOutgoingMoves].itemId or outgoingMoves[numOutgoingMoves].num == 0 then
Zerotorescue@80 225 -- Remove this element from the array
Zerotorescue@80 226 table.remove(outgoingMoves, numOutgoingMoves);
Zerotorescue@80 227 end
Zerotorescue@80 228
Zerotorescue@80 229 -- Proceed with the next element (or previous considering we're going from last to first)
Zerotorescue@80 230 numOutgoingMoves = (numOutgoingMoves - 1);
Zerotorescue@80 231 end
Zerotorescue@84 232
Zerotorescue@89 233 addon:Debug("%d moves remaining.", #outgoingMoves);
Zerotorescue@84 234
Zerotorescue@84 235 backup = (backup + 1);
Zerotorescue@84 236 if backup > 1000 then
Zerotorescue@84 237 dump(nil, outgoingMoves);
Zerotorescue@84 238 table.wipe(outgoingMoves);
Zerotorescue@84 239 self:Abort("mover crashed", "Error preparing moves, hit an endless loop");
Zerotorescue@84 240 onFinish();
Zerotorescue@84 241 return;
Zerotorescue@84 242 end
Zerotorescue@80 243 end
Zerotorescue@84 244
Zerotorescue@84 245 -- Reverse table, we need to go through it from last to first because we'll be removing elements, but we don't want the actions to be executed in a different order
Zerotorescue@84 246 combinedMoves = table.reverse(combinedMoves);
Zerotorescue@82 247
Zerotorescue@89 248 addon:Debug("%d moves should be possible.", #combinedMoves);
Zerotorescue@80 249
Zerotorescue@80 250 -- No longer needed
Zerotorescue@80 251 table.wipe(emptySlots);
Zerotorescue@80 252
Zerotorescue@81 253 self:ProcessMove();
Zerotorescue@80 254
Zerotorescue@82 255 -- Even though we aren't completely done yet, allow requeueing
Zerotorescue@81 256 onFinish();
Zerotorescue@80 257 end
Zerotorescue@80 258
Zerotorescue@81 259 function mod:ProcessMove()
Zerotorescue@81 260 addon:Debug("ProcessMove");
Zerotorescue@81 261
Zerotorescue@81 262 if #combinedMoves == 0 then
Zerotorescue@81 263 print("Nothing to move.");
Zerotorescue@81 264
Zerotorescue@81 265 self:Abort();
Zerotorescue@81 266
Zerotorescue@81 267 return;
Zerotorescue@81 268 end
Zerotorescue@81 269
Zerotorescue@88 270 --self:RegisterEvent("BAG_UPDATE");
Zerotorescue@88 271 self:RegisterEvent("ITEM_LOCK_CHANGED");
Zerotorescue@81 272 self:RegisterEvent("UI_ERROR_MESSAGE");
Zerotorescue@81 273
Zerotorescue@80 274 -- combinedMoves now has all moves in it (source -> target)
Zerotorescue@80 275 -- go through list, move everything inside it
Zerotorescue@81 276 -- add source and target to lists, if either is already in this list, skip the move
Zerotorescue@81 277 -- repeat every few seconds until we're completely done
Zerotorescue@80 278
Zerotorescue@80 279 local sourceLocationsLocked = {};
Zerotorescue@80 280 local targetLocationsLocked = {};
Zerotorescue@80 281
Zerotorescue@84 282 local _GetContainerItemId = GetContainerItemID;
Zerotorescue@82 283 if movesSource == addon.Locations.Guild then
Zerotorescue@84 284 _GetContainerItemId = function(tabId, slotId) return addon:GetItemID(GetGuildBankItemLink(tabId, slotId)); end;
Zerotorescue@82 285 end
Zerotorescue@89 286 local _GetContainerItemInfo = GetContainerItemInfo;
Zerotorescue@89 287 if movesSource == addon.Locations.Guild then
Zerotorescue@89 288 _GetContainerItemInfo = GetGuildBankItemInfo;
Zerotorescue@89 289 end
Zerotorescue@82 290
Zerotorescue@82 291 local combinedMovesOriginalLength = #combinedMoves;
Zerotorescue@82 292 local numCurrentMove = combinedMovesOriginalLength;
Zerotorescue@80 293 while numCurrentMove ~= 0 do
Zerotorescue@80 294 local move = combinedMoves[numCurrentMove];
Zerotorescue@80 295
Zerotorescue@89 296 local isSourceLocked = ((sourceLocationsLocked[move.sourceContainer] and sourceLocationsLocked[move.sourceContainer][move.sourceSlot]) or select(3, _GetContainerItemInfo(move.sourceContainer, move.sourceSlot)));
Zerotorescue@89 297 local isTargetLocked = ((targetLocationsLocked[move.targetContainer] and targetLocationsLocked[move.targetContainer][move.targetSlot]) or select(3, GetContainerItemInfo(move.targetContainer, move.targetSlot)));
Zerotorescue@88 298
Zerotorescue@89 299 if move and not isSourceLocked and not isTargetLocked then
Zerotorescue@80 300
Zerotorescue@84 301 print(("Moving %dx%s."):format(move.num, IdToItemLink(move.itemId)));
Zerotorescue@80 302
Zerotorescue@89 303 addon:Debug("Moving %dx%s from (%d,%d) to (%d,%d)", move.num, IdToItemLink(move.itemId), move.sourceContainer, move.sourceSlot, move.targetContainer, move.targetSlot);
Zerotorescue@81 304
Zerotorescue@84 305 if _GetContainerItemId(move.sourceContainer, move.sourceSlot) ~= move.itemId then
Zerotorescue@81 306 self:Abort("source changed", "Source (" .. move.sourceContainer .. "," .. move.sourceSlot .. ") is not " .. IdToItemLink(move.itemId));
Zerotorescue@81 307 return;
Zerotorescue@81 308 end
Zerotorescue@81 309
Zerotorescue@80 310 -- Pickup stack
Zerotorescue@81 311 if movesSource == addon.Locations.Bank then
Zerotorescue@81 312 SplitContainerItem(move.sourceContainer, move.sourceSlot, move.num);
Zerotorescue@81 313 elseif movesSource == addon.Locations.Guild then
Zerotorescue@81 314 SplitGuildBankItem(move.sourceContainer, move.sourceSlot, move.num);
Zerotorescue@81 315 end
Zerotorescue@80 316
Zerotorescue@80 317 -- Remember we picked this item up and thus it is now locked
Zerotorescue@80 318 if not sourceLocationsLocked[move.sourceContainer] then
Zerotorescue@80 319 sourceLocationsLocked[move.sourceContainer] = {};
Zerotorescue@80 320 end
Zerotorescue@80 321 sourceLocationsLocked[move.sourceContainer][move.sourceSlot] = true;
Zerotorescue@80 322
Zerotorescue@81 323 if movesSource == addon.Locations.Guild or CursorHasItem() then -- CursorHasItem is always false if source is a guild tab
Zerotorescue@84 324 -- We are moving into our local bags, so the below must check normal
Zerotorescue@84 325 local targetItemId = GetContainerItemID(move.targetContainer, move.targetSlot);
Zerotorescue@84 326 if targetItemId and targetItemId ~= move.itemId then
Zerotorescue@81 327 self:Abort("target changed", "Target (" .. move.targetContainer .. "," .. move.targetSlot .. ") is not " .. IdToItemLink(move.itemId) .. " nor empty");
Zerotorescue@81 328 return;
Zerotorescue@81 329 end
Zerotorescue@81 330
Zerotorescue@82 331 -- And drop it (this is always a local bag so no need to do any guild-checks)
Zerotorescue@80 332 PickupContainerItem(move.targetContainer, move.targetSlot);
Zerotorescue@80 333
Zerotorescue@80 334 -- Remember we dropped an item here and thus this is now locked
Zerotorescue@81 335 if not targetLocationsLocked[move.targetContainer] then
Zerotorescue@81 336 targetLocationsLocked[move.targetContainer] = {};
Zerotorescue@80 337 end
Zerotorescue@81 338 targetLocationsLocked[move.targetContainer][move.targetSlot] = true;
Zerotorescue@80 339
Zerotorescue@80 340 -- This move was processed
Zerotorescue@80 341 table.remove(combinedMoves, numCurrentMove);
Zerotorescue@81 342 else
Zerotorescue@81 343 self:Abort("item disappeared from mouse", "Couldn't move " .. IdToItemLink(move.itemId) .. ", CursorHasItem() is false");
Zerotorescue@81 344 return;
Zerotorescue@80 345 end
Zerotorescue@80 346 end
Zerotorescue@80 347
Zerotorescue@80 348 -- Proceed with the next element (or previous considering we're going from last to first)
Zerotorescue@80 349 numCurrentMove = (numCurrentMove - 1);
Zerotorescue@80 350 end
Zerotorescue@81 351
Zerotorescue@89 352 addon:Debug("%d moves processed. %d moves remaining.", (combinedMovesOriginalLength - #combinedMoves), #combinedMoves);
Zerotorescue@82 353
Zerotorescue@81 354 if #combinedMoves == 0 then
Zerotorescue@81 355 print("Finished.");
Zerotorescue@81 356
Zerotorescue@81 357 self:Abort();
Zerotorescue@81 358
Zerotorescue@81 359 return;
Zerotorescue@81 360 end
Zerotorescue@80 361 end
Zerotorescue@80 362
Zerotorescue@80 363 local tmrProcessNext;
Zerotorescue@88 364 function mod:ITEM_LOCK_CHANGED()
Zerotorescue@81 365 self:CancelTimer(tmrProcessNext, true); -- silent
Zerotorescue@89 366 tmrProcessNext = self:ScheduleTimer("ProcessMove", .5);
Zerotorescue@80 367 end
Zerotorescue@80 368
Zerotorescue@81 369 function IdToItemLink(itemId)
Zerotorescue@81 370 local itemLink = select(2, GetItemInfo(itemId));
Zerotorescue@81 371 itemLink = itemLink or "Unknown (" .. itemId .. ")";
Zerotorescue@81 372 return itemLink;
Zerotorescue@81 373 end
Zerotorescue@81 374
Zerotorescue@81 375 function mod:UI_ERROR_MESSAGE(e, errorMessage)
Zerotorescue@81 376 if errorMessage == ERR_SPLIT_FAILED then
Zerotorescue@81 377 self:Abort("splitting failed", "Splitting failed.");
Zerotorescue@80 378 end
Zerotorescue@80 379 end
Zerotorescue@80 380
Zerotorescue@81 381 function mod:Abort(simple, debugMsg)
Zerotorescue@81 382 if debugMsg then
Zerotorescue@89 383 addon:Debug("Aborting:%s", debugMsg);
Zerotorescue@81 384 end
Zerotorescue@81 385 if simple then
Zerotorescue@81 386 print("|cffff0000Aborting: " .. simple .. ".|r");
Zerotorescue@81 387 end
Zerotorescue@81 388 table.wipe(combinedMoves);
Zerotorescue@81 389 movesSource = nil;
Zerotorescue@80 390
Zerotorescue@81 391 -- Stop timer
Zerotorescue@89 392 self:UnregisterEvent("ITEM_LOCK_CHANGED");
Zerotorescue@81 393 self:CancelTimer(tmrProcessNext, true); -- silent
Zerotorescue@80 394
Zerotorescue@81 395 self:UnregisterEvent("UI_ERROR_MESSAGE");
Zerotorescue@80 396 end
Zerotorescue@80 397
Zerotorescue@80 398 function mod:OnEnable()
Zerotorescue@80 399 Scanner = addon:GetModule("Scanner");
Zerotorescue@80 400 end
Zerotorescue@80 401
Zerotorescue@80 402 function mod:OnDisable()
Zerotorescue@80 403 Scanner = nil;
Zerotorescue@81 404
Zerotorescue@81 405 self:Abort();
Zerotorescue@80 406 end