Asa@63: local ItemAuditor = select(2, ...) Asa@137: local Utils Asa@144: ItemAuditor = LibStub("AceAddon-3.0"):NewAddon(ItemAuditor, "ItemAuditor", "AceEvent-3.0", "AceBucket-3.0", "AceSerializer-3.0", "AceTimer-3.0") Asa@65: --@debug@ Asa@65: _G['ItemAuditor'] = ItemAuditor Asa@65: --@end-debug@ Asa@0: Asa@87: if not DevTools_Dump then Asa@87: function DevTools_Dump() Asa@87: end Asa@87: end Asa@87: Asa@144: ItemAuditor.TRACKING_DATA_DIVIDER = "\n==ItemAuditor Tracking Data==\n" Asa@144: Asa@98: local allMailboxes = {} Asa@98: local myMailbox = {} Asa@67: Asa@67: ItemAuditor.Options = { Asa@67: handler = ItemAuditor, Asa@67: name = "ItemAuditor @project-version@", Asa@67: type = 'group', Asa@67: args = { Asa@67: options = { Asa@67: type = "execute", Asa@67: name = "options", Asa@67: desc = "Show Blizzard's options GUI", Asa@67: func = "ShowOptionsGUI", Asa@67: guiHidden = true, Asa@67: }, Asa@67: debug = { Asa@67: type = "execute", Asa@67: name = "debug", Asa@67: desc = "Shows the debug frame", Asa@67: func = function() ItemAuditor_DebugFrame:Show() end, Asa@67: guiHidden = true, Asa@67: }, Asa@67: suspend = { Asa@67: type = "toggle", Asa@67: name = "suspend", Asa@67: desc = "Suspends ItemAuditor", Asa@67: get = "IsEnabled", Asa@67: set = "SetEnabled", Asa@67: guiHidden = true, Asa@67: }, Asa@67: }, Asa@67: } Asa@67: Asa@100: ItemAuditor.DB_defaults = { Asa@100: char = { Asa@100: ah = 1, Asa@100: use_quick_auctions = false, Asa@101: profitable_threshold = 10000, Asa@100: auction_threshold = 0.15, Asa@111: auction_threshold_value = 0, Asa@100: qa_extra = 0, Asa@100: output_chat_frame = nil, Asa@109: cod_warnings = true, Asa@144: incoming_tracking_ids = {} Asa@100: }, Asa@100: profile = { Asa@100: messages = { Asa@100: cost_updates = true, Asa@100: queue_skip = false, Asa@100: }, Asa@100: ItemAuditor_enabled = true, Asa@100: queue_destination = nil, Asa@100: disabled_deciders = {}, Asa@100: pricing_method = 'low', Asa@100: }, Asa@100: factionrealm = { Asa@100: item_account = {}, Asa@100: items = {}, Asa@100: outbound_cod = {}, Asa@100: mailbox = {}, Asa@132: enabled_guilds = {}, Asa@100: }, Asa@100: } Asa@100: Asa@63: function ItemAuditor:OnInitialize() Asa@137: Utils = self:GetModule("Utils") Asa@100: self.db = LibStub("AceDB-3.0"):New("ItemAuditorDB", ItemAuditor.DB_defaults, true) Asa@98: Asa@98: allMailboxes = self.db.factionrealm.mailbox Asa@98: if not allMailboxes[UnitName("player")] then Asa@98: allMailboxes[UnitName("player")] = {} Asa@98: end Asa@98: myMailbox = allMailboxes[UnitName("player")] Asa@98: Asa@67: self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("ItemAuditor", "ItemAuditor") Asa@133: Asa@67: LibStub("AceConfig-3.0"):RegisterOptionsTable("ItemAuditor", ItemAuditor.Options, {"ia"}) Asa@38: ItemAuditor:RegisterFrame(ItemAuditor_DebugFrame) Asa@133: Asa@86: LibStub("AceConsole-3.0"):RegisterChatCommand('rl', ReloadUI) Asa@100: Asa@101: if self.db.char.crafting_threshold then Asa@101: local threshold = self.db.char.crafting_threshold Asa@101: if threshold == 1 then Asa@101: self.db.char.profitable_threshold = 5000 Asa@101: elseif threshold == 2 then Asa@101: self.db.char.profitable_threshold = 10000 Asa@101: elseif threshold == 3 then Asa@101: self.db.char.profitable_threshold = 50000 Asa@101: end Asa@133: Asa@101: self.db.char.crafting_threshold = nil Asa@101: end Asa@101: Asa@119: ItemAuditor:IsQAEnabled() Asa@112: Asa@65: --@debug@ Asa@59: -- ItemAuditor_DebugFrame:Show() Asa@59: -- self:CreateFrame('tab_crafting') Asa@74: self:RegisterEvent("TRADE_SKILL_SHOW", function() Asa@93: ItemAuditor:DisplayCrafting() Asa@74: end) Asa@65: --@end-debug@ Asa@0: end Asa@0: Asa@67: Asa@67: Asa@38: local registeredEvents = {} Asa@133: local originalRegisterEvent = ItemAuditor.RegisterEvent Asa@63: function ItemAuditor:RegisterEvent(event, callback, arg) Asa@38: registeredEvents[event] = true Asa@38: if arg ~= nil then Asa@38: return originalRegisterEvent(self, event, callback, arg) Asa@38: elseif callback ~= nil then Asa@38: return originalRegisterEvent(self, event, callback) Asa@38: else Asa@38: return originalRegisterEvent(self, event) Asa@38: end Asa@38: end Asa@38: Asa@63: local originalUnregisterEvent = ItemAuditor.UnregisterEvent Asa@63: function ItemAuditor:UnregisterEvent(event) Asa@38: registeredEvents[event] = nil Asa@38: return originalUnregisterEvent(self, event) Asa@38: end Asa@38: Asa@63: function ItemAuditor:UnregisterAllEvents() Asa@38: for event in pairs(registeredEvents) do Asa@38: self:UnregisterEvent(event) Asa@38: end Asa@38: end Asa@38: Asa@38: local registeredFrames = {} Asa@63: function ItemAuditor:RegisterFrame(frame) Asa@38: tinsert(registeredFrames, frame) Asa@38: end Asa@38: Asa@63: function ItemAuditor:HideAllFrames() Asa@38: for key, frame in pairs(registeredFrames) do Asa@38: if frame then Asa@38: frame:Hide() Asa@38: end Asa@38: end Asa@38: end Asa@38: Asa@63: function ItemAuditor:ConvertItems() Asa@8: for itemName, value in pairs(self.db.factionrealm.item_account) do Asa@15: local itemID = self:GetItemID(itemName) Asa@8: if itemID ~= nil then Asa@8: self:GetItem('item:' .. itemID) Asa@8: end Asa@8: if value == 0 then Asa@8: self.db.factionrealm.item_account[itemName] = nil Asa@8: end Asa@8: end Asa@133: Asa@8: for link, data in pairs(self.db.factionrealm.items) do Asa@8: if self:GetItem(link).count == 0 or self:GetItem(link).invested == 0 then Asa@8: self:RemoveItem(link) Asa@8: end Asa@10: end Asa@133: Asa@12: self:RefreshQAGroups() Asa@12: end Asa@12: Asa@133: -- Options doesn't exist when this file is created the first time, so getOptions will Asa@133: -- make one call to :GetModule and return the result and replace itself with a Asa@65: -- function that simply returns the same object. The permanent solution will probably be Asa@65: -- to move :Print to a different module. Asa@65: local function getOptions() Asa@65: local Options = ItemAuditor:GetModule("Options") Asa@65: getOptions = function() return Options end Asa@65: return Options Asa@65: end Asa@65: Asa@24: local printPrefix = "|cFFA3CEFFItemAuditor|r: " Asa@63: function ItemAuditor:Print(message, ...) Asa@24: message = format(message, ...) Asa@65: getOptions().GetSelectedChatWindow():AddMessage( printPrefix .. tostring(message)) Asa@16: end Asa@16: Asa@81: local bankOpen = false Asa@81: Asa@81: function ItemAuditor:BankFrameChanged(event) Asa@81: bankOpen = (event == 'BANKFRAME_OPENED') Asa@81: ItemAuditor:UpdateCurrentInventory() Asa@81: end Asa@81: Asa@152: local function getTotalFromBagsAndInventory(searchID) Asa@152: local character = DataStore:GetCharacter() Asa@152: local bags, bank = DataStore:GetContainerItemCount(character, searchID) Asa@152: local count = (bags or 0) Asa@152: if bankOpen then Asa@152: count = count + bank Asa@152: end Asa@152: count = count + (DataStore:GetInventoryItemCount(character, searchID) or 0) Asa@152: Asa@152: return count Asa@152: end Asa@152: Asa@80: local function scanBag(bagID, i) Asa@152: local bag = DataStore:GetContainer(DataStore:GetCharacter(), bagID) Asa@152: if bag then Asa@152: for slotID = 0, bag.size do Asa@152: local itemID = DataStore:GetSlotInfo(bag, slotID); Asa@80: Asa@152: if itemID and i[itemID] == nil then Asa@152: i[itemID] = getTotalFromBagsAndInventory(itemID); Asa@152: end Asa@80: end Asa@80: end Asa@80: end Asa@80: Asa@152: local NUM_EQUIPMENT_SLOTS = 19 Asa@63: function ItemAuditor:GetCurrentInventory() Asa@8: local i = {} Asa@8: local bagID Asa@8: local slotID Asa@133: Asa@8: for bagID = 0, NUM_BAG_SLOTS do Asa@80: scanBag(bagID, i) Asa@8: end Asa@133: Asa@81: if bankOpen then Asa@81: scanBag(BANK_CONTAINER, i) Asa@81: for bagID = NUM_BAG_SLOTS+1, NUM_BANKBAGSLOTS do Asa@81: scanBag(bagID, i) Asa@81: end Asa@80: end Asa@133: Asa@152: local character = DataStore:GetCharacter() Asa@152: for slotID = 1, NUM_EQUIPMENT_SLOTS do Asa@152: local link = DataStore:GetInventoryItem(character, slotID) Asa@152: itemID = link and Utils.GetItemID(link) Asa@152: Asa@152: if link and itemID and i[itemID] == nil then Asa@152: i[itemID] = getTotalFromBagsAndInventory(itemID); Asa@152: end Asa@152: end Asa@152: Asa@8: return {items = i, money = GetMoney()} Asa@0: end Asa@0: Asa@63: function ItemAuditor:GetInventoryDiff(pastInventory, current) Asa@8: if current == nil then Asa@8: current = self:GetCurrentInventory() Asa@8: end Asa@8: local diff = {} Asa@8: Asa@137: for itemID, count in pairs(current.items) do Asa@137: if pastInventory.items[itemID] == nil then Asa@137: diff[itemID] = count Asa@137: self:Debug("1 diff[" .. itemID .. "]=" .. diff[itemID]) Asa@137: elseif count - pastInventory.items[itemID] ~= 0 then Asa@137: diff[itemID] = count - pastInventory.items[itemID] Asa@137: self:Debug("2 diff[" .. itemID .. "]=" .. diff[itemID]) Asa@133: end Asa@8: end Asa@8: Asa@137: for itemID, count in pairs(pastInventory.items) do Asa@137: if current.items[itemID] == nil then Asa@137: diff[itemID] = -count Asa@139: self:Debug("3 diff[" .. itemID .. "]=" .. diff[itemID]) Asa@137: elseif current.items[itemID] - count ~= 0 then Asa@137: diff[itemID] = current.items[itemID] - pastInventory.items[itemID] Asa@137: self:Debug("4 diff[" .. itemID .. "]=" .. diff[itemID]) Asa@8: end Asa@8: end Asa@8: Asa@8: local moneyDiff = current.money - pastInventory.money Asa@23: if abs(moneyDiff) > 0 then Asa@23: self:Debug("moneyDiff: " .. moneyDiff) Asa@23: end Asa@8: Asa@8: return {items = diff, money = moneyDiff} Asa@0: end Asa@0: Asa@39: local inboundCOD = {} Asa@39: local skipMail = {} Asa@63: function ItemAuditor:ScanMail() Asa@0: local results = {} Asa@39: local CODPaymentRegex = gsub(COD_PAYMENT, "%%s", "(.*)") Asa@144: local ia_tracking = {} Asa@133: Asa@0: for mailIndex = 1, GetInboxNumItems() or 0 do Asa@39: local sender, msgSubject, msgMoney, msgCOD, daysLeft, msgItem, _, _, msgText, _, isGM = select(3, GetInboxHeaderInfo(mailIndex)) Asa@15: local mailType = self:GetMailType(msgSubject) Asa@133: Asa@39: local mailSignature = msgSubject .. '-' .. msgMoney .. '-' .. msgCOD .. '-' .. daysLeft Asa@133: Asa@6: results[mailType] = (results[mailType] or {}) Asa@133: Asa@39: if skipMail[mailSignature] ~= nil then Asa@39: -- do nothing Asa@39: elseif mailType == "NonAHMail" and msgCOD > 0 then Asa@6: mailType = 'COD' Asa@6: results[mailType] = (results[mailType] or {}) Asa@133: Asa@5: local itemTypes = {} Asa@5: for itemIndex = 1, ATTACHMENTS_MAX_RECEIVE do Asa@5: local itemName, _, count, _, _= GetInboxItem(mailIndex, itemIndex) Asa@5: if itemName ~= nil then Asa@39: itemTypes[itemName] = (itemTypes[itemName] or 0) + count Asa@5: end Asa@5: end Asa@133: Asa@15: if self:tcount(itemTypes) == 1 then Asa@5: for itemName, count in pairs(itemTypes) do Asa@39: results[mailType][itemName] = (results[mailType][itemName] or {total=0,count=0}) Asa@39: results[mailType][itemName].total = results[mailType][itemName].total + msgCOD Asa@133: Asa@39: if inboundCOD[mailSignature] == nil then Asa@39: results[mailType][itemName].count = results[mailType][itemName].count + count Asa@39: inboundCOD[mailSignature] = (inboundCOD[mailSignature] or 0) + count Asa@39: else Asa@39: results[mailType][itemName].count = inboundCOD[mailSignature] Asa@39: end Asa@133: Asa@133: Asa@5: end Asa@5: else Asa@5: self:Debug("Don't know what to do with more than one item type on COD mail.") Asa@5: end Asa@133: elseif mailType == "CODPayment" then Asa@39: -- /dump ItemAuditor.db.factionrealm.outbound_cod Asa@39: self:Debug(msgSubject) Asa@39: self:Debug(CODPaymentRegex) Asa@39: local outboundSubject = select(3, msgSubject:find(CODPaymentRegex)) Asa@39: local trackID Asa@39: if outboundSubject ~= nil then Asa@39: self:Debug(outboundSubject) Asa@45: trackID = select(3, outboundSubject:find('[[]IA: (%d*)[]]')) Asa@133: Asa@39: if trackID ~= nil then Asa@45: trackID = tonumber(trackID) Asa@45: self:Debug('COD ID: %s', trackID) Asa@39: local cod = self.db.factionrealm.outbound_cod[trackID] Asa@39: if cod == nil then Asa@39: skipMail[mailSignature] = true Asa@39: self:Print("WARNING: {%s} has an invalid ItemAuditor tracking number.", msgSubject) Asa@39: else Asa@39: itemName = trackID .. "|" .. cod['link'] Asa@133: Asa@133: Asa@39: results[mailType][itemName] = (results[mailType][itemName] or {total=0,count=0}) Asa@39: results[mailType][itemName].total = results[mailType][itemName].total - msgMoney Asa@39: results[mailType][itemName].count = results[mailType][itemName].count - cod.count Asa@39: end Asa@39: end Asa@39: end Asa@133: Asa@39: if trackID == nil then Asa@39: skipMail[mailSignature] = true Asa@39: self:Print("WARNING: {%s} is a COD payment but doesn't have an ItemAuditor tracking number.", msgSubject) Asa@39: end Asa@133: Asa@0: elseif mailType == "AHSuccess" then Asa@0: local invoiceType, itemName, playerName, bid, buyout, deposit, consignment = GetInboxInvoiceInfo(mailIndex); Asa@26: results[mailType][itemName] = (results[mailType][itemName] or {total=0,count=0}) Asa@26: results[mailType][itemName].total = results[mailType][itemName].total - deposit - buyout + consignment Asa@133: Asa@0: Asa@0: elseif mailType == "AHWon" then Asa@0: local invoiceType, itemName, playerName, bid, buyout, deposit, consignment = GetInboxInvoiceInfo(mailIndex); Asa@26: results[mailType][itemName] = (results[mailType][itemName] or {total=0,count=0}) Asa@26: results[mailType][itemName].total = results[mailType][itemName].total + bid Asa@133: Asa@98: local count = select(3, GetInboxItem(mailIndex,1)) Asa@26: results[mailType][itemName].count = results[mailType][itemName].count + count Asa@5: elseif mailType == "AHExpired" or mailType == "AHCancelled" or mailType == "AHOutbid" then Asa@0: -- These should be handled when you pay the deposit at the AH Asa@0: else Asa@144: Asa@144: local body = GetInboxText(mailIndex) Asa@144: if body and body:find(ItemAuditor.TRACKING_DATA_DIVIDER) then Asa@144: local serialized = body:gsub('.*'..ItemAuditor.TRACKING_DATA_DIVIDER, '') Asa@144: local body = body:gsub(ItemAuditor.TRACKING_DATA_DIVIDER..'.*', '') Asa@144: local success, trackingID, data = ItemAuditor:Deserialize(serialized) Asa@144: if success then Asa@144: if not self.db.char.incoming_tracking_ids[trackingID] then Asa@144: for link, d in pairs(data) do Asa@144: self:SaveValue(link, d.costEach * d.count, d.count) Asa@144: end Asa@144: end Asa@144: if body == '' and msgItem == nil then Asa@144: self.deleteQueue = self.deleteQueue or {} Asa@144: local ni = #(self.deleteQueue)+1 Asa@144: print(deleteQueue, ni, mailIndex) Asa@144: self.deleteQueue[ni] = mailIndex Asa@144: end Asa@144: ia_tracking[trackingID] = true Asa@144: self.db.char.incoming_tracking_ids[trackingID] = true Asa@144: end Asa@144: end Asa@144: Asa@0: end Asa@0: Asa@0: end Asa@98: Asa@98: wipe(myMailbox) Asa@23: for mailType, collection in pairs(results) do Asa@98: myMailbox[mailType] = {} Asa@26: for item, data in pairs(collection) do Asa@98: myMailbox[mailType][item] = { Asa@98: total = data.total, Asa@98: count = data.count, Asa@98: } Asa@98: -- self:Print(format("|cFF00FF00MailScan|r: %s - %s - %s x %s", mailType, item, data.total, data.count)) Asa@23: end Asa@23: end Asa@144: if self:tcount(ia_tracking) > 0 then Asa@144: for id, _ in pairs(self.db.char.incoming_tracking_ids) do Asa@144: self.db.char.incoming_tracking_ids[id] = ia_tracking[id] Asa@144: end Asa@144: end Asa@144: Asa@133: return results Asa@0: end Asa@0: Asa@105: local realm = GetRealmName() Asa@105: local ds_account = 'Default' Asa@82: function ItemAuditor:GetItemCount(searchID) Asa@141: self:Debug('ItemAuditor:GetItemCount(%s)', tostring(searchID)) Asa@105: local count = 0 Asa@105: for _, character in pairs(DataStore:GetCharacters(realm, ds_account)) do Asa@136: if DataStore:GetCharacterFaction(character) == UnitFactionGroup("player") then Asa@136: local bag, bank = DataStore:GetContainerItemCount(character, searchID) Asa@136: count = count + (bag or 0) + (bank or 0) Asa@136: count = count + (DataStore:GetAuctionHouseItemCount(character, searchID) or 0) Asa@136: count = count + (DataStore:GetInventoryItemCount(character, searchID) or 0) Asa@136: count = count + (DataStore:GetMailItemCount(character, searchID) or 0) Asa@136: count = count + (DataStore:GetCurrencyItemCount(character, searchID) or 0) Asa@141: else Asa@141: self:Debug('Skipping %s', character) Asa@136: end Asa@105: end Asa@141: self:Debug('before guild count: %s', count) Asa@132: for guildName in pairs(self.db.factionrealm.enabled_guilds) do Asa@132: count = count + DataStore:GetGuildBankItemCount(DataStore:GetGuilds()[guildName], searchID) Asa@132: end Asa@141: self:Debug('after guild count: %s', count) Asa@132: Asa@98: local itemName = GetItemInfo(searchID) Asa@98: for character, mailbox in pairs(allMailboxes) do Asa@98: for type, items in pairs(mailbox) do Asa@98: if type == 'AHWon' or type == 'COD' then Asa@98: for name, data in pairs(items) do Asa@98: if name == itemName then Asa@98: count = count - data.count Asa@141: self:Debug('removing mail %s %s %s', character, type, data.count) Asa@98: end Asa@98: end Asa@98: end Asa@98: end Asa@82: end Asa@82: return count Asa@82: end Asa@82: Asa@63: function ItemAuditor:GetItem(link, viewOnly) Asa@9: if viewOnly == nil then Asa@9: viewOnly = false Asa@9: end Asa@133: Asa@9: local itemName = nil Asa@9: if self:GetSafeLink(link) == nil then Asa@9: itemName = link Asa@9: else Asa@9: link = self:GetSafeLink(link) Asa@9: itemName = GetItemInfo(link) Asa@9: end Asa@133: Asa@133: Asa@9: if self.db.factionrealm.item_account[itemName] ~= nil then Asa@65: self.db.factionrealm.items[link] = { Asa@82: count = ItemAuditor:GetItemCount(self:GetIDFromLink(link)), Asa@8: invested = abs(self.db.factionrealm.item_account[itemName] or 0), Asa@8: } Asa@8: self.db.factionrealm.item_account[itemName] = nil Asa@8: end Asa@133: Asa@65: if viewOnly == false and self.db.factionrealm.items[link] == nil then Asa@133: Asa@65: self.db.factionrealm.items[link] = { Asa@82: count = ItemAuditor:GetItemCount(self:GetIDFromLink(link)), Asa@9: invested = abs(self.db.factionrealm.item_account[itemName] or 0), Asa@9: } Asa@133: Asa@9: end Asa@133: Asa@65: if self.db.factionrealm.items[link] ~= nil then Asa@82: self.db.factionrealm.items[link].count = ItemAuditor:GetItemCount(self:GetIDFromLink(link)) Asa@133: Asa@65: if self.db.factionrealm.items[link].invested == nil then Asa@65: self.db.factionrealm.items[link].invested = 0 Asa@45: end Asa@37: end Asa@133: Asa@65: if viewOnly == true and self.db.factionrealm.items[link] == nil then Asa@9: return {count = 0, invested = 0} Asa@9: elseif viewOnly == true then Asa@133: Asa@65: return {count = self.db.factionrealm.items[link].count, invested = self.db.factionrealm.items[link].invested} Asa@9: end Asa@133: Asa@133: Asa@133: Asa@65: return self.db.factionrealm.items[link] Asa@8: end Asa@8: Asa@63: function ItemAuditor:RemoveItem(link) Asa@9: self.db.factionrealm.item_account[link] = nil Asa@9: link = self:GetSafeLink(link) Asa@9: if link ~= nil then Asa@63: local item = ItemAuditor:GetItem(link) Asa@35: item.invested = 0 Asa@24: else Asa@24: self:Debug('Failed to convert link' .. tostring(link)) Asa@9: end Asa@8: end Asa@8: Asa@63: function ItemAuditor:SaveValue(link, value, countChange) Asa@26: self:Debug("SaveValue(%s, %s, %s)", tostring(link), value, (countChange or 'default')) Asa@159: assert(link, "invalid link") Asa@26: countChange = countChange or 0 Asa@9: local item = nil Asa@9: local realLink = self:GetSafeLink(link) Asa@9: local itemName = nil Asa@9: if realLink == nil then Asa@26: itemName = link Asa@23: self:Debug('SaveValue: GetSafeLink failed, falling back to storing by name: ' .. tostring(itemName)) Asa@9: self.db.factionrealm.item_account[itemName] = (self.db.factionrealm.item_account[itemName] or 0) + value Asa@9: item = {invested = self.db.factionrealm.item_account[itemName], count = 1} Asa@9: else Asa@133: Asa@9: item = self:GetItem(realLink) Asa@9: item.invested = item.invested + value Asa@9: itemName = GetItemInfo(realLink) Asa@9: end Asa@133: Asa@26: if value > 0 and countChange > 0 and item.invested == value and item.count ~= countChange then Asa@26: local costPerItem = value / countChange Asa@26: value = costPerItem * item.count Asa@26: item.invested = value Asa@26: self:Print("You already owned %s %s with an unknown price, so they have also been updated to %s each", (item.count - countChange), itemName, self:FormatMoney(costPerItem)) Asa@26: end Asa@133: Asa@7: if abs(value) > 0 then Asa@22: if item.invested < 0 then Asa@16: if self.db.profile.messages.cost_updates then Asa@103: self:Print(format("Updated price of %s from %s to %s. |cFF00FF00You just made a profit of %s.", itemName, self:FormatMoney(item.invested - value), self:FormatMoney(0), self:FormatMoney(abs(item.invested)))) Asa@16: end Asa@12: self:RemoveItem(link) Asa@12: -- This doesn't work when you mail the only copy of an item you have to another character. Asa@12: --[[ Asa@133: elseif item.count == 0 and realLink and ItemAuditor:GetItemCount(self:GetIDFromLink(realLink)) then Asa@15: self:Print("You ran out of " .. itemName .. " and never recovered " .. self:FormatMoney(item.invested)) Asa@12: self:RemoveItem(link) Asa@12: ]] Asa@16: else Asa@16: if self.db.profile.messages.cost_updates then Asa@16: self:Print(format("Updated price of %s from %s to %s. (total change:%s)", itemName, self:FormatMoney(item.invested - value), self:FormatMoney(item.invested), self:FormatMoney(value))) Asa@16: end Asa@12: end Asa@0: end Asa@133: Asa@10: if realLink ~= nil then Asa@63: ItemAuditor:UpdateQAThreshold(realLink) Asa@112: self:SendMessage("IA_COST_CHANGED", realLink, unpack({ItemAuditor:GetItemCost(realLink)})) Asa@10: end Asa@35: UpdateInvestedData() Asa@10: end Asa@12: Asa@0: Asa@63: function ItemAuditor:WatchBags() Asa@4: if self.watch_handle == nil then Asa@63: ItemAuditor:UpdateCurrentInventory() Asa@152: self.watch_handle = self:RegisterBucketEvent({"BAG_UPDATE", "PLAYER_MONEY", "UNIT_INVENTORY_CHANGED"}, 0.3, "UpdateAudit") Asa@4: end Asa@0: end Asa@0: Asa@63: function ItemAuditor:UnwatchBags() Asa@4: if self.watch_handle ~= nil then Asa@4: self:UnregisterBucket(self.watch_handle) Asa@4: self.watch_handle = nil Asa@4: end Asa@0: end Asa@0: Asa@9: Asa@63: function ItemAuditor:GetSafeLink(link) Asa@9: local newLink = nil Asa@9: Asa@158: if link and link == string.match(link, '.-:[-0-9]+[-:0-9]*') then Asa@24: newLink = link Asa@24: elseif link then Asa@158: newLink = link and string.match(link, "|H(.-):([-0-9]+):([-0-9]+)|h") Asa@9: end Asa@9: if newLink == nil then Asa@9: local itemID = self:GetItemID(link) Asa@9: if itemID ~= nil then Asa@9: _, newLink = GetItemInfo(itemID) Asa@9: return self:GetSafeLink(newLink) Asa@9: end Asa@9: end Asa@158: return newLink and string.gsub(newLink, ":0:0:0:0:0:0:[-0-9]+", "") Asa@9: end Asa@9: Asa@63: function ItemAuditor:GetIDFromLink(link) Asa@9: local _, _, _, _, Id = string.find(link, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?") Asa@9: return tonumber(Id) Asa@9: end Asa@9: Asa@63: function ItemAuditor:GetItemCost(link, countModifier) Asa@159: assert(link, format('invalid link: %s', tostring(link))) Asa@9: local item = self:GetItem(link, true) Asa@8: Asa@9: if item.invested > 0 then Asa@9: local count = item.count Asa@133: Asa@9: if countModifier ~= nil then Asa@9: count = count - countModifier Asa@0: end Asa@133: if count > 0 then Asa@45: return ceil(item.invested), ceil(item.invested/count), count Asa@9: end Asa@121: return ceil(item.invested), 0, count Asa@0: end Asa@82: return 0, 0, ItemAuditor:GetItemCount(ItemAuditor:GetIDFromLink(link)) Asa@0: end Asa@132: Asa@132: ItemAuditor.Options.args.misc= { Asa@132: name = "Misc", Asa@132: type = 'group', Asa@132: args = { Asa@132: }, Asa@132: } Asa@132: local function GetGuild(info) Asa@132: local guildName = info[#(info)] Asa@132: return (ItemAuditor.db.factionrealm.enabled_guilds[guildName] == true) Asa@132: end Asa@132: Asa@132: local function SetGuild(info, value) Asa@132: local guildName = info[#(info)] Asa@132: ItemAuditor.db.factionrealm.enabled_guilds[guildName] = value or nil Asa@132: end Asa@132: Asa@132: for guildName in pairs(DataStore:GetGuilds()) do Asa@132: ItemAuditor.Options.args.misc.args[guildName] = { Asa@132: type = "toggle", Asa@132: name = "Count "..guildName.." Guild Bank", Asa@132: get = GetGuild, Asa@132: set = SetGuild, Asa@132: order = 11, Asa@132: } Asa@132: end