annotate Modules/Crafting.lua @ 157:091bae7bfca0

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