annotate Modules/Crafting.lua @ 127:4f26dc55455d

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