-- ------------------------------------------------------------------------------ --
-- 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