From 62543f8332dd6e5f594e268bc2e81815ea6eb409 Mon Sep 17 00:00:00 2001 From: ckaotik Date: Thu, 20 May 2010 22:39:01 +0200 Subject: [PATCH] major rewrite of scanning and item handling --- Broker_Garbage.toc | 2 +- Locale/deDE.lua | 2 +- Locale/enUS.lua | 4 +- constants.lua | 38 ++- core.lua | 828 +++++++++++++++++++++++----------------------------- helper.lua | 193 +++++++++++- options.lua | 31 +- 7 files changed, 609 insertions(+), 489 deletions(-) diff --git a/Broker_Garbage.toc b/Broker_Garbage.toc index 92d9652..6190a89 100644 --- a/Broker_Garbage.toc +++ b/Broker_Garbage.toc @@ -14,7 +14,7 @@ ## X-Embeds: LibPeriodicTable-3.1 ## X-Category: Inventory ## X-Localizations: enUS, deDE. Works in any language. You can help! -## X-Credits: GarbageFu(Jaerin/wmrojer), tekKonfig(Tekkub) +## X-Credits: GarbageFu(Jaerin/wmrojer), tekKonfig(Tekkub), Mirroar (<3) ## X-License: GNU GPLv2 # libraries diff --git a/Locale/deDE.lua b/Locale/deDE.lua index cf957fe..5e3fdb5 100644 --- a/Locale/deDE.lua +++ b/Locale/deDE.lua @@ -183,7 +183,7 @@ if GetLocale() == "deDE" then "Shift-Klicke, um die globale Einschlussliste zu leeren" BrokerGarbage.locale.LONIncludeAutoSellText = "Automatisch Items der Einschlussliste verkaufen" - BrokerGarbage.locale.LONIncludeAutoSellTooltip = "Aktivieren, um Items von deiner Einschlussliste beim Händler zu verkaufen; wenn aktiv hat die Verkaufsliste keinerlei Einfluss.\nItems ohne Wert werden ignoriert." + BrokerGarbage.locale.LONIncludeAutoSellTooltip = "Aktivieren, um Items von deiner Einschlussliste beim Händler zu verkaufen.\nItems ohne Wert werden ignoriert." -- Auto Sell List BrokerGarbage.locale.LONAutoSellHeader = "Verkaufsliste - Items hier werden bei Händlern automatisch verkauft." diff --git a/Locale/enUS.lua b/Locale/enUS.lua index 28c9eb1..3de3351 100644 --- a/Locale/enUS.lua +++ b/Locale/enUS.lua @@ -131,7 +131,7 @@ BrokerGarbage.locale = { defaultListsTooltip = "Click to manually create default local list entries. Right-Click to also create default global lists.", DKTitle = "Temp. disable key", - DKTooltip = "Set a key to disable BrokerGarbage temporarily.", + DKTooltip = "Set a key to temporarily disable BrokerGarbage.", disableKeys = { ["None"] = "None", ["SHIFT"] = "SHIFT", @@ -185,7 +185,7 @@ BrokerGarbage.locale = { "SHIFT-Click to empty your global Include List.", LONIncludeAutoSellText = "Automatically sell include list items", - LONIncludeAutoSellTooltip = "Check this to sell items on your include list when at a merchant; using the AutoSell list has no effect then.\nItems without a value will be ignored.", + LONIncludeAutoSellTooltip = "Check this to sell items on your include list when at a merchant.\nItems without a value will be ignored.", -- Auto Sell List LONAutoSellHeader = "Sell List - These items will be sold automatically when at a vendor.", diff --git a/constants.lua b/constants.lua index 649d5c0..84f9852 100644 --- a/constants.lua +++ b/constants.lua @@ -2,7 +2,7 @@ _, BrokerGarbage = ... -- default saved variables BrokerGarbage.defaultGlobalSettings = { - -- lists :: key is either the itemID -or- the PeriodicTable category string + -- lists :: key is either the itemID -or- the PeriodicTable category string, value is true -or- limit number exclude = {}, include = {}, autoSellList = {}, @@ -12,6 +12,7 @@ BrokerGarbage.defaultGlobalSettings = { autoSellToVendor = true, autoRepairAtVendor = true, disableKey = "SHIFT", + hideZeroValue = true, sellNotWearable = false, sellNWQualityTreshold = 4, autoSellIncludeItems = false, @@ -53,22 +54,37 @@ BrokerGarbage.defaultLocalSettings = { moneyEarned = 0, } -BrokerGarbage.tagAuction = "|cFF2bff58A" -- green -BrokerGarbage.tagVendor = "|cFFff9c5aV" -- orange -BrokerGarbage.tagVendorList = "|cFFff592dV" -- slightly darker orange -BrokerGarbage.tagDisenchant = "|cFFe052ffD" -- purple -BrokerGarbage.tagInclude = "|cFFffffffI" -- white -BrokerGarbage.tagUnusableGear = "|cFF3c73abG" -- blue +-- item classification +BrokerGarbage.EXCLUDE = 0 -- item is excluded. Nothing happened... +BrokerGarbage.INCLUDE = 1 -- item is on include list +BrokerGarbage.LIMITED = 2 -- item is on include list, but has a limit value +BrokerGarbage.UNUSABLE = 3 -- item is gear but not usable + +BrokerGarbage.AUCTION = 4 -- auction price is highest value +BrokerGarbage.VENDOR = 5 -- vendor price is highest value +BrokerGarbage.VENDORLIST = 6 -- item is on sell list +BrokerGarbage.DISENCHANT = 7 -- disenchant price is highest value + +-- corresponding tags to be used in the LDB tooltip +BrokerGarbage.tag = { + [BrokerGarbage.INCLUDE] = "|cFFffffffI", -- white + [BrokerGarbage.LIMITED] = "|cFFffffffL", -- white + [BrokerGarbage.UNUSABLE] = "|cFF3c73abG", -- blue + [BrokerGarbage.AUCTION] = "|cFF2bff58A", -- green + [BrokerGarbage.VENDOR] = "|cFFff9c5aV", -- orange + [BrokerGarbage.VENDORLIST] = "|cFFff592dV", -- dark orange + [BrokerGarbage.DISENCHANT] = "|cFFe052ffD", -- purple +} BrokerGarbage.clams = {15874, 5523, 5524, 7973, 24476, 36781, 45909} BrokerGarbage.playerClass = select(2,UnitClass("player")) BrokerGarbage.enchanting = select(1,GetSpellInfo(7411)) BrokerGarbage.disableKey = { - ["None"] = function() return false end, - ["SHIFT"] = IsShiftKeyDown, - ["ALT"] = IsAltKeyDown, - ["CTRL"] = IsControlKeyDown, + ["None"] = function() return false end, + ["SHIFT"] = IsShiftKeyDown, + ["ALT"] = IsAltKeyDown, + ["CTRL"] = IsControlKeyDown, } -- rarity strings (no need to localize) diff --git a/core.lua b/core.lua index 4907976..d3c050a 100644 --- a/core.lua +++ b/core.lua @@ -13,36 +13,58 @@ local LDB = LibStub("LibDataBroker-1.1"):NewDataObject("Broker_Garbage", { type = "data source", icon = "Interface\\Icons\\achievement_bg_returnxflags_def_wsg", label = "Garbage", - text = "Text", -- this is a placeholder until the first scan BrokerGarbage.locale.label + text = "", OnClick = function(...) BrokerGarbage:OnClick(...) end, OnEnter = function(...) BrokerGarbage:Tooltip(...) end, }) ---LDB.OnClick = function(...) BrokerGarbage:OnClick(...) end ---LDB.OnEnter = function(...) BrokerGarbage:Tooltip(...) end +local function UpdateLDB() + local cheapestItems = BrokerGarbage:GetCheapest() + BrokerGarbage.totalBagSpace, BrokerGarbage.totalFreeSlots = BrokerGarbage:GetBagSlots() -- TODO: maybe reduce to only the relevant bag + + if cheapestItems[1] then + BrokerGarbage.cheapestItem = cheapestItems[1] + LDB.text = BrokerGarbage:FormatString(BG_GlobalDB.LDBformat) + else + BrokerGarbage.cheapestItem = nil + LDB.text = BrokerGarbage:FormatString(BG_GlobalDB.LDBNoJunk) + end +end -- internal locals -local locked = false -local sellValue = 0 -- represents the actual value that we sold stuff for, opposed to BrokerGarbage.toSellValue which shows the maximum we could sell - imagine someone closing the merchant window. sellValue will then hold the real value we're interested in -local cost = 0 - -local lastReminder = time() - -BrokerGarbage.isAtVendor = false -BrokerGarbage.optionsModules = {} +-- local lastReminder = time() +BrokerGarbage.optionsModules = {} -- used for ordering/showing entries in the options panel +local locked = false -- set to true while selling stuff +local sellValue = 0 -- represents the actual value that we sold stuff for +local cost = 0 -- the amount of money that we repaired for -- Event Handler -- --------------------------------------------------------- local function eventHandler(self, event, ...) - if event == "ADDON_LOADED" then - if arg1 == "Broker_Garbage" then - BrokerGarbage:CheckSettings() - end + if event == "PLAYER_ENTERING_WORLD" then + BrokerGarbage:CheckSettings() + + -- some default values initialization + BrokerGarbage.isAtVendor = false + BrokerGarbage.toSellValue = {} -- value to show on sell icon + BrokerGarbage.totalBagSpace = 0 + BrokerGarbage.totalFreeSlots = 0 + + -- inventory database + BrokerGarbage.itemsCache = {} + BrokerGarbage.clamInInventory = false + BrokerGarbage.containerInInventory = false + + -- full inventory scan to start with + BrokerGarbage:ScanInventory() elseif event == "BAG_UPDATE" then + if arg1 < 0 or arg1 > 4 then return end + + BrokerGarbage:ScanInventoryContainer(arg1) -- partial inventory scan if not locked then - BrokerGarbage:ScanInventory() + UpdateLDB() end elseif event == "MERCHANT_SHOW" then @@ -57,16 +79,17 @@ local function eventHandler(self, event, ...) -- fallback unlock cost = 0 sellValue = 0 - BrokerGarbage.toSellValue = 0 BrokerGarbage.isAtVendor = false locked = false - BrokerGarbage:Debug("lock released") - - BrokerGarbage:ScanInventory() + BrokerGarbage:Debug("Fallback Unlock: Merchant window closed, scan lock released.") + UpdateLDB() + + elseif event == "AUCTION_HOUSE_CLOSED" then + -- Update cache auction values if needed + BrokerGarbage.itemsCache = {} elseif (locked or cost ~=0) and event == "PLAYER_MONEY" then -- regular unlock - -- wrong player_money event (resulting from repair, not sell) if sellValue ~= 0 and cost ~= 0 and ((-1)*sellValue <= cost+2 and (-1)*sellValue >= cost-2) then BrokerGarbage:Debug("Not yet ... Waiting for actual money change.") @@ -92,23 +115,21 @@ local function eventHandler(self, event, ...) end sellValue = 0 - BrokerGarbage.toSellValue = 0 cost = 0 locked = false - BrokerGarbage:Debug("lock released") - - BrokerGarbage:ScanInventory() - + BrokerGarbage:Debug("Regular Unlock: Money received, scan lock released.") + UpdateLDB() end end -- register events local frame = CreateFrame("frame") -frame:RegisterEvent("ADDON_LOADED") +frame:RegisterEvent("PLAYER_ENTERING_WORLD") frame:RegisterEvent("BAG_UPDATE") frame:RegisterEvent("MERCHANT_SHOW") frame:RegisterEvent("MERCHANT_CLOSED") +frame:RegisterEvent("AUCTION_HOUSE_CLOSED") frame:RegisterEvent("PLAYER_MONEY") frame:SetScript("OnEvent", eventHandler) @@ -127,6 +148,10 @@ function BrokerGarbage:UpdateRepairButton(...) return end + local junkValue = 0 + for i = 0, 4 do + junkValue = junkValue + BrokerGarbage.toSellValue[i] + end local iconbutton -- show auto-sell icon on vendor frame if not _G["BrokerGarbage_SellIcon"] then @@ -138,8 +163,12 @@ function BrokerGarbage:UpdateRepairButton(...) iconbutton:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_RIGHT") local tiptext - if BrokerGarbage.toSellValue and BrokerGarbage.toSellValue ~= 0 then - tiptext = format(BrokerGarbage.locale.autoSellTooltip, BrokerGarbage:FormatMoney(BrokerGarbage.toSellValue)) + local junkValue = 0 + for i = 0, 4 do + junkValue = junkValue + BrokerGarbage.toSellValue[i] + end + if junkValue ~= 0 then + tiptext = format(BrokerGarbage.locale.autoSellTooltip, BrokerGarbage:FormatMoney(junkValue)) else tiptext = BrokerGarbage.locale.reportNothingToSell end @@ -169,7 +198,7 @@ function BrokerGarbage:UpdateRepairButton(...) end MerchantRepairText:Hide() - if BrokerGarbage.toSellValue and BrokerGarbage.toSellValue ~= 0 then + if junkValue ~= 0 then _G["BrokerGarbage_SellIcon"]:GetNormalTexture():SetDesaturated(false) else _G["BrokerGarbage_SellIcon"]:GetNormalTexture():SetDesaturated(true) @@ -180,10 +209,13 @@ hooksecurefunc("MerchantFrame_UpdateRepairButtons", BrokerGarbage.UpdateRepairBu -- Tooltip -- --------------------------------------------------------- function BrokerGarbage:Tooltip(self) + local colNum, lineNum if BG_GlobalDB.showSource then BrokerGarbage.tt = LibStub("LibQTip-1.0"):Acquire("BrokerGarbage_TT", 4, "LEFT", "RIGHT", "RIGHT", "CENTER") + colNum = 4 else BrokerGarbage.tt = LibStub("LibQTip-1.0"):Acquire("BrokerGarbage_TT", 3, "LEFT", "RIGHT", "RIGHT") + colNum = 3 end BrokerGarbage.tt:Clear() @@ -204,24 +236,39 @@ function BrokerGarbage:Tooltip(self) BrokerGarbage.tt:SetFont(tooltipFont) BrokerGarbage.tt:AddLine(BrokerGarbage.locale.headerShiftClick, '', BrokerGarbage.locale.headerCtrlClick) BrokerGarbage.tt:AddSeparator(2) - + + -- add clam information + if IsAddOnLoaded("Broker_Garbage-LootManager") and ( + (BGLM_GlobalDB.openContainers and BrokerGarbage.containerInInventory) or + (BGLM_GlobalDB.openClams and BrokerGarbage.clamInInventory)) then + + if BGLM_GlobalDB.openContainers and BrokerGarbage.containerInInventory then + lineNum = BrokerGarbage.tt:AddLine() + BrokerGarbage.tt:SetCell(lineNum, 1, BrokerGarbage_LootManager.locale.openPlease, tooltipFont, "CENTER", colNum) + end + if BGLM_GlobalDB.openClams and BrokerGarbage.clamInInventory then + lineNum = BrokerGarbage.tt:AddLine() + BrokerGarbage.tt:SetCell(lineNum, 1, BrokerGarbage_LootManager.locale.openClams, tooltipFont, "CENTER", colNum) + end + BrokerGarbage.tt:AddSeparator(2) + end + -- shows up to n lines of deletable items - local lineNum local cheapList = BrokerGarbage:GetCheapest(BG_GlobalDB.tooltipNumItems) - for i = 1, #cheapList do + for i = 1, #cheapList do -- adds lines: itemLink, count, itemPrice, source lineNum = BrokerGarbage.tt:AddLine( select(2,GetItemInfo(cheapList[i].itemID)), cheapList[i].count, BrokerGarbage:FormatMoney(cheapList[i].value), - (BG_GlobalDB.showSource and cheapList[i].source or nil)) + (BG_GlobalDB.showSource and BrokerGarbage.tag[cheapList[i].source] or nil)) BrokerGarbage.tt:SetLineScript(lineNum, "OnMouseDown", BrokerGarbage.OnClick, cheapList[i]) end if lineNum == nil then BrokerGarbage.tt:AddLine(BrokerGarbage.locale.noItems, '', BrokerGarbage.locale.increaseTreshold) end - -- add useful(?) information + -- add statistics information if (BG_GlobalDB.showLost and BG_LocalDB.moneyLostByDeleting ~= 0) or (BG_GlobalDB.showEarned and BG_LocalDB.moneyEarned ~= 0) then BrokerGarbage.tt:AddSeparator(2) @@ -243,34 +290,34 @@ function BrokerGarbage:Tooltip(self) BrokerGarbage.tt:UpdateScrolling(BG_GlobalDB.tooltipMaxHeight) end --- onClick function for when you ... click. works for both, the LDB plugin -and- tooltip lines +-- onClick function - works for both, the LDB plugin -and- tooltip lines function BrokerGarbage:OnClick(itemTable, button) -- handle LDB clicks seperately + local LDBclick = false if not itemTable.itemID or type(itemTable.itemID) ~= "number" then - BrokerGarbage:Debug("No itemTable for OnClick, using cheapest item") + BrokerGarbage:Debug("Click on LDB") itemTable = BrokerGarbage.cheapestItem + LDBclick = true end -- handle different clicks if itemTable and IsShiftKeyDown() then -- delete or sell item, depending on if we're at a vendor or not - BrokerGarbage:Debug("SHIFT-Click!") if BrokerGarbage.isAtVendor and itemTable.value > 0 then - BrokerGarbage:Debug("@Vendor", "Selling") - BG_GlobalDB.moneyEarned = BG_GlobalDB.moneyEarned + itemTable.value - BG_LocalDB.moneyEarned = BG_LocalDB.moneyEarned + itemTable.value - BG_GlobalDB.itemsSold = BG_GlobalDB.itemsSold + itemTable.count + BrokerGarbage:Debug("At vendor, selling "..itemTable.itemID) + BG_GlobalDB.moneyEarned = BG_GlobalDB.moneyEarned + itemTable.value + BG_LocalDB.moneyEarned = BG_LocalDB.moneyEarned + itemTable.value + BG_GlobalDB.itemsSold = BG_GlobalDB.itemsSold + itemTable.count ClearCursor() UseContainerItem(itemTable.bag, itemTable.slot) else - BrokerGarbage:Debug("Not @Vendor", "Deleting") + BrokerGarbage:Debug("Not at vendor", "Deleting") BrokerGarbage:Delete(itemTable) end --[[elseif itemTable and IsAltKeyDown() and IsControlKeyDown() then -- disenchant - BrokerGarbage:Debug("CTRL+ALT-Click!") local itemLink = select(2, GetItemInfo(itemTable.itemID)) if BrokerGarbage:CanDisenchant(itemLink, true) then -- Disenchant: 13262 @@ -278,11 +325,11 @@ function BrokerGarbage:OnClick(itemTable, button) elseif itemTable and IsControlKeyDown() then -- add to exclude list - BrokerGarbage:Debug("CTRL-Click!") if not BG_LocalDB.exclude[itemTable.itemID] then BG_LocalDB.exclude[itemTable.itemID] = true end BrokerGarbage:Print(format(BrokerGarbage.locale.addedToSaveList, select(2,GetItemInfo(itemTable.itemID)))) + BrokerGarbage.itemsCache = {} if BrokerGarbage.optionsLoaded then BrokerGarbage:ListOptionsUpdate("exclude") @@ -290,79 +337,103 @@ function BrokerGarbage:OnClick(itemTable, button) elseif itemTable and IsAltKeyDown() then -- add to force vendor price list - BrokerGarbage:Debug("ALT-Click!") BG_GlobalDB.forceVendorPrice[itemTable.itemID] = true BrokerGarbage:Print(format(BrokerGarbage.locale.addedToPriceList, select(2,GetItemInfo(itemTable.itemID)))) + BrokerGarbage.itemsCache = {} if BrokerGarbage.optionsLoaded then BrokerGarbage:ListOptionsUpdate("forceprice") end - BrokerGarbage:ScanInventory() elseif button == "RightButton" then -- open config BrokerGarbage:OptionsFirstLoad() InterfaceOptionsFrame_OpenToCategory(BrokerGarbage.options) - else - -- do nothing + elseif LDBclick then + -- click on the LDB to rescan + BrokerGarbage:ScanInventory() end - BrokerGarbage:ScanInventory() + BrokerGarbage.debugItemTable = itemTable end -- Item Value Calculation -- --------------------------------------------------------- -- calculates the value of a stack/partial stack of an item -function BrokerGarbage:GetItemValue(itemLink, count) - if not itemLink then return nil, nil end - local itemID = BrokerGarbage:GetItemID(itemLink) - local DE = BrokerGarbage:CanDisenchant(itemLink) - local itemQuality = select(3,GetItemInfo(itemLink)) - local vendorPrice = select(11,GetItemInfo(itemLink)) - local auctionPrice, disenchantPrice, source +function BrokerGarbage:GetItemValue(item, count) + local itemID + if item and type(item) == "number" then + itemID = item + + elseif item and type(item) == "string" then + itemID = BrokerGarbage:GetItemID(item) + + else + -- invalid argument + BrokerGarbage:Debug("GetItemValue: Invalid argument "..(item or "").."supplied.") + return nil + end - if vendorPrice == 0 then vendorPrice = nil end - if not count then - count = GetItemCount(itemLink, false, false) - if count == 0 then count = 1 end + return BrokerGarbage:GetCached(itemID).value * count +end + +-- returns which of the items values is the highest (value, type) +function BrokerGarbage:GetSingleItemValue(item) + local itemID, itemLink + if item and type(item) == "number" then + itemID = item + itemLink = select(2, GetItemInfo(itemID)) + + elseif item and type(item) == "string" then + itemID = BrokerGarbage:GetItemID(item) + itemLink = item + + else + -- invalid argument + BrokerGarbage:Debug("GetSingleItemValue: Invalid argument "..(item or "").."supplied.") + return nil end + local canDE = BrokerGarbage:CanDisenchant(itemLink) + local _, _, itemQuality, _, _, _, _, _, _, _, vendorPrice = GetItemInfo(itemID) + local auctionPrice, disenchantPrice, source + -- gray items on the AH? if itemQuality == 0 then - return vendorPrice and vendorPrice*count or nil, BrokerGarbage.tagVendor + return vendorPrice, BrokerGarbage.VENDOR end -- calculate auction value if IsAddOnLoaded("Auctionator") then BrokerGarbage.auctionAddon = "Auctionator" auctionPrice = Atr_GetAuctionBuyout(itemLink) - disenchantPrice = DE and Atr_GetDisenchantValue(itemLink) + disenchantPrice = canDE and Atr_GetDisenchantValue(itemLink) elseif IsAddOnLoaded("AuctionLite") then BrokerGarbage.auctionAddon = "AuctionLite" auctionPrice = AuctionLite:GetAuctionValue(itemLink) - disenchantPrice = DE and AuctionLite:GetDisenchantValue(itemLink) + disenchantPrice = canDE and AuctionLite:GetDisenchantValue(itemLink) elseif IsAddOnLoaded("WOWEcon_PriceMod") then BrokerGarbage.auctionAddon = "WoWecon" auctionPrice = Wowecon.API.GetAuctionPrice_ByLink(itemLink) - if DE then + if canDE then disenchantPrice = 0 local DEData = Wowecon.API.GetDisenchant_ByLink(itemLink) for i,data in pairs(DEData) do -- data[1] = itemLink, data[2] = quantity, data[3] = chance disenchantPrice = disenchantPrice + (Wowecon.API.GetAuctionPrice_ByLink(data[1]) * data[2] * data[3]) end - disenchantPrice = DE and math.floor(disenchantPrice) + disenchantPrice = canDE and math.floor(disenchantPrice) end elseif IsAddOnLoaded("Auc-Advanced") then BrokerGarbage.auctionAddon = "Auc-Advanced" auctionPrice = AucAdvanced.API.GetMarketValue(itemLink) - if DE and IsAddOnLoaded("Enchantrix") then + if canDE and IsAddOnLoaded("Enchantrix") then disenchantPrice = 0 local itemType local weaponString, armorString = GetAuctionItemClasses() @@ -400,50 +471,54 @@ function BrokerGarbage:GetItemValue(itemLink, count) else BrokerGarbage.auctionAddon = "Unknown/None" auctionPrice = GetAuctionBuyout and GetAuctionBuyout(itemLink) or nil - disenchantPrice = DE and GetDisenchantValue and GetDisenchantValue(itemLink) or nil - + disenchantPrice = canDE and GetDisenchantValue and GetDisenchantValue(itemLink) or nil end local maximum = math.max((disenchantPrice or 0), (auctionPrice or 0), (vendorPrice or 0)) if vendorPrice and maximum == vendorPrice then - return vendorPrice*count, BrokerGarbage.tagVendor + return vendorPrice, BrokerGarbage.VENDOR elseif auctionPrice and maximum == auctionPrice then - return auctionPrice*count, BrokerGarbage.tagAuction + return auctionPrice, BrokerGarbage.AUCTION elseif disenchantPrice and maximum == disenchantPrice then - return disenchantPrice, BrokerGarbage.tagDisenchant + return disenchantPrice, BrokerGarbage.DISENCHANT else return nil, nil end end --- finds all occurences of the given item and returns the best location to delete from +-- finds all occurences of the given item and returns the least important location function BrokerGarbage:FindSlotToDelete(itemID, ignoreFullStack) local locations = {} - local maxStack = select(8, GetItemInfo(itemID)) + local _, _, _, _, _, _, _, maxStack = GetItemInfo(itemID) local numSlots, freeSlots, ratio, bagType for container = 0,4 do numSlots = GetContainerNumSlots(container) freeSlots, bagType = GetContainerFreeSlots(container) - if not numSlots or not freeSlots then break end - ratio = #freeSlots/numSlots + freeSlots = freeSlots and #freeSlots or 0 - for slot = 1, numSlots do - local _,count,locked,_,_,canOpen,itemLink = GetContainerItemInfo(container, slot) + if numSlots then + ratio = freeSlots/numSlots - if itemLink and BrokerGarbage:GetItemID(itemLink) == itemID then - if not ignoreFullStack or (ignoreFullStack and count < maxStack) then - -- found one - table.insert(locations, { - slot = slot, - bag = container, - count = count, - ratio = ratio, - bagType = (bagType or 0) - }) + for slot = 1, numSlots do + local _,count,_,_,_,_,link = GetContainerItemInfo(container, slot) + + if link and BrokerGarbage:GetItemID(link) == itemID then + BrokerGarbage:Debug("item found") + if not ignoreFullStack or (ignoreFullStack and count < maxStack) then + -- found one + BrokerGarbage:Debug("item stack ok") + table.insert(locations, { + slot = slot, + bag = container, + count = count, + ratio = ratio, + bagType = (bagType or 0) + }) + end end end end @@ -491,7 +566,7 @@ function BrokerGarbage:Delete(itemLink, position) else itemCount = position end - local itemValue = BrokerGarbage:GetItemValue(itemLink, itemCount) or 0 + local itemValue = BrokerGarbage:GetCached(itemID).value * itemCount -- statistics BG_GlobalDB.itemsDropped = BG_GlobalDB.itemsDropped + itemCount @@ -504,301 +579,172 @@ end -- Inventory Scanning -- --------------------------------------------------------- --- scans your inventory for possible junk items and updates LDB display function BrokerGarbage:ScanInventory() - BrokerGarbage.inventory = {} - BrokerGarbage.sellItems = {} - BrokerGarbage.unopened = {} - local limitedItemsChecked = {} + for container = 0,4 do + BrokerGarbage:ScanInventoryContainer(container) + end + UpdateLDB() +end +-- scans your inventory bags for possible junk items and updates LDB display +function BrokerGarbage:ScanInventoryContainer(container) + -- container doesn't exist or cannot be scanned + if not GetContainerNumSlots(container) then return end - BrokerGarbage.toSellValue = 0 - BrokerGarbage.totalBagSpace = 0 - BrokerGarbage.totalFreeSlots = 0 + local numSlots = GetContainerNumSlots(container) + BrokerGarbage.toSellValue[container] = 0 - for container = 0,4 do - local numSlots = GetContainerNumSlots(container) - if numSlots then - freeSlots = GetContainerFreeSlots(container) - BrokerGarbage.totalFreeSlots = BrokerGarbage.totalFreeSlots + (freeSlots and #freeSlots or 0) - BrokerGarbage.totalBagSpace = BrokerGarbage.totalBagSpace + numSlots + for slot = 1, numSlots do + local itemID = GetContainerItemID(container,slot) + + if itemID then + local item = BrokerGarbage:GetCached(itemID) + -- update toSellValue + if item.classification == BrokerGarbage.VENDORLIST or + (item.classification == BrokerGarbage.UNUSABLE and BG_GlobalDB.sellNotWearable and item.quality <= BG_GlobalDB.sellNWQualityTreshold) or + (BG_GlobalDB.autoSellIncludeItems and item.classification == BrokerGarbage.INCLUDE) then + + local itemCount = select(2, GetContainerItemInfo(container, slot)) + BrokerGarbage.toSellValue[container] = BrokerGarbage.toSellValue[container] + BrokerGarbage:GetCached(itemID).value * itemCount + end + end + end +end + +-- Find Cheap Items +-- --------------------------------------------------------- +local function TableSort(a, b) + -- put included items even prior to forced vendor price items + if (a.source == b.source) or (a.source ~= BrokerGarbage.INCLUDE and b.source ~= BrokerGarbage.INCLUDE) then + if a.value == b.value then + if a.itemID == b.itemID then + return a.count < b.count + else + return a.itemID < b.itemID + end + else + return a.value < b.value + end + else + return a.source == BrokerGarbage.INCLUDE + end +end + +-- returns the n cheapest items in your bags in a table +function BrokerGarbage:GetCheapest(number) + if not number then number = 1 end + local cheapestItems = {} + local numSlots, count, quality, canOpen, itemLink, itemID, stackSize + local item, maxValue, insert + + BrokerGarbage.clamInInventory = false + BrokerGarbage.containerInInventory = false + + for container = 0, 4 do + numSlots = GetContainerNumSlots(container) + if numSlots then for slot = 1, numSlots do - local itemID = GetContainerItemID(container,slot) - if itemID then - -- GetContainerItemInfo sucks big time ... just don't use it for quality IDs!!!!!!! - local _,count,locked,_,_, canOpen,itemLink = GetContainerItemInfo(container, slot) - local quality = select(3,GetItemInfo(itemID)) - local isClam = BrokerGarbage:Find(BrokerGarbage.clams, itemID) + -- "Gather Information" + _, count, _, _, _, canOpen, itemLink = GetContainerItemInfo(container, slot) + if itemLink then + itemID = BrokerGarbage:GetItemID(itemLink) + item = BrokerGarbage:GetCached(itemID) + insert = true + local value = count * item.value + local classification = item.classification - if canOpen or isClam then - local _,_,_,_,_,type,subType,_,_,tex = GetItemInfo(itemID) - tinsert(BrokerGarbage.unopened, { - bag = container, - slot = slot, - itemID = itemID, - clam = isClam, - }) - end - - -- check if this item belongs to an excluded category - local isExclude - for setName,_ in pairs(BrokerGarbage:JoinTables(BG_GlobalDB.exclude, BG_LocalDB.exclude)) do - if type(setName) == "string" then - _, isExclude = BrokerGarbage.PT:ItemInSet(itemID, setName) - end - if isExclude then - break + -- remember lootable items + if canOpen or item.isClam then + if item.isClam then + BrokerGarbage.clamInInventory = true + else + BrokerGarbage.containerInInventory = true end end - - local isSell, isInclude, isVendor - -- this saves excluded items - if not BG_GlobalDB.exclude[itemID] and not BG_LocalDB.exclude[itemID] then - local force = false - - -- check if item is in a category of Include List - for setName,_ in pairs(BrokerGarbage:JoinTables(BG_LocalDB.include, BG_GlobalDB.include)) do - if type(setName) == "string" then - _, isInclude = BrokerGarbage.PT:ItemInSet(itemID, setName) - end - if isInclude then isInclude = setName; break end - end - - -- check if item is in a category of Sell List - for setName,_ in pairs(BrokerGarbage:JoinTables(BG_GlobalDB.autoSellList, BG_LocalDB.autoSellList)) do - if type(setName) == "string" then - _, isSell = BrokerGarbage.PT:ItemInSet(itemID, setName) - end - if isSell then isSell = setName; break end - end - - -- check if item is in a category of Force Vendor Price List - for setName,_ in pairs(BG_GlobalDB.forceVendorPrice) do - if type(setName) == "string" then - _, isVendor = BrokerGarbage.PT:ItemInSet(itemID, setName) - end - if isVendor then isVendor = setName; break end - end - - -- ---------------------------------------------------------------------- - -- get price and tag - BrokerGarbage.checkItem = { - bag = container, - slot = slot, - itemID = itemID, - } - local value, source = BrokerGarbage:GetItemValue(itemLink, count) - BrokerGarbage.checkItem = nil - - local _,_,_,_,_,_,subClass,stackSize,invType,_,vendorPrice = GetItemInfo(itemLink) + + -- handle different types of items + if item.classification == BrokerGarbage.EXCLUDE then + insert = false + + elseif item.classification == BrokerGarbage.LIMITED then + local saveStacks = ceil(item.limit/(item.stackSize or 1)) + local locations = BrokerGarbage:FindSlotToDelete(itemID) - if (isInclude and not isExclude) - or BG_GlobalDB.include[itemID] or BG_LocalDB.include[itemID] then - -- Include List item - isInclude = true - force = true + if #locations > saveStacks then + local itemCount = 0 - local limited = BrokerGarbage:Find(limitedItemsChecked, itemID) - if not limited then - if (BG_GlobalDB.include[itemID] and type(BG_GlobalDB.include[itemID]) == "number") - or (BG_LocalDB.include[itemID] and type(BG_LocalDB.include[itemID]) == "number") then - - -- this is a limited item - only check it once - tinsert(limitedItemsChecked, itemID) - limited = true - - local limit = tonumber(BG_GlobalDB.include[itemID]) or tonumber(BG_LocalDB.include[itemID]) - local saveStacks = ceil(limit/(stackSize or 1)) - local locations = BrokerGarbage:FindSlotToDelete(itemID) - - if #locations > saveStacks then - local itemCount = 0 - for i = #locations, 1, -1 do - if itemCount < limit then - itemCount = itemCount + locations[i].count - else - tinsert(BrokerGarbage.inventory, { - bag = locations[i].bag, - slot = locations[i].slot, - itemID = itemID, - quality = quality, - count = locations[i].count, - value = 0, - source = BrokerGarbage.tagInclude, - force = force, - }) - end - end + for i = #locations, 1, -1 do + if itemCount < item.limit then + -- keep this amount + itemCount = itemCount + locations[i].count + if locations[i].bag == container and locations[i].slot == slot then + insert = false end else - limited = false + break; end end - - if not limited then - value = value or 0 - source = BrokerGarbage.tagInclude - else - -- this makes limited items not be inserted twice - value = nil - end - - elseif (isSell and not isExclude) - or BG_GlobalDB.autoSellList[itemID] or BG_LocalDB.autoSellList[itemID] then - -- AutoSell - isSell = true - force = false - - value = vendorPrice - if value then value = value * count end - source = BrokerGarbage.tagVendorList - - elseif quality and quality <= BG_GlobalDB.dropQuality and - ((isVendor and not isExclude) or BG_GlobalDB.forceVendorPrice[itemID]) then - -- Force Vendor Price List item - isVendor = true - force = false - - value = vendorPrice - if value then value = value * count end - source = BrokerGarbage.tagVendorList - - elseif not IsUsableSpell(BrokerGarbage.enchanting) and BrokerGarbage:IsItemSoulbound(itemLink) - and BG_GlobalDB.sellNotWearable and quality <= BG_GlobalDB.sellNWQualityTreshold - and string.find(invType, "INVTYPE") and not string.find(invType, "BAG") - and not BrokerGarbage.usableByClass[BrokerGarbage.playerClass][subClass] - and not BrokerGarbage.usableByAll[invType] then - -- Sell unusable Gear - isSell = true - force = false - - value = vendorPrice - source = BrokerGarbage.tagUnusableGear - - elseif isExclude or (quality and quality > BG_GlobalDB.dropQuality) or not quality then - -- setting the value to nil will prevent the item being inserted to our inventory table - value = nil - - -- all 'regular' items would be in the else part but already have their values and attributes set end - - if value then - -- save if we have something sellable - if quality == 0 or isSell - or BG_GlobalDB.autoSellList[itemID] or BG_LocalDB.autoSellList[itemID] then - BrokerGarbage.toSellValue = BrokerGarbage.toSellValue + value - end - - -- insert into BrokerGarbage.inventory - if (quality and quality <= BG_GlobalDB.dropQuality) - or (isSell and source ~= BrokerGarbage.tagUnusableGear) or isInclude or isVendor then - tinsert(BrokerGarbage.inventory, { - bag = container, - slot = slot, - itemID = itemID, - quality = quality, - count = count, - value = value, - source = source, - force = force, - }) - - elseif quality > BG_GlobalDB.dropQuality and - (source == BrokerGarbage.tagUnusableGear or source == BrokerGarbage.tagVendorList) then - tinsert(BrokerGarbage.sellItems, { - bag = container, - slot = slot, - itemID = itemID, - quality = quality, - count = count, - value = value, - source = source, - force = force, - }) - end + if insert then + -- treat like a regular include item + value = 0 end + + elseif item.classification == BrokerGarbage.DISENCHANT or item.classification == BrokerGarbage.AUCTION then + -- check if item is really soulbound + if BrokerGarbage:IsItemSoulbound(itemID, container, slot) then + -- use vendor price instead + value = select(11, GetItemInfo(itemID)) + classification = BrokerGarbage.VENDOR + end + + elseif item.classification == BrokerGarbage.UNUSABLE then + if not BG_GlobalDB.sellNotWearable or item.quality > BG_GlobalDB.sellNWQualityTreshold then + insert = false + end + + elseif item.classification == BrokerGarbage.INCLUDE then + value = 0 end - end - end - end - end - - local cheapestItem = BrokerGarbage:GetCheapest() - - if cheapestItem[1] then - BrokerGarbage.cheapestItem = cheapestItem[1] - LDB.text = BrokerGarbage:FormatString(BG_GlobalDB.LDBformat) - else - BrokerGarbage.cheapestItem = nil - LDB.text = BrokerGarbage:FormatString(BG_GlobalDB.LDBNoJunk) - end -end - --- Find Cheap Items --- --------------------------------------------------------- --- returns the n cheapest items in your bags in a table -function BrokerGarbage:GetCheapest(number) - if not number then number = 1 end - local cheapestItems, temp = {}, {} - - -- get forced items - for _, itemTable in pairs(BrokerGarbage:JoinSimpleTables(BrokerGarbage.inventory, BrokerGarbage.sellItems)) do - local skip = false - - for _, usedTable in pairs(cheapestItems) do - if usedTable == itemTable then - skip = true - break - end - end - - if not skip and itemTable.force then - tinsert(temp, itemTable) - end - end - table.sort(temp, function(a, b) - -- put included items even prior to forced vendor price items - if (a.source == b.source) or (a.source ~= BrokerGarbage.tagInclude and b.source ~= BrokerGarbage.tagInclude) then - return a.value < b.value - else - return a.source == BrokerGarbage.tagInclude - end - end) - - if #temp <= number then - cheapestItems = temp - else - for i = 1, number do - tinsert(cheapestItems, temp[i]) - end - end - - -- fill with non-forced - if #cheapestItems < number then - local minPrice, minTable - - for i = #cheapestItems +1, number do - for _, itemTable in pairs(BrokerGarbage.inventory) do - local skip = false - - for _, usedTable in pairs(cheapestItems) do - if usedTable == itemTable then - skip = true + + if item.quality > BG_GlobalDB.dropQuality and + not (classification == BrokerGarbage.INCLUDE or classification == BrokerGarbage.VENDORLIST) then + -- include and vendor list items should always be displayed + insert = false + + elseif value == 0 and BG_GlobalDB.hideZeroValue and classification == BrokerGarbage.VENDOR then + insert = false + end + + -- insert data + if insert then + maxValue = cheapestItems[number] and cheapestItems[number].value or nil + if not maxValue then + tinsert(cheapestItems, { + itemID = itemID, + bag = container, + slot = slot, + count = count, + value = value, + source = classification, + }) + elseif value < maxValue then + -- update last item + cheapestItems[number].itemID = itemID + cheapestItems[number].bag = container + cheapestItems[number].slot = slot + cheapestItems[number].count = count + cheapestItems[number].value = value + cheapestItems[number].source = classification + end + table.sort(cheapestItems, TableSort) end end - - if not skip and (not minPrice or itemTable.value < minPrice) then - minPrice = itemTable.value - minTable = itemTable - end end - - if minTable then tinsert(cheapestItems, minTable) end - minPrice = nil - minTable = nil end end + BrokerGarbage.cheapestItem = cheapestItems[1] return cheapestItems end @@ -807,104 +753,70 @@ end -- --------------------------------------------------------- -- when at a merchant this will clear your bags of junk (gray quality) and items on your autoSellList function BrokerGarbage:AutoSell() - if BG_GlobalDB.autoSellToVendor or self == _G["BrokerGarbage_SellIcon"] then - if self == _G["BrokerGarbage_SellIcon"] then - BrokerGarbage:Debug("AutoSell was triggered by a click on Sell Icon.", BrokerGarbage:FormatMoney(sellValue), BrokerGarbage:FormatMoney(BrokerGarbage.toSellValue)) - end - local i = 1 - local skip - sellValue = 0 - for _, itemTable in pairs(BrokerGarbage:JoinSimpleTables(BrokerGarbage.inventory, BrokerGarbage.sellItems)) do - local sellByString, sellByID, excludeByID, excludeByString - local temp, checkTable - - -- check if item should be saved: exclude/whitelist - excludeByID = BG_GlobalDB.exclude[itemTable.itemID] or BG_LocalDB.exclude[itemTable.itemID] - for setName,_ in pairs(BrokerGarbage:JoinTables(BG_GlobalDB.exclude, BG_LocalDB.exclude)) do - if type(setName) == "string" then - _, temp = BrokerGarbage.PT:ItemInSet(itemTable.itemID, setName) - end - if temp then - BrokerGarbage:Debug(itemTable.itemID, "is in set", temp, "on exclude list") - excludeByString = true - break - end - end - if excludeByID then - BrokerGarbage:Debug(itemTable.itemID, "is excluded via its itemID") - end - - if excludeByString or excludeByID then - sellByID = false - checkTable = {} - elseif BG_GlobalDB.autoSellIncludeItems then - sellByID = BG_GlobalDB.include[itemTable.itemID] or BG_LocalDB.include[itemTable.itemID] - checkTable = BrokerGarbage:JoinTables(BG_LocalDB.include, BG_GlobalDB.include) - else - sellByID = BG_GlobalDB.autoSellList[itemTable.itemID] or BG_LocalDB.autoSellList[itemTable.itemID] - checkTable = BrokerGarbage:JoinTables(BG_LocalDB.autoSellList, BG_GlobalDB.autoSellList) - end - - temp = nil - -- check if item should be sold - for setName,_ in pairs(checkTable) do - if type(setName) == "string" then - _, temp = BrokerGarbage.PT:ItemInSet(itemTable.itemID, setName) - end - if temp then - -- this only prints the first match - BrokerGarbage:Debug(itemTable.itemID, "is in set", temp, "on auto sell list") - sellByString = true - break - end - end - if sellByID then - BrokerGarbage:Debug(itemTable.itemID, "is to be sold via its itemID") - end - - -- ==== Sell Gear ==== -- - -- check if this item is equippable for us - local _, itemLink, quality, _, _, _, subClass, _, invType = GetItemInfo(itemTable.itemID) - local sellGear = quality - and not IsUsableSpell(BrokerGarbage.enchanting) and BrokerGarbage:IsItemSoulbound(itemLink) - and BG_GlobalDB.sellNotWearable and quality <= BG_GlobalDB.sellNWQualityTreshold - and string.find(invType, "INVTYPE") and not string.find(invType, "BAG") - and not BrokerGarbage.usableByClass[BrokerGarbage.playerClass][subClass] - and not BrokerGarbage.usableByAll[invType] - if sellGear then - BrokerGarbage:Debug("Item should be sold (as we cannot wear it):" .. itemLink) - end - - -- === Actuall Selling === --- - -- do the priorities right! - if itemTable.value ~= 0 and not excludeByID and (sellByID - or (not excludeByString and (sellByString or itemTable.quality == 0 or sellGear))) then - - if i == 1 then - BrokerGarbage:Debug("Inventory scans locked") - locked = true + if not BrokerGarbage.isAtVendor then return end + + if self == _G["BrokerGarbage_SellIcon"] then + BrokerGarbage:Debug("AutoSell was triggered by a click on Sell Icon.") + end + local sell, classification + local item, itemID, value, count, numSlots + sellValue = 0 + + for container = 0, 4 do + numSlots = GetContainerNumSlots(container) + if numSlots then + for slot = 1, numSlots do + _, count, _, _, _, _, itemLink = GetContainerItemInfo(container, slot) + if itemLink then + itemID = BrokerGarbage:GetItemID(itemLink) + item = BrokerGarbage:GetCached(itemID) + value = item.value + + sell = false + -- various cases that have us sell this item + if item.classification == BrokerGarbage.UNUSABLE then + local quality = select(3, GetItemInfo(itemID)) + if BG_GlobalDB.sellNotWearable and quality <= BG_GlobalDB.sellNWQualityTreshold then + sell = true + end + + elseif item.classification == BrokerGarbage.INCLUDE and BG_GlobalDB.autoSellIncludeItems then + sell = true + + elseif item.classification == BrokerGarbage.VENDORLIST then + sell = true + end + + -- Actual Selling + if value ~= 0 and sell then + if not locked then + BrokerGarbage:Debug("Inventory scans locked") + locked = true + end + + BrokerGarbage:Debug("Selling", itemID) + ClearCursor() + UseContainerItem(container, slot) + + sellValue = sellValue + (count * value) + -- update statistics + BG_GlobalDB.moneyEarned = BG_GlobalDB.moneyEarned + (count * value) + BG_LocalDB.moneyEarned = BG_LocalDB.moneyEarned + (count * value) + BG_GlobalDB.itemsSold = BG_GlobalDB.itemsSold + count + end end - - BrokerGarbage:Debug("Selling", itemTable.itemID) - sellValue = sellValue + itemTable.value - BG_GlobalDB.moneyEarned = BG_GlobalDB.moneyEarned + itemTable.value - BG_LocalDB.moneyEarned = BG_LocalDB.moneyEarned + itemTable.value - - ClearCursor() - UseContainerItem(itemTable.bag, itemTable.slot) - BG_GlobalDB.itemsSold = BG_GlobalDB.itemsSold + itemTable.count - i = i+1 end end - - if self == _G["BrokerGarbage_SellIcon"] then - if sellValue == 0 and BG_GlobalDB.reportNothingToSell then - BrokerGarbage:Print(BrokerGarbage.locale.reportNothingToSell) - elseif sellValue ~= 0 and not BG_GlobalDB.autoSellToVendor then - BrokerGarbage:Print(format(BrokerGarbage.locale.sell, BrokerGarbage:FormatMoney(sellValue))) - end - _G["BrokerGarbage_SellIcon"]:GetNormalTexture():SetDesaturated(true) + end + + -- create output if needed + if self == _G["BrokerGarbage_SellIcon"] then + if sellValue == 0 and BG_GlobalDB.reportNothingToSell then + BrokerGarbage:Print(BrokerGarbage.locale.reportNothingToSell) + elseif sellValue ~= 0 and not BG_GlobalDB.autoSellToVendor then + BrokerGarbage:Print(format(BrokerGarbage.locale.sell, BrokerGarbage:FormatMoney(sellValue))) end + _G["BrokerGarbage_SellIcon"]:GetNormalTexture():SetDesaturated(true) end end @@ -916,12 +828,10 @@ function BrokerGarbage:AutoRepair() if cost > 0 and CanGuildBankRepair() and GetGuildBankWithdrawMoney() >= cost and not BG_LocalDB.neverRepairGuildBank then -- guild repair if we're allowed to and the user wants it - -- RepairAllItems(1) - securecall(RepairAllItems, 1) + RepairAllItems(1) elseif cost > 0 and money >= cost then -- not enough allowance to guild bank repair, pay ourselves - --RepairAllItems(0) - securecall(RepairAllItems, 0) + RepairAllItems(0) elseif cost > 0 then -- oops. give us your moneys! BrokerGarbage:Print(format(BrokerGarbage.locale.couldNotRepair, BrokerGarbage:FormatMoney(cost))) diff --git a/helper.lua b/helper.lua index e1a4136..4e8dd10 100644 --- a/helper.lua +++ b/helper.lua @@ -1,8 +1,7 @@ +-- to enable debug mode, run this (disable by setting it to false): +-- /run BG_GlobalDB.debug = true _, BrokerGarbage = ... -local debug = false -- set this to 'true' to get your chatframe spammed :D - - -- Addon Basics -- --------------------------------------------------------- -- output functions @@ -10,8 +9,9 @@ function BrokerGarbage:Print(text) DEFAULT_CHAT_FRAME:AddMessage("|cffee6622Broker_Garbage|r "..text) end +-- prints debug messages only when debug mode is active function BrokerGarbage:Debug(...) - if debug then + if BG_GlobalDB.debug then BrokerGarbage:Print("! "..string.join(", ", tostringall(...))) end end @@ -19,7 +19,7 @@ end -- warn the player by displaying a warning message function BrokerGarbage:Warning(text) if BG_GlobalDB.showWarnings and time() - lastReminder >= 5 then - BrokerGarbage:Print("|cfff0000Warning:|r ", text) + BrokerGarbage:Print("|cfff0000Warning!|r ", text) lastReminder = time() end end @@ -66,16 +66,13 @@ function BrokerGarbage:JoinSimpleTables(...) return result end +-- counts table entries. for numerically indexed tables, use #table function BrokerGarbage:Count(table) local i = 0 for _, _ in pairs(table) do i = i + 1 end return i end -function BrokerGarbage:ErrorReport() - -- TODO -end - -- Saved Variables Management / API -- --------------------------------------------------------- function BrokerGarbage:CheckSettings() @@ -137,8 +134,10 @@ function BrokerGarbage:CreateDefaultLists(global) -- class specific if BrokerGarbage.playerClass == "HUNTER" then BG_LocalDB.exclude["Misc.Reagent.Ammo"] = true + elseif BrokerGarbage.playerClass == "WARRIOR" or BrokerGarbage.playerClass == "ROGUE" or BrokerGarbage.playerClass == "DEATHKNIGHT" then BG_LocalDB.autoSellList["Consumable.Water"] = true + elseif BrokerGarbage.playerClass == "SHAMAN" then if not BG_LocalDB.include[17058] then BG_LocalDB.include[17058] = 20 end -- fish oil if not BG_LocalDB.include[17057] then BG_LocalDB.include[17057] = 20 end -- scales @@ -209,8 +208,13 @@ function BrokerGarbage:FormatString(text) else item = BrokerGarbage.cheapestItem end + -- [junkvalue] - text = string.gsub(text, "%[junkvalue%]", BrokerGarbage:FormatMoney(BrokerGarbage.toSellValue)) + local junkValue = 0 + for i = 0, 4 do + junkValue = junkValue + BrokerGarbage.toSellValue[i] + end + text = string.gsub(text, "%[junkvalue%]", BrokerGarbage:FormatMoney(junkValue)) -- [itemname][itemcount][itemvalue] text = string.gsub(text, "%[itemname%]", (select(2,GetItemInfo(item.itemID)) or "")) @@ -314,7 +318,8 @@ function BrokerGarbage:CheckSkills() end local scanTooltip = CreateFrame('GameTooltip', 'BGItemScanTooltip', UIParent, 'GameTooltipTemplate') -function BrokerGarbage:CanDisenchant(itemLink, myself) +-- misc: either "true" to check only for the current character, or a table {container, slot} for reference +function BrokerGarbage:CanDisenchant(itemLink, misc) if (itemLink) then local _, _, quality, level, _, _, _, count, bagSlot = GetItemInfo(itemLink) @@ -349,12 +354,13 @@ function BrokerGarbage:CanDisenchant(itemLink, myself) end -- if skill is too low, still check if we can send it end - if myself then return false end -- we can't diss ourselves. hrm. maybe we can! + -- misc = "true" => we only care if we ourselves can DE. no twink mail etc. + if misc and type(misc) == "boolean" then return false end -- so we can't DE, but can we send it to someone who may? i.e. is the item not soulbound? if not BG_GlobalDB.hasEnchanter then return false end - if BrokerGarbage.checkItem then - return not BrokerGarbage:IsItemSoulbound(itemLink, BrokerGarbage.checkItem.bag, BrokerGarbage.checkItem.slot) + if misc and type(misc) == "table" then + return not BrokerGarbage:IsItemSoulbound(itemLink, misc.bag, misc.slot) else return not BrokerGarbage:IsItemSoulbound(itemLink) end @@ -390,6 +396,165 @@ function BrokerGarbage:IsItemSoulbound(itemLink, bag, slot) return false end +-- gets an item's classification and saves it to the item cache +function BrokerGarbage:UpdateCache(itemID) + if not itemID then return nil end + local class, temp, limit + + local _, itemLink, quality, _, _, _, subClass, stackSize, invType, _, value = GetItemInfo(itemID) + + -- check if item is excluded by itemID + if BG_GlobalDB.exclude[itemID] or BG_LocalDB.exclude[itemID] then + BrokerGarbage:Debug("Item "..itemID.." is excluded via its itemID.") + class = BrokerGarbage.EXCLUDE + end + + -- check if the item is classified by its itemID + if not class then + if BG_GlobalDB.include[itemID] or BG_LocalDB.include[itemID] then + + if BG_LocalDB.include[itemID] and type(BG_LocalDB.include[itemID]) ~= "boolean" then + -- limited item, local rule + BrokerGarbage:Debug("Item "..itemID.." is locally limited via its itemID.") + class = BrokerGarbage.LIMITED + limit = BG_LocalDB.include[itemID] + + elseif BG_GlobalDB.include[itemID] and type(BG_GlobalDB.include[itemID]) ~= "boolean" then + -- limited item, global rule + BrokerGarbage:Debug("Item "..itemID.." is globally limited via its itemID.") + class = BrokerGarbage.LIMITED + limit = BG_GlobalDB.include[itemID] + + else + BrokerGarbage:Debug("Item "..itemID.." is included via its itemID.") + class = BrokerGarbage.INCLUDE + end + + elseif BG_GlobalDB.autoSellList[itemID] or BG_LocalDB.autoSellList[itemID] + or BG_GlobalDB.forceVendorPrice[itemID] then + + BrokerGarbage:Debug("Item "..itemID.." has a forced vendor price via its itemID.") + class = BrokerGarbage.VENDORLIST + + elseif quality + and not IsUsableSpell(BrokerGarbage.enchanting) and BrokerGarbage:IsItemSoulbound(itemLink) + and string.find(invType, "INVTYPE") and not string.find(invType, "BAG") + and not BrokerGarbage.usableByClass[BrokerGarbage.playerClass][subClass] + and not BrokerGarbage.usableByAll[invType] then + + BrokerGarbage:Debug("Item "..itemID.." should be sold as we can't ever wear it.") + class = BrokerGarbage.UNUSABLE + + -- check if the item is classified by its category + else + -- check if item is excluded by its category + for setName,_ in pairs(BrokerGarbage:JoinTables(BG_GlobalDB.exclude, BG_LocalDB.exclude)) do + if type(setName) == "string" then + _, temp = BrokerGarbage.PT:ItemInSet(itemID, setName) + end + if temp then + BrokerGarbage:Debug("Item "..itemID.." is excluded via its category.") + class = BrokerGarbage.EXCLUDE + break + end + end + + -- Include List + if not class then + for setName,_ in pairs(BrokerGarbage:JoinTables(BG_LocalDB.include, BG_GlobalDB.include)) do + if type(setName) == "string" then + _, temp = BrokerGarbage.PT:ItemInSet(itemID, setName) + end + if temp then + BrokerGarbage:Debug("Item "..itemID.." in included via its item category.") + class = BrokerGarbage.INCLUDE + break + end + end + end + + -- Sell List + if not class then + for setName,_ in pairs(BrokerGarbage:JoinTables(BG_GlobalDB.autoSellList, BG_LocalDB.autoSellList)) do + if type(setName) == "string" then + _, temp = BrokerGarbage.PT:ItemInSet(itemID, setName) + end + if temp then + BrokerGarbage:Debug("Item "..itemID.." is on the sell list via its item category.") + class = BrokerGarbage.VENDORLIST + break + end + end + end + + -- Force Vendor Price List + if not class then + for setName,_ in pairs(BG_GlobalDB.forceVendorPrice) do + if type(setName) == "string" then + _, temp = BrokerGarbage.PT:ItemInSet(itemID, setName) + end + if temp then + BrokerGarbage:Debug("Item "..itemID.." has a forced vendor price via its item category.") + class = BrokerGarbage.VENDOR + break + end + end + end + end + end + + if not class then + value, class = BrokerGarbage:GetSingleItemValue(itemID) + end + if not value then + value = 0 + end + + -- save to items cache + if not BrokerGarbage.itemsCache[itemID] then + BrokerGarbage.itemsCache[itemID] = { + classification = class, + quality = quality, + value = value, + limit = limit, + stackSize = stackSize, + isClam = BrokerGarbage:Find(BrokerGarbage.clams, itemID), + } + else + BrokerGarbage.itemsCache[itemID].classification = class + BrokerGarbage.itemsCache[itemID].quality = quality + BrokerGarbage.itemsCache[itemID].value = value + BrokerGarbage.itemsCache[itemID].limit = limit + BrokerGarbage.itemsCache[itemID].stackSize = stackSize + BrokerGarbage.itemsCache[itemID].isClam = BrokerGarbage:Find(BrokerGarbage.clams, itemID) + end +end + +-- fetch an item from the item cache, or insert if it doesn't exist yet +function BrokerGarbage:GetCached(itemID) + if not BrokerGarbage.itemsCache[itemID] then + BrokerGarbage:UpdateCache(itemID) + end + return BrokerGarbage.itemsCache[itemID] +end + +-- returns total bag slots and free bag slots of your whole inventory +function BrokerGarbage:GetBagSlots() + local total, free = 0, 0 + local num + + for i = 0, 4 do + num = GetContainerNumSlots(i) + if num then + total = total + num + free = free + (GetContainerFreeSlots(i) and #GetContainerFreeSlots(i) or 0) + end + end + + return total, free +end + +-- formats money int values, depending on settings function BrokerGarbage:FormatMoney(amount) if not amount then return "" end diff --git a/options.lua b/options.lua index dd73139..acb6c5b 100644 --- a/options.lua +++ b/options.lua @@ -899,7 +899,8 @@ local function ShowListOptions(frame) -- function to set the drop treshold (limit) via the mousewheel local function OnMouseWheel(self, dir) if type(self.itemID) ~= "number" then return end - BrokerGarbage.debug = self + -- clear item from cache + BrokerGarbage.itemsCache[self.itemID] = nil local list, text if dir == 1 then @@ -1124,9 +1125,11 @@ local function ShowListOptions(frame) if itemID then -- real items itemID = itemID + BrokerGarbage.itemsCache[itemID] = nil else -- category strings itemID = item + BrokerGarbage.itemsCache = {} end -- create "link" for output @@ -1255,6 +1258,7 @@ local function ShowListOptions(frame) -- empty action if self == emptyExcludeList then + BrokerGarbage.itemsCache = {} if IsShiftKeyDown() then BG_GlobalDB.exclude = {} else @@ -1262,11 +1266,13 @@ local function ShowListOptions(frame) end BrokerGarbage:ListOptionsUpdate("exclude") elseif self == emptyForcePriceList then + BrokerGarbage.itemsCache = {} if IsShiftKeyDown() then BG_GlobalDB.forceVendorPrice = {} BrokerGarbage:ListOptionsUpdate("forceprice") end elseif self == emptyIncludeList then + BrokerGarbage.itemsCache = {} if IsShiftKeyDown() then BG_GlobalDB.include = {} else @@ -1274,6 +1280,7 @@ local function ShowListOptions(frame) end BrokerGarbage:ListOptionsUpdate("include") elseif self == emptyAutoSellList then + BrokerGarbage.itemsCache = {} if IsShiftKeyDown() then BG_GlobalDB.autoSellList = {} else @@ -1285,6 +1292,11 @@ local function ShowListOptions(frame) elseif self == minus then for i, button in pairs(BrokerGarbage.listButtons.exclude) do if button:GetChecked() then + if type(button.itemID) == "number" then + BrokerGarbage.itemsCache[button.itemID] = nil + else + BrokerGarbage.itemsCache = {} + end BG_LocalDB.exclude[button.itemID] = nil BG_GlobalDB.exclude[button.itemID] = nil end @@ -1294,6 +1306,11 @@ local function ShowListOptions(frame) elseif self == minus2 then for i, button in pairs(BrokerGarbage.listButtons.forceprice) do if button:GetChecked() then + if type(button.itemID) == "number" then + BrokerGarbage.itemsCache[button.itemID] = nil + else + BrokerGarbage.itemsCache = {} + end BG_GlobalDB.forceVendorPrice[button.itemID] = nil end end @@ -1302,6 +1319,11 @@ local function ShowListOptions(frame) elseif self == minus3 then for i, button in pairs(BrokerGarbage.listButtons.include) do if button:GetChecked() then + if type(button.itemID) == "number" then + BrokerGarbage.itemsCache[button.itemID] = nil + else + BrokerGarbage.itemsCache = {} + end BG_LocalDB.include[button.itemID] = nil BG_GlobalDB.include[button.itemID] = nil end @@ -1311,6 +1333,11 @@ local function ShowListOptions(frame) elseif self == minus4 then for i, button in pairs(BrokerGarbage.listButtons.autosell) do if button:GetChecked() then + if type(button.itemID) == "number" then + BrokerGarbage.itemsCache[button.itemID] = nil + else + BrokerGarbage.itemsCache = {} + end BG_LocalDB.autoSellList[button.itemID] = nil BG_GlobalDB.autoSellList[button.itemID] = nil end @@ -1498,6 +1525,8 @@ function SlashCmdList.BROKERGARBAGE(msg, editbox) itemID = tonumber(itemID) count = tonumber(count) + BrokerGarbage.itemsCache[itemID] = nil + if string.find(command, "g") then BG_GlobalDB.include[itemID] = count else -- 1.7.9.5