annotate Modules/Queue.lua @ 144:12a8ea5af671

Added a ?remove? button to the crafting queue. When removing an item from the queue or when it is finished casting (when using the Inventorium queue processer), items are moved to the ?unqueuables? window. Fixed auction price checking. Now resetting filters before scanning the tradeskill recipes.
author Zerotorescue
date Wed, 19 Jan 2011 23:21:16 +0100
parents 8eb0f5b5a885
children 6a52272a0e5a
rev   line source
Zerotorescue@17 1 local addon = select(2, ...);
Zerotorescue@13 2 local mod = addon:NewModule("Queue", "AceEvent-3.0", "AceTimer-3.0");
Zerotorescue@13 3
Zerotorescue@132 4 local _G = _G;
Zerotorescue@144 5 local tonumber, tostring, pairs, sformat, smatch, slower, floor, ceil, tinsert, twipe = _G.tonumber, _G.tostring, _G.pairs, _G.string.format, _G.string.match, _G.string.lower, _G.floor, _G.ceil, _G.table.insert, _G.table.wipe;
Zerotorescue@132 6
Zerotorescue@132 7 local queue, skipped = {}, {};
Zerotorescue@132 8
Zerotorescue@132 9 -- strings are passed by reference, so it takes no additional memory if one string was used in a thousand tables compared to any other reference type
Zerotorescue@132 10 local skipReasons = {
Zerotorescue@143 11 ["NOT_CRAFTABLE"] = {
Zerotorescue@143 12 "|cff3d3d3dNot in profession|r", -- gray
Zerotorescue@143 13 "This item is not part of this profession.",
Zerotorescue@143 14 0,
Zerotorescue@143 15 },
Zerotorescue@143 16 ["CAPPED"] = {
Zerotorescue@143 17 "|cff66ff33Fully stocked|r", -- lime/green
Zerotorescue@143 18 "The recorded item count is above or equal to your minimum restock target setting.",
Zerotorescue@143 19 5,
Zerotorescue@143 20 },
Zerotorescue@143 21 ["MIN_CRAFTING_QUEUE"] = {
Zerotorescue@143 22 "|cffffff00Min crafting queue|r", -- yellow
Zerotorescue@143 23 "The amount of missing items is below or equal to your \"don't queue if I only miss\"-setting.",
Zerotorescue@143 24 10,
Zerotorescue@143 25 },
Zerotorescue@143 26 ["LOW_VALUE"] = {
Zerotorescue@143 27 "|cffff6633Underpriced|r", -- orange
Zerotorescue@143 28 "The recorded auction value of this item is below your price threshold.",
Zerotorescue@143 29 15,
Zerotorescue@143 30 },
Zerotorescue@143 31 ["NO_ITEMCOUNT_ADDON"] = {
Zerotorescue@143 32 "|cffff0000No itemcount addon|r", -- red
Zerotorescue@143 33 "No compatible item count could be found.",
Zerotorescue@143 34 20,
Zerotorescue@143 35 },
Zerotorescue@144 36 ["REMOVED"] = { -- because this is updated realtime, it is most useful around the top of the list
Zerotorescue@144 37 "|cffff0000Removed|r", -- red
Zerotorescue@144 38 "You manually removed this item from the queue.",
Zerotorescue@144 39 45,
Zerotorescue@144 40 },
Zerotorescue@144 41 ["FINISHED"] = { -- because this is updated realtime, it is most useful on the top of the list
Zerotorescue@144 42 "|cff00ff00Just finished|r", -- green
Zerotorescue@144 43 "Just finished restocking this item.",
Zerotorescue@144 44 50,
Zerotorescue@144 45 },
Zerotorescue@132 46 };
Zerotorescue@132 47
Zerotorescue@132 48 local function MakeQueueWindow()
Zerotorescue@143 49 if not InventoriumQueuer then
Zerotorescue@143 50 addon:CreateQueueFrame();
Zerotorescue@143 51
Zerotorescue@132 52 local frame = InventoriumQueuer; -- both for speed as code-consistency
Zerotorescue@132 53
Zerotorescue@132 54 -- Scrolling table with a list of items to be moved
Zerotorescue@132 55 local scrollTableWidth = ( frame.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size
Zerotorescue@132 56 local headers = {
Zerotorescue@132 57 {
Zerotorescue@132 58 ["name"] = "Item",
Zerotorescue@144 59 ["width"] = (scrollTableWidth * .65),
Zerotorescue@132 60 ["defaultsort"] = "asc",
Zerotorescue@132 61 ["comparesort"] = function(this, aRow, bRow, column)
Zerotorescue@132 62 local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId);
Zerotorescue@132 63 local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId);
Zerotorescue@132 64 local template = "%d%s";
Zerotorescue@143 65 aName = sformat(template, (10 - (aRarity or 10)), slower(aName or ""));
Zerotorescue@143 66 bName = sformat(template, (10 - (bRarity or 10)), slower(bName or ""));
Zerotorescue@132 67
Zerotorescue@132 68 if this.cols[column].sort == "dsc" then
Zerotorescue@132 69 return aName > bName;
Zerotorescue@132 70 else
Zerotorescue@132 71 return aName < bName;
Zerotorescue@132 72 end
Zerotorescue@132 73 end,
Zerotorescue@132 74 ["sort"] = "asc", -- when the data is set, use this column so sort the default data
Zerotorescue@144 75 ["tooltipTitle"] = "Item",
Zerotorescue@144 76 ["tooltip"] = "Click to sort the list by item quality then item name.",
Zerotorescue@132 77 },
Zerotorescue@132 78 {
Zerotorescue@132 79 ["name"] = "Amount",
Zerotorescue@144 80 ["width"] = (scrollTableWidth * .15),
Zerotorescue@132 81 ["align"] = "RIGHT",
Zerotorescue@132 82 ["defaultsort"] = "dsc",
Zerotorescue@143 83 ["comparesort"] = function(this, aRow, bRow, column)
Zerotorescue@143 84 if this.cols[column].sort == "dsc" then
Zerotorescue@143 85 return (this:GetRow(aRow).rowData.amount > this:GetRow(bRow).rowData.amount);
Zerotorescue@143 86 else
Zerotorescue@143 87 return (this:GetRow(aRow).rowData.amount < this:GetRow(bRow).rowData.amount);
Zerotorescue@143 88 end
Zerotorescue@143 89 end,
Zerotorescue@132 90 ["sortnext"] = 1,
Zerotorescue@144 91 ["tooltipTitle"] = "Amount needed",
Zerotorescue@144 92 ["tooltip"] = "Click to sort the list by the amount of items needed to reach the restock target.",
Zerotorescue@132 93 },
Zerotorescue@132 94 {
Zerotorescue@132 95 ["name"] = "Extra",
Zerotorescue@144 96 ["width"] = (scrollTableWidth * .15),
Zerotorescue@132 97 ["align"] = "RIGHT",
Zerotorescue@132 98 ["defaultsort"] = "dsc",
Zerotorescue@143 99 ["comparesort"] = function(this, aRow, bRow, column)
Zerotorescue@143 100 if this.cols[column].sort == "dsc" then
Zerotorescue@143 101 return (this:GetRow(aRow).rowData.bonus > this:GetRow(bRow).rowData.bonus);
Zerotorescue@143 102 else
Zerotorescue@143 103 return (this:GetRow(aRow).rowData.bonus < this:GetRow(bRow).rowData.bonus);
Zerotorescue@143 104 end
Zerotorescue@143 105 end,
Zerotorescue@132 106 ["sortnext"] = 1,
Zerotorescue@144 107 ["tooltipTitle"] = "Extra items",
Zerotorescue@144 108 ["tooltip"] = "Click to sort the list by the amount of bonus items.",
Zerotorescue@144 109 },
Zerotorescue@144 110 {
Zerotorescue@144 111 ["name"] = "X",
Zerotorescue@144 112 ["width"] = (scrollTableWidth * .05),
Zerotorescue@144 113 ["align"] = "CENTER",
Zerotorescue@144 114 ["sortnext"] = 1,
Zerotorescue@144 115 ["tooltipTitle"] = "Remove",
Zerotorescue@144 116 ["tooltip"] = "Click any of the fields in this column to remove this item from the queue.",
Zerotorescue@144 117 ["onClick"] = function(rowData)
Zerotorescue@144 118 -- Remove this element from the queue
Zerotorescue@144 119 for index, q in pairs(queue) do
Zerotorescue@144 120 if q == rowData then
Zerotorescue@144 121 table.remove(queue, index);
Zerotorescue@144 122 mod:Skip(q.itemId, skipReasons.REMOVED);
Zerotorescue@144 123 break;
Zerotorescue@144 124 end
Zerotorescue@144 125 end
Zerotorescue@144 126
Zerotorescue@144 127 -- Rebuild our scrolltable (records were removed and added)
Zerotorescue@144 128 mod:BuildQueue();
Zerotorescue@144 129 end,
Zerotorescue@144 130 ["color"] = { ["r"] = 1.0, ["g"] = 0.0, ["b"] = 0.0, ["a"] = 1, },
Zerotorescue@132 131 },
Zerotorescue@132 132 };
Zerotorescue@132 133
Zerotorescue@132 134 local scrollTableWidth = ( InventoriumQueuerUnqueueables.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size
Zerotorescue@132 135 local unqueueablesHeaders = {
Zerotorescue@132 136 {
Zerotorescue@132 137 ["name"] = "Item",
Zerotorescue@132 138 ["width"] = (scrollTableWidth * .6),
Zerotorescue@132 139 ["defaultsort"] = "asc",
Zerotorescue@132 140 ["comparesort"] = function(this, aRow, bRow, column)
Zerotorescue@132 141 local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId);
Zerotorescue@132 142 local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId);
Zerotorescue@132 143 local template = "%d%s";
Zerotorescue@143 144 aName = sformat(template, (10 - (aRarity or 10)), slower(aName or ""));
Zerotorescue@143 145 bName = sformat(template, (10 - (bRarity or 10)), slower(bName or ""));
Zerotorescue@132 146
Zerotorescue@132 147 if this.cols[column].sort == "dsc" then
Zerotorescue@132 148 return aName > bName;
Zerotorescue@132 149 else
Zerotorescue@132 150 return aName < bName;
Zerotorescue@132 151 end
Zerotorescue@132 152 end,
Zerotorescue@144 153 ["tooltipTitle"] = "Item",
Zerotorescue@144 154 ["tooltip"] = "Click to sort the list by item quality then item name.",
Zerotorescue@132 155 },
Zerotorescue@132 156 {
Zerotorescue@132 157 ["name"] = "Reason",
Zerotorescue@132 158 ["width"] = (scrollTableWidth * .4),
Zerotorescue@132 159 ["defaultsort"] = "dsc",
Zerotorescue@143 160 ["comparesort"] = function(this, aRow, bRow, column)
Zerotorescue@143 161 if this.cols[column].sort == "dsc" then
Zerotorescue@144 162 return this:GetRow(aRow).rowData.reason[3] > this:GetRow(bRow).rowData.reason[3];
Zerotorescue@143 163 else
Zerotorescue@144 164 return this:GetRow(aRow).rowData.reason[3] < this:GetRow(bRow).rowData.reason[3];
Zerotorescue@143 165 end
Zerotorescue@143 166 end,
Zerotorescue@143 167 ["sort"] = "dsc", -- when the data is set, use this column to sort the default data
Zerotorescue@132 168 ["sortnext"] = 1,
Zerotorescue@144 169 ["tooltipTitle"] = "Reason",
Zerotorescue@144 170 ["tooltip"] = "Click to sort the list by the reason the items couldn't be queued.",
Zerotorescue@132 171 },
Zerotorescue@132 172 };
Zerotorescue@132 173
Zerotorescue@132 174 local proceedButton = {
Zerotorescue@132 175 text = "Queue",
Zerotorescue@144 176 tooltipTitle = "Queue",
Zerotorescue@144 177 tooltip = "Add these items to the queue of your crafting addon.",
Zerotorescue@144 178 onClick = function() mod:QueueProcess(); end,
Zerotorescue@132 179 };
Zerotorescue@132 180 local cancelButton = {
Zerotorescue@132 181 text = "Cancel",
Zerotorescue@144 182 tooltipTitle = "Cancel",
Zerotorescue@144 183 tooltip = "Do not queue anything and close the window.",
Zerotorescue@144 184 onClick = function() mod:QueueAbort(); end,
Zerotorescue@132 185 };
Zerotorescue@132 186
Zerotorescue@132 187 addon:SetQueueFrameSettings("Inventorium Queue", "The following items can be added to the queue of your crafting addon. Do you wish to proceed?", proceedButton, cancelButton, headers, unqueueablesHeaders);
Zerotorescue@132 188 end
Zerotorescue@132 189 end
Zerotorescue@132 190
Zerotorescue@144 191 function mod:BuildQueue()
Zerotorescue@132 192 MakeQueueWindow();
Zerotorescue@132 193
Zerotorescue@132 194 -- This table is never copied, just referenced. It is the same for every row.
Zerotorescue@132 195 local queueablesColumns = {
Zerotorescue@132 196 {
Zerotorescue@132 197 ["value"] = function(data, cols, realrow, column, table)
Zerotorescue@132 198 return IdToItemLink(data[realrow].rowData.itemId);
Zerotorescue@132 199 end,
Zerotorescue@132 200 }, -- item
Zerotorescue@132 201 {
Zerotorescue@132 202 ["value"] = function(data, cols, realrow, column, table)
Zerotorescue@132 203 return data[realrow].rowData.amount;
Zerotorescue@132 204 end,
Zerotorescue@132 205 }, -- amount
Zerotorescue@132 206 {
Zerotorescue@132 207 ["value"] = function(data, cols, realrow, column, table)
Zerotorescue@143 208 return ((data[realrow].rowData.bonus == 0) and 0) or "+" .. data[realrow].rowData.bonus;
Zerotorescue@132 209 end,
Zerotorescue@132 210 ["color"] = function(data, cols, realrow, column, table)
Zerotorescue@132 211 return ((data[realrow].rowData.bonus == 0) and { r = 1, g = 1, b = 1, a = 0.5 }) or { r = 0, g = 1, b = 0, a = 1 };
Zerotorescue@132 212 end,
Zerotorescue@132 213 }, -- extra
Zerotorescue@144 214 {
Zerotorescue@144 215 ["value"] = "X",
Zerotorescue@144 216 },
Zerotorescue@132 217 };
Zerotorescue@132 218
Zerotorescue@132 219 -- Store the list with rows in this
Zerotorescue@132 220 local queueables = {};
Zerotorescue@132 221
Zerotorescue@132 222 for _, q in pairs(queue) do
Zerotorescue@132 223 tinsert(queueables, {
Zerotorescue@132 224 ["rowData"] = q, -- this is not a key usually found in a row item and ignored by the library
Zerotorescue@132 225 ["cols"] = queueablesColumns,
Zerotorescue@132 226 });
Zerotorescue@132 227 end
Zerotorescue@132 228
Zerotorescue@132 229 -- This table is never copied, just referenced. It is the same for every row.
Zerotorescue@132 230 local unqueueablesColumns = {
Zerotorescue@132 231 {
Zerotorescue@132 232 ["value"] = function(data, cols, realrow, column, table)
Zerotorescue@132 233 return IdToItemLink(data[realrow].rowData.itemId);
Zerotorescue@132 234 end,
Zerotorescue@132 235 }, -- item
Zerotorescue@132 236 {
Zerotorescue@132 237 ["value"] = function(data, cols, realrow, column, table)
Zerotorescue@132 238 return data[realrow].rowData.reason[1];
Zerotorescue@132 239 end,
Zerotorescue@132 240 }, -- reason
Zerotorescue@132 241 };
Zerotorescue@132 242
Zerotorescue@132 243 -- Store the list with rows in this
Zerotorescue@132 244 local unqueueables = {};
Zerotorescue@132 245
Zerotorescue@132 246 for _, s in pairs(skipped) do
Zerotorescue@132 247 tinsert(unqueueables, {
Zerotorescue@132 248 ["rowData"] = s, -- this is not a key usually found in a row item and ignored by the library
Zerotorescue@132 249 ["cols"] = unqueueablesColumns,
Zerotorescue@132 250 });
Zerotorescue@132 251 end
Zerotorescue@132 252
Zerotorescue@132 253 addon:SetQueueFrameData(queueables, unqueueables);
Zerotorescue@132 254 end
Zerotorescue@62 255
Zerotorescue@144 256 local function RefreshQueue()
Zerotorescue@144 257 InventoriumQueuer.scrollTable:Refresh();
Zerotorescue@14 258 end
Zerotorescue@14 259
Zerotorescue@144 260 do -- Crafting region
Zerotorescue@144 261 -- We are keeping these events within the module object to allow for easier testing and overriding
Zerotorescue@144 262 -- To test: LibStub("AceAddon-3.0"):GetAddon("Inventorium"):GetModule("Queue"):FUNCTION_NAME(param1, param2, ...);
Zerotorescue@144 263
Zerotorescue@144 264 -- Start crafting the selected skill (or the first in line)
Zerotorescue@144 265 local currentQueueItem;
Zerotorescue@144 266 function mod:StartCrafting(test)
Zerotorescue@144 267 local frame = InventoriumQueuer; -- both for speed as code-consistency
Zerotorescue@144 268
Zerotorescue@144 269 local selectedIndex = frame.scrollTable:GetSelection(); -- gets realrow index
Zerotorescue@144 270
Zerotorescue@144 271 addon:Debug("%d was selected.", tostring(selectedIndex));
Zerotorescue@144 272
Zerotorescue@144 273 if not selectedIndex then
Zerotorescue@144 274 -- Select the top most element (scrolltable with index of 1 will contain a index of the related realrow of the data table)
Zerotorescue@144 275 selectedIndex = ((frame.scrollTable.sorttable and frame.scrollTable.sorttable[1]) or 1);
Zerotorescue@144 276
Zerotorescue@144 277 addon:Debug("%d should be the top record.", tostring(selectedIndex));
Zerotorescue@144 278 end
Zerotorescue@144 279
Zerotorescue@144 280 local nextQueue = frame.scrollTable.data[selectedIndex] or frame.scrollTable.data[1]; -- if the selected index still fails, try to get the first record
Zerotorescue@144 281
Zerotorescue@144 282 if nextQueue then
Zerotorescue@144 283 if not test then
Zerotorescue@144 284 -- Initiate spell (test will be used while debugging to fake crafts)
Zerotorescue@144 285 DoTradeSkill(nextQueue.craft.no, ceil(nextQueue.amount / nextQueue.craft.quantity));
Zerotorescue@144 286 end
Zerotorescue@144 287
Zerotorescue@144 288 -- Remember what we're crafting (saves many loops and/or table storing)
Zerotorescue@144 289 currentQueueItem = nextQueue;
Zerotorescue@144 290
Zerotorescue@144 291 return;
Zerotorescue@144 292 else
Zerotorescue@144 293 addon:Print("Nothing is available in the craft queue.", addon.Colors.Red);
Zerotorescue@144 294 end
Zerotorescue@144 295 end
Zerotorescue@144 296
Zerotorescue@144 297 function mod:SpellCastComplete(_, unit, _, _, _, spellId)
Zerotorescue@144 298 -- Sadly the item isn't put in our inventory yet so we don't know how many were made.
Zerotorescue@144 299 -- Because of that we assume the average amount was made, this isn't really the best solution, but it's pretty-est - for now.
Zerotorescue@144 300
Zerotorescue@144 301 if unit == "player" and currentQueueItem and spellId == currentQueueItem.craft.spellId then
Zerotorescue@144 302 -- Make sure the old amount is accurate, this won't be updated by the spell we just finished, that item hasn't been received yet
Zerotorescue@144 303 currentQueueItem.amount = mod:GetRestockAmount(currentQueueItem.itemId, currentQueueItem.groupName);
Zerotorescue@144 304
Zerotorescue@144 305 -- Decrease amount remaining by one quantity
Zerotorescue@144 306 currentQueueItem.amount = ( currentQueueItem.amount - currentQueueItem.craft.quantity );
Zerotorescue@144 307
Zerotorescue@144 308 if currentQueueItem.amount < 1 then
Zerotorescue@144 309 -- We finished crafting this item
Zerotorescue@144 310
Zerotorescue@144 311 -- Remove this element from the queue
Zerotorescue@144 312 for index, q in pairs(queue) do
Zerotorescue@144 313 if q == currentQueueItem then
Zerotorescue@144 314 table.remove(queue, index);
Zerotorescue@144 315 break;
Zerotorescue@144 316 end
Zerotorescue@144 317 end
Zerotorescue@144 318
Zerotorescue@144 319 -- Add this queue item to the "Unqueueables" frame - we finished it so it is no longer queueable and the user may become interested
Zerotorescue@144 320 self:Skip(currentQueueItem.itemId, skipReasons.FINISHED);
Zerotorescue@144 321
Zerotorescue@144 322 -- We are no longer crafting anything
Zerotorescue@144 323 currentQueueItem = nil;
Zerotorescue@144 324
Zerotorescue@144 325 -- Rebuild our scrolltable (records were removed and added)
Zerotorescue@144 326 mod:BuildQueue();
Zerotorescue@144 327 else
Zerotorescue@144 328 -- Refresh the scrolltable (update item counts)
Zerotorescue@144 329 RefreshQueue();
Zerotorescue@144 330 end
Zerotorescue@144 331 end
Zerotorescue@144 332 end
Zerotorescue@144 333
Zerotorescue@144 334 function mod:SpellCastStart(_, unit, _, _, _, spellId)
Zerotorescue@144 335 if unit == "player" and currentQueueItem and spellId == currentQueueItem.craft.spellId then
Zerotorescue@144 336 self.isProcessing = true;
Zerotorescue@144 337 end
Zerotorescue@144 338 end
Zerotorescue@144 339
Zerotorescue@144 340 function mod:SpellCastStop(_, unit, _, _, _, spellId)
Zerotorescue@144 341 if unit == "player" and currentQueueItem and spellId == currentQueueItem.craft.spellId then
Zerotorescue@144 342 self.isProcessing = nil;
Zerotorescue@144 343 end
Zerotorescue@144 344 end
Zerotorescue@144 345
Zerotorescue@144 346 function mod:SpellCastFailed(_, unit, _, _, _, spellId)
Zerotorescue@144 347 if unit == "player" and currentQueueItem and spellId == currentQueueItem.craft.spellId then
Zerotorescue@144 348 currentQueueItem = nil;
Zerotorescue@144 349 self.isProcessing = nil;
Zerotorescue@144 350 end
Zerotorescue@144 351 end
Zerotorescue@144 352
Zerotorescue@144 353 --@debug@
Zerotorescue@144 354 function TestCraft()
Zerotorescue@144 355 mod:StartCrafting(true);
Zerotorescue@144 356 mod:SpellCastComplete("UNIT_SPELLCAST_SUCCEEDED", "player", "Relentless Earthsiege Diamond", nil, nil, 55400);
Zerotorescue@144 357 end
Zerotorescue@144 358 --@end-debug@
Zerotorescue@14 359 end
Zerotorescue@14 360
Zerotorescue@144 361 function mod:QueueProcess()
Zerotorescue@144 362 -- Prepare a table with all possible tradeskill craftables
Zerotorescue@144 363 local craftables = self:GetTradeskillCraftables();
Zerotorescue@144 364
Zerotorescue@144 365 for _, q in pairs(queue) do
Zerotorescue@144 366 if craftables[q.itemId] then
Zerotorescue@144 367 if self:QueueWithAddon(craftables[q.itemId].no, ceil(q.amount / craftables[q.itemId].quantity), q.groupName) == -1 then
Zerotorescue@144 368 addon:Print("Couldn't queue, no supported crafting addon found.", addon.Colors.Red);
Zerotorescue@144 369
Zerotorescue@144 370 self:QueueAbort();
Zerotorescue@144 371 return;
Zerotorescue@144 372 else
Zerotorescue@144 373 -- Update the crafted-item count
Zerotorescue@144 374 for groupName, values in pairs(addon.db.profile.groups) do
Zerotorescue@144 375 if values.items and values.items[q.itemId] then
Zerotorescue@144 376 values.items[q.itemId] = (tonumber(values.items[q.itemId]) or 0) + 1;
Zerotorescue@144 377 break;
Zerotorescue@144 378 end
Zerotorescue@144 379 end
Zerotorescue@144 380 end
Zerotorescue@144 381 else
Zerotorescue@144 382 addon:Debug("Lost %s", IdToItemLink(q.itemId));
Zerotorescue@144 383 end
Zerotorescue@144 384 end
Zerotorescue@144 385
Zerotorescue@144 386 self:QueueHide();
Zerotorescue@144 387 end
Zerotorescue@144 388
Zerotorescue@144 389 function mod:QueueAbort()
Zerotorescue@144 390 self:QueueHide();
Zerotorescue@144 391 end
Zerotorescue@144 392
Zerotorescue@144 393 function mod:QueueHide()
Zerotorescue@144 394 twipe(queue);
Zerotorescue@144 395 twipe(skipped);
Zerotorescue@144 396
Zerotorescue@144 397 if InventoriumQueuer then
Zerotorescue@144 398 InventoriumQueuer:Hide();
Zerotorescue@144 399 end
Zerotorescue@13 400 end
Zerotorescue@13 401
Zerotorescue@13 402 function mod:QueueAll()
Zerotorescue@132 403 -- Prepare a table with all possible tradeskill craftables
Zerotorescue@132 404 local craftables = self:GetTradeskillCraftables();
Zerotorescue@132 405
Zerotorescue@132 406 -- Forget old queue
Zerotorescue@132 407 twipe(queue);
Zerotorescue@132 408 twipe(skipped);
Zerotorescue@132 409
Zerotorescue@14 410 local playerName = UnitName("player");
Zerotorescue@14 411
Zerotorescue@14 412 -- Go through all groups
Zerotorescue@61 413 for groupName, values in pairs(addon.db.profile.groups) do
Zerotorescue@62 414 local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters");
Zerotorescue@14 415
Zerotorescue@14 416 if trackAt[playerName] then
Zerotorescue@132 417 self:QueueGroup(groupName, craftables);
Zerotorescue@13 418 end
Zerotorescue@13 419 end
Zerotorescue@132 420
Zerotorescue@144 421 mod:BuildQueue();
Zerotorescue@13 422 end
Zerotorescue@13 423
Zerotorescue@132 424 function mod:QueueGroup(groupName, craftables)
Zerotorescue@132 425 -- Prepare a table with all possible tradeskill craftables
Zerotorescue@132 426 if not craftables then
Zerotorescue@132 427 craftables = self:GetTradeskillCraftables(); -- nil when no tradeskill window is open
Zerotorescue@132 428 end
Zerotorescue@132 429
Zerotorescue@132 430 if not craftables then
Zerotorescue@132 431 addon:Print("No tradeskill window detected.", addon.Colors.Red);
Zerotorescue@132 432 return;
Zerotorescue@132 433 elseif not addon.db.profile.groups[groupName] then
Zerotorescue@132 434 addon:Print(sformat("Tried to queue items from a group named \"%s\", but no such group exists.", groupName), addon.Colors.Red);
Zerotorescue@132 435 return;
Zerotorescue@132 436 elseif not addon.db.profile.groups[groupName].items then
Zerotorescue@132 437 addon:Debug("This group (%s) has no items.", groupName);
Zerotorescue@14 438 return;
Zerotorescue@14 439 end
Zerotorescue@14 440
Zerotorescue@132 441 -- Retrieve group settings
Zerotorescue@143 442 local minCraftingQueue = floor( addon:GetOptionByKey(groupName, "minCraftingQueue") * addon:GetOptionByKey(groupName, "restockTarget") ); -- If the minCraftingQueue is 5% and restockTarget is 60, this will result in 3
Zerotorescue@132 443 local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold");
Zerotorescue@13 444
Zerotorescue@140 445 for itemId, count in pairs(addon.db.profile.groups[groupName].items) do
Zerotorescue@132 446 if craftables[itemId] then
Zerotorescue@143 447 local amount, bonus = self:GetRestockAmount(itemId, groupName);
Zerotorescue@31 448
Zerotorescue@143 449 if amount and amount >= minCraftingQueue then
Zerotorescue@143 450 -- If we are queuing at least one AND more than the minimum amount, then proceed
Zerotorescue@31 451
Zerotorescue@143 452 -- Auction value settings
Zerotorescue@144 453 local value = (priceThreshold ~= 0 and addon:GetAuctionValue(IdToItemLink(itemId), groupName));
Zerotorescue@17 454
Zerotorescue@143 455 if priceThreshold == 0 or value == -1 or value >= priceThreshold then
Zerotorescue@143 456 -- If no price threshold is set or the auction value is equal to or larger than the price threshold, then proceed
Zerotorescue@31 457
Zerotorescue@143 458 self:Queue(itemId, amount, bonus, craftables[itemId], groupName);
Zerotorescue@132 459 else
Zerotorescue@143 460 self:Skip(itemId, skipReasons.LOW_VALUE);
Zerotorescue@144 461 --addon:Debug("%s is valued at %s while %s is needed", IdToItemLink(itemId), tostring(value), tostring(priceThreshold));
Zerotorescue@14 462 end
Zerotorescue@14 463 else
Zerotorescue@143 464 if not amount then
Zerotorescue@143 465 -- nil = no item count addon
Zerotorescue@143 466 self:Skip(itemId, skipReasons.NO_ITEMCOUNT_ADDON);
Zerotorescue@143 467 addon:Print("No usable itemcount addon found.");
Zerotorescue@143 468 return;
Zerotorescue@143 469 elseif amount <= 0 then
Zerotorescue@143 470 -- less than 0 = (over)capped
Zerotorescue@143 471 self:Skip(itemId, skipReasons.CAPPED);
Zerotorescue@143 472 else
Zerotorescue@143 473 -- more than 0 = below min crafting queue
Zerotorescue@143 474 self:Skip(itemId, skipReasons.MIN_CRAFTING_QUEUE);
Zerotorescue@143 475 end
Zerotorescue@13 476 end
Zerotorescue@132 477 else
Zerotorescue@132 478 self:Skip(itemId, skipReasons.NOT_CRAFTABLE);
Zerotorescue@13 479 end
Zerotorescue@13 480 end
Zerotorescue@13 481 end
Zerotorescue@13 482
Zerotorescue@143 483 function mod:GetRestockAmount(itemId, groupName)
Zerotorescue@143 484 local currentStock = addon:GetItemCount(itemId, groupName);
Zerotorescue@143 485
Zerotorescue@143 486 if currentStock >= 0 then
Zerotorescue@143 487 -- Current stock will be -1 when no itemcount addon was found
Zerotorescue@143 488
Zerotorescue@143 489 local restockTarget = addon:GetOptionByKey(groupName, "restockTarget");
Zerotorescue@143 490 local bonusQueue = addon:GetOptionByKey(groupName, "bonusQueue");
Zerotorescue@143 491
Zerotorescue@143 492 -- Calculate the amount to be queued
Zerotorescue@143 493 local amount = ( restockTarget - currentStock );
Zerotorescue@143 494 local bonus = 0;
Zerotorescue@143 495
Zerotorescue@143 496 if currentStock == 0 and bonusQueue > 0 then
Zerotorescue@143 497 -- If we have none left and the bonus queue is enabled, modify the amount to be queued
Zerotorescue@143 498
Zerotorescue@143 499 bonus = floor( ( amount * ( bonusQueue ) ) + .5 ); -- round
Zerotorescue@143 500
Zerotorescue@143 501 -- Update amount
Zerotorescue@143 502 amount = (amount + bonus);
Zerotorescue@143 503 end
Zerotorescue@143 504
Zerotorescue@143 505 return amount, bonus;
Zerotorescue@143 506 else
Zerotorescue@143 507 return;
Zerotorescue@143 508 end
Zerotorescue@143 509 end
Zerotorescue@143 510
Zerotorescue@143 511 function mod:Queue(itemId, amount, bonus, craft, groupName)
Zerotorescue@132 512 tinsert(queue, {
Zerotorescue@143 513 ["itemId"] = itemId, -- needed to display the queued item in the queue window
Zerotorescue@143 514 ["amount"] = amount, -- the amount missing
Zerotorescue@143 515 ["bonus"] = bonus, -- the amount queued by the bonus queue
Zerotorescue@143 516 ["craft"] = craft, -- (craftable) - needed to find the proper element of this parent array when crafting has finished (spellId), and to update the numCrafts (quantity)
Zerotorescue@143 517 ["groupName"] = groupName, -- related group, needed to find the selected crafting addon
Zerotorescue@132 518 });
Zerotorescue@132 519 end
Zerotorescue@132 520
Zerotorescue@132 521 function mod:Skip(itemId, reason)
Zerotorescue@132 522 tinsert(skipped, {
Zerotorescue@132 523 ["itemId"] = itemId,
Zerotorescue@132 524 ["reason"] = reason,
Zerotorescue@132 525 });
Zerotorescue@132 526 end
Zerotorescue@132 527
Zerotorescue@132 528 function mod:QueueWithAddon(tradeSkillIndex, amount, group)
Zerotorescue@132 529 -- Sanity check
Zerotorescue@13 530 tradeSkillIndex = tonumber(tradeSkillIndex);
Zerotorescue@13 531 amount = tonumber(amount);
Zerotorescue@13 532
Zerotorescue@23 533 local selectedExternalAddon = addon:GetOptionByKey(group, "craftingAddon");
Zerotorescue@23 534
Zerotorescue@23 535 if addon.supportedAddons.crafting[selectedExternalAddon] and addon.supportedAddons.crafting[selectedExternalAddon].IsEnabled() then
Zerotorescue@13 536 -- Try to use the default auction pricing addon
Zerotorescue@13 537
Zerotorescue@23 538 return addon.supportedAddons.crafting[selectedExternalAddon].Queue(tradeSkillIndex, amount);
Zerotorescue@13 539 else
Zerotorescue@13 540 -- Default not available, get the first one then
Zerotorescue@13 541
Zerotorescue@13 542 for name, value in pairs(addon.supportedAddons.crafting) do
Zerotorescue@13 543 if value.IsEnabled() then
Zerotorescue@13 544 return value.Queue(tradeSkillIndex, amount);
Zerotorescue@13 545 end
Zerotorescue@13 546 end
Zerotorescue@13 547 end
Zerotorescue@13 548
Zerotorescue@132 549 return -1;
Zerotorescue@13 550 end
Zerotorescue@132 551
Zerotorescue@144 552 function mod:OnEnable()
Zerotorescue@144 553 -- Register our own slash commands
Zerotorescue@144 554 -- /im queue
Zerotorescue@144 555 addon:RegisterSlash(function()
Zerotorescue@144 556 mod:QueueAll();
Zerotorescue@144 557 end, { "q", "que", "queue" }, "|Hfunction:InventoriumCommandHandler:queue|h|cff00fff7/im queue|r|h (or /im q) - Queue all items found in the currently opened profession that are within the groups tracked at this current character.");
Zerotorescue@144 558
Zerotorescue@144 559 self:RegisterMessage("IM_QUEUE_ALL");
Zerotorescue@144 560 self:RegisterMessage("IM_QUEUE_GROUP");
Zerotorescue@144 561
Zerotorescue@144 562 -- When closing the tradeskill window also hide the queue screen.
Zerotorescue@144 563 -- We scan the recipes right before queueing not when the tradeskill is opened because we really don't need it at any other time.
Zerotorescue@144 564 self:RegisterEvent("TRADE_SKILL_CLOSE", "QueueAbort");
Zerotorescue@144 565
Zerotorescue@144 566 -- Crafting events
Zerotorescue@144 567 self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED", "SpellCastComplete");
Zerotorescue@144 568
Zerotorescue@144 569 -- Button en-/disabling
Zerotorescue@144 570 self:RegisterEvent("UNIT_SPELLCAST_START", "SpellCastStart");
Zerotorescue@144 571 self:RegisterEvent("UNIT_SPELLCAST_STOP", "SpellCastStop");
Zerotorescue@144 572
Zerotorescue@144 573 self:RegisterEvent("UNIT_SPELLCAST_FAILED", "SpellCastFailed");
Zerotorescue@144 574 self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", "SpellCastFailed");
Zerotorescue@144 575 end
Zerotorescue@132 576
Zerotorescue@144 577 do -- Addon messages (Ace3) region
Zerotorescue@144 578 function mod:IM_QUEUE_ALL()
Zerotorescue@144 579 self:QueueAll();
Zerotorescue@144 580 end
Zerotorescue@144 581
Zerotorescue@144 582 function mod:IM_QUEUE_GROUP(event, groupName)
Zerotorescue@144 583 self:QueueGroup(groupName);
Zerotorescue@132 584 end
Zerotorescue@132 585 end
Zerotorescue@132 586
Zerotorescue@144 587 do -- Trade skill recipes region
Zerotorescue@144 588 -- Expand all categories so no crafts are hidden
Zerotorescue@144 589 local function ExpandSubClasses()
Zerotorescue@144 590 for i = GetNumTradeSkills(), 1, -1 do
Zerotorescue@144 591 local _, skillType, _, isExpanded = GetTradeSkillInfo(i);
Zerotorescue@144 592
Zerotorescue@144 593 if skillType == "header" and not isExpanded then
Zerotorescue@144 594 ExpandTradeSkillSubClass(i);
Zerotorescue@132 595 end
Zerotorescue@132 596 end
Zerotorescue@132 597 end
Zerotorescue@144 598
Zerotorescue@144 599 -- Reset all filters so no crafts are hidden
Zerotorescue@144 600 local function ResetFilters()
Zerotorescue@144 601 SetTradeSkillSubClassFilter(0, 1, 1);
Zerotorescue@144 602 SetTradeSkillItemNameFilter("");
Zerotorescue@144 603 SetTradeSkillItemLevelFilter(0, 0);
Zerotorescue@144 604 TradeSkillOnlyShowSkillUps(false);
Zerotorescue@144 605 TradeSkillOnlyShowMakeable(false);
Zerotorescue@144 606 end
Zerotorescue@144 607
Zerotorescue@144 608 -- Get all craftable items into a table. Each record contains "no", "spellId" and "quantity". The last is the average amount made per craft.
Zerotorescue@144 609 function mod:GetTradeskillCraftables()
Zerotorescue@144 610 local craftables = {};
Zerotorescue@144 611
Zerotorescue@144 612 if GetTradeSkillLine() ~= "UNKNOWN" then
Zerotorescue@144 613 ExpandSubClasses();
Zerotorescue@144 614 ResetFilters();
Zerotorescue@144 615
Zerotorescue@144 616 -- Cache all craftable items
Zerotorescue@144 617 for i = 1, GetNumTradeSkills() do
Zerotorescue@144 618 local itemLink = GetTradeSkillItemLink(i);
Zerotorescue@144 619
Zerotorescue@144 620 if itemLink then
Zerotorescue@144 621 local itemId = addon:GetItemId(itemLink);
Zerotorescue@144 622 if not itemId then
Zerotorescue@144 623 -- If this isn't an item, it can only be an enchant instead
Zerotorescue@144 624 itemId = tonumber(smatch(itemLink, "|Henchant:([-0-9]+)|h"));
Zerotorescue@144 625
Zerotorescue@144 626 if itemId and addon.scrollIds[itemId] then
Zerotorescue@144 627 -- Only if this scroll id actually exists
Zerotorescue@144 628 itemId = addon.scrollIds[itemId]; -- change enchantIds into scrollIds
Zerotorescue@144 629 end
Zerotorescue@144 630 end
Zerotorescue@144 631
Zerotorescue@144 632 -- Remember the average amount of items created per craft (doesn't need to be a round number, since we multiply this by the amount of items to be queued we're better off rounding at that time)
Zerotorescue@144 633 local minMade, maxMade = GetTradeSkillNumMade(i);
Zerotorescue@144 634 local average = ((minMade == maxMade) and minMade) or ((minMade + maxMade) / 2);
Zerotorescue@144 635
Zerotorescue@144 636 local recipeLink = GetTradeSkillRecipeLink(i);
Zerotorescue@144 637 local spellId = tonumber(smatch(recipeLink, "|Henchant:([-0-9]+)|h"));
Zerotorescue@144 638
Zerotorescue@144 639 craftables[itemId] = {
Zerotorescue@144 640 ["no"] = i, -- needed to start crafting at the end of the entire cycle
Zerotorescue@144 641 ["spellId"] = spellId, -- needed to detect creation of this item was finished
Zerotorescue@144 642 ["quantity"] = average, -- needed to calculate the amount of crafts
Zerotorescue@144 643 };
Zerotorescue@144 644 end
Zerotorescue@144 645 end
Zerotorescue@144 646 else
Zerotorescue@144 647 return;
Zerotorescue@144 648 end
Zerotorescue@144 649
Zerotorescue@144 650 return craftables;
Zerotorescue@144 651 end
Zerotorescue@132 652 end