annotate Core.lua @ 0:c6ff7ba0e8f6

Reasonably functional now. Cleaning up some stuff which might have to be reverted.
author Zerotorescue
date Thu, 07 Oct 2010 17:17:43 +0200
parents
children 9fff13c08f99
rev   line source
Zerotorescue@0 1 -- You can access this addon's object through: LibStub("AceAddon-3.0"):GetAddon("Inventory")
Zerotorescue@0 2 local addon = LibStub("AceAddon-3.0"):NewAddon("Inventory", "AceEvent-3.0", "AceTimer-3.0");
Zerotorescue@0 3
Zerotorescue@0 4 local Media = LibStub("LibSharedMedia-3.0");
Zerotorescue@0 5 Media:Register("sound", "Cartoon FX", [[Sound\Doodad\Goblin_Lottery_Open03.wav]]);
Zerotorescue@0 6 Media:Register("sound", "Cheer", [[Sound\Event Sounds\OgreEventCheerUnique.wav]]);
Zerotorescue@0 7 Media:Register("sound", "Explosion", [[Sound\Doodad\Hellfire_Raid_FX_Explosion05.wav]]);
Zerotorescue@0 8 Media:Register("sound", "Fel Nova", [[Sound\Spells\SeepingGaseous_Fel_Nova.wav]]);
Zerotorescue@0 9 Media:Register("sound", "Fel Portal", [[Sound\Spells\Sunwell_Fel_PortalStand.wav]]);
Zerotorescue@0 10 Media:Register("sound", "Magic Click", [[Sound\interface\MagicClick.wav]]);
Zerotorescue@0 11 Media:Register("sound", "Rubber Ducky", [[Sound\Doodad\Goblin_Lottery_Open01.wav]]);
Zerotorescue@0 12 Media:Register("sound", "Shing!", [[Sound\Doodad\PortcullisActive_Closed.wav]]);
Zerotorescue@0 13 Media:Register("sound", "Simon Chime", [[Sound\Doodad\SimonGame_LargeBlueTree.wav]]);
Zerotorescue@0 14 Media:Register("sound", "Simon Error", [[Sound\Spells\SimonGame_Visual_BadPress.wav]]);
Zerotorescue@0 15 Media:Register("sound", "Simon Start", [[Sound\Spells\SimonGame_Visual_GameStart.wav]]);
Zerotorescue@0 16 Media:Register("sound", "War Drums", [[Sound\Event Sounds\Event_wardrum_ogre.wav]]);
Zerotorescue@0 17 Media:Register("sound", "Wham!", [[Sound\Doodad\PVP_Lordaeron_Door_Open.wav]]);
Zerotorescue@0 18 Media:Register("sound", "Whisper Ping", [[Sound\interface\iTellMessage.wav]]);
Zerotorescue@0 19 Media:Register("sound", "You Will Die!", [[Sound\Creature\CThun\CThunYouWillDIe.wav]]);
Zerotorescue@0 20
Zerotorescue@0 21 local AceConfigDialog, AceConfigRegistry, AceSerializer;
Zerotorescue@0 22 local groupIdToName = {};
Zerotorescue@0 23 local options = {};
Zerotorescue@0 24
Zerotorescue@0 25 function addon:OnInitialize()
Zerotorescue@0 26 self:Debug("OnInitialize");
Zerotorescue@0 27
Zerotorescue@0 28 -- SAVED VARIABLES
Zerotorescue@0 29
Zerotorescue@0 30 local defaults = {
Zerotorescue@0 31 global = {
Zerotorescue@0 32 groups = {},
Zerotorescue@0 33 defaults = {
Zerotorescue@0 34 minimumStock = 60,
Zerotorescue@0 35 alertBelowMinimum = true,
Zerotorescue@0 36 summaryThresholdShow = 10,
Zerotorescue@0 37 restockTarget = 60,
Zerotorescue@0 38 minCraftingQueue = 0.05,
Zerotorescue@0 39 bonusQueue = 0.1,
Zerotorescue@0 40 priceThreshold = 0,
Zerotorescue@0 41 trackAtCharacters = {},
Zerotorescue@0 42 colors = {
Zerotorescue@0 43 red = 0;
Zerotorescue@0 44 orange = 0.3;
Zerotorescue@0 45 yellow = 0.6;
Zerotorescue@0 46 green = 0.95;
Zerotorescue@0 47 },
Zerotorescue@0 48 },
Zerotorescue@0 49 },
Zerotorescue@0 50 factionrealm = {
Zerotorescue@0 51 characters = {},
Zerotorescue@0 52 },
Zerotorescue@0 53 };
Zerotorescue@0 54
Zerotorescue@0 55 -- Register our saved variables database
Zerotorescue@0 56 self.db = LibStub("AceDB-3.0"):New("InventoryDB", defaults, true);
Zerotorescue@0 57
Zerotorescue@0 58 -- SLASH COMMANDS
Zerotorescue@0 59
Zerotorescue@0 60 -- Disable the AddonLoader slash commands
Zerotorescue@0 61 SLASH_INVENTORY1 = nil;
Zerotorescue@0 62 SLASH_IY1 = nil;
Zerotorescue@0 63
Zerotorescue@0 64 -- Register our own slash commands
Zerotorescue@0 65 SLASH_INVENTORY1 = "/inventory";
Zerotorescue@0 66 SLASH_INVENTORY2 = "/iy";
Zerotorescue@0 67 SlashCmdList["INVENTORY"] = function(msg)
Zerotorescue@0 68 self:CommandHandler(msg);
Zerotorescue@0 69 end
Zerotorescue@0 70
Zerotorescue@0 71 -- INTERFACE OPTIONS
Zerotorescue@0 72
Zerotorescue@0 73 -- Attempt to remove the interface options added by AddonLoader (if enabled)
Zerotorescue@0 74 if AddonLoader and AddonLoader.RemoveInterfaceOptions then
Zerotorescue@0 75 AddonLoader:RemoveInterfaceOptions("Inventory");
Zerotorescue@0 76 end
Zerotorescue@0 77
Zerotorescue@0 78 -- Now create our own options frame
Zerotorescue@0 79 local frame = CreateFrame("Frame", nil, UIParent);
Zerotorescue@0 80 frame:Hide();
Zerotorescue@0 81 frame.name = "Inventory";
Zerotorescue@0 82 frame:HookScript("OnShow", function(self)
Zerotorescue@0 83 -- Refresh the frame to instantly show the right options
Zerotorescue@0 84 InterfaceOptionsFrame_OpenToCategory(self.name)
Zerotorescue@0 85 end);
Zerotorescue@0 86 -- And add it to the interface options
Zerotorescue@0 87 InterfaceOptions_AddCategory(frame);
Zerotorescue@0 88
Zerotorescue@0 89 self:MakeWidgets();
Zerotorescue@0 90
Zerotorescue@0 91 -- Remember this character is mine
Zerotorescue@0 92 local playerName = UnitName("player");
Zerotorescue@0 93 if not self.db.factionrealm.characters[playerName] then
Zerotorescue@0 94 self.db.factionrealm.characters[playerName] = true;
Zerotorescue@0 95
Zerotorescue@0 96 -- Default to tracking on all chars, untracking is a convenience, not tracking by default would probably get multiple issue reports.
Zerotorescue@0 97 self.db.global.defaults.trackAtCharacters[playerName] = true;
Zerotorescue@0 98 end
Zerotorescue@0 99 end
Zerotorescue@0 100
Zerotorescue@0 101 function addon:MakeWidgets()
Zerotorescue@0 102 local AceGUI = LibStub("AceGUI-3.0");
Zerotorescue@0 103
Zerotorescue@0 104 --[[
Zerotorescue@0 105 [ ItemLinkButton ]
Zerotorescue@0 106 UserData: itemId, onClick event
Zerotorescue@0 107 OnEnter: tooltip show
Zerotorescue@0 108 OnLeave: tooltip hid
Zerotorescue@0 109
Zerotorescue@0 110 ]]
Zerotorescue@0 111
Zerotorescue@0 112 -- Define out custom item link button widget
Zerotorescue@0 113 -- 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 114
Zerotorescue@0 115 local widgetType = "ItemLinkButton";
Zerotorescue@0 116 local widgetVersion = 1;
Zerotorescue@0 117
Zerotorescue@0 118 -- Empty function for disabling functions
Zerotorescue@0 119 local function Dummy() end
Zerotorescue@0 120
Zerotorescue@0 121 -- Overwrite the SetText-function of our custom widgets
Zerotorescue@0 122 local function CustomWidgetSetText(self, value, ...)
Zerotorescue@0 123 if value then
Zerotorescue@0 124 -- Remember the itemId in a local parameter (using :GetText, we'd have to run a pattern over it and it would all get silly)
Zerotorescue@0 125 self.itemId = tonumber(value);
Zerotorescue@0 126
Zerotorescue@0 127 if not self.itemId then error("itemId is not a number."); end
Zerotorescue@0 128
Zerotorescue@0 129 -- Put the icon in front of it
Zerotorescue@0 130 self:SetImage(GetItemIcon(self.itemId));
Zerotorescue@0 131 -- Standardize the size
Zerotorescue@0 132 self:SetImageSize(16, 16);
Zerotorescue@0 133
Zerotorescue@0 134 -- Make readable font
Zerotorescue@0 135 self:SetFontObject(GameFontHighlight);
Zerotorescue@0 136
Zerotorescue@0 137 -- We don't want to set the itemId as text, but rather the item link, so get that.
Zerotorescue@0 138 value = select(2, GetItemInfo(value)) or ("Unknown (#%d)"):format(value);
Zerotorescue@0 139
Zerotorescue@0 140 return self.originalSetText(self, value, ...);
Zerotorescue@0 141 end
Zerotorescue@0 142 end
Zerotorescue@0 143
Zerotorescue@0 144 -- Overwrite the OnEnter-event of our custom widgets to use our own function
Zerotorescue@0 145 local function CustomWidgetOnEnter(self)
Zerotorescue@0 146 if self.itemId then
Zerotorescue@0 147 GameTooltip:SetOwner(self.frame, "ANCHOR_TOPRIGHT");
Zerotorescue@0 148 GameTooltip:SetHyperlink(("item:%d"):format(self.itemId));
Zerotorescue@0 149 GameTooltip:Show();
Zerotorescue@0 150 end
Zerotorescue@0 151 end
Zerotorescue@0 152
Zerotorescue@0 153 -- Overwrite the OnClick-event of our custom widgets to use our own function
Zerotorescue@0 154 local function CustomWidgetOnClick(self)
Zerotorescue@0 155 local info = self:GetUserDataTable()
Zerotorescue@0 156
Zerotorescue@0 157 info.option.set(self, info);
Zerotorescue@0 158 end
Zerotorescue@0 159
Zerotorescue@0 160 -- Overwrite the SetCallback-function of our custom widgets
Zerotorescue@0 161 local function CustomWidgetSetCallback(self, event, func, ...)
Zerotorescue@0 162 if event == "OnEnter" then
Zerotorescue@0 163 -- This event is called once when creating the widget
Zerotorescue@0 164 -- When it becomes hidden, all events appear to be removed, but once it's shown again, OnEnter will be re-applied
Zerotorescue@0 165 -- Hence any registered Callback must be done in here
Zerotorescue@0 166
Zerotorescue@0 167 self.originalSetCallBack(self, "OnClick", CustomWidgetOnClick);
Zerotorescue@0 168
Zerotorescue@0 169 return self.originalSetCallBack(self, event, CustomWidgetOnEnter, ...);
Zerotorescue@0 170 else
Zerotorescue@0 171 return self.originalSetCallBack(self, event, func, ...);
Zerotorescue@0 172 end
Zerotorescue@0 173 end
Zerotorescue@0 174
Zerotorescue@0 175 local function CustomWidgetHideTooltip()
Zerotorescue@0 176 GameTooltip:Hide();
Zerotorescue@0 177 end
Zerotorescue@0 178
Zerotorescue@0 179 -- Makes an instance of our ItemLinkButton widget
Zerotorescue@0 180 local function GetItemLinkButton()
Zerotorescue@0 181 local widget = AceGUI:Create("InteractiveLabel");
Zerotorescue@0 182 widget.type = widgetType;
Zerotorescue@0 183
Zerotorescue@0 184 -- We can only provide custom widgets for input, select and multiselect fields
Zerotorescue@0 185 -- Input being the simplest, we use that - however, it provides two parameters: label and text. We only need one, disable the other.
Zerotorescue@0 186 widget.SetLabel = Dummy;
Zerotorescue@0 187
Zerotorescue@0 188 if not widget.originalSetText then
Zerotorescue@0 189 -- When setting text we provide an itemId
Zerotorescue@0 190 -- Use this itemId to set the icon and do all fancy stuff
Zerotorescue@0 191 widget.originalSetText = widget.SetText;
Zerotorescue@0 192 widget.SetText = CustomWidgetSetText;
Zerotorescue@0 193 end
Zerotorescue@0 194
Zerotorescue@0 195
Zerotorescue@0 196 if not widget.originalSetCallBack then
Zerotorescue@0 197 -- We don't want AceConfig to overwrite our OnEnter with the tooltip functions, so override that
Zerotorescue@0 198 widget.originalSetCallBack = widget.SetCallback;
Zerotorescue@0 199 widget.SetCallback = CustomWidgetSetCallback;
Zerotorescue@0 200
Zerotorescue@0 201 -- Make sure it's called (AceConfig will probably repeat this, but we are prepared in case it's ever changed)
Zerotorescue@0 202 widget:SetCallback("OnEnter", Dummy);
Zerotorescue@0 203 widget:SetCallback("OnLeave", CustomWidgetHideTooltip);
Zerotorescue@0 204 end
Zerotorescue@0 205
Zerotorescue@0 206 return widget;
Zerotorescue@0 207 end
Zerotorescue@0 208
Zerotorescue@0 209 AceGUI:RegisterWidgetType(widgetType, GetItemLinkButton, widgetVersion);
Zerotorescue@0 210 end
Zerotorescue@0 211
Zerotorescue@0 212 function addon:CommandHandler(message)
Zerotorescue@0 213 local cmd, arg = string.split(" ", (message or ""), 2);
Zerotorescue@0 214 cmd = string.lower(cmd);
Zerotorescue@0 215
Zerotorescue@0 216 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@0 217 self:Show();
Zerotorescue@0 218 elseif cmd == "d" or cmd == "debug" then
Zerotorescue@0 219 self.debugChannel = false;
Zerotorescue@0 220 for i = 1, NUM_CHAT_WINDOWS do
Zerotorescue@0 221 local name = GetChatWindowInfo(i);
Zerotorescue@0 222
Zerotorescue@0 223 if name:upper() == "DEBUG" then
Zerotorescue@0 224 self.debugChannel = _G["ChatFrame" .. i];
Zerotorescue@0 225
Zerotorescue@0 226 print("A debug channel already exists, used the old one. (" .. i .. ")");
Zerotorescue@0 227 return;
Zerotorescue@0 228 end
Zerotorescue@0 229 end
Zerotorescue@0 230
Zerotorescue@0 231 if not self.debugChannel then
Zerotorescue@0 232 -- Create a new debug channel
Zerotorescue@0 233 local chatFrame = FCF_OpenNewWindow('Debug');
Zerotorescue@0 234 ChatFrame_RemoveAllMessageGroups(chatFrame);
Zerotorescue@0 235 self.debugChannel = chatFrame;
Zerotorescue@0 236
Zerotorescue@0 237 print("New debug channel created.");
Zerotorescue@0 238 end
Zerotorescue@0 239 else
Zerotorescue@0 240 print("Wrong command, available: /inventory config (or /inventory c)");
Zerotorescue@0 241 end
Zerotorescue@0 242 end
Zerotorescue@0 243
Zerotorescue@0 244 function addon:Load()
Zerotorescue@0 245 if not AceConfigDialog and not AceConfigRegistry then
Zerotorescue@0 246 self:FillOptions();
Zerotorescue@0 247
Zerotorescue@0 248 -- Build options dialog
Zerotorescue@0 249 AceConfigDialog = LibStub("AceConfigDialog-3.0");
Zerotorescue@0 250 AceConfigRegistry = LibStub("AceConfigRegistry-3.0");
Zerotorescue@0 251 -- Register options table
Zerotorescue@0 252 LibStub("AceConfig-3.0"):RegisterOptionsTable("InventoryOptions", options);
Zerotorescue@0 253 -- Set a nice default size (so that 4 normal sized elements fit next to eachother)
Zerotorescue@0 254 AceConfigDialog:SetDefaultSize("InventoryOptions", 975, 600);
Zerotorescue@0 255
Zerotorescue@0 256 -- In case the addon is loaded from another condition, always call the remove interface options
Zerotorescue@0 257 if AddonLoader and AddonLoader.RemoveInterfaceOptions then
Zerotorescue@0 258 AddonLoader:RemoveInterfaceOptions("Inventory");
Zerotorescue@0 259 end
Zerotorescue@0 260
Zerotorescue@0 261 -- Add to the blizzard addons options thing
Zerotorescue@0 262 --AceConfigDialog:AddToBlizOptions("InventoryOptions");
Zerotorescue@0 263 end
Zerotorescue@0 264 end
Zerotorescue@0 265
Zerotorescue@0 266 function addon:Show()
Zerotorescue@0 267 self:Load();
Zerotorescue@0 268
Zerotorescue@0 269 AceConfigDialog:Open("InventoryOptions");
Zerotorescue@0 270 end
Zerotorescue@0 271
Zerotorescue@0 272 function addon:FillOptions()
Zerotorescue@0 273 options = {
Zerotorescue@0 274 type = "group",
Zerotorescue@0 275 name = "Inventory",
Zerotorescue@0 276 childGroups = "tree",
Zerotorescue@0 277 args = {
Zerotorescue@0 278 },
Zerotorescue@0 279 };
Zerotorescue@0 280
Zerotorescue@0 281 self:FillGeneralOptions();
Zerotorescue@0 282
Zerotorescue@0 283 options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db, true);
Zerotorescue@0 284 options.args.profiles.order = 200;
Zerotorescue@0 285
Zerotorescue@0 286 self:MakeGroupOptions();
Zerotorescue@0 287
Zerotorescue@0 288 self:FillGroupOptions();
Zerotorescue@0 289 end
Zerotorescue@0 290
Zerotorescue@0 291 function addon:FillGeneralOptions()
Zerotorescue@0 292 options.args.general = {
Zerotorescue@0 293 order = 100,
Zerotorescue@0 294 type = "group",
Zerotorescue@0 295 name = "General",
Zerotorescue@0 296 desc = "Change general Inventory settings.",
Zerotorescue@0 297 args = {
Zerotorescue@0 298 general = {
Zerotorescue@0 299 order = 0,
Zerotorescue@0 300 type = "group",
Zerotorescue@0 301 inline = true,
Zerotorescue@0 302 name = "General",
Zerotorescue@0 303 args = {
Zerotorescue@0 304 description = {
Zerotorescue@0 305 order = 0,
Zerotorescue@0 306 type = "description",
Zerotorescue@0 307 name = "Change general settings unrelated to groups.",
Zerotorescue@0 308 },
Zerotorescue@0 309 header = {
Zerotorescue@0 310 order = 5,
Zerotorescue@0 311 type = "header",
Zerotorescue@0 312 name = "",
Zerotorescue@0 313 },
Zerotorescue@0 314 auctionAddon = {
Zerotorescue@0 315 order = 10,
Zerotorescue@0 316 type = "select",
Zerotorescue@0 317 name = "Prefered pricing addon",
Zerotorescue@0 318 values = {
Zerotorescue@0 319 Auctioneer = "Auctioneer",
Zerotorescue@0 320 Auctionator = "Auctionator",
Zerotorescue@0 321 },
Zerotorescue@0 322 get = function() end,
Zerotorescue@0 323 set = function(i, v) end,
Zerotorescue@0 324 },
Zerotorescue@0 325 itemCountAddon = {
Zerotorescue@0 326 order = 20,
Zerotorescue@0 327 type = "select",
Zerotorescue@0 328 name = "Prefered item count addon",
Zerotorescue@0 329 values = {
Zerotorescue@0 330 Altoholic = "Altoholic",
Zerotorescue@0 331 DataStore = "DataStore",
Zerotorescue@0 332 ItemCount = "ItemCount",
Zerotorescue@0 333 },
Zerotorescue@0 334 get = function() end,
Zerotorescue@0 335 set = function(i, v) end,
Zerotorescue@0 336 },
Zerotorescue@0 337 },
Zerotorescue@0 338 },
Zerotorescue@0 339 minimumStock = {
Zerotorescue@0 340 order = 10,
Zerotorescue@0 341 type = "group",
Zerotorescue@0 342 inline = true,
Zerotorescue@0 343 name = "Minimum stock",
Zerotorescue@0 344 args = {
Zerotorescue@0 345 description = {
Zerotorescue@0 346 order = 0,
Zerotorescue@0 347 type = "description",
Zerotorescue@0 348 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 349 },
Zerotorescue@0 350 header = {
Zerotorescue@0 351 order = 5,
Zerotorescue@0 352 type = "header",
Zerotorescue@0 353 name = "",
Zerotorescue@0 354 },
Zerotorescue@0 355 minimumStock = {
Zerotorescue@0 356 order = 10,
Zerotorescue@0 357 type = "range",
Zerotorescue@0 358 min = 0,
Zerotorescue@0 359 max = 100000,
Zerotorescue@0 360 softMax = 1000,
Zerotorescue@0 361 step = 1,
Zerotorescue@0 362 name = "Minimum stock",
Zerotorescue@0 363 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 364 get = function() return self.db.global.defaults.minimumStock; end,
Zerotorescue@0 365 set = function(i, v) self.db.global.defaults.minimumStock = v; end,
Zerotorescue@0 366 },
Zerotorescue@0 367 summaryThresholdShow = {
Zerotorescue@0 368 order = 20,
Zerotorescue@0 369 type = "range",
Zerotorescue@0 370 min = 0,
Zerotorescue@0 371 max = 100,
Zerotorescue@0 372 softMax = 10,
Zerotorescue@0 373 step = 0.05,
Zerotorescue@0 374 isPercent = true,
Zerotorescue@0 375 name = "Show in summary when below",
Zerotorescue@0 376 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 377 get = function() return self.db.global.defaults.summaryThresholdShow; end,
Zerotorescue@0 378 set = function(i, v) self.db.global.defaults.summaryThresholdShow = v; end,
Zerotorescue@0 379 },
Zerotorescue@0 380 alertBelowMinimum = {
Zerotorescue@0 381 order = 30,
Zerotorescue@0 382 type = "toggle",
Zerotorescue@0 383 name = "Alert when below minimum",
Zerotorescue@0 384 desc = "Show an alert when this item gets below this threshold.",
Zerotorescue@0 385 get = function() return self.db.global.defaults.alertBelowMinimum; end,
Zerotorescue@0 386 set = function(i, v) self.db.global.defaults.alertBelowMinimum = v; end,
Zerotorescue@0 387 },
Zerotorescue@0 388 trackAtCharacters = {
Zerotorescue@0 389 order = 40,
Zerotorescue@0 390 type = "multiselect",
Zerotorescue@0 391 control = "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 392 name = "Track at",
Zerotorescue@0 393 desc = "Select at which characters this should appear in the summary and generate alerts.",
Zerotorescue@0 394 values = function()
Zerotorescue@0 395 local temp = {};
Zerotorescue@0 396 for charName in pairs(self.db.factionrealm.characters) do
Zerotorescue@0 397 temp[charName] = charName;
Zerotorescue@0 398 end
Zerotorescue@0 399
Zerotorescue@0 400 return temp;
Zerotorescue@0 401 end,
Zerotorescue@0 402 get = function(i, v)
Zerotorescue@0 403 return self.db.global.defaults.trackAtCharacters[v];
Zerotorescue@0 404 end,
Zerotorescue@0 405 set = function(i, v, e)
Zerotorescue@0 406 self.db.global.defaults.trackAtCharacters[v] = e or nil;
Zerotorescue@0 407 end,
Zerotorescue@0 408 },
Zerotorescue@0 409 },
Zerotorescue@0 410 },
Zerotorescue@0 411 refill = {
Zerotorescue@0 412 order = 20,
Zerotorescue@0 413 type = "group",
Zerotorescue@0 414 inline = true,
Zerotorescue@0 415 name = "Replenishing stock",
Zerotorescue@0 416 args = {
Zerotorescue@0 417 description = {
Zerotorescue@0 418 order = 0,
Zerotorescue@0 419 type = "description",
Zerotorescue@0 420 name = function()
Zerotorescue@0 421 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 422
Zerotorescue@0 423 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 424
Zerotorescue@0 425 return r;
Zerotorescue@0 426 end,
Zerotorescue@0 427 },
Zerotorescue@0 428 header = {
Zerotorescue@0 429 order = 5,
Zerotorescue@0 430 type = "header",
Zerotorescue@0 431 name = "",
Zerotorescue@0 432 },
Zerotorescue@0 433 restockTarget = {
Zerotorescue@0 434 order = 10,
Zerotorescue@0 435 type = "range",
Zerotorescue@0 436 min = 0,
Zerotorescue@0 437 max = 100000,
Zerotorescue@0 438 softMax = 1000,
Zerotorescue@0 439 step = 1,
Zerotorescue@0 440 name = "Restock target",
Zerotorescue@0 441 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 442 get = function() return self.db.global.defaults.restockTarget; end,
Zerotorescue@0 443 set = function(i, v) self.db.global.defaults.restockTarget = v; end,
Zerotorescue@0 444 },
Zerotorescue@0 445 minCraftingQueue = {
Zerotorescue@0 446 order = 20,
Zerotorescue@0 447 type = "range",
Zerotorescue@0 448 min = 0,
Zerotorescue@0 449 max = 1,
Zerotorescue@0 450 step = 0.01, -- 1%
Zerotorescue@0 451 isPercent = true,
Zerotorescue@0 452 name = "Don't queue if I only miss",
Zerotorescue@0 453 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 454 get = function() return self.db.global.defaults.minCraftingQueue; end,
Zerotorescue@0 455 set = function(i, v) self.db.global.defaults.minCraftingQueue = v; end,
Zerotorescue@0 456 },
Zerotorescue@0 457 bonusQueue = {
Zerotorescue@0 458 order = 30,
Zerotorescue@0 459 type = "range",
Zerotorescue@0 460 min = 0,
Zerotorescue@0 461 max = 10, -- 1000%
Zerotorescue@0 462 step = 0.01, -- 1%
Zerotorescue@0 463 isPercent = true,
Zerotorescue@0 464 name = "Bonus queue",
Zerotorescue@0 465 desc = "Get additional items when I have 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.",
Zerotorescue@0 466 get = function() return self.db.global.defaults.bonusQueue; end,
Zerotorescue@0 467 set = function(i, v) self.db.global.defaults.bonusQueue = v; end,
Zerotorescue@0 468 },
Zerotorescue@0 469 priceThreshold = {
Zerotorescue@0 470 order = 40,
Zerotorescue@0 471 type = "input",
Zerotorescue@0 472 name = "Price threshold",
Zerotorescue@0 473 desc = "Only queue craftable items when they are worth at least this much according to your auction house addon.",
Zerotorescue@0 474 validate = function()
Zerotorescue@0 475 -- gold check
Zerotorescue@0 476 end,
Zerotorescue@0 477 get = function() return self.db.global.defaults.priceThreshold; end,
Zerotorescue@0 478 set = function(i, v) self.db.global.defaults.priceThreshold = v; end,
Zerotorescue@0 479 },
Zerotorescue@0 480 hideFromSummaryPriceThreshold = {
Zerotorescue@0 481 order = 50,
Zerotorescue@0 482 type = "toggle",
Zerotorescue@0 483 name = "Don't show when below threshold",
Zerotorescue@0 484 desc = "Hide items from the summary when their value is below the set price threshold.",
Zerotorescue@0 485 },
Zerotorescue@0 486 },
Zerotorescue@0 487 },
Zerotorescue@0 488 colorCodes = {
Zerotorescue@0 489 order = 30,
Zerotorescue@0 490 type = "group",
Zerotorescue@0 491 inline = true,
Zerotorescue@0 492 name = "Color codes",
Zerotorescue@0 493 args = {
Zerotorescue@0 494 description = {
Zerotorescue@0 495 order = 0,
Zerotorescue@0 496 type = "description",
Zerotorescue@0 497 name = "Change the color code thresholds based on the current stock remaining of the required minimum stock.",
Zerotorescue@0 498 },
Zerotorescue@0 499 header = {
Zerotorescue@0 500 order = 5,
Zerotorescue@0 501 type = "header",
Zerotorescue@0 502 name = "",
Zerotorescue@0 503 },
Zerotorescue@0 504 green = {
Zerotorescue@0 505 order = 10,
Zerotorescue@0 506 type = "range",
Zerotorescue@0 507 min = 0,
Zerotorescue@0 508 max = 1,
Zerotorescue@0 509 step = 0.01,
Zerotorescue@0 510 isPercent = true,
Zerotorescue@0 511 name = "|cff00ff00Green|r",
Zerotorescue@0 512 desc = "Show quantity in green when at least this much of the minimum stock is available.",
Zerotorescue@0 513 get = function() return self.db.global.defaults.colors.green; end,
Zerotorescue@0 514 set = function(i, v) self.db.global.defaults.colors.green = v; end,
Zerotorescue@0 515 },
Zerotorescue@0 516 yellow = {
Zerotorescue@0 517 order = 20,
Zerotorescue@0 518 type = "range",
Zerotorescue@0 519 min = 0,
Zerotorescue@0 520 max = 1,
Zerotorescue@0 521 step = 0.01,
Zerotorescue@0 522 isPercent = true,
Zerotorescue@0 523 name = "|cffffff00Yellow|r",
Zerotorescue@0 524 desc = "Show quantity in yellow when at least this much of the minimum stock is available.",
Zerotorescue@0 525 get = function() return self.db.global.defaults.colors.yellow; end,
Zerotorescue@0 526 set = function(i, v) self.db.global.defaults.colors.yellow = v; end,
Zerotorescue@0 527 },
Zerotorescue@0 528 orange = {
Zerotorescue@0 529 order = 30,
Zerotorescue@0 530 type = "range",
Zerotorescue@0 531 min = 0,
Zerotorescue@0 532 max = 1,
Zerotorescue@0 533 step = 0.01,
Zerotorescue@0 534 isPercent = true,
Zerotorescue@0 535 name = "|cffff9933Orange|r",
Zerotorescue@0 536 desc = "Show quantity in orange when at least this much of the minimum stock is available.",
Zerotorescue@0 537 get = function() return self.db.global.defaults.colors.orange; end,
Zerotorescue@0 538 set = function(i, v) self.db.global.defaults.colors.orange = v; end,
Zerotorescue@0 539 },
Zerotorescue@0 540 red = {
Zerotorescue@0 541 order = 40,
Zerotorescue@0 542 type = "range",
Zerotorescue@0 543 min = 0,
Zerotorescue@0 544 max = 1,
Zerotorescue@0 545 step = 0.01,
Zerotorescue@0 546 isPercent = true,
Zerotorescue@0 547 name = "|cffff0000Red|r",
Zerotorescue@0 548 desc = "Show quantity in red when at least this much of the minimum stock is available.",
Zerotorescue@0 549 get = function() return self.db.global.defaults.colors.red; end,
Zerotorescue@0 550 set = function(i, v) self.db.global.defaults.colors.red = v; end,
Zerotorescue@0 551 },
Zerotorescue@0 552 },
Zerotorescue@0 553 },
Zerotorescue@0 554 },
Zerotorescue@0 555 };
Zerotorescue@0 556 end
Zerotorescue@0 557
Zerotorescue@0 558 local count = 0;
Zerotorescue@0 559 local temp = {};
Zerotorescue@0 560
Zerotorescue@0 561 local function SetOption(info, value)
Zerotorescue@0 562 local groupName = groupIdToName[info[2]];
Zerotorescue@0 563 local optionName = info[#info];
Zerotorescue@0 564
Zerotorescue@0 565 -- No need to store a setting if it's disabled (false)
Zerotorescue@0 566 if not value and info.arg and not info.arg:find("override") then
Zerotorescue@0 567 value = nil;
Zerotorescue@0 568
Zerotorescue@0 569 -- If this is an override toggler then also set the related field to nil
Zerotorescue@0 570 addon.db.global.groups[groupName][info.arg] = nil;
Zerotorescue@0 571 end
Zerotorescue@0 572
Zerotorescue@0 573 addon.db.global.groups[groupName][optionName] = value;
Zerotorescue@0 574 end
Zerotorescue@0 575
Zerotorescue@0 576 local function GetOptionByKey(groupName, optionName, noDefault)
Zerotorescue@0 577 if addon.db.global.groups[groupName][optionName] ~= nil then
Zerotorescue@0 578 return addon.db.global.groups[groupName][optionName];
Zerotorescue@0 579 elseif addon.db.global.defaults[optionName] and not noDefault then
Zerotorescue@0 580 return addon.db.global.defaults[optionName];
Zerotorescue@0 581 else
Zerotorescue@0 582 return nil;
Zerotorescue@0 583 end
Zerotorescue@0 584 end
Zerotorescue@0 585
Zerotorescue@0 586 local function GetOption(info)
Zerotorescue@0 587 local groupName = groupIdToName[info[2]];
Zerotorescue@0 588 local optionName = info[#info];
Zerotorescue@0 589
Zerotorescue@0 590 return GetOptionByKey(groupName, optionName);
Zerotorescue@0 591 end
Zerotorescue@0 592
Zerotorescue@0 593 local function GetDisabled(info)
Zerotorescue@0 594 if not info.arg or not info.arg:find("override") then
Zerotorescue@0 595 return false;
Zerotorescue@0 596 end
Zerotorescue@0 597
Zerotorescue@0 598 local groupName = groupIdToName[info[2]];
Zerotorescue@0 599 local optionName = info[#info];
Zerotorescue@0 600
Zerotorescue@0 601 return (GetOptionByKey(groupName, info.arg, true) == nil);
Zerotorescue@0 602 end
Zerotorescue@0 603
Zerotorescue@0 604 local function ValidateGroupName(_, value)
Zerotorescue@0 605 value = string.lower(string.trim(value or ""));
Zerotorescue@0 606
Zerotorescue@0 607 for name, _ in pairs(addon.db.global.groups) do
Zerotorescue@0 608 if string.lower(name) == value then
Zerotorescue@0 609 return ("A group named \"%s\" already exists."):format(name);
Zerotorescue@0 610 end
Zerotorescue@0 611 end
Zerotorescue@0 612
Zerotorescue@0 613 return true;
Zerotorescue@0 614 end
Zerotorescue@0 615
Zerotorescue@0 616 local function InGroup(itemId)
Zerotorescue@0 617 -- Go through all groups to see if this item is already somewhere
Zerotorescue@0 618 for groupName, values in pairs(addon.db.global.groups) do
Zerotorescue@0 619 if values.items and values.items[itemId] then
Zerotorescue@0 620 return groupName;
Zerotorescue@0 621 end
Zerotorescue@0 622 end
Zerotorescue@0 623
Zerotorescue@0 624 return;
Zerotorescue@0 625 end
Zerotorescue@0 626
Zerotorescue@0 627 local function AddToGroup(groupName, itemId)
Zerotorescue@0 628 if InGroup(itemId) then
Zerotorescue@0 629 return false;
Zerotorescue@0 630 end
Zerotorescue@0 631
Zerotorescue@0 632 if not addon.db.global.groups[groupName].items then
Zerotorescue@0 633 addon.db.global.groups[groupName].items = {};
Zerotorescue@0 634 end
Zerotorescue@0 635
Zerotorescue@0 636 -- Set this item
Zerotorescue@0 637 addon.db.global.groups[groupName].items[itemId] = true;
Zerotorescue@0 638
Zerotorescue@0 639 -- Now rebuild the list
Zerotorescue@0 640 AceConfigRegistry:NotifyChange("InventoryOptions");
Zerotorescue@0 641
Zerotorescue@0 642 return true;
Zerotorescue@0 643 end
Zerotorescue@0 644
Zerotorescue@0 645 local tblAddItemTemplate = {
Zerotorescue@0 646 order = 0,
Zerotorescue@0 647 type = "input",
Zerotorescue@0 648 name = function(info)
Zerotorescue@0 649 local itemName, _, itemRarity = GetItemInfo(info[#info]);
Zerotorescue@0 650 return tostring( 7 - (itemRarity or 0) ) .. (itemName or "");
Zerotorescue@0 651 end,
Zerotorescue@0 652 get = function(info)
Zerotorescue@0 653 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 654 end,
Zerotorescue@0 655 set = function(widget, info)
Zerotorescue@0 656 -- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info.
Zerotorescue@0 657
Zerotorescue@0 658 if widget.itemId then
Zerotorescue@0 659 local groupName = groupIdToName[info[2]];
Zerotorescue@0 660
Zerotorescue@0 661 if not AddToGroup(groupName, widget.itemId) then
Zerotorescue@0 662 print("|cffff0000Couldn't add the item with itemId (" .. widget.itemId .. ") because it is already in a group.|r");
Zerotorescue@0 663 end
Zerotorescue@0 664 end
Zerotorescue@0 665 end,
Zerotorescue@0 666 width = "double",
Zerotorescue@0 667 dialogControl = "ItemLinkButton",
Zerotorescue@0 668 };
Zerotorescue@0 669
Zerotorescue@0 670 local tblRemoveItemTemplate = {
Zerotorescue@0 671 order = 0,
Zerotorescue@0 672 type = "input",
Zerotorescue@0 673 name = function(info)
Zerotorescue@0 674 local itemName, _, itemRarity = GetItemInfo(info[#info]);
Zerotorescue@0 675 return tostring( 7 - (itemRarity or 0) ) .. (itemName or "");
Zerotorescue@0 676 end,
Zerotorescue@0 677 get = function(info)
Zerotorescue@0 678 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 679 end,
Zerotorescue@0 680 set = function(widget, info)
Zerotorescue@0 681 -- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info.
Zerotorescue@0 682
Zerotorescue@0 683 if widget.itemId then
Zerotorescue@0 684 local groupName = groupIdToName[info[2]];
Zerotorescue@0 685
Zerotorescue@0 686 -- Unset this item
Zerotorescue@0 687 addon.db.global.groups[groupName].items[widget.itemId] = nil;
Zerotorescue@0 688
Zerotorescue@0 689 -- Now rebuild the list
Zerotorescue@0 690 AceConfigRegistry:NotifyChange("InventoryOptions");
Zerotorescue@0 691 end
Zerotorescue@0 692 end,
Zerotorescue@0 693 width = "double",
Zerotorescue@0 694 dialogControl = "ItemLinkButton",
Zerotorescue@0 695 };
Zerotorescue@0 696
Zerotorescue@0 697 local function UpdateAddItemList(info)
Zerotorescue@0 698 local groupName = groupIdToName[info[2]];
Zerotorescue@0 699
Zerotorescue@0 700 if not addon.db.global.groups[groupName].items then
Zerotorescue@0 701 addon.db.global.groups[groupName].items = {};
Zerotorescue@0 702 end
Zerotorescue@0 703
Zerotorescue@0 704 -- Merge all items from all groups together
Zerotorescue@0 705 local items = {};
Zerotorescue@0 706 for groupName, values in pairs(addon.db.global.groups) do
Zerotorescue@0 707 if values.items then
Zerotorescue@0 708 for itemId, _ in pairs(values.items) do
Zerotorescue@0 709 items[itemId] = true;
Zerotorescue@0 710 end
Zerotorescue@0 711 end
Zerotorescue@0 712 end
Zerotorescue@0 713
Zerotorescue@0 714 local ref = options.args.groups.args[info[2]].args.add.args.list.args;
Zerotorescue@0 715
Zerotorescue@0 716 -- Parse bags and show these
Zerotorescue@0 717 for bagID = 4, 0, -1 do
Zerotorescue@0 718 for slot = 1, GetContainerNumSlots(bagID) do
Zerotorescue@0 719 local itemId = addon:GetItemId(GetContainerItemLink(bagID, slot));
Zerotorescue@0 720
Zerotorescue@0 721 if itemId then
Zerotorescue@0 722 if not items[itemId] then
Zerotorescue@0 723 -- If this item isn't used in any group yet
Zerotorescue@0 724 ref[itemId] = tblAddItemTemplate;
Zerotorescue@0 725 else
Zerotorescue@0 726 -- It's already used in a group, don't show it
Zerotorescue@0 727 ref[itemId] = nil;
Zerotorescue@0 728 end
Zerotorescue@0 729 end
Zerotorescue@0 730 end
Zerotorescue@0 731 end
Zerotorescue@0 732 end
Zerotorescue@0 733
Zerotorescue@0 734 local function UpdateRemoveItemList(info)
Zerotorescue@0 735 local groupName = groupIdToName[info[2]];
Zerotorescue@0 736
Zerotorescue@0 737 if not addon.db.global.groups[groupName].items then
Zerotorescue@0 738 addon.db.global.groups[groupName].items = {};
Zerotorescue@0 739 end
Zerotorescue@0 740
Zerotorescue@0 741 local ref = options.args.groups.args[info[2]].args.remove.args.list.args;
Zerotorescue@0 742
Zerotorescue@0 743 -- Unset all
Zerotorescue@0 744 for itemId, _ in pairs(ref) do
Zerotorescue@0 745 ref[itemId] = nil;
Zerotorescue@0 746 end
Zerotorescue@0 747
Zerotorescue@0 748 -- Parse items in group and show these
Zerotorescue@0 749 for itemId, _ in pairs(addon.db.global.groups[groupName].items) do
Zerotorescue@0 750 ref[itemId] = tblRemoveItemTemplate;
Zerotorescue@0 751 end
Zerotorescue@0 752 end
Zerotorescue@0 753
Zerotorescue@0 754 function addon:GetItemId(itemLink)
Zerotorescue@0 755 itemLink = itemLink and select(3, string.find(itemLink, "|Hitem:([-0-9]+):")); -- if itemLink is nil, it won't execute the second part
Zerotorescue@0 756 itemLink = itemLink and tonumber(itemLink);
Zerotorescue@0 757
Zerotorescue@0 758 return itemLink;
Zerotorescue@0 759 end
Zerotorescue@0 760
Zerotorescue@0 761 -- Default group
Zerotorescue@0 762 local defaultGroup = {
Zerotorescue@0 763 order = 0,
Zerotorescue@0 764 type = "group",
Zerotorescue@0 765 childGroups = "tab",
Zerotorescue@0 766 name = function(info)
Zerotorescue@0 767 return groupIdToName[info[#info]];
Zerotorescue@0 768 end,
Zerotorescue@0 769 args = {
Zerotorescue@0 770 general = {
Zerotorescue@0 771 order = 10,
Zerotorescue@0 772 type = "group",
Zerotorescue@0 773 name = "Stock settings",
Zerotorescue@0 774 desc = "Change the stock settings for just this group.",
Zerotorescue@0 775 args = {
Zerotorescue@0 776 minimumStock = {
Zerotorescue@0 777 order = 10,
Zerotorescue@0 778 type = "group",
Zerotorescue@0 779 inline = true,
Zerotorescue@0 780 name = "Minimum stock",
Zerotorescue@0 781 set = SetOption,
Zerotorescue@0 782 get = GetOption,
Zerotorescue@0 783 disabled = GetDisabled,
Zerotorescue@0 784 args = {
Zerotorescue@0 785 description = {
Zerotorescue@0 786 order = 0,
Zerotorescue@0 787 type = "description",
Zerotorescue@0 788 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 789 },
Zerotorescue@0 790 header = {
Zerotorescue@0 791 order = 5,
Zerotorescue@0 792 type = "header",
Zerotorescue@0 793 name = "",
Zerotorescue@0 794 },
Zerotorescue@0 795 overrideMinimumStock = {
Zerotorescue@0 796 order = 9,
Zerotorescue@0 797 type = "toggle",
Zerotorescue@0 798 name = "Override min stock",
Zerotorescue@0 799 desc = "Allows you to override the minimum stock setting for this group.",
Zerotorescue@0 800 arg = "minimumStock",
Zerotorescue@0 801 },
Zerotorescue@0 802 minimumStock = {
Zerotorescue@0 803 order = 10,
Zerotorescue@0 804 type = "range",
Zerotorescue@0 805 min = 0,
Zerotorescue@0 806 max = 100000,
Zerotorescue@0 807 softMax = 1000,
Zerotorescue@0 808 step = 1,
Zerotorescue@0 809 name = "Minimum stock",
Zerotorescue@0 810 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 811 arg = "overrideMinimumStock",
Zerotorescue@0 812 },
Zerotorescue@0 813 overrideSummaryThresholdShow = {
Zerotorescue@0 814 order = 19,
Zerotorescue@0 815 type = "toggle",
Zerotorescue@0 816 name = "Override summary showing",
Zerotorescue@0 817 desc = "Allows you to override when this group should appear in the summary.",
Zerotorescue@0 818 arg = "summaryThresholdShow",
Zerotorescue@0 819 },
Zerotorescue@0 820 summaryThresholdShow = {
Zerotorescue@0 821 order = 20,
Zerotorescue@0 822 type = "range",
Zerotorescue@0 823 min = 0,
Zerotorescue@0 824 max = 100,
Zerotorescue@0 825 softMax = 10,
Zerotorescue@0 826 step = 0.05,
Zerotorescue@0 827 isPercent = true,
Zerotorescue@0 828 name = "Show in summary when below",
Zerotorescue@0 829 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 830 arg = "overrideSummaryThresholdShow",
Zerotorescue@0 831 },
Zerotorescue@0 832 overrideAlertBelowMinimum = {
Zerotorescue@0 833 order = 29,
Zerotorescue@0 834 type = "toggle",
Zerotorescue@0 835 name = "Override minimum alert",
Zerotorescue@0 836 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 837 arg = "alertBelowMinimum",
Zerotorescue@0 838 },
Zerotorescue@0 839 alertBelowMinimum = {
Zerotorescue@0 840 order = 30,
Zerotorescue@0 841 type = "toggle",
Zerotorescue@0 842 name = "Alert when below minimum",
Zerotorescue@0 843 desc = "Show an alert when an item in this group gets below the minimum stock threshold.",
Zerotorescue@0 844 arg = "overrideAlertBelowMinimum",
Zerotorescue@0 845 },
Zerotorescue@0 846 },
Zerotorescue@0 847 },
Zerotorescue@0 848 refill = {
Zerotorescue@0 849 order = 20,
Zerotorescue@0 850 type = "group",
Zerotorescue@0 851 inline = true,
Zerotorescue@0 852 name = "Replenishing stock",
Zerotorescue@0 853 set = SetOption,
Zerotorescue@0 854 get = GetOption,
Zerotorescue@0 855 disabled = GetDisabled,
Zerotorescue@0 856 args = {
Zerotorescue@0 857 description = {
Zerotorescue@0 858 order = 0,
Zerotorescue@0 859 type = "description",
Zerotorescue@0 860 name = function(info)
Zerotorescue@0 861 local groupName = groupIdToName[info[2]];
Zerotorescue@0 862 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 863
Zerotorescue@0 864 r = r .. "When restocking the target amount is |cfffed000" .. GetOptionByKey(groupName, "restockTarget") .. "|r of every item. Not queueing craftable items when only missing |cfffed000" .. floor( GetOptionByKey(groupName, "minCraftingQueue") * GetOptionByKey(groupName, "restockTarget") ) .. "|r (|cfffed000" .. ( GetOptionByKey(groupName, "minCraftingQueue") * 100 ) .. "%|r) of the restock target.";
Zerotorescue@0 865
Zerotorescue@0 866 return r;
Zerotorescue@0 867 end,
Zerotorescue@0 868 },
Zerotorescue@0 869 header = {
Zerotorescue@0 870 order = 5,
Zerotorescue@0 871 type = "header",
Zerotorescue@0 872 name = "",
Zerotorescue@0 873 },
Zerotorescue@0 874 overrideRestockTarget = {
Zerotorescue@0 875 order = 9,
Zerotorescue@0 876 type = "toggle",
Zerotorescue@0 877 name = "Override restock target",
Zerotorescue@0 878 desc = "Allows you to override the restock target setting for this group.",
Zerotorescue@0 879 arg = "restockTarget",
Zerotorescue@0 880 },
Zerotorescue@0 881 restockTarget = {
Zerotorescue@0 882 order = 10,
Zerotorescue@0 883 type = "range",
Zerotorescue@0 884 min = 0,
Zerotorescue@0 885 max = 100000,
Zerotorescue@0 886 softMax = 1000,
Zerotorescue@0 887 step = 1,
Zerotorescue@0 888 name = "Restock target",
Zerotorescue@0 889 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 890 arg = "overrideRestockTarget",
Zerotorescue@0 891 },
Zerotorescue@0 892 overrideMinCraftingQueue = {
Zerotorescue@0 893 order = 19,
Zerotorescue@0 894 type = "toggle",
Zerotorescue@0 895 name = "Override min queue",
Zerotorescue@0 896 desc = "Allows you to override the minimum craftable items queue setting for this group.",
Zerotorescue@0 897 arg = "minCraftingQueue",
Zerotorescue@0 898 },
Zerotorescue@0 899 minCraftingQueue = {
Zerotorescue@0 900 order = 20,
Zerotorescue@0 901 type = "range",
Zerotorescue@0 902 min = 0,
Zerotorescue@0 903 max = 1,
Zerotorescue@0 904 step = 0.01,
Zerotorescue@0 905 isPercent = true,
Zerotorescue@0 906 name = "Don't queue if I only miss",
Zerotorescue@0 907 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 908 arg = "overrideMinCraftingQueue",
Zerotorescue@0 909 },
Zerotorescue@0 910 },
Zerotorescue@0 911 },
Zerotorescue@0 912 },
Zerotorescue@0 913 },
Zerotorescue@0 914 group = {
Zerotorescue@0 915 order = 20,
Zerotorescue@0 916 type = "group",
Zerotorescue@0 917 name = "Group Management",
Zerotorescue@0 918 desc = "Rename, delete or export this group.",
Zerotorescue@0 919 args = {
Zerotorescue@0 920 rename = {
Zerotorescue@0 921 order = 10,
Zerotorescue@0 922 type = "group",
Zerotorescue@0 923 name = "Rename",
Zerotorescue@0 924 inline = true,
Zerotorescue@0 925 args = {
Zerotorescue@0 926 rename = {
Zerotorescue@0 927 order = 10,
Zerotorescue@0 928 type = "input",
Zerotorescue@0 929 name = "New group name",
Zerotorescue@0 930 desc = "Change the name of this group to something else. You can also use item links here as you wish.",
Zerotorescue@0 931 validate = ValidateGroupName,
Zerotorescue@0 932 set = function(info, value)
Zerotorescue@0 933 local oldGroupName = groupIdToName[info[2]];
Zerotorescue@0 934
Zerotorescue@0 935 addon.db.global.groups[value] = CopyTable(addon.db.global.groups[oldGroupName]);
Zerotorescue@0 936 addon.db.global.groups[oldGroupName] = nil;
Zerotorescue@0 937
Zerotorescue@0 938 groupIdToName[info[2]] = value;
Zerotorescue@0 939 groupIdToName[value] = true;
Zerotorescue@0 940 groupIdToName[oldGroupName] = nil;
Zerotorescue@0 941
Zerotorescue@0 942 addon:FillGroupOptions();
Zerotorescue@0 943 end,
Zerotorescue@0 944 get = function(info)
Zerotorescue@0 945 return groupIdToName[info[2]];
Zerotorescue@0 946 end,
Zerotorescue@0 947 width = "double",
Zerotorescue@0 948 },
Zerotorescue@0 949 },
Zerotorescue@0 950 },
Zerotorescue@0 951 delete = {
Zerotorescue@0 952 order = 20,
Zerotorescue@0 953 type = "group",
Zerotorescue@0 954 name = "Delete",
Zerotorescue@0 955 inline = true,
Zerotorescue@0 956 args = {
Zerotorescue@0 957 delete = {
Zerotorescue@0 958 order = 10,
Zerotorescue@0 959 type = "execute",
Zerotorescue@0 960 name = "Delete group",
Zerotorescue@0 961 desc = "Delete the currently selected group.",
Zerotorescue@0 962 confirm = true,
Zerotorescue@0 963 confirmText = "Are you sure you wish to |cffff0000DELETE|r this group? This action is not reversable!",
Zerotorescue@0 964 func = function(info)
Zerotorescue@0 965 local groupName = groupIdToName[info[2]];
Zerotorescue@0 966
Zerotorescue@0 967 addon.db.global.groups[groupName] = nil;
Zerotorescue@0 968
Zerotorescue@0 969 addon:FillGroupOptions();
Zerotorescue@0 970 end,
Zerotorescue@0 971 },
Zerotorescue@0 972 },
Zerotorescue@0 973 },
Zerotorescue@0 974 export = {
Zerotorescue@0 975 order = 30,
Zerotorescue@0 976 type = "group",
Zerotorescue@0 977 name = "Export",
Zerotorescue@0 978 inline = true,
Zerotorescue@0 979 args = {
Zerotorescue@0 980 input = {
Zerotorescue@0 981 order = 10,
Zerotorescue@0 982 type = "input",
Zerotorescue@0 983 multiline = true,
Zerotorescue@0 984 name = "Group data",
Zerotorescue@0 985 width = "full",
Zerotorescue@0 986 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 987 set = false,
Zerotorescue@0 988 get = function(info)
Zerotorescue@0 989 local groupName = groupIdToName[info[2]];
Zerotorescue@0 990
Zerotorescue@0 991 -- We want to include the group name, so we copy the table then set another value
Zerotorescue@0 992 local temp = CopyTable(addon.db.global.groups[groupName]);
Zerotorescue@0 993 temp.name = groupName;
Zerotorescue@0 994
Zerotorescue@0 995 if not AceSerializer then
Zerotorescue@0 996 AceSerializer = LibStub("AceSerializer-3.0");
Zerotorescue@0 997 end
Zerotorescue@0 998
Zerotorescue@0 999 return AceSerializer:Serialize(temp);
Zerotorescue@0 1000 end,
Zerotorescue@0 1001 },
Zerotorescue@0 1002 },
Zerotorescue@0 1003 },
Zerotorescue@0 1004 },
Zerotorescue@0 1005 },
Zerotorescue@0 1006 add = {
Zerotorescue@0 1007 order = 30,
Zerotorescue@0 1008 type = "group",
Zerotorescue@0 1009 name = "Add items",
Zerotorescue@0 1010 args = {
Zerotorescue@0 1011 singleAdd = {
Zerotorescue@0 1012 order = 10,
Zerotorescue@0 1013 type = "group",
Zerotorescue@0 1014 inline = true,
Zerotorescue@0 1015 name = "Add items",
Zerotorescue@0 1016 args = {
Zerotorescue@0 1017 help = {
Zerotorescue@0 1018 order = 10,
Zerotorescue@0 1019 type = "description",
Zerotorescue@0 1020 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 1021 },
Zerotorescue@0 1022 itemLink = {
Zerotorescue@0 1023 order = 20,
Zerotorescue@0 1024 type = "input",
Zerotorescue@0 1025 name = "Single item add (item-link or item-id)",
Zerotorescue@0 1026 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 1027 validate = function(info, value)
Zerotorescue@0 1028 -- If the value is empty we'll allow passing to clear the carret
Zerotorescue@0 1029 if value == "" then return true; end
Zerotorescue@0 1030
Zerotorescue@0 1031 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1032
Zerotorescue@0 1033 local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or ""));
Zerotorescue@0 1034
Zerotorescue@0 1035 if not itemId then
Zerotorescue@0 1036 return "This is not a valid item link.";
Zerotorescue@0 1037 elseif InGroup(itemId) then
Zerotorescue@0 1038 return ("This item is already in the group \"%s\"."):format(InGroup(itemId));
Zerotorescue@0 1039 end
Zerotorescue@0 1040
Zerotorescue@0 1041 return true;
Zerotorescue@0 1042 end,
Zerotorescue@0 1043 set = function(info, value)
Zerotorescue@0 1044 if value and value ~= "" then
Zerotorescue@0 1045 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1046
Zerotorescue@0 1047 local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or ""));
Zerotorescue@0 1048
Zerotorescue@0 1049 AddToGroup(groupName, itemId);
Zerotorescue@0 1050
Zerotorescue@0 1051 print(("Added %s"):format(select(2, GetItemInfo(itemId)) or ("Unknown (#%d)"):format(itemId)));
Zerotorescue@0 1052 end
Zerotorescue@0 1053 end,
Zerotorescue@0 1054 get = false,
Zerotorescue@0 1055 },
Zerotorescue@0 1056 import = {
Zerotorescue@0 1057 order = 40,
Zerotorescue@0 1058 type = "input",
Zerotorescue@0 1059 name = "Import item data",
Zerotorescue@0 1060 desc = "Import item data from an exported item data-string. Any items already grouped will be skipped.",
Zerotorescue@0 1061 set = function(info, value)
Zerotorescue@0 1062 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1063
Zerotorescue@0 1064 local allItemIds = { string.split(";", value or "") };
Zerotorescue@0 1065
Zerotorescue@0 1066 for _, value in pairs(allItemIds) do
Zerotorescue@0 1067 local itemId = tonumber(value);
Zerotorescue@0 1068
Zerotorescue@0 1069 if not itemId then
Zerotorescue@0 1070 print(("\"%s\" is not a number."):format(value));
Zerotorescue@0 1071 elseif InGroup(itemId) then
Zerotorescue@0 1072 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 1073 else
Zerotorescue@0 1074 AddToGroup(groupName, itemId);
Zerotorescue@0 1075 end
Zerotorescue@0 1076 end
Zerotorescue@0 1077 end,
Zerotorescue@0 1078 get = false,
Zerotorescue@0 1079 },
Zerotorescue@0 1080 },
Zerotorescue@0 1081 },
Zerotorescue@0 1082 massAdd = {
Zerotorescue@0 1083 order = 20,
Zerotorescue@0 1084 type = "group",
Zerotorescue@0 1085 inline = true,
Zerotorescue@0 1086 name = "Mass add",
Zerotorescue@0 1087 args = {
Zerotorescue@0 1088 help = {
Zerotorescue@0 1089 order = 10,
Zerotorescue@0 1090 type = "description",
Zerotorescue@0 1091 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 1092 },
Zerotorescue@0 1093 massAdd = {
Zerotorescue@0 1094 order = 20,
Zerotorescue@0 1095 type = "input",
Zerotorescue@0 1096 name = "Add all items matching...",
Zerotorescue@0 1097 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 1098 --set = massAddItems,
Zerotorescue@0 1099 get = false,
Zerotorescue@0 1100 },
Zerotorescue@0 1101 },
Zerotorescue@0 1102 },
Zerotorescue@0 1103 list = {
Zerotorescue@0 1104 order = 30,
Zerotorescue@0 1105 type = "group",
Zerotorescue@0 1106 inline = true,
Zerotorescue@0 1107 name = "Item list",
Zerotorescue@0 1108 hidden = UpdateAddItemList,
Zerotorescue@0 1109 args = {
Zerotorescue@0 1110
Zerotorescue@0 1111 },
Zerotorescue@0 1112 },
Zerotorescue@0 1113 },
Zerotorescue@0 1114 },
Zerotorescue@0 1115 remove = {
Zerotorescue@0 1116 order = 40,
Zerotorescue@0 1117 type = "group",
Zerotorescue@0 1118 name = "Current items",
Zerotorescue@0 1119 args = {
Zerotorescue@0 1120 help = {
Zerotorescue@0 1121 order = 10,
Zerotorescue@0 1122 type = "group",
Zerotorescue@0 1123 inline = true,
Zerotorescue@0 1124 name = "Help",
Zerotorescue@0 1125 hidden = false,
Zerotorescue@0 1126 args = {
Zerotorescue@0 1127 help = {
Zerotorescue@0 1128 order = 10,
Zerotorescue@0 1129 type = "description",
Zerotorescue@0 1130 name = "Click the items you wish to remove from this group.",
Zerotorescue@0 1131 },
Zerotorescue@0 1132 },
Zerotorescue@0 1133 },
Zerotorescue@0 1134 list = {
Zerotorescue@0 1135 order = 20,
Zerotorescue@0 1136 type = "group",
Zerotorescue@0 1137 inline = true,
Zerotorescue@0 1138 name = "Item list",
Zerotorescue@0 1139 hidden = UpdateRemoveItemList,
Zerotorescue@0 1140 args = {
Zerotorescue@0 1141
Zerotorescue@0 1142 },
Zerotorescue@0 1143 },
Zerotorescue@0 1144 export = {
Zerotorescue@0 1145 order = 30,
Zerotorescue@0 1146 type = "group",
Zerotorescue@0 1147 name = "Export",
Zerotorescue@0 1148 inline = true,
Zerotorescue@0 1149 args = {
Zerotorescue@0 1150 input = {
Zerotorescue@0 1151 order = 10,
Zerotorescue@0 1152 type = "input",
Zerotorescue@0 1153 name = "Item data",
Zerotorescue@0 1154 width = "full",
Zerotorescue@0 1155 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 1156 set = false,
Zerotorescue@0 1157 get = function(info)
Zerotorescue@0 1158 local groupName = groupIdToName[info[2]];
Zerotorescue@0 1159
Zerotorescue@0 1160 local combinedItemIds;
Zerotorescue@0 1161 -- Parse items in group and show these
Zerotorescue@0 1162 for itemId, _ in pairs(addon.db.global.groups[groupName].items) do
Zerotorescue@0 1163 if not combinedItemIds then
Zerotorescue@0 1164 combinedItemIds = tostring(itemId);
Zerotorescue@0 1165 else
Zerotorescue@0 1166 combinedItemIds = combinedItemIds .. (";%d"):format(itemId);
Zerotorescue@0 1167 end
Zerotorescue@0 1168 end
Zerotorescue@0 1169
Zerotorescue@0 1170 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 1171 end,
Zerotorescue@0 1172 },
Zerotorescue@0 1173 },
Zerotorescue@0 1174 },
Zerotorescue@0 1175 },
Zerotorescue@0 1176 },
Zerotorescue@0 1177 },
Zerotorescue@0 1178 };
Zerotorescue@0 1179
Zerotorescue@0 1180 function addon:MakeGroupOptions()
Zerotorescue@0 1181 options.args.groups = {
Zerotorescue@0 1182 order = 1100,
Zerotorescue@0 1183 type = "group",
Zerotorescue@0 1184 name = "Groups",
Zerotorescue@0 1185 desc = "Change a group.",
Zerotorescue@0 1186 args = {
Zerotorescue@0 1187 create = {
Zerotorescue@0 1188 order = 10,
Zerotorescue@0 1189 type = "group",
Zerotorescue@0 1190 inline = true,
Zerotorescue@0 1191 name = "Create a brand new group",
Zerotorescue@0 1192 args = {
Zerotorescue@0 1193 name = {
Zerotorescue@0 1194 order = 10,
Zerotorescue@0 1195 type = "input",
Zerotorescue@0 1196 name = "Group name",
Zerotorescue@0 1197 desc = "The name of the group. You can also use item links as you wish.",
Zerotorescue@0 1198 validate = ValidateGroupName,
Zerotorescue@0 1199 set = function(_, value)
Zerotorescue@0 1200 self.db.global.groups[value] = {};
Zerotorescue@0 1201
Zerotorescue@0 1202 addon:FillGroupOptions();
Zerotorescue@0 1203 end,
Zerotorescue@0 1204 get = false,
Zerotorescue@0 1205 width = "double",
Zerotorescue@0 1206 },
Zerotorescue@0 1207 },
Zerotorescue@0 1208 },
Zerotorescue@0 1209 import = {
Zerotorescue@0 1210 order = 20,
Zerotorescue@0 1211 type = "group",
Zerotorescue@0 1212 inline = true,
Zerotorescue@0 1213 name = "Import a group",
Zerotorescue@0 1214 args = {
Zerotorescue@0 1215 input = {
Zerotorescue@0 1216 order = 10,
Zerotorescue@0 1217 type = "input",
Zerotorescue@0 1218 multiline = true,
Zerotorescue@0 1219 name = "Group data",
Zerotorescue@0 1220 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 1221 set = function(info, value)
Zerotorescue@0 1222 local temp = { string.split("\n", value or "") };
Zerotorescue@0 1223
Zerotorescue@0 1224 for no, current in pairs(temp) do
Zerotorescue@0 1225 if not AceSerializer then
Zerotorescue@0 1226 AceSerializer = LibStub("AceSerializer-3.0");
Zerotorescue@0 1227 end
Zerotorescue@0 1228
Zerotorescue@0 1229 local result, temp = AceSerializer:Deserialize(current);
Zerotorescue@0 1230 local name;
Zerotorescue@0 1231
Zerotorescue@0 1232 if not temp.name then
Zerotorescue@0 1233 print("|cffff0000The provided data is not supported.|r");
Zerotorescue@0 1234 return;
Zerotorescue@0 1235 else
Zerotorescue@0 1236 name = temp.name;
Zerotorescue@0 1237 temp.name = nil;
Zerotorescue@0 1238 end
Zerotorescue@0 1239
Zerotorescue@0 1240 local newGroupName = string.trim(string.lower(name or ""));
Zerotorescue@0 1241
Zerotorescue@0 1242 for name in pairs(self.db.global.groups) do
Zerotorescue@0 1243 if string.lower(name) == newGroupName then
Zerotorescue@0 1244 print(("|cffff0000A group named \"%s\" already exists.|r"):format(name));
Zerotorescue@0 1245 return;
Zerotorescue@0 1246 end
Zerotorescue@0 1247 end
Zerotorescue@0 1248
Zerotorescue@0 1249 self.db.global.groups[name] = temp;
Zerotorescue@0 1250 end
Zerotorescue@0 1251 end,
Zerotorescue@0 1252 get = false,
Zerotorescue@0 1253 width = "full",
Zerotorescue@0 1254 },
Zerotorescue@0 1255 },
Zerotorescue@0 1256 },
Zerotorescue@0 1257 },
Zerotorescue@0 1258 };
Zerotorescue@0 1259 end
Zerotorescue@0 1260
Zerotorescue@0 1261 function addon:FillGroupOptions()
Zerotorescue@0 1262 for id, name in pairs(groupIdToName) do
Zerotorescue@0 1263 if type(name) == "string" and not self.db.global.groups[name] then
Zerotorescue@0 1264 options.args.groups.args[id] = nil;
Zerotorescue@0 1265 groupIdToName[id] = nil;
Zerotorescue@0 1266 groupIdToName[name] = nil;
Zerotorescue@0 1267 end
Zerotorescue@0 1268 end
Zerotorescue@0 1269
Zerotorescue@0 1270 for name, values in pairs(self.db.global.groups) do
Zerotorescue@0 1271 if not groupIdToName[name] then
Zerotorescue@0 1272 options.args.groups.args[tostring(count)] = CopyTable(defaultGroup);
Zerotorescue@0 1273
Zerotorescue@0 1274 groupIdToName[tostring(count)] = name;
Zerotorescue@0 1275 groupIdToName[name] = true;
Zerotorescue@0 1276
Zerotorescue@0 1277 count = ( count + 1 );
Zerotorescue@0 1278 end
Zerotorescue@0 1279 end
Zerotorescue@0 1280 end
Zerotorescue@0 1281
Zerotorescue@0 1282 function addon:GetItemCount(itemId)
Zerotorescue@0 1283 return Altoholic:GetItemCount(itemId);
Zerotorescue@0 1284 end
Zerotorescue@0 1285
Zerotorescue@0 1286
Zerotorescue@0 1287
Zerotorescue@0 1288
Zerotorescue@0 1289 function addon:Debug(t)
Zerotorescue@0 1290 if not self.debugChannel and self.debugChannel ~= false then
Zerotorescue@0 1291 -- 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 1292 self.debugChannel = false;
Zerotorescue@0 1293
Zerotorescue@0 1294 for i = 1, NUM_CHAT_WINDOWS do
Zerotorescue@0 1295 local name = GetChatWindowInfo(i);
Zerotorescue@0 1296
Zerotorescue@0 1297 if name:upper() == "DEBUG" then
Zerotorescue@0 1298 self.debugChannel = _G["ChatFrame" .. i];
Zerotorescue@0 1299 end
Zerotorescue@0 1300 end
Zerotorescue@0 1301 end
Zerotorescue@0 1302
Zerotorescue@0 1303 if self.debugChannel then
Zerotorescue@0 1304 self.debugChannel:AddMessage(t);
Zerotorescue@0 1305 end
Zerotorescue@0 1306 end