Mercurial > wow > itemauditor
comparison Core.lua @ 0:169f5211fc7f
First public revision.
At this point ItemAuditor watches mail for auctions sold or purchased, watches for buy/sell (money and 1 item type change) and conversions/tradeskills. Milling isn't working yet because there is too much time between the first event and the last event.
author | Asa Ayers <Asa.Ayers@Gmail.com> |
---|---|
date | Thu, 20 May 2010 19:22:19 -0700 |
parents | |
children | 6c87720c301c |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:169f5211fc7f |
---|---|
1 local addon = LibStub("AceAddon-3.0"):NewAddon("ItemAuditor", "AceConsole-3.0", "AceEvent-3.0", "AceBucket-3.0") | |
2 | |
3 ItemAuditor = addon | |
4 | |
5 local WHITE = "|cFFFFFFFF" | |
6 local RED = "|cFFFF0000" | |
7 local GREEN = "|cFF00FF00" | |
8 local YELLOW = "|cFFFFFF00" | |
9 local ORANGE = "|cFFFF7F00" | |
10 local TEAL = "|cFF00FF9A" | |
11 local GOLD = "|cFFFFD700" | |
12 | |
13 function addon:OnInitialize() | |
14 -- declare defaults to be used in the DB | |
15 local DB_defaults = { | |
16 char = { | |
17 debug = false | |
18 }, | |
19 factionrealm = { | |
20 item_account = {} | |
21 }, | |
22 } | |
23 self.db = LibStub("AceDB-3.0"):New("ItemAuditorDB", DB_defaults, true) | |
24 self.db.factionrealm.backup = self.db.factionrealm.item_account | |
25 | |
26 self.db.char.debug = true | |
27 | |
28 --[[ | |
29 Fine Thread = 510 | |
30 Greater Magic Essence = 120000 | |
31 Simple Kilt = 5913 | |
32 Bolt of Linen Cloth = 5672 | |
33 ]] | |
34 | |
35 self:RegisterOptions() | |
36 | |
37 self:Debug("Hello, world! OnInitialize") | |
38 | |
39 self:RegisterEvent("MAIL_SHOW") | |
40 self:WatchBags() | |
41 end | |
42 | |
43 function IA_tcount(tab) | |
44 local n = #tab | |
45 if (n == 0) then | |
46 for _ in pairs(tab) do | |
47 n = n + 1 | |
48 end | |
49 end | |
50 return n | |
51 end | |
52 | |
53 | |
54 local options = { | |
55 name = "ItemAuditor", | |
56 handler = ItemAuditor, | |
57 type = 'group', | |
58 args = { | |
59 debug = { | |
60 type = "toggle", | |
61 name = "Debug", | |
62 desc = "Toggles debug messages in chat", | |
63 get = "GetDebug", | |
64 set = "SetDebug" | |
65 }, | |
66 dump = { | |
67 type = "execute", | |
68 name = "dump", | |
69 desc = "dumps IA database", | |
70 func = "DumpInfo", | |
71 }, | |
72 options = { | |
73 type = "execute", | |
74 name = "options", | |
75 desc = "Show Blizzard's options GUI", | |
76 func = "ShowOptionsGUI", | |
77 guiHidden = true, | |
78 }, | |
79 }, | |
80 } | |
81 | |
82 | |
83 function addon:DumpInfo() | |
84 self:Print("self.db.char") | |
85 DevTools_Dump(self.db.char) | |
86 self:Print("self.db.factionrealm") | |
87 DevTools_Dump(self.db.factionrealm) | |
88 end | |
89 | |
90 function addon:RegisterOptions() | |
91 self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("ItemAuditor", "ItemAuditor") | |
92 | |
93 LibStub("AceConfig-3.0"):RegisterOptionsTable("ItemAuditor", options, {"ia"}) | |
94 | |
95 self:RegisterChatCommand("fuck", "ChatCommand") | |
96 end | |
97 | |
98 function addon:GetMessage(info) | |
99 return self.message | |
100 end | |
101 | |
102 function addon:SetMessage(info, newValue) | |
103 self.message = newValue | |
104 end | |
105 | |
106 | |
107 function addon:ShowOptionsGUI() | |
108 InterfaceOptionsFrame_OpenToCategory(self.optionsFrame) | |
109 end | |
110 | |
111 function addon:GetDebug(info) | |
112 return self.db.char.debug | |
113 end | |
114 | |
115 function addon:SetDebug(info, input) | |
116 self.db.char.debug = input | |
117 local value = "off" | |
118 if input then | |
119 value = "on" | |
120 end | |
121 self:Print("Debugging is now: " .. value) | |
122 end | |
123 | |
124 | |
125 -- ================ DEBUG ================ | |
126 addon.OriginalRegisterEvent = addon.RegisterEvent | |
127 addon.OriginalUnregisterEvent = addon.UnregisterEvent | |
128 | |
129 function addon:RegisterEvent(event, callback, arg) | |
130 self:Debug("RegisterEvent " .. event ) | |
131 if arg ~= nil then | |
132 addon:OriginalRegisterEvent(event, callback, arg) | |
133 elseif callback ~= nil then | |
134 addon:OriginalRegisterEvent(event, callback) | |
135 else | |
136 addon:OriginalRegisterEvent(event) | |
137 end | |
138 end | |
139 | |
140 function addon:UnregisterEvent(event) | |
141 self:Debug("UnregisterEvent " .. event ) | |
142 addon:OriginalUnregisterEvent (event) | |
143 end | |
144 | |
145 -- ================ DEBUG ================ | |
146 | |
147 function addon:FormatMoney(money) | |
148 return Altoholic:GetMoneyString(money, WHITE, false) | |
149 end | |
150 | |
151 function addon:GetCurrentInventory() | |
152 local i = {} | |
153 local link | |
154 | |
155 for bagID = 0, NUM_BAG_SLOTS do | |
156 bagSize=GetContainerNumSlots(bagID) | |
157 for slotID = 0, bagSize do | |
158 itemID = GetContainerItemID(bagID, slotID); | |
159 | |
160 if itemID ~= nil then | |
161 _, itemCount, _, _, _= GetContainerItemInfo(bagID, slotID); | |
162 name = GetItemInfo(itemID) | |
163 if i[name] == nil then | |
164 i[name] = 0 | |
165 end | |
166 i[name] = i[name] + (itemCount or 0) | |
167 end | |
168 | |
169 end | |
170 | |
171 end | |
172 return {items = i, money = GetMoney()} | |
173 end | |
174 | |
175 function addon:GetInventoryDiff(pastInventory, current) | |
176 if current == nil then | |
177 current = self:GetCurrentInventory() | |
178 end | |
179 local diff = {} | |
180 | |
181 for name, count in pairs(current.items) do | |
182 if pastInventory.items[name] == nil then | |
183 diff[name] = count | |
184 self:Debug("1 diff[" .. name .. "]=" .. diff[name]) | |
185 elseif count - pastInventory.items[name] ~= 0 then | |
186 diff[name] = count - pastInventory.items[name] | |
187 self:Debug("2 diff[" .. name .. "]=" .. diff[name]) | |
188 end | |
189 end | |
190 | |
191 for name, count in pairs(pastInventory.items) do | |
192 if current.items[name] == nil then | |
193 diff[name] = -count | |
194 self:Debug("3 diff[" .. name .. "]=" .. diff[name]) | |
195 elseif current.items[name] - count ~= 0 then | |
196 diff[name] = current.items[name] - pastInventory.items[name] | |
197 self:Debug("4 diff[" .. name .. "]=" .. diff[name]) | |
198 end | |
199 end | |
200 | |
201 local moneyDiff = current.money - pastInventory.money | |
202 | |
203 return {items = diff, money = moneyDiff} | |
204 end | |
205 | |
206 | |
207 function addon:ScanMail() | |
208 local results = {} | |
209 for mailIndex = 1, GetInboxNumItems() or 0 do | |
210 local sender, msgSubject, msgMoney, msgCOD, _, msgItem, _, _, msgText, _, isGM = select(3, GetInboxHeaderInfo(mailIndex)) | |
211 local mailType = Postal:GetMailType(msgSubject) | |
212 | |
213 if mailType == "NonAHMail" then | |
214 -- Don't know how to handle these yet | |
215 elseif mailType == "AHSuccess" then | |
216 local invoiceType, itemName, playerName, bid, buyout, deposit, consignment = GetInboxInvoiceInfo(mailIndex); | |
217 if results[itemName] == nil then | |
218 results[itemName] = 0 | |
219 end | |
220 results[itemName] = results[itemName] + deposit + buyout - consignment | |
221 | |
222 elseif mailType == "AHWon" then | |
223 local invoiceType, itemName, playerName, bid, buyout, deposit, consignment = GetInboxInvoiceInfo(mailIndex); | |
224 if results[itemName] == nil then | |
225 results[itemName] = 0 | |
226 end | |
227 results[itemName] = results[itemName] - bid | |
228 elseif mailType == "AHExpired" or mailType == "AHCancelled" then | |
229 -- These should be handled when you pay the deposit at the AH | |
230 else | |
231 self:Debug("Unhandled mail type: " .. mailType) | |
232 self:Debug(msgSubject) | |
233 end | |
234 | |
235 end | |
236 return results | |
237 end | |
238 | |
239 function addon:MAIL_SHOW() | |
240 self:Debug("MAIL_SHOW") | |
241 self.lastMailScan = self:ScanMail() | |
242 self:UnregisterEvent("MAIL_SHOW") | |
243 self:RegisterEvent("MAIL_CLOSED") | |
244 self:RegisterEvent("MAIL_INBOX_UPDATE") | |
245 self:Debug("MAIL_SHOW complete") | |
246 -- the mail scanner will handle everything | |
247 -- self:UnwatchBags() | |
248 end | |
249 | |
250 function addon:MAIL_CLOSED() | |
251 addon:UnregisterEvent("MAIL_CLOSED") | |
252 self:UnregisterEvent("MAIL_INBOX_UPDATE") | |
253 self:RegisterEvent("MAIL_SHOW") | |
254 -- self:WatchBags() | |
255 end | |
256 | |
257 function addon:MAIL_INBOX_UPDATE() | |
258 local newScan = addon:ScanMail() | |
259 local diff | |
260 for item, total in pairs(self.lastMailScan) do | |
261 | |
262 if newScan[item] == nil then | |
263 newScan[item] = 0 | |
264 end | |
265 diff = total - newScan[item] | |
266 if diff ~= 0 then | |
267 self:SaveValue(item, diff) | |
268 end | |
269 | |
270 end | |
271 | |
272 self.lastMailScan = newScan | |
273 end | |
274 | |
275 function addon:SaveValue(item, value) | |
276 local item_account = self.db.factionrealm.item_account | |
277 if item_account[item] == nil then | |
278 item_account[item] = 0 | |
279 end | |
280 item_account[item] = item_account[item] + value | |
281 | |
282 if item_account[item] >= 0 then | |
283 item_account[item] = nil | |
284 end | |
285 end | |
286 | |
287 function addon:OnEnable() | |
288 self:Debug("Hello, world! OnEnable") | |
289 end | |
290 | |
291 function addon:Debug(msg) | |
292 if self.db.char.debug then | |
293 self:Print(msg) | |
294 end | |
295 end | |
296 | |
297 function addon:WatchBags() | |
298 if self.watch_handle == nil then | |
299 self.lastInventory = self:GetCurrentInventory() | |
300 self.watch_handle = self:RegisterBucketEvent({"BAG_UPDATE", "PLAYER_MONEY"}, 0.2, "UpdateAudit") | |
301 end | |
302 end | |
303 | |
304 function addon:UnwatchBags() | |
305 if self.watch_handle ~= nil then | |
306 self:UnregisterBucket(self.watch_handle) | |
307 self.watch_handle = nil | |
308 end | |
309 end | |
310 | |
311 function addon:UpdateAudit() | |
312 self:Debug("UpdateAudit") | |
313 local currentInventory = self:GetCurrentInventory() | |
314 local diff = addon:GetInventoryDiff(self.lastInventory, currentInventory) | |
315 -- this is only here for debugging | |
316 self.lastdiff = diff | |
317 | |
318 if abs(diff.money) > 0 and IA_tcount(diff.items) == 1 then | |
319 self:Debug("purchase or sale") | |
320 | |
321 for itemName, count in pairs(diff.items) do | |
322 self:SaveValue(itemName, diff.money) | |
323 end | |
324 elseif IA_tcount(diff.items) > 1 then | |
325 local positive, negative = {}, {} | |
326 local positiveCount, negativeCount = 0, 0 | |
327 for item, count in pairs(diff.items) do | |
328 if count > 0 then | |
329 positive[item] = count | |
330 positiveCount = positiveCount + count | |
331 elseif count < 0 then | |
332 negative[item] = count | |
333 negativeCount = negativeCount + abs(count) | |
334 end | |
335 end | |
336 | |
337 if IA_tcount(positive) > 0 and IA_tcount(negative) > 0 then | |
338 -- we must have created/converted something | |
339 self:Debug("conversion") | |
340 local totalChange = 0 | |
341 for itemName, change in pairs(negative) do | |
342 local _, itemCost, count = self:GetItemCost(itemName, change) | |
343 self:SaveValue(itemName, abs(itemCost * change)) | |
344 | |
345 totalChange = totalChange + abs(itemCost * change) | |
346 end | |
347 | |
348 self:Debug("totalChange") | |
349 self:Debug(totalChange) | |
350 | |
351 local valuePerItem = totalChange / positiveCount | |
352 self:Debug(valuePerItem ) | |
353 for itemName, change in pairs(positive) do | |
354 self:Debug(itemName) | |
355 self:Debug(0-abs(valuePerItem * change)) | |
356 self:SaveValue(itemName, 0-abs(valuePerItem * change)) | |
357 end | |
358 end | |
359 end | |
360 | |
361 self.lastInventory = currentInventory | |
362 end | |
363 -- /run ItemAuditor.db.factionrealm.item_account["Tiger Lily"] = -586625 | |
364 -- /run ItemAuditor.db.factionrealm.item_account["Icy Pigment"] = -12303 | |
365 -- /run ItemAuditor.db.factionrealm.item_account["Azure Pigment"] = -258357 | |
366 | |
367 function addon:GetItemCost(itemName, countModifier) | |
368 local invested = abs(self.db.factionrealm.item_account[itemName] or 0) | |
369 | |
370 if invested > 0 then | |
371 local _, itemLink = GetItemInfo (itemName); | |
372 local _, _, _, _, Id = string.find(itemLink, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?") | |
373 local count = Altoholic:GetItemCount(tonumber(Id)) | |
374 if countModifier ~= nil then | |
375 count = count - countModifier | |
376 end | |
377 if count == 0 then | |
378 self.db.factionrealm.item_account[itemName] = nil | |
379 self:Print("You ran out of " .. itemName .. "and never recovered " .. self:FormatMoney(invested)) | |
380 return 0, 0, 0 | |
381 end | |
382 return ceil(invested), ceil(invested/count), count | |
383 end | |
384 return 0, 0, 0 | |
385 end | |
386 | |
387 function addon:ShowTooltip(tip, link, num) | |
388 if (link == nil) then | |
389 return; | |
390 end | |
391 | |
392 local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, _, _, _, _, itemVendorPrice = GetItemInfo (link); | |
393 -- local _, _, Color, Ltype, Id, Enchant, Gem1, Gem2, Gem3, Gem4, Suffix, Unique, LinkLvl, Name = string.find(link, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?") | |
394 | |
395 local investedTotal, investedPerItem, count = self:GetItemCost(itemName) | |
396 | |
397 local AHCut = 0.05 | |
398 local keep = 1 - AHCut | |
399 | |
400 if investedTotal > 0 then | |
401 tip:AddDoubleLine("\124cffffffffIA: Total Invested", self:FormatMoney(investedTotal)); | |
402 tip:AddDoubleLine("\124cffffffffIA: Invested/Item (" .. count .. ")", self:FormatMoney(ceil(investedPerItem))); | |
403 tip:AddDoubleLine("\124cffffffffIA: Minimum faction AH Price: ", self:FormatMoney(ceil(investedPerItem/keep))) | |
404 tip:Show() | |
405 end | |
406 end | |
407 | |
408 local function ShowTipWithPricing(tip, link, num) | |
409 addon:ShowTooltip(tip, link, num) | |
410 end | |
411 | |
412 hooksecurefunc (GameTooltip, "SetBagItem", | |
413 function(tip, bag, slot) | |
414 local _, num = GetContainerItemInfo(bag, slot); | |
415 ShowTipWithPricing (tip, GetContainerItemLink(bag, slot), num); | |
416 end | |
417 ); | |
418 | |
419 | |
420 hooksecurefunc (GameTooltip, "SetAuctionItem", | |
421 function (tip, type, index) | |
422 ShowTipWithPricing (tip, GetAuctionItemLink(type, index)); | |
423 end | |
424 ); | |
425 | |
426 hooksecurefunc (GameTooltip, "SetAuctionSellItem", | |
427 function (tip) | |
428 local name, _, count = GetAuctionSellItemInfo(); | |
429 local __, link = GetItemInfo(name); | |
430 ShowTipWithPricing (tip, link, num); | |
431 end | |
432 ); | |
433 | |
434 | |
435 hooksecurefunc (GameTooltip, "SetLootItem", | |
436 function (tip, slot) | |
437 if LootSlotIsItem(slot) then | |
438 local link, _, num = GetLootSlotLink(slot); | |
439 ShowTipWithPricing (tip, link, num); | |
440 end | |
441 end | |
442 ); | |
443 | |
444 hooksecurefunc (GameTooltip, "SetLootRollItem", | |
445 function (tip, slot) | |
446 local _, _, num = GetLootRollItemInfo(slot); | |
447 ShowTipWithPricing (tip, GetLootRollItemLink(slot), num); | |
448 end | |
449 ); | |
450 | |
451 | |
452 hooksecurefunc (GameTooltip, "SetInventoryItem", | |
453 function (tip, unit, slot) | |
454 ShowTipWithPricing (tip, GetInventoryItemLink(unit, slot), GetInventoryItemCount(unit, slot)); | |
455 end | |
456 ); | |
457 | |
458 hooksecurefunc (GameTooltip, "SetGuildBankItem", | |
459 function (tip, tab, slot) | |
460 local _, num = GetGuildBankItemInfo(tab, slot); | |
461 ShowTipWithPricing (tip, GetGuildBankItemLink(tab, slot), num); | |
462 end | |
463 ); | |
464 | |
465 hooksecurefunc (GameTooltip, "SetTradeSkillItem", | |
466 function (tip, skill, id) | |
467 local link = GetTradeSkillItemLink(skill); | |
468 local num = GetTradeSkillNumMade(skill); | |
469 if id then | |
470 link = GetTradeSkillReagentItemLink(skill, id); | |
471 num = select (3, GetTradeSkillReagentInfo(skill, id)); | |
472 end | |
473 | |
474 ShowTipWithPricing (tip, link, num); | |
475 end | |
476 ); | |
477 | |
478 hooksecurefunc (GameTooltip, "SetTradePlayerItem", | |
479 function (tip, id) | |
480 local _, _, num = GetTradePlayerItemInfo(id); | |
481 ShowTipWithPricing (tip, GetTradePlayerItemLink(id), num); | |
482 end | |
483 ); | |
484 | |
485 hooksecurefunc (GameTooltip, "SetTradeTargetItem", | |
486 function (tip, id) | |
487 local _, _, num = GetTradeTargetItemInfo(id); | |
488 ShowTipWithPricing (tip, GetTradeTargetItemLink(id), num); | |
489 end | |
490 ); | |
491 | |
492 hooksecurefunc (GameTooltip, "SetQuestItem", | |
493 function (tip, type, index) | |
494 local _, _, num = GetQuestItemInfo(type, index); | |
495 ShowTipWithPricing (tip, GetQuestItemLink(type, index), num); | |
496 end | |
497 ); | |
498 | |
499 hooksecurefunc (GameTooltip, "SetQuestLogItem", | |
500 function (tip, type, index) | |
501 local num, _; | |
502 if type == "choice" then | |
503 _, _, num = GetQuestLogChoiceInfo(index); | |
504 else | |
505 _, _, num = GetQuestLogRewardInfo(index) | |
506 end | |
507 | |
508 ShowTipWithPricing (tip, GetQuestLogItemLink(type, index), num); | |
509 end | |
510 ); | |
511 | |
512 hooksecurefunc (GameTooltip, "SetInboxItem", | |
513 function (tip, index, attachIndex) | |
514 local _, _, num = GetInboxItem(index, attachIndex); | |
515 ShowTipWithPricing (tip, GetInboxItemLink(index, attachIndex), num); | |
516 end | |
517 ); | |
518 | |
519 hooksecurefunc (GameTooltip, "SetSendMailItem", | |
520 function (tip, id) | |
521 local name, _, num = GetSendMailItem(id) | |
522 local name, link = GetItemInfo(name); | |
523 ShowTipWithPricing (tip, link, num); | |
524 end | |
525 ); | |
526 | |
527 hooksecurefunc (GameTooltip, "SetHyperlink", | |
528 function (tip, itemstring, num) | |
529 local name, link = GetItemInfo (itemstring); | |
530 ShowTipWithPricing (tip, link, num); | |
531 end | |
532 ); | |
533 | |
534 hooksecurefunc (ItemRefTooltip, "SetHyperlink", | |
535 function (tip, itemstring) | |
536 local name, link = GetItemInfo (itemstring); | |
537 ShowTipWithPricing (tip, link); | |
538 end | |
539 ); |