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.
438 lines
18 KiB
438 lines
18 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. -- |
|
-- ------------------------------------------------------------------------------ -- |
|
|
|
-- register this file with Ace Libraries |
|
local TSM = select(2, ...) |
|
TSM = LibStub("AceAddon-3.0"):NewAddon(TSM, "TSM_Crafting", "AceEvent-3.0", "AceConsole-3.0") |
|
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Crafting") -- loads the localization table |
|
|
|
|
|
-- default values for the savedDB |
|
local savedDBDefaults = { |
|
global = { |
|
optionsTreeStatus = {}, |
|
tooltip = true, |
|
materialTooltip = true, |
|
ignoreCharacters = {}, |
|
ignoreGuilds = {}, |
|
profitPercent = 0, |
|
defaultMatCostMethod = "min(dbmarket, crafting, vendorbuy, convert(dbmarket))", |
|
defaultCraftPriceMethod = "dbminbuyout", |
|
priceColumn = 1, |
|
ignoreCDCraftCost = true, |
|
neverCraftInks = true, |
|
frameQueueOpen = nil, |
|
showingDefaultFrame = nil, |
|
matsInTooltip = true, |
|
}, |
|
factionrealm = { |
|
tradeSkills = {}, |
|
crafts = {}, |
|
mats = {}, |
|
queueStatus = { collapsed = {} }, |
|
sourceStatus = { collapsed = {} }, |
|
gathering = { crafter = nil, professions = {}, neededMats = {}, availableMats = {}, gatheredMats = false, gatherAll = false, destroyingMats = {}, destroyDisable = false, evenStacks = true }, |
|
craftingCostCache = {} |
|
}, |
|
} |
|
|
|
-- Called once the player has loaded WOW. |
|
function TSM:OnEnable() |
|
-- create shortcuts to TradeSkillMaster_Crafting's modules |
|
for moduleName, module in pairs(TSM.modules) do |
|
TSM[moduleName] = module |
|
end |
|
|
|
-- load the savedDB into TSM.db |
|
TSM.db = LibStub:GetLibrary("AceDB-3.0"):New("AscensionTSM_CraftingDB", savedDBDefaults, true) |
|
TSM:UpdateCraftReverseLookup() |
|
|
|
-- register this module with TSM |
|
TSM:RegisterModule() |
|
|
|
-- fix vellum issue |
|
for spellid, data in pairs(TSM.db.factionrealm.crafts) do |
|
for itemString in pairs(data.mats) do |
|
-- if itemString == "item:38682" then |
|
-- TSM.db.factionrealm.crafts[spellid].mats["item:38682:0:0:0:0:0:0"] = 1 |
|
if itemString == "item:43146" then |
|
TSM.db.factionrealm.crafts[spellid].mats["item:43146:0:0:0:0:0:0"] = 1 |
|
TSM.db.factionrealm.crafts[spellid].mats[itemString] = nil |
|
elseif itemString == "item:43145" then |
|
TSM.db.factionrealm.crafts[spellid].mats["item:43145:0:0:0:0:0:0"] = 1 |
|
TSM.db.factionrealm.crafts[spellid].mats[itemString] = nil |
|
elseif itemString == "item:39350" then |
|
TSM.db.factionrealm.crafts[spellid].mats["item:39350:0:0:0:0:0:0"] = 1 |
|
TSM.db.factionrealm.crafts[spellid].mats[itemString] = nil |
|
elseif itemString == "item:37602" then |
|
TSM.db.factionrealm.crafts[spellid].mats["item:37602:0:0:0:0:0:0"] = 1 |
|
TSM.db.factionrealm.crafts[spellid].mats[itemString] = nil |
|
elseif itemString == "item:39349" then |
|
TSM.db.factionrealm.crafts[spellid].mats["item:39349:0:0:0:0:0:0"] = 1 |
|
TSM.db.factionrealm.crafts[spellid].mats[itemString] = nil |
|
elseif itemString == "item:38682" then |
|
TSM.db.factionrealm.crafts[spellid].mats["item:38682:0:0:0:0:0:0"] = 1 |
|
TSM.db.factionrealm.crafts[spellid].mats[itemString] = nil |
|
end |
|
end |
|
end |
|
-- if TSM.db.factionrealm.mats["item:38682"] then |
|
-- local name = TSMAPI:GetSafeItemInfo("item:38682:0:0:0:0:0:0") or (GetLocale() == "enUS" and "Enchanting Vellum") or nil |
|
-- TSM.db.factionrealm.mats["item:38682:0:0:0:0:0:0"] = {} |
|
-- TSM.db.factionrealm.mats["item:38682:0:0:0:0:0:0"].name = name |
|
-- TSM.db.factionrealm.mats["item:38682"] = nil |
|
-- end |
|
if TSM.db.factionrealm.mats["item:43146"] then |
|
local name = TSMAPI:GetSafeItemInfo("item:43146:0:0:0:0:0:0") or nil |
|
TSM.db.factionrealm.mats["item:43146:0:0:0:0:0:0"] = {} |
|
TSM.db.factionrealm.mats["item:43146:0:0:0:0:0:0"].name = name |
|
TSM.db.factionrealm.mats["item:43146"] = nil |
|
end |
|
if TSM.db.factionrealm.mats["item:43145"] then |
|
local name = TSMAPI:GetSafeItemInfo("item:43145:0:0:0:0:0:0") or nil |
|
TSM.db.factionrealm.mats["item:43145:0:0:0:0:0:0"] = {} |
|
TSM.db.factionrealm.mats["item:43145:0:0:0:0:0:0"].name = name |
|
TSM.db.factionrealm.mats["item:43145"] = nil |
|
end |
|
if TSM.db.factionrealm.mats["item:39350"] then |
|
local name = TSMAPI:GetSafeItemInfo("item:39350:0:0:0:0:0:0") or nil |
|
TSM.db.factionrealm.mats["item:39350:0:0:0:0:0:0"] = {} |
|
TSM.db.factionrealm.mats["item:39350:0:0:0:0:0:0"].name = name |
|
TSM.db.factionrealm.mats["item:39350"] = nil |
|
end |
|
if TSM.db.factionrealm.mats["item:39350"] then |
|
local name = TSMAPI:GetSafeItemInfo("item:39350:0:0:0:0:0:0") or nil |
|
TSM.db.factionrealm.mats["item:39350:0:0:0:0:0:0"] = {} |
|
TSM.db.factionrealm.mats["item:39350:0:0:0:0:0:0"].name = name |
|
TSM.db.factionrealm.mats["item:39350"] = nil |
|
end |
|
if TSM.db.factionrealm.mats["item:37602"] then |
|
local name = TSMAPI:GetSafeItemInfo("item:37602:0:0:0:0:0:0") or nil |
|
TSM.db.factionrealm.mats["item:37602:0:0:0:0:0:0"] = {} |
|
TSM.db.factionrealm.mats["item:37602:0:0:0:0:0:0"].name = name |
|
TSM.db.factionrealm.mats["item:37602"] = nil |
|
end |
|
if TSM.db.factionrealm.mats["item:39349"] then |
|
local name = TSMAPI:GetSafeItemInfo("item:39349:0:0:0:0:0:0") or nil |
|
TSM.db.factionrealm.mats["item:39349:0:0:0:0:0:0"] = {} |
|
TSM.db.factionrealm.mats["item:39349:0:0:0:0:0:0"].name = name |
|
TSM.db.factionrealm.mats["item:39349"] = nil |
|
end |
|
if TSM.db.factionrealm.mats["item:38682"] then |
|
local name = TSMAPI:GetSafeItemInfo("item:38682:0:0:0:0:0:0") or nil |
|
TSM.db.factionrealm.mats["item:38682:0:0:0:0:0:0"] = {} |
|
TSM.db.factionrealm.mats["item:38682:0:0:0:0:0:0"].name = name |
|
TSM.db.factionrealm.mats["item:38682"] = nil |
|
end |
|
|
|
local func, err = TSMAPI:ParseCustomPrice(TSM.db.global.defaultCraftPriceMethod, "crafting") |
|
if not func then |
|
TSM:Printf(L["Your default craft value method was invalid so it has been returned to the default. Details: %s"], err) |
|
TSM.db.global.defaultCraftPriceMethod = savedDBDefaults.defaultCraftPriceMethod |
|
end |
|
for name, operation in pairs(TSM.operations) do |
|
if operation.craftPriceMethod then |
|
local func, err = TSMAPI:ParseCustomPrice(TSM.db.global.defaultCraftPriceMethod, "crafting") |
|
if not func then |
|
TSM:Printf(L["Your craft value method for '%s' was invalid so it has been returned to the default. Details: %s"], name, err) |
|
operation.craftPriceMethod = TSM.operationDefaults.craftPriceMethod |
|
end |
|
end |
|
end |
|
end |
|
|
|
-- registers this module with TSM by first setting all fields and then calling TSMAPI:NewModule(). |
|
function TSM:RegisterModule() |
|
TSM.icons = { { side = "module", desc = "Crafting", slashCommand = "crafting", callback = "Options:LoadCrafting", icon = "Interface\\Icons\\INV_Misc_Gear_08" } } |
|
TSM.operations = { maxOperations = 1, callbackOptions = "Options:Load", callbackInfo = "GetOperationInfo" } |
|
TSM.priceSources = { |
|
{ key = "Crafting", label = L["Crafting Cost"], callback = "GetCraftingCost" }, |
|
{ key = "matPrice", label = L["Crafting Material Cost"], callback = "GetCraftingMatCost" }, |
|
} |
|
TSM.moduleAPIs = { |
|
{ key = "addQueue", callback = "Queue:addQueue" }, |
|
{ key = "removeQueue", callback = "Queue:removeQueue" }, |
|
{ key = "getQueue", callback = "Queue:getQueue" }, |
|
{ key = "getCDCrafts", callback = "getCDCrafts" }, |
|
{ key = "getCraftingFrameStatus", callback = "CraftingGUI:GetStatus" }, |
|
} |
|
TSM.tooltipOptions = { callback = "Options:LoadTooltipOptions" } |
|
TSM.slashCommands = { |
|
{ key = "profession", label = L["Opens the Crafting window to the first profession."], callback = "CraftingGUI:OpenFirstProfession" }, |
|
{ key = "restock_help", label = "Tells you why a specific item is not being restocked and added to the queue.", callback = "RestockHelp" }, |
|
} |
|
TSM.sync = { callback = "Sync:Callback" } |
|
TSMAPI:NewModule(TSM) |
|
end |
|
|
|
TSM.operationDefaults = { |
|
minRestock = 1, -- min of 1 |
|
maxRestock = 3, -- max of 3 |
|
minProfit = 1000000, |
|
craftPriceMethod = nil, |
|
ignorePlayer = {}, |
|
ignoreFactionrealm = {}, |
|
relationships = {}, |
|
} |
|
|
|
function TSM:GetOperationInfo(name) |
|
TSMAPI:UpdateOperation("Crafting", name) |
|
local operation = TSM.operations[name] |
|
if not operation then return end |
|
if operation.minProfit then |
|
return format(L["Restocking to a max of %d (min of %d) with a min profit."], operation.maxRestock, operation.minRestock) |
|
else |
|
return format(L["Restocking to a max of %d (min of %d) with no min profit."], operation.maxRestock, operation.minRestock) |
|
end |
|
end |
|
|
|
function TSM:GetTooltip(itemString) |
|
if not TSM.db.global.tooltip then return end |
|
local text = {} |
|
local moneyCoinsTooltip = TSMAPI:GetMoneyCoinsTooltip() |
|
TSM:UpdateCraftReverseLookup() |
|
itemString = TSMAPI:GetBaseItemString(itemString) -- show craft costs against random enchants |
|
|
|
if TSM.craftReverseLookup[itemString] then |
|
if TSM.db.global.tooltip then |
|
local spellID, cost, buyout, profit = TSM.Cost:GetLowestCraftPrices(itemString) |
|
local color |
|
|
|
if profit and profit < 0 then |
|
color = "|cffff0000" |
|
else |
|
color = "|cff00ff00" |
|
|
|
end |
|
|
|
if cost then |
|
local costText, profitText |
|
if moneyCoinsTooltip then |
|
costText = (TSMAPI:FormatTextMoneyIcon(cost, "|cffffffff", true) or "|cffffffff---|r") |
|
profitText = (TSMAPI:FormatTextMoneyIcon(profit, color, true) or "|cffffffff---|r") |
|
else |
|
costText = (TSMAPI:FormatTextMoney(cost, "|cffffffff", true) or "|cffffffff---|r") |
|
profitText = (TSMAPI:FormatTextMoney(profit, color, true) or "|cffffffff---|r") |
|
end |
|
if profit then |
|
local profitPercent = profit / cost * 100 |
|
local profitPercText = format("%s%.0f%%|r",color, profitPercent) |
|
|
|
if profit>0 then |
|
tinsert(text, { left = " " .. L["Crafting Cost"], right = format("%s (%s | %s profit)", costText, profitText, profitPercText) }) |
|
else |
|
tinsert(text, { left = " " .. L["Crafting Cost"], right = format("%s (%s | %s loss)", costText, profitText, profitPercText) }) |
|
end |
|
else |
|
-- tinsert(text, { left = " " .. L["Crafting Cost"], right = format(L["%s (%s profit)"], costText, profitText) }) |
|
tinsert(text, { left = " " .. L["Crafting Cost"], right = format("%s", costText) }) |
|
end |
|
|
|
if TSM.db.global.matsInTooltip and TSM.db.factionrealm.crafts[spellID] then |
|
for matItemString, matQuantity in pairs(TSM.db.factionrealm.crafts[spellID].mats) do |
|
local name, _, quality = TSMAPI:GetSafeItemInfo(matItemString) |
|
if name then |
|
local mat = TSM.db.factionrealm.mats[matItemString] |
|
|
|
|
|
|
|
-- Get Cheapest vellum, lower vellum types can be replaced by III |
|
local velName |
|
if strfind(name, "Vellum") then |
|
velName = name |
|
end |
|
if (velName ~= nil) and (not strfind(velName, "III")) then |
|
local VellumReplacePrice = TSM.Cost:GetMatCost(matItemString) |
|
|
|
if strfind(velName, "Weapon Vellum") then |
|
if VellumReplacePrice > TSM.Cost:GetMatCost("item:43146:0:0:0:0:0:0") then |
|
matItemString = "item:43146:0:0:0:0:0:0" |
|
name = TSMAPI:GetSafeItemInfo(matItemString) |
|
end |
|
else |
|
if VellumReplacePrice > TSM.Cost:GetMatCost("item:43145:0:0:0:0:0:0") then |
|
matItemString = "item:43145:0:0:0:0:0:0" |
|
name = TSMAPI:GetSafeItemInfo(matItemString) |
|
end |
|
end |
|
end |
|
|
|
|
|
|
|
|
|
if mat then |
|
local cost = TSM:GetCustomPrice(mat.customValue or TSM.db.global.defaultMatCostMethod, matItemString) |
|
if cost then |
|
-- local colorName = format("|c%s%s%s%s|r",select(4,GetItemQualityColor(quality)),name, " x ", matQuantity) |
|
local colorName = format("%s%s%s%s|r",select(4,GetItemQualityColor(quality)), name, " x ", matQuantity) |
|
if matQuantity > 1 then |
|
if moneyCoinsTooltip then |
|
tinsert(text, { left = " " .. colorName, right = "ea: "..TSMAPI:FormatTextMoneyIcon(cost, "|cffffffff", true).." | total: "..TSMAPI:FormatTextMoneyIcon(cost*matQuantity, "|cffffffff", true)}) |
|
else |
|
tinsert(text, { left = " " .. colorName, right = "ea: "..TSMAPI:FormatTextMoney(cost, "|cffffffff", true).." | total: "..TSMAPI:FormatTextMoney(cost*matQuantity, "|cffffffff", true)}) |
|
end |
|
else |
|
if moneyCoinsTooltip then |
|
tinsert(text, { left = " " .. colorName, right = TSMAPI:FormatTextMoneyIcon(cost*matQuantity, "|cffffffff", true) }) |
|
else |
|
tinsert(text, { left = " " .. colorName, right = TSMAPI:FormatTextMoney(cost*matQuantity, "|cffffffff", true) }) |
|
end |
|
end |
|
end |
|
end |
|
end |
|
end |
|
end |
|
end |
|
end |
|
end |
|
if TSM.db.global.materialTooltip then |
|
local mat = TSM.db.factionrealm.mats[itemString] |
|
if mat then |
|
local cost = TSM:GetCustomPrice(mat.customValue or TSM.db.global.defaultMatCostMethod, itemString) |
|
if cost then |
|
local costText |
|
if moneyCoinsTooltip then |
|
costText = (TSMAPI:FormatTextMoneyIcon(cost, "|cffffffff", true) or "|cffffffff---|r") |
|
else |
|
costText = (TSMAPI:FormatTextMoney(cost, "|cffffffff", true) or "|cffffffff---|r") |
|
end |
|
tinsert(text, { left = " " .. L["Mat Cost"], right = format("%s", costText) }) |
|
end |
|
end |
|
end |
|
|
|
|
|
if #text > 0 then |
|
tinsert(text, 1, "|cffffff00" .. "TSM Crafting:") |
|
return text |
|
end |
|
end |
|
|
|
function TSM:GetCraftingCost(link) |
|
link = select(2, TSMAPI:GetSafeItemInfo(link)) |
|
local itemString = TSMAPI:GetBaseItemString(link) |
|
if not itemString then return end |
|
|
|
TSM:UpdateCraftReverseLookup() |
|
local _, cost = TSM.Cost:GetLowestCraftPrices(itemString) |
|
if cost then |
|
TSM.db.factionrealm.craftingCostCache[itemString] = cost |
|
end |
|
return TSM.db.factionrealm.craftingCostCache[itemString] |
|
end |
|
|
|
function TSM:GetCraftingMatCost(link) |
|
link = select(2, TSMAPI:GetSafeItemInfo(link)) |
|
local itemString = TSMAPI:GetBaseItemString(link) |
|
if not itemString then return end |
|
|
|
TSM:UpdateCraftReverseLookup() |
|
return TSM.Cost:GetMatCost(itemString) |
|
end |
|
|
|
local reverseLookupUpdate = 0 |
|
function TSM:UpdateCraftReverseLookup() |
|
-- if reverseLookupUpdate >= time() - 30 then return end |
|
reverseLookupUpdate = time() |
|
TSM.craftReverseLookup = {} |
|
|
|
for spellID, data in pairs(TSM.db.factionrealm.crafts) do |
|
TSM.craftReverseLookup[data.itemID] = TSM.craftReverseLookup[data.itemID] or {} |
|
tinsert(TSM.craftReverseLookup[data.itemID], spellID) |
|
end |
|
end |
|
|
|
function TSM:GetCustomPrice(priceMethod, itemString) |
|
local func = TSMAPI:ParseCustomPrice(priceMethod) |
|
return func and func(itemString) |
|
end |
|
|
|
function TSM:getCDCrafts() |
|
local crafts = {} |
|
for spellID, data in pairs(TSM.db.factionrealm.crafts) do |
|
if data.hasCD then |
|
crafts[spellID] = data.name |
|
end |
|
end |
|
return crafts |
|
end |
|
|
|
function TSM:RestockHelp(link) |
|
local itemString = TSMAPI:GetItemString(link) |
|
if not itemString then |
|
return print("No item specified. Usage: /tsm restock_help [ITEM_LINK]") |
|
end |
|
|
|
TSM:Printf("Restock help for %s:", link) |
|
|
|
-- check if the item is in a group |
|
local groupPath = TSMAPI:GetGroupPath(itemString) |
|
if not groupPath then |
|
return print("This item is not in a TSM group.") |
|
end |
|
|
|
-- check that there's a crafting operation applied |
|
local operation = (TSMAPI:GetItemOperation(itemString, "Crafting") or {})[1] |
|
if not operation then |
|
return print(format("There is no TSM_Crafting operation applied to this item's TSM group (%s).", TSMAPI:FormatGroupPath(groupPath))) |
|
end |
|
|
|
-- check if it's an invalid operation |
|
local opSettings = TSM.operations[operation] |
|
if opSettings.minRestock > opSettings.maxRestock then |
|
return print(format(L["'%s' is an invalid operation! Min restock of %d is higher than max restock of %d."], operation, opSettings.minRestock, opSettings.maxRestock)) |
|
end |
|
|
|
-- check that this item is craftable |
|
TSM:UpdateCraftReverseLookup() |
|
local spellID = TSM.craftReverseLookup[itemString] and TSM.craftReverseLookup[itemString][1] |
|
if not spellID or not TSM.db.factionrealm.crafts[spellID] then |
|
return print("You don't know how to craft this item.") |
|
end |
|
|
|
-- check the restock quantity |
|
local numHave = TSM.Inventory:GetTotalQuantity(itemString) |
|
if numHave >= opSettings.maxRestock then |
|
return print(format("You already have at least your max restock quantity of this item. You have %d and the max restock quantity is %d", numHave, opSettings.maxRestock)) |
|
elseif (opSettings.maxRestock - numHave) < opSettings.minRestock then |
|
return print(format("The number which would be queued (%d) is less than the min restock quantity (%d).", (opSettings.maxRestock - numHave), opSettings.minRestock)) |
|
end |
|
|
|
-- check the prices on the item and the min profit |
|
if opSettings.minProfit then |
|
local cheapestSpellID, cost, craftedValue, profit = TSM.Cost:GetLowestCraftPrices(itemString) |
|
|
|
-- check that there's a crafted value |
|
if not craftedValue then |
|
local craftPriceMethod = operation and operation.craftPriceMethod or TSM.db.global.defaultCraftPriceMethod |
|
return print(format("The 'Craft Value Method' (%s) did not return a value for this item. If it is based on some price database (AuctionDB, TSM_WoWuction, TUJ, etc), then ensure that you have scanned for or downloaded the data as appropriate.", craftPriceMethod)) |
|
end |
|
|
|
-- check that there's a crafted cost |
|
if not cost then |
|
return print("This item does not have a crafting cost. Check that all of its mats have mat prices. If the mat prices are based on some price database (AuctionDB, TSM_WoWuction, TUJ, etc), then ensure that you have scanned for or downloaded the data as appropriate.") |
|
end |
|
|
|
-- check that there's a profit |
|
if not profit then |
|
return print("There is a crafting cost and crafted item value, but TSM_Crafting wasn't able to calculate a profit. This shouldn't happen!") |
|
end |
|
|
|
local minProfit = TSM:GetCustomPrice(opSettings.minProfit, itemString) |
|
if not minProfit then |
|
return print(format("The min profit (%s) did not evalulate to a valid value for this item.", opSettings.minProfit)) |
|
end |
|
|
|
if profit < minProfit then |
|
return print(format("The profit of this item (%s) is below the min profit (%s).", TSMAPI:FormatTextMoney(profit), TSMAPI:FormatTextMoney(minProfit))) |
|
end |
|
end |
|
|
|
print("This item will be added to the queue when you restock its group. If this isn't happening, make a post on the TSM forums with a screenshot of the item's tooltip, operation settings, and your general TSM_Crafting options.") |
|
end |