local L = AceLibrary("AceLocale-2.0"):new("FuBar_GarbageFu") local Tablet = AceLibrary("Tablet-2.0"); local dewdrop = AceLibrary("Dewdrop-2.0"); local compost = AceLibrary("Compost-2.0"); local abacus = AceLibrary("Abacus-2.0"); local PeriodicTable = PeriodicTableEmbed:GetInstance("1"); GarbageFu = AceLibrary("AceAddon-2.0"):new("FuBarPlugin-2.0", "AceEvent-2.0", "AceConsole-2.0", "AceDB-2.0", "AceDebug-2.0"); GarbageFu.version = "1.0." .. string.sub("$Revision: 10349 $", 12, -3); GarbageFu.date = string.sub("$Date: 2006-09-06 11:24:19 -0700 (Wed, 06 Sep 2006) $", 8, 17); GarbageFu.hasIcon = true; GarbageFu.clickableTooltip = true; GarbageFu.overrideMenu = true; GarbageFu.printFrame = DEFAULT_CHAT_FRAME; GarbageFu.debugFrame = DEFAULT_CHAT_FRAME; GarbageFu:RegisterDB("GarbageFuDB"); GarbageFu:RegisterDefaults("profile", { moneyformat = 1, namelength = 32, ignoreammobag = true, ignoreherbbag = false, ignoresoulbag = false, ignoreenchbag = false, sellallbutton = true, sellonlygrey = true, pricetype = false, garbageprices = false, itemicon = false, version = "", textcolor = { r=0.2, g=0.8, b=1 }; threshold = 0, dropsets = {}, dropitem = {}, keepsets = {}, keepitem = {}, }); GarbageFu:RegisterDefaults("account", { overrideprices = {}; }); ------------------------------------------------------------------------------------------------------ -- Simple Property functions ------------------------------------------------------------------------------------------------------ function GarbageFu:IsAutodrop() return self.db.profile.autodrop; end function GarbageFu:ToggleAutodrop() self.db.profile.autodrop = not self.db.profile.autodrop; end function GarbageFu:GetDropThreshold() return self.db.profile.threshold; end function GarbageFu:IsDropThreshold(value) return self.db.profile.threshold == tonumber(value); end function GarbageFu:SetDropThreshold(value) self.db.profile.threshold = tonumber(value); self:UpdateDisplay(); end function GarbageFu:GetMoneyFormat(value) return self.db.profile.moneyformat; end function GarbageFu:SetMoneyFormat(value) self.db.profile.moneyformat = tonumber(value); self:UpdateDisplay(); end function GarbageFu:GetNameLength(value) return self.db.profile.namelength; end function GarbageFu.SetNameLength(self,value) self.db.profile.namelength = value; self:UpdateText(); end function GarbageFu:IsIgnoringAmmoBag() return self.db.profile.ignoreammobag; end function GarbageFu:ToggleIgnoreAmmoBag() self.db.profile.ignoreammobag = not self.db.profile.ignoreammobag; self:InitBagScan(); end function GarbageFu:IsIgnoringHerbBag() return self.db.profile.ignoreherbbag; end function GarbageFu:ToggleIgnoreHerbBag() self.db.profile.ignoreherbbag = not self.db.profile.ignoreherbbag; self:InitBagScan(); end function GarbageFu:IsIgnoringSoulBag() return self.db.profile.ignoresoulbag; end function GarbageFu:ToggleIgnoreSoulBag() self.db.profile.ignoresoulbag = not self.db.profile.ignoresoulbag; self:InitBagScan(); end function GarbageFu:IsIgnoringEnchBag() return self.db.profile.ignoreenchbag; end function GarbageFu:ToggleIgnoreEnchBag() self.db.profile.ignoreenchbag = not self.db.profile.ignoreenchbag; self:InitBagScan(); end function GarbageFu:IsSafeToDelete() return self.vars.safedelete; end function GarbageFu:SetSafeToDelete(value) self.vars.safedelete = value; end function GarbageFu:IsSellAllButton() return self.db.profile.sellallbutton; end function GarbageFu:ToggleSellAllButton() self.db.profile.sellallbutton = not self.db.profile.sellallbutton; if self.db.profile.sellallbutton then MerchantFrame.sellAllButton:Show(); else MerchantFrame.sellAllButton:Hide(); end end function GarbageFu:IsItemIcon() return self.db.profile.itemicon; end function GarbageFu:ToggleItemIcon() self.db.profile.itemicon = not self.db.profile.itemicon; self:UpdateText(); end function GarbageFu:IsPriceType() return self.db.profile.pricetype; end function GarbageFu:TogglePriceType() self.db.profile.pricetype = not self.db.profile.pricetype; self:UpdateTooltip(); end function GarbageFu:IsSellOnlyGrey() return self.db.profile.sellonlygrey; end function GarbageFu:ToggleSellOnlyGrey() self.db.profile.sellonlygrey = not self.db.profile.sellonlygrey; end function GarbageFu:IsUsingGarbagePrices() return self.db.profile.garbageprices; end function GarbageFu:ToggleUseGarbagePrices() self.db.profile.garbageprices = not self.db.profile.garbageprices; if ( self.db.profile.garbageprices ) then self.db.profile.garbageprices = self:LoadGarbagePrices(); else self.vars.vendorprices = nil; self.vars.pricecache = self:Table(self.vars.pricecache); end self:InitBagScan(); end ------------------------------------------------------------------------------------------------------ -- A little more complicate property functions ------------------------------------------------------------------------------------------------------ function GarbageFu:IsDropItem(itemid) if (self.db.profile.dropitem[itemid]) then return true end end function GarbageFu:ToggleDropItem(itemid) if (self.db.profile.dropitem[itemid]) then self.db.profile.dropitem[itemid] = nil; else self.db.profile.dropitem[itemid] = true; self.db.profile.keepitem[itemid] = nil; end self:UpdateDisplay(); end function GarbageFu:IsKeepItem(itemid) if (self.db.profile.keepitem[itemid]) then return true end end function GarbageFu:ToggleKeepItem(itemid) if (self.db.profile.keepitem[itemid]) then self.db.profile.keepitem[itemid] = nil; else self.db.profile.keepitem[itemid] = true; self.db.profile.dropitem[itemid] = nil; end self:UpdateDisplay(); end ------------------------------------------------------------------------------------------------------ -- Constant data ------------------------------------------------------------------------------------------------------ GarbageFu.vars = {}; GarbageFu.vars.moneyformats = { { name=L["Condensed"], ex=abacus:FormatMoneyCondensed(123456,true,true) }, { name=L["Short"], ex=abacus:FormatMoneyShort(123456,true,true) }, { name=L["Full"], ex=abacus:FormatMoneyFull(123456,true,true) }, { name=L["Extended"], ex=abacus:FormatMoneyExtended(123456,true,true) }, } GarbageFu.vars.sets = { {id="foodall", name=L["Food"], order=1, sub = { {id="food", name=L["Normal Food"], order=1 }, {id="foodbonus", name=L["Bonus Food"], order=2 }, {id="foodstat", name=L["Stat Food"], order=3 }, {id="foodbreadconjured", name=L["Conjured Bread"], order=4 }, {id="foodraw", name=L["Raw Food"], order=5 }, {id="foodclassbread", name=L["Bread"], order=6 }, {id="foodclassfish", name=L["Fish"], order=7 }, {id="foodclassmeat", name=L["Meat"], order=8 }, {id="foodclasscheese", name=L["Cheese"], order=9 }, {id="foodclassfruit", name=L["Fruit"], order=10 }, {id="foodclassfungus", name=L["Fungus"], order=11 }, }, }, {id="waterall", name=L["Water"], order=2, sub = { {id="water", name=L["Normal Water"], order=1 }, {id="waterperc", name=L["Percent Water"], order=2 }, {id="waterconjured", name=L["Conjured Water"], order=3 }, }, }, {id="booze", name=L["Booze"], order=3 }, {id="tradeskills", name=L["Tradeskill"], order=4, sub = { {id="tradeskillalchemy", name=L["Alchemy"], order=1 }, {id="tradeskillblacksmithing", name=L["Blacksmithing"], order=2 }, {id="tradeskillcooking", name=L["Cooking"], order=3 }, {id="tradeskillenchanting", name=L["Enchanting"], order=4 }, {id="tradeskillengineering", name=L["Engineering"], order=5 }, {id="tradeskillfirstaid", name=L["First Aid"], order=6 }, {id="tradeskillleatherworking", name=L["Leatherworking"], order=7 }, {id="tradeskilltailoring", name=L["Tailoring"], order=8 }, {id="tradeskillpoison", name=L["Poison"], order=9 }, {id="tradeskillsmelting", name=L["Smelting"], order=10 }, }, }, {id="tradeskilltools", name=L["Tradeskill Tools"], order=5 }, {id="gatherskill", name=L["Gathered"], order=6, sub = { {id="gatherskillfishing", name=L["Fishing"], order=1 }, {id="gatherskilldisenchant", name=L["Disenchant"], order=2 }, {id="gatherskillherbalism", name=L["Herbalism"], order=3 }, {id="gatherskillmining", name=L["Mining"], order=4 }, {id="gatherskillskinning", name=L["Skinning"], order=5 }, }, }, {id="ammo", name=L["Ammunition"], order=7 }, {id="bandages", name=L["Bandages"], order=8 }, {id="explosives", name=L["Explosives"], order=9 }, {id="faire", name=L["Darkmoon Fair"], order=10 }, {id="fireworks", name=L["Fireworks"], order=11 }, {id="poisons", name=L["Poisons"], order=12 }, {id="potionall", name=L["Potions"], order=13, sub = { {id="potionhealall", name=L["Heal Potions"], order=1 }, {id="potionmanaall", name=L["Mana Potions"], order=2 }, {id="potionrage", name=L["Rage Potions"], order=3 }, {id="potioncure", name=L["Cure Potions"], order=4 }, {id="potionbuff", name=L["Buff Potions"], order=5 }, }, }, {id="scrolls", name=L["Scrolls"], order=14 }, {id="reagent", name=L["Reagents"], order=15, sub = { {id="reagentpaladin", name=L["Paladin"], order=1 }, {id="reagentdruid", name=L["Druid"], order=2 }, {id="reagentmage", name=L["Mage"], order=3 }, {id="reagentpriest", name=L["Priest"], order=4 }, {id="reagentrogue", name=L["Rogue"], order=5 }, {id="reagentshaman", name=L["Shaman"], order=6 }, {id="reagentwarlock", name=L["Warlock"], order=7 }, }, }, {id="weapontempenchants", name=L["Weapon Enchants"], order=16 }, {id="mounts", name=L["Mounts"], order=17 }, {id="minipetall", name=L["Mini Pets"], order=18 }, } ------------------------------------------------------------------------------------------------------ -- FuBar required functions ------------------------------------------------------------------------------------------------------ function GarbageFu:OnInitialize() -- Put stuff that only neeeds to be done once here self.vars.bags = self:Table(); self.vars.items = self:Table(); self.vars.colors = self:Table(); self.vars.pricecache = self:Table(); -- Get Item quality colors for i=0,6 do self.vars.colors[i] = self:Table(); self.vars.colors[i].r, self.vars.colors[i].g, self.vars.colors[i].b, self.vars.colors[i].hex = GetItemQualityColor(i); self.vars.colors[i].desc = getglobal("ITEM_QUALITY".. i.. "_DESC"); end -- Create Static dialog for Reset Settings StaticPopupDialogs["GARBAGEFU_RESET"] = { text = L["Are you sure you want to reset all your settings for GarbageFU?"], button1 = TEXT(ACCEPT), button2 = TEXT(CANCEL), OnAccept = function() GarbageFu.SettingsReset(self) end, timeout = 0, whileDead = 1, hideOnEscape = 1 }; -- Sort Sets tables for i,s in self.vars.sets do if s.sub then table.sort(s.sub,function(a,b) return a.order self:GetNameLength() ) then text = self.vars.colors[item.qual].hex..string.sub(item.name, 1, self:GetNameLength()-2).."..".."|r"; else text = self.vars.colors[item.qual].hex..item.name.."|r"; end if ( item.maxstack > 1 ) then text = text.." |cffffff00x"..tostring(item.stack).."|r"; end text = text.." "..self:GetMoneyString(item.totvalue); self:SetText(text); if self:IsItemIcon() then self:SetIcon(item.tex) else self:SetIcon(true) end else self:SetText("GarbageFu"); self:SetIcon(true); end if self:IsThereItemsToSell() then MerchantFrame.sellAllButton:Enable(); else MerchantFrame.sellAllButton:Disable(); end end function GarbageFu:OnTooltipUpdate() self:DebugPrint("OnTooltipUpdate"); local cat; if self:IsPriceType() then cat = Tablet:AddCategory('columns', 3) else cat = Tablet:AddCategory('columns', 2) end for i,item in self.vars.items do if self:IsItemDroppable(item) then local stacktext = "|r"; if ( item.maxstack > 1 ) then stacktext = stacktext .. "|r |cffffff00("..tostring(item.stack).."/"..tostring(item.maxstack)..")|r"; end local moneytext = self:GetMoneyString(item.totvalue) cat:AddLine( 'text', self.vars.colors[item.qual].hex..item.name..stacktext, 'text2', moneytext, 'text3', item.pricetype, 'hasCheck', true, 'checked', true, 'checkIcon', item.tex, 'func', 'OnClickItem', 'arg1', self, 'arg2', item ) end end if MerchantFrame:IsVisible() then Tablet:SetHint(L["Shift-Click to sell item\nControl-Click to add item to keep list"]); else Tablet:SetHint(L["Shift-Click to drop item\nControl-Click to add item to keep list"]); end end function GarbageFu:OnMenuRequest(level, value, inTooltip, value2) if value then if value2 then self:DebugPrint("OnMenuRequest level="..level.." value="..value.." value2="..value2); else self:DebugPrint("OnMenuRequest level="..level.." value="..value); end else self:DebugPrint("OnMenuRequest level="..level); end if ( level == 1 ) then local item = self:GetFirstDroppableItem(); if item then local text = self.vars.colors[item.qual].hex..item.name.."|r"; if ( item.maxstack > 1 ) then text = text.." |cffffff00x"..tostring(item.stack).."|r"; end dewdrop:AddLine('text', text..' '..self:GetMoneyString(item.totvalue), 'notClickable', true, 'checked', true, 'checkIcon', item.tex ); local text = MerchantFrame:IsVisible() and L["Sell this item"] or L["Drop this item"]; dewdrop:AddLine('text', text, 'arg1', self, 'func', 'DropFirstItem', 'tooltipTitle', text, 'tooltipText', L["Drops this item, or sells it if the vendor window is open"] ); if ( item.qual > 0 ) then dewdrop:AddLine('text', L["Keep this item"], 'arg1', self, 'func', 'KeepFirstItem', 'tooltipTitle', L["Keep this item"], 'tooltipText', L["Adds this item to the keep items list"]); end if MerchantFrame:IsVisible() and self:IsThereItemsToSell() then local sellValue = self:GetSellValue(); GameTooltip:AddLine(L["Value:"].." "..self:GetMoneyString(sellValue)); if self:IsSellOnlyGrey() then dewdrop:AddLine('text', L["Sell all grey items"].." "..self:GetMoneyString(sellValue), 'arg1', self, 'func', 'SellAllItems', 'tooltipTitle', L["Sell all grey items"], 'tooltipText', L["SellsAll TooltipText2"], 'closeWhenClicked', true ); else dewdrop:AddLine('text', L["Sell all garbage items"].." "..self:GetMoneyString(sellValue), 'arg1', self, 'func', 'SellAllItems', 'tooltipTitle', L["Sell all garbage items"], 'tooltipText', L["SellsAll TooltipText1"], 'closeWhenClicked', true ); end end if ( item.qual > 0 or item.totvalue == 0 or self.db.account.overrideprices[item.id]) then dewdrop:AddLine('text', L["Edit value for this item"], 'hasArrow', true, 'hasEditBox', true, 'editBoxText', tostring(item.value), 'editBoxArg1', self, 'editBoxFunc', GarbageFu.SetFirstItemValue, 'editBoxChangeArg1', self, 'editBoxChangeFunc', GarbageFu.ValidateValue, 'tooltipTitle', L["Edit value for this item"], 'tooltipText', L["Value TooltipText"] ); end dewdrop:AddLine(); end dewdrop:AddLine('text', L["Drop"], 'hasArrow', true, 'value', 'drop' ); dewdrop:AddLine('text', L["Keep"], 'hasArrow', true, 'value', 'keep' ); dewdrop:AddLine('text', L["Edit item values"], 'hasArrow', true, 'value', 'itemvalue' ); dewdrop:AddLine(); dewdrop:AddLine('text', L["Options"], 'hasArrow', true, 'value', 'options' ); elseif ( level == 2 ) then if ( value == 'drop' ) then dewdrop:AddLine('text', L["Drop"], "isTitle", true ); dewdrop:AddLine('text', L["Drop Sets"], 'hasArrow', true, 'value', 'dropsets' ); dewdrop:AddLine('text', L["Drop Items"], 'hasArrow', true, 'value', 'dropitem' ); elseif ( value == 'keep' ) then dewdrop:AddLine('text', L["Keep"], "isTitle", true ); dewdrop:AddLine('text', L["Keep Sets"], 'hasArrow', true, 'value', 'keepsets' ); dewdrop:AddLine('text', L["Keep Items"], 'hasArrow', true, 'value', 'keepitem' ); elseif ( value == 'itemvalue' ) then -- Edit item values dewdrop:AddLine('text', L["Edit item values"], "isTitle", true ); local tbl = self:GetCustomItemValueTable(); for _,i in tbl do dewdrop:AddLine('text', self.vars.colors[i.qual].hex .. i.name, 'checked', self.db.account.overrideprices[i.id] ~= nil, 'hasArrow', true, 'hasEditBox', true, 'editBoxText', tostring(i.value), 'editBoxArg1', self, 'editBoxArg2', i.id, 'editBoxFunc', GarbageFu.SetItemValue, 'editBoxChangeArg1', self, 'editBoxChangeFunc', GarbageFu.ValidateValue, 'tooltipTitle', L["Edit value for this item"], 'tooltipText', L["Value TooltipText"]); end --compost:Reclaim(tbl,2); --tbl = nil; elseif ( value == 'options' ) then dewdrop:AddLine('text', L["Drop Threshold"], 'hasArrow', true, 'value', 'threshold' ); dewdrop:AddLine('text', L["Money Format"], 'hasArrow', true, 'value', 'moneyformat' ); dewdrop:AddLine('text', L["Max Item Name Length"], 'hasArrow', true, 'hasSlider', true, 'sliderMin', 5, 'sliderMax', 32, 'sliderStep', 1, 'sliderValue', self:GetNameLength(), 'sliderFunc', GarbageFu.SetNameLength, 'sliderArg1', self ); dewdrop:AddLine('text', L["Sell All Button on Merchant Window"], 'checked', self:IsSellAllButton(), 'arg1', self, 'func', 'ToggleSellAllButton', 'tooltipTitle', L["Sell All Button on Merchant Window"], 'tooltipText', L["SellAllButton TooltipText"]); dewdrop:AddLine('text', L["Only Autosell Grey Items"], 'checked', self:IsSellOnlyGrey(), 'arg1', self, 'func', 'ToggleSellOnlyGrey', 'tooltipTitle', L["Only Autosell Grey Items"], 'tooltipText', L["OnlyGrey TooltipText"]); dewdrop:AddLine('text', L["Use Items Icon on Toolbar"], 'checked', self:IsItemIcon(), 'arg1', self, 'func', 'ToggleItemIcon'); dewdrop:AddLine('text', L["Show Price Type in Tooltip"], 'checked', self:IsPriceType(), 'arg1', self, 'func', 'TogglePriceType'); dewdrop:AddLine('text', L["Use GarbageFu Prices"], 'checked', self:IsUsingGarbagePrices(), 'arg1', self, 'func', 'ToggleUseGarbagePrices', 'disabled', not self:IsGarbagePricesAvailable(), 'tooltipTitle', L["Use GarbageFu Prices"], 'tooltipText', L["GarbageFu_Prices ToltipText"]); dewdrop:AddLine('text', L["Ignore Ammo Bags"], 'checked', self:IsIgnoringAmmoBag(), 'arg1', self, 'func', 'ToggleIgnoreAmmoBag'); dewdrop:AddLine('text', L["Ignore Herb Bags"], 'checked', self:IsIgnoringHerbBag(), 'arg1', self, 'func', 'ToggleIgnoreHerbBag'); dewdrop:AddLine('text', L["Ignore Soulshard Bags"], 'checked', self:IsIgnoringSoulBag(), 'arg1', self, 'func', 'ToggleIgnoreSoulBag'); dewdrop:AddLine('text', L["Ignore Enchanting Bags"], 'checked', self:IsIgnoringEnchBag(), 'arg1', self, 'func', 'ToggleIgnoreEnchBag'); --dewdrop:AddLine('text', L["Rescan"], 'arg1', self, 'func', 'InitBagScan' ); dewdrop:AddLine('text', L["Reset"], 'arg1', "GARBAGEFU_RESET", 'func', StaticPopup_Show, 'closeWhenClicked', true ); dewdrop:AddLine(); self:AddImpliedMenuOptions(2); end elseif ( level == 3 ) then if (value2 == 'drop') then if ( value == 'dropsets' ) then -- Drop - Sets dewdrop:AddLine('text', L["Drop Sets"], "isTitle", true ); for n,i in self.vars.sets do local checked = self:IsDropSet(n); local checkIcon = "Interface\\Buttons\\UI-CheckBox-Check" if self:IsChildDropSet(n) then checked = true; checkIcon = "Interface\\Buttons\\UI-CheckBox-Check-Disabled" end dewdrop:AddLine('text', i.name, 'checked', checked, 'checkIcon', checkIcon, 'disabled', self:IsKeepSet(n), 'hasArrow', i.sub ~= nil, 'value', n, 'arg1', self, 'arg2', n, 'func', 'ToggleDropSets' ); end elseif ( value == 'dropitem' ) then -- Drop - Items dewdrop:AddLine('text', L["Drop Items"], "isTitle", true ); local tbl = self:GetDropItemTable(); for _,i in tbl do dewdrop:AddLine('text', self.vars.colors[i.qual].hex .. i.name, 'checked', self:IsDropItem(i.id), 'arg1', self, 'arg2', i.id, 'func', 'ToggleDropItem'); end --compost:Reclaim(tbl,2); --tbl = nil; end elseif (value2 == 'keep') then if ( value == 'keepsets' ) then -- Keep - Sets dewdrop:AddLine('text', L["Keep Sets"], "isTitle", true ); for n,i in self.vars.sets do local checked = self:IsKeepSet(n); local checkIcon = "Interface\\Buttons\\UI-CheckBox-Check" if self:IsChildKeepSet(n) then checked = true; checkIcon = "Interface\\Buttons\\UI-CheckBox-Check-Disabled" end dewdrop:AddLine('text', i.name, 'checked', checked, 'checkIcon', checkIcon, 'disabled', self:IsDropSet(n), 'hasArrow', i.sub ~= nil, 'value', n, 'arg1', self, 'arg2', n, 'func', 'ToggleKeepSets' ); end elseif ( value == 'keepitem' ) then -- Keep - Items dewdrop:AddLine('text', L["Keep Items"], "isTitle", true ); local tbl = self:GetKeepItemTable(); for _,i in tbl do dewdrop:AddLine('text', self.vars.colors[i.qual].hex .. i.name, 'checked', self:IsKeepItem(i.id), 'arg1', self, 'arg2', i.id, 'func', 'ToggleKeepItem'); end --compost:Reclaim(tbl,2); --tbl = nil; end elseif ( value2 == 'options' ) then if ( value == 'threshold' ) then dewdrop:AddLine('text', L["Drop Threshold"], "isTitle", true ); for a=0,6 do dewdrop:AddLine('text', self.vars.colors[a].hex..self.vars.colors[a].desc.."|r", 'checked', a == self:GetDropThreshold(), 'arg1', self, 'arg2', a, 'isRadio', true, 'func', 'SetDropThreshold' ); end elseif ( value == 'moneyformat' ) then dewdrop:AddLine('text', L["Money Format"], "isTitle", true ); for a,f in self.vars.moneyformats do dewdrop:AddLine('text', f.name.."\t"..f.ex, 'checked', a == self:GetMoneyFormat(), 'arg1', self, 'arg2', a, 'isRadio', true, 'func', 'SetMoneyFormat' ); end else self:AddImpliedMenuOptions(2); end end elseif ( level == 4 ) then if ( value2 == 'dropsets' ) then dewdrop:AddLine('text', L["Drop Set"].." "..self.vars.sets[value].name, "isTitle", true ); for n,i in self.vars.sets[value].sub do dewdrop:AddLine('text', i.name, 'checked', self:IsDropSet(value,n), 'disabled',self:IsKeepSet(value,n), 'arg1', self, 'arg2', value, 'arg3', n, 'func', 'ToggleDropSets' ); end elseif ( value2 == 'keepsets' ) then dewdrop:AddLine('text', L["Keep Set"].." "..self.vars.sets[value].name, "isTitle", true ); for n,i in self.vars.sets[value].sub do dewdrop:AddLine('text', i.name, 'checked', self:IsKeepSet(value,n), 'disabled', self:IsDropSet(value,n), 'arg1', self, 'arg2', value, 'arg3', n, 'func', 'ToggleKeepSets' ); end end end end function GarbageFu:OnClick(button) if IsShiftKeyDown() then self:DropFirstItem(); end if IsControlKeyDown() then self:KeepFirstItem(); end end ------------------------------------------------------------------------------------------------------ -- Event functions ------------------------------------------------------------------------------------------------------ function GarbageFu:OnClickItem(item) if IsShiftKeyDown() then self:DropItem(item); end if IsControlKeyDown() then self:KeepItem(item); end end function GarbageFu:OnEnteringWorld() self:RegisterEvent("BAG_UPDATE","OnBagUpdate"); self:RegisterEvent("MERCHANT_SHOW","OnMerchantOpen"); self:RegisterEvent("MERCHANT_CLOSED","OnMerchantClose"); self:RegisterEvent("PLAYER_LEAVING_WORLD","OnLeavingWorld"); if self:IsEventRegistered("PLAYER_ENTERING_WORLD") then self:UnregisterEvent("PLAYER_ENTERING_WORLD") end end function GarbageFu:OnLeavingWorld() self:RegisterEvent("PLAYER_ENTERING_WORLD","OnEnteringWorld"); if self:IsEventRegistered("BAG_UPDATE") then self:UnregisterEvent("BAG_UPDATE") end if self:IsEventRegistered("MERCHANT_SHOW") then self:UnregisterEvent("MERCHANT_SHOW") end if self:IsEventRegistered("MERCHANT_CLOSED") then self:UnregisterEvent("MERCHANT_CLOSED") end if self:IsEventRegistered("PLAYER_LEAVING_WORLD") then self:UnregisterEvent("PLAYER_LEAVING_WORLD") end end function GarbageFu:OnBagUpdate(bag) -- local bag = arg1; self:DebugPrint("OnBagUpdate bag="..tostring(bag)); if ( not bag or bag < 0 or bag > 4 ) then return end if ( self.vars.bags[bag].bagName ~= GetBagName(bag) ) then -- Houston, we got a problem self:DebugPrint("New or changed bag detected. Doing a full scan"); self:InitBagScan(); -- New or changed bag detected. Do a full scan return end if self.vars.bags[bag].ignore then return end self:SetSafeToDelete(false); for slot=1,self.vars.bags[bag].numSlots do if not self.vars.bags[bag][slot] then self.vars.bags[bag][slot] = self:Table() end local link = GetContainerItemLink(bag, slot); local _, stack = GetContainerItemInfo(bag, slot); if ( link ~= self.vars.bags[bag][slot].link or stack ~= self.vars.bags[bag][slot].stack ) then self.vars.bags[bag][slot].link = link; self.vars.bags[bag][slot].stack = stack; self:UpdateItem(bag,slot); self:SortItems(); self:UpdateDisplay(); end end self:SetSafeToDelete(true); end ------------------------------------------------------------------------------------------------------ -- Core functions ------------------------------------------------------------------------------------------------------ function GarbageFu:InitBagScan() self:SetSafeToDelete(false); self.vars.items = self:Table(self.vars.items,3); for bag=0,4 do self.vars.bags[bag] = self:Table(self.vars.bags[bag],3); self.vars.bags[bag].numSlots = GetContainerNumSlots(bag); self.vars.bags[bag].bagName = GetBagName(bag); self.vars.bags[bag].ignore = self:IgnoreBag(bag); if not self.vars.bags[bag].ignore then for slot=1,self.vars.bags[bag].numSlots do self.vars.bags[bag][slot] = self:Table(self.vars.bags[bag][slot],2); self.vars.bags[bag][slot].link = GetContainerItemLink(bag, slot) _, self.vars.bags[bag][slot].stack = GetContainerItemInfo(bag, slot) self:UpdateItem(bag,slot); end end end self:SortItems(); self:UpdateDisplay(); self:SetSafeToDelete(true); end function GarbageFu:UpdateItem(bag, slot) local itemidx = nil; local item = nil; for a,i in self.vars.items do if( i.bag == bag and i.slot == slot ) then itemidx = a; item = i; break; end end if ( self.vars.bags[bag][slot].link ) then if ( not item ) then item = self:Table() end item.bag = bag; item.slot = slot; item.stack = self.vars.bags[bag][slot].stack; if ( item.link ~= self.vars.bags[bag][slot].link ) then item.link = self.vars.bags[bag][slot].link; item.id, item.code, item.name, item.color = self:GetItemId(item.link); if ( item.id ) then _, _, item.qual, _, _, _, item.maxstack, _, item.tex = GetItemInfo(item.id); if not item.qual then --- Item not in local cache item.qual = self:GetItemQualFromColor(item.color); item.tex = "Interface\\Icons\\INV_Misc_QuestionMark.blp"; item.maxstack = 0; item.notseen = true; else item.notseen = nil; end self:GetItemValue(item); else item.notseen = true; end else -- Just new stack size, recalc totvalue if ( item.value ) then item.totvalue = item.value * item.stack; end end if ( not itemidx ) then table.insert(self.vars.items, item); end elseif ( itemidx ) then compost:Reclaim(table.remove(self.vars.items, itemidx),2); end end local function ItemSortFunc(item1, item2) if item1.notseen then return false end if item2.notseen then return true end if ( item1.totvalue < item2.totvalue ) then return true end if ( item1.totvalue == item2.totvalue ) then if ( item1.id < item2.id ) then return true end end return false end function GarbageFu:SortItems() table.sort(self.vars.items, ItemSortFunc); end function GarbageFu:GetItemId(link) if link then local _, _, color, code, id, name = string.find(link, "|cff(%x%x%x%x%x%x)|Hitem:((%d+):%d+:%d+:%d+)|h%[(.+)%]|h|r") return tonumber(id), code, name, color end end function GarbageFu:GetItemQualFromColor(color) for i,c in self.vars.colors do if ( color == string.sub(c.hex,5) ) then return i end end end -- Check if an item is elegiable for drop function GarbageFu:IsItemDroppable(item) if (item.notseen) then self:UpdateItem(item.bag,item.slot) end -- Not seen item. Try again. if (item.notseen) then return false end -- Still not seen. if (item.totvalue == 0 and item.qual > 0) then return false end -- All items above poor quality without price is not dropped for saftey reasons if (self.db.profile.keepitem[item.id]) then return false end if (self.db.profile.dropitem[item.id]) then return true end if self:IsItemInKeepSets(item.id) then return false end if self:IsItemInDropSets(item.id) then return true end if (item.qual <= self:GetDropThreshold()) then return true end return false end function GarbageFu:GetFirstDroppableItem() for i,item in self.vars.items do if self:IsItemDroppable(item) then return item end end end ------------------------------------------------------------------------------------------------------ -- Drop down menu functions ------------------------------------------------------------------------------------------------------ function GarbageFu:GetDropItemTable() self.vars.temptbl = self:Table(self.vars.temptbl); -- local tbl = {}; local tbl2 = self:Table(); -- Start with itemid's listed as drop for i,_ in self.db.profile.dropitem do local item = self:Table(); item.id = i; item.name,_,item.qual = GetItemInfo(i); if item.name then table.insert(self.vars.temptbl,item); tbl2[i] = true; else compost:Reclaim(item,1); item = nil; end end -- Add items in inventory with a qual over drop threshold or in keep sets for _,i in self.vars.items do if ( not i.notseen and not tbl2[i.id] and i.totvalue > 0 and (i.qual>self:GetDropThreshold() or self:IsItemInKeepSets(i.id)) and not self:IsItemInDropSets(i.id)) then local item = self:Table(); item.id = i.id; item.name = i.name; item.qual = i.qual; table.insert(self.vars.temptbl,item); tbl2[i.id] = true; end end compost:Reclaim(tbl2,2); tbl2 = nil; table.sort(self.vars.temptbl,function(a,b) return a.name 0 and i.qual > 0 and not tbl2[i.id] and (i.qual<=self:GetDropThreshold() or self:IsItemInDropSets(i.id)) and not self:IsItemInKeepSets(i.id)) then local item = self:Table(); item.id = i.id; item.name = i.name; item.qual = i.qual; table.insert(self.vars.temptbl,item); tbl2[i.id] = true; end end compost:Reclaim(tbl2,2); tbl2 = nil; table.sort(self.vars.temptbl,function(a,b) return a.name 0 or i.totvalue == 0)) then local item = self:Table(); item.id = i.id; item.name = i.name; item.qual = i.qual; item.value = i.value; if not item.value then item.value = 0 end table.insert(self.vars.temptbl,item); tbl2[i.id] = true; end end compost:Reclaim(tbl2,2); tbl2 = nil; table.sort(self.vars.temptbl,function(a,b) return a.name 0 then return price, "|cff0077ffVW|r" end end -- PriceMaster doesn't have a price asking function, so we have to tap directly in to it's data. Ugly! function GarbageFu:GetPriceMasterVendorPrice(itemid) if ( CompletePrices and CompletePrices[itemid] and CompletePrices[itemid].p ) then return CompletePrices[itemid].p, "|cff0077ffVP|r" end end -- Ludwig_SellValue function GarbageFu:GetLudwigSellValueVendorPrice(itemid) local items = tostring(itemid) if ( Ludwig_SellValues and Ludwig_SellValues[items] ) then return Ludwig_SellValues[items], "|cff0077ffVL|r" end end function GarbageFu:GetItemSyncVendorPrice(itemlink) if (not ISync) then return end; local price = tonumber(ISync:FetchDB(ISync:GetCoreID(itemlink), "price")); if price and price > 0 then return price, "|cff0077ffVS|r" end end -- Look it up in our own price table function GarbageFu:GetLocalVendorPrice(itemid) if not self.vars.vendorprices then return end if self.vars.pricecache[itemid] then return self.vars.pricecache[itemid], "|cff0077ffVT|r" end local _, _, price = string.find(self.vars.vendorprices, " "..itemid..":(%d+)") if price then self.vars.pricecache[itemid] = tonumber(price) return self.vars.pricecache[itemid], "|cff0077ffVT|r" end end -- Check that we got a numeric value from the editbox. function GarbageFu.ValidateValue(self, value) self:DebugPrint( "ValidateValue value="..tostring(value)); local res = "" for s in string.gfind(value, "(%d*).-(%d*)") do res=res..s end return res end -- Stores a new User Override price for the top item. function GarbageFu.SetFirstItemValue(self, value) local item = self:GetFirstDroppableItem(); if item then GarbageFu.SetItemValue(self, item.id, value); end end -- Stores a new User Override price for an item, or removing it. function GarbageFu.SetItemValue(self, itemid, value) value = tonumber(value); if itemid then self:DebugPrint( "SetItemValue value="..tostring(value).."itemid="..tostring(itemid)); if ( not value or value == 0 ) then if self.db.account.overrideprices[itemid] then self.db.account.overrideprices[itemid] = nil; local name = GetItemInfo(itemid); self:MyPrint(L["Removing custom price for %s."], name); end else self.db.account.overrideprices[itemid] = value; local name = GetItemInfo(itemid); self:MyPrint(L["Setting price for %s to %s."], name, self:GetMoneyString(value)); end self:UpdateItemValue(itemid) self:SortItems(); self:UpdateDisplay(); end end -- Updates all occurances of itemid in the inventory with a new price. function GarbageFu:UpdateItemValue(itemid) for _, item in self.vars.items do if ( item.id == itemid ) then self:GetItemValue(item); end end end -- Load our own price table. function GarbageFu:LoadGarbagePrices(db) if not IsAddOnLoaded("FuBar_GarbageFu_Prices") then local res,reason = LoadAddOn("FuBar_GarbageFu_Prices"); end if GarbageFu_PriceDb then self.vars.vendorprices = GarbageFu_PriceDb; return true; elseif GarbageFu_PriceTbl then self.vars.vendorprices = ""; self.vars.pricecache = GarbageFu_PriceTbl; else self:MyPrint(L["Can't load FuBar_GarbageFu_Price. Check that it exists and are enabled"]); return; end end function GarbageFu:IsGarbagePricesAvailable() local name, title, notes, enabled, loadable, reason = GetAddOnInfo("FuBar_GarbageFu_Prices"); return not reason; end ------------------------------------------------------------------------------------------------------ -- Compost interface ------------------------------------------------------------------------------------------------------ -- Method that will get a table from compost. If a table is passed in it will be erased and return. -- If a depth is specified then any subtables will be reclaimed by compost before erasing the table and returning it. function GarbageFu:Table(t,depth) if t then if type(t) ~= "table" then error("GarbageFu:Table called with a none table as input"); return end if depth and depth > 0 then for i in pairs(t) do if type(t[i]) == "table" then compost:Reclaim(t[i], depth - 1 ); end end end return compost:Erase(t); else return compost:GetTable(); end end ------------------------------------------------------------------------------------------------------ -- Chat output functions ------------------------------------------------------------------------------------------------------ function GarbageFu:DebugPrint(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) if self.CustomDebug then self:CustomDebug(1, 0.5, 0, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); end end function GarbageFu:MyPrint(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) self:CustomPrint(self.db.profile.textcolor.r, self.db.profile.textcolor.g, self.db.profile.textcolor.b, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); end