annotate Modules/Crafting.lua @ 159:fbfd9dfa6d2b tip

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