annotate Core.lua @ 10:c4d0e5d47e10

Ok, please don?t crash again you silly Ace3 multiselect dropdown box. I know you?re itchy, but there?s nothing I can do for you. Cleaned up group management layout, added a duplicate group button. Track at character data is erased when exporting/importing groups. Duplicate items are erased when importing groups. Bug fixes and speed increases in Summary. Added a button to refresh the cache. Added a slider to increase caching speed. Auction value will no longer be cached if the threshold was set to 0.
author Zerotorescue
date Tue, 12 Oct 2010 02:08:37 +0200
parents 3bac0bdd59e2
children 10a2244f7ff0
rev   line source
Zerotorescue@0 1 -- You can access this addon's object through: LibStub("AceAddon-3.0"):GetAddon("Inventory")
Zerotorescue@1 2 local addon = LibStub("AceAddon-3.0"):NewAddon("Inventory", "AceEvent-3.0");
Zerotorescue@1 3
Zerotorescue@1 4 local AceGUI = LibStub("AceGUI-3.0");
Zerotorescue@0 5
Zerotorescue@0 6 local Media = LibStub("LibSharedMedia-3.0");
Zerotorescue@0 7 Media:Register("sound", "Cartoon FX", [[Sound\Doodad\Goblin_Lottery_Open03.wav]]);
Zerotorescue@0 8 Media:Register("sound", "Cheer", [[Sound\Event Sounds\OgreEventCheerUnique.wav]]);
Zerotorescue@0 9 Media:Register("sound", "Explosion", [[Sound\Doodad\Hellfire_Raid_FX_Explosion05.wav]]);
Zerotorescue@0 10 Media:Register("sound", "Fel Nova", [[Sound\Spells\SeepingGaseous_Fel_Nova.wav]]);
Zerotorescue@0 11 Media:Register("sound", "Fel Portal", [[Sound\Spells\Sunwell_Fel_PortalStand.wav]]);
Zerotorescue@0 12 Media:Register("sound", "Magic Click", [[Sound\interface\MagicClick.wav]]);
Zerotorescue@0 13 Media:Register("sound", "Rubber Ducky", [[Sound\Doodad\Goblin_Lottery_Open01.wav]]);
Zerotorescue@0 14 Media:Register("sound", "Shing!", [[Sound\Doodad\PortcullisActive_Closed.wav]]);
Zerotorescue@0 15 Media:Register("sound", "Simon Chime", [[Sound\Doodad\SimonGame_LargeBlueTree.wav]]);
Zerotorescue@0 16 Media:Register("sound", "Simon Error", [[Sound\Spells\SimonGame_Visual_BadPress.wav]]);
Zerotorescue@0 17 Media:Register("sound", "Simon Start", [[Sound\Spells\SimonGame_Visual_GameStart.wav]]);
Zerotorescue@0 18 Media:Register("sound", "War Drums", [[Sound\Event Sounds\Event_wardrum_ogre.wav]]);
Zerotorescue@0 19 Media:Register("sound", "Wham!", [[Sound\Doodad\PVP_Lordaeron_Door_Open.wav]]);
Zerotorescue@0 20 Media:Register("sound", "Whisper Ping", [[Sound\interface\iTellMessage.wav]]);
Zerotorescue@0 21 Media:Register("sound", "You Will Die!", [[Sound\Creature\CThun\CThunYouWillDIe.wav]]);
Zerotorescue@0 22
Zerotorescue@0 23 local AceConfigDialog, AceConfigRegistry, AceSerializer;
Zerotorescue@0 24 local groupIdToName = {};
Zerotorescue@0 25 local options = {};
Zerotorescue@0 26
Zerotorescue@0 27 function addon:OnInitialize()
Zerotorescue@0 28 self:Debug("OnInitialize");
Zerotorescue@0 29
Zerotorescue@0 30 -- SAVED VARIABLES
Zerotorescue@0 31
Zerotorescue@0 32 local defaults = {
Zerotorescue@0 33 global = {
Zerotorescue@0 34 groups = {},
Zerotorescue@0 35 defaults = {
Zerotorescue@0 36 minimumStock = 60,
Zerotorescue@0 37 alertBelowMinimum = true,
Zerotorescue@0 38 summaryThresholdShow = 10,
Zerotorescue@0 39 restockTarget = 60,
Zerotorescue@0 40 minCraftingQueue = 0.05,
Zerotorescue@0 41 bonusQueue = 0.1,
Zerotorescue@0 42 priceThreshold = 0,
Zerotorescue@1 43 hideFromSummaryWhenBelowPriceThreshold = false,
Zerotorescue@0 44 trackAtCharacters = {},
Zerotorescue@0 45 colors = {
Zerotorescue@0 46 red = 0;
Zerotorescue@0 47 orange = 0.3;
Zerotorescue@0 48 yellow = 0.6;
Zerotorescue@0 49 green = 0.95;
Zerotorescue@0 50 },
Zerotorescue@0 51 },
Zerotorescue@0 52 },
Zerotorescue@0 53 factionrealm = {
Zerotorescue@0 54 characters = {},
Zerotorescue@0 55 },
Zerotorescue@0 56 };
Zerotorescue@0 57
Zerotorescue@0 58 -- Register our saved variables database
Zerotorescue@0 59 self.db = LibStub("AceDB-3.0"):New("InventoryDB", defaults, true);
Zerotorescue@0 60
Zerotorescue@0 61 -- SLASH COMMANDS
Zerotorescue@0 62
Zerotorescue@0 63 -- Disable the AddonLoader slash commands
Zerotorescue@0 64 SLASH_INVENTORY1 = nil;
Zerotorescue@0 65 SLASH_IY1 = nil;
Zerotorescue@0 66
Zerotorescue@0 67 -- Register our own slash commands
Zerotorescue@0 68 SLASH_INVENTORY1 = "/inventory";
Zerotorescue@0 69 SLASH_INVENTORY2 = "/iy";
Zerotorescue@0 70 SlashCmdList["INVENTORY"] = function(msg)
Zerotorescue@0 71 self:CommandHandler(msg);
Zerotorescue@0 72 end
Zerotorescue@0 73
Zerotorescue@0 74 -- INTERFACE OPTIONS
Zerotorescue@0 75
Zerotorescue@0 76 -- Attempt to remove the interface options added by AddonLoader (if enabled)
Zerotorescue@0 77 if AddonLoader and AddonLoader.RemoveInterfaceOptions then
Zerotorescue@0 78 AddonLoader:RemoveInterfaceOptions("Inventory");
Zerotorescue@0 79 end
Zerotorescue@0 80
Zerotorescue@0 81 -- Now create our own options frame
Zerotorescue@0 82 local frame = CreateFrame("Frame", nil, UIParent);
Zerotorescue@0 83 frame:Hide();
Zerotorescue@0 84 frame.name = "Inventory";
Zerotorescue@0 85 frame:HookScript("OnShow", function(self)
Zerotorescue@0 86 -- Refresh the frame to instantly show the right options
Zerotorescue@0 87 InterfaceOptionsFrame_OpenToCategory(self.name)
Zerotorescue@0 88 end);
Zerotorescue@0 89 -- And add it to the interface options
Zerotorescue@0 90 InterfaceOptions_AddCategory(frame);
Zerotorescue@0 91
Zerotorescue@1 92 self:MakeItemLinkButtonWidget();
Zerotorescue@1 93 self:MakeConfigItemLinkButtonWidget();
Zerotorescue@0 94
Zerotorescue@0 95 -- Remember this character is mine
Zerotorescue@0 96 local playerName = UnitName("player");
Zerotorescue@0 97 if not self.db.factionrealm.characters[playerName] then
Zerotorescue@0 98 self.db.factionrealm.characters[playerName] = true;
Zerotorescue@0 99
Zerotorescue@0 100 -- Default to tracking on all chars, untracking is a convenience, not tracking by default would probably get multiple issue reports.
Zerotorescue@0 101 self.db.global.defaults.trackAtCharacters[playerName] = true;
Zerotorescue@0 102 end
Zerotorescue@0 103 end
Zerotorescue@0 104
Zerotorescue@1 105 local slashArgs = {};
Zerotorescue@1 106 function addon:RegisterSlash(func, ...)
Zerotorescue@1 107 for _, arg in pairs({ ... }) do
Zerotorescue@1 108 slashArgs[arg] = func;
Zerotorescue@1 109 end
Zerotorescue@1 110 end
Zerotorescue@1 111
Zerotorescue@1 112 function addon:MakeItemLinkButtonWidget()
Zerotorescue@0 113 --[[
Zerotorescue@0 114 [ ItemLinkButton ]
Zerotorescue@1 115 This custom widget has to show an icon with the item link next to it.
Zerotorescue@1 116 Upon hover it must show the item tooltip.
Zerotorescue@1 117 Upon click it must execute the function provided through user data.
Zerotorescue@1 118
Zerotorescue@1 119 UserData: itemId, onClickEvent
Zerotorescue@1 120
Zerotorescue@0 121 OnEnter: tooltip show
Zerotorescue@1 122 OnLeave: tooltip hide
Zerotorescue@1 123 OnClick: UserData.onClickEvent
Zerotorescue@0 124 ]]
Zerotorescue@0 125
Zerotorescue@0 126 local widgetType = "ItemLinkButton";
Zerotorescue@0 127 local widgetVersion = 1;
Zerotorescue@0 128
Zerotorescue@1 129 local function Constructor()
Zerotorescue@1 130 local widget = AceGUI:Create("InteractiveLabel");
Zerotorescue@1 131 widget.type = widgetType;
Zerotorescue@1 132
Zerotorescue@1 133 -- We overwrite the OnAcquire as we want to set our callbacks even
Zerotorescue@1 134 -- when the widget is re-used from the widget pool
Zerotorescue@1 135 widget.originalOnAcquire = widget.OnAcquire;
Zerotorescue@1 136 widget.OnAcquire = function(self, ...)
Zerotorescue@1 137
Zerotorescue@1 138
Zerotorescue@1 139 -- We overwrite the setcallback because we don't want anything else
Zerotorescue@1 140 -- to overwrite our OnEnter, OnLeave and OnClick events
Zerotorescue@1 141 -- which would be done by the AceConfigDialog after a widget gets re-used
Zerotorescue@1 142 if not self.originalSetCallBack then
Zerotorescue@1 143 self.originalSetCallBack = self.SetCallback;
Zerotorescue@1 144 self.SetCallback = function(this, event, func, ...)
Zerotorescue@1 145 if event == "OnEnter" or event == "OnLeave" or event == "OnClick" then
Zerotorescue@1 146 -- Don't allow overwriting of these events
Zerotorescue@1 147 return;
Zerotorescue@1 148 elseif event == "CustomOnEnter" then
Zerotorescue@1 149 return this.originalSetCallBack(this, "OnEnter", func, ...);
Zerotorescue@1 150 elseif event == "CustomOnLeave" then
Zerotorescue@1 151 return this.originalSetCallBack(this, "OnLeave", func, ...);
Zerotorescue@1 152 elseif event == "CustomOnClick" then
Zerotorescue@1 153 return this.originalSetCallBack(this, "OnClick", func, ...);
Zerotorescue@1 154 else
Zerotorescue@1 155 return this.originalSetCallBack(this, event, func, ...);
Zerotorescue@1 156 end
Zerotorescue@1 157 end;
Zerotorescue@1 158 end
Zerotorescue@1 159
Zerotorescue@1 160
Zerotorescue@1 161 -- Set our own events, since we disabled the normal event-names, we'll call them our custom versions
Zerotorescue@1 162 self:SetCallback("CustomOnEnter", function(this)
Zerotorescue@1 163 local itemId = this:GetUserData("itemId");
Zerotorescue@1 164
Zerotorescue@1 165 if itemId then
Zerotorescue@1 166 GameTooltip:SetOwner(this.frame, "ANCHOR_TOPRIGHT");
Zerotorescue@1 167 GameTooltip:SetHyperlink(("item:%d"):format(itemId));
Zerotorescue@1 168 GameTooltip:Show();
Zerotorescue@1 169 end
Zerotorescue@1 170 end);
Zerotorescue@1 171 self:SetCallback("CustomOnLeave", function(this)
Zerotorescue@1 172 GameTooltip:Hide();
Zerotorescue@1 173 end);
Zerotorescue@1 174 self:SetCallback("CustomOnClick", function(this)
Zerotorescue@1 175 if this.OnClick then
Zerotorescue@1 176 this.OnClick(this);
Zerotorescue@1 177 end
Zerotorescue@1 178
Zerotorescue@1 179 local func = this:GetUserData("exec");
Zerotorescue@1 180 local itemId = this:GetUserData("itemId");
Zerotorescue@1 181
Zerotorescue@1 182 if func then
Zerotorescue@1 183 -- If this is a config option we will need the group id
Zerotorescue@1 184 local path = this:GetUserData("path");
Zerotorescue@1 185 local groupId = (path and path[2]) or nil;
Zerotorescue@1 186
Zerotorescue@1 187 func(groupId, itemId);
Zerotorescue@1 188 end
Zerotorescue@1 189 end);
Zerotorescue@1 190
Zerotorescue@1 191
Zerotorescue@1 192
Zerotorescue@1 193 -- Then also do whatever it wanted to do
Zerotorescue@1 194 self.originalOnAcquire(self, ...);
Zerotorescue@1 195 end;
Zerotorescue@1 196
Zerotorescue@1 197 -- Remember the original SetText as this might get overwritten by the config-widget
Zerotorescue@1 198 widget.originalSetText = widget.SetText;
Zerotorescue@1 199
Zerotorescue@1 200 widget.SetItemId = function(self, itemId)
Zerotorescue@1 201 self:SetUserData("itemId", itemId);
Zerotorescue@1 202
Zerotorescue@1 203 -- Put the icon in front of it
Zerotorescue@1 204 self:SetImage(GetItemIcon(itemId));
Zerotorescue@0 205 -- Standardize the size
Zerotorescue@0 206 self:SetImageSize(16, 16);
Zerotorescue@0 207
Zerotorescue@0 208 -- Make readable font
Zerotorescue@0 209 self:SetFontObject(GameFontHighlight);
Zerotorescue@0 210
Zerotorescue@0 211 -- We don't want to set the itemId as text, but rather the item link, so get that.
Zerotorescue@1 212 local itemLink = select(2, GetItemInfo(itemId)) or ("Unknown (#%d)"):format(itemId);
Zerotorescue@0 213
Zerotorescue@1 214 self:originalSetText(itemLink);
Zerotorescue@1 215 end;
Zerotorescue@1 216
Zerotorescue@1 217 return widget;
Zerotorescue@0 218 end
Zerotorescue@1 219
Zerotorescue@1 220 AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion);
Zerotorescue@1 221 end
Zerotorescue@1 222
Zerotorescue@1 223 function addon:MakeConfigItemLinkButtonWidget()
Zerotorescue@1 224 -- Define out custom item link button widget
Zerotorescue@1 225 -- This will be called as if it's an input element, we overwrite some of the related functions which are called for default input fields
Zerotorescue@0 226
Zerotorescue@1 227 local widgetType = "ConfigItemLinkButton";
Zerotorescue@1 228 local widgetVersion = 1;
Zerotorescue@0 229
Zerotorescue@1 230 -- Empty function for disabling functions
Zerotorescue@1 231 local function Dummy() end
Zerotorescue@0 232
Zerotorescue@0 233 -- Makes an instance of our ItemLinkButton widget
Zerotorescue@0 234 local function GetItemLinkButton()
Zerotorescue@1 235 local widget = AceGUI:Create("ItemLinkButton");
Zerotorescue@0 236 widget.type = widgetType;
Zerotorescue@0 237
Zerotorescue@0 238 -- We can only provide custom widgets for input, select and multiselect fields
Zerotorescue@0 239 -- Input being the simplest, we use that - however, it provides two parameters: label and text. We only need one, disable the other.
Zerotorescue@0 240 widget.SetLabel = Dummy;
Zerotorescue@0 241
Zerotorescue@1 242 -- SetText is called when this button is being created and contains the itemId
Zerotorescue@1 243 -- Forward that itemId to the ItemLinkButton
Zerotorescue@1 244 widget.SetText = function(self, value, ...)
Zerotorescue@1 245 if value and tonumber(value) then
Zerotorescue@1 246 self:SetItemId(tonumber(value));
Zerotorescue@1 247 end
Zerotorescue@1 248 end;
Zerotorescue@1 249
Zerotorescue@1 250 widget.OnClick = function(self, ...)
Zerotorescue@1 251 local option = self:GetUserData("option");
Zerotorescue@1 252
Zerotorescue@1 253 if option and option.set then
Zerotorescue@1 254 self:SetUserData("exec", option.set);
Zerotorescue@1 255 end
Zerotorescue@1 256 end;
Zerotorescue@0 257
Zerotorescue@0 258 return widget;
Zerotorescue@0 259 end
Zerotorescue@0 260
Zerotorescue@0 261 AceGUI:RegisterWidgetType(widgetType, GetItemLinkButton, widgetVersion);
Zerotorescue@0 262 end
Zerotorescue@0 263
Zerotorescue@0 264 function addon:CommandHandler(message)
Zerotorescue@0 265 local cmd, arg = string.split(" ", (message or ""), 2);
Zerotorescue@0 266 cmd = string.lower(cmd);
Zerotorescue@0 267
Zerotorescue@0 268 if cmd == "c" or cmd == "config" or cmd == "conf" or cmd == "option" or cmd == "options" or cmd == "opt" or cmd == "setting" or cmd == "settings" then
Zerotorescue@9 269 -- We don't want any other windows open at this time.
Zerotorescue@9 270 for name, module in self:IterateModules() do
Zerotorescue@9 271 if module.CloseFrame then
Zerotorescue@9 272 module:CloseFrame();
Zerotorescue@9 273 end
Zerotorescue@9 274 end
Zerotorescue@9 275
Zerotorescue@0 276 self:Show();
Zerotorescue@0 277 elseif cmd == "d" or cmd == "debug" then
Zerotorescue@0 278 self.debugChannel = false;
Zerotorescue@0 279 for i = 1, NUM_CHAT_WINDOWS do
Zerotorescue@0 280 local name = GetChatWindowInfo(i);
Zerotorescue@0 281
Zerotorescue@0 282 if name:upper() == "DEBUG" then
Zerotorescue@0 283 self.debugChannel = _G["ChatFrame" .. i];
Zerotorescue@0 284
Zerotorescue@0 285 print("A debug channel already exists, used the old one. (" .. i .. ")");
Zerotorescue@0 286 return;
Zerotorescue@0 287 end
Zerotorescue@0 288 end
Zerotorescue@0 289
Zerotorescue@0 290 if not self.debugChannel then
Zerotorescue@0 291 -- Create a new debug channel
Zerotorescue@0 292 local chatFrame = FCF_OpenNewWindow('Debug');
Zerotorescue@0 293 ChatFrame_RemoveAllMessageGroups(chatFrame);
Zerotorescue@0 294 self.debugChannel = chatFrame;
Zerotorescue@0 295
Zerotorescue@0 296 print("New debug channel created.");
Zerotorescue@0 297 end
Zerotorescue@1 298 elseif slashArgs[cmd] then
Zerotorescue@1 299 slashArgs[cmd]();
Zerotorescue@0 300 else
Zerotorescue@9 301 print("Wrong command, available: /inventory config (or /iy c) and /inventory summary (or /iy s)");
Zerotorescue@0 302 end
Zerotorescue@0 303 end
Zerotorescue@0 304
Zerotorescue@0 305 function addon:Load()
Zerotorescue@0 306 if not AceConfigDialog and not AceConfigRegistry then
Zerotorescue@0 307 self:FillOptions();
Zerotorescue@0 308
Zerotorescue@0 309 -- Build options dialog
Zerotorescue@0 310 AceConfigDialog = LibStub("AceConfigDialog-3.0");
Zerotorescue@0 311 AceConfigRegistry = LibStub("AceConfigRegistry-3.0");
Zerotorescue@0 312 -- Register options table
Zerotorescue@0 313 LibStub("AceConfig-3.0"):RegisterOptionsTable("InventoryOptions", options);
Zerotorescue@0 314 -- Set a nice default size (so that 4 normal sized elements fit next to eachother)
Zerotorescue@0 315 AceConfigDialog:SetDefaultSize("InventoryOptions", 975, 600);
Zerotorescue@0 316
Zerotorescue@0 317 -- In case the addon is loaded from another condition, always call the remove interface options
Zerotorescue@0 318 if AddonLoader and AddonLoader.RemoveInterfaceOptions then
Zerotorescue@0 319 AddonLoader:RemoveInterfaceOptions("Inventory");
Zerotorescue@0 320 end
Zerotorescue@0 321
Zerotorescue@0 322 -- Add to the blizzard addons options thing
Zerotorescue@0 323 --AceConfigDialog:AddToBlizOptions("InventoryOptions");
Zerotorescue@0 324 end
Zerotorescue@0 325 end
Zerotorescue@0 326
Zerotorescue@0 327 function addon:Show()
Zerotorescue@0 328 self:Load();
Zerotorescue@0 329
Zerotorescue@0 330 AceConfigDialog:Open("InventoryOptions");
Zerotorescue@0 331 end
Zerotorescue@0 332
Zerotorescue@0 333 function addon:FillOptions()
Zerotorescue@0 334 options = {
Zerotorescue@0 335 type = "group",
Zerotorescue@0 336 name = "Inventory",
Zerotorescue@0 337 childGroups = "tree",
Zerotorescue@0 338 args = {
Zerotorescue@0 339 },
Zerotorescue@0 340 };
Zerotorescue@0 341
Zerotorescue@0 342 self:FillGeneralOptions();
Zerotorescue@0 343
Zerotorescue@0 344 options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db, true);
Zerotorescue@0 345 options.args.profiles.order = 200;
Zerotorescue@0 346
Zerotorescue@0 347 self:MakeGroupOptions();
Zerotorescue@0 348
Zerotorescue@0 349 self:FillGroupOptions();
Zerotorescue@0 350 end
Zerotorescue@0 351
Zerotorescue@1 352 local goldText = "%s%d|cffffd700g|r ";
Zerotorescue@1 353 local silverText = "%s%d|cffc7c7cfs|r ";
Zerotorescue@1 354 local copperText = "%s%d|cffeda55fc|r";
Zerotorescue@1 355
Zerotorescue@1 356 function addon:ReadableMoney(copper, clean)
Zerotorescue@1 357 local text = "";
Zerotorescue@1 358
Zerotorescue@1 359 local gold = floor( copper / COPPER_PER_GOLD );
Zerotorescue@1 360 if gold > 0 then
Zerotorescue@1 361 text = goldText:format(text, gold);
Zerotorescue@1 362 end
Zerotorescue@1 363
Zerotorescue@1 364 if not clean or (not gold or gold < 100) then
Zerotorescue@1 365 local silver = floor( ( copper % COPPER_PER_GOLD ) / COPPER_PER_SILVER );
Zerotorescue@1 366 if silver > 0 then
Zerotorescue@1 367 text = silverText:format(text, silver);
Zerotorescue@1 368 end
Zerotorescue@1 369
Zerotorescue@1 370 if not clean or (not gold or gold < 10) then
Zerotorescue@1 371 local copper = floor( copper % COPPER_PER_SILVER );
Zerotorescue@1 372 if copper > 0 or text == "" then
Zerotorescue@1 373 text = copperText:format(text, copper);
Zerotorescue@1 374 end
Zerotorescue@1 375 end
Zerotorescue@1 376 end
Zerotorescue@1 377
Zerotorescue@1 378
Zerotorescue@1 379 return string.trim(text);
Zerotorescue@1 380 end
Zerotorescue@1 381
Zerotorescue@1 382 function addon:ReadableMoneyToCopper(value)
Zerotorescue@1 383 -- If a player enters a value it will be filled without color codes
Zerotorescue@1 384 -- If it is retrieved from the database, it will be colored coded
Zerotorescue@1 385 -- Thus we look for both
Zerotorescue@1 386 local gold = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+g|r") or string.match(value, "(%d+)g"));
Zerotorescue@1 387 local silver = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+s|r") or string.match(value, "(%d+)s"));
Zerotorescue@1 388 local copper = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+c|r") or string.match(value, "(%d+)c"));
Zerotorescue@1 389
Zerotorescue@1 390 return ( (gold or 0) * COPPER_PER_GOLD ) + ( (silver or 0) * COPPER_PER_SILVER ) + (copper or 0);
Zerotorescue@1 391 end
Zerotorescue@1 392
Zerotorescue@1 393 function addon:ValidateReadableMoney(info, value)
Zerotorescue@1 394 -- If a player enters a value it will be filled without color codes
Zerotorescue@1 395 -- If it is retrieved from the database, it will be colored coded
Zerotorescue@1 396 -- Thus we look for both
Zerotorescue@1 397 local gold = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+g|r") or string.match(value, "(%d+)g"));
Zerotorescue@1 398 local silver = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+s|r") or string.match(value, "(%d+)s"));
Zerotorescue@1 399 local copper = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+c|r") or string.match(value, "(%d+)c"));
Zerotorescue@1 400
Zerotorescue@1 401 if not gold and not silver and not copper then
Zerotorescue@1 402 return "The provided amount of money is invalid. Please provide the amount of money as #g#s#c, e.g. 591617g24s43c.";
Zerotorescue@1 403 else
Zerotorescue@1 404 return true;
Zerotorescue@1 405 end
Zerotorescue@1 406 end
Zerotorescue@1 407
Zerotorescue@0 408 function addon:FillGeneralOptions()
Zerotorescue@0 409 options.args.general = {
Zerotorescue@0 410 order = 100,
Zerotorescue@0 411 type = "group",
Zerotorescue@0 412 name = "General",
Zerotorescue@0 413 desc = "Change general Inventory settings.",
Zerotorescue@0 414 args = {
Zerotorescue@0 415 general = {
Zerotorescue@0 416 order = 0,
Zerotorescue@0 417 type = "group",
Zerotorescue@0 418 inline = true,
Zerotorescue@0 419 name = "General",
Zerotorescue@0 420 args = {
Zerotorescue@0 421 description = {
Zerotorescue@0 422 order = 0,
Zerotorescue@0 423 type = "description",
Zerotorescue@0 424 name = "Change general settings unrelated to groups.",
Zerotorescue@0 425 },
Zerotorescue@0 426 header = {
Zerotorescue@0 427 order = 5,
Zerotorescue@0 428 type = "header",
Zerotorescue@0 429 name = "",
Zerotorescue@0 430 },
Zerotorescue@0 431 auctionAddon = {
Zerotorescue@0 432 order = 10,
Zerotorescue@0 433 type = "select",
Zerotorescue@0 434 name = "Prefered pricing addon",
Zerotorescue@0 435 values = {
Zerotorescue@0 436 Auctioneer = "Auctioneer",
Zerotorescue@0 437 Auctionator = "Auctionator",
Zerotorescue@0 438 },
Zerotorescue@0 439 get = function() end,
Zerotorescue@0 440 set = function(i, v) end,
Zerotorescue@0 441 },
Zerotorescue@0 442 itemCountAddon = {
Zerotorescue@0 443 order = 20,
Zerotorescue@0 444 type = "select",
Zerotorescue@0 445 name = "Prefered item count addon",
Zerotorescue@0 446 values = {
Zerotorescue@0 447 Altoholic = "Altoholic",
Zerotorescue@0 448 DataStore = "DataStore",
Zerotorescue@0 449 ItemCount = "ItemCount",
Zerotorescue@0 450 },
Zerotorescue@0 451 get = function() end,
Zerotorescue@0 452 set = function(i, v) end,
Zerotorescue@0 453 },
Zerotorescue@0 454 },
Zerotorescue@0 455 },
Zerotorescue@0 456 minimumStock = {
Zerotorescue@0 457 order = 10,
Zerotorescue@0 458 type = "group",
Zerotorescue@0 459 inline = true,
Zerotorescue@0 460 name = "Minimum stock",
Zerotorescue@0 461 args = {
Zerotorescue@0 462 description = {
Zerotorescue@0 463 order = 0,
Zerotorescue@0 464 type = "description",
Zerotorescue@0 465 name = "Here you can specify the default minimum amount of items you wish to keep in stock and related settings. The settings entered here will be used when you choose not to override the settings within an individual group.",
Zerotorescue@0 466 },
Zerotorescue@0 467 header = {
Zerotorescue@0 468 order = 5,
Zerotorescue@0 469 type = "header",
Zerotorescue@0 470 name = "",
Zerotorescue@0 471 },
Zerotorescue@0 472 minimumStock = {
Zerotorescue@0 473 order = 10,
Zerotorescue@0 474 type = "range",
Zerotorescue@0 475 min = 0,
Zerotorescue@0 476 max = 100000,
Zerotorescue@0 477 softMax = 1000,
Zerotorescue@0 478 step = 1,
Zerotorescue@0 479 name = "Minimum stock",
Zerotorescue@0 480 desc = "You can manually enter a value between 1.000 and 100.000 in the edit box if the provided range is insufficient.",
Zerotorescue@0 481 get = function() return self.db.global.defaults.minimumStock; end,
Zerotorescue@0 482 set = function(i, v) self.db.global.defaults.minimumStock = v; end,
Zerotorescue@0 483 },
Zerotorescue@0 484 summaryThresholdShow = {
Zerotorescue@0 485 order = 20,
Zerotorescue@0 486 type = "range",
Zerotorescue@0 487 min = 0,
Zerotorescue@0 488 max = 100,
Zerotorescue@0 489 softMax = 10,
Zerotorescue@0 490 step = 0.05,
Zerotorescue@0 491 isPercent = true,
Zerotorescue@0 492 name = "Show in summary when below",
Zerotorescue@0 493 desc = "Show items in the summary when below this percentage of the minimum stock.\n\nYou can manually enter a value between 1.000% and 10.000% in the edit box if the provided range is insufficient.",
Zerotorescue@0 494 get = function() return self.db.global.defaults.summaryThresholdShow; end,
Zerotorescue@0 495 set = function(i, v) self.db.global.defaults.summaryThresholdShow = v; end,
Zerotorescue@0 496 },
Zerotorescue@0 497 alertBelowMinimum = {
Zerotorescue@0 498 order = 30,
Zerotorescue@0 499 type = "toggle",
Zerotorescue@0 500 name = "Alert when below minimum",
Zerotorescue@0 501 desc = "Show an alert when this item gets below this threshold.",
Zerotorescue@0 502 get = function() return self.db.global.defaults.alertBelowMinimum; end,
Zerotorescue@0 503 set = function(i, v) self.db.global.defaults.alertBelowMinimum = v; end,
Zerotorescue@0 504 },
Zerotorescue@0 505 trackAtCharacters = {
Zerotorescue@0 506 order = 40,
Zerotorescue@0 507 type = "multiselect",
Zerotorescue@0 508 name = "Track at",
Zerotorescue@0 509 desc = "Select at which characters this should appear in the summary and generate alerts.",
Zerotorescue@0 510 values = function()
Zerotorescue@0 511 local temp = {};
Zerotorescue@0 512 for charName in pairs(self.db.factionrealm.characters) do
Zerotorescue@0 513 temp[charName] = charName;
Zerotorescue@0 514 end
Zerotorescue@0 515
Zerotorescue@0 516 return temp;
Zerotorescue@0 517 end,
Zerotorescue@1 518 get = function(i, v) return self.db.global.defaults.trackAtCharacters[v]; end,
Zerotorescue@0 519 set = function(i, v, e)
Zerotorescue@0 520 self.db.global.defaults.trackAtCharacters[v] = e or nil;
Zerotorescue@1 521
Zerotorescue@1 522 -- We MUST close this pullout or we can get errors or even game client crashes once we click another group or close the config dialog!
Zerotorescue@1 523 local count = AceGUI:GetNextWidgetNum("Dropdown-Pullout");
Zerotorescue@7 524 for i = 1, count do
Zerotorescue@1 525 if _G['AceGUI30Pullout' .. i] then
Zerotorescue@1 526 _G['AceGUI30Pullout' .. i]:Hide();
Zerotorescue@1 527 end
Zerotorescue@1 528 end
Zerotorescue@0 529 end,
Zerotorescue@10 530 confirm = true,
Zerotorescue@1 531 dialogControl = "Dropdown", -- this is not standard, normal multiselect control gives us a list of all chars with toggle-boxes. UGLY! We want a multiselect-box instead.
Zerotorescue@0 532 },
Zerotorescue@0 533 },
Zerotorescue@0 534 },
Zerotorescue@0 535 refill = {
Zerotorescue@0 536 order = 20,
Zerotorescue@0 537 type = "group",
Zerotorescue@0 538 inline = true,
Zerotorescue@0 539 name = "Replenishing stock",
Zerotorescue@0 540 args = {
Zerotorescue@0 541 description = {
Zerotorescue@0 542 order = 0,
Zerotorescue@0 543 type = "description",
Zerotorescue@0 544 name = function()
Zerotorescue@0 545 local r = "Here you can specify the default amount of items to which you wish to restock when you are collecting new items. This may be higher than the minimum stock. The settings entered here will be used when you choose not to override the settings within an individual group.\n\n";
Zerotorescue@0 546
Zerotorescue@0 547 r = r .. "When restocking the target amount is |cfffed000" .. self.db.global.defaults.restockTarget .. "|r of every item. Not queueing craftable items when only missing |cfffed000" .. floor( self.db.global.defaults.minCraftingQueue * self.db.global.defaults.restockTarget ) .. "|r (|cfffed000" .. ( self.db.global.defaults.minCraftingQueue * 100 ) .. "%|r) of the restock target.";
Zerotorescue@0 548
Zerotorescue@0 549 return r;
Zerotorescue@0 550 end,
Zerotorescue@0 551 },
Zerotorescue@0 552 header = {
Zerotorescue@0 553 order = 5,
Zerotorescue@0 554 type = "header",
Zerotorescue@0 555 name = "",
Zerotorescue@0 556 },
Zerotorescue@0 557 restockTarget = {
Zerotorescue@0 558 order = 10,
Zerotorescue@0 559 type = "range",
Zerotorescue@0 560 min = 0,
Zerotorescue@0 561 max = 100000,
Zerotorescue@0 562 softMax = 1000,
Zerotorescue@0 563 step = 1,
Zerotorescue@0 564 name = "Restock target",
Zerotorescue@0 565 desc = "You can manually enter a value between 1.000 and 100.000 in the edit box if the provided range is insufficient.",
Zerotorescue@0 566 get = function() return self.db.global.defaults.restockTarget; end,
Zerotorescue@0 567 set = function(i, v) self.db.global.defaults.restockTarget = v; end,
Zerotorescue@0 568 },
Zerotorescue@0 569 minCraftingQueue = {
Zerotorescue@0 570 order = 20,
Zerotorescue@0 571 type = "range",
Zerotorescue@0 572 min = 0,
Zerotorescue@0 573 max = 1,
Zerotorescue@0 574 step = 0.01, -- 1%
Zerotorescue@0 575 isPercent = true,
Zerotorescue@0 576 name = "Don't queue if I only miss",
Zerotorescue@0 577 desc = "Don't add a craftable item to the queue if I only miss this much or less of the restock target.\n\nExample: if your restock target is set to 60 and this is set to 5%, an item won't be queued unless you are missing more than 3 of it.",
Zerotorescue@0 578 get = function() return self.db.global.defaults.minCraftingQueue; end,
Zerotorescue@0 579 set = function(i, v) self.db.global.defaults.minCraftingQueue = v; end,
Zerotorescue@0 580 },
Zerotorescue@0 581 bonusQueue = {
Zerotorescue@0 582 order = 30,
Zerotorescue@0 583 type = "range",
Zerotorescue@0 584 min = 0,
Zerotorescue@0 585 max = 10, -- 1000%
Zerotorescue@0 586 step = 0.01, -- 1%
Zerotorescue@0 587 isPercent = true,
Zerotorescue@0 588 name = "Bonus queue",
Zerotorescue@1 589 desc = "Get additional items when there are none left.\n\nExample: if your restock target is set to 60 and this is set to 10%, you will get 66 items instead of just 60 if you end up with none left while queueing.",
Zerotorescue@0 590 get = function() return self.db.global.defaults.bonusQueue; end,
Zerotorescue@0 591 set = function(i, v) self.db.global.defaults.bonusQueue = v; end,
Zerotorescue@0 592 },
Zerotorescue@0 593 priceThreshold = {
Zerotorescue@0 594 order = 40,
Zerotorescue@0 595 type = "input",
Zerotorescue@0 596 name = "Price threshold",
Zerotorescue@1 597 desc = "Only queue craftable items when they are worth at least this much according to your auction house addon.\n\nSet to 0 to ignore auction prices.",
Zerotorescue@1 598 validate = function(info, value) return self:ValidateReadableMoney(info, value); end,
Zerotorescue@1 599 get = function() return self:ReadableMoney(self.db.global.defaults.priceThreshold); end,
Zerotorescue@1 600 set = function(i, v) self.db.global.defaults.priceThreshold = self:ReadableMoneyToCopper(v); end,
Zerotorescue@0 601 },
Zerotorescue@1 602 hideFromSummaryWhenBelowPriceThreshold = { -- I wish this var could be a little bit shorter...
Zerotorescue@0 603 order = 50,
Zerotorescue@0 604 type = "toggle",
Zerotorescue@1 605 name = "Hide when below threshold",
Zerotorescue@0 606 desc = "Hide items from the summary when their value is below the set price threshold.",
Zerotorescue@1 607 get = function() return self.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold; end,
Zerotorescue@1 608 set = function(i, v) self.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold = v; end,
Zerotorescue@0 609 },
Zerotorescue@0 610 },
Zerotorescue@0 611 },
Zerotorescue@0 612 colorCodes = {
Zerotorescue@0 613 order = 30,
Zerotorescue@0 614 type = "group",
Zerotorescue@0 615 inline = true,
Zerotorescue@0 616 name = "Color codes",
Zerotorescue@0 617 args = {
Zerotorescue@0 618 description = {
Zerotorescue@0 619 order = 0,
Zerotorescue@0 620 type = "description",
Zerotorescue@0 621 name = "Change the color code thresholds based on the current stock remaining of the required minimum stock.",
Zerotorescue@0 622 },
Zerotorescue@0 623 header = {
Zerotorescue@0 624 order = 5,
Zerotorescue@0 625 type = "header",
Zerotorescue@0 626 name = "",
Zerotorescue@0 627 },
Zerotorescue@0 628 green = {
Zerotorescue@0 629 order = 10,
Zerotorescue@0 630 type = "range",
Zerotorescue@0 631 min = 0,
Zerotorescue@0 632 max = 1,
Zerotorescue@0 633 step = 0.01,
Zerotorescue@0 634 isPercent = true,
Zerotorescue@0 635 name = "|cff00ff00Green|r",
Zerotorescue@0 636 desc = "Show quantity in green when at least this much of the minimum stock is available.",
Zerotorescue@0 637 get = function() return self.db.global.defaults.colors.green; end,
Zerotorescue@0 638 set = function(i, v) self.db.global.defaults.colors.green = v; end,
Zerotorescue@0 639 },
Zerotorescue@0 640 yellow = {
Zerotorescue@0 641 order = 20,
Zerotorescue@0 642 type = "range",
Zerotorescue@0 643 min = 0,
Zerotorescue@0 644 max = 1,
Zerotorescue@0 645 step = 0.01,
Zerotorescue@0 646 isPercent = true,
Zerotorescue@0 647 name = "|cffffff00Yellow|r",
Zerotorescue@0 648 desc = "Show quantity in yellow when at least this much of the minimum stock is available.",
Zerotorescue@0 649 get = function() return self.db.global.defaults.colors.yellow; end,
Zerotorescue@0 650 set = function(i, v) self.db.global.defaults.colors.yellow = v; end,
Zerotorescue@0 651 },
Zerotorescue@0 652 orange = {
Zerotorescue@0 653 order = 30,
Zerotorescue@0 654 type = "range",
Zerotorescue@0 655 min = 0,
Zerotorescue@0 656 max = 1,
Zerotorescue@0 657 step = 0.01,
Zerotorescue@0 658 isPercent = true,
Zerotorescue@0 659 name = "|cffff9933Orange|r",
Zerotorescue@0 660 desc = "Show quantity in orange when at least this much of the minimum stock is available.",
Zerotorescue@0 661 get = function() return self.db.global.defaults.colors.orange; end,
Zerotorescue@0 662 set = function(i, v) self.db.global.defaults.colors.orange = v; end,
Zerotorescue@0 663 },
Zerotorescue@0 664 red = {
Zerotorescue@0 665 order = 40,
Zerotorescue@0 666 type = "range",
Zerotorescue@0 667 min = 0,
Zerotorescue@0 668 max = 1,
Zerotorescue@0 669 step = 0.01,
Zerotorescue@0 670 isPercent = true,
Zerotorescue@0 671 name = "|cffff0000Red|r",
Zerotorescue@0 672 desc = "Show quantity in red when at least this much of the minimum stock is available.",
Zerotorescue@0 673 get = function() return self.db.global.defaults.colors.red; end,
Zerotorescue@0 674 set = function(i, v) self.db.global.defaults.colors.red = v; end,
Zerotorescue@0 675 },
Zerotorescue@0 676 },
Zerotorescue@0 677 },
Zerotorescue@0 678 },
Zerotorescue@0 679 };
Zerotorescue@0 680 end
Zerotorescue@0 681
Zerotorescue@0 682 local count = 0;
Zerotorescue@0 683 local temp = {};
Zerotorescue@0 684
Zerotorescue@1 685 local function SetOption(info, value, multiSelectEnabled)
Zerotorescue@0 686 local groupName = groupIdToName[info[2]];
Zerotorescue@0 687 local optionName = info[#info];
Zerotorescue@0 688
Zerotorescue@0 689 -- No need to store a setting if it's disabled (false)
Zerotorescue@0 690 if not value and info.arg and not info.arg:find("override") then
Zerotorescue@0 691 value = nil;
Zerotorescue@0 692
Zerotorescue@0 693 -- If this is an override toggler then also set the related field to nil
Zerotorescue@0 694 addon.db.global.groups[groupName][info.arg] = nil;
Zerotorescue@0 695 end
Zerotorescue@0 696
Zerotorescue@1 697 if multiSelectEnabled ~= nil then
Zerotorescue@1 698 -- The saved vars for a multiselect will always be an array, it may not yet exist in which case it must be created.
Zerotorescue@1 699 if not addon.db.global.groups[groupName][optionName] then
Zerotorescue@1 700 addon.db.global.groups[groupName][optionName] = {};
Zerotorescue@1 701 end
Zerotorescue@1 702
Zerotorescue@1 703 addon.db.global.groups[groupName][optionName][value] = multiSelectEnabled or nil;
Zerotorescue@1 704 else
Zerotorescue@1 705 addon.db.global.groups[groupName][optionName] = value;
Zerotorescue@1 706 end
Zerotorescue@0 707 end
Zerotorescue@0 708
Zerotorescue@1 709 function addon:GetOptionByKey(groupName, optionName, noDefault)
Zerotorescue@0 710 if addon.db.global.groups[groupName][optionName] ~= nil then
Zerotorescue@0 711 return addon.db.global.groups[groupName][optionName];
Zerotorescue@0 712 elseif addon.db.global.defaults[optionName] and not noDefault then
Zerotorescue@0 713 return addon.db.global.defaults[optionName];
Zerotorescue@0 714 else
Zerotorescue@0 715 return nil;
Zerotorescue@0 716 end
Zerotorescue@0 717 end
Zerotorescue@0 718
Zerotorescue@0 719 local function GetOption(info)
Zerotorescue@0 720 local groupName = groupIdToName[info[2]];
Zerotorescue@0 721 local optionName = info[#info];
Zerotorescue@0 722
Zerotorescue@1 723 return addon:GetOptionByKey(groupName, optionName);
Zerotorescue@1 724 end
Zerotorescue@1 725
Zerotorescue@1 726 local function GetMultiOption(info, value)
Zerotorescue@1 727 local groupName = groupIdToName[info[2]];
Zerotorescue@1 728 local optionName = info[#info];
Zerotorescue@1 729
Zerotorescue@1 730 if addon.db.global.groups[groupName][optionName] ~= nil then
Zerotorescue@1 731 return addon.db.global.groups[groupName][optionName][value];
Zerotorescue@1 732 elseif addon.db.global.defaults[optionName] then
Zerotorescue@1 733 return addon.db.global.defaults[optionName][value];
Zerotorescue@1 734 else
Zerotorescue@1 735 return nil;
Zerotorescue@1 736 end
Zerotorescue@0 737 end
Zerotorescue@0 738
Zerotorescue@0 739 local function GetDisabled(info)
Zerotorescue@0 740 if not info.arg or not info.arg:find("override") then
Zerotorescue@0 741 return false;
Zerotorescue@0 742 end
Zerotorescue@0 743
Zerotorescue@0 744 local groupName = groupIdToName[info[2]];
Zerotorescue@0 745 local optionName = info[#info];
Zerotorescue@0 746
Zerotorescue@1 747 return (addon:GetOptionByKey(groupName, info.arg, true) == nil);
Zerotorescue@0 748 end
Zerotorescue@0 749
Zerotorescue@0 750 local function ValidateGroupName(_, value)
Zerotorescue@0 751 value = string.lower(string.trim(value or ""));
Zerotorescue@0 752
Zerotorescue@0 753 for name, _ in pairs(addon.db.global.groups) do
Zerotorescue@0 754 if string.lower(name) == value then
Zerotorescue@0 755 return ("A group named \"%s\" already exists."):format(name);
Zerotorescue@0 756 end
Zerotorescue@0 757 end
Zerotorescue@0 758
Zerotorescue@0 759 return true;
Zerotorescue@0 760 end
Zerotorescue@0 761
Zerotorescue@0 762 local function InGroup(itemId)
Zerotorescue@0 763 -- Go through all groups to see if this item is already somewhere
Zerotorescue@0 764 for groupName, values in pairs(addon.db.global.groups) do
Zerotorescue@0 765 if values.items and values.items[itemId] then
Zerotorescue@0 766 return groupName;
Zerotorescue@0 767 end
Zerotorescue@0 768 end
Zerotorescue@0 769
Zerotorescue@0 770 return;
Zerotorescue@0 771 end
Zerotorescue@0 772
Zerotorescue@0 773 local function AddToGroup(groupName, itemId)
Zerotorescue@0 774 if InGroup(itemId) then
Zerotorescue@0 775 return false;
Zerotorescue@0 776 end
Zerotorescue@0 777
Zerotorescue@0 778 if not addon.db.global.groups[groupName].items then
Zerotorescue@0 779 addon.db.global.groups[groupName].items = {};
Zerotorescue@0 780 end
Zerotorescue@0 781
Zerotorescue@0 782 -- Set this item
Zerotorescue@0 783 addon.db.global.groups[groupName].items[itemId] = true;
Zerotorescue@0 784
Zerotorescue@0 785 -- Now rebuild the list
Zerotorescue@0 786 AceConfigRegistry:NotifyChange("InventoryOptions");
Zerotorescue@0 787
Zerotorescue@0 788 return true;
Zerotorescue@0 789 end
Zerotorescue@0 790
Zerotorescue@0 791 local tblAddItemTemplate = {
Zerotorescue@0 792 order = 0,
Zerotorescue@0 793 type = "input",
Zerotorescue@0 794 name = function(info)
Zerotorescue@0 795 local itemName, _, itemRarity = GetItemInfo(info[#info]);
Zerotorescue@0 796 return tostring( 7 - (itemRarity or 0) ) .. (itemName or "");
Zerotorescue@0 797 end,
Zerotorescue@0 798 get = function(info)
Zerotorescue@0 799 return tostring(info[#info]); -- Ace is going to be anal about this if it's a numeric value, so we transmute it into a string here then back to a number on the other side
Zerotorescue@0 800 end,
Zerotorescue@1 801 set = function(groupId, itemId)
Zerotorescue@0 802 -- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info.
Zerotorescue@0 803
Zerotorescue@1 804 if itemId then
Zerotorescue@1 805 local groupName = groupIdToName[groupId];
Zerotorescue@0 806
Zerotorescue@1 807 if not AddToGroup(groupName, itemId) then
Zerotorescue@1 808 print("|cffff0000Couldn't add the item with itemId (" .. itemId .. ") because it is already in a group.|r");
Zerotorescue@0 809 end
Zerotorescue@0 810 end
Zerotorescue@0 811 end,
Zerotorescue@0 812 width = "double",
Zerotorescue@1 813 dialogControl = "ConfigItemLinkButton",
Zerotorescue@0 814 };
Zerotorescue@0 815
Zerotorescue@0 816 local tblRemoveItemTemplate = {
Zerotorescue@0 817 order = 0,
Zerotorescue@0 818 type = "input",
Zerotorescue@0 819 name = function(info)
Zerotorescue@0 820 local itemName, _, itemRarity = GetItemInfo(info[#info]);
Zerotorescue@0 821 return tostring( 7 - (itemRarity or 0) ) .. (itemName or "");
Zerotorescue@0 822 end,
Zerotorescue@0 823 get = function(info)
Zerotorescue@0 824 return tostring(info[#info]); -- Ace is going to be anal about this if it's a numeric value, so we transmute it into a string here then back to a number on the other side
Zerotorescue@0 825 end,
Zerotorescue@1 826 set = function(groupId, itemId)
Zerotorescue@0 827 -- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info.
Zerotorescue@0 828
Zerotorescue@1 829 if itemId then
Zerotorescue@1 830 local groupName = groupIdToName[groupId];
Zerotorescue@0 831
Zerotorescue@0 832 -- Unset this item
Zerotorescue@1 833 addon.db.global.groups[groupName].items[itemId] = nil;
Zerotorescue@0 834
Zerotorescue@0 835 -- Now rebuild the list
Zerotorescue@0 836 AceConfigRegistry:NotifyChange("InventoryOptions");
Zerotorescue@0 837 end
Zerotorescue@0 838 end,
Zerotorescue@0 839 width = "double",
Zerotorescue@1 840 dialogControl = "ConfigItemLinkButton",
Zerotorescue@0 841 };
Zerotorescue@0 842
Zerotorescue@0 843 local function UpdateAddItemList(info)
Zerotorescue@0 844 local groupName = groupIdToName[info[2]];
Zerotorescue@0 845
Zerotorescue@0 846 if not addon.db.global.groups[groupName].items then
Zerotorescue@0 847 addon.db.global.groups[groupName].items = {};
Zerotorescue@0 848 end
Zerotorescue@0 849
Zerotorescue@0 850 -- Merge all items from all groups together
Zerotorescue@0 851 local items = {};
Zerotorescue@0 852 for groupName, values in pairs(addon.db.global.groups) do
Zerotorescue@0 853 if values.items then
Zerotorescue@0 854 for itemId, _ in pairs(values.items) do
Zerotorescue@0 855 items[itemId] = true;
Zerotorescue@0 856 end
Zerotorescue@0 857 end
Zerotorescue@0 858 end
Zerotorescue@0 859
Zerotorescue@0 860 local ref = options.args.groups.args[info[2]].args.add.args.list.args;
Zerotorescue@0 861
Zerotorescue@0 862 -- Parse bags and show these
Zerotorescue@0 863 for bagID = 4, 0, -1 do
Zerotorescue@0 864 for slot = 1, GetContainerNumSlots(bagID) do
Zerotorescue@0 865 local itemId = addon:GetItemId(GetContainerItemLink(bagID, slot));
Zerotorescue@0 866
Zerotorescue@0 867 if itemId then
Zerotorescue@0 868 if not items[itemId] then
Zerotorescue@0 869 -- If this item isn't used in any group yet
Zerotorescue@0 870 ref[itemId] = tblAddItemTemplate;
Zerotorescue@0 871 else
Zerotorescue@0 872 -- It's already used in a group, don't show it
Zerotorescue@0 873 ref[itemId] = nil;
Zerotorescue@0 874 end
Zerotorescue@0 875 end
Zerotorescue@0 876 end
Zerotorescue@0 877 end
Zerotorescue@0 878 end
Zerotorescue@0 879
Zerotorescue@0 880 local function UpdateRemoveItemList(info)
Zerotorescue@0 881 local groupName = groupIdToName[info[2]];
Zerotorescue@0 882
Zerotorescue@0 883 if not addon.db.global.groups[groupName].items then
Zerotorescue@0 884 addon.db.global.groups[groupName].items = {};
Zerotorescue@0 885 end
Zerotorescue@0 886
Zerotorescue@0 887 local ref = options.args.groups.args[info[2]].args.remove.args.list.args;
Zerotorescue@0 888
Zerotorescue@0 889 -- Unset all
Zerotorescue@0 890 for itemId, _ in pairs(ref) do
Zerotorescue@0 891 ref[itemId] = nil;
Zerotorescue@0 892 end
Zerotorescue@0 893
Zerotorescue@0 894 -- Parse items in group and show these
Zerotorescue@0 895 for itemId, _ in pairs(addon.db.global.groups[groupName].items) do
Zerotorescue@0 896 ref[itemId] = tblRemoveItemTemplate;
Zerotorescue@0 897 end
Zerotorescue@0 898 end
Zerotorescue@0 899
Zerotorescue@0 900 function addon:GetItemId(itemLink)
Zerotorescue@0 901 itemLink = itemLink and select(3, string.find(itemLink, "|Hitem:([-0-9]+):")); -- if itemLink is nil, it won't execute the second part
Zerotorescue@0 902 itemLink = itemLink and tonumber(itemLink);
Zerotorescue@0 903
Zerotorescue@0 904 return itemLink;
Zerotorescue@0 905 end
Zerotorescue@0 906
Zerotorescue@0 907 -- Default group
Zerotorescue@0 908 local defaultGroup = {
Zerotorescue@0 909 order = 0,
Zerotorescue@0 910 type = "group",
Zerotorescue@0 911 childGroups = "tab",
Zerotorescue@0 912 name = function(info)
Zerotorescue@0 913 return groupIdToName[info[#info]];
Zerotorescue@0 914 end,
Zerotorescue@0 915 args = {
Zerotorescue@0 916 general = {
Zerotorescue@0 917 order = 10,
Zerotorescue@0 918 type = "group",
Zerotorescue@0 919 name = "Stock settings",
Zerotorescue@0 920 desc = "Change the stock settings for just this group.",
Zerotorescue@0 921 args = {
Zerotorescue@0 922 minimumStock = {
Zerotorescue@0 923 order = 10,
Zerotorescue@0 924 type = "group",
Zerotorescue@0 925 inline = true,
Zerotorescue@0 926 name = "Minimum stock",
Zerotorescue@0 927 set = SetOption,
Zerotorescue@0 928 get = GetOption,
Zerotorescue@0 929 disabled = GetDisabled,
Zerotorescue@0 930 args = {
Zerotorescue@0 931 description = {
Zerotorescue@0 932 order = 0,
Zerotorescue@0 933 type = "description",
Zerotorescue@0 934 name = "Here you can specify the minimum amount of items you wish to keep in stock and related settings for the currently selected group.",
Zerotorescue@0 935 },
Zerotorescue@0 936 header = {
Zerotorescue@0 937 order = 5,
Zerotorescue@0 938 type = "header",
Zerotorescue@0 939 name = "",
Zerotorescue@0 940 },
Zerotorescue@0 941 overrideMinimumStock = {
Zerotorescue@0 942 order = 9,
Zerotorescue@0 943 type = "toggle",
Zerotorescue@0 944 name = "Override min stock",
Zerotorescue@0 945 desc = "Allows you to override the minimum stock setting for this group.",
Zerotorescue@0 946 arg = "minimumStock",
Zerotorescue@0 947 },
Zerotorescue@0 948 minimumStock = {
Zerotorescue@0 949 order = 10,
Zerotorescue@0 950 type = "range",
Zerotorescue@0 951 min = 0,
Zerotorescue@0 952 max = 100000,
Zerotorescue@0 953 softMax = 1000,
Zerotorescue@0 954 step = 1,
Zerotorescue@0 955 name = "Minimum stock",
Zerotorescue@0 956 desc = "You can manually enter a value between 1.000 and 100.000 in the edit box if the provided range is insufficient.",
Zerotorescue@0 957 arg = "overrideMinimumStock",
Zerotorescue@0 958 },
Zerotorescue@0 959 overrideSummaryThresholdShow = {
Zerotorescue@0 960 order = 19,
Zerotorescue@0 961 type = "toggle",
Zerotorescue@0 962 name = "Override summary showing",
Zerotorescue@0 963 desc = "Allows you to override when this group should appear in the summary.",
Zerotorescue@0 964 arg = "summaryThresholdShow",
Zerotorescue@0 965 },
Zerotorescue@0 966 summaryThresholdShow = {
Zerotorescue@0 967 order = 20,
Zerotorescue@0 968 type = "range",
Zerotorescue@0 969 min = 0,
Zerotorescue@0 970 max = 100,
Zerotorescue@0 971 softMax = 10,
Zerotorescue@0 972 step = 0.05,
Zerotorescue@0 973 isPercent = true,
Zerotorescue@0 974 name = "Show in summary when below",
Zerotorescue@0 975 desc = "Show items in the summary when below the specified percentage of the minimum stock.\n\nYou can manually enter a value between 1.000% and 10.000% in the edit box if the provided range is insufficient.",
Zerotorescue@0 976 arg = "overrideSummaryThresholdShow",
Zerotorescue@0 977 },
Zerotorescue@0 978 overrideAlertBelowMinimum = {
Zerotorescue@0 979 order = 29,
Zerotorescue@0 980 type = "toggle",
Zerotorescue@0 981 name = "Override minimum alert",
Zerotorescue@0 982 desc = "Allows you to override wether an alert should be shown when an item in this group gets below the minimum stock threshold.",
Zerotorescue@0 983 arg = "alertBelowMinimum",
Zerotorescue@0 984 },
Zerotorescue@0 985 alertBelowMinimum = {
Zerotorescue@0 986 order = 30,
Zerotorescue@0 987 type = "toggle",
Zerotorescue@0 988 name = "Alert when below minimum",
Zerotorescue@0 989 desc = "Show an alert when an item in this group gets below the minimum stock threshold.",
Zerotorescue@0 990 arg = "overrideAlertBelowMinimum",
Zerotorescue@0 991 },
Zerotorescue@1 992 overrideTrackAtCharacters = {
Zerotorescue@1 993 order = 39,
Zerotorescue@1 994 type = "toggle",
Zerotorescue@1 995 name = "Override track at",
Zerotorescue@1 996 desc = "Allows you to override at which characters items in this group should appear in the summary and generate alerts.",
Zerotorescue@1 997 arg = "trackAtCharacters",
Zerotorescue@1 998 },
Zerotorescue@1 999 trackAtCharacters = {
Zerotorescue@1 1000 order = 40,
Zerotorescue@1 1001 type = "multiselect",
Zerotorescue@1 1002 name = "Track at",
Zerotorescue@1 1003 desc = "Select at which characters this should appear in the summary and generate alerts.",
Zerotorescue@1 1004 values = function()
Zerotorescue@1 1005 local temp = {};
Zerotorescue@1 1006 for charName in pairs(addon.db.factionrealm.characters) do
Zerotorescue@1 1007 temp[charName] = charName;
Zerotorescue@1 1008 end
Zerotorescue@1 1009
Zerotorescue@1 1010 -- We MUST close this pullout or we can get errors or even game client crashes once we click another group or close the config dialog!
Zerotorescue@1 1011 local count = AceGUI:GetNextWidgetNum("Dropdown-Pullout");
Zerotorescue@7 1012 for i = 1, count do
Zerotorescue@1 1013 if _G['AceGUI30Pullout' .. i] then
Zerotorescue@1 1014 _G['AceGUI30Pullout' .. i]:Hide();
Zerotorescue@1 1015 end
Zerotorescue@1 1016 end
Zerotorescue@1 1017
Zerotorescue@1 1018 return temp;
Zerotorescue@1 1019 end,
Zerotorescue@1 1020 get = GetMultiOption,
Zerotorescue@10 1021 confirm = true,
Zerotorescue@1 1022 dialogControl = "Dropdown", -- this is not standard, normal multiselect control gives us a list of all chars with toggle-boxes. UGLY! We want a multiselect-box instead.
Zerotorescue@1 1023 arg = "overrideTrackAtCharacters",
Zerotorescue@1 1024 },
Zerotorescue@0 1025 },
Zerotorescue@0 1026 },
Zerotorescue@0 1027 refill = {
Zerotorescue@0 1028 order = 20,
Zerotorescue@0 1029 type = "group",
Zerotorescue@0 1030 inline = true,
Zerotorescue@0 1031 name = "Replenishing stock",
Zerotorescue@0 1032 set = SetOption,
Zerotorescue@0 1033 get = GetOption,
Zerotorescue@0 1034 disabled = GetDisabled,
Zerotorescue@0 1035 args = {
Zerotorescue@0 1036 description = {
Zerotorescue@0 1037 order = 0,
Zerotorescue@0 1038 type = "description",
Zerotorescue@0 1039 name = function(info)
Zerotorescue@0 1040 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1041 local r = "Here you can specify the amount of items to which you wish to restock when you are collecting new items for the currently selected group. This may be higher than the minimum stock.\n\n";
Zerotorescue@0 1042
Zerotorescue@1 1043 r = r .. "When restocking the target amount is |cfffed000" .. addon:GetOptionByKey(groupName, "restockTarget") .. "|r of every item. Not queueing craftable items when only missing |cfffed000" .. floor( addon:GetOptionByKey(groupName, "minCraftingQueue") * addon:GetOptionByKey(groupName, "restockTarget") ) .. "|r (|cfffed000" .. ( addon:GetOptionByKey(groupName, "minCraftingQueue") * 100 ) .. "%|r) of the restock target.";
Zerotorescue@0 1044
Zerotorescue@0 1045 return r;
Zerotorescue@0 1046 end,
Zerotorescue@0 1047 },
Zerotorescue@0 1048 header = {
Zerotorescue@0 1049 order = 5,
Zerotorescue@0 1050 type = "header",
Zerotorescue@0 1051 name = "",
Zerotorescue@0 1052 },
Zerotorescue@0 1053 overrideRestockTarget = {
Zerotorescue@0 1054 order = 9,
Zerotorescue@0 1055 type = "toggle",
Zerotorescue@0 1056 name = "Override restock target",
Zerotorescue@0 1057 desc = "Allows you to override the restock target setting for this group.",
Zerotorescue@0 1058 arg = "restockTarget",
Zerotorescue@0 1059 },
Zerotorescue@0 1060 restockTarget = {
Zerotorescue@0 1061 order = 10,
Zerotorescue@0 1062 type = "range",
Zerotorescue@0 1063 min = 0,
Zerotorescue@0 1064 max = 100000,
Zerotorescue@0 1065 softMax = 1000,
Zerotorescue@0 1066 step = 1,
Zerotorescue@0 1067 name = "Restock target",
Zerotorescue@0 1068 desc = "You can manually enter a value between 1.000 and 100.000 in the edit box if the provided range is insufficient.",
Zerotorescue@0 1069 arg = "overrideRestockTarget",
Zerotorescue@0 1070 },
Zerotorescue@0 1071 overrideMinCraftingQueue = {
Zerotorescue@0 1072 order = 19,
Zerotorescue@0 1073 type = "toggle",
Zerotorescue@0 1074 name = "Override min queue",
Zerotorescue@0 1075 desc = "Allows you to override the minimum craftable items queue setting for this group.",
Zerotorescue@0 1076 arg = "minCraftingQueue",
Zerotorescue@0 1077 },
Zerotorescue@0 1078 minCraftingQueue = {
Zerotorescue@0 1079 order = 20,
Zerotorescue@0 1080 type = "range",
Zerotorescue@0 1081 min = 0,
Zerotorescue@0 1082 max = 1,
Zerotorescue@0 1083 step = 0.01,
Zerotorescue@0 1084 isPercent = true,
Zerotorescue@0 1085 name = "Don't queue if I only miss",
Zerotorescue@0 1086 desc = "Don't add a craftable item to the queue if I only miss this much or less of the restock target.\n\nExample: if your restock target is set to 60 and this is set to 5%, an item won't be queued unless you are missing more than 3 of it.",
Zerotorescue@0 1087 arg = "overrideMinCraftingQueue",
Zerotorescue@0 1088 },
Zerotorescue@1 1089 overrideBonusQueue = {
Zerotorescue@1 1090 order = 29,
Zerotorescue@1 1091 type = "toggle",
Zerotorescue@1 1092 name = "Override bonus queue",
Zerotorescue@1 1093 desc = "Allows you to override the bonus craftable items queue setting for this group.",
Zerotorescue@1 1094 arg = "bonusQueue",
Zerotorescue@1 1095 },
Zerotorescue@1 1096 bonusQueue = {
Zerotorescue@1 1097 order = 30,
Zerotorescue@1 1098 type = "range",
Zerotorescue@1 1099 min = 0,
Zerotorescue@1 1100 max = 10, -- 1000%
Zerotorescue@1 1101 step = 0.01, -- 1%
Zerotorescue@1 1102 isPercent = true,
Zerotorescue@1 1103 name = "Bonus queue",
Zerotorescue@1 1104 desc = "Get additional items when there are none left.\n\nExample: if your restock target is set to 60 and this is set to 10%, you will get 66 items instead of just 60 if you end up with none left while queueing.",
Zerotorescue@1 1105 arg = "overrideBonusQueue",
Zerotorescue@1 1106 },
Zerotorescue@1 1107 overridePriceThreshold = {
Zerotorescue@1 1108 order = 39,
Zerotorescue@1 1109 type = "toggle",
Zerotorescue@1 1110 name = "Override price threshold",
Zerotorescue@1 1111 desc = "Allows you to override the price threshold setting for this group.",
Zerotorescue@1 1112 arg = "priceThreshold",
Zerotorescue@1 1113 },
Zerotorescue@1 1114 priceThreshold = {
Zerotorescue@1 1115 order = 40,
Zerotorescue@1 1116 type = "input",
Zerotorescue@1 1117 name = "Price threshold",
Zerotorescue@1 1118 desc = "Only queue craftable items when they are worth at least this much according to your auction house addon.\n\nSet to 0 to ignore auction prices.",
Zerotorescue@1 1119 validate = function(info, value) return addon:ValidateReadableMoney(info, value); end,
Zerotorescue@1 1120 get = function(i) return addon:ReadableMoney(GetOption(i)); end,
Zerotorescue@1 1121 set = function(i, v) SetOption(i, addon:ReadableMoneyToCopper(v)); end,
Zerotorescue@1 1122 arg = "overridePriceThreshold",
Zerotorescue@1 1123 },
Zerotorescue@1 1124 overrideHideFromSummaryWhenBelowPriceThreshold = {
Zerotorescue@1 1125 order = 49,
Zerotorescue@1 1126 type = "toggle",
Zerotorescue@1 1127 name = "Override summary showing",
Zerotorescue@1 1128 desc = "Allows you to override if items in this group should be hidden from the summary while their value is below the price threshold.",
Zerotorescue@1 1129 arg = "hideFromSummaryWhenBelowPriceThreshold",
Zerotorescue@1 1130 },
Zerotorescue@1 1131 hideFromSummaryWhenBelowPriceThreshold = { -- I wish this var could be a little bit shorter...
Zerotorescue@1 1132 order = 50,
Zerotorescue@1 1133 type = "toggle",
Zerotorescue@1 1134 name = "Hide when below threshold",
Zerotorescue@1 1135 desc = "Hide items from the summary when their value is below the set price threshold.",
Zerotorescue@1 1136 arg = "overrideHideFromSummaryWhenBelowPriceThreshold",
Zerotorescue@1 1137 },
Zerotorescue@0 1138 },
Zerotorescue@0 1139 },
Zerotorescue@0 1140 },
Zerotorescue@0 1141 },
Zerotorescue@0 1142 group = {
Zerotorescue@0 1143 order = 20,
Zerotorescue@0 1144 type = "group",
Zerotorescue@0 1145 name = "Group Management",
Zerotorescue@0 1146 desc = "Rename, delete or export this group.",
Zerotorescue@0 1147 args = {
Zerotorescue@10 1148 actions = {
Zerotorescue@0 1149 order = 10,
Zerotorescue@0 1150 type = "group",
Zerotorescue@10 1151 name = "Actions",
Zerotorescue@0 1152 inline = true,
Zerotorescue@0 1153 args = {
Zerotorescue@0 1154 rename = {
Zerotorescue@0 1155 order = 10,
Zerotorescue@0 1156 type = "input",
Zerotorescue@10 1157 name = "Rename group - New name",
Zerotorescue@0 1158 desc = "Change the name of this group to something else. You can also use item links here as you wish.",
Zerotorescue@0 1159 validate = ValidateGroupName,
Zerotorescue@0 1160 set = function(info, value)
Zerotorescue@0 1161 local oldGroupName = groupIdToName[info[2]];
Zerotorescue@0 1162
Zerotorescue@0 1163 addon.db.global.groups[value] = CopyTable(addon.db.global.groups[oldGroupName]);
Zerotorescue@0 1164 addon.db.global.groups[oldGroupName] = nil;
Zerotorescue@0 1165
Zerotorescue@0 1166 groupIdToName[info[2]] = value;
Zerotorescue@0 1167 groupIdToName[value] = true;
Zerotorescue@0 1168 groupIdToName[oldGroupName] = nil;
Zerotorescue@0 1169
Zerotorescue@0 1170 addon:FillGroupOptions();
Zerotorescue@0 1171 end,
Zerotorescue@0 1172 get = function(info)
Zerotorescue@0 1173 return groupIdToName[info[2]];
Zerotorescue@0 1174 end,
Zerotorescue@0 1175 },
Zerotorescue@10 1176 duplicate = {
Zerotorescue@10 1177 order = 20,
Zerotorescue@10 1178 type = "input",
Zerotorescue@10 1179 name = "Duplicate group - New name",
Zerotorescue@10 1180 desc = "Duplicate this group. You can also use item links here as you wish.\n\nAll item data will be erased.",
Zerotorescue@10 1181 validate = ValidateGroupName,
Zerotorescue@10 1182 set = function(info, value)
Zerotorescue@10 1183 local oldGroupName = groupIdToName[info[2]];
Zerotorescue@10 1184
Zerotorescue@10 1185 addon.db.global.groups[value] = CopyTable(addon.db.global.groups[oldGroupName]);
Zerotorescue@10 1186
Zerotorescue@10 1187 -- Reset item data (duplicate items me no want)
Zerotorescue@10 1188 addon.db.global.groups[value].items = nil;
Zerotorescue@10 1189
Zerotorescue@10 1190 addon:FillGroupOptions();
Zerotorescue@10 1191 end,
Zerotorescue@10 1192 get = false,
Zerotorescue@10 1193 },
Zerotorescue@0 1194 delete = {
Zerotorescue@10 1195 order = 30,
Zerotorescue@0 1196 type = "execute",
Zerotorescue@0 1197 name = "Delete group",
Zerotorescue@0 1198 desc = "Delete the currently selected group.",
Zerotorescue@0 1199 confirm = true,
Zerotorescue@0 1200 confirmText = "Are you sure you wish to |cffff0000DELETE|r this group? This action is not reversable!",
Zerotorescue@0 1201 func = function(info)
Zerotorescue@0 1202 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1203
Zerotorescue@0 1204 addon.db.global.groups[groupName] = nil;
Zerotorescue@0 1205
Zerotorescue@0 1206 addon:FillGroupOptions();
Zerotorescue@0 1207 end,
Zerotorescue@0 1208 },
Zerotorescue@0 1209 },
Zerotorescue@0 1210 },
Zerotorescue@0 1211 export = {
Zerotorescue@10 1212 order = 40,
Zerotorescue@0 1213 type = "group",
Zerotorescue@0 1214 name = "Export",
Zerotorescue@0 1215 inline = true,
Zerotorescue@0 1216 args = {
Zerotorescue@0 1217 input = {
Zerotorescue@0 1218 order = 10,
Zerotorescue@0 1219 type = "input",
Zerotorescue@0 1220 multiline = true,
Zerotorescue@0 1221 name = "Group data",
Zerotorescue@0 1222 width = "full",
Zerotorescue@0 1223 desc = "Export the group data for the currently selected group. Press CTRL-A to select all and CTRL-C to copy the text.",
Zerotorescue@0 1224 set = false,
Zerotorescue@0 1225 get = function(info)
Zerotorescue@0 1226 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1227
Zerotorescue@0 1228 -- We want to include the group name, so we copy the table then set another value
Zerotorescue@0 1229 local temp = CopyTable(addon.db.global.groups[groupName]);
Zerotorescue@0 1230 temp.name = groupName;
Zerotorescue@9 1231 temp.trackAtCharacters = nil;
Zerotorescue@9 1232 temp.overrideTrackAtCharacters = nil;
Zerotorescue@0 1233
Zerotorescue@0 1234 if not AceSerializer then
Zerotorescue@0 1235 AceSerializer = LibStub("AceSerializer-3.0");
Zerotorescue@0 1236 end
Zerotorescue@0 1237
Zerotorescue@0 1238 return AceSerializer:Serialize(temp);
Zerotorescue@0 1239 end,
Zerotorescue@0 1240 },
Zerotorescue@0 1241 },
Zerotorescue@0 1242 },
Zerotorescue@0 1243 },
Zerotorescue@0 1244 },
Zerotorescue@0 1245 add = {
Zerotorescue@0 1246 order = 30,
Zerotorescue@0 1247 type = "group",
Zerotorescue@0 1248 name = "Add items",
Zerotorescue@0 1249 args = {
Zerotorescue@0 1250 singleAdd = {
Zerotorescue@0 1251 order = 10,
Zerotorescue@0 1252 type = "group",
Zerotorescue@0 1253 inline = true,
Zerotorescue@0 1254 name = "Add items",
Zerotorescue@0 1255 args = {
Zerotorescue@0 1256 help = {
Zerotorescue@0 1257 order = 10,
Zerotorescue@0 1258 type = "description",
Zerotorescue@0 1259 name = "You can add a single item to this group at a time by pasting the item-id or an item-link in the field to the left or you can also import multiple items at once by pasting exported item data in the field to the right. Scroll further down to add items based on your inventory contents.",
Zerotorescue@0 1260 },
Zerotorescue@0 1261 itemLink = {
Zerotorescue@0 1262 order = 20,
Zerotorescue@0 1263 type = "input",
Zerotorescue@0 1264 name = "Single item add (item-link or item-id)",
Zerotorescue@0 1265 desc = "Shift-click an item-link or enter an item-id to add the related item to this group. You can only add one item link or item id at a time.",
Zerotorescue@0 1266 validate = function(info, value)
Zerotorescue@0 1267 -- If the value is empty we'll allow passing to clear the carret
Zerotorescue@0 1268 if value == "" then return true; end
Zerotorescue@0 1269
Zerotorescue@0 1270 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1271
Zerotorescue@0 1272 local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or ""));
Zerotorescue@0 1273
Zerotorescue@0 1274 if not itemId then
Zerotorescue@0 1275 return "This is not a valid item link.";
Zerotorescue@0 1276 elseif InGroup(itemId) then
Zerotorescue@0 1277 return ("This item is already in the group \"%s\"."):format(InGroup(itemId));
Zerotorescue@0 1278 end
Zerotorescue@0 1279
Zerotorescue@0 1280 return true;
Zerotorescue@0 1281 end,
Zerotorescue@0 1282 set = function(info, value)
Zerotorescue@0 1283 if value and value ~= "" then
Zerotorescue@0 1284 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1285
Zerotorescue@0 1286 local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or ""));
Zerotorescue@0 1287
Zerotorescue@0 1288 AddToGroup(groupName, itemId);
Zerotorescue@0 1289
Zerotorescue@0 1290 print(("Added %s"):format(select(2, GetItemInfo(itemId)) or ("Unknown (#%d)"):format(itemId)));
Zerotorescue@0 1291 end
Zerotorescue@0 1292 end,
Zerotorescue@0 1293 get = false,
Zerotorescue@0 1294 },
Zerotorescue@0 1295 import = {
Zerotorescue@0 1296 order = 40,
Zerotorescue@0 1297 type = "input",
Zerotorescue@0 1298 name = "Import item data",
Zerotorescue@0 1299 desc = "Import item data from an exported item data-string. Any items already grouped will be skipped.",
Zerotorescue@0 1300 set = function(info, value)
Zerotorescue@0 1301 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1302
Zerotorescue@0 1303 local allItemIds = { string.split(";", value or "") };
Zerotorescue@0 1304
Zerotorescue@0 1305 for _, value in pairs(allItemIds) do
Zerotorescue@0 1306 local itemId = tonumber(value);
Zerotorescue@0 1307
Zerotorescue@0 1308 if not itemId then
Zerotorescue@0 1309 print(("\"%s\" is not a number."):format(value));
Zerotorescue@0 1310 elseif InGroup(itemId) then
Zerotorescue@0 1311 print(("Skipping %s (#%d) as it is already in the group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId)));
Zerotorescue@0 1312 else
Zerotorescue@0 1313 AddToGroup(groupName, itemId);
Zerotorescue@0 1314 end
Zerotorescue@0 1315 end
Zerotorescue@0 1316 end,
Zerotorescue@0 1317 get = false,
Zerotorescue@0 1318 },
Zerotorescue@0 1319 },
Zerotorescue@0 1320 },
Zerotorescue@0 1321 massAdd = {
Zerotorescue@0 1322 order = 20,
Zerotorescue@0 1323 type = "group",
Zerotorescue@0 1324 inline = true,
Zerotorescue@0 1325 name = "Mass add",
Zerotorescue@0 1326 args = {
Zerotorescue@0 1327 help = {
Zerotorescue@0 1328 order = 10,
Zerotorescue@0 1329 type = "description",
Zerotorescue@0 1330 name = "Click the items you wish to add to this group or add multiple of these items at once by providing a name filter in the field below.",
Zerotorescue@0 1331 },
Zerotorescue@0 1332 massAdd = {
Zerotorescue@0 1333 order = 20,
Zerotorescue@0 1334 type = "input",
Zerotorescue@0 1335 name = "Add all items matching...",
Zerotorescue@0 1336 desc = "Add every item in your inventory matching the name entered in this field. If you enter \"Glyph\" as a filter, any items in your inventory containing this in their name will be added to this group.",
Zerotorescue@0 1337 --set = massAddItems,
Zerotorescue@0 1338 get = false,
Zerotorescue@0 1339 },
Zerotorescue@0 1340 },
Zerotorescue@0 1341 },
Zerotorescue@0 1342 list = {
Zerotorescue@0 1343 order = 30,
Zerotorescue@0 1344 type = "group",
Zerotorescue@0 1345 inline = true,
Zerotorescue@0 1346 name = "Item list",
Zerotorescue@0 1347 hidden = UpdateAddItemList,
Zerotorescue@0 1348 args = {
Zerotorescue@0 1349
Zerotorescue@0 1350 },
Zerotorescue@0 1351 },
Zerotorescue@0 1352 },
Zerotorescue@0 1353 },
Zerotorescue@0 1354 remove = {
Zerotorescue@0 1355 order = 40,
Zerotorescue@0 1356 type = "group",
Zerotorescue@0 1357 name = "Current items",
Zerotorescue@0 1358 args = {
Zerotorescue@0 1359 help = {
Zerotorescue@0 1360 order = 10,
Zerotorescue@0 1361 type = "group",
Zerotorescue@0 1362 inline = true,
Zerotorescue@0 1363 name = "Help",
Zerotorescue@0 1364 hidden = false,
Zerotorescue@0 1365 args = {
Zerotorescue@0 1366 help = {
Zerotorescue@0 1367 order = 10,
Zerotorescue@0 1368 type = "description",
Zerotorescue@0 1369 name = "Click the items you wish to remove from this group.",
Zerotorescue@0 1370 },
Zerotorescue@0 1371 },
Zerotorescue@0 1372 },
Zerotorescue@0 1373 list = {
Zerotorescue@0 1374 order = 20,
Zerotorescue@0 1375 type = "group",
Zerotorescue@0 1376 inline = true,
Zerotorescue@0 1377 name = "Item list",
Zerotorescue@0 1378 hidden = UpdateRemoveItemList,
Zerotorescue@0 1379 args = {
Zerotorescue@0 1380
Zerotorescue@0 1381 },
Zerotorescue@0 1382 },
Zerotorescue@0 1383 export = {
Zerotorescue@0 1384 order = 30,
Zerotorescue@0 1385 type = "group",
Zerotorescue@0 1386 name = "Export",
Zerotorescue@0 1387 inline = true,
Zerotorescue@0 1388 args = {
Zerotorescue@0 1389 input = {
Zerotorescue@0 1390 order = 10,
Zerotorescue@0 1391 type = "input",
Zerotorescue@0 1392 name = "Item data",
Zerotorescue@0 1393 width = "full",
Zerotorescue@0 1394 desc = "Export the item data for the currently selected group. Press CTRL-A to select all and CTRL-C to copy the text.",
Zerotorescue@0 1395 set = false,
Zerotorescue@0 1396 get = function(info)
Zerotorescue@0 1397 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1398
Zerotorescue@0 1399 local combinedItemIds;
Zerotorescue@0 1400 -- Parse items in group and show these
Zerotorescue@0 1401 for itemId, _ in pairs(addon.db.global.groups[groupName].items) do
Zerotorescue@0 1402 if not combinedItemIds then
Zerotorescue@0 1403 combinedItemIds = tostring(itemId);
Zerotorescue@0 1404 else
Zerotorescue@0 1405 combinedItemIds = combinedItemIds .. (";%d"):format(itemId);
Zerotorescue@0 1406 end
Zerotorescue@0 1407 end
Zerotorescue@0 1408
Zerotorescue@0 1409 return combinedItemIds; -- We don't serialize this because we actually DO want people to be able to manually modify it - besides, parsing it isn't going to be hard
Zerotorescue@0 1410 end,
Zerotorescue@0 1411 },
Zerotorescue@0 1412 },
Zerotorescue@0 1413 },
Zerotorescue@0 1414 },
Zerotorescue@0 1415 },
Zerotorescue@0 1416 },
Zerotorescue@0 1417 };
Zerotorescue@0 1418
Zerotorescue@0 1419 function addon:MakeGroupOptions()
Zerotorescue@0 1420 options.args.groups = {
Zerotorescue@0 1421 order = 1100,
Zerotorescue@0 1422 type = "group",
Zerotorescue@0 1423 name = "Groups",
Zerotorescue@0 1424 desc = "Change a group.",
Zerotorescue@0 1425 args = {
Zerotorescue@0 1426 create = {
Zerotorescue@0 1427 order = 10,
Zerotorescue@0 1428 type = "group",
Zerotorescue@0 1429 inline = true,
Zerotorescue@0 1430 name = "Create a brand new group",
Zerotorescue@0 1431 args = {
Zerotorescue@0 1432 name = {
Zerotorescue@0 1433 order = 10,
Zerotorescue@0 1434 type = "input",
Zerotorescue@0 1435 name = "Group name",
Zerotorescue@0 1436 desc = "The name of the group. You can also use item links as you wish.",
Zerotorescue@0 1437 validate = ValidateGroupName,
Zerotorescue@0 1438 set = function(_, value)
Zerotorescue@0 1439 self.db.global.groups[value] = {};
Zerotorescue@0 1440
Zerotorescue@0 1441 addon:FillGroupOptions();
Zerotorescue@0 1442 end,
Zerotorescue@0 1443 get = false,
Zerotorescue@0 1444 width = "double",
Zerotorescue@0 1445 },
Zerotorescue@0 1446 },
Zerotorescue@0 1447 },
Zerotorescue@0 1448 import = {
Zerotorescue@0 1449 order = 20,
Zerotorescue@0 1450 type = "group",
Zerotorescue@0 1451 inline = true,
Zerotorescue@0 1452 name = "Import a group",
Zerotorescue@0 1453 args = {
Zerotorescue@0 1454 input = {
Zerotorescue@0 1455 order = 10,
Zerotorescue@0 1456 type = "input",
Zerotorescue@0 1457 multiline = true,
Zerotorescue@0 1458 name = "Group data",
Zerotorescue@0 1459 desc = "Paste the group data as provided by a group export. If you are trying to import multiple groups at the same time, make sure to use newlines to seperate them.",
Zerotorescue@0 1460 set = function(info, value)
Zerotorescue@9 1461 local data = { string.split("\n", value or "") };
Zerotorescue@0 1462
Zerotorescue@9 1463 for _, current in pairs(data) do
Zerotorescue@0 1464 if not AceSerializer then
Zerotorescue@0 1465 AceSerializer = LibStub("AceSerializer-3.0");
Zerotorescue@0 1466 end
Zerotorescue@0 1467
Zerotorescue@0 1468 local result, temp = AceSerializer:Deserialize(current);
Zerotorescue@0 1469
Zerotorescue@0 1470 if not temp.name then
Zerotorescue@0 1471 print("|cffff0000The provided data is not supported.|r");
Zerotorescue@10 1472 elseif ValidateGroupName(nil, temp.name) ~= true then
Zerotorescue@10 1473 print(("|cffff0000Aborting: A group named \"%s\" already exists.|r"):format(temp.name));
Zerotorescue@0 1474 else
Zerotorescue@10 1475 local name = temp.name;
Zerotorescue@0 1476 temp.name = nil;
Zerotorescue@9 1477 print(("Importing %s..."):format(name));
Zerotorescue@10 1478
Zerotorescue@10 1479 -- Remove items that are already in another group
Zerotorescue@10 1480 for value, _ in pairs(temp.items) do
Zerotorescue@10 1481 local itemId = tonumber(itemid);
Zerotorescue@10 1482
Zerotorescue@10 1483 if not itemId then
Zerotorescue@10 1484 print(("\"%s\" is not a number."):format(value));
Zerotorescue@10 1485 temp.items[value] = nil;
Zerotorescue@10 1486 elseif InGroup(itemId) then
Zerotorescue@10 1487 print(("Skipping %s (#%d) as it is already in the group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId)));
Zerotorescue@10 1488 temp.items[value] = nil;
Zerotorescue@10 1489 else
Zerotorescue@10 1490 -- Ensure the keys are numeric
Zerotorescue@10 1491 temp.items[value] = nil;
Zerotorescue@10 1492 temp.items[itemId] = true;
Zerotorescue@10 1493 end
Zerotorescue@10 1494 end
Zerotorescue@10 1495
Zerotorescue@10 1496 -- Ensure this data isn't received (this would be buggy as exports from other accounts won't know what to do with this)
Zerotorescue@10 1497 temp.trackAtCharacters = nil;
Zerotorescue@10 1498 temp.overrideTrackAtCharacters = nil;
Zerotorescue@10 1499
Zerotorescue@10 1500 self.db.global.groups[name] = temp;
Zerotorescue@0 1501 end
Zerotorescue@0 1502 end
Zerotorescue@10 1503
Zerotorescue@10 1504 self:FillGroupOptions();
Zerotorescue@0 1505 end,
Zerotorescue@0 1506 get = false,
Zerotorescue@0 1507 width = "full",
Zerotorescue@0 1508 },
Zerotorescue@0 1509 },
Zerotorescue@0 1510 },
Zerotorescue@0 1511 },
Zerotorescue@0 1512 };
Zerotorescue@0 1513 end
Zerotorescue@0 1514
Zerotorescue@0 1515 function addon:FillGroupOptions()
Zerotorescue@0 1516 for id, name in pairs(groupIdToName) do
Zerotorescue@0 1517 if type(name) == "string" and not self.db.global.groups[name] then
Zerotorescue@0 1518 options.args.groups.args[id] = nil;
Zerotorescue@0 1519 groupIdToName[id] = nil;
Zerotorescue@0 1520 groupIdToName[name] = nil;
Zerotorescue@0 1521 end
Zerotorescue@0 1522 end
Zerotorescue@0 1523
Zerotorescue@0 1524 for name, values in pairs(self.db.global.groups) do
Zerotorescue@0 1525 if not groupIdToName[name] then
Zerotorescue@0 1526 options.args.groups.args[tostring(count)] = CopyTable(defaultGroup);
Zerotorescue@0 1527
Zerotorescue@0 1528 groupIdToName[tostring(count)] = name;
Zerotorescue@0 1529 groupIdToName[name] = true;
Zerotorescue@0 1530
Zerotorescue@0 1531 count = ( count + 1 );
Zerotorescue@0 1532 end
Zerotorescue@0 1533 end
Zerotorescue@0 1534 end
Zerotorescue@0 1535
Zerotorescue@0 1536 function addon:GetItemCount(itemId)
Zerotorescue@0 1537 return Altoholic:GetItemCount(itemId);
Zerotorescue@0 1538 end
Zerotorescue@0 1539
Zerotorescue@1 1540 function addon:GetAuctionValue(link)
Zerotorescue@1 1541 if GetAuctionBuyout then
Zerotorescue@1 1542 -- Auctionator support
Zerotorescue@1 1543
Zerotorescue@1 1544 local lowBuy = GetAuctionBuyout(link);
Zerotorescue@1 1545
Zerotorescue@1 1546 if lowBuy == nil then
Zerotorescue@1 1547 -- No auctions up at this time
Zerotorescue@1 1548 return -1;
Zerotorescue@1 1549 end
Zerotorescue@1 1550
Zerotorescue@1 1551 return lowBuy;
Zerotorescue@1 1552 elseif AucAdvanced ~= nil and AucAdvanced.Modules.Util.SimpleAuction ~= nil and AucAdvanced.Modules.Util.SimpleAuction.Private.GetItems ~= nil then
Zerotorescue@1 1553 -- Auctioneer support
Zerotorescue@1 1554
Zerotorescue@1 1555 local imgSeen, _, _, _, _, lowBuy, _, _ = AucAdvanced.Modules.Util.SimpleAuction.Private.GetItems(link);
Zerotorescue@1 1556 --local imgseen, image, matchBid, matchBuy, lowBid, lowBuy, aveBuy, aSeen
Zerotorescue@1 1557
Zerotorescue@1 1558 if imgSeen <= 0 then
Zerotorescue@1 1559 -- No auctions up at this time
Zerotorescue@1 1560 return -1;
Zerotorescue@1 1561 end
Zerotorescue@1 1562
Zerotorescue@1 1563 return lowBuy;
Zerotorescue@1 1564 end
Zerotorescue@7 1565
Zerotorescue@7 1566 return -2;
Zerotorescue@1 1567 end
Zerotorescue@1 1568
Zerotorescue@0 1569
Zerotorescue@0 1570
Zerotorescue@0 1571
Zerotorescue@0 1572 function addon:Debug(t)
Zerotorescue@0 1573 if not self.debugChannel and self.debugChannel ~= false then
Zerotorescue@0 1574 -- We want to check just once, so if you add a debug channel later just do a /reload (registering an event for this is wasted resources)
Zerotorescue@0 1575 self.debugChannel = false;
Zerotorescue@0 1576
Zerotorescue@0 1577 for i = 1, NUM_CHAT_WINDOWS do
Zerotorescue@0 1578 local name = GetChatWindowInfo(i);
Zerotorescue@0 1579
Zerotorescue@0 1580 if name:upper() == "DEBUG" then
Zerotorescue@0 1581 self.debugChannel = _G["ChatFrame" .. i];
Zerotorescue@0 1582 end
Zerotorescue@0 1583 end
Zerotorescue@0 1584 end
Zerotorescue@0 1585
Zerotorescue@0 1586 if self.debugChannel then
Zerotorescue@0 1587 self.debugChannel:AddMessage(t);
Zerotorescue@0 1588 end
Zerotorescue@0 1589 end