diff --git a/.gitignore b/.gitignore
new file mode 100755
index 000000000..ee749279b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+suf.tmproj
+.DS_Store
+mynotes.txt
\ No newline at end of file
diff --git a/.pkgmeta b/.pkgmeta
old mode 100644
new mode 100755
index 542192a1f..ae9b73dad
--- a/.pkgmeta
+++ b/.pkgmeta
@@ -1,33 +1,31 @@
package-as: ShadowedUnitFrames
move-folders:
- ShadowedUnitFrames/options: ShadowedUF_Options
+ ShadowedUnitFrames/options: ShadowedUF_Options
externals:
libs/LibStub:
- url: svn://svn.wowace.com/wow/libstub/mainline/trunk
+ url: https://repos.wowace.com/wow/libstub/trunk
tag: latest
libs/CallbackHandler-1.0:
- url: svn://svn.wowace.com/wow/callbackhandler/mainline/trunk
+ url: https://repos.wowace.com/wow/callbackhandler/trunk
tag: latest
libs/AceDB-3.0:
- url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0
+ url: https://repos.wowace.com/wow/ace3/trunk/AceDB-3.0
libs/LibSharedMedia-3.0:
- url: svn://svn.wowace.com/wow/libsharedmedia-3-0/mainline/trunk
- tag: latest
- libs/LibHealComm-4.0:
- url: git://git.wowace.com/wow/libhealcomm-4-0/mainline.git
- tag: latest
+ url: https://repos.wowace.com/wow/libsharedmedia-3-0/trunk/LibSharedMedia-3.0
+ libs/LibDualSpec-1.0:
+ url: https://repos.wowace.com/wow/libdualspec-1-0
+ libs/LibSpellRange-1.0:
+ url: git://github.com/ascott18/LibSpellRange-1.0.git
options/libs/AceConfig-3.0:
- url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConfig-3.0
+ url: https://repos.wowace.com/wow/ace3/trunk/AceConfig-3.0
options/libs/AceDBOptions-3.0:
- url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDBOptions-3.0
+ url: https://repos.wowace.com/wow/ace3/trunk/AceDBOptions-3.0
options/libs/AceGUI-3.0:
- url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceGUI-3.0
+ url: https://repos.wowace.com/wow/ace3/trunk/AceGUI-3.0
options/libs/AceGUI-3.0-SharedMediaWidgets:
- url: svn://svn.wowace.com/wow/ace-gui-3-0-shared-media-widgets/mainline/trunk
- tag: latest
-ignore:
- - globalcheck.lua
- - localcheck.lua
+ url: https://repos.wowace.com/wow/ace-gui-3-0-shared-media-widgets/trunk/AceGUI-3.0-SharedMediaWidgets
+ignore:
+ - locale-import.lua
diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua
old mode 100644
new mode 100755
index d0db7dc1b..32881c6e5
--- a/ShadowedUnitFrames.lua
+++ b/ShadowedUnitFrames.lua
@@ -1,28 +1,30 @@
--[[
- Shadowed Unit Frames, Shadow of Mal'Ganis (US) PvP
+ Shadowed Unit Frames, Shadowed of Mal'Ganis (US) PvP
]]
ShadowUF = select(2, ...)
+
local L = ShadowUF.L
-ShadowUF.dbRevision = 1
+ShadowUF.dbRevision = 59
ShadowUF.playerUnit = "player"
ShadowUF.enabledUnits = {}
ShadowUF.modules = {}
ShadowUF.moduleOrder = {}
-ShadowUF.unitList = {"player", "pet", "pettarget", "target", "targettarget", "targettargettarget", "focus", "focustarget", "party", "partypet", "partytarget", "raid", "raidpet", "boss", "bosstarget", "maintank", "maintanktarget", "mainassist", "mainassisttarget", "arena", "arenatarget", "arenapet"}
-ShadowUF.fakeUnits = {["targettarget"] = true, ["targettargettarget"] = true, ["pettarget"] = true, ["arenatarget"] = true, ["focustarget"] = true, ["focustargettarget"] = true, ["partytarget"] = true, ["raidtarget"] = true, ["bosstarget"] = true, ["maintanktarget"] = true, ["mainassisttarget"] = true}
-L.units = {["raidpet"] = L["Raid pet"], ["PET"] = L["Pet"], ["VEHICLE"] = L["Vehicle"], ["arena"] = L["Arena"], ["arenapet"] = L["Arena Pet"], ["arenatarget"] = L["Arena Target"], ["boss"] = L["Boss"], ["bosstarget"] = L["Boss Target"], ["focus"] = L["Focus"], ["focustarget"] = L["Focus Target"], ["mainassist"] = L["Main Assist"], ["mainassisttarget"] = L["Main Assist Target"], ["maintank"] = L["Main Tank"], ["maintanktarget"] = L["Main Tank Target"], ["party"] = L["Party"], ["partypet"] = L["Party Pet"], ["partytarget"] = L["Party Target"], ["pet"] = L["Pet"], ["pettarget"] = L["Pet Target"], ["player"] = L["Player"],["raid"] = L["Raid"], ["target"] = L["Target"], ["targettarget"] = L["Target of Target"], ["targettargettarget"] = L["Target of Target of Target"]}
-
+ShadowUF.unitList = {"player", "pet", "pettarget", "target", "targettarget", "targettargettarget", "focus", "focustarget", "party", "partypet", "partytarget", "partytargettarget", "raid", "raidpet", "boss", "bosstarget", "maintank", "maintanktarget", "mainassist", "mainassisttarget", "arena", "arenatarget", "arenapet", "battleground", "battlegroundtarget", "battlegroundpet", "arenatargettarget", "battlegroundtargettarget", "maintanktargettarget", "mainassisttargettarget", "bosstargettarget"}
+ShadowUF.fakeUnits = {["targettarget"] = true, ["targettargettarget"] = true, ["pettarget"] = true, ["arenatarget"] = true, ["arenatargettarget"] = true, ["focustarget"] = true, ["focustargettarget"] = true, ["partytarget"] = true, ["raidtarget"] = true, ["bosstarget"] = true, ["maintanktarget"] = true, ["mainassisttarget"] = true, ["battlegroundtarget"] = true, ["partytargettarget"] = true, ["battlegroundtargettarget"] = true, ["maintanktargettarget"] = true, ["mainassisttargettarget"] = true, ["bosstargettarget"] = true}
+L.units = {["raidpet"] = L["Raid pet"], ["PET"] = L["Pet"], ["VEHICLE"] = L["Vehicle"], ["arena"] = L["Arena"], ["arenapet"] = L["Arena Pet"], ["arenatarget"] = L["Arena Target"], ["arenatargettarget"] = L["Arena Target of Target"], ["boss"] = L["Boss"], ["bosstarget"] = L["Boss Target"], ["focus"] = L["Focus"], ["focustarget"] = L["Focus Target"], ["mainassist"] = L["Main Assist"], ["mainassisttarget"] = L["Main Assist Target"], ["maintank"] = L["Main Tank"], ["maintanktarget"] = L["Main Tank Target"], ["party"] = L["Party"], ["partypet"] = L["Party Pet"], ["partytarget"] = L["Party Target"], ["pet"] = L["Pet"], ["pettarget"] = L["Pet Target"], ["player"] = L["Player"],["raid"] = L["Raid"], ["target"] = L["Target"], ["targettarget"] = L["Target of Target"], ["targettargettarget"] = L["Target of Target of Target"], ["battleground"] = L["Battleground"], ["battlegroundpet"] = L["Battleground Pet"], ["battlegroundtarget"] = L["Battleground Target"], ["partytargettarget"] = L["Party Target of Target"], ["battlegroundtargettarget"] = L["Battleground Target of Target"], ["maintanktargettarget"] = L["Main Tank Target of Target"], ["mainassisttargettarget"] = L["Main Assist Target of Target"], ["bosstargettarget"] = L["Boss Target of Target"]}
+L.shortUnits = {["battleground"] = L["BG"], ["battlegroundtarget"] = L["BG Target"], ["battlegroundpet"] = L["BG Pet"], ["battlegroundtargettarget"] = L["BG ToT"], ["arenatargettarget"] = L["Arena ToT"], ["partytargettarget"] = L["Party ToT"], ["bosstargettarget"] = L["Boss ToT"], ["maintanktargettarget"] = L["MT ToT"], ["mainassisttargettarget"] = L["MA ToT"]}
-- Cache the units so we don't have to concat every time it updates
ShadowUF.unitTarget = setmetatable({}, {__index = function(tbl, unit) rawset(tbl, unit, unit .. "target"); return unit .. "target" end})
-ShadowUF.partyUnits, ShadowUF.raidUnits, ShadowUF.raidPetUnits, ShadowUF.bossUnits, ShadowUF.arenaUnits = {}, {}, {}, {}, {}
+ShadowUF.partyUnits, ShadowUF.raidUnits, ShadowUF.raidPetUnits, ShadowUF.bossUnits, ShadowUF.arenaUnits, ShadowUF.battlegroundUnits = {}, {}, {}, {}, {}, {}
ShadowUF.maintankUnits, ShadowUF.mainassistUnits, ShadowUF.raidpetUnits = ShadowUF.raidUnits, ShadowUF.raidUnits, ShadowUF.raidPetUnits
for i=1, MAX_PARTY_MEMBERS do ShadowUF.partyUnits[i] = "party" .. i end
for i=1, MAX_RAID_MEMBERS do ShadowUF.raidUnits[i] = "raid" .. i end
for i=1, MAX_RAID_MEMBERS do ShadowUF.raidPetUnits[i] = "raidpet" .. i end
for i=1, MAX_BOSS_FRAMES do ShadowUF.bossUnits[i] = "boss" .. i end
for i=1, 5 do ShadowUF.arenaUnits[i] = "arena" .. i end
+for i=1, 4 do ShadowUF.battlegroundUnits[i] = "arena" .. i end
function ShadowUF:OnInitialize()
self.defaults = {
@@ -31,24 +33,25 @@ function ShadowUF:OnInitialize()
advanced = false,
tooltipCombat = false,
omnicc = false,
+ blizzardcc = true,
tags = {},
units = {},
positions = {},
range = {},
- filters = {zonewhite = {}, zoneblack = {}, whitelists = {}, blacklists = {}},
+ filters = {zonewhite = {}, zoneblack = {}, zoneoverride = {}, whitelists = {}, blacklists = {}, overridelists = {}},
visibility = {arena = {}, pvp = {}, party = {}, raid = {}},
- hidden = {cast = false, runes = true, buffs = true, party = true, player = true, pet = true, target = true, focus = true, boss = true, arena = true},
+ hidden = {cast = false, playerPower = true, buffs = false, party = true, raid = false, player = true, pet = true, target = true, focus = true, boss = true, arena = true, playerAltPower = false},
},
}
self:LoadUnitDefaults()
-
+
-- Initialize DB
self.db = LibStub:GetLibrary("AceDB-3.0"):New("ShadowedUFDB", self.defaults, true)
self.db.RegisterCallback(self, "OnProfileChanged", "ProfilesChanged")
self.db.RegisterCallback(self, "OnProfileCopied", "ProfilesChanged")
self.db.RegisterCallback(self, "OnProfileReset", "ProfileReset")
-
+
-- Setup tag cache
self.tagFunc = setmetatable({}, {
__index = function(tbl, index)
@@ -72,93 +75,169 @@ function ShadowUF:OnInitialize()
self:LoadDefaultLayout()
else
self:CheckUpgrade()
+ self:CheckBuild()
+ self:ShowInfoPanel()
end
-
+
self.db.profile.revision = self.dbRevision
self:FireModuleEvent("OnInitialize")
self:HideBlizzardFrames()
self.Layout:LoadSML()
self:LoadUnits()
self.modules.movers:Update()
+
+ local LibDualSpec = LibStub("LibDualSpec-1.0", true)
+ if LibDualSpec then LibDualSpec:EnhanceDatabase(self.db, "ShadowedUnitFrames") end
+end
+
+function ShadowUF.UnitAuraBySpell(unit, spell, filter)
+ local index = 0
+ while true do
+ index = index + 1
+ local name, _, _, _, _, _, _, _, _, spellID = UnitAura(unit, index, filter)
+ if not name then break end
+ if (type(spell) == "string" and spell == name) or (type(spell) == "number" and spell == spellID) then
+ return UnitAura(unit, index, filter)
+ end
+ end
+end
+
+function ShadowUF:CheckBuild()
+ local build = select(4, GetBuildInfo())
+ if( self.db.profile.wowBuild == build ) then return end
+
+ -- Nothing to add here right now
+ self.db.profile.wowBuild = build
end
function ShadowUF:CheckUpgrade()
- -- June 19th
- if( not ShadowUF.db.profile.font.color ) then
- ShadowUF.db.profile.font.color = {r = 1, g = 1, b = 1, a = 1}
+ local revision = self.db.profile.revision or self.dbRevision
+ if( revision <= 58 ) then
for unit, config in pairs(self.db.profile.units) do
- local indicators = ShadowUF.db.profile.units[unit].indicators
- if( indicators and indicators.class ) then
- indicators.class.anchorTo = "$parent"
- indicators.class.anchorPoint = "BL"
- indicators.class.x = 0
- indicators.class.y = 0
+ if config.text then
+ local i = 1
+ while i <= #config.text do
+ local text
+ if rawget(config.text, i) or i <= #(self.defaults.profile.units[unit].text) then
+ text = config.text[i]
+ end
+
+ if not text then
+ table.remove(config.text, i)
+ elseif text.anchorTo == "$demonicFuryBar" or text.anchorTo == "$eclipseBar" or text.anchorTo == "$burningEmbersBar" or text.anchorTo == "$monkBar" then
+ table.remove(config.text, i)
+ elseif i > 6 and text.default and text.anchorTo == "$emptyBar" then
+ table.remove(config.text, i)
+ else
+ if text.anchorTo == "$emptyBar" and text.name == L["Left text"] then
+ text.width = 0.50
+ end
+
+ i = i + 1
+ end
+ end
+
+ if not config.text[6] or config.text[6].anchorTo ~= "$emptyBar" then
+ table.insert(config.text, 6, {enabled = true, width = 0.60, name = L["Right text"], text = "", anchorTo = "$emptyBar", anchorPoint = "CRI", size = 0, x = -3, y = 0, default = true})
+ else
+ config.text[6].width = 0.60
+ config.text[6].name = L["Right text"]
+ config.text[6].anchorPoint = "CRI"
+ config.text[6].size = 0
+ config.text[6].x = -3
+ config.text[6].y = 0
+ config.text[6].default = true
+ end
end
end
end
-
- -- April 29th
- if( self.db.profile.filters.zones ) then
- for unit, filter in pairs(self.db.profile.filters.zones) do
- if( self.db.profile.filters.whitelists[filter] ) then
- self.db.profile.filters.zonewhite[unit] = filter
- else
- self.db.profile.filters.zoneblack[unit] = filter
- end
- end
+
+ if( revision <= 56 ) then
+ -- new classes
+ self.db.profile.classColors.DEMONHUNTER = {r = 0.64, g = 0.19, b = 0.79}
+
+ -- new power types
+ self.db.profile.powerColors.INSANITY = {r = 0.40, g = 0, b = 0.80}
+ self.db.profile.powerColors.MAELSTROM = {r = 0.00, g = 0.50, b = 1.00}
+ self.db.profile.powerColors.FURY = {r = 0.788, g = 0.259, b = 0.992}
+ self.db.profile.powerColors.PAIN = {r = 1, g = 0, b = 0}
+ self.db.profile.powerColors.LUNAR_POWER = {r = 0.30, g = 0.52, b = 0.90}
+ self.db.profile.powerColors.ARCANECHARGES = {r = 0.1, g = 0.1, b = 0.98}
+
+ -- new bars
+ local config = self.db.profile.units
+ config.player.priestBar = {enabled = true, background = true, height = 0.40, order = 70}
+ config.player.shamanBar = {enabled = true, background = true, height = 0.40, order = 70}
+ config.player.arcaneCharges = {enabled = true, anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -8, y = 6, size = 12, spacing = -2, growth = "LEFT", isBar = true, showAlways = true}
+
+ -- clean out old bars
+ config.player.demonicFuryBar = nil
+ config.player.burningEmbersBar = nil
+ config.player.shadowOrbs = nil
+ config.player.eclipseBar = nil
+ config.player.monkBar = nil
end
-
- -- February 16th
- if( not self.db.profile.units.raidpet.enabled and self.db.profile.units.raidpet.height == 0 and self.db.profile.units.raidpet.width == 0 and self.db.profile.positions.raidpet.anchorPoint == "" and self.db.profile.positions.raidpet.point == "" ) then
- self:LoadDefaultLayout(true)
+
+ if( revision <= 49 ) then
+ ShadowUF:LoadDefaultLayout(true)
end
-
- self.db.profile.units.party.unitsPerColumn = self.db.profile.units.party.unitsPerColumn or 5
- self.db.profile.units.raid.groupsPerRow = self.db.profile.units.raid.groupsPerRow or 8
-
- local castName = {enabled = true, size = 0, anchorTo = "$parent", rank = true, anchorPoint = "CLI", x = 1, y = 0}
- local castTime = {enabled = true, size = 0, anchorTo = "$parent", anchorPoint = "CRI", x = -1, y = 0}
-
- for unit, config in pairs(self.db.profile.units) do
- config.portrait = config.portrait or {}
- config.portrait.type = config.portrait.type or "3D"
- config.portrait.fullBefore = config.portrait.fullBefore or 0
- config.portrait.fullAfter = config.portrait.fullAfter or 100
- config.portrait.order = config.portrait.order or 40
- config.portrait.height = config.portrait.height or 0.50
-
- config.highlight.size = config.highlight.size or 10
-
- config.castBar = config.castBar or {}
- config.castBar.icon = config.castBar.icon or "HIDE"
- config.castBar.height = config.castBar.height or 0.60
- config.castBar.order = config.castBar.order or 40
-
- config.castBar.name = config.castBar.name or {}
- config.castBar.time = config.castBar.time or {}
-
- for key, value in pairs(castName) do
- if( config.castBar.name[key] == nil ) then
- config.castBar.name[key] = value
- end
+
+ if( revision <= 49 ) then
+ if( ShadowUF.db.profile.font.extra == "MONOCHROME" ) then
+ ShadowUF.db.profile.font.extra = ""
end
-
- for key, value in pairs(castTime) do
- if( config.castBar.time[key] == nil ) then
- config.castBar.time[key] = value
+ end
+
+ if( revision <= 47 ) then
+ local config = self.db.profile.units
+ config.player.comboPoints = config.target.comboPoints
+ end
+
+ if( revision <= 46 ) then
+ local config = self.db.profile.units.arena
+ config.indicators.arenaSpec = {enabled = true, anchorPoint = "LC", size = 28, x = 0, y = 0, anchorTo = "$parent"}
+ config.indicators.lfdRole = {enabled = true, anchorPoint = "BR", size = 14, x = 3, y = 14, anchorTo = "$parent"}
+ end
+
+ if( revision <= 45 ) then
+ for unit, config in pairs(self.db.profile.units) do
+ if( config.auras ) then
+ for _, key in pairs({"buffs", "debuffs"}) do
+ local aura = config.auras[key]
+ aura.show = aura.show or {}
+ aura.show.player = true
+ aura.show.boss = true
+ aura.show.raid = true
+ aura.show.misc = true
+ end
end
end
end
end
-
+
+local function zoneEnabled(zone, zoneList)
+ if( type(zoneList) == "string" ) then
+ return zone == zoneList
+ end
+
+ for id, row in pairs(zoneList) do
+ if( zone == row ) then return true end
+ end
+
+ return false
+end
+
function ShadowUF:LoadUnits()
-- CanHearthAndResurrectFromArea() returns true for world pvp areas, according to BattlefieldFrame.lua
local instanceType = CanHearthAndResurrectFromArea() and "pvp" or select(2, IsInInstance())
+ if( instanceType == "scenario" ) then instanceType = "party" end
+
+ if( not instanceType ) then instanceType = "none" end
for _, type in pairs(self.unitList) do
local enabled = self.db.profile.units[type].enabled
- if( ShadowUF.Units.zoneUnits[type] and enabled ) then
- enabled = ShadowUF.Units.zoneUnits[type] == instanceType
+ if( ShadowUF.Units.zoneUnits[type] ) then
+ enabled = enabled and zoneEnabled(instanceType, ShadowUF.Units.zoneUnits[type])
elseif( instanceType ~= "none" ) then
if( self.db.profile.visibility[instanceType][type] == false ) then
enabled = false
@@ -191,25 +270,30 @@ function ShadowUF:LoadUnitDefaults()
portrait = {enabled = false},
castBar = {enabled = false, name = {}, time = {}},
text = {
- {enabled = true, name = L["Left text"], text = "[name]", anchorPoint = "C", anchorTo = "$healthBar", size = 0},
- {enabled = true, name = L["Right text"], text = "[curmaxhp]", anchorPoint = "C", anchorTo = "$healthBar", size = 0},
- {enabled = true, name = L["Left text"], text = "[level] [race]", anchorPoint = "C", anchorTo = "$powerBar", size = 0},
- {enabled = true, name = L["Right text"], text = "[curmaxpp]", anchorPoint = "C", anchorTo = "$powerBar", size = 0},
- {enabled = true, name = L["Text"], text = "", anchorTo = "$emptyBar", anchorPoint = "C", size = 0, x = 0, y = 0},
+ {enabled = true, name = L["Left text"], text = "[name]", anchorPoint = "CLI", anchorTo = "$healthBar", width = 0.50, size = 0, x = 3, y = 0, default = true},
+ {enabled = true, name = L["Right text"], text = "[curmaxhp]", anchorPoint = "CRI", anchorTo = "$healthBar", width = 0.60, size = 0, x = -3, y = 0, default = true},
+ {enabled = true, name = L["Left text"], text = "[level] [race]", anchorPoint = "CLI", anchorTo = "$powerBar", width = 0.50, size = 0, x = 3, y = 0, default = true},
+ {enabled = true, name = L["Right text"], text = "[curmaxpp]", anchorPoint = "CRI", anchorTo = "$powerBar", width = 0.60, size = 0, x = -3, y = 0, default = true},
+ {enabled = true, name = L["Left text"], text = "", anchorTo = "$emptyBar", anchorPoint = "CLI", width = 0.50, size = 0, x = 3, y = 0, default = true},
+ {enabled = true, name = L["Right text"], text = "", anchorTo = "$emptyBar", anchorPoint = "CRI", width = 0.60, size = 0, x = -3, y = 0, default = true},
+ ['*'] = {enabled = true, text = "", anchorTo = "", anchorPoint = "C", size = 0, x = 0, y = 0},
},
indicators = {raidTarget = {enabled = true, size = 0}},
highlight = {},
+ auraIndicators = {enabled = false},
auras = {
- buffs = {enabled = false, perRow = 10, maxRows = 4, selfScale = 1.30, prioritize = true, enlargeSelf = false},
- debuffs = {enabled = false, perRow = 10, maxRows = 4, selfScale = 1.30, enlargeSelf = true},
+ buffs = {enabled = false, perRow = 10, maxRows = 4, selfScale = 1.30, prioritize = true, show = {player = true, boss = true, raid = true, misc = true}, enlarge = {}, timers = {ALL = true}},
+ debuffs = {enabled = false, perRow = 10, maxRows = 4, selfScale = 1.30, show = {player = true, boss = true, raid = true, misc = true}, enlarge = {SELF = true}, timers = {ALL = true}},
},
}
if( not self.fakeUnits[unit] ) then
self.defaults.profile.units[unit].combatText = {enabled = true, anchorTo = "$parent", anchorPoint = "C", x = 0, y = 0}
- if( unit ~= "arena" and unit ~= "arenapet" ) then
- self.defaults.profile.units[unit].incHeal = {enabled = false, cap = 1.30}
+ if( unit ~= "battleground" and unit ~= "battlegroundpet" and unit ~= "arena" and unit ~= "arenapet" and unit ~= "boss" ) then
+ self.defaults.profile.units[unit].incHeal = {enabled = true, cap = 1.20}
+ self.defaults.profile.units[unit].incAbsorb = {enabled = true, cap = 1.30}
+ self.defaults.profile.units[unit].healAbsorb = {enabled = true, cap = 1.30}
end
end
@@ -220,21 +304,27 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units[unit].indicators.class = {enabled = false, size = 19}
end
end
-
- -- Want pvp/leader/ML enabled for these units
- if( unit == "player" or unit == "party" or unit == "target" or unit == "raid" or unit == "focus" ) then
+
+ if( unit == "player" or unit == "party" or unit == "target" or unit == "raid" or unit == "focus" or unit == "mainassist" or unit == "maintank" ) then
self.defaults.profile.units[unit].indicators.leader = {enabled = true, size = 0}
self.defaults.profile.units[unit].indicators.masterLoot = {enabled = true, size = 0}
self.defaults.profile.units[unit].indicators.pvp = {enabled = true, size = 0}
self.defaults.profile.units[unit].indicators.role = {enabled = true, size = 0}
self.defaults.profile.units[unit].indicators.status = {enabled = false, size = 19}
-
+ self.defaults.profile.units[unit].indicators.resurrect = {enabled = true}
+
if( unit ~= "focus" and unit ~= "target" ) then
self.defaults.profile.units[unit].indicators.ready = {enabled = true, size = 0}
end
end
+
+ if( unit == "battleground" ) then
+ self.defaults.profile.units[unit].indicators.pvp = {enabled = true, size = 0}
+ end
+
+ self.defaults.profile.units[unit].altPowerBar = {enabled = not ShadowUF.fakeUnits[unit]}
end
-
+
-- PLAYER
self.defaults.profile.units.player.enabled = true
self.defaults.profile.units.player.healthBar.predicted = true
@@ -243,25 +333,39 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.player.runeBar = {enabled = false}
self.defaults.profile.units.player.totemBar = {enabled = false}
self.defaults.profile.units.player.druidBar = {enabled = false}
+ self.defaults.profile.units.player.priestBar = {enabled = true}
+ self.defaults.profile.units.player.shamanBar = {enabled = true}
self.defaults.profile.units.player.xpBar = {enabled = false}
- self.defaults.profile.units.player.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
+ self.defaults.profile.units.player.fader = {enabled = false}
+ self.defaults.profile.units.player.soulShards = {enabled = true, isBar = true}
+ self.defaults.profile.units.player.arcaneCharges = {enabled = true, isBar = true}
+ self.defaults.profile.units.player.staggerBar = {enabled = true}
+ self.defaults.profile.units.player.comboPoints = {enabled = true, isBar = true}
+ self.defaults.profile.units.player.holyPower = {enabled = true, isBar = true}
+ self.defaults.profile.units.player.chi = {enabled = true, isBar = true}
self.defaults.profile.units.player.indicators.lfdRole = {enabled = true, size = 0, x = 0, y = 0}
- -- PET
+ self.defaults.profile.units.player.auraPoints = {enabled = false, isBar = true}
+ table.insert(self.defaults.profile.units.player.text, {enabled = true, text = "", anchorTo = "", anchorPoint = "C", size = 0, x = 0, y = 0, default = true})
+ table.insert(self.defaults.profile.units.player.text, {enabled = true, text = "", anchorTo = "", anchorPoint = "C", size = 0, x = 0, y = 0, default = true})
+ table.insert(self.defaults.profile.units.player.text, {enabled = true, text = "", anchorTo = "", anchorPoint = "C", size = 0, x = 0, y = 0, default = true})
+
+ -- PET
self.defaults.profile.units.pet.enabled = true
- self.defaults.profile.units.pet.indicators.happiness = {enabled = true, size = 16, anchorPoint = "BR", anchorTo = "$parent", x = 2, y = -2}
self.defaults.profile.units.pet.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.pet.xpBar = {enabled = false}
- -- FOCUS
+ -- FOCUS
self.defaults.profile.units.focus.enabled = true
self.defaults.profile.units.focus.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.focus.indicators.lfdRole = {enabled = false, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.focus.indicators.questBoss = {enabled = true, size = 0, x = 0, y = 0}
-- FOCUSTARGET
self.defaults.profile.units.focustarget.enabled = true
self.defaults.profile.units.focustarget.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
-- TARGET
self.defaults.profile.units.target.enabled = true
- self.defaults.profile.units.target.comboPoints = {enabled = true, isBar = false, height = 0.40, order = 30, anchorTo = "$parent", anchorPoint = "BR", x = 0, y = 0}
self.defaults.profile.units.target.indicators.lfdRole = {enabled = false, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.target.indicators.questBoss = {enabled = true, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.target.comboPoints = {enabled = false, isBar = true}
-- TARGETTARGET/TARGETTARGETTARGET
self.defaults.profile.units.targettarget.enabled = true
self.defaults.profile.units.targettargettarget.enabled = true
@@ -272,6 +376,7 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.party.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.party.combatText.enabled = false
self.defaults.profile.units.party.indicators.lfdRole = {enabled = true, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.party.indicators.phase = {enabled = true, size = 0, x = 0, y = 0}
-- ARENA
self.defaults.profile.units.arena.enabled = false
self.defaults.profile.units.arena.attribPoint = "TOP"
@@ -279,6 +384,15 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.arena.auras.debuffs.maxRows = 1
self.defaults.profile.units.arena.auras.buffs.maxRows = 1
self.defaults.profile.units.arena.offset = 0
+ self.defaults.profile.units.arena.indicators.arenaSpec = {enabled = true, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.arena.indicators.lfdRole = {enabled = true, size = 0, x = 0, y = 0}
+ -- BATTLEGROUND
+ self.defaults.profile.units.battleground.enabled = false
+ self.defaults.profile.units.battleground.attribPoint = "TOP"
+ self.defaults.profile.units.battleground.attribAnchorPoint = "LEFT"
+ self.defaults.profile.units.battleground.auras.debuffs.maxRows = 1
+ self.defaults.profile.units.battleground.auras.buffs.maxRows = 1
+ self.defaults.profile.units.battleground.offset = 0
-- BOSS
self.defaults.profile.units.boss.enabled = false
self.defaults.profile.units.boss.attribPoint = "TOP"
@@ -286,6 +400,7 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.boss.auras.debuffs.maxRows = 1
self.defaults.profile.units.boss.auras.buffs.maxRows = 1
self.defaults.profile.units.boss.offset = 0
+ self.defaults.profile.units.boss.altPowerBar.enabled = true
-- RAID
self.defaults.profile.units.raid.groupBy = "GROUP"
self.defaults.profile.units.raid.sortOrder = "ASC"
@@ -296,6 +411,7 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.raid.filters = {[1] = true, [2] = true, [3] = true, [4] = true, [5] = true, [6] = true, [7] = true, [8] = true}
self.defaults.profile.units.raid.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.raid.combatText.enabled = false
+ self.defaults.profile.units.raid.indicators.lfdRole = {enabled = true, size = 0, x = 0, y = 0}
-- RAID PET
self.defaults.profile.units.raidpet.groupBy = "GROUP"
self.defaults.profile.units.raidpet.sortOrder = "ASC"
@@ -307,6 +423,7 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.raidpet.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.raidpet.combatText.enabled = false
-- MAINTANK
+ self.defaults.profile.units.maintank.roleFilter = "TANK"
self.defaults.profile.units.maintank.groupFilter = "MAINTANK"
self.defaults.profile.units.maintank.groupBy = "GROUP"
self.defaults.profile.units.maintank.sortOrder = "ASC"
@@ -332,13 +449,116 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.positions.partytarget.anchorTo = "$parent"
self.defaults.profile.positions.partytarget.anchorPoint = "RT"
self.defaults.profile.units.partytarget.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
+ -- PARTYTARGETTARGET
+ self.defaults.profile.positions.partytarget.anchorTo = "$parent"
+ self.defaults.profile.positions.partytarget.anchorPoint = "RT"
+ self.defaults.profile.units.partytarget.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
+
+ -- Aura indicators
+ self.defaults.profile.auraIndicators = {
+ disabled = {},
+ missing = {},
+ linked = {},
+ indicators = {
+ ["tl"] = {name = L["Top Left"], anchorPoint = "TLI", anchorTo = "$parent", height = 8, width = 8, alpha = 1.0, x = 4, y = -4, friendly = true, hostile = true},
+ ["tr"] = {name = L["Top Right"], anchorPoint = "TRI", anchorTo = "$parent", height = 8, width = 8, alpha = 1.0, x = -3, y = -3, friendly = true, hostile = true},
+ ["bl"] = {name = L["Bottom Left"], anchorPoint = "BLI", anchorTo = "$parent", height = 8, width = 8, alpha = 1.0, x = 4, y = 4, friendly = true, hostile = true},
+ ["br"] = {name = L["Bottom Right"], anchorPoint = "BRI", anchorTo = "$parent", height = 8, width = 8, alpha = 1.0, x = -4, y = -4, friendly = true, hostile = true},
+ ["c"] = {name = L["Center"], anchorPoint = "C", anchorTo = "$parent", height = 20, width = 20, alpha = 1.0, x = 0, y = 0, friendly = true, hostile = true},
+ },
+ filters = {
+ ["tl"] = {boss = {priority = 100}, curable = {priority = 100}},
+ ["tr"] = {boss = {priority = 100}, curable = {priority = 100}},
+ ["bl"] = {boss = {priority = 100}, curable = {priority = 100}},
+ ["br"] = {boss = {priority = 100}, curable = {priority = 100}},
+ ["c"] = {boss = {priority = 100}, curable = {priority = 100}},
+ },
+ auras = {
+ ["20707"] = [[{indicator = '', group = "Warlock", priority = 10, r = 0.42, g = 0.21, b = 0.65}]],
+ ["116849"] = [[{r=0.19607843137255, group="Monk", indicator="c", g=1, player=false, duration=true, b=0.3843137254902, alpha=1, priority=0, icon=true, iconTexture="Interface\\Icons\\ability_monk_chicocoon"}]],
+ ["155777"] = [[{r=0.57647058823529, group="Druid", indicator="tr", g=0.28235294117647, player=true, duration=true, b=0.6156862745098, priority=100, alpha=1, iconTexture="Interface\\Icons\\Spell_Nature_Rejuvenation"}]],
+ ["121176"] = [[{alpha=1, b=0, priority=0, r=0.062745098039216, group="PvP Flags", indicator="bl", g=1, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["19705"] = [[{r=0.80392156862745, group="Food", indicator="", g=0.76470588235294, missing=true, duration=true, priority=0, alpha=1, b=0.24313725490196}]],
+ ["53563"] = [[{r=0.64313725490196, group="Paladin", indicator="tr", g=0.24705882352941, player=true, alpha=1, b=0.73333333333333, priority=100, duration=false, iconTexture="Interface\\Icons\\Ability_Paladin_BeaconofLight"}]],
+ ["774"] = [[{r=0.57647058823529, group="Druid", indicator="tr", g=0.28235294117647, player=true, duration=true, b=0.6156862745098, priority=100, alpha=1, iconTexture="Interface\\Icons\\Spell_Nature_Rejuvenation"}]],
+ ["33206"] = [[{r=0, group="Priest", indicator="c", g=0, b=0, duration=true, priority=0, icon=true, iconTexture="Interface\\Icons\\Spell_Holy_PainSupression"}]],
+ ["6788"] = [[{b=0.29019607843137, group="Priest", indicator="tl", alpha=1, player=false, g=0.56862745098039, duration=true, r=0.83921568627451, priority=20, icon=false, iconTexture="Interface\\Icons\\Spell_Holy_AshesToAshes"}]],
+ ["33763"] = [[{r=0.23137254901961, group="Druid", indicator="tl", g=1, player=true, duration=true, alpha=1, priority=0, b=0.2, iconTexture="Interface\\Icons\\INV_Misc_Herb_Felblossom"}]],
+ ["139"] = [[{r=0.23921568627451, group="Priest", indicator="tr", g=1, player=true, alpha=1, duration=true, b=0.39607843137255, priority=10, icon=false, iconTexture="Interface\\Icons\\Spell_Holy_Renew"}]],
+ ["41635"] = [[{r=1, group="Priest", indicator="br", g=0.90196078431373, missing=false, player=true, duration=false, alpha=1, b=0, priority=50, icon=false, iconTexture="Interface\\Icons\\Spell_Holy_PrayerOfMendingtga"}]],
+ ["47788"] = [[{r=0, group="Priest", indicator="c", g=0, b=0, duration=true, priority=0, icon=true, iconTexture="Interface\\Icons\\Spell_Holy_GuardianSpirit"}]],
+ ["61295"] = [[{r=0.17647058823529, group="Shaman", indicator="tl", g=0.4, player=true, alpha=1, duration=true, b=1, priority=0, icon=false, iconTexture="Interface\\Icons\\spell_nature_riptide"}]],
+ ["17"] = [[{r=1, group="Priest", indicator="tl", g=0.41960784313725, player=true, alpha=1, duration=true, b=0.5843137254902, priority=0, icon=false, iconTexture="Interface\\Icons\\Spell_Holy_PowerWordShield"}]],
+ ["152118"] = [[{r=1, group="Priest", indicator="tl", g=0.41960784313725, player=true, alpha=1, duration=true, b=0.5843137254902, priority=0, icon=false, iconTexture="Interface\\Icons\\Ability_Priest_ClarityOfWill"}]],
+ ["23335"] = [[{r=0, group="PvP Flags", indicator="bl", g=0, duration=false, b=0, priority=0, icon=true, iconTexture="Interface\\Icons\\INV_BannerPVP_02"}]],
+ ["102342"] = [[{r=0, group="Druid", indicator="c", g=0, duration=true, b=0, priority=0, icon=true, iconTexture="Interface\\Icons\\spell_druid_ironbark"}]],
+ ["121177"] = [[{r=0.78039215686275, group="PvP Flags", indicator="bl", g=0.42352941176471, alpha=1, b=0, priority=0, icon=false, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["586"] = [[{r=0, group="Priest", indicator="", g=0.85882352941176, selfColor={alpha=1, b=1, g=0.93725490196078, r=0, }, alpha=1, priority=0, b=1, iconTexture="Interface\\Icons\\Spell_Magic_LesserInvisibilty"}]],
+ ["23333"] = [[{icon=true, b=0, priority=0, r=0, group="PvP Flags", indicator="bl", g=0, iconTexture="Interface\\Icons\\INV_BannerPVP_01"}]],
+ ["119611"] = [[{r=0.26274509803922, group="Monk", indicator="tl", g=0.76078431372549, player=true, duration=true, alpha=1, b=0.53725490196078, priority=0, icon=false, iconTexture="Interface\\Icons\\ability_monk_renewingmists"}]],
+ ["8936"] = [[{r=0.12156862745098, group="Druid", indicator="br", g=0.45882352941176, player=true, duration=true, b=0.12156862745098, priority=100, alpha=1, iconTexture="Interface\\Icons\\Spell_Nature_ResistNature"}]],
+ ["34976"] = [[{r=0, group="PvP Flags", indicator="bl", g=0, player=false, b=0, priority=0, icon=true, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["121164"] = [[{alpha=1, b=1, priority=0, r=0, group="PvP Flags", indicator="bl", g=0.003921568627451, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["48438"] = [[{r=0.55294117647059, group="Druid", indicator="31685", g=1, player=true, duration=true, b=0.3921568627451, priority=100, alpha=1, iconTexture="Interface\\Icons\\Ability_Druid_Flourish"}]],
+ ["1022"] = [[{r=0, group="Paladin", indicator="c", g=0, player=false, duration=true, b=0, priority=0, icon=true, iconTexture="Interface\\Icons\\Spell_Holy_SealOfProtection"}]],
+ ["121175"] = [[{r=1, group="PvP Flags", indicator="bl", g=0.24705882352941, b=0.90196078431373, alpha=1, priority=0, icon=false, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["64844"] = [[{r=0.67843137254902, group="Priest", indicator="31685", g=0.30588235294118, player=true, alpha=1, priority=0, b=0.14117647058824, iconTexture="Interface\\Icons\\Spell_Holy_DivineProvidence"}]],
+ ["124081"] = [[{r=0.51372549019608, group="Monk", indicator="br", g=1, player=true, duration=true, b=0.90588235294118, alpha=1, priority=100, icon=false, iconTexture="Interface\\Icons\\ability_monk_forcesphere"}]],
+ ["29166"] = [[{r=0, group="Druid", indicator="c", g=0, b=0, duration=true, priority=0, icon=true, iconTexture="Interface\\Icons\\Spell_Nature_Lightning"}]],
+ ["189895"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\INV_Enchant_VoidSphere\";}",
+ ["189627"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\achievement_zone_cataclysmgreen\";}",
+ ["181306"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Ability_Mage_LivingBomb\";}",
+ ["181753"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_felarakkoa_feldetonation_green\";}",
+ ["188929"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Ability_Hunter_MarkedForDeath\";}",
+ ["189032"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_malkorok_blightofyshaarj_green\";}",
+ ["182826"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Fire_FelFlameRing\";}",
+ ["181515"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_SeedOfDestruction\";}",
+ ["179219"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_felarakkoa_feldetonation_red\";}",
+ ["179864"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Arcane_PrismaticCloak\";}",
+ ["184124"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_AntiMagicShell\";}",
+ ["184450"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossfelorcs_necromancer_purple\";}",
+ ["186134"] = "{icon=true;b=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"tr\";g=0;iconTexture=\"Interface\\\\Icons\\\\spell_fel_elementaldevastation\";}",
+ ["185066"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossfelorcs_necromancer_red\";}",
+ ["183817"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Ability_Warlock_EverlastingAffliction\";}",
+ ["179978"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossgorefiend_touchofdoom\";}",
+ ["182280"] = "{icon=true;b=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";g=0;iconTexture=\"Interface\\\\Icons\\\\Ability_Hunter_MarkedForDeath\";}",
+ ["189031"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_malkorok_blightofyshaarj_yellow\";}",
+ ["186500"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"INTERFACE\\\\ICONS\\\\inv_misc_steelweaponchain\";}",
+ ["188666"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"INTERFACE\\\\ICONS\\\\ability_warlock_soulsiphon\";}",
+ ["186333"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_DevouringPlague\";}",
+ ["186135"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"tr\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_AntiShadow\";}",
+ ["181275"] = "{icon=true;b=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";g=0;iconTexture=\"Interface\\\\Icons\\\\spell_warlock_summonterrorguard\";}",
+ ["181957"] = "{b=0;g=0;priority=2;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Frost_ArcticWinds\";}",
+ ["189030"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_malkorok_blightofyshaarj_red\";}",
+ ["182178"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_arakkoa_spinning_blade\";}",
+ ["189777"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"INTERFACE\\\\ICONS\\\\inv_misc_steelweaponchain\";}",
+ ["186407"] = "{r=0;indicator=\"c\";b=0;group=\"Hellfire Citadel\";priority=2;g=0;iconTexture=\"Interface\\\\Icons\\\\spell_fel_incinerate\";}",
+ ["180166"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"tr\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_ChillTouch\";}",
+ ["180079"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\inv_blacksmithdye_black\";}",
+ ["184449"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossfelorcs_necromancer_purple\";}",
+ ["185510"] = "{r=0;icon=true;indicator=\"tr\";b=0;group=\"Hellfire Citadel\";priority=1;g=0;iconTexture=\"INTERFACE\\\\ICONS\\\\inv_misc_steelweaponchain\";}",
+ ["185065"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossfelorcs_necromancer_orange\";}",
+ ["182769"] = "{r=0;icon=true;indicator=\"tr\";b=0;group=\"Hellfire Citadel\";priority=0;g=0;iconTexture=\"Interface\\\\Icons\\\\ability_fixated_state_purple\";}",
+ ["181508"] = "{b=0;group=\"Hellfire Citadel\";indicator=\"c\";g=0;alpha=1;r=0;priority=1;icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_SeedOfDestruction\";}",
+ ["181099"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_AuraOfDarkness\";}",
+ ["181307"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_Requiem\";}",
+ ["183865"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_warlock_shadowfurytga\";}",
+ ["186961"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_warlock_moltencoregreen\";}",
+ ["182200"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_arakkoa_spinning_blade\";}",
+ ["181597"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossmannoroth_mannorothsgaze\";}",
+ }
+ }
+
+ for classToken in pairs(RAID_CLASS_COLORS) do
+ self.defaults.profile.auraIndicators.disabled[classToken] = {}
+ end
end
-- Module APIs
-function ShadowUF:RegisterModule(module, key, name, isBar, class)
- -- December 16th
- if( module.OnDefaultsSet ) then
- DEFAULT_CHAT_FRAME:AddMessage(string.format("[WARNING!] You are running an outdated version of %s, you need to update it to the latest available for it to work with SUF.", name or key or "unknown"))
+function ShadowUF:RegisterModule(module, key, name, isBar, class, spec, level)
+ -- Prevent duplicate registration for deprecated plugin
+ if( key == "auraIndicators" and IsAddOnLoaded("ShadowedUF_Indicators") and self.modules.auraIndicators ) then
+ self:Print(L["WARNING! ShadowedUF_Indicators has been deprecated as v4 and is now built in. Please delete ShadowedUF_Indicators, your configuration will be saved."])
return
end
@@ -348,6 +568,17 @@ function ShadowUF:RegisterModule(module, key, name, isBar, class)
module.moduleHasBar = isBar
module.moduleName = name
module.moduleClass = class
+ module.moduleLevel = level
+
+ if( type(spec) == "number" ) then
+ module.moduleSpec = {}
+ module.moduleSpec[spec] = true
+ elseif( type(spec) == "table" ) then
+ module.moduleSpec = {}
+ for _, id in pairs(spec) do
+ module.moduleSpec[id] = true
+ end
+ end
table.insert(self.moduleOrder, module)
end
@@ -400,120 +631,215 @@ function ShadowUF:ProfilesChanged()
self.modules.movers:Update()
end
--- Stolen from haste
ShadowUF.noop = function() end
-function ShadowUF:HideBlizzardFrames()
- if( ShadowUF.db.profile.hidden.runes ) then
- RuneFrame.Show = self.noop
- RuneFrame:Hide()
+ShadowUF.hiddenFrame = CreateFrame("Frame")
+ShadowUF.hiddenFrame:Hide()
+
+local rehideFrame = function(self)
+ if( not InCombatLockdown() ) then
+ self:Hide()
end
-
- if( ShadowUF.db.profile.hidden.cast ) then
- CastingBarFrame:UnregisterAllEvents()
- PetCastingBarFrame:UnregisterAllEvents()
+end
+
+local function basicHideBlizzardFrames(...)
+ for i=1, select("#", ...) do
+ local frame = select(i, ...)
+ frame:UnregisterAllEvents()
+ frame:HookScript("OnShow", rehideFrame)
+ frame:Hide()
end
+end
- if( ShadowUF.db.profile.hidden.party ) then
- for i=1, MAX_PARTY_MEMBERS do
- local name = "PartyMemberFrame" .. i
- local frame = _G[name]
+local function hideBlizzardFrames(taint, ...)
+ for i=1, select("#", ...) do
+ local frame = select(i, ...)
+ frame:UnregisterAllEvents()
+ frame:Hide()
- frame:UnregisterAllEvents()
- frame.Show = self.noop
- frame:Hide()
+ if( frame.manabar ) then frame.manabar:UnregisterAllEvents() end
+ if( frame.healthbar ) then frame.healthbar:UnregisterAllEvents() end
+ if( frame.spellbar ) then frame.spellbar:UnregisterAllEvents() end
+ if( frame.powerBarAlt ) then frame.powerBarAlt:UnregisterAllEvents() end
- _G[name .. "HealthBar"]:UnregisterAllEvents()
- _G[name .. "ManaBar"]:UnregisterAllEvents()
+ if( taint ) then
+ frame.Show = ShadowUF.noop
+ else
+ frame:SetParent(ShadowUF.hiddenFrame)
+ frame:HookScript("OnShow", rehideFrame)
end
end
+end
- if( ShadowUF.db.profile.hidden.buffs ) then
- BuffFrame:UnregisterAllEvents()
- BuffFrame.Show = self.noop
- BuffFrame:Hide()
- ConsolidatedBuffs.Show = self.noop
- ConsolidatedBuffs:Hide()
- TemporaryEnchantFrame.Show = self.noop
- TemporaryEnchantFrame:Hide()
+local active_hiddens = {}
+function ShadowUF:HideBlizzardFrames()
+ if( self.db.profile.hidden.cast and not active_hiddens.cast ) then
+ hideBlizzardFrames(true, CastingBarFrame, PetCastingBarFrame)
end
-
- if( ShadowUF.db.profile.hidden.player ) then
- PlayerFrame:UnregisterAllEvents()
- PlayerFrame.Show = self.noop
- PlayerFrame:Hide()
- PlayerFrame:RegisterEvent('UNIT_ENTERING_VEHICLE')
- PlayerFrame:RegisterEvent('UNIT_ENTERED_VEHICLE')
- PlayerFrame:RegisterEvent('UNIT_EXITING_VEHICLE')
- PlayerFrame:RegisterEvent('UNIT_EXITED_VEHICLE')
+ if( self.db.profile.hidden.party and not active_hiddens.party ) then
+ for i=1, MAX_PARTY_MEMBERS do
+ local name = "PartyMemberFrame" .. i
+ hideBlizzardFrames(true, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"])
+ end
+
+ -- This stops the compact party frame from being shown
+ UIParent:UnregisterEvent("GROUP_ROSTER_UPDATE")
- PlayerFrameHealthBar:UnregisterAllEvents()
- PlayerFrameManaBar:UnregisterAllEvents()
+ -- This just makes sure
+ if( CompactPartyFrame ) then
+ hideBlizzardFrames(false, CompactPartyFrame)
+ end
end
+
+ if( CompactRaidFrameManager ) then
+ if( self.db.profile.hidden.raid and not active_hiddens.raidTriggered ) then
+ active_hiddens.raidTriggered = true
+
+ local function hideRaid()
+ CompactRaidFrameManager:UnregisterAllEvents()
+ CompactRaidFrameContainer:UnregisterAllEvents()
+ if( InCombatLockdown() ) then return end
- if( ShadowUF.db.profile.hidden.pet ) then
- PetFrame:UnregisterAllEvents()
- PetFrame.Show = self.noop
- PetFrame:Hide()
+ CompactRaidFrameManager:Hide()
+ local shown = CompactRaidFrameManager_GetSetting("IsShown")
+ if( shown and shown ~= "0" ) then
+ CompactRaidFrameManager_SetSetting("IsShown", "0")
+ end
+ end
+
+ hooksecurefunc("CompactRaidFrameManager_UpdateShown", function()
+ if( self.db.profile.hidden.raid ) then
+ hideRaid()
+ end
+ end)
+
+ hideRaid()
+ CompactRaidFrameContainer:HookScript("OnShow", hideRaid)
+ CompactRaidFrameManager:HookScript("OnShow", hideRaid)
+ end
+ end
- PetFrameHealthBar:UnregisterAllEvents()
- PetFrameManaBar:UnregisterAllEvents()
+ if( self.db.profile.hidden.buffs and not active_hiddens.buffs ) then
+ hideBlizzardFrames(false, BuffFrame, TemporaryEnchantFrame)
end
- if( ShadowUF.db.profile.hidden.target ) then
- TargetFrame:UnregisterAllEvents()
- TargetFrame.Show = self.noop
- TargetFrame:Hide()
+ if( self.db.profile.hidden.player and not active_hiddens.player ) then
+ hideBlizzardFrames(false, PlayerFrame, PlayerFrameAlternateManaBar)
+
+ -- We keep these in case someone is still using the default auras, otherwise it messes up vehicle stuff
+ PlayerFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
+ PlayerFrame:RegisterEvent("UNIT_ENTERING_VEHICLE")
+ PlayerFrame:RegisterEvent("UNIT_ENTERED_VEHICLE")
+ PlayerFrame:RegisterEvent("UNIT_EXITING_VEHICLE")
+ PlayerFrame:RegisterEvent("UNIT_EXITED_VEHICLE")
+ PlayerFrame:SetMovable(true)
+ PlayerFrame:SetUserPlaced(true)
+ PlayerFrame:SetDontSavePosition(true)
+ end
- TargetFrameHealthBar:UnregisterAllEvents()
- TargetFrameManaBar:UnregisterAllEvents()
- TargetFrameSpellBar:UnregisterAllEvents()
+ if( self.db.profile.hidden.playerPower and not active_hiddens.playerPower ) then
+ basicHideBlizzardFrames(PriestBarFrame, RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame)
+ end
- ComboFrame:UnregisterAllEvents()
- ComboFrame.Show = self.noop
- ComboFrame:Hide()
+ if( self.db.profile.hidden.pet and not active_hiddens.pet ) then
+ hideBlizzardFrames(false, PetFrame)
end
- if( ShadowUF.db.profile.hidden.focus ) then
- FocusFrame:UnregisterAllEvents()
- FocusFrame.Show = self.noop
- FocusFrame:Hide()
-
- FocusFrameHealthBar:UnregisterAllEvents()
- FocusFrameManaBar:UnregisterAllEvents()
- FocusFrameSpellBar:UnregisterAllEvents()
+ if( self.db.profile.hidden.target and not active_hiddens.target ) then
+ hideBlizzardFrames(false, TargetFrame, ComboFrame, TargetFrameToT)
+ end
+
+ if( self.db.profile.hidden.focus and not active_hiddens.focus ) then
+ hideBlizzardFrames(false, FocusFrame, FocusFrameToT)
end
- if( ShadowUF.db.profile.hidden.boss ) then
+ if( self.db.profile.hidden.boss and not active_hiddens.boss ) then
for i=1, MAX_BOSS_FRAMES do
local name = "Boss" .. i .. "TargetFrame"
- local frame = _G[name]
+ hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"])
+ end
+ end
- frame:UnregisterAllEvents()
- frame.Show = self.noop
- frame:Hide()
+ if( self.db.profile.hidden.arena and not active_hiddens.arenaTriggered and IsAddOnLoaded("Blizzard_ArenaUI") and not InCombatLockdown() ) then
+ active_hiddens.arenaTriggered = true
- _G[name .. "HealthBar"]:UnregisterAllEvents()
- _G[name .. "ManaBar"]:UnregisterAllEvents()
- end
+ ArenaEnemyFrames:UnregisterAllEvents()
+ ArenaEnemyFrames:SetParent(self.hiddenFrame)
+ ArenaPrepFrames:UnregisterAllEvents()
+ ArenaPrepFrames:SetParent(self.hiddenFrame)
end
-
- if( ShadowUF.db.profile.hidden.arena ) then
- Arena_LoadUI = self.noop
+
+ if( self.db.profile.hidden.playerAltPower and not active_hiddens.playerAltPower ) then
+ hideBlizzardFrames(false, PlayerPowerBarAlt)
end
- -- Don't modify the raid menu because that will taint the MA/MT stuff and it'll break and that's bad
- for key, list in pairs(UnitPopupMenus) do
- if( key ~= "RAID" ) then
- for i=#(list), 1, -1 do
- if( list[i] == "SET_FOCUS" or list[i] == "CLEAR_FOCUS" or list[i] == "LOCK_FOCUS_FRAME" or list[i] == "UNLOCK_FOCUS_FRAME" ) then
- table.remove(list, i)
- end
- end
+ -- As a reload is required to reset the hidden hooks, we can just set this to true if anything is true
+ for type, flag in pairs(self.db.profile.hidden) do
+ if( flag ) then
+ active_hiddens[type] = true
end
end
end
+-- Upgrade info
+local infoMessages = {
+ -- Old messages we don't need anymore
+ {}, {},
+ {
+ L["You must restart Shadowed Unit Frames."],
+ L["If you don't, you will be unable to use any combo point features (Chi, Holy Power, Combo Points, Aura Points, etc) until you do so."]
+ }
+}
+
+function ShadowUF:ShowInfoPanel()
+ local infoID = ShadowUF.db.global.infoID or 0
+ if( ShadowUF.ComboPoints and infoID < 3 ) then infoID = 3 end
+
+ ShadowUF.db.global.infoID = #(infoMessages)
+ if( infoID < 0 or infoID >= #(infoMessages) ) then return end
+
+ local frame = CreateFrame("Frame", nil, UIParent)
+ frame:SetClampedToScreen(true)
+ frame:SetFrameStrata("HIGH")
+ frame:SetToplevel(true)
+ frame:SetWidth(500)
+ frame:SetHeight(285)
+ frame:SetBackdrop({
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ edgeSize = 26,
+ insets = {left = 9, right = 9, top = 9, bottom = 9},
+ })
+ frame:SetBackdropColor(0, 0, 0, 0.85)
+ frame:SetPoint("CENTER", UIParent, "CENTER", 0, 100)
+
+ frame.titleBar = frame:CreateTexture(nil, "ARTWORK")
+ frame.titleBar:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
+ frame.titleBar:SetPoint("TOP", 0, 8)
+ frame.titleBar:SetWidth(350)
+ frame.titleBar:SetHeight(45)
+
+ frame.title = frame:CreateFontString(nil, "ARTWORK", "GameFontNormal")
+ frame.title:SetPoint("TOP", 0, 0)
+ frame.title:SetText("Shadowed Unit Frames")
+
+ frame.text = frame:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
+ frame.text:SetText(table.concat(infoMessages[ShadowUF.db.global.infoID], "\n"))
+ frame.text:SetPoint("TOPLEFT", 12, -22)
+ frame.text:SetWidth(frame:GetWidth() - 20)
+ frame.text:SetJustifyH("LEFT")
+ frame:SetHeight(frame.text:GetHeight() + 70)
+
+ frame.hide = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
+ frame.hide:SetText(L["Ok"])
+ frame.hide:SetHeight(20)
+ frame.hide:SetWidth(100)
+ frame.hide:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 8, 8)
+ frame.hide:SetScript("OnClick", function(self)
+ self:GetParent():Hide()
+ end)
+end
+
function ShadowUF:Print(msg)
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99Shadow UF|r: " .. msg)
end
@@ -562,9 +888,12 @@ end
local frame = CreateFrame("Frame")
frame:RegisterEvent("PLAYER_LOGIN")
+frame:RegisterEvent("ADDON_LOADED")
frame:SetScript("OnEvent", function(self, event, addon)
if( event == "PLAYER_LOGIN" ) then
ShadowUF:OnInitialize()
self:UnregisterEvent("PLAYER_LOGIN")
+ elseif( event == "ADDON_LOADED" and ( addon == "Blizzard_ArenaUI" or addon == "Blizzard_CompactRaidFrames" ) ) then
+ ShadowUF:HideBlizzardFrames()
end
-end)
\ No newline at end of file
+end)
diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc
index 718f941a9..240cae268 100755
--- a/ShadowedUnitFrames.toc
+++ b/ShadowedUnitFrames.toc
@@ -1,51 +1,69 @@
-## Interface: 30300
-## Title: Shadowed Unit Frames
-## Notes: An apple a day keeps the raptor away, or so they say
-## Author: Shadowed
-## Version: @project-version@
-## SavedVariables: ShadowedUFDB
-## OptionalDeps: Ace3, LibSharedMedia-3.0, LibHealComm-4.0, AceGUI-3.0-SharedMediaWidgets
-
-#@no-lib-strip@
-libs\LibStub\LibStub.lua
-libs\CallbackHandler-1.0\CallbackHandler-1.0\CallbackHandler-1.0.xml
-libs\LibSharedMedia-3.0\lib.xml
-libs\LibHealComm-4.0\LibHealComm-4.0.xml
-libs\AceDB-3.0\AceDB-3.0.xml
#@end-no-lib-strip@
-
-localization\enUS.lua
-localization\deDE.lua
-localization\esES.lua
-localization\esMX.lua
-localization\frFR.lua
-localization\koKR.lua
-localization\ruRU.lua
-localization\zhCN.lua
-localization\zhTW.lua
-
-ShadowedUnitFrames.lua
-modules\units.lua
-modules\layout.lua
-modules\movers.lua
-modules\defaultlayout.lua
-modules\highlight.lua
-modules\tags.lua
-modules\health.lua
-modules\power.lua
-modules\portrait.lua
-modules\indicators.lua
-modules\xp.lua
-modules\cast.lua
-modules\auras.lua
-modules\combattext.lua
-modules\totems.lua
-modules\runes.lua
-modules\fader.lua
-modules\combopoints.lua
-modules\incheal.lua
-modules\range.lua
-modules\empty.lua
+## Interface: 80000
+## Title: Shadowed Unit Frames
+## Notes: Moooooooooooooooooo
+## Author: Shadowed
+## Version: @project-version@
+## SavedVariables: ShadowedUFDB
+## X-Website: http://www.wowace.com/addons/shadowed-unit-frames/
+## OptionalDeps: Ace3, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibDualSpec-1.0, LibSpellRange-1.0, Clique
+
+#@no-lib-strip@
+libs\LibStub\LibStub.lua
+libs\CallbackHandler-1.0\CallbackHandler-1.0\CallbackHandler-1.0.xml
+libs\LibSharedMedia-3.0\lib.xml
+libs\AceDB-3.0\AceDB-3.0.xml
+libs\LibDualSpec-1.0\LibDualSpec-1.0.lua
+libs\LibSpellRange-1.0\lib.xml
+#@end-no-lib-strip@
+
+localization\enUS.lua
+localization\deDE.lua
+localization\esES.lua
+localization\esMX.lua
+localization\frFR.lua
+localization\koKR.lua
+localization\ruRU.lua
+localization\zhCN.lua
+localization\zhTW.lua
+
+ShadowedUnitFrames.xml
+ShadowedUnitFrames.lua
+modules\helpers.lua
+modules\units.lua
+modules\layout.lua
+modules\movers.lua
+modules\defaultlayout.lua
+modules\highlight.lua
+modules\tags.lua
+modules\health.lua
+modules\power.lua
+modules\portrait.lua
+modules\indicators.lua
+modules\xp.lua
+modules\cast.lua
+modules\auras.lua
+modules\auraindicators.lua
+modules\combattext.lua
+modules\totems.lua
+modules\runes.lua
+modules\fader.lua
+modules\basecombopoints.lua
+modules\combopoints.lua
+modules\incheal.lua
+modules\incabsorb.lua
+modules\healabsorb.lua
+modules\range.lua
+modules\empty.lua
modules\druid.lua
+modules\soulshards.lua
+modules\holypower.lua
+modules\chi.lua
+modules\altpower.lua
+modules\monkstagger.lua
+modules\aurapoints.lua
+modules\priest.lua
+modules\shaman.lua
+modules\arcanecharges.lua
#@do-not-package@
options\config.lua
-#@end-do-not-package@
\ No newline at end of file
+#@end-do-not-package@
diff --git a/ShadowedUnitFrames.xml b/ShadowedUnitFrames.xml
new file mode 100644
index 000000000..ec6af43d9
--- /dev/null
+++ b/ShadowedUnitFrames.xml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/globalcheck.lua b/globalcheck.lua
deleted file mode 100755
index 1936bc7b4..000000000
--- a/globalcheck.lua
+++ /dev/null
@@ -1,83 +0,0 @@
-local isOSX = os.getenv("MANPATH") and true or false
-local leaks = {}
-local results = ""
-local function output(msg)
- results = results .. "\r\n" .. msg
-end
-
-local function scanFile(path)
- output(io.popen(string.format("luac -l %s", path)):read("*all"))
-end
-
-local function scanFolder(path)
- local command
- if( isOSX ) then
- command = string.format("ls \"%s\"", (path or "./"))
- else
- command = string.format("dir /B \"%s\"", (path or ""))
- end
-
- for file in io.popen(command):lines() do
- local extension = string.match(file, "%.([%a%d]+)$")
- if( file ~= "" and not extension and file ~= "libs" ) then
- if( path ) then
- scanFolder(path .. "/" .. file)
- else
- scanFolder(file)
- end
- elseif( extension == "lua" and file ~= "localcheck.lua" and file ~= "globalcheck.lua" and not string.match(file, "^localization%.([a-zA-Z]+)%.lua") ) then
- if( path ) then
- scanFile(path .. "/" .. file)
- else
- scanFile(file)
- end
- end
- end
-end
-
-scanFolder()
-
-if( isOSX ) then
- io.popen("unlink luac.out")
-else
- io.popen("del luac.out")
-end
-
-local file = io.open("results.txt", "w")
-file:write(tostring(results))
-file:flush()
-file:close()
-
-
-local f = io.open("results.txt", "r")
-local data = f:read("*all")
-function lines(str)
- local t = {}
- local function helper(line) table.insert(t, line) return "" end
- helper((str:gsub("(.-)\r?\n", helper)))
- return t
-end
-
-local printFile
-for _, line in pairs(lines(data)) do
- if( string.match(line, "(.+) <(.+)>") ) then
- file = line
- printFile = nil
- end
-
- if( string.match(line, "SETGLOBAL") ) then
- if( not printFile ) then
- print(file)
- printFile = true
- end
-
- print(line)
- end
-end
-
-f:close()
-if( isOSX ) then
- io.popen("unlink results.txt")
-else
- io.popen("del results.txt")
-end
diff --git a/localcheck.lua b/locale-import.lua
old mode 100755
new mode 100644
similarity index 76%
rename from localcheck.lua
rename to locale-import.lua
index aa1603aca..ffba821e3
--- a/localcheck.lua
+++ b/locale-import.lua
@@ -1,5 +1,5 @@
--- If you want to hardcode toc or slug in and not enter it, do so here
-local ADDON_SLUG
+-- Need to hardcode the project id here
+local ADDON_PROJECT_ID = 19268
local TOC_FILE
-- Automatically identify the slug based on the .git or .svn configuration data, change the path if it's not in root, or set to false to disable
local AUTO_IDENTIFY_SLUG = "./"
@@ -10,20 +10,21 @@ local SITE_LOCATION = nil
-- Personally I keep the api key in another file and just have this reference that to get it
-- If you want to do this, create the file with CURSE_API_KEY = "" in it and set the path here
-- set this to nil and it will ask you for your API key
-local API_KEY_FILE = "../TestCode/api-key.lua"
+local API_KEY_FILE = "../../cf-api-key.lua"
-- Patterns that should not be scrapped, case-insensitive
-- Anything between the no-lib-strip is automatically ignored
local FILE_BLACKLIST = {"^localization", "^lib"}
--- 1 = English
-DEFAULT_LANGUAGE = "1"
+
+-- default language to import to
+local DEFAULT_LANGUAGE = "enUS"
-- Removes phrases that are not found through this
-DELETE_UNIMPORTED = true
+local DELETE_UNIMPORTED = true
-- No more modifying!
local OS_TYPE = os.getenv("HOME") and "linux" or "windows"
-- Mak sure we have LuaSockets
-local _, http = pcall(require, "socket.http")
+local _, http = pcall(require, "ssl.https")
local _, ltn = pcall(require, "ltn12")
if( not http ) then
print("Failed to find socket.http, did you install LuaSockets?")
@@ -31,6 +32,11 @@ elseif( not ltn ) then
print("Failed to find ltn12, did you install LuaSockets?")
end
+-- check project id is set
+if not ADDON_PROJECT_ID then
+ print("No project id specified, did you set it?")
+ return
+end
-- Figure out the API key
if( API_KEY_FILE ) then
@@ -40,14 +46,13 @@ if( API_KEY_FILE ) then
else
file:close()
dofile(API_KEY_FILE)
-
+
if( not CURSE_API_KEY ) then
print("You did not define CURSE_API_KEY in your key file, make sure it does not have local next to it.")
end
end
end
-
if( not CURSE_API_KEY ) then
while( not CURSE_API_KEY ) do
io.stdout:write("Enter API key: ")
@@ -59,23 +64,22 @@ end
-- Attempt to automatically identify the addon slug
if( AUTO_IDENTIFY_SLUG ) then
local git = io.open(AUTO_IDENTIFY_SLUG .. ".git/config")
- local svn = io.open(AUTO_IDENTIFY_SLUG .. ".svn/entries")
+ local svn = io.popen("svn info --show-item url " .. AUTO_IDENTIFY_SLUG)
if( git ) then
local contents = git:read("*all")
- git:close()
- SITE_LOCATION, ADDON_SLUG = string.match(contents, "git%.(.-)%.com:wow/(.-)/mainline%.git")
+ SITE_LOCATION = string.match(contents, "repos%.([^\n]-)%.com/wow/([^\n]-)")
elseif( svn ) then
local contents = svn:read("*all")
- svn:close()
-
- SITE_LOCATION, ADDON_SLUG = string.match(contents, "svn%.(.-)%.com/wow/(.-)/mainline")
+
+ SITE_LOCATION = string.match(contents, "repos%.([^\n]-)%.com/wow/([^\n]-)")
end
-
- if( not ADDON_SLUG ) then
- print("Failed to identify addon slug.")
- elseif( not SITE_LOCATION ) then
+
+ if( git ) then git:close() end
+ if( svn ) then svn:close() end
+
+ if( not SITE_LOCATION ) then
print("Failed to identify site location.")
end
end
@@ -88,17 +92,6 @@ if( not SITE_LOCATION ) then
end
end
--- Manually ask for it
-if( not ADDON_SLUG ) then
- while( not ADDON_SLUG ) do
- io.stdout:write("Enter slug: ")
- ADDON_SLUG = io.stdin:read("*line")
- ADDON_SLUG = ADDON_SLUG ~= "" and ADDON_SLUG or nil
- end
-end
-
-print(string.format("Using addon slug: %s", ADDON_SLUG))
-
-- Find the TOC now
if( AUTO_FIND_TOC ) then
local pipe = OS_TYPE == "windows" and io.popen(string.format("dir /B \"%s\"", AUTO_FIND_TOC)) or io.popen(string.format("ls -1 \"%s\"", AUTO_FIND_TOC))
@@ -142,14 +135,14 @@ local ignore
local localizedKeys = {}
for line in io.lines(TOC_FILE) do
line = string.gsub(line, "\r", "")
-
+
if( string.match(line, "#@no%-lib%-strip@") ) then
ignore = true
elseif( string.match(line, "#@end%-no%-lib%-strip@") ) then
ignore = nil
end
-
- if( not ignore and string.match(line, "%.lua") ) then
+
+ if( not ignore and string.match(line, "%.lua") and not string.match(line, "^%s*#")) then
-- Make sure it's a valid file
local blacklist
for _, check in pairs(FILE_BLACKLIST) do
@@ -158,22 +151,22 @@ for line in io.lines(TOC_FILE) do
break
end
end
-
+
-- File checks out, scrap everything
if( not blacklist ) then
-- Fix slashes
if( OS_TYPE == "linux" ) then
line = string.gsub(line, "\\", "/")
end
-
+
local keys = 0
local contents = io.open(line):read("*all")
-
+
for match in string.gmatch(contents, "L%[\"(.-)%\"]") do
if( not localizedKeys[match] ) then keys = keys + 1 end
localizedKeys[match] = true
end
-
+
print(string.format("%s (%d keys)", line, keys))
end
end
@@ -195,10 +188,8 @@ end
print(string.format("Found %d keys total", totalLocalizedKeys))
local addonData = {
- ["format"] = "lua_additive_table",
- ["language"] = DEFAULT_LANGUAGE,
- ["delete_unimported"] = DELETE_UNIMPORTED and "y" or "n",
- ["text"] = localization,
+ ["metadata"] = ("{ language: \"%s\", \"namespace\": \"\", \"missing-phrase-handling\": \"%s\" }"):format(DEFAULT_LANGUAGE, DELETE_UNIMPORTED and "DeletePhrase" or "DoNothing"),
+ ["localizations"] = localization,
}
-- Send it off
@@ -212,35 +203,24 @@ for key, data in pairs(addonData) do
body = string.format("%s%s\r\n", body, data)
end
-body = string.format("%s--%s\r\n", body, boundary)
+body = string.format("%s--%s--\r\n", body, boundary)
+
+local host = SITE_LOCATION == "curseforge" and "wow.curseforge.com" or "www.wowace.com"
http.request({
method = "POST",
- url = string.format("http://www.%s.com/addons/%s/localization/import/?api-key=%s", SITE_LOCATION, ADDON_SLUG, CURSE_API_KEY),
+ url = string.format("https://%s/api/projects/%s/localization/import", host, ADDON_PROJECT_ID),
sink = ltn12.sink.table(source),
source = ltn12.source.string(body),
headers = {
+ ["X-Api-Token"] = CURSE_API_KEY,
["Content-Type"] = string.format("multipart/form-data; boundary=\"%s\"", boundary),
["Content-Length"] = string.len(body),
},
})
local contents = table.concat(source, "\n")
-local errors = {}
-for line in string.gmatch(contents, "(.-)\n") do
- local msg = string.match(line, "(.-)
")
- if( msg ) then
- table.insert(errors, msg)
- end
-end
-
+print(contents)
print("")
-if( #(errors) == 0 ) then
- print(string.format("Updated localization for %s on %s!", ADDON_SLUG, SITE_LOCATION))
-else
- print("Localization failed:")
- for _, line in pairs(errors) do
- print(line)
- end
-end
+print(string.format("Updated localization on %s!", SITE_LOCATION))
diff --git a/localization/deDE.lua b/localization/deDE.lua
old mode 100644
new mode 100755
diff --git a/localization/enUS.lua b/localization/enUS.lua
old mode 100644
new mode 100755
diff --git a/localization/esES.lua b/localization/esES.lua
old mode 100644
new mode 100755
diff --git a/localization/esMX.lua b/localization/esMX.lua
old mode 100644
new mode 100755
diff --git a/localization/frFR.lua b/localization/frFR.lua
old mode 100644
new mode 100755
diff --git a/localization/koKR.lua b/localization/koKR.lua
old mode 100644
new mode 100755
diff --git a/localization/ptBR.lua b/localization/ptBR.lua
new file mode 100755
index 000000000..4a3353b48
--- /dev/null
+++ b/localization/ptBR.lua
@@ -0,0 +1,5 @@
+if( GetLocale() ~= "ptBR" ) then return end
+local L = {}
+--@localization(locale="ptBR", format="lua_additive_table", handle-unlocalized="ignore")@
+local ShadowUF = select(2, ...)
+ShadowUF.L = setmetatable(L, {__index = ShadowUF.L})
diff --git a/localization/ruRU.lua b/localization/ruRU.lua
old mode 100644
new mode 100755
diff --git a/localization/zhCN.lua b/localization/zhCN.lua
old mode 100644
new mode 100755
diff --git a/localization/zhTW.lua b/localization/zhTW.lua
old mode 100644
new mode 100755
diff --git a/media/fonts/Myriad Condensed Web.ttf b/media/fonts/Myriad Condensed Web.ttf
index ce9546b9c..dc23c18e3 100755
Binary files a/media/fonts/Myriad Condensed Web.ttf and b/media/fonts/Myriad Condensed Web.ttf differ
diff --git a/media/textures/backdrop.tga b/media/textures/backdrop.tga
new file mode 100755
index 000000000..640e8c44d
Binary files /dev/null and b/media/textures/backdrop.tga differ
diff --git a/media/textures/shard.tga b/media/textures/shard.tga
new file mode 100755
index 000000000..2d459b50e
Binary files /dev/null and b/media/textures/shard.tga differ
diff --git a/modules/altpower.lua b/modules/altpower.lua
new file mode 100755
index 000000000..5962677b0
--- /dev/null
+++ b/modules/altpower.lua
@@ -0,0 +1,51 @@
+local AltPower = {}
+AltPower.defaultVisibility = false
+ShadowUF:RegisterModule(AltPower, "altPowerBar", ShadowUF.L["Alt. Power bar"], true)
+
+function AltPower:OnEnable(frame)
+ frame.altPowerBar = frame.altPowerBar or ShadowUF.Units:CreateBar(frame)
+
+ frame:RegisterUnitEvent("UNIT_POWER_BAR_SHOW", self, "UpdateVisibility")
+ frame:RegisterUnitEvent("UNIT_POWER_BAR_HIDE", self, "UpdateVisibility")
+ frame:RegisterNormalEvent("PLAYER_ENTERING_WORLD", self, "UpdateVisibility")
+
+ frame:RegisterUpdateFunc(self, "UpdateVisibility")
+end
+
+function AltPower:OnDisable(frame)
+ frame:UnregisterAll(self)
+end
+
+local altColor = {}
+function AltPower:UpdateVisibility(frame)
+ local barType, minPower, _, _, _, hideFromOthers, showOnRaid = UnitAlternatePowerInfo(frame.unit)
+ local visible = false
+ if( barType ) then
+ if( ( frame.unitType == "player" or frame.unitType == "pet" ) or not hideFromOthers ) then
+ visible = true
+ elseif( showOnRaid and ( UnitInRaid(frame.unit) or UnitInParty(frame.unit) ) ) then
+ visible = true
+ end
+ end
+
+ ShadowUF.Layout:SetBarVisibility(frame, "altPowerBar", visible)
+
+ -- Register or unregister events based on if it's visible
+ local type = visible and "RegisterUnitEvent" or "UnregisterSingleEvent"
+ frame[type](frame, "UNIT_POWER_FREQUENT", self, "Update")
+ frame[type](frame, "UNIT_MAXPOWER", self, "Update")
+ frame[type](frame, "UNIT_DISPLAYPOWER", self, "Update")
+ if( not visible ) then return end
+
+ local color = ShadowUF.db.profile.powerColors.ALTERNATE
+ frame:SetBarColor("altPowerBar", color.r, color.g, color.b)
+
+ AltPower:Update(frame)
+end
+
+function AltPower:Update(frame, event, unit, type)
+ if( event and type ~= "ALTERNATE" ) then return end
+
+ frame.altPowerBar:SetMinMaxValues(select(2, UnitAlternatePowerInfo(frame.unit)) or 0, UnitPowerMax(frame.unit, ALTERNATE_POWER_INDEX) or 0)
+ frame.altPowerBar:SetValue(UnitPower(frame.unit, ALTERNATE_POWER_INDEX) or 0)
+end
diff --git a/modules/arcanecharges.lua b/modules/arcanecharges.lua
new file mode 100644
index 000000000..8d8eebd0a
--- /dev/null
+++ b/modules/arcanecharges.lua
@@ -0,0 +1,31 @@
+if( not ShadowUF.ComboPoints ) then return end
+
+local ArcaneCharges = setmetatable({}, {__index = ShadowUF.ComboPoints})
+ShadowUF:RegisterModule(ArcaneCharges, "arcaneCharges", ShadowUF.L["Arcane Charges"], nil, "MAGE", SPEC_MAGE_ARCANE)
+local arcaneConfig = {max = 5, key = "arcaneCharges", colorKey = "ARCANECHARGES", powerType = Enum.PowerType.ArcaneCharges, eventType = "ARCANE_CHARGES", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"}
+
+function ArcaneCharges:OnEnable(frame)
+ frame.arcaneCharges = frame.arcaneCharges or CreateFrame("Frame", nil, frame)
+ frame.arcaneCharges.cpConfig = arcaneConfig
+ frame.comboPointType = arcaneConfig.key
+
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks")
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "Update")
+
+ frame:RegisterUpdateFunc(self, "Update")
+ frame:RegisterUpdateFunc(self, "UpdateBarBlocks")
+end
+
+function ArcaneCharges:OnLayoutApplied(frame, config)
+ ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config)
+ self:UpdateBarBlocks(frame)
+end
+
+function ArcaneCharges:GetComboPointType()
+ return "arcaneCharges"
+end
+
+function ArcaneCharges:GetPoints(unit)
+ return UnitPower("player", arcaneConfig.powerType)
+end
\ No newline at end of file
diff --git a/modules/auraindicators.lua b/modules/auraindicators.lua
new file mode 100755
index 000000000..be7bdfd77
--- /dev/null
+++ b/modules/auraindicators.lua
@@ -0,0 +1,287 @@
+local Indicators = {}
+ShadowUF:RegisterModule(Indicators, "auraIndicators", ShadowUF.L["Aura indicators"])
+
+Indicators.auraFilters = {"boss", "curable"}
+
+Indicators.auraConfig = setmetatable({}, {
+ __index = function(tbl, index)
+ local aura = ShadowUF.db.profile.auraIndicators.auras[tostring(index)]
+ if( not aura ) then
+ tbl[index] = false
+ else
+ local func, msg = loadstring("return " .. aura)
+ if( func ) then
+ func = func()
+ elseif( msg ) then
+ error(msg, 3)
+ end
+
+ tbl[index] = func
+ if( not tbl[index].group ) then tbl[index].group = "Miscellaneous" end
+ end
+
+ return tbl[index]
+end})
+
+local playerUnits = {player = true, vehicle = true, pet = true}
+local backdropTbl = {bgFile = "Interface\\Addons\\ShadowedUnitFrames\\mediabackdrop", edgeFile = "Interface\\Addons\\ShadowedUnitFrames\\media\\backdrop", tile = true, tileSize = 1, edgeSize = 1}
+
+function Indicators:OnEnable(frame)
+ -- Not going to create the indicators we want here, will do that when we do the layout stuff
+ frame.auraIndicators = frame.auraIndicators or CreateFrame("Frame", nil, frame)
+ frame.auraIndicators:SetFrameLevel(4)
+ frame.auraIndicators:Show()
+
+ -- Of course, watch for auras
+ frame:RegisterUnitEvent("UNIT_AURA", self, "UpdateAuras")
+ frame:RegisterUpdateFunc(self, "UpdateAuras")
+end
+
+function Indicators:OnDisable(frame)
+ frame:UnregisterAll(self)
+ frame.auraIndicators:Hide()
+end
+
+function Indicators:OnLayoutApplied(frame)
+ if( not frame.auraIndicators ) then return end
+
+ -- Create indicators
+ local id = 1
+ for key, indicatorConfig in pairs(ShadowUF.db.profile.auraIndicators.indicators) do
+ -- Create indicator as needed
+ local indicator = frame.auraIndicators["indicator-" .. id]
+ if( not indicator ) then
+ indicator = CreateFrame("Frame", nil, frame.auraIndicators)
+ indicator:SetFrameLevel(frame.topFrameLevel + 2)
+ indicator.texture = indicator:CreateTexture(nil, "OVERLAY")
+ indicator.texture:SetPoint("CENTER", indicator)
+ indicator:SetAlpha(indicatorConfig.alpha)
+ indicator:SetBackdrop(backdropTbl)
+ indicator:SetBackdropColor(0, 0, 0, 1)
+ indicator:SetBackdropBorderColor(0, 0, 0, 0)
+
+ indicator.cooldown = CreateFrame("Cooldown", nil, indicator, "CooldownFrameTemplate")
+ indicator.cooldown:SetReverse(true)
+ indicator.cooldown:SetPoint("CENTER", 0, -1)
+ indicator.cooldown:SetHideCountdownNumbers(true)
+
+ indicator.stack = indicator:CreateFontString(nil, "OVERLAY")
+ indicator.stack:SetFont("Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf", 12, "OUTLINE")
+ indicator.stack:SetShadowColor(0, 0, 0, 1.0)
+ indicator.stack:SetShadowOffset(0.8, -0.8)
+ indicator.stack:SetPoint("BOTTOMRIGHT", indicator, "BOTTOMRIGHT", 1, 0)
+ indicator.stack:SetWidth(18)
+ indicator.stack:SetHeight(10)
+ indicator.stack:SetJustifyH("RIGHT")
+
+ frame.auraIndicators["indicator-" .. id] = indicator
+ end
+
+ -- Quick access
+ indicator.filters = ShadowUF.db.profile.auraIndicators.filters[key]
+ indicator.config = ShadowUF.db.profile.units[frame.unitType].auraIndicators
+
+ -- Set up the sizing options
+ indicator:SetHeight(indicatorConfig.height)
+ indicator.texture:SetWidth(indicatorConfig.width - 1)
+ indicator:SetWidth(indicatorConfig.width)
+ indicator.texture:SetHeight(indicatorConfig.height - 1)
+
+ ShadowUF.Layout:AnchorFrame(frame, indicator, indicatorConfig)
+
+ -- Let the auras module quickly access indicators without having to use index
+ frame.auraIndicators[key] = indicator
+
+ id = id + 1
+ end
+end
+
+local playerClass = select(2, UnitClass("player"))
+local filterMap = {}
+local canCure = ShadowUF.Units.canCure
+for _, key in pairs(Indicators.auraFilters) do filterMap[key] = "filter-" .. key end
+
+local function checkFilterAura(frame, type, isFriendly, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff)
+ local category
+ if( isFriendly and canCure[auraType] and type == "debuffs" ) then
+ category = "curable"
+ elseif( isBossDebuff ) then
+ category = "boss"
+ else
+ return
+ end
+
+ local applied = false
+
+ for key, config in pairs(ShadowUF.db.profile.auraIndicators.indicators) do
+ local indicator = frame.auraIndicators[key]
+ if( indicator and indicator.config.enabled and indicator.filters[category].enabled and not ShadowUF.db.profile.units[frame.unitType].auraIndicators[filterMap[category]] ) then
+ indicator.showStack = config.showStack
+ indicator.priority = indicator.filters[category].priority
+ indicator.showIcon = true
+ indicator.showDuration = indicator.filters[category].duration
+ indicator.spellDuration = duration
+ indicator.spellEnd = endTime
+ indicator.spellIcon = texture
+ indicator.spellName = name
+ indicator.spellStack = count
+ indicator.colorR = nil
+ indicator.colorG = nil
+ indicator.colorB = nil
+
+ applied = true
+ end
+ end
+
+ return applied
+end
+
+local function checkSpecificAura(frame, type, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff)
+ -- Not relevant
+ if( not ShadowUF.db.profile.auraIndicators.auras[name] and not ShadowUF.db.profile.auraIndicators.auras[tostring(spellID)] ) then return end
+
+ local auraConfig = Indicators.auraConfig[name] or Indicators.auraConfig[spellID]
+
+ -- Only player auras
+ if( auraConfig.player and not playerUnits[caster] ) then return end
+
+ local indicator = auraConfig and frame.auraIndicators[auraConfig.indicator]
+
+ -- No indicator or not enabled
+ if( not indicator or not indicator.enabled ) then return end
+ -- Missing aura only
+ if( auraConfig.missing ) then return end
+
+ -- Disabled on a class level
+ if( ShadowUF.db.profile.auraIndicators.disabled[playerClass][name] ) then return end
+ -- Disabled aura group by unit
+ if( ShadowUF.db.profile.units[frame.unitType].auraIndicators[auraConfig.group] ) then return end
+
+
+ -- If the indicator is not restricted to the player only, then will give the player a slightly higher priority
+ local priority = auraConfig.priority
+ local color = auraConfig
+ if( not auraConfig.player and playerUnits[caster] ) then
+ priority = priority + 0.1
+ color = auraConfig.selfColor or auraConfig
+ end
+
+ if( priority <= indicator.priority ) then return end
+
+ indicator.showStack = ShadowUF.db.profile.auraIndicators.indicators[auraConfig.indicator].showStack
+ indicator.priority = priority
+ indicator.showIcon = auraConfig.icon
+ indicator.showDuration = auraConfig.duration
+ indicator.spellDuration = duration
+ indicator.spellEnd = endTime
+ indicator.spellIcon = texture
+ indicator.spellName = name
+ indicator.spellStack = count
+ indicator.colorR = color.r
+ indicator.colorG = color.g
+ indicator.colorB = color.b
+
+ return true
+end
+
+local auraList = {}
+local function scanAuras(frame, filter, type)
+ local isFriendly = not UnitIsEnemy(frame.unit, "player")
+
+ local index = 0
+ while( true ) do
+ index = index + 1
+ local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = UnitAura(frame.unit, index, filter)
+ if( not name ) then return end
+
+ local result = checkFilterAura(frame, type, isFriendly, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff)
+ if( not result ) then
+ checkSpecificAura(frame, type, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff)
+ end
+
+ auraList[name] = true
+ end
+end
+
+function Indicators:UpdateIndicators(frame)
+ for key, indicatorConfig in pairs(ShadowUF.db.profile.auraIndicators.indicators) do
+ local indicator = frame.auraIndicators[key]
+ if( indicator and indicator.enabled and indicator.priority and indicator.priority > -1 ) then
+ -- Show a cooldown ring
+ if( indicator.showDuration and indicator.spellDuration > 0 and indicator.spellEnd > 0 ) then
+ indicator.cooldown:SetCooldown(indicator.spellEnd - indicator.spellDuration, indicator.spellDuration)
+ else
+ indicator.cooldown:Hide()
+ end
+
+ -- Show either the icon, or a solid color
+ if( indicator.showIcon and indicator.spellIcon ) then
+ indicator.texture:SetTexture(indicator.spellIcon)
+ indicator:SetBackdropColor(0, 0, 0, 0)
+ else
+ indicator.texture:SetColorTexture(indicator.colorR, indicator.colorG, indicator.colorB)
+ indicator:SetBackdropColor(0, 0, 0, 1)
+ end
+
+ -- Show aura stack
+ if( indicator.showStack and indicator.spellStack > 1 ) then
+ indicator.stack:SetText(indicator.spellStack)
+ indicator.stack:Show()
+ else
+ indicator.stack:Hide()
+ end
+
+ indicator:Show()
+ else
+ indicator:Hide()
+ end
+ end
+end
+
+function Indicators:UpdateAuras(frame)
+ for k in pairs(auraList) do auraList[k] = nil end
+ for key, config in pairs(ShadowUF.db.profile.auraIndicators.indicators) do
+ local indicator = frame.auraIndicators[key]
+ if( indicator ) then
+ indicator.priority = -1
+
+ if( UnitIsEnemy(frame.unit, "player") ) then
+ indicator.enabled = config.hostile
+ else
+ indicator.enabled = config.friendly
+ end
+ end
+ end
+
+ -- If they are dead, don't bother showing any indicators yet
+ if( UnitIsDeadOrGhost(frame.unit) or not UnitIsConnected(frame.unit) ) then
+ self:UpdateIndicators(frame)
+ return
+ end
+
+ -- Scan auras
+ scanAuras(frame, "HELPFUL", "buffs")
+ scanAuras(frame, "HARMFUL", "debuffs")
+
+ -- Check for any indicators that are triggered due to something missing
+ for name in pairs(ShadowUF.db.profile.auraIndicators.missing) do
+ if( not auraList[name] and self.auraConfig[name] ) then
+ local aura = self.auraConfig[name]
+ local indicator = frame.auraIndicators[aura.indicator]
+ if( indicator and indicator.enabled and aura.priority > indicator.priority and not ShadowUF.db.profile.auraIndicators.disabled[playerClass][name] ) then
+ indicator.priority = aura.priority or -1
+ indicator.showIcon = aura.icon
+ indicator.showDuration = aura.duration
+ indicator.spellDuration = 0
+ indicator.spellEnd = 0
+ indicator.spellIcon = aura.iconTexture or select(3, GetSpellInfo(name))
+ indicator.colorR = aura.r
+ indicator.colorG = aura.g
+ indicator.colorB = aura.b
+ end
+ end
+ end
+
+ -- Now force the indicators to update
+ self:UpdateIndicators(frame)
+end
\ No newline at end of file
diff --git a/modules/aurapoints.lua b/modules/aurapoints.lua
new file mode 100755
index 000000000..006cfeca9
--- /dev/null
+++ b/modules/aurapoints.lua
@@ -0,0 +1,29 @@
+local AuraPoints = setmetatable({
+ isComboPoints = true,
+ spells = {
+ --["MAGE"] = {max = 4, name = GetSpellInfo(36032), filter = "HARMFUL"},
+ }
+}, {__index = ShadowUF.ComboPoints})
+
+local trackSpell = AuraPoints.spells[select(2, UnitClass("player"))]
+if( not trackSpell or not trackSpell.name ) then return end
+
+ShadowUF:RegisterModule(AuraPoints, "auraPoints", ShadowUF.L["Aura Combo Points"])
+local auraConfig = {max = trackSpell.max, key = "auraPoints", colorKey = "AURAPOINTS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"}
+
+function AuraPoints:OnEnable(frame)
+ frame.auraPoints = frame.auraPoints or CreateFrame("Frame", nil, frame)
+ frame.auraPoints.cpConfig = auraConfig
+ frame.comboPointType = auraConfig.key
+
+ frame:RegisterUnitEvent("UNIT_AURA", self, "Update")
+ frame:RegisterUpdateFunc(self, "Update")
+end
+
+function AuraPoints:GetComboPointType()
+ return "auraPoints"
+end
+
+function AuraPoints:GetPoints(unit)
+ return select(3, ShadowUF.UnitAuraBySpell("player", trackSpell.name, trackSpell.filter)) or 0
+end
\ No newline at end of file
diff --git a/modules/auras.lua b/modules/auras.lua
old mode 100644
new mode 100755
index 50e6415be..6e13fbbd7
--- a/modules/auras.lua
+++ b/modules/auras.lua
@@ -1,8 +1,7 @@
local Auras = {}
-local stealableColor = {r = 1, g = 1, b = 1}
local playerUnits = {player = true, vehicle = true, pet = true}
-local mainHand, offHand = {time = 0}, {time = 0}
-local tempEnchantScan
+local mainHand, offHand, ranged, tempEnchantScan = {time = 0}, {time = 0}, {time = 0}
+local canCure = ShadowUF.Units.canCure
ShadowUF:RegisterModule(Auras, "auras", ShadowUF.L["Auras"])
function Auras:OnEnable(frame)
@@ -57,6 +56,7 @@ local positionData = setmetatable({}, {
data.initialAnchor = load(string.format([[return function(button, offset)
button:ClearAllPoints()
button:SetPoint(button.point, button.anchorTo, button.relativePoint, button.xOffset%s, button.yOffset%s)
+ button.anchorOffset = offset
end]], initialXOffset, initialYOffset))
data.column = load(string.format([[return function(button, positionTo, offset)
button:ClearAllPoints()
@@ -72,13 +72,13 @@ local positionData = setmetatable({}, {
end,
})
-local function positionButton(id, group, config)
+local function positionButton(id, group, config)
local position = positionData[group.forcedAnchorPoint or config.anchorPoint]
local button = group.buttons[id]
button.isAuraAnchor = nil
-- Alright, in order to find out where an aura group is going to be anchored to certain buttons need
- -- to be flagged as suitable anchors visually, this speeds it up bcause this data is cached and doesn't
+ -- to be flagged as suitable anchors visually, this speeds it up because this data is cached and doesn't
-- have to be recalculated unless auras are specifically changed
if( id > 1 ) then
if( position.isSideGrowth and id <= config.perRow ) then
@@ -101,15 +101,17 @@ local function positionButton(id, group, config)
button.xOffset = config.x + (position.xMod * ShadowUF.db.profile.backdrop.inset)
button.yOffset = config.y + (position.yMod * ShadowUF.db.profile.backdrop.inset)
button.anchorTo = group.anchorTo
-
+
position.initialAnchor(button, 0)
end
end
-
+--[[
+ cartok: maybe this is, where the time sorting addition needs to get implemented.
+]]
local columnsHaveScale = {}
local function positionAllButtons(group, config)
- local position = positionData[group.forcedAnchorPoint or config.anchorPoint]
+ local position = positionData[group.forcedAnchorPoint or config.anchorPoint]
-- Figure out which columns have scaling so we can work out positioning
local columnID = 0
@@ -154,22 +156,27 @@ local function positionAllButtons(group, config)
offset = offset + 1
end
- --print(columnID, math.ceil(offset))
position.column(button, anchorButton, math.ceil(offset))
else
position.aura(button, group.buttons[id - 1])
end
- -- If the initial column is self scaled, but the initial anchor isn't, will have to reposition it
- elseif( columnsHaveScale[columnID] ) then
- local offset = math.ceil(columnsHaveScale[columnID] / 8)
- if( button.isSelfScaled ) then
- offset = -(offset / 2)
- else
- offset = offset + 2
+ else
+ -- If the initial column is self scaled, but the initial anchor isn't, will have to reposition it
+ local offset = 0
+ if( columnsHaveScale[columnID] ) then
+ offset = math.ceil(columnsHaveScale[columnID] / 8)
+ if( button.isSelfScaled ) then
+ offset = -(offset / 2)
+ else
+ offset = offset + 2
+ end
+
+ offset = offset
+ end
+
+ if( offset ~= button.anchorOffset ) then
+ position.initialAnchor(button, offset)
end
-
- --print(1, offset)
- position.initialAnchor(button, offset)
end
end
end
@@ -177,13 +184,14 @@ end
-- Aura button functions
-- Updates the X seconds left on aura tooltip while it's shown
local function updateTooltip(self)
- if( GameTooltip:IsOwned(self) ) then
+ if( not GameTooltip:IsForbidden() and GameTooltip:IsOwned(self) ) then
GameTooltip:SetUnitAura(self.unit, self.auraID, self.filter)
end
end
local function showTooltip(self)
if( not ShadowUF.db.profile.locked ) then return end
+ if( GameTooltip:IsForbidden() ) then return end
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT")
if( self.filter == "TEMP" ) then
@@ -197,17 +205,25 @@ end
local function hideTooltip(self)
self:SetScript("OnUpdate", nil)
- GameTooltip:Hide()
+ if not GameTooltip:IsForbidden() then
+ GameTooltip:Hide()
+ end
end
-local function cancelBuff(self)
- if( not ShadowUF.db.profile.locked ) then return end
-
- if( self.filter == "TEMP" ) then
- CancelItemTempEnchantment(self.auraID - 15)
- else
- CancelUnitBuff(self.unit, self.auraID, self.filter)
+--[[
+ cartok: add a handler to blacklist buffs/debuffs on a extra blacklist
+ - every unit frame should have this extra blacklist
+ - ... bigger plan inc.
+]]
+local function addAuraToBlacklist(self, mouse)
+end
+
+local function cancelAura(self, mouse)
+ if( mouse ~= "RightButton" or ( not UnitIsUnit(self.parent.unit, "player") and not UnitIsUnit(self.parent.unit, "vehicle") ) or InCombatLockdown() or self.filter == "TEMP" ) then
+ return
end
+
+ CancelUnitBuff(self.parent.unit, self.auraID, self.filter)
end
local function updateButton(id, group, config)
@@ -218,14 +234,16 @@ local function updateButton(id, group, config)
button = group.buttons[id]
button:SetScript("OnEnter", showTooltip)
button:SetScript("OnLeave", hideTooltip)
- button:SetScript("OnClick", cancelBuff)
button:RegisterForClicks("RightButtonUp")
- button.cooldown = CreateFrame("Cooldown", nil, button)
+ -- cartok: should check if these features are enabled or if omnicc is used.
+ button.cooldown = CreateFrame("Cooldown", group.parent:GetName() .. "Aura" .. group.type .. id .. "Cooldown", button, "CooldownFrameTemplate")
button.cooldown:SetAllPoints(button)
button.cooldown:SetReverse(true)
- button.cooldown:SetFrameLevel(7)
- button.cooldown:Hide()
+ button.cooldown:SetDrawEdge(false)
+ button.cooldown:SetDrawSwipe(true)
+ button.cooldown:SetSwipeColor(0, 0, 0, 0.8)
+ button.cooldown:Hide()
button.stack = button:CreateFontString(nil, "OVERLAY")
button.stack:SetFont("Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf", 10, "OUTLINE")
@@ -238,7 +256,7 @@ local function updateButton(id, group, config)
button.stack:SetJustifyH("RIGHT")
button.border = button:CreateTexture(nil, "OVERLAY")
- button.border:SetPoint("CENTER", button)
+ button.border:SetPoint("CENTER", button)
button.icon = button:CreateTexture(nil, "BACKGROUND")
button.icon:SetAllPoints(button)
@@ -259,10 +277,16 @@ local function updateButton(id, group, config)
-- Set the button sizing
button.cooldown.noCooldownCount = ShadowUF.db.profile.omnicc
+ button.cooldown:SetHideCountdownNumbers(ShadowUF.db.profile.blizzardcc)
button:SetHeight(config.size)
button:SetWidth(config.size)
button.border:SetHeight(config.size + 1)
button.border:SetWidth(config.size + 1)
+ button.stack:SetFont("Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf", math.floor((config.size * 0.60) + 0.5), "OUTLINE")
+
+ button:SetScript("OnClick", cancelAura)
+
+ button.parent = group.parent
button:ClearAllPoints()
button:Hide()
@@ -286,7 +310,7 @@ local function updateGroup(self, type, config, reverseConfig)
group.type = type
group.parent = self
group.anchorTo = self
- group:SetFrameLevel(5)
+ group:SetFrameLevel(self.highFrame:GetFrameLevel() + 1)
group:Show()
-- If debuffs are anchored to buffs, debuffs need to grow however buffs do
@@ -297,6 +321,7 @@ local function updateGroup(self, type, config, reverseConfig)
if( self.unit == "player" ) then
mainHand.time = 0
offHand.time = 0
+ ranged.time = 0
group:SetScript("OnUpdate", config.temporary and tempEnchantScan or nil)
else
@@ -305,13 +330,12 @@ local function updateGroup(self, type, config, reverseConfig)
-- Update filters used for the anchor
group.filter = group.type == "buffs" and "HELPFUL" or group.type == "debuffs" and "HARMFUL" or ""
-
- -- This is a bit of an odd filter, when used with a HELPFUL filter, it will only return buffs you can cast on group members
- -- When used with HARMFUL it will only return debuffs you can cure
- if( config.raid ) then
- group.filter = group.filter .. "|RAID"
- end
+ --[[
+ cartok: add time sorting here?
+ - setting it to descending/ascending will mean the aura with the longest/shortest
+ - duration will be the first/last, and the aura vanishing soonest will be last/fist.
+ ]]
for id, button in pairs(group.buttons) do
updateButton(id, group, config)
end
@@ -368,12 +392,13 @@ end
-- Temporary enchant support
local timeElapsed = 0
-local function updateTemporaryEnchant(frame, slot, tempData, hasEnchant, timeLeft, charges)
+local function updateTemporaryEnchant(frame, slot, tempData, hasEnchant, enchantId, timeLeft, charges)
-- If there's less than a 750 millisecond differences in the times, we don't need to bother updating.
-- Any sort of enchant takes more than 0.750 seconds to cast so it's impossible for the user to have two
-- temporary enchants with that little difference, as totems don't really give pulsing auras anymore.
- if( tempData.has and ( timeLeft < tempData.time and ( tempData.time - timeLeft ) < 750 ) and charges == tempData.charges ) then return false end
-
+ charges = charges or 0
+ if( tempData.has and tempData.enchantId == enchantId and ( timeLeft < tempData.time and ( tempData.time - timeLeft ) < 750 ) ) then return false end
+
-- Some trickys magic, we can't get the start time of temporary enchants easily.
-- So will save the first time we find when a new enchant is added
if( timeLeft > tempData.time or not tempData.has ) then
@@ -383,7 +408,8 @@ local function updateTemporaryEnchant(frame, slot, tempData, hasEnchant, timeLef
tempData.has = hasEnchant
tempData.time = timeLeft
tempData.charges = charges
-
+ tempData.enchantId = enchantId
+
local config = ShadowUF.db.profile.units[frame.parent.unitType].auras[frame.type]
-- Create any buttons we need
@@ -403,7 +429,7 @@ local function updateTemporaryEnchant(frame, slot, tempData, hasEnchant, timeLef
end
-- Enlarge our own auras
- if( config.enlargeSelf and caster == ShadowUF.playerUnit ) then
+ if( config.enlarge.SELF ) then
button.isSelfScaled = true
button:SetScale(config.selfScale)
else
@@ -430,16 +456,29 @@ end
-- Unfortunately, temporary enchants have basically no support beyond hacks. So we will hack!
tempEnchantScan = function(self, elapsed)
+ if( self.parent.unit == self.parent.vehicleUnit and self.lastTemporary > 0 ) then
+ mainHand.has = false
+ offHand.has = false
+ ranged.has = false
+
+ self.temporaryEnchants = 0
+ self.lastTemporary = 0
+
+ Auras:Update(self.parent)
+ return
+ end
+
timeElapsed = timeElapsed + elapsed
if( timeElapsed < 0.50 ) then return end
timeElapsed = timeElapsed - 0.50
- local hasMain, mainTimeLeft, mainCharges, hasOff, offTimeLeft, offCharges = GetWeaponEnchantInfo()
+
+ local hasMain, mainTimeLeft, mainCharges, mainEnchantId, hasOff, offTimeLeft, offCharges, offEnchantId = GetWeaponEnchantInfo()
self.temporaryEnchants = 0
if( hasMain ) then
self.temporaryEnchants = self.temporaryEnchants + 1
- updateTemporaryEnchant(self, 16, mainHand, hasMain, mainTimeLeft or 0, mainCharges)
+ updateTemporaryEnchant(self, 16, mainHand, hasMain, mainEnchantId, mainTimeLeft or 0, mainCharges)
mainHand.time = mainTimeLeft or 0
end
@@ -447,7 +486,7 @@ tempEnchantScan = function(self, elapsed)
if( hasOff and self.temporaryEnchants < self.maxAuras ) then
self.temporaryEnchants = self.temporaryEnchants + 1
- updateTemporaryEnchant(self, 17, offHand, hasOff, offTimeLeft or 0, offCharges)
+ updateTemporaryEnchant(self, 17, offHand, hasOff, offEnchantId, offTimeLeft or 0, offCharges)
offHand.time = offTimeLeft or 0
end
@@ -466,88 +505,171 @@ end
-- This isn't actually filled with data, it's just to stop any errors from triggering if no filter is added
local filterDefault = {}
function Auras:UpdateFilter(frame)
- local zone = select(2, IsInInstance())
+ local zone = select(2, IsInInstance()) or "none"
+ if( zone == "scenario" ) then zone = "party" end
+
local id = zone .. frame.unitType
local white = ShadowUF.db.profile.filters.zonewhite[zone .. frame.unitType]
local black = ShadowUF.db.profile.filters.zoneblack[zone .. frame.unitType]
+ local override = ShadowUF.db.profile.filters.zoneoverride[zone .. frame.unitType]
frame.auras.whitelist = white and ShadowUF.db.profile.filters.whitelists[white] or filterDefault
frame.auras.blacklist = black and ShadowUF.db.profile.filters.blacklists[black] or filterDefault
+ frame.auras.overridelist = override and ShadowUF.db.profile.filters.overridelists[override] or filterDefault
end
--- Scan for auras
-local function scan(parent, frame, type, config, filter)
- if( frame.totalAuras >= frame.maxAuras or not config.enabled ) then return end
+local function categorizeAura(type, curable, auraType, caster, isRemovable, canApplyAura, isBossDebuff)
+ -- Player casted it
+ if( playerUnits[caster] ) then
+ return "player"
+ -- Boss aura
+ elseif( isBossDebuff ) then
+ return "boss"
+ -- Can dispell, curable checks type already
+ elseif( curable and canCure[auraType] ) then
+ return "raid"
+ -- Can apply it ourselves
+ elseif( type == "buffs" and canApplyAura ) then
+ return "raid"
+ -- Can be stolen/purged (dispellable)
+ elseif( type == "debuffs" and isRemovable ) then
+ return "raid"
+ else
+ return "misc"
+ end
+end
+
+local function renderAura(parent, frame, type, config, displayConfig, index, filter, isFriendly, curable, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff)
+ -- aura filters are all saved as strings, so need to override here
+ spellID = tostring(spellID)
+ -- Do our initial list check to see if we can quick filter it out
+ if( parent.whitelist[type] and not parent.whitelist[name] and not parent.whitelist[spellID] ) then return end
+ if( parent.blacklist[type] and ( parent.blacklist[name] or parent.blacklist[spellID] ) ) then return end
- local isFriendly = UnitIsFriend(frame.parent.unit, "player")
- local index = 0
- while( true ) do
- index = index + 1
- local name, rank, texture, count, auraType, duration, endTime, caster, isStealable = UnitAura(frame.parent.unit, index, filter)
- if( not name ) then break end
+ -- Now do our type filter
+ local category = categorizeAura(type, curable, auraType, caster, isRemovable, canApplyAura, isBossDebuff)
+ -- check override and type filters
+ if( not ( parent.overridelist[type] and ( parent.overridelist[name] or parent.overridelist[spellID] ) ) and not config.show[category] and (not config.show.relevant or (type == "debuffs") ~= isFriendly) ) then return end
+
+ -- Create any buttons we need
+ frame.totalAuras = frame.totalAuras + 1
+ if( #(frame.buttons) < frame.totalAuras ) then
+ updateButton(frame.totalAuras, frame, ShadowUF.db.profile.units[frame.parent.unitType].auras[frame.type])
+ end
- if( ( not config.player or playerUnits[caster] ) and ( not parent.whitelist[type] and not parent.blacklist[type] or parent.whitelist[type] and parent.whitelist[name] or parent.blacklist[type] and not parent.blacklist[name] ) ) then
- -- Create any buttons we need
- frame.totalAuras = frame.totalAuras + 1
- if( #(frame.buttons) < frame.totalAuras ) then
- updateButton(frame.totalAuras, frame, ShadowUF.db.profile.units[frame.parent.unitType].auras[frame.type])
- end
-
- -- Show debuff border, or a special colored border if it's stealable
- local button = frame.buttons[frame.totalAuras]
- if( isStealable and not isFriendly and not ShadowUF.db.profile.auras.disableColor ) then
- button.border:SetVertexColor(stealableColor.r, stealableColor.g, stealableColor.b)
- elseif( ( not isFriendly or type == "debuffs" ) and not ShadowUF.db.profile.auras.disableColor ) then
- local color = auraType and DebuffTypeColor[auraType] or DebuffTypeColor.none
- button.border:SetVertexColor(color.r, color.g, color.b)
- else
- button.border:SetVertexColor(0.60, 0.60, 0.60)
- end
-
- -- Show the cooldown ring
- if( not ShadowUF.db.profile.auras.disableCooldown and duration > 0 and endTime > 0 and ( not config.selfTimers or ( config.selfTimers and playerUnits[caster] ) ) ) then
- button.cooldown:SetCooldown(endTime - duration, duration)
- button.cooldown:Show()
+ -- Show debuff border, or a special colored border if it's stealable
+ local button = frame.buttons[frame.totalAuras]
+ if( isRemovable and not isFriendly and not ShadowUF.db.profile.auras.disableColor ) then
+ button.border:SetVertexColor(ShadowUF.db.profile.auraColors.removable.r, ShadowUF.db.profile.auraColors.removable.g, ShadowUF.db.profile.auraColors.removable.b)
+ elseif( ( not isFriendly or type == "debuffs" ) and not ShadowUF.db.profile.auras.disableColor ) then
+ local color = auraType and DebuffTypeColor[auraType] or DebuffTypeColor.none
+ button.border:SetVertexColor(color.r, color.g, color.b)
+ else
+ button.border:SetVertexColor(0.60, 0.60, 0.60)
+ end
+
+ -- Show the cooldown ring
+ if( not ShadowUF.db.profile.auras.disableCooldown and duration > 0 and endTime > 0 and ( config.timers.ALL or ( category == "player" and config.timers.SELF ) or ( category == "boss" and config.timers.BOSS ) ) ) then
+ button.cooldown:SetCooldown(endTime - duration, duration)
+ button.cooldown:Show()
+ else
+ button.cooldown:Hide()
+ end
+
+ -- Enlarge auras
+ if( ( category == "player" and config.enlarge.SELF ) or ( category == "boss" and config.enlarge.BOSS ) or ( config.enlarge.REMOVABLE and ( ( isRemovable and not isFriendly ) or ( curable and canCure[auraType]) ) ) ) then
+ button.isSelfScaled = true
+ button:SetScale(config.selfScale)
+ else
+ button.isSelfScaled = nil
+ button:SetScale(1)
+ end
+
+ -- Size it
+ button:SetHeight(config.size)
+ button:SetWidth(config.size)
+ button.border:SetHeight(config.size + 1)
+ button.border:SetWidth(config.size + 1)
+
+ -- Stack + icon + show! Never understood why, auras sometimes return 1 for stack even if they don't stack
+ button.auraID = index
+ button.filter = filter
+ button.unit = frame.parent.unit
+ button.columnHasScaled = nil
+ button.previousHasScale = nil
+ button.icon:SetTexture(texture)
+ button.stack:SetText(count > 1 and count or "")
+ button:Show()
+end
+
+
+-- Scan for auras
+local function scan(parent, frame, type, config, displayConfig, filter)
+ if( frame.totalAuras >= frame.maxAuras or not config.enabled ) then return end
+
+ -- UnitIsFriend returns true during a duel, which breaks stealable/curable detection
+ local isFriendly = not UnitIsEnemy(frame.parent.unit, "player")
+ local curable = (isFriendly and type == "debuffs")
+
+ -- get all displayable auras
+ -- sort auras by endTime if enabled
+ if(config.timeSortingEnabled and config.timeSortingMethod ~= nil) then
+ -- create table of all auras containing only save index and endTime of all auras
+ local auras = {}
+ local index = 0
+ while( frame.totalAuras <= frame.maxAuras ) do
+ index = index + 1
+ local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = UnitAura(frame.parent.unit, index, filter)
+ if( not name ) then
+ break
else
- button.cooldown:Hide()
+ -- auras with infinite duration have duration = 0 and endTime = 0
+ -- set endTime to infinity so they will be properly handled
+ if(duration == 0) then
+ endTime = math.huge
+ end
+ auras[index] = {
+ ["endTime"] = endTime,
+ ["index"] = index,
+ }
end
-
- -- Enlarge our own auras
- if( config.enlargeSelf and playerUnits[caster] ) then
- button.isSelfScaled = true
- button:SetScale(config.selfScale)
+ end
+ -- sort table by ascending endTime
+ if(config.timeSortingMethod == "ASC") then
+ table.sort(auras, function(a,b) return (a.endTime < b.endTime) end)
+ end
+ -- sort table by descending endTime
+ if(config.timeSortingMethod == "DESC") then
+ table.sort(auras, function(a,b) return (a.endTime > b.endTime) end)
+ end
+ -- use ordered aura index
+ -- aura render loop
+ for _, aura in pairs(auras) do
+ local index = aura.index
+ local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = UnitAura(frame.parent.unit, index, filter)
+ renderAura(parent, frame, type, config, displayConfig, index, filter, isFriendly, curable, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff)
+ end
+ else
+ -- no time sorting
+ -- aura render loop
+ local index = 0
+ while( frame.totalAuras <= frame.maxAuras ) do
+ index = index + 1
+ local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = UnitAura(frame.parent.unit, index, filter)
+ if( not name ) then
+ break
else
- button.isSelfScaled = nil
- button:SetScale(1)
+ renderAura(parent, frame, type, config, displayConfig, index, filter, isFriendly, curable, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff)
end
-
- -- Size it
- button:SetHeight(config.size)
- button:SetWidth(config.size)
- button.border:SetHeight(config.size + 1)
- button.border:SetWidth(config.size + 1)
-
- -- Stack + icon + show! Never understood why, auras sometimes return 1 for stack even if they don't stack
- button.auraID = index
- button.filter = filter
- button.unit = frame.parent.unit
- button.columnHasScaled = nil
- button.previousHasScale = nil
- button.icon:SetTexture(texture)
- button.stack:SetText(count > 1 and count or "")
- button:Show()
-
- -- Too many auras shown break out
- -- Get down
- if( frame.totalAuras >= frame.maxAuras ) then break end
end
end
+ -- what is this for?
for i=frame.totalAuras + 1, #(frame.buttons) do frame.buttons[i]:Hide() end
-- The default 1.30 scale doesn't need special handling, after that it does
- if( config.enlargeSelf ) then
- positionAllButtons(frame, config)
+ if( config.selfScale > 1.30 ) then
+ positionAllButtons(frame, displayConfig)
end
end
@@ -561,10 +683,10 @@ local function anchorGroupToGroup(frame, config, group, childConfig, childGroup)
if( group.totalAuras == 0 ) then
local position = positionData[config.anchorPoint]
childGroup.buttons[1]:ClearAllPoints()
- childGroup.buttons[1]:SetPoint(ShadowUF.Layout:GetPoint(config.anchorPoint), group.anchorTo, ShadowUF.Layout:GetRelative(config.anchorPoint), config.x + (position.xMod * ShadowUF.db.profile.backdrop.inset), config.y + (position.yMod * -ShadowUF.db.profile.backdrop.inset))
+ childGroup.buttons[1]:SetPoint(ShadowUF.Layout:GetPoint(config.anchorPoint), group.anchorTo, ShadowUF.Layout:GetRelative(config.anchorPoint), config.x + (position.xMod * ShadowUF.db.profile.backdrop.inset), config.y + (position.yMod * ShadowUF.db.profile.backdrop.inset))
return
end
-
+
local anchorTo
for i=#(group.buttons), 1, -1 do
local button = group.buttons[i]
@@ -590,17 +712,17 @@ function Auras:Update(frame)
if( frame.auras.anchor ) then
frame.auras.anchor.totalAuras = frame.auras.anchor.temporaryEnchants
- scan(frame.auras, frame.auras.anchor, frame.auras.primary, config[frame.auras.primary], frame.auras[frame.auras.primary].filter)
- scan(frame.auras, frame.auras.anchor, frame.auras.secondary, config[frame.auras.secondary], frame.auras[frame.auras.secondary].filter)
+ scan(frame.auras, frame.auras.anchor, frame.auras.primary, config[frame.auras.primary], config[frame.auras.primary], frame.auras[frame.auras.primary].filter)
+ scan(frame.auras, frame.auras.anchor, frame.auras.secondary, config[frame.auras.secondary], config[frame.auras.primary], frame.auras[frame.auras.secondary].filter)
else
if( config.buffs.enabled ) then
frame.auras.buffs.totalAuras = frame.auras.buffs.temporaryEnchants
- scan(frame.auras, frame.auras.buffs, "buffs", config.buffs, frame.auras.buffs.filter)
+ scan(frame.auras, frame.auras.buffs, "buffs", config.buffs, config.buffs, frame.auras.buffs.filter)
end
if( config.debuffs.enabled ) then
frame.auras.debuffs.totalAuras = 0
- scan(frame.auras, frame.auras.debuffs, "debuffs", config.debuffs, frame.auras.debuffs.filter)
+ scan(frame.auras, frame.auras.debuffs, "debuffs", config.debuffs, config.debuffs, frame.auras.debuffs.filter)
end
if( frame.auras.anchorAurasOn ) then
diff --git a/modules/basecombopoints.lua b/modules/basecombopoints.lua
new file mode 100644
index 000000000..1fbdeb396
--- /dev/null
+++ b/modules/basecombopoints.lua
@@ -0,0 +1,203 @@
+local Combo = {isComboPoints = true}
+ShadowUF.ComboPoints = Combo
+
+local function createIcons(config, pointsFrame)
+ local point, relativePoint, x, y
+ local pointsConfig = pointsFrame.cpConfig
+
+ if( config.growth == "LEFT" ) then
+ point, relativePoint = "BOTTOMRIGHT", "BOTTOMLEFT"
+ x = config.spacing
+ elseif( config.growth == "UP" ) then
+ point, relativePoint = "BOTTOMLEFT", "TOPLEFT"
+ y = config.spacing
+ elseif( config.growth == "DOWN" ) then
+ point, relativePoint = "TOPLEFT", "BOTTOMLEFT"
+ y = config.spacing
+ else
+ point, relativePoint = "BOTTOMLEFT", "BOTTOMRIGHT"
+ x = config.spacing
+ end
+
+ x = x or 0
+ y = y or 0
+
+ for id=1, pointsConfig.max do
+ pointsFrame.icons[id] = pointsFrame.icons[id] or pointsFrame:CreateTexture(nil, "OVERLAY")
+ local texture = pointsFrame.icons[id]
+ texture:SetTexture(pointsConfig.icon)
+ texture:SetSize(config.size or 16, config.size or 16)
+
+ if( id > 1 ) then
+ texture:ClearAllPoints()
+ texture:SetPoint(point, pointsFrame.icons[id - 1], relativePoint, x, y)
+ else
+ texture:ClearAllPoints()
+ texture:SetPoint("CENTER", pointsFrame, "CENTER", 0, 0)
+ end
+ end
+end
+
+local function createBlocks(config, pointsFrame)
+ local pointsConfig = pointsFrame.cpConfig
+ if pointsConfig.max == 0 then return end
+ pointsFrame.visibleBlocks = pointsConfig.max
+
+ -- Position bars, the 5 accounts for borders
+ local blockWidth = (pointsFrame:GetWidth() - ((pointsConfig.max / (pointsConfig.grouping or 1)) - 1)) / pointsConfig.max
+ for id=1, pointsConfig.max do
+ pointsFrame.blocks[id] = pointsFrame.blocks[id] or pointsFrame:CreateTexture(nil, "OVERLAY")
+ local texture = pointsFrame.blocks[id]
+ local color = ShadowUF.db.profile.powerColors[pointsConfig.colorKey or "COMBOPOINTS"]
+ texture:SetVertexColor(color.r, color.g, color.b, color.a)
+ texture:SetHorizTile(false)
+ texture:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
+ texture:SetHeight(pointsFrame:GetHeight())
+ texture:SetWidth(blockWidth)
+ texture:ClearAllPoints()
+
+ if not texture.background and config.background then
+ texture.background = pointsFrame:CreateTexture(nil, "BORDER")
+ texture.background:SetHeight(1)
+ texture.background:SetWidth(1)
+ texture.background:SetAllPoints(texture)
+ texture.background:SetHorizTile(false)
+ texture.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
+ texture.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
+ end
+
+ if texture.background then
+ texture.background:SetShown(config.background)
+ end
+
+ local offset = 1
+ if pointsConfig.grouping and ((id - 1) % pointsConfig.grouping ~= 0) then
+ offset = 0
+ end
+ if( config.growth == "LEFT" ) then
+ if( id > 1 ) then
+ texture:SetPoint("TOPRIGHT", pointsFrame.blocks[id - 1], "TOPLEFT", -offset, 0)
+ else
+ texture:SetPoint("TOPRIGHT", pointsFrame, "TOPRIGHT", 0, 0)
+ end
+ else
+ if( id > 1 ) then
+ texture:SetPoint("TOPLEFT", pointsFrame.blocks[id - 1], "TOPRIGHT", offset, 0)
+ else
+ texture:SetPoint("TOPLEFT", pointsFrame, "TOPLEFT", 0, 0)
+ end
+ end
+ end
+end
+
+function Combo:OnLayoutApplied(frame, config)
+ local key = self:GetComboPointType()
+ local pointsFrame = frame[key]
+ if( not pointsFrame ) then return end
+
+ pointsFrame:SetFrameLevel(frame.topFrameLevel + 1)
+
+ local pointsConfig = pointsFrame.cpConfig
+ config = config[key]
+
+ -- Not a bar so set the containers frame configuration
+ if( config and not config.isBar ) then
+ ShadowUF.Layout:ToggleVisibility(pointsFrame, frame.visibility[key])
+ end
+
+ if( not frame.visibility[key] ) then return end
+
+ -- Hide the active combo points
+ if( pointsFrame.points ) then
+ for _, texture in pairs(pointsFrame.points) do
+ texture:Hide()
+ end
+ end
+
+ -- Setup for bar display!
+ if( config.isBar ) then
+ pointsFrame.blocks = pointsFrame.blocks or {}
+ pointsFrame.points = pointsFrame.blocks
+
+ createBlocks(config, pointsFrame, pointsConfig.max)
+
+ -- guess not, will have to do icons :(
+ else
+ pointsFrame.icons = pointsFrame.icons or {}
+ pointsFrame.points = pointsFrame.icons
+
+ createIcons(config, pointsFrame, pointsConfig.max)
+
+ -- Position the main frame
+ pointsFrame:SetSize(0.1, 0.1)
+
+ ShadowUF.Layout:AnchorFrame(frame, pointsFrame, config)
+ end
+end
+
+function Combo:OnDisable(frame)
+ frame:UnregisterAll(self)
+end
+
+function Combo:UpdateBarBlocks(frame, event, unit, powerType)
+ local key = self:GetComboPointType()
+ local pointsFrame = frame[key]
+ if( not pointsFrame or not pointsFrame.cpConfig.eventType or not pointsFrame.blocks ) then return end
+ if( event and powerType ~= pointsFrame.cpConfig.eventType ) then return end
+
+ local max = self.GetMaxPoints and self:GetMaxPoints() or UnitPowerMax("player", pointsFrame.cpConfig.powerType)
+ if( max == 0 or pointsFrame.visibleBlocks == max ) then return end
+
+ pointsFrame.cpConfig.max = max
+
+ if( not ShadowUF.db.profile.units[frame.unitType][key].isBar ) then
+ createIcons(ShadowUF.db.profile.units[frame.unitType][key], pointsFrame)
+ pointsFrame.visibleBlocks = max
+ return
+ else
+ createBlocks(ShadowUF.db.profile.units[frame.unitType][key], pointsFrame)
+ pointsFrame.visibleBlocks = max
+ end
+
+ local blockWidth = (pointsFrame:GetWidth() - (max - 1)) / max
+ for id=1, max do
+ pointsFrame.blocks[id]:SetWidth(blockWidth)
+ pointsFrame.blocks[id]:Show()
+ end
+
+ for id=max+1, #pointsFrame.blocks do
+ pointsFrame.blocks[id]:Hide()
+ end
+
+end
+
+function Combo:Update(frame, event, unit, powerType)
+ local key = self:GetComboPointType()
+ -- Anything power based will have an eventType to filter on
+ if( event and frame[key].cpConfig.eventType and frame[key].cpConfig.eventType ~= powerType ) then return end
+
+ local points = self:GetPoints(unit)
+
+ -- Bar display, hide it if we don't have any combo points
+ if( ShadowUF.db.profile.units[frame.unitType][key].isBar ) then
+ ShadowUF.Layout:SetBarVisibility(frame, key, ShadowUF.db.profile.units[frame.unitType][key].showAlways or (points and points > 0))
+ end
+
+ for id, pointTexture in pairs(frame[key].points) do
+ if( id <= points ) then
+ pointTexture:Show()
+ else
+ pointTexture:Hide()
+ end
+ end
+end
+
+function Combo:OnLayoutWidgets(frame)
+ local key = self:GetComboPointType()
+ if( not frame.visibility[key] or not ShadowUF.db.profile.units[frame.unitType][key].isBar or not frame[key].blocks) then return end
+
+ local height = frame[key]:GetHeight()
+ for _, block in pairs(frame[key].blocks) do
+ block:SetHeight(height)
+ end
+end
diff --git a/modules/cast.lua b/modules/cast.lua
index 92457eaaa..f39893270 100755
--- a/modules/cast.lua
+++ b/modules/cast.lua
@@ -1,20 +1,15 @@
local Cast = {}
local L = ShadowUF.L
local FADE_TIME = 0.30
-local FAKE_UPDATE_TIME = 0.10
ShadowUF:RegisterModule(Cast, "castBar", L["Cast bar"], true)
-- I'm not really thrilled with this method of detecting fake unit casts, mostly because it's inefficient and ugly
-local function monitorFakeCast(self, elapsed)
- self.timeElapsed = self.timeElapsed + elapsed
- if( self.timeElapsed <= FAKE_UPDATE_TIME ) then return end
- self.timeElapsed = self.timeElapsed - FAKE_UPDATE_TIME
-
- local spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitCastingInfo(self.parent.unit)
+local function monitorFakeCast(self)
+ local spell, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(self.parent.unit)
local isChannelled
if( not spell ) then
- spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitChannelInfo(self.parent.unit)
+ spell, displayName, icon, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(self.parent.unit)
isChannelled = true
end
@@ -23,11 +18,12 @@ local function monitorFakeCast(self, elapsed)
self.endTime = endTime
self.notInterruptible = notInterruptible
self.spellName = spell
- Cast:UpdateCast(self.parent, self.parent.unit, isChannelled, spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible)
+ self.spellID = spellID
+ Cast:UpdateCast(self.parent, self.parent.unit, isChannelled, spell, displayName, icon, startTime, endTime, isTradeSkill, notInterruptible, spellID, castID)
-- Cast stopped
elseif( self.endTime and not endTime ) then
if( GetTime() <= (self.endTime / 1000) ) then
- Cast:EventInterruptCast(self.parent, nil, self.parent.unit, self.spellName)
+ Cast:EventInterruptCast(self.parent, nil, self.parent.unit, nil, self.spellID)
end
self.notInterruptible = nil
@@ -39,7 +35,7 @@ local function monitorFakeCast(self, elapsed)
-- Cast delayed
if( self.endTime and endTime ~= self.endTime ) then
self.endTime = endTime
- Cast:UpdateDelay(self.parent, spell, rank, displayName, icon, startTime, endTime)
+ Cast:UpdateDelay(self.parent, spell, displayName, icon, startTime, endTime)
end
-- Cast interruptible status changed
@@ -53,12 +49,18 @@ local function monitorFakeCast(self, elapsed)
end
end
-local function updateFakeUnitCast(self)
- self.endTime = nil
- self.notInterruptible = nil
- self.spellName = nil
-
- monitorFakeCast(self, FAKE_UPDATE_TIME)
+local function createFakeCastMonitor(frame)
+ if( not frame.castBar.monitor ) then
+ frame.castBar.monitor = C_Timer.NewTicker(0.10, monitorFakeCast)
+ frame.castBar.monitor.parent = frame
+ end
+end
+
+local function cancelFakeCastMonitor(frame)
+ if( frame.castBar and frame.castBar.monitor ) then
+ frame.castBar.monitor:Cancel()
+ frame.castBar.monitor = nil
+ end
end
function Cast:OnEnable(frame)
@@ -67,6 +69,7 @@ function Cast:OnEnable(frame)
frame.castBar.bar = ShadowUF.Units:CreateBar(frame)
frame.castBar.background = frame.castBar.bar.background
frame.castBar.bar.parent = frame
+ frame.castBar.bar.background = frame.castBar.background
frame.castBar.icon = frame.castBar.bar:CreateTexture(nil, "ARTWORK")
frame.castBar.bar.name = frame.castBar.bar:CreateFontString(nil, "ARTWORK")
@@ -74,12 +77,8 @@ function Cast:OnEnable(frame)
end
if( ShadowUF.fakeUnits[frame.unitType] ) then
- frame.castBar.monitor = frame.castBar.monitor or CreateFrame("Frame", nil, frame)
- frame.castBar.monitor.timeElapsed = 0
- frame.castBar.monitor.parent = frame
- frame.castBar.monitor:SetScript("OnUpdate", monitorFakeCast)
- frame.castBar.monitor:SetScript("OnShow", updateFakeUnitCast)
- frame.castBar.monitor:Show()
+ createFakeCastMonitor(frame)
+ frame:RegisterUpdateFunc(self, "UpdateFakeCast")
return
end
@@ -92,7 +91,7 @@ function Cast:OnEnable(frame)
frame:RegisterUnitEvent("UNIT_SPELLCAST_CHANNEL_START", self, "EventUpdateChannel")
frame:RegisterUnitEvent("UNIT_SPELLCAST_CHANNEL_STOP", self, "EventStopCast")
- frame:RegisterUnitEvent("UNIT_SPELLCAST_CHANNEL_INTERRUPTED", self, "EventInterruptCast")
+ --frame:RegisterUnitEvent("UNIT_SPELLCAST_CHANNEL_INTERRUPTED", self, "EventInterruptCast")
frame:RegisterUnitEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", self, "EventDelayChannel")
frame:RegisterUnitEvent("UNIT_SPELLCAST_INTERRUPTIBLE", self, "EventInterruptible")
@@ -111,6 +110,10 @@ function Cast:OnLayoutApplied(frame, config)
frame.castBar.background:SetVertexColor(0, 0, 0, 0)
frame.castBar.background:SetHorizTile(false)
+ -- Setup fill
+ frame.castBar.bar:SetOrientation(config.castBar.vertical and "VERTICAL" or "HORIZONTAL")
+ frame.castBar.bar:SetReverseFill(config.castBar.reverse and true or false)
+
-- Setup the main bar + icon
frame.castBar.bar:ClearAllPoints()
frame.castBar.bar:SetHeight(frame.castBar:GetHeight())
@@ -174,7 +177,8 @@ function Cast:OnDisable(frame, unit)
frame:UnregisterAll(self)
if( frame.castBar ) then
- if( frame.castBar.monitor ) then frame.castBar.monitor:Hide() end
+ cancelFakeCastMonitor(frame)
+
frame.castBar.bar.name:Hide()
frame.castBar.bar.time:Hide()
frame.castBar.bar:Hide()
@@ -183,11 +187,7 @@ end
-- Easy coloring
local function setBarColor(self, r, g, b)
- self:SetStatusBarColor(r, g, b, ShadowUF.db.profile.bars.alpha)
-
- if( not self.background.overrideColor ) then
- self.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
+ self.parent:SetBlockColor(self, "castBar", r, g, b)
end
-- Cast OnUpdates
@@ -277,9 +277,11 @@ end
function Cast:UpdateCurrentCast(frame)
if( UnitCastingInfo(frame.unit) ) then
- self:UpdateCast(frame, frame.unit, false, UnitCastingInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(frame.unit)
+ self:UpdateCast(frame, frame.unit, false, name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID, castID)
elseif( UnitChannelInfo(frame.unit) ) then
- self:UpdateCast(frame, frame.unit, true, UnitChannelInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(frame.unit)
+ self:UpdateCast(frame, frame.unit, true, name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID)
else
if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then
ShadowUF.Layout:SetBarVisibility(frame, "castBar", false)
@@ -296,36 +298,43 @@ end
-- Cast updated/changed
function Cast:EventUpdateCast(frame)
- self:UpdateCast(frame, frame.unit, false, UnitCastingInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(frame.unit)
+ self:UpdateCast(frame, frame.unit, false, name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID, castID)
end
function Cast:EventDelayCast(frame)
- self:UpdateDelay(frame, UnitCastingInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(frame.unit)
+ self:UpdateDelay(frame, name, text, texture, startTime, endTime)
end
-- Channel updated/changed
function Cast:EventUpdateChannel(frame)
- self:UpdateCast(frame, frame.unit, true, UnitChannelInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(frame.unit)
+ self:UpdateCast(frame, frame.unit, true, name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID)
end
function Cast:EventDelayChannel(frame)
- self:UpdateDelay(frame, UnitChannelInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(frame.unit)
+ self:UpdateDelay(frame, name, text, texture, startTime, endTime)
end
-- Cast finished
-function Cast:EventStopCast(frame, event, unit, spell)
+function Cast:EventStopCast(frame, event, unit, castID, spellID)
local cast = frame.castBar.bar
- if( cast.spellName ~= spell or ( event == "UNIT_SPELLCAST_FAILED" and cast.isChannelled ) ) then return end
+ if( event == "UNIT_SPELLCAST_CHANNEL_STOP" and not castID ) then castID = spellID end
+ if( cast.castID ~= castID or ( event == "UNIT_SPELLCAST_FAILED" and cast.isChannelled ) ) then return end
if( cast.time.enabled ) then
cast.time:SetText("0.0")
end
- setBarColor(cast, ShadowUF.db.profile.castColors.interrupted.r, ShadowUF.db.profile.castColors.interrupted.g, ShadowUF.db.profile.castColors.interrupted.b)
+ --setBarColor(cast, ShadowUF.db.profile.castColors.interrupted.r, ShadowUF.db.profile.castColors.interrupted.g, ShadowUF.db.profile.castColors.interrupted.b)
if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then
ShadowUF.Layout:SetBarVisibility(frame, "castBar", true)
end
cast.spellName = nil
+ cast.spellID = nil
+ cast.castID = nil
cast.fadeElapsed = FADE_TIME
cast.fadeStart = FADE_TIME
cast:SetScript("OnUpdate", fadeOnUpdate)
@@ -335,9 +344,9 @@ function Cast:EventStopCast(frame, event, unit, spell)
end
-- Cast interrupted
-function Cast:EventInterruptCast(frame, event, unit, spell)
+function Cast:EventInterruptCast(frame, event, unit, castID, spellID)
local cast = frame.castBar.bar
- if( cast.spellName ~= spell ) then return end
+ if( castID and cast.castID ~= castID ) then return end
setBarColor(cast, ShadowUF.db.profile.castColors.interrupted.r, ShadowUF.db.profile.castColors.interrupted.g, ShadowUF.db.profile.castColors.interrupted.b)
if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then
@@ -348,7 +357,7 @@ function Cast:EventInterruptCast(frame, event, unit, spell)
cast.name:SetText(L["Interrupted"])
end
- cast.spellName = nil
+ cast.spellID = nil
cast.fadeElapsed = FADE_TIME + 0.20
cast.fadeStart = cast.fadeElapsed
cast:SetScript("OnUpdate", fadeOnUpdate)
@@ -358,9 +367,9 @@ function Cast:EventInterruptCast(frame, event, unit, spell)
end
-- Cast succeeded
-function Cast:EventCastSucceeded(frame, unit, spell)
+function Cast:EventCastSucceeded(frame, event, unit, castID, spellID)
local cast = frame.castBar.bar
- if( not cast.isChannelled and cast.spellName == spell ) then
+ if( not cast.isChannelled and cast.castID == castID ) then
setBarColor(cast, ShadowUF.db.profile.castColors.finished.r, ShadowUF.db.profile.castColors.finished.g, ShadowUF.db.profile.castColors.finished.b)
end
end
@@ -379,7 +388,7 @@ function Cast:EventUninterruptible(frame)
setBarColor(frame.castBar.bar, ShadowUF.db.profile.castColors.uninterruptible.r, ShadowUF.db.profile.castColors.uninterruptible.g, ShadowUF.db.profile.castColors.uninterruptible.b)
end
-function Cast:UpdateDelay(frame, spell, rank, displayName, icon, startTime, endTime)
+function Cast:UpdateDelay(frame, spell, displayName, icon, startTime, endTime)
if( not spell or not frame.castBar.bar.startTime ) then return end
local cast = frame.castBar.bar
startTime = startTime / 1000
@@ -401,7 +410,7 @@ function Cast:UpdateDelay(frame, spell, rank, displayName, icon, startTime, endT
end
-- Update the actual bar
-function Cast:UpdateCast(frame, unit, channelled, spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible)
+function Cast:UpdateCast(frame, unit, channelled, spell, displayName, icon, startTime, endTime, isTradeSkill, notInterruptible, spellID, castID)
if( not spell ) then return end
local cast = frame.castBar.bar
if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then
@@ -410,15 +419,9 @@ function Cast:UpdateCast(frame, unit, channelled, spell, rank, displayName, icon
-- Set casted spell
if( ShadowUF.db.profile.units[frame.unitType].castBar.name.enabled ) then
- if( ShadowUF.db.profile.units[frame.unitType].castBar.name.rank and rank and rank ~= "" ) then
- cast.name:SetFormattedText("%s (%s)", spell, rank)
- cast.name:SetAlpha(ShadowUF.db.profile.bars.alpha)
- cast.name:Show()
- else
- cast.name:SetText(spell)
- cast.name:SetAlpha(ShadowUF.db.profile.bars.alpha)
- cast.name:Show()
- end
+ cast.name:SetText(spell)
+ cast.name:SetAlpha(ShadowUF.db.profile.bars.alpha)
+ cast.name:Show()
end
-- Show cast time
@@ -440,7 +443,8 @@ function Cast:UpdateCast(frame, unit, channelled, spell, rank, displayName, icon
cast.endSeconds = cast.endTime - cast.startTime
cast.elapsed = cast.isChannelled and cast.endSeconds or 0
cast.spellName = spell
- cast.spellRank = rank
+ cast.spellID = spellID
+ cast.castID = channelled and spellID or castID
cast.pushback = 0
cast.lastUpdate = cast.startTime
cast:SetMinMaxValues(0, cast.endSeconds)
@@ -462,3 +466,13 @@ function Cast:UpdateCast(frame, unit, channelled, spell, rank, displayName, icon
setBarColor(cast, ShadowUF.db.profile.castColors.cast.r, ShadowUF.db.profile.castColors.cast.g, ShadowUF.db.profile.castColors.cast.b)
end
end
+
+-- Trigger checks on fake cast
+function Cast:UpdateFakeCast(self)
+ local monitor = self.castBar.monitor
+ monitor.endTime = nil
+ monitor.notInterruptible = nil
+ monitor.spellName = nil
+ monitor.spellID = nil
+ monitorFakeCast(monitor)
+end
diff --git a/modules/chi.lua b/modules/chi.lua
new file mode 100755
index 000000000..fccb1a04b
--- /dev/null
+++ b/modules/chi.lua
@@ -0,0 +1,28 @@
+if( not ShadowUF.ComboPoints ) then return end
+
+local Chi = setmetatable({}, {__index = ShadowUF.ComboPoints})
+ShadowUF:RegisterModule(Chi, "chi", ShadowUF.L["Chi"], nil, "MONK", SPEC_MONK_WINDWALKER)
+local chiConfig = {max = 5, key = "chi", colorKey = "CHI", powerType = Enum.PowerType.Chi, eventType = "CHI", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"}
+
+function Chi:OnEnable(frame)
+ frame.chi = frame.chi or CreateFrame("Frame", nil, frame)
+ frame.chi.cpConfig = chiConfig
+
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks")
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "Update")
+ frame:RegisterUpdateFunc(self, "Update")
+end
+
+function Chi:OnLayoutApplied(frame, config)
+ ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config)
+ self:UpdateBarBlocks(frame)
+end
+
+function Chi:GetComboPointType()
+ return "chi"
+end
+
+function Chi:GetPoints(unit)
+ return UnitPower("player", chiConfig.powerType)
+end
\ No newline at end of file
diff --git a/modules/combattext.lua b/modules/combattext.lua
index 828c66856..da37a0d31 100755
--- a/modules/combattext.lua
+++ b/modules/combattext.lua
@@ -41,6 +41,9 @@ function Combat:Update(frame, event, unit, type, ...)
end
-- Increasing the font size will make the text look pixelated, however scaling it up will make it look smooth and awesome
- frame.combatText:SetScale(frame.combatText.feedbackText:GetStringHeight() / ShadowUF.db.profile.font.size)
- frame.combatText.feedbackText:SetFont(frame.combatText.fontPath, ShadowUF.db.profile.font.size, "OUTLINE")
+ local scale = frame.combatText.feedbackText:GetStringHeight() / ShadowUF.db.profile.font.size
+ if( scale > 0 ) then
+ frame.combatText:SetScale(scale)
+ frame.combatText.feedbackText:SetFont(frame.combatText.fontPath, ShadowUF.db.profile.font.size, "OUTLINE")
+ end
end
diff --git a/modules/combopoints.lua b/modules/combopoints.lua
index 3b4a31c0e..cb80f8007 100755
--- a/modules/combopoints.lua
+++ b/modules/combopoints.lua
@@ -1,128 +1,42 @@
-local Combo = {}
+if( not ShadowUF.ComboPoints ) then return end
+
+local Combo = setmetatable({}, {__index = ShadowUF.ComboPoints})
ShadowUF:RegisterModule(Combo, "comboPoints", ShadowUF.L["Combo points"])
+local cpConfig = {max = MAX_COMBO_POINTS, key = "comboPoints", colorKey = "COMBOPOINTS", powerType = 4, eventType = "COMBO_POINTS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"}
function Combo:OnEnable(frame)
frame.comboPoints = frame.comboPoints or CreateFrame("Frame", nil, frame)
- frame:RegisterNormalEvent("UNIT_COMBO_POINTS", self, "Update")
+ frame.comboPoints.cpConfig = cpConfig
+ cpConfig.max = UnitPowerMax("player", cpConfig.powerType)
+
+ frame:RegisterNormalEvent("UNIT_POWER_UPDATE", self, "Update", "player")
+ frame:RegisterNormalEvent("UNIT_POWER_FREQUENT", self, "Update", "player")
+ frame:RegisterNormalEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks", "player")
+
frame:RegisterUpdateFunc(self, "Update")
+ frame:RegisterUpdateFunc(self, "UpdateBarBlocks")
end
-function Combo:OnLayoutApplied(frame, config)
- -- Not a bar so set the containers frame configuration
- if( config.comboPoints and not config.comboPoints.isBar ) then
- ShadowUF.Layout:ToggleVisibility(frame.comboPoints, frame.visibility.comboPoints)
- end
-
- if( not frame.visibility.comboPoints ) then return end
-
- -- Hide the active combo points
- if( frame.comboPoints.points ) then
- for _, texture in pairs(frame.comboPoints.points) do
- texture:Hide()
- end
- end
-
- -- Setup for bar display!
- if( config.comboPoints.isBar ) then
- frame.comboPoints.blocks = frame.comboPoints.blocks or {}
- frame.comboPoints.points = frame.comboPoints.blocks
-
- -- Position bars, the 5 accounts for borders
- local blockWidth = (frame.comboPoints:GetWidth() - 4 ) / MAX_COMBO_POINTS
- for id=1, MAX_COMBO_POINTS do
- frame.comboPoints.blocks[id] = frame.comboPoints.blocks[id] or frame.comboPoints:CreateTexture(nil, "OVERLAY")
- local texture = frame.comboPoints.blocks[id]
- texture:SetVertexColor(1, 0.80, 0)
- texture:SetHorizTile(false)
- texture:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
- texture:SetHeight(frame.comboPoints:GetHeight())
- texture:SetWidth(blockWidth)
- texture:ClearAllPoints()
-
- if( config.comboPoints.growth == "LEFT" ) then
- if( id > 1 ) then
- texture:SetPoint("TOPRIGHT", frame.comboPoints.blocks[id - 1], "TOPLEFT", -1, 0)
- else
- texture:SetPoint("TOPRIGHT", frame.comboPoints, "TOPRIGHT", 0, 0)
- end
- else
- if( id > 1 ) then
- texture:SetPoint("TOPLEFT", frame.comboPoints.blocks[id - 1], "TOPRIGHT", 1, 0)
- else
- texture:SetPoint("TOPLEFT", frame.comboPoints, "TOPLEFT", 0, 0)
- end
- end
- end
-
- -- guess not, will have to do icons :(
- else
- local point, relativePoint
- local x, y = 0, 0
-
- if( config.comboPoints.growth == "LEFT" ) then
- point, relativePoint = "BOTTOMRIGHT", "BOTTOMLEFT"
- x = config.comboPoints.spacing
- elseif( config.comboPoints.growth == "RIGHT" ) then
- point, relativePoint = "BOTTOMLEFT", "BOTTOMRIGHT"
- x = config.comboPoints.spacing
- elseif( config.comboPoints.growth == "UP" ) then
- point, relativePoint = "BOTTOMLEFT", "TOPLEFT"
- y = config.comboPoints.spacing
- elseif( config.comboPoints.growth == "DOWN" ) then
- point, relativePoint = "TOPLEFT", "BOTTOMLEFT"
- y = config.comboPoints.spacing
- end
-
+function Combo:GetComboPointType()
+ return "comboPoints"
+end
- frame.comboPoints.icons = frame.comboPoints.icons or {}
- frame.comboPoints.points = frame.comboPoints.icons
-
- for id=1, MAX_COMBO_POINTS do
- frame.comboPoints.icons[id] = frame.comboPoints.icons[id] or frame.comboPoints:CreateTexture(nil, "OVERLAY")
- local texture = frame.comboPoints.icons[id]
- texture:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo")
- texture:SetHeight(config.comboPoints.size)
- texture:SetWidth(config.comboPoints.size)
-
- if( id > 1 ) then
- texture:ClearAllPoints()
- texture:SetPoint(point, frame.comboPoints.icons[id - 1], relativePoint, x, y)
- else
- texture:ClearAllPoints()
- texture:SetPoint("CENTER", frame.comboPoints, "CENTER", 0, 0)
- end
+function Combo:GetPoints(unit)
+ -- For Malygos dragons, they also self cast their CP on themselves, which is why we check CP on ourself
+ if( UnitHasVehicleUI("player") and UnitHasVehiclePlayerFrameUI("player") ) then
+ local points = GetComboPoints("vehicle")
+ if( points == 0 ) then
+ points = GetComboPoints("vehicle", "vehicle")
end
-
- -- Position the main frame
- frame.comboPoints:SetHeight(0.1)
- frame.comboPoints:SetWidth(0.1)
- ShadowUF.Layout:AnchorFrame(frame, frame.comboPoints, config.comboPoints)
+ return points
+ else
+ return UnitPower("player", cpConfig.powerType)
end
end
-function Combo:OnDisable(frame)
- frame:UnregisterAll(self)
-end
-
-function Combo:Update(frame)
- -- For Malygos dragons, they also self cast their CP on themselves, which is why we check CP on ourself!
- local playerUnit = UnitHasVehicleUI("player") and "vehicle" or "player"
- local points = GetComboPoints(playerUnit)
- if( points == 0 ) then
- points = GetComboPoints(playerUnit, playerUnit)
+function Combo:Update(frame, event, unit, powerType)
+ if( not event or ( unit == frame.unit or unit == frame.vehicleUnit or unit == "player" or unit == "vehicle" ) ) then
+ ShadowUF.ComboPoints.Update(self, frame, event, unit, powerType)
end
-
- -- Bar display, hide it if we don't have any combo points
- if( ShadowUF.db.profile.units[frame.unitType].comboPoints.isBar ) then
- ShadowUF.Layout:SetBarVisibility(frame, "comboPoints", points > 0)
- end
-
- for id, pointTexture in pairs(frame.comboPoints.points) do
- if( id <= points ) then
- pointTexture:Show()
- else
- pointTexture:Hide()
- end
- end
-end
+end
\ No newline at end of file
diff --git a/modules/defaultlayout.lua b/modules/defaultlayout.lua
old mode 100644
new mode 100755
index 64a89852f..37df48957
--- a/modules/defaultlayout.lua
+++ b/modules/defaultlayout.lua
@@ -43,7 +43,7 @@ local function finalizeData(config, useMerge)
mergeToChild(config.parentUnit, child)
-- Strip any invalid tables
verifyTable(child, self.defaults.profile.units[unit])
- -- Merge it in
+ -- Merge the new child table into the actual units
mergeToChild(child, self.db.profile.units[unit], true)
-- Merge position in too
@@ -63,6 +63,20 @@ local function finalizeData(config, useMerge)
for key, data in pairs(config) do
self.db.profile[key] = data
end
+ else
+ for key, data in pairs(config) do
+ if( key ~= "parentUnit" and key ~= "units" and key ~= "positions" and key ~= "hidden" ) then
+ if( self.db.profile[key] == nil ) then
+ self.db.profile[key] = data
+ else
+ for subKey, subValue in pairs(data) do
+ if( self.db.profile[key][subKey] == nil ) then
+ self.db.profile[key][subKey] = subValue
+ end
+ end
+ end
+ end
+ end
end
end
@@ -88,7 +102,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
borderColor = {r = 0.30, g = 0.30, b = 0.50, a = 1},
}
config.hidden = {
- cast = false, runes = true, buffs = false, party = true, player = true, pet = true, target = true, focus = true, boss = true, arena = true
+ cast = false, buffs = false, party = true, player = true, pet = true, target = true, focus = true, boss = true, arena = true, playerAltPower = false, playerPower = true
}
config.font = {
name = "Myriad Condensed Web",
@@ -102,10 +116,14 @@ function ShadowUF:LoadDefaultLayout(useMerge)
-- Some localizations do not work with Myriad Condensed Web, need to automatically swap it to a localization that will work for it
local SML = LibStub:GetLibrary("LibSharedMedia-3.0")
- if( GetLocale() == "koKR" or GetLocale() == "zhCN" or GetLocale() == "zhTW" or GetLocale() == "ruRU" ) then
+ if( GetLocale() == "koKR" or GetLocale() == "zhCN" or GetLocale() == "zhTW" ) then
config.font.name = SML.DefaultMedia.font
end
+ config.auraColors = {
+ removable = {r = 1, g = 1, b = 1}
+ }
+
config.classColors = {
HUNTER = {r = 0.67, g = 0.83, b = 0.45},
WARLOCK = {r = 0.58, g = 0.51, b = 0.79},
@@ -117,19 +135,38 @@ function ShadowUF:LoadDefaultLayout(useMerge)
SHAMAN = {r = 0.14, g = 0.35, b = 1.0},
WARRIOR = {r = 0.78, g = 0.61, b = 0.43},
DEATHKNIGHT = {r = 0.77, g = 0.12 , b = 0.23},
+ MONK = {r = 0.0, g = 1.00 , b = 0.59},
+ DEMONHUNTER = {r = 0.64, g = 0.19, b = 0.79},
PET = {r = 0.20, g = 0.90, b = 0.20},
VEHICLE = {r = 0.23, g = 0.41, b = 0.23},
}
config.powerColors = {
MANA = {r = 0.30, g = 0.50, b = 0.85},
RAGE = {r = 0.90, g = 0.20, b = 0.30},
- FOCUS = {r = 1.0, g = 0.85, b = 0},
+ FOCUS = {r = 1.0, g = 0.50, b = 0.25},
ENERGY = {r = 1.0, g = 0.85, b = 0.10},
- HAPPINESS = {r = 0.50, g = 0.90, b = 0.70},
RUNES = {r = 0.50, g = 0.50, b = 0.50},
RUNIC_POWER = {b = 0.60, g = 0.45, r = 0.35},
AMMOSLOT = {r = 0.85, g = 0.60, b = 0.55},
FUEL = {r = 0.85, g = 0.47, b = 0.36},
+ COMBOPOINTS = {r = 1.0, g = 0.80, b = 0.0},
+ INSANITY = {r = 0.40, g = 0, b = 0.80},
+ MAELSTROM = {r = 0.00, g = 0.50, b = 1.00},
+ LUNAR_POWER = {r = 0.30, g = 0.52, b = 0.90},
+ HOLYPOWER = {r = 0.95, g = 0.90, b = 0.60},
+ SOULSHARDS = {r = 0.58, g = 0.51, b = 0.79},
+ ARCANECHARGES = {r = 0.1, g = 0.1, b = 0.98},
+ ALTERNATE = {r = 0.815, g = 0.941, b = 1},
+ CHI = {r = 0.71, g = 1.0, b = 0.92},
+ FURY = {r = 0.788, g = 0.259, b = 0.992},
+ PAIN = {r = 1, g = 0, b = 0},
+ STATUE = {r = 0.35, g = 0.45, b = 0.60},
+ RUNEOFPOWER = {r = 0.35, g = 0.45, b = 0.60},
+ MUSHROOMS = {r = 0.20, g = 0.90, b = 0.20},
+ AURAPOINTS = {r = 1.0, g = 0.80, b = 0.0},
+ STAGGER_GREEN = {r = 0.52, g = 1.0, b = 0.52},
+ STAGGER_YELLOW = {r = 1.0, g = 0.98, b = 0.72},
+ STAGGER_RED = {r = 1.0, g = 0.42, b = 0.42},
}
config.healthColors = {
tapped = {r = 0.5, g = 0.5, b = 0.5},
@@ -138,8 +175,11 @@ function ShadowUF:LoadDefaultLayout(useMerge)
static = {r = 0.70, g = 0.20, b = 0.90},
yellow = {r = 0.93, g = 0.93, b = 0.0},
inc = {r = 0, g = 0.35, b = 0.23},
+ incAbsorb = {r = 0.93, g = 0.75, b = 0.09},
+ healAbsorb = {r = 0.68, g = 0.47, b = 1},
enemyUnattack = {r = 0.60, g = 0.20, b = 0.20},
hostile = {r = 0.90, g = 0.0, b = 0.0},
+ aggro = {r = 0.90, g = 0.0, b = 0.0},
friendly = {r = 0.20, g = 0.90, b = 0.20},
neutral = {r = 0.93, g = 0.93, b = 0.0},
offline = {r = 0.50, g = 0.50, b = 0.50}
@@ -168,34 +208,44 @@ function ShadowUF:LoadDefaultLayout(useMerge)
pettarget = {anchorPoint = "C", anchorTo = "UIParent", x = 0, y = 0},
partypet = {anchorPoint = "RB", anchorTo = "$parent", x = 0, y = 0},
partytarget = {anchorPoint = "RT", anchorTo = "$parent", x = 0, y = 0},
+ partytargettarget = {anchorPoint = "RT", anchorTo = "$parent", x = 0, y = 0},
raid = {anchorPoint = "C", anchorTo = "UIParent", x = 0, y = 0},
raidpet = {anchorPoint = "C", anchorTo = "UIParent", x = 0, y = 0},
maintank = {anchorPoint = "C", anchorTo = "UIParent", x = 0, y = 0},
maintanktarget = {anchorPoint = "RT", anchorTo = "$parent", x = 0, y = 0},
+ maintanktargettarget = {anchorPoint = "RT", anchorTo = "$parent", x = 150, y = 0},
mainassist = {anchorPoint = "C", anchorTo = "UIParent", x = 0, y = 0},
mainassisttarget = {anchorPoint = "RT", anchorTo = "$parent", x = 0, y = 0},
+ mainassisttargettarget = {anchorPoint = "RT", anchorTo = "$parent", x = 150, y = 0},
arena = {anchorPoint = "C", anchorTo = "UIParent", point = "", relativePoint = "", x = 0, y = 0},
arenapet = {anchorPoint = "RB", anchorTo = "$parent", x = 0, y = 0},
arenatarget = {anchorPoint = "RT", anchorTo = "$parent", x = 0, y = 0},
+ arenatargettarget = {anchorPoint = "RT", anchorTo = "$parent", x = 0, y = 0},
+ battleground = {anchorPoint = "C", anchorTo = "UIParent", point = "", relativePoint = "", x = 0, y = 0},
+ battlegroundpet = {anchorPoint = "RB", anchorTo = "$parent", x = 0, y = 0},
+ battlegroundtarget = {anchorPoint = "RT", anchorTo = "$parent", x = 0, y = 0},
+ battlegroundtargettarget = {anchorPoint = "RT", anchorTo = "$parent", x = 0, y = 0},
boss = {anchorPoint = "C", anchorTo = "UIParent", point = "", relativePoint = "", x = 0, y = 0},
bosstarget = {anchorPoint = "RB", anchorTo = "$parent", x = 0, y = 0},
+ bosstargettarget = {anchorPoint = "RB", anchorTo = "$parent", x = 0, y = 0},
}
-- Parent unit options that all the children will inherit unless they override it
config.parentUnit = {
portrait = {enabled = false, type = "3D", alignment = "LEFT", width = 0.22, height = 0.50, order = 15, fullBefore = 0, fullAfter = 100},
auras = {
- buffs = {enabled = false, anchorPoint = "BL", size = 16, perRow = 10, x = 0, y = 0},
- debuffs = {enabled = false, anchorPoint = "BL", size = 16, perRow = 10, x = 0, y = 0},
+ buffs = {enabled = false, anchorPoint = "BL", size = 16, perRow = 10, x = 0, y = 0, show = {player = true, boss = true, raid = true, misc = true}, enlarge = {}, timers = {ALL = true}},
+ debuffs = {enabled = false, anchorPoint = "BL", size = 16, perRow = 10, x = 0, y = 0, show = {player = true, boss = true, raid = true, misc = true}, enlarge = {SELF = true}, timers = {ALL = true}},
},
text = {
- {width = 0.50, name = L["Left text"], anchorTo = "$healthBar", anchorPoint = "CLI", x = 3, y = 0, size = 0},
- {width = 0.60, name = L["Right text"], anchorTo = "$healthBar", anchorPoint = "CRI", x = -3, y = 0, size = 0},
+ {width = 0.50, name = L["Left text"], anchorTo = "$healthBar", anchorPoint = "CLI", x = 3, y = 0, size = 0, default = true},
+ {width = 0.60, name = L["Right text"], anchorTo = "$healthBar", anchorPoint = "CRI", x = -3, y = 0, size = 0, default = true},
- {width = 0.50, name = L["Left text"], anchorTo = "$powerBar", anchorPoint = "CLI", x = 3, y = 0, size = 0},
- {width = 0.60, name = L["Right text"], anchorTo = "$powerBar", anchorPoint = "CRI", x = -3, y = 0, size = 0},
+ {width = 0.50, name = L["Left text"], anchorTo = "$powerBar", anchorPoint = "CLI", x = 3, y = 0, size = 0, default = true},
+ {width = 0.60, name = L["Right text"], anchorTo = "$powerBar", anchorPoint = "CRI", x = -3, y = 0, size = 0, default = true},
- {width = 1, name = L["Text"], anchorTo = "$emptyBar", anchorPoint = "CLI", x = 3, y = 0, size = 0},
+ {width = 0.50, name = L["Left text"], anchorTo = "$emptyBar", anchorPoint = "CLI", x = 3, y = 0, size = 0, default = true},
+ {width = 0.60, name = L["Right text"], anchorTo = "$emptyBar", anchorPoint = "CRI", x = -3, y = 0, size = 0, default = true},
},
indicators = {
raidTarget = {anchorTo = "$parent", anchorPoint = "C", size = 20, x = 0, y = 0},
@@ -212,12 +262,10 @@ function ShadowUF:LoadDefaultLayout(useMerge)
combatText = {anchorTo = "$parent", anchorPoint = "C", x = 0, y = 0},
emptyBar = {background = true, height = 1, reactionType = "none", order = 0},
healthBar = {background = true, colorType = "class", reactionType = "npc", height = 1.20, order = 10},
- powerBar = {background = true, height = 1.0, order = 20},
- druidBar = {background = true, height = 0.40, order = 25},
+ powerBar = {background = true, height = 1.0, order = 20, colorType = "type"},
xpBar = {background = true, height = 0.25, order = 55},
castBar = {background = true, height = 0.60, order = 40, icon = "HIDE", name = {enabled = true, size = 0, anchorTo = "$parent", rank = true, anchorPoint = "CLI", x = 1, y = 0}, time = {enabled = true, size = 0, anchorTo = "$parent", anchorPoint = "CRI", x = -1, y = 0}},
- runeBar = {background = false, height = 0.40, order = 70},
- totemBar = {background = false, height = 0.40, order = 70},
+ altPowerBar = {background = true, height = 0.40, order = 100},
}
-- Units configuration
@@ -236,11 +284,14 @@ function ShadowUF:LoadDefaultLayout(useMerge)
healthBar = {reactionType = "none"},
powerBar = {height = 0.30},
incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
masterLoot = {anchorTo = "$parent", anchorPoint = "TR", size = 12, x = -2, y = -10},
role = {enabled = false, anchorTo = "$parent", anchorPoint = "BR", size = 14, x = 0, y = 14},
ready = {anchorTo = "$parent", anchorPoint = "LC", size = 24, x = 25, y = 0},
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
},
text = {
{text = "[(()afk() )][name]"},
@@ -248,6 +299,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
raidpet = {
@@ -264,6 +316,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
healthBar = {reactionType = "none"},
powerBar = {height = 0.30},
incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
masterLoot = {anchorTo = "$parent", anchorPoint = "TR", size = 12, x = -2, y = -10},
@@ -276,20 +330,37 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[name]"},
+ {text = ""},
},
},
-
- player = {
+ player = {
width = 190,
height = 45,
scale = 1.0,
portrait = {enabled = true, fullAfter = 50},
castBar = {order = 60},
xpBar = {order = 55},
- runeBar = {enabled = true, order = 70},
- totemBar = {enabled = true, order = 70},
+ fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.6},
+ runeBar = {enabled = true, background = false, height = 0.40, order = 70},
+ totemBar = {enabled = true, background = false, height = 0.40, order = 70},
+ druidBar = {enabled = true, background = true, height = 0.40, order = 70},
+ priestBar = {enabled = true, background = true, height = 0.40, order = 70},
+ shamanBar = {enabled = true, background = true, height = 0.40, order = 70},
+ comboPoints = {enabled = true, anchorTo = "$parent", order = 60, anchorPoint = "BR", x = -3, y = 8, size = 14, spacing = -4, growth = "LEFT", isBar = true, height = 0.40},
+ auraPoints = {enabled = false, showAlways = true, anchorTo = "$parent", order = 60, anchorPoint = "BR", x = -3, y = 8, size = 14, spacing = -4, growth = "LEFT", isBar = true, height = 0.40},
+ staggerBar = {enabled = true, background = true, height = 0.30, order = 70},
+ soulShards = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -8, y = 6, size = 12, spacing = -2, growth = "LEFT", isBar = true, showAlways = true},
+ holyPower = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -3, y = 6, size = 14, spacing = -4, growth = "LEFT", isBar = true, showAlways = true},
+ chi = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -3, y = 6, size = 14, spacing = -4, growth = "LEFT", isBar = true, showAlways = true},
+ arcaneCharges = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -8, y = 6, size = 12, spacing = -2, growth = "LEFT", isBar = true, showAlways = true},
+ incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
+ indicators = {
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ },
auras = {
- buffs = {enabled = false, maxRows = 1, temporary = playerClass == "ROGUE" or playerClass == "SHAMAN"},
+ buffs = {enabled = false, maxRows = 1},
debuffs = {enabled = false, maxRows = 1},
},
text = {
@@ -298,6 +369,10 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[(()afk() )][name][( ()group())]"},
+ {text = ""},
+ {enabled = true, width = 1, name = L["Timer Text"], text = "[totem:timer]", anchorTo = "$totemBar", anchorPoint = "C", x = 0, y = 0, size = 0, default = true, block = true},
+ {enabled = true, width = 1, name = L["Timer Text"], text = "[rune:timer]", anchorTo = "$runeBar", anchorPoint = "C", size = 0, x = 0, y = 0, default = true, block = true},
+ {enabled = true, width = 1, name = L["Text"], text = "[monk:abs:stagger]", anchorTo = "$staggerBar", anchorPoint = "C", size = 0, x = 0, y = 0, default = true}
},
},
party = {
@@ -311,6 +386,13 @@ function ShadowUF:LoadDefaultLayout(useMerge)
portrait = {enabled = true, fullAfter = 50},
castBar = {order = 60},
offset = 23,
+ incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
+ indicators = {
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ phase = {enabled = true, anchorPoint = "RC", size = 14, x = -11, y = 0, anchorTo = "$parent"}
+ },
auras = {
buffs = {enabled = true, maxRows = 1},
debuffs = {enabled = true, maxRows = 1},
@@ -321,6 +403,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[level( )][perpp]"},
{text = "[curmaxpp]"},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
boss = {
@@ -331,6 +414,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
attribPoint = "TOP",
attribAnchorPoint = "LEFT",
offset = 20,
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
auras = {
buffs = {enabled = true, maxRows = 1, perRow = 8},
debuffs = {enabled = true, maxRows = 1, perRow = 8},
@@ -341,6 +426,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[name]"},
+ {text = ""},
},
portrait = {enabled = false},
},
@@ -348,6 +434,21 @@ function ShadowUF:LoadDefaultLayout(useMerge)
width = 90,
height = 25,
scale = 1.0,
+ healAbsorb = {cap = 1},
+ powerBar = {height = 0.60},
+ text = {
+ {text = "[name]"},
+ {text = "[curhp]"},
+ {text = ""},
+ {text = ""},
+ {text = "[name]"},
+ },
+ },
+ bosstargettarget = {
+ width = 90,
+ height = 25,
+ scale = 1.0,
+ healAbsorb = {cap = 1},
powerBar = {height = 0.60},
text = {
{text = "[name]"},
@@ -355,27 +456,36 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[name]"},
+ {text = ""},
},
},
arena = {
+ enabled = true,
width = 170,
height = 45,
scale = 1.0,
attribPoint = "TOP",
attribAnchorPoint = "LEFT",
- portrait = {enabled = false, fullAfter = 50},
+ portrait = {enabled = true, type = "class", fullAfter = 50},
+ altPower = {enabled = false},
castBar = {order = 60},
offset = 25,
+ healAbsorb = {cap = 1},
auras = {
buffs = {enabled = true, maxRows = 1, perRow = 9},
debuffs = {enabled = true, maxRows = 1, perRow = 9},
},
+ indicators = {
+ pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
+ arenaSpec = {anchorTo = "$parent", anchorPoint = "LC", size = 28, x = 0, y = 0}
+ },
text = {
{text = "[name]"},
{text = "[curmaxhp]"},
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[name]"},
+ {text = ""},
},
},
arenapet = {
@@ -383,6 +493,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 25,
scale = 1.0,
powerBar = {height = 0.60},
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
text = {
{text = "[name]"},
{text = "[curhp]"},
@@ -396,6 +508,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 25,
scale = 1.0,
powerBar = {height = 0.60},
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
},
@@ -405,6 +519,109 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[name]"},
+ {text = ""},
+ },
+ },
+ arenatargettarget = {
+ width = 90,
+ height = 25,
+ scale = 1.0,
+ powerBar = {height = 0.60},
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
+ indicators = {
+ pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
+ },
+ text = {
+ {text = "[name]"},
+ {text = "[curhp]"},
+ {text = ""},
+ {text = ""},
+ {text = "[name]"},
+ {text = ""},
+ },
+ },
+ battleground = {
+ enabled = true,
+ width = 140,
+ height = 35,
+ scale = 1.0,
+ attribPoint = "TOP",
+ attribAnchorPoint = "LEFT",
+ portrait = {enabled = false, type = "class", fullAfter = 50},
+ powerBar = {height = 0.5},
+ altPower = {enabled = false},
+ castBar = {order = 60},
+ healAbsorb = {cap = 1},
+ offset = 0,
+ auras = {
+ buffs = {enabled = false, maxRows = 1, perRow = 9},
+ debuffs = {enabled = false, maxRows = 1, perRow = 9},
+ },
+ indicators = {
+ pvp = {enabled = true, anchorTo = "$parent", anchorPoint = "LC", size = 40, x = 16, y = -8},
+ },
+ text = {
+ {text = "[name]"},
+ {text = "[curmaxhp]"},
+ {text = ""},
+ {text = ""},
+ {text = "[name]"},
+ {text = ""},
+ },
+ },
+ battlegroundpet = {
+ width = 90,
+ height = 25,
+ scale = 1.0,
+ powerBar = {height = 0.60},
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
+ text = {
+ {text = "[name]"},
+ {text = "[curhp]"},
+ {text = ""},
+ {text = ""},
+ {text = "[name]"},
+ {text = ""},
+ },
+ },
+ battlegroundtarget = {
+ width = 90,
+ height = 25,
+ scale = 1.0,
+ powerBar = {height = 0.60},
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
+ indicators = {
+ pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
+ },
+ text = {
+ {text = "[name]"},
+ {text = "[curhp]"},
+ {text = ""},
+ {text = ""},
+ {text = "[name]"},
+ {text = ""},
+ },
+ },
+ battlegroundtargettarget = {
+ width = 90,
+ height = 25,
+ scale = 1.0,
+ powerBar = {height = 0.60},
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
+ indicators = {
+ pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
+ },
+ text = {
+ {text = "[name]"},
+ {text = "[curhp]"},
+ {text = ""},
+ {text = ""},
+ {text = "[name]"},
+ {text = ""},
},
},
maintank = {
@@ -418,8 +635,13 @@ function ShadowUF:LoadDefaultLayout(useMerge)
maxColumns = 1,
columnSpacing = 5,
incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
portrait = {enabled = false, fullAfter = 50},
castBar = {order = 60},
+ indicators = {
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ },
auras = {
buffs = {enabled = false},
debuffs = {enabled = false},
@@ -430,6 +652,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
maintanktarget = {
@@ -446,6 +669,24 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[classification( )][perpp]", width = 0.50},
{text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60},
{text = "[(()afk() )][name]"},
+ {text = ""},
+ },
+ },
+ maintanktargettarget = {
+ width = 150,
+ height = 40,
+ scale = 1.0,
+ auras = {
+ buffs = {enabled = false},
+ debuffs = {enabled = false},
+ },
+ text = {
+ {text = "[(()afk() )][name]"},
+ {text = "[curmaxhp]"},
+ {text = "[classification( )][perpp]", width = 0.50},
+ {text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60},
+ {text = "[(()afk() )][name]"},
+ {text = ""},
},
},
mainassist = {
@@ -459,8 +700,13 @@ function ShadowUF:LoadDefaultLayout(useMerge)
maxColumns = 1,
columnSpacing = 5,
incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
portrait = {enabled = false, fullAfter = 50},
castBar = {order = 60},
+ indicators = {
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ },
auras = {
buffs = {enabled = false},
debuffs = {enabled = false},
@@ -471,12 +717,32 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[level( )][perpp]"},
{text = "[curmaxpp]"},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
mainassisttarget = {
width = 150,
height = 40,
scale = 1.0,
+ healAbsorb = {cap = 1},
+ auras = {
+ buffs = {enabled = false},
+ debuffs = {enabled = false},
+ },
+ text = {
+ {text = "[(()afk() )][name]"},
+ {text = "[curmaxhp]"},
+ {text = "[level( )][classification( )][perpp]", width = 0.50},
+ {text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60},
+ {text = "[(()afk() )][name]"},
+ {text = ""},
+ },
+ },
+ mainassisttargettarget = {
+ width = 150,
+ height = 40,
+ scale = 1.0,
+ healAbsorb = {cap = 1},
auras = {
buffs = {enabled = false},
debuffs = {enabled = false},
@@ -487,12 +753,14 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[level( )][classification( )][perpp]", width = 0.50},
{text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
partypet = {
width = 90,
height = 25,
scale = 1.0,
+ healAbsorb = {cap = 1},
powerBar = {height = 0.60},
text = {
{text = "[name]"},
@@ -507,6 +775,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 25,
scale = 1.0,
powerBar = {height = 0.60},
+ healAbsorb = {cap = 1},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
},
@@ -516,17 +785,42 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[name]"},
+ {text = ""},
},
},
+ partytargettarget = {
+ width = 90,
+ height = 25,
+ scale = 1.0,
+ powerBar = {height = 0.60},
+ healAbsorb = {cap = 1},
+ indicators = {
+ pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
+ },
+ text = {
+ {text = "[name]"},
+ {text = "[curhp]"},
+ {text = ""},
+ {text = ""},
+ {text = "[name]"},
+ {text = ""},
+ },
+ },
target = {
width = 190,
height = 45,
scale = 1.0,
portrait = {enabled = true, alignment = "RIGHT", fullAfter = 50},
+ incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
castBar = {order = 60},
- comboPoints = {anchorTo = "$parent", order = 60, anchorPoint = "BR", x = -3, y = 8, size = 14, spacing = -4, growth = "LEFT", isBar = true},
+ comboPoints = {enabled = false, anchorTo = "$parent", order = 60, anchorPoint = "BR", x = -3, y = 8, size = 14, spacing = -4, growth = "LEFT", isBar = true, height = 0.40},
indicators = {
- lfdRole = {enabled = false}
+ lfdRole = {enabled = false},
+ resurrect = {enabled = true, anchorPoint = "RC", size = 28, x = -39, y = -1, anchorTo = "$parent"},
+ questBoss = {enabled = true, anchorPoint = "BR", size = 22, x = 9, y = 24, anchorTo = "$parent"},
+ petBattle = {enabled = true, anchorPoint = "BL", size = 18, x = -6, y = 14, anchorTo = "$parent"}
},
auras = {
buffs = {enabled = true},
@@ -538,6 +832,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[level( )][classification( )][perpp]", width = 0.50},
{text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
pet = {
@@ -545,24 +840,24 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 30,
scale = 1.0,
powerBar = {height = 0.70},
+ healAbsorb = {cap = 1},
healthBar = {reactionType = "none"},
portrait = {enabled = false, fullAfter = 50},
castBar = {order = 60},
- indicators = {
- happiness = {enabled = false, anchorTo = "$parent", anchorPoint = "BR", size = 14, x = 3, y = 13},
- },
text = {
{text = "[name]"},
{text = "[curmaxhp]"},
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[name]"},
+ {text = ""},
},
},
pettarget = {
width = 190,
height = 30,
scale = 1.0,
+ healAbsorb = {cap = 1},
powerBar = {height = 0.70},
indicators = {
},
@@ -572,6 +867,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[name]"},
+ {text = ""},
},
},
focus = {
@@ -579,10 +875,14 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 28,
scale = 1.0,
powerBar = {height = 0.60},
+ healAbsorb = {cap = 1},
portrait = {enabled = false, fullAfter = 50},
castBar = {order = 60},
indicators = {
lfdRole = {enabled = false},
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ questBoss = {enabled = false, anchorPoint = "BR", size = 22, x = 7, y = 14, anchorTo = "$parent"},
+ petBattle = {enabled = false, anchorPoint = "BL", size = 18, x = -6, y = 12, anchorTo = "$parent"}
},
text = {
{text = "[(()afk() )][name]"},
@@ -590,6 +890,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curpp]"},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
focustarget = {
@@ -597,6 +898,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 25,
scale = 1.0,
powerBar = {height = 0.60},
+ healAbsorb = {cap = 1},
portrait = {alignment = "RIGHT"},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = -3, y = 11},
@@ -607,6 +909,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
targettarget = {
@@ -614,6 +917,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 30,
scale = 1.0,
powerBar = {height = 0.6},
+ healAbsorb = {cap = 1},
portrait = {alignment = "RIGHT"},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = -3, y = 11},
@@ -623,6 +927,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[curhp]"},
{text = "[perpp]"},
{text = "[curpp]"},
+ {text = ""},
+ {text = ""},
},
},
targettargettarget = {
@@ -630,6 +936,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 30,
scale = 1.0,
powerBar = {height = 0.6},
+ healAbsorb = {cap = 1},
portrait = {alignment = "RIGHT"},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = -3, y = 11},
@@ -639,6 +946,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = ""},
+ {text = ""},
+ {text = ""},
},
},
}
diff --git a/modules/druid.lua b/modules/druid.lua
index ee16c0477..a55b7f221 100755
--- a/modules/druid.lua
+++ b/modules/druid.lua
@@ -4,8 +4,6 @@ ShadowUF:RegisterModule(Druid, "druidBar", ShadowUF.L["Druid mana bar"], true, "
function Druid:OnEnable(frame)
frame.druidBar = frame.druidBar or ShadowUF.Units:CreateBar(frame)
- frame:RegisterUnitEvent("UNIT_MAXMANA", self, "Update")
- frame:RegisterUnitEvent("UNIT_MANA", self, "Update")
frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "PowerChanged")
frame:RegisterUpdateFunc(self, "PowerChanged")
@@ -17,30 +15,25 @@ function Druid:OnDisable(frame)
end
function Druid:OnLayoutApplied(frame)
- if( frame.visibility.druidBar ) then
- local color = ShadowUF.db.profile.powerColors.MANA
-
- if( not ShadowUF.db.profile.units[frame.unitType].druidBar.invert ) then
- frame.druidBar:SetStatusBarColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
- if( not frame.druidBar.background.overrideColor ) then
- frame.druidBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
- else
- frame.druidBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
-
- color = frame.druidBar.background.overrideColor or color
- frame.druidBar:SetStatusBarColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
- end
+ if( not frame.visibility.druidBar ) then return end
+
+ local color = ShadowUF.db.profile.powerColors.MANA
+ frame:SetBarColor("druidBar", color.r, color.g, color.b)
end
--- While power type is mana, show the bar once it is mana hide it.
function Druid:PowerChanged(frame)
- local powerType = UnitPowerType(frame.unit)
- ShadowUF.Layout:SetBarVisibility(frame, "druidBar", powerType == 1 or powerType == 3)
+ local visible = UnitPowerType(frame.unit) ~= ADDITIONAL_POWER_BAR_INDEX and not frame.inVehicle
+ local type = visible and "RegisterUnitEvent" or "UnregisterSingleEvent"
+
+ frame[type](frame, "UNIT_POWER_FREQUENT", self, "Update")
+ frame[type](frame, "UNIT_MAXPOWER", self, "Update")
+ ShadowUF.Layout:SetBarVisibility(frame, "druidBar", visible)
+
+ if( visible ) then self:Update(frame) end
end
-function Druid:Update(frame)
- frame.druidBar:SetMinMaxValues(0, UnitPowerMax(frame.unit, 0))
- frame.druidBar:SetValue(UnitIsDeadOrGhost(frame.unit) and 0 or not UnitIsConnected(frame.unit) and 0 or UnitPower(frame.unit, 0))
+function Druid:Update(frame, event, unit, powerType)
+ if( powerType and powerType ~= "MANA" ) then return end
+ frame.druidBar:SetMinMaxValues(0, UnitPowerMax(frame.unit, Enum.PowerType.Mana))
+ frame.druidBar:SetValue(UnitIsDeadOrGhost(frame.unit) and 0 or not UnitIsConnected(frame.unit) and 0 or UnitPower(frame.unit, Enum.PowerType.Mana))
end
diff --git a/modules/empty.lua b/modules/empty.lua
old mode 100644
new mode 100755
index b8d07bb4a..4fc1739ea
--- a/modules/empty.lua
+++ b/modules/empty.lua
@@ -19,7 +19,7 @@ function Empty:OnLayoutApplied(frame)
local color = frame.emptyBar.background.overrideColor or fallbackColor
frame.emptyBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
- if( ShadowUF.db.profile.units[frame.unitType].emptyBar.reaction or ShadowUF.db.profile.units[frame.unitType].emptyBar.class ) then
+ if( ShadowUF.db.profile.units[frame.unitType].emptyBar.reactionType or ShadowUF.db.profile.units[frame.unitType].emptyBar.class ) then
frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdateColor")
frame:RegisterUpdateFunc(self, "UpdateColor")
else
@@ -31,7 +31,10 @@ end
function Empty:UpdateColor(frame)
local color
local reactionType = ShadowUF.db.profile.units[frame.unitType].emptyBar.reactionType
- if( not UnitPlayerOrPetInRaid(frame.unit) and not UnitPlayerOrPetInParty(frame.unit) and ( ( ( reactionType == "player" or reactionType == "both" ) and UnitIsPlayer(frame.unit) and not UnitIsFriend(frame.unit, "player") ) or ( ( reactionType == "npc" or reactionType == "both" ) and not UnitIsPlayer(frame.unit) ) ) ) then
+
+ if( ( reactionType == "npc" or reactionType == "both" ) and not UnitPlayerControlled(frame.unit) and UnitIsTapDenied(frame.unit) and UnitCanAttack("player", frame.unit) ) then
+ color = ShadowUF.db.profile.healthColors.tapped
+ elseif( not UnitPlayerOrPetInRaid(frame.unit) and not UnitPlayerOrPetInParty(frame.unit) and ( ( ( reactionType == "player" or reactionType == "both" ) and UnitIsPlayer(frame.unit) and not UnitIsFriend(frame.unit, "player") ) or ( ( reactionType == "npc" or reactionType == "both" ) and not UnitIsPlayer(frame.unit) ) ) ) then
if( not UnitIsFriend(frame.unit, "player") and UnitPlayerControlled(frame.unit) ) then
if( UnitCanAttack("player", frame.unit) ) then
color = ShadowUF.db.profile.healthColors.hostile
@@ -49,7 +52,7 @@ function Empty:UpdateColor(frame)
end
end
elseif( ShadowUF.db.profile.units[frame.unitType].emptyBar.class and ( UnitIsPlayer(frame.unit) or UnitCreatureFamily(frame.unit) ) ) then
- local class = UnitCreatureFamily(frame.unit) or select(2, UnitClass(frame.unit))
+ local class = UnitCreatureFamily(frame.unit) or frame:UnitClassToken()
color = class and ShadowUF.db.profile.classColors[class]
end
diff --git a/modules/fader.lua b/modules/fader.lua
index 46a8faf3d..072d280c4 100755
--- a/modules/fader.lua
+++ b/modules/fader.lua
@@ -1,9 +1,29 @@
local Fader = {}
+local powerDepletes = {[Enum.PowerType.Mana] = true, [Enum.PowerType.Energy] = true, [Enum.PowerType.Focus] = true}
ShadowUF:RegisterModule(Fader, "fader", ShadowUF.L["Combat fader"])
+-- TODO: Remove once Blizzard fixes cooldown wheels not taking parents alpha
+local function tempAuraFader(frame, alpha)
+ if( not frame.auras ) then return end
+
+ local childAlpha = 0.8 * alpha
+ if( frame.auras.buffs ) then
+ for id, button in pairs(frame.auras.buffs.buttons) do
+ button.cooldown:SetSwipeColor(0, 0, 0, childAlpha)
+ end
+ end
+
+ if( frame.auras.debuffs ) then
+ for id, button in pairs(frame.auras.debuffs.buttons) do
+ button.cooldown:SetSwipeColor(0, 0, 0, childAlpha)
+ end
+ end
+end
+
local function faderUpdate(self, elapsed)
self.timeElapsed = self.timeElapsed + elapsed
if( self.timeElapsed >= self.fadeTime ) then
+ tempAuraFader(self.parent, self.alphaEnd)
self.parent:SetAlpha(self.alphaEnd)
self:Hide()
@@ -18,6 +38,8 @@ local function faderUpdate(self, elapsed)
else
self.parent:SetAlpha(((self.fadeTime - self.timeElapsed) / self.fadeTime) * (self.alphaStart - self.alphaEnd) + self.alphaEnd)
end
+
+ tempAuraFader(self.parent, self.parent:GetAlpha())
end
local function startFading(self, type, alpha, speedyFade)
@@ -80,27 +102,27 @@ function Fader:PLAYER_REGEN_ENABLED(frame, event)
frame:RegisterNormalEvent("UNIT_SPELLCAST_START", self, "CastStart")
frame:RegisterNormalEvent("UNIT_SPELLCAST_STOP", self, "CastStop")
frame:RegisterUnitEvent("UNIT_HEALTH", self, "Update")
- frame:RegisterUnitEvent("UNIT_MANA", self, "Update")
frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXMANA", self, "Update")
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "Update")
end
function Fader:PLAYER_REGEN_DISABLED(frame, event)
self:Update(frame, event)
- frame:UnregisterEvent("PLAYER_TARGET_CHANGED")
- frame:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START")
- frame:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
- frame:UnregisterEvent("UNIT_SPELLCAST_START")
- frame:UnregisterEvent("UNIT_SPELLCAST_STOP")
- frame:UnregisterEvent("UNIT_HEALTH")
- frame:UnregisterEvent("UNIT_MANA")
- frame:UnregisterEvent("UNIT_MAXHEALTH")
- frame:UnregisterEvent("UNIT_MAXMANA")
+ frame:UnregisterSingleEvent("PLAYER_TARGET_CHANGED", self)
+ frame:UnregisterSingleEvent("UNIT_SPELLCAST_CHANNEL_START", self)
+ frame:UnregisterSingleEvent("UNIT_SPELLCAST_CHANNEL_STOP", self)
+ frame:UnregisterSingleEvent("UNIT_SPELLCAST_START", self)
+ frame:UnregisterSingleEvent("UNIT_SPELLCAST_STOP", self)
+ frame:UnregisterSingleEvent("UNIT_HEALTH", self)
+ frame:UnregisterSingleEvent("UNIT_POWER_FREQUENT", self)
+ frame:UnregisterSingleEvent("UNIT_MAXHEALTH", self)
+ frame:UnregisterSingleEvent("UNIT_MAXPOWER", self)
end
local activeCastID
-function Fader:CastStart(frame, event, unit, spellName, spellRank, id)
+function Fader:CastStart(frame, event, unit, id)
if( unit ~= "player" or activeCastID == id ) then return end
activeCastID = id
@@ -108,7 +130,7 @@ function Fader:CastStart(frame, event, unit, spellName, spellRank, id)
self:Update(frame)
end
-function Fader:CastStop(frame, event, unit, spellName, spellRank, id)
+function Fader:CastStop(frame, event, unit, id)
if( unit ~= "player" or activeCastID ~= id ) then return end
activeCastID = nil
@@ -125,7 +147,7 @@ function Fader:Update(frame, event)
elseif( frame.fader.playerCasting ) then
startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha, true)
-- Ether mana or energy is not at 100%, fade in
- elseif( ( UnitPowerType(frame.unit) == 0 or UnitPowerType(frame.unit) == 3 ) and UnitPower(frame.unit) ~= UnitPowerMax(frame.unit) ) then
+ elseif( powerDepletes[UnitPowerType(frame.unit)] and UnitPower(frame.unit) ~= UnitPowerMax(frame.unit) ) then
startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha)
-- Health is not at max, fade in
elseif( UnitHealth(frame.unit) ~= UnitHealthMax(frame.unit) ) then
diff --git a/modules/healabsorb.lua b/modules/healabsorb.lua
new file mode 100755
index 000000000..498d2aacb
--- /dev/null
+++ b/modules/healabsorb.lua
@@ -0,0 +1,19 @@
+local HealAbsorb = setmetatable({["frameKey"] = "healAbsorb", ["colorKey"] = "healAbsorb", ["frameLevelMod"] = 1}, {__index = ShadowUF.IncHeal})
+ShadowUF:RegisterModule(HealAbsorb, "healAbsorb", ShadowUF.L["Healing absorb"])
+
+function HealAbsorb:OnEnable(frame)
+ frame.healAbsorb = frame.healAbsorb or ShadowUF.Units:CreateBar(frame)
+
+ frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "UpdateFrame")
+ frame:RegisterUnitEvent("UNIT_HEALTH", self, "UpdateFrame")
+ frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", self, "UpdateFrame")
+ frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", self, "UpdateFrame")
+
+ frame:RegisterUpdateFunc(self, "UpdateFrame")
+end
+
+function HealAbsorb:UpdateFrame(frame)
+ if( not frame.visibility[self.frameKey] or not frame.visibility.healthBar ) then return end
+
+ self:PositionBar(frame, UnitGetTotalHealAbsorbs(frame.unit) or 0)
+end
\ No newline at end of file
diff --git a/modules/health.lua b/modules/health.lua
old mode 100644
new mode 100755
index d701f8f0b..0895a6873
--- a/modules/health.lua
+++ b/modules/health.lua
@@ -1,8 +1,10 @@
local Health = {}
ShadowUF:RegisterModule(Health, "healthBar", ShadowUF.L["Health bar"], true)
+local canCure = ShadowUF.Units.canCure
local function getGradientColor(unit)
- local percent = UnitHealth(unit) / UnitHealthMax(unit)
+ local maxHealth = UnitHealthMax(unit)
+ local percent = maxHealth > 0 and UnitHealth(unit) / maxHealth or 0
if( percent >= 1 ) then return ShadowUF.db.profile.healthColors.green.r, ShadowUF.db.profile.healthColors.green.g, ShadowUF.db.profile.healthColors.green.b end
if( percent == 0 ) then return ShadowUF.db.profile.healthColors.red.r, ShadowUF.db.profile.healthColors.red.g, ShadowUF.db.profile.healthColors.red.b end
@@ -24,31 +26,6 @@ end
Health.getGradientColor = getGradientColor
--- Not doing full health update, because other checks can lag behind without much issue
-local function updateTimer(self)
- local currentHealth = UnitHealth(self.parent.unit)
- if( currentHealth == self.currentHealth ) then return end
- self.currentHealth = currentHealth
- self:SetValue(currentHealth)
-
- -- As much as I would rather not have to do this in an OnUpdate, I don't have much choice large health changes in a single update will make them very clearly be lagging behind
- for _, fontString in pairs(self.parent.fontStrings) do
- if( fontString.fastHealth ) then
- fontString:UpdateTags()
- end
- end
-
- -- Update incoming heal number
- if( self.parent.incHeal and self.parent.incHeal.healed ) then
- self.parent.incHeal:SetValue(currentHealth + self.parent.incHeal.healed)
- end
-
- -- The target is not offline, and we have a health percentage so update the gradient
- if( not self.parent.healthBar.wasOffline and self.parent.healthBar.hasPercent ) then
- Health:SetBarColor(self.parent.healthBar, ShadowUF.db.profile.units[self.parent.unitType].healthBar.invert, getGradientColor(self.parent.unit))
- end
-end
-
function Health:OnEnable(frame)
if( not frame.healthBar ) then
frame.healthBar = ShadowUF.Units:CreateBar(frame)
@@ -56,46 +33,49 @@ function Health:OnEnable(frame)
frame:RegisterUnitEvent("UNIT_HEALTH", self, "Update")
frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "Update")
+ frame:RegisterUnitEvent("UNIT_CONNECTION", self, "Update")
frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdateColor")
- frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", self, "UpdateColor")
+ frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", self, "UpdateColor")
+ frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "UpdateColor")
if( frame.unit == "pet" ) then
- frame:RegisterUnitEvent("UNIT_HAPPINESS", self, "UpdateColor")
+ frame:RegisterUnitEvent("UNIT_POWER_UPDATE", self, "UpdateColor")
end
-
- frame:RegisterUpdateFunc(self, "UpdateColor")
- frame:RegisterUpdateFunc(self, "Update")
-end
-function Health:OnLayoutApplied(frame)
- if( not frame.visibility.healthBar ) then return end
-
- if( ShadowUF.db.profile.units[frame.unitType].healthBar.predicted ) then
- frame.healthBar:SetScript("OnUpdate", updateTimer)
- frame.healthBar.parent = frame
- else
- frame.healthBar:SetScript("OnUpdate", nil)
+ if ( ShadowUF.db.profile.units[frame.unitType].healthBar.colorDispel ) then
+ frame:RegisterUnitEvent("UNIT_AURA", self, "UpdateAura")
+ frame:RegisterUpdateFunc(self, "UpdateAura")
end
+
+ frame:RegisterUpdateFunc(self, "UpdateColor")
+ frame:RegisterUpdateFunc(self, "Update")
end
function Health:OnDisable(frame)
frame:UnregisterAll(self)
end
-function Health:SetBarColor(bar, invert, r, g, b)
- if( not invert ) then
- bar:SetStatusBarColor(r, g, b, ShadowUF.db.profile.bars.alpha)
- if( not bar.background.overrideColor ) then
- bar.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
- else
- bar.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.alpha)
- if( not bar.background.overrideColor ) then
- bar:SetStatusBarColor(0, 0, 0, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
- else
- bar:SetStatusBarColor(bar.background.overrideColor.r, bar.background.overrideColor.g, bar.background.overrideColor.b, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
+function Health:UpdateAura(frame)
+ local hadDebuff = frame.healthBar.hasDebuff
+ frame.healthBar.hasDebuff = nil
+ if( UnitIsFriend(frame.unit, "player") ) then
+ local id = 0
+ while( true ) do
+ id = id + 1
+ local name, _, _, auraType = UnitDebuff(frame.unit, id)
+ if( not name ) then break end
+
+ if( canCure[auraType] ) then
+ frame.healthBar.hasDebuff = auraType
+ break
+ end
end
end
+
+ if hadDebuff ~= frame.healthBar.hasDebuff then
+ self:UpdateColor(frame)
+ end
end
function Health:UpdateColor(frame)
@@ -108,24 +88,17 @@ function Health:UpdateColor(frame)
local reactionType = ShadowUF.db.profile.units[frame.unitType].healthBar.reactionType
if( not UnitIsConnected(unit) ) then
frame.healthBar.wasOffline = true
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, ShadowUF.db.profile.healthColors.offline.r, ShadowUF.db.profile.healthColors.offline.g, ShadowUF.db.profile.healthColors.offline.b)
+ frame:SetBarColor("healthBar", ShadowUF.db.profile.healthColors.offline.r, ShadowUF.db.profile.healthColors.offline.g, ShadowUF.db.profile.healthColors.offline.b)
return
+ elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorDispel and frame.healthBar.hasDebuff ) then
+ color = DebuffTypeColor[frame.healthBar.hasDebuff]
elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorAggro and UnitThreatSituation(frame.unit) == 3 ) then
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, ShadowUF.db.profile.healthColors.hostile.r, ShadowUF.db.profile.healthColors.hostile.g, ShadowUF.db.profile.healthColors.hostile.b)
+ frame:SetBarColor("healthBar", ShadowUF.db.profile.healthColors.aggro.r, ShadowUF.db.profile.healthColors.aggro.g, ShadowUF.db.profile.healthColors.aggro.b)
return
elseif( frame.inVehicle ) then
color = ShadowUF.db.profile.classColors.VEHICLE
- elseif( not UnitIsTappedByPlayer(unit) and UnitIsTapped(unit) and UnitCanAttack("player", unit) ) then
+ elseif( not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) and UnitCanAttack("player", unit) ) then
color = ShadowUF.db.profile.healthColors.tapped
- elseif( unit == "pet" and reactionType == "happiness" and GetPetHappiness() ) then
- local happiness = GetPetHappiness()
- if( happiness == 3 ) then
- color = ShadowUF.db.profile.healthColors.friendly
- elseif( happiness == 2 ) then
- color = ShadowUF.db.profile.healthColors.neutral
- elseif( happiness == 1 ) then
- color = ShadowUF.db.profile.healthColors.hostile
- end
elseif( not UnitPlayerOrPetInRaid(unit) and not UnitPlayerOrPetInParty(unit) and ( ( ( reactionType == "player" or reactionType == "both" ) and UnitIsPlayer(unit) and not UnitIsFriend(unit, "player") ) or ( ( reactionType == "npc" or reactionType == "both" ) and not UnitIsPlayer(unit) ) ) ) then
if( not UnitIsFriend(unit, "player") and UnitPlayerControlled(unit) ) then
if( UnitCanAttack("player", unit) ) then
@@ -143,18 +116,35 @@ function Health:UpdateColor(frame)
color = ShadowUF.db.profile.healthColors.hostile
end
end
- elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "class" and ( UnitIsPlayer(unit) or UnitCreatureFamily(unit) ) ) then
- local class = UnitCreatureFamily(frame.unit) or select(2, UnitClass(frame.unit))
+ elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "class" and (UnitIsPlayer(unit) or unit == "pet") ) then
+ local class = (unit == "pet") and "PET" or frame:UnitClassToken()
color = class and ShadowUF.db.profile.classColors[class]
+ elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "playerclass" and unit == "pet") then
+ local class = select(2, UnitClass("player"))
+ color = class and ShadowUF.db.profile.classColors[class]
+ elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "playerclass" and (frame.unitType == "partypet" or frame.unitType == "raidpet" or frame.unitType == "arenapet") and (frame.parent or frame.unitType == "raidpet") ) then
+ local unit
+ if frame.unitType == "raidpet" then
+ local id = string.match(frame.unit, "raidpet(%d+)")
+ if id then
+ unit = "raid" .. id
+ end
+ elseif frame.parent then
+ unit = frame.parent.unit
+ end
+ if unit then
+ local class = select(2, UnitClass(unit))
+ color = class and ShadowUF.db.profile.classColors[class]
+ end
elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "static" ) then
color = ShadowUF.db.profile.healthColors.static
end
if( color ) then
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, color.r, color.g, color.b)
+ frame:SetBarColor("healthBar", color.r, color.g, color.b)
else
frame.healthBar.hasPercent = true
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, getGradientColor(unit))
+ frame:SetBarColor("healthBar", getGradientColor(unit))
end
end
@@ -169,13 +159,13 @@ function Health:Update(frame)
if( isOffline ) then
frame.healthBar.wasOffline = true
frame.unitIsOnline = nil
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, ShadowUF.db.profile.healthColors.offline.r, ShadowUF.db.profile.healthColors.offline.g, ShadowUF.db.profile.healthColors.offline.b)
+ frame:SetBarColor("healthBar", ShadowUF.db.profile.healthColors.offline.r, ShadowUF.db.profile.healthColors.offline.g, ShadowUF.db.profile.healthColors.offline.b)
-- The unit was offline, but they no longer are so we need to do a forced color update
elseif( frame.healthBar.wasOffline ) then
frame.healthBar.wasOffline = nil
self:UpdateColor(frame)
-- Color health by percentage
elseif( frame.healthBar.hasPercent ) then
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, getGradientColor(frame.unit))
+ frame:SetBarColor("healthBar", getGradientColor(frame.unit))
end
-end
\ No newline at end of file
+end
diff --git a/modules/helpers.lua b/modules/helpers.lua
new file mode 100755
index 000000000..0b0d1fd8a
--- /dev/null
+++ b/modules/helpers.lua
@@ -0,0 +1,33 @@
+-- Block Timers
+local BlockTimers = {}
+function BlockTimers:Inject(module, event)
+ ShadowUF.Tags.customEvents["SUF_" .. event] = module
+ module.EnableTag = BlockTimers.EnableTag
+ module.DisableTag = BlockTimers.DisableTag
+end
+
+function BlockTimers:EnableTag(frame, fontString)
+ fontString.block.fontString = fontString
+end
+
+function BlockTimers:DisableTag(frame, fontString)
+ fontString.block.fontString = nil
+end
+
+
+ShadowUF.BlockTimers = BlockTimers;
+
+-- Dynamic Blocks
+local DynamicBlocks = {}
+function DynamicBlocks:Inject(module)
+ module.OnLayoutWidgets = function(self, frame)
+ if( not frame.visibility[module.moduleKey] or not frame[module.moduleKey].blocks) then return end
+
+ local height = frame[module.moduleKey]:GetHeight()
+ for _, block in pairs(frame[module.moduleKey].blocks) do
+ block:SetHeight(height)
+ end
+ end
+end
+
+ShadowUF.DynamicBlocks = DynamicBlocks
\ No newline at end of file
diff --git a/modules/highlight.lua b/modules/highlight.lua
old mode 100644
new mode 100755
index 95bef4a5b..46ea1179c
--- a/modules/highlight.lua
+++ b/modules/highlight.lua
@@ -1,5 +1,8 @@
local Highlight = {}
local goldColor, mouseColor = {r = 0.75, g = 0.75, b = 0.35}, {r = 0.75, g = 0.75, b = 0.50}
+local rareColor, eliteColor = {r = 0, g = 0.63, b = 1}, {r = 1, g = 0.81, b = 0}
+
+local canCure = ShadowUF.Units.canCure
ShadowUF:RegisterModule(Highlight, "highlight", ShadowUF.L["Highlight"])
-- Might seem odd to hook my code in the core manually, but HookScript is ~40% slower due to it being a secure hook
@@ -84,16 +87,21 @@ function Highlight:OnEnable(frame)
end
if( ShadowUF.db.profile.units[frame.unitType].highlight.debuff ) then
- frame:RegisterNormalEvent("UNIT_AURA", self, "UpdateAura")
+ frame:RegisterUnitEvent("UNIT_AURA", self, "UpdateAura")
frame:RegisterUpdateFunc(self, "UpdateAura")
end
-
+
if( ShadowUF.db.profile.units[frame.unitType].highlight.mouseover and not frame.highlight.OnEnter ) then
- frame.highlight.OnEnter = frame:GetScript("OnEnter")
- frame.highlight.OnLeave = frame:GetScript("OnLeave")
+ frame.highlight.OnEnter = frame.OnEnter
+ frame.highlight.OnLeave = frame.OnLeave
- frame:SetScript("OnEnter", OnEnter)
- frame:SetScript("OnLeave", OnLeave)
+ frame.OnEnter = OnEnter
+ frame.OnLeave = OnLeave
+ end
+
+ if( ShadowUF.db.profile.units[frame.unitType].highlight.rareMob or ShadowUF.db.profile.units[frame.unitType].highlight.eliteMob ) then
+ frame:RegisterUnitEvent("UNIT_CLASSIFICATION_CHANGED", self, "UpdateClassification")
+ frame:RegisterUpdateFunc(self, "UpdateClassification")
end
end
@@ -113,20 +121,32 @@ function Highlight:OnDisable(frame)
frame.highlight.hasMouseover = nil
frame.highlight:Hide()
+
+ if( frame.highlight.OnEnter ) then
+ frame.OnEnter = frame.highlight.OnEnter
+ frame.OnLeave = frame.highlight.OnLeave
+
+ frame.highlight.OnEnter = nil
+ frame.highlight.OnLeave = nil
+ end
end
function Highlight:Update(frame)
local color
if( frame.highlight.hasDebuff ) then
- color = DebuffTypeColor[frame.highlight.hasDebuff]
+ color = DebuffTypeColor[frame.highlight.hasDebuff] or DebuffTypeColor[""]
elseif( frame.highlight.hasThreat ) then
color = ShadowUF.db.profile.healthColors.hostile
elseif( frame.highlight.hasAttention ) then
color = goldColor
elseif( frame.highlight.hasMouseover ) then
color = mouseColor
+ elseif( ShadowUF.db.profile.units[frame.unitType].highlight.rareMob and ( frame.highlight.hasClassification == "rareelite" or frame.highlight.hasClassification == "rare" ) ) then
+ color = rareColor
+ elseif( ShadowUF.db.profile.units[frame.unitType].highlight.eliteMob and frame.highlight.hasClassification == "elite" ) then
+ color = eliteColor
end
-
+
if( color ) then
frame.highlight.top:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.units[frame.unitType].highlight.alpha)
frame.highlight.left:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.units[frame.unitType].highlight.alpha)
@@ -148,8 +168,27 @@ function Highlight:UpdateAttention(frame)
self:Update(frame)
end
+function Highlight:UpdateClassification(frame)
+ frame.highlight.hasClassification = UnitClassification(frame.unit)
+ self:Update(frame)
+end
+
function Highlight:UpdateAura(frame)
- -- In theory, we don't need aura scanning because the first debuff returned is always one we can cure... in theory
- frame.highlight.hasDebuff = UnitIsFriend(frame.unit, "player") and select(5, UnitDebuff(frame.unit, 1, "RAID")) or nil
+ frame.highlight.hasDebuff = nil
+ if( UnitIsFriend(frame.unit, "player") ) then
+ local id = 0
+ while( true ) do
+ id = id + 1
+ local name, _, _, auraType = UnitDebuff(frame.unit, id)
+ if( not name ) then break end
+ if( auraType == "" ) then auraType = "Enrage" end
+
+ if( canCure[auraType] ) then
+ frame.highlight.hasDebuff = auraType
+ break
+ end
+ end
+ end
+
self:Update(frame)
end
diff --git a/modules/holypower.lua b/modules/holypower.lua
new file mode 100755
index 000000000..015e68d91
--- /dev/null
+++ b/modules/holypower.lua
@@ -0,0 +1,31 @@
+if( not ShadowUF.ComboPoints ) then return end
+
+local HolyPower = setmetatable({}, {__index = ShadowUF.ComboPoints})
+ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN", SPEC_PALADIN_RETRIBUTION, PALADINPOWERBAR_SHOW_LEVEL)
+local holyConfig = {max = 5, key = "holyPower", colorKey = "HOLYPOWER", powerType = Enum.PowerType.HolyPower, eventType = "HOLY_POWER", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"}
+
+function HolyPower:OnEnable(frame)
+ frame.holyPower = frame.holyPower or CreateFrame("Frame", nil, frame)
+ frame.holyPower.cpConfig = holyConfig
+
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks")
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "Update")
+ frame:RegisterUpdateFunc(self, "Update")
+ frame:RegisterUpdateFunc(self, "UpdateBarBlocks")
+
+ holyConfig.max = UnitPowerMax("player", holyConfig.powerType)
+end
+
+function HolyPower:OnLayoutApplied(frame, config)
+ ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config)
+ self:UpdateBarBlocks(frame)
+end
+
+function HolyPower:GetComboPointType()
+ return "holyPower"
+end
+
+function HolyPower:GetPoints(unit)
+ return UnitPower("player", holyConfig.powerType)
+end
\ No newline at end of file
diff --git a/modules/incabsorb.lua b/modules/incabsorb.lua
new file mode 100755
index 000000000..0c22b2fde
--- /dev/null
+++ b/modules/incabsorb.lua
@@ -0,0 +1,50 @@
+local IncAbsorb = setmetatable({["frameKey"] = "incAbsorb", ["colorKey"] = "incAbsorb", ["frameLevelMod"] = 3}, {__index = ShadowUF.IncHeal})
+ShadowUF:RegisterModule(IncAbsorb, "incAbsorb", ShadowUF.L["Incoming absorbs"])
+
+function IncAbsorb:OnEnable(frame)
+ frame.incAbsorb = frame.incAbsorb or ShadowUF.Units:CreateBar(frame)
+
+ frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "UpdateFrame")
+ frame:RegisterUnitEvent("UNIT_HEALTH", self, "UpdateFrame")
+ frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", self, "UpdateFrame")
+ frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", self, "UpdateFrame")
+
+ frame:RegisterUpdateFunc(self, "UpdateFrame")
+end
+
+function IncAbsorb:OnLayoutApplied(frame)
+ if( not frame.visibility[self.frameKey] or not frame.visibility.healthBar ) then return end
+
+ if( frame.visibility.incHeal ) then
+ frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", self, "UpdateFrame")
+ else
+ frame:UnregisterSingleEvent("UNIT_HEAL_PREDICTION", self, "UpdateFrame")
+ end
+
+ if( frame.visibility.healAbsorb ) then
+ frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", self, "UpdateFrame")
+ else
+ frame:UnregisterSingleEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", self, "UpdateFrame")
+ end
+
+ ShadowUF.IncHeal.OnLayoutApplied(self, frame)
+end
+
+function IncAbsorb:UpdateFrame(frame)
+ if( not frame.visibility[self.frameKey] or not frame.visibility.healthBar ) then return end
+
+ local amount = UnitGetTotalAbsorbs(frame.unit) or 0
+
+ -- Obviously we only want to add incoming heals if we have something being absorbed
+ if( amount > 0 ) then
+ if( frame.visibility.incHeal ) then
+ amount = amount + (UnitGetIncomingHeals(frame.unit) or 0)
+ end
+
+ if( frame.visibility.healAbsorb ) then
+ amount = amount + (UnitGetTotalHealAbsorbs(frame.unit) or 0)
+ end
+ end
+
+ self:PositionBar(frame, amount)
+end
\ No newline at end of file
diff --git a/modules/incheal.lua b/modules/incheal.lua
index f0e940430..cc620f5c1 100755
--- a/modules/incheal.lua
+++ b/modules/incheal.lua
@@ -1,195 +1,147 @@
-local HealComm = LibStub("LibHealComm-4.0", true)
-if( not HealComm ) then return end
-
-local IncHeal = {}
-local frames = {}
-local playerEndTime, playerGUID
+local IncHeal = {["frameKey"] = "incHeal", ["colorKey"] = "inc", ["frameLevelMod"] = 2}
+ShadowUF.IncHeal = IncHeal
ShadowUF:RegisterModule(IncHeal, "incHeal", ShadowUF.L["Incoming heals"])
-ShadowUF.Tags.customEvents["HEALCOMM"] = IncHeal
-
--- How far ahead to show heals at most
-local INCOMING_SECONDS = 3
function IncHeal:OnEnable(frame)
- frames[frame] = true
frame.incHeal = frame.incHeal or ShadowUF.Units:CreateBar(frame)
-
+
frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "UpdateFrame")
frame:RegisterUnitEvent("UNIT_HEALTH", self, "UpdateFrame")
+ frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", self, "UpdateFrame")
+ frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", self, "UpdateFrame")
+
frame:RegisterUpdateFunc(self, "UpdateFrame")
-
- self:Setup()
end
function IncHeal:OnDisable(frame)
frame:UnregisterAll(self)
- frame.incHeal:Hide()
-
- if( not frame.hasHCTag ) then
- frames[frame] = nil
- self:Setup()
- end
+ frame[self.frameKey]:Hide()
end
function IncHeal:OnLayoutApplied(frame)
- if( frame.visibility.incHeal and frame.visibility.healthBar ) then
- frame.incHeal:SetHeight(frame.healthBar:GetHeight())
- frame.incHeal:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
- frame.incHeal:SetStatusBarColor(ShadowUF.db.profile.healthColors.inc.r, ShadowUF.db.profile.healthColors.inc.g, ShadowUF.db.profile.healthColors.inc.b, ShadowUF.db.profile.bars.alpha)
- frame.incHeal:GetStatusBarTexture():SetHorizTile(false)
- frame.incHeal:Hide()
+ local bar = frame[self.frameKey]
+ if( not frame.visibility[self.frameKey] or not frame.visibility.healthBar ) then return end
+
+ if( frame.visibility.healAbsorb ) then
+ frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", self, "UpdateFrame")
+ else
+ frame:UnregisterSingleEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", self, "UpdateFrame")
+ end
+
+ -- Since we're hiding, reset state
+ bar.total = nil
+
+ bar:SetSize(frame.healthBar:GetSize())
+ bar:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
+ bar:SetStatusBarColor(ShadowUF.db.profile.healthColors[self.colorKey].r, ShadowUF.db.profile.healthColors[self.colorKey].g, ShadowUF.db.profile.healthColors[self.colorKey].b, ShadowUF.db.profile.bars.alpha)
+ bar:GetStatusBarTexture():SetHorizTile(false)
+ bar:SetOrientation(frame.healthBar:GetOrientation())
+ bar:SetReverseFill(frame.healthBar:GetReverseFill())
+ bar:Hide()
+
+ local cap = ShadowUF.db.profile.units[frame.unitType][self.frameKey].cap or 1.30
+
+ -- When we can cheat and put the incoming bar right behind the health bar, we can efficiently show the incoming heal bar
+ -- if the main bar has a transparency set, then we need a more complicated method to stop the health bar from being darker with incoming heals up
+ if( ( ShadowUF.db.profile.units[frame.unitType].healthBar.invert and ShadowUF.db.profile.bars.backgroundAlpha == 0 ) or ( not ShadowUF.db.profile.units[frame.unitType].healthBar.invert and ShadowUF.db.profile.bars.alpha == 1 ) ) then
+ bar.simple = true
+ bar:SetFrameLevel(frame.topFrameLevel - self.frameLevelMod)
+
+ if( bar:GetOrientation() == "HORIZONTAL" ) then
+ bar:SetWidth(frame.healthBar:GetWidth() * cap)
+ else
+ bar:SetHeight(frame.healthBar:GetHeight() * cap)
+ end
+
+ bar:ClearAllPoints()
- -- When we can cheat and put the incoming bar right behind the health bar, we can efficiently show the incoming heal bar
- -- if the main bar has a transparency set, then we need a more complicated method to stop the health bar from being darker with incoming heals up
- if( ( ShadowUF.db.profile.units[frame.unitType].healthBar.invert and ShadowUF.db.profile.bars.backgroundAlpha == 0 ) or ( not ShadowUF.db.profile.units[frame.unitType].healthBar.invert and ShadowUF.db.profile.bars.alpha == 1 ) ) then
- frame.incHeal.simple = true
- frame.incHeal:SetWidth(frame.healthBar:GetWidth() * ShadowUF.db.profile.units[frame.unitType].incHeal.cap)
- frame.incHeal:SetFrameLevel(frame.topFrameLevel - 3)
-
- frame.incHeal:ClearAllPoints()
- frame.incHeal:SetPoint("TOPLEFT", frame.healthBar)
- frame.incHeal:SetPoint("BOTTOMLEFT", frame.healthBar)
+ local point = bar:GetReverseFill() and "RIGHT" or "LEFT"
+ bar:SetPoint("TOP" .. point, frame.healthBar)
+ bar:SetPoint("BOTTOM" .. point, frame.healthBar)
+ else
+ bar.simple = nil
+ bar:SetFrameLevel(frame.topFrameLevel - self.frameLevelMod + 3)
+ bar:SetWidth(1)
+ bar:SetMinMaxValues(0, 1)
+ bar:SetValue(1)
+ bar:ClearAllPoints()
+
+ bar.orientation = bar:GetOrientation()
+ bar.reverseFill = bar:GetReverseFill()
+
+ if( bar.orientation == "HORIZONTAL" ) then
+ bar.healthSize = frame.healthBar:GetWidth()
+ bar.positionPoint = bar.reverseFill and "TOPRIGHT" or "TOPLEFT"
+ bar.positionRelative = bar.reverseFill and "BOTTOMRIGHT" or "BOTTOMLEFT"
else
- frame.incHeal.simple = nil
- frame.incHeal:SetFrameLevel(frame.topFrameLevel)
- frame.incHeal:SetWidth(1)
- frame.incHeal:SetMinMaxValues(0, 1)
- frame.incHeal:SetValue(1)
-
- local x, y = select(4, frame.healthBar:GetPoint())
- frame.incHeal:ClearAllPoints()
- frame.incHeal.healthX = x
- frame.incHeal.healthY = y
- frame.incHeal.healthWidth = frame.healthBar:GetWidth()
- frame.incHeal.maxWidth = frame.incHeal.healthWidth * ShadowUF.db.profile.units[frame.unitType].incHeal.cap
- frame.incHeal.cappedWidth = frame.incHeal.healthWidth * (ShadowUF.db.profile.units[frame.unitType].incHeal.cap - 1)
+ bar.healthSize = frame.healthBar:GetHeight()
+ bar.positionPoint = bar.reverseFill and "TOPLEFT" or "BOTTOMLEFT"
+ bar.positionRelative = bar.reverseFill and "TOPRIGHT" or "BOTTOMRIGHT"
end
- end
-end
--- Since I don't want a more complicated system where both incheal.lua and tags.lua are watching the same events
--- I'll update the HC tags through here instead
-function IncHeal:EnableTag(frame)
- frames[frame] = true
- frame.hasHCTag = true
-
- self:Setup()
+ bar.positionMod = bar.reverseFill and -1 or 1
+ bar.maxSize = bar.healthSize * cap
+ end
end
-function IncHeal:DisableTag(frame)
- frame.hasHCTag = nil
-
- if( not frame.visibility.incHeal ) then
- frames[frame] = nil
- self:Setup()
+function IncHeal:PositionBar(frame, incAmount)
+ local bar = frame[self.frameKey]
+ -- If incoming is <= 0 ir health is <= 0 we can hide it
+ if( incAmount <= 0 ) then
+ bar.total = nil
+ bar:Hide()
+ return
end
-end
--- Check if we need to register callbacks
-function IncHeal:Setup()
- playerGUID = UnitGUID("player")
-
- local enabled
- for frame in pairs(frames) do
- enabled = true
- break
+ local health = UnitHealth(frame.unit)
+ if( health <= 0 ) then
+ bar.total = nil
+ bar:Hide()
+ return
end
-
- if( not enabled ) then
- if( HealComm ) then
- HealComm:UnregisterAllCallbacks(IncHeal)
- end
+
+ local maxHealth = UnitHealthMax(frame.unit)
+ if( maxHealth <= 0 ) then
+ bar.total = nil
+ bar:Hide()
return
end
- HealComm.RegisterCallback(self, "HealComm_HealStarted", "HealComm_HealUpdated")
- HealComm.RegisterCallback(self, "HealComm_HealStopped")
- HealComm.RegisterCallback(self, "HealComm_HealDelayed", "HealComm_HealUpdated")
- HealComm.RegisterCallback(self, "HealComm_HealUpdated")
- HealComm.RegisterCallback(self, "HealComm_ModifierChanged")
- HealComm.RegisterCallback(self, "HealComm_GUIDDisappeared")
-end
+ if( not bar.total ) then bar:Show() end
+ bar.total = incAmount
--- Update any tags using HC
-function IncHeal:UpdateTags(frame, amount)
- if( not frame.fontStrings or not frame.hasHCTag ) then return end
-
- for _, fontString in pairs(frame.fontStrings) do
- if( fontString.HEALCOMM ) then
- fontString.incoming = amount > 0 and amount or nil
- fontString:UpdateTags()
+ -- When the primary bar has an alpha of 100%, we can cheat and do incoming heals easily. Otherwise we need to do it a more complex way to keep it looking good
+ if( bar.simple ) then
+ bar.total = health + incAmount
+ bar:SetMinMaxValues(0, maxHealth * (ShadowUF.db.profile.units[frame.unitType][self.frameKey].cap or 1.30))
+ bar:SetValue(bar.total)
+ else
+ local healthSize = bar.healthSize * (health / maxHealth)
+ local incSize = bar.healthSize * (incAmount / maxHealth)
+
+ if( (healthSize + incSize) > bar.maxSize ) then
+ incSize = bar.maxSize - healthSize
end
- end
-end
-local function updateHealthBar(frame, interrupted)
- -- This makes sure that when a heal like Tranquility is cast, it won't show the entire cast but cap it at 4 seconds into the future
- local time = GetTime()
- local timeBand = playerEndTime and math.min(playerEndTime - time, INCOMING_SECONDS) or INCOMING_SECONDS
- local healed = (HealComm:GetHealAmount(frame.unitGUID, HealComm.ALL_HEALS, time + timeBand) or 0) * HealComm:GetHealModifier(frame.unitGUID)
-
- -- Update any tags that are using HC data
- IncHeal:UpdateTags(frame, healed)
-
- -- Bar is also supposed to be enabled, lets update that too
- if( frame.visibility.incHeal and frame.visibility.healthBar ) then
- if( healed > 0 ) then
- frame.incHeal.healed = healed
- frame.incHeal:Show()
-
- -- When the primary bar has an alpha of 100%, we can cheat and do incoming heals easily. Otherwise we need to do it a more complex way to keep it looking good
- if( frame.incHeal.simple ) then
- frame.incHeal.total = UnitHealth(frame.unit) + healed
- frame.incHeal:SetMinMaxValues(0, UnitHealthMax(frame.unit) * ShadowUF.db.profile.units[frame.unitType].incHeal.cap)
- frame.incHeal:SetValue(frame.incHeal.total)
- else
- local health, maxHealth = UnitHealth(frame.unit), UnitHealthMax(frame.unit)
- local healthWidth = frame.incHeal.healthWidth * (health / maxHealth)
- local incWidth = frame.healthBar:GetWidth() * (healed / health)
- if( (healthWidth + incWidth) > frame.incHeal.maxWidth ) then
- incWidth = frame.incHeal.cappedWidth
- end
-
- frame.incHeal:SetWidth(incWidth)
- frame.incHeal:SetPoint("TOPLEFT", SUFUnitplayer, "TOPLEFT", frame.incHeal.healthX + healthWidth, frame.incHeal.healthY)
- end
+ if( bar.orientation == "HORIZONTAL" ) then
+ bar:SetWidth(incSize)
+ bar:SetPoint(bar.positionPoint, frame.healthBar, bar.positionMod * healthSize, 0)
+ bar:SetPoint(bar.positionRelative, frame.healthBar, bar.positionMod * healthSize, 0)
else
- frame.incHeal.total = nil
- frame.incHeal.healed = nil
- frame.incHeal:Hide()
+ bar:SetHeight(incSize)
+ bar:SetPoint(bar.positionPoint, frame.healthBar, 0, bar.positionMod * healthSize)
+ bar:SetPoint(bar.positionRelative, frame.healthBar, 0, bar.positionMod * healthSize)
end
end
end
function IncHeal:UpdateFrame(frame)
- updateHealthBar(frame, true)
-end
-
-function IncHeal:UpdateIncoming(interrupted, ...)
- for frame in pairs(frames) do
- for i=1, select("#", ...) do
- if( select(i, ...) == frame.unitGUID ) then
- updateHealthBar(frame, interrupted)
- end
- end
+ if( not frame.visibility[self.frameKey] or not frame.visibility.healthBar ) then return end
+
+ local amount = UnitGetIncomingHeals(frame.unit) or 0
+ if( amount > 0 and frame.visibility.healAbsorb ) then
+ amount = amount + (UnitGetTotalHealAbsorbs(frame.unit) or 0)
end
-end
-
--- Handle callbacks from HealComm
-function IncHeal:HealComm_HealUpdated(event, casterGUID, spellID, healType, endTime, ...)
- if( casterGUID == playerGUID and bit.band(healType, HealComm.CASTED_HEALS) > 0 ) then playerEndTime = endTime end
- self:UpdateIncoming(nil, ...)
-end
-
-function IncHeal:HealComm_HealStopped(event, casterGUID, spellID, healType, interrupted, ...)
- if( casterGUID == playerGUID and bit.band(healType, HealComm.CASTED_HEALS) > 0 ) then playerEndTime = nil end
- self:UpdateIncoming(interrupted, ...)
-end
-
-function IncHeal:HealComm_ModifierChanged(event, guid)
- self:UpdateIncoming(nil, guid)
-end
-function IncHeal:HealComm_GUIDDisappeared(event, guid)
- self:UpdateIncoming(true, guid)
+ self:PositionBar(frame, amount)
end
diff --git a/modules/indicators.lua b/modules/indicators.lua
old mode 100644
new mode 100755
index dbc054da8..ea9c7694a
--- a/modules/indicators.lua
+++ b/modules/indicators.lua
@@ -1,14 +1,26 @@
-local Indicators = {list = {"status", "pvp", "leader", "masterLoot", "raidTarget", "happiness", "ready", "role", "lfdRole", "class"}}
-local leavingWorld
+local Indicators = {list = {"status", "pvp", "leader", "resurrect", "masterLoot", "raidTarget", "ready", "role", "lfdRole", "class", "phase", "questBoss", "petBattle", "arenaSpec"}}
ShadowUF:RegisterModule(Indicators, "indicators", ShadowUF.L["Indicators"])
+function Indicators:UpdateArenaSpec(frame)
+ if( not frame.indicators.arenaSpec or not frame.indicators.arenaSpec.enabled ) then return end
+
+ local specID = GetArenaOpponentSpec(frame.unitID)
+ local specIcon = specID and select(4, GetSpecializationInfoByID(specID))
+ if( specIcon ) then
+ frame.indicators.arenaSpec:SetTexture(specIcon)
+ frame.indicators.arenaSpec:Show()
+ else
+ frame.indicators.arenaSpec:Hide()
+ end
+end
+
function Indicators:UpdateClass(frame)
if( not frame.indicators.class or not frame.indicators.class.enabled ) then return end
- local class = select(2, UnitClass(frame.unit))
+ local class = frame:UnitClassToken()
if( UnitIsPlayer(frame.unit) and class ) then
- local coords = CLASS_BUTTONS[class]
+ local coords = CLASS_ICON_TCOORDS[class]
frame.indicators.class:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes")
frame.indicators.class:SetTexCoord(coords[1], coords[2], coords[3], coords[4])
frame.indicators.class:Show()
@@ -17,22 +29,26 @@ function Indicators:UpdateClass(frame)
end
end
-function Indicators:UpdateHappiness(frame)
- if( not frame.indicators.happiness or not frame.indicators.happiness.enabled ) then return end
-
- local happiness = GetPetHappiness()
- if( not happiness ) then
- frame.indicators.happiness:Hide()
- elseif( happiness == 3 ) then
- frame.indicators.happiness:SetTexCoord(0, 0.1875, 0, 0.359375)
- frame.indicators.happiness:Show()
- elseif( happiness == 2 ) then
- frame.indicators.happiness:SetTexCoord(0.1875, 0.375, 0, 0.359375)
- frame.indicators.happiness:Show()
- elseif( happiness == 1 ) then
- frame.indicators.happiness:SetTexCoord(0.375, 0.5625, 0, 0.359375)
- frame.indicators.happiness:Show()
- end
+function Indicators:UpdatePhase(frame)
+ if( not frame.indicators.phase or not frame.indicators.phase.enabled ) then return end
+
+ if( UnitIsConnected(frame.unit) and not UnitInPhase(frame.unit) ) then
+ frame.indicators.phase:SetTexture("Interface\\TargetingFrame\\UI-PhasingIcon")
+ frame.indicators.phase:SetTexCoord(0.15625, 0.84375, 0.15625, 0.84375)
+ frame.indicators.phase:Show()
+ else
+ frame.indicators.phase:Hide()
+ end
+end
+
+function Indicators:UpdateResurrect(frame)
+ if( not frame.indicators.resurrect or not frame.indicators.resurrect.enabled ) then return end
+
+ if( UnitHasIncomingResurrection(frame.unit) ) then
+ frame.indicators.resurrect:Show()
+ else
+ frame.indicators.resurrect:Hide()
+ end
end
function Indicators:UpdateMasterLoot(frame)
@@ -47,7 +63,7 @@ function Indicators:UpdateMasterLoot(frame)
frame.indicators.masterLoot:Hide()
end
end
-
+
function Indicators:UpdateRaidTarget(frame)
if( not frame.indicators.raidTarget or not frame.indicators.raidTarget.enabled ) then return end
@@ -59,17 +75,34 @@ function Indicators:UpdateRaidTarget(frame)
end
end
+function Indicators:UpdateQuestBoss(frame)
+ if( not frame.indicators.questBoss or not frame.indicators.questBoss.enabled ) then return end
+
+ if( UnitIsQuestBoss(frame.unit) ) then
+ frame.indicators.questBoss:Show()
+ else
+ frame.indicators.questBoss:Hide()
+ end
+end
+
function Indicators:UpdateLFDRole(frame, event)
if( not frame.indicators.lfdRole or not frame.indicators.lfdRole.enabled ) then return end
- local isTank, isHealer, isDamage = UnitGroupRolesAssigned(frame.unitOwner)
- if( isTank ) then
+ local role
+ if( frame.unitType ~= "arena" ) then
+ role = UnitGroupRolesAssigned(frame.unitOwner)
+ else
+ local specID = GetArenaOpponentSpec(frame.unitID)
+ role = specID and select(6, GetSpecializationInfoByID(specID))
+ end
+
+ if( role == "TANK" ) then
frame.indicators.lfdRole:SetTexCoord(0, 19/64, 22/64, 41/64)
frame.indicators.lfdRole:Show()
- elseif( isHealer ) then
+ elseif( role == "HEALER" ) then
frame.indicators.lfdRole:SetTexCoord(20/64, 39/64, 1/64, 20/64)
frame.indicators.lfdRole:Show()
- elseif( isDamage ) then
+ elseif( role == "DAMAGER" ) then
frame.indicators.lfdRole:SetTexCoord(20/64, 39/64, 22/64, 41/64)
frame.indicators.lfdRole:Show()
else
@@ -80,7 +113,7 @@ end
function Indicators:UpdateRole(frame, event)
if( not frame.indicators.role or not frame.indicators.role.enabled ) then return end
- if( leavingWorld or not UnitInRaid(frame.unit) and not UnitInParty(frame.unit) ) then
+ if( not UnitInRaid(frame.unit) and not UnitInParty(frame.unit) ) then
frame.indicators.role:Hide()
elseif( GetPartyAssignment("MAINTANK", frame.unit) ) then
frame.indicators.role:SetTexture("Interface\\GroupFrame\\UI-Group-MainTankIcon")
@@ -94,32 +127,62 @@ function Indicators:UpdateRole(frame, event)
end
function Indicators:UpdateLeader(frame)
- self:UpdateMasterLoot(frame)
- self:UpdateRole(frame)
- self:UpdateLFDRole(frame)
if( not frame.indicators.leader or not frame.indicators.leader.enabled ) then return end
- if( UnitIsPartyLeader(frame.unit) ) then
+ if( UnitIsGroupLeader(frame.unit) ) then
+ if( HasLFGRestrictions() ) then
+ frame.indicators.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES")
+ frame.indicators.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125)
+ else
+ frame.indicators.leader:SetTexture("Interface\\GroupFrame\\UI-Group-LeaderIcon")
+ frame.indicators.leader:SetTexCoord(0, 1, 0, 1)
+ end
+
+ frame.indicators.leader:Show()
+
+ elseif( UnitIsGroupAssistant(frame.unit) or ( UnitInRaid(frame.unit) and IsEveryoneAssistant() ) ) then
+ frame.indicators.leader:SetTexture("Interface\\GroupFrame\\UI-Group-AssistantIcon")
+ frame.indicators.leader:SetTexCoord(0, 1, 0, 1)
frame.indicators.leader:Show()
else
frame.indicators.leader:Hide()
end
end
+function Indicators:GroupRosterUpdate(frame)
+ self:UpdateMasterLoot(frame)
+ self:UpdateRole(frame)
+ self:UpdateLFDRole(frame)
+ self:UpdateLeader(frame)
+end
+
function Indicators:UpdatePVPFlag(frame)
if( not frame.indicators.pvp or not frame.indicators.pvp.enabled ) then return end
- if( UnitIsPVP(frame.unit) and UnitFactionGroup(frame.unit) ) then
- frame.indicators.pvp:SetTexture(string.format("Interface\\TargetingFrame\\UI-PVP-%s", UnitFactionGroup(frame.unit)))
- frame.indicators.pvp:Show()
- elseif( UnitIsPVPFreeForAll(frame.unit) ) then
+ local faction = UnitFactionGroup(frame.unit)
+ if( UnitIsPVPFreeForAll(frame.unit) ) then
frame.indicators.pvp:SetTexture("Interface\\TargetingFrame\\UI-PVP-FFA")
+ frame.indicators.pvp:SetTexCoord(0,1,0,1)
+ frame.indicators.pvp:Show()
+ elseif( faction and faction ~= "Neutral" and UnitIsPVP(frame.unit) ) then
+ frame.indicators.pvp:SetTexture(string.format("Interface\\TargetingFrame\\UI-PVP-%s", faction))
+ frame.indicators.pvp:SetTexCoord(0,1,0,1)
frame.indicators.pvp:Show()
else
frame.indicators.pvp:Hide()
end
end
+function Indicators:UpdatePetBattle(frame)
+ if( UnitIsWildBattlePet(frame.unit) or UnitIsBattlePetCompanion(frame.unit) ) then
+ local petType = UnitBattlePetType(frame.unit)
+ frame.indicators.petBattle:SetTexture(string.format("Interface\\TargetingFrame\\PetBadge-%s", PET_TYPE_SUFFIX[petType]))
+ frame.indicators.petBattle:Show()
+ else
+ frame.indicators.petBattle:Hide()
+ end
+end
+
-- Non-player units do not give events when they enter or leave combat, so polling is necessary
local function combatMonitor(self, elapsed)
self.timeElapsed = self.timeElapsed + elapsed
@@ -234,7 +297,7 @@ function Indicators:OnEnable(frame)
-- Forces the indicators to be above the bars/portraits/etc
if( not frame.indicators ) then
frame.indicators = CreateFrame("Frame", nil, frame)
- frame.indicators:SetFrameLevel(frame.topFrameLevel + 1)
+ frame.indicators:SetFrameLevel(frame.topFrameLevel + 2)
end
-- Now lets enable all the indicators
@@ -259,7 +322,29 @@ function Indicators:OnEnable(frame)
elseif( frame.indicators.status ) then
frame.indicators:SetScript("OnUpdate", nil)
end
-
+
+ if( config.indicators.arenaSpec and config.indicators.arenaSpec.enabled ) then
+ frame:RegisterNormalEvent("ARENA_OPPONENT_UPDATE", self, "UpdateArenaSpec")
+ frame:RegisterUpdateFunc(self, "UpdateArenaSpec")
+ frame.indicators.arenaSpec = frame.indicators.arenaSpec or frame.indicators:CreateTexture(nil, "OVERLAY")
+ end
+
+ if( config.indicators.phase and config.indicators.phase.enabled ) then
+ -- Player phase changes do not generate a phase change event. This seems to be the best
+ -- TODO: what event does fire here? frame:RegisterNormalEvent("UPDATE_WORLD_STATES", self, "UpdatePhase")
+ frame:RegisterUpdateFunc(self, "UpdatePhase")
+ frame.indicators.phase = frame.indicators.phase or frame.indicators:CreateTexture(nil, "OVERLAY")
+ end
+
+ if( config.indicators.resurrect and config.indicators.resurrect.enabled ) then
+ frame:RegisterNormalEvent("INCOMING_RESURRECT_CHANGED", self, "UpdateResurrect")
+ frame:RegisterNormalEvent("UNIT_OTHER_PARTY_CHANGED", self, "UpdateResurrect")
+ frame:RegisterUpdateFunc(self, "UpdateResurrect")
+
+ frame.indicators.resurrect = frame.indicators.resurrect or frame.indicators:CreateTexture(nil, "OVERLAY")
+ frame.indicators.resurrect:SetTexture("Interface\\RaidFrame\\Raid-Icon-Rez")
+ end
+
if( config.indicators.pvp and config.indicators.pvp.enabled ) then
frame:RegisterUnitEvent("PLAYER_FLAGS_CHANGED", self, "UpdatePVPFlag")
frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdatePVPFlag")
@@ -278,12 +363,10 @@ function Indicators:OnEnable(frame)
frame:RegisterUpdateFunc(self, "UpdateLeader")
frame.indicators.leader = frame.indicators.leader or frame.indicators:CreateTexture(nil, "OVERLAY")
- frame.indicators.leader:SetTexture("Interface\\GroupFrame\\UI-Group-LeaderIcon")
end
if( config.indicators.masterLoot and config.indicators.masterLoot.enabled ) then
frame:RegisterNormalEvent("PARTY_LOOT_METHOD_CHANGED", self, "UpdateMasterLoot")
- frame:RegisterNormalEvent("RAID_ROSTER_UPDATE", self, "UpdateMasterLoot")
frame:RegisterUpdateFunc(self, "UpdateMasterLoot")
frame.indicators.masterLoot = frame.indicators.masterLoot or frame.indicators:CreateTexture(nil, "OVERLAY")
@@ -295,26 +378,6 @@ function Indicators:OnEnable(frame)
frame.indicators.role = frame.indicators.role or frame.indicators:CreateTexture(nil, "OVERLAY")
frame.indicators.role:SetTexture("Interface\\GroupFrame\\UI-Group-MainAssistIcon")
-
- -- Silly hack to fix the fact that Blizzard bugged an API and causes " is not in your party" errors
- if( not self.leavingFrame ) then
- self.leavingFrame = CreateFrame("Frame")
- self.leavingFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
- self.leavingFrame:RegisterEvent("PLAYER_LEAVING_WORLD")
- self.leavingFrame:SetScript("OnEvent", function(self, event)
- if( event == "PLAYER_LEAVING_WORLD" ) then
- leavingWorld = true
- else
- leavingWorld = nil
-
- for frame in pairs(ShadowUF.Units.frameList) do
- if( frame:IsVisible() and frame.indicators and frame.indicators.role and frame.indicators.role.enabled ) then
- Indicators:UpdateRole(frame)
- end
- end
- end
- end)
- end
end
if( config.indicators.raidTarget and config.indicators.raidTarget.enabled ) then
@@ -333,27 +396,31 @@ function Indicators:OnEnable(frame)
frame.indicators.ready = frame.indicators.ready or frame.indicators:CreateTexture(nil, "OVERLAY")
end
-
- if( config.indicators.happiness and config.indicators.happiness.enabled ) then
- frame:RegisterUnitEvent("UNIT_HAPPINESS", self, "UpdateHappiness")
- frame:RegisterUpdateFunc(self, "UpdateHappiness")
- frame.indicators.happiness = frame.indicators.happiness or frame.indicators:CreateTexture(nil, "OVERLAY")
- frame.indicators.happiness:SetTexture("Interface\\PetPaperDollFrame\\UI-PetHappiness")
- end
-
if( config.indicators.lfdRole and config.indicators.lfdRole.enabled ) then
- if( frame.unit == "player" ) then
- frame:RegisterNormalEvent("PLAYER_ROLES_ASSIGNED", self, "UpdateLFDRole")
- end
-
+ frame:RegisterNormalEvent("PLAYER_ROLES_ASSIGNED", self, "UpdateLFDRole")
+ frame:RegisterUpdateFunc(self, "UpdateLFDRole")
+
frame.indicators.lfdRole = frame.indicators.lfdRole or frame.indicators:CreateTexture(nil, "OVERLAY")
frame.indicators.lfdRole:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES")
end
+ if( config.indicators.questBoss and config.indicators.questBoss.enabled ) then
+ frame:RegisterUnitEvent("UNIT_CLASSIFICATION_CHANGED", self, "UpdateQuestBoss")
+ frame:RegisterUpdateFunc(self, "UpdateQuestBoss")
+
+ frame.indicators.questBoss = frame.indicators.questBoss or frame.indicators:CreateTexture(nil, "OVERLAY")
+ frame.indicators.questBoss:SetTexture("Interface\\TargetingFrame\\PortraitQuestBadge")
+ end
+
+ if( config.indicators.petBattle and config.indicators.petBattle.enabled ) then
+ frame:RegisterUpdateFunc(self, "UpdatePetBattle")
+ frame.indicators.petBattle = frame.indicators.petBattle or frame.indicators:CreateTexture(nil, "OVERLAY")
+ end
+
-- As they all share the function, register it as long as one is active
if( frame.indicators.leader or frame.indicators.masterLoot or frame.indicators.role or ( frame.unit ~= "player" and frame.indicators.lfdRole ) ) then
- frame:RegisterNormalEvent("PARTY_MEMBERS_CHANGED", self, "UpdateLeader")
+ frame:RegisterNormalEvent("GROUP_ROSTER_UPDATE", self, "GroupRosterUpdate")
end
end
@@ -375,7 +442,7 @@ function Indicators:OnLayoutApplied(frame, config)
for _, key in pairs(self.list) do
local indicator = frame.indicators[key]
- if( indicator and config.indicators[key].enabled and config.indicators[key].size ) then
+ if( indicator and config.indicators[key] and config.indicators[key].enabled and config.indicators[key].size ) then
indicator.enabled = true
indicator:SetHeight(config.indicators[key].size)
indicator:SetWidth(config.indicators[key].size)
@@ -391,4 +458,4 @@ function Indicators:OnLayoutApplied(frame, config)
frame.indicators:SetScript("OnUpdate", nil)
end
end
-end
\ No newline at end of file
+end
diff --git a/modules/layout.lua b/modules/layout.lua
index b08d3fff6..1f9a9784b 100755
--- a/modules/layout.lua
+++ b/modules/layout.lua
@@ -34,7 +34,7 @@ local function updateBackdrop()
-- Update the backdrop table
local backdrop = ShadowUF.db.profile.backdrop
backdropTbl.bgFile = mediaPath.background
- backdropTbl.edgeFile = mediaPath.border
+ if( mediaPath.border ~= "Interface\\None" ) then backdropTbl.edgeFile = mediaPath.border end
backdropTbl.tile = backdrop.tileSize > 0 and true or false
backdropTbl.edgeSize = backdrop.edgeSize
backdropTbl.tileSize = backdrop.tileSize
@@ -74,10 +74,21 @@ function Layout:ToggleVisibility(frame, visible)
end
function Layout:SetBarVisibility(frame, key, status)
+ if( frame.secureLocked ) then return end
+
+ -- Show the bar if it wasn't already
if( status and not frame[key]:IsVisible() ) then
+ ShadowUF.Tags:FastRegister(frame, frame[key])
+
+ frame[key].visibilityManaged = true
frame[key]:Show()
ShadowUF.Layout:PositionWidgets(frame, ShadowUF.db.profile.units[frame.unitType])
+
+ -- Hide the bar if it wasn't already
elseif( not status and frame[key]:IsVisible() ) then
+ ShadowUF.Tags:FastUnregister(frame, frame[key])
+
+ frame[key].visibilityManaged = nil
frame[key]:Hide()
ShadowUF.Layout:PositionWidgets(frame, ShadowUF.db.profile.units[frame.unitType])
end
@@ -96,7 +107,16 @@ function Layout:Reload(unit)
frame:FullUpdate()
end
end
-
+
+ for header in pairs(ShadowUF.Units.headerFrames) do
+ if( header.unitType and ( not unit or header.unitType == unit ) ) then
+ local config = ShadowUF.db.profile.units[header.unitType]
+ header:SetAttribute("style-height", config.height)
+ header:SetAttribute("style-width", config.width)
+ header:SetAttribute("style-scale", config.scale)
+ end
+ end
+
ShadowUF:FireModuleEvent("OnLayoutReload", unit)
end
@@ -106,6 +126,16 @@ function Layout:Load(frame)
-- About to set layout
ShadowUF:FireModuleEvent("OnPreLayoutApply", frame, unitConfig)
+
+ -- Figure out if we're secure locking
+ frame.secureLocked = nil
+ for _, module in pairs(ShadowUF.moduleOrder) do
+ if( frame.visibility[module.moduleKey] and ShadowUF.db.profile.units[frame.unitType][module.moduleKey] and
+ ShadowUF.db.profile.units[frame.unitType][module.moduleKey].secure and module:SecureLockable() ) then
+ frame.secureLocked = true
+ break
+ end
+ end
-- Load all of the layout things
self:SetupFrame(frame, unitConfig)
@@ -266,6 +296,10 @@ function Layout:AnchorFrame(parent, frame, config)
return
end
end
+
+ if( config.block ) then
+ anchorTo = anchorTo.blocks[frame.blockID]
+ end
-- Figure out where it's anchored
local point = config.point and config.point ~= "" and config.point or preDefPoint[config.anchorPoint] or "CENTER"
@@ -331,15 +365,22 @@ function Layout:SetupBars(frame, config)
local key = module.moduleKey
local widget = frame[key]
if( widget and ( module.moduleHasBar or config[key] and config[key].isBar ) ) then
- self:ToggleVisibility(widget, frame.visibility[key])
+ if( frame.visibility[key] and not frame[key].visibilityManaged and module.defaultVisibility == false ) then
+ self:ToggleVisibility(widget, false)
+ else
+ self:ToggleVisibility(widget, frame.visibility[key])
+ end
- if( widget:IsShown() and widget.SetStatusBarTexture ) then
+ if( ( widget:IsShown() or ( not frame[key].visibilityManaged and module.defaultVisibility == false ) ) and widget.SetStatusBarTexture ) then
widget:SetStatusBarTexture(mediaPath.statusbar)
widget:GetStatusBarTexture():SetHorizTile(false)
+
+ widget:SetOrientation(config[key].vertical and "VERTICAL" or "HORIZONTAL")
+ widget:SetReverseFill(config[key].reverse and true or false)
end
if( widget.background ) then
- if( config[key].background ) then
+ if( config[key].background or config[key].invert ) then
widget.background:SetTexture(mediaPath.statusbar)
widget.background:SetHorizTile(false)
widget.background:Show()
@@ -374,6 +415,38 @@ function Layout:SetupFontString(fontString, extraSize)
end
local totalWeight = {}
+function Layout:InitFontString(parent, frame, id, config, blockID)
+ local rowID = blockID and tonumber(id .. "." .. blockID) or id
+
+ local fontString = frame.fontStrings[rowID] or frame.highFrame:CreateFontString(nil, "ARTWORK")
+ fontString.configID = id
+ if( blockID ) then
+ fontString.blockID = blockID
+ fontString.block = parent.blocks[blockID]
+ end
+
+ self:SetupFontString(fontString, config.size)
+ fontString:SetTextColor(ShadowUF.db.profile.font.color.r, ShadowUF.db.profile.font.color.g, ShadowUF.db.profile.font.color.b, ShadowUF.db.profile.font.color.a)
+ fontString:SetText(config.text)
+ fontString:SetJustifyH(self:GetJustify(config))
+ self:AnchorFrame(frame, fontString, config)
+
+ -- We figure out the anchor point so we can put text in the same area with the same width requirements
+ local anchorPoint = columnDirection[config.anchorPoint]
+ if( string.len(config.anchorPoint) == 3 ) then anchorPoint = anchorPoint .. "I" end
+
+ fontString.parentBar = parent
+ fontString.availableWidth = parent:GetWidth() - config.x
+ fontString.widthID = config.anchorTo .. anchorPoint .. config.y
+ totalWeight[fontString.widthID] = (totalWeight[fontString.widthID] or 0) + config.width
+
+ ShadowUF.Tags:Register(frame, fontString, config.text)
+ fontString:UpdateTags()
+ fontString:Show()
+
+ frame.fontStrings[rowID] = fontString
+end
+
function Layout:SetupText(frame, config)
-- Update tag text
frame.fontStrings = frame.fontStrings or {}
@@ -386,33 +459,22 @@ function Layout:SetupText(frame, config)
-- Update the actual text, and figure out the weighting information now
for id, row in pairs(config.text) do
- local parent = row.anchorTo == "$parent" and frame or frame[string.sub(row.anchorTo, 2)]
- if( parent and parent:IsShown() and row.enabled and row.text ~= "" ) then
- local fontString = frame.fontStrings[id] or frame.highFrame:CreateFontString(nil, "ARTWORK")
- self:SetupFontString(fontString, row.size)
- fontString:SetTextColor(ShadowUF.db.profile.font.color.r, ShadowUF.db.profile.font.color.g, ShadowUF.db.profile.font.color.b, ShadowUF.db.profile.font.color.a)
- fontString:SetText(row.text)
- fontString:SetJustifyH(self:GetJustify(row))
- self:AnchorFrame(frame, fontString, row)
-
- -- We figure out the anchor point so we can put text in the same area with the same width requirements
- local anchorPoint = columnDirection[row.anchorPoint]
- if( string.len(row.anchorPoint) == 3 ) then anchorPoint = anchorPoint .. "I" end
-
- fontString.availableWidth = parent:GetWidth() - row.x
- fontString.widthID = row.anchorTo .. anchorPoint .. row.y
- totalWeight[fontString.widthID] = (totalWeight[fontString.widthID] or 0) + row.width
-
- ShadowUF.Tags:Register(frame, fontString, row.text)
- fontString:UpdateTags()
- fontString:Show()
-
- frame.fontStrings[id] = fontString
+ local module = string.sub(row.anchorTo, 2)
+ local parent = row.anchorTo == "$parent" and frame or frame[module]
+ if( parent and ( ShadowUF.modules[module].defaultVisibility == false or parent:IsShown() ) and row.enabled and row.text ~= "" ) then
+ if( not row.block ) then
+ self:InitFontString(parent, frame, id, row, nil)
+ else
+ for blockID, block in pairs(parent.blocks) do
+ self:InitFontString(parent, frame, id, row, blockID)
+ end
+ end
end
end
-- Now set all of the width using our weightings
- for id, fontString in pairs(frame.fontStrings) do
+ for _, fontString in pairs(frame.fontStrings) do
+ local id = fontString.configID
if( fontString:IsShown() ) then
fontString:SetWidth(fontString.availableWidth * (config.text[id].width / totalWeight[fontString.widthID]))
fontString:SetHeight(ShadowUF.db.profile.font.size + 1)
@@ -438,11 +500,15 @@ function Layout:PositionWidgets(frame, config)
-- Figure out total weighting as well as what bars are full sized
for i=#(barOrder), 1, -1 do table.remove(barOrder, i) end
for key, module in pairs(ShadowUF.modules) do
+ if( config[key] and not config[key].height ) then config[key].height = 0.50 end
+
if( ( module.moduleHasBar or config[key] and config[key].isBar ) and frame[key] and frame[key]:IsShown() and config[key].height > 0 ) then
totalWeight = totalWeight + config[key].height
totalBars = totalBars + 1
table.insert(barOrder, key)
+
+ config[key].order = config[key].order or 99
-- Decide whats full sized
if( not frame.visibility.portrait or config.portrait.isBar or config[key].order < config.portrait.fullBefore or config[key].order > config.portrait.fullAfter ) then
diff --git a/modules/monkstagger.lua b/modules/monkstagger.lua
new file mode 100755
index 000000000..102d40a24
--- /dev/null
+++ b/modules/monkstagger.lua
@@ -0,0 +1,54 @@
+local Stagger = {}
+ShadowUF:RegisterModule(Stagger, "staggerBar", ShadowUF.L["Stagger bar"], true, "MONK", SPEC_MONK_BREWMASTER)
+
+function Stagger:OnEnable(frame)
+ frame.staggerBar = frame.staggerBar or ShadowUF.Units:CreateBar(frame)
+ frame.staggerBar.timeElapsed = 0
+ frame.staggerBar.parent = frame
+ frame.staggerBar:SetScript("OnUpdate", function(self, elapsed)
+ self.timeElapsed = self.timeElapsed + elapsed
+ if( self.timeElapsed < 0.25 ) then return end
+ self.timeElapsed = self.timeElapsed - 0.25
+
+ Stagger:Update(self.parent)
+ end)
+
+ frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "UpdateMinMax")
+ frame:RegisterUpdateFunc(self, "UpdateMinMax")
+end
+
+function Stagger:OnDisable(frame)
+ frame:UnregisterAll(self)
+end
+
+function Stagger:OnLayoutApplied(frame)
+ if( frame.staggerBar ) then
+ frame.staggerBar.colorState = nil
+ end
+end
+
+function Stagger:UpdateMinMax(frame)
+ frame.staggerBar.maxHealth = UnitHealthMax(frame.unit)
+ frame.staggerBar:SetMinMaxValues(0, frame.staggerBar.maxHealth)
+
+ self:Update(frame)
+end
+
+function Stagger:Update(frame)
+ local stagger = UnitStagger(frame.unit)
+ if( not stagger ) then return end
+
+ -- Figure out how screwed they are
+ local percent = stagger / frame.staggerBar.maxHealth
+ local state
+ if( percent < STAGGER_YELLOW_TRANSITION ) then
+ state = "STAGGER_GREEN"
+ elseif( percent < STAGGER_RED_TRANSITION ) then
+ state = "STAGGER_YELLOW"
+ else
+ state = "STAGGER_RED"
+ end
+
+ frame:SetBarColor("staggerBar", ShadowUF.db.profile.powerColors[state].r, ShadowUF.db.profile.powerColors[state].g, ShadowUF.db.profile.powerColors[state].b)
+ frame.staggerBar:SetValue(stagger)
+end
\ No newline at end of file
diff --git a/modules/movers.lua b/modules/movers.lua
old mode 100644
new mode 100755
index cc8a93912..07e446f56
--- a/modules/movers.lua
+++ b/modules/movers.lua
@@ -22,7 +22,6 @@ local function createConfigEnv()
GetRaidTargetIndex = function(unit) return getValue("GetRaidTargetIndex", unit, math.random(1, 8)) end,
GetLootMethod = function(unit) return "master", 0, 0 end,
GetComboPoints = function() return MAX_COMBO_POINTS end,
- GetPetHappiness = function() return getValue("GetPetHappiness", "pet", math.random(1, 3)) end,
UnitInRaid = function() return true end,
UnitInParty = function() return true end,
UnitIsUnit = function(unitA, unitB) return unitB == "player" and true or false end,
@@ -31,11 +30,58 @@ local function createConfigEnv()
UnitLevel = function(unit) return MAX_PLAYER_LEVEL end,
UnitIsPlayer = function(unit) return unit ~= "boss" and unit ~= "pet" and not string.match(unit, "(%w+)pet") end,
UnitHealth = function(unit) return getValue("UnitHealth", unit, math.random(20000, 50000)) end,
+ UnitIsQuestBoss = function(unit) return unit == "target" or unit == "focus" end,
+ UnitIsWildBattlePet = function(unit) return unit == "target" or unit == "focus" end,
+ UnitBattlePetType = function(unit)
+ if( unit == "target" or unit == "focus" ) then
+ return getValue("UnitBattlePetType", unit, math.random(#(PET_TYPE_SUFFIX)))
+ end
+ end,
+ GetArenaOpponentSpec = function(unitID)
+ return getValue("GetArenaOpponentSpec", unitID, math.random(250, 270))
+ end,
UnitHealthMax = function(unit) return 50000 end,
- UnitPower = function(unit) return getValue("UnitPower", unit, math.random(20000, 50000)) end,
+ UnitPower = function(unit, powerType)
+ if( powerType == Enum.PowerType.HolyPower or powerType == Enum.PowerType.SoulShards ) then
+ return 3
+ elseif( powerType == Enum.PowerType.Chi) then
+ return 4
+ end
+
+ return getValue("UnitPower", unit, math.random(20000, 50000))
+ end,
+ UnitGetTotalHealAbsorbs = function(unit)
+ return getValue("UnitGetTotalHealAbsorbs", unit, math.random(5000, 10000))
+ end,
+ UnitGetIncomingHeals = function(unit)
+ return getValue("UnitGetIncomingHeals", unit, math.random(10000, 15000))
+ end,
+ UnitGetTotalAbsorbs = function(unit)
+ return getValue("UnitGetTotalAbsorbs", unit, math.random(2500, 5000))
+ end,
+ UnitPowerMax = function(unit, powerType)
+ if( powerType == Enum.PowerType.Rage or powerType == Enum.PowerType.Energy or powerType == Enum.PowerType.RunicPower
+ or powerType == Enum.PowerType.LunarPower or powerType == Enum.PowerType.Maelstrom or powerType == Enum.PowerType.Insanity
+ or powerType == Enum.PowerType.Fury or powerType == Enum.PowerType.Pain ) then
+ return 100
+ elseif( powerType == Enum.PowerType.Focus ) then
+ return 120
+ elseif( powerType == Enum.PowerType.ComboPoints or powerType == Enum.PowerType.SoulShards or powerType == Enum.PowerType.HolyPower
+ or powerType == Enum.PowerType.Chi ) then
+ return 5
+ elseif( powerType == Enum.PowerType.Runes ) then
+ return 6
+ elseif( powerType == Enum.PowerType.ArcaneCharges ) then
+ return 4
+ end
+
+ return 50000
+ end,
+ UnitHasIncomingResurrection = function(unit) return true end,
+ UnitInOtherParty = function(unit) return getValue("UnitInOtherParty", unit, math.random(0, 1) == 1) end,
+ UnitInPhase = function(unit) return false end,
UnitExists = function(unit) return true end,
- UnitPowerMax = function(unit) return 50000 end,
- UnitIsPartyLeader = function() return true end,
+ UnitIsGroupLeader = function() return true end,
UnitIsPVP = function(unit) return true end,
UnitIsDND = function(unit) return false end,
UnitIsAFK = function(unit) return false end,
@@ -43,20 +89,19 @@ local function createConfigEnv()
UnitAffectingCombat = function() return true end,
UnitThreatSituation = function() return 0 end,
UnitDetailedThreatSituation = function() return nil end,
- UnitThreatSituation = function() return 0 end,
UnitCastingInfo = function(unit)
- -- 1 -> 10: spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible
+ -- 1 -> 10: spell, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID
local data = unitConfig["UnitCastingInfo" .. unit] or {}
- if( not data[6] or GetTime() < data[6] ) then
+ if( not data[5] or GetTime() < data[5] ) then
data[1] = L["Test spell"]
- data[2] = L["Rank 1"]
- data[3] = L["Test spell"]
- data[4] = "Interface\\Icons\\Spell_Nature_Rejuvenation"
- data[5] = GetTime() * 1000
- data[6] = data[5] + 60000
- data[7] = false
- data[8] = math.floor(GetTime())
- data[9] = math.random(0, 100) < 25
+ data[2] = L["Test spell"]
+ data[3] = "Interface\\Icons\\Spell_Nature_Rejuvenation"
+ data[4] = GetTime() * 1000
+ data[5] = data[4] + 60000
+ data[6] = false
+ data[7] = math.floor(GetTime())
+ data[8] = math.random(0, 100) < 25
+ data[9] = 1000
unitConfig["UnitCastingInfo" .. unit] = data
end
@@ -73,7 +118,7 @@ local function createConfigEnv()
end,
UnitGroupRolesAssigned = function(unit)
local role = getValue("UnitGroupRolesAssigned", unit, math.random(1, 3))
- return role == 1, role == 2, role == 3
+ return role == 1 and "TANK" or (role == 2 and "HEALER" or (role == 3 and "DAMAGER"))
end,
UnitPowerType = function(unit)
local powerType = math.random(0, 4)
@@ -81,13 +126,26 @@ local function createConfigEnv()
return powerType, powerType == 0 and "MANA" or powerType == 1 and "RAGE" or powerType == 2 and "FOCUS" or powerType == 3 and "ENERGY" or powerType == 6 and "RUNIC_POWER"
end,
+ UnitStagger = function(unit)
+ if( unit ~= "player" ) then return nil end
+ return getValue("UnitStagger", math.random(2000, 10000))
+ end,
UnitAura = function(unit, id, filter)
- if( type(id) ~= "number" or id > 40 ) then return end
+ -- apply buff and debuff configurations
+ -- info: raid and group frame units have numbers we need to load their general config
+ -- by removing the numbers from the name.
+ local config = ShadowUF.db.profile.units[string.match(unit, "%a+")]
+ local buffConfig = config.auras.buffs
+ local debuffConfig = config.auras.debuffs
+ -- calculate max auras
+ local maxBuffs, maxDebuffs = buffConfig.perRow * buffConfig.maxRows, debuffConfig.perRow * debuffConfig.maxRows
+ if( filter == "HELPFUL" and (type(id) ~= "number" or id > maxBuffs) ) then return end
+ if( filter ~= "HELPFUL" and (type(id) ~= "number" or id > maxDebuffs) ) then return end
local texture = filter == "HELPFUL" and "Interface\\Icons\\Spell_Nature_Rejuvenation" or "Interface\\Icons\\Ability_DualWield"
local mod = id % 5
local auraType = mod == 0 and "Magic" or mod == 1 and "Curse" or mod == 2 and "Poison" or mod == 3 and "Disease" or "none"
- return L["Test Aura"], L["Rank 1"], texture, id, auraType, 0, 0, "player", id % 6 == 0
+ return L["Test Aura"], texture, id, auraType, 0, 0, "player", id % 6 == 0
end,
UnitName = function(unit)
local unitID = string.match(unit, "(%d+)")
@@ -114,7 +172,7 @@ local function prepareChildUnits(header, ...)
if( frame.unitType and not frame.configUnitID ) then
ShadowUF.Units.frameList[frame] = true
frame.configUnitID = header.groupID and (header.groupID * 5) - 5 + i or i
- frame:SetAttribute("unit", ShadowUF[header.unitType .. "Units"][frame.configUnitID])
+ frame:SetAttribute("unit", ShadowUF[header.unitMappedType .. "Units"][frame.configUnitID])
end
end
end
@@ -144,19 +202,21 @@ local function setupUnits(childrenOnly)
-- Unit's not visible and it's enabled so it should
elseif( not frame:IsVisible() and ShadowUF.db.profile.units[frame.unitType].enabled ) then
UnregisterUnitWatch(frame)
+
+ frame:SetAttribute("state-unitexists", true)
frame:FullUpdate()
frame:Show()
end
elseif( not frame.configMode and ShadowUF.db.profile.units[frame.unitType].enabled ) then
frame.originalUnit = frame:GetAttribute("unit")
- frame.originalOnEnter = frame:GetScript("OnEnter")
- frame.originalOnLeave = frame:GetScript("OnLeave")
+ frame.originalOnEnter = frame.OnEnter
+ frame.originalOnLeave = frame.OnLeave
frame.originalOnUpdate = frame:GetScript("OnUpdate")
frame:SetMovable(not ShadowUF.Units.childUnits[frame.unitType])
frame:SetScript("OnDragStop", OnDragStop)
frame:SetScript("OnDragStart", OnDragStart)
- frame:SetScript("OnEnter", OnEnter)
- frame:SetScript("OnLeave", OnLeave)
+ frame.OnEnter = OnEnter
+ frame.OnLeave = OnLeave
frame:SetScript("OnEvent", nil)
frame:SetScript("OnUpdate", nil)
frame:RegisterForDrag("LeftButton")
@@ -224,7 +284,7 @@ function Movers:Enable()
header:SetMovable(true)
prepareChildUnits(header, header:GetChildren())
end
-
+
-- Setup the test env
if( not self.isEnabled ) then
for _, func in pairs(ShadowUF.tagFunc) do
@@ -250,7 +310,15 @@ function Movers:Enable()
-- so the first call gets all the parent units, the second call gets the child units
setupUnits()
setupUnits(true)
-
+
+ for unitType in pairs(ShadowUF.Units.zoneUnits) do
+ local header = ShadowUF.Units.headerFrames[unitType]
+ if( ShadowUF.db.profile.units[unitType].enabled and header ) then
+ header:SetAttribute("childChanged", 1)
+ end
+ end
+
+
-- Don't show the dialog if the configuration is opened through the configmode spec
if( not self.isConfigModeSpec ) then
self:CreateInfoFrame()
@@ -286,10 +354,10 @@ function Movers:Disable()
frame:SetAttribute("unit", frame.originalUnit)
frame:SetScript("OnDragStop", nil)
frame:SetScript("OnDragStart", nil)
- frame:SetScript("OnEvent", frame:IsVisible() and ShadowUF.Units.OnEvent)
+ frame:SetScript("OnEvent", frame:IsVisible() and ShadowUF.Units.OnEvent or nil)
frame:SetScript("OnUpdate", frame.originalOnUpdate)
- frame:SetScript("OnEnter", frame.originalOnEnter)
- frame:SetScript("OnLeave", frame.originalOnLeave)
+ frame.OnEnter = frame.originalOnEnter
+ frame.OnLeave = frame.originalOnLeave
frame:SetMovable(false)
frame:RegisterForDrag()
@@ -316,6 +384,9 @@ function Movers:Disable()
ShadowUF.Units:CheckPlayerZone(true)
ShadowUF.Layout:Reload()
+ -- Don't store these so everything can be GCed
+ unitConfig = {}
+
if( self.infoFrame ) then
self.infoFrame:Hide()
end
@@ -427,8 +498,6 @@ function Movers:CreateInfoFrame()
DEFAULT_CHAT_FRAME:AddMessage(L["You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf."])
end
end)
- frame:SetScript("OnShow", OnShow)
- frame:SetScript("OnHide", OnHide)
frame:SetScript("OnDragStart", function(self)
self:StartMoving()
end)
diff --git a/modules/portrait.lua b/modules/portrait.lua
index 1e06f0703..73930164b 100755
--- a/modules/portrait.lua
+++ b/modules/portrait.lua
@@ -3,7 +3,7 @@ ShadowUF:RegisterModule(Portrait, "portrait", ShadowUF.L["Portrait"])
-- If the camera isn't reset OnShow, it'll show the entire character instead of just the head, odd I know
local function resetCamera(self)
- self:SetCamera(0)
+ self:SetPortraitZoom(1)
end
local function resetGUID(self)
@@ -14,11 +14,6 @@ function Portrait:OnEnable(frame)
frame:RegisterUnitEvent("UNIT_PORTRAIT_UPDATE", self, "UpdateFunc")
frame:RegisterUnitEvent("UNIT_MODEL_CHANGED", self, "Update")
- if( frame.unitRealType == "party" ) then
- -- frame:RegisterNormalEvent("PARTY_MEMBER_ENABLE", self, "Update")
- -- frame:RegisterNormalEvent("PARTY_MEMBER_DISABLE", self, "Update")
- end
-
frame:RegisterUpdateFunc(self, "UpdateFunc")
end
@@ -66,10 +61,9 @@ end
function Portrait:Update(frame, event)
local type = ShadowUF.db.profile.units[frame.unitType].portrait.type
-
-- Use class thingy
if( type == "class" ) then
- local classToken = select(2, UnitClass(frame.unitOwner))
+ local classToken = frame:UnitClassToken()
if( classToken ) then
frame.portrait:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes")
frame.portrait:SetTexCoord(CLASS_ICON_TCOORDS[classToken][1], CLASS_ICON_TCOORDS[classToken][2], CLASS_ICON_TCOORDS[classToken][3], CLASS_ICON_TCOORDS[classToken][4])
@@ -80,15 +74,19 @@ function Portrait:Update(frame, event)
elseif( type == "2D" ) then
frame.portrait:SetTexCoord(0.10, 0.90, 0.10, 0.90)
SetPortraitTexture(frame.portrait, frame.unitOwner)
- -- Using 3D portrait, but the players not in range so swap to 2D
+ -- Using 3D portrait, but the players not in range so swap to question mark
elseif( not UnitIsVisible(frame.unitOwner) or not UnitIsConnected(frame.unitOwner) ) then
- frame.portrait:SetModelScale(4.25)
- frame.portrait:SetPosition(0, 0, -1.5)
- frame.portrait:SetModel("Interface\\Buttons\\talktomequestionmark.mdx")
+ frame.portrait:ClearModel()
+ frame.portrait:SetModelScale(5.5)
+ frame.portrait:SetPosition(0, 0, -0.8)
+ frame.portrait:SetModel("Interface\\Buttons\\talktomequestionmark.m2")
+
-- Use animated 3D portrait
else
+ frame.portrait:ClearModel()
frame.portrait:SetUnit(frame.unitOwner)
- frame.portrait:SetCamera(0)
+ frame.portrait:SetPortraitZoom(1)
+ frame.portrait:SetPosition(0, 0, 0)
frame.portrait:Show()
end
end
diff --git a/modules/power.lua b/modules/power.lua
index fcb8d19e0..2abffb158 100755
--- a/modules/power.lua
+++ b/modules/power.lua
@@ -1,75 +1,102 @@
local Power = {}
+local powerMap = ShadowUF.Tags.powerMap
ShadowUF:RegisterModule(Power, "powerBar", ShadowUF.L["Power bar"], true)
-local function updatePower(self, elapsed)
- local currentPower = UnitPower(self.parent.unit)
- if( currentPower == self.currentPower ) then return end
- self.currentPower = currentPower
+function Power:OnEnable(frame)
+ frame.powerBar = frame.powerBar or ShadowUF.Units:CreateBar(frame)
+
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "Update")
+ frame:RegisterUnitEvent("UNIT_CONNECTION", self, "Update")
+ frame:RegisterUnitEvent("UNIT_POWER_BAR_SHOW", self, "Update")
+ frame:RegisterUnitEvent("UNIT_POWER_BAR_HIDE", self, "Update")
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "UpdateColor")
+ frame:RegisterUnitEvent("UNIT_CLASSIFICATION_CHANGED", self, "UpdateClassification")
- self:SetValue(currentPower)
- for _, fontString in pairs(self.parent.fontStrings) do
- if( fontString.fastPower ) then
- fontString:UpdateTags()
- end
+ -- run an update after returning to life
+ if ( frame.unit == "player" ) then
+ frame:RegisterNormalEvent("PLAYER_UNGHOST", self, "Update")
end
-end
-function Power:OnEnable(frame)
- frame.powerBar = frame.powerBar or ShadowUF.Units:CreateBar(frame)
-
+ -- UNIT_MANA fires after repopping at a spirit healer, make sure to update powers then
frame:RegisterUnitEvent("UNIT_MANA", self, "Update")
- frame:RegisterUnitEvent("UNIT_RAGE", self, "Update")
- frame:RegisterUnitEvent("UNIT_ENERGY", self, "Update")
- frame:RegisterUnitEvent("UNIT_FOCUS", self, "Update")
- frame:RegisterUnitEvent("UNIT_RUNIC_POWER", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXMANA", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXRAGE", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXENERGY", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXFOCUS", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXRUNIC_POWER", self, "Update")
- frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "UpdateColor")
+ frame:RegisterUpdateFunc(self, "UpdateClassification")
frame:RegisterUpdateFunc(self, "UpdateColor")
frame:RegisterUpdateFunc(self, "Update")
end
-function Power:OnLayoutApplied(frame)
- -- Enable predicted updates which requires polling in an OnUpdate to get more up to date values
- if( frame.visibility.powerBar ) then
- if( ShadowUF.db.profile.units[frame.unitType].powerBar.predicted ) then
- frame.powerBar:SetScript("OnUpdate", updatePower)
- else
- frame.powerBar:SetScript("OnUpdate", nil)
- end
- end
-end
-
function Power:OnDisable(frame)
frame:UnregisterAll(self)
end
+local altColor = {}
function Power:UpdateColor(frame)
- local color = ShadowUF.db.profile.powerColors[select(2, UnitPowerType(frame.unit))] or ShadowUF.db.profile.powerColors.MANA
+ local powerID, currentType, altR, altG, altB = UnitPowerType(frame.unit)
+ frame.powerBar.currentType = currentType
+
+ -- Overridden power types like Warlock pets, or Ulduar vehicles use "POWER_TYPE_#####" but triggers power events with "ENERGY", so this fixes that
+ -- by using the powerID to figure out the event type
+ if( not powerMap[currentType] ) then
+ frame.powerBar.currentType = powerMap[powerID] or "ENERGY"
+ end
+
+ if( ShadowUF.db.profile.units[frame.unitType].powerBar.onlyMana ) then
+ ShadowUF.Layout:SetBarVisibility(frame, "powerBar", currentType == "MANA")
+ if( currentType ~= "MANA" ) then return end
+ end
+
+
+ local color
+ if( frame.powerBar.minusMob ) then
+ color = ShadowUF.db.profile.healthColors.offline
+ elseif( ShadowUF.db.profile.units[frame.unitType].powerBar.colorType == "class" and UnitIsPlayer(frame.unit) ) then
+ local class = frame:UnitClassToken()
+ color = class and ShadowUF.db.profile.classColors[class]
+ end
- if( not ShadowUF.db.profile.units[frame.unitType].powerBar.invert ) then
- frame.powerBar:SetStatusBarColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
- if( not frame.powerBar.background.overrideColor ) then
- frame.powerBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
+ if( not color ) then
+ color = ShadowUF.db.profile.powerColors[frame.powerBar.currentType]
+ if( not color ) then
+ if( altR ) then
+ altColor.r, altColor.g, altColor.b = altR, altG, altB
+ color = altColor
+ else
+ color = ShadowUF.db.profile.powerColors.MANA
+ end
end
- else
- frame.powerBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
+ end
- color = frame.powerBar.background.overrideColor
- if( not color ) then
- frame.powerBar:SetStatusBarColor(0, 0, 0, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
- else
- frame.powerBar:SetStatusBarColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
+ frame:SetBarColor("powerBar", color.r, color.g, color.b)
+
+ self:Update(frame)
+end
+
+function Power:UpdateClassification(frame, event, unit)
+ local classif = UnitClassification(frame.unit)
+ local minus = nil
+ if( classif == "minus" ) then
+ minus = true
+
+ frame.powerBar:SetMinMaxValues(0, 1)
+ frame.powerBar:SetValue(0)
+ end
+
+ if( minus ~= frame.powerBar.minusMob ) then
+ frame.powerBar.minusMob = minus
+
+ -- Only need to force an update if it was event driven, otherwise the update func will hit color/etc next
+ if( event ) then
+ self:UpdateColor(frame)
end
end
end
-function Power:Update(frame)
+function Power:Update(frame, event, unit, powerType)
+ if( event and powerType and powerType ~= frame.powerBar.currentType ) then return end
+ if( frame.powerBar.minusMob ) then return end
+
frame.powerBar.currentPower = UnitPower(frame.unit)
frame.powerBar:SetMinMaxValues(0, UnitPowerMax(frame.unit))
frame.powerBar:SetValue(UnitIsDeadOrGhost(frame.unit) and 0 or not UnitIsConnected(frame.unit) and 0 or frame.powerBar.currentPower)
-end
\ No newline at end of file
+end
diff --git a/modules/priest.lua b/modules/priest.lua
new file mode 100644
index 000000000..114ce3660
--- /dev/null
+++ b/modules/priest.lua
@@ -0,0 +1,39 @@
+local Priest = {}
+ShadowUF:RegisterModule(Priest, "priestBar", ShadowUF.L["Priest mana bar"], true, "PRIEST", SPEC_PRIEST_SHADOW)
+
+function Priest:OnEnable(frame)
+ frame.priestBar = frame.priestBar or ShadowUF.Units:CreateBar(frame)
+
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "PowerChanged")
+
+ frame:RegisterUpdateFunc(self, "PowerChanged")
+ frame:RegisterUpdateFunc(self, "Update")
+end
+
+function Priest:OnDisable(frame)
+ frame:UnregisterAll(self)
+end
+
+function Priest:OnLayoutApplied(frame)
+ if( not frame.visibility.priestBar ) then return end
+
+ local color = ShadowUF.db.profile.powerColors.MANA
+ frame:SetBarColor("priestBar", color.r, color.g, color.b)
+end
+
+function Priest:PowerChanged(frame)
+ local visible = UnitPowerType(frame.unit) ~= ADDITIONAL_POWER_BAR_INDEX and not frame.inVehicle
+ local type = visible and "RegisterUnitEvent" or "UnregisterSingleEvent"
+
+ frame[type](frame, "UNIT_POWER_FREQUENT", self, "Update")
+ frame[type](frame, "UNIT_MAXPOWER", self, "Update")
+ ShadowUF.Layout:SetBarVisibility(frame, "priestBar", visible)
+
+ if( visible ) then self:Update(frame) end
+end
+
+function Priest:Update(frame, event, unit, powerType)
+ if( powerType and powerType ~= "MANA" ) then return end
+ frame.priestBar:SetMinMaxValues(0, UnitPowerMax(frame.unit, Enum.PowerType.Mana))
+ frame.priestBar:SetValue(UnitIsDeadOrGhost(frame.unit) and 0 or not UnitIsConnected(frame.unit) and 0 or UnitPower(frame.unit, Enum.PowerType.Mana))
+end
diff --git a/modules/range.lua b/modules/range.lua
index 233489433..2f98191e6 100755
--- a/modules/range.lua
+++ b/modules/range.lua
@@ -1,87 +1,153 @@
local Range = {
- friendly = {["PRIEST"] = GetSpellInfo(2050), ["DRUID"] = GetSpellInfo(48378), ["PALADIN"] = GetSpellInfo(48782), ["SHAMAN"] = GetSpellInfo(49273)},
- hostile = {["PRIEST"] = GetSpellInfo(48127), ["DRUID"] = GetSpellInfo(48461), ["PALADIN"] = GetSpellInfo(62124), ["HUNTER"] = GetSpellInfo(75), ["WARLOCK"] = GetSpellInfo(686), ["SHAMAN"] = GetSpellInfo(529), ["MAGE"] = GetSpellInfo(133), ["DEATHKNIGHT"] = GetSpellInfo(49576)},
- resurrect = {["PALADIN"] = GetSpellInfo(48950), ["PRIEST"] = GetSpellInfo(25435), ["SHAMAN"] = GetSpellInfo(2008), ["DRUID"] = GetSpellInfo(48477)}
+ friendly = {
+ ["PRIEST"] = {
+ (GetSpellInfo(527)), -- Purify
+ (GetSpellInfo(17)), -- Power Word: Shield
+ },
+ ["DRUID"] = {
+ (GetSpellInfo(774)), -- Rejuvenation
+ (GetSpellInfo(2782)), -- Remove Corruption
+ },
+ ["PALADIN"] = GetSpellInfo(19750), -- Flash of Light
+ ["SHAMAN"] = GetSpellInfo(8004), -- Healing Surge
+ ["WARLOCK"] = GetSpellInfo(5697), -- Unending Breath
+ ["DEATHKNIGHT"] = GetSpellInfo(47541), -- Death Coil
+ ["MONK"] = GetSpellInfo(115450), -- Detox
+ },
+ hostile = {
+ ["DEATHKNIGHT"] = {
+ (GetSpellInfo(47541)), -- Death Coil
+ (GetSpellInfo(49576)), -- Death Grip
+ },
+ ["DEMONHUNTER"] = GetSpellInfo(185123), -- Throw Glaive
+ ["DRUID"] = GetSpellInfo(8921), -- Moonfire
+ ["HUNTER"] = {
+ (GetSpellInfo(193455)), -- Cobra Shot
+ (GetSpellInfo(19434)), -- Aimed Short
+ (GetSpellInfo(193265)), -- Hatchet Toss
+ },
+ ["MAGE"] = {
+ (GetSpellInfo(116)), -- Frostbolt
+ (GetSpellInfo(30451)), -- Arcane Blast
+ (GetSpellInfo(133)), -- Fireball
+ },
+ ["MONK"] = GetSpellInfo(115546), -- Provoke
+ ["PALADIN"] = GetSpellInfo(62124), -- Hand of Reckoning
+ ["PRIEST"] = GetSpellInfo(585), -- Smite
+ --["ROGUE"] = GetSpellInfo(1725), -- Distract
+ ["SHAMAN"] = GetSpellInfo(403), -- Lightning Bolt
+ ["WARLOCK"] = GetSpellInfo(686), -- Shadow Bolt
+ ["WARRIOR"] = GetSpellInfo(355), -- Taunt
+ },
}
+
ShadowUF:RegisterModule(Range, "range", ShadowUF.L["Range indicator"])
+local LSR = LibStub("SpellRange-1.0")
+
local playerClass = select(2, UnitClass("player"))
-local friendlySpell, hostileSpell
-local resurrectSpell = Range.resurrect[playerClass]
+local rangeSpells = {}
-local function checkRange(self, elapsed)
- self.timeElapsed = self.timeElapsed + elapsed
- if( self.timeElapsed <= 0.50 ) then return end
- self.timeElapsed = 0
-
- if( self.isFriendly and resurrectSpell and UnitIsDead(self.parent.unit) ) then
- self.parent:SetRangeAlpha(IsSpellInRange(resurrectSpell, self.parent.unit) == 1 and ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha or ShadowUF.db.profile.units[self.parent.unitType].range.oorAlpha)
- -- We set a spell for them in our flags check, use that
- elseif( self.spell ) then
- self.parent:SetRangeAlpha(IsSpellInRange(self.spell, self.parent.unit) == 1 and ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha or ShadowUF.db.profile.units[self.parent.unitType].range.oorAlpha)
+local function checkRange(self)
+ local frame = self.parent
+
+ -- Check which spell to use
+ local spell
+ if( UnitCanAssist("player", frame.unit) ) then
+ spell = rangeSpells.friendly
+ elseif( UnitCanAttack("player", frame.unit) ) then
+ spell = rangeSpells.hostile
+ end
+
+ if( not UnitIsConnected(frame.unit) or not UnitInPhase(frame.unit) ) then
+ frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.oorAlpha)
+ elseif( spell ) then
+ frame:SetRangeAlpha(LSR.IsSpellInRange(spell, frame.unit) == 1 and ShadowUF.db.profile.units[frame.unitType].range.inAlpha or ShadowUF.db.profile.units[frame.unitType].range.oorAlpha)
-- That didn't work, but they are grouped lets try the actual API for this, it's a bit flaky though and not that useful generally
- elseif( self.grouped ) then
- self.parent:SetRangeAlpha(UnitInRange(self.parent.unit, "player") and ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha or ShadowUF.db.profile.units[self.parent.unitType].range.oorAlpha)
+ elseif( UnitInRaid(frame.unit) or UnitInParty(frame.unit) ) then
+ frame:SetRangeAlpha(UnitInRange(frame.unit, "player") and ShadowUF.db.profile.units[frame.unitType].range.inAlpha or ShadowUF.db.profile.units[frame.unitType].range.oorAlpha)
-- Nope, fall back to interaction :(
- elseif( self.isFriendly ) then
- self.parent:SetRangeAlpha(CheckInteractDistance(self.parent.unit, 4) and ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha or ShadowUF.db.profile.units[self.parent.unitType].range.oorAlpha)
else
- self.parent:SetRangeAlpha(ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha)
+ frame:SetRangeAlpha(CheckInteractDistance(frame.unit, 1) and ShadowUF.db.profile.units[frame.unitType].range.inAlpha or ShadowUF.db.profile.units[frame.unitType].range.oorAlpha)
+ end
+end
+
+local function updateSpellCache(category)
+ rangeSpells[category] = nil
+ if( IsUsableSpell(ShadowUF.db.profile.range[category .. playerClass]) ) then
+ rangeSpells[category] = ShadowUF.db.profile.range[category .. playerClass]
+
+ elseif( IsUsableSpell(ShadowUF.db.profile.range[category .. "Alt" .. playerClass]) ) then
+ rangeSpells[category] = ShadowUF.db.profile.range[category .. "Alt" .. playerClass]
+
+ elseif( Range[category][playerClass] ) then
+ if( type(Range[category][playerClass]) == "table" ) then
+ for i = 1, #Range[category][playerClass] do
+ local spell = Range[category][playerClass][i]
+ if( IsUsableSpell(spell) ) then
+ rangeSpells[category] = spell
+ break
+ end
+ end
+ elseif( IsUsableSpell(Range[category][playerClass]) ) then
+ rangeSpells[category] = Range[category][playerClass]
+ end
+ end
+end
+
+local function createTimer(frame)
+ if( not frame.range.timer ) then
+ frame.range.timer = C_Timer.NewTicker(0.5, checkRange)
+ frame.range.timer.parent = frame
+ end
+end
+
+local function cancelTimer(frame)
+ if( frame.range and frame.range.timer ) then
+ frame.range.timer:Cancel()
+ frame.range.timer = nil
end
end
function Range:ForceUpdate(frame)
- checkRange(frame.range, 1)
+ if( UnitIsUnit(frame.unit, "player") ) then
+ frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.inAlpha)
+ cancelTimer(frame)
+ else
+ createTimer(frame)
+ checkRange(frame.range.timer)
+ end
end
function Range:OnEnable(frame)
if( not frame.range ) then
frame.range = CreateFrame("Frame", nil, frame)
- frame.range:SetScript("OnUpdate", checkRange)
- frame.range.timeElapsed = 0
- frame.range.parent = frame
- frame.range:Hide()
end
-
- -- I want to say UNIT_FACTION is the function thats called when a unit is MCed, but not 100% sure
- frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdateFlags")
- frame:RegisterNormalEvent("PARTY_MEMBERS_CHANGED", self, "UpdateFlags")
- frame:RegisterNormalEvent("RAID_ROSTER_UPDATE", self, "UpdateFlags")
- frame:RegisterUpdateFunc(self, "UpdateFlags")
+ frame:RegisterNormalEvent("PLAYER_SPECIALIZATION_CHANGED", self, "SpellChecks")
frame:RegisterUpdateFunc(self, "ForceUpdate")
+
+ createTimer(frame)
end
function Range:OnLayoutApplied(frame)
- if( frame.visibility.range ) then
- frame.range.hostileSpell = ShadowUF.db.profile.range["hostile" .. playerClass] or self.hostile[playerClass]
- frame.range.friendlySpell = ShadowUF.db.profile.range["friendly" .. playerClass] or self.friendly[playerClass]
- end
+ self:SpellChecks(frame)
end
function Range:OnDisable(frame)
frame:UnregisterAll(self)
if( frame.range ) then
- frame.range:Hide()
+ cancelTimer(frame)
frame:SetRangeAlpha(1.0)
end
end
--- I'd rather store the flags here, they rarely change and we can do that based off events, no sense in doing it eveyr 0.50s
-function Range:UpdateFlags(frame)
- frame.range.canAttack = UnitCanAttack("player", frame.unit)
- frame.range.isFriendly = UnitIsFriend("player", frame.unit) and UnitCanAssist("player", frame.unit)
- frame.range.grouped = UnitInRaid(frame.unit) or UnitInParty(frame.unit)
- frame.range.spell = frame.range.canAttack and frame.range.hostileSpell or frame.range.isFriendly and frame.range.friendlySpell or nil
-
- -- No sense in updating range if we have no data
- if( UnitIsGhost(frame.unit) or not UnitIsConnected(frame.unit) or ( not frame.range.spell and not frame.range.grouped and not frame.range.isFriendly ) ) then
- frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.inAlpha)
- frame.range:Hide()
- else
- frame.range:Show()
- end
-end
-
+function Range:SpellChecks(frame)
+ updateSpellCache("friendly")
+ updateSpellCache("hostile")
+ if( frame.range ) then
+ self:ForceUpdate(frame)
+ end
+end
\ No newline at end of file
diff --git a/modules/runes.lua b/modules/runes.lua
index e37e12dd0..51a20773b 100755
--- a/modules/runes.lua
+++ b/modules/runes.lua
@@ -1,7 +1,7 @@
local Runes = {}
-local RUNE_MAP = {[1] = 1, [2] = 2, [3] = 5, [4] = 6, [5] = 3, [6] = 4}
-local runeColors = {{r = 1, g = 0, b = 0.4}, {r = 0, g = 1, b = 0.4}, {r = 0, g = 0.4, b = 1}, {r = 0.7, g = 0.5, b = 1}}
ShadowUF:RegisterModule(Runes, "runeBar", ShadowUF.L["Rune bar"], true, "DEATHKNIGHT")
+ShadowUF.BlockTimers:Inject(Runes, "RUNE_TIMER")
+ShadowUF.DynamicBlocks:Inject(Runes)
function Runes:OnEnable(frame)
if( not frame.runeBar ) then
@@ -9,24 +9,23 @@ function Runes:OnEnable(frame)
frame.runeBar:SetMinMaxValues(0, 1)
frame.runeBar:SetValue(0)
frame.runeBar.runes = {}
+ frame.runeBar.blocks = frame.runeBar.runes
for id=1, 6 do
- local rune = ShadowUF.Units:CreateBar(frame)
- rune:SetFrameLevel(1)
-
+ local rune = ShadowUF.Units:CreateBar(frame.runeBar)
+ rune.id = id
+
if( id > 1 ) then
- rune:SetPoint("TOPLEFT", frame.runeBar.runes[RUNE_MAP[id - 1]], "TOPRIGHT", 1, 0)
+ rune:SetPoint("TOPLEFT", frame.runeBar.runes[id-1], "TOPRIGHT", 1, 0)
else
rune:SetPoint("TOPLEFT", frame.runeBar, "TOPLEFT", 0, 0)
end
- frame.runeBar.runes[RUNE_MAP[id]] = rune
+ frame.runeBar.runes[id] = rune
end
end
frame:RegisterNormalEvent("RUNE_POWER_UPDATE", self, "UpdateUsable")
- frame:RegisterNormalEvent("RUNE_TYPE_UPDATE", self, "Update")
- frame:RegisterUpdateFunc(self, "Update")
frame:RegisterUpdateFunc(self, "UpdateUsable")
end
@@ -35,50 +34,56 @@ function Runes:OnDisable(frame)
end
function Runes:OnLayoutApplied(frame)
- if( frame.visibility.runeBar ) then
- local barWidth = (frame.runeBar:GetWidth() - 5) / 6
-
- for id, rune in pairs(frame.runeBar.runes) do
- if( ShadowUF.db.profile.units[frame.unitType].runeBar.background ) then
- rune.background:Show()
- else
- rune.background:Hide()
- end
-
- rune.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
- rune.background:SetHorizTile(false)
- rune:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
- rune:GetStatusBarTexture():SetHorizTile(false)
- rune:SetHeight(frame.runeBar:GetHeight())
- rune:SetWidth(barWidth)
+ if( not frame.visibility.runeBar ) then return end
+
+ local barWidth = (frame.runeBar:GetWidth() - 5) / 6
+ for id, rune in pairs(frame.runeBar.runes) do
+ if( ShadowUF.db.profile.units[frame.unitType].runeBar.background ) then
+ rune.background:Show()
+ else
+ rune.background:Hide()
end
+
+ rune.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
+ rune.background:SetHorizTile(false)
+ rune:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
+ rune:GetStatusBarTexture():SetHorizTile(false)
+ rune:SetWidth(barWidth)
+
+ local color = ShadowUF.db.profile.powerColors.RUNES
+ frame:SetBlockColor(rune, "runeBar", color.r, color.g, color.b)
end
end
local function runeMonitor(self, elapsed)
local time = GetTime()
self:SetValue(time)
-
+
if( time >= self.endTime ) then
self:SetValue(self.endTime)
self:SetAlpha(1.0)
self:SetScript("OnUpdate", nil)
+ self.endTime = nil
+ end
+
+ if( self.fontString ) then
+ self.fontString:UpdateTags()
end
end
-- Updates the timers on runes
function Runes:UpdateUsable(frame, event, id, usable)
- if( not id ) then
- self:UpdateColors(frame)
- return
- elseif( not frame.runeBar.runes[id] ) then
+ if( not id or not frame.runeBar.runes[id] ) then
return
end
local rune = frame.runeBar.runes[id]
local startTime, cooldown, cooled = GetRuneCooldown(id)
+ -- Blizzard changed something with this API apparently and now it can be true/false/nil
+ if( cooled == nil ) then return end
+
if( not cooled ) then
- rune.endTime = GetTime() + cooldown
+ rune.endTime = startTime + cooldown
rune:SetMinMaxValues(startTime, rune.endTime)
rune:SetValue(GetTime())
rune:SetAlpha(0.40)
@@ -88,28 +93,10 @@ function Runes:UpdateUsable(frame, event, id, usable)
rune:SetValue(1)
rune:SetAlpha(1.0)
rune:SetScript("OnUpdate", nil)
+ rune.endTime = nil
end
-end
-
-function Runes:UpdateColors(frame)
- for id, rune in pairs(frame.runeBar.runes) do
- local color = runeColors[GetRuneType(id)]
- if( color ) then
- rune:SetStatusBarColor(color.r, color.g, color.b)
-
- color = ShadowUF.db.profile.bars.backgroundColor or ShadowUF.db.profile.units[frame.unitType].runeBar.backgroundColor or color
- rune.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
- end
-end
-
--- No rune is passed for full update (Login), a single rune is passed when a single rune type changes, such as Blood Tap
-function Runes:Update(frame, event, id)
- if( id ) then
- local color = runeColors[GetRuneType(id)]
- frame.runeBar.runes[id]:SetStatusBarColor(color.r, color.g, color.b)
- color = ShadowUF.db.profile.bars.backgroundColor or ShadowUF.db.profile.units[frame.unitType].runeBar.backgroundColor or color
- frame.runeBar.runes[id].background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
+ if( rune.fontString ) then
+ rune.fontString:UpdateTags()
end
end
diff --git a/modules/shaman.lua b/modules/shaman.lua
new file mode 100644
index 000000000..2dc5270ee
--- /dev/null
+++ b/modules/shaman.lua
@@ -0,0 +1,39 @@
+local Shaman = {}
+ShadowUF:RegisterModule(Shaman, "shamanBar", ShadowUF.L["Shaman mana bar"], true, "SHAMAN")
+
+function Shaman:OnEnable(frame)
+ frame.shamanBar = frame.shamanBar or ShadowUF.Units:CreateBar(frame)
+
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "PowerChanged")
+
+ frame:RegisterUpdateFunc(self, "PowerChanged")
+ frame:RegisterUpdateFunc(self, "Update")
+end
+
+function Shaman:OnDisable(frame)
+ frame:UnregisterAll(self)
+end
+
+function Shaman:OnLayoutApplied(frame)
+ if( not frame.visibility.shamanBar ) then return end
+
+ local color = ShadowUF.db.profile.powerColors.MANA
+ frame:SetBarColor("shamanBar", color.r, color.g, color.b)
+end
+
+function Shaman:PowerChanged(frame)
+ local visible = UnitPowerType(frame.unit) ~= ADDITIONAL_POWER_BAR_INDEX and not frame.inVehicle
+ local type = visible and "RegisterUnitEvent" or "UnregisterSingleEvent"
+
+ frame[type](frame, "UNIT_POWER_FREQUENT", self, "Update")
+ frame[type](frame, "UNIT_MAXPOWER", self, "Update")
+ ShadowUF.Layout:SetBarVisibility(frame, "shamanBar", visible)
+
+ if( visible ) then self:Update(frame) end
+end
+
+function Shaman:Update(frame, event, unit, powerType)
+ if( powerType and powerType ~= "MANA" ) then return end
+ frame.shamanBar:SetMinMaxValues(0, UnitPowerMax(frame.unit, Enum.PowerType.Mana))
+ frame.shamanBar:SetValue(UnitIsDeadOrGhost(frame.unit) and 0 or not UnitIsConnected(frame.unit) and 0 or UnitPower(frame.unit, Enum.PowerType.Mana))
+end
diff --git a/modules/soulshards.lua b/modules/soulshards.lua
new file mode 100755
index 000000000..8561f8056
--- /dev/null
+++ b/modules/soulshards.lua
@@ -0,0 +1,47 @@
+if( not ShadowUF.ComboPoints ) then return end
+
+local Souls = setmetatable({}, {__index = ShadowUF.ComboPoints})
+ShadowUF:RegisterModule(Souls, "soulShards", ShadowUF.L["Soul Shards"], nil, "WARLOCK")
+local soulsConfig = {max = 5, key = "soulShards", colorKey = "SOULSHARDS", powerType = Enum.PowerType.SoulShards, eventType = "SOUL_SHARDS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\shard"}
+
+function Souls:OnEnable(frame)
+ frame.soulShards = frame.soulShards or CreateFrame("Frame", nil, frame)
+ frame.soulShards.cpConfig = soulsConfig
+ frame.soulShards.cpConfig.max = (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION) and 50 or 5
+ frame.soulShards.cpConfig.grouping = (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION) and UnitPowerDisplayMod(soulsConfig.powerType) or 1
+ frame.comboPointType = soulsConfig.key
+
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks")
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "Update")
+ frame:RegisterNormalEvent("PLAYER_SPECIALIZATION_CHANGED", self, "SpecChanged")
+
+ frame:RegisterUpdateFunc(self, "Update")
+ frame:RegisterUpdateFunc(self, "UpdateBarBlocks")
+end
+
+function Souls:OnLayoutApplied(frame, config)
+ ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config)
+ self:UpdateBarBlocks(frame)
+end
+
+function Souls:SpecChanged(frame)
+ -- update shard count on spec swap
+ if frame and frame.soulShards then
+ frame.soulShards.cpConfig.max = (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION) and 50 or 5
+ frame.soulShards.cpConfig.grouping = (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION) and UnitPowerDisplayMod(soulsConfig.powerType) or 1
+ end
+ self:UpdateBarBlocks(frame)
+end
+
+function Souls:GetComboPointType()
+ return "soulShards"
+end
+
+function Souls:GetPoints(unit)
+ return UnitPower("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION))
+end
+
+function Souls:GetMaxPoints(unit)
+ return UnitPowerMax("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION))
+end
diff --git a/modules/tags.lua b/modules/tags.lua
old mode 100644
new mode 100755
index 9000d6e72..04f152b15
--- a/modules/tags.lua
+++ b/modules/tags.lua
@@ -1,12 +1,35 @@
--- Thanks to haste for the original tagging code, which I then mostly ripped apart and stole!
-local Tags = {afkStatus = {}, offlineStatus = {}, customEvents = {}}
-local tagPool, functionPool, temp, regFontStrings, frequentUpdates, frequencyCache = {}, {}, {}, {}, {}, {}
+local Tags = {afkStatus = {}, offlineStatus = {}, customEvents = {}, powerMap = {}, moduleKey = "tags"}
+local tagPool, functionPool, temp, regFontStrings, powerMap = {}, {}, {}, {}, Tags.powerMap
local L = ShadowUF.L
ShadowUF.Tags = Tags
+-- Map the numeric index to the string
+local numerics = {}
+for id, color in pairs(PowerBarColor) do
+ if( type(id) == "number" ) then
+ numerics[color] = id
+ end
+end
+
+for id, color in pairs(PowerBarColor) do
+ if( type(id) == "string" and numerics[color] ) then
+ powerMap[numerics[color]] = id
+ powerMap[id] = true
+ end
+end
+
+-- Avoid having to do string.match on every event
+local powerFilters = {["SUF_POWERTYPE:CURRENT"] = "CURRENT"}
+for powerType in pairs(PowerBarColor) do
+ if( type(powerType) == "string" ) then
+ powerFilters["SUF_POWERTYPE:" .. powerType] = powerType
+ end
+end
+
-- Register the associated events with all the tags
function Tags:RegisterEvents(parent, fontString, tags)
+ local hasPowerFilters;
-- Strip parantheses and anything inside them
for tag in string.gmatch(tags, "%[(.-)%]") do
-- The reason the original %b() match won't work, with [( ()group())] (or any sort of tag with ( or )
@@ -20,23 +43,65 @@ function Tags:RegisterEvents(parent, fontString, tags)
local tagEvents = Tags.defaultEvents[tag] or ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].events
if( tagEvents ) then
for event in string.gmatch(tagEvents, "%S+") do
- if( self.customEvents[event] ) then
+ -- Power filter event, store it instead
+ if( powerFilters[event] ) then
+ fontString.powerFilters = fontString.powerFilters or {}
+ fontString.powerFilters[powerFilters[event]] = true
+
+ if( powerFilters[event] == "CURRENT" ) then
+ if( not hasPowerFilters ) then
+ parent:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "UpdatePowerType")
+ parent:RegisterUpdateFunc(self, "UpdatePowerType")
+ end
+
+ hasPowerFilters = true
+ end
+
+ -- Custom event registered by another module
+ elseif( self.customEvents[event] ) then
self.customEvents[event]:EnableTag(parent, fontString)
fontString[event] = true
+ -- Unit event
elseif( Tags.eventType[event] ~= "unitless" or ShadowUF.Units.unitEvents[event] ) then
- parent:RegisterUnitEvent(event, fontString, "UpdateTags")
+ local success, err = pcall(parent.RegisterUnitEvent, parent, event, fontString, "UpdateTags")
+ if not success then
+ -- switch the tag back
+ ShadowUF.Units.unitEvents[event] = false
+ Tags.eventType[event] = "unitless"
+
+ parent:RegisterNormalEvent(event, fontString, "UpdateTags")
+ end
+ -- Everything else
else
parent:RegisterNormalEvent(event, fontString, "UpdateTags")
end
-
- -- The power and health bars will handle updating tags with this flag set
- fontString.fastPower = fontString.fastPower or Tags.eventType[event] == "power"
- fontString.fastHealth = fontString.fastHealth or Tags.eventType[event] == "health"
+
+ -- register UNIT_MANA event since its the only event that fires after repopping at a spirit healer
+ if event == "UNIT_POWER_UPDATE" or event == "UNIT_POWER_FREQUENT" then
+ parent:RegisterUnitEvent("UNIT_MANA", fontString, "UpdateTags")
+
+ if ( parent.unit == "player" ) then
+ parent:RegisterNormalEvent("PLAYER_UNGHOST", fontString, "UpdateTags")
+ end
+ end
end
end
end
end
+-- Update the cached power type
+function Tags:UpdatePowerType(frame)
+ local powerID, powerType = UnitPowerType(frame.unit)
+ if( not powerMap[powerType] ) then powerType = powerMap[powerID] or "ENERGY" end
+
+ for _, fontString in pairs(frame.fontStrings) do
+ if( fontString.UpdateTags ) then
+ fontString.powerType = powerType
+ fontString:UpdateTags()
+ end
+ end
+end
+
-- This pretty much means a tag was updated in some way (or deleted) so we have to do a full update to get the new values shown
function Tags:Reload()
-- Kill cached functions, ugly I know but it ensures its fully updated with the new data
@@ -52,119 +117,157 @@ function Tags:Reload()
end
end
--- Frequent updates
-local freqFrame = CreateFrame("Frame")
-freqFrame:SetScript("OnUpdate", function(self, elapsed)
- for fontString, timeLeft in pairs(frequentUpdates) do
- if( fontString.parent:IsVisible() ) then
- frequentUpdates[fontString] = timeLeft - elapsed
- if( frequentUpdates[fontString] <= 0 ) then
- frequentUpdates[fontString] = fontString.frequentStart
- fontString:UpdateTags()
- end
+-- This is for bars that can be shown or hidden often, like druid power
+function Tags:FastRegister(frame, parent)
+ if( not frame.fontStrings ) then return end
+
+ for _, fontString in pairs(frame.fontStrings) do
+ -- Re-register anything that was already registered and is part of the parent
+ if( regFontStrings[fontString] and ( not parent or fontString.parentBar == parent ) ) then
+ fontString.UpdateTags = tagPool[regFontStrings[fontString]]
+ fontString:Show()
end
end
-end)
-freqFrame:Hide()
+end
--- Register a font string with the tag system
-function Tags:Register(parent, fontString, tags, resetCache)
- -- Unregister the font string first if we did register it already
- if( fontString.UpdateTags ) then
- self:Unregister(fontString)
+function Tags:FastUnregister(frame, parent)
+ if( not frame.fontStrings ) then return end
+
+ for _, fontString in pairs(frame.fontStrings) do
+ -- Redirect the updates to not do anything and hide it
+ if( regFontStrings[fontString] and ( not parent or fontString.parentBar == parent ) ) then
+ fontString.UpdateTags = ShadowUF.noop
+ fontString:Hide()
+ end
end
-
- fontString.parent = parent
- regFontStrings[fontString] = tags
-
- -- Use the cached polling time if we already saved it
- -- as we won't be rececking everything next call
- local pollTime = frequencyCache[tags]
- if( pollTime ) then
- frequentUpdates[fontString] = pollTime
- fontString.frequentStart = pollTime
- freqFrame:Show()
+end
+
+
+-- Register a font string with the tag system
+local powerEvents = {["UNIT_POWER_UPDATE"] = true, ["UNIT_POWER_FREQUENT"] = true, ["UNIT_MAXPOWER"] = true}
+local frequencyCache = {}
+local function createTagFunction(tags, resetCache)
+ if( tagPool[tags] and not resetCache ) then
+ return tagPool[tags], frequencyCache[tags]
end
-
- local updateFunc = not resetCache and tagPool[tags]
- if( not updateFunc ) then
- -- Using .- prevents supporting tags such as [foo ([)]. Supporting that and having a single pattern
- local formattedText = string.gsub(string.gsub(tags, "%%", "%%%%"), "[[].-[]]", "%%s")
- local args = {}
-
- for tag in string.gmatch(tags, "%[(.-)%]") do
- -- Tags that use pre or appends "foo(|)" etc need special matching, which is what this will handle
- local cachedFunc = not resetCache and functionPool[tag] or ShadowUF.tagFunc[tag]
- if( not cachedFunc ) then
- local hasPre, hasAp = true, true
- local tagKey = select(2, string.match(tag, "(%b())([%w%p]+)(%b())"))
- if( not tagKey ) then hasPre, hasAp = true, false tagKey = select(2, string.match(tag, "(%b())([%w%p]+)")) end
- if( not tagKey ) then hasPre, hasAp = false, true tagKey = string.match(tag, "([%w%p]+)(%b())") end
+
+ -- Using .- prevents supporting tags such as [foo ([)]. Supporting that and having a single pattern
+ local formattedText = string.gsub(string.gsub(tags, "%%", "%%%%"), "[[].-[]]", "%%s")
+ formattedText = string.gsub(formattedText, "|", "||")
+ formattedText = string.gsub(formattedText, "||c", "|c")
+ formattedText = string.gsub(formattedText, "||r", "|r")
+
+ local args = {}
+ local lowestFrequency = 9999
+
+ for tag in string.gmatch(tags, "%[(.-)%]") do
+ -- Tags that use pre or appends "foo(|)" etc need special matching, which is what this will handle
+ local cachedFunc = not resetCache and functionPool[tag] or ShadowUF.tagFunc[tag]
+ if( not cachedFunc ) then
+ local hasPre, hasAp = true, true
+ local tagKey = select(2, string.match(tag, "(%b())([%w%p]+)(%b())"))
+ if( not tagKey ) then hasPre, hasAp = true, false tagKey = select(2, string.match(tag, "(%b())([%w%p]+)")) end
+ if( not tagKey ) then hasPre, hasAp = false, true tagKey = string.match(tag, "([%w%p]+)(%b())") end
+
+ frequencyCache[tag] = tagKey and (Tags.defaultFrequents[tagKey] or ShadowUF.db.profile.tags[tagKey] and ShadowUF.db.profile.tags[tagKey].frequency)
+
+ local tagFunc = tagKey and ShadowUF.tagFunc[tagKey]
+ if( tagFunc ) then
+ local startOff, endOff = string.find(tag, tagKey)
+ local pre = hasPre and string.sub(tag, 2, startOff - 2)
+ local ap = hasAp and string.sub(tag, endOff + 2, -2)
- frequencyCache[tag] = tagKey and (self.defaultFrequents[tagKey] or ShadowUF.db.profile.tags[tagKey] and ShadowUF.db.profile.tags[tagKey].frequency)
- local tagFunc = tagKey and ShadowUF.tagFunc[tagKey]
- if( tagFunc ) then
- local startOff, endOff = string.find(tag, tagKey)
- local pre = hasPre and string.sub(tag, 2, startOff - 2)
- local ap = hasAp and string.sub(tag, endOff + 2, -2)
-
- if( pre and ap ) then
- cachedFunc = function(...)
- local str = tagFunc(...)
- if( str ) then return pre .. str .. ap end
- end
- elseif( pre ) then
- cachedFunc = function(...)
- local str = tagFunc(...)
- if( str ) then return pre .. str end
- end
- elseif( ap ) then
- cachedFunc = function(...)
- local str = tagFunc(...)
- if( str ) then return str .. ap end
- end
+ if( pre and ap ) then
+ cachedFunc = function(...)
+ local str = tagFunc(...)
+ if( str ) then return pre .. str .. ap end
+ end
+ elseif( pre ) then
+ cachedFunc = function(...)
+ local str = tagFunc(...)
+ if( str ) then return pre .. str end
+ end
+ elseif( ap ) then
+ cachedFunc = function(...)
+ local str = tagFunc(...)
+ if( str ) then return str .. ap end
end
-
- functionPool[tag] = cachedFunc
end
+
+ functionPool[tag] = cachedFunc
end
-
- -- Figure out what the lowest update frequency for this font string and use it
- local pollTime = self.defaultFrequents[tag] or frequencyCache[tag]
- if( ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].frequency ) then
- pollTime = ShadowUF.db.profile.tags[tag].frequency
- end
-
- if( pollTime and ( not fontString.frequentStart or fontString.frequentStart > pollTime ) ) then
- frequencyCache[tags] = pollTime
- frequentUpdates[fontString] = pollTime
- fontString.frequentStart = pollTime
- freqFrame:Show()
- end
-
- -- It's an invalid tag, simply return the tag itself wrapped in brackets
- if( not cachedFunc ) then
- functionPool[tag] = functionPool[tag] or function() return string.format("[%s-error]", tag) end
- cachedFunc = functionPool[tag]
- end
-
- table.insert(args, cachedFunc)
+ else
+ frequencyCache[tag] = Tags.defaultFrequents[tag] or ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].frequency
+ end
+
+
+ -- Figure out the lowest frequency rate we update at
+ if( frequencyCache[tag] ) then
+ lowestFrequency = math.min(lowestFrequency, frequencyCache[tag])
+ end
+
+ -- It's an invalid tag, simply return the tag itself wrapped in brackets
+ if( not cachedFunc ) then
+ functionPool[tag] = functionPool[tag] or function() return string.format("[%s-error]", tag) end
+ cachedFunc = functionPool[tag]
end
- -- Create our update function now
- updateFunc = function(fontString)
- for id, func in pairs(args) do
- temp[id] = func(fontString.parent.unit, fontString.parent.unitOwner, fontString) or ""
+ table.insert(args, cachedFunc)
+ end
+
+ frequencyCache[tags] = lowestFrequency < 9999 and lowestFrequency or nil
+ tagPool[tags] = function(fontString, frame, event, unit, powerType)
+ if( event and powerType and fontString.powerFilters and powerEvents[event] ) then
+ if( not fontString.powerFilters[powerType] and ( not fontString.powerFilters.CURRENT or fontString.powerType ~= powerType ) ) then
+ return
end
-
- fontString:SetFormattedText(formattedText, unpack(temp))
end
- tagPool[tags] = updateFunc
+ for id, func in pairs(args) do
+ temp[id] = func(fontString.parent.unit, fontString.parent.unitOwner, fontString) or ""
+ end
+
+ fontString:SetFormattedText(formattedText, unpack(temp))
+ end
+
+ return tagPool[tags], frequencyCache[tags]
+end
+
+local function createMonitorTimer(fontString, frequency)
+ if( not fontString.monitor or fontString.monitor.frequency ~= frequency ) then
+ if fontString.monitor then
+ fontString.monitor:Cancel()
+ end
+ fontString.monitor = C_Timer.NewTicker(frequency, function() fontString:UpdateTags() end)
+ fontString.monitor.frequency = frequency
end
+end
+
+local function cancelMonitorTimer(fontString)
+ if( fontString.monitor ) then
+ fontString.monitor:Cancel()
+ fontString.monitor = nil
+ end
+end
+
+function Tags:Register(parent, fontString, tags, resetCache)
+ -- Unregister the font string first if we did register it already
+ if( fontString.UpdateTags ) then
+ self:Unregister(fontString)
+ end
+
+ fontString.parent = parent
+ regFontStrings[fontString] = tags
-- And give other frames an easy way to force an update
- fontString.UpdateTags = updateFunc
+ local frequency
+ fontString.UpdateTags, frequency = createTagFunction(tags, resetCache)
+
+ if( frequency ) then
+ createMonitorTimer(fontString, frequency)
+ elseif( fontString.monitor ) then
+ cancelMonitorTimer(fontString)
+ end
-- Register any needed event
self:RegisterEvents(parent, fontString, tags)
@@ -172,18 +275,6 @@ end
function Tags:Unregister(fontString)
regFontStrings[fontString] = nil
- frequentUpdates[fontString] = nil
-
- -- Kill frequent updates if they aren't needed anymore
- local hasFrequent
- for k in pairs(frequentUpdates) do
- hasFrequent = true
- break
- end
-
- if( not hasFrequent ) then
- freqFrame:Hide()
- end
-- Unregister it as using HC
for key, module in pairs(self.customEvents) do
@@ -192,14 +283,28 @@ function Tags:Unregister(fontString)
module:DisableTag(fontString.parent, fontString)
end
end
-
+
-- Kill any tag data
+ cancelMonitorTimer(fontString)
fontString.parent:UnregisterAll(fontString)
- fontString.fastPower = nil
- fontString.fastHealth = nil
- fontString.frequentStart = nil
+ fontString.powerFilters = nil
fontString.UpdateTags = nil
fontString:SetText("")
+
+ -- See if we need to unregister events
+ local parent = fontString.parent
+ local hasPowerFilter
+ for _, fontString in pairs(parent.fontStrings) do
+ if( fontString.powerFilters and fontString.powerFilters.CURRENT ) then
+ hasPowerFilter = true
+ break
+ end
+ end
+
+ if( not hasPowerFilter ) then
+ parent:UnregisterSingleEvent("UNIT_DISPLAYPOWER", self)
+ parent:UnregisterUpdateFunc(self, "UpdatePowerType")
+ end
end
-- Helper functions for tags, the reason I store it in ShadowUF is it's easier to type ShadowUF than ShadowUF.modules.Tags, and simpler for users who want to implement it.
@@ -270,18 +375,25 @@ end})
-- Going to have to start using an env wrapper for tags I think
local Druid = {}
-Druid.CatForm, Druid.Shapeshift = GetSpellInfo(768)
+Druid.CatForm = GetSpellInfo(768)
Druid.MoonkinForm = GetSpellInfo(24858)
Druid.TravelForm = GetSpellInfo(783)
Druid.BearForm = GetSpellInfo(5487)
Druid.TreeForm = GetSpellInfo(33891)
-Druid.DireBearForm = GetSpellInfo(9634)
Druid.AquaticForm = GetSpellInfo(1066)
Druid.SwiftFlightForm = GetSpellInfo(40120)
Druid.FlightForm = GetSpellInfo(33943)
ShadowUF.Druid = Druid
Tags.defaultTags = {
+ ["rune:timer"] = [[function(unit, unitOwner, fontString)
+ local endTime = fontString.block.endTime
+ return endTime and string.format("%.1f", endTime - GetTime()) or nil
+ end]],
+ ["totem:timer"] = [[function(unit, unitOwner, fontString)
+ local endTime = fontString.block.endTime
+ return endTime and string.format("%.1f", endTime - GetTime()) or nil
+ end]],
["hp:color"] = [[function(unit, unitOwner)
return ShadowUF:Hex(ShadowUF.modules.healthBar.getGradientColor(unit))
end]],
@@ -289,19 +401,19 @@ Tags.defaultTags = {
if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end
local Druid = ShadowUF.Druid
- if( UnitAura(unit, Druid.CatForm, Druid.Shapeshift) ) then
+ if( ShadowUF.UnitAuraBySpell(unit, Druid.CatForm) ) then
return ShadowUF.L["C"]
- elseif( UnitAura(unit, Druid.TreeForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TreeForm) ) then
return ShadowUF.L["T"]
- elseif( UnitAura(unit, Druid.MoonkinForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.MoonkinForm) ) then
return ShadowUF.L["M"]
- elseif( UnitAura(unit, Druid.DireBearForm, Druid.Shapeshift) or UnitAura(unit, Druid.BearForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.BearForm) ) then
return ShadowUF.L["B"]
- elseif( UnitAura(unit, Druid.SwiftFlightForm, Druid.Shapeshift) or UnitAura(unit, Druid.FlightForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.SwiftFlightForm) or ShadowUF.UnitAuraBySpell(unit, Druid.FlightForm) ) then
return ShadowUF.L["F"]
- elseif( UnitAura(unit, Druid.TravelForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TravelForm) ) then
return ShadowUF.L["T"]
- elseif( UnitAura(unit, Druid.AquaticForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.AquaticForm) ) then
return ShadowUF.L["A"]
end
end]],
@@ -309,19 +421,19 @@ Tags.defaultTags = {
if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end
local Druid = ShadowUF.Druid
- if( UnitAura(unit, Druid.CatForm, Druid.Shapeshift) ) then
+ if( ShadowUF.UnitAuraBySpell(unit, Druid.CatForm) ) then
return ShadowUF.L["Cat"]
- elseif( UnitAura(unit, Druid.TreeForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TreeForm) ) then
return ShadowUF.L["Tree"]
- elseif( UnitAura(unit, Druid.MoonkinForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.MoonkinForm) ) then
return ShadowUF.L["Moonkin"]
- elseif( UnitAura(unit, Druid.DireBearForm, Druid.Shapeshift) or UnitAura(unit, Druid.BearForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.BearForm) ) then
return ShadowUF.L["Bear"]
- elseif( UnitAura(unit, Druid.SwiftFlightForm, Druid.Shapeshift) or UnitAura(unit, Druid.FlightForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.SwiftFlightForm) or ShadowUF.UnitAuraBySpell(unit, Druid.FlightForm) ) then
return ShadowUF.L["Flight"]
- elseif( UnitAura(unit, Druid.TravelForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TravelForm) ) then
return ShadowUF.L["Travel"]
- elseif( UnitAura(unit, Druid.AquaticForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.AquaticForm) ) then
return ShadowUF.L["Aquatic"]
end
end]],
@@ -577,6 +689,10 @@ Tags.defaultTags = {
return string.format("%s/%s", ShadowUF:SmartFormatNumber(power), ShadowUF:SmartFormatNumber(maxPower))
end]],
["levelcolor"] = [[function(unit, unitOwner)
+ if( UnitIsWildBattlePet(unit) or UnitIsBattlePetCompanion(unit) ) then
+ return nil
+ end
+
local level = UnitLevel(unit)
if( level < 0 and UnitClassification(unit) == "worldboss" ) then
return nil
@@ -590,11 +706,15 @@ Tags.defaultTags = {
return color .. (level > 0 and level or "??") .. "|r"
else
- return level
+ return level > 0 and level or "??"
end
end]],
["faction"] = [[function(unit, unitOwner) return UnitFactionGroup(unitOwner) end]],
["level"] = [[function(unit, unitOwner)
+ if( UnitIsWildBattlePet(unit) or UnitIsBattlePetCompanion(unit) ) then
+ return UnitBattlePetLevel(unit)
+ end
+
local level = UnitLevel(unit)
return level > 0 and level or UnitClassification(unit) ~= "worldboss" and "??" or nil
end]],
@@ -641,6 +761,10 @@ Tags.defaultTags = {
["name"] = [[function(unit, unitOwner) return UnitName(unitOwner) or UNKNOWN end]],
["server"] = [[function(unit, unitOwner)
local server = select(2, UnitName(unitOwner))
+ if( UnitRealmRelationship(unitOwner) == LE_REALM_RELATION_VIRTUAL ) then
+ return nil
+ end
+
return server ~= "" and server or nil
end]],
["perhp"] = [[function(unit, unitOwner)
@@ -675,13 +799,29 @@ Tags.defaultTags = {
return ShadowUF.L["Offline"]
end
end]],
+ ["sshards"] = [[function(unit, unitOwner)
+ local points = UnitPower(ShadowUF.playerUnit, Enum.PowerType.SoulShards)
+ return points and points > 0 and points
+ end]],
+ ["hpower"] = [[function(unit, unitOwner)
+ local points = UnitPower(ShadowUF.playerUnit, Enum.PowerType.HolyPower)
+ return points and points > 0 and points
+ end]],
+ ["monk:chipoints"] = [[function(unit, unitOwner)
+ local points = UnitPower(ShadowUF.playerUnit, Enum.PowerType.Chi)
+ return points and points > 0 and points
+ end]],
["cpoints"] = [[function(unit, unitOwner)
- local points = GetComboPoints(ShadowUF.playerUnit)
- if( points == 0 ) then
- points = GetComboPoints(ShadowUF.playerUnit, ShadowUF.playerUnit)
+ if( UnitHasVehicleUI("player") and UnitHasVehiclePlayerFrameUI("player") ) then
+ local points = GetComboPoints("vehicle")
+ if( points == 0 ) then
+ points = GetComboPoints("vehicle", "vehicle")
+ end
+
+ return points
+ else
+ return UnitPower("player", Enum.PowerType.ComboPoints)
end
-
- return points > 0 and points
end]],
["smartlevel"] = [[function(unit, unitOwner)
local classif = UnitClassification(unit)
@@ -697,7 +837,14 @@ Tags.defaultTags = {
end
end
end]],
- ["dechp"] = [[function(unit, unitOwner) return string.format("%.1f%%", (UnitHealth(unit) / UnitHealthMax(unit)) * 100) end]],
+ ["dechp"] = [[function(unit, unitOwner)
+ local maxHealth = UnitHealthMax(unit)
+ if( maxHealth <= 0 ) then
+ return "0.0%"
+ end
+
+ return string.format("%.1f%%", (UnitHealth(unit) / maxHealth) * 100)
+ end]],
["classification"] = [[function(unit, unitOwner)
local classif = UnitClassification(unit)
if( classif == "rare" ) then
@@ -708,22 +855,24 @@ Tags.defaultTags = {
return ShadowUF.L["Elite"]
elseif( classif == "worldboss" ) then
return ShadowUF.L["Boss"]
+ elseif( classif == "minus" ) then
+ return ShadowUF.L["Minion"]
end
return nil
end]],
["shortclassification"] = [[function(unit, unitOwner)
local classif = UnitClassification(unit)
- return classif == "rare" and "R" or classif == "rareelite" and "R+" or classif == "elite" and "+" or classif == "worldboss" and "B"
+ return classif == "rare" and "R" or classif == "rareelite" and "R+" or classif == "elite" and "+" or classif == "worldboss" and "B" or classif == "minus" and "M"
end]],
["group"] = [[function(unit, unitOwner)
- if( GetNumRaidMembers() == 0 ) then return nil end
+ if( not UnitInRaid(unitOwner) ) then return nil end
local name, server = UnitName(unitOwner)
if( server and server ~= "" ) then
name = string.format("%s-%s", name, server)
end
- for i=1, GetNumRaidMembers() do
+ for i=1, GetNumGroupMembers() do
local raidName, _, group = GetRaidRosterInfo(i)
if( raidName == name ) then
return group
@@ -735,22 +884,22 @@ Tags.defaultTags = {
["druid:curpp"] = [[function(unit, unitOwner)
if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end
local powerType = UnitPowerType(unit)
- if( powerType ~= 1 and powerType ~= 3 ) then return nil end
- return ShadowUF:FormatLargeNumber(UnitPower(unit, 0))
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ return ShadowUF:FormatLargeNumber(UnitPower(unit, Enum.PowerType.Mana))
end]],
["druid:abscurpp"] = [[function(unit, unitOwner)
if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end
local powerType = UnitPowerType(unit)
- if( powerType ~= 1 and powerType ~= 3 ) then return nil end
- return UnitPower(unit, 0)
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ return UnitPower(unit, Enum.PowerType.Mana)
end]],
["druid:curmaxpp"] = [[function(unit, unitOwner)
if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end
local powerType = UnitPowerType(unit)
- if( powerType ~= 1 and powerType ~= 3 ) then return nil end
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
- local maxPower = UnitPowerMax(unit, 0)
- local power = UnitPower(unit, 0)
+ local maxPower = UnitPowerMax(unit, Enum.PowerType.Mana)
+ local power = UnitPower(unit, Enum.PowerType.Mana)
if( UnitIsDeadOrGhost(unit) ) then
return string.format("0/%s", ShadowUF:FormatLargeNumber(maxPower))
elseif( maxPower == 0 and power == 0 ) then
@@ -762,25 +911,128 @@ Tags.defaultTags = {
["druid:absolutepp"] = [[function(unit, unitOwner)
if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end
local powerType = UnitPowerType(unit)
- if( powerType ~= 1 and powerType ~= 3 ) then return nil end
- return UnitPower(unit, 0)
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+
+ return UnitPower(unit, Enum.PowerType.Mana)
+ end]],
+ ["sec:curpp"] = [[function(unit, unitOwner)
+ local class = select(2, UnitClass(unit))
+ local powerType = UnitPowerType(unit)
+ if( class == "DRUID" ) then
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ elseif( class == "PRIEST" ) then
+ if( powerType ~= Enum.PowerType.Insanity ) then return nil end
+ elseif( class == "SHAMAN" ) then
+ if( powerType ~= Enum.PowerType.Maelstrom ) then return nil end
+ else
+ return nil
+ end
+ return ShadowUF:FormatLargeNumber(UnitPower(unit, Enum.PowerType.Mana))
+ end]],
+ ["sec:abscurpp"] = [[function(unit, unitOwner)
+ local class = select(2, UnitClass(unit))
+ local powerType = UnitPowerType(unit)
+ if( class == "DRUID" ) then
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ elseif( class == "PRIEST" ) then
+ if( powerType ~= Enum.PowerType.Insanity ) then return nil end
+ elseif( class == "SHAMAN" ) then
+ if( powerType ~= Enum.PowerType.Maelstrom ) then return nil end
+ else
+ return nil
+ end
+ return UnitPower(unit, Enum.PowerType.Mana)
+ end]],
+ ["sec:curmaxpp"] = [[function(unit, unitOwner)
+ local class = select(2, UnitClass(unit))
+ local powerType = UnitPowerType(unit)
+ if( class == "DRUID" ) then
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ elseif( class == "PRIEST" ) then
+ if( powerType ~= Enum.PowerType.Insanity ) then return nil end
+ elseif( class == "SHAMAN" ) then
+ if( powerType ~= Enum.PowerType.Maelstrom ) then return nil end
+ else
+ return nil
+ end
+
+ local maxPower = UnitPowerMax(unit, Enum.PowerType.Mana)
+ local power = UnitPower(unit, Enum.PowerType.Mana)
+ if( UnitIsDeadOrGhost(unit) ) then
+ return string.format("0/%s", ShadowUF:FormatLargeNumber(maxPower))
+ elseif( maxPower == 0 and power == 0 ) then
+ return nil
+ end
+
+ return string.format("%s/%s", ShadowUF:FormatLargeNumber(power), ShadowUF:FormatLargeNumber(maxPower))
+ end]],
+ ["sec:absolutepp"] = [[function(unit, unitOwner)
+ local class = select(2, UnitClass(unit))
+ local powerType = UnitPowerType(unit)
+ if( class == "DRUID" ) then
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ elseif( class == "PRIEST" ) then
+ if( powerType ~= Enum.PowerType.Insanity ) then return nil end
+ elseif( class == "SHAMAN" ) then
+ if( powerType ~= Enum.PowerType.Maelstrom ) then return nil end
+ else
+ return nil
+ end
+
+ return UnitPower(unit, Enum.PowerType.Mana)
+ end]],
+ ["per:incheal"] = [[function(unit, unitOwner, fontString)
+ local heal = UnitGetIncomingHeals(unit)
+ local maxHealth = UnitHealthMax(unit)
+ return heal and heal > 0 and maxHealth > 0 and string.format("%d%%", (heal / maxHealth) * 100)
end]],
["abs:incheal"] = [[function(unit, unitOwner, fontString)
- return fontString.incoming and string.format("%d", fontString.incoming)
+ local heal = UnitGetIncomingHeals(unit)
+ return heal and heal > 0 and string.format("%d", heal)
end]],
["incheal"] = [[function(unit, unitOwner, fontString)
- return fontString.incoming and ShadowUF:FormatLargeNumber(fontString.incoming) or nil
+ local heal = UnitGetIncomingHeals(unit)
+ return heal and heal > 0 and ShadowUF:FormatLargeNumber(heal)
end]],
["incheal:name"] = [[function(unit, unitOwner, fontString)
- return fontString.incoming and string.format("+%d", fontString.incoming) or ShadowUF.tagFunc.name(unit, unitOwner)
+ local heal = UnitGetIncomingHeals(unit)
+ return heal and heal > 0 and string.format("+%d", heal) or ShadowUF.tagFunc.name(unit, unitOwner, fontString)
+ end]],
+ ["monk:abs:stagger"] = [[function(unit, unitOwner)
+ local stagger = UnitStagger(unit)
+ return stagger and stagger > 0 and stagger
+ end]],
+ ["monk:stagger"] = [[function(unit, unitOwner)
+ local stagger = UnitStagger(unit)
+ return stagger and stagger > 0 and ShadowUF:FormatLargeNumber(stagger)
+ end]],
+ ["abs:incabsorb"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalAbsorbs(unit)
+ return absorb and absorb > 0 and absorb
+ end]],
+ ["incabsorb"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalAbsorbs(unit)
+ return absorb and absorb > 0 and ShadowUF:FormatLargeNumber(absorb)
+ end]],
+ ["incabsorb:name"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalAbsorbs(unit)
+ return absorb and absorb > 0 and string.format("+%d", absorb) or ShadowUF.tagFunc.name(unit, unitOwner, fontString)
+ end]],
+ ["abs:healabsorb"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalHealAbsorbs(unit)
+ return absorb and absorb > 0 and absorb
+ end]],
+ ["healabsorb"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalHealAbsorbs(unit)
+ return absorb and absorb > 0 and ShadowUF:FormatLargeNumber(absorb)
end]],
["unit:raid:targeting"] = [[function(unit, unitOwner, fontString)
- if( GetNumRaidMembers() == 0 ) then return nil end
+ if( GetNumGroupMembers() == 0 ) then return nil end
local guid = UnitGUID(unit)
if( not guid ) then return "0" end
local total = 0
- for i=1, GetNumRaidMembers() do
+ for i=1, GetNumGroupMembers() do
local unit = ShadowUF.raidUnits[i]
if( UnitGUID(ShadowUF.unitTarget[unit]) == guid ) then
total = total + 1
@@ -789,12 +1041,12 @@ Tags.defaultTags = {
return total
end]],
["unit:raid:assist"] = [[function(unit, unitOwner, fontString)
- if( GetNumRaidMembers() == 0 ) then return nil end
+ if( GetNumGroupMembers() == 0 ) then return nil end
local guid = UnitGUID(ShadowUF.unitTarget[unit])
if( not guid ) then return "--" end
local total = 0
- for i=1, GetNumRaidMembers() do
+ for i=1, GetNumGroupMembers() do
local unit = ShadowUF.raidUnits[i]
if( UnitGUID(ShadowUF.unitTarget[unit]) == guid ) then
total = total + 1
@@ -806,64 +1058,82 @@ Tags.defaultTags = {
-- Default tag events
Tags.defaultEvents = {
- ["hp:color"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["short:druidform"] = "UNIT_AURA",
- ["druidform"] = "UNIT_AURA",
- ["guild"] = "UNIT_NAME_UPDATE", -- Not sure when this data is available, guessing
- ["abs:incheal"] = "HEALCOMM",
- ["incheal:name"] = "HEALCOMM",
- ["incheal"] = "HEALCOMM",
- ["afk"] = "PLAYER_FLAGS_CHANGED", -- Yes, I know it's called PLAYER_FLAGS_CHANGED, but arg1 is the unit including non-players.
- ["afk:time"] = "PLAYER_FLAGS_CHANGED",
- ["status:time"] = "UNIT_MANA",
- ["pvp:time"] = "PLAYER_FLAGS_CHANGED",
- ["curhp"] = "UNIT_HEALTH",
- ["abscurhp"] = "UNIT_HEALTH",
- ["curmaxhp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["absolutehp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["smart:curmaxhp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["curpp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER",
- ["abscurpp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWERR",
- ["curmaxpp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["absolutepp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["smart:curmaxpp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["druid:curpp"] = "UNIT_MANA UNIT_DISPLAYPOWER",
- ["druid:abscurpp"] = "UNIT_MANA UNIT_DISPLAYPOWER",
- ["druid:curmaxpp"] = "UNIT_MANA UNIT_MAXMANA UNIT_DISPLAYPOWER",
- ["druid:absolutepp"] = "UNIT_MANA UNIT_MAXMANA UNIT_DISPLAYPOWER",
- ["level"] = "UNIT_LEVEL PLAYER_LEVEL_UP",
- ["levelcolor"] = "UNIT_LEVEL PLAYER_LEVEL_UP",
- ["maxhp"] = "UNIT_MAXHEALTH",
- ["def:name"] = "UNIT_NAME_UPDATE UNIT_MAXHEALTH UNIT_HEALTH",
- ["absmaxhp"] = "UNIT_MAXHEALTH",
- ["maxpp"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["absmaxpp"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["missinghp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["missingpp"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_MAXRUNIC_POWER UNIT_RUNIC_POWER",
- ["name"] = "UNIT_NAME_UPDATE",
- ["abbrev:name"] = "UNIT_NAME_UPDATE",
- ["server"] = "UNIT_NAME_UPDATE",
- ["colorname"] = "UNIT_NAME_UPDATE",
- ["perhp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["perpp"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_MAXRUNIC_POWER UNIT_RUNIC_POWER",
- ["status"] = "UNIT_HEALTH PLAYER_UPDATE_RESTING",
- ["smartlevel"] = "UNIT_LEVEL PLAYER_LEVEL_UP UNIT_CLASSIFICATION_CHANGED",
- ["cpoints"] = "UNIT_COMBO_POINTS PLAYER_TARGET_CHANGED",
- ["rare"] = "UNIT_CLASSIFICATION_CHANGED",
- ["classification"] = "UNIT_CLASSIFICATION_CHANGED",
- ["shortclassification"] = "UNIT_CLASSIFICATION_CHANGED",
- ["dechp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["group"] = "RAID_ROSTER_UPDATE",
- ["unit:color:aggro"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["color:aggro"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["situation"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["color:sit"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["scaled:threat"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["general:sit"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["color:gensit"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["unit:scaled:threat"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["unit:color:sit"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["unit:situation"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["totem:timer"] = "SUF_TOTEM_TIMER",
+ ["rune:timer"] = "SUF_RUNE_TIMER",
+ ["hp:color"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_MAXHEALTH",
+ ["short:druidform"] = "UNIT_AURA",
+ ["druidform"] = "UNIT_AURA",
+ ["guild"] = "UNIT_NAME_UPDATE",
+ ["per:incheal"] = "UNIT_HEAL_PREDICTION",
+ ["abs:incheal"] = "UNIT_HEAL_PREDICTION",
+ ["incheal:name"] = "UNIT_HEAL_PREDICTION",
+ ["incheal"] = "UNIT_HEAL_PREDICTION",
+ ["abs:incabsorb"] = "UNIT_ABSORB_AMOUNT_CHANGED",
+ ["incabsorb"] = "UNIT_ABSORB_AMOUNT_CHANGED",
+ ["incabsorb:name"] = "UNIT_ABSORB_AMOUNT_CHANGED",
+ ["abs:healabsorb"] = "UNIT_HEAL_ABSORB_AMOUNT_CHANGED",
+ ["healabsorb"] = "UNIT_HEAL_ABSORB_AMOUNT_CHANGED",
+ -- ["crtabs"] = "CRTABS",
+ -- ["abs:crtabs"] = "CRTABS",
+ -- ["crtabs:name"] = "CRTABS",
+ ["afk"] = "PLAYER_FLAGS_CHANGED", -- Yes, I know it's called PLAYER_FLAGS_CHANGED, but arg1 is the unit including non-players.
+ ["afk:time"] = "PLAYER_FLAGS_CHANGED UNIT_CONNECTION",
+ ["status:time"] = "UNIT_POWER_FREQUENT UNIT_CONNECTION",
+ ["pvp:time"] = "PLAYER_FLAGS_CHANGED",
+ ["curhp"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_CONNECTION",
+ ["abscurhp"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_CONNECTION",
+ ["curmaxhp"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_MAXHEALTH UNIT_CONNECTION",
+ ["absolutehp"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_MAXHEALTH UNIT_CONNECTION",
+ ["smart:curmaxhp"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_MAXHEALTH UNIT_CONNECTION",
+ ["curpp"] = "SUF_POWERTYPE:CURRENT UNIT_POWER_FREQUENT",
+ ["abscurpp"] = "SUF_POWERTYPE:CURRENT UNIT_POWER_FREQUENT UNIT_MAXPOWER",
+ ["curmaxpp"] = "SUF_POWERTYPE:CURRENT UNIT_POWER_FREQUENT UNIT_MAXPOWER",
+ ["absolutepp"] = "SUF_POWERTYPE:CURRENT UNIT_POWER_FREQUENT UNIT_MAXPOWER",
+ ["smart:curmaxpp"] = "SUF_POWERTYPE:CURRENT UNIT_POWER_FREQUENT UNIT_MAXPOWER",
+ ["druid:curpp"] = "SUF_POWERTYPE:MANA UNIT_POWER_FREQUENT UNIT_DISPLAYPOWER",
+ ["druid:abscurpp"] = "SUF_POWERTYPE:MANA UNIT_POWER_FREQUENT UNIT_DISPLAYPOWER",
+ ["druid:curmaxpp"] = "SUF_POWERTYPE:MANA UNIT_POWER_FREQUENT UNIT_MAXPOWER UNIT_DISPLAYPOWER",
+ ["druid:absolutepp"] = "SUF_POWERTYPE:MANA UNIT_POWER_FREQUENT UNIT_MAXPOWER UNIT_DISPLAYPOWER",
+ ["sec:curpp"] = "SUF_POWERTYPE:MANA UNIT_POWER_FREQUENT UNIT_DISPLAYPOWER",
+ ["sec:abscurpp"] = "SUF_POWERTYPE:MANA UNIT_POWER_FREQUENT UNIT_DISPLAYPOWER",
+ ["sec:curmaxpp"] = "SUF_POWERTYPE:MANA UNIT_POWER_FREQUENT UNIT_MAXPOWER UNIT_DISPLAYPOWER",
+ ["sec:absolutepp"] = "SUF_POWERTYPE:MANA UNIT_POWER_FREQUENT UNIT_MAXPOWER UNIT_DISPLAYPOWER",
+ ["sshards"] = "SUF_POWERTYPE:SOUL_SHARDS UNIT_POWER_FREQUENT",
+ ["hpower"] = "SUF_POWERTYPE:HOLY_POWER UNIT_POWER_FREQUENT",
+ ["level"] = "UNIT_LEVEL UNIT_FACTION PLAYER_LEVEL_UP",
+ ["levelcolor"] = "UNIT_LEVEL UNIT_FACTION PLAYER_LEVEL_UP",
+ ["maxhp"] = "UNIT_MAXHEALTH",
+ ["def:name"] = "UNIT_NAME_UPDATE UNIT_MAXHEALTH UNIT_HEALTH UNIT_HEALTH_FREQUENT",
+ ["absmaxhp"] = "UNIT_MAXHEALTH",
+ ["maxpp"] = "SUF_POWERTYPE:CURRENT UNIT_MAXPOWER",
+ ["absmaxpp"] = "SUF_POWERTYPE:CURRENT UNIT_MAXPOWER",
+ ["missinghp"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_MAXHEALTH UNIT_CONNECTION",
+ ["missingpp"] = "SUF_POWERTYPE:CURRENT UNIT_POWER_FREQUENT UNIT_MAXPOWER",
+ ["name"] = "UNIT_NAME_UPDATE",
+ ["abbrev:name"] = "UNIT_NAME_UPDATE",
+ ["server"] = "UNIT_NAME_UPDATE",
+ ["colorname"] = "UNIT_NAME_UPDATE",
+ ["perhp"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_MAXHEALTH UNIT_CONNECTION",
+ ["perpp"] = "SUF_POWERTYPE:CURRENT UNIT_POWER_FREQUENT UNIT_MAXPOWER UNIT_CONNECTION",
+ ["status"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT PLAYER_UPDATE_RESTING UNIT_CONNECTION",
+ ["smartlevel"] = "UNIT_LEVEL PLAYER_LEVEL_UP UNIT_CLASSIFICATION_CHANGED",
+ ["cpoints"] = "UNIT_POWER_FREQUENT PLAYER_TARGET_CHANGED",
+ ["rare"] = "UNIT_CLASSIFICATION_CHANGED",
+ ["classification"] = "UNIT_CLASSIFICATION_CHANGED",
+ ["shortclassification"] = "UNIT_CLASSIFICATION_CHANGED",
+ ["dechp"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_MAXHEALTH",
+ ["group"] = "GROUP_ROSTER_UPDATE",
+ ["unit:color:aggro"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["color:aggro"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["situation"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["color:sit"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["scaled:threat"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["general:sit"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["color:gensit"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["unit:scaled:threat"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["unit:color:sit"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["unit:situation"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["monk:chipoints"] = "SUF_POWERTYPE:LIGHT_FORCE UNIT_POWER_FREQUENT",
}
-- Default update frequencies for tag updating, used if it's needed to override the update speed
@@ -877,253 +1147,310 @@ Tags.defaultFrequents = {
["unit:scaled:threat"] = 1,
["unit:raid:targeting"] = 0.50,
["unit:raid:assist"] = 0.50,
+ ["monk:stagger"] = 0.25,
+ ["monk:abs:stagger"] = 0.25
}
-- Default tag categories
Tags.defaultCategories = {
- ["hp:color"] = "health",
- ["abs:incheal"] = "health",
- ["incheal"] = "health",
- ["incheal:name"] = "health",
- ["smart:curmaxhp"] = "health",
- ["smart:curmaxpp"] = "health",
- ["afk"] = "status",
- ["afk:time"] = "status",
- ["status:time"] = "status",
- ["pvp:time"] = "status",
- ["cpoints"] = "misc",
- ["smartlevel"] = "classification",
- ["classification"] = "classification",
- ["shortclassification"] = "classification",
- ["rare"] = "classification",
- ["plus"] = "classification",
- ["sex"] = "misc",
- ["smartclass"] = "classification",
- ["smartrace"] = "classification",
- ["status"] = "status",
- ["race"] = "classification",
- ["level"] = "classification",
- ["maxhp"] = "health",
- ["maxpp"] = "power",
- ["missinghp"] = "health",
- ["missingpp"] = "power",
- ["name"] = "misc",
- ["abbrev:name"] = "misc",
- ["server"] = "misc",
- ["perhp"] = "health",
- ["perpp"] = "power",
- ["class"] = "classification",
- ["classcolor"] = "classification",
- ["creature"] = "classification",
- ["short:druidform"] = "classification",
- ["druidform"] = "classification",
- ["curhp"] = "health",
- ["curpp"] = "power",
- ["curmaxhp"] = "health",
- ["curmaxpp"] = "power",
- ["levelcolor"] = "classification",
- ["def:name"] = "health",
- ["faction"] = "classification",
- ["colorname"] = "misc",
- ["guild"] = "misc",
- ["absolutepp"] = "power",
- ["absolutehp"] = "health",
- ["absmaxhp"] = "health",
- ["abscurhp"] = "health",
- ["absmaxpp"] = "power",
- ["abscurpp"] = "power",
- ["reactcolor"] = "classification",
- ["dechp"] = "health",
- ["group"] = "misc",
- ["close"] = "misc",
- ["druid:curpp"] = "power",
- ["druid:abscurpp"] = "power",
- ["druid:curmaxpp"] = "power",
- ["druid:absolutepp"] = "power",
- ["situation"] = "playerthreat",
- ["color:sit"] = "playerthreat",
- ["scaled:threat"] = "playerthreat",
- ["general:sit"] = "playerthreat",
- ["color:gensit"] = "playerthreat",
- ["color:aggro"] = "playerthreat",
- ["unit:scaled:threat"] = "threat",
- ["unit:color:sit"] = "threat",
- ["unit:situation"] = "threat",
- ["unit:color:aggro"] = "threat",
- ["unit:raid:assist"] = "raid",
- ["unit:raid:targeting"] = "raid",
+ ["totem:timer"] = "classtimer",
+ ["rune:timer"] = "classtimer",
+ ["hp:color"] = "health",
+ ["abs:incabsorb"] = "health",
+ ["incabsorb"] = "health",
+ ["incabsorb:name"] = "health",
+ ["per:incheal"] = "health",
+ ["abs:incheal"] = "health",
+ ["incheal"] = "health",
+ ["incheal:name"] = "health",
+ ["smart:curmaxhp"] = "health",
+ ["smart:curmaxpp"] = "health",
+ ["afk"] = "status",
+ ["afk:time"] = "status",
+ ["status:time"] = "status",
+ ["pvp:time"] = "status",
+ ["cpoints"] = "classspec",
+ ["smartlevel"] = "classification",
+ ["classification"] = "classification",
+ ["shortclassification"] = "classification",
+ ["rare"] = "classification",
+ ["plus"] = "classification",
+ ["sex"] = "misc",
+ ["smartclass"] = "classification",
+ ["smartrace"] = "classification",
+ ["status"] = "status",
+ ["race"] = "classification",
+ ["level"] = "classification",
+ ["maxhp"] = "health",
+ ["maxpp"] = "power",
+ ["missinghp"] = "health",
+ ["missingpp"] = "power",
+ ["name"] = "misc",
+ ["abbrev:name"] = "misc",
+ ["server"] = "misc",
+ ["perhp"] = "health",
+ ["perpp"] = "power",
+ ["class"] = "classification",
+ ["classcolor"] = "classification",
+ ["creature"] = "classification",
+ ["short:druidform"] = "classification",
+ ["druidform"] = "classification",
+ ["curhp"] = "health",
+ ["curpp"] = "power",
+ ["curmaxhp"] = "health",
+ ["curmaxpp"] = "power",
+ ["levelcolor"] = "classification",
+ ["def:name"] = "health",
+ ["faction"] = "classification",
+ ["colorname"] = "misc",
+ ["guild"] = "misc",
+ ["absolutepp"] = "power",
+ ["absolutehp"] = "health",
+ ["absmaxhp"] = "health",
+ ["abscurhp"] = "health",
+ ["absmaxpp"] = "power",
+ ["abscurpp"] = "power",
+ ["reactcolor"] = "classification",
+ ["dechp"] = "health",
+ ["group"] = "misc",
+ ["close"] = "misc",
+ ["druid:curpp"] = "classspec",
+ ["druid:abscurpp"] = "classspec",
+ ["druid:curmaxpp"] = "classspec",
+ ["druid:absolutepp"] = "classspec",
+ ["sec:curpp"] = "classspec",
+ ["sec:abscurpp"] = "classspec",
+ ["sec:curmaxpp"] = "classspec",
+ ["sec:absolutepp"] = "classspec",
+ ["sshards"] = "classspec",
+ ["hpower"] = "classspec",
+ ["situation"] = "playerthreat",
+ ["color:sit"] = "playerthreat",
+ ["scaled:threat"] = "playerthreat",
+ ["general:sit"] = "playerthreat",
+ ["color:gensit"] = "playerthreat",
+ ["color:aggro"] = "playerthreat",
+ ["unit:scaled:threat"] = "threat",
+ ["unit:color:sit"] = "threat",
+ ["unit:situation"] = "threat",
+ ["unit:color:aggro"] = "threat",
+ ["unit:raid:assist"] = "raid",
+ ["unit:raid:targeting"] = "raid",
+ ["monk:chipoints"] = "classspec",
+ ["monk:stagger"] = "classspec",
+ ["monk:abs:stagger"] = "classspec"
}
-- Default tag help
Tags.defaultHelp = {
- ["hp:color"] = L["Color code based on percentage of HP left on the unit, this works the same way as the color by health option. But for text instead of the entire bar."],
- ["guild"] = L["Show's the units guild name if they are in a guild."],
- ["short:druidform"] = L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."],
- ["druidform"] = L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."],
- ["abs:incheal"] = L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."],
- ["incheal"] = L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."],
- ["incheal:name"] = L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."],
- ["smart:curmaxhp"] = L["Smart number formating for [curmaxhp], numbers below 1,000,000 are left as is, numbers above 1,000,000 will use the short version such as 1m."],
- ["smart:curmaxpp"] = L["Smart number formating for [curmaxpp], numbers below 1,000,000 are left as is, numbers above 1,000,000 will use the short version such as 1m."],
- ["pvp:time"] = L["Shows how long until your PVP flag drops, will not show if the flag is manually on or you are in a hostile zone.|n|nThis will only work for yourself, you cannot use it to see the time left on your party or raid."],
- ["afk:time"] = L["Shows how long an unit has been AFK or DND."],
- ["status:time"] = L["Shows how long an unit has been offline."],
- ["afk"] = L["Shows AFK, DND or nothing depending on the units away status."],
- ["cpoints"] = L["Total number of combo points you have on your target."],
- ["smartlevel"] = L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."],
- ["classification"] = L["Units classification, Rare, Rare Elite, Elite, Boss, nothing is shown if they aren't any of those."],
- ["shortclassification"] = L["Short classifications, R for Rare, R+ for Rare Elite, + for Elite, B for boss, nothing is shown if they aren't any of those."],
- ["rare"] = L["Returns Rare if the unit is a rare or rare elite mob."],
- ["plus"] = L["Returns + if the unit is an elite or rare elite mob."],
- ["sex"] = L["Returns the units sex."],
- ["smartclass"] = L["If the unit is a player then class is returned, if it's a NPC then the creature type."],
- ["smartrace"] = L["If the unit is a player then race is returned, if it's a NPC then the creature type."],
- ["status"] = L["Shows Offline, Dead, Ghost or nothing depending on the units current status."],
- ["race"] = L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."],
- ["level"] = L["Level without any coloring."],
- ["maxhp"] = L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."],
- ["maxpp"] = L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."],
- ["missinghp"] = L["Amount of health missing, if none is missing nothing is shown. Uses a short format, -18500 is shown as -18.5k, values below 10000 are formatted as is."],
- ["missingpp"] = L["Amount of power missing, if none is missing nothing is shown. Uses a short format, -13850 is shown as 13.8k, values below 10000 are formatted as is."],
- ["name"] = L["Unit name"],
- ["server"] = L["Unit server, if they are from your server then nothing is shown."],
- ["perhp"] = L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."],
- ["perpp"] = L["Returns current power as a percentage."],
- ["class"] = L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."],
- ["classcolor"] = L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"],
- ["creature"] = L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."],
- ["curhp"] = L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."],
- ["curpp"] = L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."],
- ["curmaxhp"] = L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."],
- ["curmaxpp"] = L["Current and maximum power, formatted as [curpp]/[maxpp]."],
- ["levelcolor"] = L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."],
- ["def:name"] = L["When the unit is mising health, the [missinghp] tag is shown, when they are at full health then the [name] tag is shown. This lets you see -1000 when they are missing 1000 HP, but their name when they are not missing any."],
- ["faction"] = L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."],
- ["colorname"] = L["Unit name colored by class."],
- ["absolutepp"] = L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."],
- ["absolutehp"] = L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."],
- ["absmaxhp"] = L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."],
- ["abscurhp"] = L["Shows current health value in absolute form meaning 15000 health is shown as 15000."],
- ["absmaxpp"] = L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."],
- ["abscurpp"] = L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."],
- ["reactcolor"] = L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."],
- ["dechp"] = L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."],
- ["abbrev:name"] = L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."],
- ["group"] = L["Shows current group number of the unit."],
- ["close"] = L["Closes a color code, prevents colors from showing up on text that you do not want it to."],
- ["druid:curpp"] = string.format(L["Works the same as %s, but this is only shown if the unit is in Cat or Bear form."], "currpp"),
- ["druid:abscurpp"] = string.format(L["Works the same as %s, but this is only shown if the unit is in Cat or Bear form."], "abscurpp"),
- ["druid:curmaxpp"] = string.format(L["Works the same as %s, but this is only shown if the unit is in Cat or Bear form."], "curmaxpp"),
- ["druid:absolutepp"] = string.format(L["Works the same as %s, but this is only shown if the unit is in Cat or Bear form."], "absolutepp"),
- ["situation"] = L["Returns text based on your threat situation with your target: Aggro for Aggro, High for being close to taking aggro, and Medium as a general warning to be wary."],
- ["color:sit"] = L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."],
- ["scaled:threat"] = L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."],
- ["general:sit"] = L["Returns text based on your general threat situation on all units: Aggro for Aggro, High for being near to pulling aggro and Medium as a general warning."],
- ["color:gensit"] = L["Returns a color code of your general threat situation on all units: Red for Aggro, Orange for High threat and Yellow to watch out."],
- ["unit:scaled:threat"] = L["Returns the scaled threat percentage for the unit, if you put this on a party member you would see the percentage of how close they are to getting any from any hostile mobs. Always 0 - 100%.|nThis cannot be used on target of target or focus target types of units."],
- ["unit:color:sit"] = L["Returns the color code for the units threat situation in general: Red for Aggro, Orange for High threat and Yellow to watch out.|nThis cannot be used on target of target or focus target types of units."],
- ["unit:situation"] = L["Returns text based on the units general threat situation: Aggro for Aggro, High for being close to taking aggro, and Medium as a warning to be wary.|nThis cannot be used on target of target or focus target types of units."],
- ["unit:color:aggro"] = L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."],
- ["color:aggro"] = L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."],
- ["unit:raid:targeting"] = L["How many people in your raid are targeting the unit, for example if you put this on yourself it will show how many people are targeting you. This includes you in the count!"],
- ["unit:raid:assist"] = L["How many people are assisting the unit, for example if you put this on yourself it will show how many people are targeting your target. This includes you in the count!"],
+ ["totem:timer"] = L["How many seconds a totem has left before disappearing."],
+ ["rune:timer"] = L["How many seconds before a rune recharges."],
+ ["abs:incabsorb"] = L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."],
+ ["incabsorb"] = L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."],
+ ["incabsorb:name"] = L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."],
+ ["hp:color"] = L["Color code based on percentage of HP left on the unit, this works the same way as the color by health option. But for text instead of the entire bar."],
+ ["guild"] = L["Show's the units guild name if they are in a guild."],
+ ["short:druidform"] = L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."],
+ ["druidform"] = L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."],
+ ["per:incheal"] = L["Percent of the players current health that's being healed, if they have 100,000 total health and 15,000 is incoming then 15% is shown."],
+ ["abs:incheal"] = L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."],
+ ["incheal"] = L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."],
+ ["abs:healabsorb"] = L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."],
+ ["healabsorb"] = L["Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k."],
+ ["incheal:name"] = L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."],
+ ["smart:curmaxhp"] = L["Smart number formating for [curmaxhp], numbers below 1,000,000 are left as is, numbers above 1,000,000 will use the short version such as 1m."],
+ ["smart:curmaxpp"] = L["Smart number formating for [curmaxpp], numbers below 1,000,000 are left as is, numbers above 1,000,000 will use the short version such as 1m."],
+ ["pvp:time"] = L["Shows how long until your PVP flag drops, will not show if the flag is manually on or you are in a hostile zone.|n|nThis will only work for yourself, you cannot use it to see the time left on your party or raid."],
+ ["afk:time"] = L["Shows how long an unit has been AFK or DND."],
+ ["status:time"] = L["Shows how long an unit has been offline."],
+ ["afk"] = L["Shows AFK, DND or nothing depending on the units away status."],
+ ["cpoints"] = L["Total number of combo points you have on your target."],
+ ["hpower"] = L["Total number of active holy power."],
+ ["sshards"] = L["Total number of active soul shards."],
+ ["smartlevel"] = L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."],
+ ["classification"] = L["Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those."],
+ ["shortclassification"] = L["Short classifications, R for Rare, R+ for Rare Elite, + for Elite, B for Boss or M for Minion nothing is shown if they aren't any of those."],
+ ["rare"] = L["Returns Rare if the unit is a rare or rare elite mob."],
+ ["plus"] = L["Returns + if the unit is an elite or rare elite mob."],
+ ["sex"] = L["Returns the units sex."],
+ ["smartclass"] = L["If the unit is a player then class is returned, if it's a NPC then the creature type."],
+ ["smartrace"] = L["If the unit is a player then race is returned, if it's a NPC then the creature type."],
+ ["status"] = L["Shows Offline, Dead, Ghost or nothing depending on the units current status."],
+ ["race"] = L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."],
+ ["level"] = L["Level without any coloring."],
+ ["maxhp"] = L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."],
+ ["maxpp"] = L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."],
+ ["missinghp"] = L["Amount of health missing, if none is missing nothing is shown. Uses a short format, -18500 is shown as -18.5k, values below 10000 are formatted as is."],
+ ["missingpp"] = L["Amount of power missing, if none is missing nothing is shown. Uses a short format, -13850 is shown as 13.8k, values below 10000 are formatted as is."],
+ ["name"] = L["Unit name"],
+ ["server"] = L["Unit server, if they are from your server then nothing is shown."],
+ ["perhp"] = L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."],
+ ["perpp"] = L["Returns current power as a percentage."],
+ ["class"] = L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."],
+ ["classcolor"] = L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"],
+ ["creature"] = L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."],
+ ["curhp"] = L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."],
+ ["curpp"] = L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."],
+ ["curmaxhp"] = L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."],
+ ["curmaxpp"] = L["Current and maximum power, formatted as [curpp]/[maxpp]."],
+ ["levelcolor"] = L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."],
+ ["def:name"] = L["When the unit is mising health, the [missinghp] tag is shown, when they are at full health then the [name] tag is shown. This lets you see -1000 when they are missing 1000 HP, but their name when they are not missing any."],
+ ["faction"] = L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."],
+ ["colorname"] = L["Unit name colored by class."],
+ ["absolutepp"] = L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."],
+ ["absolutehp"] = L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."],
+ ["absmaxhp"] = L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."],
+ ["abscurhp"] = L["Shows current health value in absolute form meaning 15000 health is shown as 15000."],
+ ["absmaxpp"] = L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."],
+ ["abscurpp"] = L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."],
+ ["reactcolor"] = L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."],
+ ["dechp"] = L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."],
+ ["abbrev:name"] = L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."],
+ ["group"] = L["Shows current group number of the unit."],
+ ["close"] = L["Closes a color code, prevents colors from showing up on text that you do not want it to."],
+ ["druid:curpp"] = string.format(L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."], "currpp"),
+ ["druid:abscurpp"] = string.format(L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."], "abscurpp"),
+ ["druid:curmaxpp"] = string.format(L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."], "curmaxpp"),
+ ["druid:absolutepp"] = string.format(L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."], "absolutepp"),
+ ["sec:curpp"] = string.format(L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."], "curpp"),
+ ["sec:abscurpp"] = string.format(L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."], "abscurpp"),
+ ["sec:curmaxpp"] = string.format(L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."], "curmaxpp"),
+ ["sec:absolutepp"] = string.format(L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."], "absolutepp"),
+ ["situation"] = L["Returns text based on your threat situation with your target: Aggro for Aggro, High for being close to taking aggro, and Medium as a general warning to be wary."],
+ ["color:sit"] = L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."],
+ ["scaled:threat"] = L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."],
+ ["general:sit"] = L["Returns text based on your general threat situation on all units: Aggro for Aggro, High for being near to pulling aggro and Medium as a general warning."],
+ ["color:gensit"] = L["Returns a color code of your general threat situation on all units: Red for Aggro, Orange for High threat and Yellow to watch out."],
+ ["unit:scaled:threat"] = L["Returns the scaled threat percentage for the unit, if you put this on a party member you would see the percentage of how close they are to getting any from any hostile mobs. Always 0 - 100%.|nThis cannot be used on target of target or focus target types of units."],
+ ["unit:color:sit"] = L["Returns the color code for the units threat situation in general: Red for Aggro, Orange for High threat and Yellow to watch out.|nThis cannot be used on target of target or focus target types of units."],
+ ["unit:situation"] = L["Returns text based on the units general threat situation: Aggro for Aggro, High for being close to taking aggro, and Medium as a warning to be wary.|nThis cannot be used on target of target or focus target types of units."],
+ ["unit:color:aggro"] = L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."],
+ ["color:aggro"] = L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."],
+ ["unit:raid:targeting"] = L["How many people in your raid are targeting the unit, for example if you put this on yourself it will show how many people are targeting you. This includes you in the count!"],
+ ["unit:raid:assist"] = L["How many people are assisting the unit, for example if you put this on yourself it will show how many people are targeting your target. This includes you in the count!"],
+ ["monk:chipoints"] = L["How many Chi points you currently have."],
+ ["monk:stagger"] = L["Shows the current staggered damage, if 12,000 damage is staggered, shows 12k."],
+ ["monk:abs:stagger"] = L["Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000."]
}
Tags.defaultNames = {
- ["incheal:name"] = L["Incoming heal/Name"],
- ["unit:scaled:threat"] = L["Unit scaled threat"],
- ["unit:color:sit"] = L["Unit colored situation"],
- ["unit:situation"] = L["Unit situation name"],
- ["hp:color"] = L["Health color"],
- ["guild"] = L["Guild name"],
- ["druidform"] = L["Druid form"],
- ["short:druidform"] = L["Druid form (Short)"],
- ["abs:incheal"] = L["Incoming heal (Absolute)"],
- ["incheal"] = L["Incoming heal (Short)"],
- ["abbrev:name"] = L["Name (Abbreviated)"],
- ["smart:curmaxhp"] = L["Cur/Max HP (Smart)"],
- ["smart:curmaxpp"] = L["Cur/Max PP (Smart)"],
- ["pvp:time"] = L["PVP timer"],
- ["afk:time"] = L["AFK timer"],
- ["status:time"] = L["Offline timer"],
- ["afk"] = L["AFK status"],
- ["cpoints"] = L["Combo points"],
- ["smartlevel"] = L["Smart level"],
- ["classification"] = L["Classificaiton"],
- ["shortclassification"] = L["Short classification"],
- ["rare"] = L["Rare indicator"],
- ["plus"] = L["Short elite indicator"],
- ["sex"] = L["Sex"],
- ["smartclass"] = L["Class (Smart)"],
- ["smartrace"] = L["Race (Smart)"],
- ["status"] = L["Status"],
- ["race"] = L["Race"],
- ["level"] = L["Level"],
- ["maxhp"] = L["Max HP (Short)"],
- ["maxpp"] = L["Max power (Short)"],
- ["missinghp"] = L["Missing HP (Short)"],
- ["missingpp"] = L["Missing power (Short)"],
- ["name"] = L["Unit name"],
- ["server"] = L["Unit server"],
- ["perhp"] = L["Percent HP"],
- ["perpp"] = L["Percent power"],
- ["class"] = L["Class"],
- ["classcolor"] = L["Class color tag"],
- ["creature"] = L["Creature type"],
- ["curhp"] = L["Current HP (Short)"],
- ["curpp"] = L["Current Power (Short)"],
- ["curmaxhp"] = L["Cur/Max HP (Short)"],
- ["curmaxpp"] = L["Cur/Max Power (Short)"],
- ["levelcolor"] = L["Level (Colored)"],
- ["def:name"] = L["Deficit/Unit Name"],
- ["faction"] = L["Unit faction"],
- ["colorname"] = L["Unit name (Class colored)"],
- ["absolutepp"] = L["Cur/Max power (Absolute)"],
- ["absolutehp"] = L["Cur/Max HP (Absolute)"],
- ["absmaxhp"] = L["Max HP (Absolute)"],
- ["abscurhp"] = L["Current HP (Absolute)"],
- ["absmaxpp"] = L["Max power (Absolute)"],
- ["abscurpp"] = L["Current power (Absolute)"],
- ["reactcolor"] = L["Reaction color tag"],
- ["dechp"] = L["Decimal percent HP"],
- ["group"] = L["Group number"],
- ["close"] = L["Close color"],
- ["druid:curpp"] = L["Current power (Druid)"],
- ["druid:abscurpp"] = L["Current power (Druid/Absolute)"],
- ["druid:curmaxpp"] = L["Cur/Max power (Druid)"],
- ["druid:absolutepp"] = L["Current health (Druid/Absolute)"],
- ["situation"] = L["Threat situation"],
- ["color:sit"] = L["Color code for situation"],
- ["scaled:threat"] = L["Scaled threat percent"],
- ["general:sit"] = L["General threat situation"],
- ["color:gensit"] = L["Color code for general situation"],
- ["color:aggro"] = L["Color code on aggro"],
- ["unit:color:aggro"] = L["Unit color code on aggro"],
- ["unit:raid:targeting"] = L["Raid targeting unit"],
- ["unit:raid:assist"] = L["Raid assisting unit"],
+ ["totem:timer"] = L["Totem Timer"],
+ ["rune:timer"] = L["Rune Timer"],
+ ["abs:incabsorb"] = L["Damage absorption (Absolute)"],
+ ["incabsorb"] = L["Damage absorption (Short)"],
+ ["incabsorb:name"] = L["Damage absorption/Name"],
+ ["per:incheal"] = L["Incoming heal (Percent)"],
+ ["incheal:name"] = L["Incoming heal/Name"],
+ ["abs:healabsorb"] = L["Heal Absorb (Absolute)"],
+ ["healabsorb"] = L["Heal Absorb (Short)"],
+ ["unit:scaled:threat"] = L["Unit scaled threat"],
+ ["unit:color:sit"] = L["Unit colored situation"],
+ ["unit:situation"] = L["Unit situation name"],
+ ["hp:color"] = L["Health color"],
+ ["guild"] = L["Guild name"],
+ ["druidform"] = L["Druid form"],
+ ["short:druidform"] = L["Druid form (Short)"],
+ ["abs:incheal"] = L["Incoming heal (Absolute)"],
+ ["incheal"] = L["Incoming heal (Short)"],
+ ["abbrev:name"] = L["Name (Abbreviated)"],
+ ["smart:curmaxhp"] = L["Cur/Max HP (Smart)"],
+ ["smart:curmaxpp"] = L["Cur/Max PP (Smart)"],
+ ["pvp:time"] = L["PVP timer"],
+ ["afk:time"] = L["AFK timer"],
+ ["status:time"] = L["Offline timer"],
+ ["afk"] = L["AFK status"],
+ ["cpoints"] = L["Combo points"],
+ ["hpower"] = L["Holy power"],
+ ["sshards"] = L["Soul shards"],
+ ["smartlevel"] = L["Smart level"],
+ ["classification"] = L["Classification"],
+ ["shortclassification"] = L["Short classification"],
+ ["rare"] = L["Rare indicator"],
+ ["plus"] = L["Short elite indicator"],
+ ["sex"] = L["Sex"],
+ ["smartclass"] = L["Class (Smart)"],
+ ["smartrace"] = L["Race (Smart)"],
+ ["status"] = L["Status"],
+ ["race"] = L["Race"],
+ ["level"] = L["Level"],
+ ["maxhp"] = L["Max HP (Short)"],
+ ["maxpp"] = L["Max power (Short)"],
+ ["missinghp"] = L["Missing HP (Short)"],
+ ["missingpp"] = L["Missing power (Short)"],
+ ["name"] = L["Unit name"],
+ ["server"] = L["Unit server"],
+ ["perhp"] = L["Percent HP"],
+ ["perpp"] = L["Percent power"],
+ ["class"] = L["Class"],
+ ["classcolor"] = L["Class color tag"],
+ ["creature"] = L["Creature type"],
+ ["curhp"] = L["Current HP (Short)"],
+ ["curpp"] = L["Current Power (Short)"],
+ ["curmaxhp"] = L["Cur/Max HP (Short)"],
+ ["curmaxpp"] = L["Cur/Max Power (Short)"],
+ ["levelcolor"] = L["Level (Colored)"],
+ ["def:name"] = L["Deficit/Unit Name"],
+ ["faction"] = L["Unit faction"],
+ ["colorname"] = L["Unit name (Class colored)"],
+ ["absolutepp"] = L["Cur/Max power (Absolute)"],
+ ["absolutehp"] = L["Cur/Max HP (Absolute)"],
+ ["absmaxhp"] = L["Max HP (Absolute)"],
+ ["abscurhp"] = L["Current HP (Absolute)"],
+ ["absmaxpp"] = L["Max power (Absolute)"],
+ ["abscurpp"] = L["Current power (Absolute)"],
+ ["reactcolor"] = L["Reaction color tag"],
+ ["dechp"] = L["Decimal percent HP"],
+ ["group"] = L["Group number"],
+ ["close"] = L["Close color"],
+ ["druid:curpp"] = L["Current power (Druid)"],
+ ["druid:abscurpp"] = L["Current power (Druid/Absolute)"],
+ ["druid:curmaxpp"] = L["Cur/Max power (Druid)"],
+ ["druid:absolutepp"] = L["Cur/Max power (Druid/Absolute)"],
+ ["sec:curpp"] = L["Current power (Secondary)"],
+ ["sec:abscurpp"] = L["Current power (Secondary/Absolute)"],
+ ["sec:curmaxpp"] = L["Cur/Max power (Secondary)"],
+ ["sec:absolutepp"] = L["Cur/Max power (Secondary/Absolute)"],
+ ["situation"] = L["Threat situation"],
+ ["color:sit"] = L["Color code for situation"],
+ ["scaled:threat"] = L["Scaled threat percent"],
+ ["general:sit"] = L["General threat situation"],
+ ["color:gensit"] = L["Color code for general situation"],
+ ["color:aggro"] = L["Color code on aggro"],
+ ["unit:color:aggro"] = L["Unit color code on aggro"],
+ ["unit:raid:targeting"] = L["Raid targeting unit"],
+ ["unit:raid:assist"] = L["Raid assisting unit"],
+ ["monk:chipoints"] = L["Chi Points"],
+ ["monk:stagger"] = L["Stagger (Monk)"],
+ ["monk:abs:stagger"] = L["Stagger (Monk/Absolute)"]
}
-- List of event types
Tags.eventType = {
- ["UNIT_ENERGY"] = "power",
- ["UNIT_FOCUS"] = "power",
- ["UNIT_MANA"] = "power",
- ["UNIT_RAGE"] = "power",
- ["UNIT_RUNIC_POWER"] = "power",
+ ["UNIT_POWER_FREQUENT"] = "power",
+ ["UNIT_MAXPOWER"] = "power",
+ ["UNIT_ABSORB_AMOUNT_CHANGED"] = "health",
+ ["UNIT_HEALTH_FREQUENT"] = "health",
["UNIT_HEALTH"] = "health",
["UNIT_MAXHEALTH"] = "health",
- ["RAID_ROSTER_UPDATE"] = "unitless",
+ ["GROUP_ROSTER_UPDATE"] = "unitless",
["RAID_TARGET_UPDATE"] = "unitless",
["PLAYER_TARGET_CHANGED"] = "unitless",
- ["PARTY_MEMBERS_CHANGED"] = "unitless",
["PARTY_LEADER_CHANGED"] = "unitless",
["PLAYER_ENTERING_WORLD"] = "unitless",
+ ["PLAYER_REGEN_DISABLED"] = "unitless",
+ ["PLAYER_REGEN_ENABLED"] = "unitless",
["PLAYER_XP_UPDATE"] = "unitless",
["PLAYER_TOTEM_UPDATE"] = "unitless",
["PLAYER_LEVEL_UP"] = "unitless",
["UPDATE_EXHAUSTION"] = "unitless",
["PLAYER_UPDATE_RESTING"] = "unitless",
["UNIT_COMBO_POINTS"] = "unitless",
+ ["PARTY_LOOT_METHOD_CHANGED"] = "unitless",
+ ["READY_CHECK"] = "unitless",
+ ["READY_CHECK_FINISHED"] = "unitless",
+ ["RUNE_POWER_UPDATE"] = "unitless",
+ ["RUNE_TYPE_UPDATE"] = "unitless",
+ ["UPDATE_FACTION"] = "unitless",
}
-- Tag groups that have a special filter that can't be used on certain units, like the threat API's
@@ -1134,6 +1461,13 @@ Tags.unitBlacklist = {
-- Single tags that can only be used on a single unit
Tags.unitRestrictions = {
["pvp:time"] = "player",
+ ["totem:timer"] = "player",
+ ["rune:timer"] = "player"
+}
+
+Tags.anchorRestriction = {
+ ["totem:timer"] = "$totemBar",
+ ["rune:timer"] = "$runeBar"
}
-- Event scanner to automatically figure out what events a tag will need
@@ -1141,22 +1475,23 @@ local function loadAPIEvents()
if( Tags.APIEvents ) then return end
Tags.APIEvents = {
["InCombatLockdown"] = "PLAYER_REGEN_ENABLED PLAYER_REGEN_DISABLED",
- ["UnitLevel"] = "UNIT_LEVEL",
+ ["UnitLevel"] = "UNIT_LEVEL UNIT_FACTION",
+ ["UnitBattlePetLevel"] = "UNIT_LEVEL UNIT_FACTION",
["UnitName"] = "UNIT_NAME_UPDATE",
["UnitClassification"] = "UNIT_CLASSIFICATION_CHANGED",
["UnitFactionGroup"] = "UNIT_FACTION PLAYER_FLAGS_CHANGED",
- ["UnitHealth%("] = "UNIT_HEALTH",
+ ["UnitHealth%("] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT",
["UnitHealthMax"] = "UNIT_MAXHEALTH",
- ["UnitPower%("] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER",
- ["UnitPowerMax"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
+ ["UnitPower%("] = "UNIT_POWER_FREQUENT",
+ ["UnitPowerMax"] = "UNIT_MAXPOWER",
["UnitPowerType"] = "UNIT_DISPLAYPOWER",
- ["UnitIsDead"] = "UNIT_HEALTH",
- ["UnitIsGhost"] = "UNIT_HEALTH",
- ["UnitIsConnected"] = "UNIT_HEALTH",
+ ["UnitIsDead"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT",
+ ["UnitIsGhost"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT",
+ ["UnitIsConnected"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_CONNECTION",
["UnitIsAFK"] = "PLAYER_FLAGS_CHANGED",
["UnitIsDND"] = "PLAYER_FLAGS_CHANGED",
["UnitIsPVP"] = "PLAYER_FLAGS_CHANGED UNIT_FACTION",
- ["UnitIsPartyLeader"] = "PARTY_LEADER_CHANGED PARTY_MEMBERS_CHANGED",
+ ["UnitIsGroupLeader"] = "PARTY_LEADER_CHANGED GROUP_ROSTER_UPDATE",
["UnitIsPVPFreeForAll"] = "PLAYER_FLAGS_CHANGED UNIT_FACTION",
["UnitCastingInfo"] = "UNIT_SPELLCAST_START UNIT_SPELLCAST_STOP UNIT_SPELLCAST_FAILED UNIT_SPELLCAST_INTERRUPTED UNIT_SPELLCAST_DELAYED",
["UnitChannelInfo"] = "UNIT_SPELLCAST_CHANNEL_START UNIT_SPELLCAST_CHANNEL_STOP UNIT_SPELLCAST_CHANNEL_INTERRUPTED UNIT_SPELLCAST_CHANNEL_UPDATE",
@@ -1164,6 +1499,7 @@ local function loadAPIEvents()
["UnitBuff"] = "UNIT_AURA",
["UnitDebuff"] = "UNIT_AURA",
["UnitXPMax"] = "UNIT_PET_EXPERIENCE PLAYER_XP_UPDATE PLAYER_LEVEL_UP",
+ ["UnitGetTotalAbsorbs"] = "UNIT_ABSORB_AMOUNT_CHANGED",
["UnitXP%("] = "UNIT_PET_EXPERIENCE PLAYER_XP_UPDATE PLAYER_LEVEL_UP",
["GetTotemInfo"] = "PLAYER_TOTEM_UPDATE",
["GetXPExhaustion"] = "UPDATE_EXHAUSTION",
@@ -1171,11 +1507,10 @@ local function loadAPIEvents()
["GetRuneCooldown"] = "RUNE_POWER_UPDATE",
["GetRuneType"] = "RUNE_TYPE_UPDATE",
["GetRaidTargetIndex"] = "RAID_TARGET_UPDATE",
- ["GetComboPoints"] = "UNIT_COMBO_POINTS",
- ["GetNumPartyMembers"] = "PARTY_MEMBERS_CHANGED",
- ["GetNumRaidMembers"] = "RAID_ROSTER_UPDATE",
- ["GetRaidRosterInfo"] = "RAID_ROSTER_UPDATE",
- ["GetPetHappiness"] = "UNIT_HAPPINESS",
+ ["GetComboPoints"] = "UNIT_POWER_FREQUENT",
+ ["GetNumSubgroupMembers"] = "GROUP_ROSTER_UPDATE",
+ ["GetNumGroupMembers"] = "GROUP_ROSTER_UPDATE",
+ ["GetRaidRosterInfo"] = "GROUP_ROSTER_UPDATE",
["GetReadyCheckStatus"] = "READY_CHECK READY_CHECK_CONFIRM READY_CHECK_FINISHED",
["GetLootMethod"] = "PARTY_LOOT_METHOD_CHANGED",
["GetThreatStatusColor"] = "UNIT_THREAT_SITUATION_UPDATE",
diff --git a/modules/totems.lua b/modules/totems.lua
index fd9e92d9a..32307ce74 100755
--- a/modules/totems.lua
+++ b/modules/totems.lua
@@ -3,24 +3,47 @@ local totemColors = {}
local MAX_TOTEMS = MAX_TOTEMS
-- Death Knights untalented ghouls are guardians and are considered totems........... so set it up for them
-if( select(2, UnitClass("player")) == "DEATHKNIGHT" ) then
+local playerClass = select(2, UnitClass("player"))
+if( playerClass == "PALADIN" ) then
MAX_TOTEMS = 1
- ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Guardian bar"], true, "DEATHKNIGHT")
+ ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Ancient Kings bar"], true, "PALADIN", nil, 70)
+elseif( playerClass == "DRUID" ) then
+ MAX_TOTEMS = 1
+ ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Mushroom bar"], true, "DRUID", 4, 70)
+elseif( playerClass == "MONK" ) then
+ MAX_TOTEMS = 1
+ ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Statue bar"], true, "MONK", {1, 2}, 70)
+elseif( playerClass == "MAGE" ) then
+ MAX_TOTEMS = 1
+ ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Rune of Power bar"], true, "MAGE", {1, 2, 3}, 45)
+elseif( playerClass == "WARLOCK" ) then
+ MAX_TOTEMS = 2
+ ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Imp & Dreadstalker bar"], true, "WARLOCK", 2)
else
ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Totem bar"], true, "SHAMAN")
end
+ShadowUF.BlockTimers:Inject(Totems, "TOTEM_TIMER")
+ShadowUF.DynamicBlocks:Inject(Totems)
+
+function Totems:SecureLockable()
+ return MAX_TOTEMS > 1
+end
+
function Totems:OnEnable(frame)
if( not frame.totemBar ) then
frame.totemBar = CreateFrame("Frame", nil, frame)
frame.totemBar.totems = {}
+ frame.totemBar.blocks = frame.totemBar.totems
+
+ local priorities = (playerClass == "SHAMAN") and SHAMAN_TOTEM_PRIORITIES or STANDARD_TOTEM_PRIORITIES
for id=1, MAX_TOTEMS do
- local totem = ShadowUF.Units:CreateBar(frame)
- totem:SetFrameLevel(1)
+ local totem = ShadowUF.Units:CreateBar(frame.totemBar)
totem:SetMinMaxValues(0, 1)
totem:SetValue(0)
- totem.id = MAX_TOTEMS == 1 and 1 or TOTEM_PRIORITIES[id]
+ totem.id = MAX_TOTEMS == 1 and 1 or priorities[id]
+ totem.parent = frame
if( id > 1 ) then
totem:SetPoint("TOPLEFT", frame.totemBar.totems[id - 1], "TOPRIGHT", 1, 0)
@@ -30,9 +53,16 @@ function Totems:OnEnable(frame)
table.insert(frame.totemBar.totems, totem)
end
-
- if( MAX_TOTEMS == 1 ) then
+
+ if( playerClass == "DRUID" ) then
+ totemColors[1] = ShadowUF.db.profile.powerColors.MUSHROOMS
+ elseif( playerClass == "WARLOCK" ) then
totemColors[1] = ShadowUF.db.profile.classColors.PET
+ totemColors[2] = ShadowUF.db.profile.classColors.PET
+ elseif( playerClass == "MONK" ) then
+ totemColors[1] = ShadowUF.db.profile.powerColors.STATUE
+ elseif( playerClass == "MAGE" ) then
+ totemColors[1] = ShadowUF.db.profile.powerColors.RUNEOFPOWER
else
totemColors[1] = {r = 1, g = 0, b = 0.4}
totemColors[2] = {r = 0, g = 1, b = 0.4}
@@ -42,34 +72,59 @@ function Totems:OnEnable(frame)
end
frame:RegisterNormalEvent("PLAYER_TOTEM_UPDATE", self, "Update")
+ frame:RegisterUpdateFunc(self, "UpdateVisibility")
frame:RegisterUpdateFunc(self, "Update")
end
function Totems:OnDisable(frame)
frame:UnregisterAll(self)
+ frame:UnregisterUpdateFunc(self, "Update")
+
+ for _, totem in pairs(frame.totemBar.totems) do
+ totem:Hide()
+ end
end
function Totems:OnLayoutApplied(frame)
- if( frame.visibility.totemBar ) then
- local barWidth = (frame.totemBar:GetWidth() - (MAX_TOTEMS - 1)) / MAX_TOTEMS
-
- for _, totem in pairs(frame.totemBar.totems) do
- if( ShadowUF.db.profile.units[frame.unitType].totemBar.background ) then
- local color = ShadowUF.db.profile.bars.backgroundColor or ShadowUF.db.profile.units[frame.unitType].totemBar.backgroundColor or totemColors[totem.id]
- totem.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
- totem.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
- totem.background:Show()
- else
- totem.background:Hide()
- end
-
- totem:SetHeight(frame.totemBar:GetHeight())
- totem:SetWidth(barWidth)
- totem:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
- totem:SetStatusBarColor(totemColors[totem.id].r, totemColors[totem.id].g, totemColors[totem.id].b, ShadowUF.db.profile.bars.alpha)
- totem:GetStatusBarTexture():SetHorizTile(false)
+ if( not frame.visibility.totemBar ) then return end
+
+ local barWidth = (frame.totemBar:GetWidth() - (MAX_TOTEMS - 1)) / MAX_TOTEMS
+ local config = ShadowUF.db.profile.units[frame.unitType].totemBar
+
+ for _, totem in pairs(frame.totemBar.totems) do
+ totem:SetHeight(frame.totemBar:GetHeight())
+ totem:SetWidth(barWidth)
+ totem:SetOrientation(ShadowUF.db.profile.units[frame.unitType].totemBar.vertical and "VERTICAL" or "HORIZONTAL")
+ totem:SetReverseFill(ShadowUF.db.profile.units[frame.unitType].totemBar.reverse and true or false)
+ totem:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
+ totem:GetStatusBarTexture():SetHorizTile(false)
+
+ totem.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
+
+ if( config.background or config.invert ) then
+ totem.background:Show()
+ else
+ totem.background:Hide()
+ end
+
+ if( not ShadowUF.db.profile.units[frame.unitType].totemBar.icon ) then
+ frame:SetBlockColor(totem, "totemBar", totemColors[totem.id].r, totemColors[totem.id].g, totemColors[totem.id].b)
+ end
+
+ if( config.secure ) then
+ totem.secure = totem.secure or CreateFrame("Button", frame:GetName() .. "Secure" .. totem.id, totem, "SecureUnitButtonTemplate")
+ totem.secure:RegisterForClicks("RightButtonUp")
+ totem.secure:SetAllPoints(totem)
+ totem.secure:SetAttribute("type2", "destroytotem")
+ totem.secure:SetAttribute("*totem-slot*", totem.id)
+ totem.secure:Show()
+
+ elseif( totem.secure ) then
+ totem.secure:Hide()
end
end
+
+ self:Update(frame)
end
local function totemMonitor(self, elapsed)
@@ -79,14 +134,48 @@ local function totemMonitor(self, elapsed)
if( time >= self.endTime ) then
self:SetValue(0)
self:SetScript("OnUpdate", nil)
+ self.endTime = nil
+
+ if( not self.parent.inVehicle and MAX_TOTEMS == 1 ) then
+ ShadowUF.Layout:SetBarVisibility(self.parent, "totemBar", false)
+ end
+ end
+
+ if( self.fontString ) then
+ self.fontString:UpdateTags()
+ end
+end
+
+function Totems:UpdateVisibility(frame)
+ if( frame.totemBar.inVehicle ~= frame.inVehicle ) then
+ frame.totemBar.inVehicle = frame.inVehicle
+
+ if( frame.inVehicle ) then
+ ShadowUF.Layout:SetBarVisibility(frame, "totemBar", false)
+ elseif( MAX_TOTEMS ~= 1 ) then
+ self:Update(frame)
+ end
end
end
function Totems:Update(frame)
local totalActive = 0
for _, indicator in pairs(frame.totemBar.totems) do
- local have, name, start, duration = GetTotemInfo(indicator.id)
+ local have, name, start, duration, icon
+ if MAX_TOTEMS == 1 and indicator.id == 1 then
+ local id = 1
+ while not have and id <= 4 do
+ have, name, start, duration, icon = GetTotemInfo(id)
+ id = id + 1
+ end
+ else
+ have, name, start, duration, icon = GetTotemInfo(indicator.id)
+ end
if( have and start > 0 ) then
+ if( ShadowUF.db.profile.units[frame.unitType].totemBar.icon ) then
+ indicator:SetStatusBarTexture(icon)
+ end
+
indicator.have = true
indicator.endTime = start + duration
indicator:SetMinMaxValues(0, duration)
@@ -101,11 +190,18 @@ function Totems:Update(frame)
indicator:SetScript("OnUpdate", nil)
indicator:SetMinMaxValues(0, 1)
indicator:SetValue(0)
+ indicator.endTime = nil
+ end
+
+ if( indicator.fontString ) then
+ indicator.fontString:UpdateTags()
end
end
- -- Only guardian timers should auto hide, nothing else
- if( MAX_TOTEMS == 1 ) then
- ShadowUF.Layout:SetBarVisibility(frame, "totemBar", totalActive > 0)
+ if( not frame.inVehicle ) then
+ -- Guardian timers always auto hide or if it's flagged to not always be shown
+ if( MAX_TOTEMS == 1 or not ShadowUF.db.profile.units[frame.unitType].totemBar.showAlways ) then
+ ShadowUF.Layout:SetBarVisibility(frame, "totemBar", totalActive > 0)
+ end
end
end
diff --git a/modules/units.lua b/modules/units.lua
old mode 100644
new mode 100755
index 8255da444..1f2fd99ad
--- a/modules/units.lua
+++ b/modules/units.lua
@@ -1,15 +1,34 @@
-local Units = {headerFrames = {}, unitFrames = {}, frameList = {}, unitEvents = {}}
-Units.childUnits = {["partytarget"] = "party", ["partypet"] = "party", ["maintanktarget"] = "maintank", ["mainassisttarget"] = "mainassist", ["bosstarget"] = "boss", ["arenatarget"] = "arena", ["arenapet"] = "arena"}
-Units.zoneUnits = {["arena"] = "arena", ["boss"] = "raid"}
+local Units = {headerFrames = {}, unitFrames = {}, frameList = {}, unitEvents = {}, remappedUnits = {}, canCure = {}}
+Units.childUnits = {["partytarget"] = "party", ["partytargettarget"] = "party", ["partypet"] = "party", ["maintanktarget"] = "maintank", ["mainassisttarget"] = "mainassist", ["bosstarget"] = "boss", ["arenatarget"] = "arena", ["arenatargettarget"] = "arena", ["arenapet"] = "arena", ["battlegroundpet"] = "battleground", ["battlegroundtarget"] = "battleground", ["battlegroundtargettarget"] = "battleground", ["maintanktargettarget"] = "maintank", ["mainassisttargettarget"] = "mainassist", ["bosstargettarget"] = "boss"}
+Units.zoneUnits = {["arena"] = "arena", ["arenapet"] = "arena", ["arenatarget"] = "arena", ["arenatargettarget"] = "arena", ["boss"] = {"party", "raid"}, ["bosstarget"] = {"party", "raid"}, ["battleground"] = "pvp", ["battlegroundtarget"] = "pvp", ["battlegroundtargettarget"] = "pvp", ["battlegroundpet"] = "pvp", ["bosstargettarget"] = {"party", "raid"}}
+Units.remappedUnits = {["battleground"] = "arena", ["battlegroundpet"] = "arenapet", ["battlegroundtarget"] = "arenatarget", ["battlegroundtargettarget"] = "arenatargettarget"}
+Units.headerUnits = {["raid"] = true, ["party"] = true, ["maintank"] = true, ["mainassist"] = true, ["raidpet"] = true, ["partypet"] = true}
local stateMonitor = CreateFrame("Frame", nil, nil, "SecureHandlerBaseTemplate")
+stateMonitor.raids = {}
local playerClass = select(2, UnitClass("player"))
-local unitFrames, headerFrames, frameList, unitEvents, childUnits, queuedCombat = Units.unitFrames, Units.headerFrames, Units.frameList, Units.unitEvents, Units.childUnits, {}
+local unitFrames, headerFrames, frameList, unitEvents, childUnits, headerUnits, queuedCombat, zoneUnits = Units.unitFrames, Units.headerFrames, Units.frameList, Units.unitEvents, Units.childUnits, Units.headerUnits, {}, Units.zoneUnits
+local remappedUnits = Units.remappedUnits
local _G = getfenv(0)
ShadowUF.Units = Units
ShadowUF:RegisterModule(Units, "units")
-
+
+-- This is the wrapper frame that everything parents to so we can just hide it when we need to deal with pet battles
+local petBattleFrame = CreateFrame("Frame", "SUFWrapperFrame", UIParent, "SecureHandlerBaseTemplate")
+petBattleFrame:SetFrameStrata("BACKGROUND")
+petBattleFrame:SetAllPoints(UIParent)
+petBattleFrame:WrapScript(petBattleFrame, "OnAttributeChanged", [[
+ if( name ~= "state-petbattle" ) then return end
+ if( value == "active" ) then
+ self:Hide()
+ else
+ self:Show()
+ end
+]])
+
+RegisterStateDriver(petBattleFrame, "petbattle", "[petbattle] active; none")
+
-- Frame shown, do a full update
local function FullUpdate(self)
for i=1, #(self.fullUpdates), 2 do
@@ -18,28 +37,58 @@ local function FullUpdate(self)
end
end
+-- Re-registers events when unit changes
+local function ReregisterUnitEvents(self)
+ -- Not an unit event
+ if( ShadowUF.fakeUnits[self.unitRealType] or not headerUnits[self.unitType] ) then return end
+
+ for event, list in pairs(self.registeredEvents) do
+ if( unitEvents[event] ) then
+ local hasHandler
+ for handler in pairs(list) do
+ hasHandler = true
+ break
+ end
+
+ if( hasHandler ) then
+ self:UnregisterEvent(event)
+ self:BlizzRegisterUnitEvent(event, self.unitOwner, self.vehicleUnit)
+ end
+ end
+ end
+end
+
-- Register an event that should always call the frame
-local function RegisterNormalEvent(self, event, handler, func)
+local function RegisterNormalEvent(self, event, handler, func, unitOverride)
-- Make sure the handler/func exists
if( not handler[func] ) then
error(string.format("Invalid handler/function passed for %s on event %s, the function %s does not exist.", self:GetName() or tostring(self), tostring(event), tostring(func)), 3)
return
end
- self:RegisterEvent(event)
+ if( unitEvents[event] and not ShadowUF.fakeUnits[self.unitRealType] ) then
+ self:BlizzRegisterUnitEvent(event, unitOverride or self.unitOwner, self.vehicleUnit)
+ if unitOverride then
+ self.unitEventOverrides = self.unitEventOverrides or {}
+ self.unitEventOverrides[event] = unitOverride
+ end
+ else
+ self:RegisterEvent(event)
+ end
+
self.registeredEvents[event] = self.registeredEvents[event] or {}
-- Each handler can only register an event once per a frame.
if( self.registeredEvents[event][handler] ) then
return
end
-
+
self.registeredEvents[event][handler] = func
end
-- Unregister an event
local function UnregisterEvent(self, event, handler)
- if( self.registeredEvents[event] ) then
+ if( self.registeredEvents[event] and self.registeredEvents[event][handler] ) then
self.registeredEvents[event][handler] = nil
local hasHandler
@@ -63,7 +112,7 @@ end
-- Register a function to be called in an OnUpdate if it's an invalid unit (targettarget/etc)
local function RegisterUpdateFunc(self, handler, func)
if( not handler[func] ) then
- error(string.format("Invalid handler/function passed to RegisterUpdateFunc for %s, the function %s does not exist.", self:GetName() or tostring(self), event, func), 3)
+ error(string.format("Invalid handler/function passed to RegisterUpdateFunc for %s, the function %s does not exist.", self:GetName() or tostring(self), func), 3)
return
end
@@ -97,16 +146,18 @@ local function UnregisterAll(self, handler)
end
for event, list in pairs(self.registeredEvents) do
- list[handler] = nil
-
- local hasRegister
- for handler in pairs(list) do
- hasRegister = true
- break
- end
-
- if( not hasRegister ) then
- self:UnregisterEvent(event)
+ if( list[handler] ) then
+ list[handler] = nil
+
+ local hasRegister
+ for handler in pairs(list) do
+ hasRegister = true
+ break
+ end
+
+ if( not hasRegister ) then
+ self:UnregisterEvent(event)
+ end
end
end
end
@@ -128,9 +179,32 @@ local function SetRangeAlpha(self, alpha)
end
end
+local function SetBarColor(self, key, r, g, b)
+ self:SetBlockColor(self[key], key, r, g, b)
+end
+
+local function SetBlockColor(self, bar, key, r, g, b)
+ local bgColor = bar.background.overrideColor or bar.background.backgroundColor
+ if( not ShadowUF.db.profile.units[self.unitType][key].invert ) then
+ bar:SetStatusBarColor(r, g, b, ShadowUF.db.profile.bars.alpha)
+ if( not bgColor ) then
+ bar.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.backgroundAlpha)
+ else
+ bar.background:SetVertexColor(bgColor.r, bgColor.g, bgColor.b, ShadowUF.db.profile.bars.backgroundAlpha)
+ end
+ else
+ bar.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.alpha)
+ if( not bgColor ) then
+ bar:SetStatusBarColor(0, 0, 0, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
+ else
+ bar:SetStatusBarColor(bgColor.r, bgColor.g, bgColor.b, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
+ end
+ end
+end
+
-- Event handling
local function OnEvent(self, event, unit, ...)
- if( not unitEvents[event] or self.unit == unit ) then
+ if( not unitEvents[event] or self.unit == unit or (self.unitEventOverrides and self.unitEventOverrides[event] == unit)) then
for handler, func in pairs(self.registeredEvents[event]) do
handler[func](handler, self, event, unit, ...)
end
@@ -140,6 +214,12 @@ end
Units.OnEvent = OnEvent
-- Do a full update OnShow, and stop watching for events when it's not visible
+local function OnShowForced(self)
+ -- Reset the event handler
+ self:SetScript("OnEvent", OnEvent)
+ self:FullUpdate()
+end
+
local function OnShow(self)
-- Reset the event handler
self:SetScript("OnEvent", OnEvent)
@@ -148,7 +228,7 @@ end
local function OnHide(self)
self:SetScript("OnEvent", nil)
-
+
-- If it's a volatile such as target or focus, next time it's shown it has to do an update
-- OR if the unit is still shown, but it's been hidden because our parent (Basically UIParent)
-- we want to flag it as having changed so it can be updated
@@ -157,24 +237,12 @@ local function OnHide(self)
end
end
--- *target units do not give events, polling is necessary here
-local function TargetUnitUpdate(self, elapsed)
- self.timeElapsed = self.timeElapsed + elapsed
-
- if( self.timeElapsed >= 0.50 ) then
- self.timeElapsed = self.timeElapsed - 0.50
-
- -- Have to make sure the unit exists or else the frame will flash offline for a second until it hides
- if( UnitExists(self.unit) ) then
- self:FullUpdate()
- end
- end
-end
-
-- Deal with enabling modules inside a zone
local function SetVisibility(self)
local layoutUpdate
- local instanceType = select(2, IsInInstance())
+ local instanceType = select(2, IsInInstance()) or "none"
+ local playerSpec = GetSpecialization()
+ if( instanceType == "scenario" ) then instanceType = "party" end
-- Selectively disable modules
for _, module in pairs(ShadowUF.moduleOrder) do
@@ -205,8 +273,18 @@ local function SetVisibility(self)
-- Force disable modules for people who aren't the appropriate class
if( module.moduleClass and module.moduleClass ~= playerClass ) then
enabled = nil
+ -- Force disable if they aren't the appropriate spec
+ elseif( module.moduleSpec and module.moduleSpec[playerSpec] ~= true ) then
+ enabled = nil
end
-
+
+ -- Restrict by level
+ if( module.moduleLevel and enabled and self.unitType == "player" ) then
+ if( UnitLevel("player") < module.moduleLevel ) then
+ enabled = nil
+ end
+ end
+
-- Module isn't enabled all the time, only in this zone so we need to force it to be enabled
if( not self.visibility[key] and enabled ) then
module:OnEnable(self)
@@ -234,7 +312,7 @@ local function checkVehicleData(self, elapsed)
self.dataAttempts = self.dataAttempts + 1
-- Took too long to get vehicle data, or they are no longer in a vehicle
- if( self.dataAttempts >= 6 or not UnitHasVehicleUI(self.unitOwner) ) then
+ if( self.dataAttempts >= 6 or not UnitHasVehicleUI(self.unitOwner) or not UnitHasVehiclePlayerFrameUI(self.unitOwner) ) then
self.timeElapsed = nil
self.dataAttempts = nil
self:SetScript("OnUpdate", nil)
@@ -258,10 +336,9 @@ end
-- Check if a unit entered a vehicle
function Units:CheckVehicleStatus(frame, event, unit)
if( event and frame.unitOwner ~= unit ) then return end
-
+
-- Not in a vehicle yet, and they entered one that has a UI or they were in a vehicle but the GUID changed (vehicle -> vehicle)
- if( ( not frame.inVehicle or frame.unitGUID ~= UnitGUID(frame.vehicleUnit) ) and UnitHasVehicleUI(frame.unitOwner) and not ShadowUF.db.profile.units[frame.unitType].disableVehicle ) then
-
+ if( ( not frame.inVehicle or frame.unitGUID ~= UnitGUID(frame.vehicleUnit) ) and UnitHasVehicleUI(frame.unitOwner) and UnitHasVehiclePlayerFrameUI(frame.unitOwner) and not ShadowUF.db.profile.units[frame.unitType].disableVehicle ) then
frame.inVehicle = true
frame.unit = frame.vehicleUnit
@@ -275,24 +352,12 @@ function Units:CheckVehicleStatus(frame, event, unit)
end
-- Was in a vehicle, no longer has a UI
- elseif( frame.inVehicle and ( not UnitHasVehicleUI(frame.unitOwner) or ShadowUF.db.profile.units[frame.unitType].disableVehicle ) ) then
+ elseif( frame.inVehicle and ( not UnitHasVehicleUI(frame.unitOwner) or not UnitHasVehiclePlayerFrameUI(frame.unitOwner) or ShadowUF.db.profile.units[frame.unitType].disableVehicle ) ) then
frame.inVehicle = false
frame.unit = frame.unitOwner
frame.unitGUID = UnitGUID(frame.unit)
frame:FullUpdate()
end
-
- -- Keep track of the actual players unit so we can quickly see what unit to scan
- --[[
- if( frame.unitOwner == "player" and ShadowUF.playerUnit ~= frame.unit ) then
- ShadowUF.playerUnit = frame.unit
-
- if( not ShadowUF.db.profile.hidden.buffs and ShadowUF.db.profile.units.player.enabled and BuffFrame:IsVisible() ) then
- PlayerFrame.unit = frame.unit
- BuffFrame_Update()
- end
- end
- ]]
end
-- Handles checking for GUID changes for doing a full update, this fixes frames sometimes showing the wrong unit when they change
@@ -323,7 +388,7 @@ function Units:CheckGroupedUnitStatus(frame)
if( frame.inVehicle and not UnitExists(frame.unit) and UnitExists(frame.unitOwner) ) then
frame.inVehicle = false
frame.unit = frame.unitOwner
- frame.unitGUID = guid
+ frame.unitGUID = UnitGUID(frame.unit)
frame:FullUpdate()
else
frame.unitGUID = UnitGUID(frame.unit)
@@ -331,33 +396,6 @@ function Units:CheckGroupedUnitStatus(frame)
end
end
-local function ShowMenu(self)
- if( UnitIsUnit(self.unit, "player") ) then
- ToggleDropDownMenu(1, nil, PlayerFrameDropDown, "cursor")
- elseif( self.unit == "pet" or self.unit == "vehicle" ) then
- ToggleDropDownMenu(1, nil, PetFrameDropDown, "cursor")
- elseif( self.unit == "target" ) then
- ToggleDropDownMenu(1, nil, TargetFrameDropDown, "cursor")
- elseif( self.unitType == "boss" ) then
- ToggleDropDownMenu(1, nil, _G["Boss" .. self.unitID .. "TargetFrameDropDown"], "cursor")
- elseif( self.unit == "focus" ) then
- ToggleDropDownMenu(1, nil, FocusFrameDropDown, "cursor")
- elseif( self.unitRealType == "party" ) then
- ToggleDropDownMenu(1, nil, _G["PartyMemberFrame" .. self.unitID .. "DropDown"], "cursor")
- elseif( self.unitRealType == "raid" ) then
- HideDropDownMenu(1)
-
- local menuFrame = FriendsDropDown
- menuFrame.displayMode = "MENU"
- menuFrame.initialize = RaidFrameDropDown_Initialize
- menuFrame.userData = self.unitID
- menuFrame.unit = self.unitOwner
- menuFrame.name = UnitName(self.unitOwner)
- menuFrame.id = self.unitID
- ToggleDropDownMenu(1, nil, menuFrame, "cursor")
- end
-end
-
-- More fun with sorting, due to sorting magic we have to check if we want to create stuff when the frame changes of partys too
local function createChildUnits(self)
if( not self.unitID ) then return end
@@ -381,6 +419,12 @@ local function updateChildUnits(...)
end
end
+local function createFakeUnitUpdateTimer(frame)
+ if( not frame.updateTimer ) then
+ frame.updateTimer = C_Timer.NewTicker(0.5, function() if( UnitExists(frame.unit) ) then frame:FullUpdate() end end)
+ end
+end
+
-- Attribute set, something changed
-- unit = Active unitid
-- unitID = Just the number from the unitid
@@ -390,23 +434,25 @@ end
-- vehicleUnit = Unit to use when the unitOwner is in a vehicle
OnAttributeChanged = function(self, name, unit)
if( name ~= "unit" or not unit or unit == self.unitOwner ) then return end
+
-- Nullify the previous entry if it had one
- if( self.unit and unitFrames[self.unit] == self ) then unitFrames[self.unit] = nil end
+ local configUnit = self.unitUnmapped or unit
+ if( self.configUnit and unitFrames[self.configUnit] == self ) then unitFrames[self.configUnit] = nil end
-- Setup identification data
self.unit = unit
self.unitID = tonumber(string.match(unit, "([0-9]+)"))
self.unitRealType = string.gsub(unit, "([0-9]+)", "")
- self.unitType = self.unitType or self.unitRealType
+ self.unitType = self.unitUnmapped and string.gsub(self.unitUnmapped, "([0-9]+)", "") or self.unitType or self.unitRealType
self.unitOwner = unit
self.vehicleUnit = self.unitOwner == "player" and "vehicle" or self.unitRealType == "party" and "partypet" .. self.unitID or self.unitRealType == "raid" and "raidpet" .. self.unitID or nil
self.inVehicle = nil
-
+
-- Split everything into two maps, this is the simple parentUnit -> frame map
-- This is for things like finding a party parent for party target/pet, the main map for doing full updates is
-- an indexed frame that is updated once and won't have unit conflicts.
if( self.unitRealType == self.unitType ) then
- unitFrames[unit] = self
+ unitFrames[configUnit] = self
end
frameList[self] = true
@@ -422,6 +468,7 @@ OnAttributeChanged = function(self, name, unit)
-- Don't need to recheck the unitType and force a full update, because a raid frame can never become
-- a party frame, or a player frame and so on
if( self.unitInitialized ) then
+ self:ReregisterUnitEvents()
self:FullUpdate()
return
end
@@ -429,8 +476,10 @@ OnAttributeChanged = function(self, name, unit)
self.unitInitialized = true
-- Add to Clique
- ClickCastFrames = ClickCastFrames or {}
- ClickCastFrames[self] = true
+ if( not self:GetAttribute("isHeaderDriven") ) then
+ ClickCastFrames = ClickCastFrames or {}
+ ClickCastFrames[self] = true
+ end
-- Handles switching the internal unit variable to that of their vehicle
if( self.unit == "player" or self.unitRealType == "party" or self.unitRealType == "raid" ) then
@@ -439,9 +488,13 @@ OnAttributeChanged = function(self, name, unit)
self:RegisterUpdateFunc(Units, "CheckVehicleStatus")
end
+ -- Phase change, do a full update on it
+ self:RegisterUnitEvent("UNIT_PHASE", self, "FullUpdate")
+
-- Pet changed, going from pet -> vehicle for one
if( self.unit == "pet" or self.unitType == "partypet" ) then
self.unitRealOwner = self.unit == "pet" and "player" or ShadowUF.partyUnits[self.unitID]
+ self:SetAttribute("unitRealOwner", self.unitRealOwner)
self:RegisterNormalEvent("UNIT_PET", Units, "CheckPetUnitUpdated")
if( self.unit == "pet" ) then
@@ -451,14 +504,14 @@ OnAttributeChanged = function(self, name, unit)
end
-- Logged out in a vehicle
- if( UnitHasVehicleUI(self.unitRealOwner) ) then
+ if( UnitHasVehicleUI(self.unitRealOwner) and UnitHasVehiclePlayerFrameUI(self.unitRealOwner) ) then
self:SetAttribute("unitIsVehicle", true)
end
-- Hide any pet that became a vehicle, we detect this by the owner being untargetable but they have a pet out
stateMonitor:WrapScript(self, "OnAttributeChanged", [[
if( name == "state-vehicleupdated" ) then
- self:SetAttribute("unitIsVehicle", value == "vehicle" and true or false)
+ self:SetAttribute("unitIsVehicle", UnitHasVehicleUI(self:GetAttribute("unitRealOwner")) and value == "vehicle" and true or false)
elseif( name == "disablevehicleswap" or name == "state-unitexists" or name == "unitisvehicle" ) then
-- Unit does not exist, OR unit is a vehicle and vehicle swap is not disabled, hide frame
if( not self:GetAttribute("state-unitexists") or ( self:GetAttribute("unitIsVehicle") and not self:GetAttribute("disableVehicleSwap") ) ) then
@@ -475,11 +528,13 @@ OnAttributeChanged = function(self, name, unit)
elseif( self.unit == "target" ) then
self.isUnitVolatile = true
self:RegisterNormalEvent("PLAYER_TARGET_CHANGED", Units, "CheckUnitStatus")
+ self:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "FullUpdate")
-- Automatically do a full update on focus change
elseif( self.unit == "focus" ) then
self.isUnitVolatile = true
self:RegisterNormalEvent("PLAYER_FOCUS_CHANGED", Units, "CheckUnitStatus")
+ self:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "FullUpdate")
elseif( self.unit == "player" ) then
self:SetAttribute("toggleForVehicle", true)
@@ -489,33 +544,50 @@ OnAttributeChanged = function(self, name, unit)
-- Update boss
elseif( self.unitType == "boss" ) then
- self.timeElapsed = 0
- self:SetScript("OnUpdate", TargetUnitUpdate)
self:RegisterNormalEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT", self, "FullUpdate")
-
+ self:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "FullUpdate")
+ self:RegisterUnitEvent("UNIT_NAME_UPDATE", Units, "CheckUnitStatus")
+
+ -- Update arena
+ elseif( self.unitType == "arena" ) then
+ self:RegisterUnitEvent("UNIT_NAME_UPDATE", self, "FullUpdate")
+ self:RegisterUnitEvent("UNIT_CONNECTION", self, "FullUpdate")
+
+ -- Update battleground
+ elseif( self.unitType == "battleground" ) then
+ self:RegisterUnitEvent("UNIT_NAME_UPDATE", Units, "CheckUnitStatus")
+
-- Check for a unit guid to do a full update
elseif( self.unitRealType == "raid" ) then
- self:RegisterNormalEvent("RAID_ROSTER_UPDATE", Units, "CheckGroupedUnitStatus")
+ self:RegisterNormalEvent("GROUP_ROSTER_UPDATE", Units, "CheckGroupedUnitStatus")
self:RegisterUnitEvent("UNIT_NAME_UPDATE", Units, "CheckUnitStatus")
+ self:RegisterUnitEvent("UNIT_CONNECTION", self, "FullUpdate")
-- Party members need to watch for changes
elseif( self.unitRealType == "party" ) then
- self:RegisterNormalEvent("PARTY_MEMBERS_CHANGED", Units, "CheckGroupedUnitStatus")
+ self:RegisterNormalEvent("GROUP_ROSTER_UPDATE", Units, "CheckGroupedUnitStatus")
+ self:RegisterNormalEvent("PARTY_MEMBER_ENABLE", Units, "CheckGroupedUnitStatus")
+ self:RegisterNormalEvent("PARTY_MEMBER_DISABLE", Units, "CheckGroupedUnitStatus")
self:RegisterUnitEvent("UNIT_NAME_UPDATE", Units, "CheckUnitStatus")
+ self:RegisterUnitEvent("UNIT_OTHER_PARTY_CHANGED", self, "FullUpdate")
+ self:RegisterUnitEvent("UNIT_CONNECTION", self, "FullUpdate")
-- *target units are not real units, thus they do not receive events and must be polled for data
elseif( ShadowUF.fakeUnits[self.unitRealType] ) then
- self.timeElapsed = 0
- self:SetScript("OnUpdate", TargetUnitUpdate)
+ createFakeUnitUpdateTimer(self)
-- Speeds up updating units when their owner changes target, if party1 changes target then party1target is force updated, if target changes target
-- then targettarget and targettargettarget are also force updated
if( self.unitRealType == "partytarget" ) then
self.unitRealOwner = ShadowUF.partyUnits[self.unitID]
+ elseif( self.unitRealType == "partytargettarget" ) then
+ self.unitRealOwner = ShadowUF.partyUnits[self.unitID] .. "target"
elseif( self.unitRealType == "raid" ) then
self.unitRealOwner = ShadowUF.raidUnits[self.unitID]
elseif( self.unitRealType == "arenatarget" ) then
self.unitRealOwner = ShadowUF.arenaUnits[self.unitID]
+ elseif( self.unitRealType == "arenatargettarget" ) then
+ self.unitRealOwner = ShadowUF.arenaUnits[self.unitID] .. "target"
elseif( self.unit == "focustarget" ) then
self.unitRealOwner = "focus"
self:RegisterNormalEvent("PLAYER_FOCUS_CHANGED", Units, "CheckUnitStatus")
@@ -526,56 +598,94 @@ OnAttributeChanged = function(self, name, unit)
self:RegisterNormalEvent("UNIT_TARGET", Units, "CheckPetUnitUpdated")
end
-
- self.menu = ShowMenu
+
self:SetVisibility()
Units:CheckUnitStatus(self)
end
Units.OnAttributeChanged = OnAttributeChanged
--- Header unit initialized
-local function initializeUnit(self)
- local unitType = self:GetParent().unitType
- local config = ShadowUF.db.profile.units[unitType]
-
- self.ignoreAnchor = true
- self.unitType = unitType
- self:SetAttribute("initial-height", config.height)
- self:SetAttribute("initial-width", config.width)
- self:SetAttribute("initial-scale", config.scale)
+local secureInitializeUnit = [[
+ local header = self:GetParent()
+
+ self:SetHeight(header:GetAttribute("style-height"))
+ self:SetWidth(header:GetAttribute("style-width"))
+ self:SetScale(header:GetAttribute("style-scale"))
+
self:SetAttribute("toggleForVehicle", true)
-
- Units:CreateUnit(self)
+
+ self:SetAttribute("*type1", "target")
+ self:SetAttribute("*type2", "togglemenu")
+ self:SetAttribute("type2", "togglemenu")
+
+ self:SetAttribute("isHeaderDriven", true)
+
+ -- initialize frame
+ header:CallMethod("initialConfigFunction", self:GetName())
+
+ -- Clique integration
+ local clickHeader = header:GetFrameRef("clickcast_header")
+ if( clickHeader ) then
+ clickHeader:SetAttribute("clickcast_button", self)
+ clickHeader:RunAttribute("clickcast_register")
+ end
+]]
+
+local unitButtonTemplate = ClickCastHeader and "ClickCastUnitTemplate,SUF_SecureUnitTemplate" or "SUF_SecureUnitTemplate"
+
+-- Header unit initialized
+local function initializeUnit(header, frameName)
+ local frame = _G[frameName]
+
+ frame.ignoreAnchor = true
+ frame.unitType = header.unitType
+
+ Units:CreateUnit(frame)
end
-- Show tooltip
local function OnEnter(self)
- if( not ShadowUF.db.profile.tooltipCombat or not InCombatLockdown() ) then
- UnitFrame_OnEnter(self)
+ if( self.OnEnter ) then
+ self:OnEnter()
end
end
--- Reset the fact that we clamped the dropdown to the screen to be safe
-DropDownList1:HookScript("OnHide", function(self)
- self:SetClampedToScreen(false)
-end)
+local function OnLeave(self)
+ if( self.OnLeave ) then
+ self:OnLeave()
+ end
+end
+
+local function SUF_OnEnter(self)
+ if( not ShadowUF.db.profile.tooltipCombat or not InCombatLockdown() ) then
+ if not GameTooltip:IsForbidden() then
+ UnitFrame_OnEnter(self)
+ end
+ end
+end
--- Reposition the dropdown
-local function PostClick(self)
- if( UIDROPDOWNMENU_OPEN_MENU and DropDownList1:IsShown() ) then
- DropDownList1:ClearAllPoints()
- DropDownList1:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, 0)
- DropDownList1:SetClampedToScreen(true)
+local function SUF_OnLeave(self)
+ if not GameTooltip:IsForbidden() then
+ UnitFrame_OnLeave(self)
end
end
-- Create the generic things that we want in every secure frame regardless if it's a button or a header
+local function ClassToken(self)
+ return (select(2, UnitClass(self.unit)))
+end
+
+local function ArenaClassToken(self)
+ local specID = GetArenaOpponentSpec(self.unitID)
+ return specID and select(6, GetSpecializationInfoByID(specID))
+end
+
function Units:CreateUnit(...)
local frame = select("#", ...) > 1 and CreateFrame(...) or select(1, ...)
frame.fullUpdates = {}
frame.registeredEvents = {}
frame.visibility = {}
+ frame.BlizzRegisterUnitEvent = frame.RegisterUnitEvent
frame.RegisterNormalEvent = RegisterNormalEvent
frame.RegisterUnitEvent = RegisterUnitEvent
frame.RegisterUpdateFunc = RegisterUpdateFunc
@@ -584,26 +694,35 @@ function Units:CreateUnit(...)
frame.SetRangeAlpha = SetRangeAlpha
frame.DisableRangeAlpha = DisableRangeAlpha
frame.UnregisterUpdateFunc = UnregisterUpdateFunc
+ frame.ReregisterUnitEvents = ReregisterUnitEvents
+ frame.SetBarColor = SetBarColor
+ frame.SetBlockColor = SetBlockColor
frame.FullUpdate = FullUpdate
frame.SetVisibility = SetVisibility
+ frame.UnitClassToken = ClassToken
frame.topFrameLevel = 5
-
+
-- Ensures that text is the absolute highest thing there is
frame.highFrame = CreateFrame("Frame", nil, frame)
frame.highFrame:SetFrameLevel(frame.topFrameLevel + 2)
frame.highFrame:SetAllPoints(frame)
- frame:SetScript("OnAttributeChanged", OnAttributeChanged)
+ frame:HookScript("OnAttributeChanged", OnAttributeChanged)
frame:SetScript("OnEvent", OnEvent)
- frame:SetScript("OnEnter", OnEnter)
- frame:SetScript("OnLeave", UnitFrame_OnLeave)
+ frame:HookScript("OnEnter", OnEnter)
+ frame:HookScript("OnLeave", OnLeave)
frame:SetScript("OnShow", OnShow)
frame:SetScript("OnHide", OnHide)
- frame:SetScript("PostClick", PostClick)
- frame:RegisterForClicks("AnyUp")
- frame:SetAttribute("*type1", "target")
- frame:SetAttribute("*type2", "menu")
+ frame.OnEnter = SUF_OnEnter
+ frame.OnLeave = SUF_OnLeave
+
+ frame:RegisterForClicks("AnyUp")
+ -- non-header frames don't set those, so we need to do it
+ if( not InCombatLockdown() and not frame:GetAttribute("isHeaderDriven") ) then
+ frame:SetAttribute("*type1", "target")
+ frame:SetAttribute("*type2", "togglemenu")
+ end
return frame
end
@@ -623,8 +742,8 @@ function Units:ReloadHeader(type)
elseif( headerFrames[type] ) then
self:SetHeaderAttributes(headerFrames[type], type)
- ShadowUF:FireModuleEvent("OnLayoutReload", type)
ShadowUF.Layout:AnchorFrame(UIParent, headerFrames[type], ShadowUF.db.profile.positions[type])
+ ShadowUF:FireModuleEvent("OnLayoutReload", type)
end
end
@@ -688,7 +807,7 @@ function Units:SetHeaderAttributes(frame, type)
local lastHeader = frame
for id=1, 8 do
local childHeader = headerFrames["raid" .. id]
- if( childHeader and childHeader:IsVisible() ) then
+ if( childHeader ) then
childHeader:SetAttribute("showRaid", ShadowUF.db.profile.locked and true)
childHeader:SetAttribute("minWidth", config.width * widthMod)
@@ -705,7 +824,7 @@ function Units:SetHeaderAttributes(frame, type)
childHeader:SetAttribute("yOffset", frame:GetAttribute("yOffset"))
childHeader:ClearAllPoints()
- if( id % config.groupsPerRow == 1 ) then
+ if( (id - 1) % config.groupsPerRow == 0 ) then
local x = config.groupSpacing * xColMod
local y = config.groupSpacing * yColMod
@@ -725,6 +844,11 @@ function Units:SetHeaderAttributes(frame, type)
lastHeader = childHeader
end
+
+ -- There appears to be a bug where if you reloadui with a split raid frames the positions get messed up
+ -- if we force a repositioning through startingIndex it's fixed thought.
+ childHeader:SetAttribute("startingIndex", 10000)
+ childHeader:SetAttribute("startingIndex", 1)
end
end
@@ -751,18 +875,25 @@ function Units:SetHeaderAttributes(frame, type)
frame:SetAttribute("columnSpacing", config.columnSpacing)
frame:SetAttribute("columnAnchorPoint", config.attribAnchorPoint)
frame:SetAttribute("groupFilter", filter or "1,2,3,4,5,6,7,8")
-
+ frame:SetAttribute("roleFilter", config.roleFilter)
+
if( config.groupBy == "CLASS" ) then
- frame:SetAttribute("groupingOrder", "DEATHKNIGHT,DRUID,HUNTER,MAGE,PALADIN,PRIEST,ROGUE,SHAMAN,WARLOCK,WARRIOR")
+ frame:SetAttribute("groupingOrder", "DEATHKNIGHT,DEMONHUNTER,DRUID,HUNTER,MAGE,PALADIN,PRIEST,ROGUE,SHAMAN,WARLOCK,WARRIOR,MONK")
frame:SetAttribute("groupBy", "CLASS")
+ elseif( config.groupBy == "ASSIGNEDROLE" ) then
+ frame:SetAttribute("groupingOrder", "TANK,HEALER,DAMAGER,NONE")
+ frame:SetAttribute("groupBy", "ASSIGNEDROLE")
else
frame:SetAttribute("groupingOrder", "1,2,3,4,5,6,7,8")
frame:SetAttribute("groupBy", "GROUP")
end
-
+
-- Need to position the fake units
- elseif( type == "boss" or type == "arena" ) then
- frame:SetWidth(config.width)
+ elseif( type == "boss" or type == "arena" or type == "battleground" ) then
+ frame:SetAttribute("attribPoint", config.attribPoint)
+ frame:SetAttribute("baseOffset", config.offset)
+ frame:SetAttribute("childChanged", 1)
+
self:PositionHeaderChildren(frame)
-- Update party frames to not show anyone if they should be in raids
@@ -771,16 +902,43 @@ function Units:SetHeaderAttributes(frame, type)
frame:SetAttribute("unitsPerColumn", config.unitsPerColumn)
frame:SetAttribute("columnSpacing", config.columnSpacing)
frame:SetAttribute("columnAnchorPoint", config.attribAnchorPoint)
+
+ self:CheckGroupVisibility()
+ if( stateMonitor.party ) then
+ stateMonitor.party:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.party.hideSemiRaid)
+ stateMonitor.party:SetAttribute("hideAnyRaid", ShadowUF.db.profile.units.party.hideAnyRaid)
+ end
end
- -- Update the raid frames to if they should be showing raid or party
- if( type == "party" or type == "raid" ) then
+ if( type == "raid" ) then
self:CheckGroupVisibility()
-
- -- Need to update our flags on the state monitor so it knows what to do
- stateMonitor:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.party.hideSemiRaid)
- stateMonitor:SetAttribute("hideAnyRaid", ShadowUF.db.profile.units.party.hideAnyRaid)
+
+ for id, monitor in pairs(stateMonitor.raids) do
+ monitor:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.raid.hideSemiRaid)
+ end
end
+
+ if( not InCombatLockdown() and headerUnits[type] and frame.shouldReset ) then
+ -- Children no longer have ClearAllPoints() called on them before they are repositioned
+ -- this tries to stop it from bugging out by clearing it then forcing it to reposition everything
+ local name = frame:GetName() .. "UnitButton"
+ local index = 1
+ local child = _G[name .. index]
+ while( child ) do
+ child:ClearAllPoints()
+
+ index = index + 1
+ child = _G[name .. index]
+ end
+
+ -- Hiding and reshowing the header forces an update
+ if( frame:IsShown() ) then
+ frame:Hide()
+ frame:Show()
+ end
+ end
+
+ frame.shouldReset = true
end
-- Load a single unit such as player, target, pet, etc
@@ -791,37 +949,83 @@ function Units:LoadUnit(unit)
return
end
- local frame = self:CreateUnit("Button", "SUFUnit" .. unit, UIParent, "SecureUnitButtonTemplate")
+ local frame = self:CreateUnit("Button", "SUFUnit" .. unit, petBattleFrame, "SecureUnitButtonTemplate")
frame:SetAttribute("unit", unit)
frame.hasStateWatch = unit == "pet"
- -- Annd lets get this going
+ -- And lets get this going
RegisterUnitWatch(frame, frame.hasStateWatch)
end
+local function setupRaidStateMonitor(id, headerFrame)
+ if( stateMonitor.raids[id] ) then return end
+
+ stateMonitor.raids[id] = CreateFrame("Frame", nil, nil, "SecureHandlerBaseTemplate")
+ stateMonitor.raids[id]:SetAttribute("raidDisabled", nil)
+ stateMonitor.raids[id]:SetFrameRef("raidHeader", headerFrame)
+ stateMonitor.raids[id]:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.raid.hideSemiRaid)
+ stateMonitor.raids[id]:WrapScript(stateMonitor.raids[id], "OnAttributeChanged", [[
+ if( name ~= "state-raidmonitor" and name ~= "raiddisabled" and name ~= "hidesemiraid" ) then
+ return
+ end
+
+ local header = self:GetFrameRef("raidHeader")
+ if( self:GetAttribute("raidDisabled") ) then
+ if( header:IsVisible() ) then header:Hide() end
+ return
+ end
+
+ if( self:GetAttribute("hideSemiRaid") and self:GetAttribute("state-raidmonitor") ~= "raid6" ) then
+ header:Hide()
+ else
+ header:Show()
+ end
+ ]])
+
+ RegisterStateDriver(stateMonitor.raids[id], "raidmonitor", "[target=raid6, exists] raid6; none")
+end
+
function Units:LoadSplitGroupHeader(type)
if( headerFrames.raid ) then headerFrames.raid:Hide() end
headerFrames.raidParent = nil
+ for id, monitor in pairs(stateMonitor.raids) do
+ monitor:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.raid.hideSemiRaid)
+ monitor:SetAttribute("raidDisabled", id == -1 and true or nil)
+ monitor:SetAttribute("recheck", time())
+ end
+
+ local config = ShadowUF.db.profile.units[type]
for id, enabled in pairs(ShadowUF.db.profile.units[type].filters) do
local frame = headerFrames["raid" .. id]
if( enabled ) then
if( not frame ) then
- frame = CreateFrame("Frame", "SUFHeader" .. type .. id, UIParent, "SecureGroupHeaderTemplate")
- frame:SetAttribute("template", "SecureUnitButtonTemplate")
+ frame = CreateFrame("Frame", "SUFHeader" .. type .. id, petBattleFrame, "SecureGroupHeaderTemplate")
+ frame:SetAttribute("template", unitButtonTemplate)
frame:SetAttribute("initial-unitWatch", true)
frame:SetAttribute("showRaid", true)
frame:SetAttribute("groupFilter", id)
- frame:UnregisterEvent("UNIT_NAME_UPDATE")
+ frame:SetAttribute("initialConfigFunction", secureInitializeUnit)
frame.initialConfigFunction = initializeUnit
frame.isHeaderFrame = true
frame.unitType = type
+ frame.unitMappedType = type
frame.splitParent = type
frame.groupID = id
--frame:SetBackdrop({bgFile = "Interface\\ChatFrame\\ChatFrameBackground", edgeFile = "Interface\\ChatFrame\\ChatFrameBackground", edgeSize = 1})
--frame:SetBackdropBorderColor(1, 0, 0, 1)
--frame:SetBackdropColor(0, 0, 0, 0)
+ frame:SetAttribute("style-height", config.height)
+ frame:SetAttribute("style-width", config.width)
+ frame:SetAttribute("style-scale", config.scale)
+
+ if( ClickCastHeader ) then
+ -- the OnLoad adds the functions like SetFrameRef to the header
+ SecureHandler_OnLoad(frame)
+ frame:SetFrameRef("clickcast_header", ClickCastHeader)
+ end
+
headerFrames["raid" .. id] = frame
end
@@ -830,6 +1034,8 @@ function Units:LoadSplitGroupHeader(type)
if( not headerFrames.raidParent or headerFrames.raidParent.groupID > id ) then
headerFrames.raidParent = frame
end
+
+ setupRaidStateMonitor(id, frame)
elseif( frame ) then
frame:Hide()
@@ -844,47 +1050,69 @@ end
-- Load a header unit, party or raid
function Units:LoadGroupHeader(type)
- -- Any frames that were split out in this group need to be hidden
- for _, headerFrame in pairs(headerFrames) do
- if( headerFrame.splitParent == type ) then
- headerFrame:Hide()
- end
- end
-
-- Already created, so just reshow and we out
if( headerFrames[type] ) then
headerFrames[type]:Show()
-
- if( type == "party" ) then
- stateMonitor:SetAttribute("partyDisabled", nil)
+
+ if( type == "party" and stateMonitor.party ) then
+ stateMonitor.party:SetAttribute("partyDisabled", nil)
end
+ if( type == "raid" ) then
+ for id, monitor in pairs(stateMonitor.raids) do
+ monitor:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.raid.hideSemiRaid)
+ monitor:SetAttribute("raidDisabled", id >= 0 and true or nil)
+ end
+ end
+
if( type == "party" or type == "raid" ) then
self:CheckGroupVisibility()
end
return
end
-
- local headerFrame = CreateFrame("Frame", "SUFHeader" .. type, UIParent, type == "raidpet" and "SecureGroupPetHeaderTemplate" or "SecureGroupHeaderTemplate")
+
+ local headerFrame = CreateFrame("Frame", "SUFHeader" .. type, petBattleFrame, type == "raidpet" and "SecureGroupPetHeaderTemplate" or "SecureGroupHeaderTemplate")
headerFrames[type] = headerFrame
self:SetHeaderAttributes(headerFrame, type)
-
- headerFrame:SetAttribute("template", "SecureUnitButtonTemplate")
+
+ headerFrame:SetAttribute("template", unitButtonTemplate)
headerFrame:SetAttribute("initial-unitWatch", true)
+ headerFrame:SetAttribute("initialConfigFunction", secureInitializeUnit)
+
headerFrame.initialConfigFunction = initializeUnit
headerFrame.isHeaderFrame = true
headerFrame.unitType = type
- headerFrame:UnregisterEvent("UNIT_NAME_UPDATE")
-
+ headerFrame.unitMappedType = type
+
+ -- For securely managely the display
+ local config = ShadowUF.db.profile.units[type]
+ headerFrame:SetAttribute("style-height", config.height)
+ headerFrame:SetAttribute("style-width", config.width)
+ headerFrame:SetAttribute("style-scale", config.scale)
+
+ if( type == "raidpet" ) then
+ headerFrame:SetAttribute("filterOnPet", true)
+ end
+
+ if( ClickCastHeader ) then
+ -- the OnLoad adds the functions like SetFrameRef to the header
+ SecureHandler_OnLoad(headerFrame)
+ headerFrame:SetFrameRef("clickcast_header", ClickCastHeader)
+ end
+
ShadowUF.Layout:AnchorFrame(UIParent, headerFrame, ShadowUF.db.profile.positions[type])
-- We have to do party hiding based off raid as a state driver so that we can smoothly hide the party frames based off of combat and such
-- technically this isn't the cleanest solution because party frames will still have unit watches active
-- but this isn't as big of a deal, because SUF automatically will unregister the OnEvent for party frames while hidden
if( type == "party" ) then
- stateMonitor:SetFrameRef("partyHeader", headerFrame)
- stateMonitor:WrapScript(stateMonitor, "OnAttributeChanged", [[
+ stateMonitor.party = CreateFrame("Frame", nil, nil, "SecureHandlerBaseTemplate")
+ stateMonitor.party:SetAttribute("partyDisabled", nil)
+ stateMonitor.party:SetFrameRef("partyHeader", headerFrame)
+ stateMonitor.party:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.party.hideSemiRaid)
+ stateMonitor.party:SetAttribute("hideAnyRaid", ShadowUF.db.profile.units.party.hideAnyRaid)
+ stateMonitor.party:WrapScript(stateMonitor.party, "OnAttributeChanged", [[
if( name ~= "state-raidmonitor" and name ~= "partydisabled" and name ~= "hideanyraid" and name ~= "hidesemiraid" ) then return end
if( self:GetAttribute("partyDisabled") ) then return end
@@ -896,26 +1124,48 @@ function Units:LoadGroupHeader(type)
self:GetFrameRef("partyHeader"):Show()
end
]])
- RegisterStateDriver(stateMonitor, "raidmonitor", "[target=raid6, exists] raid6; [target=raid1, exists] raid1; none")
+ RegisterStateDriver(stateMonitor.party, "raidmonitor", "[target=raid6, exists] raid6; [target=raid1, exists] raid1; none")
+
+ elseif( type == "raid" ) then
+ setupRaidStateMonitor(-1, headerFrame)
else
headerFrame:Show()
end
+
+ -- Any frames that were split out in this group need to be hidden
+ if( headerFrames.raidParent ) then
+ for _, headerFrame in pairs(headerFrames) do
+ if( headerFrame.splitParent == type ) then
+ headerFrame:Hide()
+ end
+ end
+ end
end
-- Fake headers that are supposed to act like headers to the users, but are really not
function Units:LoadZoneHeader(type)
if( headerFrames[type] ) then
headerFrames[type]:Show()
+ for _, child in pairs(headerFrames[type].children) do
+ RegisterUnitWatch(child, child.hasStateWatch)
+ end
+
+ if( type == "arena" ) then
+ self:InitializeArena()
+ end
return
end
- local headerFrame = CreateFrame("Frame", "SUFHeader" .. type, UIParent)
+ local headerFrame = CreateFrame("Frame", "SUFHeader" .. type, petBattleFrame, "SecureHandlerBaseTemplate")
headerFrame.isHeaderFrame = true
headerFrame.unitType = type
+ headerFrame.unitMappedType = remappedUnits[type] or type
headerFrame:SetClampedToScreen(true)
headerFrame:SetMovable(true)
headerFrame:SetHeight(0.1)
+ headerFrame:SetAttribute("totalChildren", #(ShadowUF[type .. "Units"]))
headerFrame.children = {}
+
headerFrames[type] = headerFrame
if( type == "arena" ) then
@@ -929,17 +1179,22 @@ function Units:LoadZoneHeader(type)
for id, unit in pairs(ShadowUF[type .. "Units"]) do
local frame = self:CreateUnit("Button", "SUFHeader" .. type .. "UnitButton" .. id, headerFrame, "SecureUnitButtonTemplate")
frame.ignoreAnchor = true
+ frame.hasStateWatch = true
+ frame.unitUnmapped = type .. id
frame:SetAttribute("unit", unit)
+ frame:SetAttribute("unitID", id)
frame:Hide()
+
+ -- Override with our arena specific concerns
+ frame.UnitClassToken = ArenaClassToken
+ frame:SetScript("OnShow", OnShowForced)
headerFrame.children[id] = frame
-
+ headerFrame:SetFrameRef("child" .. id, frame)
+
-- Arena frames are only allowed to be shown not hidden from the unit existing, or else when a Rogue
-- stealths the frame will hide which looks bad. Instead force it to stay open and it has to be manually hidden when the player leaves an arena.
if( type == "arena" ) then
- frame:SetAttribute("unitID", id)
- frame.hasStateWatch = true
-
stateMonitor:WrapScript(frame, "OnAttributeChanged", [[
if( name == "state-unitexists" ) then
local parent = self:GetParent()
@@ -955,17 +1210,57 @@ function Units:LoadZoneHeader(type)
end
end
]])
-
- RegisterUnitWatch(frame, frame.hasStateWatch)
else
- RegisterUnitWatch(frame)
+ stateMonitor:WrapScript(frame, "OnAttributeChanged", [[
+ if( name == "state-unitexists" ) then
+ if( value ) then
+ self:Show()
+ else
+ self:Hide()
+ end
+
+ local parent = self:GetParent()
+ parent:SetAttribute("childChanged", self:GetAttribute("unitID"))
+ end
+ ]])
end
+
+ RegisterUnitWatch(frame, frame.hasStateWatch)
end
-
+
+ -- Dynamic height/width adjustment
+ stateMonitor:WrapScript(headerFrame, "OnAttributeChanged", [[
+ if( name ~= "childchanged" ) then return end
+
+ local visible = 0
+ for i=1, self:GetAttribute("totalChildren") do
+ if( self:GetFrameRef("child" .. i):IsShown() ) then
+ visible = visible + 1
+ end
+ end
+
+ if( visible == 0 ) then
+ self:Hide()
+ return
+ end
+
+ local child = self:GetFrameRef("child1")
+ local xMod = math.abs(self:GetAttribute("xMod"))
+ local yMod = math.abs(self:GetAttribute("yMod"))
+ local offset = self:GetAttribute("baseOffset")
+
+ self:SetWidth(xMod * ((child:GetWidth() * (visible - 1)) + (offset * (visible - 1))) + child:GetWidth())
+ self:SetHeight(yMod * ((child:GetHeight() * (visible - 1)) + (offset * (visible - 1))) + child:GetHeight())
+ self:Show()
+ ]])
+
self:SetHeaderAttributes(headerFrame, type)
-
ShadowUF.Layout:AnchorFrame(UIParent, headerFrame, ShadowUF.db.profile.positions[type])
+
+ if( type == "arena" ) then
+ self:InitializeArena()
+ end
end
-- Load a unit that is a child of another unit (party pet/party target)
@@ -988,6 +1283,15 @@ function Units:LoadChildUnit(parent, type, id)
parent.hasChildren = true
+ local suffix
+ if( string.match(type, "pet$") ) then
+ suffix = "pet"
+ elseif( string.match(type, "targettarget$") ) then
+ suffix = "targettarget"
+ else
+ suffix = "target"
+ end
+
-- Now we can create the actual frame
local frame = self:CreateUnit("Button", "SUFChild" .. type .. string.match(parent:GetName(), "(%d+)"), parent, "SecureUnitButtonTemplate")
frame.unitType = type
@@ -996,7 +1300,7 @@ function Units:LoadChildUnit(parent, type, id)
frame.hasStateWatch = type == "partypet"
frame:SetFrameStrata("LOW")
frame:SetAttribute("useparent-unit", true)
- frame:SetAttribute("unitsuffix", string.match(type, "pet$") and "pet" or "target")
+ frame:SetAttribute("unitsuffix", suffix)
OnAttributeChanged(frame, "unit", SecureButton_GetModifiedUnit(frame))
frameList[frame] = true
@@ -1010,14 +1314,14 @@ function Units:InitializeFrame(type)
self:LoadSplitGroupHeader(type)
elseif( type == "party" or type == "raid" or type == "maintank" or type == "mainassist" or type == "raidpet" ) then
self:LoadGroupHeader(type)
- elseif( self.zoneUnits[type] ) then
- self:LoadZoneHeader(type)
elseif( self.childUnits[type] ) then
for frame in pairs(frameList) do
if( frame.unitType == self.childUnits[type] and ShadowUF.db.profile.units[frame.unitType] and frame.unitID ) then
self:LoadChildUnit(frame, type, frame.unitID)
end
end
+ elseif( self.zoneUnits[type] ) then
+ self:LoadZoneHeader(type)
else
self:LoadUnit(type)
end
@@ -1025,14 +1329,20 @@ end
-- Uninitialize units
function Units:UninitializeFrame(type)
- -- Disables showing party in raid automatically if raid frames are disabled
- if( type == "party" ) then
- stateMonitor:SetAttribute("partyDisabled", true)
- end
if( type == "party" or type == "raid" ) then
self:CheckGroupVisibility()
end
+ -- Disables showing party in raid automatically if raid frames are disabled
+ if( type == "party" and stateMonitor.party ) then
+ stateMonitor.party:SetAttribute("partyDisabled", true)
+ end
+ if( type == "raid" ) then
+ for _, monitor in pairs(stateMonitor.raids) do
+ monitor:SetAttribute("raidDisabled", true)
+ end
+ end
+
-- Disable the parent and the children will follow
if( ShadowUF.db.profile.units[type].frameSplit ) then
for _, headerFrame in pairs(headerFrames) do
@@ -1045,6 +1355,11 @@ function Units:UninitializeFrame(type)
if( headerFrames[type].children ) then
for _, frame in pairs(headerFrames[type].children) do
+ if( self.zoneUnits[type] ) then
+ UnregisterUnitWatch(frame)
+ frame:SetAttribute("state-unitexists", false)
+ end
+
frame:Hide()
end
end
@@ -1053,6 +1368,7 @@ function Units:UninitializeFrame(type)
for frame in pairs(frameList) do
if( frame.unitType == type ) then
UnregisterUnitWatch(frame)
+ frame:SetAttribute("state-unitexits", false)
frame:Hide()
end
end
@@ -1107,6 +1423,21 @@ function Units:CreateBar(parent)
return bar
end
+-- Handle showing for the arena prep frames
+function Units:InitializeArena()
+ if( not headerFrames.arena or InCombatLockdown() ) then return end
+
+ local specs = GetNumArenaOpponentSpecs()
+ if( not specs or specs == 0 ) then return end
+
+ for i=1, specs do
+ local frame = headerFrames.arena.children[i]
+ frame:SetAttribute("state-unitexists", true)
+ frame:Show()
+ frame:FullUpdate()
+ end
+end
+
-- Deal with zone changes for enabling modules
local instanceType, queueZoneCheck
function Units:CheckPlayerZone(force)
@@ -1116,7 +1447,9 @@ function Units:CheckPlayerZone(force)
end
-- CanHearthAndResurrectFromArea() returns true for world pvp areas, according to BattlefieldFrame.lua
- local instance = CanHearthAndResurrectFromArea() and "pvp" or select(2, IsInInstance())
+ local instance = CanHearthAndResurrectFromArea() and "pvp" or select(2, IsInInstance()) or "none"
+ if( instance == "scenario" ) then instance = "party" end
+
if( instance == instanceType and not force ) then return end
instanceType = instance
@@ -1137,9 +1470,39 @@ function Units:CheckPlayerZone(force)
end
end
+-- Handle figuring out what auras players can cure
+local curableSpells = {
+ ["DRUID"] = {[88423] = {"Magic", "Curse", "Poison"}, [2782] = {"Curse", "Poison"}},
+ ["PRIEST"] = {[527] = {"Magic", "Disease"}, [32375] = {"Magic"}},
+ ["PALADIN"] = {[4987] = {"Poison", "Disease", "Magic"}, [213644] = {"Poison", "Disease"}},
+ ["SHAMAN"] = {[77130] = {"Curse", "Magic"}, [51886] = {"Curse"}},
+ ["MONK"] = {[115450] = {"Poison", "Disease", "Magic"}, [218164] = {"Poison", "Disease"}},
+}
+
+curableSpells = curableSpells[select(2, UnitClass("player"))]
+
+local function checkCurableSpells()
+ if( not curableSpells ) then return end
+
+ table.wipe(Units.canCure)
+
+ for spellID, cures in pairs(curableSpells) do
+ if( IsPlayerSpell(spellID) ) then
+ for _, auraType in pairs(cures) do
+ Units.canCure[auraType] = true
+ end
+ end
+ end
+end
+
local centralFrame = CreateFrame("Frame")
centralFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
centralFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
+centralFrame:RegisterEvent("PLAYER_LOGIN")
+centralFrame:RegisterEvent("PLAYER_LEVEL_UP")
+centralFrame:RegisterEvent("CINEMATIC_STOP")
+centralFrame:RegisterEvent("ARENA_PREP_OPPONENT_SPECIALIZATIONS")
+centralFrame:RegisterEvent("ARENA_OPPONENT_UPDATE")
centralFrame:SetScript("OnEvent", function(self, event, unit)
-- Check if the player changed zone types and we need to change module status, while they are dead
-- we won't change their zone type as releasing from an instance will change the zone type without them
@@ -1150,12 +1513,41 @@ centralFrame:SetScript("OnEvent", function(self, event, unit)
else
self:UnregisterEvent("PLAYER_UNGHOST")
Units:CheckPlayerZone()
- end
-
+ end
+
+ -- Force update frames
+ elseif( event == "ARENA_PREP_OPPONENT_SPECIALIZATIONS" or event == "ARENA_OPPONENT_UPDATE" ) then
+ Units:InitializeArena()
+
-- They're alive again so they "officially" changed zone types now
elseif( event == "PLAYER_UNGHOST" ) then
Units:CheckPlayerZone()
-
+
+ -- Monitor level up
+ elseif( event == "PLAYER_LEVEL_UP" or event == "CINEMATIC_STOP" ) then
+ if( unitFrames.player ) then
+ unitFrames.player:SetVisibility()
+ unitFrames.player:FullUpdate()
+ end
+
+ -- Monitor talent changes for curable changes
+ elseif( event == "PLAYER_SPECIALIZATION_CHANGED" ) then
+ checkCurableSpells()
+
+ for frame in pairs(ShadowUF.Units.frameList) do
+ if( frame.unit ) then
+ frame:SetVisibility()
+
+ if( frame:IsVisible() ) then
+ frame:FullUpdate()
+ end
+ end
+ end
+
+ elseif( event == "PLAYER_LOGIN" ) then
+ checkCurableSpells()
+ self:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
+
-- This is slightly hackish, but it suits the purpose just fine for somthing thats rarely called.
elseif( event == "PLAYER_REGEN_ENABLED" ) then
-- Now do all of the creation for child wrapping
@@ -1170,4 +1562,4 @@ centralFrame:SetScript("OnEvent", function(self, event, unit)
queueZoneCheck = nil
end
end
-end)
\ No newline at end of file
+end)
diff --git a/modules/xp.lua b/modules/xp.lua
index 6f2c28fd8..cbd062bbf 100755
--- a/modules/xp.lua
+++ b/modules/xp.lua
@@ -98,8 +98,8 @@ function XP:UpdateRep(frame)
local color = FACTION_BAR_COLORS[reaction]
frame.xpBar.rep:SetMinMaxValues(0, max)
- frame.xpBar.rep:SetValue(reaction == 8 and max or current)
- frame.xpBar.rep.tooltip = string.format(L["%s (%s): %s/%s (%.2f%% done)"], name, GetText("FACTION_STANDING_LABEL" .. reaction, UnitSex("player")), formatNumber(current), formatNumber(max), reaction == 8 and 100 or (current / max) * 100)
+ frame.xpBar.rep:SetValue(current)
+ frame.xpBar.rep.tooltip = string.format(L["%s (%s): %s/%s (%.2f%% done)"], name, GetText("FACTION_STANDING_LABEL" .. reaction, UnitSex("player")), formatNumber(current), formatNumber(max), (max > 0 and current / max or 0) * 100)
frame.xpBar.rep:SetStatusBarColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
frame.xpBar.rep.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
frame.xpBar.rep:Show()
@@ -128,10 +128,10 @@ function XP:UpdateXP(frame)
frame.xpBar.rested:SetMinMaxValues(min, max)
frame.xpBar.rested:SetValue(math.min(current + GetXPExhaustion(), max))
frame.xpBar.rested:Show()
- frame.xpBar.xp.tooltip = string.format(L["Level %s - %s: %s/%s (%.2f%% done), %s rested."], UnitLevel(frame.unitOwner), UnitLevel(frame.unitOwner) + 1, formatNumber(current), formatNumber(max), (current / max) * 100, formatNumber(GetXPExhaustion()))
+ frame.xpBar.xp.tooltip = string.format(L["Level %s - %s: %s/%s (%.2f%% done), %s rested."], UnitLevel(frame.unitOwner), UnitLevel(frame.unitOwner) + 1, formatNumber(current), formatNumber(max), (max > 0 and current / max or 0) * 100, formatNumber(GetXPExhaustion()))
else
frame.xpBar.rested:Hide()
- frame.xpBar.xp.tooltip = string.format(L["Level %s - %s: %s/%s (%.2f%% done)"], UnitLevel(frame.unitOwner), UnitLevel(frame.unitOwner) + 1, formatNumber(current), formatNumber(max), (current / max) * 100)
+ frame.xpBar.xp.tooltip = string.format(L["Level %s - %s: %s/%s (%.2f%% done)"], UnitLevel(frame.unitOwner), UnitLevel(frame.unitOwner) + 1, formatNumber(current), formatNumber(max), (max > 0 and current / max or 0) * 100)
end
end
diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc
index adaff5605..dac346cee 100755
--- a/options/ShadowedUF_Options.toc
+++ b/options/ShadowedUF_Options.toc
@@ -1,4 +1,4 @@
-## Interface: 30300
+## Interface: 80000
## Title: Shadowed UF (Options)
## Notes: Configuration for Shadowed Unit Frames.
## Author: Shadowed
@@ -12,4 +12,4 @@ libs\AceGUI-3.0-SharedMediaWidgets\widget.xml
libs\AceConfig-3.0\AceConfig-3.0.xml
#@end-no-lib-strip@
-config.lua
\ No newline at end of file
+config.lua
diff --git a/options/config.lua b/options/config.lua
old mode 100644
new mode 100755
index 687b5ace3..e4858cc27
--- a/options/config.lua
+++ b/options/config.lua
@@ -12,19 +12,33 @@ ShadowUF.Config = Config
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
I want to get done with first.
+
+ -- dated 2009
+
+ In reality, this will never be cleaned up because jesus christ, I am not refactoring 7,000 lines of configuration.
+
+ *** HERE BE DRAGONS ***
]]
local unitCategories = {
player = {"player", "pet"},
general = {"target", "targettarget", "targettargettarget", "focus", "focustarget", "pettarget"},
- party = {"party", "partypet", "partytarget"},
- raid = {"raid", "raidpet", "boss", "bosstarget", "maintank", "maintanktarget", "mainassist", "mainassisttarget"},
- arena = {"arena", "arenapet", "arenatarget"}}
+ party = {"party", "partypet", "partytarget", "partytargettarget", "party"},
+ raid = {"raid", "raidpet"},
+ raidmisc = {"maintank", "maintanktarget", "maintanktargettarget", "mainassist", "mainassisttarget", "mainassisttargettarget"},
+ boss = {"boss", "bosstarget", "bosstargettarget"},
+ arena = {"arena", "arenapet", "arenatarget", "arenatargettarget"},
+ battleground = {"battleground", "battlegroundpet", "battlegroundtarget", "battlegroundtargettarget"}
+}
local UNIT_DESC = {
["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."],
- ["mainassist"] = L["Main Assists's are set by the Blizzard Main Assist system or mods that use them such as oRA3."],
- ["maintank"] = L["Main Tank's are set by the Blizzard Main Tank system or mods that use them such as oRA3."],
+ ["mainassist"] = L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."],
+ ["maintank"] = L["Main Tank's are set through the Raid frames, or through selecting the Tank role."],
+ ["battleground"] = L["Currently used in battlegrounds for showing flag carriers."],
+ ["battlegroundpet"] = L["Current pet used by a battleground unit."],
+ ["battlegroundtarget"] = L["Current target of a battleground unit."],
+ ["battlegroundtargettarget"] = L["Current target of target of a battleground unit."]
}
local PAGE_DESC = {
@@ -36,17 +50,20 @@ local PAGE_DESC = {
["tags"] = L["Advanced tag management, allows you to add your own custom tags."],
["filter"] = L["Simple aura filtering by whitelists and blacklists."],
}
-local INDICATOR_NAMES = {["happiness"] = L["Happiness"], ["leader"] = L["Leader"], ["lfdRole"] = L["Dungeon 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"]}
-local AREA_NAMES = {["arena"] = L["Arenas"],["none"] = L["Everywhere else"], ["party"] = L["Party instances"], ["pvp"] = L["Battlegrounds"], ["raid"] = L["Raid instances"],}
-local INDICATOR_DESC = {["happiness"] = L["Indicator for your pet's happiness, only applies to Hunters."],
- ["leader"] = L["Crown indicator for group leaders."], ["lfdRole"] = L["Role the unit is playing in dungeons formed through the Looking For Dungeon system."],
+local 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"]}
+local AREA_NAMES = {["arena"] = L["Arenas"],["none"] = L["Everywhere else"], ["party"] = L["Party instances"], ["pvp"] = L["Battleground"], ["raid"] = L["Raid instances"]}
+local INDICATOR_DESC = {
+ ["leader"] = L["Crown indicator for group leader or assistants."], ["lfdRole"] = L["Role the unit is playing."],
["masterLoot"] = L["Bag indicator for master looters."], ["pvp"] = L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."],
- ["raidTarget"] = L["Raid target indicator."], ["ready"] = L["Ready status of group members."],
- ["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."]}
-local 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"],}
+ ["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."],
+ ["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."],
+ ["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."],
+ ["arenaSpec"] = L["Talent spec of your arena opponents."]
+}
+local 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"]}
local 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"]}
-local 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"] }
+local 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"]}
local unitOrder = {}
for order, unit in pairs(ShadowUF.unitList) do unitOrder[unit] = order end
@@ -182,13 +199,13 @@ local function get(info)
end
local function setColor(info, r, g, b, a)
- local color = get(info)
+ local color = get(info) or {}
color.r, color.g, color.b, color.a = r, g, b, a
set(info, color)
end
local function getColor(info)
- local color = get(info)
+ local color = get(info) or {}
return color.r, color.g, color.b, color.a
end
@@ -212,23 +229,14 @@ local function setVariable(unit, moduleKey, moduleSubKey, key, value)
end
local function specialRestricted(unit, moduleKey, moduleSubKey, key)
- if( ShadowUF.fakeUnits[unit] and ( key == "colorAggro" or key == "aggro" or moduleKey == "incHeal" or moduleKey == "castBar" ) ) then
+ 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
return true
elseif( moduleKey == "healthBar" and unit == "player" and key == "reaction" ) then
return true
end
end
-local function setUnit(info, value)
- local unit = info[2]
- -- auras, buffs, enabled / text, 1, text / portrait, enabled
- local moduleKey, moduleSubKey, key = string.split(".", info.arg)
- if( not moduleSubKey ) then key = moduleKey moduleKey = nil end
- if( moduleSubKey and not key ) then key = moduleSubKey moduleSubKey = nil end
- if( moduleSubKey == "$parent" ) then moduleSubKey = info[#(info) - 1] end
- if( moduleKey == "$parent" ) then moduleKey = info[#(info) - 1] end
- if( tonumber(moduleSubKey) ) then moduleSubKey = tonumber(moduleSubKey) end
-
+local function setDirectUnit(unit, moduleKey, moduleSubKey, key, value)
if( unit == "global" ) then
for unit in pairs(modifyUnits) do
if( not specialRestricted(unit, moduleKey, moduleSubKey, key) ) then
@@ -242,6 +250,21 @@ local function setUnit(info, value)
end
end
+local function setUnit(info, value)
+ local unit = info[2]
+ -- auras, buffs, enabled / text, 1, text / portrait, enabled
+ local moduleKey, moduleSubKey, key = string.split(".", info.arg)
+ if( not moduleSubKey ) then key = moduleKey moduleKey = nil end
+ if( moduleSubKey and not key ) then key = moduleSubKey moduleSubKey = nil end
+ if( moduleSubKey == "$parent" ) then moduleSubKey = info[#(info) - 1] end
+ if( moduleKey == "$parent" ) then moduleKey = info[#(info) - 1] end
+ if( moduleSubKey == "$parentparent" ) then moduleSubKey = info[#(info) - 2] end
+ if( moduleKey == "$parentparent" ) then moduleKey = info[#(info) - 2] end
+ if( tonumber(moduleSubKey) ) then moduleSubKey = tonumber(moduleSubKey) end
+
+ setDirectUnit(unit, moduleKey, moduleSubKey, key, value)
+end
+
local function getVariable(unit, moduleKey, moduleSubKey, key)
local configTbl = unit == "global" and globalConfig or ShadowUF.db.profile.units[unit]
if( moduleKey and moduleSubKey ) then
@@ -259,6 +282,8 @@ local function getUnit(info)
if( moduleSubKey and not key ) then key = moduleSubKey moduleSubKey = nil end
if( moduleSubKey == "$parent" ) then moduleSubKey = info[#(info) - 1] end
if( moduleKey == "$parent" ) then moduleKey = info[#(info) - 1] end
+ if( moduleSubKey == "$parentparent" ) then moduleSubKey = info[#(info) - 2] end
+ if( moduleKey == "$parentparent" ) then moduleKey = info[#(info) - 2] end
if( tonumber(moduleSubKey) ) then moduleSubKey = tonumber(moduleSubKey) end
return getVariable(info[2], moduleKey, moduleSubKey, key)
@@ -285,10 +310,10 @@ local function hideRestrictedOption(info)
local key = info[#(info)]
if( ShadowUF.modules[key] and ShadowUF.modules[key].moduleClass and ShadowUF.modules[key].moduleClass ~= playerClass ) then
return true
- elseif( key == "incHeal" and not ShadowUF.modules.incHeal ) then
+ 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
return true
-- Non-standard units do not support color by aggro or incoming heal
- elseif( key == "colorAggro" or key == "incHeal" or key == "aggro" ) then
+ elseif( key == "colorAggro" or key == "colorDispel" or key == "incHeal" or key == "incAbsorb" or key == "aggro" ) then
return string.match(unit, "%w+target" )
-- Fall back for indicators, no variable table so it shouldn't be shown
elseif( info[#(info) - 1] == "indicators" ) then
@@ -330,6 +355,44 @@ Config.hideBasicOption = hideBasicOption
--------------------
-- GENERAL CONFIGURATION
---------------------
+local function writeTable(tbl)
+ local data = ""
+ for key, value in pairs(tbl) do
+ local valueType = type(value)
+
+ -- Wrap the key in brackets if it's a number
+ if( type(key) == "number" ) then
+ key = string.format("[%s]", key)
+ -- Wrap the string with quotes if it has a space in it
+ elseif( string.match(key, "[%p%s%c]") or string.match(key, "^[0-9]+$") ) then
+ key = string.format("['%s']", string.gsub(key, "'", "\\'"))
+ end
+
+ -- foo = {bar = 5}
+ if( valueType == "table" ) then
+ data = string.format("%s%s=%s;", data, key, writeTable(value))
+ -- foo = true / foo = 5
+ elseif( valueType == "number" or valueType == "boolean" ) then
+ data = string.format("%s%s=%s;", data, key, tostring(value))
+ -- foo = "bar"
+ else
+ value = tostring(value)
+ if value and string.match(value, "[\n]") then
+ local token = ""
+ while string.find(value, "%["..token.."%[") or string.find(value, "%]"..token.."%]") do
+ token = token .. "="
+ end
+ value = string.format("[%s[%s]%s]", token, value, token)
+ else
+ value = string.format("%q", value)
+ end
+ data = string.format("%s%s=%s;", data, key, value)
+ end
+ end
+
+ return "{" .. data .. "}"
+end
+
local function loadGeneralOptions()
SML = SML or LibStub:GetLibrary("LibSharedMedia-3.0")
@@ -409,7 +472,16 @@ local function loadGeneralOptions()
if( not getVariable("player", "text", nil, id) ) then return true end
return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1]
end,
- disabled = function(info) return tonumber(info[#(info)]) <= 6 end,
+ disabled = function(info)
+ local id = tonumber(info[#(info)])
+ for _, unit in pairs(ShadowUF.unitList) do
+ if( ShadowUF.db.profile.units[unit].text[id] and ShadowUF.db.profile.units[unit].text[id].default ) then
+ return true
+ end
+ end
+
+ return false
+ end,
confirmText = L["Are you sure you want to delete this text? All settings for it will be deleted."],
confirm = true,
func = function(info)
@@ -430,47 +502,33 @@ local function loadGeneralOptions()
return true
end
-
+
local function setRange(info, spell)
ShadowUF.db.profile.range[info[#(info)] .. playerClass] = spell and spell ~= "" and spell or nil
ShadowUF.Layout:Reload()
end
-
- local function getRange(info, spell)
- local spell = ShadowUF.db.profile.range[info[#(info)] .. playerClass]
- return spell and spell ~= "" and spell or ShadowUF.modules.range[info[#(info)]][playerClass]
+
+ local function getRange(info)
+ return ShadowUF.db.profile.range[info[#(info)] .. playerClass]
end
-
- local textData = {}
-
- local function writeTable(tbl)
- local data = ""
- for key, value in pairs(tbl) do
- local valueType = type(value)
-
- -- Wrap the key in brackets if it's a number
- if( type(key) == "number" ) then
- key = string.format("[%s]", key)
- -- Wrap the string with quotes if it has a space in it
- elseif( string.match(key, "[%p%s%c]") ) then
- key = string.format("['%s']", string.gsub(key, "'", "\\'"))
- end
-
- -- foo = {bar = 5}
- if( valueType == "table" ) then
- data = string.format("%s%s=%s;", data, key, writeTable(value))
- -- foo = true / foo = 5
- elseif( valueType == "number" or valueType == "boolean" ) then
- data = string.format("%s%s=%s;", data, key, tostring(value))
- -- foo = "bar"
- else
- data = string.format("%s%s='%s';", data, key, string.gsub(tostring(value), "'", "\\'"))
- end
+
+ local function rangeWithIcon(info)
+ local name = getRange(info)
+ local text = L["Spell Name"]
+ if( string.match(info[#(info)], "Alt") ) then
+ text = L["Alternate Spell Name"]
end
-
- return "{" .. data .. "}"
+
+ local icon = select(3, GetSpellInfo(name))
+ if( not icon ) then
+ icon = "Interface\\Icons\\Inv_misc_questionmark"
+ end
+
+ return "|T" .. icon .. ":18:18:0:0|t " .. text
end
-
+
+ local textData = {}
+
local layoutData = {positions = true, visibility = true, modules = false}
local layoutManager = {
type = "group",
@@ -520,15 +578,6 @@ local function loadGeneralOptions()
get = function(info) return layoutData[info[#(info)]] end,
width = "double",
},
- modules = {
- order = 4,
- type = "toggle",
- name = L["Import non-standard module settings"],
- desc = L["Will not import settings of modules that are not included with Shadowed Unit Frames by default."],
- set = function(info, value) layoutData[info[#(info)]] = value end,
- get = function(info) return layoutData[info[#(info)]] end,
- width = "double",
- },
import = {
order = 5,
type = "input",
@@ -563,18 +612,6 @@ local function loadGeneralOptions()
end
end
- -- Strip module settings that aren't with SUF by default
- if( not layoutData.modules ) then
- local validModules = {["healthBar"] = true, ["powerBar"] = true, ["portrait"] = true, ["range"] = true, ["text"] = true, ["indicators"] = true, ["auras"] = true, ["incHeal"] = true, ["castBar"] = true, ["combatText"] = true, ["highlight"] = true, ["runeBar"] = true, ["totemBar"] = true, ["xpBar"] = true, ["fader"] = true, ["comboPoints"] = true}
- for _, unitData in pairs(layout.units) do
- for key, data in pairs(unitData) do
- if( type(data) == "table" and not validModules[key] and ShadowUF.modules[key] ) then
- unitData[key] = nil
- end
- end
- end
- end
-
-- Check if we need move over the visibility and positions info
layout.positions = layout.positions or CopyTable(ShadowUF.db.profile.positions)
layout.visibility = layout.visibility or CopyTable(ShadowUF.db.profile.positions)
@@ -673,27 +710,34 @@ local function loadGeneralOptions()
end,
arg = "locked",
},
- sep = {
- order = 1.5,
- type = "description",
- name = "",
- width = "full",
- hidden = hideAdvancedOption,
- },
advanced = {
- order = 2,
+ order = 1.5,
type = "toggle",
name = L["Advanced"],
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."],
arg = "advanced",
},
+ sep = {
+ order = 2,
+ type = "description",
+ name = "",
+ width = "full",
+ },
omnicc = {
order = 2.5,
type = "toggle",
- name = L["Disable OmniCC"],
- desc = L["Disables showing OmniCC timers in all Shadowed Unit Frame auras."],
+ name = L["Disable OmniCC Cooldown Count"],
+ desc = L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."],
arg = "omnicc",
- hidden = hideAdvancedOption,
+ width = "double",
+ },
+ blizzardcc = {
+ order = 2.5,
+ type = "toggle",
+ name = L["Disable Blizzard Cooldown Count"],
+ desc = L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."],
+ arg = "blizzardcc",
+ width = "double",
},
hideCombat = {
order = 3,
@@ -701,6 +745,13 @@ local function loadGeneralOptions()
name = L["Hide tooltips in combat"],
desc = L["Prevents unit tooltips from showing while in combat."],
arg = "tooltipCombat",
+ width = "double",
+ },
+ sep2 = {
+ order = 3.5,
+ type = "description",
+ name = "",
+ width = "full",
},
auraBorder = {
order = 5,
@@ -857,7 +908,7 @@ local function loadGeneralOptions()
order = 3,
type = "select",
name = L["Outline"],
- values = {["OUTLINE"] = L["Thin outline"], ["THICKOUTLINE"] = L["Thick outline"], [""] = L["None"]},
+ values = {["OUTLINE"] = L["Thin outline"], ["THICKOUTLINE"] = L["Thick outline"], ["MONOCHROMEOUTLINE"] = L["Monochrome Outline"], [""] = L["None"]},
arg = "font.extra",
hidden = hideAdvancedOption,
},
@@ -925,32 +976,6 @@ local function loadGeneralOptions()
},
},
},
- range = {
- order = 5,
- type = "group",
- inline = true,
- name = L["Range spells"],
- args = {
- friendly = {
- order = 0,
- type = "input",
- name = L["Friendly spell"],
- desc = L["Name of a friendly spell to check range on friendlies.|n|nThis is automatically set for your current class only."],
- validate = validateSpell,
- set = setRange,
- get = getRange,
- },
- hostile = {
- order = 1,
- type = "input",
- name = L["Hostile spell"],
- desc = L["Name of a hostile spell to check range on enemies.|n|nThis is automatically set for your current class only."],
- validate = validateSpell,
- set = setRange,
- get = getRange,
- },
- },
- },
},
},
color = {
@@ -1008,6 +1033,13 @@ local function loadGeneralOptions()
desc = L["Health bar color for hostile units."],
arg = "healthColors.hostile",
},
+ aggro = {
+ order = 6.5,
+ type = "color",
+ name = L["Has Aggro"],
+ desc = L["Health bar color for units with aggro."],
+ arg = "healthColors.aggro",
+ },
static = {
order = 7,
type = "color",
@@ -1019,19 +1051,65 @@ local function loadGeneralOptions()
order = 8,
type = "color",
name = L["Incoming heal"],
- desc = L["Health bar color to use to show how much healing someone is about to receive."],
+ desc = L["Bar color to use to show how much healing someone is about to receive."],
arg = "healthColors.inc",
},
- enemyUnattack = {
+ incAbsorb = {
order = 9,
type = "color",
+ name = L["Incoming absorb"],
+ desc = L["Color to use to show how much damage will be absorbed."],
+ arg = "healthColors.incAbsorb",
+ },
+ healAbsorb = {
+ order = 10,
+ type = "color",
+ name = L["Heal absorb"],
+ desc = L["Color to use to show how much healing will e absorbed."],
+ arg = "healthColors.healAbsorb",
+ },
+ enemyUnattack = {
+ order = 11,
+ type = "color",
name = L["Unattackable hostile"],
desc = L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."],
hidden = hideAdvancedOption,
arg = "healthColors.enemyUnattack",
- },
+ }
},
},
+ stagger = {
+ order = 1.5,
+ type = "group",
+ inline = true,
+ name = L["Stagger"],
+ set = setColor,
+ get = getColor,
+ hidden = function() return select(2, UnitClass("player")) ~= "MONK" end,
+ args = {
+ STAGGER_GREEN = {
+ order = 0,
+ type = "color",
+ name = L["Green (<30% HP)"],
+ desc = L["Stagger bar color when the staggered amount is <30% of your HP."],
+ arg = "powerColors.STAGGER_GREEN"
+ },
+ STAGGER_GREEN = {
+ order = 1,
+ type = "color",
+ name = L["Yellow (>30% HP)"],
+ desc = L["Stagger bar color when the staggered amount is >30% of your HP."],
+ arg = "powerColors.STAGGER_YELLOW"
+ },
+ STAGGER_RED = {
+ order = 2,
+ type = "color",
+ name = L["Red (>70% HP)"],
+ desc = L["Stagger bar color when the staggered amount is >70% of your HP."],
+ arg = "powerColors.STAGGER_RED"
+ }
+ }
+ },
power = {
order = 2,
type = "group",
@@ -1044,7 +1122,6 @@ local function loadGeneralOptions()
order = 0,
type = "color",
name = L["Mana"],
- hasAlpha = true,
width = "half",
arg = "powerColors.MANA",
},
@@ -1052,7 +1129,6 @@ local function loadGeneralOptions()
order = 1,
type = "color",
name = L["Rage"],
- hasAlpha = true,
width = "half",
arg = "powerColors.RAGE",
},
@@ -1060,7 +1136,6 @@ local function loadGeneralOptions()
order = 2,
type = "color",
name = L["Focus"],
- hasAlpha = true,
arg = "powerColors.FOCUS",
width = "half",
},
@@ -1068,40 +1143,142 @@ local function loadGeneralOptions()
order = 3,
type = "color",
name = L["Energy"],
- hasAlpha = true,
arg = "powerColors.ENERGY",
width = "half",
},
- HAPPINESS = {
- order = 5,
- type = "color",
- name = L["Happiness"],
- hasAlpha = true,
- arg = "powerColors.HAPPINESS",
- },
RUNIC_POWER = {
order = 6,
type = "color",
name = L["Runic Power"],
- hasAlpha = true,
arg = "powerColors.RUNIC_POWER",
},
- AMMOSLOT = {
+ RUNES = {
order = 7,
type = "color",
+ name = L["Runes"],
+ arg = "powerColors.RUNES",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DEATHKNIGHT" end,
+ },
+ AMMOSLOT = {
+ order = 9,
+ type = "color",
name = L["Ammo"],
- hasAlpha = true,
arg = "powerColors.AMMOSLOT",
hidden = hideAdvancedOption,
},
FUEL = {
- order = 8,
+ order = 10,
type = "color",
name = L["Fuel"],
- hasAlpha = true,
arg = "powerColors.FUEL",
hidden = hideAdvancedOption,
},
+ COMBOPOINTS = {
+ order = 11,
+ type = "color",
+ name = L["Combo Points"],
+ arg = "powerColors.COMBOPOINTS",
+ },
+ AURAPOINTS = {
+ order = 11.5,
+ type = "color",
+ name = L["Aura Combo Points"],
+ arg = "powerColors.AURAPOINTS",
+ hidden = function() return not ShadowUF.modules.auraPoints end
+ },
+ INSANITY = {
+ order = 12,
+ type = "color",
+ name = L["Insanity"],
+ arg = "powerColors.INSANITY",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "PRIEST" end,
+ },
+ MAELSTROM = {
+ order = 12,
+ type = "color",
+ name = L["Maelstrom"],
+ arg = "powerColors.MAELSTROM",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "SHAMAN" end,
+ },
+ HOLYPOWER = {
+ order = 12,
+ type = "color",
+ name = L["Holy Power"],
+ arg = "powerColors.HOLYPOWER",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "PALADIN" end,
+ },
+ SOULSHARDS = {
+ order = 14,
+ type = "color",
+ name = L["Soul Shards"],
+ hasAlpha = true,
+ arg = "powerColors.SOULSHARDS",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "WARLOCK" end,
+ },
+ ARCANECHARGES = {
+ order = 15,
+ type = "color",
+ name = L["Arcane Charges"],
+ hasAlpha = true,
+ arg = "powerColors.ARCANECHARGES",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "MAGE" end,
+ },
+ CHI = {
+ order = 17,
+ type = "color",
+ name = L["Chi"],
+ arg = "powerColors.CHI",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "MONK" end,
+ },
+ FURY = {
+ order = 17,
+ type = "color",
+ name = L["Fury"],
+ arg = "powerColors.FURY",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DEMONHUNTER" end,
+ },
+ PAIN = {
+ order = 17,
+ type = "color",
+ name = L["Pain"],
+ arg = "powerColors.PAIN",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DEMONHUNTER" end,
+ },
+ LUNAR_POWER = {
+ order = 17,
+ type = "color",
+ name = L["Astral Power"],
+ arg = "powerColors.LUNAR_POWER",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DRUID" end,
+ },
+ MUSHROOMS = {
+ order = 17,
+ type = "color",
+ name = L["Mushrooms"],
+ arg = "powerColors.MUSHROOMS",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DRUID" end,
+ },
+ STATUE = {
+ order = 17,
+ type = "color",
+ name = L["Statue"],
+ arg = "powerColors.STATUE",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "MONK" end,
+ },
+ RUNEOFPOWER = {
+ order = 17.5,
+ type = "color",
+ name = L["Rune of Power"],
+ arg = "powerColors.RUNEOFPOWER",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "MAGE" end,
+ },
+ ALTERNATE = {
+ order = 19,
+ type = "color",
+ name = L["Alt. Power"],
+ desc = L["Alternate power is used for things like quests and dungeons."],
+ arg = "powerColors.ALTERNATE",
+ },
},
},
cast = {
@@ -1158,6 +1335,25 @@ local function loadGeneralOptions()
},
},
},
+ auras = {
+ order = 3.5,
+ type = "group",
+ inline = true,
+ name = L["Aura borders"],
+ set = setColor,
+ get = getColor,
+ hidden = hideAdvancedOption,
+ args = {
+ removableColor = {
+ order = 0,
+ type = "color",
+ name = L["Stealable/Curable/Dispellable"],
+ desc = L["Border coloring of stealable, curable and dispellable auras."],
+ arg = "auraColors.removable",
+ width = "double"
+ }
+ }
+ },
classColors = {
order = 4,
type = "group",
@@ -1169,12 +1365,10 @@ local function loadGeneralOptions()
},
},
},
- profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ShadowUF.db, true),
- text = {
+ range = {
+ order = 5,
type = "group",
- order = 6,
- name = L["Text management"],
- hidden = false,
+ name = L["Range Checker"],
args = {
help = {
order = 0,
@@ -1185,37 +1379,124 @@ local function loadGeneralOptions()
help = {
order = 0,
type = "description",
- 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."],
+ 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."],
},
},
},
- add = {
+ friendly = {
order = 1,
- name = L["Add new text"],
inline = true,
type = "group",
- set = function(info, value) textData[info[#(info)] ] = value end,
- get = function(info, value) return textData[info[#(info)] ] end,
+ name = L["On Friendly Units"],
args = {
- name = {
- order = 0,
- type = "input",
- name = L["Text name"],
- desc = L["Text name that you can use to identify this text from others when configuring."],
- },
- parent = {
+ friendly = {
order = 1,
- type = "select",
- name = L["Text parent"],
- desc = L["Where inside the frame the text should be anchored to."],
- values = barModules,
+ type = "input",
+ name = rangeWithIcon,
+ desc = L["Name of a friendly spell to check range."],
+ validate = validateSpell,
+ set = setRange,
+ get = getRange,
},
- add = {
+ spacer = {
order = 2,
- type = "execute",
- name = L["Add"],
- disabled = function() return not textData.name or textData.name == "" or not textData.parent end,
- func = function(info)
+ type = "description",
+ width = "normal",
+ name = ""
+ },
+ friendlyAlt = {
+ order = 3,
+ type = "input",
+ name = rangeWithIcon,
+ desc = L["Alternatively friendly spell to use to check range."],
+ hidden = hideAdvancedOption,
+ validate = validateSpell,
+ set = setRange,
+ get = getRange,
+ },
+ }
+ },
+ hostile = {
+ order = 2,
+ inline = true,
+ type = "group",
+ name = L["On Hostile Units"],
+ args = {
+ hostile = {
+ order = 1,
+ type = "input",
+ name = rangeWithIcon,
+ desc = L["Name of a friendly spell to check range."],
+ validate = validateSpell,
+ set = setRange,
+ get = getRange,
+ },
+ spacer = {
+ order = 2,
+ type = "description",
+ width = "normal",
+ name = ""
+ },
+ hostileAlt = {
+ order = 3,
+ type = "input",
+ name = rangeWithIcon,
+ desc = L["Alternatively friendly spell to use to check range."],
+ hidden = hideAdvancedOption,
+ validate = validateSpell,
+ set = setRange,
+ get = getRange,
+ },
+ }
+ },
+ },
+ },
+ text = {
+ type = "group",
+ order = 6,
+ name = L["Text Management"],
+ hidden = false,
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ inline = true,
+ name = L["Help"],
+ args = {
+ help = {
+ order = 0,
+ type = "description",
+ 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."],
+ },
+ },
+ },
+ add = {
+ order = 1,
+ name = L["Add new text"],
+ inline = true,
+ type = "group",
+ set = function(info, value) textData[info[#(info)] ] = value end,
+ get = function(info, value) return textData[info[#(info)] ] end,
+ args = {
+ name = {
+ order = 0,
+ type = "input",
+ name = L["Text name"],
+ desc = L["Text name that you can use to identify this text from others when configuring."],
+ },
+ parent = {
+ order = 1,
+ type = "select",
+ name = L["Text parent"],
+ desc = L["Where inside the frame the text should be anchored to."],
+ values = barModules,
+ },
+ add = {
+ order = 2,
+ type = "execute",
+ name = L["Add"],
+ disabled = function() return not textData.name or textData.name == "" or not textData.parent end,
+ func = function(info)
-- Verify we entered a good name
textData.name = string.trim(textData.name)
textData.name = textData.name ~= "" and textData.name or nil
@@ -1255,10 +1536,12 @@ local function loadGeneralOptions()
-- Load text
for id, text in pairs(ShadowUF.db.profile.units.player.text) do
- addTextParent.args[id .. ":label"] = addTextLabel
- addTextParent.args[tostring(id)] = addText
- addTextParent.args[id .. ":sep"] = addTextSep
- options.args.general.args.text.args[text.anchorTo] = addTextParent
+ if( text.anchorTo ~= "" and not text.default ) then
+ addTextParent.args[id .. ":label"] = addTextLabel
+ addTextParent.args[tostring(id)] = addText
+ addTextParent.args[id .. ":sep"] = addTextSep
+ options.args.general.args.text.args[text.anchorTo] = addTextParent
+ end
end
@@ -1277,8 +1560,6 @@ local function loadGeneralOptions()
options.args.general.args.color.args.classColors.args.PET = Config.classTable
options.args.general.args.color.args.classColors.args.VEHICLE = Config.classTable
-
- options.args.general.args.profile.order = 4
end
---------------------
@@ -1290,7 +1571,8 @@ local function loadHideOptions()
type = "toggle",
name = function(info)
local key = info[#(info)]
- 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 == "runes" and L["rune bar"] or key == "buffs" and L["buff frames"])
+ if( key == "arena" ) then return string.format(L["Hide %s frames"], "arena/battleground") end
+ 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"])
end,
set = function(info, value)
set(info, value)
@@ -1327,14 +1609,16 @@ local function loadHideOptions()
args = {
buffs = Config.hideTable,
cast = Config.hideTable,
- runes = Config.hideTable,
+ playerPower = Config.hideTable,
party = Config.hideTable,
+ raid = Config.hideTable,
player = Config.hideTable,
pet = Config.hideTable,
target = Config.hideTable,
focus = Config.hideTable,
boss = Config.hideTable,
arena = Config.hideTable,
+ playerAltPower = Config.hideTable,
},
},
}
@@ -1452,7 +1736,7 @@ local function loadUnitOptions()
-- Load tag list
Config.advanceTextTable = {
order = 1,
- name = function(info) return getVariable(info[2], "text", quickIDMap[info[#(info)]], "name") end,
+ name = function(info) return getVariable(info[2], "text", quickIDMap[info[#(info)]], "name") end,
type = "group",
inline = true,
hidden = function(info)
@@ -1488,7 +1772,9 @@ local function loadUnitOptions()
desc = L["How much weight this should use when figuring out the total text width."],
type = "range",
min = 0, max = 10, step = 0.1,
- hidden = false,
+ hidden = function(info)
+ return hideAdvancedOption(info) or getVariable(info[2], "text", quickIDMap[info[#(info) - 1]], "block")
+ end,
},
size = {
order = 4,
@@ -1498,6 +1784,15 @@ local function loadUnitOptions()
min = -20, max = 20, step = 1, softMin = -5, softMax = 5,
hidden = false,
},
+ sep2 = {
+ order = 4.5,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = function(info)
+ return hideAdvancedOption(info) or not getVariable(info[2], "text", quickIDMap[info[#(info) - 1]], "block")
+ end
+ },
x = {
order = 5,
type = "range",
@@ -1526,7 +1821,9 @@ local function loadUnitOptions()
local function hideBlacklistedTag(info)
local unit = info[2]
+ local id = tonumber(info[#(info) - 2])
local tag = info[#(info)]
+ local cat = info[#(info) - 1]
if( unit == "global" ) then
for unit in pairs(modifyUnits) do
@@ -1535,9 +1832,16 @@ local function loadUnitOptions()
end
end
end
-
+
if( ShadowUF.Tags.unitRestrictions[tag] and ShadowUF.Tags.unitRestrictions[tag] ~= unit ) then
return true
+
+ elseif( ShadowUF.Tags.anchorRestriction[tag] ) then
+ if( ShadowUF.Tags.anchorRestriction[tag] ~= getVariable(unit, "text", id, "anchorTo") ) then
+ return true
+ else
+ return false
+ end
end
return false
@@ -1545,7 +1849,9 @@ local function loadUnitOptions()
local function hideBlacklistedGroup(info)
local unit = info[2]
+ local id = tonumber(info[#(info) - 1])
local tagGroup = info[#(info)]
+
if( unit ~= "global" ) then
if( ShadowUF.Tags.unitBlacklist[tagGroup] and string.match(unit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then
return true
@@ -1558,6 +1864,11 @@ local function loadUnitOptions()
end
end
end
+
+ local block = getVariable(unit, "text", id, "block")
+ if( ( block and tagGroup ~= "classtimer" ) or ( not block and tagGroup == "classtimer" ) ) then
+ return true
+ end
return false
end
@@ -1597,29 +1908,6 @@ local function loadUnitOptions()
text = string.format("%s[( )%s]", text, tag)
end
end
- -- Removing a tag from global config, need to make sure we can do it
- -- Hack, clean up later
- elseif( unit == "global" ) then
- table.wipe(savedTagTexts)
- for unit in pairs(modifyUnits) do
- if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(unit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then
- if( not ShadowUF.Tags.unitRestrictions[tag] or ShadowUF.Tags.unitRestrictions[tag] == unit ) then
- local text = getVariable(unit, "text", id, "text")
- for matchedTag in string.gmatch(text, "%[(.-)%]") do
- local safeTag = "[" .. matchedTag .. "]"
- if( string.match(safeTag, "%[" .. tag .. "%]") or string.match(safeTag, "%)" .. tag .. "%]") or string.match(safeTag, "%[" .. tag .. "%(") or string.match(safeTag, "%)" .. tag .. "%(") ) then
- text = string.gsub(text, "%[" .. string.gsub(string.gsub(matchedTag, "%)", "%%)"), "%(", "%%(") .. "%]", "")
- text = string.gsub(text, " ", "")
- text = string.trim(text)
- break
- end
- end
-
- savedTagTexts[unit] = text
- savedTagTexts.global = text
- end
- end
- end
-- Removing a tag from a single unit, super easy :<
else
@@ -1755,7 +2043,7 @@ local function loadUnitOptions()
end
local function disableAnchoredTo(info)
- local auras = getVariable(info[2], "auras", nil, info[#(info) - 1])
+ local auras = getVariable(info[2], "auras", nil, info[#(info) - 2])
return auras.anchorOn or not auras.enabled
end
@@ -1765,15 +2053,15 @@ local function loadUnitOptions()
local debuffs = getVariable(info[2], "auras", nil, "debuffs")
local anchor = buffs.enabled and buffs.prioritize and "buffs" or "debuffs"
- if( not getVariable(info[2], "auras", info[#(info) - 1], "enabled") ) then
+ if( not getVariable(info[2], "auras", info[#(info) - 2], "enabled") ) then
return true
end
- if( ( info[#(info)] == "x" or info[#(info)] == "y" ) and ( info[#(info) - 1] == "buffs" and buffs.anchorOn or info[#(info) - 1] == "debuffs" and debuffs.anchorOn ) ) then
+ 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
return true
end
- if( anchor == info[#(info) - 1] or buffs.anchorOn or debuffs.anchorOn ) then
+ if( anchor == info[#(info) - 2] or buffs.anchorOn or debuffs.anchorOn ) then
return false
end
@@ -1786,207 +2074,340 @@ local function loadUnitOptions()
return ShadowUF.db.profile.advanced and advancedAuraList or defaultAuraList
end
+ local function hideStealable(info)
+ if( not ShadowUF.db.profile.advanced ) then return true end
+ if( info[2] == "player" or info[2] == "pet" or info[#(info) - 2] == "debuffs" ) then return true end
+
+ return false
+ end
+
+ local function hideBuffOption(info)
+ return info[#(info) - 2] ~= "buffs"
+ end
+
+ local function hideDebuffOption(info)
+ return info[#(info) - 2] ~= "debuffs"
+ end
+
+ local function reloadUnitAuras()
+ for _, frame in pairs(ShadowUF.Units.unitFrames) do
+ if( UnitExists(frame.unit) and frame.visibility.auras ) then
+ ShadowUF.modules.auras:UpdateFilter(frame)
+ frame:FullUpdate()
+ end
+ end
+ end
+
+ local aurasDisabled = function(info) return not getVariable(info[2], "auras", info[#(info) - 2], "enabled") end
+
Config.auraTable = {
type = "group",
- inline = true,
hidden = false,
name = function(info) return info[#(info)] == "buffs" and L["Buffs"] or L["Debuffs"] end,
order = function(info) return info[#(info)] == "buffs" and 1 or 2 end,
- disabled = function(info) return not getVariable(info[2], "auras", info[#(info) - 1], "enabled") end,
+ disabled = false,
args = {
- enabled = {
- order = 1,
- type = "toggle",
- name = function(info) if( info[#(info) - 1] == "buffs" ) then return L["Enable buffs"] end return L["Enable debuffs"] end,
- disabled = false,
- arg = "auras.$parent.enabled",
+ general = {
+ type = "group",
+ name = L["General"],
+ order = 0,
+ args = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = function(info) if( info[#(info) - 2] == "buffs" ) then return L["Enable buffs"] end return L["Enable debuffs"] end,
+ disabled = false,
+ width = "full",
+ arg = "auras.$parentparent.enabled",
+ },
+ temporary = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable temporary enchants"],
+ desc = L["Adds temporary enchants to the buffs for the player."],
+ width = "full",
+ hidden = function(info) return info[2] ~= "player" or info[#(info) - 2] ~= "buffs" end,
+ disabled = function(info) return not getVariable(info[2], "auras", "buffs", "enabled") end,
+ arg = "auras.buffs.temporary",
+ }
+ }
},
- anchorOn = {
- order = 2,
- type = "toggle",
- name = function(info) return info[#(info) - 1] == "buffs" and L["Anchor to debuffs"] or L["Anchor to buffs"] end,
- 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."],
+ filters = {
+ type = "group",
+ name = L["Filters"],
+ order = 1,
set = function(info, value)
- setVariable(info[2], "auras", info[#(info) - 1] == "buffs" and "debuffs" or "buffs", "anchorOn", false)
- setUnit(info, value)
+ getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]] = value
+ reloadUnitAuras()
end,
- arg = "auras.$parent.anchorOn",
- },
- prioritize = {
- order = 2.25,
- type = "toggle",
- name = L["Prioritize buffs"],
- desc = L["Show buffs before debuffs when sharing the same anchor point."],
- hidden = function(info) return info[#(info) - 1] == "debuffs" end,
- disabled = function(info)
- if( not getVariable(info[2], "auras", info[#(info) - 1], "enabled") ) then return true end
-
- local buffs = getVariable(info[2], "auras", nil, "buffs")
- local debuffs = getVariable(info[2], "auras", nil, "debuffs")
-
- return buffs.anchorOn or debuffs.anchorOn or buffs.anchorPoint ~= debuffs.anchorPoint
+ get = function(info)
+ return getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]]
end,
- arg = "auras.$parent.prioritize",
- },
- sep2 = {
- order = 6,
- type = "description",
- name = "",
- width = "full",
- },
- player = {
- order = 7,
- type = "toggle",
- name = L["Show your auras only"],
- desc = L["Filter out any auras that you did not cast yourself."],
- arg = "auras.$parent.player",
- },
- raid = {
- order = 8,
- type = "toggle",
- name = function(info) return info[#(info) - 1] == "buffs" and L["Show castable on other auras only"] or L["Show curable only"] end,
- desc = function(info) return info[#(info) - 1] == "buffs" and L["Filter out any auras that you cannot cast on another player, or yourself."] or L["Filter out any aura that you cannot cure."] end,
- width = "double",
- arg = "auras.$parent.raid",
- },
- sep3 = {
- order = 9,
- type = "description",
- name = "",
- width = "full",
- },
- selfTimers = {
- order = 9.5,
- type = "toggle",
- name = L["Timers for self auras only"],
- desc = L["Hides the cooldown ring for any auras that you did not cast."],
- hidden = hideAdvancedOption,
- arg = "auras.$parent.selfTimers",
- },
- enlargeSelf = {
- order = 10,
- type = "toggle",
- name = L["Enlarge your auras"],
- desc = L["If you casted the aura, then the buff icon will be increased in size to make it more visible."],
- arg = "auras.$parent.enlargeSelf",
- },
- selfScale = {
- order = 11,
- type = "range",
- name = L["Self aura size"],
- desc = L["Scale for auras that you casted, any number above 100% is bigger tahn default, any number below 100% is smaller than default."],
- min = 1, max = 3, step = 0.10,
- isPercent = true,
- disabled = function(info) return not getVariable(info[2], "auras", info[#(info) - 1], "enlargeSelf") end,
- hidden = hideAdvancedOption,
- arg = "auras.$parent.selfScale",
- },
- selfTimersDouble = {
- order = 11,
- type = "toggle",
- name = L["Timers for self auras only"],
- desc = L["Hides the cooldown ring for any auras that you did not cast."],
- hidden = hideBasicOption,
- arg = "auras.$parent.selfTimers",
- width = "double",
- },
- sep4 = {
- order = 12,
- type = "description",
- name = "",
- width = "full",
+ args = {
+ player = {
+ order = 1,
+ type = "toggle",
+ name = L["Show your auras"],
+ desc = L["Whether auras you casted should be shown"],
+ width = "full"
+ },
+ raid = {
+ order = 2,
+ type = "toggle",
+ name = function(info) return info[#(info) - 2] == "buffs" and L["Show castable on other auras"] or L["Show curable/removable auras"] end,
+ 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,
+ width = "full"
+ },
+ boss = {
+ order = 3,
+ type = "toggle",
+ name = L["Show casted by boss"],
+ desc = L["Whether to show any auras casted by the boss"],
+ width = "full"
+ },
+ misc = {
+ order = 5,
+ type = "toggle",
+ name = L["Show any other auras"],
+ desc = L["Whether to show auras that do not fall into the above categories."],
+ width = "full"
+ },
+ relevant = {
+ order = 6,
+ type = "toggle",
+ name = L["Smart Friendly/Hostile Filter"],
+ desc = L["Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras."],
+ width = "full"
+ },
+ }
},
- perRow = {
- order = 13,
- type = "range",
- name = function(info)
- local anchorPoint = getVariable(info[2], "auras", info[#(info) - 1], "anchorPoint")
- if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
- return L["Per column"]
- end
-
- return L["Per row"]
- end,
- desc = L["How many auras to show in a single row."],
- min = 1, max = 100, step = 1, softMin = 1, softMax = 50,
- disabled = disableSameAnchor,
- arg = "auras.$parent.perRow",
+ display = {
+ type = "group",
+ name = L["Display"],
+ order = 2,
+ args = {
+ prioritize = {
+ order = 1,
+ type = "toggle",
+ name = L["Prioritize buffs"],
+ desc = L["Show buffs before debuffs when sharing the same anchor point."],
+ hidden = hideBuffOption,
+ disabled = function(info)
+ if( not getVariable(info[2], "auras", info[#(info) - 2], "enabled") ) then return true end
+
+ local buffs = getVariable(info[2], "auras", nil, "buffs")
+ local debuffs = getVariable(info[2], "auras", nil, "debuffs")
+
+ return buffs.anchorOn or debuffs.anchorOn or buffs.anchorPoint ~= debuffs.anchorPoint
+ end,
+ arg = "auras.$parentparent.prioritize"
+ },
+ sep1 = {order = 1.5, type = "description", name = "", width = "full"},
+ selfScale = {
+ order = 2,
+ type = "range",
+ name = L["Scaled aura size"],
+ 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."],
+ min = 1, max = 3, step = 0.10,
+ isPercent = true,
+ hidden = hideAdvancedOption,
+ arg = "auras.$parentparent.selfScale",
+ },
+ sep12 = {order = 2.5, type = "description", name = "", width = "full"},
+ timers = {
+ order = 3,
+ type = "multiselect",
+ name = L["Cooldown rings for"],
+ desc = L["When to show cooldown rings on auras"],
+ hidden = hideAdvancedOption,
+ values = function(info)
+ local tbl = {["ALL"] = L["All Auras"], ["SELF"] = L["Your Auras"]}
+ local type = info[#(info) - 2]
+ if( type == "debuffs" ) then
+ tbl["BOSS"] = L["Boss Debuffs"]
+ end
+
+ return tbl;
+ end,
+ set = function(info, key, value)
+ local tbl = getVariable(info[2], "auras", info[#(info) - 2], "timers")
+ if( key == "ALL" and value ) then
+ tbl = {["ALL"] = true}
+ elseif( key ~= "ALL" and value ) then
+ tbl["ALL"] = nil
+ tbl[key] = value
+ else
+ tbl[key] = value
+ end
+
+ setVariable(info[2], "auras", info[#(info) - 2], "timers", tbl)
+ reloadUnitAuras()
+ end,
+ get = function(info, key)
+ return getVariable(info[2], "auras", info[#(info) - 2], "timers")[key]
+ end
+ },
+ sep3 = {order = 3.5, type = "description", name = "", width = "full"},
+ enlarge = {
+ order = 4,
+ type = "multiselect",
+ name = L["Enlarge auras for"],
+ desc = L["What type of auras should be enlarged, use the scaled aura size option to change the size."],
+ values = function(info)
+ local tbl = {["SELF"] = L["Your Auras"]}
+ local type = info[#(info) - 2]
+ if( type == "debuffs" ) then
+ tbl["BOSS"] = L["Boss Debuffs"]
+ end
+
+ if( type == "debuffs" ) then
+ tbl["REMOVABLE"] = L["Curable"]
+ elseif( info[2] ~= "player" and info[2] ~= "pet" and info[2] ~= "party" and info[2] ~= "raid" and type == "buffs" ) then
+ tbl["REMOVABLE"] = L["Dispellable/Stealable"]
+ end
+
+ return tbl;
+ end,
+ set = function(info, key, value)
+ local tbl = getVariable(info[2], "auras", info[#(info) - 2], "enlarge")
+ tbl[key] = value
+
+ setVariable(info[2], "auras", info[#(info) - 2], "enlarge", tbl)
+ reloadUnitAuras()
+ end,
+ get = function(info, key)
+ return getVariable(info[2], "auras", info[#(info) - 2], "enlarge")[key]
+ end
+ }
+ }
},
- maxRows = {
- order = 14,
- type = "range",
- name = L["Max rows"],
- desc = L["How many rows total should be used, rows will be however long the per row value is set at."],
- min = 1, max = 10, step = 1, softMin = 1, softMax = 5,
- disabled = disableSameAnchor,
- hidden = function(info)
- local anchorPoint = getVariable(info[2], "auras", info[#(info) - 1], "anchorPoint")
- if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
- return true
- end
-
- return false
- end,
- arg = "auras.$parent.maxRows",
- },
- maxColumns = {
- order = 14,
- type = "range",
- name = L["Max columns"],
- 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."],
- min = 1, max = 100, step = 1, softMin = 1, softMax = 50,
- hidden = function(info)
- local anchorPoint = getVariable(info[2], "auras", info[#(info) - 1], "anchorPoint")
- if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
- return false
- end
-
- return true
- end,
- disabled = disableSameAnchor,
- arg = "auras.$parent.maxRows",
- },
- size = {
- order = 15,
- type = "range",
- name = L["Size"],
- min = 1, max = 30, step = 1,
- arg = "auras.$parent.size",
- },
- sep5 = {
- order = 16,
- type = "description",
- name = "",
- width = "full",
- },
- anchorPoint = {
- order = 17,
- type = "select",
- name = L["Position"],
- desc = L["How you want this aura to be anchored to the unit frame."],
- values = getAuraAnchors,
- disabled = disableAnchoredTo,
- arg = "auras.$parent.anchorPoint",
- },
- x = {
- order = 18,
- type = "range",
- name = L["X Offset"],
- min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100,
- disabled = disableSameAnchor,
- hidden = hideAdvancedOption,
- arg = "auras.$parent.x",
- },
- y = {
- order = 19,
- type = "range",
- name = L["Y Offset"],
- min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100,
- disabled = disableSameAnchor,
- hidden = hideAdvancedOption,
- arg = "auras.$parent.y",
- },
- },
+ positioning = {
+ type = "group",
+ name = L["Positioning"],
+ order = 3,
+ args = {
+ anchorOn = {
+ order = 1.1,
+ type = "toggle",
+ name = function(info) return info[#(info) - 2] == "buffs" and L["Anchor to debuffs"] or L["Anchor to buffs"] end,
+ 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."],
+ set = function(info, value)
+ setVariable(info[2], "auras", info[#(info) - 2] == "buffs" and "debuffs" or "buffs", "anchorOn", false)
+ setUnit(info, value)
+ end,
+ disabled = aurasDisabled,
+ arg = "auras.$parentparent.anchorOn",
+ },
+ timeSortingEnabled = {
+ order = 1.2,
+ type = "toggle",
+ name = "Enable time sorting",
+ desc = "Allows you to select a sorting method for the unit frames auras.",
+ set = function(info, value)
+ local current = getVariable(info[2], "auras", info[#(info) - 2] == "buffs" and "debuffs" or "buffs", "timeSortingToggle")
+ setVariable(info[2], "auras", info[#(info) - 2] == "buffs" and "debuffs" or "buffs", "timeSortingToggle", not current)
+ setUnit(info, value)
+ end,
+ disabled = aurasDisabled,
+ arg = "auras.$parentparent.timeSortingEnabled",
+ },
+ anchorPoint = {
+ order = 2.1,
+ type = "select",
+ name = L["Position"],
+ desc = L["How you want this aura to be anchored to the unit frame."],
+ values = getAuraAnchors,
+ disabled = disableAnchoredTo,
+ arg = "auras.$parentparent.anchorPoint",
+ },
+ timeSortingMethod = {
+ order = 2.2,
+ type = "select",
+ name = "Sorting method",
+ desc = "Sort auras by ascending or descending duration. Ascending sorts least duration to the start, descending sorts least duration to the end.",
+ values = { ["ASC"] = "Ascending", ["DESC"] = "Descending" },
+ disabled = disableTimeSorting,
+ arg = "auras.$parentparent.timeSortingMethod",
+ },
+ perRow = {
+ order = 3.1,
+ type = "range",
+ name = function(info)
+ local anchorPoint = getVariable(info[2], "auras", info[#(info) - 2], "anchorPoint")
+ if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
+ return L["Per column"]
+ end
+
+ return L["Per row"]
+ end,
+ desc = L["How many auras to show in a single row."],
+ min = 1, max = 100, step = 1, softMin = 1, softMax = 50,
+ disabled = disableSameAnchor,
+ arg = "auras.$parentparent.perRow",
+ },
+ maxRows = {
+ order = 3.2,
+ type = "range",
+ name = L["Max rows"],
+ desc = L["How many rows total should be used, rows will be however long the per row value is set at."],
+ min = 1, max = 10, step = 1, softMin = 1, softMax = 5,
+ disabled = disableSameAnchor,
+ hidden = function(info)
+ local anchorPoint = getVariable(info[2], "auras", info[#(info) - 2], "anchorPoint")
+ if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
+ return true
+ end
+
+ return false
+ end,
+ arg = "auras.$parentparent.maxRows",
+ },
+ maxColumns = {
+ order = 3.2,
+ type = "range",
+ name = L["Max columns"],
+ 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."],
+ min = 1, max = 100, step = 1, softMin = 1, softMax = 50,
+ hidden = function(info)
+ local anchorPoint = getVariable(info[2], "auras", info[#(info) - 2], "anchorPoint")
+ if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
+ return false
+ end
+
+ return true
+ end,
+ disabled = disableSameAnchor,
+ arg = "auras.$parentparent.maxRows",
+ },
+ x = {
+ order = 4.1,
+ type = "range",
+ name = L["X Offset"],
+ min = -1000, max = 1000, step = 1, softMin = -300, softMax = 300,
+ disabled = disableSameAnchor,
+ hidden = hideAdvancedOption,
+ arg = "auras.$parentparent.x",
+ },
+ y = {
+ order = 4.2,
+ type = "range",
+ name = L["Y Offset"],
+ min = -1000, max = 1000, step = 1, softMin = -300, softMax = 300,
+ disabled = disableSameAnchor,
+ hidden = hideAdvancedOption,
+ arg = "auras.$parentparent.y",
+ },
+ size = {
+ order = 5.1,
+ type = "range",
+ name = L["Icon Size"],
+ min = 1, max = 40, step = 1,
+ disabled = aurasDisabled,
+ arg = "auras.$parentparent.size",
+ },
+ }
+ }
+ }
}
local function hideBarOption(info)
@@ -2007,7 +2428,7 @@ local function loadUnitOptions()
order = getModuleOrder,
name = getName,
type = "group",
- inline = true,
+ inline = false,
hidden = function(info) return hideRestrictedOption(info) or not getVariable(info[2], info[#(info)], nil, "enabled") end,
args = {
enableBar = {
@@ -2017,8 +2438,8 @@ local function loadUnitOptions()
desc = L["Turns this widget into a bar that can be resized and ordered just like health and power bars."],
hidden = function(info) return ShadowUF.modules[info[#(info) - 1]].moduleHasBar end,
arg = "$parent.isBar",
- width = "full",
},
+ 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},
background = {
order = 1.5,
type = "toggle",
@@ -2027,18 +2448,76 @@ local function loadUnitOptions()
hidden = hideBarOption,
arg = "$parent.background",
},
- sep2 = {order = 1.75, type = "description", name = "", hidden = function(info)
- local moduleKey = info[#(info) - 1]
- return ( moduleKey ~= "healthBar" and moduleKey ~= "powerBar" and moduleKey ~= "druidBar" ) or not ShadowUF.db.profile.advanced
- end},
+ 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},
+ overrideBackground = {
+ order = 1.6,
+ type = "toggle",
+ name = L["Override background"],
+ desc = L["Show a background behind the bars with the same texture/color but faded out."],
+ disabled = function(info) return not getVariable(info[2], info[#(info) - 1], nil, "background") end,
+ hidden = function(info) return info[#(info) - 1] ~= "burningEmbersBar" end,
+ set = function(info, toggle)
+ if( toggle ) then
+ setVariable(info[2], info[#(info) - 1], nil, "backgroundColor", {r = 0, g = 0, b = 0, a = 0.70})
+ else
+ setVariable(info[2], info[#(info) - 1], nil, "backgroundColor", nil)
+ end
+ end,
+ get = function(info)
+ return not not getVariable(info[2], info[#(info) - 1], nil, "backgroundColor")
+ end
+ },
+ overrideColor = {
+ order = 1.65,
+ type = "color",
+ hasAlpha = true,
+ name = L["Background color"],
+ 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,
+ set = function(info, r, g, b, a)
+ local color = getUnit(info) or {}
+ color.r = r
+ color.g = g
+ color.b = b
+ color.a = a
+
+ setUnit(info, color)
+ end,
+ get = function(info)
+ local color = getUnit(info)
+ if( not color ) then
+ return 0, 0, 0, 1
+ end
+
+ return color.r, color.g, color.b, color.a
+
+ end,
+ arg = "$parent.backgroundColor",
+ },
+ vertical = {
+ order = 1.70,
+ type = "toggle",
+ name = L["Vertical growth"],
+ desc = L["Rather than bars filling from left -> right, they will fill from bottom -> top."],
+ arg = "$parent.vertical",
+ hidden = function(info) return not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,
+ },
+ reverse = {
+ order = 1.71,
+ type = "toggle",
+ name = L["Reverse fill"],
+ desc = L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."],
+ arg = "$parent.reverse",
+ hidden = function(info) return not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,
+ },
invert = {
order = 2,
type = "toggle",
name = L["Invert colors"],
desc = L["Flips coloring so the bar color is shown as the background color and the background as the bar"],
- hidden = function(info) return ( info[#(info) - 1] ~= "healthBar" and info[#(info) - 1] ~= "powerBar" and info[#(info) - 1] ~= "druidBar" ) or not ShadowUF.db.profile.advanced end,
+ hidden = function(info) return not ShadowUF.modules[info[#(info) - 1]] or not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,
arg = "$parent.invert",
},
+ 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,},
order = {
order = 4,
type = "range",
@@ -2055,7 +2534,7 @@ local function loadUnitOptions()
min = 0, max = 10, step = 0.1,
hidden = hideBarOption,
arg = "$parent.height",
- },
+ }
},
}
@@ -2215,7 +2694,7 @@ local function loadUnitOptions()
name = string.format(L["Enable %s"], L["Combat fader"]),
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."],
hidden = false,
- arg = "fader.enabled",
+ arg = "fader.enabled"
},
combatAlpha = {
order = 1,
@@ -2304,7 +2783,7 @@ local function loadUnitOptions()
name = L["On aggro"],
desc = L["Highlight units that have aggro on any mob."],
arg = "highlight.aggro",
- hidden = function(info) return info[2] == "arena" or info[2] == "arenapet" or ShadowUF.fakeUnits[info[2]] end,
+ hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or info[2] == "battlegroundpet" or info[2] == "arenapet" or ShadowUF.fakeUnits[info[2]] end,
},
debuff = {
order = 6,
@@ -2312,7 +2791,30 @@ local function loadUnitOptions()
name = L["On curable debuff"],
desc = L["Highlight units that are debuffed with something you can cure."],
arg = "highlight.debuff",
- hidden = function(info) return string.match(info[2], "^arena") or string.match(info[2], "^boss") end,
+ hidden = function(info) return info[2] ~= "boss" and ( ShadowUF.Units.zoneUnits[info[2]] or info[2] == "battlegroundpet" or info[2] == "arenapet" ) end,
+ },
+ raremob = {
+ order = 6.10,
+ type = "toggle",
+ name = L["On rare mobs"],
+ desc = L["Highlight units that are rare."],
+ arg = "highlight.rareMob",
+ hidden = function(info) return not (info[2] == "target" or info[2] == "focus" or info[2] == "targettarget" or info[3] == "focustarget") end,
+ },
+ elitemob = {
+ order = 6.15,
+ type = "toggle",
+ name = L["On elite mobs"],
+ desc = L["Highlight units that are "],
+ arg = "highlight.eliteMob",
+ hidden = function(info) return not (info[2] == "target" or info[2] == "focus" or info[2] == "targettarget" or info[3] == "focustarget") end,
+ },
+ sep = {
+ order = 6.5,
+ type = "description",
+ name = "",
+ width = "full",
+ 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,
},
alpha = {
order = 7,
@@ -2333,20 +2835,20 @@ local function loadUnitOptions()
},
},
},
- -- This might need some help text indicating why the options disappeared, will see.
- barComboPoints = {
+ -- SOUL SHARDS
+ barSouls = {
order = 4,
type = "group",
inline = true,
- name = L["Combo points"],
- hidden = function(info) return not getVariable(info[2], "comboPoints", nil, "isBar") or not getVariable(info[2], nil, nil, "comboPoints") end,
+ name = L["Soul Shards"],
+ hidden = function(info) return playerClass ~= "WARLOCK" or not getVariable(info[2], "soulShards", nil, "isBar") or not getVariable(info[2], nil, nil, "soulShards") end,
args = {
enabled = {
order = 1,
type = "toggle",
- name = string.format(L["Enable %s"], L["Combo points"]),
+ name = string.format(L["Enable %s"], L["Soul Shards"]),
hidden = false,
- arg = "comboPoints.enabled",
+ arg = "soulShards.enabled",
},
growth = {
order = 2,
@@ -2354,23 +2856,30 @@ local function loadUnitOptions()
name = L["Growth"],
values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
hidden = false,
- arg = "comboPoints.growth",
+ arg = "soulShards.growth",
+ },
+ showAlways = {
+ order = 3,
+ type = "toggle",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "soulShards.showAlways",
},
},
},
- comboPoints = {
+ soulShards = {
order = 4,
type = "group",
inline = true,
- name = L["Combo points"],
- hidden = function(info) if( info[2] == "global" or getVariable(info[2], "comboPoints", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
+ name = L["Soul Shards"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "soulShards", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
args = {
enabled = {
order = 0,
type = "toggle",
- name = string.format(L["Enable %s"], L["Combo points"]),
+ name = string.format(L["Enable %s"], L["Soul Shards"]),
hidden = false,
- arg = "comboPoints.enabled",
+ arg = "soulShards.enabled",
},
sep1 = {
order = 1,
@@ -2385,7 +2894,7 @@ local function loadUnitOptions()
name = L["Growth"],
values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
hidden = false,
- arg = "comboPoints.growth",
+ arg = "soulShards.growth",
},
size = {
order = 2,
@@ -2393,15 +2902,15 @@ local function loadUnitOptions()
name = L["Size"],
min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
hidden = hideAdvancedOption,
- arg = "comboPoints.size",
+ arg = "soulShards.size",
},
spacing = {
order = 3,
type = "range",
name = L["Spacing"],
- min = -20, max = 20, step = 1, softMin = -10, softMax = 10,
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
hidden = hideAdvancedOption,
- arg = "comboPoints.spacing",
+ arg = "soulShards.spacing",
},
sep2 = {
order = 4,
@@ -2416,1170 +2925,3283 @@ local function loadUnitOptions()
name = L["Anchor point"],
values = positionList,
hidden = false,
- arg = "comboPoints.anchorPoint",
+ arg = "soulShards.anchorPoint",
},
x = {
order = 6,
type = "range",
name = L["X Offset"],
- min = -20, max = 20, step = 1,
+ min = -30, max = 30, step = 1,
hidden = false,
- arg = "comboPoints.x",
+ arg = "soulShards.x",
},
y = {
order = 7,
type = "range",
name = L["Y Offset"],
- min = -20, max = 20, step = 1,
+ min = -30, max = 30, step = 1,
hidden = false,
- arg = "comboPoints.y",
+ arg = "soulShards.y",
},
},
},
- combatText = {
- order = 5,
+ -- ARCANE CHARGES
+ barArcane = {
+ order = 4,
type = "group",
inline = true,
- name = L["Combat text"],
- hidden = hideRestrictedOption,
+ name = L["Arcane Charges"],
+ hidden = function(info) return playerClass ~= "MAGE" or not getVariable(info[2], "arcaneCharges", nil, "isBar") or not getVariable(info[2], nil, nil, "arcaneCharges") end,
args = {
- combatText = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Arcane Charges"]),
+ hidden = false,
+ arg = "arcaneCharges.enabled",
+ },
+ growth = {
+ order = 2,
+ type = "select",
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
+ hidden = false,
+ arg = "arcaneCharges.growth",
+ },
+ showAlways = {
+ order = 3,
+ type = "toggle",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "arcaneCharges.showAlways",
+ },
+ },
+ },
+ arcaneCharges = {
+ order = 4,
+ type = "group",
+ inline = true,
+ name = L["Arcane Charges"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "arcaneCharges", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
+ args = {
+ enabled = {
order = 0,
type = "toggle",
- name = string.format(L["Enable %s"], L["Combat text"]),
- desc = L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."],
- arg = "combatText.enabled",
+ name = string.format(L["Enable %s"], L["Arcane Charges"]),
hidden = false,
+ arg = "arcaneCharges.enabled",
},
- sep = {
+ sep1 = {
order = 1,
type = "description",
name = "",
width = "full",
hidden = hideAdvancedOption,
},
- anchorPoint = {
+ growth = {
+ order = 2,
+ type = "select",
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
+ hidden = false,
+ arg = "arcaneCharges.growth",
+ },
+ size = {
+ order = 2,
+ type = "range",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
+ hidden = hideAdvancedOption,
+ arg = "arcaneCharges.size",
+ },
+ spacing = {
order = 3,
+ type = "range",
+ name = L["Spacing"],
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
+ hidden = hideAdvancedOption,
+ arg = "arcaneCharges.spacing",
+ },
+ sep2 = {
+ order = 4,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
+ },
+ anchorPoint = {
+ order = 5,
type = "select",
name = L["Anchor point"],
values = positionList,
- arg = "combatText.anchorPoint",
- hidden = hideAdvancedOption,
+ hidden = false,
+ arg = "arcaneCharges.anchorPoint",
},
x = {
- order = 4,
+ order = 6,
type = "range",
name = L["X Offset"],
- min = -50, max = 50, step = 1,
- arg = "combatText.x",
- hidden = hideAdvancedOption,
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "arcaneCharges.x",
},
y = {
- order = 5,
+ order = 7,
type = "range",
name = L["Y Offset"],
- min = -50, max = 50, step = 1,
- arg = "combatText.y",
- hidden = hideAdvancedOption,
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "arcaneCharges.y",
},
},
},
- },
- },
- attributes = {
- order = 1.5,
- type = "group",
- name = function(info) return L.units[info[#(info) - 1]] end,
- hidden = function(info)
- local unit = info[#(info) - 1]
- return unit ~= "raid" and unit ~= "raidpet" and unit ~= "party" and unit ~= "mainassist" and unit ~= "maintank" and unit ~= "boss" and unit ~= "arena"
- end,
- set = function(info, value)
- setUnit(info, value)
-
- ShadowUF.Units:ReloadHeader(info[2])
- ShadowUF.modules.movers:Update()
- end,
- get = getUnit,
- args = {
- show = {
- order = 0.5,
+ -- HOLY POWER
+ barHolyPower = {
+ order = 4,
type = "group",
inline = true,
- name = L["Visibility"],
- hidden = function(info) return info[2] ~= "party" and info[2] ~= "raid" end,
+ name = L["Holy Power"],
+ hidden = function(info) return playerClass ~= "PALADIN" or not getVariable(info[2], "holyPower", nil, "isBar") or not getVariable(info[2], nil, nil, "holyPower") end,
args = {
- showPlayer = {
- order = 0,
- type = "toggle",
- name = L["Show player in party"],
- desc = L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."],
- hidden = function(info) return info[2] ~= "party" end,
- arg = "showPlayer",
- },
- hideSemiRaid = {
+ enabled = {
order = 1,
type = "toggle",
- name = L["Hide in 6-man raid"],
- desc = L["Party frames are hidden while in a raid group with more than 5 people inside."],
- hidden = function(info) return info[2] ~= "party" end,
- set = function(info, value)
- if( value ) then
- setVariable(info[2], nil, nil, "hideAnyRaid", false)
- end
-
- setVariable(info[2], nil, nil, "hideSemiRaid", value)
- ShadowUF.Units:ReloadHeader(info[#(info) - 3])
- end,
- arg = "hideSemiRaid",
+ name = string.format(L["Enable %s"], L["Holy Power"]),
+ hidden = false,
+ arg = "holyPower.enabled",
},
- hideRaid = {
+ growth = {
order = 2,
+ type = "select",
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
+ hidden = false,
+ arg = "holyPower.growth",
+ },
+ showAlways = {
+ order = 3,
type = "toggle",
- name = L["Hide in any raid"],
- desc = L["Party frames are hidden while in any sort of raid no matter how many people."],
- hidden = function(info) return info[2] ~= "party" end,
- set = function(info, value)
- if( value ) then
- setVariable(info[2], nil, nil, "hideSemiRaid", false)
- end
-
- setVariable(info[2], nil, nil, "hideAnyRaid", value)
- ShadowUF.Units:ReloadHeader(info[#(info) - 3])
- end,
- arg = "hideAnyRaid",
- },
- separateFrames = {
- order = 3,
- type = "toggle",
- name = L["Separate raid frames"],
- 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."],
- hidden = function(info) return info[2] ~= "raid" end,
- arg = "frameSplit",
- },
- showInRaid = {
- order = 4,
- type = "toggle",
- name = L["Show party as raid"],
- hidden = hideRaidOption,
- set = function(info, value)
- setUnit(info, value)
-
- ShadowUF.Units:ReloadHeader("party")
- ShadowUF.Units:ReloadHeader("raid")
- ShadowUF.modules.movers:Update()
- end,
- arg = "showParty",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "holyPower.showAlways",
},
},
},
- general = {
- order = 1,
+ holyPower = {
+ order = 4,
type = "group",
inline = true,
- name = L["General"],
- hidden = false,
+ name = L["Holy Power"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "holyPower", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
args = {
- offset = {
- order = 2,
- type = "range",
- name = L["Row offset"],
- desc = L["Spacing between each row"],
- min = -10, max = 100, step = 1,
- arg = "offset",
- },
- attribPoint = {
- order = 3,
- type = "select",
- name = L["Row growth"],
- desc = L["How the rows should grow when new group members are added."],
- values = {["TOP"] = L["Down"], ["BOTTOM"] = L["Up"], ["LEFT"] = L["Right"], ["RIGHT"] = L["Left"]},
- arg = "attribPoint",
- set = function(info, value)
- -- If you set the frames to grow left, the columns have to grow down or up as well
- local attribAnchorPoint = getVariable(info[2], nil, nil, "attribAnchorPoint")
- if( ( value == "LEFT" or value == "RIGHT" ) and attribAnchorPoint ~= "BOTTOM" and attribAnchorPoint ~= "TOP" ) then
- ShadowUF.db.profile.units[info[2]].attribAnchorPoint = "BOTTOM"
- elseif( ( value == "TOP" or value == "BOTTOM" ) and attribAnchorPoint ~= "LEFT" and attribAnchorPoint ~= "RIGHT" ) then
- ShadowUF.db.profile.units[info[2]].attribAnchorPoint = "RIGHT"
- end
-
- setUnit(info, value)
-
- local position = ShadowUF.db.profile.positions[info[2]]
- if( position.top and position.bottom ) then
- local point = ShadowUF.db.profile.units[info[2]].attribAnchorPoint == "RIGHT" and "RIGHT" or "LEFT"
- position.point = (ShadowUF.db.profile.units[info[2]].attribPoint == "BOTTOM" and "BOTTOM" or "TOP") .. point
- position.y = ShadowUF.db.profile.units[info[2]].attribPoint == "BOTTOM" and position.bottom or position.top
- end
-
- ShadowUF.Units:ReloadHeader(info[2])
- ShadowUF.modules.movers:Update()
- end,
+ enabled = {
+ order = 0,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Holy Power"]),
+ hidden = false,
+ arg = "holyPower.enabled",
},
- sep2 = {
- order = 4,
+ sep1 = {
+ order = 1,
type = "description",
name = "",
width = "full",
+ hidden = hideAdvancedOption,
+ },
+ growth = {
+ order = 2,
+ type = "select",
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
hidden = false,
+ arg = "holyPower.growth",
},
- columnSpacing = {
- order = 5,
+ size = {
+ order = 2,
type = "range",
- name = L["Column spacing"],
- min = -30, max = 100, step = 1,
- hidden = hideRaidOrAdvancedOption,
- arg = "columnSpacing",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
+ hidden = hideAdvancedOption,
+ arg = "holyPower.size",
},
- attribAnchorPoint = {
- order = 6,
- type = "select",
- name = L["Column growth"],
- desc = L["How the frames should grow when a new column is added."],
- values = function(info)
- local attribPoint = getVariable(info[2], nil, nil, "attribPoint")
- if( attribPoint == "LEFT" or attribPoint == "RIGHT" ) then
- return {["TOP"] = L["Down"], ["BOTTOM"] = L["Up"]}
- end
-
- return {["LEFT"] = L["Right"], ["RIGHT"] = L["Left"]}
- end,
- hidden = hideRaidOrAdvancedOption,
- set = function(info, value)
- -- If you set the frames to grow left, the columns have to grow down or up as well
- local attribPoint = getVariable(info[2], nil, nil, "attribPoint")
- if( ( value == "LEFT" or value == "RIGHT" ) and attribPoint ~= "BOTTOM" and attribPoint ~= "TOP" ) then
- ShadowUF.db.profile.units[info[2]].attribPoint = "BOTTOM"
- end
-
- setUnit(info, value)
-
- ShadowUF.Units:ReloadHeader(info[2])
- ShadowUF.modules.movers:Update()
- end,
- arg = "attribAnchorPoint",
+ spacing = {
+ order = 3,
+ type = "range",
+ name = L["Spacing"],
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
+ hidden = hideAdvancedOption,
+ arg = "holyPower.spacing",
},
- sep3 = {
- order = 7,
+ sep2 = {
+ order = 4,
type = "description",
name = "",
width = "full",
- hidden = false,
- },
- maxColumns = {
- order = 8,
- type = "range",
- name = L["Max columns"],
- min = 1, max = 20, step = 1,
- arg = "maxColumns",
- hidden = function(info) return info[2] == "boss" or info[2] == "arena" or hideSplitOrRaidOption(info) end,
- },
- unitsPerColumn = {
- order = 8,
- type = "range",
- name = L["Units per column"],
- min = 1, max = 40, step = 1,
- arg = "unitsPerColumn",
- hidden = function(info) return info[2] == "boss" or info[2] == "arena" or hideSplitOrRaidOption(info) end,
+ hidden = hideAdvancedOption,
},
- partyPerColumn = {
- order = 9,
- type = "range",
- name = L["Units per column"],
- min = 1, max = 5, step = 1,
- arg = "unitsPerColumn",
- hidden = function(info) return info[2] ~= "party" or not ShadowUF.db.profile.advanced end,
+ anchorPoint = {
+ order = 5,
+ type = "select",
+ name = L["Anchor point"],
+ values = positionList,
+ hidden = false,
+ arg = "holyPower.anchorPoint",
},
- groupsPerRow = {
- order = 8,
+ x = {
+ order = 6,
type = "range",
- name = L["Groups per row"],
- desc = L["How many groups should be shown per row."],
- min = 1, max = 8, step = 1,
- arg = "groupsPerRow",
- hidden = function(info) return info[2] ~= "raid" or not ShadowUF.db.profile.units.raid.frameSplit end,
+ name = L["X Offset"],
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "holyPower.x",
},
- groupSpacing = {
- order = 9,
+ y = {
+ order = 7,
type = "range",
- name = L["Group row spacing"],
- desc = L["How much spacing should be between each new row of groups."],
- min = -50, max = 50, step = 1,
- arg = "groupSpacing",
- hidden = function(info) return info[2] ~= "raid" or not ShadowUF.db.profile.units.raid.frameSplit end,
+ name = L["Y Offset"],
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "holyPower.y",
},
},
},
- sort = {
- order = 2,
+ -- SHADOW ORBS
+ barShadowOrbs = {
+ order = 4,
type = "group",
inline = true,
- name = L["Sorting"],
- hidden = function(info) return info[2] == "boss" or info[2] == "arena" or ( info[2] ~= "raid" and not ShadowUF.db.profile.advanced ) end,
+ name = L["Shadow Orbs"],
+ hidden = function(info) return playerClass ~= "PRIEST" or not getVariable(info[2], "shadowOrbs", nil, "isBar") or not getVariable(info[2], nil, nil, "shadowOrbs") end,
args = {
- sortMethod = {
- order = 2,
- type = "select",
- name = L["Sort method"],
- values = {["INDEX"] = L["Index"], ["NAME"] = L["Name"]},
- arg = "sortMethod",
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Shadow Orbs"]),
hidden = false,
+ arg = "shadowOrbs.enabled",
},
- sortOrder = {
+ growth = {
order = 2,
type = "select",
- name = L["Sort order"],
- values = {["ASC"] = L["Ascending"], ["DESC"] = L["Descending"]},
- arg = "sortOrder",
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
+ hidden = false,
+ arg = "shadowOrbs.growth",
+ },
+ showAlways = {
+ order = 3,
+ type = "toggle",
+ name = L["Don't hide when empty"],
hidden = false,
+ arg = "shadowOrbs.showAlways",
},
},
},
- raid = {
- order = 3,
+ shadowOrbs = {
+ order = 4,
type = "group",
inline = true,
- name = L["Groups"],
- hidden = hideRaidOption,
+ name = L["Holy Power"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "shadowOrbs", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
args = {
- groupBy = {
- order = 4,
- type = "select",
- name = L["Group by"],
- values = {["GROUP"] = L["Group number"], ["CLASS"] = L["Class"]},
- arg = "groupBy",
- hidden = hideSplitOrRaidOption,
- },
- sortMethod = {
- order = 5,
- type = "select",
- name = L["Sort method"],
- values = {["INDEX"] = L["Index"], ["NAME"] = L["Name"]},
- arg = "sortMethod",
+ enabled = {
+ order = 0,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Shadow Orbs"]),
hidden = false,
+ arg = "shadowOrbs.enabled",
},
- sortOrder = {
- order = 6,
+ sep1 = {
+ order = 1,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
+ },
+ growth = {
+ order = 2,
type = "select",
- name = L["Sort order"],
- values = {["ASC"] = L["Ascending"], ["DESC"] = L["Descending"]},
- arg = "sortOrder",
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
hidden = false,
+ arg = "shadowOrbs.growth",
},
- selectedGroups = {
- order = 7,
- type = "multiselect",
- name = L["Groups to show"],
- 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)},
- set = function(info, key, value)
- local tbl = getVariable(info[2], nil, nil, "filters")
- tbl[key] = value
-
- setVariable(info[2], "filters", nil, tbl)
- ShadowUF.Units:ReloadHeader(info[2])
- ShadowUF.modules.movers:Update()
- end,
- get = function(info, key)
- return getVariable(info[2], nil, nil, "filters")[key]
- end,
- hidden = function(info) return info[2] ~= "raid" and info[2] ~= "raidpet" end,
- },
- },
- },
- },
- },
- frame = {
- order = 2,
- name = L["Frame"],
- type = "group",
- hidden = isModifiersSet,
- set = setUnit,
- get = getUnit,
- args = {
- size = {
- order = 0,
- type = "group",
- inline = true,
- name = L["Size"],
- hidden = false,
- set = function(info, value)
- setUnit(info, value)
- ShadowUF.modules.movers:Update()
- end,
- args = {
- scale = {
- order = 0,
+ size = {
+ order = 2,
type = "range",
- name = L["Scale"],
- min = 0.50, max = 1.50, step = 0.01,
- isPercent = true,
- arg = "scale",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
+ hidden = hideAdvancedOption,
+ arg = "shadowOrbs.size",
},
- height = {
- order = 1,
+ spacing = {
+ order = 3,
type = "range",
- name = L["Height"],
- min = 0, max = 100, step = 1,
- arg = "height",
+ name = L["Spacing"],
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
+ hidden = hideAdvancedOption,
+ arg = "shadowOrbs.spacing",
},
- width = {
- order = 2,
- type = "range",
- name = L["Width"],
- min = 0, max = 300, step = 1,
- arg = "width",
+ sep2 = {
+ order = 4,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
},
- },
- },
- anchor = {
- order = 1,
- type = "group",
- inline = true,
- hidden = function(info) return info[2] == "global" end,
- name = L["Anchor to another frame"],
- set = setPosition,
- get = getPosition,
- args = {
anchorPoint = {
- order = 0.50,
+ order = 5,
type = "select",
name = L["Anchor point"],
values = positionList,
hidden = false,
- get = function(info)
- local position = ShadowUF.db.profile.positions[info[2]]
- if( ShadowUF.db.profile.advanced ) then
- return position[info[#(info)]]
- end
-
-
- return position.movedAnchor or position[info[#(info)]]
- end,
- },
- anchorTo = {
- order = 1,
- type = "select",
- name = L["Anchor to"],
- values = getAnchorParents,
- hidden = false,
- },
- sep = {
- order = 2,
- type = "description",
- name = "",
- width = "full",
- hidden = false,
+ arg = "shadowOrbs.anchorPoint",
},
x = {
- order = 3,
- type = "input",
+ order = 6,
+ type = "range",
name = L["X Offset"],
- validate = checkNumber,
- set = setNumber,
- get = getString,
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "shadowOrbs.x",
},
y = {
- order = 4,
- type = "input",
+ order = 7,
+ type = "range",
name = L["Y Offset"],
- validate = checkNumber,
- set = setNumber,
- get = getString,
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "shadowOrbs.y",
},
},
},
- orHeader = {
- order = 1.5,
- type = "header",
- name = L["Or you can set a position manually"],
- hidden = function(info) if( info[2] == "global" or hideAdvancedOption() ) then return true else return false end end,
- },
- position = {
- order = 2,
+ -- Chi
+ barChi = {
+ order = 4,
type = "group",
- hidden = function(info) if( info[2] == "global" or hideAdvancedOption() ) then return true else return false end end,
inline = true,
- name = L["Manual position"],
- set = setPosition,
- get = getPosition,
+ name = L["Chi"],
+ hidden = function(info) return playerClass ~= "MONK" or not getVariable(info[2], "chi", nil, "isBar") or not getVariable(info[2], nil, nil, "chi") end,
args = {
- point = {
- order = 0,
- type = "select",
- name = L["Point"],
- values = pointPositions,
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Chi"]),
hidden = false,
+ arg = "chi.enabled",
},
- anchorTo = {
- order = 0.50,
+ growth = {
+ order = 2,
type = "select",
- name = L["Anchor to"],
- values = getAnchorParents,
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
hidden = false,
+ arg = "chi.growth",
},
- relativePoint = {
+ showAlways = {
+ order = 3,
+ type = "toggle",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "chi.showAlways",
+ },
+ },
+ },
+ chi = {
+ order = 4,
+ type = "group",
+ inline = true,
+ name = L["Chi"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "chi", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
+ args = {
+ enabled = {
+ order = 0,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Chi"]),
+ hidden = false,
+ arg = "chi.enabled",
+ },
+ sep1 = {
order = 1,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
+ },
+ growth = {
+ order = 2,
type = "select",
- name = L["Relative point"],
- values = pointPositions,
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
hidden = false,
+ arg = "chi.growth",
},
- sep = {
+ size = {
order = 2,
+ type = "range",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
+ hidden = hideAdvancedOption,
+ arg = "chi.size",
+ },
+ spacing = {
+ order = 3,
+ type = "range",
+ name = L["Spacing"],
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
+ hidden = hideAdvancedOption,
+ arg = "chi.spacing",
+ },
+ sep2 = {
+ order = 4,
type = "description",
name = "",
width = "full",
+ hidden = hideAdvancedOption,
+ },
+ anchorPoint = {
+ order = 5,
+ type = "select",
+ name = L["Anchor point"],
+ values = positionList,
hidden = false,
+ arg = "chi.anchorPoint",
},
x = {
- order = 3,
- type = "input",
+ order = 6,
+ type = "range",
name = L["X Offset"],
- validate = checkNumber,
- set = setNumber,
- get = getString,
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "chi.x",
},
y = {
- order = 4,
- type = "input",
+ order = 7,
+ type = "range",
name = L["Y Offset"],
- validate = checkNumber,
- set = setNumber,
- get = getString,
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "chi.y",
},
},
},
- },
- },
- bars = {
- order = 3,
- name = L["Bars"],
- type = "group",
- hidden = isModifiersSet,
- set = setUnit,
- get = getUnit,
- args = {
- bar = {
- order = 1,
+ -- COMBO POINTS
+ barComboPoints = {
+ order = 4,
type = "group",
inline = true,
- name = L["General"],
- hidden = false,
+ name = L["Combo points"],
+ hidden = function(info) return not getVariable(info[2], "comboPoints", nil, "isBar") or not getVariable(info[2], nil, nil, "comboPoints") end,
args = {
- runeBar = {
- order = 1,
- type = "toggle",
- name = string.format(L["Enable %s"], L["Rune bar"]),
- desc = L["Adds rune bars and timers before runes refresh to the player frame."],
- hidden = hideRestrictedOption,
- arg = "runeBar.enabled",
- },
- totemBar = {
- order = 1.5,
- type = "toggle",
- name = string.format(L["Enable %s"], ShadowUF.modules.totemBar.moduleName),
- desc = function(info)
- return select(2, UnitClass("player")) == "SHAMAN" and L["Adds totem bars with timers before they expire to the player frame."] or L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."]
- end,
- hidden = hideRestrictedOption,
- arg = "totemBar.enabled",
- },
- druidBar = {
+ enabled = {
order = 1,
type = "toggle",
- name = string.format(L["Enable %s"], L["Druid mana bar"]),
- 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."],
- hidden = hideRestrictedOption,
- arg = "druidBar.enabled",
+ name = string.format(L["Enable %s"], L["Combo points"]),
+ hidden = false,
+ arg = "comboPoints.enabled",
},
- xpBar = {
+ growth = {
order = 2,
- type = "toggle",
- name = string.format(L["Enable %s"], L["XP/Rep bar"]),
- desc = L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."],
- hidden = hideRestrictedOption,
- arg = "xpBar.enabled",
+ type = "select",
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
+ hidden = false,
+ arg = "comboPoints.growth",
},
- sep = {
+ showAlways = {
order = 3,
- type = "description",
- name = "",
- hidden = function(info) return playerClass ~= "DRUID" and playerClass ~= "SHAMAN" and playerClass ~= "DEATHKNIGHT" and info[2] ~= "player" end,
- },
- powerBar = {
- order = 4,
- type = "toggle",
- name = string.format(L["Enable %s"], L["Power bar"]),
- arg = "powerBar.enabled",
- },
- predictPower = {
- order = 5,
type = "toggle",
- name = L["Enable quick power"],
- desc = L["Turns fast updating of the power bar on giving you more up to date power information than normal."],
- arg = "powerBar.predicted",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "comboPoints.showAlways",
},
},
},
- healthBar = {
- order = 2,
+ comboPoints = {
+ order = 4,
type = "group",
inline = true,
- name = L["Health bar"],
- hidden = false,
+ name = L["Combo points"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "comboPoints", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
args = {
enabled = {
- order = 1,
- type = "toggle",
- name = string.format(L["Enable %s"], L["Health bar"]),
- arg = "healthBar.enabled",
- },
- predictedHealth = {
- order = 3,
+ order = 0,
type = "toggle",
- name = L["Enable quick health"],
- desc = L["Turns on fast updating of health bars giving you more up to date health info."],
- arg = "healthBar.predicted",
+ name = string.format(L["Enable %s"], L["Combo points"]),
+ hidden = false,
+ arg = "comboPoints.enabled",
},
- sep = {
- order = 3.5,
+ sep1 = {
+ order = 1,
type = "description",
name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
},
- healthColor = {
- order = 4,
+ growth = {
+ order = 2,
type = "select",
- name = L["Color health by"],
- desc = L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."],
- values = {["class"] = L["Class"], ["static"] = L["Static"], ["percent"] = L["Health percent"]},
- arg = "healthBar.colorType",
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
+ hidden = false,
+ arg = "comboPoints.growth",
},
- reactionPet = {
- order = 5,
- type = "toggle",
- name = L["Color by happiness"],
- desc = L["Colors the health bar by how happy your pet is."],
- arg = "healthBar.reactionType",
- set = function(info, value) setVariable(info[2], "healthBar", nil, "reactionType", value and "happiness" or "none") end,
- get = function(info) return getVariable(info[2], "healthBar", nil, "reactionType") == "happiness" and true or false end,
- hidden = function(info) return info[2] ~= "pet" end,
+ size = {
+ order = 2,
+ type = "range",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
+ hidden = hideAdvancedOption,
+ arg = "comboPoints.size",
},
- reaction = {
+ spacing = {
+ order = 3,
+ type = "range",
+ name = L["Spacing"],
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
+ hidden = hideAdvancedOption,
+ arg = "comboPoints.spacing",
+ },
+ sep2 = {
+ order = 4,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
+ },
+ anchorPoint = {
order = 5,
type = "select",
- name = L["Color by reaction on"],
- desc = L["When to color the health bar by the units reaction, overriding the color health by option."],
- arg = "healthBar.reactionType",
- values = {["none"] = L["Never (Disabled)"], ["player"] = L["Players only"], ["npc"] = L["NPCs only"], ["both"] = L["Both"]},
- hidden = function(info) return info[2] == "player" or info[2] == "pet" end,
+ name = L["Anchor point"],
+ values = positionList,
+ hidden = false,
+ arg = "comboPoints.anchorPoint",
},
- colorAggro = {
+ x = {
order = 6,
- type = "toggle",
- name = L["Color on aggro"],
- desc = L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."],
- arg = "healthBar.colorAggro",
- hidden = hideRestrictedOption,
- },
- },
- },
- incHeal = {
- order = 3,
- type = "group",
- inline = true,
- name = L["Incoming heals"],
- hidden = hideRestrictedOption,
- disabled = function(info) return not getVariable(info[2], "healthBar", nil, "enabled") end,
- args = {
- enabled = {
- order = 1,
- type = "toggle",
- name = string.format(L["Enable %s"], L["Incoming heals"]),
- desc = L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."],
- arg = "incHeal.enabled",
+ type = "range",
+ name = L["X Offset"],
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "comboPoints.x",
},
- cap = {
- order = 2,
+ y = {
+ order = 7,
type = "range",
- name = L["Outside bar limit"],
- 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."],
- min = 1, max = 1.50, step = 0.05, isPercent = true,
- arg = "incHeal.cap",
+ name = L["Y Offset"],
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "comboPoints.y",
},
},
},
- emptyBar = {
+ -- COMBO POINTS
+ barAuraPoints = {
order = 4,
type = "group",
inline = true,
- name = L["Empty bar"],
- hidden = false,
+ name = L["Aura Combo Points"],
+ 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,
args = {
enabled = {
order = 1,
type = "toggle",
- name = string.format(L["Enable %s"], L["Empty bar"]),
- desc = L["Adds an empty bar that you can put text into as a way of uncluttering other bars."],
- arg = "emptyBar.enabled",
- width = "full",
+ name = string.format(L["Enable %s"], L["Aura Combo Points"]),
+ hidden = false,
+ arg = "auraPoints.enabled",
},
- reaction = {
+ growth = {
order = 2,
type = "select",
- name = L["Color by reaction on"],
- desc = L["When to color the empty bar by reaction, overriding the default color by option."],
- arg = "emptyBar.reactionType",
- values = {["none"] = L["Never (Disabled)"], ["player"] = L["Players only"], ["npc"] = L["NPCs only"], ["both"] = L["Both"]},
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
+ hidden = false,
+ arg = "auraPoints.growth",
},
- colorType = {
+ showAlways = {
order = 3,
type = "toggle",
- name = L["Color by class"],
- desc = L["Players will be colored by class, "],
- arg = "emptyBar.class",
- },
- overrideColor = {
- order = 4,
- type = "color",
- name = L["Background color"],
- disabled = function(info)
- local emptyBar = getVariable(info[2], nil, nil, "emptyBar")
- return emptyBar.class and emptyBar.reaciton
- end,
- set = function(info, r, g, b)
- local color = getUnit(info) or {}
- color.r = r
- color.g = g
- color.b = b
-
- setUnit(info, color)
- end,
- get = function(info)
- local color = getUnit(info)
- if( not color ) then
- return 0, 0, 0
- end
-
- return color.r, color.g, color.b
-
- end,
- arg = "emptyBar.backgroundColor",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "auraPoints.showAlways",
},
},
},
- castBar = {
- order = 5,
+ auraPoints = {
+ order = 4,
type = "group",
inline = true,
- name = L["Cast bar"],
- hidden = hideRestrictedOption,
+ name = L["Aura Combo Points"],
+ 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,
args = {
enabled = {
- order = 1,
+ order = 0,
type = "toggle",
- name = string.format(L["Enable %s"], L["Cast bar"]),
- 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,
+ name = string.format(L["Enable %s"], L["Aura Combo Points"]),
hidden = false,
- arg = "castBar.enabled",
+ arg = "auraPoints.enabled",
},
- autoHide = {
- order = 2,
- type = "toggle",
- name = L["Hide bar when empty"],
- desc = L["Hides the cast bar if there is no cast active."],
- hidden = false,
- arg = "castBar.autoHide",
+ sep1 = {
+ order = 1,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
},
- castIcon = {
- order = 2.5,
+ growth = {
+ order = 2,
type = "select",
- name = L["Cast icon"],
- arg = "castBar.icon",
- values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["HIDE"] = L["Disabled"]},
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
hidden = false,
+ arg = "auraPoints.growth",
},
- castName = {
- order = 3,
- type = "header",
- name = L["Cast name"],
+ size = {
+ order = 2,
+ type = "range",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
hidden = hideAdvancedOption,
+ arg = "auraPoints.size",
},
- nameEnabled = {
- order = 4,
- type = "toggle",
- name = L["Show cast name"],
- arg = "castBar.name.enabled",
+ spacing = {
+ order = 3,
+ type = "range",
+ name = L["Spacing"],
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
hidden = hideAdvancedOption,
+ arg = "auraPoints.spacing",
},
- rankEnabled = {
- order = 4.5,
- type = "toggle",
- name = L["Show cast rank"],
- arg = "castBar.name.rank",
+ sep2 = {
+ order = 4,
+ type = "description",
+ name = "",
+ width = "full",
hidden = hideAdvancedOption,
- disabled = disableIfCastName,
},
- nameAnchor = {
+ anchorPoint = {
order = 5,
type = "select",
name = L["Anchor point"],
- desc = L["Where to anchor the cast name text."],
- values = {["CLI"] = L["Inside Center Left"], ["CRI"] = L["Inside Center Right"]},
- hidden = hideAdvancedOption,
- arg = "castBar.name.anchorPoint",
+ values = positionList,
+ hidden = false,
+ arg = "auraPoints.anchorPoint",
},
- nameSep = {
+ x = {
order = 6,
- type = "description",
- name = "",
- width = "full",
- hidden = hideAdvancedOption,
- },
- nameSize = {
- order = 7,
- type = "range",
- name = L["Size"],
- desc = L["Let's you modify the base font size to either make it larger or smaller."],
- type = "range",
- min = -10, max = 10, step = 1, softMin = -5, softMax = 5,
- hidden = hideAdvancedOption,
- arg = "castBar.name.size",
- },
- nameX = {
- order = 8,
type = "range",
name = L["X Offset"],
- min = -20, max = 20, step = 1,
- hidden = hideAdvancedOption,
- arg = "castBar.name.x",
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "auraPoints.x",
},
- nameY = {
- order = 9,
+ y = {
+ order = 7,
type = "range",
name = L["Y Offset"],
- min = -20, max = 20, step = 1,
- hidden = hideAdvancedOption,
- arg = "castBar.name.y",
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "auraPoints.y",
},
- castTime = {
- order = 10,
- type = "header",
- name = L["Cast time"],
- hidden = hideAdvancedOption,
- },
- timeEnabled = {
- order = 11,
+ },
+ },
+ combatText = {
+ order = 5,
+ type = "group",
+ inline = true,
+ name = L["Combat text"],
+ hidden = hideRestrictedOption,
+ args = {
+ combatText = {
+ order = 0,
type = "toggle",
- name = L["Show cast time"],
- arg = "castBar.time.enabled",
- hidden = hideAdvancedOption,
- },
- timeAnchor = {
- order = 12,
- type = "select",
- name = L["Anchor point"],
- desc = L["Where to anchor the cast time text."],
- values = {["CLI"] = L["Inside Center Left"], ["CRI"] = L["Inside Center Right"]},
- hidden = hideAdvancedOption,
- arg = "castBar.time.anchorPoint",
+ name = string.format(L["Enable %s"], L["Combat text"]),
+ desc = L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."],
+ arg = "combatText.enabled",
+ hidden = false,
},
- timeSep = {
- order = 13,
+ sep = {
+ order = 1,
type = "description",
name = "",
width = "full",
hidden = hideAdvancedOption,
},
- timeSize = {
- order = 14,
- type = "range",
- name = L["Size"],
- desc = L["Let's you modify the base font size to either make it larger or smaller."],
- type = "range",
- min = -10, max = 10, step = 1, softMin = -5, softMax = 5,
+ anchorPoint = {
+ order = 3,
+ type = "select",
+ name = L["Anchor point"],
+ values = positionList,
+ arg = "combatText.anchorPoint",
hidden = hideAdvancedOption,
- arg = "castBar.time.size",
},
- timeX = {
- order = 15,
+ x = {
+ order = 4,
type = "range",
name = L["X Offset"],
- min = -20, max = 20, step = 1,
+ min = -50, max = 50, step = 1,
+ arg = "combatText.x",
hidden = hideAdvancedOption,
- arg = "castBar.time.x",
},
- timeY = {
- order = 16,
+ y = {
+ order = 5,
type = "range",
name = L["Y Offset"],
- min = -20, max = 20, step = 1,
+ min = -50, max = 50, step = 1,
+ arg = "combatText.y",
hidden = hideAdvancedOption,
- arg = "castBar.time.y",
},
},
},
},
},
- widgetSize = {
- order = 4,
- name = L["Widget size"],
+ attributes = {
+ order = 1.5,
type = "group",
- hidden = isModifiersSet,
- set = setUnit,
+ name = function(info)
+ return L.shortUnits[info[#(info) - 1]] or L.units[info[#(info) - 1]]
+ end,
+ hidden = function(info)
+ local unit = info[#(info) - 1]
+ return unit ~= "raid" and unit ~= "raidpet" and unit ~= "party" and unit ~= "mainassist" and unit ~= "maintank" and not ShadowUF.Units.zoneUnits[unit]
+ end,
+ set = function(info, value)
+ setUnit(info, value)
+
+ ShadowUF.Units:ReloadHeader(info[2])
+ ShadowUF.modules.movers:Update()
+ end,
get = getUnit,
args = {
- help = {
- order = 0,
+ show = {
+ order = 0.5,
type = "group",
- name = L["Help"],
inline = true,
- hidden = false,
+ name = L["Visibility"],
+ hidden = function(info) return info[2] ~= "party" and info[2] ~= "raid" end,
args = {
- help = {
+ showPlayer = {
order = 0,
- type = "description",
- 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."],
+ type = "toggle",
+ name = L["Show player in party"],
+ desc = L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."],
+ hidden = function(info) return info[2] ~= "party" end,
+ arg = "showPlayer",
},
- },
- },
- portrait = {
- order = 0.5,
- type = "group",
- name = L["Portrait"],
- inline = true,
- hidden = false,
- args = {
- enableBar = {
+ hideSemiRaidParty = {
order = 1,
type = "toggle",
- name = L["Show as bar"],
- 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."],
- arg = "$parent.isBar",
- },
- sep = {
- order = 1.5,
- type = "description",
- name = "",
- width = "full",
- hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
+ name = L["Hide in >5-man raids"],
+ desc = L["Party frames are hidden while in a raid group with more than 5 people inside."],
+ hidden = function(info) return info[2] ~= "party" end,
+ set = function(info, value)
+ if( value ) then
+ setVariable(info[2], nil, nil, "hideAnyRaid", false)
+ end
+
+ setVariable(info[2], nil, nil, "hideSemiRaid", value)
+ ShadowUF.Units:ReloadHeader(info[#(info) - 3])
+ end,
+ arg = "hideSemiRaid",
},
- width = {
+ hideRaid = {
order = 2,
- type = "range",
- name = L["Width percent"],
- desc = L["Percentage of width the portrait should use."],
- min = 0, max = 1.0, step = 0.01, isPercent = true,
- hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
- arg = "$parent.width",
+ type = "toggle",
+ name = L["Hide in any raid"],
+ desc = L["Party frames are hidden while in any sort of raid no matter how many people."],
+ hidden = function(info) return info[2] ~= "party" end,
+ set = function(info, value)
+ if( value ) then
+ setVariable(info[2], nil, nil, "hideSemiRaid", false)
+ end
+
+ setVariable(info[2], nil, nil, "hideAnyRaid", value)
+ ShadowUF.Units:ReloadHeader(info[#(info) - 3])
+ end,
+ arg = "hideAnyRaid",
},
- before = {
+ separateFrames = {
order = 3,
- type = "range",
- name = L["Full size before"],
- min = 0, max = 100, step = 5,
- hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
- arg = "$parent.fullBefore",
- },
- after = {
- order = 4,
- type = "range",
- name = L["Full size after"],
- min = 0, max = 100, step = 5,
- hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
- arg = "$parent.fullAfter",
+ type = "toggle",
+ name = L["Separate raid frames"],
+ 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."],
+ hidden = function(info) return info[2] ~= "raid" end,
+ arg = "frameSplit",
},
- order = {
- order = 3,
- type = "range",
- name = L["Order"],
- min = 0, max = 100, step = 5,
- hidden = hideBarOption,
- arg = "portrait.order",
+ hideSemiRaidRaid = {
+ order = 3.5,
+ type = "toggle",
+ name = L["Hide in <=5-man raids"],
+ desc = L["Raid frames are hidden while in a raid group with 5 or less people inside."],
+ hidden = function(info) return info[2] ~= "raid" end,
+ set = function(info, value)
+ setVariable(info[2], nil, nil, "hideSemiRaid", value)
+ ShadowUF.Units:ReloadHeader(info[#(info) - 3])
+ end,
+ arg = "hideSemiRaid"
},
- height = {
+ showInRaid = {
order = 4,
- type = "range",
- name = L["Height"],
- 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."],
- min = 0, max = 10, step = 0.1,
- hidden = hideBarOption,
- arg = "portrait.height",
+ type = "toggle",
+ name = L["Show party as raid"],
+ hidden = hideRaidOption,
+ set = function(info, value)
+ setUnit(info, value)
+
+ ShadowUF.Units:ReloadHeader("party")
+ ShadowUF.Units:ReloadHeader("raid")
+ ShadowUF.modules.movers:Update()
+ end,
+ arg = "showParty",
},
},
},
- },
- },
- auras = {
- order = 5,
- name = L["Auras"],
- type = "group",
- hidden = isModifiersSet,
- set = setUnit,
- get = getUnit,
- args = {
- temp = {
- order = 0,
+ general = {
+ order = 1,
type = "group",
inline = true,
- name = L["Temporary enchants"],
- hidden = function(info) return info[2] ~= "player" end,
+ name = L["General"],
+ hidden = false,
args = {
- temporary = {
- order = 0,
- type = "toggle",
- name = L["Enable temporary enchants"],
- desc = L["Adds temporary enchants to the buffs for the player."],
- disabled = function(info) return not getVariable(info[2], "auras", "buffs", "enabled") end,
- arg = "auras.buffs.temporary",
- width = "double",
+ offset = {
+ order = 2,
+ type = "range",
+ name = L["Row offset"],
+ desc = L["Spacing between each row"],
+ min = -10, max = 100, step = 1,
+ arg = "offset",
},
- },
- },
- buffs = Config.auraTable,
- debuffs = Config.auraTable,
- },
- },
- indicators = {
- order = 5.5,
- type = "group",
- name = L["Indicators"],
- hidden = isModifiersSet,
- childGroups = "tree",
- set = setUnit,
- get = getUnit,
- args = {
- },
- },
- tag = {
- order = 7,
- name = L["Text/Tags"],
- type = "group",
- hidden = isModifiersSet,
- childGroups = "tree",
- args = tagWizard,
- },
- },
+ attribPoint = {
+ order = 3,
+ type = "select",
+ name = L["Row growth"],
+ desc = L["How the rows should grow when new group members are added."],
+ values = {["TOP"] = L["Down"], ["BOTTOM"] = L["Up"], ["LEFT"] = L["Right"], ["RIGHT"] = L["Left"]},
+ arg = "attribPoint",
+ set = function(info, value)
+ -- If you set the frames to grow left, the columns have to grow down or up as well
+ local attribAnchorPoint = getVariable(info[2], nil, nil, "attribAnchorPoint")
+ if( ( value == "LEFT" or value == "RIGHT" ) and attribAnchorPoint ~= "BOTTOM" and attribAnchorPoint ~= "TOP" ) then
+ ShadowUF.db.profile.units[info[2]].attribAnchorPoint = "BOTTOM"
+ elseif( ( value == "TOP" or value == "BOTTOM" ) and attribAnchorPoint ~= "LEFT" and attribAnchorPoint ~= "RIGHT" ) then
+ ShadowUF.db.profile.units[info[2]].attribAnchorPoint = "RIGHT"
+ end
+
+ setUnit(info, value)
+
+ local position = ShadowUF.db.profile.positions[info[2]]
+ if( position.top and position.bottom ) then
+ local point = ShadowUF.db.profile.units[info[2]].attribAnchorPoint == "RIGHT" and "RIGHT" or "LEFT"
+ position.point = (ShadowUF.db.profile.units[info[2]].attribPoint == "BOTTOM" and "BOTTOM" or "TOP") .. point
+ position.y = ShadowUF.db.profile.units[info[2]].attribPoint == "BOTTOM" and position.bottom or position.top
+ end
+
+ ShadowUF.Units:ReloadHeader(info[2])
+ ShadowUF.modules.movers:Update()
+ end,
+ },
+ sep2 = {
+ order = 4,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = false,
+ },
+ columnSpacing = {
+ order = 5,
+ type = "range",
+ name = L["Column spacing"],
+ min = -30, max = 100, step = 1,
+ hidden = hideRaidOrAdvancedOption,
+ arg = "columnSpacing",
+ },
+ attribAnchorPoint = {
+ order = 6,
+ type = "select",
+ name = L["Column growth"],
+ desc = L["How the frames should grow when a new column is added."],
+ values = function(info)
+ local attribPoint = getVariable(info[2], nil, nil, "attribPoint")
+ if( attribPoint == "LEFT" or attribPoint == "RIGHT" ) then
+ return {["TOP"] = L["Down"], ["BOTTOM"] = L["Up"]}
+ end
+
+ return {["LEFT"] = L["Right"], ["RIGHT"] = L["Left"]}
+ end,
+ hidden = hideRaidOrAdvancedOption,
+ set = function(info, value)
+ -- If you set the frames to grow left, the columns have to grow down or up as well
+ local attribPoint = getVariable(info[2], nil, nil, "attribPoint")
+ if( ( value == "LEFT" or value == "RIGHT" ) and attribPoint ~= "BOTTOM" and attribPoint ~= "TOP" ) then
+ ShadowUF.db.profile.units[info[2]].attribPoint = "BOTTOM"
+ end
+
+ setUnit(info, value)
+
+ ShadowUF.Units:ReloadHeader(info[2])
+ ShadowUF.modules.movers:Update()
+ end,
+ arg = "attribAnchorPoint",
+ },
+ sep3 = {
+ order = 7,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = false,
+ },
+ maxColumns = {
+ order = 8,
+ type = "range",
+ name = L["Max columns"],
+ min = 1, max = 20, step = 1,
+ arg = "maxColumns",
+ hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideSplitOrRaidOption(info) end,
+ },
+ unitsPerColumn = {
+ order = 8,
+ type = "range",
+ name = L["Units per column"],
+ min = 1, max = 40, step = 1,
+ arg = "unitsPerColumn",
+ hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideSplitOrRaidOption(info) end,
+ },
+ partyPerColumn = {
+ order = 9,
+ type = "range",
+ name = L["Units per column"],
+ min = 1, max = 5, step = 1,
+ arg = "unitsPerColumn",
+ hidden = function(info) return info[2] ~= "party" or not ShadowUF.db.profile.advanced end,
+ },
+ groupsPerRow = {
+ order = 8,
+ type = "range",
+ name = L["Groups per row"],
+ desc = L["How many groups should be shown per row."],
+ min = 1, max = 8, step = 1,
+ arg = "groupsPerRow",
+ hidden = function(info) return info[2] ~= "raid" or not ShadowUF.db.profile.units.raid.frameSplit end,
+ },
+ groupSpacing = {
+ order = 9,
+ type = "range",
+ name = L["Group row spacing"],
+ desc = L["How much spacing should be between each new row of groups."],
+ min = -50, max = 50, step = 1,
+ arg = "groupSpacing",
+ hidden = function(info) return info[2] ~= "raid" or not ShadowUF.db.profile.units.raid.frameSplit end,
+ },
+ },
+ },
+ sort = {
+ order = 2,
+ type = "group",
+ inline = true,
+ name = L["Sorting"],
+ hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or ( info[2] ~= "raid" and not ShadowUF.db.profile.advanced ) end,
+ args = {
+ sortMethod = {
+ order = 2,
+ type = "select",
+ name = L["Sort method"],
+ values = {["INDEX"] = L["Index"], ["NAME"] = L["Name"]},
+ arg = "sortMethod",
+ hidden = false,
+ },
+ sortOrder = {
+ order = 2,
+ type = "select",
+ name = L["Sort order"],
+ values = {["ASC"] = L["Ascending"], ["DESC"] = L["Descending"]},
+ arg = "sortOrder",
+ hidden = false,
+ },
+ },
+ },
+ raid = {
+ order = 3,
+ type = "group",
+ inline = true,
+ name = L["Groups"],
+ hidden = hideRaidOption,
+ args = {
+ groupBy = {
+ order = 4,
+ type = "select",
+ name = L["Group by"],
+ values = {["GROUP"] = L["Group number"], ["CLASS"] = L["Class"], ["ASSIGNEDROLE"] = L["Assigned Role (DPS/Tank/etc)"]},
+ arg = "groupBy",
+ hidden = hideSplitOrRaidOption,
+ },
+ selectedGroups = {
+ order = 7,
+ type = "multiselect",
+ name = L["Groups to show"],
+ 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)},
+ set = function(info, key, value)
+ local tbl = getVariable(info[2], nil, nil, "filters")
+ tbl[key] = value
+
+ setVariable(info[2], "filters", nil, tbl)
+ ShadowUF.Units:ReloadHeader(info[2])
+ ShadowUF.modules.movers:Update()
+ end,
+ get = function(info, key)
+ return getVariable(info[2], nil, nil, "filters")[key]
+ end,
+ hidden = function(info) return info[2] ~= "raid" and info[2] ~= "raidpet" end,
+ },
+ },
+ },
+ },
+ },
+ frame = {
+ order = 2,
+ name = L["Frame"],
+ type = "group",
+ hidden = isModifiersSet,
+ set = setUnit,
+ get = getUnit,
+ args = {
+ size = {
+ order = 0,
+ type = "group",
+ inline = true,
+ name = L["Size"],
+ hidden = false,
+ set = function(info, value)
+ setUnit(info, value)
+ ShadowUF.modules.movers:Update()
+ end,
+ args = {
+ scale = {
+ order = 0,
+ type = "range",
+ name = L["Scale"],
+ min = 0.25, max = 2, step = 0.01,
+ isPercent = true,
+ arg = "scale",
+ },
+ height = {
+ order = 1,
+ type = "range",
+ name = L["Height"],
+ min = 0, softMax = 100, step = 1,
+ arg = "height",
+ },
+ width = {
+ order = 2,
+ type = "range",
+ name = L["Width"],
+ min = 0, softMax = 300, step = 1,
+ arg = "width",
+ },
+ },
+ },
+ anchor = {
+ order = 1,
+ type = "group",
+ inline = true,
+ hidden = function(info) return info[2] == "global" end,
+ name = L["Anchor to another frame"],
+ set = setPosition,
+ get = getPosition,
+ args = {
+ anchorPoint = {
+ order = 0.50,
+ type = "select",
+ name = L["Anchor point"],
+ values = positionList,
+ hidden = false,
+ get = function(info)
+ local position = ShadowUF.db.profile.positions[info[2]]
+ if( ShadowUF.db.profile.advanced ) then
+ return position[info[#(info)]]
+ end
+
+
+ return position.movedAnchor or position[info[#(info)]]
+ end,
+ },
+ anchorTo = {
+ order = 1,
+ type = "select",
+ name = L["Anchor to"],
+ values = getAnchorParents,
+ hidden = false,
+ },
+ sep = {
+ order = 2,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = false,
+ },
+ x = {
+ order = 3,
+ type = "input",
+ name = L["X Offset"],
+ validate = checkNumber,
+ set = setNumber,
+ get = getString,
+ hidden = false,
+ },
+ y = {
+ order = 4,
+ type = "input",
+ name = L["Y Offset"],
+ validate = checkNumber,
+ set = setNumber,
+ get = getString,
+ hidden = false,
+ },
+ },
+ },
+ orHeader = {
+ order = 1.5,
+ type = "header",
+ name = L["Or you can set a position manually"],
+ hidden = function(info) if( info[2] == "global" or hideAdvancedOption() ) then return true else return false end end,
+ },
+ position = {
+ order = 2,
+ type = "group",
+ hidden = function(info) if( info[2] == "global" or hideAdvancedOption() ) then return true else return false end end,
+ inline = true,
+ name = L["Manual position"],
+ set = setPosition,
+ get = getPosition,
+ args = {
+ point = {
+ order = 0,
+ type = "select",
+ name = L["Point"],
+ values = pointPositions,
+ hidden = false,
+ },
+ anchorTo = {
+ order = 0.50,
+ type = "select",
+ name = L["Anchor to"],
+ values = getAnchorParents,
+ hidden = false,
+ },
+ relativePoint = {
+ order = 1,
+ type = "select",
+ name = L["Relative point"],
+ values = pointPositions,
+ hidden = false,
+ },
+ sep = {
+ order = 2,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = false,
+ },
+ x = {
+ order = 3,
+ type = "input",
+ name = L["X Offset"],
+ validate = checkNumber,
+ set = setNumber,
+ get = getString,
+ hidden = false,
+ },
+ y = {
+ order = 4,
+ type = "input",
+ name = L["Y Offset"],
+ validate = checkNumber,
+ set = setNumber,
+ get = getString,
+ hidden = false,
+ },
+ },
+ },
+ },
+ },
+ bars = {
+ order = 3,
+ name = L["Bars"],
+ type = "group",
+ hidden = isModifiersSet,
+ set = setUnit,
+ get = getUnit,
+ args = {
+ powerbar = {
+ order = 1,
+ type = "group",
+ inline = false,
+ name = L["Power bar"],
+ hidden = false,
+ args = {
+ powerBar = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Power bar"]),
+ arg = "powerBar.enabled",
+ },
+ altPowerBar = {
+ order = 3,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Alt. Power bar"]),
+ desc = L["Shows a bar for alternate power info (used in some encounters)"],
+ hidden = function(info) return ShadowUF.fakeUnits[info[2]] or hideRestrictedOption(info) end,
+ arg = "altPowerBar.enabled",
+ },
+ colorType = {
+ order = 5,
+ type = "select",
+ name = L["Color power by"],
+ 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."],
+ values = {["class"] = L["Class"], ["type"] = L["Power Type"]},
+ arg = "powerBar.colorType",
+ },
+ onlyMana = {
+ order = 6,
+ type = "toggle",
+ name = L["Only show when mana"],
+ desc = L["Hides the power bar unless the class has mana."],
+ hidden = function(info) return not ShadowUF.Units.headerUnits[info[2]] end,
+ arg = "powerBar.onlyMana",
+ }
+ },
+ },
+ classmiscbars = {
+ order = 2,
+ type = "group",
+ inline = false,
+ name = L["Class/misc bars"],
+ hidden = function(info)
+ local unit = info[2]
+ if( unit == "global" ) then
+ 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
+ else
+ return unit ~= "player" and unit ~= "pet"
+ end
+ end,
+ args = {
+ runeBar = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Rune bar"]),
+ desc = L["Adds rune bars and timers before runes refresh to the player frame."],
+ hidden = hideRestrictedOption,
+ arg = "runeBar.enabled",
+ },
+ staggerBar = {
+ order = 1.25,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Stagger bar"]),
+ desc = L["Adds a Stagger bar for Brewmaster Monks."],
+ hidden = hideRestrictedOption,
+ arg = "staggerBar.enabled",
+ },
+ druidBar = {
+ order = 3,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Druid mana bar"]),
+ 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."],
+ hidden = hideRestrictedOption,
+ arg = "druidBar.enabled",
+ },
+ priestBar = {
+ order = 3,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Priest mana bar"]),
+ desc = L["Adds a mana bar to the player frame for shadow priests."],
+ hidden = hideRestrictedOption,
+ arg = "priestBar.enabled",
+ },
+ shamanBar = {
+ order = 3,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Shaman mana bar"]),
+ desc = L["Adds a mana bar to the player frame for elemental and enhancement shamans."],
+ hidden = hideRestrictedOption,
+ arg = "shamanBar.enabled",
+ },
+ xpBar = {
+ order = 4,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["XP/Rep bar"]),
+ desc = L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."],
+ hidden = hideRestrictedOption,
+ arg = "xpBar.enabled",
+ },
+ },
+ },
+ healthBar = {
+ order = 2,
+ type = "group",
+ inline = false,
+ name = L["Health bar"],
+ hidden = false,
+ args = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Health bar"]),
+ arg = "healthBar.enabled"
+ },
+ sep = {
+ order = 3.5,
+ type = "description",
+ name = "",
+ hidden = function(info) return not (info[2] == "player" or info[2] == "pet") end,
+ },
+ colorAggro = {
+ order = 4,
+ type = "toggle",
+ name = L["Color on aggro"],
+ desc = L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."],
+ arg = "healthBar.colorAggro",
+ hidden = hideRestrictedOption,
+ },
+ colorDispel = {
+ order = 5,
+ type = "toggle",
+ name = L["Color on curable debuff"],
+ desc = L["Changes the health bar to the color of any curable debuff."],
+ arg = "healthBar.colorDispel",
+ hidden = hideRestrictedOption,
+ width = "full",
+ },
+ healthColor = {
+ order = 6,
+ type = "select",
+ name = L["Color health by"],
+ desc = L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."],
+ values = function(info)
+ if info[2] == "pet" or info[2] == "partypet" or info[2] == "raidpet" or info[2] == "arenapet" then
+ return {["class"] = L["Class"], ["static"] = L["Static"], ["percent"] = L["Health percent"], ["playerclass"] = L["Player Class"]}
+ else
+ return {["class"] = L["Class"], ["static"] = L["Static"], ["percent"] = L["Health percent"]}
+ end
+ end,
+ arg = "healthBar.colorType",
+ },
+ reaction = {
+ order = 7,
+ type = "select",
+ name = L["Color by reaction on"],
+ desc = L["When to color the health bar by the units reaction, overriding the color health by option."],
+ arg = "healthBar.reactionType",
+ values = {["none"] = L["Never (Disabled)"], ["player"] = L["Players only"], ["npc"] = L["NPCs only"], ["both"] = L["Both"]},
+ hidden = function(info) return info[2] == "player" or info[2] == "pet" end,
+ }
+ },
+ },
+ healAbsorb = {
+ order = 2.5,
+ type = "group",
+ inline = false,
+ name = L["Heal absorbs"],
+ hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideRestrictedOption(info) end,
+ disabled = function(info) return not getVariable(info[2], "healthBar", nil, "enabled") end,
+ args = {
+ heals = {
+ order = 1,
+ type = "toggle",
+ name = L["Show Heal Absorbs"],
+ desc = L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."],
+ arg = "healAbsorb.enabled",
+ hidden = false,
+ set = function(info, value)
+ setUnit(info, value)
+ setDirectUnit(info[2], "healAbsorb", nil, "enabled", getVariable(info[2], "healAbsorb", nil, "enabled"))
+ end
+ },
+ cap = {
+ order = 3,
+ type = "range",
+ name = L["Outside bar limit"],
+ 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."],
+ min = 1, max = 1.50, step = 0.05, isPercent = true,
+ arg = "healAbsorb.cap",
+ hidden = false,
+ },
+ },
+ },
+ incHeal = {
+ order = 3,
+ type = "group",
+ inline = false,
+ name = L["Incoming heals"],
+ hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideRestrictedOption(info) end,
+ disabled = function(info) return not getVariable(info[2], "healthBar", nil, "enabled") end,
+ args = {
+ heals = {
+ order = 1,
+ type = "toggle",
+ name = L["Show incoming heals"],
+ desc = L["Adds a bar inside the health bar indicating how much healing someone will receive."],
+ arg = "incHeal.enabled",
+ hidden = false,
+ set = function(info, value)
+ setUnit(info, value)
+ setDirectUnit(info[2], "incHeal", nil, "enabled", getVariable(info[2], "incHeal", nil, "enabled"))
+ end
+ },
+ cap = {
+ order = 3,
+ type = "range",
+ name = L["Outside bar limit"],
+ 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."],
+ min = 1, max = 1.50, step = 0.05, isPercent = true,
+ arg = "incHeal.cap",
+ hidden = false,
+ },
+ },
+ },
+ incAbsorb = {
+ order = 3.5,
+ type = "group",
+ inline = false,
+ name = L["Incoming absorbs"],
+ hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or hideRestrictedOption(info) end,
+ disabled = function(info) return not getVariable(info[2], "healthBar", nil, "enabled") end,
+ args = {
+ heals = {
+ order = 1,
+ type = "toggle",
+ name = L["Show incoming absorbs"],
+ desc = L["Adds a bar inside the health bar indicating how much damage will be absorbed."],
+ arg = "incAbsorb.enabled",
+ hidden = false,
+ set = function(info, value)
+ setUnit(info, value)
+ setDirectUnit(info[2], "incAbsorb", nil, "enabled", getVariable(info[2], "incAbsorb", nil, "enabled"))
+ end
+ },
+ cap = {
+ order = 3,
+ type = "range",
+ name = L["Outside bar limit"],
+ 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."],
+ min = 1, max = 1.50, step = 0.05, isPercent = true,
+ arg = "incAbsorb.cap",
+ hidden = false,
+ },
+ },
+ },
+ totemBar = {
+ order = 3.6,
+ type = "group",
+ inline = false,
+ name = ShadowUF.modules.totemBar.moduleName,
+ hidden = function(info)
+ local unit = info[2]
+ if( unit == "global" ) then
+ return not globalConfig.totemBar
+ else
+ return unit ~= "player" and unit ~= "pet"
+ end
+ end,
+ args = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], ShadowUF.modules.totemBar.moduleName),
+ desc = function(info)
+ 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."]
+ end,
+ arg = "totemBar.enabled",
+ },
+ icon = {
+ order = 2,
+ type = "toggle",
+ name = L["Show icon durations"],
+ desc = L["Uses the icon of the totem being shown instead of a status bar."],
+ arg = "totemBar.icon",
+ },
+ secure = {
+ order = 3,
+ type = "toggle",
+ name = L["Dismissable Totem bars"],
+ hidden = function()
+ return not ShadowUF.modules.totemBar:SecureLockable()
+ end,
+ desc = function(info)
+ 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."]
+ end,
+ arg = "totemBar.secure",
+ }
+ },
+ },
+ emptyBar = {
+ order = 4,
+ type = "group",
+ inline = false,
+ name = L["Empty bar"],
+ hidden = false,
+ args = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Empty bar"]),
+ desc = L["Adds an empty bar that you can put text into as a way of uncluttering other bars."],
+ arg = "emptyBar.enabled",
+ width = "full"
+ },
+ overrideColor = {
+ order = 4,
+ type = "color",
+ name = L["Background color"],
+ disabled = function(info)
+ local emptyBar = getVariable(info[2], nil, nil, "emptyBar")
+ return emptyBar.class and emptyBar.reaciton
+ end,
+ set = function(info, r, g, b)
+ local color = getUnit(info) or {}
+ color.r = r
+ color.g = g
+ color.b = b
+
+ setUnit(info, color)
+ end,
+ get = function(info)
+ local color = getUnit(info)
+ if( not color ) then
+ return 0, 0, 0
+ end
+
+ return color.r, color.g, color.b
+
+ end,
+ arg = "emptyBar.backgroundColor",
+ width = "full"
+ },
+ reaction = {
+ order = 2,
+ type = "select",
+ name = L["Color by reaction on"],
+ desc = L["When to color the empty bar by reaction, overriding the default color by option."],
+ arg = "emptyBar.reactionType",
+ values = {["none"] = L["Never (Disabled)"], ["player"] = L["Players only"], ["npc"] = L["NPCs only"], ["both"] = L["Both"]},
+ },
+ colorType = {
+ order = 3,
+ type = "toggle",
+ name = L["Color by class"],
+ desc = L["Players will be colored by class."],
+ arg = "emptyBar.class",
+ },
+ },
+ },
+ castBar = {
+ order = 5,
+ type = "group",
+ inline = false,
+ name = L["Cast bar"],
+ hidden = hideRestrictedOption,
+ args = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Cast bar"]),
+ 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,
+ hidden = false,
+ arg = "castBar.enabled",
+ width = "full"
+ },
+ autoHide = {
+ order = 2,
+ type = "toggle",
+ name = L["Hide bar when empty"],
+ desc = L["Hides the cast bar if there is no cast active."],
+ hidden = false,
+ arg = "castBar.autoHide",
+ },
+ castIcon = {
+ order = 2.5,
+ type = "select",
+ name = L["Cast icon"],
+ arg = "castBar.icon",
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["HIDE"] = L["Disabled"]},
+ hidden = false,
+ },
+ castName = {
+ order = 3,
+ type = "header",
+ name = L["Cast name"],
+ hidden = hideAdvancedOption,
+ },
+ nameEnabled = {
+ order = 4,
+ type = "toggle",
+ name = L["Show cast name"],
+ arg = "castBar.name.enabled",
+ hidden = hideAdvancedOption,
+ },
+ nameAnchor = {
+ order = 5,
+ type = "select",
+ name = L["Anchor point"],
+ desc = L["Where to anchor the cast name text."],
+ values = {["CLI"] = L["Inside Center Left"], ["CRI"] = L["Inside Center Right"]},
+ hidden = hideAdvancedOption,
+ arg = "castBar.name.anchorPoint",
+ },
+ nameSize = {
+ order = 7,
+ type = "range",
+ name = L["Size"],
+ desc = L["Let's you modify the base font size to either make it larger or smaller."],
+ type = "range",
+ min = -10, max = 10, step = 1, softMin = -5, softMax = 5,
+ hidden = hideAdvancedOption,
+ arg = "castBar.name.size",
+ },
+ nameX = {
+ order = 8,
+ type = "range",
+ name = L["X Offset"],
+ min = -20, max = 20, step = 1,
+ hidden = hideAdvancedOption,
+ arg = "castBar.name.x",
+ },
+ nameY = {
+ order = 9,
+ type = "range",
+ name = L["Y Offset"],
+ min = -20, max = 20, step = 1,
+ hidden = hideAdvancedOption,
+ arg = "castBar.name.y",
+ },
+ castTime = {
+ order = 10,
+ type = "header",
+ name = L["Cast time"],
+ hidden = hideAdvancedOption,
+ },
+ timeEnabled = {
+ order = 11,
+ type = "toggle",
+ name = L["Show cast time"],
+ arg = "castBar.time.enabled",
+ hidden = hideAdvancedOption,
+ width = "full"
+ },
+ timeAnchor = {
+ order = 12,
+ type = "select",
+ name = L["Anchor point"],
+ desc = L["Where to anchor the cast time text."],
+ values = {["CLI"] = L["Inside Center Left"], ["CRI"] = L["Inside Center Right"]},
+ hidden = hideAdvancedOption,
+ arg = "castBar.time.anchorPoint",
+ },
+ timeSize = {
+ order = 14,
+ type = "range",
+ name = L["Size"],
+ desc = L["Let's you modify the base font size to either make it larger or smaller."],
+ type = "range",
+ min = -10, max = 10, step = 1, softMin = -5, softMax = 5,
+ hidden = hideAdvancedOption,
+ arg = "castBar.time.size",
+ },
+ timeX = {
+ order = 15,
+ type = "range",
+ name = L["X Offset"],
+ min = -20, max = 20, step = 1,
+ hidden = hideAdvancedOption,
+ arg = "castBar.time.x",
+ },
+ timeY = {
+ order = 16,
+ type = "range",
+ name = L["Y Offset"],
+ min = -20, max = 20, step = 1,
+ hidden = hideAdvancedOption,
+ arg = "castBar.time.y",
+ },
+ },
+ },
+ },
+ },
+ widgetSize = {
+ order = 4,
+ name = L["Widget Size"],
+ type = "group",
+ hidden = isModifiersSet,
+ set = setUnit,
+ get = getUnit,
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ name = L["Help"],
+ inline = true,
+ hidden = false,
+ args = {
+ help = {
+ order = 0,
+ type = "description",
+ 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."],
+ },
+ },
+ },
+ portrait = {
+ order = 0.5,
+ type = "group",
+ name = L["Portrait"],
+ inline = false,
+ hidden = false,
+ args = {
+ enableBar = {
+ order = 1,
+ type = "toggle",
+ name = L["Show as bar"],
+ 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."],
+ arg = "$parent.isBar",
+ },
+ sep = {
+ order = 1.5,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
+ },
+ width = {
+ order = 2,
+ type = "range",
+ name = L["Width percent"],
+ desc = L["Percentage of width the portrait should use."],
+ min = 0, max = 1.0, step = 0.01, isPercent = true,
+ hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
+ arg = "$parent.width",
+ },
+ before = {
+ order = 3,
+ type = "range",
+ name = L["Full size before"],
+ min = 0, max = 100, step = 5,
+ hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
+ arg = "$parent.fullBefore",
+ },
+ after = {
+ order = 4,
+ type = "range",
+ name = L["Full size after"],
+ min = 0, max = 100, step = 5,
+ hidden = function(info) return getVariable(info[2], "portrait", nil, "isBar") end,
+ arg = "$parent.fullAfter",
+ },
+ order = {
+ order = 3,
+ type = "range",
+ name = L["Order"],
+ min = 0, max = 100, step = 5,
+ hidden = hideBarOption,
+ arg = "portrait.order",
+ },
+ height = {
+ order = 4,
+ type = "range",
+ name = L["Height"],
+ 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."],
+ min = 0, max = 10, step = 0.1,
+ hidden = hideBarOption,
+ arg = "portrait.height",
+ },
+ },
+ },
+ },
+ },
+ auras = {
+ order = 5,
+ name = L["Auras"],
+ type = "group",
+ hidden = isModifiersSet,
+ set = setUnit,
+ get = getUnit,
+ childGroups = "tree",
+ args = {
+ buffs = Config.auraTable,
+ debuffs = Config.auraTable,
+ },
+ },
+ indicators = {
+ order = 5.5,
+ type = "group",
+ name = L["Indicators"],
+ hidden = isModifiersSet,
+ childGroups = "tree",
+ set = setUnit,
+ get = getUnit,
+ args = {
+ },
+ },
+ tag = {
+ order = 7,
+ name = L["Text/Tags"],
+ type = "group",
+ hidden = isModifiersSet,
+ childGroups = "tree",
+ args = tagWizard,
+ },
+ },
+ }
+
+ for _, indicator in pairs(ShadowUF.modules.indicators.list) do
+ Config.unitTable.args.indicators.args[indicator] = Config.indicatorTable
+ end
+
+ -- Check for unit conflicts
+ local function hideZoneConflict()
+ for _, zone in pairs(ShadowUF.db.profile.visibility) do
+ for unit, status in pairs(zone) do
+ 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
+ return nil
+ end
+ end
+ end
+
+ return true
+ end
+
+ options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ShadowUF.db, true)
+ local LibDualSpec = LibStub("LibDualSpec-1.0", true)
+ if LibDualSpec then LibDualSpec:EnhanceOptions(options.args.profile, ShadowUF.db) end
+
+ options.args.enableUnits = {
+ type = "group",
+ name = L["Enabled Units"],
+ desc = getPageDescription,
+ args = {
+ help = {
+ order = 1,
+ type = "group",
+ inline = true,
+ name = L["Help"],
+ hidden = function()
+ if( not hideZoneConflict() or hideBasicOption() ) then
+ return true
+ end
+
+ return nil
+ end,
+ args = {
+ help = {
+ order = 0,
+ type = "description",
+ 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."],
+ },
+ },
+ },
+ zoneenabled = {
+ order = 1.5,
+ type = "group",
+ inline = true,
+ name = L["Zone configuration units"],
+ hidden = hideZoneConflict,
+ args = {
+ help = {
+ order = 1,
+ type = "description",
+ 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."]
+ },
+ sep = {
+ order = 2,
+ type = "header",
+ name = "",
+ },
+ units = {
+ order = 3,
+ type = "description",
+ name = function()
+ local text = {}
+
+ for zoneType, zone in pairs(ShadowUF.db.profile.visibility) do
+ local errors = {}
+ for unit, status in pairs(zone) do
+ if( L.units[unit] ) then
+ if ( not status and ShadowUF.db.profile.units[unit].enabled ) then
+ table.insert(errors, string.format(L["|cffff2020%s|r units disabled"], L.units[unit]))
+ elseif( status and not ShadowUF.db.profile.units[unit].enabled ) then
+ table.insert(errors, string.format(L["|cff20ff20%s|r units enabled"], L.units[unit]))
+ end
+ end
+ end
+
+ if( #(errors) > 1 ) then
+ table.insert(text, string.format("|cfffed000%s|r have the following overrides: %s", AREA_NAMES[zoneType], table.concat(errors, ", ")))
+ elseif( #(errors) == 1 ) then
+ table.insert(text, string.format("|cfffed000%s|r has the override: %s", AREA_NAMES[zoneType], errors[1]))
+ end
+ end
+
+ return #(text) > 0 and table.concat(text, "|n") or ""
+ end,
+ },
+ },
+ },
+ enabled = {
+ order = 2,
+ type = "group",
+ inline = true,
+ name = L["Enable units"],
+ args = {},
+ },
+ },
+ }
+
+ local sort_units = function(a, b)
+ return a < b
+ end
+
+ options.args.units = {
+ type = "group",
+ name = L["Unit Configuration"],
+ desc = getPageDescription,
+ args = {
+ help = {
+ order = 1,
+ type = "group",
+ inline = true,
+ name = L["Help"],
+ args = {
+ help = {
+ order = 0,
+ type = "description",
+ 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"],
+ fontSize = "medium",
+ },
+ },
+ },
+ global = {
+ type = "group",
+ childGroups = "tab",
+ order = 0,
+ name = L["Global"],
+ args = {
+ test = {
+ order = 0,
+ type = "group",
+ name = L["Currently modifying"],
+ inline = true,
+ hidden = function()
+ for k in pairs(modifyUnits) do return false end
+ return true
+ end,
+ args = {
+ info = {
+ order = 0,
+ type = "description",
+ name = function()
+ local units = {};
+ for unit, enabled in pairs(modifyUnits) do
+ if( enabled ) then
+ table.insert(units, L.units[unit])
+ end
+ end
+
+ table.sort(units, sort_units)
+ return table.concat(units, ", ")
+ end,
+ }
+ }
+ },
+ units = {
+ order = 1,
+ type = "group",
+ name = L["Units"],
+ set = function(info, value)
+ local unit = info[#(info)]
+ if( IsShiftKeyDown() ) then
+ for _, unit in pairs(ShadowUF.unitList) do
+ if( ShadowUF.db.profile.units[unit].enabled ) then
+ modifyUnits[unit] = value and true or nil
+
+ if( value ) then
+ globalConfig = mergeTables(globalConfig, ShadowUF.db.profile.units[unit])
+ end
+ end
+ end
+ else
+ modifyUnits[unit] = value and true or nil
+
+ if( value ) then
+ globalConfig = mergeTables(globalConfig, ShadowUF.db.profile.units[unit])
+ end
+ end
+
+ -- Check if we have nothing else selected, if so wipe it
+ local hasUnit
+ for k in pairs(modifyUnits) do hasUnit = true break end
+ if( not hasUnit ) then
+ globalConfig = {}
+ end
+
+ AceRegistry:NotifyChange("ShadowedUF")
+ end,
+ get = function(info) return modifyUnits[info[#(info)]] end,
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ name = L["Help"],
+ inline = true,
+ args = {
+ help = {
+ order = 0,
+ type = "description",
+ 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."],
+ },
+ },
+ },
+ units = {
+ order = 1,
+ type = "group",
+ name = L["Units"],
+ inline = true,
+ args = {},
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ -- Load modules into the unit table
+ for key, module in pairs(ShadowUF.modules) do
+ local canHaveBar = module.moduleHasBar
+ for _, data in pairs(ShadowUF.defaults.profile.units) do
+ if( data[key] and data[key].isBar ~= nil ) then
+ canHaveBar = true
+ break
+ end
+ end
+
+ if( canHaveBar ) then
+ Config.unitTable.args.widgetSize.args[key] = Config.barTable
+ end
+ end
+
+ -- Load global unit
+ for k, v in pairs(Config.unitTable.args) do
+ options.args.units.args.global.args[k] = v
+ end
+
+ -- Load all of the per unit settings
+ local perUnitList = {
+ order = getUnitOrder,
+ type = "toggle",
+ name = getName,
+ hidden = isUnitDisabled,
+ desc = function(info)
+ 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)]])
+ end,
+ }
+
+ -- Enabled units list
+ local unitCatOrder = {}
+ local enabledUnits = {
+ order = function(info) return unitCatOrder[info[#(info)]] + getUnitOrder(info) end,
+ type = "toggle",
+ name = getName,
+ set = function(info, value)
+ local unit = info[#(info)]
+ for child, parent in pairs(ShadowUF.Units.childUnits) do
+ if( unit == parent and not value ) then
+ ShadowUF.db.profile.units[child].enabled = false
+ end
+ end
+
+ ShadowUF.modules.movers:Update()
+ ShadowUF.db.profile.units[unit].enabled = value
+ ShadowUF:LoadUnits()
+
+ -- Update party frame visibility
+ if( unit == "raid" and ShadowUF.Units.headerFrames.party ) then
+ ShadowUF.Units:SetHeaderAttributes(ShadowUF.Units.headerFrames.party, "party")
+ end
+
+ ShadowUF.modules.movers:Update()
+ end,
+ get = function(info)
+ return ShadowUF.db.profile.units[info[#(info)]].enabled
+ end,
+ desc = function(info)
+ local unit = info[#(info)]
+ local unitDesc = UNIT_DESC[unit] or ""
+
+ if( ShadowUF.db.profile.units[unit].enabled and ShadowUF.Units.childUnits[unit] ) then
+ if( unitDesc ~= "" ) then unitDesc = unitDesc .. "\n\n" end
+ 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])
+ elseif( not ShadowUF.db.profile.units[unit].enabled ) then
+ for child, parent in pairs(ShadowUF.Units.childUnits) do
+ if( parent == unit ) then
+ if( unitDesc ~= "" ) then unitDesc = unitDesc .. "\n\n" end
+ return unitDesc .. L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."]
+ end
+ end
+ end
+
+ return unitDesc ~= "" and unitDesc
+ end,
+ disabled = function(info)
+ local unit = info[#(info)]
+ if( ShadowUF.Units.childUnits[unit] ) then
+ return not ShadowUF.db.profile.units[ShadowUF.Units.childUnits[unit]].enabled
+ end
+
+ return false
+ end,
+ }
+
+ local unitCategory = {
+ order = function(info)
+ local cat = info[#(info)]
+ 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
+ end,
+ type = "header",
+ name = function(info)
+ local cat = info[#(info)]
+ 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"]
+ end,
+ width = "full",
+ }
+
+ for cat, list in pairs(unitCategories) do
+ options.args.enableUnits.args.enabled.args[cat .. "cat"] = unitCategory
+
+ for _, unit in pairs(list) do
+ 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
+ end
+ end
+
+ for order, unit in pairs(ShadowUF.unitList) do
+ options.args.enableUnits.args.enabled.args[unit] = enabledUnits
+ options.args.units.args.global.args.units.args.units.args[unit] = perUnitList
+ options.args.units.args[unit] = Config.unitTable
+
+ unitCatOrder[unit] = unitCatOrder[unit] or 100
+ end
+end
+
+---------------------
+-- FILTER CONFIGURATION
+---------------------
+local function loadFilterOptions()
+ local hasWhitelist, hasBlacklist, hasOverridelist, rebuildFilters
+ local filterMap, spellMap = {}, {}
+
+ local manageFiltersTable = {
+ order = function(info) return info[#(info)] == "whitelists" and 1 or info[#(info)] == "blacklists" and 2 or 3 end,
+ type = "group",
+ name = function(info) return info[#(info)] == "whitelists" and L["Whitelists"] or info[#(info)] == "blacklists" and L["Blacklists"] or L["Override lists"] end,
+ args = {
+ },
+ }
+
+ local function reloadUnitAuras()
+ for _, frame in pairs(ShadowUF.Units.unitFrames) do
+ if( UnitExists(frame.unit) and frame.visibility.auras ) then
+ ShadowUF.modules.auras:UpdateFilter(frame)
+ frame:FullUpdate()
+ end
+ end
+ end
+
+ local function setFilterType(info, value)
+ local filter = filterMap[info[#(info) - 2]]
+ local filterType = info[#(info) - 3]
+
+ ShadowUF.db.profile.filters[filterType][filter][info[#(info)]] = value
+ reloadUnitAuras()
+ end
+
+ local function getFilterType(info)
+ local filter = filterMap[info[#(info) - 2]]
+ local filterType = info[#(info) - 3]
+
+ return ShadowUF.db.profile.filters[filterType][filter][info[#(info)]]
+ end
+
+ --- Container widget for the filter listing
+ local filterEditTable = {
+ order = 0,
+ type = "group",
+ name = function(info) return filterMap[info[#(info)]] end,
+ hidden = function(info) return not ShadowUF.db.profile.filters[info[#(info) - 1]][filterMap[info[#(info)]]] end,
+ args = {
+ general = {
+ order = 0,
+ type = "group",
+ name = function(info) return filterMap[info[#(info) - 1]] end,
+ hidden = false,
+ inline = true,
+ args = {
+ add = {
+ order = 0,
+ type = "input",
+ name = L["Aura name or spell ID"],
+ --dialogControl = "Aura_EditBox",
+ hidden = false,
+ set = function(info, value)
+ local filterType = info[#(info) - 3]
+ local filter = filterMap[info[#(info) - 2]]
+
+ ShadowUF.db.profile.filters[filterType][filter][value] = true
+
+ reloadUnitAuras()
+ rebuildFilters()
+ end,
+ },
+ delete = {
+ order = 1,
+ type = "execute",
+ name = L["Delete filter"],
+ hidden = false,
+ confirmText = L["Are you sure you want to delete this filter?"],
+ confirm = true,
+ func = function(info, value)
+ local filterType = info[#(info) - 3]
+ local filter = filterMap[info[#(info) - 2]]
+
+ ShadowUF.db.profile.filters[filterType][filter] = nil
+
+ -- Delete anything that used this filter too
+ 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
+ if filterList then
+ for id, filterUsed in pairs(filterList) do
+ if( filterUsed == filter ) then
+ filterList[id] = nil
+ end
+ end
+ end
+
+ reloadUnitAuras()
+ rebuildFilters()
+ end,
+ },
+ },
+ },
+ filters = {
+ order = 2,
+ type = "group",
+ inline = true,
+ hidden = false,
+ name = L["Aura types to filter"],
+ args = {
+ buffs = {
+ order = 4,
+ type = "toggle",
+ name = L["Buffs"],
+ desc = L["When this filter is active, apply the filter to buffs."],
+ set = setFilterType,
+ get = getFilterType,
+ },
+ debuffs = {
+ order = 5,
+ type = "toggle",
+ name = L["Debuffs"],
+ desc = L["When this filter is active, apply the filter to debuffs."],
+ set = setFilterType,
+ get = getFilterType,
+ },
+ },
+ },
+ spells = {
+ order = 3,
+ type = "group",
+ inline = true,
+ name = L["Auras"],
+ hidden = false,
+ args = {
+
+ },
+ },
+ },
+ }
+
+ -- Spell list for manage aura filters
+ local spellLabel = {
+ order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end,
+ type = "description",
+ width = "double",
+ fontSize = "medium",
+ name = function(info)
+ local name = spellMap[info[#(info)]]
+ if tonumber(name) then
+ local spellName, _, icon = GetSpellInfo(name)
+ name = string.format("|T%s:14:14:0:0|t %s (#%i)", icon or "Interface\\Icons\\Inv_misc_questionmark", spellName or L["Unknown"], name)
+ end
+ return name
+ end,
+ }
+
+ local spellRow = {
+ order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.5 end,
+ type = "execute",
+ name = L["Delete"],
+ width = "half",
+ func = function(info)
+ local spell = spellMap[info[#(info)]]
+ local filter = filterMap[info[#(info) - 2]]
+ local filterType = info[#(info) - 3]
+
+ ShadowUF.db.profile.filters[filterType][filter][spell] = nil
+
+ reloadUnitAuras()
+ rebuildFilters()
+ end
+ }
+
+ local noSpells = {
+ order = 0,
+ type = "description",
+ name = L["This filter has no auras in it, you will have to add some using the dialog above."],
+ }
+
+ -- The filter [View] widgets for manage aura filters
+ local filterLabel = {
+ order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end,
+ type = "description",
+ width = "", -- Odd I know, AceConfigDialog-3.0 expands descriptions to full width if width is nil
+ fontSize = "medium",
+ name = function(info) return filterMap[info[#(info)]] end,
+ }
+
+ local filterRow = {
+ order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.5 end,
+ type = "execute",
+ name = L["View"],
+ width = "half",
+ func = function(info)
+ local filterType = info[#(info) - 2]
+
+ AceDialog.Status.ShadowedUF.children.filter.children.filters.status.groups.groups[filterType] = true
+ selectTabGroup("filter", "filters", filterType .. "\001" .. string.match(info[#(info)], "(%d+)"))
+ end
+ }
+
+ local noFilters = {
+ order = 0,
+ type = "description",
+ 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."],
+ }
+
+ -- Container table for a filter zone
+ local globalSettings = {}
+ local zoneList = {"none", "pvp", "arena", "party", "raid"}
+ local filterTable = {
+ order = function(info) return info[#(info)] == "global" and 1 or info[#(info)] == "none" and 2 or 3 end,
+ type = "group",
+ inline = true,
+ hidden = function() return not hasWhitelist and not hasBlacklist and not hasOverridelist end,
+ name = function(info) return AREA_NAMES[info[#(info)]] or L["Global"] end,
+ set = function(info, value)
+ local filter = filterMap[info[#(info)]]
+ local zone = info[#(info) - 1]
+ local unit = info[#(info) - 2]
+ local filterKey = ShadowUF.db.profile.filters.whitelists[filter] and "zonewhite" or ShadowUF.db.profile.filters.blacklists[filter] and "zoneblack" or "zoneoverride"
+
+ for _, zoneConfig in pairs(zoneList) do
+ if( zone == "global" or zoneConfig == zone ) then
+ if( unit == "global" ) then
+ globalSettings[zoneConfig .. filterKey] = value and filter or false
+
+ for _, unit in pairs(ShadowUF.unitList) do
+ ShadowUF.db.profile.filters[filterKey][zoneConfig .. unit] = value and filter or nil
+ end
+ else
+ ShadowUF.db.profile.filters[filterKey][zoneConfig .. unit] = value and filter or nil
+ end
+ end
+ end
+
+ if( zone == "global" ) then
+ globalSettings[zone .. unit .. filterKey] = value and filter or false
+ end
+
+ reloadUnitAuras()
+ end,
+ get = function(info)
+ local filter = filterMap[info[#(info)]]
+ local zone = info[#(info) - 1]
+ local unit = info[#(info) - 2]
+
+ if( unit == "global" or zone == "global" ) then
+ local id = zone == "global" and zone .. unit or zone
+ local filterKey = ShadowUF.db.profile.filters.whitelists[filter] and "zonewhite" or ShadowUF.db.profile.filters.blacklists[filter] and "zoneblack" or "zoneoverride"
+
+ if( info[#(info)] == "nofilter" ) then
+ return globalSettings[id .. "zonewhite"] == false and globalSettings[id .. "zoneblack"] == false and globalSettings[id .. "zoneoverride"] == false
+ end
+
+ return globalSettings[id .. filterKey] == filter
+ end
+
+ if( info[#(info)] == "nofilter" ) then
+ 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]
+ end
+
+ 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
+ end,
+ args = {
+ nofilter = {
+ order = 0,
+ type = "toggle",
+ name = L["Don't use a filter"],
+ hidden = false,
+ set = function(info, value)
+ local filter = filterMap[info[#(info)]]
+ local zone = info[#(info) - 1]
+ local unit = info[#(info) - 2]
+
+ for _, zoneConfig in pairs(zoneList) do
+ if( zone == "global" or zoneConfig == zone ) then
+ if( unit == "global" ) then
+ globalSettings[zoneConfig .. "zonewhite"] = false
+ globalSettings[zoneConfig .. "zoneblack"] = false
+ globalSettings[zoneConfig .. "zoneoverride"] = false
+
+ for _, unit in pairs(ShadowUF.unitList) do
+ ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unit] = nil
+ ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unit] = nil
+ ShadowUF.db.profile.filters.zoneoverride[zoneConfig .. unit] = nil
+ end
+ else
+ ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unit] = nil
+ ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unit] = nil
+ ShadowUF.db.profile.filters.zoneoverride[zoneConfig .. unit] = nil
+ end
+ end
+ end
+
+ if( zone == "global" ) then
+ globalSettings[zone .. unit .. "zonewhite"] = false
+ globalSettings[zone .. unit .. "zoneblack"] = false
+ globalSettings[zone .. unit .. "zoneoverride"] = false
+ end
+
+ reloadUnitAuras()
+ end,
+ },
+ white = {
+ order = 1,
+ type = "header",
+ name = "|cffffffff" .. L["Whitelists"] .. "|r",
+ hidden = function(info) return not hasWhitelist end
+ },
+ black = {
+ order = 3,
+ type = "header",
+ name = L["Blacklists"], -- In theory I would make this black, but as black doesn't work with a black background I'll skip that
+ hidden = function(info) return not hasBlacklist end
+ },
+ override = {
+ order = 5,
+ type = "header",
+ 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
+ hidden = function(info) return not hasOverridelist end
+ },
+ },
+ }
+
+ -- Toggle used for set filter zones to enable filters
+ local filterToggle = {
+ 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,
+ type = "toggle",
+ name = function(info) return filterMap[info[#(info)]] end,
+ desc = function(info)
+ local filter = filterMap[info[#(info)]]
+ filter = ShadowUF.db.profile.filters.whitelists[filter] or ShadowUF.db.profile.filters.blacklists[filter] or ShadowUF.db.profile.filters.overridelists[filter]
+ if( filter.buffs and filter.debuffs ) then
+ return L["Filtering both buffs and debuffs"]
+ elseif( filter.buffs ) then
+ return L["Filtering buffs only"]
+ elseif( filter.debuffs ) then
+ return L["Filtering debuffs only"]
+ end
+
+ return L["This filter has no aura types set to filter out."]
+ end,
+ }
+
+ -- Load existing filters in
+ -- This needs to be cleaned up later
+ local filterID, spellID = 0, 0
+ local function buildList(type)
+ local manageFiltersTable = {
+ order = type == "whitelists" and 1 or type == "blacklists" and 2 or 3,
+ type = "group",
+ name = type == "whitelists" and L["Whitelists"] or type == "blacklists" and L["Blacklists"] or L["Override lists"],
+ args = {
+ groups = {
+ order = 0,
+ type = "group",
+ inline = true,
+ 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,
+ args = {
+ },
+ },
+ },
+ }
+
+ local hasFilters
+ for name, spells in pairs(ShadowUF.db.profile.filters[type]) do
+ hasFilters = true
+ filterID = filterID + 1
+ filterMap[tostring(filterID)] = name
+ filterMap[filterID .. "label"] = name
+ filterMap[filterID .. "row"] = name
+
+ manageFiltersTable.args[tostring(filterID)] = CopyTable(filterEditTable)
+ manageFiltersTable.args.groups.args[filterID .. "label"] = filterLabel
+ manageFiltersTable.args.groups.args[filterID .. "row"] = filterRow
+ filterTable.args[tostring(filterID)] = filterToggle
+
+ local hasSpells
+ for spellName in pairs(spells) do
+ if( spellName ~= "buffs" and spellName ~= "debuffs" ) then
+ hasSpells = true
+ spellID = spellID + 1
+ spellMap[tostring(spellID)] = spellName
+ spellMap[spellID .. "label"] = spellName
+
+ manageFiltersTable.args[tostring(filterID)].args.spells.args[spellID .. "label"] = spellLabel
+ manageFiltersTable.args[tostring(filterID)].args.spells.args[tostring(spellID)] = spellRow
+ end
+ end
+
+ if( not hasSpells ) then
+ manageFiltersTable.args[tostring(filterID)].args.spells.args.noSpells = noSpells
+ end
+ end
+
+ if( not hasFilters ) then
+ if( type == "whitelists" ) then hasWhitelist = nil elseif( type == "blacklists" ) then hasBlacklist = nil else hasOverridelist = nil end
+ manageFiltersTable.args.groups.args.noFilters = noFilters
+ end
+
+ return manageFiltersTable
+ end
+
+ rebuildFilters = function()
+ for id in pairs(filterMap) do filterTable.args[id] = nil end
+
+ spellID = 0
+ filterID = 0
+ hasBlacklist = true
+ hasWhitelist = true
+ hasOverridelist = true
+
+ table.wipe(filterMap)
+ table.wipe(spellMap)
+
+ options.args.filter.args.filters.args.whitelists = buildList("whitelists")
+ options.args.filter.args.filters.args.blacklists = buildList("blacklists")
+ options.args.filter.args.filters.args.overridelists = buildList("overridelists")
+ end
+
+ local unitFilterSelection = {
+ order = function(info) return info[#(info)] == "global" and 1 or (getUnitOrder(info) + 1) end,
+ type = "group",
+ name = function(info) return info[#(info)] == "global" and L["Global"] or getName(info) end,
+ disabled = function(info)
+ if( info[#(info)] == "global" ) then
+ return false
+ end
+
+ return not hasWhitelist and not hasBlacklist
+ end,
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ inline = true,
+ name = L["Help"],
+ hidden = function() return hasWhitelist or hasBlacklist or hasOverridelist end,
+ args = {
+ help = {
+ type = "description",
+ name = L["You will need to create an aura filter before you can set which unit to enable aura filtering on."],
+ width = "full",
+ }
+ },
+ },
+ header = {
+ order = 0,
+ type = "header",
+ name = function(info) return (info[#(info) - 1] == "global" and L["Global"] or L.units[info[#(info) - 1]]) end,
+ hidden = function() return not hasWhitelist and not hasBlacklist and not hasOverridelist end,
+ },
+ global = filterTable,
+ none = filterTable,
+ pvp = filterTable,
+ arena = filterTable,
+ battleground = filterTable,
+ party = filterTable,
+ raid = filterTable,
+ }
+ }
+
+ local addFilter = {type = "whitelists"}
+
+ options.args.filter = {
+ type = "group",
+ name = L["Aura Filters"],
+ childGroups = "tab",
+ desc = getPageDescription,
+ args = {
+ groups = {
+ order = 1,
+ type = "group",
+ name = L["Set Filter Zones"],
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ inline = true,
+ name = L["Help"],
+ args = {
+ help = {
+ type = "description",
+ 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."],
+ width = "full",
+ }
+ },
+ },
+ }
+ },
+ filters = {
+ order = 2,
+ type = "group",
+ name = L["Manage Aura Filters"],
+ childGroups = "tree",
+ args = {
+ manage = {
+ order = 1,
+ type = "group",
+ name = L["Management"],
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ inline = true,
+ name = L["Help"],
+ args = {
+ help = {
+ type = "description",
+ 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."],
+ width = "full",
+ }
+ },
+ },
+ error = {
+ order = 1,
+ type = "group",
+ inline = true,
+ hidden = function() return not addFilter.error end,
+ name = L["Error"],
+ args = {
+ error = {
+ order = 0,
+ type = "description",
+ name = function() return addFilter.error end,
+ width = "full",
+ },
+ },
+ },
+ add = {
+ order = 2,
+ type = "group",
+ inline = true,
+ name = L["New filter"],
+ get = function(info) return addFilter[info[#(info)]] end,
+ args = {
+ name = {
+ order = 0,
+ type = "input",
+ name = L["Name"],
+ set = function(info, value)
+ addFilter[info[#(info)]] = string.trim(value) ~= "" and value or nil
+ addFilter.error = nil
+ end,
+ get = function(info) return addFilter.errorName or addFilter.name end,
+ validate = function(info, value)
+ local name = string.lower(string.trim(value))
+ for filter in pairs(ShadowUF.db.profile.filters.whitelists) do
+ if( string.lower(filter) == name ) then
+ addFilter.error = string.format(L["The whitelist \"%s\" already exists."], value)
+ addFilter.errorName = value
+ AceRegistry:NotifyChange("ShadowedUF")
+ return ""
+ end
+ end
+
+ for filter in pairs(ShadowUF.db.profile.filters.blacklists) do
+ if( string.lower(filter) == name ) then
+ addFilter.error = string.format(L["The blacklist \"%s\" already exists."], value)
+ addFilter.errorName = value
+ AceRegistry:NotifyChange("ShadowedUF")
+ return ""
+ end
+ end
+
+ for filter in pairs(ShadowUF.db.profile.filters.overridelists) do
+ if( string.lower(filter) == name ) then
+ addFilter.error = string.format(L["The override list \"%s\" already exists."], value)
+ addFilter.errorName = value
+ AceRegistry:NotifyChange("ShadowedUF")
+ return ""
+ end
+ end
+
+ addFilter.error = nil
+ addFilter.errorName = nil
+ return true
+ end,
+ },
+ type = {
+ order = 1,
+ type = "select",
+ name = L["Filter type"],
+ set = function(info, value) addFilter[info[#(info)]] = value end,
+ values = {["whitelists"] = L["Whitelist"], ["blacklists"] = L["Blacklist"], ["overridelists"] = L["Override list"]},
+ },
+ add = {
+ order = 2,
+ type = "execute",
+ name = L["Create"],
+ disabled = function(info) return not addFilter.name end,
+ func = function(info)
+ ShadowUF.db.profile.filters[addFilter.type][addFilter.name] = {buffs = true, debuffs = true}
+ rebuildFilters()
+
+ local id
+ for key, value in pairs(filterMap) do
+ if( value == addFilter.name ) then
+ id = key
+ break
+ end
+ end
+
+ AceDialog.Status.ShadowedUF.children.filter.children.filters.status.groups.groups[addFilter.type] = true
+ selectTabGroup("filter", "filters", addFilter.type .. "\001" .. id)
+
+ table.wipe(addFilter)
+ addFilter.type = "whitelists"
+ end,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+
+ options.args.filter.args.groups.args.global = unitFilterSelection
+ for _, unit in pairs(ShadowUF.unitList) do
+ options.args.filter.args.groups.args[unit] = unitFilterSelection
+ end
+
+ rebuildFilters()
+end
+
+---------------------
+-- TAG CONFIGURATION
+---------------------
+local function loadTagOptions()
+ local tagData = {search = ""}
+ local function set(info, value, key)
+ local key = key or info[#(info)]
+ if( ShadowUF.Tags.defaultHelp[tagData.name] ) then
+ return
+ end
+
+ -- Reset loaded function + reload tags
+ if( key == "funct" ) then
+ ShadowUF.tagFunc[tagData.name] = nil
+ ShadowUF.Tags:Reload()
+ elseif( key == "category" ) then
+ local cat = ShadowUF.db.profile.tags[tagData.name][key]
+ if( cat and cat ~= value ) then
+ Config.tagTextTable.args[cat].args[tagData.name] = nil
+ Config.tagTextTable.args[value].args[tagData.name] = Config.tagTable
+ end
+ end
+
+ ShadowUF.db.profile.tags[tagData.name][key] = value
+ end
+
+ local function stripCode(text)
+ if( not text ) then
+ return ""
+ end
+
+ return string.gsub(string.gsub(text, "|", "||"), "\t", "")
+ end
+
+ local function get(info, key)
+ local key = key or info[#(info)]
+
+ if( key == "help" and ShadowUF.Tags.defaultHelp[tagData.name] ) then
+ return ShadowUF.Tags.defaultHelp[tagData.name] or ""
+ elseif( key == "events" and ShadowUF.Tags.defaultEvents[tagData.name] ) then
+ return ShadowUF.Tags.defaultEvents[tagData.name] or ""
+ elseif( key == "frequency" and ShadowUF.Tags.defaultFrequents[tagData.name] ) then
+ return ShadowUF.Tags.defaultFrequents[tagData.name] or ""
+ elseif( key == "category" and ShadowUF.Tags.defaultCategories[tagData.name] ) then
+ return ShadowUF.Tags.defaultCategories[tagData.name] or ""
+ elseif( key == "name" and ShadowUF.Tags.defaultNames[tagData.name] ) then
+ return ShadowUF.Tags.defaultNames[tagData.name] or ""
+ elseif( key == "funct" and ShadowUF.Tags.defaultTags[tagData.name] ) then
+ return ShadowUF.Tags.defaultTags[tagData.name] or ""
+ end
+
+ return ShadowUF.db.profile.tags[tagData.name] and ShadowUF.db.profile.tags[tagData.name][key] or ""
+ end
+
+ local function isSearchHidden(info)
+ return tagData.search ~= "" and not string.match(info[#(info)], tagData.search) or false
+ end
+
+ local function editTag(info)
+ tagData.name = info[#(info)]
+
+ if( ShadowUF.Tags.defaultHelp[tagData.name] ) then
+ 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."]
+ end
+
+ selectDialogGroup("tags", "edit")
+ end
+
+ -- Create all of the tag editor options, if it's a default tag will show it after any custom ones
+ local tagTable = {
+ type = "execute",
+ order = function(info) return ShadowUF.Tags.defaultTags[info[#(info)]] and 100 or 1 end,
+ name = getTagName,
+ desc = getTagHelp,
+ hidden = isSearchHidden,
+ func = editTag,
}
- for _, indicator in pairs(ShadowUF.modules.indicators.list) do
- Config.unitTable.args.indicators.args[indicator] = Config.indicatorTable
+ local tagCategories = {}
+ local function getTagCategories(info)
+ for k in pairs(tagCategories) do tagCategories[k] = nil end
+
+ for _, cat in pairs(ShadowUF.Tags.defaultCategories) do
+ tagCategories[cat] = TAG_GROUPS[cat]
+ end
+
+ return tagCategories
end
- options.args.enableUnits = {
+ -- Tag configuration
+ options.args.tags = {
type = "group",
- name = L["Enabled units"],
+ childGroups = "tab",
+ name = L["Add Tags"],
desc = getPageDescription,
+ hidden = hideAdvancedOption,
args = {
- help = {
+ general = {
+ order = 0,
+ type = "group",
+ name = L["Tag list"],
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ inline = true,
+ name = L["Help"],
+ hidden = function() return ShadowUF.db.profile.advanced end,
+ args = {
+ description = {
+ order = 0,
+ type = "description",
+ 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."],
+ },
+ },
+ },
+ search = {
+ order = 1,
+ type = "group",
+ inline = true,
+ name = L["Search"],
+ args = {
+ search = {
+ order = 1,
+ type = "input",
+ name = L["Search tags"],
+ set = function(info, text) tagData.search = text end,
+ get = function(info) return tagData.search end,
+ },
+ },
+ },
+ list = {
+ order = 2,
+ type = "group",
+ inline = true,
+ name = L["Tags"],
+ args = {},
+ },
+ },
+ },
+ add = {
order = 1,
type = "group",
- inline = true,
- name = L["Help"],
- hidden = hideBasicOption,
+ name = L["Add new tag"],
args = {
help = {
order = 0,
- type = "description",
- name = L["The check boxes below will allow you to enable or disable units."],
+ type = "group",
+ inline = true,
+ name = L["Help"],
+ args = {
+ help = {
+ order = 0,
+ type = "description",
+ name = L["You can find more information on creating your own custom tags in the \"Help\" tab above."],
+ },
+ },
+ },
+ add = {
+ order = 1,
+ type = "group",
+ inline = true,
+ name = L["Add new tag"],
+ args = {
+ error = {
+ order = 0,
+ type = "description",
+ name = function() return tagData.addError or "" end,
+ hidden = function() return not tagData.addError end,
+ },
+ errorHeader = {
+ order = 0.50,
+ type = "header",
+ name = "",
+ hidden = function() return not tagData.addError end,
+ },
+ tag = {
+ order = 1,
+ type = "input",
+ name = L["Tag name"],
+ 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]."],
+ validate = function(info, text)
+ if( text == "" ) then
+ tagData.addError = L["You must enter a tag name."]
+ elseif( string.match(text, "[%[%]%(%)]") ) then
+ tagData.addError = string.format(L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."], text)
+ elseif( ShadowUF.tagFunc[text] ) then
+ tagData.addError = string.format(L["The tag \"%s\" already exists."], text)
+ else
+ tagData.addError = nil
+ end
+
+ AceRegistry:NotifyChange("ShadowedUF")
+ return tagData.addError and "" or true
+ end,
+ set = function(info, tag)
+ tagData.name = tag
+ tagData.error = nil
+ tagData.addError = nil
+
+ ShadowUF.db.profile.tags[tag] = {func = "function(unit, unitOwner)\n\nend", category = "misc"}
+ options.args.tags.args.general.args.list.args[tag] = tagTable
+ Config.tagTextTable.args.misc.args[tag] = Config.tagTable
+
+ selectDialogGroup("tags", "edit")
+ end,
+ },
+ },
+ },
+ },
+ },
+ edit = {
+ order = 2,
+ type = "group",
+ name = L["Edit tag"],
+ hidden = function() return not tagData.name end,
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ inline = true,
+ name = L["Help"],
+ args = {
+ help = {
+ order = 0,
+ type = "description",
+ 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."],
+ },
+ },
+ },
+ tag = {
+ order = 1,
+ type = "group",
+ inline = true,
+ name = function() return string.format(L["Editing %s"], tagData.name or "") end,
+ args = {
+ error = {
+ order = 0,
+ type = "description",
+ name = function()
+ if( tagData.error ) then
+ return "|cffff0000" .. tagData.error .. "|r"
+ end
+ return ""
+ end,
+ hidden = function() return not tagData.error end,
+ },
+ errorHeader = {
+ order = 1,
+ type = "header",
+ name = "",
+ hidden = function() return not tagData.error end,
+ },
+ discovery = {
+ order = 1,
+ type = "toggle",
+ name = L["Disable event discovery"],
+ 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."],
+ set = function(info, value) tagData.discovery = value end,
+ get = function() return tagData.discovery end,
+ width = "full",
+ },
+ frequencyEnable = {
+ order = 1.10,
+ type = "toggle",
+ name = L["Enable frequent updates"],
+ desc = L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."],
+ set = function(info, value)
+ tagData.frequency = value and 5 or nil
+ set(info, tagData.frequency, "frequency")
+ end,
+ get = function(info) return get(info, "frequency") ~= "" and true or false end,
+ width = "full",
+ },
+ frequency = {
+ order = 1.20,
+ type = "input",
+ name = L["Update interval"],
+ 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."],
+ disabled = function(info) return get(info) == "" end,
+ validate = function(info, value)
+ value = tonumber(value)
+ if( not value ) then
+ tagData.error = L["Invalid interval entered, must be a number."]
+ elseif( value < 0 ) then
+ tagData.error = L["You must enter a number that is 0 or higher, negative numbers are not allowed."]
+ else
+ tagData.error = nil
+ end
+
+ if( tagData.error ) then
+ AceRegistry:NotifyChange("ShadowedUF")
+ return ""
+ end
+
+ return true
+ end,
+ set = function(info, value)
+ tagData.frequency = tonumber(value)
+ tagData.frequency = tagData.frequency < 0 and 0 or tagData.frequency
+
+ set(info, tagData.frequency)
+ end,
+ get = function(info) return tostring(get(info) or "") end,
+ width = "half",
+ },
+ name = {
+ order = 2,
+ type = "input",
+ name = L["Tag name"],
+ set = set,
+ get = get,
+ },
+ category = {
+ order = 2.5,
+ type = "select",
+ name = L["Category"],
+ values = getTagCategories,
+ set = set,
+ get = get,
+ },
+
+ sep = {
+ order = 2.75,
+ type = "description",
+ name = "",
+ width = "full",
+ },
+ events = {
+ order = 3,
+ type = "input",
+ name = L["Events"],
+ desc = L["Events that should be used to trigger an update of this tag. Separate each event with a single space."],
+ width = "full",
+ validate = function(info, text)
+ if( ShadowUF.Tags.defaultTags[tagData.name] ) then
+ return true
+ end
+
+ if( text == "" or string.match(text, "[^_%a%s]") ) then
+ 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."]
+ tagData.eventError = text
+ AceRegistry:NotifyChange("ShadowedUF")
+ return ""
+ end
+
+ tagData.eventError = text
+ tagData.error = nil
+ return true
+ end,
+ set = set,
+ get = function(info)
+ if( tagData.eventError ) then
+ return tagData.eventError
+ end
+
+ return get(info)
+ end,
+ },
+ func = {
+ order = 4,
+ type = "input",
+ multiline = true,
+ name = L["Code"],
+ 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"],
+ width = "full",
+ validate = function(info, text)
+ if( ShadowUF.Tags.defaultTags[tagData.name] ) then
+ return true
+ end
+
+ local funct, msg = loadstring("return " .. text)
+ if( not string.match(text, "function") ) then
+ tagData.error = L["You must wrap your code in a function."]
+ tagData.funcError = text
+ elseif( not funct and msg ) then
+ tagData.error = string.format(L["Failed to save tag, error:|n %s"], msg)
+ tagData.funcError = text
+ else
+ tagData.error = nil
+ tagData.funcError = nil
+ end
+
+ AceRegistry:NotifyChange("ShadowedUF")
+ return tagData.error and "" or true
+ end,
+ set = function(info, value)
+ value = string.gsub(value, "||", "|")
+ set(info, value)
+
+ -- Try and automatically identify the events this tag is going to want to use
+ if( not tagData.discovery ) then
+ tagData.eventError = nil
+ ShadowUF.db.profile.tags[tagData.name].events = ShadowUF.Tags:IdentifyEvents(value) or ""
+ end
+
+ ShadowUF.Tags:Reload(tagData.name)
+ end,
+ get = function(info)
+ if( tagData.funcError ) then
+ return stripCode(tagData.funcError)
+ end
+ return stripCode(ShadowUF.Tags.defaultTags[tagData.name] or ( ShadowUF.db.profile.tags[tagData.name] and ShadowUF.db.profile.tags[tagData.name].func))
+ end,
+ },
+ delete = {
+ order = 5,
+ type = "execute",
+ name = L["Delete"],
+ hidden = function() return ShadowUF.Tags.defaultTags[tagData.name] end,
+ confirm = true,
+ confirmText = L["Are you sure you want to delete this tag?"],
+ func = function(info)
+ local category = ShadowUF.db.profile.tags[tagData.name].category
+ if( category ) then
+ Config.tagTextTable.args[category].args[tagData.name] = nil
+ end
+
+ options.args.tags.args.general.args.list.args[tagData.name] = nil
+
+ ShadowUF.db.profile.tags[tagData.name] = nil
+ ShadowUF.tagFunc[tagData.name] = nil
+ ShadowUF.Tags:Reload(tagData.name)
+
+ tagData.name = nil
+ tagData.error = nil
+ selectDialogGroup("tags", "general")
+ end,
+ },
+ },
},
},
},
- enabled = {
- order = 2,
- type = "group",
- inline = true,
- name = L["Enable units"],
- args = {},
- },
- },
- }
-
- options.args.units = {
- type = "group",
- name = L["Unit configuration"],
- desc = getPageDescription,
- args = {
help = {
- order = 1,
+ order = 3,
type = "group",
- inline = true,
name = L["Help"],
args = {
- help = {
+ general = {
order = 0,
- type = "description",
- 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"],
- fontSize = "medium",
+ type = "group",
+ name = L["General"],
+ inline = true,
+ args = {
+ general = {
+ order = 0,
+ type = "description",
+ 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."],
+ },
+ },
},
- },
- },
- global = {
- type = "group",
- childGroups = "tab",
- order = 0,
- name = L["Global"],
- args = {
- units = {
- order = 0,
+ documentation = {
+ order = 1,
type = "group",
- name = L["Units"],
- set = function(info, value)
- local unit = info[#(info)]
- if( IsShiftKeyDown() ) then
- for _, unit in pairs(ShadowUF.unitList) do
- if( ShadowUF.db.profile.units[unit].enabled ) then
- modifyUnits[unit] = value and true or nil
-
- if( value ) then
- globalConfig = mergeTables(globalConfig, ShadowUF.db.profile.units[unit])
- end
- end
- end
- else
- modifyUnits[unit] = value and true or nil
-
- if( value ) then
- globalConfig = mergeTables(globalConfig, ShadowUF.db.profile.units[unit])
- end
- end
-
- -- Check if we have nothing else selected, if so wipe it
- local hasUnit
- for k in pairs(modifyUnits) do hasUnit = true break end
- if( not hasUnit ) then
- globalConfig = {}
- end
-
- AceRegistry:NotifyChange("ShadowedUF")
- end,
- get = function(info) return modifyUnits[info[#(info)]] end,
+ name = L["Documentation"],
+ inline = true,
+ args = {
+ doc = {
+ order = 0,
+ type = "input",
+ name = L["Documentation"],
+ set = false,
+ get = function() return "http://wiki.github.com/Shadowed/ShadowedUnitFrames/tag-documentation" end,
+ width = "full",
+ },
+ },
+ },
+ resources = {
+ order = 2,
+ type = "group",
+ inline = true,
+ name = L["Resources"],
args = {
- help = {
+ lua = {
order = 0,
- type = "group",
- name = L["Help"],
- inline = true,
- args = {
- help = {
- order = 0,
- type = "description",
- 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."],
- },
- },
+ type = "input",
+ name = L["Programming in Lua"],
+ 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."],
+ set = false,
+ get = function() return "http://www.lua.org/pil/" end,
+ width = "full",
},
- units = {
+ wow = {
order = 1,
- type = "group",
- name = L["Units"],
- inline = true,
- args = {},
+ type = "input",
+ name = L["WoW Programming"],
+ desc = L["WoW Programming is a good resource for finding out what difference API's do and how to call them."],
+ set = false,
+ get = function() return "http://wowprogramming.com/docs" end,
+ width = "full",
},
},
},
@@ -3588,1420 +6210,1369 @@ local function loadUnitOptions()
},
}
- -- Load modules into the unit table
- for key, module in pairs(ShadowUF.modules) do
- local canHaveBar = module.moduleHasBar
- for _, data in pairs(ShadowUF.defaults.profile.units) do
- if( data[key] and data[key].isBar ~= nil ) then
- canHaveBar = true
+ -- Load the initial tag list
+ for tag in pairs(ShadowUF.Tags.defaultTags) do
+ options.args.tags.args.general.args.list.args[tag] = tagTable
+ end
+
+ for tag, data in pairs(ShadowUF.db.profile.tags) do
+ options.args.tags.args.general.args.list.args[tag] = tagTable
+ end
+end
+
+---------------------
+-- VISIBILITY OPTIONS
+---------------------
+local function loadVisibilityOptions()
+ -- As zone units are only enabled in a certain zone... it's pointless to provide visibility options for them
+ local unitBlacklist = {}
+ for unit in pairs(ShadowUF.Units.zoneUnits) do unitBlacklist[unit] = true end
+ for unit, parent in pairs(ShadowUF.Units.childUnits) do
+ if( ShadowUF.Units.zoneUnits[parent] ) then
+ unitBlacklist[unit] = true
+ end
+ end
+
+ local globalVisibility = {}
+ local function set(info, value)
+ local key = info[#(info)]
+ local unit = info[#(info) - 1]
+ local area = info[#(info) - 2]
+
+ if( key == "enabled" ) then
+ key = ""
+ end
+
+ if( value == nil ) then
+ value = false
+ elseif( value == false ) then
+ value = nil
+ end
+
+ for _, configUnit in pairs(ShadowUF.unitList) do
+ if( ( configUnit == unit or unit == "global" ) and not unitBlacklist[configUnit] ) then
+ ShadowUF.db.profile.visibility[area][configUnit .. key] = value
end
end
- if( canHaveBar ) then
- Config.unitTable.args.widgetSize.args[key] = Config.barTable
+ -- Annoying yes, but only way that works
+ ShadowUF.Units:CheckPlayerZone(true)
+
+ if( unit == "global" ) then
+ globalVisibility[area .. key] = value
end
end
-
- -- Load global unit
- for k, v in pairs(Config.unitTable.args) do
- options.args.units.args.global.args[k] = v
- end
-
- -- Load all of the per unit settings
- local perUnitList = {
- order = getUnitOrder,
- type = "toggle",
- name = getName,
- hidden = isUnitDisabled,
- desc = function(info)
- 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)]])
- end,
- }
- -- Enabled units list
- local unitCatOrder = {}
- local enabledUnits = {
- order = function(info) return unitCatOrder[info[#(info)]] + getUnitOrder(info) end,
- type = "toggle",
- name = getName,
- set = function(info, value)
- local unit = info[#(info)]
- for child, parent in pairs(ShadowUF.Units.childUnits) do
- if( unit == parent and not value ) then
- ShadowUF.db.profile.units[child].enabled = false
- end
- end
-
- ShadowUF.modules.movers:Update()
- ShadowUF.db.profile.units[unit].enabled = value
- ShadowUF:LoadUnits()
+ local function get(info)
+ local key = info[#(info)]
+ local unit = info[#(info) - 1]
+ local area = info[#(info) - 2]
- -- Update party frame visibility
- if( unit == "raid" and ShadowUF.Units.headerFrames.party ) then
- ShadowUF.Units:SetHeaderAttributes(ShadowUF.Units.headerFrames.party, "party")
- end
-
- ShadowUF.modules.movers:Update()
- end,
- get = function(info)
- return ShadowUF.db.profile.units[info[#(info)]].enabled
- end,
- desc = function(info)
- local unit = info[#(info)]
- local unitDesc = UNIT_DESC[unit] or ""
-
- if( ShadowUF.db.profile.units[unit].enabled and ShadowUF.Units.childUnits[unit] ) then
- if( unitDesc ~= "" ) then unitDesc = unitDesc .. "\n\n" end
- 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])
- elseif( not ShadowUF.db.profile.units[unit].enabled ) then
- for child, parent in pairs(ShadowUF.Units.childUnits) do
- if( parent == unit ) then
- if( unitDesc ~= "" ) then unitDesc = unitDesc .. "\n\n" end
- return unitDesc .. L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."]
- end
- end
- end
-
- return unitDesc ~= "" and unitDesc
- end,
- disabled = function(info)
- local unit = info[#(info)]
- if( ShadowUF.Units.childUnits[unit] ) then
- return not ShadowUF.db.profile.units[ShadowUF.Units.childUnits[unit]].enabled
+ if( key == "enabled" ) then
+ key = ""
+ end
+
+ if( unit == "global" ) then
+ if( globalVisibility[area .. key] == false ) then
+ return nil
+ elseif( globalVisibility[area .. key] == nil ) then
+ return false
end
+ return globalVisibility[area .. key]
+ elseif( ShadowUF.db.profile.visibility[area][unit .. key] == false ) then
+ return nil
+ elseif( ShadowUF.db.profile.visibility[area][unit .. key] == nil ) then
return false
- end,
- }
+ end
+
+ return ShadowUF.db.profile.visibility[area][unit .. key]
+ end
- local unitCategory = {
- order = function(info)
- local cat = info[#(info)]
- return cat == "playercat" and 50 or cat == "generalcat" and 100 or cat == "partycat" and 200 or cat == "raidcat" and 300 or 400
- end,
- type = "header",
+ local function getHelp(info)
+ local unit = info[#(info) - 1]
+ local area = info[#(info) - 2]
+ local key = info[#(info)]
+ if( key == "enabled" ) then
+ key = ""
+ end
+
+ local current
+ if( unit == "global" ) then
+ current = globalVisibility[area .. key]
+ else
+ current = ShadowUF.db.profile.visibility[area][unit .. key]
+ end
+
+ if( current == false ) then
+ return string.format(L["Disabled in %s"], AREA_NAMES[area])
+ elseif( current == true ) then
+ return string.format(L["Enabled in %s"], AREA_NAMES[area])
+ end
+
+ return L["Using unit settings"]
+ end
+
+ local areaTable = {
+ type = "group",
+ order = function(info) return info[#(info)] == "none" and 2 or 1 end,
+ childGroups = "tree",
name = function(info)
- local cat = info[#(info)]
- 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"]
+ return AREA_NAMES[info[#(info)]]
end,
- width = "full",
+ get = get,
+ set = set,
+ args = {},
+ }
+
+ Config.visibilityTable = {
+ type = "group",
+ order = function(info) return info[#(info)] == "global" and 1 or (getUnitOrder(info) + 1) end,
+ name = function(info) return info[#(info)] == "global" and L["Global"] or getName(info) end,
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ name = L["Help"],
+ inline = true,
+ hidden = hideBasicOption,
+ args = {
+ help = {
+ order = 0,
+ type = "description",
+ name = function(info)
+ 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]]))
+ end,
+ },
+ },
+ },
+ enabled = {
+ order = 0.25,
+ type = "toggle",
+ name = function(info)
+ local unit = info[#(info) - 1]
+ if( unit == "global" ) then return "" end
+ return string.format(L["%s frames"], L.units[unit])
+ end,
+ hidden = function(info) return info[#(info) - 1] == "global" end,
+ desc = getHelp,
+ tristate = true,
+ width = "double",
+ },
+ sep = {
+ order = 0.5,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = function(info) return info[#(info) - 1] == "global" end,
+ },
+ }
}
- for cat, list in pairs(unitCategories) do
- options.args.enableUnits.args.enabled.args[cat .. "cat"] = unitCategory
-
- for _, unit in pairs(list) do
- unitCatOrder[unit] = cat == "player" and 50 or cat == "general" and 100 or cat == "party" and 200 or cat == "raid" and 300 or 400
- end
- end
-
- for order, unit in pairs(ShadowUF.unitList) do
- options.args.enableUnits.args.enabled.args[unit] = enabledUnits
- options.args.units.args.global.args.units.args.units.args[unit] = perUnitList
- options.args.units.args[unit] = Config.unitTable
-
- unitCatOrder[unit] = unitCatOrder[unit] or 100
- end
-end
-
----------------------
--- FILTER CONFIGURATION
----------------------
-local function loadFilterOptions()
- local hasWhitelist, hasBlacklist, rebuildFilters
- local filterMap, spellMap = {}, {}
-
- local manageFiltersTable = {
- order = function(info) return info[#(info)] == "whitelists" and 1 or 2 end,
- type = "group",
- name = function(info) return info[#(info)] == "whitelists" and L["Whitelists"] or L["Blacklists"] end,
- args = {
- },
+ local moduleTable = {
+ order = 1,
+ type = "toggle",
+ name = getName,
+ desc = getHelp,
+ tristate = true,
+ hidden = function(info)
+ if( info[#(info) - 1] == "global" ) then return false end
+ return hideRestrictedOption(info)
+ end,
+ arg = 1,
}
-
- local function reloadUnitAuras()
- for _, frame in pairs(ShadowUF.Units.unitFrames) do
- if( UnitExists(frame.unit) and frame.visibility.auras ) then
- ShadowUF.modules.auras:UpdateFilter(frame)
- frame:FullUpdate()
- end
- end
- end
-
- local function setFilterType(info, value)
- local filter = filterMap[info[#(info) - 2]]
- local filterType = info[#(info) - 3]
- ShadowUF.db.profile.filters[filterType][filter][info[#(info)]] = value
- reloadUnitAuras()
+ for key, module in pairs(ShadowUF.modules) do
+ if( module.moduleName ) then
+ Config.visibilityTable.args[key] = moduleTable
+ end
end
- local function getFilterType(info)
- local filter = filterMap[info[#(info) - 2]]
- local filterType = info[#(info) - 3]
-
- return ShadowUF.db.profile.filters[filterType][filter][info[#(info)]]
+ areaTable.args.global = Config.visibilityTable
+ for _, unit in pairs(ShadowUF.unitList) do
+ if( not unitBlacklist[unit] ) then
+ areaTable.args[unit] = Config.visibilityTable
+ end
end
- --- Container widget for the filter listing
- local filterEditTable = {
- order = 0,
+ options.args.visibility = {
type = "group",
- name = function(info) return filterMap[info[#(info)]] end,
- hidden = function(info) return not ShadowUF.db.profile.filters[info[#(info) - 1]][filterMap[info[#(info)]]] end,
+ childGroups = "tab",
+ name = L["Zone Configuration"],
+ desc = getPageDescription,
args = {
- general = {
+ start = {
order = 0,
type = "group",
- name = function(info) return filterMap[info[#(info) - 1]] end,
- hidden = false,
+ name = L["Help"],
inline = true,
+ hidden = hideBasicOption,
args = {
- add = {
+ help = {
order = 0,
- type = "input",
- name = L["Aura name"],
- --dialogControl = "Aura_EditBox",
- hidden = false,
- set = function(info, value)
- local filterType = info[#(info) - 3]
- local filter = filterMap[info[#(info) - 2]]
-
- ShadowUF.db.profile.filters[filterType][filter][value] = true
-
- reloadUnitAuras()
- rebuildFilters()
- end,
- },
- delete = {
- order = 1,
- type = "execute",
- name = L["Delete filter"],
- hidden = false,
- confirmText = L["Are you sure you want to delete this filter?"],
- confirm = true,
- func = function(info, value)
- local filterType = info[#(info) - 3]
- local filter = filterMap[info[#(info) - 2]]
-
- ShadowUF.db.profile.filters[filterType][filter] = nil
-
- -- Delete anything that used this filter too
- local filterList = filterType == "whitelist" and ShadowUF.db.profile.filters.zonewhite or filterType == "blacklist" and ShadowUF.db.profile.filters.zoneblack
- for id, filterUsed in pairs(filterList) do
- if( filterUsed == filter ) then
- filterList[id] = nil
- end
- end
-
- reloadUnitAuras()
- rebuildFilters()
- end,
- },
- },
- },
- filters = {
- order = 2,
- type = "group",
- inline = true,
- hidden = false,
- name = L["Aura types to filter"],
- args = {
- buffs = {
- order = 4,
- type = "toggle",
- name = L["Buffs"],
- desc = L["When this filter is active, apply the filter to buffs."],
- set = setFilterType,
- get = getFilterType,
- },
- debuffs = {
- order = 5,
- type = "toggle",
- name = L["Debuffs"],
- desc = L["When this filter is active, apply the filter to debuffs."],
- set = setFilterType,
- get = getFilterType,
+ type = "description",
+ name = L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"],
},
},
},
- spells = {
- order = 3,
- type = "group",
- inline = true,
- name = L["Auras"],
- hidden = false,
- args = {
-
- },
- },
+ pvp = areaTable,
+ arena = areaTable,
+ party = areaTable,
+ raid = areaTable,
},
}
-
- -- Spell list for manage aura filters
- local spellLabel = {
- order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end,
- type = "description",
- -- Odd I know, AceConfigDialog-3.0 expands descriptions to full width if width is nil
- -- on the other hand we can't set width to "normal" so tricking it
- width = "",
- fontSize = "medium",
- name = function(info) return spellMap[info[#(info)]] end,
- }
-
- local spellRow = {
- order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.5 end,
- type = "execute",
- name = L["Delete"],
- width = "half",
- func = function(info)
- local spell = spellMap[info[#(info)]]
- local filter = filterMap[info[#(info) - 2]]
- local filterType = info[#(info) - 3]
-
- ShadowUF.db.profile.filters[filterType][filter][spell] = nil
- rebuildFilters()
- end
- }
+end
- local noSpells = {
- order = 0,
- type = "description",
- name = L["This filter has no auras in it, you will have to add some using the dialog above."],
- }
+---------------------
+-- AURA INDICATORS OPTIONS
+---------------------
+local function loadAuraIndicatorsOptions()
+ local Indicators = ShadowUF.modules.auraIndicators
+ local auraFilters = Indicators.auraFilters
- -- The filter [View] widgets for manage aura filters
- local filterLabel = {
- order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end,
- type = "description",
- width = "", -- Odd I know, AceConfigDialog-3.0 expands descriptions to full width if width is nil
- fontSize = "medium",
- name = function(info) return filterMap[info[#(info)]] end,
+ local unitTable
+
+ local groupAliases = {
+ ["pvpflags"] = L["PvP Flags"],
+ ["food"] = L["Food"],
+ ["miscellaneous"] = L["Miscellaneous"]
}
+
+ for token, name in pairs(LOCALIZED_CLASS_NAMES_MALE) do
+ groupAliases[string.lower(token)] = name
+ end
+
+ local groupList = {}
+ local function getAuraGroup(info)
+ for k in pairs(groupList) do groupList[k] = nil end
+ for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do
+ local aura = Indicators.auraConfig[name]
+ groupList[aura.group] = aura.group
+ end
- local filterRow = {
- order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.5 end,
- type = "execute",
- name = L["View"],
- width = "half",
- func = function(info)
- local filterType = info[#(info) - 2]
-
- AceDialog.Status.ShadowedUF.children.filter.children.filters.status.groups.groups[filterType] = true
- selectTabGroup("filter", "filters", filterType .. "\001" .. string.match(info[#(info)], "(%d+)"))
+ return groupList
+ end
+
+ local auraList = {}
+ local function getAuraList(info)
+ for k in pairs(auraList) do auraList[k] = nil end
+ for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do
+ if( tonumber(name) ) then
+ local spellID = name
+ name = GetSpellInfo(name) or L["Unknown"]
+ auraList[name] = string.format("%s (#%i)", name, spellID)
+ else
+ auraList[name] = name
+ end
+ end
+
+ return auraList
+ end
+
+ local indicatorList = {}
+ local function getIndicatorList(info)
+ for k in pairs(indicatorList) do indicatorList[k] = nil end
+ indicatorList[""] = L["None (Disabled)"]
+ for key, indicator in pairs(ShadowUF.db.profile.auraIndicators.indicators) do
+ indicatorList[key] = indicator.name
end
- }
- local noFilters = {
- order = 0,
- type = "description",
- 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."],
- }
+ return indicatorList
+ end
- -- Container table for a filter zone
- local globalSettings = {}
- local zoneList = {"none", "pvp", "arena", "party", "raid"}
- local filterTable = {
- order = function(info) return info[#(info)] == "global" and 1 or info[#(info)] == "none" and 2 or 3 end,
- type = "group",
- inline = true,
- hidden = function() return not hasWhitelist and not hasBlacklist end,
- name = function(info) return AREA_NAMES[info[#(info)]] or L["Global"] end,
- set = function(info, value)
- local filter = filterMap[info[#(info)]]
- local zone = info[#(info) - 1]
- local unit = info[#(info) - 2]
- local filterKey = ShadowUF.db.profile.filters.whitelists[filter] and "zonewhite" or "zoneblack"
-
- for _, zoneConfig in pairs(zoneList) do
- if( zone == "global" or zoneConfig == zone ) then
- if( unit == "global" ) then
- globalSettings[zoneConfig .. filterKey] = value and filter or false
-
- for _, unit in pairs(ShadowUF.unitList) do
- ShadowUF.db.profile.filters[filterKey][zoneConfig .. unit] = value and filter or nil
- end
- else
- ShadowUF.db.profile.filters[filterKey][zoneConfig .. unit] = value and filter or nil
- end
+ local function writeAuraTable(name)
+ ShadowUF.db.profile.auraIndicators.auras[name] = writeTable(Indicators.auraConfig[name])
+ Indicators.auraConfig[name] = nil
+
+ local spellID = tonumber(name)
+ if( spellID ) then
+ Indicators.auraConfig[spellID] = nil
+ end
+ end
+
+ local groupMap, auraMap, linkMap = {}, {}, {}
+ local groupID, auraID, linkID = 0, 0, 0
+
+ local reverseClassMap = {}
+ for token, text in pairs(LOCALIZED_CLASS_NAMES_MALE) do
+ reverseClassMap[text] = token
+ end
+
+ local function groupName(name)
+ local converted = string.lower(string.gsub(name, " ", ""))
+ return groupAliases[converted] or name
+ end
+
+ -- Actual aura configuration
+ local auraGroupTable = {
+ order = function(info)
+ return reverseClassMap[groupName(groupMap[info[#(info)]])] and 1 or 2
+ end,
+ type = "group",
+ name = function(info)
+ local name = groupName(groupMap[info[#(info)]])
+
+ local token = reverseClassMap[name]
+ if( not token ) then return name end
+
+ return ShadowUF:Hex(ShadowUF.db.profile.classColors[token]) .. name .. "|r"
+ end,
+ desc = function(info)
+ local group = groupMap[info[#(info)]]
+ local totalInGroup = 0
+ for _, aura in pairs(Indicators.auraConfig) do
+ if( type(aura) == "table" and aura.group == group ) then
+ totalInGroup = totalInGroup + 1
end
end
- if( zone == "global" ) then
- globalSettings[zone .. unit .. filterKey] = value and filter or false
- end
-
- reloadUnitAuras()
+ return string.format(L["%d auras in group"], totalInGroup)
end,
- get = function(info)
- local filter = filterMap[info[#(info)]]
- local zone = info[#(info) - 1]
- local unit = info[#(info) - 2]
-
- if( unit == "global" or zone == "global" ) then
- local id = zone == "global" and zone .. unit or zone
- local filterKey = ShadowUF.db.profile.filters.whitelists[filter] and "zonewhite" or "zoneblack"
-
- if( info[#(info)] == "nofilter" ) then
- return globalSettings[id .. "zonewhite"] == false and globalSettings[id .. "zoneblack"] == false
- end
+ args = {},
+ }
+
+ local auraConfigTable = {
+ order = 0,
+ type = "group",
+ icon = function(info)
+ local aura = auraMap[info[#(info)]]
+ return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil
+ end,
+ name = function(info)
+ local aura = auraMap[info[#(info)]]
+ return tonumber(aura) and string.format("%s (#%i)", GetSpellInfo(aura) or "Unknown", aura) or aura
+ end,
+ hidden = function(info)
+ local group = groupMap[info[#(info) - 1]]
+ local aura = Indicators.auraConfig[auraMap[info[#(info)]]]
+ return aura.group ~= group
+ end,
+ set = function(info, value, g, b, a)
+ local aura = auraMap[info[#(info) - 1]]
+ local key = info[#(info)]
- return globalSettings[id .. filterKey] == filter
+ -- So I don't have to load every aura to see if it only triggers if it's missing
+ if( key == "missing" ) then
+ ShadowUF.db.profile.auraIndicators.missing[aura] = value and true or nil
+ -- Changing the color
+ elseif( key == "color" ) then
+ Indicators.auraConfig[aura].r = value
+ Indicators.auraConfig[aura].g = g
+ Indicators.auraConfig[aura].b = b
+ Indicators.auraConfig[aura].alpha = a
+
+ writeAuraTable(aura)
+ ShadowUF.Layout:Reload()
+ return
+ elseif( key == "selfColor" ) then
+ Indicators.auraConfig[aura].selfColor = Indicators.auraConfig[aura].selfColor or {}
+ Indicators.auraConfig[aura].selfColor.r = value
+ Indicators.auraConfig[aura].selfColor.g = g
+ Indicators.auraConfig[aura].selfColor.b = b
+ Indicators.auraConfig[aura].selfColor.alpha = a
+
+ writeAuraTable(aura)
+ ShadowUF.Layout:Reload()
+ return
end
-
- if( info[#(info)] == "nofilter" ) then
- return not ShadowUF.db.profile.filters.zonewhite[zone .. unit] and not ShadowUF.db.profile.filters.zoneblack[zone .. unit]
+
+ Indicators.auraConfig[aura][key] = value
+ writeAuraTable(aura)
+ ShadowUF.Layout:Reload()
+ end,
+ get = function(info)
+ local aura = auraMap[info[#(info) - 1]]
+ local key = info[#(info)]
+ local config = Indicators.auraConfig[aura]
+ if( key == "color" ) then
+ return config.r, config.g, config.b, config.alpha
+ elseif( key == "selfColor" ) then
+ if( not config.selfColor ) then return 0, 0, 0, 1 end
+ return config.selfColor.r, config.selfColor.g, config.selfColor.b, config.selfColor.alpha
end
- return ShadowUF.db.profile.filters.zonewhite[zone .. unit] == filter or ShadowUF.db.profile.filters.zoneblack[zone .. unit] == filter
+ return config[key]
end,
- args = {
- nofilter = {
- order = 0,
+ args = {
+ indicator = {
+ order = 1,
+ type = "select",
+ name = L["Show inside"],
+ desc = L["Indicator this aura should be displayed in."],
+ values = getIndicatorList,
+ hidden = false,
+ },
+ priority = {
+ order = 2,
+ type = "range",
+ name = L["Priority"],
+ desc = L["If multiple auras are shown in the same indicator, the higher priority one is shown first."],
+ min = 0, max = 100, step = 1,
+ hidden = false,
+ },
+ sep1 = {
+ order = 3,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = false,
+ },
+ color = {
+ order = 4,
+ type = "color",
+ name = L["Indicator color"],
+ desc = L["Solid color to use in the indicator, only used if you do not have use aura icon enabled."],
+ disabled = function(info) return Indicators.auraConfig[auraMap[info[#(info) - 1]]].icon end,
+ hidden = false,
+ hasAlpha = true,
+ },
+ selfColor = {
+ order = 4.5,
+ type = "color",
+ name = L["Your aura color"],
+ 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."],
+ hidden = false,
+ disabled = function(info)
+ if( Indicators.auraConfig[auraMap[info[#(info) - 1]]].icon ) then return true end
+ return Indicators.auraConfig[auraMap[info[#(info) - 1]]].player
+ end,
+ hasAlpha = true,
+ },
+ sep2 = {
+ order = 5,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = false,
+ },
+ icon = {
+ order = 6,
type = "toggle",
- name = L["Don't use a filter"],
+ name = L["Show aura icon"],
+ desc = L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."],
hidden = false,
- set = function(info, value)
- local filter = filterMap[info[#(info)]]
- local zone = info[#(info) - 1]
- local unit = info[#(info) - 2]
-
- for _, zoneConfig in pairs(zoneList) do
- if( zone == "global" or zoneConfig == zone ) then
- if( unit == "global" ) then
- globalSettings[zoneConfig .. "zonewhite"] = false
- globalSettings[zoneConfig .. "zoneblack"] = false
-
- for _, unit in pairs(ShadowUF.unitList) do
- ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unit] = nil
- ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unit] = nil
- end
- else
- ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unit] = nil
- ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unit] = nil
- end
- end
- end
+ },
+ duration = {
+ order = 7,
+ type = "toggle",
+ name = L["Show aura duration"],
+ desc = L["Shows a cooldown wheel on the indicator with how much time is left on the aura."],
+ hidden = false,
+ },
+ player = {
+ order = 8,
+ type = "toggle",
+ name = L["Only show self cast auras"],
+ desc = L["Only auras you specifically cast will be shown."],
+ hidden = false,
+ },
+ missing = {
+ order = 9,
+ type = "toggle",
+ name = L["Only show if missing"],
+ desc = L["Only active this aura inside an indicator if the group member does not have the aura."],
+ hidden = false,
+ },
+ delete = {
+ order = 10,
+ type = "execute",
+ name = L["Delete"],
+ hidden = function(info)
+ return ShadowUF.db.defaults.profile.auraIndicators.auras[auraMap[info[#(info) - 1]]]
+ end,
+ confirm = true,
+ confirmText = L["Are you sure you want to delete this aura?"],
+ func = function(info)
+ local key = info[#(info) - 1]
+ local aura = auraMap[key]
- if( zone == "global" ) then
- globalSettings[zone .. unit .. "zonewhite"] = false
- globalSettings[zone .. unit .. "zoneblack"] = false
+ auraGroupTable.args[key] = nil
+ ShadowUF.db.profile.auraIndicators.auras[aura] = nil
+ ShadowUF.db.profile.auraIndicators.missing[aura] = nil
+ Indicators.auraConfig[aura] = nil
+
+ -- Check if the group should disappear
+ local groupList = getAuraGroup(info)
+ for groupID, name in pairs(groupMap) do
+ if( not groupList[name] ) then
+ unitTable.args[tostring(groupID)] = nil
+ options.args.auraIndicators.args.units.args.global.args.groups.args[tostring(groupID)] = nil
+ options.args.auraIndicators.args.auras.args.groups.args[tostring(groupID)] = nil
+ groupMap[groupID] = nil
+ end
end
-
- reloadUnitAuras()
+
+ ShadowUF.Layout:Reload()
end,
},
- white = {
- order = 1,
- type = "header",
- name = "|cffffffff" .. L["Whitelists"] .. "|r",
- hidden = function(info) return not hasWhitelist end
- },
- black = {
- order = 3,
- type = "header",
- name = L["Blacklists"], -- In theory I would make this black, but as black doesn't work with a black background I'll skip that
- hidden = function(info) return not hasBlacklist end
- },
},
}
-
- -- Toggle used for set filter zones to enable filters
- local filterToggle = {
- order = function(info) return ShadowUF.db.profile.filters.whitelists[filterMap[info[#(info)]]] and 2 or 4 end,
- type = "toggle",
- name = function(info) return filterMap[info[#(info)]] end,
- desc = function(info)
- local filter = filterMap[info[#(info)]]
- filter = ShadowUF.db.profile.filters.whitelists[filter] or ShadowUF.db.profile.filters.blacklists[filter]
- if( filter.buffs and filter.debuffs ) then
- return L["Filtering both buffs and debuffs"]
- elseif( filter.buffs ) then
- return L["Filtering buffs only"]
- elseif( filter.debuffs ) then
- return L["Filtering debuffs only"]
+
+ local auraFilterConfigTable = {
+ order = 0,
+ type = "group",
+ hidden = false,
+ name = function(info)
+ return ShadowUF.db.profile.auraIndicators.indicators[info[#(info)]].name
+ end,
+ set = function(info, value)
+ local key = info[#(info)]
+ local indicator = info[#(info) - 2]
+ local filter = info[#(info) - 1]
+ ShadowUF.db.profile.auraIndicators.filters[indicator][filter][key] = value
+ ShadowUF.Layout:Reload()
+ end,
+ get = function(info)
+ local key = info[#(info)]
+ local indicator = info[#(info) - 2]
+ local filter = info[#(info) - 1]
+ if( not ShadowUF.db.profile.auraIndicators.filters[indicator][filter] ) then
+ ShadowUF.db.profile.auraIndicators.filters[indicator][filter] = {}
end
-
- return L["This filter has no aura types set to filter out."]
+
+ return ShadowUF.db.profile.auraIndicators.filters[indicator][filter][key]
end,
- }
-
- -- Load existing filters in
- -- This needs to be cleaned up later
- local filterID, spellID = 0, 0
- local function buildList(type)
- local manageFiltersTable = {
- order = type == "whitelists" and 1 or 2,
- type = "group",
- name = type == "whitelists" and L["Whitelists"] or L["Blacklists"],
- args = {
- groups = {
- order = 0,
- type = "group",
- inline = true,
- name = function(info) return info[#(info) - 1] == "whitelists" and L["Whitelist filters"] or L["Blacklist filters"] end,
- args = {
+ args = {
+ help = {
+ order = 0,
+ type = "group",
+ name = L["Help"],
+ inline = true,
+ args = {
+ help = {
+ type = "description",
+ name = L["Auras matching a criteria will automatically show up in the indicator when enabled."]
+ }
+ }
+ },
+ boss = {
+ order = 1,
+ type = "group",
+ name = L["Boss Auras"],
+ inline = true,
+ args = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = L["Show boss debuffs"],
+ desc = L["Shows debuffs cast by a boss."]
},
- },
+ duration = {
+ order = 2,
+ type = "toggle",
+ name = L["Show aura duration"],
+ desc = L["Shows a cooldown wheel on the indicator with how much time is left on the aura."]
+ },
+ priority = {
+ order = 3,
+ type = "range",
+ name = L["Priority"],
+ desc = L["If multiple auras are shown in the same indicator, the higher priority one is shown first."],
+ min = 0, max = 100, step = 1
+ }
+ }
},
- }
-
- local hasFilters
- for name, spells in pairs(ShadowUF.db.profile.filters[type]) do
- hasFilters = true
- filterID = filterID + 1
- filterMap[tostring(filterID)] = name
- filterMap[filterID .. "label"] = name
- filterMap[filterID .. "row"] = name
-
- manageFiltersTable.args[tostring(filterID)] = CopyTable(filterEditTable)
- manageFiltersTable.args.groups.args[filterID .. "label"] = filterLabel
- manageFiltersTable.args.groups.args[filterID .. "row"] = filterRow
- filterTable.args[tostring(filterID)] = filterToggle
-
- local hasSpells
- for spellName in pairs(spells) do
- if( spellName ~= "buffs" and spellName ~= "debuffs" ) then
- hasSpells = true
- spellID = spellID + 1
- spellMap[tostring(spellID)] = spellName
- spellMap[spellID .. "label"] = spellName
-
- manageFiltersTable.args[tostring(filterID)].args.spells.args[spellID .. "label"] = spellLabel
- manageFiltersTable.args[tostring(filterID)].args.spells.args[tostring(spellID)] = spellRow
- end
- end
-
- if( not hasSpells ) then
- manageFiltersTable.args[tostring(filterID)].args.spells.args.noSpells = noSpells
- end
- end
-
- if( not hasFilters ) then
- if( type == "whitelists" ) then hasWhitelist = nil else hasBlacklist = nil end
- manageFiltersTable.args.groups.args.noFilters = noFilters
- end
-
- return manageFiltersTable
- end
-
- rebuildFilters = function()
- for id in pairs(filterMap) do filterTable.args[id] = nil end
-
- spellID = 0
- filterID = 0
- hasBlacklist = true
- hasWhitelist = true
+ curable = {
+ order = 2,
+ type = "group",
+ name = L["Curable Auras"],
+ inline = true,
+ args = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = L["Show curable debuffs"],
+ desc = L["Shows debuffs that you can cure."]
+ },
+ duration = {
+ order = 2,
+ type = "toggle",
+ name = L["Show aura duration"],
+ desc = L["Shows a cooldown wheel on the indicator with how much time is left on the aura."]
+ },
+ priority = {
+ order = 3,
+ type = "range",
+ name = L["Priority"],
+ desc = L["If multiple auras are shown in the same indicator, the higher priority one is shown first."],
+ min = 0, max = 100, step = 1
+ }
+ }
+ }
+ }
+ }
- table.wipe(filterMap)
- table.wipe(spellMap)
-
- options.args.filter.args.filters.args.whitelists = buildList("whitelists")
- options.args.filter.args.filters.args.blacklists = buildList("blacklists")
- end
-
- local unitFilterSelection = {
- order = function(info) return info[#(info)] == "global" and 1 or (getUnitOrder(info) + 1) end,
+ local indicatorTable = {
+ order = 1,
type = "group",
- name = function(info) return info[#(info)] == "global" and L["Global"] or getName(info) end,
- disabled = function(info)
- if( info[#(info)] == "global" ) then
- return false
- end
-
- return not hasWhitelist and not hasBlacklist
- end,
+ name = function(info) return ShadowUF.db.profile.auraIndicators.indicators[info[#(info)]].name end,
args = {
- help = {
+ config = {
order = 0,
type = "group",
inline = true,
- name = L["Help"],
- hidden = function() return hasWhitelist or hasBlacklist end,
+ name = function(info) return ShadowUF.db.profile.auraIndicators.indicators[info[#(info) - 1]].name end,
+ set = function(info, value)
+ local indicator = info[#(info) - 2]
+ local key = info[#(info)]
+
+ ShadowUF.db.profile.auraIndicators.indicators[indicator][key] = value
+ ShadowUF.Layout:Reload()
+ end,
+ get = function(info)
+ local indicator = info[#(info) - 2]
+ local key = info[#(info)]
+ return ShadowUF.db.profile.auraIndicators.indicators[indicator][key]
+ end,
args = {
- help = {
- type = "description",
- name = L["You will need to create an aura filter before you can set which unit to enable aura filtering on."],
+ showStack = {
+ order = 1,
+ type = "toggle",
+ name = L["Show auras stack"],
+ desc = L["Any auras shown in this indicator will have their total stack displayed."],
width = "full",
- }
+ },
+ friendly = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable for friendlies"],
+ desc = L["Checking this will show the indicator on friendly units."],
+ },
+ hostile = {
+ order = 3,
+ type = "toggle",
+ name = L["Enable for hostiles"],
+ desc = L["Checking this will show the indciator on hostile units."],
+ },
+ anchorPoint = {
+ order = 4,
+ type = "select",
+ name = L["Anchor point"],
+ 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"]},
+ },
+ size = {
+ order = 5,
+ name = L["Size"],
+ type = "range",
+ min = 0, max = 50, step = 1,
+ set = function(info, value)
+ local indicator = info[#(info) - 2]
+ ShadowUF.db.profile.auraIndicators.indicators[indicator].height = value
+ ShadowUF.db.profile.auraIndicators.indicators[indicator].width = value
+ ShadowUF.Layout:Reload()
+ end,
+ get = function(info)
+ local indicator = info[#(info) - 2]
+ return ShadowUF.db.profile.auraIndicators.indicators[indicator].height
+ end,
+ },
+ x = {
+ order = 6,
+ type = "range",
+ name = L["X Offset"],
+ min = -50, max = 50, step = 1,
+ },
+ y = {
+ order = 7,
+ type = "range",
+ name = L["Y Offset"],
+ min = -50, max = 50, step = 1,
+ },
+ delete = {
+ order = 8,
+ type = "execute",
+ name = L["Delete"],
+ confirm = true,
+ confirmText = L["Are you sure you want to delete this indicator?"],
+ func = function(info)
+ local indicator = info[#(info) - 2]
+
+ options.args.auraIndicators.args.indicators.args[indicator] = nil
+ options.args.auraIndicators.args.auras.args.filters.args[indicator] = nil
+
+ ShadowUF.db.profile.auraIndicators.indicators[indicator] = nil
+ ShadowUF.db.profile.auraIndicators.filters[indicator] = nil
+
+ -- Any aura that was set to us should be swapped back to none
+ for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do
+ local aura = Indicators.auraConfig[name]
+ if( aura.indicator == indicator ) then
+ aura.indicator = ""
+ writeAuraTable(name)
+ end
+ end
+
+ ShadowUF.Layout:Reload()
+ end,
+ },
},
},
- header = {
- order = 0,
- type = "header",
- name = function(info) return (info[#(info) - 1] == "global" and L["Global"] or L.units[info[#(info) - 1]]) end,
- hidden = function() return not hasWhitelist and not hasBlacklist end,
- },
- global = filterTable,
- none = filterTable,
- pvp = filterTable,
- arena = filterTable,
- party = filterTable,
- raid = filterTable,
- }
+ },
}
- local addFilter = {type = "whitelists"}
+ local parentLinkTable = {
+ order = 3,
+ type = "group",
+ icon = function(info)
+ local aura = auraMap[info[#(info)]]
+ return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil
+ end,
+ name = function(info)
+ local aura = linkMap[info[#(info)]]
+ return tonumber(aura) and string.format("%s (#%i)", GetSpellInfo(aura) or "Unknown", aura) or aura
+ end,
+ args = {},
+ }
- options.args.filter = {
+ local childLinkTable = {
+ order = 1,
+ icon = function(info)
+ local aura = auraMap[info[#(info)]]
+ return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil
+ end,
+ name = function(info)
+ local aura = linkMap[info[#(info)]]
+ return tonumber(aura) and string.format("%s (#%i)", GetSpellInfo(aura) or "Unknown", aura) or aura
+ end,
+ hidden = function(info)
+ local aura = linkMap[info[#(info)]]
+ local parent = linkMap[info[#(info) - 1]]
+
+ return ShadowUF.db.profile.auraIndicators.linked[aura] ~= parent
+ end,
type = "group",
- name = L["Aura filters"],
- childGroups = "tab",
- desc = getPageDescription,
+ inline = true,
args = {
- groups = {
+ delete = {
+ type = "execute",
+ name = L["Delete link"],
+ hidden = false,
+ func = function(info)
+ local auraID = info[#(info) - 1]
+ local aura = linkMap[auraID]
+ local parent = ShadowUF.db.profile.auraIndicators.linked[aura]
+ ShadowUF.db.profile.auraIndicators.linked[aura] = nil
+ parentLinkTable.args[auraID] = nil
+
+ local found
+ for _, to in pairs(ShadowUF.db.profile.auraIndicators.linked) do
+ if( to == parent ) then
+ found = true
+ break
+ end
+ end
+
+ if( not found ) then
+ for id, name in pairs(linkMap) do
+ if( name == parent ) then
+ options.args.auraIndicators.args.linked.args[tostring(id)] = nil
+ linkMap[id] = nil
+ end
+ end
+ end
+
+ ShadowUF.Layout:Reload()
+ end,
+ },
+ },
+ }
+
+ local addAura, addLink, setGlobalUnits, globalConfig = {}, {}, {}, {}
+
+ -- Per unit enabled status
+ unitTable = {
+ order = ShadowUF.Config.getUnitOrder or 1,
+ type = "group",
+ name = function(info) return L.units[info[3]] end,
+ hidden = function(info) return not ShadowUF.db.profile.units[info[3]].enabled end,
+ desc = function(info)
+ local totalDisabled = 0
+ for key, enabled in pairs(ShadowUF.db.profile.units[info[3]].auraIndicators) do
+ if( key ~= "enabled" and enabled ) then
+ totalDisabled = totalDisabled + 1
+ end
+ end
+
+ if( totalDisabled == 1 ) then return L["1 aura group disabled"] end
+ return totalDisabled > 0 and string.format(L["%s aura groups disabled"], totalDisabled) or L["All aura groups enabled for unit."]
+ end,
+ args = {
+ enabled = {
order = 1,
+ inline = true,
type = "group",
- name = L["Set filter zones"],
+ name = function(info) return string.format(L["On %s units"], L.units[info[3]]) end,
args = {
- help = {
- order = 0,
- type = "group",
- inline = true,
- name = L["Help"],
- args = {
- help = {
- type = "description",
- 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."],
- width = "full",
- }
- },
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = L["Enable Indicators"],
+ desc = function(info) return string.format(L["Unchecking this will completely disable aura indicators for %s."], L.units[info[3]]) end,
+ set = function(info, value) ShadowUF.db.profile.units[info[3]].auraIndicators.enabled = value; ShadowUF.Layout:Reload() end,
+ get = function(info) return ShadowUF.db.profile.units[info[3]].auraIndicators.enabled end,
},
- }
+ },
},
filters = {
order = 2,
+ inline = true,
type = "group",
- name = L["Manage aura filters"],
- childGroups = "tree",
- args = {
- manage = {
- order = 1,
- type = "group",
- name = L["Management"],
- args = {
- help = {
- order = 0,
- type = "group",
- inline = true,
- name = L["Help"],
- args = {
- help = {
- type = "description",
- name = L["Whitelists will hide any aura not in the filter group.|nBlacklists will hide auras that are in the filter group."],
- width = "full",
- }
- },
- },
- error = {
- order = 1,
- type = "group",
- inline = true,
- hidden = function() return not addFilter.error end,
- name = L["Error"],
- args = {
- error = {
- order = 0,
- type = "description",
- name = function() return addFilter.error end,
- width = "full",
- },
- },
- },
- add = {
- order = 2,
- type = "group",
- inline = true,
- name = L["New filter"],
- get = function(info) return addFilter[info[#(info)]] end,
- args = {
- name = {
- order = 0,
- type = "input",
- name = L["Name"],
- set = function(info, value)
- addFilter[info[#(info)]] = string.trim(value) ~= "" and value or nil
- addFilter.error = nil
- end,
- get = function(info) return addFilter.errorName or addFilter.name end,
- validate = function(info, value)
- local name = string.lower(string.trim(value))
- for filter in pairs(ShadowUF.db.profile.filters.whitelists) do
- if( string.lower(filter) == name ) then
- addFilter.error = string.format(L["The whitelist \"%s\" already exists."], value)
- addFilter.errorName = value
- AceRegistry:NotifyChange("ShadowedUF")
- return ""
- end
- end
-
- for filter in pairs(ShadowUF.db.profile.filters.blacklists) do
- if( string.lower(filter) == name ) then
- addFilter.error = string.format(L["The blacklist \"%s\" already exists."], value)
- addFilter.errorName = value
- AceRegistry:NotifyChange("ShadowedUF")
- return ""
- end
- end
-
- addFilter.error = nil
- addFilter.errorName = nil
- return true
- end,
- },
- type = {
- order = 1,
- type = "select",
- name = L["Filter type"],
- set = function(info, value) addFilter[info[#(info)]] = value end,
- values = {["whitelists"] = L["Whitelist"], ["blacklists"] = L["Blacklist"]},
- },
- add = {
- order = 2,
- type = "execute",
- name = L["Create"],
- disabled = function(info) return not addFilter.name end,
- func = function(info)
- ShadowUF.db.profile.filters[addFilter.type][addFilter.name] = {buffs = true, debuffs = true}
- rebuildFilters()
-
- local id
- for key, value in pairs(filterMap) do
- if( value == addFilter.name ) then
- id = key
- break
- end
- end
-
- AceDialog.Status.ShadowedUF.children.filter.children.filters.status.groups.groups[addFilter.type] = true
- selectTabGroup("filter", "filters", addFilter.type .. "\001" .. id)
-
- table.wipe(addFilter)
- addFilter.type = "whitelists"
- end,
- },
- },
- },
- },
- },
- },
+ name = L["Aura Filters"],
+ disabled = function(info) return not ShadowUF.db.profile.units[info[3]].auraIndicators.enabled end,
+ args = {},
+ },
+ groups = {
+ order = 3,
+ inline = true,
+ type = "group",
+ name = L["Aura Groups"],
+ disabled = function(info) return not ShadowUF.db.profile.units[info[3]].auraIndicators.enabled end,
+ args = {},
},
- },
+ }
+ }
+
+ local unitFilterTable = {
+ order = 1,
+ type = "toggle",
+ name = function(info) return info[#(info)] == "boss" and L["Boss Auras"] or L["Curable Auras"] end,
+ desc = function(info)
+ local auraIndicators = ShadowUF.db.profile.units[info[3]].auraIndicators
+ 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]])
+ end,
+ set = function(info, value) ShadowUF.db.profile.units[info[3]].auraIndicators["filter-" .. info[#(info)]] = not value and true or nil end,
+ get = function(info, value) return not ShadowUF.db.profile.units[info[3]].auraIndicators["filter-" .. info[#(info)]] end
}
+ local globalUnitFilterTable = {
+ order = 1,
+ type = "toggle",
+ name = function(info) return info[#(info)] == "boss" and L["Boss Auras"] or L["Curable Auras"] end,
+ disabled = function(info) for unit in pairs(setGlobalUnits) do return false end return true end,
+ set = function(info, value)
+ local key = "filter-" .. info[#(info)]
+ globalConfig[key] = not value and true or nil
+
+ for unit in pairs(setGlobalUnits) do
+ ShadowUF.db.profile.units[unit].auraIndicators[key] = globalConfig[key]
+ end
+ end,
+ get = function(info, value) return not globalConfig["filter-" .. info[#(info)]] end
+ }
- options.args.filter.args.groups.args.global = unitFilterSelection
- for _, unit in pairs(ShadowUF.unitList) do
- options.args.filter.args.groups.args[unit] = unitFilterSelection
- end
-
- rebuildFilters()
-end
+ local unitGroupTable = {
+ order = function(info)
+ return reverseClassMap[groupName(groupMap[info[#(info)]])] and 1 or 2
+ end,
+ type = "toggle",
+ name = function(info)
+ local name = groupName(groupMap[info[#(info)]])
+ local token = reverseClassMap[name]
+ if( not token ) then return name end
+ return ShadowUF:Hex(ShadowUF.db.profile.classColors[token]) .. name .. "|r"
+ end,
+ desc = function(info)
+ local auraIndicators = ShadowUF.db.profile.units[info[3]].auraIndicators
+ local group = groupName(groupMap[info[#(info)]])
+
+ 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]])
+ end,
+ set = function(info, value) ShadowUF.db.profile.units[info[3]].auraIndicators[groupMap[info[#(info)]]] = not value and true or nil end,
+ get = function(info, value) return not ShadowUF.db.profile.units[info[3]].auraIndicators[groupMap[info[#(info)]]] end
+ }
----------------------
--- TAG CONFIGURATION
----------------------
-local function loadTagOptions()
- local tagData = {search = ""}
- local function set(info, value, key)
- local key = key or info[#(info)]
- if( ShadowUF.Tags.defaultHelp[tagData.name] ) then
- return
- end
-
- -- Reset loaded function + reload tags
- if( key == "funct" ) then
- ShadowUF.tagFunc[tagData.name] = nil
- ShadowUF.Tags:Reload()
- elseif( key == "category" ) then
- local cat = ShadowUF.db.profile.tags[tagData.name][key]
- if( cat and cat ~= value ) then
- Config.tagTextTable.args[cat].args[tagData.name] = nil
- Config.tagTextTable.args[value].args[tagData.name] = Config.tagTable
+ local globalUnitGroupTable = {
+ type = "toggle",
+ order = function(info)
+ return reverseClassMap[groupName(groupMap[info[#(info)]])] and 1 or 2
+ end,
+ name = function(info)
+ local name = groupName(groupMap[info[#(info)]])
+ local token = reverseClassMap[name]
+ if( not token ) then return name end
+ return ShadowUF:Hex(ShadowUF.db.profile.classColors[token]) .. name .. "|r"
+ end,
+ disabled = function(info) for unit in pairs(setGlobalUnits) do return false end return true end,
+ set = function(info, value)
+ local auraGroup = groupMap[info[#(info)]]
+ globalConfig[auraGroup] = not value and true or nil
+
+ for unit in pairs(setGlobalUnits) do
+ ShadowUF.db.profile.units[unit].auraIndicators[auraGroup] = globalConfig[auraGroup]
end
- end
-
- ShadowUF.db.profile.tags[tagData.name][key] = value
- end
-
- local function stripCode(text)
- if( not text ) then
- return ""
- end
-
- return string.gsub(string.gsub(text, "|", "||"), "\t", "")
- end
-
- local function get(info, key)
- local key = key or info[#(info)]
-
- if( key == "help" and ShadowUF.Tags.defaultHelp[tagData.name] ) then
- return ShadowUF.Tags.defaultHelp[tagData.name] or ""
- elseif( key == "events" and ShadowUF.Tags.defaultEvents[tagData.name] ) then
- return ShadowUF.Tags.defaultEvents[tagData.name] or ""
- elseif( key == "frequency" and ShadowUF.Tags.defaultFrequents[tagData.name] ) then
- return ShadowUF.Tags.defaultFrequents[tagData.name] or ""
- elseif( key == "category" and ShadowUF.Tags.defaultCategories[tagData.name] ) then
- return ShadowUF.Tags.defaultCategories[tagData.name] or ""
- elseif( key == "name" and ShadowUF.Tags.defaultNames[tagData.name] ) then
- return ShadowUF.Tags.defaultNames[tagData.name] or ""
- elseif( key == "funct" and ShadowUF.Tags.defaultTags[tagData.name] ) then
- return ShadowUF.Tags.defaultTags[tagData.name] or ""
- end
-
- return ShadowUF.db.profile.tags[tagData.name] and ShadowUF.db.profile.tags[tagData.name][key] or ""
- end
-
- local function isSearchHidden(info)
- return tagData.search ~= "" and not string.match(info[#(info)], tagData.search) or false
- end
-
- local function editTag(info)
- tagData.name = info[#(info)]
-
- if( ShadowUF.Tags.defaultHelp[tagData.name] ) then
- 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."]
- end
-
- selectDialogGroup("tags", "edit")
- end
-
- -- Create all of the tag editor options, if it's a default tag will show it after any custom ones
- local tagTable = {
- type = "execute",
- order = function(info) return ShadowUF.Tags.defaultTags[info[#(info)]] and 100 or 1 end,
- name = getTagName,
- desc = getTagHelp,
- hidden = isSearchHidden,
- func = editTag,
+ end,
+ get = function(info, value) return not globalConfig[groupMap[info[#(info)]]] end
}
- local tagCategories = {}
- local function getTagCategories(info)
- for k in pairs(tagCategories) do tagCategories[k] = nil end
-
- for _, cat in pairs(ShadowUF.Tags.defaultCategories) do
- tagCategories[cat] = TAG_GROUPS[cat]
+ local enabledUnits = {}
+ local function getEnabledUnits()
+ table.wipe(enabledUnits)
+ for unit, config in pairs(ShadowUF.db.profile.units) do
+ if( config.enabled and config.auraIndicators.enabled ) then
+ enabledUnits[unit] = L.units[unit]
+ end
end
- return tagCategories
+ return enabledUnits
end
-
- -- Tag configuration
- options.args.tags = {
+
+ local widthReset
+
+ -- Actual tab view thing
+ options.args.auraIndicators = {
+ order = 4.5,
type = "group",
+ name = L["Aura Indicators"],
+ desc = L["For configuring aura indicators on unit frames."],
childGroups = "tab",
- name = L["Add tags"],
- desc = getPageDescription,
- hidden = hideAdvancedOption,
+ hidden = false,
args = {
- general = {
- order = 0,
+ indicators = {
+ order = 1,
type = "group",
- name = L["Tag list"],
+ name = L["Indicators"],
+ childGroups = "tree",
args = {
- help = {
+ add = {
order = 0,
type = "group",
- inline = true,
- name = L["Help"],
- hidden = function() return ShadowUF.db.profile.advanced end,
+ name = L["Add Indicator"],
args = {
- description = {
+ add = {
order = 0,
- type = "description",
- 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."],
- },
- },
- },
- search = {
- order = 1,
- type = "group",
- inline = true,
- name = L["Search"],
- args = {
- search = {
- order = 1,
- type = "input",
- name = L["Search tags"],
- set = function(info, text) tagData.search = text end,
- get = function(info) return tagData.search end,
+ type = "group",
+ inline = true,
+ name = L["Add new indicator"],
+ args = {
+ name = {
+ order = 0,
+ type = "input",
+ name = L["Indicator name"],
+ width = "full",
+ set = function(info, value)
+ local id = string.format("%d", GetTime() + math.random(100))
+ 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}
+ ShadowUF.db.profile.auraIndicators.filters[id] = {boss = {}, curable = {}}
+
+ options.args.auraIndicators.args.indicators.args[id] = indicatorTable
+ options.args.auraIndicators.args.auras.args.filters.args[id] = auraFilterConfigTable
+
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.indicators.status.groups.selected = id
+ AceRegistry:NotifyChange("ShadowedUF")
+ end,
+ get = function() return "" end,
+ },
+ },
},
},
},
- list = {
- order = 2,
- type = "group",
- inline = true,
- name = L["Tags"],
- args = {},
- },
},
},
- add = {
- order = 1,
+ auras = {
+ order = 2,
type = "group",
- name = L["Add new tag"],
+ name = L["Auras"],
+ hidden = function(info)
+ if( not widthReset and AceDialog.Status.ShadowedUF.children.auraIndicators ) then
+ if( AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras ) then
+ widthReset = true
+
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.treewidth = 230
+
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.groups = {}
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.groups.filters = true
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.groups.groups = true
+
+ AceRegistry:NotifyChange("ShadowedUF")
+ end
+ end
+
+ return false
+ end,
args = {
- help = {
- order = 0,
- type = "group",
- inline = true,
- name = L["Help"],
- args = {
- help = {
- order = 0,
- type = "description",
- name = L["You can find more information on creating your own custom tags in the \"Help\" tab above."],
- },
- },
- },
add = {
- order = 1,
+ order = 0,
type = "group",
- inline = true,
- name = L["Add new tag"],
+ name = L["Add Aura"],
+ set = function(info, value) addAura[info[#(info)]] = value end,
+ get = function(info) return addAura[info[#(info)]] end,
args = {
- error = {
+ name = {
order = 0,
- type = "description",
- name = function() return tagData.addError or "" end,
- hidden = function() return not tagData.addError end,
- },
- errorHeader = {
- order = 0.50,
- type = "header",
- name = "",
- hidden = function() return not tagData.addError end,
+ type = "input",
+ name = L["Spell Name/ID"],
+ desc = L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."]
},
- tag = {
+ group = {
order = 1,
+ type = "select",
+ name = L["Aura group"],
+ desc = L["What group this aura belongs to, this is where you will find it when configuring."],
+ values = getAuraGroup,
+ },
+ custom = {
+ order = 2,
type = "input",
- name = L["Tag name"],
- 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]."],
- validate = function(info, text)
- if( text == "" ) then
- tagData.addError = L["You must enter a tag name."]
- elseif( string.match(text, "[%[%]%(%)]") ) then
- tagData.addError = string.format(L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."], text)
- elseif( ShadowUF.tagFunc[text] ) then
- tagData.addError = string.format(L["The tag \"%s\" already exists."], text)
- else
- tagData.addError = nil
+ name = L["New aura group"],
+ desc = L["Allows you to enter a new aura group."],
+ },
+ create = {
+ order = 3,
+ type = "execute",
+ name = L["Add aura"],
+ disabled = function(info) return not addAura.name or (not addAura.group and not addAura.custom) end,
+ func = function(info)
+ local group = string.trim(addAura.custom or "")
+ if( group == "" ) then group = string.trim(addAura.group or "") end
+ if( group == "" ) then group = L["Miscellaneous"] end
+
+ -- Don't overwrite an existing group, but don't tell them either, mostly because I don't want to add error reporting code
+ if( not ShadowUF.db.profile.auraIndicators.auras[addAura.name] ) then
+ -- 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
+ -- so will cheat it, and jump start it by storing the texture if we find it from GetSpellInfo directly
+ Indicators.auraConfig[addAura.name] = {indicator = "", group = group, iconTexture = select(3, GetSpellInfo(addAura.name)), priority = 0, r = 0, g = 0, b = 0}
+ writeAuraTable(addAura.name)
+
+ auraID = auraID + 1
+ auraMap[tostring(auraID)] = addAura.name
+ auraGroupTable.args[tostring(auraID)] = auraConfigTable
end
- AceRegistry:NotifyChange("ShadowedUF")
- return tagData.addError and "" or true
- end,
- set = function(info, tag)
- tagData.name = tag
- tagData.error = nil
- tagData.addError = nil
+ addAura.name = nil
+ addAura.custom = nil
+ addAura.group = nil
- ShadowUF.db.profile.tags[tag] = {func = "function(unit, unitOwner)\n\nend", category = "misc"}
- options.args.tags.args.general.args.list.args[tag] = tagTable
- Config.tagTextTable.args.misc.args[tag] = Config.tagTable
+ -- Check if the group exists
+ local gID
+ for id, name in pairs(groupMap) do
+ if( name == group ) then
+ gID = id
+ break
+ end
+ end
- selectDialogGroup("tags", "edit")
+ if( not gID ) then
+ groupID = groupID + 1
+ groupMap[tostring(groupID)] = group
+
+ unitTable.args.groups.args[tostring(groupID)] = unitGroupTable
+ options.args.auraIndicators.args.units.args.global.args.groups.args[tostring(groupID)] = globalUnitGroupTable
+ options.args.auraIndicators.args.auras.args.groups.args[tostring(groupID)] = auraGroupTable
+ end
+
+ -- Shunt the user to the this groups page
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.selected = tostring(gID or groupID)
+ AceRegistry:NotifyChange("ShadowedUF")
+
+ ShadowUF.Layout:Reload()
end,
},
},
},
+ filters = {
+ order = 1,
+ type = "group",
+ name = L["Automatic Auras"],
+ args = {}
+ },
+ groups = {
+ order = 2,
+ type = "group",
+ name = L["Groups"],
+ args = {}
+ },
},
},
- edit = {
- order = 2,
+ linked = {
+ order = 3,
type = "group",
- name = L["Edit tag"],
- hidden = function() return not tagData.name end,
+ name = L["Linked spells"],
+ childGroups = "tree",
+ hidden = true,
args = {
help = {
order = 0,
type = "group",
- inline = true,
name = L["Help"],
+ inline = true,
args = {
help = {
order = 0,
type = "description",
- 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."],
+ 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."],
+ width = "full",
},
},
},
- tag = {
+ add = {
order = 1,
type = "group",
+ name = L["Add link"],
inline = true,
- name = function() return string.format(L["Editing %s"], tagData.name or "") end,
+ set = function(info, value)
+ addLink[info[#(info)] ] = value
+ end,
+ get = function(info) return addLink[info[#(info)] ] end,
args = {
- error = {
+ from = {
order = 0,
- type = "description",
- name = function() return tagData.error or "" end,
- hidden = function() return not tagData.error end,
- },
- errorHeader = {
- order = 1,
- type = "header",
- name = "",
- hidden = function() return not tagData.error end,
- },
- discovery = {
- order = 1,
- type = "toggle",
- name = L["Disable event discovery"],
- 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."],
- set = function(info, value) tagData.discovery = value end,
- get = function() return tagData.discovery end,
- width = "full",
- },
- frequencyEnable = {
- order = 1.10,
- type = "toggle",
- name = L["Enable frequent updates"],
- desc = L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."],
- set = function(info, value)
- tagData.frequency = value and 5 or nil
- set(info, tagData.frequency, "frequency")
- end,
- get = function(info) return get(info, "frequency") ~= "" and true or false end,
- width = "full",
- },
- frequency = {
- order = 1.20,
- type = "input",
- name = L["Update interval"],
- 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."],
- disabled = function(info) return get(info) == "" end,
- validate = function(info, value)
- value = tonumber(value)
- if( not value ) then
- tagData.error = L["Invalid interval entered, must be a number."]
- elseif( value < 0 ) then
- tagData.error = L["You must enter a number that is 0 or higher, negative numbers are not allowed."]
- else
- tagData.error = nil
- end
-
- if( tagData.error ) then
- AceRegistry:NotifyChange("ShadowedUF")
- return ""
- end
-
- return true
- end,
- set = function(info, value)
- tagData.frequency = tonumber(value)
- tagData.frequency = tagData.frequency < 0 and 0 or tagData.frequency
-
- set(info, tagData.frequency)
- end,
- get = function(info) return tostring(get(info) or "") end,
- width = "half",
- },
- name = {
- order = 2,
type = "input",
- name = L["Tag name"],
- set = set,
- get = get,
+ name = L["Link from"],
+ desc = L["Spell you want to link to a primary aura, the casing must be exact."],
},
- category = {
- order = 2.5,
+ to = {
+ order = 1,
type = "select",
- name = L["Category"],
- values = getTagCategories,
- set = set,
- get = get,
- },
-
- sep = {
- order = 2.75,
- type = "description",
- name = "",
- width = "full",
+ name = L["Link to"],
+ values = getAuraList,
},
- events = {
+ link = {
order = 3,
- type = "input",
- name = L["Events"],
- desc = L["Events that should be used to trigger an update of this tag. Separate each event with a single space."],
- width = "full",
- validate = function(info, text)
- if( ShadowUF.Tags.defaultTags[tagData.name] ) then
- return true
- end
-
- if( text == "" or string.match(text, "[^_%a%s]") ) then
- 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."]
- tagData.eventError = text
- AceRegistry:NotifyChange("ShadowedUF")
- return ""
- end
-
- tagData.eventError = text
- tagData.error = nil
- return true
- end,
- set = set,
- get = function(info)
- if( tagData.eventError ) then
- return tagData.eventError
- end
-
- return get(info)
- end,
- },
- func = {
- order = 4,
- type = "input",
- multiline = true,
- name = L["Code"],
- 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"],
- width = "full",
- validate = function(info, text)
- if( ShadowUF.Tags.defaultTags[tagData.name] ) then
- return true
- end
-
- local funct, msg = loadstring("return " .. text)
- if( not string.match(text, "function") ) then
- tagData.error = L["You must wrap your code in a function."]
- tagData.funcError = text
- elseif( not funct and msg ) then
- tagData.error = string.format(L["Failed to save tag, error:|n %s"], msg)
- tagData.funcError = text
- else
- tagData.error = nil
- tagData.funcError = nil
- end
-
- AceRegistry:NotifyChange("ShadowedUF")
- return tagData.error and "" or true
- end,
- set = function(info, value)
- value = string.gsub(value, "||", "|")
- set(info, value)
-
- -- Try and automatically identify the events this tag is going to want to use
- if( not tagData.discovery ) then
- tagData.eventError = nil
- ShadowUF.db.profile.tags[tagData.name].events = ShadowUF.Tags:IdentifyEvents(value) or ""
- end
-
- ShadowUF.Tags:Reload(tagData.name)
- end,
- get = function(info)
- if( tagData.funcError ) then
- return stripCode(tagData.funcError)
- end
- return stripCode(ShadowUF.Tags.defaultTags[tagData.name] or ( ShadowUF.db.profile.tags[tagData.name] and ShadowUF.db.profile.tags[tagData.name].func))
- end,
- },
- delete = {
- order = 5,
type = "execute",
- name = L["Delete"],
- hidden = function() return ShadowUF.Tags.defaultTags[tagData.name] end,
- confirm = true,
- confirmText = L["Are you sure you want to delete this tag?"],
+ name = L["Link"],
+ disabled = function() return not addLink.from or not addLink.to or addLink.from == "" end,
func = function(info)
- local category = ShadowUF.db.profile.tags[tagData.name].category
- if( category ) then
- Config.tagTextTable.args[category].args[tagData.name] = nil
+ local lID, pID
+ for id, name in pairs(linkMap) do
+ if( name == addLink.from ) then
+ lID = id
+ elseif( name == addLink.to ) then
+ pID = id
+ end
end
- options.args.tags.args.general.args.list.args[tagData.name] = nil
-
- ShadowUF.db.profile.tags[tagData.name] = nil
- ShadowUF.tagFunc[tagData.name] = nil
- ShadowUF.Tags:Reload(tagData.name)
+ if( not pID ) then
+ linkID = linkID + 1
+ pID = linkID
+ linkMap[tostring(linkID)] = addLink.to
+ end
- tagData.name = nil
- tagData.error = nil
- selectDialogGroup("tags", "general")
+ if( not lID ) then
+ linkID = linkID + 1
+ lID = linkID
+ linkMap[tostring(linkID)] = addLink.from
+ end
+
+ ShadowUF.db.profile.auraIndicators.linked[addLink.from] = addLink.to
+ options.args.auraIndicators.args.linked.args[tostring(pID)] = parentLinkTable
+ parentLinkTable.args[tostring(lID)] = childLinkTable
+
+ addLink.from = nil
+ addLink.to = nil
+
+ ShadowUF.Layout:Reload()
end,
},
},
},
},
},
- help = {
- order = 3,
+ units = {
+ order = 4,
type = "group",
- name = L["Help"],
+ name = L["Enable Indicators"],
args = {
- general = {
+ help = {
order = 0,
type = "group",
- name = L["General"],
+ name = L["Help"],
inline = true,
args = {
- general = {
+ help = {
order = 0,
type = "description",
- 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."],
+ 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."],
+ width = "full",
},
},
},
- documentation = {
- order = 1,
+ global = {
+ order = 0,
type = "group",
- name = L["Documentation"],
- inline = true,
+ name = L["Global"],
+ desc = L["Global configurating will let you mass enable or disable aura groups for multiple units at once."],
args = {
- doc = {
+ units = {
order = 0,
- type = "input",
- name = L["Documentation"],
- set = false,
- get = function() return "http://wiki.github.com/Shadowed/ShadowedUnitFrames/tag-documentation" end,
- width = "full",
+ type = "multiselect",
+ name = L["Units to change"],
+ desc = L["Units that should have the aura groups settings changed below."],
+ values = getEnabledUnits,
+ set = function(info, unit, enabled) setGlobalUnits[unit] = enabled or nil end,
+ get = function(info, unit) return setGlobalUnits[unit] end,
+ },
+ filters = {
+ order = 1,
+ type = "group",
+ inline = true,
+ name = L["Aura filters"],
+ args = {}
+ },
+ groups = {
+ order = 2,
+ type = "group",
+ inline = true,
+ name = L["Aura groups"],
+ args = {}
},
},
},
- resources = {
- order = 2,
+ },
+ },
+ classes = {
+ order = 5,
+ type = "group",
+ name = L["Disable Auras by Class"],
+ childGroups = "tree",
+ args = {
+ help = {
+ order = 0,
type = "group",
+ name = L["Help"],
inline = true,
- name = L["Resources"],
args = {
- lua = {
+ help = {
order = 0,
- type = "input",
- name = L["Programming in Lua"],
- 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."],
- set = false,
- get = function() return "http://www.lua.org/pil/" end,
- width = "full",
- },
- wow = {
- order = 1,
- type = "input",
- name = L["WoW Programming"],
- desc = L["WoW Programming is a good resource for finding out what difference API's do and how to call them."],
- set = false,
- get = function() return "http://wowprogramming.com/docs" end,
+ type = "description",
+ 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."],
width = "full",
},
},
- },
+ }
},
},
},
}
+
+ local classTable = {
+ order = 1,
+ type = "group",
+ name = function(info)
+ return ShadowUF:Hex(ShadowUF.db.profile.classColors[info[#(info)]]) .. LOCALIZED_CLASS_NAMES_MALE[info[#(info)]] .. "|r"
+ end,
+ args = {},
+ }
- -- Load the initial tag list
- for tag in pairs(ShadowUF.Tags.defaultTags) do
- options.args.tags.args.general.args.list.args[tag] = tagTable
- end
-
- for tag, data in pairs(ShadowUF.db.profile.tags) do
- options.args.tags.args.general.args.list.args[tag] = tagTable
- end
-end
+ local classAuraTable = {
+ order = 1,
+ type = "toggle",
+ icon = function(info)
+ local aura = auraMap[info[#(info)]]
+ return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil
+ end,
+ name = function(info)
+ local aura = tonumber(auraMap[info[#(info)]])
+ if( not aura ) then return auraMap[info[#(info)]] end
----------------------
--- VISIBILITY OPTIONS
----------------------
-local function loadVisibilityOptions()
- -- As zone units are only enabled in a certain zone... it's pointless to provide visibility options for them
- local unitBlacklist = {}
- for unit in pairs(ShadowUF.Units.zoneUnits) do unitBlacklist[unit] = true end
- for unit, parent in pairs(ShadowUF.Units.childUnits) do
- if( ShadowUF.Units.zoneUnits[parent] ) then
- unitBlacklist[unit] = true
- end
- end
-
- local globalVisibility = {}
- local function set(info, value)
- local key = info[#(info)]
- local unit = info[#(info) - 1]
- local area = info[#(info) - 2]
-
- if( key == "enabled" ) then
- key = ""
- end
+ local name, _, icon = GetSpellInfo(aura)
+ if( not name ) then return name end
+
+ return "|T" .. icon .. ":18:18:0:0|t " .. name
+ end,
+ desc = function(info)
+ local aura = auraMap[info[#(info)]]
+ if( tonumber(aura) ) then
+ return string.format(L["Spell ID %s"], aura)
+ else
+ return aura
+ end
+ end,
+ set = function(info, value)
+ local aura = auraMap[info[#(info)]]
+ local class = info[#(info) - 1]
+ value = not value
+
+ if( value == false ) then value = nil end
+ ShadowUF.db.profile.auraIndicators.disabled[class][aura] = value
+ ShadowUF.Layout:Reload()
+ end,
+ get = function(info)
+ local aura = auraMap[info[#(info)]]
+ local class = info[#(info) - 1]
+
+ return not ShadowUF.db.profile.auraIndicators.disabled[class][aura]
+ end,
+ }
- if( value == nil ) then
- value = false
- elseif( value == false ) then
- value = nil
+ -- Build links
+ local addedFrom = {}
+ for from, to in pairs(ShadowUF.db.profile.auraIndicators.linked) do
+ local pID = addedFrom[to]
+ if( not pID ) then
+ linkID = linkID + 1
+ pID = linkID
+
+ addedFrom[to] = pID
end
+
+ linkID = linkID + 1
- for _, configUnit in pairs(ShadowUF.unitList) do
- if( ( configUnit == unit or unit == "global" ) and not unitBlacklist[configUnit] ) then
- ShadowUF.db.profile.visibility[area][configUnit .. key] = value
- end
- end
+ ShadowUF.db.profile.auraIndicators.linked[from] = to
+ options.args.auraIndicators.args.linked.args[tostring(pID)] = parentLinkTable
+ parentLinkTable.args[tostring(linkID)] = childLinkTable
- -- Annoying yes, but only way that works
- ShadowUF.Units:CheckPlayerZone(true)
+ linkMap[tostring(linkID)] = from
+ linkMap[tostring(pID)] = to
+ end
- if( unit == "global" ) then
- globalVisibility[area .. key] = value
+ -- Build the aura configuration
+ local groups = {}
+ for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do
+ local aura = Indicators.auraConfig[name]
+ if( aura.group ) then
+ auraMap[tostring(auraID)] = name
+ auraGroupTable.args[tostring(auraID)] = auraConfigTable
+ classTable.args[tostring(auraID)] = classAuraTable
+ auraID = auraID + 1
+
+ groups[aura.group] = true
end
end
-
- local function get(info)
- local key = info[#(info)]
- local unit = info[#(info) - 1]
- local area = info[#(info) - 2]
- if( key == "enabled" ) then
- key = ""
- end
+ -- Now create all of the parent stuff
+ for group in pairs(groups) do
+ groupMap[tostring(groupID)] = group
+ unitTable.args.groups.args[tostring(groupID)] = unitGroupTable
- if( unit == "global" ) then
- if( globalVisibility[area .. key] == false ) then
- return nil
- elseif( globalVisibility[area .. key] == nil ) then
- return false
- end
-
- return globalVisibility[area .. key]
- elseif( ShadowUF.db.profile.visibility[area][unit .. key] == false ) then
- return nil
- elseif( ShadowUF.db.profile.visibility[area][unit .. key] == nil ) then
- return false
- end
-
- return ShadowUF.db.profile.visibility[area][unit .. key]
- end
-
- local function getHelp(info)
- local unit = info[#(info) - 1]
- local area = info[#(info) - 2]
- local key = info[#(info)]
- if( key == "enabled" ) then
- key = ""
- end
-
- local current
- if( unit == "global" ) then
- current = globalVisibility[area .. key]
- else
- current = ShadowUF.db.profile.visibility[area][unit .. key]
- end
+ options.args.auraIndicators.args.units.args.global.args.groups.args[tostring(groupID)] = globalUnitGroupTable
+ options.args.auraIndicators.args.auras.args.groups.args[tostring(groupID)] = auraGroupTable
- if( current == false ) then
- return string.format(L["Disabled in %s"], AREA_NAMES[area])
- elseif( current == true ) then
- return string.format(L["Enabled in %s"], AREA_NAMES[area])
- end
+ groupID = groupID + 1
+ end
- return L["Using unit settings"]
+ for _, type in pairs(auraFilters) do
+ unitTable.args.filters.args[type] = unitFilterTable
+ options.args.auraIndicators.args.units.args.global.args.filters.args[type] = globalUnitFilterTable
+ end
+
+ -- Aura status by unit
+ for unit, config in pairs(ShadowUF.db.profile.units) do
+ options.args.auraIndicators.args.units.args[unit] = unitTable
end
- local areaTable = {
- type = "group",
- order = function(info) return info[#(info)] == "none" and 2 or 1 end,
- childGroups = "tree",
- name = function(info)
- return AREA_NAMES[info[#(info)]]
- end,
- get = get,
- set = set,
- args = {},
- }
-
- Config.visibilityTable = {
- type = "group",
- order = function(info) return info[#(info)] == "global" and 1 or (getUnitOrder(info) + 1) end,
- name = function(info) return info[#(info)] == "global" and L["Global"] or getName(info) end,
- args = {
- help = {
- order = 0,
- type = "group",
- name = L["Help"],
- inline = true,
- hidden = hideBasicOption,
- args = {
- help = {
- order = 0,
- type = "description",
- name = function(info)
- 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]]))
- end,
- },
- },
- },
- enabled = {
- order = 0.25,
- type = "toggle",
- name = function(info)
- local unit = info[#(info) - 1]
- if( unit == "global" ) then return "" end
- return string.format(L["%s frames"], L.units[unit])
- end,
- hidden = function(info) return info[#(info) - 1] == "global" end,
- desc = getHelp,
- tristate = true,
- width = "double",
- },
- sep = {
- order = 0.5,
- type = "description",
- name = "",
- width = "full",
- hidden = function(info) return info[#(info) - 1] == "global" end,
- },
- }
- }
+ -- Build class status thing
+ for classToken in pairs(RAID_CLASS_COLORS) do
+ options.args.auraIndicators.args.classes.args[classToken] = classTable
+ end
- local moduleTable = {
- order = 1,
- type = "toggle",
- name = getName,
- desc = getHelp,
- tristate = true,
- hidden = function(info)
- if( info[#(info) - 1] == "global" ) then return false end
- return hideRestrictedOption(info)
- end,
- arg = 1,
- }
-
- for key, module in pairs(ShadowUF.modules) do
- if( module.moduleName ) then
- Config.visibilityTable.args[key] = moduleTable
- end
+ -- Quickly build the indicator one
+ for key in pairs(ShadowUF.db.profile.auraIndicators.indicators) do
+ options.args.auraIndicators.args.indicators.args[key] = indicatorTable
+ options.args.auraIndicators.args.auras.args.filters.args[key] = auraFilterConfigTable
end
- areaTable.args.global = Config.visibilityTable
- for _, unit in pairs(ShadowUF.unitList) do
- if( not unitBlacklist[unit] ) then
- areaTable.args[unit] = Config.visibilityTable
- end
+ -- Automatically unlock the advanced text configuration for raid frames, regardless of advanced being enabled
+ local advanceTextTable = ShadowUF.Config.advanceTextTable
+ local originalHidden = advanceTextTable.args.sep.hidden
+ local function unlockRaidText(info)
+ if( info[2] == "raid" ) then return false end
+ return originalHidden(info)
end
- options.args.visibility = {
- type = "group",
- childGroups = "tab",
- name = L["Zone configuration"],
- desc = getPageDescription,
- args = {
- start = {
- order = 0,
- type = "group",
- name = L["Help"],
- inline = true,
- hidden = hideBasicOption,
- args = {
- help = {
- order = 0,
- type = "description",
- name = L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"],
- },
- },
- },
- pvp = areaTable,
- arena = areaTable,
- party = areaTable,
- raid = areaTable,
- },
- }
+ advanceTextTable.args.anchorPoint.hidden = unlockRaidText
+ advanceTextTable.args.sep.hidden = unlockRaidText
+ advanceTextTable.args.x.hidden = unlockRaidText
+ advanceTextTable.args.y.hidden = unlockRaidText
end
local function loadOptions()
@@ -5017,16 +7588,19 @@ local function loadOptions()
loadTagOptions()
loadFilterOptions()
loadVisibilityOptions()
-
+ loadAuraIndicatorsOptions()
+
-- Ordering
options.args.general.order = 1
+ options.args.profile.order = 1.5
options.args.enableUnits.order = 2
options.args.units.order = 3
options.args.filter.order = 4
+ options.args.auraIndicators.order = 4.5
options.args.hideBlizzard.order = 5
options.args.visibility.order = 6
options.args.tags.order = 7
-
+
-- So modules can access it easier/debug
Config.options = options
@@ -5034,6 +7608,7 @@ local function loadOptions()
ShadowUF:FireModuleEvent("OnConfigurationLoad")
end
+local defaultToggles
function Config:Open()
AceDialog = AceDialog or LibStub("AceConfigDialog-3.0")
AceRegistry = AceRegistry or LibStub("AceConfigRegistry-3.0")
@@ -5041,10 +7616,17 @@ function Config:Open()
if( not registered ) then
loadOptions()
- LibStub("AceConfig-3.0"):RegisterOptionsTable("ShadowedUF", options)
- AceDialog:SetDefaultSize("ShadowedUF", 835, 525)
+ AceRegistry:RegisterOptionsTable("ShadowedUF", options, true)
+ AceDialog:SetDefaultSize("ShadowedUF", 895, 570)
registered = true
end
AceDialog:Open("ShadowedUF")
+
+ if( not defaultToggles ) then
+ defaultToggles = true
+
+ AceDialog.Status.ShadowedUF.status.groups.groups.units = true
+ AceRegistry:NotifyChange("ShadowedUF")
+ end
end
\ No newline at end of file