· 8 years ago · Aug 15, 2018, 11:26 PM
1local Config = {}
2local AceDialog, AceRegistry, AceGUI, SML, registered, options
3local playerClass = select(2, UnitClass("player"))
4local modifyUnits, globalConfig = {}, {}
5local L = ShadowUF.L
6
7ShadowUF.Config = Config
8
9--[[
10 The part that makes configuration a pain when you actually try is it gets unwieldly when you're adding special code to deal with
11 showing help for certain cases, swapping tabs etc that makes it work smoothly.
12
13 I'm going to have to split it out into separate files for each type to clean everything up but that takes time and I have other things
14 I want to get done with first.
15
16 -- dated 2009
17
18 In reality, this will never be cleaned up because jesus christ, I am not refactoring 7,000 lines of configuration.
19
20 *** HERE BE DRAGONS ***
21]]
22
23local unitCategories = {
24 player = {"player", "pet"},
25 general = {"target", "targettarget", "targettargettarget", "focus", "focustarget", "pettarget"},
26 party = {"party", "partypet", "partytarget", "partytargettarget", "party"},
27 raid = {"raid", "raidpet"},
28 raidmisc = {"maintank", "maintanktarget", "maintanktargettarget", "mainassist", "mainassisttarget", "mainassisttargettarget"},
29 boss = {"boss", "bosstarget", "bosstargettarget"},
30 arena = {"arena", "arenapet", "arenatarget", "arenatargettarget"},
31 battleground = {"battleground", "battlegroundpet", "battlegroundtarget", "battlegroundtargettarget"}
32}
33
34local UNIT_DESC = {
35 ["boss"] = L["Boss units are for only certain fights, such as Blood Princes or the Gunship battle, you will not see them for every boss fight."],
36 ["mainassist"] = L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."],
37 ["maintank"] = L["Main Tank's are set through the Raid frames, or through selecting the Tank role."],
38 ["battleground"] = L["Currently used in battlegrounds for showing flag carriers."],
39 ["battlegroundpet"] = L["Current pet used by a battleground unit."],
40 ["battlegroundtarget"] = L["Current target of a battleground unit."],
41 ["battlegroundtargettarget"] = L["Current target of target of a battleground unit."]
42}
43
44local PAGE_DESC = {
45 ["general"] = L["General configuration to all enabled units."],
46 ["enableUnits"] = L["Various units can be enabled through this page, such as raid or party targets."],
47 ["hideBlizzard"] = L["Hiding and showing various aspects of the default UI such as the player buff frames."],
48 ["units"] = L["Configuration to specific unit frames."],
49 ["visibility"] = L["Disabling unit modules in various instances."],
50 ["tags"] = L["Advanced tag management, allows you to add your own custom tags."],
51 ["filter"] = L["Simple aura filtering by whitelists and blacklists."],
52}
53local INDICATOR_NAMES = {["questBoss"] = L["Quest Boss"], ["leader"] = L["Leader / Assist"], ["lfdRole"] = L["Class Role"], ["masterLoot"] = L["Master Looter"], ["pvp"] = L["PvP Flag"], ["raidTarget"] = L["Raid Target"], ["ready"] = L["Ready Status"], ["role"] = L["Raid Role"], ["status"] = L["Combat Status"], ["class"] = L["Class Icon"], ["resurrect"] = L["Resurrect Status"], ["phase"] = L["Other Party/Phase Status"], ["petBattle"] = L["Pet Battle"], ["arenaSpec"] = L["Arena Spec"]}
54local AREA_NAMES = {["arena"] = L["Arenas"],["none"] = L["Everywhere else"], ["party"] = L["Party instances"], ["pvp"] = L["Battleground"], ["raid"] = L["Raid instances"]}
55local INDICATOR_DESC = {
56 ["leader"] = L["Crown indicator for group leader or assistants."], ["lfdRole"] = L["Role the unit is playing."],
57 ["masterLoot"] = L["Bag indicator for master looters."], ["pvp"] = L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."],
58 ["raidTarget"] = L["Raid target indicator."], ["ready"] = L["Ready status of group members."], ["phase"] = L["Shows when a party member is in a different phase or another group."],
59 ["questBoss"] = L["Shows that a NPC is a boss for a quest."], ["petBattle"] = L["Shows what kind of pet the unit is for pet battles."],
60 ["role"] = L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."], ["status"] = L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."], ["class"] = L["Class icon for players."],
61 ["arenaSpec"] = L["Talent spec of your arena opponents."]
62}
63local TAG_GROUPS = {["classification"] = L["Classifications"], ["health"] = L["Health"], ["misc"] = L["Miscellaneous"], ["playerthreat"] = L["Player threat"], ["power"] = L["Power"], ["status"] = L["Status"], ["threat"] = L["Threat"], ["raid"] = L["Raid"], ["classspec"] = L["Class Specific"], ["classtimer"] = L["Class Timer"]}
64
65local pointPositions = {["BOTTOM"] = L["Bottom"], ["TOP"] = L["Top"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["TOPLEFT"] = L["Top Left"], ["TOPRIGHT"] = L["Top Right"], ["BOTTOMLEFT"] = L["Bottom Left"], ["BOTTOMRIGHT"] = L["Bottom Right"], ["CENTER"] = L["Center"]}
66local positionList = {["C"] = L["Center"], ["RT"] = L["Right Top"], ["RC"] = L["Right Center"], ["RB"] = L["Right Bottom"], ["LT"] = L["Left Top"], ["LC"] = L["Left Center"], ["LB"] = L["Left Bottom"], ["BL"] = L["Bottom Left"], ["BC"] = L["Bottom Center"], ["BR"] = L["Bottom Right"], ["TR"] = L["Top Right"], ["TC"] = L["Top Center"], ["TL"] = L["Top Left"]}
67
68local unitOrder = {}
69for order, unit in pairs(ShadowUF.unitList) do unitOrder[unit] = order end
70local fullReload = {["bars"] = true, ["auras"] = true, ["backdrop"] = true, ["font"] = true, ["classColors"] = true, ["powerColors"] = true, ["healthColors"] = true, ["xpColors"] = true, ["omnicc"] = true}
71local quickIDMap = {}
72
73-- Helper functions
74local function getPageDescription(info)
75 return PAGE_DESC[info[#(info)]]
76end
77
78local function getFrameName(unit)
79 if( unit == "raidpet" or unit == "raid" or unit == "party" or unit == "maintank" or unit == "mainassist" or unit == "boss" or unit == "arena" ) then
80 return string.format("#SUFHeader%s", unit)
81 end
82
83 return string.format("#SUFUnit%s", unit)
84end
85
86local anchorList = {}
87local function getAnchorParents(info)
88 local unit = info[2]
89 for k in pairs(anchorList) do anchorList[k] = nil end
90
91 if( ShadowUF.Units.childUnits[unit] ) then
92 anchorList["$parent"] = string.format(L["%s member"], L.units[ShadowUF.Units.childUnits[unit]])
93 return anchorList
94 end
95
96 anchorList["UIParent"] = L["Screen"]
97
98 -- Don't let a frame anchor to a frame thats anchored to it already (Stop infinite loops-o-doom)
99 local currentName = getFrameName(unit)
100 for _, unitID in pairs(ShadowUF.unitList) do
101 if( unitID ~= unit and ShadowUF.db.profile.positions[unitID] and ShadowUF.db.profile.positions[unitID].anchorTo ~= currentName ) then
102 anchorList[getFrameName(unitID)] = string.format(L["%s frames"], L.units[unitID] or unitID)
103 end
104 end
105
106 return anchorList
107end
108
109local function selectDialogGroup(group, key)
110 AceDialog.Status.ShadowedUF.children[group].status.groups.selected = key
111 AceRegistry:NotifyChange("ShadowedUF")
112end
113
114local function selectTabGroup(group, subGroup, key)
115 AceDialog.Status.ShadowedUF.children[group].status.groups.selected = subGroup
116 AceDialog.Status.ShadowedUF.children[group].children[subGroup].status.groups.selected = key
117 AceRegistry:NotifyChange("ShadowedUF")
118end
119
120local function hideAdvancedOption(info)
121 return not ShadowUF.db.profile.advanced
122end
123
124local function hideBasicOption(info)
125 return ShadowUF.db.profile.advanced
126end
127
128local function isUnitDisabled(info)
129 local unit = info[#(info)]
130 local enabled = ShadowUF.db.profile.units[unit].enabled
131 for _, visibility in pairs(ShadowUF.db.profile.visibility) do
132 if( visibility[unit] ) then
133 enabled = visibility[unit]
134 break
135 end
136 end
137
138 return not enabled
139end
140
141local function mergeTables(parent, child)
142 for key, value in pairs(child) do
143 if( type(parent[key]) == "table" ) then
144 parent[key] = mergeTables(parent[key], value)
145 elseif( type(value) == "table" ) then
146 parent[key] = CopyTable(value)
147 elseif( parent[key] == nil ) then
148 parent[key] = value
149 end
150 end
151
152 return parent
153end
154
155local function getName(info)
156 local key = info[#(info)]
157 if( ShadowUF.modules[key] and ShadowUF.modules[key].moduleName ) then
158 return ShadowUF.modules[key].moduleName
159 end
160
161 return LOCALIZED_CLASS_NAMES_MALE[key] or INDICATOR_NAMES[key] or L.units[key] or TAG_GROUPS[key] or L[key]
162end
163
164local function getUnitOrder(info)
165 return unitOrder[info[#(info)]]
166end
167
168local function isModifiersSet(info)
169 if( info[2] ~= "global" ) then return false end
170 for k in pairs(modifyUnits) do return false end
171 return true
172end
173
174-- These are for setting simple options like bars.texture = "Default" or locked = true
175local function set(info, value)
176 local cat, key = string.split(".", info.arg)
177 if( key == "$key" ) then key = info[#(info)] end
178
179 if( not key ) then
180 ShadowUF.db.profile[cat] = value
181 else
182 ShadowUF.db.profile[cat][key] = value
183 end
184
185 if( cat and fullReload[cat] ) then
186 ShadowUF.Layout:CheckMedia()
187 ShadowUF.Layout:Reload()
188 end
189end
190
191local function get(info)
192 local cat, key = string.split(".", info.arg)
193 if( key == "$key" ) then key = info[#(info)] end
194 if( not key ) then
195 return ShadowUF.db.profile[cat]
196 else
197 return ShadowUF.db.profile[cat][key]
198 end
199end
200
201local function setColor(info, r, g, b, a)
202 local color = get(info) or {}
203 color.r, color.g, color.b, color.a = r, g, b, a
204 set(info, color)
205end
206
207local function getColor(info)
208 local color = get(info) or {}
209 return color.r, color.g, color.b, color.a
210end
211
212-- These are for setting complex options like units.player.auras.buffs.enabled = true or units.player.portrait.enabled = true
213local function setVariable(unit, moduleKey, moduleSubKey, key, value)
214 local configTable = unit == "global" and globalConfig or ShadowUF.db.profile.units[unit]
215
216 -- For setting options like units.player.auras.buffs.enabled = true
217 if( moduleKey and moduleSubKey and configTable[moduleKey][moduleSubKey] ) then
218 configTable[moduleKey][moduleSubKey][key] = value
219 ShadowUF.Layout:Reload(unit)
220 -- For setting options like units.player.portrait.enabled = true
221 elseif( moduleKey and not moduleSubKey and configTable[moduleKey] ) then
222 configTable[moduleKey][key] = value
223 ShadowUF.Layout:Reload(unit)
224 -- For setting options like units.player.height = 50
225 elseif( not moduleKey and not moduleSubKey ) then
226 configTable[key] = value
227 ShadowUF.Layout:Reload(unit)
228 end
229end
230
231local function specialRestricted(unit, moduleKey, moduleSubKey, key)
232 if( ShadowUF.fakeUnits[unit] and ( key == "colorAggro" or key == "aggro" or key == "colorDispel" or moduleKey == "incHeal" or moduleKey == "healAbsorb" or moduleKey == "incAbsorb" or moduleKey == "castBar" ) ) then
233 return true
234 elseif( moduleKey == "healthBar" and unit == "player" and key == "reaction" ) then
235 return true
236 end
237end
238
239local function setDirectUnit(unit, moduleKey, moduleSubKey, key, value)
240 if( unit == "global" ) then
241 for unit in pairs(modifyUnits) do
242 if( not specialRestricted(unit, moduleKey, moduleSubKey, key) ) then
243 setVariable(unit, moduleKey, moduleSubKey, key, value)
244 end
245 end
246
247 setVariable("global", moduleKey, moduleSubKey, key, value)
248 else
249 setVariable(unit, moduleKey, moduleSubKey, key, value)
250 end
251end
252
253local function setUnit(info, value)
254 local unit = info[2]
255 -- auras, buffs, enabled / text, 1, text / portrait, enabled
256 local moduleKey, moduleSubKey, key = string.split(".", info.arg)
257 if( not moduleSubKey ) then key = moduleKey moduleKey = nil end
258 if( moduleSubKey and not key ) then key = moduleSubKey moduleSubKey = nil end
259 if( moduleSubKey == "$parent" ) then moduleSubKey = info[#(info) - 1] end
260 if( moduleKey == "$parent" ) then moduleKey = info[#(info) - 1] end
261 if( moduleSubKey == "$parentparent" ) then moduleSubKey = info[#(info) - 2] end
262 if( moduleKey == "$parentparent" ) then moduleKey = info[#(info) - 2] end
263 if( tonumber(moduleSubKey) ) then moduleSubKey = tonumber(moduleSubKey) end
264
265 setDirectUnit(unit, moduleKey, moduleSubKey, key, value)
266end
267
268local function getVariable(unit, moduleKey, moduleSubKey, key)
269 local configTbl = unit == "global" and globalConfig or ShadowUF.db.profile.units[unit]
270 if( moduleKey and moduleSubKey ) then
271 return configTbl[moduleKey][moduleSubKey] and configTbl[moduleKey][moduleSubKey][key]
272 elseif( moduleKey and not moduleSubKey ) then
273 return configTbl[moduleKey] and configTbl[moduleKey][key]
274 end
275
276 return configTbl[key]
277end
278
279local function getUnit(info)
280 local moduleKey, moduleSubKey, key = string.split(".", info.arg)
281 if( not moduleSubKey ) then key = moduleKey moduleKey = nil end
282 if( moduleSubKey and not key ) then key = moduleSubKey moduleSubKey = nil end
283 if( moduleSubKey == "$parent" ) then moduleSubKey = info[#(info) - 1] end
284 if( moduleKey == "$parent" ) then moduleKey = info[#(info) - 1] end
285 if( moduleSubKey == "$parentparent" ) then moduleSubKey = info[#(info) - 2] end
286 if( moduleKey == "$parentparent" ) then moduleKey = info[#(info) - 2] end
287 if( tonumber(moduleSubKey) ) then moduleSubKey = tonumber(moduleSubKey) end
288
289 return getVariable(info[2], moduleKey, moduleSubKey, key)
290end
291
292-- Tag functions
293local function getTagName(info)
294 local tag = info[#(info)]
295 if( ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].name ) then
296 return ShadowUF.db.profile.tags[tag].name
297 end
298
299 return ShadowUF.Tags.defaultNames[tag] or tag
300end
301
302local function getTagHelp(info)
303 local tag = info[#(info)]
304 return ShadowUF.Tags.defaultHelp[tag] or ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].help
305end
306
307-- Module functions
308local function hideRestrictedOption(info)
309 local unit = type(info.arg) == "number" and info[#(info) - info.arg] or info[2]
310 local key = info[#(info)]
311 if( ShadowUF.modules[key] and ShadowUF.modules[key].moduleClass and ShadowUF.modules[key].moduleClass ~= playerClass ) then
312 return true
313 elseif( ( key == "incHeal" and not ShadowUF.modules.incHeal ) or ( key == "incAbsorb" and not ShadowUF.modules.incAbsorb ) or ( key == "healAbsorb" and not ShadowUF.modules.healAbsorb ) ) then
314 return true
315 -- Non-standard units do not support color by aggro or incoming heal
316 elseif( key == "colorAggro" or key == "colorDispel" or key == "incHeal" or key == "incAbsorb" or key == "aggro" ) then
317 return string.match(unit, "%w+target" )
318 -- Fall back for indicators, no variable table so it shouldn't be shown
319 elseif( info[#(info) - 1] == "indicators" ) then
320 if( ( unit == "global" and not globalConfig.indicators[key] ) or ( unit ~= "global" and not ShadowUF.db.profile.units[unit].indicators[key] ) ) then
321 return true
322 end
323 -- Fall back, no variable table so it shouldn't be shown
324 elseif( ( unit == "global" and not globalConfig[key] ) or ( unit ~= "global" and not ShadowUF.db.profile.units[unit][key] ) ) then
325 return true
326 end
327
328 return false
329end
330
331local function getModuleOrder(info)
332 local key = info[#(info)]
333 return key == "healthBar" and 1 or key == "powerBar" and 2 or key == "castBar" and 3 or 4
334end
335
336-- Expose these for modules
337Config.getAnchorParents = getAnchorParents
338Config.hideAdvancedOption = hideAdvancedOption
339Config.isUnitDisabled = isUnitDisabled
340Config.selectDialogGroup = selectDialogGroup
341Config.selectTabGroup = selectTabGroup
342Config.getName = getName
343Config.getUnitOrder = getUnitOrder
344Config.isModifiersSet = isModifiersSet
345Config.set = set
346Config.get = get
347Config.setUnit = setUnit
348Config.setVariable = setVariable
349Config.getUnit = getUnit
350Config.getVariable = getVariable
351Config.hideRestrictedOption = hideRestrictedOption
352Config.hideBasicOption = hideBasicOption
353
354
355--------------------
356-- GENERAL CONFIGURATION
357---------------------
358
359local function writeTable(tbl)
360 local data = ""
361 for key, value in pairs(tbl) do
362 local valueType = type(value)
363
364 -- Wrap the key in brackets if it's a number
365 if( type(key) == "number" ) then
366 key = string.format("[%s]", key)
367 -- Wrap the string with quotes if it has a space in it
368 elseif( string.match(key, "[%p%s%c]") or string.match(key, "^[0-9]+$") ) then
369 key = string.format("['%s']", string.gsub(key, "'", "\\'"))
370 end
371
372 -- foo = {bar = 5}
373 if( valueType == "table" ) then
374 data = string.format("%s%s=%s;", data, key, writeTable(value))
375 -- foo = true / foo = 5
376 elseif( valueType == "number" or valueType == "boolean" ) then
377 data = string.format("%s%s=%s;", data, key, tostring(value))
378 -- foo = "bar"
379 else
380 value = tostring(value)
381 if value and string.match(value, "[\n]") then
382 local token = ""
383 while string.find(value, "%["..token.."%[") or string.find(value, "%]"..token.."%]") do
384 token = token .. "="
385 end
386 value = string.format("[%s[%s]%s]", token, value, token)
387 else
388 value = string.format("%q", value)
389 end
390 data = string.format("%s%s=%s;", data, key, value)
391 end
392 end
393
394 return "{" .. data .. "}"
395end
396
397local function loadGeneralOptions()
398 SML = SML or LibStub:GetLibrary("LibSharedMedia-3.0")
399
400 local MediaList = {}
401 local function getMediaData(info)
402 local mediaType = info[#(info)]
403
404 MediaList[mediaType] = MediaList[mediaType] or {}
405
406 for k in pairs(MediaList[mediaType]) do MediaList[mediaType][k] = nil end
407 for _, name in pairs(SML:List(mediaType)) do
408 MediaList[mediaType][name] = name
409 end
410
411 return MediaList[mediaType]
412 end
413
414
415 local barModules = {}
416 for key, module in pairs(ShadowUF.modules) do
417 if( module.moduleHasBar ) then
418 barModules["$" .. key] = module.moduleName
419 end
420 end
421
422 local addTextParent = {
423 order = 4,
424 type = "group",
425 inline = true,
426 name = function(info) return barModules[info[#(info)]] or string.sub(info[#(info)], 2) end,
427 hidden = function(info)
428 for _, text in pairs(ShadowUF.db.profile.units.player.text) do
429 if( text.anchorTo == info[#(info)] ) then
430 return false
431 end
432 end
433
434 return true
435 end,
436 args = {},
437 }
438
439 local addTextLabel = {
440 order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end,
441 type = "description",
442 width = "",
443 fontSize = "medium",
444 hidden = function(info)
445 local id = tonumber(string.match(info[#(info)], "(%d+)"))
446 if( not getVariable("player", "text", nil, id) ) then return true end
447 return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1]
448 end,
449 name = function(info)
450 return getVariable("player", "text", tonumber(string.match(info[#(info)], "(%d+)")), "name")
451 end,
452 }
453
454 local addTextSep = {
455 order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.75 end,
456 type = "description",
457 width = "full",
458 hidden = function(info)
459 local id = tonumber(string.match(info[#(info)], "(%d+)"))
460 if( not getVariable("player", "text", nil, id) ) then return true end
461 return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1]
462 end,
463 name = "",
464 }
465
466 local addText = {
467 order = function(info) return info[#(info)] + 0.5 end,
468 type = "execute",
469 width = "half",
470 name = L["Delete"],
471 hidden = function(info)
472 local id = tonumber(info[#(info)])
473 if( not getVariable("player", "text", nil, id) ) then return true end
474 return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1]
475 end,
476 disabled = function(info)
477 local id = tonumber(info[#(info)])
478 for _, unit in pairs(ShadowUF.unitList) do
479 if( ShadowUF.db.profile.units[unit].text[id] and ShadowUF.db.profile.units[unit].text[id].default ) then
480 return true
481 end
482 end
483
484 return false
485 end,
486 confirmText = L["Are you sure you want to delete this text? All settings for it will be deleted."],
487 confirm = true,
488 func = function(info)
489 local id = tonumber(info[#(info)])
490 for _, unit in pairs(ShadowUF.unitList) do
491 table.remove(ShadowUF.db.profile.units[unit].text, id)
492 end
493
494 addTextParent.args[info[#(info)]] = nil
495 ShadowUF.Layout:Reload()
496 end,
497 }
498
499 local function validateSpell(info, spell)
500 if( spell and spell ~= "" and not GetSpellInfo(spell) ) then
501 return string.format(L["Invalid spell \"%s\" entered."], spell or "")
502 end
503
504 return true
505 end
506
507 local function setRange(info, spell)
508 ShadowUF.db.profile.range[info[#(info)] .. playerClass] = spell and spell ~= "" and spell or nil
509 ShadowUF.Layout:Reload()
510 end
511
512 local function getRange(info)
513 return ShadowUF.db.profile.range[info[#(info)] .. playerClass]
514 end
515
516 local function rangeWithIcon(info)
517 local name = getRange(info)
518 local text = L["Spell Name"]
519 if( string.match(info[#(info)], "Alt") ) then
520 text = L["Alternate Spell Name"]
521 end
522
523 local icon = select(3, GetSpellInfo(name))
524 if( not icon ) then
525 icon = "Interface\\Icons\\Inv_misc_questionmark"
526 end
527
528 return "|T" .. icon .. ":18:18:0:0|t " .. text
529 end
530
531 local textData = {}
532
533 local layoutData = {positions = true, visibility = true, modules = false}
534 local layoutManager = {
535 type = "group",
536 order = 7,
537 name = L["Layout manager"],
538 childGroups = "tab",
539 hidden = hideAdvancedOption,
540 args = {
541 import = {
542 order = 1,
543 type = "group",
544 name = L["Import"],
545 hidden = false,
546 args = {
547 help = {
548 order = 1,
549 type = "group",
550 inline = true,
551 name = function(info) return layoutData.error and L["Error"] or L["Help"] end,
552 args = {
553 help = {
554 order = 1,
555 type = "description",
556 name = function(info)
557 if( ShadowUF.db:GetCurrentProfile() == "Import Backup" ) then
558 return L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."]
559 end
560
561 return layoutData.error or L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."]
562 end
563 },
564 },
565 },
566 positions = {
567 order = 2,
568 type = "toggle",
569 name = L["Import unit frame positions"],
570 set = function(info, value) layoutData[info[#(info)]] = value end,
571 get = function(info) return layoutData[info[#(info)]] end,
572 width = "double",
573 },
574 visibility = {
575 order = 3,
576 type = "toggle",
577 name = L["Import visibility settings"],
578 set = function(info, value) layoutData[info[#(info)]] = value end,
579 get = function(info) return layoutData[info[#(info)]] end,
580 width = "double",
581 },
582 import = {
583 order = 5,
584 type = "input",
585 name = L["Code"],
586 multiline = true,
587 width = "full",
588 get = false,
589 disabled = function() return ShadowUF.db:GetCurrentProfile() == "Import Backup" end,
590 set = function(info, import)
591 local layout, err = loadstring(string.format([[return %s]], import))
592 if( err ) then
593 layoutData.error = string.format(L["Failed to import layout, error:|n|n%s"], err)
594 return
595 end
596
597 layout = layout()
598
599 -- Strip position settings
600 if( not layoutData.positions ) then
601 layout.positions = nil
602 end
603
604 -- Strip visibility settings
605 if( not layoutData.visibility ) then
606 layout.visibility = nil
607 end
608
609 -- Strip any units we don't have included by default
610 for unit in pairs(layout.units) do
611 if( not ShadowUF.defaults.profile.units[unit] ) then
612 layout.units[unit] = nil
613 end
614 end
615
616 -- Check if we need move over the visibility and positions info
617 layout.positions = layout.positions or CopyTable(ShadowUF.db.profile.positions)
618 layout.visibility = layout.visibility or CopyTable(ShadowUF.db.profile.positions)
619
620 -- Now backup the profile
621 local currentLayout = ShadowUF.db:GetCurrentProfile()
622 ShadowUF.layoutImporting = true
623 ShadowUF.db:SetProfile("Import Backup")
624 ShadowUF.db:CopyProfile(currentLayout)
625 ShadowUF.db:SetProfile(currentLayout)
626 ShadowUF.db:ResetProfile()
627 ShadowUF.layoutImporting = nil
628
629 -- Overwrite everything we did import
630 ShadowUF:LoadDefaultLayout()
631 for key, data in pairs(layout) do
632 if( type(data) == "table" ) then
633 ShadowUF.db.profile[key] = CopyTable(data)
634 else
635 ShadowUF.db.profile[key] = data
636 end
637 end
638
639 ShadowUF:ProfilesChanged()
640 end,
641 },
642 },
643 },
644 export = {
645 order = 2,
646 type = "group",
647 name = L["Export"],
648 hidden = false,
649 args = {
650 help = {
651 order = 1,
652 type = "group",
653 inline = true,
654 name = L["Help"],
655 args = {
656 help = {
657 order = 1,
658 type = "description",
659 name = L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."],
660 },
661 },
662 },
663 doExport = {
664 order = 2,
665 type = "execute",
666 name = L["Export"],
667 func = function(info)
668 layoutData.export = writeTable(ShadowUF.db.profile)
669 end,
670 },
671 export = {
672 order = 3,
673 type = "input",
674 name = L["Code"],
675 multiline = true,
676 width = "full",
677 set = false,
678 get = function(info) return layoutData[info[#(info)]] end,
679 },
680 },
681 },
682 },
683 }
684
685 options.args.general = {
686 type = "group",
687 childGroups = "tab",
688 name = L["General"],
689 args = {
690 general = {
691 type = "group",
692 order = 1,
693 name = L["General"],
694 set = set,
695 get = get,
696 args = {
697 general = {
698 order = 1,
699 type = "group",
700 inline = true,
701 name = L["General"],
702 args = {
703 locked = {
704 order = 1,
705 type = "toggle",
706 name = L["Lock frames"],
707 desc = L["Enables configuration mode, letting you move and giving you example frames to setup."],
708 set = function(info, value)
709 set(info, value)
710 ShadowUF.modules.movers:Update()
711 end,
712 arg = "locked",
713 },
714 advanced = {
715 order = 1.5,
716 type = "toggle",
717 name = L["Advanced"],
718 desc = L["Enabling advanced settings will give you access to more configuration options. This is meant for people who want to tweak every single thing, and should not be enabled by default as it increases the options."],
719 arg = "advanced",
720 },
721 sep = {
722 order = 2,
723 type = "description",
724 name = "",
725 width = "full",
726 },
727 omnicc = {
728 order = 2.5,
729 type = "toggle",
730 name = L["Disable OmniCC Cooldown Count"],
731 desc = L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."],
732 arg = "omnicc",
733 width = "double",
734 },
735 blizzardcc = {
736 order = 2.5,
737 type = "toggle",
738 name = L["Disable Blizzard Cooldown Count"],
739 desc = L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."],
740 arg = "blizzardcc",
741 width = "double",
742 },
743 hideCombat = {
744 order = 3,
745 type = "toggle",
746 name = L["Hide tooltips in combat"],
747 desc = L["Prevents unit tooltips from showing while in combat."],
748 arg = "tooltipCombat",
749 width = "double",
750 },
751 sep2 = {
752 order = 3.5,
753 type = "description",
754 name = "",
755 width = "full",
756 },
757 auraBorder = {
758 order = 5,
759 type = "select",
760 name = L["Aura border style"],
761 desc = L["Style of borders to show for all auras."],
762 values = {["dark"] = L["Dark"], ["light"] = L["Light"], ["blizzard"] = L["Blizzard"], [""] = L["None"]},
763 arg = "auras.borderType",
764 },
765 statusbar = {
766 order = 6,
767 type = "select",
768 name = L["Bar texture"],
769 dialogControl = "LSM30_Statusbar",
770 values = getMediaData,
771 arg = "bars.texture",
772 },
773 spacing = {
774 order = 7,
775 type = "range",
776 name = L["Bar spacing"],
777 desc = L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."],
778 min = -10, max = 10, step = 0.05, softMin = -5, softMax = 5,
779 arg = "bars.spacing",
780 hidden = hideAdvancedOption,
781 },
782 },
783 },
784 backdrop = {
785 order = 2,
786 type = "group",
787 inline = true,
788 name = L["Background/border"],
789 args = {
790 backgroundColor = {
791 order = 1,
792 type = "color",
793 name = L["Background color"],
794 hasAlpha = true,
795 set = setColor,
796 get = getColor,
797 arg = "backdrop.backgroundColor",
798 },
799 borderColor = {
800 order = 2,
801 type = "color",
802 name = L["Border color"],
803 hasAlpha = true,
804 set = setColor,
805 get = getColor,
806 arg = "backdrop.borderColor",
807 },
808 sep = {
809 order = 3,
810 type = "description",
811 name = "",
812 width = "full",
813 },
814 background = {
815 order = 4,
816 type = "select",
817 name = L["Background"],
818 dialogControl = "LSM30_Background",
819 values = getMediaData,
820 arg = "backdrop.backgroundTexture",
821 },
822 border = {
823 order = 5,
824 type = "select",
825 name = L["Border"],
826 dialogControl = "LSM30_Border",
827 values = getMediaData,
828 arg = "backdrop.borderTexture",
829 },
830 inset = {
831 order = 5.5,
832 type = "range",
833 name = L["Inset"],
834 desc = L["How far the background should be from the unit frame border."],
835 min = -10, max = 10, step = 1,
836 hidden = hideAdvancedOption,
837 arg = "backdrop.inset",
838 },
839 sep2 = {
840 order = 6,
841 type = "description",
842 name = "",
843 width = "full",
844 hidden = hideAdvancedOption,
845 },
846 edgeSize = {
847 order = 7,
848 type = "range",
849 name = L["Edge size"],
850 desc = L["How large the edges should be."],
851 hidden = hideAdvancedOption,
852 min = 0, max = 20, step = 1,
853 arg = "backdrop.edgeSize",
854 },
855 tileSize = {
856 order = 8,
857 type = "range",
858 name = L["Tile size"],
859 desc = L["How large the background should tile"],
860 hidden = hideAdvancedOption,
861 min = 0, max = 20, step = 1,
862 arg = "backdrop.tileSize",
863 },
864 clip = {
865 order = 9,
866 type = "range",
867 name = L["Clip"],
868 desc = L["How close the frame should clip with the border."],
869 hidden = hideAdvancedOption,
870 min = 0, max = 20, step = 1,
871 arg = "backdrop.clip",
872 },
873 },
874 },
875 font = {
876 order = 3,
877 type = "group",
878 inline = true,
879 name = L["Font"],
880 args = {
881 color = {
882 order = 1,
883 type = "color",
884 name = L["Default color"],
885 desc = L["Default font color, any color tags inside individual tag texts will override this."],
886 hasAlpha = true,
887 set = setColor,
888 get = getColor,
889 arg = "font.color",
890 hidden = hideAdvancedOption,
891 },
892 sep = {order = 1.25, type = "description", name = "", hidden = hideAdvancedOption},
893 font = {
894 order = 1.5,
895 type = "select",
896 name = L["Font"],
897 dialogControl = "LSM30_Font",
898 values = getMediaData,
899 arg = "font.name",
900 },
901 size = {
902 order = 2,
903 type = "range",
904 name = L["Size"],
905 min = 1, max = 50, step = 1, softMin = 1, softMax = 20,
906 arg = "font.size",
907 },
908 outline = {
909 order = 3,
910 type = "select",
911 name = L["Outline"],
912 values = {["OUTLINE"] = L["Thin outline"], ["THICKOUTLINE"] = L["Thick outline"], ["MONOCHROMEOUTLINE"] = L["Monochrome Outline"], [""] = L["None"]},
913 arg = "font.extra",
914 hidden = hideAdvancedOption,
915 },
916 },
917 },
918 bar = {
919 order = 4,
920 type = "group",
921 inline = true,
922 name = L["Bars"],
923 hidden = hideAdvancedOption,
924 args = {
925 override = {
926 order = 0,
927 type = "toggle",
928 name = L["Override color"],
929 desc = L["Forces a static color to be used for the background of all bars"],
930 set = function(info, value)
931 if( value and not ShadowUF.db.profile.bars.backgroundColor ) then
932 ShadowUF.db.profile.bars.backgroundColor = {r = 0, g = 0, b = 0}
933 elseif( not value ) then
934 ShadowUF.db.profile.bars.backgroundColor = nil
935 end
936
937 ShadowUF.Layout:Reload()
938 end,
939 get = function(info)
940 return ShadowUF.db.profile.bars.backgroundColor and true or false
941 end,
942 },
943 color = {
944 order = 1,
945 type = "color",
946 name = L["Background color"],
947 desc = L["This will override all background colorings for bars including custom set ones."],
948 set = setColor,
949 get = function(info)
950 if( not ShadowUF.db.profile.bars.backgroundColor ) then
951 return {r = 0, g = 0, b = 0}
952 end
953
954 return getColor(info)
955 end,
956 disabled = function(info) return not ShadowUF.db.profile.bars.backgroundColor end,
957 arg = "bars.backgroundColor",
958 },
959 sep = { order = 2, type = "description", name = "", width = "full"},
960 barAlpha = {
961 order = 3,
962 type = "range",
963 name = L["Bar alpha"],
964 desc = L["Alpha to use for bar."],
965 arg = "bars.alpha",
966 min = 0, max = 1, step = 0.05,
967 isPercent = true
968 },
969 backgroundAlpha = {
970 order = 4,
971 type = "range",
972 name = L["Background alpha"],
973 desc = L["Alpha to use for bar backgrounds."],
974 arg = "bars.backgroundAlpha",
975 min = 0, max = 1, step = 0.05,
976 isPercent = true
977 },
978 },
979 },
980 },
981 },
982 color = {
983 order = 2,
984 type = "group",
985 name = L["Colors"],
986 args = {
987 health = {
988 order = 1,
989 type = "group",
990 inline = true,
991 name = L["Health"],
992 set = setColor,
993 get = getColor,
994 args = {
995 green = {
996 order = 1,
997 type = "color",
998 name = L["High health"],
999 desc = L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."],
1000 arg = "healthColors.green",
1001 },
1002 yellow = {
1003 order = 2,
1004 type = "color",
1005 name = L["Half health"],
1006 desc = L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."],
1007 arg = "healthColors.yellow",
1008 },
1009 red = {
1010 order = 3,
1011 type = "color",
1012 name = L["Low health"],
1013 desc = L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."],
1014 arg = "healthColors.red",
1015 },
1016 friendly = {
1017 order = 4,
1018 type = "color",
1019 name = L["Friendly"],
1020 desc = L["Health bar color for friendly units."],
1021 arg = "healthColors.friendly",
1022 },
1023 neutral = {
1024 order = 5,
1025 type = "color",
1026 name = L["Neutral"],
1027 desc = L["Health bar color for neutral units."],
1028 arg = "healthColors.neutral",
1029 },
1030 hostile = {
1031 order = 6,
1032 type = "color",
1033 name = L["Hostile"],
1034 desc = L["Health bar color for hostile units."],
1035 arg = "healthColors.hostile",
1036 },
1037 aggro = {
1038 order = 6.5,
1039 type = "color",
1040 name = L["Has Aggro"],
1041 desc = L["Health bar color for units with aggro."],
1042 arg = "healthColors.aggro",
1043 },
1044 static = {
1045 order = 7,
1046 type = "color",
1047 name = L["Static"],
1048 desc = L["Color to use for health bars that are set to be colored by a static color."],
1049 arg = "healthColors.static",
1050 },
1051 inc = {
1052 order = 8,
1053 type = "color",
1054 name = L["Incoming heal"],
1055 desc = L["Bar color to use to show how much healing someone is about to receive."],
1056 arg = "healthColors.inc",
1057 },
1058 incAbsorb = {
1059 order = 9,
1060 type = "color",
1061 name = L["Incoming absorb"],
1062 desc = L["Color to use to show how much damage will be absorbed."],
1063 arg = "healthColors.incAbsorb",
1064 },
1065 healAbsorb = {
1066 order = 10,
1067 type = "color",
1068 name = L["Heal absorb"],
1069 desc = L["Color to use to show how much healing will e absorbed."],
1070 arg = "healthColors.healAbsorb",
1071 },
1072 enemyUnattack = {
1073 order = 11,
1074 type = "color",
1075 name = L["Unattackable hostile"],
1076 desc = L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."],
1077 hidden = hideAdvancedOption,
1078 arg = "healthColors.enemyUnattack",
1079 }
1080 },
1081 },
1082 stagger = {
1083 order = 1.5,
1084 type = "group",
1085 inline = true,
1086 name = L["Stagger"],
1087 set = setColor,
1088 get = getColor,
1089 hidden = function() return select(2, UnitClass("player")) ~= "MONK" end,
1090 args = {
1091 STAGGER_GREEN = {
1092 order = 0,
1093 type = "color",
1094 name = L["Green (<30% HP)"],
1095 desc = L["Stagger bar color when the staggered amount is <30% of your HP."],
1096 arg = "powerColors.STAGGER_GREEN"
1097 },
1098 STAGGER_GREEN = {
1099 order = 1,
1100 type = "color",
1101 name = L["Yellow (>30% HP)"],
1102 desc = L["Stagger bar color when the staggered amount is >30% of your HP."],
1103 arg = "powerColors.STAGGER_YELLOW"
1104 },
1105 STAGGER_RED = {
1106 order = 2,
1107 type = "color",
1108 name = L["Red (>70% HP)"],
1109 desc = L["Stagger bar color when the staggered amount is >70% of your HP."],
1110 arg = "powerColors.STAGGER_RED"
1111 }
1112 }
1113 },
1114 power = {
1115 order = 2,
1116 type = "group",
1117 inline = true,
1118 name = L["Power"],
1119 set = setColor,
1120 get = getColor,
1121 args = {
1122 MANA = {
1123 order = 0,
1124 type = "color",
1125 name = L["Mana"],
1126 width = "half",
1127 arg = "powerColors.MANA",
1128 },
1129 RAGE = {
1130 order = 1,
1131 type = "color",
1132 name = L["Rage"],
1133 width = "half",
1134 arg = "powerColors.RAGE",
1135 },
1136 FOCUS = {
1137 order = 2,
1138 type = "color",
1139 name = L["Focus"],
1140 arg = "powerColors.FOCUS",
1141 width = "half",
1142 },
1143 ENERGY = {
1144 order = 3,
1145 type = "color",
1146 name = L["Energy"],
1147 arg = "powerColors.ENERGY",
1148 width = "half",
1149 },
1150 RUNIC_POWER = {
1151 order = 6,
1152 type = "color",
1153 name = L["Runic Power"],
1154 arg = "powerColors.RUNIC_POWER",
1155 },
1156 RUNES = {
1157 order = 7,
1158 type = "color",
1159 name = L["Runes"],
1160 arg = "powerColors.RUNES",
1161 hidden = function(info) return select(2, UnitClass("player")) ~= "DEATHKNIGHT" end,
1162 },
1163 AMMOSLOT = {
1164 order = 9,
1165 type = "color",
1166 name = L["Ammo"],
1167 arg = "powerColors.AMMOSLOT",
1168 hidden = hideAdvancedOption,
1169 },
1170 FUEL = {
1171 order = 10,
1172 type = "color",
1173 name = L["Fuel"],
1174 arg = "powerColors.FUEL",
1175 hidden = hideAdvancedOption,
1176 },
1177 COMBOPOINTS = {
1178 order = 11,
1179 type = "color",
1180 name = L["Combo Points"],
1181 arg = "powerColors.COMBOPOINTS",
1182 },
1183 AURAPOINTS = {
1184 order = 11.5,
1185 type = "color",
1186 name = L["Aura Combo Points"],
1187 arg = "powerColors.AURAPOINTS",
1188 hidden = function() return not ShadowUF.modules.auraPoints end
1189 },
1190 INSANITY = {
1191 order = 12,
1192 type = "color",
1193 name = L["Insanity"],
1194 arg = "powerColors.INSANITY",
1195 hidden = function(info) return select(2, UnitClass("player")) ~= "PRIEST" end,
1196 },
1197 MAELSTROM = {
1198 order = 12,
1199 type = "color",
1200 name = L["Maelstrom"],
1201 arg = "powerColors.MAELSTROM",
1202 hidden = function(info) return select(2, UnitClass("player")) ~= "SHAMAN" end,
1203 },
1204 HOLYPOWER = {
1205 order = 12,
1206 type = "color",
1207 name = L["Holy Power"],
1208 arg = "powerColors.HOLYPOWER",
1209 hidden = function(info) return select(2, UnitClass("player")) ~= "PALADIN" end,
1210 },
1211 SOULSHARDS = {
1212 order = 14,
1213 type = "color",
1214 name = L["Soul Shards"],
1215 hasAlpha = true,
1216 arg = "powerColors.SOULSHARDS",
1217 hidden = function(info) return select(2, UnitClass("player")) ~= "WARLOCK" end,
1218 },
1219 ARCANECHARGES = {
1220 order = 15,
1221 type = "color",
1222 name = L["Arcane Charges"],
1223 hasAlpha = true,
1224 arg = "powerColors.ARCANECHARGES",
1225 hidden = function(info) return select(2, UnitClass("player")) ~= "MAGE" end,
1226 },
1227 CHI = {
1228 order = 17,
1229 type = "color",
1230 name = L["Chi"],
1231 arg = "powerColors.CHI",
1232 hidden = function(info) return select(2, UnitClass("player")) ~= "MONK" end,
1233 },
1234 FURY = {
1235 order = 17,
1236 type = "color",
1237 name = L["Fury"],
1238 arg = "powerColors.FURY",
1239 hidden = function(info) return select(2, UnitClass("player")) ~= "DEMONHUNTER" end,
1240 },
1241 PAIN = {
1242 order = 17,
1243 type = "color",
1244 name = L["Pain"],
1245 arg = "powerColors.PAIN",
1246 hidden = function(info) return select(2, UnitClass("player")) ~= "DEMONHUNTER" end,
1247 },
1248 LUNAR_POWER = {
1249 order = 17,
1250 type = "color",
1251 name = L["Astral Power"],
1252 arg = "powerColors.LUNAR_POWER",
1253 hidden = function(info) return select(2, UnitClass("player")) ~= "DRUID" end,
1254 },
1255 MUSHROOMS = {
1256 order = 17,
1257 type = "color",
1258 name = L["Mushrooms"],
1259 arg = "powerColors.MUSHROOMS",
1260 hidden = function(info) return select(2, UnitClass("player")) ~= "DRUID" end,
1261 },
1262 STATUE = {
1263 order = 17,
1264 type = "color",
1265 name = L["Statue"],
1266 arg = "powerColors.STATUE",
1267 hidden = function(info) return select(2, UnitClass("player")) ~= "MONK" end,
1268 },
1269 RUNEOFPOWER = {
1270 order = 17.5,
1271 type = "color",
1272 name = L["Rune of Power"],
1273 arg = "powerColors.RUNEOFPOWER",
1274 hidden = function(info) return select(2, UnitClass("player")) ~= "MAGE" end,
1275 },
1276 ALTERNATE = {
1277 order = 19,
1278 type = "color",
1279 name = L["Alt. Power"],
1280 desc = L["Alternate power is used for things like quests and dungeons."],
1281 arg = "powerColors.ALTERNATE",
1282 },
1283 },
1284 },
1285 cast = {
1286 order = 3,
1287 type = "group",
1288 inline = true,
1289 name = L["Cast"],
1290 set = setColor,
1291 get = getColor,
1292 args = {
1293 cast = {
1294 order = 0,
1295 type = "color",
1296 name = L["Casting"],
1297 desc = L["Color used when an unit is casting a spell."],
1298 arg = "castColors.cast",
1299 },
1300 channel = {
1301 order = 1,
1302 type = "color",
1303 name = L["Channelling"],
1304 desc = L["Color used when a cast is a channel."],
1305 arg = "castColors.channel",
1306 },
1307 sep = {
1308 order = 2,
1309 type = "description",
1310 name = "",
1311 hidden = hideAdvancedOption,
1312 width = "full",
1313 },
1314 finished = {
1315 order = 3,
1316 type = "color",
1317 name = L["Finished cast"],
1318 desc = L["Color used when a cast is successfully finished."],
1319 hidden = hideAdvancedOption,
1320 arg = "castColors.finished",
1321 },
1322 interrupted = {
1323 order = 4,
1324 type = "color",
1325 name = L["Cast interrupted"],
1326 desc = L["Color used when a cast is interrupted either by the caster themselves or by another unit."],
1327 hidden = hideAdvancedOption,
1328 arg = "castColors.interrupted",
1329 },
1330 uninterruptible = {
1331 order = 5,
1332 type = "color",
1333 name = L["Cast uninterruptible"],
1334 desc = L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."],
1335 arg = "castColors.uninterruptible",
1336 },
1337 },
1338 },
1339 auras = {
1340 order = 3.5,
1341 type = "group",
1342 inline = true,
1343 name = L["Aura borders"],
1344 set = setColor,
1345 get = getColor,
1346 hidden = hideAdvancedOption,
1347 args = {
1348 removableColor = {
1349 order = 0,
1350 type = "color",
1351 name = L["Stealable/Curable/Dispellable"],
1352 desc = L["Border coloring of stealable, curable and dispellable auras."],
1353 arg = "auraColors.removable",
1354 width = "double"
1355 }
1356 }
1357 },
1358 classColors = {
1359 order = 4,
1360 type = "group",
1361 inline = true,
1362 name = L["Classes"],
1363 set = setColor,
1364 get = getColor,
1365 args = {}
1366 },
1367 },
1368 },
1369 range = {
1370 order = 5,
1371 type = "group",
1372 name = L["Range Checker"],
1373 args = {
1374 help = {
1375 order = 0,
1376 type = "group",
1377 inline = true,
1378 name = L["Help"],
1379 args = {
1380 help = {
1381 order = 0,
1382 type = "description",
1383 name = L["This will be set for your current class only.\nIf no custom spells are set, defaults appropriate for your class will be used."],
1384 },
1385 },
1386 },
1387 friendly = {
1388 order = 1,
1389 inline = true,
1390 type = "group",
1391 name = L["On Friendly Units"],
1392 args = {
1393 friendly = {
1394 order = 1,
1395 type = "input",
1396 name = rangeWithIcon,
1397 desc = L["Name of a friendly spell to check range."],
1398 validate = validateSpell,
1399 set = setRange,
1400 get = getRange,
1401 },
1402 spacer = {
1403 order = 2,
1404 type = "description",
1405 width = "normal",
1406 name = ""
1407 },
1408 friendlyAlt = {
1409 order = 3,
1410 type = "input",
1411 name = rangeWithIcon,
1412 desc = L["Alternatively friendly spell to use to check range."],
1413 hidden = hideAdvancedOption,
1414 validate = validateSpell,
1415 set = setRange,
1416 get = getRange,
1417 },
1418 }
1419 },
1420 hostile = {
1421 order = 2,
1422 inline = true,
1423 type = "group",
1424 name = L["On Hostile Units"],
1425 args = {
1426 hostile = {
1427 order = 1,
1428 type = "input",
1429 name = rangeWithIcon,
1430 desc = L["Name of a friendly spell to check range."],
1431 validate = validateSpell,
1432 set = setRange,
1433 get = getRange,
1434 },
1435 spacer = {
1436 order = 2,
1437 type = "description",
1438 width = "normal",
1439 name = ""
1440 },
1441 hostileAlt = {
1442 order = 3,
1443 type = "input",
1444 name = rangeWithIcon,
1445 desc = L["Alternatively friendly spell to use to check range."],
1446 hidden = hideAdvancedOption,
1447 validate = validateSpell,
1448 set = setRange,
1449 get = getRange,
1450 },
1451 }
1452 },
1453 },
1454 },
1455 text = {
1456 type = "group",
1457 order = 6,
1458 name = L["Text Management"],
1459 hidden = false,
1460 args = {
1461 help = {
1462 order = 0,
1463 type = "group",
1464 inline = true,
1465 name = L["Help"],
1466 args = {
1467 help = {
1468 order = 0,
1469 type = "description",
1470 name = L["You can add additional text with tags enabled using this configuration, note that any additional text added (or removed) effects all units, removing text will reset their settings as well.|n|nKeep in mind, you cannot delete the default text included with the units."],
1471 },
1472 },
1473 },
1474 add = {
1475 order = 1,
1476 name = L["Add new text"],
1477 inline = true,
1478 type = "group",
1479 set = function(info, value) textData[info[#(info)] ] = value end,
1480 get = function(info, value) return textData[info[#(info)] ] end,
1481 args = {
1482 name = {
1483 order = 0,
1484 type = "input",
1485 name = L["Text name"],
1486 desc = L["Text name that you can use to identify this text from others when configuring."],
1487 },
1488 parent = {
1489 order = 1,
1490 type = "select",
1491 name = L["Text parent"],
1492 desc = L["Where inside the frame the text should be anchored to."],
1493 values = barModules,
1494 },
1495 add = {
1496 order = 2,
1497 type = "execute",
1498 name = L["Add"],
1499 disabled = function() return not textData.name or textData.name == "" or not textData.parent end,
1500 func = function(info)
1501 -- Verify we entered a good name
1502 textData.name = string.trim(textData.name)
1503 textData.name = textData.name ~= "" and textData.name or nil
1504
1505 -- Add the new entry
1506 for _, unit in pairs(ShadowUF.unitList) do
1507 table.insert(ShadowUF.db.profile.units[unit].text, {enabled = true, name = textData.name or "??", text = "", anchorTo = textData.parent, x = 0, y = 0, anchorPoint = "C", size = 0, width = 0.50})
1508 end
1509
1510 -- Add it to the GUI
1511 local id = tostring(#(ShadowUF.db.profile.units.player.text))
1512 addTextParent.args[id .. ":label"] = addTextLabel
1513 addTextParent.args[id] = addText
1514 addTextParent.args[id .. ":sep"] = addTextSep
1515 options.args.general.args.text.args[textData.parent] = options.args.general.args.text.args[textData.parent] or addTextParent
1516
1517 local parent = string.sub(textData.parent, 2)
1518 Config.tagWizard[parent] = Config.tagWizard[parent] or Config.parentTable
1519 Config.tagWizard[parent].args[id] = Config.tagTextTable
1520 Config.tagWizard[parent].args[id .. ":adv"] = Config.advanceTextTable
1521
1522 quickIDMap[id .. ":adv"] = #(ShadowUF.db.profile.units.player.text)
1523
1524 -- Reset
1525 textData.name = nil
1526 textData.parent = nil
1527
1528 end,
1529 },
1530 },
1531 },
1532 },
1533 },
1534 layout = layoutManager,
1535 },
1536 }
1537
1538 -- Load text
1539 for id, text in pairs(ShadowUF.db.profile.units.player.text) do
1540 if( text.anchorTo ~= "" and not text.default ) then
1541 addTextParent.args[id .. ":label"] = addTextLabel
1542 addTextParent.args[tostring(id)] = addText
1543 addTextParent.args[id .. ":sep"] = addTextSep
1544 options.args.general.args.text.args[text.anchorTo] = addTextParent
1545 end
1546 end
1547
1548
1549 Config.classTable = {
1550 order = 0,
1551 type = "color",
1552 name = getName,
1553 hasAlpha = true,
1554 width = "half",
1555 arg = "classColors.$key",
1556 }
1557
1558 for classToken in pairs(RAID_CLASS_COLORS) do
1559 options.args.general.args.color.args.classColors.args[classToken] = Config.classTable
1560 end
1561
1562 options.args.general.args.color.args.classColors.args.PET = Config.classTable
1563 options.args.general.args.color.args.classColors.args.VEHICLE = Config.classTable
1564end
1565
1566---------------------
1567-- HIDE BLIZZARD FRAMES CONFIGURATION
1568---------------------
1569local function loadHideOptions()
1570 Config.hideTable = {
1571 order = function(info) return info[#(info)] == "buffs" and 1 or 2 end,
1572 type = "toggle",
1573 name = function(info)
1574 local key = info[#(info)]
1575 if( key == "arena" ) then return string.format(L["Hide %s frames"], "arena/battleground") end
1576 return L.units[key] and string.format(L["Hide %s frames"], string.lower(L.units[key])) or string.format(L["Hide %s"], key == "cast" and L["player cast bar"] or key == "playerPower" and L["player power frames"] or key == "buffs" and L["buff frames"] or key == "playerAltPower" and L["player alt. power"])
1577 end,
1578 set = function(info, value)
1579 set(info, value)
1580 if( value ) then ShadowUF:HideBlizzardFrames() end
1581 end,
1582 hidden = false,
1583 get = get,
1584 arg = "hidden.$key",
1585 }
1586
1587 options.args.hideBlizzard = {
1588 type = "group",
1589 name = L["Hide Blizzard"],
1590 desc = getPageDescription,
1591 args = {
1592 help = {
1593 order = 0,
1594 type = "group",
1595 name = L["Help"],
1596 inline = true,
1597 args = {
1598 description = {
1599 type = "description",
1600 name = L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."],
1601 width = "full",
1602 },
1603 },
1604 },
1605 hide = {
1606 order = 1,
1607 type = "group",
1608 name = L["Frames"],
1609 inline = true,
1610 args = {
1611 buffs = Config.hideTable,
1612 cast = Config.hideTable,
1613 playerPower = Config.hideTable,
1614 party = Config.hideTable,
1615 raid = Config.hideTable,
1616 player = Config.hideTable,
1617 pet = Config.hideTable,
1618 target = Config.hideTable,
1619 focus = Config.hideTable,
1620 boss = Config.hideTable,
1621 arena = Config.hideTable,
1622 playerAltPower = Config.hideTable,
1623 },
1624 },
1625 }
1626 }
1627end
1628
1629---------------------
1630-- UNIT CONFIGURATION
1631---------------------
1632local function loadUnitOptions()
1633 -- This makes sure we don't end up with any messed up positioning due to two different anchors being used
1634 local function fixPositions(info)
1635 local unit = info[2]
1636 local key = info[#(info)]
1637
1638 if( key == "point" or key == "relativePoint" ) then
1639 ShadowUF.db.profile.positions[unit].anchorPoint = ""
1640 ShadowUF.db.profile.positions[unit].movedAnchor = nil
1641 elseif( key == "anchorPoint" ) then
1642 ShadowUF.db.profile.positions[unit].point = ""
1643 ShadowUF.db.profile.positions[unit].relativePoint = ""
1644 end
1645
1646 -- Reset offset if it was a manually positioned frame, and it got anchored
1647 -- Why 100/-100 you ask? Because anything else requires some sort of logic applied to it
1648 -- and this means the frames won't directly overlap too which is a nice bonus
1649 if( key == "anchorTo" ) then
1650 ShadowUF.db.profile.positions[unit].x = 100
1651 ShadowUF.db.profile.positions[unit].y = -100
1652 end
1653 end
1654
1655 -- Hide raid option in party config
1656 local function hideRaidOrAdvancedOption(info)
1657 if( info[2] == "party" and ShadowUF.db.profile.advanced ) then return false end
1658
1659 return info[2] ~= "raid" and info[2] ~= "raidpet" and info[2] ~= "maintank" and info[2] ~= "mainassist"
1660 end
1661
1662 local function hideRaidOption(info)
1663 return info[2] ~= "raid" and info[2] ~= "raidpet" and info[2] ~= "maintank" and info[2] ~= "mainassist"
1664 end
1665
1666 local function hideSplitOrRaidOption(info)
1667 if( info[2] == "raid" and ShadowUF.db.profile.units.raid.frameSplit ) then
1668 return true
1669 end
1670
1671 return hideRaidOption(info)
1672 end
1673
1674 -- Not every option should be changed via global settings
1675 local function hideSpecialOptions(info)
1676 local unit = info[2]
1677 if( unit == "global" or unit == "partypet" ) then
1678 return true
1679 end
1680
1681 return hideAdvancedOption(info)
1682 end
1683
1684 local function checkNumber(info, value)
1685 return tonumber(value)
1686 end
1687
1688 local function setPosition(info, value)
1689 ShadowUF.db.profile.positions[info[2]][info[#(info)]] = value
1690 fixPositions(info)
1691
1692 if( info[2] == "raid" or info[2] == "raidpet" or info[2] == "maintank" or info[2] == "mainassist" or info[2] == "party" or info[2] == "boss" or info[2] == "arena" ) then
1693 ShadowUF.Units:ReloadHeader(info[2])
1694 else
1695 ShadowUF.Layout:Reload(info[2])
1696 end
1697 end
1698
1699 local function getPosition(info)
1700 return ShadowUF.db.profile.positions[info[2]][info[#(info)]]
1701 end
1702
1703 local function setNumber(info, value)
1704 local unit = info[2]
1705 local key = info[#(info)]
1706 local id = unit .. key
1707
1708 -- Apply effective scaling if it's anchored to UIParent
1709 if( ShadowUF.db.profile.positions[unit].anchorTo == "UIParent" ) then
1710 value = value * (ShadowUF.db.profile.units[unit].scale * UIParent:GetScale())
1711 end
1712
1713 setPosition(info, tonumber(value))
1714 end
1715
1716 local function getString(info)
1717 local unit = info[2]
1718 local key = info[#(info)]
1719 local id = unit .. key
1720 local coord = getPosition(info)
1721
1722 -- If the frame is created and it's anchored to UIParent, will return the number modified by scale
1723 if( ShadowUF.db.profile.positions[unit].anchorTo == "UIParent" ) then
1724 coord = coord / (ShadowUF.db.profile.units[unit].scale * UIParent:GetScale())
1725 end
1726
1727 -- OCD, most definitely.
1728 -- Pain to check coord == math.floor(coord) because floats are handled oddly with frames and return 0.99999999999435
1729 return string.gsub(string.format("%.2f", coord), "%.00$", "")
1730 end
1731
1732
1733 -- TAG WIZARD
1734 local tagWizard = {}
1735 Config.tagWizard = tagWizard
1736 do
1737 -- Load tag list
1738 Config.advanceTextTable = {
1739 order = 1,
1740 name = function(info) return getVariable(info[2], "text", quickIDMap[info[#(info)]], "name") end,
1741 type = "group",
1742 inline = true,
1743 hidden = function(info)
1744 if( not getVariable(info[2], "text", nil, quickIDMap[info[#(info)]]) ) then return true end
1745 return string.sub(getVariable(info[2], "text", quickIDMap[info[#(info)]], "anchorTo"), 2) ~= info[#(info) - 1]
1746 end,
1747 set = function(info, value)
1748 info.arg = string.format("text.%s.%s", quickIDMap[info[#(info) - 1]], info[#(info)])
1749 setUnit(info, value)
1750 end,
1751 get = function(info)
1752 info.arg = string.format("text.%s.%s", quickIDMap[info[#(info) - 1]], info[#(info)])
1753 return getUnit(info)
1754 end,
1755 args = {
1756 anchorPoint = {
1757 order = 1,
1758 type = "select",
1759 name = L["Anchor point"],
1760 values = {["LC"] = L["Left Center"], ["RT"] = L["Right Top"], ["RB"] = L["Right Bottom"], ["LT"] = L["Left Top"], ["LB"] = L["Left Bottom"], ["RC"] = L["Right Center"],["TRI"] = L["Inside Top Right"], ["TLI"] = L["Inside Top Left"], ["CLI"] = L["Inside Center Left"], ["C"] = L["Inside Center"], ["CRI"] = L["Inside Center Right"], ["TR"] = L["Top Right"], ["TL"] = L["Top Left"], ["BR"] = L["Bottom Right"], ["BL"] = L["Bottom Left"]},
1761 hidden = hideAdvancedOption,
1762 },
1763 sep = {
1764 order = 2,
1765 type = "description",
1766 name = "",
1767 width = "full",
1768 hidden = hideAdvancedOption,
1769 },
1770 width = {
1771 order = 3,
1772 name = L["Width weight"],
1773 desc = L["How much weight this should use when figuring out the total text width."],
1774 type = "range",
1775 min = 0, max = 10, step = 0.1,
1776 hidden = function(info)
1777 return hideAdvancedOption(info) or getVariable(info[2], "text", quickIDMap[info[#(info) - 1]], "block")
1778 end,
1779 },
1780 size = {
1781 order = 4,
1782 name = L["Size"],
1783 desc = L["Let's you modify the base font size to either make it larger or smaller."],
1784 type = "range",
1785 min = -20, max = 20, step = 1, softMin = -5, softMax = 5,
1786 hidden = false,
1787 },
1788 sep2 = {
1789 order = 4.5,
1790 type = "description",
1791 name = "",
1792 width = "full",
1793 hidden = function(info)
1794 return hideAdvancedOption(info) or not getVariable(info[2], "text", quickIDMap[info[#(info) - 1]], "block")
1795 end
1796 },
1797 x = {
1798 order = 5,
1799 type = "range",
1800 name = L["X Offset"],
1801 min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100,
1802 hidden = false,
1803 },
1804 y = {
1805 order = 6,
1806 type = "range",
1807 name = L["Y Offset"],
1808 min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100,
1809 hidden = false,
1810 },
1811 },
1812 }
1813
1814 Config.parentTable = {
1815 order = 0,
1816 type = "group",
1817 hidden = false,
1818 name = function(info) return getName(info) or string.sub(info[#(info)], 1) end,
1819 hidden = function(info) return not getVariable(info[2], info[#(info)], nil, "enabled") end,
1820 args = {}
1821 }
1822
1823 local function hideBlacklistedTag(info)
1824 local unit = info[2]
1825 local id = tonumber(info[#(info) - 2])
1826 local tag = info[#(info)]
1827 local cat = info[#(info) - 1]
1828
1829 if( unit == "global" ) then
1830 for unit in pairs(modifyUnits) do
1831 if( ShadowUF.Tags.unitRestrictions[tag] == unit ) then
1832 return false
1833 end
1834 end
1835 end
1836
1837 if( ShadowUF.Tags.unitRestrictions[tag] and ShadowUF.Tags.unitRestrictions[tag] ~= unit ) then
1838 return true
1839
1840 elseif( ShadowUF.Tags.anchorRestriction[tag] ) then
1841 if( ShadowUF.Tags.anchorRestriction[tag] ~= getVariable(unit, "text", id, "anchorTo") ) then
1842 return true
1843 else
1844 return false
1845 end
1846 end
1847
1848 return false
1849 end
1850
1851 local function hideBlacklistedGroup(info)
1852 local unit = info[2]
1853 local id = tonumber(info[#(info) - 1])
1854 local tagGroup = info[#(info)]
1855
1856 if( unit ~= "global" ) then
1857 if( ShadowUF.Tags.unitBlacklist[tagGroup] and string.match(unit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then
1858 return true
1859 end
1860 else
1861 -- If the only units that are in the global configuration have the tag filtered, then don't bother showing it
1862 for unit in pairs(modifyUnits) do
1863 if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(unit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then
1864 return false
1865 end
1866 end
1867 end
1868
1869 local block = getVariable(unit, "text", id, "block")
1870 if( ( block and tagGroup ~= "classtimer" ) or ( not block and tagGroup == "classtimer" ) ) then
1871 return true
1872 end
1873
1874 return false
1875 end
1876
1877 local savedTagTexts = {}
1878 local function selectTag(info, value)
1879 local unit = info[2]
1880 local id = tonumber(info[#(info) - 2])
1881 local tag = info[#(info)]
1882 local text = getVariable(unit, "text", id, "text")
1883 local savedText
1884
1885 if( value ) then
1886 if( unit == "global" ) then
1887 table.wipe(savedTagTexts)
1888
1889 -- Set special tag texts based on the unit, so targettarget won't get a tag that will cause errors
1890 local tagGroup = ShadowUF.Tags.defaultCategories[tag]
1891 for unit in pairs(modifyUnits) do
1892 savedTagTexts[unit] = getVariable(unit, "text", id, "text")
1893 if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(unit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then
1894 if( not ShadowUF.Tags.unitRestrictions[tag] or ShadowUF.Tags.unitRestrictions[tag] == unit ) then
1895 if( text == "" ) then
1896 savedTagTexts[unit] = string.format("[%s]", tag)
1897 else
1898 savedTagTexts[unit] = string.format("%s[( )%s]", savedTagTexts[unit], tag)
1899 end
1900
1901 savedTagTexts.global = savedTagTexts[unit]
1902 end
1903 end
1904 end
1905 else
1906 if( text == "" ) then
1907 text = string.format("[%s]", tag)
1908 else
1909 text = string.format("%s[( )%s]", text, tag)
1910 end
1911 end
1912
1913 -- Removing a tag from a single unit, super easy :<
1914 else
1915 -- Ugly, but it works
1916 for matchedTag in string.gmatch(text, "%[(.-)%]") do
1917 local safeTag = "[" .. matchedTag .. "]"
1918 if( string.match(safeTag, "%[" .. tag .. "%]") or string.match(safeTag, "%)" .. tag .. "%]") or string.match(safeTag, "%[" .. tag .. "%(") or string.match(safeTag, "%)" .. tag .. "%(") ) then
1919 text = string.gsub(text, "%[" .. string.gsub(string.gsub(matchedTag, "%)", "%%)"), "%(", "%%(") .. "%]", "")
1920 text = string.gsub(text, " ", "")
1921 text = string.trim(text)
1922 break
1923 end
1924 end
1925 end
1926
1927 if( unit == "global" ) then
1928 for unit in pairs(modifyUnits) do
1929 if( savedTagTexts[unit] ) then
1930 setVariable(unit, "text", id, "text", savedTagTexts[unit])
1931 end
1932 end
1933
1934 setVariable("global", "text", id, "text", savedTagTexts.global)
1935 else
1936 setVariable(unit, "text", id, "text", text)
1937 end
1938 end
1939
1940 local function getTag(info)
1941 local text = getVariable(info[2], "text", tonumber(info[#(info) - 2]), "text")
1942 local tag = info[#(info)]
1943
1944 -- FUN WITH PATTERN MATCHING
1945 if( string.match(text, "%[" .. tag .. "%]") or string.match(text, "%)" .. tag .. "%]") or string.match(text, "%[" .. tag .. "%(") or string.match(text, "%)" .. tag .. "%(") ) then
1946 return true
1947 end
1948
1949 return false
1950 end
1951
1952 Config.tagTextTable = {
1953 type = "group",
1954 name = function(info) return getVariable(info[2], "text", nil, tonumber(info[#(info)])) and getVariable(info[2], "text", tonumber(info[#(info)]), "name") or "" end,
1955 hidden = function(info)
1956 if( not getVariable(info[2], "text", nil, tonumber(info[#(info)])) ) then return true end
1957 return string.sub(getVariable(info[2], "text", tonumber(info[#(info)]), "anchorTo"), 2) ~= info[#(info) - 1] end,
1958 set = false,
1959 get = false,
1960 args = {
1961 text = {
1962 order = 0,
1963 type = "input",
1964 name = L["Text"],
1965 width = "full",
1966 hidden = false,
1967 set = function(info, value) setUnit(info, string.gsub(value, "||", "|")) end,
1968 get = function(info) return string.gsub(getUnit(info), "|", "||") end,
1969 arg = "text.$parent.text",
1970 },
1971 },
1972 }
1973
1974
1975 local function getCategoryOrder(info)
1976 return info[#(info)] == "health" and 1 or info[#(info)] == "power" and 2 or info[#(info)] == "misc" and 3 or 4
1977 end
1978
1979 for _, cat in pairs(ShadowUF.Tags.defaultCategories) do
1980 Config.tagTextTable.args[cat] = Config.tagTextTable.args[cat] or {
1981 order = getCategoryOrder,
1982 type = "group",
1983 inline = true,
1984 name = getName,
1985 hidden = hideBlacklistedGroup,
1986 set = selectTag,
1987 get = getTag,
1988 args = {},
1989 }
1990 end
1991
1992 Config.tagTable = {
1993 order = 0,
1994 type = "toggle",
1995 hidden = hideBlacklistedTag,
1996 name = getTagName,
1997 desc = getTagHelp,
1998 }
1999
2000 local tagList = {}
2001 for tag in pairs(ShadowUF.Tags.defaultTags) do
2002 local category = ShadowUF.Tags.defaultCategories[tag] or "misc"
2003 Config.tagTextTable.args[category].args[tag] = Config.tagTable
2004 end
2005
2006 for tag, data in pairs(ShadowUF.db.profile.tags) do
2007 local category = data.category or "misc"
2008 Config.tagTextTable.args[category].args[tag] = Config.tagTable
2009 end
2010
2011 local parentList = {}
2012 for id, text in pairs(ShadowUF.db.profile.units.player.text) do
2013 parentList[text.anchorTo] = parentList[text.anchorTo] or {}
2014 parentList[text.anchorTo][id] = text
2015 end
2016
2017 local nagityNagNagTable = {
2018 order = 0,
2019 type = "group",
2020 name = L["Help"],
2021 inline = true,
2022 hidden = false,
2023 args = {
2024 help = {
2025 order = 0,
2026 type = "description",
2027 name = L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."],
2028 },
2029 },
2030 }
2031
2032 for parent, list in pairs(parentList) do
2033 parent = string.sub(parent, 2)
2034 tagWizard[parent] = Config.parentTable
2035 Config.parentTable.args.help = nagityNagNagTable
2036
2037 for id in pairs(list) do
2038 tagWizard[parent].args[tostring(id)] = Config.tagTextTable
2039 tagWizard[parent].args[tostring(id) .. ":adv"] = Config.advanceTextTable
2040
2041 quickIDMap[tostring(id) .. ":adv"] = id
2042 end
2043 end
2044 end
2045
2046 local function disableAnchoredTo(info)
2047 local auras = getVariable(info[2], "auras", nil, info[#(info) - 2])
2048
2049 return auras.anchorOn or not auras.enabled
2050 end
2051
2052 local function disableSameAnchor(info)
2053 local buffs = getVariable(info[2], "auras", nil, "buffs")
2054 local debuffs = getVariable(info[2], "auras", nil, "debuffs")
2055 local anchor = buffs.enabled and buffs.prioritize and "buffs" or "debuffs"
2056
2057 if( not getVariable(info[2], "auras", info[#(info) - 2], "enabled") ) then
2058 return true
2059 end
2060
2061 if( ( info[#(info)] == "x" or info[#(info)] == "y" ) and ( info[#(info) - 2] == "buffs" and buffs.anchorOn or info[#(info) - 2] == "debuffs" and debuffs.anchorOn ) ) then
2062 return true
2063 end
2064
2065 if( anchor == info[#(info) - 2] or buffs.anchorOn or debuffs.anchorOn ) then
2066 return false
2067 end
2068
2069 return buffs.anchorPoint == debuffs.anchorPoint
2070 end
2071
2072 local defaultAuraList = {["BL"] = L["Bottom"], ["TL"] = L["Top"], ["LT"] = L["Left"], ["RT"] = L["Right"]}
2073 local advancedAuraList = {["BL"] = L["Bottom Left"], ["BR"] = L["Bottom Right"], ["TL"] = L["Top Left"], ["TR"] = L["Top Right"], ["RT"] = L["Right Top"], ["RB"] = L["Right Bottom"], ["LT"] = L["Left Top"], ["LB"] = L["Left Bottom"]}
2074 local function getAuraAnchors()
2075 return ShadowUF.db.profile.advanced and advancedAuraList or defaultAuraList
2076 end
2077
2078 local function hideStealable(info)
2079 if( not ShadowUF.db.profile.advanced ) then return true end
2080 if( info[2] == "player" or info[2] == "pet" or info[#(info) - 2] == "debuffs" ) then return true end
2081
2082 return false
2083 end
2084
2085 local function hideBuffOption(info)
2086 return info[#(info) - 2] ~= "buffs"
2087 end
2088
2089 local function hideDebuffOption(info)
2090 return info[#(info) - 2] ~= "debuffs"
2091 end
2092
2093 local function reloadUnitAuras()
2094 for _, frame in pairs(ShadowUF.Units.unitFrames) do
2095 if( UnitExists(frame.unit) and frame.visibility.auras ) then
2096 ShadowUF.modules.auras:UpdateFilter(frame)
2097 frame:FullUpdate()
2098 end
2099 end
2100 end
2101
2102 local aurasDisabled = function(info) return not getVariable(info[2], "auras", info[#(info) - 2], "enabled") end
2103
2104 Config.auraTable = {
2105 type = "group",
2106 hidden = false,
2107 name = function(info) return info[#(info)] == "buffs" and L["Buffs"] or L["Debuffs"] end,
2108 order = function(info) return info[#(info)] == "buffs" and 1 or 2 end,
2109 disabled = false,
2110 args = {
2111 general = {
2112 type = "group",
2113 name = L["General"],
2114 order = 0,
2115 args = {
2116 enabled = {
2117 order = 1,
2118 type = "toggle",
2119 name = function(info) if( info[#(info) - 2] == "buffs" ) then return L["Enable buffs"] end return L["Enable debuffs"] end,
2120 disabled = false,
2121 width = "full",
2122 arg = "auras.$parentparent.enabled",
2123 },
2124 temporary = {
2125 order = 2,
2126 type = "toggle",
2127 name = L["Enable temporary enchants"],
2128 desc = L["Adds temporary enchants to the buffs for the player."],
2129 width = "full",
2130 hidden = function(info) return info[2] ~= "player" or info[#(info) - 2] ~= "buffs" end,
2131 disabled = function(info) return not getVariable(info[2], "auras", "buffs", "enabled") end,
2132 arg = "auras.buffs.temporary",
2133 }
2134 }
2135 },
2136 filters = {
2137 type = "group",
2138 name = L["Filters"],
2139 order = 1,
2140 set = function(info, value)
2141 getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]] = value
2142 reloadUnitAuras()
2143 end,
2144 get = function(info)
2145 return getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]]
2146 end,
2147 args = {
2148 player = {
2149 order = 1,
2150 type = "toggle",
2151 name = L["Show your auras"],
2152 desc = L["Whether auras you casted should be shown"],
2153 width = "full"
2154 },
2155 raid = {
2156 order = 2,
2157 type = "toggle",
2158 name = function(info) return info[#(info) - 2] == "buffs" and L["Show castable on other auras"] or L["Show curable/removable auras"] end,
2159 desc = function(info) return info[#(info) - 2] == "buffs" and L["Whether to show buffs that you cannot cast."] or L["Whether to show any debuffs you can remove, cure or steal."] end,
2160 width = "full"
2161 },
2162 boss = {
2163 order = 3,
2164 type = "toggle",
2165 name = L["Show casted by boss"],
2166 desc = L["Whether to show any auras casted by the boss"],
2167 width = "full"
2168 },
2169 misc = {
2170 order = 5,
2171 type = "toggle",
2172 name = L["Show any other auras"],
2173 desc = L["Whether to show auras that do not fall into the above categories."],
2174 width = "full"
2175 },
2176 relevant = {
2177 order = 6,
2178 type = "toggle",
2179 name = L["Smart Friendly/Hostile Filter"],
2180 desc = L["Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras."],
2181 width = "full"
2182 },
2183 }
2184 },
2185 display = {
2186 type = "group",
2187 name = L["Display"],
2188 order = 2,
2189 args = {
2190 prioritize = {
2191 order = 1,
2192 type = "toggle",
2193 name = L["Prioritize buffs"],
2194 desc = L["Show buffs before debuffs when sharing the same anchor point."],
2195 hidden = hideBuffOption,
2196 disabled = function(info)
2197 if( not getVariable(info[2], "auras", info[#(info) - 2], "enabled") ) then return true end
2198
2199 local buffs = getVariable(info[2], "auras", nil, "buffs")
2200 local debuffs = getVariable(info[2], "auras", nil, "debuffs")
2201
2202 return buffs.anchorOn or debuffs.anchorOn or buffs.anchorPoint ~= debuffs.anchorPoint
2203 end,
2204 arg = "auras.$parentparent.prioritize"
2205 },
2206 sep1 = {order = 1.5, type = "description", name = "", width = "full"},
2207 selfScale = {
2208 order = 2,
2209 type = "range",
2210 name = L["Scaled aura size"],
2211 desc = L["Scale for auras that you casted or can Spellsteal, any number above 100% is bigger than default, any number below 100% is smaller than default."],
2212 min = 1, max = 3, step = 0.10,
2213 isPercent = true,
2214 hidden = hideAdvancedOption,
2215 arg = "auras.$parentparent.selfScale",
2216 },
2217 sep12 = {order = 2.5, type = "description", name = "", width = "full"},
2218 timers = {
2219 order = 3,
2220 type = "multiselect",
2221 name = L["Cooldown rings for"],
2222 desc = L["When to show cooldown rings on auras"],
2223 hidden = hideAdvancedOption,
2224 values = function(info)
2225 local tbl = {["ALL"] = L["All Auras"], ["SELF"] = L["Your Auras"]}
2226 local type = info[#(info) - 2]
2227 if( type == "debuffs" ) then
2228 tbl["BOSS"] = L["Boss Debuffs"]
2229 end
2230
2231 return tbl;
2232 end,
2233 set = function(info, key, value)
2234 local tbl = getVariable(info[2], "auras", info[#(info) - 2], "timers")
2235 if( key == "ALL" and value ) then
2236 tbl = {["ALL"] = true}
2237 elseif( key ~= "ALL" and value ) then
2238 tbl["ALL"] = nil
2239 tbl[key] = value
2240 else
2241 tbl[key] = value
2242 end
2243
2244 setVariable(info[2], "auras", info[#(info) - 2], "timers", tbl)
2245 reloadUnitAuras()
2246 end,
2247 get = function(info, key)
2248 return getVariable(info[2], "auras", info[#(info) - 2], "timers")[key]
2249 end
2250 },
2251 sep3 = {order = 3.5, type = "description", name = "", width = "full"},
2252 enlarge = {
2253 order = 4,
2254 type = "multiselect",
2255 name = L["Enlarge auras for"],
2256 desc = L["What type of auras should be enlarged, use the scaled aura size option to change the size."],
2257 values = function(info)
2258 local tbl = {["SELF"] = L["Your Auras"]}
2259 local type = info[#(info) - 2]
2260 if( type == "debuffs" ) then
2261 tbl["BOSS"] = L["Boss Debuffs"]
2262 end
2263
2264 if( type == "debuffs" ) then
2265 tbl["REMOVABLE"] = L["Curable"]
2266 elseif( info[2] ~= "player" and info[2] ~= "pet" and info[2] ~= "party" and info[2] ~= "raid" and type == "buffs" ) then
2267 tbl["REMOVABLE"] = L["Dispellable/Stealable"]
2268 end
2269
2270 return tbl;
2271 end,
2272 set = function(info, key, value)
2273 local tbl = getVariable(info[2], "auras", info[#(info) - 2], "enlarge")
2274 tbl[key] = value
2275
2276 setVariable(info[2], "auras", info[#(info) - 2], "enlarge", tbl)
2277 reloadUnitAuras()
2278 end,
2279 get = function(info, key)
2280 return getVariable(info[2], "auras", info[#(info) - 2], "enlarge")[key]
2281 end
2282 }
2283 }
2284 },
2285 positioning = {
2286 type = "group",
2287 name = L["Positioning"],
2288 order = 3,
2289 args = {
2290 anchorOn = {
2291 order = 1,
2292 type = "toggle",
2293 name = function(info) return info[#(info) - 2] == "buffs" and L["Anchor to debuffs"] or L["Anchor to buffs"] end,
2294 desc = L["Allows you to anchor the aura group to another, you can then choose where it will be anchored using the position.|n|nUse this if you want to duplicate the default ui style where buffs and debuffs are separate groups."],
2295 set = function(info, value)
2296 setVariable(info[2], "auras", info[#(info) - 2] == "buffs" and "debuffs" or "buffs", "anchorOn", false)
2297 setUnit(info, value)
2298 end,
2299 width = "full",
2300 arg = "auras.$parentparent.anchorOn",
2301 },
2302 anchorPoint = {
2303 order = 1.5,
2304 type = "select",
2305 name = L["Position"],
2306 desc = L["How you want this aura to be anchored to the unit frame."],
2307 values = getAuraAnchors,
2308 disabled = disableAnchoredTo,
2309 arg = "auras.$parentparent.anchorPoint",
2310 },
2311 size = {
2312 order = 2,
2313 type = "range",
2314 name = L["Icon Size"],
2315 min = 1, max = 30, step = 1,
2316 arg = "auras.$parentparent.size",
2317 },
2318 sep1 = {order = 3, type = "description", name = "", width = "full"},
2319 perRow = {
2320 order = 13,
2321 type = "range",
2322 name = function(info)
2323 local anchorPoint = getVariable(info[2], "auras", info[#(info) - 2], "anchorPoint")
2324 if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
2325 return L["Per column"]
2326 end
2327
2328 return L["Per row"]
2329 end,
2330 desc = L["How many auras to show in a single row."],
2331 min = 1, max = 100, step = 1, softMin = 1, softMax = 50,
2332 disabled = disableSameAnchor,
2333 arg = "auras.$parentparent.perRow",
2334 },
2335 maxRows = {
2336 order = 14,
2337 type = "range",
2338 name = L["Max rows"],
2339 desc = L["How many rows total should be used, rows will be however long the per row value is set at."],
2340 min = 1, max = 10, step = 1, softMin = 1, softMax = 5,
2341 disabled = disableSameAnchor,
2342 hidden = function(info)
2343 local anchorPoint = getVariable(info[2], "auras", info[#(info) - 2], "anchorPoint")
2344 if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
2345 return true
2346 end
2347
2348 return false
2349 end,
2350 arg = "auras.$parentparent.maxRows",
2351 },
2352 maxColumns = {
2353 order = 14,
2354 type = "range",
2355 name = L["Max columns"],
2356 desc = L["How many auras per a column for example, entering two her will create two rows that are filled up to whatever per row is set as."],
2357 min = 1, max = 100, step = 1, softMin = 1, softMax = 50,
2358 hidden = function(info)
2359 local anchorPoint = getVariable(info[2], "auras", info[#(info) - 2], "anchorPoint")
2360 if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
2361 return false
2362 end
2363
2364 return true
2365 end,
2366 disabled = disableSameAnchor,
2367 arg = "auras.$parentparent.maxRows",
2368 },
2369 x = {
2370 order = 18,
2371 type = "range",
2372 name = L["X Offset"],
2373 min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100,
2374 disabled = disableSameAnchor,
2375 hidden = hideAdvancedOption,
2376 arg = "auras.$parentparent.x",
2377 },
2378 y = {
2379 order = 19,
2380 type = "range",
2381 name = L["Y Offset"],
2382 min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100,
2383 disabled = disableSameAnchor,
2384 hidden = hideAdvancedOption,
2385 arg = "auras.$parentparent.y",
2386 },
2387
2388 }
2389 }
2390 }
2391 }
2392
2393 local function hideBarOption(info)
2394 local module = info[#(info) - 1]
2395 if( ShadowUF.modules[module].moduleHasBar or getVariable(info[2], module, nil, "isBar") ) then
2396 return false
2397 end
2398
2399 return true
2400 end
2401
2402 local function disableIfCastName(info)
2403 return not getVariable(info[2], "castBar", "name", "enabled")
2404 end
2405
2406
2407 Config.barTable = {
2408 order = getModuleOrder,
2409 name = getName,
2410 type = "group",
2411 inline = false,
2412 hidden = function(info) return hideRestrictedOption(info) or not getVariable(info[2], info[#(info)], nil, "enabled") end,
2413 args = {
2414 enableBar = {
2415 order = 1,
2416 type = "toggle",
2417 name = L["Show as bar"],
2418 desc = L["Turns this widget into a bar that can be resized and ordered just like health and power bars."],
2419 hidden = function(info) return ShadowUF.modules[info[#(info) - 1]].moduleHasBar end,
2420 arg = "$parent.isBar",
2421 },
2422 sep1 = {order = 1.25, type = "description", name = "", hidden = function(info) return (info[#(info) - 1] ~= "burningEmbersBar" or not getVariable(info[2], info[#(info) - 1], nil, "backgroundColor") or not getVariable(info[2], info[#(info) - 1], nil, "background")) end},
2423 background = {
2424 order = 1.5,
2425 type = "toggle",
2426 name = L["Show background"],
2427 desc = L["Show a background behind the bars with the same texture/color but faded out."],
2428 hidden = hideBarOption,
2429 arg = "$parent.background",
2430 },
2431 sep2 = {order = 1.55, type = "description", name = "", hidden = function(info) return not (not ShadowUF.modules[info[#(info) - 1]] or not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints) end},
2432 overrideBackground = {
2433 order = 1.6,
2434 type = "toggle",
2435 name = L["Override background"],
2436 desc = L["Show a background behind the bars with the same texture/color but faded out."],
2437 disabled = function(info) return not getVariable(info[2], info[#(info) - 1], nil, "background") end,
2438 hidden = function(info) return info[#(info) - 1] ~= "burningEmbersBar" end,
2439 set = function(info, toggle)
2440 if( toggle ) then
2441 setVariable(info[2], info[#(info) - 1], nil, "backgroundColor", {r = 0, g = 0, b = 0, a = 0.70})
2442 else
2443 setVariable(info[2], info[#(info) - 1], nil, "backgroundColor", nil)
2444 end
2445 end,
2446 get = function(info)
2447 return not not getVariable(info[2], info[#(info) - 1], nil, "backgroundColor")
2448 end
2449 },
2450 overrideColor = {
2451 order = 1.65,
2452 type = "color",
2453 hasAlpha = true,
2454 name = L["Background color"],
2455 hidden = function(info) return info[#(info) - 1] ~= "burningEmbersBar" or not getVariable(info[2], info[#(info) - 1], nil, "backgroundColor") or not getVariable(info[2], info[#(info) - 1], nil, "background") end,
2456 set = function(info, r, g, b, a)
2457 local color = getUnit(info) or {}
2458 color.r = r
2459 color.g = g
2460 color.b = b
2461 color.a = a
2462
2463 setUnit(info, color)
2464 end,
2465 get = function(info)
2466 local color = getUnit(info)
2467 if( not color ) then
2468 return 0, 0, 0, 1
2469 end
2470
2471 return color.r, color.g, color.b, color.a
2472
2473 end,
2474 arg = "$parent.backgroundColor",
2475 },
2476 vertical = {
2477 order = 1.70,
2478 type = "toggle",
2479 name = L["Vertical growth"],
2480 desc = L["Rather than bars filling from left -> right, they will fill from bottom -> top."],
2481 arg = "$parent.vertical",
2482 hidden = function(info) return not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,
2483 },
2484 reverse = {
2485 order = 1.71,
2486 type = "toggle",
2487 name = L["Reverse fill"],
2488 desc = L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."],
2489 arg = "$parent.reverse",
2490 hidden = function(info) return not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,
2491 },
2492 invert = {
2493 order = 2,
2494 type = "toggle",
2495 name = L["Invert colors"],
2496 desc = L["Flips coloring so the bar color is shown as the background color and the background as the bar"],
2497 hidden = function(info) return not ShadowUF.modules[info[#(info) - 1]] or not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,
2498 arg = "$parent.invert",
2499 },
2500 sep3 = {order = 3, type = "description", name = "", hidden = function(info) return not ShadowUF.modules[info[#(info) - 1]] or not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,},
2501 order = {
2502 order = 4,
2503 type = "range",
2504 name = L["Order"],
2505 min = 0, max = 100, step = 5,
2506 hidden = hideBarOption,
2507 arg = "$parent.order",
2508 },
2509 height = {
2510 order = 5,
2511 type = "range",
2512 name = L["Height"],
2513 desc = L["How much of the frames total height this bar should get, this is a weighted value, the higher it is the more it gets."],
2514 min = 0, max = 10, step = 0.1,
2515 hidden = hideBarOption,
2516 arg = "$parent.height",
2517 }
2518 },
2519 }
2520
2521 Config.indicatorTable = {
2522 order = 0,
2523 name = function(info)
2524 if( info[#(info)] == "status" and info[2] == "player" ) then
2525 return L["Combat/resting status"]
2526 end
2527
2528 return getName(info)
2529 end,
2530 desc = function(info) return INDICATOR_DESC[info[#(info)]] end,
2531 type = "group",
2532 hidden = hideRestrictedOption,
2533 args = {
2534 enabled = {
2535 order = 0,
2536 type = "toggle",
2537 name = L["Enable indicator"],
2538 hidden = false,
2539 arg = "indicators.$parent.enabled",
2540 },
2541 sep1 = {
2542 order = 1,
2543 type = "description",
2544 name = "",
2545 width = "full",
2546 hidden = function() return not ShadowUF.db.profile.advanced end,
2547 },
2548 anchorPoint = {
2549 order = 2,
2550 type = "select",
2551 name = L["Anchor point"],
2552 values = positionList,
2553 hidden = false,
2554 arg = "indicators.$parent.anchorPoint",
2555 },
2556 size = {
2557 order = 4,
2558 type = "range",
2559 name = L["Size"],
2560 min = 1, max = 40, step = 1,
2561 hidden = hideAdvancedOption,
2562 arg = "indicators.$parent.size",
2563 },
2564 x = {
2565 order = 5,
2566 type = "range",
2567 name = L["X Offset"],
2568 min = -100, max = 100, step = 1, softMin = -50, softMax = 50,
2569 hidden = false,
2570 arg = "indicators.$parent.x",
2571 },
2572 y = {
2573 order = 6,
2574 type = "range",
2575 name = L["Y Offset"],
2576 min = -100, max = 100, step = 1, softMin = -50, softMax = 50,
2577 hidden = false,
2578 arg = "indicators.$parent.y",
2579 },
2580 },
2581 }
2582
2583 Config.unitTable = {
2584 type = "group",
2585 childGroups = "tab",
2586 order = getUnitOrder,
2587 name = getName,
2588 hidden = isUnitDisabled,
2589 args = {
2590 general = {
2591 order = 1,
2592 name = L["General"],
2593 type = "group",
2594 hidden = isModifiersSet,
2595 set = setUnit,
2596 get = getUnit,
2597 args = {
2598 vehicle = {
2599 order = 1,
2600 type = "group",
2601 inline = true,
2602 name = L["Vehicles"],
2603 hidden = function(info) return info[2] ~= "player" and info[2] ~= "party" or not ShadowUF.db.profile.advanced end,
2604 args = {
2605 disable = {
2606 order = 0,
2607 type = "toggle",
2608 name = L["Disable vehicle swap"],
2609 desc = L["Disables the unit frame from turning into a vehicle when the player enters one."],
2610 set = function(info, value)
2611 setUnit(info, value)
2612 local unit = info[2]
2613 if( unit == "player" ) then
2614 if( ShadowUF.Units.unitFrames.pet ) then
2615 ShadowUF.Units.unitFrames.pet:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units[unit].disableVehicle)
2616 end
2617
2618 if( ShadowUF.Units.unitFrames.player ) then
2619 ShadowUF.Units:CheckVehicleStatus(ShadowUF.Units.unitFrames.player)
2620 end
2621 elseif( unit == "party" ) then
2622 for frame in pairs(ShadowUF.Units.unitFrames) do
2623 if( frame.unitType == "partypet" ) then
2624 frame:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units[unit].disableVehicle)
2625 elseif( frame.unitType == "party" ) then
2626 ShadowUF.Units:CheckVehicleStatus(frame)
2627 end
2628 end
2629 end
2630 end,
2631 arg = "disableVehicle",
2632 },
2633 },
2634 },
2635 portrait = {
2636 order = 2,
2637 type = "group",
2638 inline = true,
2639 hidden = false,
2640 name = L["Portrait"],
2641 args = {
2642 portrait = {
2643 order = 0,
2644 type = "toggle",
2645 name = string.format(L["Enable %s"], L["Portrait"]),
2646 arg = "portrait.enabled",
2647 },
2648 portraitType = {
2649 order = 1,
2650 type = "select",
2651 name = L["Portrait type"],
2652 values = {["class"] = L["Class icon"], ["2D"] = L["2D"], ["3D"] = L["3D"]},
2653 arg = "portrait.type",
2654 },
2655 alignment = {
2656 order = 2,
2657 type = "select",
2658 name = L["Position"],
2659 values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
2660 arg = "portrait.alignment",
2661 },
2662 },
2663 },
2664 fader = {
2665 order = 3,
2666 type = "group",
2667 inline = true,
2668 name = L["Combat fader"],
2669 hidden = hideRestrictedOption,
2670 args = {
2671 fader = {
2672 order = 0,
2673 type = "toggle",
2674 name = string.format(L["Enable %s"], L["Combat fader"]),
2675 desc = L["Combat fader will fade out all your frames while they are inactive and fade them back in once you are in combat or active."],
2676 hidden = false,
2677 arg = "fader.enabled"
2678 },
2679 combatAlpha = {
2680 order = 1,
2681 type = "range",
2682 name = L["Combat alpha"],
2683 desc = L["Frame alpha while this unit is in combat."],
2684 min = 0, max = 1.0, step = 0.1,
2685 arg = "fader.combatAlpha",
2686 hidden = false,
2687 isPercent = true,
2688 },
2689 inactiveAlpha = {
2690 order = 2,
2691 type = "range",
2692 name = L["Inactive alpha"],
2693 desc = L["Frame alpha when you are out of combat while having no target and 100% mana or energy."],
2694 min = 0, max = 1.0, step = 0.1,
2695 arg = "fader.inactiveAlpha",
2696 hidden = false,
2697 isPercent = true,
2698 },
2699 }
2700 },
2701 range = {
2702 order = 3,
2703 type = "group",
2704 inline = true,
2705 name = L["Range indicator"],
2706 hidden = hideRestrictedOption,
2707 args = {
2708 fader = {
2709 order = 0,
2710 type = "toggle",
2711 name = string.format(L["Enable %s"], L["Range indicator"]),
2712 desc = L["Fades out the unit frames of people who are not within range of you."],
2713 arg = "range.enabled",
2714 hidden = false,
2715 },
2716 inAlpha = {
2717 order = 1,
2718 type = "range",
2719 name = L["In range alpha"],
2720 desc = L["Frame alpha while this unit is in combat."],
2721 min = 0, max = 1.0, step = 0.05,
2722 arg = "range.inAlpha",
2723 hidden = false,
2724 isPercent = true,
2725 },
2726 oorAlpha = {
2727 order = 2,
2728 type = "range",
2729 name = L["Out of range alpha"],
2730 min = 0, max = 1.0, step = 0.05,
2731 arg = "range.oorAlpha",
2732 hidden = false,
2733 isPercent = true,
2734 },
2735 }
2736 },
2737 highlight = {
2738 order = 3.5,
2739 type = "group",
2740 inline = true,
2741 name = L["Border highlighting"],
2742 hidden = hideRestrictedOption,
2743 args = {
2744 mouseover = {
2745 order = 3,
2746 type = "toggle",
2747 name = L["On mouseover"],
2748 desc = L["Highlight units when you mouse over them."],
2749 arg = "highlight.mouseover",
2750 hidden = false,
2751 },
2752 attention = {
2753 order = 4,
2754 type = "toggle",
2755 name = L["For target/focus"],
2756 desc = L["Highlight units that you are targeting or have focused."],
2757 arg = "highlight.attention",
2758 hidden = function(info) return info[2] == "target" or info[2] == "focus" end,
2759 },
2760 aggro = {
2761 order = 5,
2762 type = "toggle",
2763 name = L["On aggro"],
2764 desc = L["Highlight units that have aggro on any mob."],
2765 arg = "highlight.aggro",
2766 hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or info[2] == "battlegroundpet" or info[2] == "arenapet" or ShadowUF.fakeUnits[info[2]] end,
2767 },
2768 debuff = {
2769 order = 6,
2770 type = "toggle",
2771 name = L["On curable debuff"],
2772 desc = L["Highlight units that are debuffed with something you can cure."],
2773 arg = "highlight.debuff",
2774 hidden = function(info) return info[2] ~= "boss" and ( ShadowUF.Units.zoneUnits[info[2]] or info[2] == "battlegroundpet" or info[2] == "arenapet" ) end,
2775 },
2776 raremob = {
2777 order = 6.10,
2778 type = "toggle",
2779 name = L["On rare mobs"],
2780 desc = L["Highlight units that are rare."],
2781 arg = "highlight.rareMob",
2782 hidden = function(info) return not (info[2] == "target" or info[2] == "focus" or info[2] == "targettarget" or info[3] == "focustarget") end,
2783 },
2784 elitemob = {
2785 order = 6.15,
2786 type = "toggle",
2787 name = L["On elite mobs"],
2788 desc = L["Highlight units that are "],
2789 arg = "highlight.eliteMob",
2790 hidden = function(info) return not (info[2] == "target" or info[2] == "focus" or info[2] == "targettarget" or info[3] == "focustarget") end,
2791 },
2792 sep = {
2793 order = 6.5,
2794 type = "description",
2795 name = "",
2796 width = "full",
2797 hidden = function(info) return not (ShadowUF.Units.zoneUnits[info[2]] or info[2] == "battlegroundpet" or info[2] == "arenapet" or ShadowUF.fakeUnits[info[2]]) and not (info[2] == "target" or info[2] == "focus" or info[2] == "targettarget" or info[3] == "focustarget") end,
2798 },
2799 alpha = {
2800 order = 7,
2801 type = "range",
2802 name = L["Border alpha"],
2803 min = 0, max = 1, step = 0.05,
2804 isPercent = true,
2805 hidden = false,
2806 arg = "highlight.alpha",
2807 },
2808 size = {
2809 order = 8,
2810 type = "range",
2811 name = L["Border thickness"],
2812 min = 0, max = 50, step = 1,
2813 arg = "highlight.size",
2814 hidden = false,
2815 },
2816 },
2817 },
2818 -- SOUL SHARDS
2819 barSouls = {
2820 order = 4,
2821 type = "group",
2822 inline = true,
2823 name = L["Soul Shards"],
2824 hidden = function(info) return playerClass ~= "WARLOCK" or not getVariable(info[2], "soulShards", nil, "isBar") or not getVariable(info[2], nil, nil, "soulShards") end,
2825 args = {
2826 enabled = {
2827 order = 1,
2828 type = "toggle",
2829 name = string.format(L["Enable %s"], L["Soul Shards"]),
2830 hidden = false,
2831 arg = "soulShards.enabled",
2832 },
2833 growth = {
2834 order = 2,
2835 type = "select",
2836 name = L["Growth"],
2837 values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
2838 hidden = false,
2839 arg = "soulShards.growth",
2840 },
2841 showAlways = {
2842 order = 3,
2843 type = "toggle",
2844 name = L["Don't hide when empty"],
2845 hidden = false,
2846 arg = "soulShards.showAlways",
2847 },
2848 },
2849 },
2850 soulShards = {
2851 order = 4,
2852 type = "group",
2853 inline = true,
2854 name = L["Soul Shards"],
2855 hidden = function(info) if( info[2] == "global" or getVariable(info[2], "soulShards", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
2856 args = {
2857 enabled = {
2858 order = 0,
2859 type = "toggle",
2860 name = string.format(L["Enable %s"], L["Soul Shards"]),
2861 hidden = false,
2862 arg = "soulShards.enabled",
2863 },
2864 sep1 = {
2865 order = 1,
2866 type = "description",
2867 name = "",
2868 width = "full",
2869 hidden = hideAdvancedOption,
2870 },
2871 growth = {
2872 order = 2,
2873 type = "select",
2874 name = L["Growth"],
2875 values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
2876 hidden = false,
2877 arg = "soulShards.growth",
2878 },
2879 size = {
2880 order = 2,
2881 type = "range",
2882 name = L["Size"],
2883 min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
2884 hidden = hideAdvancedOption,
2885 arg = "soulShards.size",
2886 },
2887 spacing = {
2888 order = 3,
2889 type = "range",
2890 name = L["Spacing"],
2891 min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
2892 hidden = hideAdvancedOption,
2893 arg = "soulShards.spacing",
2894 },
2895 sep2 = {
2896 order = 4,
2897 type = "description",
2898 name = "",
2899 width = "full",
2900 hidden = hideAdvancedOption,
2901 },
2902 anchorPoint = {
2903 order = 5,
2904 type = "select",
2905 name = L["Anchor point"],
2906 values = positionList,
2907 hidden = false,
2908 arg = "soulShards.anchorPoint",
2909 },
2910 x = {
2911 order = 6,
2912 type = "range",
2913 name = L["X Offset"],
2914 min = -30, max = 30, step = 1,
2915 hidden = false,
2916 arg = "soulShards.x",
2917 },
2918 y = {
2919 order = 7,
2920 type = "range",
2921 name = L["Y Offset"],
2922 min = -30, max = 30, step = 1,
2923 hidden = false,
2924 arg = "soulShards.y",
2925 },
2926 },
2927 },
2928 -- ARCANE CHARGES
2929 barArcane = {
2930 order = 4,
2931 type = "group",
2932 inline = true,
2933 name = L["Arcane Charges"],
2934 hidden = function(info) return playerClass ~= "MAGE" or not getVariable(info[2], "arcaneCharges", nil, "isBar") or not getVariable(info[2], nil, nil, "arcaneCharges") end,
2935 args = {
2936 enabled = {
2937 order = 1,
2938 type = "toggle",
2939 name = string.format(L["Enable %s"], L["Arcane Charges"]),
2940 hidden = false,
2941 arg = "arcaneCharges.enabled",
2942 },
2943 growth = {
2944 order = 2,
2945 type = "select",
2946 name = L["Growth"],
2947 values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
2948 hidden = false,
2949 arg = "arcaneCharges.growth",
2950 },
2951 showAlways = {
2952 order = 3,
2953 type = "toggle",
2954 name = L["Don't hide when empty"],
2955 hidden = false,
2956 arg = "arcaneCharges.showAlways",
2957 },
2958 },
2959 },
2960 arcaneCharges = {
2961 order = 4,
2962 type = "group",
2963 inline = true,
2964 name = L["Arcane Charges"],
2965 hidden = function(info) if( info[2] == "global" or getVariable(info[2], "arcaneCharges", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
2966 args = {
2967 enabled = {
2968 order = 0,
2969 type = "toggle",
2970 name = string.format(L["Enable %s"], L["Arcane Charges"]),
2971 hidden = false,
2972 arg = "arcaneCharges.enabled",
2973 },
2974 sep1 = {
2975 order = 1,
2976 type = "description",
2977 name = "",
2978 width = "full",
2979 hidden = hideAdvancedOption,
2980 },
2981 growth = {
2982 order = 2,
2983 type = "select",
2984 name = L["Growth"],
2985 values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
2986 hidden = false,
2987 arg = "arcaneCharges.growth",
2988 },
2989 size = {
2990 order = 2,
2991 type = "range",
2992 name = L["Size"],
2993 min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
2994 hidden = hideAdvancedOption,
2995 arg = "arcaneCharges.size",
2996 },
2997 spacing = {
2998 order = 3,
2999 type = "range",
3000 name = L["Spacing"],
3001 min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
3002 hidden = hideAdvancedOption,
3003 arg = "arcaneCharges.spacing",
3004 },
3005 sep2 = {
3006 order = 4,
3007 type = "description",
3008 name = "",
3009 width = "full",
3010 hidden = hideAdvancedOption,
3011 },
3012 anchorPoint = {
3013 order = 5,
3014 type = "select",
3015 name = L["Anchor point"],
3016 values = positionList,
3017 hidden = false,
3018 arg = "arcaneCharges.anchorPoint",
3019 },
3020 x = {
3021 order = 6,
3022 type = "range",
3023 name = L["X Offset"],
3024 min = -30, max = 30, step = 1,
3025 hidden = false,
3026 arg = "arcaneCharges.x",
3027 },
3028 y = {
3029 order = 7,
3030 type = "range",
3031 name = L["Y Offset"],
3032 min = -30, max = 30, step = 1,
3033 hidden = false,
3034 arg = "arcaneCharges.y",
3035 },
3036 },
3037 },
3038 -- HOLY POWER
3039 barHolyPower = {
3040 order = 4,
3041 type = "group",
3042 inline = true,
3043 name = L["Holy Power"],
3044 hidden = function(info) return playerClass ~= "PALADIN" or not getVariable(info[2], "holyPower", nil, "isBar") or not getVariable(info[2], nil, nil, "holyPower") end,
3045 args = {
3046 enabled = {
3047 order = 1,
3048 type = "toggle",
3049 name = string.format(L["Enable %s"], L["Holy Power"]),
3050 hidden = false,
3051 arg = "holyPower.enabled",
3052 },
3053 growth = {
3054 order = 2,
3055 type = "select",
3056 name = L["Growth"],
3057 values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
3058 hidden = false,
3059 arg = "holyPower.growth",
3060 },
3061 showAlways = {
3062 order = 3,
3063 type = "toggle",
3064 name = L["Don't hide when empty"],
3065 hidden = false,
3066 arg = "holyPower.showAlways",
3067 },
3068 },
3069 },
3070 holyPower = {
3071 order = 4,
3072 type = "group",
3073 inline = true,
3074 name = L["Holy Power"],
3075 hidden = function(info) if( info[2] == "global" or getVariable(info[2], "holyPower", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
3076 args = {
3077 enabled = {
3078 order = 0,
3079 type = "toggle",
3080 name = string.format(L["Enable %s"], L["Holy Power"]),
3081 hidden = false,
3082 arg = "holyPower.enabled",
3083 },
3084 sep1 = {
3085 order = 1,
3086 type = "description",
3087 name = "",
3088 width = "full",
3089 hidden = hideAdvancedOption,
3090 },
3091 growth = {
3092 order = 2,
3093 type = "select",
3094 name = L["Growth"],
3095 values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
3096 hidden = false,
3097 arg = "holyPower.growth",
3098 },
3099 size = {
3100 order = 2,
3101 type = "range",
3102 name = L["Size"],
3103 min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
3104 hidden = hideAdvancedOption,
3105 arg = "holyPower.size",
3106 },
3107 spacing = {
3108 order = 3,
3109 type = "range",
3110 name = L["Spacing"],
3111 min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
3112 hidden = hideAdvancedOption,
3113 arg = "holyPower.spacing",
3114 },
3115 sep2 = {
3116 order = 4,
3117 type = "description",
3118 name = "",
3119 width = "full",
3120 hidden = hideAdvancedOption,
3121 },
3122 anchorPoint = {
3123 order = 5,
3124 type = "select",
3125 name = L["Anchor point"],
3126 values = positionList,
3127 hidden = false,
3128 arg = "holyPower.anchorPoint",
3129 },
3130 x = {
3131 order = 6,
3132 type = "range",
3133 name = L["X Offset"],
3134 min = -30, max = 30, step = 1,
3135 hidden = false,
3136 arg = "holyPower.x",
3137 },
3138 y = {
3139 order = 7,
3140 type = "range",
3141 name = L["Y Offset"],
3142 min = -30, max = 30, step = 1,
3143 hidden = false,
3144 arg = "holyPower.y",
3145 },
3146 },
3147 },
3148 -- SHADOW ORBS
3149 barShadowOrbs = {
3150 order = 4,
3151 type = "group",
3152 inline = true,
3153 name = L["Shadow Orbs"],
3154 hidden = function(info) return playerClass ~= "PRIEST" or not getVariable(info[2], "shadowOrbs", nil, "isBar") or not getVariable(info[2], nil, nil, "shadowOrbs") end,
3155 args = {
3156 enabled = {
3157 order = 1,
3158 type = "toggle",
3159 name = string.format(L["Enable %s"], L["Shadow Orbs"]),
3160 hidden = false,
3161 arg = "shadowOrbs.enabled",
3162 },
3163 growth = {
3164 order = 2,
3165 type = "select",
3166 name = L["Growth"],
3167 values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
3168 hidden = false,
3169 arg = "shadowOrbs.growth",
3170 },
3171 showAlways = {
3172 order = 3,
3173 type = "toggle",
3174 name = L["Don't hide when empty"],
3175 hidden = false,
3176 arg = "shadowOrbs.showAlways",
3177 },
3178 },
3179 },
3180 shadowOrbs = {
3181 order = 4,
3182 type = "group",
3183 inline = true,
3184 name = L["Holy Power"],
3185 hidden = function(info) if( info[2] == "global" or getVariable(info[2], "shadowOrbs", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
3186 args = {
3187 enabled = {
3188 order = 0,
3189 type = "toggle",
3190 name = string.format(L["Enable %s"], L["Shadow Orbs"]),
3191 hidden = false,
3192 arg = "shadowOrbs.enabled",
3193 },
3194 sep1 = {
3195 order = 1,
3196 type = "description",
3197 name = "",
3198 width = "full",
3199 hidden = hideAdvancedOption,
3200 },
3201 growth = {
3202 order = 2,
3203 type = "select",
3204 name = L["Growth"],
3205 values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
3206 hidden = false,
3207 arg = "shadowOrbs.growth",
3208 },
3209 size = {
3210 order = 2,
3211 type = "range",
3212 name = L["Size"],
3213 min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
3214 hidden = hideAdvancedOption,
3215 arg = "shadowOrbs.size",
3216 },
3217 spacing = {
3218 order = 3,
3219 type = "range",
3220 name = L["Spacing"],
3221 min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
3222 hidden = hideAdvancedOption,
3223 arg = "shadowOrbs.spacing",
3224 },
3225 sep2 = {
3226 order = 4,
3227 type = "description",
3228 name = "",
3229 width = "full",
3230 hidden = hideAdvancedOption,
3231 },
3232 anchorPoint = {
3233 order = 5,
3234 type = "select",
3235 name = L["Anchor point"],
3236 values = positionList,
3237 hidden = false,
3238 arg = "shadowOrbs.anchorPoint",
3239 },
3240 x = {
3241 order = 6,
3242 type = "range",
3243 name = L["X Offset"],
3244 min = -30, max = 30, step = 1,
3245 hidden = false,
3246 arg = "shadowOrbs.x",
3247 },
3248 y = {
3249 order = 7,
3250 type = "range",
3251 name = L["Y Offset"],
3252 min = -30, max = 30, step = 1,
3253 hidden = false,
3254 arg = "shadowOrbs.y",
3255 },
3256 },
3257 },
3258 -- Chi
3259 barChi = {
3260 order = 4,
3261 type = "group",
3262 inline = true,
3263 name = L["Chi"],
3264 hidden = function(info) return playerClass ~= "MONK" or not getVariable(info[2], "chi", nil, "isBar") or not getVariable(info[2], nil, nil, "chi") end,
3265 args = {
3266 enabled = {
3267 order = 1,
3268 type = "toggle",
3269 name = string.format(L["Enable %s"], L["Chi"]),
3270 hidden = false,
3271 arg = "chi.enabled",
3272 },
3273 growth = {
3274 order = 2,
3275 type = "select",
3276 name = L["Growth"],
3277 values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
3278 hidden = false,
3279 arg = "chi.growth",
3280 },
3281 showAlways = {
3282 order = 3,
3283 type = "toggle",
3284 name = L["Don't hide when empty"],
3285 hidden = false,
3286 arg = "chi.showAlways",
3287 },
3288 },
3289 },
3290 chi = {
3291 order = 4,
3292 type = "group",
3293 inline = true,
3294 name = L["Chi"],
3295 hidden = function(info) if( info[2] == "global" or getVariable(info[2], "chi", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
3296 args = {
3297 enabled = {
3298 order = 0,
3299 type = "toggle",
3300 name = string.format(L["Enable %s"], L["Chi"]),
3301 hidden = false,
3302 arg = "chi.enabled",
3303 },
3304 sep1 = {
3305 order = 1,
3306 type = "description",
3307 name = "",
3308 width = "full",
3309 hidden = hideAdvancedOption,
3310 },
3311 growth = {
3312 order = 2,
3313 type = "select",
3314 name = L["Growth"],
3315 values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
3316 hidden = false,
3317 arg = "chi.growth",
3318 },
3319 size = {
3320 order = 2,
3321 type = "range",
3322 name = L["Size"],
3323 min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
3324 hidden = hideAdvancedOption,
3325 arg = "chi.size",
3326 },
3327 spacing = {
3328 order = 3,
3329 type = "range",
3330 name = L["Spacing"],
3331 min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
3332 hidden = hideAdvancedOption,
3333 arg = "chi.spacing",
3334 },
3335 sep2 = {
3336 order = 4,
3337 type = "description",
3338 name = "",
3339 width = "full",
3340 hidden = hideAdvancedOption,
3341 },
3342 anchorPoint = {
3343 order = 5,
3344 type = "select",
3345 name = L["Anchor point"],
3346 values = positionList,
3347 hidden = false,
3348 arg = "chi.anchorPoint",
3349 },
3350 x = {
3351 order = 6,
3352 type = "range",
3353 name = L["X Offset"],
3354 min = -30, max = 30, step = 1,
3355 hidden = false,
3356 arg = "chi.x",
3357 },
3358 y = {
3359 order = 7,
3360 type = "range",
3361 name = L["Y Offset"],
3362 min = -30, max = 30, step = 1,
3363 hidden = false,
3364 arg = "chi.y",
3365 },
3366 },
3367 },
3368 -- COMBO POINTS
3369 barComboPoints = {
3370 order = 4,
3371 type = "group",
3372 inline = true,
3373 name = L["Combo points"],
3374 hidden = function(info) return not getVariable(info[2], "comboPoints", nil, "isBar") or not getVariable(info[2], nil, nil, "comboPoints") end,
3375 args = {
3376 enabled = {
3377 order = 1,
3378 type = "toggle",
3379 name = string.format(L["Enable %s"], L["Combo points"]),
3380 hidden = false,
3381 arg = "comboPoints.enabled",
3382 },
3383 growth = {
3384 order = 2,
3385 type = "select",
3386 name = L["Growth"],
3387 values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
3388 hidden = false,
3389 arg = "comboPoints.growth",
3390 },
3391 showAlways = {
3392 order = 3,
3393 type = "toggle",
3394 name = L["Don't hide when empty"],
3395 hidden = false,
3396 arg = "comboPoints.showAlways",
3397 },
3398 },
3399 },
3400 comboPoints = {
3401 order = 4,
3402 type = "group",
3403 inline = true,
3404 name = L["Combo points"],
3405 hidden = function(info) if( info[2] == "global" or getVariable(info[2], "comboPoints", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
3406 args = {
3407 enabled = {
3408 order = 0,
3409 type = "toggle",
3410 name = string.format(L["Enable %s"], L["Combo points"]),
3411 hidden = false,
3412 arg = "comboPoints.enabled",
3413 },
3414 sep1 = {
3415 order = 1,
3416 type = "description",
3417 name = "",
3418 width = "full",
3419 hidden = hideAdvancedOption,
3420 },
3421 growth = {
3422 order = 2,
3423 type = "select",
3424 name = L["Growth"],
3425 values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
3426 hidden = false,
3427 arg = "comboPoints.growth",
3428 },
3429 size = {
3430 order = 2,
3431 type = "range",
3432 name = L["Size"],
3433 min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
3434 hidden = hideAdvancedOption,
3435 arg = "comboPoints.size",
3436 },
3437 spacing = {
3438 order = 3,
3439 type = "range",
3440 name = L["Spacing"],
3441 min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
3442 hidden = hideAdvancedOption,
3443 arg = "comboPoints.spacing",
3444 },
3445 sep2 = {
3446 order = 4,
3447 type = "description",
3448 name = "",
3449 width = "full",
3450 hidden = hideAdvancedOption,
3451 },
3452 anchorPoint = {
3453 order = 5,
3454 type = "select",
3455 name = L["Anchor point"],
3456 values = positionList,
3457 hidden = false,
3458 arg = "comboPoints.anchorPoint",
3459 },
3460 x = {
3461 order = 6,
3462 type = "range",
3463 name = L["X Offset"],
3464 min = -30, max = 30, step = 1,
3465 hidden = false,
3466 arg = "comboPoints.x",
3467 },
3468 y = {
3469 order = 7,
3470 type = "range",
3471 name = L["Y Offset"],
3472 min = -30, max = 30, step = 1,
3473 hidden = false,
3474 arg = "comboPoints.y",
3475 },
3476 },
3477 },
3478 -- COMBO POINTS
3479 barAuraPoints = {
3480 order = 4,
3481 type = "group",
3482 inline = true,
3483 name = L["Aura Combo Points"],
3484 hidden = function(info) return not ShadowUF.modules.auraPoints or not getVariable(info[2], "auraPoints", nil, "isBar") or not getVariable(info[2], nil, nil, "auraPoints") end,
3485 args = {
3486 enabled = {
3487 order = 1,
3488 type = "toggle",
3489 name = string.format(L["Enable %s"], L["Aura Combo Points"]),
3490 hidden = false,
3491 arg = "auraPoints.enabled",
3492 },
3493 growth = {
3494 order = 2,
3495 type = "select",
3496 name = L["Growth"],
3497 values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
3498 hidden = false,
3499 arg = "auraPoints.growth",
3500 },
3501 showAlways = {
3502 order = 3,
3503 type = "toggle",
3504 name = L["Don't hide when empty"],
3505 hidden = false,
3506 arg = "auraPoints.showAlways",
3507 },
3508 },
3509 },
3510 auraPoints = {
3511 order = 4,
3512 type = "group",
3513 inline = true,
3514 name = L["Aura Combo Points"],
3515 hidden = function(info) if( info[2] == "global" or getVariable(info[2], "auraPoints", nil, "isBar") ) then return true end return not ShadowUF.modules.auraPoints or hideRestrictedOption(info) end,
3516 args = {
3517 enabled = {
3518 order = 0,
3519 type = "toggle",
3520 name = string.format(L["Enable %s"], L["Aura Combo Points"]),
3521 hidden = false,
3522 arg = "auraPoints.enabled",
3523 },
3524 sep1 = {
3525 order = 1,
3526 type = "description",
3527 name = "",
3528 width = "full",
3529 hidden = hideAdvancedOption,
3530 },
3531 growth = {
3532 order = 2,
3533 type = "select",
3534 name = L["Growth"],
3535 values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
3536 hidden = false,
3537 arg = "auraPoints.growth",
3538 },
3539 size = {
3540 order = 2,
3541 type = "range",
3542 name = L["Size"],
3543 min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
3544 hidden = hideAdvancedOption,
3545 arg = "auraPoints.size",
3546 },
3547 spacing = {
3548 order = 3,
3549 type = "range",
3550 name = L["Spacing"],
3551 min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
3552 hidden = hideAdvancedOption,
3553 arg = "auraPoints.spacing",
3554 },
3555 sep2 = {
3556 order = 4,
3557 type = "description",
3558 name = "",
3559 width = "full",
3560 hidden = hideAdvancedOption,
3561 },
3562 anchorPoint = {
3563 order = 5,
3564 type = "select",
3565 name = L["Anchor point"],
3566 values = positionList,
3567 hidden = false,
3568 arg = "auraPoints.anchorPoint",
3569 },
3570 x = {
3571 order = 6,
3572 type = "range",
3573 name = L["X Offset"],
3574 min = -30, max = 30, step = 1,
3575 hidden = false,
3576 arg = "auraPoints.x",
3577 },
3578 y = {
3579 order = 7,
3580 type = "range",
3581 name = L["Y Offset"],
3582 min = -30, max = 30, step = 1,
3583 hidden = false,
3584 arg = "auraPoints.y",
3585 },
3586 },
3587 },
3588 combatText = {
3589 order = 5,
3590 type = "group",
3591 inline = true,
3592 name = L["Combat text"],
3593 hidden = hideRestrictedOption,
3594 args = {
3595 combatText = {
3596 order = 0,
3597 type = "toggle",
3598 name = string.format(L["Enable %s"], L["Combat text"]),
3599 desc = L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."],
3600 arg = "combatText.enabled",
3601 hidden = false,
3602 },
3603 sep = {
3604 order = 1,
3605 type = "description",
3606 name = "",
3607 width = "full",
3608 hidden = hideAdvancedOption,
3609 },
3610 anchorPoint = {
3611 order = 3,
3612 type = "select",
3613 name = L["Anchor point"],
3614 values = positionList,
3615 arg = "combatText.anchorPoint",
3616 hidden = hideAdvancedOption,
3617 },
3618 x = {
3619 order = 4,
3620 type = "range",
3621 name = L["X Offset"],
3622 min = -50, max = 50, step = 1,
3623 arg = "combatText.x",
3624 hidden = hideAdvancedOption,
3625 },
3626 y = {
3627 order = 5,
3628 type = "range",
3629 name = L["Y Offset"],
3630 min = -50, max = 50, step = 1,
3631 arg = "combatText.y",
3632 hidden = hideAdvancedOption,
3633 },
3634 },
3635 },
3636 },
3637 },
3638 attributes = {
3639 order = 1.5,
3640 type = "group",
3641 name = function(info)
3642 return L.shortUnits[info[#(info) - 1]] or L.units[info[#(info) - 1]]
3643 end,
3644 hidden = function(info)
3645 local unit = info[#(info) - 1]
3646 return unit ~= "raid" and unit ~= "raidpet" and unit ~= "party" and unit ~= "mainassist" and unit ~= "maintank" and not ShadowUF.Units.zoneUnits[unit]
3647 end,
3648 set = function(info, value)
3649 setUnit(info, value)
3650
3651 ShadowUF.Units:ReloadHeader(info[2])
3652 ShadowUF.modules.movers:Update()
3653 end,
3654 get = getUnit,
3655 args = {
3656 show = {
3657 order = 0.5,
3658 type = "group",
3659 inline = true,
3660 name = L["Visibility"],
3661 hidden = function(info) return info[2] ~= "party" and info[2] ~= "raid" end,
3662 args = {
3663 showPlayer = {
3664 order = 0,
3665 type = "toggle",
3666 name = L["Show player in party"],
3667 desc = L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."],
3668 hidden = function(info) return info[2] ~= "party" end,
3669 arg = "showPlayer",
3670 },
3671 hideSemiRaidParty = {
3672 order = 1,
3673 type = "toggle",
3674 name = L["Hide in >5-man raids"],
3675 desc = L["Party frames are hidden while in a raid group with more than 5 people inside."],
3676 hidden = function(info) return info[2] ~= "party" end,
3677 set = function(info, value)
3678 if( value ) then
3679 setVariable(info[2], nil, nil, "hideAnyRaid", false)
3680 end
3681
3682 setVariable(info[2], nil, nil, "hideSemiRaid", value)
3683 ShadowUF.Units:ReloadHeader(info[#(info) - 3])
3684 end,
3685 arg = "hideSemiRaid",
3686 },
3687 hideRaid = {
3688 order = 2,
3689 type = "toggle",
3690 name = L["Hide in any raid"],
3691 desc = L["Party frames are hidden while in any sort of raid no matter how many people."],
3692 hidden = function(info) return info[2] ~= "party" end,
3693 set = function(info, value)
3694 if( value ) then
3695 setVariable(info[2], nil, nil, "hideSemiRaid", false)
3696 end
3697
3698 setVariable(info[2], nil, nil, "hideAnyRaid", value)
3699 ShadowUF.Units:ReloadHeader(info[#(info) - 3])
3700 end,
3701 arg = "hideAnyRaid",
3702 },
3703 separateFrames = {
3704 order = 3,
3705 type = "toggle",
3706 name = L["Separate raid frames"],
3707 desc = L["Splits raid frames into individual frames for each raid group instead of one single frame.|nNOTE! You cannot drag each group frame individualy, but how they grow is set through the column and row growth options."],
3708 hidden = function(info) return info[2] ~= "raid" end,
3709 arg = "frameSplit",
3710 },
3711 hideSemiRaidRaid = {
3712 order = 3.5,
3713 type = "toggle",
3714 name = L["Hide in <=5-man raids"],
3715 desc = L["Raid frames are hidden while in a raid group with 5 or less people inside."],
3716 hidden = function(info) return info[2] ~= "raid" end,
3717 set = function(info, value)
3718 setVariable(info[2], nil, nil, "hideSemiRaid", value)
3719 ShadowUF.Units:ReloadHeader(info[#(info) - 3])
3720 end,
3721 arg = "hideSemiRaid"
3722 },
3723 showInRaid = {
3724 order = 4,
3725 type = "toggle",
3726 name = L["Show party as raid"],
3727 hidden = hideRaidOption,
3728 set = function(info, value)
3729 setUnit(info, value)
3730
3731 ShadowUF.Units:ReloadHeader("party")
3732 ShadowUF.Units:ReloadHeader("raid")
3733 ShadowUF.modules.movers:Update()
3734 end,
3735 arg = "showParty",
3736 },
3737 },
3738 },
3739 general = {
3740 order = 1,
3741 type = "group",
3742 inline = true,
3743 name = L["General"],
3744 hidden = false,
3745 args = {
3746 offset = {
3747 order = 2,
3748 type = "range",
3749 name = L["Row offset"],
3750 desc = L["Spacing between each row"],
3751 min = -10, max = 100, step = 1,
3752 arg = "offset",
3753 },
3754 attribPoint = {
3755 order = 3,
3756 type = "select",
3757 name = L["Row growth"],
3758 desc = L["How the rows should grow when new group members are added."],
3759 values = {["TOP"] = L["Down"], ["BOTTOM"] = L["Up"], ["LEFT"] = L["Right"], ["RIGHT"] = L["Left"]},
3760 arg = "attribPoint",
3761 set = function(info, value)
3762 -- If you set the frames to grow left, the columns have to grow down or up as well
3763 local attribAnchorPoint = getVariable(info[2], nil, nil, "attribAnchorPoint")
3764 if( ( value == "LEFT" or value == "RIGHT" ) and attribAnchorPoint ~= "BOTTOM" and attribAnchorPoint ~= "TOP" ) then
3765 ShadowUF.db.profile.units[info[2]].attribAnchorPoint = "BOTTOM"
3766 elseif( ( value == "TOP" or value == "BOTTOM" ) and attribAnchorPoint ~= "LEFT" and attribAnchorPoint ~= "RIGHT" ) then
3767 ShadowUF.db.profile.units[info[2]].attribAnchorPoint = "RIGHT"
3768 end
3769
3770 setUnit(info, value)
3771
3772 local position = ShadowUF.db.profile.positions[info[2]]
3773 if( position.top and position.bottom ) then
3774 local point = ShadowUF.db.profile.units[info[2]].attribAnchorPoint == "RIGHT" and "RIGHT" or "LEFT"
3775 position.point = (ShadowUF.db.profile.units[info[2]].attribPoint == "BOTTOM" and "BOTTOM" or "TOP") .. point
3776 position.y = ShadowUF.db.profile.units[info[2]].attribPoint == "BOTTOM" and position.bottom or position.top
3777 end
3778
3779 ShadowUF.Units:ReloadHeader(info[2])
3780 ShadowUF.modules.movers:Update()
3781 end,
3782 },
3783 sep2 = {
3784 order = 4,
3785 type = "description",
3786 name = "",
3787 width = "full",
3788 hidden = false,
3789 },
3790 columnSpacing = {
3791 order = 5,
3792 type = "range",
3793 name = L["Column spacing"],
3794 min = -30, max = 100, step = 1,
3795 hidden = hideRaidOrAdvancedOption,
3796 arg = "columnSpacing",
3797 },
3798 attribAnchorPoint = {
3799 order = 6,
3800 type = "select",
3801 name = L["Column growth"],
3802 desc = L["How the frames should grow when a new column is added."],
3803 values = function(info)
3804 local attribPoint = getVariable(info[2], nil, nil, "attribPoint")
3805 if( attribPoint == "LEFT" or attribPoint == "RIGHT" ) then
3806 return {["TOP"] = L["Down"], ["BOTTOM"] = L["Up"]}
3807 end
3808
3809 return {["LEFT"] = L["Right"], ["RIGHT"] = L["Left"]}
3810 end,
3811 hidden = hideRaidOrAdvancedOption,
3812 set = function(info, value)
3813 -- If you set the frames to grow left, the columns have to grow down or up as well
3814 local attribPoint = getVariable(info[2], nil, nil, "attribPoint")
3815 if( ( value == "LEFT" or value == "RIGHT" ) and attribPoint ~= "BOTTOM" and attribPoint ~= "TOP" ) then
3816 ShadowUF.db.profile.units[info[2]].attribPoint = "BOTTOM"
3817 end
3818
3819 setUnit(info, value)
3820
3821 ShadowUF.Units:ReloadHeader(info[2])
3822 ShadowUF.modules.movers:Update()
3823 end,
3824 arg = "attribAnchorPoint",
3825 },
3826 sep3 = {
3827 order = 7,
3828 type = "description",
3829 name = "",
3830 width = "full",
3831 hidden = false,
3832 },
3833 maxColumns = {
3834 order = 8,
3835 type = "range",
3836 name = L["Max columns"],
3837 min = 1, max = 20, step = 1,
3838 arg = "maxColumns",
3839 hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideSplitOrRaidOption(info) end,
3840 },
3841 unitsPerColumn = {
3842 order = 8,
3843 type = "range",
3844 name = L["Units per column"],
3845 min = 1, max = 40, step = 1,
3846 arg = "unitsPerColumn",
3847 hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideSplitOrRaidOption(info) end,
3848 },
3849 partyPerColumn = {
3850 order = 9,
3851 type = "range",
3852 name = L["Units per column"],
3853 min = 1, max = 5, step = 1,
3854 arg = "unitsPerColumn",
3855 hidden = function(info) return info[2] ~= "party" or not ShadowUF.db.profile.advanced end,
3856 },
3857 groupsPerRow = {
3858 order = 8,
3859 type = "range",
3860 name = L["Groups per row"],
3861 desc = L["How many groups should be shown per row."],
3862 min = 1, max = 8, step = 1,
3863 arg = "groupsPerRow",
3864 hidden = function(info) return info[2] ~= "raid" or not ShadowUF.db.profile.units.raid.frameSplit end,
3865 },
3866 groupSpacing = {
3867 order = 9,
3868 type = "range",
3869 name = L["Group row spacing"],
3870 desc = L["How much spacing should be between each new row of groups."],
3871 min = -50, max = 50, step = 1,
3872 arg = "groupSpacing",
3873 hidden = function(info) return info[2] ~= "raid" or not ShadowUF.db.profile.units.raid.frameSplit end,
3874 },
3875 },
3876 },
3877 sort = {
3878 order = 2,
3879 type = "group",
3880 inline = true,
3881 name = L["Sorting"],
3882 hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or ( info[2] ~= "raid" and not ShadowUF.db.profile.advanced ) end,
3883 args = {
3884 sortMethod = {
3885 order = 2,
3886 type = "select",
3887 name = L["Sort method"],
3888 values = {["INDEX"] = L["Index"], ["NAME"] = L["Name"]},
3889 arg = "sortMethod",
3890 hidden = false,
3891 },
3892 sortOrder = {
3893 order = 2,
3894 type = "select",
3895 name = L["Sort order"],
3896 values = {["ASC"] = L["Ascending"], ["DESC"] = L["Descending"]},
3897 arg = "sortOrder",
3898 hidden = false,
3899 },
3900 },
3901 },
3902 raid = {
3903 order = 3,
3904 type = "group",
3905 inline = true,
3906 name = L["Groups"],
3907 hidden = hideRaidOption,
3908 args = {
3909 groupBy = {
3910 order = 4,
3911 type = "select",
3912 name = L["Group by"],
3913 values = {["GROUP"] = L["Group number"], ["CLASS"] = L["Class"], ["ASSIGNEDROLE"] = L["Assigned Role (DPS/Tank/etc)"]},
3914 arg = "groupBy",
3915 hidden = hideSplitOrRaidOption,
3916 },
3917 selectedGroups = {
3918 order = 7,
3919 type = "multiselect",
3920 name = L["Groups to show"],
3921 values = {string.format(L["Group %d"], 1), string.format(L["Group %d"], 2), string.format(L["Group %d"], 3), string.format(L["Group %d"], 4), string.format(L["Group %d"], 5), string.format(L["Group %d"], 6), string.format(L["Group %d"], 7), string.format(L["Group %d"], 8)},
3922 set = function(info, key, value)
3923 local tbl = getVariable(info[2], nil, nil, "filters")
3924 tbl[key] = value
3925
3926 setVariable(info[2], "filters", nil, tbl)
3927 ShadowUF.Units:ReloadHeader(info[2])
3928 ShadowUF.modules.movers:Update()
3929 end,
3930 get = function(info, key)
3931 return getVariable(info[2], nil, nil, "filters")[key]
3932 end,
3933 hidden = function(info) return info[2] ~= "raid" and info[2] ~= "raidpet" end,
3934 },
3935 },
3936 },
3937 },
3938 },
3939 frame = {
3940 order = 2,
3941 name = L["Frame"],
3942 type = "group",
3943 hidden = isModifiersSet,
3944 set = setUnit,
3945 get = getUnit,
3946 args = {
3947 size = {
3948 order = 0,
3949 type = "group",
3950 inline = true,
3951 name = L["Size"],
3952 hidden = false,
3953 set = function(info, value)
3954 setUnit(info, value)
3955 ShadowUF.modules.movers:Update()
3956 end,
3957 args = {
3958 scale = {
3959 order = 0,
3960 type = "range",
3961 name = L["Scale"],
3962 min = 0.25, max = 2, step = 0.01,
3963 isPercent = true,
3964 arg = "scale",
3965 },
3966 height = {
3967 order = 1,
3968 type = "range",
3969 name = L["Height"],
3970 min = 0, softMax = 100, step = 1,
3971 arg = "height",
3972 },
3973 width = {
3974 order = 2,
3975 type = "range",
3976 name = L["Width"],
3977 min = 0, softMax = 300, step = 1,
3978 arg = "width",
3979 },
3980 },
3981 },
3982 anchor = {
3983 order = 1,
3984 type = "group",
3985 inline = true,
3986 hidden = function(info) return info[2] == "global" end,
3987 name = L["Anchor to another frame"],
3988 set = setPosition,
3989 get = getPosition,
3990 args = {
3991 anchorPoint = {
3992 order = 0.50,
3993 type = "select",
3994 name = L["Anchor point"],
3995 values = positionList,
3996 hidden = false,
3997 get = function(info)
3998 local position = ShadowUF.db.profile.positions[info[2]]
3999 if( ShadowUF.db.profile.advanced ) then
4000 return position[info[#(info)]]
4001 end
4002
4003
4004 return position.movedAnchor or position[info[#(info)]]
4005 end,
4006 },
4007 anchorTo = {
4008 order = 1,
4009 type = "select",
4010 name = L["Anchor to"],
4011 values = getAnchorParents,
4012 hidden = false,
4013 },
4014 sep = {
4015 order = 2,
4016 type = "description",
4017 name = "",
4018 width = "full",
4019 hidden = false,
4020 },
4021 x = {
4022 order = 3,
4023 type = "input",
4024 name = L["X Offset"],
4025 validate = checkNumber,
4026 set = setNumber,
4027 get = getString,
4028 hidden = false,
4029 },
4030 y = {
4031 order = 4,
4032 type = "input",
4033 name = L["Y Offset"],
4034 validate = checkNumber,
4035 set = setNumber,
4036 get = getString,
4037 hidden = false,
4038 },
4039 },
4040 },
4041 orHeader = {
4042 order = 1.5,
4043 type = "header",
4044 name = L["Or you can set a position manually"],
4045 hidden = function(info) if( info[2] == "global" or hideAdvancedOption() ) then return true else return false end end,
4046 },
4047 position = {
4048 order = 2,
4049 type = "group",
4050 hidden = function(info) if( info[2] == "global" or hideAdvancedOption() ) then return true else return false end end,
4051 inline = true,
4052 name = L["Manual position"],
4053 set = setPosition,
4054 get = getPosition,
4055 args = {
4056 point = {
4057 order = 0,
4058 type = "select",
4059 name = L["Point"],
4060 values = pointPositions,
4061 hidden = false,
4062 },
4063 anchorTo = {
4064 order = 0.50,
4065 type = "select",
4066 name = L["Anchor to"],
4067 values = getAnchorParents,
4068 hidden = false,
4069 },
4070 relativePoint = {
4071 order = 1,
4072 type = "select",
4073 name = L["Relative point"],
4074 values = pointPositions,
4075 hidden = false,
4076 },
4077 sep = {
4078 order = 2,
4079 type = "description",
4080 name = "",
4081 width = "full",
4082 hidden = false,
4083 },
4084 x = {
4085 order = 3,
4086 type = "input",
4087 name = L["X Offset"],
4088 validate = checkNumber,
4089 set = setNumber,
4090 get = getString,
4091 hidden = false,
4092 },
4093 y = {
4094 order = 4,
4095 type = "input",
4096 name = L["Y Offset"],
4097 validate = checkNumber,
4098 set = setNumber,
4099 get = getString,
4100 hidden = false,
4101 },
4102 },
4103 },
4104 },
4105 },
4106 bars = {
4107 order = 3,
4108 name = L["Bars"],
4109 type = "group",
4110 hidden = isModifiersSet,
4111 set = setUnit,
4112 get = getUnit,
4113 args = {
4114 powerbar = {
4115 order = 1,
4116 type = "group",
4117 inline = false,
4118 name = L["Power bar"],
4119 hidden = false,
4120 args = {
4121 powerBar = {
4122 order = 1,
4123 type = "toggle",
4124 name = string.format(L["Enable %s"], L["Power bar"]),
4125 arg = "powerBar.enabled",
4126 },
4127 altPowerBar = {
4128 order = 3,
4129 type = "toggle",
4130 name = string.format(L["Enable %s"], L["Alt. Power bar"]),
4131 desc = L["Shows a bar for alternate power info (used in some encounters)"],
4132 hidden = function(info) return ShadowUF.fakeUnits[info[2]] or hideRestrictedOption(info) end,
4133 arg = "altPowerBar.enabled",
4134 },
4135 colorType = {
4136 order = 5,
4137 type = "select",
4138 name = L["Color power by"],
4139 desc = L["Primary means of coloring the power bar. Coloring by class only applies to players, for non-players it will default to the power type."],
4140 values = {["class"] = L["Class"], ["type"] = L["Power Type"]},
4141 arg = "powerBar.colorType",
4142 },
4143 onlyMana = {
4144 order = 6,
4145 type = "toggle",
4146 name = L["Only show when mana"],
4147 desc = L["Hides the power bar unless the class has mana."],
4148 hidden = function(info) return not ShadowUF.Units.headerUnits[info[2]] end,
4149 arg = "powerBar.onlyMana",
4150 }
4151 },
4152 },
4153 classmiscbars = {
4154 order = 2,
4155 type = "group",
4156 inline = false,
4157 name = L["Class/misc bars"],
4158 hidden = function(info)
4159 local unit = info[2]
4160 if( unit == "global" ) then
4161 return not globalConfig.runeBar and not globalConfig.totemBar and not globalConfig.druidBar and not globalConfig.priestBar and not globalConfig.shamanBar and not globalConfig.xpBar and not globalConfig.staggerBar
4162 else
4163 return unit ~= "player" and unit ~= "pet"
4164 end
4165 end,
4166 args = {
4167 runeBar = {
4168 order = 1,
4169 type = "toggle",
4170 name = string.format(L["Enable %s"], L["Rune bar"]),
4171 desc = L["Adds rune bars and timers before runes refresh to the player frame."],
4172 hidden = hideRestrictedOption,
4173 arg = "runeBar.enabled",
4174 },
4175 staggerBar = {
4176 order = 1.25,
4177 type = "toggle",
4178 name = string.format(L["Enable %s"], L["Stagger bar"]),
4179 desc = L["Adds a Stagger bar for Brewmaster Monks."],
4180 hidden = hideRestrictedOption,
4181 arg = "staggerBar.enabled",
4182 },
4183 druidBar = {
4184 order = 3,
4185 type = "toggle",
4186 name = string.format(L["Enable %s"], L["Druid mana bar"]),
4187 desc = L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."],
4188 hidden = hideRestrictedOption,
4189 arg = "druidBar.enabled",
4190 },
4191 priestBar = {
4192 order = 3,
4193 type = "toggle",
4194 name = string.format(L["Enable %s"], L["Priest mana bar"]),
4195 desc = L["Adds a mana bar to the player frame for shadow priests."],
4196 hidden = hideRestrictedOption,
4197 arg = "priestBar.enabled",
4198 },
4199 shamanBar = {
4200 order = 3,
4201 type = "toggle",
4202 name = string.format(L["Enable %s"], L["Shaman mana bar"]),
4203 desc = L["Adds a mana bar to the player frame for elemental and enhancement shamans."],
4204 hidden = hideRestrictedOption,
4205 arg = "shamanBar.enabled",
4206 },
4207 xpBar = {
4208 order = 4,
4209 type = "toggle",
4210 name = string.format(L["Enable %s"], L["XP/Rep bar"]),
4211 desc = L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."],
4212 hidden = hideRestrictedOption,
4213 arg = "xpBar.enabled",
4214 },
4215 },
4216 },
4217 healthBar = {
4218 order = 2,
4219 type = "group",
4220 inline = false,
4221 name = L["Health bar"],
4222 hidden = false,
4223 args = {
4224 enabled = {
4225 order = 1,
4226 type = "toggle",
4227 name = string.format(L["Enable %s"], L["Health bar"]),
4228 arg = "healthBar.enabled"
4229 },
4230 sep = {
4231 order = 3.5,
4232 type = "description",
4233 name = "",
4234 hidden = function(info) return not (info[2] == "player" or info[2] == "pet") end,
4235 },
4236 colorAggro = {
4237 order = 4,
4238 type = "toggle",
4239 name = L["Color on aggro"],
4240 desc = L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."],
4241 arg = "healthBar.colorAggro",
4242 hidden = hideRestrictedOption,
4243 },
4244 colorDispel = {
4245 order = 5,
4246 type = "toggle",
4247 name = L["Color on curable debuff"],
4248 desc = L["Changes the health bar to the color of any curable debuff."],
4249 arg = "healthBar.colorDispel",
4250 hidden = hideRestrictedOption,
4251 width = "full",
4252 },
4253 healthColor = {
4254 order = 6,
4255 type = "select",
4256 name = L["Color health by"],
4257 desc = L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."],
4258 values = function(info)
4259 if info[2] == "pet" or info[2] == "partypet" or info[2] == "raidpet" or info[2] == "arenapet" then
4260 return {["class"] = L["Class"], ["static"] = L["Static"], ["percent"] = L["Health percent"], ["playerclass"] = L["Player Class"]}
4261 else
4262 return {["class"] = L["Class"], ["static"] = L["Static"], ["percent"] = L["Health percent"]}
4263 end
4264 end,
4265 arg = "healthBar.colorType",
4266 },
4267 reaction = {
4268 order = 7,
4269 type = "select",
4270 name = L["Color by reaction on"],
4271 desc = L["When to color the health bar by the units reaction, overriding the color health by option."],
4272 arg = "healthBar.reactionType",
4273 values = {["none"] = L["Never (Disabled)"], ["player"] = L["Players only"], ["npc"] = L["NPCs only"], ["both"] = L["Both"]},
4274 hidden = function(info) return info[2] == "player" or info[2] == "pet" end,
4275 }
4276 },
4277 },
4278 healAbsorb = {
4279 order = 2.5,
4280 type = "group",
4281 inline = false,
4282 name = L["Heal absorbs"],
4283 hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideRestrictedOption(info) end,
4284 disabled = function(info) return not getVariable(info[2], "healthBar", nil, "enabled") end,
4285 args = {
4286 heals = {
4287 order = 1,
4288 type = "toggle",
4289 name = L["Show Heal Absorbs"],
4290 desc = L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."],
4291 arg = "healAbsorb.enabled",
4292 hidden = false,
4293 set = function(info, value)
4294 setUnit(info, value)
4295 setDirectUnit(info[2], "healAbsorb", nil, "enabled", getVariable(info[2], "healAbsorb", nil, "enabled"))
4296 end
4297 },
4298 cap = {
4299 order = 3,
4300 type = "range",
4301 name = L["Outside bar limit"],
4302 desc = L["Percentage value of how far outside the unit frame the absorbed health bar can go. 130% means it will go 30% outside the frame, 100% means it will not go outside."],
4303 min = 1, max = 1.50, step = 0.05, isPercent = true,
4304 arg = "healAbsorb.cap",
4305 hidden = false,
4306 },
4307 },
4308 },
4309 incHeal = {
4310 order = 3,
4311 type = "group",
4312 inline = false,
4313 name = L["Incoming heals"],
4314 hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideRestrictedOption(info) end,
4315 disabled = function(info) return not getVariable(info[2], "healthBar", nil, "enabled") end,
4316 args = {
4317 heals = {
4318 order = 1,
4319 type = "toggle",
4320 name = L["Show incoming heals"],
4321 desc = L["Adds a bar inside the health bar indicating how much healing someone will receive."],
4322 arg = "incHeal.enabled",
4323 hidden = false,
4324 set = function(info, value)
4325 setUnit(info, value)
4326 setDirectUnit(info[2], "incHeal", nil, "enabled", getVariable(info[2], "incHeal", nil, "enabled"))
4327 end
4328 },
4329 cap = {
4330 order = 3,
4331 type = "range",
4332 name = L["Outside bar limit"],
4333 desc = L["Percentage value of how far outside the unit frame the incoming heal bar can go. 130% means it will go 30% outside the frame, 100% means it will not go outside."],
4334 min = 1, max = 1.50, step = 0.05, isPercent = true,
4335 arg = "incHeal.cap",
4336 hidden = false,
4337 },
4338 },
4339 },
4340 incAbsorb = {
4341 order = 3.5,
4342 type = "group",
4343 inline = false,
4344 name = L["Incoming absorbs"],
4345 hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideRestrictedOption(info) end,
4346 disabled = function(info) return not getVariable(info[2], "healthBar", nil, "enabled") end,
4347 args = {
4348 heals = {
4349 order = 1,
4350 type = "toggle",
4351 name = L["Show incoming absorbs"],
4352 desc = L["Adds a bar inside the health bar indicating how much damage will be absorbed."],
4353 arg = "incAbsorb.enabled",
4354 hidden = false,
4355 set = function(info, value)
4356 setUnit(info, value)
4357 setDirectUnit(info[2], "incAbsorb", nil, "enabled", getVariable(info[2], "incAbsorb", nil, "enabled"))
4358 end
4359 },
4360 cap = {
4361 order = 3,
4362 type = "range",
4363 name = L["Outside bar limit"],
4364 desc = L["Percentage value of how far outside the unit frame the incoming absorb bar can go. 130% means it will go 30% outside the frame, 100% means it will not go outside."],
4365 min = 1, max = 1.50, step = 0.05, isPercent = true,
4366 arg = "incAbsorb.cap",
4367 hidden = false,
4368 },
4369 },
4370 },
4371 totemBar = {
4372 order = 3.6,
4373 type = "group",
4374 inline = false,
4375 name = ShadowUF.modules.totemBar.moduleName,
4376 hidden = function(info)
4377 local unit = info[2]
4378 if( unit == "global" ) then
4379 return not globalConfig.totemBar
4380 else
4381 return unit ~= "player" and unit ~= "pet"
4382 end
4383 end,
4384 args = {
4385 enabled = {
4386 order = 1,
4387 type = "toggle",
4388 name = string.format(L["Enable %s"], ShadowUF.modules.totemBar.moduleName),
4389 desc = function(info)
4390 return select(2, UnitClass("player")) == "SHAMAN" and L["Adds totem bars with timers before they expire to the player frame."] or select(2, UnitClass("player")) == "DEATHKNIGHT" and L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] or select(2, UnitClass("player")) == "MAGE" and L["Adds a bar indicating how much time is left on your Rune of Power."] or L["Adds a bar indicating how much time is left on your mushrooms."]
4391 end,
4392 arg = "totemBar.enabled",
4393 },
4394 icon = {
4395 order = 2,
4396 type = "toggle",
4397 name = L["Show icon durations"],
4398 desc = L["Uses the icon of the totem being shown instead of a status bar."],
4399 arg = "totemBar.icon",
4400 },
4401 secure = {
4402 order = 3,
4403 type = "toggle",
4404 name = L["Dismissable Totem bars"],
4405 hidden = function()
4406 return not ShadowUF.modules.totemBar:SecureLockable()
4407 end,
4408 desc = function(info)
4409 return L["Allows you to disable the totem by right clicking it.|n|nWarning: Inner bars for this unit will not resize in combat if you enable this."]
4410 end,
4411 arg = "totemBar.secure",
4412 }
4413 },
4414 },
4415 emptyBar = {
4416 order = 4,
4417 type = "group",
4418 inline = false,
4419 name = L["Empty bar"],
4420 hidden = false,
4421 args = {
4422 enabled = {
4423 order = 1,
4424 type = "toggle",
4425 name = string.format(L["Enable %s"], L["Empty bar"]),
4426 desc = L["Adds an empty bar that you can put text into as a way of uncluttering other bars."],
4427 arg = "emptyBar.enabled",
4428 width = "full"
4429 },
4430 overrideColor = {
4431 order = 4,
4432 type = "color",
4433 name = L["Background color"],
4434 disabled = function(info)
4435 local emptyBar = getVariable(info[2], nil, nil, "emptyBar")
4436 return emptyBar.class and emptyBar.reaciton
4437 end,
4438 set = function(info, r, g, b)
4439 local color = getUnit(info) or {}
4440 color.r = r
4441 color.g = g
4442 color.b = b
4443
4444 setUnit(info, color)
4445 end,
4446 get = function(info)
4447 local color = getUnit(info)
4448 if( not color ) then
4449 return 0, 0, 0
4450 end
4451
4452 return color.r, color.g, color.b
4453
4454 end,
4455 arg = "emptyBar.backgroundColor",
4456 width = "full"
4457 },
4458 reaction = {
4459 order = 2,
4460 type = "select",
4461 name = L["Color by reaction on"],
4462 desc = L["When to color the empty bar by reaction, overriding the default color by option."],
4463 arg = "emptyBar.reactionType",
4464 values = {["none"] = L["Never (Disabled)"], ["player"] = L["Players only"], ["npc"] = L["NPCs only"], ["both"] = L["Both"]},
4465 },
4466 colorType = {
4467 order = 3,
4468 type = "toggle",
4469 name = L["Color by class"],
4470 desc = L["Players will be colored by class."],
4471 arg = "emptyBar.class",
4472 },
4473 },
4474 },
4475 castBar = {
4476 order = 5,
4477 type = "group",
4478 inline = false,
4479 name = L["Cast bar"],
4480 hidden = hideRestrictedOption,
4481 args = {
4482 enabled = {
4483 order = 1,
4484 type = "toggle",
4485 name = string.format(L["Enable %s"], L["Cast bar"]),
4486 desc = function(info) return ShadowUF.fakeUnits[info[2]] and string.format(L["Due to the nature of fake units, cast bars for %s are not super efficient and can take at most 0.10 seconds to notice a change in cast."], L.units[info[2]] or info[2]) end,
4487 hidden = false,
4488 arg = "castBar.enabled",
4489 width = "full"
4490 },
4491 autoHide = {
4492 order = 2,
4493 type = "toggle",
4494 name = L["Hide bar when empty"],
4495 desc = L["Hides the cast bar if there is no cast active."],
4496 hidden = false,
4497 arg = "castBar.autoHide",
4498 },
4499 castIcon = {
4500 order = 2.5,
4501 type = "select",
4502 name = L["Cast icon"],
4503 arg = "castBar.icon",
4504 values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["HIDE"] = L["Disabled"]},
4505 hidden = false,
4506 },
4507 castName = {
4508 order = 3,
4509 type = "header",
4510 name = L["Cast name"],
4511 hidden = hideAdvancedOption,
4512 },
4513 nameEnabled = {
4514 order = 4,
4515 type = "toggle",
4516 name = L["Show cast name"],
4517 arg = "castBar.name.enabled",
4518 hidden = hideAdvancedOption,
4519 },
4520 nameAnchor = {
4521 order = 5,
4522 type = "select",
4523 name = L["Anchor point"],
4524 desc = L["Where to anchor the cast name text."],
4525 values = {["CLI"] = L["Inside Center Left"], ["CRI"] = L["Inside Center Right"]},
4526 hidden = hideAdvancedOption,
4527 arg = "castBar.name.anchorPoint",
4528 },
4529 nameSize = {
4530 order = 7,
4531 type = "range",
4532 name = L["Size"],
4533 desc = L["Let's you modify the base font size to either make it larger or smaller."],
4534 type = "range",
4535 min = -10, max = 10, step = 1, softMin = -5, softMax = 5,
4536 hidden = hideAdvancedOption,
4537 arg = "castBar.name.size",
4538 },
4539 nameX = {
4540 order = 8,
4541 type = "range",
4542 name = L["X Offset"],
4543 min = -20, max = 20, step = 1,
4544 hidden = hideAdvancedOption,
4545 arg = "castBar.name.x",
4546 },
4547 nameY = {
4548 order = 9,
4549 type = "range",
4550 name = L["Y Offset"],
4551 min = -20, max = 20, step = 1,
4552 hidden = hideAdvancedOption,
4553 arg = "castBar.name.y",
4554 },
4555 castTime = {
4556 order = 10,
4557 type = "header",
4558 name = L["Cast time"],
4559 hidden = hideAdvancedOption,
4560 },
4561 timeEnabled = {
4562 order = 11,
4563 type = "toggle",
4564 name = L["Show cast time"],
4565 arg = "castBar.time.enabled",
4566 hidden = hideAdvancedOption,
4567 width = "full"
4568 },
4569 timeAnchor = {
4570 order = 12,
4571 type = "select",
4572 name = L["Anchor point"],
4573 desc = L["Where to anchor the cast time text."],
4574 values = {["CLI"] = L["Inside Center Left"], ["CRI"] = L["Inside Center Right"]},
4575 hidden = hideAdvancedOption,
4576 arg = "castBar.time.anchorPoint",
4577 },
4578 timeSize = {
4579 order = 14,
4580 type = "range",
4581 name = L["Size"],
4582 desc = L["Let's you modify the base font size to either make it larger or smaller."],
4583 type = "range",
4584 min = -10, max = 10, step = 1, softMin = -5, softMax = 5,
4585 hidden = hideAdvancedOption,
4586 arg = "castBar.time.size",
4587 },
4588 timeX = {
4589 order = 15,
4590 type = "range",
4591 name = L["X Offset"],
4592 min = -20, max = 20, step = 1,
4593 hidden = hideAdvancedOption,
4594 arg = "castBar.time.x",
4595 },
4596 timeY = {
4597 order = 16,
4598 type = "range",
4599 name = L["Y Offset"],
4600 min = -20, max = 20, step = 1,
4601 hidden = hideAdvancedOption,
4602 arg = "castBar.time.y",
4603 },
4604 },
4605 },
4606 },
4607 },
4608 widgetSize = {
4609 order = 4,
4610 name = L["Widget Size"],
4611 type = "group",
4612 hidden = isModifiersSet,
4613 set = setUnit,
4614 get = getUnit,
4615 args = {
4616 help = {
4617 order = 0,
4618 type = "group",
4619 name = L["Help"],
4620 inline = true,
4621 hidden = false,
4622 args = {
4623 help = {
4624 order = 0,
4625 type = "description",
4626 name = L["Bars with an order higher or lower than the full size options will use the entire unit frame width.|n|nBar orders between those two numbers are shown next to the portrait."],
4627 },
4628 },
4629 },
4630 portrait = {
4631 order = 0.5,
4632 type = "group",
4633 name = L["Portrait"],
4634 inline = false,
4635 hidden = false,
4636 args = {
4637 enableBar = {
4638 order = 1,
4639 type = "toggle",
4640 name = L["Show as bar"],
4641 desc = L["Changes this widget into a bar, you will be able to change the height and ordering like you can change health and power bars."],
4642 arg = "$parent.isBar",
4643 },
4644 sep = {
4645 order = 1.5,
4646 type = "description",
4647 name = "",
4648 width = "full",
4649 hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
4650 },
4651 width = {
4652 order = 2,
4653 type = "range",
4654 name = L["Width percent"],
4655 desc = L["Percentage of width the portrait should use."],
4656 min = 0, max = 1.0, step = 0.01, isPercent = true,
4657 hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
4658 arg = "$parent.width",
4659 },
4660 before = {
4661 order = 3,
4662 type = "range",
4663 name = L["Full size before"],
4664 min = 0, max = 100, step = 5,
4665 hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
4666 arg = "$parent.fullBefore",
4667 },
4668 after = {
4669 order = 4,
4670 type = "range",
4671 name = L["Full size after"],
4672 min = 0, max = 100, step = 5,
4673 hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
4674 arg = "$parent.fullAfter",
4675 },
4676 order = {
4677 order = 3,
4678 type = "range",
4679 name = L["Order"],
4680 min = 0, max = 100, step = 5,
4681 hidden = hideBarOption,
4682 arg = "portrait.order",
4683 },
4684 height = {
4685 order = 4,
4686 type = "range",
4687 name = L["Height"],
4688 desc = L["How much of the frames total height this bar should get, this is a weighted value, the higher it is the more it gets."],
4689 min = 0, max = 10, step = 0.1,
4690 hidden = hideBarOption,
4691 arg = "portrait.height",
4692 },
4693 },
4694 },
4695 },
4696 },
4697 auras = {
4698 order = 5,
4699 name = L["Auras"],
4700 type = "group",
4701 hidden = isModifiersSet,
4702 set = setUnit,
4703 get = getUnit,
4704 childGroups = "tree",
4705 args = {
4706 buffs = Config.auraTable,
4707 debuffs = Config.auraTable,
4708 },
4709 },
4710 indicators = {
4711 order = 5.5,
4712 type = "group",
4713 name = L["Indicators"],
4714 hidden = isModifiersSet,
4715 childGroups = "tree",
4716 set = setUnit,
4717 get = getUnit,
4718 args = {
4719 },
4720 },
4721 tag = {
4722 order = 7,
4723 name = L["Text/Tags"],
4724 type = "group",
4725 hidden = isModifiersSet,
4726 childGroups = "tree",
4727 args = tagWizard,
4728 },
4729 },
4730 }
4731
4732 for _, indicator in pairs(ShadowUF.modules.indicators.list) do
4733 Config.unitTable.args.indicators.args[indicator] = Config.indicatorTable
4734 end
4735
4736 -- Check for unit conflicts
4737 local function hideZoneConflict()
4738 for _, zone in pairs(ShadowUF.db.profile.visibility) do
4739 for unit, status in pairs(zone) do
4740 if( L.units[unit] and ( not status and ShadowUF.db.profile.units[unit].enabled or status and not ShadowUF.db.profile.units[unit].enabled ) ) then
4741 return nil
4742 end
4743 end
4744 end
4745
4746 return true
4747 end
4748
4749 options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ShadowUF.db, true)
4750 local LibDualSpec = LibStub("LibDualSpec-1.0", true)
4751 if LibDualSpec then LibDualSpec:EnhanceOptions(options.args.profile, ShadowUF.db) end
4752
4753 options.args.enableUnits = {
4754 type = "group",
4755 name = L["Enabled Units"],
4756 desc = getPageDescription,
4757 args = {
4758 help = {
4759 order = 1,
4760 type = "group",
4761 inline = true,
4762 name = L["Help"],
4763 hidden = function()
4764 if( not hideZoneConflict() or hideBasicOption() ) then
4765 return true
4766 end
4767
4768 return nil
4769 end,
4770 args = {
4771 help = {
4772 order = 0,
4773 type = "description",
4774 name = L["The check boxes below will allow you to enable or disable units.|n|n|cffff2020Warning!|r Target of Target units have a higher performance cost compared to other units. If you have performance issues, please disable those units or reduce the features enabled for those units."],
4775 },
4776 },
4777 },
4778 zoneenabled = {
4779 order = 1.5,
4780 type = "group",
4781 inline = true,
4782 name = L["Zone configuration units"],
4783 hidden = hideZoneConflict,
4784 args = {
4785 help = {
4786 order = 1,
4787 type = "description",
4788 name = L["|cffff2020Warning!|r Some units have overrides set in zone configuration, and may show (or not show up) in certain zone. Regardless of the settings below."]
4789 },
4790 sep = {
4791 order = 2,
4792 type = "header",
4793 name = "",
4794 },
4795 units = {
4796 order = 3,
4797 type = "description",
4798 name = function()
4799 local text = {}
4800
4801 for zoneType, zone in pairs(ShadowUF.db.profile.visibility) do
4802 local errors = {}
4803 for unit, status in pairs(zone) do
4804 if( L.units[unit] ) then
4805 if ( not status and ShadowUF.db.profile.units[unit].enabled ) then
4806 table.insert(errors, string.format(L["|cffff2020%s|r units disabled"], L.units[unit]))
4807 elseif( status and not ShadowUF.db.profile.units[unit].enabled ) then
4808 table.insert(errors, string.format(L["|cff20ff20%s|r units enabled"], L.units[unit]))
4809 end
4810 end
4811 end
4812
4813 if( #(errors) > 1 ) then
4814 table.insert(text, string.format("|cfffed000%s|r have the following overrides: %s", AREA_NAMES[zoneType], table.concat(errors, ", ")))
4815 elseif( #(errors) == 1 ) then
4816 table.insert(text, string.format("|cfffed000%s|r has the override: %s", AREA_NAMES[zoneType], errors[1]))
4817 end
4818 end
4819
4820 return #(text) > 0 and table.concat(text, "|n") or ""
4821 end,
4822 },
4823 },
4824 },
4825 enabled = {
4826 order = 2,
4827 type = "group",
4828 inline = true,
4829 name = L["Enable units"],
4830 args = {},
4831 },
4832 },
4833 }
4834
4835 local sort_units = function(a, b)
4836 return a < b
4837 end
4838
4839 options.args.units = {
4840 type = "group",
4841 name = L["Unit Configuration"],
4842 desc = getPageDescription,
4843 args = {
4844 help = {
4845 order = 1,
4846 type = "group",
4847 inline = true,
4848 name = L["Help"],
4849 args = {
4850 help = {
4851 order = 0,
4852 type = "description",
4853 name = L["Wondering what all of the tabs for the unit configuration mean? Here's some information:|n|n|cfffed000General:|r Portrait, range checker, combat fader, border highlighting|n|cfffed000Frame:|r Unit positioning and frame anchoring|n|cfffed000Bars:|r Health, power, empty and cast bar, and combo point configuration|n|cfffed000Widget size:|r All bar and portrait sizing and ordering options|n|cfffed000Auras:|r All aura configuration for enabling/disabling/enlarging self/etc|n|cfffed000Indicators:|r All indicator configuration|n|cfffed000Text/Tags:|r Tag management as well as text positioning and width settings.|n|n|n*** Frequently looked for options ***|n|n|cfffed000Raid frames by group|r - Unit configuration -> Raid -> Raid -> Separate raid frames|n|cfffed000Class coloring:|r Bars -> Color health by|n|cfffed000Timers on auras:|r You need OmniCC for that|n|cfffed000Showing/Hiding default buff frames:|r Hide Blizzard -> Hide buff frames|n|cfffed000Percentage HP/MP text:|r Tags/Text tab, use the [percenthp] or [percentpp] tags|n|cfffed000Hiding party based on raid|r - Unit configuration -> Party -> Party -> Hide in 6-man raid/Hide in any raid"],
4854 fontSize = "medium",
4855 },
4856 },
4857 },
4858 global = {
4859 type = "group",
4860 childGroups = "tab",
4861 order = 0,
4862 name = L["Global"],
4863 args = {
4864 test = {
4865 order = 0,
4866 type = "group",
4867 name = L["Currently modifying"],
4868 inline = true,
4869 hidden = function()
4870 for k in pairs(modifyUnits) do return false end
4871 return true
4872 end,
4873 args = {
4874 info = {
4875 order = 0,
4876 type = "description",
4877 name = function()
4878 local units = {};
4879 for unit, enabled in pairs(modifyUnits) do
4880 if( enabled ) then
4881 table.insert(units, L.units[unit])
4882 end
4883 end
4884
4885 table.sort(units, sort_units)
4886 return table.concat(units, ", ")
4887 end,
4888 }
4889 }
4890 },
4891 units = {
4892 order = 1,
4893 type = "group",
4894 name = L["Units"],
4895 set = function(info, value)
4896 local unit = info[#(info)]
4897 if( IsShiftKeyDown() ) then
4898 for _, unit in pairs(ShadowUF.unitList) do
4899 if( ShadowUF.db.profile.units[unit].enabled ) then
4900 modifyUnits[unit] = value and true or nil
4901
4902 if( value ) then
4903 globalConfig = mergeTables(globalConfig, ShadowUF.db.profile.units[unit])
4904 end
4905 end
4906 end
4907 else
4908 modifyUnits[unit] = value and true or nil
4909
4910 if( value ) then
4911 globalConfig = mergeTables(globalConfig, ShadowUF.db.profile.units[unit])
4912 end
4913 end
4914
4915 -- Check if we have nothing else selected, if so wipe it
4916 local hasUnit
4917 for k in pairs(modifyUnits) do hasUnit = true break end
4918 if( not hasUnit ) then
4919 globalConfig = {}
4920 end
4921
4922 AceRegistry:NotifyChange("ShadowedUF")
4923 end,
4924 get = function(info) return modifyUnits[info[#(info)]] end,
4925 args = {
4926 help = {
4927 order = 0,
4928 type = "group",
4929 name = L["Help"],
4930 inline = true,
4931 args = {
4932 help = {
4933 order = 0,
4934 type = "description",
4935 name = L["Select the units that you want to modify, any settings changed will change every unit you selected. If you want to anchor or change raid/party unit specific settings you will need to do that through their options.|n|nShift click a unit to select all/unselect all."],
4936 },
4937 },
4938 },
4939 units = {
4940 order = 1,
4941 type = "group",
4942 name = L["Units"],
4943 inline = true,
4944 args = {},
4945 },
4946 },
4947 },
4948 },
4949 },
4950 },
4951 }
4952
4953 -- Load modules into the unit table
4954 for key, module in pairs(ShadowUF.modules) do
4955 local canHaveBar = module.moduleHasBar
4956 for _, data in pairs(ShadowUF.defaults.profile.units) do
4957 if( data[key] and data[key].isBar ~= nil ) then
4958 canHaveBar = true
4959 break
4960 end
4961 end
4962
4963 if( canHaveBar ) then
4964 Config.unitTable.args.widgetSize.args[key] = Config.barTable
4965 end
4966 end
4967
4968 -- Load global unit
4969 for k, v in pairs(Config.unitTable.args) do
4970 options.args.units.args.global.args[k] = v
4971 end
4972
4973 -- Load all of the per unit settings
4974 local perUnitList = {
4975 order = getUnitOrder,
4976 type = "toggle",
4977 name = getName,
4978 hidden = isUnitDisabled,
4979 desc = function(info)
4980 return string.format(L["Adds %s to the list of units to be modified when you change values in this tab."], L.units[info[#(info)]])
4981 end,
4982 }
4983
4984 -- Enabled units list
4985 local unitCatOrder = {}
4986 local enabledUnits = {
4987 order = function(info) return unitCatOrder[info[#(info)]] + getUnitOrder(info) end,
4988 type = "toggle",
4989 name = getName,
4990 set = function(info, value)
4991 local unit = info[#(info)]
4992 for child, parent in pairs(ShadowUF.Units.childUnits) do
4993 if( unit == parent and not value ) then
4994 ShadowUF.db.profile.units[child].enabled = false
4995 end
4996 end
4997
4998 ShadowUF.modules.movers:Update()
4999 ShadowUF.db.profile.units[unit].enabled = value
5000 ShadowUF:LoadUnits()
5001
5002 -- Update party frame visibility
5003 if( unit == "raid" and ShadowUF.Units.headerFrames.party ) then
5004 ShadowUF.Units:SetHeaderAttributes(ShadowUF.Units.headerFrames.party, "party")
5005 end
5006
5007 ShadowUF.modules.movers:Update()
5008 end,
5009 get = function(info)
5010 return ShadowUF.db.profile.units[info[#(info)]].enabled
5011 end,
5012 desc = function(info)
5013 local unit = info[#(info)]
5014 local unitDesc = UNIT_DESC[unit] or ""
5015
5016 if( ShadowUF.db.profile.units[unit].enabled and ShadowUF.Units.childUnits[unit] ) then
5017 if( unitDesc ~= "" ) then unitDesc = unitDesc .. "\n\n" end
5018 return unitDesc .. string.format(L["This unit depends on another to work, disabling %s will disable %s."], L.units[ShadowUF.Units.childUnits[unit]], L.units[unit])
5019 elseif( not ShadowUF.db.profile.units[unit].enabled ) then
5020 for child, parent in pairs(ShadowUF.Units.childUnits) do
5021 if( parent == unit ) then
5022 if( unitDesc ~= "" ) then unitDesc = unitDesc .. "\n\n" end
5023 return unitDesc .. L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."]
5024 end
5025 end
5026 end
5027
5028 return unitDesc ~= "" and unitDesc
5029 end,
5030 disabled = function(info)
5031 local unit = info[#(info)]
5032 if( ShadowUF.Units.childUnits[unit] ) then
5033 return not ShadowUF.db.profile.units[ShadowUF.Units.childUnits[unit]].enabled
5034 end
5035
5036 return false
5037 end,
5038 }
5039
5040 local unitCategory = {
5041 order = function(info)
5042 local cat = info[#(info)]
5043 return cat == "playercat" and 50 or cat == "generalcat" and 100 or cat == "partycat" and 200 or cat == "raidcat" and 300 or cat == "raidmisccat" and 400 or cat == "bosscat" and 500 or cat == "arenacat" and 600 or 700
5044 end,
5045 type = "header",
5046 name = function(info)
5047 local cat = info[#(info)]
5048 return cat == "playercat" and L["Player"] or cat == "generalcat" and L["General"] or cat == "raidcat" and L["Raid"] or cat == "partycat" and L["Party"] or cat == "arenacat" and L["Arena"] or cat == "battlegroundcat" and L["Battlegrounds"] or cat == "raidmisccat" and L["Raid Misc"] or cat == "bosscat" and L["Boss"]
5049 end,
5050 width = "full",
5051 }
5052
5053 for cat, list in pairs(unitCategories) do
5054 options.args.enableUnits.args.enabled.args[cat .. "cat"] = unitCategory
5055
5056 for _, unit in pairs(list) do
5057 unitCatOrder[unit] = cat == "player" and 50 or cat == "general" and 100 or cat == "party" and 200 or cat == "raid" and 300 or cat == "raidmisc" and 400 or cat == "boss" and 500 or cat == "arena" and 600 or 700
5058 end
5059 end
5060
5061 for order, unit in pairs(ShadowUF.unitList) do
5062 options.args.enableUnits.args.enabled.args[unit] = enabledUnits
5063 options.args.units.args.global.args.units.args.units.args[unit] = perUnitList
5064 options.args.units.args[unit] = Config.unitTable
5065
5066 unitCatOrder[unit] = unitCatOrder[unit] or 100
5067 end
5068end
5069
5070---------------------
5071-- FILTER CONFIGURATION
5072---------------------
5073local function loadFilterOptions()
5074 local hasWhitelist, hasBlacklist, hasOverridelist, rebuildFilters
5075 local filterMap, spellMap = {}, {}
5076
5077 local manageFiltersTable = {
5078 order = function(info) return info[#(info)] == "whitelists" and 1 or info[#(info)] == "blacklists" and 2 or 3 end,
5079 type = "group",
5080 name = function(info) return info[#(info)] == "whitelists" and L["Whitelists"] or info[#(info)] == "blacklists" and L["Blacklists"] or L["Override lists"] end,
5081 args = {
5082 },
5083 }
5084
5085 local function reloadUnitAuras()
5086 for _, frame in pairs(ShadowUF.Units.unitFrames) do
5087 if( UnitExists(frame.unit) and frame.visibility.auras ) then
5088 ShadowUF.modules.auras:UpdateFilter(frame)
5089 frame:FullUpdate()
5090 end
5091 end
5092 end
5093
5094 local function setFilterType(info, value)
5095 local filter = filterMap[info[#(info) - 2]]
5096 local filterType = info[#(info) - 3]
5097
5098 ShadowUF.db.profile.filters[filterType][filter][info[#(info)]] = value
5099 reloadUnitAuras()
5100 end
5101
5102 local function getFilterType(info)
5103 local filter = filterMap[info[#(info) - 2]]
5104 local filterType = info[#(info) - 3]
5105
5106 return ShadowUF.db.profile.filters[filterType][filter][info[#(info)]]
5107 end
5108
5109 --- Container widget for the filter listing
5110 local filterEditTable = {
5111 order = 0,
5112 type = "group",
5113 name = function(info) return filterMap[info[#(info)]] end,
5114 hidden = function(info) return not ShadowUF.db.profile.filters[info[#(info) - 1]][filterMap[info[#(info)]]] end,
5115 args = {
5116 general = {
5117 order = 0,
5118 type = "group",
5119 name = function(info) return filterMap[info[#(info) - 1]] end,
5120 hidden = false,
5121 inline = true,
5122 args = {
5123 add = {
5124 order = 0,
5125 type = "input",
5126 name = L["Aura name or spell ID"],
5127 --dialogControl = "Aura_EditBox",
5128 hidden = false,
5129 set = function(info, value)
5130 local filterType = info[#(info) - 3]
5131 local filter = filterMap[info[#(info) - 2]]
5132
5133 ShadowUF.db.profile.filters[filterType][filter][value] = true
5134
5135 reloadUnitAuras()
5136 rebuildFilters()
5137 end,
5138 },
5139 delete = {
5140 order = 1,
5141 type = "execute",
5142 name = L["Delete filter"],
5143 hidden = false,
5144 confirmText = L["Are you sure you want to delete this filter?"],
5145 confirm = true,
5146 func = function(info, value)
5147 local filterType = info[#(info) - 3]
5148 local filter = filterMap[info[#(info) - 2]]
5149
5150 ShadowUF.db.profile.filters[filterType][filter] = nil
5151
5152 -- Delete anything that used this filter too
5153 local filterList = filterType == "whitelists" and ShadowUF.db.profile.filters.zonewhite or filterType == "blacklists" and ShadowUF.db.profile.filters.zoneblack or filterType == "overridelists" and ShadowUF.db.profile.filters.zoneoverride
5154 if filterList then
5155 for id, filterUsed in pairs(filterList) do
5156 if( filterUsed == filter ) then
5157 filterList[id] = nil
5158 end
5159 end
5160 end
5161
5162 reloadUnitAuras()
5163 rebuildFilters()
5164 end,
5165 },
5166 },
5167 },
5168 filters = {
5169 order = 2,
5170 type = "group",
5171 inline = true,
5172 hidden = false,
5173 name = L["Aura types to filter"],
5174 args = {
5175 buffs = {
5176 order = 4,
5177 type = "toggle",
5178 name = L["Buffs"],
5179 desc = L["When this filter is active, apply the filter to buffs."],
5180 set = setFilterType,
5181 get = getFilterType,
5182 },
5183 debuffs = {
5184 order = 5,
5185 type = "toggle",
5186 name = L["Debuffs"],
5187 desc = L["When this filter is active, apply the filter to debuffs."],
5188 set = setFilterType,
5189 get = getFilterType,
5190 },
5191 },
5192 },
5193 spells = {
5194 order = 3,
5195 type = "group",
5196 inline = true,
5197 name = L["Auras"],
5198 hidden = false,
5199 args = {
5200
5201 },
5202 },
5203 },
5204 }
5205
5206 -- Spell list for manage aura filters
5207 local spellLabel = {
5208 order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end,
5209 type = "description",
5210 width = "double",
5211 fontSize = "medium",
5212 name = function(info)
5213 local name = spellMap[info[#(info)]]
5214 if tonumber(name) then
5215 local spellName, _, icon = GetSpellInfo(name)
5216 name = string.format("|T%s:14:14:0:0|t %s (#%i)", icon or "Interface\\Icons\\Inv_misc_questionmark", spellName or L["Unknown"], name)
5217 end
5218 return name
5219 end,
5220 }
5221
5222 local spellRow = {
5223 order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.5 end,
5224 type = "execute",
5225 name = L["Delete"],
5226 width = "half",
5227 func = function(info)
5228 local spell = spellMap[info[#(info)]]
5229 local filter = filterMap[info[#(info) - 2]]
5230 local filterType = info[#(info) - 3]
5231
5232 ShadowUF.db.profile.filters[filterType][filter][spell] = nil
5233
5234 reloadUnitAuras()
5235 rebuildFilters()
5236 end
5237 }
5238
5239 local noSpells = {
5240 order = 0,
5241 type = "description",
5242 name = L["This filter has no auras in it, you will have to add some using the dialog above."],
5243 }
5244
5245 -- The filter [View] widgets for manage aura filters
5246 local filterLabel = {
5247 order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end,
5248 type = "description",
5249 width = "", -- Odd I know, AceConfigDialog-3.0 expands descriptions to full width if width is nil
5250 fontSize = "medium",
5251 name = function(info) return filterMap[info[#(info)]] end,
5252 }
5253
5254 local filterRow = {
5255 order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.5 end,
5256 type = "execute",
5257 name = L["View"],
5258 width = "half",
5259 func = function(info)
5260 local filterType = info[#(info) - 2]
5261
5262 AceDialog.Status.ShadowedUF.children.filter.children.filters.status.groups.groups[filterType] = true
5263 selectTabGroup("filter", "filters", filterType .. "\001" .. string.match(info[#(info)], "(%d+)"))
5264 end
5265 }
5266
5267 local noFilters = {
5268 order = 0,
5269 type = "description",
5270 name = L["You do not have any filters of this type added yet, you will have to create one in the management panel before this page is useful."],
5271 }
5272
5273 -- Container table for a filter zone
5274 local globalSettings = {}
5275 local zoneList = {"none", "pvp", "arena", "party", "raid"}
5276 local filterTable = {
5277 order = function(info) return info[#(info)] == "global" and 1 or info[#(info)] == "none" and 2 or 3 end,
5278 type = "group",
5279 inline = true,
5280 hidden = function() return not hasWhitelist and not hasBlacklist and not hasOverridelist end,
5281 name = function(info) return AREA_NAMES[info[#(info)]] or L["Global"] end,
5282 set = function(info, value)
5283 local filter = filterMap[info[#(info)]]
5284 local zone = info[#(info) - 1]
5285 local unit = info[#(info) - 2]
5286 local filterKey = ShadowUF.db.profile.filters.whitelists[filter] and "zonewhite" or ShadowUF.db.profile.filters.blacklists[filter] and "zoneblack" or "zoneoverride"
5287
5288 for _, zoneConfig in pairs(zoneList) do
5289 if( zone == "global" or zoneConfig == zone ) then
5290 if( unit == "global" ) then
5291 globalSettings[zoneConfig .. filterKey] = value and filter or false
5292
5293 for _, unit in pairs(ShadowUF.unitList) do
5294 ShadowUF.db.profile.filters[filterKey][zoneConfig .. unit] = value and filter or nil
5295 end
5296 else
5297 ShadowUF.db.profile.filters[filterKey][zoneConfig .. unit] = value and filter or nil
5298 end
5299 end
5300 end
5301
5302 if( zone == "global" ) then
5303 globalSettings[zone .. unit .. filterKey] = value and filter or false
5304 end
5305
5306 reloadUnitAuras()
5307 end,
5308 get = function(info)
5309 local filter = filterMap[info[#(info)]]
5310 local zone = info[#(info) - 1]
5311 local unit = info[#(info) - 2]
5312
5313 if( unit == "global" or zone == "global" ) then
5314 local id = zone == "global" and zone .. unit or zone
5315 local filterKey = ShadowUF.db.profile.filters.whitelists[filter] and "zonewhite" or ShadowUF.db.profile.filters.blacklists[filter] and "zoneblack" or "zoneoverride"
5316
5317 if( info[#(info)] == "nofilter" ) then
5318 return globalSettings[id .. "zonewhite"] == false and globalSettings[id .. "zoneblack"] == false and globalSettings[id .. "zoneoverride"] == false
5319 end
5320
5321 return globalSettings[id .. filterKey] == filter
5322 end
5323
5324 if( info[#(info)] == "nofilter" ) then
5325 return not ShadowUF.db.profile.filters.zonewhite[zone .. unit] and not ShadowUF.db.profile.filters.zoneblack[zone .. unit] and not ShadowUF.db.profile.filters.zoneoverride[zone .. unit]
5326 end
5327
5328 return ShadowUF.db.profile.filters.zonewhite[zone .. unit] == filter or ShadowUF.db.profile.filters.zoneblack[zone .. unit] == filter or ShadowUF.db.profile.filters.zoneoverride[zone .. unit] == filter
5329 end,
5330 args = {
5331 nofilter = {
5332 order = 0,
5333 type = "toggle",
5334 name = L["Don't use a filter"],
5335 hidden = false,
5336 set = function(info, value)
5337 local filter = filterMap[info[#(info)]]
5338 local zone = info[#(info) - 1]
5339 local unit = info[#(info) - 2]
5340
5341 for _, zoneConfig in pairs(zoneList) do
5342 if( zone == "global" or zoneConfig == zone ) then
5343 if( unit == "global" ) then
5344 globalSettings[zoneConfig .. "zonewhite"] = false
5345 globalSettings[zoneConfig .. "zoneblack"] = false
5346 globalSettings[zoneConfig .. "zoneoverride"] = false
5347
5348 for _, unit in pairs(ShadowUF.unitList) do
5349 ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unit] = nil
5350 ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unit] = nil
5351 ShadowUF.db.profile.filters.zoneoverride[zoneConfig .. unit] = nil
5352 end
5353 else
5354 ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unit] = nil
5355 ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unit] = nil
5356 ShadowUF.db.profile.filters.zoneoverride[zoneConfig .. unit] = nil
5357 end
5358 end
5359 end
5360
5361 if( zone == "global" ) then
5362 globalSettings[zone .. unit .. "zonewhite"] = false
5363 globalSettings[zone .. unit .. "zoneblack"] = false
5364 globalSettings[zone .. unit .. "zoneoverride"] = false
5365 end
5366
5367 reloadUnitAuras()
5368 end,
5369 },
5370 white = {
5371 order = 1,
5372 type = "header",
5373 name = "|cffffffff" .. L["Whitelists"] .. "|r",
5374 hidden = function(info) return not hasWhitelist end
5375 },
5376 black = {
5377 order = 3,
5378 type = "header",
5379 name = L["Blacklists"], -- In theory I would make this black, but as black doesn't work with a black background I'll skip that
5380 hidden = function(info) return not hasBlacklist end
5381 },
5382 override = {
5383 order = 5,
5384 type = "header",
5385 name = L["Override lists"], -- In theory I would make this black, but as black doesn't work with a black background I'll skip that
5386 hidden = function(info) return not hasOverridelist end
5387 },
5388 },
5389 }
5390
5391 -- Toggle used for set filter zones to enable filters
5392 local filterToggle = {
5393 order = function(info) return ShadowUF.db.profile.filters.whitelists[filterMap[info[#(info)]]] and 2 or ShadowUF.db.profile.filters.blacklists[filterMap[info[#(info)]]] and 4 or 6 end,
5394 type = "toggle",
5395 name = function(info) return filterMap[info[#(info)]] end,
5396 desc = function(info)
5397 local filter = filterMap[info[#(info)]]
5398 filter = ShadowUF.db.profile.filters.whitelists[filter] or ShadowUF.db.profile.filters.blacklists[filter] or ShadowUF.db.profile.filters.overridelists[filter]
5399 if( filter.buffs and filter.debuffs ) then
5400 return L["Filtering both buffs and debuffs"]
5401 elseif( filter.buffs ) then
5402 return L["Filtering buffs only"]
5403 elseif( filter.debuffs ) then
5404 return L["Filtering debuffs only"]
5405 end
5406
5407 return L["This filter has no aura types set to filter out."]
5408 end,
5409 }
5410
5411 -- Load existing filters in
5412 -- This needs to be cleaned up later
5413 local filterID, spellID = 0, 0
5414 local function buildList(type)
5415 local manageFiltersTable = {
5416 order = type == "whitelists" and 1 or type == "blacklists" and 2 or 3,
5417 type = "group",
5418 name = type == "whitelists" and L["Whitelists"] or type == "blacklists" and L["Blacklists"] or L["Override lists"],
5419 args = {
5420 groups = {
5421 order = 0,
5422 type = "group",
5423 inline = true,
5424 name = function(info) return info[#(info) - 1] == "whitelists" and L["Whitelist filters"] or info[#(info) - 1] == "blacklists" and L["Blacklist filters"] or L["Override list filters"] end,
5425 args = {
5426 },
5427 },
5428 },
5429 }
5430
5431 local hasFilters
5432 for name, spells in pairs(ShadowUF.db.profile.filters[type]) do
5433 hasFilters = true
5434 filterID = filterID + 1
5435 filterMap[tostring(filterID)] = name
5436 filterMap[filterID .. "label"] = name
5437 filterMap[filterID .. "row"] = name
5438
5439 manageFiltersTable.args[tostring(filterID)] = CopyTable(filterEditTable)
5440 manageFiltersTable.args.groups.args[filterID .. "label"] = filterLabel
5441 manageFiltersTable.args.groups.args[filterID .. "row"] = filterRow
5442 filterTable.args[tostring(filterID)] = filterToggle
5443
5444 local hasSpells
5445 for spellName in pairs(spells) do
5446 if( spellName ~= "buffs" and spellName ~= "debuffs" ) then
5447 hasSpells = true
5448 spellID = spellID + 1
5449 spellMap[tostring(spellID)] = spellName
5450 spellMap[spellID .. "label"] = spellName
5451
5452 manageFiltersTable.args[tostring(filterID)].args.spells.args[spellID .. "label"] = spellLabel
5453 manageFiltersTable.args[tostring(filterID)].args.spells.args[tostring(spellID)] = spellRow
5454 end
5455 end
5456
5457 if( not hasSpells ) then
5458 manageFiltersTable.args[tostring(filterID)].args.spells.args.noSpells = noSpells
5459 end
5460 end
5461
5462 if( not hasFilters ) then
5463 if( type == "whitelists" ) then hasWhitelist = nil elseif( type == "blacklists" ) then hasBlacklist = nil else hasOverridelist = nil end
5464 manageFiltersTable.args.groups.args.noFilters = noFilters
5465 end
5466
5467 return manageFiltersTable
5468 end
5469
5470 rebuildFilters = function()
5471 for id in pairs(filterMap) do filterTable.args[id] = nil end
5472
5473 spellID = 0
5474 filterID = 0
5475 hasBlacklist = true
5476 hasWhitelist = true
5477 hasOverridelist = true
5478
5479 table.wipe(filterMap)
5480 table.wipe(spellMap)
5481
5482 options.args.filter.args.filters.args.whitelists = buildList("whitelists")
5483 options.args.filter.args.filters.args.blacklists = buildList("blacklists")
5484 options.args.filter.args.filters.args.overridelists = buildList("overridelists")
5485 end
5486
5487 local unitFilterSelection = {
5488 order = function(info) return info[#(info)] == "global" and 1 or (getUnitOrder(info) + 1) end,
5489 type = "group",
5490 name = function(info) return info[#(info)] == "global" and L["Global"] or getName(info) end,
5491 disabled = function(info)
5492 if( info[#(info)] == "global" ) then
5493 return false
5494 end
5495
5496 return not hasWhitelist and not hasBlacklist
5497 end,
5498 args = {
5499 help = {
5500 order = 0,
5501 type = "group",
5502 inline = true,
5503 name = L["Help"],
5504 hidden = function() return hasWhitelist or hasBlacklist or hasOverridelist end,
5505 args = {
5506 help = {
5507 type = "description",
5508 name = L["You will need to create an aura filter before you can set which unit to enable aura filtering on."],
5509 width = "full",
5510 }
5511 },
5512 },
5513 header = {
5514 order = 0,
5515 type = "header",
5516 name = function(info) return (info[#(info) - 1] == "global" and L["Global"] or L.units[info[#(info) - 1]]) end,
5517 hidden = function() return not hasWhitelist and not hasBlacklist and not hasOverridelist end,
5518 },
5519 global = filterTable,
5520 none = filterTable,
5521 pvp = filterTable,
5522 arena = filterTable,
5523 battleground = filterTable,
5524 party = filterTable,
5525 raid = filterTable,
5526 }
5527 }
5528
5529 local addFilter = {type = "whitelists"}
5530
5531 options.args.filter = {
5532 type = "group",
5533 name = L["Aura Filters"],
5534 childGroups = "tab",
5535 desc = getPageDescription,
5536 args = {
5537 groups = {
5538 order = 1,
5539 type = "group",
5540 name = L["Set Filter Zones"],
5541 args = {
5542 help = {
5543 order = 0,
5544 type = "group",
5545 inline = true,
5546 name = L["Help"],
5547 args = {
5548 help = {
5549 type = "description",
5550 name = L["You can set what unit frame should use what filter group and in what zone type here, if you want to change what auras goes into what group then see the \"Manage aura groups\" option."],
5551 width = "full",
5552 }
5553 },
5554 },
5555 }
5556 },
5557 filters = {
5558 order = 2,
5559 type = "group",
5560 name = L["Manage Aura Filters"],
5561 childGroups = "tree",
5562 args = {
5563 manage = {
5564 order = 1,
5565 type = "group",
5566 name = L["Management"],
5567 args = {
5568 help = {
5569 order = 0,
5570 type = "group",
5571 inline = true,
5572 name = L["Help"],
5573 args = {
5574 help = {
5575 type = "description",
5576 name = L["Whitelists will hide any aura not in the filter group.|nBlacklists will hide auras that are in the filter group.|nOverride lists will bypass any filter and always be shown."],
5577 width = "full",
5578 }
5579 },
5580 },
5581 error = {
5582 order = 1,
5583 type = "group",
5584 inline = true,
5585 hidden = function() return not addFilter.error end,
5586 name = L["Error"],
5587 args = {
5588 error = {
5589 order = 0,
5590 type = "description",
5591 name = function() return addFilter.error end,
5592 width = "full",
5593 },
5594 },
5595 },
5596 add = {
5597 order = 2,
5598 type = "group",
5599 inline = true,
5600 name = L["New filter"],
5601 get = function(info) return addFilter[info[#(info)]] end,
5602 args = {
5603 name = {
5604 order = 0,
5605 type = "input",
5606 name = L["Name"],
5607 set = function(info, value)
5608 addFilter[info[#(info)]] = string.trim(value) ~= "" and value or nil
5609 addFilter.error = nil
5610 end,
5611 get = function(info) return addFilter.errorName or addFilter.name end,
5612 validate = function(info, value)
5613 local name = string.lower(string.trim(value))
5614 for filter in pairs(ShadowUF.db.profile.filters.whitelists) do
5615 if( string.lower(filter) == name ) then
5616 addFilter.error = string.format(L["The whitelist \"%s\" already exists."], value)
5617 addFilter.errorName = value
5618 AceRegistry:NotifyChange("ShadowedUF")
5619 return ""
5620 end
5621 end
5622
5623 for filter in pairs(ShadowUF.db.profile.filters.blacklists) do
5624 if( string.lower(filter) == name ) then
5625 addFilter.error = string.format(L["The blacklist \"%s\" already exists."], value)
5626 addFilter.errorName = value
5627 AceRegistry:NotifyChange("ShadowedUF")
5628 return ""
5629 end
5630 end
5631
5632 for filter in pairs(ShadowUF.db.profile.filters.overridelists) do
5633 if( string.lower(filter) == name ) then
5634 addFilter.error = string.format(L["The override list \"%s\" already exists."], value)
5635 addFilter.errorName = value
5636 AceRegistry:NotifyChange("ShadowedUF")
5637 return ""
5638 end
5639 end
5640
5641 addFilter.error = nil
5642 addFilter.errorName = nil
5643 return true
5644 end,
5645 },
5646 type = {
5647 order = 1,
5648 type = "select",
5649 name = L["Filter type"],
5650 set = function(info, value) addFilter[info[#(info)]] = value end,
5651 values = {["whitelists"] = L["Whitelist"], ["blacklists"] = L["Blacklist"], ["overridelists"] = L["Override list"]},
5652 },
5653 add = {
5654 order = 2,
5655 type = "execute",
5656 name = L["Create"],
5657 disabled = function(info) return not addFilter.name end,
5658 func = function(info)
5659 ShadowUF.db.profile.filters[addFilter.type][addFilter.name] = {buffs = true, debuffs = true}
5660 rebuildFilters()
5661
5662 local id
5663 for key, value in pairs(filterMap) do
5664 if( value == addFilter.name ) then
5665 id = key
5666 break
5667 end
5668 end
5669
5670 AceDialog.Status.ShadowedUF.children.filter.children.filters.status.groups.groups[addFilter.type] = true
5671 selectTabGroup("filter", "filters", addFilter.type .. "\001" .. id)
5672
5673 table.wipe(addFilter)
5674 addFilter.type = "whitelists"
5675 end,
5676 },
5677 },
5678 },
5679 },
5680 },
5681 },
5682 },
5683 },
5684 }
5685
5686
5687 options.args.filter.args.groups.args.global = unitFilterSelection
5688 for _, unit in pairs(ShadowUF.unitList) do
5689 options.args.filter.args.groups.args[unit] = unitFilterSelection
5690 end
5691
5692 rebuildFilters()
5693end
5694
5695---------------------
5696-- TAG CONFIGURATION
5697---------------------
5698local function loadTagOptions()
5699 local tagData = {search = ""}
5700 local function set(info, value, key)
5701 local key = key or info[#(info)]
5702 if( ShadowUF.Tags.defaultHelp[tagData.name] ) then
5703 return
5704 end
5705
5706 -- Reset loaded function + reload tags
5707 if( key == "funct" ) then
5708 ShadowUF.tagFunc[tagData.name] = nil
5709 ShadowUF.Tags:Reload()
5710 elseif( key == "category" ) then
5711 local cat = ShadowUF.db.profile.tags[tagData.name][key]
5712 if( cat and cat ~= value ) then
5713 Config.tagTextTable.args[cat].args[tagData.name] = nil
5714 Config.tagTextTable.args[value].args[tagData.name] = Config.tagTable
5715 end
5716 end
5717
5718 ShadowUF.db.profile.tags[tagData.name][key] = value
5719 end
5720
5721 local function stripCode(text)
5722 if( not text ) then
5723 return ""
5724 end
5725
5726 return string.gsub(string.gsub(text, "|", "||"), "\t", "")
5727 end
5728
5729 local function get(info, key)
5730 local key = key or info[#(info)]
5731
5732 if( key == "help" and ShadowUF.Tags.defaultHelp[tagData.name] ) then
5733 return ShadowUF.Tags.defaultHelp[tagData.name] or ""
5734 elseif( key == "events" and ShadowUF.Tags.defaultEvents[tagData.name] ) then
5735 return ShadowUF.Tags.defaultEvents[tagData.name] or ""
5736 elseif( key == "frequency" and ShadowUF.Tags.defaultFrequents[tagData.name] ) then
5737 return ShadowUF.Tags.defaultFrequents[tagData.name] or ""
5738 elseif( key == "category" and ShadowUF.Tags.defaultCategories[tagData.name] ) then
5739 return ShadowUF.Tags.defaultCategories[tagData.name] or ""
5740 elseif( key == "name" and ShadowUF.Tags.defaultNames[tagData.name] ) then
5741 return ShadowUF.Tags.defaultNames[tagData.name] or ""
5742 elseif( key == "funct" and ShadowUF.Tags.defaultTags[tagData.name] ) then
5743 return ShadowUF.Tags.defaultTags[tagData.name] or ""
5744 end
5745
5746 return ShadowUF.db.profile.tags[tagData.name] and ShadowUF.db.profile.tags[tagData.name][key] or ""
5747 end
5748
5749 local function isSearchHidden(info)
5750 return tagData.search ~= "" and not string.match(info[#(info)], tagData.search) or false
5751 end
5752
5753 local function editTag(info)
5754 tagData.name = info[#(info)]
5755
5756 if( ShadowUF.Tags.defaultHelp[tagData.name] ) then
5757 tagData.error = L["You cannot edit this tag because it is one of the default ones included in this mod. This function is here to provide an example for your own custom tags."]
5758 end
5759
5760 selectDialogGroup("tags", "edit")
5761 end
5762
5763 -- Create all of the tag editor options, if it's a default tag will show it after any custom ones
5764 local tagTable = {
5765 type = "execute",
5766 order = function(info) return ShadowUF.Tags.defaultTags[info[#(info)]] and 100 or 1 end,
5767 name = getTagName,
5768 desc = getTagHelp,
5769 hidden = isSearchHidden,
5770 func = editTag,
5771 }
5772
5773 local tagCategories = {}
5774 local function getTagCategories(info)
5775 for k in pairs(tagCategories) do tagCategories[k] = nil end
5776
5777 for _, cat in pairs(ShadowUF.Tags.defaultCategories) do
5778 tagCategories[cat] = TAG_GROUPS[cat]
5779 end
5780
5781 return tagCategories
5782 end
5783
5784 -- Tag configuration
5785 options.args.tags = {
5786 type = "group",
5787 childGroups = "tab",
5788 name = L["Add Tags"],
5789 desc = getPageDescription,
5790 hidden = hideAdvancedOption,
5791 args = {
5792 general = {
5793 order = 0,
5794 type = "group",
5795 name = L["Tag list"],
5796 args = {
5797 help = {
5798 order = 0,
5799 type = "group",
5800 inline = true,
5801 name = L["Help"],
5802 hidden = function() return ShadowUF.db.profile.advanced end,
5803 args = {
5804 description = {
5805 order = 0,
5806 type = "description",
5807 name = L["You can add new custom tags through this page, if you're looking to change what tags are used in text look under the Text tab for an Units configuration."],
5808 },
5809 },
5810 },
5811 search = {
5812 order = 1,
5813 type = "group",
5814 inline = true,
5815 name = L["Search"],
5816 args = {
5817 search = {
5818 order = 1,
5819 type = "input",
5820 name = L["Search tags"],
5821 set = function(info, text) tagData.search = text end,
5822 get = function(info) return tagData.search end,
5823 },
5824 },
5825 },
5826 list = {
5827 order = 2,
5828 type = "group",
5829 inline = true,
5830 name = L["Tags"],
5831 args = {},
5832 },
5833 },
5834 },
5835 add = {
5836 order = 1,
5837 type = "group",
5838 name = L["Add new tag"],
5839 args = {
5840 help = {
5841 order = 0,
5842 type = "group",
5843 inline = true,
5844 name = L["Help"],
5845 args = {
5846 help = {
5847 order = 0,
5848 type = "description",
5849 name = L["You can find more information on creating your own custom tags in the \"Help\" tab above."],
5850 },
5851 },
5852 },
5853 add = {
5854 order = 1,
5855 type = "group",
5856 inline = true,
5857 name = L["Add new tag"],
5858 args = {
5859 error = {
5860 order = 0,
5861 type = "description",
5862 name = function() return tagData.addError or "" end,
5863 hidden = function() return not tagData.addError end,
5864 },
5865 errorHeader = {
5866 order = 0.50,
5867 type = "header",
5868 name = "",
5869 hidden = function() return not tagData.addError end,
5870 },
5871 tag = {
5872 order = 1,
5873 type = "input",
5874 name = L["Tag name"],
5875 desc = L["Tag that you will use to access this code, do not wrap it in brackets or parenthesis it's automatically done. For example, you would enter \"foobar\" and then access it with [foobar]."],
5876 validate = function(info, text)
5877 if( text == "" ) then
5878 tagData.addError = L["You must enter a tag name."]
5879 elseif( string.match(text, "[%[%]%(%)]") ) then
5880 tagData.addError = string.format(L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."], text)
5881 elseif( ShadowUF.tagFunc[text] ) then
5882 tagData.addError = string.format(L["The tag \"%s\" already exists."], text)
5883 else
5884 tagData.addError = nil
5885 end
5886
5887 AceRegistry:NotifyChange("ShadowedUF")
5888 return tagData.addError and "" or true
5889 end,
5890 set = function(info, tag)
5891 tagData.name = tag
5892 tagData.error = nil
5893 tagData.addError = nil
5894
5895 ShadowUF.db.profile.tags[tag] = {func = "function(unit, unitOwner)\n\nend", category = "misc"}
5896 options.args.tags.args.general.args.list.args[tag] = tagTable
5897 Config.tagTextTable.args.misc.args[tag] = Config.tagTable
5898
5899 selectDialogGroup("tags", "edit")
5900 end,
5901 },
5902 },
5903 },
5904 },
5905 },
5906 edit = {
5907 order = 2,
5908 type = "group",
5909 name = L["Edit tag"],
5910 hidden = function() return not tagData.name end,
5911 args = {
5912 help = {
5913 order = 0,
5914 type = "group",
5915 inline = true,
5916 name = L["Help"],
5917 args = {
5918 help = {
5919 order = 0,
5920 type = "description",
5921 name = L["You can find more information on creating your own custom tags in the \"Help\" tab above.|nSUF will attempt to automatically detect what events your tag will need, so you do not generally need to fill out the events field."],
5922 },
5923 },
5924 },
5925 tag = {
5926 order = 1,
5927 type = "group",
5928 inline = true,
5929 name = function() return string.format(L["Editing %s"], tagData.name or "") end,
5930 args = {
5931 error = {
5932 order = 0,
5933 type = "description",
5934 name = function()
5935 if( tagData.error ) then
5936 return "|cffff0000" .. tagData.error .. "|r"
5937 end
5938 return ""
5939 end,
5940 hidden = function() return not tagData.error end,
5941 },
5942 errorHeader = {
5943 order = 1,
5944 type = "header",
5945 name = "",
5946 hidden = function() return not tagData.error end,
5947 },
5948 discovery = {
5949 order = 1,
5950 type = "toggle",
5951 name = L["Disable event discovery"],
5952 desc = L["This will disable the automatic detection of what events this tag will need, you should leave this unchecked unless you know what you are doing."],
5953 set = function(info, value) tagData.discovery = value end,
5954 get = function() return tagData.discovery end,
5955 width = "full",
5956 },
5957 frequencyEnable = {
5958 order = 1.10,
5959 type = "toggle",
5960 name = L["Enable frequent updates"],
5961 desc = L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."],
5962 set = function(info, value)
5963 tagData.frequency = value and 5 or nil
5964 set(info, tagData.frequency, "frequency")
5965 end,
5966 get = function(info) return get(info, "frequency") ~= "" and true or false end,
5967 width = "full",
5968 },
5969 frequency = {
5970 order = 1.20,
5971 type = "input",
5972 name = L["Update interval"],
5973 desc = L["How many seconds between updates.|n[WARNING] By setting the frequency to 0 it will update every single frame redraw, if you want to disable frequent updating uncheck it don't set this to 0."],
5974 disabled = function(info) return get(info) == "" end,
5975 validate = function(info, value)
5976 value = tonumber(value)
5977 if( not value ) then
5978 tagData.error = L["Invalid interval entered, must be a number."]
5979 elseif( value < 0 ) then
5980 tagData.error = L["You must enter a number that is 0 or higher, negative numbers are not allowed."]
5981 else
5982 tagData.error = nil
5983 end
5984
5985 if( tagData.error ) then
5986 AceRegistry:NotifyChange("ShadowedUF")
5987 return ""
5988 end
5989
5990 return true
5991 end,
5992 set = function(info, value)
5993 tagData.frequency = tonumber(value)
5994 tagData.frequency = tagData.frequency < 0 and 0 or tagData.frequency
5995
5996 set(info, tagData.frequency)
5997 end,
5998 get = function(info) return tostring(get(info) or "") end,
5999 width = "half",
6000 },
6001 name = {
6002 order = 2,
6003 type = "input",
6004 name = L["Tag name"],
6005 set = set,
6006 get = get,
6007 },
6008 category = {
6009 order = 2.5,
6010 type = "select",
6011 name = L["Category"],
6012 values = getTagCategories,
6013 set = set,
6014 get = get,
6015 },
6016
6017 sep = {
6018 order = 2.75,
6019 type = "description",
6020 name = "",
6021 width = "full",
6022 },
6023 events = {
6024 order = 3,
6025 type = "input",
6026 name = L["Events"],
6027 desc = L["Events that should be used to trigger an update of this tag. Separate each event with a single space."],
6028 width = "full",
6029 validate = function(info, text)
6030 if( ShadowUF.Tags.defaultTags[tagData.name] ) then
6031 return true
6032 end
6033
6034 if( text == "" or string.match(text, "[^_%a%s]") ) then
6035 tagData.error = L["You have to set the events to fire, you can only enter letters and underscores, \"FOO_BAR\" for example is valid, \"APPLE_5_ORANGE\" is not because it contains a number."]
6036 tagData.eventError = text
6037 AceRegistry:NotifyChange("ShadowedUF")
6038 return ""
6039 end
6040
6041 tagData.eventError = text
6042 tagData.error = nil
6043 return true
6044 end,
6045 set = set,
6046 get = function(info)
6047 if( tagData.eventError ) then
6048 return tagData.eventError
6049 end
6050
6051 return get(info)
6052 end,
6053 },
6054 func = {
6055 order = 4,
6056 type = "input",
6057 multiline = true,
6058 name = L["Code"],
6059 desc = L["Your code must be wrapped in a function, for example, if you were to make a tag to return the units name you would do:|n|nfunction(unit, unitOwner)|nreturn UnitName(unitOwner)|nend"],
6060 width = "full",
6061 validate = function(info, text)
6062 if( ShadowUF.Tags.defaultTags[tagData.name] ) then
6063 return true
6064 end
6065
6066 local funct, msg = loadstring("return " .. text)
6067 if( not string.match(text, "function") ) then
6068 tagData.error = L["You must wrap your code in a function."]
6069 tagData.funcError = text
6070 elseif( not funct and msg ) then
6071 tagData.error = string.format(L["Failed to save tag, error:|n %s"], msg)
6072 tagData.funcError = text
6073 else
6074 tagData.error = nil
6075 tagData.funcError = nil
6076 end
6077
6078 AceRegistry:NotifyChange("ShadowedUF")
6079 return tagData.error and "" or true
6080 end,
6081 set = function(info, value)
6082 value = string.gsub(value, "||", "|")
6083 set(info, value)
6084
6085 -- Try and automatically identify the events this tag is going to want to use
6086 if( not tagData.discovery ) then
6087 tagData.eventError = nil
6088 ShadowUF.db.profile.tags[tagData.name].events = ShadowUF.Tags:IdentifyEvents(value) or ""
6089 end
6090
6091 ShadowUF.Tags:Reload(tagData.name)
6092 end,
6093 get = function(info)
6094 if( tagData.funcError ) then
6095 return stripCode(tagData.funcError)
6096 end
6097 return stripCode(ShadowUF.Tags.defaultTags[tagData.name] or ( ShadowUF.db.profile.tags[tagData.name] and ShadowUF.db.profile.tags[tagData.name].func))
6098 end,
6099 },
6100 delete = {
6101 order = 5,
6102 type = "execute",
6103 name = L["Delete"],
6104 hidden = function() return ShadowUF.Tags.defaultTags[tagData.name] end,
6105 confirm = true,
6106 confirmText = L["Are you sure you want to delete this tag?"],
6107 func = function(info)
6108 local category = ShadowUF.db.profile.tags[tagData.name].category
6109 if( category ) then
6110 Config.tagTextTable.args[category].args[tagData.name] = nil
6111 end
6112
6113 options.args.tags.args.general.args.list.args[tagData.name] = nil
6114
6115 ShadowUF.db.profile.tags[tagData.name] = nil
6116 ShadowUF.tagFunc[tagData.name] = nil
6117 ShadowUF.Tags:Reload(tagData.name)
6118
6119 tagData.name = nil
6120 tagData.error = nil
6121 selectDialogGroup("tags", "general")
6122 end,
6123 },
6124 },
6125 },
6126 },
6127 },
6128 help = {
6129 order = 3,
6130 type = "group",
6131 name = L["Help"],
6132 args = {
6133 general = {
6134 order = 0,
6135 type = "group",
6136 name = L["General"],
6137 inline = true,
6138 args = {
6139 general = {
6140 order = 0,
6141 type = "description",
6142 name = L["See the documentation below for information and examples on creating tags, if you just want basic Lua or WoW API information then see the Programming in Lua and WoW Programming links."],
6143 },
6144 },
6145 },
6146 documentation = {
6147 order = 1,
6148 type = "group",
6149 name = L["Documentation"],
6150 inline = true,
6151 args = {
6152 doc = {
6153 order = 0,
6154 type = "input",
6155 name = L["Documentation"],
6156 set = false,
6157 get = function() return "http://wiki.github.com/Shadowed/ShadowedUnitFrames/tag-documentation" end,
6158 width = "full",
6159 },
6160 },
6161 },
6162 resources = {
6163 order = 2,
6164 type = "group",
6165 inline = true,
6166 name = L["Resources"],
6167 args = {
6168 lua = {
6169 order = 0,
6170 type = "input",
6171 name = L["Programming in Lua"],
6172 desc = L["This is a good guide on how to get started with programming in Lua, while you do not need to read the entire thing it is a helpful for understanding the basics of Lua syntax and API's."],
6173 set = false,
6174 get = function() return "http://www.lua.org/pil/" end,
6175 width = "full",
6176 },
6177 wow = {
6178 order = 1,
6179 type = "input",
6180 name = L["WoW Programming"],
6181 desc = L["WoW Programming is a good resource for finding out what difference API's do and how to call them."],
6182 set = false,
6183 get = function() return "http://wowprogramming.com/docs" end,
6184 width = "full",
6185 },
6186 },
6187 },
6188 },
6189 },
6190 },
6191 }
6192
6193 -- Load the initial tag list
6194 for tag in pairs(ShadowUF.Tags.defaultTags) do
6195 options.args.tags.args.general.args.list.args[tag] = tagTable
6196 end
6197
6198 for tag, data in pairs(ShadowUF.db.profile.tags) do
6199 options.args.tags.args.general.args.list.args[tag] = tagTable
6200 end
6201end
6202
6203---------------------
6204-- VISIBILITY OPTIONS
6205---------------------
6206local function loadVisibilityOptions()
6207 -- As zone units are only enabled in a certain zone... it's pointless to provide visibility options for them
6208 local unitBlacklist = {}
6209 for unit in pairs(ShadowUF.Units.zoneUnits) do unitBlacklist[unit] = true end
6210 for unit, parent in pairs(ShadowUF.Units.childUnits) do
6211 if( ShadowUF.Units.zoneUnits[parent] ) then
6212 unitBlacklist[unit] = true
6213 end
6214 end
6215
6216 local globalVisibility = {}
6217 local function set(info, value)
6218 local key = info[#(info)]
6219 local unit = info[#(info) - 1]
6220 local area = info[#(info) - 2]
6221
6222 if( key == "enabled" ) then
6223 key = ""
6224 end
6225
6226 if( value == nil ) then
6227 value = false
6228 elseif( value == false ) then
6229 value = nil
6230 end
6231
6232 for _, configUnit in pairs(ShadowUF.unitList) do
6233 if( ( configUnit == unit or unit == "global" ) and not unitBlacklist[configUnit] ) then
6234 ShadowUF.db.profile.visibility[area][configUnit .. key] = value
6235 end
6236 end
6237
6238 -- Annoying yes, but only way that works
6239 ShadowUF.Units:CheckPlayerZone(true)
6240
6241 if( unit == "global" ) then
6242 globalVisibility[area .. key] = value
6243 end
6244 end
6245
6246 local function get(info)
6247 local key = info[#(info)]
6248 local unit = info[#(info) - 1]
6249 local area = info[#(info) - 2]
6250
6251 if( key == "enabled" ) then
6252 key = ""
6253 end
6254
6255 if( unit == "global" ) then
6256 if( globalVisibility[area .. key] == false ) then
6257 return nil
6258 elseif( globalVisibility[area .. key] == nil ) then
6259 return false
6260 end
6261
6262 return globalVisibility[area .. key]
6263 elseif( ShadowUF.db.profile.visibility[area][unit .. key] == false ) then
6264 return nil
6265 elseif( ShadowUF.db.profile.visibility[area][unit .. key] == nil ) then
6266 return false
6267 end
6268
6269 return ShadowUF.db.profile.visibility[area][unit .. key]
6270 end
6271
6272 local function getHelp(info)
6273 local unit = info[#(info) - 1]
6274 local area = info[#(info) - 2]
6275 local key = info[#(info)]
6276 if( key == "enabled" ) then
6277 key = ""
6278 end
6279
6280 local current
6281 if( unit == "global" ) then
6282 current = globalVisibility[area .. key]
6283 else
6284 current = ShadowUF.db.profile.visibility[area][unit .. key]
6285 end
6286
6287 if( current == false ) then
6288 return string.format(L["Disabled in %s"], AREA_NAMES[area])
6289 elseif( current == true ) then
6290 return string.format(L["Enabled in %s"], AREA_NAMES[area])
6291 end
6292
6293 return L["Using unit settings"]
6294 end
6295
6296 local areaTable = {
6297 type = "group",
6298 order = function(info) return info[#(info)] == "none" and 2 or 1 end,
6299 childGroups = "tree",
6300 name = function(info)
6301 return AREA_NAMES[info[#(info)]]
6302 end,
6303 get = get,
6304 set = set,
6305 args = {},
6306 }
6307
6308 Config.visibilityTable = {
6309 type = "group",
6310 order = function(info) return info[#(info)] == "global" and 1 or (getUnitOrder(info) + 1) end,
6311 name = function(info) return info[#(info)] == "global" and L["Global"] or getName(info) end,
6312 args = {
6313 help = {
6314 order = 0,
6315 type = "group",
6316 name = L["Help"],
6317 inline = true,
6318 hidden = hideBasicOption,
6319 args = {
6320 help = {
6321 order = 0,
6322 type = "description",
6323 name = function(info)
6324 return string.format(L["Disabling a module on this page disables it while inside %s. Do not disable a module here if you do not want this to happen!."], string.lower(AREA_NAMES[info[2]]))
6325 end,
6326 },
6327 },
6328 },
6329 enabled = {
6330 order = 0.25,
6331 type = "toggle",
6332 name = function(info)
6333 local unit = info[#(info) - 1]
6334 if( unit == "global" ) then return "" end
6335 return string.format(L["%s frames"], L.units[unit])
6336 end,
6337 hidden = function(info) return info[#(info) - 1] == "global" end,
6338 desc = getHelp,
6339 tristate = true,
6340 width = "double",
6341 },
6342 sep = {
6343 order = 0.5,
6344 type = "description",
6345 name = "",
6346 width = "full",
6347 hidden = function(info) return info[#(info) - 1] == "global" end,
6348 },
6349 }
6350 }
6351
6352 local moduleTable = {
6353 order = 1,
6354 type = "toggle",
6355 name = getName,
6356 desc = getHelp,
6357 tristate = true,
6358 hidden = function(info)
6359 if( info[#(info) - 1] == "global" ) then return false end
6360 return hideRestrictedOption(info)
6361 end,
6362 arg = 1,
6363 }
6364
6365 for key, module in pairs(ShadowUF.modules) do
6366 if( module.moduleName ) then
6367 Config.visibilityTable.args[key] = moduleTable
6368 end
6369 end
6370
6371 areaTable.args.global = Config.visibilityTable
6372 for _, unit in pairs(ShadowUF.unitList) do
6373 if( not unitBlacklist[unit] ) then
6374 areaTable.args[unit] = Config.visibilityTable
6375 end
6376 end
6377
6378 options.args.visibility = {
6379 type = "group",
6380 childGroups = "tab",
6381 name = L["Zone Configuration"],
6382 desc = getPageDescription,
6383 args = {
6384 start = {
6385 order = 0,
6386 type = "group",
6387 name = L["Help"],
6388 inline = true,
6389 hidden = hideBasicOption,
6390 args = {
6391 help = {
6392 order = 0,
6393 type = "description",
6394 name = L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"],
6395 },
6396 },
6397 },
6398 pvp = areaTable,
6399 arena = areaTable,
6400 party = areaTable,
6401 raid = areaTable,
6402 },
6403 }
6404end
6405
6406---------------------
6407-- AURA INDICATORS OPTIONS
6408---------------------
6409local function loadAuraIndicatorsOptions()
6410 local Indicators = ShadowUF.modules.auraIndicators
6411 local auraFilters = Indicators.auraFilters
6412
6413 local unitTable
6414
6415 local groupAliases = {
6416 ["pvpflags"] = L["PvP Flags"],
6417 ["food"] = L["Food"],
6418 ["miscellaneous"] = L["Miscellaneous"]
6419 }
6420
6421 for token, name in pairs(LOCALIZED_CLASS_NAMES_MALE) do
6422 groupAliases[string.lower(token)] = name
6423 end
6424
6425 local groupList = {}
6426 local function getAuraGroup(info)
6427 for k in pairs(groupList) do groupList[k] = nil end
6428 for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do
6429 local aura = Indicators.auraConfig[name]
6430 groupList[aura.group] = aura.group
6431 end
6432
6433 return groupList
6434 end
6435
6436 local auraList = {}
6437 local function getAuraList(info)
6438 for k in pairs(auraList) do auraList[k] = nil end
6439 for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do
6440 if( tonumber(name) ) then
6441 local spellID = name
6442 name = GetSpellInfo(name) or L["Unknown"]
6443 auraList[name] = string.format("%s (#%i)", name, spellID)
6444 else
6445 auraList[name] = name
6446 end
6447 end
6448
6449 return auraList
6450 end
6451
6452 local indicatorList = {}
6453 local function getIndicatorList(info)
6454 for k in pairs(indicatorList) do indicatorList[k] = nil end
6455 indicatorList[""] = L["None (Disabled)"]
6456 for key, indicator in pairs(ShadowUF.db.profile.auraIndicators.indicators) do
6457 indicatorList[key] = indicator.name
6458 end
6459
6460 return indicatorList
6461 end
6462
6463 local function writeAuraTable(name)
6464 ShadowUF.db.profile.auraIndicators.auras[name] = writeTable(Indicators.auraConfig[name])
6465 Indicators.auraConfig[name] = nil
6466
6467 local spellID = tonumber(name)
6468 if( spellID ) then
6469 Indicators.auraConfig[spellID] = nil
6470 end
6471 end
6472
6473 local groupMap, auraMap, linkMap = {}, {}, {}
6474 local groupID, auraID, linkID = 0, 0, 0
6475
6476 local reverseClassMap = {}
6477 for token, text in pairs(LOCALIZED_CLASS_NAMES_MALE) do
6478 reverseClassMap[text] = token
6479 end
6480
6481 local function groupName(name)
6482 local converted = string.lower(string.gsub(name, " ", ""))
6483 return groupAliases[converted] or name
6484 end
6485
6486 -- Actual aura configuration
6487 local auraGroupTable = {
6488 order = function(info)
6489 return reverseClassMap[groupName(groupMap[info[#(info)]])] and 1 or 2
6490 end,
6491 type = "group",
6492 name = function(info)
6493 local name = groupName(groupMap[info[#(info)]])
6494
6495 local token = reverseClassMap[name]
6496 if( not token ) then return name end
6497
6498 return ShadowUF:Hex(ShadowUF.db.profile.classColors[token]) .. name .. "|r"
6499 end,
6500 desc = function(info)
6501 local group = groupMap[info[#(info)]]
6502 local totalInGroup = 0
6503 for _, aura in pairs(Indicators.auraConfig) do
6504 if( type(aura) == "table" and aura.group == group ) then
6505 totalInGroup = totalInGroup + 1
6506 end
6507 end
6508
6509 return string.format(L["%d auras in group"], totalInGroup)
6510 end,
6511 args = {},
6512 }
6513
6514 local auraConfigTable = {
6515 order = 0,
6516 type = "group",
6517 icon = function(info)
6518 local aura = auraMap[info[#(info)]]
6519 return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil
6520 end,
6521 name = function(info)
6522 local aura = auraMap[info[#(info)]]
6523 return tonumber(aura) and string.format("%s (#%i)", GetSpellInfo(aura) or "Unknown", aura) or aura
6524 end,
6525 hidden = function(info)
6526 local group = groupMap[info[#(info) - 1]]
6527 local aura = Indicators.auraConfig[auraMap[info[#(info)]]]
6528 return aura.group ~= group
6529 end,
6530 set = function(info, value, g, b, a)
6531 local aura = auraMap[info[#(info) - 1]]
6532 local key = info[#(info)]
6533
6534 -- So I don't have to load every aura to see if it only triggers if it's missing
6535 if( key == "missing" ) then
6536 ShadowUF.db.profile.auraIndicators.missing[aura] = value and true or nil
6537 -- Changing the color
6538 elseif( key == "color" ) then
6539 Indicators.auraConfig[aura].r = value
6540 Indicators.auraConfig[aura].g = g
6541 Indicators.auraConfig[aura].b = b
6542 Indicators.auraConfig[aura].alpha = a
6543
6544 writeAuraTable(aura)
6545 ShadowUF.Layout:Reload()
6546 return
6547 elseif( key == "selfColor" ) then
6548 Indicators.auraConfig[aura].selfColor = Indicators.auraConfig[aura].selfColor or {}
6549 Indicators.auraConfig[aura].selfColor.r = value
6550 Indicators.auraConfig[aura].selfColor.g = g
6551 Indicators.auraConfig[aura].selfColor.b = b
6552 Indicators.auraConfig[aura].selfColor.alpha = a
6553
6554 writeAuraTable(aura)
6555 ShadowUF.Layout:Reload()
6556 return
6557 end
6558
6559 Indicators.auraConfig[aura][key] = value
6560 writeAuraTable(aura)
6561 ShadowUF.Layout:Reload()
6562 end,
6563 get = function(info)
6564 local aura = auraMap[info[#(info) - 1]]
6565 local key = info[#(info)]
6566 local config = Indicators.auraConfig[aura]
6567 if( key == "color" ) then
6568 return config.r, config.g, config.b, config.alpha
6569 elseif( key == "selfColor" ) then
6570 if( not config.selfColor ) then return 0, 0, 0, 1 end
6571 return config.selfColor.r, config.selfColor.g, config.selfColor.b, config.selfColor.alpha
6572 end
6573
6574 return config[key]
6575 end,
6576 args = {
6577 indicator = {
6578 order = 1,
6579 type = "select",
6580 name = L["Show inside"],
6581 desc = L["Indicator this aura should be displayed in."],
6582 values = getIndicatorList,
6583 hidden = false,
6584 },
6585 priority = {
6586 order = 2,
6587 type = "range",
6588 name = L["Priority"],
6589 desc = L["If multiple auras are shown in the same indicator, the higher priority one is shown first."],
6590 min = 0, max = 100, step = 1,
6591 hidden = false,
6592 },
6593 sep1 = {
6594 order = 3,
6595 type = "description",
6596 name = "",
6597 width = "full",
6598 hidden = false,
6599 },
6600 color = {
6601 order = 4,
6602 type = "color",
6603 name = L["Indicator color"],
6604 desc = L["Solid color to use in the indicator, only used if you do not have use aura icon enabled."],
6605 disabled = function(info) return Indicators.auraConfig[auraMap[info[#(info) - 1]]].icon end,
6606 hidden = false,
6607 hasAlpha = true,
6608 },
6609 selfColor = {
6610 order = 4.5,
6611 type = "color",
6612 name = L["Your aura color"],
6613 desc = L["This color will be used if the indicator shown is your own, only applies if icons are not used.\nHandy if you want to know if a target has a Rejuvenation on them, but you also want to know if you were the one who casted the Rejuvenation."],
6614 hidden = false,
6615 disabled = function(info)
6616 if( Indicators.auraConfig[auraMap[info[#(info) - 1]]].icon ) then return true end
6617 return Indicators.auraConfig[auraMap[info[#(info) - 1]]].player
6618 end,
6619 hasAlpha = true,
6620 },
6621 sep2 = {
6622 order = 5,
6623 type = "description",
6624 name = "",
6625 width = "full",
6626 hidden = false,
6627 },
6628 icon = {
6629 order = 6,
6630 type = "toggle",
6631 name = L["Show aura icon"],
6632 desc = L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."],
6633 hidden = false,
6634 },
6635 duration = {
6636 order = 7,
6637 type = "toggle",
6638 name = L["Show aura duration"],
6639 desc = L["Shows a cooldown wheel on the indicator with how much time is left on the aura."],
6640 hidden = false,
6641 },
6642 player = {
6643 order = 8,
6644 type = "toggle",
6645 name = L["Only show self cast auras"],
6646 desc = L["Only auras you specifically cast will be shown."],
6647 hidden = false,
6648 },
6649 missing = {
6650 order = 9,
6651 type = "toggle",
6652 name = L["Only show if missing"],
6653 desc = L["Only active this aura inside an indicator if the group member does not have the aura."],
6654 hidden = false,
6655 },
6656 delete = {
6657 order = 10,
6658 type = "execute",
6659 name = L["Delete"],
6660 hidden = function(info)
6661 return ShadowUF.db.defaults.profile.auraIndicators.auras[auraMap[info[#(info) - 1]]]
6662 end,
6663 confirm = true,
6664 confirmText = L["Are you sure you want to delete this aura?"],
6665 func = function(info)
6666 local key = info[#(info) - 1]
6667 local aura = auraMap[key]
6668
6669 auraGroupTable.args[key] = nil
6670 ShadowUF.db.profile.auraIndicators.auras[aura] = nil
6671 ShadowUF.db.profile.auraIndicators.missing[aura] = nil
6672 Indicators.auraConfig[aura] = nil
6673
6674 -- Check if the group should disappear
6675 local groupList = getAuraGroup(info)
6676 for groupID, name in pairs(groupMap) do
6677 if( not groupList[name] ) then
6678 unitTable.args[tostring(groupID)] = nil
6679 options.args.auraIndicators.args.units.args.global.args.groups.args[tostring(groupID)] = nil
6680 options.args.auraIndicators.args.auras.args.groups.args[tostring(groupID)] = nil
6681 groupMap[groupID] = nil
6682 end
6683 end
6684
6685 ShadowUF.Layout:Reload()
6686 end,
6687 },
6688 },
6689 }
6690
6691 local auraFilterConfigTable = {
6692 order = 0,
6693 type = "group",
6694 hidden = false,
6695 name = function(info)
6696 return ShadowUF.db.profile.auraIndicators.indicators[info[#(info)]].name
6697 end,
6698 set = function(info, value)
6699 local key = info[#(info)]
6700 local indicator = info[#(info) - 2]
6701 local filter = info[#(info) - 1]
6702 ShadowUF.db.profile.auraIndicators.filters[indicator][filter][key] = value
6703 ShadowUF.Layout:Reload()
6704 end,
6705 get = function(info)
6706 local key = info[#(info)]
6707 local indicator = info[#(info) - 2]
6708 local filter = info[#(info) - 1]
6709 if( not ShadowUF.db.profile.auraIndicators.filters[indicator][filter] ) then
6710 ShadowUF.db.profile.auraIndicators.filters[indicator][filter] = {}
6711 end
6712
6713 return ShadowUF.db.profile.auraIndicators.filters[indicator][filter][key]
6714 end,
6715 args = {
6716 help = {
6717 order = 0,
6718 type = "group",
6719 name = L["Help"],
6720 inline = true,
6721 args = {
6722 help = {
6723 type = "description",
6724 name = L["Auras matching a criteria will automatically show up in the indicator when enabled."]
6725 }
6726 }
6727 },
6728 boss = {
6729 order = 1,
6730 type = "group",
6731 name = L["Boss Auras"],
6732 inline = true,
6733 args = {
6734 enabled = {
6735 order = 1,
6736 type = "toggle",
6737 name = L["Show boss debuffs"],
6738 desc = L["Shows debuffs cast by a boss."]
6739 },
6740 duration = {
6741 order = 2,
6742 type = "toggle",
6743 name = L["Show aura duration"],
6744 desc = L["Shows a cooldown wheel on the indicator with how much time is left on the aura."]
6745 },
6746 priority = {
6747 order = 3,
6748 type = "range",
6749 name = L["Priority"],
6750 desc = L["If multiple auras are shown in the same indicator, the higher priority one is shown first."],
6751 min = 0, max = 100, step = 1
6752 }
6753 }
6754 },
6755 curable = {
6756 order = 2,
6757 type = "group",
6758 name = L["Curable Auras"],
6759 inline = true,
6760 args = {
6761 enabled = {
6762 order = 1,
6763 type = "toggle",
6764 name = L["Show curable debuffs"],
6765 desc = L["Shows debuffs that you can cure."]
6766 },
6767 duration = {
6768 order = 2,
6769 type = "toggle",
6770 name = L["Show aura duration"],
6771 desc = L["Shows a cooldown wheel on the indicator with how much time is left on the aura."]
6772 },
6773 priority = {
6774 order = 3,
6775 type = "range",
6776 name = L["Priority"],
6777 desc = L["If multiple auras are shown in the same indicator, the higher priority one is shown first."],
6778 min = 0, max = 100, step = 1
6779 }
6780 }
6781 }
6782 }
6783 }
6784
6785 local indicatorTable = {
6786 order = 1,
6787 type = "group",
6788 name = function(info) return ShadowUF.db.profile.auraIndicators.indicators[info[#(info)]].name end,
6789 args = {
6790 config = {
6791 order = 0,
6792 type = "group",
6793 inline = true,
6794 name = function(info) return ShadowUF.db.profile.auraIndicators.indicators[info[#(info) - 1]].name end,
6795 set = function(info, value)
6796 local indicator = info[#(info) - 2]
6797 local key = info[#(info)]
6798
6799 ShadowUF.db.profile.auraIndicators.indicators[indicator][key] = value
6800 ShadowUF.Layout:Reload()
6801 end,
6802 get = function(info)
6803 local indicator = info[#(info) - 2]
6804 local key = info[#(info)]
6805 return ShadowUF.db.profile.auraIndicators.indicators[indicator][key]
6806 end,
6807 args = {
6808 showStack = {
6809 order = 1,
6810 type = "toggle",
6811 name = L["Show auras stack"],
6812 desc = L["Any auras shown in this indicator will have their total stack displayed."],
6813 width = "full",
6814 },
6815 friendly = {
6816 order = 2,
6817 type = "toggle",
6818 name = L["Enable for friendlies"],
6819 desc = L["Checking this will show the indicator on friendly units."],
6820 },
6821 hostile = {
6822 order = 3,
6823 type = "toggle",
6824 name = L["Enable for hostiles"],
6825 desc = L["Checking this will show the indciator on hostile units."],
6826 },
6827 anchorPoint = {
6828 order = 4,
6829 type = "select",
6830 name = L["Anchor point"],
6831 values = {["BRI"] = L["Inside Bottom Right"], ["BLI"] = L["Inside Bottom Left"], ["TRI"] = L["Inside Top Right"], ["TLI"] = L["Inside Top Left"], ["CLI"] = L["Inside Center Left"], ["C"] = L["Center"], ["CRI"] = L["Inside Center Right"]},
6832 },
6833 size = {
6834 order = 5,
6835 name = L["Size"],
6836 type = "range",
6837 min = 0, max = 50, step = 1,
6838 set = function(info, value)
6839 local indicator = info[#(info) - 2]
6840 ShadowUF.db.profile.auraIndicators.indicators[indicator].height = value
6841 ShadowUF.db.profile.auraIndicators.indicators[indicator].width = value
6842 ShadowUF.Layout:Reload()
6843 end,
6844 get = function(info)
6845 local indicator = info[#(info) - 2]
6846 return ShadowUF.db.profile.auraIndicators.indicators[indicator].height
6847 end,
6848 },
6849 x = {
6850 order = 6,
6851 type = "range",
6852 name = L["X Offset"],
6853 min = -50, max = 50, step = 1,
6854 },
6855 y = {
6856 order = 7,
6857 type = "range",
6858 name = L["Y Offset"],
6859 min = -50, max = 50, step = 1,
6860 },
6861 delete = {
6862 order = 8,
6863 type = "execute",
6864 name = L["Delete"],
6865 confirm = true,
6866 confirmText = L["Are you sure you want to delete this indicator?"],
6867 func = function(info)
6868 local indicator = info[#(info) - 2]
6869
6870 options.args.auraIndicators.args.indicators.args[indicator] = nil
6871 options.args.auraIndicators.args.auras.args.filters.args[indicator] = nil
6872
6873 ShadowUF.db.profile.auraIndicators.indicators[indicator] = nil
6874 ShadowUF.db.profile.auraIndicators.filters[indicator] = nil
6875
6876 -- Any aura that was set to us should be swapped back to none
6877 for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do
6878 local aura = Indicators.auraConfig[name]
6879 if( aura.indicator == indicator ) then
6880 aura.indicator = ""
6881 writeAuraTable(name)
6882 end
6883 end
6884
6885 ShadowUF.Layout:Reload()
6886 end,
6887 },
6888 },
6889 },
6890 },
6891 }
6892
6893 local parentLinkTable = {
6894 order = 3,
6895 type = "group",
6896 icon = function(info)
6897 local aura = auraMap[info[#(info)]]
6898 return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil
6899 end,
6900 name = function(info)
6901 local aura = linkMap[info[#(info)]]
6902 return tonumber(aura) and string.format("%s (#%i)", GetSpellInfo(aura) or "Unknown", aura) or aura
6903 end,
6904 args = {},
6905 }
6906
6907 local childLinkTable = {
6908 order = 1,
6909 icon = function(info)
6910 local aura = auraMap[info[#(info)]]
6911 return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil
6912 end,
6913 name = function(info)
6914 local aura = linkMap[info[#(info)]]
6915 return tonumber(aura) and string.format("%s (#%i)", GetSpellInfo(aura) or "Unknown", aura) or aura
6916 end,
6917 hidden = function(info)
6918 local aura = linkMap[info[#(info)]]
6919 local parent = linkMap[info[#(info) - 1]]
6920
6921 return ShadowUF.db.profile.auraIndicators.linked[aura] ~= parent
6922 end,
6923 type = "group",
6924 inline = true,
6925 args = {
6926 delete = {
6927 type = "execute",
6928 name = L["Delete link"],
6929 hidden = false,
6930 func = function(info)
6931 local auraID = info[#(info) - 1]
6932 local aura = linkMap[auraID]
6933 local parent = ShadowUF.db.profile.auraIndicators.linked[aura]
6934 ShadowUF.db.profile.auraIndicators.linked[aura] = nil
6935 parentLinkTable.args[auraID] = nil
6936
6937 local found
6938 for _, to in pairs(ShadowUF.db.profile.auraIndicators.linked) do
6939 if( to == parent ) then
6940 found = true
6941 break
6942 end
6943 end
6944
6945 if( not found ) then
6946 for id, name in pairs(linkMap) do
6947 if( name == parent ) then
6948 options.args.auraIndicators.args.linked.args[tostring(id)] = nil
6949 linkMap[id] = nil
6950 end
6951 end
6952 end
6953
6954 ShadowUF.Layout:Reload()
6955 end,
6956 },
6957 },
6958 }
6959
6960 local addAura, addLink, setGlobalUnits, globalConfig = {}, {}, {}, {}
6961
6962 -- Per unit enabled status
6963 unitTable = {
6964 order = ShadowUF.Config.getUnitOrder or 1,
6965 type = "group",
6966 name = function(info) return L.units[info[3]] end,
6967 hidden = function(info) return not ShadowUF.db.profile.units[info[3]].enabled end,
6968 desc = function(info)
6969 local totalDisabled = 0
6970 for key, enabled in pairs(ShadowUF.db.profile.units[info[3]].auraIndicators) do
6971 if( key ~= "enabled" and enabled ) then
6972 totalDisabled = totalDisabled + 1
6973 end
6974 end
6975
6976 if( totalDisabled == 1 ) then return L["1 aura group disabled"] end
6977 return totalDisabled > 0 and string.format(L["%s aura groups disabled"], totalDisabled) or L["All aura groups enabled for unit."]
6978 end,
6979 args = {
6980 enabled = {
6981 order = 1,
6982 inline = true,
6983 type = "group",
6984 name = function(info) return string.format(L["On %s units"], L.units[info[3]]) end,
6985 args = {
6986 enabled = {
6987 order = 1,
6988 type = "toggle",
6989 name = L["Enable Indicators"],
6990 desc = function(info) return string.format(L["Unchecking this will completely disable aura indicators for %s."], L.units[info[3]]) end,
6991 set = function(info, value) ShadowUF.db.profile.units[info[3]].auraIndicators.enabled = value; ShadowUF.Layout:Reload() end,
6992 get = function(info) return ShadowUF.db.profile.units[info[3]].auraIndicators.enabled end,
6993 },
6994 },
6995 },
6996 filters = {
6997 order = 2,
6998 inline = true,
6999 type = "group",
7000 name = L["Aura Filters"],
7001 disabled = function(info) return not ShadowUF.db.profile.units[info[3]].auraIndicators.enabled end,
7002 args = {},
7003 },
7004 groups = {
7005 order = 3,
7006 inline = true,
7007 type = "group",
7008 name = L["Aura Groups"],
7009 disabled = function(info) return not ShadowUF.db.profile.units[info[3]].auraIndicators.enabled end,
7010 args = {},
7011 },
7012 }
7013 }
7014
7015 local unitFilterTable = {
7016 order = 1,
7017 type = "toggle",
7018 name = function(info) return info[#(info)] == "boss" and L["Boss Auras"] or L["Curable Auras"] end,
7019 desc = function(info)
7020 local auraIndicators = ShadowUF.db.profile.units[info[3]].auraIndicators
7021 return auraIndicators["filter-" .. info[#(info)]] and string.format(L["Disabled for %s."], L.units[info[3]]) or string.format(L["Enabled for %s."], L.units[info[3]])
7022 end,
7023 set = function(info, value) ShadowUF.db.profile.units[info[3]].auraIndicators["filter-" .. info[#(info)]] = not value and true or nil end,
7024 get = function(info, value) return not ShadowUF.db.profile.units[info[3]].auraIndicators["filter-" .. info[#(info)]] end
7025 }
7026
7027 local globalUnitFilterTable = {
7028 order = 1,
7029 type = "toggle",
7030 name = function(info) return info[#(info)] == "boss" and L["Boss Auras"] or L["Curable Auras"] end,
7031 disabled = function(info) for unit in pairs(setGlobalUnits) do return false end return true end,
7032 set = function(info, value)
7033 local key = "filter-" .. info[#(info)]
7034 globalConfig[key] = not value and true or nil
7035
7036 for unit in pairs(setGlobalUnits) do
7037 ShadowUF.db.profile.units[unit].auraIndicators[key] = globalConfig[key]
7038 end
7039 end,
7040 get = function(info, value) return not globalConfig["filter-" .. info[#(info)]] end
7041 }
7042
7043 local unitGroupTable = {
7044 order = function(info)
7045 return reverseClassMap[groupName(groupMap[info[#(info)]])] and 1 or 2
7046 end,
7047 type = "toggle",
7048 name = function(info)
7049 local name = groupName(groupMap[info[#(info)]])
7050 local token = reverseClassMap[name]
7051 if( not token ) then return name end
7052 return ShadowUF:Hex(ShadowUF.db.profile.classColors[token]) .. name .. "|r"
7053 end,
7054 desc = function(info)
7055 local auraIndicators = ShadowUF.db.profile.units[info[3]].auraIndicators
7056 local group = groupName(groupMap[info[#(info)]])
7057
7058 return auraIndicators[group] and string.format(L["Disabled for %s."], L.units[info[3]]) or string.format(L["Enabled for %s."], L.units[info[3]])
7059 end,
7060 set = function(info, value) ShadowUF.db.profile.units[info[3]].auraIndicators[groupMap[info[#(info)]]] = not value and true or nil end,
7061 get = function(info, value) return not ShadowUF.db.profile.units[info[3]].auraIndicators[groupMap[info[#(info)]]] end
7062 }
7063
7064 local globalUnitGroupTable = {
7065 type = "toggle",
7066 order = function(info)
7067 return reverseClassMap[groupName(groupMap[info[#(info)]])] and 1 or 2
7068 end,
7069 name = function(info)
7070 local name = groupName(groupMap[info[#(info)]])
7071 local token = reverseClassMap[name]
7072 if( not token ) then return name end
7073 return ShadowUF:Hex(ShadowUF.db.profile.classColors[token]) .. name .. "|r"
7074 end,
7075 disabled = function(info) for unit in pairs(setGlobalUnits) do return false end return true end,
7076 set = function(info, value)
7077 local auraGroup = groupMap[info[#(info)]]
7078 globalConfig[auraGroup] = not value and true or nil
7079
7080 for unit in pairs(setGlobalUnits) do
7081 ShadowUF.db.profile.units[unit].auraIndicators[auraGroup] = globalConfig[auraGroup]
7082 end
7083 end,
7084 get = function(info, value) return not globalConfig[groupMap[info[#(info)]]] end
7085 }
7086
7087 local enabledUnits = {}
7088 local function getEnabledUnits()
7089 table.wipe(enabledUnits)
7090 for unit, config in pairs(ShadowUF.db.profile.units) do
7091 if( config.enabled and config.auraIndicators.enabled ) then
7092 enabledUnits[unit] = L.units[unit]
7093 end
7094 end
7095
7096 return enabledUnits
7097 end
7098
7099 local widthReset
7100
7101 -- Actual tab view thing
7102 options.args.auraIndicators = {
7103 order = 4.5,
7104 type = "group",
7105 name = L["Aura Indicators"],
7106 desc = L["For configuring aura indicators on unit frames."],
7107 childGroups = "tab",
7108 hidden = false,
7109 args = {
7110 indicators = {
7111 order = 1,
7112 type = "group",
7113 name = L["Indicators"],
7114 childGroups = "tree",
7115 args = {
7116 add = {
7117 order = 0,
7118 type = "group",
7119 name = L["Add Indicator"],
7120 args = {
7121 add = {
7122 order = 0,
7123 type = "group",
7124 inline = true,
7125 name = L["Add new indicator"],
7126 args = {
7127 name = {
7128 order = 0,
7129 type = "input",
7130 name = L["Indicator name"],
7131 width = "full",
7132 set = function(info, value)
7133 local id = string.format("%d", GetTime() + math.random(100))
7134 ShadowUF.db.profile.auraIndicators.indicators[id] = {enabled = true, friendly = true, hostile = true, name = value, anchorPoint = "C", anchorTo = "$parent", height = 10, width = 10, alpha = 1.0, x = 0, y = 0}
7135 ShadowUF.db.profile.auraIndicators.filters[id] = {boss = {}, curable = {}}
7136
7137 options.args.auraIndicators.args.indicators.args[id] = indicatorTable
7138 options.args.auraIndicators.args.auras.args.filters.args[id] = auraFilterConfigTable
7139
7140 AceDialog.Status.ShadowedUF.children.auraIndicators.children.indicators.status.groups.selected = id
7141 AceRegistry:NotifyChange("ShadowedUF")
7142 end,
7143 get = function() return "" end,
7144 },
7145 },
7146 },
7147 },
7148 },
7149 },
7150 },
7151 auras = {
7152 order = 2,
7153 type = "group",
7154 name = L["Auras"],
7155 hidden = function(info)
7156 if( not widthReset and AceDialog.Status.ShadowedUF.children.auraIndicators ) then
7157 if( AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras ) then
7158 widthReset = true
7159
7160 AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.treewidth = 230
7161
7162 AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.groups = {}
7163 AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.groups.filters = true
7164 AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.groups.groups = true
7165
7166 AceRegistry:NotifyChange("ShadowedUF")
7167 end
7168 end
7169
7170 return false
7171 end,
7172 args = {
7173 add = {
7174 order = 0,
7175 type = "group",
7176 name = L["Add Aura"],
7177 set = function(info, value) addAura[info[#(info)]] = value end,
7178 get = function(info) return addAura[info[#(info)]] end,
7179 args = {
7180 name = {
7181 order = 0,
7182 type = "input",
7183 name = L["Spell Name/ID"],
7184 desc = L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."]
7185 },
7186 group = {
7187 order = 1,
7188 type = "select",
7189 name = L["Aura group"],
7190 desc = L["What group this aura belongs to, this is where you will find it when configuring."],
7191 values = getAuraGroup,
7192 },
7193 custom = {
7194 order = 2,
7195 type = "input",
7196 name = L["New aura group"],
7197 desc = L["Allows you to enter a new aura group."],
7198 },
7199 create = {
7200 order = 3,
7201 type = "execute",
7202 name = L["Add aura"],
7203 disabled = function(info) return not addAura.name or (not addAura.group and not addAura.custom) end,
7204 func = function(info)
7205 local group = string.trim(addAura.custom or "")
7206 if( group == "" ) then group = string.trim(addAura.group or "") end
7207 if( group == "" ) then group = L["Miscellaneous"] end
7208
7209 -- Don't overwrite an existing group, but don't tell them either, mostly because I don't want to add error reporting code
7210 if( not ShadowUF.db.profile.auraIndicators.auras[addAura.name] ) then
7211 -- Odds are, if they are saying to show it only if a buff is missing it's cause they want to know when their own class buff is not there
7212 -- so will cheat it, and jump start it by storing the texture if we find it from GetSpellInfo directly
7213 Indicators.auraConfig[addAura.name] = {indicator = "", group = group, iconTexture = select(3, GetSpellInfo(addAura.name)), priority = 0, r = 0, g = 0, b = 0}
7214 writeAuraTable(addAura.name)
7215
7216 auraID = auraID + 1
7217 auraMap[tostring(auraID)] = addAura.name
7218 auraGroupTable.args[tostring(auraID)] = auraConfigTable
7219 end
7220
7221 addAura.name = nil
7222 addAura.custom = nil
7223 addAura.group = nil
7224
7225 -- Check if the group exists
7226 local gID
7227 for id, name in pairs(groupMap) do
7228 if( name == group ) then
7229 gID = id
7230 break
7231 end
7232 end
7233
7234 if( not gID ) then
7235 groupID = groupID + 1
7236 groupMap[tostring(groupID)] = group
7237
7238 unitTable.args.groups.args[tostring(groupID)] = unitGroupTable
7239 options.args.auraIndicators.args.units.args.global.args.groups.args[tostring(groupID)] = globalUnitGroupTable
7240 options.args.auraIndicators.args.auras.args.groups.args[tostring(groupID)] = auraGroupTable
7241 end
7242
7243 -- Shunt the user to the this groups page
7244 AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.selected = tostring(gID or groupID)
7245 AceRegistry:NotifyChange("ShadowedUF")
7246
7247 ShadowUF.Layout:Reload()
7248 end,
7249 },
7250 },
7251 },
7252 filters = {
7253 order = 1,
7254 type = "group",
7255 name = L["Automatic Auras"],
7256 args = {}
7257 },
7258 groups = {
7259 order = 2,
7260 type = "group",
7261 name = L["Groups"],
7262 args = {}
7263 },
7264 },
7265 },
7266 linked = {
7267 order = 3,
7268 type = "group",
7269 name = L["Linked spells"],
7270 childGroups = "tree",
7271 hidden = true,
7272 args = {
7273 help = {
7274 order = 0,
7275 type = "group",
7276 name = L["Help"],
7277 inline = true,
7278 args = {
7279 help = {
7280 order = 0,
7281 type = "description",
7282 name = L["You can link auras together using this, for example you can link Mark of the Wild to Gift of the Wild so if the player has Mark of the Wild but not Gift of the Wild, it will still show Mark of the Wild as if they had Gift of the Wild."],
7283 width = "full",
7284 },
7285 },
7286 },
7287 add = {
7288 order = 1,
7289 type = "group",
7290 name = L["Add link"],
7291 inline = true,
7292 set = function(info, value)
7293 addLink[info[#(info)] ] = value
7294 end,
7295 get = function(info) return addLink[info[#(info)] ] end,
7296 args = {
7297 from = {
7298 order = 0,
7299 type = "input",
7300 name = L["Link from"],
7301 desc = L["Spell you want to link to a primary aura, the casing must be exact."],
7302 },
7303 to = {
7304 order = 1,
7305 type = "select",
7306 name = L["Link to"],
7307 values = getAuraList,
7308 },
7309 link = {
7310 order = 3,
7311 type = "execute",
7312 name = L["Link"],
7313 disabled = function() return not addLink.from or not addLink.to or addLink.from == "" end,
7314 func = function(info)
7315 local lID, pID
7316 for id, name in pairs(linkMap) do
7317 if( name == addLink.from ) then
7318 lID = id
7319 elseif( name == addLink.to ) then
7320 pID = id
7321 end
7322 end
7323
7324 if( not pID ) then
7325 linkID = linkID + 1
7326 pID = linkID
7327 linkMap[tostring(linkID)] = addLink.to
7328 end
7329
7330 if( not lID ) then
7331 linkID = linkID + 1
7332 lID = linkID
7333 linkMap[tostring(linkID)] = addLink.from
7334 end
7335
7336 ShadowUF.db.profile.auraIndicators.linked[addLink.from] = addLink.to
7337 options.args.auraIndicators.args.linked.args[tostring(pID)] = parentLinkTable
7338 parentLinkTable.args[tostring(lID)] = childLinkTable
7339
7340 addLink.from = nil
7341 addLink.to = nil
7342
7343 ShadowUF.Layout:Reload()
7344 end,
7345 },
7346 },
7347 },
7348 },
7349 },
7350 units = {
7351 order = 4,
7352 type = "group",
7353 name = L["Enable Indicators"],
7354 args = {
7355 help = {
7356 order = 0,
7357 type = "group",
7358 name = L["Help"],
7359 inline = true,
7360 args = {
7361 help = {
7362 order = 0,
7363 type = "description",
7364 name = L["You can disable aura filters and groups for units here. For example, you could set an aura group that shows DPS debuffs to only show on the target."],
7365 width = "full",
7366 },
7367 },
7368 },
7369 global = {
7370 order = 0,
7371 type = "group",
7372 name = L["Global"],
7373 desc = L["Global configurating will let you mass enable or disable aura groups for multiple units at once."],
7374 args = {
7375 units = {
7376 order = 0,
7377 type = "multiselect",
7378 name = L["Units to change"],
7379 desc = L["Units that should have the aura groups settings changed below."],
7380 values = getEnabledUnits,
7381 set = function(info, unit, enabled) setGlobalUnits[unit] = enabled or nil end,
7382 get = function(info, unit) return setGlobalUnits[unit] end,
7383 },
7384 filters = {
7385 order = 1,
7386 type = "group",
7387 inline = true,
7388 name = L["Aura filters"],
7389 args = {}
7390 },
7391 groups = {
7392 order = 2,
7393 type = "group",
7394 inline = true,
7395 name = L["Aura groups"],
7396 args = {}
7397 },
7398 },
7399 },
7400 },
7401 },
7402 classes = {
7403 order = 5,
7404 type = "group",
7405 name = L["Disable Auras by Class"],
7406 childGroups = "tree",
7407 args = {
7408 help = {
7409 order = 0,
7410 type = "group",
7411 name = L["Help"],
7412 inline = true,
7413 args = {
7414 help = {
7415 order = 0,
7416 type = "description",
7417 name = L["You can override what aura is enabled on a per-class basis, note that if the aura is disabled through the main listing, then your class settings here will not matter."],
7418 width = "full",
7419 },
7420 },
7421 }
7422 },
7423 },
7424 },
7425 }
7426
7427 local classTable = {
7428 order = 1,
7429 type = "group",
7430 name = function(info)
7431 return ShadowUF:Hex(ShadowUF.db.profile.classColors[info[#(info)]]) .. LOCALIZED_CLASS_NAMES_MALE[info[#(info)]] .. "|r"
7432 end,
7433 args = {},
7434 }
7435
7436 local classAuraTable = {
7437 order = 1,
7438 type = "toggle",
7439 icon = function(info)
7440 local aura = auraMap[info[#(info)]]
7441 return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil
7442 end,
7443 name = function(info)
7444 local aura = tonumber(auraMap[info[#(info)]])
7445 if( not aura ) then return auraMap[info[#(info)]] end
7446
7447 local name, _, icon = GetSpellInfo(aura)
7448 if( not name ) then return name end
7449
7450 return "|T" .. icon .. ":18:18:0:0|t " .. name
7451 end,
7452 desc = function(info)
7453 local aura = auraMap[info[#(info)]]
7454 if( tonumber(aura) ) then
7455 return string.format(L["Spell ID %s"], aura)
7456 else
7457 return aura
7458 end
7459 end,
7460 set = function(info, value)
7461 local aura = auraMap[info[#(info)]]
7462 local class = info[#(info) - 1]
7463 value = not value
7464
7465 if( value == false ) then value = nil end
7466 ShadowUF.db.profile.auraIndicators.disabled[class][aura] = value
7467 ShadowUF.Layout:Reload()
7468 end,
7469 get = function(info)
7470 local aura = auraMap[info[#(info)]]
7471 local class = info[#(info) - 1]
7472
7473 return not ShadowUF.db.profile.auraIndicators.disabled[class][aura]
7474 end,
7475 }
7476
7477 -- Build links
7478 local addedFrom = {}
7479 for from, to in pairs(ShadowUF.db.profile.auraIndicators.linked) do
7480 local pID = addedFrom[to]
7481 if( not pID ) then
7482 linkID = linkID + 1
7483 pID = linkID
7484
7485 addedFrom[to] = pID
7486 end
7487
7488 linkID = linkID + 1
7489
7490 ShadowUF.db.profile.auraIndicators.linked[from] = to
7491 options.args.auraIndicators.args.linked.args[tostring(pID)] = parentLinkTable
7492 parentLinkTable.args[tostring(linkID)] = childLinkTable
7493
7494 linkMap[tostring(linkID)] = from
7495 linkMap[tostring(pID)] = to
7496 end
7497
7498 -- Build the aura configuration
7499 local groups = {}
7500 for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do
7501 local aura = Indicators.auraConfig[name]
7502 if( aura.group ) then
7503 auraMap[tostring(auraID)] = name
7504 auraGroupTable.args[tostring(auraID)] = auraConfigTable
7505 classTable.args[tostring(auraID)] = classAuraTable
7506 auraID = auraID + 1
7507
7508 groups[aura.group] = true
7509 end
7510 end
7511
7512 -- Now create all of the parent stuff
7513 for group in pairs(groups) do
7514 groupMap[tostring(groupID)] = group
7515 unitTable.args.groups.args[tostring(groupID)] = unitGroupTable
7516
7517 options.args.auraIndicators.args.units.args.global.args.groups.args[tostring(groupID)] = globalUnitGroupTable
7518 options.args.auraIndicators.args.auras.args.groups.args[tostring(groupID)] = auraGroupTable
7519
7520 groupID = groupID + 1
7521 end
7522
7523 for _, type in pairs(auraFilters) do
7524 unitTable.args.filters.args[type] = unitFilterTable
7525 options.args.auraIndicators.args.units.args.global.args.filters.args[type] = globalUnitFilterTable
7526 end
7527
7528 -- Aura status by unit
7529 for unit, config in pairs(ShadowUF.db.profile.units) do
7530 options.args.auraIndicators.args.units.args[unit] = unitTable
7531 end
7532
7533 -- Build class status thing
7534 for classToken in pairs(RAID_CLASS_COLORS) do
7535 options.args.auraIndicators.args.classes.args[classToken] = classTable
7536 end
7537
7538 -- Quickly build the indicator one
7539 for key in pairs(ShadowUF.db.profile.auraIndicators.indicators) do
7540 options.args.auraIndicators.args.indicators.args[key] = indicatorTable
7541 options.args.auraIndicators.args.auras.args.filters.args[key] = auraFilterConfigTable
7542 end
7543
7544 -- Automatically unlock the advanced text configuration for raid frames, regardless of advanced being enabled
7545 local advanceTextTable = ShadowUF.Config.advanceTextTable
7546 local originalHidden = advanceTextTable.args.sep.hidden
7547 local function unlockRaidText(info)
7548 if( info[2] == "raid" ) then return false end
7549 return originalHidden(info)
7550 end
7551
7552 advanceTextTable.args.anchorPoint.hidden = unlockRaidText
7553 advanceTextTable.args.sep.hidden = unlockRaidText
7554 advanceTextTable.args.x.hidden = unlockRaidText
7555 advanceTextTable.args.y.hidden = unlockRaidText
7556end
7557
7558local function loadOptions()
7559 options = {
7560 type = "group",
7561 name = "Shadowed UF",
7562 args = {}
7563 }
7564
7565 loadGeneralOptions()
7566 loadUnitOptions()
7567 loadHideOptions()
7568 loadTagOptions()
7569 loadFilterOptions()
7570 loadVisibilityOptions()
7571 loadAuraIndicatorsOptions()
7572
7573 -- Ordering
7574 options.args.general.order = 1
7575 options.args.profile.order = 1.5
7576 options.args.enableUnits.order = 2
7577 options.args.units.order = 3
7578 options.args.filter.order = 4
7579 options.args.auraIndicators.order = 4.5
7580 options.args.hideBlizzard.order = 5
7581 options.args.visibility.order = 6
7582 options.args.tags.order = 7
7583
7584 -- So modules can access it easier/debug
7585 Config.options = options
7586
7587 -- Options finished loading, fire callback for any non-default modules that want to be included
7588 ShadowUF:FireModuleEvent("OnConfigurationLoad")
7589end
7590
7591local defaultToggles
7592function Config:Open()
7593 AceDialog = AceDialog or LibStub("AceConfigDialog-3.0")
7594 AceRegistry = AceRegistry or LibStub("AceConfigRegistry-3.0")
7595
7596 if( not registered ) then
7597 loadOptions()
7598
7599 AceRegistry:RegisterOptionsTable("ShadowedUF", options, true)
7600 AceDialog:SetDefaultSize("ShadowedUF", 895, 570)
7601 registered = true
7602 end
7603
7604 AceDialog:Open("ShadowedUF")
7605
7606 if( not defaultToggles ) then
7607 defaultToggles = true
7608
7609 AceDialog.Status.ShadowedUF.status.groups.groups.units = true
7610 AceRegistry:NotifyChange("ShadowedUF")
7611 end
7612end