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.
362 lines
15 KiB
362 lines
15 KiB
|
4 years ago
|
-- ------------------------------------------------------------------------------ --
|
||
|
|
-- 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("TradeSkillMaster_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:52510" then
|
||
|
|
TSM.db.factionrealm.crafts[spellid].mats["item:52510:0:0:0:0:0:0"] = 1
|
||
|
|
TSM.db.factionrealm.crafts[spellid].mats[itemString] = nil
|
||
|
|
elseif itemString == "item:52511" then
|
||
|
|
TSM.db.factionrealm.crafts[spellid].mats["item:52511:0:0:0:0:0:0"] = 1
|
||
|
|
TSM.db.factionrealm.crafts[spellid].mats[itemString] = nil
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if TSM.db.factionrealm.mats["item:52510"] then
|
||
|
|
local name = TSMAPI:GetSafeItemInfo("item:52510:0:0:0:0:0:0") or nil
|
||
|
|
TSM.db.factionrealm.mats["item:52510:0:0:0:0:0:0"] = {}
|
||
|
|
TSM.db.factionrealm.mats["item:52510:0:0:0:0:0:0"].name = name
|
||
|
|
TSM.db.factionrealm.mats["item:52510"] = nil
|
||
|
|
end
|
||
|
|
if TSM.db.factionrealm.mats["item:52511"] then
|
||
|
|
local name = TSMAPI:GetSafeItemInfo("item:52511:0:0:0:0:0:0") or nil
|
||
|
|
TSM.db.factionrealm.mats["item:52511:0:0:0:0:0:0"] = {}
|
||
|
|
TSM.db.factionrealm.mats["item:52511:0:0:0:0:0:0"].name = name
|
||
|
|
TSM.db.factionrealm.mats["item:52511"] = 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]
|
||
|
|
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
|