annotate Modules/Crafting.lua @ 135:a529a4a4ccbe

I removed the persistent queue (Ticket 33) It caused to many bugs and was blocking me from getting other things done. I think its something that will get implemented again once I figure out the best way to do it.
author Asa Ayers <Asa.Ayers@Gmail.com>
date Sat, 02 Oct 2010 11:38:22 -0700
parents 5eefa40e2a29 7f81764aa03a
children 106c1523777e
rev   line source
Asa@63 1 local ItemAuditor = select(2, ...)
Asa@124 2 local Crafting = ItemAuditor:NewModule("Crafting", 'AceEvent-3.0')
Asa@59 3
Asa@86 4 local Utils = ItemAuditor:GetModule("Utils")
Asa@86 5
Asa@59 6 local AceGUI = LibStub("AceGUI-3.0")
Asa@59 7 local ScrollingTable = LibStub("ScrollingTable")
Asa@59 8
Asa@59 9 local validateMoney = ItemAuditor.validateMoney
Asa@59 10 local parseMoney = ItemAuditor.parseMoney
Asa@59 11
Asa@59 12 local realData = {}
Asa@128 13 local nameMap = nil
Asa@59 14
Asa@124 15 local vellumLevelMap = {
Asa@124 16 [38682] = 37602, -- Armor Vellum => Armor Vellum II
Asa@124 17 [37602] = 43145, -- Armor Vellum II => Armor Vellum III
Asa@124 18 [39349] = 39350, -- Weapon Vellum => Weapon Vellum II
Asa@124 19 [39350] = 43146, -- Weapon Vellum II => Weapon Vellum III
Asa@124 20 }
Asa@67 21
Asa@128 22 function Crafting:OnInitialize()
Asa@128 23 self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
Asa@128 24 end
Asa@128 25
Asa@128 26 local function getQueueLocation(name)
Asa@128 27 if not nameMap then
Asa@128 28 nameMap = {}
Asa@128 29 for key, data in pairs(realData) do
Asa@128 30 nameMap[data.skillName] = key
Asa@128 31 end
Asa@128 32 end
Asa@128 33 return nameMap[name]
Asa@128 34 end
Asa@128 35
Asa@128 36 --@debug@
Asa@128 37 Crafting.getQueueLocation = getQueueLocation
Asa@128 38 function Crafting.getNameMap()
Asa@128 39 return nameMap
Asa@128 40 end
Asa@128 41
Asa@128 42 function Crafting.getRealData()
Asa@128 43 return realData
Asa@128 44 end
Asa@128 45 --@end-debug@
Asa@128 46
Asa@128 47 function Crafting:UNIT_SPELLCAST_SUCCEEDED(event, unit, spell)
Asa@128 48 if unit == "player" and getQueueLocation(spell) then
Asa@128 49 local data = realData[getQueueLocation(spell)]
Asa@128 50 data.queue = data.queue - 1
Asa@128 51 ItemAuditor:RefreshCraftingTable()
Asa@128 52 end
Asa@128 53 end
Asa@128 54
Asa@68 55 local queueDestinations = {}
Asa@70 56 local displayCraftingDestinations = {}
Asa@68 57 function Crafting.RegisterQueueDestination(name, destination)
Asa@68 58 queueDestinations[name] = destination
Asa@70 59 displayCraftingDestinations[name] = name
Asa@70 60 end
Asa@70 61
Asa@70 62 function Crafting.UnRegisterQueueDestination(name)
Asa@70 63 queueDestinations[name] = nil
Asa@70 64 displayCraftingDestinations[name] = nil
Asa@70 65 end
Asa@70 66
Asa@70 67 function Crafting.GetQueueDestination()
Asa@70 68 local dest = ItemAuditor.db.profile.queue_destination
Asa@70 69 if dest and queueDestinations[dest] then
Asa@70 70 return queueDestinations[dest], dest
Asa@70 71 end
Asa@133 72 -- If there is none selected or the selected option has
Asa@70 73 -- dissapeared, choose the first one in the list
Asa@70 74 for name, func in pairs(queueDestinations) do
Asa@70 75 if dest then
Asa@70 76 ItemAuditor:Print("%s is no longer available as a queue destination. %s is the new default", dest, name)
Asa@70 77 end
Asa@70 78 ItemAuditor.db.profile.queue_destination = name
Asa@70 79 return func, name
Asa@70 80 end
Asa@133 81
Asa@70 82 error('Unable to determine queue destination.')
Asa@68 83 end
Asa@68 84
Asa@68 85 function ItemAuditor:GetCraftingThreshold()
Asa@101 86 return self.db.char.profitable_threshold
Asa@68 87 end
Asa@68 88
Asa@67 89 ItemAuditor.Options.args.crafting_options = {
Asa@70 90 name = "Crafting",
Asa@67 91 type = 'group',
Asa@67 92 args = {
Asa@70 93 queue_destination = {
Asa@70 94 type = "select",
Asa@70 95 name = "Queue Destination",
Asa@70 96 desc = "Select the addon who's queue you would like ItemAuditor to post to.",
Asa@70 97 values = displayCraftingDestinations,
Asa@70 98 get = function() return select(2, Crafting.GetQueueDestination()) end,
Asa@70 99 set = function(info, value) ItemAuditor.db.profile.queue_destination = value end,
Asa@72 100 order = 1,
Asa@70 101 },
Asa@72 102 deciders = {
Asa@72 103 type="header",
Asa@72 104 name="Crafting Deciders",
Asa@72 105 order = 10,
Asa@72 106 },
Asa@67 107 },
Asa@67 108 }
Asa@67 109
Asa@59 110 local function displayMoney(rowFrame, cellFrame, data, cols, row, realrow, column, fShow, table, ...)
Asa@59 111 if fShow == true then
Asa@59 112 local money = data[realrow][column]
Asa@59 113 if money then
Asa@59 114 cellFrame.text:SetText(ItemAuditor:FormatMoney(tonumber(money)))
Asa@59 115 else
Asa@59 116 cellFrame.text:SetText("")
Asa@59 117 end
Asa@133 118
Asa@59 119 end
Asa@59 120 end
Asa@59 121
Asa@59 122 local craftingCols = {
Asa@59 123 { name= "Item", width = 200, defaultsort = "desc",
Asa@59 124 ['DoCellUpdate'] = function(rowFrame, cellFrame, data, cols, row, realrow, column, fShow, table, ...)
Asa@59 125 if fShow == true then
Asa@59 126 local data = realData[realrow]
Asa@59 127 cellFrame.text:SetText(data.link)
Asa@59 128 end
Asa@59 129 end,
Asa@59 130 },
Asa@133 131 { name= "Cost Each", width = 100, align = "RIGHT",
Asa@59 132 ['DoCellUpdate'] = displayMoney,
Asa@59 133 },
Asa@133 134 { name= "Est Sale Each", width = 100, align = "RIGHT",
Asa@59 135 ['DoCellUpdate'] = displayMoney,
Asa@59 136 },
Asa@99 137 { name= "Decided By", width = 125, align = "RIGHT",
Asa@133 138
Asa@59 139 },
Asa@133 140 { name= "craft", width = 50, align = "RIGHT",
Asa@133 141
Asa@59 142 },
Asa@133 143 { name= "Have Mats", width = 60, align = "RIGHT",
Asa@133 144
Asa@99 145 },
Asa@123 146 { name= "Profit Each", width = 100, align = "RIGHT",
Asa@59 147 ['DoCellUpdate'] = displayMoney,
Asa@59 148 },
Asa@59 149 }
Asa@59 150
Asa@68 151 function Crafting.ExportToSkillet(data)
Asa@68 152 local skillString = select(3, string.find(data.recipeLink, "^|%x+|H(.+)|h%[.+%]"))
Asa@68 153 local _, skillId = strsplit(":", skillString)
Asa@133 154
Asa@68 155 ItemAuditor:AddToQueue(skillId,tradeSkillIndex, data.queue)
Asa@68 156 end
Asa@68 157
Asa@68 158 Crafting.RegisterQueueDestination('Skillet', Crafting.ExportToSkillet)
Asa@68 159
Asa@68 160
Asa@68 161
Asa@68 162 function Crafting.Export(destination)
Asa@68 163 if type(destination) == 'function' then
Asa@68 164 -- do nothing
Asa@68 165 elseif destination == nil then
Asa@70 166 destination = Crafting.GetQueueDestination()
Asa@68 167 elseif type(destination) == 'string' then
Asa@68 168 destination = queueDestinations[destination]
Asa@68 169 else
Asa@68 170 error('destination must be a function or a string')
Asa@68 171 end
Asa@133 172
Asa@59 173 local index = 1
Asa@59 174 local data = ItemAuditor:GetCraftingRow(index)
Asa@59 175 while data do
Asa@68 176 if data.queue > 0 then
Asa@68 177 destination(data)
Asa@68 178 end
Asa@61 179 index = index + 1
Asa@61 180 data = ItemAuditor:GetCraftingRow(index)
Asa@133 181
Asa@59 182 end
Asa@59 183 end
Asa@59 184
Asa@74 185 -- ItemAuditor:GetModule('Crafting').filter_queued = false
Asa@99 186 Crafting.filter_have_mats = false
Asa@99 187 Crafting.filter_show_all = false
Asa@74 188 local function tableFilter(self, row, ...)
Asa@128 189 if Crafting.nameFilter then
Asa@128 190 return string.find(row[1], Crafting.nameFilter) ~= nil
Asa@128 191 end
Asa@128 192
Asa@99 193 if Crafting.filter_show_all then
Asa@99 194 return true
Asa@99 195 end
Asa@99 196
Asa@74 197 -- column 5 is how many should be crafted
Asa@126 198 if Crafting.filter_have_mats and row[6] == 0 then
Asa@99 199 return false
Asa@99 200 end
Asa@99 201 if strfind(row[4], 'VETO: .*') or row[5] == 0 then
Asa@74 202 return false
Asa@74 203 end
Asa@74 204 return true
Asa@74 205 end
Asa@74 206
Asa@59 207 local craftingContent = false
Asa@59 208 local craftingTable = false
Asa@60 209 local btnProcess = false
Asa@59 210 local function ShowCrafting(container)
Asa@59 211 if craftingContent == false then
Asa@59 212 local window = container.frame
Asa@59 213 craftingContent = CreateFrame("Frame",nil,window)
Asa@133 214 craftingContent:SetBackdropColor(0, 0, 1, 0.5)
Asa@59 215 craftingContent:SetBackdropBorderColor(1, 0, 0, 1)
Asa@133 216
Asa@59 217 craftingContent:SetPoint("TOPLEFT", window, 10, -50)
Asa@59 218 craftingContent:SetPoint("BOTTOMRIGHT",window, -10, 10)
Asa@133 219
Asa@59 220 craftingTable = ScrollingTable:CreateST(craftingCols, 22, nil, nil, craftingContent )
Asa@133 221
Asa@133 222 IAcc = craftingContent
Asa@59 223 IAccWindow = window
Asa@59 224 craftingTable.frame:SetPoint("TOPLEFT",craftingContent, 0,0)
Asa@59 225 craftingTable.frame:SetPoint("BOTTOMRIGHT", craftingContent, 0, 30)
Asa@133 226
Asa@59 227 craftingTable:RegisterEvents({
Asa@59 228 ["OnEnter"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...)
Asa@59 229 if realrow then
Asa@134 230 local data = realData[realrow]
Asa@134 231
Asa@134 232 GameTooltip:SetOwner(rowFrame, "ANCHOR_CURSOR")
Asa@134 233 GameTooltip:SetHyperlink(data.link)
Asa@134 234 GameTooltip:Show()
Asa@59 235 end
Asa@59 236 end,
Asa@59 237 ["OnLeave"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...)
Asa@59 238 GameTooltip:Hide()
Asa@59 239 end,
Asa@59 240 });
Asa@133 241
Asa@99 242 local craftingView = CreateFrame("Button", nil, craftingContent, "UIPanelButtonTemplate")
Asa@99 243 craftingView:SetText("View")
Asa@99 244 craftingView:SetSize(50, 25)
Asa@99 245 craftingView:SetPoint("BOTTOMLEFT", craftingContent, 0, 0)
Asa@99 246
Asa@99 247 local menu = {
Asa@99 248 { text = "View", isTitle = true},
Asa@99 249 { text = "To be crafted", func = function()
Asa@99 250 Crafting.filter_have_mats = false
Asa@99 251 Crafting.filter_show_all = false
Asa@99 252 ItemAuditor:RefreshCraftingTable()
Asa@99 253 end },
Asa@99 254 { text = "Have Mats", func = function()
Asa@99 255 Crafting.filter_have_mats = true
Asa@99 256 Crafting.filter_show_all = false
Asa@99 257 ItemAuditor:RefreshCraftingTable()
Asa@99 258 end },
Asa@99 259 { text = "All", func = function()
Asa@99 260 Crafting.filter_have_mats = false
Asa@99 261 Crafting.filter_show_all = true
Asa@99 262 ItemAuditor:RefreshCraftingTable()
Asa@99 263 end },
Asa@99 264 }
Asa@99 265 local menuFrame = CreateFrame("Frame", "ExampleMenuFrame", UIParent, "UIDropDownMenuTemplate")
Asa@99 266 craftingView:SetScript("OnClick", function (self, button, down)
Asa@99 267 EasyMenu(menu, menuFrame, "cursor", 0 , 0, "MENU");
Asa@99 268 end)
Asa@99 269
Asa@99 270
Asa@59 271 btnProcess = CreateFrame("Button", nil, craftingContent, "UIPanelButtonTemplate")
Asa@59 272 btnProcess:SetText("Process")
Asa@133 273 btnProcess:SetSize(100, 25)
Asa@59 274 btnProcess:SetPoint("BOTTOMRIGHT", craftingContent, 0, 0)
Asa@59 275 btnProcess:RegisterForClicks("LeftButtonUp");
Asa@133 276
Asa@60 277 local function UpdateProcessTooltip(btn)
Asa@59 278 local data = ItemAuditor:GetCraftingRow(1)
Asa@59 279 if data then
Asa@59 280 GameTooltip:SetOwner(this, "ANCHOR_CURSOR")
Asa@59 281 GameTooltip:SetText(format('Create %sx%s', data.link, data.queue))
Asa@59 282 GameTooltip:Show()
Asa@59 283 end
Asa@60 284 end
Asa@124 285
Asa@124 286 --[[
Asa@124 287 When enchanting UseContainerItem seems to be protected, so the enchants
Asa@124 288 have to be done one at a time.
Asa@124 289 ]]
Asa@124 290 local function useVellum(vellumID, idealVellum)
Asa@124 291 for bagID = 0, NUM_BAG_SLOTS do
Asa@124 292 for slotID = 0, GetContainerNumSlots(bagID) do
Asa@124 293 local link = GetContainerItemLink(bagID, slotID)
Asa@124 294 local id = Utils.GetItemID(link);
Asa@124 295 if id == vellumID then
Asa@124 296 if idealVellum then
Asa@124 297 ItemAuditor:Print("Using %s instead of %s.",
Asa@124 298 select(2, GetItemInfo(vellumID)),
Asa@124 299 select(2, GetItemInfo(idealVellum))
Asa@124 300 )
Asa@124 301 end
Asa@124 302 UseContainerItem(bagID, slotID)
Asa@124 303 return
Asa@124 304 end
Asa@124 305 end
Asa@124 306 end
Asa@124 307 if vellumLevelMap[vellumID] then
Asa@124 308 return useVellum(vellumLevelMap[vellumID], idealVellum or vellumID)
Asa@124 309 end
Asa@124 310 end
Asa@133 311
Asa@60 312 btnProcess:SetScript("OnClick", function (self, button, down)
Asa@60 313 local data = ItemAuditor:GetCraftingRow(1)
Asa@60 314 if data then
Asa@128 315 -- This will make sure the correct tradeskill window is open.
Asa@128 316 local tradeskillName = GetTradeSkillLine()
Asa@128 317 if data.tradeskillName ~= tradeskillName then
Asa@128 318 CastSpellByName(data.tradeskillName)
Asa@128 319 end
Asa@133 320
Asa@124 321 local queue = data.queue
Asa@124 322 local vellumID = nil
Asa@124 323 _, _, _, _, altVerb = GetTradeSkillInfo(data.tradeSkillIndex)
Asa@124 324 if altVerb == 'Enchant' and LSW.scrollData[data.recipeID] ~= nil then
Asa@124 325 vellumID = LSW.scrollData[data.recipeID]["vellumID"]
Asa@124 326 queue = 1
Asa@124 327 end
Asa@124 328 ItemAuditor:Print('Crafting %sx%s', data.link, queue)
Asa@124 329 DoTradeSkill(data.tradeSkillIndex, queue)
Asa@124 330 if vellumID then
Asa@124 331 useVellum(vellumID)
Asa@124 332 end
Asa@124 333
Asa@60 334 UpdateProcessTooltip()
Asa@60 335 end
Asa@59 336 end)
Asa@59 337
Asa@60 338 btnProcess:SetScript("OnEnter", UpdateProcessTooltip)
Asa@60 339
Asa@59 340 btnProcess:SetScript("OnLeave", function()
Asa@59 341 GameTooltip:Hide()
Asa@59 342 end)
Asa@133 343
Asa@59 344 btnSkillet = CreateFrame("Button", nil, craftingContent, "UIPanelButtonTemplate")
Asa@99 345
Asa@133 346 btnSkillet:SetSize(125, 25)
Asa@59 347 btnSkillet:SetPoint("BOTTOMRIGHT", btnProcess, 'BOTTOMLEFT', 0, 0)
Asa@59 348 btnSkillet:RegisterForClicks("LeftButtonUp");
Asa@59 349 btnSkillet:SetScript("OnClick", function (self, button, down)
Asa@70 350 Crafting.Export()
Asa@59 351 end)
Asa@133 352
Asa@59 353 end
Asa@70 354 local destination = select(2, Crafting.GetQueueDestination())
Asa@70 355 btnSkillet:SetText("Export to "..destination)
Asa@133 356
Asa@59 357 craftingContent:Show()
Asa@133 358
Asa@59 359 if container.parent then
Asa@59 360 local width = 80
Asa@133 361 for i, data in pairs(craftingCols) do
Asa@59 362 width = width + data.width
Asa@59 363 end
Asa@59 364 container.parent:SetWidth(width);
Asa@59 365 end
Asa@133 366
Asa@59 367 ItemAuditor:RegisterEvent("TRADE_SKILL_SHOW", function()
Asa@59 368 if craftingContent and craftingContent:IsVisible() then
Asa@59 369 ItemAuditor:UpdateCraftingTable()
Asa@59 370 end
Asa@59 371 end)
Asa@59 372 ItemAuditor:UpdateCraftingTable()
Asa@133 373
Asa@59 374 return craftingContent
Asa@59 375 end
Asa@59 376
Asa@59 377 ItemAuditor:RegisterTab('Crafting', 'tab_crafting', ShowCrafting)
Asa@59 378 function ItemAuditor:DisplayCrafting()
Asa@59 379 self:CreateFrame('tab_crafting')
Asa@59 380 end
Asa@59 381
Asa@59 382 local craftingDeciders = {}
Asa@59 383
Asa@72 384 function Crafting.RegisterCraftingDecider(name, decider, options)
Asa@59 385 craftingDeciders[name] = decider
Asa@133 386
Asa@72 387 ItemAuditor.Options.args.crafting_options.args['chk'..name] = {
Asa@72 388 type = "toggle",
Asa@72 389 name = "Enable "..name,
Asa@72 390 get = function() return not ItemAuditor.db.profile.disabled_deciders[name] end,
Asa@72 391 set = function(info, value) ItemAuditor.db.profile.disabled_deciders[name] = not value end,
Asa@72 392 order = 11,
Asa@72 393 }
Asa@133 394
Asa@72 395 if options then
Asa@72 396 ItemAuditor.Options.args.crafting_options.args['decider_'..name] = {
Asa@72 397 handler = {},
Asa@72 398 name = name,
Asa@72 399 type = 'group',
Asa@72 400 args = options,
Asa@72 401 }
Asa@72 402 end
Asa@59 403 end
Asa@59 404
Asa@59 405 local lastWinnder = ""
Asa@59 406 local function Decide(data)
Asa@59 407 local newDecision = 0
Asa@74 408 local reason = ""
Asa@59 409 for name, decider in pairs(craftingDeciders) do
Asa@72 410 if not ItemAuditor.db.profile.disabled_deciders[name] and name ~= lastWinner then
Asa@74 411 newDecision, reason = decider(data)
Asa@133 412
Asa@59 413 if newDecision > data.queue then
Asa@59 414 data.queue = newDecision
Asa@74 415 lastWinner = (reason or name)
Asa@59 416 return Decide(data)
Asa@59 417 elseif newDecision < 0 then
Asa@59 418 lastWinner = ""
Asa@74 419 return 'VETO: '..(reason or name), -1
Asa@59 420 end
Asa@59 421 end
Asa@59 422 end
Asa@133 423
Asa@59 424 winner = lastWinner
Asa@59 425 lastWinner = ""
Asa@133 426
Asa@77 427 data.queue = ceil(data.queue / GetTradeSkillNumMade(data.tradeSkillIndex))
Asa@133 428
Asa@59 429 return winner, data.queue
Asa@59 430 end
Asa@59 431
Asa@59 432 local function isProfitable(data)
Asa@59 433 if data.profit > 0 and data.profit > ItemAuditor:GetCraftingThreshold() then
Asa@59 434 return 1
Asa@59 435 end
Asa@99 436 return -1, 'Not Profitable'
Asa@59 437 end
Asa@72 438
Asa@101 439 local isProfitableOptions = {
Asa@101 440 profitable_threshold = {
Asa@101 441 type = "input",
Asa@101 442 name = "Crafting Threshold",
Asa@101 443 desc = "Don't create items that will make less than this amount of profit",
Asa@101 444 get = function() return
Asa@101 445 Utils.FormatMoney(ItemAuditor:GetCraftingThreshold(), '', true)
Asa@101 446 end,
Asa@101 447 validate = function(info, value)
Asa@101 448 if not Utils.validateMoney(value) then
Asa@101 449 return "Invalid money format"
Asa@101 450 end
Asa@101 451 return true
Asa@101 452 end,
Asa@101 453 set = function(info, value)
Asa@101 454 ItemAuditor.db.char.profitable_threshold = Utils.parseMoney(value)
Asa@101 455 end,
Asa@101 456 usage = "###g ##s ##c",
Asa@101 457 order = 0,
Asa@101 458 },
Asa@101 459 }
Asa@101 460
Asa@101 461 Crafting.RegisterCraftingDecider('Is Profitable', isProfitable, isProfitableOptions)
Asa@59 462
Asa@74 463
Asa@59 464
Asa@59 465 local tableData = {}
Asa@59 466 function ItemAuditor:UpdateCraftingTable()
Asa@59 467 if LSW == nil then
Asa@59 468 self:Print("This feature requires LilSparky's Workshop.")
Asa@59 469 return
Asa@59 470 end
Asa@59 471 if GetAuctionBuyout ~= nil then
Asa@59 472 elseif AucAdvanced and AucAdvanced.Version then
Asa@59 473 else
Asa@59 474 self:Print("This feature requires Auctionator, Auctioneer, AuctionLite, or AuctionMaster.")
Asa@59 475 return
Asa@59 476 end
Asa@128 477 local tradeskillName = GetTradeSkillLine()
Asa@133 478
Asa@59 479 wipe(tableData)
Asa@133 480
Asa@59 481 local profitableItems = {}
Asa@59 482 local profitableIndex = 1
Asa@59 483 local numChecked = 0
Asa@128 484 local numTradeSkills = GetNumTradeSkills()
Asa@128 485 if tradeskillName == 'UNKNOWN' then
Asa@128 486 numTradeSkills = 0
Asa@128 487 end
Asa@133 488
Asa@134 489 local row = 1
Asa@59 490
Asa@128 491 for i = 1, numTradeSkills do
Asa@59 492 local itemLink = GetTradeSkillItemLink(i)
Asa@86 493 local itemId = Utils.GetItemID(itemLink)
Asa@124 494 local vellumID = nil
Asa@59 495
Asa@59 496 --Figure out if its an enchant or not
Asa@59 497 _, _, _, _, altVerb = GetTradeSkillInfo(i)
Asa@59 498 if LSW.scrollData[itemId] ~= nil and altVerb == 'Enchant' then
Asa@59 499 -- Ask LSW for the correct scroll
Asa@124 500 local sd = LSW.scrollData[itemId]
Asa@124 501 itemId = sd.scrollID
Asa@124 502 vellumID = sd.vellumID
Asa@59 503 end
Asa@59 504
Asa@59 505 local recipeLink = GetTradeSkillRecipeLink(i)
Asa@59 506 local stackSize = 1
Asa@59 507 if recipeLink ~= nil and itemId ~= nil then
Asa@59 508 local skillName, skillType, numAvailable, isExpanded, altVerb = GetTradeSkillInfo(i)
Asa@59 509 local itemName, itemLink= GetItemInfo(itemId)
Asa@133 510
Asa@74 511 -- This check has to be here for things like Inscription Research that don't produce an item.
Asa@74 512 if itemLink then
Asa@82 513 local count = ItemAuditor:GetItemCount(itemId)
Asa@74 514 local reagents = {}
Asa@74 515 local totalCost = 0
Asa@74 516 for reagentId = 1, GetTradeSkillNumReagents(i) do
Asa@74 517 local reagentName, _, reagentCount = GetTradeSkillReagentInfo(i, reagentId);
Asa@74 518 local reagentLink = GetTradeSkillReagentItemLink(i, reagentId)
Asa@102 519 local reagentTotalCost = self:GetReagentCost(reagentLink, reagentCount)
Asa@133 520
Asa@74 521 reagents[reagentId] = {
Asa@93 522 link = reagentLink,
Asa@124 523 itemID = Utils.GetItemID(reagentLink),
Asa@74 524 name = reagentName,
Asa@74 525 count = reagentCount,
Asa@102 526 price = reagentTotalCost / reagentCount,
Asa@94 527 need = 0, -- This will get populated after the decisions have been made. it can't
Asa@94 528 -- be done before that because highest profit items get priority on materials.
Asa@74 529 }
Asa@102 530 totalCost = totalCost + reagentTotalCost
Asa@74 531 end
Asa@124 532 if vellumID then
Asa@124 533 reagentId = GetTradeSkillNumReagents(i) + 1
Asa@124 534 local reagentName, reagentLink = GetItemInfo(vellumID)
Asa@124 535 reagents[reagentId] = {
Asa@124 536 link = reagentLink,
Asa@124 537 itemID = vellumID,
Asa@124 538 name = reagentName,
Asa@124 539 count = 1,
Asa@124 540 price = self:GetReagentCost(reagentLink, 1),
Asa@124 541 need = 0, -- This will get populated after the decisions have been made. it can't
Asa@124 542 -- be done before that because highest profit items get priority on materials.
Asa@124 543 }
Asa@124 544 totalCost = totalCost + self:GetReagentCost(reagentLink, 1)
Asa@124 545 end
Asa@116 546
Asa@116 547 local price = (self:GetAuctionPrice(itemLink) or 0)
Asa@116 548 totalCost = totalCost + (price * ItemAuditor:GetAHCut())
Asa@74 549 local data = {
Asa@74 550 recipeLink = recipeLink,
Asa@95 551 recipeID = Utils.GetItemID(recipeLink),
Asa@74 552 link = itemLink,
Asa@74 553 name = itemName,
Asa@128 554 skillName = skillName,
Asa@74 555 count = count,
Asa@110 556 price = price,
Asa@74 557 cost = totalCost,
Asa@110 558 profit = price - totalCost,
Asa@74 559 reagents = reagents,
Asa@74 560 count = count,
Asa@74 561 tradeSkillIndex = i,
Asa@74 562 queue = 0,
Asa@74 563 winner = "",
Asa@128 564 tradeskillName = tradeskillName,
Asa@74 565 }
Asa@133 566
Asa@74 567 data.winner, data.queue = Decide(data)
Asa@99 568 --[[
Asa@99 569 If it wasn't vetoed we need to reduce the number by how many are owned
Asa@99 570 but this should not go below 0
Asa@99 571 ]]
Asa@99 572 if data.queue > 0 then
Asa@99 573 data.queue = max(0, data.queue - count)
Asa@99 574 end
Asa@133 575
Asa@133 576 -- If a tradeskill makes 5 at a time and something asks for 9, we should only
Asa@74 577 -- craft twice to get 10.
Asa@74 578 data.queue = ceil(data.queue / GetTradeSkillNumMade(i))
Asa@128 579
Asa@74 580 realData[row] = data
Asa@128 581 nameMap[skillName] = row
Asa@74 582 row = row + 1
Asa@59 583 end
Asa@59 584 end
Asa@59 585 end
Asa@99 586 table.sort(realData, function(a, b) return a.profit*max(1, a.queue) > b.profit*max(1, b.queue) end)
Asa@94 587
Asa@94 588 local numOwned = {}
Asa@124 589
Asa@94 590 for key, data in pairs(realData) do
Asa@126 591 data.haveMaterials = data.queue
Asa@94 592 for id, reagent in pairs(data.reagents) do
Asa@126 593 local needEach = reagent.count
Asa@122 594 reagent.count = reagent.count * data.queue
Asa@122 595
Asa@94 596 if not numOwned[reagent.link] then
Asa@94 597 numOwned[reagent.link] = ItemAuditor:GetItemCount(ItemAuditor:GetIDFromLink(reagent.link))
Asa@94 598 end
Asa@126 599 data.haveMaterials = min(data.haveMaterials, floor(numOwned[reagent.link] / needEach))
Asa@94 600 numOwned[reagent.link] = numOwned[reagent.link] - reagent.count
Asa@94 601
Asa@124 602 -- Vellums count in cost, but not against whether or not you have the mats.
Asa@124 603 -- I chose to do it this way because you can use a higher level of vellum
Asa@124 604 -- and I'm not sure the best way to determine cost and materials in that situation.
Asa@124 605 if numOwned[reagent.link] < 0 and not vellumLevelMap[reagent.itemID] then
Asa@94 606 reagent.need = min(reagent.count, abs(numOwned[reagent.link]))
Asa@94 607 end
Asa@94 608 end
Asa@126 609 data.haveMaterials = max(0, data.haveMaterials)
Asa@94 610 end
Asa@94 611
Asa@68 612 if craftingTable then
Asa@68 613 craftingTable:SetFilter(tableFilter)
Asa@68 614 self:RefreshCraftingTable()
Asa@68 615 end
Asa@60 616 end
Asa@60 617
Asa@60 618 function ItemAuditor:RefreshCraftingTable()
Asa@131 619 -- If the crafting table hasn't been created/displayed, there is no
Asa@131 620 -- reason to try to update it.
Asa@131 621 if not craftingTable then
Asa@131 622 return
Asa@131 623 end
Asa@128 624 tableData = {}
Asa@128 625 nameMap = {}
Asa@59 626 for key, data in pairs(realData) do
Asa@128 627 nameMap[data.name] = key
Asa@128 628
Asa@59 629 tableData[key] = {
Asa@59 630 data.name,
Asa@59 631 data.cost,
Asa@59 632 data.price,
Asa@59 633 data.winner,
Asa@99 634 abs(data.queue),
Asa@126 635 data.haveMaterials,
Asa@123 636 data.profit,
Asa@59 637 }
Asa@59 638 end
Asa@60 639 craftingTable:SetData(tableData, true)
Asa@133 640
Asa@60 641 if self:GetCraftingRow(1) then
Asa@60 642 btnProcess:Enable()
Asa@60 643 else
Asa@60 644 btnProcess:Disable()
Asa@60 645 end
Asa@59 646 end
Asa@59 647
Asa@59 648 function ItemAuditor:GetCraftingRow(row)
Asa@59 649 if craftingTable then
Asa@59 650 for _, index in pairs(craftingTable.sorttable) do
Asa@59 651 local tableRow = tableData[index]
Asa@59 652 if tableFilter(nil, tableRow) then
Asa@59 653 row = row - 1
Asa@59 654 if row == 0 then
Asa@59 655 return realData[index]
Asa@59 656 end
Asa@59 657 end
Asa@59 658 end
Asa@59 659 elseif realData then
Asa@59 660 return realData[row]
Asa@59 661 end
Asa@59 662 return nil
Asa@59 663 end
Asa@67 664 ItemAuditor.Options.args.crafting = {
Asa@67 665 type = "execute",
Asa@67 666 name = "crafting",
Asa@67 667 desc = "This opens a window to configure a crafting queue.",
Asa@67 668 func = "DisplayCrafting",
Asa@67 669 guiHidden = false,
Asa@67 670 }