annotate Modules/Queue.lua @ 225:2e4e52a589e5

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