annotate Core.lua @ 9:3bac0bdd59e2

Close the summary frame when opening the config. Remove ?track at? data when exporting/importing a group. Don?t add items when importing a group that are already inside a group.
author Zerotorescue
date Sun, 10 Oct 2010 04:37:21 +0200
parents 1a815139e4c3
children c4d0e5d47e10
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@1 530 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 531 },
Zerotorescue@0 532 },
Zerotorescue@0 533 },
Zerotorescue@0 534 refill = {
Zerotorescue@0 535 order = 20,
Zerotorescue@0 536 type = "group",
Zerotorescue@0 537 inline = true,
Zerotorescue@0 538 name = "Replenishing stock",
Zerotorescue@0 539 args = {
Zerotorescue@0 540 description = {
Zerotorescue@0 541 order = 0,
Zerotorescue@0 542 type = "description",
Zerotorescue@0 543 name = function()
Zerotorescue@0 544 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 545
Zerotorescue@0 546 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 547
Zerotorescue@0 548 return r;
Zerotorescue@0 549 end,
Zerotorescue@0 550 },
Zerotorescue@0 551 header = {
Zerotorescue@0 552 order = 5,
Zerotorescue@0 553 type = "header",
Zerotorescue@0 554 name = "",
Zerotorescue@0 555 },
Zerotorescue@0 556 restockTarget = {
Zerotorescue@0 557 order = 10,
Zerotorescue@0 558 type = "range",
Zerotorescue@0 559 min = 0,
Zerotorescue@0 560 max = 100000,
Zerotorescue@0 561 softMax = 1000,
Zerotorescue@0 562 step = 1,
Zerotorescue@0 563 name = "Restock target",
Zerotorescue@0 564 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 565 get = function() return self.db.global.defaults.restockTarget; end,
Zerotorescue@0 566 set = function(i, v) self.db.global.defaults.restockTarget = v; end,
Zerotorescue@0 567 },
Zerotorescue@0 568 minCraftingQueue = {
Zerotorescue@0 569 order = 20,
Zerotorescue@0 570 type = "range",
Zerotorescue@0 571 min = 0,
Zerotorescue@0 572 max = 1,
Zerotorescue@0 573 step = 0.01, -- 1%
Zerotorescue@0 574 isPercent = true,
Zerotorescue@0 575 name = "Don't queue if I only miss",
Zerotorescue@0 576 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 577 get = function() return self.db.global.defaults.minCraftingQueue; end,
Zerotorescue@0 578 set = function(i, v) self.db.global.defaults.minCraftingQueue = v; end,
Zerotorescue@0 579 },
Zerotorescue@0 580 bonusQueue = {
Zerotorescue@0 581 order = 30,
Zerotorescue@0 582 type = "range",
Zerotorescue@0 583 min = 0,
Zerotorescue@0 584 max = 10, -- 1000%
Zerotorescue@0 585 step = 0.01, -- 1%
Zerotorescue@0 586 isPercent = true,
Zerotorescue@0 587 name = "Bonus queue",
Zerotorescue@1 588 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 589 get = function() return self.db.global.defaults.bonusQueue; end,
Zerotorescue@0 590 set = function(i, v) self.db.global.defaults.bonusQueue = v; end,
Zerotorescue@0 591 },
Zerotorescue@0 592 priceThreshold = {
Zerotorescue@0 593 order = 40,
Zerotorescue@0 594 type = "input",
Zerotorescue@0 595 name = "Price threshold",
Zerotorescue@1 596 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 597 validate = function(info, value) return self:ValidateReadableMoney(info, value); end,
Zerotorescue@1 598 get = function() return self:ReadableMoney(self.db.global.defaults.priceThreshold); end,
Zerotorescue@1 599 set = function(i, v) self.db.global.defaults.priceThreshold = self:ReadableMoneyToCopper(v); end,
Zerotorescue@0 600 },
Zerotorescue@1 601 hideFromSummaryWhenBelowPriceThreshold = { -- I wish this var could be a little bit shorter...
Zerotorescue@0 602 order = 50,
Zerotorescue@0 603 type = "toggle",
Zerotorescue@1 604 name = "Hide when below threshold",
Zerotorescue@0 605 desc = "Hide items from the summary when their value is below the set price threshold.",
Zerotorescue@1 606 get = function() return self.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold; end,
Zerotorescue@1 607 set = function(i, v) self.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold = v; end,
Zerotorescue@0 608 },
Zerotorescue@0 609 },
Zerotorescue@0 610 },
Zerotorescue@0 611 colorCodes = {
Zerotorescue@0 612 order = 30,
Zerotorescue@0 613 type = "group",
Zerotorescue@0 614 inline = true,
Zerotorescue@0 615 name = "Color codes",
Zerotorescue@0 616 args = {
Zerotorescue@0 617 description = {
Zerotorescue@0 618 order = 0,
Zerotorescue@0 619 type = "description",
Zerotorescue@0 620 name = "Change the color code thresholds based on the current stock remaining of the required minimum stock.",
Zerotorescue@0 621 },
Zerotorescue@0 622 header = {
Zerotorescue@0 623 order = 5,
Zerotorescue@0 624 type = "header",
Zerotorescue@0 625 name = "",
Zerotorescue@0 626 },
Zerotorescue@0 627 green = {
Zerotorescue@0 628 order = 10,
Zerotorescue@0 629 type = "range",
Zerotorescue@0 630 min = 0,
Zerotorescue@0 631 max = 1,
Zerotorescue@0 632 step = 0.01,
Zerotorescue@0 633 isPercent = true,
Zerotorescue@0 634 name = "|cff00ff00Green|r",
Zerotorescue@0 635 desc = "Show quantity in green when at least this much of the minimum stock is available.",
Zerotorescue@0 636 get = function() return self.db.global.defaults.colors.green; end,
Zerotorescue@0 637 set = function(i, v) self.db.global.defaults.colors.green = v; end,
Zerotorescue@0 638 },
Zerotorescue@0 639 yellow = {
Zerotorescue@0 640 order = 20,
Zerotorescue@0 641 type = "range",
Zerotorescue@0 642 min = 0,
Zerotorescue@0 643 max = 1,
Zerotorescue@0 644 step = 0.01,
Zerotorescue@0 645 isPercent = true,
Zerotorescue@0 646 name = "|cffffff00Yellow|r",
Zerotorescue@0 647 desc = "Show quantity in yellow when at least this much of the minimum stock is available.",
Zerotorescue@0 648 get = function() return self.db.global.defaults.colors.yellow; end,
Zerotorescue@0 649 set = function(i, v) self.db.global.defaults.colors.yellow = v; end,
Zerotorescue@0 650 },
Zerotorescue@0 651 orange = {
Zerotorescue@0 652 order = 30,
Zerotorescue@0 653 type = "range",
Zerotorescue@0 654 min = 0,
Zerotorescue@0 655 max = 1,
Zerotorescue@0 656 step = 0.01,
Zerotorescue@0 657 isPercent = true,
Zerotorescue@0 658 name = "|cffff9933Orange|r",
Zerotorescue@0 659 desc = "Show quantity in orange when at least this much of the minimum stock is available.",
Zerotorescue@0 660 get = function() return self.db.global.defaults.colors.orange; end,
Zerotorescue@0 661 set = function(i, v) self.db.global.defaults.colors.orange = v; end,
Zerotorescue@0 662 },
Zerotorescue@0 663 red = {
Zerotorescue@0 664 order = 40,
Zerotorescue@0 665 type = "range",
Zerotorescue@0 666 min = 0,
Zerotorescue@0 667 max = 1,
Zerotorescue@0 668 step = 0.01,
Zerotorescue@0 669 isPercent = true,
Zerotorescue@0 670 name = "|cffff0000Red|r",
Zerotorescue@0 671 desc = "Show quantity in red when at least this much of the minimum stock is available.",
Zerotorescue@0 672 get = function() return self.db.global.defaults.colors.red; end,
Zerotorescue@0 673 set = function(i, v) self.db.global.defaults.colors.red = v; end,
Zerotorescue@0 674 },
Zerotorescue@0 675 },
Zerotorescue@0 676 },
Zerotorescue@0 677 },
Zerotorescue@0 678 };
Zerotorescue@0 679 end
Zerotorescue@0 680
Zerotorescue@0 681 local count = 0;
Zerotorescue@0 682 local temp = {};
Zerotorescue@0 683
Zerotorescue@1 684 local function SetOption(info, value, multiSelectEnabled)
Zerotorescue@0 685 local groupName = groupIdToName[info[2]];
Zerotorescue@0 686 local optionName = info[#info];
Zerotorescue@0 687
Zerotorescue@0 688 -- No need to store a setting if it's disabled (false)
Zerotorescue@0 689 if not value and info.arg and not info.arg:find("override") then
Zerotorescue@0 690 value = nil;
Zerotorescue@0 691
Zerotorescue@0 692 -- If this is an override toggler then also set the related field to nil
Zerotorescue@0 693 addon.db.global.groups[groupName][info.arg] = nil;
Zerotorescue@0 694 end
Zerotorescue@0 695
Zerotorescue@1 696 if multiSelectEnabled ~= nil then
Zerotorescue@1 697 -- 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 698 if not addon.db.global.groups[groupName][optionName] then
Zerotorescue@1 699 addon.db.global.groups[groupName][optionName] = {};
Zerotorescue@1 700 end
Zerotorescue@1 701
Zerotorescue@1 702 addon.db.global.groups[groupName][optionName][value] = multiSelectEnabled or nil;
Zerotorescue@1 703 else
Zerotorescue@1 704 addon.db.global.groups[groupName][optionName] = value;
Zerotorescue@1 705 end
Zerotorescue@0 706 end
Zerotorescue@0 707
Zerotorescue@1 708 function addon:GetOptionByKey(groupName, optionName, noDefault)
Zerotorescue@0 709 if addon.db.global.groups[groupName][optionName] ~= nil then
Zerotorescue@0 710 return addon.db.global.groups[groupName][optionName];
Zerotorescue@0 711 elseif addon.db.global.defaults[optionName] and not noDefault then
Zerotorescue@0 712 return addon.db.global.defaults[optionName];
Zerotorescue@0 713 else
Zerotorescue@0 714 return nil;
Zerotorescue@0 715 end
Zerotorescue@0 716 end
Zerotorescue@0 717
Zerotorescue@0 718 local function GetOption(info)
Zerotorescue@0 719 local groupName = groupIdToName[info[2]];
Zerotorescue@0 720 local optionName = info[#info];
Zerotorescue@0 721
Zerotorescue@1 722 return addon:GetOptionByKey(groupName, optionName);
Zerotorescue@1 723 end
Zerotorescue@1 724
Zerotorescue@1 725 local function GetMultiOption(info, value)
Zerotorescue@1 726 local groupName = groupIdToName[info[2]];
Zerotorescue@1 727 local optionName = info[#info];
Zerotorescue@1 728
Zerotorescue@1 729 if addon.db.global.groups[groupName][optionName] ~= nil then
Zerotorescue@1 730 return addon.db.global.groups[groupName][optionName][value];
Zerotorescue@1 731 elseif addon.db.global.defaults[optionName] then
Zerotorescue@1 732 return addon.db.global.defaults[optionName][value];
Zerotorescue@1 733 else
Zerotorescue@1 734 return nil;
Zerotorescue@1 735 end
Zerotorescue@0 736 end
Zerotorescue@0 737
Zerotorescue@0 738 local function GetDisabled(info)
Zerotorescue@0 739 if not info.arg or not info.arg:find("override") then
Zerotorescue@0 740 return false;
Zerotorescue@0 741 end
Zerotorescue@0 742
Zerotorescue@0 743 local groupName = groupIdToName[info[2]];
Zerotorescue@0 744 local optionName = info[#info];
Zerotorescue@0 745
Zerotorescue@1 746 return (addon:GetOptionByKey(groupName, info.arg, true) == nil);
Zerotorescue@0 747 end
Zerotorescue@0 748
Zerotorescue@0 749 local function ValidateGroupName(_, value)
Zerotorescue@0 750 value = string.lower(string.trim(value or ""));
Zerotorescue@0 751
Zerotorescue@0 752 for name, _ in pairs(addon.db.global.groups) do
Zerotorescue@0 753 if string.lower(name) == value then
Zerotorescue@0 754 return ("A group named \"%s\" already exists."):format(name);
Zerotorescue@0 755 end
Zerotorescue@0 756 end
Zerotorescue@0 757
Zerotorescue@0 758 return true;
Zerotorescue@0 759 end
Zerotorescue@0 760
Zerotorescue@0 761 local function InGroup(itemId)
Zerotorescue@0 762 -- Go through all groups to see if this item is already somewhere
Zerotorescue@0 763 for groupName, values in pairs(addon.db.global.groups) do
Zerotorescue@0 764 if values.items and values.items[itemId] then
Zerotorescue@0 765 return groupName;
Zerotorescue@0 766 end
Zerotorescue@0 767 end
Zerotorescue@0 768
Zerotorescue@0 769 return;
Zerotorescue@0 770 end
Zerotorescue@0 771
Zerotorescue@0 772 local function AddToGroup(groupName, itemId)
Zerotorescue@0 773 if InGroup(itemId) then
Zerotorescue@0 774 return false;
Zerotorescue@0 775 end
Zerotorescue@0 776
Zerotorescue@0 777 if not addon.db.global.groups[groupName].items then
Zerotorescue@0 778 addon.db.global.groups[groupName].items = {};
Zerotorescue@0 779 end
Zerotorescue@0 780
Zerotorescue@0 781 -- Set this item
Zerotorescue@0 782 addon.db.global.groups[groupName].items[itemId] = true;
Zerotorescue@0 783
Zerotorescue@0 784 -- Now rebuild the list
Zerotorescue@0 785 AceConfigRegistry:NotifyChange("InventoryOptions");
Zerotorescue@0 786
Zerotorescue@0 787 return true;
Zerotorescue@0 788 end
Zerotorescue@0 789
Zerotorescue@0 790 local tblAddItemTemplate = {
Zerotorescue@0 791 order = 0,
Zerotorescue@0 792 type = "input",
Zerotorescue@0 793 name = function(info)
Zerotorescue@0 794 local itemName, _, itemRarity = GetItemInfo(info[#info]);
Zerotorescue@0 795 return tostring( 7 - (itemRarity or 0) ) .. (itemName or "");
Zerotorescue@0 796 end,
Zerotorescue@0 797 get = function(info)
Zerotorescue@0 798 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 799 end,
Zerotorescue@1 800 set = function(groupId, itemId)
Zerotorescue@0 801 -- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info.
Zerotorescue@0 802
Zerotorescue@1 803 if itemId then
Zerotorescue@1 804 local groupName = groupIdToName[groupId];
Zerotorescue@0 805
Zerotorescue@1 806 if not AddToGroup(groupName, itemId) then
Zerotorescue@1 807 print("|cffff0000Couldn't add the item with itemId (" .. itemId .. ") because it is already in a group.|r");
Zerotorescue@0 808 end
Zerotorescue@0 809 end
Zerotorescue@0 810 end,
Zerotorescue@0 811 width = "double",
Zerotorescue@1 812 dialogControl = "ConfigItemLinkButton",
Zerotorescue@0 813 };
Zerotorescue@0 814
Zerotorescue@0 815 local tblRemoveItemTemplate = {
Zerotorescue@0 816 order = 0,
Zerotorescue@0 817 type = "input",
Zerotorescue@0 818 name = function(info)
Zerotorescue@0 819 local itemName, _, itemRarity = GetItemInfo(info[#info]);
Zerotorescue@0 820 return tostring( 7 - (itemRarity or 0) ) .. (itemName or "");
Zerotorescue@0 821 end,
Zerotorescue@0 822 get = function(info)
Zerotorescue@0 823 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 824 end,
Zerotorescue@1 825 set = function(groupId, itemId)
Zerotorescue@0 826 -- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info.
Zerotorescue@0 827
Zerotorescue@1 828 if itemId then
Zerotorescue@1 829 local groupName = groupIdToName[groupId];
Zerotorescue@0 830
Zerotorescue@0 831 -- Unset this item
Zerotorescue@1 832 addon.db.global.groups[groupName].items[itemId] = nil;
Zerotorescue@0 833
Zerotorescue@0 834 -- Now rebuild the list
Zerotorescue@0 835 AceConfigRegistry:NotifyChange("InventoryOptions");
Zerotorescue@0 836 end
Zerotorescue@0 837 end,
Zerotorescue@0 838 width = "double",
Zerotorescue@1 839 dialogControl = "ConfigItemLinkButton",
Zerotorescue@0 840 };
Zerotorescue@0 841
Zerotorescue@0 842 local function UpdateAddItemList(info)
Zerotorescue@0 843 local groupName = groupIdToName[info[2]];
Zerotorescue@0 844
Zerotorescue@0 845 if not addon.db.global.groups[groupName].items then
Zerotorescue@0 846 addon.db.global.groups[groupName].items = {};
Zerotorescue@0 847 end
Zerotorescue@0 848
Zerotorescue@0 849 -- Merge all items from all groups together
Zerotorescue@0 850 local items = {};
Zerotorescue@0 851 for groupName, values in pairs(addon.db.global.groups) do
Zerotorescue@0 852 if values.items then
Zerotorescue@0 853 for itemId, _ in pairs(values.items) do
Zerotorescue@0 854 items[itemId] = true;
Zerotorescue@0 855 end
Zerotorescue@0 856 end
Zerotorescue@0 857 end
Zerotorescue@0 858
Zerotorescue@0 859 local ref = options.args.groups.args[info[2]].args.add.args.list.args;
Zerotorescue@0 860
Zerotorescue@0 861 -- Parse bags and show these
Zerotorescue@0 862 for bagID = 4, 0, -1 do
Zerotorescue@0 863 for slot = 1, GetContainerNumSlots(bagID) do
Zerotorescue@0 864 local itemId = addon:GetItemId(GetContainerItemLink(bagID, slot));
Zerotorescue@0 865
Zerotorescue@0 866 if itemId then
Zerotorescue@0 867 if not items[itemId] then
Zerotorescue@0 868 -- If this item isn't used in any group yet
Zerotorescue@0 869 ref[itemId] = tblAddItemTemplate;
Zerotorescue@0 870 else
Zerotorescue@0 871 -- It's already used in a group, don't show it
Zerotorescue@0 872 ref[itemId] = nil;
Zerotorescue@0 873 end
Zerotorescue@0 874 end
Zerotorescue@0 875 end
Zerotorescue@0 876 end
Zerotorescue@0 877 end
Zerotorescue@0 878
Zerotorescue@0 879 local function UpdateRemoveItemList(info)
Zerotorescue@0 880 local groupName = groupIdToName[info[2]];
Zerotorescue@0 881
Zerotorescue@0 882 if not addon.db.global.groups[groupName].items then
Zerotorescue@0 883 addon.db.global.groups[groupName].items = {};
Zerotorescue@0 884 end
Zerotorescue@0 885
Zerotorescue@0 886 local ref = options.args.groups.args[info[2]].args.remove.args.list.args;
Zerotorescue@0 887
Zerotorescue@0 888 -- Unset all
Zerotorescue@0 889 for itemId, _ in pairs(ref) do
Zerotorescue@0 890 ref[itemId] = nil;
Zerotorescue@0 891 end
Zerotorescue@0 892
Zerotorescue@0 893 -- Parse items in group and show these
Zerotorescue@0 894 for itemId, _ in pairs(addon.db.global.groups[groupName].items) do
Zerotorescue@0 895 ref[itemId] = tblRemoveItemTemplate;
Zerotorescue@0 896 end
Zerotorescue@0 897 end
Zerotorescue@0 898
Zerotorescue@0 899 function addon:GetItemId(itemLink)
Zerotorescue@0 900 itemLink = itemLink and select(3, string.find(itemLink, "|Hitem:([-0-9]+):")); -- if itemLink is nil, it won't execute the second part
Zerotorescue@0 901 itemLink = itemLink and tonumber(itemLink);
Zerotorescue@0 902
Zerotorescue@0 903 return itemLink;
Zerotorescue@0 904 end
Zerotorescue@0 905
Zerotorescue@0 906 -- Default group
Zerotorescue@0 907 local defaultGroup = {
Zerotorescue@0 908 order = 0,
Zerotorescue@0 909 type = "group",
Zerotorescue@0 910 childGroups = "tab",
Zerotorescue@0 911 name = function(info)
Zerotorescue@0 912 return groupIdToName[info[#info]];
Zerotorescue@0 913 end,
Zerotorescue@0 914 args = {
Zerotorescue@0 915 general = {
Zerotorescue@0 916 order = 10,
Zerotorescue@0 917 type = "group",
Zerotorescue@0 918 name = "Stock settings",
Zerotorescue@0 919 desc = "Change the stock settings for just this group.",
Zerotorescue@0 920 args = {
Zerotorescue@0 921 minimumStock = {
Zerotorescue@0 922 order = 10,
Zerotorescue@0 923 type = "group",
Zerotorescue@0 924 inline = true,
Zerotorescue@0 925 name = "Minimum stock",
Zerotorescue@0 926 set = SetOption,
Zerotorescue@0 927 get = GetOption,
Zerotorescue@0 928 disabled = GetDisabled,
Zerotorescue@0 929 args = {
Zerotorescue@0 930 description = {
Zerotorescue@0 931 order = 0,
Zerotorescue@0 932 type = "description",
Zerotorescue@0 933 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 934 },
Zerotorescue@0 935 header = {
Zerotorescue@0 936 order = 5,
Zerotorescue@0 937 type = "header",
Zerotorescue@0 938 name = "",
Zerotorescue@0 939 },
Zerotorescue@0 940 overrideMinimumStock = {
Zerotorescue@0 941 order = 9,
Zerotorescue@0 942 type = "toggle",
Zerotorescue@0 943 name = "Override min stock",
Zerotorescue@0 944 desc = "Allows you to override the minimum stock setting for this group.",
Zerotorescue@0 945 arg = "minimumStock",
Zerotorescue@0 946 },
Zerotorescue@0 947 minimumStock = {
Zerotorescue@0 948 order = 10,
Zerotorescue@0 949 type = "range",
Zerotorescue@0 950 min = 0,
Zerotorescue@0 951 max = 100000,
Zerotorescue@0 952 softMax = 1000,
Zerotorescue@0 953 step = 1,
Zerotorescue@0 954 name = "Minimum stock",
Zerotorescue@0 955 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 956 arg = "overrideMinimumStock",
Zerotorescue@0 957 },
Zerotorescue@0 958 overrideSummaryThresholdShow = {
Zerotorescue@0 959 order = 19,
Zerotorescue@0 960 type = "toggle",
Zerotorescue@0 961 name = "Override summary showing",
Zerotorescue@0 962 desc = "Allows you to override when this group should appear in the summary.",
Zerotorescue@0 963 arg = "summaryThresholdShow",
Zerotorescue@0 964 },
Zerotorescue@0 965 summaryThresholdShow = {
Zerotorescue@0 966 order = 20,
Zerotorescue@0 967 type = "range",
Zerotorescue@0 968 min = 0,
Zerotorescue@0 969 max = 100,
Zerotorescue@0 970 softMax = 10,
Zerotorescue@0 971 step = 0.05,
Zerotorescue@0 972 isPercent = true,
Zerotorescue@0 973 name = "Show in summary when below",
Zerotorescue@0 974 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 975 arg = "overrideSummaryThresholdShow",
Zerotorescue@0 976 },
Zerotorescue@0 977 overrideAlertBelowMinimum = {
Zerotorescue@0 978 order = 29,
Zerotorescue@0 979 type = "toggle",
Zerotorescue@0 980 name = "Override minimum alert",
Zerotorescue@0 981 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 982 arg = "alertBelowMinimum",
Zerotorescue@0 983 },
Zerotorescue@0 984 alertBelowMinimum = {
Zerotorescue@0 985 order = 30,
Zerotorescue@0 986 type = "toggle",
Zerotorescue@0 987 name = "Alert when below minimum",
Zerotorescue@0 988 desc = "Show an alert when an item in this group gets below the minimum stock threshold.",
Zerotorescue@0 989 arg = "overrideAlertBelowMinimum",
Zerotorescue@0 990 },
Zerotorescue@1 991 overrideTrackAtCharacters = {
Zerotorescue@1 992 order = 39,
Zerotorescue@1 993 type = "toggle",
Zerotorescue@1 994 name = "Override track at",
Zerotorescue@1 995 desc = "Allows you to override at which characters items in this group should appear in the summary and generate alerts.",
Zerotorescue@1 996 arg = "trackAtCharacters",
Zerotorescue@1 997 },
Zerotorescue@1 998 trackAtCharacters = {
Zerotorescue@1 999 order = 40,
Zerotorescue@1 1000 type = "multiselect",
Zerotorescue@1 1001 name = "Track at",
Zerotorescue@1 1002 desc = "Select at which characters this should appear in the summary and generate alerts.",
Zerotorescue@1 1003 values = function()
Zerotorescue@1 1004 local temp = {};
Zerotorescue@1 1005 for charName in pairs(addon.db.factionrealm.characters) do
Zerotorescue@1 1006 temp[charName] = charName;
Zerotorescue@1 1007 end
Zerotorescue@1 1008
Zerotorescue@1 1009 -- 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 1010 local count = AceGUI:GetNextWidgetNum("Dropdown-Pullout");
Zerotorescue@7 1011 for i = 1, count do
Zerotorescue@1 1012 if _G['AceGUI30Pullout' .. i] then
Zerotorescue@1 1013 _G['AceGUI30Pullout' .. i]:Hide();
Zerotorescue@1 1014 end
Zerotorescue@1 1015 end
Zerotorescue@1 1016
Zerotorescue@1 1017 return temp;
Zerotorescue@1 1018 end,
Zerotorescue@1 1019 get = GetMultiOption,
Zerotorescue@1 1020 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 1021 arg = "overrideTrackAtCharacters",
Zerotorescue@1 1022 },
Zerotorescue@0 1023 },
Zerotorescue@0 1024 },
Zerotorescue@0 1025 refill = {
Zerotorescue@0 1026 order = 20,
Zerotorescue@0 1027 type = "group",
Zerotorescue@0 1028 inline = true,
Zerotorescue@0 1029 name = "Replenishing stock",
Zerotorescue@0 1030 set = SetOption,
Zerotorescue@0 1031 get = GetOption,
Zerotorescue@0 1032 disabled = GetDisabled,
Zerotorescue@0 1033 args = {
Zerotorescue@0 1034 description = {
Zerotorescue@0 1035 order = 0,
Zerotorescue@0 1036 type = "description",
Zerotorescue@0 1037 name = function(info)
Zerotorescue@0 1038 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1039 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 1040
Zerotorescue@1 1041 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 1042
Zerotorescue@0 1043 return r;
Zerotorescue@0 1044 end,
Zerotorescue@0 1045 },
Zerotorescue@0 1046 header = {
Zerotorescue@0 1047 order = 5,
Zerotorescue@0 1048 type = "header",
Zerotorescue@0 1049 name = "",
Zerotorescue@0 1050 },
Zerotorescue@0 1051 overrideRestockTarget = {
Zerotorescue@0 1052 order = 9,
Zerotorescue@0 1053 type = "toggle",
Zerotorescue@0 1054 name = "Override restock target",
Zerotorescue@0 1055 desc = "Allows you to override the restock target setting for this group.",
Zerotorescue@0 1056 arg = "restockTarget",
Zerotorescue@0 1057 },
Zerotorescue@0 1058 restockTarget = {
Zerotorescue@0 1059 order = 10,
Zerotorescue@0 1060 type = "range",
Zerotorescue@0 1061 min = 0,
Zerotorescue@0 1062 max = 100000,
Zerotorescue@0 1063 softMax = 1000,
Zerotorescue@0 1064 step = 1,
Zerotorescue@0 1065 name = "Restock target",
Zerotorescue@0 1066 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 1067 arg = "overrideRestockTarget",
Zerotorescue@0 1068 },
Zerotorescue@0 1069 overrideMinCraftingQueue = {
Zerotorescue@0 1070 order = 19,
Zerotorescue@0 1071 type = "toggle",
Zerotorescue@0 1072 name = "Override min queue",
Zerotorescue@0 1073 desc = "Allows you to override the minimum craftable items queue setting for this group.",
Zerotorescue@0 1074 arg = "minCraftingQueue",
Zerotorescue@0 1075 },
Zerotorescue@0 1076 minCraftingQueue = {
Zerotorescue@0 1077 order = 20,
Zerotorescue@0 1078 type = "range",
Zerotorescue@0 1079 min = 0,
Zerotorescue@0 1080 max = 1,
Zerotorescue@0 1081 step = 0.01,
Zerotorescue@0 1082 isPercent = true,
Zerotorescue@0 1083 name = "Don't queue if I only miss",
Zerotorescue@0 1084 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 1085 arg = "overrideMinCraftingQueue",
Zerotorescue@0 1086 },
Zerotorescue@1 1087 overrideBonusQueue = {
Zerotorescue@1 1088 order = 29,
Zerotorescue@1 1089 type = "toggle",
Zerotorescue@1 1090 name = "Override bonus queue",
Zerotorescue@1 1091 desc = "Allows you to override the bonus craftable items queue setting for this group.",
Zerotorescue@1 1092 arg = "bonusQueue",
Zerotorescue@1 1093 },
Zerotorescue@1 1094 bonusQueue = {
Zerotorescue@1 1095 order = 30,
Zerotorescue@1 1096 type = "range",
Zerotorescue@1 1097 min = 0,
Zerotorescue@1 1098 max = 10, -- 1000%
Zerotorescue@1 1099 step = 0.01, -- 1%
Zerotorescue@1 1100 isPercent = true,
Zerotorescue@1 1101 name = "Bonus queue",
Zerotorescue@1 1102 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 1103 arg = "overrideBonusQueue",
Zerotorescue@1 1104 },
Zerotorescue@1 1105 overridePriceThreshold = {
Zerotorescue@1 1106 order = 39,
Zerotorescue@1 1107 type = "toggle",
Zerotorescue@1 1108 name = "Override price threshold",
Zerotorescue@1 1109 desc = "Allows you to override the price threshold setting for this group.",
Zerotorescue@1 1110 arg = "priceThreshold",
Zerotorescue@1 1111 },
Zerotorescue@1 1112 priceThreshold = {
Zerotorescue@1 1113 order = 40,
Zerotorescue@1 1114 type = "input",
Zerotorescue@1 1115 name = "Price threshold",
Zerotorescue@1 1116 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 1117 validate = function(info, value) return addon:ValidateReadableMoney(info, value); end,
Zerotorescue@1 1118 get = function(i) return addon:ReadableMoney(GetOption(i)); end,
Zerotorescue@1 1119 set = function(i, v) SetOption(i, addon:ReadableMoneyToCopper(v)); end,
Zerotorescue@1 1120 arg = "overridePriceThreshold",
Zerotorescue@1 1121 },
Zerotorescue@1 1122 overrideHideFromSummaryWhenBelowPriceThreshold = {
Zerotorescue@1 1123 order = 49,
Zerotorescue@1 1124 type = "toggle",
Zerotorescue@1 1125 name = "Override summary showing",
Zerotorescue@1 1126 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 1127 arg = "hideFromSummaryWhenBelowPriceThreshold",
Zerotorescue@1 1128 },
Zerotorescue@1 1129 hideFromSummaryWhenBelowPriceThreshold = { -- I wish this var could be a little bit shorter...
Zerotorescue@1 1130 order = 50,
Zerotorescue@1 1131 type = "toggle",
Zerotorescue@1 1132 name = "Hide when below threshold",
Zerotorescue@1 1133 desc = "Hide items from the summary when their value is below the set price threshold.",
Zerotorescue@1 1134 arg = "overrideHideFromSummaryWhenBelowPriceThreshold",
Zerotorescue@1 1135 },
Zerotorescue@0 1136 },
Zerotorescue@0 1137 },
Zerotorescue@0 1138 },
Zerotorescue@0 1139 },
Zerotorescue@0 1140 group = {
Zerotorescue@0 1141 order = 20,
Zerotorescue@0 1142 type = "group",
Zerotorescue@0 1143 name = "Group Management",
Zerotorescue@0 1144 desc = "Rename, delete or export this group.",
Zerotorescue@0 1145 args = {
Zerotorescue@0 1146 rename = {
Zerotorescue@0 1147 order = 10,
Zerotorescue@0 1148 type = "group",
Zerotorescue@0 1149 name = "Rename",
Zerotorescue@0 1150 inline = true,
Zerotorescue@0 1151 args = {
Zerotorescue@0 1152 rename = {
Zerotorescue@0 1153 order = 10,
Zerotorescue@0 1154 type = "input",
Zerotorescue@0 1155 name = "New group name",
Zerotorescue@0 1156 desc = "Change the name of this group to something else. You can also use item links here as you wish.",
Zerotorescue@0 1157 validate = ValidateGroupName,
Zerotorescue@0 1158 set = function(info, value)
Zerotorescue@0 1159 local oldGroupName = groupIdToName[info[2]];
Zerotorescue@0 1160
Zerotorescue@0 1161 addon.db.global.groups[value] = CopyTable(addon.db.global.groups[oldGroupName]);
Zerotorescue@0 1162 addon.db.global.groups[oldGroupName] = nil;
Zerotorescue@0 1163
Zerotorescue@0 1164 groupIdToName[info[2]] = value;
Zerotorescue@0 1165 groupIdToName[value] = true;
Zerotorescue@0 1166 groupIdToName[oldGroupName] = nil;
Zerotorescue@0 1167
Zerotorescue@0 1168 addon:FillGroupOptions();
Zerotorescue@0 1169 end,
Zerotorescue@0 1170 get = function(info)
Zerotorescue@0 1171 return groupIdToName[info[2]];
Zerotorescue@0 1172 end,
Zerotorescue@0 1173 width = "double",
Zerotorescue@0 1174 },
Zerotorescue@0 1175 },
Zerotorescue@0 1176 },
Zerotorescue@0 1177 delete = {
Zerotorescue@0 1178 order = 20,
Zerotorescue@0 1179 type = "group",
Zerotorescue@0 1180 name = "Delete",
Zerotorescue@0 1181 inline = true,
Zerotorescue@0 1182 args = {
Zerotorescue@0 1183 delete = {
Zerotorescue@0 1184 order = 10,
Zerotorescue@0 1185 type = "execute",
Zerotorescue@0 1186 name = "Delete group",
Zerotorescue@0 1187 desc = "Delete the currently selected group.",
Zerotorescue@0 1188 confirm = true,
Zerotorescue@0 1189 confirmText = "Are you sure you wish to |cffff0000DELETE|r this group? This action is not reversable!",
Zerotorescue@0 1190 func = function(info)
Zerotorescue@0 1191 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1192
Zerotorescue@0 1193 addon.db.global.groups[groupName] = nil;
Zerotorescue@0 1194
Zerotorescue@0 1195 addon:FillGroupOptions();
Zerotorescue@0 1196 end,
Zerotorescue@0 1197 },
Zerotorescue@0 1198 },
Zerotorescue@0 1199 },
Zerotorescue@0 1200 export = {
Zerotorescue@0 1201 order = 30,
Zerotorescue@0 1202 type = "group",
Zerotorescue@0 1203 name = "Export",
Zerotorescue@0 1204 inline = true,
Zerotorescue@0 1205 args = {
Zerotorescue@0 1206 input = {
Zerotorescue@0 1207 order = 10,
Zerotorescue@0 1208 type = "input",
Zerotorescue@0 1209 multiline = true,
Zerotorescue@0 1210 name = "Group data",
Zerotorescue@0 1211 width = "full",
Zerotorescue@0 1212 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 1213 set = false,
Zerotorescue@0 1214 get = function(info)
Zerotorescue@0 1215 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1216
Zerotorescue@0 1217 -- We want to include the group name, so we copy the table then set another value
Zerotorescue@0 1218 local temp = CopyTable(addon.db.global.groups[groupName]);
Zerotorescue@0 1219 temp.name = groupName;
Zerotorescue@9 1220 temp.trackAtCharacters = nil;
Zerotorescue@9 1221 temp.overrideTrackAtCharacters = nil;
Zerotorescue@0 1222
Zerotorescue@0 1223 if not AceSerializer then
Zerotorescue@0 1224 AceSerializer = LibStub("AceSerializer-3.0");
Zerotorescue@0 1225 end
Zerotorescue@0 1226
Zerotorescue@0 1227 return AceSerializer:Serialize(temp);
Zerotorescue@0 1228 end,
Zerotorescue@0 1229 },
Zerotorescue@0 1230 },
Zerotorescue@0 1231 },
Zerotorescue@0 1232 },
Zerotorescue@0 1233 },
Zerotorescue@0 1234 add = {
Zerotorescue@0 1235 order = 30,
Zerotorescue@0 1236 type = "group",
Zerotorescue@0 1237 name = "Add items",
Zerotorescue@0 1238 args = {
Zerotorescue@0 1239 singleAdd = {
Zerotorescue@0 1240 order = 10,
Zerotorescue@0 1241 type = "group",
Zerotorescue@0 1242 inline = true,
Zerotorescue@0 1243 name = "Add items",
Zerotorescue@0 1244 args = {
Zerotorescue@0 1245 help = {
Zerotorescue@0 1246 order = 10,
Zerotorescue@0 1247 type = "description",
Zerotorescue@0 1248 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 1249 },
Zerotorescue@0 1250 itemLink = {
Zerotorescue@0 1251 order = 20,
Zerotorescue@0 1252 type = "input",
Zerotorescue@0 1253 name = "Single item add (item-link or item-id)",
Zerotorescue@0 1254 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 1255 validate = function(info, value)
Zerotorescue@0 1256 -- If the value is empty we'll allow passing to clear the carret
Zerotorescue@0 1257 if value == "" then return true; end
Zerotorescue@0 1258
Zerotorescue@0 1259 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1260
Zerotorescue@0 1261 local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or ""));
Zerotorescue@0 1262
Zerotorescue@0 1263 if not itemId then
Zerotorescue@0 1264 return "This is not a valid item link.";
Zerotorescue@0 1265 elseif InGroup(itemId) then
Zerotorescue@0 1266 return ("This item is already in the group \"%s\"."):format(InGroup(itemId));
Zerotorescue@0 1267 end
Zerotorescue@0 1268
Zerotorescue@0 1269 return true;
Zerotorescue@0 1270 end,
Zerotorescue@0 1271 set = function(info, value)
Zerotorescue@0 1272 if value and value ~= "" then
Zerotorescue@0 1273 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1274
Zerotorescue@0 1275 local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or ""));
Zerotorescue@0 1276
Zerotorescue@0 1277 AddToGroup(groupName, itemId);
Zerotorescue@0 1278
Zerotorescue@0 1279 print(("Added %s"):format(select(2, GetItemInfo(itemId)) or ("Unknown (#%d)"):format(itemId)));
Zerotorescue@0 1280 end
Zerotorescue@0 1281 end,
Zerotorescue@0 1282 get = false,
Zerotorescue@0 1283 },
Zerotorescue@0 1284 import = {
Zerotorescue@0 1285 order = 40,
Zerotorescue@0 1286 type = "input",
Zerotorescue@0 1287 name = "Import item data",
Zerotorescue@0 1288 desc = "Import item data from an exported item data-string. Any items already grouped will be skipped.",
Zerotorescue@0 1289 set = function(info, value)
Zerotorescue@0 1290 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1291
Zerotorescue@0 1292 local allItemIds = { string.split(";", value or "") };
Zerotorescue@0 1293
Zerotorescue@0 1294 for _, value in pairs(allItemIds) do
Zerotorescue@0 1295 local itemId = tonumber(value);
Zerotorescue@0 1296
Zerotorescue@0 1297 if not itemId then
Zerotorescue@0 1298 print(("\"%s\" is not a number."):format(value));
Zerotorescue@0 1299 elseif InGroup(itemId) then
Zerotorescue@0 1300 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 1301 else
Zerotorescue@0 1302 AddToGroup(groupName, itemId);
Zerotorescue@0 1303 end
Zerotorescue@0 1304 end
Zerotorescue@0 1305 end,
Zerotorescue@0 1306 get = false,
Zerotorescue@0 1307 },
Zerotorescue@0 1308 },
Zerotorescue@0 1309 },
Zerotorescue@0 1310 massAdd = {
Zerotorescue@0 1311 order = 20,
Zerotorescue@0 1312 type = "group",
Zerotorescue@0 1313 inline = true,
Zerotorescue@0 1314 name = "Mass add",
Zerotorescue@0 1315 args = {
Zerotorescue@0 1316 help = {
Zerotorescue@0 1317 order = 10,
Zerotorescue@0 1318 type = "description",
Zerotorescue@0 1319 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 1320 },
Zerotorescue@0 1321 massAdd = {
Zerotorescue@0 1322 order = 20,
Zerotorescue@0 1323 type = "input",
Zerotorescue@0 1324 name = "Add all items matching...",
Zerotorescue@0 1325 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 1326 --set = massAddItems,
Zerotorescue@0 1327 get = false,
Zerotorescue@0 1328 },
Zerotorescue@0 1329 },
Zerotorescue@0 1330 },
Zerotorescue@0 1331 list = {
Zerotorescue@0 1332 order = 30,
Zerotorescue@0 1333 type = "group",
Zerotorescue@0 1334 inline = true,
Zerotorescue@0 1335 name = "Item list",
Zerotorescue@0 1336 hidden = UpdateAddItemList,
Zerotorescue@0 1337 args = {
Zerotorescue@0 1338
Zerotorescue@0 1339 },
Zerotorescue@0 1340 },
Zerotorescue@0 1341 },
Zerotorescue@0 1342 },
Zerotorescue@0 1343 remove = {
Zerotorescue@0 1344 order = 40,
Zerotorescue@0 1345 type = "group",
Zerotorescue@0 1346 name = "Current items",
Zerotorescue@0 1347 args = {
Zerotorescue@0 1348 help = {
Zerotorescue@0 1349 order = 10,
Zerotorescue@0 1350 type = "group",
Zerotorescue@0 1351 inline = true,
Zerotorescue@0 1352 name = "Help",
Zerotorescue@0 1353 hidden = false,
Zerotorescue@0 1354 args = {
Zerotorescue@0 1355 help = {
Zerotorescue@0 1356 order = 10,
Zerotorescue@0 1357 type = "description",
Zerotorescue@0 1358 name = "Click the items you wish to remove from this group.",
Zerotorescue@0 1359 },
Zerotorescue@0 1360 },
Zerotorescue@0 1361 },
Zerotorescue@0 1362 list = {
Zerotorescue@0 1363 order = 20,
Zerotorescue@0 1364 type = "group",
Zerotorescue@0 1365 inline = true,
Zerotorescue@0 1366 name = "Item list",
Zerotorescue@0 1367 hidden = UpdateRemoveItemList,
Zerotorescue@0 1368 args = {
Zerotorescue@0 1369
Zerotorescue@0 1370 },
Zerotorescue@0 1371 },
Zerotorescue@0 1372 export = {
Zerotorescue@0 1373 order = 30,
Zerotorescue@0 1374 type = "group",
Zerotorescue@0 1375 name = "Export",
Zerotorescue@0 1376 inline = true,
Zerotorescue@0 1377 args = {
Zerotorescue@0 1378 input = {
Zerotorescue@0 1379 order = 10,
Zerotorescue@0 1380 type = "input",
Zerotorescue@0 1381 name = "Item data",
Zerotorescue@0 1382 width = "full",
Zerotorescue@0 1383 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 1384 set = false,
Zerotorescue@0 1385 get = function(info)
Zerotorescue@0 1386 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1387
Zerotorescue@0 1388 local combinedItemIds;
Zerotorescue@0 1389 -- Parse items in group and show these
Zerotorescue@0 1390 for itemId, _ in pairs(addon.db.global.groups[groupName].items) do
Zerotorescue@0 1391 if not combinedItemIds then
Zerotorescue@0 1392 combinedItemIds = tostring(itemId);
Zerotorescue@0 1393 else
Zerotorescue@0 1394 combinedItemIds = combinedItemIds .. (";%d"):format(itemId);
Zerotorescue@0 1395 end
Zerotorescue@0 1396 end
Zerotorescue@0 1397
Zerotorescue@0 1398 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 1399 end,
Zerotorescue@0 1400 },
Zerotorescue@0 1401 },
Zerotorescue@0 1402 },
Zerotorescue@0 1403 },
Zerotorescue@0 1404 },
Zerotorescue@0 1405 },
Zerotorescue@0 1406 };
Zerotorescue@0 1407
Zerotorescue@0 1408 function addon:MakeGroupOptions()
Zerotorescue@0 1409 options.args.groups = {
Zerotorescue@0 1410 order = 1100,
Zerotorescue@0 1411 type = "group",
Zerotorescue@0 1412 name = "Groups",
Zerotorescue@0 1413 desc = "Change a group.",
Zerotorescue@0 1414 args = {
Zerotorescue@0 1415 create = {
Zerotorescue@0 1416 order = 10,
Zerotorescue@0 1417 type = "group",
Zerotorescue@0 1418 inline = true,
Zerotorescue@0 1419 name = "Create a brand new group",
Zerotorescue@0 1420 args = {
Zerotorescue@0 1421 name = {
Zerotorescue@0 1422 order = 10,
Zerotorescue@0 1423 type = "input",
Zerotorescue@0 1424 name = "Group name",
Zerotorescue@0 1425 desc = "The name of the group. You can also use item links as you wish.",
Zerotorescue@0 1426 validate = ValidateGroupName,
Zerotorescue@0 1427 set = function(_, value)
Zerotorescue@0 1428 self.db.global.groups[value] = {};
Zerotorescue@0 1429
Zerotorescue@0 1430 addon:FillGroupOptions();
Zerotorescue@0 1431 end,
Zerotorescue@0 1432 get = false,
Zerotorescue@0 1433 width = "double",
Zerotorescue@0 1434 },
Zerotorescue@0 1435 },
Zerotorescue@0 1436 },
Zerotorescue@0 1437 import = {
Zerotorescue@0 1438 order = 20,
Zerotorescue@0 1439 type = "group",
Zerotorescue@0 1440 inline = true,
Zerotorescue@0 1441 name = "Import a group",
Zerotorescue@0 1442 args = {
Zerotorescue@0 1443 input = {
Zerotorescue@0 1444 order = 10,
Zerotorescue@0 1445 type = "input",
Zerotorescue@0 1446 multiline = true,
Zerotorescue@0 1447 name = "Group data",
Zerotorescue@0 1448 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 1449 set = function(info, value)
Zerotorescue@9 1450 local data = { string.split("\n", value or "") };
Zerotorescue@0 1451
Zerotorescue@9 1452 for _, current in pairs(data) do
Zerotorescue@0 1453 if not AceSerializer then
Zerotorescue@0 1454 AceSerializer = LibStub("AceSerializer-3.0");
Zerotorescue@0 1455 end
Zerotorescue@0 1456
Zerotorescue@0 1457 local result, temp = AceSerializer:Deserialize(current);
Zerotorescue@0 1458 local name;
Zerotorescue@0 1459
Zerotorescue@0 1460 if not temp.name then
Zerotorescue@0 1461 print("|cffff0000The provided data is not supported.|r");
Zerotorescue@0 1462 return;
Zerotorescue@0 1463 else
Zerotorescue@0 1464 name = temp.name;
Zerotorescue@0 1465 temp.name = nil;
Zerotorescue@9 1466 print(("Importing %s..."):format(name));
Zerotorescue@0 1467 end
Zerotorescue@0 1468
Zerotorescue@0 1469 local newGroupName = string.trim(string.lower(name or ""));
Zerotorescue@0 1470
Zerotorescue@0 1471 for name in pairs(self.db.global.groups) do
Zerotorescue@0 1472 if string.lower(name) == newGroupName then
Zerotorescue@9 1473 print(("|cffff0000Aborting: A group named \"%s\" already exists.|r"):format(name));
Zerotorescue@0 1474 return;
Zerotorescue@0 1475 end
Zerotorescue@0 1476 end
Zerotorescue@9 1477
Zerotorescue@9 1478 -- Remove items that are already in another group
Zerotorescue@9 1479 for value, _ in pairs(temp.items) do
Zerotorescue@9 1480 local itemId = tonumber(itemid);
Zerotorescue@9 1481
Zerotorescue@9 1482 if not itemId then
Zerotorescue@9 1483 print(("\"%s\" is not a number."):format(value));
Zerotorescue@9 1484 temp.items[value] = nil;
Zerotorescue@9 1485 elseif InGroup(itemId) then
Zerotorescue@9 1486 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@9 1487 temp.items[value] = nil;
Zerotorescue@9 1488 else
Zerotorescue@9 1489 -- Ensure the keys are numeric
Zerotorescue@9 1490 temp.items[value] = nil;
Zerotorescue@9 1491 temp.items[itemId] = true;
Zerotorescue@9 1492 end
Zerotorescue@9 1493 end
Zerotorescue@9 1494
Zerotorescue@9 1495 -- Ensure this data isn't received (this would be buggy as exports from other accounts won't know what to do with this)
Zerotorescue@9 1496 temp.trackAtCharacters = nil;
Zerotorescue@9 1497 temp.overrideTrackAtCharacters = nil;
Zerotorescue@9 1498
Zerotorescue@0 1499 self.db.global.groups[name] = temp;
Zerotorescue@7 1500
Zerotorescue@7 1501 self:FillGroupOptions();
Zerotorescue@0 1502 end
Zerotorescue@0 1503 end,
Zerotorescue@0 1504 get = false,
Zerotorescue@0 1505 width = "full",
Zerotorescue@0 1506 },
Zerotorescue@0 1507 },
Zerotorescue@0 1508 },
Zerotorescue@0 1509 },
Zerotorescue@0 1510 };
Zerotorescue@0 1511 end
Zerotorescue@0 1512
Zerotorescue@0 1513 function addon:FillGroupOptions()
Zerotorescue@0 1514 for id, name in pairs(groupIdToName) do
Zerotorescue@0 1515 if type(name) == "string" and not self.db.global.groups[name] then
Zerotorescue@0 1516 options.args.groups.args[id] = nil;
Zerotorescue@0 1517 groupIdToName[id] = nil;
Zerotorescue@0 1518 groupIdToName[name] = nil;
Zerotorescue@0 1519 end
Zerotorescue@0 1520 end
Zerotorescue@0 1521
Zerotorescue@0 1522 for name, values in pairs(self.db.global.groups) do
Zerotorescue@0 1523 if not groupIdToName[name] then
Zerotorescue@0 1524 options.args.groups.args[tostring(count)] = CopyTable(defaultGroup);
Zerotorescue@0 1525
Zerotorescue@0 1526 groupIdToName[tostring(count)] = name;
Zerotorescue@0 1527 groupIdToName[name] = true;
Zerotorescue@0 1528
Zerotorescue@0 1529 count = ( count + 1 );
Zerotorescue@0 1530 end
Zerotorescue@0 1531 end
Zerotorescue@0 1532 end
Zerotorescue@0 1533
Zerotorescue@0 1534 function addon:GetItemCount(itemId)
Zerotorescue@0 1535 return Altoholic:GetItemCount(itemId);
Zerotorescue@0 1536 end
Zerotorescue@0 1537
Zerotorescue@1 1538 function addon:GetAuctionValue(link)
Zerotorescue@1 1539 if GetAuctionBuyout then
Zerotorescue@1 1540 -- Auctionator support
Zerotorescue@1 1541
Zerotorescue@1 1542 local lowBuy = GetAuctionBuyout(link);
Zerotorescue@1 1543
Zerotorescue@1 1544 if lowBuy == nil then
Zerotorescue@1 1545 -- No auctions up at this time
Zerotorescue@1 1546 return -1;
Zerotorescue@1 1547 end
Zerotorescue@1 1548
Zerotorescue@1 1549 return lowBuy;
Zerotorescue@1 1550 elseif AucAdvanced ~= nil and AucAdvanced.Modules.Util.SimpleAuction ~= nil and AucAdvanced.Modules.Util.SimpleAuction.Private.GetItems ~= nil then
Zerotorescue@1 1551 -- Auctioneer support
Zerotorescue@1 1552
Zerotorescue@1 1553 local imgSeen, _, _, _, _, lowBuy, _, _ = AucAdvanced.Modules.Util.SimpleAuction.Private.GetItems(link);
Zerotorescue@1 1554 --local imgseen, image, matchBid, matchBuy, lowBid, lowBuy, aveBuy, aSeen
Zerotorescue@1 1555
Zerotorescue@1 1556 if imgSeen <= 0 then
Zerotorescue@1 1557 -- No auctions up at this time
Zerotorescue@1 1558 return -1;
Zerotorescue@1 1559 end
Zerotorescue@1 1560
Zerotorescue@1 1561 return lowBuy;
Zerotorescue@1 1562 end
Zerotorescue@7 1563
Zerotorescue@7 1564 return -2;
Zerotorescue@1 1565 end
Zerotorescue@1 1566
Zerotorescue@0 1567
Zerotorescue@0 1568
Zerotorescue@0 1569
Zerotorescue@0 1570 function addon:Debug(t)
Zerotorescue@0 1571 if not self.debugChannel and self.debugChannel ~= false then
Zerotorescue@0 1572 -- 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 1573 self.debugChannel = false;
Zerotorescue@0 1574
Zerotorescue@0 1575 for i = 1, NUM_CHAT_WINDOWS do
Zerotorescue@0 1576 local name = GetChatWindowInfo(i);
Zerotorescue@0 1577
Zerotorescue@0 1578 if name:upper() == "DEBUG" then
Zerotorescue@0 1579 self.debugChannel = _G["ChatFrame" .. i];
Zerotorescue@0 1580 end
Zerotorescue@0 1581 end
Zerotorescue@0 1582 end
Zerotorescue@0 1583
Zerotorescue@0 1584 if self.debugChannel then
Zerotorescue@0 1585 self.debugChannel:AddMessage(t);
Zerotorescue@0 1586 end
Zerotorescue@0 1587 end