Asa@63
|
1 local ItemAuditor = select(2, ...)
|
Asa@63
|
2 local Crafting = ItemAuditor:NewModule("Crafting")
|
Asa@59
|
3
|
Asa@59
|
4 local AceGUI = LibStub("AceGUI-3.0")
|
Asa@59
|
5 local ScrollingTable = LibStub("ScrollingTable")
|
Asa@59
|
6
|
Asa@59
|
7 local validateMoney = ItemAuditor.validateMoney
|
Asa@59
|
8 local parseMoney = ItemAuditor.parseMoney
|
Asa@59
|
9
|
Asa@59
|
10 local realData = {}
|
Asa@59
|
11
|
Asa@67
|
12
|
Asa@68
|
13 local queueDestinations = {}
|
Asa@68
|
14
|
Asa@68
|
15 function Crafting.RegisterQueueDestination(name, destination)
|
Asa@68
|
16 queueDestinations[name] = destination
|
Asa@68
|
17 end
|
Asa@68
|
18
|
Asa@67
|
19 -- TODO: Convert this to a text field.
|
Asa@67
|
20 local craftingThresholds = {5000, 10000, 50000}
|
Asa@67
|
21 local craftingThresholdsDisplay = {}
|
Asa@67
|
22
|
Asa@67
|
23 for key, value in pairs(craftingThresholds) do
|
Asa@67
|
24 craftingThresholdsDisplay[key] = ItemAuditor:FormatMoney(value, '', true)
|
Asa@67
|
25 -- craftingThresholdsDisplay[key] = value
|
Asa@67
|
26 end
|
Asa@67
|
27
|
Asa@68
|
28 function ItemAuditor:GetCraftingThreshold()
|
Asa@68
|
29 local key = ItemAuditor.db.char.crafting_threshold
|
Asa@68
|
30 return craftingThresholds[key]
|
Asa@68
|
31 end
|
Asa@68
|
32
|
Asa@67
|
33 ItemAuditor.Options.args.crafting_options = {
|
Asa@67
|
34 name = "Crafting with Skillet",
|
Asa@67
|
35 desc = "/ia queue",
|
Asa@67
|
36 type = 'group',
|
Asa@67
|
37 disabled = function() return Skillet == nil end,
|
Asa@67
|
38 args = {
|
Asa@67
|
39 crafting_threshold = {
|
Asa@67
|
40 type = "select",
|
Asa@67
|
41 name = "Crafting Threshold",
|
Asa@67
|
42 desc = "Don't create items that will make less than this amount of profit",
|
Asa@67
|
43 values = craftingThresholdsDisplay,
|
Asa@67
|
44 get = function() return ItemAuditor.db.char.crafting_threshold end,
|
Asa@67
|
45 set = function(info, value) ItemAuditor.db.char.crafting_threshold = value end,
|
Asa@67
|
46 order = 11,
|
Asa@67
|
47 },
|
Asa@67
|
48 },
|
Asa@67
|
49 }
|
Asa@67
|
50
|
Asa@59
|
51 local function displayMoney(rowFrame, cellFrame, data, cols, row, realrow, column, fShow, table, ...)
|
Asa@59
|
52 if fShow == true then
|
Asa@59
|
53 local money = data[realrow][column]
|
Asa@59
|
54 if money then
|
Asa@59
|
55 cellFrame.text:SetText(ItemAuditor:FormatMoney(tonumber(money)))
|
Asa@59
|
56 else
|
Asa@59
|
57 cellFrame.text:SetText("")
|
Asa@59
|
58 end
|
Asa@59
|
59
|
Asa@59
|
60 end
|
Asa@59
|
61 end
|
Asa@59
|
62
|
Asa@59
|
63 local craftingCols = {
|
Asa@59
|
64 { name= "Item", width = 200, defaultsort = "desc",
|
Asa@59
|
65 ['DoCellUpdate'] = function(rowFrame, cellFrame, data, cols, row, realrow, column, fShow, table, ...)
|
Asa@59
|
66 if fShow == true then
|
Asa@59
|
67 local data = realData[realrow]
|
Asa@59
|
68 cellFrame.text:SetText(data.link)
|
Asa@59
|
69 end
|
Asa@59
|
70 end,
|
Asa@59
|
71 },
|
Asa@59
|
72 { name= "Cost Each", width = 100, align = "RIGHT",
|
Asa@59
|
73 ['DoCellUpdate'] = displayMoney,
|
Asa@59
|
74 },
|
Asa@59
|
75 { name= "Est Sale Each", width = 100, align = "RIGHT",
|
Asa@59
|
76 ['DoCellUpdate'] = displayMoney,
|
Asa@59
|
77 },
|
Asa@59
|
78 { name= "Decided By", width = 100, align = "RIGHT",
|
Asa@59
|
79
|
Asa@59
|
80 },
|
Asa@59
|
81 { name= "craft", width = 50, align = "RIGHT",
|
Asa@59
|
82
|
Asa@59
|
83 },
|
Asa@59
|
84 { name= "Total Profit", width = 100, align = "RIGHT",
|
Asa@59
|
85 ['DoCellUpdate'] = displayMoney,
|
Asa@59
|
86 },
|
Asa@59
|
87 }
|
Asa@59
|
88
|
Asa@68
|
89 function Crafting.ExportToSkillet(data)
|
Asa@68
|
90 local skillString = select(3, string.find(data.recipeLink, "^|%x+|H(.+)|h%[.+%]"))
|
Asa@68
|
91 local _, skillId = strsplit(":", skillString)
|
Asa@68
|
92
|
Asa@68
|
93 ItemAuditor:AddToQueue(skillId,tradeSkillIndex, data.queue)
|
Asa@68
|
94 end
|
Asa@68
|
95
|
Asa@68
|
96 Crafting.RegisterQueueDestination('Skillet', Crafting.ExportToSkillet)
|
Asa@68
|
97
|
Asa@68
|
98
|
Asa@68
|
99
|
Asa@68
|
100 function Crafting.Export(destination)
|
Asa@68
|
101 if type(destination) == 'function' then
|
Asa@68
|
102 -- do nothing
|
Asa@68
|
103 elseif destination == nil then
|
Asa@68
|
104 destination = queueDestinations['Skillet']
|
Asa@68
|
105 elseif type(destination) == 'string' then
|
Asa@68
|
106 destination = queueDestinations[destination]
|
Asa@68
|
107 else
|
Asa@68
|
108 error('destination must be a function or a string')
|
Asa@68
|
109 end
|
Asa@68
|
110
|
Asa@59
|
111 local index = 1
|
Asa@59
|
112 local data = ItemAuditor:GetCraftingRow(index)
|
Asa@59
|
113 while data do
|
Asa@68
|
114 if data.queue > 0 then
|
Asa@68
|
115 destination(data)
|
Asa@68
|
116 end
|
Asa@61
|
117 index = index + 1
|
Asa@61
|
118 data = ItemAuditor:GetCraftingRow(index)
|
Asa@59
|
119
|
Asa@59
|
120 end
|
Asa@59
|
121 end
|
Asa@59
|
122
|
Asa@59
|
123 local craftingContent = false
|
Asa@59
|
124 local craftingTable = false
|
Asa@60
|
125 local btnProcess = false
|
Asa@59
|
126 local function ShowCrafting(container)
|
Asa@59
|
127 if craftingContent == false then
|
Asa@59
|
128 local window = container.frame
|
Asa@59
|
129 craftingContent = CreateFrame("Frame",nil,window)
|
Asa@59
|
130 craftingContent:SetBackdropColor(0, 0, 1, 0.5)
|
Asa@59
|
131 craftingContent:SetBackdropBorderColor(1, 0, 0, 1)
|
Asa@59
|
132
|
Asa@59
|
133 craftingContent:SetPoint("TOPLEFT", window, 10, -50)
|
Asa@59
|
134 craftingContent:SetPoint("BOTTOMRIGHT",window, -10, 10)
|
Asa@59
|
135
|
Asa@59
|
136 craftingTable = ScrollingTable:CreateST(craftingCols, 22, nil, nil, craftingContent )
|
Asa@59
|
137
|
Asa@59
|
138 IAcc = craftingContent
|
Asa@59
|
139 IAccWindow = window
|
Asa@59
|
140 craftingTable.frame:SetPoint("TOPLEFT",craftingContent, 0,0)
|
Asa@59
|
141 craftingTable.frame:SetPoint("BOTTOMRIGHT", craftingContent, 0, 30)
|
Asa@59
|
142
|
Asa@59
|
143 craftingTable:RegisterEvents({
|
Asa@59
|
144 ["OnEnter"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...)
|
Asa@59
|
145 if realrow then
|
Asa@59
|
146 local data = realData[realrow]
|
Asa@59
|
147
|
Asa@59
|
148 GameTooltip:SetOwner(rowFrame, "ANCHOR_CURSOR")
|
Asa@59
|
149 GameTooltip:SetHyperlink(data.link)
|
Asa@59
|
150 GameTooltip:Show()
|
Asa@59
|
151 end
|
Asa@59
|
152 end,
|
Asa@59
|
153 ["OnLeave"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...)
|
Asa@59
|
154 GameTooltip:Hide()
|
Asa@59
|
155 end,
|
Asa@59
|
156 });
|
Asa@59
|
157
|
Asa@59
|
158
|
Asa@59
|
159 btnProcess = CreateFrame("Button", nil, craftingContent, "UIPanelButtonTemplate")
|
Asa@59
|
160 btnProcess:SetText("Process")
|
Asa@59
|
161 btnProcess:SetSize(100, 25)
|
Asa@59
|
162 btnProcess:SetPoint("BOTTOMRIGHT", craftingContent, 0, 0)
|
Asa@59
|
163 btnProcess:RegisterForClicks("LeftButtonUp");
|
Asa@59
|
164
|
Asa@60
|
165 local function UpdateProcessTooltip(btn)
|
Asa@59
|
166 local data = ItemAuditor:GetCraftingRow(1)
|
Asa@59
|
167 if data then
|
Asa@59
|
168 GameTooltip:SetOwner(this, "ANCHOR_CURSOR")
|
Asa@59
|
169 GameTooltip:SetText(format('Create %sx%s', data.link, data.queue))
|
Asa@59
|
170 GameTooltip:Show()
|
Asa@59
|
171 end
|
Asa@60
|
172 end
|
Asa@60
|
173 btnProcess:SetScript("OnClick", function (self, button, down)
|
Asa@60
|
174 local data = ItemAuditor:GetCraftingRow(1)
|
Asa@60
|
175 if data then
|
Asa@60
|
176 ItemAuditor:Print('Crafting %sx%s', data.link, data.queue)
|
Asa@60
|
177 DoTradeSkill(data.tradeSkillIndex, data.queue)
|
Asa@60
|
178 data.queue = 0
|
Asa@60
|
179 ItemAuditor:RefreshCraftingTable()
|
Asa@60
|
180 UpdateProcessTooltip()
|
Asa@60
|
181 end
|
Asa@59
|
182 end)
|
Asa@59
|
183
|
Asa@60
|
184 btnProcess:SetScript("OnEnter", UpdateProcessTooltip)
|
Asa@60
|
185
|
Asa@59
|
186 btnProcess:SetScript("OnLeave", function()
|
Asa@59
|
187 GameTooltip:Hide()
|
Asa@59
|
188 end)
|
Asa@59
|
189
|
Asa@59
|
190 btnSkillet = CreateFrame("Button", nil, craftingContent, "UIPanelButtonTemplate")
|
Asa@59
|
191 btnSkillet:SetText("Queue in Skillet")
|
Asa@59
|
192 btnSkillet:SetSize(125, 25)
|
Asa@59
|
193 btnSkillet:SetPoint("BOTTOMRIGHT", btnProcess, 'BOTTOMLEFT', 0, 0)
|
Asa@59
|
194 btnSkillet:RegisterForClicks("LeftButtonUp");
|
Asa@59
|
195 btnSkillet:SetScript("OnClick", function (self, button, down)
|
Asa@59
|
196 ExportToSkillet()
|
Asa@59
|
197 end)
|
Asa@59
|
198
|
Asa@59
|
199 end
|
Asa@59
|
200 craftingContent:Show()
|
Asa@59
|
201
|
Asa@59
|
202 if container.parent then
|
Asa@59
|
203 local width = 80
|
Asa@59
|
204 for i, data in pairs(craftingCols) do
|
Asa@59
|
205 width = width + data.width
|
Asa@59
|
206 end
|
Asa@59
|
207 container.parent:SetWidth(width);
|
Asa@59
|
208 end
|
Asa@59
|
209
|
Asa@59
|
210 ItemAuditor:RegisterEvent("TRADE_SKILL_SHOW", function()
|
Asa@59
|
211 if craftingContent and craftingContent:IsVisible() then
|
Asa@59
|
212 ItemAuditor:UpdateCraftingTable()
|
Asa@59
|
213 end
|
Asa@59
|
214 end)
|
Asa@59
|
215 ItemAuditor:UpdateCraftingTable()
|
Asa@59
|
216
|
Asa@59
|
217 return craftingContent
|
Asa@59
|
218 end
|
Asa@59
|
219
|
Asa@59
|
220
|
Asa@59
|
221
|
Asa@59
|
222 ItemAuditor:RegisterTab('Crafting', 'tab_crafting', ShowCrafting)
|
Asa@59
|
223 function ItemAuditor:DisplayCrafting()
|
Asa@59
|
224 self:CreateFrame('tab_crafting')
|
Asa@59
|
225 end
|
Asa@59
|
226
|
Asa@59
|
227 local craftingDeciders = {}
|
Asa@59
|
228
|
Asa@64
|
229 function Crafting.RegisterCraftingDecider(name, decider)
|
Asa@59
|
230 craftingDeciders[name] = decider
|
Asa@59
|
231 end
|
Asa@59
|
232
|
Asa@59
|
233 local lastWinnder = ""
|
Asa@59
|
234 local function Decide(data)
|
Asa@59
|
235 local newDecision = 0
|
Asa@59
|
236 for name, decider in pairs(craftingDeciders) do
|
Asa@59
|
237 if name ~= lastWinner then
|
Asa@59
|
238 newDecision = decider(data)
|
Asa@59
|
239 if newDecision > data.queue then
|
Asa@59
|
240 data.queue = newDecision
|
Asa@59
|
241 lastWinner = name
|
Asa@59
|
242 return Decide(data)
|
Asa@59
|
243 elseif newDecision < 0 then
|
Asa@59
|
244 lastWinner = ""
|
Asa@59
|
245 return 'VETO: '..name, 0
|
Asa@59
|
246 end
|
Asa@59
|
247 end
|
Asa@59
|
248 end
|
Asa@59
|
249
|
Asa@59
|
250 winner = lastWinner
|
Asa@59
|
251 lastWinner = ""
|
Asa@59
|
252
|
Asa@59
|
253 return winner, data.queue
|
Asa@59
|
254 end
|
Asa@59
|
255
|
Asa@59
|
256 local function isProfitable(data)
|
Asa@59
|
257 if data.profit > 0 and data.profit > ItemAuditor:GetCraftingThreshold() then
|
Asa@59
|
258 return 1
|
Asa@59
|
259 end
|
Asa@59
|
260 return -1
|
Asa@59
|
261 end
|
Asa@64
|
262 Crafting.RegisterCraftingDecider('Is Profitable', isProfitable)
|
Asa@59
|
263
|
Asa@59
|
264 local function tableFilter(self, row, ...)
|
Asa@59
|
265 -- column 5 is how many should be crafted
|
Asa@59
|
266 return row[5] > 0
|
Asa@59
|
267 end
|
Asa@59
|
268
|
Asa@59
|
269 local tableData = {}
|
Asa@59
|
270 function ItemAuditor:UpdateCraftingTable()
|
Asa@59
|
271 if LSW == nil then
|
Asa@59
|
272 self:Print("This feature requires LilSparky's Workshop.")
|
Asa@59
|
273 return
|
Asa@59
|
274 end
|
Asa@59
|
275 if Skillet == nil then
|
Asa@59
|
276 self:Print("This feature requires Skillet.")
|
Asa@59
|
277 return
|
Asa@59
|
278 end
|
Asa@59
|
279 if GetAuctionBuyout ~= nil then
|
Asa@59
|
280 elseif AucAdvanced and AucAdvanced.Version then
|
Asa@59
|
281 else
|
Asa@59
|
282 self:Print("This feature requires Auctionator, Auctioneer, AuctionLite, or AuctionMaster.")
|
Asa@59
|
283 return
|
Asa@59
|
284 end
|
Asa@59
|
285 wipe(realData)
|
Asa@59
|
286 wipe(tableData)
|
Asa@59
|
287
|
Asa@59
|
288 local profitableItems = {}
|
Asa@59
|
289 local profitableIndex = 1
|
Asa@59
|
290 local numChecked = 0
|
Asa@59
|
291 local row = 1
|
Asa@59
|
292
|
Asa@59
|
293 for i = 1, GetNumTradeSkills() do
|
Asa@59
|
294 local itemLink = GetTradeSkillItemLink(i)
|
Asa@59
|
295 local itemId = Skillet:GetItemIDFromLink(itemLink)
|
Asa@59
|
296
|
Asa@59
|
297 --Figure out if its an enchant or not
|
Asa@59
|
298 _, _, _, _, altVerb = GetTradeSkillInfo(i)
|
Asa@59
|
299 if LSW.scrollData[itemId] ~= nil and altVerb == 'Enchant' then
|
Asa@59
|
300 -- Ask LSW for the correct scroll
|
Asa@59
|
301 itemId = LSW.scrollData[itemId]["scrollID"]
|
Asa@59
|
302 end
|
Asa@59
|
303
|
Asa@59
|
304 local recipeLink = GetTradeSkillRecipeLink(i)
|
Asa@59
|
305 local stackSize = 1
|
Asa@59
|
306 if recipeLink ~= nil and itemId ~= nil then
|
Asa@59
|
307 local skillName, skillType, numAvailable, isExpanded, altVerb = GetTradeSkillInfo(i)
|
Asa@59
|
308 local itemName, itemLink= GetItemInfo(itemId)
|
Asa@59
|
309
|
Asa@59
|
310 local count = Altoholic:GetItemCount(itemId)
|
Asa@59
|
311 local reagents = {}
|
Asa@59
|
312 local totalCost = 0
|
Asa@59
|
313 for reagentId = 1, GetTradeSkillNumReagents(i) do
|
Asa@59
|
314 local reagentName, _, reagentCount = GetTradeSkillReagentInfo(i, reagentId);
|
Asa@59
|
315 local reagentLink = GetTradeSkillReagentItemLink(i, reagentId)
|
Asa@59
|
316
|
Asa@59
|
317 reagents[reagentId] = {
|
Asa@59
|
318 name = reagentName,
|
Asa@59
|
319 count = reagentCount,
|
Asa@59
|
320 price = self:GetReagentCost(reagentLink, reagentCount),
|
Asa@59
|
321 }
|
Asa@59
|
322 totalCost = totalCost + self:GetReagentCost(reagentLink, reagentCount)
|
Asa@59
|
323 end
|
Asa@59
|
324
|
Asa@59
|
325 local data = {
|
Asa@59
|
326 recipeLink = recipeLink,
|
Asa@59
|
327 link = itemLink,
|
Asa@59
|
328 name = itemName,
|
Asa@59
|
329 count = count,
|
Asa@59
|
330 price = (self:GetAuctionPrice(itemLink) or 0),
|
Asa@59
|
331 cost = totalCost,
|
Asa@59
|
332 profit = (self:GetAuctionPrice(itemLink) or 0) - totalCost,
|
Asa@59
|
333 reagents = reagents,
|
Asa@59
|
334 count = count,
|
Asa@59
|
335 tradeSkillIndex = i,
|
Asa@59
|
336 queue = 0,
|
Asa@59
|
337 winner = "",
|
Asa@59
|
338 }
|
Asa@59
|
339
|
Asa@59
|
340 data.winner, data.queue = Decide(data)
|
Asa@59
|
341 data.queue = data.queue - count
|
Asa@59
|
342
|
Asa@59
|
343 -- If a tradeskill makes 5 at a time and something asks for 9, we should only
|
Asa@59
|
344 -- craft twice to get 10.
|
Asa@59
|
345 data.queue = ceil(data.queue / GetTradeSkillNumMade(i))
|
Asa@59
|
346
|
Asa@59
|
347 realData[row] = data
|
Asa@59
|
348 row = row + 1
|
Asa@59
|
349 end
|
Asa@59
|
350 end
|
Asa@59
|
351 table.sort(realData, function(a, b) return a.profit*a.queue > b.profit*b.queue end)
|
Asa@68
|
352 if craftingTable then
|
Asa@68
|
353 craftingTable:SetFilter(tableFilter)
|
Asa@68
|
354 self:RefreshCraftingTable()
|
Asa@68
|
355 end
|
Asa@60
|
356 end
|
Asa@60
|
357
|
Asa@60
|
358 function ItemAuditor:RefreshCraftingTable()
|
Asa@59
|
359 for key, data in pairs(realData) do
|
Asa@59
|
360 tableData[key] = {
|
Asa@59
|
361 data.name,
|
Asa@59
|
362 data.cost,
|
Asa@59
|
363 data.price,
|
Asa@59
|
364 data.winner,
|
Asa@59
|
365 data.queue,
|
Asa@59
|
366 data.profit*data.queue,
|
Asa@59
|
367 }
|
Asa@59
|
368 end
|
Asa@60
|
369 craftingTable:SetData(tableData, true)
|
Asa@59
|
370
|
Asa@60
|
371 if self:GetCraftingRow(1) then
|
Asa@60
|
372 btnProcess:Enable()
|
Asa@60
|
373 else
|
Asa@60
|
374 btnProcess:Disable()
|
Asa@60
|
375 end
|
Asa@59
|
376 end
|
Asa@59
|
377
|
Asa@59
|
378 function ItemAuditor:GetCraftingRow(row)
|
Asa@59
|
379 if craftingTable then
|
Asa@59
|
380 for _, index in pairs(craftingTable.sorttable) do
|
Asa@59
|
381 local tableRow = tableData[index]
|
Asa@59
|
382 if tableFilter(nil, tableRow) then
|
Asa@59
|
383 row = row - 1
|
Asa@59
|
384 if row == 0 then
|
Asa@59
|
385 return realData[index]
|
Asa@59
|
386 end
|
Asa@59
|
387 end
|
Asa@59
|
388 end
|
Asa@59
|
389 elseif realData then
|
Asa@59
|
390 return realData[row]
|
Asa@59
|
391 end
|
Asa@59
|
392 return nil
|
Asa@59
|
393 end
|
Asa@67
|
394 ItemAuditor.Options.args.crafting = {
|
Asa@67
|
395 type = "execute",
|
Asa@67
|
396 name = "crafting",
|
Asa@67
|
397 desc = "This opens a window to configure a crafting queue.",
|
Asa@67
|
398 func = "DisplayCrafting",
|
Asa@67
|
399 guiHidden = false,
|
Asa@67
|
400 }
|