Mercurial > wow > inventory
view Modules/Queue.lua @ 132:8460855e3d90
Rewrote queueing module to insert a GUI.
Minor mover window changes.
author | Zerotorescue |
---|---|
date | Tue, 18 Jan 2011 00:30:15 +0100 |
parents | 67bd5057ecb7 |
children | 396c2960d54d |
line wrap: on
line source
local addon = select(2, ...); local mod = addon:NewModule("Queue", "AceEvent-3.0", "AceTimer-3.0"); local _G = _G; local tonumber, pairs, sformat, smatch, floor, ceil, tinsert, twipe = _G.tonumber, _G.pairs, _G.string.format, _G.string.match, _G.floor, _G.ceil, _G.table.insert, _G.table.wipe; local queue, skipped = {}, {}; -- 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 local skipReasons = { ["LOW_VALUE"] = { "|cffff6633Underpriced|r", "The recorded auction value of this item is below your price threshold." }, ["CAPPED"] = { "|cff66ff33Fully stocked|r", "The recorded item count is above or equal to your minimum global stock setting." }, ["MIN_CRAFTING_QUEUE"] = { "|cffffff00Min crafting queue|r", "The amount of missing items is below or equal to your \"don't queue if I only miss\"-setting." }, ["NO_ITEMCOUNT_ADDON"] = { "|cffff0000No itemcount addon|r", "No compatible item count could be found." }, ["NOT_CRAFTABLE"] = { "|cff3d3d3dNot in profession|r", "This item is not part of this profession." }, }; local function OnQueueCancel() twipe(queue); twipe(skipped); InventoriumQueuer:Hide(); end local function OnQueueAccept() -- Prepare a table with all possible tradeskill craftables local craftables = mod:GetTradeskillCraftables(); for _, q in pairs(queue) do if craftables[q.itemId] then if mod:QueueWithAddon(craftables[q.itemId].no, ceil(q.amount / craftables[q.itemId].quantity), q.groupName) == -1 then addon:Print("Couldn't queue, no supported crafting addon found.", addon.Colors.Red); OnQueueCancel(); return; end else addon:Debug("Lost %s", IdToItemLink(q.itemId)); end end twipe(queue); twipe(skipped); InventoriumQueuer:Hide(); end local function MakeQueueWindow() do local frame = InventoriumQueuer; -- both for speed as code-consistency -- Scrolling table with a list of items to be moved local scrollTableWidth = ( frame.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size local headers = { { ["name"] = "Item", ["width"] = (scrollTableWidth * .60), ["defaultsort"] = "asc", ["comparesort"] = function(this, aRow, bRow, column) local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId); local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId); local template = "%d%s"; aName = template:format((10 - (aRarity or 10)), (aName or ""):lower()); bName = template:format((10 - (bRarity or 10)), (bName or ""):lower()); if this.cols[column].sort == "dsc" then return aName > bName; else return aName < bName; end end, ["sort"] = "asc", -- when the data is set, use this column so sort the default data ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Item"), ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by item quality then item name."), }, { ["name"] = "Amount", ["width"] = (scrollTableWidth * .20), ["align"] = "RIGHT", ["defaultsort"] = "dsc", ["sortnext"] = 1, ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Amount"), ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by the amount of items to be queued."), }, { ["name"] = "Extra", ["width"] = (scrollTableWidth * .20), ["align"] = "RIGHT", ["defaultsort"] = "dsc", ["sortnext"] = 1, ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Extra"), ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by the amount of bonus items."), }, }; local scrollTableWidth = ( InventoriumQueuerUnqueueables.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size local unqueueablesHeaders = { { ["name"] = "Item", ["width"] = (scrollTableWidth * .6), ["defaultsort"] = "asc", ["comparesort"] = function(this, aRow, bRow, column) local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId); local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId); local template = "%d%s"; aName = template:format((10 - (aRarity or 10)), (aName or ""):lower()); bName = template:format((10 - (bRarity or 10)), (bName or ""):lower()); if this.cols[column].sort == "dsc" then return aName > bName; else return aName < bName; end end, ["sort"] = "asc", -- when the data is set, use this column so sort the default data ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Item"), ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by item quality then item name."), }, { ["name"] = "Reason", ["width"] = (scrollTableWidth * .4), ["defaultsort"] = "dsc", ["sortnext"] = 1, ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Reason"), ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by the reason the items couldn't be queued."), }, }; local proceedButton = { text = "Queue", tooltipTitle = (not addon.db.profile.defaults.hideHelp and "Queue"), tooltip = (not addon.db.profile.defaults.hideHelp and "Add these items to the queue of your crafting addon."), onClick = OnQueueAccept, }; local cancelButton = { text = "Cancel", tooltipTitle = (not addon.db.profile.defaults.hideHelp and "Cancel"), tooltip = (not addon.db.profile.defaults.hideHelp and "Do not queue anything and close the window."), onClick = OnQueueCancel, }; 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); end end local function DisplayQueue() MakeQueueWindow(); -- This table is never copied, just referenced. It is the same for every row. local queueablesColumns = { { ["value"] = function(data, cols, realrow, column, table) return IdToItemLink(data[realrow].rowData.itemId); end, }, -- item { ["value"] = function(data, cols, realrow, column, table) return data[realrow].rowData.amount; end, }, -- amount { ["value"] = function(data, cols, realrow, column, table) return (data[realrow].rowData.bonus == 0 and 0) or "+" .. data[realrow].rowData.bonus; end, ["color"] = function(data, cols, realrow, column, table) 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 }; end, }, -- extra }; -- Store the list with rows in this local queueables = {}; for _, q in pairs(queue) do tinsert(queueables, { ["rowData"] = q, -- this is not a key usually found in a row item and ignored by the library ["cols"] = queueablesColumns, }); end -- This table is never copied, just referenced. It is the same for every row. local unqueueablesColumns = { { ["value"] = function(data, cols, realrow, column, table) return IdToItemLink(data[realrow].rowData.itemId); end, }, -- item { ["value"] = function(data, cols, realrow, column, table) return data[realrow].rowData.reason[1]; end, }, -- reason }; -- Store the list with rows in this local unqueueables = {}; for _, s in pairs(skipped) do tinsert(unqueueables, { ["rowData"] = s, -- this is not a key usually found in a row item and ignored by the library ["cols"] = unqueueablesColumns, }); end addon:SetQueueFrameData(queueables, unqueueables); end function mod:OnEnable() -- Register our own slash commands -- /im queue addon:RegisterSlash(function() mod:QueueAll(); 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."); self:RegisterMessage("IM_QUEUE_ALL"); self:RegisterMessage("IM_QUEUE_GROUP"); if not InventoriumQueuer then addon:CreateQueueFrame(OnMoveAccept, OnMoveCancel); end end function mod:IM_QUEUE_ALL() self:QueueAll(); end function mod:IM_QUEUE_GROUP(event, groupName) self:QueueGroup(groupName); end function mod:QueueAll() -- Prepare a table with all possible tradeskill craftables local craftables = self:GetTradeskillCraftables(); -- Forget old queue twipe(queue); twipe(skipped); local playerName = UnitName("player"); -- Go through all groups for groupName, values in pairs(addon.db.profile.groups) do local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters"); if trackAt[playerName] then self:QueueGroup(groupName, craftables); end end DisplayQueue(); end function mod:QueueGroup(groupName, craftables) -- Prepare a table with all possible tradeskill craftables if not craftables then craftables = self:GetTradeskillCraftables(); -- nil when no tradeskill window is open end if not craftables then addon:Print("No tradeskill window detected.", addon.Colors.Red); return; elseif not addon.db.profile.groups[groupName] then addon:Print(sformat("Tried to queue items from a group named \"%s\", but no such group exists.", groupName), addon.Colors.Red); return; elseif not addon.db.profile.groups[groupName].items then addon:Debug("This group (%s) has no items.", groupName); return; end -- Retrieve group settings local restockTarget = addon:GetOptionByKey(groupName, "restockTarget"); local bonusQueue = addon:GetOptionByKey(groupName, "bonusQueue"); local minCraftingQueue = floor( addon:GetOptionByKey(groupName, "minCraftingQueue") * restockTarget ); -- If the minCraftingQueue is 5% and restockTarget is 60, this will result in 3 local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold"); for itemId in pairs(addon.db.profile.groups[groupName].items) do if craftables[itemId] then local currentStock = addon:GetItemCount(itemId, groupName); if currentStock >= 0 then -- Current stock will be -1 when no itemcount addon was found -- Calculate the amount to be queued local amount = ( restockTarget - currentStock ); local bonus = 0; if currentStock == 0 and bonusQueue > 0 then -- If we have none left and the bonus queue is enabled, modify the amount to be queued bonus = floor( ( amount * ( bonusQueue ) ) + .5 ); -- round -- Update amount amount = (amount + bonus); end if amount > 0 and amount >= minCraftingQueue then -- If we are queueing at least one AND more than the minimum amount, then proceed -- Auction value settings local value = (priceThreshold ~= 0 and addon:GetAuctionValue(itemLink, groupName)); if priceThreshold == 0 or value == -1 or value >= priceThreshold then -- If no price threshold is set or the auction value is equal to or larger than the price threshold, then proceed self:Queue(itemId, amount, bonus, groupName); else self:Skip(itemId, skipReasons.LOW_VALUE); end else if amount <= 0 then self:Skip(itemId, skipReasons.CAPPED); else self:Skip(itemId, skipReasons.MIN_CRAFTING_QUEUE); end end else self:Skip(itemId, skipReasons.NO_ITEMCOUNT_ADDON); addon:Print("No usable itemcount addon found."); return; end else self:Skip(itemId, skipReasons.NOT_CRAFTABLE); end end end function mod:Queue(itemId, amount, bonus, groupName) tinsert(queue, { ["itemId"] = itemId, ["amount"] = amount, ["bonus"] = bonus, ["groupName"] = groupName, }); end function mod:Skip(itemId, reason) tinsert(skipped, { ["itemId"] = itemId, ["reason"] = reason, }); end function mod:QueueWithAddon(tradeSkillIndex, amount, group) -- Sanity check tradeSkillIndex = tonumber(tradeSkillIndex); amount = tonumber(amount); local selectedExternalAddon = addon:GetOptionByKey(group, "craftingAddon"); if addon.supportedAddons.crafting[selectedExternalAddon] and addon.supportedAddons.crafting[selectedExternalAddon].IsEnabled() then -- Try to use the default auction pricing addon return addon.supportedAddons.crafting[selectedExternalAddon].Queue(tradeSkillIndex, amount); else -- Default not available, get the first one then for name, value in pairs(addon.supportedAddons.crafting) do if value.IsEnabled() then return value.Queue(tradeSkillIndex, amount); end end end return -1; end -- Expand all categories local function ExpandSubClasses() for i = GetNumTradeSkills(), 1, -1 do local _, skillType, _, isExpanded = GetTradeSkillInfo(i); if skillType == "header" and not isExpanded then ExpandTradeSkillSubClass(i); end end end function mod:GetTradeskillCraftables() local craftables = {}; if GetTradeSkillLine() ~= "UNKNOWN" then ExpandSubClasses(); -- Cache all craftable items for i = 1, GetNumTradeSkills() do local itemLink = GetTradeSkillItemLink(i); if itemLink then local itemId = addon:GetItemId(itemLink); if not itemId then -- If this isn't an item, it can only be an enchant instead itemId = tonumber(smatch(itemLink, "|Henchant:([-0-9]+)|h")); itemId = addon.scrollIds[itemId]; -- change enchantIds into scrollIds end -- 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) local minMade, maxMade = GetTradeSkillNumMade(i); local average = ((minMade == maxMade) and minMade) or ((minMade + maxMade) / 2); craftables[itemId] = { ["no"] = i, ["quantity"] = average, }; end end else return; end return craftables; end