From 8a45b1e56f96f5a952ac6f9d90b4f1896199f7e3 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 14 Aug 2019 14:49:27 +0200 Subject: [PATCH 001/108] Fix remaining LuaCheck issues --- .luacheckrc | 7 +++++++ ShadowedUnitFrames.lua | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index ecc070242..cc38459b5 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -8,6 +8,7 @@ exclude_files = { ignore = { "11./BINDING_.*", -- Setting an undefined (Keybinding) global variable + "11./SLASH_.*", -- Setting an undefined (Slash) global variable "211", -- Unused local variable "211/L", -- Unused local variable "L" "212", -- Unused argument @@ -22,6 +23,8 @@ ignore = { globals = { "ShadowUF", "ClickCastFrames", + "CONFIGMODE_CALLBACKS", + "SlashCmdList", } read_globals = { @@ -73,6 +76,7 @@ read_globals = { "IsShiftKeyDown", "IsUsableSpell", "IsXPUserDisabled", + "LoadAddOn", "UnitAffectingCombat", "UnitAlternatePowerInfo", "UnitAura", @@ -132,6 +136,8 @@ read_globals = { "UnitXPMax", -- FrameXML frames + "ArenaEnemyFrames", + "ArenaPrepFrames", "BuffFrame", "CastingBarFrame", "ComboFrame", @@ -149,6 +155,7 @@ read_globals = { "PetFrame", "PlayerFrame", "PlayerFrameAlternateManaBar", + "PlayerPowerBarAlt", "PriestBarFrame", "RuneFrame", "TargetFrame", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 70d21367c..81ffcd655 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -836,8 +836,8 @@ function ShadowUF:ShowInfoPanel() 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() + frame.hide:SetScript("OnClick", function(f) + f:GetParent():Hide() end) end From 01711649499a79a09ce8fce174daa442df5c8253 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 14 Aug 2019 14:49:46 +0200 Subject: [PATCH 002/108] Add Travis-CI support --- .travis.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..273c9f2b1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,19 @@ +language: minimal + +addons: + apt: + packages: + - luarocks + +install: luarocks install --local luacheck + +before_script: + - /home/travis/.luarocks/bin/luacheck . --no-color -q + +script: + - curl -s https://raw.githubusercontent.com/BigWigsMods/packager/master/release.sh | bash + +notifications: + email: + on_success: never + on_failure: always From 13432ddf09fc0dba3e3d0a1ec94c2b4c1ff3f3df Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 14 Aug 2019 14:54:14 +0200 Subject: [PATCH 003/108] Update LibSpellRange-1.0 repo URL --- .pkgmeta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pkgmeta b/.pkgmeta index ae9b73dad..3ad3e7f2b 100755 --- a/.pkgmeta +++ b/.pkgmeta @@ -17,7 +17,7 @@ externals: 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 + url: https://github.com/ascott18/LibSpellRange-1.0.git options/libs/AceConfig-3.0: url: https://repos.wowace.com/wow/ace3/trunk/AceConfig-3.0 options/libs/AceDBOptions-3.0: From 761d5ac95db604ed4e7e29ffad84b16c93b2d822 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 14 Aug 2019 14:56:01 +0200 Subject: [PATCH 004/108] Add project IDs to the TOC --- ShadowedUnitFrames.toc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 60463bad0..74935e300 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -4,8 +4,10 @@ ## Author: Shadowed ## Version: @project-version@ ## SavedVariables: ShadowedUFDB -## X-Website: http://www.wowace.com/addons/shadowed-unit-frames/ +## X-Website: https://www.wowace.com/addons/shadowed-unit-frames/ ## OptionalDeps: Ace3, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibDualSpec-1.0, LibSpellRange-1.0, Clique +## X-Curse-Project-ID: 19268 +## X-WoWI-ID: 13494 #@no-lib-strip@ libs\LibStub\LibStub.lua From 333b51da81aaf78f87ad32d796a16a7bf1e0f8a7 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 14 Aug 2019 14:56:11 +0200 Subject: [PATCH 005/108] Update options TOC to 8.2 --- options/ShadowedUF_Options.toc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index dac346cee..06ad103bd 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80200 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 5a2033d3393ebec1e2947bfcfa776908e518e676 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 14 Aug 2019 15:03:25 +0200 Subject: [PATCH 006/108] Adjust CBH and LibStub repo urls --- .pkgmeta | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.pkgmeta b/.pkgmeta index 3ad3e7f2b..a9479100b 100755 --- a/.pkgmeta +++ b/.pkgmeta @@ -5,11 +5,9 @@ move-folders: externals: libs/LibStub: - url: https://repos.wowace.com/wow/libstub/trunk - tag: latest + url: https://repos.wowace.com/wow/libstub/tags/1.0 libs/CallbackHandler-1.0: url: https://repos.wowace.com/wow/callbackhandler/trunk - tag: latest libs/AceDB-3.0: url: https://repos.wowace.com/wow/ace3/trunk/AceDB-3.0 libs/LibSharedMedia-3.0: From 5e3aa6cf3b52f0ae3e99cab340442856c0199ef3 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 14 Aug 2019 15:07:00 +0200 Subject: [PATCH 007/108] Properly reference the correct subdirectory in the CBH external --- .pkgmeta | 2 +- ShadowedUnitFrames.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pkgmeta b/.pkgmeta index a9479100b..0cc5e480d 100755 --- a/.pkgmeta +++ b/.pkgmeta @@ -7,7 +7,7 @@ externals: libs/LibStub: url: https://repos.wowace.com/wow/libstub/tags/1.0 libs/CallbackHandler-1.0: - url: https://repos.wowace.com/wow/callbackhandler/trunk + url: https://repos.wowace.com/wow/callbackhandler/trunk/CallbackHandler-1.0 libs/AceDB-3.0: url: https://repos.wowace.com/wow/ace3/trunk/AceDB-3.0 libs/LibSharedMedia-3.0: diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 74935e300..e89fc23aa 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -11,7 +11,7 @@ #@no-lib-strip@ libs\LibStub\LibStub.lua -libs\CallbackHandler-1.0\CallbackHandler-1.0\CallbackHandler-1.0.xml +libs\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 From af00dd0f33c5c7f6368acca7332ebd4f537d9fe5 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 14 Aug 2019 15:39:47 +0200 Subject: [PATCH 008/108] Slightly increase font shadow to offset 8.2 scaling changes --- ShadowedUnitFrames.lua | 6 +++++- modules/defaultlayout.lua | 4 ++-- modules/layout.lua | 4 +--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 81ffcd655..0b04f2dad 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -5,7 +5,7 @@ ShadowUF = select(2, ...) local L = ShadowUF.L -ShadowUF.dbRevision = 59 +ShadowUF.dbRevision = 60 ShadowUF.playerUnit = "player" ShadowUF.enabledUnits = {} ShadowUF.modules = {} @@ -112,6 +112,10 @@ end function ShadowUF:CheckUpgrade() local revision = self.db.profile.revision or self.dbRevision + if (revision <= 59 ) then + self.db.profile.font.shadowX = 1.0 + self.db.profile.font.shadowY = -1.0 + end if( revision <= 58 ) then for unit, config in pairs(self.db.profile.units) do if config.text then diff --git a/modules/defaultlayout.lua b/modules/defaultlayout.lua index 8cdc0d242..e66ea5da3 100755 --- a/modules/defaultlayout.lua +++ b/modules/defaultlayout.lua @@ -110,8 +110,8 @@ function ShadowUF:LoadDefaultLayout(useMerge) extra = "", shadowColor = {r = 0, g = 0, b = 0, a = 1}, color = {r = 1, g = 1, b = 1, a = 1}, - shadowX = 0.80, - shadowY = -0.80, + shadowX = 1.00, + shadowY = -1.00, } -- Some localizations do not work with Myriad Condensed Web, need to automatically swap it to a localization that will work for it diff --git a/modules/layout.lua b/modules/layout.lua index 2ede94d57..e7fafa6c5 100755 --- a/modules/layout.lua +++ b/modules/layout.lua @@ -407,9 +407,7 @@ function Layout:SetupFontString(fontString, extraSize) if( ShadowUF.db.profile.font.shadowColor and ShadowUF.db.profile.font.shadowX and ShadowUF.db.profile.font.shadowY ) then fontString:SetShadowColor(ShadowUF.db.profile.font.shadowColor.r, ShadowUF.db.profile.font.shadowColor.g, ShadowUF.db.profile.font.shadowColor.b, ShadowUF.db.profile.font.shadowColor.a) - local scale = fontString:GetEffectiveScale() - local x, y = ShadowUF.db.profile.font.shadowX * scale, ShadowUF.db.profile.font.shadowY * scale - fontString:SetShadowOffset(x, y) + fontString:SetShadowOffset(ShadowUF.db.profile.font.shadowX, ShadowUF.db.profile.font.shadowY) else fontString:SetShadowColor(0, 0, 0, 0) fontString:SetShadowOffset(0, 0) From 3428a0e5ab38314990d69b00e06866b485bacc2e Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 21 Aug 2019 16:41:30 +0200 Subject: [PATCH 009/108] Add Shadow Priest Disease Dispel --- modules/units.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/units.lua b/modules/units.lua index efaa56bb9..c0d39c327 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -1476,7 +1476,7 @@ 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"}}, + ["PRIEST"] = {[527] = {"Magic", "Disease"}, [32375] = {"Magic"}, [213634] = {"Disease"}}, ["PALADIN"] = {[4987] = {"Poison", "Disease", "Magic"}, [213644] = {"Poison", "Disease"}}, ["SHAMAN"] = {[77130] = {"Curse", "Magic"}, [51886] = {"Curse"}}, ["MONK"] = {[115450] = {"Poison", "Disease", "Magic"}, [218164] = {"Poison", "Disease"}}, From 61b69a5045855bda0ca1dc8dcd0cb825176a5e3b Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 21 Aug 2019 16:42:52 +0200 Subject: [PATCH 010/108] Remove Death Coil as friendly range check Death Coil hasn't had the healing function in a while now and is fully offensive --- modules/range.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/range.lua b/modules/range.lua index 8b93da0ee..d02693301 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -11,7 +11,7 @@ local Range = { ["PALADIN"] = GetSpellInfo(19750), -- Flash of Light ["SHAMAN"] = GetSpellInfo(8004), -- Healing Surge ["WARLOCK"] = GetSpellInfo(5697), -- Unending Breath - ["DEATHKNIGHT"] = GetSpellInfo(47541), -- Death Coil + --["DEATHKNIGHT"] = GetSpellInfo(47541), -- Death Coil ["MONK"] = GetSpellInfo(115450), -- Detox }, hostile = { From 88cfbd524ce176a2b6d6d219d0226d78a36c89cf Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 25 Sep 2019 10:07:10 +0200 Subject: [PATCH 011/108] Update TOC for 8.2.5 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index e89fc23aa..79490307e 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 80200 +## Interface: 80205 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 06ad103bd..2f4a97404 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 80200 +## Interface: 80205 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 2b23b635c0eeed5a91e8c028c54dd8cc567b2e5e Mon Sep 17 00:00:00 2001 From: Saxayone <47307427+Saxayone@users.noreply.github.com> Date: Mon, 4 Nov 2019 12:48:57 +0100 Subject: [PATCH 012/108] Added Summon Pending/Accepted/Declined Functionality from 8.1.5 --- .luacheckrc | 1 + ShadowedUnitFrames.lua | 10 +++++++++- modules/defaultlayout.lua | 27 +++++++++++++++++---------- modules/indicators.lua | 35 ++++++++++++++++++++++++++++++++++- options/config.lua | 2 +- 5 files changed, 62 insertions(+), 13 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index cc38459b5..fc08f90b5 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -40,6 +40,7 @@ read_globals = { "LibStub", -- API functions + "C_IncomingSummon", "C_Timer", "CancelUnitBuff", "CanHearthAndResurrectFromArea", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 0b04f2dad..931cb52af 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -5,7 +5,7 @@ ShadowUF = select(2, ...) local L = ShadowUF.L -ShadowUF.dbRevision = 60 +ShadowUF.dbRevision = 61 ShadowUF.playerUnit = "player" ShadowUF.enabledUnits = {} ShadowUF.modules = {} @@ -112,6 +112,13 @@ end function ShadowUF:CheckUpgrade() local revision = self.db.profile.revision or self.dbRevision + if (revision <= 60 ) then + for unit, config in pairs(self.db.profile.units) do + if( unit == "player" or unit == "party" or unit == "target" or unit == "raid" or unit == "focus" or unit == "mainassist" or unit == "maintank" ) then + config.indicators.sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"} + end + end + end if (revision <= 59 ) then self.db.profile.font.shadowX = 1.0 self.db.profile.font.shadowY = -1.0 @@ -316,6 +323,7 @@ function ShadowUF:LoadUnitDefaults() 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} + self.defaults.profile.units[unit].indicators.sumPending = {enabled = true} if( unit ~= "focus" and unit ~= "target" ) then self.defaults.profile.units[unit].indicators.ready = {enabled = true, size = 0} diff --git a/modules/defaultlayout.lua b/modules/defaultlayout.lua index e66ea5da3..10f9da667 100755 --- a/modules/defaultlayout.lua +++ b/modules/defaultlayout.lua @@ -292,6 +292,7 @@ function ShadowUF:LoadDefaultLayout(useMerge) 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"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, }, text = { {text = "[(()afk() )][name]"}, @@ -357,7 +358,8 @@ function ShadowUF:LoadDefaultLayout(useMerge) incAbsorb = {cap = 1}, healAbsorb = {cap = 1}, indicators = { - resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"}, + resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, }, auras = { buffs = {enabled = false, maxRows = 1}, @@ -390,8 +392,9 @@ function ShadowUF:LoadDefaultLayout(useMerge) 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"} + resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, + phase = {enabled = true, anchorPoint = "RC", size = 14, x = -11, y = 0, anchorTo = "$parent"} }, auras = { buffs = {enabled = true, maxRows = 1}, @@ -640,7 +643,8 @@ function ShadowUF:LoadDefaultLayout(useMerge) portrait = {enabled = false, fullAfter = 50}, castBar = {order = 60}, indicators = { - resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"}, + resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, }, auras = { buffs = {enabled = false}, @@ -705,7 +709,8 @@ function ShadowUF:LoadDefaultLayout(useMerge) portrait = {enabled = false, fullAfter = 50}, castBar = {order = 60}, indicators = { - resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"}, + resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, }, auras = { buffs = {enabled = false}, @@ -818,8 +823,9 @@ function ShadowUF:LoadDefaultLayout(useMerge) 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}, - 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"}, + resurrect = {enabled = true, anchorPoint = "RC", size = 28, x = -39, y = -1, anchorTo = "$parent"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, 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 = { @@ -880,9 +886,10 @@ function ShadowUF:LoadDefaultLayout(useMerge) 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"} + resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, 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]"}, diff --git a/modules/indicators.lua b/modules/indicators.lua index 6d1215bb6..0091b9255 100755 --- a/modules/indicators.lua +++ b/modules/indicators.lua @@ -1,4 +1,4 @@ -local Indicators = {list = {"status", "pvp", "leader", "resurrect", "masterLoot", "raidTarget", "ready", "role", "lfdRole", "class", "phase", "questBoss", "petBattle", "arenaSpec"}} +local Indicators = {list = {"status", "pvp", "leader", "resurrect", "sumPending", "masterLoot", "raidTarget", "ready", "role", "lfdRole", "class", "phase", "questBoss", "petBattle", "arenaSpec"}} ShadowUF:RegisterModule(Indicators, "indicators", ShadowUF.L["Indicators"]) @@ -51,6 +51,31 @@ function Indicators:UpdateResurrect(frame) end end +function Indicators:SummonPending(frame) + if( not frame.indicators.sumPending or not frame.indicators.sumPending.enabled ) then return end + + if( C_IncomingSummon.HasIncomingSummon(frame.unit) ) then + if( C_IncomingSummon.IncomingSummonStatus(frame.unit) == 1 ) then + frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") + frame.indicators.sumPending:SetTexCoord(0.539062, 0.789062, 0.015625, 0.515625) + frame.indicators.sumPending:Show() + elseif( C_IncomingSummon.IncomingSummonStatus(frame.unit) == 2 ) then + frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") + frame.indicators.sumPending:SetTexCoord(0.0078125, 0.257812, 0.015625, 0.515625) + frame.indicators.sumPending:Show() + elseif( C_IncomingSummon.IncomingSummonStatus(frame.unit) == 3 ) then + frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") + frame.indicators.sumPending:SetTexCoord(0.273438, 0.523438, 0.015625, 0.515625) + frame.indicators.sumPending:Show() + else + frame.indicators.sumPending:Hide() + end + else + frame.indicators.sumPending:Hide() + end +end + + function Indicators:UpdateMasterLoot(frame) if( not frame.indicators.masterLoot or not frame.indicators.masterLoot.enabled ) then return end @@ -345,6 +370,14 @@ function Indicators:OnEnable(frame) frame.indicators.resurrect:SetTexture("Interface\\RaidFrame\\Raid-Icon-Rez") end + if( config.indicators.sumPending and config.indicators.sumPending.enabled ) then + frame:RegisterNormalEvent("INCOMING_SUMMON_CHANGED", self, "SummonPending") + frame:RegisterUpdateFunc(self, "SummonPending") + + frame.indicators.sumPending = frame.indicators.sumPending or frame.indicators:CreateTexture(nil, "OVERLAY") + frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") + end + if( config.indicators.pvp and config.indicators.pvp.enabled ) then frame:RegisterUnitEvent("PLAYER_FLAGS_CHANGED", self, "UpdatePVPFlag") frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdatePVPFlag") diff --git a/options/config.lua b/options/config.lua index bbb8c0eba..a2bd8b70f 100755 --- a/options/config.lua +++ b/options/config.lua @@ -50,7 +50,7 @@ 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 = {["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 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"], ["sumPending"] = L["Summon Pending"], ["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."], From 04d4c9e6f50ead4594763ab92660312ae69d890f Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 28 Jan 2020 17:24:33 +0100 Subject: [PATCH 013/108] Allow the party leader indicator on "target" to show for any party leader --- .luacheckrc | 1 + modules/indicators.lua | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index fc08f90b5..daae65316 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -121,6 +121,7 @@ read_globals = { "UnitIsUnit", "UnitIsVisible", "UnitIsWildBattlePet", + "UnitLeadsAnyGroup", "UnitLevel", "UnitPlayerControlled", "UnitPlayerOrPetInParty", diff --git a/modules/indicators.lua b/modules/indicators.lua index 0091b9255..2618da63b 100755 --- a/modules/indicators.lua +++ b/modules/indicators.lua @@ -154,7 +154,7 @@ end function Indicators:UpdateLeader(frame) if( not frame.indicators.leader or not frame.indicators.leader.enabled ) then return end - if( UnitIsGroupLeader(frame.unit) ) then + if( UnitIsGroupLeader(frame.unit) or (frame.unit == "target" and UnitLeadsAnyGroup(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) @@ -318,6 +318,11 @@ function Indicators:UpdateReadyCheck(frame, event) frame.indicators.ready:Show() end +function Indicators:UpdateFlags(frame) + self:UpdateLeader(frame) + self:UpdatePVPFlag(frame) +end + function Indicators:OnEnable(frame) -- Forces the indicators to be above the bars/portraits/etc if( not frame.indicators ) then @@ -379,7 +384,6 @@ function Indicators:OnEnable(frame) end if( config.indicators.pvp and config.indicators.pvp.enabled ) then - frame:RegisterUnitEvent("PLAYER_FLAGS_CHANGED", self, "UpdatePVPFlag") frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdatePVPFlag") frame:RegisterUpdateFunc(self, "UpdatePVPFlag") @@ -455,6 +459,10 @@ function Indicators:OnEnable(frame) if( frame.indicators.leader or frame.indicators.masterLoot or frame.indicators.role or ( frame.unit ~= "player" and frame.indicators.lfdRole ) ) then frame:RegisterNormalEvent("GROUP_ROSTER_UPDATE", self, "GroupRosterUpdate") end + + if( frame.indicators.leader or frame.indicators.pvp ) then + frame:RegisterUnitEvent("PLAYER_FLAGS_CHANGED", self, "UpdateFlags") + end end function Indicators:OnDisable(frame) From 2b1bbb4424921da294512ff13d0772f5ed5bdd98 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 28 Jan 2020 17:28:41 +0100 Subject: [PATCH 014/108] Update TOC for 8.3 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 79490307e..ffb2f3020 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 80205 +## Interface: 80300 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 2f4a97404..a8419a0f6 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 80205 +## Interface: 80300 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 9157cb5561168a47afe4b967b00905c166b04c6d Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 18 Jul 2020 11:47:32 +0200 Subject: [PATCH 015/108] Use BackdropTemplate on WoW 9.0 --- .luacheckrc | 1 + modules/layout.lua | 2 +- modules/movers.lua | 2 +- modules/units.lua | 8 ++++---- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index daae65316..03fde5b42 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -167,6 +167,7 @@ read_globals = { "WarlockPowerFrame", -- FrameXML functions + "BackdropTemplateMixin", "CombatFeedback_OnCombatEvent", "CombatFeedback_OnUpdate", "CompactRaidFrameManager_GetSetting", diff --git a/modules/layout.lua b/modules/layout.lua index e7fafa6c5..59a3d31d9 100755 --- a/modules/layout.lua +++ b/modules/layout.lua @@ -36,7 +36,7 @@ local function updateBackdrop() backdropTbl.bgFile = mediaPath.background 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.edgeSize = backdrop.edgeSize == 0 and 1 or backdrop.edgeSize backdropTbl.tileSize = backdrop.tileSize backdropTbl.insets.left = backdrop.inset backdropTbl.insets.right = backdrop.inset diff --git a/modules/movers.lua b/modules/movers.lua index 5e8ec811d..2757cd8e0 100755 --- a/modules/movers.lua +++ b/modules/movers.lua @@ -473,7 +473,7 @@ function Movers:CreateInfoFrame() if( self.infoFrame ) then return end -- Show an info frame that users can lock the frames through - local frame = CreateFrame("Frame", nil, UIParent) + local frame = CreateFrame("Frame", nil, UIParent, BackdropTemplateMixin and "BackdropTemplate" or nil) frame:SetClampedToScreen(true) frame:SetWidth(300) frame:SetHeight(115) diff --git a/modules/units.lua b/modules/units.lua index c0d39c327..6fb496ad4 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -634,7 +634,7 @@ local secureInitializeUnit = [[ end ]] -local unitButtonTemplate = ClickCastHeader and "ClickCastUnitTemplate,SUF_SecureUnitTemplate" or "SUF_SecureUnitTemplate" +local unitButtonTemplate = ClickCastHeader and (BackdropTemplateMixin and "ClickCastUnitTemplate,SUF_SecureUnitTemplate,BackdropTemplate" or "ClickCastUnitTemplate,SUF_SecureUnitTemplate") or (BackdropTemplateMixin and "SUF_SecureUnitTemplate,BackdropTemplate" or "SUF_SecureUnitTemplate") -- Header unit initialized local function initializeUnit(header, frameName) @@ -952,7 +952,7 @@ function Units:LoadUnit(unit) return end - local frame = self:CreateUnit("Button", "SUFUnit" .. unit, petBattleFrame, "SecureUnitButtonTemplate") + local frame = self:CreateUnit("Button", "SUFUnit" .. unit, petBattleFrame, BackdropTemplateMixin and "SecureUnitButtonTemplate,BackdropTemplate" or "SecureUnitButtonTemplate") frame:SetAttribute("unit", unit) frame.hasStateWatch = unit == "pet" @@ -1180,7 +1180,7 @@ function Units:LoadZoneHeader(type) end for id, unit in pairs(ShadowUF[type .. "Units"]) do - local frame = self:CreateUnit("Button", "SUFHeader" .. type .. "UnitButton" .. id, headerFrame, "SecureUnitButtonTemplate") + local frame = self:CreateUnit("Button", "SUFHeader" .. type .. "UnitButton" .. id, headerFrame, BackdropTemplateMixin and "SecureUnitButtonTemplate,BackdropTemplate" or "SecureUnitButtonTemplate") frame.ignoreAnchor = true frame.hasStateWatch = true frame.unitUnmapped = type .. id @@ -1296,7 +1296,7 @@ function Units:LoadChildUnit(parent, type, id) end -- Now we can create the actual frame - local frame = self:CreateUnit("Button", "SUFChild" .. type .. string.match(parent:GetName(), "(%d+)"), parent, "SecureUnitButtonTemplate") + local frame = self:CreateUnit("Button", "SUFChild" .. type .. string.match(parent:GetName(), "(%d+)"), parent, BackdropTemplateMixin and "SecureUnitButtonTemplate,BackdropTemplate" or "SecureUnitButtonTemplate") frame.unitType = type frame.parent = parent frame.isChildUnit = true From eb1a3936b6979b9ebb507dd0c051a33e1d998564 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 18 Jul 2020 11:47:47 +0200 Subject: [PATCH 016/108] Re-map UNIT_HEALTH_FREQUENT to UNIT_HEALTH for WoW 9.0 --- modules/units.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/units.lua b/modules/units.lua index 6fb496ad4..e53e7a7b2 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -11,6 +11,8 @@ local unitFrames, headerFrames, frameList, unitEvents, childUnits, headerUnits, local remappedUnits = Units.remappedUnits local _G = getfenv(0) +local WoW90 = select(4, GetBuildInfo()) >= 90000 + ShadowUF.Units = Units ShadowUF:RegisterModule(Units, "units") @@ -66,6 +68,11 @@ local function RegisterNormalEvent(self, event, handler, func, unitOverride) return end + -- XXX: replace once 9.0 goes live, and we can cleanly remove events from tags and all modules + if WoW90 and event == "UNIT_HEALTH_FREQUENT" then + event = "UNIT_HEALTH" + end + if( unitEvents[event] and not ShadowUF.fakeUnits[self.unitRealType] ) then self:BlizzRegisterUnitEvent(event, unitOverride or self.unitOwner, self.vehicleUnit) if unitOverride then From 93a68e49d5e42b67a0d7d0c24fdc21212b564300 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 18 Jul 2020 15:55:18 +0200 Subject: [PATCH 017/108] Another set of BackdropTemplate --- ShadowedUnitFrames.lua | 2 +- modules/auraindicators.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 931cb52af..23fb33de9 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -811,7 +811,7 @@ function ShadowUF:ShowInfoPanel() ShadowUF.db.global.infoID = #(infoMessages) if( infoID < 0 or infoID >= #(infoMessages) ) then return end - local frame = CreateFrame("Frame", nil, UIParent) + local frame = CreateFrame("Frame", nil, UIParent, BackdropTemplateMixin and "BackdropTemplate" or nil) frame:SetClampedToScreen(true) frame:SetFrameStrata("HIGH") frame:SetToplevel(true) diff --git a/modules/auraindicators.lua b/modules/auraindicators.lua index 59e9905b8..b1e1499d2 100755 --- a/modules/auraindicators.lua +++ b/modules/auraindicators.lua @@ -51,7 +51,7 @@ function Indicators:OnLayoutApplied(frame) -- Create indicator as needed local indicator = frame.auraIndicators["indicator-" .. id] if( not indicator ) then - indicator = CreateFrame("Frame", nil, frame.auraIndicators) + indicator = CreateFrame("Frame", nil, frame.auraIndicators, BackdropTemplateMixin and "BackdropTemplate" or nil) indicator:SetFrameLevel(frame.topFrameLevel + 2) indicator.texture = indicator:CreateTexture(nil, "OVERLAY") indicator.texture:SetPoint("CENTER", indicator) From da67129474dbe1d835dd4f1a628d9bb352988a1e Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 20 Aug 2020 13:33:43 +0200 Subject: [PATCH 018/108] Add 9.0 compat for UnitInPhase --- .luacheckrc | 1 + modules/indicators.lua | 2 ++ modules/range.lua | 2 ++ 3 files changed, 5 insertions(+) diff --git a/.luacheckrc b/.luacheckrc index 03fde5b42..d9c9a134c 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -123,6 +123,7 @@ read_globals = { "UnitIsWildBattlePet", "UnitLeadsAnyGroup", "UnitLevel", + "UnitPhaseReason", "UnitPlayerControlled", "UnitPlayerOrPetInParty", "UnitPlayerOrPetInRaid", diff --git a/modules/indicators.lua b/modules/indicators.lua index 2618da63b..75fdf732d 100755 --- a/modules/indicators.lua +++ b/modules/indicators.lua @@ -2,6 +2,8 @@ local Indicators = {list = {"status", "pvp", "leader", "resurrect", "sumPending" ShadowUF:RegisterModule(Indicators, "indicators", ShadowUF.L["Indicators"]) +local UnitInPhase = UnitInPhase or UnitPhaseReason + function Indicators:UpdateArenaSpec(frame) if( not frame.indicators.arenaSpec or not frame.indicators.arenaSpec.enabled ) then return end diff --git a/modules/range.lua b/modules/range.lua index d02693301..d482b2231 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -48,6 +48,8 @@ local LSR = LibStub("SpellRange-1.0") local playerClass = select(2, UnitClass("player")) local rangeSpells = {} +local UnitInPhase = UnitInPhase or UnitPhaseReason + local function checkRange(self) local frame = self.parent From bf698bdc4186fed166a47dd2f5fc59874efe71f5 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 20 Aug 2020 15:38:29 +0200 Subject: [PATCH 019/108] Enable Holy Power for all Paladin specs in 9.0 --- modules/holypower.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/holypower.lua b/modules/holypower.lua index b7d707c2a..8584059ed 100755 --- a/modules/holypower.lua +++ b/modules/holypower.lua @@ -1,7 +1,9 @@ if( not ShadowUF.ComboPoints ) then return end +local WoW90 = select(4, GetBuildInfo()) >= 90001 + local HolyPower = setmetatable({}, {__index = ShadowUF.ComboPoints}) -ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN", SPEC_PALADIN_RETRIBUTION, PALADINPOWERBAR_SHOW_LEVEL) +ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN", not WoW90 and SPEC_PALADIN_RETRIBUTION or nil, 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) From 747042357fa9deb6653d337fa30e8a0bab30a1e5 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 20 Aug 2020 15:45:18 +0200 Subject: [PATCH 020/108] Disable shaman mana bar on 9.0, mana is their primary resource again --- modules/shaman.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/shaman.lua b/modules/shaman.lua index 15cdb5293..0333d8b07 100644 --- a/modules/shaman.lua +++ b/modules/shaman.lua @@ -1,3 +1,6 @@ +local WoW90 = select(4, GetBuildInfo()) >= 90001 +if WoW90 then return end -- no more maelstrom in 9.0, so no need for the shaman mana bar + local Shaman = {} ShadowUF:RegisterModule(Shaman, "shamanBar", ShadowUF.L["Shaman mana bar"], true, "SHAMAN") From 312d7dedf416f94601458247052f4918402c2036 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 20 Aug 2020 15:52:48 +0200 Subject: [PATCH 021/108] Back out previous change, since without full removal it leaves artifacts in the settings --- modules/shaman.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/shaman.lua b/modules/shaman.lua index 0333d8b07..5a1572eb4 100644 --- a/modules/shaman.lua +++ b/modules/shaman.lua @@ -1,5 +1,5 @@ -local WoW90 = select(4, GetBuildInfo()) >= 90001 -if WoW90 then return end -- no more maelstrom in 9.0, so no need for the shaman mana bar +--local WoW90 = select(4, GetBuildInfo()) >= 90001 +--if WoW90 then return end -- no more maelstrom in 9.0, so no need for the shaman mana bar local Shaman = {} ShadowUF:RegisterModule(Shaman, "shamanBar", ShadowUF.L["Shaman mana bar"], true, "SHAMAN") From 5bfbfb59d6d937dddcca3e881004ca68c1824ef7 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 27 Aug 2020 10:10:56 +0200 Subject: [PATCH 022/108] Revert Shaman mana bar changes entirely, Maelstrom is back This reverts commit 312d7dedf416f94601458247052f4918402c2036. This reverts commit 747042357fa9deb6653d337fa30e8a0bab30a1e5. --- modules/shaman.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/shaman.lua b/modules/shaman.lua index 5a1572eb4..15cdb5293 100644 --- a/modules/shaman.lua +++ b/modules/shaman.lua @@ -1,6 +1,3 @@ ---local WoW90 = select(4, GetBuildInfo()) >= 90001 ---if WoW90 then return end -- no more maelstrom in 9.0, so no need for the shaman mana bar - local Shaman = {} ShadowUF:RegisterModule(Shaman, "shamanBar", ShadowUF.L["Shaman mana bar"], true, "SHAMAN") From 66cc00f887dca57151390e1bd1667c47a80b75df Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 27 Aug 2020 10:19:49 +0200 Subject: [PATCH 023/108] Update alternate power handling for new API --- modules/altpower.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/modules/altpower.lua b/modules/altpower.lua index 5962677b0..6224b127e 100755 --- a/modules/altpower.lua +++ b/modules/altpower.lua @@ -18,12 +18,13 @@ end local altColor = {} function AltPower:UpdateVisibility(frame) - local barType, minPower, _, _, _, hideFromOthers, showOnRaid = UnitAlternatePowerInfo(frame.unit) + local barID = UnitPowerBarID(frame.unit) or 0 + local barInfo = GetUnitPowerBarInfoByID(barID) local visible = false - if( barType ) then - if( ( frame.unitType == "player" or frame.unitType == "pet" ) or not hideFromOthers ) then + if( barInfo and barInfo.barType ) then + if( ( frame.unitType == "player" or frame.unitType == "pet" ) or not barInfo.hideFromOthers ) then visible = true - elseif( showOnRaid and ( UnitInRaid(frame.unit) or UnitInParty(frame.unit) ) ) then + elseif( barInfo.showOnRaid and ( UnitInRaid(frame.unit) or UnitInParty(frame.unit) ) ) then visible = true end end @@ -45,7 +46,10 @@ end function AltPower:Update(frame, event, unit, type) if( event and type ~= "ALTERNATE" ) then return end + local barID = UnitPowerBarID(frame.unit) + local barInfo = GetUnitPowerBarInfoByID(barID) or 0 + local minPower = barInfo and barInfo.minPower or 0 - frame.altPowerBar:SetMinMaxValues(select(2, UnitAlternatePowerInfo(frame.unit)) or 0, UnitPowerMax(frame.unit, ALTERNATE_POWER_INDEX) or 0) + frame.altPowerBar:SetMinMaxValues(minPower, UnitPowerMax(frame.unit, ALTERNATE_POWER_INDEX) or 0) frame.altPowerBar:SetValue(UnitPower(frame.unit, ALTERNATE_POWER_INDEX) or 0) end From cb2c5f9e081e86cb75c706e786f876cd43d5ada8 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 27 Aug 2020 10:21:03 +0200 Subject: [PATCH 024/108] Fix typo --- modules/altpower.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/altpower.lua b/modules/altpower.lua index 6224b127e..c79c608bd 100755 --- a/modules/altpower.lua +++ b/modules/altpower.lua @@ -46,8 +46,8 @@ end function AltPower:Update(frame, event, unit, type) if( event and type ~= "ALTERNATE" ) then return end - local barID = UnitPowerBarID(frame.unit) - local barInfo = GetUnitPowerBarInfoByID(barID) or 0 + local barID = UnitPowerBarID(frame.unit) or 0 + local barInfo = GetUnitPowerBarInfoByID(barID) local minPower = barInfo and barInfo.minPower or 0 frame.altPowerBar:SetMinMaxValues(minPower, UnitPowerMax(frame.unit, ALTERNATE_POWER_INDEX) or 0) From 3a59755f07cf6126daa16a4d76b4bf018d7dd692 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 27 Aug 2020 12:04:21 +0200 Subject: [PATCH 025/108] Update luacheck --- .luacheckrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.luacheckrc b/.luacheckrc index d9c9a134c..10a29a509 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -64,6 +64,7 @@ read_globals = { "GetText", "GetTime", "GetTotemInfo", + "GetUnitPowerBarInfoByID", "GetWatchedFactionInfo", "GetWeaponEnchantInfo", "GetXPExhaustion", @@ -79,7 +80,6 @@ read_globals = { "IsXPUserDisabled", "LoadAddOn", "UnitAffectingCombat", - "UnitAlternatePowerInfo", "UnitAura", "UnitBattlePetType", "UnitCanAssist", @@ -128,6 +128,7 @@ read_globals = { "UnitPlayerOrPetInParty", "UnitPlayerOrPetInRaid", "UnitPower", + "UnitPowerBarID", "UnitPowerDisplayMod", "UnitPowerMax", "UnitPowerType", From cf216a27dd60ce69f8a79bb2d330047452bb3441 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 18 Sep 2020 16:06:18 +0200 Subject: [PATCH 026/108] Migrate to GitHub Actions --- .github/workflows/packager.yml | 39 ++++++++++++++++++++++++++++++ .github/workflows/pull_request.yml | 21 ++++++++++++++++ .travis.yml | 19 --------------- 3 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/packager.yml create mode 100644 .github/workflows/pull_request.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/packager.yml b/.github/workflows/packager.yml new file mode 100644 index 000000000..0eb13e7b5 --- /dev/null +++ b/.github/workflows/packager.yml @@ -0,0 +1,39 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + push: + branches: [ master ] + tags: + - '**' + - '!**classic**' + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Luacheck + run: | + sudo apt-get install luarocks + luarocks install --local luacheck + /home/runner/.luarocks/bin/luacheck . --no-color -q + + - name: Create Package + run: curl -s https://raw.githubusercontent.com/BigWigsMods/packager/master/release.sh | bash + env: + CF_API_KEY: ${{ secrets.CF_API_KEY }} + WOWI_API_TOKEN: ${{ secrets.WOWI_API_TOKEN }} + GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 000000000..ab585dbe0 --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,21 @@ +# This is a basic workflow to help you get started with Actions + +name: CI-PR + +on: [pull_request] + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Install and run Luacheck + run: | + sudo apt-get install luarocks + luarocks install --local luacheck + /home/runner/.luarocks/bin/luacheck . --no-color -q + diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 273c9f2b1..000000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: minimal - -addons: - apt: - packages: - - luarocks - -install: luarocks install --local luacheck - -before_script: - - /home/travis/.luarocks/bin/luacheck . --no-color -q - -script: - - curl -s https://raw.githubusercontent.com/BigWigsMods/packager/master/release.sh | bash - -notifications: - email: - on_success: never - on_failure: always From 5801d342cc7150f70d50813a229c2c73101e18b0 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 13 Oct 2020 19:47:20 +0200 Subject: [PATCH 027/108] Update TOC for 9.0 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index ffb2f3020..ae42eecd1 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 80300 +## Interface: 90001 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index a8419a0f6..970c22d5e 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 80300 +## Interface: 90001 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 85f19bf9756749ab984cd6d981215e2e4c971762 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 14 Oct 2020 16:46:43 +0200 Subject: [PATCH 028/108] Fix phase detection in 9.0 --- modules/indicators.lua | 8 +++----- modules/movers.lua | 2 +- modules/range.lua | 4 +--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/modules/indicators.lua b/modules/indicators.lua index 75fdf732d..a4533c3e4 100755 --- a/modules/indicators.lua +++ b/modules/indicators.lua @@ -2,8 +2,6 @@ local Indicators = {list = {"status", "pvp", "leader", "resurrect", "sumPending" ShadowUF:RegisterModule(Indicators, "indicators", ShadowUF.L["Indicators"]) -local UnitInPhase = UnitInPhase or UnitPhaseReason - function Indicators:UpdateArenaSpec(frame) if( not frame.indicators.arenaSpec or not frame.indicators.arenaSpec.enabled ) then return end @@ -34,9 +32,9 @@ 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) + if( UnitIsConnected(frame.unit) and UnitPhaseReason(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() diff --git a/modules/movers.lua b/modules/movers.lua index 2757cd8e0..f8f0f08fb 100755 --- a/modules/movers.lua +++ b/modules/movers.lua @@ -79,7 +79,7 @@ local function createConfigEnv() 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, + UnitPhaseReason = function(unit) return nil end, UnitExists = function(unit) return true end, UnitIsGroupLeader = function() return true end, UnitIsPVP = function(unit) return true end, diff --git a/modules/range.lua b/modules/range.lua index d482b2231..dae58ff6f 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -48,8 +48,6 @@ local LSR = LibStub("SpellRange-1.0") local playerClass = select(2, UnitClass("player")) local rangeSpells = {} -local UnitInPhase = UnitInPhase or UnitPhaseReason - local function checkRange(self) local frame = self.parent @@ -61,7 +59,7 @@ local function checkRange(self) spell = rangeSpells.hostile end - if( not UnitIsConnected(frame.unit) or not UnitInPhase(frame.unit) ) then + if( not UnitIsConnected(frame.unit) or UnitPhaseReason(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) From e779c8ed85e9b605b4416ed01277b722f2274869 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 16 Oct 2020 13:38:29 +0200 Subject: [PATCH 029/108] Ensure backdrop changes are always applied --- modules/layout.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/layout.lua b/modules/layout.lua index 59a3d31d9..d23b6df5a 100755 --- a/modules/layout.lua +++ b/modules/layout.lua @@ -318,7 +318,8 @@ end -- Setup the main frame function Layout:SetupFrame(frame, config) local backdrop = ShadowUF.db.profile.backdrop - frame:SetBackdrop(backdropTbl) + frame.backdropInfo = backdropTbl + frame:ApplyBackdrop() frame:SetBackdropColor(backdrop.backgroundColor.r, backdrop.backgroundColor.g, backdrop.backgroundColor.b, backdrop.backgroundColor.a) frame:SetBackdropBorderColor(backdrop.borderColor.r, backdrop.borderColor.g, backdrop.borderColor.b, backdrop.borderColor.a) From 93e601012be414b475070cc99d847bb80ead2368 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 17 Oct 2020 12:39:20 +0200 Subject: [PATCH 030/108] Prefer PW:S for range checks on priests --- modules/range.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/range.lua b/modules/range.lua index dae58ff6f..c3e42e65d 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -1,8 +1,8 @@ local Range = { friendly = { ["PRIEST"] = { - (GetSpellInfo(527)), -- Purify (GetSpellInfo(17)), -- Power Word: Shield + (GetSpellInfo(527)), -- Purify }, ["DRUID"] = { (GetSpellInfo(774)), -- Rejuvenation From cefd5798b50c7a1a523ed12ce01696111683c3be Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sun, 18 Oct 2020 10:56:58 +0200 Subject: [PATCH 031/108] Fix disabling the range indicator Previously it would only apply after a reload --- modules/range.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/range.lua b/modules/range.lua index c3e42e65d..a78538cfe 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -147,7 +147,7 @@ end function Range:SpellChecks(frame) updateSpellCache("friendly") updateSpellCache("hostile") - if( frame.range ) then + if( frame.range and ShadowUF.db.profile.units[frame.unitType].range.enabled ) then self:ForceUpdate(frame) end end From 1e2c0736d6f1fbf539d59220937a4ebdab8e59da Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sun, 18 Oct 2020 11:10:25 +0200 Subject: [PATCH 032/108] Add a workaround for out-of-phase targets in WarMode or Chromie Time --- modules/range.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/range.lua b/modules/range.lua index a78538cfe..561960585 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -48,6 +48,15 @@ local LSR = LibStub("SpellRange-1.0") local playerClass = select(2, UnitClass("player")) local rangeSpells = {} +local UnitPhaseReason_o = UnitPhaseReason +local UnitPhaseReason = function(unit) + local phase = UnitPhaseReason_o(unit) + if (phase == Enum.PhaseReason.WarMode or phase == Enum.PhaseReason.ChromieTime) and UnitIsVisible(unit) then + return nil + end + return phase +end + local function checkRange(self) local frame = self.parent From 1ba954528ae2a1dcd06f16a0c8d06677537e1f00 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 20 Oct 2020 19:27:28 +0200 Subject: [PATCH 033/108] Add Warlock Imp Dispel to curable --- modules/units.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/units.lua b/modules/units.lua index e53e7a7b2..65648a329 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -1488,9 +1488,10 @@ local curableSpells = { ["SHAMAN"] = {[77130] = {"Curse", "Magic"}, [51886] = {"Curse"}}, ["MONK"] = {[115450] = {"Poison", "Disease", "Magic"}, [218164] = {"Poison", "Disease"}}, ["MAGE"] = {[475] = {"Curse"}}, + ["WARLOCK"] = {[89808] = {"Magic"}}, } -curableSpells = curableSpells[select(2, UnitClass("player"))] +curableSpells = curableSpells[playerClass] local function checkCurableSpells() if( not curableSpells ) then return end @@ -1498,7 +1499,7 @@ local function checkCurableSpells() table.wipe(Units.canCure) for spellID, cures in pairs(curableSpells) do - if( IsPlayerSpell(spellID) ) then + if( IsPlayerSpell(spellID) or IsSpellKnown(spellID, true) ) then for _, auraType in pairs(cures) do Units.canCure[auraType] = true end @@ -1542,7 +1543,7 @@ centralFrame:SetScript("OnEvent", function(self, event, unit) end -- Monitor talent changes for curable changes - elseif( event == "PLAYER_SPECIALIZATION_CHANGED" ) then + elseif( event == "PLAYER_SPECIALIZATION_CHANGED" or event == "UNIT_PET" ) then checkCurableSpells() for frame in pairs(ShadowUF.Units.frameList) do @@ -1558,6 +1559,9 @@ centralFrame:SetScript("OnEvent", function(self, event, unit) elseif( event == "PLAYER_LOGIN" ) then checkCurableSpells() self:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED") + if( playerClass == "WARLOCK" ) then + self:RegisterUnitEvent("UNIT_PET", "player", nil) + end -- This is slightly hackish, but it suits the purpose just fine for somthing thats rarely called. elseif( event == "PLAYER_REGEN_ENABLED" ) then From 68ac31d81911ba4bc61c7536a14afa2626959bd2 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 20 Oct 2020 19:35:05 +0200 Subject: [PATCH 034/108] Fix luacheck --- .luacheckrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.luacheckrc b/.luacheckrc index 10a29a509..a20b9d72e 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -76,6 +76,7 @@ read_globals = { "IsPlayerSpell", "IsResting", "IsShiftKeyDown", + "IsSpellKnown", "IsUsableSpell", "IsXPUserDisabled", "LoadAddOn", From 9ce8ffaf57637701eb7b643e34b6a2d09f056449 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 19 Nov 2020 12:34:55 +0100 Subject: [PATCH 035/108] Update TOC for 9.0.2 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index ae42eecd1..115cb899e 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 90001 +## Interface: 90002 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 970c22d5e..fe265fad6 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 90001 +## Interface: 90002 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 3610c052a56e01c3c55b927c46672b7ebfe4b78a Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 19 Nov 2020 12:53:41 +0100 Subject: [PATCH 036/108] Update totem module level limits --- modules/totems.lua | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/modules/totems.lua b/modules/totems.lua index a79bf0bff..0fc57b2c1 100755 --- a/modules/totems.lua +++ b/modules/totems.lua @@ -4,18 +4,15 @@ local MAX_TOTEMS = MAX_TOTEMS -- Death Knights untalented ghouls are guardians and are considered totems........... so set it up for them local playerClass = select(2, UnitClass("player")) -if( playerClass == "PALADIN" ) then +if( playerClass == "DRUID" ) then MAX_TOTEMS = 1 - 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) + ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Mushroom bar"], true, "DRUID", 4, 39) elseif( playerClass == "MONK" ) then MAX_TOTEMS = 1 - ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Statue bar"], true, "MONK", {1, 2}, 70) + ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Statue bar"], true, "MONK", {1, 2}, 35) elseif( playerClass == "MAGE" ) then MAX_TOTEMS = 1 - ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Rune of Power bar"], true, "MAGE", {1, 2, 3}, 45) + ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Rune of Power bar"], true, "MAGE", {1, 2, 3}, 30) elseif( playerClass == "WARLOCK" ) then MAX_TOTEMS = 2 ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Imp & Dreadstalker bar"], true, "WARLOCK", 2) From 7345b67d505828209782eac84be0790f2bda44cf Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 19 Nov 2020 12:57:14 +0100 Subject: [PATCH 037/108] Remove pre-9.0 condition --- modules/holypower.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/holypower.lua b/modules/holypower.lua index 8584059ed..4b362c030 100755 --- a/modules/holypower.lua +++ b/modules/holypower.lua @@ -3,7 +3,7 @@ if( not ShadowUF.ComboPoints ) then return end local WoW90 = select(4, GetBuildInfo()) >= 90001 local HolyPower = setmetatable({}, {__index = ShadowUF.ComboPoints}) -ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN", not WoW90 and SPEC_PALADIN_RETRIBUTION or nil, PALADINPOWERBAR_SHOW_LEVEL) +ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN", nil, 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) From b326791a458ccab5c7aca663a5d194eac4f0c951 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 19 Nov 2020 12:59:25 +0100 Subject: [PATCH 038/108] Migrate UNIT_HEALTH_FREQUENT --- modules/healabsorb.lua | 1 - modules/health.lua | 1 - modules/holypower.lua | 2 -- modules/incabsorb.lua | 1 - modules/incheal.lua | 1 - modules/tags.lua | 31 +++++++++++++++---------------- modules/units.lua | 4 +--- 7 files changed, 16 insertions(+), 25 deletions(-) diff --git a/modules/healabsorb.lua b/modules/healabsorb.lua index 9e32c3331..673646bf3 100755 --- a/modules/healabsorb.lua +++ b/modules/healabsorb.lua @@ -6,7 +6,6 @@ function HealAbsorb:OnEnable(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") diff --git a/modules/health.lua b/modules/health.lua index 1ade52e8b..902fabb93 100755 --- a/modules/health.lua +++ b/modules/health.lua @@ -36,7 +36,6 @@ function Health:OnEnable(frame) frame:RegisterUnitEvent("UNIT_CONNECTION", self, "Update") frame:RegisterUnitEvent("UNIT_FACTION", 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 diff --git a/modules/holypower.lua b/modules/holypower.lua index 4b362c030..4c8f4edd6 100755 --- a/modules/holypower.lua +++ b/modules/holypower.lua @@ -1,7 +1,5 @@ if( not ShadowUF.ComboPoints ) then return end -local WoW90 = select(4, GetBuildInfo()) >= 90001 - local HolyPower = setmetatable({}, {__index = ShadowUF.ComboPoints}) ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN", nil, 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"} diff --git a/modules/incabsorb.lua b/modules/incabsorb.lua index 53ffe0956..10ae25239 100755 --- a/modules/incabsorb.lua +++ b/modules/incabsorb.lua @@ -6,7 +6,6 @@ function IncAbsorb:OnEnable(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") diff --git a/modules/incheal.lua b/modules/incheal.lua index afc45a055..a3095b86a 100755 --- a/modules/incheal.lua +++ b/modules/incheal.lua @@ -7,7 +7,6 @@ function IncHeal:OnEnable(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") diff --git a/modules/tags.lua b/modules/tags.lua index 269855971..1f38d139e 100755 --- a/modules/tags.lua +++ b/modules/tags.lua @@ -1065,7 +1065,7 @@ Tags.defaultTags = { Tags.defaultEvents = { ["totem:timer"] = "SUF_TOTEM_TIMER", ["rune:timer"] = "SUF_RUNE_TIMER", - ["hp:color"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_MAXHEALTH", + ["hp:color"] = "UNIT_HEALTH UNIT_MAXHEALTH", ["short:druidform"] = "UNIT_AURA", ["druidform"] = "UNIT_AURA", ["guild"] = "UNIT_NAME_UPDATE", @@ -1085,11 +1085,11 @@ Tags.defaultEvents = { ["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", + ["curhp"] = "UNIT_HEALTH UNIT_CONNECTION", + ["abscurhp"] = "UNIT_HEALTH UNIT_CONNECTION", + ["curmaxhp"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION", + ["absolutehp"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION", + ["smart:curmaxhp"] = "UNIT_HEALTH 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", @@ -1108,25 +1108,25 @@ Tags.defaultEvents = { ["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", + ["def:name"] = "UNIT_NAME_UPDATE UNIT_MAXHEALTH UNIT_HEALTH", ["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", + ["missinghp"] = "UNIT_HEALTH 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", + ["perhp"] = "UNIT_HEALTH 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", + ["status"] = "UNIT_HEALTH 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", + ["dechp"] = "UNIT_HEALTH UNIT_MAXHEALTH", ["group"] = "GROUP_ROSTER_UPDATE", ["unit:color:aggro"] = "UNIT_THREAT_SITUATION_UPDATE", ["color:aggro"] = "UNIT_THREAT_SITUATION_UPDATE", @@ -1434,7 +1434,6 @@ Tags.eventType = { ["UNIT_POWER_FREQUENT"] = "power", ["UNIT_MAXPOWER"] = "power", ["UNIT_ABSORB_AMOUNT_CHANGED"] = "health", - ["UNIT_HEALTH_FREQUENT"] = "health", ["UNIT_HEALTH"] = "health", ["UNIT_MAXHEALTH"] = "health", ["GROUP_ROSTER_UPDATE"] = "unitless", @@ -1485,14 +1484,14 @@ local function loadAPIEvents() ["UnitName"] = "UNIT_NAME_UPDATE", ["UnitClassification"] = "UNIT_CLASSIFICATION_CHANGED", ["UnitFactionGroup"] = "UNIT_FACTION PLAYER_FLAGS_CHANGED", - ["UnitHealth%("] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT", + ["UnitHealth%("] = "UNIT_HEALTH", ["UnitHealthMax"] = "UNIT_MAXHEALTH", ["UnitPower%("] = "UNIT_POWER_FREQUENT", ["UnitPowerMax"] = "UNIT_MAXPOWER", ["UnitPowerType"] = "UNIT_DISPLAYPOWER", - ["UnitIsDead"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT", - ["UnitIsGhost"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT", - ["UnitIsConnected"] = "UNIT_HEALTH UNIT_HEALTH_FREQUENT UNIT_CONNECTION", + ["UnitIsDead"] = "UNIT_HEALTH", + ["UnitIsGhost"] = "UNIT_HEALTH", + ["UnitIsConnected"] = "UNIT_HEALTH UNIT_CONNECTION", ["UnitIsAFK"] = "PLAYER_FLAGS_CHANGED", ["UnitIsDND"] = "PLAYER_FLAGS_CHANGED", ["UnitIsPVP"] = "PLAYER_FLAGS_CHANGED UNIT_FACTION", diff --git a/modules/units.lua b/modules/units.lua index 65648a329..0f210912d 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -11,8 +11,6 @@ local unitFrames, headerFrames, frameList, unitEvents, childUnits, headerUnits, local remappedUnits = Units.remappedUnits local _G = getfenv(0) -local WoW90 = select(4, GetBuildInfo()) >= 90000 - ShadowUF.Units = Units ShadowUF:RegisterModule(Units, "units") @@ -69,7 +67,7 @@ local function RegisterNormalEvent(self, event, handler, func, unitOverride) end -- XXX: replace once 9.0 goes live, and we can cleanly remove events from tags and all modules - if WoW90 and event == "UNIT_HEALTH_FREQUENT" then + if event == "UNIT_HEALTH_FREQUENT" then event = "UNIT_HEALTH" end From 1bebd5c593704491b5ed7e037a62175458fab316 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 25 Nov 2020 10:19:49 +0100 Subject: [PATCH 039/108] Run a full update on UNIT_TARGETABLE_CHANGE for players This fixes eg. jumping down into the maw showing as "Offline" --- modules/units.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/units.lua b/modules/units.lua index 0f210912d..a4fd0f62e 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -550,6 +550,9 @@ OnAttributeChanged = function(self, name, unit) -- Force a full update when the player is alive to prevent freezes when releasing in a zone that forces a ressurect (naxx/tk/etc) self:RegisterNormalEvent("PLAYER_ALIVE", self, "FullUpdate") + -- full update when the player targetable changes, ie. during cutscenes or transports + self:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "FullUpdate") + -- Update boss elseif( self.unitType == "boss" ) then self:RegisterNormalEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT", self, "FullUpdate") From 2bca6d35e3bd197bd286fdb7581ab20130ad809d Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 1 Dec 2020 17:55:28 +0100 Subject: [PATCH 040/108] Conform to the statusbar textures of upstream SharedMedia --- ShadowedUnitFrames.lua | 7 ++++++- media/textures/Smoothv2.tga | Bin 0 -> 32812 bytes media/textures/smooth.tga | Bin 32812 -> 32812 bytes media/textures/smoother.tga | Bin 0 -> 32812 bytes modules/layout.lua | 4 +++- 5 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 media/textures/Smoothv2.tga create mode 100644 media/textures/smoother.tga diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 23fb33de9..1db0eb57d 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -5,7 +5,7 @@ ShadowUF = select(2, ...) local L = ShadowUF.L -ShadowUF.dbRevision = 61 +ShadowUF.dbRevision = 62 ShadowUF.playerUnit = "player" ShadowUF.enabledUnits = {} ShadowUF.modules = {} @@ -112,6 +112,11 @@ end function ShadowUF:CheckUpgrade() local revision = self.db.profile.revision or self.dbRevision + if (revision <= 61 ) then + if self.db.profile.bars.texture == "Smooth" then + self.db.profile.bars.texture = "Smoother" + end + end if (revision <= 60 ) then for unit, config in pairs(self.db.profile.units) do if( unit == "player" or unit == "party" or unit == "target" or unit == "raid" or unit == "focus" or unit == "mainassist" or unit == "maintank" ) then diff --git a/media/textures/Smoothv2.tga b/media/textures/Smoothv2.tga new file mode 100644 index 0000000000000000000000000000000000000000..dd5f0cf0392db2197f6df4b72067adda69d39a42 GIT binary patch literal 32812 zcmeHGZH`<=a-{vs$Jh(lw^#!L3>)wld^3JYoEdQ_Q6eRhlE|SBqqDR#A~LeFUf1jH zp|oBD%K-{ml^GcknXl);gTH@Je}DI<2Y>p9FTVKV@cDe+!ROz=-{x=N(W8flhYuef z9>sb1@KMA#$US<*JZcZ){V3jr#XIq;p^hASfYV{`hOhdl894L+Po2DHzjD@2PI?+#_|e2O7Bx_4W7gp?#nxUxkG> z`t6l>&olJLKHxd=sf&JbWX&^XUUkjsZ|PYPwO47;2WRqIoC6bidQ|MbG+WNhy`nef z!@c%2a_ogi&jT;qPhe^$_((0(@~$12EBn~*UiHYUa{89y;J$Kp?k7DEkGs$0552B! zykx$AU+p$~%o8~8gS&}5XXT#KCw9em{x;CV*%OO;_GuX8@cwwr@i;gi zKMo9X&O4%({TYE1XTw-4c%WfD#mGT}7}SsZwi-)J<8}QpJW*4;@?|Z@rb!=N-?Iqo zen*bF-tO<|gPOZQZi*GjhN8a4lcW=b%Lv6!h@BSU+4Em1n75L26?Ab#u)}R6X9;G$; zWFI&;-pr9RP5Z!Zl6U$Rm?QeUSNh~^;?_R26ZPjT<^nHu!H=EDJF%5VPIb-EckKKs zZu{UfdY9*k@=vz)Cx<6X{Ns`DJ^jAuE3Or8kt3e@^ta$Vo=4cxyPYZDU9aD%(dO>8 zet*31G}ULFn%y(3u&yoQQU3z-cd^HH(uv@*VMi6%f9Ao@@*ekcdz4wJ=W}dTKlu^h?v=4pFF{w zmz~EK;?DCy|1!~2?Q+`fv9BfXETW4OhKe%<>&x*?Zy}q2BoEVS1nFh316qyV&X5;62Zm zUw(P`^2?`j5dT^y^q*d+eJSn_pQY_+Z`8~m!D_E zK0DhZ+&SL!JPU8nkh_e3sn7mn-e>pZJm>vfy}a2^#8nS+BY(-Zar+K@akbj`Eua3q zp!eCcXVbZg_tmqj%Hd7S)r?aga94*b)<(~kbN?N^=I@%|i=$fbUg328-lx1g}LH7|?$ zkzXbMNClbgk$3HM}%G#;tlYcf=oiFJ53KZtu9qm1eKc_tGogx!z~ry{~$E zuHUEGx4Sv7U4Db-X2rY8S@TrQn7tUiU3~Va43l8Z~hwtPp zU)CAEN_V5Ld4%_j18bgnrnx@+)O_i&X5&oe+D3a9kLL3(%suz`8<2nEPA=$skBD`W zhi`q${;kxb{Fu?4Et1=wGQZht&7OIGzpkg>O7m(C#_o02(03oX=^fr~^EY9wsosBs zxO0}^a)dVS;Ncy=A>quY-K_jIzUW0?^>luEP=D1^w|`seOnsg?waJ6r@G|&}anBru zOApi-c>hmSd~tht!Smv9ix~U8eeoi4ac(o0cfK=6Y~&H~O~?^7VAzX%^4u~9T;R>` zp6n+kd)en6XrKpp_JbdK(9Yu;@{QM?N;f&#TUz2`A9UzhTAYR4;idFeiN^N8Qt3dGEUbuekN?zz3f6le?lm@5rkzZQrF$F6e@z_JX%H z6uVE(h#nsEt6yG{FYEe#>61F>4PNRZ?~}U8t(^(0eZq@p%n(*N{iBZmZX(pGs1BW^^>7zx?g&h&AI7$m`v&f^T=?E_S)*dpt=zeu`_w1?oOjzF`?^Sb;@aO= z=UUDGVuz>q)qRWY?|$FTbml#L?ajWIA9I(-(7M-5XT3rD68*&R`z`S2_OnwTyBV{t za(#Z>v4a^m&oS4`z3{!+&%Jk>bG>}|?crOTZ(qjo9q(~ox)u?5ycOe~@4|2RUIq^} z*pnKS0~a)duj$E8dI3K;dp&z5ztjc4xZGp!_DS!7F<*HjXVZah<~rAm7mvLg4{qf= zSL!9Fy$t{98G1f#p32dWIe{H>2orB;#6A^;u|Mn?IK1UGxS(Ur9;rX(@LtKw9ZREh z(+jy%r+Cwk_4R$_MSRvtzw`ueIR|{jo!^qa+79A9&F5bD$-AR)smoc12VtNy_MzX3 zbHEB;y99Nb0gV-GZ%cF&==dU8(YG-u5k{k}VT-|`pu@)25bSKfWn|L)~? z2cGXDe)lpCV!KEECEnqQb>f2~urG0s8tZtwFF9Qwn877%??=rX%F_q*OGkD4F$aDp z#MmP}rC-dH{hBLhAr?C3^n3$f{GO{t)qqWH*EoC2@!jV18~SnAYAZ?J&iCKHn(|xR>G!MT zXxy*beWQ7rYtdI+TaTM};T9Y<=ejmL4NmPP@Mm~O?>X)Z>eh0+WOql{nBgclv{&D| zW-Yz3hxL4|enM;AyY({O6aIJbPCPkNpRwOp*kz7>+T69P9sl(|b*|@JUHr$M-RHRH zW8`1IivQJDuMdd2$NTkb=8%8IdgdbknmOk)0{nhPFt4#ey$znlqqdyqHImU~AJkFir!U-$OI4?i5nfya2` zwEXKIUQh2I^8LDDI)1*RHx79lPrRuWwc?2xX6?kMALEN39N}U31Ku3j+dU@U80;K+ z)MwoEx|Z`wSG+^hyBc$l7juE1`i`k(&%rN!)CYz=sCDn)LmxS3taboAG!=`ZW{{RS zIdgKBc40gJxPu#Wt5^P{H@K@7KI*Y5Arg_jVwG+;3KF+J%QZMrKnRV~9d#~^3T_uMw z@<=`WcIYGdUS@X`}8$u;2@{Ed6|()HV& znvDniJ_|qn`}n?$lh0Xi%+&J6J5Jhf+Hb+Xi{^RSdE=ZoGQZ?E=c2dmbDDF9r(=$O zPvNKM-n@Am|Icp@ZzH~atMewJaxwGUI8jILE$^uLp7q3#BYCP1z1d&6!b3MsyrJEB zk*5dLthe!HjQZr6T7mam)}FA*M@`O^z0}gI)CLaz=tcL+qt70xm$>wZS>4N6I-wOc z?KnB`1_yds)9msNtPb@GtG#e`_#h_u%2#s1fAwcQ-rPAgn^w-jZ@uj+4dVyDW8iVAz9*Ssit+8Q2R?o~!kHN1Q3O;y(GLfBVU3F7`t=`ROh7*(XkD!=EGk!XFR) z8HZ?pzDM+aQm1wW-aOokxf*`#GxdoXe&iv&;H84>0O+k-o;UThZtOV^PYLu zfh8W;Jll8SL(3fOvqtBL9DJw#yX2QHYE8!&>sAD>w8k9jBVYM3SMyDEujX6jHr&%Ljd$E&PwwJW&#Bry zG~S=#!T-=-_k1|7|3Mx`qar55refaRJf}3O{}Xy=-n+|o9(yRw+!tsy#3xAt}XZW-FzO;Fy^y|DT2$#d-0n(>IW~mncMhl`sN-!PUufu1Gl#$ zbL0PG+|x^Xu3mFHE*$3S z&1W1q(i?hFCq{YsRgOD=CUGNbHoucUz0s>RBYJ1_Zr`4Rb@j`m@7`T&IUYA2WxjJMz-!oAZdGo|kiQ z#+(zg<}CK|+i$-eKA+D!`1~9A+x!hY$iM&m_y79ye}C~GU;Nv@{^S4r^B4c}=YM+e Ezv_}}_W%F@ literal 0 HcmV?d00001 diff --git a/media/textures/smooth.tga b/media/textures/smooth.tga index 0201f3371b718ee6872084fd9b45076386a2cae0..9ad81ad91ac1c9e2b98ed8ea8983054e8b0a4865 100755 GIT binary patch literal 32812 zcmeH`?W$eX6^7IP>ScHX?Oj+9N(=oW<|Yg%C@A_PK|xV4#2-oo1qCGm1qDSR0R=@t zA;ExR?qxM&)93U#uVc=&_BlI7XbO{ejQ4A-vrW&O`Td!r|NZWvGY|dY{Q2|CV~;(y z7@3o2M+cK<2g}!a&6Sr2?_4*-8Mz6TMlT#Y8i>vgnoo`{JjT&n9rS?iA(uY(#LiD2 z{YLWkz~M`c9mHp(qdYmojq>Q^+>1t*9j|$7$+M4gnZ*a9)6-#j;XOO+K6rbXL3_x8 z+`i6@>|>OKDWR z^4#?9dDL%DHaSaQ4{pTso%L_wsh!tOKob zWI?o1@5o0NI{3^p&n(@0`st^4JlJ{6ZS^^G+PS;gai_i0u))2zWY7a zxb7xg;b>m#wN8h*L(H?@nRbZV_qyY`=bl?0ylub1v(G+zs^99g`TP0b=@8%kTj{u; zzvFN1_Js=H2{`MWNT{~K@pmd&@~-_uER z{;pBSh%y?&Z7Oum*S)P5e zUFV4FZjHRj`iL(*Z!upZ_PgTt+~;C z_b`KN-RR{fQ~2VGFCM*@UV7vP6)W!OP_Mwq^CFV4?h_T#ahv;C#zo_;*`dA8p? zbDfH_pR!_~|yYA%3kOT2~$BR~ozNXph{EWxP z4fYQ4fL$-z2+5S*dCcSGTT+9^m%8_w?Q?eDnO=9&on3gW!-1)p&pz+=F@x#rcs!-? z;0m3w4iBzn@MQ;@1pZ)fAGh88$E;R4vJm+09iJ5V(G@kjK z+40f|mhNYs8KleTtmn+IgV~XM?S7+f_q_i4>&qK&ys;Q-9_@JX;4410jcTCjc#LR*vWJ|`O@$uriKph4sN8D8GPo+pe1sL42aJ=vymBpp}Csbnb}8~jwee$ zJ4nWR&G@(I_{n6KclULE>+Z#i&Ym9Yp6%m%K)Pn=uFf~o)62~c?akRc+2Y`f^UjR^ z)?05aZ@>Na?szS?@(wj&I zo^B)a$OB)PGrRBLGjan&V>gaw-y)w}W%G63(G7Tdjr7ou<_sL((M|@$H`?KiHM3_P z4Ly(p##K67PQV>i2v%Ofy!kEON4;dZ!%jAL z^Jt)N6bBD>y0w}=_~3)(!w)~);cPCASAJ)lgExAfb>8HylpM0`=HIJS>o=16m zYQ~rS>BHOk(a3B;?%A8&);!}Y&OJF>cg9`aJn9+sWjA?v<7oDGkngy){7iSReWSmt zyN}m6@+D8k-(gScoo~d^!{0?0y!Y&2A7#zY`sm>nJ9+lCj?zE>{PUyt*=L{a=0aZS zo;yEW`no;)?5WvZcxQ;;9?x`w`17uH<`L4L9q`7{J$Sry&2Emoqb~d)H}LybYIwl( z!WW{!v1jL29-q5MUA{@qNUp;z{p9evo7=|ple5S3$e(<7H$B|y_>p$~`t_yWjT<+P zkQvQ79G*hI)V-5&pR>#}-F^7zbsis{(M}ef4lsH44#|M_6j!@7X0$E-&XZi%XOCyR ziRFRA@4aRox-;obkM-2(!85v(JUiI+!j*>^B!|YHdhK{T+u!N*fFnQp2+4u=b$2@- znJ>Tma`F4(i!YA$ntApx#vWYIXoakM8aJ~(!;c+WFm zr_HkXM>o)`gO^_OGi~%8=9x$6@A0klr*E_;PtT0U1L93YFZ5hK@10JUeQ=3*;Bz-` zt!CcLgI0*&Xq~xqW^##i*k_M<_tpH(H{a~ux8HtyG{b?`JX?nct$8jTk1=^Pvc}Zb z_R6}SE;taM(O&qi_cH5!){z=_oo7zXyysabS|M}x!Y6Vg`PzASMx7%){rKqR=EyhV z$)mG(eaYp{H_^rJPG`{5Z@!z|k=^W>b7pk!yYIeR_I=-f|NSnL=pHn4p111d>%4HF zyJxfgo<|uxiRCv}GkbQ8`1H+oI>7WMpL_b*(^oqW&kRR-GUyW zWTwNrXY>xUhg|Z`;xWgJ2Ev0U;mLs2b@S%U<<_lR$FR8WrLXqnx|})uGp_U4f6|#= za7)h?uRY9QcVnh?{^Uma5%2uWgI4HQc{Fz&Y94i)=X<)Fw{9N)_v>8ePtJbsm@7Yf z>hRe)+SAVtcDb2m|5l$fKm72+vi04*eY^FJ_^rJs@%iSK**ENmhXafEjIYD=<-R3@ zC$qWZGj8#ef2+^kYxAr#wcN9NO;7(J_Pm+<)*Iv!$&YySLm_vz_Wk(dk4wIve){Pb zoIRc1acddtHLrD~zuOPd(e=*0?_S+JRPS0(>ghCyI&**PDd-m+| z;63;a9{d~l|NJ*_?$Jk=dXFCbox9uFy}_+>cX{5iZ*j*Ud(3|z58twe&24_ud-J<) z{QLaf%{LzYzxVvR_)UK8yN9{we}gsaZ}smyn9tqi`TMuvv3}pW2lJW#{_mfE|JTF+ We&ipI{OzxQJp1QI{_^mj&in_%iDNtf literal 32812 zcmeH`ee0%k8pdb$uYDQb!0x-SrMBJLr}kYCqKKkqB19BL6h$;sL=hq6F^Wc}JiM1{ z_qf~7?8h zaQIqd2k{x{h^J?`SstC7d(p_U<27%sdG=YZv-m)CdPW#8yk}?K2X8MkXb)MCTX;aS zAimDsdh4yrEw|kAqc`JjzWL@Q8ahb6_wdcpVJ#dT=948qn&H4?=?C5GZr@BkyE*da ze8*kB3r}A%;r!e)x{cR9dO@@xoYCJMo=1)ygr~3h>~sd>>z$5xneosEatCzAS#;3( z=5mW~!w2?vBx{a2JiQ>_MprO?GUly0A1^ydE_-v)%#A$O?YDR2fy+1De*5jqZMWUF z!^~R`FKB-_p83q}$2a1gZGBB!^E!9vOfQ(cXZl9mq27J{xz+dJW<1|{DAId5IsP8L zsgX{2{P3Xlk*9TXMteNlGn(;&_B7Xfyd!R{11&kSAlj^V=A#Q8yz|aGm(jc9jyrZd zIP#d=*XPW!^XTS?JNC{ff9#!O^2cQJw;Y=v{T^G~=q6lnHgEM>r^DPy%xk@C+DY8L z(j9l-efM(h?e`npb=O@-{Z_~3f69MPC-Ln+myVzEcl^2CzW3gHmuqjo-{78m?m6nW zIyV1H|MzqffB#8z{L+8Nll=bEr%x|i@64Gqo1U$XYx?Qs*Z4dB8vo|2`rrDQ?f-w* zzURLC?pyNizyJQ-V>h3u{*J@nAd4?5ekv(b8QKc4u~ALOBpGBb{Q?!aqp z)V))8HJ#ay0^xolvXdr(ByFJb^$JZIMAYQsg zd^CFOC)1q0=^J(8X&tZ89_M`59`pFkZOzXEpE=KDecQ7;&3hhsqVu@NPS%KKuV=jG zGLr+%F@xO^z8@ZA&)!Gf(ea>G#AFPwcoLb3C4%fd|ogAMx#B2gx*Ej=pbZ%h%t+-ns0}#R~_LKLppZYg*r! zd1t)8f1jD2#{Q1(x*UDh;oF(LkM7Wecgv5y)-}`i;kWun-`knl{^XNSE>Au6)MCs$ z+wtPT7rwO-XTLihyckA9W zKl98pyZ7|dPhT>JgJ)(>ZpNX}ZR`v?nbA%@8otKX(Ba*|jn+DY&pa8lM(&US@p)%9 zGUE@L%goNqKFf@Fvh=fqWV~m_zmJZeOm}&A-^g#>y?D{t+hg6ceS8l{*BZKOmr&po$$p5cPwdGPEYJ}^9Uqcdw7KDzM2vxD$!Xs>57 z;mnU_JYce(=~_d28_B@aZDgK#;DbH0`wl)MH$XIY<81aV^35gNZ{(fbfT!0;5B+G) zz~P+k4?+)_j$r+jPyR&D!!O={IHFM-z-@4=6EZcY3L3eP^ zIMaR49`oFw&l(wPt)tQ73|>6!BQ(cM4h)Y5_Fa3>Ks3;NX7--#A9>J0^7f(y;oo!WU-z-EAwBM;56=5&-lyMp+|fK;-1gqN+1{P_;EiY? zTJPb*ojv!zf0uYbXPH5Jm_ai%EUfJQ=9E}&hGtR*qJ+F1p)Bfz{ zMzeeAF`^sk1<|}S2kB$R58`E?AwGJHXvxAeTcdj)4iD%)dd$VwJDmNVN8O#l19Ahz zZ@sm?$xgQY@Zd;q&7Nre&_VJ>GV%D0csTO(l7qLeXM54y1K0T4Yp*S@zWVB7WDal5 zb3E;{-x@Qx))NnpKKtQDUHHg@WE$N;)`;IeI*nxD$c@mR%$-FaX|p~$8tF1mNB6gf ztbJsS_Ib94nXc^i!o%(BZ(rxp_eJu?WW9T)*BmpN(OPD@@wDC^_V&Y*2kBqa-+1GV z<@MKJ-@VMUXOHJu-k!|(y1#vRM}9Oi`ylu1?QUzH@r83w&(@uB*Jz&g%=)^UJiKu> z`#Z>wxUKw}?q2(5f7j?fUgONyJQ;t7J*|&?GmakqF1p~ocL)0{YksYd9&WLdXW#0G z{?=P>U3_o8`Q~m8@}hel`Qh3(+Plx5%h57=J#AQ~KdckavMbN8&vH^~{vjc}iSa(La%ZDae%+2eWUZ+>*Q zJ=_}cGwq#s-dXbAefQnv?YH0FVfM^uBaEM1W_EJ)kwwpr2aO)%A)33HeFKh8@0mwl zduHDiexEFN<8^Ol@Aw+=1k=H5-`ei)#Mj@`J9qK>erBG#$+VY_5jr28@1TRu&W3M| z9dxGeaLY(1-{Aag<`x*A=dIlA7T+86%s09hJsf_%q5by0|Ni?+zYjk6V8^}p-g^rV z4sZ5o&0Eh*9v&pm4!SSd=FKtFXpIPVV9x@!Ub9tC6mtGvti+n(rJwZn3wI@5hG@PY#3+wwE364C5Q!iyywT@Zg%) zS^PoIc;ME)y|rY*@psS>%=_r0k5=D@AAY#x+4u3sAMbYfk;i`f%x6X$&1=1AN8be(PyZI=!M+bq2Z)b-S!U38`Q6Pi`!^&D z;_>b|`fLx+qi5uAZPwRW`$m5Qz4pQ3&(4f5$c#T24lld)(d?el{K+SuEP0=O_Sp_U z{q)lvhRe*u*L(Y%rB2an%4>W;tj_@cQF-u_uX-stY2)0{gpcYp8g?;E3?j?vu_*B#`;XZDVl zzYR~&k306k*+(~bf@DBE?Bw0|`RAW6$G$JV_~Ph}{)Q{jdCU#I2XxnnJ4Cm4HgDaS z*L{XHYCx!$+(*4JiwgUloUn$~`MnS;!0{?@kkS?5}Al=!clg_t@VujBW~8w z-rk*St#^B`*3376$KG|1=kw>!FJFKC^KXZGzDxKEm;N_=iD&TNxo_g% z`bK=6O^(-^_e1)9Yv1|M{%^nicIo%sci&yY*)!5d+*ZbV=B@i*Ly_)k6Km4#)W>UtMUCmhi^Fc@66wDQh&!u_00aJQ~&+v?|=Qr_5Zx#Z#Vqq&%giIA8+{6^?x|^ EZ+31>RsaA1 diff --git a/media/textures/smoother.tga b/media/textures/smoother.tga new file mode 100644 index 0000000000000000000000000000000000000000..0201f3371b718ee6872084fd9b45076386a2cae0 GIT binary patch literal 32812 zcmeH`ee0%k8pdb$uYDQb!0x-SrMBJLr}kYCqKKkqB19BL6h$;sL=hq6F^Wc}JiM1{ z_qf~7?8h zaQIqd2k{x{h^J?`SstC7d(p_U<27%sdG=YZv-m)CdPW#8yk}?K2X8MkXb)MCTX;aS zAimDsdh4yrEw|kAqc`JjzWL@Q8ahb6_wdcpVJ#dT=948qn&H4?=?C5GZr@BkyE*da ze8*kB3r}A%;r!e)x{cR9dO@@xoYCJMo=1)ygr~3h>~sd>>z$5xneosEatCzAS#;3( z=5mW~!w2?vBx{a2JiQ>_MprO?GUly0A1^ydE_-v)%#A$O?YDR2fy+1De*5jqZMWUF z!^~R`FKB-_p83q}$2a1gZGBB!^E!9vOfQ(cXZl9mq27J{xz+dJW<1|{DAId5IsP8L zsgX{2{P3Xlk*9TXMteNlGn(;&_B7Xfyd!R{11&kSAlj^V=A#Q8yz|aGm(jc9jyrZd zIP#d=*XPW!^XTS?JNC{ff9#!O^2cQJw;Y=v{T^G~=q6lnHgEM>r^DPy%xk@C+DY8L z(j9l-efM(h?e`npb=O@-{Z_~3f69MPC-Ln+myVzEcl^2CzW3gHmuqjo-{78m?m6nW zIyV1H|MzqffB#8z{L+8Nll=bEr%x|i@64Gqo1U$XYx?Qs*Z4dB8vo|2`rrDQ?f-w* zzURLC?pyNizyJQ-V>h3u{*J@nAd4?5ekv(b8QKc4u~ALOBpGBb{Q?!aqp z)V))8HJ#ay0^xolvXdr(ByFJb^$JZIMAYQsg zd^CFOC)1q0=^J(8X&tZ89_M`59`pFkZOzXEpE=KDecQ7;&3hhsqVu@NPS%KKuV=jG zGLr+%F@xO^z8@ZA&)!Gf(ea>G#AFPwcoLb3C4%fd|ogAMx#B2gx*Ej=pbZ%h%t+-ns0}#R~_LKLppZYg*r! zd1t)8f1jD2#{Q1(x*UDh;oF(LkM7Wecgv5y)-}`i;kWun-`knl{^XNSE>Au6)MCs$ z+wtPT7rwO-XTLihyckA9W zKl98pyZ7|dPhT>JgJ)(>ZpNX}ZR`v?nbA%@8otKX(Ba*|jn+DY&pa8lM(&US@p)%9 zGUE@L%goNqKFf@Fvh=fqWV~m_zmJZeOm}&A-^g#>y?D{t+hg6ceS8l{*BZKOmr&po$$p5cPwdGPEYJ}^9Uqcdw7KDzM2vxD$!Xs>57 z;mnU_JYce(=~_d28_B@aZDgK#;DbH0`wl)MH$XIY<81aV^35gNZ{(fbfT!0;5B+G) zz~P+k4?+)_j$r+jPyR&D!!O={IHFM-z-@4=6EZcY3L3eP^ zIMaR49`oFw&l(wPt)tQ73|>6!BQ(cM4h)Y5_Fa3>Ks3;NX7--#A9>J0^7f(y;oo!WU-z-EAwBM;56=5&-lyMp+|fK;-1gqN+1{P_;EiY? zTJPb*ojv!zf0uYbXPH5Jm_ai%EUfJQ=9E}&hGtR*qJ+F1p)Bfz{ zMzeeAF`^sk1<|}S2kB$R58`E?AwGJHXvxAeTcdj)4iD%)dd$VwJDmNVN8O#l19Ahz zZ@sm?$xgQY@Zd;q&7Nre&_VJ>GV%D0csTO(l7qLeXM54y1K0T4Yp*S@zWVB7WDal5 zb3E;{-x@Qx))NnpKKtQDUHHg@WE$N;)`;IeI*nxD$c@mR%$-FaX|p~$8tF1mNB6gf ztbJsS_Ib94nXc^i!o%(BZ(rxp_eJu?WW9T)*BmpN(OPD@@wDC^_V&Y*2kBqa-+1GV z<@MKJ-@VMUXOHJu-k!|(y1#vRM}9Oi`ylu1?QUzH@r83w&(@uB*Jz&g%=)^UJiKu> z`#Z>wxUKw}?q2(5f7j?fUgONyJQ;t7J*|&?GmakqF1p~ocL)0{YksYd9&WLdXW#0G z{?=P>U3_o8`Q~m8@}hel`Qh3(+Plx5%h57=J#AQ~KdckavMbN8&vH^~{vjc}iSa(La%ZDae%+2eWUZ+>*Q zJ=_}cGwq#s-dXbAefQnv?YH0FVfM^uBaEM1W_EJ)kwwpr2aO)%A)33HeFKh8@0mwl zduHDiexEFN<8^Ol@Aw+=1k=H5-`ei)#Mj@`J9qK>erBG#$+VY_5jr28@1TRu&W3M| z9dxGeaLY(1-{Aag<`x*A=dIlA7T+86%s09hJsf_%q5by0|Ni?+zYjk6V8^}p-g^rV z4sZ5o&0Eh*9v&pm4!SSd=FKtFXpIPVV9x@!Ub9tC6mtGvti+n(rJwZn3wI@5hG@PY#3+wwE364C5Q!iyywT@Zg%) zS^PoIc;ME)y|rY*@psS>%=_r0k5=D@AAY#x+4u3sAMbYfk;i`f%x6X$&1=1AN8be(PyZI=!M+bq2Z)b-S!U38`Q6Pi`!^&D z;_>b|`fLx+qi5uAZPwRW`$m5Qz4pQ3&(4f5$c#T24lld)(d?el{K+SuEP0=O_Sp_U z{q)lvhRe*u*L(Y%rB2an%4>W;tj_@cQF-u_uX-stY2)0{gpcYp8g?;E3?j?vu_*B#`;XZDVl zzYR~&k306k*+(~bf@DBE?Bw0|`RAW6$G$JV_~Ph}{)Q{jdCU#I2XxnnJ4Cm4HgDaS z*L{XHYCx!$+(*4JiwgUloUn$~`MnS;!0{?@kkS?5}Al=!clg_t@VujBW~8w z-rk*St#^B`*3376$KG|1=kw>!FJFKC^KXZGzDxKEm;N_=iD&TNxo_g% z`bK=6O^(-^_e1)9Yv1|M{%^nicIo%sci&yY*)!5d+*ZbV=B@i*Ly_)k6Km4#)W>UtMUCmhi^Fc@66wDQh&!u_00aJQ~&+v?|=Qr_5Zx#Z#Vqq&%giIA8+{6^?x|^ EZ+31>RsaA1 literal 0 HcmV?d00001 diff --git a/modules/layout.lua b/modules/layout.lua index d23b6df5a..181860cd1 100755 --- a/modules/layout.lua +++ b/modules/layout.lua @@ -153,7 +153,9 @@ SML:Register(SML.MediaType.FONT, "Myriad Condensed Web", "Interface\\AddOns\\Sha SML:Register(SML.MediaType.BORDER, "Square Clean", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\ABFBorder") SML:Register(SML.MediaType.BACKGROUND, "Chat Frame", "Interface\\ChatFrame\\ChatFrameBackground") SML:Register(SML.MediaType.STATUSBAR, "BantoBar", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\banto") -SML:Register(SML.MediaType.STATUSBAR, "Smooth", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smooth") +SML:Register(SML.MediaType.STATUSBAR, "Smooth", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Smooth") +SML:Register(SML.MediaType.STATUSBAR, "Smooth v2","Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Smoothv2") +SML:Register(SML.MediaType.STATUSBAR, "Smoother", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smoother") SML:Register(SML.MediaType.STATUSBAR, "Perl", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\perl") SML:Register(SML.MediaType.STATUSBAR, "Glaze", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\glaze") SML:Register(SML.MediaType.STATUSBAR, "Charcoal", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Charcoal") From f7555639e4341e1d038b873c22ec496a8a5a6472 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Mon, 7 Dec 2020 14:23:34 +0100 Subject: [PATCH 041/108] Treat player-controlled units like players in health bar coloring --- modules/health.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/health.lua b/modules/health.lua index 902fabb93..187e0641b 100755 --- a/modules/health.lua +++ b/modules/health.lua @@ -98,7 +98,7 @@ function Health:UpdateColor(frame) color = ShadowUF.db.profile.classColors.VEHICLE elseif( not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) and UnitCanAttack("player", unit) ) then color = ShadowUF.db.profile.healthColors.tapped - 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 + elseif( not UnitPlayerOrPetInRaid(unit) and not UnitPlayerOrPetInParty(unit) and ( ( ( reactionType == "player" or reactionType == "both" ) and UnitPlayerControlled(unit) and not UnitIsFriend(unit, "player") ) or ( ( reactionType == "npc" or reactionType == "both" ) and not UnitPlayerControlled(unit) ) ) ) then if( not UnitIsFriend(unit, "player") and UnitPlayerControlled(unit) ) then if( UnitCanAttack("player", unit) ) then color = ShadowUF.db.profile.healthColors.hostile From 60ff1b0d19940fb8490ac1c3cbf029c8bfc0782a Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Mon, 7 Dec 2020 14:49:55 +0100 Subject: [PATCH 042/108] Fix case of smooth texture --- modules/layout.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/layout.lua b/modules/layout.lua index 181860cd1..d483a0b6d 100755 --- a/modules/layout.lua +++ b/modules/layout.lua @@ -153,7 +153,7 @@ SML:Register(SML.MediaType.FONT, "Myriad Condensed Web", "Interface\\AddOns\\Sha SML:Register(SML.MediaType.BORDER, "Square Clean", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\ABFBorder") SML:Register(SML.MediaType.BACKGROUND, "Chat Frame", "Interface\\ChatFrame\\ChatFrameBackground") SML:Register(SML.MediaType.STATUSBAR, "BantoBar", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\banto") -SML:Register(SML.MediaType.STATUSBAR, "Smooth", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Smooth") +SML:Register(SML.MediaType.STATUSBAR, "Smooth", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smooth") SML:Register(SML.MediaType.STATUSBAR, "Smooth v2","Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Smoothv2") SML:Register(SML.MediaType.STATUSBAR, "Smoother", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smoother") SML:Register(SML.MediaType.STATUSBAR, "Perl", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\perl") From 504a7ed1535200eb103dc92d3c975e94c63b869e Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Mon, 15 Mar 2021 11:21:27 +0100 Subject: [PATCH 043/108] Update TOC --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 115cb899e..8115abd11 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 90002 +## Interface: 90005 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index fe265fad6..a9115d5f5 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 90002 +## Interface: 90005 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 200f064ecb205a2b796cb8dee7cc75b37b61a6d0 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 21 May 2021 17:53:28 +0200 Subject: [PATCH 044/108] Properly update the profile version when loading a new profile --- ShadowedUnitFrames.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 1db0eb57d..009049421 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -638,8 +638,11 @@ function ShadowUF:ProfilesChanged() self:LoadDefaultLayout() else self:CheckUpgrade() + self:CheckBuild() end + self.db.profile.revision = self.dbRevision + self:FireModuleEvent("OnProfileChange") self:LoadUnits() self:HideBlizzardFrames() From cd5e1f8916708ec3d97363ba9b07c2ab6ed9f7b8 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 21 May 2021 17:56:01 +0200 Subject: [PATCH 045/108] Merge profile changes for modules that are enabled by default --- modules/defaultlayout.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/defaultlayout.lua b/modules/defaultlayout.lua index 10f9da667..37de72cdd 100755 --- a/modules/defaultlayout.lua +++ b/modules/defaultlayout.lua @@ -38,7 +38,7 @@ local function finalizeData(config, useMerge) -- Set everything for unit, child in pairs(config.units) do if( self.defaults.profile.units[unit] ) then - if( not useMerge or ( useMerge and not self.db.profile.units[unit].enabled and self.db.profile.units[unit].height == 0 and self.db.profile.units[unit].width == 0 and self.db.profile.positions[unit].anchorPoint == "" and self.db.profile.positions[unit].point == "" ) ) then + if( not useMerge or ( useMerge and self.db.profile.units[unit].height == 0 and self.db.profile.units[unit].width == 0 and self.db.profile.positions[unit].anchorPoint == "" and self.db.profile.positions[unit].point == "" ) ) then -- Merge the primary parent table mergeToChild(config.parentUnit, child) -- Strip any invalid tables From b317a546587ed94f26cf9585884208426a4a6707 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 29 Jun 2021 23:31:18 +0200 Subject: [PATCH 046/108] Update TOC for 9.1 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 8115abd11..d058979e6 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 90005 +## Interface: 90100 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index a9115d5f5..289c02f05 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 90005 +## Interface: 90100 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 08817beee4ad2591b485a9c895f5e628dd983899 Mon Sep 17 00:00:00 2001 From: exochron Date: Wed, 30 Jun 2021 09:41:56 +0200 Subject: [PATCH 047/108] Added Totem bar for Death Knight Ghouls --- modules/totems.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/totems.lua b/modules/totems.lua index 0fc57b2c1..7aa1243d8 100755 --- a/modules/totems.lua +++ b/modules/totems.lua @@ -2,9 +2,13 @@ local Totems = {} local totemColors = {} local MAX_TOTEMS = MAX_TOTEMS --- Death Knights untalented ghouls are guardians and are considered totems........... so set it up for them local playerClass = select(2, UnitClass("player")) -if( playerClass == "DRUID" ) then +if( playerClass == "DEATHKNIGHT" ) then + MAX_TOTEMS = 1 + -- Unholy DKs get rank 2 on level 29 which converts their ghoul into a proper pet. + local spec = (UnitLevel("player") < 29) and {1, 2, 3} or {1, 2} + ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Totem bar"], true, "DEATHKNIGHT", spec, 12) +elseif( playerClass == "DRUID" ) then MAX_TOTEMS = 1 ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Mushroom bar"], true, "DRUID", 4, 39) elseif( playerClass == "MONK" ) then From 97d48cf5b8dc97eabc6ba7e78b45870c055c3f89 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 30 Jun 2021 09:46:00 +0200 Subject: [PATCH 048/108] Some tweaking for ghoul bar --- modules/totems.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/totems.lua b/modules/totems.lua index 7aa1243d8..2540a99c2 100755 --- a/modules/totems.lua +++ b/modules/totems.lua @@ -7,7 +7,7 @@ if( playerClass == "DEATHKNIGHT" ) then MAX_TOTEMS = 1 -- Unholy DKs get rank 2 on level 29 which converts their ghoul into a proper pet. local spec = (UnitLevel("player") < 29) and {1, 2, 3} or {1, 2} - ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Totem bar"], true, "DEATHKNIGHT", spec, 12) + ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Ghoul bar"], true, "DEATHKNIGHT", spec, 12) elseif( playerClass == "DRUID" ) then MAX_TOTEMS = 1 ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Mushroom bar"], true, "DRUID", 4, 39) @@ -55,7 +55,9 @@ function Totems:OnEnable(frame) table.insert(frame.totemBar.totems, totem) end - if( playerClass == "DRUID" ) then + if( playerClass == "DEATHKNIGHT" ) then + totemColors[1] = ShadowUF.db.profile.classColors.PET + elseif( playerClass == "DRUID" ) then totemColors[1] = ShadowUF.db.profile.powerColors.MUSHROOMS elseif( playerClass == "WARLOCK" ) then totemColors[1] = ShadowUF.db.profile.classColors.PET From 8b1d30cfd31faaff71fef6612b1cf41a3e3fcac8 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 22 Sep 2022 11:29:07 +0200 Subject: [PATCH 049/108] Update Hide Blizzard for WoW 10.0 --- .luacheckrc | 3 +++ ShadowedUnitFrames.lua | 24 ++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index a20b9d72e..42bbd4534 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -149,6 +149,7 @@ read_globals = { "CompactPartyFrame", "CompactRaidFrameContainer", "CompactRaidFrameManager", + "DebuffFrame", "DEFAULT_CHAT_FRAME", "FocusFrame", "FocusFrameToT", @@ -156,8 +157,10 @@ read_globals = { "MageArcaneChargesFrame", "MonkHarmonyBarFrame", "PaladinPowerBarFrame", + "PartyFrame", "PetCastingBarFrame", "PetFrame", + "PlayerCastingBarFrame", "PlayerFrame", "PlayerFrameAlternateManaBar", "PlayerPowerBarAlt", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 009049421..eca0788b6 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -694,13 +694,21 @@ end local active_hiddens = {} function ShadowUF:HideBlizzardFrames() if( self.db.profile.hidden.cast and not active_hiddens.cast ) then - hideBlizzardFrames(true, CastingBarFrame, PetCastingBarFrame) + hideBlizzardFrames(true, PlayerCastingBarFrame or CastingBarFrame, PetCastingBarFrame) end if( self.db.profile.hidden.party and not active_hiddens.party ) then - for i=1, MAX_PARTY_MEMBERS do - local name = "PartyMemberFrame" .. i - hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"]) + if( PartyFrame ) then + hideBlizzardFrames(false, PartyFrame) + for memberFrame in PartyFrame.PartyMemberFramePool:EnumerateActive() do + hideBlizzardFrames(false, memberFrame, memberFrame.HealthBar, memberFrame.ManaBar) + end + PartyFrame.PartyMemberFramePool:ReleaseAll() + else + for i=1, MAX_PARTY_MEMBERS do + local name = "PartyMemberFrame" .. i + hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"]) + end end -- This stops the compact party frame from being shown @@ -741,7 +749,7 @@ function ShadowUF:HideBlizzardFrames() end if( self.db.profile.hidden.buffs and not active_hiddens.buffs ) then - hideBlizzardFrames(false, BuffFrame, TemporaryEnchantFrame) + hideBlizzardFrames(false, BuffFrame, TemporaryEnchantFrame or DebuffFrame) end if( self.db.profile.hidden.player and not active_hiddens.player ) then @@ -777,7 +785,11 @@ function ShadowUF:HideBlizzardFrames() if( self.db.profile.hidden.boss and not active_hiddens.boss ) then for i=1, MAX_BOSS_FRAMES do local name = "Boss" .. i .. "TargetFrame" - hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"]) + if _G[name].TargetFrameContent then + hideBlizzardFrames(false, _G[name], _G[name].TargetFrameContent.TargetFrameContentMain.HealthBar, _G[name].TargetFrameContent.TargetFrameContentMain.ManaBar) + else + hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"]) + end end end From c23dba7b3f6d31c67097a5a47adf919924253485 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 7 Oct 2022 09:50:24 +0200 Subject: [PATCH 050/108] Add Evoker support (class color, power color, essence bar) --- ShadowedUnitFrames.lua | 9 ++++++++- ShadowedUnitFrames.toc | 1 + modules/defaultlayout.lua | 3 +++ modules/essence.lua | 31 +++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 modules/essence.lua diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index eca0788b6..c56dff46b 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -5,7 +5,7 @@ ShadowUF = select(2, ...) local L = ShadowUF.L -ShadowUF.dbRevision = 62 +ShadowUF.dbRevision = 63 ShadowUF.playerUnit = "player" ShadowUF.enabledUnits = {} ShadowUF.modules = {} @@ -112,6 +112,12 @@ end function ShadowUF:CheckUpgrade() local revision = self.db.profile.revision or self.dbRevision + if (revision <= 62 ) then + -- evoker setup + self.db.profile.classColors.EVOKER = {r = 0.20, g = 0.58, b = 0.50} + self.db.profile.powerColors.ESSENCE = {r = 0.40, g = 0.80, b = 1.00} + self.db.profile.units.player.essence = {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} + end if (revision <= 61 ) then if self.db.profile.bars.texture == "Smooth" then self.db.profile.bars.texture = "Smoother" @@ -362,6 +368,7 @@ function ShadowUF:LoadUnitDefaults() 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} self.defaults.profile.units.player.auraPoints = {enabled = false, isBar = true} + self.defaults.profile.units.player.essence = {enabled = true, 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}) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index d058979e6..93fc7bccd 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -66,6 +66,7 @@ modules\aurapoints.lua modules\priest.lua modules\shaman.lua modules\arcanecharges.lua +modules\essence.lua #@do-not-package@ options\config.lua #@end-do-not-package@ diff --git a/modules/defaultlayout.lua b/modules/defaultlayout.lua index 37de72cdd..2ceb6fb5d 100755 --- a/modules/defaultlayout.lua +++ b/modules/defaultlayout.lua @@ -137,6 +137,7 @@ function ShadowUF:LoadDefaultLayout(useMerge) 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}, + EVOKER = {r = 0.20, g = 0.58, b = 0.50}, PET = {r = 0.20, g = 0.90, b = 0.20}, VEHICLE = {r = 0.23, g = 0.41, b = 0.23}, } @@ -167,6 +168,7 @@ function ShadowUF:LoadDefaultLayout(useMerge) 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}, + ESSENCE = {r = 0.40, g = 0.80, b = 1.00}, } config.healthColors = { tapped = {r = 0.5, g = 0.5, b = 0.5}, @@ -354,6 +356,7 @@ function ShadowUF:LoadDefaultLayout(useMerge) 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}, + essence = {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}, diff --git a/modules/essence.lua b/modules/essence.lua new file mode 100644 index 000000000..6cd7442be --- /dev/null +++ b/modules/essence.lua @@ -0,0 +1,31 @@ +if( not ShadowUF.ComboPoints ) then return end + +local Essence = setmetatable({}, {__index = ShadowUF.ComboPoints}) +ShadowUF:RegisterModule(Essence, "essence", ShadowUF.L["Essence"], nil, "EVOKER") +local essenceConfig = {max = 5, key = "essence", colorKey = "ESSENCE", powerType = Enum.PowerType.Essence, eventType = "ESSENCE", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"} + +function Essence:OnEnable(frame) + frame.essence = frame.essence or CreateFrame("Frame", nil, frame) + frame.essence.cpConfig = essenceConfig + + 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") + + essenceConfig.max = UnitPowerMax("player", essenceConfig.powerType) +end + +function Essence:OnLayoutApplied(frame, config) + ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config) + self:UpdateBarBlocks(frame) +end + +function Essence:GetComboPointType() + return "essence" +end + +function Essence:GetPoints(unit) + return UnitPower("player", essenceConfig.powerType) +end From 296b8722f4cc875343a1eee28f4dd7c7a96a8ed4 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 7 Oct 2022 10:07:24 +0200 Subject: [PATCH 051/108] Fix a minor difference in localization --- options/config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/config.lua b/options/config.lua index a2bd8b70f..f81b88781 100755 --- a/options/config.lua +++ b/options/config.lua @@ -7198,7 +7198,7 @@ local function loadAuraIndicatorsOptions() create = { order = 3, type = "execute", - name = L["Add aura"], + 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 "") From 40d81d1255fbcb754ccfd8060235d9c933affd9b Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 7 Oct 2022 10:13:51 +0200 Subject: [PATCH 052/108] Update TOC for 9.2.7 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 93fc7bccd..548f3d1d2 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 90100 +## Interface: 90207 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 289c02f05..ecab090f3 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 90100 +## Interface: 90207 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From a50a7b41f32c850d0b79a821e678b1749313c62d Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 7 Oct 2022 10:25:38 +0200 Subject: [PATCH 053/108] Support UTF8 lib for abbreviating names --- .luacheckrc | 1 + .pkgmeta | 2 ++ ShadowedUnitFrames.toc | 3 ++- modules/tags.lua | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 42bbd4534..db83326cc 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -32,6 +32,7 @@ read_globals = { "CopyTable", "string.split", "string.trim", + "string.utf8sub", "table.wipe", "time", diff --git a/.pkgmeta b/.pkgmeta index 0cc5e480d..c4b13cd29 100755 --- a/.pkgmeta +++ b/.pkgmeta @@ -16,6 +16,8 @@ externals: url: https://repos.wowace.com/wow/libdualspec-1-0 libs/LibSpellRange-1.0: url: https://github.com/ascott18/LibSpellRange-1.0.git + libs/UTF8: + url: https://repos.wowace.com/wow/utf8/tags/v1.1 options/libs/AceConfig-3.0: url: https://repos.wowace.com/wow/ace3/trunk/AceConfig-3.0 options/libs/AceDBOptions-3.0: diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 548f3d1d2..4800b07eb 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -5,7 +5,7 @@ ## Version: @project-version@ ## SavedVariables: ShadowedUFDB ## X-Website: https://www.wowace.com/addons/shadowed-unit-frames/ -## OptionalDeps: Ace3, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibDualSpec-1.0, LibSpellRange-1.0, Clique +## OptionalDeps: Ace3, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibDualSpec-1.0, LibSpellRange-1.0, UTF8, Clique ## X-Curse-Project-ID: 19268 ## X-WoWI-ID: 13494 @@ -16,6 +16,7 @@ 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 +libs\UTF8\utf8.lua #@end-no-lib-strip@ localization\enUS.lua diff --git a/modules/tags.lua b/modules/tags.lua index 1f38d139e..2a9fc27ca 100755 --- a/modules/tags.lua +++ b/modules/tags.lua @@ -368,7 +368,7 @@ end -- Name abbreviation local function abbreviateName(text) - return string.sub(text, 1, 1) .. "." + return (string.utf8sub or string.sub)(text, 1, 1) .. "." end Tags.abbrevCache = setmetatable({}, { From cea7f063d22fb1cee747ecdff045822cc1c2de89 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 25 Oct 2022 14:54:50 +0200 Subject: [PATCH 054/108] Fix default override color return --- options/config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/config.lua b/options/config.lua index f81b88781..91eff5b14 100755 --- a/options/config.lua +++ b/options/config.lua @@ -948,7 +948,7 @@ local function loadGeneralOptions() set = setColor, get = function(info) if( not ShadowUF.db.profile.bars.backgroundColor ) then - return {r = 0, g = 0, b = 0} + return 0, 0, 0 end return getColor(info) From 410dcebdb392bfc7e5168c1808c4c320acfde962 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 26 Oct 2022 00:21:16 +0200 Subject: [PATCH 055/108] Update TOC for 10.0 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 4800b07eb..864327f62 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 90207 +## Interface: 100000 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index ecab090f3..4ef99d5a7 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 90207 +## Interface: 100000 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 626cdee9e94fec20bb8303e69cf00fbd0a519c5b Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 2 Nov 2022 22:10:42 +0100 Subject: [PATCH 056/108] Check for expired fade before trying to set alpha This prevents an out of bound alpha value --- modules/indicators.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/indicators.lua b/modules/indicators.lua index a4533c3e4..75cf5f9ff 100755 --- a/modules/indicators.lua +++ b/modules/indicators.lua @@ -273,11 +273,12 @@ function Indicators:UpdateReadyCheck(frame, event) hasTimer = true f.fadeList[fadeFrame] = timeLeft - elapsed - fadeFrame:SetAlpha(f.fadeList[fadeFrame] / FADEOUT_TIME) if( f.fadeList[fadeFrame] <= 0 ) then f.fadeList[fadeFrame] = nil fadeFrame:Hide() + else + fadeFrame:SetAlpha(f.fadeList[fadeFrame] / FADEOUT_TIME) end end From 2cd1d74823bcc5546081de44e9eb05b58f890054 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sun, 6 Nov 2022 08:49:47 +0100 Subject: [PATCH 057/108] Remove unused function --- modules/indicators.lua | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/modules/indicators.lua b/modules/indicators.lua index 75cf5f9ff..5f19040d2 100755 --- a/modules/indicators.lua +++ b/modules/indicators.lua @@ -241,19 +241,6 @@ function Indicators:UpdateStatus(frame) end end --- Ready check fading once the check complete -local function fadeReadyStatus(self, elapsed) - self.timeLeft = self.timeLeft - elapsed - self.ready:SetAlpha(self.timeLeft / self.startTime) - - if( self.timeLeft <= 0 ) then - self:SetScript("OnUpdate", nil) - - self.ready.status = nil - self.ready:Hide() - end -end - local FADEOUT_TIME = 6 function Indicators:UpdateReadyCheck(frame, event) if( not frame.indicators.ready or not frame.indicators.ready.enabled ) then return end From d919e7f913fed86d97114ec16e59b277d7a6fc80 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sun, 6 Nov 2022 08:56:31 +0100 Subject: [PATCH 058/108] Add Evoker to the raid class filter --- modules/units.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/units.lua b/modules/units.lua index a4fd0f62e..6c1a4a98d 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -889,7 +889,7 @@ function Units:SetHeaderAttributes(frame, type) frame:SetAttribute("roleFilter", config.roleFilter) if( config.groupBy == "CLASS" ) then - frame:SetAttribute("groupingOrder", "DEATHKNIGHT,DEMONHUNTER,DRUID,HUNTER,MAGE,PALADIN,PRIEST,ROGUE,SHAMAN,WARLOCK,WARRIOR,MONK") + frame:SetAttribute("groupingOrder", "DEATHKNIGHT,DEMONHUNTER,DRUID,HUNTER,MAGE,PALADIN,PRIEST,ROGUE,SHAMAN,WARLOCK,WARRIOR,MONK,EVOKER") frame:SetAttribute("groupBy", "CLASS") elseif( config.groupBy == "ASSIGNEDROLE" ) then frame:SetAttribute("groupingOrder", "TANK,HEALER,DAMAGER,NONE") From 90b030704744fa2762c7ca9e72221b42b7f13fd9 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 16 Nov 2022 15:15:03 +0100 Subject: [PATCH 059/108] Update TOC for 10.0.2 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 864327f62..6b9b06748 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 100000 +## Interface: 100002 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 4ef99d5a7..07fc90ff2 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 100000 +## Interface: 100002 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 20739c22da259249b52bc41d912a7965692f2ebe Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sun, 12 Feb 2023 20:11:55 +0100 Subject: [PATCH 060/108] Add Evoker dispel support Based on data from Zaccin, thanks! --- modules/units.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/units.lua b/modules/units.lua index 6c1a4a98d..2e5be7f1d 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -1490,6 +1490,7 @@ local curableSpells = { ["MONK"] = {[115450] = {"Poison", "Disease", "Magic"}, [218164] = {"Poison", "Disease"}}, ["MAGE"] = {[475] = {"Curse"}}, ["WARLOCK"] = {[89808] = {"Magic"}}, + ["EVOKER"] = {[365585] = {"Poison"}, [360823] = {"Magic", "Poison"}, [374251] = {"Poison", "Curse", "Disease"}} } curableSpells = curableSpells[playerClass] @@ -1544,7 +1545,7 @@ centralFrame:SetScript("OnEvent", function(self, event, unit) end -- Monitor talent changes for curable changes - elseif( event == "PLAYER_SPECIALIZATION_CHANGED" or event == "UNIT_PET" ) then + elseif( event == "PLAYER_SPECIALIZATION_CHANGED" or event == "UNIT_PET" or event == "SPELLS_CHANGED") then checkCurableSpells() for frame in pairs(ShadowUF.Units.frameList) do @@ -1560,6 +1561,7 @@ centralFrame:SetScript("OnEvent", function(self, event, unit) elseif( event == "PLAYER_LOGIN" ) then checkCurableSpells() self:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED") + self:RegisterEvent("SPELLS_CHANGED") if( playerClass == "WARLOCK" ) then self:RegisterUnitEvent("UNIT_PET", "player", nil) end From 58d65021034dbf12721983394eff96d9377df652 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 22 Mar 2023 08:49:20 +0100 Subject: [PATCH 061/108] Update TOC for 10.0.7 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 6b9b06748..58c4314af 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 100002 +## Interface: 100007 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 07fc90ff2..4baf29a96 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 100002 +## Interface: 100007 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From a03ec2c8094cbd3e9fdf41e29deddc339a59055d Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 28 Apr 2023 14:02:01 +0200 Subject: [PATCH 062/108] PriestBarFrame has been removed in 10.1 --- ShadowedUnitFrames.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index c56dff46b..cb8ade132 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -774,7 +774,11 @@ function ShadowUF:HideBlizzardFrames() end if( self.db.profile.hidden.playerPower and not active_hiddens.playerPower ) then - basicHideBlizzardFrames(PriestBarFrame, RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame) + if PriestBarFrame then -- 10.1 removed the PriestBarFrame + basicHideBlizzardFrames(PriestBarFrame, RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame) + else + basicHideBlizzardFrames(RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame) + end end if( self.db.profile.hidden.pet and not active_hiddens.pet ) then From 11dd75bb0ad0a3360676757ee3f6764ceb7b2f74 Mon Sep 17 00:00:00 2001 From: Chris Johnson Date: Fri, 28 Apr 2023 14:06:36 +0200 Subject: [PATCH 063/108] Fix hiding of Arena Frames --- .luacheckrc | 5 +++-- ShadowedUnitFrames.lua | 7 ++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index db83326cc..36e125c32 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -142,8 +142,9 @@ read_globals = { "UnitXPMax", -- FrameXML frames - "ArenaEnemyFrames", - "ArenaPrepFrames", + "ArenaEnemyFramesContainer", + "ArenaEnemyPrepFramesContainer", + "ArenaEnemyMatchFramesContainer", "BuffFrame", "CastingBarFrame", "ComboFrame", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index cb8ade132..31c233897 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -804,13 +804,10 @@ function ShadowUF:HideBlizzardFrames() end end - if( self.db.profile.hidden.arena and not active_hiddens.arenaTriggered and IsAddOnLoaded("Blizzard_ArenaUI") and not InCombatLockdown() ) then + if( self.db.profile.hidden.arena and not active_hiddens.arenaTriggered ) then active_hiddens.arenaTriggered = true - ArenaEnemyFrames:UnregisterAllEvents() - ArenaEnemyFrames:SetParent(self.hiddenFrame) - ArenaPrepFrames:UnregisterAllEvents() - ArenaPrepFrames:SetParent(self.hiddenFrame) + hideBlizzardFrames(true, ArenaEnemyFramesContainer, ArenaEnemyPrepFramesContainer, ArenaEnemyMatchFramesContainer) end if( self.db.profile.hidden.playerAltPower and not active_hiddens.playerAltPower ) then From 892a2302b6ca898aa2f4c46bf65eb4017f023d13 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 3 May 2023 09:43:00 +0200 Subject: [PATCH 064/108] Update TOC for 10.1 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 58c4314af..a37723ea3 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 100007 +## Interface: 100100 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 4baf29a96..1b53a8ed7 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 100007 +## Interface: 100100 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From a7422e01803ec08eca270cf27f39b47dfa3c7ca8 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 3 May 2023 09:43:30 +0200 Subject: [PATCH 065/108] Remove compat --- ShadowedUnitFrames.lua | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 31c233897..858b34c34 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -774,11 +774,7 @@ function ShadowUF:HideBlizzardFrames() end if( self.db.profile.hidden.playerPower and not active_hiddens.playerPower ) then - if PriestBarFrame then -- 10.1 removed the PriestBarFrame - basicHideBlizzardFrames(PriestBarFrame, RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame) - else - basicHideBlizzardFrames(RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame) - end + basicHideBlizzardFrames(RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame) end if( self.db.profile.hidden.pet and not active_hiddens.pet ) then From ef52a81aad5028f527abaca2b2a42e331c90f9dc Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 13 May 2023 14:31:22 +0200 Subject: [PATCH 066/108] Clear old block points to avoid complications --- modules/basecombopoints.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/basecombopoints.lua b/modules/basecombopoints.lua index 8d7ca9466..b612ee745 100644 --- a/modules/basecombopoints.lua +++ b/modules/basecombopoints.lua @@ -111,6 +111,7 @@ function Combo:OnLayoutApplied(frame, config) if( pointsFrame.points ) then for _, texture in pairs(pointsFrame.points) do texture:Hide() + texture:ClearAllPoints() end end From 370f456530c14b9ee7f953d6a8943ccad2d26c8a Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 13 May 2023 14:32:02 +0200 Subject: [PATCH 067/108] Properly set limits on Essence Fixes client crashes caused by creating 50000 blocks --- modules/movers.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/movers.lua b/modules/movers.lua index f8f0f08fb..c90efef4a 100755 --- a/modules/movers.lua +++ b/modules/movers.lua @@ -42,7 +42,7 @@ local function createConfigEnv() end, UnitHealthMax = function(unit) return 50000 end, UnitPower = function(unit, powerType) - if( powerType == Enum.PowerType.HolyPower or powerType == Enum.PowerType.SoulShards ) then + if( powerType == Enum.PowerType.HolyPower or powerType == Enum.PowerType.SoulShards or powerType == Enum.PowerType.Essence ) then return 3 elseif( powerType == Enum.PowerType.Chi) then return 4 @@ -67,7 +67,7 @@ local function createConfigEnv() 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 + or powerType == Enum.PowerType.Chi or powerType == Enum.PowerType.Essence ) then return 5 elseif( powerType == Enum.PowerType.Runes ) then return 6 From 61bbea910d4adc8cd13cb3dfa21b16ff6d993be8 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 13 May 2023 14:32:33 +0200 Subject: [PATCH 068/108] Add Evoker essence frame to the hider --- .luacheckrc | 1 + ShadowedUnitFrames.lua | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.luacheckrc b/.luacheckrc index 36e125c32..35b2ca8f0 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -153,6 +153,7 @@ read_globals = { "CompactRaidFrameManager", "DebuffFrame", "DEFAULT_CHAT_FRAME", + "EssencePlayerFrame", "FocusFrame", "FocusFrameToT", "GameTooltip", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 858b34c34..37b1503d9 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -774,7 +774,7 @@ function ShadowUF:HideBlizzardFrames() end if( self.db.profile.hidden.playerPower and not active_hiddens.playerPower ) then - basicHideBlizzardFrames(RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame) + basicHideBlizzardFrames(RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame, EssencePlayerFrame) end if( self.db.profile.hidden.pet and not active_hiddens.pet ) then From 57aec2b11d3655572edcbaa94fece2fc71d16019 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 26 May 2023 12:50:25 +0200 Subject: [PATCH 069/108] Fix alternate mana bar hiding in 10.1.5 --- .luacheckrc | 1 + ShadowedUnitFrames.lua | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.luacheckrc b/.luacheckrc index 35b2ca8f0..8c5e4edeb 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -142,6 +142,7 @@ read_globals = { "UnitXPMax", -- FrameXML frames + "AlternatePowerBar", "ArenaEnemyFramesContainer", "ArenaEnemyPrepFramesContainer", "ArenaEnemyMatchFramesContainer", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 37b1503d9..8daa3d7b1 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -760,7 +760,8 @@ function ShadowUF:HideBlizzardFrames() end if( self.db.profile.hidden.player and not active_hiddens.player ) then - hideBlizzardFrames(false, PlayerFrame, PlayerFrameAlternateManaBar) + -- alternate bar renamed in 10.1.5 + hideBlizzardFrames(false, PlayerFrame, PlayerFrameAlternateManaBar or AlternatePowerBar) -- We keep these in case someone is still using the default auras, otherwise it messes up vehicle stuff PlayerFrame:RegisterEvent("PLAYER_ENTERING_WORLD") From d7f37ff720ec8c0ffdd2e761343fe0e33bf2dfd9 Mon Sep 17 00:00:00 2001 From: Nihus Date: Sun, 14 May 2023 13:07:34 +0200 Subject: [PATCH 070/108] Add Shaman Poison Cleansing Totem support --- modules/units.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/units.lua b/modules/units.lua index 2e5be7f1d..b5051e01c 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -1486,7 +1486,7 @@ local curableSpells = { ["DRUID"] = {[88423] = {"Magic", "Curse", "Poison"}, [2782] = {"Curse", "Poison"}}, ["PRIEST"] = {[527] = {"Magic", "Disease"}, [32375] = {"Magic"}, [213634] = {"Disease"}}, ["PALADIN"] = {[4987] = {"Poison", "Disease", "Magic"}, [213644] = {"Poison", "Disease"}}, - ["SHAMAN"] = {[77130] = {"Curse", "Magic"}, [51886] = {"Curse"}}, + ["SHAMAN"] = {[77130] = {"Curse", "Magic"}, [51886] = {"Curse"}, [383013] = {"Poison"}}, ["MONK"] = {[115450] = {"Poison", "Disease", "Magic"}, [218164] = {"Poison", "Disease"}}, ["MAGE"] = {[475] = {"Curse"}}, ["WARLOCK"] = {[89808] = {"Magic"}}, From daa6dda3d23e7949e967f880bed47274f34092c7 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 11 Jul 2023 16:24:39 +0200 Subject: [PATCH 071/108] Update TOC for 10.1.5 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index a37723ea3..c89e1b93e 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 100100 +## Interface: 100105 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 1b53a8ed7..379153d25 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 100100 +## Interface: 100105 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From d536645bb3b6c8d838739b98422694208231f02f Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 31 Aug 2023 15:59:08 +0200 Subject: [PATCH 072/108] Fix Ready Check indicator display --- .luacheckrc | 1 + modules/indicators.lua | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 8c5e4edeb..6251a1f05 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -225,4 +225,5 @@ read_globals = { "STAGGER_RED_TRANSITION", "STAGGER_YELLOW_TRANSITION", "STANDARD_TOTEM_PRIORITIES", + "TextureKitConstants", } diff --git a/modules/indicators.lua b/modules/indicators.lua index 5f19040d2..eacb08b72 100755 --- a/modules/indicators.lua +++ b/modules/indicators.lua @@ -279,7 +279,7 @@ function Indicators:UpdateReadyCheck(frame, event) -- Player never responded so they are AFK if( frame.indicators.ready.status == "waiting" ) then - frame.indicators.ready:SetTexture("Interface\\RaidFrame\\ReadyCheck-NotReady") + frame.indicators.ready:SetAtlas(READY_CHECK_NOT_READY_TEXTURE, TextureKitConstants.IgnoreAtlasSize) end return end @@ -293,11 +293,11 @@ function Indicators:UpdateReadyCheck(frame, event) end if( status == "ready" ) then - frame.indicators.ready:SetTexture(READY_CHECK_READY_TEXTURE) + frame.indicators.ready:SetAtlas(READY_CHECK_READY_TEXTURE, TextureKitConstants.IgnoreAtlasSize) elseif( status == "notready" ) then - frame.indicators.ready:SetTexture(READY_CHECK_NOT_READY_TEXTURE) + frame.indicators.ready:SetAtlas(READY_CHECK_NOT_READY_TEXTURE, TextureKitConstants.IgnoreAtlasSize) elseif( status == "waiting" ) then - frame.indicators.ready:SetTexture(READY_CHECK_WAITING_TEXTURE) + frame.indicators.ready:SetAtlas(READY_CHECK_WAITING_TEXTURE, TextureKitConstants.IgnoreAtlasSize) end frame.indicators:SetScript("OnUpdate", nil) From 59c3d38d48b0c13ffe90f54762e98e066e461e8b Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 17 Nov 2023 09:42:20 +0100 Subject: [PATCH 073/108] Remove CheckInteractDistance from range checker, as its protected now --- .luacheckrc | 1 - modules/range.lua | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 6251a1f05..e587abb57 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -45,7 +45,6 @@ read_globals = { "C_Timer", "CancelUnitBuff", "CanHearthAndResurrectFromArea", - "CheckInteractDistance", "CreateFrame", "GetArenaOpponentSpec", "GetBuildInfo", diff --git a/modules/range.lua b/modules/range.lua index 561960585..6ecc0a8af 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -75,9 +75,9 @@ local function checkRange(self) -- 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( 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 :( + -- Nope, just show in range :( else - frame:SetRangeAlpha(CheckInteractDistance(frame.unit, 1) and ShadowUF.db.profile.units[frame.unitType].range.inAlpha or ShadowUF.db.profile.units[frame.unitType].range.oorAlpha) + frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.inAlpha) end end From 24634b59eff380716ae3d3732cfc44b17ed80070 Mon Sep 17 00:00:00 2001 From: Eric Seastrand Date: Sat, 18 Nov 2023 01:57:08 -0600 Subject: [PATCH 074/108] Update STAGGER_STATES global for 10.2 10.2 added a new table-type global `STAGGER_STATES` to replace the old decimal variables like `STAGGER_RED_TRANSITION`. These are now undefined (causing lua errors + stagger bar color doesn't work). This commit updates SUF to get stagger thresholds in the [same way official UI code does](https://github.com/Gethe/wow-ui-source/blob/d4aa41ee5366c48fa8a04b9263afec45415c34d2/Interface/FrameXML/MonkStaggerBar.lua#L35). --- .luacheckrc | 3 +-- modules/monkstagger.lua | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index e587abb57..9a255e1c0 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -221,8 +221,7 @@ read_globals = { "SPEC_PALADIN_RETRIBUTION", "SPEC_PRIEST_SHADOW", "SPEC_WARLOCK_DESTRUCTION", - "STAGGER_RED_TRANSITION", - "STAGGER_YELLOW_TRANSITION", + "STAGGER_STATES", "STANDARD_TOTEM_PRIORITIES", "TextureKitConstants", } diff --git a/modules/monkstagger.lua b/modules/monkstagger.lua index 86c0e686d..19b034deb 100755 --- a/modules/monkstagger.lua +++ b/modules/monkstagger.lua @@ -41,9 +41,9 @@ function Stagger:Update(frame) -- Figure out how screwed they are local percent = stagger / frame.staggerBar.maxHealth local state - if( percent < STAGGER_YELLOW_TRANSITION ) then + if( percent < STAGGER_STATES.YELLOW.threshold ) then state = "STAGGER_GREEN" - elseif( percent < STAGGER_RED_TRANSITION ) then + elseif( percent < STAGGER_STATES.RED.threshold ) then state = "STAGGER_YELLOW" else state = "STAGGER_RED" From c745a18c6af2fd6f6e88013d2e56b25e506462cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Verseczi=20Tam=C3=A1s?= Date: Sat, 6 Jan 2024 15:26:33 +0100 Subject: [PATCH 075/108] Use high-quality class icon atlas --- .luacheckrc | 1 + modules/portrait.lua | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 9a255e1c0..0d3691690 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -181,6 +181,7 @@ read_globals = { "CombatFeedback_OnUpdate", "CompactRaidFrameManager_GetSetting", "CompactRaidFrameManager_SetSetting", + "GetClassAtlas", "RegisterStateDriver", "RegisterUnitWatch", "SecureButton_GetModifiedUnit", diff --git a/modules/portrait.lua b/modules/portrait.lua index 48af4ac83..9582e52c8 100755 --- a/modules/portrait.lua +++ b/modules/portrait.lua @@ -65,8 +65,12 @@ function Portrait:Update(frame, event) if( type == "class" ) then 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]) + local classIconAtlas = GetClassAtlas(classToken) + if( classIconAtlas ) then + frame.portrait:SetAtlas(classIconAtlas) + else + frame.portrait:SetTexture("") + end else frame.portrait:SetTexture("") end From b404b4d3ea9fa9e24c50e650a3018fba6fd29a37 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 23 Feb 2024 11:11:03 +0100 Subject: [PATCH 076/108] Update TOC --- ShadowedUnitFrames.toc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index c89e1b93e..49dfc0ccc 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 100105 +## Interface: 100205 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed From 70afa4f3e2c96d1e2f831596c2cc7880d4e5a663 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 23 Feb 2024 11:54:04 +0100 Subject: [PATCH 077/108] Switch PR CI to checkout v2 --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index ab585dbe0..cc60c7699 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Install and run Luacheck run: | sudo apt-get install luarocks From 088444aa09f858e98b308201f378dc2575fe165c Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 20 Mar 2024 08:32:55 +0100 Subject: [PATCH 078/108] Update TOCs for 10.2.6 --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 49dfc0ccc..49bcf13f2 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 100205 +## Interface: 100206 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 379153d25..5b199acd4 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 100105 +## Interface: 100206 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 19764362ad5b43a5dd89ebf26d6a02280b04c99e Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 27 Jun 2024 13:34:00 +0200 Subject: [PATCH 079/108] Remove defunct battleground zone filter --- options/config.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/options/config.lua b/options/config.lua index 91eff5b14..44c79c6da 100755 --- a/options/config.lua +++ b/options/config.lua @@ -5517,7 +5517,6 @@ local function loadFilterOptions() none = filterTable, pvp = filterTable, arena = filterTable, - battleground = filterTable, party = filterTable, raid = filterTable, } From b2814c7a1d0b2d62333280dc6ef312fd63c90be1 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 20 Jul 2024 09:22:10 +0200 Subject: [PATCH 080/108] GetSpellInfo API replacements --- .luacheckrc | 1 + modules/auraindicators.lua | 4 ++- modules/aurapoints.lua | 2 +- modules/range.lua | 53 +++++++++++++++++++------------------- modules/tags.lua | 18 +++++++------ options/config.lua | 33 ++++++++++++++---------- 6 files changed, 61 insertions(+), 50 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 0d3691690..cb3a27a54 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -42,6 +42,7 @@ read_globals = { -- API functions "C_IncomingSummon", + "C_Spell", "C_Timer", "CancelUnitBuff", "CanHearthAndResurrectFromArea", diff --git a/modules/auraindicators.lua b/modules/auraindicators.lua index b1e1499d2..d7b9c588a 100755 --- a/modules/auraindicators.lua +++ b/modules/auraindicators.lua @@ -3,6 +3,8 @@ ShadowUF:RegisterModule(Indicators, "auraIndicators", ShadowUF.L["Aura indicator Indicators.auraFilters = {"boss", "curable"} +local GetSpellTexture = C_Spell and C_Spell.GetSpellTexture or function(id) return (select(3, GetSpellInfo(id))) end + Indicators.auraConfig = setmetatable({}, { __index = function(tbl, index) local aura = ShadowUF.db.profile.auraIndicators.auras[tostring(index)] @@ -274,7 +276,7 @@ function Indicators:UpdateAuras(frame) indicator.showDuration = aura.duration indicator.spellDuration = 0 indicator.spellEnd = 0 - indicator.spellIcon = aura.iconTexture or select(3, GetSpellInfo(name)) + indicator.spellIcon = aura.iconTexture or GetSpellTexture(name) indicator.colorR = aura.r indicator.colorG = aura.g indicator.colorB = aura.b diff --git a/modules/aurapoints.lua b/modules/aurapoints.lua index ebfecc90d..fbda1df3e 100755 --- a/modules/aurapoints.lua +++ b/modules/aurapoints.lua @@ -1,7 +1,7 @@ local AuraPoints = setmetatable({ isComboPoints = true, spells = { - --["MAGE"] = {max = 4, name = GetSpellInfo(36032), filter = "HARMFUL"}, + --["MAGE"] = {max = 4, name = C_Spell.GetSpellName(36032), filter = "HARMFUL"}, } }, {__index = ShadowUF.ComboPoints}) diff --git a/modules/range.lua b/modules/range.lua index 6ecc0a8af..bba12d8eb 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -1,43 +1,44 @@ +local GetSpellName = C_Spell and C_Spell.GetSpellName or GetSpellInfo local Range = { friendly = { ["PRIEST"] = { - (GetSpellInfo(17)), -- Power Word: Shield - (GetSpellInfo(527)), -- Purify + (GetSpellName(17)), -- Power Word: Shield + (GetSpellName(527)), -- Purify }, ["DRUID"] = { - (GetSpellInfo(774)), -- Rejuvenation - (GetSpellInfo(2782)), -- Remove Corruption + (GetSpellName(774)), -- Rejuvenation + (GetSpellName(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 + ["PALADIN"] = GetSpellName(19750), -- Flash of Light + ["SHAMAN"] = GetSpellName(8004), -- Healing Surge + ["WARLOCK"] = GetSpellName(5697), -- Unending Breath + --["DEATHKNIGHT"] = GetSpellName(47541), -- Death Coil + ["MONK"] = GetSpellName(115450), -- Detox }, hostile = { ["DEATHKNIGHT"] = { - (GetSpellInfo(47541)), -- Death Coil - (GetSpellInfo(49576)), -- Death Grip + (GetSpellName(47541)), -- Death Coil + (GetSpellName(49576)), -- Death Grip }, - ["DEMONHUNTER"] = GetSpellInfo(185123), -- Throw Glaive - ["DRUID"] = GetSpellInfo(8921), -- Moonfire + ["DEMONHUNTER"] = GetSpellName(185123), -- Throw Glaive + ["DRUID"] = GetSpellName(8921), -- Moonfire ["HUNTER"] = { - (GetSpellInfo(193455)), -- Cobra Shot - (GetSpellInfo(19434)), -- Aimed Short - (GetSpellInfo(193265)), -- Hatchet Toss + (GetSpellName(193455)), -- Cobra Shot + (GetSpellName(19434)), -- Aimed Short + (GetSpellName(193265)), -- Hatchet Toss }, ["MAGE"] = { - (GetSpellInfo(116)), -- Frostbolt - (GetSpellInfo(30451)), -- Arcane Blast - (GetSpellInfo(133)), -- Fireball + (GetSpellName(116)), -- Frostbolt + (GetSpellName(30451)), -- Arcane Blast + (GetSpellName(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 + ["MONK"] = GetSpellName(115546), -- Provoke + ["PALADIN"] = GetSpellName(62124), -- Hand of Reckoning + ["PRIEST"] = GetSpellName(585), -- Smite + --["ROGUE"] = GetSpellName(1725), -- Distract + ["SHAMAN"] = GetSpellName(403), -- Lightning Bolt + ["WARLOCK"] = GetSpellName(686), -- Shadow Bolt + ["WARRIOR"] = GetSpellName(355), -- Taunt }, } diff --git a/modules/tags.lua b/modules/tags.lua index 2a9fc27ca..610807b23 100755 --- a/modules/tags.lua +++ b/modules/tags.lua @@ -1,3 +1,5 @@ +local GetSpellName = C_Spell and C_Spell.GetSpellName or GetSpellInfo + local Tags = {afkStatus = {}, offlineStatus = {}, customEvents = {}, powerMap = {}, moduleKey = "tags"} local tagPool, functionPool, temp, regFontStrings, powerMap = {}, {}, {}, {}, Tags.powerMap local L = ShadowUF.L @@ -380,14 +382,14 @@ end}) -- Going to have to start using an env wrapper for tags I think local Druid = {} -Druid.CatForm = GetSpellInfo(768) -Druid.MoonkinForm = GetSpellInfo(24858) -Druid.TravelForm = GetSpellInfo(783) -Druid.BearForm = GetSpellInfo(5487) -Druid.TreeForm = GetSpellInfo(33891) -Druid.AquaticForm = GetSpellInfo(1066) -Druid.SwiftFlightForm = GetSpellInfo(40120) -Druid.FlightForm = GetSpellInfo(33943) +Druid.CatForm = GetSpellName(768) +Druid.MoonkinForm = GetSpellName(24858) +Druid.TravelForm = GetSpellName(783) +Druid.BearForm = GetSpellName(5487) +Druid.TreeForm = GetSpellName(33891) +Druid.AquaticForm = GetSpellName(1066) +Druid.SwiftFlightForm = GetSpellName(40120) +Druid.FlightForm = GetSpellName(33943) ShadowUF.Druid = Druid Tags.defaultTags = { diff --git a/options/config.lua b/options/config.lua index 44c79c6da..a9a60c3bc 100755 --- a/options/config.lua +++ b/options/config.lua @@ -6,6 +6,9 @@ local L = ShadowUF.L ShadowUF.Config = Config +local GetSpellName = C_Spell and C_Spell.GetSpellName or GetSpellInfo +local GetSpellTexture = C_Spell and C_Spell.GetSpellTexture or function(id) return (select(3, GetSpellInfo(id))) end + --[[ The part that makes configuration a pain when you actually try is it gets unwieldly when you're adding special code to deal with showing help for certain cases, swapping tabs etc that makes it work smoothly. @@ -497,7 +500,7 @@ local function loadGeneralOptions() } local function validateSpell(info, spell) - if( spell and spell ~= "" and not GetSpellInfo(spell) ) then + if( spell and spell ~= "" and not GetSpellName(spell) ) then return string.format(L["Invalid spell \"%s\" entered."], spell or "") end @@ -520,7 +523,7 @@ local function loadGeneralOptions() text = L["Alternate Spell Name"] end - local icon = select(3, GetSpellInfo(name)) + local icon = GetSpellTexture(name) if( not icon ) then icon = "Interface\\Icons\\Inv_misc_questionmark" end @@ -5209,7 +5212,8 @@ local function loadFilterOptions() name = function(info) local name = spellMap[info[#(info)]] if tonumber(name) then - local spellName, _, icon = GetSpellInfo(name) + local spellName = GetSpellName(name) + local icon = GetSpellTexture(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 @@ -6437,7 +6441,7 @@ local function loadAuraIndicatorsOptions() for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do if( tonumber(name) ) then local spellID = name - name = GetSpellInfo(name) or L["Unknown"] + name = GetSpellName(name) or L["Unknown"] auraList[name] = string.format("%s (#%i)", name, spellID) else auraList[name] = name @@ -6514,11 +6518,11 @@ local function loadAuraIndicatorsOptions() type = "group", icon = function(info) local aura = auraMap[info[#(info)]] - return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil + return tonumber(aura) and (GetSpellTexture(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 + return tonumber(aura) and string.format("%s (#%i)", GetSpellName(aura) or "Unknown", aura) or aura end, hidden = function(info) local group = groupMap[info[#(info) - 1]] @@ -6893,11 +6897,11 @@ local function loadAuraIndicatorsOptions() type = "group", icon = function(info) local aura = auraMap[info[#(info)]] - return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil + return tonumber(aura) and (GetSpellTexture(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 + return tonumber(aura) and string.format("%s (#%i)", GetSpellName(aura) or "Unknown", aura) or aura end, args = {}, } @@ -6906,11 +6910,11 @@ local function loadAuraIndicatorsOptions() order = 1, icon = function(info) local aura = auraMap[info[#(info)]] - return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil + return tonumber(aura) and (GetSpellTexture(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 + return tonumber(aura) and string.format("%s (#%i)", GetSpellName(aura) or "Unknown", aura) or aura end, hidden = function(info) local aura = linkMap[info[#(info)]] @@ -7207,8 +7211,8 @@ local function loadAuraIndicatorsOptions() -- 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} + -- so will cheat it, and jump start it by storing the texture if we find it from GetSpellTexture directly + Indicators.auraConfig[addAura.name] = {indicator = "", group = group, iconTexture = GetSpellTexture(addAura.name), priority = 0, r = 0, g = 0, b = 0} writeAuraTable(addAura.name) auraID = auraID + 1 @@ -7436,13 +7440,14 @@ local function loadAuraIndicatorsOptions() type = "toggle", icon = function(info) local aura = auraMap[info[#(info)]] - return tonumber(aura) and (select(3, GetSpellInfo(aura))) or nil + return tonumber(aura) and (GetSpellTexture(aura)) or nil end, name = function(info) local aura = tonumber(auraMap[info[#(info)]]) if( not aura ) then return auraMap[info[#(info)]] end - local name, _, icon = GetSpellInfo(aura) + local name = GetSpellName(aura) + local icon = GetSpellTexture(aura) if( not name ) then return name end return "|T" .. icon .. ":18:18:0:0|t " .. name From ecde17f0cb9418a40589fb855078fc55cdb15859 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 20 Jul 2024 09:26:09 +0200 Subject: [PATCH 081/108] Update C_AddOns APIs --- .luacheckrc | 3 +-- ShadowedUnitFrames.lua | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index cb3a27a54..b929f8af7 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -41,6 +41,7 @@ read_globals = { "LibStub", -- API functions + "C_AddOns", "C_IncomingSummon", "C_Spell", "C_Timer", @@ -71,7 +72,6 @@ read_globals = { "GetXPExhaustion", "HasLFGRestrictions", "InCombatLockdown", - "IsAddOnLoaded", "IsEveryoneAssistant", "IsInInstance", "IsPlayerSpell", @@ -80,7 +80,6 @@ read_globals = { "IsSpellKnown", "IsUsableSpell", "IsXPUserDisabled", - "LoadAddOn", "UnitAffectingCombat", "UnitAura", "UnitBattlePetType", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 8daa3d7b1..202252cbd 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -581,7 +581,7 @@ end -- Module APIs 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 + if( key == "auraIndicators" and C_AddOns.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 @@ -915,7 +915,7 @@ SlashCmdList["SHADOWEDUF"] = function(msg) return end - local loaded, reason = LoadAddOn("ShadowedUF_Options") + local loaded, reason = C_AddOns.LoadAddOn("ShadowedUF_Options") if( not ShadowUF.Config ) then DEFAULT_CHAT_FRAME:AddMessage(string.format(L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"], reason and _G["ADDON_" .. reason] or "")) return From c7dc8deab5fdadf7871172c668f840b39cc7491e Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 20 Jul 2024 09:26:37 +0200 Subject: [PATCH 082/108] Update TOC --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index 49bcf13f2..ad899b64f 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 100206 +## Interface: 100207,110000,110002 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 5b199acd4..5a25a65d6 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 100206 +## Interface: 100207,110000,110002 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 903a6b23ce2bc5d27640e88f5bd581451fa30183 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 20 Jul 2024 11:13:30 +0200 Subject: [PATCH 083/108] Spell API updates for Range module --- modules/range.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/range.lua b/modules/range.lua index bba12d8eb..d77e8f4a7 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -1,4 +1,5 @@ local GetSpellName = C_Spell and C_Spell.GetSpellName or GetSpellInfo +local IsSpellUsable = C_Spell and C_Spell.IsSpellUsable or IsUsableSpell local Range = { friendly = { ["PRIEST"] = { @@ -36,7 +37,7 @@ local Range = { ["PALADIN"] = GetSpellName(62124), -- Hand of Reckoning ["PRIEST"] = GetSpellName(585), -- Smite --["ROGUE"] = GetSpellName(1725), -- Distract - ["SHAMAN"] = GetSpellName(403), -- Lightning Bolt + ["SHAMAN"] = GetSpellName(188196), -- Lightning Bolt ["WARLOCK"] = GetSpellName(686), -- Shadow Bolt ["WARRIOR"] = GetSpellName(355), -- Taunt }, @@ -84,22 +85,22 @@ end local function updateSpellCache(category) rangeSpells[category] = nil - if( IsUsableSpell(ShadowUF.db.profile.range[category .. playerClass]) ) then + if( ShadowUF.db.profile.range[category .. playerClass] and IsSpellUsable(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 + elseif( ShadowUF.db.profile.range[category .. "Alt" .. playerClass] and IsSpellUsable(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 + if( spell and IsSpellUsable(spell) ) then rangeSpells[category] = spell break end end - elseif( IsUsableSpell(Range[category][playerClass]) ) then + elseif( Range[category][playerClass] and IsSpellUsable(Range[category][playerClass]) ) then rangeSpells[category] = Range[category][playerClass] end end From 2bc7d27416ad4a2d7cc5e6813c8e5cec33a9ac9a Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 20 Jul 2024 11:13:51 +0200 Subject: [PATCH 084/108] Safety for UnitLevel --- modules/tags.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/tags.lua b/modules/tags.lua index 610807b23..518399a23 100755 --- a/modules/tags.lua +++ b/modules/tags.lua @@ -700,7 +700,7 @@ Tags.defaultTags = { return nil end - local level = UnitLevel(unit) + local level = UnitLevel(unit) or 0 if( level < 0 and UnitClassification(unit) == "worldboss" ) then return nil end @@ -722,7 +722,7 @@ Tags.defaultTags = { return UnitBattlePetLevel(unit) end - local level = UnitLevel(unit) + local level = UnitLevel(unit) or 0 return level > 0 and level or UnitClassification(unit) ~= "worldboss" and "??" or nil end]], ["maxhp"] = [[function(unit, unitOwner) return ShadowUF:FormatLargeNumber(UnitHealthMax(unit)) end]], From caf7b1c005370151531b4c1ba9cb55298c8fca61 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 20 Jul 2024 11:14:05 +0200 Subject: [PATCH 085/108] Update HideBlizzard for health bar changes --- ShadowedUnitFrames.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 202252cbd..4468a174d 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -708,7 +708,11 @@ function ShadowUF:HideBlizzardFrames() if( PartyFrame ) then hideBlizzardFrames(false, PartyFrame) for memberFrame in PartyFrame.PartyMemberFramePool:EnumerateActive() do - hideBlizzardFrames(false, memberFrame, memberFrame.HealthBar, memberFrame.ManaBar) + if memberFrame.HealthBarContainer and memberFrame.HealthBarContainer.HealthBar then + hideBlizzardFrames(false, memberFrame, memberFrame.HealthBarContainer.HealthBar, memberFrame.ManaBar) + else + hideBlizzardFrames(false, memberFrame, memberFrame.HealthBar, memberFrame.ManaBar) + end end PartyFrame.PartyMemberFramePool:ReleaseAll() else @@ -794,7 +798,11 @@ function ShadowUF:HideBlizzardFrames() for i=1, MAX_BOSS_FRAMES do local name = "Boss" .. i .. "TargetFrame" if _G[name].TargetFrameContent then - hideBlizzardFrames(false, _G[name], _G[name].TargetFrameContent.TargetFrameContentMain.HealthBar, _G[name].TargetFrameContent.TargetFrameContentMain.ManaBar) + if _G[name].TargetFrameContent.TargetFrameContentMain.HealthBarsContainer then + hideBlizzardFrames(false, _G[name], _G[name].TargetFrameContent.TargetFrameContentMain.HealthBarsContainer.HealthBar, _G[name].TargetFrameContent.TargetFrameContentMain.ManaBar) + else + hideBlizzardFrames(false, _G[name], _G[name].TargetFrameContent.TargetFrameContentMain.HealthBar, _G[name].TargetFrameContent.TargetFrameContentMain.ManaBar) + end else hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"]) end From b077157814908583530f5e68867abc31db0b43f0 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 20 Jul 2024 11:33:05 +0200 Subject: [PATCH 086/108] Update Aura API changes --- .luacheckrc | 3 ++- ShadowedUnitFrames.lua | 21 ++++++++++++++------- modules/auraindicators.lua | 2 +- modules/auras.lua | 2 +- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index b929f8af7..455656373 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -45,6 +45,7 @@ read_globals = { "C_IncomingSummon", "C_Spell", "C_Timer", + "C_UnitAuras", "CancelUnitBuff", "CanHearthAndResurrectFromArea", "CreateFrame", @@ -81,7 +82,6 @@ read_globals = { "IsUsableSpell", "IsXPUserDisabled", "UnitAffectingCombat", - "UnitAura", "UnitBattlePetType", "UnitCanAssist", "UnitCanAttack", @@ -176,6 +176,7 @@ read_globals = { "WarlockPowerFrame", -- FrameXML functions + "AuraUtil.UnpackAuraData", "BackdropTemplateMixin", "CombatFeedback_OnCombatEvent", "CombatFeedback_OnUpdate", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 4468a174d..40402e568 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -91,15 +91,22 @@ function ShadowUF:OnInitialize() 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) + local auraData + if type(spell) == "string" then + auraData = C_UnitAuras.GetAuraDataBySpellName(unit, spell, filter) + elseif type(spell) == "number" then + local index = 0 + while true do + index = index + 1 + local data = C_UnitAuras.GetAuraDataByIndex(unit, index, filter) + if not data then break end + if data.spellId == spell then + auraData = data + break + end end end + return AuraUtil.UnpackAuraData(auraData) end function ShadowUF:CheckBuild() diff --git a/modules/auraindicators.lua b/modules/auraindicators.lua index d7b9c588a..dffaa7e20 100755 --- a/modules/auraindicators.lua +++ b/modules/auraindicators.lua @@ -193,7 +193,7 @@ local function scanAuras(frame, filter, type) 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) + local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = AuraUtil.UnpackAuraData(C_UnitAuras.GetAuraDataByIndex(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) diff --git a/modules/auras.lua b/modules/auras.lua index ea90eaadc..89476411e 100755 --- a/modules/auras.lua +++ b/modules/auras.lua @@ -594,7 +594,7 @@ local function scan(parent, frame, type, config, displayConfig, filter) local index = 0 while( true ) do index = index + 1 - local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = UnitAura(frame.parent.unit, index, filter) + local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = AuraUtil.UnpackAuraData(C_UnitAuras.GetAuraDataByIndex(frame.parent.unit, index, filter)) if( not name ) then break end renderAura(parent, frame, type, config, displayConfig, index, filter, isFriendly, curable, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff) From 4c0ed7e0713aa4242ce9daa281764b0fc9db3916 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 20 Jul 2024 11:33:14 +0200 Subject: [PATCH 087/108] Safety check for valid spell being set --- options/config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/config.lua b/options/config.lua index a9a60c3bc..d5fb5d01d 100755 --- a/options/config.lua +++ b/options/config.lua @@ -523,7 +523,7 @@ local function loadGeneralOptions() text = L["Alternate Spell Name"] end - local icon = GetSpellTexture(name) + local icon = name and GetSpellTexture(name) if( not icon ) then icon = "Interface\\Icons\\Inv_misc_questionmark" end From 3936d7f6820d3e0f4ed749955cd9c4755949fbc9 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 15 Aug 2024 19:38:46 +0200 Subject: [PATCH 088/108] Update some more deprecated aura functions --- .luacheckrc | 1 - modules/health.lua | 2 +- modules/highlight.lua | 2 +- modules/tags.lua | 7 ++++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 455656373..6d9ed6fbd 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -90,7 +90,6 @@ read_globals = { "UnitClass", "UnitClassification", "UnitCreatureFamily", - "UnitDebuff", "UnitExists", "UnitFactionGroup", "UnitGetIncomingHeals", diff --git a/modules/health.lua b/modules/health.lua index 187e0641b..f9081cf59 100755 --- a/modules/health.lua +++ b/modules/health.lua @@ -62,7 +62,7 @@ function Health:UpdateAura(frame) local id = 0 while( true ) do id = id + 1 - local name, _, _, auraType = UnitDebuff(frame.unit, id) + local name, _, _, auraType = AuraUtil.UnpackAuraData(C_UnitAuras.GetDebuffDataByIndex(frame.unit, id)) if( not name ) then break end if( canCure[auraType] ) then diff --git a/modules/highlight.lua b/modules/highlight.lua index 637f46861..3fec3d62e 100755 --- a/modules/highlight.lua +++ b/modules/highlight.lua @@ -179,7 +179,7 @@ function Highlight:UpdateAura(frame) local id = 0 while( true ) do id = id + 1 - local name, _, _, auraType = UnitDebuff(frame.unit, id) + local name, _, _, auraType = AuraUtil.UnpackAuraData(C_UnitAuras.GetDebuffDataByIndex(frame.unit, id)) if( not name ) then break end if( auraType == "" ) then auraType = "Enrage" end diff --git a/modules/tags.lua b/modules/tags.lua index 518399a23..25ce37d61 100755 --- a/modules/tags.lua +++ b/modules/tags.lua @@ -1501,9 +1501,10 @@ local function loadAPIEvents() ["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", - ["UnitAura"] = "UNIT_AURA", - ["UnitBuff"] = "UNIT_AURA", - ["UnitDebuff"] = "UNIT_AURA", + ["GetAuraDataByIndex"] = "UNIT_AURA", + ["GetBuffDataByIndex"] = "UNIT_AURA", + ["GetDebuffDataByIndex"] = "UNIT_AURA", + ["UnitAuraBySpell"] = "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", From e6a045f165cc55c1ec6db1d82bc550f6dd2886d2 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 16 Aug 2024 10:25:58 +0200 Subject: [PATCH 089/108] Update for reputation API changes in the xp/rep bar module Replaces PR #58 --- .luacheckrc | 2 +- modules/xp.lua | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 6d9ed6fbd..0263bfa69 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -43,6 +43,7 @@ read_globals = { -- API functions "C_AddOns", "C_IncomingSummon", + "C_Reputation", "C_Spell", "C_Timer", "C_UnitAuras", @@ -68,7 +69,6 @@ read_globals = { "GetTime", "GetTotemInfo", "GetUnitPowerBarInfoByID", - "GetWatchedFactionInfo", "GetWeaponEnchantInfo", "GetXPExhaustion", "HasLFGRestrictions", diff --git a/modules/xp.lua b/modules/xp.lua index 7c7f8eadb..f7d569aed 100755 --- a/modules/xp.lua +++ b/modules/xp.lua @@ -86,20 +86,21 @@ end function XP:UpdateRep(frame) if( not frame.xpBar.rep ) then return end - local name, reaction, min, max, current = GetWatchedFactionInfo() - if( not name ) then + local factionData = C_Reputation.GetWatchedFactionData() + if( not factionData ) then frame.xpBar.rep:Hide() return end -- Blizzard stores faction info related to Exalted, not your current level, so get more mathier to find the current reputation using the current standing tier + local min, max, current = factionData.currentReactionThreshold, factionData.nextReactionThreshold, factionData.currentStanding current = math.abs(min - current) max = math.abs(min - max) - local color = FACTION_BAR_COLORS[reaction] + local color = FACTION_BAR_COLORS[factionData.reaction] frame.xpBar.rep:SetMinMaxValues(0, max) 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.tooltip = string.format(L["%s (%s): %s/%s (%.2f%% done)"], factionData.name, GetText("FACTION_STANDING_LABEL" .. tostring(factionData.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() From 4b6bc60aec3202b12fd6d68090a56144cc0db438 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 16 Aug 2024 10:29:51 +0200 Subject: [PATCH 090/108] Fix max player level condition --- .luacheckrc | 2 +- modules/movers.lua | 2 +- modules/xp.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 0263bfa69..1e20dcb51 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -56,6 +56,7 @@ read_globals = { "GetInventoryItemTexture", "GetLocale", "GetLootMethod", + "GetMaxLevelForPlayerExpansion", "GetNumArenaOpponentSpecs", "GetPartyAssignment", "GetPetExperience", @@ -205,7 +206,6 @@ read_globals = { "MAX_BOSS_FRAMES", "MAX_COMBO_POINTS", "MAX_PARTY_MEMBERS", - "MAX_PLAYER_LEVEL", "MAX_RAID_MEMBERS", "MAX_TOTEMS", "MEMBERS_PER_RAID_GROUP", diff --git a/modules/movers.lua b/modules/movers.lua index c90efef4a..f45333f94 100755 --- a/modules/movers.lua +++ b/modules/movers.lua @@ -27,7 +27,7 @@ local function createConfigEnv() UnitIsUnit = function(unitA, unitB) return unitB == "player" and true or false end, UnitIsDeadOrGhost = function(unit) return false end, UnitIsConnected = function(unit) return true end, - UnitLevel = function(unit) return MAX_PLAYER_LEVEL end, + UnitLevel = function(unit) return GetMaxLevelForPlayerExpansion() 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, diff --git a/modules/xp.lua b/modules/xp.lua index f7d569aed..0f625e31a 100755 --- a/modules/xp.lua +++ b/modules/xp.lua @@ -108,7 +108,7 @@ end function XP:UpdateXP(frame) -- At the level cap or XP is disabled, or the pet is actually a vehicle right now, swap to reputation bar (or hide it) - if( UnitLevel(frame.unitOwner) == MAX_PLAYER_LEVEL or IsXPUserDisabled() or ( frame.unitOwner == "pet" and UnitExists("vehicle") ) ) then + if( UnitLevel(frame.unitOwner) == GetMaxLevelForPlayerExpansion() or IsXPUserDisabled() or ( frame.unitOwner == "pet" and UnitExists("vehicle") ) ) then frame.xpBar.xp:Hide() return end From a0cd5d80bacc94a37b80c3d721925b76ece814ac Mon Sep 17 00:00:00 2001 From: Aldric Ducreux Date: Fri, 19 Apr 2024 02:45:44 +0200 Subject: [PATCH 091/108] Fix lua error mount/unmount vehicle --- modules/combopoints.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/combopoints.lua b/modules/combopoints.lua index 81cbd1787..a68a74153 100755 --- a/modules/combopoints.lua +++ b/modules/combopoints.lua @@ -24,7 +24,7 @@ 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") + local points = GetComboPoints("vehicle", "target") if( points == 0 ) then points = GetComboPoints("vehicle", "vehicle") end From 3ff5a92eab84549397c9a32a57da308c298c4403 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 16 Aug 2024 11:02:11 +0200 Subject: [PATCH 092/108] Cleanup uses of removed functions --- .luacheckrc | 9 --------- ShadowedUnitFrames.lua | 7 +++---- modules/auraindicators.lua | 2 +- modules/druid.lua | 2 +- modules/holypower.lua | 2 +- modules/priest.lua | 2 +- modules/range.lua | 4 ++-- modules/shaman.lua | 2 +- modules/tags.lua | 2 +- options/config.lua | 4 ++-- 10 files changed, 13 insertions(+), 23 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 1e20dcb51..e401a6ca3 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -65,7 +65,6 @@ read_globals = { "GetRuneCooldown", "GetSpecialization", "GetSpecializationInfoByID", - "GetSpellInfo", "GetText", "GetTime", "GetTotemInfo", @@ -80,7 +79,6 @@ read_globals = { "IsResting", "IsShiftKeyDown", "IsSpellKnown", - "IsUsableSpell", "IsXPUserDisabled", "UnitAffectingCombat", "UnitBattlePetType", @@ -104,7 +102,6 @@ read_globals = { "UnitHealth", "UnitHealthMax", "UnitInParty", - "UnitInPhase", "UnitInRaid", "UnitInRange", "UnitIsBattlePetCompanion", @@ -146,7 +143,6 @@ read_globals = { "ArenaEnemyPrepFramesContainer", "ArenaEnemyMatchFramesContainer", "BuffFrame", - "CastingBarFrame", "ComboFrame", "CompactPartyFrame", "CompactRaidFrameContainer", @@ -165,13 +161,10 @@ read_globals = { "PetFrame", "PlayerCastingBarFrame", "PlayerFrame", - "PlayerFrameAlternateManaBar", "PlayerPowerBarAlt", - "PriestBarFrame", "RuneFrame", "TargetFrame", "TargetFrameToT", - "TemporaryEnchantFrame", "UIParent", "WarlockPowerFrame", @@ -197,7 +190,6 @@ read_globals = { "DebuffTypeColor", "Enum", "PowerBarColor", - "ADDITIONAL_POWER_BAR_INDEX", "ALTERNATE_POWER_INDEX", "CLASS_ICON_TCOORDS", "CLASS_SORT_ORDER", @@ -209,7 +201,6 @@ read_globals = { "MAX_RAID_MEMBERS", "MAX_TOTEMS", "MEMBERS_PER_RAID_GROUP", - "PALADINPOWERBAR_SHOW_LEVEL", "PET_TYPE_SUFFIX", "RAID_CLASS_COLORS", "READY_CHECK_NOT_READY_TEXTURE", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 40402e568..472211493 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -708,7 +708,7 @@ end local active_hiddens = {} function ShadowUF:HideBlizzardFrames() if( self.db.profile.hidden.cast and not active_hiddens.cast ) then - hideBlizzardFrames(true, PlayerCastingBarFrame or CastingBarFrame, PetCastingBarFrame) + hideBlizzardFrames(true, PlayerCastingBarFrame, PetCastingBarFrame) end if( self.db.profile.hidden.party and not active_hiddens.party ) then @@ -767,12 +767,11 @@ function ShadowUF:HideBlizzardFrames() end if( self.db.profile.hidden.buffs and not active_hiddens.buffs ) then - hideBlizzardFrames(false, BuffFrame, TemporaryEnchantFrame or DebuffFrame) + hideBlizzardFrames(false, BuffFrame, DebuffFrame) end if( self.db.profile.hidden.player and not active_hiddens.player ) then - -- alternate bar renamed in 10.1.5 - hideBlizzardFrames(false, PlayerFrame, PlayerFrameAlternateManaBar or AlternatePowerBar) + hideBlizzardFrames(false, PlayerFrame, AlternatePowerBar) -- We keep these in case someone is still using the default auras, otherwise it messes up vehicle stuff PlayerFrame:RegisterEvent("PLAYER_ENTERING_WORLD") diff --git a/modules/auraindicators.lua b/modules/auraindicators.lua index dffaa7e20..251523eff 100755 --- a/modules/auraindicators.lua +++ b/modules/auraindicators.lua @@ -3,7 +3,7 @@ ShadowUF:RegisterModule(Indicators, "auraIndicators", ShadowUF.L["Aura indicator Indicators.auraFilters = {"boss", "curable"} -local GetSpellTexture = C_Spell and C_Spell.GetSpellTexture or function(id) return (select(3, GetSpellInfo(id))) end +local GetSpellTexture = C_Spell.GetSpellTexture Indicators.auraConfig = setmetatable({}, { __index = function(tbl, index) diff --git a/modules/druid.lua b/modules/druid.lua index e08270ef2..51d0c1998 100755 --- a/modules/druid.lua +++ b/modules/druid.lua @@ -22,7 +22,7 @@ function Druid:OnLayoutApplied(frame) end function Druid:PowerChanged(frame) - local visible = UnitPowerType(frame.unit) ~= ADDITIONAL_POWER_BAR_INDEX and not frame.inVehicle + local visible = UnitPowerType(frame.unit) ~= Enum.PowerType.Mana and not frame.inVehicle local type = visible and "RegisterUnitEvent" or "UnregisterSingleEvent" frame[type](frame, "UNIT_POWER_FREQUENT", self, "Update") diff --git a/modules/holypower.lua b/modules/holypower.lua index 4c8f4edd6..65870909d 100755 --- a/modules/holypower.lua +++ b/modules/holypower.lua @@ -1,7 +1,7 @@ if( not ShadowUF.ComboPoints ) then return end local HolyPower = setmetatable({}, {__index = ShadowUF.ComboPoints}) -ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN", nil, PALADINPOWERBAR_SHOW_LEVEL) +ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN") 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) diff --git a/modules/priest.lua b/modules/priest.lua index 95d4ed710..038ea2641 100644 --- a/modules/priest.lua +++ b/modules/priest.lua @@ -22,7 +22,7 @@ function Priest:OnLayoutApplied(frame) end function Priest:PowerChanged(frame) - local visible = UnitPowerType(frame.unit) ~= ADDITIONAL_POWER_BAR_INDEX and not frame.inVehicle + local visible = UnitPowerType(frame.unit) ~= Enum.PowerType.Mana and not frame.inVehicle local type = visible and "RegisterUnitEvent" or "UnregisterSingleEvent" frame[type](frame, "UNIT_POWER_FREQUENT", self, "Update") diff --git a/modules/range.lua b/modules/range.lua index d77e8f4a7..b00b8f6e2 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -1,5 +1,5 @@ -local GetSpellName = C_Spell and C_Spell.GetSpellName or GetSpellInfo -local IsSpellUsable = C_Spell and C_Spell.IsSpellUsable or IsUsableSpell +local GetSpellName = C_Spell.GetSpellName +local IsSpellUsable = C_Spell.IsSpellUsable local Range = { friendly = { ["PRIEST"] = { diff --git a/modules/shaman.lua b/modules/shaman.lua index 15cdb5293..f2b5071f9 100644 --- a/modules/shaman.lua +++ b/modules/shaman.lua @@ -22,7 +22,7 @@ function Shaman:OnLayoutApplied(frame) end function Shaman:PowerChanged(frame) - local visible = UnitPowerType(frame.unit) ~= ADDITIONAL_POWER_BAR_INDEX and not frame.inVehicle + local visible = UnitPowerType(frame.unit) ~= Enum.PowerType.Mana and not frame.inVehicle local type = visible and "RegisterUnitEvent" or "UnregisterSingleEvent" frame[type](frame, "UNIT_POWER_FREQUENT", self, "Update") diff --git a/modules/tags.lua b/modules/tags.lua index 25ce37d61..a6fed25ff 100755 --- a/modules/tags.lua +++ b/modules/tags.lua @@ -1,4 +1,4 @@ -local GetSpellName = C_Spell and C_Spell.GetSpellName or GetSpellInfo +local GetSpellName = C_Spell.GetSpellName local Tags = {afkStatus = {}, offlineStatus = {}, customEvents = {}, powerMap = {}, moduleKey = "tags"} local tagPool, functionPool, temp, regFontStrings, powerMap = {}, {}, {}, {}, Tags.powerMap diff --git a/options/config.lua b/options/config.lua index d5fb5d01d..8f16c6195 100755 --- a/options/config.lua +++ b/options/config.lua @@ -6,8 +6,8 @@ local L = ShadowUF.L ShadowUF.Config = Config -local GetSpellName = C_Spell and C_Spell.GetSpellName or GetSpellInfo -local GetSpellTexture = C_Spell and C_Spell.GetSpellTexture or function(id) return (select(3, GetSpellInfo(id))) end +local GetSpellName = C_Spell.GetSpellName +local GetSpellTexture = C_Spell.GetSpellTexture --[[ The part that makes configuration a pain when you actually try is it gets unwieldly when you're adding special code to deal with From 227b61844c0eed42b340ddca55bca4cebbded00f Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 16 Oct 2024 07:54:16 +0200 Subject: [PATCH 093/108] Add support for BigWigs Spell Renames --- .luacheckrc | 1 + ShadowedUnitFrames.lua | 1 + modules/cast.lua | 5 +++++ options/config.lua | 8 ++++++++ 4 files changed, 15 insertions(+) diff --git a/.luacheckrc b/.luacheckrc index e401a6ca3..d7c49069b 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -39,6 +39,7 @@ read_globals = { -- misc custom, third party libraries "ClickCastHeader", "LibStub", + "BigWigsAPI", -- API functions "C_AddOns", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 472211493..98a20aa89 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -32,6 +32,7 @@ function ShadowUF:OnInitialize() locked = false, advanced = false, tooltipCombat = false, + bossmodSpellRename = true, omnicc = false, blizzardcc = true, tags = {}, diff --git a/modules/cast.lua b/modules/cast.lua index f15256b76..56ee5c1fa 100755 --- a/modules/cast.lua +++ b/modules/cast.lua @@ -436,6 +436,11 @@ function Cast:UpdateCast(frame, unit, channelled, spell, displayName, icon, star frame.castBar.icon:Show() end + -- BigWigs Spell Name Override + if (BigWigsAPI and BigWigsAPI.GetSpellRename and ShadowUF.db.profile.bossmodSpellRename and spellID) then + spell = BigWigsAPI.GetSpellRename(spellID) or spell + end + -- Setup cast info cast.isChannelled = channelled cast.startTime = startTime / 1000 diff --git a/options/config.lua b/options/config.lua index 8f16c6195..70e5a43a0 100755 --- a/options/config.lua +++ b/options/config.lua @@ -751,6 +751,14 @@ local function loadGeneralOptions() arg = "tooltipCombat", width = "double", }, + bossmodCastNames = { + order = 3.1, + type = "toggle", + name = L["Use Boss Mod Cast Name overrides"], + desc = L["Use spell name overrides provided by boss mods (BigWigs) on the cast bars."], + arg = "bossmodSpellRename", + width = "double", + }, sep2 = { order = 3.5, type = "description", From 2ea63ae60087a25a24128da7935d83ee1d4ac96d Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 16 Oct 2024 07:54:47 +0200 Subject: [PATCH 094/108] Specify ubuntu-22.04 as the running image, as latest lacks subversion --- .github/workflows/packager.yml | 2 +- .github/workflows/pull_request.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/packager.yml b/.github/workflows/packager.yml index 0eb13e7b5..f19ca09d7 100644 --- a/.github/workflows/packager.yml +++ b/.github/workflows/packager.yml @@ -16,7 +16,7 @@ jobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index cc60c7699..e8593bfe5 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -9,7 +9,7 @@ jobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 From 77bd580c9a58ab07f38eab6bc0368f2c0d8e92c6 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 16 Oct 2024 07:58:49 +0200 Subject: [PATCH 095/108] Update TOC for future releases --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index ad899b64f..f3d0884c8 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 100207,110000,110002 +## Interface: 110002,110005 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 5a25a65d6..1cbc6e3da 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 100207,110000,110002 +## Interface: 110002,110005 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From c5d4d8bcd7219c480bb1d38cb9a82b06923246d7 Mon Sep 17 00:00:00 2001 From: Max Burov Date: Sat, 24 Aug 2024 15:13:15 +0200 Subject: [PATCH 096/108] Hide BossTargetFrameContainer to avoid errors in EditMode --- .luacheckrc | 1 + ShadowedUnitFrames.lua | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.luacheckrc b/.luacheckrc index d7c49069b..b2d7ee895 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -143,6 +143,7 @@ read_globals = { "ArenaEnemyFramesContainer", "ArenaEnemyPrepFramesContainer", "ArenaEnemyMatchFramesContainer", + "BossTargetFrameContainer", "BuffFrame", "ComboFrame", "CompactPartyFrame", diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index 98a20aa89..ff3b32a81 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -802,6 +802,8 @@ function ShadowUF:HideBlizzardFrames() end if( self.db.profile.hidden.boss and not active_hiddens.boss ) then + hideBlizzardFrames(false, BossTargetFrameContainer) + for i=1, MAX_BOSS_FRAMES do local name = "Boss" .. i .. "TargetFrame" if _G[name].TargetFrameContent then From 0b33188ba4803b32ccc2d43c2c11f350e1817ed8 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 18 Jul 2025 10:00:14 +0200 Subject: [PATCH 097/108] Add Ping support to the unit frames --- modules/units.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/units.lua b/modules/units.lua index b5051e01c..9e9da07e3 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -642,7 +642,7 @@ local secureInitializeUnit = [[ end ]] -local unitButtonTemplate = ClickCastHeader and (BackdropTemplateMixin and "ClickCastUnitTemplate,SUF_SecureUnitTemplate,BackdropTemplate" or "ClickCastUnitTemplate,SUF_SecureUnitTemplate") or (BackdropTemplateMixin and "SUF_SecureUnitTemplate,BackdropTemplate" or "SUF_SecureUnitTemplate") +local unitButtonTemplate = ClickCastHeader and ("ClickCastUnitTemplate,SUF_SecureUnitTemplate,PingableUnitFrameTemplate,BackdropTemplate") or ("SUF_SecureUnitTemplate,PingableUnitFrameTemplate,BackdropTemplate") -- Header unit initialized local function initializeUnit(header, frameName) @@ -960,7 +960,7 @@ function Units:LoadUnit(unit) return end - local frame = self:CreateUnit("Button", "SUFUnit" .. unit, petBattleFrame, BackdropTemplateMixin and "SecureUnitButtonTemplate,BackdropTemplate" or "SecureUnitButtonTemplate") + local frame = self:CreateUnit("Button", "SUFUnit" .. unit, petBattleFrame, "SecureUnitButtonTemplate,PingableUnitFrameTemplate,BackdropTemplate") frame:SetAttribute("unit", unit) frame.hasStateWatch = unit == "pet" @@ -1188,7 +1188,7 @@ function Units:LoadZoneHeader(type) end for id, unit in pairs(ShadowUF[type .. "Units"]) do - local frame = self:CreateUnit("Button", "SUFHeader" .. type .. "UnitButton" .. id, headerFrame, BackdropTemplateMixin and "SecureUnitButtonTemplate,BackdropTemplate" or "SecureUnitButtonTemplate") + local frame = self:CreateUnit("Button", "SUFHeader" .. type .. "UnitButton" .. id, headerFrame, "SecureUnitButtonTemplate,PingableUnitFrameTemplate,BackdropTemplate") frame.ignoreAnchor = true frame.hasStateWatch = true frame.unitUnmapped = type .. id @@ -1304,7 +1304,7 @@ function Units:LoadChildUnit(parent, type, id) end -- Now we can create the actual frame - local frame = self:CreateUnit("Button", "SUFChild" .. type .. string.match(parent:GetName(), "(%d+)"), parent, BackdropTemplateMixin and "SecureUnitButtonTemplate,BackdropTemplate" or "SecureUnitButtonTemplate") + local frame = self:CreateUnit("Button", "SUFChild" .. type .. string.match(parent:GetName(), "(%d+)"), parent, "SecureUnitButtonTemplate,PingableUnitFrameTemplate,BackdropTemplate") frame.unitType = type frame.parent = parent frame.isChildUnit = true From ac6205c90479807052c5df78e5b9cb5416a934f1 Mon Sep 17 00:00:00 2001 From: R-Pete-G Date: Mon, 24 Feb 2025 10:54:53 +0000 Subject: [PATCH 098/108] feat: adding "Category" as per 11.1 addon changes --- ShadowedUnitFrames.toc | 1 + options/ShadowedUF_Options.toc | 1 + 2 files changed, 2 insertions(+) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index f3d0884c8..b1c57580b 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -8,6 +8,7 @@ ## OptionalDeps: Ace3, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibDualSpec-1.0, LibSpellRange-1.0, UTF8, Clique ## X-Curse-Project-ID: 19268 ## X-WoWI-ID: 13494 +## Category: ShadowedUnitFrames #@no-lib-strip@ libs\LibStub\LibStub.lua diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 1cbc6e3da..fe7f00e50 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -4,6 +4,7 @@ ## Author: Shadowed ## LoadOnDemand: true ## Dependencies: ShadowedUnitFrames +## Category: ShadowedUnitFrames #@no-lib-strip@ libs\AceDBOptions-3.0\AceDBOptions-3.0.xml From c811cf7e53a68cb359ba598adb8f010fb60299a2 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 18 Jul 2025 10:08:01 +0200 Subject: [PATCH 099/108] Update TOC --- ShadowedUnitFrames.toc | 2 +- options/ShadowedUF_Options.toc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index b1c57580b..ceeec4a37 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,4 +1,4 @@ -## Interface: 110002,110005 +## Interface: 110107 ## Title: Shadowed Unit Frames ## Notes: Moooooooooooooooooo ## Author: Shadowed diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index fe7f00e50..120cd18be 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,4 +1,4 @@ -## Interface: 110002,110005 +## Interface: 110107 ## Title: Shadowed UF (Options) ## Notes: Configuration for Shadowed Unit Frames. ## Author: Shadowed From 0ff79dc4e42876f4bb092db48fd4552a9c27326e Mon Sep 17 00:00:00 2001 From: Hyphie <31455641+Hyphie24@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:42:52 -0400 Subject: [PATCH 100/108] Add AI Class colors to UnitFrame --- modules/health.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/health.lua b/modules/health.lua index f9081cf59..48c7ceeba 100755 --- a/modules/health.lua +++ b/modules/health.lua @@ -115,7 +115,7 @@ 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 unit == "pet") ) then + elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "class" and (UnitIsPlayer(unit) or UnitInPartyIsAI(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 From 319eeeab207280f2979011344087fef612588454 Mon Sep 17 00:00:00 2001 From: Hyphie <31455641+Hyphie24@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:59:22 -0400 Subject: [PATCH 101/108] Mists Sync From SUF-Mists repo --- ExternalAPI.lua | 18 + ShadowedUnitFrames.lua | 2170 +++-- ShadowedUnitFrames.toc | 152 +- ShadowedUnitFrames.xml | 16 +- localization/deDE.lua | 914 +- localization/enUS.lua | 998 +- localization/esES.lua | 478 +- localization/esMX.lua | 301 +- localization/frFR.lua | 951 +- localization/koKR.lua | 945 +- localization/ptBR.lua | 2057 ++++- localization/ruRU.lua | 744 +- localization/zhCN.lua | 948 +- localization/zhTW.lua | 950 +- modules/altpower.lua | 110 +- modules/arcanecharges.lua | 62 +- modules/auraindicators.lua | 578 +- modules/aurapoints.lua | 58 +- modules/auras.lua | 1342 +-- modules/basecombopoints.lua | 408 +- modules/burningembers.lua | 119 + modules/cast.lua | 966 +- modules/chi.lua | 56 +- modules/combattext.lua | 98 +- modules/combopoints.lua | 84 +- modules/defaultlayout.lua | 1946 ++-- modules/demonicfury.lua | 34 + modules/druid.lua | 78 +- modules/eclipse.lua | 76 + modules/empty.lua | 124 +- modules/essence.lua | 62 +- modules/fader.lua | 324 +- modules/healabsorb.lua | 36 +- modules/health.lua | 340 +- modules/helpers.lua | 66 +- modules/highlight.lua | 388 +- modules/holypower.lua | 62 +- modules/incabsorb.lua | 98 +- modules/incheal.lua | 292 +- modules/indicators.lua | 993 +- modules/layout.lua | 1218 +-- modules/monk.lua | 28 + modules/monkstagger.lua | 108 +- modules/movers.lua | 1126 +-- modules/portrait.lua | 200 +- modules/power.lua | 204 +- modules/priest.lua | 78 +- modules/range.lua | 319 +- modules/runes.lua | 226 +- modules/shadoworbs.lua | 32 + modules/shaman.lua | 78 +- modules/soulshards.lua | 95 +- modules/tags.lua | 3306 +++---- modules/totems.lua | 420 +- modules/units.lua | 3174 +++---- modules/xp.lua | 323 +- options/ShadowedUF_Options.toc | 31 +- options/config.lua | 15321 ++++++++++++++++--------------- 58 files changed, 28335 insertions(+), 18394 deletions(-) create mode 100644 ExternalAPI.lua create mode 100644 modules/burningembers.lua create mode 100644 modules/demonicfury.lua create mode 100644 modules/eclipse.lua create mode 100644 modules/monk.lua create mode 100644 modules/shadoworbs.lua diff --git a/ExternalAPI.lua b/ExternalAPI.lua new file mode 100644 index 000000000..95a73ebe4 --- /dev/null +++ b/ExternalAPI.lua @@ -0,0 +1,18 @@ +--[[ + API overrides from external addons that augment the data missing in the Classic API +]] +ShadowUF = select(2, ...) +ShadowUF.API = {} + +-- Threat colors +function ShadowUF.API.GetThreatStatusColor(state) + if( state == 3 ) then + return 1, 0, 0 + elseif( state == 2 ) then + return 1, 0.6, 0 + elseif( state == 1 ) then + return 1, 1, 0.47 + else + return 0.69, 0.69, 0.69 + end +end diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua index ff3b32a81..98be50c18 100755 --- a/ShadowedUnitFrames.lua +++ b/ShadowedUnitFrames.lua @@ -1,954 +1,1216 @@ ---[[ - Shadowed Unit Frames, Shadowed of Mal'Ganis (US) PvP -]] - -ShadowUF = select(2, ...) - -local L = ShadowUF.L -ShadowUF.dbRevision = 63 -ShadowUF.playerUnit = "player" -ShadowUF.enabledUnits = {} -ShadowUF.modules = {} -ShadowUF.moduleOrder = {} -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.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 = { - profile = { - locked = false, - advanced = false, - tooltipCombat = false, - bossmodSpellRename = true, - omnicc = false, - blizzardcc = true, - tags = {}, - units = {}, - positions = {}, - range = {}, - filters = {zonewhite = {}, zoneblack = {}, zoneoverride = {}, whitelists = {}, blacklists = {}, overridelists = {}}, - visibility = {arena = {}, pvp = {}, party = {}, raid = {}}, - 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) - if( not ShadowUF.Tags.defaultTags[index] and not ShadowUF.db.profile.tags[index] ) then - tbl[index] = false - return false - end - - local func, msg = loadstring("return " .. (ShadowUF.Tags.defaultTags[index] or ShadowUF.db.profile.tags[index].func or "")) - if( func ) then - func = func() - elseif( msg ) then - error(msg, 3) - end - - tbl[index] = func - return tbl[index] - end}) - - if( not self.db.profile.loadedLayout ) then - 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 auraData - if type(spell) == "string" then - auraData = C_UnitAuras.GetAuraDataBySpellName(unit, spell, filter) - elseif type(spell) == "number" then - local index = 0 - while true do - index = index + 1 - local data = C_UnitAuras.GetAuraDataByIndex(unit, index, filter) - if not data then break end - if data.spellId == spell then - auraData = data - break - end - end - end - return AuraUtil.UnpackAuraData(auraData) -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() - local revision = self.db.profile.revision or self.dbRevision - if (revision <= 62 ) then - -- evoker setup - self.db.profile.classColors.EVOKER = {r = 0.20, g = 0.58, b = 0.50} - self.db.profile.powerColors.ESSENCE = {r = 0.40, g = 0.80, b = 1.00} - self.db.profile.units.player.essence = {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} - end - if (revision <= 61 ) then - if self.db.profile.bars.texture == "Smooth" then - self.db.profile.bars.texture = "Smoother" - end - end - if (revision <= 60 ) then - for unit, config in pairs(self.db.profile.units) do - if( unit == "player" or unit == "party" or unit == "target" or unit == "raid" or unit == "focus" or unit == "mainassist" or unit == "maintank" ) then - config.indicators.sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"} - end - end - end - if (revision <= 59 ) then - self.db.profile.font.shadowX = 1.0 - self.db.profile.font.shadowY = -1.0 - end - if( revision <= 58 ) then - for unit, config in pairs(self.db.profile.units) do - 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 - - 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 - - if( revision <= 49 ) then - ShadowUF:LoadDefaultLayout(true) - end - - if( revision <= 49 ) then - if( ShadowUF.db.profile.font.extra == "MONOCHROME" ) then - ShadowUF.db.profile.font.extra = "" - end - 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] ) 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 - elseif( self.db.profile.visibility[instanceType][type] == true ) then - enabled = true - end - end - - self.enabledUnits[type] = enabled - - if( enabled ) then - self.Units:InitializeFrame(type) - else - self.Units:UninitializeFrame(type) - end - end -end - -function ShadowUF:LoadUnitDefaults() - for _, unit in pairs(self.unitList) do - self.defaults.profile.positions[unit] = {point = "", relativePoint = "", anchorPoint = "", anchorTo = "UIParent", x = 0, y = 0} - - -- The reason why the defaults are so sparse, is because the layout needs to specify most of this. The reason I set tables here is basically - -- as an indication that hey, the unit wants this, if it doesn't that it won't want it. - self.defaults.profile.units[unit] = { - enabled = false, height = 0, width = 0, scale = 1.0, - healthBar = {enabled = true}, - powerBar = {enabled = true}, - emptyBar = {enabled = false}, - portrait = {enabled = false}, - castBar = {enabled = false, name = {}, time = {}}, - text = { - {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, 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 ~= "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 - - if( unit ~= "player" ) then - self.defaults.profile.units[unit].range = {enabled = false, oorAlpha = 0.80, inAlpha = 1.0} - - if( not string.match(unit, "pet") ) then - self.defaults.profile.units[unit].indicators.class = {enabled = false, size = 19} - end - end - - 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} - self.defaults.profile.units[unit].indicators.sumPending = {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 - self.defaults.profile.units.player.powerBar.predicted = true - self.defaults.profile.units.player.indicators.status.enabled = true - 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} - 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} - self.defaults.profile.units.player.auraPoints = {enabled = false, isBar = true} - self.defaults.profile.units.player.essence = {enabled = true, 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.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60} - self.defaults.profile.units.pet.xpBar = {enabled = false} - -- 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.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 - -- PARTY - self.defaults.profile.units.party.enabled = true - self.defaults.profile.units.party.auras.debuffs.maxRows = 1 - self.defaults.profile.units.party.auras.buffs.maxRows = 1 - 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" - self.defaults.profile.units.arena.attribAnchorPoint = "LEFT" - 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" - self.defaults.profile.units.boss.attribAnchorPoint = "LEFT" - 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" - self.defaults.profile.units.raid.sortMethod = "INDEX" - self.defaults.profile.units.raid.attribPoint = "TOP" - self.defaults.profile.units.raid.attribAnchorPoint = "RIGHT" - self.defaults.profile.units.raid.offset = 0 - 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" - self.defaults.profile.units.raidpet.sortMethod = "INDEX" - self.defaults.profile.units.raidpet.attribPoint = "TOP" - self.defaults.profile.units.raidpet.attribAnchorPoint = "RIGHT" - self.defaults.profile.units.raidpet.offset = 0 - self.defaults.profile.units.raidpet.filters = {[1] = true, [2] = true, [3] = true, [4] = true, [5] = true, [6] = true, [7] = true, [8] = true} - 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" - self.defaults.profile.units.maintank.sortMethod = "INDEX" - self.defaults.profile.units.maintank.attribPoint = "TOP" - self.defaults.profile.units.maintank.attribAnchorPoint = "RIGHT" - self.defaults.profile.units.maintank.offset = 0 - self.defaults.profile.units.maintank.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60} - -- MAINASSIST - self.defaults.profile.units.mainassist.groupFilter = "MAINASSIST" - self.defaults.profile.units.mainassist.groupBy = "GROUP" - self.defaults.profile.units.mainassist.sortOrder = "ASC" - self.defaults.profile.units.mainassist.sortMethod = "INDEX" - self.defaults.profile.units.mainassist.attribPoint = "TOP" - self.defaults.profile.units.mainassist.attribAnchorPoint = "RIGHT" - self.defaults.profile.units.mainassist.offset = 0 - self.defaults.profile.units.mainassist.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60} - -- PARTYPET - self.defaults.profile.positions.partypet.anchorTo = "$parent" - self.defaults.profile.positions.partypet.anchorPoint = "RB" - self.defaults.profile.units.partypet.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60} - -- PARTYTARGET - 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, spec, level) - -- Prevent duplicate registration for deprecated plugin - if( key == "auraIndicators" and C_AddOns.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 - - self.modules[key] = module - - module.moduleKey = key - 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 - -function ShadowUF:FireModuleEvent(event, frame, unit) - for _, module in pairs(self.moduleOrder) do - if( module[event] ) then - module[event](module, frame, unit) - end - end -end - --- Profiles changed --- I really dislike this solution, but if we don't do it then there is setting issues --- because when copying a profile, AceDB-3.0 fires OnProfileReset -> OnProfileCopied --- SUF then sees that on the new reset profile has no profile, tries to load one in --- ... followed by the profile copying happen and it doesn't copy everything correctly --- due to variables being reset already. -local resetTimer -function ShadowUF:ProfileReset() - if( not resetTimer ) then - resetTimer = CreateFrame("Frame") - resetTimer:SetScript("OnUpdate", function(f) - ShadowUF:ProfilesChanged() - f:Hide() - end) - end - - resetTimer:Show() -end - -function ShadowUF:ProfilesChanged() - if( self.layoutImporting ) then return end - if( resetTimer ) then resetTimer:Hide() end - - self.db:RegisterDefaults(self.defaults) - - -- No active layout, register the default one - if( not self.db.profile.loadedLayout ) then - self:LoadDefaultLayout() - else - self:CheckUpgrade() - self:CheckBuild() - end - - self.db.profile.revision = self.dbRevision - - self:FireModuleEvent("OnProfileChange") - self:LoadUnits() - self:HideBlizzardFrames() - self.Layout:CheckMedia() - self.Units:ProfileChanged() - self.modules.movers:Update() -end - -ShadowUF.noop = function() end -ShadowUF.hiddenFrame = CreateFrame("Frame") -ShadowUF.hiddenFrame:Hide() - -local rehideFrame = function(self) - if( not InCombatLockdown() ) then - self:Hide() - end -end - -local function basicHideBlizzardFrames(...) - for i=1, select("#", ...) do - local frame = select(i, ...) - frame:UnregisterAllEvents() - frame:HookScript("OnShow", rehideFrame) - frame:Hide() - end -end - -local function hideBlizzardFrames(taint, ...) - for i=1, select("#", ...) do - local frame = select(i, ...) - UnregisterUnitWatch(frame) - frame:UnregisterAllEvents() - 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 - - if( taint ) then - frame.Show = ShadowUF.noop - else - frame:SetParent(ShadowUF.hiddenFrame) - frame:HookScript("OnShow", rehideFrame) - end - end -end - -local active_hiddens = {} -function ShadowUF:HideBlizzardFrames() - if( self.db.profile.hidden.cast and not active_hiddens.cast ) then - hideBlizzardFrames(true, PlayerCastingBarFrame, PetCastingBarFrame) - end - - if( self.db.profile.hidden.party and not active_hiddens.party ) then - if( PartyFrame ) then - hideBlizzardFrames(false, PartyFrame) - for memberFrame in PartyFrame.PartyMemberFramePool:EnumerateActive() do - if memberFrame.HealthBarContainer and memberFrame.HealthBarContainer.HealthBar then - hideBlizzardFrames(false, memberFrame, memberFrame.HealthBarContainer.HealthBar, memberFrame.ManaBar) - else - hideBlizzardFrames(false, memberFrame, memberFrame.HealthBar, memberFrame.ManaBar) - end - end - PartyFrame.PartyMemberFramePool:ReleaseAll() - else - for i=1, MAX_PARTY_MEMBERS do - local name = "PartyMemberFrame" .. i - hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"]) - end - end - - -- This stops the compact party frame from being shown - UIParent:UnregisterEvent("GROUP_ROSTER_UPDATE") - - -- 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 - - 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 - - if( self.db.profile.hidden.buffs and not active_hiddens.buffs ) then - hideBlizzardFrames(false, BuffFrame, DebuffFrame) - end - - if( self.db.profile.hidden.player and not active_hiddens.player ) then - hideBlizzardFrames(false, PlayerFrame, AlternatePowerBar) - - -- 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 - - if( self.db.profile.hidden.playerPower and not active_hiddens.playerPower ) then - basicHideBlizzardFrames(RuneFrame, WarlockPowerFrame, MonkHarmonyBarFrame, PaladinPowerBarFrame, MageArcaneChargesFrame, EssencePlayerFrame) - end - - if( self.db.profile.hidden.pet and not active_hiddens.pet ) then - hideBlizzardFrames(false, PetFrame) - end - - 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( self.db.profile.hidden.boss and not active_hiddens.boss ) then - hideBlizzardFrames(false, BossTargetFrameContainer) - - for i=1, MAX_BOSS_FRAMES do - local name = "Boss" .. i .. "TargetFrame" - if _G[name].TargetFrameContent then - if _G[name].TargetFrameContent.TargetFrameContentMain.HealthBarsContainer then - hideBlizzardFrames(false, _G[name], _G[name].TargetFrameContent.TargetFrameContentMain.HealthBarsContainer.HealthBar, _G[name].TargetFrameContent.TargetFrameContentMain.ManaBar) - else - hideBlizzardFrames(false, _G[name], _G[name].TargetFrameContent.TargetFrameContentMain.HealthBar, _G[name].TargetFrameContent.TargetFrameContentMain.ManaBar) - end - else - hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"]) - end - end - end - - if( self.db.profile.hidden.arena and not active_hiddens.arenaTriggered ) then - active_hiddens.arenaTriggered = true - - hideBlizzardFrames(true, ArenaEnemyFramesContainer, ArenaEnemyPrepFramesContainer, ArenaEnemyMatchFramesContainer) - end - - if( self.db.profile.hidden.playerAltPower and not active_hiddens.playerAltPower ) then - hideBlizzardFrames(false, PlayerPowerBarAlt) - 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, BackdropTemplateMixin and "BackdropTemplate" or nil) - 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(f) - f:GetParent():Hide() - end) -end - -function ShadowUF:Print(msg) - DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99Shadow UF|r: " .. msg) -end - -CONFIGMODE_CALLBACKS = CONFIGMODE_CALLBACKS or {} -CONFIGMODE_CALLBACKS["Shadowed Unit Frames"] = function(mode) - if( mode == "ON" ) then - ShadowUF.db.profile.locked = false - ShadowUF.modules.movers.isConfigModeSpec = true - elseif( mode == "OFF" ) then - ShadowUF.db.profile.locked = true - end - - ShadowUF.modules.movers:Update() -end - -SLASH_SHADOWEDUF1 = "/suf" -SLASH_SHADOWEDUF2 = "/shadowuf" -SLASH_SHADOWEDUF3 = "/shadoweduf" -SLASH_SHADOWEDUF4 = "/shadowedunitframes" -SlashCmdList["SHADOWEDUF"] = function(msg) - msg = msg and string.lower(msg) - if( msg and string.match(msg, "^profile (.+)") ) then - local profile = string.match(msg, "^profile (.+)") - - for id, name in pairs(ShadowUF.db:GetProfiles()) do - if( string.lower(name) == profile ) then - ShadowUF.db:SetProfile(name) - ShadowUF:Print(string.format(L["Changed profile to %s."], name)) - return - end - end - - ShadowUF:Print(string.format(L["Cannot find any profiles named \"%s\"."], profile)) - return - end - - local loaded, reason = C_AddOns.LoadAddOn("ShadowedUF_Options") - if( not ShadowUF.Config ) then - DEFAULT_CHAT_FRAME:AddMessage(string.format(L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"], reason and _G["ADDON_" .. reason] or "")) - return - end - - ShadowUF.Config:Open() -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) +--[[ + Shadowed Unit Frames, Shadowed of Mal'Ganis (US) PvP +]] + +ShadowUF = select(2, ...) + +local L = ShadowUF.L +ShadowUF.dbRevision = 63 +ShadowUF.dbRevisionClassic = 61 +ShadowUF.playerUnit = "player" +ShadowUF.enabledUnits = {} +ShadowUF.modules = {} +ShadowUF.moduleOrder = {} +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.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 = { + profile = { + locked = false, + advanced = false, + tooltipCombat = false, + bossmodSpellRename = true, + omnicc = false, + blizzardcc = true, + tags = {}, + units = {}, + positions = {}, + range = {}, + filters = {zonewhite = {}, zoneblack = {}, zoneoverride = {}, whitelists = {}, blacklists = {}, overridelists = {}}, + visibility = {arena = {}, pvp = {}, party = {}, raid = {}}, + 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) + if( not ShadowUF.Tags.defaultTags[index] and not ShadowUF.db.profile.tags[index] ) then + tbl[index] = false + return false + end + + local func, msg = loadstring("return " .. (ShadowUF.Tags.defaultTags[index] or ShadowUF.db.profile.tags[index].func or "")) + if( func ) then + func = func() + elseif( msg ) then + error(msg, 3) + end + + tbl[index] = func + return tbl[index] + end}) + + if( not self.db.profile.loadedLayout ) then + self:LoadDefaultLayout() + else + self:CheckUpgrade() + self:CheckBuild() + self:ShowInfoPanel() + end + + self.db.profile.revision = self.dbRevision + self.db.profile.revisionClassic = self.dbRevisionClassic + 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 auraData + if type(spell) == "string" then + auraData = C_UnitAuras.GetAuraDataBySpellName(unit, spell, filter) + elseif type(spell) == "number" then + local index = 0 + while true do + index = index + 1 + local data = C_UnitAuras.GetAuraDataByIndex(unit, index, filter) + if not data then break end + if data.spellId == spell then + auraData = data + break + end + end + end + return AuraUtil.UnpackAuraData(auraData) +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() + local revisionClassic = self.db.profile.revisionClassic or (self.db.profile.revision and 1 or self.dbRevisionClassic) + local revision = self.db.profile.revision or self.dbRevision + if( revisionClassic <= 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.consolidated = true + aura.show.misc = true + end + end + end + end + + if( revisionClassic <= 44 ) then + ShadowUF:LoadDefaultLayout(true) + + for unit, config in pairs(self.defaults.profile.units) do + if( config.indicators and config.indicators.resurrect ) then + local db = self.db.profile.units[unit] + + local options + if( unit == "target" ) then + options = {enabled = true, anchorPoint = "RC", size = 28, x = -39, y = -1, anchorTo = "$parent"} + else + options = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"} + end + + for key, value in pairs(options) do + if( db.indicators.resurrect[key] == nil ) then + db.indicators.resurrect[key] = value + end + end + end + end + end + + if( revisionClassic <= 43 ) then + for key, _ in pairs(self.db.profile.auraIndicators.indicators) do + self.db.profile.auraIndicators.height = nil + self.db.profile.auraIndicators.filters[key] = {boss = {priority = 100}, curable = {priority = 100}} + end + end + + if( revisionClassic <= 42 ) then + for unit, config in pairs(self.db.profile.units) do + config.auras.height = nil + + for type, auraConfig in pairs(config.auras) do + auraConfig.show = {misc = true} + auraConfig.show.player = auraConfig.player + auraConfig.show.raid = auraConfig.raid + + auraConfig.enlarge = {} + auraConfig.enlarge["SELF"] = auraConfig.enlargeSelf + auraConfig.enlarge["REMOVABLE"] = auraConfig.enlargeStealable + + auraConfig.timers = {} + if( auraConfig.selfTimers ) then + auraConfig.timers["SELF"] = true + else + auraConfig.timers["ALL"] = true + end + + auraConfig.selfTimers = nil + auraConfig.player = nil + auraConfig.raid = nil + auraConfig.enlargeSelf = nil + auraConfig.enlargeStealable = nil + end + + config.auras.buffs.show.consolidated = true + config.auras.debuffs.show.boss = true + end + end + + if( revisionClassic <= 41 ) then + local phase = self.db.profile.units.party.indicators.phase + phase.anchorPoint = phase.anchorPoint or "RC" + phase.size = phase.size or 14 + phase.x = phase.x or -11 + phase.y = phase.y or 0 + phase.anchorTo = phase.anchorTo or "$parent" + end + + if( revisionClassic <= 40 ) then + ShadowUF:LoadDefaultLayout(true) + + for unit, config in pairs(self.db.profile.units) do + if( config.healAbsorb and not self.defaults.profile.units[unit].healAbsorb ) then + config.healAbsorb = nil + end + end + end + + if( revisionClassic <= 37 ) then + self.db.profile.healthColors.healAbsorb = {r = 0.68, g = 0.47, b = 1} + end + + if( revisionClassic <= 34 ) then + self.db.profile.units.player.staggerBar = {enabled = true, background = true, height = 0.30, order = 70} + self.db.profile.powerColors.STAGGER_GREEN = {r = 0.52, g = 1.0, b = 0.52} + self.db.profile.powerColors.STAGGER_YELLOW = {r = 1.0, g = 0.98, b = 0.72} + self.db.profile.powerColors.STAGGER_RED = {r = 1.0, g = 0.42, b = 0.42} + end + + if( revisionClassic <= 33 ) then + for unit, config in pairs(self.db.profile.units) do + if( not self.defaults.profile.units[unit].incHeal and config.incHeal ) then + config.incHeal = nil + end + + if( not self.defaults.profile.units[unit].incAbsorb and config.incAbsorb ) then + config.incAbsorb = nil + end + + if( config.incAbsorb ) then + config.incAbsorb.cap = config.incAbsorb.cap or 1.30 + end + + if( config.incHeal ) then + config.incHeal.cap = config.incHeal.cap or 1.30 + end + end + end + + if( revisionClassic <= 32 ) then + for unit, config in pairs(self.db.profile.units) do + if( config.incAbsorb and not config.incAbsorb.cap ) then + config.incAbsorb.cap = 1.30 + end + end + end + + if( revisionClassic <= 31 or not self.db.profile.healthColors.incAbsorb ) then + self.db.profile.healthColors.incAbsorb = {r = 0.93, g = 0.75, b = 0.09} + + for unit, config in pairs(self.db.profile.units) do + if( config.incHeal ) then + config.incHeal.enabled = config.incHeal.heals + config.incHeal.heals = nil + config.incAbsorb = {enabled = config.incHeal.enabled} + end + end + end + + if( revisionClassic <= 30 ) then + self.db.profile.powerColors.RUNEOFPOWER = {r = 0.35, g = 0.45, b = 0.60} + end + + if( revisionClassic <= 29 ) then + self.db.profile.units.player.totemBar.showAlways = true + end + + if( revisionClassic <= 28 ) then + self.db.profile.units.target.indicators.questBoss = {enabled = true, anchorPoint = "BR", size = 22, x = 9, y = 24, anchorTo = "$parent"} + self.db.profile.units.focus.indicators.questBoss = {enabled = false, anchorPoint = "BR", size = 22, x = 7, y = 14, anchorTo = "$parent"} + + for unit, config in pairs(self.db.profile.units) do + for key, module in pairs(ShadowUF.modules) do + if( config[key] and ( module.moduleHasBar or module.isComboPoints or config[key].isBar or config[key].order ) ) then + config[key].height = config[key].height or 0.40 + end + end + end + end + + if( revisionClassic <= 27 ) then + self.db.profile.healthColors.aggro = CopyTable(self.db.profile.healthColors.hostile) + end + + if( revisionClassic <= 26 ) then + for _, unit in pairs(self.unitList) do + if( unit ~= "player" ) then + for id, text in pairs(self.db.profile.units[unit].text) do + if( text.anchorTo == "$demonicFuryBar" ) then + self.db.profile.units[unit].text[id] = nil + end + end + end + end + end + + -- if( revisionClassic <= 25 ) then + -- table.insert(self.db.profile.units.player.text, {enabled = true, width = 1, name = L["Eclipse Power"], text = "[druid:balance]", anchorTo = "$eclipseBar", anchorPoint = "C", size = 0, x = 0, y = 0, default = true}) + -- end + if( revisionClassic <= 24 ) then + self.db.profile.powerColors.AURAPOINTS = {r = 1.0, g = 0.80, b = 0} + self.db.profile.units.player.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} + end + + if( revisionClassic <= 23 ) then + self.db.profile.hidden.playerAltPower = false + self.db.profile.powerColors.ALTERNATE = {r = 0.815, g = 0.941, b = 1} + end + + if( revisionClassic <= 22 ) then + self:LoadDefaultLayout(true) + + for _, unit in pairs(self.unitList) do + if( ShadowUF.fakeUnits[unit] ) then + self.db.profile.units[unit].altPowerBar.enabled = false + end + end + end + + if( revisionClassic <= 21 ) then + self.db.profile.powerColors["POWER_TYPE_FEL_ENERGY"] = {r = 0.878, g = 0.980, b = 0} + end + + if( revisionClassic <= 20 ) then + self.db.profile.powerColors["ALTERNATE"] = {r = 0.71, g = 0.0, b = 1.0} + + for _, unit in pairs(self.unitList) do + self.db.profile.units[unit].altPowerBar.enabled = true + self.db.profile.units[unit].altPowerBar.background = true + self.db.profile.units[unit].altPowerBar.height = 0.40 + self.db.profile.units[unit].altPowerBar.order = 100 + end + end + if( revisionClassic <= 19 ) then + table.insert(self.db.profile.units.player.text, {enabled = true, width = 1, name = L["Demonic Power"], text = "", anchorTo = "$demonicFuryBar", anchorPoint = "C", x = 3, y = 0, size = -1}) + table.insert(self.db.profile.units.player.text, {enabled = true, width = 1, name = L["Eclipse Power"], text = "", anchorTo = "$eclipseBar", anchorPoint = "C", size = 0, x = 0, y = 0}) + table.insert(self.db.profile.units.player.text, {enabled = true, width = 1, name = L["Timer Text"], text = "", anchorTo = "$runeBar", anchorPoint = "C", size = 0, x = 0, y = 0}) + table.insert(self.db.profile.units.player.text, {enabled = true, width = 1, name = L["Timer Text"], text = "", anchorTo = "$totemBar", anchorPoint = "C", size = 0, x = 0, y = 0}) + table.insert(self.db.profile.units.player.text, {enabled = true, width = 1, name = L["Stagger Power"], text = "", anchorTo = "$staggerBar", anchorPoint = "C", size = 0, x = 0, y = 0}) + end + if( revisionClassic <= 18 ) then + self.db.profile.powerColors["MUSHROOMS"] = {r = 0.20, g = 0.90, b = 0.20} + self.db.profile.powerColors["STATUE"] = {r = 0.35, g = 0.45, b = 0.60} + end + + if( revisionClassic <= 17 ) then + self.db.profile.units.target.indicators.petBattle = {enabled = true, anchorPoint = "BL", size = 18, x = -6, y = 14, anchorTo = "$parent"} + self.db.profile.units.focus.indicators.petBattle = {enabled = false, anchorPoint = "BL", size = 18, x = -6, y = 12, anchorTo = "$parent"} + self.db.profile.units.party.indicators.phase = {enabled = true} + end + + if( revisionClassic <= 16 ) then + self.db.profile.units.target.indicators.questBoss = {enabled = true, anchorPoint = "BR", size = 22, x = 9, y = 24, anchorTo = "$parent"} + self.db.profile.units.focus.indicators.questBoss = {enabled = false, anchorPoint = "BR", size = 22, x = 7, y = 14, anchorTo = "$parent"} + end + + if( revisionClassic <= 15 ) then + self.db.profile.powerColors["DEMONICFURY"] = {r = 0.58, g = 0.51, b = 0.79} + self.db.profile.powerColors["BURNINGEMBERS"] = {r = 0.58, g = 0.51, b = 0.79} + self.db.profile.powerColors["FULLBURNINGEMBER"] = {r = 0.88, g = 0.09, b = 0.062} + self.db.profile.powerColors["SHADOWORBS"] = {r = 0.58, g = 0.51, b = 0.79} + + self.db.profile.units.player.shadowOrbsBar = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -3, y = 6, size = 14, spacing = -4, growth = "LEFT", isBar = true, showAlways = true} + self.db.profile.units.player.burningEmbersBar = {enabled = true, background = false, height = 0.40, order = 70} + self.db.profile.units.player.demonicFuryBar = {enabled = true, background = false, height = 0.40, order = 70} + end + + if( revisionClassic <= 14 ) then + self.db.profile.powerColors["CHI"] = {r = 0.71, g = 1.0, b = 0.92} + + self.db.profile.units.player.chi = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -3, y = 6, size = 14, spacing = -4, growth = "LEFT", isBar = true, showAlways = true} + end + if( revisionClassic <= 13 ) then + self.db.profile.powerColors["BANKEDHOLYPOWER"] = {r = 0.96, g = 0.61, b = 0.84} + end + + if( revisionClassic <= 12 ) then + self.db.profile.classColors["MONK"] = {r = 0.0, g = 1.00, b = 0.59} + end + + if( revisionClassic <= 11 ) then + for unit, config in pairs(self.db.profile.units) do + if( config.powerBar ) then + config.powerBar.colorType = "type" + end + end + end + + if( revisionClassic <= 5 ) then + local config = self.db.profile.units + config.player.soulShards = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -8, y = 6, size = 12, spacing = -2, growth = "LEFT", isBar = true, showAlways = true} + config.player.holyPower = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -3, y = 6, size = 14, spacing = -4, growth = "LEFT", isBar = true, showAlways = true} + + self.db.profile.classColors.VEHICLE = {r = 0.23, g = 0.41, b = 0.23} + self.db.profile.healthColors.aggro = {r = 0.9, g = 0, b = 0} + end + if( revisionClassic <= 4 ) then + -- new resources + self.db.profile.powerColors.RUNES_BLOOD = {r = 0.95, g = 0.0, b = 0.08} + self.db.profile.powerColors.RUNES_FROST = {r = 0.0, g = 0.85, b = 1.0} + self.db.profile.powerColors.RUNES_UNHOLY = {r = 0.0, g = 1.0, b = 0.35} + self.db.profile.powerColors.RUNES_DEATH = {r = 0.69, g = 0.15, b = 1.0} + + -- new bars + local config = self.db.profile.units + config.player.runeBar = {enabled = true, background = false, height = 0.40, order = 70} + local hasRuneText = false + for i, text in ipairs(config.player.text) do + if text and text.anchorTo == "$runeBar" and text == "[rune:timer]" then + hasRuneText = true + end + end + end + if( revisionClassic <= 4 or not self.db.profile.revisionClassic ) then + ShadowUF:LoadDefaultLayout(true) + end + if( revisionClassic <= 1 ) then + local indicators = self.db.profile.units.pet.indicators or {} + self.db.profile.units.pet.indicators = indicators + if( revision <= 59 or not indicators.happiness ) then + indicators.happiness = {enabled = true, anchorPoint = "RC", size = 20, x = 0, y = 0, anchorTo = "$parent"} + else + local happiness = indicators.happiness + if happiness.size == 0 then + happiness.size = 20 + end + if not happiness.anchorPoint then + happiness.anchorPoint = "RC" + end + if not happiness.anchorTo then + happiness.anchorTo = "$parent" + end + end + end + if( revision <= 58 ) then + for unit, config in pairs(self.db.profile.units) do + 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 + + if( revision <= 49 ) then + ShadowUF:LoadDefaultLayout(true) + self.db.profile.classColors.DEMONHUNTER = {r = 0.64, g = 0.19, b = 0.79} + end + + if( revision <= 49 ) then + if( ShadowUF.db.profile.font.extra == "MONOCHROME" ) then + ShadowUF.db.profile.font.extra = "" + end + 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 + + if( revisionClassic <= 15 ) then + self.db.profile.powerColors["DEMONICFURY"] = {r = 0.58, g = 0.51, b = 0.79} + self.db.profile.powerColors["BURNINGEMBERS"] = {r = 0.58, g = 0.51, b = 0.79} + self.db.profile.powerColors["FULLBURNINGEMBER"] = {r = 0.88, g = 0.09, b = 0.062} + self.db.profile.powerColors["SHADOWORBS"] = {r = 0.58, g = 0.51, b = 0.79} + + self.db.profile.units.player.shadowOrbs = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -3, y = 6, size = 14, spacing = -4, growth = "LEFT", isBar = true, showAlways = true} + self.db.profile.units.player.burningEmbersBar = {enabled = true, background = false, height = 0.40, order = 70} + self.db.profile.units.player.demonicFuryBar = {enabled = true, background = false, height = 0.40, order = 70} + 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] ) 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 + elseif( self.db.profile.visibility[instanceType][type] == true ) then + enabled = true + end + end + + self.enabledUnits[type] = enabled + + if( enabled ) then + self.Units:InitializeFrame(type) + else + self.Units:UninitializeFrame(type) + end + end +end + +function ShadowUF:LoadUnitDefaults() + for _, unit in pairs(self.unitList) do + self.defaults.profile.positions[unit] = {point = "", relativePoint = "", anchorPoint = "", anchorTo = "UIParent", x = 0, y = 0} + + -- The reason why the defaults are so sparse, is because the layout needs to specify most of this. The reason I set tables here is basically + -- as an indication that hey, the unit wants this, if it doesn't that it won't want it. + self.defaults.profile.units[unit] = { + enabled = false, height = 0, width = 0, scale = 1.0, + healthBar = {enabled = true}, + powerBar = {enabled = true}, + emptyBar = {enabled = false}, + portrait = {enabled = false}, + castBar = {enabled = false, name = {}, time = {}}, + text = { + {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, 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 ~= "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 + + if( unit ~= "player" ) then + self.defaults.profile.units[unit].range = {enabled = false, oorAlpha = 0.80, inAlpha = 1.0} + + if( not string.match(unit, "pet") ) then + self.defaults.profile.units[unit].indicators.class = {enabled = false, size = 19} + end + end + + 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} + self.defaults.profile.units[unit].indicators.sumPending = {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 + self.defaults.profile.units.player.powerBar.predicted = true + self.defaults.profile.units.player.indicators.status.enabled = true + 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.monkBar = {enabled = false} + self.defaults.profile.units.player.shamanBar = {enabled = true} + self.defaults.profile.units.player.xpBar = {enabled = false} + 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.demonicFuryBar = {enabled = true} + self.defaults.profile.units.player.burningEmbersBar = {enabled = true} + self.defaults.profile.units.player.eclipseBar = {enabled = true} + self.defaults.profile.units.player.holyPower = {enabled = true, isBar = true} + self.defaults.profile.units.player.shadowOrbs = {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} + self.defaults.profile.units.player.auraPoints = {enabled = false, isBar = true} + self.defaults.profile.units.player.essence = {enabled = true, 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}) + 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.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60} + self.defaults.profile.units.pet.xpBar = {enabled = false} + -- 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.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 + -- PARTY + self.defaults.profile.units.party.enabled = true + self.defaults.profile.units.party.auras.debuffs.maxRows = 1 + self.defaults.profile.units.party.auras.buffs.maxRows = 1 + 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" + self.defaults.profile.units.arena.attribAnchorPoint = "LEFT" + 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" + self.defaults.profile.units.boss.attribAnchorPoint = "LEFT" + 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" + self.defaults.profile.units.raid.sortMethod = "INDEX" + self.defaults.profile.units.raid.attribPoint = "TOP" + self.defaults.profile.units.raid.attribAnchorPoint = "RIGHT" + self.defaults.profile.units.raid.offset = 0 + 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" + self.defaults.profile.units.raidpet.sortMethod = "INDEX" + self.defaults.profile.units.raidpet.attribPoint = "TOP" + self.defaults.profile.units.raidpet.attribAnchorPoint = "RIGHT" + self.defaults.profile.units.raidpet.offset = 0 + self.defaults.profile.units.raidpet.filters = {[1] = true, [2] = true, [3] = true, [4] = true, [5] = true, [6] = true, [7] = true, [8] = true} + 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" + self.defaults.profile.units.maintank.sortMethod = "INDEX" + self.defaults.profile.units.maintank.attribPoint = "TOP" + self.defaults.profile.units.maintank.attribAnchorPoint = "RIGHT" + self.defaults.profile.units.maintank.offset = 0 + self.defaults.profile.units.maintank.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60} + -- MAINASSIST + self.defaults.profile.units.mainassist.groupFilter = "MAINASSIST" + self.defaults.profile.units.mainassist.groupBy = "GROUP" + self.defaults.profile.units.mainassist.sortOrder = "ASC" + self.defaults.profile.units.mainassist.sortMethod = "INDEX" + self.defaults.profile.units.mainassist.attribPoint = "TOP" + self.defaults.profile.units.mainassist.attribAnchorPoint = "RIGHT" + self.defaults.profile.units.mainassist.offset = 0 + self.defaults.profile.units.mainassist.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60} + -- PARTYPET + self.defaults.profile.positions.partypet.anchorTo = "$parent" + self.defaults.profile.positions.partypet.anchorPoint = "RB" + self.defaults.profile.units.partypet.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60} + -- PARTYTARGET + 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, spec, level) + -- Prevent duplicate registration for deprecated plugin + if( key == "auraIndicators" and C_AddOns.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 + + self.modules[key] = module + + module.moduleKey = key + 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 + +function ShadowUF:FireModuleEvent(event, frame, unit) + for _, module in pairs(self.moduleOrder) do + if( module[event] ) then + module[event](module, frame, unit) + end + end +end + +-- Profiles changed +-- I really dislike this solution, but if we don't do it then there is setting issues +-- because when copying a profile, AceDB-3.0 fires OnProfileReset -> OnProfileCopied +-- SUF then sees that on the new reset profile has no profile, tries to load one in +-- ... followed by the profile copying happen and it doesn't copy everything correctly +-- due to variables being reset already. +local resetTimer +function ShadowUF:ProfileReset() + if( not resetTimer ) then + resetTimer = CreateFrame("Frame") + resetTimer:SetScript("OnUpdate", function(f) + ShadowUF:ProfilesChanged() + f:Hide() + end) + end + + resetTimer:Show() +end + +function ShadowUF:ProfilesChanged() + if( self.layoutImporting ) then return end + if( resetTimer ) then resetTimer:Hide() end + + self.db:RegisterDefaults(self.defaults) + + -- No active layout, register the default one + if( not self.db.profile.loadedLayout ) then + self:LoadDefaultLayout() + else + self:CheckUpgrade() + self:CheckBuild() + end + + self.db.profile.revision = self.dbRevision + + self:FireModuleEvent("OnProfileChange") + self:LoadUnits() + self:HideBlizzardFrames() + self.Layout:CheckMedia() + self.Units:ProfileChanged() + self.modules.movers:Update() +end + +ShadowUF.noop = function() end +ShadowUF.hiddenFrame = CreateFrame("Frame") +ShadowUF.hiddenFrame:Hide() + +local rehideFrame = function(self) + if( not InCombatLockdown() ) then + self:Hide() + end +end + +local function basicHideBlizzardFrames(...) + for i=1, select("#", ...) do + local frame = select(i, ...) + frame:UnregisterAllEvents() + frame:HookScript("OnShow", rehideFrame) + frame:Hide() + end +end + +local function hideBlizzardFrames(taint, ...) + for i=1, select("#", ...) do + local frame = select(i, ...) + UnregisterUnitWatch(frame) + frame:UnregisterAllEvents() + 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 + + if( taint ) then + frame.Show = ShadowUF.noop + else + frame:SetParent(ShadowUF.hiddenFrame) + frame:HookScript("OnShow", rehideFrame) + end + end +end + +local active_hiddens = {} +function ShadowUF:HideBlizzardFrames() + if( self.db.profile.hidden.cast and not active_hiddens.cast ) then + hideBlizzardFrames(true, CastingBarFrame, PetCastingBarFrame) + end + + if( self.db.profile.hidden.party and not active_hiddens.party ) then + for i=1, MAX_PARTY_MEMBERS do + local name = "PartyMemberFrame" .. i + hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"]) + end + + -- This stops the compact party frame from being shown + UIParent:UnregisterEvent("GROUP_ROSTER_UPDATE") + + -- 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 + + 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 + + if( self.db.profile.hidden.buffs and not active_hiddens.buffs ) then + hideBlizzardFrames(false, BuffFrame, TemporaryEnchantFrame) + end + + if( self.db.profile.hidden.player and not active_hiddens.player ) then + hideBlizzardFrames(false, PlayerFrame) + + -- 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 + + if( self.db.profile.hidden.pet and not active_hiddens.pet ) then + hideBlizzardFrames(false, PetFrame) + end + + 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 and FocusFrame and FocusFrameToT ) then + hideBlizzardFrames(false, FocusFrame, FocusFrameToT) + end + + if( self.db.profile.hidden.boss and not active_hiddens.boss ) then + + for i=1, MAX_BOSS_FRAMES do + local name = "Boss" .. i .. "TargetFrame" + + hideBlizzardFrames(false, _G[name], _G[name .. "HealthBar"], _G[name .. "ManaBar"]) + + 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, BackdropTemplateMixin and "BackdropTemplate" or nil) + 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(f) + f:GetParent():Hide() + end) +end + +function ShadowUF:Print(msg) + DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99Shadow UF|r: " .. msg) +end + +CONFIGMODE_CALLBACKS = CONFIGMODE_CALLBACKS or {} +CONFIGMODE_CALLBACKS["Shadowed Unit Frames"] = function(mode) + if( mode == "ON" ) then + ShadowUF.db.profile.locked = false + ShadowUF.modules.movers.isConfigModeSpec = true + elseif( mode == "OFF" ) then + ShadowUF.db.profile.locked = true + end + + ShadowUF.modules.movers:Update() +end + +SLASH_SHADOWEDUF1 = "/suf" +SLASH_SHADOWEDUF2 = "/shadowuf" +SLASH_SHADOWEDUF3 = "/shadoweduf" +SLASH_SHADOWEDUF4 = "/shadowedunitframes" +SlashCmdList["SHADOWEDUF"] = function(msg) + msg = msg and string.lower(msg) + if( msg and string.match(msg, "^profile (.+)") ) then + local profile = string.match(msg, "^profile (.+)") + + for id, name in pairs(ShadowUF.db:GetProfiles()) do + if( string.lower(name) == profile ) then + ShadowUF.db:SetProfile(name) + ShadowUF:Print(string.format(L["Changed profile to %s."], name)) + return + end + end + + ShadowUF:Print(string.format(L["Cannot find any profiles named \"%s\"."], profile)) + return + end + + local loaded, reason = C_AddOns.LoadAddOn("ShadowedUF_Options") + if( not ShadowUF.Config ) then + DEFAULT_CHAT_FRAME:AddMessage(string.format(L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"], reason and _G["ADDON_" .. reason] or "")) + return + end + + ShadowUF.Config:Open() +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) diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc index ceeec4a37..2bc46c4b3 100755 --- a/ShadowedUnitFrames.toc +++ b/ShadowedUnitFrames.toc @@ -1,74 +1,78 @@ -## Interface: 110107 -## Title: Shadowed Unit Frames -## Notes: Moooooooooooooooooo -## Author: Shadowed -## Version: @project-version@ -## SavedVariables: ShadowedUFDB -## X-Website: https://www.wowace.com/addons/shadowed-unit-frames/ -## OptionalDeps: Ace3, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibDualSpec-1.0, LibSpellRange-1.0, UTF8, Clique -## X-Curse-Project-ID: 19268 -## X-WoWI-ID: 13494 -## Category: ShadowedUnitFrames - -#@no-lib-strip@ -libs\LibStub\LibStub.lua -libs\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 -libs\UTF8\utf8.lua -#@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 -modules\essence.lua -#@do-not-package@ -options\config.lua -#@end-do-not-package@ +## Interface: 110105, 50500, 110107, 110200 +## Title: Shadowed Unit Frames +## Notes: Moooooooooooooooooo +## Author: Shadowed +## Version: v5.5.05 +## SavedVariables: ShadowedUFDB +## X-Website: https://www.wowace.com/addons/shadowed-unit-frames/ +## OptionalDeps: Ace3, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibDualSpec-1.0, LibSpellRange-1.0, LibClassicDurations, Clique, LibClassicCasterino +## X-Curse-Project-ID: 19268 +## X-WoWI-ID: 13494 +## Category: ShadowedUnitFrames + +#@no-lib-strip@ +libs\LibStub\LibStub.lua +libs\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 +libs\UTF8\utf8.lua +libs\LibClassicDurations\LibClassicDurations.xml +libs\LibClassicCasterino\LibClassicCasterino.lua +#@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 + +ExternalAPI.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\eclipse.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 +modules\essence.lua +modules\burningembers.lua +modules\shadoworbs.lua +modules\demonicfury.lua diff --git a/ShadowedUnitFrames.xml b/ShadowedUnitFrames.xml index ec6af43d9..4fbd05630 100644 --- a/ShadowedUnitFrames.xml +++ b/ShadowedUnitFrames.xml @@ -1,8 +1,8 @@ - - - + + + diff --git a/localization/deDE.lua b/localization/deDE.lua index 269c7f1bf..e76726669 100755 --- a/localization/deDE.lua +++ b/localization/deDE.lua @@ -1,5 +1,909 @@ -if( GetLocale() ~= "deDE" ) then return end -local L = {} ---@localization(locale="deDE", format="lua_additive_table", handle-unlocalized="ignore")@ -local ShadowUF = select(2, ...) -ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) +if( GetLocale() ~= "deDE" ) then return end +local L = {} +L["%d auras in group"] = "%d Auren in Gruppe" +L["%s (%s): %s/%s (%.2f%% done)"] = "%s (%s): %s/%s (%.2f%% erhalten)" +L["%s aura groups disabled"] = "%s Aurengruppen deaktiviert" +L["%s frames"] = "%s Fenster" +L["%s member"] = "%s Mitglieder" +L["|cff20ff20%s|r units enabled"] = "|cff20ff20%s|r Einheiten aktiviert" +L["|cffff2020%s|r units disabled"] = "|cffff2020%s|r Einheiten deaktiviert" +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."] = "|cffff2020Warnung!|r Einige Einheiten sind trotz den unten aufgeführten Einstellungen in der Gebietskonfiguration überschrieben worden und werden womöglich in bestimmten Gebieten angezeigt (oder nicht angezeigt)." +L["1 aura group disabled"] = "1 Aurengruppe deaktiviert" +L["2D"] = "2D" +L["3D"] = "3D" +L["A"] = "A" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "Kürzt die Namen von Einheiten mit mehr als 10 Buchstaben. \"Dunkler Runenchampion\" wird zu \"D.R.Champion\" und \"Dunkler Runenbürger\" wird zu \"D.R.Bürger\"." +L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."] = "Absolute Schadensabsorption der Einheit, wenn 10.000 Schaden absorbiert werden, wird 10.000 angezeigt." +L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."] = "Absolute Heilungsabsorption, wenn 16.000 Heilung absorbiert werden, wird 16.000 angezeigt." +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "Absoluter Wert der eingehenden Heilung. Wenn 10.000 eingehen, werden auch 10.000 angezeigt." +L["Add"] = "Hinzufügen" +L["Add Aura"] = "Aura hinzufügen" +L["Add aura"] = "Aura hinzufügen" +L["Add Indicator"] = "Indikator hinzufügen" +L["Add link"] = "Link hinzufügen" +L["Add new indicator"] = "Neuen Indikator hinzufügen" +L["Add new tag"] = "Neuen Tag hinzufügen" +L["Add new text"] = "Neuen Text hinzufügen" +L["Add Tags"] = "Tag hinzufügen" +L["Adds %s to the list of units to be modified when you change values in this tab."] = "Fügt %s zur Liste der Einheiten hinzu, die verändert werden, wenn Du die Werte in diesem Reiter änderst." +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "Fügt eine Leiste hinzu, die Dir die verbleibende Zeit für Deinen Ghul anzeigt (wird nur verwendet wenn Du keinen permanenten Ghul-Begleiter hast)." +L["Adds a bar indicating how much time is left on your mushrooms."] = "Fügt eine Leiste hinzu, wieviel Zeit eure Pilze noch haben." +L["Adds a bar indicating how much time is left on your Rune of Power."] = "Zusatzleiste zur Anzeige der Restzeit deiner Rune der Kraft." +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = "Zusatzleiste innerhalb der Lebensleiste die anzeigt wieviel Schaden absorbiert wird." +L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."] = "Fügt eine Leiste innerhalb der Gesundheitsleiste hinzu, die angibt, wie viel Heilung jemand schätzungsweise erhält." +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = "Fügt eine Leiste innerhalb der Lebensleiste ein, die anzeigt wieviel Heilung jemand benötigen wird." +L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."] = "Fügt eine Leiste innerhalb der Gesundheitsleiste hinzu, die anzeigt, wie viel Heilung absorbiert und nicht auf den Spieler angewendet wird." +L["Adds a mana bar to the player frame for elemental and enhancement shamans."] = "Fügt eine Mana-Leiste zum Spieler-Frame hinzu für Verstärker und Elementar Schamanen." +L["Adds a mana bar to the player frame for shadow priests."] = "Fügt eine Mana-Leiste zum Spieler-Frame hinzu für Schattenpriester." +L["Adds a Stagger bar for Brewmaster Monks."] = "Fügt eine Staffelungsleiste für Braumeistermönche hinzu." +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "Fügt eine weitere leere Leiste hinzu, in der Du zusätzlichen Text anzeigen lassen kannst." +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "Fügt eine weitere Manaleiste hinzu, um zu sehen wieviel Mana Du hast, während Du in Bär- oder Katzenform bist." +L["Adds rune bars and timers before runes refresh to the player frame."] = "Fügt eine Runenleiste und einen Timer, bevor die Runen aktualisiert werden, dem Spielerfenster hinzu." +L["Adds temporary enchants to the buffs for the player."] = "Fügt vorübergehende Verzauberungen zu den Stärkungszaubern des Spielers hinzu." +L["Adds totem bars with timers before they expire to the player frame."] = "Fügt dem Spielerfenster eine Totemleiste mit Timern hinzu, bevor diese ablaufen." +L["Advanced"] = "Erweitert" +L["Advanced tag management, allows you to add your own custom tags."] = "Erweiterte Tag-Verwaltung, erlaubt Dir das Hinzufügen von benutzerdefinierten Tags." +L["AFK"] = "AFK" +L["AFK status"] = "AFK-Status" +L["AFK timer"] = "AFK-Timer" +L["AFK:%s"] = "AFK:%s" +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "Nachdem Du \"Exportieren\" gedrückt hast, kannst Du den unten aufgeführten Code an andere weitergeben und sie erhalten exakt das selbe Layout." +L["Aggro"] = "Aggro" +L["All aura groups enabled for unit."] = "Alle Aurengruppen für Einheit aktivieren." +L["All Auras"] = "Alle Auren" +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."] = "Erlaubt Dir die Auren-Gruppe an einer anderen zu befestigen. Du kannst anschließend mit der Position auswählen, wo diese befestigt werden soll.|n|nVerwende dies, wenn Du das Aussehen der Standard UI klonen möchtest, bei dem Stärkungszauber und Schwächungszauber in seperaten Gruppen sind." +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."] = "Erlaubt dir das deaktivieren des Totems, indem du darauf rechtsklickst. |n|n Warnung: Innere Leisten für diese Einheit werden im Kampf nicht ihre Größe ändern, wenn die das aktivierst." +L["Allows you to enter a new aura group."] = "Erlaubt es dir eine neue Aura-Gruppe einzugeben." +L["Alpha to use for bar backgrounds."] = "Transparenz für Leistenhintergründe verwenden." +L["Alpha to use for bar."] = "Transparenz für Leiste verwenden." +L["Alt. Power"] = "Alt. Ressource" +L["Alt. Power bar"] = "Alt.-Ressourcen-Leiste" +L["Alternate power is used for things like quests and dungeons."] = "Alternative Kraft ist für Sachen benutzt wie Quests und Instanzen." +L["Alternate Spell Name"] = "Alternativer Zaubername" +L["Alternatively friendly spell to use to check range."] = "Alternativer freundlicher Zauber um Reichweite zu checken" +L["Ammo"] = "Munition" +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."] = "Menge der fehlenden Gesundheit, bei voller Gesundheit wird nichts angezeigt. Verwendet ein kurzes Format, -18.500 wird als -18.5k angezeigt, Werte unter 10.000 werden ganz normal angezeigt." +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."] = "Menge der fehlenden Energie, bei voller Energie wird nichts angezeigt. Verwendet ein kurzes Format, -13.850 wird als -13.8k angezeigt, Werte unter 10.000 werden ganz normal angezeigt." +L["Anchor point"] = "Ausrichtungspunkt" +L["Anchor to"] = "Ausrichten an" +L["Anchor to another frame"] = "Ausrichten an einem anderen Fenster" +L["Anchor to buffs"] = "Ausrichten an Stärkungszauber" +L["Anchor to debuffs"] = "Ausrichten an Schwächungszauber" +L["Ancient Kings bar"] = "Uralte Könige Leiste" +L["Any auras shown in this indicator will have their total stack displayed."] = "Jede Aura in diesem Indikator hat ihren kompletten Stappel angezeigt." +L["Aquatic"] = "aquatisch" +L["Arcane Charges"] = "Arkane Aufladungen" +L["Are you sure you want to delete this aura?"] = "Bist du dir sicher, dass du diese Aura löschen willst?" +L["Are you sure you want to delete this filter?"] = "Bist Du sicher, dass Du diesen Filter löschen möchtest?" +L["Are you sure you want to delete this indicator?"] = "Bist du dir sicher, dass du diesen Indikator löschen willst?" +L["Are you sure you want to delete this tag?"] = "Bist Du sicher, dass Du diesen Tag löschen möchtest?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "Bist Du sicher, dass Du diesen Text löschen möchtest? Alle Einstellungen hierfür werden gelöscht." +L["Arena"] = "Arena" +L["Arena Pet"] = "Arena Begleiter" +L["Arena Spec"] = "Arenaspezialisierung" +L["Arena Target"] = "Arenaziel" +L["Arena Target of Target"] = "Arena-Ziel-des-Ziels" +L["Arena ToT"] = "Arena-ZdZ" +L["Arenas"] = "Arenen" +L["Ascending"] = "Aufsteigend" +L["Assigned Role (DPS/Tank/etc)"] = "Zugewiesene Rolle (DPS/Tank/etc)" +L["Astral Power"] = "Astrale Macht" +L["Aura border style"] = "Rahmenstil der Aura" +L["Aura borders"] = "Aura Rahmen" +L["Aura Combo Points"] = "Aura Kombo Punkte" +L["Aura Filters"] = "Aurenfilter" +L["Aura filters"] = "Aura-Filter" +L["Aura group"] = "Auragruppe" +L["Aura groups"] = "Auragruppen" +L["Aura Groups"] = "Auragruppen" +L["Aura Indicators"] = "Auraindikatoren" +L["Aura indicators"] = "Aura-Indikatoren" +L["Aura name or spell ID"] = "Auraname oder Zauber-ID" +L["Aura types to filter"] = "Auren zum Filtern" +L["Auras"] = "Auren" +L["Auras matching a criteria will automatically show up in the indicator when enabled."] = "Wenn aktiviert, werden Auren, die ein Kriterium erfüllen, automatisch in dem Indikator angezeigt." +L["Automatic Auras"] = "Automatische Auren" +L["B"] = "B" +L["Background"] = "Hintergrund" +L["Background alpha"] = "Hintergrund-Transparenz" +L["Background color"] = "Hintergrundfarbe" +L["Background/border"] = "Hintergrund/Rahmen" +L["Bag indicator for master looters."] = "Taschen-Indikator für Plündermeister." +L["Bar alpha"] = "Leisten-Transparenz" +L["Bar color to use to show how much healing someone is about to receive."] = "Verwendete Balkenfarbe die anzeigt, wieviel Heilung jemand erhalten wird." +L["Bar spacing"] = "Leistenabstand" +L["Bar texture"] = "Leistentextur" +L["Bars"] = "Leisten" +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."] = "Leisten mit einer höheren oder niedrigeren Anordnung als die volle Größe Optionen, verwenden die gesamte Breite des Einheitenfensters.|n|nLeistenanordnungen zwischen diesen Zwei Nummern, werden neber dem Portrait angezeigt." +L["Battleground"] = "Schlachtfeld" +L["Battleground Pet"] = "Schlachtfeld-Begleiter" +L["Battleground Target"] = "Schlachtfeld-Ziel" +L["Battleground Target of Target"] = "Schlachtfeld-Ziel-des-Ziels" +L["Battlegrounds"] = "Schlachtfelder" +L["Bear"] = "Bär" +L["BG"] = "BG" +L["BG Pet"] = "BG-Begleiter" +L["BG Target"] = "BG-Ziel" +L["BG ToT"] = "BG-ZdZ" +L["Blacklist"] = "Schwarze Liste" +L["Blacklist filters"] = "Schwarze Liste Filter" +L["Blacklists"] = "Schwarze Listen" +L["Blizzard"] = "Blizzard" +L["Border"] = "Rahmen" +L["Border alpha"] = "Rahmen-Transparenz" +L["Border color"] = "Rahmenfarbe" +L["Border coloring of stealable, curable and dispellable auras."] = "Rahmenfarbe von stelbaren, heilbaren und bannbaren Auren." +L["Border highlighting"] = "Rahmenhervorhebung" +L["Border thickness"] = "Rahmendicke" +L["Boss"] = "Boss" +L["Boss Auras"] = "Bossauren" +L["Boss Debuffs"] = "Boss-Schwächungszauber" +L["Boss Target"] = "Boss-Ziel" +L["Boss Target of Target"] = "Boss-Ziel-des-Ziels" +L["Boss ToT"] = "Boss-ZdZ" +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."] = "Die Boss-Einheitenfenster sind nur für bestimmte Kämpfe, wie z.B. die Blutprinzen oder der Luftschiffkampf. Du wirst sie nicht bei jedem Bosskampf sehen." +L["Both"] = "Beide" +L["Bottom"] = "Unten" +L["Bottom Center"] = "Unten zentriert" +L["Bottom Left"] = "Unten links" +L["Bottom Right"] = "Unten rechts" +L["buff frames"] = "Stärkungszauber" +L["Buffs"] = "Stärkungszauber" +L["C"] = "C" +L["Cannot find any profiles named \"%s\"."] = "Es kann kein Profil mit dem Namen \"%s\" gefunden werden." +L["Cast"] = "Zauber" +L["Cast bar"] = "Zauberleiste" +L["Cast icon"] = "Zaubersymbol" +L["Cast interrupted"] = "Zauber unterbrochen" +L["Cast name"] = "Zaubername" +L["Cast time"] = "Zauberzeit" +L["Cast uninterruptible"] = "Zauber nicht unterbrechbar" +L["Casting"] = "Zaubern" +L["Cat"] = "Katze" +L["Category"] = "Kategorie" +L["Center"] = "Zentriert" +L["Changed profile to %s."] = "Profil auf %s geändert." +L["Changes the health bar to the color of any curable debuff."] = "Ändert die Farbe der Gesundheitsleiste zur Farbe jedes heilbaren Schwächungszaubers." +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = "Ändert die Farbe der Gesundheitsleiste zur festgelegten feindliche Farbe (Standardmäßig Rot) wenn eine Einheit Aggro zieht." +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."] = "Ändert dieses Widget in eine Leiste, womit Du in der Lage bist, die Höhe und Reihenfolge wie die der Gesundheits- oder Energieleisten zu verändern." +L["Channelling"] = "Kanalisieren" +L["Checking this will show the indciator on hostile units."] = "Ankaken, um den Indikator auf feindlichen Einheiten zu zeigen." +L["Checking this will show the indicator on friendly units."] = "Ankaken, um den Indikator auf verbündeten Einheiten zu zeigen." +L["Chi"] = "Chi" +L["Chi Points"] = "Chi-Punkte" +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = "Kinder-Einheiten können nicht verschoben werden. Du musst diese mit /shadowuf repositionieren." +L["Class"] = "Klasse" +L["Class (Smart)"] = "Klasse (Intelligent) " +L["Class color tag"] = "Tag für Klassenfarbe" +L["Class icon"] = "Klassensymbol" +L["Class Icon"] = "Klassensymbol" +L["Class icon for players."] = "Klassensymbol für Spieler." +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = "Klassenname ohne Farbe. Verwende [classcolor][class][close], wenn der Klassenname nach der jeweiligen Klasse eingefärbt werden soll." +L["Class Role"] = "Klassenrolle" +L["Class Specific"] = "Klassenspezifisch" +L["Class Timer"] = "Klassen-Timer" +L["Class/misc bars"] = "Klassen/Sonstige Leisten" +L["Classes"] = "Klassen" +L["Classification"] = "Klassifikation" +L["Classifications"] = "Klassifizierungen" +L["Clip"] = "Anheften" +L["Close color"] = "Farbe stoppen" +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = "Ende eines Farben-Tags. Verhindert das Anzeigen von Farben auf dem darauffolgenden Text." +L["Code"] = "Code" +L["Color by class"] = "Nach Klasse färben" +L["Color by reaction on"] = "Farbe durch Reaktionen auf" +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."] = "Farbcode, basierend auf der verbleibenden prozentualen Gesundheit der Einheit. Dies funktioniert auf dem selben Weg wie die Farbe der Gesundheitsleiste, jedoch nur für den Text anstatt für die gesamte Leiste." +L["Color code for general situation"] = "Farbcode für normale Situationen" +L["Color code for situation"] = "Farbcode für Situation" +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = "Farbcode für die Klasse. Benutze [classcolor][class][close] wenn der Klassentext nach der Klasse gefärbt werden soll." +L["Color code on aggro"] = "Farbcode bei Aggro" +L["Color health by"] = "Gesundheit färben nach" +L["Color on aggro"] = "Farbe bei Aggro" +L["Color on curable debuff"] = "Farbe bei heilbaren Debuff" +L["Color power by"] = "Färbe Power bei" +L["Color to use for health bars that are set to be colored by a static color."] = "Farbe der Gesundheitsleiste, die von einer festgesetzten Farbe bestimmt ist." +L["Color to use to show how much damage will be absorbed."] = "Verwendete Farbe die anzeigt, wieviel Schaden absorbiert wird." +L["Color to use to show how much healing will e absorbed."] = "Farbe, die benutzt wird, um zu zeigen, wie viel Heilung absorbiert wird." +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = "Farbe die angezeigt wird, wenn der Zauber nicht unterbrochen werden kann. Dies wird nur bei PvE Gegnern verwendet." +L["Color used when a cast is a channel."] = "Farbe die angezeigt wird, wenn der Zauber kanalisiert wird." +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "Farbe die angezeigt wird, wenn ein Zauber entweder vom Zauberer oder einer anderen Einheit unterbrochen wurde." +L["Color used when a cast is successfully finished."] = "Farbe die angezeigt wird, wenn ein Zauber erfolgreich gewirkt wurde." +L["Color used when an unit is casting a spell."] = "Farbe die angezeigt wird, wenn eine Einheit einen Zauber wirkt." +L["Colors"] = "Farben" +L["Column growth"] = "Spaltenanstieg" +L["Column spacing"] = "Spaltenabstand" +L["Combat alpha"] = "Kampf-Transparenz" +L["Combat fader"] = "Kampfausblender" +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."] = "Der Kampfausblender blendet alle unbenutzen Fenster aus, während diese inaktiv sind und blendet sie wieder ein wenn ein Kampf beginnt." +L["Combat Status"] = "Kampfstatus" +L["Combat text"] = "Kampftext" +L["Combat/resting status"] = "Kampf/Ruhe Status" +L["Combo points"] = "Kombopunkte" +L["Combo Points"] = "Kombo Punkte" +L["Configuration to specific unit frames."] = "Konfiguration für bestimmte Einheitenfenster." +L["Cooldown rings for"] = "Cooldown Ringe für" +L["Create"] = "Erstellen" +L["Creature type"] = "Kreaturen-Typ" +L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."] = "Kreaturen-Typ, gibt Teufelswache zurück, wenn es sich bei der Einheit um eine Teufelswache handel, Wolf wenn es sich um einen Wolf handelt und so weiter." +L["Crown indicator for group leader or assistants."] = "Kronen-Indikator für Gruppenleiter oder Assistent." +L["Cur/Max HP (Absolute)"] = "Akt/Max GP (Absolut)" +L["Cur/Max HP (Short)"] = "Akt/Max GP (Kurz)" +L["Cur/Max HP (Smart)"] = "Akt/Max GP (Intelligent)" +L["Cur/Max power (Absolute)"] = "Akt/Max Energie (Absolut)" +L["Cur/Max power (Druid)"] = "Akt/Max Energie (Druide)" +L["Cur/Max power (Druid/Absolute)"] = "Aktuelle/Max Power (Druide/absolut)" +L["Cur/Max power (Secondary)"] = "Aktuelle/Max Power (Sekundär)" +L["Cur/Max power (Secondary/Absolute)"] = "Aktuelle/Max Power (Sekundär/absolut)" +L["Cur/Max Power (Short)"] = "Akt/Max Energie (Kurz)" +L["Cur/Max PP (Smart)"] = "Akt/Max KP (Intelligent)" +L["Curable"] = "heilbar" +L["Curable Auras"] = "Heilbare Auren" +L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."] = "Aktuelle und maximale Gesundheit. Angegeben mit [curhp]/[maxhp], wenn die Einheit Tot oder Offline ist, wird dies stattdessen angezeigt." +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "Aktuelle und maximale Energie. Angegeben mit [curpp]/[maxpp]." +L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."] = "Aktuelle Gesundheit, verwendet ein kurzes Format, 11.500 wird als 11.5k angezeigt, Werte unter 10.000 werden normal angezeigt." +L["Current HP (Absolute)"] = "Aktuelle GP (Absolut)" +L["Current HP (Short)"] = "Aktuelle GP (Kurz)" +L["Current pet used by a battleground unit."] = "Aktuell benutzter Begleiter von Schlachtfeld Einheit." +L["Current power (Absolute)"] = "Aktuelle Energie (Absolut)" +L["Current power (Druid)"] = "Aktuelle Energie (Druide)" +L["Current power (Druid/Absolute)"] = "Aktuelle Energie (Druide/Absolut)" +L["Current power (Secondary)"] = "Aktuelle Power (Sekundär)" +L["Current power (Secondary/Absolute)"] = "Aktuelle Power (Sekundär/Absolut)" +L["Current Power (Short)"] = "Akutelle Energie (Kurz)" +L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."] = "Aktuelle Energie, verwendet ein kurzes Format, 12.750 wird als 12.7k angezeigt, Werte unter 10.000 werden normal angezeigt." +L["Current target of a battleground unit."] = "Aktuelles Ziel einer Schlachtfeld-Einheit." +L["Current target of target of a battleground unit."] = "Aktuelles Ziel des Ziels einer Schlachtfeld-Einheit." +L["Currently modifying"] = "Zurzeit ändernd" +L["Currently used in battlegrounds for showing flag carriers."] = "Aktuell auf Schlachtfelder genutzt, um Flaggenträger anzuzeigen." +L["Damage absorption (Absolute)"] = "Schadensabsorbtion (Absolut)" +L["Damage absorption (Short)"] = "Schadensabsorbtion (Kurz)" +L["Damage absorption/Name"] = "Schadensabsorbtion/Name" +L["Dark"] = "Dunkel" +L["Dead"] = "Tot" +L["Debuffs"] = "Schwächungszauber" +L["Decimal percent HP"] = "Dezimale prozentuale GP" +L["Default color"] = "Standardfarbe" +L["Default font color, any color tags inside individual tag texts will override this."] = "Standardfarbe, jeder Farbtag in einem einzelnen Tagtext überschreibt diesen." +L["Deficit/Unit Name"] = "Defizit/Einheiten Name" +L["Delete"] = "Löschen" +L["Delete filter"] = "Filter löschen" +L["Delete link"] = "Lösche Link" +L["Descending"] = "Absteigend" +L["Disable Auras by Class"] = "Deaktiviere Auren bei Klasse" +L["Disable Blizzard Cooldown Count"] = "Deaktiviere Blizzard Cooldown Zähler" +L["Disable event discovery"] = "Ereignis-Entdeckung deaktivieren" +L["Disable OmniCC Cooldown Count"] = "Deaktiviere OmniCC Cooldown Zähler" +L["Disable vehicle swap"] = "Fahrzeug-Wechsel deaktivieren" +L["Disabled"] = "Deaktiviert" +L["Disabled for %s."] = "Deaktiviere für %s." +L["Disabled in %s"] = "Deaktiviert in %s" +L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."] = "Deaktiviere gezeigte Cooldown Zähler in allen Shadow Unit Frame Auren" +L["Disables the unit frame from turning into a vehicle when the player enters one."] = "Verhindert, dass das Einheitenfenster sich in ein Fahrzeug ändert wenn der Spieler dies betritt." +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!."] = "Das Deaktivieren eines Moduls auf dieser Seite, deaktiviert es innerhalb %s. Deaktiviere kein Modul hier, wenn Du nicht möchtest, dass dies passiert!" +L["Disabling unit modules in various instances."] = "Einheiten-Module in verschiedenen Instanzen deaktivieren." +L["Dismissable Totem bars"] = "Zurückrufbare Totemleiste" +L["Dispellable/Stealable"] = "Bannbar/Stehlbar" +L["Display"] = "Anzeige" +L["Display enemy buffs using LibClassicDuration data."] = "Zeigt dir feindliche Buffs mit LibClassicDuration-Daten an." +L["DND"] = "DND" +L["DND:%s"] = "DND:%s" +L["Documentation"] = "Dokumentation" +L["Don't hide when empty"] = "Nicht verstecken wenn leer" +L["Don't use a filter"] = "Keinen Filter verwenden" +L["Down"] = "Runter" +L["Druid form"] = "Druidenform" +L["Druid form (Short)"] = "Druidenform (Kurz)" +L["Druid mana bar"] = "Druiden Manaleiste" +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."] = "Aufgrund von künstlichen Einheiten, sind Zauberleisten für %s nicht super effizient und nimmt meistens nur 0.10 Sekunden in Anspruch, bis das Wirken eines neuen Zaubers bemerkt wird." +L["Edge size"] = "Kantenlänge" +L["Edit tag"] = "Tag bearbeiten" +L["Editing %s"] = "Bearbeite %s" +L["Elite"] = "Elite" +L["Empty bar"] = "Leere Leiste" +L["Enable %s"] = "%s aktivieren" +L["Enable buffs"] = "Stärkungszauber aktivieren" +L["Enable debuffs"] = "Schwächungszauber aktivieren" +L["Enable enemy buff tracking"] = "Gegner Buff-Verfolgung aktivieren" +L["Enable for friendlies"] = "Aktiviere für Verbündete" +L["Enable for hostiles"] = "Aktiviere für Feinde" +L["Enable frequent updates"] = "Regelmäßige Updates aktivieren" +L["Enable indicator"] = "Indikator aktivieren" +L["Enable Indicators"] = "Aktiviere Indikatoren" +L["Enable temporary enchants"] = "Vorübergehende Verzauberungen aktivieren" +L["Enable units"] = "Einheiten aktivieren" +L["Enabled for %s."] = "Aktiviere für %s." +L["Enabled in %s"] = "Aktiviert in %s" +L["Enabled Units"] = "Aktiviere Einheiten" +L["Enables configuration mode, letting you move and giving you example frames to setup."] = "Aktiviert den Konfigurationsmodus, in dem Du Beispiel-Fenster zum Konfigurieren und verschieben erhälst." +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."] = "Das Aktivieren der erweiterten Einstellungen gibt Dir die Möglichkeit, mehr Optionen einzustellen. Dies ist vor allem für Leute gedacht, die jedes einzelne Detail optimieren möchten. Es sollte nicht standardmäßig aktiviert sein, da es die Anzahl der Optionen deutlich erhöht." +L["Energy"] = "Energie" +L["Enlarge auras for"] = "Vergrößere Aura für" +L["Error"] = "Fehler" +L["Events"] = "Ereignisse" +L["Events that should be used to trigger an update of this tag. Separate each event with a single space."] = "Ereignisse die verwendet werden sollen, um eine Aktualisierung für diesen Tag auszulösen. Trenne jedes Ereignis durch ein einzelnes Leerzeichen." +L["Everywhere else"] = "Überall anders" +L["Export"] = "Exportieren" +L["F"] = "F" +L["Fades out the unit frames of people who are not within range of you."] = "Lässt Einheiten, die sich nicht in Deiner Reichweite befinden, verblassen." +L["Failed to import layout, error:|n|n%s"] = "Importieren des Layouts fehlgeschlagen, Fehlermeldung:|n|n%s" +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "Laden von ShadowedUF_Options fehlgeschlagen, die Konfiguration kann nicht geöffnet werden. Fehlermeldung: %s" +L["Failed to save tag, error:|n %s"] = "Speichern des Tags fehlgeschlagen, Fehler:|n %s" +L["Female"] = "Weiblich" +L["Filter type"] = "Filter-Typ" +L["Filtering both buffs and debuffs"] = "Stärkungs- und Schwächungszauber filtern" +L["Filtering buffs only"] = "Nur Stärkungszauber filtern" +L["Filtering debuffs only"] = "Nur Schwächungszauber filtern" +L["Filters"] = "Filter" +L["Finished cast"] = "Gewirkte Zauber" +L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."] = "Markiere den Tag für ein regelmäßiges Aktualisieren. Dies aktualisiert den Tag nach einem Timer, unabhängig davon, wann ein Ereginis ausgeführt wird." +L["Flight"] = "Flug" +L["Flips coloring so the bar color is shown as the background color and the background as the bar"] = "Dreht das Einfärben herum, so dass die Leistenfarbe als Hintergrundfarbe und die Hintergrundfarbe als Leistenfarbe angezeigt wird." +L["Focus"] = "Fokus" +L["Focus Target"] = "Fokus Ziel" +L["Font"] = "Schrift" +L["Food"] = "Essen" +L["For configuring aura indicators on unit frames."] = "Zum einstellen von Aura-Indikatoren bei Unit Frames." +L["For target/focus"] = "Für Ziel/Fokus" +L["Forces a static color to be used for the background of all bars"] = "Erzwingt die Verwendung einer festgesetzten Farbe für die Hintergründe aller Leisten." +L["Frame"] = "Fenster" +L["Frame alpha when you are out of combat while having no target and 100% mana or energy."] = "Fenster-Transparenz, wenn Du nicht im Kampf, kein Ziel und 100% Mana oder Energie hast." +L["Frame alpha while this unit is in combat."] = "Fenster-Transparenz, während die Einheit im Kampf ist." +L["Frames"] = "Fenster" +L["Friendly"] = "Freundlich" +L["Fuel"] = "Treibstoff" +L["Full size after"] = "Volle Größe nach" +L["Full size before"] = "Volle Größe bevor" +L["Fury"] = "Jähzorn" +L["General"] = "Allgemein" +L["General configuration to all enabled units."] = "Allgemeine Konfiguration für alle aktivierten Einheiten." +L["General threat situation"] = "Normale Bedrohungssituation" +L["Ghost"] = "Geist" +L["Ghoul bar"] = "Ghoul Leiste" +L["Global"] = "Global" +L["Global configurating will let you mass enable or disable aura groups for multiple units at once."] = "Globale Konfiguration lässt dich alle Aurengruppen für mehrere Einheiten auf einmal aktivieren oder deaktivieren." +L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"] = "Gold Kontrollmarkierung - Aktiviert in diesem Gebiet / Graue Kontrollmarkierung - Deaktiviert in diesem Gebiet / Keine Kontrollmarkierung - Verwendet die Standard Einheiteneinstellungen" +L["Green (<30% HP)"] = "Grün (<30% HP)" +L["Group %d"] = "Gruppe %d" +L["Group by"] = "Gruppieren nach" +L["Group number"] = "Gruppennummer" +L["Group row spacing"] = "Abstand der Gruppenreihen" +L["Groups"] = "Gruppen" +L["Groups per row"] = "Gruppen per Reihe" +L["Groups to show"] = "Angezeigte Gruppen" +L["Growth"] = "Anstieg" +L["Guild name"] = "Gildenname" +L["Half health"] = "Halbe Gesundheit" +L["Has Aggro"] = "Hat Aggro" +L["Heal absorb"] = "Heilungsabsorption" +L["Heal Absorb (Absolute)"] = "Heilungsabsorption (Absolut)" +L["Heal Absorb (Short)"] = "Heilungsabsorption (Kurz)" +L["Heal absorbs"] = "Heilungsabsorptionen" +L["Healing absorb"] = "Heilungsabsorption" +L["Health"] = "Gesundheit" +L["Health bar"] = "Gesundheitsleiste" +L["Health bar color for friendly units."] = "Farbe der Gesundheitsleiste für freundliche Einheiten." +L["Health bar color for hostile units."] = "Farbe der Gesundheitsleiste für feindliche Einheiten." +L["Health bar color for neutral units."] = "Farbe der Gesundheitsleiste für neutrale Einheiten." +L["Health bar color for units with aggro."] = "Farbe der Lebensleiste für Einheiten die Aggro haben." +L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."] = "Farbe der Gesundheitsleiste für feindliche Einheiten, die nicht angegriffen werden können." +L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."] = "Übergangsfarbe, die benutzt wird für die Lebensanzeige von 100% auf 0% beim Spieler und wenn der Begleiter etwas unglücklich ist" +L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."] = "Übergangsfarbe, die benutzt wird für die Lebensanzeige von 100% auf 50% beim Spieler und wenn der Begleiter glücklich ist." +L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."] = "Übergangsfarbe, die benutzt wird für die Lebensanzeige von 50% auf 0% beim Spieler und wenn der Begleiter sehr unglücklich ist." +L["Health color"] = "Gesundheitsfarbe" +L["Health percent"] = "Gesundheit in Prozent" +L["Height"] = "Höhe" +L["Help"] = "Hilfe" +L["Hide %s"] = "%s verstecken" +L["Hide %s frames"] = "Verstecke %s Fenster" +L["Hide bar when empty"] = "Leere Leiste verstecken" +L["Hide Blizzard"] = "Blizzard ausblenden" +L["Hide in <=5-man raids"] = "Verstecke in <=5-Mann-Schlachtzügen" +L["Hide in >5-man raids"] = "Verstecke in >5-mann Schlachtzügen" +L["Hide in any raid"] = "In jedem Schlachtzug ausblenden" +L["Hide tooltips in combat"] = "Tooltips im Kampf ausblenden" +L["Hides the cast bar if there is no cast active."] = "Die Zauberleiste ausblenden, wenn kein Zauber aktiv ist." +L["Hides the power bar unless the class has mana."] = "Verstecke die Power-Leiste, außer die Klasse hat Mana." +L["Hiding and showing various aspects of the default UI such as the player buff frames."] = "Verstecke und zeige verschiedene Aspekte der Standard UI, wie zum Beispiel die Stärkungszauber des Spielers." +L["High"] = "Hoch" +L["High health"] = "Hohe Gesundheit" +L["Highlight"] = "Hervorhebung" +L["Highlight units that are "] = "Hebe Einheiten hervor, die ....." +L["Highlight units that are debuffed with something you can cure."] = "Einheiten mit einem Schwächungszauber den Du reinigen kannst, hervorheben." +L["Highlight units that are rare."] = "Hebe Einheiten hervor, die selten sind." +L["Highlight units that have aggro on any mob."] = "Einheiten die Aggro von irgendeinem Gegner haben, hervorheben." +L["Highlight units that you are targeting or have focused."] = "Einheiten die Du im Ziel oder Fokus hast, hervorheben." +L["Highlight units when you mouse over them."] = "Einheiten hervorheben, wenn Du die Maus über sie bewegst." +L["Holy power"] = "Heilige Kraft" +L["Holy Power"] = "Heilige Kraft" +L["Hostile"] = "Feind" +L["How close the frame should clip with the border."] = "Wie nah das Fenster am Rand angeheftet werden soll." +L["How far the background should be from the unit frame border."] = "Wie weit weg der Hintergrund vom Rahmen des Einheitenfensters entfernt sein soll." +L["How large the background should tile"] = "Die Größe der Kacheln des Hintergrundes" +L["How large the edges should be."] = "Wie groß die Ecken sein sollen." +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."] = "Wie viele Auren pro Reihen angezeigt werden sollen. Wenn hier bspw. Zwei eingetragen wird, werden Zwei Reihen soweit gefüllt wie per Reihen festgelegt wurde." +L["How many auras to show in a single row."] = "Wie viele Auren in einer einzelnen Zeile angezeigt werden sollen." +L["How many Chi points you currently have."] = "Aktuelle Chi Punkte die Du hast." +L["How many groups should be shown per row."] = "Wie viele Gruppen sollen pro Reihe angezeigt werden." +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!"] = "Wie viele Spieler der Einheit assistieren. Wenn Du dies beispielsweise auf Dich selbst setzt, wird angezeigt, wie viele Spieler Dein aktuelles Ziel anvisieren. Bei der Anzahl wirst Du selbst mit einbezogen!" +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!"] = "Wie viele Spieler in Deinem Schlachtzug diese Einheit anvisieren. Wenn Du dies beispielsweise auf Dich selbst setzt, wird angezeigt, wie viele Spieler Dich anvisieren. Bei der Anzahl wirst Du selbst mit einbezogen!" +L["How many rows total should be used, rows will be however long the per row value is set at."] = "Wie viele Reihen insgesamt verwendet werden sollen. Reihen werden allerdings nur so lange, wie der Reihen-Wert gesetzt wurde." +L["How many seconds a totem has left before disappearing."] = "Wie viele Sekunden einem Totem verbleiben, bevor es verschwinden." +L["How many seconds before a rune recharges."] = "Wie viele Sekunden verbleiben, bevor eine Rune wiederauflädt." +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."] = "Wie viele Sekunden zwischen den Updates liegen.|n[WARNUNG] Wenn die Häufigkeit auf 0 gesetzt wird, wird jedes einzelne Fenster neu aufgebaut. Wenn Du die regelmäßige Aktualisierung deaktivieren möchtest, setze es nicht auf 0." +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."] = "Der Anteil vom Fenster der von der Leiste eingenommen wird. Dieser Wert ist gewichtet, um so höher der Wert, desto größer die Leiste." +L["How much spacing should be between each new row of groups."] = "Wie groß der Abstand zwischen jeder neuen Reihe von Gruppen sein soll." +L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."] = "Wie viel Abstand zwischen allen Leisten innerhalb eines Einheitenfensters vorausgesetzt werden soll. Negative Werte bewegen diese weiter auseinander, positive Werte bringen sie hingegen näher zusammen. 0 für keinen Abstand." +L["How much weight this should use when figuring out the total text width."] = "Wie viel Masse verwendet werden soll, wenn die gesamte Textbreite dargestellt wird." +L["How the frames should grow when a new column is added."] = "Wie die Fenster anwachsen sollen wenn eine neue Spalte hinzugefügt wird." +L["How the rows should grow when new group members are added."] = "Wie die Reihen anwachsen sollen wenn neue Gruppenmitglieder hinzugefügt werden." +L["How you want this aura to be anchored to the unit frame."] = "Wie diese Aura an den Einheitenfenster ausgerichtet sein soll." +L["Icon Size"] = "Symbolgröße" +L["If multiple auras are shown in the same indicator, the higher priority one is shown first."] = "Wenn mehrere Auren im selben Indikator gezeigt werden, ist das mit der höheren Priorität das erste gezeigte." +L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."] = "Wenn ein Name eingegeben wird, muss dieser exakt sein, da die Groß- und Kleinschreibung beachtet wird. Alternativ können Sie stattdessen die Zauber-ID verwenden." +L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."] = "Wenn die Einheit ein Absorbtionsschild besitzt, wird der absolute Absorbtionswert angezeigt, andernfalls der Einheitenname." +L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."] = "Wenn die Einheit eingehende Heilung erhält, wird die gesamte Menge der eingehenden Heilung angezeigt. Anderenfalls wird der Name der Einheit angezeigt." +L["If the unit is a player then class is returned, if it's a NPC then the creature type."] = "Wenn die Einheit ein Spieler ist wird die Klasse angezeigt, wenn es sich um einen NPC handelt, siehst du die Art der Kreatur." +L["If the unit is a player then race is returned, if it's a NPC then the creature type."] = "Wenn die Einheit ein Spieler ist, wird die Rasse angezeigt. Wenn es sich um einen NPC handelt, siehst du die Art der Kreatur." +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."] = "Wenn Sie dies nicht tun, können Sie keine Kombinationspunktfunktionen (Chi, Heilige Kraft, Combo Punkte, Aura-Punkte usw.) verwenden, bis Sie dies tun." +L["Imp & Dreadstalker bar"] = "Wichtel & Schreckenspirscher Leiste" +L["Import"] = "Import" +L["Import unit frame positions"] = "Positionen der Einheitenfenster importieren" +L["Import visibility settings"] = "Sichtbarkeitseinstellungen importieren" +L["In range alpha"] = "In-Reichweite-Transparenz" +L["Inactive alpha"] = "Inaktiv-Transparenz" +L["Incoming absorb"] = "Eingehende Absorption" +L["Incoming absorbs"] = "Eingehende Absorptionen" +L["Incoming heal"] = "Eingehende Heilung" +L["Incoming heal (Absolute)"] = "Eingehende Heilung (Absolut)" +L["Incoming heal (Percent)"] = "Eingehende Heilung (Prozent)" +L["Incoming heal (Short)"] = "Eingehende Heilung (Kurz)" +L["Incoming heal/Name"] = "Eingehende Heilung/Name" +L["Incoming heals"] = "Eingehende Heilungen" +L["Index"] = "Index" +L["Indicator color"] = "Indikatorenfarbe" +L["Indicator for the current pet happiness."] = "Indikator für die aktuelle Begleiter-Glücklichkeit." +L["Indicator name"] = "Indikatorenname" +L["Indicator this aura should be displayed in."] = "Indikator, in welchem die Aura gezeigt werden soll." +L["Indicators"] = "Indikatoren" +L["Insanity"] = "Wahnsinn" +L["Inset"] = "Eingefügt" +L["Inside Bottom Left"] = "Innen Unten Links" +L["Inside Bottom Right"] = "Innen Unten Rechts" +L["Inside Center"] = "Innen - Zentriert" +L["Inside Center Left"] = "Innen - Zentriert links" +L["Inside Center Right"] = "Innen - Zentriert rechts" +L["Inside Top Left"] = "Innen - Oben links" +L["Inside Top Right"] = "Innen - Oben rechts" +L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."] = "Anstatt eine durchgehende Farbe im Indikator anzuzeigen, wird das Symbol der Aura angezeigt." +L["Interrupted"] = "Unterbrochen" +L["Invalid interval entered, must be a number."] = "Ungültigen Interval eingegeben, muss eine Zahl sein." +L["Invalid spell \"%s\" entered."] = "Ungültiger Zauber \"%s\" eingegeben." +L["Invert colors"] = "Farben umkehren" +L["Layout manager"] = "Layout-Manager" +L["Leader / Assist"] = "Leiter / Assistent" +L["Left"] = "Links" +L["Left Bottom"] = "Links unten" +L["Left Center"] = "Links zentriert" +L["Left text"] = "Linker Text" +L["Left Top"] = "Links oben" +L["Let's you modify the base font size to either make it larger or smaller."] = "Lässt Dich die Größe der Grundschrift ändern, entweder um sie größer oder kleiner zu machen." +L["Level"] = "Level" +L["Level %s - %s: %s/%s (%.2f%% done)"] = "Level %s - %s: %s/%s (%.2f%% erhalten)" +L["Level %s - %s: %s/%s (%.2f%% done), %s rested."] = "Level %s - %s: %s/%s (%.2f%% erhalten), %s erholt." +L["Level (Colored)"] = "Level (Farbig)" +L["Level without any coloring."] = "Level ohne jegliche Einfärbung." +L["Light"] = "Hell" +L["Link"] = "Link" +L["Link from"] = "Link von" +L["Link to"] = "Link zu" +L["Linked spells"] = "Verlinkte Zauber" +L["Lock frames"] = "Sperren" +L["Locks the unit frame positionings hiding the mover boxes."] = "Sperrt die Einheitenfenster und versteckt die Bewegungsboxen." +L["Low health"] = "Niedrige Gesundheit" +L["M"] = "M" +L["MA ToT"] = "MA ToT" +L["Maelstrom"] = "Maelstrom" +L["Main Assist"] = "Hauptassistent" +L["Main Assist Target"] = "Hauptassistenten Ziel" +L["Main Assist Target of Target"] = "Hauptassistent Ziel vom Ziel" +L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."] = "Hauptassistenten sind vom Blizzard Hauptassistentensystem oder von Mods, die das benutzen, gesetzt." +L["Main Tank"] = "Haupttank" +L["Main Tank Target"] = "Haupttank Ziel" +L["Main Tank Target of Target"] = "Haupttank Ziel des Ziel" +L["Main Tank's are set through the Raid frames, or through selecting the Tank role."] = "Haupttanks sind durch die Schlachtzugsframes oder durch das auswählen der Tankrolle gesetzt." +L["Male"] = "Männlich" +L["Mana"] = "Mana" +L["Manage Aura Filters"] = "verwalte Aurenfilter" +L["Management"] = "Verwaltung" +L["Manual position"] = "Manuelle Position" +L["Master Looter"] = "Plündermeister" +L["Max columns"] = "Max. Spalten" +L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."] = "Max. Gesundheit, verwendet ein kurzes Format, 17.750 wird als 17.7k angezeigt, Werte unter 10.000 werden normal angezeigt." +L["Max HP (Absolute)"] = "Max. GP (Absolut)" +L["Max HP (Short)"] = "Max. GP (Kurz)" +L["Max power (Absolute)"] = "Max. Energie (Absolut)" +L["Max power (Short)"] = "Max. Energie (Kurz)" +L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."] = "Max. Energie, verwendet ein kurzes Format, 16.000 wird als 16k angezeigt, Werte unter 10.000 werden normal angezeigt." +L["Max rows"] = "Max. Reihen" +L["Medium"] = "Medium" +L["Minion"] = "Kreatur" +L["Miscellaneous"] = "Verschiedenes" +L["Missing HP (Short)"] = "Fehlende GP (Kurz)" +L["Missing power (Short)"] = "Fehlende Energie (Kurz)" +L["Monochrome Outline"] = "Einfarbige Kontur" +L["Moonkin"] = "Mondkin" +L["MT ToT"] = "MT ToT" +L["Mushroom bar"] = "Pilz-Leiste" +L["Mushrooms"] = "Pilze" +L["Name"] = "Name" +L["Name (Abbreviated)"] = "Name (Abgekürzt)" +L["Name of a friendly spell to check range."] = "Freundlicher Zauber um Reichweite zu checken" +L["Neutral"] = "Neutral" +L["Never (Disabled)"] = "Nie (Deaktiviert)" +L["New aura group"] = "Neue Auren-Gruppe" +L["New filter"] = "Neuer Filter" +L["None"] = "Keine" +L["None (Disabled)"] = "Nichts (Deaktiviert)" +L["NPCs only"] = "Nur NPCs" +L["Offline"] = "Offline" +L["Offline timer"] = "Offline-Timer" +L["Ok"] = "Ok" +L["On %s units"] = "bei %s Einheiten" +L["On aggro"] = "Bei Aggro" +L["On curable debuff"] = "Bei entfernbaren Schwächungszauber" +L["On elite mobs"] = "Bei Elite Gegnern" +L["On Friendly Units"] = "Bei freundlichen Einheiten" +L["On Hostile Units"] = "Bei feindlichen Einheiten" +L["On mouseover"] = "Bei MouseOver" +L["On rare mobs"] = "Bei seltenen Gegnern" +L["Only active this aura inside an indicator if the group member does not have the aura."] = "Aktiviere diese Aura nur innerhalb eines Indikators, wenn das Gruppenmitglied diese Aura nicht hat." +L["Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras."] = "Wenden Sie die ausgewählten Filter nur auf Buffs bei befreundeten Einheiten und auf Debuffs bei feindlichen Einheiten an und zeigen Sie ansonsten alle Auren an." +L["Only auras you specifically cast will be shown."] = "Es werden nur Auren angezeigt, die Sie gewirkt haben." +L["Only show if missing"] = "Nur zeigen, wenn es fehlt" +L["Only show self cast auras"] = "Zeige nur selbst gezauberte Auren" +L["Only show when mana"] = "Zeige nur wenn Mana verfügbar" +L["Or you can set a position manually"] = "Oder Du kannst eine Position manuell festlegen." +L["Order"] = "Reihenfolge" +L["Other Party/Phase Status"] = "Andere Gruppe/Phase Status" +L["Out of range alpha"] = "Außer-Reichweite-Transparenz" +L["Outline"] = "Kontur" +L["Outside bar limit"] = "Kontur Leistenlimit" +L["Override background"] = "Hintergrund überschreiben" +L["Override color"] = "Farbe überschreiben" +L["Override list"] = "Überschreibungsliste" +L["Override list filters"] = "Überschreibungsliste Filter" +L["Override lists"] = "Überschreibungslisten" +L["Pain"] = "Schmerz" +L["Party"] = "Gruppe" +L["Party frames are hidden while in a raid group with more than 5 people inside."] = "Die Gruppenfenster werden ausgeblendet, während Du Dich in einem Schlachtzug mit mehr als 5 Personen befindest." +L["Party frames are hidden while in any sort of raid no matter how many people."] = "Gruppenfenster werden ausgeblendet, innerhalb eines Schlachtzugs, unabhängig davon wie viele Leute sich darin befinden." +L["Party instances"] = "Gruppen Instanzen" +L["Party Pet"] = "Gruppenbegleiter" +L["Party Target"] = "Gruppen Ziel" +L["Party Target of Target"] = "Gruppe Ziel des Ziels" +L["Party ToT"] = "Gruppen ToT" +L["Per column"] = "Per Spalte" +L["Per row"] = "Per Reihe" +L["Percent HP"] = "Prozent GP" +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."] = "Prozentanzeige des durch Heilung erhaltenen Lebens. Wenn ein Spieler z.B. 100.000 Leben hat und 15.000 Leben durch Heilung erhält, werden 15% angezeigt." +L["Percent power"] = "Energie Prozent" +L["Percentage of width the portrait should use."] = "Prozentsatz der Breite, der für das Portrait verwendet werden soll." +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."] = "Prozentanteil dafür, wie weit der Balken für absorbierte Heilung den Unitframe verlassen kann. 130% bedeutet, er kann ihn um 30% verlassen, 100% bedeutet, er wird den Frame nie verlassen." +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."] = "Wie weit die Leiste \"Eingehende Heilung\" aus dem Frame herausragen kann. (In Prozent vom Originalframe) 130% heißt, sie kann 30% herausragen, 100% heißt sie geht nicht darüber hinaus." +L["Pet"] = "Begleiter" +L["Pet Battle"] = "Haustierkampf" +L["Pet Happiness"] = "Begleiter-Glücklichkeit" +L["Pet Target"] = "Begleiter Ziel" +L["Player"] = "Spieler" +L["player alt. power"] = "Spieler alt. Energie" +L["player cast bar"] = "Spieler Zauberleiste" +L["Player Class"] = "Spielerklasse" +L["player power frames"] = "Spieler Power Frames" +L["Player threat"] = "Spieler Bedrohung" +L["Players only"] = "Nur Spieler" +L["Players will be colored by class."] = "Spieler in Klassenfarben anzeigen." +L["Point"] = "Punkt" +L["Portrait"] = "Portrait" +L["Portrait type"] = "Portrait-Typ" +L["Position"] = "Position" +L["Positioning"] = "Positionierung" +L["Power"] = "Energie" +L["Power bar"] = "Energieleiste" +L["Power Type"] = "Ressourcentyp" +L["Prevents unit tooltips from showing while in combat."] = "Verhindert das Einblenden von Einheiten-Tooltips im Kampf." +L["Priest mana bar"] = "Priester Mana Leiste" +L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."] = "Primär bedeutet, dass das Einfärben der Gesundheitsleiste, Farbe bei Aggro und Farbe bei Reaktion überschrieben wird, wenn dies erforderlich ist." +L["Prioritize buffs"] = "Stärkungszauber priorisieren" +L["Priority"] = "Wichtigkeit" +L["Programming in Lua"] = "Programmierung in Lua" +L["PvP Flag"] = "PvP-Markierung" +L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."] = "PVP-Markierung, Horde für Horde markierte PVPler und Allianz für Allianz markierte PVPler." +L["PvP Flags"] = "PVP Flaggen (if you mean the flags to carry like in warsong gulch)" +L["PVP timer"] = "PVP-Timer" +L["PVP:%s"] = "PVP:%s" +L["Quest Boss"] = "Quest Boss" +L["Race"] = "Rasse" +L["Race (Smart)"] = "Rasse (Intelligent)" +L["Rage"] = "Wut" +L["Raid"] = "Schlachtzug" +L["Raid assisting unit"] = "Schlachtzugsassistenten Einheit" +L["Raid frames are hidden while in a raid group with 5 or less people inside."] = "Schlachtzugsfenster sind versteckt in einer Gruppe mit 5 oder weniger Mitgliedern." +L["Raid instances"] = "Schlachtzugsinstanzen" +L["Raid Misc"] = "Raid Verschieden" +L["Raid pet"] = "Schlachtzugsbegleiter" +L["Raid Role"] = "Schlachtzugsrolle" +L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."] = "Schlachtzugrollen-Indikator, fügt ein Schild-Indikator für Haupttanks und ein Schwertsymbol für Hauptassistenten hinzu." +L["Raid Target"] = "Schlachtzug Ziel" +L["Raid target indicator."] = "Schlachtzugziel-Indikator" +L["Raid targeting unit"] = "Schlachtzugziel Einheit" +L["Range Checker"] = "Reichweiter Checker" +L["Range indicator"] = "Reichweiten-Indikator" +L["Rare"] = "Selten" +L["Rare Elite"] = "Selten Elite" +L["Rare indicator"] = "Rar-Indikator" +L["Rather than bars filling from left -> right, they will fill from bottom -> top."] = "Statt dass die Leisten sich von Links nach Rechts füllen, füllen sie sich von Unten nach Oben." +L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."] = "Reaktions Farbcode, verwende [reactcolor][name][close] um den Einheitenname durch seine Reaktion zu färben." +L["Reaction color tag"] = "Reaktionsfarbe" +L["Ready Status"] = "Bereitschaftstatus" +L["Ready status of group members."] = "Bereitschaftscheck der Gruppenmitglieder." +L["Red (>70% HP)"] = "Rot (>70% HP)" +L["Relative point"] = "Relativer Punkt" +L["Resources"] = "Quellen" +L["Resurrect Status"] = "Wiederbelebungsstatus" +L["Returns + if the unit is an elite or rare elite mob."] = "Gibt ein + wieder, wenn es sich bei der Einheit um einen Elite- oder raren Elite-Mob handelt." +L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."] = "Gibt einen Farbcode für die Bedrohungssituation mit Deinem Ziel wieder: Rot für Aggro, Orange für hohe Bedrohung und Gelb für Vorsichtig." +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."] = "Gibt einen Farbcode für Deine allgemeine Bedrohungssituation bei allen Einheiten wieder: Rot für Aggro, Orange für hohe Bedrohung und Gelb für vorsichtig sein." +L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."] = "Gibt für Dein aktuelles Ziel die Bedrohung in einem Prozentsatz wieder. Immer zwischen 0 - 100%." +L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."] = "Gibt die aktuelle Gesundheit als Prozentsatz wieder (wenn die Einheit tot oder offline ist wird dies angezeigt)." +L["Returns current power as a percentage."] = "Gibt die aktuelle Energie als Prozentsatz wieder." +L["Returns Rare if the unit is a rare or rare elite mob."] = "Gibt Rar wieder, wenn es sich bei der Einheit um einen Elite- oder raren Elite-Mob handelt." +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."] = "Gibt einen Text wieder, basierend auf der allgemeinen Bedrohungssituation der Einheiten: Aggro für Aggro, Hoch für nah am Aggro bekommen und Mittel als eine allgemeine Warnung vorsichtig zu sein.|nDies kann nicht für Einheiten von Ziel des Ziels oder Fokus Ziel verwendet werden." +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."] = "Gibt einen Text wieder, basierend auf Deiner Bedrohungssituation mit deinem Ziel: Aggro für Aggro, Hoch für nah am Aggro ziehen und Mittel als allgemeine Warnung." +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."] = "Gibt einen Text wieder, basierend auf Deiner Bedrohungssituation mit deinem Ziel: Aggro für Aggro, Hoch für nah am Aggro bekommen und Mittel als eine allgemeine Warnung vorsichtig zu sein." +L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."] = "Gibt einen Farbcode wieder, basierend auf dem Level der Einheiten verglichen mit Deinem. Wenn Du sie nicht angreifen kannst, wird keine Farbe ausgegeben." +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."] = "Gibt einen Farbcode für die allgemeine Bedrohungssituation der Einheiten wieder: Rot für Aggro, Orange für hohe Bedrohung und Gelb für Vorsichtig.|nDies kann nicht für Einheiten von Ziel des Ziels oder Fokus Ziel verwendet werden." +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."] = "Gibt die Bedrohung in einem Prozentsatz für die Einheit wieder. Wenn Du dies auf ein Gruppenmitglied setzt, würdest Du in Prozenten sehen, wie nah sie sind Aggro irgendeines feindlichen Gegners zu erhalten. Immer zwischen 0 - 100%.|Dies kann nicht bei Einheiten von Ziel des Ziels oder Fokus Ziel verwendet werden." +L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."] = "Gibt die aktuelle Form der Einheit wieder, wenn sie ein Druide ist. Katze für Katzenform, Moonkin für Moonkin und so weiter." +L["Returns the units sex."] = "Gibt das Geschlecht der Einheit wieder." +L["Reverse fill"] = "Umgekehrt füllen" +L["Right"] = "Rechts" +L["Right Bottom"] = "Rechts unten" +L["Right Center"] = "Rechts zentriert" +L["Right text"] = "Rechter Text" +L["Right Top"] = "Rechts oben" +L["Role the unit is playing."] = "Rolle, die diese Einheit spielt." +L["Row growth"] = "Reihenanstieg" +L["Row offset"] = "Reihen-Verschiebung" +L["Rune bar"] = "Runenleiste" +L["Rune of Power"] = "Rune der Kraft" +L["Rune Timer"] = "Runen-Timer" +L["Runes"] = "Runen" +L["Runic Power"] = "Runenmacht" +L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."] = "Dasselbe wie [color:sit], außer das es nur Rot ausgibt, wenn Du Aggro hast, anstatt einem Übergang von Gelb -> Orange -> Rot." +L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."] = "Dasselbe wie [unit:color:sit], außer das es nur Rot ausgibt, wenn die Einheit Aggro hat, anstatt einem Übergang von Gelb -> Orange -> Rot." +L["Scale"] = "Skalierung" +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."] = "Vergrößerung für eigene oder raubbare Auren. Werte über 100% sind größer als Standard, Werte kleiner als 100% sind kleiner als Standard." +L["Scaled aura size"] = "Skalierte Aura Größe" +L["Scaled threat percent"] = "Skaliert die Bedrohungsprozente" +L["Screen"] = "Bildschirm" +L["Search"] = "Suche" +L["Search tags"] = "Tags suchen" +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."] = "Siehe unten in der Dokumentation für Informationen und Beispiele für das Erstellen von Tags. Wenn Du nur einfache Lua oder WoW API Informationen möchtest, siehe Dir die Programmieren in Lua und WoW Programmieren Links an." +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."] = "Wähle die Einheiten aus, die Du bearbeiten möchtest. Alle Einstellungen die verändert werden, werden bei den Einheiten die Du ausgewählt hast verändert. Wenn Du bestimmte Einstellungen für Schlachtzug/Gruppen Einheiten ausrichten oder verändern möchtest, musst Du dies durch ihre Einstellungen tun.|n|nUmschalt-Klick auf eine Einheit, um alle aus- oder abzuwählen." +L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."] = "Wähle einen Tagtext aus dem linken Menü, um die Tags zu verändern. Breite kürzen, Größenbestimmung und Verschieben kann im aktuellen Menü durchgeführt werden." +L["Separate raid frames"] = "Seperate Schlachtzugsfenster" +L["Sex"] = "Geschlecht" +L["Shadow Orbs"] = "Schattenkugeln" +L["Shaman mana bar"] = "Schamanen Mana Leiste" +L["Short classification"] = "Kurze Klassifizierung" +L["Short elite indicator"] = "Kurzer Elite-Indikator" +L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."] = "Kurze Version von [druidform], K = Katze, B = Bär, F = Flug und so weiter." +L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."] = "Verkürzte Schadensabsorbtion, wenn 13.000 Schaden absorbiert werden, werden 13k angezeigt." +L["Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k."] = "gekürzter Heilungsabsorptionswert, wenn 17.000 Heilung absobiert werden wird es 17k anzeigen." +L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."] = "Eingehenden Heilwert abkürzen, wenn 13.000 Heilung eintreffen, wird 13k angezeigt." +L["Show a background behind the bars with the same texture/color but faded out."] = "Zeige einen Hintergrund hinter den Leisten mit der selben Textur/Farbe, allerdings verblassend." +L["Show any other auras"] = "Zeige jede andere Aura" +L["Show as bar"] = "Zeige als Leiste" +L["Show aura duration"] = "Zeige Aura Dauer" +L["Show aura icon"] = "Zeie Aura Symbol" +L["Show auras stack"] = "Zeige Aura Stappel" +L["Show background"] = "Zeige Hintergrund" +L["Show boss debuffs"] = "Zeige Boss Debuffs" +L["Show buffs before debuffs when sharing the same anchor point."] = "Zeige Stärkungszauber vor Schwächungszauber, wenn sie sich den Ausrichtungspunkt teilen." +L["Show cast name"] = "Zeige Zaubername" +L["Show cast time"] = "Zeige Zauberzeit" +L["Show castable on other auras"] = "Zeige \"auf andere anwendbar\" Auren" +L["Show casted by boss"] = "Zeige vom Boss verursacht" +L["Show curable debuffs"] = "Zeige heilbare Debuffs" +L["Show curable/removable auras"] = "Zeige heilbare/entfernbare Auren" +L["Show Heal Absorbs"] = "Zeige Heilungsabsorptionen" +L["Show icon durations"] = "Zeige Symboldauer" +L["Show incoming absorbs"] = "Zeige Absorbtion" +L["Show incoming heals"] = "Zeige eingehende Heilungen." +L["Show inside"] = "Zeige innen" +L["Show party as raid"] = "Zeige Gruppe als Schlachtzug" +L["Show player in party"] = "Zeige Spieler in einer Gruppe" +L["Show your auras"] = "Zeige deine Auren" +L["Shows a bar for alternate power info (used in some encounters)"] = "Zeigt eine Leiste für alternative Energie Informationen (wird bei einigen Kämpfen verwendet)" +L["Shows a cooldown wheel on the indicator with how much time is left on the aura."] = "Zeigt ein Cooldown Rad auf dem Inidkator mit wie viel Zeit noch der Aura verbleibt." +L["Shows AFK, DND or nothing depending on the units away status."] = "Zeigt AFK, DND oder nichts abhängig vom aktuellen Status der Einheit." +L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."] = "Zeigt Kampf-Feedback, die letzte erhaltene Heilung der Einheit, letzter Treffer, den sie verfehlt, widerstanden, ausgewischen ist und so weiter." +L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."] = "Zeigt aktuelle und maximale Gesundheit in absoluter Form. 17.500 Gesundheit wird auch als 17.500 angezeigt." +L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."] = "Zeigt aktuelle und maximale Energie in absoluter Form, 18.000 Energie werden auch als 18.000 Energie angezeigt." +L["Shows current group number of the unit."] = "Zeige aktuelle Gruppennummer des Spielers." +L["Shows current health value in absolute form meaning 15000 health is shown as 15000."] = "Zeigt aktuelle Gesundheit in absoluter Form, 15.000 Gesundheit wird als 15.000 Gesundheit angezeigt." +L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."] = "Zeigt aktuelle Energie in absoluter Form, 15.000 Energie werden auch als 15.000 Energie angezeigt." +L["Shows debuffs cast by a boss."] = "Zeigt Debuffs verursacht durch einen Boss" +L["Shows debuffs that you can cure."] = "Zeigt Debuffs, die du heilen kannst." +L["Shows how long an unit has been AFK or DND."] = "Zeige wie lange ein Spieler AFK oder DND ist." +L["Shows how long an unit has been offline."] = "Zeige wie lange ein Spieler offline ist." +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."] = "Zeigt wann Deine PVP-Markierung ausläuft. Wird nicht angezeigt wenn die Markierung manuell eingeschaltet wurde oder Du Dich in einem feindlichen Gebiet befindest.|n|nDies funktioniert nur für Dich selbst, Du kannst die verbleibende Zeit Deiner Gruppen- oder Schlachtzugsmitglieder nicht einsehen." +L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."] = "Zeigt die maximale Gesundheit in absoluter Form, 14.000 Gesundheit werden auch als 14.000 angezeigt." +L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."] = "Zeigt die maximale Energie in absoluter Form, 13.000 Energie werden auch als 13.000 angezeigt." +L["Shows Offline, Dead, Ghost or nothing depending on the units current status."] = "Zeigt Offline, Tot, Geist oder nichts abhängig vom aktuellen Status der Einheit." +L["Shows that a NPC is a boss for a quest."] = "Zeigt an dass ein NPC ein Boss für eine Quest ist." +L["Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000."] = "Zeigt den absolut gestaffelten Schaden, wenn 16.000 Schaden ist gestaffelt, zeigt es 16k." +L["Shows the current staggered damage, if 12,000 damage is staggered, shows 12k."] = "Zeigt den aktuell gestaffelten Schaden, wenn 12.000 Schaden ist gestaffelt, zeigt es 12k." +L["Show's the units guild name if they are in a guild."] = "Den Gildennamen der Einheiten anzeigen, wenn sie sich in einer Gilde befinden." +L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."] = "Zeigt die Gesundheit der Einheit als Prozentsatz, gerundet auf die erste Dezimalstelle (z.B. werden 61 von 110 GP als 55.4% angezeigt)." +L["Shows what kind of pet the unit is for pet battles."] = "Zeigt für Haustierkämpfe was für ein Haustier die Einheit ist." +L["Shows when a party member is in a different phase or another group."] = "Zeigt an ob ein Gruppenmitglied in einer anderen Phase oder einer anderen Gruppe ist." +L["Simple aura filtering by whitelists and blacklists."] = "Einfache Auren-Filterung durch Ausnahme- und Schwarze Listen." +L["Size"] = "Größe" +L["Smart level"] = "Intelligentes Level" +L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."] = "Intelligentes Level, gibt Boss für Bosse wieder, +50 für ein Level 50 Elite-Mob oder nur 80 für ein Level 80." +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."] = "Intelligente Nummern formatiert für [curmaxhp], Nummern unter 1.000.000 verbleiben wie sie sind, Nummern über 1.000.000 verwenden die kurze Version wie zum Beispiel 1m." +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."] = "Intelligente Nummern formatiert für [curmaxpp], Nummern unter 1.000.000 verbleiben wie sie sind, Nummern über 1.000.000 verwenden die kurze Version wie zum Beispiel 1m." +L["Sort method"] = "Sortierungsmethode" +L["Sort order"] = "Sortierungsanordnung" +L["Sorting"] = "Sortierung" +L["Soul Shards"] = "Seelensplitter" +L["Soul shards"] = "Seelensplitter" +L["Spacing"] = "Abstand" +L["Spacing between each row"] = "Abstand zwischen jeder Reihe" +L["Spell ID %s"] = "Zauber-ID %s" +L["Spell Name"] = "Zaubername" +L["Spell Name/ID"] = "Zauber Name/ID" +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."] = "Teilt die Schlachtzugsfenster in einzelne Fenster für jede Schlachtzugsgruppe, anstatt ein einzelnes Fenster.|nBEACHTE! Du kannst nicht jedes Gruppenfenster einzeln verschieben, aber wie sie ansteigen sollen, durch die Spalten und Reihenanstieg Einstellungen." +L["Stagger"] = "Staffelung" +L["Stagger (Monk)"] = "Staffelung (Mönch)" +L["Stagger (Monk/Absolute)"] = "Staffelung (Mönch/Absolut)" +L["Stagger bar"] = "Staffelungsleiste" +L["Stagger bar color when the staggered amount is <30% of your HP."] = "Farbe der Staffelungsleiste, wenn der gestaffelte Schaden <30% des Lebens beträgt." +L["Stagger bar color when the staggered amount is >30% of your HP."] = "Farbe der Staffelungsleiste, wenn der gestaffelte Schaden >30% des Lebens beträgt." +L["Stagger bar color when the staggered amount is >70% of your HP."] = "Farbe der Staffelungsleiste, wenn der gestaffelte Schaden >70% des Lebens beträgt." +L["Static"] = "Statisch" +L["Statue"] = "Statue" +L["Statue bar"] = "Statuenleiste" +L["Status"] = "Status" +L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."] = "Status-Indikator, zeigt ob die Einheit sich aktuell im Kampf befindet. Für Spieler zeigt es ebenso, ob sie ausruht sind." +L["Stealable/Curable/Dispellable"] = "Stehlbar/Heilbar/Bannbar" +L["Style of borders to show for all auras."] = "Aussehen des Rahmens, welches für alle Auren verwendet werden soll." +L["T"] = "T" +L["Tag list"] = "Tag-Liste" +L["Tag name"] = "Tag-Name" +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]."] = "Tag den Du verwendest zum Abrufen dieses Codes. Füge keine Klammern ein, da dies automatisch getan wird. Wenn Du zum Beispiel \"foobar\" eingibst, wird es mit [foobar] automatisch abgerufen." +L["Tags"] = "Tags" +L["Talent spec of your arena opponents."] = "Talentspezialisierung deiner Arenagegner." +L["Target"] = "Ziel" +L["Target of Target"] = "Ziel des Ziels" +L["Target of Target of Target"] = "Ziel des Ziel des Ziels" +L["Test Aura"] = "Aura testen" +L["Test spell"] = "Zauber testen" +L["Text"] = "Text" +L["Text Management"] = "Text Management" +L["Text name"] = "Text-Name" +L["Text name that you can use to identify this text from others when configuring."] = "Textname, den Du beim Konfigurieren zum Unterscheiden von diesem Text und weiteren verwenden kannst." +L["Text parent"] = "Text-Eltern" +L["Text/Tags"] = "Text/Tags" +L["The blacklist \"%s\" already exists."] = "Die schwarze Liste \"%s\" existiert bereits." +L["The override list \"%s\" already exists."] = "Die Überschreibungsliste \"%s\" existiert bereits." +L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."] = "Das Spielerfenster wird nicht rücksichtslos versteckt. Du musst dies manuell deaktivieren, entweder komplett oder per Gebiets-Typ." +L["The tag \"%s\" already exists."] = "Der Tag \"%s\" existiert bereits." +L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."] = "Die Einheitenfenster die Du siehst, sind Beispiele und zeigen nicht die Daten an, die sie normalerweiße würden.|n|nDu kannst sie durch /shadowuf oder klicken des unteren Buttons sperren." +L["The whitelist \"%s\" already exists."] = "Die Ausnahmeliste \"%s\" existiert bereits." +L["Thick outline"] = "Dicke Kontur" +L["Thin outline"] = "Dünne Kontur" +L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."] = "Diese Leiste wird automatisch ausgeblendet, wenn Du das Level-Maximum erreicht hast, oder Du gerade keinen Ruf verfolgst." +L["This filter has no aura types set to filter out."] = "Dieser Filter hat keine Auren zum Herausfiltern gesetzt." +L["This filter has no auras in it, you will have to add some using the dialog above."] = "Dieser Filter enthält keine Auren. Du musst mittels des oberen Dialogs einige hinzufügen." +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."] = "Dies ist eine gute Einführung wie man mit dem Programmieren von Lua beginnen sollte. Obwohl Du nicht alles vollständig lesen musst, ist es jedoch sehr hilfreich zum Verstehen der Grundlagen von Lua Syntax und APIs." +L["This unit depends on another to work, disabling %s will disable %s."] = "Diese Einheit hängt von einer anderen ab um zu funktionieren. Das Deaktivieren von %s wird auch %s deaktivieren." +L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."] = "Diese Einheit hat weitere untergeordnete Einheiten, die hiervon abhängig sind. Du musst diese Einheit aktivieren bevor Du die untergeordneten aktivieren kannst." +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."] = "Dies deaktiviert die automatische Erkennung der Ereignisse, die dieser Tag benötigt. Du solltest dies unabgehakt lassen, außer Du weißt was Du tust." +L["This will override all background colorings for bars including custom set ones."] = "Dies überschreibt alle Hintergrund-Färbungen für alle Leisten, einschließlich den benutzerdefinierten." +L["Threat"] = "Bedrohung" +L["Threat situation"] = "Bedrohungssituation" +L["Tile size"] = "Kachel-Größe" +L["Timer Text"] = "Timer Text" +L["Top"] = "Oben" +L["Top Center"] = "Oben Mitte" +L["Top Left"] = "Oben Links" +L["Top Right"] = "Oben Rechts" +L["Total number of active holy power."] = "Anzahl der aktiven Heiligen Kraft." +L["Total number of active soul shards."] = "Anzahl der aktiven Seelensplitter" +L["Total number of combo points you have on your target."] = "Gesamtzahl der Kombo-Punkte die Du auf dem Ziel hast." +L["Totem bar"] = "Totemleiste" +L["Totem Timer"] = "Totem Timer" +L["Travel"] = "Reise" +L["Tree"] = "Baum" +L["Turns this widget into a bar that can be resized and ordered just like health and power bars."] = "Schaltet dieses Widget in eine Leiste um, die in der Größe und Sortierung wie die Gesundheits- oder Energieleiste verändert werden kann." +L["Unattackable hostile"] = "Nicht angreifbare Feinde" +L["Unit color code on aggro"] = "Einheit - Farbe bei Aggro" +L["Unit colored situation"] = "Einheit - Situation gefärbt" +L["Unit Configuration"] = "Einheiten Einstellung" +L["Unit faction"] = "Einheiten Fraktion" +L["Unit name"] = "Einheitenname" +L["Unit name (Class colored)"] = "Einheitenname (Klassenfarben)" +L["Unit name colored by class."] = "Einheitenname nach Klasse gefärbt" +L["Unit scaled threat"] = "Einheit - Skalierte Bedrohung" +L["Unit server"] = "Einheit - Server" +L["Unit server, if they are from your server then nothing is shown."] = "Einheit - Server, wenn sie von Deinem Server sind, wird nichts angezeigt." +L["Unit situation name"] = "Einheit - Situations Name" +L["Units"] = "Einheiten" +L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."] = "Einheiten-Zugehörigkeit, Thrall gibt Horde wieder, König Magni Bronzebart hingegen Allianz." +L["Units per column"] = "Einheiten pro Spalte" +L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."] = "Einheiten Rasse, Blutelf, Tauren, Troll und so weiter." +L["Unknown"] = "Unbekannt" +L["Unlink frames"] = "Entsperren" +L["Up"] = "Hoch" +L["Update interval"] = "Aktualisierungsinterval" +L["Using unit settings"] = "Einheiteneinstellungen verwenden" +L["Various units can be enabled through this page, such as raid or party targets."] = "Verschiedene Einheiten können auf dieser Seite aktiviert werden, zum Beispiel Schlachtzug oder Gruppen-Ziele." +L["Vehicle"] = "Fahrzeug" +L["Vehicles"] = "Fahrzeuge" +L["Vertical growth"] = "Vertikale Zunahme" +L["View"] = "Ansicht" +L["Visibility"] = "Sichtbarkeit" +L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] = "WARNUNG: Hiermit trennst Du Fenster voneinander damit Du sie bewegen kannst, ohne dass sich dabei andere Fenster mitbewegen." +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."] = "Wenn der Einheit Gesundheitspunkte fehlen, wird der [missinghp] Tag angezeigt, sollten sie volle Gesundheit haben, wird stattdessen der [name] Tag angezeigt. Dies lässt Dich -1000 sehen wenn ihnen 1000 GP fehlen und ihren Namen wenn sie volle Gesundheit besitzen." +L["When this filter is active, apply the filter to buffs."] = "Wenn dieser Filter aktiv ist, diesen auch für Stärkungszauber anwenden." +L["When this filter is active, apply the filter to debuffs."] = "Wenn dieser Filter aktiv ist, diesen auch für Schwächungszauber anwenden." +L["When to color the empty bar by reaction, overriding the default color by option."] = "Falls die leere Leiste durch eine Reaktion die Farbe ändert, so wird die Standardfarbe durch die Option überschrieben." +L["When to color the health bar by the units reaction, overriding the color health by option."] = "Falls die Gesundheitsleiste durch die Einheitenreaktion gefärbt werden soll, so wird die Farbe der Gesundheit überschrieben." +L["Where inside the frame the text should be anchored to."] = "Wo innerhalb des Fensters der Text ausgerichtet werden soll." +L["Where to anchor the cast name text."] = "Wo der Text der Zaubernamen ausgerichtet werden soll." +L["Where to anchor the cast time text."] = "Wo der Text der Zauberzeit ausgerichtet werden soll." +L["Whitelist"] = "Ausnahmeliste" +L["Whitelist filters"] = "Ausnahmeliste-Filter" +L["Whitelists"] = "Ausnahmelisten" +L["Width"] = "Breite" +L["Width percent"] = "Breite Prozent" +L["Width weight"] = "Masse der Breite" +L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."] = "Füllt sich von rechts nach links, wenn horizontale Zunahme, oder von oben nach unten, wenn vertikale Zunahme verwendet wird." +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"] = "Verwundert was die ganzen Reiter für die Einheitenkonfiguration bedeuten? Hier sind einige Informationen:|n|n|cfffed000Allgemein:|r Portrait, Reichweitencheck, Kampfausblender, Ränder hervorheben|n|cfffed000Fenster:|r Einheiten Positionierung und Fenster ausrichten|n|cfffed000Leisten:|r Gesundheits- , Energie- , Leere- , Zauberleiste und Konfiguration der Kombopunkte|n|cfffed000Widget Größe:|r Alle Optionen zur Größeneinteilung und Anordnung der Leisten und Portraits|n|cfffed000Auren:|r Alle Konfigurationen für Auren zum aktivieren/deaktivieren/eigene vergrößeren/etc|n|cfffed000Indikatoren:|r Alle Konfigurationen für Indikatoren|n|cfffed000Text/Tags:|r Tag-Verwaltung sowie Text-Positionierung und Einstellungen der Breite.|n|n|n*** Häufig gesuchte Einstellungen ***|n|n|cfffed000Schlachtzugsfenster nach Gruppe|r - Einheiten Konfiguration -> Schlachtzug -> Schlachtzug -> Seperate Schlachtzugsfenster|n|cfffed000Klassen-Einfärbung:|r Leisten -> Gesundheit färben bei |n|cfffed000Timern der Auren:|r Hierfür benötigst Du OmniCC|n|cfffed000Zeige/Verstecke standard Stärkungszauber-Fenster:|r Blizzard ausblenden -> Stärkungszauber-Fenster verstecken|n|cfffed000Prozentualer GP/MP Text:|r Tags/Text-Reiter, verwende die [percenthp] oder [percentpp] Tags|n|cfffed000Verstecke Gruppe basierend auf Schlachtzug|r - Einheiten Konfiguration -> Gruppe -> Gruppe -> In einem 6-Mann-Schlachtzug ausblenden/In jedem Schlachtzug ausblenden" +L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."] = "Funktioniert genau wie [%s], aber das wird nur angezeigt, wenn die Einheit Mana als Sekundäre Power benutzt." +L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."] = "Funktioniert genau wie [%s], aber das wird nur angezeigt, wenn die Einheit in Katzen- oder Bärengestalt ist." +L["WoW Programming"] = "WoW Programmierung" +L["WoW Programming is a good resource for finding out what difference API's do and how to call them."] = "WoW-Programmieren ist eine gute Anlaufstelle um herauszufinden, wie die verschiedenen API's arbeiten und wie man diese abruft." +L["X Offset"] = "X-Verschiebung" +L["XP/Rep bar"] = "XP/EP Leiste" +L["Y Offset"] = "Y-Verschiebung" +L["Yellow (>30% HP)"] = "Gelb (>30% HP)" +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."] = "Du kannst zusätzlich Text mit aktivierten Tags hinzufügen mit dieser Konfiguration. Beachte, dass jeder zusätzliche hinzugefügte Text (oder entfernte) sich auf alle Einheiten auswirkt. Texte entfernen setzt ebenso all ihre Einstellungen zurück.|n|nBedenke, dass Du keinen Standard Text löschen kannst, der in den Einheiten inbegriffen ist." +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."] = "Du kannst neue benutzerdefinierte Tags über diese Seite hinzufügen. Wenn Du sehen möchtest, welche Tags im Text verwendet werden, schaue unter dem Text-Reiter für eine Einheitenkonfiguration." +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."] = "Du kannst hier Aurenfilter und Gruppen für Einheiten deaktivieren. Zum Beispiel kannst du eine Aurengruppe erstellen, die nur DPS Debuffs auf dem Ziel zeigt." +L["You can find more information on creating your own custom tags in the \"Help\" tab above."] = "Du kannst mehr Informationen zum Erstellen von benutzerdefinierten Tags im \"Hilfe\"-Reiter weiter oben finden." +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."] = "Du kannst mehr Informationen über Erstellen von eigenen benutzerdefinierten Tags in dem oberen \"Hilfe\"-Reiter finden.|nSUF wird versuchen automatisch zu erkennen welche Ereignisse Dein Tag benötigt, sodass Du üblicherweise nicht die Ereignisfelder ausfüllen musst." +L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] = "Du kannst andere Benutzer Konfigurationen von Shadowed Unit Frames importieren, indem Du den exportierten Code den sie Dir gegeben haben unten einfügst. Dein aktuelles Layout wird unter \"Importiere Backup\" gesichert.|n|nNach dem Einfügen Deines neuen Layouts, wird es ca. 30-60 Sekunden geladen, bitte habe Geduld." +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."] = "Hier kannst Du festlegen, welche Einheitenfenster, welche Filter-Gruppe und in welchem Gebietstyp verwendet werden soll. Wenn Du festlegen möchtest, welche Aura in welche Gruppe soll, dann schaue unter der \"Auren-Filter verwalten\" Option." +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."] = "Du kannst diesen Tag nicht bearbeiten, da es einer der inbegriffenen Standard Tags dieses Addons ist. Diese Funktion ist hier um ein Beispiel für Deine eigenen benutzerdefinierten Tags bereitzustellen." +L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."] = "Du kannst diesen Tag nicht \"%s\" nennen, Tag-Namen dürfen keine Klammern beinhalten." +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."] = "Du hast bisher keinen Filter dieser Art hinzugefügt. Vor dem Nutzen dieser Seite, musst du einen Filter in der Verwaltung erstellen." +L["You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf."] = "Du bist einem Kampf beigetreten, alle Fenster wurden gesperrt. Wenn Du den Kampf wieder verlassen hast, musst Du erneut /shadowuf eingeben, um sie wieder zu entsperren." +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."] = "Du musst die Ereignisse festlegen zum Ausführen. Du kannst nur Buchstaben und Unterstriche eingeben, \"FOO_BAR\" ist zum Beispiel zulässig, \"APPLE_5_ORANGE\" nicht, da eine Nummer enthalten ist." +L["You must enter a number that is 0 or higher, negative numbers are not allowed."] = "Du musst eine Nummer die 0 oder höher ist eingeben. Negative Nummern sind nicht erlaubt." +L["You must enter a tag name."] = "Du musst einen Tag-Namen eingeben." +L["You must restart Shadowed Unit Frames."] = "Du musst Shadowed Unit Frames neustarten" +L["You must wrap your code in a function."] = "Du musst Deinen Code in eine Funktion umbrechen." +L["You will need to create an aura filter before you can set which unit to enable aura filtering on."] = "Du musst einen Auren-Filter erstellen, bevor Du festlegen kannst, bei welcher Einheit die Auren-Filterung aktiviert sein soll." +L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."] = "Du musst /console reloadui ausführen, bevor ein verstecktes Fenster wieder sichtbar wird.|nSpieler und andere Einheitenfenster sind automatisch versteckt, abhängig davon, ob Du die Einheit in Shadowed Unit Frames aktiviert hast." +L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] = "Dein aktives Layout ist ein Profil, welches für Backup importieren verwendet wird. Dies kann nicht durch einen Import überschrieben werden. Wechsel Dein Profil in irgendein anderes und versuche es erneut." +L["Your aura color"] = "Deine Aurenfarbe" +L["Your Auras"] = "Deine Auren" +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"] = "Dein Code muss in eine Funktion umgebrochen werden. Wenn Du beispielsweise einen Tag erstellst um den Einheitenname auszugeben, würdest Du folgendes tun:|n|nfunction(unit, unitOwner)|nreturn UnitName(unitOwner)|nend" +L["Zone Configuration"] = "Zonen Einstellung" +L["Zone configuration units"] = "Gebiet Konfiguration - Einheiten" + +local ShadowUF = select(2, ...) +ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) diff --git a/localization/enUS.lua b/localization/enUS.lua index cf3267984..e83fcea84 100755 --- a/localization/enUS.lua +++ b/localization/enUS.lua @@ -1,13 +1,985 @@ -local ShadowUF = select(2, ...) -local L = {} ---@localization(locale="enUS", format="lua_additive_table")@ - -ShadowUF.L = L ---@debug@ -ShadowUF.L = setmetatable(ShadowUF.L, { - __index = function(tbl, value) - rawset(tbl, value, value) - return value - end, -}) ---@end-debug@ +local ShadowUF = select(2, ...) +local L = {} +L["%d auras in group"] = "%d auras in group" +L["%s (%s): %s/%s (%.2f%% done)"] = "%s (%s): %s/%s (%.2f%% done)" +L["%s aura groups disabled"] = "%s aura groups disabled" +L["%s frames"] = "%s frames" +L["%s member"] = "%s member" +L["|cff20ff20%s|r units enabled"] = "|cff20ff20%s|r units enabled" +L["|cffff2020%s|r units disabled"] = "|cffff2020%s|r units disabled" +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."] = "|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." +L["1 aura group disabled"] = "1 aura group disabled" +L["2D"] = "2D" +L["3D"] = "3D" +L["A"] = "A" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"." +L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."] = "Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000." +L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."] = "Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000." +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000." +L["Add"] = "Add" +L["Add Aura"] = "Add Aura" +L["Add aura"] = "Add aura" +L["Add Indicator"] = "Add Indicator" +L["Add link"] = "Add link" +L["Add new indicator"] = "Add new indicator" +L["Add new tag"] = "Add new tag" +L["Add new text"] = "Add new text" +L["Add Tags"] = "Add Tags" +L["Adds %s to the list of units to be modified when you change values in this tab."] = "Adds %s to the list of units to be modified when you change values in this tab." +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul." +L["Adds a bar indicating how much time is left on your mushrooms."] = "Adds a bar indicating how much time is left on your mushrooms." +L["Adds a bar indicating how much time is left on your Rune of Power."] = "Adds a bar indicating how much time is left on your Rune of Power." +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = "Adds a bar inside the health bar indicating how much damage will be absorbed." +L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."] = "Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving." +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = "Adds a bar inside the health bar indicating how much healing someone will receive." +L["Adds a Burning Embers bar for Destruction Warlocks."] = "Adds a Burning Embers bar for Destruction Warlocks." +L["Adds a Demonic Fury bar for Demonology Warlocks."] = "Adds a Demonic Fury bar for Demonology Warlocks." +L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."] = "Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player." +L["Adds a mana bar to the player frame for elemental and enhancement shamans."] = "Adds a mana bar to the player frame for elemental and enhancement shamans." +L["Adds a mana bar to the player frame for shadow priests."] = "Adds a mana bar to the player frame for shadow priests." +L["Adds a Stagger bar for Brewmaster Monks."] = "Adds a Stagger bar for Brewmaster Monks." +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "Adds an empty bar that you can put text into as a way of uncluttering other bars." +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have." +L["Adds eclipse bars and how far into sun or moon eclipse is."] = "Adds eclipse bars and how far into sun or moon eclipse is." +L["Adds rune bars and timers before runes refresh to the player frame."] = "Adds rune bars and timers before runes refresh to the player frame." +L["Adds temporary enchants to the buffs for the player."] = "Adds temporary enchants to the buffs for the player." +L["Adds totem bars with timers before they expire to the player frame."] = "Adds totem bars with timers before they expire to the player frame." +L["Advanced"] = "Advanced" +L["Advanced tag management, allows you to add your own custom tags."] = "Advanced tag management, allows you to add your own custom tags." +L["AFK"] = "AFK" +L["AFK status"] = "AFK status" +L["AFK timer"] = "AFK timer" +L["AFK:%s"] = "AFK:%s" +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout." +L["Aggro"] = "Aggro" +L["All aura groups enabled for unit."] = "All aura groups enabled for unit." +L["All Auras"] = "All Auras" +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."] = "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." +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."] = "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." +L["Allows you to enter a new aura group."] = "Allows you to enter a new aura group." +L["Alpha to use for bar backgrounds."] = "Alpha to use for bar backgrounds." +L["Alpha to use for bar."] = "Alpha to use for bar." +L["Alt. Power"] = "Alt. Power" +L["Alt. Power bar"] = "Alt. Power bar" +L["Alternate power is used for things like quests and dungeons."] = "Alternate power is used for things like quests and dungeons." +L["Alternate Spell Name"] = "Alternate Spell Name" +L["Alternatively friendly spell to use to check range."] = "Alternatively friendly spell to use to check range." +L["Ammo"] = "Ammo" +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."] = "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." +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."] = "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." +L["Anchor point"] = "Anchor point" +L["Anchor to"] = "Anchor to" +L["Anchor to another frame"] = "Anchor to another frame" +L["Anchor to buffs"] = "Anchor to buffs" +L["Anchor to debuffs"] = "Anchor to debuffs" +L["Ancient Kings bar"] = "Ancient Kings bar" +L["Any auras shown in this indicator will have their total stack displayed."] = "Any auras shown in this indicator will have their total stack displayed." +L["Aquatic"] = "Aquatic" +L["Arcane Charges"] = "Arcane Charges" +L["Are you sure you want to delete this aura?"] = "Are you sure you want to delete this aura?" +L["Are you sure you want to delete this filter?"] = "Are you sure you want to delete this filter?" +L["Are you sure you want to delete this indicator?"] = "Are you sure you want to delete this indicator?" +L["Are you sure you want to delete this tag?"] = "Are you sure you want to delete this tag?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "Are you sure you want to delete this text? All settings for it will be deleted." +L["Arena"] = "Arena" +L["Arena Pet"] = "Arena Pet" +L["Arena Spec"] = "Arena Spec" +L["Arena Target"] = "Arena Target" +L["Arena Target of Target"] = "Arena Target of Target" +L["Arena ToT"] = "Arena ToT" +L["Arenas"] = "Arenas" +L["Ascending"] = "Ascending" +L["Assigned Role (DPS/Tank/etc)"] = "Assigned Role (DPS/Tank/etc)" +L["Astral Power"] = "Astral Power" +L["Aura border style"] = "Aura border style" +L["Aura borders"] = "Aura borders" +L["Aura Combo Points"] = "Aura Combo Points" +L["Aura Filters"] = "Aura Filters" +L["Aura filters"] = "Aura filters" +L["Aura group"] = "Aura group" +L["Aura groups"] = "Aura groups" +L["Aura Groups"] = "Aura Groups" +L["Aura Indicators"] = "Aura Indicators" +L["Aura indicators"] = "Aura indicators" +L["Aura name or spell ID"] = "Aura name or spell ID" +L["Aura types to filter"] = "Aura types to filter" +L["Auras"] = "Auras" +L["Auras matching a criteria will automatically show up in the indicator when enabled."] = "Auras matching a criteria will automatically show up in the indicator when enabled." +L["Automatic Auras"] = "Automatic Auras" +L["B"] = "B" +L["Background"] = "Background" +L["Background alpha"] = "Background alpha" +L["Background color"] = "Background color" +L["Background/border"] = "Background/border" +L["Bag indicator for master looters."] = "Bag indicator for master looters." +L["Banked Holy Power"] = "Banked Holy Power" +L["Bar alpha"] = "Bar alpha" +L["Bar coloring for the moon portion of the eclipse bar."] = "Bar coloring for the moon portion of the eclipse bar." +L["Bar color to use to show how much healing someone is about to receive."] = "Bar color to use to show how much healing someone is about to receive." +L["Bar spacing"] = "Bar spacing" +L["Bar texture"] = "Bar texture" +L["Bars"] = "Bars" +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."] = "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." +L["Battleground"] = "Battleground" +L["Battleground Pet"] = "Battleground Pet" +L["Battleground Target"] = "Battleground Target" +L["Battleground Target of Target"] = "Battleground Target of Target" +L["Battlegrounds"] = "Battlegrounds" +L["Bear"] = "Bear" +L["BG"] = "BG" +L["BG Pet"] = "BG Pet" +L["BG Target"] = "BG Target" +L["BG ToT"] = "BG ToT" +L["Blacklist"] = "Blacklist" +L["Blacklist filters"] = "Blacklist filters" +L["Blacklists"] = "Blacklists" +L["Blizzard"] = "Blizzard" +L["Border"] = "Border" +L["Border alpha"] = "Border alpha" +L["Border color"] = "Border color" +L["Border coloring of stealable, curable and dispellable auras."] = "Border coloring of stealable, curable and dispellable auras." +L["Border highlighting"] = "Border highlighting" +L["Border thickness"] = "Border thickness" +L["Boss"] = "Boss" +L["Boss Auras"] = "Boss Auras" +L["Boss Debuffs"] = "Boss Debuffs" +L["Boss Target"] = "Boss Target" +L["Boss Target of Target"] = "Boss Target of Target" +L["Boss ToT"] = "Boss ToT" +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."] = "Boss units are for only certain fights, such as Blood Princes or the Gunship battle, you will not see them for every boss fight." +L["Both"] = "Both" +L["Bottom"] = "Bottom" +L["Bottom Center"] = "Bottom Center" +L["Bottom Left"] = "Bottom Left" +L["Bottom Right"] = "Bottom Right" +L["buff frames"] = "buff frames" +L["Buffs"] = "Buffs" +L["Burning Embers"] = "Burning Embers" +L["Burning Embers bar"] = "Burning Embers bar" +L["C"] = "C" +L["Cannot find any profiles named \"%s\"."] = "Cannot find any profiles named \"%s\"." +L["Cast"] = "Cast" +L["Cast bar"] = "Cast bar" +L["Cast icon"] = "Cast icon" +L["Cast interrupted"] = "Cast interrupted" +L["Cast name"] = "Cast name" +L["Cast time"] = "Cast time" +L["Cast uninterruptible"] = "Cast uninterruptible" +L["Casting"] = "Casting" +L["Cat"] = "Cat" +L["Category"] = "Category" +L["Center"] = "Center" +L["Changed profile to %s."] = "Changed profile to %s." +L["Changes the health bar to the color of any curable debuff."] = "Changes the health bar to the color of any curable debuff." +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = "Changes the health bar to the set hostile color (Red by default) when the unit takes aggro." +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."] = "Changes this widget into a bar, you will be able to change the height and ordering like you can change health and power bars." +L["Channelling"] = "Channelling" +L["Checking this will show the indciator on hostile units."] = "Checking this will show the indciator on hostile units." +L["Checking this will show the indicator on friendly units."] = "Checking this will show the indicator on friendly units." +L["Chi"] = "Chi" +L["Chi Points"] = "Chi Points" +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = "Child units cannot be dragged, you will have to reposition them through /shadowuf." +L["Class"] = "Class" +L["Class (Smart)"] = "Class (Smart)" +L["Class color tag"] = "Class color tag" +L["Class icon"] = "Class icon" +L["Class Icon"] = "Class Icon" +L["Class icon for players."] = "Class icon for players." +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = "Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class." +L["Class Role"] = "Class Role" +L["Class Specific"] = "Class Specific" +L["Class Timer"] = "Class Timer" +L["Class/misc bars"] = "Class/misc bars" +L["Classes"] = "Classes" +L["Classification"] = "Classification" +L["Classifications"] = "Classifications" +L["Clip"] = "Clip" +L["Close color"] = "Close color" +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = "Closes a color code, prevents colors from showing up on text that you do not want it to." +L["Code"] = "Code" +L["Color by class"] = "Color by class" +L["Color by reaction on"] = "Color by reaction on" +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."] = "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." +L["Color code for general situation"] = "Color code for general situation" +L["Color code for situation"] = "Color code for situation" +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = "Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class" +L["Color code on aggro"] = "Color code on aggro" +L["Color health by"] = "Color health by" +L["Color on aggro"] = "Color on aggro" +L["Color on curable debuff"] = "Color on curable debuff" +L["Color power by"] = "Color power by" +L["Color to use for health bars that are set to be colored by a static color."] = "Color to use for health bars that are set to be colored by a static color." +L["Color to use to show how much damage will be absorbed."] = "Color to use to show how much damage will be absorbed." +L["Color to use to show how much healing will e absorbed."] = "Color to use to show how much healing will e absorbed." +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = "Color used when a cast cannot be interrupted, this is only used for PvE mobs." +L["Color used when a cast is a channel."] = "Color used when a cast is a channel." +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "Color used when a cast is interrupted either by the caster themselves or by another unit." +L["Color used when a cast is successfully finished."] = "Color used when a cast is successfully finished." +L["Color used when an unit is casting a spell."] = "Color used when an unit is casting a spell." +L["Colors"] = "Colors" +L["Column growth"] = "Column growth" +L["Column spacing"] = "Column spacing" +L["Combat alpha"] = "Combat alpha" +L["Combat fader"] = "Combat fader" +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."] = "Combat fader will fade out all your frames while they are inactive and fade them back in once you are in combat or active." +L["Combat Status"] = "Combat Status" +L["Combat text"] = "Combat text" +L["Combat/resting status"] = "Combat/resting status" +L["Combo points"] = "Combo points" +L["Combo Points"] = "Combo Points" +L["Configuration to specific unit frames."] = "Configuration to specific unit frames." +L["Cooldown rings for"] = "Cooldown rings for" +L["Create"] = "Create" +L["Creature type"] = "Creature type" +L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."] = "Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on." +L["Crown indicator for group leader or assistants."] = "Crown indicator for group leader or assistants." +L["Cur/Max HP (Absolute)"] = "Cur/Max HP (Absolute)" +L["Cur/Max HP (Short)"] = "Cur/Max HP (Short)" +L["Cur/Max HP (Smart)"] = "Cur/Max HP (Smart)" +L["Cur/Max power (Absolute)"] = "Cur/Max power (Absolute)" +L["Cur/Max power (Druid)"] = "Cur/Max power (Druid)" +L["Cur/Max power (Druid/Absolute)"] = "Cur/Max power (Druid/Absolute)" +L["Cur/Max power (Secondary)"] = "Cur/Max power (Secondary)" +L["Cur/Max power (Secondary/Absolute)"] = "Cur/Max power (Secondary/Absolute)" +L["Cur/Max Power (Short)"] = "Cur/Max Power (Short)" +L["Cur/Max PP (Smart)"] = "Cur/Max PP (Smart)" +L["Curable"] = "Curable" +L["Curable Auras"] = "Curable Auras" +L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."] = "Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead." +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "Current and maximum power, formatted as [curpp]/[maxpp]." +L["Current Demonic Fury (Short)"] = "Current Demonic Fury (Short)" +L["Current Eclipse, <0 is Lunar Energy and >0 is Solar Energy."] = "Current Eclipse, <0 is Lunar Energy and >0 is Solar Energy." +L["Current health (Druid/Absolute)"] = "Current health (Druid/Absolute)" +L["Current health (Monk/Absolute)"] = "Current health (Monk/Absolute)" +L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."] = "Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is." +L["Current HP (Absolute)"] = "Current HP (Absolute)" +L["Current HP (Short)"] = "Current HP (Short)" +L["Current pet used by a battleground unit."] = "Current pet used by a battleground unit." +L["Current power (Absolute)"] = "Current power (Absolute)" +L["Current power (Druid)"] = "Current power (Druid)" +L["Current power (Druid/Absolute)"] = "Current power (Druid/Absolute)" +L["Current power (Secondary)"] = "Current power (Secondary)" +L["Current power (Secondary/Absolute)"] = "Current power (Secondary/Absolute)" +L["Current Power (Short)"] = "Current Power (Short)" +L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."] = "Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is." +L["Current target of a battleground unit."] = "Current target of a battleground unit." +L["Current target of target of a battleground unit."] = "Current target of target of a battleground unit." +L["Currently modifying"] = "Currently modifying" +L["Currently used in battlegrounds for showing flag carriers."] = "Currently used in battlegrounds for showing flag carriers." +L["Damage absorption (Absolute)"] = "Damage absorption (Absolute)" +L["Damage absorption (Short)"] = "Damage absorption (Short)" +L["Damage absorption/Name"] = "Damage absorption/Name" +L["Dark"] = "Dark" +L["Dead"] = "Dead" +L["Debuffs"] = "Debuffs" +L["Decimal percent HP"] = "Decimal percent HP" +L["Default color"] = "Default color" +L["Default font color, any color tags inside individual tag texts will override this."] = "Default font color, any color tags inside individual tag texts will override this." +L["Deficit/Unit Name"] = "Deficit/Unit Name" +L["Delete"] = "Delete" +L["Delete filter"] = "Delete filter" +L["Delete link"] = "Delete link" +L["Demonic Fury"] = "Demonic Fury" +L["Demonic Fury bar"] = "Demonic Fury bar" +L["Demonic Power"] = "Show Demonic Power" +L["Descending"] = "Descending" +L["Disable Auras by Class"] = "Disable Auras by Class" +L["Disable Blizzard Cooldown Count"] = "Disable Blizzard Cooldown Count" +L["Disable event discovery"] = "Disable event discovery" +L["Disable OmniCC Cooldown Count"] = "Disable OmniCC Cooldown Count" +L["Disable vehicle swap"] = "Disable vehicle swap" +L["Disabled"] = "Disabled" +L["Disabled for %s."] = "Disabled for %s." +L["Disabled in %s"] = "Disabled in %s" +L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."] = "Disables showing Cooldown Count timers in all Shadowed Unit Frame auras." +L["Disables the unit frame from turning into a vehicle when the player enters one."] = "Disables the unit frame from turning into a vehicle when the player enters one." +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!."] = "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!." +L["Disabling unit modules in various instances."] = "Disabling unit modules in various instances." +L["Dismissable Totem bars"] = "Dismissable Totem bars" +L["Dispellable/Stealable"] = "Dispellable/Stealable" +L["Display"] = "Display" +L["Display enemy buffs using LibClassicDuration data."] = "Display enemy buffs using LibClassicDuration data." +L["DND"] = "DND" +L["DND:%s"] = "DND:%s" +L["Documentation"] = "Documentation" +L["Don't hide when empty"] = "Don't hide when empty" +L["Don't use a filter"] = "Don't use a filter" +L["Down"] = "Down" +L["Druid form"] = "Druid form" +L["Druid form (Short)"] = "Druid form (Short)" +L["Druid mana bar"] = "Druid mana bar" +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."] = "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["Dungeon Role"] = "Dungeon Role" +L["Eclipse bar"] = "Eclipse bar" +L["Eclipse (Druid)"] = "Eclipse (Druid)" +L["Eclipse (Moon)"] = "Eclipse (Moon)" +L["Eclipse (Sun)"] = "Eclipse (Sun)" +L["Eclipse Power"] = "Show Eclipse Power" +L["Edge size"] = "Edge size" +L["Edit tag"] = "Edit tag" +L["Editing %s"] = "Editing %s" +L["Elite"] = "Elite" +L["Empty bar"] = "Empty bar" +L["Enable %s"] = "Enable %s" +L["Enable buffs"] = "Enable buffs" +L["Enable debuffs"] = "Enable debuffs" +L["Enable enemy buff tracking"] = "Enable enemy buff tracking" +L["Enable for friendlies"] = "Enable for friendlies" +L["Enable for hostiles"] = "Enable for hostiles" +L["Enable frequent updates"] = "Enable frequent updates" +L["Enable indicator"] = "Enable indicator" +L["Enable Indicators"] = "Enable Indicators" +L["Enable temporary enchants"] = "Enable temporary enchants" +L["Enable units"] = "Enable units" +L["Enabled for %s."] = "Enabled for %s." +L["Enabled in %s"] = "Enabled in %s" +L["Enabled Units"] = "Enabled Units" +L["Enables configuration mode, letting you move and giving you example frames to setup."] = "Enables configuration mode, letting you move and giving you example frames to setup." +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."] = "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." +L["Energy"] = "Energy" +L["Enlarge auras for"] = "Enlarge auras for" +L["Error"] = "Error" +L["Essence"] = "Essence" +L["Events"] = "Events" +L["Events that should be used to trigger an update of this tag. Separate each event with a single space."] = "Events that should be used to trigger an update of this tag. Separate each event with a single space." +L["Everywhere else"] = "Everywhere else" +L["Export"] = "Export" +L["F"] = "F" +L["Fades out the unit frames of people who are not within range of you."] = "Fades out the unit frames of people who are not within range of you." +L["Failed to import layout, error:|n|n%s"] = "Failed to import layout, error:|n|n%s" +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s" +L["Failed to save tag, error:|n %s"] = "Failed to save tag, error:|n %s" +L["Fel Energy"] = "Fel Energy" +L["Female"] = "Female" +L["Filter type"] = "Filter type" +L["Filtering both buffs and debuffs"] = "Filtering both buffs and debuffs" +L["Filtering buffs only"] = "Filtering buffs only" +L["Filtering debuffs only"] = "Filtering debuffs only" +L["Filters"] = "Filters" +L["Finished cast"] = "Finished cast" +L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."] = "Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing." +L["Flight"] = "Flight" +L["Flips coloring so the bar color is shown as the background color and the background as the bar"] = "Flips coloring so the bar color is shown as the background color and the background as the bar" +L["Focus"] = "Focus" +L["Focus Target"] = "Focus Target" +L["Font"] = "Font" +L["Food"] = "Food" +L["For configuring aura indicators on unit frames."] = "For configuring aura indicators on unit frames." +L["For target/focus"] = "For target/focus" +L["Forces a static color to be used for the background of all bars"] = "Forces a static color to be used for the background of all bars" +L["Frame"] = "Frame" +L["Frame alpha when you are out of combat while having no target and 100% mana or energy."] = "Frame alpha when you are out of combat while having no target and 100% mana or energy." +L["Frame alpha while this unit is in combat."] = "Frame alpha while this unit is in combat." +L["Frames"] = "Frames" +L["Friendly"] = "Friendly" +L["Fuel"] = "Fuel" +L["Full Burning Ember"] = "Full Burning Ember" +L["Full size after"] = "Full size after" +L["Full size before"] = "Full size before" +L["Fury"] = "Fury" +L["General"] = "General" +L["General configuration to all enabled units."] = "General configuration to all enabled units." +L["General threat situation"] = "General threat situation" +L["Ghost"] = "Ghost" +L["Ghoul bar"] = "Ghoul bar" +L["Global"] = "Global" +L["Global configurating will let you mass enable or disable aura groups for multiple units at once."] = "Global configurating will let you mass enable or disable aura groups for multiple units at once." +L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"] = "Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings" +L["Green (<30% HP)"] = "Green (<30% HP)" +L["Group %d"] = "Group %d" +L["Group by"] = "Group by" +L["Group number"] = "Group number" +L["Group row spacing"] = "Group row spacing" +L["Groups"] = "Groups" +L["Groups per row"] = "Groups per row" +L["Groups to show"] = "Groups to show" +L["Growth"] = "Growth" +L["Guild name"] = "Guild name" +L["Half health"] = "Half health" +L["Has Aggro"] = "Has Aggro" +L["Heal absorb"] = "Heal absorb" +L["Heal Absorb (Absolute)"] = "Heal Absorb (Absolute)" +L["Heal Absorb (Short)"] = "Heal Absorb (Short)" +L["Heal absorbs"] = "Heal absorbs" +L["Healing absorb"] = "Healing absorb" +L["Health"] = "Health" +L["Health bar"] = "Health bar" +L["Health bar color for friendly units."] = "Health bar color for friendly units." +L["Health bar color for hostile units."] = "Health bar color for hostile units." +L["Health bar color for neutral units."] = "Health bar color for neutral units." +L["Health bar color for units with aggro."] = "Health bar color for units with aggro." +L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."] = "Health bar color to use for hostile units who you cannot attack, used for reaction coloring." +L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."] = "Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy." +L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."] = "Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy." +L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."] = "Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy." +L["Health color"] = "Health color" +L["Health percent"] = "Health percent" +L["Height"] = "Height" +L["Help"] = "Help" +L["Hide %s"] = "Hide %s" +L["Hide %s frames"] = "Hide %s frames" +L["Hide bar when empty"] = "Hide bar when empty" +L["Hide Blizzard"] = "Hide Blizzard" +L["Hide in <=5-man raids"] = "Hide in <=5-man raids" +L["Hide in >5-man raids"] = "Hide in >5-man raids" +L["Hide in any raid"] = "Hide in any raid" +L["Hide tooltips in combat"] = "Hide tooltips in combat" +L["Hides the cast bar if there is no cast active."] = "Hides the cast bar if there is no cast active." +L["Hides the power bar unless the class has mana."] = "Hides the power bar unless the class has mana." +L["Hiding and showing various aspects of the default UI such as the player buff frames."] = "Hiding and showing various aspects of the default UI such as the player buff frames." +L["High"] = "High" +L["High health"] = "High health" +L["Highlight"] = "Highlight" +L["Highlight units that are "] = "Highlight units that are " +L["Highlight units that are debuffed with something you can cure."] = "Highlight units that are debuffed with something you can cure." +L["Highlight units that are rare."] = "Highlight units that are rare." +L["Highlight units that have aggro on any mob."] = "Highlight units that have aggro on any mob." +L["Highlight units that you are targeting or have focused."] = "Highlight units that you are targeting or have focused." +L["Highlight units when you mouse over them."] = "Highlight units when you mouse over them." +L["Holy power"] = "Holy power" +L["Holy Power"] = "Holy Power" +L["Hostile"] = "Hostile" +L["How close the frame should clip with the border."] = "How close the frame should clip with the border." +L["How far the background should be from the unit frame border."] = "How far the background should be from the unit frame border." +L["How large the background should tile"] = "How large the background should tile" +L["How large the edges should be."] = "How large the edges should be." +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."] = "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." +L["How many auras to show in a single row."] = "How many auras to show in a single row." +L["How many Chi points you currently have."] = "How many Chi points you currently have." +L["How many groups should be shown per row."] = "How many groups should be shown per row." +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!"] = "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!" +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!"] = "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!" +L["How many rows total should be used, rows will be however long the per row value is set at."] = "How many rows total should be used, rows will be however long the per row value is set at." +L["How many seconds a totem has left before disappearing."] = "How many seconds a totem has left before disappearing." +L["How many seconds before a rune recharges."] = "How many seconds before a rune recharges." +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."] = "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." +L["How many Shadow Orbs you have if you're Shadow"] = "How many Shadow Orbs you have if you're Shadow" +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."] = "How much of the frames total height this bar should get, this is a weighted value, the higher it is the more it gets." +L["How much spacing should be between each new row of groups."] = "How much spacing should be between each new row of groups." +L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."] = "How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing." +L["How much weight this should use when figuring out the total text width."] = "How much weight this should use when figuring out the total text width." +L["How the frames should grow when a new column is added."] = "How the frames should grow when a new column is added." +L["How the rows should grow when new group members are added."] = "How the rows should grow when new group members are added." +L["How you want this aura to be anchored to the unit frame."] = "How you want this aura to be anchored to the unit frame." +L["Icon Size"] = "Icon Size" +L["If multiple auras are shown in the same indicator, the higher priority one is shown first."] = "If multiple auras are shown in the same indicator, the higher priority one is shown first." +L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."] = "If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead." +L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."] = "If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name." +L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."] = "If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name." +L["If the unit is a player then class is returned, if it's a NPC then the creature type."] = "If the unit is a player then class is returned, if it's a NPC then the creature type." +L["If the unit is a player then race is returned, if it's a NPC then the creature type."] = "If the unit is a player then race is returned, if it's a NPC then the creature type." +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."] = "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." +L["Imp & Dreadstalker bar"] = "Imp & Dreadstalker bar" +L["Import"] = "Import" +L["Import unit frame positions"] = "Import unit frame positions" +L["Import visibility settings"] = "Import visibility settings" +L["In range alpha"] = "In range alpha" +L["Inactive alpha"] = "Inactive alpha" +L["Incoming absorb"] = "Incoming absorb" +L["Incoming absorbs"] = "Incoming absorbs" +L["Incoming heal"] = "Incoming heal" +L["Incoming heal (Absolute)"] = "Incoming heal (Absolute)" +L["Incoming heal (Percent)"] = "Incoming heal (Percent)" +L["Incoming heal (Short)"] = "Incoming heal (Short)" +L["Incoming heal/Name"] = "Incoming heal/Name" +L["Incoming heals"] = "Incoming heals" +L["Index"] = "Index" +L["Indicator color"] = "Indicator color" +L["Indicator for the current pet happiness."] = "Indicator for the current pet happiness." +L["Indicator name"] = "Indicator name" +L["Indicator this aura should be displayed in."] = "Indicator this aura should be displayed in." +L["Indicators"] = "Indicators" +L["Insanity"] = "Insanity" +L["Inset"] = "Inset" +L["Inside Bottom Left"] = "Inside Bottom Left" +L["Inside Bottom Right"] = "Inside Bottom Right" +L["Inside Center"] = "Inside Center" +L["Inside Center Left"] = "Inside Center Left" +L["Inside Center Right"] = "Inside Center Right" +L["Inside Top Left"] = "Inside Top Left" +L["Inside Top Right"] = "Inside Top Right" +L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."] = "Instead of showing a solid color inside the indicator, the icon of the aura will be shown." +L["Interrupted"] = "Interrupted" +L["Invalid interval entered, must be a number."] = "Invalid interval entered, must be a number." +L["Invalid spell \"%s\" entered."] = "Invalid spell \"%s\" entered." +L["Invert colors"] = "Invert colors" +L["Layout manager"] = "Layout manager" +L["Leader / Assist"] = "Leader / Assist" +L["Left"] = "Left" +L["Left Bottom"] = "Left Bottom" +L["Left Center"] = "Left Center" +L["Left text"] = "Left text" +L["Left Top"] = "Left Top" +L["Let's you modify the base font size to either make it larger or smaller."] = "Let's you modify the base font size to either make it larger or smaller." +L["Level"] = "Level" +L["Level %s - %s: %s/%s (%.2f%% done)"] = "Level %s - %s: %s/%s (%.2f%% done)" +L["Level %s - %s: %s/%s (%.2f%% done), %s rested."] = "Level %s - %s: %s/%s (%.2f%% done), %s rested." +L["Level (Colored)"] = "Level (Colored)" +L["Level without any coloring."] = "Level without any coloring." +L["Light"] = "Light" +L["Link"] = "Link" +L["Link from"] = "Link from" +L["Link to"] = "Link to" +L["Linked spells"] = "Linked spells" +L["Lock frames"] = "Lock frames" +L["Locks the unit frame positionings hiding the mover boxes."] = "Locks the unit frame positionings hiding the mover boxes." +L["Low health"] = "Low health" +L["M"] = "M" +L["MA ToT"] = "MA ToT" +L["Maelstrom"] = "Maelstrom" +L["Main Assist"] = "Main Assist" +L["Main Assist Target"] = "Main Assist Target" +L["Main Assist Target of Target"] = "Main Assist Target of Target" +L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."] = "Main Assists's are set by the Blizzard Main Assist system or mods that use it." +L["Main Tank"] = "Main Tank" +L["Main Tank Target"] = "Main Tank Target" +L["Main Tank Target of Target"] = "Main Tank Target of Target" +L["Main Tank's are set through the Raid frames, or through selecting the Tank role."] = "Main Tank's are set through the Raid frames, or through selecting the Tank role." +L["Male"] = "Male" +L["Mana"] = "Mana" +L["Manage Aura Filters"] = "Manage Aura Filters" +L["Management"] = "Management" +L["Manual position"] = "Manual position" +L["Master Looter"] = "Master Looter" +L["Max columns"] = "Max columns" +L["Max Demonic Fury (Short)"] = "Max Demonic Fury (Short)" +L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."] = "Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is." +L["Max HP (Absolute)"] = "Max HP (Absolute)" +L["Max HP (Short)"] = "Max HP (Short)" +L["Max power (Absolute)"] = "Max power (Absolute)" +L["Max power (Short)"] = "Max power (Short)" +L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."] = "Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is." +L["Max rows"] = "Max rows" +L["Medium"] = "Medium" +L["Minion"] = "Minion" +L["Miscellaneous"] = "Miscellaneous" +L["Missing HP (Short)"] = "Missing HP (Short)" +L["Missing power (Short)"] = "Missing power (Short)" +L["Monk mana bar"] = "Monk mana bar" +L["Monochrome Outline"] = "Monochrome Outline" +L["Moonkin"] = "Moonkin" +L["MT ToT"] = "MT ToT" +L["Mushroom bar"] = "Mushroom bar" +L["Mushrooms"] = "Mushrooms" +L["Name"] = "Name" +L["Name (Abbreviated)"] = "Name (Abbreviated)" +L["Name of a friendly spell to check range."] = "Name of a friendly spell to check range." +L["Neutral"] = "Neutral" +L["Never (Disabled)"] = "Never (Disabled)" +L["New aura group"] = "New aura group" +L["New filter"] = "New filter" +L["None"] = "None" +L["None (Disabled)"] = "None (Disabled)" +L["NPCs only"] = "NPCs only" +L["Off:%s"] = "Off:%s" +L["Offline"] = "Offline" +L["Offline timer"] = "Offline timer" +L["Ok"] = "Ok" +L["On %s units"] = "On %s units" +L["On aggro"] = "On aggro" +L["On curable debuff"] = "On curable debuff" +L["On elite mobs"] = "On elite mobs" +L["On Friendly Units"] = "On Friendly Units" +L["On Hostile Units"] = "On Hostile Units" +L["On mouseover"] = "On mouseover" +L["On rare mobs"] = "On rare mobs" +L["Only active this aura inside an indicator if the group member does not have the aura."] = "Only active this aura inside an indicator if the group member does not have the aura." +L["Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras."] = "Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras." +L["Only auras you specifically cast will be shown."] = "Only auras you specifically cast will be shown." +L["Only show if missing"] = "Only show if missing" +L["Only show self cast auras"] = "Only show self cast auras" +L["Only show when mana"] = "Only show when mana" +L["Or you can set a position manually"] = "Or you can set a position manually" +L["Order"] = "Order" +L["Other Party/Phase Status"] = "Other Party/Phase Status" +L["Out of range alpha"] = "Out of range alpha" +L["Outline"] = "Outline" +L["Outside bar limit"] = "Outside bar limit" +L["Override background"] = "Override background" +L["Override color"] = "Override color" +L["Override list"] = "Override list" +L["Override list filters"] = "Override list filters" +L["Override lists"] = "Override lists" +L["Pain"] = "Pain" +L["Party"] = "Party" +L["Party frames are hidden while in a raid group with more than 5 people inside."] = "Party frames are hidden while in a raid group with more than 5 people inside." +L["Party frames are hidden while in any sort of raid no matter how many people."] = "Party frames are hidden while in any sort of raid no matter how many people." +L["Party instances"] = "Party instances" +L["Party Pet"] = "Party Pet" +L["Party Target"] = "Party Target" +L["Party Target of Target"] = "Party Target of Target" +L["Party ToT"] = "Party ToT" +L["Per column"] = "Per column" +L["Per row"] = "Per row" +L["Percent Demonic Fury"] = "Percent Demonic Fury" +L["Percent HP"] = "Percent HP" +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."] = "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." +L["Percent power"] = "Percent power" +L["Percentage of width the portrait should use."] = "Percentage of width the portrait should use." +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."] = "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." +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."] = "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." +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."] = "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." +L["Pet"] = "Pet" +L["Pet Battle"] = "Pet Battle" +L["Pet Happiness"] = "Pet Happiness" +L["Pet Target"] = "Pet Target" +L["Player"] = "Player" +L["player alt. power"] = "player alt. power" +L["player cast bar"] = "player cast bar" +L["Player Class"] = "Player Class" +L["player power frames"] = "player power frames" +L["Player threat"] = "Player threat" +L["Players only"] = "Players only" +L["Players will be colored by class."] = "Players will be colored by class." +L["Point"] = "Point" +L["Portrait"] = "Portrait" +L["Portrait type"] = "Portrait type" +L["Position"] = "Position" +L["Positioning"] = "Positioning" +L["Power"] = "Power" +L["Power bar"] = "Power bar" +L["Power Type"] = "Power Type" +L["Prevents unit tooltips from showing while in combat."] = "Prevents unit tooltips from showing while in combat." +L["Priest mana bar"] = "Priest mana bar" +L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."] = "Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary." +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."] = "Primary means of coloring the power bar. Coloring by class only applies to players, for non-players it will default to the power type." +L["Prioritize buffs"] = "Prioritize buffs" +L["Priority"] = "Priority" +L["Programming in Lua"] = "Programming in Lua" +L["PvP Flag"] = "PvP Flag" +L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."] = "PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers." +L["PvP Flags"] = "PvP Flags" +L["PVP timer"] = "PVP timer" +L["PVP:%s"] = "PVP:%s" +L["Quest Boss"] = "Quest Boss" +L["Race"] = "Race" +L["Race (Smart)"] = "Race (Smart)" +L["Rage"] = "Rage" +L["Raid"] = "Raid" +L["Raid assisting unit"] = "Raid assisting unit" +L["Raid frames are hidden while in a raid group with 5 or less people inside."] = "Raid frames are hidden while in a raid group with 5 or less people inside." +L["Raid instances"] = "Raid instances" +L["Raid Misc"] = "Raid Misc" +L["Raid pet"] = "Raid pet" +L["Raid Role"] = "Raid Role" +L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."] = "Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists." +L["Raid Target"] = "Raid Target" +L["Raid target indicator."] = "Raid target indicator." +L["Raid targeting unit"] = "Raid targeting unit" +L["Range Checker"] = "Range Checker" +L["Range indicator"] = "Range indicator" +L["Rare"] = "Rare" +L["Rare Elite"] = "Rare Elite" +L["Rare indicator"] = "Rare indicator" +L["Rather than bars filling from left -> right, they will fill from bottom -> top."] = "Rather than bars filling from left -> right, they will fill from bottom -> top." +L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."] = "Reaction color code, use [reactcolor][name][close] to color the units name by their reaction." +L["Reaction color tag"] = "Reaction color tag" +L["Ready Status"] = "Ready Status" +L["Ready status of group members."] = "Ready status of group members." +L["Red (>70% HP)"] = "Red (>70% HP)" +L["Relative point"] = "Relative point" +L["Resources"] = "Resources" +L["Resurrect Status"] = "Resurrect Status" +L["Returns + if the unit is an elite or rare elite mob."] = "Returns + if the unit is an elite or rare elite mob." +L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."] = "Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful." +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."] = "Returns a color code of your general threat situation on all units: Red for Aggro, Orange for High threat and Yellow to watch out." +L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."] = "Returns a scaled threat percent of your aggro on your current target, always 0 - 100%." +L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."] = "Returns current health as a percentage, if the unit is dead or offline than that is shown instead." +L["Returns current power as a percentage."] = "Returns current power as a percentage." +L["Returns Rare if the unit is a rare or rare elite mob."] = "Returns Rare if the unit is a rare or rare elite mob." +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."] = "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." +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."] = "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." +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."] = "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." +L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."] = "Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned." +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."] = "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." +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."] = "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." +L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."] = "Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on." +L["Returns the units sex."] = "Returns the units sex." +L["Reverse fill"] = "Reverse fill" +L["Right"] = "Right" +L["Right Bottom"] = "Right Bottom" +L["Right Center"] = "Right Center" +L["Right text"] = "Right text" +L["Right Top"] = "Right Top" +L["Role the unit is playing."] = "Role the unit is playing." +L["Row growth"] = "Row growth" +L["Row offset"] = "Row offset" +L["Rune bar"] = "Rune bar" +L["Rune of Power"] = "Rune of Power" +L["Rune of Power bar"] = "Rune of Power bar" +L["Rune Timer"] = "Rune Timer" +L["Runes"] = "Runes" +L["Runic Power"] = "Runic Power" +L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."] = "Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red." +L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."] = "Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red." +L["Scale"] = "Scale" +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."] = "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." +L["Scaled aura size"] = "Scaled aura size" +L["Scaled threat percent"] = "Scaled threat percent" +L["Screen"] = "Screen" +L["Search"] = "Search" +L["Search tags"] = "Search tags" +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."] = "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." +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."] = "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." +L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."] = "Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel." +L["Separate raid frames"] = "Separate raid frames" +L["Set Filter Zones"] = "Set Filter Zones" +L["Sex"] = "Sex" +L["Shadow Orbs"] = "Shadow Orbs" +L["Shaman mana bar"] = "Shaman mana bar" +L["Short classification"] = "Short classification" +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."] = "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." +L["Short elite indicator"] = "Short elite indicator" +L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."] = "Short version of [druidform], C = Cat, B = Bear, F = Flight and so on." +L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."] = "Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k." +L["Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k."] = "Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k." +L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."] = "Shorten incoming heal value, if 13,000 healing is incoming it will show 13k." +L["Show a background behind the bars with the same texture/color but faded out."] = "Show a background behind the bars with the same texture/color but faded out." +L["Show any other auras"] = "Show any other auras" +L["Show as bar"] = "Show as bar" +L["Show aura duration"] = "Show aura duration" +L["Show aura icon"] = "Show aura icon" +L["Show auras stack"] = "Show auras stack" +L["Show background"] = "Show background" +L["Show boss debuffs"] = "Show boss debuffs" +L["Show buffs before debuffs when sharing the same anchor point."] = "Show buffs before debuffs when sharing the same anchor point." +L["Show cast name"] = "Show cast name" +L["Show cast time"] = "Show cast time" +L["Show castable on other auras"] = "Show castable on other auras" +L["Show casted by boss"] = "Show casted by boss" +L["Show curable debuffs"] = "Show curable debuffs" +L["Show curable/removable auras"] = "Show curable/removable auras" +L["Show Heal Absorbs"] = "Show Heal Absorbs" +L["Show icon durations"] = "Show icon durations" +L["Show incoming absorbs"] = "Show incoming absorbs" +L["Show incoming heals"] = "Show incoming heals" +L["Show inside"] = "Show inside" +L["Show party as raid"] = "Show party as raid" +L["Show player in party"] = "Show player in party" +L["Show your auras"] = "Show your auras" +L["Shows a bar for alternate power info (used in some encounters)"] = "Shows a bar for alternate power info (used in some encounters)" +L["Shows a cooldown wheel on the indicator with how much time is left on the aura."] = "Shows a cooldown wheel on the indicator with how much time is left on the aura." +L["Shows AFK, DND or nothing depending on the units away status."] = "Shows AFK, DND or nothing depending on the units away status." +L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."] = "Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on." +L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."] = "Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health." +L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."] = "Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power." +L["Shows current group number of the unit."] = "Shows current group number of the unit." +L["Shows current health value in absolute form meaning 15000 health is shown as 15000."] = "Shows current health value in absolute form meaning 15000 health is shown as 15000." +L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."] = "Shows current power value in absolute form, 15000 power will be displayed as 1500 still." +L["Shows debuffs cast by a boss."] = "Shows debuffs cast by a boss." +L["Shows debuffs that you can cure."] = "Shows debuffs that you can cure." +L["Shows how long an unit has been AFK or DND."] = "Shows how long an unit has been AFK or DND." +L["Shows how long an unit has been offline."] = "Shows how long an unit has been offline." +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."] = "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." +L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."] = "Shows maximum health in absolute form, 14000 health is showed as 14000 health." +L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."] = "Shows maximum power in absolute form, 13000 power is showed as 13000 power." +L["Shows Offline, Dead, Ghost or nothing depending on the units current status."] = "Shows Offline, Dead, Ghost or nothing depending on the units current status." +L["Shows that a NPC is a boss for a quest."] = "Shows that a NPC is a boss for a quest." +L["Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000."] = "Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000." +L["Shows the current staggered damage, if 12,000 damage is staggered, shows 12k."] = "Shows the current staggered damage, if 12,000 damage is staggered, shows 12k." +L["Shows the mana power bar for Mistweaver Monks."] = "Shows the mana power bar for Mistweaver Monks." +L["Show's the units guild name if they are in a guild."] = "Show's the units guild name if they are in a guild." +L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."] = "Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%." +L["Shows what kind of pet the unit is for pet battles."] = "Shows what kind of pet the unit is for pet battles." +L["Shows when a party member is in a different phase or another group."] = "Shows when a party member is in a different phase or another group." +L["Simple aura filtering by whitelists and blacklists."] = "Simple aura filtering by whitelists and blacklists." +L["Size"] = "Size" +L["Smart Friendly/Hostile Filter"] = "Smart Friendly/Hostile Filter" +L["Smart level"] = "Smart level" +L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."] = "Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80." +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 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." +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."] = "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." +L["Solid color to use in the indicator, only used if you do not have use aura icon enabled."] = "Solid color to use in the indicator, only used if you do not have use aura icon enabled." +L["Sort method"] = "Sort method" +L["Sort order"] = "Sort order" +L["Sorting"] = "Sorting" +L["Soul Shards"] = "Soul Shards" +L["Soul shards"] = "Soul shards" +L["Spacing"] = "Spacing" +L["Spacing between each row"] = "Spacing between each row" +L["Spell ID %s"] = "Spell ID %s" +L["Spell Name"] = "Spell Name" +L["Spell Name/ID"] = "Spell Name/ID" +L["Spell you want to link to a primary aura, the casing must be exact."] = "Spell you want to link to a primary aura, the casing must be exact." +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."] = "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." +L["Stagger"] = "Stagger" +L["Stagger (Monk)"] = "Stagger (Monk)" +L["Stagger (Monk/Absolute)"] = "Stagger (Monk/Absolute)" +L["Stagger bar"] = "Stagger bar" +L["Stagger bar color when the staggered amount is <30% of your HP."] = "Stagger bar color when the staggered amount is <30% of your HP." +L["Stagger bar color when the staggered amount is >30% of your HP."] = "Stagger bar color when the staggered amount is >30% of your HP." +L["Stagger bar color when the staggered amount is >70% of your HP."] = "Stagger bar color when the staggered amount is >70% of your HP." +L["Stagger Power"] = "Show Stagger Power" +L["Static"] = "Static" +L["Statue"] = "Statue" +L["Statue bar"] = "Statue bar" +L["Status"] = "Status" +L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."] = "Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested." +L["Stealable/Curable/Dispellable"] = "Stealable/Curable/Dispellable" +L["Style of borders to show for all auras."] = "Style of borders to show for all auras." +L["Summon Pending"] = "Summon Pending" +L["T"] = "T" +L["Tag list"] = "Tag list" +L["Tag name"] = "Tag name" +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]."] = "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]." +L["Tags"] = "Tags" +L["Talent spec of your arena opponents."] = "Talent spec of your arena opponents." +L["Target"] = "Target" +L["Target of Target"] = "Target of Target" +L["Target of Target of Target"] = "Target of Target of Target" +L["Test Aura"] = "Test Aura" +L["Test spell"] = "Test spell" +L["Text"] = "Text" +L["Text Management"] = "Text Management" +L["Text name"] = "Text name" +L["Text name that you can use to identify this text from others when configuring."] = "Text name that you can use to identify this text from others when configuring." +L["Text parent"] = "Text parent" +L["Text/Tags"] = "Text/Tags" +L["The blacklist \"%s\" already exists."] = "The blacklist \"%s\" already exists." +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."] = "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." +L["The override list \"%s\" already exists."] = "The override list \"%s\" already exists." +L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."] = "The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type." +L["The tag \"%s\" already exists."] = "The tag \"%s\" already exists." +L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."] = "The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below." +L["The whitelist \"%s\" already exists."] = "The whitelist \"%s\" already exists." +L["Thick outline"] = "Thick outline" +L["Thin outline"] = "Thin outline" +L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."] = "This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked." +L[ [=[This color will be used if the indicator shown is your own, only applies if icons are not used. +Handy 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.]=] ] = [=[This color will be used if the indicator shown is your own, only applies if icons are not used. +Handy 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.]=] +L["This filter has no aura types set to filter out."] = "This filter has no aura types set to filter out." +L["This filter has no auras in it, you will have to add some using the dialog above."] = "This filter has no auras in it, you will have to add some using the dialog above." +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."] = "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." +L["This unit depends on another to work, disabling %s will disable %s."] = "This unit depends on another to work, disabling %s will disable %s." +L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."] = "This unit has child units that depend on it, you need to enable this unit before you can enable its children." +L[ [=[This will be set for your current class only. +If no custom spells are set, defaults appropriate for your class will be used.]=] ] = [=[This will be set for your current class only. +If no custom spells are set, defaults appropriate for your class will be used.]=] +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."] = "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." +L["This will override all background colorings for bars including custom set ones."] = "This will override all background colorings for bars including custom set ones." +L["Threat"] = "Threat" +L["Threat situation"] = "Threat situation" +L["Tile size"] = "Tile size" +L["Timer Text"] = "Timer Text" +L["Top"] = "Top" +L["Top Center"] = "Top Center" +L["Top Left"] = "Top Left" +L["Top Right"] = "Top Right" +L["Total number of active holy power."] = "Total number of active holy power." +L["Total number of active soul shards."] = "Total number of active soul shards." +L["Total number of combo points you have on your target."] = "Total number of combo points you have on your target." +L["Totem bar"] = "Totem bar" +L["Totem Timer"] = "Totem Timer" +L["Travel"] = "Travel" +L["Tree"] = "Tree" +L["Turns this widget into a bar that can be resized and ordered just like health and power bars."] = "Turns this widget into a bar that can be resized and ordered just like health and power bars." +L["Unattackable hostile"] = "Unattackable hostile" +L["Unchecking this will completely disable aura indicators for %s."] = "Unchecking this will completely disable aura indicators for %s." +L["Unit color code on aggro"] = "Unit color code on aggro" +L["Unit colored situation"] = "Unit colored situation" +L["Unit Configuration"] = "Unit Configuration" +L["Unit faction"] = "Unit faction" +L["Unit name"] = "Unit name" +L["Unit name (Class colored)"] = "Unit name (Class colored)" +L["Unit name colored by class."] = "Unit name colored by class." +L["Unit scaled threat"] = "Unit scaled threat" +L["Unit server"] = "Unit server" +L["Unit server, if they are from your server then nothing is shown."] = "Unit server, if they are from your server then nothing is shown." +L["Unit situation name"] = "Unit situation name" +L["Units"] = "Units" +L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."] = "Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance." +L["Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those."] = "Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those." +L["Units per column"] = "Units per column" +L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."] = "Units race, Blood Elf, Tauren, Troll (unfortunately) and so on." +L["Units that should have the aura groups settings changed below."] = "Units that should have the aura groups settings changed below." +L["Units to change"] = "Units to change" +L["Unknown"] = "Unknown" +L["Unlink frames"] = "Unlink frames" +L["Up"] = "Up" +L["Update interval"] = "Update interval" +L["Use Boss Mod Cast Name overrides"] = "Use Boss Mod Cast Name overrides" +L["Use spell name overrides provided by boss mods (BigWigs) on the cast bars."] = "Use spell name overrides provided by boss mods (BigWigs) on the cast bars." +L["Uses the icon of the totem being shown instead of a status bar."] = "Uses the icon of the totem being shown instead of a status bar." +L["Using unit settings"] = "Using unit settings" +L["Various units can be enabled through this page, such as raid or party targets."] = "Various units can be enabled through this page, such as raid or party targets." +L["Vehicle"] = "Vehicle" +L["Vehicles"] = "Vehicles" +L["Vertical growth"] = "Vertical growth" +L["View"] = "View" +L["Visibility"] = "Visibility" +L["WARNING! ShadowedUF_Indicators has been deprecated as v4 and is now built in. Please delete ShadowedUF_Indicators, your configuration will be saved."] = "WARNING! ShadowedUF_Indicators has been deprecated as v4 and is now built in. Please delete ShadowedUF_Indicators, your configuration will be saved." +L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] = "WARNING: This will unlink all frames from each other so you can move them without another frame moving with it." +L["What group this aura belongs to, this is where you will find it when configuring."] = "What group this aura belongs to, this is where you will find it when configuring." +L["What type of auras should be enlarged, use the scaled aura size option to change the size."] = "What type of auras should be enlarged, use the scaled aura size option to change the size." +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."] = "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." +L["When this filter is active, apply the filter to buffs."] = "When this filter is active, apply the filter to buffs." +L["When this filter is active, apply the filter to debuffs."] = "When this filter is active, apply the filter to debuffs." +L["When to color the empty bar by reaction, overriding the default color by option."] = "When to color the empty bar by reaction, overriding the default color by option." +L["When to color the health bar by the units reaction, overriding the color health by option."] = "When to color the health bar by the units reaction, overriding the color health by option." +L["When to show cooldown rings on auras"] = "When to show cooldown rings on auras" +L["Where inside the frame the text should be anchored to."] = "Where inside the frame the text should be anchored to." +L["Where to anchor the cast name text."] = "Where to anchor the cast name text." +L["Where to anchor the cast time text."] = "Where to anchor the cast time text." +L["Whether auras you casted should be shown"] = "Whether auras you casted should be shown" +L["Whether to show any auras casted by the boss"] = "Whether to show any auras casted by the boss" +L["Whether to show any debuffs you can remove, cure or steal."] = "Whether to show any debuffs you can remove, cure or steal." +L["Whether to show auras that do not fall into the above categories."] = "Whether to show auras that do not fall into the above categories." +L["Whether to show buffs that you cannot cast."] = "Whether to show buffs that you cannot cast." +L["Whitelist"] = "Whitelist" +L["Whitelist filters"] = "Whitelist filters" +L["Whitelists"] = "Whitelists" +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."] = "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." +L["Widget Size"] = "Widget Size" +L["Width"] = "Width" +L["Width percent"] = "Width percent" +L["Width weight"] = "Width weight" +L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."] = "Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth." +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"] = "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" +L["Works the same as [%s], but this is only shown if you are a Mistweaver Monk."] = "Works the same as [%s], but this is only shown if you are a Mistweaver Monk." +L["Works the same as [%s], but this is usedd to show Demonic Fury power for Demonology Warlocks."] = "Works the same as [%s], but this is usedd to show Demonic Fury power for Demonology Warlocks." +L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."] = "Works the same as [%s], but always shows mana and is only shown if mana is a secondary power." +L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."] = "Works the same as [%s], but this is only shown if the unit is in Cat or Bear form." +L["WoW Programming"] = "WoW Programming" +L["WoW Programming is a good resource for finding out what difference API's do and how to call them."] = "WoW Programming is a good resource for finding out what difference API's do and how to call them." +L["X Offset"] = "X Offset" +L["XP/Rep bar"] = "XP/Rep bar" +L["Y Offset"] = "Y Offset" +L["Yellow (>30% HP)"] = "Yellow (>30% HP)" +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."] = "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." +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."] = "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." +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."] = "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." +L["You can find more information on creating your own custom tags in the \"Help\" tab above."] = "You can find more information on creating your own custom tags in the \"Help\" tab above." +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."] = "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." +L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] = "You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient." +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."] = "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." +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."] = "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." +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."] = "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." +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."] = "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." +L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."] = "You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis." +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."] = "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." +L["You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf."] = "You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf." +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."] = "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." +L["You must enter a number that is 0 or higher, negative numbers are not allowed."] = "You must enter a number that is 0 or higher, negative numbers are not allowed." +L["You must enter a tag name."] = "You must enter a tag name." +L["You must restart Shadowed Unit Frames."] = "You must restart Shadowed Unit Frames." +L["You must wrap your code in a function."] = "You must wrap your code in a function." +L["You will need to create an aura filter before you can set which unit to enable aura filtering on."] = "You will need to create an aura filter before you can set which unit to enable aura filtering on." +L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."] = "You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames." +L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] = "Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again." +L["Your aura color"] = "Your aura color" +L["Your Auras"] = "Your Auras" +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"] = "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" +L["Zone Configuration"] = "Zone Configuration" +L["Zone configuration units"] = "Zone configuration units" + + +ShadowUF.L = L +--[==[@debug@ +ShadowUF.L = setmetatable(ShadowUF.L, { + __index = function(tbl, value) + rawset(tbl, value, value) + return value + end, +}) +--@end-debug@]==] diff --git a/localization/esES.lua b/localization/esES.lua index 368c1068f..c5731a8eb 100755 --- a/localization/esES.lua +++ b/localization/esES.lua @@ -1,5 +1,473 @@ -if( GetLocale() ~= "esES" ) then return end -local L = {} ---@localization(locale="esES", format="lua_additive_table", handle-unlocalized="ignore")@ -local ShadowUF = select(2, ...) -ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) +if( GetLocale() ~= "esES" ) then return end +local L = {} +L["%d auras in group"] = "%d auras en el grupo" +L["%s (%s): %s/%s (%.2f%% done)"] = "%s (%s): %s/%s (%.2f%% hecho)" +L["%s aura groups disabled"] = "%s grupos de auras desactivadas" +L["%s frames"] = "%s marcos" +L["%s member"] = "%s miembro" +L["|cff20ff20%s|r units enabled"] = "|cff20ff20%s|r unidades habilitadas" +L["|cffff2020%s|r units disabled"] = "|cffff2020%s|r unidades desactivadas" +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."] = "|cffff2020Warning!|r Algunas unidades tienen anulaciones establecidas en la configuración de la zona y pueden mostrarse (o no aparecer) en ciertas zonas. Independientemente de la configuración establecida a continuación." +L["1 aura group disabled"] = "1 grupo de aura deshabilitado" +L["2D"] = "2D" +L["3D"] = "3D" +L["A"] = "A" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "Abrevia nombres de las unidades de más de 10 carácteres, \"Dark Runa Champion\" se convierte en \"D.R.Champion\" y \"Dark Runa Commoner\" se convierte en \"D.R.Commoner\"." +L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."] = "Valor absoluto de absorción de daño en la unidad, si se absorven 10.000 puntos de daño, se mostrará 10.000." +L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."] = "Valor absoluto de absorción de curación, si se absorven 16.000 puntos de curación, se mostrará 16.000." +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "Valor absoluto de cura entrante, si la curación entrante es 10,000 se mostrará 10,000." +L["Add"] = "Añade" +L["Add Aura"] = "Añadir Aura" +L["Add aura"] = "Añadir aura" +L["Add Indicator"] = "Añadir Indicador" +L["Add link"] = "Añadir enlace" +L["Add new indicator"] = "Añadir nuevo indicador" +L["Add new tag"] = "Añadir nueva etiqueta" +L["Add new text"] = "Añade nuevo texto" +L["Add Tags"] = "Añadir etiquetas" +L["Adds %s to the list of units to be modified when you change values in this tab."] = "Añade %s a la lista de unidades para ser modificadas cuando cambias el valor en esta pestaña" +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "Añade una barra indicando cuánto tiempo queda en el cronómetro de tu necrófago, sólo se utiliza si no tienes un necrófago permanente." +L["Adds a bar indicating how much time is left on your mushrooms."] = "Añade una barra que indica cuánto tiempo queda en tus champiñones." +L["Adds a bar indicating how much time is left on your Rune of Power."] = "Añade una barra indicando cuánto tiempo le queda a tu Runa de Poder." +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = "Añade una barra dentro de la barra de salud que indica cuánto daño se absorberá." +L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."] = "Añade una barra dentro de la barra de salud indicando cuánta sanación se estima que se va a recibir." +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = "Añade una barra dentro de la barra de salud que indica cuánta curación recibirá alguien." +L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."] = "Añade una barra dentro de la barra de salud que indica cuánta curación se absorberá y no se aplicará al jugador." +L["Adds a mana bar to the player frame for elemental and enhancement shamans."] = "Añade una barra de maná al marco del jugador para chamanes elementales y de mejora." +L["Adds a mana bar to the player frame for shadow priests."] = "Añade una barra de maná al marco del jugador para los sacerdotes sombras." +L["Adds a Stagger bar for Brewmaster Monks."] = "Añade una barra escalonada para los monjes Maestro Cervecero." +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "Añade una barra vacía en la que puedes poner texto, de forma que despeja otras barras." +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "Añade otra barra de maná al marco del jugador cuando está en forma de oso o gato, mostrando la cantidad de maná que tienes." +L["Adds rune bars and timers before runes refresh to the player frame."] = "Añade al marco del jugador barras de runas y temporizadores antes de que las runas se actualicen." +L["Adds temporary enchants to the buffs for the player."] = "Añade encantamientos temporales a los beneficios para el jugador." +L["Adds totem bars with timers before they expire to the player frame."] = "Añade barras de tótem con temporizadores antes de que caduquen en el marco del jugador." +L["Advanced"] = "Avanzado" +L["Advanced tag management, allows you to add your own custom tags."] = "La gestión avanzada de etiquetas te permite agregar tus propias etiquetas personalizadas." +L["AFK"] = "AUS" +L["AFK status"] = "Estado AUS" +L["AFK timer"] = "Tiempo AUS" +L["AFK:%s"] = "AUS:%s" +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "Después de pulsar en exportar, puede proporcionar el siguiente código a otros usuarios de Shadowed Unit Frames y obtendrán su diseño exacto." +L["Aggro"] = "Amenaza" +L["All aura groups enabled for unit."] = "Todos los grupos de aura habilitados para la unidad." +L["All Auras"] = "Todas las Auras" +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."] = "Le permite anclar el grupo de aura a otro, después puede elegir dónde se anclará utilizando la posición.|n|nUtilice esto si desea duplicar el estilo de interfaz de usuario predeterminado donde los bufos y debufos están en grupos separados." +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."] = "Te permite desactivar el tótem haciendo clic derecho sobre él.|n|nAdvertencia: si habilitas esto las barras internas de esta unidad no cambiarán de tamaño en combate." +L["Allows you to enter a new aura group."] = "Te permite añadir un nuevo grupo de aura." +L["Alpha to use for bar backgrounds."] = "Alfa para usar en fondos de barra." +L["Alpha to use for bar."] = "Alfa para usar en la barra." +L["Alt. Power"] = "Poder Alt." +L["Alt. Power bar"] = "Barra de Poder Alt." +L["Alternate power is used for things like quests and dungeons."] = "El poder alternativo se usa para cosas como misiones y mazmorras." +L["Alternate Spell Name"] = "Nombre de hechizo alternativo" +L["Alternatively friendly spell to use to check range."] = "Hechizo amigable alternativo para usar para verificar el rango." +L["Ammo"] = "Munición" +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."] = "Cantidad de salud que falta, si no falta, no se muestra nada. Utiliza un formato corto, -18500 se muestra como -18.5k, los valores inferiores a 10000 se formatean tal cual." +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."] = "Cantidad de energía que falta, si no falta no se muestra nada. Utiliza un formato corto, -13.850 se muestra como 13.8k, valores por debajo de 10.000 están en este formato." +L["Anchor point"] = "Punto de anclaje" +L["Anchor to"] = "Anclado a" +L["Anchor to another frame"] = "Anclado a otro marco" +L["Anchor to buffs"] = "Anclado a los buffs" +L["Anchor to debuffs"] = "Anclado a los debuff" +L["Any auras shown in this indicator will have their total stack displayed."] = "Cualquier aura que se muestre en este indicador mostrará su montón total." +L["Aquatic"] = "Acuático" +L["Arcane Charges"] = "Cargas Arcanas" +L["Are you sure you want to delete this aura?"] = "¿Seguro que deseas eliminar este aura?" +L["Are you sure you want to delete this filter?"] = "¿Está seguro que desea eliminar este filtro?" +L["Are you sure you want to delete this indicator?"] = "¿Seguro que deseas eliminar este indicador?" +L["Are you sure you want to delete this tag?"] = "¿Está seguro que desea eliminar esta etiqueta?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "¿Está seguro de que desea eliminar este texto? Todos los ajustes de este serán eliminados." +L["Arena"] = "Arena" +L["Arenas"] = "Arenas" +L["Ascending"] = "Ascendente" +L["Assigned Role (DPS/Tank/etc)"] = "Rol Asignado (Rango/tanque/etc.)" +L["Astral Power"] = "Poder Astral" +L["Aura border style"] = "Estilo del borde del Aura" +L["Aura borders"] = "Bordes de Aura" +L["Aura Combo Points"] = "Puntos de Combo de Aura" +L["Aura Filters"] = "Filtro de Aura" +L["Aura filters"] = "Filtros de Auras" +L["Aura group"] = "Grupo de aura" +L["Aura groups"] = "Grupos de aura" +L["Aura Groups"] = "Grupos de Auras" +L["Aura Indicators"] = "Indicadores de Auras" +L["Aura indicators"] = "Indicadores de aura" +L["Aura name or spell ID"] = "Nombre del aura o ID del hechizo" +L["Aura types to filter"] = "Filtro de tipo de Auras" +L["Auras"] = "Auras" +L["Auras matching a criteria will automatically show up in the indicator when enabled."] = "Las auras que coinciden con un criterio aparecerán automáticamente en el indicador cuando estén habilitadas." +L["Automatic Auras"] = "Auras automaticas " +L["Background"] = "Fondo" +L["Background alpha"] = "Trasparencia del fondo" +L["Background color"] = "Color del fondo" +L["Background/border"] = "Fondo/contorno" +L["Bag indicator for master looters."] = "Bolsa indicadora para Maestro despojador" +L["Bar color to use to show how much healing someone is about to receive."] = "Color de la barra que muestra cuánta sanación está alguien a punto de recibir." +L["Bar spacing"] = "Espacio entre barras" +L["Bar texture"] = "Textura de barras" +L["Bars"] = "Barras" +L["Battleground"] = "Campo de batalla" +L["Battlegrounds"] = "Campos de Batalla" +L["Bear"] = "Oso" +L["BG"] = "CB" +L["BG Pet"] = "Mascota CB" +L["Blacklist"] = "Lista negra" +L["Blacklist filters"] = "Filtro de Lista negra" +L["Blacklists"] = "Listas negras" +L["Blizzard"] = "Blizzard" +L["Border"] = "Contorno" +L["Border alpha"] = "trasparencia contorno " +L["Border color"] = "Color del contorno " +L["Border highlighting"] = "Resaltado contorno " +L["Border thickness"] = "Grosor contorno" +L["Boss"] = "Jefe" +L["Boss Auras"] = "Auras del Jefe" +L["Boss Debuffs"] = "Debufos del Jefe" +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."] = "Unidades de Jefes son sólo para ciertas luchas, como los Princesa Sangrienta o de la batalla Gunship, no los vera para cada lucha del jefes." +L["Both"] = "Ambos" +L["Bottom"] = "Abajo" +L["Bottom Center"] = "Abajo centro" +L["Bottom Left"] = "Abajo izquierda" +L["Bottom Right"] = "Abajo derecha" +L["buff frames"] = "Marcos de bufos" +L["Buffs"] = "Buffs" +L["Cannot find any profiles named \"%s\"."] = "No se ha encontrado ningún perfil llamado \"%s\"." +L["Cast"] = "Lanzar" +L["Cast bar"] = "Barra de lanzamiento" +L["Cast icon"] = "Icono de lanzamiento" +L["Cast interrupted"] = "Lanzamiento interrumpido" +L["Cast name"] = "Nombre de Hechizo" +L["Cast time"] = "Tiempo de lanzamiento" +L["Cast uninterruptible"] = "Lanzar ininterrumpible" +L["Casting"] = "Lanzando" +L["Cat"] = "Gato" +L["Category"] = "Categoría" +L["Center"] = "Centro" +L["Changed profile to %s."] = "Perfil cambiado a %s." +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = "Cambia la barra de salud al color hostil establecido (rojo por defecto) cuando la unidad recibe amenaza." +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."] = "Cambia este aplicación en una barra, que será capaz de cambiar la altura y ordenar como se puede cambiar las barras de salud y poder." +L["Channelling"] = "Canalizando" +L["Chi Points"] = "Puntos de Chi" +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = "Unidades filiales no se puede arrastrar, que tendrá que cambiar la posición a través de / shadowuf." +L["Class"] = "Clase" +L["Class (Smart)"] = "Clase (inteligente)" +L["Class color tag"] = "Etiqueta de color de clase" +L["Class icon"] = "Icono de clase" +L["Class Icon"] = "Icono de clase" +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = "Si el nombre de la clase está sin color, usa [classcolor][class][close] si deseas que el nombre de la clase tenga el color de la clase." +L["Classes"] = "Clases" +L["Classification"] = "Clasificación" +L["Classifications"] = "Clasificaciones" +L["Clip"] = "sujetar" +L["Close color"] = "Cierra color" +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = "Cierra un código de color, evita que los colores aparezcan en el texto en que no quieres que lo haga." +L["Code"] = "Código" +L["Color by class"] = "Color por clase" +L["Color by reaction on"] = "Color por reacción en" +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."] = "Código de color en función del porcentaje de salud restante en la unidad, esto funciona de la misma forma como en la opción de color por salud. Pero para el texto en lugar de la barra entera." +L["Color code for general situation"] = "Código de color para situación general" +L["Color code for situation"] = "Código de color para situación" +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = "Código de color por clase, utilice [classcolor][class][close] si desea que el texto de la clase esté influido por la clase" +L["Color code on aggro"] = "Codigo de color en amenaza" +L["Color health by"] = "Color de salud por" +L["Color on aggro"] = "Color en agresivo" +L["Color to use for health bars that are set to be colored by a static color."] = "Color a utilizar para las barras de salud que se establecen para ser coloreado con un color estático." +L["Color to use to show how much damage will be absorbed."] = "Color a usar para mostrar cuánto daño será absorbido." +L["Color to use to show how much healing will e absorbed."] = "Color a usar para mostrar cuánta sanación será absorbida." +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = "Color que se utiliza cuando una lanzamiento no puede ser interrumpido, esta sólo se utiliza para las unidades PvE." +L["Color used when a cast is a channel."] = "Color que se utiliza cuando un lanzamiento es una canalización." +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "Color usado cuando un lanzamiento se ve interrumpido por el propio taumaturgo o por otra unidad." +L["Color used when a cast is successfully finished."] = "Color usado cuando un lanzamiento finaliza con éxito." +L["Color used when an unit is casting a spell."] = "Color usado cuando una unidad está casteando un hechizo." +L["Colors"] = "Colores" +L["Column growth"] = "Crecimiento de Columna" +L["Column spacing"] = "Separación de columna " +L["Combat alpha"] = "Trasparencia en Combate" +L["Combat fader"] = "Atenua en combate" +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."] = "Atenua en combate desvanecerá todos sus marcos, mientras que esta inactiva y desaparece de nuevo una vez que esté en combate o en activo." +L["Combat Status"] = "Estado de combate" +L["Combat text"] = "Texto de combate" +L["Combat/resting status"] = "Combate/descanso estado" +L["Combo points"] = "Puntos de combo" +L["Combo Points"] = "Puntos de Combo" +L["Configuration to specific unit frames."] = "Configuración de unidades de marco especifico" +L["Create"] = "Crear" +L["Creature type"] = "Tipo de Criatura" +L["Cur/Max HP (Absolute)"] = "Actual/Máximo HP (Absoluto)" +L["Cur/Max HP (Short)"] = "Actual/Máximo HP (Corto)" +L["Cur/Max power (Druid)"] = "Actual/Máximo Mana (Druida)" +L["Cur/Max Power (Short)"] = "Actual/Máximo Mana (Corto)" +L["Curable Auras"] = "Auras Curables" +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "Actual y Máximo Mana, tienen el formato [curpp]/[maxpp]" +L["Current HP (Absolute)"] = "Actual HP (Absoluto)" +L["Current HP (Short)"] = "Actual HP (Corto)" +L["Current power (Absolute)"] = "Actual Mana (Absoluto)" +L["Current power (Druid)"] = "Actual Mana (Druida)" +L["Current power (Druid/Absolute)"] = "Actual Mana (Druida/Absoluto)" +L["Current Power (Short)"] = "Actual Mana (Corto)" +L["Currently modifying"] = "Actualmente modificando" +L["Damage absorption (Absolute)"] = "Absorción de Daño (Absoluto)" +L["Damage absorption (Short)"] = "Absorción de Daño (Corto)" +L["Damage absorption/Name"] = "Absorción de Daño/Nombre" +L["Dark"] = "Oscuro" +L["Dead"] = "Muerto" +L["Debuffs"] = "Debufos" +L["Decimal percent HP"] = "Porcentaje decimal HP" +L["Default color"] = "Color por defecto" +L["Delete"] = "Borrar" +L["Delete filter"] = "Borrar filtros " +L["Delete link"] = "Borrar unión " +L["Descending"] = "Descendiente" +L["Disable Auras by Class"] = "Desactivar Auras por Clases" +L["Disable vehicle swap"] = "Intercambio de vehículos descativado" +L["Disabled"] = "Desactivado" +L["Disabled for %s."] = "Desactivado para %s" +L["Disabled in %s"] = "Desactivado en %s" +L["Display"] = "Mostrar" +L["DND"] = "NM" +L["DND:%s"] = "NM:%S" +L["Documentation"] = "Documentación " +L["Don't hide when empty"] = "No ocultar cuando esté vacío." +L["Don't use a filter"] = "No usar filtros" +L["Down"] = "Abajo" +L["Druid form"] = "Forma de druida" +L["Druid form (Short)"] = "Forma del Druida (Corto)" +L["Druid mana bar"] = "Barra de maná del druida" +L["Edit tag"] = "Editar etiqueta" +L["Editing %s"] = "Editando %s" +L["Elite"] = "Élite" +L["Empty bar"] = "Barra vacía" +L["Enable %s"] = "Habilitar %s" +L["Enable buffs"] = "Habilitar bufos" +L["Enable debuffs"] = "Habilitar debufos" +L["Enable for friendlies"] = "Habilitar para amistosos" +L["Enable for hostiles"] = "Habilitar para hostiles" +L["Enable frequent updates"] = "Habilitar actualizaciones frecuentes" +L["Enable indicator"] = "Habilitar indicador" +L["Enable Indicators"] = "Habilitar indicadores" +L["Enable temporary enchants"] = "Habilitar encantamientos temporales" +L["Enable units"] = "Habilitar unidades" +L["Enabled for %s."] = "Habilitado para %s" +L["Enabled in %s"] = "Habilitado en %s" +L["Enabled Units"] = "Unidades habilitadas" +L["Energy"] = "Energía" +L["Error"] = "Error" +L["Events"] = "Eventos" +L["Export"] = "Exportar" +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "Error intentando cargar ShadowedUF_Options, no se pudo abrir la configuración. Error recibido: %s" +L["Failed to save tag, error:|n %s"] = "No se ha podido guardar la etiqueta, error:|n %s" +L["Female"] = "Hembra" +L["Filtering buffs only"] = "Filtrando solo bufos" +L["Filtering debuffs only"] = "Filtrando solo debufos " +L["Filters"] = "Filtros" +L["Finished cast"] = "Casteo terminado" +L["Flight"] = "Vuelo" +L["Focus"] = "Focus" +L["Font"] = "Fuente" +L["Food"] = "Comida" +L["For target/focus"] = "Para objetivo/focus" +L["Frame"] = "Marco" +L["Frames"] = "Marcos" +L["Friendly"] = "Amistoso" +L["Fuel"] = "Combustible" +L["Full size after"] = "Tamaño completo después " +L["Full size before"] = "Tamaño completo antes " +L["Fury"] = "Furia" +L["General"] = "General" +L["General configuration to all enabled units."] = "Configuración general a todas las unidades activadas" +L["Ghost"] = "Fantasma" +L["Global"] = "General" +L["Green (<30% HP)"] = "Verde (<30% HP)" +L["Group %d"] = "Grupo %d" +L["Group by"] = "Grupos por" +L["Group number"] = "Número de grupo " +L["Group row spacing"] = "Espaciado entre las columnas de los grupos" +L["Groups"] = "Grupos" +L["Groups per row"] = "Grupos por columna" +L["Groups to show"] = "Grupos a mostrar" +L["Growth"] = "Crecimiento" +L["Guild name"] = "Nombre de Hermandad" +L["Half health"] = "Salud media" +L["Has Aggro"] = "Tiene Aggro" +L["Heal absorb"] = "Sanación Absorvida" +L["Heal Absorb (Absolute)"] = "Sanación Absorvida (Absoluta)" +L["Heal Absorb (Short)"] = "Sanación Absorvida (Corto)" +L["Heal absorbs"] = "Sanaciones Absorvidas" +L["Health"] = "Salud" +L["Health bar"] = "Barra de salud" +L["Health bar color for friendly units."] = "Color de barra de salud para unidades amigas" +L["Health bar color for hostile units."] = "Color de barra de salud para unidades hostiles" +L["Health bar color for neutral units."] = "Color de barra de salud para unidades neutrales" +L["Health bar color for units with aggro."] = "Color de la barra de salud para unidades con amenaza." +L["Health color"] = "Color de Salud" +L["Health percent"] = "Porcentaje de Salud" +L["Height"] = "Altura" +L["Help"] = "Ayuda" +L["Hide %s"] = "Ocultar %s" +L["Hide %s frames"] = "Ocultar %s marcos" +L["Hide bar when empty"] = "Ocultar barra cuando esté vacía" +L["Hide Blizzard"] = "Ocultar Blizzard" +L["Hide in any raid"] = "Ocultar en cualquier raid" +L["Hide tooltips in combat"] = "Ocultar tooltips en combate" +L["Hides the cast bar if there is no cast active."] = "Oculta la barra de lanzamiento si no hay ninguno activo." +L["Hides the power bar unless the class has mana."] = "Oculta la barra de poder a menos que la clase tenga maná." +L["High"] = "Alto" +L["High health"] = "Salud alta" +L["Holy Power"] = "Poder Sagrado" +L["Hostile"] = "Hostil" +L["Icon Size"] = "Tamaño del icono" +L["Import"] = "Importar" +L["Import unit frame positions"] = "Importar posiciones de la unidad de marcos" +L["In range alpha"] = "En rango alpha" +L["Inactive alpha"] = "Alpha inactivo" +L["Incoming absorb"] = "Absorciones entrantes" +L["Incoming absorbs"] = "Absorciones entrantes" +L["Incoming heal"] = "Sanación entrante" +L["Incoming heal (Absolute)"] = "Sanación entrante (Absoluta)" +L["Incoming heal (Percent)"] = "Sanación entrante (Porcentaje)" +L["Incoming heal (Short)"] = "Sanación entrante (Corto)" +L["Incoming heal/Name"] = "Sanación entrante/Nombre" +L["Incoming heals"] = "Sanaciones entrantes" +L["Index"] = "Índice" +L["Indicator color"] = "Color del indicador" +L["Indicator name"] = "Nombre del indicador" +L["Indicators"] = "Indicadores" +L["Insanity"] = "Locura" +L["Interrupted"] = "Interrumpido" +L["Invalid interval entered, must be a number."] = "Carácter ingresado invalido, debe ser un número." +L["Invalid spell \"%s\" entered."] = "Hechizo invalido %s ingresado" +L["Invert colors"] = "Invertir colores" +L["Leader / Assist"] = "Lider/Asistente" +L["Left"] = "Izquierda" +L["Left Bottom"] = "Izquierda abajo" +L["Left Center"] = "Izquierda centro" +L["Left Top"] = "Izquierda arriba" +L["Level"] = "Nivel" +L["Level %s - %s: %s/%s (%.2f%% done)"] = "Nivel %s - %s: %s/%s (%.2f%% hecho)" +L["Level %s - %s: %s/%s (%.2f%% done), %s rested."] = "Nivel %s - %s: %s/%s (%.2f%% hecho) %s restante." +L["Light"] = "Luz" +L["Link"] = "Unir" +L["Link from"] = "Unir desde " +L["Link to"] = "Unir a " +L["Linked spells"] = "Hechizos encadenados" +L["Lock frames"] = "Bloquear marcos" +L["Low health"] = "Salud baja" +L["Main Tank"] = "Tanque principal" +L["Male"] = "Varón" +L["Mana"] = "Maná" +L["Manual position"] = "Posición manual" +L["Master Looter"] = "Maestro despojador" +L["Minion"] = "Esbirro" +L["Moonkin"] = "Lechuchico" +L["Name"] = "Nombre" +L["Name (Abbreviated)"] = "Nombre (abreviado)" +L["Neutral"] = "Neutral" +L["Never (Disabled)"] = "Nunca (deshabilitado)" +L["New aura group"] = "Nuevo grupo de auras" +L["New filter"] = "Nuevo filtro" +L["None"] = "Ninguno" +L["None (Disabled)"] = "Ninguno (Desactivado)" +L["NPCs only"] = "Solo PNJs" +L["Offline"] = "Desconectado" +L["On %s units"] = "Sobre %s unidades" +L["Order"] = "Orden" +L["Pain"] = "Dolor" +L["Party"] = "Grupo" +L["Party frames are hidden while in a raid group with more than 5 people inside."] = "Los marcos de grupo están ocultos cuando se está en grupo de raid con más de 5 personas." +L["Pet"] = "Mascota" +L["Pet Happiness"] = "Felicidad de la mascota" +L["Player"] = "Jugador" +L["Player Class"] = "Clase del jugador" +L["Player threat"] = "Amenaza del jugador" +L["Players will be colored by class."] = "Los jugadores serán coloreados por clase." +L["Portrait"] = "Retrato" +L["Portrait type"] = "Tipo de retrato" +L["Position"] = "Posición" +L["Positioning"] = "Posicionamiento" +L["Power"] = "Poder" +L["Power bar"] = "Barra de poder" +L["Priest mana bar"] = "Barra de maná del sacerdote" +L["Priority"] = "Prioridad" +L["PvP Flag"] = "Bandera PVP" +L["PvP Flags"] = "Banderas PvP" +L["PVP:%s"] = "PvP:%s" +L["Quest Boss"] = "Jefe de misión" +L["Race"] = "Raza" +L["Red (>70% HP)"] = "Rojo (>70% HP)" +L["Right"] = "Derecha" +L["Rune bar"] = "Barra de runas" +L["Rune of Power"] = "Runa de Poder" +L["Runes"] = "Runas" +L["Runic Power"] = "Poder rúnico" +L["Scale"] = "Escala" +L["Screen"] = "Pantalla" +L["Search"] = "Buscar" +L["Search tags"] = "Buscar etiquetas" +L["Sex"] = "Sexo" +L["Shadow Orbs"] = "Orbes de las Sombras" +L["Shaman mana bar"] = "Barra de maná del chamán" +L["Show any other auras"] = "Mostrar cualquier otras auras" +L["Show as bar"] = "Mostrar como barra" +L["Show aura duration"] = "Mostrar duración del aura" +L["Show aura icon"] = "Mostrar icono del aura" +L["Show auras stack"] = "Mostrar acumulaciones de auras" +L["Show background"] = "Mostrar fondo" +L["Show boss debuffs"] = "Mostrar debufos del Jefe" +L["Show cast name"] = "Mostrar nombre del lanzamiento" +L["Show cast time"] = "Mostrar tiempo de lanzamiento" +L["Show casted by boss"] = "Mostrar casteos del Jefe" +L["Show curable debuffs"] = "Mostrar debufos curables" +L["Show curable/removable auras"] = "mostrar auras curables/removibles" +L["Show Heal Absorbs"] = "Mostrar Sanaciones absorvidas" +L["Show icon durations"] = "Mostrar duraciones en iconos" +L["Show incoming absorbs"] = "Mostrar absorciones entrantes" +L["Show incoming heals"] = "Mostrar sanaciones entrantes" +L["Show party as raid"] = "Mostrar grupo como raid" +L["Show your auras"] = "Mostrar auras propias" +L["Shows debuffs cast by a boss."] = "Mostrar debufos casteados por el Jefe" +L["Shows debuffs that you can cure."] = "Mostrar los debufos que ud, puede curar" +L["Size"] = "Tamaño" +L["Smart Friendly/Hostile Filter"] = "Filtro amistoso/hostil inteligente" +L["Soul Shards"] = "Piedras de alma" +L["Spell ID %s"] = "ID hechizo %s" +L["Spell Name"] = "Nombre del hechizo" +L["Spell Name/ID"] = "Nombre de hechizo/ID" +L["Statue"] = "Estado" +L["Status"] = "Estado" +L["Tag list"] = "Lista de etiquetas" +L["Tag name"] = "Nombre de etiqueta" +L["Tags"] = "Etiquetas" +L["Target"] = "Objetivo" +L["Target of Target"] = "Objetivo del objetivo" +L["Target of Target of Target"] = "Objetivo del objetivo del objetivo" +L["Text"] = "Texto" +L["Text/Tags"] = "Texto/etiquetas" +L["The blacklist \"%s\" already exists."] = "La lista negra \"%s\" ya existe." +L["The tag \"%s\" already exists."] = "La etiqueta \"%s\" ya existe." +L["Threat"] = "Amenaza" +L["Top"] = "Arriba" +L["Travel"] = "Viajar" +L["Tree"] = "Árbol" +L["Unit Configuration"] = "Configuración de Unidades" +L["Unit faction"] = "Facción de la unidad" +L["Unit name"] = "Nombre de la unidad" +L["Unit server"] = "Servidor de la unidad" +L["Units"] = "Unidades" +L["Units per column"] = "Unidades por columna" +L["Unknown"] = "Desconocido" +L["Unlink frames"] = "Desvincular marcos" +L["Vehicle"] = "Vehículo" +L["Vehicles"] = "Vehículos" +L["Visibility"] = "Visibilidad" +L["Widget Size"] = "Tamaño del widget" +L["Width"] = "Ancho" +L["Width percent"] = "Porcentaje del ancho" +L["Yellow (>30% HP)"] = "Amarillo (>30% HP)" +L["You must enter a number that is 0 or higher, negative numbers are not allowed."] = "Debes introducir un número que sea 0 o superior, los números negativos no están permitidos." +L["You must enter a tag name."] = "Debes introducir un nombre de etiqueta." +L["Your aura color"] = "Tu color de aura" +L["Your Auras"] = "Tus auras" +L["Zone Configuration"] = "Configuración de Zonas" + +local ShadowUF = select(2, ...) +ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) diff --git a/localization/esMX.lua b/localization/esMX.lua index 29d52e164..b3fdead97 100755 --- a/localization/esMX.lua +++ b/localization/esMX.lua @@ -1,5 +1,296 @@ -if( GetLocale() ~= "esMX" ) then return end -local L = {} ---@localization(locale="esMX", format="lua_additive_table", handle-unlocalized="ignore")@ -local ShadowUF = select(2, ...) -ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) +if( GetLocale() ~= "esMX" ) then return end +local L = {} +L["%s (%s): %s/%s (%.2f%% done)"] = " %s (%s): %s/%s (%.2f%% hecho)" +L["%s frames"] = "%s retratos" +L["%s member"] = "%s miembro" +L["|cff20ff20%s|r units enabled"] = "|cff20ff20%s|r unidades habilitados" +L["|cffff2020%s|r units disabled"] = "|cffff2020%s|r unidades deshabilitadas" +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."] = "|cffff2020Atención!|r Algunas unidades tienen anulaciones establecidas en la configuración por zona y pueden mostrarse (o no mostrarse) in ciertas zonas, Sin importar la configuración de abajo." +L["2D"] = "2D" +L["3D"] = "3D" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "Abrevia nombres de unidades con mas que 10 letros. \"Campeón Runa Oscura\" se convertirá a \"Campeón R.O.\" y \"Plebeyo Runa Oscura\" se convertirá a \"Plebeyo R.O.\"" +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "Valor absoluto de curación entrante. Si 10.000 curación llegará, mostrará 10.000." +L["Add"] = "Añadir" +L["Add new tag"] = "Añadir nueva etiqueta." +L["Add new text"] = "Añadir nuevo texto." +L["Adds %s to the list of units to be modified when you change values in this tab."] = "Añade %s a la lista de unidades para ser modificados cuando cambias los valores en esta etiqueta." +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "Añade una barra que indica cuanto tiempo aún permanece del temporizador del necrófago. Solo se usa si no tienes un necrófago permanente" +L["Adds a bar indicating how much time is left on your mushrooms."] = "Agrega una barra indicando el tiempo restante de sus hongos" +L["Adds a bar indicating how much time is left on your Rune of Power."] = "Agrega una barra que indica cuánto tiempo queda en su runa de poder." +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = "Agrega una barra dentro de la barra de vida indicando cuanto daño será absorbido" +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = "Agrega una barra dentro de la barra de vida indicando cuanta sanación recibirá alguien." +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "Añade una barra vacía en que puedes insertar mas texto sin hacer un lío de otras barras." +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "Añade otra barra de mana al retrato del jugador cuando estás en forma de oso o forma felina que te muestra cuanta mana tienes." +L["Adds rune bars and timers before runes refresh to the player frame."] = "Añade barras y temporizadores de runas al retrato del jugador antes se restaura las runas." +L["Adds temporary enchants to the buffs for the player."] = "Añade encantamientos temporarios a las bendiciones sobre el jugador." +L["Adds totem bars with timers before they expire to the player frame."] = "Añade barras y temporizadores del tótem al cuadro del jugadores antes de expirar." +L["Advanced"] = "Avanzado" +L["Advanced tag management, allows you to add your own custom tags."] = "Manejo avanzado de las etiquetas. Te permite añadir tus propias etiquetas personalizadas." +L["AFK status"] = "Estado ausente" +L["AFK timer"] = "Temporizador de estar ausente" +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "Una vez que le des Clic en Exportar, puedes dar el código abajo mostrado a otro Usuario de Shadowed Unit Frames y tendrán la misma configuración." +L["Alpha to use for bar backgrounds."] = "Opacidad en uso para el fondo de las barras." +L["Alt. Power bar"] = "Barra de Poder Alternativa" +L["Ammo"] = "Munición" +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."] = "Cantidad de salud que falta. Si no falta salud, nada se muestra. Usa un formato corto, -18500 se muestra como -18.5m(mil), valores menos que 10000 no cambian." +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."] = "Cantidad de poder (mana, ira, poder rúnico, energía) que falta. Si no falta poder, nada se muestra. Usa un formato corto, -13850 se muestra como 13.8m(mil), valores menos que 10000 no cambian. " +L["Anchor point"] = "Punto de fijar" +L["Anchor to"] = "fijar a" +L["Anchor to another frame"] = "fijar a otro cuadro" +L["Anchor to buffs"] = "fijar a bendiciones" +L["Anchor to debuffs"] = "fijar a maldiciones" +L["Are you sure you want to delete this filter?"] = "¿Estás seguro(a) que quieres borrar este filtro?" +L["Are you sure you want to delete this tag?"] = "¿Estás seguro(a) que quieres borrar esta etiqueta?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "¿Estás seguro(a) que quieres borrar este texto? Todas sus configuraciones se borrará." +L["Arena"] = "Arena" +L["Arenas"] = "Arenas" +L["Ascending"] = "Ascendiendo" +L["Assigned Role (DPS/Tank/etc)"] = "Rol Asignado (Dps/Tanque/Sanador)" +L["Aura border style"] = "Estilo del borde de las auras." +L["Aura borders"] = "Bordes de aura" +L["Aura filters"] = "Filtros de las auras." +L["Aura types to filter"] = "Tipos de auras para filtrar." +L["Auras"] = "Auras." +L["Background"] = "Fondo" +L["Background alpha"] = "Opacidad del fondo" +L["Background color"] = "Color del fondo" +L["Background/border"] = "Fondo/borde" +L["Bag indicator for master looters."] = "indicador de bolsas para los maestros de despojas." +L["Bar color to use to show how much healing someone is about to receive."] = "Color de la barra que se utilizará para mostrar la cantidad de sanación que alguien está a punto de recibir." +L["Bar spacing"] = "espaciamiento de las barras" +L["Bar texture"] = "textura de las barras" +L["Bars"] = "barras" +L["Battlegrounds"] = "Campos de Batalla" +L["Blacklist"] = "Lista negra" +L["Blacklist filters"] = "Filtros de la lista negra" +L["Blacklists"] = "Listas negras" +L["Blizzard"] = "Blizzard" +L["Border"] = "Borde" +L["Border alpha"] = "Opacidad del borde" +L["Border color"] = "Color del borde" +L["Border highlighting"] = "Brillo del borde" +L["Border thickness"] = "Densidad del borde." +L["Boss"] = "Jefe" +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."] = "Las unidades de jefe solo muestran durante luchas especificas, como los príncipes de sangre o Arsenal de la nave de guerra. No las verás en cada lucha contra jefe." +L["Both"] = "Ambos(as)" +L["Bottom"] = "Bajo" +L["Bottom Center"] = "Bajo y centro" +L["Bottom Left"] = "Bajo y a la izquierda" +L["Bottom Right"] = "Bajo y a la derecha" +L["buff frames"] = "Marcos de beneficios" +L["Buffs"] = "Bendiciones" +L["Cannot find any profiles named \"%s\"."] = "No se encuentra ningún perfil llamado \"%s\"." +L["Cast"] = "Lanzar (verb) Lanzamiento (noun)" +L["Cast bar"] = "Barra de lanzamiento" +L["Cast icon"] = "Icono del lanzamiento" +L["Cast interrupted"] = "Lanzamiento interrumpido" +L["Cast name"] = "Nombre del lanzamiento" +L["Cast time"] = "Tiempo del lanzamiento" +L["Cast uninterruptible"] = "Lanzamiento ininterrumpible" +L["Casting"] = "Lanzando" +L["Category"] = "Categoría " +L["Center"] = "Centro" +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = "Cambia el color de la barra de salud al color hostil (rojo por defecto) cuando un enemigo da aggro a la unidad." +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."] = "Cambia este widget en una barra asi que podrás cambiar la altura y orden como puedes cambiar a las barras de salud y poder." +L["Channelling"] = "Canalizando" +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = "Unidades hijas no se pueden arrastrar. Tendrás que posicionarlas de nuevo a través de '/shadowuf'." +L["Class"] = "Clase" +L["Class (Smart)"] = "Clase (Lista)" +L["Class color tag"] = "Etiqueta del color de la clase" +L["Class icon"] = "Icono de clase" +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = "El nombre de la clase sin color, usa [classcolor][class][close] si quieres que el nombre de la clase tenga el color de la clase." +L["Class/misc bars"] = "Barras de clase/miscelaneas" +L["Classes"] = "Clases" +L["Classifications"] = "Clasificación " +L["Clip"] = "Presilla" +L["Close color"] = "Cerrar el color" +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = "Cierra un código de color para prohibir que se aparezca en texto en que no quiero verlo." +L["Code"] = "Código" +L["Color by class"] = "Pintar para representar la clase" +L["Color by reaction on"] = "Pintar para representar la disposición de la unidad" +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."] = "Pintar el código para representar porcentaje de salud restante de la unidad. Funciona en la misma manera como la opción de pintar para representar salud, pero se pinta el texto en lugar de la barra completa." +L["Color code for general situation"] = "Pintar el código para la situación general" +L["Color code for situation"] = "Pintar el código para la situación." +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = "Pintar el código para la clase, usa [classcolor][class][close] si quieres que el texto de la clase sea colorado para representar la clase." +L["Color code on aggro"] = "Pintar el código cuando la unidad recibe aggro." +L["Color health by"] = "Pintar el salud para representar" +L["Color on aggro"] = "Pintar cuando se recibe aggro" +L["Color to use for health bars that are set to be colored by a static color."] = "El color que se usará para las barras de salud que están configuradas para ser colorado por un color inactivo." +L["Color to use to show how much damage will be absorbed."] = "Color que se utilizará para mostrar cuánto daño será absorbido." +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = "Color usado cuando un lanzamiento no puede ser interrumpido (Este color solo se usa para los enemigos de JcE)." +L["Color used when a cast is a channel."] = "Color usado cuando un lanzamiento es canalizado." +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "Color usado cuando un lanzamiento se interrumpe por los propios hechiceros o por otra unidad." +L["Color used when a cast is successfully finished."] = "Color usado cuando un lanzamiento se completa con éxito. " +L["Color used when an unit is casting a spell."] = "Color usado cuando una unidad está lanzando un hechizo." +L["Colors"] = "Colores" +L["Column growth"] = "Expansión de la columna" +L["Column spacing"] = "Espacio entre columnas" +L["Combat alpha"] = "Opacidad en combate" +L["Combat fader"] = "Desvanecimiento en combate" +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."] = "Desvanecedor para el combate desvanecerá todos sus marcos mientras se encuentren inactivos y aparecerán de vuelta una vez que el combate inicie o se activen." +L["Combat text"] = "Texto de combate" +L["Combat/resting status"] = "Estado de combate y reposo" +L["Combo points"] = "Puntos de combinación " +L["Configuration to specific unit frames."] = "Configuración para los retratos específicos de las unidades." +L["Create"] = "Crear" +L["Creature type"] = "Tipo de Criatura" +L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."] = "Tipo de criatura, regresa Guardia vil si la unidad es un Guardia vil, Lobo si es un Lobo y así sucesivamente." +L["Cur/Max HP (Absolute)"] = "Actual/Máxima PS (Absoluta)" +L["Cur/Max HP (Short)"] = "Actual/Máxima PS (Corto)" +L["Cur/Max HP (Smart)"] = "Actual/Máxima PS (Inteligente)" +L["Cur/Max power (Absolute)"] = "Actual/Máximo Poder (Absoluto)" +L["Cur/Max power (Druid)"] = "Actual/Máximo Poder (Druida)" +L["Cur/Max Power (Short)"] = "Actual/Máxima PP (Corto)" +L["Cur/Max PP (Smart)"] = "Actual/Máxima PP (Inteligente)" +L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."] = "Salud actual y máxima, con el formato: [psact]/[psmax], si la unidad está muerta o desconectada se mostrará eso en su lugar." +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "Poder actual y máximo, con el formato: [ppact]/[ppmax]." +L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."] = "Salud actual, usa el formato corto, 11 500 es escrito como 11.5k, valores por debajo de 10 000 son escritos como son." +L["Current HP (Absolute)"] = "PS Actual (Absoluto)" +L["Current HP (Short)"] = "PS Actual (Corto)" +L["Current power (Absolute)"] = "Poder actual (Absoluto)" +L["Current power (Druid)"] = "Poder actual (Druida)" +L["Current power (Druid/Absolute)"] = "Poder actual (Druida/Absoluto)" +L["Current Power (Short)"] = "Poder Actual (Corto)" +L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."] = "Poder Actual, usa el formato corto: 12 750 es escrito como 12.7k, valores por debajo de 10 000 se dejan como están." +L["Currently modifying"] = "Actualmente modificando" +L["Dark"] = "Oscuro" +L["Debuffs"] = "Perjuicios" +L["Decimal percent HP"] = "PS en porcentaje decimal" +L["Deficit/Unit Name"] = "Déficit/Nombre de unidad" +L["Delete"] = "Suprimir" +L["Delete filter"] = "Eliminar filtro" +L["Descending"] = "Descendiente" +L["Disable event discovery"] = "Deshabilitar descubrimiento de eventos" +L["Disable vehicle swap"] = "Deshabilitar intercambio de vehículo" +L["Disabled"] = "Deshabiliitado" +L["Disabled in %s"] = "Deshabiliitado en %s" +L["Disables the unit frame from turning into a vehicle when the player enters one."] = "Deshabilita que el marco de unidad se convierta en vehículo cuando el jugador entra en uno." +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!."] = "Deshabilitar un módulo en esta página lo deshabilita mientras esté dentro de %s. ¡No deshabilite un módulo aquí si no quiere que esto pase!." +L["Disabling unit modules in various instances."] = "Deshabilitando módulos de unidad en varias instancias." +L["Documentation"] = "Documentación" +L["Don't hide when empty"] = "No ocultar cuando esté vacío" +L["Don't use a filter"] = "No usar filtro" +L["Down"] = "Abajo" +L["Druid form"] = "Forma de druida" +L["Druid form (Short)"] = "Forma de druida (Corto)" +L["Druid mana bar"] = "Barra de maná de druida" +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."] = "Debido a la naturaleza de las unidades falsas, las barras de lanzamiento para %s no son súper eficientes y pueden tardar hasta 0.1 segundos para tomar en cuenta cambios en el lanzamiento." +L["Edge size"] = "Tamaño del borde" +L["Edit tag"] = "Editar etiqueta" +L["Editing %s"] = "Editando %s" +L["Empty bar"] = "Barra vacía" +L["Enable %s"] = "Habilitar %s" +L["Enable buffs"] = "Habilitar beneficios" +L["Enable debuffs"] = "Habilitar perjuicios" +L["Enable frequent updates"] = "Habilitar actualizaciones frecuentes" +L["Enable indicator"] = "Habilitar indicador" +L["Enable temporary enchants"] = "Habilitar encantamientos temporales" +L["Enable units"] = "Habilitar unidades" +L["Enabled in %s"] = "Habilitado en %s" +L["Enables configuration mode, letting you move and giving you example frames to setup."] = "Habilitar el modo de configuración, permitiéndote mover y dándote muestras de marcos a instalar." +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."] = "Habilitar ajustes avanzados te dará acceso a más opciones de configuración. Esto está dirigido a personas que quieran modificar cada una de las configuraciones y no debería esta habilitado por defecto ya que incrementa las opciones." +L["Energy"] = "Energía" +L["Error"] = "Error" +L["Events"] = "Eventos" +L["Events that should be used to trigger an update of this tag. Separate each event with a single space."] = "Eventos que serán usados para disparar una actualización de esta etiqueta. Separa cada evento con un espacio indivual." +L["Everywhere else"] = "Cualquier otro lugar" +L["Export"] = "Exportar" +L["Fades out the unit frames of people who are not within range of you."] = "Desvanece los marcos de unidad de las personas que no están dentro de tu rango." +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "Fallo al cargar 'ShadowedUF_Options', no se puede abrir la configuración, Error devuelto: %s" +L["Filter type"] = "Tipo de filtro" +L["Filtering both buffs and debuffs"] = "Filtrando tanto beneficios como perjuicios" +L["Filtering buffs only"] = "Filtrando solo beneficios" +L["Filtering debuffs only"] = "Filtrando solo perjuicios" +L["Finished cast"] = "Lanzamiento finalizado" +L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."] = "Marca la etiqueta para actualización frecuente, actualizará la etiqueta basado en temporizador sin importar los eventos que sucedan." +L["Focus"] = "Foco" +L["Font"] = "Fuente" +L["For target/focus"] = "Para objetivo/foco" +L["Forces a static color to be used for the background of all bars"] = "Fuerza un color estático a ser usado como fondo en todas las barras" +L["Frame"] = "Marco" +L["Frame alpha when you are out of combat while having no target and 100% mana or energy."] = "Opacidad del marco cuando te encuentres fuera de combate mientras no haya objetivo y tengas 100% de maná o energía." +L["Frame alpha while this unit is in combat."] = "Opacidad del marco mientras esta unidad está en combate." +L["Frames"] = "Marcos" +L["Friendly"] = "Amistoso" +L["Fuel"] = "Combustible" +L["Full size after"] = "Tamaño completo después" +L["Full size before"] = "Tamaño completo antes" +L["General"] = "General" +L["General configuration to all enabled units."] = "Configuración general para todas las unidades habilitadas." +L["General threat situation"] = "Situación General de amenaza" +L["Global"] = "Global" +L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"] = "Marca dorada - Habilitado en esta zona / Marca gris - Deshabilitado en esta zona / Sin marca - Usa los ajustes de unidad por defecto" +L["Group %d"] = "Grupo %d" +L["Group by"] = "Agrupar por" +L["Group number"] = "Número de Grupo" +L["Groups"] = "Grupos" +L["Groups to show"] = "Grupos a mostrar" +L["Growth"] = "Crecimiento" +L["Guild name"] = "Nombre de hermandad" +L["Half health"] = "Media Vida" +L["Health"] = "Vida" +L["Health bar"] = "Barra de vida" +L["Health bar color for friendly units."] = "Color de la barra de vida para unidades amistosas." +L["Health bar color for hostile units."] = "Color de la barra de vida para unidades hostiles." +L["Health bar color for neutral units."] = "Color de la barra de vida para unidades neutrales." +L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."] = "Color de la barra de vida a usar en unidades hostiles a las cuales no puedes atacar, utilizado para la coloración de reacción." +L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."] = "Color de la barra de vida usado como el color de transición de 100% a 0% en jugadores, así también cuando tu mascota está ligeramente infeliz." +L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."] = "Color de la barra de vida usado como el color de transición de 100% a 50% en jugadores, así también cuando tu mascota está feliz." +L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."] = "Color de la barra de vida usado como el color de transición de 50% a 0% en jugadores, así también cuando tu mascota está infeliz." +L["Health color"] = "Color de vida" +L["Health percent"] = "Porcentaje de vida" +L["Height"] = "Altura" +L["Help"] = "Ayuda" +L["Hide %s"] = "Ocultar %s" +L["Hide %s frames"] = "Ocultar marcos %s" +L["Hide bar when empty"] = "Ocultar barra cuando esté vacía" +L["Hide Blizzard"] = "Ocultar 'Blizzard'" +L["Hide in any raid"] = "Ocultar en cualquier banda" +L["Hide tooltips in combat"] = "Ocultar descripciones en combate" +L["Hides the cast bar if there is no cast active."] = "Oculta la barra de lanzamiento si no hay lanzamiento activo." +L["Hiding and showing various aspects of the default UI such as the player buff frames."] = "Ocultando y mostrando varios aspectos de la IU por defecto como los marcos de beneficios del jugador." +L["High health"] = "Vida alta" +L["Highlight units that are debuffed with something you can cure."] = "Señalar unidades que tienen perjuicios que puedes remover." +L["Highlight units that have aggro on any mob."] = "Destacar unidades que tienen 'aggro' de cualquier 'mob'." +L["Highlight units that you are targeting or have focused."] = "Destacar unidades que tienes como objetivo o foco." +L["Highlight units when you mouse over them."] = "Destacar unidades cuando posicione el ratón sobre ellos." +L["Holy Power"] = "Poder Sagrado" +L["Hostile"] = "Hostil" +L["How close the frame should clip with the border."] = "Que tan cerca el marco debe cortar el borde." +L["How far the background should be from the unit frame border."] = "Que tan lejos el fondo debe estar desde el borde del marco de la unidad." +L["How large the background should tile"] = "Que tanto debe cubrir el fondo." +L["How large the edges should be."] = "Que tan largos serán los bordes." +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."] = "Cuantas auras por columna, por ejemplo, ingresar dos creará dos filas que serán llenadas hasta el número configurado por fila." +L["How many auras to show in a single row."] = "Cuantas auras por fila se mostraran." +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!"] = "Cantidad de personas asistiendo a la unidad, por ejemplo si usted establece esto en usted mismo se mostrará cuantas personas tienen seleccionado a tu objetivo. Esto te incluye en el conteo." +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!"] = "Cantidad de personas en la banda seleccionando la unidad, por ejemplo si usted establece esto en usted mismo se mostrará cuantas personas te tienen seleccionado. Esto te incluye en el conteo." +L["How many rows total should be used, rows will be however long the per row value is set at."] = "Cantidad total de filas a usarse, las filas serán tan largas como el valor por fila establecido." +L["Incoming absorb"] = "Absorción entrante" +L["Incoming absorbs"] = "Absorciones entrantes" +L["Incoming heal (Absolute)"] = "Sanación entrante (Absoluta)" +L["Incoming heal (Percent)"] = "Sanación entrante (Porcentaje)" +L["Invalid interval entered, must be a number."] = "Intervalo ingresado invalido, debe ser un número." +L["Left"] = "Izquierda" +L["Management"] = "Adminstración" +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."] = "Valor porcentual de hasta qué punto fuera del marco de la unidad la barra de absorción entrante puede llegar. 130% significa que va a ir el 30% fuera del marco, 100% significa que no salirse del marco." +L["player alt. power"] = "Poder alternativo de jugador" +L["Players will be colored by class."] = "Los jugadores serán coloreados por clase" +L["Programming in Lua"] = "Programación en LUA" +L["PvP Flag"] = "Emblema de JcJ" +L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."] = "Regresa un porcentaje de amenaza escalado de su 'aggro' en su objetivo actual, siempre 0 - 100%." +L["Rune of Power"] = "Poder de runa" +L["Show incoming absorbs"] = "Mostar absorciones entrantes" +L["Show incoming heals"] = "Mostrar sanaciones entrantes" +L["Shows a bar for alternate power info (used in some encounters)"] = "Muestra una barra para la información de poder alternativo (usada en algunos encuentros)" +L["Size"] = "Tamaño" +L["Soul Shards"] = "Fragmentos de alma" +L["Soul shards"] = "Fragmentos de alma" +L["Status"] = "Estado" +L["Top"] = "Arriba" +L["Total number of active holy power."] = "Número total de poder sagrado activo." +L["Total number of active soul shards."] = "Número total de fragmentos de almas activos." +L["Whitelist"] = "Lista blanca" +L["Zone configuration units"] = "Configuración de unidades por zona" + +local ShadowUF = select(2, ...) +ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) diff --git a/localization/frFR.lua b/localization/frFR.lua index b42c961cf..2ff754898 100755 --- a/localization/frFR.lua +++ b/localization/frFR.lua @@ -1,5 +1,946 @@ -if( GetLocale() ~= "frFR" ) then return end -local L = {} ---@localization(locale="frFR", format="lua_additive_table", handle-unlocalized="ignore")@ -local ShadowUF = select(2, ...) -ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) +if( GetLocale() ~= "frFR" ) then return end +local L = {} +L["%d auras in group"] = "%d auras dans le groupe" +L["%s (%s): %s/%s (%.2f%% done)"] = "%s (%s) : %s/%s (%.2f%% terminé)" +L["%s aura groups disabled"] = "%s groupes d'auras désactivés" +L["%s frames"] = "cadres |2 %s" +L["%s member"] = "membre |2 %s" +L["|cff20ff20%s|r units enabled"] = "|cff20ff20%s|r unités activées" +L["|cffff2020%s|r units disabled"] = "|cffff2020%s|r unités désactivées" +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."] = "|cffff2020Attention !|r Certaines unités ont des spécificités définies dans la config de zone, et peuvent apparaître (ou ne pas apparaître) dans certaines zones. Quel que soit le réglage ci-dessous." +L["1 aura group disabled"] = "1 groupe d'auras désactivé" +L["2D"] = "2D" +L["3D"] = "3D" +L["A"] = "A" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "Raccourci les noms d'unité de plus de 10 caractères. Par exemple, \"Champion sombre-rune\" devient \"C. sombre-rune\" (les premiers mots sont raccourcis de la même façon qu'ils le sont en anglais)" +L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."] = "Absorption de dégâts absolue sur l'unité. Si 10 000 dégâts vont être absorbés, 10 000 sera affiché." +L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."] = "Valeur absolue de soins absorbés. Si 16 000 de soins seront absorbés, 16 000 sera affiché." +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "Valeur absolue des soins entrants. Si un soin à 10 000 arrive, 10 000 sera affiché." +L["Add"] = "Ajouter" +L["Add Aura"] = "Ajouter une Aura" +L["Add aura"] = "Ajouter une aura" +L["Add Indicator"] = "Ajouter un indicateur" +L["Add link"] = "Ajouter un lien" +L["Add new indicator"] = "Ajouter un nouvel indicateur" +L["Add new tag"] = "Ajout de nouveaux tags" +L["Add new text"] = "Ajout d'un nouveau texte" +L["Add Tags"] = "Ajouter des Tags" +L["Adds %s to the list of units to be modified when you change values in this tab."] = "Ajoute %s dans la liste des unités à modifier quand vous effectuez des changements dans cet onglet." +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "Ajoute une barre indiquant combien de temps il reste à vivre à votre goules. Utilisée uniquement si votre goule n'est pas permanente." +L["Adds a bar indicating how much time is left on your mushrooms."] = "Ajoute une barre indiquant combien de temps il reste pour vos champignons." +L["Adds a bar indicating how much time is left on your Rune of Power."] = "Ajoute une barre indiquant le temps restant sur votre Rune de puissance." +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = "Ajoute une barre dans la barre de vie indiquant combien de dégâts seront absorbés." +L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."] = "Ajoute une barre à l'intérieur de la barre de santé indiquant la quantité de soins que l'on estime recevoir." +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = "Ajoute une barre à l'intérieur de la barre de vie indiquant combien de soins quelqu'un va recevoir." +L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."] = "Ajoute une barre dans la barre de vie indiquant combien de soins seront absorbés sans être appliqués au joueur." +L["Adds a mana bar to the player frame for elemental and enhancement shamans."] = "Ajoute une barre de mana au cadre du joueur pour les chamans élémentaires et amélioration." +L["Adds a mana bar to the player frame for shadow priests."] = "Ajoute une barre de mana au cadre du joueur pour les prêtres ombre." +L["Adds a Stagger bar for Brewmaster Monks."] = "Ajoute une barre de Report pour les Moines Maître brasseurs." +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "Ajoute une barre vide dans laquelle vous pouvez placer du texte afin de soulager les autres barres." +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "Ajoute une autre barre de mana au cadre du joueur quand vous êtes en forme d'ours ou de félin." +L["Adds rune bars and timers before runes refresh to the player frame."] = "Ajoute une barre des runes avec les compteurs de recharge des runes au cadre du joueur." +L["Adds temporary enchants to the buffs for the player."] = "Ajoute les enchantements temporaires aux buffs du joueur." +L["Adds totem bars with timers before they expire to the player frame."] = "Ajoute des barres de totem avec des compteurs d'expiration au cadre du joueur." +L["Advanced"] = "Avancé" +L["Advanced tag management, allows you to add your own custom tags."] = "Gestion avancée des tags, permettant d'ajouter vos propres tags." +L["AFK"] = "AFK" +L["AFK status"] = "Statut ABS" +L["AFK timer"] = "Durée ABS" +L["AFK:%s"] = "AFK:%s" +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "Une fois que vous avez appuyé sur Exporter, vous pouvez donner le code ci-dessous aux autres utilisateurs de Shadowed Unit Frames et ils obtiendront exactement votre disposition." +L["Aggro"] = "Aggro" +L["All aura groups enabled for unit."] = "Tous les groupes d'auras activés pour l'unité." +L["All Auras"] = "Toutes les auras" +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."] = "Vous permet d'ancrer le groupe d'auras sur un autre. Vous pouvez alors choisir où il sera ancré avec la position.|n|nUtilisez cela si vous voulez dupliquer le style d'UI par défaut où buffs et débuffs dont des groupes séparés." +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."] = "Vous permet de désactiver le totem avec un clic-droit.|n|nAttention : les barres internes de cette unité ne se redimensionneront pas en combat si vous l'activez." +L["Allows you to enter a new aura group."] = "Permet d'entrer un nouveau groupe d'auras." +L["Alpha to use for bar backgrounds."] = "Définit la transparence à utiliser pour les arrières-plan des barres." +L["Alpha to use for bar."] = "La transparence à utiliser pour les barres." +L["Alt. Power"] = "Puissance Alt." +L["Alt. Power bar"] = "Barre de puissance alt." +L["Alternate power is used for things like quests and dungeons."] = "Puissance alternative utilisée par exemple dans les quêtes et donjons." +L["Alternate Spell Name"] = "Nom de sort alternatif" +L["Alternatively friendly spell to use to check range."] = "Sort amical alternativement à utiliser pour vérifier la portée." +L["Ammo"] = "Munitions" +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."] = "Quantité de vie manquante. Si nul, rien n'est affiché. Utilise un format court : -18 500 est remplacé par -18.5k, et les valeurs inférieures à 10 000 sont affichées telles qu'elles." +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."] = "Quantité de puissance manquante. Si nul, rien n'est affiché. Utilise un format court : -13 850 est remplacé par 13.8k, et les valeurs inférieures à 10 000 sont affichées telles qu'elles." +L["Anchor point"] = "Point d'ancrage" +L["Anchor to"] = "Ancrer à" +L["Anchor to another frame"] = "Ancrer à un autre cadre" +L["Anchor to buffs"] = "Ancrer aux buffs" +L["Anchor to debuffs"] = "Ancrer aux debuffs" +L["Ancient Kings bar"] = "Barre Gardien des anciens rois " +L["Any auras shown in this indicator will have their total stack displayed."] = "Toute aura montrée dans cet indicateur affichera son stack total." +L["Aquatic"] = "Aquatique" +L["Arcane Charges"] = "Charges arcaniques" +L["Are you sure you want to delete this aura?"] = "Êtes-vous sûr de vouloir supprimer cette aura ?" +L["Are you sure you want to delete this filter?"] = "Êtes-vous sûr de vouloir supprimer ce filtre ?" +L["Are you sure you want to delete this indicator?"] = "Êtes-vous sûr de vouloir supprimer cet indicateur ?" +L["Are you sure you want to delete this tag?"] = "Êtes-vous sûr de vouloir supprimer ce tag ?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "Êtes-vous sûr de vouloir supprimer ce texte ? Tous les paramètres seront supprimés." +L["Arena"] = "Arène" +L["Arena Pet"] = "Familier d'arène" +L["Arena Spec"] = "Spécialisation" +L["Arena Target"] = "Cibles d'arène" +L["Arena Target of Target"] = "Cible de la cible d'arène" +L["Arena ToT"] = "CdC Arène" +L["Arenas"] = "Arènes" +L["Ascending"] = "Ascendant" +L["Assigned Role (DPS/Tank/etc)"] = "Rôle attribué (DPS/Tank/etc)" +L["Astral Power"] = "Puissance astrale" +L["Aura border style"] = "Style de bordure des auras" +L["Aura borders"] = "Bord des auras" +L["Aura Combo Points"] = "Points de combo Aura" +L["Aura Filters"] = "Filtres d'aura" +L["Aura filters"] = "Filtres d'auras" +L["Aura group"] = "Groupe d'aura" +L["Aura groups"] = "Groupes d'aura" +L["Aura Groups"] = "Groupes d'aura" +L["Aura Indicators"] = "Indicateurs d'aura" +L["Aura indicators"] = "Indicateurs d'Aura" +L["Aura name or spell ID"] = "Nom d'aura ou ID de sort" +L["Aura types to filter"] = "Types de filtre d'auras" +L["Auras"] = "Auras" +L["Auras matching a criteria will automatically show up in the indicator when enabled."] = "Les auras correspondant à un critère apparaîtront automatiquement dans l'indicateur si activé." +L["Automatic Auras"] = "Auras automatiques" +L["B"] = "B" +L["Background"] = "Arrière-plan" +L["Background alpha"] = "Transp. de l'arrière-plan" +L["Background color"] = "Couleur d'arrière-plan" +L["Background/border"] = "Arrière-plan/bordure" +L["Bag indicator for master looters."] = "Sac-indicateur des maîtres du butin." +L["Bar alpha"] = "Transparence des barres" +L["Bar color to use to show how much healing someone is about to receive."] = "Couleur de barre à utiliser pour montrer combien de soins quelqu'un va recevoir." +L["Bar spacing"] = "Espacement des barres" +L["Bar texture"] = "Texture des barres" +L["Bars"] = "Barres" +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."] = "Les barres avec un ordre plus ou moins élevé que les option \"Pleine taille\" utiliseront toute la largeur du cadre.|n|nLes barres entre ces deux nombres seront à côté du portrait." +L["Battleground"] = "Champ de bataille" +L["Battleground Pet"] = "Familier du champ de bataille" +L["Battleground Target"] = "Cible du champ de bataille" +L["Battleground Target of Target"] = "Cible de la cible de champ de bataille" +L["Battlegrounds"] = "Champs de bataille" +L["Bear"] = "Ours" +L["BG"] = "CdB" +L["BG Pet"] = "Familier du CdB" +L["BG Target"] = "Cible CdB" +L["BG ToT"] = "CdC CdB" +L["Blacklist"] = "Liste noire" +L["Blacklist filters"] = "Filtres des listes noires" +L["Blacklists"] = "Listes noires" +L["Blizzard"] = "Blizzard" +L["Border"] = "Bordure" +L["Border alpha"] = "Transp. de la bordure" +L["Border color"] = "Couleur de la bordure" +L["Border coloring of stealable, curable and dispellable auras."] = "Couleur de bordure des auras volables, soignables, et dissipables." +L["Border highlighting"] = "Surbrillance de la bordure" +L["Border thickness"] = "Épaisseur de la bordure" +L["Boss"] = "Boss" +L["Boss Auras"] = "Auras de boss" +L["Boss Debuffs"] = "Débuffs de boss" +L["Boss Target"] = "Cible des boss" +L["Boss Target of Target"] = "Cible de la cible des boss" +L["Boss ToT"] = "CdC 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."] = "Les unités boss ne sont utilisées que dans certains combats, tels que les princes de sang ou la bataille des canonnières. Vous ne les verrez pas à chaque rencontre de boss." +L["Both"] = "Les deux" +L["Bottom"] = "Bas" +L["Bottom Center"] = "Bas Centre" +L["Bottom Left"] = "Bas Gauche" +L["Bottom Right"] = "Bas Droite" +L["buff frames"] = "cadres des buffs" +L["Buffs"] = "Buffs" +L["C"] = "C" +L["Cannot find any profiles named \"%s\"."] = "Impossible de trouver un profil nommé \"%s\"." +L["Cast"] = "Incantation" +L["Cast bar"] = "Barre d'incantation" +L["Cast icon"] = "Icône d'incantation" +L["Cast interrupted"] = "Incantation interrompue" +L["Cast name"] = "Nom d'incantation" +L["Cast time"] = "Durée d'incantation" +L["Cast uninterruptible"] = "Incantation non-interruptible" +L["Casting"] = "Incantation" +L["Cat"] = "Chat" +L["Category"] = "Catégorie" +L["Center"] = "Centre" +L["Changed profile to %s."] = "Profil changé vers %s." +L["Changes the health bar to the color of any curable debuff."] = "Change la barre de vie en la couleur d'un affaiblissement dissipable." +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = "Change la couleur de la barre de vie vers la couleur d'hostilité définie (rouge par défaut) quand l'unité prend l'aggro." +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."] = "Change ce widget en barre. Vous pourrez changer la hauteur et l'ordre de la même façon que pour les barres de vie et de puissance." +L["Channelling"] = "Canalisation" +L["Checking this will show the indciator on hostile units."] = "Cocher pour afficher l'indicateur sur les unités hostiles." +L["Checking this will show the indicator on friendly units."] = "Cocher pour afficher l'indicateur sur les unités amicales." +L["Chi"] = "Chi" +L["Chi Points"] = "Points de chi" +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = "Child units cannot be dragged, you will have to reposition them through /shadowuf." +L["Class"] = "Classe" +L["Class (Smart)"] = "Classe (intelligent)" +L["Class color tag"] = "Tag de couleur de classe" +L["Class icon"] = "Icône de classe" +L["Class Icon"] = "Icône de classe" +L["Class icon for players."] = "Icône de classe pour les joueurs." +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = "Nom de la classe sans coloration. Utilisez [classcolor][class][close] si vous souhaitez que le nom de la classe soit coloré selon la classe." +L["Class Role"] = "Rôle de classe" +L["Class Specific"] = "Spécifique aux classes" +L["Class Timer"] = "Compteur de classe" +L["Class/misc bars"] = "Barres de classe/diverses" +L["Classes"] = "Classes" +L["Classification"] = "Classification" +L["Classifications"] = "Classifications" +L["Clip"] = "Marge" +L["Close color"] = "Fin de couleur" +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = "Ferme un code couleur, empêche les couleurs de s'afficher jusqu'à une partie du texte alors que vous ne le souhaitez pas." +L["Code"] = "Code" +L["Color by class"] = "Colorer selon la classe" +L["Color by reaction on"] = "Colorer selon la réaction pour" +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."] = "Code de couleur basé sur le pourcentage de vie restant de l'unité. Ceci fonctionne de la même manière que l'option de coloration selon la vie, mais pour le texte au lieu de toute la barre." +L["Color code for general situation"] = "Code couleur de situation générale" +L["Color code for situation"] = "Code couleur de situation" +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = "Code couleur pour la classe, utilisez [classcolor][class][close] si vous souhaitez que le texte de classe soit coloré selon la classe." +L["Color code on aggro"] = "Code couleur à l'aggro" +L["Color health by"] = "Colorer la vie par" +L["Color on aggro"] = "Colorer à l'aggro" +L["Color on curable debuff"] = "Couleur d'affaiblissement dissipable" +L["Color power by"] = "Colorer puissance par" +L["Color to use for health bars that are set to be colored by a static color."] = "Couleur à utiliser pour les barres de vie définies pour être colorées par une couleur statique." +L["Color to use to show how much damage will be absorbed."] = "Couleur à utiliser pour montrer combien de dégâts seront absorbés." +L["Color to use to show how much healing will e absorbed."] = "Couleur à utiliser pour montrer combien de soins seront absorbés." +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = "Couleur utilisée quand une incantation ne peut être interrompue. Utilisé uniquement pour les monstres." +L["Color used when a cast is a channel."] = "Couleur utilisée quand une incantation est canalisée." +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "Couleur utilisée quand une incantation est interrompue soit par l'incantateur lui-même, soit par une autre unité." +L["Color used when a cast is successfully finished."] = "Couleur utilisée quand une incantation s'est terminée avec succès." +L["Color used when an unit is casting a spell."] = "Couleur utilisée quand une unité est en train d'incanter un sort." +L["Colors"] = "Couleurs" +L["Column growth"] = "Sens d'ajout des colonnes" +L["Column spacing"] = "Espacement des colonnes" +L["Combat alpha"] = "Transp. en combat" +L["Combat fader"] = "Fondu de combat" +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."] = "Le fondu de combat estompera tous vos cadres quand ces dernières sont inactives et les remet au premier plan une fois que vous êtes en combat ou qu'elles sont actives." +L["Combat Status"] = "Statut du combat" +L["Combat text"] = "Texte de combat" +L["Combat/resting status"] = "Statut combat/repos" +L["Combo points"] = "Points de combo" +L["Combo Points"] = "Points de combo" +L["Configuration to specific unit frames."] = "Configuration de cadres d'unité spécifiques." +L["Cooldown rings for"] = "Spirale de recharge pour" +L["Create"] = "Créer" +L["Creature type"] = "Type de créature" +L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."] = "Type de la créature. Renvoie Gangregarde si l'unité est un gangregarde, Loup si c'est un loup, etc." +L["Crown indicator for group leader or assistants."] = "Couronne - indicateur de chef de groupe et assistants." +L["Cur/Max HP (Absolute)"] = "Vie actu./max. (absolue)" +L["Cur/Max HP (Short)"] = "Vie actu./max. (courte)" +L["Cur/Max HP (Smart)"] = "Vie actu./max. (intelligent)" +L["Cur/Max power (Absolute)"] = "Puissance actu./max. (absolue)" +L["Cur/Max power (Druid)"] = "Puissance actu./max. (druide)" +L["Cur/Max power (Druid/Absolute)"] = "Puissance Actu/Max (Druide/Absolu)" +L["Cur/Max power (Secondary)"] = "Puissance Actu/Max (Secondaire)" +L["Cur/Max power (Secondary/Absolute)"] = "Puissance Actu/Max (Secondaire/Absolu)" +L["Cur/Max Power (Short)"] = "Puissance actu./max. (courte)" +L["Cur/Max PP (Smart)"] = "Puissance actu./max. (intelligent)" +L["Curable"] = "Soignable" +L["Curable Auras"] = "Auras dissipables" +L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."] = "Vie actuelle et maximale, sous la forme [curhp]/[maxhp]. Si l'unité est morte ou hors ligne, ces derniers sont affichés à la place." +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "Puissance actuelle et maximale, sous la forme [curpp]/[maxpp]." +L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."] = "Vie actuelle dans un format court : 11 500 est remplacé par 11.5k, et les valeurs inférieures à 10 000 sont affichées telles qu'elles." +L["Current HP (Absolute)"] = "Vie actuelle (absolue)" +L["Current HP (Short)"] = "Vie actuelle (court)" +L["Current pet used by a battleground unit."] = "Familier actuel d'une unité de champ de bataille." +L["Current power (Absolute)"] = "Puissance actuelle (absolue)" +L["Current power (Druid)"] = "Puissance actuelle (druide)" +L["Current power (Druid/Absolute)"] = "Puissance actuelle (druide/absolue)" +L["Current power (Secondary)"] = "Puissance Actuelle (Secondaire)" +L["Current power (Secondary/Absolute)"] = "Puissance Actuelle (Secondaire/Absolu)" +L["Current Power (Short)"] = "Puissance actuelle (court)" +L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."] = "Puissance actuelle dans un format court : 12 750 est remplacé par 12.7k, et les valeurs inférieures à 10 000 sont affichées telles qu'elles." +L["Current target of a battleground unit."] = "Cible actuelle d'une unité de champ-de-bataille." +L["Current target of target of a battleground unit."] = "Cible de la cible d'une unité de champ-de-bataille." +L["Currently modifying"] = "Modifie actuellement" +L["Currently used in battlegrounds for showing flag carriers."] = "Utilisé en champ de bataille pour montrer les porteurs de drapeaux." +L["Damage absorption (Absolute)"] = "Absorption (absolue)" +L["Damage absorption (Short)"] = "Absorption (court)" +L["Damage absorption/Name"] = "Absorption/Nom" +L["Dark"] = "Sombre" +L["Dead"] = "Mort" +L["Debuffs"] = "Debuffs" +L["Decimal percent HP"] = "PV en pourcent décimal" +L["Default color"] = "Couleur par défaut" +L["Default font color, any color tags inside individual tag texts will override this."] = "Couleur de police par défaut. Les tags de couleurs dans les tag de texte individuels outrepasseront cela." +L["Deficit/Unit Name"] = "Déficit/Nom de l'unité" +L["Delete"] = "Supprimer" +L["Delete filter"] = "Supprimer le filtre" +L["Delete link"] = "Supprimer le lien" +L["Descending"] = "Descendant" +L["Disable Auras by Class"] = "Désactiver les auras par classe." +L["Disable Blizzard Cooldown Count"] = "Désactiver le décompte du temps de recharge de Blizzard" +L["Disable event discovery"] = "Désactiver la découverte d'évènement" +L["Disable OmniCC Cooldown Count"] = "Désactiver le décompte du temps de recharge de OmniCC" +L["Disable vehicle swap"] = "Désactiver l'échange avec le véhicule" +L["Disabled"] = "Désactivé" +L["Disabled for %s."] = "Désactivé pour %s." +L["Disabled in %s"] = "Désactivé en %s" +L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."] = [=[Désactive l'affichage des compteurs de temps de recharge de toutes les auras de Shadowed Unit Frame. +]=] +L["Disables the unit frame from turning into a vehicle when the player enters one."] = "Empêche le cadre d'unité de se transformer en véhicule quand le joueur entre dans l'un d'eux." +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!."] = "La désactivation d'un module sur cette page désactive ce dernier quand vous êtes en %s. Ne désactivez pas un module ici si vous ne voulez pas que cela arrive !" +L["Disabling unit modules in various instances."] = "Désactivation des modules d'unité dans diverses instances." +L["Dismissable Totem bars"] = "Totems renvoyables" +L["Dispellable/Stealable"] = "Dissipable/Volable" +L["Display"] = "Afficher" +L["Display enemy buffs using LibClassicDuration data."] = "Affiche les buffs ennemis en utilisant les données LibClassicDuration." +L["DND"] = "Ne pas déranger" +L["DND:%s"] = "Ne pas déranger :%s" +L["Documentation"] = "Documentation" +L["Don't hide when empty"] = "Ne pas cacher si vide" +L["Don't use a filter"] = "Ne pas utiliser de filtre" +L["Down"] = "Bas" +L["Druid form"] = "Forme druidique" +L["Druid form (Short)"] = "Forme druidique (court)" +L["Druid mana bar"] = "Barre de mana druidique" +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."] = "Étant donnée la nature des fausses unités, les barres d'incantation |2 %s ne sont pas très efficaces et un délai d'au plus 0,10 seconde est nécessaire pour repérer un changement dans l'incantation." +L["Edge size"] = "Taille de bord" +L["Edit tag"] = "Édition de tag" +L["Editing %s"] = "Edition |2 %s" +L["Elite"] = "Élite" +L["Empty bar"] = "Barre vide" +L["Enable %s"] = "Activer %s" +L["Enable buffs"] = "Activer les buffs" +L["Enable debuffs"] = "Activer les debuffs" +L["Enable enemy buff tracking"] = "Activer le suivi des buffs ennemis" +L["Enable for friendlies"] = "Activer pour les amis" +L["Enable for hostiles"] = "Activer pour les ennemis" +L["Enable frequent updates"] = "Activer les m. à j. fréquentes" +L["Enable indicator"] = "Activer l'indicateur" +L["Enable Indicators"] = "Activer indicateurs" +L["Enable temporary enchants"] = "Activer les enchant. temporaires" +L["Enable units"] = "Activation d'unités" +L["Enabled for %s."] = "Activé pour %s." +L["Enabled in %s"] = "Activé en %s" +L["Enabled Units"] = "Unités activées" +L["Enables configuration mode, letting you move and giving you example frames to setup."] = "Active le mode de configuration, vous permettant de déplacer les cadres et donnant également des cadres d'exemple à paramétrer." +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."] = "L'activation des paramètres avancés vous donnera accès à plus d'options de configuration. Conseillé pour les gens qui souhaitent peaufiner la moindre petite chose." +L["Energy"] = "Énergie" +L["Enlarge auras for"] = "Agrandir auras pour" +L["Error"] = "Erreur" +L["Essence"] = "Essence" +L["Events"] = "Événements" +L["Events that should be used to trigger an update of this tag. Separate each event with a single space."] = "Les événements qui doivent être utilisées pour déclencher une mise à jour de ce tag. Séparez chaque événement par une espace." +L["Everywhere else"] = "Partout ailleurs" +L["Export"] = "Exporter" +L["F"] = "F" +L["Fades out the unit frames of people who are not within range of you."] = "Estompe les cadres d'unité des gens qui ne sont pas à votre portée." +L["Failed to import layout, error:|n|n%s"] = "Échec de l'importation de la disposition, erreur : |n|n%s" +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "Échec du chargement de ShadowedUF_Options car impossible de charger la configuration. Erreur renvoyée : %s" +L["Failed to save tag, error:|n %s"] = "Échec de la sauvegarde du tag, erreur : |n %s" +L["Female"] = "Femme" +L["Filter type"] = "Type de filtre" +L["Filtering both buffs and debuffs"] = "Filtrage des buffs et des debuffs" +L["Filtering buffs only"] = "Filtrage des buffs uniquement" +L["Filtering debuffs only"] = "Filtrage des debuffs uniquement" +L["Filters"] = "Filtres" +L["Finished cast"] = "Incantation terminée" +L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."] = "Marque le tag pour mise à jour fréquente, cela mettra à jour le tag sur un timer, indépendamment des déclenchements d'événements." +L["Flight"] = "Vol" +L["Flips coloring so the bar color is shown as the background color and the background as the bar"] = "Inverse les couleurs. La barre prend l'aspect du fond, et le fond celui de la barre." +L["Focus"] = "Focalisation" +L["Focus Target"] = "Cible de la focalisation" +L["Font"] = "Police d'écriture" +L["Food"] = "Nourriture" +L["For configuring aura indicators on unit frames."] = "Pour configurer les indicateurs d'auras sur les cadres d'unité." +L["For target/focus"] = "Pour cible/focal." +L["Forces a static color to be used for the background of all bars"] = "Force l'utilisation d'une couleur statique pour l'arrière-plan de toutes les barres." +L["Frame"] = "Cadre" +L["Frame alpha when you are out of combat while having no target and 100% mana or energy."] = "Définit la transparence du cadre quand vous êtes hors combat, tout en ayant aucune cible et 100% de mana ou d'énergie." +L["Frame alpha while this unit is in combat."] = "Définit la transparence du cadre quand cette unité est en combat." +L["Frames"] = "Cadres" +L["Friendly"] = "Amical" +L["Fuel"] = "Carburant" +L["Full size after"] = "Pleine taille après" +L["Full size before"] = "Pleine taille avant" +L["Fury"] = "Fureur" +L["General"] = "Général" +L["General configuration to all enabled units."] = "Configuration générale de toutes les unités activées." +L["General threat situation"] = "Situation générale de la menace" +L["Ghost"] = "Fantôme" +L["Ghoul bar"] = "Barre des goules" +L["Global"] = "Global" +L["Global configurating will let you mass enable or disable aura groups for multiple units at once."] = "La configuration globale permet d'activer ou désactiver en masse des groupes d'auras pour plusieurs unités à la fois." +L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"] = "Coche dorée - activé dans cette zone / Coche grisée - Désactivée dans cette zone / Pas de coche - Utilise les paramètres par défaut de l'unité" +L["Green (<30% HP)"] = "Vert (<30% PV)" +L["Group %d"] = "Groupe %d" +L["Group by"] = "Grouper par" +L["Group number"] = "Numéro de groupe" +L["Group row spacing"] = "Ecart entre les rangées du groupe" +L["Groups"] = "Groupes" +L["Groups per row"] = "Groupes par rangée" +L["Groups to show"] = "Groupes à afficher" +L["Growth"] = "Sens d'ajout" +L["Guild name"] = "Nom de guilde" +L["Half health"] = "Mi-vie" +L["Has Aggro"] = "A l'aggro" +L["Heal absorb"] = "Soins absorbés" +L["Heal Absorb (Absolute)"] = "Soins absorbés (absolu)" +L["Heal Absorb (Short)"] = "Soins absorbés (court)" +L["Heal absorbs"] = "Soins absorbés" +L["Healing absorb"] = "Absorption de la guérison" +L["Health"] = "Vie" +L["Health bar"] = "Barre de vie" +L["Health bar color for friendly units."] = "La couleur de la barre de vie pour les unités amicales." +L["Health bar color for hostile units."] = "La couleur de la barre de vie pour les unités hostiles." +L["Health bar color for neutral units."] = "La couleur de la barre de vie pour les unités neutres." +L["Health bar color for units with aggro."] = "Couleur de la barre de vie des unités ayant l'aggro." +L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."] = "La couleur de barre de vie à utiliser pour les unités hostiles que vous ne pouvez pas attaquer. Utilisée pour la coloration selon la réaction." +L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."] = "La couleur de la barre de vie utilisée comme couleur de transition de 100% -> 0% sur les joueurs, ainsi que quand votre familier est un peu mécontent." +L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."] = "La couleur de la barre de vie utilisée comme couleur de transition de 100% -> 50% sur les joueurs, ainsi que quand votre familier est heureux." +L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."] = "La couleur de la barre de vie utilisée comme couleur de transition de 50% -> 0% sur les joueurs, ainsi que quand votre familier est mécontent." +L["Health color"] = "Couleur de vie" +L["Health percent"] = "Pourcentage de vie" +L["Height"] = "Hauteur" +L["Help"] = "Aide" +L["Hide %s"] = "Cacher %s" +L["Hide %s frames"] = "Cacher cadres |2 %s" +L["Hide bar when empty"] = "Cacher barre si vide" +L["Hide Blizzard"] = "Cacher Blizzard" +L["Hide in <=5-man raids"] = "Masquer dans raids <= 5" +L["Hide in >5-man raids"] = "Masquer dans raids > 5" +L["Hide in any raid"] = "Cacher ds tous les raids" +L["Hide tooltips in combat"] = "Cacher bulles en combat" +L["Hides the cast bar if there is no cast active."] = "Cache la barre d'incantation si aucune incantation n'est en cours." +L["Hides the power bar unless the class has mana."] = "Cache la barre de puissance si la classe n'a pas de mana." +L["Hiding and showing various aspects of the default UI such as the player buff frames."] = "Masquage et affichage de divers aspects de l'IU par défaut tel que les cadres des buffs du joueur." +L["High"] = "Haut" +L["High health"] = "Vie élevée" +L["Highlight"] = "Mise en évidence" +L["Highlight units that are "] = "Met en surbrillance les unités élites." +L["Highlight units that are debuffed with something you can cure."] = "Met en surbrillance les unités qui sont affectées par quelque chose que vous pouvez enlever." +L["Highlight units that are rare."] = "Met en surbrillance les unités rares." +L["Highlight units that have aggro on any mob."] = "Met en surbrillance les unités qui ont l'attention d'un monstre." +L["Highlight units that you are targeting or have focused."] = "Met en surbrillance les unités que vous avez en cible ou en focalisation." +L["Highlight units when you mouse over them."] = "Met en surbrillance les unités que vous survolez avec la souris." +L["Holy power"] = "Puissance sacrée" +L["Holy Power"] = "Puissance sacrée" +L["Hostile"] = "Hostile" +L["How close the frame should clip with the border."] = "Quelle marge laisser entre l'unité et le bord." +L["How far the background should be from the unit frame border."] = "La distance à laquelle l'arrière-plan doit se trouver par rapport à la bordure du cadre d'unité." +L["How large the background should tile"] = "La largeur des carreaux d'arrière-plan." +L["How large the edges should be."] = "À quel point les bords doivent être." +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."] = "Le nombre d'auras par colonne. Par exemple, entrer 2 ici créera 2 rangées qui seront remplies indépendamment de la valeur par rangée." +L["How many auras to show in a single row."] = "Le nombre d'auras à afficher dans une seule rangée." +L["How many Chi points you currently have."] = "Combien de points de chi vous avez actuellement." +L["How many groups should be shown per row."] = "Définit le nombre de groupes à afficher par rangée." +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!"] = "Nombre de joueurs qui soutiennent l'unité. Par exemple, si vous placez ceci sur vous même, cela affichera le nombre de joueurs qui ciblent votre cible. Vous êtes inclus dans le compte !" +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!"] = "Nombre de joueurs dans votre raid qui ciblent l'unité. Par exemple, si vous placez ceci sur vous même, cela affichera le nombre de joueurs qui vous ciblent. Vous êtes inclus dans le compte !" +L["How many rows total should be used, rows will be however long the per row value is set at."] = "Nombre total de rangées. Les rangées auront la longueur définie avec la valeur par rangée." +L["How many seconds a totem has left before disappearing."] = "Combien de secondes avant qu'un totem disparaisse." +L["How many seconds before a rune recharges."] = "Nombre de secondes avant la recharge d'une rune." +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."] = "Le nombre de secondes entre les mises à jours.|n|n[ATTENTION] En paramétrant la fréquence à 0, la mise à jour s'effectuera à chaque retrace de trame. Si vous voulez désactiver les mises à jour fréquentes, ne définissez pas ceci à 0." +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."] = "La partie de la hauteur totale du cadre cette barre doit utiliser. Il s'agit d'une valeur pondérée : plus elle est grande, plus la partie est importante." +L["How much spacing should be between each new row of groups."] = "Définit l'espacement entre chaque rangée de groupe." +L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."] = "L'espacement entre toutes les barres d'un même cadre d'unité. Les valeurs négatives les éloignent les uns des autres, les valeurs positives les rapprochent. 0 pour n'avoir aucun espacement." +L["How much weight this should use when figuring out the total text width."] = "Le poids de ceci lors de la détermination de la largeur totale du texte." +L["How the frames should grow when a new column is added."] = "Définit la façon dont les cadres s'étendent quand une nouvelle colonne est ajoutée." +L["How the rows should grow when new group members are added."] = "La façon dont les rangées doivent s'étendre quand de nouveaux groupes sont ajoutés." +L["How you want this aura to be anchored to the unit frame."] = "La façon dont vous souhaitez que cet aura soit ancré au cadre d'unité." +L["Icon Size"] = "Taille d'icône" +L["If multiple auras are shown in the same indicator, the higher priority one is shown first."] = "Si plusieurs auras sont affichées dans le même indicateur, celle avec la priorité la plus élevée est montrée en premier." +L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."] = "Si un nom est entré, il doit être exact y compris les majuscules. Autrement, vous pouvez utiliser l'ID de sort à la place." +L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."] = "Si l'unité a un bouclier d'absorption de dégâts, cela montrera la valeur absolue d’absorption, sinon le nom de l'unité." +L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."] = "Si l'unité a des soins entrants, ceci affichera la valeur absolue des soins entrants. Le nom de l'unité sera affiché dans le cas contraire." +L["If the unit is a player then class is returned, if it's a NPC then the creature type."] = "Si l'unité est un joueur, sa classe est renvoyée. S'il s'agit d'un PNJ, son type de créature est renvoyé." +L["If the unit is a player then race is returned, if it's a NPC then the creature type."] = "Si l'unité est un joueur, sa race est renvoyée. S'il s'agit d'un PNJ, son type de créature est renvoyé." +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."] = "Sinon, vous ne pourrez pas utiliser les fonctions des points de combo (Chi, Puissance sacrée, Points de combo, Points d'aura, etc) jusqu'à ce que vous le fassiez." +L["Imp & Dreadstalker bar"] = "Bar des diablotins et traqueffrois" +L["Import"] = "Importer" +L["Import unit frame positions"] = "Importer les positions des cadres d'unité" +L["Import visibility settings"] = "Importer les paramètres de visibilité" +L["In range alpha"] = "Transp. si à portée" +L["Inactive alpha"] = "Transp. qd inactif" +L["Incoming absorb"] = "Dégâts absorbés" +L["Incoming absorbs"] = "Dégâts absorbés" +L["Incoming heal"] = "Soin entrant" +L["Incoming heal (Absolute)"] = "Soins entrants (absolu)" +L["Incoming heal (Percent)"] = "Soins entrants (pourcentage)" +L["Incoming heal (Short)"] = "Soins entrants (court)" +L["Incoming heal/Name"] = "Soins entrants/Nom" +L["Incoming heals"] = "Soins entrants" +L["Index"] = "Index" +L["Indicator color"] = "Couleur de l'indicateur" +L["Indicator for the current pet happiness."] = "Indicateur du bonheur actuel du familier." +L["Indicator name"] = "Nom de l'indicateur" +L["Indicator this aura should be displayed in."] = "Indicateur dans lequel cette aura doit être affichée." +L["Indicators"] = "Indicateurs" +L["Insanity"] = "Insanité" +L["Inset"] = "Encart" +L["Inside Bottom Left"] = "Intérieur Bas Gauche" +L["Inside Bottom Right"] = "Intérieur Bas Droite" +L["Inside Center"] = "Intérieur Centre" +L["Inside Center Left"] = "Intérieur Centre Gauche" +L["Inside Center Right"] = "Intérieur Milieu Droite" +L["Inside Top Left"] = "Intérieur Haut Gauche" +L["Inside Top Right"] = "Intérieur Haut Droite" +L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."] = "Au lieu d'afficher une couleur unie dans l'indicateur, l'icône de l'aura sera affichée." +L["Interrupted"] = "Interrompu" +L["Invalid interval entered, must be a number."] = "Intervalle entré invalide : doit être un nombre." +L["Invalid spell \"%s\" entered."] = "Sort entré \"%s\" invalide." +L["Invert colors"] = "Inverser les couleurs" +L["Layout manager"] = "Gestionnaire de disposition" +L["Leader / Assist"] = "Chef / Assistant" +L["Left"] = "Gauche" +L["Left Bottom"] = "Gauche Bas" +L["Left Center"] = "Gauche Centre" +L["Left text"] = "Texte de gauche" +L["Left Top"] = "Gauche Haut" +L["Let's you modify the base font size to either make it larger or smaller."] = "Vous permet de modifier la taille de police de base afin de la rendre plus grande ou plus petite." +L["Level"] = "Niveau" +L["Level %s - %s: %s/%s (%.2f%% done)"] = "Niveau %s - %s : %s/%s (%.2f%% terminé)" +L["Level %s - %s: %s/%s (%.2f%% done), %s rested."] = "Niveau %s - %s : %s/%s (%.2f%% terminé), %s reposé." +L["Level (Colored)"] = "Niveau (coloré)" +L["Level without any coloring."] = "Le niveau sans aucune coloration." +L["Light"] = "Léger" +L["Link"] = "Lien" +L["Link from"] = "Lier depuis" +L["Link to"] = "Lier vers" +L["Linked spells"] = "Sorts liés" +L["Lock frames"] = "Verr. cadres" +L["Locks the unit frame positionings hiding the mover boxes."] = "Verrouille la position du cadre d'unité, cachant les cadres de déplacement." +L["Low health"] = "Vie faible" +L["M"] = "M" +L["MA ToT"] = "CdC Soutient" +L["Maelstrom"] = "Maelström" +L["Main Assist"] = "Soutiens principaux" +L["Main Assist Target"] = "Cibles des soutiens principaux" +L["Main Assist Target of Target"] = "Cible de la cible des soutiens principaux" +L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."] = "Les soutiens principaux sont définis par le système de soutiens de Blizzard ou les mods qui l'utilisent." +L["Main Tank"] = "Tanks principaux" +L["Main Tank Target"] = "Cibles des tanks principaux" +L["Main Tank Target of Target"] = "Cible de la cible des tanks principaux" +L["Main Tank's are set through the Raid frames, or through selecting the Tank role."] = "Les Tanks Principaux sont définis dans l'interface de raid, ou en choisissant le rôle de Tank." +L["Male"] = "Homme" +L["Mana"] = "Mana" +L["Manage Aura Filters"] = "Gérer filtres d'aura" +L["Management"] = "Gestion" +L["Manual position"] = "Position manuelle" +L["Master Looter"] = "Maître du butin" +L["Max columns"] = "Nbre max. de colonnes" +L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."] = "Vie maximale dans un format court : 17 750 est remplacé par 17.7k, et les valeurs inférieures à 10 000 sont affichées telles qu'elles." +L["Max HP (Absolute)"] = "Vie max. (absolue)" +L["Max HP (Short)"] = "Vie max. (court)" +L["Max power (Absolute)"] = "Puissance max. (absolue)" +L["Max power (Short)"] = "Puissance max. (court)" +L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."] = "Puissance maximale dans un format court : 17 750 remplacé par 17.7k, et les valeurs inférieures à 10 000 sont affichées telles qu'elles." +L["Max rows"] = "Nbre max. de rangées" +L["Medium"] = "Moyen" +L["Minion"] = "Esclave" +L["Miscellaneous"] = "Divers" +L["Missing HP (Short)"] = "Vie manquante (court)" +L["Missing power (Short)"] = "Puissance manquante (court)" +L["Monochrome Outline"] = "Contour monochrome" +L["Moonkin"] = "Sélénien" +L["MT ToT"] = "CdC Tank" +L["Mushroom bar"] = "Bar des champignons" +L["Mushrooms"] = "Champignons" +L["Name"] = "Nom" +L["Name (Abbreviated)"] = "Nom (abbrévié)" +L["Name of a friendly spell to check range."] = "Nom d'un sort amical pour vérifier la portée." +L["Neutral"] = "Neutre" +L["Never (Disabled)"] = "Jamais (désactivé)" +L["New aura group"] = "Nouveau groupe d'aura" +L["New filter"] = "Nouveau filtre" +L["None"] = "Aucun" +L["None (Disabled)"] = "Aucun (désactivé)" +L["NPCs only"] = "PNJs uniquement" +L["Off:%s"] = "Déconnecter :%s" +L["Offline"] = "Hors-ligne" +L["Offline timer"] = "Durée de déconnexion" +L["Ok"] = "Ok" +L["On %s units"] = "Sur %s unités" +L["On aggro"] = "À l'aggro" +L["On curable debuff"] = "Sur débuff dissipable" +L["On elite mobs"] = "Sur monstre élite" +L["On Friendly Units"] = "Sur Unités amies" +L["On Hostile Units"] = "Sur Unités hostiles" +L["On mouseover"] = "Au survol de la souris" +L["On rare mobs"] = "Sur monstre rare" +L["Only active this aura inside an indicator if the group member does not have the aura."] = "Ne montre cette aura dans l'indicateur que si l’unité n'a pas cette aura." +L["Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras."] = "N'applique les filtres sélectionnés qu'aux améliorations des unités amicales et aux affaiblissements des unités hostiles, et montre toutes autres auras." +L["Only auras you specifically cast will be shown."] = "Seules les auras lancées par vous seront affichées." +L["Only show if missing"] = "Seulement si manquant" +L["Only show self cast auras"] = "Seulement les siens" +L["Only show when mana"] = "Montrer seulement le mana" +L["Or you can set a position manually"] = "Ou vous pouvez définir une position manuellement" +L["Order"] = "Ordre" +L["Other Party/Phase Status"] = "Autre statut de Groupe/Phase" +L["Out of range alpha"] = "Transp. si hors de portée" +L["Outline"] = "Contour" +L["Outside bar limit"] = "Hors de la barre" +L["Override background"] = "Écraser l'arrière-plan" +L["Override color"] = "Outrepasser la couleur" +L["Override list"] = "Liste prioritaire" +L["Override list filters"] = "Filtres de liste prioritaire" +L["Override lists"] = "Listes prioritaires" +L["Pain"] = "Douleur" +L["Party"] = "Groupe" +L["Party frames are hidden while in a raid group with more than 5 people inside."] = "Cache les cadres du groupe quand vous vous trouvez dans un groupe de raid de plus de 5 personnes." +L["Party frames are hidden while in any sort of raid no matter how many people."] = "Les cadres du groupe sont cachés quelque soit le type de raid et le nombre de personne le composant." +L["Party instances"] = "Instances de groupe" +L["Party Pet"] = "Familier du groupe" +L["Party Target"] = "Cibles du groupe" +L["Party Target of Target"] = "Cible de la cible du groupe" +L["Party ToT"] = "CdC Groupe" +L["Per column"] = "Par colonne" +L["Per row"] = "Par rangée" +L["Percent HP"] = "Pourcentage de vie" +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."] = "Pourcentage de la vie du joueur qui est soigné. S'il a 100,000 PV total et 15,000 arrivent, cela affichera 15%." +L["Percent power"] = "Pourcentage de puissance" +L["Percentage of width the portrait should use."] = "Définit le pourcentage de la largeur que le portrait doit utiliser." +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."] = "Jusqu'où la barre des soins absorbés peut aller. 130% signifie qu'elle peut aller 30% hors du cadre, 100% signifie qu'elle n'en sortira pas." +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."] = "Jusqu'où la barre d'absorption peut aller. 130% signifie qu'elle peut aller 30% hors du cadre, 100% signifie qu’elle n'en sortira pas." +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."] = "Jusqu'où la barre des soins entrant peut aller. 130% signifie qu'elle peut aller 30% hors du cadre, 100% signifie qu'elle n'en sortira pas." +L["Pet"] = "Familier" +L["Pet Battle"] = "Combat de mascottes" +L["Pet Happiness"] = "Bonheur des familiers" +L["Pet Target"] = "Cible du familier" +L["Player"] = "Joueur" +L["player alt. power"] = "puissance alt. du joueur" +L["player cast bar"] = "barre d'incant. du joueur" +L["Player Class"] = "Classe du Joueur" +L["player power frames"] = "cadre de puissance du joueur" +L["Player threat"] = "Menace du joueur" +L["Players only"] = "Joueurs uniquement" +L["Players will be colored by class."] = "Les joueurs seront coloriés selon la classe." +L["Point"] = "Point" +L["Portrait"] = "Portrait" +L["Portrait type"] = "Type de portrait" +L["Position"] = "Position" +L["Positioning"] = "Positionnement" +L["Power"] = "Puissance" +L["Power bar"] = "Barre de puissance" +L["Power Type"] = "Type de puissance" +L["Prevents unit tooltips from showing while in combat."] = "Empêche les bulles d'aide des unités de s'afficher quand vous êtes en combat." +L["Priest mana bar"] = "Barre de mana de Prêtre" +L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."] = "Méthode principale pour colorer la barre de vie. Les couleur par aggro et couleur par réaction peuvent l'outrepasser si nécessaire." +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."] = "Moyens principaux de colorier la barre de puissance. La coloration par classe s'applique uniquement aux joueurs, les non-joueurs utiliseront comme couleur le type de puissance par défaut." +L["Prioritize buffs"] = "Priorité aux buffs" +L["Priority"] = "Priorité" +L["Programming in Lua"] = "Programmer en Lua" +L["PvP Flag"] = "Marqueur PvP" +L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."] = "Indicateur de marque PvP. Horde pour les joueurs de la Horde marqués et Alliance pour ceux de l'Alliance." +L["PvP Flags"] = "Drapeaux PvP" +L["PVP timer"] = "Durée PvP" +L["PVP:%s"] = "PvP :%s" +L["Quest Boss"] = "Boss de quête" +L["Race"] = "Race" +L["Race (Smart)"] = "Race (intelligent)" +L["Rage"] = "Rage" +L["Raid"] = "Raid" +L["Raid assisting unit"] = "Soutien du raid sur l'unité" +L["Raid frames are hidden while in a raid group with 5 or less people inside."] = "Les cadres de raid sont masqués si vous vous trouvez dans un groupe de raid de 5 personnes ou moins." +L["Raid instances"] = "Instances de raid" +L["Raid Misc"] = "Raid divers" +L["Raid pet"] = "Familier du raid" +L["Raid Role"] = "Rôle en raid" +L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."] = "Indicateur de rôle de raid. Ajoute un bouclier pour les tanks principaux et une épée pour les soutiens principaux." +L["Raid Target"] = "Cible de raid" +L["Raid target indicator."] = "Indicateur de cible de raid" +L["Raid targeting unit"] = "Ciblage du raid sur l'unité" +L["Range Checker"] = "Vérification de portée" +L["Range indicator"] = "Indicateur de portée" +L["Rare"] = "Rare" +L["Rare Elite"] = "Élite Rare" +L["Rare indicator"] = "Indicateur de rareté" +L["Rather than bars filling from left -> right, they will fill from bottom -> top."] = "Au lieu de se remplir de gauche à droite, les barres se rempliront de bas en haut." +L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."] = "Code couleur de réaction utilisez [reactcolor][name][close] pour colorer les noms d'unité selon leur réaction." +L["Reaction color tag"] = "Tag couleur de réaction" +L["Ready Status"] = "Statut de l'appel" +L["Ready status of group members."] = "Résultats de l'appel des membres du groupe." +L["Red (>70% HP)"] = "Rouge (>70% PV)" +L["Relative point"] = "Point relatif" +L["Resources"] = "Ressources" +L["Resurrect Status"] = "Statut de résurrection" +L["Returns + if the unit is an elite or rare elite mob."] = "Renvoie + si l'unité est un monstre élite ou rare élite." +L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."] = "Renvoie un code de couleur indiquant indiquant votre niveau de menace avec votre cible : rouge pour Aggro, orange pour Menace élevée et jaune pour Prudence." +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."] = "Renvoie un code de couleur indiquant votre niveau de menace envers toutes les unités : rouge pour Aggro, orange pour Menace élevée et jaune pour Prudence." +L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."] = "Renvoie un pourcentage pondéré de la menace envers votre cible actuelle compris entre 0 et 100%." +L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."] = "Renvoie la vie actuelle sous forme de pourcentage, sauf si l'unité est morte ou déconnectée." +L["Returns current power as a percentage."] = "Renvoie la puissance actuelle sous forme de pourcentage." +L["Returns Rare if the unit is a rare or rare elite mob."] = "Renvoie Rare si l'unité est un monstre rare ou rare élite." +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."] = "Donne un texte selon la menace générale de l'unité : Aggro quand elle a l'aggro, High pour proche de prendre l'aggro, et Medium pour avertir d'être prudent.|nCela ne peut pas être utilisé sur des unités de type Cible de Cible ou Cible de Focus." +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."] = "Renvoie un texte de indiquant votre niveau de menace envers toutes les unités : Aggro quand vous avez l'aggro, Élevé quand vous êtes sur le point de reprendre l'aggro et Moyen comme avertissement général." +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."] = "Renvoie un texte indiquant votre niveau de menace avec votre cible : Aggro quand vous avez l'aggro, Élevé quand vous êtes sur le point de reprendre l'aggro et Moyen comme avertissement général." +L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."] = "Renvoie un code de couleur basée sur la comparaison du niveau de l'unité par rapport à vous. Si vous ne pouvez pas l'attaquer, aucune code de couleur n'est renvoyé." +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."] = "Donne le code couleur selon la menace générale de l'unité : Rouge pour Aggro, Orange pour Menace élevée, Jaune pour faire attention.|nCela ne peut pas être utilisé sur des unités de type Cible de Cible ou Cible de Focus." +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."] = "Donne le pourcentage de menace mis à l'échelle de l'unité. Si vous mettez cela sur un membre du groupe, vous verrez combien il est prêt d'en avoir de n'importe quel mob hostile. Toujours 0 - 100%.|nCela ne peut pas être utilisé sur des unités de type Cible de Cible ou Cible de Focus." +L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."] = "Renvoie la forme actuelle de l'unité s'il s'agit d'un druide (chat, sélénien, etc.)." +L["Returns the units sex."] = "Renvoie le sexe de l'unité." +L["Reverse fill"] = "Remplissage inversé" +L["Right"] = "Droite" +L["Right Bottom"] = "Droite Bas" +L["Right Center"] = "Droite Centre" +L["Right text"] = "Texte de droite" +L["Right Top"] = "Droite Haut" +L["Role the unit is playing."] = "Rôle joué par l'unité." +L["Row growth"] = "Sens d'ajout des rangées" +L["Row offset"] = "Décalage des rangées" +L["Rune bar"] = "Barre des runes" +L["Rune of Power"] = "Rune de puissance" +L["Rune of Power bar"] = "Barre de runes de puissance" +L["Rune Timer"] = "Compteur de Runes" +L["Runes"] = "Runes" +L["Runic Power"] = "Puissance runique" +L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."] = "Idem que [color:sit], à l'exception qu'il ne renvoie la couleur rouge que si vous avez l'aggro, au lieu d'effectuer la transition jaune -> orange -> rouge." +L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."] = "Idem que [unit:color:sit], à l'exception qu'il ne renvoie la couleur rouge que si l'unité a l'aggro, au lieu d'effectuer la transition jaune -> orange-> rouge." +L["Scale"] = "Échelle" +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."] = "Echelle pour les auras que vous avez lancé ou pouvez volez. Plus de 100% sera plus grand que par défaut, moins de 100% sera plus petit." +L["Scaled aura size"] = "Echelle d'aura spéciale" +L["Scaled threat percent"] = "Pourcentage de menace pondéré" +L["Screen"] = "Écran" +L["Search"] = "Rechercher" +L["Search tags"] = "Recherche de tag" +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."] = "Parcourez la documentation ci-dessous pour obtenir des informations et des exemples sur la création de tags. Si vous souhaitez des informations basiques concernant Lua ou l'API de WoW, reportez-vous aux liens vers Programming in Lua et WoW Programming." +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."] = "Sélectionnez les unités que vous voulez modifier. Tous les réglages modifiés changeront toutes les unités sélectionnées. Si vous voulez changer l'ancrage ou les réglages spéciaux de groupe/raid, vous devrez faire ça dans leurs options.|n|nShift-clic une unité pour les sélectionner/désélectionner toutes." +L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."] = "Choisir un tag de texte du panneau de gauche pour changer les tags. La largeur, la taille, et le décalage peuvent être réglés dans le panneau actuel." +L["Separate raid frames"] = "Séparer les cadres" +L["Set Filter Zones"] = "Définir filtre par zone" +L["Sex"] = "Sexe" +L["Shadow Orbs"] = "Orbes d'ombre" +L["Shaman mana bar"] = "Barre de mana de Chaman" +L["Short classification"] = "Classification courte" +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."] = "Classification courte, R pour Rare, Rare+ pour Rare Élite, + pour Élite, B pour Boss, M pour Serviteur. Rien s'il ne sont d'aucune de ces catégories." +L["Short elite indicator"] = "Indicateur court d'élite" +L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."] = "Version courte de [druidform], C = Félin, B = Ours , F = Vol et ainsi de suite." +L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."] = "Absorption de dégâts courte. Si 13 000 dégâts seront absorbés, 13k sera affiché." +L["Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k."] = "Valeur courte de soins absorbés. Si 17 000 de soins seront absorbés, 17k sera affiché." +L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."] = "Raccourcit la valeur des soins entrants. Si 13 000 points de soins arrivent, 13k sera affiché." +L["Show a background behind the bars with the same texture/color but faded out."] = "Affiche un arrière-plan derrière les barres avec la même texture/couleur mais estompé." +L["Show any other auras"] = "Montrer toute autre aura" +L["Show as bar"] = "Afficher comme barre" +L["Show aura duration"] = "Montrer durée de l'aura" +L["Show aura icon"] = "Montrer icône de l'aura" +L["Show auras stack"] = "Montrer stacks de l'aura" +L["Show background"] = "Aff. l'arrière-plan" +L["Show boss debuffs"] = "Montrer débuffs de boss" +L["Show buffs before debuffs when sharing the same anchor point."] = "Affiche les buffs avant les débuffs quand ces deux types d'auras partagent le même point d'ancrage." +L["Show cast name"] = "Aff. nom de l'incant." +L["Show cast time"] = "Aff. tps d'incantation" +L["Show castable on other auras"] = "Montrer auras lancées par d'autres" +L["Show casted by boss"] = "Montrer auras lancées par les boss" +L["Show curable debuffs"] = "Montrer auras dissipables" +L["Show curable/removable auras"] = "Montrer auras dissipables" +L["Show Heal Absorbs"] = "Montrer soins absorbés" +L["Show icon durations"] = "Durée sur l'icône." +L["Show incoming absorbs"] = "Montrer les absorption prévues" +L["Show incoming heals"] = "Afficher les soins entrants" +L["Show inside"] = "Montrer dedans" +L["Show party as raid"] = "Aff. groupe comme raid" +L["Show player in party"] = "Aff. joueur ds groupe" +L["Show your auras"] = "Montrer vos auras" +L["Shows a bar for alternate power info (used in some encounters)"] = "Affiche une barre contenant les informations de la puissance alternative (utilisé dans certaines rencontres)." +L["Shows a cooldown wheel on the indicator with how much time is left on the aura."] = "Affiche une spirale de recharge sur l'indicateur qui montre le temps restant sur l'aura." +L["Shows AFK, DND or nothing depending on the units away status."] = "Affiche ABS, NPD ou rien du tout selon le statut de l'unité." +L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."] = "Affiche les retours de combat : dernier dégâts ou soins reçus par l'unité, esquive, etc." +L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."] = "Affiche la vie actuelle et maximale en valeur absolue." +L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."] = "Affiche la puissance actuelle et maximale en valeur absolue." +L["Shows current group number of the unit."] = "Affiche le numéro de groupe actuel de l'unité." +L["Shows current health value in absolute form meaning 15000 health is shown as 15000."] = "Affiche les points de vie actuels de la vie en valeur absolue." +L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."] = "Affiche les points de puissance actuels puissance en valeur absolue." +L["Shows debuffs cast by a boss."] = "Affiche les débuffs lancés par un boss." +L["Shows debuffs that you can cure."] = "Affiche les débuffs que vous pouvez dissiper." +L["Shows how long an unit has been AFK or DND."] = "Indique depuis combien de temps une unité est ABS ou en mode NPD." +L["Shows how long an unit has been offline."] = "Affiche depuis combien de temps une unité est hors ligne." +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."] = "Affiche le temps avant que le mode PvP se désactive. N'apparaitra pas si le mode est activé manuellement ou dans une zone hostile.|n|nCela ne marchera que pour vous, vous ne pouvez pas voir le temps restant pour votre groupe ou raid." +L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."] = "Affiche les points de vie maximaux en valeur absolue." +L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."] = "Affiche les points de puissance maximaux en valeur absolue." +L["Shows Offline, Dead, Ghost or nothing depending on the units current status."] = "Affiche Hors-ligne, Mort, Fantôme ou rien du tout selon le statut de l'unité." +L["Shows that a NPC is a boss for a quest."] = "Indique qu'un PNJ est un boss lié à une quête." +L["Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000."] = "Montre la valeur absolue des dégâts reportés. Si 16000 dégâts sont reportés, montre 16000." +L["Shows the current staggered damage, if 12,000 damage is staggered, shows 12k."] = "Montre les dégâts reportés. Si 12000 dégâts sont reportés, montre 12k." +L["Show's the units guild name if they are in a guild."] = "Affiche le nom de la guilde de l'unité si elle en a une." +L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."] = "Affiche la vie de l'unité comme pourcentage arrondi à la première décimale." +L["Shows what kind of pet the unit is for pet battles."] = "Indique quel genre de mascotte est l'unité dans les combat de mascottes." +L["Shows when a party member is in a different phase or another group."] = "Indique quand un membre du groupe est dans une phase différente ou dans un autre groupe." +L["Simple aura filtering by whitelists and blacklists."] = "Filtrage simple des auras à l'aide de listes blanches et noires." +L["Size"] = "Taille" +L["Smart Friendly/Hostile Filter"] = "Filtre Amical/Hostile intelligent" +L["Smart level"] = "Niveau intelligent" +L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."] = "Niveau intelligent : renvoie Boss pour les boss, +50 pour un monstre élite de niveau 50 ou juste 80 pour un niveau 80." +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."] = "Affichage intelligent des nombres pour [curmaxhp]. Ceux inférieurs à 1 000 000 sont laissés tels quels, ceux supérieurs utiliseront la version courte du type 1m." +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."] = "Affichage intelligent des nombres pour [curmaxpp]. Ceux inférieurs à 1 000 000 sont laissés tels quels, ceux supérieurs utiliseront la version courte du type 1m." +L["Solid color to use in the indicator, only used if you do not have use aura icon enabled."] = "Couleur unie à utiliser dans l'indicateur, utilisée seulement si vous n’utilisez pas l'icône de l'aura." +L["Sort method"] = "Méthode de tri" +L["Sort order"] = "Ordre de tri" +L["Sorting"] = "Tri" +L["Soul Shards"] = "Fragments d'âme" +L["Soul shards"] = "Fragments d'âme" +L["Spacing"] = "Espacement" +L["Spacing between each row"] = "Espacement entre chaque rangée" +L["Spell ID %s"] = "ID de sort %s" +L["Spell Name"] = "Nom de Sort" +L["Spell Name/ID"] = "Nom/ID du sort" +L["Spell you want to link to a primary aura, the casing must be exact."] = "Sort que vous voulez lier à une aura principale. Les majuscules doivent être exactes." +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."] = "Sépare les cadres de raid en cadres individuels pour chaque groupe au lieu d'un seul cadre.|nNOTE ! Vous ne pouvez pas déplacer chaque groupe individuellement, mais leur croissance est gérée par les options de croissance des colonnes et rangées." +L["Stagger"] = "Report" +L["Stagger (Monk)"] = "Report (Moine)" +L["Stagger (Monk/Absolute)"] = "Report (Moine/Absolu)" +L["Stagger bar"] = "Barre de Report" +L["Stagger bar color when the staggered amount is <30% of your HP."] = "Couleur de la barre de Report quand le montant reporté est <30% de vos PV." +L["Stagger bar color when the staggered amount is >30% of your HP."] = "Couleur de la barre de Report quand le montant reporté est >30% de vos PV." +L["Stagger bar color when the staggered amount is >70% of your HP."] = "Couleur de la barre de Report quand le montant reporté est >70% de vos PV." +L["Static"] = "Statique" +L["Statue"] = "Statue" +L["Statue bar"] = "Barre de statue" +L["Status"] = "Statut" +L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."] = "Indicateur de statut, affiche si l'unité est actuellement en combat. Pour le joueur, il indique également si vous êtes en repos." +L["Stealable/Curable/Dispellable"] = "Volable/Soignable/Dissipable" +L["Style of borders to show for all auras."] = "Le style des bordures à afficher pour toutes les auras." +L["Summon Pending"] = "Invocation en cours" +L["T"] = "T" +L["Tag list"] = "Liste des tags" +L["Tag name"] = "Nom du tag" +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]."] = "Tag que vous utiliserez pour accéder à ce code. Ne le mettez pas entre crochets ou parenthèses, c'est automatique. Par exemple entrez \"foobar\" et utilisez-le ensuite avec [foobar]." +L["Tags"] = "Tags" +L["Talent spec of your arena opponents."] = "Spécialisation de vos adversaires d'arène." +L["Target"] = "Cible" +L["Target of Target"] = "Cible de la cible" +L["Target of Target of Target"] = "Cible de la cible de la cible" +L["Test Aura"] = "Aura de test" +L["Test spell"] = "Sort de test" +L["Text"] = "Texte" +L["Text Management"] = "Gestion de texte" +L["Text name"] = "Nom du texte" +L["Text name that you can use to identify this text from others when configuring."] = "Un nom de texte que vous pouvez utiliser pour identifier ce texte parmi d'autres lors de la configuration." +L["Text parent"] = "Texte parent" +L["Text/Tags"] = "Texte/Tags" +L["The blacklist \"%s\" already exists."] = "La liste noire \"%s\" existe déjà." +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."] = "Les cases ci-dessous permettent d'activer ou désactiver des unités.|n|n|cffff2020Attention !|r Les Cible de la Cible ont un plus grand impact sur les performances comparés aux autres unités. Si vous avez des problèmes de performances, désactivez ces unités ou réduisez le nombre d'éléments actifs pour ces unités." +L["The override list \"%s\" already exists."] = "La liste prioritaire \"%s\" existe déjà." +L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."] = "Le cadre du joueur ne sera pas caché dans tous les cas, vous devrez manuellement le désactiver soit entièrement soit par type de zone." +L["The tag \"%s\" already exists."] = "Le tag \"%s\" existe déjà." +L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."] = "Les cadres d'unité que vous voyez sont des exemples ; ils ne sont pas parfaits et n'affichent pas toutes les données qu'ils afficheraient en temps normal.|n|nVous pouvez les cacher en les verrouillant via /shadowuf ou en cliquant sur le bouton ci-dessous." +L["The whitelist \"%s\" already exists."] = "La liste blanche \"%s\" existe déjà." +L["Thick outline"] = "Contour épais" +L["Thin outline"] = "Contour fin" +L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."] = "Cette barre se cachera automatiquement quand vous atteindrez le niveau maximal, ou si vous ne suivez aucune réputation." +L[ [=[This color will be used if the indicator shown is your own, only applies if icons are not used. +Handy 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.]=] ] = [=[Cette couleur sera utilisée si l'indicateur affiché est le votre, si l'icône n'est pas utilisée. +Pratique si vous voulez savoir si une cible a Récupération sur elle, mais que vous voulez aussi savoir si vous êtes celui qui a lancé cette Récupération.]=] +L["This filter has no aura types set to filter out."] = "Ce filtre n'a aucun type d'auras à filtrer." +L["This filter has no auras in it, you will have to add some using the dialog above."] = "Ce filtre ne contient aucune aura. Ajoutez en au moins une ci-dessus." +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."] = "Il s'agit d'un bon guide sur la façon de s'initier à la programmation en Lua. Bien que vous ne devez pas tout lire, il est très utile pour comprendre les bases de la syntaxe et des APIs Lua." +L["This unit depends on another to work, disabling %s will disable %s."] = "Cette unité dépend d'une autre pour fonctionner : désactiver %s désactivera %s." +L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."] = "Cette unité possède des unités-filles qui dépendent d'elle : vous devez activer cette unité avant de pouvoir activer ses filles." +L[ [=[This will be set for your current class only. +If no custom spells are set, defaults appropriate for your class will be used.]=] ] = [=[Réglé pour votre classe actuelle seulement. +Si aucun sort personnalisé n'est défini, des sorts par défaut de votre classe seront utilisés.]=] +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."] = "Ceci désactivera la détection automatique des événements que ce tag aura besoin. Il est vivement conseillé de laisser ceci décoché à moins que vous savez ce que vous faites." +L["This will override all background colorings for bars including custom set ones."] = "Ceci écrasera toutes les colorations d'arrière-plan des barres, y compris celles personnalisées." +L["Threat"] = "Menace" +L["Threat situation"] = "Situation de la menace" +L["Tile size"] = "Taille de carreau" +L["Timer Text"] = "Texte du compteur" +L["Top"] = "Haut" +L["Top Center"] = "Haut Centre" +L["Top Left"] = "Haut Gauche" +L["Top Right"] = "Haut Droite" +L["Total number of active holy power."] = "Nombre total de puissances sacrées actives." +L["Total number of active soul shards."] = "Nombre total de fragments d'âme actifs." +L["Total number of combo points you have on your target."] = "Nombre total de points de combo que vous avez sur votre cible." +L["Totem bar"] = "Barre de Totem" +L["Totem Timer"] = "Compteur de totems" +L["Travel"] = "Voyage" +L["Tree"] = "Arbre" +L["Turns this widget into a bar that can be resized and ordered just like health and power bars."] = "Transforme ce widget en barre qui peut être redimensionnée et ordonnée de la même façon que les barres de vie et de puissance." +L["Unattackable hostile"] = "Hostile inattaquable" +L["Unchecking this will completely disable aura indicators for %s."] = "Décocher pour désactiver complètement les indicateurs d'auras pour %s." +L["Unit color code on aggro"] = "Code couleur d'unité si aggro" +L["Unit colored situation"] = "Couleur de situation d'unité" +L["Unit Configuration"] = "Configuration d'unités" +L["Unit faction"] = "Faction de l'unité" +L["Unit name"] = "Nom de l'unité" +L["Unit name (Class colored)"] = "Nom de l'unité (coloré selon la classe)" +L["Unit name colored by class."] = "Nom de l'unité coloré selon la classe." +L["Unit scaled threat"] = "Menace pondérée de l'unité" +L["Unit server"] = "Serveur de l'unité" +L["Unit server, if they are from your server then nothing is shown."] = "Serveur de l'unité. Si l'unité provient de votre serveur, rien n'est affiché." +L["Unit situation name"] = "Nom de situation d'unité" +L["Units"] = "Unités" +L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."] = "Faction de l'unité : Thrall renvoie Horde, tandis que Magni Barbe-de-bronze renvoie Alliance." +L["Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those."] = "Classification d'unités, Rare, Rare Élite, Élite, Boss, Serviteur. Rien s'il ne sont d'aucune de ces catégories." +L["Units per column"] = "Unités par colonne" +L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."] = "Race de l'unité : Elfe de sang, Tauren, etc." +L["Units that should have the aura groups settings changed below."] = "Les unités dont les réglages de groupe d'aura seront changés ci-dessous." +L["Units to change"] = "Unités à changer" +L["Unknown"] = "Inconnu" +L["Unlink frames"] = "Délier cadres" +L["Up"] = "Haut" +L["Update interval"] = "Intervalle de m. à j." +L["Uses the icon of the totem being shown instead of a status bar."] = "Utilise l'icône du totem au lieu d'une barre de statut." +L["Using unit settings"] = "Utilisation des paramètres d'unité" +L["Various units can be enabled through this page, such as raid or party targets."] = "De nombreuses unités peuvent être activés grâce à cette page, telles que les unités de raid ou les cibles du groupe." +L["Vehicle"] = "Véhicule" +L["Vehicles"] = "Véhicules" +L["Vertical growth"] = "Croissance verticale" +L["View"] = "Voir" +L["Visibility"] = "Visibilité" +L["WARNING! ShadowedUF_Indicators has been deprecated as v4 and is now built in. Please delete ShadowedUF_Indicators, your configuration will be saved."] = "ATTENTION ! ShadowedUF_Indicators est obsolète car il est intégré avec la v4. Veuillez supprimer ShadowedUF_Indicators, votre configuration sera sauvée." +L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] = "ATTENTION : ceci déliera tous les cadres des uns et des autres afin que vous puissiez les déplacer sans qu'un autre cadre bouge avec." +L["What group this aura belongs to, this is where you will find it when configuring."] = "Le groupe auquel cette aura appartient. C'est là que vous la trouverez pour la configurer." +L["What type of auras should be enlarged, use the scaled aura size option to change the size."] = "Quel type d'aura doit être agrandi. Utilisez l'option Echelle d'aura spéciale pour régler la taille." +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."] = "Quand il manque de la vie à l'unité, le tag [missinghp] est affiché, quand sa vie est pleine le tag [name] est affiché. Cela vous permet de voir -1000 s'il leur manque 1000 PV, mais leur nom quand il ne leur manque rien." +L["When this filter is active, apply the filter to buffs."] = "Quand ce filtre est actif, applique le filtre aux buffs." +L["When this filter is active, apply the filter to debuffs."] = "Quand ce filtre est actif, applique le filtre aux debuffs." +L["When to color the empty bar by reaction, overriding the default color by option."] = "Quand colorer la barre vide selon la réaction, outrepassant la couleur par défaut." +L["When to color the health bar by the units reaction, overriding the color health by option."] = "Quand colorer la barre de vie selon la réaction de l'unité, outrepassant la couleur de barre de vie." +L["When to show cooldown rings on auras"] = "Quand afficher la spirale de recharge sur les auras." +L["Where inside the frame the text should be anchored to."] = "L'endroit à l'intérieur du cadre où le texte doit être ancré." +L["Where to anchor the cast name text."] = "L'endroit où ancrer le texte du nom de l'incantation." +L["Where to anchor the cast time text."] = "L'endroit où ancrer le texte de la durée d'incantation." +L["Whether auras you casted should be shown"] = "Afficher les auras que vous avez lancées." +L["Whether to show any auras casted by the boss"] = "Afficher les auras lancées par le boss." +L["Whether to show any debuffs you can remove, cure or steal."] = "Afficher les débuffs que vous pouvez enlever, soigner, ou voler." +L["Whether to show auras that do not fall into the above categories."] = "Afficher les auras qui n'appartiennent pas aux catégories précédentes." +L["Whether to show buffs that you cannot cast."] = "Afficher les buffs que vous ne pouvez pas lancer." +L["Whitelist"] = "Liste blanche" +L["Whitelist filters"] = "Filtres des listes blanches" +L["Whitelists"] = "Listes blanches" +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."] = "Une liste blanche cache toute aura qui n'est pas dans le groupe de filtres.|nUne liste noire cache les auras qui sont dans le groupe de filtres.|nUne liste prioritaire ignorera les autres filtres et sera toujours montrée." +L["Widget Size"] = "Taille des éléments" +L["Width"] = "Largeur" +L["Width percent"] = "%tage de la largeur" +L["Width weight"] = "Poids en largeur" +L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."] = "Se remplira de droite à gauche en croissance horizontale, ou de haut en bas en croissance verticale." +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"] = "Vous vous demandez ce que tous les onglets de la configuration d'unité signifient ? Voici quelques informations :|n|n|cfffed000Général :|r Portrait, vérification des portées, fondu de combat, surbrillance de la bordure|n|cfffed000Cadre:|r Positionnement de l'unité et ancrage du cadre|n|cfffed000Barres :|r Vie, puissance, barre d'incantation et vide, configuration des points de combo|n|cfffed000Taille de widget :|r options de taille et d'ordre de toutes les barres et du portrait|n|cfffed000Auras :|r Config. de toutes les auras (activation/désactivation/élargissement des siens/etc.)|n|cfffed000Indicateurs :|r Configuration de tous les indicateurs|n|cfffed000Texte/Tags :|r Gestion des tags ainsi que paramètres de positionnement et de largeur du texte|n|n|n*** Options fréquemment recherchées ***|n|n|cfffed000Cadres de raid par groupe :|r Configuration d'unité -> Raid -> Raid -> Séparer les cadres de raid|n|cfffed000Coloration selon la classe :|r Barres -> Colorer la vie par|n|cfffed000Durée sur les auras :|r Il vous faut OmniCC pour cela|n|cfffed000Afficher/cacher le cadre des buffs par défaut :|r Cacher Blizzard -> Cacher cadre des buffs|n|cfffed000Texte de pourcentage des PVs/PMs :|r Onglet Tags/Texte, utilisez le tag [percenthp] ou [percentpp]|n|cfffed000Cacher le groupe selon le raid|r - Configuration d'unité -> Groupe -> Groupe -> Cacher si raid > 5 joueurs/Cacher dans tous les raids" +L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."] = "Fonctionne comme [%s], mais montre toujours la mana et n'est affiché que si la mana est la puissance secondaire." +L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."] = "Fonctionne de la même manière que [%s], mais s'affiche uniquement si l'unité est en forme de félin ou d'ours." +L["WoW Programming"] = "Programmation WoW" +L["WoW Programming is a good resource for finding out what difference API's do and how to call them."] = "WoW Programming est un bon outil pour trouver ce que font les différentes API et comment y faire appel." +L["X Offset"] = "Décalage en X" +L["XP/Rep bar"] = "Barre d'EXP/de réput." +L["Y Offset"] = "Décalage en Y" +L["Yellow (>30% HP)"] = "Jaune (>30% PV)" +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."] = "Vous pouvez ajouter des textes additionnels avec les tags activés avec cette config. Notez que tout texte ajouté (ou enlevé) affecte toutes les unités. Enlever un texte réinitialisera également leurs réglages.|n|nNoubliez pas, vous ne pouvez pas supprimer les textes par défaut inclus avec les unités." +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."] = "Vous pouvez ajouter de nouveaux tags personnalisés sur cette page. Si vous cherchez à changer quels tags sont utilisés en texte, regardez dans l'onglet Texte d'une configuration d'unité." +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."] = "Vous pouvez désactiver les filtres et groupes d'auras pour des unités ici. Par exemple, vous pourriez faire un groupe d'auras qui montre les débuffs pour DPS qui ne s'affiche que sur la cible." +L["You can find more information on creating your own custom tags in the \"Help\" tab above."] = "Vous pouvez trouver plus d'informations sur la façon de créer vos propres tags dans l'onglet \"Aide\" ci-dessus." +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."] = "Vous trouverez plus d'informations sur la création de vos propres tags dans l'onglet \"Aide\" ci-dessus.|nSUF essaiera de détecter automatiquement quels évènements votre tag utilise, vous n'aurez donc généralement pas besoin de remplir ces champs." +L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] = "Vous pouvez importer la configuration d'autres utilisateurs de Shadowed Unit Frames en entrant ci-dessous le code d'exportation qu'ils vous donnent. Cela aura pour effet de sauvegarder votre ancienne disposition dans \"Sauvegarde d'importation\".|n|nIl faudra entre 30 et 60 secondes pour importer la disposition que vous aurez collé, soyez donc patient." +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."] = "Vous pouvez lier des auras ensemble avec ça. Par exemple vous pouvez lier Marque du fauve à Don du fauve, pour qu'un joueur qui a Marque du fauve mais pas Don du fauve apparaisse comme s'il l'avait." +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."] = "Vous pouvez décider quelle aura est activée classe par classe. Notez que si l'aura est désactivée dans la liste principale, le réglage par classe ne changera rien." +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."] = "Vous pouvez définir quel cadre d'unité utilise quel groupe de filtres dans quelles zones ici. Si vous voulez changer quelle aura va dans quel groupe, voyez les options \"Gérer les filtres d'aura\"." +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."] = "Vous ne pouvez pas éditer ce tag car il s'agit d'un des tags par défaut de cet addon. Cette fonction est présente afin de fournir un exemple pour vos propres tags." +L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."] = "Vous ne pouvez pas nommer un tag \"%s\" : les noms de tag ne peuvent contenir de crochets ou de parenthèses." +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."] = "Vous n'avez pas encore ajouté de filtre de ce type, vous devez en créer un dans le panneau de gestion avant que cette page ne soit utile." +L["You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf."] = "Vous venez d'entrer en combat, les cadres d'unité ont été verrouillées. Une fois que vous êtes sorti de combat, vous devrez les déverrouiller à nouveau via la commande /shadowuf" +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."] = "Vous devez définir les événements à déclencher en utilisant uniquement des lettres et des tirets bas. Par exemple, \"FOO_BAR\" est valide, tandis que \"APPLE_5_ORANGE\" ne l'est pas car il contient un nombre." +L["You must enter a number that is 0 or higher, negative numbers are not allowed."] = "Vous devez entrer un nombre supérieur à 0 : les nombres négatifs ne sont pas autorisés." +L["You must enter a tag name."] = "Vous devez entrer un nom de tag." +L["You must restart Shadowed Unit Frames."] = "Vous devez redémarrer Shadowed Unit Frames." +L["You must wrap your code in a function."] = "Vous devez placer votre code dans une fonction." +L["You will need to create an aura filter before you can set which unit to enable aura filtering on."] = "Vous aurez besoin de créer un filtre d'aura avant de pouvoir définir sur quelle unité activer le filtrage d'aura." +L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."] = "Vous aurez besoin d'effectuer un /console reloadui avant qu'un cadre caché ne puisse être visible à nouveau.|nLe joueur ainsi que d'autres cadres d'unité sont automatiquement cachés si ces derniers ont été activés dans Shadowed Unit Frames." +L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] = "Votre disposition active est le profil utilisé pour la sauvegarde d'importation, ceci ne peut pas être écrasé par un import. Changez vos profils vers quelque chose d'autre et essayez à nouveau." +L["Your aura color"] = "Couleur de votre aura" +L["Your Auras"] = "Vos auras" +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"] = "Votre code doit être contenu dans une fonction. Par exemple, si vous voulez créer un tag qui renvoie le nom de l'unité, le code doit ressembler à ceci :|n|nfunction(unit, unitOwner)|nreturn UnitName(unitOwner)|nend" +L["Zone Configuration"] = "Configuration de zone" +L["Zone configuration units"] = "Unités de Config. de zone" + +local ShadowUF = select(2, ...) +ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) diff --git a/localization/koKR.lua b/localization/koKR.lua index 4a52690ec..3e16726e2 100755 --- a/localization/koKR.lua +++ b/localization/koKR.lua @@ -1,5 +1,940 @@ -if( GetLocale() ~= "koKR" ) then return end -local L = {} ---@localization(locale="koKR", format="lua_additive_table", handle-unlocalized="ignore")@ -local ShadowUF = select(2, ...) -ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) +if( GetLocale() ~= "koKR" ) then return end +local L = {} +L["%d auras in group"] = "그룹 내 오라 %d개" +L["%s (%s): %s/%s (%.2f%% done)"] = "%s (%s): %s/%s (현재 %.2f%%)" +L["%s aura groups disabled"] = "오라 그룹 %s개 사용 안 함" +L["%s frames"] = "%s 창" +L["%s member"] = "%s 구성원" +L["|cff20ff20%s|r units enabled"] = "|cff20ff20%s|r 유닛 사용함" +L["|cffff2020%s|r units disabled"] = "|cffff2020%s|r 유닛 사용 안 함" +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."] = "|cffff2020경고!|r 일부 유닛은 지역 구성 옵션에 재정의 세트가 있으며, 특정 지역에서 표시되거나 표시되지 않을 수도 있습니다. 아래 설정에도 불구하고." +L["1 aura group disabled"] = "오라 그룹 1개 사용 안 함" +L["2D"] = "2D" +L["3D"] = "3D" +L["A"] = "바" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "영문 10글자 이상의 이름을 줄여씁니다. \"Dark Rune Champion\" 을 \"D.R.Champion\" 으로 \"Dark Rune Commoner\" 를 \"D.R.Commoner\" 형식으로..." +L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."] = "유닛의 피해 흡수량 절댓값으로, 피해량 10,000이 흡수되는 경우 10,000으로 표시합니다." +L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."] = "치유 흡수량 절댓값으로, 치유량 16,000이 흡수되는 경우 16,000으로 표시합니다." +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "시전 중 치유량 절댓값으로, 치유량이 10,000이면 10,000으로 표시합니다." +L["Add"] = "추가" +L["Add Aura"] = "오라 추가" +L["Add aura"] = "오라 추가" +L["Add Indicator"] = "표시기 추가" +L["Add link"] = "링크 추가" +L["Add new indicator"] = "새로운 표시기 추가" +L["Add new tag"] = "새로운 태그 추가" +L["Add new text"] = "새로운 텍스트 추가" +L["Add Tags"] = "태그 추가" +L["Adds %s to the list of units to be modified when you change values in this tab."] = "이 탭에서 값을 바꾸면 수정되는 유닛 목록에 %s|1을;를; 추가합니다." +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "구울 타이머에 남은 시간을 나타내는 바를 추가하며, 지속 구울이 없는 경우에만 사용됩니다." +L["Adds a bar indicating how much time is left on your mushrooms."] = "버섯에 남은 시간을 나타내는 바를 추가합니다." +L["Adds a bar indicating how much time is left on your Rune of Power."] = "당신의 룬 마력에 얼마나 많은 시간이 남았는지를 나타내는 바를 추가합니다." +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = "피해가 흡수되는 양을 나타내는 바를 생명력 바 내부에 추가합니다." +L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."] = "누군가 받는 것으로 추정되는 치유량을 나타내는 바를 생명력 바 내부에 추가합니다." +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = "누군가 받을 치유량을 나타내는 바를 생명력 바 내부에 추가합니다." +L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."] = "흡수되어 플레이어에게 적용되지 않는 치유량을 나타내는 바를 생명력 바 내부에 추가합니다." +L["Adds a mana bar to the player frame for elemental and enhancement shamans."] = "정기 및 고양 주술사용 플레이어 창에 마나 바를 추가합니다." +L["Adds a mana bar to the player frame for shadow priests."] = "암흑 사제용 플레이어 창에 마나 바를 추가합니다." +L["Adds a Stagger bar for Brewmaster Monks."] = "양조 수도사용 시간차 바를 추가합니다." +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "다른 바를 정돈하는 한 방법으로 텍스트를 넣을 수 있는 빈 바를 추가합니다." +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "곰 또는 표범 폼인 경우 마나 보유량을 표시하는 다른 마나 바를 플레이어 창에 추가합니다." +L["Adds rune bars and timers before runes refresh to the player frame."] = "룬이 재충전되기 전까지 룬 바와 타이머를 플레이어 창에 추가합니다." +L["Adds temporary enchants to the buffs for the player."] = "일시 강화효과를 플레이어 버프에 추가합니다." +L["Adds totem bars with timers before they expire to the player frame."] = "토템이 사라지기 전까지 타이머 달린 토템 바를 플레이어 창에 추가합니다." +L["Advanced"] = "고급 옵션" +L["Advanced tag management, allows you to add your own custom tags."] = "고급 태그 관리로, 사용자 정의 태그를 추가하거나 수정할 수 있습니다." +L["AFK"] = "자리 비움" +L["AFK status"] = "자리 비움 상태" +L["AFK timer"] = "자리 비움 타이머" +L["AFK:%s"] = "자리 비움:%s" +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "내보내기를 누른 후, 다른 유저에게 설정을 보내줄 수 있으며, 보다 정확한 화면배치의 정보를 얻을 수 있을 것입니다." +L["Aggro"] = "어그로" +L["All aura groups enabled for unit."] = "모든 오라 그룹을 유닛에 대해 사용합니다." +L["All Auras"] = "모든 오라" +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."] = "오라 그룹을 다른 그룹에 부착할 수 있으며, 그런 다음 위치를 사용해 부착되는 곳을 고를 수 있습니다.|n|n버프와 디버프가 별도 그룹인 기본 UI 스타일을 복제하려면 이를 사용하세요." +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."] = "토템을 우클릭하여 해제할 수 있습니다.|n|n경고: 이 유닛의 내부 바는 이 옵션을 사용하면 전투 중 크기가 조정되지 않습니다." +L["Allows you to enter a new aura group."] = "새로운 오라 그룹을 입력할 수 있습니다." +L["Alpha to use for bar backgrounds."] = "바 배경에 사용할 투명도입니다." +L["Alpha to use for bar."] = "바에 사용할 투명도입니다." +L["Alt. Power"] = "대체 자원" +L["Alt. Power bar"] = "대체 자원 바" +L["Alternate power is used for things like quests and dungeons."] = "대체 자원은 퀘스트 및 던전과 같은 것에 사용됩니다." +L["Alternate Spell Name"] = "대체 주문 이름" +L["Alternatively friendly spell to use to check range."] = "사정거리를 확인하는 데 사용할 다른 우호 주문입니다." +L["Ammo"] = "탄약류" +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."] = "생명력 감소량으로, 없으면 아무것도 표시되지 않습니다. 짧은 형태를 사용해 -18500은 -18.5k로 10000 미만 값은 그대로 표시됩니다." +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."] = "자원 감소량으로, 없으면 아무것도 표시되지 않습니다. 짧은 형태를 사용해 -13850은 13.8k로 10000 미만 값은 그대로 표시됩니다." +L["Anchor point"] = "부착 지점" +L["Anchor to"] = "부착" +L["Anchor to another frame"] = "다른 창에 부착" +L["Anchor to buffs"] = "버프에 부착" +L["Anchor to debuffs"] = "디버프에 부착" +L["Ancient Kings bar"] = "고대 왕 바" +L["Any auras shown in this indicator will have their total stack displayed."] = "이 표시기에 보이는 모든 오라는 총 중첩 수를 표시합니다." +L["Aquatic"] = "바다표범" +L["Arcane Charges"] = "비전 충전물" +L["Are you sure you want to delete this aura?"] = "이 오라를 삭제할까요?" +L["Are you sure you want to delete this filter?"] = "이 필터를 삭제할까요?" +L["Are you sure you want to delete this indicator?"] = "이 표시기를 삭제할까요?" +L["Are you sure you want to delete this tag?"] = "이 태그를 삭제할까요?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "이 텍스트를 삭제할까요? 해당 설정이 모두 삭제됩니다." +L["Arena"] = "투기장" +L["Arena Pet"] = "투기장 소환수" +L["Arena Spec"] = "투기장 전문화" +L["Arena Target"] = "투기장 대상" +L["Arena Target of Target"] = "투기장 대상의 대상" +L["Arena ToT"] = "투기장 대상의 대상" +L["Arenas"] = "투기장" +L["Ascending"] = "오름차순" +L["Assigned Role (DPS/Tank/etc)"] = "할당된 역할 (딜/탱/기타)" +L["Astral Power"] = "천공의 힘" +L["Aura border style"] = "오라 테두리 스타일" +L["Aura borders"] = "오라 테두리" +L["Aura Combo Points"] = "오라 연계 점수" +L["Aura Filters"] = "오라 필터" +L["Aura filters"] = "오라 필터" +L["Aura group"] = "오라 그룹" +L["Aura groups"] = "오라 그룹" +L["Aura Groups"] = "오라 그룹" +L["Aura Indicators"] = "오라 표시기" +L["Aura indicators"] = "오라 표시기" +L["Aura name or spell ID"] = "오라 이름 또는 주문 ID" +L["Aura types to filter"] = "필터링할 오라 유형" +L["Auras"] = "오라" +L["Auras matching a criteria will automatically show up in the indicator when enabled."] = "기준과 일치하는 오라는 사용하는 경우 표시기에 자동으로 나타납니다." +L["Automatic Auras"] = "자동 오라" +L["B"] = "곰" +L["Background"] = "배경" +L["Background alpha"] = "배경 투명도" +L["Background color"] = "배경 색상" +L["Background/border"] = "배경/테두리" +L["Bag indicator for master looters."] = "전리품 담당자를 위한 가방 표시기입니다." +L["Bar alpha"] = "바 투명도" +L["Bar color to use to show how much healing someone is about to receive."] = "누군가 곧 받는 치유량을 표시하는 데 쓰이는 바 색상입니다." +L["Bar spacing"] = "바 간격" +L["Bar texture"] = "바 무늬" +L["Bars"] = "바" +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."] = "전체 크기 옵션보다 높거나 낮은 순위인 바는 유닛 창 너비 전체를 사용합니다.|n|n이 두 수 사이의 바 순위는 초상화 옆에 표시됩니다." +L["Battleground"] = "전장" +L["Battleground Pet"] = "전장 소환수" +L["Battleground Target"] = "전장 대상" +L["Battleground Target of Target"] = "전장 대상의 대상" +L["Battlegrounds"] = "전장" +L["Bear"] = "곰" +L["BG"] = "전장" +L["BG Pet"] = "전장 소환수" +L["BG Target"] = "전장 대상" +L["BG ToT"] = "전장 대상의 대상" +L["Blacklist"] = "차단목록" +L["Blacklist filters"] = "차단목록 필터" +L["Blacklists"] = "차단목록" +L["Blizzard"] = "블리자드 창" +L["Border"] = "테두리" +L["Border alpha"] = "테두리 투명도" +L["Border color"] = "테두리 색상" +L["Border coloring of stealable, curable and dispellable auras."] = "훔치기, 치유 및 해제 가능한 오라의 테두리 색상 지정입니다." +L["Border highlighting"] = "테두리 강조" +L["Border thickness"] = "테두리 두께" +L["Boss"] = "보스" +L["Boss Auras"] = "보스 오라" +L["Boss Debuffs"] = "보스 디버프" +L["Boss Target"] = "보스 대상" +L["Boss Target of Target"] = "보스 대상의 대상" +L["Boss ToT"] = "보스 대상의 대상" +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."] = "보스 유닛은 피의 공작 의회나 얼음왕관 비행포격선 전투와 같은 특정 전투용이며, 모든 보스전에서 보지는 못합니다." +L["Both"] = "둘 다" +L["Bottom"] = "하단" +L["Bottom Center"] = "하단 중앙" +L["Bottom Left"] = "하단 왼쪽" +L["Bottom Right"] = "하단 오른쪽" +L["buff frames"] = "버프 창" +L["Buffs"] = "버프" +L["C"] = "표" +L["Cannot find any profiles named \"%s\"."] = "이름이 \"%s\"인 프로필을 찾을 수 없습니다." +L["Cast"] = "시전" +L["Cast bar"] = "시전 바" +L["Cast icon"] = "주문 아이콘" +L["Cast interrupted"] = "시전 차단" +L["Cast name"] = "주문 이름" +L["Cast time"] = "시전 시간" +L["Cast uninterruptible"] = "시전 차단 불가" +L["Casting"] = "시전 중" +L["Cat"] = "표범" +L["Category"] = "부류" +L["Center"] = "중앙" +L["Changed profile to %s."] = "프로필을 %s|1으로;로; 바꿨습니다." +L["Changes the health bar to the color of any curable debuff."] = "생명력 바를 치유 가능한 디버프 색상으로 바꿉니다." +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = "유닛이 어그로를 획득한 경우 생명력 바를 설정된 적대 색상(기본값: 적색)으로 바꿉니다." +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."] = "이 위젯을 바 형태로 변경해, 생명력 및 자원 바처럼 높이와 순서를 바꿀 수 있습니다." +L["Channelling"] = "정신 집중" +L["Checking this will show the indciator on hostile units."] = "이를 체크하면 적대 유닛에 표시기를 나타냅니다." +L["Checking this will show the indicator on friendly units."] = "이를 체크하면 우호 유닛에 표시기를 나타냅니다." +L["Chi"] = "기" +L["Chi Points"] = "기 점수" +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = "하위 유닛은 드래그할 수 없으며, /suf를 통해 위치를 변경해야 합니다." +L["Class"] = "직업" +L["Class (Smart)"] = "직업 (스마트)" +L["Class color tag"] = "직업 색상 태그" +L["Class icon"] = "직업 아이콘" +L["Class Icon"] = "직업 아이콘" +L["Class icon for players."] = "플레이어의 직업 아이콘입니다." +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = "색상 지정 없는 직업 이름으로, 직업별 색상이 지정된 직업 이름을 원하는 경우 [classcolor][class][close] 를 사용하세요." +L["Class Role"] = "직업 역할" +L["Class Specific"] = "직업 전용" +L["Class Timer"] = "직업 타이머" +L["Class/misc bars"] = "직업/기타 바" +L["Classes"] = "직업" +L["Classification"] = "분류" +L["Classifications"] = "유닛 분류" +L["Clip"] = "테두리 간격" +L["Close color"] = "색상 닫기" +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = "색상 코드를 닫아, 해당 색상이 당신이 원하지 않는 텍스트에 나타나지 않게 합니다." +L["Code"] = "코드" +L["Color by class"] = "직업별 색상 지정" +L["Color by reaction on"] = "평판에 따른 색상 지정" +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."] = "유닛에 남은 백분율 생명력 기반 색상 코드로, 이는 생명력별 색상 지정 옵션과 같은 식으로 동작합니다. 하지만 전체 바 대신 텍스트 용입니다." +L["Color code for general situation"] = "일반 상황 색상 코드" +L["Color code for situation"] = "상황 색상 코드" +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = "직업 색상 코드로, 직업별 색상이 지정된 직업 텍스트를 원하는 경우 [classcolor][class][close] 를 사용하세요." +L["Color code on aggro"] = "어그로 획득 색상 코드" +L["Color health by"] = "생명력 색상 지정" +L["Color on aggro"] = "어그로에 색상 지정" +L["Color on curable debuff"] = "치유 가능 디버프에 색상 지정" +L["Color power by"] = "자원 색상 지정" +L["Color to use for health bars that are set to be colored by a static color."] = "고정 색상을 쓰도록 설정된 생명력 바에 사용할 색상입니다." +L["Color to use to show how much damage will be absorbed."] = "피해가 흡수되는 양을 보여주는 색상입니다." +L["Color to use to show how much healing will e absorbed."] = "치유가 흡수되는 양을 보여주는 색상입니다." +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = "시전이 차단 불가인 경우 사용되는 색상으로, 이는 오직 PvE 몹에만 사용됩니다." +L["Color used when a cast is a channel."] = "시전이 정신 집중인 경우 사용되는 색상입니다." +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "시전이 스스로 혹은 다른 유닛에 의해 차단된 경우 사용되는 색상입니다." +L["Color used when a cast is successfully finished."] = "시전을 성공적으로 끝마친 경우 사용되는 색상입니다." +L["Color used when an unit is casting a spell."] = "유닛이 주문을 시전 중인 경우 사용되는 색상입니다." +L["Colors"] = "색상" +L["Column growth"] = "열 확장" +L["Column spacing"] = "열 간격" +L["Combat alpha"] = "전투 중 투명도" +L["Combat fader"] = "투명도 조절기" +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."] = "투명도 조절기(Combat fader)는 활동하지 않는 동안 모든 창을 희미하게 하고 일단 전투 중이거나 활동 중일 때 다시 선명하게 합니다." +L["Combat Status"] = "전투 상태" +L["Combat text"] = "전투 메세지" +L["Combat/resting status"] = "전투/휴식 상태" +L["Combo points"] = "연계 점수" +L["Combo Points"] = "연계 점수" +L["Configuration to specific unit frames."] = "특정 유닛 창의 구성입니다." +L["Cooldown rings for"] = "재사용 대기시간 링" +L["Create"] = "만들기" +L["Creature type"] = "생물체 유형" +L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."] = "생물체 유형으로, 유닛이 지옥수호병일 경우 지옥수호병, 늑대면 늑대 등을 반환합니다." +L["Crown indicator for group leader or assistants."] = "파티(/공격대)장이나 부공격대장을 위한 왕관 표시기입니다." +L["Cur/Max HP (Absolute)"] = "현재/최대 생명력 (절댓값)" +L["Cur/Max HP (Short)"] = "현재/최대 생명력 (짧게)" +L["Cur/Max HP (Smart)"] = "현재/최대 생명력 (스마트)" +L["Cur/Max power (Absolute)"] = "현재/최대 자원 (절댓값)" +L["Cur/Max power (Druid)"] = "현재/최대 자원 (드루이드)" +L["Cur/Max power (Druid/Absolute)"] = "현재/최대 자원 (드루이드/절댓값)" +L["Cur/Max power (Secondary)"] = "현재/최대 자원 (2차)" +L["Cur/Max power (Secondary/Absolute)"] = "현재/최대 자원 (2차/절댓값)" +L["Cur/Max Power (Short)"] = "현재/최대 자원 (짧게)" +L["Cur/Max PP (Smart)"] = "현재/최대 PP (스마트)" +L["Curable"] = "치유 가능" +L["Curable Auras"] = "치유 가능 오라" +L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."] = "현재 및 최대 생명력을 [curhp]/[maxhp] 형태로 사용해, 유닛이 죽거나 오프라인인 경우 대신 표시됩니다." +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "현재 및 최대 자원을 [curpp]/[maxpp] 형태로 사용합니다." +L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."] = "현재 생명력을 짧은 형태를 사용해, 10000 미만 값은 그대로 두고 11500은 11.5k로 표시합니다." +L["Current HP (Absolute)"] = "현재 생명력 (절댓값)" +L["Current HP (Short)"] = "현재 생명력 (짧게)" +L["Current pet used by a battleground unit."] = "현재 전장 유닛이 사용하는 소환수입니다." +L["Current power (Absolute)"] = "현재 자원 (절댓값)" +L["Current power (Druid)"] = "현재 자원 (드루이드)" +L["Current power (Druid/Absolute)"] = "현재 자원 (드루이드/절댓값)" +L["Current power (Secondary)"] = "현재 자원 (2차)" +L["Current power (Secondary/Absolute)"] = "현재 자원 (2차/절댓값)" +L["Current Power (Short)"] = "현재 자원 (짧게)" +L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."] = "현재 자원을 짧은 형태를 사용해, 12750은 12.7k로 10000 미만 값은 그대로 표시됩니다." +L["Current target of a battleground unit."] = "전장 유닛의 현재 대상입니다." +L["Current target of target of a battleground unit."] = "전장 유닛의 현재 대상의 대상입니다." +L["Currently modifying"] = "현재 수정 중" +L["Currently used in battlegrounds for showing flag carriers."] = "현재 깃발 운반수를 표시하기 위해 전장에서 사용됩니다." +L["Damage absorption (Absolute)"] = "피해 흡수량 (절댓값)" +L["Damage absorption (Short)"] = "피해 흡수량 (짧게)" +L["Damage absorption/Name"] = "피해 흡수량/이름" +L["Dark"] = "어둡게" +L["Dead"] = "죽음" +L["Debuffs"] = "디버프" +L["Decimal percent HP"] = "소수 백분율 생명력" +L["Default color"] = "기본 색상" +L["Default font color, any color tags inside individual tag texts will override this."] = "기본 글꼴 색상으로, 개별 태그 텍스트 내부의 모든 색상 태그는 이를 재정의합니다." +L["Deficit/Unit Name"] = "손실/유닛 이름" +L["Delete"] = "삭제" +L["Delete filter"] = "필터 삭제" +L["Delete link"] = "링크 삭제" +L["Descending"] = "내림차순" +L["Disable Auras by Class"] = "직업별 오라 사용 중지" +L["Disable Blizzard Cooldown Count"] = "블리자드 재사용 대기시간 카운트 사용 안 함" +L["Disable event discovery"] = "이벤트 발견 사용 안 함" +L["Disable OmniCC Cooldown Count"] = "OmniCC 재사용 대기시간 카운트 사용 안 함" +L["Disable vehicle swap"] = "차량 전환 사용 안 함" +L["Disabled"] = "비활성(끔)" +L["Disabled for %s."] = "%s 유닛에 사용하지 않습니다." +L["Disabled in %s"] = "%s 비활성(꺼짐)." +L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."] = "모든 SUF 오라에 재사용 대기시간 카운트 타이머를 표시하지 않습니다." +L["Disables the unit frame from turning into a vehicle when the player enters one."] = "플레이어가 차량을 탄 경우 유닛 창이 차량으로 바뀌지 않도록 합니다." +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!."] = "이 페이지에서 모듈 사용을 중지하면 %s 내부에서 이를 사용할 수 없습니다. 이 일이 일어나길 바라지 않으면 여기에서 모듈을 중지하지 마세요!" +L["Disabling unit modules in various instances."] = "특정 던전 혹은 지역에서 사용하거나 혹은 사용하지 않을 모듈 설정" +L["Dismissable Totem bars"] = "소환 해제 가능 토템 바" +L["Dispellable/Stealable"] = "해제 가능/훔치기 가능" +L["Display"] = "표시" +L["Display enemy buffs using LibClassicDuration data."] = "적 버프를 LibClassicDuration 데이터를 사용하여 표시합니다." +L["DND"] = "다른 용무 중" +L["DND:%s"] = "다른 용무 중:%s" +L["Documentation"] = "문서" +L["Don't hide when empty"] = "빈 경우에 숨기지 않음" +L["Don't use a filter"] = "필터를 사용하지 않습니다." +L["Down"] = "아래" +L["Druid form"] = "드루이드 폼" +L["Druid form (Short)"] = "드루이드 폼 (짧게)" +L["Druid mana bar"] = "드루이드 마나 바" +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."] = "가짜 유닛의 특성상, %s용 시전 바는 매우 효율이 낮고 시전 변화를 알아차리는데 최대 0.10초가 걸릴 수 있습니다." +L["Edge size"] = "테두리 크기" +L["Edit tag"] = "태그 편집" +L["Editing %s"] = "%s 수정" +L["Elite"] = "정예" +L["Empty bar"] = "빈 바" +L["Enable %s"] = "%s 사용" +L["Enable buffs"] = "버프 사용" +L["Enable debuffs"] = "디버프 사용" +L["Enable enemy buff tracking"] = "적 버프 추적 사용" +L["Enable for friendlies"] = "아군에게 사용" +L["Enable for hostiles"] = "적에게 사용" +L["Enable frequent updates"] = "잦은 업데이트 사용" +L["Enable indicator"] = "표시기 사용" +L["Enable Indicators"] = "표시기 사용" +L["Enable temporary enchants"] = "일시 강화효과 사용" +L["Enable units"] = "유닛 사용" +L["Enabled for %s."] = "%s 유닛에 사용합니다." +L["Enabled in %s"] = "%s 안에서 사용" +L["Enabled Units"] = "사용 유닛" +L["Enables configuration mode, letting you move and giving you example frames to setup."] = "설정을 위해 예제 창을 제공하며 이를 이동할 수 있는 구성 모드를 사용합니다." +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."] = "고급 설정 사용은 더 많은 구성 옵션에 접근할 수 있습니다. 이는 모든 옵션을 조정하고 싶은 이에게 적합하며 옵션이 늘어나기에 기본으로 체크하지는 마세요." +L["Energy"] = "기력" +L["Enlarge auras for"] = "오라 확대" +L["Error"] = "오류" +L["Essence"] = "정수" +L["Events"] = "이벤트" +L["Events that should be used to trigger an update of this tag. Separate each event with a single space."] = "이 태그의 갱신을 일으키기 위해 사용되어야 하는 이벤트입니다. 각 이벤트는 공백 하나로 구분하세요." +L["Everywhere else"] = "다른 모든 곳" +L["Export"] = "내보내기" +L["F"] = "날" +L["Fades out the unit frames of people who are not within range of you."] = "사정거리 안에 없는 대상의 유닛 창은 희미해집니다." +L["Failed to import layout, error:|n|n%s"] = "화면배치를 가져오는 데 실패했습니다. 오류:|n|n%s" +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "ShadowedUF_Options 로딩에 실패해, 구성을 열 수가 없습니다. 반환된 오류: %s" +L["Failed to save tag, error:|n %s"] = "태그 저장 실패, 오류:|n %s" +L["Female"] = "여성" +L["Filter type"] = "필터 유형" +L["Filtering both buffs and debuffs"] = "버프와 디버프를 함께 필터링" +L["Filtering buffs only"] = "버프만 필터링" +L["Filtering debuffs only"] = "디버프만 필터링" +L["Filters"] = "필터" +L["Finished cast"] = "시전 종료" +L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."] = "잦은 업데이트를 위한 태그를 달아, 발생하는 이벤트와 상관없이 타이머의 태그를 갱신합니다." +L["Flight"] = "날쌘 동물" +L["Flips coloring so the bar color is shown as the background color and the background as the bar"] = "바 색상은 배경 색상으로 배경 색상은 바 색상으로 표시되도록 색상 지정을 뒤집습니다." +L["Focus"] = "주시 대상" +L["Focus Target"] = "주시 대상의 대상" +L["Font"] = "글꼴" +L["Food"] = "음식" +L["For configuring aura indicators on unit frames."] = "유닛 창에 오라 표시기를 구성하는 용도입니다." +L["For target/focus"] = "대상/주시 대상" +L["Forces a static color to be used for the background of all bars"] = "해당 색상을 모든 바의 배경에 사용하도록 강제합니다." +L["Frame"] = "창" +L["Frame alpha when you are out of combat while having no target and 100% mana or energy."] = "대상이 없고 마나나 기력이 100%이면서 비전투 중인 경우 창 투명도입니다." +L["Frame alpha while this unit is in combat."] = "이 유닛이 전투 중일 때 창 투명도입니다." +L["Frames"] = "창" +L["Friendly"] = "우호" +L["Fuel"] = "연료" +L["Full size after"] = "전체 크기 이후" +L["Full size before"] = "전체 크기 이전" +L["Fury"] = "분노" +L["General"] = "일반" +L["General configuration to all enabled units."] = "사용하는 모든 유닛의 일반 설정입니다." +L["General threat situation"] = "일반 위협 수준 상황" +L["Ghost"] = "유령" +L["Ghoul bar"] = "구울 바" +L["Global"] = "공통" +L["Global configurating will let you mass enable or disable aura groups for multiple units at once."] = "공통 구성은 한 번에 여러 유닛에 대해 오라 그룹을 대량으로 사용 또는 사용 중지할 수 있습니다." +L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"] = "노란 체크 표시 - 이 지역에서 사용 / 회색 체크 표시 - 이 지역에서 사용 안 함 / 체크 표시 없음 - 기본 유닛 설정 사용" +L["Green (<30% HP)"] = "녹색 (HP 30% 미만)" +L["Group %d"] = "%d 파티" +L["Group by"] = "분류 기준" +L["Group number"] = "파티 번호" +L["Group row spacing"] = "파티 행 간격" +L["Groups"] = "파티" +L["Groups per row"] = "행당 파티" +L["Groups to show"] = "표시할 파티" +L["Growth"] = "확장" +L["Guild name"] = "길드 이름" +L["Half health"] = "중간 생명력" +L["Has Aggro"] = "어그로 획득" +L["Heal absorb"] = "치유 흡수량" +L["Heal Absorb (Absolute)"] = "치유 흡수량 (절댓값)" +L["Heal Absorb (Short)"] = "치유 흡수량 (짧게)" +L["Heal absorbs"] = "치유 흡수량" +L["Healing absorb"] = "치유 흡수량" +L["Health"] = "생명력" +L["Health bar"] = "생명력 바" +L["Health bar color for friendly units."] = "우호 유닛의 생명력 바 색상입니다." +L["Health bar color for hostile units."] = "적대 유닛의 생명력 바 색상입니다." +L["Health bar color for neutral units."] = "중립 유닛의 생명력 바 색상입니다." +L["Health bar color for units with aggro."] = "어그로를 획득한 유닛의 생명력 바 색상입니다." +L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."] = "공격할 수 없는 적대 유닛에 사용하는 생명력 바 색상으로, 평판 색상 지정에 쓰입니다." +L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."] = "체력이 100% -> 0%로 이동되는 동안 사용되는 바 색상, 또한 당신의 소환수가 불행함을 느낄 때 사용됩니다." +L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."] = "체력이 100% -> 50%까지 일 경우에 사용되는 바 색상, 또한 당신의 소환수가 행복할 때 사용됩니다." +L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."] = "체력이 50% -> 0%까지 이동되는 동안 사용되는 바 색상, 또한 당신의 소환수가 매우 불행함을 느낄 때 사용됩니다." +L["Health color"] = "생명력 색상" +L["Health percent"] = "생명력 백분율" +L["Height"] = "높이" +L["Help"] = "도움말" +L["Hide %s"] = "%s 숨김" +L["Hide %s frames"] = "%s 창 숨김" +L["Hide bar when empty"] = "빈 경우에 바 숨김" +L["Hide Blizzard"] = "블리자드 창 숨기기" +L["Hide in <=5-man raids"] = "5인 이하 공격대에서 숨김" +L["Hide in >5-man raids"] = "5인 초과 공격대에서 숨김" +L["Hide in any raid"] = "모든 공격대에서 숨김" +L["Hide tooltips in combat"] = "전투 중 툴팁 숨김" +L["Hides the cast bar if there is no cast active."] = "만약 시전 중이 아닐 경우 시전 바를 숨깁니다." +L["Hides the power bar unless the class has mana."] = "마나 있는 직업 이외에는 자원 바를 숨깁니다." +L["Hiding and showing various aspects of the default UI such as the player buff frames."] = "플레이어 버프 창과 같은 다양한 모양의 블리자드 기본 UI를 숨기거나 표시합니다." +L["High"] = "높음" +L["High health"] = "높은 생명력" +L["Highlight"] = "강조" +L["Highlight units that are "] = "정예 유닛을 강조합니다." +L["Highlight units that are debuffed with something you can cure."] = "당신이 치유 가능한 디버프에 걸린 유닛을 강조합니다." +L["Highlight units that are rare."] = "희귀 유닛을 강조합니다." +L["Highlight units that have aggro on any mob."] = "몹에 어그로를 획득한 유닛을 강조합니다." +L["Highlight units that you are targeting or have focused."] = "대상이거나 주시 대상으로 설정한 유닛을 강조합니다." +L["Highlight units when you mouse over them."] = "마우스를 올리면 유닛을 강조합니다." +L["Holy power"] = "신성한 힘" +L["Holy Power"] = "신성한 힘" +L["Hostile"] = "적대" +L["How close the frame should clip with the border."] = "창과 테두리 사이의 간격입니다." +L["How far the background should be from the unit frame border."] = "유닛 창 테두리와 삽입하는 배경 사이의 간격입니다." +L["How large the background should tile"] = "배경 타일의 크기를 조정합니다." +L["How large the edges should be."] = "테두리 크기를 조정합니다." +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."] = "행당 오라의 개수로 예를 들어, 2를 입력하면 한 열당 개수에 설정된 값으로 채워지는 두 열이 생성됩니다." +L["How many auras to show in a single row."] = "한 줄에 표시할 오라 개수입니다." +L["How many Chi points you currently have."] = "현재 갖고 있는 기 점수입니다." +L["How many groups should be shown per row."] = "행당 표시되는 파티 수입니다." +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!"] = "유닛을 지원 중인 사람 수로, 예를 들어 이를 자신에게 쓰면 당신의 대상을 선택한 사람 수를 표시합니다. 이 계산에는 당신을 포함합니다!" +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!"] = "유닛을 대상으로 선택 중인 사람 수로, 예를 들어 이를 자신에게 쓰면 당신을 대상으로 선택 중인 사람 수를 표시합니다. 이 계산에는 당신을 포함합니다!" +L["How many rows total should be used, rows will be however long the per row value is set at."] = "사용돼야 할 총 행 수, 하지만 행 길이는 한 행당 개수에 설정된 값입니다." +L["How many seconds a totem has left before disappearing."] = "토템이 사라지기까지 남은 시간(초)입니다." +L["How many seconds before a rune recharges."] = "룬이 재충전되기 전까지 남은 시간(초)입니다." +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."] = "업데이트 간격(초)입니다.|n[경고] 빈도를 0으로 설정하면 단일 프레임 다시 그리기마다 갱신하므로, 잦은 업데이트를 사용하지 않으려면 이를 선택 해제하고 0으로 설정하지 마세요." +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."] = "이 바가 지녀야 할 창의 총 높이로 이는 가중치이며 클수록 더 높습니다." +L["How much spacing should be between each new row of groups."] = "각 새로운 파티 행 사이 간격입니다." +L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."] = "유닛 창 내부 모든 바 사이에 두어야 하는 간격입니다. 음수 값은 더 멀리 떨어뜨리고, 양수 값은 더 가깝게 가져옵니다. 0은 사이 간격이 없습니다." +L["How much weight this should use when figuring out the total text width."] = "이는 전체 텍스트 너비를 계산할 때 사용해야 하는 가중치입니다." +L["How the frames should grow when a new column is added."] = "새로운 열이 추가될 때 창을 확장하는 방법입니다." +L["How the rows should grow when new group members are added."] = "새로운 구성원이 추가될 때 행을 확장하는 방법입니다." +L["How you want this aura to be anchored to the unit frame."] = "이 오라를 유닛 창에 부착시키고 싶은 위치입니다." +L["Icon Size"] = "아이콘 크기" +L["If multiple auras are shown in the same indicator, the higher priority one is shown first."] = "여러 오라가 같은 표시기에 보이는 경우, 우선순위가 더 높은 오라가 먼저 표시됩니다." +L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."] = "이름을 입력하는 경우, 대소문자를 구별해야 합니다. 아니면 대신에 주문 id를 사용할 수 있습니다." +L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."] = "유닛에 피해 흡수 보호막이 있는 경우, 흡수량 절댓값을 그 이외에는 유닛 이름을 표시합니다." +L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."] = "유닛이 치유를 받는 경우, 시전 중 치유량 절댓값을 보이고 그 이외에는 유닛 이름을 표시합니다." +L["If the unit is a player then class is returned, if it's a NPC then the creature type."] = "유닛이 플레이어라면 직업이, NPC라면 생물체 유형이 반환됩니다." +L["If the unit is a player then race is returned, if it's a NPC then the creature type."] = "유닛이 플레이어라면 종족이, NPC라면 생물체 유형이 반환됩니다." +L["Imp & Dreadstalker bar"] = "임프 & 지옥사냥개 바" +L["Import"] = "가져오기" +L["Import unit frame positions"] = "유닛 창 위치 가져오기" +L["Import visibility settings"] = "창 보임 설정 가져오기" +L["In range alpha"] = "사정거리 안 투명도" +L["Inactive alpha"] = "비활동 투명도" +L["Incoming absorb"] = "피해 흡수량" +L["Incoming absorbs"] = "피해 흡수량" +L["Incoming heal"] = "시전 중 치유량" +L["Incoming heal (Absolute)"] = "시전 중 치유량 (절댓값)" +L["Incoming heal (Percent)"] = "시전 중 치유량 (백분율)" +L["Incoming heal (Short)"] = "시전 중 치유량 (짧게)" +L["Incoming heal/Name"] = "시전 중 치유량/이름" +L["Incoming heals"] = "시전 중 치유량" +L["Index"] = "색인" +L["Indicator color"] = "표시기 색상" +L["Indicator for the current pet happiness."] = "현재 야수의 포만감 표시기입니다." +L["Indicator name"] = "표시기 이름" +L["Indicator this aura should be displayed in."] = "이 오라가 표시되어야 하는 표시기입니다." +L["Indicators"] = "표시기" +L["Insanity"] = "광기" +L["Inset"] = "삽입" +L["Inside Bottom Left"] = "내부 - 좌하단" +L["Inside Bottom Right"] = "내부 - 우하단" +L["Inside Center"] = "내부 - 중앙" +L["Inside Center Left"] = "내부 - 좌중앙" +L["Inside Center Right"] = "내부 - 우중앙" +L["Inside Top Left"] = "내부 - 좌상단" +L["Inside Top Right"] = "내부 - 우상단" +L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."] = "표시기 안에 단색을 표시하는 대신 오라 아이콘이 표시됩니다." +L["Interrupted"] = "차단(방해)" +L["Invalid interval entered, must be a number."] = "잘못된 간격을 입력했습니다. 숫자여야 합니다." +L["Invalid spell \"%s\" entered."] = "인식불가능한 주문 \"%s\"이 들어있습니다." +L["Invert colors"] = "색상 반전" +L["Layout manager"] = "화면배치 관리기" +L["Leader / Assist"] = "파티(/공격대)장 / 부공격대장" +L["Left"] = "왼쪽" +L["Left Bottom"] = "왼쪽 하단" +L["Left Center"] = "왼쪽 중앙" +L["Left text"] = "왼쪽 텍스트" +L["Left Top"] = "왼쪽 상단" +L["Let's you modify the base font size to either make it larger or smaller."] = "기본 글꼴 크기를 수정하여 크거나 작게 만듭니다." +L["Level"] = "레벨" +L["Level %s - %s: %s/%s (%.2f%% done)"] = "레벨 %s - %s: %s/%s (현재 %.2f%%)" +L["Level %s - %s: %s/%s (%.2f%% done), %s rested."] = "레벨 %s - %s: %s/%s (현재 %.2f%%), 휴식경험치 %s." +L["Level (Colored)"] = "레벨 (색상)" +L["Level without any coloring."] = "어떤 색상 지정도 없는 레벨입니다." +L["Light"] = "밝게" +L["Link"] = "링크" +L["Linked spells"] = "링크된 주문" +L["Lock frames"] = "창 잠금" +L["Locks the unit frame positionings hiding the mover boxes."] = "창 이동 상자를 감추고 유닛 창 위치를 잠급니다." +L["Low health"] = "낮은 생명력" +L["M"] = "달" +L["MA ToT"] = "메인 지원 대상의 대상" +L["Maelstrom"] = "소용돌이" +L["Main Assist"] = "지원공격 전담" +L["Main Assist Target"] = "지원공격 전담 대상" +L["Main Assist Target of Target"] = "지원공격 전담 대상의 대상" +L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."] = "지원공격 전담은 블리자드 지원공격 전담 시스템이나 이를 사용하는 애드온에 의해 설정됩니다." +L["Main Tank"] = "방어 전담" +L["Main Tank Target"] = "방어 전담 대상" +L["Main Tank Target of Target"] = "방어 전담 대상의 대상" +L["Main Tank's are set through the Raid frames, or through selecting the Tank role."] = "방어 전담은 공격대 창이나 방어 역할 선택을 통하여 설정됩니다." +L["Male"] = "남성" +L["Mana"] = "마나" +L["Manage Aura Filters"] = "오라 필터 관리" +L["Management"] = "관리" +L["Manual position"] = "수동 위치" +L["Master Looter"] = "전리품 담당자" +L["Max columns"] = "최대 열 수" +L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."] = "최대 생명력을 짧은 형태를 사용해, 17750은 17.7k로 10000 미만 값은 그대로 표시됩니다." +L["Max HP (Absolute)"] = "최대 생명력 (절댓값)" +L["Max HP (Short)"] = "최대 생명력 (짧게)" +L["Max power (Absolute)"] = "최대 자원 (절댓값)" +L["Max power (Short)"] = "최대 자원 (짧게)" +L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."] = "최대 자원을 짧은 형태를 사용해, 16000은 16k로 10000 미만 값은 그대로 표시됩니다." +L["Max rows"] = "최대 행 수" +L["Medium"] = "중간" +L["Minion"] = "하수인" +L["Miscellaneous"] = "기타" +L["Missing HP (Short)"] = "감소 생명력 (짧게)" +L["Missing power (Short)"] = "감소 자원 (짧게)" +L["Monochrome Outline"] = "흑백 외곽선" +L["Moonkin"] = "달빛야수" +L["MT ToT"] = "메인 탱커 대상의 대상" +L["Mushroom bar"] = "버섯 바" +L["Mushrooms"] = "버섯" +L["Name"] = "이름" +L["Name (Abbreviated)"] = "이름 (약식)" +L["Name of a friendly spell to check range."] = "사정거리를 확인하는 우호 주문의 이름입니다." +L["Neutral"] = "중립" +L["Never (Disabled)"] = "절대 (사용 안 함)" +L["New aura group"] = "새로운 오라 그룹" +L["New filter"] = "새로운 필터" +L["None"] = "없음" +L["None (Disabled)"] = "없음 (사용 안 함)" +L["NPCs only"] = "NPC만" +L["Off:%s"] = "접속 종료:%s" +L["Offline"] = "접속 종료" +L["Offline timer"] = "오프라인 타이머" +L["Ok"] = "확인" +L["On %s units"] = "%s 유닛에" +L["On aggro"] = "어그로 획득" +L["On curable debuff"] = "치유 가능 디버프" +L["On elite mobs"] = "정예 몹에" +L["On Friendly Units"] = "우호 유닛에" +L["On Hostile Units"] = "적대 유닛에" +L["On mouseover"] = "마우스 오버 시" +L["On rare mobs"] = "희귀 몹에" +L["Only active this aura inside an indicator if the group member does not have the aura."] = "파티원이 오라가 없는 경우 표시기 안에 이 오라만 활성화합니다." +L["Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras."] = "선택한 필터를 우호 유닛의 버프와 적대 유닛의 디버프에만 적용하고 그 외에는 모든 오라를 표시합니다." +L["Only auras you specifically cast will be shown."] = "확실히 자기가 시전한 오라만 표시됩니다." +L["Only show if missing"] = "사라진 경우에만 표시" +L["Only show self cast auras"] = "자기 시전 오라만 표시" +L["Only show when mana"] = "마나인 경우만 표시" +L["Or you can set a position manually"] = "또는 직접 위치 설정 가능" +L["Order"] = "순위" +L["Other Party/Phase Status"] = "다른 파티/위상 상태" +L["Out of range alpha"] = "사정거리 밖 투명도" +L["Outline"] = "외곽선" +L["Outside bar limit"] = "바 외곽 한계" +L["Override background"] = "배경 재정의" +L["Override color"] = "색상 재정의" +L["Override list"] = "재정의 목록" +L["Override list filters"] = "재정의 목록 필터" +L["Override lists"] = "재정의 목록" +L["Pain"] = "고통" +L["Party"] = "파티" +L["Party frames are hidden while in a raid group with more than 5 people inside."] = "파티 창을 5인이 넘는 공격대에 있는 동안 숨깁니다." +L["Party frames are hidden while in any sort of raid no matter how many people."] = "파티 창을 인원수와 상관없이 공격대에 있는 동안 숨깁니다." +L["Party instances"] = "파티 던전" +L["Party Pet"] = "파티 소환수" +L["Party Target"] = "파티 대상" +L["Party Target of Target"] = "파티 대상의 대상" +L["Party ToT"] = "파티 대상의 대상" +L["Per column"] = "한 열당 개수" +L["Per row"] = "한 행당 개수" +L["Percent HP"] = "백분율 생명력" +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."] = "치유 중인 플레이어의 현재 백분율 생명력으로 총 생명력이 100,000이고 15,000이 들어오는 경우 15%가 표시됩니다." +L["Percent power"] = "백분율 자원" +L["Percentage of width the portrait should use."] = "초상화가 사용해야 하는 너비의 백분율입니다." +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."] = "치유 흡수량 바가 유닛 창밖으로 나갈 수 있는 양을 나타내는 백분율 값입니다. 130%는 창밖으로 30% 나가고, 100%는 밖으로 나가지 않음을 뜻합니다." +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."] = "피해 흡수량 바가 유닛 창밖으로 나갈 수 있는 양을 나타내는 백분율 값입니다. 130%는 창밖으로 30% 나가고, 100%는 밖으로 나가지 않음을 뜻합니다." +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."] = "시전 중 치유량 바가 유닛 창밖으로 나갈 수 있는 양을 나타내는 백분율 값입니다. 130%는 창밖으로 30% 나가고, 100%는 밖으로 나가지 않음을 뜻합니다." +L["Pet"] = "소환수" +L["Pet Battle"] = "애완동물 대전" +L["Pet Happiness"] = "야수 포만감" +L["Pet Target"] = "소환수 대상" +L["Player"] = "플레이어" +L["player alt. power"] = "플레이어 대체 자원" +L["player cast bar"] = "플레이어 시전 바" +L["Player Class"] = "플레이어 직업" +L["player power frames"] = "플레이어 자원 창" +L["Player threat"] = "플레이어 위협 수준" +L["Players only"] = "플레이어만" +L["Players will be colored by class."] = "플레이어는 직업별로 색상 지정됩니다." +L["Point"] = "지점" +L["Portrait"] = "초상화" +L["Portrait type"] = "초상화 유형" +L["Position"] = "위치" +L["Positioning"] = "위치 지정" +L["Power"] = "자원" +L["Power bar"] = "자원 바" +L["Power Type"] = "자원 유형" +L["Prevents unit tooltips from showing while in combat."] = "전투 중에 유닛 툴팁이 표시되지 않도록 합니다." +L["Priest mana bar"] = "사제 마나 바" +L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."] = "생명력 바 색상, 어그로 획득 색상, 평판에 따른 색상 지정의 주요 수단으로 필요한 경우 이를 재정의합니다." +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."] = "자원 바 색상 지정의 주요 수단입니다. 직업별 색상 지정은 플레이어에만 적용되고 플레이어가 아닌 경우 자원 유형이 기본값입니다." +L["Prioritize buffs"] = "버프 우선시함" +L["Priority"] = "우선순위" +L["Programming in Lua"] = "Programming in Lua" +L["PvP Flag"] = "PvP 깃발" +L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."] = "PvP 깃발 표시기입니다." +L["PvP Flags"] = "PvP 깃발" +L["PVP timer"] = "PvP 타이머" +L["PVP:%s"] = "PvP:%s" +L["Quest Boss"] = "퀘스트 보스" +L["Race"] = "종족" +L["Race (Smart)"] = "종족 (스마트)" +L["Rage"] = "분노" +L["Raid"] = "공격대" +L["Raid assisting unit"] = "공격대 지원 유닛" +L["Raid frames are hidden while in a raid group with 5 or less people inside."] = "공격대 창을 5인 이하가 속한 공격대에 있는 동안 숨깁니다." +L["Raid instances"] = "공격대 던전" +L["Raid Misc"] = "공격대 기타" +L["Raid pet"] = "공격대 소환수" +L["Raid Role"] = "공격대 역할" +L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."] = "공격대 역할 표시기로 방어 전담은 방패 모양, 지원공격 전담은 칼 모양입니다." +L["Raid Target"] = "공격대 대상" +L["Raid target indicator."] = "공격대 대상 표시기입니다." +L["Raid targeting unit"] = "공격대 대상 유닛" +L["Range Checker"] = "사정거리 확인기" +L["Range indicator"] = "사정거리 표시기" +L["Rare"] = "희귀" +L["Rare Elite"] = "희귀 정예" +L["Rare indicator"] = "희귀 표시기" +L["Rather than bars filling from left -> right, they will fill from bottom -> top."] = "바를 좌에서 우로 채우기보다는, 밑에서 위로 채웁니다." +L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."] = "평판 색상 코드로, 평판에 따라 유닛 이름에 색상을 지정하려면 [reactcolor][name][close] 를 사용하세요." +L["Reaction color tag"] = "평판 색상 태그" +L["Ready Status"] = "전투 준비 상황" +L["Ready status of group members."] = "파티원의 전투 준비 상황입니다." +L["Red (>70% HP)"] = "적색 (HP 70% 초과)" +L["Relative point"] = "상대 지점" +L["Resources"] = "참고자료" +L["Resurrect Status"] = "부활 상태" +L["Returns + if the unit is an elite or rare elite mob."] = "유닛이 정예나 희귀 정예 몹인 경우 +를 반환합니다." +L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."] = "대상에 갖는 위협 수준 상황(어그로에 적색, 높은 위협 수준에 주황색, 주의에 노란색)에 따른 색상 코드를 반환합니다." +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."] = "모든 유닛에 대한 일반 위협 수준 상황의 색상 코드(어그로에 적색, 높은 위협 수준에 주황색, 주의는 황색)를 반환합니다." +L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."] = "현재 대상에 대한 위협 수준 백분율 비율을 반환하며, 항상 0 - 100%입니다." +L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."] = "현재 생명력을 백분율로 반환하며 유닛이 죽거나 오프라인인 경우 대신 표시됩니다." +L["Returns current power as a percentage."] = "현재 자원을 백분율로 반환합니다." +L["Returns Rare if the unit is a rare or rare elite mob."] = "유닛이 희귀나 희귀 정예 몹인 경우 희귀를 반환합니다." +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."] = "유닛의 일반 위협 수준 상황에 따른 텍스트(어그로에 Aggro, 어그로 획득에 가까우면 High, 주의하라는 경고로 Medium)를 반환합니다.|n이는 대상의 대상 또는 주시 대상 유형의 유닛에는 사용될 수 없습니다." +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."] = "모든 유닛에 대한 일반 위협 수준 상황에 따른 텍스트(어그로엔 Aggro, 어그로 획득에 가까우면 High, 일반 경고로 Medium)를 반환합니다." +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."] = "대상에 갖는 위협 수준 상황에 따른 텍스트(어그로엔 Aggro, 어그로 획득에 가까우면 High, 주의하라는 일반 경고로 Medium)를 반환합니다." +L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."] = "자신과 비교한 유닛 레벨을 기반으로 한 색상 코드를 반환합니다. 공격할 수 없다면 어떤 색상도 반환되지 않습니다." +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."] = "대체로 유닛의 위협 수준 상황(어그로에 적색, 높은 위협 수준은 주황색, 주의 수준은 노란색)에 따른 색상 코드를 반환합니다.|n이는 대상의 대상 또는 주시 대상 유형의 유닛에는 사용될 수 없습니다." +L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."] = "유닛이 드루이드인 경우 표범은 Cat, 달빛야수는 Moonkin 등 유닛의 현재 폼을 반환합니다." +L["Returns the units sex."] = "유닛의 성별을 반환합니다." +L["Reverse fill"] = "반대로 채움" +L["Right"] = "오른쪽" +L["Right Bottom"] = "오른쪽 하단" +L["Right Center"] = "오른쪽 중앙" +L["Right text"] = "오른쪽 텍스트" +L["Right Top"] = "오른쪽 상단" +L["Role the unit is playing."] = "유닛이 플레이 중인 역할입니다." +L["Row growth"] = "행 확장" +L["Row offset"] = "행 간격" +L["Rune bar"] = "룬 바" +L["Rune of Power"] = "룬 마력" +L["Rune of Power bar"] = "마력의 룬 바" +L["Rune Timer"] = "룬 타이머" +L["Runes"] = "룬" +L["Runic Power"] = "룬 마력" +L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."] = "노란색 -> 주황색 -> 적색으로 바뀌기보다는 어그로가 있는 경우에만 적색을 반환하는 것만 빼면 [color:sit]과 같습니다." +L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."] = "노란색 -> 주황색 -> 적색으로 바뀌기보다는 유닛에 어그로가 있는 경우에만 적색을 반환하는 것만 빼면 [unit:color:sit]와 같습니다." +L["Scale"] = "크기 비율" +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."] = "마법을 훔칠 수 있거나 시전한 오라의 크기 비율로, 100% 이상은 기본값보다 크고 100% 이하는 작습니다." +L["Scaled aura size"] = "오라 크기 비율" +L["Scaled threat percent"] = "위협 수준 백분율 비율" +L["Screen"] = "화면" +L["Search"] = "검색" +L["Search tags"] = "태그 검색" +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."] = "태그 생성 정보와 예제는 아래 문서를, 그냥 Lua 기초나 WoW API 정보를 원한다면 Programming in Lua 와 WoW Programming 링크를 참고하세요." +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."] = "수정할 유닛을 선택하면, 바뀐 설정이 고른 모든 유닛을 변경합니다. 공격대/파티 유닛을 특정 설정으로 정하거나 바꾸려면 해당 옵션을 통해야 합니다.|n|n유닛을 모두 선택/취소하려면 Shift 클릭하세요." +L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."] = "왼쪽 패널에서 바꾸려는 태그 텍스트를 고르세요. 너비 및 크기 조정, 좌표는 현재 패널에서 할 수 있습니다." +L["Separate raid frames"] = "공격대 창 분리" +L["Set Filter Zones"] = "필터 지역 설정" +L["Sex"] = "성별" +L["Shadow Orbs"] = "어둠의 구슬" +L["Shaman mana bar"] = "주술사 마나 바" +L["Short classification"] = "분류 (짧게)" +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."] = "짧은 분류로 희귀는 R, 희귀 정예는 R+, 정예는 +, 우두머리는 B, 하수인은 M이며 이 중 하나가 아닌 경우 아무것도 표시되지 않습니다." +L["Short elite indicator"] = "짧은 정예 표시기" +L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."] = "[드루이드 폼]의 짧은 버전으로, 표범은 표, 곰은 곰, 날쌘 동물은 날 등을 반환합니다." +L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."] = "짧게 표시한 피해 흡수량으로, 피해량 13,000이 흡수되는 경우 13k로 표시합니다." +L["Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k."] = "짧게 표시한 치유 흡수량 값으로, 치유량 17,000이 흡수되는 경우 17k로 표시합니다." +L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."] = "짧게 표시한 시전 중 치유량 값으로, 치유량이 13,000이면 13k로 표시합니다." +L["Show a background behind the bars with the same texture/color but faded out."] = "바 뒤에 배경을 같은 무늬/색상으로 표시하지만 희미해집니다." +L["Show any other auras"] = "다른 오라 표시" +L["Show as bar"] = "바 형태로 표시" +L["Show aura duration"] = "오라 지속시간 표시" +L["Show aura icon"] = "오라 아이콘 표시" +L["Show auras stack"] = "오라 중첩 표시" +L["Show background"] = "배경 표시" +L["Show boss debuffs"] = "보스 디버프 표시" +L["Show buffs before debuffs when sharing the same anchor point."] = "같은 부착 지점을 공유하는 경우 디버프 앞에 버프를 표시합니다." +L["Show cast name"] = "주문 이름 보기" +L["Show cast time"] = "시전 시간 보기" +L["Show castable on other auras"] = "다른 오라에 시전 가능 표시" +L["Show casted by boss"] = "보스가 시전한 오라 표시" +L["Show curable debuffs"] = "치유 가능 디버프 표시" +L["Show curable/removable auras"] = "치유 가능/제거 가능 오라 표시" +L["Show Heal Absorbs"] = "치유 흡수량 표시" +L["Show icon durations"] = "아이콘 지속시간 표시" +L["Show incoming absorbs"] = "피해 흡수량 표시" +L["Show incoming heals"] = "시전 중 치유량 표시" +L["Show inside"] = "내부에 표시" +L["Show party as raid"] = "공격대일 때 파티 보기" +L["Show player in party"] = "파티에 플레이어 표시" +L["Show your auras"] = "자기 오라 표시" +L["Shows a bar for alternate power info (used in some encounters)"] = "(일부 전투에서 쓰이는) 대체 자원 정보에 대한 바를 표시합니다." +L["Shows a cooldown wheel on the indicator with how much time is left on the aura."] = "오라에 남은 시간과 함께 표시기에 재사용 대기시간 휠을 표시합니다." +L["Shows AFK, DND or nothing depending on the units away status."] = "유닛 자리 비움 상태에 따라 자리 비움, 다른 용무 중 등을 표시합니다." +L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."] = "유닛이 받은 마지막 치유, 유닛이 빗나가거나 저항, 회피한 마지막 타격 등 전투 피드백을 표시합니다." +L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."] = "현재/최대 생명력을 절댓값 형태로 표시해, 생명력 17500은 17500으로 보여줍니다." +L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."] = "현재 및 최대 자원을 절댓값 형태로 표시해, 자원 18000은 18000 그대로 보여줍니다." +L["Shows current group number of the unit."] = "유닛의 현재 파티 번호를 표시합니다." +L["Shows current health value in absolute form meaning 15000 health is shown as 15000."] = "현재 생명력을 절댓값 형태로 표시해, 생명력 15000은 15000으로 보이게 됩니다." +L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."] = "현재 자원을 절대값 형태로 표시해, 자원 15000을 15000 그대로 보여줍니다." +L["Shows debuffs cast by a boss."] = "보스가 시전한 디버프를 표시합니다." +L["Shows debuffs that you can cure."] = "치유할 수 있는 디버프를 표시합니다." +L["Shows how long an unit has been AFK or DND."] = "유닛이 자리 비움이나 다른 용무 중 상태였던 시간을 표시합니다." +L["Shows how long an unit has been offline."] = "유닛이 오프라인 상태였던 시간을 표시합니다." +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."] = "PVP 깃발이 떨어질 때까지 얼마나 남았는지 보여줍니다. 깃발이 수동으로 켜져 있거나 적대적인 지역에 있으면 표시되지 않습니다.|n|n이는 자신에게만 효과가 있으며 파티나 공격대의 남은 시간을 확인하는 데 사용할 수 없습니다." +L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."] = "최대 생명력을 절댓값 형태로 표시해, 생명력 14000은 14000 그대로 보여줍니다." +L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."] = "최대 자원을 절댓값 형태로 표시해, 자원 13000은 13000 그대로 보여줍니다." +L["Shows Offline, Dead, Ghost or nothing depending on the units current status."] = "유닛의 현재 상태에 따라 오프라인, 죽음, 유령 등을 표시합니다." +L["Shows that a NPC is a boss for a quest."] = "퀘스트 보스인 NPC를 표시합니다." +L["Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000."] = "시간차 피해량을 절댓값으로 표시해, 피해량이 16,000이면 16,000으로 나타냅니다." +L["Shows the current staggered damage, if 12,000 damage is staggered, shows 12k."] = "현재 시간차 피해량을 표시해, 피해량이 12,000이면 12k로 나타냅니다." +L["Show's the units guild name if they are in a guild."] = "유닛이 길드에 가입되어 있을 경우 길드 이름을 표시합니다." +L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."] = "유닛 생명력을 소수 둘째 자리에서 반올림한 백분율로 표시해, 생명력 110중 61은 55.4%로 보이게 됩니다." +L["Shows what kind of pet the unit is for pet battles."] = "대전에 쓰이는 애완동물의 종류를 표시합니다." +L["Shows when a party member is in a different phase or another group."] = "파티원이 다른 위상이나 다른 파티에 있는 경우 표시합니다." +L["Simple aura filtering by whitelists and blacklists."] = "허용목록 및 차단목록에 의한 간단한 오라 필터링입니다." +L["Size"] = "크기" +L["Smart Friendly/Hostile Filter"] = "스마트 우호/적대 필터" +L["Smart level"] = "레벨 (스마트)" +L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."] = "영리한 레벨 표시로, 보스는 보스, 50레벨 정예 몹은 +50, 80레벨은 그냥 80을 반환합니다." +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."] = "[curmaxhp]용 영리한 숫자 형태로, 1,000,000 미만의 수는 그대로 두고 1,000,000 이상의 수는 1m과 같은 짧은 버전을 사용합니다." +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."] = "[curmaxhp]의 짧은 숫자 형태로, 1,000,000 미만의 수는 그대로 두고 1,000,000 이상의 수는 1m과 같은 짧은 버전을 사용합니다." +L["Solid color to use in the indicator, only used if you do not have use aura icon enabled."] = "표시기에 사용할 단색으로, 오라 아이콘을 사용하지 않는 경우에만 쓰입니다." +L["Sort method"] = "정렬 방법" +L["Sort order"] = "순서 정렬" +L["Sorting"] = "정렬" +L["Soul Shards"] = "영혼의 조각" +L["Soul shards"] = "영혼의 조각" +L["Spacing"] = "간격" +L["Spacing between each row"] = "각 행 사이의 간격입니다." +L["Spell ID %s"] = "주문 ID %s" +L["Spell Name"] = "주문 이름" +L["Spell Name/ID"] = "주문 이름/ID" +L["Spell you want to link to a primary aura, the casing must be exact."] = "기본 오라에 연결하려는 주문은 대소문자가 정확해야 합니다." +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."] = "공격대 창을 단일 창 하나 대신 각 공격대 파티용 개별 창으로 분리합니다.|n유의! 각 파티 창을 따로 움직일 수는 없지만 확장하는 법은 열과 행 확장 옵션을 통해 설정됩니다." +L["Stagger"] = "시간차" +L["Stagger (Monk)"] = "시간차 (수도사)" +L["Stagger (Monk/Absolute)"] = "시간차 (수도사/절댓값)" +L["Stagger bar"] = "시간차 바" +L["Stagger bar color when the staggered amount is <30% of your HP."] = "시간차 양이 생명력의 30% 미만일 때 시간차 바 색상입니다." +L["Stagger bar color when the staggered amount is >30% of your HP."] = "시간차 양이 생명력의 30% 초과일 때 시간차 바 색상입니다." +L["Stagger bar color when the staggered amount is >70% of your HP."] = "시간차 양이 생명력의 70% 초과일 때 시간차 바 색상입니다." +L["Static"] = "일반 생명력" +L["Statue"] = "조각상" +L["Statue bar"] = "조각상 바" +L["Status"] = "상태" +L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."] = "유닛이 현재 전투 중인 경우를 표시하는 상태 표시기입니다. 플레이어의 경우 휴식 중인 경우에도 표시합니다." +L["Stealable/Curable/Dispellable"] = "훔치기 가능/치유 가능/해제 가능" +L["Style of borders to show for all auras."] = "모든 오라에 표시할 테두리 스타일입니다." +L["Summon Pending"] = "소환 대기 중" +L["T"] = "나" +L["Tag list"] = "태그 목록" +L["Tag name"] = "태그 이름" +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]."] = "이 코드에 접근하는 데 사용할 태그로, 대괄호나 소괄호로 감싸지 마세요. 자동으로 됩니다. 예를 들어, \"foobar\"를 입력한 다음 [foobar]로 접근하세요." +L["Tags"] = "태그" +L["Talent spec of your arena opponents."] = "투기장 상대의 특성 전문화입니다." +L["Target"] = "대상" +L["Target of Target"] = "대상의 대상" +L["Target of Target of Target"] = "대상의 대상의 대상" +L["Test Aura"] = "오라 테스트" +L["Test spell"] = "주문 테스트" +L["Text"] = "텍스트" +L["Text Management"] = "텍스트 관리" +L["Text name"] = "텍스트 이름" +L["Text name that you can use to identify this text from others when configuring."] = "구성할 때 이 텍스트를 딴 거와 구별하는 데 쓸 수 있는 텍스트 이름입니다." +L["Text parent"] = "텍스트 위치" +L["Text/Tags"] = "텍스트/태그" +L["The blacklist \"%s\" already exists."] = "\"%s\"인 차단목록이 이미 있습니다." +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."] = "아래 확인 상자를 사용하여 유닛을 사용하거나 중지할 수 있습니다.|n|n|cffff2020경고!|r 대상의 대상 유닛은 다른 유닛에 비해 성능비용이 높습니다. 성능 문제가 있는 경우, 유닛을 사용 중지하거나 해당 유닛에 대해 사용된 기능을 줄이세요." +L["The override list \"%s\" already exists."] = "\"%s\" 재정의 목록이 이미 있습니다." +L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."] = "플레이어 창은 설정과 상관없이 숨겨지지 않으며, 전체 또는 지역 유형에 따라 직접 사용 중지해야 합니다." +L["The tag \"%s\" already exists."] = "\"%s\"인 태그가 이미 있습니다." +L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."] = "지금 보는 유닛 창은 예이며, 완전하지 않아 보통 보여주는 데이터를 모두 표시하지 않습니다.|n|n창은 /suf나 아래 버튼 클릭을 통해 숨길 수 있습니다." +L["The whitelist \"%s\" already exists."] = "\"%s\"인 허용목록이 이미 있습니다." +L["Thick outline"] = "두꺼운 외곽선" +L["Thin outline"] = "얇은 외곽선" +L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."] = "이 바는 최고 레벨이거나 추적하는 평판이 없을 때는 저절로 숨겨집니다." +L[ [=[This color will be used if the indicator shown is your own, only applies if icons are not used. +Handy 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.]=] ] = [=[이 색상은 보이는 표시기가 자기 것이면 사용되며, 아이콘이 쓰이지 않는 경우에만 적용합니다. +대상에 회복이 있는지 뿐만 아니라 시전자가 자기인지 알고 싶다면 편리합니다.]=] +L["This filter has no aura types set to filter out."] = "이 필터에는 필터링할 오라 유형 세트가 없습니다." +L["This filter has no auras in it, you will have to add some using the dialog above."] = "이 필터에는 오라가 없습니다. 위 대화 상자를 이용해 오라를 추가해야 합니다." +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."] = "Lua 프로그래밍을 어떻게 시작할 것인가, 그리고 기본적인 Lua 문법이나 API들을 충분히 이해하는데 좋은 길잡이가 될 것입니다." +L["This unit depends on another to work, disabling %s will disable %s."] = "이 모듈은 상호작용하는 모듈이며, %s 모듈을 비활성화 하면 %s 모듈도 비활성화 됩니다." +L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."] = "이 유닛은 딸린 하위 유닛이 있으며, 이 유닛을 켜야 해당 하위 유닛을 사용할 수 있습니다." +L[ [=[This will be set for your current class only. +If no custom spells are set, defaults appropriate for your class will be used.]=] ] = "이는 현재 직업에만 설정됩니다. 사용자 정의 주문이 설정되지 않은 경우, 직업에 맞는 기본값이 사용됩니다." +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."] = "이 태그가 필요한 이벤트 자동 감지를 사용하지 않으며, 뭘 하는지 모르겠다면 이를 선택하지 않아야 합니다." +L["This will override all background colorings for bars including custom set ones."] = "이는 사용자 정의 세트를 포함한 바에 대한 모든 배경 색상을 무시합니다." +L["Threat"] = "위협 수준" +L["Threat situation"] = "위협 수준 상황" +L["Tile size"] = "타일 크기" +L["Timer Text"] = "타이머 텍스트" +L["Top"] = "상단" +L["Top Center"] = "상단 중앙" +L["Top Left"] = "상단 왼쪽" +L["Top Right"] = "상단 오른쪽" +L["Total number of active holy power."] = "현재 총 신성한 힘의 수입니다." +L["Total number of active soul shards."] = "현재 총 영혼의 조각 수입니다." +L["Total number of combo points you have on your target."] = "대상에 갖고 있는 총 연계 점수입니다." +L["Totem bar"] = "토템 바" +L["Totem Timer"] = "토템 타이머" +L["Travel"] = "날쌘 동물" +L["Tree"] = "나무" +L["Turns this widget into a bar that can be resized and ordered just like health and power bars."] = "이 위젯을 생명력 및 자원 바처럼 크기 및 순서를 바꿀 수 있는 바 형태로 바꿉니다." +L["Unattackable hostile"] = "공격불가 적" +L["Unchecking this will completely disable aura indicators for %s."] = "이를 선택 해제하면 %s 유닛에 오라 표시기를 전혀 사용하지 않습니다." +L["Unit color code on aggro"] = "어그로 획득 시 유닛 색상 코드" +L["Unit colored situation"] = "유닛 상황 (색상)" +L["Unit Configuration"] = "유닛 구성" +L["Unit faction"] = "유닛 진영" +L["Unit name"] = "유닛 이름" +L["Unit name (Class colored)"] = "유닛 이름 (직업 색상)" +L["Unit name colored by class."] = "직업별 색상이 지정된 유닛 이름입니다." +L["Unit scaled threat"] = "크기변경된 위협 유닛" +L["Unit server"] = "유닛 서버" +L["Unit server, if they are from your server then nothing is shown."] = "유닛 서버로, 당신 서버인 경우 아무것도 표시되지 않습니다." +L["Unit situation name"] = "유닛 상황 이름" +L["Units"] = "유닛" +L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."] = "유닛 연합, 스랄은 호드, 마그니 브론즈비어드는 얼라이언스를 반환합니다." +L["Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those."] = "유닛 분류로 희귀, 희귀 정예, 정예, 우두머리 또는 하수인이며 이 중 하나가 아닌 경우 아무것도 표시되지 않습니다." +L["Units per column"] = "열당 유닛 수" +L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."] = "유닛 종족으로, 블러드 엘프, 타우렌, 트롤(불행히도) 따위입니다." +L["Units that should have the aura groups settings changed below."] = "아래 변경된 오라 그룹 설정을 지녀야 하는 유닛입니다." +L["Units to change"] = "변경할 유닛" +L["Unknown"] = "알 수 없음" +L["Unlink frames"] = "창 사이 연결해제" +L["Up"] = "위" +L["Update interval"] = "업데이트 간격" +L["Uses the icon of the totem being shown instead of a status bar."] = "상태 바 대신 표시되는 토템 아이콘을 사용합니다." +L["Using unit settings"] = "유닛 설정을 사용" +L["Various units can be enabled through this page, such as raid or party targets."] = "다양한 유닛(가령 공격대나 파티 대상)을 이 페이지를 통해 사용할 수 있습니다." +L["Vehicle"] = "차량" +L["Vehicles"] = "차량" +L["Vertical growth"] = "수직 확장" +L["View"] = "보기" +L["Visibility"] = "창 보임" +L["WARNING! ShadowedUF_Indicators has been deprecated as v4 and is now built in. Please delete ShadowedUF_Indicators, your configuration will be saved."] = "경고! ShadowedUF_Indicators는 v4 때 사용되지 않고 사라져 이제 내장되어 있습니다. ShadowedUF_Indicators를 삭제하세요, 구성은 저장됩니다." +L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] = "경고: 이는 함께 움직이는 다른 창 없이 이동할 수 있도록 모든 창을 서로 연결해제합니다." +L["What group this aura belongs to, this is where you will find it when configuring."] = "이 오라가 속하는 그룹으로, 이는 구성할 때 오라를 찾을 수 있는 곳입니다." +L["What type of auras should be enlarged, use the scaled aura size option to change the size."] = "확대되어야 하는 오라의 유형으로, 크기를 바꾸려면 오라 크기 비율 옵션을 사용하세요." +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."] = "유닛의 생명력이 빠진 경우 [missinghp] 태그가, 생명력이 가득찬 경우에는 [name] 태그가 표시됩니다. 이렇게 하면 생명력 1000이 감소한 경우 -1000이 보이지만 감소하지 않은 때는 이름이 보입니다." +L["When this filter is active, apply the filter to buffs."] = "이 필터를 활성화하면, 버프에 필터를 적용합니다." +L["When this filter is active, apply the filter to debuffs."] = "이 필터를 활성화하면, 디버프에 필터를 적용합니다." +L["When to color the empty bar by reaction, overriding the default color by option."] = "빈 바를 평판에 따라 색상 지정하는 경우, 옵션에 따른 기본 색상을 재정의합니다." +L["When to color the health bar by the units reaction, overriding the color health by option."] = "생명력 바를 유닛 평판에 따라 색상 지정하는 경우, 옵션에 따른 생명력 색상을 재정의합니다." +L["When to show cooldown rings on auras"] = "오라에 재사용 대기시간 링을 표시할 경우" +L["Where inside the frame the text should be anchored to."] = "텍스트가 부착되어야 하는 창 내부 위치입니다." +L["Where to anchor the cast name text."] = "주문 이름 텍스트 부착 위치입니다." +L["Where to anchor the cast time text."] = "시전 시간 텍스트 부착 위치입니다." +L["Whether auras you casted should be shown"] = "자기가 시전한 오라가 표시되어야 하는지 여부입니다." +L["Whether to show any auras casted by the boss"] = "보스가 시전한 모든 오라를 표시할지 여부입니다." +L["Whether to show any debuffs you can remove, cure or steal."] = "해제나 치유, 훔치기 가능한 모든 디버프 표시 여부입니다." +L["Whether to show auras that do not fall into the above categories."] = "위 부류에 속하지 않는 오라를 표시할지 여부입니다." +L["Whether to show buffs that you cannot cast."] = "자기가 시전할 수 없는 버프를 표시할지 여부입니다." +L["Whitelist"] = "허용목록" +L["Whitelist filters"] = "허용목록 필터" +L["Whitelists"] = "허용목록" +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."] = "허용목록은 필터 그룹에 없는 모든 오라를 숨깁니다.|n차단목록은 필터 그룹에 있는 오라를 숨깁니다.|n재정의 목록은 모든 필터를 무시하고 항상 표시됩니다." +L["Widget Size"] = "위젯 크기" +L["Width"] = "너비" +L["Width percent"] = "너비 백분율" +L["Width weight"] = "너비 가중치" +L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."] = "수평 확장을 사용하는 경우 우에서 좌로, 수직 확장을 사용하는 경우 위에서 밑으로 채웁니다." +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"] = "\"유닛 구성에 대한 모든 탭이 뭘 뜻하는지 궁금하세요? 여기 몇 가지 정보가 있습니다:|n|n|cfffed000일반:|r 초상화, 사정거리 확인기, 투명도 조절기, 테두리 강조|n|cfffed000창:|r 유닛 위치 지정 및 창 부착|n|cfffed000바:|r 생명력, 자원, 빈 바와 시전 바 및 연계 점수 구성|n|cfffed000위젯 크기:|r 모든 바와 초상화의 크기 조정 및 순위 지정 옵션|n|cfffed000오라:|r 사용/미사용/자기 오라 확대 등에 대한 모든 오라 구성|n|cfffed000표시기:|r 모든 표시기 구성|n|cfffed000텍스트/태그:|r 텍스트 위치 지정과 너비 설정뿐만 아니라 태그 관리.|n|n|n*** 자주 찾는 옵션 ***|n|n|cfffed000파티별 공격대 창|r - 유닛 구성 -> 공격대 -> 공격대 -> 공격대 창 분리|n|cfffed000직업 색상 지정:|r 바 -> 생명력 색상 지정|n|cfffed000오라에 타이머:|r 이는 OmniCC가 필요합니다|n|cfffed000기본 버프 창 표시/숨기기:|r 블리자드 창 숨기기 -> 버프 창 숨김|n|cfffed000백분율 생명력/마나 텍스트:|r 텍스트/태그 탭, [perhp] 또는 [perpp] 태그를 쓰세요|n|cfffed000공격대에 따라 파티 숨기기|r - 유닛 구성 -> 파티 -> 파티 -> 5인 초과 공격대에서 숨김/모든 공격대에서 숨김\"" +L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."] = "[%s]와 동일하게 동작하지만 마나는 항상 보이며 또 마나가 2차 자원인 경우에만 표시됩니다." +L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."] = "[%s]와 동일하게 동작하지만 이는 유닛이 표범이나 곰 모습인 경우에만 표시됩니다." +L["WoW Programming"] = "WoW Programming" +L["WoW Programming is a good resource for finding out what difference API's do and how to call them."] = "WoW Programming은 다른 API의 사용법이나 호출 방법을 파악할 수 있는 좋은 참고자료입니다." +L["X Offset"] = "X 좌표" +L["XP/Rep bar"] = "경험치/평판 바" +L["Y Offset"] = "Y 좌표" +L["Yellow (>30% HP)"] = "노랑 (HP 30% 초과)" +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."] = "이 구성을 이용해 사용되는 태그 달린 부가 텍스트를 추가할 수 있으며, 추가(나 삭제)된 어떤 텍스트든 모든 유닛에 영향을 주고 텍스트를 제거하면 설정 또한 초기화됨을 유의하세요.|n|n명심하세요, 유닛에 포함된 기본 텍스트는 삭제할 수 없습니다." +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."] = "유닛 구성의 텍스트 탭 아래에 보이는 텍스트에 사용되는 태그를 바꾸려고 하는 경우, 이 페이지를 통해 새로운 사용자 정의 태그를 추가할 수 있습니다." +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."] = "여기서 유닛에 대해 오라 필터와 오라 그룹을 사용 중지할 수 있습니다. 예를 들어, 대상에만 표시할 DPS 디버프를 보여주는 오라 그룹을 설정할 수 있습니다." +L["You can find more information on creating your own custom tags in the \"Help\" tab above."] = "위 \"도움말\" 탭에서 사용자 정의 태그 제작에 대한 자세한 정보를 찾을 수 있습니다." +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."] = "위 \"도움말\" 탭에서 사용자 정의 태그 제작에 대한 자세한 정보를 찾을 수 있습니다.|nSUF는 자동으로 태그에 필요한 이벤트 감지를 시도하므로, 보통 이벤트 필드를 채울 필요가 없습니다." +L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] = "아래 주어진 가져오기 코드를 입력하여 다른 SUF 사용자의 구성을 가져올 수 있습니다. 이는 \"백업을 가져오기\" 위해 기존 화면배치를 백업합니다.|n|n붙여넣을 때 화면배치 로딩에 30-60초가 걸리니, 기다려 주세요." +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."] = "이를 이용해 오라를 서로 연결할 수 있습니다. 예를 들어, 야생의 징표를 야생의 선물에 연결할 수 있습니다. 그래서 플레이어가 야생의 징표는 있지만 야생의 선물은 없는 경우, 마치 야생의 선물이 있는 것처럼 야생의 징표를 여전히 표시합니다." +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."] = "직업별로 어떤 오라가 사용되는지를 재정의할 수 있으나, 오라가 주 목록을 통해 사용 중지된 경우 여기 직업 설정은 상관없음을 유의하세요." +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."] = "여기서 유닛 창이 어떤 필터 그룹과 지역 유형에서 사용해야 하는지를 설정할 수 있습니다. 오라가 속한 그룹을 바꾸고 싶다면, \"오라 그룹 관리\" 옵션을 보세요." +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."] = "이 태그는 SUF에 포함된 기본 태그 중 하나이기에 편집할 수 없습니다. 이 함수는 사용자 정의 태그에 대한 예를 제공하기 위해 여기에 있습니다." +L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."] = "\"%s\"인 태그 이름을 지정할 수 없으며, 태그 이름에는 괄호나 대괄호가 없어야 합니다." +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."] = "이 필터 유형에 아직 추가된 것이 없으므로, 이 페이지를 사용하기 전에 관리 탭에서 새로운 필터를 만들어야 합니다." +L["You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf."] = "전투에 참여해, 유닛 창이 잠겼습니다. 일단 전투가 끝나면 /suf 를 통해 다시 잠금을 해제해야 합니다." +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."] = "발생시킬 이벤트를 설정해야 하며, 문자와 밑줄만 입력할 수 있습니다. 예를 들어 \"FOO_BAR\"는 올바르고, \"APPLE_5_ORANGE\"는 숫자가 있기에 아닙니다." +L["You must enter a number that is 0 or higher, negative numbers are not allowed."] = "0 이상의 숫자를 입력해야 하며, 음수는 허용되지 않습니다." +L["You must enter a tag name."] = "반드시 태그 이름을 입력해야 합니다." +L["You must restart Shadowed Unit Frames."] = "SUF를 재시작해야 합니다." +L["You must wrap your code in a function."] = "코드는 함수로 감싸야 합니다." +L["You will need to create an aura filter before you can set which unit to enable aura filtering on."] = "오라 필터링을 사용할 유닛을 설정하기 전에 오라 필터를 만들어야 합니다." +L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."] = "숨겨진 창이 다시 표시되기 전 UI 재시작(/rl)이 필요합니다.|n플레이어와 다른 유닛 창은 SUF에서 유닛 사용 여부에 따라 자동으로 숨겨집니다." +L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] = "현재 화면배치는 가져오기 백업용으로 쓰이는 프로필로, 이는 가져오기로 덮어쓸 수 없습니다. 다른 무언가로 프로필을 변경한 뒤 다시 시도하세요." +L["Your aura color"] = "자기 오라 색상" +L["Your Auras"] = "자기 오라" +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"] = "코드는 함수로 감싸야 합니다. 예를 들어, 태그가 유닛 이름을 반환하도록 하려면 다음과 같이 할 겁니다:|n|nfunction(unit, unitOwner)|nreturn UnitName(unitOwner)|nend" +L["Zone Configuration"] = "지역 구성" +L["Zone configuration units"] = "지역 구성 유닛" + +local ShadowUF = select(2, ...) +ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) diff --git a/localization/ptBR.lua b/localization/ptBR.lua index 4a3353b48..0e24ee901 100755 --- a/localization/ptBR.lua +++ b/localization/ptBR.lua @@ -1,5 +1,2052 @@ -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}) +if( GetLocale() ~= "ptBR" ) then return end +local L = {} +L["%d auras in group"] = [=[%d auras em grupo + +]=] +L["%s (%s): %s/%s (%.2f%% done)"] = "%s (%s): %s/%s (%.2f%% terminado)" +L["%s aura groups disabled"] = [=[%s aura grupos desativados + +]=] +L["%s frames"] = "%s moldura" +L["%s member"] = "%s membro" +L["|cff20ff20%s|r units enabled"] = [=[|cff20ff20%s|r unidades habilitadas + +]=] +L["|cffff2020%s|r units disabled"] = [=[|cffff2020%s|r unidades desativadas + +]=] +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."] = [=[|cffff2020Aviso!|r Algumas unidades têm substituições definidas na configuração de zona e podem aparecer (ou não) em determinada zona. Independentemente das configurações abaixo. + +]=] +L["1 aura group disabled"] = [=[1 grupo de aura desativado + +]=] +L["2D"] = "2D" +L["3D"] = "3D" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "Abrevia os nomes das unidades com mais de 10 caracteres, \"Dark Rune Champion\" passa a \"D.R.Champion\" e \"Dark Rune Commoner\" passa a \"D.R.Commoner\"." +L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."] = [=[Valor absoluto de absorção de danos na unidade, se 10.000 danos forem absorvidos, ele mostrará 10.000. + +]=] +L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."] = [=[Valor absoluto de absorção de cura, se 16.000 cicatrizações forem absorvidas, mostrará 16.000. + +]=] +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "Valor absoluto de cura a receber, se vai receber 10,000 de cura, então mostrará 10,000." +L["Add"] = "Adiciona" +L["Add Aura"] = [=[Adicionar Aura + +]=] +L["Add aura"] = [=[Adicionar aura + +]=] +L["Add Indicator"] = [=[Adicionar indicador + +]=] +L["Add link"] = [=[Adicionar link + +]=] +L["Add new indicator"] = [=[Adicionar novo indicador + +]=] +L["Add new tag"] = "Adicionar nova tag" +L["Add new text"] = "Adicionar novo texto" +L["Add Tags"] = [=[Adicionar tags + +]=] +L["Adds %s to the list of units to be modified when you change values in this tab."] = "Adiciona %s à lista de unidades que vão ser modificadas quando muda valores neste separador." +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "Adiciona uma barra a indicar quanto tempo resta no temporizador da ghoul, apenas é usado se não tiver uma ghoul permanente." +L["Adds a bar indicating how much time is left on your mushrooms."] = [=[Adiciona uma barra indicando quanto tempo resta em seus cogumelos. + +]=] +L["Adds a bar indicating how much time is left on your Rune of Power."] = [=[Adiciona uma barra indicando quanto tempo resta na Runa do Poder. + +]=] +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = [=[Adiciona uma barra dentro da barra de integridade indicando quanto dano será absorvido. + +]=] +L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."] = [=[Adiciona uma barra dentro da barra de saúde indicando quanta cura se estima que alguém esteja recebendo. + +]=] +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = [=[Adiciona uma barra dentro da barra de saúde indicando quanta cura alguém receberá. + +]=] +L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."] = [=[Adiciona uma barra dentro da barra de saúde indicando quanto de cura será absorvido e não aplicado ao jogador. + +]=] +L["Adds a mana bar to the player frame for elemental and enhancement shamans."] = [=[Adiciona uma barra de mana ao quadro do jogador para xamãs elementais e de aprimoramento. + +]=] +L["Adds a mana bar to the player frame for shadow priests."] = [=[Adiciona uma barra de mana ao quadro do jogador para sacerdotes das sombras. + +]=] +L["Adds a Stagger bar for Brewmaster Monks."] = "Adiciona uma barra Stagger para Monges Mestres Cervejeiros." +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "Adiciona uma barra onde pode por texto como forma de desatafulhar outras barras." +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "Adiciona uma outra barra de mana à moldura quando está em forma de Gato ou Urso indicando a mana que possui." +L["Adds rune bars and timers before runes refresh to the player frame."] = "Adiciona à moldura do jogador temporizadores de tempo restante para as runes refrescarem e barras de runes." +L["Adds temporary enchants to the buffs for the player."] = "Adiciona encantamentos temporários aos feitiços benéficos para o jogador." +L["Adds totem bars with timers before they expire to the player frame."] = "Adiciona à moldura do jogador barras de totems com temporizadores de tempo restante para expirarem." +L["Advanced"] = "Avançadas" +L["Advanced tag management, allows you to add your own custom tags."] = "Gestão avançada de tags, permite-lhe adicionar as suas próprias tags." +L["AFK"] = "AFK" +L["AFK status"] = "estado LDT" +L["AFK timer"] = "temporizador LDT" +L["AFK:%s"] = [=[AFK:%s + +]=] +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "Depois de clicar em exportar, pode dar o código abaixo a outros utilizadores do Shadowed Unit Frames e eles irão ficar com a disposição das molduras igual à sua." +L["Aggro"] = "Aggro" +L["All aura groups enabled for unit."] = [=[Todos os grupos de aura habilitados para unidade. + +]=] +L["All Auras"] = [=[Todas as Auras + +]=] +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."] = [=[Permite ancorar o grupo de aura a outro, você pode então escolher onde ele será ancorado usando a posição.|n|nUse isso se quiser duplicar o estilo de interface do usuário padrão em que buffs e debuffs são grupos separados. + +]=] +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."] = [=[Permite desativar o totem clicando com o botão direito do mouse nele.|n|nAviso: As barras internas desta unidade não serão redimensionadas em combate se você ativar isso. + +]=] +L["Allows you to enter a new aura group."] = [=[Permite que você insira um novo grupo de aura. + +]=] +L["Alpha to use for bar backgrounds."] = "Alpha para usar no background da barra." +L["Alpha to use for bar."] = [=[Alfa para usar na barra. + +]=] +L["Alt. Power"] = "Alt. Poder" +L["Alt. Power bar"] = [=[Alt. Barra de poder + +]=] +L["Alternate power is used for things like quests and dungeons."] = [=[O poder alternativo é usado para coisas como missões e masmorras. + +]=] +L["Alternate Spell Name"] = "Nome de feitiço alternativo" +L["Alternatively friendly spell to use to check range."] = "Alternativamente, feitiço amigável para usar para verificar o alcance." +L["Ammo"] = "Munições" +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."] = "Quantidade de vida em falta, se há 0 em falta nada é mostrado. Utiliza um formato curto, -18500 é mostrado como -18.5k, valores abaixo de 10000 são formatados assim mesmo." +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."] = "Quantidade de power em falta, se faltar 0 nada será mostrado. Usa um formato curto, -13850 é mostrado como 13.8k, valores abaixo de 10000 são formatados assim mesmo." +L["Anchor point"] = "Ponto de ancoragem" +L["Anchor to"] = "Ancorar a" +L["Anchor to another frame"] = "Ancorar a outra moldura" +L["Anchor to buffs"] = "Ancorar aos buffs" +L["Anchor to debuffs"] = "Ancorar aos debuffs" +L["Ancient Kings bar"] = "Barra dos Reis Antigos" +L["Any auras shown in this indicator will have their total stack displayed."] = [=[Quaisquer auras mostradas neste indicador terão sua pilha total exibida. + +]=] +L["Aquatic"] = "Aquático" +L["Arcane Charges"] = [=[Cargas arcanas + +]=] +L["Are you sure you want to delete this aura?"] = [=[Tem certeza de que deseja excluir essa aura? + +]=] +L["Are you sure you want to delete this filter?"] = "Tem a certeza que pretende remover este filtro?" +L["Are you sure you want to delete this indicator?"] = [=[Tem certeza de que deseja excluir esse indicador? + +]=] +L["Are you sure you want to delete this tag?"] = "Tem a certeza que quer apagar esta tag?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "Tem a certeza que quer apagar este texto? Todas as definições do mesmo serão apagadas." +L["Arena"] = "Arena" +L["Arena Pet"] = [=[Arena Pet + +]=] +L["Arena Spec"] = [=[Arena Spec + +]=] +L["Arena Target"] = [=[Arena Alvo + +]=] +L["Arena Target of Target"] = [=[Arena Alvo do Alvo + +]=] +L["Arena ToT"] = [=[Arena ToT + +]=] +L["Arenas"] = "Arenas" +L["Ascending"] = "Ascendente" +L["Assigned Role (DPS/Tank/etc)"] = "Função atribuída (DPS/Tank/etc)" +L["Astral Power"] = [=[Poder Astral + +]=] +L["Aura border style"] = "Estilo da aura da aresta" +L["Aura borders"] = "Bordas da Aura" +L["Aura Combo Points"] = "Pontos de Combo Aura" +L["Aura Filters"] = [=[Filtros Aura + +]=] +L["Aura filters"] = "Filtros de aura" +L["Aura group"] = [=[Grupo Aura + +]=] +L["Aura groups"] = [=[Grupos de Aura + +]=] +L["Aura Groups"] = [=[Grupos Aura + +]=] +L["Aura Indicators"] = [=[Indicadores Aura + +]=] +L["Aura indicators"] = [=[indicadores Aura + +]=] +L["Aura name or spell ID"] = "Nome da aura ou ID do feitiço" +L["Aura types to filter"] = "Tipos de filtros de aura" +L["Auras"] = "Auras" +L["Auras matching a criteria will automatically show up in the indicator when enabled."] = [=[As Auras correspondentes a um critério aparecerão automaticamente no indicador quando ativadas. + +]=] +L["Automatic Auras"] = [=[Auras Automáticas + +]=] +L["Background"] = "Background" +L["Background alpha"] = "Alpha de background" +L["Background color"] = "Cor de background" +L["Background/border"] = "Background/border" +L["Bag indicator for master looters."] = "Indicador de saco para master looters" +L["Bar alpha"] = "Barra alfa" +L["Bar color to use to show how much healing someone is about to receive."] = [=[Cor da barra para usar para mostrar quanta cura alguém está prestes a receber. + +]=] +L["Bar spacing"] = "Espaçamento da barra" +L["Bar texture"] = "Textura da barra" +L["Bars"] = "Barras" +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."] = [=[As barras com um pedido maior ou menor do que as opções de tamanho completo usarão toda a largura do quadro da unidade.|n|nOrdens entre esses dois números são mostradas ao lado do retrato. + +]=] +L["Battleground"] = [=[Campo de batalha + +]=] +L["Battleground Pet"] = [=[Campo de batalha Pet + +]=] +L["Battleground Target"] = "Campo de batalha Alvo" +L["Battleground Target of Target"] = "Campo de batalha Alvo do Alvo" +L["Battlegrounds"] = "Battlegrounds" +L["Bear"] = "Urso" +L["BG"] = "BG" +L["BG Pet"] = [=[BG Pet + +]=] +L["BG Target"] = "BG Alvo" +L["BG ToT"] = [=[BG ToT + +]=] +L["Blacklist"] = "Lista negra" +L["Blacklist filters"] = "Filtros de lista negra" +L["Blacklists"] = "Lista negra" +L["Blizzard"] = "Blizzard" +L["Border"] = "Borda" +L["Border alpha"] = "Alpha da aresta" +L["Border color"] = "Cor da borda" +L["Border coloring of stealable, curable and dispellable auras."] = [=[Coloração de bordas de auras furtáveis, curáveis e dissipáveis. + +]=] +L["Border highlighting"] = "Border highlighting" +L["Border thickness"] = "Grossura da borda" +L["Boss"] = "Chefe" +L["Boss Auras"] = [=[Chefe Auras + +]=] +L["Boss Debuffs"] = [=[Debuffs Chefe + +]=] +L["Boss Target"] = "Alvo do Chefe" +L["Boss Target of Target"] = [=[Chefe Alvo do Alvo + +]=] +L["Boss ToT"] = [=[Chefe ToT + +]=] +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."] = [=[As unidades de chefe são apenas para certas lutas, como Príncipes de Sangue ou a batalha de Gunship, você não as verá para todas as lutas de chefes. + +]=] +L["Both"] = "Ambos" +L["Bottom"] = "Botão" +L["Bottom Center"] = "Centro Inferior" +L["Bottom Left"] = "Inferior esquerdo" +L["Bottom Right"] = "Canto inferior direito" +L["buff frames"] = [=[Quadros de buff + +]=] +L["Buffs"] = "Buffs" +L["Cannot find any profiles named \"%s\"."] = "Nenhum profile encontrado com o nome \"%s\"." +L["Cast"] = "Lançar" +L["Cast bar"] = "Barra de Lançamento" +L["Cast icon"] = "Ícone de lançamento" +L["Cast interrupted"] = "Lançamento interrompido" +L["Cast name"] = "Nome do lançamento" +L["Cast time"] = "Tempo de Lançamento" +L["Cast uninterruptible"] = [=[Lançamento ininterrupto +]=] +L["Casting"] = "Lançamento" +L["Cat"] = "Gato" +L["Category"] = "Categoria" +L["Center"] = "Centro" +L["Changed profile to %s."] = [=[Perfil alterado para %s. + +]=] +L["Changes the health bar to the color of any curable debuff."] = [=[Altera a barra de integridade para a cor de qualquer debuff curável. + +]=] +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = [=[Altera a barra de integridade para a cor hostil definida (vermelho por padrão) quando a unidade usa aggro. + +]=] +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."] = [=[Altera este widget em uma barra, você será capaz de alterar a altura e ordenação como você pode alterar a saúde e barras de energia. + +]=] +L["Channelling"] = "Canalização" +L["Checking this will show the indciator on hostile units."] = "Marcar isto mostrará o indicador em unidades hostis." +L["Checking this will show the indicator on friendly units."] = [=[Verificando isso mostrará o indicador em unidades amigáveis. + +]=] +L["Chi"] = "Chi" +L["Chi Points"] = [=[Pontos Chi + +]=] +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = [=[As unidades secundárias não podem ser arrastadas, terá de as reposicionar através do /shadowuf. +]=] +L["Class"] = "Classe" +L["Class (Smart)"] = "Classe (curto)" +L["Class color tag"] = [=[Marca de cor de classe + +]=] +L["Class icon"] = [=[ícone de classe + +]=] +L["Class Icon"] = [=[Ícone de classe + +]=] +L["Class icon for players."] = [=[Ícone de classe para jogadores. + +]=] +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = [=[Nome da classe sem colorir, use [classcolor][class][close] se quiser que o nome da classe seja colorido por classe. + +]=] +L["Class Role"] = [=[Função de classe + +]=] +L["Class Specific"] = "Classe Específica" +L["Class Timer"] = [=[Temporizador de classe + +]=] +L["Class/misc bars"] = [=[Barras de classe/misc + +]=] +L["Classes"] = "Classes" +L["Classification"] = "Classificação" +L["Classifications"] = "Classficações" +L["Close color"] = [=[Fechar cor + +]=] +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = [=[Fecha um código de cores, impede que as cores apareçam no texto que você não deseja. + +]=] +L["Code"] = "Código" +L["Color by class"] = "Classe por cor" +L["Color by reaction on"] = [=[Cor por reação em +]=] +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."] = [=[Código de cores com base na porcentagem de HP deixada na unidade, isso funciona da mesma forma que a opção de cor por integridade. Mas para texto em vez de toda a barra. + +]=] +L["Color code for general situation"] = [=[Código de cores para situação geral + +]=] +L["Color code for situation"] = [=[Código de cores para situação + +]=] +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = [=[Código de cores para a classe, use [classcolor][class][close] se quiser que o texto da classe seja colorido por classe + +]=] +L["Color code on aggro"] = [=[Código de cores no aggro + +]=] +L["Color health by"] = [=[Cor saúde por + +]=] +L["Color on aggro"] = [=[Cor no aggro + +]=] +L["Color on curable debuff"] = [=[Cor no debuff curável + +]=] +L["Color power by"] = [=[Poder da cor por + +]=] +L["Color to use for health bars that are set to be colored by a static color."] = [=[Cor a ser usada para barras de integridade definidas para serem coloridas por uma cor estática. + +]=] +L["Color to use to show how much damage will be absorbed."] = "Cor para exibir o quanto de dano for absorvido" +L["Color to use to show how much healing will e absorbed."] = "Cor a ser usada para mostrar quanta cura será absorvida." +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = [=[Cor usada quando um lançamento não pode ser interrompido, isto só é usado para mobs PvE. +]=] +L["Color used when a cast is a channel."] = "Cor utilizada quando um lançamento é um canal." +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "Cor usada quando um lançamento é interrompido pelo próprio lançador ou por outra unidade." +L["Color used when a cast is successfully finished."] = "Cor usada quando um lançamento é finalizado com sucesso." +L["Color used when an unit is casting a spell."] = "Cor usada quando uma unidade está lançando um feitiço." +L["Colors"] = "Cores" +L["Column growth"] = [=[Crescimento da coluna + +]=] +L["Column spacing"] = "Espaçamento da coluna" +L["Combat alpha"] = "Combate alfa" +L["Combat fader"] = "Fader de combate" +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."] = [=[O fader de combate irá desaparecer todos os seus quadros enquanto eles estiverem inativos e desvanecê-los de volta quando você estiver em combate ou ativo. + +]=] +L["Combat Status"] = [=[Status de Combate + +]=] +L["Combat text"] = [=[Texto de combate + +]=] +L["Combat/resting status"] = [=[Status de combate/repouso + +]=] +L["Combo points"] = "Pontos de combo" +L["Combo Points"] = "Pontos de Combo" +L["Configuration to specific unit frames."] = [=[Configuração para quadros de unidade específicos. + +]=] +L["Cooldown rings for"] = "Anéis de resfriamento para" +L["Create"] = "Criar" +L["Creature type"] = "Tipo de criatura" +L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."] = [=[Tipo de criatura, retorna Felguard se a unidade é um Felguard, Wolf se é um Wolf e assim por diante. + +]=] +L["Crown indicator for group leader or assistants."] = [=[Indicador de coroa para líder de grupo ou assistentes. + +]=] +L["Cur/Max HP (Absolute)"] = "Atual/Máximo Vida (absoluto)" +L["Cur/Max HP (Short)"] = [=[Cur/Max HP (Curto) + +]=] +L["Cur/Max HP (Smart)"] = [=[Cur/Max HP (Inteligente) + +]=] +L["Cur/Max power (Absolute)"] = [=[Potência Cur/Max (Absoluta) + +]=] +L["Cur/Max power (Druid)"] = [=[Potência Cur/Max (Druida) + +]=] +L["Cur/Max power (Druid/Absolute)"] = [=[Potência Cur/Max (Druida/Absoluta) + +]=] +L["Cur/Max power (Secondary)"] = [=[Potência Cur/Max (Secundária) + +]=] +L["Cur/Max power (Secondary/Absolute)"] = [=[Potência Cur/Max (Secundária/Absoluta) + +]=] +L["Cur/Max Power (Short)"] = [=[Cur/Max Power (Curto) + +]=] +L["Cur/Max PP (Smart)"] = [=[Cur/Max PP (Inteligente) + +]=] +L["Curable"] = [=[Curável + +]=] +L["Curable Auras"] = [=[Auras curáveis + +]=] +L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."] = [=[Integridade atual e máxima, formatada como [curhp]/[maxhp], se a unidade estiver morta ou off-line, isso é mostrado. + +]=] +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "Poder atual e máxima, formatada como [curpp]/[maxpp]." +L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."] = [=[Integridade atual, usa um formato curto, 11500 é formatado como 11,5k, valores abaixo de 10000 são formatados como está. + +]=] +L["Current HP (Absolute)"] = "Vida atual (Absoluta)" +L["Current HP (Short)"] = [=[HP atual (curto) + +]=] +L["Current pet used by a battleground unit."] = "Animal de estimação atual usado por uma unidade de campo de batalha." +L["Current power (Absolute)"] = [=[Poder atual (Absoluta) + +]=] +L["Current power (Druid)"] = [=[Poder atual (Druida) + +]=] +L["Current power (Druid/Absolute)"] = [=[Poder atual (Druida/Absoluta) + +]=] +L["Current power (Secondary)"] = [=[Poder atual (Secundária) + +]=] +L["Current power (Secondary/Absolute)"] = [=[Poder atual (Secundária/Absoluta) + +]=] +L["Current Power (Short)"] = "Poder atual (curto)" +L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."] = [=[Poder atual, usa um formato curto, 12750 é formatado como 12.7k, valores abaixo de 10000 são formatados como está. + +]=] +L["Current target of a battleground unit."] = [=[Alvo atual de uma unidade de campo de batalha. + +]=] +L["Current target of target of a battleground unit."] = "Alvo atual do alvo de uma unidade de campo de batalha." +L["Currently modifying"] = "Modificando atualmente" +L["Currently used in battlegrounds for showing flag carriers."] = [=[Atualmente usado em campos de batalha para mostrar porta-bandeiras. + +]=] +L["Damage absorption (Absolute)"] = [=[Absorção de danos (Absoluto) + +]=] +L["Damage absorption (Short)"] = [=[Absorção de danos (Curto) + +]=] +L["Damage absorption/Name"] = [=[Absorção de danos/Nome + +]=] +L["Dark"] = "Escuro" +L["Dead"] = "Morto" +L["Debuffs"] = "Debuffs" +L["Decimal percent HP"] = [=[Porcentagem decimal HP + +]=] +L["Default color"] = "Cor padrão" +L["Default font color, any color tags inside individual tag texts will override this."] = [=[Cor de fonte padrão, quaisquer marcas de cor dentro de textos de marcas individuais substituirão isso. + +]=] +L["Deficit/Unit Name"] = [=[Déficit/Nome da Unidade + +]=] +L["Delete"] = "Apagar" +L["Delete filter"] = "Remover Filtro" +L["Delete link"] = [=[Excluir link + +]=] +L["Descending"] = "Descendente" +L["Disable Auras by Class"] = [=[Desativar Auras por classe + +]=] +L["Disable Blizzard Cooldown Count"] = [=[Desativar a contagem de resfriamento da Blizzard + +]=] +L["Disable event discovery"] = [=[Desabilitar a descoberta de eventos + +]=] +L["Disable OmniCC Cooldown Count"] = [=[Desativar a contagem de resfriamento do OmniCC + +]=] +L["Disable vehicle swap"] = "Desabilitar troca de veículo" +L["Disabled"] = "Desabilitado" +L["Disabled for %s."] = [=[Desabilitado para %s. + +]=] +L["Disabled in %s"] = "Desabilitado em %s" +L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."] = [=[Desativa a exibição de temporizadores de Contagem de Resfriamento em todas as auras de Quadro de Unidade Sombreada. + +]=] +L["Disables the unit frame from turning into a vehicle when the player enters one."] = [=[Desativa o quadro da unidade de se transformar em um veículo quando o jogador entra em um. + +]=] +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!."] = [=[Desabilitar um módulo nesta página o desabilita enquanto estiver dentro de %s. Não desative um módulo aqui se você não quiser que isso aconteça!. + +]=] +L["Disabling unit modules in various instances."] = [=[Desativando módulos de unidade em várias instâncias. + +]=] +L["Dismissable Totem bars"] = [=[Totens descartáveis + +]=] +L["Dispellable/Stealable"] = [=[Dissipável/Roubável + +]=] +L["Display"] = "Mostrar" +L["Display enemy buffs using LibClassicDuration data."] = [=[Exiba buffs inimigos usando dados LibClassicDuration. + +]=] +L["Documentation"] = "Documentação" +L["Don't hide when empty"] = "Não ocultar enquanto vazio" +L["Don't use a filter"] = [=[Não use um filtro + +]=] +L["Down"] = "Baixo" +L["Druid form"] = [=[Forma druida + +]=] +L["Druid form (Short)"] = [=[Forma druida (Curta) + +]=] +L["Druid mana bar"] = [=[Barra de mana druida + +]=] +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."] = [=[Devido à natureza das unidades falsas, as barras fundidas para %s não são supereficientes e podem levar no máximo 0,10 segundos para notar uma mudança no cast. + +]=] +L["Edge size"] = [=[Tamanho da borda + +]=] +L["Edit tag"] = [=[Editar tag + +]=] +L["Editing %s"] = "Editando %s" +L["Elite"] = "Elite" +L["Empty bar"] = [=[Barra vazia + +]=] +L["Enable %s"] = "Habilitar %s" +L["Enable buffs"] = [=[Ativar buffs + +]=] +L["Enable debuffs"] = [=[Ativar debuffs + +]=] +L["Enable enemy buff tracking"] = [=[Ativar o rastreamento de buff inimigo + +]=] +L["Enable for friendlies"] = "Habilitar para os amigáveis" +L["Enable for hostiles"] = [=[Habilitar para hostis + +]=] +L["Enable frequent updates"] = [=[Habilitar atualizações frequentes + +]=] +L["Enable indicator"] = [=[Habilitar indicador + +]=] +L["Enable Indicators"] = [=[Habilitar indicadores + +]=] +L["Enable temporary enchants"] = [=[Habilitar encantamentos temporários + +]=] +L["Enable units"] = [=[Habilitar unidades + +]=] +L["Enabled for %s."] = [=[Habilitado para %s. + +]=] +L["Enabled in %s"] = "Habilitado em %s" +L["Enabled Units"] = [=[Unidades habilitadas + +]=] +L["Enables configuration mode, letting you move and giving you example frames to setup."] = [=[Habilita o modo de configuração, permitindo que você mova e fornecendo quadros de exemplo para configuração. + +]=] +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."] = [=[Habilitar as configurações avançadas lhe dará acesso a mais opções de configuração. Isso é destinado a pessoas que querem ajustar cada coisa, e não deve ser ativado por padrão, pois aumenta as opções. + +]=] +L["Energy"] = "Energia" +L["Enlarge auras for"] = [=[Ampliar auras para + +]=] +L["Error"] = "Erro" +L["Essence"] = "Essência" +L["Events"] = "Eventos" +L["Events that should be used to trigger an update of this tag. Separate each event with a single space."] = [=[Eventos que devem ser usados para disparar uma atualização dessa marca. Separe cada evento com um único espaço. + +]=] +L["Everywhere else"] = [=[Em qualquer outro lugar + +]=] +L["Export"] = "Exportar" +L["Fades out the unit frames of people who are not within range of you."] = [=[Desaparece os quadros unitários de pessoas que não estão ao seu alcance. + +]=] +L["Failed to import layout, error:|n|n%s"] = [=[Falha ao importar layout, erro:|n|n%s + +]=] +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "Falha ao carregar ShadowedUF_Options, impossível abrir configuração. Erro reportado: %s" +L["Failed to save tag, error:|n %s"] = [=[Falha ao salvar a tag, erro:|n %s + +]=] +L["Female"] = "Fêmea" +L["Filter type"] = "Tipo de filtro" +L["Filtering both buffs and debuffs"] = [=[Filtrando buffs e debuffs + +]=] +L["Filtering buffs only"] = [=[Apenas buffs de filtragem + +]=] +L["Filtering debuffs only"] = [=[Filtrando apenas debuffs + +]=] +L["Filters"] = "Filtros" +L["Finished cast"] = "Lançamento finalizado" +L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."] = [=[Sinaliza a tag para atualização frequente, ela atualizará a tag em um temporizador, independentemente de qualquer disparo de eventos. + +]=] +L["Flight"] = "Voo" +L["Flips coloring so the bar color is shown as the background color and the background as the bar"] = [=[Inverte a coloração para que a cor da barra seja mostrada como a cor do plano de fundo e o plano de fundo como a barra + +]=] +L["Focus"] = "Foco" +L["Focus Target"] = [=[Alvo de foco + +]=] +L["Font"] = "Fonte" +L["Food"] = "Alimento" +L["For configuring aura indicators on unit frames."] = [=[Para configurar indicadores de aura em quadros unitários. + +]=] +L["For target/focus"] = [=[Para o alvo/foco + +]=] +L["Forces a static color to be used for the background of all bars"] = [=[Força uma cor estática a ser usada para o plano de fundo de todas as barras + +]=] +L["Frame"] = "Quadro" +L["Frame alpha when you are out of combat while having no target and 100% mana or energy."] = "Quadro alfa quando você está fora de combate sem ter alvo e 100% de mana ou energia." +L["Frame alpha while this unit is in combat."] = "Quadro alfa enquanto esta unidade está em combate." +L["Frames"] = "Quadros" +L["Friendly"] = "Amigável" +L["Fuel"] = "Combustivel" +L["Full size after"] = "Tamanho completo depois" +L["Full size before"] = [=[Tamanho completo antes + +]=] +L["Fury"] = "Fúria" +L["General"] = "Geral" +L["General configuration to all enabled units."] = [=[Configuração geral para todas as unidades habilitadas. + +]=] +L["General threat situation"] = [=[Situação geral de ameaça + +]=] +L["Ghost"] = "Fantasma" +L["Ghoul bar"] = "Barra de fantasmas" +L["Global"] = "Global" +L["Global configurating will let you mass enable or disable aura groups for multiple units at once."] = [=[A configuração global permitirá que você habilite ou desabilite grupos de aura em massa para várias unidades de uma só vez. + +]=] +L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"] = [=[Marca de verificação dourada - Ativada nesta zona / Marca de verificação cinzenta - Desativada nesta zona / Sem marca de verificação - Utilize as predefinições da unidade + +]=] +L["Green (<30% HP)"] = "Verde (<30% HP)" +L["Group %d"] = "Grupo %d" +L["Group by"] = "Agrupar por" +L["Group number"] = "Grupo número" +L["Group row spacing"] = [=[Espaçamento entre linhas de grupo + +]=] +L["Groups"] = "Grupos" +L["Groups per row"] = [=[Grupos por linha + +]=] +L["Groups to show"] = [=[Grupos a mostrar + +]=] +L["Growth"] = "Crescimento" +L["Guild name"] = [=[Nome da guilda + +]=] +L["Half health"] = "Metade da saúde" +L["Has Aggro"] = [=[Tem Aggro + +]=] +L["Heal absorb"] = [=[Curar absorver + +]=] +L["Heal Absorb (Absolute)"] = [=[Curar Absorver (Absoluto) + +]=] +L["Heal Absorb (Short)"] = [=[Curar Absorver (Curto) + +]=] +L["Heal absorbs"] = [=[Curar absorve + +]=] +L["Healing absorb"] = "Cura absorver" +L["Health"] = "Vida" +L["Health bar"] = "Barra de Vida" +L["Health bar color for friendly units."] = [=[Cor da barra de saúde para unidades amigáveis. + +]=] +L["Health bar color for hostile units."] = [=[Cor da barra de saúde para unidades hostis. + +]=] +L["Health bar color for neutral units."] = [=[Cor da barra de saúde para unidades neutras. + +]=] +L["Health bar color for units with aggro."] = [=[Cor da barra de saúde para unidades com aggro. + +]=] +L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."] = [=[Cor da barra de saúde para usar para unidades hostis que você não pode atacar, usada para coloração de reação. + +]=] +L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."] = [=[Cor da barra de saúde usada como a cor de transição para 100% -> 0% em jogadores, bem como quando seu animal de estimação está levemente infeliz. + +]=] +L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."] = [=[Cor da barra de saúde usada como a cor de transição para 100% -> 50% nos jogadores, bem como quando seu animal de estimação está feliz. + +]=] +L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."] = [=[Cor da barra de saúde usada como a cor de transição para 50% -> 0% em jogadores, bem como quando seu animal de estimação está muito infeliz. + +]=] +L["Health color"] = [=[Cor de saúde + +]=] +L["Health percent"] = [=[Percentual de saúde + +]=] +L["Height"] = "Altura" +L["Help"] = "Ajuda" +L["Hide %s"] = "Ocultar %s" +L["Hide %s frames"] = "Ocultar %s" +L["Hide bar when empty"] = [=[Ocultar barra quando vazia + +]=] +L["Hide Blizzard"] = "Ocultar Blizzard" +L["Hide in <=5-man raids"] = [=[Esconder-se em < ataques de 5 homens + +]=] +L["Hide in >5-man raids"] = "Ocultar >5man raid" +L["Hide in any raid"] = [=[Esconda-se em qualquer ataque + +]=] +L["Hide tooltips in combat"] = [=[Ocultar dicas de ferramentas em combate + +]=] +L["Hides the cast bar if there is no cast active."] = "Oculta a barra de lançamento se não houver lançamento ativo." +L["Hides the power bar unless the class has mana."] = [=[Oculta a barra de energia, a menos que a classe tenha mana. + +]=] +L["Hiding and showing various aspects of the default UI such as the player buff frames."] = [=[Ocultar e mostrar vários aspectos da interface do usuário padrão, como os quadros de buff do jogador. + +]=] +L["High"] = "Alta" +L["High health"] = "Saúde alta" +L["Highlight"] = [=[Destacar + +]=] +L["Highlight units that are "] = [=[Destaque as unidades que são + +]=] +L["Highlight units that are debuffed with something you can cure."] = [=[Destaque as unidades que são debuffed com algo que você pode curar. + +]=] +L["Highlight units that are rare."] = [=[Destaque as unidades que são raras. + +]=] +L["Highlight units that have aggro on any mob."] = [=[Destaque as unidades que têm aggro em qualquer mob. + +]=] +L["Highlight units that you are targeting or have focused."] = "Destaque as unidades que você está almejando ou focou." +L["Highlight units when you mouse over them."] = "Destaque as unidades ao passar o mouse sobre elas." +L["Holy power"] = "Poder sagrado" +L["Holy Power"] = "Poder Sagrado" +L["Hostile"] = "Hostil" +L["How close the frame should clip with the border."] = [=[Quão perto o quadro deve ser cortado com a borda. + +]=] +L["How far the background should be from the unit frame border."] = [=[A distância entre o plano de fundo e a borda do quadro da unidade. + +]=] +L["How large the background should tile"] = [=[Qual deve ser o tamanho do plano de fundo + +]=] +L["How large the edges should be."] = [=[Quão grandes devem ser as bordas. + +]=] +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."] = [=[Quantas auras por uma coluna, por exemplo, inserir duas delas criará duas linhas que são preenchidas até o que for definido como por linha. + +]=] +L["How many auras to show in a single row."] = "Quantas auras para exibir em uma coluna simples" +L["How many Chi points you currently have."] = "Quantos pontos de Chi você tem no momento" +L["How many groups should be shown per row."] = [=[Quantos grupos devem ser mostrados por linha. + +]=] +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!"] = [=[Quantas pessoas estão ajudando a unidade, por exemplo, se você colocar isso em si mesmo, mostrará quantas pessoas estão mirando seu alvo. Isso inclui você na contagem! + +]=] +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!"] = [=[Quantas pessoas em sua invasão estão mirando a unidade, por exemplo, se você colocar isso em si mesmo, mostrará quantas pessoas estão mirando em você. Isso inclui você na contagem! + +]=] +L["How many rows total should be used, rows will be however long the per row value is set at."] = [=[Quantas linhas o total deve ser usado, as linhas serão independentemente do tempo em que o valor por linha estiver definido. + +]=] +L["How many seconds a totem has left before disappearing."] = [=[Quantos segundos falta para um totem desaparecer. + +]=] +L["How many seconds before a rune recharges."] = [=[Quantos segundos antes de uma runa recarregar. + +]=] +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."] = [=[Quantos segundos entre as atualizações.|n[AVISO] Ao definir a frequência como 0, ele atualizará cada redesenho de quadro, se você quiser desativar a atualização frequente desmarque a opção não defina isso como 0. + +]=] +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."] = [=[Quanto da altura total dos quadros esta barra deve obter, este é um valor ponderado, quanto maior ele é, mais ele fica. + +]=] +L["How much spacing should be between each new row of groups."] = "Quanto de espaço entre cada nova célula de grupo" +L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."] = [=[Quanto espaçamento deve ser fornecido entre todas as barras dentro de um quadro unitário, valores negativos os afastam mais, valores positivos os aproximam. 0 para nenhum espaçamento. + +]=] +L["How much weight this should use when figuring out the total text width."] = [=[Quanto peso isso deve usar ao descobrir a largura total do texto. + +]=] +L["How the frames should grow when a new column is added."] = [=[Como os quadros devem crescer quando uma nova coluna é adicionada. + +]=] +L["How the rows should grow when new group members are added."] = [=[Como as linhas devem crescer quando novos membros do grupo são adicionados. + +]=] +L["How you want this aura to be anchored to the unit frame."] = [=[Como você quer que essa aura seja ancorada ao quadro da unidade. + +]=] +L["Icon Size"] = [=[Tamanho do ícone + +]=] +L["If multiple auras are shown in the same indicator, the higher priority one is shown first."] = [=[Se várias auras são mostradas no mesmo indicador, a prioridade mais alta é mostrada primeiro. + +]=] +L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."] = "Se o nome for inserido, ele deverá ser exato, pois diferencia maiúsculas de minúsculas. Alternativamente, você pode usar o ID do feitiço." +L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."] = [=[Se a unidade tiver uma proteção de absorção de danos sobre eles, ela mostrará o valor absoluto de absorção, caso contrário, o nome da unidade. + +]=] +L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."] = [=[Se a unidade tiver curados chegando, ela mostrará o valor absoluto de cura de entrada, caso contrário, mostrará o nome da unidade. + +]=] +L["If the unit is a player then class is returned, if it's a NPC then the creature type."] = "Se a unidade for um jogador, a classe será retornada; se for um NPC, o tipo de criatura." +L["If the unit is a player then race is returned, if it's a NPC then the creature type."] = "Se a unidade for um jogador, a raça será retornada; se for um NPC, o tipo de criatura." +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."] = [=[Se você não fizer isso, você não poderá usar nenhum recurso de ponto de combinação (Chi, Holy Power, Combo Points, Aura Points, etc) até que você faça isso. + +]=] +L["Imp & Dreadstalker bar"] = "Barra Diabrete e Espreitadores do Medo" +L["Import"] = "Importar" +L["Import unit frame positions"] = [=[Importar posições de quadro de unidade + +]=] +L["Import visibility settings"] = [=[Importar configurações de visibilidade + +]=] +L["Inactive alpha"] = "Alfa inativo" +L["Incoming absorb"] = "Absorção de entrada" +L["Incoming absorbs"] = "Absorções recebidas" +L["Incoming heal"] = [=[Cura recebida + +]=] +L["Incoming heal (Absolute)"] = [=[Cura de entrada (Absoluta) + +]=] +L["Incoming heal (Percent)"] = "Cura recebida (porcentagem)" +L["Incoming heal (Short)"] = "Cura recebida (curta)" +L["Incoming heal/Name"] = [=[Recebimento de cura/Nome + +]=] +L["Incoming heals"] = [=[Recebimento de curas + +]=] +L["Index"] = "Índice" +L["Indicator color"] = [=[Cor do indicador + +]=] +L["Indicator for the current pet happiness."] = [=[Indicador da felicidade atual do animal de estimação. + +]=] +L["Indicator name"] = [=[Nome do indicador + +]=] +L["Indicator this aura should be displayed in."] = [=[Indicador em que essa aura deve ser exibida. + +]=] +L["Indicators"] = "Indicadores" +L["Insanity"] = "Insanidade" +L["Inset"] = "Inserir" +L["Inside Bottom Left"] = [=[Dentro do canto inferior esquerdo + +]=] +L["Inside Bottom Right"] = [=[Dentro do canto inferior direito + +]=] +L["Inside Center"] = [=[Dentro do Centro + +]=] +L["Inside Center Left"] = [=[Dentro do centro esquerdo + +]=] +L["Inside Center Right"] = [=[Por dentro do centro-direita + +]=] +L["Inside Top Left"] = [=[Dentro do canto superior esquerdo + +]=] +L["Inside Top Right"] = [=[Por dentro do canto superior direito + +]=] +L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."] = [=[Em vez de mostrar uma cor sólida dentro do indicador, o ícone da aura será mostrado. + +]=] +L["Interrupted"] = "Interrompido" +L["Invalid interval entered, must be a number."] = [=[Intervalo inválido inserido, deve ser um número. + +]=] +L["Invalid spell \"%s\" entered."] = "Feitiço \"%s\" inválido digitado." +L["Invert colors"] = "Inverter cores" +L["Layout manager"] = "Gerenciador de Visual" +L["Leader / Assist"] = [=[Líder / Auxiliar + +]=] +L["Left"] = "Esquerdo" +L["Left Bottom"] = "Botão esquerdo" +L["Left Center"] = [=[Centro esquerdo + +]=] +L["Left text"] = [=[Texto à esquerda + +]=] +L["Left Top"] = [=[Topo esquerdo + +]=] +L["Let's you modify the base font size to either make it larger or smaller."] = [=[Vamos modificar o tamanho da fonte base para torná-lo maior ou menor. + +]=] +L["Level"] = "Nível" +L["Level %s - %s: %s/%s (%.2f%% done)"] = "Nível %s - %s: %s/%s (%.2f%% atingido)" +L["Level %s - %s: %s/%s (%.2f%% done), %s rested."] = "Nível %s - %s: %s/%s (%.2f%% done), %s restante." +L["Level (Colored)"] = [=[Nível (Colorido) + +]=] +L["Level without any coloring."] = [=[Nível sem qualquer coloração. + +]=] +L["Light"] = "Luz" +L["Link"] = "Link" +L["Link from"] = [=[Link de + +]=] +L["Link to"] = [=[Link para + +]=] +L["Linked spells"] = [=[Feitiços vinculados + +]=] +L["Lock frames"] = [=[Quadros de bloqueio + +]=] +L["Locks the unit frame positionings hiding the mover boxes."] = [=[Bloqueia os posicionamentos do quadro da unidade ocultando as caixas do movimentador. + +]=] +L["Low health"] = [=[Baixa saúde + +]=] +L["Maelstrom"] = "Voragem" +L["Main Assist"] = [=[Assistência Principal + +]=] +L["Main Assist Target"] = [=[Alvo de assistência principal + +]=] +L["Main Assist Target of Target"] = [=[Alvo de Assistência Principal do Alvo + +]=] +L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."] = [=[As Assistências Principais são definidas pelo sistema Main Assist da Blizzard ou mods que o utilizam. + +]=] +L["Main Tank"] = [=[Tanque Principal + +]=] +L["Main Tank Target"] = [=[Alvo principal do tanque + +]=] +L["Main Tank Target of Target"] = [=[Tanque Principal Alvo do Alvo + +]=] +L["Main Tank's are set through the Raid frames, or through selecting the Tank role."] = [=[Os tanques principais são definidos através dos quadros de Raid ou através da seleção da função de tanque. + +]=] +L["Male"] = "Masculino" +L["Mana"] = "Mana" +L["Manage Aura Filters"] = [=[Gerenciar filtros Aura + +]=] +L["Management"] = "Gerenciamento" +L["Manual position"] = "Posição Manual" +L["Master Looter"] = [=[Mestre Looter + +]=] +L["Max columns"] = "Máximo de colunas" +L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."] = "Saúde máxima, usa um formato curto, 17750 é formatado como 17,7k, valores abaixo de 10.000 são formatados como estão." +L["Max HP (Absolute)"] = [=[HP máximo (absoluto) + +]=] +L["Max HP (Short)"] = [=[HP máximo (curto) + +]=] +L["Max power (Absolute)"] = [=[Poder máximo (Absoluta) + +]=] +L["Max power (Short)"] = "Poder máximo (curta)" +L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."] = "Poder máximo, usa um formato curto, 16.000 é formatado como 16k, valores abaixo de 10.000 são formatados como estão." +L["Max rows"] = "Máximo de linhas" +L["Medium"] = "Média" +L["Minion"] = "Lacaio" +L["Miscellaneous"] = "Miscelânea" +L["Missing HP (Short)"] = [=[HP ausente (curto) + +]=] +L["Missing power (Short)"] = "Falta de energia (curto)" +L["Monochrome Outline"] = [=[Contorno monocromático + +]=] +L["Mushroom bar"] = "Barra de cogumelos" +L["Mushrooms"] = "Cogumelos" +L["Name"] = "Nome" +L["Name (Abbreviated)"] = "Nome" +L["Name of a friendly spell to check range."] = "Nome de um feitiço amigável para verificar o alcance." +L["Neutral"] = "Neutro" +L["Never (Disabled)"] = "Never (desabilitado)" +L["New aura group"] = [=[Novo grupo de aura + +]=] +L["New filter"] = "Novo Filtro" +L["None"] = "Nenhum" +L["None (Disabled)"] = [=[Nenhum (desativado) + +]=] +L["NPCs only"] = [=[Somente NPCs + +]=] +L["Off:%s"] = [=[Desativado:%s + +]=] +L["Offline"] = [=[Offline + +]=] +L["Offline timer"] = "Tempo desconectado" +L["Ok"] = "ok" +L["On %s units"] = [=[Em unidades %s + +]=] +L["On aggro"] = [=[No aggro + +]=] +L["On curable debuff"] = [=[Sobre debuff curável + +]=] +L["On elite mobs"] = "Em mobs de elite" +L["On Friendly Units"] = [=[Em Unidades Amigáveis + +]=] +L["On Hostile Units"] = [=[Sobre unidades hostis + +]=] +L["On mouseover"] = [=[Ao passar o mouse + +]=] +L["On rare mobs"] = "Em mobs raros" +L["Only active this aura inside an indicator if the group member does not have the aura."] = [=[Somente ative essa aura dentro de um indicador se o membro do grupo não tiver a aura. + +]=] +L["Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras."] = [=[Aplique apenas os filtros selecionados aos buffs em unidades amigáveis e debuffs em unidades hostis e, caso contrário, mostre todas as auras. + +]=] +L["Only auras you specifically cast will be shown."] = [=[Apenas as auras que você especificamente escalar serão mostradas. + +]=] +L["Only show if missing"] = [=[Mostrar somente se faltar + +]=] +L["Only show self cast auras"] = "Mostrar apenas auras auto-lançadas" +L["Only show when mana"] = "Mostrar apenas quando a mana" +L["Or you can set a position manually"] = [=[Ou você pode definir uma posição manualmente + +]=] +L["Order"] = "Ordenar" +L["Other Party/Phase Status"] = [=[Status de outra parte/fase + +]=] +L["Out of range alpha"] = [=[Alfa fora do alcance + +]=] +L["Outline"] = "Contorno" +L["Outside bar limit"] = "Fora da barra limite" +L["Override background"] = [=[Substituir plano de fundo + +]=] +L["Override color"] = [=[Substituir cor + +]=] +L["Override list"] = [=[Lista de substituição + +]=] +L["Override list filters"] = [=[Substituir filtros de lista + +]=] +L["Override lists"] = [=[Substituir listas + +]=] +L["Pain"] = "Dor" +L["Party"] = "Grupo" +L["Party frames are hidden while in a raid group with more than 5 people inside."] = "Os frames do grupo ficam ocultos em um grupo de ataque com mais de 5 pessoas dentro." +L["Party frames are hidden while in any sort of raid no matter how many people."] = "Os frames do grupo ficam ocultos durante qualquer tipo de ataque, não importa quantas pessoas." +L["Party instances"] = "Instâncias grupo" +L["Party Pet"] = "Grupo Pet" +L["Party Target"] = "Grupo Alvo" +L["Party Target of Target"] = "Grupo Alvo do Alvo" +L["Party ToT"] = "Grupo ToT" +L["Per column"] = "Por coluna" +L["Per row"] = [=[Por linha + +]=] +L["Percent HP"] = [=[Porcentagem de HP + +]=] +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."] = [=[Porcentagem da saúde atual dos jogadores que está sendo curada, se eles têm 100.000 saúde total e 15.000 está chegando, então 15% é mostrado. + +]=] +L["Percent power"] = "Poder percentual" +L["Percentage of width the portrait should use."] = [=[Porcentagem de largura que o retrato deve usar. + +]=] +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."] = [=[Valor percentual de até onde fora do quadro da unidade a barra de integridade absorvida pode ir. 130% significam que vai 30% para fora do quadro, 100% significam que não vai para fora. + +]=] +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."] = [=[Valor percentual de até onde a barra de absorção de entrada pode ir fora do quadro da unidade. 130% significam que vai 30% para fora do quadro, 100% significam que não vai para fora. + +]=] +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."] = [=[Valor percentual de até onde a barra de recuperação de entrada pode ir fora do quadro da unidade. 130% significa que vai 30% para fora do quadro, 100% significa que não vai para fora. + +]=] +L["Pet"] = [=[Animal de estimação + +]=] +L["Pet Battle"] = [=[Batalha de Animais de Estimação +]=] +L["Pet Happiness"] = "Felicidade do animal de estimação" +L["Pet Target"] = [=[Alvo Pet + +]=] +L["Player"] = "Jogador" +L["player alt. power"] = [=[poder alt. + +]=] +L["player cast bar"] = "barra de lançamento do jogador" +L["Player Class"] = [=[Classe do jogador + +]=] +L["player power frames"] = [=[quadros de poder do jogador + +]=] +L["Player threat"] = [=[Ameaça do jogador + +]=] +L["Players only"] = [=[Apenas jogadores + +]=] +L["Players will be colored by class."] = [=[Os jogadores serão coloridos por classe. + +]=] +L["Point"] = "Ponto" +L["Portrait"] = "Retrato" +L["Portrait type"] = [=[Tipo de retrato + +]=] +L["Position"] = "Posição" +L["Positioning"] = [=[Posicionamento + +]=] +L["Power"] = "Poder" +L["Power bar"] = "Barra de poder" +L["Power Type"] = "Tipo de poder" +L["Prevents unit tooltips from showing while in combat."] = [=[Impede que as dicas de ferramentas da unidade sejam exibidas durante o combate. + +]=] +L["Priest mana bar"] = [=[Sacerdote mana bar + +]=] +L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."] = [=[Os principais meios de colorir a barra de saúde, cor no aggro e cor por reação substituirão isso, se necessário. + +]=] +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."] = [=[Meios primários de colorir a barra de energia. Colorir por classe só se aplica a jogadores, para não-jogadores será padrão para o tipo de poder. + +]=] +L["Prioritize buffs"] = [=[Priorize os buffs + +]=] +L["Priority"] = "Prioridade" +L["Programming in Lua"] = [=[Programação em Lua + +]=] +L["PvP Flag"] = "Bandeira JxJ" +L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."] = [=[Indicador de bandeira PVP, Horda para Horda sinalizado pvpers e Alliance for Alliance sinalizado pvpers. + +]=] +L["PvP Flags"] = [=[Sinalizadores PvP + +]=] +L["PVP timer"] = [=[Temporizador PVP + +]=] +L["PVP:%s"] = [=[PVP:%s + +]=] +L["Quest Boss"] = [=[Chefe da Missão + +]=] +L["Race"] = "Raça" +L["Race (Smart)"] = "Raça (inteligente)" +L["Rage"] = "Raiva" +L["Raid"] = "RAID" +L["Raid assisting unit"] = [=[Unidade de assistência a ataques + +]=] +L["Raid frames are hidden while in a raid group with 5 or less people inside."] = [=[Os quadros de invasão são escondidos enquanto estão em um grupo de invasão com 5 ou menos pessoas dentro. + +]=] +L["Raid instances"] = [=[Instâncias de RAID + +]=] +L["Raid Misc"] = [=[Invasão Misc + +]=] +L["Raid pet"] = "Raid pet" +L["Raid Role"] = [=[Função Raid + +]=] +L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."] = [=[Indicador de função de raid, adiciona um indicador de escudo para tanques principais e um ícone de espada para assistências principais. + +]=] +L["Raid Target"] = "Raid Alvo" +L["Raid target indicator."] = [=[Indicador de alvo de raid. +]=] +L["Raid targeting unit"] = "Unidade de alvo de raid" +L["Range Checker"] = [=[Verificador de Alcance + +]=] +L["Range indicator"] = [=[Indicador de intervalo + +]=] +L["Rare"] = "Raro" +L["Rare Elite"] = [=[Elite Rara + +]=] +L["Rare indicator"] = [=[Indicador raro + +]=] +L["Rather than bars filling from left -> right, they will fill from bottom -> top."] = [=[Em vez de barras preenchendo da esquerda > da direita, elas serão preenchidas de baixo para cima > de cima. + +]=] +L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."] = [=[Código de cor de reação, use [reactcolor][name][close] para colorir o nome das unidades por sua reação. + +]=] +L["Reaction color tag"] = "Etiqueta de cor de reação" +L["Ready Status"] = [=[Status Pronto + +]=] +L["Ready status of group members."] = [=[Status pronto dos membros do grupo. + +]=] +L["Red (>70% HP)"] = "Vermelho (>70% Vida)" +L["Relative point"] = "Ponto relativo" +L["Resources"] = "Recursos" +L["Resurrect Status"] = [=[Status de ressuscitar + +]=] +L["Returns + if the unit is an elite or rare elite mob."] = "Retorna + se a unidade for um mob de elite ou de elite rara." +L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."] = [=[Retorna um código de cores da situação de ameaça com seu alvo: Vermelho para Aggro, Laranja para Alta ameaça e Amarelo para ter cuidado. + +]=] +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."] = [=[Retorna um código de cores da sua situação geral de ameaça em todas as unidades: Vermelho para Aggro, Laranja para Alta ameaça e Amarelo para ficar atento. + +]=] +L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."] = [=[Retorna uma porcentagem de ameaça dimensionada do seu aggro em seu alvo atual, sempre de 0 a 100%. + +]=] +L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."] = [=[Retorna a integridade atual como uma porcentagem, se a unidade estiver morta ou offline do que isso é mostrado. + +]=] +L["Returns current power as a percentage."] = "Retorna o poder atual como uma porcentagem." +L["Returns Rare if the unit is a rare or rare elite mob."] = "Retorna Raro se a unidade for um mob raro ou raro de elite." +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."] = "Retorna o texto com base na situação de ameaça geral da unidade: Aggro para Aggro, Alto para estar perto de receber aggro e Médio como um aviso para ser cauteloso.|nIsso não pode ser usado em alvo de alvo ou foco em tipos de unidades." +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."] = "Retorna texto com base na sua situação de ameaça geral em todas as unidades: Aggro para Aggro, Alto por estar perto de puxar o aggro e Médio como um aviso geral." +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."] = "Retorna o texto com base na situação de ameaça com seu alvo: Aggro para Aggro, Alto por estar perto de receber aggro e Médio como um aviso geral para ser cauteloso." +L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."] = "Retorna o código de cores com base no nível das unidades comparado ao seu. Se você não puder atacá-los, nenhuma cor será retornada." +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."] = "Retorna o código de cores para a situação de ameaça das unidades em geral: Vermelho para Aggro, Laranja para Alta ameaça e Amarelo para cuidado." +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."] = "Retorna a porcentagem de ameaça escalonada para a unidade. Se você colocar isso em um membro do grupo, verá a porcentagem de quão perto ele está de receber qualquer mob hostil. Sempre 0 - 100%.|nIsso não pode ser usado em tipos de unidades de alvo ou alvo de foco." +L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."] = "Retorna a forma atual da unidade se ela for druida, Gato para Forma de Gato, Moonkin para Moonkin e assim por diante." +L["Returns the units sex."] = [=[Retorna as unidades de sexo. + +]=] +L["Reverse fill"] = [=[Preenchimento reverso + +]=] +L["Right"] = "Certo" +L["Right Bottom"] = [=[Parte inferior direita + +]=] +L["Right Center"] = [=[Centro Direito: + +]=] +L["Right text"] = [=[Texto direito + +]=] +L["Right Top"] = [=[Topo direito + +]=] +L["Role the unit is playing."] = [=[Papel que a unidade está desempenhando. + +]=] +L["Row growth"] = [=[Crescimento da linha + +]=] +L["Row offset"] = [=[Deslocamento de linha + +]=] +L["Rune bar"] = [=[Barra de runas + +]=] +L["Rune of Power"] = [=[Runa do Poder + +]=] +L["Rune of Power bar"] = [=[Runa da barra de poder + +]=] +L["Rune Timer"] = [=[Temporizador Runa + +]=] +L["Runes"] = "Runas" +L["Runic Power"] = [=[Poder Rúnico + +]=] +L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."] = [=[O mesmo que [color:sit], exceto que ele só retorna vermelho se você tiver aggro, em vez de transitar de amarelo -> laranja -> vermelho. + +]=] +L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."] = [=[O mesmo que [unit:color:sit], exceto que só retorna vermelho se a unidade tiver aggro, em vez de transitar de amarelo -> laranja -> vermelho. + +]=] +L["Scale"] = "Escala" +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."] = [=[Escala para auras que você lançou ou pode Spellsteal, qualquer número acima de 100% é maior do que o padrão, qualquer número abaixo de 100% é menor do que o padrão. + +]=] +L["Scaled aura size"] = [=[Tamanho da aura em escala + +]=] +L["Scaled threat percent"] = [=[Porcentagem de ameaças dimensionada + +]=] +L["Screen"] = "Tela" +L["Search"] = "Busca" +L["Search tags"] = "Tags de pesquisa" +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."] = [=[Veja a documentação abaixo para obter informações e exemplos sobre a criação de tags, se você quiser apenas informações básicas sobre Lua ou API WoW, consulte os links Programação em Lua e Programação WoW. + +]=] +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."] = [=[Selecione as unidades que você deseja modificar, quaisquer configurações alteradas irão alterar cada unidade que você selecionou. Se você quiser ancorar ou alterar as configurações específicas da unidade raid/party, você precisará fazer isso por meio de suas opções.|n|nShift clique em uma unidade para selecionar tudo/desmarcar tudo. + +]=] +L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."] = [=[Selecionar um texto de marca no painel esquerdo para alterar as marcas. O truncamento de largura, dimensionamento e deslocamentos pode ser feito no painel atual. + +]=] +L["Separate raid frames"] = [=[Quadros de raid separados + +]=] +L["Set Filter Zones"] = [=[Definir zonas de filtro + +]=] +L["Sex"] = "Sexo" +L["Shadow Orbs"] = [=[Orbes de sombra + +]=] +L["Shaman mana bar"] = [=[Xamã mana bar + +]=] +L["Short classification"] = [=[Classificação curta + +]=] +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."] = [=[Classificações curtas, R para Rare, R+ para Rare Elite, + para Elite, B para Boss ou M para Minion nada é mostrado se não forem nenhum desses. + +]=] +L["Short elite indicator"] = [=[Indicador de elite curto + +]=] +L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."] = [=[Versão curta de [druidform], C = Cat, B = Bear, F = Flight e assim por diante. + +]=] +L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."] = [=[Encurtar a absorção de danos, se 13.000 danos forem absorvidos, ele mostrará 13k. + +]=] +L["Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k."] = [=[Encurte o valor de absorção da cura, se 17.000 cicatrizes forem absorvidas, ela mostrará 17k. + +]=] +L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."] = [=[Encurte o valor de cura de entrada, se 13.000 curativos estiverem entrando, ele mostrará 13k. + +]=] +L["Show a background behind the bars with the same texture/color but faded out."] = [=[Mostre um plano de fundo atrás das barras com a mesma textura/cor, mas desbotado. + +]=] +L["Show any other auras"] = [=[Mostrar quaisquer outras auras + +]=] +L["Show as bar"] = [=[Mostrar como barra + +]=] +L["Show aura duration"] = [=[Mostrar duração da aura + +]=] +L["Show aura icon"] = [=[Mostrar ícone de aura + +]=] +L["Show auras stack"] = [=[Mostrar pilha de auras + +]=] +L["Show background"] = [=[Mostrar plano de fundo + +]=] +L["Show boss debuffs"] = [=[Mostrar debuffs chefe + +]=] +L["Show buffs before debuffs when sharing the same anchor point."] = [=[Mostre buffs antes de debuffs ao compartilhar o mesmo ponto de ancoragem. + +]=] +L["Show cast name"] = [=[Mostrar nome do lançamento +]=] +L["Show cast time"] = "Mostrar tempo de lançamento" +L["Show castable on other auras"] = "Mostrar conjurável em outras auras" +L["Show casted by boss"] = "Mostrar casted do chefe" +L["Show curable debuffs"] = [=[Mostrar debuffs curáveis + +]=] +L["Show curable/removable auras"] = [=[Mostrar auras curáveis/removíveis + +]=] +L["Show Heal Absorbs"] = "Exibir cura absorvida" +L["Show icon durations"] = [=[Mostrar durações de ícones + +]=] +L["Show incoming absorbs"] = "Mostrar absorção recebida" +L["Show incoming heals"] = [=[Mostrar curas recebidas + +]=] +L["Show inside"] = "Mostrar por dentro" +L["Show party as raid"] = "Mostrar grupo como raid" +L["Show player in party"] = "Mostrar jogador no grupo" +L["Show your auras"] = [=[Mostre suas auras + +]=] +L["Shows a bar for alternate power info (used in some encounters)"] = [=[Mostra uma barra para informações de energia alternativa (usada em alguns encontros) + +]=] +L["Shows a cooldown wheel on the indicator with how much time is left on the aura."] = [=[Mostra uma roda de resfriamento no indicador com quanto tempo resta na aura. + +]=] +L["Shows AFK, DND or nothing depending on the units away status."] = [=[Mostra AFK, DND ou nada, dependendo do status das unidades afastadas. + +]=] +L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."] = [=[Mostra feedback de combate, última cura que a unidade recebeu, último golpe que errou, resistiu, esquivou-se e assim por diante. + +]=] +L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."] = [=[Mostra a saúde atual e máxima em forma absoluta, 17500 saúde será mostrada como 17500 saúde. + +]=] +L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."] = [=[Mostra a corrente e a potência máxima em forma absoluta, 18000 potência será mostrada como 18000 potência. + +]=] +L["Shows current group number of the unit."] = [=[Mostra o número do grupo atual da unidade. + +]=] +L["Shows current health value in absolute form meaning 15000 health is shown as 15000."] = [=[Mostra o valor de integridade atual em forma absoluta, o que significa que a integridade de 15000 é mostrada como 15000. + +]=] +L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."] = [=[Mostra o valor da potência atual em forma absoluta, 15000 potência será exibida como 1500 ainda. + +]=] +L["Shows debuffs cast by a boss."] = [=[Mostra debuffs lançados por um chefe. + +]=] +L["Shows debuffs that you can cure."] = [=[Mostra debuffs que você pode curar. + +]=] +L["Shows how long an unit has been AFK or DND."] = [=[Mostra há quanto tempo uma unidade é AFK ou DND. + +]=] +L["Shows how long an unit has been offline."] = [=[Mostra há quanto tempo uma unidade está offline. + +]=] +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."] = [=[Mostra quanto tempo até que seu sinalizador PVP caia, não mostrará se o sinalizador está ativado manualmente ou se você está em uma zona hostil.|n|nIsso só funcionará para você mesmo, você não pode usá-lo para ver o tempo restante em sua festa ou invasão. + +]=] +L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."] = [=[Mostra saúde máxima em forma absoluta, 14000 saúde é mostrada como 14000 saúde. + +]=] +L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."] = [=[Mostra a potência máxima em forma absoluta, 13000 potência é mostrada como 13000 potência. + +]=] +L["Shows Offline, Dead, Ghost or nothing depending on the units current status."] = [=[Mostra Offline, Morto, Ghost ou nada, dependendo do status atual das unidades. + +]=] +L["Shows that a NPC is a boss for a quest."] = [=[Mostra que um NPC é um chefe para uma missão. + +]=] +L["Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000."] = [=[Mostra o dano escalonado absoluto, se 16.000 danos são escalonados, mostra 16.000. + +]=] +L["Shows the current staggered damage, if 12,000 damage is staggered, shows 12k."] = [=[Mostra o dano escalonado atual, se 12.000 danos forem escalonados, mostra 12k. + +]=] +L["Show's the units guild name if they are in a guild."] = [=[Mostrar é o nome da guilda de unidades se elas estiverem em uma guilda. + +]=] +L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."] = [=[Mostra a integridade das unidades como uma porcentagem arredondada para a primeira casa decimal, o que significa que 61 de 110 saúde é mostrada como 55,4%. + +]=] +L["Shows what kind of pet the unit is for pet battles."] = [=[Mostra que tipo de animal de estimação a unidade é para batalhas de animais de estimação. + +]=] +L["Shows when a party member is in a different phase or another group."] = [=[Mostra quando um membro do grupo está em uma fase diferente ou outro grupo. + +]=] +L["Simple aura filtering by whitelists and blacklists."] = [=[Filtragem de aura simples por whitelists e blacklists. + +]=] +L["Size"] = "Tamanho" +L["Smart Friendly/Hostile Filter"] = [=[Filtro inteligente/hostil + +]=] +L["Smart level"] = [=[Nível inteligente + +]=] +L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."] = [=[Nível inteligente, retorna Boss para chefes, +50 para uma mob de elite de nível 50, ou apenas 80 para um nível 80. + +]=] +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."] = [=[Formatação de número inteligente para [curmaxhp], números abaixo de 1.000.000 são deixados como estão, números acima de 1.000.000 usarão a versão curta, como 1m. + +]=] +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."] = [=[Formatação de número inteligente para [curmaxpp], números abaixo de 1.000.000 são deixados como estão, números acima de 1.000.000 usarão a versão curta, como 1m. + +]=] +L["Solid color to use in the indicator, only used if you do not have use aura icon enabled."] = [=[Cor sólida para usar no indicador, usado somente se você não tiver o ícone de aura de uso ativado. + +]=] +L["Sort method"] = "Método de classificação" +L["Sort order"] = [=[Ordem de classificação + +]=] +L["Sorting"] = [=[Classificação + +]=] +L["Soul Shards"] = [=[Fragmentos de Alma + +]=] +L["Soul shards"] = [=[Fragmentos de alma + +]=] +L["Spacing"] = "Espaçamento" +L["Spacing between each row"] = [=[Espaçamento entre cada linha + +]=] +L["Spell ID %s"] = [=[ID da ortografia %s + +]=] +L["Spell Name"] = [=[Nome do Feitiço + +]=] +L["Spell Name/ID"] = [=[Nome do feitiço/ID + +]=] +L["Spell you want to link to a primary aura, the casing must be exact."] = [=[Feitiço que você deseja vincular a uma aura primária, o invólucro deve ser exato. + +]=] +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."] = [=[Divide quadros de raid em quadros individuais para cada grupo de raid em vez de um único quadro.|nNOTA! Não é possível arrastar cada quadro de grupo individualmente, mas a forma como eles cresce é definida através das opções de crescimento de coluna e linha. + +]=] +L["Stagger"] = [=[Cambalear + +]=] +L["Stagger (Monk)"] = [=[Stagger (Monge) + +]=] +L["Stagger (Monk/Absolute)"] = [=[Stagger (Monge/Absoluto) + +]=] +L["Stagger bar"] = [=[Barra escalonada + +]=] +L["Stagger bar color when the staggered amount is <30% of your HP."] = [=[Escalone a cor da barra quando a quantidade escalonada for <30% do seu HP. + +]=] +L["Stagger bar color when the staggered amount is >30% of your HP."] = [=[Escalone a cor da barra quando a quantidade escalonada for >30% do seu HP. + +]=] +L["Stagger bar color when the staggered amount is >70% of your HP."] = [=[Escalone a cor da barra quando a quantidade escalonada for >70% do seu HP. + +]=] +L["Static"] = "Estática" +L["Statue"] = "Estátua" +L["Statue bar"] = "Barra de estátua" +L["Status"] = "Estado" +L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."] = [=[Indicador de status, mostra se a unidade está atualmente em combate. Para o jogador, também mostrará se você está descansado. + +]=] +L["Stealable/Curable/Dispellable"] = [=[Roubável/Curável/Dissipável + +]=] +L["Style of borders to show for all auras."] = [=[Estilo de bordas para mostrar para todas as auras. + +]=] +L["Summon Pending"] = "Convocação pendente" +L["T"] = "T" +L["Tag list"] = [=[Lista de tags + +]=] +L["Tag name"] = [=[Nome da tag + +]=] +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]."] = [=[Tag que você vai usar para acessar este código, não o enrolar entre colchetes ou parênteses é feito automaticamente. Por exemplo, você digitaria "foobar" e depois acessaria com [foobar]. + +]=] +L["Tags"] = "Tags" +L["Talent spec of your arena opponents."] = [=[Especificação de talento de seus adversários de arena. + +]=] +L["Target"] = "Alvo" +L["Target of Target"] = "Alvo do Alvo" +L["Target of Target of Target"] = "Alvo do Alvo do Alvo" +L["Test Aura"] = [=[Teste Aura + +]=] +L["Test spell"] = [=[Teste de feitiço + +]=] +L["Text"] = "Texto" +L["Text Management"] = "Gerenciamento de texto" +L["Text name"] = [=[Nome do texto + +]=] +L["Text name that you can use to identify this text from others when configuring."] = [=[Nome do texto que você pode usar para identificar esse texto de outras pessoas durante a configuração. + +]=] +L["Text parent"] = "Texto pai" +L["Text/Tags"] = [=[Texto/Tags + +]=] +L["The blacklist \"%s\" already exists."] = [=[A lista negra "%s" já existe. + +]=] +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."] = [=[As caixas de seleção abaixo permitirão que você habilite ou desabilite unidades.|n|n|cffff2020Aviso!|r As unidades Target of Target têm um custo de desempenho mais elevado em comparação com outras unidades. Se você tiver problemas de desempenho, desative essas unidades ou reduza os recursos ativados para essas unidades. + +]=] +L["The override list \"%s\" already exists."] = [=[A lista de substituição "%s" já existe. + +]=] +L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."] = [=[O quadro do jogador não ficará oculto independentemente disso, você terá que desativá-lo manualmente por completo ou por tipo de zona. + +]=] +L["The tag \"%s\" already exists."] = [=[A tag "%s" já existe. + +]=] +L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."] = [=[Os quadros de unidade que você vê são exemplos, não são perfeitos e não mostram todos os dados que normalmente fariam.|n|nVocê pode ocultá-los bloqueando-os através de /shadowuf ou clicando no botão abaixo. + +]=] +L["The whitelist \"%s\" already exists."] = [=[A lista branca "%s" já existe. + +]=] +L["Thick outline"] = [=[Contorno espesso + +]=] +L["Thin outline"] = [=[Contorno fino + +]=] +L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."] = "Essa barra será oculta automaticamente quando você atingir o nível máximo, ou se você não tiver alguma reputação." +L[ [=[This color will be used if the indicator shown is your own, only applies if icons are not used. +Handy 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.]=] ] = [=[Esta cor será usada se o indicador mostrado for seu, só se aplica se os ícones não forem usados. Útil se você quiser saber se um alvo tem um Rejuvenescimento neles, mas você também quer saber se você foi quem lançou o Rejuvenescimento. + +]=] +L["This filter has no aura types set to filter out."] = [=[Esse filtro não tem tipos de aura definidos para filtrar. + +]=] +L["This filter has no auras in it, you will have to add some using the dialog above."] = [=[Este filtro não tem auras nele, você terá que adicionar alguns usando a caixa de diálogo acima. + +]=] +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."] = [=[Este é um bom guia sobre como começar a programar em Lua, enquanto você não precisa ler a coisa toda, é útil para entender o básico de sintaxe Lua e API's. + +]=] +L["This unit depends on another to work, disabling %s will disable %s."] = [=[Essa unidade depende de outra para funcionar, desabilitar %s desabilitará %s. + +]=] +L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."] = [=[Esta unidade tem unidades filhas que dependem dela, você precisa habilitar esta unidade antes de poder habilitar seus filhos. + +]=] +L[ [=[This will be set for your current class only. +If no custom spells are set, defaults appropriate for your class will be used.]=] ] = [=[Isso será definido apenas para sua classe atual. Se nenhum feitiço personalizado for definido, os padrões apropriados para sua classe serão usados. + +]=] +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."] = [=[Isso desativará a detecção automática de quais eventos essa tag precisará, você deve deixar isso desmarcado, a menos que você saiba o que está fazendo. + +]=] +L["This will override all background colorings for bars including custom set ones."] = [=[Isso substituirá todas as colorações de plano de fundo para barras, incluindo as de conjunto personalizado. + +]=] +L["Threat"] = "Ameaça" +L["Threat situation"] = [=[Situação de ameaça + +]=] +L["Tile size"] = [=[Tamanho do bloco + +]=] +L["Timer Text"] = [=[Texto do temporizador + +]=] +L["Top"] = "Topo" +L["Top Center"] = "Topo Centro" +L["Top Left"] = "Topo Esquerdo" +L["Top Right"] = "Topo Direito" +L["Total number of active holy power."] = "Número total de poder sagrado ativo." +L["Total number of active soul shards."] = [=[Número total de fragmentos de alma ativos. + +]=] +L["Total number of combo points you have on your target."] = [=[Número total de pontos de combinação que você tem em seu alvo. + +]=] +L["Totem bar"] = [=[Barra do totem + +]=] +L["Totem Timer"] = [=[Temporizador Totem + +]=] +L["Travel"] = "Viajar" +L["Tree"] = "Árvore" +L["Turns this widget into a bar that can be resized and ordered just like health and power bars."] = [=[Transforma este widget em uma barra que pode ser redimensionada e ordenada assim como as barras de saúde e energia. + +]=] +L["Unattackable hostile"] = [=[Hostil inofensivo + +]=] +L["Unchecking this will completely disable aura indicators for %s."] = [=[Desmarcar isso desabilitará completamente os indicadores de aura para %s. + +]=] +L["Unit color code on aggro"] = [=[Código de cor da unidade no aggro + +]=] +L["Unit colored situation"] = [=[Situação colorida da unidade + +]=] +L["Unit Configuration"] = [=[Configuração da unidade + +]=] +L["Unit faction"] = "Facção da unidade" +L["Unit name"] = [=[Nome da unidade + +]=] +L["Unit name (Class colored)"] = [=[Nome da unidade (Classe colorida) + +]=] +L["Unit name colored by class."] = [=[Nome da unidade colorido por classe. + +]=] +L["Unit scaled threat"] = [=[Ameaça dimensionada pela unidade + +]=] +L["Unit server"] = [=[Servidor de unidade + +]=] +L["Unit server, if they are from your server then nothing is shown."] = [=[Servidor de unidade, se eles são do seu servidor, então nada é mostrado. + +]=] +L["Unit situation name"] = [=[Nome da situação da unidade + +]=] +L["Units"] = "Unidades" +L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."] = [=[Alinhamento de unidades, Thrall retornará Horde, Magni Bronzebeard retornará Alliance. + +]=] +L["Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those."] = [=[Classificação de unidades, Rare, Rare Elite, Elite, Boss ou Minion nada é mostrado se eles não são qualquer um desses. + +]=] +L["Units per column"] = [=[Unidades por coluna + +]=] +L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."] = [=[Unidades de raça, Blood Elf, Tauren, Troll (infelizmente) e assim por diante. + +]=] +L["Units that should have the aura groups settings changed below."] = [=[Unidades que devem ter as configurações de grupos de aura alteradas abaixo. + +]=] +L["Units to change"] = [=[Unidades a trocar + +]=] +L["Unknown"] = "Desconhecido" +L["Unlink frames"] = [=[Desvincular quadros + +]=] +L["Up"] = "Cima" +L["Update interval"] = "Intervalo de atualização" +L["Uses the icon of the totem being shown instead of a status bar."] = [=[Usa o ícone do totem que está sendo mostrado em vez de uma barra de status. + +]=] +L["Using unit settings"] = [=[Usando configurações de unidade + +]=] +L["Various units can be enabled through this page, such as raid or party targets."] = [=[Várias unidades podem ser habilitadas através desta página, como alvos de ataques ou de grupo. + +]=] +L["Vehicle"] = "Veículo" +L["Vehicles"] = "Veículos" +L["Vertical growth"] = [=[Crescimento vertical + +]=] +L["View"] = "Ver" +L["Visibility"] = "Visibilidade" +L["WARNING! ShadowedUF_Indicators has been deprecated as v4 and is now built in. Please delete ShadowedUF_Indicators, your configuration will be saved."] = [=[AVISO! ShadowedUF_Indicators foi preterido como v4 e agora está integrado. Por favor, exclua ShadowedUF_Indicators, sua configuração será salva. + +]=] +L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] = [=[AVISO: Isso desvinculará todos os quadros uns dos outros para que você possa movê-los sem que outro quadro se mova com ele. + +]=] +L["What group this aura belongs to, this is where you will find it when configuring."] = [=[A que grupo pertence essa aura, é aqui que você vai encontrá-la ao configurar. + +]=] +L["What type of auras should be enlarged, use the scaled aura size option to change the size."] = [=[Que tipo de auras deve ser ampliado, use a opção de tamanho de aura dimensionada para alterar o tamanho. + +]=] +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."] = [=[Quando a unidade está com a saúde debilitada, a tag [missinghp] é mostrada, quando eles estão em plena saúde, a tag [name] é mostrada. Isso permite que você veja -1000 quando eles estão faltando 1000 HP, mas seu nome quando eles não estão faltando nenhum. + +]=] +L["When this filter is active, apply the filter to buffs."] = [=[Quando esse filtro estiver ativo, aplique o filtro aos buffs. + +]=] +L["When this filter is active, apply the filter to debuffs."] = [=[Quando esse filtro estiver ativo, aplique o filtro aos debuffs. + +]=] +L["When to color the empty bar by reaction, overriding the default color by option."] = [=[Quando colorir a barra vazia por reação, substituindo a cor padrão por opção. + +]=] +L["When to color the health bar by the units reaction, overriding the color health by option."] = [=[Quando colorir a barra de integridade pela reação das unidades, substituindo a integridade da cor por opção. + +]=] +L["When to show cooldown rings on auras"] = [=[Quando mostrar anéis de resfriamento em auras + +]=] +L["Where inside the frame the text should be anchored to."] = [=[Onde dentro do quadro o texto deve ser ancorado. + +]=] +L["Where to anchor the cast name text."] = [=[Onde ancorar o texto do nome do cast. + +]=] +L["Where to anchor the cast time text."] = [=[Onde ancorar o texto de tempo de transmissão. + +]=] +L["Whether auras you casted should be shown"] = [=[Se as auras que você lançou devem ser mostradas + +]=] +L["Whether to show any auras casted by the boss"] = [=[Se deve mostrar algumas auras lançada pelo chefe + +]=] +L["Whether to show any debuffs you can remove, cure or steal."] = [=[Seja para mostrar algum debuffs que você pode remover, curar ou roubar. + +]=] +L["Whether to show auras that do not fall into the above categories."] = [=[Se deve mostrar auras que não se enquadram nas categorias acima. + +]=] +L["Whether to show buffs that you cannot cast."] = [=[Se mostrar buffs que você não pode lançar. + +]=] +L["Whitelist"] = [=[Lista de permissões + +]=] +L["Whitelist filters"] = [=[Filtros de lista branca + +]=] +L["Whitelists"] = [=[Listas brancas + +]=] +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."] = [=[As listas brancas ocultarão qualquer aura que não esteja no grupo de filtros.|nBlacklists ocultará auras que estão no grupo de filtros.|As listas nOverride ignorarão qualquer filtro e sempre serão mostradas. + +]=] +L["Widget Size"] = [=[Tamanho do widget + +]=] +L["Width"] = "Largura" +L["Width percent"] = [=[Porcentagem de largura + +]=] +L["Width weight"] = [=[Largura peso + +]=] +L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."] = [=[Preencherá a direita > a esquerda ao usar o crescimento horizontal ou a parte superior > inferior ao usar o crescimento vertical. + +]=] +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"] = "Quer saber o que significam todas as guias para a configuração da unidade? Aqui estão algumas informações:|n|n|cfffed000General:|r Retrato, verificador de alcance, fader de combate, realce de borda|n|cfffed000Frame:|r Posicionamento da unidade e ancoragem do quadro|n|cfffed000Bars:|r Saúde, alimentação, barra vazia e fundida e configuração de ponto de combinação|n|cfffed000Tamanho do widget:|r Todas as opções de dimensionamento e ordenação de barras e retratos|n|cfffed000Auras:|r Toda a configuração de aura para ativar/desabilitar/ampliar auto/etc|n|cfffed000Indicadores: |r Toda a configuração do indicador|n|cfffed000Text/Tags:|r Gerenciamento de tags, bem como posicionamento de texto e configurações de largura.|n|n|n*** Opções frequentemente procuradas ***|n|n|cfffed000Quadros de Raid por grupo|r - Configuração da unidade -> Raid -> Raid -> Quadros de raid separados|n|cfffed000Classe colorir:|r Barras -> Saúde da cor por|n|cfffed000Timers em auras:|r Você precisa do OmniCC para isso|n|cfffed000Mostrando/Ocultando quadros de buff padrão:|r Ocultar Blizzard -> Ocultar quadros de buff|n|cfffed000Porcentagem HP/MP texto: |r Guia Tags/Texto, use as tags [percenthp] ou [percentpp]|n|cfffed000Escondendo o partido com base no raid|r - Configuração da unidade -> Party -> Party -> Ocultar em raid de 6 homens/Ocultar em qualquer raid" +L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."] = [=[Funciona da mesma forma que [%s], mas sempre mostra mana e só é mostrado se mana é um poder secundário. + +]=] +L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."] = [=[Funciona da mesma forma que [%s], mas isso só é mostrado se a unidade estiver no formato Cat ou Bear. + +]=] +L["WoW Programming"] = [=[Programação WoW + +]=] +L["WoW Programming is a good resource for finding out what difference API's do and how to call them."] = [=[WoW Programming é um bom recurso para descobrir o que as APIs fazem diferença e como chamá-las. + +]=] +L["X Offset"] = [=[Deslocamento X + +]=] +L["XP/Rep bar"] = [=[Barra XP/Rep + +]=] +L["Y Offset"] = [=[Deslocamento Y + +]=] +L["Yellow (>30% HP)"] = "Amarelo (>30% Vida)" +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."] = "Você pode adicionar texto adicional com tags habilitadas usando essa configuração, observe que qualquer texto adicional adicionado (ou removido) afeta todas as unidades, removendo texto irá redefinir suas configurações também.|n|nLembre-se de que não é possível excluir o texto padrão incluído nas unidades." +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."] = [=[Você pode adicionar novas marcas personalizadas por meio desta página, se quiser alterar quais marcas são usadas no texto, procure na guia Texto para uma configuração de Unidades. + +]=] +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."] = [=[Você pode desativar filtros de aura e grupos para unidades aqui. Por exemplo, você pode definir um grupo de aura que mostre debuffs de DPS para mostrar apenas no destino. + +]=] +L["You can find more information on creating your own custom tags in the \"Help\" tab above."] = [=[Você pode encontrar mais informações sobre como criar suas próprias tags personalizadas na guia "Ajuda" acima. + +]=] +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."] = "Você pode encontrar mais informações sobre como criar suas próprias tags personalizadas na guia \"Ajuda\" acima.|O nSUF tentará detectar automaticamente quais eventos sua tag precisará, portanto, você geralmente não precisa preencher o campo de eventos." +L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] = "Você pode importar outra configuração de usuário do Shadowed Unit Frame inserindo o código de exportação fornecido abaixo. Isso fará o backup do seu layout antigo para \"Importar Backup\".|n|nLevará de 30 a 60 segundos para carregar o seu layout quando você colá-lo, por favor, com paciência." +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."] = [=[Você pode vincular auras usando isso, por exemplo, você pode vincular Mark of the Wild a Gift of the Wild, então se o jogador tiver Mark of the Wild, mas não Gift of the Wild, ele ainda mostrará Mark of the Wild como se tivesse Gift of the Wild. + +]=] +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."] = [=[Você pode substituir qual aura está habilitada por classe, observe que se a aura estiver desabilitada através da listagem principal, suas configurações de classe aqui não serão importantes. + +]=] +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."] = [=[Você pode definir qual quadro de unidade deve usar qual grupo de filtros e em que tipo de zona aqui, se quiser alterar quais auras entram em qual grupo, consulte a opção "Gerenciar grupos de aura". + +]=] +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."] = [=[Você não pode editar esta tag porque é um dos padrões incluídos neste mod. Essa função está aqui para fornecer um exemplo para suas próprias tags personalizadas. + +]=] +L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."] = [=[Você não pode nomear uma marca "%s", os nomes de marca não devem conter colchetes ou parênteses. + +]=] +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."] = [=[Você não tem nenhum filtro deste tipo adicionado ainda, você terá que criar um no painel de gerenciamento antes que esta página seja útil. + +]=] +L["You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf."] = [=[Você entrou em combate, os quadros da unidade foram bloqueados. Uma vez que você deixar o combate, você precisará desbloqueá-los novamente através de /shadowuf. + +]=] +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."] = "Você tem que definir os eventos para disparar, você só pode inserir letras e sublinhados, \"FOO_BAR\" por exemplo é válido, \"APPLE_5_ORANGE\" não é porque contém um número." +L["You must enter a number that is 0 or higher, negative numbers are not allowed."] = "Você precisa por um número, 0 ou maior, número negativos não serão aceitos." +L["You must enter a tag name."] = [=[Você deve inserir um nome de marca. + +]=] +L["You must restart Shadowed Unit Frames."] = [=[Você deve reiniciar os Quadros de Unidade Sombreada. + +]=] +L["You must wrap your code in a function."] = [=[Você deve encapsular seu código em uma função. + +]=] +L["You will need to create an aura filter before you can set which unit to enable aura filtering on."] = [=[Você precisará criar um filtro de aura antes de definir em qual unidade habilitar a filtragem de aura. + +]=] +L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."] = [=[Você precisará fazer um /console reloadui antes que um quadro oculto se torne visível novamente.|O nPlayer e outros quadros de unidade ficam automaticamente ocultos, dependendo se você ativar a unidade em Quadros de Unidade Sombreada. + +]=] +L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] = [=[Seu layout ativo é o perfil usado para backup de importação, isso não pode ser substituído por uma importação. Altere seus perfis para outra coisa e tente novamente. + +]=] +L["Your aura color"] = [=[Sua cor de aura + +]=] +L["Your Auras"] = [=[Suas Auras + +]=] +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"] = [=[Seu código deve ser encapsulado em uma função, por exemplo, se você fosse criar uma tag para retornar o nome das unidades, você faria:|n|nfunction(unit, unitOwner)|nreturn UnitName(unitOwner)|nend + +]=] +L["Zone Configuration"] = "Configuração de Zona" +L["Zone configuration units"] = [=[Unidades de configuração de zona + +]=] + +local ShadowUF = select(2, ...) +ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) diff --git a/localization/ruRU.lua b/localization/ruRU.lua index 4637d5836..1c51c6c1f 100755 --- a/localization/ruRU.lua +++ b/localization/ruRU.lua @@ -1,5 +1,739 @@ -if( GetLocale() ~= "ruRU" ) then return end -local L = {} ---@localization(locale="ruRU", format="lua_additive_table", handle-unlocalized="ignore")@ -local ShadowUF = select(2, ...) -ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) +if( GetLocale() ~= "ruRU" ) then return end +local L = {} +L["%d auras in group"] = "%d ауры в группе" +L["%s (%s): %s/%s (%.2f%% done)"] = "%s (%s): %s/%s (%.2f%% готово)" +L["%s aura groups disabled"] = "%s группы аур отключены" +L["%s frames"] = "%s фреймы" +L["%s member"] = "%s участник" +L["|cff20ff20%s|r units enabled"] = "|cff20ff20%s|r вкл. фреймы" +L["|cffff2020%s|r units disabled"] = "|cffff2020%s|r выкл. фреймы" +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."] = "|cffff2020Внимание!|r Отображение отдельных фреймов можно настроить для каждой зоны. Вне зависимости от настроек ниже." +L["1 aura group disabled"] = "1 группа аур отключена" +L["2D"] = "2D" +L["3D"] = "3D" +L["A"] = "А" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "Сокращение названий объектов у которых оно длиннее чем 10 букв, \"Защитник клана Темных Рун\" станет \"З.к.Т.Рун\" и \"Обыватель из клана Темных Рун\" станет \"О.и.к.Т.Рун\"." +L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."] = "Абсолютное значение поглощения юнитом урона. Если поглощается 10,000 урона - отображается 10,000." +L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."] = "Абсолютное значение поглощения исцеления. Если поглощается 16,000 исцеления - отображается 16,000." +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "Полное значение входящего исцеления, если входящее исцеление проходит на 10,000 оно так и будет отображаться как 10,000." +L["Add"] = "Добавить" +L["Add Aura"] = "Добавить ауру" +L["Add aura"] = "Добавить ауру" +L["Add Indicator"] = "Добавить индикатор" +L["Add link"] = "Добавить ссылку" +L["Add new indicator"] = "Добавить новый индикатор" +L["Add new tag"] = "Добавить новый тег" +L["Add new text"] = "Добавить новый текст" +L["Add Tags"] = "Добавить теги" +L["Adds %s to the list of units to be modified when you change values in this tab."] = "При изменении значения в данной вкладке добавляет %s в список фреймов, подлежащих модификации." +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "Добавляет полосу, отображающую сколько времени осталось до исчезновения вурдалака; используется только если у вас нет постоянного вурдалака." +L["Adds a bar indicating how much time is left on your mushrooms."] = "Добавляет полосу, показывающую, сколько осталось времени до исчезновения грибов." +L["Adds a bar indicating how much time is left on your Rune of Power."] = "Добавляет полосу, показывающую оставшуюся длительность вашей Руны мощи." +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = "Добавляет индикацию на полосе здоровья показывающую сколько урона будет поглощаться." +L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."] = "Добавляет полосу внутри полосы здоровья, указывая количество исцеления, которое персонаж должен получить." +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = "Показывает полосу внутри полосы здоровья, показывающую, сколько лечения кто-то получит." +L["Adds a Stagger bar for Brewmaster Monks."] = "Добавляет индикатор пошатывания для Монахов Хмелеваров" +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "Добавляет пустую полосу, куда вы можете поместить текст." +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "Добавление полоски отображающей количество вашей маны, когда вы находитесь в форме Кошки или Медведя." +L["Adds rune bars and timers before runes refresh to the player frame."] = "Добавляет к рамке игрока полосы рун и таймеры обновления рун." +L["Adds temporary enchants to the buffs for the player."] = "Добавляет временные улучшения/зачарования к баффам игрока." +L["Adds totem bars with timers before they expire to the player frame."] = "Добавляет к рамке игрока полосы тотемов с их таймерами." +L["Advanced"] = "Расширенные" +L["Advanced tag management, allows you to add your own custom tags."] = "Расширенное управление тегами, позволяет вам добавить ваши собственные пользовательские теги." +L["AFK"] = "АФК" +L["AFK status"] = "АФК статус" +L["AFK timer"] = "АФК таймер" +L["AFK:%s"] = "АФК:%s" +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "После того, как вы проделаете экспорт, вы можете передать код, размещенный ниже, другим пользователям Shadowed Unit Frames, и они получат вашу точную расстановку вёрстки фреймов." +L["Aggro"] = "Аггро" +L["All Auras"] = "Все Ауры" +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."] = "Позволяет прикрепить группу ауры к другой, затем вы можете выбрать, где будет прикреплено используя позицию.|n|nИспользуйте это, если вы хотите вернуть вид интерфейса по умолчанию, где положительные и отрицательные эффекты отдельные группы." +L["Allows you to enter a new aura group."] = "Позволяет вам вводить новые группы аур." +L["Alpha to use for bar backgrounds."] = "Прозрачность фона полос." +L["Alpha to use for bar."] = "Прозрачность полосы." +L["Alt. Power"] = "Альт. энергия" +L["Alt. Power bar"] = "Альт. полоса энергии" +L["Alternate power is used for things like quests and dungeons."] = "Альтернативная энергия используемая в квестах, рейдах и подземельях." +L["Alternate Spell Name"] = "Альтернативное название заклинания" +L["Ammo"] = "Боеприпасы" +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."] = "Значение убывания здоровья, если здоровье полное, ничего не отображается. Используется формат сокращения, -18500 отображается как -18.5k, значения ниже 10000 не форматируются." +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."] = "Значение убывания энергии, если энергия полная, ничего не отображается. Используется формат сокращения, -13850 отображается как 13.8k, значения ниже 10000 не форматируются." +L["Anchor point"] = "Точка привязки" +L["Anchor to"] = "Привязка к" +L["Anchor to another frame"] = "Привязка к другой рамке" +L["Anchor to buffs"] = "Привязка к баффам" +L["Anchor to debuffs"] = "Привязка к дебаффам" +L["Are you sure you want to delete this aura?"] = "Вы уверены, что хотите удалить эту ауру?" +L["Are you sure you want to delete this filter?"] = "Вы действительно хотите удалить этот фильтр?" +L["Are you sure you want to delete this indicator?"] = "Вы уверены, что хотите удалить этот индикатор?" +L["Are you sure you want to delete this tag?"] = "Вы действительно хотите удалить этот тег?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "Вы действительно хотите удалить этот текст? Все настройки будут удалены." +L["Arena"] = "Арена" +L["Arena Pet"] = "Питомец на арене" +L["Arena Spec"] = "Специализация на арене" +L["Arena Target"] = "Цель на арене" +L["Arena Target of Target"] = "Цель цели на арене" +L["Arenas"] = "Арены" +L["Ascending"] = "Возрастающий" +L["Assigned Role (DPS/Tank/etc)"] = "Комбо-очки ауры" +L["Aura border style"] = "Стиль границ аур" +L["Aura borders"] = "Границы ауры" +L["Aura Filters"] = "Фильтры аур" +L["Aura filters"] = "Фильтры аур" +L["Aura types to filter"] = "Типы аур для фильтра" +L["Auras"] = "Ауры" +L["Auras matching a criteria will automatically show up in the indicator when enabled."] = "Ауры, соответствующие критериям, будут автоматически отображаться в индикаторе при включении." +L["Automatic Auras"] = "Автоматические ауры" +L["Background"] = "Фон" +L["Background alpha"] = "Прозрачность фона" +L["Background color"] = "Цвет фона" +L["Background/border"] = "Фон/края" +L["Bag indicator for master looters."] = "Индикатор сумки для ответственного за добычу." +L["Bar alpha"] = "Прозрачнос полосы" +L["Bar spacing"] = "Промежуток полос" +L["Bar texture"] = "Текстура полосы" +L["Bars"] = "Полосы" +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."] = "Полосы с порядком выше или ниже, чем порядок полного размера, будут на всю ширину рамки.|n|nПолосы с порядком между этими двумя номерами показаны рядом с портретом." +L["Battleground"] = "Поле боя" +L["Battleground Pet"] = "Дебаффы босса" +L["Battleground Target of Target"] = "ПБ Цель цели" +L["Battlegrounds"] = "Поля боя" +L["Bear"] = "Медведь" +L["BG"] = "ПБ" +L["BG Pet"] = "ПБ Питомец" +L["BG Target"] = "ПБ Цель" +L["BG ToT"] = "ПБ Цель цели" +L["Blacklist"] = "Черный список" +L["Blacklist filters"] = "Фильтр черного списка" +L["Blacklists"] = "Черные списки" +L["Blizzard"] = "Blizzard" +L["Border"] = "Края" +L["Border alpha"] = "Прозрачность края" +L["Border color"] = "Цвет краев" +L["Border highlighting"] = "Подсвечивание краев" +L["Border thickness"] = "Толщина края" +L["Boss"] = "Босс" +L["Boss Auras"] = "Ауры босса" +L["Boss Debuffs"] = "Дебаффы босса" +L["Boss Target"] = "Цель босса" +L["Boss Target of Target"] = "Цель цели босса" +L["Boss ToT"] = "Цель цели босса" +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."] = "Панели боссов для определенных боев, вроде Кровавого совета или битвы на кораблях, вы не увидите их в остальных боях с боссами." +L["Both"] = "Оба" +L["Bottom"] = "Внизу" +L["Bottom Center"] = "Внизу по центру" +L["Bottom Left"] = "Внизу слева" +L["Bottom Right"] = "Внизу справа" +L["buff frames"] = "область баффов" +L["Buffs"] = "Баффы" +L["Cannot find any profiles named \"%s\"."] = "Не удается найти профиль с именем: \"%s\"." +L["Cast"] = "Применение" +L["Cast bar"] = "Полоса применений" +L["Cast icon"] = "Иконка применения" +L["Cast interrupted"] = "Применение прервано" +L["Cast name"] = "Название применения" +L["Cast time"] = "Время применения" +L["Cast uninterruptible"] = "Бесперебойное применение" +L["Casting"] = "Применение" +L["Cat"] = "Кошка" +L["Category"] = "Категория" +L["Center"] = "В центре" +L["Changed profile to %s."] = "Прифиль изменён на: %s." +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = "При получении угрозы, изменяет цвет полосы здоровья на цвет враждебно настроенного существа (красный по умолчанию)." +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."] = "Изменив эту штуку в полосу, вы сможете изменить высоту и порядок как можно изменять полосы здоровье и энергии." +L["Channelling"] = "Направленное" +L["Chi"] = "Чи" +L["Chi Points"] = "Энергия Чи" +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = "Дочерние разделы не могут быть открыты, для этого воспользуйтесь /shadowuf." +L["Class"] = "Класс" +L["Class (Smart)"] = "Класс (Smart)" +L["Class color tag"] = "Тег цвета класса" +L["Class icon"] = "Иконка класса" +L["Class Icon"] = "Иконка класса" +L["Class icon for players."] = "Иконка класса для игроков." +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = "Название класса без окраски, используйте [classcolor][class][close] если вы хотите окрасить название класса." +L["Class Role"] = "Роль класса" +L["Class Specific"] = "Конкретный класс" +L["Class/misc bars"] = "Панели класса\\разные" +L["Classes"] = "Классы" +L["Classification"] = "Классификация" +L["Classifications"] = "Классификации" +L["Clip"] = "Cрезать" +L["Close color"] = "Закрыть цвет" +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = "Код закрытия цвета, предотвращает окраску текста, который вы не хотите раскрашивать." +L["Code"] = "Код" +L["Color by class"] = "Цвет класса" +L["Color by reaction on"] = "Цвет по реакции" +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."] = "Код цвета, основанный на проценте оставшегося здоровья объекта, работает так же, как цвет здоровья по. Только для текста, а не для всей полосы." +L["Color code for general situation"] = "Код цвета общего состояние" +L["Color code for situation"] = "Код цвета для состояния" +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = "Код окраски класса, используйте [classcolor][class][close] если вы хотите чтобы текст класса окрашивался в соответствующий цвет" +L["Color code on aggro"] = "Код цвета угрозы" +L["Color health by"] = "Цвет здоровья по" +L["Color on aggro"] = "Цвет при угрозе" +L["Color on curable debuff"] = "Цвет развеиваемого дефаба" +L["Color power by"] = "Окрашивать силу" +L["Color to use for health bars that are set to be colored by a static color."] = "Цвет, используемый для полос здоровья, которые будут окрашены постоянным цветом." +L["Color to use to show how much damage will be absorbed."] = "Цвет для отображения количества урона, который будет поглощен" +L["Color to use to show how much healing will e absorbed."] = "Цвет для отображения количества исцеления, которое будет поглощено" +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = "Используемый цвет, когда применение не может быть прерванно, этоиспользуется только на PvE существах." +L["Color used when a cast is a channel."] = "Используемый цвет при применении направленного заклинания." +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "Используемый цвет при прерывании применения самим заклинателем или другим объектом." +L["Color used when a cast is successfully finished."] = "Используемый цвет при удачном применении." +L["Color used when an unit is casting a spell."] = "Используемый цвет при применении объектом заклинаний." +L["Colors"] = "Цвета" +L["Column growth"] = "Возрастание колонок" +L["Column spacing"] = "Промежуток колонок" +L["Combat alpha"] = "Прозрачность в бою" +L["Combat fader"] = "Затухание боя" +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."] = "Затухание боя, будет скрывать все ваши рамки, во время бездействия. А во время проявления активности или в бою они будут снова появляться." +L["Combat Status"] = "Статус боя" +L["Combat text"] = "Текст боя" +L["Combat/resting status"] = "Статус боя/отдыха" +L["Combo points"] = "Приемы в серии" +L["Combo Points"] = "Комбо-очки" +L["Configuration to specific unit frames."] = "Настройка конкретных рамок." +L["Create"] = "Создать" +L["Creature type"] = "Тип существа" +L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."] = "Тип создания, выводит надпись Стража Скверны, если это Стража Скверны, Волк, если это Волк и так далее." +L["Cur/Max HP (Absolute)"] = "Тек/макс ЗД (полное)" +L["Cur/Max HP (Short)"] = "Тек/макс ЗД (Коротко)" +L["Cur/Max HP (Smart)"] = "Тек/макс ЗД (Smart)" +L["Cur/Max power (Absolute)"] = "Тек/макс энергии (полное)" +L["Cur/Max power (Druid)"] = "Тек/макс энергии (Друид)" +L["Cur/Max Power (Short)"] = "Тек/макс энергии (коротко)" +L["Cur/Max PP (Smart)"] = "Тек/макс ЗД (Smart)" +L["Curable"] = "Излечимо" +L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."] = "Текущее и максимальное здоровье, используемые параметры [curhp]/[maxhp], также отображается когда игрок умер или вышел из сети." +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "Текущая и максимальная энергия, выглядит как [curpp]/[maxpp]." +L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."] = "Текущее здоровье, используется формат сокращения, 11500 отображается как 11.5k, значения ниже 10000 не форматируются." +L["Current HP (Absolute)"] = "Текущее ЗД (полное)" +L["Current HP (Short)"] = "Текущее ЗД (коротко)" +L["Current power (Absolute)"] = "Текущая энергия (полная)" +L["Current power (Druid)"] = "Текущая энергия (друид)" +L["Current power (Druid/Absolute)"] = "Текущая энергия (друид/полная)" +L["Current Power (Short)"] = "Текущая энергия (коротко)" +L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."] = "Текущая энергия, используется формат сокращения, 12750 отображается как 12.7k, значения ниже 10000 не форматируются." +L["Currently modifying"] = "Текущие изменения" +L["Dark"] = "Тёмный" +L["Dead"] = "Мертв" +L["Debuffs"] = "Дебаффы" +L["Decimal percent HP"] = "Десятичный процент ЗД" +L["Default color"] = "Цвет по умолчанию" +L["Default font color, any color tags inside individual tag texts will override this."] = "Цвет текста по умолчанию, будет замещен другим цветом, если тот будет определен." +L["Deficit/Unit Name"] = "Нехватка/Имя" +L["Delete"] = "Удалить" +L["Delete filter"] = "Удалить фильтр" +L["Delete link"] = "Удалить ссылку" +L["Descending"] = "Убывающий" +L["Disable event discovery"] = "Отключить обнаружение собития" +L["Disable vehicle swap"] = "Отключить смену на транспорт" +L["Disabled"] = "Отключен" +L["Disabled for %s."] = "Отключен для %s." +L["Disabled in %s"] = "Отключить в %s" +L["Disables the unit frame from turning into a vehicle when the player enters one."] = "Отключает преобразование в рамку транспорта, когда игрок в него садится." +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!."] = "Отключение на этой странице отключает модуль пока в %s. Не отключайте модуль, если вы не хотите, чтобы это произошло!." +L["Disabling unit modules in various instances."] = "Отключение модуля рамок в разных вариантах." +L["Documentation"] = "Документация" +L["Don't hide when empty"] = "Не прятать, когда пусто" +L["Don't use a filter"] = "Не использовать фильтр" +L["Down"] = "Вниз" +L["Druid form"] = "Облик друида" +L["Druid form (Short)"] = "Облик друида (коротко)" +L["Druid mana bar"] = "Полоса маны друида" +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."] = "В связи с характером ложных объектов, полоса применения для %s не слишком эффективна и может занять 0.10 сек для отражения изменений в применении." +L["Edge size"] = "Размер контура" +L["Edit tag"] = "Править тег" +L["Editing %s"] = "Правка %s" +L["Elite"] = "Элитный" +L["Empty bar"] = "Пустая полоса" +L["Enable %s"] = "Включить %s" +L["Enable buffs"] = "Включить баффы" +L["Enable debuffs"] = "Включить дебаффы" +L["Enable frequent updates"] = "Включить частое обновление" +L["Enable indicator"] = "Включить индикатор" +L["Enable Indicators"] = "Включить индикаторы" +L["Enable temporary enchants"] = "Временные улучшения/зачарования" +L["Enable units"] = "Включить рамки" +L["Enabled in %s"] = "Включить в %s" +L["Enables configuration mode, letting you move and giving you example frames to setup."] = "Включает режим настройки, давая возможность двигать панели и показывая пример расположения панелей." +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."] = "Включение расширенных настроек, даёт вам доступ к более продвинутым настройкам. (Для опытных пользователей)." +L["Energy"] = "Энергия" +L["Enlarge auras for"] = "Увеличить ауры для" +L["Error"] = "Ошибка" +L["Events"] = "События" +L["Events that should be used to trigger an update of this tag. Separate each event with a single space."] = "События, которые должны использоваться, чтобы вызвать обновление этого тэга. Отделите каждое событие одиночным пробелом." +L["Everywhere else"] = "Где-то еще" +L["Export"] = "Экспорт" +L["Fades out the unit frames of people who are not within range of you."] = "Затемнение рамок игроков, которые находятся в не досягаемости от вас." +L["Failed to import layout, error:|n|n%s"] = "Не удалось импортировать слои, ошибка:|n|n%s" +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "Не удалось загрузить ShadowedUF_Options, невозможно открыть настройки. Ошибка: %s" +L["Failed to save tag, error:|n %s"] = "Не удалось сохранить тег, ошибка:|n %s" +L["Female"] = "Женщина" +L["Filter type"] = "Тип фильтра" +L["Filtering both buffs and debuffs"] = "Фильтрация баффов и дебаффов, вместе" +L["Filtering buffs only"] = "Фильтрация только баффов" +L["Filtering debuffs only"] = "Фильтрация только дебаффов" +L["Filters"] = "Фильтры" +L["Finished cast"] = "Завершенное применение" +L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."] = "Отметить теги для частого обновления, это будет обновлять теги по таймеру независимо от любого события." +L["Flight"] = "Полет" +L["Flips coloring so the bar color is shown as the background color and the background as the bar"] = "Сменить цвета, тоесть цвет полосы будет отображаться как цвет фона, а фон как цвет полосы" +L["Focus"] = "Фокус" +L["Focus Target"] = "Цель фокуса" +L["Font"] = "Шрифт" +L["Food"] = "Еда" +L["For target/focus"] = "Для цели/фокуса" +L["Forces a static color to be used for the background of all bars"] = "Применить использование статического цвета для фона во всех полосах" +L["Frame"] = "Рамка" +L["Frame alpha when you are out of combat while having no target and 100% mana or energy."] = "Прозрачность рамки вне боя, когда у вас нету цели и значение маны или энергии 100%." +L["Frame alpha while this unit is in combat."] = "Прозрачность рамки в бою." +L["Frames"] = "Рамки" +L["Friendly"] = "Дружелюбные" +L["Fuel"] = "Топливо" +L["Full size after"] = "Полный размер после" +L["Full size before"] = "Полный размер до" +L["Fury"] = "Ярость" +L["General"] = "Общее" +L["General configuration to all enabled units."] = "Основные настройки для всех включенных объектов." +L["General threat situation"] = "Состояние общей угрозы" +L["Ghost"] = "Призрак" +L["Global"] = "Основное" +L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"] = "Золотая галочка - включено в этой зоне / Серая галочка - отключено в эетой зоне / Нет галочки - использовать стандартные настройки" +L["Green (<30% HP)"] = "Зеленый (<30% HP)" +L["Group %d"] = "Группа %d" +L["Group by"] = "Групировать по" +L["Group number"] = "Номер группы" +L["Group row spacing"] = "Промежуток групп" +L["Groups"] = "Группы" +L["Groups per row"] = "Групп в ряду" +L["Groups to show"] = "Показ групп" +L["Growth"] = "Возрастание" +L["Guild name"] = "Гильдия" +L["Half health"] = "Половина здоровья" +L["Health"] = "Здоровье" +L["Health bar"] = "Полосы здоровья" +L["Health bar color for friendly units."] = "Цвет полосы здоровья дружелюбных существ/игроков." +L["Health bar color for hostile units."] = "Цвет полосы здоровья враждебных существ/игроков." +L["Health bar color for neutral units."] = "Цвет полосы здоровья равнодушных существ/игроков." +L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."] = "Используемый цвет полосы здоровья для враждебных существ/игроков которых вы не можете атаковать, используемое отображение окраски реакции цели." +L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."] = "Цвет полосы здоровья, как переходный от 100% к 0% на игроках, также когда ваш питомец грустный." +L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."] = "Цвет полосы здоровья, как переходный от 100% к 50% на игроках, также когда ваш питомец счастливый." +L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."] = "Цвет полосы здоровья, как переходный от 50% к 0% на игроках, также когда ваш питомец несчастный." +L["Health color"] = "Цвет здоровья" +L["Health percent"] = "Процент здоровья" +L["Height"] = "Высота" +L["Help"] = "Справка" +L["Hide %s"] = "Скрыть %s" +L["Hide %s frames"] = "Скрыть рамки %s" +L["Hide bar when empty"] = "Скрыть полосу когда она пуста" +L["Hide Blizzard"] = "Скрыть Blizzard" +L["Hide in <=5-man raids"] = "Скрыть в <=5-чел рейдах" +L["Hide in >5-man raids"] = "Скрыть в >5-чел рейдах" +L["Hide in any raid"] = "Скрыть в любом рейде" +L["Hide tooltips in combat"] = "Скрыть подсказки в бою" +L["Hides the cast bar if there is no cast active."] = "Скрывает полосу заклинаний, если нет активного применения заклинания." +L["Hiding and showing various aspects of the default UI such as the player buff frames."] = "Скрывает и показывает различные аспекты стандартного интерфейса, такие как фрейм баффов игрока." +L["High health"] = "Много здоровья" +L["Highlight units that are debuffed with something you can cure."] = "Подсвечивать игрока параженного отрицательным эффектом, который вы можете излечить/рассеять." +L["Highlight units that have aggro on any mob."] = "Подсвечивать игрока, которому угрожает любое существо." +L["Highlight units that you are targeting or have focused."] = "Подсвечивать игрока/существо, на которое вы нацелились или взяли в фокус." +L["Highlight units when you mouse over them."] = "Подсвечивать игрока, когды вы наводите курсор мыши на него." +L["Holy power"] = "Энергия Света" +L["Holy Power"] = "Святая Мощь" +L["Hostile"] = "Враждебные" +L["How close the frame should clip with the border."] = "Установка срезания от края рамки." +L["How far the background should be from the unit frame border."] = "Установка расстояния фона в зависимости от границы рамок." +L["How large the background should tile"] = "Изменение размера мазайки фона." +L["How large the edges should be."] = "Изменение размера контура." +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."] = "Сколько должно отображаться аура в колонке." +L["How many auras to show in a single row."] = "Сколько показывать аур в одном ряду." +L["How many Chi points you currently have."] = "Количество энергии Чи в данный момент." +L["How many groups should be shown per row."] = "Сколько групп будут отображаться в одном ряду." +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!"] = "Сколько игроков помогают цели, например, если вы укажите это для себя, то будет показано сколько игроков выбрали целью вашу цель (включая вас)." +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!"] = "Сколько игроков рейда взяли в цель существо/игрока, нпример, если вы укажите это для себя, то будет показано сколько игроков выбрали целью вас (включая вас)." +L["How many rows total should be used, rows will be however long the per row value is set at."] = "Сколько должно использоваться рядов в общем количестве, все ряды будут одинаковой длины которая установлена в соответствующих опциях." +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."] = "Секунд между обновлениями.|n[Внимание] Установив частоту 0 приведет к перерисовке каждого кадра, если вы хотите отключить частое обновление снимите его не устанавливайте это значение в 0." +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."] = "Общая высота этой полосы в рамке, это взвешенное значение, чем больше значение тем больше она будет." +L["How much spacing should be between each new row of groups."] = "Промежуток между каждым новым рядом группы." +L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."] = "Установка расстояния между всеми полосами внутри фрейма (отрицательные значения перемещают их дальше друг от друга, положительные значения сближают, 0 - без промежутков)." +L["How much weight this should use when figuring out the total text width."] = "Используемое значение, которое определяется от общей ширины текста." +L["How the frames should grow when a new column is added."] = "Установка возрастания рамок, при добавлении новой колонки." +L["How the rows should grow when new group members are added."] = "Направление роста рядов, когда добавляются новые члены группы." +L["How you want this aura to be anchored to the unit frame."] = "Установка расположения аур на рамке." +L["Icon Size"] = "Размер иконки" +L["If multiple auras are shown in the same indicator, the higher priority one is shown first."] = "Если несколько аур отображаются в одном индикаторе, выше приоритет у той, что была первой." +L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."] = "Ввод названия заклинаний чувствителен к регистру и должен быть точным. Можно использовать id заклинаний." +L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."] = "Если на юнита наложен щит поглощения урона, то будет показываться абсолютное значение, в противном случае - имя юнита" +L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."] = "Когда существо/игрок получает входящее исцеление, будет отображено абсолютное значение этого исцеления, в противном случае будет отображено названия существа/игрока." +L["If the unit is a player then class is returned, if it's a NPC then the creature type."] = "Если объект является игроком то будет выводиться его класс, если же НИП, то его тип." +L["If the unit is a player then race is returned, if it's a NPC then the creature type."] = "Если объект является игроком то будет выводиться его раса, если же НИП, то его тип." +L["Import"] = "Импорт" +L["Import unit frame positions"] = "Импорт расмещения рамок" +L["Import visibility settings"] = "Импорт настроек отображения" +L["In range alpha"] = "Прозрачность в досягаемости" +L["Inactive alpha"] = "Прозрачность в бездействии" +L["Incoming heal"] = "Входящее исцеление" +L["Incoming heal (Absolute)"] = "Входящее исцеление (полное)" +L["Incoming heal (Percent)"] = "Входящее исцеление (%)" +L["Incoming heal (Short)"] = "Входящее исцеление (коротко)" +L["Incoming heal/Name"] = "Входящее исцеление/назв." +L["Incoming heals"] = "Входящие исцеления" +L["Index"] = "Индекс" +L["Indicator color"] = "Цвет индикатора" +L["Indicator name"] = "Имя индикатора" +L["Indicators"] = "Индикаторы" +L["Inset"] = "Вставить" +L["Inside Center"] = "Внутри в центре" +L["Inside Center Left"] = "Внутри от центра влево" +L["Inside Center Right"] = "Внутри от центра вправо" +L["Inside Top Left"] = "Внутри вверху слева" +L["Inside Top Right"] = "Внутри верху справа" +L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."] = "Вместо отображения сплошного цвета внутри индикатора будет отображаться значок ауры." +L["Interrupted"] = "Прервано" +L["Invalid interval entered, must be a number."] = "Введен неправильный интервал, это должно быть число." +L["Invalid spell \"%s\" entered."] = "Введено неверное заклинание \"%s\"." +L["Invert colors"] = "Инверсия цветов" +L["Layout manager"] = "Управление расположением рамок" +L["Leader / Assist"] = "Лидер / Помощник" +L["Left"] = "Слева" +L["Left Bottom"] = "Слева внизу" +L["Left Center"] = "Слева по центру" +L["Left text"] = "Текст слева" +L["Left Top"] = "Слева вверху" +L["Let's you modify the base font size to either make it larger or smaller."] = "Позволяет изменить базовый размер шрифта либо сделать его больше либо меньше." +L["Level"] = "Уровень" +L["Level %s - %s: %s/%s (%.2f%% done)"] = "Уровень %s - %s: %s/%s (%.2f%% готово)" +L["Level %s - %s: %s/%s (%.2f%% done), %s rested."] = "Уровень %s - %s: %s/%s (%.2f%% готово), %s отдыха." +L["Level (Colored)"] = "Уровень (Окрашен)" +L["Level without any coloring."] = "Уровень без окраски." +L["Light"] = "Светлый" +L["Link"] = "Ссылка" +L["Lock frames"] = "Закрепить рамки" +L["Locks the unit frame positionings hiding the mover boxes."] = "Закрепить рамки и скрыть перемещаемые области." +L["Low health"] = "Мало здоровья" +L["Main Assist"] = "Наводчик" +L["Main Assist Target"] = "Цель наводчика" +L["Main Tank"] = "Главный танк" +L["Main Tank Target"] = "Цель главного танка" +L["Male"] = "Мужчина" +L["Mana"] = "Мана" +L["Management"] = "Управление" +L["Manual position"] = "Указать позицию" +L["Master Looter"] = "Ответственный за добычу" +L["Max columns"] = "Макс колонок" +L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."] = "Макс здоровья, используется формат сокращения, 17750 отображается как 17.7k, значения ниже 10000 не форматируются." +L["Max HP (Absolute)"] = "Макс ЗД (полное)" +L["Max HP (Short)"] = "Макс ЗД (коротко)" +L["Max power (Absolute)"] = "Макс энергии (полное)" +L["Max power (Short)"] = "Макс энергии (коротко)" +L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."] = "Макс энергии, используется формат сокращения, 16000 отображается как 16k, vзначения ниже 10000 не форматируются." +L["Max rows"] = "Макс рядов" +L["Miscellaneous"] = "Разное" +L["Missing HP (Short)"] = "Нехват ЗД (коротко)" +L["Missing power (Short)"] = "Нехват энергии (коротко)" +L["Mushrooms"] = "Грибы" +L["Name"] = "Название" +L["Name (Abbreviated)"] = "Название (сокр.)" +L["Neutral"] = "Нейтральный" +L["Never (Disabled)"] = "Никогда (откл.)" +L["New aura group"] = "Новая группа аур" +L["New filter"] = "Новый фильтр" +L["None"] = "Нету" +L["None (Disabled)"] = "Нет (Отключен)" +L["NPCs only"] = "Только НИПы" +L["Offline timer"] = "Таймер выхода из сети" +L["On aggro"] = "При угрозе" +L["On curable debuff"] = "При излечимом дебаффе" +L["On mouseover"] = "При наводе курсора" +L["Or you can set a position manually"] = "Или же вы можете установить позицию вручную." +L["Order"] = "Порядок" +L["Other Party/Phase Status"] = "Другая группа/Статус фазы" +L["Out of range alpha"] = "Прозрачность в не досягаемости" +L["Outline"] = "Контур" +L["Outside bar limit"] = "Предел внешней полосы" +L["Override background"] = "Перекрывать задний фон" +L["Override color"] = "Замещение цвета" +L["Party"] = "Группа" +L["Party frames are hidden while in a raid group with more than 5 people inside."] = "Рамки группы будут скрыты, если в рейде больше 5 человек." +L["Party frames are hidden while in any sort of raid no matter how many people."] = "Рамки группы будут скрыты, независимо от количества участников в рейде." +L["Party instances"] = "Групповые подземелья" +L["Party Pet"] = "Питомец группы" +L["Party Target"] = "Цель группы" +L["Per column"] = "В колонке" +L["Per row"] = "В ряду" +L["Percent HP"] = "Процент ЗД" +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."] = "Отображать количество исцеления в процентах от общего количества здоровья, если у цели 100,000 общего здоровья и получаемое исцеление равняется 15,000, тогда будет показано 15%." +L["Percent power"] = "Процент энергии" +L["Percentage of width the portrait should use."] = "Ширина портрета в процентах." +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."] = "Значение в процентах, на сколько полоса поглощения урона может выйти за границы фрейма. 130% означает возможность выхода за пределы фрейма на 30%, 100% не позволяет полосе выходить за границы фрейма." +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."] = "Значеине в процентах как далеко за пределы рамки может выходить входящее исцеление: 130% означает выход за рамку на 30%, 100% без выхода за рамку." +L["Pet"] = "Питомец" +L["Pet Battle"] = "Бой питомца" +L["Pet Target"] = "Цель питомца" +L["Player"] = "Игрок" +L["player alt. power"] = "альт. энергия игрока" +L["player cast bar"] = "панель применений игрока" +L["Player Class"] = "Класс игрока" +L["player power frames"] = "рамка энергии игрока" +L["Player threat"] = "Угроза игрока" +L["Players only"] = "Только игроки" +L["Players will be colored by class."] = "Игроки будут окрашены по классу." +L["Point"] = "Точка" +L["Portrait"] = "Портрет" +L["Portrait type"] = "Тип портрета" +L["Position"] = "Позиция" +L["Power"] = "Энергия" +L["Power bar"] = "Полоса энергии" +L["Power Type"] = "Тип силы" +L["Prevents unit tooltips from showing while in combat."] = "Предотвращает отображение подсказкок во время боя." +L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."] = "Первичная окраска полосы здоровья, будет замещена цвтом по угрозе или реакции, если это необходимо." +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."] = "Главная цель окраски полос силы. Окрашивание в зависимости от класса применимо только к игрокам, у всех остальных будет по-умолчанию." +L["Prioritize buffs"] = "Приоритеты баффам" +L["Programming in Lua"] = "Программирование в Lua" +L["PvP Flag"] = "Знак PvP" +L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."] = "Индикатор знака PVP, Орда для пвпшеров орды и Альянс для пвпшеров альянса." +L["PvP Flags"] = "Знаки PvP" +L["PVP timer"] = "Таймер PVP" +L["Quest Boss"] = "Квестовый босс" +L["Race"] = "Раса" +L["Race (Smart)"] = "Раса (Smart)" +L["Rage"] = "Ярость" +L["Raid"] = "Рейд" +L["Raid assisting unit"] = "Помощник рейда" +L["Raid frames are hidden while in a raid group with 5 or less people inside."] = "Рамки рейда будут скрыты если в рейд группе 5-чел или меньше." +L["Raid instances"] = "Рейдовые подземелья" +L["Raid pet"] = "Питомец рейда" +L["Raid Role"] = "Роль в рейде" +L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."] = "Индикатор роли, добавляет индикатор щита для основного танка и меч для наводчика." +L["Raid Target"] = "Цель рейда" +L["Raid target indicator."] = "Индикатор цели рейда" +L["Raid targeting unit"] = "Мишень рейда" +L["Range indicator"] = "Индикатор дистанции" +L["Rare indicator"] = "Индикатор редкого" +L["Rather than bars filling from left -> right, they will fill from bottom -> top."] = "Вместо того, чтобы полосы заполнялись слева -> направо, они заполнятсь снизу -> вверх." +L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."] = "Код окраски реакции, используйте [reactcolor][name][close] для окраски имени игрока/существа в соответствии с его реакцией к вам." +L["Reaction color tag"] = "Тег цвета реакции" +L["Ready Status"] = "Статус готовности" +L["Ready status of group members."] = "Статус готовности участников группы." +L["Red (>70% HP)"] = "Красный (>70% ЗД)" +L["Relative point"] = "Относительно точки" +L["Resources"] = "Ресурсы" +L["Resurrect Status"] = "Статус воскрешения" +L["Returns + if the unit is an elite or rare elite mob."] = "Выводит + , если объект является существом элитным или редкой элитой." +L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."] = "Выводит текст цвета угрозы для вашей цели: Красный для агрессии, Оранжевый для высокой угрозы и Желтый для средней угрозы." +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."] = "Выводит текст цвета угрозы для всех существ: Красный для агрессии, Оранжевый для высокой угрозы и Желтый для средней угрозы." +L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."] = "Выводит среднее значение угрозы в процентах от агрессивности вашей текущей цели, от 0 до 100%." +L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."] = "Выводит текущее значение здоровья в процентах, если существо/игрок умер или вышел из сети, тогда вместо процента будет отображаться труп или вышел из сети." +L["Returns current power as a percentage."] = "Выводит текущее значение энергии в процентах." +L["Returns Rare if the unit is a rare or rare elite mob."] = "Выводит Редкий если объект является существом редким или редкой элитой." +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."] = "Выводит текст, основанный на общей ситуации угрозы: Агро для агрессии, Высокая, когда близок к срыву агрессии, и Средняя, когда следует обратить внимание.|nНе может быть использована для цель цели и цель фокуса." +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."] = "Выводит текст, основанный угрозе для всех игроков: Агро для агрессии, Высокая, когда близок к срыву агрессии, и Средняя, когда следует обратить внимание." +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."] = "Выводит текст, основанный угрозе вашей цели: Агро для агрессии, Высокая, когда близок к срыву агрессии, и Средняя, когда следует обратить внимание." +L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."] = "Возвращает цвет основанный на сравнении уровня объекта и вашего. Если вы не не можете атаковать его, то цвет не будет определен." +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."] = "Выводит цвет, основанный на общей ситуации угрозы: Красный для агрессии, Оранжевый для высокой угрозы, и Желтый для средней угрозы.|nНе может быть использована для цель цели и цель фокуса." +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."] = "Возвращает процентное значение угрозы объекта, если вы укажите это для члена группы, вы увидите процент того, как близко они к срыву агро любого моба. Значение от 0 до 100%.|nНе может быть использована для цель цели и цель фокуса." +L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."] = "Выводит текущую форму игрока-друида: Кошка для формы кошки, Совух для формы совуха и т.д." +L["Returns the units sex."] = "Отображает пол игрока/существа." +L["Reverse fill"] = "Обратное заполнение" +L["Right"] = "Справа" +L["Right Bottom"] = "Справа внизу" +L["Right Center"] = "Справа по центру" +L["Right text"] = "Текст справа" +L["Right Top"] = "Справа верху" +L["Row growth"] = "Возрастание ряда" +L["Row offset"] = "Смещение ряда" +L["Rune bar"] = "Полоса рун" +L["Runic Power"] = "Сила рун" +L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."] = "Также как и [color:sit] за исключением того, что возвращает только красным, если у вас есть агро, а не транзитом желтый -> оранжевый -> красный." +L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."] = "Также как и [unit:color:sit] за исключением того, что возвращает только красным, если у вас есть агро, а не транзитом желтый -> оранжевый -> красный." +L["Scale"] = "Масштаб" +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."] = "Увеличивает масштаб наложенных вами аур или тех, которые можно украсть, любое число свыше 100% больше, чем по-умолчанию, любое число ниже 100% меньше, чем по-умолчанию." +L["Scaled aura size"] = "Размер масштабированной ауры." +L["Scaled threat percent"] = "Нормированный % угрозы" +L["Screen"] = "Экран" +L["Search"] = "Поиск" +L["Search tags"] = "Поиск тегов" +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."] = "См. документацию ниже для сведений и примеров по созданию тегов, если вы просто хотите освоить основы Lua или WoW API, то см. ссылки Programming in Lua и WoW Programming." +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."] = "Выберите объекты, которые вы хотите изменить: любые принятые изменения коснутся всех выбранных обхектов. Если вы хотите изменить положение или особые значения блоков группы/рейда, вам необходимо перейти на настройки этих блоков.|n|nShift-клик блок чтобы выбрать все/отменить выбор всего." +L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."] = "Выберите текст из панели с лева для его изменения. Используйте эту страницу чтобы установить теги, изменить/сократить их ширину и размер." +L["Separate raid frames"] = "Разделять рамки рейда" +L["Sex"] = "Пол" +L["Shadow Orbs"] = "Теневые сферы" +L["Short classification"] = "Короткая классификация" +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."] = "Укороченная класификация R (редкий), R+ (редкий элитный), + (элитный), B (босс), M (миньон) и пустота в остальных случаях." +L["Short elite indicator"] = "Коротко-индикатор элиты" +L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."] = "Сокращенная версия [druidform], C = кошка, B = медведь, F = летающий и т.д." +L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."] = "Укороченное значение поглащения урона. Если поглащается 13,000 урона - отображается 13k." +L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."] = "Сокращение значения входящего исцеления, если входит 13,000 исцеления то покажет как 13k." +L["Show a background behind the bars with the same texture/color but faded out."] = "Показать фон за полосой с одинаковой текстурой/цветом, но постепенно исчезающий." +L["Show as bar"] = "Показать как полосу" +L["Show aura icon"] = "Показать значок ауры" +L["Show background"] = "Показать фон" +L["Show boss debuffs"] = "Показать дебаффы босса" +L["Show buffs before debuffs when sharing the same anchor point."] = "Показать баффы раньше дебаффов, когда и те и другие используют одну и туже привязку (месторасположение)." +L["Show cast name"] = "Показать название" +L["Show cast time"] = "Показать время применения" +L["Show incoming heals"] = "Показать входящее исцеление" +L["Show party as raid"] = "Показать группу как рейд" +L["Show player in party"] = "Показать игрока в группе" +L["Show your auras"] = "Показать ваши ауры" +L["Shows a bar for alternate power info (used in some encounters)"] = "Показывает полосу для информации об альт. энергии (используется в некоторых боях)" +L["Shows AFK, DND or nothing depending on the units away status."] = "Показывать метки \"Отсутствует\" или \"Не беспокоить\"." +L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."] = "Показать ответ боя, последенее полученное исцеление, последний пропущенный удар, сопротивление, парирование и т.д." +L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."] = "Отображает текущее и максимальное значение здоровья, 17500 здоровья будут отображаться как 17500 здоровья." +L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."] = "Отображает текущее и максимальное значение энергии, 18000 энергии будут отображаться как 18000 энергии." +L["Shows current group number of the unit."] = "Показывает текущий номер группы игрока." +L["Shows current health value in absolute form meaning 15000 health is shown as 15000."] = "Отображает текущее значение здоровья в чистой форме, т.е. 15000 здоровья будет отображаться как 15000." +L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."] = "Отображает текущее значение энергии в чистой форме, т.е. 15000 энергии будет отображаться как 15000." +L["Shows debuffs that you can cure."] = "Показывать вредоносные эффекты, которые вы можете снять" +L["Shows how long an unit has been AFK or DND."] = "Показывает как долго игрок отсутствует или помечен статусом \"не беспокоить\"." +L["Shows how long an unit has been offline."] = "Показывает как долго игрок находится вне сети." +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."] = "Показывает как долго выключен флаг PVP, не показывает, когда флаг включен вручную или вы находитесь во враждебной зоне.|n|nРаботает только на себе." +L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."] = "Отображает максимальное значение здоровья в чистой форме, 14000 здоровья будет отображаться как 14000 здоровья." +L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."] = "Отображает максимальное значение энергии в чистой форме, 13000 энергии будет отображаться как 13000 энергии." +L["Shows Offline, Dead, Ghost or nothing depending on the units current status."] = "Показывает состояние игрока/существа, труп, призрак, вышел из сети. Остаётся пустым если нету активного состояния." +L["Shows that a NPC is a boss for a quest."] = "Показывать является ли НИП боссом для квеста." +L["Show's the units guild name if they are in a guild."] = "Показывает название гильдии игрока если он состоит в ней." +L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."] = "Показывает здоровье в процентах с округлением до первого десятичного числа, то есть 61 из 110 здоровья будет показано как 55,4%." +L["Shows what kind of pet the unit is for pet battles."] = "Отображать тип питомца для боев питомцев" +L["Shows when a party member is in a different phase or another group."] = "Показывать, когда член группы находится в другой фазе или в другой группе." +L["Simple aura filtering by whitelists and blacklists."] = "Обычная фильтрация аур с черным списком и белым." +L["Size"] = "Размер" +L["Smart level"] = "Smart-уровень" +L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."] = "Разумное отображение уровеня, выводит Босс для боссов, +50 для элитных существ 50 уровня, или просто 80 для 80 уровня." +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-значение для [curmaxhp], значения до 1,000,000 остаются как есть, значения выше 1,000,000 будут сокращены как 1m." +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."] = "Smart-значение для [curmaxpp], значения до 1,000,000 остаются как есть, значения выше 1,000,000 будут сокращены как 1m." +L["Sort method"] = "Способ сортировки" +L["Sort order"] = "Порядок сортировки" +L["Sorting"] = "Сортировка" +L["Soul Shards"] = "Осколки души" +L["Soul shards"] = "Осколки душ" +L["Spacing"] = "Промежуток" +L["Spacing between each row"] = "Промежуток между рядами" +L["Spell ID %s"] = "ID заклинания %s" +L["Spell Name"] = "Название заклинания" +L["Spell Name/ID"] = "Название/ID заклинания" +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."] = "Разделяет рамки рейда на отдельные рамки для каждой группы рейда.|nОбратите внимание! Вы не можете переместить каждую рамку группу в отдельности, но можно настроить как возрастание рядов и колонок." +L["Static"] = "Статический" +L["Statue"] = "Статуя" +L["Status"] = "Статус" +L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."] = "Индикатор состояния показывает в бою ли существо/игрок. Для игрока также отображает отдохнувший ли он." +L["Style of borders to show for all auras."] = "Стиль границ, отображаемый на всех аурах." +L["Tag list"] = "Список тегов" +L["Tag name"] = "Название тега" +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]."] = "Теги, которые вы хотите использовать для доступа к коду, не делайте переносов в скобках. например, вы должны ввести \"foobar\" и затем обращаться к нему как [foobar]." +L["Tags"] = "Теги" +L["Target"] = "Цель" +L["Target of Target"] = "Цель цели" +L["Target of Target of Target"] = "Цель цели цели" +L["Test Aura"] = "Тест аур" +L["Test spell"] = "Тест заклинания" +L["Text"] = "Текст" +L["Text name"] = "Название текста" +L["Text name that you can use to identify this text from others when configuring."] = "Названия текста, которые поможет идентифицировать его среди других во время настройки." +L["Text parent"] = "Родитель текста" +L["Text/Tags"] = "Текст/Теги" +L["The blacklist \"%s\" already exists."] = "Черный список \"%s\", уже существует." +L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."] = "Рамка игрока, невзирая ни на что, не будет скрыта, вам придется вручную отключить ей полностью или в типах зон." +L["The tag \"%s\" already exists."] = "Тег \"%s\", уже существует." +L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."] = "Рамки объектов, которые вы видите, это примеры, они не совершенны и не отображают все данные, которые должны.|n|nВы можете спрятать их отключив через /shadowuf или нажать кнопку ниже." +L["The whitelist \"%s\" already exists."] = "Рекомендательный список \"%s\", уже существует." +L["Thick outline"] = "Толстый контур" +L["Thin outline"] = "Тонкий контур" +L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."] = "Эта полоса автоматически скроется, когда вы достигнете максимального уровня или у вас не будет никакой отслеживаемой репутаций." +L["This filter has no aura types set to filter out."] = "Фильтр не имеет установленных типов аур для фильтрования." +L["This filter has no auras in it, you will have to add some using the dialog above."] = "Фильтр не имеет аур, вы можете добавить их используя поле ввода вверху." +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."] = "Это хорошее руководство о том, как начать работу с программированием в Lua, вам не обязательно читать все, руководство является полезным для понимания основ синтаксиса Lua и API." +L["This unit depends on another to work, disabling %s will disable %s."] = "Этот объект связан с другим объектом, отключив %s отключится и %s." +L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."] = "Этот объект имеет подчиненные объекты, вы должны включить его, чтобы можно было включить подчиненный объект." +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."] = "Это отключит автоматическое обнаружение события, которое будет необходимо для тега, не отмечайте это, если вы не знаете, что вы делаете." +L["This will override all background colorings for bars including custom set ones."] = "Включение этой опции, заменит все цвета фона для полос, включая пользовательские." +L["Threat"] = "Угроза" +L["Threat situation"] = "Состояние угрозы" +L["Tile size"] = "Размер мозайки" +L["Top"] = "Сверху" +L["Top Center"] = "Сверху по центру" +L["Top Left"] = "Сверху слева" +L["Top Right"] = "Сверху справа" +L["Total number of active holy power."] = "Общее количество активной Энергии Света." +L["Total number of active soul shards."] = "Общее количество активных камней душ." +L["Total number of combo points you have on your target."] = "Всего накопившихся приёмов в серии на текущей цели." +L["Turns this widget into a bar that can be resized and ordered just like health and power bars."] = "Переключает данный виджет в полосу, которая может быть изменена в размерах и упорядочена как полоса здоровья или энергии." +L["Unattackable hostile"] = "Неатакуемые враждебные" +L["Unit color code on aggro"] = "Окраска объекта по агрессивности" +L["Unit colored situation"] = "Окраска объекта по ситуации" +L["Unit faction"] = "Фракция объекта" +L["Unit name"] = "Имя объекта" +L["Unit name (Class colored)"] = "Имя объекта (окраска класса)" +L["Unit name colored by class."] = "Окраска названия/имени игрока/существа в соответствии с цветом его класса." +L["Unit scaled threat"] = "Общая угроза объекта" +L["Unit server"] = "Сервер объекта" +L["Unit server, if they are from your server then nothing is shown."] = "Сервер объекта, если он с вашего сервера, тогда ничего не будет выводится." +L["Unit situation name"] = "Название ситуации объекта" +L["Units"] = "Рамки" +L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."] = "Принадлежность игрока/существа, Тралл будет отображаться как Орда, Магни Бронзобород как Альянс." +L["Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those."] = "Классификация юнитов Rare, Rare Elite, Boss, Minion или пустота в остальных случаях." +L["Units per column"] = "Рамок в колонке" +L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."] = "Расса игрока/существа, Кровавый Эльф, Ночной Эльф и т.д." +L["Unknown"] = "Неизвестный" +L["Unlink frames"] = "Разъединить рамки" +L["Up"] = "Вверху" +L["Update interval"] = "Интервал обновления" +L["Using unit settings"] = "Использование настроек рамок" +L["Various units can be enabled through this page, such as raid or party targets."] = "На этой странице можно включить / выключить различные рамки, такие как рейд или цели группы." +L["Vehicle"] = "Транспорт" +L["Vehicles"] = "Транспорт" +L["Vertical growth"] = "Вертикальное расположение" +L["View"] = "Просмотр" +L["Visibility"] = "Отображение" +L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] = "Предупреждение: This will unlink all frames from each other so you can move them without another frame moving with it." +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."] = "Когда игрок/существо теряет здоровье, отображается тег [missinghp], когда значение здоровье максимальное тогда отображается тег [name]. Это позволит вам увидеть -1000 при потере 1000 очков здоровья." +L["When this filter is active, apply the filter to buffs."] = "Когда данный фильтр активен, применяется фильтрация баффов." +L["When this filter is active, apply the filter to debuffs."] = "Когда данный фильтр активен, применяется фильтрация дебаффов." +L["When to color the empty bar by reaction, overriding the default color by option."] = "Окрашивать пустую строку по реакции, замещает цвет по умолчанию." +L["When to color the health bar by the units reaction, overriding the color health by option."] = "Окрашивать полосу здоровья по реакции объекта, замещает цвет строки здоровья по умолчанию." +L["Where inside the frame the text should be anchored to."] = "В каком месте, внутри рамки, должно быть расположен текст." +L["Where to anchor the cast name text."] = "Установка расположение текста названия применения." +L["Where to anchor the cast time text."] = "Установка расположение текста времени применения." +L["Whitelist"] = "Белый список" +L["Whitelist filters"] = "Фильтры рекомендательного списка" +L["Whitelists"] = "Белые списки" +L["Widget Size"] = "Размер виджета" +L["Width"] = "Ширина" +L["Width percent"] = "Ширина в %" +L["Width weight"] = "Ширина вес" +L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."] = "Будет заполняться справа -> налево при горизонтальном расположении или сверху -> вниз вертикальном расположении." +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"] = "Хотите знать, что это за вкладки и что в них настраивается? Коротко о них:|n|n|cfffed000Общее:|r Портреты, проверка досягаемости, затухание в бою, подсветка границ|n|cfffed000Рамка:|r Расположение объекта и привязка рамок|n|cfffed000Полосы:|r Настройка полос здоровье, энергие, пустых полос, полос заклинаний и приемов в серии|n|cfffed000Размер виджета:|r Настройка размеров всех полос и портретов а так-же их порядка|n|cfffed000Ауры:|r Настройка аур. Включение/отключение и так делее|n|cfffed000Индикаторы:|r Настройка всех индикаторов|n|cfffed000Текст/Теги:|r Управление тегами, позиционирование текста и настройка ширины.|n|n|cfffed000Рамки рейда по группам|r - Настройка объекта -> Рейд -> Рейд -> Разделять рамки рейда|n|n|n*** Популярные настройки ***|n|n|cfffed000Окраска по классу:|r Полосы -> Цвет здоровья по|n|cfffed000Таймеры на аурах:|r Для этого вам нужен OmniCC|n|cfffed000Отображение стандартной облости баффов:|r Hide Blizzard -> Снемите галку с Скрыть область баффов|n|cfffed000Процентное значение ЗД/М:|r Вкладка Текст/теги, используйте теги [percenthp] или [percentpp]|n|cfffed000Сокрытие группы в рейде|r - Настройка объекта -> Группа -> Группа -> Скрыть в рейде из 6-чел/Скрыть в любом рейде" +L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."] = "Работает так же, как и [%s], показывается только в форме Кота или Медведя." +L["WoW Programming"] = "WoW программирование" +L["WoW Programming is a good resource for finding out what difference API's do and how to call them."] = "WoW программирование - отличный ресурс, где можно узнать о различных функциях API." +L["X Offset"] = "Смещение по X" +L["XP/Rep bar"] = "Индикатор опыта/реп." +L["Y Offset"] = "Смещение по Y" +L["Yellow (>30% HP)"] = "Желтый (>30% ЗД)" +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."] = "Вы можете добавить дополнительный текст с включенными тегами используя этй настройку, заметьте, что любой текст влияет на все объекты, удалив текст вы вернете настройки по умолчанию|n|nВы не можете удалить текст, который установлен объекту по умолчанию." +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."] = "На этой странице вы можете добавить новые пользовательские теги, а также изменить существующие." +L["You can find more information on creating your own custom tags in the \"Help\" tab above."] = "Вы можете найти более подробную информацию о создании собственных пользовательских тегов в вкладке \"Справка \"." +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."] = "Вы найдете больше информации по соданию собственных тегов в \"Справке\" на закладке выше.|nSUF будет пытаться автоматически определять каким событиям необходимо добавлять теги, так что вам не особо нужно заполнять поле события." +L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] = "Вы можете импортировать настройки Shadowed Unit Frame от другого пользователя скопировав экспортированный код в поле ниже. Это сохранит ваши старые настройки в \"Import Backup\".|n|nЭта процедура может занять 30-60 секунд, пожалуйста, будьте терпеливы." +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."] = "Вы можете установить, к каким рамкам, и какой, следует использовать фильтр группы и в каком типе зоны, если вы хотите изменить ауры, перейдите в ту группу и увидете опцию \"Управление группами аур\"." +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."] = "Вы не можете изменить этот тег, поскольку он является одним из входящих по умолчанию в состав кода данного аддона. Эта функция здесь, служить примером для вас, в создании пользовательских тегов." +L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."] = "Вы не можете задать тегу название \"%s\", назване тега не должно содержать символы или скобки." +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."] = "У вас нет фильтров такого типа, вам нужно создать хоть один в панели управления, до жтого эта страница вам безполезна." +L["You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf."] = "Когда вы будете участвовать в бою, рамки объектов будут заблокированы. После выхода из боя вы должны будете разблокировать их снова черезе /shadowuf." +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."] = "Вы должны установить события для срабатывания, вы можете ввести только буквы и символы подчёркивания. К примеру: \"FOO_BAR \" действителен, \"APPLE_5_ORANGE \" нет, потому что оно содержит число." +L["You must enter a number that is 0 or higher, negative numbers are not allowed."] = "Вы должны ввести число 0 и выше, отрицательные цифры не допускается." +L["You must enter a tag name."] = "Вы должны ввести название тега." +L["You must restart Shadowed Unit Frames."] = "Вы должны перезагрузить Shadowed Unit Frames." +L["You must wrap your code in a function."] = "Вы должны обернуть свой код в функцию." +L["You will need to create an aura filter before you can set which unit to enable aura filtering on."] = "Вам нужно создать фильтр аур, прежде чем установить рамку, к которой будет применяться фильтрация аур." +L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."] = "Вам необходимо будет выполнить команду /console reloadui перед тем как скрытые рамки станут видимыми.|nРамки игрока и других объектов будут автоматически скрыты до тех пор, пока вы не включите их отображение в Shadowed Unit Frames." +L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] = "Ваше активное расположение рамок - это профиль используемый для резервного копирования импорта, и он не может быть перезаписан при импорте. Измените свой профиль на какой-нибудь другой, и попробуйте еще раз." +L["Your aura color"] = "Цвет ваших аур" +L["Your Auras"] = "Ваши ауры" +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"] = "Ваш код должен быть написан с разделением строк. Например, если вы хотите создать тег для возврата наименования объекта, вам необходимо сделать это так:|n|nfunction(unit, unitOwner)|nreturn UnitName(unitOwner)|nend" +L["Zone configuration units"] = "Настройка зон" + +local ShadowUF = select(2, ...) +ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) diff --git a/localization/zhCN.lua b/localization/zhCN.lua index fbfe2318d..35359b04e 100755 --- a/localization/zhCN.lua +++ b/localization/zhCN.lua @@ -1,5 +1,943 @@ -if( GetLocale() ~= "zhCN" ) then return end -local L = {} ---@localization(locale="zhCN", format="lua_additive_table", handle-unlocalized="ignore")@ -local ShadowUF = select(2, ...) -ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) +if( GetLocale() ~= "zhCN" ) then return end +local L = {} +L["%d auras in group"] = "%d光环在组里" +L["%s (%s): %s/%s (%.2f%% done)"] = "%s (%s): %s/%s (%.2f%%已完成)" +L["%s aura groups disabled"] = "%s光环组已禁用" +L["%s frames"] = "%s框体" +L["%s member"] = "%s成员" +L["|cff20ff20%s|r units enabled"] = "|cff20ff20%s|r单位已启用" +L["|cffff2020%s|r units disabled"] = "|cffff2020%s|r单位已禁用" +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."] = "|cffff2020Warning!|r 在区域配置中有些单位的覆盖设置,在某些区域可能显示(或不显示)。都不会受下列设置影响。" +L["1 aura group disabled"] = "1光环组已禁用" +L["2D"] = "2D" +L["3D"] = "3D" +L["A"] = "A" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "缩写超过10个单词的头像名字,\"Dark Rune Champion\" 缩写为 \"D.R.Champion\" 或 \"Dark Rune Commoner\" 缩写为 \"D.R.Commoner\"。" +L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."] = "在单位上显示伤害吸收的绝对值,如果10000的伤害被吸收,将会显示为10000。" +L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."] = "治疗吸收绝对值,如果16000的治疗量被吸收,显示为16000。" +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "精确显示接受治疗的治疗量,如 10,000 治疗量显示为 10,000。" +L["Add"] = "增加" +L["Add Aura"] = "添加光环" +L["Add aura"] = "添加光环" +L["Add Indicator"] = "添加指示器" +L["Add link"] = "添加链接" +L["Add new indicator"] = "添加新指示器" +L["Add new tag"] = "增加新的标签" +L["Add new text"] = "增加新的文字" +L["Add Tags"] = "添加标签" +L["Adds %s to the list of units to be modified when you change values in this tab."] = "增加 %s 到头像列表,你可以在这个选项卡里修改参数值。" +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "在你的食尸鬼计时器上增加一个计时条指示器,仅用于一个非永久性的食尸鬼。" +L["Adds a bar indicating how much time is left on your mushrooms."] = "增加一个条,提示你的蘑菇还有多长时间消失。" +L["Adds a bar indicating how much time is left on your Rune of Power."] = "添加状态条显示符文能量还有剩余多长时间。" +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = "在生命条里增加一个状态条显示将会有多少伤害量会被吸收。" +L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."] = "在生命条内添加一条指示某人预计将接受多少治疗。 " +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = "在血量条里添加一个显示受到任何治疗量的指示条。" +L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."] = "在血量条里增加一条用于显示有多少治疗量被吸收而没有作用于玩家身上。" +L["Adds a mana bar to the player frame for elemental and enhancement shamans."] = "在玩家框架上为元素萨满和增强萨满添加一个法力条。" +L["Adds a mana bar to the player frame for shadow priests."] = "在玩家框架上为暗影牧师添加一个法力条。" +L["Adds a Stagger bar for Brewmaster Monks."] = "为酒仙武僧增加一个醉拳状态条显示醉拳化解伤害计时。" +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "增加一个可以放置文本的空的计量条。" +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "当你在熊或猫形态下时在玩家头像上增加一个额外的法力条。" +L["Adds rune bars and timers before runes refresh to the player frame."] = "在符文刷新之前增加符文条和计时器到玩家头像框体。" +L["Adds temporary enchants to the buffs for the player."] = "为玩家的增益效果增加临时附魔。" +L["Adds totem bars with timers before they expire to the player frame."] = "在到期之前增加带有计时器的图腾条到玩家头像框体。" +L["Advanced"] = "高级" +L["Advanced tag management, allows you to add your own custom tags."] = "高级标签管理,允许你添加自定义的标签。" +L["AFK"] = "AFK" +L["AFK status"] = "AFK 状态" +L["AFK timer"] = "AFK 计时器" +L["AFK:%s"] = "AFK:%s" +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "你点击输出后,你可以复制下面的代码给其他ShadowedUF用户来使用你的布局方式。" +L["Aggro"] = "仇恨" +L["All aura groups enabled for unit."] = "此单位所有光环都已启用。" +L["All Auras"] = "所有光环" +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."] = "允许你定位锚点光环组到另一个,然后可以选择要使用的锚点位置.|n|n你可以使用这个来复制那些在增益效果和负面效果在不同分组的默认UI样式。" +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."] = "允许通过右键点击它禁用图腾.|n|n警告: In如果你启用它,则单位附近的状态条无法在战斗中调整大小。" +L["Allows you to enter a new aura group."] = "允许你输入一个新的光环组。" +L["Alpha to use for bar backgrounds."] = "计量条背景所使用的透明度。" +L["Alpha to use for bar."] = "计量条要使用的透明度。" +L["Alt. Power"] = "特定能量" +L["Alt. Power bar"] = "特殊能力条" +L["Alternate power is used for things like quests and dungeons."] = "特定能量用于像任务或者副本等情况下。" +L["Alternate Spell Name"] = "另一个法术名称" +L["Alternatively friendly spell to use to check range."] = "交替使用友方法术来检查距离。" +L["Ammo"] = "弹药" +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."] = "缺损生命值的总数,如果没有缺损则不会显示。使用一个短的格式, -18500 显示为 -18.5k,低于 10000 的生命值则不会被格式化。" +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."] = "缺损能力值的总数,如果没有缺损则不会显示。使用一个短的格式, -13850 显示为 13.8k,低于 10000 的能力值则不会被格式化。" +L["Anchor point"] = "锚点" +L["Anchor to"] = "锚点定位到" +L["Anchor to another frame"] = "定位到其他框体" +L["Anchor to buffs"] = "锚点定位到增益效果" +L["Anchor to debuffs"] = "锚点定位到负面效果" +L["Ancient Kings bar"] = "远古列王条" +L["Any auras shown in this indicator will have their total stack displayed."] = "在这个指示器里显示的光环将会显示它们总的叠加数。" +L["Aquatic"] = "水栖形态" +L["Arcane Charges"] = "奥术炸弹" +L["Are you sure you want to delete this aura?"] = "你确定要删除这个光环吗?" +L["Are you sure you want to delete this filter?"] = "你是否确定删除这个过滤器?" +L["Are you sure you want to delete this indicator?"] = "你确定要删除这个指示器吗?" +L["Are you sure you want to delete this tag?"] = "你是否确定删除这个标签?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "你是否确定删除这个文字?有关这个的所有设置将被删除。" +L["Arena"] = "竞技场" +L["Arena Pet"] = "竞技场宠物" +L["Arena Spec"] = "竞技场规格" +L["Arena Target"] = "竞技场目标" +L["Arena Target of Target"] = "竞技场目标的目标" +L["Arena ToT"] = "竞技场 ToT" +L["Arenas"] = "竞技场" +L["Ascending"] = "上升" +L["Assigned Role (DPS/Tank/etc)"] = "职责分配(输出/坦克/等等)" +L["Astral Power"] = "星界能量" +L["Aura border style"] = "光环边框样式" +L["Aura borders"] = "光环边框" +L["Aura Combo Points"] = "光环连击点" +L["Aura Filters"] = "光环过滤器" +L["Aura filters"] = "光环过滤器" +L["Aura group"] = "光环组" +L["Aura groups"] = "光环组" +L["Aura Groups"] = "光环组" +L["Aura Indicators"] = "光环指示器" +L["Aura indicators"] = "光环指示器" +L["Aura name or spell ID"] = "光环名称或法术ID" +L["Aura types to filter"] = "要过滤的光环类型" +L["Auras"] = "光环" +L["Auras matching a criteria will automatically show up in the indicator when enabled."] = "当启用后,满足条件的光环将自动显示在这个指示器中。" +L["Automatic Auras"] = "自动光环" +L["B"] = "B" +L["Background"] = "背景" +L["Background alpha"] = "背景透明度" +L["Background color"] = "背景颜色" +L["Background/border"] = "背景/边框" +L["Bag indicator for master looters."] = "主拾取的背包指示器。" +L["Bar alpha"] = "计量条透明度" +L["Bar color to use to show how much healing someone is about to receive."] = "条颜色用于某个人受到的治疗量。" +L["Bar spacing"] = "计量条间距" +L["Bar texture"] = "背景材质" +L["Bars"] = "计量条" +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."] = "条顺序高于或低于全尺寸选项会使用整个单位框架的宽度. |n|n条显示在两个数字之间的头像旁。" +L["Battleground"] = "战场" +L["Battleground Pet"] = "战场宠物" +L["Battleground Target"] = "战场目标" +L["Battleground Target of Target"] = "战场目标的目标" +L["Battlegrounds"] = "战场" +L["Bear"] = "熊" +L["BG"] = "战场" +L["BG Pet"] = "战场宠物" +L["BG Target"] = "战场目标" +L["BG ToT"] = "战场ToT" +L["Blacklist"] = "黑名单" +L["Blacklist filters"] = "黑名单过滤器" +L["Blacklists"] = "黑名单" +L["Blizzard"] = "暴雪" +L["Border"] = "边框" +L["Border alpha"] = "边框透明度" +L["Border color"] = "边框颜色" +L["Border coloring of stealable, curable and dispellable auras."] = "着色可偷取,治愈和驱散的光环边框。" +L["Border highlighting"] = "边框高亮" +L["Border thickness"] = "边框厚度" +L["Boss"] = "首领" +L["Boss Auras"] = "首领光环" +L["Boss Debuffs"] = "首领负面效果" +L["Boss Target"] = "首领目标" +L["Boss Target of Target"] = "首领目标的目标" +L["Boss ToT"] = "首领 ToT" +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."] = "首领单位仅作为某些战斗情况,如鲜血议会或炮艇大战,你不会在每个首领战看到他们。" +L["Both"] = "全部" +L["Bottom"] = "底部" +L["Bottom Center"] = "底部居中" +L["Bottom Left"] = "底部左边" +L["Bottom Right"] = "底部右边" +L["buff frames"] = "增益效果框体" +L["Buffs"] = "增益效果" +L["C"] = "C" +L["Cannot find any profiles named \"%s\"."] = "不能找到名为\" %s\"的配置文件。" +L["Cast"] = "施法" +L["Cast bar"] = "施法条" +L["Cast icon"] = "施法图标" +L["Cast interrupted"] = "施法打断" +L["Cast name"] = "施法名" +L["Cast time"] = "施法时间" +L["Cast uninterruptible"] = "施法不可打断" +L["Casting"] = "施法中" +L["Cat"] = "猫" +L["Category"] = "分类" +L["Center"] = "居中" +L["Changed profile to %s."] = "修改配置文件到 %s。" +L["Changes the health bar to the color of any curable debuff."] = "转变血量条为可治愈的负面效果颜色。" +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = "当单位获得仇恨时改变生命条颜色为敌对颜色 (默认为红色)。" +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."] = "修改这个小组件为计量条,你可以像修改生命条和能力条一样修改高度和顺序。" +L["Channelling"] = "通道法术" +L["Checking this will show the indciator on hostile units."] = "选中此项将会在敌对单位上显示此指示器" +L["Checking this will show the indicator on friendly units."] = "选中此项将会在友好单位上显示此指示器。" +L["Chi"] = "气" +L["Chi Points"] = "气点数" +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = "子单位不能被拖动,你必须通过 /shadowuf 来重新定位。" +L["Class"] = "职业" +L["Class (Smart)"] = "职业 (简洁)" +L["Class color tag"] = "职业颜色标签" +L["Class icon"] = "职业图标" +L["Class Icon"] = "职业图标" +L["Class icon for players."] = "玩家的职业图标。" +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = "职业未着色的名字,如果你想按职业着色名字请使用 [classcolor][class][close] 。" +L["Class Role"] = "职业角色" +L["Class Specific"] = "特定职业" +L["Class Timer"] = "职业计时器" +L["Class/misc bars"] = "职业/杂项条" +L["Classes"] = "职业" +L["Classification"] = "分类" +L["Classifications"] = "职业类别" +L["Clip"] = "内间距" +L["Close color"] = "关闭颜色" +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = "关闭一个颜色代码,阻止那些你不想要的显示在文字上的颜色。" +L["Code"] = "代码" +L["Color by class"] = "按职业着色" +L["Color by reaction on"] = "按反应类型着色" +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."] = "按单位的剩余生命值百分比着色代码。" +L["Color code for general situation"] = "一般情况下的着色代码" +L["Color code for situation"] = "某些情况下的着色代码" +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = "按职业着色代码,使用 [classcolor][class][close] 如果你想按职业着色职业文字" +L["Color code on aggro"] = "获得仇恨的着色代码" +L["Color health by"] = "着色血量按" +L["Color on aggro"] = "着色获得仇恨" +L["Color on curable debuff"] = "着色可治愈的负面效果" +L["Color power by"] = "着色能量依据" +L["Color to use for health bars that are set to be colored by a static color."] = "生命值设置为着色为固定颜色的生命条颜色。" +L["Color to use to show how much damage will be absorbed."] = "染色显示多少伤害将会被吸收。" +L["Color to use to show how much healing will e absorbed."] = "用颜色显示多少治疗量会被吸收。" +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = "当施法不可打断所使用的颜色,这个仅能用在 PvE 怪物上。" +L["Color used when a cast is a channel."] = "当施法是通道法术所使用的颜色。" +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "当可以被自身和其他人打断的施法所使用的颜色。" +L["Color used when a cast is successfully finished."] = "当成功施法完成所使用的颜色。" +L["Color used when an unit is casting a spell."] = "当施放一个法术时所使用的颜色。" +L["Colors"] = "颜色" +L["Column growth"] = "列的增长方向" +L["Column spacing"] = "列之间的距离" +L["Combat alpha"] = "战斗透明度" +L["Combat fader"] = "战斗渐隐" +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."] = "战斗渐隐将渐隐你的所有的头像,并当你进入战斗或单位激活后恢复透明度。" +L["Combat Status"] = "战斗状态" +L["Combat text"] = "战斗文字" +L["Combat/resting status"] = "战斗/休息状态" +L["Combo points"] = "连击点数" +L["Combo Points"] = "连击点" +L["Configuration to specific unit frames."] = "特殊头像框体的配置。" +L["Cooldown rings for"] = "以下显示冷却动画" +L["Create"] = "创建" +L["Creature type"] = "创建类型" +L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."] = "可以创建的类型,如单位是恶魔守卫则返回一个恶魔守卫的值。" +L["Crown indicator for group leader or assistants."] = "为团长或团队助理显示一个皇冠指示器。" +L["Cur/Max HP (Absolute)"] = "当前/最大 血量 (绝对值)" +L["Cur/Max HP (Short)"] = "当前/最大 血量 (短格式)" +L["Cur/Max HP (Smart)"] = "当前/最大 血量 (简洁)" +L["Cur/Max power (Absolute)"] = "当前/最大 能力值 (绝对值)" +L["Cur/Max power (Druid)"] = "当前/最大 能量值 (德鲁伊)" +L["Cur/Max power (Druid/Absolute)"] = "当前/最大 能量值(德鲁伊/绝对值)" +L["Cur/Max power (Secondary)"] = "当前/最大 能量值(次要能量)" +L["Cur/Max power (Secondary/Absolute)"] = "当前/最大 能量值(次要能量/绝对值)" +L["Cur/Max Power (Short)"] = "当前/最大 能力值 (短格式)" +L["Cur/Max PP (Smart)"] = "当前/最大 能力值 (简洁)" +L["Curable"] = "可治愈" +L["Curable Auras"] = "可治愈光环" +L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."] = "当前和最大生命值,格式化为 [curhp]/[maxhp],如果已死亡或离线则显示相应的状态。" +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "当前和最大能力值,格式化为 [curhp]/[maxhp]。" +L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."] = "当前生命值,使用一个短的格式文本,11500 被格式化为 11.5k,低于 10000 的值则保持现状。" +L["Current HP (Absolute)"] = "当前血量 (绝对值)" +L["Current HP (Short)"] = "当前血量 (短格式)" +L["Current pet used by a battleground unit."] = "当前宠物使用一个战场单位。" +L["Current power (Absolute)"] = "当前能力值 (绝对值)" +L["Current power (Druid)"] = "当前能力值 (德鲁伊)" +L["Current power (Druid/Absolute)"] = "当前能力值 (德鲁伊/绝对值)" +L["Current power (Secondary)"] = "当前能量值(次要能量)" +L["Current power (Secondary/Absolute)"] = "当前能量值(次要能量/绝对值)" +L["Current Power (Short)"] = "当前能力值 (短格式)" +L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."] = "当前能力值,使用一个短的格式文本,12750 被格式化为 12.7k,低于 10000 的值则保持现状。" +L["Current target of a battleground unit."] = "战场单位的当前目标。" +L["Current target of target of a battleground unit."] = "战场单位当前目标的目标。" +L["Currently modifying"] = "当前修改" +L["Currently used in battlegrounds for showing flag carriers."] = "当前用于在战场中显示旗帜携带者。" +L["Damage absorption (Absolute)"] = "伤害吸收 (绝对值)" +L["Damage absorption (Short)"] = "伤害吸收 (缩写)" +L["Damage absorption/Name"] = "伤害吸收/名字" +L["Dark"] = "深色" +L["Dead"] = "死" +L["Debuffs"] = "负面效果" +L["Decimal percent HP"] = "十进制百分比生命值" +L["Default color"] = "默认颜色" +L["Default font color, any color tags inside individual tag texts will override this."] = "默认字体颜色,单个标签内的任何颜色标签将覆盖掉这个值。" +L["Deficit/Unit Name"] = "亏损/头像名字" +L["Delete"] = "删除" +L["Delete filter"] = "删除过滤器" +L["Delete link"] = "删除链接" +L["Descending"] = "降序" +L["Disable Auras by Class"] = "禁用职业光环" +L["Disable Blizzard Cooldown Count"] = "禁用暴雪冷却计时器" +L["Disable event discovery"] = "禁用事件探索" +L["Disable OmniCC Cooldown Count"] = "禁用 OmniCC 冷却计时器" +L["Disable vehicle swap"] = "禁用载具切换" +L["Disabled"] = "禁用" +L["Disabled for %s."] = "关于 %s 的已禁用。" +L["Disabled in %s"] = "在 %s 中禁用" +L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."] = "在所有SUF的光环上禁用冷却显示。" +L["Disables the unit frame from turning into a vehicle when the player enters one."] = "当玩家进入一个载具时禁止头像转换为载具。" +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!."] = "当在 %s 时禁用一个模块。如果你不想请不要禁用!" +L["Disabling unit modules in various instances."] = "在各种不同副本禁用头像模块。" +L["Dismissable Totem bars"] = "图腾召唤条" +L["Dispellable/Stealable"] = "可驱散/偷取" +L["Display"] = "显示" +L["Display enemy buffs using LibClassicDuration data."] = "使用 LibClassicDuration 数据显示敌对增益。" +L["DND"] = "勿扰" +L["DND:%s"] = "勿扰:%s" +L["Documentation"] = "说明文档" +L["Don't hide when empty"] = "当为空时不隐藏" +L["Don't use a filter"] = "不使用过滤器" +L["Down"] = "下" +L["Druid form"] = "德鲁伊形态" +L["Druid form (Short)"] = "德鲁伊形态 (短格式)" +L["Druid mana bar"] = "德鲁伊法力条" +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."] = "由于伪造单位的性质,%s的施法条不是很高效,提示施法的变化最短只能采集到0.10秒。" +L["Edge size"] = "边角大小" +L["Edit tag"] = "编辑标签" +L["Editing %s"] = "正在编辑 %s" +L["Elite"] = "精英" +L["Empty bar"] = "空计量条" +L["Enable %s"] = "启用 %s" +L["Enable buffs"] = "启用增益效果" +L["Enable debuffs"] = "启用负面效果" +L["Enable enemy buff tracking"] = "启用敌对增益追踪" +L["Enable for friendlies"] = "为友好单位启用" +L["Enable for hostiles"] = "为敌对单位启用" +L["Enable frequent updates"] = "启用频繁刷新" +L["Enable indicator"] = "启用指示器" +L["Enable Indicators"] = "启用指示器" +L["Enable temporary enchants"] = "启用临时附魔" +L["Enable units"] = "启用头像" +L["Enabled for %s."] = "关于 %s 的已启用。" +L["Enabled in %s"] = "在 %s 中启用" +L["Enabled Units"] = "单位已启用" +L["Enables configuration mode, letting you move and giving you example frames to setup."] = "启用配置模式,可以移动并给出样板框体来设置。" +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."] = "启用高级设置将可以获得更多的配置选项。 这个意味着你可以调整每个单独的东西。 默认为不启用。" +L["Energy"] = "能量" +L["Enlarge auras for"] = "放大以下光环" +L["Error"] = "错误" +L["Events"] = "事件" +L["Events that should be used to trigger an update of this tag. Separate each event with a single space."] = "用来触发这个标签更新的事件. 用一个单独的间隔来分开每个事件。" +L["Everywhere else"] = "其他任何地方" +L["Export"] = "导出" +L["F"] = "F" +L["Fades out the unit frames of people who are not within range of you."] = "当目标超出你的距离范围内则淡化头像,仅能作用于在你的队伍中的成员。" +L["Failed to import layout, error:|n|n%s"] = "导入布局失败,错误::|n|n%s" +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "加载 ShadowedUF_Options 失败,不能打开配置。错误返回:%s" +L["Failed to save tag, error:|n %s"] = "保存标签失败,错误:|n %s" +L["Female"] = "女性" +L["Filter type"] = "过滤类型" +L["Filtering both buffs and debuffs"] = "过滤增益效果和负面效果" +L["Filtering buffs only"] = "仅过滤增益效果" +L["Filtering debuffs only"] = "仅过滤负面效果" +L["Filters"] = "过滤器" +L["Finished cast"] = "完成施法" +L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."] = "标记标签为频繁刷新。" +L["Flight"] = "飞行" +L["Flips coloring so the bar color is shown as the background color and the background as the bar"] = "反转颜色后计量条颜色将显示为背景颜色,背景颜色将显示为计量条颜色" +L["Focus"] = "焦点" +L["Focus Target"] = "焦点目标" +L["Font"] = "字体" +L["Food"] = "食物" +L["For configuring aura indicators on unit frames."] = "在单位框架上配置相关光环指示器。" +L["For target/focus"] = "作用于目标/焦点" +L["Forces a static color to be used for the background of all bars"] = "强制一种颜色应用到所有计量条的背景色上" +L["Frame"] = "框体" +L["Frame alpha when you are out of combat while having no target and 100% mana or energy."] = "当你脱离战斗状态并没有目标而且是100%法力或者能量时的框体透明度。" +L["Frame alpha while this unit is in combat."] = "当这个单位在战斗状态中时的框体透明度。" +L["Frames"] = "框体" +L["Friendly"] = "友善" +L["Fuel"] = "燃料" +L["Full size after"] = "在之后全尺寸" +L["Full size before"] = "在之前全尺寸" +L["Fury"] = "愤怒" +L["General"] = "综合" +L["General configuration to all enabled units."] = "所有已启用头像的综合配置。" +L["General threat situation"] = "综合仇恨条件" +L["Ghost"] = "魂" +L["Global"] = "全局" +L["Global configurating will let you mass enable or disable aura groups for multiple units at once."] = "全局配置将会让你同时为多个单位启用或禁用光环组。" +L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"] = "金色选中标记 - 在这个区域启用 / 灰色选中标记 - 在这个区域禁用 / 没有选中标记 - 使用默认头像设置" +L["Green (<30% HP)"] = "绿色(<30% 生命值)" +L["Group %d"] = "队伍 %d" +L["Group by"] = "分组按" +L["Group number"] = "队伍数字" +L["Group row spacing"] = "队伍行间距" +L["Groups"] = "队伍" +L["Groups per row"] = "每行的队伍" +L["Groups to show"] = "要显示的队伍" +L["Growth"] = "增长" +L["Guild name"] = "公会名字" +L["Half health"] = "半血" +L["Has Aggro"] = "获得仇恨" +L["Heal absorb"] = "治疗吸收" +L["Heal Absorb (Absolute)"] = "治疗吸收(绝对值)" +L["Heal Absorb (Short)"] = "治疗吸收(缩写)" +L["Heal absorbs"] = "吸收治疗" +L["Healing absorb"] = "吸收治疗" +L["Health"] = "生命" +L["Health bar"] = "生命条" +L["Health bar color for friendly units."] = "友善单位的生命条颜色。" +L["Health bar color for hostile units."] = "敌对单位的生命条颜色。" +L["Health bar color for neutral units."] = "中立单位的生命条颜色。" +L["Health bar color for units with aggro."] = "血量条着色显示获得仇恨。" +L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."] = "你不能攻击的敌对目标所使用的生命条颜色,被用作反应颜色。" +L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."] = "生命条颜色按从 100% -> 0% 的过渡来着色,也可以作用于你的宠物欢乐度。" +L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."] = "生命条颜色按从 100% -> 50% 的过渡来着色,也可以作用于你的宠物欢乐度。" +L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."] = "生命条颜色按从 50% -> 00% 的过渡来着色,也可以作用于你的宠物欢乐度。" +L["Health color"] = "生命值颜色" +L["Health percent"] = "生命值百分比(%)" +L["Height"] = "高" +L["Help"] = "帮助" +L["Hide %s"] = "隐藏 %s" +L["Hide %s frames"] = "隐藏 %s 框体" +L["Hide bar when empty"] = "当计量条为空时隐藏" +L["Hide Blizzard"] = "隐藏暴雪默认框体" +L["Hide in <=5-man raids"] = "在 <=5 人团队中隐藏" +L["Hide in >5-man raids"] = "在 > 5 人团队中隐藏" +L["Hide in any raid"] = "任何团队中隐藏" +L["Hide tooltips in combat"] = "战斗中隐藏提示讯息" +L["Hides the cast bar if there is no cast active."] = "如果当前没有施法动作则隐藏施法条。" +L["Hides the power bar unless the class has mana."] = "没有法力值属性则隐藏能量条。" +L["Hiding and showing various aspects of the default UI such as the player buff frames."] = "隐藏和显示默认的UI框体如玩家增益效果框体。" +L["High"] = "高" +L["High health"] = "高生命值" +L["Highlight"] = "高亮" +L["Highlight units that are "] = "高亮单位是" +L["Highlight units that are debuffed with something you can cure."] = "高亮你可以治愈的被施放了负面效果的头像框体。" +L["Highlight units that are rare."] = "高亮单位是稀有。" +L["Highlight units that have aggro on any mob."] = "高亮获得任何怪物触怒的头像框体。" +L["Highlight units that you are targeting or have focused."] = "高亮你的当前目标或被设为焦点的头像框体。" +L["Highlight units when you mouse over them."] = "高亮当你的滑鼠移动到的头像框体。" +L["Holy power"] = "神圣能量" +L["Holy Power"] = "神圣能量" +L["Hostile"] = "敌对" +L["How close the frame should clip with the border."] = "头像和边框的间距。" +L["How far the background should be from the unit frame border."] = "背景和头像边框的距离。" +L["How large the background should tile"] = "背景平铺的大小" +L["How large the edges should be."] = "边角的大小。" +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."] = "每一列的增益效果/负面效果数量示例,输入 2 将创建两个行。" +L["How many auras to show in a single row."] = "每一行显示的增益效果/负面效果数量。" +L["How many Chi points you currently have."] = "显示你当前有多少气点数。" +L["How many groups should be shown per row."] = "每行显示的队伍数量。" +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!"] = "有多少人在协助这个单位,例如如果你将这个设置为你自己则将显示与哦多少人以你的目标为目标. 这个数目包括你自身!" +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!"] = "你的团队有多少人以这个单位为目标,例如如果你将这个设置为你自己则将显示有多少人以你为目标. 这个数目包括你自身!" +L["How many rows total should be used, rows will be however long the per row value is set at."] = "要用到的行数量总数。" +L["How many seconds a totem has left before disappearing."] = "图腾在消失之前还剩下多少秒数。" +L["How many seconds before a rune recharges."] = "距符文再次开始冲能有多少秒时间。" +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."] = "更新间隔的秒数..|n[警告] 设置频率为0后将会在每次单个框体重绘后更新,如果你想要禁用频繁更新请反选并不要设置为。" +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."] = "这个计量条获得的框体总体高度,这是一个加权值,设置更高将获得更多。" +L["How much spacing should be between each new row of groups."] = "每个队伍行之间的间距。" +L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."] = "在一个头像中所有计量条之间的间距,负值为更远,正值为更近,0为无间距。" +L["How much weight this should use when figuring out the total text width."] = "当合计到总的文字宽度时使用的宽度。" +L["How the frames should grow when a new column is added."] = "当一个新的列被加入时行的增长方向。" +L["How the rows should grow when new group members are added."] = "当新的队伍成员加入时框体的增长方向。" +L["How you want this aura to be anchored to the unit frame."] = "你想要这个增益效果/负面效果定位到头像框体的方式。" +L["Icon Size"] = "图标大小" +L["If multiple auras are shown in the same indicator, the higher priority one is shown first."] = "如果多个光环在同一个指示器中,将首先显示高优先级的。" +L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."] = "已输入的名字必须是准确的一字不差的. 或者,你可以使用法术ID来代替。" +L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."] = "如果单位拥有伤害吸收护盾,它会显示吸收的绝对值,否则显示单位名称。" +L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."] = "如果这个单位获得治疗,将显示获得治疗的精确值,否则则显示单位名字。" +L["If the unit is a player then class is returned, if it's a NPC then the creature type."] = "如果单位为玩家则显示职业,如果是NPC则显示NPC类型。" +L["If the unit is a player then race is returned, if it's a NPC then the creature type."] = "如果单位为玩家则显示种族,如果是NPC则显示NPC类型。" +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."] = "如果你不这样做,你将不允许使用任何连击点功能 (真气,神圣能量,连击点,等等) 直到你这样做为止。" +L["Imp & Dreadstalker bar"] = "小鬼&恐惧猎犬条" +L["Import"] = "导入" +L["Import unit frame positions"] = "导入头像位置" +L["Import visibility settings"] = "导入可见性设置" +L["In range alpha"] = "在距离范围内透明度" +L["Inactive alpha"] = "未激活透明度" +L["Incoming absorb"] = "受到的吸收" +L["Incoming absorbs"] = "受到的吸收" +L["Incoming heal"] = "接受的治疗" +L["Incoming heal (Absolute)"] = "接受的治疗(绝对值)" +L["Incoming heal (Percent)"] = "受到的治疗(百分比)" +L["Incoming heal (Short)"] = "接受治疗 (短格式)" +L["Incoming heal/Name"] = "接受治疗/名字" +L["Incoming heals"] = "接受的治疗" +L["Index"] = "索引" +L["Indicator color"] = "指示器颜色" +L["Indicator for the current pet happiness."] = "当前宠物快乐度指示器" +L["Indicator name"] = "指示器名称" +L["Indicator this aura should be displayed in."] = "这个光环指示器要显示在。" +L["Indicators"] = "指示器" +L["Insanity"] = "立即" +L["Inset"] = "插入" +L["Inside Bottom Left"] = "内部下方靠左" +L["Inside Bottom Right"] = "内部下方靠右" +L["Inside Center"] = "内部居中" +L["Inside Center Left"] = "内部居中靠左" +L["Inside Center Right"] = "内部居中靠右" +L["Inside Top Left"] = "内部顶端靠左" +L["Inside Top Right"] = "内部顶端靠右" +L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."] = "在这个指示器将显示光环的图标而不是单纯的颜色。" +L["Interrupted"] = "已打断" +L["Invalid interval entered, must be a number."] = "必须输入一个数字。" +L["Invalid spell \"%s\" entered."] = "输入的 \"%s\" 法术不可用。" +L["Invert colors"] = "反转颜色" +L["Layout manager"] = "布局管理器" +L["Leader / Assist"] = "团长 / 团队助理" +L["Left"] = "左边" +L["Left Bottom"] = "左边底部" +L["Left Center"] = "左边居中" +L["Left text"] = "左边文字" +L["Left Top"] = "左边顶部" +L["Let's you modify the base font size to either make it larger or smaller."] = "让你修改基础字型的大小。" +L["Level"] = "等级" +L["Level %s - %s: %s/%s (%.2f%% done)"] = "等级 %s - %s: %s/%s (%.2f%% 已完成)" +L["Level %s - %s: %s/%s (%.2f%% done), %s rested."] = "等级 %s - %s: %s/%s (%.2f%% 已完成),%s 双倍经验。" +L["Level (Colored)"] = "等级 (着色)" +L["Level without any coloring."] = "等级不使用任何颜色。" +L["Light"] = "明亮" +L["Link"] = "链接" +L["Link from"] = "关联自" +L["Link to"] = "关联到" +L["Linked spells"] = "已关联法术" +L["Lock frames"] = "锁定框体" +L["Locks the unit frame positionings hiding the mover boxes."] = "锁定框体位置。" +L["Low health"] = "低生命值" +L["M"] = "M" +L["MA ToT"] = "主助理 ToT" +L["Maelstrom"] = "旋涡值" +L["Main Assist"] = "主助理" +L["Main Assist Target"] = "主助理目标" +L["Main Assist Target of Target"] = "主助理目标的目标" +L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."] = "主助理的设置是有暴雪主助理系统或它的MOD实现。" +L["Main Tank"] = "主坦克" +L["Main Tank Target"] = "主坦克目标" +L["Main Tank Target of Target"] = "主坦目标的目标" +L["Main Tank's are set through the Raid frames, or through selecting the Tank role."] = "主坦克是通过团队界面,或者通过选择坦克职责来设定。" +L["Male"] = "男性" +L["Mana"] = "法力" +L["Manage Aura Filters"] = "管理光环过滤器" +L["Management"] = "管理" +L["Manual position"] = "自定义位置" +L["Master Looter"] = "队长分配" +L["Max columns"] = "最大列数量" +L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."] = "最大生命值,使用一个短的格式文本,17750 被格式化为 17.7k,低于 10000 的值则保持现状。" +L["Max HP (Absolute)"] = "最大生命值 (绝对值)" +L["Max HP (Short)"] = "最大生命值 (短格式)" +L["Max power (Absolute)"] = "最大能力值 (绝对值)" +L["Max power (Short)"] = "最大能力值 (短格式)" +L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."] = "最大能力值,使用一个短的格式文本,16000 被格式化为 16k,低于 10000 的值则保持现状。" +L["Max rows"] = "最大行数量" +L["Medium"] = "中" +L["Minion"] = "小怪" +L["Miscellaneous"] = "杂项" +L["Missing HP (Short)"] = "缺失的生命值 (短格式)" +L["Missing power (Short)"] = "缺失的能力值 (短格式)" +L["Monochrome Outline"] = "单色轮廓" +L["Moonkin"] = "枭兽" +L["MT ToT"] = "主坦 ToT" +L["Mushroom bar"] = "旋涡值条" +L["Mushrooms"] = "蘑菇" +L["Name"] = "名字" +L["Name (Abbreviated)"] = "名字 (缩写)" +L["Name of a friendly spell to check range."] = "要检测距离的友好法术名称" +L["Neutral"] = "中立" +L["Never (Disabled)"] = "从不 (禁用)" +L["New aura group"] = "新光环组" +L["New filter"] = "新的过滤器" +L["None"] = "无" +L["None (Disabled)"] = "None (禁用)" +L["NPCs only"] = "仅NPC" +L["Off:%s"] = "离线:%s" +L["Offline"] = "离线" +L["Offline timer"] = "离线计时器" +L["Ok"] = "确定" +L["On %s units"] = "在 %s 单位" +L["On aggro"] = "在获得目标" +L["On curable debuff"] = "有可治愈的负面效果" +L["On elite mobs"] = "在精英目标上" +L["On Friendly Units"] = "在友好单位上" +L["On Hostile Units"] = "在敌对单位上" +L["On mouseover"] = "在鼠标悬停" +L["On rare mobs"] = "在稀有目标上" +L["Only active this aura inside an indicator if the group member does not have the aura."] = "如果在组成员中没有这个光环, 则只会在一个指示器里激活。" +L["Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras."] = "仅应用所选过滤器到友好单位的增益效果上和敌对单位的负面效果上,其他的显示所有光环。" +L["Only auras you specifically cast will be shown."] = "将只会显示你特别施放的光环。" +L["Only show if missing"] = "只会显示缺少的" +L["Only show self cast auras"] = "只会显示自己施放的光环" +L["Only show when mana"] = "只在有法力值时显示" +L["Or you can set a position manually"] = "或者你可以手动设置位置" +L["Order"] = "顺序" +L["Other Party/Phase Status"] = "其他小队/镜像状态" +L["Out of range alpha"] = "超出距离透明度" +L["Outline"] = "描边" +L["Outside bar limit"] = "外围计量条限制" +L["Override background"] = "覆盖背景" +L["Override color"] = "覆盖颜色" +L["Override list"] = "覆盖列表" +L["Override list filters"] = "覆盖列表过滤器" +L["Override lists"] = "覆盖列表" +L["Pain"] = "痛苦" +L["Party"] = "小队" +L["Party frames are hidden while in a raid group with more than 5 people inside."] = "当在一个超过5人的团队中时小队框体将被隐藏。" +L["Party frames are hidden while in any sort of raid no matter how many people."] = "当在一个任何人数的团队中时小队框体将被隐藏。" +L["Party instances"] = "小队副本" +L["Party Pet"] = "小队宠物" +L["Party Target"] = "小队目标" +L["Party Target of Target"] = "小队目标的目标" +L["Party ToT"] = "小队ToT" +L["Per column"] = "每栏" +L["Per row"] = "每行" +L["Percent HP"] = "百分比生命值" +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."] = "玩家当前受到的治疗量占总血量的百分比, 假如他有100000总血量并且受到15000的治疗量那么显示为15%。" +L["Percent power"] = "百分比能力值" +L["Percentage of width the portrait should use."] = "肖像使用的宽度百分比。" +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."] = "治疗吸收条超出单位框架的百分比. 130%表示会超出单位框架30%,100%表示不会超出框架。" +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."] = "百分比数值显示超多少头像框架的吸收伤害条。 130%就是说会超出框架的30%。 100%就是说不会超出。" +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."] = "接受治疗条超出头像框体的百分比值. 130% 意味着将超出 30% ,100% 意味着不超出。" +L["Pet"] = "宠物" +L["Pet Battle"] = "宠物战斗" +L["Pet Happiness"] = "宠物快乐度" +L["Pet Target"] = "宠物目标" +L["Player"] = "玩家" +L["player alt. power"] = "玩家特殊能力条" +L["player cast bar"] = "玩家施法条" +L["Player Class"] = "玩家职业" +L["player power frames"] = "玩家能量框体" +L["Player threat"] = "玩家仇恨" +L["Players only"] = "仅玩家" +L["Players will be colored by class."] = "玩家将按职业着色。" +L["Point"] = "框体部位" +L["Portrait"] = "肖像" +L["Portrait type"] = "肖像类型" +L["Position"] = "位置" +L["Positioning"] = "定位" +L["Power"] = "能力" +L["Power bar"] = "能力条" +L["Power Type"] = "能量类型" +L["Prevents unit tooltips from showing while in combat."] = "当在战斗中禁用鼠标提示。" +L["Priest mana bar"] = "牧师发力条" +L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."] = "生命条的初始颜色,获得仇恨或按反应类型如果需要可以覆盖这个颜色。" +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."] = "主要指的是能量条的着色. 按职业着色仅适用于玩家, 对于非玩家则用默认能量类型。" +L["Prioritize buffs"] = "优先增益效果" +L["Priority"] = "优先级" +L["Programming in Lua"] = "Lua 编程" +L["PvP Flag"] = "PvP 标识" +L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."] = "PVP 标识指示器,为开启PVP的显示联盟或者部落标识。" +L["PvP Flags"] = "PvP标志" +L["PVP timer"] = "PVP 计时器" +L["PVP:%s"] = "PVP:%s" +L["Quest Boss"] = "任务首领" +L["Race"] = "种族" +L["Race (Smart)"] = "种族 (简洁)" +L["Rage"] = "怒气" +L["Raid"] = "团队" +L["Raid assisting unit"] = "团队协助单位" +L["Raid frames are hidden while in a raid group with 5 or less people inside."] = "当团队中少于5个人时隐藏团队框体。" +L["Raid instances"] = "团队副本" +L["Raid Misc"] = "团队其他" +L["Raid pet"] = "团队宠物" +L["Raid Role"] = "团队职责" +L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."] = "团队角色指示器,主坦克显示盾,主助理显示剑。" +L["Raid Target"] = "团队目标" +L["Raid target indicator."] = "团队目标指示器。" +L["Raid targeting unit"] = "团队目标单位" +L["Range Checker"] = "距离检测" +L["Range indicator"] = "距离指示器" +L["Rare"] = "稀有" +L["Rare Elite"] = "稀有精英" +L["Rare indicator"] = "稀有指示器" +L["Rather than bars filling from left -> right, they will fill from bottom -> top."] = "条的增长方向并非是从左-->右,而是从下-->上。" +L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."] = "感应颜色代码,使用 [reactcolor][name][close] 来按他们的反应类型着色头像名字。" +L["Reaction color tag"] = "感应颜色标签" +L["Ready Status"] = "就绪状态" +L["Ready status of group members."] = "队伍成员的就绪状态。" +L["Red (>70% HP)"] = "红色(>70% 生命值)" +L["Relative point"] = "相对位置" +L["Resources"] = "来源" +L["Resurrect Status"] = "复活状态" +L["Returns + if the unit is an elite or rare elite mob."] = "如果是精英或稀有精英怪则显示 + 。" +L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."] = "按你的目标的仇恨值情况显示颜色:红色为获得仇恨,橘红为高仇恨值,黄色为提醒留意仇恨。" +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."] = "按所有单位的仇恨值情况显示颜色: 红色为获得仇恨,橘红为高仇恨值黄色为提醒留意仇恨。" +L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."] = "对于你的当前目标的仇恨值百分比,显示为 0 - 100%。" +L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."] = "用百分比显示当前生命值,如果已死亡或离线则显示相应的状态。" +L["Returns current power as a percentage."] = "用百分比显示当前能力值。" +L["Returns Rare if the unit is a rare or rare elite mob."] = "如果是稀有或者稀有精英怪则显示 Rare 。" +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."] = "基于单位的一般仇恨值情况显示文字:Aggro 为获得目标,High 为高仇恨,Medium 为小心仇恨.|n这个不能被用作目标的目标或焦点的目标等类型单位。" +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."] = "按你对所有单位的仇恨值情况显示文字: 获得仇恨为获得仇恨,高为高仇恨值,中为提醒留意仇恨。" +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."] = "按你的目标的仇恨值情况显示颜色: 获得仇恨为获得仇恨, 高为高仇恨值,中为提醒留意仇恨。" +L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."] = "基于目标相对于你的等级的颜色代码. 如果你不能攻击他那么不会显示颜色。" +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."] = "显示单位的仇恨值的颜色代码:红色 为获得目标,橘红色 为高仇恨,黄色 为小心仇恨.|n这个不能被用作目标的目标或焦点的目标等类型单位。" +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."] = "显示单位的可缩放的仇恨值百分比,如果你将这个放到一个小队成员身上你将看到他们对任何敌对怪物的仇恨百分比. 百分比在0-100%之间.|n这个不能被用作目标的目标或焦点的目标等类型单位。" +L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."] = "如果是德鲁伊显示当前的形态,猫、枭兽、熊等等。" +L["Returns the units sex."] = "显示单位性别。" +L["Reverse fill"] = "反向增长" +L["Right"] = "右边" +L["Right Bottom"] = "右边底部" +L["Right Center"] = "右边居中" +L["Right text"] = "右边文字" +L["Right Top"] = "右边顶部" +L["Role the unit is playing."] = "单位所担任的职责。" +L["Row growth"] = "行增长方向" +L["Row offset"] = "行坐标" +L["Rune bar"] = "符文条" +L["Rune of Power"] = "符文能量" +L["Rune of Power bar"] = "符文能量条" +L["Rune Timer"] = "符文计时器" +L["Runes"] = "符文" +L["Runic Power"] = "符文能量" +L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."] = "如果你获得仇恨仅显示红色,不再显示黄 --> 橘红 --> 红色。" +L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."] = "如果单位获得仇恨仅显示红色,不再显示黄 --> 橘红 --> 红色。" +L["Scale"] = "缩放" +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."] = "缩放你释放的或可以法术偷取的光环,任何100%以上的数值为大于默认,任何100%以下的数值为小于默认。" +L["Scaled aura size"] = "缩放增益效果/负面效果大小" +L["Scaled threat percent"] = "缩放仇恨值百分比" +L["Screen"] = "屏幕" +L["Search"] = "搜索" +L["Search tags"] = "搜寻标签" +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."] = "查看下面创建标签的说明文档和示例,如果你仅想要基本的 Lua 或 WoW API 信息请查看 Programming in Lua 和 WoW Programming 链接。" +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."] = "选择你想要更改的单位,任何设置的改变都会改变你已选择的单位. 如果你想要锚点定位或修改团队/小队单位的特定设置你需要通过他们的选项的实现.|n|nShift + 点击一个单位来选择全部或反选全部。" +L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."] = "从左侧面板选择一个标签文本来修改标签. 在当前面板可以修剪宽度,尺寸和坐标。" +L["Separate raid frames"] = "独立团队框体" +L["Set Filter Zones"] = "局部过滤设置" +L["Sex"] = "性别" +L["Shadow Orbs"] = "暗影宝珠" +L["Shaman mana bar"] = "萨满发力条" +L["Short classification"] = "短的职业类别显示" +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."] = "怪物简称分类,稀有为R,稀有精英为 R+,精英为 +,首领为 B,爪牙为 M,不包含在这些当中的什么都不显示。" +L["Short elite indicator"] = "短的精英指示器" +L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."] = "[druidform] 标签的短格式,C = 猫,B = 熊,F = 飞行 等等。" +L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."] = "简写伤害吸收,如果13000的伤害被吸收,将会显示为13k。" +L["Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k."] = "简化治疗吸收值,如果17000的治疗量被吸收,则显示为17k。" +L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."] = "短格式显示接受的治疗量,如 13,000 显示为 13k。" +L["Show a background behind the bars with the same texture/color but faded out."] = "在计量条的背后显示一个相同材质和颜色的背景,但是该背景将被淡化。" +L["Show any other auras"] = "显示任何其他光环" +L["Show as bar"] = "显示为计量条" +L["Show aura duration"] = "显示光环持续时间" +L["Show aura icon"] = "显示光环图标" +L["Show auras stack"] = "显示光环叠加" +L["Show background"] = "显示背景" +L["Show boss debuffs"] = "显示首领负面效果" +L["Show buffs before debuffs when sharing the same anchor point."] = "当公用一个相同的锚点定位时,增益效果将显示在负面效果之前。" +L["Show cast name"] = "显示施法名字" +L["Show cast time"] = "显示施法事件" +L["Show castable on other auras"] = "显示其它可施放光环" +L["Show casted by boss"] = "显示首领施放的" +L["Show curable debuffs"] = "显示可被治愈的负面效果" +L["Show curable/removable auras"] = "显示可治愈/消除的光环" +L["Show Heal Absorbs"] = "显示治疗吸收值" +L["Show icon durations"] = "显示图标持续时间" +L["Show incoming absorbs"] = "显示受到的吸收" +L["Show incoming heals"] = "显示受到的治疗" +L["Show inside"] = "显示在内部" +L["Show party as raid"] = "显示小队为团队" +L["Show player in party"] = "在小队显示玩家" +L["Show your auras"] = "显示你的光环" +L["Shows a bar for alternate power info (used in some encounters)"] = "显示特殊能力条的信息(在某些遭遇战中使用)" +L["Shows a cooldown wheel on the indicator with how much time is left on the aura."] = "在指示器上显示一个旋转的指针提示还有多长时间结束冷却。" +L["Shows AFK, DND or nothing depending on the units away status."] = "根据单位离开状态来显示 (AFK),(勿打扰) 或不显示任何东西。" +L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."] = "显示战斗信息,最后接受的治疗,最后的命中与否,抵抗,躲闪等等。" +L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."] = "用精确格式显示当前和最大生命值, 17500 生命值将显示为 17500。" +L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."] = "用精确格式显示当前和最大能力值,18000 法力将被显示为 18000。" +L["Shows current group number of the unit."] = "显示这个单位的当前队伍编号。" +L["Shows current health value in absolute form meaning 15000 health is shown as 15000."] = "用精确格式显示当前的生命值,15000 生命值将显示为 15000。" +L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."] = "用精确格式显示当前的能力值,15000 法力将显示为 15000。" +L["Shows debuffs cast by a boss."] = "显示首领施放的负面效果。" +L["Shows debuffs that you can cure."] = "显示你能够治愈的负面效果。" +L["Shows how long an unit has been AFK or DND."] = "显示AFK或者勿打扰状态的时间。" +L["Shows how long an unit has been offline."] = "显示离线的时间。" +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."] = "显示PVP标记消失的时间,不会在手动开启PVP或在一个敌对区域中显示.|n|n这个仅对你自身有效,你不能使用他来查看你的小队或团队的PVP标记消失时间。" +L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."] = "用精确格式显示最大的生命值,14000 生命值将显示为 14000。" +L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."] = "用精确格式显示最大的能力,143000 法力值将显示为 13000。" +L["Shows Offline, Dead, Ghost or nothing depending on the units current status."] = "根据单位当前状态来显示离线,死亡,灵魂状态或不显示任何东西。" +L["Shows that a NPC is a boss for a quest."] = "为任务把首领显示为任务NPC。" +L["Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000."] = "显示醉拳化解伤害的绝对值,如果化解了16000的伤害,显示为16000。" +L["Shows the current staggered damage, if 12,000 damage is staggered, shows 12k."] = "显示醉拳当前化解的伤害,如果化解了12000的伤害,显示为12k。" +L["Show's the units guild name if they are in a guild."] = "如果有公会则显示单位所在的公会名字。" +L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."] = "使用一个小数点的百分比来显示生命值,这意味著 61 / 110 生命值将显示为 55.4%。" +L["Shows what kind of pet the unit is for pet battles."] = "宠物战斗中显示单位是哪种宠物。" +L["Shows when a party member is in a different phase or another group."] = "显示一个小队成员在不同的镜像里或其他小组中。" +L["Simple aura filtering by whitelists and blacklists."] = "简单的增益效果和负面效果过滤器。" +L["Size"] = "大小" +L["Smart Friendly/Hostile Filter"] = "智能化 友好/敌对 过滤器" +L["Smart level"] = "等级的简洁格式" +L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."] = "简洁的等级显示,首领显示为 B ,等级50的精英怪显示为 +50 ,等级80显示为80 。" +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."] = "[curmaxhp] 的简洁数字格式, 低于1,000,000 将如此显示,高于 1,000,000 的数字将显示短格式如 1m。" +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."] = "[curmaxpp] 的简洁数字格式,低于1,000,000 将如此显示,高于 1,000,000 的数字将显示短格式如 1m。" +L["Solid color to use in the indicator, only used if you do not have use aura icon enabled."] = "在指示器中使用单纯颜色,仅作用于你没有启用显示光环图标选项。" +L["Sort method"] = "分类方式" +L["Sort order"] = "分类顺序" +L["Sorting"] = "分类" +L["Soul Shards"] = "灵魂碎片" +L["Soul shards"] = "灵魂碎片" +L["Spacing"] = "距离" +L["Spacing between each row"] = "每行之间的距离" +L["Spell ID %s"] = "法术ID %s" +L["Spell Name"] = "法术名称" +L["Spell Name/ID"] = "法术名称/ID" +L["Spell you want to link to a primary aura, the casing must be exact."] = "输入一个你想链接到的主要光环,这个通道必须准确。" +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."] = "为每个团队队伍分割团队框体到单独的框体.|n请注意! 你不能拖曳单独的每个队伍框体,但可以通过在行和列增长选项中设置他们的增长方向。" +L["Stagger"] = "醉拳" +L["Stagger (Monk)"] = "醉拳(武僧)" +L["Stagger (Monk/Absolute)"] = "醉拳(武僧/绝对值)" +L["Stagger bar"] = "醉拳条" +L["Stagger bar color when the staggered amount is <30% of your HP."] = "当你的生命值<30%时 醉拳状态条的颜色。" +L["Stagger bar color when the staggered amount is >30% of your HP."] = "当你的生命值>30%时 醉拳状态条的颜色。" +L["Stagger bar color when the staggered amount is >70% of your HP."] = "当你的生命值>70%时 醉拳状态条的颜色。" +L["Static"] = "静态" +L["Statue"] = "雕像" +L["Statue bar"] = "状态条" +L["Status"] = "状态" +L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."] = "状态指示器,当单位当前在战斗中时显示. 同时还显示玩家在休息状态。" +L["Stealable/Curable/Dispellable"] = "可偷取/治愈/驱散" +L["Style of borders to show for all auras."] = "所有光环边框的显示样式。" +L["Summon Pending"] = "召唤等待" +L["T"] = "T" +L["Tag list"] = "标签列表" +L["Tag name"] = "标签名字" +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]."] = "你用来访问这个代码的标签,不要使用方或者圆括号,他会自动填充. 例如,你输入 \"foobar\" 就会自动通过 [foobar] 来访问。" +L["Tags"] = "标签" +L["Talent spec of your arena opponents."] = "你的竞技场对手的天赋技能。" +L["Target"] = "目标" +L["Target of Target"] = "目标的目标" +L["Target of Target of Target"] = "目标的目标的目标" +L["Test Aura"] = "测试光环" +L["Test spell"] = "测试法术" +L["Text"] = "文字" +L["Text Management"] = "文字管理" +L["Text name"] = "文字名字" +L["Text name that you can use to identify this text from others when configuring."] = "你可以在配置时用来定义来自于其他文字的文字名字。" +L["Text parent"] = "文字来源" +L["Text/Tags"] = "文本/标签" +L["The blacklist \"%s\" already exists."] = "黑名单 \"%s\" 已经存在。" +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."] = "以下勾选框将允许你启用或禁用单位. |n|n|cffff2020警告!|r 目标的目标相比其他单位有更高的性能消耗. 如果你有性能问题,清禁用这些单位减少启用这些功能的单位。" +L["The override list \"%s\" already exists."] = "此覆盖列表 \"%s\" 已经存在。" +L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."] = "玩家框体将不被隐藏,你必须通过完全或由区域类型来手动禁用。" +L["The tag \"%s\" already exists."] = "这个标签 \"%s\" 已存在。" +L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."] = "你看到的头像仅是范例,他们不是那么完美并且不会显示应该显示的所有数据.|n|n你可以通过命令行 /shadowuf或点击下面的按钮锁定来隐藏他们。" +L["The whitelist \"%s\" already exists."] = "白名单 \"%s\" 已经存在。" +L["Thick outline"] = "粗描边" +L["Thin outline"] = "细描边" +L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."] = "这个计量条会在当你达到顶级时自动隐藏,或者你当前没有追踪任何声望时自动隐藏。" +L[ [=[This color will be used if the indicator shown is your own, only applies if icons are not used. +Handy 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.]=] ] = [=[这个颜色作用于显示你自己的指示器, 仅应用于未使用图标的时候 +有助于你了解假如一个目标有 回春 , 但你也想知道这个 回春 是不是你施放的.]=] +L["This filter has no aura types set to filter out."] = "这个过滤器没有要过滤的光环类型。" +L["This filter has no auras in it, you will have to add some using the dialog above."] = "这个过滤器内没有光环,你可以使用上面的对话框来添加。" +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."] = "这是一个如何开始Lua编程的很好的指南,然而你并不需要阅读整个事情,它有助于了解Lua的语法和API的基础知识。" +L["This unit depends on another to work, disabling %s will disable %s."] = "这个头像必须依靠另一个才能正常工作,禁用 %s 将同时禁用 %s。" +L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."] = "这个头像有子头像,你需要首先启用他的子头像来启用这个头像。" +L[ [=[This will be set for your current class only. +If no custom spells are set, defaults appropriate for your class will be used.]=] ] = [=[这只能对你当前职业设置。 +如果没有设定自定义法术,将会使用适于你当前职业的默认设置。]=] +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."] = "这个将禁用这个标签需要事件的自动探测,你应当保持这个未被选中除非你知道你在做什么。" +L["This will override all background colorings for bars including custom set ones."] = "这个将覆盖所有计量条的背景颜色,包括自定义设置的。" +L["Threat"] = "仇恨" +L["Threat situation"] = "仇恨情况" +L["Tile size"] = "标题大小" +L["Timer Text"] = "计时器文字" +L["Top"] = "顶部" +L["Top Center"] = "顶部居中" +L["Top Left"] = "顶部左边" +L["Top Right"] = "顶部右边" +L["Total number of active holy power."] = "可用神圣能量的数量。" +L["Total number of active soul shards."] = "可用灵魂碎片的数量。" +L["Total number of combo points you have on your target."] = "你在你的目标身上的连击点数的总数。" +L["Totem bar"] = "图腾条" +L["Totem Timer"] = "图腾计时器" +L["Travel"] = "旅行" +L["Tree"] = "树人" +L["Turns this widget into a bar that can be resized and ordered just like health and power bars."] = "改变这个组件为一个计量条,可以被调整大小或者像生命条和能力条一样被排序。" +L["Unattackable hostile"] = "不可攻击的敌对单位" +L["Unchecking this will completely disable aura indicators for %s."] = "不选择此项将会完全禁用 %s 的光环指示器。" +L["Unit color code on aggro"] = "获得仇恨的单位颜色代码" +L["Unit colored situation"] = "单位着色情况" +L["Unit Configuration"] = "单位配置" +L["Unit faction"] = "单位阵营" +L["Unit name"] = "单位名字" +L["Unit name (Class colored)"] = "单位名字 (按职业着色)" +L["Unit name colored by class."] = "按职业着色单位名字。" +L["Unit scaled threat"] = "单位比例仇恨" +L["Unit server"] = "单位所在服务器" +L["Unit server, if they are from your server then nothing is shown."] = "单位所在服务器,如果是同一个服务器则不显示。" +L["Unit situation name"] = "单位情况名字" +L["Units"] = "单位" +L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."] = "单位阵营,萨尔将显示为部落,麦格尼·铜须将显示为联盟。" +L["Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those."] = "怪物分类为,稀有,稀有精英,精英,首领或爪牙,不包含在这些当中的什么都不显示。" +L["Units per column"] = "每行单位数" +L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."] = "单位的种族。" +L["Units that should have the aura groups settings changed below."] = "单位将要改变的光环组设置如下。" +L["Units to change"] = "单位变化" +L["Unknown"] = "未知" +L["Unlink frames"] = "脱离框体" +L["Up"] = "向上" +L["Update interval"] = "刷新间隔" +L["Uses the icon of the totem being shown instead of a status bar."] = "使用图腾图标显示代替状态条。" +L["Using unit settings"] = "使用单位设置" +L["Various units can be enabled through this page, such as raid or party targets."] = "你可以在这个页面启用不同的头像,如团队或小队目标。" +L["Vehicle"] = "载具" +L["Vehicles"] = "垂直" +L["Vertical growth"] = "垂直增长" +L["View"] = "查看" +L["Visibility"] = "可见性" +L["WARNING! ShadowedUF_Indicators has been deprecated as v4 and is now built in. Please delete ShadowedUF_Indicators, your configuration will be saved."] = "警告! ShadowedUF_Indicators 组件已于v4版时弃用,并已内建. 请删除 ShadowedUF_Indicators,你的的配置将会保存。" +L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] = "警告: 这个将解开所有框体之间的链接。" +L["What group this aura belongs to, this is where you will find it when configuring."] = "这个光环属于什么组,当你设置的时候你会在这里找到它。" +L["What type of auras should be enlarged, use the scaled aura size option to change the size."] = "什么类型的光环将会放大,使用缩放光环尺寸选项去改变大小。" +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."] = "当单位正在少血, [missinghp] 标签将显示,当这单位满血 [name] 标签将显示. 这个会让你看到 -1000 当他们少了 1000 血量,满血时将只显示名字。" +L["When this filter is active, apply the filter to buffs."] = "当这个过滤器激活时,过滤增益效果。" +L["When this filter is active, apply the filter to debuffs."] = "当这个过滤器激活时,过滤负面效果。" +L["When to color the empty bar by reaction, overriding the default color by option."] = "何时按目标对你的反应类型着色空的计量条,覆盖选项的默认颜色When to color the empty bar by reaction, overriding the default color by option." +L["When to color the health bar by the units reaction, overriding the color health by option."] = "何时按目标对你的反应类型着色血量条,覆盖选项的默认血量颜色。" +L["When to show cooldown rings on auras"] = "何时在光环上显示冷却动画" +L["Where inside the frame the text should be anchored to."] = "这个框体内文字锚点的定位。" +L["Where to anchor the cast name text."] = "施法名字文字锚点的定位。" +L["Where to anchor the cast time text."] = "施法事件文字锚点的定位。" +L["Whether auras you casted should be shown"] = "是否显示你施放的光环" +L["Whether to show any auras casted by the boss"] = "是否要显示由首领施放的任何光环" +L["Whether to show any debuffs you can remove, cure or steal."] = "是否要显示任何你可以消除,治愈或偷取的负面效果。" +L["Whether to show auras that do not fall into the above categories."] = "是否要显示不属于上述类别的光环。" +L["Whether to show buffs that you cannot cast."] = "是否要显示你无法施放的增益效果。" +L["Whitelist"] = "白名单" +L["Whitelist filters"] = "白名单过滤器" +L["Whitelists"] = "白名单" +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."] = "白名单 将会隐藏任何不在过滤器组里的光环。|n黑名单 将会隐藏在过滤器组里的光环。|n其他的将会绕过所有过滤器一直显示。" +L["Widget Size"] = "小部件调整" +L["Width"] = "宽" +L["Width percent"] = "宽度百分比" +L["Width weight"] = "宽度加权" +L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."] = "当使用水平增长时为从右-->左,使用垂直增长时为从上-->下。" +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"] = "想了解所有单位配置标签的作用?这里有些提示:|n|n|cfffed000综合:|r 头像,范围检查,战斗文字,边框高亮|n|cfffed000框架:|r 单位定位和框架锚点|n|cfffed000Bars:|r 生命计量条,能量计量条,空计量条,施法条和连击点的配置|n|cfffed000组建大小:|r 所有的状态条和头像大笑以及框架排序的选项|n|cfffed000光环:|r 启用/关闭/放大自己等等的所有光环配置|n|cfffed000指示器:|r 所有的指示器配置包括PVP标识团队角色 就绪状态 和任务状态等等|n|cfffed000文本/标签:|r 标签管理以及文本定位和宽度设置.|n|n|n*** 常用选项 ***|n|n|cfffed000按组排列团队框架|r - 头像配置 -> 团队 -> 团队 -> 独立团队框架|n|cfffed000职业染色:|r 计量条 -> 着色血量按|n|cfffed000光环计时:|r 你需要OmniCC|n|cfffed000显示/隐藏默认的增益效果框架:|r 隐藏暴雪默认框体 -> 隐藏增益效果框体|n|cfffed000Percentage HP/MP 文字:|r 文本/标签选项,使用 [百分比生命值] 或者 [百分比能量值] 标签|n|cfffed000在团队中隐藏小队框架|r - 头像配置 -> 小队 -> 小队 -> 在>5人团队中隐藏/任何团队中隐藏" +L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."] = "工作方式就像[%s],在法力作为次要能量时,也会一直显示法力值。" +L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."] = "工作方式就像 [%s],只是仅用于显示豹或熊形态。" +L["WoW Programming"] = "WoW 编程" +L["WoW Programming is a good resource for finding out what difference API's do and how to call them."] = "WoW Programming 是一个很不错的查找API运用的资源站。" +L["X Offset"] = "X 坐标" +L["XP/Rep bar"] = "经验/声望条" +L["Y Offset"] = "Y 坐标" +L["Yellow (>30% HP)"] = "黄色(>30%生命值)" +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."] = "你可以使用这个配置来通过标签添加额外的文本,请注意任何额外的文本添加(或移除)将影响到所有的单位,移除文本也将会重置他们的设定..|n|n请记住,你不能在单位里面删除默认文本。" +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."] = "你可以通过这个页面来增加新的自定义标签,if you're looking to change what tags are used in text look under the Text tab for an Units configuration." +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."] = "在这里你可以禁用光环过滤器和组. 例如, 你可以设置一个光环组只显示目标身上的负面效果。" +L["You can find more information on creating your own custom tags in the \"Help\" tab above."] = "你可以在上面的\"帮助\"选项卡里找到更多的关于创建自定义标签的讯息。" +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."] = "你可以在上面的\"帮助\"标签里找到有关如何创建自定义标签的更多信息.|nSUF 将尝试自动检测你的标签需要什么事件,所以你不一定需要填写事件区域。" +L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] = "你可以在下面通过输入代码来导入另一个 Shadowed Unit Frame 用户的配置. 这个将备份你的旧有的布局到 \"导入备份\"中.|n|n你粘贴后将花费30-60秒的时间来加载,请耐心等待。" +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."] = "你可以连接到一起使用这个光环,例如你能链接 野性印记 到 野性赐福 ,那么如果玩家有 野性印记 但没有 野性赐福, 它仍然会把 野性印记 显示为就像拥有 野性赐福 一样。" +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."] = "在每个职业上你可以覆盖已启用的光环设置,提醒,如果光环是通过主列表选项禁用的,那么在这里你的职业设置不受影响。" +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."] = "你可以在这里设置在不同的区域类型和过滤器分组条件下使用的头像,如果你想要改变光环分组你可以查看 \"管理光环分组\" 选项。" +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."] = "你不能编辑这个标签因为这个是预设的标签中的一员. 这有一个为你提供一个自定义标签的示例。" +L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."] = "你不能命名一个标签 \"%s\",标签名字不能包含方括号或者圆括号。" +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."] = "你还没有添加这个类型的任何过滤器,你必须先到管理面板创建一个。" +L["You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf."] = "你已进入战斗,头像框体已被锁定. 当你离开战斗后你可能需要通过命令/shadowuf来重新解锁。" +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."] = "你只能输入字母和下划线,如 \"FOO_BAR\" 为可用,而\"APPLE_5_ORANGE\" 不可以因为包含了一个数字。" +L["You must enter a number that is 0 or higher, negative numbers are not allowed."] = "你必须输入一个大于 0 的数字,不允许为负数。" +L["You must enter a tag name."] = "你必须输入一个标签名字。" +L["You must restart Shadowed Unit Frames."] = "你必须重启Shadowed Unit Frames。" +L["You must wrap your code in a function."] = "你必须包装你的代码在一个函数内。" +L["You will need to create an aura filter before you can set which unit to enable aura filtering on."] = "在你设置需要过滤光环的单位前你必须创建一个光环过滤器。" +L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."] = "在隐藏框体重新变为可见之前你需要通过命令行 /console reloadui 来重载插件.|n玩家和其他的头像将依据你是否在插件里启用来自动隐藏。" +L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] = "你的已激活布局已被用作导入备份的配置文件,这个不能被导入所覆盖. 修改你的配置文件并再次尝试。" +L["Your aura color"] = "你的光环颜色" +L["Your Auras"] = "你的光环" +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"] = "你的代码必须包括在一个函数中,比如,如果你使一个标签显示头像的名字你需要这样做:|n|nfunction(unit, unitOwner)|nreturn UnitName(unitOwner)|nend" +L["Zone Configuration"] = "区域配置" +L["Zone configuration units"] = "区域配置单位" + +local ShadowUF = select(2, ...) +ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) diff --git a/localization/zhTW.lua b/localization/zhTW.lua index 4e1a8f19b..bf1741b1c 100755 --- a/localization/zhTW.lua +++ b/localization/zhTW.lua @@ -1,5 +1,945 @@ -if( GetLocale() ~= "zhTW" ) then return end -local L = {} ---@localization(locale="zhTW", format="lua_additive_table", handle-unlocalized="ignore")@ -local ShadowUF = select(2, ...) -ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) +if( GetLocale() ~= "zhTW" ) then return end +local L = {} +L["%d auras in group"] = "%d 光環組" +L["%s (%s): %s/%s (%.2f%% done)"] = "%s (%s): %s/%s (%.2f%% 已完成)" +L["%s aura groups disabled"] = "停用 %s 光環組" +L["%s frames"] = "%s框架" +L["%s member"] = "%s成員" +L["|cff20ff20%s|r units enabled"] = "|cffff2020%s|r 單位啟用" +L["|cffff2020%s|r units disabled"] = "|cffff2020%s|r 單位禁用" +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."] = "|cffff2020警告!|r 某些單位在地區設定已複寫設定,在某些地區可能顯示(或不顯示)。 無視以下設定。" +L["1 aura group disabled"] = "1組光環禁用" +L["2D"] = "2D" +L["3D"] = "3D" +L["A"] = "A" +L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."] = "簡化單位名稱需10個位元以上,'Dark Rune Champion'顯示為'D.R.Champion'或'Dark Rune Commoner'顯示為'D.R.Commoner'。" +L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."] = "在單位上顯示傷害吸收的絕對值,如果10,000的傷害被吸收,將會顯示為10,000。" +L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."] = "治療量吸收絕對值, 如果16,000的治療量被吸收, 顯示為16,000。" +L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."] = "顯示完整的治療量,如10,000治療量則顯示為10,000。" +L["Add"] = "新增" +L["Add Aura"] = "增加光環" +L["Add aura"] = "增加光環" +L["Add Indicator"] = "增加標記" +L["Add link"] = "增加連結" +L["Add new indicator"] = "增加新標記" +L["Add new tag"] = "新增新標籤" +L["Add new text"] = "新增新文字" +L["Add Tags"] = "增加標籤" +L["Adds %s to the list of units to be modified when you change values in this tab."] = "當你變更此標籤的數值時新增%s到單位清單中進行修改。" +L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."] = "為你的食屍鬼計時器上新增存活多久的計時條,僅用於非永久性的食屍鬼。" +L["Adds a bar indicating how much time is left on your mushrooms."] = "增加一個動作條指示蘑菇剩餘的時間" +L["Adds a bar indicating how much time is left on your Rune of Power."] = "新增狀態條指示你的符文能量剩餘多少時間。" +L["Adds a bar inside the health bar indicating how much damage will be absorbed."] = "在生命條中增加一個條以顯示已吸收多少傷害。" +L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."] = "在生命條中增加一個條以顯示某些人預計將獲得多少治療。" +L["Adds a bar inside the health bar indicating how much healing someone will receive."] = "在生命條中增加一個條以顯示某些人將獲得多少治療。" +L["Adds a bar inside the health bar indicating how much healing will be absorbed and not applied to the player."] = "在生命條中新增一條以指示多少的治療會被吸收並且不會作用到玩家身上。" +L["Adds a mana bar to the player frame for elemental and enhancement shamans."] = "在元素與增強薩滿的玩家框架中添加一個法力條。" +L["Adds a mana bar to the player frame for shadow priests."] = "在暗牧的玩家框架中添加一個法力條。" +L["Adds a Stagger bar for Brewmaster Monks."] = "為釀酒武僧增加一個醉仙緩勁條。" +L["Adds an empty bar that you can put text into as a way of uncluttering other bars."] = "增加一個空的計量條,你可以在裡面輸入文字並用來整理其他的計量條。" +L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."] = "當你處於巨熊或獵豹形態時新增額外的法力條玩家框架上。" +L["Adds rune bars and timers before runes refresh to the player frame."] = "在符文刷新前新增符文條和計時器到玩家框架上。" +L["Adds temporary enchants to the buffs for the player."] = "為玩家的增益新增暫時性附魔效果。" +L["Adds totem bars with timers before they expire to the player frame."] = "在圖騰結束前新增圖騰條的計時器到玩家框架上。" +L["Advanced"] = "進階" +L["Advanced tag management, allows you to add your own custom tags."] = "進階標籤管理,允許你新增自訂的標籤。" +L["AFK"] = "暫離" +L["AFK status"] = "暫離狀態" +L["AFK timer"] = "暫離計時器" +L["AFK:%s"] = "暫離:%s" +L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."] = "點擊匯出後,你可以複製以下的代碼給其他SUF使用者並獲得你的版面編排。" +L["Aggro"] = "獲得仇恨" +L["All aura groups enabled for unit."] = "啟用此單位所有光環群組。" +L["All Auras"] = "所有光環" +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."] = "允許您定位此光環群組到其他人,然後你可以選擇使用哪個位置定位它。|n|n你可以使用這個來複製那些增益和減益在不同分組的預設UI樣式。" +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."] = "允許您透過右鍵點擊取消圖騰。|n|n警告: 如果您啟用此選項,本單位內的項目條將不會在戰鬥中調整。" +L["Allows you to enter a new aura group."] = "允許你建立一個新的光環群組。" +L["Alpha to use for bar backgrounds."] = "計量條背景使用的透明度。" +L["Alpha to use for bar."] = "計量條使用的透明度。" +L["Alt. Power"] = "替代能量" +L["Alt. Power bar"] = "替代的能量條" +L["Alternate power is used for things like quests and dungeons."] = "替代能量被用於像是任務和地城。" +L["Alternate Spell Name"] = "備用的法術名稱" +L["Alternatively friendly spell to use to check range."] = "另外用來檢查範圍的友方法術。" +L["Ammo"] = "彈藥" +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."] = "生命損失值,如果沒有損失則不顯示。使用簡化格式-18500顯示為-18.5k,低於10000的生命值則不簡化。" +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."] = "能量損失值,如果沒有損失則不顯示。使用簡化格式-13850顯示為-13.8k,低於10000的能量值則不簡化。" +L["Anchor point"] = "定位處" +L["Anchor to"] = "定位到" +L["Anchor to another frame"] = "定位到其他框架" +L["Anchor to buffs"] = "定位到增益" +L["Anchor to debuffs"] = "定位到減益" +L["Ancient Kings bar"] = "遠古諸王條" +L["Any auras shown in this indicator will have their total stack displayed."] = "此指標顯示的任何光環都會顯示總堆疊數。" +L["Aquatic"] = "水棲" +L["Arcane Charges"] = "祕法充能" +L["Are you sure you want to delete this aura?"] = "您確定要刪除此光環?" +L["Are you sure you want to delete this filter?"] = "你確定你要刪除這個篩選?" +L["Are you sure you want to delete this indicator?"] = "您確定要刪除此指標?" +L["Are you sure you want to delete this tag?"] = "你確定你要刪除這個標籤?" +L["Are you sure you want to delete this text? All settings for it will be deleted."] = "你確定你要刪除這個文字?相關的所有設定將會被刪除。" +L["Arena"] = "競技場" +L["Arena Pet"] = "競技場寵物" +L["Arena Spec"] = "競技場專精" +L["Arena Target"] = "競技場目標" +L["Arena Target of Target"] = "競技場目標的目標" +L["Arena ToT"] = "競技場 ToT" +L["Arenas"] = "競技場" +L["Ascending"] = "遞增" +L["Assigned Role (DPS/Tank/etc)"] = "角色分配(DPS/坦克/等等)" +L["Astral Power"] = "星體能量" +L["Aura border style"] = "光環邊框樣式" +L["Aura borders"] = "光環外框" +L["Aura Combo Points"] = "光環連擊點" +L["Aura Filters"] = "光環篩選" +L["Aura filters"] = "光環篩選" +L["Aura group"] = "光環群組" +L["Aura groups"] = "光環群組" +L["Aura Groups"] = "光環群組" +L["Aura Indicators"] = "光環指標" +L["Aura indicators"] = "光環指標" +L["Aura name or spell ID"] = "光環名稱或法術ID" +L["Aura types to filter"] = "篩選光環類型" +L["Auras"] = "光環" +L["Auras matching a criteria will automatically show up in the indicator when enabled."] = "當啟用後,匹配條件的光環將自動顯示在這個指標中。" +L["Automatic Auras"] = "自動化光環" +L["B"] = "B" +L["Background"] = "背景" +L["Background alpha"] = "背景透明度" +L["Background color"] = "背景着色" +L["Background/border"] = "背景/邊框" +L["Bag indicator for master looters."] = "拾取分配者的背包標記。" +L["Bar alpha"] = "計量調透明度" +L["Bar color to use to show how much healing someone is about to receive."] = "用來顯示某人收到了多少治療的條顏色。" +L["Bar spacing"] = "計量條間隔" +L["Bar texture"] = "背景材質" +L["Bars"] = "計量條" +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."] = "高於或低於全尺寸選項的條將使用整個單位框架的寬度。|n|n在那兩個數字之間的條在頭像旁邊顯示。" +L["Battleground"] = "戰場" +L["Battleground Pet"] = "戰場寵物" +L["Battleground Target"] = "戰場目標" +L["Battleground Target of Target"] = "戰場目標的目標" +L["Battlegrounds"] = "戰場" +L["Bear"] = "巨熊" +L["BG"] = "戰場" +L["BG Pet"] = "戰場寵物" +L["BG Target"] = "戰場目標" +L["BG ToT"] = "戰場 ToT" +L["Blacklist"] = "黑名單" +L["Blacklist filters"] = "黑名單篩選" +L["Blacklists"] = "黑名單" +L["Blizzard"] = "Blizzard" +L["Border"] = "邊框" +L["Border alpha"] = "邊框透明度" +L["Border color"] = "邊框顏色" +L["Border coloring of stealable, curable and dispellable auras."] = "著色可偷取、可治愈和可驅散的光環邊框。" +L["Border highlighting"] = "邊框高亮" +L["Border thickness"] = "邊框厚度" +L["Boss"] = "首領" +L["Boss Auras"] = "首領光環" +L["Boss Debuffs"] = "首領減益" +L["Boss Target"] = "首領目標" +L["Boss Target of Target"] = "首領目標的目標" +L["Boss ToT"] = "首領 ToT" +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."] = "首領單位框架只在特定戰如血親王議會及砲艇戰中看到,你並不會在每個首領戰中看到它。" +L["Both"] = "兩者" +L["Bottom"] = "底部" +L["Bottom Center"] = "底部中間" +L["Bottom Left"] = "底部左邊" +L["Bottom Right"] = "底部右邊" +L["buff frames"] = "增益效果" +L["Buffs"] = "增益" +L["C"] = "C" +L["Cannot find any profiles named \"%s\"."] = "未能發現 \"%s\" 設置檔" +L["Cast"] = "施法" +L["Cast bar"] = "施法條" +L["Cast icon"] = "施法圖示" +L["Cast interrupted"] = "已中斷施法" +L["Cast name"] = "施法名稱" +L["Cast time"] = "施法時間" +L["Cast uninterruptible"] = "無法中斷施法" +L["Casting"] = "施法中" +L["Cat"] = "獵豹" +L["Category"] = "類別" +L["Center"] = "中間" +L["Changed profile to %s."] = "更改設置檔為 %s" +L["Changes the health bar to the color of any curable debuff."] = "改變生命條的顏色為任何可治癒的減益。" +L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."] = "當單位獲得仇恨時變更生命條顏色為敵對顏色(預設為紅色)。" +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."] = "變更這個組件到計量條,你可以像修改生命條和能量條那樣修改高度和排列。" +L["Channelling"] = "引導性" +L["Checking this will show the indciator on hostile units."] = "勾選此選項會顯示指標在敵方單位。" +L["Checking this will show the indicator on friendly units."] = "勾選此選項會顯示指標在友方單位。" +L["Chi"] = "氣" +L["Chi Points"] = "氣點數" +L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] = "無法拖曳子單位,你必須透過 /shadowuf 來重新定位它。" +L["Class"] = "職業" +L["Class (Smart)"] = "職業 (智能)" +L["Class color tag"] = "職業着色標籤" +L["Class icon"] = "職業圖示" +L["Class Icon"] = "職業圖標" +L["Class icon for players."] = "玩家的職業圖示。" +L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."] = "未著色的職業名稱,請使用 [classcolor][class][close] 如果你想依照職業顏色的話。" +L["Class Role"] = "職業角色職責" +L["Class Specific"] = "職業限定" +L["Class Timer"] = "職業計時器" +L["Class/misc bars"] = "職業/雜項 動作條" +L["Classes"] = "職業" +L["Classification"] = "分類" +L["Classifications"] = "職業類別" +L["Clip"] = "內間距" +L["Close color"] = "關閉着色" +L["Closes a color code, prevents colors from showing up on text that you do not want it to."] = "關閉一個顏色代碼,你不想要使用在文字上的着色將不會顯示。" +L["Code"] = "代碼" +L["Color by class"] = "依照職業着色" +L["Color by reaction on"] = "依照對應類型着色" +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."] = "依照單位的階段性生命值百分比着色,這與生命值選項相同,僅影響計量條上的文字。" +L["Color code for general situation"] = "一般情況下的顏色代碼" +L["Color code for situation"] = "某種情況下的顏色代碼" +L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"] = "職業的顏色代碼,請使用 [classcolor][class][close] 如果妳想按職業著色職業文字" +L["Color code on aggro"] = "獲得仇恨的顏色代碼" +L["Color health by"] = "生命值着色依照" +L["Color on aggro"] = "獲得仇恨着色" +L["Color on curable debuff"] = "可治癒減益著色" +L["Color power by"] = "著色能量根據" +L["Color to use for health bars that are set to be colored by a static color."] = "為生命值着色並設定為固定顏色。" +L["Color to use to show how much damage will be absorbed."] = "用來顯示有多少傷害被吸收了的顏色。" +L["Color to use to show how much healing will e absorbed."] = "用來顯示有多少治療被吸收了的顏色。" +L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."] = "當施法無法中斷時所使用的顏色,僅用於PvE怪物身上。" +L["Color used when a cast is a channel."] = "當施法為引導性法術時所使用的顏色。" +L["Color used when a cast is interrupted either by the caster themselves or by another unit."] = "當施法可以被自已和其他人中斷時所使用的顏色。" +L["Color used when a cast is successfully finished."] = "當施法成功時所使用的顏色。" +L["Color used when an unit is casting a spell."] = "當單位施放法術時所使用的顏色。" +L["Colors"] = "着色" +L["Column growth"] = "列展延方向" +L["Column spacing"] = "列間距" +L["Combat alpha"] = "戰鬥透明度" +L["Combat fader"] = "戰鬥淡出" +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."] = "戰鬥淡出將淡出所有你的框架,並在你進入戰鬥或活動後恢復。" +L["Combat Status"] = "戰鬥狀態" +L["Combat text"] = "戰鬥文字" +L["Combat/resting status"] = "戰鬥/休息狀態" +L["Combo points"] = "連擊點數" +L["Combo Points"] = "連擊點" +L["Configuration to specific unit frames."] = "特定單位框架的配置。" +L["Cooldown rings for"] = "冷卻動畫作用於" +L["Create"] = "建立" +L["Creature type"] = "生物類型" +L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."] = "生物類型,如果單位是惡魔守衛則為惡魔守衛,如果是狼則為狼。" +L["Crown indicator for group leader or assistants."] = "為團長或團隊助理顯示一個皇冠標記。" +L["Cur/Max HP (Absolute)"] = "當前/最大生命值(完整)" +L["Cur/Max HP (Short)"] = "當前/最大生命值(簡化)" +L["Cur/Max HP (Smart)"] = "當前/最大生命值(智能)" +L["Cur/Max power (Absolute)"] = "當前/最大能量值(完整)" +L["Cur/Max power (Druid)"] = "當前/最大能量值(德魯伊)" +L["Cur/Max power (Druid/Absolute)"] = "當前/最大能量值(德魯伊/完整)" +L["Cur/Max power (Secondary)"] = "當前/最大能量值(輔助)" +L["Cur/Max power (Secondary/Absolute)"] = "當前/最大能量值(輔助/完整)" +L["Cur/Max Power (Short)"] = "當前/最大能量值(簡化)" +L["Cur/Max PP (Smart)"] = "當前/最大能量值(智能)" +L["Curable"] = "可治癒" +L["Curable Auras"] = "可治癒光環" +L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."] = "當前和最大生命值,格式為[curhp]/[maxhp],如果單位死亡或離線則由此代替顯示。" +L["Current and maximum power, formatted as [curpp]/[maxpp]."] = "當前和最大能量值,格式為[curpp]/[maxpp]。" +L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."] = "當前生命值,使用簡化格式11500顯示為11.5k,低於10000的生命值則不簡化。" +L["Current HP (Absolute)"] = "當前生命值(完整)" +L["Current HP (Short)"] = "當前生命值(簡化)" +L["Current pet used by a battleground unit."] = "將應用到戰場單位的當前寵物框架。" +L["Current power (Absolute)"] = "當前能量值(完整)" +L["Current power (Druid)"] = "當前能量值(德魯伊)" +L["Current power (Druid/Absolute)"] = "當前能量值(德魯伊/完整)" +L["Current power (Secondary)"] = "當前能量值(輔助)" +L["Current power (Secondary/Absolute)"] = "當前能量值(輔助/完整)" +L["Current Power (Short)"] = "當前能量值(簡化)" +L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."] = "當前能量值,當使用簡化格式12,750顯示為12.7k,低於10,000的能量值則不簡化。" +L["Current target of a battleground unit."] = "戰場單位的當前目標" +L["Current target of target of a battleground unit."] = "戰場單位的當前目標的目標" +L["Currently modifying"] = "目前的設定" +L["Currently used in battlegrounds for showing flag carriers."] = "目前使用在戰場或顯示戴旗者。" +L["Damage absorption (Absolute)"] = "吸收傷害(絕對值)" +L["Damage absorption (Short)"] = "吸收傷害(簡化)" +L["Damage absorption/Name"] = "吸收傷害/名稱" +L["Dark"] = "暗色" +L["Dead"] = "死亡" +L["Debuffs"] = "減益" +L["Decimal percent HP"] = "十進制百分比生命值" +L["Default color"] = "預設顏色" +L["Default font color, any color tags inside individual tag texts will override this."] = "預設字型顏色,任何顏色標籤內部個別的標籤文字會複寫。" +L["Deficit/Unit Name"] = "損失值/單位名稱" +L["Delete"] = "刪除" +L["Delete filter"] = "刪除篩選" +L["Delete link"] = "刪除連結" +L["Descending"] = "遞減" +L["Disable Auras by Class"] = "停用職業光環" +L["Disable Blizzard Cooldown Count"] = "停用暴雪冷卻計時" +L["Disable event discovery"] = "停用檢測事件" +L["Disable OmniCC Cooldown Count"] = "停用OmniCC冷卻計時" +L["Disable vehicle swap"] = "停用載具轉換" +L["Disabled"] = "已停用" +L["Disabled for %s."] = "已停用%s" +L["Disabled in %s"] = "在%s已停用" +L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."] = "在所有SUF單位框架光環不顯示冷卻計時。" +L["Disables the unit frame from turning into a vehicle when the player enters one."] = "當玩家進入載具時停用單位框架轉換為載具。" +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!."] = "當進入%s時停用此頁面上的一個模組。如果你不希望這種事情發生的話就不要停用!。" +L["Disabling unit modules in various instances."] = "在各種不同副本中停用單位模組。" +L["Dismissable Totem bars"] = "可解除圖騰列" +L["Dispellable/Stealable"] = "可驅散/可偷取" +L["Display"] = "顯示" +L["Display enemy buffs using LibClassicDuration data."] = "使用LibClassicDurations數據顯示敵人的增益。" +L["DND"] = "勿擾" +L["DND:%s"] = "勿擾:%s" +L["Documentation"] = "使用說明" +L["Don't hide when empty"] = "空的時候不隱藏" +L["Don't use a filter"] = "不使用篩選" +L["Down"] = "下" +L["Druid form"] = "德魯伊形態" +L["Druid form (Short)"] = "德魯伊形態(簡化)" +L["Druid mana bar"] = "德魯伊法力條" +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."] = "鑒於假單位的性質,%s的施法條超級沒有效率,最多只能注意到0.10秒施法的改變。" +L["Edge size"] = "邊緣大小" +L["Edit tag"] = "編輯標籤" +L["Editing %s"] = "正在編輯%s" +L["Elite"] = "精英" +L["Empty bar"] = "空計量條" +L["Enable %s"] = "啟用%s" +L["Enable buffs"] = "啟用增益" +L["Enable debuffs"] = "啟用減益" +L["Enable enemy buff tracking"] = "啟用敵人增益追踪" +L["Enable for friendlies"] = "啟用於友方單位" +L["Enable for hostiles"] = "啟用於敵方單位" +L["Enable frequent updates"] = "啟用刷新頻率" +L["Enable indicator"] = "啟用標記" +L["Enable Indicators"] = "啟用標記" +L["Enable temporary enchants"] = "啟用暫時性附魔" +L["Enable units"] = "啟用單位" +L["Enabled for %s."] = "啟用於 %s" +L["Enabled in %s"] = "在%s已啟用" +L["Enabled Units"] = "啟用單位" +L["Enables configuration mode, letting you move and giving you example frames to setup."] = "啟用配置模組,讓你設定並移動框架樣板。" +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."] = "啟用進階設定讓你使用更多的配置選項,你可以調整細部結構,預設為不啟用。" +L["Energy"] = "能量" +L["Enlarge auras for"] = "放大光環於" +L["Error"] = "錯誤" +L["Essence"] = "精華" +L["Events"] = "事件" +L["Events that should be used to trigger an update of this tag. Separate each event with a single space."] = "用來觸發此更新標籤的事件,用單獨的區隔來分開每個事件。" +L["Everywhere else"] = "其他任何地方" +L["Export"] = "匯出" +L["F"] = "F" +L["Fades out the unit frames of people who are not within range of you."] = "當有人超出你的距離範圍時淡出單位框架。" +L["Failed to import layout, error:|n|n%s"] = "匯入版面編排失敗,錯誤:|n|n%s" +L["Failed to load ShadowedUF_Options, cannot open configuration. Error returned: %s"] = "載入ShadowedUF_Options失敗,無法開啟配置。錯誤返回:%s" +L["Failed to save tag, error:|n %s"] = "儲存標記失敗,錯誤|n %s" +L["Female"] = "女性" +L["Filter type"] = "篩選類型" +L["Filtering both buffs and debuffs"] = "篩選增益和減益兩者" +L["Filtering buffs only"] = "僅篩選增益" +L["Filtering debuffs only"] = "僅篩選減益" +L["Filters"] = "篩選" +L["Finished cast"] = "完成施法" +L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."] = "標記標籤為刷新頻率。不論任何事件它將為計時器不斷刷新。" +L["Flight"] = "飛行" +L["Flips coloring so the bar color is shown as the background color and the background as the bar"] = "反轉顏色為計量條顏色變成背景顏色,而背景顏色變成計量條顏色" +L["Focus"] = "專注" +L["Focus Target"] = "專注目標" +L["Font"] = "字型" +L["Food"] = "食物" +L["For configuring aura indicators on unit frames."] = "在單位框架上配置相關光環標記" +L["For target/focus"] = "於目標/專注" +L["Forces a static color to be used for the background of all bars"] = "為所有計量條的背景使用固定顏色" +L["Frame"] = "框架" +L["Frame alpha when you are out of combat while having no target and 100% mana or energy."] = "當你沒有目標且100%法力或能量時脫離戰鬥後的框架透明度。" +L["Frame alpha while this unit is in combat."] = "當此單位在戰鬥中時的框架透明度。" +L["Frames"] = "框架" +L["Friendly"] = "友好" +L["Fuel"] = "燃料" +L["Full size after"] = "全尺寸後" +L["Full size before"] = "全尺寸前" +L["Fury"] = "怒氣" +L["General"] = "一般" +L["General configuration to all enabled units."] = "所有已啟用單位的一般配置。" +L["General threat situation"] = "一般仇恨條件" +L["Ghost"] = "靈魂" +L["Ghoul bar"] = "食屍鬼條" +L["Global"] = "總體" +L["Global configurating will let you mass enable or disable aura groups for multiple units at once."] = "通用設置會讓你在多個單位一次性大量啟用或停用光環群組。" +L["Gold checkmark - Enabled in this zone / Grey checkmark - Disabled in this zone / No checkmark - Use the default unit settings"] = "金色勾選 - 在此地區已啟用 / 灰色勾選 - 在此地區已停用 / 沒有勾選 - 使用預設的單位設定" +L["Green (<30% HP)"] = "綠色(<30%HP)" +L["Group %d"] = "小隊 %d" +L["Group by"] = "小隊依照" +L["Group number"] = "小隊" +L["Group row spacing"] = "小隊間間距" +L["Groups"] = "小隊" +L["Groups per row"] = "每行小隊" +L["Groups to show"] = "顯示小隊" +L["Growth"] = "增長" +L["Guild name"] = "公會名稱" +L["Half health"] = "一半的生命值" +L["Has Aggro"] = "引起仇恨" +L["Heal absorb"] = "吸收治療" +L["Heal Absorb (Absolute)"] = "治療吸收(完整)" +L["Heal Absorb (Short)"] = "治療吸收(簡化)" +L["Heal absorbs"] = "治療吸收" +L["Healing absorb"] = "治療吸收" +L["Health"] = "生命值" +L["Health bar"] = "生命條" +L["Health bar color for friendly units."] = "友好單位的生命條顏色。" +L["Health bar color for hostile units."] = "敵對單位的生命條顏色。" +L["Health bar color for neutral units."] = "中立單位的生命條顏色。" +L["Health bar color for units with aggro."] = "仇恨單位的血量條顏色" +L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."] = "你不能攻擊使用敵對生命條顏色的單位,用於對應着色。" +L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."] = "生命條顏色從100%->0%的過渡來着色,也可用於你的寵物快樂值。" +L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."] = "生命條顏色從100%->50%的過渡來着色,也可用於你的寵物快樂值。" +L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."] = "生命條顏色從50%->100%的過渡來着色,也可用於你的寵物快樂值。" +L["Health color"] = "生命值顏色" +L["Health percent"] = "生命值百分比" +L["Height"] = "高" +L["Help"] = "說明" +L["Hide %s"] = "隱藏%s" +L["Hide %s frames"] = "隱藏%s框架" +L["Hide bar when empty"] = "當計量條為空時隱藏" +L["Hide Blizzard"] = "隱藏遊戲內建框架" +L["Hide in <=5-man raids"] = "當<=5人團隊時隱藏" +L["Hide in >5-man raids"] = "當>5人團隊時隱藏" +L["Hide in any raid"] = "任何團隊中隱藏" +L["Hide tooltips in combat"] = "戰鬥中隱藏提示訊息" +L["Hides the cast bar if there is no cast active."] = "如果當前沒有施法動作則隱藏施法條。" +L["Hides the power bar unless the class has mana."] = "隱藏能量條除非此職業有法力。" +L["Hiding and showing various aspects of the default UI such as the player buff frames."] = "隱藏和顯示各種預設的插件框架如玩家增益框架。" +L["High"] = "高" +L["High health"] = "高生命值" +L["Highlight"] = "高亮" +L["Highlight units that are "] = "高亮單位是" +L["Highlight units that are debuffed with something you can cure."] = "高亮你可以消除減益的單位。" +L["Highlight units that are rare."] = "高亮稀有單位。" +L["Highlight units that have aggro on any mob."] = "高亮獲得怪物仇恨的單位。" +L["Highlight units that you are targeting or have focused."] = "高亮你當前或專注目標的單位。" +L["Highlight units when you mouse over them."] = "當你的滑鼠移動到單位時高亮。" +L["Holy power"] = "聖光能量" +L["Holy Power"] = "神聖能量" +L["Hostile"] = "敵對" +L["How close the frame should clip with the border."] = "框架和邊框的間距。" +L["How far the background should be from the unit frame border."] = "背景和單位框架邊框的距離。" +L["How large the background should tile"] = "背景並列的大小" +L["How large the edges should be."] = "邊緣的大小。" +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."] = "樣板中每列顯示多少光環,輸入2將創建兩行而每行均可設定。" +L["How many auras to show in a single row."] = "單行顯示多少光環。" +L["How many Chi points you currently have."] = "你目前有多少的氣點。" +L["How many groups should be shown per row."] = "每行顯示多少小隊。" +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!"] = "樣板中顯示多少人助攻此單位,如果你的目標為你自己則將顯示多少人的目標為你的目標。也包含你自己!" +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!"] = "樣板中顯示你的團隊有多少人的目標為此單位,如果你的目標為你自己則將顯示多少人以你為目標。也包含你自己!" +L["How many rows total should be used, rows will be however long the per row value is set at."] = "顯示多少總行數,不管你設定每行數為多少。" +L["How many seconds a totem has left before disappearing."] = "在圖騰消失前還剩幾秒。" +L["How many seconds before a rune recharges."] = "在符文充能前還有幾秒。" +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."] = "兩次更新之間有幾秒。|n[警告] 通過將頻率設置為0,每一個框架的重繪都會更新,如果你想禁止頻繁更新請取消勾選並且不要設置為0。" +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."] = "此計量條應獲得多少框架總高度,這是個比重,設定更高將獲得更多。" +L["How much spacing should be between each new row of groups."] = "在小隊每個新行中需要多少間距。" +L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."] = "在單位框架中所有計量條之間需要多少間距,負值為更遠,正值為更近,0為無間距。" +L["How much weight this should use when figuring out the total text width."] = "當計算出總文字寬度時應使用多少比重。" +L["How the frames should grow when a new column is added."] = "當新增一個新列時框架的增長方向為何。" +L["How the rows should grow when new group members are added."] = "當新加入隊伍成員時框架的增長方向為何。" +L["How you want this aura to be anchored to the unit frame."] = "你要此光環定位到單位框架的何處。" +L["Icon Size"] = "圖示尺寸" +L["If multiple auras are shown in the same indicator, the higher priority one is shown first."] = "如果多個光環顯示在一個指標中,高優先順序的首先顯示。" +L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."] = "如果以名稱輸入的必須是很準確的,因為它是區分大小寫的。或者您也可以使用法術ID來代替。" +L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."] = "如果單位擁有傷害吸收護盾,它會顯示吸收的絕對值,否則顯示單位名稱。" +L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."] = "如果此單位受到治療,它將顯示完整治療量,否則顯示單位名稱。" +L["If the unit is a player then class is returned, if it's a NPC then the creature type."] = "如果單位為玩家則顯示職業,如果是NPC則顯示NPC類型。" +L["If the unit is a player then race is returned, if it's a NPC then the creature type."] = "如果單位為玩家則顯示種族,如果是NPC則顯示NPC類型。" +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."] = "如果你不這樣做,你將無法使用任何連擊點數功能 (氣、聖能、連擊點、光環點..等等) 直到你這樣做。" +L["Imp & Dreadstalker bar"] = "小鬼 & 恐懼獵犬條" +L["Import"] = "匯入" +L["Import unit frame positions"] = "匯入單位框架位置" +L["Import visibility settings"] = "匯入可見的設定" +L["In range alpha"] = "在距離內的透明度" +L["Inactive alpha"] = "無效的透明度" +L["Incoming absorb"] = "將到來的吸收" +L["Incoming absorbs"] = "到來的吸收" +L["Incoming heal"] = "受到的治療" +L["Incoming heal (Absolute)"] = "接收治療(完整的)" +L["Incoming heal (Percent)"] = "受到治療(百分比)" +L["Incoming heal (Short)"] = "受到治療(簡化)" +L["Incoming heal/Name"] = "受到治療/名字" +L["Incoming heals"] = "受到的治療量" +L["Index"] = "索引" +L["Indicator color"] = "標記顏色" +L["Indicator for the current pet happiness."] = "當前寵物快樂度的指標。" +L["Indicator name"] = "標記名稱" +L["Indicator this aura should be displayed in."] = "要顯示此光環的標記。" +L["Indicators"] = "標記" +L["Insanity"] = "瘋狂" +L["Inset"] = "插入" +L["Inside Bottom Left"] = "內部左下" +L["Inside Bottom Right"] = "内部右下" +L["Inside Center"] = "內部居中" +L["Inside Center Left"] = "內部居中靠左" +L["Inside Center Right"] = "內部居中靠右" +L["Inside Top Left"] = "內部頂部靠左" +L["Inside Top Right"] = "內部頂部靠右" +L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."] = "這個標記將顯示光環的圖標而不是單純的顏色。" +L["Interrupted"] = "已中斷" +L["Invalid interval entered, must be a number."] = "無效的輸入,必須為數字。" +L["Invalid spell \"%s\" entered."] = "無效的\"%s\"法術輸入。" +L["Invert colors"] = "反轉顏色" +L["Layout manager"] = "版面編排管理" +L["Leader / Assist"] = "團長/助理" +L["Left"] = "左邊" +L["Left Bottom"] = "左邊底部" +L["Left Center"] = "左邊居中" +L["Left text"] = "左邊文字" +L["Left Top"] = "左邊頂部" +L["Let's you modify the base font size to either make it larger or smaller."] = "讓妳可以修改基本的字型大小,不是變大就是變小。" +L["Level"] = "等級" +L["Level %s - %s: %s/%s (%.2f%% done)"] = "等級%s - %s:%s/%s(%.2f%%已完成)" +L["Level %s - %s: %s/%s (%.2f%% done), %s rested."] = "等級%s - %s:%s/%s(%.2f%%已完成),%s休息經驗值。" +L["Level (Colored)"] = "等級(已着色)" +L["Level without any coloring."] = "等級不使用任何着色。" +L["Light"] = "亮度" +L["Link"] = "連結" +L["Link from"] = "連結從" +L["Link to"] = "連結至" +L["Linked spells"] = "已連結法術" +L["Lock frames"] = "鎖定框架" +L["Locks the unit frame positionings hiding the mover boxes."] = "鎖定框架位置。" +L["Low health"] = "低生命值" +L["M"] = "M" +L["MA ToT"] = "主助攻 ToT" +L["Maelstrom"] = "氣旋" +L["Main Assist"] = "主助攻" +L["Main Assist Target"] = "主助攻目標" +L["Main Assist Target of Target"] = "主助攻目標的目標" +L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."] = "主助攻設置依據暴雪主助攻系統或是使用首領插件。" +L["Main Tank"] = "主坦克" +L["Main Tank Target"] = "主坦克目標" +L["Main Tank Target of Target"] = "主坦克目標的目標" +L["Main Tank's are set through the Raid frames, or through selecting the Tank role."] = "主坦克藉由團隊框架設置,或者通過選擇坦克的角色類型。" +L["Male"] = "男性" +L["Mana"] = "法力" +L["Manage Aura Filters"] = "管理光環篩選" +L["Management"] = "管理" +L["Manual position"] = "手動位置" +L["Master Looter"] = "隊長分配" +L["Max columns"] = "最大列數量" +L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."] = "最大生命值,使用簡化格式17750顯示為17.7k,低於10000的生命值則不簡化。" +L["Max HP (Absolute)"] = "最大生命值(完整)" +L["Max HP (Short)"] = "最大生命值(簡化)" +L["Max power (Absolute)"] = "最大能量值(完整)" +L["Max power (Short)"] = "最大能量值(簡化)" +L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."] = "最大能量值,使用簡化格式16000顯示為16k,低於10000的能量值則不簡化。" +L["Max rows"] = "最大行數" +L["Medium"] = "中" +L["Minion"] = "爪牙" +L["Miscellaneous"] = "雜項" +L["Missing HP (Short)"] = "生命損失值(簡化)" +L["Missing power (Short)"] = "能量損失值(簡化)" +L["Monochrome Outline"] = "單色描邊" +L["Moonkin"] = "梟獸" +L["MT ToT"] = "主坦 ToT" +L["Mushroom bar"] = "蘑菇條" +L["Mushrooms"] = "蘑菇" +L["Name"] = "名稱" +L["Name (Abbreviated)"] = "名稱(縮寫)" +L["Name of a friendly spell to check range."] = "用以檢查距離的友方法術名稱。" +L["Neutral"] = "中立" +L["Never (Disabled)"] = "從不(停用)" +L["New aura group"] = "新光環群組" +L["New filter"] = "新篩選" +L["None"] = "無" +L["None (Disabled)"] = "無 (停用)" +L["NPCs only"] = "僅NPC" +L["Off:%s"] = "離線:%s" +L["Offline"] = "離線" +L["Offline timer"] = "離線計時器" +L["Ok"] = "OK" +L["On %s units"] = "在%s單位" +L["On aggro"] = "在獲得仇恨" +L["On curable debuff"] = "在消除減益" +L["On elite mobs"] = "在精英目標" +L["On Friendly Units"] = "在友方單位" +L["On Hostile Units"] = "在敵方單位" +L["On mouseover"] = "在鼠標懸停" +L["On rare mobs"] = "在稀有目標" +L["Only active this aura inside an indicator if the group member does not have the aura."] = "標記只有在該隊員沒有此光環情況下生效。" +L["Only apply the selected filters to buffs on friendly units and debuffs on hostile units, and otherwise show all auras."] = "選擇的篩選只有應用在友方單位的增益與敵對單位的減益,否則則顯示所有光環。" +L["Only auras you specifically cast will be shown."] = "只顯示你施放的特定光環。" +L["Only show if missing"] = "只會顯示缺少的" +L["Only show self cast auras"] = "只顯示自己施放的光環" +L["Only show when mana"] = "只在有法力時才顯示" +L["Or you can set a position manually"] = "或你可手動設定位置" +L["Order"] = "排列" +L["Other Party/Phase Status"] = "其他隊伍/相位狀態" +L["Out of range alpha"] = "超出距離透明度" +L["Outline"] = "細體" +L["Outside bar limit"] = "外圍計量條限制" +L["Override background"] = "替代背景" +L["Override color"] = "覆蓋顏色" +L["Override list"] = "覆蓋清單" +L["Override list filters"] = "覆蓋清單過濾" +L["Override lists"] = "覆蓋清單" +L["Pain"] = "痛" +L["Party"] = "隊伍" +L["Party frames are hidden while in a raid group with more than 5 people inside."] = "當在超過5人的團隊中時隱藏隊伍框架。" +L["Party frames are hidden while in any sort of raid no matter how many people."] = "當在任何人數的團隊中時隱藏隊伍框架。" +L["Party instances"] = "隊伍副本" +L["Party Pet"] = "隊伍寵物" +L["Party Target"] = "隊伍目標" +L["Party Target of Target"] = "隊伍目標的目標" +L["Party ToT"] = "隊伍ToT" +L["Per column"] = "每欄" +L["Per row"] = "每行" +L["Percent HP"] = "百分比生命值" +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."] = "百分比顯示玩家目前受到治療的生命值,如果他們有100,000總生命並且受到15,000的治療則顯示15%。" +L["Percent power"] = "百分比能量值" +L["Percentage of width the portrait should use."] = "頭像使用的寬度百分比。" +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."] = "允許治療吸收條突出單位框架的百分率。130%表示會突出單位框架30%,100%表示不會突出框架。" +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."] = "吸收傷害條可以突出單位框架多少的百分比值。130%意指突出30%,100%意指不會突出。" +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."] = "距離單位框架超過多遠的百分比值才能治療。130%意指超過30%,100%意指不超過。" +L["Pet"] = "寵物" +L["Pet Battle"] = "寵物戰鬥" +L["Pet Happiness"] = "寵物快樂指數" +L["Pet Target"] = "寵物目標" +L["Player"] = "玩家" +L["player alt. power"] = "玩家替代能量" +L["player cast bar"] = "玩家施法條" +L["Player Class"] = "玩家職業" +L["player power frames"] = "玩家能量框架" +L["Player threat"] = "玩家仇恨" +L["Players only"] = "僅玩家" +L["Players will be colored by class."] = "玩家將按照職業著色。" +L["Point"] = "點" +L["Portrait"] = "頭像" +L["Portrait type"] = "頭像類型" +L["Position"] = "位置" +L["Positioning"] = "定位" +L["Power"] = "綜合能量" +L["Power bar"] = "綜合能量條" +L["Power Type"] = "能量類型" +L["Prevents unit tooltips from showing while in combat."] = "當在戰鬥中時顯示頭像單位的提示訊息。" +L["Priest mana bar"] = "牧師法力條" +L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."] = "主要的生命條顏色,如果有必要則獲得仇恨或按對應類型的顏色可覆蓋。" +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."] = "主要意義在於著色能量條,根據職業著色只限於玩家,非玩家單位能量條將為預設。" +L["Prioritize buffs"] = "優先增益" +L["Priority"] = "優先順序" +L["Programming in Lua"] = "編輯Lua" +L["PvP Flag"] = "PvP標記" +L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."] = "PVP標記,部落PVP為部落標記及聯盟PVP為聯盟標記。" +L["PvP Flags"] = "PvP標記" +L["PVP timer"] = "PVP計時器" +L["PVP:%s"] = "PVP:%s" +L["Quest Boss"] = "任務首領" +L["Race"] = "種族" +L["Race (Smart)"] = "種族(智能)" +L["Rage"] = "怒氣" +L["Raid"] = "團隊" +L["Raid assisting unit"] = "團隊助攻單位" +L["Raid frames are hidden while in a raid group with 5 or less people inside."] = "當團隊人數5個或更少,隱藏團隊框架。" +L["Raid instances"] = "團隊副本" +L["Raid Misc"] = "團隊雜項" +L["Raid pet"] = "團隊寵物" +L["Raid Role"] = "團隊角色" +L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."] = "團隊角色標記,主坦克顯示為盾,主助攻顯示為劍。" +L["Raid Target"] = "團隊目標" +L["Raid target indicator."] = "團隊目標標記。" +L["Raid targeting unit"] = "團隊目標單位" +L["Range Checker"] = "距離確認" +L["Range indicator"] = "距離標記" +L["Rare"] = "稀有" +L["Rare Elite"] = "稀有精英" +L["Rare indicator"] = "稀有標記" +L["Rather than bars filling from left -> right, they will fill from bottom -> top."] = "讓條的填充不是從左→右,它會從底部→頂部。" +L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."] = "對應顏色代碼,依照對應的單位名稱顏色來使用[reactcolor][name][close]。" +L["Reaction color tag"] = "對應顏色標籤" +L["Ready Status"] = "準備狀態" +L["Ready status of group members."] = "小隊成員的準備就緒狀態。" +L["Red (>70% HP)"] = "紅色(>70%HP)" +L["Relative point"] = "相對點" +L["Resources"] = "來源" +L["Resurrect Status"] = "復活狀態" +L["Returns + if the unit is an elite or rare elite mob."] = "如果單位為精英或稀有精英怪則顯示+。" +L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."] = "依照你的目標的仇恨情況來對應顏色代碼,紅色為獲得仇恨,橘色為高仇恨及黃色為注意仇恨。" +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."] = "依照所有單位的仇恨情況來對應顏色代碼:紅色為獲得仇恨,橘色為高仇恨及黃色為注意仇恨。" +L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."] = "在你的當前目標顯示你的仇恨值百分比0-100%。" +L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."] = "顯示當前生命值百分比,如果單位已死亡或離線則顯示對應的狀態。" +L["Returns current power as a percentage."] = "顯示當前能量值百分比。" +L["Returns Rare if the unit is a rare or rare elite mob."] = "如果是稀有或者稀有精英怪則顯示稀有。" +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."] = "依照單位的一般仇恨情況顯示文字:Aggro(仇恨)你成為被仇恨目標,High(高)仇恨值很高快成為目標和Medium(中)小心仇恨值正在上升。|n這個不能用在目標的目標或是焦點目標類型的單位。" +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."] = "依照所有單位的一般仇恨情況顯示文字:獲得仇恨為獲得仇恨,高為拉高仇恨,中為一般警告。" +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."] = "依照你的目標的仇恨情況顯示顏色:獲得仇恨為獲得仇恨,高為接近坦克仇恨,中為警告注意仇恨。" +L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."] = "依照目標相對於你的等級來對應顏色代碼。如果你不能攻擊他們則不對應顏色。" +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."] = "依照一般的仇恨情況顯示顏色: 紅色為獲得仇恨,橘色為高威脅值並且黃色需要當心。|n這個不能用在目標的目標或是焦點目標類型的單位。" +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."] = "依照單位的威脅值百分比顯示縮放,如果你把這放在隊伍成員上,你會看到他們從任何敵方怪物上得到的威脅百分比。百分比在 0 - 100%之間。|n這個不能用在目標的目標或是焦點目標類型的單位。" +L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."] = "顯示單位的當前形態如果為德魯伊,獵豹為獵豹形態,梟獸為梟獸形態等等。" +L["Returns the units sex."] = "顯示單位性別。" +L["Reverse fill"] = "反向填充" +L["Right"] = "右邊" +L["Right Bottom"] = "右邊底部" +L["Right Center"] = "右邊居中" +L["Right text"] = "右邊文字" +L["Right Top"] = "右邊頂部" +L["Role the unit is playing."] = "單位扮演的角色。" +L["Row growth"] = "行延展方向" +L["Row offset"] = "行偏移量" +L["Rune bar"] = "符文條" +L["Rune of Power"] = "符文能量" +L["Rune of Power bar"] = "符文能量條" +L["Rune Timer"] = "符文計時器" +L["Runes"] = "符文" +L["Runic Power"] = "符能" +L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."] = "等同於[color:sit]如果你獲得仇恨除了只顯示紅色,不再顯示黃-->橘-->紅" +L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."] = "等同於[unit:color:sit]如果單位獲得仇恨除了只顯示紅色,不再顯示黃-->橘-->紅" +L["Scale"] = "比例" +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."] = "縮放那些你施放或可法術偷取的光環,任何數字大於100%的將比預設的大,任何小於100%的將比預設的小。" +L["Scaled aura size"] = "縮放光環尺寸" +L["Scaled threat percent"] = "仇恨百分比比例" +L["Screen"] = "螢幕" +L["Search"] = "搜尋" +L["Search tags"] = "搜尋標籤" +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."] = "查看下列的使用說明來為資訊及樣板建立標籤,如果你只想要基本的Lua或WoW API資訊請查看Lua編譯及WoW編譯的連結。" +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."] = "選擇你想要更改的單位,任何設置的改變都會改變你已選擇的單位。如果你想要定位或修改團隊/小隊單位的特定設置,你需要透過它們的選項來實現。|n|nShift + 點擊一個單位來選擇全部或反選全部。" +L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."] = "從左邊面板選擇一個標籤文字來修改標籤。在當前面板可以修改寬度,大小和坐標。" +L["Separate raid frames"] = "獨立團隊框架" +L["Set Filter Zones"] = "設置篩選區域" +L["Sex"] = "性別" +L["Shadow Orbs"] = "暗影寶珠" +L["Shaman mana bar"] = "薩滿法力條" +L["Short classification"] = "簡化職業類別" +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."] = "怪物分類簡稱,稀有為R,稀有精英為R +,精英為+,首領為B,爪牙為M,不包含在這些當中的什麼都不顯示。" +L["Short elite indicator"] = "簡化精英標記" +L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."] = "簡化[druidform]的形式,C=獵豹,B=熊,F=飛行等等。" +L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."] = "簡化傷害吸收,如果13,000的傷害被吸收,將會顯示為13K。" +L["Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k."] = "簡化治療吸收值,如果17,000的治療量被吸收,則顯示為17K。" +L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."] = "簡化顯示受到治療量,如13,000治療量顯示為13k。" +L["Show a background behind the bars with the same texture/color but faded out."] = "顯示相同材質和顏色的背景在計量條的後面但淡出。" +L["Show any other auras"] = "顯示任何其他光環" +L["Show as bar"] = "計量條中顯示" +L["Show aura duration"] = "顯示光環持續時間" +L["Show aura icon"] = "顯示光環圖示" +L["Show auras stack"] = "顯示光環疊加" +L["Show background"] = "顯示背景" +L["Show boss debuffs"] = "顯示首領減益" +L["Show buffs before debuffs when sharing the same anchor point."] = "當定位在相同錨點時,增益顯示在減益前面。" +L["Show cast name"] = "顯示施法名稱" +L["Show cast time"] = "顯示施法時間" +L["Show castable on other auras"] = "顯示可施放的其他光環" +L["Show casted by boss"] = "顯示首領施放的" +L["Show curable debuffs"] = "顯示可治癒的減益" +L["Show curable/removable auras"] = "顯示可治癒/可驅散的光環" +L["Show Heal Absorbs"] = "顯示治療吸收值" +L["Show icon durations"] = "顯示圖示持續時間" +L["Show incoming absorbs"] = "顯示受到的吸收" +L["Show incoming heals"] = "顯示受到的治療" +L["Show inside"] = "顯示在內部" +L["Show party as raid"] = "團隊中顯示隊伍" +L["Show player in party"] = "隊伍中顯示玩家" +L["Show your auras"] = "顯示你的光環" +L["Shows a bar for alternate power info (used in some encounters)"] = "顯示替代的能量條資訊(在某些對戰中使用)" +L["Shows a cooldown wheel on the indicator with how much time is left on the aura."] = "於標記上顯示冷卻輪,提示還有多長時間光環結束冷卻。" +L["Shows AFK, DND or nothing depending on the units away status."] = "依照單位暫離狀態來顯示暫離,勿擾或不顯示任何東西。" +L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."] = "顯示戰鬥反饋,單位受到的最後治療量,最後是否有治療到,抵抗,免疫等等。" +L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."] = "顯示完整當前和最大生命值,17500的生命值顯示為17500。" +L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."] = "顯示當前完整和最大能量值,18,000的能量值顯示為18,000。" +L["Shows current group number of the unit."] = "顯示單位的當前小隊編號。" +L["Shows current health value in absolute form meaning 15000 health is shown as 15000."] = "顯示完整當前生命值,15000的生命值顯示為15000。" +L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."] = "顯示當前完整能量值,15,000的能量值顯示為15,000。" +L["Shows debuffs cast by a boss."] = "顯示首領施放的減益。" +L["Shows debuffs that you can cure."] = "顯示您可以治癒的減益。" +L["Shows how long an unit has been AFK or DND."] = "顯示單位暫離或勿擾多久。" +L["Shows how long an unit has been offline."] = "顯示單位離線多久。" +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."] = "顯示PVP標記消失的時間, 不會在手動開啟PVP或在一個敵對區域中顯示。|n|n這個僅對你自身有效, 你不能使用他來查看你的小隊或團隊的PVP標記消失時間。" +L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."] = "顯示完整最大生命值,14000生命值顯示為14000。" +L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."] = "顯示完整最大能量值,1,3000能量值顯示為13,000。" +L["Shows Offline, Dead, Ghost or nothing depending on the units current status."] = "依照單位當前狀態來顯示離線,死亡,靈魂或不顯示任何東西。" +L["Shows that a NPC is a boss for a quest."] = "顯示一個NPC為任務的首領" +L["Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000."] = "顯示醉仙緩勁化解傷害的絕對值,如果化解了16,000的傷害,顯示為16,000。" +L["Shows the current staggered damage, if 12,000 damage is staggered, shows 12k."] = "顯示醉仙緩勁當前化解的傷害,如果化解了12,000的傷害,顯示為12k 。" +L["Show's the units guild name if they are in a guild."] = "如果有公會則顯示單位的公會名稱。" +L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."] = "使用壹個小數點的百分比來顯示生命值, 這意味著 61 / 110 生命值將顯示為 55.4%." +L["Shows what kind of pet the unit is for pet battles."] = "顯示什麼種類的寵物在寵物戰鬥的單位。" +L["Shows when a party member is in a different phase or another group."] = "顯示當隊友是在不同相位或是其它的團體。" +L["Simple aura filtering by whitelists and blacklists."] = "簡易的增益和減益篩選於白名單和黑名單。" +L["Size"] = "大小" +L["Smart Friendly/Hostile Filter"] = "智能友方/敵對篩選" +L["Smart level"] = "智能等級" +L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."] = "智能等級,首領顯示為首領,等級50的精英怪顯示為+50,等級80顯示為80。" +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."] = "為[curmaxhp]顯示智能數值,數值低於1,000,000顯示為此,數值高於1,000,000顯示為1m。" +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."] = "為[curmaxpp]顯示智能數值,數值低於1,000,000顯示為此,數值高於1,000,000顯示為1m。" +L["Solid color to use in the indicator, only used if you do not have use aura icon enabled."] = "標記使用單色,僅限於您沒有啟用光環圖示下使用。" +L["Sort method"] = "分類方式" +L["Sort order"] = "分類排列" +L["Sorting"] = "分類" +L["Soul Shards"] = "靈魂裂片" +L["Soul shards"] = "靈魂碎片" +L["Spacing"] = "間隔" +L["Spacing between each row"] = "每行之間的間隔" +L["Spell ID %s"] = "法術 ID %s" +L["Spell Name"] = "法術名稱" +L["Spell Name/ID"] = "法術名稱/ID" +L["Spell you want to link to a primary aura, the casing must be exact."] = "您想要連結到主光環的法術,法術名稱必須精確。" +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."] = "為每個團隊隊伍分割團隊框架為單獨的框架。|n請注意! 你不能拖曳單獨的每個隊伍框架,但可以透過在行和列延展選項中設置他們的延展方向。" +L["Stagger"] = "醉仙緩勁" +L["Stagger (Monk)"] = "醉仙緩勁 (武僧)" +L["Stagger (Monk/Absolute)"] = "醉仙緩勁 (武僧/絕對值)" +L["Stagger bar"] = "醉仙緩勁條" +L["Stagger bar color when the staggered amount is <30% of your HP."] = "當醉仙緩勁數值小於生命值30%時,醉仙緩勁條的顏色。" +L["Stagger bar color when the staggered amount is >30% of your HP."] = "當醉仙緩勁數值大於生命值30%時,醉仙緩勁條的顏色。" +L["Stagger bar color when the staggered amount is >70% of your HP."] = "當醉仙緩勁數值大於生命值70%時,醉仙緩勁條的顏色。" +L["Static"] = "休息" +L["Statue"] = "雕像" +L["Statue bar"] = "雕像條" +L["Status"] = "狀態" +L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."] = "狀態標記,如果單位目前戰鬥中時顯示。如果你已重置也會被顯示。" +L["Stealable/Curable/Dispellable"] = "可偷取/可治癒/可驅散" +L["Style of borders to show for all auras."] = "為所有光環邊框顯示樣式。" +L["Summon Pending"] = "聽候召喚" +L["T"] = "T" +L["Tag list"] = "標籤清單" +L["Tag name"] = "標籤名稱" +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]."] = "你用來存取此代碼的標籤,不要使用方或圓括號,它會自動加入。例如,你輸入\"foobar\"就會自動變成[foobar]來存取。" +L["Tags"] = "標籤" +L["Talent spec of your arena opponents."] = "您競技場對手的天賦專精。" +L["Target"] = "目標" +L["Target of Target"] = "目標的目標" +L["Target of Target of Target"] = "目標的目標的目標" +L["Test Aura"] = "測試光環" +L["Test spell"] = "測試法術" +L["Text"] = "文字" +L["Text Management"] = "文字管理" +L["Text name"] = "文字名稱" +L["Text name that you can use to identify this text from others when configuring."] = "你可以從其他的使用此識別文字來配置文字名稱。" +L["Text parent"] = "文字來源" +L["Text/Tags"] = "文字/標籤" +L["The blacklist \"%s\" already exists."] = "\"%s\"已經存在於黑名單。" +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."] = "以下勾選框將允許你啟用或停用單位。|n|n|cffff2020警告!|r目標的目標相比其他單位有更高的性能消耗。如果你有性能問題,請停用這些單位或減少這些單位啟用的功能。" +L["The override list \"%s\" already exists."] = "此覆蓋清單 \\\"%s\\\" 已經存在。" +L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."] = "無論此玩家框架是否會被隱藏,你將可以完全或每個地區輸入手動停用它。" +L["The tag \"%s\" already exists."] = "\"%s\"已存在於此標籤。" +L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."] = "你看到的頭像僅是範例,它們不是那麼完美並且不會顯示應該顯示的所有數據。|n|n您可以通過/ shadowuf指令鎖定它們或點擊下面的按鈕來隱藏它們。" +L["The whitelist \"%s\" already exists."] = "\"%s\"已經存在於白名單。" +L["Thick outline"] = "粗體" +L["Thin outline"] = "細體" +L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."] = "當你達到頂級或你沒有追蹤任何聲望時自動隱藏此計量條。" +L[ [=[This color will be used if the indicator shown is your own, only applies if icons are not used. +Handy 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.]=] ] = [=[這個顏色作用於顯示你自己的標記,僅用於未使用圖示的時候。 +有助於你了解如一個目標有回春術,但你也想知道這個回春術是不是你施放的。]=] +L["This filter has no aura types set to filter out."] = "在篩選中設定要篩選的光環類型。" +L["This filter has no auras in it, you will have to add some using the dialog above."] = "沒有光環在篩選中,你必須使用上面的對話框來新增。" +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."] = "這是一份如何開始 Lua 程式設計的很好的指南,只是你並不需要閱讀所有部分,它有助於理解 Lua 的語法和 API 的基礎知識。" +L["This unit depends on another to work, disabling %s will disable %s."] = "此單位必須依靠另一個才能顯示,停用%s也同時停用%s。" +L["This unit has child units that depend on it, you need to enable this unit before you can enable its children."] = "有子單位依靠在此單位,你需要在啟用子單位之前先啟用此單位。" +L[ [=[This will be set for your current class only. +If no custom spells are set, defaults appropriate for your class will be used.]=] ] = [=[這只會為當前職業設置。 +如果沒有設置自訂的法術,將會使用你職業預設適當的法術。]=] +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."] = "這將停用自動檢測什麼事件需要此標記功能,你應保持這個未勾選除非你知道你在做什麽。" +L["This will override all background colorings for bars including custom set ones."] = "這將覆蓋所有計量條的背景顏色,包括自訂設定的。" +L["Threat"] = "仇恨" +L["Threat situation"] = "仇恨情況" +L["Tile size"] = "標題大小" +L["Timer Text"] = "計時器文字" +L["Top"] = "頂部" +L["Top Center"] = "頂部居中" +L["Top Left"] = "頂部靠左" +L["Top Right"] = "頂部靠右" +L["Total number of active holy power."] = "作用的聖光能量總數" +L["Total number of active soul shards."] = "作用的靈魂碎片總數" +L["Total number of combo points you have on your target."] = "你在你的目標身上的總連擊點數。" +L["Totem bar"] = "圖騰條" +L["Totem Timer"] = "圖騰計時器" +L["Travel"] = "旅行" +L["Tree"] = "樹" +L["Turns this widget into a bar that can be resized and ordered just like health and power bars."] = "改變這個計量條組件的比重,可以調整排列就像生命條和能量值一樣。" +L["Unattackable hostile"] = "不可攻擊的敵對單位" +L["Unchecking this will completely disable aura indicators for %s."] = "不勾選的話,將會完全停用%s的光環標記。" +L["Unit color code on aggro"] = "獲得仇恨的單位顏色代碼" +L["Unit colored situation"] = "單位着色情況" +L["Unit Configuration"] = "單位設置" +L["Unit faction"] = "單位陣營" +L["Unit name"] = "單位名稱" +L["Unit name (Class colored)"] = "單位名稱(職業着色)" +L["Unit name colored by class."] = "依照職業着色單位名稱。" +L["Unit scaled threat"] = "單位仇恨比例" +L["Unit server"] = "單位伺服器" +L["Unit server, if they are from your server then nothing is shown."] = "單位伺服器,如果來自同伺服器則不顯示。" +L["Unit situation name"] = "單位情況名稱" +L["Units"] = "單位" +L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."] = "單位陣營,如薩爾顯示為部落,麥格尼·銅須顯示為聯盟。" +L["Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those."] = "怪物分類為:稀有、稀有精英、精英、Boss或爪牙,不包含在這些當中的什麼都不顯示。" +L["Units per column"] = "每行單位數" +L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."] = "單位種族,血精靈,牛頭人,食人妖 (被遺忘者)等等。" +L["Units that should have the aura groups settings changed below."] = "單位光環群組設置將有如下的變動。" +L["Units to change"] = "變動的單位" +L["Unknown"] = "未知" +L["Unlink frames"] = "脫離框架" +L["Up"] = "上" +L["Update interval"] = "刷新間隔" +L["Uses the icon of the totem being shown instead of a status bar."] = "使用圖騰圖標顯示代替狀態條。" +L["Using unit settings"] = "使用單位設定" +L["Various units can be enabled through this page, such as raid or party targets."] = "各種單位可透過此頁面啟用,如團隊或隊伍的目標。" +L["Vehicle"] = "載具" +L["Vehicles"] = "垂直" +L["Vertical growth"] = "垂直增長" +L["View"] = "查看" +L["Visibility"] = "可見性" +L["WARNING! ShadowedUF_Indicators has been deprecated as v4 and is now built in. Please delete ShadowedUF_Indicators, your configuration will be saved."] = "警告!ShadowedUF_Indicators在版本4之後被棄用並已內建,請刪除ShadowedUF_Indicators,您的設置將會繼續保留。" +L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] = "警告:這將解除所有框架之間的連結,所以你可以移動任何框架到任何地方。" +L["What group this aura belongs to, this is where you will find it when configuring."] = "這個光環屬於哪個群組,你在設置的時候會在哪裡找到它。" +L["What type of auras should be enlarged, use the scaled aura size option to change the size."] = "什麼類型的光環應該放大,使用光環大小縮放選項來改變大小。" +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."] = "當單位的生命損失時,將顯示[missinghp]標籤。當單位生命恢復時,將顯示[name]標籤。當生命損失1000時則顯示為-1000,當生命無損失時則顯示為名稱。" +L["When this filter is active, apply the filter to buffs."] = "當此篩選執行時,篩選增益。" +L["When this filter is active, apply the filter to debuffs."] = "當此篩選執行時,篩選減益。" +L["When to color the empty bar by reaction, overriding the default color by option."] = "當空的計量條顏色確認時,覆蓋選項的預設顏色。" +L["When to color the health bar by the units reaction, overriding the color health by option."] = "當單位的生命條顏色確認時,覆蓋選項的預設生命條顏色。" +L["When to show cooldown rings on auras"] = "何時在光環上顯示冷卻動態" +L["Where inside the frame the text should be anchored to."] = "框架內文字定位何處。" +L["Where to anchor the cast name text."] = "施法名稱文字定位何處。" +L["Where to anchor the cast time text."] = "施法時間文字定位何處。" +L["Whether auras you casted should be shown"] = "無論是否你施放的光環都會顯示" +L["Whether to show any auras casted by the boss"] = "是否顯示由首領施放的任何光環" +L["Whether to show any debuffs you can remove, cure or steal."] = "是否顯示你可以移除、治癒、偷取的任何減益。" +L["Whether to show auras that do not fall into the above categories."] = "是否顯示不屬於上述類別的光環。" +L["Whether to show buffs that you cannot cast."] = "是否顯示你無法施放的增益。" +L["Whitelist"] = "白名單" +L["Whitelist filters"] = "白名單篩選" +L["Whitelists"] = "白名單" +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."] = "白名單將會隱藏任何不在過濾群組的光環。/n黑名單將會隱藏在過濾群組的光環。|n覆蓋清單將會不顧任何過濾並總是顯示。" +L["Widget Size"] = "組件尺寸" +L["Width"] = "寬" +L["Width percent"] = "寬度百分比" +L["Width weight"] = "寬度比重" +L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."] = "將會填充由右→左當使用水平增長,或是上→下當使用垂直增長。" +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"] = "想了解所有單位配置標籤的作用?這裡有些提示:|n|n|cfffed000綜合:|r 頭像, 範圍檢查, 戰鬥文字, 邊框高亮|n|cfffed000框架:|r 單位定位和框架錨點|n|cfffed000Bars:|r 生命計量條,能量計量條,空計量條,施法條和連擊點的配置|n|cfffed000組建大小:|r 所有的狀態條和頭像大笑以及框架排序的選項|n|cfffed000光環:|r 啟用/關閉/放大自己等等的所有光環配置|n|cfffed000指示器:|r 所有的指示器配置包括PVP標記團隊角色就緒狀態和任務狀態等等|n|cfffed000文本/標籤:|r 標籤管理以及文本定位和寬度設置.|n|n|n*** 常用選項***|n|n|cfffed000按組排列團隊框架|r - 頭像配置-> 團隊-> 團隊->獨立團隊框架|n|cfffed000職業染色:|r 計量條​​-> 著色血量按|n|cfffed000光環計時:|r 你需要OmniCC|n|cfffed000顯示/隱藏默認的Buff框架:|r 隱藏暴雪默認框體-> 隱藏Buff框體|n|cfffed000Percentage HP/MP 文字:|r 文本/標籤選項, 使用[百分比生命值] 或者[百分比能量值] 標籤|n|cfffed000在團隊中隱藏小隊框架|r - 頭像配置-> 小隊-> 小隊-> 在>5人團隊中隱藏/任何團隊中隱藏" +L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."] = "運作如同[%s],但這只有顯示在單位為貓或熊型態。" +L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."] = "運作如同[%s],但這只有顯示在單位為貓或熊型態。" +L["WoW Programming"] = "WoW編譯" +L["WoW Programming is a good resource for finding out what difference API's do and how to call them."] = "WOW編譯是一個不同於API的執行能力並如何呼叫他們。" +L["X Offset"] = "X坐標" +L["XP/Rep bar"] = "經驗/聲望條" +L["Y Offset"] = "Y坐標" +L["Yellow (>30% HP)"] = "黃色(>30% HP)" +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."] = "你可以用已啟用的標籤使用設定來新增額外文字,注意任何額外文字的新增(或移除)對所有單位的影響,移除文字也會重置設定。|n|n記住,你無法刪除包含著單位的預設文字。" +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."] = "你可以在此頁面新增新的自訂標籤,為單位配置變更你想看到什麼標籤使用於文字標籤下的文字。" +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."] = "你可以在這裡取消單位的光環過濾與群組,例如,你可以設置一個光環群組用以顯示DPS的減益並只顯示在目標上。" +L["You can find more information on creating your own custom tags in the \"Help\" tab above."] = "在上面的 \"說明\" 標籤頁中可以找到更多關於建立自訂標籤的資訊。" +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."] = "在上面的 \"說明\" 標籤頁中可以找到更多關於建立你自己的自訂標籤的資訊。|nSUF 將會嘗試自動去偵測你的標籤會需要哪些事件,所以通常不用填寫事件欄位。" +L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] = "你可以在下面匯入其他玩家所匯出的Shadowed Unit Frame的代碼,這將備份你原本的版面編排到\"匯入備份\"中。|n|n這需要30-60秒來載入,請耐心等待。" +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."] = "你可以使用這個將光環連結在一起,舉例:你可以連結野性印記與野性賜福,所以如果玩家只有野性印記沒有野性賜福,它仍將顯示野性印記,就像擁有野性賜福一樣。" +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."] = "您可以覆蓋每個職業上已啟用的光環設置,注意!,如果光環是通過主列表選項禁用的,那麼在這裡你的職業設置亦不受影響。" +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."] = "你可以在什麼地區類型中設定什麼單位框架使用什麼篩選組,如果妳想要變更光環到哪個光環組可查看\"管理光環分組\"選項。" +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."] = "你不能編輯此標籤因為這是預設標籤中的一個。這有函數提供自訂標籤的範例給你。" +L["You cannot name a tag \"%s\", tag names should contain no brackets or parenthesis."] = "你不能命名\"%s\"的標籤,標籤名稱不能包含方括號或圓括號。" +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."] = "你還沒新增此類型的任何篩選,你必須先在管理頁面建立一個。" +L["You have entered combat, unit frames have been locked. Once you leave combat you will need to unlock them again through /shadowuf."] = "你已進入戰鬥,單位框架已被鎖定。當你離開戰鬥後你需要透過命令/shadowuf來解鎖。" +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."] = "妳只能輸入字母和下劃線, 如 \"FOO_BAR\" 為可用, 而\"APPLE_5_ORANGE\" 不可以因為包含了壹個數字." +L["You must enter a number that is 0 or higher, negative numbers are not allowed."] = "你必須輸入一個>=0的值,不可為負數。" +L["You must enter a tag name."] = "你必須輸入一個標籤名稱。" +L["You must restart Shadowed Unit Frames."] = "你必須重新啟動 Shadowed Unit Frames。" +L["You must wrap your code in a function."] = "你必須在函數中包裝你的代碼。" +L["You will need to create an aura filter before you can set which unit to enable aura filtering on."] = "在妳設置需要過濾光環的單位前妳必須創建壹個光環過濾器." +L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."] = "隱藏框架在刺變為可見時你必須先執行/console reloadui重載插件。|n玩家和其他單位框架是否自動隱藏將取決於你在Shadowed Unit Frames中有無啟用該單位。" +L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] = "妳的已激活布局已被用作導入備份的配置文件, 這個不能被導入所覆蓋. 修改妳的配置文件並再次嘗試." +L["Your aura color"] = "你的光環顏色" +L["Your Auras"] = "你的光環" +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"] = "你的代碼必須包含在函數中,例如,你要在單位名稱中顯示標記你必須這樣寫::|n|nfunction(unit, unitOwner)|nreturn UnitName(unitOwner)|nend" +L["Zone Configuration"] = "區域設置" +L["Zone configuration units"] = "單位地區設定" + +local ShadowUF = select(2, ...) +ShadowUF.L = setmetatable(L, {__index = ShadowUF.L}) diff --git a/modules/altpower.lua b/modules/altpower.lua index c79c608bd..6fa42ddf1 100755 --- a/modules/altpower.lua +++ b/modules/altpower.lua @@ -1,55 +1,55 @@ -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 barID = UnitPowerBarID(frame.unit) or 0 - local barInfo = GetUnitPowerBarInfoByID(barID) - local visible = false - if( barInfo and barInfo.barType ) then - if( ( frame.unitType == "player" or frame.unitType == "pet" ) or not barInfo.hideFromOthers ) then - visible = true - elseif( barInfo.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 - local barID = UnitPowerBarID(frame.unit) or 0 - local barInfo = GetUnitPowerBarInfoByID(barID) - local minPower = barInfo and barInfo.minPower or 0 - - frame.altPowerBar:SetMinMaxValues(minPower, UnitPowerMax(frame.unit, ALTERNATE_POWER_INDEX) or 0) - frame.altPowerBar:SetValue(UnitPower(frame.unit, ALTERNATE_POWER_INDEX) or 0) -end +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 barID = UnitPowerBarID(frame.unit) or 0 + local barInfo = GetUnitPowerBarInfoByID(barID) + local visible = false + if( barInfo and barInfo.barType ) then + if( ( frame.unitType == "player" or frame.unitType == "pet" ) or not barInfo.hideFromOthers ) then + visible = true + elseif( barInfo.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 + local barID = UnitPowerBarID(frame.unit) or 0 + local barInfo = GetUnitPowerBarInfoByID(barID) + local minPower = barInfo and barInfo.minPower or 0 + + frame.altPowerBar:SetMinMaxValues(minPower, 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 index 8ff32cdc9..c67195069 100644 --- a/modules/arcanecharges.lua +++ b/modules/arcanecharges.lua @@ -1,31 +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 +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 diff --git a/modules/auraindicators.lua b/modules/auraindicators.lua index 251523eff..85018358e 100755 --- a/modules/auraindicators.lua +++ b/modules/auraindicators.lua @@ -1,289 +1,289 @@ -local Indicators = {} -ShadowUF:RegisterModule(Indicators, "auraIndicators", ShadowUF.L["Aura indicators"]) - -Indicators.auraFilters = {"boss", "curable"} - -local GetSpellTexture = C_Spell.GetSpellTexture - -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, BackdropTemplateMixin and "BackdropTemplate" or nil) - 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 = AuraUtil.UnpackAuraData(C_UnitAuras.GetAuraDataByIndex(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 GetSpellTexture(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 +local Indicators = {} +ShadowUF:RegisterModule(Indicators, "auraIndicators", ShadowUF.L["Aura indicators"]) + +Indicators.auraFilters = {"boss", "curable"} + +local GetSpellTexture = C_Spell.GetSpellTexture + +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, BackdropTemplateMixin and "BackdropTemplate" or nil) + 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 = AuraUtil.UnpackAuraData(C_UnitAuras.GetAuraDataByIndex(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 GetSpellTexture(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 diff --git a/modules/aurapoints.lua b/modules/aurapoints.lua index fbda1df3e..f036645fc 100755 --- a/modules/aurapoints.lua +++ b/modules/aurapoints.lua @@ -1,29 +1,29 @@ -local AuraPoints = setmetatable({ - isComboPoints = true, - spells = { - --["MAGE"] = {max = 4, name = C_Spell.GetSpellName(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 +local AuraPoints = setmetatable({ + isComboPoints = true, + spells = { + --["MAGE"] = {max = 4, name = C_Spell.GetSpellName(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 diff --git a/modules/auras.lua b/modules/auras.lua index 89476411e..5f2635349 100755 --- a/modules/auras.lua +++ b/modules/auras.lua @@ -1,671 +1,671 @@ -local Auras = {} -local playerUnits = {player = true, vehicle = true, pet = true} -local mainHand, offHand, tempEnchantScan = {time = 0}, {time = 0} -local canCure = ShadowUF.Units.canCure -ShadowUF:RegisterModule(Auras, "auras", ShadowUF.L["Auras"]) - -function Auras:OnEnable(frame) - frame.auras = frame.auras or {} - - frame:RegisterNormalEvent("PLAYER_ENTERING_WORLD", self, "Update") - frame:RegisterUnitEvent("UNIT_AURA", self, "Update") - frame:RegisterUpdateFunc(self, "Update") - - self:UpdateFilter(frame) -end - -function Auras:OnDisable(frame) - frame:UnregisterAll(self) -end - --- Aura positioning code --- Definitely some of the more unusual code I've done, not sure I really like this method --- but it does allow more flexibility with how things are anchored without me having to hardcode the 10 different growth methods -local function load(text) - local result, err = loadstring(text) - if( err ) then - error(err, 3) - return nil - end - - return result() -end - -local positionData = setmetatable({}, { - __index = function(tbl, index) - local data = {} - local columnGrowth = ShadowUF.Layout:GetColumnGrowth(index) - local auraGrowth = ShadowUF.Layout:GetAuraGrowth(index) - data.xMod = (columnGrowth == "RIGHT" or auraGrowth == "RIGHT") and 1 or -1 - data.yMod = (columnGrowth ~= "TOP" and auraGrowth ~= "TOP") and -1 or 1 - - local auraX, colX, auraY, colY, xOffset, yOffset, initialXOffset, initialYOffset = 0, 0, 0, 0, "", "", "", "" - if( columnGrowth == "LEFT" or columnGrowth == "RIGHT" ) then - colX = 1 - xOffset = " + offset" - initialXOffset = string.format(" + (%d * offset)", data.xMod) - auraY = 3 - data.isSideGrowth = true - elseif( columnGrowth == "TOP" or columnGrowth == "BOTTOM" ) then - colY = 2 - yOffset = " + offset" - initialYOffset = string.format(" + (%d * offset)", data.yMod) - auraX = 2 - end - - 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() - button:SetPoint("%s", positionTo, "%s", %d * (%d%s), %d * (%d%s)) end - ]], ShadowUF.Layout:ReverseDirection(columnGrowth), columnGrowth, data.xMod, colX, xOffset, data.yMod, colY, yOffset)) - data.aura = load(string.format([[return function(button, positionTo) - button:ClearAllPoints() - button:SetPoint("%s", positionTo, "%s", %d, %d) end - ]], ShadowUF.Layout:ReverseDirection(auraGrowth), auraGrowth, data.xMod * auraX, data.yMod * auraY)) - - tbl[index] = data - return tbl[index] - end, -}) - -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 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 - button.isAuraAnchor = true - end - - if( id % config.perRow == 1 or config.perRow == 1 ) then - position.column(button, group.buttons[id - config.perRow], 0) - - if( not position.isSideGrowth ) then - button.isAuraAnchor = true - end - else - position.aura(button, group.buttons[id - 1]) - end - else - button.isAuraAnchor = true - button.point = ShadowUF.Layout:GetPoint(config.anchorPoint) - button.relativePoint = ShadowUF.Layout:GetRelative(config.anchorPoint) - 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 - - -local columnsHaveScale = {} -local function positionAllButtons(group, config) - local position = positionData[group.forcedAnchorPoint or config.anchorPoint] - - -- Figure out which columns have scaling so we can work out positioning - local columnID = 0 - for id, button in pairs(group.buttons) do - if( id % config.perRow == 1 or config.perRow == 1 ) then - columnID = columnID + 1 - columnsHaveScale[columnID] = nil - end - - if( not columnsHaveScale[columnID] and button.isSelfScaled ) then - local size = math.ceil(button:GetSize() * button:GetScale()) - columnsHaveScale[columnID] = columnsHaveScale[columnID] and math.max(size, columnsHaveScale[columnID]) or size - end - end - - columnID = 1 - for id, button in pairs(group.buttons) do - if( id > 1 ) then - if( id % config.perRow == 1 or config.perRow == 1 ) then - columnID = columnID + 1 - - local anchorButton = group.buttons[id - config.perRow] - local previousScale, currentScale = columnsHaveScale[columnID - 1], columnsHaveScale[columnID] - local offset = 0 - -- Previous column has a scaled aura, and the button we are anchoring to is not scaled - if( previousScale and not anchorButton.isSelfScaled ) then - offset = (previousScale / 4) - end - - -- Current column has a scaled aura, and the button isn't scaled - if( currentScale and not button.isSelfScaled ) then - offset = offset + (currentScale / 4) - end - - -- Current anchor is scaled, previous is not - if( button.isSelfScaled and not anchorButton.isSelfScaled ) then - offset = offset - (currentScale / 6) - end - - -- At least one of them is scaled - if( ( not button.isSelfScaled or not anchorButton.isSelfScaled ) and offset > 0 ) then - offset = offset + 1 - end - - position.column(button, anchorButton, math.ceil(offset)) - else - position.aura(button, group.buttons[id - 1]) - end - 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 - end - end -end - --- Aura button functions --- Updates the X seconds left on aura tooltip while it's shown -local function updateTooltip(self) - 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 - GameTooltip:SetInventoryItem("player", self.auraID) - self:SetScript("OnUpdate", nil) - else - GameTooltip:SetUnitAura(self.unit, self.auraID, self.filter) - self:SetScript("OnUpdate", updateTooltip) - end -end - -local function hideTooltip(self) - self:SetScript("OnUpdate", nil) - if not GameTooltip:IsForbidden() then - GameTooltip:Hide() - end -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) - local button = group.buttons[id] - if( not button ) then - group.buttons[id] = CreateFrame("Button", nil, group) - - button = group.buttons[id] - button:SetScript("OnEnter", showTooltip) - button:SetScript("OnLeave", hideTooltip) - button:RegisterForClicks("RightButtonUp") - - button.cooldown = CreateFrame("Cooldown", group.parent:GetName() .. "Aura" .. group.type .. id .. "Cooldown", button, "CooldownFrameTemplate") - button.cooldown:SetAllPoints(button) - button.cooldown:SetReverse(true) - 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") - button.stack:SetShadowColor(0, 0, 0, 1.0) - button.stack:SetShadowOffset(0.50, -0.50) - button.stack:SetHeight(1) - button.stack:SetWidth(1) - button.stack:SetAllPoints(button) - button.stack:SetJustifyV("BOTTOM") - button.stack:SetJustifyH("RIGHT") - - button.border = button:CreateTexture(nil, "OVERLAY") - button.border:SetPoint("CENTER", button) - - button.icon = button:CreateTexture(nil, "BACKGROUND") - button.icon:SetAllPoints(button) - button.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93) - end - - if( ShadowUF.db.profile.auras.borderType == "" ) then - button.border:Hide() - elseif( ShadowUF.db.profile.auras.borderType == "blizzard" ) then - button.border:SetTexture("Interface\\Buttons\\UI-Debuff-Overlays") - button.border:SetTexCoord(0.296875, 0.5703125, 0, 0.515625) - button.border:Show() - else - button.border:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\border-" .. ShadowUF.db.profile.auras.borderType) - button.border:SetTexCoord(0, 1, 0, 1) - button.border:Show() - end - - -- 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() - - -- Position the button quickly - positionButton(id, group, config) -end - --- Let the mover access this for creating aura things -Auras.updateButton = updateButton - --- Create an aura anchor as well as the buttons to contain it -local function updateGroup(self, type, config, reverseConfig) - self.auras[type] = self.auras[type] or CreateFrame("Frame", nil, self.highFrame) - - local group = self.auras[type] - group.buttons = group.buttons or {} - - group.maxAuras = config.perRow * config.maxRows - group.totalAuras = 0 - group.temporaryEnchants = 0 - group.type = type - group.parent = self - group.anchorTo = self - group:SetFrameLevel(self.highFrame:GetFrameLevel() + 1) - group:Show() - - -- If debuffs are anchored to buffs, debuffs need to grow however buffs do - if( config.anchorOn and reverseConfig.enabled ) then - group.forcedAnchorPoint = reverseConfig.anchorPoint - end - - if( self.unit == "player" ) then - mainHand.time = 0 - offHand.time = 0 - - group:SetScript("OnUpdate", config.temporary and tempEnchantScan or nil) - else - group:SetScript("OnUpdate", nil) - end - - -- Update filters used for the anchor - group.filter = group.type == "buffs" and "HELPFUL" or group.type == "debuffs" and "HARMFUL" or "" - - for id, button in pairs(group.buttons) do - updateButton(id, group, config) - end -end - --- Update aura positions based off of configuration -function Auras:OnLayoutApplied(frame, config) - if( frame.auras ) then - if( frame.auras.buffs ) then - for _, button in pairs(frame.auras.buffs.buttons) do - button:Hide() - end - end - if( frame.auras.debuffs ) then - for _, button in pairs(frame.auras.debuffs.buttons) do - button:Hide() - end - end - end - - if( not frame.visibility.auras ) then return end - - if( config.auras.buffs.enabled ) then - updateGroup(frame, "buffs", config.auras.buffs, config.auras.debuffs) - end - - if( config.auras.debuffs.enabled ) then - updateGroup(frame, "debuffs", config.auras.debuffs, config.auras.buffs) - end - - -- Anchor an aura group to another aura group - frame.auras.anchorAurasOn = nil - if( config.auras.buffs.enabled and config.auras.debuffs.enabled ) then - if( config.auras.buffs.anchorOn ) then - frame.auras.anchorAurasOn = frame.auras.debuffs - frame.auras.anchorAurasChild = frame.auras.buffs - elseif( config.auras.debuffs.anchorOn ) then - frame.auras.anchorAurasOn = frame.auras.buffs - frame.auras.anchorAurasChild = frame.auras.debuffs - end - end - - -- Check if either auras are anchored to each other - if( config.auras.buffs.anchorPoint == config.auras.debuffs.anchorPoint and config.auras.buffs.enabled and config.auras.debuffs.enabled and not config.auras.buffs.anchorOn and not config.auras.debuffs.anchorOn ) then - frame.auras.anchor = frame.auras[config.auras.buffs.prioritize and "buffs" or "debuffs"] - frame.auras.primary = config.auras.buffs.prioritize and "buffs" or "debuffs" - frame.auras.secondary = frame.auras.primary == "buffs" and "debuffs" or "buffs" - else - frame.auras.anchor = nil - end - - self:UpdateFilter(frame) -end - --- Temporary enchant support -local timeElapsed = 0 -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. - 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 - tempData.startTime = GetTime() - end - - 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 - if( #(frame.buttons) < frame.temporaryEnchants ) then - updateButton(frame.temporaryEnchants, frame, config) - end - - local button = frame.buttons[frame.temporaryEnchants] - - -- Purple border - button.border:SetVertexColor(0.50, 0, 0.50) - - -- Show the cooldown ring - if( not ShadowUF.db.profile.auras.disableCooldown ) then - button.cooldown:SetCooldown(tempData.startTime, timeLeft / 1000) - button.cooldown:Show() - end - - -- Enlarge our own auras - if( config.enlarge.SELF ) 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 = slot - button.filter = "TEMP" - button.unit = nil - button.columnHasScaled = nil - button.previousHasScale = nil - button.icon:SetTexture(GetInventoryItemTexture("player", slot)) - button.stack:SetText(charges > 1 and charges or "") - button:Show() -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 - - 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, mainEnchantId, hasOff, offTimeLeft, offCharges, offEnchantId = GetWeaponEnchantInfo() - self.temporaryEnchants = 0 - - if( hasMain ) then - self.temporaryEnchants = self.temporaryEnchants + 1 - updateTemporaryEnchant(self, 16, mainHand, hasMain, mainEnchantId, mainTimeLeft or 0, mainCharges) - mainHand.time = mainTimeLeft or 0 - end - - mainHand.has = hasMain - - if( hasOff and self.temporaryEnchants < self.maxAuras ) then - self.temporaryEnchants = self.temporaryEnchants + 1 - updateTemporaryEnchant(self, 17, offHand, hasOff, offEnchantId, offTimeLeft or 0, offCharges) - offHand.time = offTimeLeft or 0 - end - - offHand.has = hasOff - - -- Update if totals changed - if( self.lastTemporary ~= self.temporaryEnchants ) then - self.lastTemporary = self.temporaryEnchants - Auras:Update(self.parent) - end -end - --- Nice and simple, don't need to do a full update because either this is called in an OnEnable or --- the zone monitor will handle it all cleanly. The fun part of this code is aura filtering itself takes 10 seconds --- but making the configuration clean takes two weeks and another 2-3 days of implementing --- 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()) 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 - -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 - - -- 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 - - -- 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") - local index = 0 - while( true ) do - index = index + 1 - local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = AuraUtil.UnpackAuraData(C_UnitAuras.GetAuraDataByIndex(frame.parent.unit, index, filter)) - if( not name ) then break end - - renderAura(parent, frame, type, config, displayConfig, index, filter, isFriendly, curable, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff) - - -- Too many auras shown, break out - -- Get down - if( frame.totalAuras >= frame.maxAuras ) then break end - end - - 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.selfScale > 1.30 ) then - positionAllButtons(frame, displayConfig) - end -end - -Auras.scan = scan - -local function anchorGroupToGroup(frame, config, group, childConfig, childGroup) - -- Child group has nothing in it yet, so don't care - if( not childGroup.buttons[1] ) then return end - - -- Group we want to anchor to has nothing in it, takeover the postion - 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)) - return - end - - local anchorTo - for i=#(group.buttons), 1, -1 do - local button = group.buttons[i] - if( button.isAuraAnchor and button:IsVisible() ) then - anchorTo = button - break - end - end - - local position = positionData[childGroup.forcedAnchorPoint or childConfig.anchorPoint] - if( position.isSideGrowth ) then - position.aura(childGroup.buttons[1], anchorTo) - else - position.column(childGroup.buttons[1], anchorTo, 2) - end -end - -Auras.anchorGroupToGroup = anchorGroupToGroup - --- Do an update and figure out what we need to scan -function Auras:Update(frame) - local config = ShadowUF.db.profile.units[frame.unitType].auras - 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], 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, 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, config.debuffs, frame.auras.debuffs.filter) - end - - if( frame.auras.anchorAurasOn ) then - anchorGroupToGroup(frame, config[frame.auras.anchorAurasOn.type], frame.auras.anchorAurasOn, config[frame.auras.anchorAurasChild.type], frame.auras.anchorAurasChild) - end - end -end +local Auras = {} +local playerUnits = {player = true, vehicle = true, pet = true} +local mainHand, offHand, tempEnchantScan = {time = 0}, {time = 0} +local canCure = ShadowUF.Units.canCure +ShadowUF:RegisterModule(Auras, "auras", ShadowUF.L["Auras"]) + +function Auras:OnEnable(frame) + frame.auras = frame.auras or {} + + frame:RegisterNormalEvent("PLAYER_ENTERING_WORLD", self, "Update") + frame:RegisterUnitEvent("UNIT_AURA", self, "Update") + frame:RegisterUpdateFunc(self, "Update") + + self:UpdateFilter(frame) +end + +function Auras:OnDisable(frame) + frame:UnregisterAll(self) +end + +-- Aura positioning code +-- Definitely some of the more unusual code I've done, not sure I really like this method +-- but it does allow more flexibility with how things are anchored without me having to hardcode the 10 different growth methods +local function load(text) + local result, err = loadstring(text) + if( err ) then + error(err, 3) + return nil + end + + return result() +end + +local positionData = setmetatable({}, { + __index = function(tbl, index) + local data = {} + local columnGrowth = ShadowUF.Layout:GetColumnGrowth(index) + local auraGrowth = ShadowUF.Layout:GetAuraGrowth(index) + data.xMod = (columnGrowth == "RIGHT" or auraGrowth == "RIGHT") and 1 or -1 + data.yMod = (columnGrowth ~= "TOP" and auraGrowth ~= "TOP") and -1 or 1 + + local auraX, colX, auraY, colY, xOffset, yOffset, initialXOffset, initialYOffset = 0, 0, 0, 0, "", "", "", "" + if( columnGrowth == "LEFT" or columnGrowth == "RIGHT" ) then + colX = 1 + xOffset = " + offset" + initialXOffset = string.format(" + (%d * offset)", data.xMod) + auraY = 3 + data.isSideGrowth = true + elseif( columnGrowth == "TOP" or columnGrowth == "BOTTOM" ) then + colY = 2 + yOffset = " + offset" + initialYOffset = string.format(" + (%d * offset)", data.yMod) + auraX = 2 + end + + 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() + button:SetPoint("%s", positionTo, "%s", %d * (%d%s), %d * (%d%s)) end + ]], ShadowUF.Layout:ReverseDirection(columnGrowth), columnGrowth, data.xMod, colX, xOffset, data.yMod, colY, yOffset)) + data.aura = load(string.format([[return function(button, positionTo) + button:ClearAllPoints() + button:SetPoint("%s", positionTo, "%s", %d, %d) end + ]], ShadowUF.Layout:ReverseDirection(auraGrowth), auraGrowth, data.xMod * auraX, data.yMod * auraY)) + + tbl[index] = data + return tbl[index] + end, +}) + +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 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 + button.isAuraAnchor = true + end + + if( id % config.perRow == 1 or config.perRow == 1 ) then + position.column(button, group.buttons[id - config.perRow], 0) + + if( not position.isSideGrowth ) then + button.isAuraAnchor = true + end + else + position.aura(button, group.buttons[id - 1]) + end + else + button.isAuraAnchor = true + button.point = ShadowUF.Layout:GetPoint(config.anchorPoint) + button.relativePoint = ShadowUF.Layout:GetRelative(config.anchorPoint) + 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 + + +local columnsHaveScale = {} +local function positionAllButtons(group, config) + local position = positionData[group.forcedAnchorPoint or config.anchorPoint] + + -- Figure out which columns have scaling so we can work out positioning + local columnID = 0 + for id, button in pairs(group.buttons) do + if( id % config.perRow == 1 or config.perRow == 1 ) then + columnID = columnID + 1 + columnsHaveScale[columnID] = nil + end + + if( not columnsHaveScale[columnID] and button.isSelfScaled ) then + local size = math.ceil(button:GetSize() * button:GetScale()) + columnsHaveScale[columnID] = columnsHaveScale[columnID] and math.max(size, columnsHaveScale[columnID]) or size + end + end + + columnID = 1 + for id, button in pairs(group.buttons) do + if( id > 1 ) then + if( id % config.perRow == 1 or config.perRow == 1 ) then + columnID = columnID + 1 + + local anchorButton = group.buttons[id - config.perRow] + local previousScale, currentScale = columnsHaveScale[columnID - 1], columnsHaveScale[columnID] + local offset = 0 + -- Previous column has a scaled aura, and the button we are anchoring to is not scaled + if( previousScale and not anchorButton.isSelfScaled ) then + offset = (previousScale / 4) + end + + -- Current column has a scaled aura, and the button isn't scaled + if( currentScale and not button.isSelfScaled ) then + offset = offset + (currentScale / 4) + end + + -- Current anchor is scaled, previous is not + if( button.isSelfScaled and not anchorButton.isSelfScaled ) then + offset = offset - (currentScale / 6) + end + + -- At least one of them is scaled + if( ( not button.isSelfScaled or not anchorButton.isSelfScaled ) and offset > 0 ) then + offset = offset + 1 + end + + position.column(button, anchorButton, math.ceil(offset)) + else + position.aura(button, group.buttons[id - 1]) + end + 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 + end + end +end + +-- Aura button functions +-- Updates the X seconds left on aura tooltip while it's shown +local function updateTooltip(self) + 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 + GameTooltip:SetInventoryItem("player", self.auraID) + self:SetScript("OnUpdate", nil) + else + GameTooltip:SetUnitAura(self.unit, self.auraID, self.filter) + self:SetScript("OnUpdate", updateTooltip) + end +end + +local function hideTooltip(self) + self:SetScript("OnUpdate", nil) + if not GameTooltip:IsForbidden() then + GameTooltip:Hide() + end +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) + local button = group.buttons[id] + if( not button ) then + group.buttons[id] = CreateFrame("Button", nil, group) + + button = group.buttons[id] + button:SetScript("OnEnter", showTooltip) + button:SetScript("OnLeave", hideTooltip) + button:RegisterForClicks("RightButtonUp") + + button.cooldown = CreateFrame("Cooldown", group.parent:GetName() .. "Aura" .. group.type .. id .. "Cooldown", button, "CooldownFrameTemplate") + button.cooldown:SetAllPoints(button) + button.cooldown:SetReverse(true) + 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") + button.stack:SetShadowColor(0, 0, 0, 1.0) + button.stack:SetShadowOffset(0.50, -0.50) + button.stack:SetHeight(1) + button.stack:SetWidth(1) + button.stack:SetAllPoints(button) + button.stack:SetJustifyV("BOTTOM") + button.stack:SetJustifyH("RIGHT") + + button.border = button:CreateTexture(nil, "OVERLAY") + button.border:SetPoint("CENTER", button) + + button.icon = button:CreateTexture(nil, "BACKGROUND") + button.icon:SetAllPoints(button) + button.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93) + end + + if( ShadowUF.db.profile.auras.borderType == "" ) then + button.border:Hide() + elseif( ShadowUF.db.profile.auras.borderType == "blizzard" ) then + button.border:SetTexture("Interface\\Buttons\\UI-Debuff-Overlays") + button.border:SetTexCoord(0.296875, 0.5703125, 0, 0.515625) + button.border:Show() + else + button.border:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\border-" .. ShadowUF.db.profile.auras.borderType) + button.border:SetTexCoord(0, 1, 0, 1) + button.border:Show() + end + + -- 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() + + -- Position the button quickly + positionButton(id, group, config) +end + +-- Let the mover access this for creating aura things +Auras.updateButton = updateButton + +-- Create an aura anchor as well as the buttons to contain it +local function updateGroup(self, type, config, reverseConfig) + self.auras[type] = self.auras[type] or CreateFrame("Frame", nil, self.highFrame) + + local group = self.auras[type] + group.buttons = group.buttons or {} + + group.maxAuras = config.perRow * config.maxRows + group.totalAuras = 0 + group.temporaryEnchants = 0 + group.type = type + group.parent = self + group.anchorTo = self + group:SetFrameLevel(self.highFrame:GetFrameLevel() + 1) + group:Show() + + -- If debuffs are anchored to buffs, debuffs need to grow however buffs do + if( config.anchorOn and reverseConfig.enabled ) then + group.forcedAnchorPoint = reverseConfig.anchorPoint + end + + if( self.unit == "player" ) then + mainHand.time = 0 + offHand.time = 0 + + group:SetScript("OnUpdate", config.temporary and tempEnchantScan or nil) + else + group:SetScript("OnUpdate", nil) + end + + -- Update filters used for the anchor + group.filter = group.type == "buffs" and "HELPFUL" or group.type == "debuffs" and "HARMFUL" or "" + + for id, button in pairs(group.buttons) do + updateButton(id, group, config) + end +end + +-- Update aura positions based off of configuration +function Auras:OnLayoutApplied(frame, config) + if( frame.auras ) then + if( frame.auras.buffs ) then + for _, button in pairs(frame.auras.buffs.buttons) do + button:Hide() + end + end + if( frame.auras.debuffs ) then + for _, button in pairs(frame.auras.debuffs.buttons) do + button:Hide() + end + end + end + + if( not frame.visibility.auras ) then return end + + if( config.auras.buffs.enabled ) then + updateGroup(frame, "buffs", config.auras.buffs, config.auras.debuffs) + end + + if( config.auras.debuffs.enabled ) then + updateGroup(frame, "debuffs", config.auras.debuffs, config.auras.buffs) + end + + -- Anchor an aura group to another aura group + frame.auras.anchorAurasOn = nil + if( config.auras.buffs.enabled and config.auras.debuffs.enabled ) then + if( config.auras.buffs.anchorOn ) then + frame.auras.anchorAurasOn = frame.auras.debuffs + frame.auras.anchorAurasChild = frame.auras.buffs + elseif( config.auras.debuffs.anchorOn ) then + frame.auras.anchorAurasOn = frame.auras.buffs + frame.auras.anchorAurasChild = frame.auras.debuffs + end + end + + -- Check if either auras are anchored to each other + if( config.auras.buffs.anchorPoint == config.auras.debuffs.anchorPoint and config.auras.buffs.enabled and config.auras.debuffs.enabled and not config.auras.buffs.anchorOn and not config.auras.debuffs.anchorOn ) then + frame.auras.anchor = frame.auras[config.auras.buffs.prioritize and "buffs" or "debuffs"] + frame.auras.primary = config.auras.buffs.prioritize and "buffs" or "debuffs" + frame.auras.secondary = frame.auras.primary == "buffs" and "debuffs" or "buffs" + else + frame.auras.anchor = nil + end + + self:UpdateFilter(frame) +end + +-- Temporary enchant support +local timeElapsed = 0 +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. + 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 + tempData.startTime = GetTime() + end + + 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 + if( #(frame.buttons) < frame.temporaryEnchants ) then + updateButton(frame.temporaryEnchants, frame, config) + end + + local button = frame.buttons[frame.temporaryEnchants] + + -- Purple border + button.border:SetVertexColor(0.50, 0, 0.50) + + -- Show the cooldown ring + if( not ShadowUF.db.profile.auras.disableCooldown ) then + button.cooldown:SetCooldown(tempData.startTime, timeLeft / 1000) + button.cooldown:Show() + end + + -- Enlarge our own auras + if( config.enlarge.SELF ) 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 = slot + button.filter = "TEMP" + button.unit = nil + button.columnHasScaled = nil + button.previousHasScale = nil + button.icon:SetTexture(GetInventoryItemTexture("player", slot)) + button.stack:SetText(charges > 1 and charges or "") + button:Show() +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 + + 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, mainEnchantId, hasOff, offTimeLeft, offCharges, offEnchantId = GetWeaponEnchantInfo() + self.temporaryEnchants = 0 + + if( hasMain ) then + self.temporaryEnchants = self.temporaryEnchants + 1 + updateTemporaryEnchant(self, 16, mainHand, hasMain, mainEnchantId, mainTimeLeft or 0, mainCharges) + mainHand.time = mainTimeLeft or 0 + end + + mainHand.has = hasMain + + if( hasOff and self.temporaryEnchants < self.maxAuras ) then + self.temporaryEnchants = self.temporaryEnchants + 1 + updateTemporaryEnchant(self, 17, offHand, hasOff, offEnchantId, offTimeLeft or 0, offCharges) + offHand.time = offTimeLeft or 0 + end + + offHand.has = hasOff + + -- Update if totals changed + if( self.lastTemporary ~= self.temporaryEnchants ) then + self.lastTemporary = self.temporaryEnchants + Auras:Update(self.parent) + end +end + +-- Nice and simple, don't need to do a full update because either this is called in an OnEnable or +-- the zone monitor will handle it all cleanly. The fun part of this code is aura filtering itself takes 10 seconds +-- but making the configuration clean takes two weeks and another 2-3 days of implementing +-- 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()) 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 + +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 + + -- 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 + + -- 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") + local index = 0 + while( true ) do + index = index + 1 + local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = AuraUtil.UnpackAuraData(C_UnitAuras.GetAuraDataByIndex(frame.parent.unit, index, filter)) + if( not name ) then break end + + renderAura(parent, frame, type, config, displayConfig, index, filter, isFriendly, curable, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff) + + -- Too many auras shown, break out + -- Get down + if( frame.totalAuras >= frame.maxAuras ) then break end + end + + 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.selfScale > 1.30 ) then + positionAllButtons(frame, displayConfig) + end +end + +Auras.scan = scan + +local function anchorGroupToGroup(frame, config, group, childConfig, childGroup) + -- Child group has nothing in it yet, so don't care + if( not childGroup.buttons[1] ) then return end + + -- Group we want to anchor to has nothing in it, takeover the postion + 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)) + return + end + + local anchorTo + for i=#(group.buttons), 1, -1 do + local button = group.buttons[i] + if( button.isAuraAnchor and button:IsVisible() ) then + anchorTo = button + break + end + end + + local position = positionData[childGroup.forcedAnchorPoint or childConfig.anchorPoint] + if( position.isSideGrowth ) then + position.aura(childGroup.buttons[1], anchorTo) + else + position.column(childGroup.buttons[1], anchorTo, 2) + end +end + +Auras.anchorGroupToGroup = anchorGroupToGroup + +-- Do an update and figure out what we need to scan +function Auras:Update(frame) + local config = ShadowUF.db.profile.units[frame.unitType].auras + 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], 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, 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, config.debuffs, frame.auras.debuffs.filter) + end + + if( frame.auras.anchorAurasOn ) then + anchorGroupToGroup(frame, config[frame.auras.anchorAurasOn.type], frame.auras.anchorAurasOn, config[frame.auras.anchorAurasChild.type], frame.auras.anchorAurasChild) + end + end +end diff --git a/modules/basecombopoints.lua b/modules/basecombopoints.lua index b612ee745..c08519da3 100644 --- a/modules/basecombopoints.lua +++ b/modules/basecombopoints.lua @@ -1,204 +1,204 @@ -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() - texture:ClearAllPoints() - 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 +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() + texture:ClearAllPoints() + 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/burningembers.lua b/modules/burningembers.lua new file mode 100644 index 000000000..9be8a899b --- /dev/null +++ b/modules/burningembers.lua @@ -0,0 +1,119 @@ +local Embers = {} +ShadowUF:RegisterModule(Embers, "burningEmbersBar", ShadowUF.L["Burning Embers bar"], true, "WARLOCK", SPEC_WARLOCK_DESTRUCTION) + +-- This is a local in ShardBar.lua so we can't access it right now +local MAX_POWER_PER_EMBER = MAX_POWER_PER_EMBER or 10 + +function Embers:OnEnable(frame) + if( not frame.burningEmbersBar ) then + frame.burningEmbersBar = CreateFrame("StatusBar", nil, frame) + frame.burningEmbersBar:SetMinMaxValues(0, 1) + frame.burningEmbersBar:SetValue(0) + frame.burningEmbersBar.embers = {} + + for id=1, 4 do + local ember = ShadowUF.Units:CreateBar(frame.burningEmbersBar) + + if( id > 1 ) then + ember:SetPoint("TOPLEFT", frame.burningEmbersBar.embers[id - 1], "TOPRIGHT", 1, 0) + else + ember:SetPoint("TOPLEFT", frame.burningEmbersBar, "TOPLEFT", 0, 0) + end + + frame.burningEmbersBar.embers[id] = ember + end + end + + frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update") + frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks") + frame:RegisterUpdateFunc(self, "Update") + frame:RegisterUpdateFunc(self, "UpdateBarBlocks") +end + +function Embers:OnDisable(frame) + frame:UnregisterAll(self) + + for id, ember in pairs(frame.burningEmbersBar.embers) do + ember.background:Hide() + end +end + +function Embers:OnLayoutApplied(frame) + if( not frame.visibility.burningEmbersBar ) then return end + + for id, ember in pairs(frame.burningEmbersBar.embers) do + if( ShadowUF.db.profile.units[frame.unitType].burningEmbersBar.background ) then + ember.background:Show() + else + ember.background:Hide() + end + + ember.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar) + ember.background:SetHorizTile(false) + ember:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) + ember:GetStatusBarTexture():SetHorizTile(false) + ember:SetHeight(frame.burningEmbersBar:GetHeight()) + ember:SetMinMaxValues(0, MAX_POWER_PER_EMBER) + ember:SetOrientation(ShadowUF.db.profile.units[frame.unitType].burningEmbersBar.vertical and "VERTICAL" or "HORIZONTAL") + ember:SetReverseFill(ShadowUF.db.profile.units[frame.unitType].burningEmbersBar.reverse and true or false) + ember.setColor = nil + end + + self:UpdateBarBlocks(frame) +end + +function Embers:UpdateBarBlocks(frame, event, unit, powerType) + if( not frame.visibility.burningEmbersBar ) then return end + if( event and powerType ~= "BURNING_EMBERS" ) then return end + + local max = UnitPowerMax("player", Enum.PowerType.BurningEmbers, true) + max = floor(max / MAX_POWER_PER_EMBER) + + if( max == 0 or frame.burningEmbersBar.visibleBlocks == max ) then return end + + local blockWidth = (frame.burningEmbersBar:GetWidth() - (max - 1)) / max + for id=1, max do + local ember = frame.burningEmbersBar.embers[id] + ember:SetWidth(blockWidth) + + if( ShadowUF.db.profile.units[frame.unitType].burningEmbersBar.background ) then + ember.background:Show() + end + + ember:Show() + end + + for id=max+1, #(frame.burningEmbersBar.embers) do + frame.burningEmbersBar.embers[id]:Hide() + end + + frame.burningEmbersBar.visibleBlocks = max +end + +function Embers:Update(frame, event, unit, powerType) + if( event and powerType ~= "BURNING_EMBERS" ) then return end + + local power = UnitPower("player", Enum.PowerType.BurningEmbers, true) + for id=1, frame.burningEmbersBar.visibleBlocks do + local ember = frame.burningEmbersBar.embers[id] + + local color + if( power >= MAX_POWER_PER_EMBER ) then + color = "FULLBURNINGEMBER" + ember:SetValue(MAX_POWER_PER_EMBER) + elseif( power > 0 ) then + color = "BURNINGEMBERS" + ember:SetValue(power) + else + color = "BURNINGEMBERS" + ember:SetValue(0) + end + + if( ember.setColor ~= color ) then + ember.setColor = color + frame:SetBlockColor(ember, "burningEmbersBar", ShadowUF.db.profile.powerColors[color].r, ShadowUF.db.profile.powerColors[color].g, ShadowUF.db.profile.powerColors[color].b) + end + + power = power - MAX_POWER_PER_EMBER + end +end diff --git a/modules/cast.lua b/modules/cast.lua index 56ee5c1fa..f1843560b 100755 --- a/modules/cast.lua +++ b/modules/cast.lua @@ -1,483 +1,483 @@ -local Cast = {} -local L = ShadowUF.L -local FADE_TIME = 0.30 - -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) - local spell, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(self.parent.unit) - local isChannelled - if( not spell ) then - spell, displayName, icon, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(self.parent.unit) - isChannelled = true - end - - -- Cast started - if( not self.endTime and endTime ) then - self.endTime = endTime - self.notInterruptible = notInterruptible - self.spellName = spell - 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, nil, self.spellID) - end - - self.notInterruptible = nil - self.spellName = nil - self.endTime = nil - return - end - - -- Cast delayed - if( self.endTime and endTime ~= self.endTime ) then - self.endTime = endTime - Cast:UpdateDelay(self.parent, spell, displayName, icon, startTime, endTime) - end - - -- Cast interruptible status changed - if( self.spellName and self.notInterruptible ~= notInterruptible ) then - self.notInterruptible = notInterruptible - if( notInterruptible ) then - Cast:EventUninterruptible(self.parent) - else - Cast:EventInterruptible(self.parent) - end - end -end - -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) - if( not frame.castBar ) then - frame.castBar = CreateFrame("Frame", nil, 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") - frame.castBar.bar.time = frame.castBar.bar:CreateFontString(nil, "ARTWORK") - end - - if( ShadowUF.fakeUnits[frame.unitType] ) then - createFakeCastMonitor(frame) - frame:RegisterUpdateFunc(self, "UpdateFakeCast") - return - end - - frame:RegisterUnitEvent("UNIT_SPELLCAST_START", self, "EventUpdateCast") - frame:RegisterUnitEvent("UNIT_SPELLCAST_STOP", self, "EventStopCast") - frame:RegisterUnitEvent("UNIT_SPELLCAST_FAILED", self, "EventStopCast") - frame:RegisterUnitEvent("UNIT_SPELLCAST_INTERRUPTED", self, "EventInterruptCast") - frame:RegisterUnitEvent("UNIT_SPELLCAST_DELAYED", self, "EventDelayCast") - frame:RegisterUnitEvent("UNIT_SPELLCAST_SUCCEEDED", self, "EventCastSucceeded") - - 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_UPDATE", self, "EventDelayChannel") - - frame:RegisterUnitEvent("UNIT_SPELLCAST_INTERRUPTIBLE", self, "EventInterruptible") - frame:RegisterUnitEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE", self, "EventUninterruptible") - - frame:RegisterUpdateFunc(self, "UpdateCurrentCast") -end - -function Cast:OnLayoutApplied(frame, config) - if( not frame.visibility.castBar ) then return end - - -- Set textures - frame.castBar.bar:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) - frame.castBar.bar:SetStatusBarColor(0, 0, 0, 0) - frame.castBar.bar:GetStatusBarTexture():SetHorizTile(false) - 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()) - frame.castBar.bar:SetValue(0) - frame.castBar.bar:SetMinMaxValues(0, 1) - - -- Use the entire bars width and show the icon - if( config.castBar.icon == "HIDE" ) then - frame.castBar.bar:SetWidth(frame.castBar:GetWidth()) - frame.castBar.bar:SetAllPoints(frame.castBar) - frame.castBar.icon:Hide() - -- Shift the bar to the side and show an icon - else - frame.castBar.bar:SetWidth(frame.castBar:GetWidth() - frame.castBar:GetHeight()) - frame.castBar.icon:ClearAllPoints() - frame.castBar.icon:SetWidth(frame.castBar:GetHeight()) - frame.castBar.icon:SetHeight(frame.castBar:GetHeight()) - frame.castBar.icon:Show() - - if( config.castBar.icon == "LEFT" ) then - frame.castBar.bar:SetPoint("TOPLEFT", frame.castBar, "TOPLEFT", frame.castBar:GetHeight() + 1, 0) - frame.castBar.icon:SetPoint("TOPRIGHT", frame.castBar.bar, "TOPLEFT", -1, 0) - else - frame.castBar.bar:SetPoint("TOPLEFT", frame.castBar, "TOPLEFT", 1, 0) - frame.castBar.icon:SetPoint("TOPLEFT", frame.castBar.bar, "TOPRIGHT", 0, 0) - end - end - - -- Set the font at the very least, so it doesn't error when we set text on it even if it isn't being shown - ShadowUF.Layout:ToggleVisibility(frame.castBar.bar.name, config.castBar.name.enabled) - if( config.castBar.name.enabled ) then - frame.castBar.bar.name:SetParent(frame.highFrame) - frame.castBar.bar.name:SetWidth(frame.castBar.bar:GetWidth() * 0.75) - frame.castBar.bar.name:SetHeight(ShadowUF.db.profile.font.size + 1) - frame.castBar.bar.name:SetJustifyH(ShadowUF.Layout:GetJustify(config.castBar.name)) - - ShadowUF.Layout:AnchorFrame(frame.castBar.bar, frame.castBar.bar.name, config.castBar.name) - ShadowUF.Layout:SetupFontString(frame.castBar.bar.name, config.castBar.name.size) - end - - ShadowUF.Layout:ToggleVisibility(frame.castBar.bar.time, config.castBar.time.enabled) - if( config.castBar.time.enabled ) then - frame.castBar.bar.time:SetParent(frame.highFrame) - frame.castBar.bar.time:SetWidth(frame.castBar.bar:GetWidth() * 0.25) - frame.castBar.bar.time:SetHeight(ShadowUF.db.profile.font.size + 1) - frame.castBar.bar.time:SetJustifyH(ShadowUF.Layout:GetJustify(config.castBar.time)) - - ShadowUF.Layout:AnchorFrame(frame.castBar.bar, frame.castBar.bar.time, config.castBar.time) - ShadowUF.Layout:SetupFontString(frame.castBar.bar.time, config.castBar.time.size) - end - - -- So we don't have to check the entire thing in an OnUpdate - frame.castBar.bar.time.enabled = config.castBar.time.enabled - - if( config.castBar.autoHide and not UnitCastingInfo(frame.unit) and not UnitChannelInfo(frame.unit) ) then - ShadowUF.Layout:SetBarVisibility(frame, "castBar", false) - end -end - -function Cast:OnDisable(frame, unit) - frame:UnregisterAll(self) - - if( frame.castBar ) then - cancelFakeCastMonitor(frame) - - frame.castBar.bar.name:Hide() - frame.castBar.bar.time:Hide() - frame.castBar.bar:Hide() - end -end - --- Easy coloring -local function setBarColor(self, r, g, b) - self.parent:SetBlockColor(self, "castBar", r, g, b) -end - --- Cast OnUpdates -local function fadeOnUpdate(self, elapsed) - self.fadeElapsed = self.fadeElapsed - elapsed - - if( self.fadeElapsed <= 0 ) then - self.fadeElapsed = nil - self.name:Hide() - self.time:Hide() - self:Hide() - - local frame = self:GetParent() - if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then - ShadowUF.Layout:SetBarVisibility(frame, "castBar", false) - end - else - local alpha = self.fadeElapsed / self.fadeStart - self:SetAlpha(alpha) - self.time:SetAlpha(alpha) - self.name:SetAlpha(alpha) - end -end - -local function castOnUpdate(self, elapsed) - local time = GetTime() - self.elapsed = self.elapsed + (time - self.lastUpdate) - self.lastUpdate = time - self:SetValue(self.elapsed) - - if( self.elapsed <= 0 ) then - self.elapsed = 0 - end - - if( self.time.enabled ) then - local timeLeft = self.endSeconds - self.elapsed - if( timeLeft <= 0 ) then - self.time:SetText("0.0") - elseif( self.pushback == 0 ) then - self.time:SetFormattedText("%.1f", timeLeft) - else - self.time:SetFormattedText("|cffff0000%.1f|r %.1f", self.pushback, timeLeft) - end - end - - -- Cast finished, do a quick fade - if( self.elapsed >= self.endSeconds ) then - setBarColor(self, ShadowUF.db.profile.castColors.finished.r, ShadowUF.db.profile.castColors.finished.g, ShadowUF.db.profile.castColors.finished.b) - - self.spellName = nil - self.fadeElapsed = FADE_TIME - self.fadeStart = FADE_TIME - self:SetScript("OnUpdate", fadeOnUpdate) - end -end - -local function channelOnUpdate(self, elapsed) - local time = GetTime() - self.elapsed = self.elapsed - (time - self.lastUpdate) - self.lastUpdate = time - self:SetValue(self.elapsed) - - if( self.elapsed <= 0 ) then - self.elapsed = 0 - end - - if( self.time.enabled ) then - if( self.elapsed <= 0 ) then - self.time:SetText("0.0") - elseif( self.pushback == 0 ) then - self.time:SetFormattedText("%.1f", self.elapsed) - else - self.time:SetFormattedText("|cffff0000%.1f|r %.1f", self.pushback, self.elapsed) - end - end - - -- Channel finished, do a quick fade - if( self.elapsed <= 0 ) then - setBarColor(self, ShadowUF.db.profile.castColors.finished.r, ShadowUF.db.profile.castColors.finished.g, ShadowUF.db.profile.castColors.finished.b) - - self.spellName = nil - self.fadeElapsed = FADE_TIME - self.fadeStart = FADE_TIME - self:SetScript("OnUpdate", fadeOnUpdate) - end -end - -function Cast:UpdateCurrentCast(frame) - if( UnitCastingInfo(frame.unit) ) then - 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 - 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) - end - - setBarColor(frame.castBar.bar, 0, 0, 0) - - frame.castBar.bar.spellName = nil - frame.castBar.bar.name:Hide() - frame.castBar.bar.time:Hide() - frame.castBar.bar:Hide() - end -end - --- Cast updated/changed -function Cast:EventUpdateCast(frame) - 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) - 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) - 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) - 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, castID, spellID) - local cast = frame.castBar.bar - 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) - 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) - cast:SetMinMaxValues(0, 1) - cast:SetValue(1) - cast:Show() -end - --- Cast interrupted -function Cast:EventInterruptCast(frame, event, unit, castID, spellID) - local cast = frame.castBar.bar - 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 - ShadowUF.Layout:SetBarVisibility(frame, "castBar", true) - end - - if( ShadowUF.db.profile.units[frame.unitType].castBar.name.enabled ) then - cast.name:SetText(L["Interrupted"]) - end - - cast.spellID = nil - cast.fadeElapsed = FADE_TIME + 0.20 - cast.fadeStart = cast.fadeElapsed - cast:SetScript("OnUpdate", fadeOnUpdate) - cast:SetMinMaxValues(0, 1) - cast:SetValue(1) - cast:Show() -end - --- Cast succeeded -function Cast:EventCastSucceeded(frame, event, unit, castID, spellID) - local cast = frame.castBar.bar - 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 - --- Interruptible status changed -function Cast:EventInterruptible(frame) - local cast = frame.castBar.bar - if( cast.isChannelled ) then - setBarColor(cast, ShadowUF.db.profile.castColors.channel.r, ShadowUF.db.profile.castColors.channel.g, ShadowUF.db.profile.castColors.channel.b) - else - setBarColor(cast, ShadowUF.db.profile.castColors.cast.r, ShadowUF.db.profile.castColors.cast.g, ShadowUF.db.profile.castColors.cast.b) - end -end - -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, displayName, icon, startTime, endTime) - if( not spell or not frame.castBar.bar.startTime ) then return end - local cast = frame.castBar.bar - startTime = startTime / 1000 - endTime = endTime / 1000 - - -- For a channel, delay is a negative value so using plus is fine here - local delay = startTime - cast.startTime - if( not cast.isChannelled ) then - cast.endSeconds = cast.endSeconds + delay - cast:SetMinMaxValues(0, cast.endSeconds) - else - cast.elapsed = cast.elapsed + delay - end - - cast.pushback = cast.pushback + delay - cast.lastUpdate = GetTime() - cast.startTime = startTime - cast.endTime = endTime -end - --- Update the actual bar -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 - ShadowUF.Layout:SetBarVisibility(frame, "castBar", true) - end - - -- Set casted spell - if( ShadowUF.db.profile.units[frame.unitType].castBar.name.enabled ) then - cast.name:SetText(spell) - cast.name:SetAlpha(ShadowUF.db.profile.bars.alpha) - cast.name:Show() - end - - -- Show cast time - if( cast.time.enabled ) then - cast.time:SetAlpha(1) - cast.time:Show() - end - - -- Set spell icon - if( ShadowUF.db.profile.units[frame.unitType].castBar.icon ~= "HIDE" ) then - frame.castBar.icon:SetTexture(icon) - frame.castBar.icon:Show() - end - - -- BigWigs Spell Name Override - if (BigWigsAPI and BigWigsAPI.GetSpellRename and ShadowUF.db.profile.bossmodSpellRename and spellID) then - spell = BigWigsAPI.GetSpellRename(spellID) or spell - end - - -- Setup cast info - cast.isChannelled = channelled - cast.startTime = startTime / 1000 - cast.endTime = endTime / 1000 - cast.endSeconds = cast.endTime - cast.startTime - cast.elapsed = cast.isChannelled and cast.endSeconds or 0 - cast.spellName = spell - cast.spellID = spellID - cast.castID = channelled and spellID or castID - cast.pushback = 0 - cast.lastUpdate = cast.startTime - cast:SetMinMaxValues(0, cast.endSeconds) - cast:SetValue(cast.elapsed) - cast:SetAlpha(ShadowUF.db.profile.bars.alpha) - cast:Show() - - if( cast.isChannelled ) then - cast:SetScript("OnUpdate", channelOnUpdate) - else - cast:SetScript("OnUpdate", castOnUpdate) - end - - if( notInterruptible ) then - setBarColor(cast, ShadowUF.db.profile.castColors.uninterruptible.r, ShadowUF.db.profile.castColors.uninterruptible.g, ShadowUF.db.profile.castColors.uninterruptible.b) - elseif( cast.isChannelled ) then - setBarColor(cast, ShadowUF.db.profile.castColors.channel.r, ShadowUF.db.profile.castColors.channel.g, ShadowUF.db.profile.castColors.channel.b) - else - 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(f) - local monitor = f.castBar.monitor - monitor.endTime = nil - monitor.notInterruptible = nil - monitor.spellName = nil - monitor.spellID = nil - monitorFakeCast(monitor) -end +local Cast = {} +local L = ShadowUF.L +local FADE_TIME = 0.30 + +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) + local spell, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(self.parent.unit) + local isChannelled + if( not spell ) then + spell, displayName, icon, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(self.parent.unit) + isChannelled = true + end + + -- Cast started + if( not self.endTime and endTime ) then + self.endTime = endTime + self.notInterruptible = notInterruptible + self.spellName = spell + 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, nil, self.spellID) + end + + self.notInterruptible = nil + self.spellName = nil + self.endTime = nil + return + end + + -- Cast delayed + if( self.endTime and endTime ~= self.endTime ) then + self.endTime = endTime + Cast:UpdateDelay(self.parent, spell, displayName, icon, startTime, endTime) + end + + -- Cast interruptible status changed + if( self.spellName and self.notInterruptible ~= notInterruptible ) then + self.notInterruptible = notInterruptible + if( notInterruptible ) then + Cast:EventUninterruptible(self.parent) + else + Cast:EventInterruptible(self.parent) + end + end +end + +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) + if( not frame.castBar ) then + frame.castBar = CreateFrame("Frame", nil, 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") + frame.castBar.bar.time = frame.castBar.bar:CreateFontString(nil, "ARTWORK") + end + + if( ShadowUF.fakeUnits[frame.unitType] ) then + createFakeCastMonitor(frame) + frame:RegisterUpdateFunc(self, "UpdateFakeCast") + return + end + + frame:RegisterUnitEvent("UNIT_SPELLCAST_START", self, "EventUpdateCast") + frame:RegisterUnitEvent("UNIT_SPELLCAST_STOP", self, "EventStopCast") + frame:RegisterUnitEvent("UNIT_SPELLCAST_FAILED", self, "EventStopCast") + frame:RegisterUnitEvent("UNIT_SPELLCAST_INTERRUPTED", self, "EventInterruptCast") + frame:RegisterUnitEvent("UNIT_SPELLCAST_DELAYED", self, "EventDelayCast") + frame:RegisterUnitEvent("UNIT_SPELLCAST_SUCCEEDED", self, "EventCastSucceeded") + + 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_UPDATE", self, "EventDelayChannel") + + frame:RegisterUnitEvent("UNIT_SPELLCAST_INTERRUPTIBLE", self, "EventInterruptible") + frame:RegisterUnitEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE", self, "EventUninterruptible") + + frame:RegisterUpdateFunc(self, "UpdateCurrentCast") +end + +function Cast:OnLayoutApplied(frame, config) + if( not frame.visibility.castBar ) then return end + + -- Set textures + frame.castBar.bar:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) + frame.castBar.bar:SetStatusBarColor(0, 0, 0, 0) + frame.castBar.bar:GetStatusBarTexture():SetHorizTile(false) + 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()) + frame.castBar.bar:SetValue(0) + frame.castBar.bar:SetMinMaxValues(0, 1) + + -- Use the entire bars width and show the icon + if( config.castBar.icon == "HIDE" ) then + frame.castBar.bar:SetWidth(frame.castBar:GetWidth()) + frame.castBar.bar:SetAllPoints(frame.castBar) + frame.castBar.icon:Hide() + -- Shift the bar to the side and show an icon + else + frame.castBar.bar:SetWidth(frame.castBar:GetWidth() - frame.castBar:GetHeight()) + frame.castBar.icon:ClearAllPoints() + frame.castBar.icon:SetWidth(frame.castBar:GetHeight()) + frame.castBar.icon:SetHeight(frame.castBar:GetHeight()) + frame.castBar.icon:Show() + + if( config.castBar.icon == "LEFT" ) then + frame.castBar.bar:SetPoint("TOPLEFT", frame.castBar, "TOPLEFT", frame.castBar:GetHeight() + 1, 0) + frame.castBar.icon:SetPoint("TOPRIGHT", frame.castBar.bar, "TOPLEFT", -1, 0) + else + frame.castBar.bar:SetPoint("TOPLEFT", frame.castBar, "TOPLEFT", 1, 0) + frame.castBar.icon:SetPoint("TOPLEFT", frame.castBar.bar, "TOPRIGHT", 0, 0) + end + end + + -- Set the font at the very least, so it doesn't error when we set text on it even if it isn't being shown + ShadowUF.Layout:ToggleVisibility(frame.castBar.bar.name, config.castBar.name.enabled) + if( config.castBar.name.enabled ) then + frame.castBar.bar.name:SetParent(frame.highFrame) + frame.castBar.bar.name:SetWidth(frame.castBar.bar:GetWidth() * 0.75) + frame.castBar.bar.name:SetHeight(ShadowUF.db.profile.font.size + 1) + frame.castBar.bar.name:SetJustifyH(ShadowUF.Layout:GetJustify(config.castBar.name)) + + ShadowUF.Layout:AnchorFrame(frame.castBar.bar, frame.castBar.bar.name, config.castBar.name) + ShadowUF.Layout:SetupFontString(frame.castBar.bar.name, config.castBar.name.size) + end + + ShadowUF.Layout:ToggleVisibility(frame.castBar.bar.time, config.castBar.time.enabled) + if( config.castBar.time.enabled ) then + frame.castBar.bar.time:SetParent(frame.highFrame) + frame.castBar.bar.time:SetWidth(frame.castBar.bar:GetWidth() * 0.25) + frame.castBar.bar.time:SetHeight(ShadowUF.db.profile.font.size + 1) + frame.castBar.bar.time:SetJustifyH(ShadowUF.Layout:GetJustify(config.castBar.time)) + + ShadowUF.Layout:AnchorFrame(frame.castBar.bar, frame.castBar.bar.time, config.castBar.time) + ShadowUF.Layout:SetupFontString(frame.castBar.bar.time, config.castBar.time.size) + end + + -- So we don't have to check the entire thing in an OnUpdate + frame.castBar.bar.time.enabled = config.castBar.time.enabled + + if( config.castBar.autoHide and not UnitCastingInfo(frame.unit) and not UnitChannelInfo(frame.unit) ) then + ShadowUF.Layout:SetBarVisibility(frame, "castBar", false) + end +end + +function Cast:OnDisable(frame, unit) + frame:UnregisterAll(self) + + if( frame.castBar ) then + cancelFakeCastMonitor(frame) + + frame.castBar.bar.name:Hide() + frame.castBar.bar.time:Hide() + frame.castBar.bar:Hide() + end +end + +-- Easy coloring +local function setBarColor(self, r, g, b) + self.parent:SetBlockColor(self, "castBar", r, g, b) +end + +-- Cast OnUpdates +local function fadeOnUpdate(self, elapsed) + self.fadeElapsed = self.fadeElapsed - elapsed + + if( self.fadeElapsed <= 0 ) then + self.fadeElapsed = nil + self.name:Hide() + self.time:Hide() + self:Hide() + + local frame = self:GetParent() + if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then + ShadowUF.Layout:SetBarVisibility(frame, "castBar", false) + end + else + local alpha = self.fadeElapsed / self.fadeStart + self:SetAlpha(alpha) + self.time:SetAlpha(alpha) + self.name:SetAlpha(alpha) + end +end + +local function castOnUpdate(self, elapsed) + local time = GetTime() + self.elapsed = self.elapsed + (time - self.lastUpdate) + self.lastUpdate = time + self:SetValue(self.elapsed) + + if( self.elapsed <= 0 ) then + self.elapsed = 0 + end + + if( self.time.enabled ) then + local timeLeft = self.endSeconds - self.elapsed + if( timeLeft <= 0 ) then + self.time:SetText("0.0") + elseif( self.pushback == 0 ) then + self.time:SetFormattedText("%.1f", timeLeft) + else + self.time:SetFormattedText("|cffff0000%.1f|r %.1f", self.pushback, timeLeft) + end + end + + -- Cast finished, do a quick fade + if( self.elapsed >= self.endSeconds ) then + setBarColor(self, ShadowUF.db.profile.castColors.finished.r, ShadowUF.db.profile.castColors.finished.g, ShadowUF.db.profile.castColors.finished.b) + + self.spellName = nil + self.fadeElapsed = FADE_TIME + self.fadeStart = FADE_TIME + self:SetScript("OnUpdate", fadeOnUpdate) + end +end + +local function channelOnUpdate(self, elapsed) + local time = GetTime() + self.elapsed = self.elapsed - (time - self.lastUpdate) + self.lastUpdate = time + self:SetValue(self.elapsed) + + if( self.elapsed <= 0 ) then + self.elapsed = 0 + end + + if( self.time.enabled ) then + if( self.elapsed <= 0 ) then + self.time:SetText("0.0") + elseif( self.pushback == 0 ) then + self.time:SetFormattedText("%.1f", self.elapsed) + else + self.time:SetFormattedText("|cffff0000%.1f|r %.1f", self.pushback, self.elapsed) + end + end + + -- Channel finished, do a quick fade + if( self.elapsed <= 0 ) then + setBarColor(self, ShadowUF.db.profile.castColors.finished.r, ShadowUF.db.profile.castColors.finished.g, ShadowUF.db.profile.castColors.finished.b) + + self.spellName = nil + self.fadeElapsed = FADE_TIME + self.fadeStart = FADE_TIME + self:SetScript("OnUpdate", fadeOnUpdate) + end +end + +function Cast:UpdateCurrentCast(frame) + if( UnitCastingInfo(frame.unit) ) then + 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 + 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) + end + + setBarColor(frame.castBar.bar, 0, 0, 0) + + frame.castBar.bar.spellName = nil + frame.castBar.bar.name:Hide() + frame.castBar.bar.time:Hide() + frame.castBar.bar:Hide() + end +end + +-- Cast updated/changed +function Cast:EventUpdateCast(frame) + 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) + 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) + 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) + 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, castID, spellID) + local cast = frame.castBar.bar + 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) + 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) + cast:SetMinMaxValues(0, 1) + cast:SetValue(1) + cast:Show() +end + +-- Cast interrupted +function Cast:EventInterruptCast(frame, event, unit, castID, spellID) + local cast = frame.castBar.bar + 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 + ShadowUF.Layout:SetBarVisibility(frame, "castBar", true) + end + + if( ShadowUF.db.profile.units[frame.unitType].castBar.name.enabled ) then + cast.name:SetText(L["Interrupted"]) + end + + cast.spellID = nil + cast.fadeElapsed = FADE_TIME + 0.20 + cast.fadeStart = cast.fadeElapsed + cast:SetScript("OnUpdate", fadeOnUpdate) + cast:SetMinMaxValues(0, 1) + cast:SetValue(1) + cast:Show() +end + +-- Cast succeeded +function Cast:EventCastSucceeded(frame, event, unit, castID, spellID) + local cast = frame.castBar.bar + 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 + +-- Interruptible status changed +function Cast:EventInterruptible(frame) + local cast = frame.castBar.bar + if( cast.isChannelled ) then + setBarColor(cast, ShadowUF.db.profile.castColors.channel.r, ShadowUF.db.profile.castColors.channel.g, ShadowUF.db.profile.castColors.channel.b) + else + setBarColor(cast, ShadowUF.db.profile.castColors.cast.r, ShadowUF.db.profile.castColors.cast.g, ShadowUF.db.profile.castColors.cast.b) + end +end + +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, displayName, icon, startTime, endTime) + if( not spell or not frame.castBar.bar.startTime ) then return end + local cast = frame.castBar.bar + startTime = startTime / 1000 + endTime = endTime / 1000 + + -- For a channel, delay is a negative value so using plus is fine here + local delay = startTime - cast.startTime + if( not cast.isChannelled ) then + cast.endSeconds = cast.endSeconds + delay + cast:SetMinMaxValues(0, cast.endSeconds) + else + cast.elapsed = cast.elapsed + delay + end + + cast.pushback = cast.pushback + delay + cast.lastUpdate = GetTime() + cast.startTime = startTime + cast.endTime = endTime +end + +-- Update the actual bar +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 + ShadowUF.Layout:SetBarVisibility(frame, "castBar", true) + end + + -- Set casted spell + if( ShadowUF.db.profile.units[frame.unitType].castBar.name.enabled ) then + cast.name:SetText(spell) + cast.name:SetAlpha(ShadowUF.db.profile.bars.alpha) + cast.name:Show() + end + + -- Show cast time + if( cast.time.enabled ) then + cast.time:SetAlpha(1) + cast.time:Show() + end + + -- Set spell icon + if( ShadowUF.db.profile.units[frame.unitType].castBar.icon ~= "HIDE" ) then + frame.castBar.icon:SetTexture(icon) + frame.castBar.icon:Show() + end + + -- BigWigs Spell Name Override + if (BigWigsAPI and BigWigsAPI.GetSpellRename and ShadowUF.db.profile.bossmodSpellRename and spellID) then + spell = BigWigsAPI.GetSpellRename(spellID) or spell + end + + -- Setup cast info + cast.isChannelled = channelled + cast.startTime = startTime / 1000 + cast.endTime = endTime / 1000 + cast.endSeconds = cast.endTime - cast.startTime + cast.elapsed = cast.isChannelled and cast.endSeconds or 0 + cast.spellName = spell + cast.spellID = spellID + cast.castID = channelled and spellID or castID + cast.pushback = 0 + cast.lastUpdate = cast.startTime + cast:SetMinMaxValues(0, cast.endSeconds) + cast:SetValue(cast.elapsed) + cast:SetAlpha(ShadowUF.db.profile.bars.alpha) + cast:Show() + + if( cast.isChannelled ) then + cast:SetScript("OnUpdate", channelOnUpdate) + else + cast:SetScript("OnUpdate", castOnUpdate) + end + + if( notInterruptible ) then + setBarColor(cast, ShadowUF.db.profile.castColors.uninterruptible.r, ShadowUF.db.profile.castColors.uninterruptible.g, ShadowUF.db.profile.castColors.uninterruptible.b) + elseif( cast.isChannelled ) then + setBarColor(cast, ShadowUF.db.profile.castColors.channel.r, ShadowUF.db.profile.castColors.channel.g, ShadowUF.db.profile.castColors.channel.b) + else + 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(f) + local monitor = f.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 index b32f0b948..f0092aefe 100755 --- a/modules/chi.lua +++ b/modules/chi.lua @@ -1,28 +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 +if( not ShadowUF.ComboPoints ) then return end + +local Chi = setmetatable({}, {__index = ShadowUF.ComboPoints}) +ShadowUF:RegisterModule(Chi, "chi", ShadowUF.L["Chi"], nil, "MONK") +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 diff --git a/modules/combattext.lua b/modules/combattext.lua index 2f8b89a26..687188b2c 100755 --- a/modules/combattext.lua +++ b/modules/combattext.lua @@ -1,49 +1,49 @@ -local Combat = {} -ShadowUF:RegisterModule(Combat, "combatText", ShadowUF.L["Combat text"]) - -function Combat:OnEnable(frame) - if( not frame.combatText ) then - frame.combatText = CreateFrame("Frame", nil, frame.highFrame) - frame.combatText:SetFrameStrata("HIGH") - frame.combatText.feedbackText = frame.combatText:CreateFontString(nil, "ARTWORK") - frame.combatText.feedbackText:SetPoint("CENTER", frame.combatText, "CENTER", 0, 0) - frame.combatText:SetFrameLevel(frame.topFrameLevel) - - frame.combatText.feedbackStartTime = 0 - frame.combatText:SetScript("OnUpdate", CombatFeedback_OnUpdate) - frame.combatText:SetHeight(1) - frame.combatText:SetWidth(1) - end - - frame:RegisterUnitEvent("UNIT_COMBAT", self, "Update") -end - -function Combat:OnLayoutApplied(frame, config) - -- Update feedback text - ShadowUF.Layout:ToggleVisibility(frame.combatText, frame.visibility.combatText) - if( frame.visibility.combatText ) then - frame.combatText.feedbackFontHeight = ShadowUF.db.profile.font.size + 1 - frame.combatText.fontPath = ShadowUF.Layout.mediaPath.font - - ShadowUF.Layout:SetupFontString(frame.combatText.feedbackText, 1) - ShadowUF.Layout:AnchorFrame(frame, frame.combatText, config.combatText) - end -end - -function Combat:OnDisable(frame) - frame:UnregisterAll(self) -end - -function Combat:Update(frame, event, unit, type, ...) - CombatFeedback_OnCombatEvent(frame.combatText, type, ...) - if( type == "IMMUNE" ) then - frame.combatText.feedbackText:SetTextHeight(frame.combatText.feedbackFontHeight * 0.75) - end - - -- Increasing the font size will make the text look pixelated, however scaling it up will make it look smooth and awesome - 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 +local Combat = {} +ShadowUF:RegisterModule(Combat, "combatText", ShadowUF.L["Combat text"]) + +function Combat:OnEnable(frame) + if( not frame.combatText ) then + frame.combatText = CreateFrame("Frame", nil, frame.highFrame) + frame.combatText:SetFrameStrata("HIGH") + frame.combatText.feedbackText = frame.combatText:CreateFontString(nil, "ARTWORK") + frame.combatText.feedbackText:SetPoint("CENTER", frame.combatText, "CENTER", 0, 0) + frame.combatText:SetFrameLevel(frame.topFrameLevel) + + frame.combatText.feedbackStartTime = 0 + frame.combatText:SetScript("OnUpdate", CombatFeedback_OnUpdate) + frame.combatText:SetHeight(1) + frame.combatText:SetWidth(1) + end + + frame:RegisterUnitEvent("UNIT_COMBAT", self, "Update") +end + +function Combat:OnLayoutApplied(frame, config) + -- Update feedback text + ShadowUF.Layout:ToggleVisibility(frame.combatText, frame.visibility.combatText) + if( frame.visibility.combatText ) then + frame.combatText.feedbackFontHeight = ShadowUF.db.profile.font.size + 1 + frame.combatText.fontPath = ShadowUF.Layout.mediaPath.font + + ShadowUF.Layout:SetupFontString(frame.combatText.feedbackText, 1) + ShadowUF.Layout:AnchorFrame(frame, frame.combatText, config.combatText) + end +end + +function Combat:OnDisable(frame) + frame:UnregisterAll(self) +end + +function Combat:Update(frame, event, unit, type, ...) + CombatFeedback_OnCombatEvent(frame.combatText, type, ...) + if( type == "IMMUNE" ) then + frame.combatText.feedbackText:SetTextHeight(frame.combatText.feedbackFontHeight * 0.75) + end + + -- Increasing the font size will make the text look pixelated, however scaling it up will make it look smooth and awesome + 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 a68a74153..d72b4f871 100755 --- a/modules/combopoints.lua +++ b/modules/combopoints.lua @@ -1,42 +1,42 @@ -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.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:GetComboPointType() - return "comboPoints" -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", "target") - if( points == 0 ) then - points = GetComboPoints("vehicle", "vehicle") - end - - return points - else - return UnitPower("player", cpConfig.powerType) - end -end - -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 -end +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.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:GetComboPointType() + return "comboPoints" +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", "target") + if( points == 0 ) then + points = GetComboPoints("vehicle", "vehicle") + end + + return points + else + return UnitPower("player", cpConfig.powerType) + end +end + +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 +end diff --git a/modules/defaultlayout.lua b/modules/defaultlayout.lua index 2ceb6fb5d..46cd5cc26 100755 --- a/modules/defaultlayout.lua +++ b/modules/defaultlayout.lua @@ -1,967 +1,979 @@ -local L = ShadowUF.L -local playerClass = select(2, UnitClass("player")) - -local function finalizeData(config, useMerge) - local self = ShadowUF - -- Merges all of the parentUnit options into the child if they weren't set. - -- if it's a table, it recurses inside the table and copies any nil values in too - local function mergeToChild(parent, child, forceMerge) - for key, value in pairs(parent) do - if( type(child[key]) == "table" ) then - mergeToChild(value, child[key], forceMerge) - elseif( type(value) == "table" ) then - child[key] = CopyTable(value) - elseif( forceMerge or ( value ~= nil and child[key] == nil ) ) then - child[key] = value - end - end - end - - -- This makes sure that the unit has no values it shouldn't, for example if the defaults do not set incHeal for targettarget - -- and I try to set incHeal table here, then it'll remove it since it can't do that. - local function verifyTable(tbl, checkTable) - for key, value in pairs(tbl) do - if( type(value) == "table" ) then - if( not checkTable[key] ) then - tbl[key] = nil - else - for subKey, subValue in pairs(value) do - if( type(subValue) == "table" ) then - verifyTable(value, checkTable[key]) - end - end - end - end - end - end - - -- Set everything - for unit, child in pairs(config.units) do - if( self.defaults.profile.units[unit] ) then - if( not useMerge or ( useMerge and self.db.profile.units[unit].height == 0 and self.db.profile.units[unit].width == 0 and self.db.profile.positions[unit].anchorPoint == "" and self.db.profile.positions[unit].point == "" ) ) then - -- Merge the primary parent table - mergeToChild(config.parentUnit, child) - -- Strip any invalid tables - verifyTable(child, self.defaults.profile.units[unit]) - -- Merge the new child table into the actual units - mergeToChild(child, self.db.profile.units[unit], true) - - -- Merge position in too - if( useMerge and self.db.profile.positions[unit].point == "" and self.db.profile.positions[unit].relativePoint == "" and self.db.profile.positions[unit].anchorPoint == "" and self.db.profile.positions[unit].x == 0 and self.db.profile.positions[unit].y == 0 ) then - self.db.profile.positions[unit] = config.positions[unit] - end - end - end - end - - self.db.profile.loadedLayout = true - - if( not useMerge ) then - config.parentUnit = nil - config.units = nil - - 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 - -function ShadowUF:LoadDefaultLayout(useMerge) - local config = {} - config.bars = { - texture = "Minimalist", - spacing = -1.25, - alpha = 1.0, - backgroundAlpha = 0.20, - } - config.auras = { - borderType = "light", - } - config.backdrop = { - tileSize = 1, - edgeSize = 5, - clip = 1, - inset = 3, - backgroundTexture = "Chat Frame", - backgroundColor = {r = 0, g = 0, b = 0, a = 0.80}, - borderTexture = "None", - borderColor = {r = 0.30, g = 0.30, b = 0.50, a = 1}, - } - config.hidden = { - 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", - size = 11, - extra = "", - shadowColor = {r = 0, g = 0, b = 0, a = 1}, - color = {r = 1, g = 1, b = 1, a = 1}, - shadowX = 1.00, - shadowY = -1.00, - } - - -- 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" ) 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}, - PRIEST = {r = 1.0, g = 1.0, b = 1.0}, - PALADIN = {r = 0.96, g = 0.55, b = 0.73}, - MAGE = {r = 0.41, g = 0.8, b = 0.94}, - ROGUE = {r = 1.0, g = 0.96, b = 0.41}, - DRUID = {r = 1.0, g = 0.49, b = 0.04}, - 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}, - EVOKER = {r = 0.20, g = 0.58, b = 0.50}, - 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.50, b = 0.25}, - ENERGY = {r = 1.0, g = 0.85, b = 0.10}, - 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}, - ESSENCE = {r = 0.40, g = 0.80, b = 1.00}, - } - config.healthColors = { - tapped = {r = 0.5, g = 0.5, b = 0.5}, - red = {r = 0.90, g = 0.0, b = 0.0}, - green = {r = 0.20, g = 0.90, b = 0.20}, - 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} - } - config.castColors = { - channel = {r = 0.25, g = 0.25, b = 1.0}, - cast = {r = 1.0, g = 0.70, b = 0.30}, - interrupted = {r = 1, g = 0, b = 0}, - uninterruptible = {r = 0.71, g = 0, b = 1}, - finished = {r = 0.10, g = 1.0, b = 0.10}, - } - config.xpColors = { - normal = {r = 0.58, g = 0.0, b = 0.55}, - rested = {r = 0.0, g = 0.39, b = 0.88}, - } - - config.positions = { - targettargettarget = {anchorPoint = "RC", anchorTo = "#SUFUnittargettarget", x = 0, y = 0}, - targettarget = {anchorPoint = "TL", anchorTo = "#SUFUnittarget", x = 0, y = 0}, - focustarget = {anchorPoint = "TL", anchorTo = "#SUFUnitfocus", x = 0, y = 0}, - party = {point = "TOPLEFT", anchorTo = "#SUFUnitplayer", relativePoint = "TOPLEFT", movedAnchor = "TL", x = 0, y = -60}, - focus = {anchorPoint = "RB", anchorTo = "#SUFUnittarget", x = 35, y = -4}, - target = {anchorPoint = "RC", anchorTo = "#SUFUnitplayer", x = 50, y = 0}, - player = {point = "TOPLEFT", anchorTo = "UIParent", relativePoint = "TOPLEFT", y = -25, x = 20}, - pet = {anchorPoint = "TL", anchorTo = "#SUFUnitplayer", x = 0, y = 0}, - 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, 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, 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, default = true}, - {width = 0.60, name = L["Right text"], anchorTo = "$powerBar", anchorPoint = "CRI", x = -3, y = 0, size = 0, default = true}, - - {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}, - class = {anchorTo = "$parent", anchorPoint = "BL", size = 16, x = 0, y = 0}, - masterLoot = {anchorTo = "$parent", anchorPoint = "TL", size = 12, x = 16, y = -10}, - leader = {anchorTo = "$parent", anchorPoint = "TL", size = 14, x = 2, y = -12}, - pvp = {anchorTo = "$parent", anchorPoint = "TR", size = 22, x = 11, y = -21}, - ready = {anchorTo = "$parent", anchorPoint = "LC", size = 24, x = 35, y = 0}, - role = {anchorTo = "$parent", anchorPoint = "TL", size = 14, x = 30, y = -11}, - status = {anchorTo = "$parent", anchorPoint = "LB", size = 16, x = 12, y = -2}, - lfdRole = {enabled = true, anchorPoint = "BR", size = 14, x = 3, y = 14, anchorTo = "$parent"} - }, - highlight = {size = 10}, - 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, 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}}, - altPowerBar = {background = true, height = 0.40, order = 100}, - } - - -- Units configuration - config.units = { - raid = { - width = 100, - height = 30, - scale = 0.85, - unitsPerColumn = 8, - maxColumns = 8, - columnSpacing = 5, - groupsPerRow = 8, - groupSpacing = 0, - attribPoint = "TOP", - attribAnchorPoint = "LEFT", - 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"}, - sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, - }, - text = { - {text = "[(()afk() )][name]"}, - {text = "[missinghp]"}, - {text = ""}, - {text = ""}, - {text = "[(()afk() )][name]"}, - {text = ""}, - }, - }, - raidpet = { - width = 90, - height = 30, - scale = 0.85, - unitsPerColumn = 8, - maxColumns = 8, - columnSpacing = 5, - groupsPerRow = 8, - groupSpacing = 0, - attribPoint = "TOP", - attribAnchorPoint = "LEFT", - 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}, - }, - text = { - {text = "[name]"}, - {text = "[missinghp]"}, - {text = ""}, - {text = ""}, - {text = "[name]"}, - {text = ""}, - }, - }, - player = { - width = 190, - height = 45, - scale = 1.0, - portrait = {enabled = true, fullAfter = 50}, - castBar = {order = 60}, - xpBar = {order = 55}, - 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}, - essence = {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"}, - sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, - }, - auras = { - buffs = {enabled = false, maxRows = 1}, - debuffs = {enabled = false, maxRows = 1}, - }, - text = { - {text = "[(()afk() )][name][( ()group())]"}, - {text = "[curmaxhp]"}, - {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 = { - width = 190, - height = 45, - scale = 1.0, - attribPoint = "TOP", - attribAnchorPoint = "LEFT", - unitsPerColumn = 5, - columnSpacing = 30, - 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"}, - sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, 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}, - }, - text = { - {text = "[(()afk() )][name]"}, - {text = "[curmaxhp]"}, - {text = "[level( )][perpp]"}, - {text = "[curmaxpp]"}, - {text = "[(()afk() )][name]"}, - {text = ""}, - }, - }, - boss = { - enabled = true, - width = 160, - height = 40, - scale = 1.0, - 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}, - }, - text = { - {text = "[name]"}, - {text = "[curmaxhp]"}, - {text = "[perpp]"}, - {text = "[curmaxpp]"}, - {text = "[name]"}, - {text = ""}, - }, - portrait = {enabled = false}, - }, - bosstarget = { - 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]"}, - {text = "[curhp]"}, - {text = ""}, - {text = ""}, - {text = "[name]"}, - {text = ""}, - }, - }, - arena = { - enabled = true, - width = 170, - height = 45, - scale = 1.0, - attribPoint = "TOP", - attribAnchorPoint = "LEFT", - 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 = { - 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]"}, - }, - }, - arenatarget = { - 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 = ""}, - }, - }, - 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 = { - width = 150, - height = 40, - scale = 1.0, - attribPoint = "TOP", - attribAnchorPoint = "LEFT", - offset = 5, - unitsPerColumn = 5, - 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"}, - sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, - }, - auras = { - buffs = {enabled = false}, - debuffs = {enabled = false}, - }, - text = { - {text = "[(()afk() )][name]"}, - {text = "[curmaxhp]"}, - {text = "[perpp]"}, - {text = "[curmaxpp]"}, - {text = "[(()afk() )][name]"}, - {text = ""}, - }, - }, - maintanktarget = { - 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 = ""}, - }, - }, - 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 = { - width = 150, - height = 40, - scale = 1.0, - attribPoint = "TOP", - attribAnchorPoint = "LEFT", - offset = 5, - unitsPerColumn = 5, - 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"}, - sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, - }, - auras = { - buffs = {enabled = false}, - debuffs = {enabled = false}, - }, - text = { - {text = "[(()afk() )][name]"}, - {text = "[curmaxhp]"}, - {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}, - }, - text = { - {text = "[(()afk() )][name]"}, - {text = "[curmaxhp]"}, - {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]"}, - {text = "[curhp]"}, - {text = ""}, - {text = ""}, - {text = "[name]"}, - }, - }, - partytarget = { - 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 = ""}, - }, - }, - 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 = {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}, - resurrect = {enabled = true, anchorPoint = "RC", size = 28, x = -39, y = -1, anchorTo = "$parent"}, - sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, 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}, - debuffs = {enabled = true}, - }, - text = { - {text = "[(()afk() )][name]"}, - {text = "[curmaxhp]"}, - {text = "[level( )][classification( )][perpp]", width = 0.50}, - {text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60}, - {text = "[(()afk() )][name]"}, - {text = ""}, - }, - }, - pet = { - width = 190, - height = 30, - scale = 1.0, - powerBar = {height = 0.70}, - healAbsorb = {cap = 1}, - healthBar = {reactionType = "none"}, - portrait = {enabled = false, fullAfter = 50}, - castBar = {order = 60}, - 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 = { - }, - text = { - {text = "[name]"}, - {text = "[curmaxhp]"}, - {text = "[perpp]"}, - {text = "[curmaxpp]"}, - {text = "[name]"}, - {text = ""}, - }, - }, - focus = { - width = 120, - 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"}, - sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, 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]"}, - {text = "[curhp]"}, - {text = "[perpp]"}, - {text = "[curpp]"}, - {text = "[(()afk() )][name]"}, - {text = ""}, - }, - }, - focustarget = { - width = 120, - 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}, - }, - text = { - {text = "[(()afk() )][name]"}, - {text = "[curhp]"}, - {text = ""}, - {text = ""}, - {text = "[(()afk() )][name]"}, - {text = ""}, - }, - }, - targettarget = { - width = 110, - 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}, - }, - text = { - {text = "[name]"}, - {text = "[curhp]"}, - {text = "[perpp]"}, - {text = "[curpp]"}, - {text = ""}, - {text = ""}, - }, - }, - targettargettarget = { - width = 80, - 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}, - }, - text = { - {text = "[name]", width = 1.0}, - {text = ""}, - {text = ""}, - {text = ""}, - {text = ""}, - {text = ""}, - }, - }, - } - - finalizeData(config, useMerge) -end - +local L = ShadowUF.L +local playerClass = select(2, UnitClass("player")) + +local function finalizeData(config, useMerge) + local self = ShadowUF + -- Merges all of the parentUnit options into the child if they weren't set. + -- if it's a table, it recurses inside the table and copies any nil values in too + local function mergeToChild(parent, child, forceMerge) + for key, value in pairs(parent) do + if( type(child[key]) == "table" ) then + mergeToChild(value, child[key], forceMerge) + elseif( type(value) == "table" ) then + child[key] = CopyTable(value) + elseif( forceMerge or ( value ~= nil and child[key] == nil ) ) then + child[key] = value + end + end + end + + -- This makes sure that the unit has no values it shouldn't, for example if the defaults do not set incHeal for targettarget + -- and I try to set incHeal table here, then it'll remove it since it can't do that. + local function verifyTable(tbl, checkTable) + for key, value in pairs(tbl) do + if( type(value) == "table" ) then + if( not checkTable[key] ) then + tbl[key] = nil + else + for subKey, subValue in pairs(value) do + if( type(subValue) == "table" ) then + verifyTable(value, checkTable[key]) + end + end + end + end + end + end + + -- Set everything + for unit, child in pairs(config.units) do + if( self.defaults.profile.units[unit] ) then + if( not useMerge or ( useMerge and self.db.profile.units[unit].height == 0 and self.db.profile.units[unit].width == 0 and self.db.profile.positions[unit].anchorPoint == "" and self.db.profile.positions[unit].point == "" ) ) then + -- Merge the primary parent table + mergeToChild(config.parentUnit, child) + -- Strip any invalid tables + verifyTable(child, self.defaults.profile.units[unit]) + -- Merge the new child table into the actual units + mergeToChild(child, self.db.profile.units[unit], true) + + -- Merge position in too + if( useMerge and self.db.profile.positions[unit].point == "" and self.db.profile.positions[unit].relativePoint == "" and self.db.profile.positions[unit].anchorPoint == "" and self.db.profile.positions[unit].x == 0 and self.db.profile.positions[unit].y == 0 ) then + self.db.profile.positions[unit] = config.positions[unit] + end + end + end + end + + self.db.profile.loadedLayout = true + + if( not useMerge ) then + config.parentUnit = nil + config.units = nil + + 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 + +function ShadowUF:LoadDefaultLayout(useMerge) + local config = {} + config.bars = { + texture = "Minimalist", + spacing = -1.25, + alpha = 1.0, + backgroundAlpha = 0.20, + } + config.auras = { + borderType = "light", + } + config.backdrop = { + tileSize = 1, + edgeSize = 5, + clip = 1, + inset = 3, + backgroundTexture = "Chat Frame", + backgroundColor = {r = 0, g = 0, b = 0, a = 0.80}, + borderTexture = "None", + borderColor = {r = 0.30, g = 0.30, b = 0.50, a = 1}, + } + config.hidden = { + 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", + size = 11, + extra = "", + shadowColor = {r = 0, g = 0, b = 0, a = 1}, + color = {r = 1, g = 1, b = 1, a = 1}, + shadowX = 1.00, + shadowY = -1.00, + } + + -- 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" ) 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}, + PRIEST = {r = 1.0, g = 1.0, b = 1.0}, + PALADIN = {r = 0.96, g = 0.55, b = 0.73}, + MAGE = {r = 0.41, g = 0.8, b = 0.94}, + ROGUE = {r = 1.0, g = 0.96, b = 0.41}, + DRUID = {r = 1.0, g = 0.49, b = 0.04}, + 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}, + EVOKER = {r = 0.20, g = 0.58, b = 0.50}, + 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.50, b = 0.25}, + ENERGY = {r = 1.0, g = 0.85, b = 0.10}, + RUNES = {r = 0.50, g = 0.50, b = 0.50}, + RUNIC_POWER = {b = 0.60, g = 0.45, r = 0.35}, + ECLIPSE_SUN = {r = 1.0, g = 1.0, b = 0.0}, + ECLIPSE_MOON = {r = 0.30, g = 0.52, b = 0.90}, + 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}, + BANKEDHOLYPOWER = {r = 0.96, g = 0.61, b = 0.84}, + SOULSHARDS = {r = 0.58, g = 0.51, b = 0.79}, + ARCANECHARGES = {r = 0.1, g = 0.1, b = 0.98}, + DEMONICFURY = {r = 0.58, g = 0.51, b = 0.79}, + BURNINGEMBERS = {r = 0.58, g = 0.51, b = 0.79}, + FULLBURNINGEMBER = {r = 0.88, g = 0.09, b = 0.062}, + SHADOWORBS = {r = 0.58, g = 0.51, b = 0.79}, + 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}, + ESSENCE = {r = 0.40, g = 0.80, b = 1.00}, + } + config.healthColors = { + tapped = {r = 0.5, g = 0.5, b = 0.5}, + red = {r = 0.90, g = 0.0, b = 0.0}, + green = {r = 0.20, g = 0.90, b = 0.20}, + 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} + } + config.castColors = { + channel = {r = 0.25, g = 0.25, b = 1.0}, + cast = {r = 1.0, g = 0.70, b = 0.30}, + interrupted = {r = 1, g = 0, b = 0}, + uninterruptible = {r = 0.71, g = 0, b = 1}, + finished = {r = 0.10, g = 1.0, b = 0.10}, + } + config.xpColors = { + normal = {r = 0.58, g = 0.0, b = 0.55}, + rested = {r = 0.0, g = 0.39, b = 0.88}, + } + + config.positions = { + targettargettarget = {anchorPoint = "RC", anchorTo = "#SUFUnittargettarget", x = 0, y = 0}, + targettarget = {anchorPoint = "TL", anchorTo = "#SUFUnittarget", x = 0, y = 0}, + focustarget = {anchorPoint = "TL", anchorTo = "#SUFUnitfocus", x = 0, y = 0}, + party = {point = "TOPLEFT", anchorTo = "#SUFUnitplayer", relativePoint = "TOPLEFT", movedAnchor = "TL", x = 0, y = -60}, + focus = {anchorPoint = "RB", anchorTo = "#SUFUnittarget", x = 35, y = -4}, + target = {anchorPoint = "RC", anchorTo = "#SUFUnitplayer", x = 50, y = 0}, + player = {point = "TOPLEFT", anchorTo = "UIParent", relativePoint = "TOPLEFT", y = -25, x = 20}, + pet = {anchorPoint = "TL", anchorTo = "#SUFUnitplayer", x = 0, y = 0}, + 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, 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, 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, default = true}, + {width = 0.60, name = L["Right text"], anchorTo = "$powerBar", anchorPoint = "CRI", x = -3, y = 0, size = 0, default = true}, + + {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}, + {width = 1, name = L["Demonic Power"], anchorTo = "$demonicFuryBar", anchorPoint = "C", x = 3, y = 0, size = -1, default = true}, + {width = 1, name = L["Eclipse Power"], anchorTo = "$eclipseBar", anchorPoint = "C", size = 0, x = 0, y = 0, default = true}, + {width = 1, name = L["Timer Text"], anchorTo = "$runeBar", anchorPoint = "C", size = 0, x = 0, y = 0, default = true}, + {width = 1, name = L["Timer Text"], anchorTo = "$totemBar", anchorPoint = "C", size = 0, x = 0, y = 0, default = true}, + {width = 1, name = L["Stagger Power"], anchorTo = "$staggerBar", anchorPoint = "C", size = 0, x = 0, y = 0, default = true}, + }, + indicators = { + raidTarget = {anchorTo = "$parent", anchorPoint = "C", size = 20, x = 0, y = 0}, + class = {anchorTo = "$parent", anchorPoint = "BL", size = 16, x = 0, y = 0}, + masterLoot = {anchorTo = "$parent", anchorPoint = "TL", size = 12, x = 16, y = -10}, + leader = {anchorTo = "$parent", anchorPoint = "TL", size = 14, x = 2, y = -12}, + pvp = {anchorTo = "$parent", anchorPoint = "TR", size = 22, x = 11, y = -21}, + ready = {anchorTo = "$parent", anchorPoint = "LC", size = 24, x = 35, y = 0}, + role = {anchorTo = "$parent", anchorPoint = "TL", size = 14, x = 30, y = -11}, + status = {anchorTo = "$parent", anchorPoint = "LB", size = 16, x = 12, y = -2}, + lfdRole = {enabled = true, anchorPoint = "BR", size = 14, x = 3, y = 14, anchorTo = "$parent"} + }, + highlight = {size = 10}, + 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, 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}}, + altPowerBar = {background = true, height = 0.40, order = 100}, + } + + -- Units configuration + config.units = { + raid = { + width = 100, + height = 30, + scale = 0.85, + unitsPerColumn = 8, + maxColumns = 8, + columnSpacing = 5, + groupsPerRow = 8, + groupSpacing = 0, + attribPoint = "TOP", + attribAnchorPoint = "LEFT", + 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"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, + }, + text = { + {text = "[(()afk() )][name]"}, + {text = "[missinghp]"}, + {text = ""}, + {text = ""}, + {text = "[(()afk() )][name]"}, + {text = ""}, + }, + }, + raidpet = { + width = 90, + height = 30, + scale = 0.85, + unitsPerColumn = 8, + maxColumns = 8, + columnSpacing = 5, + groupsPerRow = 8, + groupSpacing = 0, + attribPoint = "TOP", + attribAnchorPoint = "LEFT", + 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}, + }, + text = { + {text = "[name]"}, + {text = "[missinghp]"}, + {text = ""}, + {text = ""}, + {text = "[name]"}, + {text = ""}, + }, + }, + player = { + width = 190, + height = 45, + scale = 1.0, + portrait = {enabled = true, fullAfter = 50}, + castBar = {order = 60}, + xpBar = {order = 55}, + 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}, + eclipseBar = {enabled = true, background = true, order = 70, height = 0.75}, + 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}, + demonicFuryBar = {enabled = true, background = false, height = 0.50, order = 70}, + burningEmbersBar = {enabled = true, background = false, height = 0.40, 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}, + shadowOrbs = {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}, + essence = {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"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, + }, + auras = { + buffs = {enabled = false, maxRows = 1}, + debuffs = {enabled = false, maxRows = 1}, + }, + text = { + {text = "[(()afk() )][name][( ()group())]"}, + {text = "[curmaxhp]"}, + {text = "[perpp]"}, + {text = "[curmaxpp]"}, + {text = "[(()afk() )][name][( ()group())]"}, + }, + }, + party = { + width = 190, + height = 45, + scale = 1.0, + attribPoint = "TOP", + attribAnchorPoint = "LEFT", + unitsPerColumn = 5, + columnSpacing = 30, + 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"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, 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}, + }, + text = { + {text = "[(()afk() )][name]"}, + {text = "[curmaxhp]"}, + {text = "[level( )][perpp]"}, + {text = "[curmaxpp]"}, + {text = "[(()afk() )][name]"}, + {text = ""}, + }, + }, + boss = { + enabled = true, + width = 160, + height = 40, + scale = 1.0, + 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}, + }, + text = { + {text = "[name]"}, + {text = "[curmaxhp]"}, + {text = "[perpp]"}, + {text = "[curmaxpp]"}, + {text = "[name]"}, + {text = ""}, + }, + portrait = {enabled = false}, + }, + bosstarget = { + 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]"}, + {text = "[curhp]"}, + {text = ""}, + {text = ""}, + {text = "[name]"}, + {text = ""}, + }, + }, + arena = { + enabled = true, + width = 170, + height = 45, + scale = 1.0, + attribPoint = "TOP", + attribAnchorPoint = "LEFT", + 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 = { + 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]"}, + }, + }, + arenatarget = { + 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 = ""}, + }, + }, + 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 = { + width = 150, + height = 40, + scale = 1.0, + attribPoint = "TOP", + attribAnchorPoint = "LEFT", + offset = 5, + unitsPerColumn = 5, + 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"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, + }, + auras = { + buffs = {enabled = false}, + debuffs = {enabled = false}, + }, + text = { + {text = "[(()afk() )][name]"}, + {text = "[curmaxhp]"}, + {text = "[perpp]"}, + {text = "[curmaxpp]"}, + {text = "[(()afk() )][name]"}, + {text = ""}, + }, + }, + maintanktarget = { + 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 = ""}, + }, + }, + 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 = { + width = 150, + height = 40, + scale = 1.0, + attribPoint = "TOP", + attribAnchorPoint = "LEFT", + offset = 5, + unitsPerColumn = 5, + 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"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"}, + }, + auras = { + buffs = {enabled = false}, + debuffs = {enabled = false}, + }, + text = { + {text = "[(()afk() )][name]"}, + {text = "[curmaxhp]"}, + {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}, + }, + text = { + {text = "[(()afk() )][name]"}, + {text = "[curmaxhp]"}, + {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]"}, + {text = "[curhp]"}, + {text = ""}, + {text = ""}, + {text = "[name]"}, + }, + }, + partytarget = { + 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 = ""}, + }, + }, + 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 = {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}, + resurrect = {enabled = true, anchorPoint = "RC", size = 28, x = -39, y = -1, anchorTo = "$parent"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, 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}, + debuffs = {enabled = true}, + }, + text = { + {text = "[(()afk() )][name]"}, + {text = "[curmaxhp]"}, + {text = "[level( )][classification( )][perpp]", width = 0.50}, + {text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60}, + {text = "[(()afk() )][name]"}, + {text = ""}, + }, + }, + pet = { + width = 190, + height = 30, + scale = 1.0, + powerBar = {height = 0.70}, + healAbsorb = {cap = 1}, + healthBar = {reactionType = "none"}, + portrait = {enabled = false, fullAfter = 50}, + castBar = {order = 60}, + 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 = { + }, + text = { + {text = "[name]"}, + {text = "[curmaxhp]"}, + {text = "[perpp]"}, + {text = "[curmaxpp]"}, + {text = "[name]"}, + {text = ""}, + }, + }, + focus = { + width = 120, + 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"}, + sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, 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]"}, + {text = "[curhp]"}, + {text = "[perpp]"}, + {text = "[curpp]"}, + {text = "[(()afk() )][name]"}, + {text = ""}, + }, + }, + focustarget = { + width = 120, + 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}, + }, + text = { + {text = "[(()afk() )][name]"}, + {text = "[curhp]"}, + {text = ""}, + {text = ""}, + {text = "[(()afk() )][name]"}, + {text = ""}, + }, + }, + targettarget = { + width = 110, + 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}, + }, + text = { + {text = "[name]"}, + {text = "[curhp]"}, + {text = "[perpp]"}, + {text = "[curpp]"}, + {text = ""}, + {text = ""}, + }, + }, + targettargettarget = { + width = 80, + 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}, + }, + text = { + {text = "[name]", width = 1.0}, + {text = ""}, + {text = ""}, + {text = ""}, + {text = ""}, + {text = ""}, + }, + }, + } + + finalizeData(config, useMerge) +end + diff --git a/modules/demonicfury.lua b/modules/demonicfury.lua new file mode 100644 index 000000000..2051461d8 --- /dev/null +++ b/modules/demonicfury.lua @@ -0,0 +1,34 @@ +local DemonicFury = {} +ShadowUF:RegisterModule(DemonicFury, "demonicFuryBar", ShadowUF.L["Demonic Fury"], true, "WARLOCK", SPEC_WARLOCK_DEMONOLOGY) + +function DemonicFury:OnEnable(frame) + frame.demonicFuryBar = frame.demonicFuryBar or ShadowUF.Units:CreateBar(frame) + + frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update") + frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "UpdateMax") + + frame:RegisterUpdateFunc(self, "Update") + frame:RegisterUpdateFunc(self, "UpdateMax") +end + +function DemonicFury:OnLayoutApplied(frame) + if( frame.visibility.demonicFuryBar ) then + local color = ShadowUF.db.profile.powerColors.DEMONICFURY + frame:SetBarColor("demonicFuryBar", color.r, color.g, color.b) + end +end + +function DemonicFury:OnDisable(frame) + frame:UnregisterAll(self) +end + +function DemonicFury:UpdateMax(frame, event, unit, powerType) + if( event and powerType ~= "DEMONIC_FURY" ) then return end + frame.demonicFuryBar:SetMinMaxValues(0, UnitPowerMax("player", Enum.PowerType.DemonicFury) or 0) +end + +function DemonicFury:Update(frame, event, unit, powerType) + if( event and powerType ~= "DEMONIC_FURY" ) then return end + + frame.demonicFuryBar:SetValue(UnitPower("player", Enum.PowerType.DemonicFury) or 0) +end \ No newline at end of file diff --git a/modules/druid.lua b/modules/druid.lua index 51d0c1998..783521c2e 100755 --- a/modules/druid.lua +++ b/modules/druid.lua @@ -1,39 +1,39 @@ -local Druid = {} -ShadowUF:RegisterModule(Druid, "druidBar", ShadowUF.L["Druid mana bar"], true, "DRUID") - -function Druid:OnEnable(frame) - frame.druidBar = frame.druidBar or ShadowUF.Units:CreateBar(frame) - - frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "PowerChanged") - - frame:RegisterUpdateFunc(self, "PowerChanged") - frame:RegisterUpdateFunc(self, "Update") -end - -function Druid:OnDisable(frame) - frame:UnregisterAll(self) -end - -function Druid:OnLayoutApplied(frame) - 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 - -function Druid:PowerChanged(frame) - local visible = UnitPowerType(frame.unit) ~= Enum.PowerType.Mana 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, 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 +local Druid = {} +ShadowUF:RegisterModule(Druid, "druidBar", ShadowUF.L["Druid mana bar"], true, "DRUID") + +function Druid:OnEnable(frame) + frame.druidBar = frame.druidBar or ShadowUF.Units:CreateBar(frame) + + frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "PowerChanged") + + frame:RegisterUpdateFunc(self, "PowerChanged") + frame:RegisterUpdateFunc(self, "Update") +end + +function Druid:OnDisable(frame) + frame:UnregisterAll(self) +end + +function Druid:OnLayoutApplied(frame) + 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 + +function Druid:PowerChanged(frame) + local visible = UnitPowerType(frame.unit) ~= Enum.PowerType.Mana 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, 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/eclipse.lua b/modules/eclipse.lua new file mode 100644 index 000000000..bd46d886f --- /dev/null +++ b/modules/eclipse.lua @@ -0,0 +1,76 @@ +-- Moon on left, Sun on right +-- Cast Arcane -> Move to Sun (Buff Nature) +-- Cast Nature -> Move to Moon (Buff Arcane) +-- 1 = Balance spec +local Eclipse = {types = {"sun", "moon"}} +ShadowUF:RegisterModule(Eclipse, "eclipseBar", ShadowUF.L["Eclipse bar"], true, "DRUID", 1) + +function Eclipse:OnEnable(frame) + if( not frame.eclipseBar ) then + frame.eclipseBar = CreateFrame("Frame", nil, frame) + -- the arrow marker + frame.eclipseBar.marker = CreateFrame("Frame", nil, frame.eclipseBar) + frame.eclipseBar.marker:SetPoint("CENTER", frame.eclipseBar) + frame.eclipseBar.marker.texture = frame.eclipseBar.marker:CreateTexture(nil, "OVERLAY") + frame.eclipseBar.marker.texture:SetTexture([[Interface\PlayerFrame\UI-DruidEclipse]]) + frame.eclipseBar.marker.texture:SetTexCoord(1.0, 0.914, 0.82, 1.0) + frame.eclipseBar.marker.texture:SetBlendMode("ADD") + frame.eclipseBar.marker.texture:SetAllPoints(frame.eclipseBar.marker) + + -- the actual bar textures + frame.eclipseBar.moon = frame.eclipseBar:CreateTexture(nil, "ARTWORK") + frame.eclipseBar.moon:SetPoint("TOPLEFT", frame.eclipseBar, "TOPLEFT") + frame.eclipseBar.moon:SetPoint("BOTTOMRIGHT", frame.eclipseBar, "BOTTOM") + + frame.eclipseBar.sun = frame.eclipseBar:CreateTexture(nil, "ARTWORK") + frame.eclipseBar.sun:SetPoint("TOPRIGHT", frame.eclipseBar, "TOPRIGHT") + frame.eclipseBar.sun:SetPoint("BOTTOMLEFT", frame.eclipseBar, "BOTTOM") + end + + frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update") + frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "Update") + frame:RegisterNormalEvent("ECLIPSE_DIRECTION_CHANGE", self, "UpdateDirection") + frame:RegisterNormalEvent("UPDATE_SHAPESHIFT_FORM", self, "UpdateVisibility") + + frame:RegisterUpdateFunc(self, "UpdateVisibility") +end + +function Eclipse:OnDisable(frame) + frame:UnregisterAll(self) +end + +function Eclipse:OnLayoutApplied(frame) + if( not frame.visibility.eclipseBar ) then return end + + for _, type in pairs(self.types) do + local color = ShadowUF.db.profile.powerColors["ECLIPSE_" .. string.upper(type)] + frame.eclipseBar[type]:SetTexture(ShadowUF.Layout.mediaPath.statusbar) + frame.eclipseBar[type]:SetVertexColor(color.r, color.g, color.b) + frame.eclipseBar[type]:SetHorizTile(false) + end + frame.eclipseBar.marker:SetSize(frame.eclipseBar:GetHeight() * 2, frame.eclipseBar:GetHeight() * 2) + + self:UpdateVisibility(frame) +end + +function Eclipse:UpdateVisibility(frame) + local form = GetShapeshiftFormID() + ShadowUF.Layout:SetBarVisibility(frame, "eclipseBar", form == MOONKIN_FORM or not form and not frame.inVehicle) + self:UpdateDirection(frame) + self:Update(frame, nil, nil, "BALANCE") +end + +function Eclipse:UpdateDirection(frame) + local direction = GetEclipseDirection() + if( direction ) then + frame.eclipseBar.marker.texture:SetTexCoord(unpack(ECLIPSE_MARKER_COORDS[direction])) + end +end + +function Eclipse:Update(frame, event, unit, powerType) + if( event and powerType ~= "BALANCE" ) then return end + + local power = UnitPower("player", Enum.PowerType.Balance ) + local xpos = (frame.eclipseBar:GetWidth() / 2) * (power / 100) + frame.eclipseBar.marker:SetPoint("CENTER", frame.eclipseBar, "CENTER", xpos, 0) +end diff --git a/modules/empty.lua b/modules/empty.lua index fde045d18..516965c4a 100755 --- a/modules/empty.lua +++ b/modules/empty.lua @@ -1,62 +1,62 @@ -local Empty = {} -local fallbackColor -ShadowUF:RegisterModule(Empty, "emptyBar", ShadowUF.L["Empty bar"], true) - -function Empty:OnEnable(frame) - frame.emptyBar = frame.emptyBar or ShadowUF.Units:CreateBar(frame) - frame.emptyBar:SetMinMaxValues(0, 1) - frame.emptyBar:SetValue(0) - - fallbackColor = fallbackColor or {r = 0, g = 0, b = 0} -end - -function Empty:OnDisable(frame) - frame:UnregisterAll(self) -end - -function Empty:OnLayoutApplied(frame) - if( frame.visibility.emptyBar ) then - 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.reactionType or ShadowUF.db.profile.units[frame.unitType].emptyBar.class ) then - frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdateColor") - frame:RegisterUpdateFunc(self, "UpdateColor") - else - self:OnDisable(frame) - end - end -end - -function Empty:UpdateColor(frame) - local color - local reactionType = ShadowUF.db.profile.units[frame.unitType].emptyBar.reactionType - - 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 - else - color = ShadowUF.db.profile.healthColors.enemyUnattack - end - elseif( UnitReaction(frame.unit, "player") ) then - local reaction = UnitReaction(frame.unit, "player") - if( reaction > 4 ) then - color = ShadowUF.db.profile.healthColors.friendly - elseif( reaction == 4 ) then - color = ShadowUF.db.profile.healthColors.neutral - elseif( reaction < 4 ) then - color = ShadowUF.db.profile.healthColors.hostile - 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 frame:UnitClassToken() - color = class and ShadowUF.db.profile.classColors[class] - end - - color = color or frame.emptyBar.background.overrideColor or fallbackColor - frame.emptyBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha) -end - +local Empty = {} +local fallbackColor +ShadowUF:RegisterModule(Empty, "emptyBar", ShadowUF.L["Empty bar"], true) + +function Empty:OnEnable(frame) + frame.emptyBar = frame.emptyBar or ShadowUF.Units:CreateBar(frame) + frame.emptyBar:SetMinMaxValues(0, 1) + frame.emptyBar:SetValue(0) + + fallbackColor = fallbackColor or {r = 0, g = 0, b = 0} +end + +function Empty:OnDisable(frame) + frame:UnregisterAll(self) +end + +function Empty:OnLayoutApplied(frame) + if( frame.visibility.emptyBar ) then + 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.reactionType or ShadowUF.db.profile.units[frame.unitType].emptyBar.class ) then + frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdateColor") + frame:RegisterUpdateFunc(self, "UpdateColor") + else + self:OnDisable(frame) + end + end +end + +function Empty:UpdateColor(frame) + local color + local reactionType = ShadowUF.db.profile.units[frame.unitType].emptyBar.reactionType + + 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 + else + color = ShadowUF.db.profile.healthColors.enemyUnattack + end + elseif( UnitReaction(frame.unit, "player") ) then + local reaction = UnitReaction(frame.unit, "player") + if( reaction > 4 ) then + color = ShadowUF.db.profile.healthColors.friendly + elseif( reaction == 4 ) then + color = ShadowUF.db.profile.healthColors.neutral + elseif( reaction < 4 ) then + color = ShadowUF.db.profile.healthColors.hostile + 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 frame:UnitClassToken() + color = class and ShadowUF.db.profile.classColors[class] + end + + color = color or frame.emptyBar.background.overrideColor or fallbackColor + frame.emptyBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha) +end + diff --git a/modules/essence.lua b/modules/essence.lua index 6cd7442be..5789f6d00 100644 --- a/modules/essence.lua +++ b/modules/essence.lua @@ -1,31 +1,31 @@ -if( not ShadowUF.ComboPoints ) then return end - -local Essence = setmetatable({}, {__index = ShadowUF.ComboPoints}) -ShadowUF:RegisterModule(Essence, "essence", ShadowUF.L["Essence"], nil, "EVOKER") -local essenceConfig = {max = 5, key = "essence", colorKey = "ESSENCE", powerType = Enum.PowerType.Essence, eventType = "ESSENCE", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"} - -function Essence:OnEnable(frame) - frame.essence = frame.essence or CreateFrame("Frame", nil, frame) - frame.essence.cpConfig = essenceConfig - - 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") - - essenceConfig.max = UnitPowerMax("player", essenceConfig.powerType) -end - -function Essence:OnLayoutApplied(frame, config) - ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config) - self:UpdateBarBlocks(frame) -end - -function Essence:GetComboPointType() - return "essence" -end - -function Essence:GetPoints(unit) - return UnitPower("player", essenceConfig.powerType) -end +if( not ShadowUF.ComboPoints ) then return end + +local Essence = setmetatable({}, {__index = ShadowUF.ComboPoints}) +ShadowUF:RegisterModule(Essence, "essence", ShadowUF.L["Essence"], nil, "EVOKER") +local essenceConfig = {max = 5, key = "essence", colorKey = "ESSENCE", powerType = Enum.PowerType.Essence, eventType = "ESSENCE", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"} + +function Essence:OnEnable(frame) + frame.essence = frame.essence or CreateFrame("Frame", nil, frame) + frame.essence.cpConfig = essenceConfig + + 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") + + essenceConfig.max = UnitPowerMax("player", essenceConfig.powerType) +end + +function Essence:OnLayoutApplied(frame, config) + ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config) + self:UpdateBarBlocks(frame) +end + +function Essence:GetComboPointType() + return "essence" +end + +function Essence:GetPoints(unit) + return UnitPower("player", essenceConfig.powerType) +end diff --git a/modules/fader.lua b/modules/fader.lua index bf96ccaf5..2d48c42c4 100755 --- a/modules/fader.lua +++ b/modules/fader.lua @@ -1,162 +1,162 @@ -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() - - if( self.fadeType == "in" ) then - self.parent:DisableRangeAlpha(false) - end - return - end - - if( self.fadeType == "in" ) then - self.parent:SetAlpha((self.timeElapsed / self.fadeTime) * (self.alphaEnd - self.alphaStart) + self.alphaStart) - 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) - if( self.fader.fadeType == type ) then return end - if( type == "out" ) then - self:DisableRangeAlpha(true) - end - - self.fader.fadeTime = speedyFade and 0.15 or type == "in" and 0.25 or type == "out" and 0.75 - self.fader.fadeType = type - self.fader.timeElapsed = 0 - self.fader.alphaEnd = alpha - self.fader.alphaStart = self:GetAlpha() - self.fader:Show() -end - -function Fader:OnEnable(frame) - if( not frame.fader ) then - frame.fader = CreateFrame("Frame", nil, frame) - frame.fader.timeElapsed = 0 - frame.fader.parent = frame - frame.fader:SetScript("OnUpdate", faderUpdate) - frame.fader:Hide() - end - - frame:RegisterNormalEvent("PLAYER_REGEN_ENABLED", self, "Update") - frame:RegisterNormalEvent("PLAYER_REGEN_DISABLED", self, "Update") - frame:RegisterUpdateFunc(self, "Update") - - if( InCombatLockdown() ) then - Fader:PLAYER_REGEN_DISABLED(frame, "PLAYER_REGEN_DISABLED") - else - Fader:PLAYER_REGEN_ENABLED(frame, "PLAYER_REGEN_ENABLED") - end -end - -function Fader:OnLayoutApplied(frame) - if( frame.visibility.fader ) then - frame.fader.fadeType = nil - frame:DisableRangeAlpha(false) - end -end - -function Fader:OnDisable(frame) - frame:UnregisterAll(self) - frame:SetAlpha(1.0) - - if( frame.fader ) then - frame.fader.fadeType = nil - frame.fader:Hide() - end -end - --- While we're in combat, we don't care about the other events so we might as well unregister them -function Fader:PLAYER_REGEN_ENABLED(frame, event) - self:Update(frame, event) - frame:RegisterNormalEvent("PLAYER_TARGET_CHANGED", self, "Update") - frame:RegisterNormalEvent("UNIT_SPELLCAST_CHANNEL_START", self, "CastStart") - frame:RegisterNormalEvent("UNIT_SPELLCAST_CHANNEL_STOP", self, "CastStop") - frame:RegisterNormalEvent("UNIT_SPELLCAST_START", self, "CastStart") - frame:RegisterNormalEvent("UNIT_SPELLCAST_STOP", self, "CastStop") - frame:RegisterUnitEvent("UNIT_HEALTH", self, "Update") - frame:RegisterUnitEvent("UNIT_MAXHEALTH", 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: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, id) - if( unit ~= "player" or activeCastID == id ) then return end - activeCastID = id - - frame.fader.playerCasting = true - self:Update(frame) -end - -function Fader:CastStop(frame, event, unit, id) - if( unit ~= "player" or activeCastID ~= id ) then return end - activeCastID = nil - - frame.fader.playerCasting = nil - self:Update(frame) -end - - -function Fader:Update(frame, event) - -- In combat, fade back in - if( InCombatLockdown() or event == "PLAYER_REGEN_DISABLED" ) then - startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha) - -- Player is casting, fade in - 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( 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 - startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha) - -- Targetting somebody, fade in - elseif( frame.unitType == "player" and UnitExists("target") ) then - startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha) - -- Nothing else? Fade out! - else - startFading(frame, "out", ShadowUF.db.profile.units[frame.unitType].fader.inactiveAlpha) - end -end +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() + + if( self.fadeType == "in" ) then + self.parent:DisableRangeAlpha(false) + end + return + end + + if( self.fadeType == "in" ) then + self.parent:SetAlpha((self.timeElapsed / self.fadeTime) * (self.alphaEnd - self.alphaStart) + self.alphaStart) + 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) + if( self.fader.fadeType == type ) then return end + if( type == "out" ) then + self:DisableRangeAlpha(true) + end + + self.fader.fadeTime = speedyFade and 0.15 or type == "in" and 0.25 or type == "out" and 0.75 + self.fader.fadeType = type + self.fader.timeElapsed = 0 + self.fader.alphaEnd = alpha + self.fader.alphaStart = self:GetAlpha() + self.fader:Show() +end + +function Fader:OnEnable(frame) + if( not frame.fader ) then + frame.fader = CreateFrame("Frame", nil, frame) + frame.fader.timeElapsed = 0 + frame.fader.parent = frame + frame.fader:SetScript("OnUpdate", faderUpdate) + frame.fader:Hide() + end + + frame:RegisterNormalEvent("PLAYER_REGEN_ENABLED", self, "Update") + frame:RegisterNormalEvent("PLAYER_REGEN_DISABLED", self, "Update") + frame:RegisterUpdateFunc(self, "Update") + + if( InCombatLockdown() ) then + Fader:PLAYER_REGEN_DISABLED(frame, "PLAYER_REGEN_DISABLED") + else + Fader:PLAYER_REGEN_ENABLED(frame, "PLAYER_REGEN_ENABLED") + end +end + +function Fader:OnLayoutApplied(frame) + if( frame.visibility.fader ) then + frame.fader.fadeType = nil + frame:DisableRangeAlpha(false) + end +end + +function Fader:OnDisable(frame) + frame:UnregisterAll(self) + frame:SetAlpha(1.0) + + if( frame.fader ) then + frame.fader.fadeType = nil + frame.fader:Hide() + end +end + +-- While we're in combat, we don't care about the other events so we might as well unregister them +function Fader:PLAYER_REGEN_ENABLED(frame, event) + self:Update(frame, event) + frame:RegisterNormalEvent("PLAYER_TARGET_CHANGED", self, "Update") + frame:RegisterNormalEvent("UNIT_SPELLCAST_CHANNEL_START", self, "CastStart") + frame:RegisterNormalEvent("UNIT_SPELLCAST_CHANNEL_STOP", self, "CastStop") + frame:RegisterNormalEvent("UNIT_SPELLCAST_START", self, "CastStart") + frame:RegisterNormalEvent("UNIT_SPELLCAST_STOP", self, "CastStop") + frame:RegisterUnitEvent("UNIT_HEALTH", self, "Update") + frame:RegisterUnitEvent("UNIT_MAXHEALTH", 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: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, id) + if( unit ~= "player" or activeCastID == id ) then return end + activeCastID = id + + frame.fader.playerCasting = true + self:Update(frame) +end + +function Fader:CastStop(frame, event, unit, id) + if( unit ~= "player" or activeCastID ~= id ) then return end + activeCastID = nil + + frame.fader.playerCasting = nil + self:Update(frame) +end + + +function Fader:Update(frame, event) + -- In combat, fade back in + if( InCombatLockdown() or event == "PLAYER_REGEN_DISABLED" ) then + startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha) + -- Player is casting, fade in + 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( 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 + startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha) + -- Targetting somebody, fade in + elseif( frame.unitType == "player" and UnitExists("target") ) then + startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha) + -- Nothing else? Fade out! + else + startFading(frame, "out", ShadowUF.db.profile.units[frame.unitType].fader.inactiveAlpha) + end +end diff --git a/modules/healabsorb.lua b/modules/healabsorb.lua index 673646bf3..260037e55 100755 --- a/modules/healabsorb.lua +++ b/modules/healabsorb.lua @@ -1,18 +1,18 @@ -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_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 +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_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 diff --git a/modules/health.lua b/modules/health.lua index 48c7ceeba..6bb17e779 100755 --- a/modules/health.lua +++ b/modules/health.lua @@ -1,170 +1,170 @@ -local Health = {} -ShadowUF:RegisterModule(Health, "healthBar", ShadowUF.L["Health bar"], true) -local canCure = ShadowUF.Units.canCure - -local function getGradientColor(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 - - local sR, sG, sB, eR, eG, eB = 0, 0, 0, 0, 0, 0 - local modifier, inverseModifier = percent * 2, 0 - if( percent > 0.50 ) then - sR, sG, sB = ShadowUF.db.profile.healthColors.green.r, ShadowUF.db.profile.healthColors.green.g, ShadowUF.db.profile.healthColors.green.b - eR, eG, eB = ShadowUF.db.profile.healthColors.yellow.r, ShadowUF.db.profile.healthColors.yellow.g, ShadowUF.db.profile.healthColors.yellow.b - - modifier = modifier - 1 - else - sR, sG, sB = ShadowUF.db.profile.healthColors.yellow.r, ShadowUF.db.profile.healthColors.yellow.g, ShadowUF.db.profile.healthColors.yellow.b - eR, eG, eB = ShadowUF.db.profile.healthColors.red.r, ShadowUF.db.profile.healthColors.red.g, ShadowUF.db.profile.healthColors.red.b - end - - inverseModifier = 1 - modifier - return eR * inverseModifier + sR * modifier, eG * inverseModifier + sG * modifier, eB * inverseModifier + sB * modifier -end - -Health.getGradientColor = getGradientColor - -function Health:OnEnable(frame) - if( not frame.healthBar ) then - frame.healthBar = ShadowUF.Units:CreateBar(frame) - end - - 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_TARGETABLE_CHANGED", self, "UpdateColor") - - if( frame.unit == "pet" ) then - frame:RegisterUnitEvent("UNIT_POWER_UPDATE", self, "UpdateColor") - end - - 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: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 = AuraUtil.UnpackAuraData(C_UnitAuras.GetDebuffDataByIndex(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) - frame.healthBar.hasReaction = nil - frame.healthBar.hasPercent = nil - frame.healthBar.wasOffline = nil - - local color - local unit = frame.unit - local reactionType = ShadowUF.db.profile.units[frame.unitType].healthBar.reactionType - if( not UnitIsConnected(unit) ) then - frame.healthBar.wasOffline = true - 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 - 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 UnitPlayerControlled(unit) and UnitIsTapDenied(unit) and UnitCanAttack("player", unit) ) then - color = ShadowUF.db.profile.healthColors.tapped - elseif( not UnitPlayerOrPetInRaid(unit) and not UnitPlayerOrPetInParty(unit) and ( ( ( reactionType == "player" or reactionType == "both" ) and UnitPlayerControlled(unit) and not UnitIsFriend(unit, "player") ) or ( ( reactionType == "npc" or reactionType == "both" ) and not UnitPlayerControlled(unit) ) ) ) then - if( not UnitIsFriend(unit, "player") and UnitPlayerControlled(unit) ) then - if( UnitCanAttack("player", unit) ) then - color = ShadowUF.db.profile.healthColors.hostile - else - color = ShadowUF.db.profile.healthColors.enemyUnattack - end - elseif( UnitReaction(unit, "player") ) then - local reaction = UnitReaction(unit, "player") - if( reaction > 4 ) then - color = ShadowUF.db.profile.healthColors.friendly - elseif( reaction == 4 ) then - color = ShadowUF.db.profile.healthColors.neutral - elseif( reaction < 4 ) then - color = ShadowUF.db.profile.healthColors.hostile - end - end - elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "class" and (UnitIsPlayer(unit) or UnitInPartyIsAI(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 unit2 - if frame.unitType == "raidpet" then - local id = string.match(frame.unit, "raidpet(%d+)") - if id then - unit2 = "raid" .. id - end - elseif frame.parent then - unit2 = frame.parent.unit - end - if unit2 then - local class = select(2, UnitClass(unit2)) - 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 - frame:SetBarColor("healthBar", color.r, color.g, color.b) - else - frame.healthBar.hasPercent = true - frame:SetBarColor("healthBar", getGradientColor(unit)) - end -end - -function Health:Update(frame) - local isOffline = not UnitIsConnected(frame.unit) - frame.isDead = UnitIsDeadOrGhost(frame.unit) - frame.healthBar.currentHealth = UnitHealth(frame.unit) - frame.healthBar:SetMinMaxValues(0, UnitHealthMax(frame.unit)) - frame.healthBar:SetValue(isOffline and UnitHealthMax(frame.unit) or frame.isDead and 0 or frame.healthBar.currentHealth) - - -- Unit is offline, fill bar up + grey it - if( isOffline ) then - frame.healthBar.wasOffline = true - frame.unitIsOnline = nil - 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 - frame:SetBarColor("healthBar", getGradientColor(frame.unit)) - end -end +local Health = {} +ShadowUF:RegisterModule(Health, "healthBar", ShadowUF.L["Health bar"], true) +local canCure = ShadowUF.Units.canCure + +local function getGradientColor(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 + + local sR, sG, sB, eR, eG, eB = 0, 0, 0, 0, 0, 0 + local modifier, inverseModifier = percent * 2, 0 + if( percent > 0.50 ) then + sR, sG, sB = ShadowUF.db.profile.healthColors.green.r, ShadowUF.db.profile.healthColors.green.g, ShadowUF.db.profile.healthColors.green.b + eR, eG, eB = ShadowUF.db.profile.healthColors.yellow.r, ShadowUF.db.profile.healthColors.yellow.g, ShadowUF.db.profile.healthColors.yellow.b + + modifier = modifier - 1 + else + sR, sG, sB = ShadowUF.db.profile.healthColors.yellow.r, ShadowUF.db.profile.healthColors.yellow.g, ShadowUF.db.profile.healthColors.yellow.b + eR, eG, eB = ShadowUF.db.profile.healthColors.red.r, ShadowUF.db.profile.healthColors.red.g, ShadowUF.db.profile.healthColors.red.b + end + + inverseModifier = 1 - modifier + return eR * inverseModifier + sR * modifier, eG * inverseModifier + sG * modifier, eB * inverseModifier + sB * modifier +end + +Health.getGradientColor = getGradientColor + +function Health:OnEnable(frame) + if( not frame.healthBar ) then + frame.healthBar = ShadowUF.Units:CreateBar(frame) + end + + 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_TARGETABLE_CHANGED", self, "UpdateColor") + + if( frame.unit == "pet" ) then + frame:RegisterUnitEvent("UNIT_POWER_UPDATE", self, "UpdateColor") + end + + 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: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 = AuraUtil.UnpackAuraData(C_UnitAuras.GetDebuffDataByIndex(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) + frame.healthBar.hasReaction = nil + frame.healthBar.hasPercent = nil + frame.healthBar.wasOffline = nil + + local color + local unit = frame.unit + local reactionType = ShadowUF.db.profile.units[frame.unitType].healthBar.reactionType + if( not UnitIsConnected(unit) ) then + frame.healthBar.wasOffline = true + 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 + 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 UnitPlayerControlled(unit) and UnitIsTapDenied(unit) and UnitCanAttack("player", unit) ) then + color = ShadowUF.db.profile.healthColors.tapped + elseif( not UnitPlayerOrPetInRaid(unit) and not UnitPlayerOrPetInParty(unit) and ( ( ( reactionType == "player" or reactionType == "both" ) and UnitPlayerControlled(unit) and not UnitIsFriend(unit, "player") ) or ( ( reactionType == "npc" or reactionType == "both" ) and not UnitPlayerControlled(unit) ) ) ) then + if( not UnitIsFriend(unit, "player") and UnitPlayerControlled(unit) ) then + if( UnitCanAttack("player", unit) ) then + color = ShadowUF.db.profile.healthColors.hostile + else + color = ShadowUF.db.profile.healthColors.enemyUnattack + end + elseif( UnitReaction(unit, "player") ) then + local reaction = UnitReaction(unit, "player") + if( reaction > 4 ) then + color = ShadowUF.db.profile.healthColors.friendly + elseif( reaction == 4 ) then + color = ShadowUF.db.profile.healthColors.neutral + elseif( reaction < 4 ) then + color = ShadowUF.db.profile.healthColors.hostile + end + end + elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "class" and (UnitIsPlayer(unit) or UnitInPartyIsAI(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 unit2 + if frame.unitType == "raidpet" then + local id = string.match(frame.unit, "raidpet(%d+)") + if id then + unit2 = "raid" .. id + end + elseif frame.parent then + unit2 = frame.parent.unit + end + if unit2 then + local class = select(2, UnitClass(unit2)) + 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 + frame:SetBarColor("healthBar", color.r, color.g, color.b) + else + frame.healthBar.hasPercent = true + frame:SetBarColor("healthBar", getGradientColor(unit)) + end +end + +function Health:Update(frame) + local isOffline = not UnitIsConnected(frame.unit) + frame.isDead = UnitIsDeadOrGhost(frame.unit) + frame.healthBar.currentHealth = UnitHealth(frame.unit) + frame.healthBar:SetMinMaxValues(0, UnitHealthMax(frame.unit)) + frame.healthBar:SetValue(isOffline and UnitHealthMax(frame.unit) or frame.isDead and 0 or frame.healthBar.currentHealth) + + -- Unit is offline, fill bar up + grey it + if( isOffline ) then + frame.healthBar.wasOffline = true + frame.unitIsOnline = nil + 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 + frame:SetBarColor("healthBar", getGradientColor(frame.unit)) + end +end diff --git a/modules/helpers.lua b/modules/helpers.lua index 612a6dde0..df5ede551 100755 --- a/modules/helpers.lua +++ b/modules/helpers.lua @@ -1,33 +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(_, 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 +-- 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(_, 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 diff --git a/modules/highlight.lua b/modules/highlight.lua index 3fec3d62e..deb6ab31f 100755 --- a/modules/highlight.lua +++ b/modules/highlight.lua @@ -1,194 +1,194 @@ -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 -local function OnEnter(frame) - if( ShadowUF.db.profile.units[frame.unitType].highlight.mouseover ) then - frame.highlight.hasMouseover = true - Highlight:Update(frame) - end - - frame.highlight.OnEnter(frame) -end - -local function OnLeave(frame) - if( ShadowUF.db.profile.units[frame.unitType].highlight.mouseover ) then - frame.highlight.hasMouseover = nil - Highlight:Update(frame) - end - - frame.highlight.OnLeave(frame) -end - -function Highlight:OnEnable(frame) - if( not frame.highlight ) then - frame.highlight = CreateFrame("Frame", nil, frame) - frame.highlight:SetFrameLevel(frame.topFrameLevel) - frame.highlight:SetAllPoints(frame) - frame.highlight:SetSize(1, 1) - - frame.highlight.top = frame.highlight:CreateTexture(nil, "OVERLAY") - frame.highlight.top:SetBlendMode("ADD") - frame.highlight.top:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\highlight") - frame.highlight.top:SetPoint("TOPLEFT", frame, ShadowUF.db.profile.backdrop.inset, -ShadowUF.db.profile.backdrop.inset) - frame.highlight.top:SetPoint("TOPRIGHT", frame, -ShadowUF.db.profile.backdrop.inset, ShadowUF.db.profile.backdrop.inset) - frame.highlight.top:SetHeight(30) - frame.highlight.top:SetTexCoord(0.3125, 0.625, 0, 0.3125) - frame.highlight.top:SetHorizTile(false) - - frame.highlight.left = frame.highlight:CreateTexture(nil, "OVERLAY") - frame.highlight.left:SetBlendMode("ADD") - frame.highlight.left:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\highlight") - frame.highlight.left:SetPoint("TOPLEFT", frame, ShadowUF.db.profile.backdrop.inset, -ShadowUF.db.profile.backdrop.inset) - frame.highlight.left:SetPoint("BOTTOMLEFT", frame, -ShadowUF.db.profile.backdrop.inset, ShadowUF.db.profile.backdrop.inset) - frame.highlight.left:SetWidth(30) - frame.highlight.left:SetTexCoord(0, 0.3125, 0.3125, 0.625) - frame.highlight.left:SetHorizTile(false) - - frame.highlight.right = frame.highlight:CreateTexture(nil, "OVERLAY") - frame.highlight.right:SetBlendMode("ADD") - frame.highlight.right:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\highlight") - frame.highlight.right:SetPoint("TOPRIGHT", frame, -ShadowUF.db.profile.backdrop.inset, -ShadowUF.db.profile.backdrop.inset) - frame.highlight.right:SetPoint("BOTTOMRIGHT", frame, 0, ShadowUF.db.profile.backdrop.inset) - frame.highlight.right:SetWidth(30) - frame.highlight.right:SetTexCoord(0.625, 0.93, 0.3125, 0.625) - frame.highlight.right:SetHorizTile(false) - - frame.highlight.bottom = frame.highlight:CreateTexture(nil, "OVERLAY") - frame.highlight.bottom:SetBlendMode("ADD") - frame.highlight.bottom:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\highlight") - frame.highlight.bottom:SetPoint("BOTTOMLEFT", frame, ShadowUF.db.profile.backdrop.inset, ShadowUF.db.profile.backdrop.inset) - frame.highlight.bottom:SetPoint("BOTTOMRIGHT", frame, -ShadowUF.db.profile.backdrop.inset, ShadowUF.db.profile.backdrop.inset) - frame.highlight.bottom:SetHeight(30) - frame.highlight.bottom:SetTexCoord(0.3125, 0.625, 0.625, 0.93) - frame.highlight.bottom:SetHorizTile(false) - frame.highlight:Hide() - end - - frame.highlight.top:SetHeight(ShadowUF.db.profile.units[frame.unitType].highlight.size) - frame.highlight.bottom:SetHeight(ShadowUF.db.profile.units[frame.unitType].highlight.size) - frame.highlight.left:SetWidth(ShadowUF.db.profile.units[frame.unitType].highlight.size) - frame.highlight.right:SetWidth(ShadowUF.db.profile.units[frame.unitType].highlight.size) - - - if( ShadowUF.db.profile.units[frame.unitType].highlight.aggro ) then - frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", self, "UpdateThreat") - frame:RegisterUpdateFunc(self, "UpdateThreat") - end - - if( ShadowUF.db.profile.units[frame.unitType].highlight.attention and frame.unitType ~= "target" and frame.unitType ~= "focus" ) then - frame:RegisterNormalEvent("PLAYER_TARGET_CHANGED", self, "UpdateAttention") - frame:RegisterNormalEvent("PLAYER_FOCUS_CHANGED", self, "UpdateAttention") - frame:RegisterUpdateFunc(self, "UpdateAttention") - end - - if( ShadowUF.db.profile.units[frame.unitType].highlight.debuff ) then - 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.OnEnter - frame.highlight.OnLeave = frame.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 - -function Highlight:OnLayoutApplied(frame) - if( frame.visibility.highlight ) then - self:OnDisable(frame) - self:OnEnable(frame) - end -end - -function Highlight:OnDisable(frame) - frame:UnregisterAll(self) - - frame.highlight.hasDebuff = nil - frame.highlight.hasThreat = nil - frame.highlight.hasAttention = nil - 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] 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) - frame.highlight.bottom:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.units[frame.unitType].highlight.alpha) - frame.highlight.right:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.units[frame.unitType].highlight.alpha) - frame.highlight:Show() - else - frame.highlight:Hide() - end -end - -function Highlight:UpdateThreat(frame) - frame.highlight.hasThreat = UnitThreatSituation(frame.unit) == 3 or nil - self:Update(frame) -end - -function Highlight:UpdateAttention(frame) - frame.highlight.hasAttention = UnitIsUnit(frame.unit, "target") or UnitIsUnit(frame.unit, "focus") or nil - self:Update(frame) -end - -function Highlight:UpdateClassification(frame) - frame.highlight.hasClassification = UnitClassification(frame.unit) - self:Update(frame) -end - -function Highlight:UpdateAura(frame) - frame.highlight.hasDebuff = nil - if( UnitIsFriend(frame.unit, "player") ) then - local id = 0 - while( true ) do - id = id + 1 - local name, _, _, auraType = AuraUtil.UnpackAuraData(C_UnitAuras.GetDebuffDataByIndex(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 +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 +local function OnEnter(frame) + if( ShadowUF.db.profile.units[frame.unitType].highlight.mouseover ) then + frame.highlight.hasMouseover = true + Highlight:Update(frame) + end + + frame.highlight.OnEnter(frame) +end + +local function OnLeave(frame) + if( ShadowUF.db.profile.units[frame.unitType].highlight.mouseover ) then + frame.highlight.hasMouseover = nil + Highlight:Update(frame) + end + + frame.highlight.OnLeave(frame) +end + +function Highlight:OnEnable(frame) + if( not frame.highlight ) then + frame.highlight = CreateFrame("Frame", nil, frame) + frame.highlight:SetFrameLevel(frame.topFrameLevel) + frame.highlight:SetAllPoints(frame) + frame.highlight:SetSize(1, 1) + + frame.highlight.top = frame.highlight:CreateTexture(nil, "OVERLAY") + frame.highlight.top:SetBlendMode("ADD") + frame.highlight.top:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\highlight") + frame.highlight.top:SetPoint("TOPLEFT", frame, ShadowUF.db.profile.backdrop.inset, -ShadowUF.db.profile.backdrop.inset) + frame.highlight.top:SetPoint("TOPRIGHT", frame, -ShadowUF.db.profile.backdrop.inset, ShadowUF.db.profile.backdrop.inset) + frame.highlight.top:SetHeight(30) + frame.highlight.top:SetTexCoord(0.3125, 0.625, 0, 0.3125) + frame.highlight.top:SetHorizTile(false) + + frame.highlight.left = frame.highlight:CreateTexture(nil, "OVERLAY") + frame.highlight.left:SetBlendMode("ADD") + frame.highlight.left:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\highlight") + frame.highlight.left:SetPoint("TOPLEFT", frame, ShadowUF.db.profile.backdrop.inset, -ShadowUF.db.profile.backdrop.inset) + frame.highlight.left:SetPoint("BOTTOMLEFT", frame, -ShadowUF.db.profile.backdrop.inset, ShadowUF.db.profile.backdrop.inset) + frame.highlight.left:SetWidth(30) + frame.highlight.left:SetTexCoord(0, 0.3125, 0.3125, 0.625) + frame.highlight.left:SetHorizTile(false) + + frame.highlight.right = frame.highlight:CreateTexture(nil, "OVERLAY") + frame.highlight.right:SetBlendMode("ADD") + frame.highlight.right:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\highlight") + frame.highlight.right:SetPoint("TOPRIGHT", frame, -ShadowUF.db.profile.backdrop.inset, -ShadowUF.db.profile.backdrop.inset) + frame.highlight.right:SetPoint("BOTTOMRIGHT", frame, 0, ShadowUF.db.profile.backdrop.inset) + frame.highlight.right:SetWidth(30) + frame.highlight.right:SetTexCoord(0.625, 0.93, 0.3125, 0.625) + frame.highlight.right:SetHorizTile(false) + + frame.highlight.bottom = frame.highlight:CreateTexture(nil, "OVERLAY") + frame.highlight.bottom:SetBlendMode("ADD") + frame.highlight.bottom:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\highlight") + frame.highlight.bottom:SetPoint("BOTTOMLEFT", frame, ShadowUF.db.profile.backdrop.inset, ShadowUF.db.profile.backdrop.inset) + frame.highlight.bottom:SetPoint("BOTTOMRIGHT", frame, -ShadowUF.db.profile.backdrop.inset, ShadowUF.db.profile.backdrop.inset) + frame.highlight.bottom:SetHeight(30) + frame.highlight.bottom:SetTexCoord(0.3125, 0.625, 0.625, 0.93) + frame.highlight.bottom:SetHorizTile(false) + frame.highlight:Hide() + end + + frame.highlight.top:SetHeight(ShadowUF.db.profile.units[frame.unitType].highlight.size) + frame.highlight.bottom:SetHeight(ShadowUF.db.profile.units[frame.unitType].highlight.size) + frame.highlight.left:SetWidth(ShadowUF.db.profile.units[frame.unitType].highlight.size) + frame.highlight.right:SetWidth(ShadowUF.db.profile.units[frame.unitType].highlight.size) + + + if( ShadowUF.db.profile.units[frame.unitType].highlight.aggro ) then + frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", self, "UpdateThreat") + frame:RegisterUpdateFunc(self, "UpdateThreat") + end + + if( ShadowUF.db.profile.units[frame.unitType].highlight.attention and frame.unitType ~= "target" and frame.unitType ~= "focus" ) then + frame:RegisterNormalEvent("PLAYER_TARGET_CHANGED", self, "UpdateAttention") + frame:RegisterNormalEvent("PLAYER_FOCUS_CHANGED", self, "UpdateAttention") + frame:RegisterUpdateFunc(self, "UpdateAttention") + end + + if( ShadowUF.db.profile.units[frame.unitType].highlight.debuff ) then + 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.OnEnter + frame.highlight.OnLeave = frame.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 + +function Highlight:OnLayoutApplied(frame) + if( frame.visibility.highlight ) then + self:OnDisable(frame) + self:OnEnable(frame) + end +end + +function Highlight:OnDisable(frame) + frame:UnregisterAll(self) + + frame.highlight.hasDebuff = nil + frame.highlight.hasThreat = nil + frame.highlight.hasAttention = nil + 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] 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) + frame.highlight.bottom:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.units[frame.unitType].highlight.alpha) + frame.highlight.right:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.units[frame.unitType].highlight.alpha) + frame.highlight:Show() + else + frame.highlight:Hide() + end +end + +function Highlight:UpdateThreat(frame) + frame.highlight.hasThreat = UnitThreatSituation(frame.unit) == 3 or nil + self:Update(frame) +end + +function Highlight:UpdateAttention(frame) + frame.highlight.hasAttention = UnitIsUnit(frame.unit, "target") or UnitIsUnit(frame.unit, "focus") or nil + self:Update(frame) +end + +function Highlight:UpdateClassification(frame) + frame.highlight.hasClassification = UnitClassification(frame.unit) + self:Update(frame) +end + +function Highlight:UpdateAura(frame) + frame.highlight.hasDebuff = nil + if( UnitIsFriend(frame.unit, "player") ) then + local id = 0 + while( true ) do + id = id + 1 + local name, _, _, auraType = AuraUtil.UnpackAuraData(C_UnitAuras.GetDebuffDataByIndex(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 index 65870909d..5e042026c 100755 --- a/modules/holypower.lua +++ b/modules/holypower.lua @@ -1,31 +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") -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 +if( not ShadowUF.ComboPoints ) then return end + +local HolyPower = setmetatable({}, {__index = ShadowUF.ComboPoints}) +ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN") +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 diff --git a/modules/incabsorb.lua b/modules/incabsorb.lua index 10ae25239..8b346588a 100755 --- a/modules/incabsorb.lua +++ b/modules/incabsorb.lua @@ -1,49 +1,49 @@ -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_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 +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_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 diff --git a/modules/incheal.lua b/modules/incheal.lua index a3095b86a..1b1b8f363 100755 --- a/modules/incheal.lua +++ b/modules/incheal.lua @@ -1,146 +1,146 @@ -local IncHeal = {["frameKey"] = "incHeal", ["colorKey"] = "inc", ["frameLevelMod"] = 2} -ShadowUF.IncHeal = IncHeal -ShadowUF:RegisterModule(IncHeal, "incHeal", ShadowUF.L["Incoming heals"]) - -function IncHeal:OnEnable(frame) - frame.incHeal = frame.incHeal or ShadowUF.Units:CreateBar(frame) - - frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "UpdateFrame") - frame:RegisterUnitEvent("UNIT_HEALTH", self, "UpdateFrame") - frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", self, "UpdateFrame") - - frame:RegisterUpdateFunc(self, "UpdateFrame") -end - -function IncHeal:OnDisable(frame) - frame:UnregisterAll(self) - frame[self.frameKey]:Hide() -end - -function IncHeal:OnLayoutApplied(frame) - 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() - - 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 - bar.healthSize = frame.healthBar:GetHeight() - bar.positionPoint = bar.reverseFill and "TOPLEFT" or "BOTTOMLEFT" - bar.positionRelative = bar.reverseFill and "TOPRIGHT" or "BOTTOMRIGHT" - end - - bar.positionMod = bar.reverseFill and -1 or 1 - bar.maxSize = bar.healthSize * cap - end -end - -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 - - local health = UnitHealth(frame.unit) - if( health <= 0 ) then - bar.total = nil - bar:Hide() - return - end - - local maxHealth = UnitHealthMax(frame.unit) - if( maxHealth <= 0 ) then - bar.total = nil - bar:Hide() - return - end - - if( not bar.total ) then bar:Show() end - bar.total = incAmount - - -- 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 - - 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 - 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) - 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 - - self:PositionBar(frame, amount) -end +local IncHeal = {["frameKey"] = "incHeal", ["colorKey"] = "inc", ["frameLevelMod"] = 2} +ShadowUF.IncHeal = IncHeal +ShadowUF:RegisterModule(IncHeal, "incHeal", ShadowUF.L["Incoming heals"]) + +function IncHeal:OnEnable(frame) + frame.incHeal = frame.incHeal or ShadowUF.Units:CreateBar(frame) + + frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "UpdateFrame") + frame:RegisterUnitEvent("UNIT_HEALTH", self, "UpdateFrame") + frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", self, "UpdateFrame") + + frame:RegisterUpdateFunc(self, "UpdateFrame") +end + +function IncHeal:OnDisable(frame) + frame:UnregisterAll(self) + frame[self.frameKey]:Hide() +end + +function IncHeal:OnLayoutApplied(frame) + 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() + + 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 + bar.healthSize = frame.healthBar:GetHeight() + bar.positionPoint = bar.reverseFill and "TOPLEFT" or "BOTTOMLEFT" + bar.positionRelative = bar.reverseFill and "TOPRIGHT" or "BOTTOMRIGHT" + end + + bar.positionMod = bar.reverseFill and -1 or 1 + bar.maxSize = bar.healthSize * cap + end +end + +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 + + local health = UnitHealth(frame.unit) + if( health <= 0 ) then + bar.total = nil + bar:Hide() + return + end + + local maxHealth = UnitHealthMax(frame.unit) + if( maxHealth <= 0 ) then + bar.total = nil + bar:Hide() + return + end + + if( not bar.total ) then bar:Show() end + bar.total = incAmount + + -- 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 + + 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 + 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) + 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 + + self:PositionBar(frame, amount) +end diff --git a/modules/indicators.lua b/modules/indicators.lua index eacb08b72..5480d19d2 100755 --- a/modules/indicators.lua +++ b/modules/indicators.lua @@ -1,490 +1,503 @@ -local Indicators = {list = {"status", "pvp", "leader", "resurrect", "sumPending", "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 = frame:UnitClassToken() - if( UnitIsPlayer(frame.unit) and class ) then - 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() - else - frame.indicators.class:Hide() - end -end - -function Indicators:UpdatePhase(frame) - if( not frame.indicators.phase or not frame.indicators.phase.enabled ) then return end - - if( UnitIsConnected(frame.unit) and UnitPhaseReason(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:SummonPending(frame) - if( not frame.indicators.sumPending or not frame.indicators.sumPending.enabled ) then return end - - if( C_IncomingSummon.HasIncomingSummon(frame.unit) ) then - if( C_IncomingSummon.IncomingSummonStatus(frame.unit) == 1 ) then - frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") - frame.indicators.sumPending:SetTexCoord(0.539062, 0.789062, 0.015625, 0.515625) - frame.indicators.sumPending:Show() - elseif( C_IncomingSummon.IncomingSummonStatus(frame.unit) == 2 ) then - frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") - frame.indicators.sumPending:SetTexCoord(0.0078125, 0.257812, 0.015625, 0.515625) - frame.indicators.sumPending:Show() - elseif( C_IncomingSummon.IncomingSummonStatus(frame.unit) == 3 ) then - frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") - frame.indicators.sumPending:SetTexCoord(0.273438, 0.523438, 0.015625, 0.515625) - frame.indicators.sumPending:Show() - else - frame.indicators.sumPending:Hide() - end - else - frame.indicators.sumPending:Hide() - end -end - - -function Indicators:UpdateMasterLoot(frame) - if( not frame.indicators.masterLoot or not frame.indicators.masterLoot.enabled ) then return end - - local lootType, partyID, raidID = GetLootMethod() - if( lootType ~= "master" ) then - frame.indicators.masterLoot:Hide() - elseif( ( partyID and partyID == 0 and UnitIsUnit(frame.unit, "player") ) or ( partyID and partyID > 0 and UnitIsUnit(frame.unit, ShadowUF.partyUnits[partyID]) ) or ( raidID and raidID > 0 and UnitIsUnit(frame.unit, ShadowUF.raidUnits[raidID]) ) ) then - frame.indicators.masterLoot:Show() - else - frame.indicators.masterLoot:Hide() - end -end - -function Indicators:UpdateRaidTarget(frame) - if( not frame.indicators.raidTarget or not frame.indicators.raidTarget.enabled ) then return end - - if( UnitExists(frame.unit) and GetRaidTargetIndex(frame.unit) ) then - SetRaidTargetIconTexture(frame.indicators.raidTarget, GetRaidTargetIndex(frame.unit)) - frame.indicators.raidTarget:Show() - else - frame.indicators.raidTarget:Hide() - 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 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( role == "HEALER" ) then - frame.indicators.lfdRole:SetTexCoord(20/64, 39/64, 1/64, 20/64) - frame.indicators.lfdRole:Show() - elseif( role == "DAMAGER" ) then - frame.indicators.lfdRole:SetTexCoord(20/64, 39/64, 22/64, 41/64) - frame.indicators.lfdRole:Show() - else - frame.indicators.lfdRole:Hide() - end -end - -function Indicators:UpdateRole(frame, event) - if( not frame.indicators.role or not frame.indicators.role.enabled ) then return end - - 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") - frame.indicators.role:Show() - elseif( GetPartyAssignment("MAINASSIST", frame.unit) ) then - frame.indicators.role:SetTexture("Interface\\GroupFrame\\UI-Group-MainAssistIcon") - frame.indicators.role:Show() - else - frame.indicators.role:Hide() - end -end - -function Indicators:UpdateLeader(frame) - if( not frame.indicators.leader or not frame.indicators.leader.enabled ) then return end - - if( UnitIsGroupLeader(frame.unit) or (frame.unit == "target" and UnitLeadsAnyGroup(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 - - 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 - if( self.timeElapsed < 1 ) then return end - self.timeElapsed = self.timeElapsed - 1 - - if( UnitAffectingCombat(self.parent.unit) ) then - self.status:Show() - else - self.status:Hide() - end -end - --- It looks like the combat check for players is a bit buggy when they are in a vehicle, so swap it to also check polling -function Indicators:CheckVehicle(frame) - frame.indicators.timeElapsed = 0 - frame.indicators:SetScript("OnUpdate", frame.inVehicle and combatMonitor or nil) -end - -function Indicators:UpdateStatus(frame) - if( not frame.indicators.status or not frame.indicators.status.enabled ) then return end - - if( UnitAffectingCombat(frame.unitOwner) ) then - frame.indicators.status:SetTexCoord(0.50, 1.0, 0.0, 0.49) - frame.indicators.status:Show() - elseif( frame.unitRealType == "player" and IsResting() ) then - frame.indicators.status:SetTexCoord(0.0, 0.50, 0.0, 0.421875) - frame.indicators.status:Show() - else - frame.indicators.status:Hide() - end -end - -local FADEOUT_TIME = 6 -function Indicators:UpdateReadyCheck(frame, event) - if( not frame.indicators.ready or not frame.indicators.ready.enabled ) then return end - - -- We're done, and should fade it out if it's shown - if( event == "READY_CHECK_FINISHED" ) then - if( not frame.indicators.ready:IsShown() ) then return end - - -- Create the central timer frame if ones not already made - if( not self.fadeTimer ) then - self.fadeTimer = CreateFrame("Frame", nil) - self.fadeTimer.fadeList = {} - self.fadeTimer:Hide() - self.fadeTimer:SetScript("OnUpdate", function(f, elapsed) - local hasTimer - for fadeFrame, timeLeft in pairs(f.fadeList) do - hasTimer = true - - f.fadeList[fadeFrame] = timeLeft - elapsed - - if( f.fadeList[fadeFrame] <= 0 ) then - f.fadeList[fadeFrame] = nil - fadeFrame:Hide() - else - fadeFrame:SetAlpha(f.fadeList[fadeFrame] / FADEOUT_TIME) - end - end - - if( not hasTimer ) then f:Hide() end - end) - end - - -- Start the timer - self.fadeTimer.fadeList[frame.indicators.ready] = FADEOUT_TIME - self.fadeTimer:Show() - - -- Player never responded so they are AFK - if( frame.indicators.ready.status == "waiting" ) then - frame.indicators.ready:SetAtlas(READY_CHECK_NOT_READY_TEXTURE, TextureKitConstants.IgnoreAtlasSize) - end - return - end - - -- Have a state change in ready status - local status = GetReadyCheckStatus(frame.unit) - if( not status ) then - frame.indicators.ready.status = nil - frame.indicators.ready:Hide() - return - end - - if( status == "ready" ) then - frame.indicators.ready:SetAtlas(READY_CHECK_READY_TEXTURE, TextureKitConstants.IgnoreAtlasSize) - elseif( status == "notready" ) then - frame.indicators.ready:SetAtlas(READY_CHECK_NOT_READY_TEXTURE, TextureKitConstants.IgnoreAtlasSize) - elseif( status == "waiting" ) then - frame.indicators.ready:SetAtlas(READY_CHECK_WAITING_TEXTURE, TextureKitConstants.IgnoreAtlasSize) - end - - frame.indicators:SetScript("OnUpdate", nil) - frame.indicators.ready.status = status - frame.indicators.ready:SetAlpha(1.0) - frame.indicators.ready:Show() -end - -function Indicators:UpdateFlags(frame) - self:UpdateLeader(frame) - self:UpdatePVPFlag(frame) -end - -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 + 2) - end - - -- Now lets enable all the indicators - local config = ShadowUF.db.profile.units[frame.unitType] - if( config.indicators.status and config.indicators.status.enabled ) then - frame:RegisterUpdateFunc(self, "UpdateStatus") - frame.indicators.status = frame.indicators.status or frame.indicators:CreateTexture(nil, "OVERLAY") - frame.indicators.status:SetTexture("Interface\\CharacterFrame\\UI-StateIcon") - frame.indicators.timeElapsed = 0 - frame.indicators.parent = frame - - if( frame.unitType == "player" ) then - frame:RegisterUpdateFunc(self, "CheckVehicle") - frame:RegisterNormalEvent("PLAYER_REGEN_ENABLED", self, "UpdateStatus") - frame:RegisterNormalEvent("PLAYER_REGEN_DISABLED", self, "UpdateStatus") - frame:RegisterNormalEvent("PLAYER_UPDATE_RESTING", self, "UpdateStatus") - frame:RegisterNormalEvent("UPDATE_FACTION", self, "UpdateStatus") - else - frame.indicators.status:SetTexCoord(0.50, 1.0, 0.0, 0.49) - frame.indicators:SetScript("OnUpdate", combatMonitor) - end - 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.sumPending and config.indicators.sumPending.enabled ) then - frame:RegisterNormalEvent("INCOMING_SUMMON_CHANGED", self, "SummonPending") - frame:RegisterUpdateFunc(self, "SummonPending") - - frame.indicators.sumPending = frame.indicators.sumPending or frame.indicators:CreateTexture(nil, "OVERLAY") - frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") - end - - if( config.indicators.pvp and config.indicators.pvp.enabled ) then - frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdatePVPFlag") - frame:RegisterUpdateFunc(self, "UpdatePVPFlag") - - frame.indicators.pvp = frame.indicators.pvp or frame.indicators:CreateTexture(nil, "OVERLAY") - end - - if( config.indicators.class and config.indicators.class.enabled ) then - frame:RegisterUpdateFunc(self, "UpdateClass") - frame.indicators.class = frame.indicators.class or frame.indicators:CreateTexture(nil, "OVERLAY") - end - - if( config.indicators.leader and config.indicators.leader.enabled ) then - frame:RegisterNormalEvent("PARTY_LEADER_CHANGED", self, "UpdateLeader") - frame:RegisterUpdateFunc(self, "UpdateLeader") - - frame.indicators.leader = frame.indicators.leader or frame.indicators:CreateTexture(nil, "OVERLAY") - end - - if( config.indicators.masterLoot and config.indicators.masterLoot.enabled ) then - frame:RegisterNormalEvent("PARTY_LOOT_METHOD_CHANGED", self, "UpdateMasterLoot") - frame:RegisterUpdateFunc(self, "UpdateMasterLoot") - - frame.indicators.masterLoot = frame.indicators.masterLoot or frame.indicators:CreateTexture(nil, "OVERLAY") - frame.indicators.masterLoot:SetTexture("Interface\\GroupFrame\\UI-Group-MasterLooter") - end - - if( config.indicators.role and config.indicators.role.enabled ) then - frame:RegisterUpdateFunc(self, "UpdateRole") - - frame.indicators.role = frame.indicators.role or frame.indicators:CreateTexture(nil, "OVERLAY") - frame.indicators.role:SetTexture("Interface\\GroupFrame\\UI-Group-MainAssistIcon") - end - - if( config.indicators.raidTarget and config.indicators.raidTarget.enabled ) then - frame:RegisterNormalEvent("RAID_TARGET_UPDATE", self, "UpdateRaidTarget") - frame:RegisterUpdateFunc(self, "UpdateRaidTarget") - - frame.indicators.raidTarget = frame.indicators.raidTarget or frame.indicators:CreateTexture(nil, "OVERLAY") - frame.indicators.raidTarget:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons") - end - - if( config.indicators.ready and config.indicators.ready.enabled ) then - frame:RegisterNormalEvent("READY_CHECK", self, "UpdateReadyCheck") - frame:RegisterNormalEvent("READY_CHECK_CONFIRM", self, "UpdateReadyCheck") - frame:RegisterNormalEvent("READY_CHECK_FINISHED", self, "UpdateReadyCheck") - frame:RegisterUpdateFunc(self, "UpdateReadyCheck") - - frame.indicators.ready = frame.indicators.ready or frame.indicators:CreateTexture(nil, "OVERLAY") - end - - if( config.indicators.lfdRole and config.indicators.lfdRole.enabled ) then - 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("GROUP_ROSTER_UPDATE", self, "GroupRosterUpdate") - end - - if( frame.indicators.leader or frame.indicators.pvp ) then - frame:RegisterUnitEvent("PLAYER_FLAGS_CHANGED", self, "UpdateFlags") - end -end - -function Indicators:OnDisable(frame) - frame:UnregisterAll(self) - - for _, key in pairs(self.list) do - if( frame.indicators[key] ) then - frame.indicators[key].enabled = nil - frame.indicators[key]:Hide() - end - end -end - -function Indicators:OnLayoutApplied(frame, config) - if( frame.visibility.indicators ) then - self:OnDisable(frame) - self:OnEnable(frame) - - for _, key in pairs(self.list) do - local indicator = frame.indicators[key] - 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) - ShadowUF.Layout:AnchorFrame(frame, indicator, config.indicators[key]) - elseif( indicator ) then - indicator.enabled = nil - indicator:Hide() - end - end - - -- Disable the polling - if( config.indicators.status and not config.indicators.status.enabled and frame.indicators.status ) then - frame.indicators:SetScript("OnUpdate", nil) - end - end -end +local Indicators = {list = {"status", "pvp", "leader", "resurrect", "masterLoot", "raidTarget", "ready", "role", "class", "phase", "happiness" }} + +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 = frame:UnitClassToken() + if( UnitIsPlayer(frame.unit) and class ) then + 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() + else + frame.indicators.class:Hide() + end +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:SummonPending(frame) + -- if( not frame.indicators.sumPending or not frame.indicators.sumPending.enabled ) then return end + + -- if( C_IncomingSummon.HasIncomingSummon(frame.unit) ) then + -- if( C_IncomingSummon.IncomingSummonStatus(frame.unit) == 1 ) then + -- frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") + -- frame.indicators.sumPending:SetTexCoord(0.539062, 0.789062, 0.015625, 0.515625) + -- frame.indicators.sumPending:Show() + -- elseif( C_IncomingSummon.IncomingSummonStatus(frame.unit) == 2 ) then + -- frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") + -- frame.indicators.sumPending:SetTexCoord(0.0078125, 0.257812, 0.015625, 0.515625) + -- frame.indicators.sumPending:Show() + -- elseif( C_IncomingSummon.IncomingSummonStatus(frame.unit) == 3 ) then + -- frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") + -- frame.indicators.sumPending:SetTexCoord(0.273438, 0.523438, 0.015625, 0.515625) + -- frame.indicators.sumPending:Show() + -- else + -- frame.indicators.sumPending:Hide() + -- end + -- else + -- frame.indicators.sumPending:Hide() + -- end +-- end + + +function Indicators:UpdateMasterLoot(frame) + if( not frame.indicators.masterLoot or not frame.indicators.masterLoot.enabled ) then return end + + local lootType, partyID, raidID = GetLootMethod() + if( lootType ~= "master" ) then + frame.indicators.masterLoot:Hide() + elseif( ( partyID and partyID == 0 and UnitIsUnit(frame.unit, "player") ) or ( partyID and partyID > 0 and UnitIsUnit(frame.unit, ShadowUF.partyUnits[partyID]) ) or ( raidID and raidID > 0 and UnitIsUnit(frame.unit, ShadowUF.raidUnits[raidID]) ) ) then + frame.indicators.masterLoot:Show() + else + frame.indicators.masterLoot:Hide() + end +end + +function Indicators:UpdateRaidTarget(frame) + if( not frame.indicators.raidTarget or not frame.indicators.raidTarget.enabled ) then return end + + if( UnitExists(frame.unit) and GetRaidTargetIndex(frame.unit) ) then + SetRaidTargetIconTexture(frame.indicators.raidTarget, GetRaidTargetIndex(frame.unit)) + frame.indicators.raidTarget:Show() + else + frame.indicators.raidTarget:Hide() + 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 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( role == "HEALER" ) then + frame.indicators.lfdRole:SetTexCoord(20/64, 39/64, 1/64, 20/64) + frame.indicators.lfdRole:Show() + elseif( role == "DAMAGER" ) then + frame.indicators.lfdRole:SetTexCoord(20/64, 39/64, 22/64, 41/64) + frame.indicators.lfdRole:Show() + else + frame.indicators.lfdRole:Hide() + end +end + +function Indicators:UpdateRole(frame, event) + if( not frame.indicators.role or not frame.indicators.role.enabled ) then return end + + 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") + frame.indicators.role:Show() + elseif( GetPartyAssignment("MAINASSIST", frame.unit) ) then + frame.indicators.role:SetTexture("Interface\\GroupFrame\\UI-Group-MainAssistIcon") + frame.indicators.role:Show() + else + frame.indicators.role:Hide() + end +end + +function Indicators:UpdateLeader(frame) + if( not frame.indicators.leader or not frame.indicators.leader.enabled ) then return end + + if( UnitIsGroupLeader(frame.unit) or (frame.unit == "target" and UnitLeadsAnyGroup(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 + + 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 + if( self.timeElapsed < 1 ) then return end + self.timeElapsed = self.timeElapsed - 1 + + if( UnitAffectingCombat(self.parent.unit) ) then + self.status:Show() + else + self.status:Hide() + end +end + +-- It looks like the combat check for players is a bit buggy when they are in a vehicle, so swap it to also check polling +function Indicators:CheckVehicle(frame) + frame.indicators.timeElapsed = 0 + frame.indicators:SetScript("OnUpdate", frame.inVehicle and combatMonitor or nil) +end + +function Indicators:UpdateStatus(frame) + if( not frame.indicators.status or not frame.indicators.status.enabled ) then return end + + if( UnitAffectingCombat(frame.unitOwner) ) then + frame.indicators.status:SetTexCoord(0.50, 1.0, 0.0, 0.49) + frame.indicators.status:Show() + elseif( frame.unitRealType == "player" and IsResting() ) then + frame.indicators.status:SetTexCoord(0.0, 0.50, 0.0, 0.421875) + frame.indicators.status:Show() + else + frame.indicators.status:Hide() + end +end + +-- Ready check fading once the check complete +local function fadeReadyStatus(self, elapsed) + self.timeLeft = self.timeLeft - elapsed + self.ready:SetAlpha(self.timeLeft / self.startTime) + + if( self.timeLeft <= 0 ) then + self:SetScript("OnUpdate", nil) + + self.ready.status = nil + self.ready:Hide() + end +end + +local FADEOUT_TIME = 6 +function Indicators:UpdateReadyCheck(frame, event) + if( not frame.indicators.ready or not frame.indicators.ready.enabled ) then return end + + -- We're done, and should fade it out if it's shown + if( event == "READY_CHECK_FINISHED" ) then + if( not frame.indicators.ready:IsShown() ) then return end + + -- Create the central timer frame if ones not already made + if( not self.fadeTimer ) then + self.fadeTimer = CreateFrame("Frame", nil) + self.fadeTimer.fadeList = {} + self.fadeTimer:Hide() + self.fadeTimer:SetScript("OnUpdate", function(f, elapsed) + local hasTimer + for fadeFrame, timeLeft in pairs(f.fadeList) do + hasTimer = true + + f.fadeList[fadeFrame] = timeLeft - elapsed + + if( f.fadeList[fadeFrame] <= 0 ) then + f.fadeList[fadeFrame] = nil + fadeFrame:Hide() + else + fadeFrame:SetAlpha(f.fadeList[fadeFrame] / FADEOUT_TIME) + end + end + + if( not hasTimer ) then f:Hide() end + end) + end + + -- Start the timer + self.fadeTimer.fadeList[frame.indicators.ready] = FADEOUT_TIME + self.fadeTimer:Show() + + -- Player never responded so they are AFK + if( frame.indicators.ready.status == "waiting" ) then + frame.indicators.ready:SetTexture("Interface\\RaidFrame\\ReadyCheck-NotReady") + end + return + end + + -- Have a state change in ready status + local status = GetReadyCheckStatus(frame.unit) + if( not status ) then + frame.indicators.ready.status = nil + frame.indicators.ready:Hide() + return + end + + if( status == "ready" ) then + frame.indicators.ready:SetTexture(READY_CHECK_READY_TEXTURE) + elseif( status == "notready" ) then + frame.indicators.ready:SetTexture(READY_CHECK_NOT_READY_TEXTURE) + elseif( status == "waiting" ) then + frame.indicators.ready:SetTexture(READY_CHECK_WAITING_TEXTURE) + end + + frame.indicators:SetScript("OnUpdate", nil) + frame.indicators.ready.status = status + frame.indicators.ready:SetAlpha(1.0) + frame.indicators.ready:Show() +end + +function Indicators:UpdateFlags(frame) + self:UpdateLeader(frame) + self:UpdatePVPFlag(frame) +end + +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 + 2) + end + + -- Now lets enable all the indicators + local config = ShadowUF.db.profile.units[frame.unitType] + if( config.indicators.status and config.indicators.status.enabled ) then + frame:RegisterUpdateFunc(self, "UpdateStatus") + frame.indicators.status = frame.indicators.status or frame.indicators:CreateTexture(nil, "OVERLAY") + frame.indicators.status:SetTexture("Interface\\CharacterFrame\\UI-StateIcon") + frame.indicators.timeElapsed = 0 + frame.indicators.parent = frame + + if( frame.unitType == "player" ) then + frame:RegisterUpdateFunc(self, "CheckVehicle") + frame:RegisterNormalEvent("PLAYER_REGEN_ENABLED", self, "UpdateStatus") + frame:RegisterNormalEvent("PLAYER_REGEN_DISABLED", self, "UpdateStatus") + frame:RegisterNormalEvent("PLAYER_UPDATE_RESTING", self, "UpdateStatus") + frame:RegisterNormalEvent("UPDATE_FACTION", self, "UpdateStatus") + else + frame.indicators.status:SetTexCoord(0.50, 1.0, 0.0, 0.49) + frame.indicators:SetScript("OnUpdate", combatMonitor) + end + 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.sumPending and config.indicators.sumPending.enabled ) then + -- frame:RegisterNormalEvent("INCOMING_SUMMON_CHANGED", self, "SummonPending") + -- frame:RegisterUpdateFunc(self, "SummonPending") + + -- frame.indicators.sumPending = frame.indicators.sumPending or frame.indicators:CreateTexture(nil, "OVERLAY") + -- frame.indicators.sumPending:SetTexture("Interface\\RaidFrame\\RaidFrameSummon") + -- end + + if( config.indicators.pvp and config.indicators.pvp.enabled ) then + frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdatePVPFlag") + frame:RegisterUpdateFunc(self, "UpdatePVPFlag") + + frame.indicators.pvp = frame.indicators.pvp or frame.indicators:CreateTexture(nil, "OVERLAY") + end + + if( config.indicators.class and config.indicators.class.enabled ) then + frame:RegisterUpdateFunc(self, "UpdateClass") + frame.indicators.class = frame.indicators.class or frame.indicators:CreateTexture(nil, "OVERLAY") + end + + if( config.indicators.leader and config.indicators.leader.enabled ) then + frame:RegisterNormalEvent("PARTY_LEADER_CHANGED", self, "UpdateLeader") + frame:RegisterUpdateFunc(self, "UpdateLeader") + + frame.indicators.leader = frame.indicators.leader or frame.indicators:CreateTexture(nil, "OVERLAY") + end + + if( config.indicators.masterLoot and config.indicators.masterLoot.enabled ) then + frame:RegisterNormalEvent("PARTY_LOOT_METHOD_CHANGED", self, "UpdateMasterLoot") + frame:RegisterUpdateFunc(self, "UpdateMasterLoot") + + frame.indicators.masterLoot = frame.indicators.masterLoot or frame.indicators:CreateTexture(nil, "OVERLAY") + frame.indicators.masterLoot:SetTexture("Interface\\GroupFrame\\UI-Group-MasterLooter") + end + + if( config.indicators.role and config.indicators.role.enabled ) then + frame:RegisterUpdateFunc(self, "UpdateRole") + + frame.indicators.role = frame.indicators.role or frame.indicators:CreateTexture(nil, "OVERLAY") + frame.indicators.role:SetTexture("Interface\\GroupFrame\\UI-Group-MainAssistIcon") + end + + if( config.indicators.raidTarget and config.indicators.raidTarget.enabled ) then + frame:RegisterNormalEvent("RAID_TARGET_UPDATE", self, "UpdateRaidTarget") + frame:RegisterUpdateFunc(self, "UpdateRaidTarget") + + frame.indicators.raidTarget = frame.indicators.raidTarget or frame.indicators:CreateTexture(nil, "OVERLAY") + frame.indicators.raidTarget:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons") + end + + if( config.indicators.ready and config.indicators.ready.enabled ) then + frame:RegisterNormalEvent("READY_CHECK", self, "UpdateReadyCheck") + frame:RegisterNormalEvent("READY_CHECK_CONFIRM", self, "UpdateReadyCheck") + frame:RegisterNormalEvent("READY_CHECK_FINISHED", self, "UpdateReadyCheck") + frame:RegisterUpdateFunc(self, "UpdateReadyCheck") + + frame.indicators.ready = frame.indicators.ready or frame.indicators:CreateTexture(nil, "OVERLAY") + end + + if( config.indicators.lfdRole and config.indicators.lfdRole.enabled ) then + 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("GROUP_ROSTER_UPDATE", self, "GroupRosterUpdate") + end + + if( frame.indicators.leader or frame.indicators.pvp ) then + frame:RegisterUnitEvent("PLAYER_FLAGS_CHANGED", self, "UpdateFlags") + end +end + +function Indicators:OnDisable(frame) + frame:UnregisterAll(self) + + for _, key in pairs(self.list) do + if( frame.indicators[key] ) then + frame.indicators[key].enabled = nil + frame.indicators[key]:Hide() + end + end +end + +function Indicators:OnLayoutApplied(frame, config) + if( frame.visibility.indicators ) then + self:OnDisable(frame) + self:OnEnable(frame) + + for _, key in pairs(self.list) do + local indicator = frame.indicators[key] + 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) + ShadowUF.Layout:AnchorFrame(frame, indicator, config.indicators[key]) + elseif( indicator ) then + indicator.enabled = nil + indicator:Hide() + end + end + + -- Disable the polling + if( config.indicators.status and not config.indicators.status.enabled and frame.indicators.status ) then + frame.indicators:SetScript("OnUpdate", nil) + end + end +end diff --git a/modules/layout.lua b/modules/layout.lua index d483a0b6d..d4008ac39 100755 --- a/modules/layout.lua +++ b/modules/layout.lua @@ -1,609 +1,609 @@ -local Layout = {mediaPath = {}} -local SML, mediaRequired, anchoringQueued -local mediaPath = Layout.mediaPath -local backdropTbl = {insets = {}} -local _G = getfenv(0) - -ShadowUF.Layout = Layout - --- Someone is using another mod that is forcing a media type for all mods using SML -function Layout:MediaForced(mediaType) - local oldPath = mediaPath[mediaType] - self:CheckMedia() - - if( mediaPath[mediaType] ~= oldPath ) then - self:Reload() - end -end - -local function loadMedia(type, name, default) - if( name == "" ) then return "" end - - local media = SML:Fetch(type, name, true) - if( not media ) then - mediaRequired = mediaRequired or {} - mediaRequired[type] = name - return default - end - - return media -end - --- Updates the background table -local function updateBackdrop() - -- Update the backdrop table - local backdrop = ShadowUF.db.profile.backdrop - backdropTbl.bgFile = mediaPath.background - if( mediaPath.border ~= "Interface\\None" ) then backdropTbl.edgeFile = mediaPath.border end - backdropTbl.tile = backdrop.tileSize > 0 and true or false - backdropTbl.edgeSize = backdrop.edgeSize == 0 and 1 or backdrop.edgeSize - backdropTbl.tileSize = backdrop.tileSize - backdropTbl.insets.left = backdrop.inset - backdropTbl.insets.right = backdrop.inset - backdropTbl.insets.top = backdrop.inset - backdropTbl.insets.bottom = backdrop.inset -end - --- Tries to load media, if it fails it will default to whatever I set -function Layout:CheckMedia() - mediaPath[SML.MediaType.STATUSBAR] = loadMedia(SML.MediaType.STATUSBAR, ShadowUF.db.profile.bars.texture, "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Aluminium") - mediaPath[SML.MediaType.FONT] = loadMedia(SML.MediaType.FONT, ShadowUF.db.profile.font.name, "Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf") - mediaPath[SML.MediaType.BACKGROUND] = loadMedia(SML.MediaType.BACKGROUND, ShadowUF.db.profile.backdrop.backgroundTexture, "Interface\\ChatFrame\\ChatFrameBackground") - mediaPath[SML.MediaType.BORDER] = loadMedia(SML.MediaType.BORDER, ShadowUF.db.profile.backdrop.borderTexture, "") - - updateBackdrop() -end - --- We might not have had a media we required at initial load, wait for it to load and then update everything when it does -function Layout:MediaRegistered(event, mediaType, key) - if( mediaRequired and mediaRequired[mediaType] and mediaRequired[mediaType] == key ) then - mediaPath[mediaType] = SML:Fetch(mediaType, key) - mediaRequired[mediaType] = nil - - self:Reload() - end -end - --- Helper functions -function Layout:ToggleVisibility(frame, visible) - if( frame and visible ) then - frame:Show() - elseif( frame ) then - frame:Hide() - end -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 -end - - --- Frame changed somehow between when we first set it all up and now -function Layout:Reload(unit) - updateBackdrop() - - -- Now update them - for frame in pairs(ShadowUF.Units.frameList) do - if( frame.unit and ( not unit or frame.unitType == unit ) and not frame.isHeaderFrame ) then - frame:SetVisibility() - self:Load(frame) - 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 - --- Do a full update -function Layout:Load(frame) - local unitConfig = ShadowUF.db.profile.units[frame.unitType] - - -- 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) - self:SetupBars(frame, unitConfig) - self:PositionWidgets(frame, unitConfig) - self:SetupText(frame, unitConfig) - - -- Layouts been fully set - ShadowUF:FireModuleEvent("OnLayoutApplied", frame, unitConfig) -end - --- Register it on file load because authors seem to do a bad job at registering the callbacks -SML = LibStub:GetLibrary("LibSharedMedia-3.0") -SML:Register(SML.MediaType.FONT, "Myriad Condensed Web", "Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf") -SML:Register(SML.MediaType.BORDER, "Square Clean", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\ABFBorder") -SML:Register(SML.MediaType.BACKGROUND, "Chat Frame", "Interface\\ChatFrame\\ChatFrameBackground") -SML:Register(SML.MediaType.STATUSBAR, "BantoBar", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\banto") -SML:Register(SML.MediaType.STATUSBAR, "Smooth", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smooth") -SML:Register(SML.MediaType.STATUSBAR, "Smooth v2","Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Smoothv2") -SML:Register(SML.MediaType.STATUSBAR, "Smoother", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smoother") -SML:Register(SML.MediaType.STATUSBAR, "Perl", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\perl") -SML:Register(SML.MediaType.STATUSBAR, "Glaze", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\glaze") -SML:Register(SML.MediaType.STATUSBAR, "Charcoal", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Charcoal") -SML:Register(SML.MediaType.STATUSBAR, "Otravi", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\otravi") -SML:Register(SML.MediaType.STATUSBAR, "Striped", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\striped") -SML:Register(SML.MediaType.STATUSBAR, "LiteStep", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\LiteStep") -SML:Register(SML.MediaType.STATUSBAR, "Aluminium", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Aluminium") -SML:Register(SML.MediaType.STATUSBAR, "Minimalist", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Minimalist") - -function Layout:LoadSML() - SML.RegisterCallback(self, "LibSharedMedia_Registered", "MediaRegistered") - SML.RegisterCallback(self, "LibSharedMedia_SetGlobal", "MediaForced") - self:CheckMedia() -end - ---[[ - Keep in mind this is relative to where you're parenting it, RT will put the object outside of the frame, on the right side, at the top of it while ITR will put it inside the frame, at the top to the right - - * Positions OUTSIDE the frame - RT = Right Top, RC = Right Center, RB = Right Bottom - LT = Left Top, LC = Left Center, LB = Left Bottom, - BL = Bottom Left, BC = Bottom Center, BR = Bottom Right - TR = Top Right, TC = Top Center, TL = Top Left - - * Positions INSIDE the frame - CLI = Inside Center Left, CRI = Inside Center Right - TRI = Inside Top Right, TLI = Inside Top Left - BRI = Inside Bottom Right, BRI = Inside Bottom left -]] - -local preDefPoint = {C = "CENTER", CLI = "LEFT", RT = "TOPLEFT", BC = "TOP", CRI = "RIGHT", LT = "TOPRIGHT", TR = "BOTTOMRIGHT", BL = "TOPLEFT", LB = "BOTTOMRIGHT", LC = "RIGHT", RB = "BOTTOMLEFT", RC = "LEFT", TC = "BOTTOM", BR = "TOPRIGHT", TL = "BOTTOMLEFT", BRI = "BOTTOMRIGHT", BLI = "BOTTOMLEFT", TRI = "TOPRIGHT", TLI = "TOPLEFT"} -local preDefRelative = {C = "CENTER", CLI = "LEFT", RT = "TOPRIGHT", BC = "BOTTOM", CRI = "RIGHT", LT = "TOPLEFT", TR = "TOPRIGHT", BL = "BOTTOMLEFT", LB = "BOTTOMLEFT", LC = "LEFT", RB = "BOTTOMRIGHT", RC = "RIGHT", TC = "TOP", BR = "BOTTOMRIGHT", TL = "TOPLEFT", BRI = "BOTTOMRIGHT", BLI = "BOTTOMLEFT", TRI = "TOPRIGHT", TLI = "TOPLEFT"} -local columnDirection = {RT = "RIGHT", C = "RIGHT", BC = "BOTTOM", LT = "LEFT", TR = "TOP", BL = "BOTTOM", LB = "LEFT", LC = "LEFT", TRI = "TOP", RB = "RIGHT", RC = "RIGHT", TC = "TOP", CLI = "RIGHT", TL = "TOP", BR = "BOTTOM", IBL = "RIGHT", IBR = "RIGHT", CRI = "RIGHT", TLI = "TOP"} -local auraDirection = {RT = "BOTTOM", C = "LEFT", BC = "LEFT", LT = "BOTTOM", TR = "LEFT", BL = "RIGHT", LB = "TOP", LC = "LEFT", TRI = "LEFT", RB = "TOP", RC = "LEFT", TC = "LEFT", CLI = "RIGHT", TL = "RIGHT", BR = "LEFT", IBL = "TOP", IBR = "TOP", CRI = "LEFT", TLI = "RIGHT"} - --- Figures out how text should be justified based on where it's anchoring -function Layout:GetJustify(config) - local point = config.anchorPoint and config.anchorPoint ~= "" and preDefPoint[config.anchorPoint] or config.point - if( point and point ~= "" ) then - if( string.match(point, "LEFT$") ) then - return "LEFT" - elseif( string.match(point, "RIGHT$") ) then - return "RIGHT" - end - end - - return "CENTER" -end - -function Layout:GetPoint(key) - return preDefPoint[key] or "CENTER" -end - -function Layout:GetRelative(key) - return preDefRelative[key] or "CENTER" -end - -function Layout:GetColumnGrowth(key) - return columnDirection[key] or "DOWN" -end - -function Layout:GetAuraGrowth(key) - return auraDirection[key] or "LEFT" -end - -function Layout:ReverseDirection(key) - return key == "LEFT" and "RIGHT" or key == "RIGHT" and "LEFT" or key == "TOP" and "BOTTOM" or key == "BOTTOM" and "TOP" -end - --- Gets the relative anchoring for Blizzards default raid frames, these differ from the split ones -function Layout:GetRelativeAnchor(point) - if( point == "TOP" ) then - return "BOTTOM", 0, -1 - elseif( point == "BOTTOM" ) then - return "TOP", 0, 1 - elseif( point == "LEFT" ) then - return "RIGHT", 1, 0 - elseif( point == "RIGHT" ) then - return "LEFT", -1, 0 - elseif( point == "TOPLEFT" ) then - return "BOTTOMRIGHT", 1, -1 - elseif( point == "TOPRIGHT" ) then - return "BOTTOMLEFT", -1, -1 - elseif( point == "BOTTOMLEFT" ) then - return "TOPRIGHT", 1, 1 - elseif( point == "BOTTOMRIGHT" ) then - return "TOPLEFT", -1, 1 - else - return "CENTER", 0, 0 - end -end - -function Layout:GetSplitRelativeAnchor(point, columnPoint) - -- Column is growing to the RIGHT - if( columnPoint == "LEFT" ) then - return "TOPLEFT", "TOPRIGHT", 1, 0 - -- Column is growing to the LEFT - elseif( columnPoint == "RIGHT" ) then - return "TOPRIGHT", "TOPLEFT", -1, 0 - -- Column is growing DOWN - elseif( columnPoint == "TOP" ) then - return "TOP" .. point, "BOTTOM" .. point, 0, -1 - -- Column is growing UP - elseif( columnPoint == "BOTTOM" ) then - return "BOTTOM" .. point, "TOP" .. point, 0, 1 - end -end - -function Layout:AnchorFrame(parent, frame, config) - if( not config or not config.anchorTo or not config.x or not config.y ) then - return - end - - local anchorTo = config.anchorTo - local prefix = string.sub(config.anchorTo, 0, 1) - if( config.anchorTo == "$parent" ) then - anchorTo = parent - -- $ is used as an indicator of a sub-frame inside a parent, $healthBar -> parent.healthBar and so on - elseif( prefix == "$" ) then - anchorTo = parent[string.sub(config.anchorTo, 2)] - -- # is used as an indicator of an actual frame created by SUF, it lets us know that the frame might not be created yet - -- and if so, to watch for it to be created and fix the anchoring - elseif( prefix == "#" ) then - anchorTo = string.sub(config.anchorTo, 2) - - -- The frame we wanted to anchor to doesn't exist yet, so will queue and wait for it to exist - if( not _G[anchorTo] ) then - frame.queuedParent = parent - frame.queuedConfig = config - frame.queuedName = anchorTo - - anchoringQueued = anchoringQueued or {} - anchoringQueued[frame] = true - - -- For the time being, will take over the frame we wanted to anchor to's position. - local unit = string.match(anchorTo, "SUFUnit(%w+)") or string.match(anchorTo, "SUFHeader(%w+)") - if( unit and ShadowUF.db.profile.positions[unit] ) then - self:AnchorFrame(parent, frame, ShadowUF.db.profile.positions[unit]) - end - 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" - local relativePoint = config.relativePoint and config.relativePoint ~= "" and config.relativePoint or preDefRelative[config.anchorPoint] or "CENTER" - - -- Effective scaling is only used for unit based frames and if they are anchored to UIParent - local scale = 1 - if( config.anchorTo == "UIParent" and frame.unitType ) then - scale = frame:GetScale() * UIParent:GetScale() - end - - frame:ClearAllPoints() - frame:SetPoint(point, anchorTo, relativePoint, config.x / scale, config.y / scale) -end - --- Setup the main frame -function Layout:SetupFrame(frame, config) - local backdrop = ShadowUF.db.profile.backdrop - frame.backdropInfo = backdropTbl - frame:ApplyBackdrop() - frame:SetBackdropColor(backdrop.backgroundColor.r, backdrop.backgroundColor.g, backdrop.backgroundColor.b, backdrop.backgroundColor.a) - frame:SetBackdropBorderColor(backdrop.borderColor.r, backdrop.borderColor.g, backdrop.borderColor.b, backdrop.borderColor.a) - - -- Prevent these from updating while in combat to prevent tainting - if( not InCombatLockdown() ) then - frame:SetHeight(config.height) - frame:SetWidth(config.width) - frame:SetScale(config.scale) - - -- Let the frame clip closer to the edge, not using inset + clip as that lets you move it too far in - local clamp = backdrop.inset + 0.20 - frame:SetClampRectInsets(clamp, -clamp, -clamp, clamp) - frame:SetClampedToScreen(true) - - -- This is wrong technically, I need to redo the backdrop stuff so it will accept insets and that will fit hitbox issues - -- for the time being, this is a temporary fix to it - local hit = backdrop.borderTexture == "None" and backdrop.inset or 0 - frame:SetHitRectInsets(hit, hit, hit, hit) - - if( not frame.ignoreAnchor ) then - self:AnchorFrame(frame.parent or UIParent, frame, ShadowUF.db.profile.positions[frame.unitType]) - end - end - - -- Check if we had anything parented to us - if( anchoringQueued ) then - for queued in pairs(anchoringQueued) do - if( queued.queuedName == frame:GetName() ) then - self:AnchorFrame(queued.queuedParent, queued, queued.queuedConfig) - - queued.queuedParent = nil - queued.queuedConfig = nil - queued.queuedName = nil - anchoringQueued[queued] = nil - end - end - end - -end - --- Setup bars -function Layout:SetupBars(frame, config) - for _, module in pairs(ShadowUF.modules) do - local key = module.moduleKey - local widget = frame[key] - if( widget and ( module.moduleHasBar or config[key] and config[key].isBar ) ) then - 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() 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 or config[key].invert ) then - widget.background:SetTexture(mediaPath.statusbar) - widget.background:SetHorizTile(false) - widget.background:Show() - - widget.background.overrideColor = ShadowUF.db.profile.bars.backgroundColor or config[key].backgroundColor - - if( widget.background.overrideColor ) then - widget.background:SetVertexColor(widget.background.overrideColor.r, widget.background.overrideColor.g, widget.background.overrideColor.b, ShadowUF.db.profile.bars.backgroundAlpha) - end - else - widget.background:Hide() - end - end - end - end -end - --- Setup text -function Layout:SetupFontString(fontString, extraSize) - local size = ShadowUF.db.profile.font.size + (extraSize or 0) - if( size <= 0 ) then size = 1 end - - fontString:SetFont(mediaPath.font, size, ShadowUF.db.profile.font.extra) - - if( ShadowUF.db.profile.font.shadowColor and ShadowUF.db.profile.font.shadowX and ShadowUF.db.profile.font.shadowY ) then - fontString:SetShadowColor(ShadowUF.db.profile.font.shadowColor.r, ShadowUF.db.profile.font.shadowColor.g, ShadowUF.db.profile.font.shadowColor.b, ShadowUF.db.profile.font.shadowColor.a) - fontString:SetShadowOffset(ShadowUF.db.profile.font.shadowX, ShadowUF.db.profile.font.shadowY) - else - fontString:SetShadowColor(0, 0, 0, 0) - fontString:SetShadowOffset(0, 0) - end -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 {} - for _, fontString in pairs(frame.fontStrings) do - ShadowUF.Tags:Unregister(fontString) - fontString:Hide() - end - - for k in pairs(totalWeight) do totalWeight[k] = nil end - - -- Update the actual text, and figure out the weighting information now - for id, row in pairs(config.text) do - 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 _, 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) - - frame:RegisterUpdateFunc(fontString, "UpdateTags") - else - frame:UnregisterAll(fontString) - end - end -end - --- Setup the bar barOrder/info -local currentConfig -local function sortOrder(a, b) - return currentConfig[a].order < currentConfig[b].order -end - -local barOrder = {} -function Layout:PositionWidgets(frame, config) - -- Deal with setting all of the bar heights - local totalWidgetWeight, totalBars, hasFullSize = 0, -1 - - -- 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 - totalWidgetWeight = totalWidgetWeight + 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 - hasFullSize = true - frame[key].fullSize = true - else - frame[key].fullSize = nil - end - end - end - - -- Sort the barOrder so it's all nice and orderly (:>) - currentConfig = config - table.sort(barOrder, sortOrder) - - -- Now deal with setting the heights and figure out how large the portrait should be. - local clip = ShadowUF.db.profile.backdrop.inset + ShadowUF.db.profile.backdrop.clip - local clipDoubled = clip * 2 - - local portraitOffset, portraitAlignment, portraitAnchor, portraitWidth - if( not config.portrait.isBar ) then - self:ToggleVisibility(frame.portrait, frame.visibility.portrait) - - if( frame.visibility.portrait ) then - -- Figure out portrait alignment - portraitAlignment = config.portrait.alignment - - -- Set the portrait width so we can figure out the offset to use on bars, will do height and position later - portraitWidth = math.floor(frame:GetWidth() * config.portrait.width) - ShadowUF.db.profile.backdrop.inset - frame.portrait:SetWidth(portraitWidth - (portraitAlignment == "RIGHT" and 1 or 0.5)) - - -- Disable portrait if there isn't enough room - if( portraitWidth <= 0 ) then - frame.portrait:Hide() - end - - -- As well as how much to offset bars by (if it's using a left alignment) to keep them all fancy looking - portraitOffset = clip - if( portraitAlignment == "LEFT" ) then - portraitOffset = portraitOffset + portraitWidth - end - end - end - - -- Position and size everything - local portraitHeight, xOffset = 0, -clip - local availableHeight = frame:GetHeight() - clipDoubled - (math.abs(ShadowUF.db.profile.bars.spacing) * totalBars) - for id, key in pairs(barOrder) do - local bar = frame[key] - - -- Position the actual bar based on it's type - if( bar.fullSize ) then - bar:SetWidth(frame:GetWidth() - clipDoubled) - bar:SetHeight(availableHeight * (config[key].height / totalWidgetWeight)) - - bar:ClearAllPoints() - bar:SetPoint("TOPLEFT", frame, "TOPLEFT", clip, xOffset) - else - bar:SetWidth(frame:GetWidth() - portraitWidth - clipDoubled) - bar:SetHeight(availableHeight * (config[key].height / totalWidgetWeight)) - - bar:ClearAllPoints() - bar:SetPoint("TOPLEFT", frame, "TOPLEFT", portraitOffset, xOffset) - - portraitHeight = portraitHeight + bar:GetHeight() - end - - -- Figure out where the portrait is going to be anchored to - if( not portraitAnchor and config[key].order >= config.portrait.fullBefore ) then - portraitAnchor = bar - end - - xOffset = xOffset - bar:GetHeight() + ShadowUF.db.profile.bars.spacing - end - - -- Now position the portrait and set the height - if( frame.portrait and frame.portrait:IsShown() and portraitAnchor and portraitHeight > 0 ) then - if( portraitAlignment == "LEFT" ) then - frame.portrait:ClearAllPoints() - frame.portrait:SetPoint("TOPLEFT", portraitAnchor, "TOPLEFT", -frame.portrait:GetWidth() - 0.5, 0) - elseif( portraitAlignment == "RIGHT" ) then - frame.portrait:ClearAllPoints() - frame.portrait:SetPoint("TOPRIGHT", portraitAnchor, "TOPRIGHT", frame.portrait:GetWidth() + 1, 0) - end - - if( hasFullSize ) then - frame.portrait:SetHeight(portraitHeight) - else - frame.portrait:SetHeight(frame:GetHeight() - clipDoubled) - end - end - - ShadowUF:FireModuleEvent("OnLayoutWidgets", frame, config) -end - +local Layout = {mediaPath = {}} +local SML, mediaRequired, anchoringQueued +local mediaPath = Layout.mediaPath +local backdropTbl = {insets = {}} +local _G = getfenv(0) + +ShadowUF.Layout = Layout + +-- Someone is using another mod that is forcing a media type for all mods using SML +function Layout:MediaForced(mediaType) + local oldPath = mediaPath[mediaType] + self:CheckMedia() + + if( mediaPath[mediaType] ~= oldPath ) then + self:Reload() + end +end + +local function loadMedia(type, name, default) + if( name == "" ) then return "" end + + local media = SML:Fetch(type, name, true) + if( not media ) then + mediaRequired = mediaRequired or {} + mediaRequired[type] = name + return default + end + + return media +end + +-- Updates the background table +local function updateBackdrop() + -- Update the backdrop table + local backdrop = ShadowUF.db.profile.backdrop + backdropTbl.bgFile = mediaPath.background + if( mediaPath.border ~= "Interface\\None" ) then backdropTbl.edgeFile = mediaPath.border end + backdropTbl.tile = backdrop.tileSize > 0 and true or false + backdropTbl.edgeSize = backdrop.edgeSize == 0 and 1 or backdrop.edgeSize + backdropTbl.tileSize = backdrop.tileSize + backdropTbl.insets.left = backdrop.inset + backdropTbl.insets.right = backdrop.inset + backdropTbl.insets.top = backdrop.inset + backdropTbl.insets.bottom = backdrop.inset +end + +-- Tries to load media, if it fails it will default to whatever I set +function Layout:CheckMedia() + mediaPath[SML.MediaType.STATUSBAR] = loadMedia(SML.MediaType.STATUSBAR, ShadowUF.db.profile.bars.texture, "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Aluminium") + mediaPath[SML.MediaType.FONT] = loadMedia(SML.MediaType.FONT, ShadowUF.db.profile.font.name, "Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf") + mediaPath[SML.MediaType.BACKGROUND] = loadMedia(SML.MediaType.BACKGROUND, ShadowUF.db.profile.backdrop.backgroundTexture, "Interface\\ChatFrame\\ChatFrameBackground") + mediaPath[SML.MediaType.BORDER] = loadMedia(SML.MediaType.BORDER, ShadowUF.db.profile.backdrop.borderTexture, "") + + updateBackdrop() +end + +-- We might not have had a media we required at initial load, wait for it to load and then update everything when it does +function Layout:MediaRegistered(event, mediaType, key) + if( mediaRequired and mediaRequired[mediaType] and mediaRequired[mediaType] == key ) then + mediaPath[mediaType] = SML:Fetch(mediaType, key) + mediaRequired[mediaType] = nil + + self:Reload() + end +end + +-- Helper functions +function Layout:ToggleVisibility(frame, visible) + if( frame and visible ) then + frame:Show() + elseif( frame ) then + frame:Hide() + end +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 +end + + +-- Frame changed somehow between when we first set it all up and now +function Layout:Reload(unit) + updateBackdrop() + + -- Now update them + for frame in pairs(ShadowUF.Units.frameList) do + if( frame.unit and ( not unit or frame.unitType == unit ) and not frame.isHeaderFrame ) then + frame:SetVisibility() + self:Load(frame) + 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 + +-- Do a full update +function Layout:Load(frame) + local unitConfig = ShadowUF.db.profile.units[frame.unitType] + + -- 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) + self:SetupBars(frame, unitConfig) + self:PositionWidgets(frame, unitConfig) + self:SetupText(frame, unitConfig) + + -- Layouts been fully set + ShadowUF:FireModuleEvent("OnLayoutApplied", frame, unitConfig) +end + +-- Register it on file load because authors seem to do a bad job at registering the callbacks +SML = LibStub:GetLibrary("LibSharedMedia-3.0") +SML:Register(SML.MediaType.FONT, "Myriad Condensed Web", "Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf") +SML:Register(SML.MediaType.BORDER, "Square Clean", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\ABFBorder") +SML:Register(SML.MediaType.BACKGROUND, "Chat Frame", "Interface\\ChatFrame\\ChatFrameBackground") +SML:Register(SML.MediaType.STATUSBAR, "BantoBar", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\banto") +SML:Register(SML.MediaType.STATUSBAR, "Smooth", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smooth") +SML:Register(SML.MediaType.STATUSBAR, "Smooth v2","Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Smoothv2") +SML:Register(SML.MediaType.STATUSBAR, "Smoother", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smoother") +SML:Register(SML.MediaType.STATUSBAR, "Perl", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\perl") +SML:Register(SML.MediaType.STATUSBAR, "Glaze", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\glaze") +SML:Register(SML.MediaType.STATUSBAR, "Charcoal", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Charcoal") +SML:Register(SML.MediaType.STATUSBAR, "Otravi", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\otravi") +SML:Register(SML.MediaType.STATUSBAR, "Striped", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\striped") +SML:Register(SML.MediaType.STATUSBAR, "LiteStep", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\LiteStep") +SML:Register(SML.MediaType.STATUSBAR, "Aluminium", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Aluminium") +SML:Register(SML.MediaType.STATUSBAR, "Minimalist", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Minimalist") + +function Layout:LoadSML() + SML.RegisterCallback(self, "LibSharedMedia_Registered", "MediaRegistered") + SML.RegisterCallback(self, "LibSharedMedia_SetGlobal", "MediaForced") + self:CheckMedia() +end + +--[[ + Keep in mind this is relative to where you're parenting it, RT will put the object outside of the frame, on the right side, at the top of it while ITR will put it inside the frame, at the top to the right + + * Positions OUTSIDE the frame + RT = Right Top, RC = Right Center, RB = Right Bottom + LT = Left Top, LC = Left Center, LB = Left Bottom, + BL = Bottom Left, BC = Bottom Center, BR = Bottom Right + TR = Top Right, TC = Top Center, TL = Top Left + + * Positions INSIDE the frame + CLI = Inside Center Left, CRI = Inside Center Right + TRI = Inside Top Right, TLI = Inside Top Left + BRI = Inside Bottom Right, BRI = Inside Bottom left +]] + +local preDefPoint = {C = "CENTER", CLI = "LEFT", RT = "TOPLEFT", BC = "TOP", CRI = "RIGHT", LT = "TOPRIGHT", TR = "BOTTOMRIGHT", BL = "TOPLEFT", LB = "BOTTOMRIGHT", LC = "RIGHT", RB = "BOTTOMLEFT", RC = "LEFT", TC = "BOTTOM", BR = "TOPRIGHT", TL = "BOTTOMLEFT", BRI = "BOTTOMRIGHT", BLI = "BOTTOMLEFT", TRI = "TOPRIGHT", TLI = "TOPLEFT"} +local preDefRelative = {C = "CENTER", CLI = "LEFT", RT = "TOPRIGHT", BC = "BOTTOM", CRI = "RIGHT", LT = "TOPLEFT", TR = "TOPRIGHT", BL = "BOTTOMLEFT", LB = "BOTTOMLEFT", LC = "LEFT", RB = "BOTTOMRIGHT", RC = "RIGHT", TC = "TOP", BR = "BOTTOMRIGHT", TL = "TOPLEFT", BRI = "BOTTOMRIGHT", BLI = "BOTTOMLEFT", TRI = "TOPRIGHT", TLI = "TOPLEFT"} +local columnDirection = {RT = "RIGHT", C = "RIGHT", BC = "BOTTOM", LT = "LEFT", TR = "TOP", BL = "BOTTOM", LB = "LEFT", LC = "LEFT", TRI = "TOP", RB = "RIGHT", RC = "RIGHT", TC = "TOP", CLI = "RIGHT", TL = "TOP", BR = "BOTTOM", IBL = "RIGHT", IBR = "RIGHT", CRI = "RIGHT", TLI = "TOP"} +local auraDirection = {RT = "BOTTOM", C = "LEFT", BC = "LEFT", LT = "BOTTOM", TR = "LEFT", BL = "RIGHT", LB = "TOP", LC = "LEFT", TRI = "LEFT", RB = "TOP", RC = "LEFT", TC = "LEFT", CLI = "RIGHT", TL = "RIGHT", BR = "LEFT", IBL = "TOP", IBR = "TOP", CRI = "LEFT", TLI = "RIGHT"} + +-- Figures out how text should be justified based on where it's anchoring +function Layout:GetJustify(config) + local point = config.anchorPoint and config.anchorPoint ~= "" and preDefPoint[config.anchorPoint] or config.point + if( point and point ~= "" ) then + if( string.match(point, "LEFT$") ) then + return "LEFT" + elseif( string.match(point, "RIGHT$") ) then + return "RIGHT" + end + end + + return "CENTER" +end + +function Layout:GetPoint(key) + return preDefPoint[key] or "CENTER" +end + +function Layout:GetRelative(key) + return preDefRelative[key] or "CENTER" +end + +function Layout:GetColumnGrowth(key) + return columnDirection[key] or "DOWN" +end + +function Layout:GetAuraGrowth(key) + return auraDirection[key] or "LEFT" +end + +function Layout:ReverseDirection(key) + return key == "LEFT" and "RIGHT" or key == "RIGHT" and "LEFT" or key == "TOP" and "BOTTOM" or key == "BOTTOM" and "TOP" +end + +-- Gets the relative anchoring for Blizzards default raid frames, these differ from the split ones +function Layout:GetRelativeAnchor(point) + if( point == "TOP" ) then + return "BOTTOM", 0, -1 + elseif( point == "BOTTOM" ) then + return "TOP", 0, 1 + elseif( point == "LEFT" ) then + return "RIGHT", 1, 0 + elseif( point == "RIGHT" ) then + return "LEFT", -1, 0 + elseif( point == "TOPLEFT" ) then + return "BOTTOMRIGHT", 1, -1 + elseif( point == "TOPRIGHT" ) then + return "BOTTOMLEFT", -1, -1 + elseif( point == "BOTTOMLEFT" ) then + return "TOPRIGHT", 1, 1 + elseif( point == "BOTTOMRIGHT" ) then + return "TOPLEFT", -1, 1 + else + return "CENTER", 0, 0 + end +end + +function Layout:GetSplitRelativeAnchor(point, columnPoint) + -- Column is growing to the RIGHT + if( columnPoint == "LEFT" ) then + return "TOPLEFT", "TOPRIGHT", 1, 0 + -- Column is growing to the LEFT + elseif( columnPoint == "RIGHT" ) then + return "TOPRIGHT", "TOPLEFT", -1, 0 + -- Column is growing DOWN + elseif( columnPoint == "TOP" ) then + return "TOP" .. point, "BOTTOM" .. point, 0, -1 + -- Column is growing UP + elseif( columnPoint == "BOTTOM" ) then + return "BOTTOM" .. point, "TOP" .. point, 0, 1 + end +end + +function Layout:AnchorFrame(parent, frame, config) + if( not config or not config.anchorTo or not config.x or not config.y ) then + return + end + + local anchorTo = config.anchorTo + local prefix = string.sub(config.anchorTo, 0, 1) + if( config.anchorTo == "$parent" ) then + anchorTo = parent + -- $ is used as an indicator of a sub-frame inside a parent, $healthBar -> parent.healthBar and so on + elseif( prefix == "$" ) then + anchorTo = parent[string.sub(config.anchorTo, 2)] + -- # is used as an indicator of an actual frame created by SUF, it lets us know that the frame might not be created yet + -- and if so, to watch for it to be created and fix the anchoring + elseif( prefix == "#" ) then + anchorTo = string.sub(config.anchorTo, 2) + + -- The frame we wanted to anchor to doesn't exist yet, so will queue and wait for it to exist + if( not _G[anchorTo] ) then + frame.queuedParent = parent + frame.queuedConfig = config + frame.queuedName = anchorTo + + anchoringQueued = anchoringQueued or {} + anchoringQueued[frame] = true + + -- For the time being, will take over the frame we wanted to anchor to's position. + local unit = string.match(anchorTo, "SUFUnit(%w+)") or string.match(anchorTo, "SUFHeader(%w+)") + if( unit and ShadowUF.db.profile.positions[unit] ) then + self:AnchorFrame(parent, frame, ShadowUF.db.profile.positions[unit]) + end + 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" + local relativePoint = config.relativePoint and config.relativePoint ~= "" and config.relativePoint or preDefRelative[config.anchorPoint] or "CENTER" + + -- Effective scaling is only used for unit based frames and if they are anchored to UIParent + local scale = 1 + if( config.anchorTo == "UIParent" and frame.unitType ) then + scale = frame:GetScale() * UIParent:GetScale() + end + + frame:ClearAllPoints() + frame:SetPoint(point, anchorTo, relativePoint, config.x / scale, config.y / scale) +end + +-- Setup the main frame +function Layout:SetupFrame(frame, config) + local backdrop = ShadowUF.db.profile.backdrop + frame.backdropInfo = backdropTbl + frame:ApplyBackdrop() + frame:SetBackdropColor(backdrop.backgroundColor.r, backdrop.backgroundColor.g, backdrop.backgroundColor.b, backdrop.backgroundColor.a) + frame:SetBackdropBorderColor(backdrop.borderColor.r, backdrop.borderColor.g, backdrop.borderColor.b, backdrop.borderColor.a) + + -- Prevent these from updating while in combat to prevent tainting + if( not InCombatLockdown() ) then + frame:SetHeight(config.height) + frame:SetWidth(config.width) + frame:SetScale(config.scale) + + -- Let the frame clip closer to the edge, not using inset + clip as that lets you move it too far in + local clamp = backdrop.inset + 0.20 + frame:SetClampRectInsets(clamp, -clamp, -clamp, clamp) + frame:SetClampedToScreen(true) + + -- This is wrong technically, I need to redo the backdrop stuff so it will accept insets and that will fit hitbox issues + -- for the time being, this is a temporary fix to it + local hit = backdrop.borderTexture == "None" and backdrop.inset or 0 + frame:SetHitRectInsets(hit, hit, hit, hit) + + if( not frame.ignoreAnchor ) then + self:AnchorFrame(frame.parent or UIParent, frame, ShadowUF.db.profile.positions[frame.unitType]) + end + end + + -- Check if we had anything parented to us + if( anchoringQueued ) then + for queued in pairs(anchoringQueued) do + if( queued.queuedName == frame:GetName() ) then + self:AnchorFrame(queued.queuedParent, queued, queued.queuedConfig) + + queued.queuedParent = nil + queued.queuedConfig = nil + queued.queuedName = nil + anchoringQueued[queued] = nil + end + end + end + +end + +-- Setup bars +function Layout:SetupBars(frame, config) + for _, module in pairs(ShadowUF.modules) do + local key = module.moduleKey + local widget = frame[key] + if( widget and ( module.moduleHasBar or config[key] and config[key].isBar ) ) then + 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() 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 or config[key].invert ) then + widget.background:SetTexture(mediaPath.statusbar) + widget.background:SetHorizTile(false) + widget.background:Show() + + widget.background.overrideColor = ShadowUF.db.profile.bars.backgroundColor or config[key].backgroundColor + + if( widget.background.overrideColor ) then + widget.background:SetVertexColor(widget.background.overrideColor.r, widget.background.overrideColor.g, widget.background.overrideColor.b, ShadowUF.db.profile.bars.backgroundAlpha) + end + else + widget.background:Hide() + end + end + end + end +end + +-- Setup text +function Layout:SetupFontString(fontString, extraSize) + local size = ShadowUF.db.profile.font.size + (extraSize or 0) + if( size <= 0 ) then size = 1 end + + fontString:SetFont(mediaPath.font, size, ShadowUF.db.profile.font.extra) + + if( ShadowUF.db.profile.font.shadowColor and ShadowUF.db.profile.font.shadowX and ShadowUF.db.profile.font.shadowY ) then + fontString:SetShadowColor(ShadowUF.db.profile.font.shadowColor.r, ShadowUF.db.profile.font.shadowColor.g, ShadowUF.db.profile.font.shadowColor.b, ShadowUF.db.profile.font.shadowColor.a) + fontString:SetShadowOffset(ShadowUF.db.profile.font.shadowX, ShadowUF.db.profile.font.shadowY) + else + fontString:SetShadowColor(0, 0, 0, 0) + fontString:SetShadowOffset(0, 0) + end +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 {} + for _, fontString in pairs(frame.fontStrings) do + ShadowUF.Tags:Unregister(fontString) + fontString:Hide() + end + + for k in pairs(totalWeight) do totalWeight[k] = nil end + + -- Update the actual text, and figure out the weighting information now + for id, row in pairs(config.text) do + 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 _, 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) + + frame:RegisterUpdateFunc(fontString, "UpdateTags") + else + frame:UnregisterAll(fontString) + end + end +end + +-- Setup the bar barOrder/info +local currentConfig +local function sortOrder(a, b) + return currentConfig[a].order < currentConfig[b].order +end + +local barOrder = {} +function Layout:PositionWidgets(frame, config) + -- Deal with setting all of the bar heights + local totalWidgetWeight, totalBars, hasFullSize = 0, -1 + + -- 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 + totalWidgetWeight = totalWidgetWeight + 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 + hasFullSize = true + frame[key].fullSize = true + else + frame[key].fullSize = nil + end + end + end + + -- Sort the barOrder so it's all nice and orderly (:>) + currentConfig = config + table.sort(barOrder, sortOrder) + + -- Now deal with setting the heights and figure out how large the portrait should be. + local clip = ShadowUF.db.profile.backdrop.inset + ShadowUF.db.profile.backdrop.clip + local clipDoubled = clip * 2 + + local portraitOffset, portraitAlignment, portraitAnchor, portraitWidth + if( not config.portrait.isBar ) then + self:ToggleVisibility(frame.portrait, frame.visibility.portrait) + + if( frame.visibility.portrait ) then + -- Figure out portrait alignment + portraitAlignment = config.portrait.alignment + + -- Set the portrait width so we can figure out the offset to use on bars, will do height and position later + portraitWidth = math.floor(frame:GetWidth() * config.portrait.width) - ShadowUF.db.profile.backdrop.inset + frame.portrait:SetWidth(portraitWidth - (portraitAlignment == "RIGHT" and 1 or 0.5)) + + -- Disable portrait if there isn't enough room + if( portraitWidth <= 0 ) then + frame.portrait:Hide() + end + + -- As well as how much to offset bars by (if it's using a left alignment) to keep them all fancy looking + portraitOffset = clip + if( portraitAlignment == "LEFT" ) then + portraitOffset = portraitOffset + portraitWidth + end + end + end + + -- Position and size everything + local portraitHeight, xOffset = 0, -clip + local availableHeight = frame:GetHeight() - clipDoubled - (math.abs(ShadowUF.db.profile.bars.spacing) * totalBars) + for id, key in pairs(barOrder) do + local bar = frame[key] + + -- Position the actual bar based on it's type + if( bar.fullSize ) then + bar:SetWidth(frame:GetWidth() - clipDoubled) + bar:SetHeight(availableHeight * (config[key].height / totalWidgetWeight)) + + bar:ClearAllPoints() + bar:SetPoint("TOPLEFT", frame, "TOPLEFT", clip, xOffset) + else + bar:SetWidth(frame:GetWidth() - portraitWidth - clipDoubled) + bar:SetHeight(availableHeight * (config[key].height / totalWidgetWeight)) + + bar:ClearAllPoints() + bar:SetPoint("TOPLEFT", frame, "TOPLEFT", portraitOffset, xOffset) + + portraitHeight = portraitHeight + bar:GetHeight() + end + + -- Figure out where the portrait is going to be anchored to + if( not portraitAnchor and config[key].order >= config.portrait.fullBefore ) then + portraitAnchor = bar + end + + xOffset = xOffset - bar:GetHeight() + ShadowUF.db.profile.bars.spacing + end + + -- Now position the portrait and set the height + if( frame.portrait and frame.portrait:IsShown() and portraitAnchor and portraitHeight > 0 ) then + if( portraitAlignment == "LEFT" ) then + frame.portrait:ClearAllPoints() + frame.portrait:SetPoint("TOPLEFT", portraitAnchor, "TOPLEFT", -frame.portrait:GetWidth() - 0.5, 0) + elseif( portraitAlignment == "RIGHT" ) then + frame.portrait:ClearAllPoints() + frame.portrait:SetPoint("TOPRIGHT", portraitAnchor, "TOPRIGHT", frame.portrait:GetWidth() + 1, 0) + end + + if( hasFullSize ) then + frame.portrait:SetHeight(portraitHeight) + else + frame.portrait:SetHeight(frame:GetHeight() - clipDoubled) + end + end + + ShadowUF:FireModuleEvent("OnLayoutWidgets", frame, config) +end + diff --git a/modules/monk.lua b/modules/monk.lua new file mode 100644 index 000000000..abda54b95 --- /dev/null +++ b/modules/monk.lua @@ -0,0 +1,28 @@ +local Monk = {} +ShadowUF:RegisterModule(Monk, "monkBar", ShadowUF.L["Monk mana bar"], true, "MONK", SPEC_MONK_MISTWEAVER) + +function Monk:OnEnable(frame) + frame.monkBar = frame.monkBar or ShadowUF.Units:CreateBar(frame) + + frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update") + frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "Update") + + frame:RegisterUpdateFunc(self, "Update") +end + +function Monk:OnDisable(frame) + frame:UnregisterAll(self) +end + +function Monk:OnLayoutApplied(frame) + if( frame.visibility.monkBar ) then + local color = ShadowUF.db.profile.powerColors.MANA + frame:SetBarColor("monkBar", color.r, color.g, color.b) + end +end + +function Monk:Update(frame, event, unit, powerType) + if( powerType ~= "MANA" ) then return end + frame.monkBar:SetMinMaxValues(0, UnitPowerMax(frame.unit, SPELL_POWER_MANA)) + frame.monkBar:SetValue(UnitIsDeadOrGhost(frame.unit) and 0 or not UnitIsConnected(frame.unit) and 0 or UnitPower(frame.unit, SPELL_POWER_MANA)) +end diff --git a/modules/monkstagger.lua b/modules/monkstagger.lua index 19b034deb..8cc495663 100755 --- a/modules/monkstagger.lua +++ b/modules/monkstagger.lua @@ -1,54 +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(f, elapsed) - f.timeElapsed = f.timeElapsed + elapsed - if( f.timeElapsed < 0.25 ) then return end - f.timeElapsed = f.timeElapsed - 0.25 - - Stagger:Update(f.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_STATES.YELLOW.threshold ) then - state = "STAGGER_GREEN" - elseif( percent < STAGGER_STATES.RED.threshold ) 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 +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(f, elapsed) + f.timeElapsed = f.timeElapsed + elapsed + if( f.timeElapsed < 0.25 ) then return end + f.timeElapsed = f.timeElapsed - 0.25 + + Stagger:Update(f.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 diff --git a/modules/movers.lua b/modules/movers.lua index f45333f94..1f3546cfb 100755 --- a/modules/movers.lua +++ b/modules/movers.lua @@ -1,556 +1,570 @@ --- I am undecided if this is a brilliant idea or an insane one -local L = ShadowUF.L -local Movers = {} -local originalEnvs = {} -local unitConfig = {} -local attributeBlacklist = {["showplayer"] = true, ["showraid"] = true, ["showparty"] = true, ["showsolo"] = true, ["initial-unitwatch"] = true} -local playerClass = select(2, UnitClass("player")) -local noop = function() end -local OnDragStop, OnDragStart, configEnv -ShadowUF:RegisterModule(Movers, "movers") - --- This is the fun part, the env to fake units and make them show up as examples -local function getValue(func, unit, value) - unit = string.gsub(unit, "(%d+)", "") - if( unitConfig[func .. unit] == nil ) then unitConfig[func .. unit] = value end - return unitConfig[func .. unit] -end - -local function createConfigEnv() - if( configEnv ) then return end - configEnv = setmetatable({ - 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, - UnitInRaid = function() return true end, - UnitInParty = function() return true end, - UnitIsUnit = function(unitA, unitB) return unitB == "player" and true or false end, - UnitIsDeadOrGhost = function(unit) return false end, - UnitIsConnected = function(unit) return true end, - UnitLevel = function(unit) return GetMaxLevelForPlayerExpansion() 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, powerType) - if( powerType == Enum.PowerType.HolyPower or powerType == Enum.PowerType.SoulShards or powerType == Enum.PowerType.Essence ) 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 or powerType == Enum.PowerType.Essence ) 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, - UnitPhaseReason = function(unit) return nil end, - UnitExists = function(unit) 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, - UnitFactionGroup = function(unit) return _G.UnitFactionGroup("player") end, - UnitAffectingCombat = function() return true end, - UnitThreatSituation = function() return 0 end, - UnitDetailedThreatSituation = function() return nil end, - UnitCastingInfo = function(unit) - -- 1 -> 10: spell, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID - local data = unitConfig["UnitCastingInfo" .. unit] or {} - if( not data[5] or GetTime() < data[5] ) then - data[1] = L["Test spell"] - 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 - - return unpack(data) - end, - UnitIsFriend = function(unit) return unit ~= "target" and unit ~= ShadowUF.fakeUnits[unit] and unit ~= "arena" end, - GetReadyCheckStatus = function(unit) - local status = getValue("GetReadyCheckStatus", unit, math.random(1, 3)) - return status == 1 and "ready" or status == 2 and "notready" or "waiting" - end, - GetPartyAssignment = function(type, unit) - local assignment = getValue("GetPartyAssignment", unit, math.random(1, 2) == 1 and "MAINTANK" or "MAINASSIST") - return assignment == type - end, - UnitGroupRolesAssigned = function(unit) - local role = getValue("UnitGroupRolesAssigned", unit, math.random(1, 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) - powerType = getValue("UnitPowerType", unit, powerType == 4 and 6 or powerType) - - 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 - - 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"], texture, id, auraType, 0, 0, "player", id % 6 == 0 - end, - UnitName = function(unit) - local unitID = string.match(unit, "(%d+)") - if( unitID ) then - return string.format("%s #%d", L.units[string.gsub(unit, "(%d+)", "")] or unit, unitID) - end - - return L.units[unit] - end, - UnitClass = function(unit) - local classToken = getValue("UnitClass", unit, CLASS_SORT_ORDER[math.random(1, #(CLASS_SORT_ORDER))]) - return LOCALIZED_CLASS_NAMES_MALE[classToken], classToken - end, - }, { - __index = _G, - __newindex = function(tbl, key, value) _G[key] = value end, - }) -end - --- Child units have to manually be added to the list to make sure they function properly -local function prepareChildUnits(header, ...) - for i=1, select("#", ...) do - local frame = select(i, ...) - 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.unitMappedType .. "Units"][frame.configUnitID]) - end - end -end - -local function OnEnter(self) - local tooltip = self.tooltipText or self.unitID and string.format("%s #%d", L.units[self.unitType], self.unitID) or L.units[self.unit] or self.unit - local additionalText = ShadowUF.Units.childUnits[self.unitType] and L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] - - GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT") - GameTooltip:SetText(tooltip, 1, 0.81, 0, 1, true) - if( additionalText ) then GameTooltip:AddLine(additionalText, 0.90, 0.90, 0.90, 1) end - GameTooltip:Show() -end - -local function OnLeave(self) - GameTooltip:Hide() -end - -local function setupUnits(childrenOnly) - for frame in pairs(ShadowUF.Units.frameList) do - if( frame.configMode ) then - -- Units visible, but it's not supposed to be - if( frame:IsVisible() and not ShadowUF.db.profile.units[frame.unitType].enabled ) then - RegisterUnitWatch(frame, frame.hasStateWatch) - if( not UnitExists(frame.unit) ) then frame:Hide() end - - -- 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.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.OnEnter = OnEnter - frame.OnLeave = OnLeave - frame:SetScript("OnEvent", nil) - frame:SetScript("OnUpdate", nil) - frame:RegisterForDrag("LeftButton") - frame.configMode = true - frame.unitOwner = nil - frame.originalMenu = frame.menu - frame.menu = nil - - local unit - if( frame.isChildUnit ) then - local unitFormat = string.gsub(string.gsub(frame.unitType, "target$", "%%dtarget"), "pet$", "pet%%d") - unit = string.format(unitFormat, frame.parent.configUnitID or "") - else - unit = frame.unitType .. (frame.configUnitID or "") - end - - ShadowUF.Units.OnAttributeChanged(frame, "unit", unit) - - if( frame.healthBar ) then frame.healthBar:SetScript("OnUpdate", nil) end - if( frame.powerBar ) then frame.powerBar:SetScript("OnUpdate", nil) end - if( frame.indicators ) then frame.indicators:SetScript("OnUpdate", nil) end - - UnregisterUnitWatch(frame) - frame:FullUpdate() - frame:Show() - end - end -end - -function Movers:Enable() - createConfigEnv() - - -- Force create zone headers - for type, zone in pairs(ShadowUF.Units.zoneUnits) do - if( ShadowUF.db.profile.units[type].enabled ) then - ShadowUF.Units:InitializeFrame(type) - end - end - - -- Setup the headers - for _, header in pairs(ShadowUF.Units.headerFrames) do - for key in pairs(attributeBlacklist) do - header:SetAttribute(key, nil) - end - - local config = ShadowUF.db.profile.units[header.unitType] - if( config.frameSplit ) then - header:SetAttribute("startingIndex", -4) - elseif( config.maxColumns ) then - local maxUnits = MAX_RAID_MEMBERS - if( config.filters ) then - for _, enabled in pairs(config.filters) do - if( not enabled ) then - maxUnits = maxUnits - 5 - end - end - end - - header:SetAttribute("startingIndex", -math.min(config.maxColumns * config.unitsPerColumn, maxUnits) + 1) - elseif( ShadowUF[header.unitType .. "Units"] ) then - header:SetAttribute("startingIndex", -#(ShadowUF[header.unitType .. "Units"]) + 1) - end - - header.startingIndex = header:GetAttribute("startingIndex") - header:SetMovable(true) - prepareChildUnits(header, header:GetChildren()) - end - - -- Setup the test env - if( not self.isEnabled ) then - for _, func in pairs(ShadowUF.tagFunc) do - if( type(func) == "function" ) then - originalEnvs[func] = getfenv(func) - setfenv(func, configEnv) - end - end - - for _, module in pairs(ShadowUF.modules) do - if( module.moduleName ) then - for key, func in pairs(module) do - if( type(func) == "function" ) then - originalEnvs[module[key]] = getfenv(module[key]) - setfenv(module[key], configEnv) - end - end - end - end - end - - -- Why is this called twice you ask? Child units are created on the OnAttributeChanged call - -- 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() - self.infoFrame:Show() - elseif( self.infoFrame ) then - self.infoFrame:Hide() - end - - self.isEnabled = true -end - -function Movers:Disable() - if( not self.isEnabled ) then return nil end - - for func, env in pairs(originalEnvs) do - setfenv(func, env) - originalEnvs[func] = nil - end - - for frame in pairs(ShadowUF.Units.frameList) do - if( frame.configMode ) then - if( frame.isMoving ) then - frame:GetScript("OnDragStop")(frame) - end - - frame.configMode = nil - frame.unitOwner = nil - frame.unit = nil - frame.configUnitID = nil - frame.menu = frame.originalMenu - frame.originalMenu = nil - frame.Hide = frame.originalHide - frame:SetAttribute("unit", frame.originalUnit) - frame:SetScript("OnDragStop", nil) - frame:SetScript("OnDragStart", nil) - frame:SetScript("OnEvent", frame:IsVisible() and ShadowUF.Units.OnEvent or nil) - frame:SetScript("OnUpdate", frame.originalOnUpdate) - frame.OnEnter = frame.originalOnEnter - frame.OnLeave = frame.originalOnLeave - frame:SetMovable(false) - frame:RegisterForDrag() - - if( frame.isChildUnit ) then - ShadowUF.Units.OnAttributeChanged(frame, "unit", SecureButton_GetModifiedUnit(frame)) - end - - - RegisterUnitWatch(frame, frame.hasStateWatch) - if( not UnitExists(frame.unit) ) then frame:Hide() end - end - end - - for type, header in pairs(ShadowUF.Units.headerFrames) do - header:SetMovable(false) - header:SetAttribute("startingIndex", 1) - header:SetAttribute("initial-unitWatch", true) - - if( header.unitType == type or type == "raidParent" ) then - ShadowUF.Units:ReloadHeader(header.unitType) - end - end - - 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 - - self.isConfigModeSpec = nil - self.isEnabled = nil -end - -OnDragStart = function(self) - if( not self:IsMovable() ) then return end - - if( self.unitType == "raid" and ShadowUF.Units.headerFrames.raidParent and ShadowUF.Units.headerFrames.raidParent:IsVisible() ) then - self = ShadowUF.Units.headerFrames.raidParent - else - self = ShadowUF.Units.headerFrames[self.unitType] or ShadowUF.Units.unitFrames[self.unitType] - end - - self.isMoving = true - self:StartMoving() -end - -OnDragStop = function(self) - if( not self:IsMovable() ) then return end - if( self.unitType == "raid" and ShadowUF.Units.headerFrames.raidParent and ShadowUF.Units.headerFrames.raidParent:IsVisible() ) then - self = ShadowUF.Units.headerFrames.raidParent - else - self = ShadowUF.Units.headerFrames[self.unitType] or ShadowUF.Units.unitFrames[self.unitType] - end - - self.isMoving = nil - self:StopMovingOrSizing() - - -- When dragging the frame around, Blizzard changes the anchoring based on the closet portion of the screen - -- When a widget is near the top left it uses top left, near the left it uses left and so on, which messes up positioning for header frames - local scale = (self:GetScale() * UIParent:GetScale()) or 1 - local position = ShadowUF.db.profile.positions[self.unitType] - local point, _, relativePoint, x, y = self:GetPoint() - - -- Figure out the horizontal anchor - if( self.isHeaderFrame ) then - if( ShadowUF.db.profile.units[self.unitType].attribAnchorPoint == "RIGHT" ) then - x = self:GetRight() - point = "RIGHT" - else - x = self:GetLeft() - point = "LEFT" - end - - if( ShadowUF.db.profile.units[self.unitType].attribPoint == "BOTTOM" ) then - y = self:GetBottom() - point = "BOTTOM" .. point - else - y = self:GetTop() - point = "TOP" .. point - end - - relativePoint = "BOTTOMLEFT" - position.bottom = self:GetBottom() * scale - position.top = self:GetTop() * scale - end - - position.anchorTo = "UIParent" - position.movedAnchor = nil - position.anchorPoint = "" - position.point = point - position.relativePoint = relativePoint - position.x = x * scale - position.y = y * scale - - ShadowUF.Layout:AnchorFrame(UIParent, self, ShadowUF.db.profile.positions[self.unitType]) - - -- Unlock the parent frame from the mover now too - if( self.parent ) then - ShadowUF.Layout:AnchorFrame(UIParent, self.parent, ShadowUF.db.profile.positions[self.parent.unitType]) - end - - -- Notify the configuration it can update itself now - local ACR = LibStub("AceConfigRegistry-3.0", true) - if( ACR ) then - ACR:NotifyChange("ShadowedUF") - end -end - -function Movers:Update() - if( not ShadowUF.db.profile.locked ) then - self:Enable() - elseif( ShadowUF.db.profile.locked ) then - self:Disable() - end -end - -function Movers:CreateInfoFrame() - if( self.infoFrame ) then return end - - -- Show an info frame that users can lock the frames through - local frame = CreateFrame("Frame", nil, UIParent, BackdropTemplateMixin and "BackdropTemplate" or nil) - frame:SetClampedToScreen(true) - frame:SetWidth(300) - frame:SetHeight(115) - frame:RegisterForDrag("LeftButton") - frame:EnableMouse(true) - frame:SetMovable(true) - frame:RegisterEvent("PLAYER_REGEN_DISABLED") - frame:SetScript("OnEvent", function(f) - if( not ShadowUF.db.profile.locked and f:IsVisible() ) then - ShadowUF.db.profile.locked = true - Movers:Disable() - - 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("OnDragStart", function(f) - f:StartMoving() - end) - frame:SetScript("OnDragStop", function(f) - f:StopMovingOrSizing() - end) - 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, 225) - - 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", "GameFontHighlightSmall") - frame.text:SetText(L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."]) - frame.text:SetPoint("TOPLEFT", 12, -22) - frame.text:SetWidth(frame:GetWidth() - 20) - frame.text:SetJustifyH("LEFT") - - frame.lock = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate") - frame.lock:SetText(L["Lock frames"]) - frame.lock:SetHeight(20) - frame.lock:SetWidth(100) - frame.lock:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 6, 8) - frame.lock:SetScript("OnEnter", OnEnter) - frame.lock:SetScript("OnLeave", OnLeave) - frame.lock.tooltipText = L["Locks the unit frame positionings hiding the mover boxes."] - frame.lock:SetScript("OnClick", function() - ShadowUF.db.profile.locked = true - Movers:Update() - end) - - frame.unlink = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate") - frame.unlink:SetText(L["Unlink frames"]) - frame.unlink:SetHeight(20) - frame.unlink:SetWidth(100) - frame.unlink:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 8) - frame.unlink:SetScript("OnEnter", OnEnter) - frame.unlink:SetScript("OnLeave", OnLeave) - frame.unlink.tooltipText = L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] - frame.unlink:SetScript("OnClick", function() - for f in pairs(ShadowUF.Units.frameList) do - if( not ShadowUF.Units.childUnits[f.unitType] and f:GetScript("OnDragStart") and f:GetScript("OnDragStop") ) then - f:GetScript("OnDragStart")(f) - f:GetScript("OnDragStop")(f) - end - end - - Movers:Update() - end) - - self.infoFrame = frame -end +-- I am undecided if this is a brilliant idea or an insane one +local L = ShadowUF.L +local Movers = {} +local originalEnvs = {} +local unitConfig = {} +local attributeBlacklist = {["showplayer"] = true, ["showraid"] = true, ["showparty"] = true, ["showsolo"] = true, ["initial-unitwatch"] = true} +local playerClass = select(2, UnitClass("player")) +local noop = function() end +local OnDragStop, OnDragStart, configEnv +ShadowUF:RegisterModule(Movers, "movers") + +-- This is the fun part, the env to fake units and make them show up as examples +local function getValue(func, unit, value) + unit = string.gsub(unit, "(%d+)", "") + if( unitConfig[func .. unit] == nil ) then unitConfig[func .. unit] = value end + return unitConfig[func .. unit] +end + +local function createConfigEnv() + if( configEnv ) then return end + configEnv = setmetatable({ + 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, + UnitInRaid = function() return true end, + UnitInParty = function() return true end, + UnitIsUnit = function(unitA, unitB) return unitB == "player" and true or false end, + UnitIsDeadOrGhost = function(unit) return false end, + UnitIsConnected = function(unit) return true end, + UnitLevel = function(unit) return GetMaxPlayerLevel() 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, powerType) + if( powerType == Enum.PowerType.HolyPower or powerType == Enum.PowerType.SoulShards or powerType == Enum.PowerType.Essence or powerType == Enum.PowerType.ShadowOrbs ) then + return 3 + elseif( powerType == Enum.PowerType.Balance ) then + return getValue("UnitPower", unit, math.random(-100, 100)) + elseif( powerType == Enum.PowerType.Chi) then + return 4 + elseif( powerType == Enum.PowerType.ShadowOrbs ) then + return PRIEST_BAR_NUM_ORBS + elseif( powerType == Enum.PowerType.BurningEmbers ) then + return math.floor(MAX_POWER_PER_EMBER + (MAX_POWER_PER_EMBER / 2)) + elseif( powerType == Enum.PowerType.DemonicFury ) then + return 100 + 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.Maelstrom or powerType == Enum.PowerType.Insanity + or powerType == Enum.PowerType.Fury or powerType == Enum.PowerType.Pain or powerType == Enum.PowerType.Balance ) 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 or powerType == Enum.PowerType.Essence ) then + return 5 + elseif( powerType == Enum.PowerType.Runes ) then + return 6 + elseif( powerType == Enum.PowerType.ArcaneCharges ) then + return 4 + elseif( powerType == Enum.PowerType.ShadowOrbs ) then + return PRIEST_BAR_NUM_ORBS + elseif( powerType == Enum.PowerType.BurningEmbers ) then + return MAX_POWER_PER_EMBER * 3 + elseif( powerType == Enum.PowerType.DemonicFury ) then + return 100 + end + + return 50000 + end, + UnitHasIncomingResurrection = function(unit) return true end, + UnitInOtherParty = function(unit) return getValue("UnitInOtherParty", unit, math.random(0, 1) == 1) end, + UnitPhaseReason = function(unit) return nil end, + UnitExists = function(unit) 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, + UnitFactionGroup = function(unit) return _G.UnitFactionGroup("player") end, + UnitAffectingCombat = function() return true end, + UnitThreatSituation = function() return 0 end, + UnitDetailedThreatSituation = function() return nil end, + UnitCastingInfo = function(unit) + -- 1 -> 10: spell, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID + local data = unitConfig["UnitCastingInfo" .. unit] or {} + if( not data[5] or GetTime() < data[5] ) then + data[1] = L["Test spell"] + 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 + + return unpack(data) + end, + UnitIsFriend = function(unit) return unit ~= "target" and unit ~= ShadowUF.fakeUnits[unit] and unit ~= "arena" end, + GetReadyCheckStatus = function(unit) + local status = getValue("GetReadyCheckStatus", unit, math.random(1, 3)) + return status == 1 and "ready" or status == 2 and "notready" or "waiting" + end, + GetPartyAssignment = function(type, unit) + local assignment = getValue("GetPartyAssignment", unit, math.random(1, 2) == 1 and "MAINTANK" or "MAINASSIST") + return assignment == type + end, + UnitGroupRolesAssigned = function(unit) + local role = getValue("UnitGroupRolesAssigned", unit, math.random(1, 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) + powerType = getValue("UnitPowerType", unit, powerType == 4 and 6 or powerType) + + 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 + + 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"], texture, id, auraType, 0, 0, "player", id % 6 == 0 + end, + UnitName = function(unit) + local unitID = string.match(unit, "(%d+)") + if( unitID ) then + return string.format("%s #%d", L.units[string.gsub(unit, "(%d+)", "")] or unit, unitID) + end + + return L.units[unit] + end, + UnitClass = function(unit) + local classToken = getValue("UnitClass", unit, CLASS_SORT_ORDER[math.random(1, #(CLASS_SORT_ORDER))]) + return LOCALIZED_CLASS_NAMES_MALE[classToken], classToken + end, + }, { + __index = _G, + __newindex = function(tbl, key, value) _G[key] = value end, + }) +end + +-- Child units have to manually be added to the list to make sure they function properly +local function prepareChildUnits(header, ...) + for i=1, select("#", ...) do + local frame = select(i, ...) + 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.unitMappedType .. "Units"][frame.configUnitID]) + end + end +end + +local function OnEnter(self) + local tooltip = self.tooltipText or self.unitID and string.format("%s #%d", L.units[self.unitType], self.unitID) or L.units[self.unit] or self.unit + local additionalText = ShadowUF.Units.childUnits[self.unitType] and L["Child units cannot be dragged, you will have to reposition them through /shadowuf."] + + GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT") + GameTooltip:SetText(tooltip, 1, 0.81, 0, 1, true) + if( additionalText ) then GameTooltip:AddLine(additionalText, 0.90, 0.90, 0.90, 1) end + GameTooltip:Show() +end + +local function OnLeave(self) + GameTooltip:Hide() +end + +local function setupUnits(childrenOnly) + for frame in pairs(ShadowUF.Units.frameList) do + if( frame.configMode ) then + -- Units visible, but it's not supposed to be + if( frame:IsVisible() and not ShadowUF.db.profile.units[frame.unitType].enabled ) then + RegisterUnitWatch(frame, frame.hasStateWatch) + if( not UnitExists(frame.unit) ) then frame:Hide() end + + -- 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.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.OnEnter = OnEnter + frame.OnLeave = OnLeave + frame:SetScript("OnEvent", nil) + frame:SetScript("OnUpdate", nil) + frame:RegisterForDrag("LeftButton") + frame.configMode = true + frame.unitOwner = nil + frame.originalMenu = frame.menu + frame.menu = nil + + local unit + if( frame.isChildUnit ) then + local unitFormat = string.gsub(string.gsub(frame.unitType, "target$", "%%dtarget"), "pet$", "pet%%d") + unit = string.format(unitFormat, frame.parent.configUnitID or "") + else + unit = frame.unitType .. (frame.configUnitID or "") + end + + ShadowUF.Units.OnAttributeChanged(frame, "unit", unit) + + if( frame.healthBar ) then frame.healthBar:SetScript("OnUpdate", nil) end + if( frame.powerBar ) then frame.powerBar:SetScript("OnUpdate", nil) end + if( frame.indicators ) then frame.indicators:SetScript("OnUpdate", nil) end + + UnregisterUnitWatch(frame) + frame:FullUpdate() + frame:Show() + end + end +end + +function Movers:Enable() + createConfigEnv() + + -- Force create zone headers + for type, zone in pairs(ShadowUF.Units.zoneUnits) do + if( ShadowUF.db.profile.units[type].enabled ) then + ShadowUF.Units:InitializeFrame(type) + end + end + + -- Setup the headers + for _, header in pairs(ShadowUF.Units.headerFrames) do + for key in pairs(attributeBlacklist) do + header:SetAttribute(key, nil) + end + + local config = ShadowUF.db.profile.units[header.unitType] + if( config.frameSplit ) then + header:SetAttribute("startingIndex", -4) + elseif( config.maxColumns ) then + local maxUnits = MAX_RAID_MEMBERS + if( config.filters ) then + for _, enabled in pairs(config.filters) do + if( not enabled ) then + maxUnits = maxUnits - 5 + end + end + end + + header:SetAttribute("startingIndex", -math.min(config.maxColumns * config.unitsPerColumn, maxUnits) + 1) + elseif( ShadowUF[header.unitType .. "Units"] ) then + header:SetAttribute("startingIndex", -#(ShadowUF[header.unitType .. "Units"]) + 1) + end + + header.startingIndex = header:GetAttribute("startingIndex") + header:SetMovable(true) + prepareChildUnits(header, header:GetChildren()) + end + + -- Setup the test env + if( not self.isEnabled ) then + for _, func in pairs(ShadowUF.tagFunc) do + if( type(func) == "function" ) then + originalEnvs[func] = getfenv(func) + setfenv(func, configEnv) + end + end + + for _, module in pairs(ShadowUF.modules) do + if( module.moduleName ) then + for key, func in pairs(module) do + if( type(func) == "function" ) then + originalEnvs[module[key]] = getfenv(module[key]) + setfenv(module[key], configEnv) + end + end + end + end + end + + -- Why is this called twice you ask? Child units are created on the OnAttributeChanged call + -- 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() + self.infoFrame:Show() + elseif( self.infoFrame ) then + self.infoFrame:Hide() + end + + self.isEnabled = true +end + +function Movers:Disable() + if( not self.isEnabled ) then return nil end + + for func, env in pairs(originalEnvs) do + setfenv(func, env) + originalEnvs[func] = nil + end + + for frame in pairs(ShadowUF.Units.frameList) do + if( frame.configMode ) then + if( frame.isMoving ) then + frame:GetScript("OnDragStop")(frame) + end + + frame.configMode = nil + frame.unitOwner = nil + frame.unit = nil + frame.configUnitID = nil + frame.menu = frame.originalMenu + frame.originalMenu = nil + frame.Hide = frame.originalHide + frame:SetAttribute("unit", frame.originalUnit) + frame:SetScript("OnDragStop", nil) + frame:SetScript("OnDragStart", nil) + frame:SetScript("OnEvent", frame:IsVisible() and ShadowUF.Units.OnEvent or nil) + frame:SetScript("OnUpdate", frame.originalOnUpdate) + frame.OnEnter = frame.originalOnEnter + frame.OnLeave = frame.originalOnLeave + frame:SetMovable(false) + frame:RegisterForDrag() + + if( frame.isChildUnit ) then + ShadowUF.Units.OnAttributeChanged(frame, "unit", SecureButton_GetModifiedUnit(frame)) + end + + + RegisterUnitWatch(frame, frame.hasStateWatch) + if( not UnitExists(frame.unit) ) then frame:Hide() end + end + end + + for type, header in pairs(ShadowUF.Units.headerFrames) do + header:SetMovable(false) + header:SetAttribute("startingIndex", 1) + header:SetAttribute("initial-unitWatch", true) + + if( header.unitType == type or type == "raidParent" ) then + ShadowUF.Units:ReloadHeader(header.unitType) + end + end + + 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 + + self.isConfigModeSpec = nil + self.isEnabled = nil +end + +OnDragStart = function(self) + if( not self:IsMovable() ) then return end + + if( self.unitType == "raid" and ShadowUF.Units.headerFrames.raidParent and ShadowUF.Units.headerFrames.raidParent:IsVisible() ) then + self = ShadowUF.Units.headerFrames.raidParent + else + self = ShadowUF.Units.headerFrames[self.unitType] or ShadowUF.Units.unitFrames[self.unitType] + end + + self.isMoving = true + self:StartMoving() +end + +OnDragStop = function(self) + if( not self:IsMovable() ) then return end + if( self.unitType == "raid" and ShadowUF.Units.headerFrames.raidParent and ShadowUF.Units.headerFrames.raidParent:IsVisible() ) then + self = ShadowUF.Units.headerFrames.raidParent + else + self = ShadowUF.Units.headerFrames[self.unitType] or ShadowUF.Units.unitFrames[self.unitType] + end + + self.isMoving = nil + self:StopMovingOrSizing() + + -- When dragging the frame around, Blizzard changes the anchoring based on the closet portion of the screen + -- When a widget is near the top left it uses top left, near the left it uses left and so on, which messes up positioning for header frames + local scale = (self:GetScale() * UIParent:GetScale()) or 1 + local position = ShadowUF.db.profile.positions[self.unitType] + local point, _, relativePoint, x, y = self:GetPoint() + + -- Figure out the horizontal anchor + if( self.isHeaderFrame ) then + if( ShadowUF.db.profile.units[self.unitType].attribAnchorPoint == "RIGHT" ) then + x = self:GetRight() + point = "RIGHT" + else + x = self:GetLeft() + point = "LEFT" + end + + if( ShadowUF.db.profile.units[self.unitType].attribPoint == "BOTTOM" ) then + y = self:GetBottom() + point = "BOTTOM" .. point + else + y = self:GetTop() + point = "TOP" .. point + end + + relativePoint = "BOTTOMLEFT" + position.bottom = self:GetBottom() * scale + position.top = self:GetTop() * scale + end + + position.anchorTo = "UIParent" + position.movedAnchor = nil + position.anchorPoint = "" + position.point = point + position.relativePoint = relativePoint + position.x = x * scale + position.y = y * scale + + ShadowUF.Layout:AnchorFrame(UIParent, self, ShadowUF.db.profile.positions[self.unitType]) + + -- Unlock the parent frame from the mover now too + if( self.parent ) then + ShadowUF.Layout:AnchorFrame(UIParent, self.parent, ShadowUF.db.profile.positions[self.parent.unitType]) + end + + -- Notify the configuration it can update itself now + local ACR = LibStub("AceConfigRegistry-3.0", true) + if( ACR ) then + ACR:NotifyChange("ShadowedUF") + end +end + +function Movers:Update() + if( not ShadowUF.db.profile.locked ) then + self:Enable() + elseif( ShadowUF.db.profile.locked ) then + self:Disable() + end +end + +function Movers:CreateInfoFrame() + if( self.infoFrame ) then return end + + -- Show an info frame that users can lock the frames through + local frame = CreateFrame("Frame", nil, UIParent, BackdropTemplateMixin and "BackdropTemplate" or nil) + frame:SetClampedToScreen(true) + frame:SetWidth(300) + frame:SetHeight(115) + frame:RegisterForDrag("LeftButton") + frame:EnableMouse(true) + frame:SetMovable(true) + frame:RegisterEvent("PLAYER_REGEN_DISABLED") + frame:SetScript("OnEvent", function(f) + if( not ShadowUF.db.profile.locked and f:IsVisible() ) then + ShadowUF.db.profile.locked = true + Movers:Disable() + + 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("OnDragStart", function(f) + f:StartMoving() + end) + frame:SetScript("OnDragStop", function(f) + f:StopMovingOrSizing() + end) + 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, 225) + + 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", "GameFontHighlightSmall") + frame.text:SetText(L["The unit frames you see are examples, they are not perfect and do not show all the data they normally would.|n|nYou can hide them by locking them through /shadowuf or clicking the button below."]) + frame.text:SetPoint("TOPLEFT", 12, -22) + frame.text:SetWidth(frame:GetWidth() - 20) + frame.text:SetJustifyH("LEFT") + + frame.lock = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate") + frame.lock:SetText(L["Lock frames"]) + frame.lock:SetHeight(20) + frame.lock:SetWidth(100) + frame.lock:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 6, 8) + frame.lock:SetScript("OnEnter", OnEnter) + frame.lock:SetScript("OnLeave", OnLeave) + frame.lock.tooltipText = L["Locks the unit frame positionings hiding the mover boxes."] + frame.lock:SetScript("OnClick", function() + ShadowUF.db.profile.locked = true + Movers:Update() + end) + + frame.unlink = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate") + frame.unlink:SetText(L["Unlink frames"]) + frame.unlink:SetHeight(20) + frame.unlink:SetWidth(100) + frame.unlink:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 8) + frame.unlink:SetScript("OnEnter", OnEnter) + frame.unlink:SetScript("OnLeave", OnLeave) + frame.unlink.tooltipText = L["WARNING: This will unlink all frames from each other so you can move them without another frame moving with it."] + frame.unlink:SetScript("OnClick", function() + for f in pairs(ShadowUF.Units.frameList) do + if( not ShadowUF.Units.childUnits[f.unitType] and f:GetScript("OnDragStart") and f:GetScript("OnDragStop") ) then + f:GetScript("OnDragStart")(f) + f:GetScript("OnDragStop")(f) + end + end + + Movers:Update() + end) + + self.infoFrame = frame +end diff --git a/modules/portrait.lua b/modules/portrait.lua index 9582e52c8..7033c4341 100755 --- a/modules/portrait.lua +++ b/modules/portrait.lua @@ -1,100 +1,100 @@ -local Portrait = {} -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:SetPortraitZoom(1) -end - -local function resetGUID(self) - self.guid = nil -end - -function Portrait:OnEnable(frame) - frame:RegisterUnitEvent("UNIT_PORTRAIT_UPDATE", self, "UpdateFunc") - frame:RegisterUnitEvent("UNIT_MODEL_CHANGED", self, "Update") - - frame:RegisterUpdateFunc(self, "UpdateFunc") -end - -function Portrait:OnDisable(frame) - frame:UnregisterAll(self) -end - -function Portrait:OnPreLayoutApply(frame, config) - if( not frame.visibility.portrait ) then return end - - if( config.portrait.type == "3D" ) then - if( not frame.portraitModel ) then - frame.portraitModel = CreateFrame("PlayerModel", nil, frame) - frame.portraitModel:SetScript("OnShow", resetCamera) - frame.portraitModel:SetScript("OnHide", resetGUID) - frame.portraitModel.parent = frame - end - - frame.portrait = frame.portraitModel - frame.portrait:Show() - - ShadowUF.Layout:ToggleVisibility(frame.portraitTexture, false) - else - frame.portraitTexture = frame.portraitTexture or frame:CreateTexture(nil, "ARTWORK") - frame.portrait = frame.portraitTexture - frame.portrait:Show() - - ShadowUF.Layout:ToggleVisibility(frame.portraitModel, false) - end -end - -function Portrait:UpdateFunc(frame) - -- Portrait models can't be updated unless the GUID changed or else you have the animation jumping around - if( ShadowUF.db.profile.units[frame.unitType].portrait.type == "3D" ) then - local guid = UnitGUID(frame.unitOwner) - if( frame.portrait.guid ~= guid ) then - self:Update(frame) - end - - frame.portrait.guid = guid - else - self:Update(frame) - end -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 = frame:UnitClassToken() - if( classToken ) then - local classIconAtlas = GetClassAtlas(classToken) - if( classIconAtlas ) then - frame.portrait:SetAtlas(classIconAtlas) - else - frame.portrait:SetTexture("") - end - else - frame.portrait:SetTexture("") - end - -- Use 2D character image - 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 question mark - elseif( not UnitIsVisible(frame.unitOwner) or not UnitIsConnected(frame.unitOwner) ) then - 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:SetPortraitZoom(1) - frame.portrait:SetPosition(0, 0, 0) - frame.portrait:Show() - end -end - - - - +local Portrait = {} +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:SetPortraitZoom(1) +end + +local function resetGUID(self) + self.guid = nil +end + +function Portrait:OnEnable(frame) + frame:RegisterUnitEvent("UNIT_PORTRAIT_UPDATE", self, "UpdateFunc") + frame:RegisterUnitEvent("UNIT_MODEL_CHANGED", self, "Update") + + frame:RegisterUpdateFunc(self, "UpdateFunc") +end + +function Portrait:OnDisable(frame) + frame:UnregisterAll(self) +end + +function Portrait:OnPreLayoutApply(frame, config) + if( not frame.visibility.portrait ) then return end + + if( config.portrait.type == "3D" ) then + if( not frame.portraitModel ) then + frame.portraitModel = CreateFrame("PlayerModel", nil, frame) + frame.portraitModel:SetScript("OnShow", resetCamera) + frame.portraitModel:SetScript("OnHide", resetGUID) + frame.portraitModel.parent = frame + end + + frame.portrait = frame.portraitModel + frame.portrait:Show() + + ShadowUF.Layout:ToggleVisibility(frame.portraitTexture, false) + else + frame.portraitTexture = frame.portraitTexture or frame:CreateTexture(nil, "ARTWORK") + frame.portrait = frame.portraitTexture + frame.portrait:Show() + + ShadowUF.Layout:ToggleVisibility(frame.portraitModel, false) + end +end + +function Portrait:UpdateFunc(frame) + -- Portrait models can't be updated unless the GUID changed or else you have the animation jumping around + if( ShadowUF.db.profile.units[frame.unitType].portrait.type == "3D" ) then + local guid = UnitGUID(frame.unitOwner) + if( frame.portrait.guid ~= guid ) then + self:Update(frame) + end + + frame.portrait.guid = guid + else + self:Update(frame) + end +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 = frame:UnitClassToken() + if( classToken ) then + local classIconAtlas = GetClassAtlas(classToken) + if( classIconAtlas ) then + frame.portrait:SetAtlas(classIconAtlas) + else + frame.portrait:SetTexture("") + end + else + frame.portrait:SetTexture("") + end + -- Use 2D character image + 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 question mark + elseif( not UnitIsVisible(frame.unitOwner) or not UnitIsConnected(frame.unitOwner) ) then + 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:SetPortraitZoom(1) + frame.portrait:SetPosition(0, 0, 0) + frame.portrait:Show() + end +end + + + + diff --git a/modules/power.lua b/modules/power.lua index 74e9339ec..23ce09b2a 100755 --- a/modules/power.lua +++ b/modules/power.lua @@ -1,102 +1,102 @@ -local Power = {} -local powerMap = ShadowUF.Tags.powerMap -ShadowUF:RegisterModule(Power, "powerBar", ShadowUF.L["Power bar"], true) - -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") - - -- run an update after returning to life - if ( frame.unit == "player" ) then - frame:RegisterNormalEvent("PLAYER_UNGHOST", self, "Update") - end - - -- UNIT_MANA fires after repopping at a spirit healer, make sure to update powers then - frame:RegisterUnitEvent("UNIT_MANA", self, "Update") - - frame:RegisterUpdateFunc(self, "UpdateClassification") - frame:RegisterUpdateFunc(self, "UpdateColor") - frame:RegisterUpdateFunc(self, "Update") -end - -function Power:OnDisable(frame) - frame:UnregisterAll(self) -end - -local altColor = {} -function Power:UpdateColor(frame) - 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 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 - end - - 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, 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 +local Power = {} +local powerMap = ShadowUF.Tags.powerMap +ShadowUF:RegisterModule(Power, "powerBar", ShadowUF.L["Power bar"], true) + +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") + + -- run an update after returning to life + if ( frame.unit == "player" ) then + frame:RegisterNormalEvent("PLAYER_UNGHOST", self, "Update") + end + + -- UNIT_MANA fires after repopping at a spirit healer, make sure to update powers then + frame:RegisterUnitEvent("UNIT_MANA", self, "Update") + + frame:RegisterUpdateFunc(self, "UpdateClassification") + frame:RegisterUpdateFunc(self, "UpdateColor") + frame:RegisterUpdateFunc(self, "Update") +end + +function Power:OnDisable(frame) + frame:UnregisterAll(self) +end + +local altColor = {} +function Power:UpdateColor(frame) + 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 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 + end + + 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, 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 diff --git a/modules/priest.lua b/modules/priest.lua index 038ea2641..7e0a0c3e1 100644 --- a/modules/priest.lua +++ b/modules/priest.lua @@ -1,39 +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) ~= Enum.PowerType.Mana 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 +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) ~= Enum.PowerType.Mana 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 b00b8f6e2..b3c04fe1a 100755 --- a/modules/range.lua +++ b/modules/range.lua @@ -1,164 +1,155 @@ -local GetSpellName = C_Spell.GetSpellName -local IsSpellUsable = C_Spell.IsSpellUsable -local Range = { - friendly = { - ["PRIEST"] = { - (GetSpellName(17)), -- Power Word: Shield - (GetSpellName(527)), -- Purify - }, - ["DRUID"] = { - (GetSpellName(774)), -- Rejuvenation - (GetSpellName(2782)), -- Remove Corruption - }, - ["PALADIN"] = GetSpellName(19750), -- Flash of Light - ["SHAMAN"] = GetSpellName(8004), -- Healing Surge - ["WARLOCK"] = GetSpellName(5697), -- Unending Breath - --["DEATHKNIGHT"] = GetSpellName(47541), -- Death Coil - ["MONK"] = GetSpellName(115450), -- Detox - }, - hostile = { - ["DEATHKNIGHT"] = { - (GetSpellName(47541)), -- Death Coil - (GetSpellName(49576)), -- Death Grip - }, - ["DEMONHUNTER"] = GetSpellName(185123), -- Throw Glaive - ["DRUID"] = GetSpellName(8921), -- Moonfire - ["HUNTER"] = { - (GetSpellName(193455)), -- Cobra Shot - (GetSpellName(19434)), -- Aimed Short - (GetSpellName(193265)), -- Hatchet Toss - }, - ["MAGE"] = { - (GetSpellName(116)), -- Frostbolt - (GetSpellName(30451)), -- Arcane Blast - (GetSpellName(133)), -- Fireball - }, - ["MONK"] = GetSpellName(115546), -- Provoke - ["PALADIN"] = GetSpellName(62124), -- Hand of Reckoning - ["PRIEST"] = GetSpellName(585), -- Smite - --["ROGUE"] = GetSpellName(1725), -- Distract - ["SHAMAN"] = GetSpellName(188196), -- Lightning Bolt - ["WARLOCK"] = GetSpellName(686), -- Shadow Bolt - ["WARRIOR"] = GetSpellName(355), -- Taunt - }, -} - -ShadowUF:RegisterModule(Range, "range", ShadowUF.L["Range indicator"]) - -local LSR = LibStub("SpellRange-1.0") - -local playerClass = select(2, UnitClass("player")) -local rangeSpells = {} - -local UnitPhaseReason_o = UnitPhaseReason -local UnitPhaseReason = function(unit) - local phase = UnitPhaseReason_o(unit) - if (phase == Enum.PhaseReason.WarMode or phase == Enum.PhaseReason.ChromieTime) and UnitIsVisible(unit) then - return nil - end - return phase -end - -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 UnitPhaseReason(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( 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, just show in range :( - else - frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.inAlpha) - end -end - -local function updateSpellCache(category) - rangeSpells[category] = nil - if( ShadowUF.db.profile.range[category .. playerClass] and IsSpellUsable(ShadowUF.db.profile.range[category .. playerClass]) ) then - rangeSpells[category] = ShadowUF.db.profile.range[category .. playerClass] - - elseif( ShadowUF.db.profile.range[category .. "Alt" .. playerClass] and IsSpellUsable(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( spell and IsSpellUsable(spell) ) then - rangeSpells[category] = spell - break - end - end - elseif( Range[category][playerClass] and IsSpellUsable(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) - 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) - end - - frame:RegisterNormalEvent("PLAYER_SPECIALIZATION_CHANGED", self, "SpellChecks") - frame:RegisterUpdateFunc(self, "ForceUpdate") - - createTimer(frame) -end - -function Range:OnLayoutApplied(frame) - self:SpellChecks(frame) -end - -function Range:OnDisable(frame) - frame:UnregisterAll(self) - - if( frame.range ) then - cancelTimer(frame) - frame:SetRangeAlpha(1.0) - end -end - - -function Range:SpellChecks(frame) - updateSpellCache("friendly") - updateSpellCache("hostile") - if( frame.range and ShadowUF.db.profile.units[frame.unitType].range.enabled ) then - self:ForceUpdate(frame) - end -end +local GetSpellName = C_Spell.GetSpellName +local IsSpellUsable = C_Spell.IsSpellUsable +local Range = { + friendly = { + ["PRIEST"] = { + (GetSpellName(17)), -- Power Word: Shield + (GetSpellName(527)), -- Purify + }, + ["DRUID"] = { + (GetSpellName(774)), -- Rejuvenation + (GetSpellName(2782)), -- Remove Corruption + }, + ["PALADIN"] = GetSpellName(19750), -- Flash of Light + ["SHAMAN"] = GetSpellName(8004), -- Healing Surge + ["WARLOCK"] = GetSpellName(5697), -- Unending Breath + ["DEATHKNIGHT"] = GetSpellName(47541), -- Death Coil + ["MONK"] = GetSpellName(115450), -- Detox + }, + hostile = { + ["DEATHKNIGHT"] = { + (GetSpellName(47541)), -- Death Coil + (GetSpellName(49576)), -- Death Grip + }, + ["DEMONHUNTER"] = GetSpellName(185123), -- Throw Glaive + ["DRUID"] = GetSpellName(8921), -- Moonfire + ["HUNTER"] = { + (GetSpellName(193455)), -- Cobra Shot + (GetSpellName(19434)), -- Aimed Short + (GetSpellName(193265)), -- Hatchet Toss + }, + ["MAGE"] = { + (GetSpellName(116)), -- Frostbolt + (GetSpellName(30451)), -- Arcane Blast + (GetSpellName(133)), -- Fireball + }, + ["MONK"] = GetSpellName(115546), -- Provoke + ["PALADIN"] = GetSpellName(62124), -- Hand of Reckoning + ["PRIEST"] = GetSpellName(585), -- Smite + --["ROGUE"] = GetSpellName(1725), -- Distract + ["SHAMAN"] = GetSpellName(188196), -- Lightning Bolt + ["WARLOCK"] = GetSpellName(686), -- Shadow Bolt + ["WARRIOR"] = GetSpellName(355), -- Taunt + }, +} + +ShadowUF:RegisterModule(Range, "range", ShadowUF.L["Range indicator"]) + +local LSR = LibStub("SpellRange-1.0") + +local playerClass = select(2, UnitClass("player")) +local rangeSpells = {} + +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( 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 :( + else + frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.inAlpha) + 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) + 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) + end + + frame:RegisterNormalEvent("CHARACTER_POINTS_CHANGED", self, "SpellChecks") + frame:RegisterUpdateFunc(self, "ForceUpdate") + + createTimer(frame) +end + +function Range:OnLayoutApplied(frame) + self:SpellChecks(frame) +end + +function Range:OnDisable(frame) + frame:UnregisterAll(self) + + if( frame.range ) then + cancelTimer(frame) + frame:SetRangeAlpha(1.0) + 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 c3eb4bdb1..deac5757a 100755 --- a/modules/runes.lua +++ b/modules/runes.lua @@ -1,102 +1,124 @@ -local Runes = {} -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 - frame.runeBar = CreateFrame("StatusBar", nil, 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.runeBar) - rune.id = id - - if( id > 1 ) then - rune:SetPoint("TOPLEFT", frame.runeBar.runes[id-1], "TOPRIGHT", 1, 0) - else - rune:SetPoint("TOPLEFT", frame.runeBar, "TOPLEFT", 0, 0) - end - - frame.runeBar.runes[id] = rune - end - end - - frame:RegisterNormalEvent("RUNE_POWER_UPDATE", self, "UpdateUsable") - frame:RegisterUpdateFunc(self, "UpdateUsable") -end - -function Runes:OnDisable(frame) - frame:UnregisterAll(self) -end - -function Runes:OnLayoutApplied(frame) - 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 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 = startTime + cooldown - rune:SetMinMaxValues(startTime, rune.endTime) - rune:SetValue(GetTime()) - rune:SetAlpha(0.40) - rune:SetScript("OnUpdate", runeMonitor) - else - rune:SetMinMaxValues(0, 1) - rune:SetValue(1) - rune:SetAlpha(1.0) - rune:SetScript("OnUpdate", nil) - rune.endTime = nil - end - - if( rune.fontString ) then - rune.fontString:UpdateTags() - end -end +local Runes = {} +local RUNE_MAP = {[1] = 1, [2] = 2, [3] = 5, [4] = 6, [5] = 3, [6] = 4} +local runeColors = {{r = 0.95, g = 0.0, b = 0.08}, {r = 0.0, g = 0.85, b = 1.0}, {r = 0.0, g = 1.0, b = 0.35}, {r = 0.69, g = 0.15, b = 1.0}} +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 + frame.runeBar = CreateFrame("StatusBar", nil, 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.runeBar) + rune.id = id + + if( id > 1 ) then + rune:SetPoint("TOPLEFT", frame.runeBar.runes[RUNE_MAP[id - 1]], "TOPRIGHT", 1, 0) + else + rune:SetPoint("TOPLEFT", frame.runeBar, "TOPLEFT", 0, 0) + end + + frame.runeBar.runes[RUNE_MAP[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 + +function Runes:OnDisable(frame) + frame:UnregisterAll(self) +end + +function Runes:OnLayoutApplied(frame) + 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) + 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 + return + end + + local rune = frame.runeBar.runes[id] + local startTime, cooldown, cooled = GetRuneCooldown(id) + if( not cooled ) then + rune.endTime = startTime + cooldown + rune:SetMinMaxValues(startTime, rune.endTime) + rune:SetValue(GetTime()) + rune:SetAlpha(0.40) + rune:SetScript("OnUpdate", runeMonitor) + else + rune:SetMinMaxValues(0, 1) + rune:SetValue(1) + rune:SetAlpha(1.0) + rune:SetScript("OnUpdate", nil) + rune.endTime = nil + end + + if( rune.fontString ) then + rune.fontString:UpdateTags() + end +end + +function Runes:UpdateColors(frame) + for id, rune in pairs(frame.runeBar.runes) do + local colorType = GetRuneType(id) + if( frame.runeBar.runes[id].colorType ~= colorType ) then + local color = runeColors[colorType] + frame:SetBlockColor(frame.runeBar.runes[id], "runeBar", color.r, color.g, color.b) + 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( not id ) then return end + + local colorType = GetRuneType(id) + if( frame.runeBar.runes[id].colorType ~= colorType ) then + local color = runeColors[colorType] + frame:SetBlockColor(frame.runeBar.runes[id], "runeBar", color.r, color.g, color.b) + end +end diff --git a/modules/shadoworbs.lua b/modules/shadoworbs.lua new file mode 100644 index 000000000..492d0f3b0 --- /dev/null +++ b/modules/shadoworbs.lua @@ -0,0 +1,32 @@ +if( not ShadowUF.ComboPoints ) then return end +local ShadowOrbs = setmetatable({}, {__index = ShadowUF.ComboPoints}) +ShadowUF:RegisterModule(ShadowOrbs, "shadowOrbs", ShadowUF.L["Shadow Orbs"], nil, "PRIEST", SPEC_PRIEST_SHADOW, SHADOW_ORBS_SHOW_LEVEL) +local shadowConfig = {max = 3, key = "shadowOrbs", colorKey = "SHADOWORBS", powerType = Enum.PowerType.ShadowOrbs, eventType = "SHADOW_ORBS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\shard"} + +function ShadowOrbs:OnEnable(frame) + frame.shadowOrbs = frame.shadowOrbs or CreateFrame("Frame", nil, frame) + frame.shadowOrbs.cpConfig = shadowConfig + frame.comboPointType = shadowConfig.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") + + shadowConfig.max = UnitPowerMax("player", shadowConfig.powerType) +end + +function ShadowOrbs:OnLayoutApplied(frame, config) + ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config) + self:UpdateBarBlocks(frame) +end + + function ShadowOrbs:GetComboPointType() + return "shadowOrbs" + end + +function ShadowOrbs:GetPoints(unit) + return UnitPower("player", shadowConfig.powerType) +end diff --git a/modules/shaman.lua b/modules/shaman.lua index f2b5071f9..d4171a6dd 100644 --- a/modules/shaman.lua +++ b/modules/shaman.lua @@ -1,39 +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) ~= Enum.PowerType.Mana 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 +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) ~= Enum.PowerType.Mana 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 index 8561f8056..7db176068 100755 --- a/modules/soulshards.lua +++ b/modules/soulshards.lua @@ -1,47 +1,48 @@ -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 +if( not ShadowUF.ComboPoints ) then return end +--if select(4, GetBuildInfo()) < 50500 then return end + +local Souls = setmetatable({}, {__index = ShadowUF.ComboPoints}) +ShadowUF:RegisterModule(Souls, "soulShards", ShadowUF.L["Soul Shards"], nil, "WARLOCK", SPEC_WARLOCK_AFFLICTION) +local soulsConfig = {max = 4, 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.comboPointType = soulsConfig.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") + + + soulsConfig.max = UnitPowerMax("player", soulsConfig.powerType) + +end + +function Souls:OnLayoutApplied(frame, config) + ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config) + self:UpdateBarBlocks(frame) +end + + function Souls:GetComboPointType() + return "soulShards" + end + +function Souls:GetPoints(unit) + return UnitPower("player", soulsConfig.powerType) + + + + + + + + + + + + +end diff --git a/modules/tags.lua b/modules/tags.lua index a6fed25ff..463d25ad2 100755 --- a/modules/tags.lua +++ b/modules/tags.lua @@ -1,1621 +1,1685 @@ -local GetSpellName = C_Spell.GetSpellName - -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 ) - -- was breaking the logic and stripping the entire tag, this is a quick fix to stop that. - local tagKey = select(2, string.match(tag, "(%b())([%w%p]+)(%b())")) - if( not tagKey ) then tagKey = select(2, string.match(tag, "(%b())([%w%p]+)")) end - if( not tagKey ) then tagKey = string.match(tag, "([%w%p]+)(%b())") end - - tag = tagKey or tag - - 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 - -- 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 - 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 - - -- 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 - table.wipe(functionPool) - table.wipe(ShadowUF.tagFunc) - table.wipe(tagPool) - - -- Now update frames - for fontString, tags in pairs(regFontStrings) do - self:Register(fontString.parent, fontString, tags) - fontString.parent:RegisterUpdateFunc(fontString, "UpdateTags") - fontString:UpdateTags() - end -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 - -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 -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 - - -- 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) - - 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 - end - - functionPool[tag] = cachedFunc - end - 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 - - table.insert(args, cachedFunc) - end - - frequencyCache[tags] = lowestFrequency < 9999 and lowestFrequency or nil - tagPool[tags] = function(fontString, frame, event, unit, powerType) - -- we can only run on frames with units set - if not fontString.parent.unit then - return - end - - 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 - end - - 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 - 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) -end - -function Tags:Unregister(fontString) - regFontStrings[fontString] = nil - - -- Unregister it as using HC - for key, module in pairs(self.customEvents) do - if( fontString[key] ) then - fontString[key] = nil - module:DisableTag(fontString.parent, fontString) - end - end - - -- Kill any tag data - cancelMonitorTimer(fontString) - fontString.parent:UnregisterAll(fontString) - fontString.powerFilters = nil - fontString.UpdateTags = nil - fontString:SetText("") - - -- See if we need to unregister events - local parent = fontString.parent - local hasPowerFilter - for _, f in pairs(parent.fontStrings) do - if( f.powerFilters and f.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. -function ShadowUF:Hex(r, g, b) - if( type(r) == "table" ) then - if( r.r ) then - r, g, b = r.r, r.g, r.b - else - r, g, b = unpack(r) - end - end - - return string.format("|cff%02x%02x%02x", r * 255, g * 255, b * 255) -end - -function ShadowUF:FormatLargeNumber(number) - if( number < 9999 ) then - return number - elseif( number < 999999 ) then - return string.format("%.1fk", number / 1000) - elseif( number < 99999999 ) then - return string.format("%.2fm", number / 1000000) - end - - return string.format("%dm", number / 1000000) -end - -function ShadowUF:SmartFormatNumber(number) - if( number < 999999 ) then - return number - elseif( number < 99999999 ) then - return string.format("%.2fm", number / 1000000) - end - - return string.format("%dm", number / 1000000) -end - -function ShadowUF:GetClassColor(unit) - if( not UnitIsPlayer(unit) ) then - return nil - end - - local class = select(2, UnitClass(unit)) - return class and ShadowUF:Hex(ShadowUF.db.profile.classColors[class]) -end - -function ShadowUF:FormatShortTime(seconds) - if( seconds >= 3600 ) then - return string.format("%dh", seconds / 3600) - elseif( seconds >= 60 ) then - return string.format("%dm", seconds / 60) - end - - return string.format("%ds", seconds) -end - --- Name abbreviation -local function abbreviateName(text) - return (string.utf8sub or string.sub)(text, 1, 1) .. "." -end - -Tags.abbrevCache = setmetatable({}, { - __index = function(tbl, val) - val = string.gsub(val, "([^%s]+) ", abbreviateName) - rawset(tbl, val, val) - return val -end}) - --- Going to have to start using an env wrapper for tags I think -local Druid = {} -Druid.CatForm = GetSpellName(768) -Druid.MoonkinForm = GetSpellName(24858) -Druid.TravelForm = GetSpellName(783) -Druid.BearForm = GetSpellName(5487) -Druid.TreeForm = GetSpellName(33891) -Druid.AquaticForm = GetSpellName(1066) -Druid.SwiftFlightForm = GetSpellName(40120) -Druid.FlightForm = GetSpellName(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]], - ["short:druidform"] = [[function(unit, unitOwner) - if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end - - local Druid = ShadowUF.Druid - if( ShadowUF.UnitAuraBySpell(unit, Druid.CatForm) ) then - return ShadowUF.L["C"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TreeForm) ) then - return ShadowUF.L["T"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.MoonkinForm) ) then - return ShadowUF.L["M"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.BearForm) ) then - return ShadowUF.L["B"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.SwiftFlightForm) or ShadowUF.UnitAuraBySpell(unit, Druid.FlightForm) ) then - return ShadowUF.L["F"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TravelForm) ) then - return ShadowUF.L["T"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.AquaticForm) ) then - return ShadowUF.L["A"] - end - end]], - ["druidform"] = [[function(unit, unitOwner) - if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end - - local Druid = ShadowUF.Druid - if( ShadowUF.UnitAuraBySpell(unit, Druid.CatForm) ) then - return ShadowUF.L["Cat"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TreeForm) ) then - return ShadowUF.L["Tree"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.MoonkinForm) ) then - return ShadowUF.L["Moonkin"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.BearForm) ) then - return ShadowUF.L["Bear"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.SwiftFlightForm) or ShadowUF.UnitAuraBySpell(unit, Druid.FlightForm) ) then - return ShadowUF.L["Flight"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TravelForm) ) then - return ShadowUF.L["Travel"] - elseif( ShadowUF.UnitAuraBySpell(unit, Druid.AquaticForm) ) then - return ShadowUF.L["Aquatic"] - end - end]], - ["guild"] = [[function(unit, unitOwner) - return GetGuildInfo(unitOwner) - end]], - ["abbrev:name"] = [[function(unit, unitOwner) - local name = UnitName(unitOwner) or UNKNOWN - return string.len(name) > 10 and ShadowUF.Tags.abbrevCache[name] or name - end]], - ["unit:situation"] = [[function(unit, unitOwner) - local state = UnitThreatSituation(unit) - if( state == 3 ) then - return ShadowUF.L["Aggro"] - elseif( state == 2 ) then - return ShadowUF.L["High"] - elseif( state == 1 ) then - return ShadowUF.L["Medium"] - end - end]], - ["situation"] = [[function(unit, unitOwner) - local state = UnitThreatSituation("player", "target") - if( state == 3 ) then - return ShadowUF.L["Aggro"] - elseif( state == 2 ) then - return ShadowUF.L["High"] - elseif( state == 1 ) then - return ShadowUF.L["Medium"] - end - end]], - ["unit:color:sit"] = [[function(unit, unitOwner) - local state = UnitThreatSituation(unit) - - return state and state > 0 and ShadowUF:Hex(GetThreatStatusColor(state)) - end]], - ["unit:color:aggro"] = [[function(unit, unitOwner) - local state = UnitThreatSituation(unit) - - return state and state >= 3 and ShadowUF:Hex(GetThreatStatusColor(state)) - end]], - ["color:sit"] = [[function(unit, unitOwner) - local state = UnitThreatSituation("player", "target") - - return state and state > 0 and ShadowUF:Hex(GetThreatStatusColor(state)) - end]], - ["color:aggro"] = [[function(unit, unitOwner) - local state = UnitThreatSituation("player", "target") - - return state and state >= 3 and ShadowUF:Hex(GetThreatStatusColor(state)) - end]], - --["unit:scaled:threat"] = [[function(unit, unitOwner, fontString) - -- local scaled = select(3, UnitDetailedThreatSituation(unit)) - -- return scaled and string.format("%d%%", scaled) - --end]], - ["scaled:threat"] = [[function(unit, unitOwner) - local scaled = select(3, UnitDetailedThreatSituation("player", "target")) - return scaled and string.format("%d%%", scaled) - end]], - ["general:sit"] = [[function(unit, unitOwner) - local state = UnitThreatSituation("player") - if( state == 3 ) then - return ShadowUF.L["Aggro"] - elseif( state == 2 ) then - return ShadowUF.L["High"] - elseif( state == 1 ) then - return ShadowUF.L["Medium"] - end - end]], - ["color:gensit"] = [[function(unit, unitOwner) - local state = UnitThreatSituation("player") - - return state and state > 0 and ShadowUF:Hex(GetThreatStatusColor(state)) - end]], - ["status:time"] = [[function(unit, unitOwner) - local offlineStatus = ShadowUF.Tags.offlineStatus - if( not UnitIsConnected(unitOwner) ) then - offlineStatus[unitOwner] = offlineStatus[unitOwner] or GetTime() - return string.format(ShadowUF.L["Off:%s"], ShadowUF:FormatShortTime(GetTime() - offlineStatus[unitOwner])) - end - - offlineStatus[unitOwner] = nil - end]], - ["afk:time"] = [[function(unit, unitOwner) - if( not UnitIsConnected(unitOwner) ) then return end - - local afkStatus = ShadowUF.Tags.afkStatus - local status = UnitIsAFK(unitOwner) and ShadowUF.L["AFK:%s"] or UnitIsDND(unitOwner) and ShadowUF.L["DND:%s"] - if( status ) then - afkStatus[unitOwner] = afkStatus[unitOwner] or GetTime() - return string.format(status, ShadowUF:FormatShortTime(GetTime() - afkStatus[unitOwner])) - end - - afkStatus[unitOwner] = nil - end]], - ["pvp:time"] = [[function(unit, unitOwner) - if( GetPVPTimer() >= 300000 ) then - return nil - end - - return string.format(ShadowUF.L["PVP:%s"], ShadowUF:FormatShortTime(GetPVPTimer() / 1000)) - end]], - ["afk"] = [[function(unit, unitOwner, fontString) - return UnitIsAFK(unitOwner) and ShadowUF.L["AFK"] or UnitIsDND(unitOwner) and ShadowUF.L["DND"] - end]], - ["close"] = [[function(unit, unitOwner) return "|r" end]], - ["smartrace"] = [[function(unit, unitOwner) - return UnitIsPlayer(unit) and ShadowUF.tagFunc.race(unit) or ShadowUF.tagFunc.creature(unit) - end]], - ["reactcolor"] = [[function(unit, unitOwner) - local color - if( not UnitIsFriend(unit, "player") and UnitPlayerControlled(unit) ) then - if( UnitCanAttack("player", unit) ) then - color = ShadowUF.db.profile.healthColors.hostile - else - color = ShadowUF.db.profile.healthColors.enemyUnattack - end - elseif( UnitReaction(unit, "player") ) then - local reaction = UnitReaction(unit, "player") - if( reaction > 4 ) then - color = ShadowUF.db.profile.healthColors.friendly - elseif( reaction == 4 ) then - color = ShadowUF.db.profile.healthColors.neutral - elseif( reaction < 4 ) then - color = ShadowUF.db.profile.healthColors.hostile - end - end - - return color and ShadowUF:Hex(color) - end]], - ["class"] = [[function(unit, unitOwner) - return UnitIsPlayer(unit) and UnitClass(unit) - end]], - ["classcolor"] = [[function(unit, unitOwner) return ShadowUF:GetClassColor(unit) end]], - ["creature"] = [[function(unit, unitOwner) return UnitCreatureFamily(unit) or UnitCreatureType(unit) end]], - ["curhp"] = [[function(unit, unitOwner) - if( UnitIsDead(unit) ) then - return ShadowUF.L["Dead"] - elseif( UnitIsGhost(unit) ) then - return ShadowUF.L["Ghost"] - elseif( not UnitIsConnected(unit) ) then - return ShadowUF.L["Offline"] - end - - return ShadowUF:FormatLargeNumber(UnitHealth(unit)) - end]], - ["colorname"] = [[function(unit, unitOwner) - local color = ShadowUF:GetClassColor(unitOwner) - local name = UnitName(unitOwner) or UNKNOWN - if( not color ) then - return name - end - - return string.format("%s%s|r", color, name) - end]], - ["curpp"] = [[function(unit, unitOwner) - if( UnitPowerMax(unit) <= 0 ) then - return nil - elseif( UnitIsDeadOrGhost(unit) ) then - return 0 - end - - return ShadowUF:FormatLargeNumber(UnitPower(unit)) - end]], - ["curmaxhp"] = [[function(unit, unitOwner) - if( UnitIsDead(unit) ) then - return ShadowUF.L["Dead"] - elseif( UnitIsGhost(unit) ) then - return ShadowUF.L["Ghost"] - elseif( not UnitIsConnected(unit) ) then - return ShadowUF.L["Offline"] - end - - return string.format("%s/%s", ShadowUF:FormatLargeNumber(UnitHealth(unit)), ShadowUF:FormatLargeNumber(UnitHealthMax(unit))) - end]], - ["smart:curmaxhp"] = [[function(unit, unitOwner) - if( UnitIsDead(unit) ) then - return ShadowUF.L["Dead"] - elseif( UnitIsGhost(unit) ) then - return ShadowUF.L["Ghost"] - elseif( not UnitIsConnected(unit) ) then - return ShadowUF.L["Offline"] - end - - return string.format("%s/%s", ShadowUF:SmartFormatNumber(UnitHealth(unit)), ShadowUF:SmartFormatNumber(UnitHealthMax(unit))) - end]], - ["absolutehp"] = [[function(unit, unitOwner) - if( UnitIsDead(unit) ) then - return ShadowUF.L["Dead"] - elseif( UnitIsGhost(unit) ) then - return ShadowUF.L["Ghost"] - elseif( not UnitIsConnected(unit) ) then - return ShadowUF.L["Offline"] - end - - return string.format("%s/%s", UnitHealth(unit), UnitHealthMax(unit)) - end]], - ["abscurhp"] = [[function(unit, unitOwner) - if( UnitIsDead(unit) ) then - return ShadowUF.L["Dead"] - elseif( UnitIsGhost(unit) ) then - return ShadowUF.L["Ghost"] - elseif( not UnitIsConnected(unit) ) then - return ShadowUF.L["Offline"] - end - - return UnitHealth(unit) - end]], - ["absmaxhp"] = [[function(unit, unitOwner) return UnitHealthMax(unit) end]], - ["abscurpp"] = [[function(unit, unitOwner) - if( UnitPowerMax(unit) <= 0 ) then - return nil - elseif( UnitIsDeadOrGhost(unit) ) then - return 0 - end - - return UnitPower(unit) - end]], - ["absmaxpp"] = [[function(unit, unitOwner) - local power = UnitPowerMax(unit) - return power > 0 and power or nil - end]], - ["absolutepp"] = [[function(unit, unitOwner) - local maxPower = UnitPowerMax(unit) - local power = UnitPower(unit) - if( UnitIsDeadOrGhost(unit) ) then - return string.format("0/%s", maxPower) - elseif( maxPower <= 0 ) then - return nil - end - - return string.format("%s/%s", power, maxPower) - end]], - ["curmaxpp"] = [[function(unit, unitOwner) - local maxPower = UnitPowerMax(unit) - local power = UnitPower(unit) - if( UnitIsDeadOrGhost(unit) ) then - return string.format("0/%s", ShadowUF:FormatLargeNumber(maxPower)) - elseif( maxPower <= 0 ) then - return nil - end - - return string.format("%s/%s", ShadowUF:FormatLargeNumber(power), ShadowUF:FormatLargeNumber(maxPower)) - end]], - ["smart:curmaxpp"] = [[function(unit, unitOwner) - local maxPower = UnitPowerMax(unit) - local power = UnitPower(unit) - if( UnitIsDeadOrGhost(unit) ) then - return string.format("0/%s", maxPower) - elseif( maxPower <= 0 ) then - return nil - end - - 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) or 0 - if( level < 0 and UnitClassification(unit) == "worldboss" ) then - return nil - end - - if( UnitCanAttack("player", unit) ) then - local color = ShadowUF:Hex(GetQuestDifficultyColor(level > 0 and level or 99)) - if( not color ) then - return level > 0 and level or "??" - end - - return color .. (level > 0 and level or "??") .. "|r" - else - 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) or 0 - return level > 0 and level or UnitClassification(unit) ~= "worldboss" and "??" or nil - end]], - ["maxhp"] = [[function(unit, unitOwner) return ShadowUF:FormatLargeNumber(UnitHealthMax(unit)) end]], - ["maxpp"] = [[function(unit, unitOwner) - local power = UnitPowerMax(unit) - if( power <= 0 ) then - return nil - elseif( UnitIsDeadOrGhost(unit) ) then - return 0 - end - - return ShadowUF:FormatLargeNumber(power) - end]], - ["missinghp"] = [[function(unit, unitOwner) - if( UnitIsDead(unit) ) then - return ShadowUF.L["Dead"] - elseif( UnitIsGhost(unit) ) then - return ShadowUF.L["Ghost"] - elseif( not UnitIsConnected(unit) ) then - return ShadowUF.L["Offline"] - end - - local missing = UnitHealthMax(unit) - UnitHealth(unit) - if( missing <= 0 ) then return nil end - return "-" .. ShadowUF:FormatLargeNumber(missing) - end]], - ["missingpp"] = [[function(unit, unitOwner) - local power = UnitPowerMax(unit) - if( power <= 0 ) then - return nil - end - - local missing = power - UnitPower(unit) - if( missing <= 0 ) then return nil end - return "-" .. ShadowUF:FormatLargeNumber(missing) - end]], - ["def:name"] = [[function(unit, unitOwner) - local deficit = ShadowUF.tagFunc.missinghp(unit, unitOwner) - if( deficit ) then return deficit end - - return ShadowUF.tagFunc.name(unit, unitOwner) - end]], - ["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) - local max = UnitHealthMax(unit) - if( max <= 0 or UnitIsDead(unit) or UnitIsGhost(unit) or not UnitIsConnected(unit) ) then - return "0%" - end - - return math.floor(UnitHealth(unit) / max * 100 + 0.5) .. "%" - end]], - ["perpp"] = [[function(unit, unitOwner) - local maxPower = UnitPowerMax(unit) - if( maxPower <= 0 ) then - return nil - elseif( UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) ) then - return "0%" - end - - return string.format("%d%%", math.floor(UnitPower(unit) / maxPower * 100 + 0.5)) - end]], - ["plus"] = [[function(unit, unitOwner) local classif = UnitClassification(unit) return (classif == "elite" or classif == "rareelite") and "+" end]], - ["race"] = [[function(unit, unitOwner) return UnitRace(unit) end]], - ["rare"] = [[function(unit, unitOwner) local classif = UnitClassification(unit) return (classif == "rare" or classif == "rareelite") and ShadowUF.L["Rare"] end]], - ["sex"] = [[function(unit, unitOwner) local sex = UnitSex(unit) return sex == 2 and ShadowUF.L["Male"] or sex == 3 and ShadowUF.L["Female"] end]], - ["smartclass"] = [[function(unit, unitOwner) return UnitIsPlayer(unit) and ShadowUF.tagFunc.class(unit) or ShadowUF.tagFunc.creature(unit) end]], - ["status"] = [[function(unit, unitOwner) - if( UnitIsDead(unit) ) then - return ShadowUF.L["Dead"] - elseif( UnitIsGhost(unit) ) then - return ShadowUF.L["Ghost"] - elseif( not UnitIsConnected(unit) ) then - 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) - 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 - end]], - ["smartlevel"] = [[function(unit, unitOwner) - local classif = UnitClassification(unit) - if( classif == "worldboss" ) then - return ShadowUF.L["Boss"] - else - local plus = ShadowUF.tagFunc.plus(unit) - local level = ShadowUF.tagFunc.level(unit) - if( plus ) then - return level .. plus - else - return level - end - end - 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 - return ShadowUF.L["Rare"] - elseif( classif == "rareelite" ) then - return ShadowUF.L["Rare Elite"] - elseif( classif == "elite" ) then - 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" or classif == "minus" and "M" - end]], - ["group"] = [[function(unit, unitOwner) - 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, GetNumGroupMembers() do - local raidName, _, group = GetRaidRosterInfo(i) - if( raidName == name ) then - return group - end - end - - return nil - end]], - ["druid:curpp"] = [[function(unit, unitOwner) - if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end - local powerType = UnitPowerType(unit) - 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 ~= 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 ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then 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]], - ["druid:absolutepp"] = [[function(unit, unitOwner) - if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end - local powerType = UnitPowerType(unit) - 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) - local heal = UnitGetIncomingHeals(unit) - return heal and heal > 0 and string.format("%d", heal) - end]], - ["incheal"] = [[function(unit, unitOwner, fontString) - local heal = UnitGetIncomingHeals(unit) - return heal and heal > 0 and ShadowUF:FormatLargeNumber(heal) - end]], - ["incheal:name"] = [[function(unit, unitOwner, fontString) - 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( GetNumGroupMembers() == 0 ) then return nil end - local guid = UnitGUID(unit) - if( not guid ) then return "0" end - - local total = 0 - for i=1, GetNumGroupMembers() do - local unit = ShadowUF.raidUnits[i] - if( UnitGUID(ShadowUF.unitTarget[unit]) == guid ) then - total = total + 1 - end - end - return total - end]], - ["unit:raid:assist"] = [[function(unit, unitOwner, fontString) - 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, GetNumGroupMembers() do - local unit = ShadowUF.raidUnits[i] - if( UnitGUID(ShadowUF.unitTarget[unit]) == guid ) then - total = total + 1 - end - end - return total - end]], -} - --- Default tag events -Tags.defaultEvents = { - ["totem:timer"] = "SUF_TOTEM_TIMER", - ["rune:timer"] = "SUF_RUNE_TIMER", - ["hp:color"] = "UNIT_HEALTH 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_CONNECTION", - ["abscurhp"] = "UNIT_HEALTH UNIT_CONNECTION", - ["curmaxhp"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION", - ["absolutehp"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION", - ["smart:curmaxhp"] = "UNIT_HEALTH 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", - ["absmaxhp"] = "UNIT_MAXHEALTH", - ["maxpp"] = "SUF_POWERTYPE:CURRENT UNIT_MAXPOWER", - ["absmaxpp"] = "SUF_POWERTYPE:CURRENT UNIT_MAXPOWER", - ["missinghp"] = "UNIT_HEALTH 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_MAXHEALTH UNIT_CONNECTION", - ["perpp"] = "SUF_POWERTYPE:CURRENT UNIT_POWER_FREQUENT UNIT_MAXPOWER UNIT_CONNECTION", - ["status"] = "UNIT_HEALTH 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_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 --- or it can't be purely event based -Tags.defaultFrequents = { - ["afk"] = 1, - ["afk:time"] = 1, - ["status:time"] = 1, - ["pvp:time"] = 1, - ["scaled:threat"] = 1, - ["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 = { - ["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 = { - ["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 = { - ["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_POWER_FREQUENT"] = "power", - ["UNIT_MAXPOWER"] = "power", - ["UNIT_ABSORB_AMOUNT_CHANGED"] = "health", - ["UNIT_HEALTH"] = "health", - ["UNIT_MAXHEALTH"] = "health", - ["GROUP_ROSTER_UPDATE"] = "unitless", - ["RAID_TARGET_UPDATE"] = "unitless", - ["PLAYER_TARGET_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 -Tags.unitBlacklist = { - ["threat"] = "%w+target", -} - --- 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 -local function loadAPIEvents() - if( Tags.APIEvents ) then return end - Tags.APIEvents = { - ["InCombatLockdown"] = "PLAYER_REGEN_ENABLED PLAYER_REGEN_DISABLED", - ["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", - ["UnitHealthMax"] = "UNIT_MAXHEALTH", - ["UnitPower%("] = "UNIT_POWER_FREQUENT", - ["UnitPowerMax"] = "UNIT_MAXPOWER", - ["UnitPowerType"] = "UNIT_DISPLAYPOWER", - ["UnitIsDead"] = "UNIT_HEALTH", - ["UnitIsGhost"] = "UNIT_HEALTH", - ["UnitIsConnected"] = "UNIT_HEALTH UNIT_CONNECTION", - ["UnitIsAFK"] = "PLAYER_FLAGS_CHANGED", - ["UnitIsDND"] = "PLAYER_FLAGS_CHANGED", - ["UnitIsPVP"] = "PLAYER_FLAGS_CHANGED UNIT_FACTION", - ["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", - ["GetAuraDataByIndex"] = "UNIT_AURA", - ["GetBuffDataByIndex"] = "UNIT_AURA", - ["GetDebuffDataByIndex"] = "UNIT_AURA", - ["UnitAuraBySpell"] = "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", - ["GetWatchedFactionInfo"] = "UPDATE_FACTION", - ["GetRuneCooldown"] = "RUNE_POWER_UPDATE", - ["GetRuneType"] = "RUNE_TYPE_UPDATE", - ["GetRaidTargetIndex"] = "RAID_TARGET_UPDATE", - ["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", - ["UnitThreatSituation"] = "UNIT_THREAT_SITUATION_UPDATE", - ["UnitDetailedThreatSituation"] = "UNIT_THREAT_SITUATION_UPDATE", - } -end - --- Scan the actual tag code to find the events it uses -local alreadyScanned = {} -function Tags:IdentifyEvents(code, parentTag) - -- Already scanned this tag, prevents infinite recursion - if( parentTag and alreadyScanned[parentTag] ) then - return "" - -- Flagged that we already took care of this - elseif( parentTag ) then - alreadyScanned[parentTag] = true - else - for k in pairs(alreadyScanned) do alreadyScanned[k] = nil end - loadAPIEvents() - end - - -- Scan our function list to see what APIs are used - local eventList = "" - for func, events in pairs(self.APIEvents) do - if( string.match(code, func) ) then - eventList = eventList .. events .. " " - end - end - - -- Scan if they use any tags, if so we need to check them as well to see what content is used - for tag in string.gmatch(code, "tagFunc%.(%w+)%(") do - local c = ShadowUF.Tags.defaultTags[tag] or ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].func - eventList = eventList .. " " .. self:IdentifyEvents(c, tag) - end - - -- Remove any duplicate events - if( not parentTag ) then - local tagEvents = {} - for event in string.gmatch(string.trim(eventList), "%S+") do - tagEvents[event] = true - end - - eventList = "" - for event in pairs(tagEvents) do - eventList = eventList .. event .. " " - end - end - - -- And give them our nicely outputted data - return string.trim(eventList or "") -end - - --- Checker function, makes sure tags are all happy ---@debug@ -function Tags:Verify() - local fine = true - for tag, events in pairs(self.defaultEvents) do - if( not self.defaultTags[tag] ) then - print(string.format("Found event for %s, but no tag associated with it.", tag)) - fine = nil - end - end - - for tag, data in pairs(self.defaultTags) do - if( not self.defaultTags[tag] ) then - print(string.format("Found tag for %s, but no event associated with it.", tag)) - fine = nil - end - - if( not self.defaultHelp[tag] ) then - print(string.format("Found tag for %s, but no help text associated with it.", tag)) - fine = nil - end - - if( not self.defaultNames[tag] ) then - print(string.format("Found tag for %s, but no name associated with it.", tag)) - fine = nil - end - - if( not self.defaultCategories[tag] ) then - print(string.format("Found tag for %s, but no category associated with it.", tag)) - fine = nil - end - - local funct, msg = loadstring("return " .. data) - if( not funct and msg ) then - print(string.format("Failed to load tag %s.", tag)) - print(msg) - fine = nil - else - funct("player") - end - end - - if( fine ) then - print("Verified tags, everything is fine.") - end -end ---@end-debug@ +local GetSpellName = C_Spell.GetSpellName +local GetSpecialization = C_SpecializationInfo.GetSpecialization or _G.GetSpecialization + + +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 ) + -- was breaking the logic and stripping the entire tag, this is a quick fix to stop that. + local tagKey = select(2, string.match(tag, "(%b())([%w%p]+)(%b())")) + if( not tagKey ) then tagKey = select(2, string.match(tag, "(%b())([%w%p]+)")) end + if( not tagKey ) then tagKey = string.match(tag, "([%w%p]+)(%b())") end + + tag = tagKey or tag + + 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 + -- 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 + 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 + + -- 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 + table.wipe(functionPool) + table.wipe(ShadowUF.tagFunc) + table.wipe(tagPool) + + -- Now update frames + for fontString, tags in pairs(regFontStrings) do + self:Register(fontString.parent, fontString, tags) + fontString.parent:RegisterUpdateFunc(fontString, "UpdateTags") + fontString:UpdateTags() + end +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 + +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 +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 + + -- 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) + + 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 + end + + functionPool[tag] = cachedFunc + end + 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 + + table.insert(args, cachedFunc) + end + + frequencyCache[tags] = lowestFrequency < 9999 and lowestFrequency or nil + tagPool[tags] = function(fontString, frame, event, unit, powerType) + -- we can only run on frames with units set + if not fontString.parent.unit then + return + end + + 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 + end + + 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 + 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) +end + +function Tags:Unregister(fontString) + regFontStrings[fontString] = nil + + -- Unregister it as using HC + for key, module in pairs(self.customEvents) do + if( fontString[key] ) then + fontString[key] = nil + module:DisableTag(fontString.parent, fontString) + end + end + + -- Kill any tag data + cancelMonitorTimer(fontString) + fontString.parent:UnregisterAll(fontString) + fontString.powerFilters = nil + fontString.UpdateTags = nil + fontString:SetText("") + + -- See if we need to unregister events + local parent = fontString.parent + local hasPowerFilter + for _, f in pairs(parent.fontStrings) do + if( f.powerFilters and f.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. +function ShadowUF:Hex(r, g, b) + if( type(r) == "table" ) then + if( r.r ) then + r, g, b = r.r, r.g, r.b + else + r, g, b = unpack(r) + end + end + + return string.format("|cff%02x%02x%02x", r * 255, g * 255, b * 255) +end + +function ShadowUF:FormatLargeNumber(number) + if( number < 9999 ) then + return number + elseif( number < 999999 ) then + return string.format("%.1fk", number / 1000) + elseif( number < 99999999 ) then + return string.format("%.2fm", number / 1000000) + end + + return string.format("%dm", number / 1000000) +end + +function ShadowUF:SmartFormatNumber(number) + if( number < 999999 ) then + return number + elseif( number < 99999999 ) then + return string.format("%.2fm", number / 1000000) + end + + return string.format("%dm", number / 1000000) +end + +function ShadowUF:GetClassColor(unit) + if( not UnitIsPlayer(unit) ) then + return nil + end + + local class = select(2, UnitClass(unit)) + return class and ShadowUF:Hex(ShadowUF.db.profile.classColors[class]) +end + +function ShadowUF:FormatShortTime(seconds) + if( seconds >= 3600 ) then + return string.format("%dh", seconds / 3600) + elseif( seconds >= 60 ) then + return string.format("%dm", seconds / 60) + end + + return string.format("%ds", seconds) +end + +-- Name abbreviation +local function abbreviateName(text) + return (string.utf8sub or string.sub)(text, 1, 1) .. "." +end + +Tags.abbrevCache = setmetatable({}, { + __index = function(tbl, val) + val = string.gsub(val, "([^%s]+) ", abbreviateName) + rawset(tbl, val, val) + return val +end}) + +-- Going to have to start using an env wrapper for tags I think +local Druid = {} +Druid.CatForm = GetSpellName(768) +Druid.MoonkinForm = GetSpellName(24858) +Druid.TravelForm = GetSpellName(783) +Druid.BearForm = GetSpellName(5487) +Druid.TreeForm = GetSpellName(33891) +Druid.AquaticForm = GetSpellName(1066) +Druid.SwiftFlightForm = GetSpellName(40120) +Druid.FlightForm = GetSpellName(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]], + ["short:druidform"] = [[function(unit, unitOwner) + if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end + + local Druid = ShadowUF.Druid + if( ShadowUF.UnitAuraBySpell(unit, Druid.CatForm) ) then + return ShadowUF.L["C"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TreeForm) ) then + return ShadowUF.L["T"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.MoonkinForm) ) then + return ShadowUF.L["M"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.BearForm) ) then + return ShadowUF.L["B"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.SwiftFlightForm) or ShadowUF.UnitAuraBySpell(unit, Druid.FlightForm) ) then + return ShadowUF.L["F"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TravelForm) ) then + return ShadowUF.L["T"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.AquaticForm) ) then + return ShadowUF.L["A"] + end + end]], + ["druidform"] = [[function(unit, unitOwner) + if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end + + local Druid = ShadowUF.Druid + if( ShadowUF.UnitAuraBySpell(unit, Druid.CatForm) ) then + return ShadowUF.L["Cat"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TreeForm) ) then + return ShadowUF.L["Tree"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.MoonkinForm) ) then + return ShadowUF.L["Moonkin"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.BearForm) ) then + return ShadowUF.L["Bear"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.SwiftFlightForm) or ShadowUF.UnitAuraBySpell(unit, Druid.FlightForm) ) then + return ShadowUF.L["Flight"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TravelForm) ) then + return ShadowUF.L["Travel"] + elseif( ShadowUF.UnitAuraBySpell(unit, Druid.AquaticForm) ) then + return ShadowUF.L["Aquatic"] + end + end]], + ["guild"] = [[function(unit, unitOwner) + return GetGuildInfo(unitOwner) + end]], + ["abbrev:name"] = [[function(unit, unitOwner) + local name = UnitName(unitOwner) or UNKNOWN + return string.len(name) > 10 and ShadowUF.Tags.abbrevCache[name] or name + end]], + ["unit:situation"] = [[function(unit, unitOwner) + local state = UnitThreatSituation(unit) + if( state == 3 ) then + return ShadowUF.L["Aggro"] + elseif( state == 2 ) then + return ShadowUF.L["High"] + elseif( state == 1 ) then + return ShadowUF.L["Medium"] + end + end]], + ["situation"] = [[function(unit, unitOwner) + local state = UnitThreatSituation("player", "target") + if( state == 3 ) then + return ShadowUF.L["Aggro"] + elseif( state == 2 ) then + return ShadowUF.L["High"] + elseif( state == 1 ) then + return ShadowUF.L["Medium"] + end + end]], + ["unit:color:sit"] = [[function(unit, unitOwner) + local state = UnitThreatSituation(unit) + + return state and state > 0 and ShadowUF:Hex(GetThreatStatusColor(state)) + end]], + ["unit:color:aggro"] = [[function(unit, unitOwner) + local state = UnitThreatSituation(unit) + + return state and state >= 3 and ShadowUF:Hex(GetThreatStatusColor(state)) + end]], + ["color:sit"] = [[function(unit, unitOwner) + local state = UnitThreatSituation("player", "target") + + return state and state > 0 and ShadowUF:Hex(GetThreatStatusColor(state)) + end]], + ["color:aggro"] = [[function(unit, unitOwner) + local state = UnitThreatSituation("player", "target") + + return state and state >= 3 and ShadowUF:Hex(GetThreatStatusColor(state)) + end]], + --["unit:scaled:threat"] = [[function(unit, unitOwner, fontString) + -- local scaled = select(3, UnitDetailedThreatSituation(unit)) + -- return scaled and string.format("%d%%", scaled) + --end]], + ["scaled:threat"] = [[function(unit, unitOwner) + local scaled = select(3, UnitDetailedThreatSituation("player", "target")) + return scaled and string.format("%d%%", scaled) + end]], + ["general:sit"] = [[function(unit, unitOwner) + local state = UnitThreatSituation("player") + if( state == 3 ) then + return ShadowUF.L["Aggro"] + elseif( state == 2 ) then + return ShadowUF.L["High"] + elseif( state == 1 ) then + return ShadowUF.L["Medium"] + end + end]], + ["color:gensit"] = [[function(unit, unitOwner) + local state = UnitThreatSituation("player") + + return state and state > 0 and ShadowUF:Hex(GetThreatStatusColor(state)) + end]], + ["status:time"] = [[function(unit, unitOwner) + local offlineStatus = ShadowUF.Tags.offlineStatus + if( not UnitIsConnected(unitOwner) ) then + offlineStatus[unitOwner] = offlineStatus[unitOwner] or GetTime() + return string.format(ShadowUF.L["Off:%s"], ShadowUF:FormatShortTime(GetTime() - offlineStatus[unitOwner])) + end + + offlineStatus[unitOwner] = nil + end]], + ["afk:time"] = [[function(unit, unitOwner) + if( not UnitIsConnected(unitOwner) ) then return end + + local afkStatus = ShadowUF.Tags.afkStatus + local status = UnitIsAFK(unitOwner) and ShadowUF.L["AFK:%s"] or UnitIsDND(unitOwner) and ShadowUF.L["DND:%s"] + if( status ) then + afkStatus[unitOwner] = afkStatus[unitOwner] or GetTime() + return string.format(status, ShadowUF:FormatShortTime(GetTime() - afkStatus[unitOwner])) + end + + afkStatus[unitOwner] = nil + end]], + ["pvp:time"] = [[function(unit, unitOwner) + if( GetPVPTimer() >= 300000 ) then + return nil + end + + return string.format(ShadowUF.L["PVP:%s"], ShadowUF:FormatShortTime(GetPVPTimer() / 1000)) + end]], + ["afk"] = [[function(unit, unitOwner, fontString) + return UnitIsAFK(unitOwner) and ShadowUF.L["AFK"] or UnitIsDND(unitOwner) and ShadowUF.L["DND"] + end]], + ["close"] = [[function(unit, unitOwner) return "|r" end]], + ["smartrace"] = [[function(unit, unitOwner) + return UnitIsPlayer(unit) and ShadowUF.tagFunc.race(unit) or ShadowUF.tagFunc.creature(unit) + end]], + ["reactcolor"] = [[function(unit, unitOwner) + local color + if( not UnitIsFriend(unit, "player") and UnitPlayerControlled(unit) ) then + if( UnitCanAttack("player", unit) ) then + color = ShadowUF.db.profile.healthColors.hostile + else + color = ShadowUF.db.profile.healthColors.enemyUnattack + end + elseif( UnitReaction(unit, "player") ) then + local reaction = UnitReaction(unit, "player") + if( reaction > 4 ) then + color = ShadowUF.db.profile.healthColors.friendly + elseif( reaction == 4 ) then + color = ShadowUF.db.profile.healthColors.neutral + elseif( reaction < 4 ) then + color = ShadowUF.db.profile.healthColors.hostile + end + end + + return color and ShadowUF:Hex(color) + end]], + ["class"] = [[function(unit, unitOwner) + return UnitIsPlayer(unit) and UnitClass(unit) + end]], + ["classcolor"] = [[function(unit, unitOwner) return ShadowUF:GetClassColor(unit) end]], + ["creature"] = [[function(unit, unitOwner) return UnitCreatureFamily(unit) or UnitCreatureType(unit) end]], + ["curhp"] = [[function(unit, unitOwner) + if( UnitIsDead(unit) ) then + return ShadowUF.L["Dead"] + elseif( UnitIsGhost(unit) ) then + return ShadowUF.L["Ghost"] + elseif( not UnitIsConnected(unit) ) then + return ShadowUF.L["Offline"] + end + + return ShadowUF:FormatLargeNumber(UnitHealth(unit)) + end]], + ["colorname"] = [[function(unit, unitOwner) + local color = ShadowUF:GetClassColor(unitOwner) + local name = UnitName(unitOwner) or UNKNOWN + if( not color ) then + return name + end + + return string.format("%s%s|r", color, name) + end]], + ["curpp"] = [[function(unit, unitOwner) + if( UnitPowerMax(unit) <= 0 ) then + return nil + elseif( UnitIsDeadOrGhost(unit) ) then + return 0 + end + + return ShadowUF:FormatLargeNumber(UnitPower(unit)) + end]], + ["curmaxhp"] = [[function(unit, unitOwner) + if( UnitIsDead(unit) ) then + return ShadowUF.L["Dead"] + elseif( UnitIsGhost(unit) ) then + return ShadowUF.L["Ghost"] + elseif( not UnitIsConnected(unit) ) then + return ShadowUF.L["Offline"] + end + + return string.format("%s/%s", ShadowUF:FormatLargeNumber(UnitHealth(unit)), ShadowUF:FormatLargeNumber(UnitHealthMax(unit))) + end]], + ["smart:curmaxhp"] = [[function(unit, unitOwner) + if( UnitIsDead(unit) ) then + return ShadowUF.L["Dead"] + elseif( UnitIsGhost(unit) ) then + return ShadowUF.L["Ghost"] + elseif( not UnitIsConnected(unit) ) then + return ShadowUF.L["Offline"] + end + + return string.format("%s/%s", ShadowUF:SmartFormatNumber(UnitHealth(unit)), ShadowUF:SmartFormatNumber(UnitHealthMax(unit))) + end]], + ["absolutehp"] = [[function(unit, unitOwner) + if( UnitIsDead(unit) ) then + return ShadowUF.L["Dead"] + elseif( UnitIsGhost(unit) ) then + return ShadowUF.L["Ghost"] + elseif( not UnitIsConnected(unit) ) then + return ShadowUF.L["Offline"] + end + + return string.format("%s/%s", UnitHealth(unit), UnitHealthMax(unit)) + end]], + ["abscurhp"] = [[function(unit, unitOwner) + if( UnitIsDead(unit) ) then + return ShadowUF.L["Dead"] + elseif( UnitIsGhost(unit) ) then + return ShadowUF.L["Ghost"] + elseif( not UnitIsConnected(unit) ) then + return ShadowUF.L["Offline"] + end + + return UnitHealth(unit) + end]], + ["absmaxhp"] = [[function(unit, unitOwner) return UnitHealthMax(unit) end]], + ["abscurpp"] = [[function(unit, unitOwner) + if( UnitPowerMax(unit) <= 0 ) then + return nil + elseif( UnitIsDeadOrGhost(unit) ) then + return 0 + end + + return UnitPower(unit) + end]], + ["absmaxpp"] = [[function(unit, unitOwner) + local power = UnitPowerMax(unit) + return power > 0 and power or nil + end]], + ["absolutepp"] = [[function(unit, unitOwner) + local maxPower = UnitPowerMax(unit) + local power = UnitPower(unit) + if( UnitIsDeadOrGhost(unit) ) then + return string.format("0/%s", maxPower) + elseif( maxPower <= 0 ) then + return nil + end + + return string.format("%s/%s", power, maxPower) + end]], + ["curmaxpp"] = [[function(unit, unitOwner) + local maxPower = UnitPowerMax(unit) + local power = UnitPower(unit) + if( UnitIsDeadOrGhost(unit) ) then + return string.format("0/%s", ShadowUF:FormatLargeNumber(maxPower)) + elseif( maxPower <= 0 ) then + return nil + end + + return string.format("%s/%s", ShadowUF:FormatLargeNumber(power), ShadowUF:FormatLargeNumber(maxPower)) + end]], + ["smart:curmaxpp"] = [[function(unit, unitOwner) + local maxPower = UnitPowerMax(unit) + local power = UnitPower(unit) + if( UnitIsDeadOrGhost(unit) ) then + return string.format("0/%s", maxPower) + elseif( maxPower <= 0 ) then + return nil + end + + 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) or 0 + if( level < 0 and UnitClassification(unit) == "worldboss" ) then + return nil + end + + if( UnitCanAttack("player", unit) ) then + local color = ShadowUF:Hex(GetQuestDifficultyColor(level > 0 and level or 99)) + if( not color ) then + return level > 0 and level or "??" + end + + return color .. (level > 0 and level or "??") .. "|r" + else + 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) or 0 + return level > 0 and level or UnitClassification(unit) ~= "worldboss" and "??" or nil + end]], + ["maxhp"] = [[function(unit, unitOwner) return ShadowUF:FormatLargeNumber(UnitHealthMax(unit)) end]], + ["maxpp"] = [[function(unit, unitOwner) + local power = UnitPowerMax(unit) + if( power <= 0 ) then + return nil + elseif( UnitIsDeadOrGhost(unit) ) then + return 0 + end + + return ShadowUF:FormatLargeNumber(power) + end]], + ["missinghp"] = [[function(unit, unitOwner) + if( UnitIsDead(unit) ) then + return ShadowUF.L["Dead"] + elseif( UnitIsGhost(unit) ) then + return ShadowUF.L["Ghost"] + elseif( not UnitIsConnected(unit) ) then + return ShadowUF.L["Offline"] + end + + local missing = UnitHealthMax(unit) - UnitHealth(unit) + if( missing <= 0 ) then return nil end + return "-" .. ShadowUF:FormatLargeNumber(missing) + end]], + ["missingpp"] = [[function(unit, unitOwner) + local power = UnitPowerMax(unit) + if( power <= 0 ) then + return nil + end + + local missing = power - UnitPower(unit) + if( missing <= 0 ) then return nil end + return "-" .. ShadowUF:FormatLargeNumber(missing) + end]], + ["def:name"] = [[function(unit, unitOwner) + local deficit = ShadowUF.tagFunc.missinghp(unit, unitOwner) + if( deficit ) then return deficit end + + return ShadowUF.tagFunc.name(unit, unitOwner) + end]], + ["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) + local max = UnitHealthMax(unit) + if( max <= 0 or UnitIsDead(unit) or UnitIsGhost(unit) or not UnitIsConnected(unit) ) then + return "0%" + end + + return math.floor(UnitHealth(unit) / max * 100 + 0.5) .. "%" + end]], + ["perpp"] = [[function(unit, unitOwner) + local maxPower = UnitPowerMax(unit) + if( maxPower <= 0 ) then + return nil + elseif( UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) ) then + return "0%" + end + + return string.format("%d%%", math.floor(UnitPower(unit) / maxPower * 100 + 0.5)) + end]], + ["plus"] = [[function(unit, unitOwner) local classif = UnitClassification(unit) return (classif == "elite" or classif == "rareelite") and "+" end]], + ["race"] = [[function(unit, unitOwner) return UnitRace(unit) end]], + ["rare"] = [[function(unit, unitOwner) local classif = UnitClassification(unit) return (classif == "rare" or classif == "rareelite") and ShadowUF.L["Rare"] end]], + ["sex"] = [[function(unit, unitOwner) local sex = UnitSex(unit) return sex == 2 and ShadowUF.L["Male"] or sex == 3 and ShadowUF.L["Female"] end]], + ["smartclass"] = [[function(unit, unitOwner) return UnitIsPlayer(unit) and ShadowUF.tagFunc.class(unit) or ShadowUF.tagFunc.creature(unit) end]], + ["status"] = [[function(unit, unitOwner) + if( UnitIsDead(unit) ) then + return ShadowUF.L["Dead"] + elseif( UnitIsGhost(unit) ) then + return ShadowUF.L["Ghost"] + elseif( not UnitIsConnected(unit) ) then + 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]], + ["priest:shadoworbs"] = [[function(unit, unitOwner) + local points = UnitPower(ShadowUF.playerUnit, Enum.PowerType.ShadowOrbs) + 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]], + ["warlock:demonic:perpp"] = [[function(unit, unitOwner) + local maxPower = UnitPowerMax(unit, Enum.PowerType.DemonicFury) + if( maxPower <= 0 ) then + return nil + elseif( UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) ) then + return "0%" + end + + return string.format("%d%%", math.floor(UnitPower(unit, Enum.PowerType.DemonicFury) / maxPower * 100 + 0.5)) + end]], + ["warlock:demonic:maxpp"] = [[function(unit, unitOwner) + local power = UnitPowerMax(unit, Enum.PowerType.DemonicFury) + if( power <= 0 ) then + return nil + elseif( UnitIsDeadOrGhost(unit) ) then + return 0 + end + + return ShadowUF:FormatLargeNumber(power) + end]], + ["warlock:demonic:curpp"] = [[function(unit, unitOwner) + local power = UnitPower(unit, Enum.PowerType.DemonicFury) + if( power <= 0 ) then + return nil + elseif( UnitIsDeadOrGhost(unit) ) then + return 0 + end + + return ShadowUF:FormatLargeNumber(power) + end]], + ["cpoints"] = [[function(unit, unitOwner) + 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 + end]], + ["smartlevel"] = [[function(unit, unitOwner) + local classif = UnitClassification(unit) + if( classif == "worldboss" ) then + return ShadowUF.L["Boss"] + else + local plus = ShadowUF.tagFunc.plus(unit) + local level = ShadowUF.tagFunc.level(unit) + if( plus ) then + return level .. plus + else + return level + end + end + 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 + return ShadowUF.L["Rare"] + elseif( classif == "rareelite" ) then + return ShadowUF.L["Rare Elite"] + elseif( classif == "elite" ) then + 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" or classif == "minus" and "M" + end]], + ["group"] = [[function(unit, unitOwner) + 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, GetNumGroupMembers() do + local raidName, _, group = GetRaidRosterInfo(i) + if( raidName == name ) then + return group + end + end + + return nil + end]], + ["druid:curpp"] = [[function(unit, unitOwner) + if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end + local powerType = UnitPowerType(unit) + if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.Balance ) 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 ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.Balance ) 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 ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.Balance ) then 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]], + ["druid:eclipse"] = [[function(unit, unitOwner) + if( C_SpecializationInfo.GetSpecialization() ~= 1 ) then return nil end + + return UnitPower(unitOwner, Enum.PowerType.Balance) + end]], + ["druid:absolutepp"] = [[function(unit, unitOwner) + if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end + local powerType = UnitPowerType(unit) + if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.Balance ) 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.Balance ) 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.Balance ) 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.Balance ) 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.Balance ) 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) + local heal = UnitGetIncomingHeals(unit) + return heal and heal > 0 and string.format("%d", heal) + end]], + ["incheal"] = [[function(unit, unitOwner, fontString) + local heal = UnitGetIncomingHeals(unit) + return heal and heal > 0 and ShadowUF:FormatLargeNumber(heal) + end]], + ["incheal:name"] = [[function(unit, unitOwner, fontString) + 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( GetNumGroupMembers() == 0 ) then return nil end + local guid = UnitGUID(unit) + if( not guid ) then return "0" end + + local total = 0 + for i=1, GetNumGroupMembers() do + local unit = ShadowUF.raidUnits[i] + if( UnitGUID(ShadowUF.unitTarget[unit]) == guid ) then + total = total + 1 + end + end + return total + end]], + ["unit:raid:assist"] = [[function(unit, unitOwner, fontString) + 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, GetNumGroupMembers() do + local unit = ShadowUF.raidUnits[i] + if( UnitGUID(ShadowUF.unitTarget[unit]) == guid ) then + total = total + 1 + end + end + return total + end]], +} + +-- Default tag events +Tags.defaultEvents = { + ["totem:timer"] = "SUF_TOTEM_TIMER", + ["rune:timer"] = "SUF_RUNE_TIMER", + ["hp:color"] = "UNIT_HEALTH 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_CONNECTION", + ["abscurhp"] = "UNIT_HEALTH UNIT_CONNECTION", + ["curmaxhp"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION", + ["absolutehp"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION", + ["smart:curmaxhp"] = "UNIT_HEALTH 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:eclipse"] = "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", + ["absmaxhp"] = "UNIT_MAXHEALTH", + ["maxpp"] = "SUF_POWERTYPE:CURRENT UNIT_MAXPOWER", + ["absmaxpp"] = "SUF_POWERTYPE:CURRENT UNIT_MAXPOWER", + ["missinghp"] = "UNIT_HEALTH 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_MAXHEALTH UNIT_CONNECTION", + ["perpp"] = "SUF_POWERTYPE:CURRENT UNIT_POWER_FREQUENT UNIT_MAXPOWER UNIT_CONNECTION", + ["status"] = "UNIT_HEALTH 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_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", + ["warlock:demonic:curpp"] = "UNIT_POWER_FREQUENT", + ["warlock:demonic:maxpp"] = "UNIT_MAXPOWER", + ["warlock:demonic:perpp"] = "UNIT_POWER_FREQUENT UNIT_MAXPOWER", + ["monk:chipoints"] = "SUF_POWERTYPE:LIGHT_FORCE UNIT_POWER_FREQUENT", + ["priest:shadoworbs"] = "SUF_POWERTYPE:SHADOW_ORBS UNIT_POWER_FREQUENT", +} + +-- Default update frequencies for tag updating, used if it's needed to override the update speed +-- or it can't be purely event based +Tags.defaultFrequents = { + ["afk"] = 1, + ["afk:time"] = 1, + ["status:time"] = 1, + ["pvp:time"] = 1, + ["scaled:threat"] = 1, + ["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 = { + ["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", + ["druid:eclipse"] = "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", + ["warlock:demonic:curpp"] = "classspec", + ["warlock:demonic:maxpp"] = "classspec", + ["warlock:demonic:perpp"] = "classspec", + ["monk:chipoints"] = "classspec", + ["monk:stagger"] = "classspec", + ["monk:abs:stagger"] = "classspec", + ["priest:shadoworbs"] = "classspec", + +} + +-- Default tag help +Tags.defaultHelp = { + ["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:eclipse"] = L["Current Eclipse, <0 is Lunar Energy and >0 is Solar Energy."], + ["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!"], + ["warlock:demonic:curpp"] = string.format(L["Works the same as [%s], but this is usedd to show Demonic Fury power for Demonology Warlocks."], "curpp"), + ["warlock:demonic:maxpp"] = string.format(L["Works the same as [%s], but this is usedd to show Demonic Fury power for Demonology Warlocks."], "maxpp"), + ["warlock:demonic:perpp"] = string.format(L["Works the same as [%s], but this is usedd to show Demonic Fury power for Demonology Warlocks."], "perpp"), + ["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."], + ["priest:shadoworbs"] = L["How many Shadow Orbs you have if you're Shadow"], + +} + +Tags.defaultNames = { + ["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:eclipse"] = L["Eclipse (Druid)"], + ["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"], + ["warlock:demonic:curpp"] = L["Current Demonic Fury (Short)"], + ["warlock:demonic:maxpp"] = L["Max Demonic Fury (Short)"], + ["warlock:demonic:perpp"] = L["Percent Demonic Fury"], + ["monk:chipoints"] = L["Chi Points"], + ["monk:stagger"] = L["Stagger (Monk)"], + ["monk:abs:stagger"] = L["Stagger (Monk/Absolute)"], + ["priest:shadoworbs"] = L["Shadow Orbs"], + +} + +-- List of event types +Tags.eventType = { + ["UNIT_POWER_FREQUENT"] = "power", + ["UNIT_MAXPOWER"] = "power", + ["UNIT_ABSORB_AMOUNT_CHANGED"] = "health", + ["UNIT_HEALTH"] = "health", + ["UNIT_MAXHEALTH"] = "health", + ["GROUP_ROSTER_UPDATE"] = "unitless", + ["RAID_TARGET_UPDATE"] = "unitless", + ["PLAYER_TARGET_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 +Tags.unitBlacklist = { + ["threat"] = "%w+target", +} + +-- 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 +local function loadAPIEvents() + if( Tags.APIEvents ) then return end + Tags.APIEvents = { + ["InCombatLockdown"] = "PLAYER_REGEN_ENABLED PLAYER_REGEN_DISABLED", + ["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", + ["UnitHealthMax"] = "UNIT_MAXHEALTH", + ["UnitPower%("] = "UNIT_POWER_FREQUENT", + ["UnitPowerMax"] = "UNIT_MAXPOWER", + ["UnitPowerType"] = "UNIT_DISPLAYPOWER", + ["UnitIsDead"] = "UNIT_HEALTH", + ["UnitIsGhost"] = "UNIT_HEALTH", + ["UnitIsConnected"] = "UNIT_HEALTH UNIT_CONNECTION", + ["UnitIsAFK"] = "PLAYER_FLAGS_CHANGED", + ["UnitIsDND"] = "PLAYER_FLAGS_CHANGED", + ["UnitIsPVP"] = "PLAYER_FLAGS_CHANGED UNIT_FACTION", + ["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", + ["GetAuraDataByIndex"] = "UNIT_AURA", + ["GetBuffDataByIndex"] = "UNIT_AURA", + ["GetDebuffDataByIndex"] = "UNIT_AURA", + ["UnitAuraBySpell"] = "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", + ["GetWatchedFactionInfo"] = "UPDATE_FACTION", + ["GetRuneCooldown"] = "RUNE_POWER_UPDATE", + ["GetRuneType"] = "RUNE_TYPE_UPDATE", + ["GetRaidTargetIndex"] = "RAID_TARGET_UPDATE", + ["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", + ["UnitThreatSituation"] = "UNIT_THREAT_SITUATION_UPDATE", + ["UnitDetailedThreatSituation"] = "UNIT_THREAT_SITUATION_UPDATE", + } +end + +-- Scan the actual tag code to find the events it uses +local alreadyScanned = {} +function Tags:IdentifyEvents(code, parentTag) + -- Already scanned this tag, prevents infinite recursion + if( parentTag and alreadyScanned[parentTag] ) then + return "" + -- Flagged that we already took care of this + elseif( parentTag ) then + alreadyScanned[parentTag] = true + else + for k in pairs(alreadyScanned) do alreadyScanned[k] = nil end + loadAPIEvents() + end + + -- Scan our function list to see what APIs are used + local eventList = "" + for func, events in pairs(self.APIEvents) do + if( string.match(code, func) ) then + eventList = eventList .. events .. " " + end + end + + -- Scan if they use any tags, if so we need to check them as well to see what content is used + for tag in string.gmatch(code, "tagFunc%.(%w+)%(") do + local c = ShadowUF.Tags.defaultTags[tag] or ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].func + eventList = eventList .. " " .. self:IdentifyEvents(c, tag) + end + + -- Remove any duplicate events + if( not parentTag ) then + local tagEvents = {} + for event in string.gmatch(string.trim(eventList), "%S+") do + tagEvents[event] = true + end + + eventList = "" + for event in pairs(tagEvents) do + eventList = eventList .. event .. " " + end + end + + -- And give them our nicely outputted data + return string.trim(eventList or "") +end + + +-- Checker function, makes sure tags are all happy +--[==[@debug@ +function Tags:Verify() + local fine = true + for tag, events in pairs(self.defaultEvents) do + if( not self.defaultTags[tag] ) then + print(string.format("Found event for %s, but no tag associated with it.", tag)) + fine = nil + end + end + + for tag, data in pairs(self.defaultTags) do + if( not self.defaultTags[tag] ) then + print(string.format("Found tag for %s, but no event associated with it.", tag)) + fine = nil + end + + if( not self.defaultHelp[tag] ) then + print(string.format("Found tag for %s, but no help text associated with it.", tag)) + fine = nil + end + + if( not self.defaultNames[tag] ) then + print(string.format("Found tag for %s, but no name associated with it.", tag)) + fine = nil + end + + if( not self.defaultCategories[tag] ) then + print(string.format("Found tag for %s, but no category associated with it.", tag)) + fine = nil + end + + local funct, msg = loadstring("return " .. data) + if( not funct and msg ) then + print(string.format("Failed to load tag %s.", tag)) + print(msg) + fine = nil + else + funct("player") + end + end + + if( fine ) then + print("Verified tags, everything is fine.") + end +end +--@end-debug@]==] diff --git a/modules/totems.lua b/modules/totems.lua index 2540a99c2..2e16939d9 100755 --- a/modules/totems.lua +++ b/modules/totems.lua @@ -1,210 +1,210 @@ -local Totems = {} -local totemColors = {} -local MAX_TOTEMS = MAX_TOTEMS - -local playerClass = select(2, UnitClass("player")) -if( playerClass == "DEATHKNIGHT" ) then - MAX_TOTEMS = 1 - -- Unholy DKs get rank 2 on level 29 which converts their ghoul into a proper pet. - local spec = (UnitLevel("player") < 29) and {1, 2, 3} or {1, 2} - ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Ghoul bar"], true, "DEATHKNIGHT", spec, 12) -elseif( playerClass == "DRUID" ) then - MAX_TOTEMS = 1 - ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Mushroom bar"], true, "DRUID", 4, 39) -elseif( playerClass == "MONK" ) then - MAX_TOTEMS = 1 - ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Statue bar"], true, "MONK", {1, 2}, 35) -elseif( playerClass == "MAGE" ) then - MAX_TOTEMS = 1 - ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Rune of Power bar"], true, "MAGE", {1, 2, 3}, 30) -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.totemBar) - totem:SetMinMaxValues(0, 1) - totem:SetValue(0) - 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) - else - totem:SetPoint("TOPLEFT", frame.totemBar, "TOPLEFT", 0, 0) - end - - table.insert(frame.totemBar.totems, totem) - end - - if( playerClass == "DEATHKNIGHT" ) then - totemColors[1] = ShadowUF.db.profile.classColors.PET - elseif( 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} - totemColors[3] = {r = 0, g = 0.4, b = 1} - totemColors[4] = {r = 0.90, g = 0.90, b = 0.90} - end - 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( 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) - local time = GetTime() - self:SetValue(self.endTime - time) - - 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, 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) - indicator:SetValue(indicator.endTime - GetTime()) - indicator:SetScript("OnUpdate", totemMonitor) - indicator:SetAlpha(1.0) - - totalActive = totalActive + 1 - - elseif( indicator.have ) then - indicator.have = nil - indicator:SetScript("OnUpdate", nil) - indicator:SetMinMaxValues(0, 1) - indicator:SetValue(0) - indicator.endTime = nil - end - - if( indicator.fontString ) then - indicator.fontString:UpdateTags() - end - end - - 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 +local Totems = {} +local totemColors = {} +local MAX_TOTEMS = MAX_TOTEMS + +local playerClass = select(2, UnitClass("player")) +if( playerClass == "DEATHKNIGHT" ) then + MAX_TOTEMS = 1 + -- Unholy DKs get rank 2 on level 29 which converts their ghoul into a proper pet. + local spec = (UnitLevel("player") < 29) and {1, 2, 3} or {1, 2} + ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Ghoul bar"], true, "DEATHKNIGHT", spec, 12) +elseif( playerClass == "DRUID" ) then + MAX_TOTEMS = 1 + ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Mushroom bar"], true, "DRUID", 4, 39) +elseif( playerClass == "MONK" ) then + MAX_TOTEMS = 1 + ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Statue bar"], true, "MONK", {1, 2}, 35) +elseif( playerClass == "MAGE" ) then + MAX_TOTEMS = 1 + ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Rune of Power bar"], true, "MAGE", {1, 2, 3}, 30) +-- 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.totemBar) + totem:SetMinMaxValues(0, 1) + totem:SetValue(0) + 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) + else + totem:SetPoint("TOPLEFT", frame.totemBar, "TOPLEFT", 0, 0) + end + + table.insert(frame.totemBar.totems, totem) + end + + if( playerClass == "DEATHKNIGHT" ) then + totemColors[1] = ShadowUF.db.profile.classColors.PET + elseif( 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} + totemColors[3] = {r = 0, g = 0.4, b = 1} + totemColors[4] = {r = 0.90, g = 0.90, b = 0.90} + end + 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( 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) + local time = GetTime() + self:SetValue(self.endTime - time) + + 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, 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) + indicator:SetValue(indicator.endTime - GetTime()) + indicator:SetScript("OnUpdate", totemMonitor) + indicator:SetAlpha(1.0) + + totalActive = totalActive + 1 + + elseif( indicator.have ) then + indicator.have = nil + indicator:SetScript("OnUpdate", nil) + indicator:SetMinMaxValues(0, 1) + indicator:SetValue(0) + indicator.endTime = nil + end + + if( indicator.fontString ) then + indicator.fontString:UpdateTags() + end + end + + 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 index 9e9da07e3..58d389b53 100755 --- a/modules/units.lua +++ b/modules/units.lua @@ -1,1583 +1,1591 @@ -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, 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 - local handler = self.fullUpdates[i] - handler[self.fullUpdates[i + 1]](handler, 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, 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 - - -- XXX: replace once 9.0 goes live, and we can cleanly remove events from tags and all modules - if event == "UNIT_HEALTH_FREQUENT" then - event = "UNIT_HEALTH" - end - - 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] and self.registeredEvents[event][handler] ) then - self.registeredEvents[event][handler] = nil - - local hasHandler - for _handler in pairs(self.registeredEvents[event]) do - hasHandler = true - break - end - - if( not hasHandler ) then - self:UnregisterEvent(event) - end - end -end - --- Register an event thats only called if it's for the actual unit -local function RegisterUnitEvent(self, event, handler, func) - unitEvents[event] = true - RegisterNormalEvent(self, event, handler, func) -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), func), 3) - return - end - - for i=1, #(self.fullUpdates), 2 do - local data = self.fullUpdates[i] - if( data == handler and self.fullUpdates[i + 1] == func ) then - return - end - end - - table.insert(self.fullUpdates, handler) - table.insert(self.fullUpdates, func) -end - -local function UnregisterUpdateFunc(self, handler, func) - for i=#(self.fullUpdates), 1, -1 do - if( self.fullUpdates[i] == handler and self.fullUpdates[i + 1] == func ) then - table.remove(self.fullUpdates, i + 1) - table.remove(self.fullUpdates, i) - end - end -end - --- Used when something is disabled, removes all callbacks etc to it -local function UnregisterAll(self, handler) - for i=#(self.fullUpdates), 1, -1 do - if( self.fullUpdates[i] == handler ) then - table.remove(self.fullUpdates, i + 1) - table.remove(self.fullUpdates, i) - end - end - - for event, list in pairs(self.registeredEvents) do - 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 - --- Handles setting alphas in a way so combat fader and range checker don't override each other -local function DisableRangeAlpha(self, toggle) - self.disableRangeAlpha = toggle - - if( not toggle and self.rangeAlpha ) then - self:SetAlpha(self.rangeAlpha) - end -end - -local function SetRangeAlpha(self, alpha) - if( not self.disableRangeAlpha ) then - self:SetAlpha(alpha) - else - self.rangeAlpha = 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 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 - end -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) - Units:CheckUnitStatus(self) -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 - if( self.isUnitVolatile or self:IsShown() ) then - self.unitGUID = nil - end -end - --- Deal with enabling modules inside a zone -local function SetVisibility(self) - local layoutUpdate - 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 - if( module.OnEnable and module.OnDisable and ShadowUF.db.profile.units[self.unitType][module.moduleKey] ) then - local key = module.moduleKey - local enabled = ShadowUF.db.profile.units[self.unitType][key].enabled - - -- These modules have mini-modules, the entire module should be enabled if at least one is enabled, and disabled if all are disabled - if( key == "auras" or key == "indicators" or key == "highlight" ) then - enabled = nil - for _, option in pairs(ShadowUF.db.profile.units[self.unitType][key]) do - if( type(option) == "table" and option.enabled or option == true ) then - enabled = true - break - end - end - end - - -- In an actual zone, check to see if we have an override for the zone - if( instanceType ~= "none" ) then - if( ShadowUF.db.profile.visibility[instanceType][self.unitType .. key] == false ) then - enabled = nil - elseif( ShadowUF.db.profile.visibility[instanceType][self.unitType .. key] == true ) then - enabled = true - end - end - - -- 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) - layoutUpdate = true - elseif( self.visibility[key] and not enabled ) then - module:OnDisable(self) - layoutUpdate = true - end - - self.visibility[key] = enabled or nil - end - end - - -- We had a module update, force a full layout update of this frame - if( layoutUpdate ) then - ShadowUF.Layout:Load(self) - end -end - --- Vehicles do not always return their data right away, a pure OnUpdate check seems to be the most accurate unfortunately -local function checkVehicleData(self, elapsed) - self.timeElapsed = self.timeElapsed + elapsed - if( self.timeElapsed >= 0.50 ) then - self.timeElapsed = 0 - 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) or not UnitHasVehiclePlayerFrameUI(self.unitOwner) ) then - self.timeElapsed = nil - self.dataAttempts = nil - self:SetScript("OnUpdate", nil) - - self.inVehicle = false - self.unit = self.unitOwner - self:FullUpdate() - - -- Got data, stop checking and do a full frame update - elseif( UnitIsConnected(self.unit) or UnitHealthMax(self.unit) > 0 ) then - self.timeElapsed = nil - self.dataAttempts = nil - self:SetScript("OnUpdate", nil) - - self.unitGUID = UnitGUID(self.unit) - self:FullUpdate() - end - end -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 UnitHasVehiclePlayerFrameUI(frame.unitOwner) and not ShadowUF.db.profile.units[frame.unitType].disableVehicle ) then - frame.inVehicle = true - frame.unit = frame.vehicleUnit - - if( not UnitIsConnected(frame.unit) or UnitHealthMax(frame.unit) == 0 ) then - frame.timeElapsed = 0 - frame.dataAttempts = 0 - frame:SetScript("OnUpdate", checkVehicleData) - else - frame.unitGUID = UnitGUID(frame.unit) - frame:FullUpdate() - end - - -- Was in a vehicle, no longer has a UI - 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 -end - --- Handles checking for GUID changes for doing a full update, this fixes frames sometimes showing the wrong unit when they change -function Units:CheckUnitStatus(frame) - local guid = frame.unit and UnitGUID(frame.unit) - if( guid ~= frame.unitGUID ) then - frame.unitGUID = guid - - if( guid ) then - frame:FullUpdate() - end - end -end - - --- The argument from UNIT_PET is the pets owner, so the player summoning a new pet gets "player", party1 summoning a new pet gets "party1" and so on -function Units:CheckPetUnitUpdated(frame, event, unit) - if( unit == frame.unitRealOwner and UnitExists(frame.unit) ) then - frame.unitGUID = UnitGUID(frame.unit) - frame:FullUpdate() - end -end - --- When raid1, raid2, raid3 are in a group with each other and raid1 or raid2 are in a vehicle and get kicked --- OnAttributeChanged won't do anything because the frame is already setup, however, the active unit is non-existant --- while the primary unit is. So if we see they're in a vehicle with this case, we force the full update to get the vehicle change -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 = UnitGUID(frame.unit) - frame:FullUpdate() - else - frame.unitGUID = UnitGUID(frame.unit) - frame:FullUpdate() - 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 - - for child, parentUnit in pairs(childUnits) do - if( parentUnit == self.unitType and ShadowUF.db.profile.units[child].enabled ) then - Units:LoadChildUnit(self, child, self.unitID) - end - end -end - -local OnAttributeChanged -local function updateChildUnits(...) - if( not ShadowUF.db.profile.locked ) then return end - - for i=1, select("#", ...) do - local child = select(i, ...) - if( child.parent and child.unitType ) then - OnAttributeChanged(child, "unit", SecureButton_GetModifiedUnit(child)) - end - 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 --- unitType = Unitid minus numbers in it, used for configuration --- unitRealType = The actual unit type, if party is shown in raid this will be "party" while unitType is still "raid" --- unitOwner = Always the units owner even when unit changes due to vehicles --- 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 - 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.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[configUnit] = self - end - - frameList[self] = true - - if( self.hasChildren ) then - updateChildUnits(self:GetChildren()) - end - - -- Create child frames - createChildUnits(self) - - -- Unit already exists but unitid changed, update the info we got on them - -- 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 - - self.unitInitialized = true - - -- Add to Clique - 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 - self:RegisterNormalEvent("UNIT_ENTERED_VEHICLE", Units, "CheckVehicleStatus") - self:RegisterNormalEvent("UNIT_EXITED_VEHICLE", Units, "CheckVehicleStatus") - 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 - self:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units.player.disableVehicle) - else - self:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units.party.disableVehicle) - end - - -- Logged out in a vehicle - 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", 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 - self:Hide() - -- Unit exists, show it - else - self:Show() - end - end - ]]) - RegisterStateDriver(self, "vehicleupdated", string.format("[target=%s, nohelp, noharm] vehicle; pet", self.unitRealOwner, self.unit)) - - -- Automatically do a full update on target change - 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 - -- this should not get called in combat, but just in case make sure we are not actually in combat - if not InCombatLockdown() then - self:SetAttribute("toggleForVehicle", true) - end - - -- Force a full update when the player is alive to prevent freezes when releasing in a zone that forces a ressurect (naxx/tk/etc) - self:RegisterNormalEvent("PLAYER_ALIVE", self, "FullUpdate") - - -- full update when the player targetable changes, ie. during cutscenes or transports - self:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "FullUpdate") - - -- Update boss - elseif( self.unitType == "boss" ) then - 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("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("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 - 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") - elseif( self.unit == "targettarget" or self.unit == "targettargettarget" ) then - self.unitRealOwner = "target" - self:RegisterNormalEvent("PLAYER_TARGET_CHANGED", Units, "CheckUnitStatus") - end - - self:RegisterNormalEvent("UNIT_TARGET", Units, "CheckPetUnitUpdated") - end - - self:SetVisibility() - Units:CheckUnitStatus(self) -end - -Units.OnAttributeChanged = OnAttributeChanged - -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) - - 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,PingableUnitFrameTemplate,BackdropTemplate") or ("SUF_SecureUnitTemplate,PingableUnitFrameTemplate,BackdropTemplate") - --- 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( self.OnEnter ) then - self:OnEnter() - end -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 - -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 - frame.UnregisterAll = UnregisterAll - frame.UnregisterSingleEvent = UnregisterEvent - 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:HookScript("OnAttributeChanged", OnAttributeChanged) - frame:SetScript("OnEvent", OnEvent) - frame:HookScript("OnEnter", OnEnter) - frame:HookScript("OnLeave", OnLeave) - frame:SetScript("OnShow", OnShow) - frame:SetScript("OnHide", OnHide) - - 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 - --- Reload a header completely -function Units:ReloadHeader(type) - if( ShadowUF.db.profile.units[type].frameSplit ) then - if( headerFrames.raid ) then - self:InitializeFrame("raid") - else - self:SetHeaderAttributes(headerFrames.raidParent, type) - ShadowUF.Layout:AnchorFrame(UIParent, headerFrames.raidParent, ShadowUF.db.profile.positions[type]) - ShadowUF:FireModuleEvent("OnLayoutReload", type) - end - elseif( type == "raid" and not ShadowUF.db.profile.units[type].frameSplit and headerFrames.raidParent ) then - self:InitializeFrame("raid") - - elseif( headerFrames[type] ) then - self:SetHeaderAttributes(headerFrames[type], type) - ShadowUF.Layout:AnchorFrame(UIParent, headerFrames[type], ShadowUF.db.profile.positions[type]) - ShadowUF:FireModuleEvent("OnLayoutReload", type) - end -end - -function Units:PositionHeaderChildren(frame) - local point = frame:GetAttribute("point") or "TOP" - local relativePoint = ShadowUF.Layout:GetRelativeAnchor(point) - - if( #(frame.children) == 0 ) then return end - - local xMod, yMod = math.abs(frame:GetAttribute("xMod")), math.abs(frame:GetAttribute("yMod")) - local x = frame:GetAttribute("xOffset") or 0 - local y = frame:GetAttribute("yOffset") or 0 - - for id, child in pairs(frame.children) do - if( id > 1 ) then - frame.children[id]:ClearAllPoints() - frame.children[id]:SetPoint(point, frame.children[id - 1], relativePoint, xMod * x, yMod * y) - else - frame.children[id]:ClearAllPoints() - frame.children[id]:SetPoint(point, frame, point, 0, 0) - end - end -end - -function Units:CheckGroupVisibility() - if( not ShadowUF.db.profile.locked ) then return end - local raid = headerFrames.raid and not ShadowUF.db.profile.units.raid.frameSplit and headerFrames.raid or headerFrames.raidParent - local party = headerFrames.party - if( party ) then - party:SetAttribute("showParty", ( not ShadowUF.db.profile.units.raid.showParty or not ShadowUF.enabledUnits.raid ) and true or false) - party:SetAttribute("showPlayer", ShadowUF.db.profile.units.party.showPlayer) - end - - if( raid and party ) then - raid:SetAttribute("showParty", not party:GetAttribute("showParty")) - raid:SetAttribute("showPlayer", party:GetAttribute("showPlayer")) - end -end - -function Units:SetHeaderAttributes(frame, type) - local config = ShadowUF.db.profile.units[type] - local xMod = config.attribPoint == "LEFT" and 1 or config.attribPoint == "RIGHT" and -1 or 0 - local yMod = config.attribPoint == "TOP" and -1 or config.attribPoint == "BOTTOM" and 1 or 0 - local widthMod = (config.attribPoint == "LEFT" or config.attribPoint == "RIGHT") and MEMBERS_PER_RAID_GROUP or 1 - local heightMod = (config.attribPoint == "TOP" or config.attribPoint == "BOTTOM") and MEMBERS_PER_RAID_GROUP or 1 - - frame:SetAttribute("point", config.attribPoint) - frame:SetAttribute("sortMethod", config.sortMethod) - frame:SetAttribute("sortDir", config.sortOrder) - - frame:SetAttribute("xOffset", config.offset * xMod) - frame:SetAttribute("yOffset", config.offset * yMod) - frame:SetAttribute("xMod", xMod) - frame:SetAttribute("yMod", yMod) - - -- Split up raid frame groups - if( config.frameSplit and type == "raid" ) then - local anchorPoint, relativePoint, xModRow, yModRow = ShadowUF.Layout:GetSplitRelativeAnchor(config.attribPoint, config.attribAnchorPoint) - local columnPoint, xColMod, yColMod = ShadowUF.Layout:GetRelativeAnchor(config.attribPoint) - - local lastHeader = frame - for id=1, 8 do - local childHeader = headerFrames["raid" .. id] - if( childHeader ) then - childHeader:SetAttribute("showRaid", ShadowUF.db.profile.locked and true) - - childHeader:SetAttribute("minWidth", config.width * widthMod) - childHeader:SetAttribute("minHeight", config.height * heightMod) - - if( childHeader ~= frame ) then - childHeader:SetAttribute("point", config.attribPoint) - childHeader:SetAttribute("sortMethod", config.sortMethod) - childHeader:SetAttribute("sortDir", config.sortOrder) - childHeader:SetAttribute("showPlayer", nil) - childHeader:SetAttribute("showParty", nil) - - childHeader:SetAttribute("xOffset", frame:GetAttribute("xOffset")) - childHeader:SetAttribute("yOffset", frame:GetAttribute("yOffset")) - - childHeader:ClearAllPoints() - if( (id - 1) % config.groupsPerRow == 0 ) then - local x = config.groupSpacing * xColMod - local y = config.groupSpacing * yColMod - - -- When we're anchoring a new column to the bottom of naother one, the height will mess it up - -- if what we anchored to isn't full, by anchoring it to the top instead will get a consistent result - local point = columnPoint - if( point == "BOTTOM" ) then - point = config.attribPoint - x = x + (config.height * 5) * xColMod - y = y + (config.height * 5) * yColMod - end - - childHeader:SetPoint(config.attribPoint, headerFrames["raid" .. id - config.groupsPerRow], point, x, y) - else - childHeader:SetPoint(anchorPoint, lastHeader, relativePoint, config.columnSpacing * xModRow, config.columnSpacing * yModRow) - end - - 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 - - -- Normal raid, ma or mt - elseif( type == "raidpet" or type == "raid" or type == "mainassist" or type == "maintank" ) then - local filter - if( config.filters ) then - for id, enabled in pairs(config.filters) do - if( enabled ) then - if( filter ) then - filter = filter .. "," .. id - else - filter = id - end - end - end - else - filter = config.groupFilter - end - - frame:SetAttribute("showRaid", ShadowUF.db.profile.locked and true) - frame:SetAttribute("maxColumns", config.maxColumns) - frame:SetAttribute("unitsPerColumn", config.unitsPerColumn) - 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,DEMONHUNTER,DRUID,HUNTER,MAGE,PALADIN,PRIEST,ROGUE,SHAMAN,WARLOCK,WARRIOR,MONK,EVOKER") - 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" 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 - elseif( type == "party" ) then - frame:SetAttribute("maxColumns", math.ceil((config.showPlayer and 5 or 4) / config.unitsPerColumn)) - 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 - - if( type == "raid" ) then - self:CheckGroupVisibility() - - 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 -function Units:LoadUnit(unit) - -- Already be loaded, just enable - if( unitFrames[unit] ) then - RegisterUnitWatch(unitFrames[unit], unitFrames[unit].hasStateWatch) - return - end - - local frame = self:CreateUnit("Button", "SUFUnit" .. unit, petBattleFrame, "SecureUnitButtonTemplate,PingableUnitFrameTemplate,BackdropTemplate") - frame:SetAttribute("unit", unit) - frame.hasStateWatch = unit == "pet" - - -- Annd 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, petBattleFrame, "SecureGroupHeaderTemplate") - frame:SetAttribute("template", unitButtonTemplate) - frame:SetAttribute("initial-unitWatch", true) - frame:SetAttribute("showRaid", true) - frame:SetAttribute("groupFilter", id) - 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 - - frame:Show() - - if( not headerFrames.raidParent or headerFrames.raidParent.groupID > id ) then - headerFrames.raidParent = frame - end - - setupRaidStateMonitor(id, frame) - - elseif( frame ) then - frame:Hide() - end - end - - if( headerFrames.raidParent ) then - self:SetHeaderAttributes(headerFrames.raidParent, type) - ShadowUF.Layout:AnchorFrame(UIParent, headerFrames.raidParent, ShadowUF.db.profile.positions.raid) - end -end - --- Load a header unit, party or raid -function Units:LoadGroupHeader(type) - -- Already created, so just reshow and we out - if( headerFrames[type] ) then - headerFrames[type]:Show() - - 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, petBattleFrame, type == "raidpet" and "SecureGroupPetHeaderTemplate" or "SecureGroupHeaderTemplate") - headerFrames[type] = headerFrame - - self:SetHeaderAttributes(headerFrame, type) - - headerFrame:SetAttribute("template", unitButtonTemplate) - headerFrame:SetAttribute("initial-unitWatch", true) - headerFrame:SetAttribute("initialConfigFunction", secureInitializeUnit) - - headerFrame.initialConfigFunction = initializeUnit - headerFrame.isHeaderFrame = true - headerFrame.unitType = type - 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.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 - - if( self:GetAttribute("hideAnyRaid") and ( self:GetAttribute("state-raidmonitor") == "raid1" or self:GetAttribute("state-raidmonitor") == "raid6" ) ) then - self:GetFrameRef("partyHeader"):Hide() - elseif( self:GetAttribute("hideSemiRaid") and self:GetAttribute("state-raidmonitor") == "raid6" ) then - self:GetFrameRef("partyHeader"):Hide() - else - self:GetFrameRef("partyHeader"):Show() - end - ]]) - 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 _, f in pairs(headerFrames) do - if( f.splitParent == type ) then - f: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, 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 - headerFrame:SetScript("OnAttributeChanged", function(frame, key, value) - if( key == "childChanged" and value and frame.children[value] and frame:IsVisible() ) then - frame.children[value]:FullUpdate() - end - end) - end - - for id, unit in pairs(ShadowUF[type .. "Units"]) do - local frame = self:CreateUnit("Button", "SUFHeader" .. type .. "UnitButton" .. id, headerFrame, "SecureUnitButtonTemplate,PingableUnitFrameTemplate,BackdropTemplate") - 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 - stateMonitor:WrapScript(frame, "OnAttributeChanged", [[ - if( name == "state-unitexists" ) then - local parent = self:GetParent() - if( value and self:GetAttribute("unitDisappeared") ) then - parent:SetAttribute("childChanged", self:GetAttribute("unitID")) - self:SetAttribute("unitDisappeared", nil) - elseif( not value and not self:GetAttribute("unitDisappeared") ) then - self:SetAttribute("unitDisappeared", true) - end - - if( value ) then - self:Show() - end - end - ]]) - else - 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) -function Units:LoadChildUnit(parent, type, id) - if( InCombatLockdown() ) then - if( not queuedCombat[parent:GetName() .. type] ) then - queuedCombat[parent:GetName() .. type] = {parent = parent, type = type, id = id} - end - return - else - -- This is a bit confusing to write down, but just in case I forget: - -- It's possible theres a bug where you have a frame skip creating it's child because it thinks one was already created, but the one that was created is actually associated to another parent. What would need to be changed is it checks if the frame has the parent set to it and it's the same unit type before returning, not that the units match. - for frame in pairs(frameList) do - if( frame.unitType == type and frame.parent == parent ) then - RegisterUnitWatch(frame, frame.hasStateWatch) - return - end - end - end - - 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,PingableUnitFrameTemplate,BackdropTemplate") - frame.unitType = type - frame.parent = parent - frame.isChildUnit = true - frame.hasStateWatch = type == "partypet" - frame:SetFrameStrata("LOW") - frame:SetAttribute("useparent-unit", true) - frame:SetAttribute("unitsuffix", suffix) - OnAttributeChanged(frame, "unit", SecureButton_GetModifiedUnit(frame)) - frameList[frame] = true - - RegisterUnitWatch(frame, frame.hasStateWatch) - ShadowUF.Layout:AnchorFrame(parent, frame, ShadowUF.db.profile.positions[type]) -end - --- Initialize units -function Units:InitializeFrame(type) - if( type == "raid" and ShadowUF.db.profile.units[type].frameSplit ) then - self:LoadSplitGroupHeader(type) - elseif( type == "party" or type == "raid" or type == "maintank" or type == "mainassist" or type == "raidpet" ) then - self:LoadGroupHeader(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 -end - --- Uninitialize units -function Units:UninitializeFrame(type) - 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 - if( headerFrame.splitParent == type ) then - headerFrame:Hide() - end - end - elseif( headerFrames[type] ) then - headerFrames[type]:Hide() - - 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 - else - -- Disable all frames of this type - for frame in pairs(frameList) do - if( frame.unitType == type ) then - UnregisterUnitWatch(frame) - frame:SetAttribute("state-unitexits", false) - frame:Hide() - end - end - end -end - --- Profile changed, reload units -function Units:ProfileChanged() - -- Reset the anchors for all frames to prevent X is dependant on Y - for frame in pairs(frameList) do - if( frame.unit ) then - frame:ClearAllPoints() - end - end - - for frame in pairs(frameList) do - if( frame.unit and ShadowUF.db.profile.units[frame.unitType].enabled ) then - -- Force all enabled modules to disable - for key, module in pairs(ShadowUF.modules) do - if( frame[key] and frame.visibility[key] ) then - frame.visibility[key] = nil - module:OnDisable(frame) - end - end - - -- Now enable whatever we need to - frame:SetVisibility() - ShadowUF.Layout:Load(frame) - frame:FullUpdate() - end - end - - for _, frame in pairs(headerFrames) do - if( ShadowUF.db.profile.units[frame.unitType].enabled ) then - self:ReloadHeader(frame.unitType) - end - end -end - --- Small helper function for creating bars with -function Units:CreateBar(parent) - local bar = CreateFrame("StatusBar", nil, parent) - bar:SetFrameLevel(parent.topFrameLevel or 5) - bar.parent = parent - - bar.background = bar:CreateTexture(nil, "BORDER") - bar.background:SetHeight(1) - bar.background:SetWidth(1) - bar.background:SetAllPoints(bar) - bar.background:SetHorizTile(false) - - 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) - if( InCombatLockdown() ) then - queueZoneCheck = force and 2 or 1 - return - end - - -- CanHearthAndResurrectFromArea() returns true for world pvp areas, according to BattlefieldFrame.lua - 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 - - ShadowUF:LoadUnits() - for frame in pairs(frameList) do - if( frame.unit and ShadowUF.db.profile.units[frame.unitType].enabled ) then - frame:SetVisibility() - - -- Auras are enabled so will need to check if the filter has to change - if( frame.visibility.auras ) then - ShadowUF.modules.auras:UpdateFilter(frame) - end - - if( UnitExists(frame.unit) ) then - frame:FullUpdate() - end - end - 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"}, [213634] = {"Disease"}}, - ["PALADIN"] = {[4987] = {"Poison", "Disease", "Magic"}, [213644] = {"Poison", "Disease"}}, - ["SHAMAN"] = {[77130] = {"Curse", "Magic"}, [51886] = {"Curse"}, [383013] = {"Poison"}}, - ["MONK"] = {[115450] = {"Poison", "Disease", "Magic"}, [218164] = {"Poison", "Disease"}}, - ["MAGE"] = {[475] = {"Curse"}}, - ["WARLOCK"] = {[89808] = {"Magic"}}, - ["EVOKER"] = {[365585] = {"Poison"}, [360823] = {"Magic", "Poison"}, [374251] = {"Poison", "Curse", "Disease"}} -} - -curableSpells = curableSpells[playerClass] - -local function checkCurableSpells() - if( not curableSpells ) then return end - - table.wipe(Units.canCure) - - for spellID, cures in pairs(curableSpells) do - if( IsPlayerSpell(spellID) or IsSpellKnown(spellID, true) ) 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 - -- really having left the zone - if( event == "ZONE_CHANGED_NEW_AREA" ) then - if( UnitIsDeadOrGhost("player") ) then - self:RegisterEvent("PLAYER_UNGHOST") - else - self:UnregisterEvent("PLAYER_UNGHOST") - Units:CheckPlayerZone() - 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" or event == "UNIT_PET" or event == "SPELLS_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") - self:RegisterEvent("SPELLS_CHANGED") - if( playerClass == "WARLOCK" ) then - self:RegisterUnitEvent("UNIT_PET", "player", nil) - end - - -- 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 - for _, queue in pairs(queuedCombat) do - Units:LoadChildUnit(queue.parent, queue.type, queue.id) - end - - table.wipe(queuedCombat) - - if( queueZoneCheck ) then - Units:CheckPlayerZone(queueZoneCheck == 2 and true) - queueZoneCheck = nil - end - end -end) +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, 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") +local GetSpecialization = C_SpecializationInfo.GetSpecialization or _G.GetSpecialization + +-- 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 + local handler = self.fullUpdates[i] + handler[self.fullUpdates[i + 1]](handler, 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, 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 + + -- XXX: replace once 9.0 goes live, and we can cleanly remove events from tags and all modules + if event == "UNIT_HEALTH_FREQUENT" then + event = "UNIT_HEALTH" + end + + 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] and self.registeredEvents[event][handler] ) then + self.registeredEvents[event][handler] = nil + + local hasHandler + for _handler in pairs(self.registeredEvents[event]) do + hasHandler = true + break + end + + if( not hasHandler ) then + self:UnregisterEvent(event) + end + end +end + +-- Register an event thats only called if it's for the actual unit +local function RegisterUnitEvent(self, event, handler, func) + unitEvents[event] = true + RegisterNormalEvent(self, event, handler, func) +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), func), 3) + return + end + + for i=1, #(self.fullUpdates), 2 do + local data = self.fullUpdates[i] + if( data == handler and self.fullUpdates[i + 1] == func ) then + return + end + end + + table.insert(self.fullUpdates, handler) + table.insert(self.fullUpdates, func) +end + +local function UnregisterUpdateFunc(self, handler, func) + for i=#(self.fullUpdates), 1, -1 do + if( self.fullUpdates[i] == handler and self.fullUpdates[i + 1] == func ) then + table.remove(self.fullUpdates, i + 1) + table.remove(self.fullUpdates, i) + end + end +end + +-- Used when something is disabled, removes all callbacks etc to it +local function UnregisterAll(self, handler) + for i=#(self.fullUpdates), 1, -1 do + if( self.fullUpdates[i] == handler ) then + table.remove(self.fullUpdates, i + 1) + table.remove(self.fullUpdates, i) + end + end + + for event, list in pairs(self.registeredEvents) do + 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 + +-- Handles setting alphas in a way so combat fader and range checker don't override each other +local function DisableRangeAlpha(self, toggle) + self.disableRangeAlpha = toggle + + if( not toggle and self.rangeAlpha ) then + self:SetAlpha(self.rangeAlpha) + end +end + +local function SetRangeAlpha(self, alpha) + if( not self.disableRangeAlpha ) then + self:SetAlpha(alpha) + else + self.rangeAlpha = 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 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 + end +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) + Units:CheckUnitStatus(self) +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 + if( self.isUnitVolatile or self:IsShown() ) then + self.unitGUID = nil + end +end + +-- Deal with enabling modules inside a zone +local function SetVisibility(self) + local layoutUpdate + 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 + if( module.OnEnable and module.OnDisable and ShadowUF.db.profile.units[self.unitType][module.moduleKey] ) then + local key = module.moduleKey + local enabled = ShadowUF.db.profile.units[self.unitType][key].enabled + + -- These modules have mini-modules, the entire module should be enabled if at least one is enabled, and disabled if all are disabled + if( key == "auras" or key == "indicators" or key == "highlight" ) then + enabled = nil + for _, option in pairs(ShadowUF.db.profile.units[self.unitType][key]) do + if( type(option) == "table" and option.enabled or option == true ) then + enabled = true + break + end + end + end + + -- In an actual zone, check to see if we have an override for the zone + if( instanceType ~= "none" ) then + if( ShadowUF.db.profile.visibility[instanceType][self.unitType .. key] == false ) then + enabled = nil + elseif( ShadowUF.db.profile.visibility[instanceType][self.unitType .. key] == true ) then + enabled = true + end + end + + -- 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) + layoutUpdate = true + elseif( self.visibility[key] and not enabled ) then + module:OnDisable(self) + layoutUpdate = true + end + + self.visibility[key] = enabled or nil + end + end + + -- We had a module update, force a full layout update of this frame + if( layoutUpdate ) then + ShadowUF.Layout:Load(self) + end +end + +-- Vehicles do not always return their data right away, a pure OnUpdate check seems to be the most accurate unfortunately +local function checkVehicleData(self, elapsed) + self.timeElapsed = self.timeElapsed + elapsed + if( self.timeElapsed >= 0.50 ) then + self.timeElapsed = 0 + 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) or not UnitHasVehiclePlayerFrameUI(self.unitOwner) ) then + self.timeElapsed = nil + self.dataAttempts = nil + self:SetScript("OnUpdate", nil) + + self.inVehicle = false + self.unit = self.unitOwner + self:FullUpdate() + + -- Got data, stop checking and do a full frame update + elseif( UnitIsConnected(self.unit) or UnitHealthMax(self.unit) > 0 ) then + self.timeElapsed = nil + self.dataAttempts = nil + self:SetScript("OnUpdate", nil) + + self.unitGUID = UnitGUID(self.unit) + self:FullUpdate() + end + end +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 UnitHasVehiclePlayerFrameUI(frame.unitOwner) and not ShadowUF.db.profile.units[frame.unitType].disableVehicle ) then + frame.inVehicle = true + frame.unit = frame.vehicleUnit + + if( not UnitIsConnected(frame.unit) or UnitHealthMax(frame.unit) == 0 ) then + frame.timeElapsed = 0 + frame.dataAttempts = 0 + frame:SetScript("OnUpdate", checkVehicleData) + else + frame.unitGUID = UnitGUID(frame.unit) + frame:FullUpdate() + end + + -- Was in a vehicle, no longer has a UI + 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 +end + +-- Handles checking for GUID changes for doing a full update, this fixes frames sometimes showing the wrong unit when they change +function Units:CheckUnitStatus(frame) + local guid = frame.unit and UnitGUID(frame.unit) + if( guid ~= frame.unitGUID ) then + frame.unitGUID = guid + + if( guid ) then + frame:FullUpdate() + end + end +end + + +-- The argument from UNIT_PET is the pets owner, so the player summoning a new pet gets "player", party1 summoning a new pet gets "party1" and so on +function Units:CheckPetUnitUpdated(frame, event, unit) + if( unit == frame.unitRealOwner and UnitExists(frame.unit) ) then + frame.unitGUID = UnitGUID(frame.unit) + frame:FullUpdate() + end +end + +-- When raid1, raid2, raid3 are in a group with each other and raid1 or raid2 are in a vehicle and get kicked +-- OnAttributeChanged won't do anything because the frame is already setup, however, the active unit is non-existant +-- while the primary unit is. So if we see they're in a vehicle with this case, we force the full update to get the vehicle change +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 = UnitGUID(frame.unit) + frame:FullUpdate() + else + frame.unitGUID = UnitGUID(frame.unit) + frame:FullUpdate() + 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 + + for child, parentUnit in pairs(childUnits) do + if( parentUnit == self.unitType and ShadowUF.db.profile.units[child].enabled ) then + Units:LoadChildUnit(self, child, self.unitID) + end + end +end + +local OnAttributeChanged +local function updateChildUnits(...) + if( not ShadowUF.db.profile.locked ) then return end + + for i=1, select("#", ...) do + local child = select(i, ...) + if( child.parent and child.unitType ) then + OnAttributeChanged(child, "unit", SecureButton_GetModifiedUnit(child)) + end + 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 +-- unitType = Unitid minus numbers in it, used for configuration +-- unitRealType = The actual unit type, if party is shown in raid this will be "party" while unitType is still "raid" +-- unitOwner = Always the units owner even when unit changes due to vehicles +-- 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 + 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.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[configUnit] = self + end + + frameList[self] = true + + if( self.hasChildren ) then + updateChildUnits(self:GetChildren()) + end + + -- Create child frames + createChildUnits(self) + + -- Unit already exists but unitid changed, update the info we got on them + -- 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 + + self.unitInitialized = true + + -- Add to Clique + 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 + self:RegisterNormalEvent("UNIT_ENTERED_VEHICLE", Units, "CheckVehicleStatus") + self:RegisterNormalEvent("UNIT_EXITED_VEHICLE", Units, "CheckVehicleStatus") + 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 + self:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units.player.disableVehicle) + else + self:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units.party.disableVehicle) + end + + -- Logged out in a vehicle + 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", 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 + self:Hide() + -- Unit exists, show it + else + self:Show() + end + end + ]]) + RegisterStateDriver(self, "vehicleupdated", string.format("[target=%s, nohelp, noharm] vehicle; pet", self.unitRealOwner, self.unit)) + + -- Automatically do a full update on target change + 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 + -- this should not get called in combat, but just in case make sure we are not actually in combat + if not InCombatLockdown() then + self:SetAttribute("toggleForVehicle", true) + end + + -- Force a full update when the player is alive to prevent freezes when releasing in a zone that forces a ressurect (naxx/tk/etc) + self:RegisterNormalEvent("PLAYER_ALIVE", self, "FullUpdate") + + -- full update when the player targetable changes, ie. during cutscenes or transports + self:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "FullUpdate") + + -- Update boss + elseif( self.unitType == "boss" ) then + 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("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("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 + 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") + elseif( self.unit == "targettarget" or self.unit == "targettargettarget" ) then + self.unitRealOwner = "target" + self:RegisterNormalEvent("PLAYER_TARGET_CHANGED", Units, "CheckUnitStatus") + end + + self:RegisterNormalEvent("UNIT_TARGET", Units, "CheckPetUnitUpdated") + end + + self:SetVisibility() + Units:CheckUnitStatus(self) +end + +Units.OnAttributeChanged = OnAttributeChanged + +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) + + 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 (BackdropTemplateMixin and "ClickCastUnitTemplate,SUF_SecureUnitTemplate,BackdropTemplate" or "ClickCastUnitTemplate,SUF_SecureUnitTemplate") or (BackdropTemplateMixin and "SUF_SecureUnitTemplate,BackdropTemplate" 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( self.OnEnter ) then + self:OnEnter() + end +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 + +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 + frame.UnregisterAll = UnregisterAll + frame.UnregisterSingleEvent = UnregisterEvent + 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:HookScript("OnAttributeChanged", OnAttributeChanged) + frame:SetScript("OnEvent", OnEvent) + frame:HookScript("OnEnter", OnEnter) + frame:HookScript("OnLeave", OnLeave) + frame:SetScript("OnShow", OnShow) + frame:SetScript("OnHide", OnHide) + + frame.OnEnter = SUF_OnEnter + frame.OnLeave = SUF_OnLeave + + if (PingUtil) then + frame:SetToplevel(true) + frame:SetAttribute("ping-receiver", true) + frame.IsPingable = true + Mixin(frame, PingableType_UnitFrameMixin) + end + + 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 + +-- Reload a header completely +function Units:ReloadHeader(type) + if( ShadowUF.db.profile.units[type].frameSplit ) then + if( headerFrames.raid ) then + self:InitializeFrame("raid") + else + self:SetHeaderAttributes(headerFrames.raidParent, type) + ShadowUF.Layout:AnchorFrame(UIParent, headerFrames.raidParent, ShadowUF.db.profile.positions[type]) + ShadowUF:FireModuleEvent("OnLayoutReload", type) + end + elseif( type == "raid" and not ShadowUF.db.profile.units[type].frameSplit and headerFrames.raidParent ) then + self:InitializeFrame("raid") + + elseif( headerFrames[type] ) then + self:SetHeaderAttributes(headerFrames[type], type) + ShadowUF.Layout:AnchorFrame(UIParent, headerFrames[type], ShadowUF.db.profile.positions[type]) + ShadowUF:FireModuleEvent("OnLayoutReload", type) + end +end + +function Units:PositionHeaderChildren(frame) + local point = frame:GetAttribute("point") or "TOP" + local relativePoint = ShadowUF.Layout:GetRelativeAnchor(point) + + if( #(frame.children) == 0 ) then return end + + local xMod, yMod = math.abs(frame:GetAttribute("xMod")), math.abs(frame:GetAttribute("yMod")) + local x = frame:GetAttribute("xOffset") or 0 + local y = frame:GetAttribute("yOffset") or 0 + + for id, child in pairs(frame.children) do + if( id > 1 ) then + frame.children[id]:ClearAllPoints() + frame.children[id]:SetPoint(point, frame.children[id - 1], relativePoint, xMod * x, yMod * y) + else + frame.children[id]:ClearAllPoints() + frame.children[id]:SetPoint(point, frame, point, 0, 0) + end + end +end + +function Units:CheckGroupVisibility() + if( not ShadowUF.db.profile.locked ) then return end + local raid = headerFrames.raid and not ShadowUF.db.profile.units.raid.frameSplit and headerFrames.raid or headerFrames.raidParent + local party = headerFrames.party + if( party ) then + party:SetAttribute("showParty", ( not ShadowUF.db.profile.units.raid.showParty or not ShadowUF.enabledUnits.raid ) and true or false) + party:SetAttribute("showPlayer", ShadowUF.db.profile.units.party.showPlayer) + end + + if( raid and party ) then + raid:SetAttribute("showParty", not party:GetAttribute("showParty")) + raid:SetAttribute("showPlayer", party:GetAttribute("showPlayer")) + end +end + +function Units:SetHeaderAttributes(frame, type) + local config = ShadowUF.db.profile.units[type] + local xMod = config.attribPoint == "LEFT" and 1 or config.attribPoint == "RIGHT" and -1 or 0 + local yMod = config.attribPoint == "TOP" and -1 or config.attribPoint == "BOTTOM" and 1 or 0 + local widthMod = (config.attribPoint == "LEFT" or config.attribPoint == "RIGHT") and MEMBERS_PER_RAID_GROUP or 1 + local heightMod = (config.attribPoint == "TOP" or config.attribPoint == "BOTTOM") and MEMBERS_PER_RAID_GROUP or 1 + + frame:SetAttribute("point", config.attribPoint) + frame:SetAttribute("sortMethod", config.sortMethod) + frame:SetAttribute("sortDir", config.sortOrder) + + frame:SetAttribute("xOffset", config.offset * xMod) + frame:SetAttribute("yOffset", config.offset * yMod) + frame:SetAttribute("xMod", xMod) + frame:SetAttribute("yMod", yMod) + + -- Split up raid frame groups + if( config.frameSplit and type == "raid" ) then + local anchorPoint, relativePoint, xModRow, yModRow = ShadowUF.Layout:GetSplitRelativeAnchor(config.attribPoint, config.attribAnchorPoint) + local columnPoint, xColMod, yColMod = ShadowUF.Layout:GetRelativeAnchor(config.attribPoint) + + local lastHeader = frame + for id=1, 8 do + local childHeader = headerFrames["raid" .. id] + if( childHeader ) then + childHeader:SetAttribute("showRaid", ShadowUF.db.profile.locked and true) + + childHeader:SetAttribute("minWidth", config.width * widthMod) + childHeader:SetAttribute("minHeight", config.height * heightMod) + + if( childHeader ~= frame ) then + childHeader:SetAttribute("point", config.attribPoint) + childHeader:SetAttribute("sortMethod", config.sortMethod) + childHeader:SetAttribute("sortDir", config.sortOrder) + childHeader:SetAttribute("showPlayer", nil) + childHeader:SetAttribute("showParty", nil) + + childHeader:SetAttribute("xOffset", frame:GetAttribute("xOffset")) + childHeader:SetAttribute("yOffset", frame:GetAttribute("yOffset")) + + childHeader:ClearAllPoints() + if( (id - 1) % config.groupsPerRow == 0 ) then + local x = config.groupSpacing * xColMod + local y = config.groupSpacing * yColMod + + -- When we're anchoring a new column to the bottom of naother one, the height will mess it up + -- if what we anchored to isn't full, by anchoring it to the top instead will get a consistent result + local point = columnPoint + if( point == "BOTTOM" ) then + point = config.attribPoint + x = x + (config.height * 5) * xColMod + y = y + (config.height * 5) * yColMod + end + + childHeader:SetPoint(config.attribPoint, headerFrames["raid" .. id - config.groupsPerRow], point, x, y) + else + childHeader:SetPoint(anchorPoint, lastHeader, relativePoint, config.columnSpacing * xModRow, config.columnSpacing * yModRow) + end + + 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 + + -- Normal raid, ma or mt + elseif( type == "raidpet" or type == "raid" or type == "mainassist" or type == "maintank" ) then + local filter + if( config.filters ) then + for id, enabled in pairs(config.filters) do + if( enabled ) then + if( filter ) then + filter = filter .. "," .. id + else + filter = id + end + end + end + else + filter = config.groupFilter + end + + frame:SetAttribute("showRaid", ShadowUF.db.profile.locked and true) + frame:SetAttribute("maxColumns", config.maxColumns) + frame:SetAttribute("unitsPerColumn", config.unitsPerColumn) + 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,DEMONHUNTER,DRUID,HUNTER,MAGE,PALADIN,PRIEST,ROGUE,SHAMAN,WARLOCK,WARRIOR,MONK,EVOKER") + 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" 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 + elseif( type == "party" ) then + frame:SetAttribute("maxColumns", math.ceil((config.showPlayer and 5 or 4) / config.unitsPerColumn)) + 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 + + if( type == "raid" ) then + self:CheckGroupVisibility() + + 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 +function Units:LoadUnit(unit) + -- Already be loaded, just enable + if( unitFrames[unit] ) then + RegisterUnitWatch(unitFrames[unit], unitFrames[unit].hasStateWatch) + return + end + + local frame = self:CreateUnit("Button", "SUFUnit" .. unit, petBattleFrame, BackdropTemplateMixin and "SecureUnitButtonTemplate,BackdropTemplate" or "SecureUnitButtonTemplate") + frame:SetAttribute("unit", unit) + frame.hasStateWatch = unit == "pet" + + -- Annd 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, petBattleFrame, "SecureGroupHeaderTemplate") + frame:SetAttribute("template", unitButtonTemplate) + frame:SetAttribute("initial-unitWatch", true) + frame:SetAttribute("showRaid", true) + frame:SetAttribute("groupFilter", id) + 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 + + frame:Show() + + if( not headerFrames.raidParent or headerFrames.raidParent.groupID > id ) then + headerFrames.raidParent = frame + end + + setupRaidStateMonitor(id, frame) + + elseif( frame ) then + frame:Hide() + end + end + + if( headerFrames.raidParent ) then + self:SetHeaderAttributes(headerFrames.raidParent, type) + ShadowUF.Layout:AnchorFrame(UIParent, headerFrames.raidParent, ShadowUF.db.profile.positions.raid) + end +end + +-- Load a header unit, party or raid +function Units:LoadGroupHeader(type) + -- Already created, so just reshow and we out + if( headerFrames[type] ) then + headerFrames[type]:Show() + + 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, petBattleFrame, type == "raidpet" and "SecureGroupPetHeaderTemplate" or "SecureGroupHeaderTemplate") + headerFrames[type] = headerFrame + + self:SetHeaderAttributes(headerFrame, type) + + headerFrame:SetAttribute("template", unitButtonTemplate) + headerFrame:SetAttribute("initial-unitWatch", true) + headerFrame:SetAttribute("initialConfigFunction", secureInitializeUnit) + + headerFrame.initialConfigFunction = initializeUnit + headerFrame.isHeaderFrame = true + headerFrame.unitType = type + 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.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 + + if( self:GetAttribute("hideAnyRaid") and ( self:GetAttribute("state-raidmonitor") == "raid1" or self:GetAttribute("state-raidmonitor") == "raid6" ) ) then + self:GetFrameRef("partyHeader"):Hide() + elseif( self:GetAttribute("hideSemiRaid") and self:GetAttribute("state-raidmonitor") == "raid6" ) then + self:GetFrameRef("partyHeader"):Hide() + else + self:GetFrameRef("partyHeader"):Show() + end + ]]) + 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 _, f in pairs(headerFrames) do + if( f.splitParent == type ) then + f: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, 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 + headerFrame:SetScript("OnAttributeChanged", function(frame, key, value) + if( key == "childChanged" and value and frame.children[value] and frame:IsVisible() ) then + frame.children[value]:FullUpdate() + end + end) + end + + for id, unit in pairs(ShadowUF[type .. "Units"]) do + local frame = self:CreateUnit("Button", "SUFHeader" .. type .. "UnitButton" .. id, headerFrame, BackdropTemplateMixin and "SecureUnitButtonTemplate,BackdropTemplate" or "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 + stateMonitor:WrapScript(frame, "OnAttributeChanged", [[ + if( name == "state-unitexists" ) then + local parent = self:GetParent() + if( value and self:GetAttribute("unitDisappeared") ) then + parent:SetAttribute("childChanged", self:GetAttribute("unitID")) + self:SetAttribute("unitDisappeared", nil) + elseif( not value and not self:GetAttribute("unitDisappeared") ) then + self:SetAttribute("unitDisappeared", true) + end + + if( value ) then + self:Show() + end + end + ]]) + else + 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) +function Units:LoadChildUnit(parent, type, id) + if( InCombatLockdown() ) then + if( not queuedCombat[parent:GetName() .. type] ) then + queuedCombat[parent:GetName() .. type] = {parent = parent, type = type, id = id} + end + return + else + -- This is a bit confusing to write down, but just in case I forget: + -- It's possible theres a bug where you have a frame skip creating it's child because it thinks one was already created, but the one that was created is actually associated to another parent. What would need to be changed is it checks if the frame has the parent set to it and it's the same unit type before returning, not that the units match. + for frame in pairs(frameList) do + if( frame.unitType == type and frame.parent == parent ) then + RegisterUnitWatch(frame, frame.hasStateWatch) + return + end + end + end + + 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, BackdropTemplateMixin and "SecureUnitButtonTemplate,BackdropTemplate" or "SecureUnitButtonTemplate") + frame.unitType = type + frame.parent = parent + frame.isChildUnit = true + frame.hasStateWatch = type == "partypet" + frame:SetFrameStrata("LOW") + frame:SetAttribute("useparent-unit", true) + frame:SetAttribute("unitsuffix", suffix) + OnAttributeChanged(frame, "unit", SecureButton_GetModifiedUnit(frame)) + frameList[frame] = true + + RegisterUnitWatch(frame, frame.hasStateWatch) + ShadowUF.Layout:AnchorFrame(parent, frame, ShadowUF.db.profile.positions[type]) +end + +-- Initialize units +function Units:InitializeFrame(type) + if( type == "raid" and ShadowUF.db.profile.units[type].frameSplit ) then + self:LoadSplitGroupHeader(type) + elseif( type == "party" or type == "raid" or type == "maintank" or type == "mainassist" or type == "raidpet" ) then + self:LoadGroupHeader(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 +end + +-- Uninitialize units +function Units:UninitializeFrame(type) + 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 + if( headerFrame.splitParent == type ) then + headerFrame:Hide() + end + end + elseif( headerFrames[type] ) then + headerFrames[type]:Hide() + + 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 + else + -- Disable all frames of this type + for frame in pairs(frameList) do + if( frame.unitType == type ) then + UnregisterUnitWatch(frame) + frame:SetAttribute("state-unitexits", false) + frame:Hide() + end + end + end +end + +-- Profile changed, reload units +function Units:ProfileChanged() + -- Reset the anchors for all frames to prevent X is dependant on Y + for frame in pairs(frameList) do + if( frame.unit ) then + frame:ClearAllPoints() + end + end + + for frame in pairs(frameList) do + if( frame.unit and ShadowUF.db.profile.units[frame.unitType].enabled ) then + -- Force all enabled modules to disable + for key, module in pairs(ShadowUF.modules) do + if( frame[key] and frame.visibility[key] ) then + frame.visibility[key] = nil + module:OnDisable(frame) + end + end + + -- Now enable whatever we need to + frame:SetVisibility() + ShadowUF.Layout:Load(frame) + frame:FullUpdate() + end + end + + for _, frame in pairs(headerFrames) do + if( ShadowUF.db.profile.units[frame.unitType].enabled ) then + self:ReloadHeader(frame.unitType) + end + end +end + +-- Small helper function for creating bars with +function Units:CreateBar(parent) + local bar = CreateFrame("StatusBar", nil, parent) + bar:SetFrameLevel(parent.topFrameLevel or 5) + bar.parent = parent + + bar.background = bar:CreateTexture(nil, "BORDER") + bar.background:SetHeight(1) + bar.background:SetWidth(1) + bar.background:SetAllPoints(bar) + bar.background:SetHorizTile(false) + + 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) + if( InCombatLockdown() ) then + queueZoneCheck = force and 2 or 1 + return + end + + -- CanHearthAndResurrectFromArea() returns true for world pvp areas, according to BattlefieldFrame.lua + 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 + + ShadowUF:LoadUnits() + for frame in pairs(frameList) do + if( frame.unit and ShadowUF.db.profile.units[frame.unitType].enabled ) then + frame:SetVisibility() + + -- Auras are enabled so will need to check if the filter has to change + if( frame.visibility.auras ) then + ShadowUF.modules.auras:UpdateFilter(frame) + end + + if( UnitExists(frame.unit) ) then + frame:FullUpdate() + end + end + 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"}, [213634] = {"Disease"}}, + ["PALADIN"] = {[4987] = {"Poison", "Disease", "Magic"}, [213644] = {"Poison", "Disease"}}, + ["SHAMAN"] = {[77130] = {"Curse", "Magic"}, [51886] = {"Curse"}, [383013] = {"Poison"}}, + ["MONK"] = {[115450] = {"Poison", "Disease", "Magic"}, [218164] = {"Poison", "Disease"}}, + ["MAGE"] = {[475] = {"Curse"}}, + ["WARLOCK"] = {[89808] = {"Magic"}}, + ["EVOKER"] = {[365585] = {"Poison"}, [360823] = {"Magic", "Poison"}, [374251] = {"Poison", "Curse", "Disease"}} +} + +curableSpells = curableSpells[playerClass] + +local function checkCurableSpells() + if( not curableSpells ) then return end + + table.wipe(Units.canCure) + + for spellID, cures in pairs(curableSpells) do + if( IsPlayerSpell(spellID) or IsSpellKnown(spellID, true) ) 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 + -- really having left the zone + if( event == "ZONE_CHANGED_NEW_AREA" ) then + if( UnitIsDeadOrGhost("player") ) then + self:RegisterEvent("PLAYER_UNGHOST") + else + self:UnregisterEvent("PLAYER_UNGHOST") + Units:CheckPlayerZone() + 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" or event == "UNIT_PET" or event == "SPELLS_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") + self:RegisterEvent("SPELLS_CHANGED") + if( playerClass == "WARLOCK" ) then + self:RegisterUnitEvent("UNIT_PET", "player", nil) + end + + -- 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 + for _, queue in pairs(queuedCombat) do + Units:LoadChildUnit(queue.parent, queue.type, queue.id) + end + + table.wipe(queuedCombat) + + if( queueZoneCheck ) then + Units:CheckPlayerZone(queueZoneCheck == 2 and true) + queueZoneCheck = nil + end + end +end) diff --git a/modules/xp.lua b/modules/xp.lua index 0f625e31a..845859e6e 100755 --- a/modules/xp.lua +++ b/modules/xp.lua @@ -1,162 +1,161 @@ -local XP = {} -local L = ShadowUF.L -ShadowUF:RegisterModule(XP, "xpBar", L["XP/Rep bar"], true) - -local function OnEnter(self) - if( self.tooltip ) then - GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT") - GameTooltip:SetText(self.tooltip) - end -end - -local function OnLeave(self) - GameTooltip:Hide() -end - -function XP:OnEnable(frame) - if( not frame.xpBar ) then - frame.xpBar = CreateFrame("Frame", nil, frame) - frame.xpBar:SetScript("OnEnter", OnEnter) - frame.xpBar:SetScript("OnLeave", OnLeave) - frame.xpBar:EnableMouse(true) - - frame.xpBar.xp = ShadowUF.Units:CreateBar(frame.xpBar) - frame.xpBar.xp:SetPoint("BOTTOMLEFT", frame.xpBar) - frame.xpBar.xp:SetPoint("BOTTOMRIGHT", frame.xpBar) - - if( frame.unitType == "player" ) then - frame.xpBar.rep = ShadowUF.Units:CreateBar(frame.xpBar) - frame.xpBar.rep:SetPoint("TOPLEFT", frame.xpBar) - frame.xpBar.rep:SetPoint("TOPRIGHT", frame.xpBar) - end - - frame.xpBar.rested = CreateFrame("StatusBar", nil, frame.xpBar.xp) - frame.xpBar.rested:SetFrameLevel(frame.xpBar.xp:GetFrameLevel() - 1) - frame.xpBar.rested:SetAllPoints(frame.xpBar.xp) - end - - frame:RegisterNormalEvent("ENABLE_XP_GAIN", self, "Update") - frame:RegisterNormalEvent("DISABLE_XP_GAIN", self, "Update") - - if( frame.unitType == "player" ) then - frame:RegisterNormalEvent("PLAYER_XP_UPDATE", self, "Update") - frame:RegisterNormalEvent("UPDATE_EXHAUSTION", self, "Update") - frame:RegisterNormalEvent("PLAYER_LEVEL_UP", self, "Update") - frame:RegisterNormalEvent("UPDATE_FACTION", self, "Update") - else - frame:RegisterNormalEvent("UNIT_PET_EXPERIENCE", self, "Update") - frame:RegisterUnitEvent("UNIT_LEVEL", self, "Update") - end - - frame:RegisterUpdateFunc(self, "Update") -end - -function XP:OnDisable(frame) - frame:UnregisterAll(self) -end - -function XP:OnLayoutApplied(frame) - if( frame.visibility.xpBar ) then - frame.xpBar.xp:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) - frame.xpBar.xp:SetStatusBarColor(ShadowUF.db.profile.xpColors.normal.r, ShadowUF.db.profile.xpColors.normal.g, ShadowUF.db.profile.xpColors.normal.b, ShadowUF.db.profile.bars.alpha) - - frame.xpBar.xp.background:SetVertexColor(ShadowUF.db.profile.xpColors.normal.r, ShadowUF.db.profile.xpColors.normal.g, ShadowUF.db.profile.xpColors.normal.b, ShadowUF.db.profile.bars.backgroundAlpha) - frame.xpBar.xp.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar) - - frame.xpBar.rested:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) - frame.xpBar.rested:SetStatusBarColor(ShadowUF.db.profile.xpColors.rested.r, ShadowUF.db.profile.xpColors.rested.g, ShadowUF.db.profile.xpColors.rested.b, ShadowUF.db.profile.bars.alpha) - - if( frame.xpBar.rep ) then - frame.xpBar.rep:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) - frame.xpBar.rep.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar) - end - end -end - --- Format 5000 into 5,000 -local function formatNumber(number) - local found - while( true ) do - number, found = string.gsub(number, "^(-?%d+)(%d%d%d)", "%1,%2") - if( found == 0 ) then break end - end - - return number -end - -function XP:UpdateRep(frame) - if( not frame.xpBar.rep ) then return end - local factionData = C_Reputation.GetWatchedFactionData() - if( not factionData ) then - frame.xpBar.rep:Hide() - return - end - - -- Blizzard stores faction info related to Exalted, not your current level, so get more mathier to find the current reputation using the current standing tier - local min, max, current = factionData.currentReactionThreshold, factionData.nextReactionThreshold, factionData.currentStanding - current = math.abs(min - current) - max = math.abs(min - max) - - local color = FACTION_BAR_COLORS[factionData.reaction] - frame.xpBar.rep:SetMinMaxValues(0, max) - frame.xpBar.rep:SetValue(current) - frame.xpBar.rep.tooltip = string.format(L["%s (%s): %s/%s (%.2f%% done)"], factionData.name, GetText("FACTION_STANDING_LABEL" .. tostring(factionData.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() -end - -function XP:UpdateXP(frame) - -- At the level cap or XP is disabled, or the pet is actually a vehicle right now, swap to reputation bar (or hide it) - if( UnitLevel(frame.unitOwner) == GetMaxLevelForPlayerExpansion() or IsXPUserDisabled() or ( frame.unitOwner == "pet" and UnitExists("vehicle") ) ) then - frame.xpBar.xp:Hide() - return - end - - local current, max - if( frame.unitOwner == "player" ) then - current, max = UnitXP(frame.unitOwner), UnitXPMax(frame.unitOwner) - else - current, max = GetPetExperience() - end - - local min = math.min(0, current) - frame.xpBar.xp:SetMinMaxValues(min, max) - frame.xpBar.xp:SetValue(current) - frame.xpBar.xp:Show() - - if( frame.unitOwner == "player" and GetXPExhaustion() ) then - 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), (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), (max > 0 and current / max or 0) * 100) - end -end - -function XP:Update(frame) - self:UpdateRep(frame) - self:UpdateXP(frame) - - if( ( not frame.xpBar.rep or not frame.xpBar.rep:IsShown() ) and not frame.xpBar.xp:IsShown() ) then - ShadowUF.Layout:SetBarVisibility(frame, "xpBar", false) - return - end - - ShadowUF.Layout:SetBarVisibility(frame, "xpBar", true) - if( frame.xpBar.rep and frame.xpBar.rep:IsVisible() and frame.xpBar.xp:IsVisible() ) then - frame.xpBar.rep:SetHeight(frame.xpBar:GetHeight() * 0.48) - frame.xpBar.xp:SetHeight(frame.xpBar:GetHeight() * 0.48) - frame.xpBar.tooltip = frame.xpBar.rep.tooltip .. "\n" .. frame.xpBar.xp.tooltip - - elseif( frame.xpBar.rep and frame.xpBar.rep:IsVisible() ) then - frame.xpBar.rep:SetHeight(frame.xpBar:GetHeight()) - frame.xpBar.tooltip = frame.xpBar.rep.tooltip - - elseif( frame.xpBar.xp:IsVisible() ) then - frame.xpBar.xp:SetHeight(frame.xpBar:GetHeight()) - frame.xpBar.tooltip = frame.xpBar.xp.tooltip - end -end +local XP = {} +local L = ShadowUF.L +ShadowUF:RegisterModule(XP, "xpBar", L["XP/Rep bar"], true) + +local function OnEnter(self) + if( self.tooltip ) then + GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT") + GameTooltip:SetText(self.tooltip) + end +end + +local function OnLeave(self) + GameTooltip:Hide() +end + +function XP:OnEnable(frame) + if( not frame.xpBar ) then + frame.xpBar = CreateFrame("Frame", nil, frame) + frame.xpBar:SetScript("OnEnter", OnEnter) + frame.xpBar:SetScript("OnLeave", OnLeave) + frame.xpBar:EnableMouse(true) + + frame.xpBar.xp = ShadowUF.Units:CreateBar(frame.xpBar) + frame.xpBar.xp:SetPoint("BOTTOMLEFT", frame.xpBar) + frame.xpBar.xp:SetPoint("BOTTOMRIGHT", frame.xpBar) + + if( frame.unitType == "player" ) then + frame.xpBar.rep = ShadowUF.Units:CreateBar(frame.xpBar) + frame.xpBar.rep:SetPoint("TOPLEFT", frame.xpBar) + frame.xpBar.rep:SetPoint("TOPRIGHT", frame.xpBar) + end + + frame.xpBar.rested = CreateFrame("StatusBar", nil, frame.xpBar.xp) + frame.xpBar.rested:SetFrameLevel(frame.xpBar.xp:GetFrameLevel() - 1) + frame.xpBar.rested:SetAllPoints(frame.xpBar.xp) + end + + frame:RegisterNormalEvent("ENABLE_XP_GAIN", self, "Update") + frame:RegisterNormalEvent("DISABLE_XP_GAIN", self, "Update") + + if( frame.unitType == "player" ) then + frame:RegisterNormalEvent("PLAYER_XP_UPDATE", self, "Update") + frame:RegisterNormalEvent("UPDATE_EXHAUSTION", self, "Update") + frame:RegisterNormalEvent("PLAYER_LEVEL_UP", self, "Update") + frame:RegisterNormalEvent("UPDATE_FACTION", self, "Update") + else + frame:RegisterNormalEvent("UNIT_PET_EXPERIENCE", self, "Update") + frame:RegisterUnitEvent("UNIT_LEVEL", self, "Update") + end + + frame:RegisterUpdateFunc(self, "Update") +end + +function XP:OnDisable(frame) + frame:UnregisterAll(self) +end + +function XP:OnLayoutApplied(frame) + if( frame.visibility.xpBar ) then + frame.xpBar.xp:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) + frame.xpBar.xp:SetStatusBarColor(ShadowUF.db.profile.xpColors.normal.r, ShadowUF.db.profile.xpColors.normal.g, ShadowUF.db.profile.xpColors.normal.b, ShadowUF.db.profile.bars.alpha) + + frame.xpBar.xp.background:SetVertexColor(ShadowUF.db.profile.xpColors.normal.r, ShadowUF.db.profile.xpColors.normal.g, ShadowUF.db.profile.xpColors.normal.b, ShadowUF.db.profile.bars.backgroundAlpha) + frame.xpBar.xp.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar) + + frame.xpBar.rested:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) + frame.xpBar.rested:SetStatusBarColor(ShadowUF.db.profile.xpColors.rested.r, ShadowUF.db.profile.xpColors.rested.g, ShadowUF.db.profile.xpColors.rested.b, ShadowUF.db.profile.bars.alpha) + + if( frame.xpBar.rep ) then + frame.xpBar.rep:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) + frame.xpBar.rep.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar) + end + end +end + +-- Format 5000 into 5,000 +local function formatNumber(number) + local found + while( true ) do + number, found = string.gsub(number, "^(-?%d+)(%d%d%d)", "%1,%2") + if( found == 0 ) then break end + end + + return number +end + +function XP:UpdateRep(frame) + if( not frame.xpBar.rep ) then return end + local name, reaction, min, max, current = GetWatchedFactionInfo() + if( not name ) then + frame.xpBar.rep:Hide() + return + end + + -- Blizzard stores faction info related to Exalted, not your current level, so get more mathier to find the current reputation using the current standing tier + current = math.abs(min - current) + max = math.abs(min - max) + + local color = FACTION_BAR_COLORS[reaction] + frame.xpBar.rep:SetMinMaxValues(0, max) + 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() +end + +function XP:UpdateXP(frame) + -- At the level cap or XP is disabled, or the pet is actually a vehicle right now, swap to reputation bar (or hide it) + if( UnitLevel(frame.unitOwner) == MAX_PLAYER_LEVEL or IsXPUserDisabled() or ( frame.unitOwner == "pet" and UnitExists("vehicle") ) ) then + frame.xpBar.xp:Hide() + return + end + + local current, max + if( frame.unitOwner == "player" ) then + current, max = UnitXP(frame.unitOwner), UnitXPMax(frame.unitOwner) + else + current, max = GetPetExperience() + end + + local min = math.min(0, current) + frame.xpBar.xp:SetMinMaxValues(min, max) + frame.xpBar.xp:SetValue(current) + frame.xpBar.xp:Show() + + if( frame.unitOwner == "player" and GetXPExhaustion() ) then + 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), (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), (max > 0 and current / max or 0) * 100) + end +end + +function XP:Update(frame) + self:UpdateRep(frame) + self:UpdateXP(frame) + + if( ( not frame.xpBar.rep or not frame.xpBar.rep:IsShown() ) and not frame.xpBar.xp:IsShown() ) then + ShadowUF.Layout:SetBarVisibility(frame, "xpBar", false) + return + end + + ShadowUF.Layout:SetBarVisibility(frame, "xpBar", true) + if( frame.xpBar.rep and frame.xpBar.rep:IsVisible() and frame.xpBar.xp:IsVisible() ) then + frame.xpBar.rep:SetHeight(frame.xpBar:GetHeight() * 0.48) + frame.xpBar.xp:SetHeight(frame.xpBar:GetHeight() * 0.48) + frame.xpBar.tooltip = frame.xpBar.rep.tooltip .. "\n" .. frame.xpBar.xp.tooltip + + elseif( frame.xpBar.rep and frame.xpBar.rep:IsVisible() ) then + frame.xpBar.rep:SetHeight(frame.xpBar:GetHeight()) + frame.xpBar.tooltip = frame.xpBar.rep.tooltip + + elseif( frame.xpBar.xp:IsVisible() ) then + frame.xpBar.xp:SetHeight(frame.xpBar:GetHeight()) + frame.xpBar.tooltip = frame.xpBar.xp.tooltip + end +end diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc index 120cd18be..0da9366ef 100755 --- a/options/ShadowedUF_Options.toc +++ b/options/ShadowedUF_Options.toc @@ -1,16 +1,15 @@ -## Interface: 110107 -## Title: Shadowed UF (Options) -## Notes: Configuration for Shadowed Unit Frames. -## Author: Shadowed -## LoadOnDemand: true -## Dependencies: ShadowedUnitFrames -## Category: ShadowedUnitFrames - -#@no-lib-strip@ -libs\AceDBOptions-3.0\AceDBOptions-3.0.xml -libs\AceGUI-3.0\AceGUI-3.0.xml -libs\AceGUI-3.0-SharedMediaWidgets\widget.xml -libs\AceConfig-3.0\AceConfig-3.0.xml -#@end-no-lib-strip@ - -config.lua +## Interface: 110105, 110107, 110200, 50500 +## Title: Shadowed UF (Options) +## Notes: Configuration for Shadowed Unit Frames. +## Author: Shadowed +## LoadOnDemand: true +## Dependencies: ShadowedUnitFrames + +#@no-lib-strip@ +libs\AceDBOptions-3.0\AceDBOptions-3.0.xml +libs\AceGUI-3.0\AceGUI-3.0.xml +libs\AceGUI-3.0-SharedMediaWidgets\widget.xml +libs\AceConfig-3.0\AceConfig-3.0.xml +#@end-no-lib-strip@ + +config.lua diff --git a/options/config.lua b/options/config.lua index 70e5a43a0..20d26a99d 100755 --- a/options/config.lua +++ b/options/config.lua @@ -1,7623 +1,7698 @@ -local Config = {} -local AceDialog, AceRegistry, AceGUI, SML, registered, options -local playerClass = select(2, UnitClass("player")) -local modifyUnits, globalConfig = {}, {} -local L = ShadowUF.L - -ShadowUF.Config = Config - -local GetSpellName = C_Spell.GetSpellName -local GetSpellTexture = C_Spell.GetSpellTexture - ---[[ - The part that makes configuration a pain when you actually try is it gets unwieldly when you're adding special code to deal with - showing help for certain cases, swapping tabs etc that makes it work smoothly. - - 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", "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 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 = { - ["general"] = L["General configuration to all enabled units."], - ["enableUnits"] = L["Various units can be enabled through this page, such as raid or party targets."], - ["hideBlizzard"] = L["Hiding and showing various aspects of the default UI such as the player buff frames."], - ["units"] = L["Configuration to specific unit frames."], - ["visibility"] = L["Disabling unit modules in various instances."], - ["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 = {["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"], ["sumPending"] = L["Summon Pending"], ["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."], ["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 unitOrder = {} -for order, unit in pairs(ShadowUF.unitList) do unitOrder[unit] = order end -local fullReload = {["bars"] = true, ["auras"] = true, ["backdrop"] = true, ["font"] = true, ["classColors"] = true, ["powerColors"] = true, ["healthColors"] = true, ["xpColors"] = true, ["omnicc"] = true} -local quickIDMap = {} - --- Helper functions -local function getPageDescription(info) - return PAGE_DESC[info[#(info)]] -end - -local function getFrameName(unit) - if( unit == "raidpet" or unit == "raid" or unit == "party" or unit == "maintank" or unit == "mainassist" or unit == "boss" or unit == "arena" ) then - return string.format("#SUFHeader%s", unit) - end - - return string.format("#SUFUnit%s", unit) -end - -local anchorList = {} -local function getAnchorParents(info) - local unit = info[2] - for k in pairs(anchorList) do anchorList[k] = nil end - - if( ShadowUF.Units.childUnits[unit] ) then - anchorList["$parent"] = string.format(L["%s member"], L.units[ShadowUF.Units.childUnits[unit]]) - return anchorList - end - - anchorList["UIParent"] = L["Screen"] - - -- Don't let a frame anchor to a frame thats anchored to it already (Stop infinite loops-o-doom) - local currentName = getFrameName(unit) - for _, unitID in pairs(ShadowUF.unitList) do - if( unitID ~= unit and ShadowUF.db.profile.positions[unitID] and ShadowUF.db.profile.positions[unitID].anchorTo ~= currentName ) then - anchorList[getFrameName(unitID)] = string.format(L["%s frames"], L.units[unitID] or unitID) - end - end - - return anchorList -end - -local function selectDialogGroup(group, key) - AceDialog.Status.ShadowedUF.children[group].status.groups.selected = key - AceRegistry:NotifyChange("ShadowedUF") -end - -local function selectTabGroup(group, subGroup, key) - AceDialog.Status.ShadowedUF.children[group].status.groups.selected = subGroup - AceDialog.Status.ShadowedUF.children[group].children[subGroup].status.groups.selected = key - AceRegistry:NotifyChange("ShadowedUF") -end - -local function hideAdvancedOption(info) - return not ShadowUF.db.profile.advanced -end - -local function hideBasicOption(info) - return ShadowUF.db.profile.advanced -end - -local function isUnitDisabled(info) - local unit = info[#(info)] - local enabled = ShadowUF.db.profile.units[unit].enabled - for _, visibility in pairs(ShadowUF.db.profile.visibility) do - if( visibility[unit] ) then - enabled = visibility[unit] - break - end - end - - return not enabled -end - -local function mergeTables(parent, child) - for key, value in pairs(child) do - if( type(parent[key]) == "table" ) then - parent[key] = mergeTables(parent[key], value) - elseif( type(value) == "table" ) then - parent[key] = CopyTable(value) - elseif( parent[key] == nil ) then - parent[key] = value - end - end - - return parent -end - -local function getName(info) - local key = info[#(info)] - if( ShadowUF.modules[key] and ShadowUF.modules[key].moduleName ) then - return ShadowUF.modules[key].moduleName - end - - return LOCALIZED_CLASS_NAMES_MALE[key] or INDICATOR_NAMES[key] or L.units[key] or TAG_GROUPS[key] or L[key] -end - -local function getUnitOrder(info) - return unitOrder[info[#(info)]] -end - -local function isModifiersSet(info) - if( info[2] ~= "global" ) then return false end - for k in pairs(modifyUnits) do return false end - return true -end - --- These are for setting simple options like bars.texture = "Default" or locked = true -local function set(info, value) - local cat, key = string.split(".", info.arg) - if( key == "$key" ) then key = info[#(info)] end - - if( not key ) then - ShadowUF.db.profile[cat] = value - else - ShadowUF.db.profile[cat][key] = value - end - - if( cat and fullReload[cat] ) then - ShadowUF.Layout:CheckMedia() - ShadowUF.Layout:Reload() - end -end - -local function get(info) - local cat, key = string.split(".", info.arg) - if( key == "$key" ) then key = info[#(info)] end - if( not key ) then - return ShadowUF.db.profile[cat] - else - return ShadowUF.db.profile[cat][key] - end -end - -local function setColor(info, r, g, b, a) - 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) or {} - return color.r, color.g, color.b, color.a -end - --- These are for setting complex options like units.player.auras.buffs.enabled = true or units.player.portrait.enabled = true -local function setVariable(unit, moduleKey, moduleSubKey, key, value) - local configTable = unit == "global" and globalConfig or ShadowUF.db.profile.units[unit] - - -- For setting options like units.player.auras.buffs.enabled = true - if( moduleKey and moduleSubKey and configTable[moduleKey][moduleSubKey] ) then - configTable[moduleKey][moduleSubKey][key] = value - ShadowUF.Layout:Reload(unit) - -- For setting options like units.player.portrait.enabled = true - elseif( moduleKey and not moduleSubKey and configTable[moduleKey] ) then - configTable[moduleKey][key] = value - ShadowUF.Layout:Reload(unit) - -- For setting options like units.player.height = 50 - elseif( not moduleKey and not moduleSubKey ) then - configTable[key] = value - ShadowUF.Layout:Reload(unit) - end -end - -local function specialRestricted(unit, moduleKey, moduleSubKey, key) - 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 setDirectUnit(unit, moduleKey, moduleSubKey, key, value) - if( unit == "global" ) then - for globalUnit in pairs(modifyUnits) do - if( not specialRestricted(globalUnit, moduleKey, moduleSubKey, key) ) then - setVariable(globalUnit, moduleKey, moduleSubKey, key, value) - end - end - - setVariable("global", moduleKey, moduleSubKey, key, value) - else - setVariable(unit, moduleKey, moduleSubKey, key, 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 - return configTbl[moduleKey][moduleSubKey] and configTbl[moduleKey][moduleSubKey][key] - elseif( moduleKey and not moduleSubKey ) then - return configTbl[moduleKey] and configTbl[moduleKey][key] - end - - return configTbl[key] -end - -local function getUnit(info) - 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 - - return getVariable(info[2], moduleKey, moduleSubKey, key) -end - --- Tag functions -local function getTagName(info) - local tag = info[#(info)] - if( ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].name ) then - return ShadowUF.db.profile.tags[tag].name - end - - return ShadowUF.Tags.defaultNames[tag] or tag -end - -local function getTagHelp(info) - local tag = info[#(info)] - return ShadowUF.Tags.defaultHelp[tag] or ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].help -end - --- Module functions -local function hideRestrictedOption(info) - local unit = type(info.arg) == "number" and info[#(info) - info.arg] or info[2] - 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 ) 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 == "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 - if( ( unit == "global" and not globalConfig.indicators[key] ) or ( unit ~= "global" and not ShadowUF.db.profile.units[unit].indicators[key] ) ) then - return true - end - -- Fall back, no variable table so it shouldn't be shown - elseif( ( unit == "global" and not globalConfig[key] ) or ( unit ~= "global" and not ShadowUF.db.profile.units[unit][key] ) ) then - return true - end - - return false -end - -local function getModuleOrder(info) - local key = info[#(info)] - return key == "healthBar" and 1 or key == "powerBar" and 2 or key == "castBar" and 3 or 4 -end - --- Expose these for modules -Config.getAnchorParents = getAnchorParents -Config.hideAdvancedOption = hideAdvancedOption -Config.isUnitDisabled = isUnitDisabled -Config.selectDialogGroup = selectDialogGroup -Config.selectTabGroup = selectTabGroup -Config.getName = getName -Config.getUnitOrder = getUnitOrder -Config.isModifiersSet = isModifiersSet -Config.set = set -Config.get = get -Config.setUnit = setUnit -Config.setVariable = setVariable -Config.getUnit = getUnit -Config.getVariable = getVariable -Config.hideRestrictedOption = hideRestrictedOption -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") - - local MediaList = {} - local function getMediaData(info) - local mediaType = info[#(info)] - - MediaList[mediaType] = MediaList[mediaType] or {} - - for k in pairs(MediaList[mediaType]) do MediaList[mediaType][k] = nil end - for _, name in pairs(SML:List(mediaType)) do - MediaList[mediaType][name] = name - end - - return MediaList[mediaType] - end - - - local barModules = {} - for key, module in pairs(ShadowUF.modules) do - if( module.moduleHasBar ) then - barModules["$" .. key] = module.moduleName - end - end - - local addTextParent = { - order = 4, - type = "group", - inline = true, - name = function(info) return barModules[info[#(info)]] or string.sub(info[#(info)], 2) end, - hidden = function(info) - for _, text in pairs(ShadowUF.db.profile.units.player.text) do - if( text.anchorTo == info[#(info)] ) then - return false - end - end - - return true - end, - args = {}, - } - - local addTextLabel = { - order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end, - type = "description", - width = "", - fontSize = "medium", - hidden = function(info) - local id = tonumber(string.match(info[#(info)], "(%d+)")) - if( not getVariable("player", "text", nil, id) ) then return true end - return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1] - end, - name = function(info) - return getVariable("player", "text", tonumber(string.match(info[#(info)], "(%d+)")), "name") - end, - } - - local addTextSep = { - order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.75 end, - type = "description", - width = "full", - hidden = function(info) - local id = tonumber(string.match(info[#(info)], "(%d+)")) - if( not getVariable("player", "text", nil, id) ) then return true end - return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1] - end, - name = "", - } - - local addText = { - order = function(info) return info[#(info)] + 0.5 end, - type = "execute", - width = "half", - name = L["Delete"], - hidden = function(info) - local id = tonumber(info[#(info)]) - if( not getVariable("player", "text", nil, id) ) then return true end - return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1] - 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) - local id = tonumber(info[#(info)]) - for _, unit in pairs(ShadowUF.unitList) do - table.remove(ShadowUF.db.profile.units[unit].text, id) - end - - addTextParent.args[info[#(info)]] = nil - ShadowUF.Layout:Reload() - end, - } - - local function validateSpell(info, spell) - if( spell and spell ~= "" and not GetSpellName(spell) ) then - return string.format(L["Invalid spell \"%s\" entered."], spell or "") - end - - 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) - return ShadowUF.db.profile.range[info[#(info)] .. playerClass] - 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 - - local icon = name and GetSpellTexture(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", - order = 7, - name = L["Layout manager"], - childGroups = "tab", - hidden = hideAdvancedOption, - args = { - import = { - order = 1, - type = "group", - name = L["Import"], - hidden = false, - args = { - help = { - order = 1, - type = "group", - inline = true, - name = function(info) return layoutData.error and L["Error"] or L["Help"] end, - args = { - help = { - order = 1, - type = "description", - name = function(info) - if( ShadowUF.db:GetCurrentProfile() == "Import Backup" ) then - return L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] - end - - return layoutData.error or L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] - end - }, - }, - }, - positions = { - order = 2, - type = "toggle", - name = L["Import unit frame positions"], - set = function(info, value) layoutData[info[#(info)]] = value end, - get = function(info) return layoutData[info[#(info)]] end, - width = "double", - }, - visibility = { - order = 3, - type = "toggle", - name = L["Import visibility settings"], - set = function(info, value) layoutData[info[#(info)]] = value end, - get = function(info) return layoutData[info[#(info)]] end, - width = "double", - }, - import = { - order = 5, - type = "input", - name = L["Code"], - multiline = true, - width = "full", - get = false, - disabled = function() return ShadowUF.db:GetCurrentProfile() == "Import Backup" end, - set = function(info, import) - local layout, err = loadstring(string.format([[return %s]], import)) - if( err ) then - layoutData.error = string.format(L["Failed to import layout, error:|n|n%s"], err) - return - end - - layout = layout() - - -- Strip position settings - if( not layoutData.positions ) then - layout.positions = nil - end - - -- Strip visibility settings - if( not layoutData.visibility ) then - layout.visibility = nil - end - - -- Strip any units we don't have included by default - for unit in pairs(layout.units) do - if( not ShadowUF.defaults.profile.units[unit] ) then - layout.units[unit] = nil - 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) - - -- Now backup the profile - local currentLayout = ShadowUF.db:GetCurrentProfile() - ShadowUF.layoutImporting = true - ShadowUF.db:SetProfile("Import Backup") - ShadowUF.db:CopyProfile(currentLayout) - ShadowUF.db:SetProfile(currentLayout) - ShadowUF.db:ResetProfile() - ShadowUF.layoutImporting = nil - - -- Overwrite everything we did import - ShadowUF:LoadDefaultLayout() - for key, data in pairs(layout) do - if( type(data) == "table" ) then - ShadowUF.db.profile[key] = CopyTable(data) - else - ShadowUF.db.profile[key] = data - end - end - - ShadowUF:ProfilesChanged() - end, - }, - }, - }, - export = { - order = 2, - type = "group", - name = L["Export"], - hidden = false, - args = { - help = { - order = 1, - type = "group", - inline = true, - name = L["Help"], - args = { - help = { - order = 1, - type = "description", - name = L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."], - }, - }, - }, - doExport = { - order = 2, - type = "execute", - name = L["Export"], - func = function(info) - layoutData.export = writeTable(ShadowUF.db.profile) - end, - }, - export = { - order = 3, - type = "input", - name = L["Code"], - multiline = true, - width = "full", - set = false, - get = function(info) return layoutData[info[#(info)]] end, - }, - }, - }, - }, - } - - options.args.general = { - type = "group", - childGroups = "tab", - name = L["General"], - args = { - general = { - type = "group", - order = 1, - name = L["General"], - set = set, - get = get, - args = { - general = { - order = 1, - type = "group", - inline = true, - name = L["General"], - args = { - locked = { - order = 1, - type = "toggle", - name = L["Lock frames"], - desc = L["Enables configuration mode, letting you move and giving you example frames to setup."], - set = function(info, value) - set(info, value) - ShadowUF.modules.movers:Update() - end, - arg = "locked", - }, - advanced = { - 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 Cooldown Count"], - desc = L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."], - arg = "omnicc", - 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, - type = "toggle", - name = L["Hide tooltips in combat"], - desc = L["Prevents unit tooltips from showing while in combat."], - arg = "tooltipCombat", - width = "double", - }, - bossmodCastNames = { - order = 3.1, - type = "toggle", - name = L["Use Boss Mod Cast Name overrides"], - desc = L["Use spell name overrides provided by boss mods (BigWigs) on the cast bars."], - arg = "bossmodSpellRename", - width = "double", - }, - sep2 = { - order = 3.5, - type = "description", - name = "", - width = "full", - }, - auraBorder = { - order = 5, - type = "select", - name = L["Aura border style"], - desc = L["Style of borders to show for all auras."], - values = {["dark"] = L["Dark"], ["light"] = L["Light"], ["blizzard"] = L["Blizzard"], [""] = L["None"]}, - arg = "auras.borderType", - }, - statusbar = { - order = 6, - type = "select", - name = L["Bar texture"], - dialogControl = "LSM30_Statusbar", - values = getMediaData, - arg = "bars.texture", - }, - spacing = { - order = 7, - type = "range", - name = L["Bar spacing"], - desc = L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."], - min = -10, max = 10, step = 0.05, softMin = -5, softMax = 5, - arg = "bars.spacing", - hidden = hideAdvancedOption, - }, - }, - }, - backdrop = { - order = 2, - type = "group", - inline = true, - name = L["Background/border"], - args = { - backgroundColor = { - order = 1, - type = "color", - name = L["Background color"], - hasAlpha = true, - set = setColor, - get = getColor, - arg = "backdrop.backgroundColor", - }, - borderColor = { - order = 2, - type = "color", - name = L["Border color"], - hasAlpha = true, - set = setColor, - get = getColor, - arg = "backdrop.borderColor", - }, - sep = { - order = 3, - type = "description", - name = "", - width = "full", - }, - background = { - order = 4, - type = "select", - name = L["Background"], - dialogControl = "LSM30_Background", - values = getMediaData, - arg = "backdrop.backgroundTexture", - }, - border = { - order = 5, - type = "select", - name = L["Border"], - dialogControl = "LSM30_Border", - values = getMediaData, - arg = "backdrop.borderTexture", - }, - inset = { - order = 5.5, - type = "range", - name = L["Inset"], - desc = L["How far the background should be from the unit frame border."], - min = -10, max = 10, step = 1, - hidden = hideAdvancedOption, - arg = "backdrop.inset", - }, - sep2 = { - order = 6, - type = "description", - name = "", - width = "full", - hidden = hideAdvancedOption, - }, - edgeSize = { - order = 7, - type = "range", - name = L["Edge size"], - desc = L["How large the edges should be."], - hidden = hideAdvancedOption, - min = 0, max = 20, step = 1, - arg = "backdrop.edgeSize", - }, - tileSize = { - order = 8, - type = "range", - name = L["Tile size"], - desc = L["How large the background should tile"], - hidden = hideAdvancedOption, - min = 0, max = 20, step = 1, - arg = "backdrop.tileSize", - }, - clip = { - order = 9, - type = "range", - name = L["Clip"], - desc = L["How close the frame should clip with the border."], - hidden = hideAdvancedOption, - min = 0, max = 20, step = 1, - arg = "backdrop.clip", - }, - }, - }, - font = { - order = 3, - type = "group", - inline = true, - name = L["Font"], - args = { - color = { - order = 1, - type = "color", - name = L["Default color"], - desc = L["Default font color, any color tags inside individual tag texts will override this."], - hasAlpha = true, - set = setColor, - get = getColor, - arg = "font.color", - hidden = hideAdvancedOption, - }, - sep = {order = 1.25, type = "description", name = "", hidden = hideAdvancedOption}, - font = { - order = 1.5, - type = "select", - name = L["Font"], - dialogControl = "LSM30_Font", - values = getMediaData, - arg = "font.name", - }, - size = { - order = 2, - type = "range", - name = L["Size"], - min = 1, max = 50, step = 1, softMin = 1, softMax = 20, - arg = "font.size", - }, - outline = { - order = 3, - type = "select", - name = L["Outline"], - values = {["OUTLINE"] = L["Thin outline"], ["THICKOUTLINE"] = L["Thick outline"], ["MONOCHROMEOUTLINE"] = L["Monochrome Outline"], [""] = L["None"]}, - arg = "font.extra", - hidden = hideAdvancedOption, - }, - }, - }, - bar = { - order = 4, - type = "group", - inline = true, - name = L["Bars"], - hidden = hideAdvancedOption, - args = { - override = { - order = 0, - type = "toggle", - name = L["Override color"], - desc = L["Forces a static color to be used for the background of all bars"], - set = function(info, value) - if( value and not ShadowUF.db.profile.bars.backgroundColor ) then - ShadowUF.db.profile.bars.backgroundColor = {r = 0, g = 0, b = 0} - elseif( not value ) then - ShadowUF.db.profile.bars.backgroundColor = nil - end - - ShadowUF.Layout:Reload() - end, - get = function(info) - return ShadowUF.db.profile.bars.backgroundColor and true or false - end, - }, - color = { - order = 1, - type = "color", - name = L["Background color"], - desc = L["This will override all background colorings for bars including custom set ones."], - set = setColor, - get = function(info) - if( not ShadowUF.db.profile.bars.backgroundColor ) then - return 0, 0, 0 - end - - return getColor(info) - end, - disabled = function(info) return not ShadowUF.db.profile.bars.backgroundColor end, - arg = "bars.backgroundColor", - }, - sep = { order = 2, type = "description", name = "", width = "full"}, - barAlpha = { - order = 3, - type = "range", - name = L["Bar alpha"], - desc = L["Alpha to use for bar."], - arg = "bars.alpha", - min = 0, max = 1, step = 0.05, - isPercent = true - }, - backgroundAlpha = { - order = 4, - type = "range", - name = L["Background alpha"], - desc = L["Alpha to use for bar backgrounds."], - arg = "bars.backgroundAlpha", - min = 0, max = 1, step = 0.05, - isPercent = true - }, - }, - }, - }, - }, - color = { - order = 2, - type = "group", - name = L["Colors"], - args = { - health = { - order = 1, - type = "group", - inline = true, - name = L["Health"], - set = setColor, - get = getColor, - args = { - green = { - order = 1, - type = "color", - name = L["High health"], - desc = L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."], - arg = "healthColors.green", - }, - yellow = { - order = 2, - type = "color", - name = L["Half health"], - desc = L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."], - arg = "healthColors.yellow", - }, - red = { - order = 3, - type = "color", - name = L["Low health"], - desc = L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."], - arg = "healthColors.red", - }, - friendly = { - order = 4, - type = "color", - name = L["Friendly"], - desc = L["Health bar color for friendly units."], - arg = "healthColors.friendly", - }, - neutral = { - order = 5, - type = "color", - name = L["Neutral"], - desc = L["Health bar color for neutral units."], - arg = "healthColors.neutral", - }, - hostile = { - order = 6, - type = "color", - name = L["Hostile"], - 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", - name = L["Static"], - desc = L["Color to use for health bars that are set to be colored by a static color."], - arg = "healthColors.static", - }, - inc = { - order = 8, - type = "color", - name = L["Incoming heal"], - desc = L["Bar color to use to show how much healing someone is about to receive."], - arg = "healthColors.inc", - }, - 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_YELLOW = { - 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", - inline = true, - name = L["Power"], - set = setColor, - get = getColor, - args = { - MANA = { - order = 0, - type = "color", - name = L["Mana"], - width = "half", - arg = "powerColors.MANA", - }, - RAGE = { - order = 1, - type = "color", - name = L["Rage"], - width = "half", - arg = "powerColors.RAGE", - }, - FOCUS = { - order = 2, - type = "color", - name = L["Focus"], - arg = "powerColors.FOCUS", - width = "half", - }, - ENERGY = { - order = 3, - type = "color", - name = L["Energy"], - arg = "powerColors.ENERGY", - width = "half", - }, - RUNIC_POWER = { - order = 6, - type = "color", - name = L["Runic Power"], - arg = "powerColors.RUNIC_POWER", - }, - 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"], - arg = "powerColors.AMMOSLOT", - hidden = hideAdvancedOption, - }, - FUEL = { - order = 10, - type = "color", - name = L["Fuel"], - 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 = { - order = 3, - type = "group", - inline = true, - name = L["Cast"], - set = setColor, - get = getColor, - args = { - cast = { - order = 0, - type = "color", - name = L["Casting"], - desc = L["Color used when an unit is casting a spell."], - arg = "castColors.cast", - }, - channel = { - order = 1, - type = "color", - name = L["Channelling"], - desc = L["Color used when a cast is a channel."], - arg = "castColors.channel", - }, - sep = { - order = 2, - type = "description", - name = "", - hidden = hideAdvancedOption, - width = "full", - }, - finished = { - order = 3, - type = "color", - name = L["Finished cast"], - desc = L["Color used when a cast is successfully finished."], - hidden = hideAdvancedOption, - arg = "castColors.finished", - }, - interrupted = { - order = 4, - type = "color", - name = L["Cast interrupted"], - desc = L["Color used when a cast is interrupted either by the caster themselves or by another unit."], - hidden = hideAdvancedOption, - arg = "castColors.interrupted", - }, - uninterruptible = { - order = 5, - type = "color", - name = L["Cast uninterruptible"], - desc = L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."], - arg = "castColors.uninterruptible", - }, - }, - }, - 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", - inline = true, - name = L["Classes"], - set = setColor, - get = getColor, - args = {} - }, - }, - }, - range = { - order = 5, - type = "group", - name = L["Range Checker"], - args = { - help = { - order = 0, - type = "group", - inline = true, - name = L["Help"], - args = { - help = { - order = 0, - type = "description", - 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."], - }, - }, - }, - friendly = { - order = 1, - inline = true, - type = "group", - name = L["On Friendly Units"], - args = { - friendly = { - 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 = "" - }, - 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 - - -- Add the new entry - for _, unit in pairs(ShadowUF.unitList) do - table.insert(ShadowUF.db.profile.units[unit].text, {enabled = true, name = textData.name or "??", text = "", anchorTo = textData.parent, x = 0, y = 0, anchorPoint = "C", size = 0, width = 0.50}) - end - - -- Add it to the GUI - local id = tostring(#(ShadowUF.db.profile.units.player.text)) - addTextParent.args[id .. ":label"] = addTextLabel - addTextParent.args[id] = addText - addTextParent.args[id .. ":sep"] = addTextSep - options.args.general.args.text.args[textData.parent] = options.args.general.args.text.args[textData.parent] or addTextParent - - local parent = string.sub(textData.parent, 2) - Config.tagWizard[parent] = Config.tagWizard[parent] or Config.parentTable - Config.tagWizard[parent].args[id] = Config.tagTextTable - Config.tagWizard[parent].args[id .. ":adv"] = Config.advanceTextTable - - quickIDMap[id .. ":adv"] = #(ShadowUF.db.profile.units.player.text) - - -- Reset - textData.name = nil - textData.parent = nil - - end, - }, - }, - }, - }, - }, - layout = layoutManager, - }, - } - - -- Load text - for id, text in pairs(ShadowUF.db.profile.units.player.text) do - 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 - - - Config.classTable = { - order = 0, - type = "color", - name = getName, - hasAlpha = true, - width = "half", - arg = "classColors.$key", - } - - for classToken in pairs(RAID_CLASS_COLORS) do - options.args.general.args.color.args.classColors.args[classToken] = Config.classTable - end - - options.args.general.args.color.args.classColors.args.PET = Config.classTable - options.args.general.args.color.args.classColors.args.VEHICLE = Config.classTable -end - ---------------------- --- HIDE BLIZZARD FRAMES CONFIGURATION ---------------------- -local function loadHideOptions() - Config.hideTable = { - order = function(info) return info[#(info)] == "buffs" and 1 or 2 end, - type = "toggle", - name = function(info) - local key = info[#(info)] - 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) - if( value ) then ShadowUF:HideBlizzardFrames() end - end, - hidden = false, - get = get, - arg = "hidden.$key", - } - - options.args.hideBlizzard = { - type = "group", - name = L["Hide Blizzard"], - desc = getPageDescription, - args = { - help = { - order = 0, - type = "group", - name = L["Help"], - inline = true, - args = { - description = { - type = "description", - name = L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."], - width = "full", - }, - }, - }, - hide = { - order = 1, - type = "group", - name = L["Frames"], - inline = true, - args = { - buffs = Config.hideTable, - cast = 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, - }, - }, - } - } -end - ---------------------- --- UNIT CONFIGURATION ---------------------- -local function loadUnitOptions() - -- This makes sure we don't end up with any messed up positioning due to two different anchors being used - local function fixPositions(info) - local unit = info[2] - local key = info[#(info)] - - if( key == "point" or key == "relativePoint" ) then - ShadowUF.db.profile.positions[unit].anchorPoint = "" - ShadowUF.db.profile.positions[unit].movedAnchor = nil - elseif( key == "anchorPoint" ) then - ShadowUF.db.profile.positions[unit].point = "" - ShadowUF.db.profile.positions[unit].relativePoint = "" - end - - -- Reset offset if it was a manually positioned frame, and it got anchored - -- Why 100/-100 you ask? Because anything else requires some sort of logic applied to it - -- and this means the frames won't directly overlap too which is a nice bonus - if( key == "anchorTo" ) then - ShadowUF.db.profile.positions[unit].x = 100 - ShadowUF.db.profile.positions[unit].y = -100 - end - end - - -- Hide raid option in party config - local function hideRaidOrAdvancedOption(info) - if( info[2] == "party" and ShadowUF.db.profile.advanced ) then return false end - - return info[2] ~= "raid" and info[2] ~= "raidpet" and info[2] ~= "maintank" and info[2] ~= "mainassist" - end - - local function hideRaidOption(info) - return info[2] ~= "raid" and info[2] ~= "raidpet" and info[2] ~= "maintank" and info[2] ~= "mainassist" - end - - local function hideSplitOrRaidOption(info) - if( info[2] == "raid" and ShadowUF.db.profile.units.raid.frameSplit ) then - return true - end - - return hideRaidOption(info) - end - - -- Not every option should be changed via global settings - local function hideSpecialOptions(info) - local unit = info[2] - if( unit == "global" or unit == "partypet" ) then - return true - end - - return hideAdvancedOption(info) - end - - local function checkNumber(info, value) - return tonumber(value) - end - - local function setPosition(info, value) - ShadowUF.db.profile.positions[info[2]][info[#(info)]] = value - fixPositions(info) - - if( info[2] == "raid" or info[2] == "raidpet" or info[2] == "maintank" or info[2] == "mainassist" or info[2] == "party" or info[2] == "boss" or info[2] == "arena" ) then - ShadowUF.Units:ReloadHeader(info[2]) - else - ShadowUF.Layout:Reload(info[2]) - end - end - - local function getPosition(info) - return ShadowUF.db.profile.positions[info[2]][info[#(info)]] - end - - local function setNumber(info, value) - local unit = info[2] - local key = info[#(info)] - local id = unit .. key - - -- Apply effective scaling if it's anchored to UIParent - if( ShadowUF.db.profile.positions[unit].anchorTo == "UIParent" ) then - value = value * (ShadowUF.db.profile.units[unit].scale * UIParent:GetScale()) - end - - setPosition(info, tonumber(value)) - end - - local function getString(info) - local unit = info[2] - local key = info[#(info)] - local id = unit .. key - local coord = getPosition(info) - - -- If the frame is created and it's anchored to UIParent, will return the number modified by scale - if( ShadowUF.db.profile.positions[unit].anchorTo == "UIParent" ) then - coord = coord / (ShadowUF.db.profile.units[unit].scale * UIParent:GetScale()) - end - - -- OCD, most definitely. - -- Pain to check coord == math.floor(coord) because floats are handled oddly with frames and return 0.99999999999435 - return string.gsub(string.format("%.2f", coord), "%.00$", "") - end - - - -- TAG WIZARD - local tagWizard = {} - Config.tagWizard = tagWizard - do - -- Load tag list - Config.advanceTextTable = { - order = 1, - name = function(info) return getVariable(info[2], "text", quickIDMap[info[#(info)]], "name") end, - type = "group", - inline = true, - hidden = function(info) - if( not getVariable(info[2], "text", nil, quickIDMap[info[#(info)]]) ) then return true end - return string.sub(getVariable(info[2], "text", quickIDMap[info[#(info)]], "anchorTo"), 2) ~= info[#(info) - 1] - end, - set = function(info, value) - info.arg = string.format("text.%s.%s", quickIDMap[info[#(info) - 1]], info[#(info)]) - setUnit(info, value) - end, - get = function(info) - info.arg = string.format("text.%s.%s", quickIDMap[info[#(info) - 1]], info[#(info)]) - return getUnit(info) - end, - args = { - anchorPoint = { - order = 1, - type = "select", - name = L["Anchor point"], - values = {["LC"] = L["Left Center"], ["RT"] = L["Right Top"], ["RB"] = L["Right Bottom"], ["LT"] = L["Left Top"], ["LB"] = L["Left Bottom"], ["RC"] = L["Right Center"],["TRI"] = L["Inside Top Right"], ["TLI"] = L["Inside Top Left"], ["CLI"] = L["Inside Center Left"], ["C"] = L["Inside Center"], ["CRI"] = L["Inside Center Right"], ["TR"] = L["Top Right"], ["TL"] = L["Top Left"], ["BR"] = L["Bottom Right"], ["BL"] = L["Bottom Left"]}, - hidden = hideAdvancedOption, - }, - sep = { - order = 2, - type = "description", - name = "", - width = "full", - hidden = hideAdvancedOption, - }, - width = { - order = 3, - name = L["Width weight"], - 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 = function(info) - return hideAdvancedOption(info) or getVariable(info[2], "text", quickIDMap[info[#(info) - 1]], "block") - end, - }, - size = { - order = 4, - name = L["Size"], - desc = L["Let's you modify the base font size to either make it larger or smaller."], - type = "range", - 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", - name = L["X Offset"], - min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100, - hidden = false, - }, - y = { - order = 6, - type = "range", - name = L["Y Offset"], - min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100, - hidden = false, - }, - }, - } - - Config.parentTable = { - order = 0, - type = "group", - name = function(info) return getName(info) or string.sub(info[#(info)], 1) end, - hidden = function(info) return not getVariable(info[2], info[#(info)], nil, "enabled") end, - args = {} - } - - 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 modUnit in pairs(modifyUnits) do - if( ShadowUF.Tags.unitRestrictions[tag] == modUnit ) then - return false - 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 - end - - 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 - end - else - -- If the only units that are in the global configuration have the tag filtered, then don't bother showing it - for modUnit in pairs(modifyUnits) do - if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(modUnit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then - return false - 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 - - local savedTagTexts = {} - local function selectTag(info, value) - local unit = info[2] - local id = tonumber(info[#(info) - 2]) - local tag = info[#(info)] - local text = getVariable(unit, "text", id, "text") - local savedText - - if( value ) then - if( unit == "global" ) then - table.wipe(savedTagTexts) - - -- Set special tag texts based on the unit, so targettarget won't get a tag that will cause errors - local tagGroup = ShadowUF.Tags.defaultCategories[tag] - for modUnit in pairs(modifyUnits) do - savedTagTexts[modUnit] = getVariable(modUnit, "text", id, "text") - if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(modUnit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then - if( not ShadowUF.Tags.unitRestrictions[tag] or ShadowUF.Tags.unitRestrictions[tag] == modUnit ) then - if( text == "" ) then - savedTagTexts[modUnit] = string.format("[%s]", tag) - else - savedTagTexts[modUnit] = string.format("%s[( )%s]", savedTagTexts[modUnit], tag) - end - - savedTagTexts.global = savedTagTexts[modUnit] - end - end - end - else - if( text == "" ) then - text = string.format("[%s]", tag) - else - text = string.format("%s[( )%s]", text, tag) - end - end - - -- Removing a tag from a single unit, super easy :< - else - -- Ugly, but it works - 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 - end - - if( unit == "global" ) then - for modUnit in pairs(modifyUnits) do - if( savedTagTexts[modUnit] ) then - setVariable(modUnit, "text", id, "text", savedTagTexts[modUnit]) - end - end - - setVariable("global", "text", id, "text", savedTagTexts.global) - else - setVariable(unit, "text", id, "text", text) - end - end - - local function getTag(info) - local text = getVariable(info[2], "text", tonumber(info[#(info) - 2]), "text") - local tag = info[#(info)] - - -- FUN WITH PATTERN MATCHING - if( string.match(text, "%[" .. tag .. "%]") or string.match(text, "%)" .. tag .. "%]") or string.match(text, "%[" .. tag .. "%(") or string.match(text, "%)" .. tag .. "%(") ) then - return true - end - - return false - end - - Config.tagTextTable = { - type = "group", - name = function(info) return getVariable(info[2], "text", nil, tonumber(info[#(info)])) and getVariable(info[2], "text", tonumber(info[#(info)]), "name") or "" end, - hidden = function(info) - if( not getVariable(info[2], "text", nil, tonumber(info[#(info)])) ) then return true end - return string.sub(getVariable(info[2], "text", tonumber(info[#(info)]), "anchorTo"), 2) ~= info[#(info) - 1] end, - set = false, - get = false, - args = { - text = { - order = 0, - type = "input", - name = L["Text"], - width = "full", - hidden = false, - set = function(info, value) setUnit(info, string.gsub(value, "||", "|")) end, - get = function(info) return string.gsub(getUnit(info), "|", "||") end, - arg = "text.$parent.text", - }, - }, - } - - - local function getCategoryOrder(info) - return info[#(info)] == "health" and 1 or info[#(info)] == "power" and 2 or info[#(info)] == "misc" and 3 or 4 - end - - for _, cat in pairs(ShadowUF.Tags.defaultCategories) do - Config.tagTextTable.args[cat] = Config.tagTextTable.args[cat] or { - order = getCategoryOrder, - type = "group", - inline = true, - name = getName, - hidden = hideBlacklistedGroup, - set = selectTag, - get = getTag, - args = {}, - } - end - - Config.tagTable = { - order = 0, - type = "toggle", - hidden = hideBlacklistedTag, - name = getTagName, - desc = getTagHelp, - } - - local tagList = {} - for tag in pairs(ShadowUF.Tags.defaultTags) do - local category = ShadowUF.Tags.defaultCategories[tag] or "misc" - Config.tagTextTable.args[category].args[tag] = Config.tagTable - end - - for tag, data in pairs(ShadowUF.db.profile.tags) do - local category = data.category or "misc" - Config.tagTextTable.args[category].args[tag] = Config.tagTable - end - - local parentList = {} - for id, text in pairs(ShadowUF.db.profile.units.player.text) do - parentList[text.anchorTo] = parentList[text.anchorTo] or {} - parentList[text.anchorTo][id] = text - end - - local nagityNagNagTable = { - order = 0, - type = "group", - name = L["Help"], - inline = true, - hidden = false, - args = { - help = { - order = 0, - type = "description", - name = L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."], - }, - }, - } - - for parent, list in pairs(parentList) do - parent = string.sub(parent, 2) - tagWizard[parent] = Config.parentTable - Config.parentTable.args.help = nagityNagNagTable - - for id in pairs(list) do - tagWizard[parent].args[tostring(id)] = Config.tagTextTable - tagWizard[parent].args[tostring(id) .. ":adv"] = Config.advanceTextTable - - quickIDMap[tostring(id) .. ":adv"] = id - end - end - end - - local function disableAnchoredTo(info) - local auras = getVariable(info[2], "auras", nil, info[#(info) - 2]) - - return auras.anchorOn or not auras.enabled - end - - local function disableSameAnchor(info) - local buffs = getVariable(info[2], "auras", nil, "buffs") - 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) - 2], "enabled") ) then - return true - end - - 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) - 2] or buffs.anchorOn or debuffs.anchorOn ) then - return false - end - - return buffs.anchorPoint == debuffs.anchorPoint - end - - local defaultAuraList = {["BL"] = L["Bottom"], ["TL"] = L["Top"], ["LT"] = L["Left"], ["RT"] = L["Right"]} - local advancedAuraList = {["BL"] = L["Bottom Left"], ["BR"] = L["Bottom Right"], ["TL"] = L["Top Left"], ["TR"] = L["Top Right"], ["RT"] = L["Right Top"], ["RB"] = L["Right Bottom"], ["LT"] = L["Left Top"], ["LB"] = L["Left Bottom"]} - local function getAuraAnchors() - 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", - 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 = false, - args = { - 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", - } - } - }, - filters = { - type = "group", - name = L["Filters"], - order = 1, - set = function(info, value) - getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]] = value - reloadUnitAuras() - end, - get = function(info) - return getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]] - end, - 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" - }, - } - }, - 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 - } - } - }, - positioning = { - type = "group", - name = L["Positioning"], - order = 3, - args = { - anchorOn = { - order = 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, - width = "full", - arg = "auras.$parentparent.anchorOn", - }, - anchorPoint = { - order = 1.5, - 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", - }, - size = { - order = 2, - type = "range", - name = L["Icon Size"], - min = 1, max = 30, step = 1, - arg = "auras.$parentparent.size", - }, - sep1 = {order = 3, type = "description", name = "", width = "full"}, - perRow = { - order = 13, - 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 = 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) - 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 = 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) - 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 = 18, - type = "range", - name = L["X Offset"], - min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100, - disabled = disableSameAnchor, - hidden = hideAdvancedOption, - arg = "auras.$parentparent.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.$parentparent.y", - }, - - } - } - } - } - - local function hideBarOption(info) - local module = info[#(info) - 1] - if( ShadowUF.modules[module].moduleHasBar or getVariable(info[2], module, nil, "isBar") ) then - return false - end - - return true - end - - local function disableIfCastName(info) - return not getVariable(info[2], "castBar", "name", "enabled") - end - - - Config.barTable = { - order = getModuleOrder, - name = getName, - type = "group", - inline = false, - hidden = function(info) return hideRestrictedOption(info) or not getVariable(info[2], info[#(info)], nil, "enabled") end, - args = { - enableBar = { - order = 1, - type = "toggle", - name = L["Show as bar"], - 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", - }, - 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", - name = L["Show background"], - desc = L["Show a background behind the bars with the same texture/color but faded out."], - hidden = hideBarOption, - arg = "$parent.background", - }, - 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 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", - name = L["Order"], - min = 0, max = 100, step = 5, - hidden = hideBarOption, - arg = "$parent.order", - }, - height = { - order = 5, - 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 = "$parent.height", - } - }, - } - - Config.indicatorTable = { - order = 0, - name = function(info) - if( info[#(info)] == "status" and info[2] == "player" ) then - return L["Combat/resting status"] - end - - return getName(info) - end, - desc = function(info) return INDICATOR_DESC[info[#(info)]] end, - type = "group", - hidden = hideRestrictedOption, - args = { - enabled = { - order = 0, - type = "toggle", - name = L["Enable indicator"], - hidden = false, - arg = "indicators.$parent.enabled", - }, - sep1 = { - order = 1, - type = "description", - name = "", - width = "full", - hidden = function() return not ShadowUF.db.profile.advanced end, - }, - anchorPoint = { - order = 2, - type = "select", - name = L["Anchor point"], - values = positionList, - hidden = false, - arg = "indicators.$parent.anchorPoint", - }, - size = { - order = 4, - type = "range", - name = L["Size"], - min = 1, max = 40, step = 1, - hidden = hideAdvancedOption, - arg = "indicators.$parent.size", - }, - x = { - order = 5, - type = "range", - name = L["X Offset"], - min = -100, max = 100, step = 1, softMin = -50, softMax = 50, - hidden = false, - arg = "indicators.$parent.x", - }, - y = { - order = 6, - type = "range", - name = L["Y Offset"], - min = -100, max = 100, step = 1, softMin = -50, softMax = 50, - hidden = false, - arg = "indicators.$parent.y", - }, - }, - } - - Config.unitTable = { - type = "group", - childGroups = "tab", - order = getUnitOrder, - name = getName, - hidden = isUnitDisabled, - args = { - general = { - order = 1, - name = L["General"], - type = "group", - hidden = isModifiersSet, - set = setUnit, - get = getUnit, - args = { - vehicle = { - order = 1, - type = "group", - inline = true, - name = L["Vehicles"], - hidden = function(info) return info[2] ~= "player" and info[2] ~= "party" or not ShadowUF.db.profile.advanced end, - args = { - disable = { - order = 0, - type = "toggle", - name = L["Disable vehicle swap"], - desc = L["Disables the unit frame from turning into a vehicle when the player enters one."], - set = function(info, value) - setUnit(info, value) - local unit = info[2] - if( unit == "player" ) then - if( ShadowUF.Units.unitFrames.pet ) then - ShadowUF.Units.unitFrames.pet:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units[unit].disableVehicle) - end - - if( ShadowUF.Units.unitFrames.player ) then - ShadowUF.Units:CheckVehicleStatus(ShadowUF.Units.unitFrames.player) - end - elseif( unit == "party" ) then - for frame in pairs(ShadowUF.Units.unitFrames) do - if( frame.unitType == "partypet" ) then - frame:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units[unit].disableVehicle) - elseif( frame.unitType == "party" ) then - ShadowUF.Units:CheckVehicleStatus(frame) - end - end - end - end, - arg = "disableVehicle", - }, - }, - }, - portrait = { - order = 2, - type = "group", - inline = true, - hidden = false, - name = L["Portrait"], - args = { - portrait = { - order = 0, - type = "toggle", - name = string.format(L["Enable %s"], L["Portrait"]), - arg = "portrait.enabled", - }, - portraitType = { - order = 1, - type = "select", - name = L["Portrait type"], - values = {["class"] = L["Class icon"], ["2D"] = L["2D"], ["3D"] = L["3D"]}, - arg = "portrait.type", - }, - alignment = { - order = 2, - type = "select", - name = L["Position"], - values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, - arg = "portrait.alignment", - }, - }, - }, - fader = { - order = 3, - type = "group", - inline = true, - name = L["Combat fader"], - hidden = hideRestrictedOption, - args = { - fader = { - order = 0, - type = "toggle", - 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" - }, - combatAlpha = { - order = 1, - type = "range", - name = L["Combat alpha"], - desc = L["Frame alpha while this unit is in combat."], - min = 0, max = 1.0, step = 0.1, - arg = "fader.combatAlpha", - hidden = false, - isPercent = true, - }, - inactiveAlpha = { - order = 2, - type = "range", - name = L["Inactive alpha"], - desc = L["Frame alpha when you are out of combat while having no target and 100% mana or energy."], - min = 0, max = 1.0, step = 0.1, - arg = "fader.inactiveAlpha", - hidden = false, - isPercent = true, - }, - } - }, - range = { - order = 3, - type = "group", - inline = true, - name = L["Range indicator"], - hidden = hideRestrictedOption, - args = { - fader = { - order = 0, - type = "toggle", - name = string.format(L["Enable %s"], L["Range indicator"]), - desc = L["Fades out the unit frames of people who are not within range of you."], - arg = "range.enabled", - hidden = false, - }, - inAlpha = { - order = 1, - type = "range", - name = L["In range alpha"], - desc = L["Frame alpha while this unit is in combat."], - min = 0, max = 1.0, step = 0.05, - arg = "range.inAlpha", - hidden = false, - isPercent = true, - }, - oorAlpha = { - order = 2, - type = "range", - name = L["Out of range alpha"], - min = 0, max = 1.0, step = 0.05, - arg = "range.oorAlpha", - hidden = false, - isPercent = true, - }, - } - }, - highlight = { - order = 3.5, - type = "group", - inline = true, - name = L["Border highlighting"], - hidden = hideRestrictedOption, - args = { - mouseover = { - order = 3, - type = "toggle", - name = L["On mouseover"], - desc = L["Highlight units when you mouse over them."], - arg = "highlight.mouseover", - hidden = false, - }, - attention = { - order = 4, - type = "toggle", - name = L["For target/focus"], - desc = L["Highlight units that you are targeting or have focused."], - arg = "highlight.attention", - hidden = function(info) return info[2] == "target" or info[2] == "focus" end, - }, - aggro = { - order = 5, - type = "toggle", - name = L["On aggro"], - desc = L["Highlight units that have aggro on any mob."], - arg = "highlight.aggro", - 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, - type = "toggle", - name = L["On curable debuff"], - desc = L["Highlight units that are debuffed with something you can cure."], - arg = "highlight.debuff", - 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, - type = "range", - name = L["Border alpha"], - min = 0, max = 1, step = 0.05, - isPercent = true, - hidden = false, - arg = "highlight.alpha", - }, - size = { - order = 8, - type = "range", - name = L["Border thickness"], - min = 0, max = 50, step = 1, - arg = "highlight.size", - hidden = false, - }, - }, - }, - -- SOUL SHARDS - barSouls = { - order = 4, - type = "group", - inline = true, - 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["Soul Shards"]), - hidden = false, - arg = "soulShards.enabled", - }, - growth = { - order = 2, - type = "select", - name = L["Growth"], - values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, - hidden = false, - arg = "soulShards.growth", - }, - showAlways = { - order = 3, - type = "toggle", - name = L["Don't hide when empty"], - hidden = false, - arg = "soulShards.showAlways", - }, - }, - }, - soulShards = { - order = 4, - type = "group", - inline = true, - 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["Soul Shards"]), - hidden = false, - arg = "soulShards.enabled", - }, - 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 = "soulShards.growth", - }, - size = { - order = 2, - type = "range", - name = L["Size"], - min = 0, max = 50, step = 1, softMin = 0, softMax = 20, - hidden = hideAdvancedOption, - arg = "soulShards.size", - }, - spacing = { - order = 3, - type = "range", - name = L["Spacing"], - min = -30, max = 30, step = 1, softMin = -15, softMax = 15, - hidden = hideAdvancedOption, - arg = "soulShards.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 = "soulShards.anchorPoint", - }, - x = { - order = 6, - type = "range", - name = L["X Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "soulShards.x", - }, - y = { - order = 7, - type = "range", - name = L["Y Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "soulShards.y", - }, - }, - }, - -- ARCANE CHARGES - barArcane = { - order = 4, - type = "group", - inline = true, - 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 = { - 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["Arcane Charges"]), - hidden = false, - arg = "arcaneCharges.enabled", - }, - 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 = "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, - hidden = false, - arg = "arcaneCharges.anchorPoint", - }, - x = { - order = 6, - type = "range", - name = L["X Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "arcaneCharges.x", - }, - y = { - order = 7, - type = "range", - name = L["Y Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "arcaneCharges.y", - }, - }, - }, - -- HOLY POWER - barHolyPower = { - order = 4, - type = "group", - inline = true, - 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 = { - enabled = { - order = 1, - type = "toggle", - name = string.format(L["Enable %s"], L["Holy Power"]), - hidden = false, - arg = "holyPower.enabled", - }, - 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["Don't hide when empty"], - hidden = false, - arg = "holyPower.showAlways", - }, - }, - }, - holyPower = { - order = 4, - type = "group", - inline = true, - 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 = { - enabled = { - order = 0, - type = "toggle", - name = string.format(L["Enable %s"], L["Holy Power"]), - hidden = false, - arg = "holyPower.enabled", - }, - 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", - }, - size = { - order = 2, - type = "range", - name = L["Size"], - min = 0, max = 50, step = 1, softMin = 0, softMax = 20, - hidden = hideAdvancedOption, - arg = "holyPower.size", - }, - spacing = { - order = 3, - type = "range", - name = L["Spacing"], - min = -30, max = 30, step = 1, softMin = -15, softMax = 15, - hidden = hideAdvancedOption, - arg = "holyPower.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 = "holyPower.anchorPoint", - }, - x = { - order = 6, - type = "range", - name = L["X Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "holyPower.x", - }, - y = { - order = 7, - type = "range", - name = L["Y Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "holyPower.y", - }, - }, - }, - -- SHADOW ORBS - barShadowOrbs = { - order = 4, - type = "group", - inline = true, - 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 = { - enabled = { - order = 1, - type = "toggle", - name = string.format(L["Enable %s"], L["Shadow Orbs"]), - hidden = false, - arg = "shadowOrbs.enabled", - }, - growth = { - order = 2, - type = "select", - 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", - }, - }, - }, - shadowOrbs = { - order = 4, - type = "group", - inline = true, - 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 = { - enabled = { - order = 0, - type = "toggle", - name = string.format(L["Enable %s"], L["Shadow Orbs"]), - hidden = false, - arg = "shadowOrbs.enabled", - }, - 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 = "shadowOrbs.growth", - }, - size = { - order = 2, - type = "range", - name = L["Size"], - min = 0, max = 50, step = 1, softMin = 0, softMax = 20, - hidden = hideAdvancedOption, - arg = "shadowOrbs.size", - }, - spacing = { - order = 3, - type = "range", - name = L["Spacing"], - min = -30, max = 30, step = 1, softMin = -15, softMax = 15, - hidden = hideAdvancedOption, - arg = "shadowOrbs.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 = "shadowOrbs.anchorPoint", - }, - x = { - order = 6, - type = "range", - name = L["X Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "shadowOrbs.x", - }, - y = { - order = 7, - type = "range", - name = L["Y Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "shadowOrbs.y", - }, - }, - }, - -- Chi - barChi = { - order = 4, - type = "group", - inline = true, - 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 = { - enabled = { - order = 1, - type = "toggle", - name = string.format(L["Enable %s"], L["Chi"]), - hidden = false, - arg = "chi.enabled", - }, - growth = { - order = 2, - type = "select", - name = L["Growth"], - values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, - hidden = false, - arg = "chi.growth", - }, - 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["Growth"], - values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]}, - hidden = false, - arg = "chi.growth", - }, - 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 = 6, - type = "range", - name = L["X Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "chi.x", - }, - y = { - order = 7, - type = "range", - name = L["Y Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "chi.y", - }, - }, - }, - -- COMBO POINTS - barComboPoints = { - 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, - args = { - enabled = { - order = 1, - type = "toggle", - name = string.format(L["Enable %s"], L["Combo points"]), - hidden = false, - arg = "comboPoints.enabled", - }, - growth = { - order = 2, - type = "select", - name = L["Growth"], - values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, - hidden = false, - arg = "comboPoints.growth", - }, - showAlways = { - order = 3, - type = "toggle", - name = L["Don't hide when empty"], - hidden = false, - arg = "comboPoints.showAlways", - }, - }, - }, - comboPoints = { - 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, - args = { - enabled = { - order = 0, - type = "toggle", - name = string.format(L["Enable %s"], L["Combo points"]), - hidden = false, - arg = "comboPoints.enabled", - }, - 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 = "comboPoints.growth", - }, - size = { - order = 2, - type = "range", - name = L["Size"], - min = 0, max = 50, step = 1, softMin = 0, softMax = 20, - hidden = hideAdvancedOption, - arg = "comboPoints.size", - }, - 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["Anchor point"], - values = positionList, - hidden = false, - arg = "comboPoints.anchorPoint", - }, - x = { - order = 6, - type = "range", - name = L["X Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "comboPoints.x", - }, - y = { - order = 7, - type = "range", - name = L["Y Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "comboPoints.y", - }, - }, - }, - -- COMBO POINTS - barAuraPoints = { - order = 4, - type = "group", - inline = true, - 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["Aura Combo Points"]), - hidden = false, - arg = "auraPoints.enabled", - }, - growth = { - order = 2, - type = "select", - name = L["Growth"], - values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, - hidden = false, - arg = "auraPoints.growth", - }, - showAlways = { - order = 3, - type = "toggle", - name = L["Don't hide when empty"], - hidden = false, - arg = "auraPoints.showAlways", - }, - }, - }, - auraPoints = { - order = 4, - type = "group", - inline = true, - 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 = 0, - type = "toggle", - name = string.format(L["Enable %s"], L["Aura Combo Points"]), - hidden = false, - arg = "auraPoints.enabled", - }, - 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 = "auraPoints.growth", - }, - size = { - order = 2, - type = "range", - name = L["Size"], - min = 0, max = 50, step = 1, softMin = 0, softMax = 20, - hidden = hideAdvancedOption, - arg = "auraPoints.size", - }, - spacing = { - order = 3, - type = "range", - name = L["Spacing"], - min = -30, max = 30, step = 1, softMin = -15, softMax = 15, - hidden = hideAdvancedOption, - arg = "auraPoints.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 = "auraPoints.anchorPoint", - }, - x = { - order = 6, - type = "range", - name = L["X Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "auraPoints.x", - }, - y = { - order = 7, - type = "range", - name = L["Y Offset"], - min = -30, max = 30, step = 1, - hidden = false, - arg = "auraPoints.y", - }, - }, - }, - combatText = { - order = 5, - type = "group", - inline = true, - name = L["Combat text"], - hidden = hideRestrictedOption, - args = { - combatText = { - 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", - hidden = false, - }, - sep = { - order = 1, - type = "description", - name = "", - width = "full", - hidden = hideAdvancedOption, - }, - anchorPoint = { - order = 3, - type = "select", - name = L["Anchor point"], - values = positionList, - arg = "combatText.anchorPoint", - hidden = hideAdvancedOption, - }, - x = { - order = 4, - type = "range", - name = L["X Offset"], - min = -50, max = 50, step = 1, - arg = "combatText.x", - hidden = hideAdvancedOption, - }, - y = { - order = 5, - type = "range", - name = L["Y Offset"], - min = -50, max = 50, step = 1, - arg = "combatText.y", - hidden = hideAdvancedOption, - }, - }, - }, - }, - }, - attributes = { - order = 1.5, - type = "group", - 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 = { - show = { - order = 0.5, - type = "group", - inline = true, - name = L["Visibility"], - hidden = function(info) return info[2] ~= "party" and info[2] ~= "raid" 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", - }, - hideSemiRaidParty = { - order = 1, - type = "toggle", - 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", - }, - hideRaid = { - order = 2, - 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", - }, - 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" - }, - 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", - }, - }, - }, - general = { - order = 1, - type = "group", - inline = true, - name = L["General"], - hidden = false, - 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, - }, - 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."], - 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."], - 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) - 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 - local unit = info[#(info)] - 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 = GetSpellName(name) - local icon = GetSpellTexture(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 _, unitEntry in pairs(ShadowUF.unitList) do - ShadowUF.db.profile.filters[filterKey][zoneConfig .. unitEntry] = 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 _, unitEntry in pairs(ShadowUF.unitList) do - ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unitEntry] = nil - ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unitEntry] = nil - ShadowUF.db.profile.filters.zoneoverride[zoneConfig .. unitEntry] = 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 manageFiltersTableEntry = { - 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 - - manageFiltersTableEntry.args[tostring(filterID)] = CopyTable(filterEditTable) - manageFiltersTableEntry.args.groups.args[filterID .. "label"] = filterLabel - manageFiltersTableEntry.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 - - manageFiltersTableEntry.args[tostring(filterID)].args.spells.args[spellID .. "label"] = spellLabel - manageFiltersTableEntry.args[tostring(filterID)].args.spells.args[tostring(spellID)] = spellRow - end - end - - if( not hasSpells ) then - manageFiltersTableEntry.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 - manageFiltersTableEntry.args.groups.args.noFilters = noFilters - end - - return manageFiltersTableEntry - 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, - 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) - 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) - 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."] - else - tagData.error = nil - 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, - } - - 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 - - -- Tag configuration - options.args.tags = { - type = "group", - childGroups = "tab", - name = L["Add Tags"], - desc = getPageDescription, - hidden = hideAdvancedOption, - args = { - 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", - name = L["Add new tag"], - 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, - 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, - }, - }, - }, - }, - }, - help = { - order = 3, - type = "group", - name = L["Help"], - args = { - general = { - order = 0, - 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."], - }, - }, - }, - documentation = { - order = 1, - type = "group", - 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 = { - lua = { - 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, - width = "full", - }, - }, - }, - }, - }, - }, - } - - -- 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 - - -- Annoying yes, but only way that works - ShadowUF.Units:CheckPlayerZone(true) - - if( unit == "global" ) then - globalVisibility[area .. key] = value - 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 - - 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 - - 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) - 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, - }, - } - } - - 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 - end - - areaTable.args.global = Config.visibilityTable - for _, unit in pairs(ShadowUF.unitList) do - if( not unitBlacklist[unit] ) then - areaTable.args[unit] = Config.visibilityTable - end - 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, - }, - } -end - ---------------------- --- AURA INDICATORS OPTIONS ---------------------- -local function loadAuraIndicatorsOptions() - local Indicators = ShadowUF.modules.auraIndicators - local auraFilters = Indicators.auraFilters - - 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 - - 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 = GetSpellName(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 - - return indicatorList - 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 - - return string.format(L["%d auras in group"], totalInGroup) - end, - args = {}, - } - - local auraConfigTable = { - order = 0, - type = "group", - icon = function(info) - local aura = auraMap[info[#(info)]] - return tonumber(aura) and (GetSpellTexture(aura)) or nil - end, - name = function(info) - local aura = auraMap[info[#(info)]] - return tonumber(aura) and string.format("%s (#%i)", GetSpellName(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)] - - -- 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 - - 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 config[key] - end, - 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["Show aura icon"], - desc = L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."], - hidden = false, - }, - 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] - - 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 - - ShadowUF.Layout:Reload() - end, - }, - }, - } - - 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 ShadowUF.db.profile.auraIndicators.filters[indicator][filter][key] - end, - 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 - } - } - }, - 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 - } - } - } - } - } - - local indicatorTable = { - order = 1, - type = "group", - name = function(info) return ShadowUF.db.profile.auraIndicators.indicators[info[#(info)]].name end, - args = { - config = { - order = 0, - type = "group", - inline = true, - 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 = { - 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, - }, - }, - }, - }, - } - - local parentLinkTable = { - order = 3, - type = "group", - icon = function(info) - local aura = auraMap[info[#(info)]] - return tonumber(aura) and (GetSpellTexture(aura)) or nil - end, - name = function(info) - local aura = linkMap[info[#(info)]] - return tonumber(aura) and string.format("%s (#%i)", GetSpellName(aura) or "Unknown", aura) or aura - end, - args = {}, - } - - local childLinkTable = { - order = 1, - icon = function(info) - local aura = auraMap[info[#(info)]] - return tonumber(aura) and (GetSpellTexture(aura)) or nil - end, - name = function(info) - local aura = linkMap[info[#(info)]] - return tonumber(aura) and string.format("%s (#%i)", GetSpellName(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", - inline = true, - args = { - 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 = function(info) return string.format(L["On %s units"], L.units[info[3]]) end, - args = { - 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["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 - } - - 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 - } - - 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, - get = function(info, value) return not globalConfig[groupMap[info[#(info)]]] end - } - - 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 enabledUnits - end - - 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", - hidden = false, - args = { - indicators = { - order = 1, - type = "group", - name = L["Indicators"], - childGroups = "tree", - args = { - add = { - order = 0, - type = "group", - name = L["Add Indicator"], - args = { - add = { - order = 0, - 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, - }, - }, - }, - }, - }, - }, - }, - auras = { - order = 2, - type = "group", - 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 = { - add = { - order = 0, - type = "group", - name = L["Add Aura"], - set = function(info, value) addAura[info[#(info)]] = value end, - get = function(info) return addAura[info[#(info)]] end, - args = { - name = { - order = 0, - 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."] - }, - 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["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 GetSpellTexture directly - Indicators.auraConfig[addAura.name] = {indicator = "", group = group, iconTexture = GetSpellTexture(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 - - addAura.name = nil - addAura.custom = nil - addAura.group = nil - - -- Check if the group exists - local gID - for id, name in pairs(groupMap) do - if( name == group ) then - gID = id - break - end - end - - 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 = {} - }, - }, - }, - linked = { - order = 3, - type = "group", - name = L["Linked spells"], - childGroups = "tree", - hidden = true, - args = { - help = { - order = 0, - type = "group", - name = L["Help"], - inline = true, - args = { - help = { - order = 0, - type = "description", - 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", - }, - }, - }, - add = { - order = 1, - type = "group", - name = L["Add link"], - inline = true, - set = function(info, value) - addLink[info[#(info)] ] = value - end, - get = function(info) return addLink[info[#(info)] ] end, - args = { - from = { - order = 0, - type = "input", - name = L["Link from"], - desc = L["Spell you want to link to a primary aura, the casing must be exact."], - }, - to = { - order = 1, - type = "select", - name = L["Link to"], - values = getAuraList, - }, - link = { - order = 3, - type = "execute", - name = L["Link"], - disabled = function() return not addLink.from or not addLink.to or addLink.from == "" end, - func = function(info) - 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 - - if( not pID ) then - linkID = linkID + 1 - pID = linkID - linkMap[tostring(linkID)] = addLink.to - end - - 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, - }, - }, - }, - }, - }, - units = { - order = 4, - type = "group", - name = L["Enable Indicators"], - args = { - help = { - order = 0, - type = "group", - name = L["Help"], - inline = true, - args = { - help = { - order = 0, - type = "description", - 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", - }, - }, - }, - global = { - order = 0, - type = "group", - name = L["Global"], - desc = L["Global configurating will let you mass enable or disable aura groups for multiple units at once."], - args = { - units = { - order = 0, - 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 = {} - }, - }, - }, - }, - }, - classes = { - order = 5, - type = "group", - name = L["Disable Auras by Class"], - childGroups = "tree", - args = { - help = { - order = 0, - type = "group", - name = L["Help"], - inline = true, - args = { - help = { - order = 0, - 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 = {}, - } - - local classAuraTable = { - order = 1, - type = "toggle", - icon = function(info) - local aura = auraMap[info[#(info)]] - return tonumber(aura) and (GetSpellTexture(aura)) or nil - end, - name = function(info) - local aura = tonumber(auraMap[info[#(info)]]) - if( not aura ) then return auraMap[info[#(info)]] end - - local name = GetSpellName(aura) - local icon = GetSpellTexture(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, - } - - -- 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 - - ShadowUF.db.profile.auraIndicators.linked[from] = to - options.args.auraIndicators.args.linked.args[tostring(pID)] = parentLinkTable - parentLinkTable.args[tostring(linkID)] = childLinkTable - - linkMap[tostring(linkID)] = from - linkMap[tostring(pID)] = to - end - - -- 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 - - -- Now create all of the parent stuff - for group in pairs(groups) do - 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 - - groupID = groupID + 1 - end - - 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 - - -- Build class status thing - for classToken in pairs(RAID_CLASS_COLORS) do - options.args.auraIndicators.args.classes.args[classToken] = classTable - 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 - - -- 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 - - advanceTextTable.args.anchorPoint.hidden = unlockRaidText - advanceTextTable.args.sep.hidden = unlockRaidText - advanceTextTable.args.x.hidden = unlockRaidText - advanceTextTable.args.y.hidden = unlockRaidText -end - -local function loadOptions() - options = { - type = "group", - name = "Shadowed UF", - args = {} - } - - loadGeneralOptions() - loadUnitOptions() - loadHideOptions() - 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 - - -- Options finished loading, fire callback for any non-default modules that want to be included - ShadowUF:FireModuleEvent("OnConfigurationLoad") -end - -local defaultToggles -function Config:Open() - AceDialog = AceDialog or LibStub("AceConfigDialog-3.0") - AceRegistry = AceRegistry or LibStub("AceConfigRegistry-3.0") - - if( not registered ) then - loadOptions() - - 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 +local Config = {} +local AceDialog, AceRegistry, AceGUI, SML, registered, options +local playerClass = select(2, UnitClass("player")) +local modifyUnits, globalConfig = {}, {} +local L = ShadowUF.L + +ShadowUF.Config = Config + +local GetSpellName = C_Spell.GetSpellName +local GetSpellTexture = C_Spell.GetSpellTexture + +--[[ + The part that makes configuration a pain when you actually try is it gets unwieldly when you're adding special code to deal with + showing help for certain cases, swapping tabs etc that makes it work smoothly. + + 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", "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 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 = { + ["general"] = L["General configuration to all enabled units."], + ["enableUnits"] = L["Various units can be enabled through this page, such as raid or party targets."], + ["hideBlizzard"] = L["Hiding and showing various aspects of the default UI such as the player buff frames."], + ["units"] = L["Configuration to specific unit frames."], + ["visibility"] = L["Disabling unit modules in various instances."], + ["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 = {["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"], ["sumPending"] = L["Summon Pending"], ["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."], ["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 unitOrder = {} +for order, unit in pairs(ShadowUF.unitList) do unitOrder[unit] = order end +local fullReload = {["bars"] = true, ["auras"] = true, ["backdrop"] = true, ["font"] = true, ["classColors"] = true, ["powerColors"] = true, ["healthColors"] = true, ["xpColors"] = true, ["omnicc"] = true} +local quickIDMap = {} + +-- Helper functions +local function getPageDescription(info) + return PAGE_DESC[info[#(info)]] +end + +local function getFrameName(unit) + if( unit == "raidpet" or unit == "raid" or unit == "party" or unit == "maintank" or unit == "mainassist" or unit == "boss" or unit == "arena" ) then + return string.format("#SUFHeader%s", unit) + end + + return string.format("#SUFUnit%s", unit) +end + +local anchorList = {} +local function getAnchorParents(info) + local unit = info[2] + for k in pairs(anchorList) do anchorList[k] = nil end + + if( ShadowUF.Units.childUnits[unit] ) then + anchorList["$parent"] = string.format(L["%s member"], L.units[ShadowUF.Units.childUnits[unit]]) + return anchorList + end + + anchorList["UIParent"] = L["Screen"] + + -- Don't let a frame anchor to a frame thats anchored to it already (Stop infinite loops-o-doom) + local currentName = getFrameName(unit) + for _, unitID in pairs(ShadowUF.unitList) do + if( unitID ~= unit and ShadowUF.db.profile.positions[unitID] and ShadowUF.db.profile.positions[unitID].anchorTo ~= currentName ) then + anchorList[getFrameName(unitID)] = string.format(L["%s frames"], L.units[unitID] or unitID) + end + end + + return anchorList +end + +local function selectDialogGroup(group, key) + AceDialog.Status.ShadowedUF.children[group].status.groups.selected = key + AceRegistry:NotifyChange("ShadowedUF") +end + +local function selectTabGroup(group, subGroup, key) + AceDialog.Status.ShadowedUF.children[group].status.groups.selected = subGroup + AceDialog.Status.ShadowedUF.children[group].children[subGroup].status.groups.selected = key + AceRegistry:NotifyChange("ShadowedUF") +end + +local function hideAdvancedOption(info) + return not ShadowUF.db.profile.advanced +end + +local function hideBasicOption(info) + return ShadowUF.db.profile.advanced +end + +local function isUnitDisabled(info) + local unit = info[#(info)] + local enabled = ShadowUF.db.profile.units[unit].enabled + for _, visibility in pairs(ShadowUF.db.profile.visibility) do + if( visibility[unit] ) then + enabled = visibility[unit] + break + end + end + + return not enabled +end + +local function mergeTables(parent, child) + for key, value in pairs(child) do + if( type(parent[key]) == "table" ) then + parent[key] = mergeTables(parent[key], value) + elseif( type(value) == "table" ) then + parent[key] = CopyTable(value) + elseif( parent[key] == nil ) then + parent[key] = value + end + end + + return parent +end + +local function getName(info) + local key = info[#(info)] + if( ShadowUF.modules[key] and ShadowUF.modules[key].moduleName ) then + return ShadowUF.modules[key].moduleName + end + + return LOCALIZED_CLASS_NAMES_MALE[key] or INDICATOR_NAMES[key] or L.units[key] or TAG_GROUPS[key] or L[key] +end + +local function getUnitOrder(info) + return unitOrder[info[#(info)]] +end + +local function isModifiersSet(info) + if( info[2] ~= "global" ) then return false end + for k in pairs(modifyUnits) do return false end + return true +end + +-- These are for setting simple options like bars.texture = "Default" or locked = true +local function set(info, value) + local cat, key = string.split(".", info.arg) + if( key == "$key" ) then key = info[#(info)] end + + if( not key ) then + ShadowUF.db.profile[cat] = value + else + ShadowUF.db.profile[cat][key] = value + end + + if( cat and fullReload[cat] ) then + ShadowUF.Layout:CheckMedia() + ShadowUF.Layout:Reload() + end +end + +local function get(info) + local cat, key = string.split(".", info.arg) + if( key == "$key" ) then key = info[#(info)] end + if( not key ) then + return ShadowUF.db.profile[cat] + else + return ShadowUF.db.profile[cat][key] + end +end + +local function setColor(info, r, g, b, a) + 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) or {} + return color.r, color.g, color.b, color.a +end + +-- These are for setting complex options like units.player.auras.buffs.enabled = true or units.player.portrait.enabled = true +local function setVariable(unit, moduleKey, moduleSubKey, key, value) + local configTable = unit == "global" and globalConfig or ShadowUF.db.profile.units[unit] + + -- For setting options like units.player.auras.buffs.enabled = true + if( moduleKey and moduleSubKey and configTable[moduleKey][moduleSubKey] ) then + configTable[moduleKey][moduleSubKey][key] = value + ShadowUF.Layout:Reload(unit) + -- For setting options like units.player.portrait.enabled = true + elseif( moduleKey and not moduleSubKey and configTable[moduleKey] ) then + configTable[moduleKey][key] = value + ShadowUF.Layout:Reload(unit) + -- For setting options like units.player.height = 50 + elseif( not moduleKey and not moduleSubKey ) then + configTable[key] = value + ShadowUF.Layout:Reload(unit) + end +end + +local function specialRestricted(unit, moduleKey, moduleSubKey, key) + 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 setDirectUnit(unit, moduleKey, moduleSubKey, key, value) + if( unit == "global" ) then + for globalUnit in pairs(modifyUnits) do + if( not specialRestricted(globalUnit, moduleKey, moduleSubKey, key) ) then + setVariable(globalUnit, moduleKey, moduleSubKey, key, value) + end + end + + setVariable("global", moduleKey, moduleSubKey, key, value) + else + setVariable(unit, moduleKey, moduleSubKey, key, 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 + return configTbl[moduleKey][moduleSubKey] and configTbl[moduleKey][moduleSubKey][key] + elseif( moduleKey and not moduleSubKey ) then + return configTbl[moduleKey] and configTbl[moduleKey][key] + end + + return configTbl[key] +end + +local function getUnit(info) + 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 + + return getVariable(info[2], moduleKey, moduleSubKey, key) +end + +-- Tag functions +local function getTagName(info) + local tag = info[#(info)] + if( ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].name ) then + return ShadowUF.db.profile.tags[tag].name + end + + return ShadowUF.Tags.defaultNames[tag] or tag +end + +local function getTagHelp(info) + local tag = info[#(info)] + return ShadowUF.Tags.defaultHelp[tag] or ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].help +end + +-- Module functions +local function hideRestrictedOption(info) + local unit = type(info.arg) == "number" and info[#(info) - info.arg] or info[2] + 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 ) 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 == "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 + if( ( unit == "global" and not globalConfig.indicators[key] ) or ( unit ~= "global" and not ShadowUF.db.profile.units[unit].indicators[key] ) ) then + return true + end + -- Fall back, no variable table so it shouldn't be shown + elseif( ( unit == "global" and not globalConfig[key] ) or ( unit ~= "global" and not ShadowUF.db.profile.units[unit][key] ) ) then + return true + end + + return false +end + +local function getModuleOrder(info) + local key = info[#(info)] + return key == "healthBar" and 1 or key == "powerBar" and 2 or key == "castBar" and 3 or 4 +end + +-- Expose these for modules +Config.getAnchorParents = getAnchorParents +Config.hideAdvancedOption = hideAdvancedOption +Config.isUnitDisabled = isUnitDisabled +Config.selectDialogGroup = selectDialogGroup +Config.selectTabGroup = selectTabGroup +Config.getName = getName +Config.getUnitOrder = getUnitOrder +Config.isModifiersSet = isModifiersSet +Config.set = set +Config.get = get +Config.setUnit = setUnit +Config.setVariable = setVariable +Config.getUnit = getUnit +Config.getVariable = getVariable +Config.hideRestrictedOption = hideRestrictedOption +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") + + local MediaList = {} + local function getMediaData(info) + local mediaType = info[#(info)] + + MediaList[mediaType] = MediaList[mediaType] or {} + + for k in pairs(MediaList[mediaType]) do MediaList[mediaType][k] = nil end + for _, name in pairs(SML:List(mediaType)) do + MediaList[mediaType][name] = name + end + + return MediaList[mediaType] + end + + + local barModules = {} + for key, module in pairs(ShadowUF.modules) do + if( module.moduleHasBar ) then + barModules["$" .. key] = module.moduleName + end + end + + local addTextParent = { + order = 4, + type = "group", + inline = true, + name = function(info) return barModules[info[#(info)]] or string.sub(info[#(info)], 2) end, + hidden = function(info) + for _, text in pairs(ShadowUF.db.profile.units.player.text) do + if( text.anchorTo == info[#(info)] ) then + return false + end + end + + return true + end, + args = {}, + } + + local addTextLabel = { + order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end, + type = "description", + width = "", + fontSize = "medium", + hidden = function(info) + local id = tonumber(string.match(info[#(info)], "(%d+)")) + if( not getVariable("player", "text", nil, id) ) then return true end + return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1] + end, + name = function(info) + return getVariable("player", "text", tonumber(string.match(info[#(info)], "(%d+)")), "name") + end, + } + + local addTextSep = { + order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.75 end, + type = "description", + width = "full", + hidden = function(info) + local id = tonumber(string.match(info[#(info)], "(%d+)")) + if( not getVariable("player", "text", nil, id) ) then return true end + return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1] + end, + name = "", + } + + local addText = { + order = function(info) return info[#(info)] + 0.5 end, + type = "execute", + width = "half", + name = L["Delete"], + hidden = function(info) + local id = tonumber(info[#(info)]) + if( not getVariable("player", "text", nil, id) ) then return true end + return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1] + 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) + local id = tonumber(info[#(info)]) + for _, unit in pairs(ShadowUF.unitList) do + table.remove(ShadowUF.db.profile.units[unit].text, id) + end + + addTextParent.args[info[#(info)]] = nil + ShadowUF.Layout:Reload() + end, + } + + local function validateSpell(info, spell) + if( spell and spell ~= "" and not GetSpellName(spell) ) then + return string.format(L["Invalid spell \"%s\" entered."], spell or "") + end + + 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) + return ShadowUF.db.profile.range[info[#(info)] .. playerClass] + 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 + + local icon = name and GetSpellTexture(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", + order = 7, + name = L["Layout manager"], + childGroups = "tab", + hidden = hideAdvancedOption, + args = { + import = { + order = 1, + type = "group", + name = L["Import"], + hidden = false, + args = { + help = { + order = 1, + type = "group", + inline = true, + name = function(info) return layoutData.error and L["Error"] or L["Help"] end, + args = { + help = { + order = 1, + type = "description", + name = function(info) + if( ShadowUF.db:GetCurrentProfile() == "Import Backup" ) then + return L["Your active layout is the profile used for import backup, this cannot be overwritten by an import. Change your profiles to something else and try again."] + end + + return layoutData.error or L["You can import another Shadowed Unit Frame users configuration by entering the export code they gave you below. This will backup your old layout to \"Import Backup\".|n|nIt will take 30-60 seconds for it to load your layout when you paste it in, please by patient."] + end + }, + }, + }, + positions = { + order = 2, + type = "toggle", + name = L["Import unit frame positions"], + set = function(info, value) layoutData[info[#(info)]] = value end, + get = function(info) return layoutData[info[#(info)]] end, + width = "double", + }, + visibility = { + order = 3, + type = "toggle", + name = L["Import visibility settings"], + set = function(info, value) layoutData[info[#(info)]] = value end, + get = function(info) return layoutData[info[#(info)]] end, + width = "double", + }, + import = { + order = 5, + type = "input", + name = L["Code"], + multiline = true, + width = "full", + get = false, + disabled = function() return ShadowUF.db:GetCurrentProfile() == "Import Backup" end, + set = function(info, import) + local layout, err = loadstring(string.format([[return %s]], import)) + if( err ) then + layoutData.error = string.format(L["Failed to import layout, error:|n|n%s"], err) + return + end + + layout = layout() + + -- Strip position settings + if( not layoutData.positions ) then + layout.positions = nil + end + + -- Strip visibility settings + if( not layoutData.visibility ) then + layout.visibility = nil + end + + -- Strip any units we don't have included by default + for unit in pairs(layout.units) do + if( not ShadowUF.defaults.profile.units[unit] ) then + layout.units[unit] = nil + end + end + if( not layoutData.modules ) then + local validModules = {["healthBar"] = true, ["powerBar"] = true, ["portrait"] = true, ["range"] = true, ["text"] = true, ["indicators"] = true, ["auras"] = true, ["incAbsorb"] = true, ["healAbsorb"] = true, ["incHeal"] = true, ["castBar"] = true, ["combatText"] = true, ["highlight"] = true, ["runeBar"] = true, ["totemBar"] = true, ["xpBar"] = true, ["fader"] = true, ["comboPoints"] = true, ["eclipseBar"] = true, ["soulShards"] = true, ["holyPower"] = true, ["altPowerBar"] = true, ["demonicFuryBar"] = true, ["burningEmbersBar"] = true, ["chi"] = true, ["shadowOrbs"] = true, ["auraPoints"] = true, ["staggerBar"] = 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) + + -- Now backup the profile + local currentLayout = ShadowUF.db:GetCurrentProfile() + ShadowUF.layoutImporting = true + ShadowUF.db:SetProfile("Import Backup") + ShadowUF.db:CopyProfile(currentLayout) + ShadowUF.db:SetProfile(currentLayout) + ShadowUF.db:ResetProfile() + ShadowUF.layoutImporting = nil + + -- Overwrite everything we did import + ShadowUF:LoadDefaultLayout() + for key, data in pairs(layout) do + if( type(data) == "table" ) then + ShadowUF.db.profile[key] = CopyTable(data) + else + ShadowUF.db.profile[key] = data + end + end + + ShadowUF:ProfilesChanged() + end, + }, + }, + }, + export = { + order = 2, + type = "group", + name = L["Export"], + hidden = false, + args = { + help = { + order = 1, + type = "group", + inline = true, + name = L["Help"], + args = { + help = { + order = 1, + type = "description", + name = L["After you hit export, you can give the below code to other Shadowed Unit Frames users and they will get your exact layout."], + }, + }, + }, + doExport = { + order = 2, + type = "execute", + name = L["Export"], + func = function(info) + layoutData.export = writeTable(ShadowUF.db.profile) + end, + }, + export = { + order = 3, + type = "input", + name = L["Code"], + multiline = true, + width = "full", + set = false, + get = function(info) return layoutData[info[#(info)]] end, + }, + }, + }, + }, + } + + options.args.general = { + type = "group", + childGroups = "tab", + name = L["General"], + args = { + general = { + type = "group", + order = 1, + name = L["General"], + set = set, + get = get, + args = { + general = { + order = 1, + type = "group", + inline = true, + name = L["General"], + args = { + locked = { + order = 1, + type = "toggle", + name = L["Lock frames"], + desc = L["Enables configuration mode, letting you move and giving you example frames to setup."], + set = function(info, value) + set(info, value) + ShadowUF.modules.movers:Update() + end, + arg = "locked", + }, + advanced = { + 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 Cooldown Count"], + desc = L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."], + arg = "omnicc", + 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, + type = "toggle", + name = L["Hide tooltips in combat"], + desc = L["Prevents unit tooltips from showing while in combat."], + arg = "tooltipCombat", + width = "double", + }, + bossmodCastNames = { + order = 3.1, + type = "toggle", + name = L["Use Boss Mod Cast Name overrides"], + desc = L["Use spell name overrides provided by boss mods (BigWigs) on the cast bars."], + arg = "bossmodSpellRename", + width = "double", + }, + sep2 = { + order = 3.5, + type = "description", + name = "", + width = "full", + }, + auraBorder = { + order = 5, + type = "select", + name = L["Aura border style"], + desc = L["Style of borders to show for all auras."], + values = {["dark"] = L["Dark"], ["light"] = L["Light"], ["blizzard"] = L["Blizzard"], [""] = L["None"]}, + arg = "auras.borderType", + }, + statusbar = { + order = 6, + type = "select", + name = L["Bar texture"], + dialogControl = "LSM30_Statusbar", + values = getMediaData, + arg = "bars.texture", + }, + spacing = { + order = 7, + type = "range", + name = L["Bar spacing"], + desc = L["How much spacing should be provided between all of the bars inside a unit frame, negative values move them farther apart, positive values bring them closer together. 0 for no spacing."], + min = -10, max = 10, step = 0.05, softMin = -5, softMax = 5, + arg = "bars.spacing", + hidden = hideAdvancedOption, + }, + }, + }, + backdrop = { + order = 2, + type = "group", + inline = true, + name = L["Background/border"], + args = { + backgroundColor = { + order = 1, + type = "color", + name = L["Background color"], + hasAlpha = true, + set = setColor, + get = getColor, + arg = "backdrop.backgroundColor", + }, + borderColor = { + order = 2, + type = "color", + name = L["Border color"], + hasAlpha = true, + set = setColor, + get = getColor, + arg = "backdrop.borderColor", + }, + sep = { + order = 3, + type = "description", + name = "", + width = "full", + }, + background = { + order = 4, + type = "select", + name = L["Background"], + dialogControl = "LSM30_Background", + values = getMediaData, + arg = "backdrop.backgroundTexture", + }, + border = { + order = 5, + type = "select", + name = L["Border"], + dialogControl = "LSM30_Border", + values = getMediaData, + arg = "backdrop.borderTexture", + }, + inset = { + order = 5.5, + type = "range", + name = L["Inset"], + desc = L["How far the background should be from the unit frame border."], + min = -10, max = 10, step = 1, + hidden = hideAdvancedOption, + arg = "backdrop.inset", + }, + sep2 = { + order = 6, + type = "description", + name = "", + width = "full", + hidden = hideAdvancedOption, + }, + edgeSize = { + order = 7, + type = "range", + name = L["Edge size"], + desc = L["How large the edges should be."], + hidden = hideAdvancedOption, + min = 0, max = 20, step = 1, + arg = "backdrop.edgeSize", + }, + tileSize = { + order = 8, + type = "range", + name = L["Tile size"], + desc = L["How large the background should tile"], + hidden = hideAdvancedOption, + min = 0, max = 20, step = 1, + arg = "backdrop.tileSize", + }, + clip = { + order = 9, + type = "range", + name = L["Clip"], + desc = L["How close the frame should clip with the border."], + hidden = hideAdvancedOption, + min = 0, max = 20, step = 1, + arg = "backdrop.clip", + }, + }, + }, + font = { + order = 3, + type = "group", + inline = true, + name = L["Font"], + args = { + color = { + order = 1, + type = "color", + name = L["Default color"], + desc = L["Default font color, any color tags inside individual tag texts will override this."], + hasAlpha = true, + set = setColor, + get = getColor, + arg = "font.color", + hidden = hideAdvancedOption, + }, + sep = {order = 1.25, type = "description", name = "", hidden = hideAdvancedOption}, + font = { + order = 1.5, + type = "select", + name = L["Font"], + dialogControl = "LSM30_Font", + values = getMediaData, + arg = "font.name", + }, + size = { + order = 2, + type = "range", + name = L["Size"], + min = 1, max = 50, step = 1, softMin = 1, softMax = 20, + arg = "font.size", + }, + outline = { + order = 3, + type = "select", + name = L["Outline"], + values = {["OUTLINE"] = L["Thin outline"], ["THICKOUTLINE"] = L["Thick outline"], ["MONOCHROMEOUTLINE"] = L["Monochrome Outline"], [""] = L["None"]}, + arg = "font.extra", + hidden = hideAdvancedOption, + }, + }, + }, + bar = { + order = 4, + type = "group", + inline = true, + name = L["Bars"], + hidden = hideAdvancedOption, + args = { + override = { + order = 0, + type = "toggle", + name = L["Override color"], + desc = L["Forces a static color to be used for the background of all bars"], + set = function(info, value) + if( value and not ShadowUF.db.profile.bars.backgroundColor ) then + ShadowUF.db.profile.bars.backgroundColor = {r = 0, g = 0, b = 0} + elseif( not value ) then + ShadowUF.db.profile.bars.backgroundColor = nil + end + + ShadowUF.Layout:Reload() + end, + get = function(info) + return ShadowUF.db.profile.bars.backgroundColor and true or false + end, + }, + color = { + order = 1, + type = "color", + name = L["Background color"], + desc = L["This will override all background colorings for bars including custom set ones."], + set = setColor, + get = function(info) + if( not ShadowUF.db.profile.bars.backgroundColor ) then + return 0, 0, 0 + end + + return getColor(info) + end, + disabled = function(info) return not ShadowUF.db.profile.bars.backgroundColor end, + arg = "bars.backgroundColor", + }, + sep = { order = 2, type = "description", name = "", width = "full"}, + barAlpha = { + order = 3, + type = "range", + name = L["Bar alpha"], + desc = L["Alpha to use for bar."], + arg = "bars.alpha", + min = 0, max = 1, step = 0.05, + isPercent = true + }, + backgroundAlpha = { + order = 4, + type = "range", + name = L["Background alpha"], + desc = L["Alpha to use for bar backgrounds."], + arg = "bars.backgroundAlpha", + min = 0, max = 1, step = 0.05, + isPercent = true + }, + }, + }, + }, + }, + color = { + order = 2, + type = "group", + name = L["Colors"], + args = { + health = { + order = 1, + type = "group", + inline = true, + name = L["Health"], + set = setColor, + get = getColor, + args = { + green = { + order = 1, + type = "color", + name = L["High health"], + desc = L["Health bar color used as the transitional color for 100% -> 50% on players, as well as when your pet is happy."], + arg = "healthColors.green", + }, + yellow = { + order = 2, + type = "color", + name = L["Half health"], + desc = L["Health bar color used as the transitional color for 100% -> 0% on players, as well as when your pet is mildly unhappy."], + arg = "healthColors.yellow", + }, + red = { + order = 3, + type = "color", + name = L["Low health"], + desc = L["Health bar color used as the transitional color for 50% -> 0% on players, as well as when your pet is very unhappy."], + arg = "healthColors.red", + }, + friendly = { + order = 4, + type = "color", + name = L["Friendly"], + desc = L["Health bar color for friendly units."], + arg = "healthColors.friendly", + }, + neutral = { + order = 5, + type = "color", + name = L["Neutral"], + desc = L["Health bar color for neutral units."], + arg = "healthColors.neutral", + }, + hostile = { + order = 6, + type = "color", + name = L["Hostile"], + 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", + name = L["Static"], + desc = L["Color to use for health bars that are set to be colored by a static color."], + arg = "healthColors.static", + }, + inc = { + order = 8, + type = "color", + name = L["Incoming heal"], + desc = L["Bar color to use to show how much healing someone is about to receive."], + arg = "healthColors.inc", + }, + 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_YELLOW = { + 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", + inline = true, + name = L["Power"], + set = setColor, + get = getColor, + args = { + MANA = { + order = 0, + type = "color", + name = L["Mana"], + width = "half", + arg = "powerColors.MANA", + }, + RAGE = { + order = 1, + type = "color", + name = L["Rage"], + width = "half", + arg = "powerColors.RAGE", + }, + FOCUS = { + order = 2, + type = "color", + name = L["Focus"], + arg = "powerColors.FOCUS", + width = "half", + }, + ENERGY = { + order = 3, + type = "color", + name = L["Energy"], + arg = "powerColors.ENERGY", + width = "half", + }, + RUNIC_POWER = { + order = 6, + type = "color", + name = L["Runic Power"], + arg = "powerColors.RUNIC_POWER", + }, + ECLIPSE_MOON = { + order = 7, + type = "color", + name = L["Eclipse (Moon)"], + desc = L["Bar coloring for the moon portion of the eclipse bar."], + hidden = function(info) return select(2, UnitClass("player")) ~= "DRUID" end, + arg = "powerColors.ECLIPSE_MOON", + }, + ECLIPSE_SUN = { + order = 8, + type = "color", + name = L["Eclipse (Sun)"], + desc = L["Bar coloring for the moon portion of the eclipse bar."], + hidden = function(info) return select(2, UnitClass("player")) ~= "DRUID" end, + arg = "powerColors.ECLIPSE_SUN", + }, + 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"], + arg = "powerColors.AMMOSLOT", + hidden = hideAdvancedOption, + }, + FUEL = { + order = 10, + type = "color", + name = L["Fuel"], + 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 + }, + SHADOWORBS = { + order = 12, + type = "color", + name = L["Shadow Orbs"], + arg = "powerColors.SHADOWORBS", + hidden = function(info) return select(2, UnitClass("player")) ~= "PRIEST" end, + }, + MAELSTROM = { + order = 12.5, + type = "color", + name = L["Maelstrom"], + arg = "powerColors.MAELSTROM", + hidden = function(info) return select(2, UnitClass("player")) ~= "SHAMAN" end, + }, + HOLYPOWER = { + order = 12.5, + type = "color", + name = L["Holy Power"], + arg = "powerColors.HOLYPOWER", + hidden = function(info) return select(2, UnitClass("player")) ~= "PALADIN" end, + }, + BANKEDHOLYPOWER = { + order = 13, + type = "color", + name = L["Banked Holy Power"], + hasAlpha = true, + arg = "powerColors.BANKEDHOLYPOWER", + 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, + }, + DEMONICFURY = { + order = 15, + type = "color", + name = L["Demonic Fury"], + arg = "powerColors.DEMONICFURY", + hidden = function(info) return select(2, UnitClass("player")) ~= "WARLOCK" end, + }, + BURNINGEMBERS = { + order = 16, + type = "color", + name = L["Burning Embers"], + arg = "powerColors.BURNINGEMBERS", + hidden = function(info) return select(2, UnitClass("player")) ~= "WARLOCK" end, + }, + FULLBURNINGEMBER = { + order = 16, + type = "color", + name = L["Full Burning Ember"], + + arg = "powerColors.FULLBURNINGEMBER", + 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, + }, + 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 = { + order = 3, + type = "group", + inline = true, + name = L["Cast"], + set = setColor, + get = getColor, + args = { + cast = { + order = 0, + type = "color", + name = L["Casting"], + desc = L["Color used when an unit is casting a spell."], + arg = "castColors.cast", + }, + channel = { + order = 1, + type = "color", + name = L["Channelling"], + desc = L["Color used when a cast is a channel."], + arg = "castColors.channel", + }, + sep = { + order = 2, + type = "description", + name = "", + hidden = hideAdvancedOption, + width = "full", + }, + finished = { + order = 3, + type = "color", + name = L["Finished cast"], + desc = L["Color used when a cast is successfully finished."], + hidden = hideAdvancedOption, + arg = "castColors.finished", + }, + interrupted = { + order = 4, + type = "color", + name = L["Cast interrupted"], + desc = L["Color used when a cast is interrupted either by the caster themselves or by another unit."], + hidden = hideAdvancedOption, + arg = "castColors.interrupted", + }, + uninterruptible = { + order = 5, + type = "color", + name = L["Cast uninterruptible"], + desc = L["Color used when a cast cannot be interrupted, this is only used for PvE mobs."], + arg = "castColors.uninterruptible", + }, + }, + }, + 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", + inline = true, + name = L["Classes"], + set = setColor, + get = getColor, + args = {} + }, + }, + }, + range = { + order = 5, + type = "group", + name = L["Range Checker"], + args = { + help = { + order = 0, + type = "group", + inline = true, + name = L["Help"], + args = { + help = { + order = 0, + type = "description", + 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."], + }, + }, + }, + friendly = { + order = 1, + inline = true, + type = "group", + name = L["On Friendly Units"], + args = { + friendly = { + 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 = "" + }, + 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 + + -- Add the new entry + for _, unit in pairs(ShadowUF.unitList) do + table.insert(ShadowUF.db.profile.units[unit].text, {enabled = true, name = textData.name or "??", text = "", anchorTo = textData.parent, x = 0, y = 0, anchorPoint = "C", size = 0, width = 0.50}) + end + + -- Add it to the GUI + local id = tostring(#(ShadowUF.db.profile.units.player.text)) + addTextParent.args[id .. ":label"] = addTextLabel + addTextParent.args[id] = addText + addTextParent.args[id .. ":sep"] = addTextSep + options.args.general.args.text.args[textData.parent] = options.args.general.args.text.args[textData.parent] or addTextParent + + local parent = string.sub(textData.parent, 2) + Config.tagWizard[parent] = Config.tagWizard[parent] or Config.parentTable + Config.tagWizard[parent].args[id] = Config.tagTextTable + Config.tagWizard[parent].args[id .. ":adv"] = Config.advanceTextTable + + quickIDMap[id .. ":adv"] = #(ShadowUF.db.profile.units.player.text) + + -- Reset + textData.name = nil + textData.parent = nil + + end, + }, + }, + }, + }, + }, + layout = layoutManager, + }, + } + + -- Load text + for id, text in pairs(ShadowUF.db.profile.units.player.text) do + 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 + + + Config.classTable = { + order = 0, + type = "color", + name = getName, + hasAlpha = true, + width = "half", + arg = "classColors.$key", + } + + for classToken in pairs(RAID_CLASS_COLORS) do + options.args.general.args.color.args.classColors.args[classToken] = Config.classTable + end + + options.args.general.args.color.args.classColors.args.PET = Config.classTable + options.args.general.args.color.args.classColors.args.VEHICLE = Config.classTable +end + +--------------------- +-- HIDE BLIZZARD FRAMES CONFIGURATION +--------------------- +local function loadHideOptions() + Config.hideTable = { + order = function(info) return info[#(info)] == "buffs" and 1 or 2 end, + type = "toggle", + name = function(info) + local key = info[#(info)] + 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) + if( value ) then ShadowUF:HideBlizzardFrames() end + end, + hidden = false, + get = get, + arg = "hidden.$key", + } + + options.args.hideBlizzard = { + type = "group", + name = L["Hide Blizzard"], + desc = getPageDescription, + args = { + help = { + order = 0, + type = "group", + name = L["Help"], + inline = true, + args = { + description = { + type = "description", + name = L["You will need to do a /console reloadui before a hidden frame becomes visible again.|nPlayer and other unit frames are automatically hidden depending on if you enable the unit in Shadowed Unit Frames."], + width = "full", + }, + }, + }, + hide = { + order = 1, + type = "group", + name = L["Frames"], + inline = true, + args = { + buffs = Config.hideTable, + cast = 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, + }, + }, + } + } +end + +--------------------- +-- UNIT CONFIGURATION +--------------------- +local function loadUnitOptions() + -- This makes sure we don't end up with any messed up positioning due to two different anchors being used + local function fixPositions(info) + local unit = info[2] + local key = info[#(info)] + + if( key == "point" or key == "relativePoint" ) then + ShadowUF.db.profile.positions[unit].anchorPoint = "" + ShadowUF.db.profile.positions[unit].movedAnchor = nil + elseif( key == "anchorPoint" ) then + ShadowUF.db.profile.positions[unit].point = "" + ShadowUF.db.profile.positions[unit].relativePoint = "" + end + + -- Reset offset if it was a manually positioned frame, and it got anchored + -- Why 100/-100 you ask? Because anything else requires some sort of logic applied to it + -- and this means the frames won't directly overlap too which is a nice bonus + if( key == "anchorTo" ) then + ShadowUF.db.profile.positions[unit].x = 100 + ShadowUF.db.profile.positions[unit].y = -100 + end + end + + -- Hide raid option in party config + local function hideRaidOrAdvancedOption(info) + if( info[2] == "party" and ShadowUF.db.profile.advanced ) then return false end + + return info[2] ~= "raid" and info[2] ~= "raidpet" and info[2] ~= "maintank" and info[2] ~= "mainassist" + end + + local function hideRaidOption(info) + return info[2] ~= "raid" and info[2] ~= "raidpet" and info[2] ~= "maintank" and info[2] ~= "mainassist" + end + + local function hideSplitOrRaidOption(info) + if( info[2] == "raid" and ShadowUF.db.profile.units.raid.frameSplit ) then + return true + end + + return hideRaidOption(info) + end + + -- Not every option should be changed via global settings + local function hideSpecialOptions(info) + local unit = info[2] + if( unit == "global" or unit == "partypet" ) then + return true + end + + return hideAdvancedOption(info) + end + + local function checkNumber(info, value) + return tonumber(value) + end + + local function setPosition(info, value) + ShadowUF.db.profile.positions[info[2]][info[#(info)]] = value + fixPositions(info) + + if( info[2] == "raid" or info[2] == "raidpet" or info[2] == "maintank" or info[2] == "mainassist" or info[2] == "party" or info[2] == "boss" or info[2] == "arena" ) then + ShadowUF.Units:ReloadHeader(info[2]) + else + ShadowUF.Layout:Reload(info[2]) + end + end + + local function getPosition(info) + return ShadowUF.db.profile.positions[info[2]][info[#(info)]] + end + + local function setNumber(info, value) + local unit = info[2] + local key = info[#(info)] + local id = unit .. key + + -- Apply effective scaling if it's anchored to UIParent + if( ShadowUF.db.profile.positions[unit].anchorTo == "UIParent" ) then + value = value * (ShadowUF.db.profile.units[unit].scale * UIParent:GetScale()) + end + + setPosition(info, tonumber(value)) + end + + local function getString(info) + local unit = info[2] + local key = info[#(info)] + local id = unit .. key + local coord = getPosition(info) + + -- If the frame is created and it's anchored to UIParent, will return the number modified by scale + if( ShadowUF.db.profile.positions[unit].anchorTo == "UIParent" ) then + coord = coord / (ShadowUF.db.profile.units[unit].scale * UIParent:GetScale()) + end + + -- OCD, most definitely. + -- Pain to check coord == math.floor(coord) because floats are handled oddly with frames and return 0.99999999999435 + return string.gsub(string.format("%.2f", coord), "%.00$", "") + end + + + -- TAG WIZARD + local tagWizard = {} + Config.tagWizard = tagWizard + do + -- Load tag list + Config.advanceTextTable = { + order = 1, + name = function(info) return getVariable(info[2], "text", quickIDMap[info[#(info)]], "name") end, + type = "group", + inline = true, + hidden = function(info) + if( not getVariable(info[2], "text", nil, quickIDMap[info[#(info)]]) ) then return true end + return string.sub(getVariable(info[2], "text", quickIDMap[info[#(info)]], "anchorTo"), 2) ~= info[#(info) - 1] + end, + set = function(info, value) + info.arg = string.format("text.%s.%s", quickIDMap[info[#(info) - 1]], info[#(info)]) + setUnit(info, value) + end, + get = function(info) + info.arg = string.format("text.%s.%s", quickIDMap[info[#(info) - 1]], info[#(info)]) + return getUnit(info) + end, + args = { + anchorPoint = { + order = 1, + type = "select", + name = L["Anchor point"], + values = {["LC"] = L["Left Center"], ["RT"] = L["Right Top"], ["RB"] = L["Right Bottom"], ["LT"] = L["Left Top"], ["LB"] = L["Left Bottom"], ["RC"] = L["Right Center"],["TRI"] = L["Inside Top Right"], ["TLI"] = L["Inside Top Left"], ["CLI"] = L["Inside Center Left"], ["C"] = L["Inside Center"], ["CRI"] = L["Inside Center Right"], ["TR"] = L["Top Right"], ["TL"] = L["Top Left"], ["BR"] = L["Bottom Right"], ["BL"] = L["Bottom Left"]}, + hidden = hideAdvancedOption, + }, + sep = { + order = 2, + type = "description", + name = "", + width = "full", + hidden = hideAdvancedOption, + }, + width = { + order = 3, + name = L["Width weight"], + 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 = function(info) + return hideAdvancedOption(info) or getVariable(info[2], "text", quickIDMap[info[#(info) - 1]], "block") + end, + }, + size = { + order = 4, + name = L["Size"], + desc = L["Let's you modify the base font size to either make it larger or smaller."], + type = "range", + 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", + name = L["X Offset"], + min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100, + hidden = false, + }, + y = { + order = 6, + type = "range", + name = L["Y Offset"], + min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100, + hidden = false, + }, + }, + } + + Config.parentTable = { + order = 0, + type = "group", + name = function(info) return getName(info) or string.sub(info[#(info)], 1) end, + hidden = function(info) return not getVariable(info[2], info[#(info)], nil, "enabled") end, + args = {} + } + + 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 modUnit in pairs(modifyUnits) do + if( ShadowUF.Tags.unitRestrictions[tag] == modUnit ) then + return false + 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 + end + + 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 + end + else + -- If the only units that are in the global configuration have the tag filtered, then don't bother showing it + for modUnit in pairs(modifyUnits) do + if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(modUnit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then + return false + 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 + + local savedTagTexts = {} + local function selectTag(info, value) + local unit = info[2] + local id = tonumber(info[#(info) - 2]) + local tag = info[#(info)] + local text = getVariable(unit, "text", id, "text") + local savedText + + if( value ) then + if( unit == "global" ) then + table.wipe(savedTagTexts) + + -- Set special tag texts based on the unit, so targettarget won't get a tag that will cause errors + local tagGroup = ShadowUF.Tags.defaultCategories[tag] + for modUnit in pairs(modifyUnits) do + savedTagTexts[modUnit] = getVariable(modUnit, "text", id, "text") + if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(modUnit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then + if( not ShadowUF.Tags.unitRestrictions[tag] or ShadowUF.Tags.unitRestrictions[tag] == modUnit ) then + if( text == "" ) then + savedTagTexts[modUnit] = string.format("[%s]", tag) + else + savedTagTexts[modUnit] = string.format("%s[( )%s]", savedTagTexts[modUnit], tag) + end + + savedTagTexts.global = savedTagTexts[modUnit] + end + end + end + else + if( text == "" ) then + text = string.format("[%s]", tag) + else + text = string.format("%s[( )%s]", text, tag) + end + end + + -- Removing a tag from a single unit, super easy :< + else + -- Ugly, but it works + 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 + end + + if( unit == "global" ) then + for modUnit in pairs(modifyUnits) do + if( savedTagTexts[modUnit] ) then + setVariable(modUnit, "text", id, "text", savedTagTexts[modUnit]) + end + end + + setVariable("global", "text", id, "text", savedTagTexts.global) + else + setVariable(unit, "text", id, "text", text) + end + end + + local function getTag(info) + local text = getVariable(info[2], "text", tonumber(info[#(info) - 2]), "text") + local tag = info[#(info)] + + -- FUN WITH PATTERN MATCHING + if( string.match(text, "%[" .. tag .. "%]") or string.match(text, "%)" .. tag .. "%]") or string.match(text, "%[" .. tag .. "%(") or string.match(text, "%)" .. tag .. "%(") ) then + return true + end + + return false + end + + Config.tagTextTable = { + type = "group", + name = function(info) return getVariable(info[2], "text", nil, tonumber(info[#(info)])) and getVariable(info[2], "text", tonumber(info[#(info)]), "name") or "" end, + hidden = function(info) + if( not getVariable(info[2], "text", nil, tonumber(info[#(info)])) ) then return true end + return string.sub(getVariable(info[2], "text", tonumber(info[#(info)]), "anchorTo"), 2) ~= info[#(info) - 1] end, + set = false, + get = false, + args = { + text = { + order = 0, + type = "input", + name = L["Text"], + width = "full", + hidden = false, + set = function(info, value) setUnit(info, string.gsub(value, "||", "|")) end, + get = function(info) return string.gsub(getUnit(info), "|", "||") end, + arg = "text.$parent.text", + }, + }, + } + + + local function getCategoryOrder(info) + return info[#(info)] == "health" and 1 or info[#(info)] == "power" and 2 or info[#(info)] == "misc" and 3 or 4 + end + + for _, cat in pairs(ShadowUF.Tags.defaultCategories) do + Config.tagTextTable.args[cat] = Config.tagTextTable.args[cat] or { + order = getCategoryOrder, + type = "group", + inline = true, + name = getName, + hidden = hideBlacklistedGroup, + set = selectTag, + get = getTag, + args = {}, + } + end + + Config.tagTable = { + order = 0, + type = "toggle", + hidden = hideBlacklistedTag, + name = getTagName, + desc = getTagHelp, + } + + local tagList = {} + for tag in pairs(ShadowUF.Tags.defaultTags) do + local category = ShadowUF.Tags.defaultCategories[tag] or "misc" + Config.tagTextTable.args[category].args[tag] = Config.tagTable + end + + for tag, data in pairs(ShadowUF.db.profile.tags) do + local category = data.category or "misc" + Config.tagTextTable.args[category].args[tag] = Config.tagTable + end + + local parentList = {} + for id, text in pairs(ShadowUF.db.profile.units.player.text) do + parentList[text.anchorTo] = parentList[text.anchorTo] or {} + parentList[text.anchorTo][id] = text + end + + local nagityNagNagTable = { + order = 0, + type = "group", + name = L["Help"], + inline = true, + hidden = false, + args = { + help = { + order = 0, + type = "description", + name = L["Selecting a tag text from the left panel to change tags. Truncating width, sizing, and offsets can be done in the current panel."], + }, + }, + } + + for parent, list in pairs(parentList) do + parent = string.sub(parent, 2) + tagWizard[parent] = Config.parentTable + Config.parentTable.args.help = nagityNagNagTable + + for id in pairs(list) do + tagWizard[parent].args[tostring(id)] = Config.tagTextTable + tagWizard[parent].args[tostring(id) .. ":adv"] = Config.advanceTextTable + + quickIDMap[tostring(id) .. ":adv"] = id + end + end + end + + local function disableAnchoredTo(info) + local auras = getVariable(info[2], "auras", nil, info[#(info) - 2]) + + return auras.anchorOn or not auras.enabled + end + + local function disableSameAnchor(info) + local buffs = getVariable(info[2], "auras", nil, "buffs") + 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) - 2], "enabled") ) then + return true + end + + 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) - 2] or buffs.anchorOn or debuffs.anchorOn ) then + return false + end + + return buffs.anchorPoint == debuffs.anchorPoint + end + + local defaultAuraList = {["BL"] = L["Bottom"], ["TL"] = L["Top"], ["LT"] = L["Left"], ["RT"] = L["Right"]} + local advancedAuraList = {["BL"] = L["Bottom Left"], ["BR"] = L["Bottom Right"], ["TL"] = L["Top Left"], ["TR"] = L["Top Right"], ["RT"] = L["Right Top"], ["RB"] = L["Right Bottom"], ["LT"] = L["Left Top"], ["LB"] = L["Left Bottom"]} + local function getAuraAnchors() + 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", + 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 = false, + args = { + 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", + } + } + }, + filters = { + type = "group", + name = L["Filters"], + order = 1, + set = function(info, value) + getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]] = value + reloadUnitAuras() + end, + get = function(info) + return getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]] + end, + 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" + }, + } + }, + 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 + } + } + }, + positioning = { + type = "group", + name = L["Positioning"], + order = 3, + args = { + anchorOn = { + order = 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, + width = "full", + arg = "auras.$parentparent.anchorOn", + }, + anchorPoint = { + order = 1.5, + 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", + }, + size = { + order = 2, + type = "range", + name = L["Icon Size"], + min = 1, max = 30, step = 1, + arg = "auras.$parentparent.size", + }, + sep1 = {order = 3, type = "description", name = "", width = "full"}, + perRow = { + order = 13, + 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 = 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) - 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 = 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) - 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 = 18, + type = "range", + name = L["X Offset"], + min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100, + disabled = disableSameAnchor, + hidden = hideAdvancedOption, + arg = "auras.$parentparent.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.$parentparent.y", + }, + + } + } + } + } + + local function hideBarOption(info) + local module = info[#(info) - 1] + if( ShadowUF.modules[module].moduleHasBar or getVariable(info[2], module, nil, "isBar") ) then + return false + end + + return true + end + + local function disableIfCastName(info) + return not getVariable(info[2], "castBar", "name", "enabled") + end + + + Config.barTable = { + order = getModuleOrder, + name = getName, + type = "group", + inline = false, + hidden = function(info) return hideRestrictedOption(info) or not getVariable(info[2], info[#(info)], nil, "enabled") end, + args = { + enableBar = { + order = 1, + type = "toggle", + name = L["Show as bar"], + 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", + }, + 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", + name = L["Show background"], + desc = L["Show a background behind the bars with the same texture/color but faded out."], + hidden = hideBarOption, + arg = "$parent.background", + }, + sep2 = {order = 1.55, type = "description", name = "", hidden = function(info) return not (not ShadowUF.modules[info[#(info) - 1]] or info[#(info) - 1] == "eclipseBar" 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 not ShadowUF.modules[info[#(info) - 1]] or info[#(info) - 1] == "eclipseBar" 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 info[#(info) - 1] == "eclipseBar" or not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,}, + order = { + order = 4, + type = "range", + name = L["Order"], + min = 0, max = 100, step = 5, + hidden = hideBarOption, + arg = "$parent.order", + }, + height = { + order = 5, + 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 = "$parent.height", + } + }, + } + + Config.indicatorTable = { + order = 0, + name = function(info) + if( info[#(info)] == "status" and info[2] == "player" ) then + return L["Combat/resting status"] + end + + return getName(info) + end, + desc = function(info) return INDICATOR_DESC[info[#(info)]] end, + type = "group", + hidden = hideRestrictedOption, + args = { + enabled = { + order = 0, + type = "toggle", + name = L["Enable indicator"], + hidden = false, + arg = "indicators.$parent.enabled", + }, + sep1 = { + order = 1, + type = "description", + name = "", + width = "full", + hidden = function() return not ShadowUF.db.profile.advanced end, + }, + anchorPoint = { + order = 2, + type = "select", + name = L["Anchor point"], + values = positionList, + hidden = false, + arg = "indicators.$parent.anchorPoint", + }, + size = { + order = 4, + type = "range", + name = L["Size"], + min = 1, max = 40, step = 1, + hidden = hideAdvancedOption, + arg = "indicators.$parent.size", + }, + x = { + order = 5, + type = "range", + name = L["X Offset"], + min = -100, max = 100, step = 1, softMin = -50, softMax = 50, + hidden = false, + arg = "indicators.$parent.x", + }, + y = { + order = 6, + type = "range", + name = L["Y Offset"], + min = -100, max = 100, step = 1, softMin = -50, softMax = 50, + hidden = false, + arg = "indicators.$parent.y", + }, + }, + } + + Config.unitTable = { + type = "group", + childGroups = "tab", + order = getUnitOrder, + name = getName, + hidden = isUnitDisabled, + args = { + general = { + order = 1, + name = L["General"], + type = "group", + hidden = isModifiersSet, + set = setUnit, + get = getUnit, + args = { + vehicle = { + order = 1, + type = "group", + inline = true, + name = L["Vehicles"], + hidden = function(info) return info[2] ~= "player" and info[2] ~= "party" or not ShadowUF.db.profile.advanced end, + args = { + disable = { + order = 0, + type = "toggle", + name = L["Disable vehicle swap"], + desc = L["Disables the unit frame from turning into a vehicle when the player enters one."], + set = function(info, value) + setUnit(info, value) + local unit = info[2] + if( unit == "player" ) then + if( ShadowUF.Units.unitFrames.pet ) then + ShadowUF.Units.unitFrames.pet:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units[unit].disableVehicle) + end + + if( ShadowUF.Units.unitFrames.player ) then + ShadowUF.Units:CheckVehicleStatus(ShadowUF.Units.unitFrames.player) + end + elseif( unit == "party" ) then + for frame in pairs(ShadowUF.Units.unitFrames) do + if( frame.unitType == "partypet" ) then + frame:SetAttribute("disableVehicleSwap", ShadowUF.db.profile.units[unit].disableVehicle) + elseif( frame.unitType == "party" ) then + ShadowUF.Units:CheckVehicleStatus(frame) + end + end + end + end, + arg = "disableVehicle", + }, + }, + }, + portrait = { + order = 2, + type = "group", + inline = true, + hidden = false, + name = L["Portrait"], + args = { + portrait = { + order = 0, + type = "toggle", + name = string.format(L["Enable %s"], L["Portrait"]), + arg = "portrait.enabled", + }, + portraitType = { + order = 1, + type = "select", + name = L["Portrait type"], + values = {["class"] = L["Class icon"], ["2D"] = L["2D"], ["3D"] = L["3D"]}, + arg = "portrait.type", + }, + alignment = { + order = 2, + type = "select", + name = L["Position"], + values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, + arg = "portrait.alignment", + }, + }, + }, + fader = { + order = 3, + type = "group", + inline = true, + name = L["Combat fader"], + hidden = hideRestrictedOption, + args = { + fader = { + order = 0, + type = "toggle", + 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" + }, + combatAlpha = { + order = 1, + type = "range", + name = L["Combat alpha"], + desc = L["Frame alpha while this unit is in combat."], + min = 0, max = 1.0, step = 0.1, + arg = "fader.combatAlpha", + hidden = false, + isPercent = true, + }, + inactiveAlpha = { + order = 2, + type = "range", + name = L["Inactive alpha"], + desc = L["Frame alpha when you are out of combat while having no target and 100% mana or energy."], + min = 0, max = 1.0, step = 0.1, + arg = "fader.inactiveAlpha", + hidden = false, + isPercent = true, + }, + } + }, + range = { + order = 3, + type = "group", + inline = true, + name = L["Range indicator"], + hidden = hideRestrictedOption, + args = { + fader = { + order = 0, + type = "toggle", + name = string.format(L["Enable %s"], L["Range indicator"]), + desc = L["Fades out the unit frames of people who are not within range of you."], + arg = "range.enabled", + hidden = false, + }, + inAlpha = { + order = 1, + type = "range", + name = L["In range alpha"], + desc = L["Frame alpha while this unit is in combat."], + min = 0, max = 1.0, step = 0.05, + arg = "range.inAlpha", + hidden = false, + isPercent = true, + }, + oorAlpha = { + order = 2, + type = "range", + name = L["Out of range alpha"], + min = 0, max = 1.0, step = 0.05, + arg = "range.oorAlpha", + hidden = false, + isPercent = true, + }, + } + }, + highlight = { + order = 3.5, + type = "group", + inline = true, + name = L["Border highlighting"], + hidden = hideRestrictedOption, + args = { + mouseover = { + order = 3, + type = "toggle", + name = L["On mouseover"], + desc = L["Highlight units when you mouse over them."], + arg = "highlight.mouseover", + hidden = false, + }, + attention = { + order = 4, + type = "toggle", + name = L["For target/focus"], + desc = L["Highlight units that you are targeting or have focused."], + arg = "highlight.attention", + hidden = function(info) return info[2] == "target" or info[2] == "focus" end, + }, + aggro = { + order = 5, + type = "toggle", + name = L["On aggro"], + desc = L["Highlight units that have aggro on any mob."], + arg = "highlight.aggro", + 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, + type = "toggle", + name = L["On curable debuff"], + desc = L["Highlight units that are debuffed with something you can cure."], + arg = "highlight.debuff", + 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, + type = "range", + name = L["Border alpha"], + min = 0, max = 1, step = 0.05, + isPercent = true, + hidden = false, + arg = "highlight.alpha", + }, + size = { + order = 8, + type = "range", + name = L["Border thickness"], + min = 0, max = 50, step = 1, + arg = "highlight.size", + hidden = false, + }, + }, + }, + -- SOUL SHARDS + barSouls = { + order = 4, + type = "group", + inline = true, + 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["Soul Shards"]), + hidden = false, + arg = "soulShards.enabled", + }, + growth = { + order = 2, + type = "select", + name = L["Growth"], + values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, + hidden = false, + arg = "soulShards.growth", + }, + showAlways = { + order = 3, + type = "toggle", + name = L["Don't hide when empty"], + hidden = false, + arg = "soulShards.showAlways", + }, + }, + }, + soulShards = { + order = 4, + type = "group", + inline = true, + 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["Soul Shards"]), + hidden = false, + arg = "soulShards.enabled", + }, + 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 = "soulShards.growth", + }, + size = { + order = 2, + type = "range", + name = L["Size"], + min = 0, max = 50, step = 1, softMin = 0, softMax = 20, + hidden = hideAdvancedOption, + arg = "soulShards.size", + }, + spacing = { + order = 3, + type = "range", + name = L["Spacing"], + min = -30, max = 30, step = 1, softMin = -15, softMax = 15, + hidden = hideAdvancedOption, + arg = "soulShards.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 = "soulShards.anchorPoint", + }, + x = { + order = 6, + type = "range", + name = L["X Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "soulShards.x", + }, + y = { + order = 7, + type = "range", + name = L["Y Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "soulShards.y", + }, + }, + }, + -- ARCANE CHARGES + barArcane = { + order = 4, + type = "group", + inline = true, + 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 = { + 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["Arcane Charges"]), + hidden = false, + arg = "arcaneCharges.enabled", + }, + 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 = "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, + hidden = false, + arg = "arcaneCharges.anchorPoint", + }, + x = { + order = 6, + type = "range", + name = L["X Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "arcaneCharges.x", + }, + y = { + order = 7, + type = "range", + name = L["Y Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "arcaneCharges.y", + }, + }, + }, + -- HOLY POWER + barHolyPower = { + order = 4, + type = "group", + inline = true, + 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 = { + enabled = { + order = 1, + type = "toggle", + name = string.format(L["Enable %s"], L["Holy Power"]), + hidden = false, + arg = "holyPower.enabled", + }, + 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["Don't hide when empty"], + hidden = false, + arg = "holyPower.showAlways", + }, + }, + }, + holyPower = { + order = 4, + type = "group", + inline = true, + 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 = { + enabled = { + order = 0, + type = "toggle", + name = string.format(L["Enable %s"], L["Holy Power"]), + hidden = false, + arg = "holyPower.enabled", + }, + 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", + }, + size = { + order = 2, + type = "range", + name = L["Size"], + min = 0, max = 50, step = 1, softMin = 0, softMax = 20, + hidden = hideAdvancedOption, + arg = "holyPower.size", + }, + spacing = { + order = 3, + type = "range", + name = L["Spacing"], + min = -30, max = 30, step = 1, softMin = -15, softMax = 15, + hidden = hideAdvancedOption, + arg = "holyPower.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 = "holyPower.anchorPoint", + }, + x = { + order = 6, + type = "range", + name = L["X Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "holyPower.x", + }, + y = { + order = 7, + type = "range", + name = L["Y Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "holyPower.y", + }, + }, + }, + -- SHADOW ORBS + barShadowOrbs = { + order = 4, + type = "group", + inline = true, + 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 = { + enabled = { + order = 1, + type = "toggle", + name = string.format(L["Enable %s"], L["Shadow Orbs"]), + hidden = false, + arg = "shadowOrbs.enabled", + }, + growth = { + order = 2, + type = "select", + 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", + }, + }, + }, + shadowOrbs = { + order = 4, + type = "group", + inline = true, + name = L["Shadow Orbs"], + hidden = function(info) if( info[2] == "global" or getVariable(info[2], "shadowOrbs", nil, "isBar") ) then return true end return hideRestrictedOption(info) end, + args = { + enabled = { + order = 0, + type = "toggle", + name = string.format(L["Enable %s"], L["Shadow Orbs"]), + hidden = false, + arg = "shadowOrbs.enabled", + }, + 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 = "shadowOrbs.growth", + }, + size = { + order = 2, + type = "range", + name = L["Size"], + min = 0, max = 50, step = 1, softMin = 0, softMax = 20, + hidden = hideAdvancedOption, + arg = "shadowOrbs.size", + }, + spacing = { + order = 3, + type = "range", + name = L["Spacing"], + min = -30, max = 30, step = 1, softMin = -15, softMax = 15, + hidden = hideAdvancedOption, + arg = "shadowOrbs.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 = "shadowOrbs.anchorPoint", + }, + x = { + order = 6, + type = "range", + name = L["X Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "shadowOrbs.x", + }, + y = { + order = 7, + type = "range", + name = L["Y Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "shadowOrbs.y", + }, + }, + }, + -- Chi + barChi = { + order = 4, + type = "group", + inline = true, + 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 = { + enabled = { + order = 1, + type = "toggle", + name = string.format(L["Enable %s"], L["Chi"]), + hidden = false, + arg = "chi.enabled", + }, + growth = { + order = 2, + type = "select", + name = L["Growth"], + values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, + hidden = false, + arg = "chi.growth", + }, + 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["Growth"], + values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]}, + hidden = false, + arg = "chi.growth", + }, + 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 = 6, + type = "range", + name = L["X Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "chi.x", + }, + y = { + order = 7, + type = "range", + name = L["Y Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "chi.y", + }, + }, + }, + -- COMBO POINTS + barComboPoints = { + 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, + args = { + enabled = { + order = 1, + type = "toggle", + name = string.format(L["Enable %s"], L["Combo points"]), + hidden = false, + arg = "comboPoints.enabled", + }, + growth = { + order = 2, + type = "select", + name = L["Growth"], + values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, + hidden = false, + arg = "comboPoints.growth", + }, + showAlways = { + order = 3, + type = "toggle", + name = L["Don't hide when empty"], + hidden = false, + arg = "comboPoints.showAlways", + }, + }, + }, + comboPoints = { + 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, + args = { + enabled = { + order = 0, + type = "toggle", + name = string.format(L["Enable %s"], L["Combo points"]), + hidden = false, + arg = "comboPoints.enabled", + }, + 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 = "comboPoints.growth", + }, + size = { + order = 2, + type = "range", + name = L["Size"], + min = 0, max = 50, step = 1, softMin = 0, softMax = 20, + hidden = hideAdvancedOption, + arg = "comboPoints.size", + }, + 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["Anchor point"], + values = positionList, + hidden = false, + arg = "comboPoints.anchorPoint", + }, + x = { + order = 6, + type = "range", + name = L["X Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "comboPoints.x", + }, + y = { + order = 7, + type = "range", + name = L["Y Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "comboPoints.y", + }, + }, + }, + -- COMBO POINTS + barAuraPoints = { + order = 4, + type = "group", + inline = true, + 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["Aura Combo Points"]), + hidden = false, + arg = "auraPoints.enabled", + }, + growth = { + order = 2, + type = "select", + name = L["Growth"], + values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]}, + hidden = false, + arg = "auraPoints.growth", + }, + showAlways = { + order = 3, + type = "toggle", + name = L["Don't hide when empty"], + hidden = false, + arg = "auraPoints.showAlways", + }, + }, + }, + auraPoints = { + order = 4, + type = "group", + inline = true, + 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 = 0, + type = "toggle", + name = string.format(L["Enable %s"], L["Aura Combo Points"]), + hidden = false, + arg = "auraPoints.enabled", + }, + 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 = "auraPoints.growth", + }, + size = { + order = 2, + type = "range", + name = L["Size"], + min = 0, max = 50, step = 1, softMin = 0, softMax = 20, + hidden = hideAdvancedOption, + arg = "auraPoints.size", + }, + spacing = { + order = 3, + type = "range", + name = L["Spacing"], + min = -30, max = 30, step = 1, softMin = -15, softMax = 15, + hidden = hideAdvancedOption, + arg = "auraPoints.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 = "auraPoints.anchorPoint", + }, + x = { + order = 6, + type = "range", + name = L["X Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "auraPoints.x", + }, + y = { + order = 7, + type = "range", + name = L["Y Offset"], + min = -30, max = 30, step = 1, + hidden = false, + arg = "auraPoints.y", + }, + }, + }, + combatText = { + order = 5, + type = "group", + inline = true, + name = L["Combat text"], + hidden = hideRestrictedOption, + args = { + combatText = { + 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", + hidden = false, + }, + sep = { + order = 1, + type = "description", + name = "", + width = "full", + hidden = hideAdvancedOption, + }, + anchorPoint = { + order = 3, + type = "select", + name = L["Anchor point"], + values = positionList, + arg = "combatText.anchorPoint", + hidden = hideAdvancedOption, + }, + x = { + order = 4, + type = "range", + name = L["X Offset"], + min = -50, max = 50, step = 1, + arg = "combatText.x", + hidden = hideAdvancedOption, + }, + y = { + order = 5, + type = "range", + name = L["Y Offset"], + min = -50, max = 50, step = 1, + arg = "combatText.y", + hidden = hideAdvancedOption, + }, + }, + }, + }, + }, + attributes = { + order = 1.5, + type = "group", + 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 = { + show = { + order = 0.5, + type = "group", + inline = true, + name = L["Visibility"], + hidden = function(info) return info[2] ~= "party" and info[2] ~= "raid" 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", + }, + hideSemiRaidParty = { + order = 1, + type = "toggle", + 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", + }, + hideRaid = { + order = 2, + 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", + }, + 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" + }, + 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", + }, + }, + }, + general = { + order = 1, + type = "group", + inline = true, + name = L["General"], + hidden = false, + 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, + }, + 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 = -200, max = 200, 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.eclipseBar and not globalConfig.totemBar and not globalConfig.monkBar and not globalConfig.xpBar and not globalConfig.demonicFuryBar and not globalConfig.burningEmbersBar 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", + }, + eclipseBar = { + order = 1.25, + type = "toggle", + name = string.format(L["Enable %s"], L["Eclipse bar"]), + desc = L["Adds eclipse bars and how far into sun or moon eclipse is."], + hidden = hideRestrictedOption, + arg = "eclipseBar.enabled", + }, + demonicFuryBar = { + order = 1.25, + type = "toggle", + name = string.format(L["Enable %s"], L["Demonic Fury bar"]), + desc = L["Adds a Demonic Fury bar for Demonology Warlocks."], + hidden = hideRestrictedOption, + arg = "demonicFuryBar.enabled", + }, + burningEmbersBar = { + order = 1.25, + type = "toggle", + name = string.format(L["Enable %s"], L["Burning Embers bar"]), + desc = L["Adds a Burning Embers bar for Destruction Warlocks."], + hidden = hideRestrictedOption, + arg = "burningEmbersBar.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 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 L["Adds a bar indicating how much time is left on your mushrooms."] + end, + hidden = hideRestrictedOption, + arg = "totemBar.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."], + 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."], + 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) + 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 + local unit = info[#(info)] + 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 = GetSpellName(name) + local icon = GetSpellTexture(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 _, unitEntry in pairs(ShadowUF.unitList) do + ShadowUF.db.profile.filters[filterKey][zoneConfig .. unitEntry] = 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 _, unitEntry in pairs(ShadowUF.unitList) do + ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unitEntry] = nil + ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unitEntry] = nil + ShadowUF.db.profile.filters.zoneoverride[zoneConfig .. unitEntry] = 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 manageFiltersTableEntry = { + 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 + + manageFiltersTableEntry.args[tostring(filterID)] = CopyTable(filterEditTable) + manageFiltersTableEntry.args.groups.args[filterID .. "label"] = filterLabel + manageFiltersTableEntry.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 + + manageFiltersTableEntry.args[tostring(filterID)].args.spells.args[spellID .. "label"] = spellLabel + manageFiltersTableEntry.args[tostring(filterID)].args.spells.args[tostring(spellID)] = spellRow + end + end + + if( not hasSpells ) then + manageFiltersTableEntry.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 + manageFiltersTableEntry.args.groups.args.noFilters = noFilters + end + + return manageFiltersTableEntry + 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, + 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) + 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) + 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."] + else + tagData.error = nil + 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, + } + + 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 + + -- Tag configuration + options.args.tags = { + type = "group", + childGroups = "tab", + name = L["Add Tags"], + desc = getPageDescription, + hidden = hideAdvancedOption, + args = { + 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", + name = L["Add new tag"], + 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, + 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, + }, + }, + }, + }, + }, + help = { + order = 3, + type = "group", + name = L["Help"], + args = { + general = { + order = 0, + 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."], + }, + }, + }, + documentation = { + order = 1, + type = "group", + 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 = { + lua = { + 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, + width = "full", + }, + }, + }, + }, + }, + }, + } + + -- 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 + + -- Annoying yes, but only way that works + ShadowUF.Units:CheckPlayerZone(true) + + if( unit == "global" ) then + globalVisibility[area .. key] = value + 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 + + 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 + + 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) + 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, + }, + } + } + + 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 + end + + areaTable.args.global = Config.visibilityTable + for _, unit in pairs(ShadowUF.unitList) do + if( not unitBlacklist[unit] ) then + areaTable.args[unit] = Config.visibilityTable + end + 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, + }, + } +end + +--------------------- +-- AURA INDICATORS OPTIONS +--------------------- +local function loadAuraIndicatorsOptions() + local Indicators = ShadowUF.modules.auraIndicators + local auraFilters = Indicators.auraFilters + + 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 + + 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 = GetSpellName(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 + + return indicatorList + 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 + + return string.format(L["%d auras in group"], totalInGroup) + end, + args = {}, + } + + local auraConfigTable = { + order = 0, + type = "group", + icon = function(info) + local aura = auraMap[info[#(info)]] + return tonumber(aura) and (GetSpellTexture(aura)) or nil + end, + name = function(info) + local aura = auraMap[info[#(info)]] + return tonumber(aura) and string.format("%s (#%i)", GetSpellName(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)] + + -- 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 + + 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 config[key] + end, + 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["Show aura icon"], + desc = L["Instead of showing a solid color inside the indicator, the icon of the aura will be shown."], + hidden = false, + }, + 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] + + 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 + + ShadowUF.Layout:Reload() + end, + }, + }, + } + + 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 ShadowUF.db.profile.auraIndicators.filters[indicator][filter][key] + end, + 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 + } + } + }, + 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 + } + } + } + } + } + + local indicatorTable = { + order = 1, + type = "group", + name = function(info) return ShadowUF.db.profile.auraIndicators.indicators[info[#(info)]].name end, + args = { + config = { + order = 0, + type = "group", + inline = true, + 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 = { + 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, + }, + }, + }, + }, + } + + local parentLinkTable = { + order = 3, + type = "group", + icon = function(info) + local aura = auraMap[info[#(info)]] + return tonumber(aura) and (GetSpellTexture(aura)) or nil + end, + name = function(info) + local aura = linkMap[info[#(info)]] + return tonumber(aura) and string.format("%s (#%i)", GetSpellName(aura) or "Unknown", aura) or aura + end, + args = {}, + } + + local childLinkTable = { + order = 1, + icon = function(info) + local aura = auraMap[info[#(info)]] + return tonumber(aura) and (GetSpellTexture(aura)) or nil + end, + name = function(info) + local aura = linkMap[info[#(info)]] + return tonumber(aura) and string.format("%s (#%i)", GetSpellName(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", + inline = true, + args = { + 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 = function(info) return string.format(L["On %s units"], L.units[info[3]]) end, + args = { + 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["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 + } + + 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 + } + + 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, + get = function(info, value) return not globalConfig[groupMap[info[#(info)]]] end + } + + 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 enabledUnits + end + + 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", + hidden = false, + args = { + indicators = { + order = 1, + type = "group", + name = L["Indicators"], + childGroups = "tree", + args = { + add = { + order = 0, + type = "group", + name = L["Add Indicator"], + args = { + add = { + order = 0, + 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, + }, + }, + }, + }, + }, + }, + }, + auras = { + order = 2, + type = "group", + 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 = { + add = { + order = 0, + type = "group", + name = L["Add Aura"], + set = function(info, value) addAura[info[#(info)]] = value end, + get = function(info) return addAura[info[#(info)]] end, + args = { + name = { + order = 0, + 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."] + }, + 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["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 GetSpellTexture directly + Indicators.auraConfig[addAura.name] = {indicator = "", group = group, iconTexture = GetSpellTexture(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 + + addAura.name = nil + addAura.custom = nil + addAura.group = nil + + -- Check if the group exists + local gID + for id, name in pairs(groupMap) do + if( name == group ) then + gID = id + break + end + end + + 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 = {} + }, + }, + }, + linked = { + order = 3, + type = "group", + name = L["Linked spells"], + childGroups = "tree", + hidden = true, + args = { + help = { + order = 0, + type = "group", + name = L["Help"], + inline = true, + args = { + help = { + order = 0, + type = "description", + 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", + }, + }, + }, + add = { + order = 1, + type = "group", + name = L["Add link"], + inline = true, + set = function(info, value) + addLink[info[#(info)] ] = value + end, + get = function(info) return addLink[info[#(info)] ] end, + args = { + from = { + order = 0, + type = "input", + name = L["Link from"], + desc = L["Spell you want to link to a primary aura, the casing must be exact."], + }, + to = { + order = 1, + type = "select", + name = L["Link to"], + values = getAuraList, + }, + link = { + order = 3, + type = "execute", + name = L["Link"], + disabled = function() return not addLink.from or not addLink.to or addLink.from == "" end, + func = function(info) + 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 + + if( not pID ) then + linkID = linkID + 1 + pID = linkID + linkMap[tostring(linkID)] = addLink.to + end + + 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, + }, + }, + }, + }, + }, + units = { + order = 4, + type = "group", + name = L["Enable Indicators"], + args = { + help = { + order = 0, + type = "group", + name = L["Help"], + inline = true, + args = { + help = { + order = 0, + type = "description", + 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", + }, + }, + }, + global = { + order = 0, + type = "group", + name = L["Global"], + desc = L["Global configurating will let you mass enable or disable aura groups for multiple units at once."], + args = { + units = { + order = 0, + 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 = {} + }, + }, + }, + }, + }, + classes = { + order = 5, + type = "group", + name = L["Disable Auras by Class"], + childGroups = "tree", + args = { + help = { + order = 0, + type = "group", + name = L["Help"], + inline = true, + args = { + help = { + order = 0, + 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 = {}, + } + + local classAuraTable = { + order = 1, + type = "toggle", + icon = function(info) + local aura = auraMap[info[#(info)]] + return tonumber(aura) and (GetSpellTexture(aura)) or nil + end, + name = function(info) + local aura = tonumber(auraMap[info[#(info)]]) + if( not aura ) then return auraMap[info[#(info)]] end + + local name = GetSpellName(aura) + local icon = GetSpellTexture(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, + } + + -- 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 + + ShadowUF.db.profile.auraIndicators.linked[from] = to + options.args.auraIndicators.args.linked.args[tostring(pID)] = parentLinkTable + parentLinkTable.args[tostring(linkID)] = childLinkTable + + linkMap[tostring(linkID)] = from + linkMap[tostring(pID)] = to + end + + -- 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 + + -- Now create all of the parent stuff + for group in pairs(groups) do + 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 + + groupID = groupID + 1 + end + + 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 + + -- Build class status thing + for classToken in pairs(RAID_CLASS_COLORS) do + options.args.auraIndicators.args.classes.args[classToken] = classTable + 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 + + -- 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 + + advanceTextTable.args.anchorPoint.hidden = unlockRaidText + advanceTextTable.args.sep.hidden = unlockRaidText + advanceTextTable.args.x.hidden = unlockRaidText + advanceTextTable.args.y.hidden = unlockRaidText +end + +local function loadOptions() + options = { + type = "group", + name = "Shadowed UF", + args = {} + } + + loadGeneralOptions() + loadUnitOptions() + loadHideOptions() + 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 + + -- Options finished loading, fire callback for any non-default modules that want to be included + ShadowUF:FireModuleEvent("OnConfigurationLoad") +end + +local defaultToggles +function Config:Open() + AceDialog = AceDialog or LibStub("AceConfigDialog-3.0") + AceRegistry = AceRegistry or LibStub("AceConfigRegistry-3.0") + + if( not registered ) then + loadOptions() + + 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 From 49b0ecde7a98ccf541d4e9650e6278839a45ebee Mon Sep 17 00:00:00 2001 From: Hyphie <31455641+Hyphie24@users.noreply.github.com> Date: Fri, 26 Sep 2025 22:54:11 -0400 Subject: [PATCH 102/108] Update indicators.lua --- modules/indicators.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/indicators.lua b/modules/indicators.lua index 5480d19d2..a89ed7965 100755 --- a/modules/indicators.lua +++ b/modules/indicators.lua @@ -1,4 +1,4 @@ -local Indicators = {list = {"status", "pvp", "leader", "resurrect", "masterLoot", "raidTarget", "ready", "role", "class", "phase", "happiness" }} +local Indicators = {list = {"status", "pvp", "leader", "resurrect", "sumPending", "masterLoot", "raidTarget", "ready", "role", "lfdRole", "class", "phase", "questBoss", "petBattle", "arenaSpec"}} ShadowUF:RegisterModule(Indicators, "indicators", ShadowUF.L["Indicators"]) @@ -79,7 +79,7 @@ end function Indicators:UpdateMasterLoot(frame) if( not frame.indicators.masterLoot or not frame.indicators.masterLoot.enabled ) then return end - local lootType, partyID, raidID = GetLootMethod() + local lootType, partyID, raidID = C_PartyInfo.GetLootMethod() if( lootType ~= "master" ) then frame.indicators.masterLoot:Hide() elseif( ( partyID and partyID == 0 and UnitIsUnit(frame.unit, "player") ) or ( partyID and partyID > 0 and UnitIsUnit(frame.unit, ShadowUF.partyUnits[partyID]) ) or ( raidID and raidID > 0 and UnitIsUnit(frame.unit, ShadowUF.raidUnits[raidID]) ) ) then From d6e54e4b3ffba22b97459cb0712a2a217208ca91 Mon Sep 17 00:00:00 2001 From: Hyphie <31455641+Hyphie24@users.noreply.github.com> Date: Fri, 26 Sep 2025 22:56:12 -0400 Subject: [PATCH 103/108] Update soulshards.lua --- modules/soulshards.lua | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/modules/soulshards.lua b/modules/soulshards.lua index 7db176068..aef963edc 100755 --- a/modules/soulshards.lua +++ b/modules/soulshards.lua @@ -1,24 +1,25 @@ if( not ShadowUF.ComboPoints ) then return end ---if select(4, GetBuildInfo()) < 50500 then return end local Souls = setmetatable({}, {__index = ShadowUF.ComboPoints}) ShadowUF:RegisterModule(Souls, "soulShards", ShadowUF.L["Soul Shards"], nil, "WARLOCK", SPEC_WARLOCK_AFFLICTION) local soulsConfig = {max = 4, key = "soulShards", colorKey = "SOULSHARDS", powerType = Enum.PowerType.SoulShards, eventType = "SOUL_SHARDS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\shard"} +local GetSpecialization = C_SpecializationInfo.GetSpecialization or _G.GetSpecialization + function Souls:OnEnable(frame) frame.soulShards = frame.soulShards or CreateFrame("Frame", nil, frame) frame.soulShards.cpConfig = soulsConfig + frame.soulShards.cpConfig.max = (GetSpecialization() == SPEC_WARLOCK_AFFLICTION) and 50 or 5 + frame.soulShards.cpConfig.grouping = (GetSpecialization() == SPEC_WARLOCK_AFFLICTION) 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") - - - soulsConfig.max = UnitPowerMax("player", soulsConfig.powerType) end @@ -27,22 +28,23 @@ function Souls:OnLayoutApplied(frame, config) self:UpdateBarBlocks(frame) end - function Souls:GetComboPointType() - return "soulShards" - end +function Souls:SpecChanged(frame) + -- update shard count on spec swap + if frame and frame.soulShards then + frame.soulShards.cpConfig.max = (GetSpecialization() == SPEC_WARLOCK_AFFLICTION) and 50 or 5 + frame.soulShards.cpConfig.grouping = (GetSpecialization() == SPEC_WARLOCK_AFFLICTION) 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) - - - - - - - - - - - - + return UnitPower("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_AFFLICTION)) +end + +function Souls:GetMaxPoints(unit) + return UnitPowerMax("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_AFFLICTION)) end From 015b64c981b02ae59a1a532843eb516f40cfd2f0 Mon Sep 17 00:00:00 2001 From: Hyphie <31455641+Hyphie24@users.noreply.github.com> Date: Sun, 28 Sep 2025 18:25:26 -0400 Subject: [PATCH 104/108] Display Auras when SUF is Unlocked --- modules/auras.lua | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/modules/auras.lua b/modules/auras.lua index 5f2635349..e3d9b665a 100755 --- a/modules/auras.lua +++ b/modules/auras.lua @@ -2,6 +2,8 @@ local Auras = {} local playerUnits = {player = true, vehicle = true, pet = true} local mainHand, offHand, tempEnchantScan = {time = 0}, {time = 0} local canCure = ShadowUF.Units.canCure +local GetAuraDataByIndex = C_UnitAuras.GetAuraDataByIndex + ShadowUF:RegisterModule(Auras, "auras", ShadowUF.L["Auras"]) function Auras:OnEnable(frame) @@ -594,7 +596,49 @@ local function scan(parent, frame, type, config, displayConfig, filter) local index = 0 while( true ) do index = index + 1 - local name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = AuraUtil.UnpackAuraData(C_UnitAuras.GetAuraDataByIndex(frame.parent.unit, index, filter)) + + +local UnitAuraFunc +if not ShadowUF.db.profile.locked then + -- Config (unlocked) mode: functions run with configEnv as their _ENV, so plain UnitAura refers to configEnv.UnitAura (the dummy movers.lua provides). + if _G.type(UnitAura) == "function" then + UnitAuraFunc = UnitAura + else + -- Safety: fallback no-op to avoid nil calls + UnitAuraFunc = function() return end + end +else + -- Locked/normal gameplay: use the real Blizzard API (global _G.UnitAura) or the modern C_UnitAuras interface + if _G.type(_G.UnitAura) == "function" then + UnitAuraFunc = _G.UnitAura + elseif _G.C_UnitAuras and _G.type(_G.C_UnitAuras.GetAuraDataByIndex) == "function" then + UnitAuraFunc = function(unit, index, filter) + local info = _G.C_UnitAuras.GetAuraDataByIndex(unit, index, filter) + if not info then return end + local name = info.spellName or info.name or info.displayName + local texture = info.icon or info.texture + local count = info.count or info.stackCount or 0 + local auraType = info.debuffType or info.dispelType or info.auraType + local duration = info.durationSec or info.duration or 0 + local endTime = info.expirationTime or (duration > 0 and (_G.GetTime() + duration)) or 0 + local caster = info.sourceUnit or info.caster + local isRemovable = info.isStealable or info.isRemovable or false + local nameplateShowPersonal = info.nameplateShowPersonal or false + local spellID = info.spellId or info.spellID or 0 + local canApplyAura = info.canApplyAura or info.canApply or false + local isBossDebuff = info.isBossAura or info.isBossDebuff or false + return name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff + end + else + UnitAuraFunc = function() return end + end +end + +-- Call resolved function +local name, texture, count, auraType, duration, endTime, caster, isRemovable, + nameplateShowPersonal, spellID, canApplyAura, isBossDebuff = + UnitAuraFunc(frame.parent.unit, index, filter) + if( not name ) then break end renderAura(parent, frame, type, config, displayConfig, index, filter, isFriendly, curable, name, texture, count, auraType, duration, endTime, caster, isRemovable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff) From 0c94dae1b0557609def298a85643707258340d9c Mon Sep 17 00:00:00 2001 From: Hyphie <31455641+Hyphie24@users.noreply.github.com> Date: Sun, 28 Sep 2025 18:25:50 -0400 Subject: [PATCH 105/108] STACK OVERFLOW Crash Fix --- modules/basecombopoints.lua | 376 +++++++++++++++++++----------------- 1 file changed, 196 insertions(+), 180 deletions(-) diff --git a/modules/basecombopoints.lua b/modules/basecombopoints.lua index c08519da3..b99bbb9ca 100644 --- a/modules/basecombopoints.lua +++ b/modules/basecombopoints.lua @@ -1,204 +1,220 @@ local Combo = {isComboPoints = true} ShadowUF.ComboPoints = Combo +-- Create combo point icons 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 + 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 +-- Create combo point blocks (bar mode) 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 + local pointsConfig = pointsFrame.cpConfig + if pointsConfig.max == 0 then return end + pointsFrame.visibleBlocks = pointsConfig.max + + 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 +-- Prevent recursion during layout 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() - texture:ClearAllPoints() - 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 + local key = self:GetComboPointType() + local pointsFrame = frame[key] + if not pointsFrame then return end + + if pointsFrame._inLayout then return end + pointsFrame._inLayout = true + + pointsFrame:SetFrameLevel(frame.topFrameLevel + 1) + + local pointsConfig = pointsFrame.cpConfig + config = config[key] + + if config and not config.isBar then + ShadowUF.Layout:ToggleVisibility(pointsFrame, frame.visibility[key]) + end + + if not frame.visibility[key] then + pointsFrame._inLayout = nil + return + end + + if pointsFrame.points then + for _, texture in pairs(pointsFrame.points) do + texture:Hide() + texture:ClearAllPoints() + end + end + + if config.isBar then + pointsFrame.blocks = pointsFrame.blocks or {} + pointsFrame.points = pointsFrame.blocks + createBlocks(config, pointsFrame) + else + pointsFrame.icons = pointsFrame.icons or {} + pointsFrame.points = pointsFrame.icons + createIcons(config, pointsFrame) + + if pointsFrame:GetWidth() ~= 0.1 or pointsFrame:GetHeight() ~= 0.1 then + pointsFrame:SetSize(0.1, 0.1) + end + + if not pointsFrame._anchored then + ShadowUF.Layout:AnchorFrame(frame, pointsFrame, config) + pointsFrame._anchored = true + end + end + + pointsFrame._inLayout = nil end function Combo:OnDisable(frame) - frame:UnregisterAll(self) + frame:UnregisterAll(self) end +-- Safe update for bar blocks 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 - + 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) + -- Clamp to safe maximum of 5 + if max > 5 then max = 5 end + if max == 0 or pointsFrame.visibleBlocks == max then return end + + if pointsFrame._updatingBlocks then return end + pointsFrame._updatingBlocks = true + + 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 + pointsFrame._updatingBlocks = nil + 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 + + pointsFrame._updatingBlocks = nil end +-- Regular Update 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 + local key = self:GetComboPointType() + if event and frame[key].cpConfig.eventType and frame[key].cpConfig.eventType ~= powerType then return end + + local points = self:GetPoints(unit) + + 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 +-- Adjust block heights when frame changes 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 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 + local height = frame[key]:GetHeight() + for _, block in pairs(frame[key].blocks) do + block:SetHeight(height) + end end From 446643632741c39f2cbdae3f9d4fd2f1762afaee Mon Sep 17 00:00:00 2001 From: Hyphie <31455641+Hyphie24@users.noreply.github.com> Date: Sun, 28 Sep 2025 18:26:09 -0400 Subject: [PATCH 106/108] Update burningembers.lua --- modules/burningembers.lua | 54 ++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/modules/burningembers.lua b/modules/burningembers.lua index 9be8a899b..04da71499 100644 --- a/modules/burningembers.lua +++ b/modules/burningembers.lua @@ -91,29 +91,35 @@ function Embers:UpdateBarBlocks(frame, event, unit, powerType) end function Embers:Update(frame, event, unit, powerType) - if( event and powerType ~= "BURNING_EMBERS" ) then return end - - local power = UnitPower("player", Enum.PowerType.BurningEmbers, true) - for id=1, frame.burningEmbersBar.visibleBlocks do - local ember = frame.burningEmbersBar.embers[id] - - local color - if( power >= MAX_POWER_PER_EMBER ) then - color = "FULLBURNINGEMBER" - ember:SetValue(MAX_POWER_PER_EMBER) - elseif( power > 0 ) then - color = "BURNINGEMBERS" - ember:SetValue(power) - else - color = "BURNINGEMBERS" - ember:SetValue(0) - end + if( event and powerType ~= "BURNING_EMBERS" ) then return end + + local power = UnitPower("player", Enum.PowerType.BurningEmbers, true) + for id=1, frame.burningEmbersBar.visibleBlocks do + local ember = frame.burningEmbersBar.embers[id] + + local value = math.min(power, MAX_POWER_PER_EMBER) + ember:SetValue(value) + + local color + if value == MAX_POWER_PER_EMBER then + color = "FULLBURNINGEMBER" + else + color = "BURNINGEMBERS" + end + + if ember.setColor ~= color then + ember.setColor = color + frame:SetBlockColor( + ember, + "burningEmbersBar", + ShadowUF.db.profile.powerColors[color].r, + ShadowUF.db.profile.powerColors[color].g, + ShadowUF.db.profile.powerColors[color].b + ) + end + + power = power - MAX_POWER_PER_EMBER + end +end - if( ember.setColor ~= color ) then - ember.setColor = color - frame:SetBlockColor(ember, "burningEmbersBar", ShadowUF.db.profile.powerColors[color].r, ShadowUF.db.profile.powerColors[color].g, ShadowUF.db.profile.powerColors[color].b) - end - power = power - MAX_POWER_PER_EMBER - end -end From 1ad83e4bc41b562c07c2c5e759c037c150791978 Mon Sep 17 00:00:00 2001 From: Hyphie <31455641+Hyphie24@users.noreply.github.com> Date: Sun, 28 Sep 2025 18:26:27 -0400 Subject: [PATCH 107/108] Update combopoints.lua --- modules/combopoints.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/combopoints.lua b/modules/combopoints.lua index d72b4f871..8b0b602ba 100755 --- a/modules/combopoints.lua +++ b/modules/combopoints.lua @@ -2,7 +2,7 @@ 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"} +local cpConfig = {max = MAX_COMBO_POINTS, key = "comboPoints", colorKey = "COMBOPOINTS", powerType = Enum.PowerType.ComboPoints, eventType = "COMBO_POINTS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"} function Combo:OnEnable(frame) frame.comboPoints = frame.comboPoints or CreateFrame("Frame", nil, frame) @@ -35,8 +35,14 @@ function Combo:GetPoints(unit) end end +local ParentUpdate = ShadowUF.ComboPoints.Update + function Combo:Update(frame, event, unit, powerType) + -- Prevent recursion when arena frames are unloading + if not frame or not frame.comboPoints or not frame.comboPoints.cpConfig then + return + end 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) + ParentUpdate(self, frame, event, unit, powerType) end end From 267708b20ef0f15fa720b818af3d19630cb10703 Mon Sep 17 00:00:00 2001 From: Hyphie <31455641+Hyphie24@users.noreply.github.com> Date: Sun, 28 Sep 2025 18:26:44 -0400 Subject: [PATCH 108/108] STACK OVERFLOW Fix --- modules/soulshards.lua | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/modules/soulshards.lua b/modules/soulshards.lua index aef963edc..1db8c677b 100755 --- a/modules/soulshards.lua +++ b/modules/soulshards.lua @@ -2,15 +2,16 @@ if( not ShadowUF.ComboPoints ) then return end local Souls = setmetatable({}, {__index = ShadowUF.ComboPoints}) ShadowUF:RegisterModule(Souls, "soulShards", ShadowUF.L["Soul Shards"], nil, "WARLOCK", SPEC_WARLOCK_AFFLICTION) -local soulsConfig = {max = 4, key = "soulShards", colorKey = "SOULSHARDS", powerType = Enum.PowerType.SoulShards, eventType = "SOUL_SHARDS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\shard"} +local soulsConfig = {max = 5, key = "soulShards", colorKey = "SOULSHARDS", powerType = Enum.PowerType.SoulShards, eventType = "SOUL_SHARDS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\shard"} -local GetSpecialization = C_SpecializationInfo.GetSpecialization or _G.GetSpecialization +local GetSpecialization = C_SpecializationInfo.GetSpecialization function Souls:OnEnable(frame) frame.soulShards = frame.soulShards or CreateFrame("Frame", nil, frame) frame.soulShards.cpConfig = soulsConfig - frame.soulShards.cpConfig.max = (GetSpecialization() == SPEC_WARLOCK_AFFLICTION) and 50 or 5 - frame.soulShards.cpConfig.grouping = (GetSpecialization() == SPEC_WARLOCK_AFFLICTION) and UnitPowerDisplayMod(soulsConfig.powerType) or 1 + -- Force safe max (never above 5) + frame.soulShards.cpConfig.max = 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") @@ -20,7 +21,6 @@ function Souls:OnEnable(frame) frame:RegisterUpdateFunc(self, "Update") frame:RegisterUpdateFunc(self, "UpdateBarBlocks") - end function Souls:OnLayoutApplied(frame, config) @@ -31,8 +31,9 @@ end function Souls:SpecChanged(frame) -- update shard count on spec swap if frame and frame.soulShards then - frame.soulShards.cpConfig.max = (GetSpecialization() == SPEC_WARLOCK_AFFLICTION) and 50 or 5 - frame.soulShards.cpConfig.grouping = (GetSpecialization() == SPEC_WARLOCK_AFFLICTION) and UnitPowerDisplayMod(soulsConfig.powerType) or 1 + -- Force safe max (never above 5) + frame.soulShards.cpConfig.max = 5 + frame.soulShards.cpConfig.grouping = (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION) and UnitPowerDisplayMod(soulsConfig.powerType) or 1 end self:UpdateBarBlocks(frame) end @@ -42,9 +43,9 @@ function Souls:GetComboPointType() end function Souls:GetPoints(unit) - return UnitPower("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_AFFLICTION)) + return UnitPower("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION)) end function Souls:GetMaxPoints(unit) - return UnitPowerMax("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_AFFLICTION)) + return UnitPowerMax("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION)) end