You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
9.4 KiB
257 lines
9.4 KiB
-- ------------------------------------------------------------------------------ -- |
|
-- TradeSkillMaster_Crafting -- |
|
-- http://www.curse.com/addons/wow/tradeskillmaster_crafting -- |
|
-- -- |
|
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) -- |
|
-- All Rights Reserved* - Detailed license information included with addon. -- |
|
-- ------------------------------------------------------------------------------ -- |
|
|
|
-- load the parent file (TSM) into a local variable and register this file as a module |
|
local TSM = select(2, ...) |
|
local Queue = TSM:NewModule("Queue") |
|
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Crafting") -- loads the localization table |
|
|
|
local MAX_QUEUE_STAGES = 10 |
|
local inventoryTotals = {} |
|
|
|
|
|
local notified = {} |
|
function Queue:ValidateOperation(operation, opName) |
|
if not operation then return end |
|
|
|
if operation.minRestock > operation.maxRestock then |
|
-- invalid cause min > max restock quantity (shouldn't happen) |
|
if not notified[opName] then |
|
notified[opName] = true |
|
TSM:Printf(L["'%s' is an invalid operation! Min restock of %d is higher than max restock of %d."], opName, operation.minRestock, operation.maxRestock) |
|
end |
|
return |
|
end |
|
return true |
|
end |
|
|
|
function Queue:CreateRestockQueue(groupInfo) |
|
TSM:UpdateCraftReverseLookup() |
|
local numItems = 0 |
|
|
|
for _, data in pairs(groupInfo) do |
|
for _, opName in ipairs(data.operations) do |
|
TSMAPI:UpdateOperation("Crafting", opName) |
|
local opSettings = TSM.operations[opName] |
|
if Queue:ValidateOperation(opSettings, opName) then |
|
-- it's a valid operation |
|
for itemString in pairs(data.items) do |
|
itemString = TSMAPI:GetItemString(itemString) |
|
local spellID = TSM.craftReverseLookup[itemString] and TSM.craftReverseLookup[itemString][1] |
|
if spellID and TSM.db.realm.crafts[spellID] then |
|
local maxQueueCount = max(opSettings.maxRestock - TSM.Inventory:GetTotalQuantity(itemString), 0) |
|
local numToQueue = 0 |
|
|
|
if not opSettings.minProfit then |
|
-- no minimum, so queue as many as we can |
|
numToQueue = maxQueueCount |
|
else |
|
-- queue it if the profit is at least the min profit |
|
local cheapestSpellID, cost, _, profit = TSM.Cost:GetLowestCraftPrices(itemString) |
|
local minProfit = TSM:GetCustomPrice(opSettings.minProfit, itemString) |
|
if minProfit and profit and profit >= minProfit then |
|
spellID = cheapestSpellID |
|
numToQueue = maxQueueCount |
|
end |
|
end |
|
|
|
local craft = TSM.db.realm.crafts[spellID] |
|
craft.queued = floor(numToQueue / craft.numResult) |
|
craft.queued = craft.queued >= opSettings.minRestock and craft.queued or 0 |
|
if craft.queued > 0 then |
|
numItems = numItems + 1 |
|
end |
|
end |
|
end |
|
end |
|
end |
|
end |
|
|
|
if numItems==0 then |
|
TSM:Printf("There are no items to restock.") |
|
end |
|
TSMAPI:FireEvent("CRAFTING:QUEUE:RESTOCKED", numItems) |
|
end |
|
|
|
function Queue:HasLoop(itemString, steps, visited) |
|
steps = steps + 1 |
|
if steps > 10 then return true end |
|
if visited[itemString] then return true end |
|
visited[itemString] = true |
|
local craftCost = TSM:GetCustomPrice("Crafting", itemString) |
|
local mat = TSM.db.realm.mats[itemString] |
|
local lowestCost = TSM:GetCustomPrice(mat.customValue or TSM.db.global.defaultMatCostMethod, itemString) |
|
if craftCost and lowestCost and craftCost <= lowestCost and (not TSM.db.global.neverCraftInks or not TSMAPI.InkConversions[itemString]) then |
|
local spellID = TSM.Cost:GetLowestCraftPrices(itemString, true) |
|
if spellID and TSM.db.realm.crafts[spellID] then |
|
for matItemString in pairs(TSM.db.realm.crafts[spellID].mats) do |
|
if Queue:HasLoop(matItemString, steps, CopyTable(visited)) then |
|
return true |
|
end |
|
end |
|
end |
|
end |
|
end |
|
|
|
function Queue:GetIntermediateCrafts(mats, usedItems, usedMats, tempMats) |
|
local subCrafts = {} |
|
for profession, data in pairs(mats) do |
|
tempMats[profession] = tempMats[profession] or {} |
|
for itemString, quantity in pairs(data) do |
|
usedItems[itemString] = usedItems[itemString] or 0 |
|
local numHave = (inventoryTotals[itemString] or 0) - usedItems[itemString] |
|
if TSMAPI.SOULBOUND_MATS[itemString] then |
|
numHave = numHave + GetItemCount(itemString, true) |
|
end |
|
if numHave > 0 then |
|
if numHave >= quantity then |
|
usedItems[itemString] = usedItems[itemString] + quantity |
|
tempMats[profession][itemString] = (tempMats[profession][itemString] or 0) + quantity |
|
quantity = 0 |
|
mats[profession][itemString] = nil |
|
else |
|
usedItems[itemString] = numHave |
|
quantity = quantity - numHave |
|
tempMats[profession][itemString] = (tempMats[profession][itemString] or 0) + numHave |
|
mats[profession][itemString] = mats[profession][itemString] - numHave |
|
end |
|
end |
|
|
|
if quantity > 0 and not Queue:HasLoop(itemString, 0, {}) then |
|
local mat = TSM.db.realm.mats[itemString] |
|
local craftCost = TSM:GetCustomPrice("Crafting", itemString) |
|
local lowestCost = TSM:GetCustomPrice(mat.customValue or TSM.db.global.defaultMatCostMethod, itemString) |
|
if craftCost and lowestCost and craftCost <= lowestCost and (not TSM.db.global.neverCraftInks or not TSMAPI.InkConversions[itemString]) then |
|
local spellID = TSM.Cost:GetLowestCraftPrices(itemString, true) |
|
if spellID and TSM.db.realm.crafts[spellID] then |
|
local numResult = TSM.db.realm.crafts[spellID].numResult |
|
quantity = ceil(quantity / numResult) |
|
subCrafts[TSM.db.realm.crafts[spellID].profession] = subCrafts[TSM.db.realm.crafts[spellID].profession] or {} |
|
subCrafts[TSM.db.realm.crafts[spellID].profession][spellID] = (subCrafts[TSM.db.realm.crafts[spellID].profession][spellID] or 0) + quantity |
|
TSM.db.realm.crafts[spellID].queued = TSM.db.realm.crafts[spellID].queued + quantity |
|
TSM.db.realm.crafts[spellID].intermediateQueued = (TSM.db.realm.crafts[spellID].intermediateQueued or 0) + quantity |
|
mats[profession][itemString] = nil |
|
usedMats[profession] = usedMats[profession] or {} |
|
usedMats[profession][itemString] = numHave |
|
end |
|
end |
|
end |
|
end |
|
end |
|
|
|
local newSubCrafts |
|
for profession, data in pairs(subCrafts) do |
|
for spellID, quantity in pairs(data) do |
|
newSubCrafts = true |
|
for itemString, matQuantity in pairs(TSM.db.realm.crafts[spellID].mats) do |
|
mats[profession] = mats[profession] or {} |
|
mats[profession][itemString] = (mats[profession][itemString] or 0) + matQuantity * quantity |
|
end |
|
end |
|
end |
|
return newSubCrafts and subCrafts |
|
end |
|
|
|
function Queue:GetQueue() |
|
local tempCrafts, queuedCrafts, mats = {}, {}, {} |
|
local totalCost, totalProfit |
|
|
|
-- first queue up all the normally queued stuff |
|
for spellID, data in pairs(TSM.db.realm.crafts) do |
|
if data.intermediateQueued then |
|
data.queued = max(data.queued - data.intermediateQueued, 0) |
|
data.intermediateQueued = nil |
|
end |
|
if data.queued > 0 then |
|
local cost, buyout, profit = TSM.Cost:GetCraftPrices(spellID) |
|
if cost then |
|
totalCost = (totalCost or 0) + cost * data.queued |
|
end |
|
if profit then |
|
totalProfit = (totalProfit or 0) + profit * data.queued |
|
end |
|
tempCrafts[data.profession] = tempCrafts[data.profession] or {} |
|
tempCrafts[data.profession][spellID] = data.queued |
|
for itemString, quantity in pairs(data.mats) do |
|
mats[data.profession] = mats[data.profession] or {} |
|
mats[data.profession][itemString] = (mats[data.profession][itemString] or 0) + quantity * data.queued |
|
end |
|
end |
|
end |
|
for profession, data in pairs(tempCrafts) do |
|
queuedCrafts[profession] = queuedCrafts[profession] or {} |
|
tinsert(queuedCrafts[profession], 1, { crafts = data }) |
|
end |
|
|
|
-- queue intermediate crafts |
|
local usedItems, usedMats, tempMats = {}, {}, {} |
|
inventoryTotals = select(4, TSM.Inventory:GetTotals()) |
|
for i = 1, MAX_QUEUE_STAGES - 1 do |
|
local subCrafts = Queue:GetIntermediateCrafts(mats, usedItems, usedMats, tempMats) |
|
if not subCrafts then break end |
|
|
|
for profession, data in pairs(subCrafts) do |
|
queuedCrafts[profession] = queuedCrafts[profession] or {} |
|
tinsert(queuedCrafts[profession], 1, { crafts = data }) |
|
end |
|
end |
|
|
|
-- readd usedMats back in |
|
for profession, data in pairs(tempMats) do |
|
for itemString, quantity in pairs(data) do |
|
mats[profession][itemString] = (mats[profession][itemString] or 0) + quantity |
|
end |
|
end |
|
|
|
for profession, data in pairs(usedMats) do |
|
if mats[profession] then |
|
for itemString, quantity in pairs(data) do |
|
mats[profession][itemString] = (mats[profession][itemString] or 0) + quantity |
|
end |
|
end |
|
end |
|
|
|
-- give each stage the appropriate name |
|
for profession, stages in pairs(queuedCrafts) do |
|
for i, stageInfo in ipairs(stages) do |
|
stageInfo.name = format(L["Stage %d"], i) |
|
end |
|
end |
|
|
|
totalCost = totalCost or "---" |
|
totalProfit = totalProfit or "---" |
|
return queuedCrafts, mats, totalCost, totalProfit |
|
end |
|
|
|
function Queue:ClearQueue() |
|
for spellID, data in pairs(TSM.db.realm.crafts) do |
|
data.queued = 0 |
|
data.intermediateQueued = nil |
|
end |
|
end |
|
|
|
function Queue:addQueue(spellID, quantity) |
|
local craft = TSM.db.realm.crafts[spellID] |
|
if not craft then return end |
|
quantity = quantity or 1 |
|
craft.queued = craft.queued + quantity |
|
TSM.CraftingGUI:UpdateQueue() |
|
end |
|
|
|
function Queue:removeQueue(spellID, quantity) |
|
local craft = TSM.db.realm.crafts[spellID] |
|
if not craft then return end |
|
quantity = quantity or 1 |
|
craft.queued = max(craft.queued - quantity, 0) |
|
TSM.CraftingGUI:UpdateQueue() |
|
end |
|
|
|
function Queue:getQueue(spellID) |
|
local craft = TSM.db.realm.crafts[spellID] |
|
return craft.queued |
|
end |