vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 local L = AceLibrary("AceLocale-2.0"):new("FuBar_GarbageFu")
2 local Tablet = AceLibrary("Tablet-2.0");
3 local dewdrop = AceLibrary("Dewdrop-2.0");
4 local compost = AceLibrary("Compost-2.0");
5 local abacus = AceLibrary("Abacus-2.0");
6 local PeriodicTable = PeriodicTableEmbed:GetInstance("1");
7  
8 GarbageFu = AceLibrary("AceAddon-2.0"):new("FuBarPlugin-2.0", "AceEvent-2.0", "AceConsole-2.0", "AceDB-2.0", "AceDebug-2.0");
9 GarbageFu.version = "1.0." .. string.sub("$Revision: 10349 $", 12, -3);
10 GarbageFu.date = string.sub("$Date: 2006-09-06 11:24:19 -0700 (Wed, 06 Sep 2006) $", 8, 17);
11 GarbageFu.hasIcon = true;
12 GarbageFu.clickableTooltip = true;
13 GarbageFu.overrideMenu = true;
14 GarbageFu.printFrame = DEFAULT_CHAT_FRAME;
15 GarbageFu.debugFrame = DEFAULT_CHAT_FRAME;
16  
17 GarbageFu:RegisterDB("GarbageFuDB");
18 GarbageFu:RegisterDefaults("profile", {
19 moneyformat = 1,
20 namelength = 32,
21 ignoreammobag = true,
22 ignoreherbbag = false,
23 ignoresoulbag = false,
24 ignoreenchbag = false,
25 sellallbutton = true,
26 sellonlygrey = true,
27 pricetype = false,
28 garbageprices = false,
29 itemicon = false,
30 version = "",
31 textcolor = { r=0.2, g=0.8, b=1 };
32 threshold = 0,
33 dropsets = {},
34 dropitem = {},
35 keepsets = {},
36 keepitem = {},
37 });
38  
39 GarbageFu:RegisterDefaults("account", {
40 overrideprices = {};
41 });
42  
43 ------------------------------------------------------------------------------------------------------
44 -- Simple Property functions
45 ------------------------------------------------------------------------------------------------------
46  
47 function GarbageFu:IsAutodrop()
48 return self.db.profile.autodrop;
49 end
50  
51 function GarbageFu:ToggleAutodrop()
52 self.db.profile.autodrop = not self.db.profile.autodrop;
53 end
54  
55 function GarbageFu:GetDropThreshold()
56 return self.db.profile.threshold;
57 end
58  
59 function GarbageFu:IsDropThreshold(value)
60 return self.db.profile.threshold == tonumber(value);
61 end
62  
63 function GarbageFu:SetDropThreshold(value)
64 self.db.profile.threshold = tonumber(value);
65 self:UpdateDisplay();
66 end
67  
68 function GarbageFu:GetMoneyFormat(value)
69 return self.db.profile.moneyformat;
70 end
71  
72 function GarbageFu:SetMoneyFormat(value)
73 self.db.profile.moneyformat = tonumber(value);
74 self:UpdateDisplay();
75 end
76  
77 function GarbageFu:GetNameLength(value)
78 return self.db.profile.namelength;
79 end
80  
81 function GarbageFu.SetNameLength(self,value)
82 self.db.profile.namelength = value;
83 self:UpdateText();
84 end
85  
86 function GarbageFu:IsIgnoringAmmoBag()
87 return self.db.profile.ignoreammobag;
88 end
89  
90 function GarbageFu:ToggleIgnoreAmmoBag()
91 self.db.profile.ignoreammobag = not self.db.profile.ignoreammobag;
92 self:InitBagScan();
93 end
94  
95 function GarbageFu:IsIgnoringHerbBag()
96 return self.db.profile.ignoreherbbag;
97 end
98  
99 function GarbageFu:ToggleIgnoreHerbBag()
100 self.db.profile.ignoreherbbag = not self.db.profile.ignoreherbbag;
101 self:InitBagScan();
102 end
103  
104 function GarbageFu:IsIgnoringSoulBag()
105 return self.db.profile.ignoresoulbag;
106 end
107  
108 function GarbageFu:ToggleIgnoreSoulBag()
109 self.db.profile.ignoresoulbag = not self.db.profile.ignoresoulbag;
110 self:InitBagScan();
111 end
112  
113 function GarbageFu:IsIgnoringEnchBag()
114 return self.db.profile.ignoreenchbag;
115 end
116  
117 function GarbageFu:ToggleIgnoreEnchBag()
118 self.db.profile.ignoreenchbag = not self.db.profile.ignoreenchbag;
119 self:InitBagScan();
120 end
121  
122 function GarbageFu:IsSafeToDelete()
123 return self.vars.safedelete;
124 end
125  
126 function GarbageFu:SetSafeToDelete(value)
127 self.vars.safedelete = value;
128 end
129  
130 function GarbageFu:IsSellAllButton()
131 return self.db.profile.sellallbutton;
132 end
133  
134 function GarbageFu:ToggleSellAllButton()
135 self.db.profile.sellallbutton = not self.db.profile.sellallbutton;
136 if self.db.profile.sellallbutton then
137 MerchantFrame.sellAllButton:Show();
138 else
139 MerchantFrame.sellAllButton:Hide();
140 end
141 end
142  
143 function GarbageFu:IsItemIcon()
144 return self.db.profile.itemicon;
145 end
146  
147 function GarbageFu:ToggleItemIcon()
148 self.db.profile.itemicon = not self.db.profile.itemicon;
149 self:UpdateText();
150 end
151  
152 function GarbageFu:IsPriceType()
153 return self.db.profile.pricetype;
154 end
155  
156 function GarbageFu:TogglePriceType()
157 self.db.profile.pricetype = not self.db.profile.pricetype;
158 self:UpdateTooltip();
159 end
160  
161 function GarbageFu:IsSellOnlyGrey()
162 return self.db.profile.sellonlygrey;
163 end
164  
165 function GarbageFu:ToggleSellOnlyGrey()
166 self.db.profile.sellonlygrey = not self.db.profile.sellonlygrey;
167 end
168  
169 function GarbageFu:IsUsingGarbagePrices()
170 return self.db.profile.garbageprices;
171 end
172  
173 function GarbageFu:ToggleUseGarbagePrices()
174 self.db.profile.garbageprices = not self.db.profile.garbageprices;
175 if ( self.db.profile.garbageprices ) then
176 self.db.profile.garbageprices = self:LoadGarbagePrices();
177 else
178 self.vars.vendorprices = nil;
179 self.vars.pricecache = self:Table(self.vars.pricecache);
180 end
181 self:InitBagScan();
182 end
183  
184 ------------------------------------------------------------------------------------------------------
185 -- A little more complicate property functions
186 ------------------------------------------------------------------------------------------------------
187  
188 function GarbageFu:IsDropItem(itemid)
189 if (self.db.profile.dropitem[itemid]) then return true end
190 end
191  
192 function GarbageFu:ToggleDropItem(itemid)
193 if (self.db.profile.dropitem[itemid]) then
194 self.db.profile.dropitem[itemid] = nil;
195 else
196 self.db.profile.dropitem[itemid] = true;
197 self.db.profile.keepitem[itemid] = nil;
198 end
199 self:UpdateDisplay();
200 end
201  
202 function GarbageFu:IsKeepItem(itemid)
203 if (self.db.profile.keepitem[itemid]) then return true end
204 end
205  
206 function GarbageFu:ToggleKeepItem(itemid)
207 if (self.db.profile.keepitem[itemid]) then
208 self.db.profile.keepitem[itemid] = nil;
209 else
210 self.db.profile.keepitem[itemid] = true;
211 self.db.profile.dropitem[itemid] = nil;
212 end
213 self:UpdateDisplay();
214 end
215  
216 ------------------------------------------------------------------------------------------------------
217 -- Constant data
218 ------------------------------------------------------------------------------------------------------
219  
220 GarbageFu.vars = {};
221 GarbageFu.vars.moneyformats = {
222 { name=L["Condensed"], ex=abacus:FormatMoneyCondensed(123456,true,true) },
223 { name=L["Short"], ex=abacus:FormatMoneyShort(123456,true,true) },
224 { name=L["Full"], ex=abacus:FormatMoneyFull(123456,true,true) },
225 { name=L["Extended"], ex=abacus:FormatMoneyExtended(123456,true,true) },
226 }
227 GarbageFu.vars.sets = {
228 {id="foodall", name=L["Food"], order=1, sub = {
229 {id="food", name=L["Normal Food"], order=1 },
230 {id="foodbonus", name=L["Bonus Food"], order=2 },
231 {id="foodstat", name=L["Stat Food"], order=3 },
232 {id="foodbreadconjured", name=L["Conjured Bread"], order=4 },
233 {id="foodraw", name=L["Raw Food"], order=5 },
234 {id="foodclassbread", name=L["Bread"], order=6 },
235 {id="foodclassfish", name=L["Fish"], order=7 },
236 {id="foodclassmeat", name=L["Meat"], order=8 },
237 {id="foodclasscheese", name=L["Cheese"], order=9 },
238 {id="foodclassfruit", name=L["Fruit"], order=10 },
239 {id="foodclassfungus", name=L["Fungus"], order=11 },
240 }, },
241 {id="waterall", name=L["Water"], order=2, sub = {
242 {id="water", name=L["Normal Water"], order=1 },
243 {id="waterperc", name=L["Percent Water"], order=2 },
244 {id="waterconjured", name=L["Conjured Water"], order=3 },
245 }, },
246 {id="booze", name=L["Booze"], order=3 },
247 {id="tradeskills", name=L["Tradeskill"], order=4, sub = {
248 {id="tradeskillalchemy", name=L["Alchemy"], order=1 },
249 {id="tradeskillblacksmithing", name=L["Blacksmithing"], order=2 },
250 {id="tradeskillcooking", name=L["Cooking"], order=3 },
251 {id="tradeskillenchanting", name=L["Enchanting"], order=4 },
252 {id="tradeskillengineering", name=L["Engineering"], order=5 },
253 {id="tradeskillfirstaid", name=L["First Aid"], order=6 },
254 {id="tradeskillleatherworking", name=L["Leatherworking"], order=7 },
255 {id="tradeskilltailoring", name=L["Tailoring"], order=8 },
256 {id="tradeskillpoison", name=L["Poison"], order=9 },
257 {id="tradeskillsmelting", name=L["Smelting"], order=10 },
258 }, },
259 {id="tradeskilltools", name=L["Tradeskill Tools"], order=5 },
260 {id="gatherskill", name=L["Gathered"], order=6, sub = {
261 {id="gatherskillfishing", name=L["Fishing"], order=1 },
262 {id="gatherskilldisenchant", name=L["Disenchant"], order=2 },
263 {id="gatherskillherbalism", name=L["Herbalism"], order=3 },
264 {id="gatherskillmining", name=L["Mining"], order=4 },
265 {id="gatherskillskinning", name=L["Skinning"], order=5 },
266 }, },
267 {id="ammo", name=L["Ammunition"], order=7 },
268 {id="bandages", name=L["Bandages"], order=8 },
269 {id="explosives", name=L["Explosives"], order=9 },
270 {id="faire", name=L["Darkmoon Fair"], order=10 },
271 {id="fireworks", name=L["Fireworks"], order=11 },
272 {id="poisons", name=L["Poisons"], order=12 },
273 {id="potionall", name=L["Potions"], order=13, sub = {
274 {id="potionhealall", name=L["Heal Potions"], order=1 },
275 {id="potionmanaall", name=L["Mana Potions"], order=2 },
276 {id="potionrage", name=L["Rage Potions"], order=3 },
277 {id="potioncure", name=L["Cure Potions"], order=4 },
278 {id="potionbuff", name=L["Buff Potions"], order=5 },
279 }, },
280 {id="scrolls", name=L["Scrolls"], order=14 },
281 {id="reagent", name=L["Reagents"], order=15, sub = {
282 {id="reagentpaladin", name=L["Paladin"], order=1 },
283 {id="reagentdruid", name=L["Druid"], order=2 },
284 {id="reagentmage", name=L["Mage"], order=3 },
285 {id="reagentpriest", name=L["Priest"], order=4 },
286 {id="reagentrogue", name=L["Rogue"], order=5 },
287 {id="reagentshaman", name=L["Shaman"], order=6 },
288 {id="reagentwarlock", name=L["Warlock"], order=7 },
289 }, },
290 {id="weapontempenchants", name=L["Weapon Enchants"], order=16 },
291 {id="mounts", name=L["Mounts"], order=17 },
292 {id="minipetall", name=L["Mini Pets"], order=18 },
293 }
294  
295 ------------------------------------------------------------------------------------------------------
296 -- FuBar required functions
297 ------------------------------------------------------------------------------------------------------
298  
299 function GarbageFu:OnInitialize()
300 -- Put stuff that only neeeds to be done once here
301 self.vars.bags = self:Table();
302 self.vars.items = self:Table();
303 self.vars.colors = self:Table();
304 self.vars.pricecache = self:Table();
305 -- Get Item quality colors
306 for i=0,6 do
307 self.vars.colors[i] = self:Table();
308 self.vars.colors[i].r, self.vars.colors[i].g, self.vars.colors[i].b, self.vars.colors[i].hex = GetItemQualityColor(i);
309 self.vars.colors[i].desc = getglobal("ITEM_QUALITY".. i.. "_DESC");
310 end
311 -- Create Static dialog for Reset Settings
312 StaticPopupDialogs["GARBAGEFU_RESET"] = {
313 text = L["Are you sure you want to reset all your settings for GarbageFU?"],
314 button1 = TEXT(ACCEPT),
315 button2 = TEXT(CANCEL),
316 OnAccept = function() GarbageFu.SettingsReset(self) end,
317 timeout = 0,
318 whileDead = 1,
319 hideOnEscape = 1
320 };
321 -- Sort Sets tables
322 for i,s in self.vars.sets do
323 if s.sub then table.sort(s.sub,function(a,b) return a.order<b.order end) end
324 end
325 table.sort(self.vars.sets,function(a,b) return a.order<b.order end)
326 -- Create the SellAllButton
327 self:MakeSellAllButton()
328 if self:IsUsingGarbagePrices() then
329 self:LoadGarbagePrices();
330 end
331 -- Store AddOn version. In case we need to check it in the future for upgrades.
332 self.db.profile.version = self.version;
333 end
334  
335 function GarbageFu:OnEnable()
336 -- Stuff that needs to be done every time the mod is enabled
337 self:SetSafeToDelete(false);
338 if self:IsSellAllButton() then
339 MerchantFrame.sellAllButton:Show();
340 end
341 self:InitBagScan();
342 self:MakeSetsTables();
343 self:OnEnteringWorld();
344 self:SetSafeToDelete(true);
345 end
346  
347 function GarbageFu:OnDisable()
348 self:SetSafeToDelete(false);
349 MerchantFrame.sellAllButton:Hide();
350 end
351  
352 function GarbageFu:OnDataUpdate()
353 end
354  
355 function GarbageFu:OnTextUpdate()
356 self:DebugPrint("OnTextUpdate");
357 local item = self:GetFirstDroppableItem();
358 if item then
359 local text = "";
360 if ( string.len(item.name) > self:GetNameLength() ) then
361 text = self.vars.colors[item.qual].hex..string.sub(item.name, 1, self:GetNameLength()-2).."..".."|r";
362 else
363 text = self.vars.colors[item.qual].hex..item.name.."|r";
364 end
365 if ( item.maxstack > 1 ) then
366 text = text.." |cffffff00x"..tostring(item.stack).."|r";
367 end
368 text = text.." "..self:GetMoneyString(item.totvalue);
369 self:SetText(text);
370 if self:IsItemIcon() then self:SetIcon(item.tex) else self:SetIcon(true) end
371 else
372 self:SetText("GarbageFu");
373 self:SetIcon(true);
374 end
375 if self:IsThereItemsToSell() then
376 MerchantFrame.sellAllButton:Enable();
377 else
378 MerchantFrame.sellAllButton:Disable();
379 end
380 end
381  
382 function GarbageFu:OnTooltipUpdate()
383 self:DebugPrint("OnTooltipUpdate");
384 local cat;
385 if self:IsPriceType() then
386 cat = Tablet:AddCategory('columns', 3)
387 else
388 cat = Tablet:AddCategory('columns', 2)
389 end
390 for i,item in self.vars.items do
391 if self:IsItemDroppable(item) then
392 local stacktext = "|r";
393 if ( item.maxstack > 1 ) then
394 stacktext = stacktext .. "|r |cffffff00("..tostring(item.stack).."/"..tostring(item.maxstack)..")|r";
395 end
396 local moneytext = self:GetMoneyString(item.totvalue)
397 cat:AddLine(
398 'text', self.vars.colors[item.qual].hex..item.name..stacktext,
399 'text2', moneytext,
400 'text3', item.pricetype,
401 'hasCheck', true, 'checked', true, 'checkIcon', item.tex,
402 'func', 'OnClickItem', 'arg1', self, 'arg2', item
403 )
404 end
405 end
406 if MerchantFrame:IsVisible() then
407 Tablet:SetHint(L["Shift-Click to sell item\nControl-Click to add item to keep list"]);
408 else
409 Tablet:SetHint(L["Shift-Click to drop item\nControl-Click to add item to keep list"]);
410 end
411 end
412  
413 function GarbageFu:OnMenuRequest(level, value, inTooltip, value2)
414 if value then
415 if value2 then
416 self:DebugPrint("OnMenuRequest level="..level.." value="..value.." value2="..value2);
417 else
418 self:DebugPrint("OnMenuRequest level="..level.." value="..value);
419 end
420 else
421 self:DebugPrint("OnMenuRequest level="..level);
422 end
423 if ( level == 1 ) then
424 local item = self:GetFirstDroppableItem();
425 if item then
426 local text = self.vars.colors[item.qual].hex..item.name.."|r";
427 if ( item.maxstack > 1 ) then
428 text = text.." |cffffff00x"..tostring(item.stack).."|r";
429 end
430 dewdrop:AddLine('text', text..' '..self:GetMoneyString(item.totvalue),
431 'notClickable', true, 'checked', true, 'checkIcon', item.tex );
432 local text = MerchantFrame:IsVisible() and L["Sell this item"] or L["Drop this item"];
433 dewdrop:AddLine('text', text, 'arg1', self, 'func', 'DropFirstItem', 'tooltipTitle', text,
434 'tooltipText', L["Drops this item, or sells it if the vendor window is open"] );
435 if ( item.qual > 0 ) then
436 dewdrop:AddLine('text', L["Keep this item"], 'arg1', self, 'func', 'KeepFirstItem',
437 'tooltipTitle', L["Keep this item"], 'tooltipText', L["Adds this item to the keep items list"]);
438 end
439 if MerchantFrame:IsVisible() and self:IsThereItemsToSell() then
440 local sellValue = self:GetSellValue();
441 GameTooltip:AddLine(L["Value:"].." "..self:GetMoneyString(sellValue));
442 if self:IsSellOnlyGrey() then
443 dewdrop:AddLine('text', L["Sell all grey items"].." "..self:GetMoneyString(sellValue),
444 'arg1', self, 'func', 'SellAllItems',
445 'tooltipTitle', L["Sell all grey items"], 'tooltipText', L["SellsAll TooltipText2"],
446 'closeWhenClicked', true );
447 else
448 dewdrop:AddLine('text', L["Sell all garbage items"].." "..self:GetMoneyString(sellValue),
449 'arg1', self, 'func', 'SellAllItems',
450 'tooltipTitle', L["Sell all garbage items"], 'tooltipText', L["SellsAll TooltipText1"],
451 'closeWhenClicked', true );
452 end
453 end
454 if ( item.qual > 0 or item.totvalue == 0 or self.db.account.overrideprices[item.id]) then
455 dewdrop:AddLine('text', L["Edit value for this item"], 'hasArrow', true,
456 'hasEditBox', true, 'editBoxText', tostring(item.value),
457 'editBoxArg1', self, 'editBoxFunc', GarbageFu.SetFirstItemValue,
458 'editBoxChangeArg1', self, 'editBoxChangeFunc', GarbageFu.ValidateValue,
459 'tooltipTitle', L["Edit value for this item"], 'tooltipText', L["Value TooltipText"] );
460 end
461 dewdrop:AddLine();
462 end
463 dewdrop:AddLine('text', L["Drop"], 'hasArrow', true, 'value', 'drop' );
464 dewdrop:AddLine('text', L["Keep"], 'hasArrow', true, 'value', 'keep' );
465 dewdrop:AddLine('text', L["Edit item values"], 'hasArrow', true, 'value', 'itemvalue' );
466 dewdrop:AddLine();
467 dewdrop:AddLine('text', L["Options"], 'hasArrow', true, 'value', 'options' );
468 elseif ( level == 2 ) then
469 if ( value == 'drop' ) then
470 dewdrop:AddLine('text', L["Drop"], "isTitle", true );
471 dewdrop:AddLine('text', L["Drop Sets"], 'hasArrow', true, 'value', 'dropsets' );
472 dewdrop:AddLine('text', L["Drop Items"], 'hasArrow', true, 'value', 'dropitem' );
473 elseif ( value == 'keep' ) then
474 dewdrop:AddLine('text', L["Keep"], "isTitle", true );
475 dewdrop:AddLine('text', L["Keep Sets"], 'hasArrow', true, 'value', 'keepsets' );
476 dewdrop:AddLine('text', L["Keep Items"], 'hasArrow', true, 'value', 'keepitem' );
477 elseif ( value == 'itemvalue' ) then
478 -- Edit item values
479 dewdrop:AddLine('text', L["Edit item values"], "isTitle", true );
480 local tbl = self:GetCustomItemValueTable();
481 for _,i in tbl do
482 dewdrop:AddLine('text', self.vars.colors[i.qual].hex .. i.name,
483 'checked', self.db.account.overrideprices[i.id] ~= nil, 'hasArrow', true, 'hasEditBox', true,
484 'editBoxText', tostring(i.value),
485 'editBoxArg1', self, 'editBoxArg2', i.id, 'editBoxFunc', GarbageFu.SetItemValue,
486 'editBoxChangeArg1', self, 'editBoxChangeFunc', GarbageFu.ValidateValue,
487 'tooltipTitle', L["Edit value for this item"], 'tooltipText', L["Value TooltipText"]);
488 end
489 --compost:Reclaim(tbl,2);
490 --tbl = nil;
491 elseif ( value == 'options' ) then
492 dewdrop:AddLine('text', L["Drop Threshold"], 'hasArrow', true, 'value', 'threshold' );
493 dewdrop:AddLine('text', L["Money Format"], 'hasArrow', true, 'value', 'moneyformat' );
494 dewdrop:AddLine('text', L["Max Item Name Length"], 'hasArrow', true,
495 'hasSlider', true, 'sliderMin', 5, 'sliderMax', 32, 'sliderStep', 1,
496 'sliderValue', self:GetNameLength(),
497 'sliderFunc', GarbageFu.SetNameLength, 'sliderArg1', self );
498 dewdrop:AddLine('text', L["Sell All Button on Merchant Window"], 'checked', self:IsSellAllButton(),
499 'arg1', self, 'func', 'ToggleSellAllButton',
500 'tooltipTitle', L["Sell All Button on Merchant Window"], 'tooltipText', L["SellAllButton TooltipText"]);
501 dewdrop:AddLine('text', L["Only Autosell Grey Items"], 'checked', self:IsSellOnlyGrey(),
502 'arg1', self, 'func', 'ToggleSellOnlyGrey',
503 'tooltipTitle', L["Only Autosell Grey Items"], 'tooltipText', L["OnlyGrey TooltipText"]);
504 dewdrop:AddLine('text', L["Use Items Icon on Toolbar"], 'checked', self:IsItemIcon(),
505 'arg1', self, 'func', 'ToggleItemIcon');
506 dewdrop:AddLine('text', L["Show Price Type in Tooltip"], 'checked', self:IsPriceType(),
507 'arg1', self, 'func', 'TogglePriceType');
508 dewdrop:AddLine('text', L["Use GarbageFu Prices"], 'checked', self:IsUsingGarbagePrices(),
509 'arg1', self, 'func', 'ToggleUseGarbagePrices',
510 'disabled', not self:IsGarbagePricesAvailable(),
511 'tooltipTitle', L["Use GarbageFu Prices"], 'tooltipText', L["GarbageFu_Prices ToltipText"]);
512 dewdrop:AddLine('text', L["Ignore Ammo Bags"], 'checked', self:IsIgnoringAmmoBag(),
513 'arg1', self, 'func', 'ToggleIgnoreAmmoBag');
514 dewdrop:AddLine('text', L["Ignore Herb Bags"], 'checked', self:IsIgnoringHerbBag(),
515 'arg1', self, 'func', 'ToggleIgnoreHerbBag');
516 dewdrop:AddLine('text', L["Ignore Soulshard Bags"], 'checked', self:IsIgnoringSoulBag(),
517 'arg1', self, 'func', 'ToggleIgnoreSoulBag');
518 dewdrop:AddLine('text', L["Ignore Enchanting Bags"], 'checked', self:IsIgnoringEnchBag(),
519 'arg1', self, 'func', 'ToggleIgnoreEnchBag');
520 --dewdrop:AddLine('text', L["Rescan"], 'arg1', self, 'func', 'InitBagScan' );
521 dewdrop:AddLine('text', L["Reset"], 'arg1', "GARBAGEFU_RESET", 'func', StaticPopup_Show, 'closeWhenClicked', true );
522 dewdrop:AddLine();
523 self:AddImpliedMenuOptions(2);
524 end
525 elseif ( level == 3 ) then
526 if (value2 == 'drop') then
527 if ( value == 'dropsets' ) then
528 -- Drop - Sets
529 dewdrop:AddLine('text', L["Drop Sets"], "isTitle", true );
530 for n,i in self.vars.sets do
531 local checked = self:IsDropSet(n);
532 local checkIcon = "Interface\\Buttons\\UI-CheckBox-Check"
533 if self:IsChildDropSet(n) then
534 checked = true;
535 checkIcon = "Interface\\Buttons\\UI-CheckBox-Check-Disabled"
536 end
537 dewdrop:AddLine('text', i.name,
538 'checked', checked, 'checkIcon', checkIcon,
539 'disabled', self:IsKeepSet(n),
540 'hasArrow', i.sub ~= nil, 'value', n,
541 'arg1', self, 'arg2', n, 'func', 'ToggleDropSets' );
542 end
543 elseif ( value == 'dropitem' ) then
544 -- Drop - Items
545 dewdrop:AddLine('text', L["Drop Items"], "isTitle", true );
546 local tbl = self:GetDropItemTable();
547 for _,i in tbl do
548 dewdrop:AddLine('text', self.vars.colors[i.qual].hex .. i.name,
549 'checked', self:IsDropItem(i.id),
550 'arg1', self, 'arg2', i.id, 'func', 'ToggleDropItem');
551 end
552 --compost:Reclaim(tbl,2);
553 --tbl = nil;
554 end
555 elseif (value2 == 'keep') then
556 if ( value == 'keepsets' ) then
557 -- Keep - Sets
558 dewdrop:AddLine('text', L["Keep Sets"], "isTitle", true );
559 for n,i in self.vars.sets do
560 local checked = self:IsKeepSet(n);
561 local checkIcon = "Interface\\Buttons\\UI-CheckBox-Check"
562 if self:IsChildKeepSet(n) then
563 checked = true;
564 checkIcon = "Interface\\Buttons\\UI-CheckBox-Check-Disabled"
565 end
566 dewdrop:AddLine('text', i.name,
567 'checked', checked, 'checkIcon', checkIcon,
568 'disabled', self:IsDropSet(n),
569 'hasArrow', i.sub ~= nil, 'value', n,
570 'arg1', self, 'arg2', n, 'func', 'ToggleKeepSets' );
571 end
572 elseif ( value == 'keepitem' ) then
573 -- Keep - Items
574 dewdrop:AddLine('text', L["Keep Items"], "isTitle", true );
575 local tbl = self:GetKeepItemTable();
576 for _,i in tbl do
577 dewdrop:AddLine('text', self.vars.colors[i.qual].hex .. i.name,
578 'checked', self:IsKeepItem(i.id),
579 'arg1', self, 'arg2', i.id, 'func', 'ToggleKeepItem');
580 end
581 --compost:Reclaim(tbl,2);
582 --tbl = nil;
583 end
584 elseif ( value2 == 'options' ) then
585 if ( value == 'threshold' ) then
586 dewdrop:AddLine('text', L["Drop Threshold"], "isTitle", true );
587 for a=0,6 do
588 dewdrop:AddLine('text', self.vars.colors[a].hex..self.vars.colors[a].desc.."|r",
589 'checked', a == self:GetDropThreshold(),
590 'arg1', self, 'arg2', a, 'isRadio', true,
591 'func', 'SetDropThreshold' );
592 end
593 elseif ( value == 'moneyformat' ) then
594 dewdrop:AddLine('text', L["Money Format"], "isTitle", true );
595 for a,f in self.vars.moneyformats do
596 dewdrop:AddLine('text', f.name.."\t"..f.ex,
597 'checked', a == self:GetMoneyFormat(),
598 'arg1', self, 'arg2', a, 'isRadio', true,
599 'func', 'SetMoneyFormat' );
600 end
601 else
602 self:AddImpliedMenuOptions(2);
603 end
604 end
605 elseif ( level == 4 ) then
606 if ( value2 == 'dropsets' ) then
607 dewdrop:AddLine('text', L["Drop Set"].." "..self.vars.sets[value].name, "isTitle", true );
608 for n,i in self.vars.sets[value].sub do
609 dewdrop:AddLine('text', i.name,
610 'checked', self:IsDropSet(value,n),
611 'disabled',self:IsKeepSet(value,n),
612 'arg1', self, 'arg2', value, 'arg3', n, 'func', 'ToggleDropSets' );
613 end
614 elseif ( value2 == 'keepsets' ) then
615 dewdrop:AddLine('text', L["Keep Set"].." "..self.vars.sets[value].name, "isTitle", true );
616 for n,i in self.vars.sets[value].sub do
617 dewdrop:AddLine('text', i.name,
618 'checked', self:IsKeepSet(value,n),
619 'disabled', self:IsDropSet(value,n),
620 'arg1', self, 'arg2', value, 'arg3', n, 'func', 'ToggleKeepSets' );
621 end
622 end
623 end
624 end
625  
626 function GarbageFu:OnClick(button)
627 if IsShiftKeyDown() then
628 self:DropFirstItem();
629 end
630 if IsControlKeyDown() then
631 self:KeepFirstItem();
632 end
633 end
634  
635 ------------------------------------------------------------------------------------------------------
636 -- Event functions
637 ------------------------------------------------------------------------------------------------------
638  
639 function GarbageFu:OnClickItem(item)
640 if IsShiftKeyDown() then
641 self:DropItem(item);
642 end
643 if IsControlKeyDown() then
644 self:KeepItem(item);
645 end
646 end
647  
648 function GarbageFu:OnEnteringWorld()
649 self:RegisterEvent("BAG_UPDATE","OnBagUpdate");
650 self:RegisterEvent("MERCHANT_SHOW","OnMerchantOpen");
651 self:RegisterEvent("MERCHANT_CLOSED","OnMerchantClose");
652 self:RegisterEvent("PLAYER_LEAVING_WORLD","OnLeavingWorld");
653 if self:IsEventRegistered("PLAYER_ENTERING_WORLD") then self:UnregisterEvent("PLAYER_ENTERING_WORLD") end
654 end
655  
656 function GarbageFu:OnLeavingWorld()
657 self:RegisterEvent("PLAYER_ENTERING_WORLD","OnEnteringWorld");
658 if self:IsEventRegistered("BAG_UPDATE") then self:UnregisterEvent("BAG_UPDATE") end
659 if self:IsEventRegistered("MERCHANT_SHOW") then self:UnregisterEvent("MERCHANT_SHOW") end
660 if self:IsEventRegistered("MERCHANT_CLOSED") then self:UnregisterEvent("MERCHANT_CLOSED") end
661 if self:IsEventRegistered("PLAYER_LEAVING_WORLD") then self:UnregisterEvent("PLAYER_LEAVING_WORLD") end
662 end
663  
664 function GarbageFu:OnBagUpdate(bag)
665 -- local bag = arg1;
666 self:DebugPrint("OnBagUpdate bag="..tostring(bag));
667 if ( not bag or bag < 0 or bag > 4 ) then return end
668 if ( self.vars.bags[bag].bagName ~= GetBagName(bag) ) then -- Houston, we got a problem
669 self:DebugPrint("New or changed bag detected. Doing a full scan");
670 self:InitBagScan(); -- New or changed bag detected. Do a full scan
671 return
672 end
673 if self.vars.bags[bag].ignore then return end
674 self:SetSafeToDelete(false);
675 for slot=1,self.vars.bags[bag].numSlots do
676 if not self.vars.bags[bag][slot] then self.vars.bags[bag][slot] = self:Table() end
677 local link = GetContainerItemLink(bag, slot);
678 local _, stack = GetContainerItemInfo(bag, slot);
679 if ( link ~= self.vars.bags[bag][slot].link or stack ~= self.vars.bags[bag][slot].stack ) then
680 self.vars.bags[bag][slot].link = link;
681 self.vars.bags[bag][slot].stack = stack;
682 self:UpdateItem(bag,slot);
683 self:SortItems();
684 self:UpdateDisplay();
685 end
686 end
687 self:SetSafeToDelete(true);
688 end
689  
690 ------------------------------------------------------------------------------------------------------
691 -- Core functions
692 ------------------------------------------------------------------------------------------------------
693  
694 function GarbageFu:InitBagScan()
695 self:SetSafeToDelete(false);
696 self.vars.items = self:Table(self.vars.items,3);
697 for bag=0,4 do
698 self.vars.bags[bag] = self:Table(self.vars.bags[bag],3);
699 self.vars.bags[bag].numSlots = GetContainerNumSlots(bag);
700 self.vars.bags[bag].bagName = GetBagName(bag);
701 self.vars.bags[bag].ignore = self:IgnoreBag(bag);
702 if not self.vars.bags[bag].ignore then
703 for slot=1,self.vars.bags[bag].numSlots do
704 self.vars.bags[bag][slot] = self:Table(self.vars.bags[bag][slot],2);
705 self.vars.bags[bag][slot].link = GetContainerItemLink(bag, slot)
706 _, self.vars.bags[bag][slot].stack = GetContainerItemInfo(bag, slot)
707 self:UpdateItem(bag,slot);
708 end
709 end
710 end
711 self:SortItems();
712 self:UpdateDisplay();
713 self:SetSafeToDelete(true);
714 end
715  
716 function GarbageFu:UpdateItem(bag, slot)
717 local itemidx = nil;
718 local item = nil;
719 for a,i in self.vars.items do
720 if( i.bag == bag and i.slot == slot ) then
721 itemidx = a;
722 item = i;
723 break;
724 end
725 end
726 if ( self.vars.bags[bag][slot].link ) then
727 if ( not item ) then item = self:Table() end
728 item.bag = bag;
729 item.slot = slot;
730 item.stack = self.vars.bags[bag][slot].stack;
731 if ( item.link ~= self.vars.bags[bag][slot].link ) then
732 item.link = self.vars.bags[bag][slot].link;
733 item.id, item.code, item.name, item.color = self:GetItemId(item.link);
734 if ( item.id ) then
735 _, _, item.qual, _, _, _, item.maxstack, _, item.tex = GetItemInfo(item.id);
736 if not item.qual then --- Item not in local cache
737 item.qual = self:GetItemQualFromColor(item.color);
738 item.tex = "Interface\\Icons\\INV_Misc_QuestionMark.blp";
739 item.maxstack = 0;
740 item.notseen = true;
741 else
742 item.notseen = nil;
743 end
744 self:GetItemValue(item);
745 else
746 item.notseen = true;
747 end
748 else -- Just new stack size, recalc totvalue
749 if ( item.value ) then
750 item.totvalue = item.value * item.stack;
751 end
752 end
753 if ( not itemidx ) then
754 table.insert(self.vars.items, item);
755 end
756 elseif ( itemidx ) then
757 compost:Reclaim(table.remove(self.vars.items, itemidx),2);
758 end
759 end
760  
761 local function ItemSortFunc(item1, item2)
762 if item1.notseen then return false end
763 if item2.notseen then return true end
764 if ( item1.totvalue < item2.totvalue ) then return true end
765 if ( item1.totvalue == item2.totvalue ) then
766 if ( item1.id < item2.id ) then return true end
767 end
768 return false
769 end
770  
771 function GarbageFu:SortItems()
772 table.sort(self.vars.items, ItemSortFunc);
773 end
774  
775 function GarbageFu:GetItemId(link)
776 if link then
777 local _, _, color, code, id, name = string.find(link, "|cff(%x%x%x%x%x%x)|Hitem:((%d+):%d+:%d+:%d+)|h%[(.+)%]|h|r")
778 return tonumber(id), code, name, color
779 end
780 end
781  
782 function GarbageFu:GetItemQualFromColor(color)
783 for i,c in self.vars.colors do
784 if ( color == string.sub(c.hex,5) ) then return i end
785 end
786 end
787  
788  
789 -- Check if an item is elegiable for drop
790 function GarbageFu:IsItemDroppable(item)
791 if (item.notseen) then self:UpdateItem(item.bag,item.slot) end -- Not seen item. Try again.
792 if (item.notseen) then return false end -- Still not seen.
793 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
794 if (self.db.profile.keepitem[item.id]) then return false end
795 if (self.db.profile.dropitem[item.id]) then return true end
796 if self:IsItemInKeepSets(item.id) then return false end
797 if self:IsItemInDropSets(item.id) then return true end
798 if (item.qual <= self:GetDropThreshold()) then return true end
799 return false
800 end
801  
802 function GarbageFu:GetFirstDroppableItem()
803 for i,item in self.vars.items do
804 if self:IsItemDroppable(item) then
805 return item
806 end
807 end
808 end
809  
810 ------------------------------------------------------------------------------------------------------
811 -- Drop down menu functions
812 ------------------------------------------------------------------------------------------------------
813  
814 function GarbageFu:GetDropItemTable()
815 self.vars.temptbl = self:Table(self.vars.temptbl);
816 -- local tbl = {};
817 local tbl2 = self:Table();
818 -- Start with itemid's listed as drop
819 for i,_ in self.db.profile.dropitem do
820 local item = self:Table();
821 item.id = i;
822 item.name,_,item.qual = GetItemInfo(i);
823 if item.name then
824 table.insert(self.vars.temptbl,item);
825 tbl2[i] = true;
826 else
827 compost:Reclaim(item,1);
828 item = nil;
829 end
830 end
831 -- Add items in inventory with a qual over drop threshold or in keep sets
832 for _,i in self.vars.items do
833 if ( not i.notseen and not tbl2[i.id] and i.totvalue > 0 and
834 (i.qual>self:GetDropThreshold() or self:IsItemInKeepSets(i.id)) and
835 not self:IsItemInDropSets(i.id)) then
836 local item = self:Table();
837 item.id = i.id;
838 item.name = i.name;
839 item.qual = i.qual;
840 table.insert(self.vars.temptbl,item);
841 tbl2[i.id] = true;
842 end
843 end
844 compost:Reclaim(tbl2,2);
845 tbl2 = nil;
846 table.sort(self.vars.temptbl,function(a,b) return a.name<b.name end);
847 return self.vars.temptbl
848 end
849  
850 function GarbageFu:GetKeepItemTable()
851 self.vars.temptbl = self:Table(self.vars.temptbl);
852 local tbl2 = self:Table();
853 -- Start with itemid's listed as keep
854 for i,_ in self.db.profile.keepitem do
855 local item = self:Table();
856 item.id = i;
857 item.name,_,item.qual = GetItemInfo(i);
858 if item.name then
859 table.insert(self.vars.temptbl,item);
860 tbl2[i] = true;
861 else
862 compost:Reclaim(item,1);
863 item = nil;
864 end
865 end
866 -- Add items in inventory with a qual eq or below drop threshold or in drop sets. Not poor quality items
867 for _,i in self.vars.items do
868 if ( not i.notseen and i.totvalue > 0 and i.qual > 0 and not tbl2[i.id] and
869 (i.qual<=self:GetDropThreshold() or self:IsItemInDropSets(i.id)) and
870 not self:IsItemInKeepSets(i.id)) then
871 local item = self:Table();
872 item.id = i.id;
873 item.name = i.name;
874 item.qual = i.qual;
875 table.insert(self.vars.temptbl,item);
876 tbl2[i.id] = true;
877 end
878 end
879 compost:Reclaim(tbl2,2);
880 tbl2 = nil;
881 table.sort(self.vars.temptbl,function(a,b) return a.name<b.name end);
882 return self.vars.temptbl
883 end
884  
885 function GarbageFu:GetCustomItemValueTable()
886 self.vars.temptbl = self:Table(self.vars.temptbl);
887 local tbl2 = self:Table();
888 -- Start with itemid's with a custom price
889 for i,v in self.db.account.overrideprices do
890 local item = self:Table();
891 item.id = i;
892 item.value = v;
893 item.name,_,item.qual = GetItemInfo(i);
894 if item.name then
895 table.insert(self.vars.temptbl,item);
896 tbl2[i] = true;
897 else
898 compost:Reclaim(item,1);
899 item = nil;
900 end
901 end
902 -- Add items in inventory. Not poor quality items that already have a price
903 for _,i in self.vars.items do
904 if ( not i.notseen and not tbl2[i.id] and (i.qual > 0 or i.totvalue == 0)) then
905 local item = self:Table();
906 item.id = i.id;
907 item.name = i.name;
908 item.qual = i.qual;
909 item.value = i.value;
910 if not item.value then item.value = 0 end
911 table.insert(self.vars.temptbl,item);
912 tbl2[i.id] = true;
913 end
914 end
915 compost:Reclaim(tbl2,2);
916 tbl2 = nil;
917 table.sort(self.vars.temptbl,function(a,b) return a.name<b.name end);
918 return self.vars.temptbl
919 end
920  
921 function GarbageFu:KeepFirstItem()
922 local item = self:GetFirstDroppableItem();
923 if item then
924 self:KeepItem(item);
925 end
926 end
927  
928 function GarbageFu:KeepItem(item)
929 if item then
930 self:ToggleKeepItem(item.id);
931 self:MyPrint(L["Adding %s to keep item list"], item.link );
932 end
933 end
934  
935 function GarbageFu:DropFirstItem()
936 local item = self:GetFirstDroppableItem();
937 if item then
938 self:DropItem(item);
939 end
940 end
941  
942 function GarbageFu:DropItem(item)
943 if not item or not item.bag or not item.slot then return end
944 if not self:IsSafeToDelete() then return end
945 if self:IsItemDroppable(item) then
946 if (MerchantFrame:IsVisible()) then
947 self:MyPrint(L["Selling x%s %s worth %s"], item.stack, item.name, self:GetMoneyString(item.totvalue) );
948 UseContainerItem(item.bag, item.slot)
949 self:SetSafeToDelete(false);
950 else
951 self:MyPrint(L["Dropping x%s %s worth %s"], item.stack, item.name, self:GetMoneyString(item.totvalue) );
952 PickupContainerItem(item.bag, item.slot)
953 DeleteCursorItem();
954 self:SetSafeToDelete(false);
955 end
956 end
957 end
958  
959 function GarbageFu:SettingsReset()
960 self:ResetDB('profile');
961 self:ResetDB('account');
962 self.vars.dropsets = self:Table(self.vars.dropsets,1);
963 self.vars.keepsets = self:Table(self.vars.keepsets,1);
964 self:UpdateDisplay();
965 end
966  
967 function GarbageFu:GetMoneyString(value)
968 if ( value == 0 ) then
969 return "|cffffcc00??|r"; -- No price
970 elseif ( self.db.profile.moneyformat == 1 ) then
971 return abacus:FormatMoneyCondensed(value,true,true)
972 elseif ( self.db.profile.moneyformat == 2 ) then
973 return abacus:FormatMoneyShort(value,true,true)
974 elseif ( self.db.profile.moneyformat == 3 ) then
975 return abacus:FormatMoneyFull(value,true,true)
976 else
977 return abacus:FormatMoneyExtended(value,true,true)
978 end
979 end
980  
981 ------------------------------------------------------------------------------------------------------
982 -- Sets functions
983 ------------------------------------------------------------------------------------------------------
984  
985 function GarbageFu:IsItemInSet(itemId,set)
986 local val,set = PeriodicTable:ItemInSet(itemId,set);
987 if set then return true end
988 end
989  
990 -- Check if item is in one of the sets selected for drop.
991 function GarbageFu:IsItemInDropSets(itemid)
992 local val,set = PeriodicTable:ItemInSet(itemid,self.vars.dropsets);
993 if set then return true end
994 end
995  
996 -- Check if item is in one of the sets selected for keep.
997 function GarbageFu:IsItemInKeepSets(itemid)
998 local val,set = PeriodicTable:ItemInSet(itemid,self.vars.keepsets);
999 if set then return true end
1000 end
1001  
1002 function GarbageFu:IsDropSet(set,subset)
1003 local setid = self.vars.sets[set].id;
1004 if subset then
1005 local subsetid = self.vars.sets[set].sub[subset].id;
1006 return self.db.profile.dropsets[setid] or self.db.profile.dropsets[subsetid];
1007 end
1008 return self.db.profile.dropsets[setid];
1009 end
1010  
1011 function GarbageFu:IsChildDropSet(set)
1012 if self.vars.sets[set].sub then
1013 for _,s in self.vars.sets[set].sub do
1014 if self.db.profile.dropsets[s.id] then
1015 return true;
1016 end
1017 end
1018 end
1019 end
1020  
1021 -- Converts self.db.profile.dropsets into self.vars.dropsets
1022 -- Needed because self.db.profile.dropsets is index by name and self.vars.dropsets needs to be indexed by number with names as string.
1023 function GarbageFu:MakeSetsTables()
1024 self.vars.dropsets = self:Table(self.vars.dropsets,1);
1025 for n,_ in self.db.profile.dropsets do
1026 table.insert(self.vars.dropsets,n);
1027 end
1028 self.vars.keepsets = self:Table(self.vars.keepsets,1);
1029 for n,_ in self.db.profile.keepsets do
1030 table.insert(self.vars.keepsets,n);
1031 end
1032 end
1033  
1034 function GarbageFu:ToggleDropSets(set,subset)
1035 self:DebugPrint("ToggleDropSets(set) set="..tostring(set).." subset="..tostring(subset));
1036 local setid = self.vars.sets[set].id;
1037 if subset then -- Clicked a child
1038 local subsetid = self.vars.sets[set].sub[subset].id;
1039 if self.db.profile.dropsets[setid] then -- Check if parent is set
1040 self.db.profile.dropsets[setid] = nil; -- Clear parent
1041 for _,s in self.vars.sets[set].sub do
1042 self.db.profile.dropsets[s.id] = true; -- Set all children
1043 end
1044 end
1045 if self.db.profile.dropsets[subsetid] then -- Reverse child
1046 self.db.profile.dropsets[subsetid] = nil;
1047 else
1048 self.db.profile.dropsets[subsetid] = true;
1049 end
1050 local allset = true;
1051 for _,s in self.vars.sets[set].sub do
1052 if not self.db.profile.dropsets[s.id] then -- Check if all children are set
1053 allset = false;
1054 break;
1055 end
1056 end
1057 if allset then -- All children are set
1058 self.db.profile.dropsets[setid] = true; -- set parent
1059 for i,s in self.vars.sets[set].sub do
1060 self.db.profile.dropsets[s.id] = nil; -- And clear all children
1061 end
1062 end
1063 else -- Clicked a parent or a single
1064 if self.db.profile.dropsets[setid] then -- Reverse it
1065 self.db.profile.dropsets[setid] = nil;
1066 else
1067 self.db.profile.dropsets[setid] = true;
1068 if self.vars.sets[set].sub then -- If it is a parent
1069 for _,s in self.vars.sets[set].sub do -- Clear all children for both drop and keep
1070 self.db.profile.dropsets[s.id] = nil;
1071 self.db.profile.keepsets[s.id] = nil;
1072 end
1073 end
1074 end
1075 end
1076 self:MakeSetsTables();
1077 self:UpdateDisplay();
1078 end
1079  
1080 function GarbageFu:IsKeepSet(set,subset)
1081 local setid = self.vars.sets[set].id;
1082 if subset then
1083 local subsetid = self.vars.sets[set].sub[subset].id;
1084 return self.db.profile.keepsets[setid] or self.db.profile.keepsets[subsetid];
1085 end
1086 return self.db.profile.keepsets[setid];
1087 end
1088  
1089 function GarbageFu:IsChildKeepSet(set)
1090 if self.vars.sets[set].sub then
1091 for _,s in self.vars.sets[set].sub do
1092 if self.db.profile.keepsets[s.id] then
1093 return true;
1094 end
1095 end
1096 end
1097 end
1098  
1099 function GarbageFu:ToggleKeepSets(set,subset)
1100 self:DebugPrint("ToggleKeepSets(set) set="..tostring(set).." subset="..tostring(subset));
1101 local setid = self.vars.sets[set].id;
1102 if subset then -- Clicked a child
1103 local subsetid = self.vars.sets[set].sub[subset].id;
1104 if self.db.profile.keepsets[setid] then -- Check if parent is set
1105 self.db.profile.keepsets[setid] = nil; -- Clear parent
1106 for _,s in self.vars.sets[set].sub do
1107 self.db.profile.keepsets[s.id] = true; -- Set all children
1108 end
1109 end
1110 if self.db.profile.keepsets[subsetid] then -- Reverse child
1111 self.db.profile.keepsets[subsetid] = nil;
1112 else
1113 self.db.profile.keepsets[subsetid] = true;
1114 end
1115 local allset = true;
1116 for _,s in self.vars.sets[set].sub do
1117 if not self.db.profile.keepsets[s.id] then -- Check if all children are set
1118 allset = false;
1119 break;
1120 end
1121 end
1122 if allset then -- All children are set
1123 self.db.profile.keepsets[setid] = true; -- set parent
1124 for i,s in self.vars.sets[set].sub do
1125 self.db.profile.keepsets[s.id] = nil; -- And clear all children
1126 end
1127 end
1128 else -- Clicked a parent or a single
1129 if self.db.profile.keepsets[setid] then -- Reverse it
1130 self.db.profile.keepsets[setid] = nil;
1131 else
1132 self.db.profile.keepsets[setid] = true;
1133 if self.vars.sets[set].sub then -- If it is a parent
1134 for _,s in self.vars.sets[set].sub do -- Clear all children for both drop and keep
1135 self.db.profile.keepsets[s.id] = nil;
1136 self.db.profile.dropsets[s.id] = nil;
1137 end
1138 end
1139 end
1140 end
1141 self:MakeSetsTables();
1142 self:UpdateDisplay();
1143 end
1144  
1145 ------------------------------------------------------------------------------------------------------
1146 -- Special bag functions
1147 ------------------------------------------------------------------------------------------------------
1148  
1149 function GarbageFu:GetBagId(bag)
1150 local slotId = ContainerIDToInventoryID(bag);
1151 local bagLink = GetInventoryItemLink("player",slotId);
1152 local bagId = self:GetItemId(bagLink);
1153 return bagId;
1154 end
1155  
1156 function GarbageFu:IsBagAmmoBag(bagId)
1157 return self:IsItemInSet(bagId, {"bagsammo","bagsquiver"});
1158 end
1159  
1160 function GarbageFu:IsBagHerbBag(bagId)
1161 return self:IsItemInSet(bagId, "bagsherb");
1162 end
1163  
1164 function GarbageFu:IsBagSoulBag(bagId)
1165 return self:IsItemInSet(bagId, "bagssoul");
1166 end
1167  
1168 function GarbageFu:IsBagEnchBag(bagId)
1169 return self:IsItemInSet(bagId, "bagsench");
1170 end
1171  
1172 function GarbageFu:IgnoreBag(bag)
1173 local bagId = self:GetBagId(bag);
1174 if ( self:IsIgnoringAmmoBag() and self:IsBagAmmoBag(bagId) ) then return true end
1175 if ( self:IsIgnoringHerbBag() and self:IsBagHerbBag(bagId) ) then return true end
1176 if ( self:IsIgnoringSoulBag() and self:IsBagSoulBag(bagId) ) then return true end
1177 if ( self:IsIgnoringEnchBag() and self:IsBagEnchBag(bagId) ) then return true end
1178 end
1179  
1180 ------------------------------------------------------------------------------------------------------
1181 -- Sell Items functions
1182 ------------------------------------------------------------------------------------------------------
1183  
1184 function GarbageFu:IsItemSellable(item)
1185 if ( item.qual == 0 or ( not self:IsSellOnlyGrey() and self:IsItemDroppable(item))) then
1186 return true;
1187 end
1188 return false;
1189 end
1190  
1191 function GarbageFu:IsThereItemsToSell()
1192 for _,item in pairs(self.vars.items) do
1193 if self:IsItemSellable(item) then
1194 return true;
1195 end
1196 end
1197 return false;
1198 end
1199  
1200 function GarbageFu:GetSellItems()
1201 local sellItems = self:Table();
1202 local sellValue = 0;
1203 for _,item in pairs(self.vars.items) do
1204 if self:IsItemSellable(item) then
1205 table.insert(sellItems,item);
1206 sellValue = sellValue + item.totvalue;
1207 end
1208 end
1209 return sellItems, sellValue;
1210 end
1211  
1212 function GarbageFu:GetSellValue()
1213 local sellValue = 0;
1214 for _,item in pairs(self.vars.items) do
1215 if self:IsItemSellable(item) then
1216 sellValue = sellValue + item.totvalue;
1217 end
1218 end
1219 return sellValue;
1220 end
1221  
1222 function GarbageFu:SellAllItems()
1223 if ( not self:IsEventScheduled("SellItem") ) then
1224 if self.vars.sellitems then compost:Reclaim(self.vars.sellitems) end
1225 self.vars.sellitems, self.vars.sellvalue = self:GetSellItems();
1226 if self.vars.sellitems[1] then
1227 self:ScheduleRepeatingEvent("SellItem", self.SellItemEvent, 0.5, self);
1228 end
1229 end
1230 end
1231  
1232 function GarbageFu:SellItemEvent()
1233 local item = self.vars.sellitems[1];
1234 if ( item and MerchantFrame:IsVisible() ) then
1235 if self:IsSafeToDelete() then
1236 self:SetSafeToDelete(false);
1237 self:MyPrint(L["Selling x%s %s worth %s"], item.stack, item.name, self:GetMoneyString(item.totvalue) );
1238 UseContainerItem(item.bag, item.slot)
1239 table.remove(self.vars.sellitems,1);
1240 end
1241 else -- No more items or Merchant frame closed
1242 if ( not item ) then
1243 self:MyPrint(L["All items sold."]);
1244 MerchantFrame.sellAllButton:Disable();
1245 end
1246 self:CancelScheduledEvent("SellItem");
1247 return
1248 end
1249 end
1250  
1251 function GarbageFu:OnMerchantOpen()
1252 if self:IsThereItemsToSell() then
1253 MerchantFrame.sellAllButton:Enable();
1254 else
1255 MerchantFrame.sellAllButton:Disable();
1256 end
1257 end
1258  
1259 function GarbageFu:OnMerchantClose()
1260 if ( self:IsEventScheduled("SellItem") ) then
1261 self:CancelScheduledEvent("SellItem");
1262 end
1263 end
1264  
1265 local buttonSize = 32
1266 function GarbageFu:MakeSellAllButton()
1267 if not MerchantFrame.sellAllButton then
1268 local sellAllButton = CreateFrame("Button", "GarbageFu_SellItemButton", MerchantFrame)
1269 MerchantFrame.sellAllButton = sellAllButton
1270 sellAllButton:SetWidth(buttonSize)
1271 sellAllButton:SetHeight(buttonSize)
1272 local texture = sellAllButton:CreateTexture()
1273 texture:SetWidth(buttonSize * 1.6458333)
1274 texture:SetHeight(buttonSize * 1.6458333)
1275 texture:SetPoint("CENTER", sellAllButton, "CENTER")
1276 texture:SetTexture("Interface\\Buttons\\UI-Quickslot2")
1277 sellAllButton:SetNormalTexture(texture)
1278 local texture = sellAllButton:CreateTexture(nil, "BACKGROUND")
1279 texture:SetTexture("Interface\\AddOns\\FuBar_GarbageFu\\icon.tga")
1280 texture:SetAllPoints(sellAllButton)
1281 sellAllButton:SetPushedTexture("Interface\\Buttons\\UI-Quickslot-Depress")
1282 local texture = sellAllButton:CreateTexture()
1283 texture:SetTexture("Interface\\Buttons\\ButtonHilight-Square")
1284 texture:SetAllPoints(sellAllButton)
1285 sellAllButton:SetHighlightTexture(texture)
1286 local texture = sellAllButton:CreateTexture()
1287 texture:SetTexture("Interface\\AddOns\\FuBar_GarbageFu\\icon.tga")
1288 texture:SetDesaturated(true)
1289 texture:SetAllPoints(sellAllButton)
1290 sellAllButton:SetDisabledTexture(texture)
1291 sellAllButton:SetPoint("TOPRIGHT", MerchantFrame, "TOPRIGHT", -44, -38)
1292 sellAllButton:SetScript("OnClick", function()
1293 self:SellAllItems()
1294 end)
1295 sellAllButton:SetScript("OnEnter", function()
1296 self:SellAllButtonOnEnter(this)
1297 end)
1298 sellAllButton:SetScript("OnLeave", function()
1299 GameTooltip:Hide()
1300 end)
1301 local texture = sellAllButton:CreateTexture(nil, "ARTWORK")
1302 texture:SetTexture(0, 0, 0, 0.5)
1303 texture:SetAllPoints(sellAllButton)
1304 local button_Enable = sellAllButton.Enable
1305 function sellAllButton:Enable()
1306 button_Enable(self)
1307 texture:Hide()
1308 end
1309 local button_Disable = sellAllButton.Disable
1310 function sellAllButton:Disable()
1311 button_Disable(self)
1312 texture:Show()
1313 end
1314 MerchantFrame.sellAllButton:Disable()
1315 end
1316 end
1317  
1318 function GarbageFu:SellAllButtonOnEnter(button)
1319 GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
1320 if self:IsSellOnlyGrey() then
1321 GameTooltip:SetText(L["Sell all grey items"]);
1322 GameTooltip:AddLine(L["SellsAll TooltipText2"]);
1323 else
1324 GameTooltip:SetText(L["Sell all garbage items"]);
1325 GameTooltip:AddLine(L["SellsAll TooltipText1"]);
1326 end
1327 local sellValue = self:GetSellValue();
1328 GameTooltip:AddLine(L["Value:"].." "..self:GetMoneyString(sellValue));
1329 GameTooltip:Show()
1330 end
1331  
1332 ------------------------------------------------------------------------------------------------------
1333 -- Item Price functions
1334 ------------------------------------------------------------------------------------------------------
1335  
1336 -- Get item value. Doh!
1337 function GarbageFu:GetItemValue(item)
1338 if item.id and item.qual and item.code then
1339 item.value, item.pricetype = self:GetUserOverridePrice(item.id)
1340 if not item.value then item.value, item.pricetype = self:GetKCIVendorPrice(item.id) end
1341 if not item.value then item.value, item.pricetype = self:GetInformantVendorPrice(item) end
1342 if not item.value then item.value, item.pricetype = self:GetWoWEconVendorPrice(item) end
1343 if not item.value then item.value, item.pricetype = self:GetItemSyncVendorPrice(item.link) end
1344 if not item.value then item.value, item.pricetype = self:GetPriceMasterVendorPrice(item.id) end
1345 if not item.value then item.value, item.pricetype = self:GetLudwigSellValueVendorPrice(item.id) end
1346 if not item.value then item.value, item.pricetype = self:GetLocalVendorPrice(item.id) end
1347 end
1348  
1349 if item.value then
1350 item.totvalue = item.value * item.stack;
1351 else
1352 item.value = 0; -- No item value know
1353 item.totvalue = 0; -- No item value know
1354 end
1355 end
1356  
1357 -- Price Types. First char: U = User, V = Vendor, A = Auction
1358 -- Second char: Addon the price was gotten from.
1359 -- K = KC_Items, W = WoWEcon, I = Informant, P = PriceMaster, L = Ludwig, T = Local table
1360  
1361 -- Get item price from the User Override table
1362 function GarbageFu:GetUserOverridePrice(itemid)
1363 if self.db.account.overrideprices[itemid] then
1364 return self.db.account.overrideprices[itemid], "|cffff7700UO|r"
1365 end
1366 end
1367  
1368 -- KC_Items
1369 function GarbageFu:GetKCIVendorPrice(itemid)
1370 local kv, vs
1371 if not KC_ItemsDB then return end
1372 kv = KC_ItemsDB[itemid]
1373 if kv then _, _, vs = string.find(kv, ",(%d+),%d+") end
1374 if (vs and vs ~= "0") then return tonumber(vs), "|cff0077ffVK|r" end
1375 end
1376  
1377 -- Auctioneer/Informant
1378 function GarbageFu:GetInformantVendorPrice(item)
1379 if not Informant then return end
1380 local itemData = Informant.GetItem(item.id)
1381 if (itemData and itemData['buy'] and itemData['buy'] ~= 0) then return itemData['sell'], "|cff0077ffVI" end
1382 end
1383  
1384 -- WoWEcon
1385 function GarbageFu:GetWoWEconVendorPrice(item)
1386 if not WOWEcon_Enabled then return end
1387 local price = WOWEcon_GetVendorPrice_ByLink(item.link);
1388 if price and price > 0 then return price, "|cff0077ffVW|r" end
1389 end
1390  
1391 -- PriceMaster doesn't have a price asking function, so we have to tap directly in to it's data. Ugly!
1392 function GarbageFu:GetPriceMasterVendorPrice(itemid)
1393 if ( CompletePrices and CompletePrices[itemid] and CompletePrices[itemid].p ) then
1394 return CompletePrices[itemid].p, "|cff0077ffVP|r"
1395 end
1396 end
1397  
1398 -- Ludwig_SellValue
1399 function GarbageFu:GetLudwigSellValueVendorPrice(itemid)
1400 local items = tostring(itemid)
1401 if ( Ludwig_SellValues and Ludwig_SellValues[items] ) then
1402 return Ludwig_SellValues[items], "|cff0077ffVL|r"
1403 end
1404 end
1405  
1406 function GarbageFu:GetItemSyncVendorPrice(itemlink)
1407 if (not ISync) then return end;
1408 local price = tonumber(ISync:FetchDB(ISync:GetCoreID(itemlink), "price"));
1409 if price and price > 0 then return price, "|cff0077ffVS|r" end
1410 end
1411  
1412 -- Look it up in our own price table
1413 function GarbageFu:GetLocalVendorPrice(itemid)
1414 if not self.vars.vendorprices then return end
1415  
1416 if self.vars.pricecache[itemid] then return self.vars.pricecache[itemid], "|cff0077ffVT|r" end
1417  
1418 local _, _, price = string.find(self.vars.vendorprices, " "..itemid..":(%d+)")
1419 if price then
1420 self.vars.pricecache[itemid] = tonumber(price)
1421 return self.vars.pricecache[itemid], "|cff0077ffVT|r"
1422 end
1423 end
1424  
1425 -- Check that we got a numeric value from the editbox.
1426 function GarbageFu.ValidateValue(self, value)
1427 self:DebugPrint( "ValidateValue value="..tostring(value));
1428 local res = ""
1429 for s in string.gfind(value, "(%d*).-(%d*)") do
1430 res=res..s
1431 end
1432 return res
1433 end
1434  
1435 -- Stores a new User Override price for the top item.
1436 function GarbageFu.SetFirstItemValue(self, value)
1437 local item = self:GetFirstDroppableItem();
1438 if item then
1439 GarbageFu.SetItemValue(self, item.id, value);
1440 end
1441 end
1442  
1443 -- Stores a new User Override price for an item, or removing it.
1444 function GarbageFu.SetItemValue(self, itemid, value)
1445 value = tonumber(value);
1446 if itemid then
1447 self:DebugPrint( "SetItemValue value="..tostring(value).."itemid="..tostring(itemid));
1448 if ( not value or value == 0 ) then
1449 if self.db.account.overrideprices[itemid] then
1450 self.db.account.overrideprices[itemid] = nil;
1451 local name = GetItemInfo(itemid);
1452 self:MyPrint(L["Removing custom price for %s."], name);
1453 end
1454 else
1455 self.db.account.overrideprices[itemid] = value;
1456 local name = GetItemInfo(itemid);
1457 self:MyPrint(L["Setting price for %s to %s."], name, self:GetMoneyString(value));
1458 end
1459 self:UpdateItemValue(itemid)
1460 self:SortItems();
1461 self:UpdateDisplay();
1462 end
1463 end
1464  
1465 -- Updates all occurances of itemid in the inventory with a new price.
1466 function GarbageFu:UpdateItemValue(itemid)
1467 for _, item in self.vars.items do
1468 if ( item.id == itemid ) then
1469 self:GetItemValue(item);
1470 end
1471 end
1472 end
1473  
1474 -- Load our own price table.
1475 function GarbageFu:LoadGarbagePrices(db)
1476 if not IsAddOnLoaded("FuBar_GarbageFu_Prices") then
1477 local res,reason = LoadAddOn("FuBar_GarbageFu_Prices");
1478 end
1479 if GarbageFu_PriceDb then
1480 self.vars.vendorprices = GarbageFu_PriceDb;
1481 return true;
1482 elseif GarbageFu_PriceTbl then
1483 self.vars.vendorprices = "";
1484 self.vars.pricecache = GarbageFu_PriceTbl;
1485 else
1486 self:MyPrint(L["Can't load FuBar_GarbageFu_Price. Check that it exists and are enabled"]);
1487 return;
1488 end
1489 end
1490  
1491 function GarbageFu:IsGarbagePricesAvailable()
1492 local name, title, notes, enabled, loadable, reason = GetAddOnInfo("FuBar_GarbageFu_Prices");
1493 return not reason;
1494 end
1495  
1496 ------------------------------------------------------------------------------------------------------
1497 -- Compost interface
1498 ------------------------------------------------------------------------------------------------------
1499  
1500 -- Method that will get a table from compost. If a table is passed in it will be erased and return.
1501 -- If a depth is specified then any subtables will be reclaimed by compost before erasing the table and returning it.
1502 function GarbageFu:Table(t,depth)
1503 if t then
1504 if type(t) ~= "table" then
1505 error("GarbageFu:Table called with a none table as input");
1506 return
1507 end
1508 if depth and depth > 0 then
1509 for i in pairs(t) do
1510 if type(t[i]) == "table" then
1511 compost:Reclaim(t[i], depth - 1 );
1512 end
1513 end
1514 end
1515 return compost:Erase(t);
1516 else
1517 return compost:GetTable();
1518 end
1519 end
1520  
1521 ------------------------------------------------------------------------------------------------------
1522 -- Chat output functions
1523 ------------------------------------------------------------------------------------------------------
1524  
1525 function GarbageFu:DebugPrint(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
1526 if self.CustomDebug then
1527 self:CustomDebug(1, 0.5, 0, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
1528 end
1529 end
1530  
1531 function GarbageFu:MyPrint(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
1532 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);
1533 end