diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..29f90321e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+indent_style = tab
+indent_size = 4
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[{.travis.yml,.pkgmeta}]
+indent_style = space
+indent_size = 2
diff --git a/.github/workflows/packager.yml b/.github/workflows/packager.yml
new file mode 100644
index 000000000..f19ca09d7
--- /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-22.04
+
+ # 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..e8593bfe5
--- /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-22.04
+
+ steps:
+ - uses: actions/checkout@v2
+ - 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/.gitignore b/.gitignore
new file mode 100755
index 000000000..24b392cd1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+suf.tmproj
+.DS_Store
\ No newline at end of file
diff --git a/.luacheckrc b/.luacheckrc
new file mode 100644
index 000000000..29cb0dcd6
--- /dev/null
+++ b/.luacheckrc
@@ -0,0 +1,222 @@
+std = "lua51"
+max_line_length = false
+exclude_files = {
+ "libs/",
+ "locale-import.lua",
+ ".luacheckrc"
+}
+
+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
+ "213", -- Unused loop variable
+ "231/_.*", -- unused variables starting with _
+ "431", -- shadowing upvalue
+ "311", -- Value assigned to a local variable is unused
+ "512", -- loop only executed once
+ "542", -- empty if branch
+}
+
+globals = {
+ "ShadowUF",
+ "ClickCastFrames",
+ "CONFIGMODE_CALLBACKS",
+ "SlashCmdList",
+}
+
+read_globals = {
+ "hooksecurefunc",
+ "CopyTable",
+ "string.split",
+ "string.trim",
+ "string.utf8sub",
+ "table.wipe",
+ "time",
+
+ -- misc custom, third party libraries
+ "ClickCastHeader",
+ "LibStub",
+ "BigWigsAPI",
+
+ -- API functions
+ "C_AddOns",
+ "C_IncomingSummon",
+ "C_PartyInfo",
+ "C_Reputation",
+ "C_Spell",
+ "C_Timer",
+ "C_UnitAuras",
+ "CancelUnitBuff",
+ "CanHearthAndResurrectFromArea",
+ "CreateFrame",
+ "GetArenaOpponentSpec",
+ "GetBuildInfo",
+ "GetComboPoints",
+ "GetInventoryItemTexture",
+ "GetLocale",
+ "GetLootMethod",
+ "GetMaxLevelForPlayerExpansion",
+ "GetNumArenaOpponentSpecs",
+ "GetPartyAssignment",
+ "GetPetExperience",
+ "GetRaidTargetIndex",
+ "GetReadyCheckStatus",
+ "GetRuneCooldown",
+ "GetSpecialization",
+ "GetSpecializationInfoByID",
+ "GetText",
+ "GetTime",
+ "GetTotemInfo",
+ "GetUnitPowerBarInfoByID",
+ "GetWeaponEnchantInfo",
+ "GetXPExhaustion",
+ "HasLFGRestrictions",
+ "InCombatLockdown",
+ "IsEveryoneAssistant",
+ "IsInInstance",
+ "IsPlayerSpell",
+ "IsResting",
+ "IsShiftKeyDown",
+ "IsSpellKnown",
+ "IsXPUserDisabled",
+ "UnitAffectingCombat",
+ "UnitBattlePetType",
+ "UnitCanAssist",
+ "UnitCanAttack",
+ "UnitCastingInfo",
+ "UnitChannelInfo",
+ "UnitClass",
+ "UnitClassification",
+ "UnitCreatureFamily",
+ "UnitExists",
+ "UnitFactionGroup",
+ "UnitGetIncomingHeals",
+ "UnitGetTotalAbsorbs",
+ "UnitGetTotalHealAbsorbs",
+ "UnitGroupRolesAssigned",
+ "UnitGUID",
+ "UnitHasIncomingResurrection",
+ "UnitHasVehiclePlayerFrameUI",
+ "UnitHasVehicleUI",
+ "UnitHealth",
+ "UnitHealthMax",
+ "UnitInParty",
+ "UnitInRaid",
+ "UnitInRange",
+ "UnitIsBattlePetCompanion",
+ "UnitIsConnected",
+ "UnitIsDeadOrGhost",
+ "UnitIsEnemy",
+ "UnitIsFriend",
+ "UnitIsGroupAssistant",
+ "UnitIsGroupLeader",
+ "UnitIsPlayer",
+ "UnitIsPVP",
+ "UnitIsPVPFreeForAll",
+ "UnitIsQuestBoss",
+ "UnitIsTapDenied",
+ "UnitIsUnit",
+ "UnitIsVisible",
+ "UnitIsWildBattlePet",
+ "UnitLeadsAnyGroup",
+ "UnitLevel",
+ "UnitPhaseReason",
+ "UnitPlayerControlled",
+ "UnitPlayerOrPetInParty",
+ "UnitPlayerOrPetInRaid",
+ "UnitPower",
+ "UnitPowerBarID",
+ "UnitPowerDisplayMod",
+ "UnitPowerMax",
+ "UnitPowerType",
+ "UnitReaction",
+ "UnitSex",
+ "UnitStagger",
+ "UnitThreatSituation",
+ "UnitXP",
+ "UnitXPMax",
+
+ -- FrameXML frames
+ "AlternatePowerBar",
+ "ArenaEnemyFramesContainer",
+ "ArenaEnemyPrepFramesContainer",
+ "ArenaEnemyMatchFramesContainer",
+ "BossTargetFrameContainer",
+ "BuffFrame",
+ "ComboFrame",
+ "CompactPartyFrame",
+ "CompactRaidFrameContainer",
+ "CompactRaidFrameManager",
+ "DebuffFrame",
+ "DEFAULT_CHAT_FRAME",
+ "EssencePlayerFrame",
+ "FocusFrame",
+ "FocusFrameToT",
+ "GameTooltip",
+ "MageArcaneChargesFrame",
+ "MonkHarmonyBarFrame",
+ "PaladinPowerBarFrame",
+ "PartyFrame",
+ "PetCastingBarFrame",
+ "PetFrame",
+ "PlayerCastingBarFrame",
+ "PlayerFrame",
+ "PlayerPowerBarAlt",
+ "RuneFrame",
+ "TargetFrame",
+ "TargetFrameToT",
+ "UIParent",
+ "WarlockPowerFrame",
+
+ -- FrameXML functions
+ "AuraUtil.UnpackAuraData",
+ "BackdropTemplateMixin",
+ "CombatFeedback_OnCombatEvent",
+ "CombatFeedback_OnUpdate",
+ "CompactRaidFrameManager_GetSetting",
+ "CompactRaidFrameManager_SetSetting",
+ "GetClassAtlas",
+ "RegisterStateDriver",
+ "RegisterUnitWatch",
+ "SecureButton_GetModifiedUnit",
+ "SecureHandler_OnLoad",
+ "SetPortraitTexture",
+ "SetRaidTargetIconTexture",
+ "UnitFrame_OnEnter",
+ "UnitFrame_OnLeave",
+ "UnregisterUnitWatch",
+
+ -- FrameXML constants
+ "DebuffTypeColor",
+ "Enum",
+ "PowerBarColor",
+ "ALTERNATE_POWER_INDEX",
+ "CLASS_ICON_TCOORDS",
+ "CLASS_SORT_ORDER",
+ "FACTION_BAR_COLORS",
+ "LOCALIZED_CLASS_NAMES_MALE",
+ "MAX_BOSS_FRAMES",
+ "MAX_COMBO_POINTS",
+ "MAX_PARTY_MEMBERS",
+ "MAX_RAID_MEMBERS",
+ "MAX_TOTEMS",
+ "MEMBERS_PER_RAID_GROUP",
+ "PET_TYPE_SUFFIX",
+ "RAID_CLASS_COLORS",
+ "READY_CHECK_NOT_READY_TEXTURE",
+ "READY_CHECK_READY_TEXTURE",
+ "READY_CHECK_WAITING_TEXTURE",
+ "SHAMAN_TOTEM_PRIORITIES",
+ "SPEC_MAGE_ARCANE",
+ "SPEC_MONK_BREWMASTER",
+ "SPEC_MONK_WINDWALKER",
+ "SPEC_PALADIN_RETRIBUTION",
+ "SPEC_PRIEST_SHADOW",
+ "SPEC_WARLOCK_DESTRUCTION",
+ "STAGGER_STATES",
+ "STANDARD_TOTEM_PRIORITIES",
+ "TextureKitConstants",
+}
diff --git a/.pkgmeta b/.pkgmeta
old mode 100644
new mode 100755
index 542192a1f..c4b13cd29
--- a/.pkgmeta
+++ b/.pkgmeta
@@ -1,33 +1,31 @@
package-as: ShadowedUnitFrames
move-folders:
- ShadowedUnitFrames/options: ShadowedUF_Options
+ ShadowedUnitFrames/options: ShadowedUF_Options
externals:
libs/LibStub:
- url: svn://svn.wowace.com/wow/libstub/mainline/trunk
- tag: latest
+ url: https://repos.wowace.com/wow/libstub/tags/1.0
libs/CallbackHandler-1.0:
- url: svn://svn.wowace.com/wow/callbackhandler/mainline/trunk
- tag: latest
+ url: https://repos.wowace.com/wow/callbackhandler/trunk/CallbackHandler-1.0
libs/AceDB-3.0:
- url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0
+ url: https://repos.wowace.com/wow/ace3/trunk/AceDB-3.0
libs/LibSharedMedia-3.0:
- url: svn://svn.wowace.com/wow/libsharedmedia-3-0/mainline/trunk
- tag: latest
- libs/LibHealComm-4.0:
- url: git://git.wowace.com/wow/libhealcomm-4-0/mainline.git
- tag: latest
+ url: https://repos.wowace.com/wow/libsharedmedia-3-0/trunk/LibSharedMedia-3.0
+ libs/LibDualSpec-1.0:
+ url: https://repos.wowace.com/wow/libdualspec-1-0
+ libs/LibSpellRange-1.0:
+ url: 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: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConfig-3.0
+ url: https://repos.wowace.com/wow/ace3/trunk/AceConfig-3.0
options/libs/AceDBOptions-3.0:
- url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDBOptions-3.0
+ url: https://repos.wowace.com/wow/ace3/trunk/AceDBOptions-3.0
options/libs/AceGUI-3.0:
- url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceGUI-3.0
+ url: https://repos.wowace.com/wow/ace3/trunk/AceGUI-3.0
options/libs/AceGUI-3.0-SharedMediaWidgets:
- url: svn://svn.wowace.com/wow/ace-gui-3-0-shared-media-widgets/mainline/trunk
- tag: latest
-ignore:
- - globalcheck.lua
- - localcheck.lua
+ url: https://repos.wowace.com/wow/ace-gui-3-0-shared-media-widgets/trunk/AceGUI-3.0-SharedMediaWidgets
+ignore:
+ - locale-import.lua
diff --git a/ShadowedUnitFrames.lua b/ShadowedUnitFrames.lua
old mode 100644
new mode 100755
index d0db7dc1b..95e54b954
--- a/ShadowedUnitFrames.lua
+++ b/ShadowedUnitFrames.lua
@@ -1,28 +1,30 @@
---[[
- Shadowed Unit Frames, Shadow of Mal'Ganis (US) PvP
+--[[
+ Shadowed Unit Frames, Shadowed of Mal'Ganis (US) PvP
]]
ShadowUF = select(2, ...)
+
local L = ShadowUF.L
-ShadowUF.dbRevision = 1
+ShadowUF.dbRevision = 63
ShadowUF.playerUnit = "player"
ShadowUF.enabledUnits = {}
ShadowUF.modules = {}
ShadowUF.moduleOrder = {}
-ShadowUF.unitList = {"player", "pet", "pettarget", "target", "targettarget", "targettargettarget", "focus", "focustarget", "party", "partypet", "partytarget", "raid", "raidpet", "boss", "bosstarget", "maintank", "maintanktarget", "mainassist", "mainassisttarget", "arena", "arenatarget", "arenapet"}
-ShadowUF.fakeUnits = {["targettarget"] = true, ["targettargettarget"] = true, ["pettarget"] = true, ["arenatarget"] = true, ["focustarget"] = true, ["focustargettarget"] = true, ["partytarget"] = true, ["raidtarget"] = true, ["bosstarget"] = true, ["maintanktarget"] = true, ["mainassisttarget"] = true}
-L.units = {["raidpet"] = L["Raid pet"], ["PET"] = L["Pet"], ["VEHICLE"] = L["Vehicle"], ["arena"] = L["Arena"], ["arenapet"] = L["Arena Pet"], ["arenatarget"] = L["Arena Target"], ["boss"] = L["Boss"], ["bosstarget"] = L["Boss Target"], ["focus"] = L["Focus"], ["focustarget"] = L["Focus Target"], ["mainassist"] = L["Main Assist"], ["mainassisttarget"] = L["Main Assist Target"], ["maintank"] = L["Main Tank"], ["maintanktarget"] = L["Main Tank Target"], ["party"] = L["Party"], ["partypet"] = L["Party Pet"], ["partytarget"] = L["Party Target"], ["pet"] = L["Pet"], ["pettarget"] = L["Pet Target"], ["player"] = L["Player"],["raid"] = L["Raid"], ["target"] = L["Target"], ["targettarget"] = L["Target of Target"], ["targettargettarget"] = L["Target of Target of Target"]}
-
+ShadowUF.unitList = {"player", "pet", "pettarget", "target", "targettarget", "targettargettarget", "focus", "focustarget", "party", "partypet", "partytarget", "partytargettarget", "raid", "raidpet", "boss", "bosstarget", "maintank", "maintanktarget", "mainassist", "mainassisttarget", "arena", "arenatarget", "arenapet", "battleground", "battlegroundtarget", "battlegroundpet", "arenatargettarget", "battlegroundtargettarget", "maintanktargettarget", "mainassisttargettarget", "bosstargettarget"}
+ShadowUF.fakeUnits = {["targettarget"] = true, ["targettargettarget"] = true, ["pettarget"] = true, ["arenatarget"] = true, ["arenatargettarget"] = true, ["focustarget"] = true, ["focustargettarget"] = true, ["partytarget"] = true, ["raidtarget"] = true, ["bosstarget"] = true, ["maintanktarget"] = true, ["mainassisttarget"] = true, ["battlegroundtarget"] = true, ["partytargettarget"] = true, ["battlegroundtargettarget"] = true, ["maintanktargettarget"] = true, ["mainassisttargettarget"] = true, ["bosstargettarget"] = true}
+L.units = {["raidpet"] = L["Raid pet"], ["PET"] = L["Pet"], ["VEHICLE"] = L["Vehicle"], ["arena"] = L["Arena"], ["arenapet"] = L["Arena Pet"], ["arenatarget"] = L["Arena Target"], ["arenatargettarget"] = L["Arena Target of Target"], ["boss"] = L["Boss"], ["bosstarget"] = L["Boss Target"], ["focus"] = L["Focus"], ["focustarget"] = L["Focus Target"], ["mainassist"] = L["Main Assist"], ["mainassisttarget"] = L["Main Assist Target"], ["maintank"] = L["Main Tank"], ["maintanktarget"] = L["Main Tank Target"], ["party"] = L["Party"], ["partypet"] = L["Party Pet"], ["partytarget"] = L["Party Target"], ["pet"] = L["Pet"], ["pettarget"] = L["Pet Target"], ["player"] = L["Player"],["raid"] = L["Raid"], ["target"] = L["Target"], ["targettarget"] = L["Target of Target"], ["targettargettarget"] = L["Target of Target of Target"], ["battleground"] = L["Battleground"], ["battlegroundpet"] = L["Battleground Pet"], ["battlegroundtarget"] = L["Battleground Target"], ["partytargettarget"] = L["Party Target of Target"], ["battlegroundtargettarget"] = L["Battleground Target of Target"], ["maintanktargettarget"] = L["Main Tank Target of Target"], ["mainassisttargettarget"] = L["Main Assist Target of Target"], ["bosstargettarget"] = L["Boss Target of Target"]}
+L.shortUnits = {["battleground"] = L["BG"], ["battlegroundtarget"] = L["BG Target"], ["battlegroundpet"] = L["BG Pet"], ["battlegroundtargettarget"] = L["BG ToT"], ["arenatargettarget"] = L["Arena ToT"], ["partytargettarget"] = L["Party ToT"], ["bosstargettarget"] = L["Boss ToT"], ["maintanktargettarget"] = L["MT ToT"], ["mainassisttargettarget"] = L["MA ToT"]}
-- Cache the units so we don't have to concat every time it updates
ShadowUF.unitTarget = setmetatable({}, {__index = function(tbl, unit) rawset(tbl, unit, unit .. "target"); return unit .. "target" end})
-ShadowUF.partyUnits, ShadowUF.raidUnits, ShadowUF.raidPetUnits, ShadowUF.bossUnits, ShadowUF.arenaUnits = {}, {}, {}, {}, {}
+ShadowUF.partyUnits, ShadowUF.raidUnits, ShadowUF.raidPetUnits, ShadowUF.bossUnits, ShadowUF.arenaUnits, ShadowUF.battlegroundUnits = {}, {}, {}, {}, {}, {}
ShadowUF.maintankUnits, ShadowUF.mainassistUnits, ShadowUF.raidpetUnits = ShadowUF.raidUnits, ShadowUF.raidUnits, ShadowUF.raidPetUnits
for i=1, MAX_PARTY_MEMBERS do ShadowUF.partyUnits[i] = "party" .. i end
for i=1, MAX_RAID_MEMBERS do ShadowUF.raidUnits[i] = "raid" .. i end
for i=1, MAX_RAID_MEMBERS do ShadowUF.raidPetUnits[i] = "raidpet" .. i end
for i=1, MAX_BOSS_FRAMES do ShadowUF.bossUnits[i] = "boss" .. i end
for i=1, 5 do ShadowUF.arenaUnits[i] = "arena" .. i end
+for i=1, 4 do ShadowUF.battlegroundUnits[i] = "arena" .. i end
function ShadowUF:OnInitialize()
self.defaults = {
@@ -30,25 +32,27 @@ function ShadowUF:OnInitialize()
locked = false,
advanced = false,
tooltipCombat = false,
+ bossmodSpellRename = true,
omnicc = false,
+ blizzardcc = true,
tags = {},
units = {},
positions = {},
range = {},
- filters = {zonewhite = {}, zoneblack = {}, whitelists = {}, blacklists = {}},
- visibility = {arena = {}, pvp = {}, party = {}, raid = {}},
- hidden = {cast = false, runes = true, buffs = true, party = true, player = true, pet = true, target = true, focus = true, boss = true, arena = true},
+ filters = {zonewhite = {}, zoneblack = {}, zoneoverride = {}, whitelists = {}, blacklists = {}, overridelists = {}},
+ visibility = {arena = {}, pvp = {}, party = {}, raid = {}, neighborhood = {}},
+ 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)
@@ -56,109 +60,215 @@ function ShadowUF:OnInitialize()
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()
- -- June 19th
- if( not ShadowUF.db.profile.font.color ) then
- ShadowUF.db.profile.font.color = {r = 1, g = 1, b = 1, a = 1}
+ local revision = self.db.profile.revision or self.dbRevision
+ if (revision <= 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
- local indicators = ShadowUF.db.profile.units[unit].indicators
- if( indicators and indicators.class ) then
- indicators.class.anchorTo = "$parent"
- indicators.class.anchorPoint = "BL"
- indicators.class.x = 0
- indicators.class.y = 0
+ if( 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
-
- -- April 29th
- if( self.db.profile.filters.zones ) then
- for unit, filter in pairs(self.db.profile.filters.zones) do
- if( self.db.profile.filters.whitelists[filter] ) then
- self.db.profile.filters.zonewhite[unit] = filter
- else
- self.db.profile.filters.zoneblack[unit] = filter
+ 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
-
- -- February 16th
- if( not self.db.profile.units.raidpet.enabled and self.db.profile.units.raidpet.height == 0 and self.db.profile.units.raidpet.width == 0 and self.db.profile.positions.raidpet.anchorPoint == "" and self.db.profile.positions.raidpet.point == "" ) then
- self:LoadDefaultLayout(true)
- end
-
- self.db.profile.units.party.unitsPerColumn = self.db.profile.units.party.unitsPerColumn or 5
- self.db.profile.units.raid.groupsPerRow = self.db.profile.units.raid.groupsPerRow or 8
-
- local castName = {enabled = true, size = 0, anchorTo = "$parent", rank = true, anchorPoint = "CLI", x = 1, y = 0}
- local castTime = {enabled = true, size = 0, anchorTo = "$parent", anchorPoint = "CRI", x = -1, y = 0}
-
- for unit, config in pairs(self.db.profile.units) do
- config.portrait = config.portrait or {}
- config.portrait.type = config.portrait.type or "3D"
- config.portrait.fullBefore = config.portrait.fullBefore or 0
- config.portrait.fullAfter = config.portrait.fullAfter or 100
- config.portrait.order = config.portrait.order or 40
- config.portrait.height = config.portrait.height or 0.50
-
- config.highlight.size = config.highlight.size or 10
-
- config.castBar = config.castBar or {}
- config.castBar.icon = config.castBar.icon or "HIDE"
- config.castBar.height = config.castBar.height or 0.60
- config.castBar.order = config.castBar.order or 40
-
- config.castBar.name = config.castBar.name or {}
- config.castBar.time = config.castBar.time or {}
-
- for key, value in pairs(castName) do
- if( config.castBar.name[key] == nil ) then
- config.castBar.name[key] = value
- end
+
+ if( revision <= 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
-
- for key, value in pairs(castTime) do
- if( config.castBar.time[key] == nil ) then
- config.castBar.time[key] = value
+ end
+
+ if( revision <= 47 ) then
+ local config = self.db.profile.units
+ config.player.comboPoints = config.target.comboPoints
+ end
+
+ if( revision <= 46 ) then
+ local config = self.db.profile.units.arena
+ config.indicators.arenaSpec = {enabled = true, anchorPoint = "LC", size = 28, x = 0, y = 0, anchorTo = "$parent"}
+ config.indicators.lfdRole = {enabled = true, anchorPoint = "BR", size = 14, x = 3, y = 14, anchorTo = "$parent"}
+ end
+
+ if( revision <= 45 ) then
+ for unit, config in pairs(self.db.profile.units) do
+ if( config.auras ) then
+ for _, key in pairs({"buffs", "debuffs"}) do
+ local aura = config.auras[key]
+ aura.show = aura.show or {}
+ aura.show.player = true
+ aura.show.boss = true
+ aura.show.raid = true
+ aura.show.misc = true
+ end
end
end
end
end
-
+
+local function zoneEnabled(zone, zoneList)
+ if( type(zoneList) == "string" ) then
+ return zone == zoneList
+ end
+
+ for id, row in pairs(zoneList) do
+ if( zone == row ) then return true end
+ end
+
+ return false
+end
+
function ShadowUF:LoadUnits()
-- CanHearthAndResurrectFromArea() returns true for world pvp areas, according to BattlefieldFrame.lua
local instanceType = CanHearthAndResurrectFromArea() and "pvp" or select(2, IsInInstance())
-
+ if( instanceType == "scenario" ) then instanceType = "party" end
+ if( instanceType == "interior" ) then instanceType = "neighborhood" end
+
+ if( not instanceType ) then instanceType = "none" end
+
for _, type in pairs(self.unitList) do
local enabled = self.db.profile.units[type].enabled
- if( ShadowUF.Units.zoneUnits[type] and enabled ) then
- enabled = ShadowUF.Units.zoneUnits[type] == instanceType
+ if( ShadowUF.Units.zoneUnits[type] ) then
+ enabled = enabled and zoneEnabled(instanceType, ShadowUF.Units.zoneUnits[type])
elseif( instanceType ~= "none" ) then
if( self.db.profile.visibility[instanceType][type] == false ) then
enabled = false
@@ -166,9 +276,9 @@ function ShadowUF:LoadUnits()
enabled = true
end
end
-
+
self.enabledUnits[type] = enabled
-
+
if( enabled ) then
self.Units:InitializeFrame(type)
else
@@ -180,7 +290,7 @@ 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] = {
@@ -191,28 +301,33 @@ function ShadowUF:LoadUnitDefaults()
portrait = {enabled = false},
castBar = {enabled = false, name = {}, time = {}},
text = {
- {enabled = true, name = L["Left text"], text = "[name]", anchorPoint = "C", anchorTo = "$healthBar", size = 0},
- {enabled = true, name = L["Right text"], text = "[curmaxhp]", anchorPoint = "C", anchorTo = "$healthBar", size = 0},
- {enabled = true, name = L["Left text"], text = "[level] [race]", anchorPoint = "C", anchorTo = "$powerBar", size = 0},
- {enabled = true, name = L["Right text"], text = "[curmaxpp]", anchorPoint = "C", anchorTo = "$powerBar", size = 0},
- {enabled = true, name = L["Text"], text = "", anchorTo = "$emptyBar", anchorPoint = "C", size = 0, x = 0, y = 0},
+ {enabled = true, name = L["Left text"], text = "[name]", anchorPoint = "CLI", anchorTo = "$healthBar", width = 0.50, size = 0, x = 3, y = 0, default = true},
+ {enabled = true, name = L["Right text"], text = "[curmaxhp]", anchorPoint = "CRI", anchorTo = "$healthBar", width = 0.60, size = 0, x = -3, y = 0, default = true},
+ {enabled = true, name = L["Left text"], text = "[level] [race]", anchorPoint = "CLI", anchorTo = "$powerBar", width = 0.50, size = 0, x = 3, y = 0, default = true},
+ {enabled = true, name = L["Right text"], text = "[curmaxpp]", anchorPoint = "CRI", anchorTo = "$powerBar", width = 0.60, size = 0, x = -3, y = 0, default = true},
+ {enabled = true, name = L["Left text"], text = "", anchorTo = "$emptyBar", anchorPoint = "CLI", width = 0.50, size = 0, x = 3, y = 0, default = true},
+ {enabled = true, name = L["Right text"], text = "", anchorTo = "$emptyBar", anchorPoint = "CRI", width = 0.60, size = 0, x = -3, y = 0, default = true},
+ ['*'] = {enabled = true, text = "", anchorTo = "", anchorPoint = "C", size = 0, x = 0, y = 0},
},
- indicators = {raidTarget = {enabled = true, size = 0}},
+ indicators = {raidTarget = {enabled = true, size = 0}},
highlight = {},
+ auraIndicators = {enabled = false},
auras = {
- buffs = {enabled = false, perRow = 10, maxRows = 4, selfScale = 1.30, prioritize = true, enlargeSelf = false},
- debuffs = {enabled = false, perRow = 10, maxRows = 4, selfScale = 1.30, enlargeSelf = true},
+ buffs = {enabled = false, perRow = 10, maxRows = 4, selfScale = 1.30, prioritize = true, show = {player = true, boss = true, raid = true, misc = true}, enlarge = {}, timers = {ALL = true}},
+ debuffs = {enabled = false, perRow = 10, maxRows = 4, selfScale = 1.30, show = {player = true, boss = true, raid = true, misc = true}, enlarge = {SELF = true}, timers = {ALL = true}},
},
}
-
+
if( not self.fakeUnits[unit] ) then
self.defaults.profile.units[unit].combatText = {enabled = true, anchorTo = "$parent", anchorPoint = "C", x = 0, y = 0}
- if( unit ~= "arena" and unit ~= "arenapet" ) then
- self.defaults.profile.units[unit].incHeal = {enabled = false, cap = 1.30}
+ if( unit ~= "battleground" and unit ~= "battlegroundpet" and unit ~= "arena" and unit ~= "arenapet" and unit ~= "boss" ) then
+ self.defaults.profile.units[unit].incHeal = {enabled = true, cap = 1.20}
+ self.defaults.profile.units[unit].incAbsorb = {enabled = true, cap = 1.30}
+ self.defaults.profile.units[unit].healAbsorb = {enabled = true, cap = 1.30}
end
end
-
+
if( unit ~= "player" ) then
self.defaults.profile.units[unit].range = {enabled = false, oorAlpha = 0.80, inAlpha = 1.0}
@@ -220,21 +335,28 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units[unit].indicators.class = {enabled = false, size = 19}
end
end
-
- -- Want pvp/leader/ML enabled for these units
- if( unit == "player" or unit == "party" or unit == "target" or unit == "raid" or unit == "focus" ) then
+
+ if( unit == "player" or unit == "party" or unit == "target" or unit == "raid" or unit == "focus" or unit == "mainassist" or unit == "maintank" ) then
self.defaults.profile.units[unit].indicators.leader = {enabled = true, size = 0}
self.defaults.profile.units[unit].indicators.masterLoot = {enabled = true, size = 0}
self.defaults.profile.units[unit].indicators.pvp = {enabled = true, size = 0}
self.defaults.profile.units[unit].indicators.role = {enabled = true, size = 0}
self.defaults.profile.units[unit].indicators.status = {enabled = false, size = 19}
-
+ self.defaults.profile.units[unit].indicators.resurrect = {enabled = true}
+ 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
@@ -243,25 +365,40 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.player.runeBar = {enabled = false}
self.defaults.profile.units.player.totemBar = {enabled = false}
self.defaults.profile.units.player.druidBar = {enabled = false}
+ self.defaults.profile.units.player.priestBar = {enabled = true}
+ self.defaults.profile.units.player.shamanBar = {enabled = true}
self.defaults.profile.units.player.xpBar = {enabled = false}
- self.defaults.profile.units.player.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
+ self.defaults.profile.units.player.fader = {enabled = false}
+ self.defaults.profile.units.player.soulShards = {enabled = true, isBar = true}
+ self.defaults.profile.units.player.arcaneCharges = {enabled = true, isBar = true}
+ self.defaults.profile.units.player.staggerBar = {enabled = true}
+ self.defaults.profile.units.player.comboPoints = {enabled = true, isBar = true}
+ self.defaults.profile.units.player.holyPower = {enabled = true, isBar = true}
+ self.defaults.profile.units.player.chi = {enabled = true, isBar = true}
self.defaults.profile.units.player.indicators.lfdRole = {enabled = true, size = 0, x = 0, y = 0}
- -- PET
+ self.defaults.profile.units.player.auraPoints = {enabled = false, isBar = true}
+ 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.indicators.happiness = {enabled = true, size = 16, anchorPoint = "BR", anchorTo = "$parent", x = 2, y = -2}
self.defaults.profile.units.pet.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.pet.xpBar = {enabled = false}
- -- FOCUS
+ -- FOCUS
self.defaults.profile.units.focus.enabled = true
self.defaults.profile.units.focus.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.focus.indicators.lfdRole = {enabled = false, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.focus.indicators.questBoss = {enabled = true, size = 0, x = 0, y = 0}
-- FOCUSTARGET
self.defaults.profile.units.focustarget.enabled = true
self.defaults.profile.units.focustarget.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
-- TARGET
self.defaults.profile.units.target.enabled = true
- self.defaults.profile.units.target.comboPoints = {enabled = true, isBar = false, height = 0.40, order = 30, anchorTo = "$parent", anchorPoint = "BR", x = 0, y = 0}
self.defaults.profile.units.target.indicators.lfdRole = {enabled = false, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.target.indicators.questBoss = {enabled = true, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.target.comboPoints = {enabled = false, isBar = true}
-- TARGETTARGET/TARGETTARGETTARGET
self.defaults.profile.units.targettarget.enabled = true
self.defaults.profile.units.targettargettarget.enabled = true
@@ -272,6 +409,7 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.party.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.party.combatText.enabled = false
self.defaults.profile.units.party.indicators.lfdRole = {enabled = true, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.party.indicators.phase = {enabled = true, size = 0, x = 0, y = 0}
-- ARENA
self.defaults.profile.units.arena.enabled = false
self.defaults.profile.units.arena.attribPoint = "TOP"
@@ -279,6 +417,15 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.arena.auras.debuffs.maxRows = 1
self.defaults.profile.units.arena.auras.buffs.maxRows = 1
self.defaults.profile.units.arena.offset = 0
+ self.defaults.profile.units.arena.indicators.arenaSpec = {enabled = true, size = 0, x = 0, y = 0}
+ self.defaults.profile.units.arena.indicators.lfdRole = {enabled = true, size = 0, x = 0, y = 0}
+ -- BATTLEGROUND
+ self.defaults.profile.units.battleground.enabled = false
+ self.defaults.profile.units.battleground.attribPoint = "TOP"
+ self.defaults.profile.units.battleground.attribAnchorPoint = "LEFT"
+ self.defaults.profile.units.battleground.auras.debuffs.maxRows = 1
+ self.defaults.profile.units.battleground.auras.buffs.maxRows = 1
+ self.defaults.profile.units.battleground.offset = 0
-- BOSS
self.defaults.profile.units.boss.enabled = false
self.defaults.profile.units.boss.attribPoint = "TOP"
@@ -286,6 +433,7 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.boss.auras.debuffs.maxRows = 1
self.defaults.profile.units.boss.auras.buffs.maxRows = 1
self.defaults.profile.units.boss.offset = 0
+ self.defaults.profile.units.boss.altPowerBar.enabled = true
-- RAID
self.defaults.profile.units.raid.groupBy = "GROUP"
self.defaults.profile.units.raid.sortOrder = "ASC"
@@ -296,6 +444,7 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.raid.filters = {[1] = true, [2] = true, [3] = true, [4] = true, [5] = true, [6] = true, [7] = true, [8] = true}
self.defaults.profile.units.raid.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.raid.combatText.enabled = false
+ self.defaults.profile.units.raid.indicators.lfdRole = {enabled = true, size = 0, x = 0, y = 0}
-- RAID PET
self.defaults.profile.units.raidpet.groupBy = "GROUP"
self.defaults.profile.units.raidpet.sortOrder = "ASC"
@@ -307,6 +456,7 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.units.raidpet.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
self.defaults.profile.units.raidpet.combatText.enabled = false
-- MAINTANK
+ self.defaults.profile.units.maintank.roleFilter = "TANK"
self.defaults.profile.units.maintank.groupFilter = "MAINTANK"
self.defaults.profile.units.maintank.groupBy = "GROUP"
self.defaults.profile.units.maintank.sortOrder = "ASC"
@@ -332,13 +482,116 @@ function ShadowUF:LoadUnitDefaults()
self.defaults.profile.positions.partytarget.anchorTo = "$parent"
self.defaults.profile.positions.partytarget.anchorPoint = "RT"
self.defaults.profile.units.partytarget.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
+ -- PARTYTARGETTARGET
+ self.defaults.profile.positions.partytarget.anchorTo = "$parent"
+ self.defaults.profile.positions.partytarget.anchorPoint = "RT"
+ self.defaults.profile.units.partytarget.fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.60}
+
+ -- Aura indicators
+ self.defaults.profile.auraIndicators = {
+ disabled = {},
+ missing = {},
+ linked = {},
+ indicators = {
+ ["tl"] = {name = L["Top Left"], anchorPoint = "TLI", anchorTo = "$parent", height = 8, width = 8, alpha = 1.0, x = 4, y = -4, friendly = true, hostile = true},
+ ["tr"] = {name = L["Top Right"], anchorPoint = "TRI", anchorTo = "$parent", height = 8, width = 8, alpha = 1.0, x = -3, y = -3, friendly = true, hostile = true},
+ ["bl"] = {name = L["Bottom Left"], anchorPoint = "BLI", anchorTo = "$parent", height = 8, width = 8, alpha = 1.0, x = 4, y = 4, friendly = true, hostile = true},
+ ["br"] = {name = L["Bottom Right"], anchorPoint = "BRI", anchorTo = "$parent", height = 8, width = 8, alpha = 1.0, x = -4, y = -4, friendly = true, hostile = true},
+ ["c"] = {name = L["Center"], anchorPoint = "C", anchorTo = "$parent", height = 20, width = 20, alpha = 1.0, x = 0, y = 0, friendly = true, hostile = true},
+ },
+ filters = {
+ ["tl"] = {boss = {priority = 100}, curable = {priority = 100}},
+ ["tr"] = {boss = {priority = 100}, curable = {priority = 100}},
+ ["bl"] = {boss = {priority = 100}, curable = {priority = 100}},
+ ["br"] = {boss = {priority = 100}, curable = {priority = 100}},
+ ["c"] = {boss = {priority = 100}, curable = {priority = 100}},
+ },
+ auras = {
+ ["20707"] = [[{indicator = '', group = "Warlock", priority = 10, r = 0.42, g = 0.21, b = 0.65}]],
+ ["116849"] = [[{r=0.19607843137255, group="Monk", indicator="c", g=1, player=false, duration=true, b=0.3843137254902, alpha=1, priority=0, icon=true, iconTexture="Interface\\Icons\\ability_monk_chicocoon"}]],
+ ["155777"] = [[{r=0.57647058823529, group="Druid", indicator="tr", g=0.28235294117647, player=true, duration=true, b=0.6156862745098, priority=100, alpha=1, iconTexture="Interface\\Icons\\Spell_Nature_Rejuvenation"}]],
+ ["121176"] = [[{alpha=1, b=0, priority=0, r=0.062745098039216, group="PvP Flags", indicator="bl", g=1, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["19705"] = [[{r=0.80392156862745, group="Food", indicator="", g=0.76470588235294, missing=true, duration=true, priority=0, alpha=1, b=0.24313725490196}]],
+ ["53563"] = [[{r=0.64313725490196, group="Paladin", indicator="tr", g=0.24705882352941, player=true, alpha=1, b=0.73333333333333, priority=100, duration=false, iconTexture="Interface\\Icons\\Ability_Paladin_BeaconofLight"}]],
+ ["774"] = [[{r=0.57647058823529, group="Druid", indicator="tr", g=0.28235294117647, player=true, duration=true, b=0.6156862745098, priority=100, alpha=1, iconTexture="Interface\\Icons\\Spell_Nature_Rejuvenation"}]],
+ ["33206"] = [[{r=0, group="Priest", indicator="c", g=0, b=0, duration=true, priority=0, icon=true, iconTexture="Interface\\Icons\\Spell_Holy_PainSupression"}]],
+ ["6788"] = [[{b=0.29019607843137, group="Priest", indicator="tl", alpha=1, player=false, g=0.56862745098039, duration=true, r=0.83921568627451, priority=20, icon=false, iconTexture="Interface\\Icons\\Spell_Holy_AshesToAshes"}]],
+ ["33763"] = [[{r=0.23137254901961, group="Druid", indicator="tl", g=1, player=true, duration=true, alpha=1, priority=0, b=0.2, iconTexture="Interface\\Icons\\INV_Misc_Herb_Felblossom"}]],
+ ["139"] = [[{r=0.23921568627451, group="Priest", indicator="tr", g=1, player=true, alpha=1, duration=true, b=0.39607843137255, priority=10, icon=false, iconTexture="Interface\\Icons\\Spell_Holy_Renew"}]],
+ ["41635"] = [[{r=1, group="Priest", indicator="br", g=0.90196078431373, missing=false, player=true, duration=false, alpha=1, b=0, priority=50, icon=false, iconTexture="Interface\\Icons\\Spell_Holy_PrayerOfMendingtga"}]],
+ ["47788"] = [[{r=0, group="Priest", indicator="c", g=0, b=0, duration=true, priority=0, icon=true, iconTexture="Interface\\Icons\\Spell_Holy_GuardianSpirit"}]],
+ ["61295"] = [[{r=0.17647058823529, group="Shaman", indicator="tl", g=0.4, player=true, alpha=1, duration=true, b=1, priority=0, icon=false, iconTexture="Interface\\Icons\\spell_nature_riptide"}]],
+ ["17"] = [[{r=1, group="Priest", indicator="tl", g=0.41960784313725, player=true, alpha=1, duration=true, b=0.5843137254902, priority=0, icon=false, iconTexture="Interface\\Icons\\Spell_Holy_PowerWordShield"}]],
+ ["152118"] = [[{r=1, group="Priest", indicator="tl", g=0.41960784313725, player=true, alpha=1, duration=true, b=0.5843137254902, priority=0, icon=false, iconTexture="Interface\\Icons\\Ability_Priest_ClarityOfWill"}]],
+ ["23335"] = [[{r=0, group="PvP Flags", indicator="bl", g=0, duration=false, b=0, priority=0, icon=true, iconTexture="Interface\\Icons\\INV_BannerPVP_02"}]],
+ ["102342"] = [[{r=0, group="Druid", indicator="c", g=0, duration=true, b=0, priority=0, icon=true, iconTexture="Interface\\Icons\\spell_druid_ironbark"}]],
+ ["121177"] = [[{r=0.78039215686275, group="PvP Flags", indicator="bl", g=0.42352941176471, alpha=1, b=0, priority=0, icon=false, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["586"] = [[{r=0, group="Priest", indicator="", g=0.85882352941176, selfColor={alpha=1, b=1, g=0.93725490196078, r=0, }, alpha=1, priority=0, b=1, iconTexture="Interface\\Icons\\Spell_Magic_LesserInvisibilty"}]],
+ ["23333"] = [[{icon=true, b=0, priority=0, r=0, group="PvP Flags", indicator="bl", g=0, iconTexture="Interface\\Icons\\INV_BannerPVP_01"}]],
+ ["119611"] = [[{r=0.26274509803922, group="Monk", indicator="tl", g=0.76078431372549, player=true, duration=true, alpha=1, b=0.53725490196078, priority=0, icon=false, iconTexture="Interface\\Icons\\ability_monk_renewingmists"}]],
+ ["8936"] = [[{r=0.12156862745098, group="Druid", indicator="br", g=0.45882352941176, player=true, duration=true, b=0.12156862745098, priority=100, alpha=1, iconTexture="Interface\\Icons\\Spell_Nature_ResistNature"}]],
+ ["34976"] = [[{r=0, group="PvP Flags", indicator="bl", g=0, player=false, b=0, priority=0, icon=true, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["121164"] = [[{alpha=1, b=1, priority=0, r=0, group="PvP Flags", indicator="bl", g=0.003921568627451, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["48438"] = [[{r=0.55294117647059, group="Druid", indicator="31685", g=1, player=true, duration=true, b=0.3921568627451, priority=100, alpha=1, iconTexture="Interface\\Icons\\Ability_Druid_Flourish"}]],
+ ["1022"] = [[{r=0, group="Paladin", indicator="c", g=0, player=false, duration=true, b=0, priority=0, icon=true, iconTexture="Interface\\Icons\\Spell_Holy_SealOfProtection"}]],
+ ["121175"] = [[{r=1, group="PvP Flags", indicator="bl", g=0.24705882352941, b=0.90196078431373, alpha=1, priority=0, icon=false, iconTexture="Interface\\Icons\\INV_BannerPVP_03"}]],
+ ["64844"] = [[{r=0.67843137254902, group="Priest", indicator="31685", g=0.30588235294118, player=true, alpha=1, priority=0, b=0.14117647058824, iconTexture="Interface\\Icons\\Spell_Holy_DivineProvidence"}]],
+ ["124081"] = [[{r=0.51372549019608, group="Monk", indicator="br", g=1, player=true, duration=true, b=0.90588235294118, alpha=1, priority=100, icon=false, iconTexture="Interface\\Icons\\ability_monk_forcesphere"}]],
+ ["29166"] = [[{r=0, group="Druid", indicator="c", g=0, b=0, duration=true, priority=0, icon=true, iconTexture="Interface\\Icons\\Spell_Nature_Lightning"}]],
+ ["189895"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\INV_Enchant_VoidSphere\";}",
+ ["189627"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\achievement_zone_cataclysmgreen\";}",
+ ["181306"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Ability_Mage_LivingBomb\";}",
+ ["181753"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_felarakkoa_feldetonation_green\";}",
+ ["188929"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Ability_Hunter_MarkedForDeath\";}",
+ ["189032"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_malkorok_blightofyshaarj_green\";}",
+ ["182826"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Fire_FelFlameRing\";}",
+ ["181515"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_SeedOfDestruction\";}",
+ ["179219"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_felarakkoa_feldetonation_red\";}",
+ ["179864"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Arcane_PrismaticCloak\";}",
+ ["184124"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_AntiMagicShell\";}",
+ ["184450"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossfelorcs_necromancer_purple\";}",
+ ["186134"] = "{icon=true;b=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"tr\";g=0;iconTexture=\"Interface\\\\Icons\\\\spell_fel_elementaldevastation\";}",
+ ["185066"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossfelorcs_necromancer_red\";}",
+ ["183817"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Ability_Warlock_EverlastingAffliction\";}",
+ ["179978"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossgorefiend_touchofdoom\";}",
+ ["182280"] = "{icon=true;b=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";g=0;iconTexture=\"Interface\\\\Icons\\\\Ability_Hunter_MarkedForDeath\";}",
+ ["189031"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_malkorok_blightofyshaarj_yellow\";}",
+ ["186500"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"INTERFACE\\\\ICONS\\\\inv_misc_steelweaponchain\";}",
+ ["188666"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"INTERFACE\\\\ICONS\\\\ability_warlock_soulsiphon\";}",
+ ["186333"] = "{b=0;g=0;priority=1;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_DevouringPlague\";}",
+ ["186135"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"tr\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_AntiShadow\";}",
+ ["181275"] = "{icon=true;b=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";g=0;iconTexture=\"Interface\\\\Icons\\\\spell_warlock_summonterrorguard\";}",
+ ["181957"] = "{b=0;g=0;priority=2;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Frost_ArcticWinds\";}",
+ ["189030"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_malkorok_blightofyshaarj_red\";}",
+ ["182178"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_arakkoa_spinning_blade\";}",
+ ["189777"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"INTERFACE\\\\ICONS\\\\inv_misc_steelweaponchain\";}",
+ ["186407"] = "{r=0;indicator=\"c\";b=0;group=\"Hellfire Citadel\";priority=2;g=0;iconTexture=\"Interface\\\\Icons\\\\spell_fel_incinerate\";}",
+ ["180166"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"tr\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_ChillTouch\";}",
+ ["180079"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\inv_blacksmithdye_black\";}",
+ ["184449"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossfelorcs_necromancer_purple\";}",
+ ["185510"] = "{r=0;icon=true;indicator=\"tr\";b=0;group=\"Hellfire Citadel\";priority=1;g=0;iconTexture=\"INTERFACE\\\\ICONS\\\\inv_misc_steelweaponchain\";}",
+ ["185065"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossfelorcs_necromancer_orange\";}",
+ ["182769"] = "{r=0;icon=true;indicator=\"tr\";b=0;group=\"Hellfire Citadel\";priority=0;g=0;iconTexture=\"Interface\\\\Icons\\\\ability_fixated_state_purple\";}",
+ ["181508"] = "{b=0;group=\"Hellfire Citadel\";indicator=\"c\";g=0;alpha=1;r=0;priority=1;icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_SeedOfDestruction\";}",
+ ["181099"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_AuraOfDarkness\";}",
+ ["181307"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\Spell_Shadow_Requiem\";}",
+ ["183865"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_warlock_shadowfurytga\";}",
+ ["186961"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_warlock_moltencoregreen\";}",
+ ["182200"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_arakkoa_spinning_blade\";}",
+ ["181597"] = "{b=0;g=0;priority=0;r=0;group=\"Hellfire Citadel\";indicator=\"c\";icon=true;iconTexture=\"Interface\\\\Icons\\\\ability_bossmannoroth_mannorothsgaze\";}",
+ }
+ }
+
+ for classToken in pairs(RAID_CLASS_COLORS) do
+ self.defaults.profile.auraIndicators.disabled[classToken] = {}
+ end
end
-- Module APIs
-function ShadowUF:RegisterModule(module, key, name, isBar, class)
- -- December 16th
- if( module.OnDefaultsSet ) then
- DEFAULT_CHAT_FRAME:AddMessage(string.format("[WARNING!] You are running an outdated version of %s, you need to update it to the latest available for it to work with SUF.", name or key or "unknown"))
+function ShadowUF:RegisterModule(module, key, name, isBar, class, spec, level)
+ -- Prevent duplicate registration for deprecated plugin
+ if( key == "auraIndicators" and 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
@@ -348,7 +601,18 @@ function ShadowUF:RegisterModule(module, key, name, isBar, class)
module.moduleHasBar = isBar
module.moduleName = name
module.moduleClass = class
-
+ module.moduleLevel = level
+
+ if( type(spec) == "number" ) then
+ module.moduleSpec = {}
+ module.moduleSpec[spec] = true
+ elseif( type(spec) == "table" ) then
+ module.moduleSpec = {}
+ for _, id in pairs(spec) do
+ module.moduleSpec[id] = true
+ end
+ end
+
table.insert(self.moduleOrder, module)
end
@@ -370,28 +634,31 @@ local resetTimer
function ShadowUF:ProfileReset()
if( not resetTimer ) then
resetTimer = CreateFrame("Frame")
- resetTimer:SetScript("OnUpdate", function(self)
+ resetTimer:SetScript("OnUpdate", function(f)
ShadowUF:ProfilesChanged()
- self:Hide()
+ 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()
@@ -400,118 +667,233 @@ function ShadowUF:ProfilesChanged()
self.modules.movers:Update()
end
--- Stolen from haste
ShadowUF.noop = function() end
-function ShadowUF:HideBlizzardFrames()
- if( ShadowUF.db.profile.hidden.runes ) then
- RuneFrame.Show = self.noop
- RuneFrame:Hide()
+ShadowUF.hiddenFrame = CreateFrame("Frame")
+ShadowUF.hiddenFrame:Hide()
+
+local rehideFrame = function(self)
+ if( not InCombatLockdown() ) then
+ self:Hide()
end
-
- if( ShadowUF.db.profile.hidden.cast ) then
- CastingBarFrame:UnregisterAllEvents()
- PetCastingBarFrame:UnregisterAllEvents()
+end
+
+local function basicHideBlizzardFrames(...)
+ for i=1, select("#", ...) do
+ local frame = select(i, ...)
+ frame:UnregisterAllEvents()
+ frame:HookScript("OnShow", rehideFrame)
+ frame:Hide()
end
+end
- if( ShadowUF.db.profile.hidden.party ) then
- for i=1, MAX_PARTY_MEMBERS do
- local name = "PartyMemberFrame" .. i
- local frame = _G[name]
+local function hideBlizzardFrames(taint, ...)
+ for i=1, select("#", ...) do
+ local frame = select(i, ...)
+ UnregisterUnitWatch(frame)
+ frame:UnregisterAllEvents()
+ frame:Hide()
- frame:UnregisterAllEvents()
- frame.Show = self.noop
- frame:Hide()
+ if( frame.manabar ) then frame.manabar:UnregisterAllEvents() end
+ if( frame.healthbar ) then frame.healthbar:UnregisterAllEvents() end
+ if( frame.spellbar ) then frame.spellbar:UnregisterAllEvents() end
+ if( frame.powerBarAlt ) then frame.powerBarAlt:UnregisterAllEvents() end
- _G[name .. "HealthBar"]:UnregisterAllEvents()
- _G[name .. "ManaBar"]:UnregisterAllEvents()
+ if( taint ) then
+ frame.Show = ShadowUF.noop
+ else
+ frame:SetParent(ShadowUF.hiddenFrame)
+ frame:HookScript("OnShow", rehideFrame)
end
end
+end
- if( ShadowUF.db.profile.hidden.buffs ) then
- BuffFrame:UnregisterAllEvents()
- BuffFrame.Show = self.noop
- BuffFrame:Hide()
- ConsolidatedBuffs.Show = self.noop
- ConsolidatedBuffs:Hide()
- TemporaryEnchantFrame.Show = self.noop
- TemporaryEnchantFrame:Hide()
- end
-
- if( ShadowUF.db.profile.hidden.player ) then
- PlayerFrame:UnregisterAllEvents()
- PlayerFrame.Show = self.noop
- PlayerFrame:Hide()
-
- PlayerFrame:RegisterEvent('UNIT_ENTERING_VEHICLE')
- PlayerFrame:RegisterEvent('UNIT_ENTERED_VEHICLE')
- PlayerFrame:RegisterEvent('UNIT_EXITING_VEHICLE')
- PlayerFrame:RegisterEvent('UNIT_EXITED_VEHICLE')
-
- PlayerFrameHealthBar:UnregisterAllEvents()
- PlayerFrameManaBar:UnregisterAllEvents()
- end
-
- if( ShadowUF.db.profile.hidden.pet ) then
- PetFrame:UnregisterAllEvents()
- PetFrame.Show = self.noop
- PetFrame:Hide()
-
- PetFrameHealthBar:UnregisterAllEvents()
- PetFrameManaBar:UnregisterAllEvents()
- end
-
- if( ShadowUF.db.profile.hidden.target ) then
- TargetFrame:UnregisterAllEvents()
- TargetFrame.Show = self.noop
- TargetFrame:Hide()
-
- TargetFrameHealthBar:UnregisterAllEvents()
- TargetFrameManaBar:UnregisterAllEvents()
- TargetFrameSpellBar:UnregisterAllEvents()
-
- ComboFrame:UnregisterAllEvents()
- ComboFrame.Show = self.noop
- ComboFrame:Hide()
- end
-
- if( ShadowUF.db.profile.hidden.focus ) then
- FocusFrame:UnregisterAllEvents()
- FocusFrame.Show = self.noop
- FocusFrame:Hide()
-
- FocusFrameHealthBar:UnregisterAllEvents()
- FocusFrameManaBar:UnregisterAllEvents()
- FocusFrameSpellBar:UnregisterAllEvents()
- end
-
- if( ShadowUF.db.profile.hidden.boss ) then
- for i=1, MAX_BOSS_FRAMES do
- local name = "Boss" .. i .. "TargetFrame"
- local frame = _G[name]
+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
- frame:UnregisterAllEvents()
- frame.Show = self.noop
- frame:Hide()
+ CompactRaidFrameManager:Hide()
+ local shown = CompactRaidFrameManager_GetSetting("IsShown")
+ if( shown and shown ~= "0" ) then
+ CompactRaidFrameManager_SetSetting("IsShown", "0")
+ end
+ end
- _G[name .. "HealthBar"]:UnregisterAllEvents()
- _G[name .. "ManaBar"]:UnregisterAllEvents()
+ 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( ShadowUF.db.profile.hidden.arena ) then
- Arena_LoadUI = self.noop
+
+ 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
- -- Don't modify the raid menu because that will taint the MA/MT stuff and it'll break and that's bad
- for key, list in pairs(UnitPopupMenus) do
- if( key ~= "RAID" ) then
- for i=#(list), 1, -1 do
- if( list[i] == "SET_FOCUS" or list[i] == "CLEAR_FOCUS" or list[i] == "LOCK_FOCUS_FRAME" or list[i] == "UNLOCK_FOCUS_FRAME" ) then
- table.remove(list, i)
+ 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)
@@ -526,7 +908,7 @@ CONFIGMODE_CALLBACKS["Shadowed Unit Frames"] = function(mode)
elseif( mode == "OFF" ) then
ShadowUF.db.profile.locked = true
end
-
+
ShadowUF.modules.movers:Update()
end
@@ -538,7 +920,7 @@ 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)
@@ -546,25 +928,28 @@ SlashCmdList["SHADOWEDUF"] = function(msg)
return
end
end
-
+
ShadowUF:Print(string.format(L["Cannot find any profiles named \"%s\"."], profile))
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
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)
\ No newline at end of file
+end)
diff --git a/ShadowedUnitFrames.toc b/ShadowedUnitFrames.toc
index 718f941a9..47b73bd71 100755
--- a/ShadowedUnitFrames.toc
+++ b/ShadowedUnitFrames.toc
@@ -1,51 +1,85 @@
-## Interface: 30300
-## Title: Shadowed Unit Frames
-## Notes: An apple a day keeps the raptor away, or so they say
-## Author: Shadowed
-## Version: @project-version@
-## SavedVariables: ShadowedUFDB
-## OptionalDeps: Ace3, LibSharedMedia-3.0, LibHealComm-4.0, AceGUI-3.0-SharedMediaWidgets
-
-#@no-lib-strip@
-libs\LibStub\LibStub.lua
-libs\CallbackHandler-1.0\CallbackHandler-1.0\CallbackHandler-1.0.xml
-libs\LibSharedMedia-3.0\lib.xml
-libs\LibHealComm-4.0\LibHealComm-4.0.xml
-libs\AceDB-3.0\AceDB-3.0.xml
#@end-no-lib-strip@
-
-localization\enUS.lua
-localization\deDE.lua
-localization\esES.lua
-localization\esMX.lua
-localization\frFR.lua
-localization\koKR.lua
-localization\ruRU.lua
-localization\zhCN.lua
-localization\zhTW.lua
-
-ShadowedUnitFrames.lua
-modules\units.lua
-modules\layout.lua
-modules\movers.lua
-modules\defaultlayout.lua
-modules\highlight.lua
-modules\tags.lua
-modules\health.lua
-modules\power.lua
-modules\portrait.lua
-modules\indicators.lua
-modules\xp.lua
-modules\cast.lua
-modules\auras.lua
-modules\combattext.lua
-modules\totems.lua
-modules\runes.lua
-modules\fader.lua
-modules\combopoints.lua
-modules\incheal.lua
-modules\range.lua
-modules\empty.lua
+## Interface: 110207, 110205
+## 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: Unit Frames
+## Category-deDE: Einheitenfenster
+## Category-esES: Marcos de unidades
+## Category-esMX: Marcos de unidades
+## Category-frFR: Portraits d'unités
+## Category-itIT: Riquadri delle unità
+## Category-koKR: 개체창
+## Category-ptBR: Quadros de unidade
+## Category-ruRU: Рамки юнитов
+## Category-zhCN: 单位框体
+## Category-zhTW: 單位框架
+## Group: 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@
\ No newline at end of file
+#@end-do-not-package@
diff --git a/ShadowedUnitFrames.xml b/ShadowedUnitFrames.xml
new file mode 100644
index 000000000..01955443e
--- /dev/null
+++ b/ShadowedUnitFrames.xml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/globalcheck.lua b/globalcheck.lua
deleted file mode 100755
index 1936bc7b4..000000000
--- a/globalcheck.lua
+++ /dev/null
@@ -1,83 +0,0 @@
-local isOSX = os.getenv("MANPATH") and true or false
-local leaks = {}
-local results = ""
-local function output(msg)
- results = results .. "\r\n" .. msg
-end
-
-local function scanFile(path)
- output(io.popen(string.format("luac -l %s", path)):read("*all"))
-end
-
-local function scanFolder(path)
- local command
- if( isOSX ) then
- command = string.format("ls \"%s\"", (path or "./"))
- else
- command = string.format("dir /B \"%s\"", (path or ""))
- end
-
- for file in io.popen(command):lines() do
- local extension = string.match(file, "%.([%a%d]+)$")
- if( file ~= "" and not extension and file ~= "libs" ) then
- if( path ) then
- scanFolder(path .. "/" .. file)
- else
- scanFolder(file)
- end
- elseif( extension == "lua" and file ~= "localcheck.lua" and file ~= "globalcheck.lua" and not string.match(file, "^localization%.([a-zA-Z]+)%.lua") ) then
- if( path ) then
- scanFile(path .. "/" .. file)
- else
- scanFile(file)
- end
- end
- end
-end
-
-scanFolder()
-
-if( isOSX ) then
- io.popen("unlink luac.out")
-else
- io.popen("del luac.out")
-end
-
-local file = io.open("results.txt", "w")
-file:write(tostring(results))
-file:flush()
-file:close()
-
-
-local f = io.open("results.txt", "r")
-local data = f:read("*all")
-function lines(str)
- local t = {}
- local function helper(line) table.insert(t, line) return "" end
- helper((str:gsub("(.-)\r?\n", helper)))
- return t
-end
-
-local printFile
-for _, line in pairs(lines(data)) do
- if( string.match(line, "(.+) <(.+)>") ) then
- file = line
- printFile = nil
- end
-
- if( string.match(line, "SETGLOBAL") ) then
- if( not printFile ) then
- print(file)
- printFile = true
- end
-
- print(line)
- end
-end
-
-f:close()
-if( isOSX ) then
- io.popen("unlink results.txt")
-else
- io.popen("del results.txt")
-end
diff --git a/localcheck.lua b/locale-import.lua
old mode 100755
new mode 100644
similarity index 76%
rename from localcheck.lua
rename to locale-import.lua
index aa1603aca..ffba821e3
--- a/localcheck.lua
+++ b/locale-import.lua
@@ -1,5 +1,5 @@
--- If you want to hardcode toc or slug in and not enter it, do so here
-local ADDON_SLUG
+-- Need to hardcode the project id here
+local ADDON_PROJECT_ID = 19268
local TOC_FILE
-- Automatically identify the slug based on the .git or .svn configuration data, change the path if it's not in root, or set to false to disable
local AUTO_IDENTIFY_SLUG = "./"
@@ -10,20 +10,21 @@ local SITE_LOCATION = nil
-- Personally I keep the api key in another file and just have this reference that to get it
-- If you want to do this, create the file with CURSE_API_KEY = "" in it and set the path here
-- set this to nil and it will ask you for your API key
-local API_KEY_FILE = "../TestCode/api-key.lua"
+local API_KEY_FILE = "../../cf-api-key.lua"
-- Patterns that should not be scrapped, case-insensitive
-- Anything between the no-lib-strip is automatically ignored
local FILE_BLACKLIST = {"^localization", "^lib"}
--- 1 = English
-DEFAULT_LANGUAGE = "1"
+
+-- default language to import to
+local DEFAULT_LANGUAGE = "enUS"
-- Removes phrases that are not found through this
-DELETE_UNIMPORTED = true
+local DELETE_UNIMPORTED = true
-- No more modifying!
local OS_TYPE = os.getenv("HOME") and "linux" or "windows"
-- Mak sure we have LuaSockets
-local _, http = pcall(require, "socket.http")
+local _, http = pcall(require, "ssl.https")
local _, ltn = pcall(require, "ltn12")
if( not http ) then
print("Failed to find socket.http, did you install LuaSockets?")
@@ -31,6 +32,11 @@ elseif( not ltn ) then
print("Failed to find ltn12, did you install LuaSockets?")
end
+-- check project id is set
+if not ADDON_PROJECT_ID then
+ print("No project id specified, did you set it?")
+ return
+end
-- Figure out the API key
if( API_KEY_FILE ) then
@@ -40,14 +46,13 @@ if( API_KEY_FILE ) then
else
file:close()
dofile(API_KEY_FILE)
-
+
if( not CURSE_API_KEY ) then
print("You did not define CURSE_API_KEY in your key file, make sure it does not have local next to it.")
end
end
end
-
if( not CURSE_API_KEY ) then
while( not CURSE_API_KEY ) do
io.stdout:write("Enter API key: ")
@@ -59,23 +64,22 @@ end
-- Attempt to automatically identify the addon slug
if( AUTO_IDENTIFY_SLUG ) then
local git = io.open(AUTO_IDENTIFY_SLUG .. ".git/config")
- local svn = io.open(AUTO_IDENTIFY_SLUG .. ".svn/entries")
+ local svn = io.popen("svn info --show-item url " .. AUTO_IDENTIFY_SLUG)
if( git ) then
local contents = git:read("*all")
- git:close()
- SITE_LOCATION, ADDON_SLUG = string.match(contents, "git%.(.-)%.com:wow/(.-)/mainline%.git")
+ SITE_LOCATION = string.match(contents, "repos%.([^\n]-)%.com/wow/([^\n]-)")
elseif( svn ) then
local contents = svn:read("*all")
- svn:close()
-
- SITE_LOCATION, ADDON_SLUG = string.match(contents, "svn%.(.-)%.com/wow/(.-)/mainline")
+
+ SITE_LOCATION = string.match(contents, "repos%.([^\n]-)%.com/wow/([^\n]-)")
end
-
- if( not ADDON_SLUG ) then
- print("Failed to identify addon slug.")
- elseif( not SITE_LOCATION ) then
+
+ if( git ) then git:close() end
+ if( svn ) then svn:close() end
+
+ if( not SITE_LOCATION ) then
print("Failed to identify site location.")
end
end
@@ -88,17 +92,6 @@ if( not SITE_LOCATION ) then
end
end
--- Manually ask for it
-if( not ADDON_SLUG ) then
- while( not ADDON_SLUG ) do
- io.stdout:write("Enter slug: ")
- ADDON_SLUG = io.stdin:read("*line")
- ADDON_SLUG = ADDON_SLUG ~= "" and ADDON_SLUG or nil
- end
-end
-
-print(string.format("Using addon slug: %s", ADDON_SLUG))
-
-- Find the TOC now
if( AUTO_FIND_TOC ) then
local pipe = OS_TYPE == "windows" and io.popen(string.format("dir /B \"%s\"", AUTO_FIND_TOC)) or io.popen(string.format("ls -1 \"%s\"", AUTO_FIND_TOC))
@@ -142,14 +135,14 @@ local ignore
local localizedKeys = {}
for line in io.lines(TOC_FILE) do
line = string.gsub(line, "\r", "")
-
+
if( string.match(line, "#@no%-lib%-strip@") ) then
ignore = true
elseif( string.match(line, "#@end%-no%-lib%-strip@") ) then
ignore = nil
end
-
- if( not ignore and string.match(line, "%.lua") ) then
+
+ if( not ignore and string.match(line, "%.lua") and not string.match(line, "^%s*#")) then
-- Make sure it's a valid file
local blacklist
for _, check in pairs(FILE_BLACKLIST) do
@@ -158,22 +151,22 @@ for line in io.lines(TOC_FILE) do
break
end
end
-
+
-- File checks out, scrap everything
if( not blacklist ) then
-- Fix slashes
if( OS_TYPE == "linux" ) then
line = string.gsub(line, "\\", "/")
end
-
+
local keys = 0
local contents = io.open(line):read("*all")
-
+
for match in string.gmatch(contents, "L%[\"(.-)%\"]") do
if( not localizedKeys[match] ) then keys = keys + 1 end
localizedKeys[match] = true
end
-
+
print(string.format("%s (%d keys)", line, keys))
end
end
@@ -195,10 +188,8 @@ end
print(string.format("Found %d keys total", totalLocalizedKeys))
local addonData = {
- ["format"] = "lua_additive_table",
- ["language"] = DEFAULT_LANGUAGE,
- ["delete_unimported"] = DELETE_UNIMPORTED and "y" or "n",
- ["text"] = localization,
+ ["metadata"] = ("{ language: \"%s\", \"namespace\": \"\", \"missing-phrase-handling\": \"%s\" }"):format(DEFAULT_LANGUAGE, DELETE_UNIMPORTED and "DeletePhrase" or "DoNothing"),
+ ["localizations"] = localization,
}
-- Send it off
@@ -212,35 +203,24 @@ for key, data in pairs(addonData) do
body = string.format("%s%s\r\n", body, data)
end
-body = string.format("%s--%s\r\n", body, boundary)
+body = string.format("%s--%s--\r\n", body, boundary)
+
+local host = SITE_LOCATION == "curseforge" and "wow.curseforge.com" or "www.wowace.com"
http.request({
method = "POST",
- url = string.format("http://www.%s.com/addons/%s/localization/import/?api-key=%s", SITE_LOCATION, ADDON_SLUG, CURSE_API_KEY),
+ url = string.format("https://%s/api/projects/%s/localization/import", host, ADDON_PROJECT_ID),
sink = ltn12.sink.table(source),
source = ltn12.source.string(body),
headers = {
+ ["X-Api-Token"] = CURSE_API_KEY,
["Content-Type"] = string.format("multipart/form-data; boundary=\"%s\"", boundary),
["Content-Length"] = string.len(body),
},
})
local contents = table.concat(source, "\n")
-local errors = {}
-for line in string.gmatch(contents, "(.-)\n") do
- local msg = string.match(line, "(.-)
")
- if( msg ) then
- table.insert(errors, msg)
- end
-end
-
+print(contents)
print("")
-if( #(errors) == 0 ) then
- print(string.format("Updated localization for %s on %s!", ADDON_SLUG, SITE_LOCATION))
-else
- print("Localization failed:")
- for _, line in pairs(errors) do
- print(line)
- end
-end
+print(string.format("Updated localization on %s!", SITE_LOCATION))
diff --git a/localization/deDE.lua b/localization/deDE.lua
old mode 100644
new mode 100755
diff --git a/localization/enUS.lua b/localization/enUS.lua
old mode 100644
new mode 100755
diff --git a/localization/esES.lua b/localization/esES.lua
old mode 100644
new mode 100755
diff --git a/localization/esMX.lua b/localization/esMX.lua
old mode 100644
new mode 100755
diff --git a/localization/frFR.lua b/localization/frFR.lua
old mode 100644
new mode 100755
diff --git a/localization/koKR.lua b/localization/koKR.lua
old mode 100644
new mode 100755
diff --git a/localization/ptBR.lua b/localization/ptBR.lua
new file mode 100755
index 000000000..4a3353b48
--- /dev/null
+++ b/localization/ptBR.lua
@@ -0,0 +1,5 @@
+if( GetLocale() ~= "ptBR" ) then return end
+local L = {}
+--@localization(locale="ptBR", format="lua_additive_table", handle-unlocalized="ignore")@
+local ShadowUF = select(2, ...)
+ShadowUF.L = setmetatable(L, {__index = ShadowUF.L})
diff --git a/localization/ruRU.lua b/localization/ruRU.lua
old mode 100644
new mode 100755
diff --git a/localization/zhCN.lua b/localization/zhCN.lua
old mode 100644
new mode 100755
diff --git a/localization/zhTW.lua b/localization/zhTW.lua
old mode 100644
new mode 100755
diff --git a/media/fonts/Myriad Condensed Web.ttf b/media/fonts/Myriad Condensed Web.ttf
index ce9546b9c..dc23c18e3 100755
Binary files a/media/fonts/Myriad Condensed Web.ttf and b/media/fonts/Myriad Condensed Web.ttf differ
diff --git a/media/textures/Smoothv2.tga b/media/textures/Smoothv2.tga
new file mode 100644
index 000000000..dd5f0cf03
Binary files /dev/null and b/media/textures/Smoothv2.tga differ
diff --git a/media/textures/backdrop.tga b/media/textures/backdrop.tga
new file mode 100755
index 000000000..640e8c44d
Binary files /dev/null and b/media/textures/backdrop.tga differ
diff --git a/media/textures/shard.tga b/media/textures/shard.tga
new file mode 100755
index 000000000..2d459b50e
Binary files /dev/null and b/media/textures/shard.tga differ
diff --git a/media/textures/smooth.tga b/media/textures/smooth.tga
index 0201f3371..9ad81ad91 100755
Binary files a/media/textures/smooth.tga and b/media/textures/smooth.tga differ
diff --git a/media/textures/smoother.tga b/media/textures/smoother.tga
new file mode 100644
index 000000000..0201f3371
Binary files /dev/null and b/media/textures/smoother.tga differ
diff --git a/modules/altpower.lua b/modules/altpower.lua
new file mode 100755
index 000000000..c79c608bd
--- /dev/null
+++ b/modules/altpower.lua
@@ -0,0 +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
diff --git a/modules/arcanecharges.lua b/modules/arcanecharges.lua
new file mode 100644
index 000000000..8ff32cdc9
--- /dev/null
+++ b/modules/arcanecharges.lua
@@ -0,0 +1,31 @@
+if( not ShadowUF.ComboPoints ) then return end
+
+local ArcaneCharges = setmetatable({}, {__index = ShadowUF.ComboPoints})
+ShadowUF:RegisterModule(ArcaneCharges, "arcaneCharges", ShadowUF.L["Arcane Charges"], nil, "MAGE", SPEC_MAGE_ARCANE)
+local arcaneConfig = {max = 5, key = "arcaneCharges", colorKey = "ARCANECHARGES", powerType = Enum.PowerType.ArcaneCharges, eventType = "ARCANE_CHARGES", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"}
+
+function ArcaneCharges:OnEnable(frame)
+ frame.arcaneCharges = frame.arcaneCharges or CreateFrame("Frame", nil, frame)
+ frame.arcaneCharges.cpConfig = arcaneConfig
+ frame.comboPointType = arcaneConfig.key
+
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks")
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "Update")
+
+ frame:RegisterUpdateFunc(self, "Update")
+ frame:RegisterUpdateFunc(self, "UpdateBarBlocks")
+end
+
+function ArcaneCharges:OnLayoutApplied(frame, config)
+ ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config)
+ self:UpdateBarBlocks(frame)
+end
+
+function ArcaneCharges:GetComboPointType()
+ return "arcaneCharges"
+end
+
+function ArcaneCharges:GetPoints(unit)
+ return UnitPower("player", arcaneConfig.powerType)
+end
diff --git a/modules/auraindicators.lua b/modules/auraindicators.lua
new file mode 100755
index 000000000..251523eff
--- /dev/null
+++ b/modules/auraindicators.lua
@@ -0,0 +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
diff --git a/modules/aurapoints.lua b/modules/aurapoints.lua
new file mode 100755
index 000000000..fbda1df3e
--- /dev/null
+++ b/modules/aurapoints.lua
@@ -0,0 +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
diff --git a/modules/auras.lua b/modules/auras.lua
old mode 100644
new mode 100755
index 50e6415be..11eda167a
--- a/modules/auras.lua
+++ b/modules/auras.lua
@@ -1,13 +1,12 @@
local Auras = {}
-local stealableColor = {r = 1, g = 1, b = 1}
local playerUnits = {player = true, vehicle = true, pet = true}
-local mainHand, offHand = {time = 0}, {time = 0}
-local tempEnchantScan
+local mainHand, offHand, 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")
@@ -28,7 +27,7 @@ local function load(text)
error(err, 3)
return nil
end
-
+
return result()
end
@@ -39,7 +38,7 @@ local positionData = setmetatable({}, {
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
@@ -53,38 +52,39 @@ local positionData = setmetatable({}, {
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)
+ 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 position = positionData[group.forcedAnchorPoint or config.anchorPoint]
local button = group.buttons[id]
button.isAuraAnchor = nil
-
+
-- Alright, in order to find out where an aura group is going to be anchored to certain buttons need
- -- to be flagged as suitable anchors visually, this speeds it up bcause this data is cached and doesn't
+ -- to be flagged as suitable anchors visually, this speeds it up because this data is cached and doesn't
-- have to be recalculated unless auras are specifically changed
if( id > 1 ) then
if( position.isSideGrowth and id <= config.perRow ) then
button.isAuraAnchor = true
end
-
+
if( id % config.perRow == 1 or config.perRow == 1 ) then
position.column(button, group.buttons[id - config.perRow], 0)
@@ -101,7 +101,7 @@ local function positionButton(id, group, config)
button.xOffset = config.x + (position.xMod * ShadowUF.db.profile.backdrop.inset)
button.yOffset = config.y + (position.yMod * ShadowUF.db.profile.backdrop.inset)
button.anchorTo = group.anchorTo
-
+
position.initialAnchor(button, 0)
end
end
@@ -109,8 +109,8 @@ end
local columnsHaveScale = {}
local function positionAllButtons(group, config)
- local position = positionData[group.forcedAnchorPoint or config.anchorPoint]
-
+ local position = positionData[group.forcedAnchorPoint or config.anchorPoint]
+
-- Figure out which columns have scaling so we can work out positioning
local columnID = 0
for id, button in pairs(group.buttons) do
@@ -118,19 +118,19 @@ local function positionAllButtons(group, config)
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
- local columnID = 1
+ 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
@@ -154,22 +154,27 @@ local function positionAllButtons(group, config)
offset = offset + 1
end
- --print(columnID, math.ceil(offset))
position.column(button, anchorButton, math.ceil(offset))
else
position.aura(button, group.buttons[id - 1])
end
- -- If the initial column is self scaled, but the initial anchor isn't, will have to reposition it
- elseif( columnsHaveScale[columnID] ) then
- local offset = math.ceil(columnsHaveScale[columnID] / 8)
- if( button.isSelfScaled ) then
- offset = -(offset / 2)
- else
- offset = offset + 2
+ else
+ -- If the initial column is self scaled, but the initial anchor isn't, will have to reposition it
+ local offset = 0
+ if( columnsHaveScale[columnID] ) then
+ offset = math.ceil(columnsHaveScale[columnID] / 8)
+ if( button.isSelfScaled ) then
+ offset = -(offset / 2)
+ else
+ offset = offset + 2
+ end
+
+ offset = offset
+ end
+
+ if( offset ~= button.anchorOffset ) then
+ position.initialAnchor(button, offset)
end
-
- --print(1, offset)
- position.initialAnchor(button, offset)
end
end
end
@@ -177,13 +182,14 @@ end
-- Aura button functions
-- Updates the X seconds left on aura tooltip while it's shown
local function updateTooltip(self)
- if( GameTooltip:IsOwned(self) ) then
+ if( not GameTooltip:IsForbidden() and GameTooltip:IsOwned(self) ) then
GameTooltip:SetUnitAura(self.unit, self.auraID, self.filter)
end
end
local function showTooltip(self)
if( not ShadowUF.db.profile.locked ) then return end
+ if( GameTooltip:IsForbidden() ) then return end
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT")
if( self.filter == "TEMP" ) then
@@ -197,36 +203,37 @@ end
local function hideTooltip(self)
self:SetScript("OnUpdate", nil)
- GameTooltip:Hide()
+ if not GameTooltip:IsForbidden() then
+ GameTooltip:Hide()
+ end
end
-local function cancelBuff(self)
- if( not ShadowUF.db.profile.locked ) then return end
-
- if( self.filter == "TEMP" ) then
- CancelItemTempEnchantment(self.auraID - 15)
- else
- CancelUnitBuff(self.unit, self.auraID, self.filter)
+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:SetScript("OnClick", cancelBuff)
button:RegisterForClicks("RightButtonUp")
-
- button.cooldown = CreateFrame("Cooldown", nil, button)
+
+ button.cooldown = CreateFrame("Cooldown", group.parent:GetName() .. "Aura" .. group.type .. id .. "Cooldown", button, "CooldownFrameTemplate")
button.cooldown:SetAllPoints(button)
button.cooldown:SetReverse(true)
- button.cooldown:SetFrameLevel(7)
- button.cooldown:Hide()
-
+ button.cooldown:SetDrawEdge(false)
+ button.cooldown:SetDrawSwipe(true)
+ button.cooldown:SetSwipeColor(0, 0, 0, 0.8)
+ button.cooldown:Hide()
+
button.stack = button:CreateFontString(nil, "OVERLAY")
button.stack:SetFont("Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf", 10, "OUTLINE")
button.stack:SetShadowColor(0, 0, 0, 1.0)
@@ -238,13 +245,13 @@ local function updateButton(id, group, config)
button.stack:SetJustifyH("RIGHT")
button.border = button:CreateTexture(nil, "OVERLAY")
- button.border:SetPoint("CENTER", button)
-
+ button.border:SetPoint("CENTER", button)
+
button.icon = button:CreateTexture(nil, "BACKGROUND")
button.icon:SetAllPoints(button)
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
@@ -256,16 +263,21 @@ local function updateButton(id, group, config)
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
@@ -276,24 +288,24 @@ 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(5)
+ 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
@@ -302,19 +314,13 @@ local function updateGroup(self, type, config, reverseConfig)
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 ""
- -- This is a bit of an odd filter, when used with a HELPFUL filter, it will only return buffs you can cast on group members
- -- When used with HARMFUL it will only return debuffs you can cure
- if( config.raid ) then
- group.filter = group.filter .. "|RAID"
- end
-
for id, button in pairs(group.buttons) do
updateButton(id, group, config)
- end
+ end
end
-- Update aura positions based off of configuration
@@ -322,8 +328,8 @@ 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
+ button:Hide()
+ end
end
if( frame.auras.debuffs ) then
for _, button in pairs(frame.auras.debuffs.buttons) do
@@ -331,17 +337,17 @@ function Auras:OnLayoutApplied(frame, config)
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
@@ -353,7 +359,7 @@ function Auras:OnLayoutApplied(frame, config)
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"]
@@ -368,12 +374,13 @@ end
-- Temporary enchant support
local timeElapsed = 0
-local function updateTemporaryEnchant(frame, slot, tempData, hasEnchant, timeLeft, charges)
+local function updateTemporaryEnchant(frame, slot, tempData, hasEnchant, enchantId, timeLeft, charges)
-- If there's less than a 750 millisecond differences in the times, we don't need to bother updating.
-- Any sort of enchant takes more than 0.750 seconds to cast so it's impossible for the user to have two
-- temporary enchants with that little difference, as totems don't really give pulsing auras anymore.
- if( tempData.has and ( timeLeft < tempData.time and ( tempData.time - timeLeft ) < 750 ) and charges == tempData.charges ) then return false end
-
+ charges = charges or 0
+ if( tempData.has and tempData.enchantId == enchantId and ( timeLeft < tempData.time and ( tempData.time - timeLeft ) < 750 ) ) then return false end
+
-- Some trickys magic, we can't get the start time of temporary enchants easily.
-- So will save the first time we find when a new enchant is added
if( timeLeft > tempData.time or not tempData.has ) then
@@ -383,19 +390,20 @@ local function updateTemporaryEnchant(frame, slot, tempData, hasEnchant, timeLef
tempData.has = hasEnchant
tempData.time = timeLeft
tempData.charges = charges
-
+ tempData.enchantId = enchantId
+
local config = ShadowUF.db.profile.units[frame.parent.unitType].auras[frame.type]
-
+
-- Create any buttons we need
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)
@@ -403,7 +411,7 @@ local function updateTemporaryEnchant(frame, slot, tempData, hasEnchant, timeLef
end
-- Enlarge our own auras
- if( config.enlargeSelf and caster == ShadowUF.playerUnit ) then
+ if( config.enlarge.SELF ) then
button.isSelfScaled = true
button:SetScale(config.selfScale)
else
@@ -416,7 +424,7 @@ local function updateTemporaryEnchant(frame, slot, tempData, hasEnchant, timeLef
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"
@@ -430,29 +438,41 @@ 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, hasOff, offTimeLeft, offCharges = GetWeaponEnchantInfo()
+
+ local hasMain, mainTimeLeft, mainCharges, mainEnchantId, hasOff, offTimeLeft, offCharges, offEnchantId = GetWeaponEnchantInfo()
self.temporaryEnchants = 0
-
+
if( hasMain ) then
self.temporaryEnchants = self.temporaryEnchants + 1
- updateTemporaryEnchant(self, 16, mainHand, hasMain, mainTimeLeft or 0, mainCharges)
+ updateTemporaryEnchant(self, 16, mainHand, hasMain, mainEnchantId, mainTimeLeft or 0, mainCharges)
mainHand.time = mainTimeLeft or 0
end
mainHand.has = hasMain
-
+
if( hasOff and self.temporaryEnchants < self.maxAuras ) then
self.temporaryEnchants = self.temporaryEnchants + 1
- updateTemporaryEnchant(self, 17, offHand, hasOff, offTimeLeft or 0, offCharges)
+ updateTemporaryEnchant(self, 17, offHand, hasOff, offEnchantId, offTimeLeft or 0, offCharges)
offHand.time = offTimeLeft or 0
end
-
+
offHand.has = hasOff
-
+
-- Update if totals changed
if( self.lastTemporary ~= self.temporaryEnchants ) then
self.lastTemporary = self.temporaryEnchants
@@ -466,88 +486,130 @@ end
-- This isn't actually filled with data, it's just to stop any errors from triggering if no filter is added
local filterDefault = {}
function Auras:UpdateFilter(frame)
- local zone = select(2, IsInInstance())
+ local zone = select(2, IsInInstance()) or "none"
+ if( zone == "scenario" ) then zone = "party" end
+ if( zone == "interior" ) then zone = "neighborhood" 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, filter)
+local function scan(parent, frame, type, config, displayConfig, filter)
if( frame.totalAuras >= frame.maxAuras or not config.enabled ) then return end
- local isFriendly = UnitIsFriend(frame.parent.unit, "player")
+ -- 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, rank, texture, count, auraType, duration, endTime, caster, isStealable = 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
-
- if( ( not config.player or playerUnits[caster] ) and ( not parent.whitelist[type] and not parent.blacklist[type] or parent.whitelist[type] and parent.whitelist[name] or parent.blacklist[type] and not parent.blacklist[name] ) ) then
- -- Create any buttons we need
- frame.totalAuras = frame.totalAuras + 1
- if( #(frame.buttons) < frame.totalAuras ) then
- updateButton(frame.totalAuras, frame, ShadowUF.db.profile.units[frame.parent.unitType].auras[frame.type])
- end
-
- -- Show debuff border, or a special colored border if it's stealable
- local button = frame.buttons[frame.totalAuras]
- if( isStealable and not isFriendly and not ShadowUF.db.profile.auras.disableColor ) then
- button.border:SetVertexColor(stealableColor.r, stealableColor.g, stealableColor.b)
- elseif( ( not isFriendly or type == "debuffs" ) and not ShadowUF.db.profile.auras.disableColor ) then
- local color = auraType and DebuffTypeColor[auraType] or DebuffTypeColor.none
- button.border:SetVertexColor(color.r, color.g, color.b)
- else
- button.border:SetVertexColor(0.60, 0.60, 0.60)
- end
-
- -- Show the cooldown ring
- if( not ShadowUF.db.profile.auras.disableCooldown and duration > 0 and endTime > 0 and ( not config.selfTimers or ( config.selfTimers and playerUnits[caster] ) ) ) then
- button.cooldown:SetCooldown(endTime - duration, duration)
- button.cooldown:Show()
- else
- button.cooldown:Hide()
- end
-
- -- Enlarge our own auras
- if( config.enlargeSelf and playerUnits[caster] ) 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()
-
- -- Too many auras shown break out
- -- Get down
- if( frame.totalAuras >= frame.maxAuras ) then break end
- 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.enlargeSelf ) then
- positionAllButtons(frame, config)
+ if( config.selfScale > 1.30 ) then
+ positionAllButtons(frame, displayConfig)
end
end
@@ -561,10 +623,10 @@ local function anchorGroupToGroup(frame, config, group, childConfig, childGroup)
if( group.totalAuras == 0 ) then
local position = positionData[config.anchorPoint]
childGroup.buttons[1]:ClearAllPoints()
- childGroup.buttons[1]:SetPoint(ShadowUF.Layout:GetPoint(config.anchorPoint), group.anchorTo, ShadowUF.Layout:GetRelative(config.anchorPoint), config.x + (position.xMod * ShadowUF.db.profile.backdrop.inset), config.y + (position.yMod * -ShadowUF.db.profile.backdrop.inset))
+ childGroup.buttons[1]:SetPoint(ShadowUF.Layout:GetPoint(config.anchorPoint), group.anchorTo, ShadowUF.Layout:GetRelative(config.anchorPoint), config.x + (position.xMod * ShadowUF.db.profile.backdrop.inset), config.y + (position.yMod * ShadowUF.db.profile.backdrop.inset))
return
end
-
+
local anchorTo
for i=#(group.buttons), 1, -1 do
local button = group.buttons[i]
@@ -574,7 +636,7 @@ local function anchorGroupToGroup(frame, config, group, childConfig, childGroup)
end
end
- local position = positionData[childGroup.forcedAnchorPoint or childConfig.anchorPoint]
+ local position = positionData[childGroup.forcedAnchorPoint or childConfig.anchorPoint]
if( position.isSideGrowth ) then
position.aura(childGroup.buttons[1], anchorTo)
else
@@ -589,20 +651,20 @@ 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], frame.auras[frame.auras.primary].filter)
- scan(frame.auras, frame.auras.anchor, frame.auras.secondary, config[frame.auras.secondary], frame.auras[frame.auras.secondary].filter)
+
+ scan(frame.auras, frame.auras.anchor, frame.auras.primary, config[frame.auras.primary], config[frame.auras.primary], frame.auras[frame.auras.primary].filter)
+ scan(frame.auras, frame.auras.anchor, frame.auras.secondary, config[frame.auras.secondary], config[frame.auras.primary], frame.auras[frame.auras.secondary].filter)
else
if( config.buffs.enabled ) then
frame.auras.buffs.totalAuras = frame.auras.buffs.temporaryEnchants
- scan(frame.auras, frame.auras.buffs, "buffs", config.buffs, frame.auras.buffs.filter)
+ scan(frame.auras, frame.auras.buffs, "buffs", config.buffs, config.buffs, frame.auras.buffs.filter)
end
if( config.debuffs.enabled ) then
frame.auras.debuffs.totalAuras = 0
- scan(frame.auras, frame.auras.debuffs, "debuffs", config.debuffs, frame.auras.debuffs.filter)
+ scan(frame.auras, frame.auras.debuffs, "debuffs", config.debuffs, config.debuffs, frame.auras.debuffs.filter)
end
-
+
if( frame.auras.anchorAurasOn ) then
anchorGroupToGroup(frame, config[frame.auras.anchorAurasOn.type], frame.auras.anchorAurasOn, config[frame.auras.anchorAurasChild.type], frame.auras.anchorAurasChild)
end
diff --git a/modules/basecombopoints.lua b/modules/basecombopoints.lua
new file mode 100644
index 000000000..b612ee745
--- /dev/null
+++ b/modules/basecombopoints.lua
@@ -0,0 +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
diff --git a/modules/cast.lua b/modules/cast.lua
index 92457eaaa..56ee5c1fa 100755
--- a/modules/cast.lua
+++ b/modules/cast.lua
@@ -1,45 +1,41 @@
local Cast = {}
local L = ShadowUF.L
local FADE_TIME = 0.30
-local FAKE_UPDATE_TIME = 0.10
ShadowUF:RegisterModule(Cast, "castBar", L["Cast bar"], true)
-- I'm not really thrilled with this method of detecting fake unit casts, mostly because it's inefficient and ugly
-local function monitorFakeCast(self, elapsed)
- self.timeElapsed = self.timeElapsed + elapsed
- if( self.timeElapsed <= FAKE_UPDATE_TIME ) then return end
- self.timeElapsed = self.timeElapsed - FAKE_UPDATE_TIME
-
- local spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitCastingInfo(self.parent.unit)
+local function monitorFakeCast(self)
+ local spell, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(self.parent.unit)
local isChannelled
if( not spell ) then
- spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitChannelInfo(self.parent.unit)
+ spell, displayName, icon, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(self.parent.unit)
isChannelled = true
end
-
+
-- Cast started
if( not self.endTime and endTime ) then
self.endTime = endTime
self.notInterruptible = notInterruptible
self.spellName = spell
- Cast:UpdateCast(self.parent, self.parent.unit, isChannelled, spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible)
+ self.spellID = spellID
+ Cast:UpdateCast(self.parent, self.parent.unit, isChannelled, spell, displayName, icon, startTime, endTime, isTradeSkill, notInterruptible, spellID, castID)
-- Cast stopped
elseif( self.endTime and not endTime ) then
if( GetTime() <= (self.endTime / 1000) ) then
- Cast:EventInterruptCast(self.parent, nil, self.parent.unit, self.spellName)
+ Cast:EventInterruptCast(self.parent, nil, self.parent.unit, nil, self.spellID)
end
-
+
self.notInterruptible = nil
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, rank, displayName, icon, startTime, endTime)
+ Cast:UpdateDelay(self.parent, spell, displayName, icon, startTime, endTime)
end
-- Cast interruptible status changed
@@ -53,12 +49,18 @@ local function monitorFakeCast(self, elapsed)
end
end
-local function updateFakeUnitCast(self)
- self.endTime = nil
- self.notInterruptible = nil
- self.spellName = nil
-
- monitorFakeCast(self, FAKE_UPDATE_TIME)
+local function createFakeCastMonitor(frame)
+ if( not frame.castBar.monitor ) then
+ frame.castBar.monitor = C_Timer.NewTicker(0.10, monitorFakeCast)
+ frame.castBar.monitor.parent = frame
+ end
+end
+
+local function cancelFakeCastMonitor(frame)
+ if( frame.castBar and frame.castBar.monitor ) then
+ frame.castBar.monitor:Cancel()
+ frame.castBar.monitor = nil
+ end
end
function Cast:OnEnable(frame)
@@ -67,56 +69,57 @@ function Cast:OnEnable(frame)
frame.castBar.bar = ShadowUF.Units:CreateBar(frame)
frame.castBar.background = frame.castBar.bar.background
frame.castBar.bar.parent = frame
-
+ frame.castBar.bar.background = frame.castBar.background
+
frame.castBar.icon = frame.castBar.bar:CreateTexture(nil, "ARTWORK")
frame.castBar.bar.name = frame.castBar.bar:CreateFontString(nil, "ARTWORK")
frame.castBar.bar.time = frame.castBar.bar:CreateFontString(nil, "ARTWORK")
end
-
+
if( ShadowUF.fakeUnits[frame.unitType] ) then
- frame.castBar.monitor = frame.castBar.monitor or CreateFrame("Frame", nil, frame)
- frame.castBar.monitor.timeElapsed = 0
- frame.castBar.monitor.parent = frame
- frame.castBar.monitor:SetScript("OnUpdate", monitorFakeCast)
- frame.castBar.monitor:SetScript("OnShow", updateFakeUnitCast)
- frame.castBar.monitor:Show()
+ createFakeCastMonitor(frame)
+ frame:RegisterUpdateFunc(self, "UpdateFakeCast")
return
end
-
+
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_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())
@@ -138,7 +141,7 @@ function Cast:OnLayoutApplied(frame, config)
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
@@ -150,7 +153,7 @@ function Cast:OnLayoutApplied(frame, config)
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)
@@ -161,10 +164,10 @@ function Cast:OnLayoutApplied(frame, config)
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
@@ -174,7 +177,8 @@ function Cast:OnDisable(frame, unit)
frame:UnregisterAll(self)
if( frame.castBar ) then
- if( frame.castBar.monitor ) then frame.castBar.monitor:Hide() end
+ cancelFakeCastMonitor(frame)
+
frame.castBar.bar.name:Hide()
frame.castBar.bar.time:Hide()
frame.castBar.bar:Hide()
@@ -183,23 +187,19 @@ end
-- Easy coloring
local function setBarColor(self, r, g, b)
- self:SetStatusBarColor(r, g, b, ShadowUF.db.profile.bars.alpha)
-
- if( not self.background.overrideColor ) then
- self.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
+ self.parent:SetBlockColor(self, "castBar", r, g, b)
end
-- Cast OnUpdates
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)
@@ -217,11 +217,11 @@ local function castOnUpdate(self, elapsed)
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
@@ -277,16 +277,18 @@ end
function Cast:UpdateCurrentCast(frame)
if( UnitCastingInfo(frame.unit) ) then
- self:UpdateCast(frame, frame.unit, false, UnitCastingInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(frame.unit)
+ self:UpdateCast(frame, frame.unit, false, name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID, castID)
elseif( UnitChannelInfo(frame.unit) ) then
- self:UpdateCast(frame, frame.unit, true, UnitChannelInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(frame.unit)
+ self:UpdateCast(frame, frame.unit, true, name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID)
else
if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then
ShadowUF.Layout:SetBarVisibility(frame, "castBar", false)
end
setBarColor(frame.castBar.bar, 0, 0, 0)
-
+
frame.castBar.bar.spellName = nil
frame.castBar.bar.name:Hide()
frame.castBar.bar.time:Hide()
@@ -296,36 +298,43 @@ end
-- Cast updated/changed
function Cast:EventUpdateCast(frame)
- self:UpdateCast(frame, frame.unit, false, UnitCastingInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(frame.unit)
+ self:UpdateCast(frame, frame.unit, false, name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID, castID)
end
function Cast:EventDelayCast(frame)
- self:UpdateDelay(frame, UnitCastingInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(frame.unit)
+ self:UpdateDelay(frame, name, text, texture, startTime, endTime)
end
-- Channel updated/changed
function Cast:EventUpdateChannel(frame)
- self:UpdateCast(frame, frame.unit, true, UnitChannelInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(frame.unit)
+ self:UpdateCast(frame, frame.unit, true, name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID)
end
function Cast:EventDelayChannel(frame)
- self:UpdateDelay(frame, UnitChannelInfo(frame.unit))
+ local name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(frame.unit)
+ self:UpdateDelay(frame, name, text, texture, startTime, endTime)
end
-- Cast finished
-function Cast:EventStopCast(frame, event, unit, spell)
+function Cast:EventStopCast(frame, event, unit, castID, spellID)
local cast = frame.castBar.bar
- if( cast.spellName ~= spell or ( event == "UNIT_SPELLCAST_FAILED" and cast.isChannelled ) ) then return end
+ if( event == "UNIT_SPELLCAST_CHANNEL_STOP" and not castID ) then castID = spellID end
+ if( cast.castID ~= castID or ( event == "UNIT_SPELLCAST_FAILED" and cast.isChannelled ) ) then return end
if( cast.time.enabled ) then
cast.time:SetText("0.0")
end
- setBarColor(cast, ShadowUF.db.profile.castColors.interrupted.r, ShadowUF.db.profile.castColors.interrupted.g, ShadowUF.db.profile.castColors.interrupted.b)
+ --setBarColor(cast, ShadowUF.db.profile.castColors.interrupted.r, ShadowUF.db.profile.castColors.interrupted.g, ShadowUF.db.profile.castColors.interrupted.b)
if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then
ShadowUF.Layout:SetBarVisibility(frame, "castBar", true)
end
cast.spellName = nil
+ cast.spellID = nil
+ cast.castID = nil
cast.fadeElapsed = FADE_TIME
cast.fadeStart = FADE_TIME
cast:SetScript("OnUpdate", fadeOnUpdate)
@@ -335,10 +344,10 @@ function Cast:EventStopCast(frame, event, unit, spell)
end
-- Cast interrupted
-function Cast:EventInterruptCast(frame, event, unit, spell)
+function Cast:EventInterruptCast(frame, event, unit, castID, spellID)
local cast = frame.castBar.bar
- if( cast.spellName ~= spell ) then return end
-
+ if( castID and cast.castID ~= castID ) then return end
+
setBarColor(cast, ShadowUF.db.profile.castColors.interrupted.r, ShadowUF.db.profile.castColors.interrupted.g, ShadowUF.db.profile.castColors.interrupted.b)
if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then
ShadowUF.Layout:SetBarVisibility(frame, "castBar", true)
@@ -348,7 +357,7 @@ function Cast:EventInterruptCast(frame, event, unit, spell)
cast.name:SetText(L["Interrupted"])
end
- cast.spellName = nil
+ cast.spellID = nil
cast.fadeElapsed = FADE_TIME + 0.20
cast.fadeStart = cast.fadeElapsed
cast:SetScript("OnUpdate", fadeOnUpdate)
@@ -358,9 +367,9 @@ function Cast:EventInterruptCast(frame, event, unit, spell)
end
-- Cast succeeded
-function Cast:EventCastSucceeded(frame, unit, spell)
+function Cast:EventCastSucceeded(frame, event, unit, castID, spellID)
local cast = frame.castBar.bar
- if( not cast.isChannelled and cast.spellName == spell ) then
+ if( not cast.isChannelled and cast.castID == castID ) then
setBarColor(cast, ShadowUF.db.profile.castColors.finished.r, ShadowUF.db.profile.castColors.finished.g, ShadowUF.db.profile.castColors.finished.b)
end
end
@@ -379,12 +388,12 @@ function Cast:EventUninterruptible(frame)
setBarColor(frame.castBar.bar, ShadowUF.db.profile.castColors.uninterruptible.r, ShadowUF.db.profile.castColors.uninterruptible.g, ShadowUF.db.profile.castColors.uninterruptible.b)
end
-function Cast:UpdateDelay(frame, spell, rank, displayName, icon, startTime, endTime)
+function Cast:UpdateDelay(frame, spell, displayName, icon, startTime, endTime)
if( not spell or not frame.castBar.bar.startTime ) then return end
local cast = frame.castBar.bar
startTime = startTime / 1000
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
@@ -401,7 +410,7 @@ function Cast:UpdateDelay(frame, spell, rank, displayName, icon, startTime, endT
end
-- Update the actual bar
-function Cast:UpdateCast(frame, unit, channelled, spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible)
+function Cast:UpdateCast(frame, unit, channelled, spell, displayName, icon, startTime, endTime, isTradeSkill, notInterruptible, spellID, castID)
if( not spell ) then return end
local cast = frame.castBar.bar
if( ShadowUF.db.profile.units[frame.unitType].castBar.autoHide ) then
@@ -410,29 +419,28 @@ function Cast:UpdateCast(frame, unit, channelled, spell, rank, displayName, icon
-- Set casted spell
if( ShadowUF.db.profile.units[frame.unitType].castBar.name.enabled ) then
- if( ShadowUF.db.profile.units[frame.unitType].castBar.name.rank and rank and rank ~= "" ) then
- cast.name:SetFormattedText("%s (%s)", spell, rank)
- cast.name:SetAlpha(ShadowUF.db.profile.bars.alpha)
- cast.name:Show()
- else
- cast.name:SetText(spell)
- cast.name:SetAlpha(ShadowUF.db.profile.bars.alpha)
- cast.name:Show()
- end
+ cast.name:SetText(spell)
+ cast.name:SetAlpha(ShadowUF.db.profile.bars.alpha)
+ cast.name:Show()
end
-
+
-- Show cast time
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
@@ -440,20 +448,21 @@ function Cast:UpdateCast(frame, unit, channelled, spell, rank, displayName, icon
cast.endSeconds = cast.endTime - cast.startTime
cast.elapsed = cast.isChannelled and cast.endSeconds or 0
cast.spellName = spell
- cast.spellRank = rank
+ cast.spellID = spellID
+ cast.castID = channelled and spellID or castID
cast.pushback = 0
cast.lastUpdate = cast.startTime
cast:SetMinMaxValues(0, cast.endSeconds)
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
@@ -462,3 +471,13 @@ function Cast:UpdateCast(frame, unit, channelled, spell, rank, displayName, icon
setBarColor(cast, ShadowUF.db.profile.castColors.cast.r, ShadowUF.db.profile.castColors.cast.g, ShadowUF.db.profile.castColors.cast.b)
end
end
+
+-- Trigger checks on fake cast
+function Cast:UpdateFakeCast(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
new file mode 100755
index 000000000..b32f0b948
--- /dev/null
+++ b/modules/chi.lua
@@ -0,0 +1,28 @@
+if( not ShadowUF.ComboPoints ) then return end
+
+local Chi = setmetatable({}, {__index = ShadowUF.ComboPoints})
+ShadowUF:RegisterModule(Chi, "chi", ShadowUF.L["Chi"], nil, "MONK", SPEC_MONK_WINDWALKER)
+local chiConfig = {max = 5, key = "chi", colorKey = "CHI", powerType = Enum.PowerType.Chi, eventType = "CHI", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"}
+
+function Chi:OnEnable(frame)
+ frame.chi = frame.chi or CreateFrame("Frame", nil, frame)
+ frame.chi.cpConfig = chiConfig
+
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks")
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "Update")
+ frame:RegisterUpdateFunc(self, "Update")
+end
+
+function Chi:OnLayoutApplied(frame, config)
+ ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config)
+ self:UpdateBarBlocks(frame)
+end
+
+function Chi:GetComboPointType()
+ return "chi"
+end
+
+function Chi:GetPoints(unit)
+ return UnitPower("player", chiConfig.powerType)
+end
diff --git a/modules/combattext.lua b/modules/combattext.lua
index 828c66856..2f8b89a26 100755
--- a/modules/combattext.lua
+++ b/modules/combattext.lua
@@ -8,13 +8,13 @@ function Combat:OnEnable(frame)
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
@@ -24,7 +24,7 @@ function Combat:OnLayoutApplied(frame, config)
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
@@ -39,8 +39,11 @@ function Combat:Update(frame, event, unit, 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
- frame.combatText:SetScale(frame.combatText.feedbackText:GetStringHeight() / ShadowUF.db.profile.font.size)
- frame.combatText.feedbackText:SetFont(frame.combatText.fontPath, ShadowUF.db.profile.font.size, "OUTLINE")
+ local scale = frame.combatText.feedbackText:GetStringHeight() / ShadowUF.db.profile.font.size
+ if( scale > 0 ) then
+ frame.combatText:SetScale(scale)
+ frame.combatText.feedbackText:SetFont(frame.combatText.fontPath, ShadowUF.db.profile.font.size, "OUTLINE")
+ end
end
diff --git a/modules/combopoints.lua b/modules/combopoints.lua
index 3b4a31c0e..a68a74153 100755
--- a/modules/combopoints.lua
+++ b/modules/combopoints.lua
@@ -1,128 +1,42 @@
-local Combo = {}
+if( not ShadowUF.ComboPoints ) then return end
+
+local Combo = setmetatable({}, {__index = ShadowUF.ComboPoints})
ShadowUF:RegisterModule(Combo, "comboPoints", ShadowUF.L["Combo points"])
+local cpConfig = {max = MAX_COMBO_POINTS, key = "comboPoints", colorKey = "COMBOPOINTS", powerType = 4, eventType = "COMBO_POINTS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo"}
function Combo:OnEnable(frame)
frame.comboPoints = frame.comboPoints or CreateFrame("Frame", nil, frame)
- frame:RegisterNormalEvent("UNIT_COMBO_POINTS", self, "Update")
+ frame.comboPoints.cpConfig = cpConfig
+ cpConfig.max = UnitPowerMax("player", cpConfig.powerType)
+
+ frame:RegisterNormalEvent("UNIT_POWER_UPDATE", self, "Update", "player")
+ frame:RegisterNormalEvent("UNIT_POWER_FREQUENT", self, "Update", "player")
+ frame:RegisterNormalEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks", "player")
+
frame:RegisterUpdateFunc(self, "Update")
+ frame:RegisterUpdateFunc(self, "UpdateBarBlocks")
end
-function Combo:OnLayoutApplied(frame, config)
- -- Not a bar so set the containers frame configuration
- if( config.comboPoints and not config.comboPoints.isBar ) then
- ShadowUF.Layout:ToggleVisibility(frame.comboPoints, frame.visibility.comboPoints)
- end
-
- if( not frame.visibility.comboPoints ) then return end
-
- -- Hide the active combo points
- if( frame.comboPoints.points ) then
- for _, texture in pairs(frame.comboPoints.points) do
- texture:Hide()
- end
- end
-
- -- Setup for bar display!
- if( config.comboPoints.isBar ) then
- frame.comboPoints.blocks = frame.comboPoints.blocks or {}
- frame.comboPoints.points = frame.comboPoints.blocks
-
- -- Position bars, the 5 accounts for borders
- local blockWidth = (frame.comboPoints:GetWidth() - 4 ) / MAX_COMBO_POINTS
- for id=1, MAX_COMBO_POINTS do
- frame.comboPoints.blocks[id] = frame.comboPoints.blocks[id] or frame.comboPoints:CreateTexture(nil, "OVERLAY")
- local texture = frame.comboPoints.blocks[id]
- texture:SetVertexColor(1, 0.80, 0)
- texture:SetHorizTile(false)
- texture:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
- texture:SetHeight(frame.comboPoints:GetHeight())
- texture:SetWidth(blockWidth)
- texture:ClearAllPoints()
-
- if( config.comboPoints.growth == "LEFT" ) then
- if( id > 1 ) then
- texture:SetPoint("TOPRIGHT", frame.comboPoints.blocks[id - 1], "TOPLEFT", -1, 0)
- else
- texture:SetPoint("TOPRIGHT", frame.comboPoints, "TOPRIGHT", 0, 0)
- end
- else
- if( id > 1 ) then
- texture:SetPoint("TOPLEFT", frame.comboPoints.blocks[id - 1], "TOPRIGHT", 1, 0)
- else
- texture:SetPoint("TOPLEFT", frame.comboPoints, "TOPLEFT", 0, 0)
- end
- end
- end
-
- -- guess not, will have to do icons :(
- else
- local point, relativePoint
- local x, y = 0, 0
-
- if( config.comboPoints.growth == "LEFT" ) then
- point, relativePoint = "BOTTOMRIGHT", "BOTTOMLEFT"
- x = config.comboPoints.spacing
- elseif( config.comboPoints.growth == "RIGHT" ) then
- point, relativePoint = "BOTTOMLEFT", "BOTTOMRIGHT"
- x = config.comboPoints.spacing
- elseif( config.comboPoints.growth == "UP" ) then
- point, relativePoint = "BOTTOMLEFT", "TOPLEFT"
- y = config.comboPoints.spacing
- elseif( config.comboPoints.growth == "DOWN" ) then
- point, relativePoint = "TOPLEFT", "BOTTOMLEFT"
- y = config.comboPoints.spacing
- end
-
+function Combo:GetComboPointType()
+ return "comboPoints"
+end
- frame.comboPoints.icons = frame.comboPoints.icons or {}
- frame.comboPoints.points = frame.comboPoints.icons
-
- for id=1, MAX_COMBO_POINTS do
- frame.comboPoints.icons[id] = frame.comboPoints.icons[id] or frame.comboPoints:CreateTexture(nil, "OVERLAY")
- local texture = frame.comboPoints.icons[id]
- texture:SetTexture("Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\combo")
- texture:SetHeight(config.comboPoints.size)
- texture:SetWidth(config.comboPoints.size)
-
- if( id > 1 ) then
- texture:ClearAllPoints()
- texture:SetPoint(point, frame.comboPoints.icons[id - 1], relativePoint, x, y)
- else
- texture:ClearAllPoints()
- texture:SetPoint("CENTER", frame.comboPoints, "CENTER", 0, 0)
- end
+function Combo:GetPoints(unit)
+ -- For Malygos dragons, they also self cast their CP on themselves, which is why we check CP on ourself
+ if( UnitHasVehicleUI("player") and UnitHasVehiclePlayerFrameUI("player") ) then
+ local points = GetComboPoints("vehicle", "target")
+ if( points == 0 ) then
+ points = GetComboPoints("vehicle", "vehicle")
end
-
- -- Position the main frame
- frame.comboPoints:SetHeight(0.1)
- frame.comboPoints:SetWidth(0.1)
- ShadowUF.Layout:AnchorFrame(frame, frame.comboPoints, config.comboPoints)
+ return points
+ else
+ return UnitPower("player", cpConfig.powerType)
end
end
-function Combo:OnDisable(frame)
- frame:UnregisterAll(self)
-end
-
-function Combo:Update(frame)
- -- For Malygos dragons, they also self cast their CP on themselves, which is why we check CP on ourself!
- local playerUnit = UnitHasVehicleUI("player") and "vehicle" or "player"
- local points = GetComboPoints(playerUnit)
- if( points == 0 ) then
- points = GetComboPoints(playerUnit, playerUnit)
- end
-
- -- Bar display, hide it if we don't have any combo points
- if( ShadowUF.db.profile.units[frame.unitType].comboPoints.isBar ) then
- ShadowUF.Layout:SetBarVisibility(frame, "comboPoints", points > 0)
- end
-
- for id, pointTexture in pairs(frame.comboPoints.points) do
- if( id <= points ) then
- pointTexture:Show()
- else
- pointTexture:Hide()
- end
+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
old mode 100644
new mode 100755
index 64a89852f..2ceb6fb5d
--- a/modules/defaultlayout.lua
+++ b/modules/defaultlayout.lua
@@ -34,18 +34,18 @@ local function finalizeData(config, useMerge)
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 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
verifyTable(child, self.defaults.profile.units[unit])
- -- Merge it in
+ -- Merge the new child table into the actual units
mergeToChild(child, self.db.profile.units[unit], true)
-
+
-- Merge position in too
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]
@@ -55,14 +55,28 @@ local function finalizeData(config, useMerge)
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
@@ -88,7 +102,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
borderColor = {r = 0.30, g = 0.30, b = 0.50, a = 1},
}
config.hidden = {
- cast = false, runes = true, buffs = false, party = true, player = true, pet = true, target = true, focus = true, boss = true, arena = true
+ cast = false, buffs = false, party = true, player = true, pet = true, target = true, focus = true, boss = true, arena = true, playerAltPower = false, playerPower = true
}
config.font = {
name = "Myriad Condensed Web",
@@ -96,16 +110,20 @@ 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
local SML = LibStub:GetLibrary("LibSharedMedia-3.0")
- if( GetLocale() == "koKR" or GetLocale() == "zhCN" or GetLocale() == "zhTW" or GetLocale() == "ruRU" ) then
+ if( GetLocale() == "koKR" or GetLocale() == "zhCN" or GetLocale() == "zhTW" ) then
config.font.name = SML.DefaultMedia.font
end
-
+
+ config.auraColors = {
+ removable = {r = 1, g = 1, b = 1}
+ }
+
config.classColors = {
HUNTER = {r = 0.67, g = 0.83, b = 0.45},
WARLOCK = {r = 0.58, g = 0.51, b = 0.79},
@@ -117,19 +135,40 @@ function ShadowUF:LoadDefaultLayout(useMerge)
SHAMAN = {r = 0.14, g = 0.35, b = 1.0},
WARRIOR = {r = 0.78, g = 0.61, b = 0.43},
DEATHKNIGHT = {r = 0.77, g = 0.12 , b = 0.23},
+ MONK = {r = 0.0, g = 1.00 , b = 0.59},
+ DEMONHUNTER = {r = 0.64, g = 0.19, b = 0.79},
+ 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},
+ MANA = {r = 0.30, g = 0.50, b = 0.85},
RAGE = {r = 0.90, g = 0.20, b = 0.30},
- FOCUS = {r = 1.0, g = 0.85, b = 0},
- ENERGY = {r = 1.0, g = 0.85, b = 0.10},
- HAPPINESS = {r = 0.50, g = 0.90, b = 0.70},
- RUNES = {r = 0.50, g = 0.50, b = 0.50},
+ 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},
@@ -138,8 +177,11 @@ function ShadowUF:LoadDefaultLayout(useMerge)
static = {r = 0.70, g = 0.20, b = 0.90},
yellow = {r = 0.93, g = 0.93, b = 0.0},
inc = {r = 0, g = 0.35, b = 0.23},
+ incAbsorb = {r = 0.93, g = 0.75, b = 0.09},
+ healAbsorb = {r = 0.68, g = 0.47, b = 1},
enemyUnattack = {r = 0.60, g = 0.20, b = 0.20},
hostile = {r = 0.90, g = 0.0, b = 0.0},
+ aggro = {r = 0.90, g = 0.0, b = 0.0},
friendly = {r = 0.20, g = 0.90, b = 0.20},
neutral = {r = 0.93, g = 0.93, b = 0.0},
offline = {r = 0.50, g = 0.50, b = 0.50}
@@ -155,47 +197,57 @@ function ShadowUF:LoadDefaultLayout(useMerge)
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},
+ 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},
+ 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},
- debuffs = {enabled = false, anchorPoint = "BL", size = 16, perRow = 10, x = 0, y = 0},
+ buffs = {enabled = false, anchorPoint = "BL", size = 16, perRow = 10, x = 0, y = 0, show = {player = true, boss = true, raid = true, misc = true}, enlarge = {}, timers = {ALL = true}},
+ debuffs = {enabled = false, anchorPoint = "BL", size = 16, perRow = 10, x = 0, y = 0, show = {player = true, boss = true, raid = true, misc = true}, enlarge = {SELF = true}, timers = {ALL = true}},
},
text = {
- {width = 0.50, name = L["Left text"], anchorTo = "$healthBar", anchorPoint = "CLI", x = 3, y = 0, size = 0},
- {width = 0.60, name = L["Right text"], anchorTo = "$healthBar", anchorPoint = "CRI", x = -3, y = 0, size = 0},
+ {width = 0.50, name = L["Left text"], anchorTo = "$healthBar", anchorPoint = "CLI", x = 3, y = 0, size = 0, default = true},
+ {width = 0.60, name = L["Right text"], anchorTo = "$healthBar", anchorPoint = "CRI", x = -3, y = 0, size = 0, default = true},
- {width = 0.50, name = L["Left text"], anchorTo = "$powerBar", anchorPoint = "CLI", x = 3, y = 0, size = 0},
- {width = 0.60, name = L["Right text"], anchorTo = "$powerBar", anchorPoint = "CRI", x = -3, y = 0, size = 0},
+ {width = 0.50, name = L["Left text"], anchorTo = "$powerBar", anchorPoint = "CLI", x = 3, y = 0, size = 0, default = true},
+ {width = 0.60, name = L["Right text"], anchorTo = "$powerBar", anchorPoint = "CRI", x = -3, y = 0, size = 0, default = true},
- {width = 1, name = L["Text"], anchorTo = "$emptyBar", anchorPoint = "CLI", x = 3, y = 0, size = 0},
+ {width = 0.50, name = L["Left text"], anchorTo = "$emptyBar", anchorPoint = "CLI", x = 3, y = 0, size = 0, default = true},
+ {width = 0.60, name = L["Right text"], anchorTo = "$emptyBar", anchorPoint = "CRI", x = -3, y = 0, size = 0, default = true},
},
indicators = {
raidTarget = {anchorTo = "$parent", anchorPoint = "C", size = 20, x = 0, y = 0},
@@ -212,14 +264,12 @@ function ShadowUF:LoadDefaultLayout(useMerge)
combatText = {anchorTo = "$parent", anchorPoint = "C", x = 0, y = 0},
emptyBar = {background = true, height = 1, reactionType = "none", order = 0},
healthBar = {background = true, colorType = "class", reactionType = "npc", height = 1.20, order = 10},
- powerBar = {background = true, height = 1.0, order = 20},
- druidBar = {background = true, height = 0.40, order = 25},
+ powerBar = {background = true, height = 1.0, order = 20, colorType = "type"},
xpBar = {background = true, height = 0.25, order = 55},
castBar = {background = true, height = 0.60, order = 40, icon = "HIDE", name = {enabled = true, size = 0, anchorTo = "$parent", rank = true, anchorPoint = "CLI", x = 1, y = 0}, time = {enabled = true, size = 0, anchorTo = "$parent", anchorPoint = "CRI", x = -1, y = 0}},
- runeBar = {background = false, height = 0.40, order = 70},
- totemBar = {background = false, height = 0.40, order = 70},
+ altPowerBar = {background = true, height = 0.40, order = 100},
}
-
+
-- Units configuration
config.units = {
raid = {
@@ -236,11 +286,15 @@ function ShadowUF:LoadDefaultLayout(useMerge)
healthBar = {reactionType = "none"},
powerBar = {height = 0.30},
incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
masterLoot = {anchorTo = "$parent", anchorPoint = "TR", size = 12, x = -2, y = -10},
role = {enabled = false, anchorTo = "$parent", anchorPoint = "BR", size = 14, x = 0, y = 14},
ready = {anchorTo = "$parent", anchorPoint = "LC", size = 24, x = 25, y = 0},
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"},
},
text = {
{text = "[(()afk() )][name]"},
@@ -248,6 +302,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
raidpet = {
@@ -264,6 +319,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
healthBar = {reactionType = "none"},
powerBar = {height = 0.30},
incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
masterLoot = {anchorTo = "$parent", anchorPoint = "TR", size = 12, x = -2, y = -10},
@@ -276,20 +333,39 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[name]"},
+ {text = ""},
},
},
-
- player = {
+ player = {
width = 190,
height = 45,
scale = 1.0,
portrait = {enabled = true, fullAfter = 50},
castBar = {order = 60},
xpBar = {order = 55},
- runeBar = {enabled = true, order = 70},
- totemBar = {enabled = true, order = 70},
+ fader = {enabled = false, combatAlpha = 1.0, inactiveAlpha = 0.6},
+ runeBar = {enabled = true, background = false, height = 0.40, order = 70},
+ totemBar = {enabled = true, background = false, height = 0.40, order = 70},
+ druidBar = {enabled = true, background = true, height = 0.40, order = 70},
+ priestBar = {enabled = true, background = true, height = 0.40, order = 70},
+ shamanBar = {enabled = true, background = true, height = 0.40, order = 70},
+ comboPoints = {enabled = true, anchorTo = "$parent", order = 60, anchorPoint = "BR", x = -3, y = 8, size = 14, spacing = -4, growth = "LEFT", isBar = true, height = 0.40},
+ auraPoints = {enabled = false, showAlways = true, anchorTo = "$parent", order = 60, anchorPoint = "BR", x = -3, y = 8, size = 14, spacing = -4, growth = "LEFT", isBar = true, height = 0.40},
+ staggerBar = {enabled = true, background = true, height = 0.30, order = 70},
+ soulShards = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -8, y = 6, size = 12, spacing = -2, growth = "LEFT", isBar = true, showAlways = true},
+ holyPower = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -3, y = 6, size = 14, spacing = -4, growth = "LEFT", isBar = true, showAlways = true},
+ chi = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -3, y = 6, size = 14, spacing = -4, growth = "LEFT", isBar = true, showAlways = true},
+ arcaneCharges = {anchorTo = "$parent", order = 60, height = 0.40, anchorPoint = "BR", x = -8, y = 6, size = 12, spacing = -2, growth = "LEFT", isBar = true, showAlways = true},
+ 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, temporary = playerClass == "ROGUE" or playerClass == "SHAMAN"},
+ buffs = {enabled = false, maxRows = 1},
debuffs = {enabled = false, maxRows = 1},
},
text = {
@@ -298,6 +374,10 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[(()afk() )][name][( ()group())]"},
+ {text = ""},
+ {enabled = true, width = 1, name = L["Timer Text"], text = "[totem:timer]", anchorTo = "$totemBar", anchorPoint = "C", x = 0, y = 0, size = 0, default = true, block = true},
+ {enabled = true, width = 1, name = L["Timer Text"], text = "[rune:timer]", anchorTo = "$runeBar", anchorPoint = "C", size = 0, x = 0, y = 0, default = true, block = true},
+ {enabled = true, width = 1, name = L["Text"], text = "[monk:abs:stagger]", anchorTo = "$staggerBar", anchorPoint = "C", size = 0, x = 0, y = 0, default = true}
},
},
party = {
@@ -311,6 +391,14 @@ function ShadowUF:LoadDefaultLayout(useMerge)
portrait = {enabled = true, fullAfter = 50},
castBar = {order = 60},
offset = 23,
+ incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
+ indicators = {
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ 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},
@@ -321,6 +409,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[level( )][perpp]"},
{text = "[curmaxpp]"},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
boss = {
@@ -331,6 +420,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
attribPoint = "TOP",
attribAnchorPoint = "LEFT",
offset = 20,
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
auras = {
buffs = {enabled = true, maxRows = 1, perRow = 8},
debuffs = {enabled = true, maxRows = 1, perRow = 8},
@@ -341,6 +432,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[name]"},
+ {text = ""},
},
portrait = {enabled = false},
},
@@ -348,6 +440,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
width = 90,
height = 25,
scale = 1.0,
+ healAbsorb = {cap = 1},
powerBar = {height = 0.60},
text = {
{text = "[name]"},
@@ -357,25 +450,48 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{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 = false, fullAfter = 50},
+ portrait = {enabled = true, type = "class", fullAfter = 50},
+ altPower = {enabled = false},
castBar = {order = 60},
offset = 25,
+ healAbsorb = {cap = 1},
auras = {
buffs = {enabled = true, maxRows = 1, perRow = 9},
debuffs = {enabled = true, maxRows = 1, perRow = 9},
},
+ indicators = {
+ pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
+ arenaSpec = {anchorTo = "$parent", anchorPoint = "LC", size = 28, x = 0, y = 0}
+ },
text = {
{text = "[name]"},
{text = "[curmaxhp]"},
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[name]"},
+ {text = ""},
},
},
arenapet = {
@@ -383,6 +499,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 25,
scale = 1.0,
powerBar = {height = 0.60},
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
text = {
{text = "[name]"},
{text = "[curhp]"},
@@ -396,6 +514,110 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 25,
scale = 1.0,
powerBar = {height = 0.60},
+ altPower = {enabled = false},
+ healAbsorb = {cap = 1},
+ indicators = {
+ pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
+ },
+ 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},
},
@@ -405,6 +627,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[name]"},
+ {text = ""},
},
},
maintank = {
@@ -418,8 +641,14 @@ function ShadowUF:LoadDefaultLayout(useMerge)
maxColumns = 1,
columnSpacing = 5,
incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
portrait = {enabled = false, fullAfter = 50},
castBar = {order = 60},
+ indicators = {
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"},
+ },
auras = {
buffs = {enabled = false},
debuffs = {enabled = false},
@@ -430,6 +659,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
maintanktarget = {
@@ -446,6 +676,24 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[classification( )][perpp]", width = 0.50},
{text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60},
{text = "[(()afk() )][name]"},
+ {text = ""},
+ },
+ },
+ maintanktargettarget = {
+ width = 150,
+ height = 40,
+ scale = 1.0,
+ auras = {
+ buffs = {enabled = false},
+ debuffs = {enabled = false},
+ },
+ text = {
+ {text = "[(()afk() )][name]"},
+ {text = "[curmaxhp]"},
+ {text = "[classification( )][perpp]", width = 0.50},
+ {text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60},
+ {text = "[(()afk() )][name]"},
+ {text = ""},
},
},
mainassist = {
@@ -459,8 +707,14 @@ function ShadowUF:LoadDefaultLayout(useMerge)
maxColumns = 1,
columnSpacing = 5,
incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
portrait = {enabled = false, fullAfter = 50},
castBar = {order = 60},
+ indicators = {
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ sumPending = {enabled = true, anchorPoint = "C", size = 40, x = 0, y = 0, anchorTo = "$parent"},
+ },
auras = {
buffs = {enabled = false},
debuffs = {enabled = false},
@@ -471,12 +725,14 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[level( )][perpp]"},
{text = "[curmaxpp]"},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
mainassisttarget = {
width = 150,
height = 40,
scale = 1.0,
+ healAbsorb = {cap = 1},
auras = {
buffs = {enabled = false},
debuffs = {enabled = false},
@@ -487,12 +743,32 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{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]"},
@@ -507,6 +783,25 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 25,
scale = 1.0,
powerBar = {height = 0.60},
+ healAbsorb = {cap = 1},
+ indicators = {
+ pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = 0, y = 11},
+ },
+ 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},
},
@@ -516,6 +811,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[name]"},
+ {text = ""},
},
},
target = {
@@ -523,10 +819,17 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 45,
scale = 1.0,
portrait = {enabled = true, alignment = "RIGHT", fullAfter = 50},
+ incHeal = {cap = 1},
+ incAbsorb = {cap = 1},
+ healAbsorb = {cap = 1},
castBar = {order = 60},
- comboPoints = {anchorTo = "$parent", order = 60, anchorPoint = "BR", x = -3, y = 8, size = 14, spacing = -4, growth = "LEFT", isBar = true},
+ comboPoints = {enabled = false, anchorTo = "$parent", order = 60, anchorPoint = "BR", x = -3, y = 8, size = 14, spacing = -4, growth = "LEFT", isBar = true, height = 0.40},
indicators = {
- lfdRole = {enabled = false}
+ lfdRole = {enabled = false},
+ resurrect = {enabled = true, anchorPoint = "RC", size = 28, x = -39, y = -1, anchorTo = "$parent"},
+ 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},
@@ -538,6 +841,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[level( )][classification( )][perpp]", width = 0.50},
{text = "[curmaxpp]", anchorTo = "$powerBar", width = 0.60},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
pet = {
@@ -545,24 +849,24 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 30,
scale = 1.0,
powerBar = {height = 0.70},
+ healAbsorb = {cap = 1},
healthBar = {reactionType = "none"},
portrait = {enabled = false, fullAfter = 50},
castBar = {order = 60},
- indicators = {
- happiness = {enabled = false, anchorTo = "$parent", anchorPoint = "BR", size = 14, x = 3, y = 13},
- },
text = {
{text = "[name]"},
{text = "[curmaxhp]"},
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[name]"},
+ {text = ""},
},
},
pettarget = {
width = 190,
height = 30,
scale = 1.0,
+ healAbsorb = {cap = 1},
powerBar = {height = 0.70},
indicators = {
},
@@ -572,6 +876,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curmaxpp]"},
{text = "[name]"},
+ {text = ""},
},
},
focus = {
@@ -579,10 +884,15 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 28,
scale = 1.0,
powerBar = {height = 0.60},
+ healAbsorb = {cap = 1},
portrait = {enabled = false, fullAfter = 50},
castBar = {order = 60},
indicators = {
lfdRole = {enabled = false},
+ resurrect = {enabled = true, anchorPoint = "LC", size = 28, x = 37, y = -1, anchorTo = "$parent"},
+ 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]"},
@@ -590,6 +900,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[perpp]"},
{text = "[curpp]"},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
focustarget = {
@@ -597,6 +908,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 25,
scale = 1.0,
powerBar = {height = 0.60},
+ healAbsorb = {cap = 1},
portrait = {alignment = "RIGHT"},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = -3, y = 11},
@@ -607,6 +919,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = "[(()afk() )][name]"},
+ {text = ""},
},
},
targettarget = {
@@ -614,6 +927,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 30,
scale = 1.0,
powerBar = {height = 0.6},
+ healAbsorb = {cap = 1},
portrait = {alignment = "RIGHT"},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = -3, y = 11},
@@ -623,6 +937,8 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = "[curhp]"},
{text = "[perpp]"},
{text = "[curpp]"},
+ {text = ""},
+ {text = ""},
},
},
targettargettarget = {
@@ -630,6 +946,7 @@ function ShadowUF:LoadDefaultLayout(useMerge)
height = 30,
scale = 1.0,
powerBar = {height = 0.6},
+ healAbsorb = {cap = 1},
portrait = {alignment = "RIGHT"},
indicators = {
pvp = {anchorTo = "$parent", anchorPoint = "BL", size = 22, x = -3, y = 11},
@@ -639,10 +956,12 @@ function ShadowUF:LoadDefaultLayout(useMerge)
{text = ""},
{text = ""},
{text = ""},
+ {text = ""},
+ {text = ""},
},
},
}
-
+
finalizeData(config, useMerge)
end
-
+
diff --git a/modules/druid.lua b/modules/druid.lua
index ee16c0477..51d0c1998 100755
--- a/modules/druid.lua
+++ b/modules/druid.lua
@@ -4,10 +4,8 @@ ShadowUF:RegisterModule(Druid, "druidBar", ShadowUF.L["Druid mana bar"], true, "
function Druid:OnEnable(frame)
frame.druidBar = frame.druidBar or ShadowUF.Units:CreateBar(frame)
- frame:RegisterUnitEvent("UNIT_MAXMANA", self, "Update")
- frame:RegisterUnitEvent("UNIT_MANA", self, "Update")
frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "PowerChanged")
-
+
frame:RegisterUpdateFunc(self, "PowerChanged")
frame:RegisterUpdateFunc(self, "Update")
end
@@ -17,30 +15,25 @@ function Druid:OnDisable(frame)
end
function Druid:OnLayoutApplied(frame)
- if( frame.visibility.druidBar ) then
- local color = ShadowUF.db.profile.powerColors.MANA
-
- if( not ShadowUF.db.profile.units[frame.unitType].druidBar.invert ) then
- frame.druidBar:SetStatusBarColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
- if( not frame.druidBar.background.overrideColor ) then
- frame.druidBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
- else
- frame.druidBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
-
- color = frame.druidBar.background.overrideColor or color
- frame.druidBar:SetStatusBarColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
- end
+ if( not frame.visibility.druidBar ) then return end
+
+ local color = ShadowUF.db.profile.powerColors.MANA
+ frame:SetBarColor("druidBar", color.r, color.g, color.b)
end
--- While power type is mana, show the bar once it is mana hide it.
function Druid:PowerChanged(frame)
- local powerType = UnitPowerType(frame.unit)
- ShadowUF.Layout:SetBarVisibility(frame, "druidBar", powerType == 1 or powerType == 3)
+ local visible = UnitPowerType(frame.unit) ~= 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)
- frame.druidBar:SetMinMaxValues(0, UnitPowerMax(frame.unit, 0))
- frame.druidBar:SetValue(UnitIsDeadOrGhost(frame.unit) and 0 or not UnitIsConnected(frame.unit) and 0 or UnitPower(frame.unit, 0))
+function Druid:Update(frame, event, unit, powerType)
+ if( powerType and powerType ~= "MANA" ) then return end
+ frame.druidBar:SetMinMaxValues(0, UnitPowerMax(frame.unit, Enum.PowerType.Mana))
+ frame.druidBar:SetValue(UnitIsDeadOrGhost(frame.unit) and 0 or not UnitIsConnected(frame.unit) and 0 or UnitPower(frame.unit, Enum.PowerType.Mana))
end
diff --git a/modules/empty.lua b/modules/empty.lua
old mode 100644
new mode 100755
index b8d07bb4a..fde045d18
--- a/modules/empty.lua
+++ b/modules/empty.lua
@@ -19,7 +19,7 @@ function Empty:OnLayoutApplied(frame)
local color = frame.emptyBar.background.overrideColor or fallbackColor
frame.emptyBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
- if( ShadowUF.db.profile.units[frame.unitType].emptyBar.reaction or ShadowUF.db.profile.units[frame.unitType].emptyBar.class ) then
+ if( ShadowUF.db.profile.units[frame.unitType].emptyBar.reactionType or ShadowUF.db.profile.units[frame.unitType].emptyBar.class ) then
frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdateColor")
frame:RegisterUpdateFunc(self, "UpdateColor")
else
@@ -31,7 +31,10 @@ end
function Empty:UpdateColor(frame)
local color
local reactionType = ShadowUF.db.profile.units[frame.unitType].emptyBar.reactionType
- if( not UnitPlayerOrPetInRaid(frame.unit) and not UnitPlayerOrPetInParty(frame.unit) and ( ( ( reactionType == "player" or reactionType == "both" ) and UnitIsPlayer(frame.unit) and not UnitIsFriend(frame.unit, "player") ) or ( ( reactionType == "npc" or reactionType == "both" ) and not UnitIsPlayer(frame.unit) ) ) ) then
+
+ if( ( reactionType == "npc" or reactionType == "both" ) and not UnitPlayerControlled(frame.unit) and UnitIsTapDenied(frame.unit) and UnitCanAttack("player", frame.unit) ) then
+ color = ShadowUF.db.profile.healthColors.tapped
+ elseif( not UnitPlayerOrPetInRaid(frame.unit) and not UnitPlayerOrPetInParty(frame.unit) and ( ( ( reactionType == "player" or reactionType == "both" ) and UnitIsPlayer(frame.unit) and not UnitIsFriend(frame.unit, "player") ) or ( ( reactionType == "npc" or reactionType == "both" ) and not UnitIsPlayer(frame.unit) ) ) ) then
if( not UnitIsFriend(frame.unit, "player") and UnitPlayerControlled(frame.unit) ) then
if( UnitCanAttack("player", frame.unit) ) then
color = ShadowUF.db.profile.healthColors.hostile
@@ -49,10 +52,10 @@ function Empty:UpdateColor(frame)
end
end
elseif( ShadowUF.db.profile.units[frame.unitType].emptyBar.class and ( UnitIsPlayer(frame.unit) or UnitCreatureFamily(frame.unit) ) ) then
- local class = UnitCreatureFamily(frame.unit) or select(2, UnitClass(frame.unit))
+ local class = UnitCreatureFamily(frame.unit) or frame:UnitClassToken()
color = class and ShadowUF.db.profile.classColors[class]
end
-
+
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
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
diff --git a/modules/fader.lua b/modules/fader.lua
index 46a8faf3d..bf96ccaf5 100755
--- a/modules/fader.lua
+++ b/modules/fader.lua
@@ -1,23 +1,45 @@
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)
@@ -25,7 +47,7 @@ local function startFading(self, type, alpha, speedyFade)
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
@@ -42,11 +64,11 @@ function Fader:OnEnable(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
@@ -80,38 +102,38 @@ function Fader:PLAYER_REGEN_ENABLED(frame, event)
frame:RegisterNormalEvent("UNIT_SPELLCAST_START", self, "CastStart")
frame:RegisterNormalEvent("UNIT_SPELLCAST_STOP", self, "CastStop")
frame:RegisterUnitEvent("UNIT_HEALTH", self, "Update")
- frame:RegisterUnitEvent("UNIT_MANA", self, "Update")
frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXMANA", self, "Update")
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "Update")
end
function Fader:PLAYER_REGEN_DISABLED(frame, event)
self:Update(frame, event)
- frame:UnregisterEvent("PLAYER_TARGET_CHANGED")
- frame:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START")
- frame:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
- frame:UnregisterEvent("UNIT_SPELLCAST_START")
- frame:UnregisterEvent("UNIT_SPELLCAST_STOP")
- frame:UnregisterEvent("UNIT_HEALTH")
- frame:UnregisterEvent("UNIT_MANA")
- frame:UnregisterEvent("UNIT_MAXHEALTH")
- frame:UnregisterEvent("UNIT_MAXMANA")
+ frame:UnregisterSingleEvent("PLAYER_TARGET_CHANGED", self)
+ frame:UnregisterSingleEvent("UNIT_SPELLCAST_CHANNEL_START", self)
+ frame:UnregisterSingleEvent("UNIT_SPELLCAST_CHANNEL_STOP", self)
+ frame:UnregisterSingleEvent("UNIT_SPELLCAST_START", self)
+ frame:UnregisterSingleEvent("UNIT_SPELLCAST_STOP", self)
+ frame:UnregisterSingleEvent("UNIT_HEALTH", self)
+ frame:UnregisterSingleEvent("UNIT_POWER_FREQUENT", self)
+ frame:UnregisterSingleEvent("UNIT_MAXHEALTH", self)
+ frame:UnregisterSingleEvent("UNIT_MAXPOWER", self)
end
local activeCastID
-function Fader:CastStart(frame, event, unit, spellName, spellRank, id)
+function Fader:CastStart(frame, event, unit, id)
if( unit ~= "player" or activeCastID == id ) then return end
activeCastID = id
-
+
frame.fader.playerCasting = true
self:Update(frame)
end
-function Fader:CastStop(frame, event, unit, spellName, spellRank, id)
+function Fader:CastStop(frame, event, unit, id)
if( unit ~= "player" or activeCastID ~= id ) then return end
activeCastID = nil
-
+
frame.fader.playerCasting = nil
self:Update(frame)
end
@@ -125,7 +147,7 @@ function Fader:Update(frame, event)
elseif( frame.fader.playerCasting ) then
startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha, true)
-- Ether mana or energy is not at 100%, fade in
- elseif( ( UnitPowerType(frame.unit) == 0 or UnitPowerType(frame.unit) == 3 ) and UnitPower(frame.unit) ~= UnitPowerMax(frame.unit) ) then
+ elseif( powerDepletes[UnitPowerType(frame.unit)] and UnitPower(frame.unit) ~= UnitPowerMax(frame.unit) ) then
startFading(frame, "in", ShadowUF.db.profile.units[frame.unitType].fader.combatAlpha)
-- Health is not at max, fade in
elseif( UnitHealth(frame.unit) ~= UnitHealthMax(frame.unit) ) then
diff --git a/modules/healabsorb.lua b/modules/healabsorb.lua
new file mode 100755
index 000000000..673646bf3
--- /dev/null
+++ b/modules/healabsorb.lua
@@ -0,0 +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
diff --git a/modules/health.lua b/modules/health.lua
old mode 100644
new mode 100755
index d701f8f0b..f9081cf59
--- a/modules/health.lua
+++ b/modules/health.lua
@@ -1,11 +1,13 @@
local Health = {}
ShadowUF:RegisterModule(Health, "healthBar", ShadowUF.L["Health bar"], true)
+local canCure = ShadowUF.Units.canCure
local function getGradientColor(unit)
- local percent = UnitHealth(unit) / UnitHealthMax(unit)
+ local maxHealth = UnitHealthMax(unit)
+ local percent = maxHealth > 0 and UnitHealth(unit) / maxHealth or 0
if( percent >= 1 ) then return ShadowUF.db.profile.healthColors.green.r, ShadowUF.db.profile.healthColors.green.g, ShadowUF.db.profile.healthColors.green.b end
if( percent == 0 ) then return ShadowUF.db.profile.healthColors.red.r, ShadowUF.db.profile.healthColors.red.g, ShadowUF.db.profile.healthColors.red.b end
-
+
local sR, sG, sB, eR, eG, eB = 0, 0, 0, 0, 0, 0
local modifier, inverseModifier = percent * 2, 0
if( percent > 0.50 ) then
@@ -17,116 +19,86 @@ local function getGradientColor(unit)
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
--- Not doing full health update, because other checks can lag behind without much issue
-local function updateTimer(self)
- local currentHealth = UnitHealth(self.parent.unit)
- if( currentHealth == self.currentHealth ) then return end
- self.currentHealth = currentHealth
- self:SetValue(currentHealth)
-
- -- As much as I would rather not have to do this in an OnUpdate, I don't have much choice large health changes in a single update will make them very clearly be lagging behind
- for _, fontString in pairs(self.parent.fontStrings) do
- if( fontString.fastHealth ) then
- fontString:UpdateTags()
- end
- end
-
- -- Update incoming heal number
- if( self.parent.incHeal and self.parent.incHeal.healed ) then
- self.parent.incHeal:SetValue(currentHealth + self.parent.incHeal.healed)
- end
-
- -- The target is not offline, and we have a health percentage so update the gradient
- if( not self.parent.healthBar.wasOffline and self.parent.healthBar.hasPercent ) then
- Health:SetBarColor(self.parent.healthBar, ShadowUF.db.profile.units[self.parent.unitType].healthBar.invert, getGradientColor(self.parent.unit))
- end
-end
-
function Health:OnEnable(frame)
if( not frame.healthBar ) then
frame.healthBar = ShadowUF.Units:CreateBar(frame)
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_THREAT_SITUATION_UPDATE", self, "UpdateColor")
+ frame:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "UpdateColor")
+
if( frame.unit == "pet" ) then
- frame:RegisterUnitEvent("UNIT_HAPPINESS", self, "UpdateColor")
+ frame:RegisterUnitEvent("UNIT_POWER_UPDATE", self, "UpdateColor")
end
-
- frame:RegisterUpdateFunc(self, "UpdateColor")
- frame:RegisterUpdateFunc(self, "Update")
-end
-function Health:OnLayoutApplied(frame)
- if( not frame.visibility.healthBar ) then return end
-
- if( ShadowUF.db.profile.units[frame.unitType].healthBar.predicted ) then
- frame.healthBar:SetScript("OnUpdate", updateTimer)
- frame.healthBar.parent = frame
- else
- frame.healthBar:SetScript("OnUpdate", nil)
+ if ( ShadowUF.db.profile.units[frame.unitType].healthBar.colorDispel ) then
+ frame:RegisterUnitEvent("UNIT_AURA", self, "UpdateAura")
+ frame:RegisterUpdateFunc(self, "UpdateAura")
end
+
+ frame:RegisterUpdateFunc(self, "UpdateColor")
+ frame:RegisterUpdateFunc(self, "Update")
end
function Health:OnDisable(frame)
frame:UnregisterAll(self)
end
-function Health:SetBarColor(bar, invert, r, g, b)
- if( not invert ) then
- bar:SetStatusBarColor(r, g, b, ShadowUF.db.profile.bars.alpha)
- if( not bar.background.overrideColor ) then
- bar.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
- else
- bar.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.alpha)
- if( not bar.background.overrideColor ) then
- bar:SetStatusBarColor(0, 0, 0, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
- else
- bar:SetStatusBarColor(bar.background.overrideColor.r, bar.background.overrideColor.g, bar.background.overrideColor.b, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
+function Health:UpdateAura(frame)
+ local hadDebuff = frame.healthBar.hasDebuff
+ frame.healthBar.hasDebuff = nil
+ if( UnitIsFriend(frame.unit, "player") ) then
+ local id = 0
+ while( true ) do
+ id = id + 1
+ local name, _, _, auraType = 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
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, ShadowUF.db.profile.healthColors.offline.r, ShadowUF.db.profile.healthColors.offline.g, ShadowUF.db.profile.healthColors.offline.b)
+ frame:SetBarColor("healthBar", ShadowUF.db.profile.healthColors.offline.r, ShadowUF.db.profile.healthColors.offline.g, ShadowUF.db.profile.healthColors.offline.b)
return
+ elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorDispel and frame.healthBar.hasDebuff ) then
+ color = DebuffTypeColor[frame.healthBar.hasDebuff]
elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorAggro and UnitThreatSituation(frame.unit) == 3 ) then
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, ShadowUF.db.profile.healthColors.hostile.r, ShadowUF.db.profile.healthColors.hostile.g, ShadowUF.db.profile.healthColors.hostile.b)
+ frame:SetBarColor("healthBar", ShadowUF.db.profile.healthColors.aggro.r, ShadowUF.db.profile.healthColors.aggro.g, ShadowUF.db.profile.healthColors.aggro.b)
return
elseif( frame.inVehicle ) then
color = ShadowUF.db.profile.classColors.VEHICLE
- elseif( not UnitIsTappedByPlayer(unit) and UnitIsTapped(unit) and UnitCanAttack("player", unit) ) then
+ elseif( not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) and UnitCanAttack("player", unit) ) then
color = ShadowUF.db.profile.healthColors.tapped
- elseif( unit == "pet" and reactionType == "happiness" and GetPetHappiness() ) then
- local happiness = GetPetHappiness()
- if( happiness == 3 ) then
- color = ShadowUF.db.profile.healthColors.friendly
- elseif( happiness == 2 ) then
- color = ShadowUF.db.profile.healthColors.neutral
- elseif( happiness == 1 ) then
- color = ShadowUF.db.profile.healthColors.hostile
- end
- elseif( not UnitPlayerOrPetInRaid(unit) and not UnitPlayerOrPetInParty(unit) and ( ( ( reactionType == "player" or reactionType == "both" ) and UnitIsPlayer(unit) and not UnitIsFriend(unit, "player") ) or ( ( reactionType == "npc" or reactionType == "both" ) and not UnitIsPlayer(unit) ) ) ) then
+ 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
@@ -143,18 +115,35 @@ function Health:UpdateColor(frame)
color = ShadowUF.db.profile.healthColors.hostile
end
end
- elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "class" and ( UnitIsPlayer(unit) or UnitCreatureFamily(unit) ) ) then
- local class = UnitCreatureFamily(frame.unit) or select(2, UnitClass(frame.unit))
+ elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "class" and (UnitIsPlayer(unit) or unit == "pet") ) then
+ local class = (unit == "pet") and "PET" or frame:UnitClassToken()
+ color = class and ShadowUF.db.profile.classColors[class]
+ elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "playerclass" and unit == "pet") then
+ local class = select(2, UnitClass("player"))
color = class and ShadowUF.db.profile.classColors[class]
+ elseif( ShadowUF.db.profile.units[frame.unitType].healthBar.colorType == "playerclass" and (frame.unitType == "partypet" or frame.unitType == "raidpet" or frame.unitType == "arenapet") and (frame.parent or frame.unitType == "raidpet") ) then
+ local 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
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, color.r, color.g, color.b)
+ frame:SetBarColor("healthBar", color.r, color.g, color.b)
else
frame.healthBar.hasPercent = true
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, getGradientColor(unit))
+ frame:SetBarColor("healthBar", getGradientColor(unit))
end
end
@@ -164,18 +153,18 @@ function Health:Update(frame)
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
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, ShadowUF.db.profile.healthColors.offline.r, ShadowUF.db.profile.healthColors.offline.g, ShadowUF.db.profile.healthColors.offline.b)
+ frame:SetBarColor("healthBar", ShadowUF.db.profile.healthColors.offline.r, ShadowUF.db.profile.healthColors.offline.g, ShadowUF.db.profile.healthColors.offline.b)
-- The unit was offline, but they no longer are so we need to do a forced color update
elseif( frame.healthBar.wasOffline ) then
frame.healthBar.wasOffline = nil
self:UpdateColor(frame)
-- Color health by percentage
elseif( frame.healthBar.hasPercent ) then
- self:SetBarColor(frame.healthBar, ShadowUF.db.profile.units[frame.unitType].healthBar.invert, getGradientColor(frame.unit))
+ frame:SetBarColor("healthBar", getGradientColor(frame.unit))
end
-end
\ No newline at end of file
+end
diff --git a/modules/helpers.lua b/modules/helpers.lua
new file mode 100755
index 000000000..612a6dde0
--- /dev/null
+++ b/modules/helpers.lua
@@ -0,0 +1,33 @@
+-- Block Timers
+local BlockTimers = {}
+function BlockTimers:Inject(module, event)
+ ShadowUF.Tags.customEvents["SUF_" .. event] = module
+ module.EnableTag = BlockTimers.EnableTag
+ module.DisableTag = BlockTimers.DisableTag
+end
+
+function BlockTimers:EnableTag(frame, fontString)
+ fontString.block.fontString = fontString
+end
+
+function BlockTimers:DisableTag(frame, fontString)
+ fontString.block.fontString = nil
+end
+
+
+ShadowUF.BlockTimers = BlockTimers;
+
+-- Dynamic Blocks
+local DynamicBlocks = {}
+function DynamicBlocks:Inject(module)
+ module.OnLayoutWidgets = function(_, 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
old mode 100644
new mode 100755
index 95bef4a5b..3fec3d62e
--- a/modules/highlight.lua
+++ b/modules/highlight.lua
@@ -1,5 +1,8 @@
local Highlight = {}
local goldColor, mouseColor = {r = 0.75, g = 0.75, b = 0.35}, {r = 0.75, g = 0.75, b = 0.50}
+local rareColor, eliteColor = {r = 0, g = 0.63, b = 1}, {r = 1, g = 0.81, b = 0}
+
+local canCure = ShadowUF.Units.canCure
ShadowUF:RegisterModule(Highlight, "highlight", ShadowUF.L["Highlight"])
-- Might seem odd to hook my code in the core manually, but HookScript is ~40% slower due to it being a secure hook
@@ -8,7 +11,7 @@ local function OnEnter(frame)
frame.highlight.hasMouseover = true
Highlight:Update(frame)
end
-
+
frame.highlight.OnEnter(frame)
end
@@ -17,7 +20,7 @@ local function OnLeave(frame)
frame.highlight.hasMouseover = nil
Highlight:Update(frame)
end
-
+
frame.highlight.OnLeave(frame)
end
@@ -27,7 +30,7 @@ function Highlight:OnEnable(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")
@@ -36,7 +39,7 @@ function Highlight:OnEnable(frame)
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")
@@ -65,18 +68,18 @@ function Highlight:OnEnable(frame)
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")
@@ -84,16 +87,21 @@ function Highlight:OnEnable(frame)
end
if( ShadowUF.db.profile.units[frame.unitType].highlight.debuff ) then
- frame:RegisterNormalEvent("UNIT_AURA", self, "UpdateAura")
+ frame:RegisterUnitEvent("UNIT_AURA", self, "UpdateAura")
frame:RegisterUpdateFunc(self, "UpdateAura")
end
-
+
if( ShadowUF.db.profile.units[frame.unitType].highlight.mouseover and not frame.highlight.OnEnter ) then
- frame.highlight.OnEnter = frame:GetScript("OnEnter")
- frame.highlight.OnLeave = frame:GetScript("OnLeave")
-
- frame:SetScript("OnEnter", OnEnter)
- frame:SetScript("OnLeave", OnLeave)
+ 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
@@ -106,27 +114,39 @@ 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]
+ color = DebuffTypeColor[frame.highlight.hasDebuff] or DebuffTypeColor[""]
elseif( frame.highlight.hasThreat ) then
color = ShadowUF.db.profile.healthColors.hostile
elseif( frame.highlight.hasAttention ) then
color = goldColor
elseif( frame.highlight.hasMouseover ) then
color = mouseColor
+ elseif( ShadowUF.db.profile.units[frame.unitType].highlight.rareMob and ( frame.highlight.hasClassification == "rareelite" or frame.highlight.hasClassification == "rare" ) ) then
+ color = rareColor
+ elseif( ShadowUF.db.profile.units[frame.unitType].highlight.eliteMob and frame.highlight.hasClassification == "elite" ) then
+ color = eliteColor
end
-
+
if( color ) then
frame.highlight.top:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.units[frame.unitType].highlight.alpha)
frame.highlight.left:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.units[frame.unitType].highlight.alpha)
@@ -148,8 +168,27 @@ function Highlight:UpdateAttention(frame)
self:Update(frame)
end
+function Highlight:UpdateClassification(frame)
+ frame.highlight.hasClassification = UnitClassification(frame.unit)
+ self:Update(frame)
+end
+
function Highlight:UpdateAura(frame)
- -- In theory, we don't need aura scanning because the first debuff returned is always one we can cure... in theory
- frame.highlight.hasDebuff = UnitIsFriend(frame.unit, "player") and select(5, UnitDebuff(frame.unit, 1, "RAID")) or nil
+ frame.highlight.hasDebuff = nil
+ if( UnitIsFriend(frame.unit, "player") ) then
+ local id = 0
+ while( true ) do
+ id = id + 1
+ local name, _, _, auraType = 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
new file mode 100755
index 000000000..65870909d
--- /dev/null
+++ b/modules/holypower.lua
@@ -0,0 +1,31 @@
+if( not ShadowUF.ComboPoints ) then return end
+
+local HolyPower = setmetatable({}, {__index = ShadowUF.ComboPoints})
+ShadowUF:RegisterModule(HolyPower, "holyPower", ShadowUF.L["Holy Power"], nil, "PALADIN")
+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
new file mode 100755
index 000000000..10ae25239
--- /dev/null
+++ b/modules/incabsorb.lua
@@ -0,0 +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
diff --git a/modules/incheal.lua b/modules/incheal.lua
index f0e940430..a3095b86a 100755
--- a/modules/incheal.lua
+++ b/modules/incheal.lua
@@ -1,195 +1,146 @@
-local HealComm = LibStub("LibHealComm-4.0", true)
-if( not HealComm ) then return end
-
-local IncHeal = {}
-local frames = {}
-local playerEndTime, playerGUID
+local IncHeal = {["frameKey"] = "incHeal", ["colorKey"] = "inc", ["frameLevelMod"] = 2}
+ShadowUF.IncHeal = IncHeal
ShadowUF:RegisterModule(IncHeal, "incHeal", ShadowUF.L["Incoming heals"])
-ShadowUF.Tags.customEvents["HEALCOMM"] = IncHeal
-
--- How far ahead to show heals at most
-local INCOMING_SECONDS = 3
function IncHeal:OnEnable(frame)
- frames[frame] = true
frame.incHeal = frame.incHeal or ShadowUF.Units:CreateBar(frame)
-
+
frame:RegisterUnitEvent("UNIT_MAXHEALTH", self, "UpdateFrame")
frame:RegisterUnitEvent("UNIT_HEALTH", self, "UpdateFrame")
+ frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", self, "UpdateFrame")
+
frame:RegisterUpdateFunc(self, "UpdateFrame")
-
- self:Setup()
end
function IncHeal:OnDisable(frame)
frame:UnregisterAll(self)
- frame.incHeal:Hide()
-
- if( not frame.hasHCTag ) then
- frames[frame] = nil
- self:Setup()
- end
+ frame[self.frameKey]:Hide()
end
function IncHeal:OnLayoutApplied(frame)
- if( frame.visibility.incHeal and frame.visibility.healthBar ) then
- frame.incHeal:SetHeight(frame.healthBar:GetHeight())
- frame.incHeal:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
- frame.incHeal:SetStatusBarColor(ShadowUF.db.profile.healthColors.inc.r, ShadowUF.db.profile.healthColors.inc.g, ShadowUF.db.profile.healthColors.inc.b, ShadowUF.db.profile.bars.alpha)
- frame.incHeal:GetStatusBarTexture():SetHorizTile(false)
- frame.incHeal:Hide()
-
- -- When we can cheat and put the incoming bar right behind the health bar, we can efficiently show the incoming heal bar
- -- if the main bar has a transparency set, then we need a more complicated method to stop the health bar from being darker with incoming heals up
- if( ( ShadowUF.db.profile.units[frame.unitType].healthBar.invert and ShadowUF.db.profile.bars.backgroundAlpha == 0 ) or ( not ShadowUF.db.profile.units[frame.unitType].healthBar.invert and ShadowUF.db.profile.bars.alpha == 1 ) ) then
- frame.incHeal.simple = true
- frame.incHeal:SetWidth(frame.healthBar:GetWidth() * ShadowUF.db.profile.units[frame.unitType].incHeal.cap)
- frame.incHeal:SetFrameLevel(frame.topFrameLevel - 3)
-
- frame.incHeal:ClearAllPoints()
- frame.incHeal:SetPoint("TOPLEFT", frame.healthBar)
- frame.incHeal:SetPoint("BOTTOMLEFT", frame.healthBar)
+ local 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
- frame.incHeal.simple = nil
- frame.incHeal:SetFrameLevel(frame.topFrameLevel)
- frame.incHeal:SetWidth(1)
- frame.incHeal:SetMinMaxValues(0, 1)
- frame.incHeal:SetValue(1)
-
- local x, y = select(4, frame.healthBar:GetPoint())
- frame.incHeal:ClearAllPoints()
- frame.incHeal.healthX = x
- frame.incHeal.healthY = y
- frame.incHeal.healthWidth = frame.healthBar:GetWidth()
- frame.incHeal.maxWidth = frame.incHeal.healthWidth * ShadowUF.db.profile.units[frame.unitType].incHeal.cap
- frame.incHeal.cappedWidth = frame.incHeal.healthWidth * (ShadowUF.db.profile.units[frame.unitType].incHeal.cap - 1)
+ bar:SetHeight(frame.healthBar:GetHeight() * cap)
end
- end
-end
--- Since I don't want a more complicated system where both incheal.lua and tags.lua are watching the same events
--- I'll update the HC tags through here instead
-function IncHeal:EnableTag(frame)
- frames[frame] = true
- frame.hasHCTag = true
-
- self:Setup()
-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
-function IncHeal:DisableTag(frame)
- frame.hasHCTag = nil
-
- if( not frame.visibility.incHeal ) then
- frames[frame] = nil
- self:Setup()
+ bar.positionMod = bar.reverseFill and -1 or 1
+ bar.maxSize = bar.healthSize * cap
end
end
--- Check if we need to register callbacks
-function IncHeal:Setup()
- playerGUID = UnitGUID("player")
-
- local enabled
- for frame in pairs(frames) do
- enabled = true
- break
+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
-
- if( not enabled ) then
- if( HealComm ) then
- HealComm:UnregisterAllCallbacks(IncHeal)
- end
+
+ local health = UnitHealth(frame.unit)
+ if( health <= 0 ) then
+ bar.total = nil
+ bar:Hide()
return
end
- HealComm.RegisterCallback(self, "HealComm_HealStarted", "HealComm_HealUpdated")
- HealComm.RegisterCallback(self, "HealComm_HealStopped")
- HealComm.RegisterCallback(self, "HealComm_HealDelayed", "HealComm_HealUpdated")
- HealComm.RegisterCallback(self, "HealComm_HealUpdated")
- HealComm.RegisterCallback(self, "HealComm_ModifierChanged")
- HealComm.RegisterCallback(self, "HealComm_GUIDDisappeared")
-end
+ 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
--- Update any tags using HC
-function IncHeal:UpdateTags(frame, amount)
- if( not frame.fontStrings or not frame.hasHCTag ) then return end
-
- for _, fontString in pairs(frame.fontStrings) do
- if( fontString.HEALCOMM ) then
- fontString.incoming = amount > 0 and amount or nil
- fontString:UpdateTags()
+ -- When the primary bar has an alpha of 100%, we can cheat and do incoming heals easily. Otherwise we need to do it a more complex way to keep it looking good
+ if( bar.simple ) then
+ bar.total = health + incAmount
+ bar:SetMinMaxValues(0, maxHealth * (ShadowUF.db.profile.units[frame.unitType][self.frameKey].cap or 1.30))
+ bar:SetValue(bar.total)
+ else
+ local healthSize = bar.healthSize * (health / maxHealth)
+ local incSize = bar.healthSize * (incAmount / maxHealth)
+
+ if( (healthSize + incSize) > bar.maxSize ) then
+ incSize = bar.maxSize - healthSize
end
- end
-end
-local function updateHealthBar(frame, interrupted)
- -- This makes sure that when a heal like Tranquility is cast, it won't show the entire cast but cap it at 4 seconds into the future
- local time = GetTime()
- local timeBand = playerEndTime and math.min(playerEndTime - time, INCOMING_SECONDS) or INCOMING_SECONDS
- local healed = (HealComm:GetHealAmount(frame.unitGUID, HealComm.ALL_HEALS, time + timeBand) or 0) * HealComm:GetHealModifier(frame.unitGUID)
-
- -- Update any tags that are using HC data
- IncHeal:UpdateTags(frame, healed)
-
- -- Bar is also supposed to be enabled, lets update that too
- if( frame.visibility.incHeal and frame.visibility.healthBar ) then
- if( healed > 0 ) then
- frame.incHeal.healed = healed
- frame.incHeal:Show()
-
- -- When the primary bar has an alpha of 100%, we can cheat and do incoming heals easily. Otherwise we need to do it a more complex way to keep it looking good
- if( frame.incHeal.simple ) then
- frame.incHeal.total = UnitHealth(frame.unit) + healed
- frame.incHeal:SetMinMaxValues(0, UnitHealthMax(frame.unit) * ShadowUF.db.profile.units[frame.unitType].incHeal.cap)
- frame.incHeal:SetValue(frame.incHeal.total)
- else
- local health, maxHealth = UnitHealth(frame.unit), UnitHealthMax(frame.unit)
- local healthWidth = frame.incHeal.healthWidth * (health / maxHealth)
- local incWidth = frame.healthBar:GetWidth() * (healed / health)
- if( (healthWidth + incWidth) > frame.incHeal.maxWidth ) then
- incWidth = frame.incHeal.cappedWidth
- end
-
- frame.incHeal:SetWidth(incWidth)
- frame.incHeal:SetPoint("TOPLEFT", SUFUnitplayer, "TOPLEFT", frame.incHeal.healthX + healthWidth, frame.incHeal.healthY)
- end
+ if( bar.orientation == "HORIZONTAL" ) then
+ bar:SetWidth(incSize)
+ bar:SetPoint(bar.positionPoint, frame.healthBar, bar.positionMod * healthSize, 0)
+ bar:SetPoint(bar.positionRelative, frame.healthBar, bar.positionMod * healthSize, 0)
else
- frame.incHeal.total = nil
- frame.incHeal.healed = nil
- frame.incHeal:Hide()
+ bar:SetHeight(incSize)
+ bar:SetPoint(bar.positionPoint, frame.healthBar, 0, bar.positionMod * healthSize)
+ bar:SetPoint(bar.positionRelative, frame.healthBar, 0, bar.positionMod * healthSize)
end
end
end
function IncHeal:UpdateFrame(frame)
- updateHealthBar(frame, true)
-end
+ if( not frame.visibility[self.frameKey] or not frame.visibility.healthBar ) then return end
-function IncHeal:UpdateIncoming(interrupted, ...)
- for frame in pairs(frames) do
- for i=1, select("#", ...) do
- if( select(i, ...) == frame.unitGUID ) then
- updateHealthBar(frame, interrupted)
- end
- end
+ local amount = UnitGetIncomingHeals(frame.unit) or 0
+ if( amount > 0 and frame.visibility.healAbsorb ) then
+ amount = amount + (UnitGetTotalHealAbsorbs(frame.unit) or 0)
end
-end
-
--- Handle callbacks from HealComm
-function IncHeal:HealComm_HealUpdated(event, casterGUID, spellID, healType, endTime, ...)
- if( casterGUID == playerGUID and bit.band(healType, HealComm.CASTED_HEALS) > 0 ) then playerEndTime = endTime end
- self:UpdateIncoming(nil, ...)
-end
-
-function IncHeal:HealComm_HealStopped(event, casterGUID, spellID, healType, interrupted, ...)
- if( casterGUID == playerGUID and bit.band(healType, HealComm.CASTED_HEALS) > 0 ) then playerEndTime = nil end
- self:UpdateIncoming(interrupted, ...)
-end
-
-function IncHeal:HealComm_ModifierChanged(event, guid)
- self:UpdateIncoming(nil, guid)
-end
-function IncHeal:HealComm_GUIDDisappeared(event, guid)
- self:UpdateIncoming(true, guid)
+ self:PositionBar(frame, amount)
end
diff --git a/modules/indicators.lua b/modules/indicators.lua
old mode 100644
new mode 100755
index dbc054da8..0dd4e5936
--- a/modules/indicators.lua
+++ b/modules/indicators.lua
@@ -1,14 +1,26 @@
-local Indicators = {list = {"status", "pvp", "leader", "masterLoot", "raidTarget", "happiness", "ready", "role", "lfdRole", "class"}}
-local leavingWorld
+local Indicators = {list = {"status", "pvp", "leader", "resurrect", "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 = select(2, UnitClass(frame.unit))
+
+ local class = frame:UnitClassToken()
if( UnitIsPlayer(frame.unit) and class ) then
- local coords = CLASS_BUTTONS[class]
+ local coords = CLASS_ICON_TCOORDS[class]
frame.indicators.class:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes")
frame.indicators.class:SetTexCoord(coords[1], coords[2], coords[3], coords[4])
frame.indicators.class:Show()
@@ -17,29 +29,67 @@ function Indicators:UpdateClass(frame)
end
end
-function Indicators:UpdateHappiness(frame)
- if( not frame.indicators.happiness or not frame.indicators.happiness.enabled ) then return end
-
- local happiness = GetPetHappiness()
- if( not happiness ) then
- frame.indicators.happiness:Hide()
- elseif( happiness == 3 ) then
- frame.indicators.happiness:SetTexCoord(0, 0.1875, 0, 0.359375)
- frame.indicators.happiness:Show()
- elseif( happiness == 2 ) then
- frame.indicators.happiness:SetTexCoord(0.1875, 0.375, 0, 0.359375)
- frame.indicators.happiness:Show()
- elseif( happiness == 1 ) then
- frame.indicators.happiness:SetTexCoord(0.375, 0.5625, 0, 0.359375)
- frame.indicators.happiness:Show()
+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
+ local masterLoot, partyID, raidID
+ if C_PartyInfo and C_PartyInfo.GetLootMethod then
+ local lootType
+ lootType, partyID, raidID = C_PartyInfo.GetLootMethod()
+ masterLoot = (lootType == Enum.LootMethod.Masterlooter)
+ else
+ local lootType
+ lootType, partyID, raidID = GetLootMethod()
+ masterLoot = (lootType == "master")
+ end
+ if( not masterLoot ) 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()
@@ -47,7 +97,7 @@ function Indicators:UpdateMasterLoot(frame)
frame.indicators.masterLoot:Hide()
end
end
-
+
function Indicators:UpdateRaidTarget(frame)
if( not frame.indicators.raidTarget or not frame.indicators.raidTarget.enabled ) then return end
@@ -59,28 +109,45 @@ function Indicators:UpdateRaidTarget(frame)
end
end
+function Indicators:UpdateQuestBoss(frame)
+ if( not frame.indicators.questBoss or not frame.indicators.questBoss.enabled ) then return end
+
+ if( UnitIsQuestBoss(frame.unit) ) then
+ frame.indicators.questBoss:Show()
+ else
+ frame.indicators.questBoss:Hide()
+ end
+end
+
function Indicators:UpdateLFDRole(frame, event)
if( not frame.indicators.lfdRole or not frame.indicators.lfdRole.enabled ) then return end
-
- local isTank, isHealer, isDamage = UnitGroupRolesAssigned(frame.unitOwner)
- if( isTank ) then
+
+ local role
+ if( frame.unitType ~= "arena" ) then
+ role = UnitGroupRolesAssigned(frame.unitOwner)
+ else
+ local specID = GetArenaOpponentSpec(frame.unitID)
+ role = specID and select(6, GetSpecializationInfoByID(specID))
+ end
+
+ if( role == "TANK" ) then
frame.indicators.lfdRole:SetTexCoord(0, 19/64, 22/64, 41/64)
frame.indicators.lfdRole:Show()
- elseif( isHealer ) then
+ elseif( role == "HEALER" ) then
frame.indicators.lfdRole:SetTexCoord(20/64, 39/64, 1/64, 20/64)
frame.indicators.lfdRole:Show()
- elseif( isDamage ) then
+ elseif( role == "DAMAGER" ) then
frame.indicators.lfdRole:SetTexCoord(20/64, 39/64, 22/64, 41/64)
frame.indicators.lfdRole:Show()
else
frame.indicators.lfdRole:Hide()
- end
+ end
end
function Indicators:UpdateRole(frame, event)
if( not frame.indicators.role or not frame.indicators.role.enabled ) then return end
-
- if( leavingWorld or not UnitInRaid(frame.unit) and not UnitInParty(frame.unit) ) then
+
+ if( not UnitInRaid(frame.unit) and not UnitInParty(frame.unit) ) then
frame.indicators.role:Hide()
elseif( GetPartyAssignment("MAINTANK", frame.unit) ) then
frame.indicators.role:SetTexture("Interface\\GroupFrame\\UI-Group-MainTankIcon")
@@ -94,38 +161,68 @@ function Indicators:UpdateRole(frame, event)
end
function Indicators:UpdateLeader(frame)
- self:UpdateMasterLoot(frame)
- self:UpdateRole(frame)
- self:UpdateLFDRole(frame)
if( not frame.indicators.leader or not frame.indicators.leader.enabled ) then return end
- if( UnitIsPartyLeader(frame.unit) ) then
+ if( UnitIsGroupLeader(frame.unit) 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
- if( UnitIsPVP(frame.unit) and UnitFactionGroup(frame.unit) ) then
- frame.indicators.pvp:SetTexture(string.format("Interface\\TargetingFrame\\UI-PVP-%s", UnitFactionGroup(frame.unit)))
- frame.indicators.pvp:Show()
- elseif( UnitIsPVPFreeForAll(frame.unit) ) then
+ local faction = UnitFactionGroup(frame.unit)
+ if( UnitIsPVPFreeForAll(frame.unit) ) then
frame.indicators.pvp:SetTexture("Interface\\TargetingFrame\\UI-PVP-FFA")
+ frame.indicators.pvp:SetTexCoord(0,1,0,1)
+ frame.indicators.pvp:Show()
+ elseif( faction and faction ~= "Neutral" and UnitIsPVP(frame.unit) ) then
+ frame.indicators.pvp:SetTexture(string.format("Interface\\TargetingFrame\\UI-PVP-%s", faction))
+ frame.indicators.pvp:SetTexCoord(0,1,0,1)
frame.indicators.pvp:Show()
else
frame.indicators.pvp:Hide()
end
end
+function Indicators:UpdatePetBattle(frame)
+ if( UnitIsWildBattlePet(frame.unit) or UnitIsBattlePetCompanion(frame.unit) ) then
+ local petType = UnitBattlePetType(frame.unit)
+ frame.indicators.petBattle:SetTexture(string.format("Interface\\TargetingFrame\\PetBadge-%s", PET_TYPE_SUFFIX[petType]))
+ frame.indicators.petBattle:Show()
+ else
+ frame.indicators.petBattle:Hide()
+ end
+end
+
-- Non-player units do not give events when they enter or leave combat, so polling is necessary
local function combatMonitor(self, elapsed)
self.timeElapsed = self.timeElapsed + elapsed
if( self.timeElapsed < 1 ) then return end
self.timeElapsed = self.timeElapsed - 1
-
+
if( UnitAffectingCombat(self.parent.unit) ) then
self.status:Show()
else
@@ -153,19 +250,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
@@ -173,41 +257,42 @@ function Indicators:UpdateReadyCheck(frame, event)
-- 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(self, elapsed)
+ self.fadeTimer:SetScript("OnUpdate", function(f, elapsed)
local hasTimer
- for frame, timeLeft in pairs(self.fadeList) do
+ for fadeFrame, timeLeft in pairs(f.fadeList) do
hasTimer = true
-
- self.fadeList[frame] = timeLeft - elapsed
- frame:SetAlpha(self.fadeList[frame] / FADEOUT_TIME)
-
- if( self.fadeList[frame] <= 0 ) then
- self.fadeList[frame] = nil
- frame:Hide()
+
+ 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 self:Hide() 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")
+ 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
@@ -215,13 +300,13 @@ function Indicators:UpdateReadyCheck(frame, event)
frame.indicators.ready:Hide()
return
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)
@@ -230,13 +315,18 @@ 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
frame.indicators = CreateFrame("Frame", nil, frame)
- frame.indicators:SetFrameLevel(frame.topFrameLevel + 1)
+ frame.indicators:SetFrameLevel(frame.topFrameLevel + 2)
end
-
+
-- Now lets enable all the indicators
local config = ShadowUF.db.profile.units[frame.unitType]
if( config.indicators.status and config.indicators.status.enabled ) then
@@ -259,9 +349,38 @@ function Indicators:OnEnable(frame)
elseif( frame.indicators.status ) then
frame.indicators:SetScript("OnUpdate", nil)
end
-
+
+ if( config.indicators.arenaSpec and config.indicators.arenaSpec.enabled ) then
+ frame:RegisterNormalEvent("ARENA_OPPONENT_UPDATE", self, "UpdateArenaSpec")
+ frame:RegisterUpdateFunc(self, "UpdateArenaSpec")
+ frame.indicators.arenaSpec = frame.indicators.arenaSpec or frame.indicators:CreateTexture(nil, "OVERLAY")
+ end
+
+ if( config.indicators.phase and config.indicators.phase.enabled ) then
+ -- Player phase changes do not generate a phase change event. This seems to be the best
+ -- TODO: what event does fire here? frame:RegisterNormalEvent("UPDATE_WORLD_STATES", self, "UpdatePhase")
+ frame:RegisterUpdateFunc(self, "UpdatePhase")
+ frame.indicators.phase = frame.indicators.phase or frame.indicators:CreateTexture(nil, "OVERLAY")
+ end
+
+ if( config.indicators.resurrect and config.indicators.resurrect.enabled ) then
+ frame:RegisterNormalEvent("INCOMING_RESURRECT_CHANGED", self, "UpdateResurrect")
+ frame:RegisterNormalEvent("UNIT_OTHER_PARTY_CHANGED", self, "UpdateResurrect")
+ frame:RegisterUpdateFunc(self, "UpdateResurrect")
+
+ frame.indicators.resurrect = frame.indicators.resurrect or frame.indicators:CreateTexture(nil, "OVERLAY")
+ frame.indicators.resurrect:SetTexture("Interface\\RaidFrame\\Raid-Icon-Rez")
+ end
+
+ if( config.indicators.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")
frame:RegisterUpdateFunc(self, "UpdatePVPFlag")
@@ -272,18 +391,16 @@ function Indicators:OnEnable(frame)
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")
- frame.indicators.leader:SetTexture("Interface\\GroupFrame\\UI-Group-LeaderIcon")
end
-
+
if( config.indicators.masterLoot and config.indicators.masterLoot.enabled ) then
frame:RegisterNormalEvent("PARTY_LOOT_METHOD_CHANGED", self, "UpdateMasterLoot")
- frame:RegisterNormalEvent("RAID_ROSTER_UPDATE", self, "UpdateMasterLoot")
frame:RegisterUpdateFunc(self, "UpdateMasterLoot")
frame.indicators.masterLoot = frame.indicators.masterLoot or frame.indicators:CreateTexture(nil, "OVERLAY")
@@ -295,32 +412,12 @@ function Indicators:OnEnable(frame)
frame.indicators.role = frame.indicators.role or frame.indicators:CreateTexture(nil, "OVERLAY")
frame.indicators.role:SetTexture("Interface\\GroupFrame\\UI-Group-MainAssistIcon")
-
- -- Silly hack to fix the fact that Blizzard bugged an API and causes " is not in your party" errors
- if( not self.leavingFrame ) then
- self.leavingFrame = CreateFrame("Frame")
- self.leavingFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
- self.leavingFrame:RegisterEvent("PLAYER_LEAVING_WORLD")
- self.leavingFrame:SetScript("OnEvent", function(self, event)
- if( event == "PLAYER_LEAVING_WORLD" ) then
- leavingWorld = true
- else
- leavingWorld = nil
-
- for frame in pairs(ShadowUF.Units.frameList) do
- if( frame:IsVisible() and frame.indicators and frame.indicators.role and frame.indicators.role.enabled ) then
- Indicators:UpdateRole(frame)
- end
- end
- end
- end)
- end
end
-
+
if( config.indicators.raidTarget and config.indicators.raidTarget.enabled ) then
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
@@ -330,30 +427,38 @@ function Indicators:OnEnable(frame)
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.happiness and config.indicators.happiness.enabled ) then
- frame:RegisterUnitEvent("UNIT_HAPPINESS", self, "UpdateHappiness")
- frame:RegisterUpdateFunc(self, "UpdateHappiness")
-
- frame.indicators.happiness = frame.indicators.happiness or frame.indicators:CreateTexture(nil, "OVERLAY")
- frame.indicators.happiness:SetTexture("Interface\\PetPaperDollFrame\\UI-PetHappiness")
- end
-
+
if( config.indicators.lfdRole and config.indicators.lfdRole.enabled ) then
- if( frame.unit == "player" ) then
- frame:RegisterNormalEvent("PLAYER_ROLES_ASSIGNED", self, "UpdateLFDRole")
- end
-
+ frame:RegisterNormalEvent("PLAYER_ROLES_ASSIGNED", self, "UpdateLFDRole")
+ frame:RegisterUpdateFunc(self, "UpdateLFDRole")
+
frame.indicators.lfdRole = frame.indicators.lfdRole or frame.indicators:CreateTexture(nil, "OVERLAY")
frame.indicators.lfdRole:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES")
end
+ if( config.indicators.questBoss and config.indicators.questBoss.enabled ) then
+ frame:RegisterUnitEvent("UNIT_CLASSIFICATION_CHANGED", self, "UpdateQuestBoss")
+ frame:RegisterUpdateFunc(self, "UpdateQuestBoss")
+
+ frame.indicators.questBoss = frame.indicators.questBoss or frame.indicators:CreateTexture(nil, "OVERLAY")
+ frame.indicators.questBoss:SetTexture("Interface\\TargetingFrame\\PortraitQuestBadge")
+ end
+
+ if( config.indicators.petBattle and config.indicators.petBattle.enabled ) then
+ frame:RegisterUpdateFunc(self, "UpdatePetBattle")
+ frame.indicators.petBattle = frame.indicators.petBattle or frame.indicators:CreateTexture(nil, "OVERLAY")
+ end
+
-- As they all share the function, register it as long as one is active
if( frame.indicators.leader or frame.indicators.masterLoot or frame.indicators.role or ( frame.unit ~= "player" and frame.indicators.lfdRole ) ) then
- frame:RegisterNormalEvent("PARTY_MEMBERS_CHANGED", self, "UpdateLeader")
+ frame:RegisterNormalEvent("GROUP_ROSTER_UPDATE", self, "GroupRosterUpdate")
+ end
+
+ if( frame.indicators.leader or frame.indicators.pvp ) then
+ frame:RegisterUnitEvent("PLAYER_FLAGS_CHANGED", self, "UpdateFlags")
end
end
@@ -372,10 +477,10 @@ 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].enabled and config.indicators[key].size ) then
+ if( indicator and config.indicators[key] and config.indicators[key].enabled and config.indicators[key].size ) then
indicator.enabled = true
indicator:SetHeight(config.indicators[key].size)
indicator:SetWidth(config.indicators[key].size)
@@ -385,10 +490,10 @@ function Indicators:OnLayoutApplied(frame, config)
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
\ No newline at end of file
+end
diff --git a/modules/layout.lua b/modules/layout.lua
index b08d3fff6..d483a0b6d 100755
--- a/modules/layout.lua
+++ b/modules/layout.lua
@@ -10,7 +10,7 @@ ShadowUF.Layout = Layout
function Layout:MediaForced(mediaType)
local oldPath = mediaPath[mediaType]
self:CheckMedia()
-
+
if( mediaPath[mediaType] ~= oldPath ) then
self:Reload()
end
@@ -18,14 +18,14 @@ 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
@@ -34,9 +34,9 @@ local function updateBackdrop()
-- Update the backdrop table
local backdrop = ShadowUF.db.profile.backdrop
backdropTbl.bgFile = mediaPath.background
- backdropTbl.edgeFile = mediaPath.border
+ if( mediaPath.border ~= "Interface\\None" ) then backdropTbl.edgeFile = mediaPath.border end
backdropTbl.tile = backdrop.tileSize > 0 and true or false
- backdropTbl.edgeSize = backdrop.edgeSize
+ backdropTbl.edgeSize = backdrop.edgeSize == 0 and 1 or backdrop.edgeSize
backdropTbl.tileSize = backdrop.tileSize
backdropTbl.insets.left = backdrop.inset
backdropTbl.insets.right = backdrop.inset
@@ -50,7 +50,7 @@ function Layout:CheckMedia()
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
@@ -59,7 +59,7 @@ 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
@@ -71,13 +71,24 @@ function Layout:ToggleVisibility(frame, visible)
elseif( frame ) then
frame:Hide()
end
-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
@@ -96,7 +107,16 @@ function Layout:Reload(unit)
frame:FullUpdate()
end
end
-
+
+ for header in pairs(ShadowUF.Units.headerFrames) do
+ if( header.unitType and ( not unit or header.unitType == unit ) ) then
+ local config = ShadowUF.db.profile.units[header.unitType]
+ header:SetAttribute("style-height", config.height)
+ header:SetAttribute("style-width", config.width)
+ header:SetAttribute("style-scale", config.scale)
+ end
+ end
+
ShadowUF:FireModuleEvent("OnLayoutReload", unit)
end
@@ -106,7 +126,17 @@ function Layout:Load(frame)
-- About to set layout
ShadowUF:FireModuleEvent("OnPreLayoutApply", frame, unitConfig)
-
+
+ -- Figure out if we're secure locking
+ frame.secureLocked = nil
+ for _, module in pairs(ShadowUF.moduleOrder) do
+ if( frame.visibility[module.moduleKey] and ShadowUF.db.profile.units[frame.unitType][module.moduleKey] and
+ ShadowUF.db.profile.units[frame.unitType][module.moduleKey].secure and module:SecureLockable() ) then
+ frame.secureLocked = true
+ break
+ end
+ end
+
-- Load all of the layout things
self:SetupFrame(frame, unitConfig)
self:SetupBars(frame, unitConfig)
@@ -124,6 +154,8 @@ SML:Register(SML.MediaType.BORDER, "Square Clean", "Interface\\AddOns\\ShadowedU
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")
@@ -141,13 +173,13 @@ 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
@@ -169,7 +201,7 @@ function Layout:GetJustify(config)
return "RIGHT"
end
end
-
+
return "CENTER"
end
@@ -236,7 +268,7 @@ 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
@@ -248,16 +280,16 @@ function Layout:AnchorFrame(parent, frame, config)
-- 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
@@ -266,7 +298,11 @@ function Layout:AnchorFrame(parent, frame, config)
return
end
end
-
+
+ if( config.block ) then
+ anchorTo = anchorTo.blocks[frame.blockID]
+ end
+
-- Figure out where it's anchored
local point = config.point and config.point ~= "" and config.point or preDefPoint[config.anchorPoint] or "CENTER"
local relativePoint = config.relativePoint and config.relativePoint ~= "" and config.relativePoint or preDefRelative[config.anchorPoint] or "CENTER"
@@ -276,7 +312,7 @@ function Layout:AnchorFrame(parent, frame, config)
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
@@ -284,10 +320,11 @@ 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)
-
+
-- Prevent these from updating while in combat to prevent tainting
if( not InCombatLockdown() ) then
frame:SetHeight(config.height)
@@ -303,7 +340,7 @@ function Layout:SetupFrame(frame, config)
-- 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
@@ -331,15 +368,22 @@ function Layout:SetupBars(frame, config)
local key = module.moduleKey
local widget = frame[key]
if( widget and ( module.moduleHasBar or config[key] and config[key].isBar ) ) then
- self:ToggleVisibility(widget, frame.visibility[key])
-
- if( widget:IsShown() and widget.SetStatusBarTexture ) 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 ) then
+ if( config[key].background or config[key].invert ) then
widget.background:SetTexture(mediaPath.statusbar)
widget.background:SetHorizTile(false)
widget.background:Show()
@@ -361,9 +405,9 @@ end
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)
@@ -374,6 +418,38 @@ function Layout:SetupFontString(fontString, extraSize)
end
local totalWeight = {}
+function Layout:InitFontString(parent, frame, id, config, blockID)
+ local rowID = blockID and tonumber(id .. "." .. blockID) or id
+
+ local fontString = frame.fontStrings[rowID] or frame.highFrame:CreateFontString(nil, "ARTWORK")
+ fontString.configID = id
+ if( blockID ) then
+ fontString.blockID = blockID
+ fontString.block = parent.blocks[blockID]
+ end
+
+ self:SetupFontString(fontString, config.size)
+ fontString:SetTextColor(ShadowUF.db.profile.font.color.r, ShadowUF.db.profile.font.color.g, ShadowUF.db.profile.font.color.b, ShadowUF.db.profile.font.color.a)
+ fontString:SetText(config.text)
+ fontString:SetJustifyH(self:GetJustify(config))
+ self:AnchorFrame(frame, fontString, config)
+
+ -- We figure out the anchor point so we can put text in the same area with the same width requirements
+ local anchorPoint = columnDirection[config.anchorPoint]
+ if( string.len(config.anchorPoint) == 3 ) then anchorPoint = anchorPoint .. "I" end
+
+ fontString.parentBar = parent
+ fontString.availableWidth = parent:GetWidth() - config.x
+ fontString.widthID = config.anchorTo .. anchorPoint .. config.y
+ totalWeight[fontString.widthID] = (totalWeight[fontString.widthID] or 0) + config.width
+
+ ShadowUF.Tags:Register(frame, fontString, config.text)
+ fontString:UpdateTags()
+ fontString:Show()
+
+ frame.fontStrings[rowID] = fontString
+end
+
function Layout:SetupText(frame, config)
-- Update tag text
frame.fontStrings = frame.fontStrings or {}
@@ -381,38 +457,27 @@ function Layout:SetupText(frame, config)
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 parent = row.anchorTo == "$parent" and frame or frame[string.sub(row.anchorTo, 2)]
- if( parent and parent:IsShown() and row.enabled and row.text ~= "" ) then
- local fontString = frame.fontStrings[id] or frame.highFrame:CreateFontString(nil, "ARTWORK")
- self:SetupFontString(fontString, row.size)
- fontString:SetTextColor(ShadowUF.db.profile.font.color.r, ShadowUF.db.profile.font.color.g, ShadowUF.db.profile.font.color.b, ShadowUF.db.profile.font.color.a)
- fontString:SetText(row.text)
- fontString:SetJustifyH(self:GetJustify(row))
- self:AnchorFrame(frame, fontString, row)
-
- -- We figure out the anchor point so we can put text in the same area with the same width requirements
- local anchorPoint = columnDirection[row.anchorPoint]
- if( string.len(row.anchorPoint) == 3 ) then anchorPoint = anchorPoint .. "I" end
-
- fontString.availableWidth = parent:GetWidth() - row.x
- fontString.widthID = row.anchorTo .. anchorPoint .. row.y
- totalWeight[fontString.widthID] = (totalWeight[fontString.widthID] or 0) + row.width
-
- ShadowUF.Tags:Register(frame, fontString, row.text)
- fontString:UpdateTags()
- fontString:Show()
-
- frame.fontStrings[id] = fontString
+ local module = string.sub(row.anchorTo, 2)
+ local parent = row.anchorTo == "$parent" and frame or frame[module]
+ if( parent and ( ShadowUF.modules[module].defaultVisibility == false or parent:IsShown() ) and row.enabled and row.text ~= "" ) then
+ if( not row.block ) then
+ self:InitFontString(parent, frame, id, row, nil)
+ else
+ for blockID, block in pairs(parent.blocks) do
+ self:InitFontString(parent, frame, id, row, blockID)
+ end
+ end
end
end
-- Now set all of the width using our weightings
- for id, fontString in pairs(frame.fontStrings) do
+ for _, fontString in pairs(frame.fontStrings) do
+ local id = fontString.configID
if( fontString:IsShown() ) then
fontString:SetWidth(fontString.availableWidth * (config.text[id].width / totalWeight[fontString.widthID]))
fontString:SetHeight(ShadowUF.db.profile.font.size + 1)
@@ -422,7 +487,7 @@ function Layout:SetupText(frame, config)
frame:UnregisterAll(fontString)
end
end
-end
+end
-- Setup the bar barOrder/info
local currentConfig
@@ -433,17 +498,21 @@ end
local barOrder = {}
function Layout:PositionWidgets(frame, config)
-- Deal with setting all of the bar heights
- local totalWeight, totalBars, hasFullSize = 0, -1
-
+ 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
- totalWeight = totalWeight + config[key].height
+ 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
@@ -461,19 +530,19 @@ function Layout:PositionWidgets(frame, config)
-- 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()
@@ -486,30 +555,30 @@ function Layout:PositionWidgets(frame, config)
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 / totalWeight))
+ 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 / totalWeight))
+ 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
@@ -517,7 +586,7 @@ function Layout:PositionWidgets(frame, config)
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
@@ -527,14 +596,14 @@ function Layout:PositionWidgets(frame, config)
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/monkstagger.lua b/modules/monkstagger.lua
new file mode 100755
index 000000000..19b034deb
--- /dev/null
+++ b/modules/monkstagger.lua
@@ -0,0 +1,54 @@
+local Stagger = {}
+ShadowUF:RegisterModule(Stagger, "staggerBar", ShadowUF.L["Stagger bar"], true, "MONK", SPEC_MONK_BREWMASTER)
+
+function Stagger:OnEnable(frame)
+ frame.staggerBar = frame.staggerBar or ShadowUF.Units:CreateBar(frame)
+ frame.staggerBar.timeElapsed = 0
+ frame.staggerBar.parent = frame
+ frame.staggerBar:SetScript("OnUpdate", function(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
diff --git a/modules/movers.lua b/modules/movers.lua
old mode 100644
new mode 100755
index cc8a93912..f45333f94
--- a/modules/movers.lua
+++ b/modules/movers.lua
@@ -22,20 +22,66 @@ local function createConfigEnv()
GetRaidTargetIndex = function(unit) return getValue("GetRaidTargetIndex", unit, math.random(1, 8)) end,
GetLootMethod = function(unit) return "master", 0, 0 end,
GetComboPoints = function() return MAX_COMBO_POINTS end,
- GetPetHappiness = function() return getValue("GetPetHappiness", "pet", math.random(1, 3)) end,
UnitInRaid = function() return true end,
UnitInParty = function() return true end,
UnitIsUnit = function(unitA, unitB) return unitB == "player" and true or false end,
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,
+ UnitIsWildBattlePet = function(unit) return unit == "target" or unit == "focus" end,
+ UnitBattlePetType = function(unit)
+ if( unit == "target" or unit == "focus" ) then
+ return getValue("UnitBattlePetType", unit, math.random(#(PET_TYPE_SUFFIX)))
+ end
+ end,
+ GetArenaOpponentSpec = function(unitID)
+ return getValue("GetArenaOpponentSpec", unitID, math.random(250, 270))
+ end,
UnitHealthMax = function(unit) return 50000 end,
- UnitPower = function(unit) return getValue("UnitPower", unit, math.random(20000, 50000)) end,
+ UnitPower = function(unit, powerType)
+ if( powerType == Enum.PowerType.HolyPower or powerType == Enum.PowerType.SoulShards 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,
- UnitPowerMax = function(unit) return 50000 end,
- UnitIsPartyLeader = function() return true end,
+ UnitIsGroupLeader = function() return true end,
UnitIsPVP = function(unit) return true end,
UnitIsDND = function(unit) return false end,
UnitIsAFK = function(unit) return false end,
@@ -43,23 +89,22 @@ local function createConfigEnv()
UnitAffectingCombat = function() return true end,
UnitThreatSituation = function() return 0 end,
UnitDetailedThreatSituation = function() return nil end,
- UnitThreatSituation = function() return 0 end,
UnitCastingInfo = function(unit)
- -- 1 -> 10: spell, rank, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible
+ -- 1 -> 10: spell, displayName, icon, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID
local data = unitConfig["UnitCastingInfo" .. unit] or {}
- if( not data[6] or GetTime() < data[6] ) then
+ if( not data[5] or GetTime() < data[5] ) then
data[1] = L["Test spell"]
- data[2] = L["Rank 1"]
- data[3] = L["Test spell"]
- data[4] = "Interface\\Icons\\Spell_Nature_Rejuvenation"
- data[5] = GetTime() * 1000
- data[6] = data[5] + 60000
- data[7] = false
- data[8] = math.floor(GetTime())
- data[9] = math.random(0, 100) < 25
+ data[2] = L["Test spell"]
+ data[3] = "Interface\\Icons\\Spell_Nature_Rejuvenation"
+ data[4] = GetTime() * 1000
+ data[5] = data[4] + 60000
+ data[6] = false
+ data[7] = math.floor(GetTime())
+ data[8] = math.random(0, 100) < 25
+ data[9] = 1000
unitConfig["UnitCastingInfo" .. unit] = data
end
-
+
return unpack(data)
end,
UnitIsFriend = function(unit) return unit ~= "target" and unit ~= ShadowUF.fakeUnits[unit] and unit ~= "arena" end,
@@ -73,28 +118,32 @@ local function createConfigEnv()
end,
UnitGroupRolesAssigned = function(unit)
local role = getValue("UnitGroupRolesAssigned", unit, math.random(1, 3))
- return role == 1, role == 2, role == 3
+ return role == 1 and "TANK" or (role == 2 and "HEALER" or (role == 3 and "DAMAGER"))
end,
UnitPowerType = function(unit)
local powerType = math.random(0, 4)
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"], L["Rank 1"], texture, id, auraType, 0, 0, "player", id % 6 == 0
+ return L["Test Aura"], texture, id, auraType, 0, 0, "player", id % 6 == 0
end,
UnitName = function(unit)
local unitID = string.match(unit, "(%d+)")
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)
@@ -114,7 +163,7 @@ local function prepareChildUnits(header, ...)
if( frame.unitType and not frame.configUnitID ) then
ShadowUF.Units.frameList[frame] = true
frame.configUnitID = header.groupID and (header.groupID * 5) - 5 + i or i
- frame:SetAttribute("unit", ShadowUF[header.unitType .. "Units"][frame.configUnitID])
+ frame:SetAttribute("unit", ShadowUF[header.unitMappedType .. "Units"][frame.configUnitID])
end
end
end
@@ -122,7 +171,7 @@ 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
@@ -140,23 +189,25 @@ local function setupUnits(childrenOnly)
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:GetScript("OnEnter")
- frame.originalOnLeave = frame:GetScript("OnLeave")
+ frame.originalOnEnter = frame.OnEnter
+ frame.originalOnLeave = frame.OnLeave
frame.originalOnUpdate = frame:GetScript("OnUpdate")
frame:SetMovable(not ShadowUF.Units.childUnits[frame.unitType])
frame:SetScript("OnDragStop", OnDragStop)
frame:SetScript("OnDragStart", OnDragStart)
- frame:SetScript("OnEnter", OnEnter)
- frame:SetScript("OnLeave", OnLeave)
+ frame.OnEnter = OnEnter
+ frame.OnLeave = OnLeave
frame:SetScript("OnEvent", nil)
frame:SetScript("OnUpdate", nil)
frame:RegisterForDrag("LeftButton")
@@ -164,7 +215,7 @@ local function setupUnits(childrenOnly)
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")
@@ -172,13 +223,13 @@ local function setupUnits(childrenOnly)
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()
@@ -188,20 +239,20 @@ 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)
@@ -214,17 +265,17 @@ function Movers:Enable()
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
@@ -245,12 +296,20 @@ function Movers:Enable()
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()
@@ -258,24 +317,24 @@ function Movers:Enable()
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
@@ -286,47 +345,50 @@ function Movers:Disable()
frame:SetAttribute("unit", frame.originalUnit)
frame:SetScript("OnDragStop", nil)
frame:SetScript("OnDragStart", nil)
- frame:SetScript("OnEvent", frame:IsVisible() and ShadowUF.Units.OnEvent)
+ frame:SetScript("OnEvent", frame:IsVisible() and ShadowUF.Units.OnEvent or nil)
frame:SetScript("OnUpdate", frame.originalOnUpdate)
- frame:SetScript("OnEnter", frame.originalOnEnter)
- frame:SetScript("OnLeave", frame.originalOnLeave)
+ frame.OnEnter = frame.originalOnEnter
+ frame.OnLeave = frame.originalOnLeave
frame:SetMovable(false)
frame:RegisterForDrag()
-
+
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
@@ -347,13 +409,13 @@ OnDragStop = function(self)
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
@@ -363,7 +425,7 @@ OnDragStop = function(self)
x = self:GetLeft()
point = "LEFT"
end
-
+
if( ShadowUF.db.profile.units[self.unitType].attribPoint == "BOTTOM" ) then
y = self:GetBottom()
point = "BOTTOM" .. point
@@ -371,12 +433,12 @@ OnDragStop = function(self)
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 = ""
@@ -384,14 +446,14 @@ OnDragStop = function(self)
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
@@ -409,9 +471,9 @@ 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)
+ local frame = CreateFrame("Frame", nil, UIParent, BackdropTemplateMixin and "BackdropTemplate" or nil)
frame:SetClampedToScreen(true)
frame:SetWidth(300)
frame:SetHeight(115)
@@ -419,21 +481,19 @@ function Movers:CreateInfoFrame()
frame:EnableMouse(true)
frame:SetMovable(true)
frame:RegisterEvent("PLAYER_REGEN_DISABLED")
- frame:SetScript("OnEvent", function(self)
- if( not ShadowUF.db.profile.locked and self:IsVisible() ) then
+ 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("OnShow", OnShow)
- frame:SetScript("OnHide", OnHide)
- frame:SetScript("OnDragStart", function(self)
- self:StartMoving()
+ frame:SetScript("OnDragStart", function(f)
+ f:StartMoving()
end)
- frame:SetScript("OnDragStop", function(self)
- self:StopMovingOrSizing()
+ frame:SetScript("OnDragStop", function(f)
+ f:StopMovingOrSizing()
end)
frame:SetBackdrop({
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
@@ -482,13 +542,13 @@ function Movers:CreateInfoFrame()
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 frame in pairs(ShadowUF.Units.frameList) do
- if( not ShadowUF.Units.childUnits[frame.unitType] and frame:GetScript("OnDragStart") and frame:GetScript("OnDragStop") ) then
- frame:GetScript("OnDragStart")(frame)
- frame:GetScript("OnDragStop")(frame)
+ 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)
diff --git a/modules/portrait.lua b/modules/portrait.lua
index 1e06f0703..9582e52c8 100755
--- a/modules/portrait.lua
+++ b/modules/portrait.lua
@@ -3,7 +3,7 @@ ShadowUF:RegisterModule(Portrait, "portrait", ShadowUF.L["Portrait"])
-- If the camera isn't reset OnShow, it'll show the entire character instead of just the head, odd I know
local function resetCamera(self)
- self:SetCamera(0)
+ self:SetPortraitZoom(1)
end
local function resetGUID(self)
@@ -13,12 +13,7 @@ end
function Portrait:OnEnable(frame)
frame:RegisterUnitEvent("UNIT_PORTRAIT_UPDATE", self, "UpdateFunc")
frame:RegisterUnitEvent("UNIT_MODEL_CHANGED", self, "Update")
-
- if( frame.unitRealType == "party" ) then
- -- frame:RegisterNormalEvent("PARTY_MEMBER_ENABLE", self, "Update")
- -- frame:RegisterNormalEvent("PARTY_MEMBER_DISABLE", self, "Update")
- end
-
+
frame:RegisterUpdateFunc(self, "UpdateFunc")
end
@@ -36,7 +31,7 @@ function Portrait:OnPreLayoutApply(frame, config)
frame.portraitModel:SetScript("OnHide", resetGUID)
frame.portraitModel.parent = frame
end
-
+
frame.portrait = frame.portraitModel
frame.portrait:Show()
@@ -57,7 +52,7 @@ function Portrait:UpdateFunc(frame)
if( frame.portrait.guid ~= guid ) then
self:Update(frame)
end
-
+
frame.portrait.guid = guid
else
self:Update(frame)
@@ -66,13 +61,16 @@ end
function Portrait:Update(frame, event)
local type = ShadowUF.db.profile.units[frame.unitType].portrait.type
-
-- Use class thingy
if( type == "class" ) then
- local classToken = select(2, UnitClass(frame.unitOwner))
+ local classToken = frame:UnitClassToken()
if( classToken ) then
- frame.portrait:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes")
- frame.portrait:SetTexCoord(CLASS_ICON_TCOORDS[classToken][1], CLASS_ICON_TCOORDS[classToken][2], CLASS_ICON_TCOORDS[classToken][3], CLASS_ICON_TCOORDS[classToken][4])
+ local classIconAtlas = GetClassAtlas(classToken)
+ if( classIconAtlas ) then
+ frame.portrait:SetAtlas(classIconAtlas)
+ else
+ frame.portrait:SetTexture("")
+ end
else
frame.portrait:SetTexture("")
end
@@ -80,15 +78,19 @@ function Portrait:Update(frame, event)
elseif( type == "2D" ) then
frame.portrait:SetTexCoord(0.10, 0.90, 0.10, 0.90)
SetPortraitTexture(frame.portrait, frame.unitOwner)
- -- Using 3D portrait, but the players not in range so swap to 2D
+ -- Using 3D portrait, but the players not in range so swap to question mark
elseif( not UnitIsVisible(frame.unitOwner) or not UnitIsConnected(frame.unitOwner) ) then
- frame.portrait:SetModelScale(4.25)
- frame.portrait:SetPosition(0, 0, -1.5)
- frame.portrait:SetModel("Interface\\Buttons\\talktomequestionmark.mdx")
+ frame.portrait:ClearModel()
+ frame.portrait:SetModelScale(5.5)
+ frame.portrait:SetPosition(0, 0, -0.8)
+ frame.portrait:SetModel("Interface\\Buttons\\talktomequestionmark.m2")
+
-- Use animated 3D portrait
else
+ frame.portrait:ClearModel()
frame.portrait:SetUnit(frame.unitOwner)
- frame.portrait:SetCamera(0)
+ frame.portrait:SetPortraitZoom(1)
+ frame.portrait:SetPosition(0, 0, 0)
frame.portrait:Show()
end
end
diff --git a/modules/power.lua b/modules/power.lua
index fcb8d19e0..74e9339ec 100755
--- a/modules/power.lua
+++ b/modules/power.lua
@@ -1,75 +1,102 @@
local Power = {}
+local powerMap = ShadowUF.Tags.powerMap
ShadowUF:RegisterModule(Power, "powerBar", ShadowUF.L["Power bar"], true)
-local function updatePower(self, elapsed)
- local currentPower = UnitPower(self.parent.unit)
- if( currentPower == self.currentPower ) then return end
- self.currentPower = currentPower
+function Power:OnEnable(frame)
+ frame.powerBar = frame.powerBar or ShadowUF.Units:CreateBar(frame)
- self:SetValue(currentPower)
- for _, fontString in pairs(self.parent.fontStrings) do
- if( fontString.fastPower ) then
- fontString:UpdateTags()
- end
+ 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
-end
-function Power:OnEnable(frame)
- frame.powerBar = frame.powerBar or ShadowUF.Units:CreateBar(frame)
-
+ -- UNIT_MANA fires after repopping at a spirit healer, make sure to update powers then
frame:RegisterUnitEvent("UNIT_MANA", self, "Update")
- frame:RegisterUnitEvent("UNIT_RAGE", self, "Update")
- frame:RegisterUnitEvent("UNIT_ENERGY", self, "Update")
- frame:RegisterUnitEvent("UNIT_FOCUS", self, "Update")
- frame:RegisterUnitEvent("UNIT_RUNIC_POWER", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXMANA", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXRAGE", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXENERGY", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXFOCUS", self, "Update")
- frame:RegisterUnitEvent("UNIT_MAXRUNIC_POWER", self, "Update")
- frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "UpdateColor")
+ frame:RegisterUpdateFunc(self, "UpdateClassification")
frame:RegisterUpdateFunc(self, "UpdateColor")
frame:RegisterUpdateFunc(self, "Update")
end
-function Power:OnLayoutApplied(frame)
- -- Enable predicted updates which requires polling in an OnUpdate to get more up to date values
- if( frame.visibility.powerBar ) then
- if( ShadowUF.db.profile.units[frame.unitType].powerBar.predicted ) then
- frame.powerBar:SetScript("OnUpdate", updatePower)
- else
- frame.powerBar:SetScript("OnUpdate", nil)
- end
- end
-end
-
function Power:OnDisable(frame)
frame:UnregisterAll(self)
end
+local altColor = {}
function Power:UpdateColor(frame)
- local color = ShadowUF.db.profile.powerColors[select(2, UnitPowerType(frame.unit))] or ShadowUF.db.profile.powerColors.MANA
-
- if( not ShadowUF.db.profile.units[frame.unitType].powerBar.invert ) then
- frame.powerBar:SetStatusBarColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
- if( not frame.powerBar.background.overrideColor ) then
- frame.powerBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
- else
- frame.powerBar.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.alpha)
+ 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
- color = frame.powerBar.background.overrideColor
+ 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
- frame.powerBar:SetStatusBarColor(0, 0, 0, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
- else
- frame.powerBar:SetStatusBarColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
+ 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)
+function Power:Update(frame, event, unit, powerType)
+ if( event and powerType and powerType ~= frame.powerBar.currentType ) then return end
+ if( frame.powerBar.minusMob ) then return end
+
frame.powerBar.currentPower = UnitPower(frame.unit)
frame.powerBar:SetMinMaxValues(0, UnitPowerMax(frame.unit))
frame.powerBar:SetValue(UnitIsDeadOrGhost(frame.unit) and 0 or not UnitIsConnected(frame.unit) and 0 or frame.powerBar.currentPower)
-end
\ No newline at end of file
+end
diff --git a/modules/priest.lua b/modules/priest.lua
new file mode 100644
index 000000000..038ea2641
--- /dev/null
+++ b/modules/priest.lua
@@ -0,0 +1,39 @@
+local Priest = {}
+ShadowUF:RegisterModule(Priest, "priestBar", ShadowUF.L["Priest mana bar"], true, "PRIEST", SPEC_PRIEST_SHADOW)
+
+function Priest:OnEnable(frame)
+ frame.priestBar = frame.priestBar or ShadowUF.Units:CreateBar(frame)
+
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "PowerChanged")
+
+ frame:RegisterUpdateFunc(self, "PowerChanged")
+ frame:RegisterUpdateFunc(self, "Update")
+end
+
+function Priest:OnDisable(frame)
+ frame:UnregisterAll(self)
+end
+
+function Priest:OnLayoutApplied(frame)
+ if( not frame.visibility.priestBar ) then return end
+
+ local color = ShadowUF.db.profile.powerColors.MANA
+ frame:SetBarColor("priestBar", color.r, color.g, color.b)
+end
+
+function Priest:PowerChanged(frame)
+ local visible = UnitPowerType(frame.unit) ~= 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 233489433..9ebe41eb1 100755
--- a/modules/range.lua
+++ b/modules/range.lua
@@ -1,87 +1,164 @@
+local GetSpellName = C_Spell.GetSpellName
+local IsSpellUsable = C_Spell.IsSpellUsable
local Range = {
- friendly = {["PRIEST"] = GetSpellInfo(2050), ["DRUID"] = GetSpellInfo(48378), ["PALADIN"] = GetSpellInfo(48782), ["SHAMAN"] = GetSpellInfo(49273)},
- hostile = {["PRIEST"] = GetSpellInfo(48127), ["DRUID"] = GetSpellInfo(48461), ["PALADIN"] = GetSpellInfo(62124), ["HUNTER"] = GetSpellInfo(75), ["WARLOCK"] = GetSpellInfo(686), ["SHAMAN"] = GetSpellInfo(529), ["MAGE"] = GetSpellInfo(133), ["DEATHKNIGHT"] = GetSpellInfo(49576)},
- resurrect = {["PALADIN"] = GetSpellInfo(48950), ["PRIEST"] = GetSpellInfo(25435), ["SHAMAN"] = GetSpellInfo(2008), ["DRUID"] = GetSpellInfo(48477)}
+ friendly = {
+ ["PRIEST"] = {
+ (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 friendlySpell, hostileSpell
-local resurrectSpell = Range.resurrect[playerClass]
-
-local function checkRange(self, elapsed)
- self.timeElapsed = self.timeElapsed + elapsed
- if( self.timeElapsed <= 0.50 ) then return end
- self.timeElapsed = 0
-
- if( self.isFriendly and resurrectSpell and UnitIsDead(self.parent.unit) ) then
- self.parent:SetRangeAlpha(IsSpellInRange(resurrectSpell, self.parent.unit) == 1 and ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha or ShadowUF.db.profile.units[self.parent.unitType].range.oorAlpha)
- -- We set a spell for them in our flags check, use that
- elseif( self.spell ) then
- self.parent:SetRangeAlpha(IsSpellInRange(self.spell, self.parent.unit) == 1 and ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha or ShadowUF.db.profile.units[self.parent.unitType].range.oorAlpha)
+local rangeSpells = {}
+
+local UnitPhaseReason_o = UnitPhaseReason
+local UnitPhaseReason = function(unit)
+ local phase = UnitPhaseReason_o(unit)
+ if (phase == Enum.PhaseReason.WarMode or phase == Enum.PhaseReason.ChromieTime or Enum.PhaseReason.TimerunningHwt) 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( self.grouped ) then
- self.parent:SetRangeAlpha(UnitInRange(self.parent.unit, "player") and ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha or ShadowUF.db.profile.units[self.parent.unitType].range.oorAlpha)
- -- Nope, fall back to interaction :(
- elseif( self.isFriendly ) then
- self.parent:SetRangeAlpha(CheckInteractDistance(self.parent.unit, 4) and ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha or ShadowUF.db.profile.units[self.parent.unitType].range.oorAlpha)
+ 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
- self.parent:SetRangeAlpha(ShadowUF.db.profile.units[self.parent.unitType].range.inAlpha)
+ 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)
- checkRange(frame.range, 1)
+ if( UnitIsUnit(frame.unit, "player") ) then
+ frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.inAlpha)
+ cancelTimer(frame)
+ else
+ createTimer(frame)
+ checkRange(frame.range.timer)
+ end
end
function Range:OnEnable(frame)
if( not frame.range ) then
frame.range = CreateFrame("Frame", nil, frame)
- frame.range:SetScript("OnUpdate", checkRange)
- frame.range.timeElapsed = 0
- frame.range.parent = frame
- frame.range:Hide()
end
-
- -- I want to say UNIT_FACTION is the function thats called when a unit is MCed, but not 100% sure
- frame:RegisterUnitEvent("UNIT_FACTION", self, "UpdateFlags")
- frame:RegisterNormalEvent("PARTY_MEMBERS_CHANGED", self, "UpdateFlags")
- frame:RegisterNormalEvent("RAID_ROSTER_UPDATE", self, "UpdateFlags")
- frame:RegisterUpdateFunc(self, "UpdateFlags")
+ frame:RegisterNormalEvent("PLAYER_SPECIALIZATION_CHANGED", self, "SpellChecks")
frame:RegisterUpdateFunc(self, "ForceUpdate")
+
+ createTimer(frame)
end
function Range:OnLayoutApplied(frame)
- if( frame.visibility.range ) then
- frame.range.hostileSpell = ShadowUF.db.profile.range["hostile" .. playerClass] or self.hostile[playerClass]
- frame.range.friendlySpell = ShadowUF.db.profile.range["friendly" .. playerClass] or self.friendly[playerClass]
- end
+ self:SpellChecks(frame)
end
function Range:OnDisable(frame)
frame:UnregisterAll(self)
-
+
if( frame.range ) then
- frame.range:Hide()
+ cancelTimer(frame)
frame:SetRangeAlpha(1.0)
end
end
--- I'd rather store the flags here, they rarely change and we can do that based off events, no sense in doing it eveyr 0.50s
-function Range:UpdateFlags(frame)
- frame.range.canAttack = UnitCanAttack("player", frame.unit)
- frame.range.isFriendly = UnitIsFriend("player", frame.unit) and UnitCanAssist("player", frame.unit)
- frame.range.grouped = UnitInRaid(frame.unit) or UnitInParty(frame.unit)
- frame.range.spell = frame.range.canAttack and frame.range.hostileSpell or frame.range.isFriendly and frame.range.friendlySpell or nil
-
- -- No sense in updating range if we have no data
- if( UnitIsGhost(frame.unit) or not UnitIsConnected(frame.unit) or ( not frame.range.spell and not frame.range.grouped and not frame.range.isFriendly ) ) then
- frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.inAlpha)
- frame.range:Hide()
- else
- frame.range:Show()
+
+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
-
-
diff --git a/modules/runes.lua b/modules/runes.lua
index e37e12dd0..c3eb4bdb1 100755
--- a/modules/runes.lua
+++ b/modules/runes.lua
@@ -1,7 +1,7 @@
local Runes = {}
-local RUNE_MAP = {[1] = 1, [2] = 2, [3] = 5, [4] = 6, [5] = 3, [6] = 4}
-local runeColors = {{r = 1, g = 0, b = 0.4}, {r = 0, g = 1, b = 0.4}, {r = 0, g = 0.4, b = 1}, {r = 0.7, g = 0.5, b = 1}}
ShadowUF:RegisterModule(Runes, "runeBar", ShadowUF.L["Rune bar"], true, "DEATHKNIGHT")
+ShadowUF.BlockTimers:Inject(Runes, "RUNE_TIMER")
+ShadowUF.DynamicBlocks:Inject(Runes)
function Runes:OnEnable(frame)
if( not frame.runeBar ) then
@@ -9,24 +9,23 @@ function Runes:OnEnable(frame)
frame.runeBar:SetMinMaxValues(0, 1)
frame.runeBar:SetValue(0)
frame.runeBar.runes = {}
-
+ frame.runeBar.blocks = frame.runeBar.runes
+
for id=1, 6 do
- local rune = ShadowUF.Units:CreateBar(frame)
- rune:SetFrameLevel(1)
-
+ local rune = ShadowUF.Units:CreateBar(frame.runeBar)
+ rune.id = id
+
if( id > 1 ) then
- rune:SetPoint("TOPLEFT", frame.runeBar.runes[RUNE_MAP[id - 1]], "TOPRIGHT", 1, 0)
+ rune:SetPoint("TOPLEFT", frame.runeBar.runes[id-1], "TOPRIGHT", 1, 0)
else
rune:SetPoint("TOPLEFT", frame.runeBar, "TOPLEFT", 0, 0)
end
-
- frame.runeBar.runes[RUNE_MAP[id]] = rune
+
+ frame.runeBar.runes[id] = rune
end
end
-
+
frame:RegisterNormalEvent("RUNE_POWER_UPDATE", self, "UpdateUsable")
- frame:RegisterNormalEvent("RUNE_TYPE_UPDATE", self, "Update")
- frame:RegisterUpdateFunc(self, "Update")
frame:RegisterUpdateFunc(self, "UpdateUsable")
end
@@ -35,50 +34,56 @@ function Runes:OnDisable(frame)
end
function Runes:OnLayoutApplied(frame)
- if( frame.visibility.runeBar ) then
- local barWidth = (frame.runeBar:GetWidth() - 5) / 6
-
- for id, rune in pairs(frame.runeBar.runes) do
- if( ShadowUF.db.profile.units[frame.unitType].runeBar.background ) then
- rune.background:Show()
- else
- rune.background:Hide()
- end
-
- rune.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
- rune.background:SetHorizTile(false)
- rune:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
- rune:GetStatusBarTexture():SetHorizTile(false)
- rune:SetHeight(frame.runeBar:GetHeight())
- rune:SetWidth(barWidth)
+ if( not frame.visibility.runeBar ) then return end
+
+ local barWidth = (frame.runeBar:GetWidth() - 5) / 6
+ for id, rune in pairs(frame.runeBar.runes) do
+ if( ShadowUF.db.profile.units[frame.unitType].runeBar.background ) then
+ rune.background:Show()
+ else
+ rune.background:Hide()
end
+
+ rune.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
+ rune.background:SetHorizTile(false)
+ rune:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
+ rune:GetStatusBarTexture():SetHorizTile(false)
+ rune:SetWidth(barWidth)
+
+ local color = ShadowUF.db.profile.powerColors.RUNES
+ frame:SetBlockColor(rune, "runeBar", color.r, color.g, color.b)
end
end
local function runeMonitor(self, elapsed)
local time = GetTime()
self:SetValue(time)
-
+
if( time >= self.endTime ) then
self:SetValue(self.endTime)
self:SetAlpha(1.0)
self:SetScript("OnUpdate", nil)
+ self.endTime = nil
+ end
+
+ if( self.fontString ) then
+ self.fontString:UpdateTags()
end
end
-- Updates the timers on runes
function Runes:UpdateUsable(frame, event, id, usable)
- if( not id ) then
- self:UpdateColors(frame)
- return
- elseif( not frame.runeBar.runes[id] ) then
+ if( not id or not frame.runeBar.runes[id] ) then
return
end
-
+
local rune = frame.runeBar.runes[id]
local startTime, cooldown, cooled = GetRuneCooldown(id)
+ -- Blizzard changed something with this API apparently and now it can be true/false/nil
+ if( cooled == nil ) then return end
+
if( not cooled ) then
- rune.endTime = GetTime() + cooldown
+ rune.endTime = startTime + cooldown
rune:SetMinMaxValues(startTime, rune.endTime)
rune:SetValue(GetTime())
rune:SetAlpha(0.40)
@@ -88,28 +93,10 @@ function Runes:UpdateUsable(frame, event, id, usable)
rune:SetValue(1)
rune:SetAlpha(1.0)
rune:SetScript("OnUpdate", nil)
+ rune.endTime = nil
end
-end
-
-function Runes:UpdateColors(frame)
- for id, rune in pairs(frame.runeBar.runes) do
- local color = runeColors[GetRuneType(id)]
- if( color ) then
- rune:SetStatusBarColor(color.r, color.g, color.b)
-
- color = ShadowUF.db.profile.bars.backgroundColor or ShadowUF.db.profile.units[frame.unitType].runeBar.backgroundColor or color
- rune.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
- end
- end
-end
-
--- No rune is passed for full update (Login), a single rune is passed when a single rune type changes, such as Blood Tap
-function Runes:Update(frame, event, id)
- if( id ) then
- local color = runeColors[GetRuneType(id)]
- frame.runeBar.runes[id]:SetStatusBarColor(color.r, color.g, color.b)
- color = ShadowUF.db.profile.bars.backgroundColor or ShadowUF.db.profile.units[frame.unitType].runeBar.backgroundColor or color
- frame.runeBar.runes[id].background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
+ if( rune.fontString ) then
+ rune.fontString:UpdateTags()
end
end
diff --git a/modules/shaman.lua b/modules/shaman.lua
new file mode 100644
index 000000000..f2b5071f9
--- /dev/null
+++ b/modules/shaman.lua
@@ -0,0 +1,39 @@
+local Shaman = {}
+ShadowUF:RegisterModule(Shaman, "shamanBar", ShadowUF.L["Shaman mana bar"], true, "SHAMAN")
+
+function Shaman:OnEnable(frame)
+ frame.shamanBar = frame.shamanBar or ShadowUF.Units:CreateBar(frame)
+
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "PowerChanged")
+
+ frame:RegisterUpdateFunc(self, "PowerChanged")
+ frame:RegisterUpdateFunc(self, "Update")
+end
+
+function Shaman:OnDisable(frame)
+ frame:UnregisterAll(self)
+end
+
+function Shaman:OnLayoutApplied(frame)
+ if( not frame.visibility.shamanBar ) then return end
+
+ local color = ShadowUF.db.profile.powerColors.MANA
+ frame:SetBarColor("shamanBar", color.r, color.g, color.b)
+end
+
+function Shaman:PowerChanged(frame)
+ local visible = UnitPowerType(frame.unit) ~= 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
new file mode 100755
index 000000000..8561f8056
--- /dev/null
+++ b/modules/soulshards.lua
@@ -0,0 +1,47 @@
+if( not ShadowUF.ComboPoints ) then return end
+
+local Souls = setmetatable({}, {__index = ShadowUF.ComboPoints})
+ShadowUF:RegisterModule(Souls, "soulShards", ShadowUF.L["Soul Shards"], nil, "WARLOCK")
+local soulsConfig = {max = 5, key = "soulShards", colorKey = "SOULSHARDS", powerType = Enum.PowerType.SoulShards, eventType = "SOUL_SHARDS", icon = "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\shard"}
+
+function Souls:OnEnable(frame)
+ frame.soulShards = frame.soulShards or CreateFrame("Frame", nil, frame)
+ frame.soulShards.cpConfig = soulsConfig
+ frame.soulShards.cpConfig.max = (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION) and 50 or 5
+ frame.soulShards.cpConfig.grouping = (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION) and UnitPowerDisplayMod(soulsConfig.powerType) or 1
+ frame.comboPointType = soulsConfig.key
+
+ frame:RegisterUnitEvent("UNIT_POWER_FREQUENT", self, "Update")
+ frame:RegisterUnitEvent("UNIT_MAXPOWER", self, "UpdateBarBlocks")
+ frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "Update")
+ frame:RegisterNormalEvent("PLAYER_SPECIALIZATION_CHANGED", self, "SpecChanged")
+
+ frame:RegisterUpdateFunc(self, "Update")
+ frame:RegisterUpdateFunc(self, "UpdateBarBlocks")
+end
+
+function Souls:OnLayoutApplied(frame, config)
+ ShadowUF.ComboPoints.OnLayoutApplied(self, frame, config)
+ self:UpdateBarBlocks(frame)
+end
+
+function Souls:SpecChanged(frame)
+ -- update shard count on spec swap
+ if frame and frame.soulShards then
+ frame.soulShards.cpConfig.max = (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION) and 50 or 5
+ frame.soulShards.cpConfig.grouping = (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION) and UnitPowerDisplayMod(soulsConfig.powerType) or 1
+ end
+ self:UpdateBarBlocks(frame)
+end
+
+function Souls:GetComboPointType()
+ return "soulShards"
+end
+
+function Souls:GetPoints(unit)
+ return UnitPower("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION))
+end
+
+function Souls:GetMaxPoints(unit)
+ return UnitPowerMax("player", soulsConfig.powerType, (GetSpecialization() == SPEC_WARLOCK_DESTRUCTION))
+end
diff --git a/modules/tags.lua b/modules/tags.lua
old mode 100644
new mode 100755
index 9000d6e72..a6fed25ff
--- a/modules/tags.lua
+++ b/modules/tags.lua
@@ -1,12 +1,37 @@
--- Thanks to haste for the original tagging code, which I then mostly ripped apart and stole!
-local Tags = {afkStatus = {}, offlineStatus = {}, customEvents = {}}
-local tagPool, functionPool, temp, regFontStrings, frequentUpdates, frequencyCache = {}, {}, {}, {}, {}, {}
+local 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 )
@@ -14,36 +39,78 @@ function Tags:RegisterEvents(parent, fontString, tags)
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
- if( self.customEvents[event] ) then
+ -- Power filter event, store it instead
+ if( powerFilters[event] ) then
+ fontString.powerFilters = fontString.powerFilters or {}
+ fontString.powerFilters[powerFilters[event]] = true
+
+ if( powerFilters[event] == "CURRENT" ) then
+ if( not hasPowerFilters ) then
+ parent:RegisterUnitEvent("UNIT_DISPLAYPOWER", self, "UpdatePowerType")
+ parent:RegisterUpdateFunc(self, "UpdatePowerType")
+ end
+
+ hasPowerFilters = true
+ end
+
+ -- Custom event registered by another module
+ elseif( self.customEvents[event] ) then
self.customEvents[event]:EnableTag(parent, fontString)
fontString[event] = true
+ -- Unit event
elseif( Tags.eventType[event] ~= "unitless" or ShadowUF.Units.unitEvents[event] ) then
- parent:RegisterUnitEvent(event, fontString, "UpdateTags")
+ local success, err = pcall(parent.RegisterUnitEvent, parent, event, fontString, "UpdateTags")
+ if not success then
+ -- switch the tag back
+ ShadowUF.Units.unitEvents[event] = false
+ Tags.eventType[event] = "unitless"
+
+ parent:RegisterNormalEvent(event, fontString, "UpdateTags")
+ end
+ -- Everything else
else
parent:RegisterNormalEvent(event, fontString, "UpdateTags")
end
-
- -- The power and health bars will handle updating tags with this flag set
- fontString.fastPower = fontString.fastPower or Tags.eventType[event] == "power"
- fontString.fastHealth = fontString.fastHealth or Tags.eventType[event] == "health"
+
+ -- register UNIT_MANA event since its the only event that fires after repopping at a spirit healer
+ if event == "UNIT_POWER_UPDATE" or event == "UNIT_POWER_FREQUENT" then
+ parent:RegisterUnitEvent("UNIT_MANA", fontString, "UpdateTags")
+
+ if ( parent.unit == "player" ) then
+ parent:RegisterNormalEvent("PLAYER_UNGHOST", fontString, "UpdateTags")
+ end
+ end
end
end
end
end
+-- Update the cached power type
+function Tags:UpdatePowerType(frame)
+ local powerID, powerType = UnitPowerType(frame.unit)
+ if( not powerMap[powerType] ) then powerType = powerMap[powerID] or "ENERGY" end
+
+ for _, fontString in pairs(frame.fontStrings) do
+ if( fontString.UpdateTags ) then
+ fontString.powerType = powerType
+ fontString:UpdateTags()
+ end
+ end
+end
+
-- This pretty much means a tag was updated in some way (or deleted) so we have to do a full update to get the new values shown
function Tags:Reload()
-- Kill cached functions, ugly I know but it ensures its fully updated with the new data
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)
@@ -52,119 +119,162 @@ function Tags:Reload()
end
end
--- Frequent updates
-local freqFrame = CreateFrame("Frame")
-freqFrame:SetScript("OnUpdate", function(self, elapsed)
- for fontString, timeLeft in pairs(frequentUpdates) do
- if( fontString.parent:IsVisible() ) then
- frequentUpdates[fontString] = timeLeft - elapsed
- if( frequentUpdates[fontString] <= 0 ) then
- frequentUpdates[fontString] = fontString.frequentStart
- fontString:UpdateTags()
- end
+-- This is for bars that can be shown or hidden often, like druid power
+function Tags:FastRegister(frame, parent)
+ if( not frame.fontStrings ) then return end
+
+ for _, fontString in pairs(frame.fontStrings) do
+ -- Re-register anything that was already registered and is part of the parent
+ if( regFontStrings[fontString] and ( not parent or fontString.parentBar == parent ) ) then
+ fontString.UpdateTags = tagPool[regFontStrings[fontString]]
+ fontString:Show()
end
end
-end)
-freqFrame:Hide()
+end
--- Register a font string with the tag system
-function Tags:Register(parent, fontString, tags, resetCache)
- -- Unregister the font string first if we did register it already
- if( fontString.UpdateTags ) then
- self:Unregister(fontString)
+function Tags:FastUnregister(frame, parent)
+ if( not frame.fontStrings ) then return end
+
+ for _, fontString in pairs(frame.fontStrings) do
+ -- Redirect the updates to not do anything and hide it
+ if( regFontStrings[fontString] and ( not parent or fontString.parentBar == parent ) ) then
+ fontString.UpdateTags = ShadowUF.noop
+ fontString:Hide()
+ end
end
-
- fontString.parent = parent
- regFontStrings[fontString] = tags
-
- -- Use the cached polling time if we already saved it
- -- as we won't be rececking everything next call
- local pollTime = frequencyCache[tags]
- if( pollTime ) then
- frequentUpdates[fontString] = pollTime
- fontString.frequentStart = pollTime
- freqFrame:Show()
+end
+
+
+-- Register a font string with the tag system
+local powerEvents = {["UNIT_POWER_UPDATE"] = true, ["UNIT_POWER_FREQUENT"] = true, ["UNIT_MAXPOWER"] = true}
+local frequencyCache = {}
+local function createTagFunction(tags, resetCache)
+ if( tagPool[tags] and not resetCache ) then
+ return tagPool[tags], frequencyCache[tags]
end
-
- local updateFunc = not resetCache and tagPool[tags]
- if( not updateFunc ) then
- -- Using .- prevents supporting tags such as [foo ([)]. Supporting that and having a single pattern
- local formattedText = string.gsub(string.gsub(tags, "%%", "%%%%"), "[[].-[]]", "%%s")
- local args = {}
-
- for tag in string.gmatch(tags, "%[(.-)%]") do
- -- Tags that use pre or appends "foo(|)" etc need special matching, which is what this will handle
- local cachedFunc = not resetCache and functionPool[tag] or ShadowUF.tagFunc[tag]
- if( not cachedFunc ) then
- local hasPre, hasAp = true, true
- local tagKey = select(2, string.match(tag, "(%b())([%w%p]+)(%b())"))
- if( not tagKey ) then hasPre, hasAp = true, false tagKey = select(2, string.match(tag, "(%b())([%w%p]+)")) end
- if( not tagKey ) then hasPre, hasAp = false, true tagKey = string.match(tag, "([%w%p]+)(%b())") end
-
- frequencyCache[tag] = tagKey and (self.defaultFrequents[tagKey] or ShadowUF.db.profile.tags[tagKey] and ShadowUF.db.profile.tags[tagKey].frequency)
- local tagFunc = tagKey and ShadowUF.tagFunc[tagKey]
- if( tagFunc ) then
- local startOff, endOff = string.find(tag, tagKey)
- local pre = hasPre and string.sub(tag, 2, startOff - 2)
- local ap = hasAp and string.sub(tag, endOff + 2, -2)
-
- if( pre and ap ) then
- cachedFunc = function(...)
- local str = tagFunc(...)
- if( str ) then return pre .. str .. ap end
- end
- elseif( pre ) then
- cachedFunc = function(...)
- local str = tagFunc(...)
- if( str ) then return pre .. str end
- end
- elseif( ap ) then
- cachedFunc = function(...)
- local str = tagFunc(...)
- if( str ) then return str .. ap end
- end
+
+ -- 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
-
- functionPool[tag] = cachedFunc
end
+
+ functionPool[tag] = cachedFunc
end
-
- -- Figure out what the lowest update frequency for this font string and use it
- local pollTime = self.defaultFrequents[tag] or frequencyCache[tag]
- if( ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].frequency ) then
- pollTime = ShadowUF.db.profile.tags[tag].frequency
- end
-
- if( pollTime and ( not fontString.frequentStart or fontString.frequentStart > pollTime ) ) then
- frequencyCache[tags] = pollTime
- frequentUpdates[fontString] = pollTime
- fontString.frequentStart = pollTime
- freqFrame:Show()
- end
-
- -- It's an invalid tag, simply return the tag itself wrapped in brackets
- if( not cachedFunc ) then
- functionPool[tag] = functionPool[tag] or function() return string.format("[%s-error]", tag) end
- cachedFunc = functionPool[tag]
- end
-
- table.insert(args, cachedFunc)
- end
-
- -- Create our update function now
- updateFunc = function(fontString)
- for id, func in pairs(args) do
- temp[id] = func(fontString.parent.unit, fontString.parent.unitOwner, fontString) or ""
+ 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
-
- fontString:SetFormattedText(formattedText, unpack(temp))
end
- tagPool[tags] = updateFunc
+ for id, func in pairs(args) do
+ temp[id] = func(fontString.parent.unit, fontString.parent.unitOwner, fontString) or ""
+ end
+
+ fontString:SetFormattedText(formattedText, unpack(temp))
+ end
+
+ return tagPool[tags], frequencyCache[tags]
+end
+
+local function createMonitorTimer(fontString, frequency)
+ if( not fontString.monitor or fontString.monitor.frequency ~= frequency ) then
+ if fontString.monitor then
+ fontString.monitor:Cancel()
+ end
+ fontString.monitor = C_Timer.NewTicker(frequency, function() fontString:UpdateTags() end)
+ fontString.monitor.frequency = frequency
+ end
+end
+
+local function cancelMonitorTimer(fontString)
+ if( fontString.monitor ) then
+ fontString.monitor:Cancel()
+ fontString.monitor = nil
end
-
+end
+
+function Tags:Register(parent, fontString, tags, resetCache)
+ -- Unregister the font string first if we did register it already
+ if( fontString.UpdateTags ) then
+ self:Unregister(fontString)
+ end
+
+ fontString.parent = parent
+ regFontStrings[fontString] = tags
+
-- And give other frames an easy way to force an update
- fontString.UpdateTags = updateFunc
+ local frequency
+ fontString.UpdateTags, frequency = createTagFunction(tags, resetCache)
+
+ if( frequency ) then
+ createMonitorTimer(fontString, frequency)
+ elseif( fontString.monitor ) then
+ cancelMonitorTimer(fontString)
+ end
-- Register any needed event
self:RegisterEvents(parent, fontString, tags)
@@ -172,19 +282,7 @@ end
function Tags:Unregister(fontString)
regFontStrings[fontString] = nil
- frequentUpdates[fontString] = nil
-
- -- Kill frequent updates if they aren't needed anymore
- local hasFrequent
- for k in pairs(frequentUpdates) do
- hasFrequent = true
- break
- end
-
- if( not hasFrequent ) then
- freqFrame:Hide()
- end
-
+
-- Unregister it as using HC
for key, module in pairs(self.customEvents) do
if( fontString[key] ) then
@@ -192,14 +290,28 @@ function Tags:Unregister(fontString)
module:DisableTag(fontString.parent, fontString)
end
end
-
+
-- Kill any tag data
+ cancelMonitorTimer(fontString)
fontString.parent:UnregisterAll(fontString)
- fontString.fastPower = nil
- fontString.fastHealth = nil
- fontString.frequentStart = nil
+ fontString.powerFilters = nil
fontString.UpdateTags = nil
fontString:SetText("")
+
+ -- See if we need to unregister events
+ local parent = fontString.parent
+ local hasPowerFilter
+ for _, 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.
@@ -223,7 +335,7 @@ function ShadowUF:FormatLargeNumber(number)
elseif( number < 99999999 ) then
return string.format("%.2fm", number / 1000000)
end
-
+
return string.format("%dm", number / 1000000)
end
@@ -233,7 +345,7 @@ function ShadowUF:SmartFormatNumber(number)
elseif( number < 99999999 ) then
return string.format("%.2fm", number / 1000000)
end
-
+
return string.format("%dm", number / 1000000)
end
@@ -241,7 +353,7 @@ 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
@@ -258,7 +370,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({}, {
@@ -270,58 +382,65 @@ end})
-- Going to have to start using an env wrapper for tags I think
local Druid = {}
-Druid.CatForm, Druid.Shapeshift = GetSpellInfo(768)
-Druid.MoonkinForm = GetSpellInfo(24858)
-Druid.TravelForm = GetSpellInfo(783)
-Druid.BearForm = GetSpellInfo(5487)
-Druid.TreeForm = GetSpellInfo(33891)
-Druid.DireBearForm = GetSpellInfo(9634)
-Druid.AquaticForm = GetSpellInfo(1066)
-Druid.SwiftFlightForm = GetSpellInfo(40120)
-Druid.FlightForm = GetSpellInfo(33943)
+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( UnitAura(unit, Druid.CatForm, Druid.Shapeshift) ) then
+ if( ShadowUF.UnitAuraBySpell(unit, Druid.CatForm) ) then
return ShadowUF.L["C"]
- elseif( UnitAura(unit, Druid.TreeForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TreeForm) ) then
return ShadowUF.L["T"]
- elseif( UnitAura(unit, Druid.MoonkinForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.MoonkinForm) ) then
return ShadowUF.L["M"]
- elseif( UnitAura(unit, Druid.DireBearForm, Druid.Shapeshift) or UnitAura(unit, Druid.BearForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.BearForm) ) then
return ShadowUF.L["B"]
- elseif( UnitAura(unit, Druid.SwiftFlightForm, Druid.Shapeshift) or UnitAura(unit, Druid.FlightForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.SwiftFlightForm) or ShadowUF.UnitAuraBySpell(unit, Druid.FlightForm) ) then
return ShadowUF.L["F"]
- elseif( UnitAura(unit, Druid.TravelForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TravelForm) ) then
return ShadowUF.L["T"]
- elseif( UnitAura(unit, Druid.AquaticForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.AquaticForm) ) then
return ShadowUF.L["A"]
end
end]],
["druidform"] = [[function(unit, unitOwner)
if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end
-
+
local Druid = ShadowUF.Druid
- if( UnitAura(unit, Druid.CatForm, Druid.Shapeshift) ) then
+ if( ShadowUF.UnitAuraBySpell(unit, Druid.CatForm) ) then
return ShadowUF.L["Cat"]
- elseif( UnitAura(unit, Druid.TreeForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TreeForm) ) then
return ShadowUF.L["Tree"]
- elseif( UnitAura(unit, Druid.MoonkinForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.MoonkinForm) ) then
return ShadowUF.L["Moonkin"]
- elseif( UnitAura(unit, Druid.DireBearForm, Druid.Shapeshift) or UnitAura(unit, Druid.BearForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.BearForm) ) then
return ShadowUF.L["Bear"]
- elseif( UnitAura(unit, Druid.SwiftFlightForm, Druid.Shapeshift) or UnitAura(unit, Druid.FlightForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.SwiftFlightForm) or ShadowUF.UnitAuraBySpell(unit, Druid.FlightForm) ) then
return ShadowUF.L["Flight"]
- elseif( UnitAura(unit, Druid.TravelForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.TravelForm) ) then
return ShadowUF.L["Travel"]
- elseif( UnitAura(unit, Druid.AquaticForm, Druid.Shapeshift) ) then
+ elseif( ShadowUF.UnitAuraBySpell(unit, Druid.AquaticForm) ) then
return ShadowUF.L["Aquatic"]
end
end]],
@@ -354,22 +473,22 @@ Tags.defaultTags = {
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)
@@ -392,7 +511,7 @@ Tags.defaultTags = {
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)
@@ -401,26 +520,26 @@ Tags.defaultTags = {
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)
@@ -448,7 +567,7 @@ Tags.defaultTags = {
color = ShadowUF.db.profile.healthColors.hostile
end
end
-
+
return color and ShadowUF:Hex(color)
end]],
["class"] = [[function(unit, unitOwner)
@@ -473,16 +592,16 @@ Tags.defaultTags = {
if( not color ) then
return name
end
-
+
return string.format("%s%s|r", color, name)
end]],
- ["curpp"] = [[function(unit, unitOwner)
+ ["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)
@@ -493,7 +612,7 @@ Tags.defaultTags = {
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)
@@ -504,7 +623,7 @@ Tags.defaultTags = {
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)
@@ -515,7 +634,7 @@ Tags.defaultTags = {
elseif( not UnitIsConnected(unit) ) then
return ShadowUF.L["Offline"]
end
-
+
return string.format("%s/%s", UnitHealth(unit), UnitHealthMax(unit))
end]],
["abscurhp"] = [[function(unit, unitOwner)
@@ -526,7 +645,7 @@ Tags.defaultTags = {
elseif( not UnitIsConnected(unit) ) then
return ShadowUF.L["Offline"]
end
-
+
return UnitHealth(unit)
end]],
["absmaxhp"] = [[function(unit, unitOwner) return UnitHealthMax(unit) end]],
@@ -535,8 +654,8 @@ Tags.defaultTags = {
return nil
elseif( UnitIsDeadOrGhost(unit) ) then
return 0
- end
-
+ end
+
return UnitPower(unit)
end]],
["absmaxpp"] = [[function(unit, unitOwner)
@@ -551,7 +670,7 @@ Tags.defaultTags = {
elseif( maxPower <= 0 ) then
return nil
end
-
+
return string.format("%s/%s", power, maxPower)
end]],
["curmaxpp"] = [[function(unit, unitOwner)
@@ -562,7 +681,7 @@ Tags.defaultTags = {
elseif( maxPower <= 0 ) then
return nil
end
-
+
return string.format("%s/%s", ShadowUF:FormatLargeNumber(power), ShadowUF:FormatLargeNumber(maxPower))
end]],
["smart:curmaxpp"] = [[function(unit, unitOwner)
@@ -573,29 +692,37 @@ Tags.defaultTags = {
elseif( maxPower <= 0 ) then
return nil
end
-
+
return string.format("%s/%s", ShadowUF:SmartFormatNumber(power), ShadowUF:SmartFormatNumber(maxPower))
end]],
["levelcolor"] = [[function(unit, unitOwner)
- local level = UnitLevel(unit)
+ 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
+ return level > 0 and level or "??"
end
end]],
["faction"] = [[function(unit, unitOwner) return UnitFactionGroup(unitOwner) end]],
["level"] = [[function(unit, unitOwner)
- local level = UnitLevel(unit)
+ 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]],
@@ -606,7 +733,7 @@ Tags.defaultTags = {
elseif( UnitIsDeadOrGhost(unit) ) then
return 0
end
-
+
return ShadowUF:FormatLargeNumber(power)
end]],
["missinghp"] = [[function(unit, unitOwner)
@@ -620,7 +747,7 @@ Tags.defaultTags = {
local missing = UnitHealthMax(unit) - UnitHealth(unit)
if( missing <= 0 ) then return nil end
- return "-" .. ShadowUF:FormatLargeNumber(missing)
+ return "-" .. ShadowUF:FormatLargeNumber(missing)
end]],
["missingpp"] = [[function(unit, unitOwner)
local power = UnitPowerMax(unit)
@@ -635,12 +762,16 @@ Tags.defaultTags = {
["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)
@@ -648,7 +779,7 @@ Tags.defaultTags = {
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)
@@ -658,7 +789,7 @@ Tags.defaultTags = {
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]],
@@ -675,13 +806,29 @@ Tags.defaultTags = {
return ShadowUF.L["Offline"]
end
end]],
+ ["sshards"] = [[function(unit, unitOwner)
+ local points = UnitPower(ShadowUF.playerUnit, Enum.PowerType.SoulShards)
+ return points and points > 0 and points
+ end]],
+ ["hpower"] = [[function(unit, unitOwner)
+ local points = UnitPower(ShadowUF.playerUnit, Enum.PowerType.HolyPower)
+ return points and points > 0 and points
+ end]],
+ ["monk:chipoints"] = [[function(unit, unitOwner)
+ local points = UnitPower(ShadowUF.playerUnit, Enum.PowerType.Chi)
+ return points and points > 0 and points
+ end]],
["cpoints"] = [[function(unit, unitOwner)
- local points = GetComboPoints(ShadowUF.playerUnit)
- if( points == 0 ) then
- points = GetComboPoints(ShadowUF.playerUnit, ShadowUF.playerUnit)
+ if( UnitHasVehicleUI("player") and UnitHasVehiclePlayerFrameUI("player") ) then
+ local points = GetComboPoints("vehicle")
+ if( points == 0 ) then
+ points = GetComboPoints("vehicle", "vehicle")
+ end
+
+ return points
+ else
+ return UnitPower("player", Enum.PowerType.ComboPoints)
end
-
- return points > 0 and points
end]],
["smartlevel"] = [[function(unit, unitOwner)
local classif = UnitClassification(unit)
@@ -697,7 +844,14 @@ Tags.defaultTags = {
end
end
end]],
- ["dechp"] = [[function(unit, unitOwner) return string.format("%.1f%%", (UnitHealth(unit) / UnitHealthMax(unit)) * 100) end]],
+ ["dechp"] = [[function(unit, unitOwner)
+ local maxHealth = UnitHealthMax(unit)
+ if( maxHealth <= 0 ) then
+ return "0.0%"
+ end
+
+ return string.format("%.1f%%", (UnitHealth(unit) / maxHealth) * 100)
+ end]],
["classification"] = [[function(unit, unitOwner)
local classif = UnitClassification(unit)
if( classif == "rare" ) then
@@ -708,164 +862,287 @@ Tags.defaultTags = {
return ShadowUF.L["Elite"]
elseif( classif == "worldboss" ) then
return ShadowUF.L["Boss"]
+ elseif( classif == "minus" ) then
+ return ShadowUF.L["Minion"]
end
-
+
return nil
end]],
["shortclassification"] = [[function(unit, unitOwner)
local classif = UnitClassification(unit)
- return classif == "rare" and "R" or classif == "rareelite" and "R+" or classif == "elite" and "+" or classif == "worldboss" and "B"
+ return classif == "rare" and "R" or classif == "rareelite" and "R+" or classif == "elite" and "+" or classif == "worldboss" and "B" or classif == "minus" and "M"
end]],
["group"] = [[function(unit, unitOwner)
- if( GetNumRaidMembers() == 0 ) then return nil end
+ if( not UnitInRaid(unitOwner) ) then return nil end
local name, server = UnitName(unitOwner)
if( server and server ~= "" ) then
name = string.format("%s-%s", name, server)
end
-
- for i=1, GetNumRaidMembers() do
+
+ for i=1, GetNumGroupMembers() do
local raidName, _, group = GetRaidRosterInfo(i)
if( raidName == name ) then
return group
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 ~= 1 and powerType ~= 3 ) then return nil end
- return ShadowUF:FormatLargeNumber(UnitPower(unit, 0))
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ return ShadowUF:FormatLargeNumber(UnitPower(unit, Enum.PowerType.Mana))
end]],
["druid:abscurpp"] = [[function(unit, unitOwner)
if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end
local powerType = UnitPowerType(unit)
- if( powerType ~= 1 and powerType ~= 3 ) then return nil end
- return UnitPower(unit, 0)
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ return UnitPower(unit, Enum.PowerType.Mana)
end]],
["druid:curmaxpp"] = [[function(unit, unitOwner)
if( select(2, UnitClass(unit)) ~= "DRUID" ) then return nil end
local powerType = UnitPowerType(unit)
- if( powerType ~= 1 and powerType ~= 3 ) then return nil end
-
- local maxPower = UnitPowerMax(unit, 0)
- local power = UnitPower(unit, 0)
+ 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 ~= 1 and powerType ~= 3 ) then return nil end
- return UnitPower(unit, 0)
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+
+ return UnitPower(unit, Enum.PowerType.Mana)
+ end]],
+ ["sec:curpp"] = [[function(unit, unitOwner)
+ local class = select(2, UnitClass(unit))
+ local powerType = UnitPowerType(unit)
+ if( class == "DRUID" ) then
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ elseif( class == "PRIEST" ) then
+ if( powerType ~= Enum.PowerType.Insanity ) then return nil end
+ elseif( class == "SHAMAN" ) then
+ if( powerType ~= Enum.PowerType.Maelstrom ) then return nil end
+ else
+ return nil
+ end
+ return ShadowUF:FormatLargeNumber(UnitPower(unit, Enum.PowerType.Mana))
+ end]],
+ ["sec:abscurpp"] = [[function(unit, unitOwner)
+ local class = select(2, UnitClass(unit))
+ local powerType = UnitPowerType(unit)
+ if( class == "DRUID" ) then
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ elseif( class == "PRIEST" ) then
+ if( powerType ~= Enum.PowerType.Insanity ) then return nil end
+ elseif( class == "SHAMAN" ) then
+ if( powerType ~= Enum.PowerType.Maelstrom ) then return nil end
+ else
+ return nil
+ end
+ return UnitPower(unit, Enum.PowerType.Mana)
+ end]],
+ ["sec:curmaxpp"] = [[function(unit, unitOwner)
+ local class = select(2, UnitClass(unit))
+ local powerType = UnitPowerType(unit)
+ if( class == "DRUID" ) then
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ elseif( class == "PRIEST" ) then
+ if( powerType ~= Enum.PowerType.Insanity ) then return nil end
+ elseif( class == "SHAMAN" ) then
+ if( powerType ~= Enum.PowerType.Maelstrom ) then return nil end
+ else
+ return nil
+ end
+
+ local maxPower = UnitPowerMax(unit, Enum.PowerType.Mana)
+ local power = UnitPower(unit, Enum.PowerType.Mana)
+ if( UnitIsDeadOrGhost(unit) ) then
+ return string.format("0/%s", ShadowUF:FormatLargeNumber(maxPower))
+ elseif( maxPower == 0 and power == 0 ) then
+ return nil
+ end
+
+ return string.format("%s/%s", ShadowUF:FormatLargeNumber(power), ShadowUF:FormatLargeNumber(maxPower))
+ end]],
+ ["sec:absolutepp"] = [[function(unit, unitOwner)
+ local class = select(2, UnitClass(unit))
+ local powerType = UnitPowerType(unit)
+ if( class == "DRUID" ) then
+ if( powerType ~= Enum.PowerType.Rage and powerType ~= Enum.PowerType.Energy and powerType ~= Enum.PowerType.LunarPower ) then return nil end
+ elseif( class == "PRIEST" ) then
+ if( powerType ~= Enum.PowerType.Insanity ) then return nil end
+ elseif( class == "SHAMAN" ) then
+ if( powerType ~= Enum.PowerType.Maelstrom ) then return nil end
+ else
+ return nil
+ end
+
+ return UnitPower(unit, Enum.PowerType.Mana)
+ end]],
+ ["per:incheal"] = [[function(unit, unitOwner, fontString)
+ local heal = UnitGetIncomingHeals(unit)
+ local maxHealth = UnitHealthMax(unit)
+ return heal and heal > 0 and maxHealth > 0 and string.format("%d%%", (heal / maxHealth) * 100)
end]],
["abs:incheal"] = [[function(unit, unitOwner, fontString)
- return fontString.incoming and string.format("%d", fontString.incoming)
+ local heal = UnitGetIncomingHeals(unit)
+ return heal and heal > 0 and string.format("%d", heal)
end]],
["incheal"] = [[function(unit, unitOwner, fontString)
- return fontString.incoming and ShadowUF:FormatLargeNumber(fontString.incoming) or nil
+ local heal = UnitGetIncomingHeals(unit)
+ return heal and heal > 0 and ShadowUF:FormatLargeNumber(heal)
end]],
["incheal:name"] = [[function(unit, unitOwner, fontString)
- return fontString.incoming and string.format("+%d", fontString.incoming) or ShadowUF.tagFunc.name(unit, unitOwner)
+ local heal = UnitGetIncomingHeals(unit)
+ return heal and heal > 0 and string.format("+%d", heal) or ShadowUF.tagFunc.name(unit, unitOwner, fontString)
+ end]],
+ ["monk:abs:stagger"] = [[function(unit, unitOwner)
+ local stagger = UnitStagger(unit)
+ return stagger and stagger > 0 and stagger
+ end]],
+ ["monk:stagger"] = [[function(unit, unitOwner)
+ local stagger = UnitStagger(unit)
+ return stagger and stagger > 0 and ShadowUF:FormatLargeNumber(stagger)
+ end]],
+ ["abs:incabsorb"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalAbsorbs(unit)
+ return absorb and absorb > 0 and absorb
+ end]],
+ ["incabsorb"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalAbsorbs(unit)
+ return absorb and absorb > 0 and ShadowUF:FormatLargeNumber(absorb)
+ end]],
+ ["incabsorb:name"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalAbsorbs(unit)
+ return absorb and absorb > 0 and string.format("+%d", absorb) or ShadowUF.tagFunc.name(unit, unitOwner, fontString)
+ end]],
+ ["abs:healabsorb"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalHealAbsorbs(unit)
+ return absorb and absorb > 0 and absorb
+ end]],
+ ["healabsorb"] = [[function(unit, unitOwner, fontString)
+ local absorb = UnitGetTotalHealAbsorbs(unit)
+ return absorb and absorb > 0 and ShadowUF:FormatLargeNumber(absorb)
end]],
["unit:raid:targeting"] = [[function(unit, unitOwner, fontString)
- if( GetNumRaidMembers() == 0 ) then return nil end
+ if( GetNumGroupMembers() == 0 ) then return nil end
local guid = UnitGUID(unit)
if( not guid ) then return "0" end
-
+
local total = 0
- for i=1, GetNumRaidMembers() do
+ for i=1, GetNumGroupMembers() do
local unit = ShadowUF.raidUnits[i]
if( UnitGUID(ShadowUF.unitTarget[unit]) == guid ) then
total = total + 1
end
- end
+ end
return total
end]],
["unit:raid:assist"] = [[function(unit, unitOwner, fontString)
- if( GetNumRaidMembers() == 0 ) then return nil end
+ if( GetNumGroupMembers() == 0 ) then return nil end
local guid = UnitGUID(ShadowUF.unitTarget[unit])
if( not guid ) then return "--" end
-
+
local total = 0
- for i=1, GetNumRaidMembers() do
+ for i=1, GetNumGroupMembers() do
local unit = ShadowUF.raidUnits[i]
if( UnitGUID(ShadowUF.unitTarget[unit]) == guid ) then
total = total + 1
end
- end
+ end
return total
end]],
}
-- Default tag events
Tags.defaultEvents = {
- ["hp:color"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["short:druidform"] = "UNIT_AURA",
- ["druidform"] = "UNIT_AURA",
- ["guild"] = "UNIT_NAME_UPDATE", -- Not sure when this data is available, guessing
- ["abs:incheal"] = "HEALCOMM",
- ["incheal:name"] = "HEALCOMM",
- ["incheal"] = "HEALCOMM",
- ["afk"] = "PLAYER_FLAGS_CHANGED", -- Yes, I know it's called PLAYER_FLAGS_CHANGED, but arg1 is the unit including non-players.
- ["afk:time"] = "PLAYER_FLAGS_CHANGED",
- ["status:time"] = "UNIT_MANA",
- ["pvp:time"] = "PLAYER_FLAGS_CHANGED",
- ["curhp"] = "UNIT_HEALTH",
- ["abscurhp"] = "UNIT_HEALTH",
- ["curmaxhp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["absolutehp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["smart:curmaxhp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["curpp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER",
- ["abscurpp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWERR",
- ["curmaxpp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["absolutepp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["smart:curmaxpp"] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER UNIT_DISPLAYPOWER UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["druid:curpp"] = "UNIT_MANA UNIT_DISPLAYPOWER",
- ["druid:abscurpp"] = "UNIT_MANA UNIT_DISPLAYPOWER",
- ["druid:curmaxpp"] = "UNIT_MANA UNIT_MAXMANA UNIT_DISPLAYPOWER",
- ["druid:absolutepp"] = "UNIT_MANA UNIT_MAXMANA UNIT_DISPLAYPOWER",
- ["level"] = "UNIT_LEVEL PLAYER_LEVEL_UP",
- ["levelcolor"] = "UNIT_LEVEL PLAYER_LEVEL_UP",
- ["maxhp"] = "UNIT_MAXHEALTH",
- ["def:name"] = "UNIT_NAME_UPDATE UNIT_MAXHEALTH UNIT_HEALTH",
- ["absmaxhp"] = "UNIT_MAXHEALTH",
- ["maxpp"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["absmaxpp"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
- ["missinghp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["missingpp"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_MAXRUNIC_POWER UNIT_RUNIC_POWER",
- ["name"] = "UNIT_NAME_UPDATE",
- ["abbrev:name"] = "UNIT_NAME_UPDATE",
- ["server"] = "UNIT_NAME_UPDATE",
- ["colorname"] = "UNIT_NAME_UPDATE",
- ["perhp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["perpp"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_MAXRUNIC_POWER UNIT_RUNIC_POWER",
- ["status"] = "UNIT_HEALTH PLAYER_UPDATE_RESTING",
- ["smartlevel"] = "UNIT_LEVEL PLAYER_LEVEL_UP UNIT_CLASSIFICATION_CHANGED",
- ["cpoints"] = "UNIT_COMBO_POINTS PLAYER_TARGET_CHANGED",
- ["rare"] = "UNIT_CLASSIFICATION_CHANGED",
- ["classification"] = "UNIT_CLASSIFICATION_CHANGED",
- ["shortclassification"] = "UNIT_CLASSIFICATION_CHANGED",
- ["dechp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
- ["group"] = "RAID_ROSTER_UPDATE",
- ["unit:color:aggro"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["color:aggro"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["situation"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["color:sit"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["scaled:threat"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["general:sit"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["color:gensit"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["unit:scaled:threat"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["unit:color:sit"] = "UNIT_THREAT_SITUATION_UPDATE",
- ["unit:situation"] = "UNIT_THREAT_SITUATION_UPDATE",
+ ["totem:timer"] = "SUF_TOTEM_TIMER",
+ ["rune:timer"] = "SUF_RUNE_TIMER",
+ ["hp:color"] = "UNIT_HEALTH UNIT_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 = {
@@ -877,253 +1154,309 @@ Tags.defaultFrequents = {
["unit:scaled:threat"] = 1,
["unit:raid:targeting"] = 0.50,
["unit:raid:assist"] = 0.50,
+ ["monk:stagger"] = 0.25,
+ ["monk:abs:stagger"] = 0.25
}
-- Default tag categories
Tags.defaultCategories = {
- ["hp:color"] = "health",
- ["abs:incheal"] = "health",
- ["incheal"] = "health",
- ["incheal:name"] = "health",
- ["smart:curmaxhp"] = "health",
- ["smart:curmaxpp"] = "health",
- ["afk"] = "status",
- ["afk:time"] = "status",
- ["status:time"] = "status",
- ["pvp:time"] = "status",
- ["cpoints"] = "misc",
- ["smartlevel"] = "classification",
- ["classification"] = "classification",
- ["shortclassification"] = "classification",
- ["rare"] = "classification",
- ["plus"] = "classification",
- ["sex"] = "misc",
- ["smartclass"] = "classification",
- ["smartrace"] = "classification",
- ["status"] = "status",
- ["race"] = "classification",
- ["level"] = "classification",
- ["maxhp"] = "health",
- ["maxpp"] = "power",
- ["missinghp"] = "health",
- ["missingpp"] = "power",
- ["name"] = "misc",
- ["abbrev:name"] = "misc",
- ["server"] = "misc",
- ["perhp"] = "health",
- ["perpp"] = "power",
- ["class"] = "classification",
- ["classcolor"] = "classification",
- ["creature"] = "classification",
- ["short:druidform"] = "classification",
- ["druidform"] = "classification",
- ["curhp"] = "health",
- ["curpp"] = "power",
- ["curmaxhp"] = "health",
- ["curmaxpp"] = "power",
- ["levelcolor"] = "classification",
- ["def:name"] = "health",
- ["faction"] = "classification",
- ["colorname"] = "misc",
- ["guild"] = "misc",
- ["absolutepp"] = "power",
- ["absolutehp"] = "health",
- ["absmaxhp"] = "health",
- ["abscurhp"] = "health",
- ["absmaxpp"] = "power",
- ["abscurpp"] = "power",
- ["reactcolor"] = "classification",
- ["dechp"] = "health",
- ["group"] = "misc",
- ["close"] = "misc",
- ["druid:curpp"] = "power",
- ["druid:abscurpp"] = "power",
- ["druid:curmaxpp"] = "power",
- ["druid:absolutepp"] = "power",
- ["situation"] = "playerthreat",
- ["color:sit"] = "playerthreat",
- ["scaled:threat"] = "playerthreat",
- ["general:sit"] = "playerthreat",
- ["color:gensit"] = "playerthreat",
- ["color:aggro"] = "playerthreat",
- ["unit:scaled:threat"] = "threat",
- ["unit:color:sit"] = "threat",
- ["unit:situation"] = "threat",
- ["unit:color:aggro"] = "threat",
- ["unit:raid:assist"] = "raid",
- ["unit:raid:targeting"] = "raid",
+ ["totem:timer"] = "classtimer",
+ ["rune:timer"] = "classtimer",
+ ["hp:color"] = "health",
+ ["abs:incabsorb"] = "health",
+ ["incabsorb"] = "health",
+ ["incabsorb:name"] = "health",
+ ["per:incheal"] = "health",
+ ["abs:incheal"] = "health",
+ ["incheal"] = "health",
+ ["incheal:name"] = "health",
+ ["smart:curmaxhp"] = "health",
+ ["smart:curmaxpp"] = "health",
+ ["afk"] = "status",
+ ["afk:time"] = "status",
+ ["status:time"] = "status",
+ ["pvp:time"] = "status",
+ ["cpoints"] = "classspec",
+ ["smartlevel"] = "classification",
+ ["classification"] = "classification",
+ ["shortclassification"] = "classification",
+ ["rare"] = "classification",
+ ["plus"] = "classification",
+ ["sex"] = "misc",
+ ["smartclass"] = "classification",
+ ["smartrace"] = "classification",
+ ["status"] = "status",
+ ["race"] = "classification",
+ ["level"] = "classification",
+ ["maxhp"] = "health",
+ ["maxpp"] = "power",
+ ["missinghp"] = "health",
+ ["missingpp"] = "power",
+ ["name"] = "misc",
+ ["abbrev:name"] = "misc",
+ ["server"] = "misc",
+ ["perhp"] = "health",
+ ["perpp"] = "power",
+ ["class"] = "classification",
+ ["classcolor"] = "classification",
+ ["creature"] = "classification",
+ ["short:druidform"] = "classification",
+ ["druidform"] = "classification",
+ ["curhp"] = "health",
+ ["curpp"] = "power",
+ ["curmaxhp"] = "health",
+ ["curmaxpp"] = "power",
+ ["levelcolor"] = "classification",
+ ["def:name"] = "health",
+ ["faction"] = "classification",
+ ["colorname"] = "misc",
+ ["guild"] = "misc",
+ ["absolutepp"] = "power",
+ ["absolutehp"] = "health",
+ ["absmaxhp"] = "health",
+ ["abscurhp"] = "health",
+ ["absmaxpp"] = "power",
+ ["abscurpp"] = "power",
+ ["reactcolor"] = "classification",
+ ["dechp"] = "health",
+ ["group"] = "misc",
+ ["close"] = "misc",
+ ["druid:curpp"] = "classspec",
+ ["druid:abscurpp"] = "classspec",
+ ["druid:curmaxpp"] = "classspec",
+ ["druid:absolutepp"] = "classspec",
+ ["sec:curpp"] = "classspec",
+ ["sec:abscurpp"] = "classspec",
+ ["sec:curmaxpp"] = "classspec",
+ ["sec:absolutepp"] = "classspec",
+ ["sshards"] = "classspec",
+ ["hpower"] = "classspec",
+ ["situation"] = "playerthreat",
+ ["color:sit"] = "playerthreat",
+ ["scaled:threat"] = "playerthreat",
+ ["general:sit"] = "playerthreat",
+ ["color:gensit"] = "playerthreat",
+ ["color:aggro"] = "playerthreat",
+ ["unit:scaled:threat"] = "threat",
+ ["unit:color:sit"] = "threat",
+ ["unit:situation"] = "threat",
+ ["unit:color:aggro"] = "threat",
+ ["unit:raid:assist"] = "raid",
+ ["unit:raid:targeting"] = "raid",
+ ["monk:chipoints"] = "classspec",
+ ["monk:stagger"] = "classspec",
+ ["monk:abs:stagger"] = "classspec"
}
-
+
-- Default tag help
Tags.defaultHelp = {
- ["hp:color"] = L["Color code based on percentage of HP left on the unit, this works the same way as the color by health option. But for text instead of the entire bar."],
- ["guild"] = L["Show's the units guild name if they are in a guild."],
- ["short:druidform"] = L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."],
- ["druidform"] = L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."],
- ["abs:incheal"] = L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."],
- ["incheal"] = L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."],
- ["incheal:name"] = L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."],
- ["smart:curmaxhp"] = L["Smart number formating for [curmaxhp], numbers below 1,000,000 are left as is, numbers above 1,000,000 will use the short version such as 1m."],
- ["smart:curmaxpp"] = L["Smart number formating for [curmaxpp], numbers below 1,000,000 are left as is, numbers above 1,000,000 will use the short version such as 1m."],
- ["pvp:time"] = L["Shows how long until your PVP flag drops, will not show if the flag is manually on or you are in a hostile zone.|n|nThis will only work for yourself, you cannot use it to see the time left on your party or raid."],
- ["afk:time"] = L["Shows how long an unit has been AFK or DND."],
- ["status:time"] = L["Shows how long an unit has been offline."],
- ["afk"] = L["Shows AFK, DND or nothing depending on the units away status."],
- ["cpoints"] = L["Total number of combo points you have on your target."],
- ["smartlevel"] = L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."],
- ["classification"] = L["Units classification, Rare, Rare Elite, Elite, Boss, nothing is shown if they aren't any of those."],
- ["shortclassification"] = L["Short classifications, R for Rare, R+ for Rare Elite, + for Elite, B for boss, nothing is shown if they aren't any of those."],
- ["rare"] = L["Returns Rare if the unit is a rare or rare elite mob."],
- ["plus"] = L["Returns + if the unit is an elite or rare elite mob."],
- ["sex"] = L["Returns the units sex."],
- ["smartclass"] = L["If the unit is a player then class is returned, if it's a NPC then the creature type."],
- ["smartrace"] = L["If the unit is a player then race is returned, if it's a NPC then the creature type."],
- ["status"] = L["Shows Offline, Dead, Ghost or nothing depending on the units current status."],
- ["race"] = L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."],
- ["level"] = L["Level without any coloring."],
- ["maxhp"] = L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."],
- ["maxpp"] = L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."],
- ["missinghp"] = L["Amount of health missing, if none is missing nothing is shown. Uses a short format, -18500 is shown as -18.5k, values below 10000 are formatted as is."],
- ["missingpp"] = L["Amount of power missing, if none is missing nothing is shown. Uses a short format, -13850 is shown as 13.8k, values below 10000 are formatted as is."],
- ["name"] = L["Unit name"],
- ["server"] = L["Unit server, if they are from your server then nothing is shown."],
- ["perhp"] = L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."],
- ["perpp"] = L["Returns current power as a percentage."],
- ["class"] = L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."],
- ["classcolor"] = L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"],
- ["creature"] = L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."],
- ["curhp"] = L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."],
- ["curpp"] = L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."],
- ["curmaxhp"] = L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."],
- ["curmaxpp"] = L["Current and maximum power, formatted as [curpp]/[maxpp]."],
- ["levelcolor"] = L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."],
- ["def:name"] = L["When the unit is mising health, the [missinghp] tag is shown, when they are at full health then the [name] tag is shown. This lets you see -1000 when they are missing 1000 HP, but their name when they are not missing any."],
- ["faction"] = L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."],
- ["colorname"] = L["Unit name colored by class."],
- ["absolutepp"] = L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."],
- ["absolutehp"] = L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."],
- ["absmaxhp"] = L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."],
- ["abscurhp"] = L["Shows current health value in absolute form meaning 15000 health is shown as 15000."],
- ["absmaxpp"] = L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."],
- ["abscurpp"] = L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."],
- ["reactcolor"] = L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."],
- ["dechp"] = L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."],
- ["abbrev:name"] = L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."],
- ["group"] = L["Shows current group number of the unit."],
- ["close"] = L["Closes a color code, prevents colors from showing up on text that you do not want it to."],
- ["druid:curpp"] = string.format(L["Works the same as %s, but this is only shown if the unit is in Cat or Bear form."], "currpp"),
- ["druid:abscurpp"] = string.format(L["Works the same as %s, but this is only shown if the unit is in Cat or Bear form."], "abscurpp"),
- ["druid:curmaxpp"] = string.format(L["Works the same as %s, but this is only shown if the unit is in Cat or Bear form."], "curmaxpp"),
- ["druid:absolutepp"] = string.format(L["Works the same as %s, but this is only shown if the unit is in Cat or Bear form."], "absolutepp"),
- ["situation"] = L["Returns text based on your threat situation with your target: Aggro for Aggro, High for being close to taking aggro, and Medium as a general warning to be wary."],
- ["color:sit"] = L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."],
- ["scaled:threat"] = L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."],
- ["general:sit"] = L["Returns text based on your general threat situation on all units: Aggro for Aggro, High for being near to pulling aggro and Medium as a general warning."],
- ["color:gensit"] = L["Returns a color code of your general threat situation on all units: Red for Aggro, Orange for High threat and Yellow to watch out."],
- ["unit:scaled:threat"] = L["Returns the scaled threat percentage for the unit, if you put this on a party member you would see the percentage of how close they are to getting any from any hostile mobs. Always 0 - 100%.|nThis cannot be used on target of target or focus target types of units."],
- ["unit:color:sit"] = L["Returns the color code for the units threat situation in general: Red for Aggro, Orange for High threat and Yellow to watch out.|nThis cannot be used on target of target or focus target types of units."],
- ["unit:situation"] = L["Returns text based on the units general threat situation: Aggro for Aggro, High for being close to taking aggro, and Medium as a warning to be wary.|nThis cannot be used on target of target or focus target types of units."],
- ["unit:color:aggro"] = L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."],
- ["color:aggro"] = L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."],
- ["unit:raid:targeting"] = L["How many people in your raid are targeting the unit, for example if you put this on yourself it will show how many people are targeting you. This includes you in the count!"],
- ["unit:raid:assist"] = L["How many people are assisting the unit, for example if you put this on yourself it will show how many people are targeting your target. This includes you in the count!"],
+ ["totem:timer"] = L["How many seconds a totem has left before disappearing."],
+ ["rune:timer"] = L["How many seconds before a rune recharges."],
+ ["abs:incabsorb"] = L["Absolute damage absorption value on the unit, if 10,000 damage will be absorbed, it will show 10,000."],
+ ["incabsorb"] = L["Shorten damage absorption, if 13,000 damage will e absorbed, it will show 13k."],
+ ["incabsorb:name"] = L["If the unit has a damage absorption shield on them, it will show the absolute absorb value, otherwise the units name."],
+ ["hp:color"] = L["Color code based on percentage of HP left on the unit, this works the same way as the color by health option. But for text instead of the entire bar."],
+ ["guild"] = L["Show's the units guild name if they are in a guild."],
+ ["short:druidform"] = L["Short version of [druidform], C = Cat, B = Bear, F = Flight and so on."],
+ ["druidform"] = L["Returns the units current form if they are a druid, Cat for Cat Form, Moonkin for Moonkin and so on."],
+ ["per:incheal"] = L["Percent of the players current health that's being healed, if they have 100,000 total health and 15,000 is incoming then 15% is shown."],
+ ["abs:incheal"] = L["Absolute incoming heal value, if 10,000 healing is incoming it will show 10,000."],
+ ["incheal"] = L["Shorten incoming heal value, if 13,000 healing is incoming it will show 13k."],
+ ["abs:healabsorb"] = L["Absolute heal absorb value, if 16,000 healing will be absorbed, it will show 16,000."],
+ ["healabsorb"] = L["Shorten heal absorb value, if 17,000 healing will be absorbed, it will show 17k."],
+ ["incheal:name"] = L["If the unit has heals incoming, it will show the absolute incoming heal value, otherwise it will show the units name."],
+ ["smart:curmaxhp"] = L["Smart number formating for [curmaxhp], numbers below 1,000,000 are left as is, numbers above 1,000,000 will use the short version such as 1m."],
+ ["smart:curmaxpp"] = L["Smart number formating for [curmaxpp], numbers below 1,000,000 are left as is, numbers above 1,000,000 will use the short version such as 1m."],
+ ["pvp:time"] = L["Shows how long until your PVP flag drops, will not show if the flag is manually on or you are in a hostile zone.|n|nThis will only work for yourself, you cannot use it to see the time left on your party or raid."],
+ ["afk:time"] = L["Shows how long an unit has been AFK or DND."],
+ ["status:time"] = L["Shows how long an unit has been offline."],
+ ["afk"] = L["Shows AFK, DND or nothing depending on the units away status."],
+ ["cpoints"] = L["Total number of combo points you have on your target."],
+ ["hpower"] = L["Total number of active holy power."],
+ ["sshards"] = L["Total number of active soul shards."],
+ ["smartlevel"] = L["Smart level, returns Boss for bosses, +50 for a level 50 elite mob, or just 80 for a level 80."],
+ ["classification"] = L["Units classification, Rare, Rare Elite, Elite, Boss or Minion nothing is shown if they aren't any of those."],
+ ["shortclassification"] = L["Short classifications, R for Rare, R+ for Rare Elite, + for Elite, B for Boss or M for Minion nothing is shown if they aren't any of those."],
+ ["rare"] = L["Returns Rare if the unit is a rare or rare elite mob."],
+ ["plus"] = L["Returns + if the unit is an elite or rare elite mob."],
+ ["sex"] = L["Returns the units sex."],
+ ["smartclass"] = L["If the unit is a player then class is returned, if it's a NPC then the creature type."],
+ ["smartrace"] = L["If the unit is a player then race is returned, if it's a NPC then the creature type."],
+ ["status"] = L["Shows Offline, Dead, Ghost or nothing depending on the units current status."],
+ ["race"] = L["Units race, Blood Elf, Tauren, Troll (unfortunately) and so on."],
+ ["level"] = L["Level without any coloring."],
+ ["maxhp"] = L["Max health, uses a short format, 17750 is formatted as 17.7k, values below 10000 are formatted as is."],
+ ["maxpp"] = L["Max power, uses a short format, 16000 is formatted as 16k, values below 10000 are formatted as is."],
+ ["missinghp"] = L["Amount of health missing, if none is missing nothing is shown. Uses a short format, -18500 is shown as -18.5k, values below 10000 are formatted as is."],
+ ["missingpp"] = L["Amount of power missing, if none is missing nothing is shown. Uses a short format, -13850 is shown as 13.8k, values below 10000 are formatted as is."],
+ ["name"] = L["Unit name"],
+ ["server"] = L["Unit server, if they are from your server then nothing is shown."],
+ ["perhp"] = L["Returns current health as a percentage, if the unit is dead or offline than that is shown instead."],
+ ["perpp"] = L["Returns current power as a percentage."],
+ ["class"] = L["Class name without coloring, use [classcolor][class][close] if you want the class name to be colored by class."],
+ ["classcolor"] = L["Color code for the class, use [classcolor][class][close] if you want the class text to be colored by class"],
+ ["creature"] = L["Creature type, returns Felguard if the unit is a Felguard, Wolf if it's a Wolf and so on."],
+ ["curhp"] = L["Current health, uses a short format, 11500 is formatted as 11.5k, values below 10000 are formatted as is."],
+ ["curpp"] = L["Current power, uses a short format, 12750 is formatted as 12.7k, values below 10000 are formatted as is."],
+ ["curmaxhp"] = L["Current and maximum health, formatted as [curhp]/[maxhp], if the unit is dead or offline then that is shown instead."],
+ ["curmaxpp"] = L["Current and maximum power, formatted as [curpp]/[maxpp]."],
+ ["levelcolor"] = L["Returns the color code based off of the units level compared to yours. If you cannot attack them then no color is returned."],
+ ["def:name"] = L["When the unit is mising health, the [missinghp] tag is shown, when they are at full health then the [name] tag is shown. This lets you see -1000 when they are missing 1000 HP, but their name when they are not missing any."],
+ ["faction"] = L["Units alignment, Thrall will return Horde, Magni Bronzebeard will return Alliance."],
+ ["colorname"] = L["Unit name colored by class."],
+ ["absolutepp"] = L["Shows current and maximum power in absolute form, 18000 power will be showed as 18000 power."],
+ ["absolutehp"] = L["Shows current and maximum health in absolute form, 17500 health will be showed as 17500 health."],
+ ["absmaxhp"] = L["Shows maximum health in absolute form, 14000 health is showed as 14000 health."],
+ ["abscurhp"] = L["Shows current health value in absolute form meaning 15000 health is shown as 15000."],
+ ["absmaxpp"] = L["Shows maximum power in absolute form, 13000 power is showed as 13000 power."],
+ ["abscurpp"] = L["Shows current power value in absolute form, 15000 power will be displayed as 1500 still."],
+ ["reactcolor"] = L["Reaction color code, use [reactcolor][name][close] to color the units name by their reaction."],
+ ["dechp"] = L["Shows the units health as a percentage rounded to the first decimal, meaning 61 out of 110 health is shown as 55.4%."],
+ ["abbrev:name"] = L["Abbreviates unit names above 10 characters, \"Dark Rune Champion\" becomes \"D.R.Champion\" and \"Dark Rune Commoner\" becomes \"D.R.Commoner\"."],
+ ["group"] = L["Shows current group number of the unit."],
+ ["close"] = L["Closes a color code, prevents colors from showing up on text that you do not want it to."],
+ ["druid:curpp"] = string.format(L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."], "currpp"),
+ ["druid:abscurpp"] = string.format(L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."], "abscurpp"),
+ ["druid:curmaxpp"] = string.format(L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."], "curmaxpp"),
+ ["druid:absolutepp"] = string.format(L["Works the same as [%s], but this is only shown if the unit is in Cat or Bear form."], "absolutepp"),
+ ["sec:curpp"] = string.format(L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."], "curpp"),
+ ["sec:abscurpp"] = string.format(L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."], "abscurpp"),
+ ["sec:curmaxpp"] = string.format(L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."], "curmaxpp"),
+ ["sec:absolutepp"] = string.format(L["Works the same as [%s], but always shows mana and is only shown if mana is a secondary power."], "absolutepp"),
+ ["situation"] = L["Returns text based on your threat situation with your target: Aggro for Aggro, High for being close to taking aggro, and Medium as a general warning to be wary."],
+ ["color:sit"] = L["Returns a color code of the threat situation with your target: Red for Aggro, Orange for High threat and Yellow to be careful."],
+ ["scaled:threat"] = L["Returns a scaled threat percent of your aggro on your current target, always 0 - 100%."],
+ ["general:sit"] = L["Returns text based on your general threat situation on all units: Aggro for Aggro, High for being near to pulling aggro and Medium as a general warning."],
+ ["color:gensit"] = L["Returns a color code of your general threat situation on all units: Red for Aggro, Orange for High threat and Yellow to watch out."],
+ ["unit:scaled:threat"] = L["Returns the scaled threat percentage for the unit, if you put this on a party member you would see the percentage of how close they are to getting any from any hostile mobs. Always 0 - 100%.|nThis cannot be used on target of target or focus target types of units."],
+ ["unit:color:sit"] = L["Returns the color code for the units threat situation in general: Red for Aggro, Orange for High threat and Yellow to watch out.|nThis cannot be used on target of target or focus target types of units."],
+ ["unit:situation"] = L["Returns text based on the units general threat situation: Aggro for Aggro, High for being close to taking aggro, and Medium as a warning to be wary.|nThis cannot be used on target of target or focus target types of units."],
+ ["unit:color:aggro"] = L["Same as [unit:color:sit] except it only returns red if the unit has aggro, rather than transiting from yellow -> orange -> red."],
+ ["color:aggro"] = L["Same as [color:sit] except it only returns red if you have aggro, rather than transiting from yellow -> orange -> red."],
+ ["unit:raid:targeting"] = L["How many people in your raid are targeting the unit, for example if you put this on yourself it will show how many people are targeting you. This includes you in the count!"],
+ ["unit:raid:assist"] = L["How many people are assisting the unit, for example if you put this on yourself it will show how many people are targeting your target. This includes you in the count!"],
+ ["monk:chipoints"] = L["How many Chi points you currently have."],
+ ["monk:stagger"] = L["Shows the current staggered damage, if 12,000 damage is staggered, shows 12k."],
+ ["monk:abs:stagger"] = L["Shows the absolute staggered damage, if 16,000 damage is staggered, shows 16,000."]
}
Tags.defaultNames = {
- ["incheal:name"] = L["Incoming heal/Name"],
- ["unit:scaled:threat"] = L["Unit scaled threat"],
- ["unit:color:sit"] = L["Unit colored situation"],
- ["unit:situation"] = L["Unit situation name"],
- ["hp:color"] = L["Health color"],
- ["guild"] = L["Guild name"],
- ["druidform"] = L["Druid form"],
- ["short:druidform"] = L["Druid form (Short)"],
- ["abs:incheal"] = L["Incoming heal (Absolute)"],
- ["incheal"] = L["Incoming heal (Short)"],
- ["abbrev:name"] = L["Name (Abbreviated)"],
- ["smart:curmaxhp"] = L["Cur/Max HP (Smart)"],
- ["smart:curmaxpp"] = L["Cur/Max PP (Smart)"],
- ["pvp:time"] = L["PVP timer"],
- ["afk:time"] = L["AFK timer"],
- ["status:time"] = L["Offline timer"],
- ["afk"] = L["AFK status"],
- ["cpoints"] = L["Combo points"],
- ["smartlevel"] = L["Smart level"],
- ["classification"] = L["Classificaiton"],
- ["shortclassification"] = L["Short classification"],
- ["rare"] = L["Rare indicator"],
- ["plus"] = L["Short elite indicator"],
- ["sex"] = L["Sex"],
- ["smartclass"] = L["Class (Smart)"],
- ["smartrace"] = L["Race (Smart)"],
- ["status"] = L["Status"],
- ["race"] = L["Race"],
- ["level"] = L["Level"],
- ["maxhp"] = L["Max HP (Short)"],
- ["maxpp"] = L["Max power (Short)"],
- ["missinghp"] = L["Missing HP (Short)"],
- ["missingpp"] = L["Missing power (Short)"],
- ["name"] = L["Unit name"],
- ["server"] = L["Unit server"],
- ["perhp"] = L["Percent HP"],
- ["perpp"] = L["Percent power"],
- ["class"] = L["Class"],
- ["classcolor"] = L["Class color tag"],
- ["creature"] = L["Creature type"],
- ["curhp"] = L["Current HP (Short)"],
- ["curpp"] = L["Current Power (Short)"],
- ["curmaxhp"] = L["Cur/Max HP (Short)"],
- ["curmaxpp"] = L["Cur/Max Power (Short)"],
- ["levelcolor"] = L["Level (Colored)"],
- ["def:name"] = L["Deficit/Unit Name"],
- ["faction"] = L["Unit faction"],
- ["colorname"] = L["Unit name (Class colored)"],
- ["absolutepp"] = L["Cur/Max power (Absolute)"],
- ["absolutehp"] = L["Cur/Max HP (Absolute)"],
- ["absmaxhp"] = L["Max HP (Absolute)"],
- ["abscurhp"] = L["Current HP (Absolute)"],
- ["absmaxpp"] = L["Max power (Absolute)"],
- ["abscurpp"] = L["Current power (Absolute)"],
- ["reactcolor"] = L["Reaction color tag"],
- ["dechp"] = L["Decimal percent HP"],
- ["group"] = L["Group number"],
- ["close"] = L["Close color"],
- ["druid:curpp"] = L["Current power (Druid)"],
- ["druid:abscurpp"] = L["Current power (Druid/Absolute)"],
- ["druid:curmaxpp"] = L["Cur/Max power (Druid)"],
- ["druid:absolutepp"] = L["Current health (Druid/Absolute)"],
- ["situation"] = L["Threat situation"],
- ["color:sit"] = L["Color code for situation"],
- ["scaled:threat"] = L["Scaled threat percent"],
- ["general:sit"] = L["General threat situation"],
- ["color:gensit"] = L["Color code for general situation"],
- ["color:aggro"] = L["Color code on aggro"],
- ["unit:color:aggro"] = L["Unit color code on aggro"],
- ["unit:raid:targeting"] = L["Raid targeting unit"],
- ["unit:raid:assist"] = L["Raid assisting unit"],
+ ["totem:timer"] = L["Totem Timer"],
+ ["rune:timer"] = L["Rune Timer"],
+ ["abs:incabsorb"] = L["Damage absorption (Absolute)"],
+ ["incabsorb"] = L["Damage absorption (Short)"],
+ ["incabsorb:name"] = L["Damage absorption/Name"],
+ ["per:incheal"] = L["Incoming heal (Percent)"],
+ ["incheal:name"] = L["Incoming heal/Name"],
+ ["abs:healabsorb"] = L["Heal Absorb (Absolute)"],
+ ["healabsorb"] = L["Heal Absorb (Short)"],
+ ["unit:scaled:threat"] = L["Unit scaled threat"],
+ ["unit:color:sit"] = L["Unit colored situation"],
+ ["unit:situation"] = L["Unit situation name"],
+ ["hp:color"] = L["Health color"],
+ ["guild"] = L["Guild name"],
+ ["druidform"] = L["Druid form"],
+ ["short:druidform"] = L["Druid form (Short)"],
+ ["abs:incheal"] = L["Incoming heal (Absolute)"],
+ ["incheal"] = L["Incoming heal (Short)"],
+ ["abbrev:name"] = L["Name (Abbreviated)"],
+ ["smart:curmaxhp"] = L["Cur/Max HP (Smart)"],
+ ["smart:curmaxpp"] = L["Cur/Max PP (Smart)"],
+ ["pvp:time"] = L["PVP timer"],
+ ["afk:time"] = L["AFK timer"],
+ ["status:time"] = L["Offline timer"],
+ ["afk"] = L["AFK status"],
+ ["cpoints"] = L["Combo points"],
+ ["hpower"] = L["Holy power"],
+ ["sshards"] = L["Soul shards"],
+ ["smartlevel"] = L["Smart level"],
+ ["classification"] = L["Classification"],
+ ["shortclassification"] = L["Short classification"],
+ ["rare"] = L["Rare indicator"],
+ ["plus"] = L["Short elite indicator"],
+ ["sex"] = L["Sex"],
+ ["smartclass"] = L["Class (Smart)"],
+ ["smartrace"] = L["Race (Smart)"],
+ ["status"] = L["Status"],
+ ["race"] = L["Race"],
+ ["level"] = L["Level"],
+ ["maxhp"] = L["Max HP (Short)"],
+ ["maxpp"] = L["Max power (Short)"],
+ ["missinghp"] = L["Missing HP (Short)"],
+ ["missingpp"] = L["Missing power (Short)"],
+ ["name"] = L["Unit name"],
+ ["server"] = L["Unit server"],
+ ["perhp"] = L["Percent HP"],
+ ["perpp"] = L["Percent power"],
+ ["class"] = L["Class"],
+ ["classcolor"] = L["Class color tag"],
+ ["creature"] = L["Creature type"],
+ ["curhp"] = L["Current HP (Short)"],
+ ["curpp"] = L["Current Power (Short)"],
+ ["curmaxhp"] = L["Cur/Max HP (Short)"],
+ ["curmaxpp"] = L["Cur/Max Power (Short)"],
+ ["levelcolor"] = L["Level (Colored)"],
+ ["def:name"] = L["Deficit/Unit Name"],
+ ["faction"] = L["Unit faction"],
+ ["colorname"] = L["Unit name (Class colored)"],
+ ["absolutepp"] = L["Cur/Max power (Absolute)"],
+ ["absolutehp"] = L["Cur/Max HP (Absolute)"],
+ ["absmaxhp"] = L["Max HP (Absolute)"],
+ ["abscurhp"] = L["Current HP (Absolute)"],
+ ["absmaxpp"] = L["Max power (Absolute)"],
+ ["abscurpp"] = L["Current power (Absolute)"],
+ ["reactcolor"] = L["Reaction color tag"],
+ ["dechp"] = L["Decimal percent HP"],
+ ["group"] = L["Group number"],
+ ["close"] = L["Close color"],
+ ["druid:curpp"] = L["Current power (Druid)"],
+ ["druid:abscurpp"] = L["Current power (Druid/Absolute)"],
+ ["druid:curmaxpp"] = L["Cur/Max power (Druid)"],
+ ["druid:absolutepp"] = L["Cur/Max power (Druid/Absolute)"],
+ ["sec:curpp"] = L["Current power (Secondary)"],
+ ["sec:abscurpp"] = L["Current power (Secondary/Absolute)"],
+ ["sec:curmaxpp"] = L["Cur/Max power (Secondary)"],
+ ["sec:absolutepp"] = L["Cur/Max power (Secondary/Absolute)"],
+ ["situation"] = L["Threat situation"],
+ ["color:sit"] = L["Color code for situation"],
+ ["scaled:threat"] = L["Scaled threat percent"],
+ ["general:sit"] = L["General threat situation"],
+ ["color:gensit"] = L["Color code for general situation"],
+ ["color:aggro"] = L["Color code on aggro"],
+ ["unit:color:aggro"] = L["Unit color code on aggro"],
+ ["unit:raid:targeting"] = L["Raid targeting unit"],
+ ["unit:raid:assist"] = L["Raid assisting unit"],
+ ["monk:chipoints"] = L["Chi Points"],
+ ["monk:stagger"] = L["Stagger (Monk)"],
+ ["monk:abs:stagger"] = L["Stagger (Monk/Absolute)"]
}
-- List of event types
Tags.eventType = {
- ["UNIT_ENERGY"] = "power",
- ["UNIT_FOCUS"] = "power",
- ["UNIT_MANA"] = "power",
- ["UNIT_RAGE"] = "power",
- ["UNIT_RUNIC_POWER"] = "power",
+ ["UNIT_POWER_FREQUENT"] = "power",
+ ["UNIT_MAXPOWER"] = "power",
+ ["UNIT_ABSORB_AMOUNT_CHANGED"] = "health",
["UNIT_HEALTH"] = "health",
["UNIT_MAXHEALTH"] = "health",
- ["RAID_ROSTER_UPDATE"] = "unitless",
+ ["GROUP_ROSTER_UPDATE"] = "unitless",
["RAID_TARGET_UPDATE"] = "unitless",
["PLAYER_TARGET_CHANGED"] = "unitless",
- ["PARTY_MEMBERS_CHANGED"] = "unitless",
["PARTY_LEADER_CHANGED"] = "unitless",
["PLAYER_ENTERING_WORLD"] = "unitless",
+ ["PLAYER_REGEN_DISABLED"] = "unitless",
+ ["PLAYER_REGEN_ENABLED"] = "unitless",
["PLAYER_XP_UPDATE"] = "unitless",
["PLAYER_TOTEM_UPDATE"] = "unitless",
["PLAYER_LEVEL_UP"] = "unitless",
["UPDATE_EXHAUSTION"] = "unitless",
["PLAYER_UPDATE_RESTING"] = "unitless",
["UNIT_COMBO_POINTS"] = "unitless",
+ ["PARTY_LOOT_METHOD_CHANGED"] = "unitless",
+ ["READY_CHECK"] = "unitless",
+ ["READY_CHECK_FINISHED"] = "unitless",
+ ["RUNE_POWER_UPDATE"] = "unitless",
+ ["RUNE_TYPE_UPDATE"] = "unitless",
+ ["UPDATE_FACTION"] = "unitless",
}
-- Tag groups that have a special filter that can't be used on certain units, like the threat API's
@@ -1133,7 +1466,14 @@ Tags.unitBlacklist = {
-- Single tags that can only be used on a single unit
Tags.unitRestrictions = {
- ["pvp:time"] = "player",
+ ["pvp:time"] = "player",
+ ["totem:timer"] = "player",
+ ["rune:timer"] = "player"
+}
+
+Tags.anchorRestriction = {
+ ["totem:timer"] = "$totemBar",
+ ["rune:timer"] = "$runeBar"
}
-- Event scanner to automatically figure out what events a tag will need
@@ -1141,29 +1481,32 @@ local function loadAPIEvents()
if( Tags.APIEvents ) then return end
Tags.APIEvents = {
["InCombatLockdown"] = "PLAYER_REGEN_ENABLED PLAYER_REGEN_DISABLED",
- ["UnitLevel"] = "UNIT_LEVEL",
+ ["UnitLevel"] = "UNIT_LEVEL UNIT_FACTION",
+ ["UnitBattlePetLevel"] = "UNIT_LEVEL UNIT_FACTION",
["UnitName"] = "UNIT_NAME_UPDATE",
["UnitClassification"] = "UNIT_CLASSIFICATION_CHANGED",
["UnitFactionGroup"] = "UNIT_FACTION PLAYER_FLAGS_CHANGED",
["UnitHealth%("] = "UNIT_HEALTH",
["UnitHealthMax"] = "UNIT_MAXHEALTH",
- ["UnitPower%("] = "UNIT_ENERGY UNIT_FOCUS UNIT_MANA UNIT_RAGE UNIT_RUNIC_POWER",
- ["UnitPowerMax"] = "UNIT_MAXENERGY UNIT_MAXFOCUS UNIT_MAXMANA UNIT_MAXRAGE UNIT_MAXRUNIC_POWER",
+ ["UnitPower%("] = "UNIT_POWER_FREQUENT",
+ ["UnitPowerMax"] = "UNIT_MAXPOWER",
["UnitPowerType"] = "UNIT_DISPLAYPOWER",
["UnitIsDead"] = "UNIT_HEALTH",
["UnitIsGhost"] = "UNIT_HEALTH",
- ["UnitIsConnected"] = "UNIT_HEALTH",
+ ["UnitIsConnected"] = "UNIT_HEALTH UNIT_CONNECTION",
["UnitIsAFK"] = "PLAYER_FLAGS_CHANGED",
["UnitIsDND"] = "PLAYER_FLAGS_CHANGED",
["UnitIsPVP"] = "PLAYER_FLAGS_CHANGED UNIT_FACTION",
- ["UnitIsPartyLeader"] = "PARTY_LEADER_CHANGED PARTY_MEMBERS_CHANGED",
+ ["UnitIsGroupLeader"] = "PARTY_LEADER_CHANGED GROUP_ROSTER_UPDATE",
["UnitIsPVPFreeForAll"] = "PLAYER_FLAGS_CHANGED UNIT_FACTION",
["UnitCastingInfo"] = "UNIT_SPELLCAST_START UNIT_SPELLCAST_STOP UNIT_SPELLCAST_FAILED UNIT_SPELLCAST_INTERRUPTED UNIT_SPELLCAST_DELAYED",
["UnitChannelInfo"] = "UNIT_SPELLCAST_CHANNEL_START UNIT_SPELLCAST_CHANNEL_STOP UNIT_SPELLCAST_CHANNEL_INTERRUPTED UNIT_SPELLCAST_CHANNEL_UPDATE",
- ["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",
["GetTotemInfo"] = "PLAYER_TOTEM_UPDATE",
["GetXPExhaustion"] = "UPDATE_EXHAUSTION",
@@ -1171,11 +1514,10 @@ local function loadAPIEvents()
["GetRuneCooldown"] = "RUNE_POWER_UPDATE",
["GetRuneType"] = "RUNE_TYPE_UPDATE",
["GetRaidTargetIndex"] = "RAID_TARGET_UPDATE",
- ["GetComboPoints"] = "UNIT_COMBO_POINTS",
- ["GetNumPartyMembers"] = "PARTY_MEMBERS_CHANGED",
- ["GetNumRaidMembers"] = "RAID_ROSTER_UPDATE",
- ["GetRaidRosterInfo"] = "RAID_ROSTER_UPDATE",
- ["GetPetHappiness"] = "UNIT_HAPPINESS",
+ ["GetComboPoints"] = "UNIT_POWER_FREQUENT",
+ ["GetNumSubgroupMembers"] = "GROUP_ROSTER_UPDATE",
+ ["GetNumGroupMembers"] = "GROUP_ROSTER_UPDATE",
+ ["GetRaidRosterInfo"] = "GROUP_ROSTER_UPDATE",
["GetReadyCheckStatus"] = "READY_CHECK READY_CHECK_CONFIRM READY_CHECK_FINISHED",
["GetLootMethod"] = "PARTY_LOOT_METHOD_CHANGED",
["GetThreatStatusColor"] = "UNIT_THREAT_SITUATION_UPDATE",
@@ -1183,7 +1525,7 @@ local function loadAPIEvents()
["UnitDetailedThreatSituation"] = "UNIT_THREAT_SITUATION_UPDATE",
}
end
-
+
-- Scan the actual tag code to find the events it uses
local alreadyScanned = {}
function Tags:IdentifyEvents(code, parentTag)
@@ -1197,34 +1539,34 @@ function Tags:IdentifyEvents(code, parentTag)
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 .. " "
+ 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 code = ShadowUF.Tags.defaultTags[tag] or ShadowUF.db.profile.tags[tag] and ShadowUF.db.profile.tags[tag].func
- eventList = eventList .. " " .. self:IdentifyEvents(code, tag)
+ 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
@@ -1240,28 +1582,28 @@ function Tags:Verify()
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))
@@ -1271,7 +1613,7 @@ function Tags:Verify()
funct("player")
end
end
-
+
if( fine ) then
print("Verified tags, everything is fine.")
end
diff --git a/modules/totems.lua b/modules/totems.lua
index fd9e92d9a..2540a99c2 100755
--- a/modules/totems.lua
+++ b/modules/totems.lua
@@ -2,37 +2,70 @@ 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
-if( select(2, UnitClass("player")) == "DEATHKNIGHT" ) then
+local playerClass = select(2, UnitClass("player"))
+if( playerClass == "DEATHKNIGHT" ) then
MAX_TOTEMS = 1
- ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Guardian bar"], true, "DEATHKNIGHT")
+ -- 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)
- totem:SetFrameLevel(1)
+ local totem = ShadowUF.Units:CreateBar(frame.totemBar)
totem:SetMinMaxValues(0, 1)
totem:SetValue(0)
- totem.id = MAX_TOTEMS == 1 and 1 or TOTEM_PRIORITIES[id]
-
+ totem.id = MAX_TOTEMS == 1 and 1 or priorities[id]
+ totem.parent = frame
+
if( id > 1 ) then
totem:SetPoint("TOPLEFT", frame.totemBar.totems[id - 1], "TOPRIGHT", 1, 0)
else
totem:SetPoint("TOPLEFT", frame.totemBar, "TOPLEFT", 0, 0)
end
-
+
table.insert(frame.totemBar.totems, totem)
end
-
- if( MAX_TOTEMS == 1 ) 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
+ 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}
@@ -40,72 +73,138 @@ function Totems:OnEnable(frame)
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( frame.visibility.totemBar ) then
- local barWidth = (frame.totemBar:GetWidth() - (MAX_TOTEMS - 1)) / MAX_TOTEMS
-
- for _, totem in pairs(frame.totemBar.totems) do
- if( ShadowUF.db.profile.units[frame.unitType].totemBar.background ) then
- local color = ShadowUF.db.profile.bars.backgroundColor or ShadowUF.db.profile.units[frame.unitType].totemBar.backgroundColor or totemColors[totem.id]
- totem.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
- totem.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha)
- totem.background:Show()
- else
- totem.background:Hide()
- end
-
- totem:SetHeight(frame.totemBar:GetHeight())
- totem:SetWidth(barWidth)
- totem:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
- totem:SetStatusBarColor(totemColors[totem.id].r, totemColors[totem.id].g, totemColors[totem.id].b, ShadowUF.db.profile.bars.alpha)
- totem:GetStatusBarTexture():SetHorizTile(false)
+ if( not frame.visibility.totemBar ) then return end
+
+ local barWidth = (frame.totemBar:GetWidth() - (MAX_TOTEMS - 1)) / MAX_TOTEMS
+ local config = ShadowUF.db.profile.units[frame.unitType].totemBar
+
+ for _, totem in pairs(frame.totemBar.totems) do
+ totem:SetHeight(frame.totemBar:GetHeight())
+ totem:SetWidth(barWidth)
+ totem:SetOrientation(ShadowUF.db.profile.units[frame.unitType].totemBar.vertical and "VERTICAL" or "HORIZONTAL")
+ totem:SetReverseFill(ShadowUF.db.profile.units[frame.unitType].totemBar.reverse and true or false)
+ totem:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar)
+ totem:GetStatusBarTexture():SetHorizTile(false)
+
+ totem.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar)
+
+ if( config.background or config.invert ) then
+ totem.background:Show()
+ else
+ totem.background:Hide()
+ end
+
+ if( not ShadowUF.db.profile.units[frame.unitType].totemBar.icon ) then
+ frame:SetBlockColor(totem, "totemBar", totemColors[totem.id].r, totemColors[totem.id].g, totemColors[totem.id].b)
+ end
+
+ if( config.secure ) then
+ totem.secure = totem.secure or CreateFrame("Button", frame:GetName() .. "Secure" .. totem.id, totem, "SecureUnitButtonTemplate")
+ totem.secure:RegisterForClicks("RightButtonUp")
+ totem.secure:SetAllPoints(totem)
+ totem.secure:SetAttribute("type2", "destroytotem")
+ totem.secure:SetAttribute("*totem-slot*", totem.id)
+ totem.secure:Show()
+
+ elseif( totem.secure ) then
+ totem.secure:Hide()
end
end
+
+ self:Update(frame)
end
local function totemMonitor(self, elapsed)
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 = GetTotemInfo(indicator.id)
+ local have, _name, start, duration, icon
+ if MAX_TOTEMS == 1 and indicator.id == 1 then
+ local id = 1
+ while not have and id <= 4 do
+ have, _name, start, duration, icon = GetTotemInfo(id)
+ id = id + 1
+ end
+ else
+ have, _name, start, duration, icon = GetTotemInfo(indicator.id)
+ end
if( have and start > 0 ) then
+ if( ShadowUF.db.profile.units[frame.unitType].totemBar.icon ) then
+ indicator:SetStatusBarTexture(icon)
+ end
+
indicator.have = true
indicator.endTime = start + duration
indicator:SetMinMaxValues(0, duration)
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
-
- -- Only guardian timers should auto hide, nothing else
- if( MAX_TOTEMS == 1 ) then
- ShadowUF.Layout:SetBarVisibility(frame, "totemBar", totalActive > 0)
+
+ if( not frame.inVehicle ) then
+ -- Guardian timers always auto hide or if it's flagged to not always be shown
+ if( MAX_TOTEMS == 1 or not ShadowUF.db.profile.units[frame.unitType].totemBar.showAlways ) then
+ ShadowUF.Layout:SetBarVisibility(frame, "totemBar", totalActive > 0)
+ end
end
end
diff --git a/modules/units.lua b/modules/units.lua
old mode 100644
new mode 100755
index 8255da444..93eb8563a
--- a/modules/units.lua
+++ b/modules/units.lua
@@ -1,15 +1,34 @@
-local Units = {headerFrames = {}, unitFrames = {}, frameList = {}, unitEvents = {}}
-Units.childUnits = {["partytarget"] = "party", ["partypet"] = "party", ["maintanktarget"] = "maintank", ["mainassisttarget"] = "mainassist", ["bosstarget"] = "boss", ["arenatarget"] = "arena", ["arenapet"] = "arena"}
-Units.zoneUnits = {["arena"] = "arena", ["boss"] = "raid"}
+local Units = {headerFrames = {}, unitFrames = {}, frameList = {}, unitEvents = {}, remappedUnits = {}, canCure = {}}
+Units.childUnits = {["partytarget"] = "party", ["partytargettarget"] = "party", ["partypet"] = "party", ["maintanktarget"] = "maintank", ["mainassisttarget"] = "mainassist", ["bosstarget"] = "boss", ["arenatarget"] = "arena", ["arenatargettarget"] = "arena", ["arenapet"] = "arena", ["battlegroundpet"] = "battleground", ["battlegroundtarget"] = "battleground", ["battlegroundtargettarget"] = "battleground", ["maintanktargettarget"] = "maintank", ["mainassisttargettarget"] = "mainassist", ["bosstargettarget"] = "boss"}
+Units.zoneUnits = {["arena"] = "arena", ["arenapet"] = "arena", ["arenatarget"] = "arena", ["arenatargettarget"] = "arena", ["boss"] = {"party", "raid"}, ["bosstarget"] = {"party", "raid"}, ["battleground"] = "pvp", ["battlegroundtarget"] = "pvp", ["battlegroundtargettarget"] = "pvp", ["battlegroundpet"] = "pvp", ["bosstargettarget"] = {"party", "raid"}}
+Units.remappedUnits = {["battleground"] = "arena", ["battlegroundpet"] = "arenapet", ["battlegroundtarget"] = "arenatarget", ["battlegroundtargettarget"] = "arenatargettarget"}
+Units.headerUnits = {["raid"] = true, ["party"] = true, ["maintank"] = true, ["mainassist"] = true, ["raidpet"] = true, ["partypet"] = true}
local stateMonitor = CreateFrame("Frame", nil, nil, "SecureHandlerBaseTemplate")
+stateMonitor.raids = {}
local playerClass = select(2, UnitClass("player"))
-local unitFrames, headerFrames, frameList, unitEvents, childUnits, queuedCombat = Units.unitFrames, Units.headerFrames, Units.frameList, Units.unitEvents, Units.childUnits, {}
+local unitFrames, headerFrames, frameList, unitEvents, childUnits, headerUnits, queuedCombat, zoneUnits = Units.unitFrames, Units.headerFrames, Units.frameList, Units.unitEvents, Units.childUnits, Units.headerUnits, {}, Units.zoneUnits
+local remappedUnits = Units.remappedUnits
local _G = getfenv(0)
ShadowUF.Units = Units
ShadowUF:RegisterModule(Units, "units")
-
+
+-- This is the wrapper frame that everything parents to so we can just hide it when we need to deal with pet battles
+local petBattleFrame = CreateFrame("Frame", "SUFWrapperFrame", UIParent, "SecureHandlerBaseTemplate")
+petBattleFrame:SetFrameStrata("BACKGROUND")
+petBattleFrame:SetAllPoints(UIParent)
+petBattleFrame:WrapScript(petBattleFrame, "OnAttributeChanged", [[
+ if( name ~= "state-petbattle" ) then return end
+ if( value == "active" ) then
+ self:Hide()
+ else
+ self:Show()
+ end
+]])
+
+RegisterStateDriver(petBattleFrame, "petbattle", "[petbattle] active; none")
+
-- Frame shown, do a full update
local function FullUpdate(self)
for i=1, #(self.fullUpdates), 2 do
@@ -18,36 +37,71 @@ local function FullUpdate(self)
end
end
+-- Re-registers events when unit changes
+local function ReregisterUnitEvents(self)
+ -- Not an unit event
+ if( ShadowUF.fakeUnits[self.unitRealType] or not headerUnits[self.unitType] ) then return end
+
+ for event, list in pairs(self.registeredEvents) do
+ if( unitEvents[event] ) then
+ local hasHandler
+ for handler in pairs(list) do
+ hasHandler = true
+ break
+ end
+
+ if( hasHandler ) then
+ self:UnregisterEvent(event)
+ self:BlizzRegisterUnitEvent(event, self.unitOwner, self.vehicleUnit)
+ end
+ end
+ end
+end
+
-- Register an event that should always call the frame
-local function RegisterNormalEvent(self, event, handler, func)
+local function RegisterNormalEvent(self, event, handler, func, unitOverride)
-- Make sure the handler/func exists
if( not handler[func] ) then
error(string.format("Invalid handler/function passed for %s on event %s, the function %s does not exist.", self:GetName() or tostring(self), tostring(event), tostring(func)), 3)
return
end
- self:RegisterEvent(event)
+ -- 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] ) then
+ 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
+ for _handler in pairs(self.registeredEvents[event]) do
hasHandler = true
break
end
-
+
if( not hasHandler ) then
self:UnregisterEvent(event)
end
@@ -63,7 +117,7 @@ end
-- Register a function to be called in an OnUpdate if it's an invalid unit (targettarget/etc)
local function RegisterUpdateFunc(self, handler, func)
if( not handler[func] ) then
- error(string.format("Invalid handler/function passed to RegisterUpdateFunc for %s, the function %s does not exist.", self:GetName() or tostring(self), event, func), 3)
+ error(string.format("Invalid handler/function passed to RegisterUpdateFunc for %s, the function %s does not exist.", self:GetName() or tostring(self), func), 3)
return
end
@@ -73,7 +127,7 @@ local function RegisterUpdateFunc(self, handler, func)
return
end
end
-
+
table.insert(self.fullUpdates, handler)
table.insert(self.fullUpdates, func)
end
@@ -97,16 +151,18 @@ local function UnregisterAll(self, handler)
end
for event, list in pairs(self.registeredEvents) do
- list[handler] = nil
-
- local hasRegister
- for handler in pairs(list) do
- hasRegister = true
- break
- end
-
- if( not hasRegister ) then
- self:UnregisterEvent(event)
+ if( list[handler] ) then
+ list[handler] = nil
+
+ local hasRegister
+ for _handler in pairs(list) do
+ hasRegister = true
+ break
+ end
+
+ if( not hasRegister ) then
+ self:UnregisterEvent(event)
+ end
end
end
end
@@ -114,7 +170,7 @@ 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
@@ -128,9 +184,32 @@ local function SetRangeAlpha(self, alpha)
end
end
+local function SetBarColor(self, key, r, g, b)
+ self:SetBlockColor(self[key], key, r, g, b)
+end
+
+local function SetBlockColor(self, bar, key, r, g, b)
+ local bgColor = bar.background.overrideColor or bar.background.backgroundColor
+ if( not ShadowUF.db.profile.units[self.unitType][key].invert ) then
+ bar:SetStatusBarColor(r, g, b, ShadowUF.db.profile.bars.alpha)
+ if( not bgColor ) then
+ bar.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.backgroundAlpha)
+ else
+ bar.background:SetVertexColor(bgColor.r, bgColor.g, bgColor.b, ShadowUF.db.profile.bars.backgroundAlpha)
+ end
+ else
+ bar.background:SetVertexColor(r, g, b, ShadowUF.db.profile.bars.alpha)
+ if( not bgColor ) then
+ bar:SetStatusBarColor(0, 0, 0, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
+ else
+ bar:SetStatusBarColor(bgColor.r, bgColor.g, bgColor.b, 1 - ShadowUF.db.profile.bars.backgroundAlpha)
+ end
+ end
+end
+
-- Event handling
local function OnEvent(self, event, unit, ...)
- if( not unitEvents[event] or self.unit == unit ) then
+ if( not unitEvents[event] or self.unit == unit or (self.unitEventOverrides and self.unitEventOverrides[event] == unit)) then
for handler, func in pairs(self.registeredEvents[event]) do
handler[func](handler, self, event, unit, ...)
end
@@ -140,6 +219,12 @@ end
Units.OnEvent = OnEvent
-- Do a full update OnShow, and stop watching for events when it's not visible
+local function OnShowForced(self)
+ -- Reset the event handler
+ self:SetScript("OnEvent", OnEvent)
+ self:FullUpdate()
+end
+
local function OnShow(self)
-- Reset the event handler
self:SetScript("OnEvent", OnEvent)
@@ -148,7 +233,7 @@ end
local function OnHide(self)
self:SetScript("OnEvent", nil)
-
+
-- If it's a volatile such as target or focus, next time it's shown it has to do an update
-- OR if the unit is still shown, but it's been hidden because our parent (Basically UIParent)
-- we want to flag it as having changed so it can be updated
@@ -157,31 +242,20 @@ local function OnHide(self)
end
end
--- *target units do not give events, polling is necessary here
-local function TargetUnitUpdate(self, elapsed)
- self.timeElapsed = self.timeElapsed + elapsed
-
- if( self.timeElapsed >= 0.50 ) then
- self.timeElapsed = self.timeElapsed - 0.50
-
- -- Have to make sure the unit exists or else the frame will flash offline for a second until it hides
- if( UnitExists(self.unit) ) then
- self:FullUpdate()
- end
- end
-end
-
-- Deal with enabling modules inside a zone
local function SetVisibility(self)
local layoutUpdate
- local instanceType = select(2, IsInInstance())
+ local instanceType = select(2, IsInInstance()) or "none"
+ local playerSpec = GetSpecialization()
+ if( instanceType == "scenario" ) then instanceType = "party" end
+ if( instanceType == "interior" ) then instanceType = "neighborhood" 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
@@ -192,7 +266,7 @@ local function SetVisibility(self)
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
@@ -201,12 +275,22 @@ local function SetVisibility(self)
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)
@@ -215,11 +299,11 @@ local function SetVisibility(self)
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)
@@ -232,9 +316,9 @@ local function checkVehicleData(self, 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) ) then
+ if( self.dataAttempts >= 6 or not UnitHasVehicleUI(self.unitOwner) or not UnitHasVehiclePlayerFrameUI(self.unitOwner) ) then
self.timeElapsed = nil
self.dataAttempts = nil
self:SetScript("OnUpdate", nil)
@@ -242,26 +326,25 @@ local function checkVehicleData(self, elapsed)
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
+end
-- Check if a unit entered a vehicle
function Units:CheckVehicleStatus(frame, event, unit)
if( event and frame.unitOwner ~= unit ) then return end
-
+
-- Not in a vehicle yet, and they entered one that has a UI or they were in a vehicle but the GUID changed (vehicle -> vehicle)
- if( ( not frame.inVehicle or frame.unitGUID ~= UnitGUID(frame.vehicleUnit) ) and UnitHasVehicleUI(frame.unitOwner) and not ShadowUF.db.profile.units[frame.unitType].disableVehicle ) then
-
+ if( ( not frame.inVehicle or frame.unitGUID ~= UnitGUID(frame.vehicleUnit) ) and UnitHasVehicleUI(frame.unitOwner) and UnitHasVehiclePlayerFrameUI(frame.unitOwner) and not ShadowUF.db.profile.units[frame.unitType].disableVehicle ) then
frame.inVehicle = true
frame.unit = frame.vehicleUnit
@@ -273,26 +356,14 @@ function Units:CheckVehicleStatus(frame, event, unit)
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 ShadowUF.db.profile.units[frame.unitType].disableVehicle ) ) then
+ elseif( frame.inVehicle and ( not UnitHasVehicleUI(frame.unitOwner) or not UnitHasVehiclePlayerFrameUI(frame.unitOwner) or ShadowUF.db.profile.units[frame.unitType].disableVehicle ) ) then
frame.inVehicle = false
frame.unit = frame.unitOwner
frame.unitGUID = UnitGUID(frame.unit)
frame:FullUpdate()
end
-
- -- Keep track of the actual players unit so we can quickly see what unit to scan
- --[[
- if( frame.unitOwner == "player" and ShadowUF.playerUnit ~= frame.unit ) then
- ShadowUF.playerUnit = frame.unit
-
- if( not ShadowUF.db.profile.hidden.buffs and ShadowUF.db.profile.units.player.enabled and BuffFrame:IsVisible() ) then
- PlayerFrame.unit = frame.unit
- BuffFrame_Update()
- end
- end
- ]]
end
-- Handles checking for GUID changes for doing a full update, this fixes frames sometimes showing the wrong unit when they change
@@ -300,7 +371,7 @@ 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
@@ -323,7 +394,7 @@ function Units:CheckGroupedUnitStatus(frame)
if( frame.inVehicle and not UnitExists(frame.unit) and UnitExists(frame.unitOwner) ) then
frame.inVehicle = false
frame.unit = frame.unitOwner
- frame.unitGUID = guid
+ frame.unitGUID = UnitGUID(frame.unit)
frame:FullUpdate()
else
frame.unitGUID = UnitGUID(frame.unit)
@@ -331,37 +402,10 @@ function Units:CheckGroupedUnitStatus(frame)
end
end
-local function ShowMenu(self)
- if( UnitIsUnit(self.unit, "player") ) then
- ToggleDropDownMenu(1, nil, PlayerFrameDropDown, "cursor")
- elseif( self.unit == "pet" or self.unit == "vehicle" ) then
- ToggleDropDownMenu(1, nil, PetFrameDropDown, "cursor")
- elseif( self.unit == "target" ) then
- ToggleDropDownMenu(1, nil, TargetFrameDropDown, "cursor")
- elseif( self.unitType == "boss" ) then
- ToggleDropDownMenu(1, nil, _G["Boss" .. self.unitID .. "TargetFrameDropDown"], "cursor")
- elseif( self.unit == "focus" ) then
- ToggleDropDownMenu(1, nil, FocusFrameDropDown, "cursor")
- elseif( self.unitRealType == "party" ) then
- ToggleDropDownMenu(1, nil, _G["PartyMemberFrame" .. self.unitID .. "DropDown"], "cursor")
- elseif( self.unitRealType == "raid" ) then
- HideDropDownMenu(1)
-
- local menuFrame = FriendsDropDown
- menuFrame.displayMode = "MENU"
- menuFrame.initialize = RaidFrameDropDown_Initialize
- menuFrame.userData = self.unitID
- menuFrame.unit = self.unitOwner
- menuFrame.name = UnitName(self.unitOwner)
- menuFrame.id = self.unitID
- ToggleDropDownMenu(1, nil, menuFrame, "cursor")
- end
-end
-
-- More fun with sorting, due to sorting magic we have to check if we want to create stuff when the frame changes of partys too
local function createChildUnits(self)
if( not self.unitID ) then return end
-
+
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)
@@ -372,7 +416,7 @@ 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
@@ -381,6 +425,12 @@ local function updateChildUnits(...)
end
end
+local function createFakeUnitUpdateTimer(frame)
+ if( not frame.updateTimer ) then
+ frame.updateTimer = C_Timer.NewTicker(0.5, function() if( UnitExists(frame.unit) ) then frame:FullUpdate() end end)
+ end
+end
+
-- Attribute set, something changed
-- unit = Active unitid
-- unitID = Just the number from the unitid
@@ -390,25 +440,27 @@ end
-- vehicleUnit = Unit to use when the unitOwner is in a vehicle
OnAttributeChanged = function(self, name, unit)
if( name ~= "unit" or not unit or unit == self.unitOwner ) then return end
+
-- Nullify the previous entry if it had one
- if( self.unit and unitFrames[self.unit] == self ) then unitFrames[self.unit] = nil end
-
+ local configUnit = self.unitUnmapped or unit
+ if( self.configUnit and unitFrames[self.configUnit] == self ) then unitFrames[self.configUnit] = nil end
+
-- Setup identification data
self.unit = unit
self.unitID = tonumber(string.match(unit, "([0-9]+)"))
self.unitRealType = string.gsub(unit, "([0-9]+)", "")
- self.unitType = self.unitType or self.unitRealType
+ self.unitType = self.unitUnmapped and string.gsub(self.unitUnmapped, "([0-9]+)", "") or self.unitType or self.unitRealType
self.unitOwner = unit
self.vehicleUnit = self.unitOwner == "player" and "vehicle" or self.unitRealType == "party" and "partypet" .. self.unitID or self.unitRealType == "raid" and "raidpet" .. self.unitID or nil
self.inVehicle = nil
-
+
-- Split everything into two maps, this is the simple parentUnit -> frame map
-- This is for things like finding a party parent for party target/pet, the main map for doing full updates is
-- an indexed frame that is updated once and won't have unit conflicts.
if( self.unitRealType == self.unitType ) then
- unitFrames[unit] = self
+ unitFrames[configUnit] = self
end
-
+
frameList[self] = true
if( self.hasChildren ) then
@@ -422,43 +474,50 @@ OnAttributeChanged = function(self, name, unit)
-- Don't need to recheck the unitType and force a full update, because a raid frame can never become
-- a party frame, or a player frame and so on
if( self.unitInitialized ) then
+ self:ReregisterUnitEvents()
self:FullUpdate()
return
end
-
+
self.unitInitialized = true
-- Add to Clique
- ClickCastFrames = ClickCastFrames or {}
- ClickCastFrames[self] = true
-
+ if( not self:GetAttribute("isHeaderDriven") ) then
+ ClickCastFrames = ClickCastFrames or {}
+ ClickCastFrames[self] = true
+ end
+
-- Handles switching the internal unit variable to that of their vehicle
if( self.unit == "player" or self.unitRealType == "party" or self.unitRealType == "raid" ) then
self:RegisterNormalEvent("UNIT_ENTERED_VEHICLE", Units, "CheckVehicleStatus")
self:RegisterNormalEvent("UNIT_EXITED_VEHICLE", Units, "CheckVehicleStatus")
self:RegisterUpdateFunc(Units, "CheckVehicleStatus")
- end
-
+ 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) ) then
+ if( UnitHasVehicleUI(self.unitRealOwner) and UnitHasVehiclePlayerFrameUI(self.unitRealOwner) ) then
self:SetAttribute("unitIsVehicle", true)
end
-
+
-- Hide any pet that became a vehicle, we detect this by the owner being untargetable but they have a pet out
stateMonitor:WrapScript(self, "OnAttributeChanged", [[
if( name == "state-vehicleupdated" ) then
- self:SetAttribute("unitIsVehicle", value == "vehicle" and true or false)
+ self:SetAttribute("unitIsVehicle", UnitHasVehicleUI(self:GetAttribute("unitRealOwner")) and value == "vehicle" and true or false)
elseif( name == "disablevehicleswap" or name == "state-unitexists" or name == "unitisvehicle" ) then
-- Unit does not exist, OR unit is a vehicle and vehicle swap is not disabled, hide frame
if( not self:GetAttribute("state-unitexists") or ( self:GetAttribute("unitIsVehicle") and not self:GetAttribute("disableVehicleSwap") ) ) then
@@ -475,47 +534,72 @@ OnAttributeChanged = function(self, name, unit)
elseif( self.unit == "target" ) then
self.isUnitVolatile = true
self:RegisterNormalEvent("PLAYER_TARGET_CHANGED", Units, "CheckUnitStatus")
+ self:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "FullUpdate")
-- Automatically do a full update on focus change
elseif( self.unit == "focus" ) then
self.isUnitVolatile = true
self:RegisterNormalEvent("PLAYER_FOCUS_CHANGED", Units, "CheckUnitStatus")
-
+ self:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "FullUpdate")
+
elseif( self.unit == "player" ) then
- self:SetAttribute("toggleForVehicle", true)
-
+ -- 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.timeElapsed = 0
- self:SetScript("OnUpdate", TargetUnitUpdate)
self:RegisterNormalEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT", self, "FullUpdate")
-
+ self:RegisterUnitEvent("UNIT_TARGETABLE_CHANGED", self, "FullUpdate")
+ self:RegisterUnitEvent("UNIT_NAME_UPDATE", Units, "CheckUnitStatus")
+
+ -- Update arena
+ elseif( self.unitType == "arena" ) then
+ self:RegisterUnitEvent("UNIT_NAME_UPDATE", self, "FullUpdate")
+ self:RegisterUnitEvent("UNIT_CONNECTION", self, "FullUpdate")
+
+ -- Update battleground
+ elseif( self.unitType == "battleground" ) then
+ self:RegisterUnitEvent("UNIT_NAME_UPDATE", Units, "CheckUnitStatus")
+
-- Check for a unit guid to do a full update
elseif( self.unitRealType == "raid" ) then
- self:RegisterNormalEvent("RAID_ROSTER_UPDATE", Units, "CheckGroupedUnitStatus")
+ self:RegisterNormalEvent("GROUP_ROSTER_UPDATE", Units, "CheckGroupedUnitStatus")
self:RegisterUnitEvent("UNIT_NAME_UPDATE", Units, "CheckUnitStatus")
-
+ self:RegisterUnitEvent("UNIT_CONNECTION", self, "FullUpdate")
+
-- Party members need to watch for changes
elseif( self.unitRealType == "party" ) then
- self:RegisterNormalEvent("PARTY_MEMBERS_CHANGED", Units, "CheckGroupedUnitStatus")
+ self:RegisterNormalEvent("GROUP_ROSTER_UPDATE", Units, "CheckGroupedUnitStatus")
+ self:RegisterNormalEvent("PARTY_MEMBER_ENABLE", Units, "CheckGroupedUnitStatus")
+ self:RegisterNormalEvent("PARTY_MEMBER_DISABLE", Units, "CheckGroupedUnitStatus")
self:RegisterUnitEvent("UNIT_NAME_UPDATE", Units, "CheckUnitStatus")
-
+ self:RegisterUnitEvent("UNIT_OTHER_PARTY_CHANGED", self, "FullUpdate")
+ self:RegisterUnitEvent("UNIT_CONNECTION", self, "FullUpdate")
+
-- *target units are not real units, thus they do not receive events and must be polled for data
elseif( ShadowUF.fakeUnits[self.unitRealType] ) then
- self.timeElapsed = 0
- self:SetScript("OnUpdate", TargetUnitUpdate)
-
+ createFakeUnitUpdateTimer(self)
+
-- Speeds up updating units when their owner changes target, if party1 changes target then party1target is force updated, if target changes target
-- then targettarget and targettargettarget are also force updated
if( self.unitRealType == "partytarget" ) then
self.unitRealOwner = ShadowUF.partyUnits[self.unitID]
+ elseif( self.unitRealType == "partytargettarget" ) then
+ self.unitRealOwner = ShadowUF.partyUnits[self.unitID] .. "target"
elseif( self.unitRealType == "raid" ) then
self.unitRealOwner = ShadowUF.raidUnits[self.unitID]
elseif( self.unitRealType == "arenatarget" ) then
self.unitRealOwner = ShadowUF.arenaUnits[self.unitID]
+ elseif( self.unitRealType == "arenatargettarget" ) then
+ self.unitRealOwner = ShadowUF.arenaUnits[self.unitID] .. "target"
elseif( self.unit == "focustarget" ) then
self.unitRealOwner = "focus"
self:RegisterNormalEvent("PLAYER_FOCUS_CHANGED", Units, "CheckUnitStatus")
@@ -526,56 +610,94 @@ OnAttributeChanged = function(self, name, unit)
self:RegisterNormalEvent("UNIT_TARGET", Units, "CheckPetUnitUpdated")
end
-
- self.menu = ShowMenu
+
self:SetVisibility()
Units:CheckUnitStatus(self)
end
Units.OnAttributeChanged = OnAttributeChanged
--- Header unit initialized
-local function initializeUnit(self)
- local unitType = self:GetParent().unitType
- local config = ShadowUF.db.profile.units[unitType]
-
- self.ignoreAnchor = true
- self.unitType = unitType
- self:SetAttribute("initial-height", config.height)
- self:SetAttribute("initial-width", config.width)
- self:SetAttribute("initial-scale", config.scale)
+local secureInitializeUnit = [[
+ local header = self:GetParent()
+
+ self:SetHeight(header:GetAttribute("style-height"))
+ self:SetWidth(header:GetAttribute("style-width"))
+ self:SetScale(header:GetAttribute("style-scale"))
+
self:SetAttribute("toggleForVehicle", true)
-
- Units:CreateUnit(self)
+
+ self:SetAttribute("*type1", "target")
+ self:SetAttribute("*type2", "togglemenu")
+ self:SetAttribute("type2", "togglemenu")
+
+ self:SetAttribute("isHeaderDriven", true)
+
+ -- initialize frame
+ header:CallMethod("initialConfigFunction", self:GetName())
+
+ -- Clique integration
+ local clickHeader = header:GetFrameRef("clickcast_header")
+ if( clickHeader ) then
+ clickHeader:SetAttribute("clickcast_button", self)
+ clickHeader:RunAttribute("clickcast_register")
+ end
+]]
+
+local unitButtonTemplate = ClickCastHeader and ("ClickCastUnitTemplate,SUF_SecureUnitTemplate,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( not ShadowUF.db.profile.tooltipCombat or not InCombatLockdown() ) then
- UnitFrame_OnEnter(self)
+ if( self.OnEnter ) then
+ self:OnEnter()
end
end
--- Reset the fact that we clamped the dropdown to the screen to be safe
-DropDownList1:HookScript("OnHide", function(self)
- self:SetClampedToScreen(false)
-end)
+local function OnLeave(self)
+ if( self.OnLeave ) then
+ self:OnLeave()
+ end
+end
--- Reposition the dropdown
-local function PostClick(self)
- if( UIDROPDOWNMENU_OPEN_MENU and DropDownList1:IsShown() ) then
- DropDownList1:ClearAllPoints()
- DropDownList1:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, 0)
- DropDownList1:SetClampedToScreen(true)
+local function SUF_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
@@ -584,27 +706,36 @@ function Units:CreateUnit(...)
frame.SetRangeAlpha = SetRangeAlpha
frame.DisableRangeAlpha = DisableRangeAlpha
frame.UnregisterUpdateFunc = UnregisterUpdateFunc
+ frame.ReregisterUnitEvents = ReregisterUnitEvents
+ frame.SetBarColor = SetBarColor
+ frame.SetBlockColor = SetBlockColor
frame.FullUpdate = FullUpdate
frame.SetVisibility = SetVisibility
+ frame.UnitClassToken = ClassToken
frame.topFrameLevel = 5
-
+
-- Ensures that text is the absolute highest thing there is
frame.highFrame = CreateFrame("Frame", nil, frame)
frame.highFrame:SetFrameLevel(frame.topFrameLevel + 2)
frame.highFrame:SetAllPoints(frame)
-
- frame:SetScript("OnAttributeChanged", OnAttributeChanged)
+
+ frame:HookScript("OnAttributeChanged", OnAttributeChanged)
frame:SetScript("OnEvent", OnEvent)
- frame:SetScript("OnEnter", OnEnter)
- frame:SetScript("OnLeave", UnitFrame_OnLeave)
+ frame:HookScript("OnEnter", OnEnter)
+ frame:HookScript("OnLeave", OnLeave)
frame:SetScript("OnShow", OnShow)
frame:SetScript("OnHide", OnHide)
- frame:SetScript("PostClick", PostClick)
- frame:RegisterForClicks("AnyUp")
- frame:SetAttribute("*type1", "target")
- frame:SetAttribute("*type2", "menu")
-
+ frame.OnEnter = SUF_OnEnter
+ frame.OnLeave = SUF_OnLeave
+
+ -- non-header frames don't set those, so we need to do it
+ if( not InCombatLockdown() and not frame:GetAttribute("isHeaderDriven") ) then
+ frame:RegisterForClicks("AnyUp")
+ frame:SetAttribute("*type1", "target")
+ frame:SetAttribute("*type2", "togglemenu")
+ end
+
return frame
end
@@ -620,24 +751,24 @@ function Units:ReloadHeader(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:FireModuleEvent("OnLayoutReload", 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()
@@ -670,45 +801,45 @@ function Units:SetHeaderAttributes(frame, type)
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, xMod, yMod = ShadowUF.Layout:GetSplitRelativeAnchor(config.attribPoint, config.attribAnchorPoint)
+ 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 and childHeader:IsVisible() ) then
+ 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 % config.groupsPerRow == 1 ) then
+ 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
@@ -717,17 +848,22 @@ function Units:SetHeaderAttributes(frame, type)
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 * xMod, config.columnSpacing * yMod)
+ childHeader:SetPoint(anchorPoint, lastHeader, relativePoint, config.columnSpacing * xModRow, config.columnSpacing * yModRow)
end
lastHeader = childHeader
end
- 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
@@ -744,43 +880,77 @@ function Units:SetHeaderAttributes(frame, type)
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,DRUID,HUNTER,MAGE,PALADIN,PRIEST,ROGUE,SHAMAN,WARLOCK,WARRIOR")
+ 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" ) then
- frame:SetWidth(config.width)
+ elseif( type == "boss" or type == "arena" or type == "battleground" ) then
+ frame:SetAttribute("attribPoint", config.attribPoint)
+ frame:SetAttribute("baseOffset", config.offset)
+ frame:SetAttribute("childChanged", 1)
+
self:PositionHeaderChildren(frame)
-
+
-- Update party frames to not show anyone if they should be in raids
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
-
- -- Update the raid frames to if they should be showing raid or party
- if( type == "party" or type == "raid" ) then
+
+ if( type == "raid" ) then
self:CheckGroupVisibility()
-
- -- Need to update our flags on the state monitor so it knows what to do
- stateMonitor:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.party.hideSemiRaid)
- stateMonitor:SetAttribute("hideAnyRaid", ShadowUF.db.profile.units.party.hideAnyRaid)
+
+ for id, monitor in pairs(stateMonitor.raids) do
+ monitor:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.raid.hideSemiRaid)
+ end
+ end
+
+ if( not InCombatLockdown() and headerUnits[type] and frame.shouldReset ) then
+ -- Children no longer have ClearAllPoints() called on them before they are repositioned
+ -- this tries to stop it from bugging out by clearing it then forcing it to reposition everything
+ local name = frame:GetName() .. "UnitButton"
+ local index = 1
+ local child = _G[name .. index]
+ while( child ) do
+ child:ClearAllPoints()
+
+ index = index + 1
+ child = _G[name .. index]
+ end
+
+ -- Hiding and reshowing the header forces an update
+ if( frame:IsShown() ) then
+ frame:Hide()
+ frame:Show()
+ end
end
+
+ frame.shouldReset = true
end
-- Load a single unit such as player, target, pet, etc
@@ -790,52 +960,100 @@ function Units:LoadUnit(unit)
RegisterUnitWatch(unitFrames[unit], unitFrames[unit].hasStateWatch)
return
end
-
- local frame = self:CreateUnit("Button", "SUFUnit" .. unit, UIParent, "SecureUnitButtonTemplate")
+
+ 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, UIParent, "SecureGroupHeaderTemplate")
- frame:SetAttribute("template", "SecureUnitButtonTemplate")
+ frame = CreateFrame("Frame", "SUFHeader" .. type .. id, petBattleFrame, "SecureGroupHeaderTemplate")
+ frame:SetAttribute("template", unitButtonTemplate)
frame:SetAttribute("initial-unitWatch", true)
frame:SetAttribute("showRaid", true)
frame:SetAttribute("groupFilter", id)
- frame:UnregisterEvent("UNIT_NAME_UPDATE")
+ frame:SetAttribute("initialConfigFunction", secureInitializeUnit)
frame.initialConfigFunction = initializeUnit
frame.isHeaderFrame = true
frame.unitType = type
+ frame.unitMappedType = type
frame.splitParent = type
frame.groupID = id
--frame:SetBackdrop({bgFile = "Interface\\ChatFrame\\ChatFrameBackground", edgeFile = "Interface\\ChatFrame\\ChatFrameBackground", edgeSize = 1})
--frame:SetBackdropBorderColor(1, 0, 0, 1)
--frame:SetBackdropColor(0, 0, 0, 0)
-
+
+ frame:SetAttribute("style-height", config.height)
+ frame:SetAttribute("style-width", config.width)
+ frame:SetAttribute("style-scale", config.scale)
+
+ if( ClickCastHeader ) then
+ -- the OnLoad adds the functions like SetFrameRef to the header
+ SecureHandler_OnLoad(frame)
+ frame:SetFrameRef("clickcast_header", ClickCastHeader)
+ end
+
headerFrames["raid" .. id] = frame
end
-
+
frame:Show()
-
+
if( not headerFrames.raidParent or headerFrames.raidParent.groupID > id ) then
headerFrames.raidParent = frame
end
-
+
+ setupRaidStateMonitor(id, frame)
+
elseif( frame ) then
- frame:Hide()
+ frame:Hide()
end
end
-
+
if( headerFrames.raidParent ) then
self:SetHeaderAttributes(headerFrames.raidParent, type)
ShadowUF.Layout:AnchorFrame(UIParent, headerFrames.raidParent, ShadowUF.db.profile.positions.raid)
@@ -844,50 +1062,72 @@ end
-- Load a header unit, party or raid
function Units:LoadGroupHeader(type)
- -- Any frames that were split out in this group need to be hidden
- for _, headerFrame in pairs(headerFrames) do
- if( headerFrame.splitParent == type ) then
- headerFrame:Hide()
- end
- end
-
-- Already created, so just reshow and we out
if( headerFrames[type] ) then
headerFrames[type]:Show()
-
- if( type == "party" ) then
- stateMonitor:SetAttribute("partyDisabled", nil)
+
+ if( type == "party" and stateMonitor.party ) then
+ stateMonitor.party:SetAttribute("partyDisabled", nil)
+ end
+
+ if( type == "raid" ) then
+ for id, monitor in pairs(stateMonitor.raids) do
+ monitor:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.raid.hideSemiRaid)
+ monitor:SetAttribute("raidDisabled", id >= 0 and true or nil)
+ end
end
-
+
if( type == "party" or type == "raid" ) then
self:CheckGroupVisibility()
end
return
end
-
- local headerFrame = CreateFrame("Frame", "SUFHeader" .. type, UIParent, type == "raidpet" and "SecureGroupPetHeaderTemplate" or "SecureGroupHeaderTemplate")
+
+ local headerFrame = CreateFrame("Frame", "SUFHeader" .. type, petBattleFrame, type == "raidpet" and "SecureGroupPetHeaderTemplate" or "SecureGroupHeaderTemplate")
headerFrames[type] = headerFrame
self:SetHeaderAttributes(headerFrame, type)
-
- headerFrame:SetAttribute("template", "SecureUnitButtonTemplate")
+
+ headerFrame:SetAttribute("template", unitButtonTemplate)
headerFrame:SetAttribute("initial-unitWatch", true)
+ headerFrame:SetAttribute("initialConfigFunction", secureInitializeUnit)
+
headerFrame.initialConfigFunction = initializeUnit
headerFrame.isHeaderFrame = true
headerFrame.unitType = type
- headerFrame:UnregisterEvent("UNIT_NAME_UPDATE")
-
+ headerFrame.unitMappedType = type
+
+ -- For securely managely the display
+ local config = ShadowUF.db.profile.units[type]
+ headerFrame:SetAttribute("style-height", config.height)
+ headerFrame:SetAttribute("style-width", config.width)
+ headerFrame:SetAttribute("style-scale", config.scale)
+
+ if( type == "raidpet" ) then
+ headerFrame:SetAttribute("filterOnPet", true)
+ end
+
+ if( ClickCastHeader ) then
+ -- the OnLoad adds the functions like SetFrameRef to the header
+ SecureHandler_OnLoad(headerFrame)
+ headerFrame:SetFrameRef("clickcast_header", ClickCastHeader)
+ end
+
ShadowUF.Layout:AnchorFrame(UIParent, headerFrame, ShadowUF.db.profile.positions[type])
-
+
-- We have to do party hiding based off raid as a state driver so that we can smoothly hide the party frames based off of combat and such
-- technically this isn't the cleanest solution because party frames will still have unit watches active
-- but this isn't as big of a deal, because SUF automatically will unregister the OnEvent for party frames while hidden
if( type == "party" ) then
- stateMonitor:SetFrameRef("partyHeader", headerFrame)
- stateMonitor:WrapScript(stateMonitor, "OnAttributeChanged", [[
+ stateMonitor.party = CreateFrame("Frame", nil, nil, "SecureHandlerBaseTemplate")
+ stateMonitor.party:SetAttribute("partyDisabled", nil)
+ stateMonitor.party:SetFrameRef("partyHeader", headerFrame)
+ stateMonitor.party:SetAttribute("hideSemiRaid", ShadowUF.db.profile.units.party.hideSemiRaid)
+ stateMonitor.party:SetAttribute("hideAnyRaid", ShadowUF.db.profile.units.party.hideAnyRaid)
+ stateMonitor.party:WrapScript(stateMonitor.party, "OnAttributeChanged", [[
if( name ~= "state-raidmonitor" and name ~= "partydisabled" and name ~= "hideanyraid" and name ~= "hidesemiraid" ) then return end
if( self:GetAttribute("partyDisabled") ) then return end
-
+
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
@@ -896,50 +1136,77 @@ function Units:LoadGroupHeader(type)
self:GetFrameRef("partyHeader"):Show()
end
]])
- RegisterStateDriver(stateMonitor, "raidmonitor", "[target=raid6, exists] raid6; [target=raid1, exists] raid1; none")
+ RegisterStateDriver(stateMonitor.party, "raidmonitor", "[target=raid6, exists] raid6; [target=raid1, exists] raid1; none")
+
+ elseif( type == "raid" ) then
+ setupRaidStateMonitor(-1, headerFrame)
else
headerFrame:Show()
end
+
+ -- Any frames that were split out in this group need to be hidden
+ if( headerFrames.raidParent ) then
+ for _, 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, UIParent)
+
+ local headerFrame = CreateFrame("Frame", "SUFHeader" .. type, petBattleFrame, "SecureHandlerBaseTemplate")
headerFrame.isHeaderFrame = true
headerFrame.unitType = type
+ headerFrame.unitMappedType = remappedUnits[type] or type
headerFrame:SetClampedToScreen(true)
headerFrame:SetMovable(true)
headerFrame:SetHeight(0.1)
+ headerFrame:SetAttribute("totalChildren", #(ShadowUF[type .. "Units"]))
headerFrame.children = {}
+
headerFrames[type] = headerFrame
-
+
if( type == "arena" ) then
- headerFrame:SetScript("OnAttributeChanged", function(self, key, value)
- if( key == "childChanged" and value and self.children[value] and self:IsVisible() ) then
- self.children[value]:FullUpdate()
+ 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")
+ 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
- frame:SetAttribute("unitID", id)
- frame.hasStateWatch = true
-
stateMonitor:WrapScript(frame, "OnAttributeChanged", [[
if( name == "state-unitexists" ) then
local parent = self:GetParent()
@@ -949,23 +1216,63 @@ function Units:LoadZoneHeader(type)
elseif( not value and not self:GetAttribute("unitDisappeared") ) then
self:SetAttribute("unitDisappeared", true)
end
-
+
if( value ) then
self:Show()
end
end
]])
-
- RegisterUnitWatch(frame, frame.hasStateWatch)
else
- RegisterUnitWatch(frame)
- end
- end
-
+ 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])
+ 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)
@@ -985,21 +1292,30 @@ function Units:LoadChildUnit(parent, type, id)
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")
+ 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", string.match(type, "pet$") and "pet" or "target")
+ 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
@@ -1010,14 +1326,14 @@ function Units:InitializeFrame(type)
self:LoadSplitGroupHeader(type)
elseif( type == "party" or type == "raid" or type == "maintank" or type == "mainassist" or type == "raidpet" ) then
self:LoadGroupHeader(type)
- elseif( self.zoneUnits[type] ) then
- self:LoadZoneHeader(type)
elseif( self.childUnits[type] ) then
for frame in pairs(frameList) do
if( frame.unitType == self.childUnits[type] and ShadowUF.db.profile.units[frame.unitType] and frame.unitID ) then
self:LoadChildUnit(frame, type, frame.unitID)
end
end
+ elseif( self.zoneUnits[type] ) then
+ self:LoadZoneHeader(type)
else
self:LoadUnit(type)
end
@@ -1025,14 +1341,20 @@ end
-- Uninitialize units
function Units:UninitializeFrame(type)
- -- Disables showing party in raid automatically if raid frames are disabled
- if( type == "party" ) then
- stateMonitor:SetAttribute("partyDisabled", true)
- end
if( type == "party" or type == "raid" ) then
self:CheckGroupVisibility()
end
+ -- Disables showing party in raid automatically if raid frames are disabled
+ if( type == "party" and stateMonitor.party ) then
+ stateMonitor.party:SetAttribute("partyDisabled", true)
+ end
+ if( type == "raid" ) then
+ for _, monitor in pairs(stateMonitor.raids) do
+ monitor:SetAttribute("raidDisabled", true)
+ end
+ end
+
-- Disable the parent and the children will follow
if( ShadowUF.db.profile.units[type].frameSplit ) then
for _, headerFrame in pairs(headerFrames) do
@@ -1042,9 +1364,14 @@ function Units:UninitializeFrame(type)
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
@@ -1053,6 +1380,7 @@ function Units:UninitializeFrame(type)
for frame in pairs(frameList) do
if( frame.unitType == type ) then
UnregisterUnitWatch(frame)
+ frame:SetAttribute("state-unitexits", false)
frame:Hide()
end
end
@@ -1067,7 +1395,7 @@ function Units:ProfileChanged()
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
@@ -1077,14 +1405,14 @@ function Units:ProfileChanged()
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)
@@ -1097,7 +1425,7 @@ 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)
@@ -1107,6 +1435,21 @@ function Units:CreateBar(parent)
return bar
end
+-- Handle showing for the arena prep frames
+function Units:InitializeArena()
+ if( not headerFrames.arena or InCombatLockdown() ) then return end
+
+ local specs = GetNumArenaOpponentSpecs()
+ if( not specs or specs == 0 ) then return end
+
+ for i=1, specs do
+ local frame = headerFrames.arena.children[i]
+ frame:SetAttribute("state-unitexists", true)
+ frame:Show()
+ frame:FullUpdate()
+ end
+end
+
-- Deal with zone changes for enabling modules
local instanceType, queueZoneCheck
function Units:CheckPlayerZone(force)
@@ -1114,22 +1457,25 @@ function Units:CheckPlayerZone(force)
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())
+ local instance = CanHearthAndResurrectFromArea() and "pvp" or select(2, IsInInstance()) or "none"
+ if( instance == "scenario" ) then instance = "party" end
+ if( instance == "interior" ) then instance = "neighborhood" 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
@@ -1137,9 +1483,42 @@ function Units:CheckPlayerZone(force)
end
end
+-- Handle figuring out what auras players can cure
+local curableSpells = {
+ ["DRUID"] = {[88423] = {"Magic", "Curse", "Poison"}, [2782] = {"Curse", "Poison"}},
+ ["PRIEST"] = {[527] = {"Magic", "Disease"}, [32375] = {"Magic"}, [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
@@ -1150,24 +1529,57 @@ centralFrame:SetScript("OnEvent", function(self, event, unit)
else
self:UnregisterEvent("PLAYER_UNGHOST")
Units:CheckPlayerZone()
- end
-
+ end
+
+ -- Force update frames
+ elseif( event == "ARENA_PREP_OPPONENT_SPECIALIZATIONS" or event == "ARENA_OPPONENT_UPDATE" ) then
+ Units:InitializeArena()
+
-- They're alive again so they "officially" changed zone types now
elseif( event == "PLAYER_UNGHOST" ) then
Units:CheckPlayerZone()
-
+
+ -- Monitor level up
+ elseif( event == "PLAYER_LEVEL_UP" or event == "CINEMATIC_STOP" ) then
+ if( unitFrames.player ) then
+ unitFrames.player:SetVisibility()
+ unitFrames.player:FullUpdate()
+ end
+
+ -- Monitor talent changes for curable changes
+ elseif( event == "PLAYER_SPECIALIZATION_CHANGED" 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)
\ No newline at end of file
+end)
diff --git a/modules/xp.lua b/modules/xp.lua
index 6f2c28fd8..0f625e31a 100755
--- a/modules/xp.lua
+++ b/modules/xp.lua
@@ -19,22 +19,22 @@ function XP:OnEnable(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")
@@ -59,10 +59,10 @@ 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)
@@ -80,26 +80,27 @@ local function formatNumber(number)
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
+ 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(reaction == 8 and max or current)
- frame.xpBar.rep.tooltip = string.format(L["%s (%s): %s/%s (%.2f%% done)"], name, GetText("FACTION_STANDING_LABEL" .. reaction, UnitSex("player")), formatNumber(current), formatNumber(max), reaction == 8 and 100 or (current / max) * 100)
+ frame.xpBar.rep:SetValue(current)
+ frame.xpBar.rep.tooltip = string.format(L["%s (%s): %s/%s (%.2f%% done)"], 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()
@@ -107,31 +108,31 @@ 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
-
+
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), (current / max) * 100, formatNumber(GetXPExhaustion()))
+ frame.xpBar.xp.tooltip = string.format(L["Level %s - %s: %s/%s (%.2f%% done), %s rested."], UnitLevel(frame.unitOwner), UnitLevel(frame.unitOwner) + 1, formatNumber(current), formatNumber(max), (max > 0 and current / max or 0) * 100, formatNumber(GetXPExhaustion()))
else
frame.xpBar.rested:Hide()
- frame.xpBar.xp.tooltip = string.format(L["Level %s - %s: %s/%s (%.2f%% done)"], UnitLevel(frame.unitOwner), UnitLevel(frame.unitOwner) + 1, formatNumber(current), formatNumber(max), (current / max) * 100)
+ frame.xpBar.xp.tooltip = string.format(L["Level %s - %s: %s/%s (%.2f%% done)"], UnitLevel(frame.unitOwner), UnitLevel(frame.unitOwner) + 1, formatNumber(current), formatNumber(max), (max > 0 and current / max or 0) * 100)
end
end
@@ -143,7 +144,7 @@ function XP:Update(frame)
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)
diff --git a/options/ShadowedUF_Options.toc b/options/ShadowedUF_Options.toc
index adaff5605..a818716e1 100755
--- a/options/ShadowedUF_Options.toc
+++ b/options/ShadowedUF_Options.toc
@@ -1,9 +1,10 @@
-## Interface: 30300
+## Interface: 110207, 110205
## Title: Shadowed UF (Options)
## Notes: Configuration for Shadowed Unit Frames.
## Author: Shadowed
## LoadOnDemand: true
## Dependencies: ShadowedUnitFrames
+## Group: ShadowedUnitFrames
#@no-lib-strip@
libs\AceDBOptions-3.0\AceDBOptions-3.0.xml
@@ -12,4 +13,4 @@ libs\AceGUI-3.0-SharedMediaWidgets\widget.xml
libs\AceConfig-3.0\AceConfig-3.0.xml
#@end-no-lib-strip@
-config.lua
\ No newline at end of file
+config.lua
diff --git a/options/config.lua b/options/config.lua
old mode 100644
new mode 100755
index 687b5ace3..411012e54
--- a/options/config.lua
+++ b/options/config.lua
@@ -6,25 +6,42 @@ 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"},
- raid = {"raid", "raidpet", "boss", "bosstarget", "maintank", "maintanktarget", "mainassist", "mainassisttarget"},
- arena = {"arena", "arenapet", "arenatarget"}}
+ party = {"party", "partypet", "partytarget", "partytargettarget", "party"},
+ raid = {"raid", "raidpet"},
+ raidmisc = {"maintank", "maintanktarget", "maintanktargettarget", "mainassist", "mainassisttarget", "mainassisttargettarget"},
+ boss = {"boss", "bosstarget", "bosstargettarget"},
+ arena = {"arena", "arenapet", "arenatarget", "arenatargettarget"},
+ battleground = {"battleground", "battlegroundpet", "battlegroundtarget", "battlegroundtargettarget"}
+}
local UNIT_DESC = {
["boss"] = L["Boss units are for only certain fights, such as Blood Princes or the Gunship battle, you will not see them for every boss fight."],
- ["mainassist"] = L["Main Assists's are set by the Blizzard Main Assist system or mods that use them such as oRA3."],
- ["maintank"] = L["Main Tank's are set by the Blizzard Main Tank system or mods that use them such as oRA3."],
+ ["mainassist"] = L["Main Assists's are set by the Blizzard Main Assist system or mods that use it."],
+ ["maintank"] = L["Main Tank's are set through the Raid frames, or through selecting the Tank role."],
+ ["battleground"] = L["Currently used in battlegrounds for showing flag carriers."],
+ ["battlegroundpet"] = L["Current pet used by a battleground unit."],
+ ["battlegroundtarget"] = L["Current target of a battleground unit."],
+ ["battlegroundtargettarget"] = L["Current target of target of a battleground unit."]
}
local PAGE_DESC = {
@@ -36,17 +53,20 @@ local PAGE_DESC = {
["tags"] = L["Advanced tag management, allows you to add your own custom tags."],
["filter"] = L["Simple aura filtering by whitelists and blacklists."],
}
-local INDICATOR_NAMES = {["happiness"] = L["Happiness"], ["leader"] = L["Leader"], ["lfdRole"] = L["Dungeon role"], ["masterLoot"] = L["Master looter"], ["pvp"] = L["PvP Flag"],["raidTarget"] = L["Raid target"], ["ready"] = L["Ready status"], ["role"] = L["Raid role"], ["status"] = L["Combat status"], ["class"] = L["Class icon"]}
-local AREA_NAMES = {["arena"] = L["Arenas"],["none"] = L["Everywhere else"], ["party"] = L["Party instances"], ["pvp"] = L["Battlegrounds"], ["raid"] = L["Raid instances"],}
-local INDICATOR_DESC = {["happiness"] = L["Indicator for your pet's happiness, only applies to Hunters."],
- ["leader"] = L["Crown indicator for group leaders."], ["lfdRole"] = L["Role the unit is playing in dungeons formed through the Looking For Dungeon system."],
+local INDICATOR_NAMES = {["questBoss"] = L["Quest Boss"], ["leader"] = L["Leader / Assist"], ["lfdRole"] = L["Class Role"], ["masterLoot"] = L["Master Looter"], ["pvp"] = L["PvP Flag"], ["raidTarget"] = L["Raid Target"], ["ready"] = L["Ready Status"], ["role"] = L["Raid Role"], ["status"] = L["Combat Status"], ["class"] = L["Class Icon"], ["resurrect"] = L["Resurrect Status"], ["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"], ["neighborhood"] = L["Neighborhood"]}
+local INDICATOR_DESC = {
+ ["leader"] = L["Crown indicator for group leader or assistants."], ["lfdRole"] = L["Role the unit is playing."],
["masterLoot"] = L["Bag indicator for master looters."], ["pvp"] = L["PVP flag indicator, Horde for Horde flagged pvpers and Alliance for Alliance flagged pvpers."],
- ["raidTarget"] = L["Raid target indicator."], ["ready"] = L["Ready status of group members."],
- ["role"] = L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."], ["status"] = L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."], ["class"] = L["Class icon for players."]}
-local TAG_GROUPS = {["classification"] = L["Classifications"], ["health"] = L["Health"], ["misc"] = L["Miscellaneous"], ["playerthreat"] = L["Player threat"], ["power"] = L["Power"], ["status"] = L["Status"], ["threat"] = L["Threat"], ["raid"] = L["Raid"],}
+ ["raidTarget"] = L["Raid target indicator."], ["ready"] = L["Ready status of group members."], ["phase"] = L["Shows when a party member is in a different phase or another group."],
+ ["questBoss"] = L["Shows that a NPC is a boss for a quest."], ["petBattle"] = L["Shows what kind of pet the unit is for pet battles."],
+ ["role"] = L["Raid role indicator, adds a shield indicator for main tanks and a sword icon for main assists."], ["status"] = L["Status indicator, shows if the unit is currently in combat. For the player it will also show if you are rested."], ["class"] = L["Class icon for players."],
+ ["arenaSpec"] = L["Talent spec of your arena opponents."]
+}
+local TAG_GROUPS = {["classification"] = L["Classifications"], ["health"] = L["Health"], ["misc"] = L["Miscellaneous"], ["playerthreat"] = L["Player threat"], ["power"] = L["Power"], ["status"] = L["Status"], ["threat"] = L["Threat"], ["raid"] = L["Raid"], ["classspec"] = L["Class Specific"], ["classtimer"] = L["Class Timer"]}
local pointPositions = {["BOTTOM"] = L["Bottom"], ["TOP"] = L["Top"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["TOPLEFT"] = L["Top Left"], ["TOPRIGHT"] = L["Top Right"], ["BOTTOMLEFT"] = L["Bottom Left"], ["BOTTOMRIGHT"] = L["Bottom Right"], ["CENTER"] = L["Center"]}
-local positionList = {["C"] = L["Center"], ["RT"] = L["Right Top"], ["RC"] = L["Right Center"], ["RB"] = L["Right Bottom"], ["LT"] = L["Left Top"], ["LC"] = L["Left Center"], ["LB"] = L["Left Bottom"], ["BL"] = L["Bottom Left"], ["BC"] = L["Bottom Center"], ["BR"] = L["Bottom Right"], ["TR"] = L["Top Right"], ["TC"] = L["Top Center"], ["TL"] = L["Top Left"] }
+local positionList = {["C"] = L["Center"], ["RT"] = L["Right Top"], ["RC"] = L["Right Center"], ["RB"] = L["Right Bottom"], ["LT"] = L["Left Top"], ["LC"] = L["Left Center"], ["LB"] = L["Left Bottom"], ["BL"] = L["Bottom Left"], ["BC"] = L["Bottom Center"], ["BR"] = L["Bottom Right"], ["TR"] = L["Top Right"], ["TC"] = L["Top Center"], ["TL"] = L["Top Left"]}
local unitOrder = {}
for order, unit in pairs(ShadowUF.unitList) do unitOrder[unit] = order end
@@ -62,7 +82,7 @@ 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
@@ -70,14 +90,14 @@ 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
@@ -85,7 +105,7 @@ local function getAnchorParents(info)
anchorList[getFrameName(unitID)] = string.format(L["%s frames"], L.units[unitID] or unitID)
end
end
-
+
return anchorList
end
@@ -99,7 +119,7 @@ local function selectTabGroup(group, subGroup, key)
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
@@ -117,7 +137,7 @@ local function isUnitDisabled(info)
break
end
end
-
+
return not enabled
end
@@ -131,7 +151,7 @@ local function mergeTables(parent, child)
parent[key] = value
end
end
-
+
return parent
end
@@ -140,7 +160,7 @@ local function getName(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
@@ -158,13 +178,13 @@ end
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()
@@ -182,20 +202,20 @@ local function get(info)
end
local function setColor(info, r, g, b, a)
- local color = get(info)
+ local color = get(info) or {}
color.r, color.g, color.b, color.a = r, g, b, a
set(info, color)
end
local function getColor(info)
- local color = get(info)
+ local color = get(info) or {}
return color.r, color.g, color.b, color.a
end
-- 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
@@ -212,13 +232,27 @@ local function setVariable(unit, moduleKey, moduleSubKey, key, value)
end
local function specialRestricted(unit, moduleKey, moduleSubKey, key)
- if( ShadowUF.fakeUnits[unit] and ( key == "colorAggro" or key == "aggro" or moduleKey == "incHeal" or moduleKey == "castBar" ) ) then
+ if( ShadowUF.fakeUnits[unit] and ( key == "colorAggro" or key == "aggro" or key == "colorDispel" or moduleKey == "incHeal" or moduleKey == "healAbsorb" or moduleKey == "incAbsorb" or moduleKey == "castBar" ) ) then
return true
elseif( moduleKey == "healthBar" and unit == "player" and key == "reaction" ) then
return true
end
end
+local function 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
@@ -227,19 +261,11 @@ local function setUnit(info, value)
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
-
- if( unit == "global" ) then
- for unit in pairs(modifyUnits) do
- if( not specialRestricted(unit, moduleKey, moduleSubKey, key) ) then
- setVariable(unit, moduleKey, moduleSubKey, key, value)
- end
- end
-
- setVariable("global", moduleKey, moduleSubKey, key, value)
- else
- setVariable(unit, moduleKey, moduleSubKey, key, value)
- end
+
+ setDirectUnit(unit, moduleKey, moduleSubKey, key, value)
end
local function getVariable(unit, moduleKey, moduleSubKey, key)
@@ -259,8 +285,10 @@ local function getUnit(info)
if( moduleSubKey and not key ) then key = moduleSubKey moduleSubKey = nil end
if( moduleSubKey == "$parent" ) then moduleSubKey = info[#(info) - 1] end
if( moduleKey == "$parent" ) then moduleKey = info[#(info) - 1] end
+ if( moduleSubKey == "$parentparent" ) then moduleSubKey = info[#(info) - 2] end
+ if( moduleKey == "$parentparent" ) then moduleKey = info[#(info) - 2] end
if( tonumber(moduleSubKey) ) then moduleSubKey = tonumber(moduleSubKey) end
-
+
return getVariable(info[2], moduleKey, moduleSubKey, key)
end
@@ -270,7 +298,7 @@ local function getTagName(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
@@ -285,10 +313,10 @@ local function hideRestrictedOption(info)
local key = info[#(info)]
if( ShadowUF.modules[key] and ShadowUF.modules[key].moduleClass and ShadowUF.modules[key].moduleClass ~= playerClass ) then
return true
- elseif( key == "incHeal" and not ShadowUF.modules.incHeal ) then
+ elseif( ( key == "incHeal" and not ShadowUF.modules.incHeal ) or ( key == "incAbsorb" and not ShadowUF.modules.incAbsorb ) or ( key == "healAbsorb" and not ShadowUF.modules.healAbsorb ) ) then
return true
-- Non-standard units do not support color by aggro or incoming heal
- elseif( key == "colorAggro" or key == "incHeal" or key == "aggro" ) then
+ elseif( key == "colorAggro" or key == "colorDispel" or key == "incHeal" or key == "incAbsorb" or key == "aggro" ) then
return string.match(unit, "%w+target" )
-- Fall back for indicators, no variable table so it shouldn't be shown
elseif( info[#(info) - 1] == "indicators" ) then
@@ -299,7 +327,7 @@ local function hideRestrictedOption(info)
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
@@ -330,9 +358,48 @@ 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)]
@@ -343,10 +410,10 @@ local function loadGeneralOptions()
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
@@ -354,7 +421,7 @@ local function loadGeneralOptions()
barModules["$" .. key] = module.moduleName
end
end
-
+
local addTextParent = {
order = 4,
type = "group",
@@ -366,12 +433,12 @@ local function loadGeneralOptions()
return false
end
end
-
+
return true
end,
args = {},
}
-
+
local addTextLabel = {
order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end,
type = "description",
@@ -398,7 +465,7 @@ local function loadGeneralOptions()
end,
name = "",
}
-
+
local addText = {
order = function(info) return info[#(info)] + 0.5 end,
type = "execute",
@@ -409,7 +476,16 @@ local function loadGeneralOptions()
if( not getVariable("player", "text", nil, id) ) then return true end
return getVariable("player", "text", id, "anchorTo") ~= info[#(info) - 1]
end,
- disabled = function(info) return tonumber(info[#(info)]) <= 6 end,
+ disabled = function(info)
+ local id = tonumber(info[#(info)])
+ for _, unit in pairs(ShadowUF.unitList) do
+ if( ShadowUF.db.profile.units[unit].text[id] and ShadowUF.db.profile.units[unit].text[id].default ) then
+ return true
+ end
+ end
+
+ return false
+ end,
confirmText = L["Are you sure you want to delete this text? All settings for it will be deleted."],
confirm = true,
func = function(info)
@@ -417,60 +493,46 @@ local function loadGeneralOptions()
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 GetSpellInfo(spell) ) then
+ 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, spell)
- local spell = ShadowUF.db.profile.range[info[#(info)] .. playerClass]
- return spell and spell ~= "" and spell or ShadowUF.modules.range[info[#(info)]][playerClass]
+
+ local function getRange(info)
+ return ShadowUF.db.profile.range[info[#(info)] .. playerClass]
end
-
- local textData = {}
-
- local function writeTable(tbl)
- local data = ""
- for key, value in pairs(tbl) do
- local valueType = type(value)
-
- -- Wrap the key in brackets if it's a number
- if( type(key) == "number" ) then
- key = string.format("[%s]", key)
- -- Wrap the string with quotes if it has a space in it
- elseif( string.match(key, "[%p%s%c]") ) then
- key = string.format("['%s']", string.gsub(key, "'", "\\'"))
- end
-
- -- foo = {bar = 5}
- if( valueType == "table" ) then
- data = string.format("%s%s=%s;", data, key, writeTable(value))
- -- foo = true / foo = 5
- elseif( valueType == "number" or valueType == "boolean" ) then
- data = string.format("%s%s=%s;", data, key, tostring(value))
- -- foo = "bar"
- else
- data = string.format("%s%s='%s';", data, key, string.gsub(tostring(value), "'", "\\'"))
- end
+
+ local function rangeWithIcon(info)
+ local name = getRange(info)
+ local text = L["Spell Name"]
+ if( string.match(info[#(info)], "Alt") ) then
+ text = L["Alternate Spell Name"]
+ end
+
+ local icon = name and GetSpellTexture(name)
+ if( not icon ) then
+ icon = "Interface\\Icons\\Inv_misc_questionmark"
end
-
- return "{" .. data .. "}"
+
+ return "|T" .. icon .. ":18:18:0:0|t " .. text
end
-
+
+ local textData = {}
+
local layoutData = {positions = true, visibility = true, modules = false}
local layoutManager = {
type = "group",
@@ -498,7 +560,7 @@ local function loadGeneralOptions()
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
},
@@ -520,15 +582,6 @@ local function loadGeneralOptions()
get = function(info) return layoutData[info[#(info)]] end,
width = "double",
},
- modules = {
- order = 4,
- type = "toggle",
- name = L["Import non-standard module settings"],
- desc = L["Will not import settings of modules that are not included with Shadowed Unit Frames by default."],
- set = function(info, value) layoutData[info[#(info)]] = value end,
- get = function(info) return layoutData[info[#(info)]] end,
- width = "double",
- },
import = {
order = 5,
type = "input",
@@ -543,38 +596,26 @@ local function loadGeneralOptions()
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
-
- -- Strip module settings that aren't with SUF by default
- if( not layoutData.modules ) then
- local validModules = {["healthBar"] = true, ["powerBar"] = true, ["portrait"] = true, ["range"] = true, ["text"] = true, ["indicators"] = true, ["auras"] = true, ["incHeal"] = true, ["castBar"] = true, ["combatText"] = true, ["highlight"] = true, ["runeBar"] = true, ["totemBar"] = true, ["xpBar"] = true, ["fader"] = true, ["comboPoints"] = true}
- for _, unitData in pairs(layout.units) do
- for key, data in pairs(unitData) do
- if( type(data) == "table" and not validModules[key] and ShadowUF.modules[key] ) then
- unitData[key] = nil
- end
- end
- end
- end
-
+
-- Check if we need move over the visibility and positions info
layout.positions = layout.positions or CopyTable(ShadowUF.db.profile.positions)
layout.visibility = layout.visibility or CopyTable(ShadowUF.db.profile.positions)
@@ -587,7 +628,7 @@ local function loadGeneralOptions()
ShadowUF.db:SetProfile(currentLayout)
ShadowUF.db:ResetProfile()
ShadowUF.layoutImporting = nil
-
+
-- Overwrite everything we did import
ShadowUF:LoadDefaultLayout()
for key, data in pairs(layout) do
@@ -597,7 +638,7 @@ local function loadGeneralOptions()
ShadowUF.db.profile[key] = data
end
end
-
+
ShadowUF:ProfilesChanged()
end,
},
@@ -643,7 +684,7 @@ local function loadGeneralOptions()
},
},
}
-
+
options.args.general = {
type = "group",
childGroups = "tab",
@@ -673,27 +714,34 @@ local function loadGeneralOptions()
end,
arg = "locked",
},
- sep = {
- order = 1.5,
- type = "description",
- name = "",
- width = "full",
- hidden = hideAdvancedOption,
- },
advanced = {
- order = 2,
+ order = 1.5,
type = "toggle",
name = L["Advanced"],
desc = L["Enabling advanced settings will give you access to more configuration options. This is meant for people who want to tweak every single thing, and should not be enabled by default as it increases the options."],
arg = "advanced",
},
+ sep = {
+ order = 2,
+ type = "description",
+ name = "",
+ width = "full",
+ },
omnicc = {
order = 2.5,
type = "toggle",
- name = L["Disable OmniCC"],
- desc = L["Disables showing OmniCC timers in all Shadowed Unit Frame auras."],
+ name = L["Disable OmniCC Cooldown Count"],
+ desc = L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."],
arg = "omnicc",
- hidden = hideAdvancedOption,
+ width = "double",
+ },
+ blizzardcc = {
+ order = 2.5,
+ type = "toggle",
+ name = L["Disable Blizzard Cooldown Count"],
+ desc = L["Disables showing Cooldown Count timers in all Shadowed Unit Frame auras."],
+ arg = "blizzardcc",
+ width = "double",
},
hideCombat = {
order = 3,
@@ -701,6 +749,21 @@ local function loadGeneralOptions()
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,
@@ -857,7 +920,7 @@ local function loadGeneralOptions()
order = 3,
type = "select",
name = L["Outline"],
- values = {["OUTLINE"] = L["Thin outline"], ["THICKOUTLINE"] = L["Thick outline"], [""] = L["None"]},
+ values = {["OUTLINE"] = L["Thin outline"], ["THICKOUTLINE"] = L["Thick outline"], ["MONOCHROMEOUTLINE"] = L["Monochrome Outline"], [""] = L["None"]},
arg = "font.extra",
hidden = hideAdvancedOption,
},
@@ -881,7 +944,7 @@ local function loadGeneralOptions()
elseif( not value ) then
ShadowUF.db.profile.bars.backgroundColor = nil
end
-
+
ShadowUF.Layout:Reload()
end,
get = function(info)
@@ -896,9 +959,9 @@ 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)
end,
disabled = function(info) return not ShadowUF.db.profile.bars.backgroundColor end,
@@ -925,32 +988,6 @@ local function loadGeneralOptions()
},
},
},
- range = {
- order = 5,
- type = "group",
- inline = true,
- name = L["Range spells"],
- args = {
- friendly = {
- order = 0,
- type = "input",
- name = L["Friendly spell"],
- desc = L["Name of a friendly spell to check range on friendlies.|n|nThis is automatically set for your current class only."],
- validate = validateSpell,
- set = setRange,
- get = getRange,
- },
- hostile = {
- order = 1,
- type = "input",
- name = L["Hostile spell"],
- desc = L["Name of a hostile spell to check range on enemies.|n|nThis is automatically set for your current class only."],
- validate = validateSpell,
- set = setRange,
- get = getRange,
- },
- },
- },
},
},
color = {
@@ -1008,6 +1045,13 @@ local function loadGeneralOptions()
desc = L["Health bar color for hostile units."],
arg = "healthColors.hostile",
},
+ aggro = {
+ order = 6.5,
+ type = "color",
+ name = L["Has Aggro"],
+ desc = L["Health bar color for units with aggro."],
+ arg = "healthColors.aggro",
+ },
static = {
order = 7,
type = "color",
@@ -1019,19 +1063,65 @@ local function loadGeneralOptions()
order = 8,
type = "color",
name = L["Incoming heal"],
- desc = L["Health bar color to use to show how much healing someone is about to receive."],
+ desc = L["Bar color to use to show how much healing someone is about to receive."],
arg = "healthColors.inc",
},
- enemyUnattack = {
+ incAbsorb = {
order = 9,
type = "color",
+ name = L["Incoming absorb"],
+ desc = L["Color to use to show how much damage will be absorbed."],
+ arg = "healthColors.incAbsorb",
+ },
+ healAbsorb = {
+ order = 10,
+ type = "color",
+ name = L["Heal absorb"],
+ desc = L["Color to use to show how much healing will e absorbed."],
+ arg = "healthColors.healAbsorb",
+ },
+ enemyUnattack = {
+ order = 11,
+ type = "color",
name = L["Unattackable hostile"],
desc = L["Health bar color to use for hostile units who you cannot attack, used for reaction coloring."],
hidden = hideAdvancedOption,
arg = "healthColors.enemyUnattack",
- },
+ }
},
},
+ stagger = {
+ order = 1.5,
+ type = "group",
+ inline = true,
+ name = L["Stagger"],
+ set = setColor,
+ get = getColor,
+ hidden = function() return select(2, UnitClass("player")) ~= "MONK" end,
+ args = {
+ STAGGER_GREEN = {
+ order = 0,
+ type = "color",
+ name = L["Green (<30% HP)"],
+ desc = L["Stagger bar color when the staggered amount is <30% of your HP."],
+ arg = "powerColors.STAGGER_GREEN"
+ },
+ STAGGER_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",
@@ -1044,7 +1134,6 @@ local function loadGeneralOptions()
order = 0,
type = "color",
name = L["Mana"],
- hasAlpha = true,
width = "half",
arg = "powerColors.MANA",
},
@@ -1052,7 +1141,6 @@ local function loadGeneralOptions()
order = 1,
type = "color",
name = L["Rage"],
- hasAlpha = true,
width = "half",
arg = "powerColors.RAGE",
},
@@ -1060,7 +1148,6 @@ local function loadGeneralOptions()
order = 2,
type = "color",
name = L["Focus"],
- hasAlpha = true,
arg = "powerColors.FOCUS",
width = "half",
},
@@ -1068,40 +1155,142 @@ local function loadGeneralOptions()
order = 3,
type = "color",
name = L["Energy"],
- hasAlpha = true,
arg = "powerColors.ENERGY",
width = "half",
},
- HAPPINESS = {
- order = 5,
- type = "color",
- name = L["Happiness"],
- hasAlpha = true,
- arg = "powerColors.HAPPINESS",
- },
RUNIC_POWER = {
order = 6,
type = "color",
name = L["Runic Power"],
- hasAlpha = true,
arg = "powerColors.RUNIC_POWER",
},
- AMMOSLOT = {
+ RUNES = {
order = 7,
type = "color",
+ name = L["Runes"],
+ arg = "powerColors.RUNES",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DEATHKNIGHT" end,
+ },
+ AMMOSLOT = {
+ order = 9,
+ type = "color",
name = L["Ammo"],
- hasAlpha = true,
arg = "powerColors.AMMOSLOT",
hidden = hideAdvancedOption,
},
FUEL = {
- order = 8,
+ order = 10,
type = "color",
name = L["Fuel"],
- hasAlpha = true,
arg = "powerColors.FUEL",
hidden = hideAdvancedOption,
},
+ COMBOPOINTS = {
+ order = 11,
+ type = "color",
+ name = L["Combo Points"],
+ arg = "powerColors.COMBOPOINTS",
+ },
+ AURAPOINTS = {
+ order = 11.5,
+ type = "color",
+ name = L["Aura Combo Points"],
+ arg = "powerColors.AURAPOINTS",
+ hidden = function() return not ShadowUF.modules.auraPoints end
+ },
+ INSANITY = {
+ order = 12,
+ type = "color",
+ name = L["Insanity"],
+ arg = "powerColors.INSANITY",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "PRIEST" end,
+ },
+ MAELSTROM = {
+ order = 12,
+ type = "color",
+ name = L["Maelstrom"],
+ arg = "powerColors.MAELSTROM",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "SHAMAN" end,
+ },
+ HOLYPOWER = {
+ order = 12,
+ type = "color",
+ name = L["Holy Power"],
+ arg = "powerColors.HOLYPOWER",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "PALADIN" end,
+ },
+ SOULSHARDS = {
+ order = 14,
+ type = "color",
+ name = L["Soul Shards"],
+ hasAlpha = true,
+ arg = "powerColors.SOULSHARDS",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "WARLOCK" end,
+ },
+ ARCANECHARGES = {
+ order = 15,
+ type = "color",
+ name = L["Arcane Charges"],
+ hasAlpha = true,
+ arg = "powerColors.ARCANECHARGES",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "MAGE" end,
+ },
+ CHI = {
+ order = 17,
+ type = "color",
+ name = L["Chi"],
+ arg = "powerColors.CHI",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "MONK" end,
+ },
+ FURY = {
+ order = 17,
+ type = "color",
+ name = L["Fury"],
+ arg = "powerColors.FURY",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DEMONHUNTER" end,
+ },
+ PAIN = {
+ order = 17,
+ type = "color",
+ name = L["Pain"],
+ arg = "powerColors.PAIN",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DEMONHUNTER" end,
+ },
+ LUNAR_POWER = {
+ order = 17,
+ type = "color",
+ name = L["Astral Power"],
+ arg = "powerColors.LUNAR_POWER",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DRUID" end,
+ },
+ MUSHROOMS = {
+ order = 17,
+ type = "color",
+ name = L["Mushrooms"],
+ arg = "powerColors.MUSHROOMS",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "DRUID" end,
+ },
+ STATUE = {
+ order = 17,
+ type = "color",
+ name = L["Statue"],
+ arg = "powerColors.STATUE",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "MONK" end,
+ },
+ RUNEOFPOWER = {
+ order = 17.5,
+ type = "color",
+ name = L["Rune of Power"],
+ arg = "powerColors.RUNEOFPOWER",
+ hidden = function(info) return select(2, UnitClass("player")) ~= "MAGE" end,
+ },
+ ALTERNATE = {
+ order = 19,
+ type = "color",
+ name = L["Alt. Power"],
+ desc = L["Alternate power is used for things like quests and dungeons."],
+ arg = "powerColors.ALTERNATE",
+ },
},
},
cast = {
@@ -1158,6 +1347,25 @@ local function loadGeneralOptions()
},
},
},
+ auras = {
+ order = 3.5,
+ type = "group",
+ inline = true,
+ name = L["Aura borders"],
+ set = setColor,
+ get = getColor,
+ hidden = hideAdvancedOption,
+ args = {
+ removableColor = {
+ order = 0,
+ type = "color",
+ name = L["Stealable/Curable/Dispellable"],
+ desc = L["Border coloring of stealable, curable and dispellable auras."],
+ arg = "auraColors.removable",
+ width = "double"
+ }
+ }
+ },
classColors = {
order = 4,
type = "group",
@@ -1169,11 +1377,96 @@ local function loadGeneralOptions()
},
},
},
- profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ShadowUF.db, true),
+ 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"],
+ name = L["Text Management"],
hidden = false,
args = {
help = {
@@ -1219,30 +1512,30 @@ local function loadGeneralOptions()
-- 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,
},
},
@@ -1252,16 +1545,18 @@ local function loadGeneralOptions()
layout = layoutManager,
},
}
-
+
-- Load text
for id, text in pairs(ShadowUF.db.profile.units.player.text) do
- addTextParent.args[id .. ":label"] = addTextLabel
- addTextParent.args[tostring(id)] = addText
- addTextParent.args[id .. ":sep"] = addTextSep
- options.args.general.args.text.args[text.anchorTo] = addTextParent
+ if( text.anchorTo ~= "" and not text.default ) then
+ addTextParent.args[id .. ":label"] = addTextLabel
+ addTextParent.args[tostring(id)] = addText
+ addTextParent.args[id .. ":sep"] = addTextSep
+ options.args.general.args.text.args[text.anchorTo] = addTextParent
+ end
end
-
-
+
+
Config.classTable = {
order = 0,
type = "color",
@@ -1270,15 +1565,13 @@ local function loadGeneralOptions()
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
-
- options.args.general.args.profile.order = 4
end
---------------------
@@ -1290,7 +1583,8 @@ local function loadHideOptions()
type = "toggle",
name = function(info)
local key = info[#(info)]
- return L.units[key] and string.format(L["Hide %s frames"], string.lower(L.units[key])) or string.format(L["Hide %s"], key == "cast" and L["player cast bar"] or key == "runes" and L["rune bar"] or key == "buffs" and L["buff frames"])
+ if( key == "arena" ) then return string.format(L["Hide %s frames"], "arena/battleground") end
+ return L.units[key] and string.format(L["Hide %s frames"], string.lower(L.units[key])) or string.format(L["Hide %s"], key == "cast" and L["player cast bar"] or key == "playerPower" and L["player power frames"] or key == "buffs" and L["buff frames"] or key == "playerAltPower" and L["player alt. power"])
end,
set = function(info, value)
set(info, value)
@@ -1300,7 +1594,7 @@ local function loadHideOptions()
get = get,
arg = "hidden.$key",
}
-
+
options.args.hideBlizzard = {
type = "group",
name = L["Hide Blizzard"],
@@ -1327,14 +1621,16 @@ local function loadHideOptions()
args = {
buffs = Config.hideTable,
cast = Config.hideTable,
- runes = Config.hideTable,
+ playerPower = Config.hideTable,
party = Config.hideTable,
+ raid = Config.hideTable,
player = Config.hideTable,
pet = Config.hideTable,
target = Config.hideTable,
focus = Config.hideTable,
boss = Config.hideTable,
arena = Config.hideTable,
+ playerAltPower = Config.hideTable,
},
},
}
@@ -1349,7 +1645,7 @@ local function loadUnitOptions()
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
@@ -1357,7 +1653,7 @@ local function loadUnitOptions()
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
@@ -1366,24 +1662,24 @@ local function loadUnitOptions()
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)
+
+ return hideRaidOption(info)
end
-- Not every option should be changed via global settings
@@ -1392,25 +1688,25 @@ local function loadUnitOptions()
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
@@ -1419,32 +1715,32 @@ local function loadUnitOptions()
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
@@ -1452,7 +1748,7 @@ local function loadUnitOptions()
-- Load tag list
Config.advanceTextTable = {
order = 1,
- name = function(info) return getVariable(info[2], "text", quickIDMap[info[#(info)]], "name") end,
+ name = function(info) return getVariable(info[2], "text", quickIDMap[info[#(info)]], "name") end,
type = "group",
inline = true,
hidden = function(info)
@@ -1488,7 +1784,9 @@ local function loadUnitOptions()
desc = L["How much weight this should use when figuring out the total text width."],
type = "range",
min = 0, max = 10, step = 0.1,
- hidden = false,
+ hidden = function(info)
+ return hideAdvancedOption(info) or getVariable(info[2], "text", quickIDMap[info[#(info) - 1]], "block")
+ end,
},
size = {
order = 4,
@@ -1498,6 +1796,15 @@ local function loadUnitOptions()
min = -20, max = 20, step = 1, softMin = -5, softMax = 5,
hidden = false,
},
+ sep2 = {
+ order = 4.5,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = function(info)
+ return hideAdvancedOption(info) or not getVariable(info[2], "text", quickIDMap[info[#(info) - 1]], "block")
+ end
+ },
x = {
order = 5,
type = "range",
@@ -1514,54 +1821,69 @@ local function loadUnitOptions()
},
},
}
-
+
Config.parentTable = {
order = 0,
type = "group",
- hidden = false,
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 unit in pairs(modifyUnits) do
- if( ShadowUF.Tags.unitRestrictions[tag] == unit ) 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 unit in pairs(modifyUnits) do
- if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(unit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then
+ 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]
@@ -1573,20 +1895,20 @@ local function loadUnitOptions()
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 unit in pairs(modifyUnits) do
- savedTagTexts[unit] = getVariable(unit, "text", id, "text")
- if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(unit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then
- if( not ShadowUF.Tags.unitRestrictions[tag] or ShadowUF.Tags.unitRestrictions[tag] == unit ) then
+ 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[unit] = string.format("[%s]", tag)
+ savedTagTexts[modUnit] = string.format("[%s]", tag)
else
- savedTagTexts[unit] = string.format("%s[( )%s]", savedTagTexts[unit], tag)
+ savedTagTexts[modUnit] = string.format("%s[( )%s]", savedTagTexts[modUnit], tag)
end
-
- savedTagTexts.global = savedTagTexts[unit]
+
+ savedTagTexts.global = savedTagTexts[modUnit]
end
end
end
@@ -1597,30 +1919,7 @@ local function loadUnitOptions()
text = string.format("%s[( )%s]", text, tag)
end
end
- -- Removing a tag from global config, need to make sure we can do it
- -- Hack, clean up later
- elseif( unit == "global" ) then
- table.wipe(savedTagTexts)
- for unit in pairs(modifyUnits) do
- if( not ShadowUF.Tags.unitBlacklist[tagGroup] or not string.match(unit, ShadowUF.Tags.unitBlacklist[tagGroup]) ) then
- if( not ShadowUF.Tags.unitRestrictions[tag] or ShadowUF.Tags.unitRestrictions[tag] == unit ) then
- local text = getVariable(unit, "text", id, "text")
- for matchedTag in string.gmatch(text, "%[(.-)%]") do
- local safeTag = "[" .. matchedTag .. "]"
- if( string.match(safeTag, "%[" .. tag .. "%]") or string.match(safeTag, "%)" .. tag .. "%]") or string.match(safeTag, "%[" .. tag .. "%(") or string.match(safeTag, "%)" .. tag .. "%(") ) then
- text = string.gsub(text, "%[" .. string.gsub(string.gsub(matchedTag, "%)", "%%)"), "%(", "%%(") .. "%]", "")
- text = string.gsub(text, " ", "")
- text = string.trim(text)
- break
- end
- end
-
- savedTagTexts[unit] = text
- savedTagTexts.global = text
- end
- end
- end
-
+
-- Removing a tag from a single unit, super easy :<
else
-- Ugly, but it works
@@ -1634,11 +1933,11 @@ local function loadUnitOptions()
end
end
end
-
+
if( unit == "global" ) then
- for unit in pairs(modifyUnits) do
- if( savedTagTexts[unit] ) then
- setVariable(unit, "text", id, "text", savedTagTexts[unit])
+ for modUnit in pairs(modifyUnits) do
+ if( savedTagTexts[modUnit] ) then
+ setVariable(modUnit, "text", id, "text", savedTagTexts[modUnit])
end
end
@@ -1647,19 +1946,19 @@ local function loadUnitOptions()
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,
@@ -1681,12 +1980,12 @@ local function loadUnitOptions()
},
},
}
-
-
+
+
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,
@@ -1697,34 +1996,34 @@ local function loadUnitOptions()
set = selectTag,
get = getTag,
args = {},
- }
+ }
end
Config.tagTable = {
order = 0,
type = "toggle",
hidden = hideBlacklistedTag,
- name = getTagName,
+ 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",
@@ -1739,275 +2038,387 @@ local function loadUnitOptions()
},
},
}
-
+
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) - 1])
-
+ 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) - 1], "enabled") ) then
+
+ if( not getVariable(info[2], "auras", info[#(info) - 2], "enabled") ) then
return true
end
-
- if( ( info[#(info)] == "x" or info[#(info)] == "y" ) and ( info[#(info) - 1] == "buffs" and buffs.anchorOn or info[#(info) - 1] == "debuffs" and debuffs.anchorOn ) ) then
+
+ if( ( info[#(info)] == "x" or info[#(info)] == "y" ) and ( info[#(info) - 2] == "buffs" and buffs.anchorOn or info[#(info) - 2] == "debuffs" and debuffs.anchorOn ) ) then
return true
end
-
- if( anchor == info[#(info) - 1] or buffs.anchorOn or debuffs.anchorOn ) then
+
+ if( anchor == info[#(info) - 2] or buffs.anchorOn or debuffs.anchorOn ) then
return false
- end
-
+ 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",
- inline = true,
hidden = false,
name = function(info) return info[#(info)] == "buffs" and L["Buffs"] or L["Debuffs"] end,
order = function(info) return info[#(info)] == "buffs" and 1 or 2 end,
- disabled = function(info) return not getVariable(info[2], "auras", info[#(info) - 1], "enabled") end,
+ disabled = false,
args = {
- enabled = {
- order = 1,
- type = "toggle",
- name = function(info) if( info[#(info) - 1] == "buffs" ) then return L["Enable buffs"] end return L["Enable debuffs"] end,
- disabled = false,
- arg = "auras.$parent.enabled",
+ general = {
+ type = "group",
+ name = L["General"],
+ order = 0,
+ args = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = function(info) if( info[#(info) - 2] == "buffs" ) then return L["Enable buffs"] end return L["Enable debuffs"] end,
+ disabled = false,
+ width = "full",
+ arg = "auras.$parentparent.enabled",
+ },
+ temporary = {
+ order = 2,
+ type = "toggle",
+ name = L["Enable temporary enchants"],
+ desc = L["Adds temporary enchants to the buffs for the player."],
+ width = "full",
+ hidden = function(info) return info[2] ~= "player" or info[#(info) - 2] ~= "buffs" end,
+ disabled = function(info) return not getVariable(info[2], "auras", "buffs", "enabled") end,
+ arg = "auras.buffs.temporary",
+ }
+ }
},
- anchorOn = {
- order = 2,
- type = "toggle",
- name = function(info) return info[#(info) - 1] == "buffs" and L["Anchor to debuffs"] or L["Anchor to buffs"] end,
- desc = L["Allows you to anchor the aura group to another, you can then choose where it will be anchored using the position.|n|nUse this if you want to duplicate the default ui style where buffs and debuffs are separate groups."],
+ filters = {
+ type = "group",
+ name = L["Filters"],
+ order = 1,
set = function(info, value)
- setVariable(info[2], "auras", info[#(info) - 1] == "buffs" and "debuffs" or "buffs", "anchorOn", false)
- setUnit(info, value)
+ getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]] = value
+ reloadUnitAuras()
end,
- arg = "auras.$parent.anchorOn",
- },
- prioritize = {
- order = 2.25,
- type = "toggle",
- name = L["Prioritize buffs"],
- desc = L["Show buffs before debuffs when sharing the same anchor point."],
- hidden = function(info) return info[#(info) - 1] == "debuffs" end,
- disabled = function(info)
- if( not getVariable(info[2], "auras", info[#(info) - 1], "enabled") ) then return true end
-
- local buffs = getVariable(info[2], "auras", nil, "buffs")
- local debuffs = getVariable(info[2], "auras", nil, "debuffs")
-
- return buffs.anchorOn or debuffs.anchorOn or buffs.anchorPoint ~= debuffs.anchorPoint
+ get = function(info)
+ return getVariable(info[2], "auras", info[#(info) - 2], "show")[info[#(info)]]
end,
- arg = "auras.$parent.prioritize",
+ 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"
+ },
+ }
},
- sep2 = {
- order = 6,
- type = "description",
- name = "",
- 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
+ }
+ }
},
- player = {
- order = 7,
- type = "toggle",
- name = L["Show your auras only"],
- desc = L["Filter out any auras that you did not cast yourself."],
- arg = "auras.$parent.player",
- },
- raid = {
- order = 8,
- type = "toggle",
- name = function(info) return info[#(info) - 1] == "buffs" and L["Show castable on other auras only"] or L["Show curable only"] end,
- desc = function(info) return info[#(info) - 1] == "buffs" and L["Filter out any auras that you cannot cast on another player, or yourself."] or L["Filter out any aura that you cannot cure."] end,
- width = "double",
- arg = "auras.$parent.raid",
- },
- sep3 = {
- order = 9,
- type = "description",
- name = "",
- width = "full",
- },
- selfTimers = {
- order = 9.5,
- type = "toggle",
- name = L["Timers for self auras only"],
- desc = L["Hides the cooldown ring for any auras that you did not cast."],
- hidden = hideAdvancedOption,
- arg = "auras.$parent.selfTimers",
- },
- enlargeSelf = {
- order = 10,
- type = "toggle",
- name = L["Enlarge your auras"],
- desc = L["If you casted the aura, then the buff icon will be increased in size to make it more visible."],
- arg = "auras.$parent.enlargeSelf",
- },
- selfScale = {
- order = 11,
- type = "range",
- name = L["Self aura size"],
- desc = L["Scale for auras that you casted, any number above 100% is bigger tahn default, any number below 100% is smaller than default."],
- min = 1, max = 3, step = 0.10,
- isPercent = true,
- disabled = function(info) return not getVariable(info[2], "auras", info[#(info) - 1], "enlargeSelf") end,
- hidden = hideAdvancedOption,
- arg = "auras.$parent.selfScale",
- },
- selfTimersDouble = {
- order = 11,
- type = "toggle",
- name = L["Timers for self auras only"],
- desc = L["Hides the cooldown ring for any auras that you did not cast."],
- hidden = hideBasicOption,
- arg = "auras.$parent.selfTimers",
- width = "double",
- },
- sep4 = {
- order = 12,
- type = "description",
- name = "",
- width = "full",
- },
- perRow = {
- order = 13,
- type = "range",
- name = function(info)
- local anchorPoint = getVariable(info[2], "auras", info[#(info) - 1], "anchorPoint")
- if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
- return L["Per column"]
- end
-
- return L["Per row"]
- end,
- desc = L["How many auras to show in a single row."],
- min = 1, max = 100, step = 1, softMin = 1, softMax = 50,
- disabled = disableSameAnchor,
- arg = "auras.$parent.perRow",
- },
- maxRows = {
- order = 14,
- type = "range",
- name = L["Max rows"],
- desc = L["How many rows total should be used, rows will be however long the per row value is set at."],
- min = 1, max = 10, step = 1, softMin = 1, softMax = 5,
- disabled = disableSameAnchor,
- hidden = function(info)
- local anchorPoint = getVariable(info[2], "auras", info[#(info) - 1], "anchorPoint")
- if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
- return true
- end
-
- return false
- end,
- arg = "auras.$parent.maxRows",
- },
- maxColumns = {
- order = 14,
- type = "range",
- name = L["Max columns"],
- desc = L["How many auras per a column for example, entering two her will create two rows that are filled up to whatever per row is set as."],
- min = 1, max = 100, step = 1, softMin = 1, softMax = 50,
- hidden = function(info)
- local anchorPoint = getVariable(info[2], "auras", info[#(info) - 1], "anchorPoint")
- if( ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "LEFT" or ShadowUF.Layout:GetColumnGrowth(anchorPoint) == "RIGHT" ) then
- return false
- end
-
- return true
- end,
- disabled = disableSameAnchor,
- arg = "auras.$parent.maxRows",
- },
- size = {
- order = 15,
- type = "range",
- name = L["Size"],
- min = 1, max = 30, step = 1,
- arg = "auras.$parent.size",
- },
- sep5 = {
- order = 16,
- type = "description",
- name = "",
- width = "full",
- },
- anchorPoint = {
- order = 17,
- type = "select",
- name = L["Position"],
- desc = L["How you want this aura to be anchored to the unit frame."],
- values = getAuraAnchors,
- disabled = disableAnchoredTo,
- arg = "auras.$parent.anchorPoint",
- },
- x = {
- order = 18,
- type = "range",
- name = L["X Offset"],
- min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100,
- disabled = disableSameAnchor,
- hidden = hideAdvancedOption,
- arg = "auras.$parent.x",
- },
- y = {
- order = 19,
- type = "range",
- name = L["Y Offset"],
- min = -1000, max = 1000, step = 1, softMin = -100, softMax = 100,
- disabled = disableSameAnchor,
- hidden = hideAdvancedOption,
- arg = "auras.$parent.y",
- },
- },
+ positioning = {
+ type = "group",
+ name = L["Positioning"],
+ order = 3,
+ args = {
+ anchorOn = {
+ order = 1,
+ 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 = true,
+ inline = false,
hidden = function(info) return hideRestrictedOption(info) or not getVariable(info[2], info[#(info)], nil, "enabled") end,
args = {
enableBar = {
@@ -2017,8 +2428,8 @@ local function loadUnitOptions()
desc = L["Turns this widget into a bar that can be resized and ordered just like health and power bars."],
hidden = function(info) return ShadowUF.modules[info[#(info) - 1]].moduleHasBar end,
arg = "$parent.isBar",
- width = "full",
},
+ sep1 = {order = 1.25, type = "description", name = "", hidden = function(info) return (info[#(info) - 1] ~= "burningEmbersBar" or not getVariable(info[2], info[#(info) - 1], nil, "backgroundColor") or not getVariable(info[2], info[#(info) - 1], nil, "background")) end},
background = {
order = 1.5,
type = "toggle",
@@ -2027,18 +2438,76 @@ local function loadUnitOptions()
hidden = hideBarOption,
arg = "$parent.background",
},
- sep2 = {order = 1.75, type = "description", name = "", hidden = function(info)
- local moduleKey = info[#(info) - 1]
- return ( moduleKey ~= "healthBar" and moduleKey ~= "powerBar" and moduleKey ~= "druidBar" ) or not ShadowUF.db.profile.advanced
- end},
+ sep2 = {order = 1.55, type = "description", name = "", hidden = function(info) return not (not ShadowUF.modules[info[#(info) - 1]] or not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints) end},
+ overrideBackground = {
+ order = 1.6,
+ type = "toggle",
+ name = L["Override background"],
+ desc = L["Show a background behind the bars with the same texture/color but faded out."],
+ disabled = function(info) return not getVariable(info[2], info[#(info) - 1], nil, "background") end,
+ hidden = function(info) return info[#(info) - 1] ~= "burningEmbersBar" end,
+ set = function(info, toggle)
+ if( toggle ) then
+ setVariable(info[2], info[#(info) - 1], nil, "backgroundColor", {r = 0, g = 0, b = 0, a = 0.70})
+ else
+ setVariable(info[2], info[#(info) - 1], nil, "backgroundColor", nil)
+ end
+ end,
+ get = function(info)
+ return not not getVariable(info[2], info[#(info) - 1], nil, "backgroundColor")
+ end
+ },
+ overrideColor = {
+ order = 1.65,
+ type = "color",
+ hasAlpha = true,
+ name = L["Background color"],
+ hidden = function(info) return info[#(info) - 1] ~= "burningEmbersBar" or not getVariable(info[2], info[#(info) - 1], nil, "backgroundColor") or not getVariable(info[2], info[#(info) - 1], nil, "background") end,
+ set = function(info, r, g, b, a)
+ local color = getUnit(info) or {}
+ color.r = r
+ color.g = g
+ color.b = b
+ color.a = a
+
+ setUnit(info, color)
+ end,
+ get = function(info)
+ local color = getUnit(info)
+ if( not color ) then
+ return 0, 0, 0, 1
+ end
+
+ return color.r, color.g, color.b, color.a
+
+ end,
+ arg = "$parent.backgroundColor",
+ },
+ vertical = {
+ order = 1.70,
+ type = "toggle",
+ name = L["Vertical growth"],
+ desc = L["Rather than bars filling from left -> right, they will fill from bottom -> top."],
+ arg = "$parent.vertical",
+ hidden = function(info) return not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,
+ },
+ reverse = {
+ order = 1.71,
+ type = "toggle",
+ name = L["Reverse fill"],
+ desc = L["Will fill right -> left when using horizontal growth, or top -> bottom when using vertical growth."],
+ arg = "$parent.reverse",
+ hidden = function(info) return not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,
+ },
invert = {
order = 2,
type = "toggle",
name = L["Invert colors"],
desc = L["Flips coloring so the bar color is shown as the background color and the background as the bar"],
- hidden = function(info) return ( info[#(info) - 1] ~= "healthBar" and info[#(info) - 1] ~= "powerBar" and info[#(info) - 1] ~= "druidBar" ) or not ShadowUF.db.profile.advanced end,
+ hidden = function(info) return not ShadowUF.modules[info[#(info) - 1]] or not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,
arg = "$parent.invert",
},
+ sep3 = {order = 3, type = "description", name = "", hidden = function(info) return not ShadowUF.modules[info[#(info) - 1]] or not ShadowUF.db.profile.advanced or ShadowUF.modules[info[#(info) - 1]].isComboPoints end,},
order = {
order = 4,
type = "range",
@@ -2055,17 +2524,17 @@ local function loadUnitOptions()
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,
@@ -2120,7 +2589,7 @@ local function loadUnitOptions()
},
},
}
-
+
Config.unitTable = {
type = "group",
childGroups = "tab",
@@ -2155,7 +2624,7 @@ local function loadUnitOptions()
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
@@ -2215,7 +2684,7 @@ local function loadUnitOptions()
name = string.format(L["Enable %s"], L["Combat fader"]),
desc = L["Combat fader will fade out all your frames while they are inactive and fade them back in once you are in combat or active."],
hidden = false,
- arg = "fader.enabled",
+ arg = "fader.enabled"
},
combatAlpha = {
order = 1,
@@ -2304,7 +2773,7 @@ local function loadUnitOptions()
name = L["On aggro"],
desc = L["Highlight units that have aggro on any mob."],
arg = "highlight.aggro",
- hidden = function(info) return info[2] == "arena" or info[2] == "arenapet" or ShadowUF.fakeUnits[info[2]] end,
+ hidden = function(info) return ShadowUF.Units.zoneUnits[info[2]] or info[2] == "battlegroundpet" or info[2] == "arenapet" or ShadowUF.fakeUnits[info[2]] end,
},
debuff = {
order = 6,
@@ -2312,7 +2781,30 @@ local function loadUnitOptions()
name = L["On curable debuff"],
desc = L["Highlight units that are debuffed with something you can cure."],
arg = "highlight.debuff",
- hidden = function(info) return string.match(info[2], "^arena") or string.match(info[2], "^boss") end,
+ hidden = function(info) return info[2] ~= "boss" and ( ShadowUF.Units.zoneUnits[info[2]] or info[2] == "battlegroundpet" or info[2] == "arenapet" ) end,
+ },
+ raremob = {
+ order = 6.10,
+ type = "toggle",
+ name = L["On rare mobs"],
+ desc = L["Highlight units that are rare."],
+ arg = "highlight.rareMob",
+ hidden = function(info) return not (info[2] == "target" or info[2] == "focus" or info[2] == "targettarget" or info[3] == "focustarget") end,
+ },
+ elitemob = {
+ order = 6.15,
+ type = "toggle",
+ name = L["On elite mobs"],
+ desc = L["Highlight units that are "],
+ arg = "highlight.eliteMob",
+ hidden = function(info) return not (info[2] == "target" or info[2] == "focus" or info[2] == "targettarget" or info[3] == "focustarget") end,
+ },
+ sep = {
+ order = 6.5,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = function(info) return not (ShadowUF.Units.zoneUnits[info[2]] or info[2] == "battlegroundpet" or info[2] == "arenapet" or ShadowUF.fakeUnits[info[2]]) and not (info[2] == "target" or info[2] == "focus" or info[2] == "targettarget" or info[3] == "focustarget") end,
},
alpha = {
order = 7,
@@ -2333,20 +2825,20 @@ local function loadUnitOptions()
},
},
},
- -- This might need some help text indicating why the options disappeared, will see.
- barComboPoints = {
+ -- SOUL SHARDS
+ barSouls = {
order = 4,
type = "group",
inline = true,
- name = L["Combo points"],
- hidden = function(info) return not getVariable(info[2], "comboPoints", nil, "isBar") or not getVariable(info[2], nil, nil, "comboPoints") end,
+ name = L["Soul Shards"],
+ hidden = function(info) return playerClass ~= "WARLOCK" or not getVariable(info[2], "soulShards", nil, "isBar") or not getVariable(info[2], nil, nil, "soulShards") end,
args = {
enabled = {
order = 1,
type = "toggle",
- name = string.format(L["Enable %s"], L["Combo points"]),
+ name = string.format(L["Enable %s"], L["Soul Shards"]),
hidden = false,
- arg = "comboPoints.enabled",
+ arg = "soulShards.enabled",
},
growth = {
order = 2,
@@ -2354,23 +2846,30 @@ local function loadUnitOptions()
name = L["Growth"],
values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
hidden = false,
- arg = "comboPoints.growth",
+ arg = "soulShards.growth",
+ },
+ showAlways = {
+ order = 3,
+ type = "toggle",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "soulShards.showAlways",
},
},
},
- comboPoints = {
+ soulShards = {
order = 4,
type = "group",
inline = true,
- name = L["Combo points"],
- hidden = function(info) if( info[2] == "global" or getVariable(info[2], "comboPoints", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
+ name = L["Soul Shards"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "soulShards", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
args = {
enabled = {
order = 0,
type = "toggle",
- name = string.format(L["Enable %s"], L["Combo points"]),
+ name = string.format(L["Enable %s"], L["Soul Shards"]),
hidden = false,
- arg = "comboPoints.enabled",
+ arg = "soulShards.enabled",
},
sep1 = {
order = 1,
@@ -2385,7 +2884,7 @@ local function loadUnitOptions()
name = L["Growth"],
values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
hidden = false,
- arg = "comboPoints.growth",
+ arg = "soulShards.growth",
},
size = {
order = 2,
@@ -2393,15 +2892,15 @@ local function loadUnitOptions()
name = L["Size"],
min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
hidden = hideAdvancedOption,
- arg = "comboPoints.size",
+ arg = "soulShards.size",
},
spacing = {
order = 3,
type = "range",
name = L["Spacing"],
- min = -20, max = 20, step = 1, softMin = -10, softMax = 10,
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
hidden = hideAdvancedOption,
- arg = "comboPoints.spacing",
+ arg = "soulShards.spacing",
},
sep2 = {
order = 4,
@@ -2416,2592 +2915,4656 @@ local function loadUnitOptions()
name = L["Anchor point"],
values = positionList,
hidden = false,
- arg = "comboPoints.anchorPoint",
+ arg = "soulShards.anchorPoint",
},
x = {
order = 6,
type = "range",
name = L["X Offset"],
- min = -20, max = 20, step = 1,
+ min = -30, max = 30, step = 1,
hidden = false,
- arg = "comboPoints.x",
+ arg = "soulShards.x",
},
y = {
order = 7,
type = "range",
name = L["Y Offset"],
- min = -20, max = 20, step = 1,
+ min = -30, max = 30, step = 1,
hidden = false,
- arg = "comboPoints.y",
+ arg = "soulShards.y",
},
},
},
- combatText = {
- order = 5,
+ -- ARCANE CHARGES
+ barArcane = {
+ order = 4,
type = "group",
inline = true,
- name = L["Combat text"],
- hidden = hideRestrictedOption,
+ name = L["Arcane Charges"],
+ hidden = function(info) return playerClass ~= "MAGE" or not getVariable(info[2], "arcaneCharges", nil, "isBar") or not getVariable(info[2], nil, nil, "arcaneCharges") end,
args = {
- combatText = {
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Arcane Charges"]),
+ hidden = false,
+ arg = "arcaneCharges.enabled",
+ },
+ growth = {
+ order = 2,
+ type = "select",
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
+ hidden = false,
+ arg = "arcaneCharges.growth",
+ },
+ showAlways = {
+ order = 3,
+ type = "toggle",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "arcaneCharges.showAlways",
+ },
+ },
+ },
+ arcaneCharges = {
+ order = 4,
+ type = "group",
+ inline = true,
+ name = L["Arcane Charges"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "arcaneCharges", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
+ args = {
+ enabled = {
order = 0,
type = "toggle",
- name = string.format(L["Enable %s"], L["Combat text"]),
- desc = L["Shows combat feedback, last healing the unit received, last hit did it miss, resist, dodged and so on."],
- arg = "combatText.enabled",
+ name = string.format(L["Enable %s"], L["Arcane Charges"]),
hidden = false,
+ arg = "arcaneCharges.enabled",
},
- sep = {
+ sep1 = {
order = 1,
type = "description",
name = "",
width = "full",
hidden = hideAdvancedOption,
},
- anchorPoint = {
+ growth = {
+ order = 2,
+ type = "select",
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
+ hidden = false,
+ arg = "arcaneCharges.growth",
+ },
+ size = {
+ order = 2,
+ type = "range",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
+ hidden = hideAdvancedOption,
+ arg = "arcaneCharges.size",
+ },
+ spacing = {
order = 3,
+ type = "range",
+ name = L["Spacing"],
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
+ hidden = hideAdvancedOption,
+ arg = "arcaneCharges.spacing",
+ },
+ sep2 = {
+ order = 4,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
+ },
+ anchorPoint = {
+ order = 5,
type = "select",
name = L["Anchor point"],
values = positionList,
- arg = "combatText.anchorPoint",
- hidden = hideAdvancedOption,
+ hidden = false,
+ arg = "arcaneCharges.anchorPoint",
},
x = {
- order = 4,
+ order = 6,
type = "range",
name = L["X Offset"],
- min = -50, max = 50, step = 1,
- arg = "combatText.x",
- hidden = hideAdvancedOption,
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "arcaneCharges.x",
},
y = {
- order = 5,
+ order = 7,
type = "range",
name = L["Y Offset"],
- min = -50, max = 50, step = 1,
- arg = "combatText.y",
- hidden = hideAdvancedOption,
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "arcaneCharges.y",
},
},
},
- },
- },
- attributes = {
- order = 1.5,
- type = "group",
- name = function(info) return L.units[info[#(info) - 1]] end,
- hidden = function(info)
- local unit = info[#(info) - 1]
- return unit ~= "raid" and unit ~= "raidpet" and unit ~= "party" and unit ~= "mainassist" and unit ~= "maintank" and unit ~= "boss" and unit ~= "arena"
- end,
- set = function(info, value)
- setUnit(info, value)
-
- ShadowUF.Units:ReloadHeader(info[2])
- ShadowUF.modules.movers:Update()
- end,
- get = getUnit,
- args = {
- show = {
- order = 0.5,
+ -- HOLY POWER
+ barHolyPower = {
+ order = 4,
type = "group",
inline = true,
- name = L["Visibility"],
- hidden = function(info) return info[2] ~= "party" and info[2] ~= "raid" end,
+ name = L["Holy Power"],
+ hidden = function(info) return playerClass ~= "PALADIN" or not getVariable(info[2], "holyPower", nil, "isBar") or not getVariable(info[2], nil, nil, "holyPower") end,
args = {
- showPlayer = {
- order = 0,
- type = "toggle",
- name = L["Show player in party"],
- desc = L["The player frame will not be hidden regardless, you will have to manually disable it either entirely or per zone type."],
- hidden = function(info) return info[2] ~= "party" end,
- arg = "showPlayer",
- },
- hideSemiRaid = {
+ enabled = {
order = 1,
type = "toggle",
- name = L["Hide in 6-man raid"],
- desc = L["Party frames are hidden while in a raid group with more than 5 people inside."],
- hidden = function(info) return info[2] ~= "party" end,
- set = function(info, value)
- if( value ) then
- setVariable(info[2], nil, nil, "hideAnyRaid", false)
- end
-
- setVariable(info[2], nil, nil, "hideSemiRaid", value)
- ShadowUF.Units:ReloadHeader(info[#(info) - 3])
- end,
- arg = "hideSemiRaid",
+ name = string.format(L["Enable %s"], L["Holy Power"]),
+ hidden = false,
+ arg = "holyPower.enabled",
},
- hideRaid = {
+ growth = {
order = 2,
- type = "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",
+ type = "select",
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
+ hidden = false,
+ arg = "holyPower.growth",
},
- separateFrames = {
+ showAlways = {
order = 3,
type = "toggle",
- name = L["Separate raid frames"],
- desc = L["Splits raid frames into individual frames for each raid group instead of one single frame.|nNOTE! You cannot drag each group frame individualy, but how they grow is set through the column and row growth options."],
- hidden = function(info) return info[2] ~= "raid" end,
- arg = "frameSplit",
- },
- showInRaid = {
- order = 4,
- type = "toggle",
- name = L["Show party as raid"],
- hidden = hideRaidOption,
- set = function(info, value)
- setUnit(info, value)
-
- ShadowUF.Units:ReloadHeader("party")
- ShadowUF.Units:ReloadHeader("raid")
- ShadowUF.modules.movers:Update()
- end,
- arg = "showParty",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "holyPower.showAlways",
},
},
},
- general = {
- order = 1,
+ holyPower = {
+ order = 4,
type = "group",
inline = true,
- name = L["General"],
- hidden = false,
+ name = L["Holy Power"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "holyPower", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
args = {
- offset = {
- order = 2,
- type = "range",
- name = L["Row offset"],
- desc = L["Spacing between each row"],
- min = -10, max = 100, step = 1,
- arg = "offset",
- },
- attribPoint = {
- order = 3,
- type = "select",
- name = L["Row growth"],
- desc = L["How the rows should grow when new group members are added."],
- values = {["TOP"] = L["Down"], ["BOTTOM"] = L["Up"], ["LEFT"] = L["Right"], ["RIGHT"] = L["Left"]},
- arg = "attribPoint",
- set = function(info, value)
- -- If you set the frames to grow left, the columns have to grow down or up as well
- local attribAnchorPoint = getVariable(info[2], nil, nil, "attribAnchorPoint")
- if( ( value == "LEFT" or value == "RIGHT" ) and attribAnchorPoint ~= "BOTTOM" and attribAnchorPoint ~= "TOP" ) then
- ShadowUF.db.profile.units[info[2]].attribAnchorPoint = "BOTTOM"
- elseif( ( value == "TOP" or value == "BOTTOM" ) and attribAnchorPoint ~= "LEFT" and attribAnchorPoint ~= "RIGHT" ) then
- ShadowUF.db.profile.units[info[2]].attribAnchorPoint = "RIGHT"
- end
-
- setUnit(info, value)
-
- local position = ShadowUF.db.profile.positions[info[2]]
- if( position.top and position.bottom ) then
- local point = ShadowUF.db.profile.units[info[2]].attribAnchorPoint == "RIGHT" and "RIGHT" or "LEFT"
- position.point = (ShadowUF.db.profile.units[info[2]].attribPoint == "BOTTOM" and "BOTTOM" or "TOP") .. point
- position.y = ShadowUF.db.profile.units[info[2]].attribPoint == "BOTTOM" and position.bottom or position.top
- end
-
- ShadowUF.Units:ReloadHeader(info[2])
- ShadowUF.modules.movers:Update()
- end,
+ enabled = {
+ order = 0,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Holy Power"]),
+ hidden = false,
+ arg = "holyPower.enabled",
},
- sep2 = {
- order = 4,
+ sep1 = {
+ order = 1,
type = "description",
name = "",
width = "full",
+ hidden = hideAdvancedOption,
+ },
+ growth = {
+ order = 2,
+ type = "select",
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
hidden = false,
+ arg = "holyPower.growth",
},
- columnSpacing = {
- order = 5,
+ size = {
+ order = 2,
type = "range",
- name = L["Column spacing"],
- min = -30, max = 100, step = 1,
- hidden = hideRaidOrAdvancedOption,
- arg = "columnSpacing",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
+ hidden = hideAdvancedOption,
+ arg = "holyPower.size",
},
- attribAnchorPoint = {
- order = 6,
- type = "select",
- name = L["Column growth"],
- desc = L["How the frames should grow when a new column is added."],
- values = function(info)
- local attribPoint = getVariable(info[2], nil, nil, "attribPoint")
- if( attribPoint == "LEFT" or attribPoint == "RIGHT" ) then
- return {["TOP"] = L["Down"], ["BOTTOM"] = L["Up"]}
- end
-
- return {["LEFT"] = L["Right"], ["RIGHT"] = L["Left"]}
- end,
- hidden = hideRaidOrAdvancedOption,
- set = function(info, value)
- -- If you set the frames to grow left, the columns have to grow down or up as well
- local attribPoint = getVariable(info[2], nil, nil, "attribPoint")
- if( ( value == "LEFT" or value == "RIGHT" ) and attribPoint ~= "BOTTOM" and attribPoint ~= "TOP" ) then
- ShadowUF.db.profile.units[info[2]].attribPoint = "BOTTOM"
- end
-
- setUnit(info, value)
-
- ShadowUF.Units:ReloadHeader(info[2])
- ShadowUF.modules.movers:Update()
- end,
- arg = "attribAnchorPoint",
+ spacing = {
+ order = 3,
+ type = "range",
+ name = L["Spacing"],
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
+ hidden = hideAdvancedOption,
+ arg = "holyPower.spacing",
},
- sep3 = {
- order = 7,
+ sep2 = {
+ order = 4,
type = "description",
name = "",
width = "full",
- hidden = false,
- },
- maxColumns = {
- order = 8,
- type = "range",
- name = L["Max columns"],
- min = 1, max = 20, step = 1,
- arg = "maxColumns",
- hidden = function(info) return info[2] == "boss" or info[2] == "arena" or hideSplitOrRaidOption(info) end,
- },
- unitsPerColumn = {
- order = 8,
- type = "range",
- name = L["Units per column"],
- min = 1, max = 40, step = 1,
- arg = "unitsPerColumn",
- hidden = function(info) return info[2] == "boss" or info[2] == "arena" or hideSplitOrRaidOption(info) end,
+ hidden = hideAdvancedOption,
},
- partyPerColumn = {
- order = 9,
- type = "range",
- name = L["Units per column"],
- min = 1, max = 5, step = 1,
- arg = "unitsPerColumn",
- hidden = function(info) return info[2] ~= "party" or not ShadowUF.db.profile.advanced end,
+ anchorPoint = {
+ order = 5,
+ type = "select",
+ name = L["Anchor point"],
+ values = positionList,
+ hidden = false,
+ arg = "holyPower.anchorPoint",
},
- groupsPerRow = {
- order = 8,
+ x = {
+ order = 6,
type = "range",
- name = L["Groups per row"],
- desc = L["How many groups should be shown per row."],
- min = 1, max = 8, step = 1,
- arg = "groupsPerRow",
- hidden = function(info) return info[2] ~= "raid" or not ShadowUF.db.profile.units.raid.frameSplit end,
+ name = L["X Offset"],
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "holyPower.x",
},
- groupSpacing = {
- order = 9,
+ y = {
+ order = 7,
type = "range",
- name = L["Group row spacing"],
- desc = L["How much spacing should be between each new row of groups."],
- min = -50, max = 50, step = 1,
- arg = "groupSpacing",
- hidden = function(info) return info[2] ~= "raid" or not ShadowUF.db.profile.units.raid.frameSplit end,
+ name = L["Y Offset"],
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "holyPower.y",
},
},
},
- sort = {
- order = 2,
+ -- SHADOW ORBS
+ barShadowOrbs = {
+ order = 4,
type = "group",
inline = true,
- name = L["Sorting"],
- hidden = function(info) return info[2] == "boss" or info[2] == "arena" or ( info[2] ~= "raid" and not ShadowUF.db.profile.advanced ) end,
+ name = L["Shadow Orbs"],
+ hidden = function(info) return playerClass ~= "PRIEST" or not getVariable(info[2], "shadowOrbs", nil, "isBar") or not getVariable(info[2], nil, nil, "shadowOrbs") end,
args = {
- sortMethod = {
- order = 2,
- type = "select",
- name = L["Sort method"],
- values = {["INDEX"] = L["Index"], ["NAME"] = L["Name"]},
- arg = "sortMethod",
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Shadow Orbs"]),
hidden = false,
+ arg = "shadowOrbs.enabled",
},
- sortOrder = {
+ growth = {
order = 2,
type = "select",
- name = L["Sort order"],
- values = {["ASC"] = L["Ascending"], ["DESC"] = L["Descending"]},
- arg = "sortOrder",
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
+ hidden = false,
+ arg = "shadowOrbs.growth",
+ },
+ showAlways = {
+ order = 3,
+ type = "toggle",
+ name = L["Don't hide when empty"],
hidden = false,
+ arg = "shadowOrbs.showAlways",
},
},
},
- raid = {
- order = 3,
+ shadowOrbs = {
+ order = 4,
type = "group",
inline = true,
- name = L["Groups"],
- hidden = hideRaidOption,
+ name = L["Holy Power"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "shadowOrbs", nil, "isBar") ) then return true end return hideRestrictedOption(info) end,
args = {
- groupBy = {
- order = 4,
- type = "select",
- name = L["Group by"],
- values = {["GROUP"] = L["Group number"], ["CLASS"] = L["Class"]},
- arg = "groupBy",
- hidden = hideSplitOrRaidOption,
+ enabled = {
+ order = 0,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Shadow Orbs"]),
+ hidden = false,
+ arg = "shadowOrbs.enabled",
},
- sortMethod = {
+ 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["Sort method"],
- values = {["INDEX"] = L["Index"], ["NAME"] = L["Name"]},
- arg = "sortMethod",
+ name = L["Anchor point"],
+ values = positionList,
hidden = false,
+ arg = "shadowOrbs.anchorPoint",
},
- sortOrder = {
+ x = {
order = 6,
- type = "select",
- name = L["Sort order"],
- values = {["ASC"] = L["Ascending"], ["DESC"] = L["Descending"]},
- arg = "sortOrder",
+ type = "range",
+ name = L["X Offset"],
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "shadowOrbs.x",
},
- selectedGroups = {
+ y = {
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,
+ type = "range",
+ name = L["Y Offset"],
+ min = -30, max = 30, step = 1,
+ hidden = false,
+ arg = "shadowOrbs.y",
},
},
},
- },
- },
- frame = {
- order = 2,
- name = L["Frame"],
- type = "group",
- hidden = isModifiersSet,
- set = setUnit,
- get = getUnit,
- args = {
- size = {
- order = 0,
+ -- Chi
+ barChi = {
+ order = 4,
type = "group",
inline = true,
- name = L["Size"],
- hidden = false,
- set = function(info, value)
- setUnit(info, value)
- ShadowUF.modules.movers:Update()
- end,
+ 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 = {
- scale = {
- order = 0,
- type = "range",
- name = L["Scale"],
- min = 0.50, max = 1.50, step = 0.01,
- isPercent = true,
- arg = "scale",
- },
- height = {
+ enabled = {
order = 1,
- type = "range",
- name = L["Height"],
- min = 0, max = 100, step = 1,
- arg = "height",
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Chi"]),
+ hidden = false,
+ arg = "chi.enabled",
},
- width = {
+ growth = {
order = 2,
- type = "range",
- name = L["Width"],
- min = 0, max = 300, step = 1,
- arg = "width",
+ 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",
},
},
},
- anchor = {
- order = 1,
+ chi = {
+ order = 4,
type = "group",
inline = true,
- hidden = function(info) return info[2] == "global" end,
- name = L["Anchor to another frame"],
- set = setPosition,
- get = getPosition,
+ 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 = {
- anchorPoint = {
- order = 0.50,
- type = "select",
- name = L["Anchor point"],
- values = positionList,
+ enabled = {
+ order = 0,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Chi"]),
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,
+ arg = "chi.enabled",
},
- anchorTo = {
+ sep1 = {
order = 1,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
+ },
+ growth = {
+ order = 2,
type = "select",
- name = L["Anchor to"],
- values = getAnchorParents,
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
hidden = false,
+ arg = "chi.growth",
},
- sep = {
+ size = {
order = 2,
+ type = "range",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
+ hidden = hideAdvancedOption,
+ arg = "chi.size",
+ },
+ spacing = {
+ order = 3,
+ type = "range",
+ name = L["Spacing"],
+ min = -30, max = 30, step = 1, softMin = -15, softMax = 15,
+ hidden = hideAdvancedOption,
+ arg = "chi.spacing",
+ },
+ sep2 = {
+ order = 4,
type = "description",
name = "",
width = "full",
+ hidden = hideAdvancedOption,
+ },
+ anchorPoint = {
+ order = 5,
+ type = "select",
+ name = L["Anchor point"],
+ values = positionList,
hidden = false,
+ arg = "chi.anchorPoint",
},
x = {
- order = 3,
- type = "input",
+ order = 6,
+ type = "range",
name = L["X Offset"],
- validate = checkNumber,
- set = setNumber,
- get = getString,
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "chi.x",
},
y = {
- order = 4,
- type = "input",
+ order = 7,
+ type = "range",
name = L["Y Offset"],
- validate = checkNumber,
- set = setNumber,
- get = getString,
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "chi.y",
},
},
},
- 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,
+ -- COMBO POINTS
+ barComboPoints = {
+ order = 4,
type = "group",
- hidden = function(info) if( info[2] == "global" or hideAdvancedOption() ) then return true else return false end end,
inline = true,
- name = L["Manual position"],
- set = setPosition,
- get = getPosition,
+ name = L["Combo points"],
+ hidden = function(info) return not getVariable(info[2], "comboPoints", nil, "isBar") or not getVariable(info[2], nil, nil, "comboPoints") end,
args = {
- point = {
- order = 0,
- type = "select",
- name = L["Point"],
- values = pointPositions,
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = string.format(L["Enable %s"], L["Combo points"]),
hidden = false,
+ arg = "comboPoints.enabled",
},
- anchorTo = {
- order = 0.50,
+ growth = {
+ order = 2,
type = "select",
- name = L["Anchor to"],
- values = getAnchorParents,
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
hidden = false,
+ arg = "comboPoints.growth",
},
- relativePoint = {
- order = 1,
- type = "select",
- name = L["Relative point"],
- values = pointPositions,
+ showAlways = {
+ order = 3,
+ type = "toggle",
+ name = L["Don't hide when empty"],
hidden = false,
+ arg = "comboPoints.showAlways",
},
- sep = {
- order = 2,
+ },
+ },
+ 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",
},
- x = {
- order = 3,
- type = "input",
+ 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"],
- validate = checkNumber,
- set = setNumber,
- get = getString,
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "comboPoints.x",
},
y = {
- order = 4,
- type = "input",
+ order = 7,
+ type = "range",
name = L["Y Offset"],
- validate = checkNumber,
- set = setNumber,
- get = getString,
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "comboPoints.y",
},
},
},
- },
- },
- bars = {
- order = 3,
- name = L["Bars"],
- type = "group",
- hidden = isModifiersSet,
- set = setUnit,
- get = getUnit,
- args = {
- bar = {
- order = 1,
+ -- COMBO POINTS
+ barAuraPoints = {
+ order = 4,
type = "group",
inline = true,
- name = L["General"],
- hidden = false,
+ name = L["Aura Combo Points"],
+ hidden = function(info) return not ShadowUF.modules.auraPoints or not getVariable(info[2], "auraPoints", nil, "isBar") or not getVariable(info[2], nil, nil, "auraPoints") end,
args = {
- runeBar = {
- order = 1,
- type = "toggle",
- name = string.format(L["Enable %s"], L["Rune bar"]),
- desc = L["Adds rune bars and timers before runes refresh to the player frame."],
- hidden = hideRestrictedOption,
- arg = "runeBar.enabled",
- },
- totemBar = {
- order = 1.5,
- type = "toggle",
- name = string.format(L["Enable %s"], ShadowUF.modules.totemBar.moduleName),
- desc = function(info)
- return select(2, UnitClass("player")) == "SHAMAN" and L["Adds totem bars with timers before they expire to the player frame."] or L["Adds a bar indicating how much time is left on your ghoul timer, only used if you do not have a permanent ghoul."]
- end,
- hidden = hideRestrictedOption,
- arg = "totemBar.enabled",
- },
- druidBar = {
+ enabled = {
order = 1,
type = "toggle",
- name = string.format(L["Enable %s"], L["Druid mana bar"]),
- desc = L["Adds another mana bar to the player frame when you are in Bear or Cat form showing you how much mana you have."],
- hidden = hideRestrictedOption,
- arg = "druidBar.enabled",
+ name = string.format(L["Enable %s"], L["Aura Combo Points"]),
+ hidden = false,
+ arg = "auraPoints.enabled",
},
- xpBar = {
+ growth = {
order = 2,
- type = "toggle",
- name = string.format(L["Enable %s"], L["XP/Rep bar"]),
- desc = L["This bar will automatically hide when you are at the level cap, or you do not have any reputations tracked."],
- hidden = hideRestrictedOption,
- arg = "xpBar.enabled",
+ type = "select",
+ name = L["Growth"],
+ values = {["LEFT"] = L["Left"], ["RIGHT"] = L["Right"]},
+ hidden = false,
+ arg = "auraPoints.growth",
},
- sep = {
+ showAlways = {
order = 3,
- type = "description",
- name = "",
- hidden = function(info) return playerClass ~= "DRUID" and playerClass ~= "SHAMAN" and playerClass ~= "DEATHKNIGHT" and info[2] ~= "player" end,
- },
- powerBar = {
- order = 4,
- type = "toggle",
- name = string.format(L["Enable %s"], L["Power bar"]),
- arg = "powerBar.enabled",
- },
- predictPower = {
- order = 5,
type = "toggle",
- name = L["Enable quick power"],
- desc = L["Turns fast updating of the power bar on giving you more up to date power information than normal."],
- arg = "powerBar.predicted",
+ name = L["Don't hide when empty"],
+ hidden = false,
+ arg = "auraPoints.showAlways",
},
},
},
- healthBar = {
- order = 2,
+ auraPoints = {
+ order = 4,
type = "group",
inline = true,
- name = L["Health bar"],
- hidden = false,
+ name = L["Aura Combo Points"],
+ hidden = function(info) if( info[2] == "global" or getVariable(info[2], "auraPoints", nil, "isBar") ) then return true end return not ShadowUF.modules.auraPoints or hideRestrictedOption(info) end,
args = {
enabled = {
- order = 1,
- type = "toggle",
- name = string.format(L["Enable %s"], L["Health bar"]),
- arg = "healthBar.enabled",
- },
- predictedHealth = {
- order = 3,
+ order = 0,
type = "toggle",
- name = L["Enable quick health"],
- desc = L["Turns on fast updating of health bars giving you more up to date health info."],
- arg = "healthBar.predicted",
+ name = string.format(L["Enable %s"], L["Aura Combo Points"]),
+ hidden = false,
+ arg = "auraPoints.enabled",
},
- sep = {
- order = 3.5,
+ sep1 = {
+ order = 1,
type = "description",
name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
},
- healthColor = {
- order = 4,
+ growth = {
+ order = 2,
type = "select",
- name = L["Color health by"],
- desc = L["Primary means of coloring the health bar, color on aggro and color by reaction will override this if necessary."],
- values = {["class"] = L["Class"], ["static"] = L["Static"], ["percent"] = L["Health percent"]},
- arg = "healthBar.colorType",
+ name = L["Growth"],
+ values = {["UP"] = L["Up"], ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"], ["DOWN"] = L["Down"]},
+ hidden = false,
+ arg = "auraPoints.growth",
},
- reactionPet = {
- order = 5,
- type = "toggle",
- name = L["Color by happiness"],
- desc = L["Colors the health bar by how happy your pet is."],
- arg = "healthBar.reactionType",
- set = function(info, value) setVariable(info[2], "healthBar", nil, "reactionType", value and "happiness" or "none") end,
- get = function(info) return getVariable(info[2], "healthBar", nil, "reactionType") == "happiness" and true or false end,
- hidden = function(info) return info[2] ~= "pet" end,
+ size = {
+ order = 2,
+ type = "range",
+ name = L["Size"],
+ min = 0, max = 50, step = 1, softMin = 0, softMax = 20,
+ hidden = hideAdvancedOption,
+ arg = "auraPoints.size",
},
- reaction = {
+ 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["Color by reaction on"],
- desc = L["When to color the health bar by the units reaction, overriding the color health by option."],
- arg = "healthBar.reactionType",
- values = {["none"] = L["Never (Disabled)"], ["player"] = L["Players only"], ["npc"] = L["NPCs only"], ["both"] = L["Both"]},
- hidden = function(info) return info[2] == "player" or info[2] == "pet" end,
+ name = L["Anchor point"],
+ values = positionList,
+ hidden = false,
+ arg = "auraPoints.anchorPoint",
},
- colorAggro = {
+ x = {
order = 6,
- type = "toggle",
- name = L["Color on aggro"],
- desc = L["Changes the health bar to the set hostile color (Red by default) when the unit takes aggro."],
- arg = "healthBar.colorAggro",
- hidden = hideRestrictedOption,
- },
- },
- },
- incHeal = {
- order = 3,
- type = "group",
- inline = true,
- name = L["Incoming heals"],
- hidden = hideRestrictedOption,
- disabled = function(info) return not getVariable(info[2], "healthBar", nil, "enabled") end,
- args = {
- enabled = {
- order = 1,
- type = "toggle",
- name = string.format(L["Enable %s"], L["Incoming heals"]),
- desc = L["Adds a bar inside the health bar indicating how much healing someone is estimated to be receiving."],
- arg = "incHeal.enabled",
+ type = "range",
+ name = L["X Offset"],
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "auraPoints.x",
},
- cap = {
- order = 2,
+ y = {
+ order = 7,
type = "range",
- name = L["Outside bar limit"],
- desc = L["Percentage value of how far outside the unit frame the incoming heal bar can go. 130% means it will go 30% outside the frame, 100% means it will not go outside."],
- min = 1, max = 1.50, step = 0.05, isPercent = true,
- arg = "incHeal.cap",
+ name = L["Y Offset"],
+ min = -30, max = 30, step = 1,
hidden = false,
+ arg = "auraPoints.y",
},
},
},
- emptyBar = {
- order = 4,
+ combatText = {
+ order = 5,
type = "group",
inline = true,
- name = L["Empty bar"],
- hidden = false,
+ name = L["Combat text"],
+ hidden = hideRestrictedOption,
args = {
- enabled = {
- order = 1,
+ combatText = {
+ order = 0,
type = "toggle",
- name = string.format(L["Enable %s"], L["Empty bar"]),
- desc = L["Adds an empty bar that you can put text into as a way of uncluttering other bars."],
- arg = "emptyBar.enabled",
- width = "full",
+ name = string.format(L["Enable %s"], L["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,
},
- 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"]},
+ sep = {
+ order = 1,
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = hideAdvancedOption,
},
- colorType = {
+ anchorPoint = {
order = 3,
- type = "toggle",
- name = L["Color by class"],
- desc = L["Players will be colored by class, "],
- arg = "emptyBar.class",
+ type = "select",
+ name = L["Anchor point"],
+ values = positionList,
+ arg = "combatText.anchorPoint",
+ hidden = hideAdvancedOption,
},
- overrideColor = {
+ x = {
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",
+ 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,
},
},
},
- castBar = {
- order = 5,
+ },
+ },
+ 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["Cast bar"],
- hidden = hideRestrictedOption,
+ name = L["Visibility"],
+ hidden = function(info) return info[2] ~= "party" and info[2] ~= "raid" end,
args = {
- enabled = {
+ 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 = 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",
+ 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",
},
- autoHide = {
+ hideRaid = {
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,
+ 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",
},
- castName = {
+ separateFrames = {
order = 3,
- type = "header",
- name = L["Cast name"],
- hidden = hideAdvancedOption,
+ 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",
},
- nameEnabled = {
- order = 4,
+ hideSemiRaidRaid = {
+ order = 3.5,
type = "toggle",
- name = L["Show cast name"],
- arg = "castBar.name.enabled",
- hidden = hideAdvancedOption,
+ 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"
},
- rankEnabled = {
- order = 4.5,
+ showInRaid = {
+ order = 4,
type = "toggle",
- name = L["Show cast rank"],
- arg = "castBar.name.rank",
- hidden = hideAdvancedOption,
- disabled = disableIfCastName,
+ 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",
},
- nameAnchor = {
- order = 5,
+ },
+ },
+ 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["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",
+ 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,
},
- nameSep = {
- order = 6,
+ sep2 = {
+ order = 4,
type = "description",
name = "",
width = "full",
- hidden = hideAdvancedOption,
+ hidden = false,
},
- nameSize = {
- order = 7,
+ columnSpacing = {
+ order = 5,
type = "range",
- name = L["Size"],
- desc = L["Let's you modify the base font size to either make it larger or smaller."],
+ 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",
- min = -10, max = 10, step = 1, softMin = -5, softMax = 5,
- hidden = hideAdvancedOption,
- arg = "castBar.name.size",
+ 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,
},
- nameX = {
+ unitsPerColumn = {
order = 8,
type = "range",
- name = L["X Offset"],
- min = -20, max = 20, step = 1,
- hidden = hideAdvancedOption,
- arg = "castBar.name.x",
+ 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,
},
- nameY = {
+ partyPerColumn = {
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,
+ 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,
},
- timeEnabled = {
- order = 11,
- type = "toggle",
- name = L["Show cast time"],
- arg = "castBar.time.enabled",
- hidden = hideAdvancedOption,
+ 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,
},
- 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",
+ 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,
},
- timeSep = {
- order = 13,
- type = "description",
- name = "",
- width = "full",
- hidden = hideAdvancedOption,
+ },
+ },
+ 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,
},
- timeSize = {
- order = 14,
- type = "range",
- name = L["Size"],
- desc = L["Let's you modify the base font size to either make it larger or smaller."],
- type = "range",
- min = -10, max = 10, step = 1, softMin = -5, softMax = 5,
- hidden = hideAdvancedOption,
- arg = "castBar.time.size",
+ sortOrder = {
+ order = 2,
+ type = "select",
+ name = L["Sort order"],
+ values = {["ASC"] = L["Ascending"], ["DESC"] = L["Descending"]},
+ arg = "sortOrder",
+ hidden = false,
},
- timeX = {
- order = 15,
- type = "range",
- name = L["X Offset"],
- min = -20, max = 20, step = 1,
- hidden = hideAdvancedOption,
- arg = "castBar.time.x",
+ },
+ },
+ 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,
},
- timeY = {
- order = 16,
- type = "range",
- name = L["Y Offset"],
- min = -20, max = 20, step = 1,
- hidden = hideAdvancedOption,
- arg = "castBar.time.y",
+ 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,
},
},
},
},
},
- widgetSize = {
- order = 4,
- name = L["Widget size"],
+ frame = {
+ order = 2,
+ name = L["Frame"],
type = "group",
hidden = isModifiersSet,
set = setUnit,
get = getUnit,
args = {
- help = {
+ size = {
order = 0,
type = "group",
- name = L["Help"],
inline = true,
+ name = L["Size"],
hidden = false,
+ set = function(info, value)
+ setUnit(info, value)
+ ShadowUF.modules.movers:Update()
+ end,
args = {
- help = {
+ scale = {
order = 0,
- type = "description",
- name = L["Bars with an order higher or lower than the full size options will use the entire unit frame width.|n|nBar orders between those two numbers are shown next to the portrait."],
+ type = "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",
},
},
},
- portrait = {
- order = 0.5,
+ anchor = {
+ order = 1,
type = "group",
- name = L["Portrait"],
inline = true,
- hidden = false,
+ hidden = function(info) return info[2] == "global" end,
+ name = L["Anchor to another frame"],
+ set = setPosition,
+ get = getPosition,
args = {
- enableBar = {
+ 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 = "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",
+ type = "select",
+ name = L["Anchor to"],
+ values = getAnchorParents,
+ hidden = false,
},
sep = {
- order = 1.5,
+ order = 2,
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",
+ hidden = false,
},
- order = {
+ x = {
order = 3,
- type = "range",
- name = L["Order"],
- min = 0, max = 100, step = 5,
- hidden = hideBarOption,
- arg = "portrait.order",
+ type = "input",
+ name = L["X Offset"],
+ validate = checkNumber,
+ set = setNumber,
+ get = getString,
+ hidden = false,
},
- height = {
+ y = {
order = 4,
- type = "range",
- name = L["Height"],
- desc = L["How much of the frames total height this bar should get, this is a weighted value, the higher it is the more it gets."],
- min = 0, max = 10, step = 0.1,
- hidden = hideBarOption,
- arg = "portrait.height",
+ type = "input",
+ name = L["Y Offset"],
+ validate = checkNumber,
+ set = setNumber,
+ get = getString,
+ hidden = false,
},
},
},
- },
- },
- auras = {
- order = 5,
- name = L["Auras"],
- type = "group",
- hidden = isModifiersSet,
- set = setUnit,
- get = getUnit,
- args = {
- temp = {
- order = 0,
+ 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["Temporary enchants"],
- hidden = function(info) return info[2] ~= "player" end,
+ name = L["Manual position"],
+ set = setPosition,
+ get = getPosition,
args = {
- temporary = {
+ point = {
order = 0,
- type = "toggle",
- name = L["Enable temporary enchants"],
- desc = L["Adds temporary enchants to the buffs for the player."],
- disabled = function(info) return not getVariable(info[2], "auras", "buffs", "enabled") end,
- arg = "auras.buffs.temporary",
- width = "double",
+ 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,
},
},
},
- buffs = Config.auraTable,
- debuffs = Config.auraTable,
},
},
- indicators = {
- order = 5.5,
+ bars = {
+ order = 3,
+ name = L["Bars"],
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
-
- options.args.enableUnits = {
- type = "group",
- name = L["Enabled units"],
- desc = getPageDescription,
- args = {
- help = {
- order = 1,
- type = "group",
- inline = true,
- name = L["Help"],
- hidden = hideBasicOption,
- args = {
- help = {
- order = 0,
- type = "description",
- name = L["The check boxes below will allow you to enable or disable units."],
- },
- },
- },
- enabled = {
- order = 2,
- type = "group",
- inline = true,
- name = L["Enable units"],
- args = {},
- },
- },
- }
-
- options.args.units = {
- type = "group",
- name = L["Unit configuration"],
- desc = getPageDescription,
- args = {
- help = {
- order = 1,
- 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",
+ 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",
+ }
+ },
},
- },
- },
- global = {
- type = "group",
- childGroups = "tab",
- order = 0,
- name = L["Global"],
- args = {
- units = {
- order = 0,
+ classmiscbars = {
+ order = 2,
type = "group",
- name = L["Units"],
- set = function(info, value)
- local unit = info[#(info)]
- if( IsShiftKeyDown() ) then
- for _, unit in pairs(ShadowUF.unitList) do
- if( ShadowUF.db.profile.units[unit].enabled ) then
- modifyUnits[unit] = value and true or nil
-
- if( value ) then
- globalConfig = mergeTables(globalConfig, ShadowUF.db.profile.units[unit])
- end
- end
- end
+ 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
- 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 = {}
+ return unit ~= "player" and unit ~= "pet"
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 = {
+ runeBar = {
order = 1,
- type = "group",
- name = L["Units"],
- inline = true,
- args = {},
+ 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",
},
},
},
- },
- },
- },
- }
-
- -- 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
- 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,
+ 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 = getName,
- hidden = isUnitDisabled,
+ name = function(info) return filterMap[info[#(info)]] end,
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)]])
+ 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",
+ },
+ },
+ },
+ },
+ },
+ },
}
-
- -- 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
+ -- 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
-
- 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 400
- 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"]
- end,
- width = "full",
- }
-
- for cat, list in pairs(unitCategories) do
- options.args.enableUnits.args.enabled.args[cat .. "cat"] = unitCategory
+ end
- for _, unit in pairs(list) do
- unitCatOrder[unit] = cat == "player" and 50 or cat == "general" and 100 or cat == "party" and 200 or cat == "raid" and 300 or 400
+ -- Annoying yes, but only way that works
+ ShadowUF.Units:CheckPlayerZone(true)
+
+ if( unit == "global" ) then
+ globalVisibility[area .. key] = value
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
+ local function get(info)
+ local key = info[#(info)]
+ local unit = info[#(info) - 1]
+ local area = info[#(info) - 2]
----------------------
--- FILTER CONFIGURATION
----------------------
-local function loadFilterOptions()
- local hasWhitelist, hasBlacklist, rebuildFilters
- local filterMap, spellMap = {}, {}
+ if( key == "enabled" ) then
+ key = ""
+ end
- local manageFiltersTable = {
- order = function(info) return info[#(info)] == "whitelists" and 1 or 2 end,
- type = "group",
- name = function(info) return info[#(info)] == "whitelists" and L["Whitelists"] or L["Blacklists"] end,
- args = {
- },
- }
-
- local 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()
+ 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 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)]]
+
+ 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
-
- --- Container widget for the filter listing
- local filterEditTable = {
- order = 0,
+
+ local areaTable = {
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,
+ 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 = {
- general = {
+ help = {
order = 0,
type = "group",
- name = function(info) return filterMap[info[#(info) - 1]] end,
- hidden = false,
+ name = L["Help"],
inline = true,
+ hidden = hideBasicOption,
args = {
- add = {
+ help = {
order = 0,
- type = "input",
- name = L["Aura name"],
- --dialogControl = "Aura_EditBox",
- hidden = false,
- set = function(info, value)
- local filterType = info[#(info) - 3]
- local filter = filterMap[info[#(info) - 2]]
-
- ShadowUF.db.profile.filters[filterType][filter][value] = true
-
- reloadUnitAuras()
- rebuildFilters()
- end,
- },
- delete = {
- order = 1,
- type = "execute",
- name = L["Delete filter"],
- hidden = false,
- confirmText = L["Are you sure you want to delete this filter?"],
- confirm = true,
- func = function(info, value)
- local filterType = info[#(info) - 3]
- local filter = filterMap[info[#(info) - 2]]
-
- ShadowUF.db.profile.filters[filterType][filter] = nil
-
- -- Delete anything that used this filter too
- local filterList = filterType == "whitelist" and ShadowUF.db.profile.filters.zonewhite or filterType == "blacklist" and ShadowUF.db.profile.filters.zoneblack
- for id, filterUsed in pairs(filterList) do
- if( filterUsed == filter ) then
- filterList[id] = nil
- end
- end
-
- reloadUnitAuras()
- rebuildFilters()
+ 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,
},
},
},
- 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,
- },
- },
+ 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",
},
- spells = {
- order = 3,
+ 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,
- name = L["Auras"],
- hidden = false,
+ 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,
+ neighborhood = areaTable,
},
}
-
- -- Spell list for manage aura filters
- local spellLabel = {
- order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) end,
- type = "description",
- -- Odd I know, AceConfigDialog-3.0 expands descriptions to full width if width is nil
- -- on the other hand we can't set width to "normal" so tricking it
- width = "",
- fontSize = "medium",
- name = function(info) return spellMap[info[#(info)]] end,
+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"]
}
-
- local spellRow = {
- order = function(info) return tonumber(string.match(info[#(info)], "(%d+)")) + 0.5 end,
- type = "execute",
- name = L["Delete"],
- width = "half",
- func = function(info)
- local spell = spellMap[info[#(info)]]
- local filter = filterMap[info[#(info) - 2]]
- local filterType = info[#(info) - 3]
-
- ShadowUF.db.profile.filters[filterType][filter][spell] = nil
- rebuildFilters()
+
+ for token, name in pairs(LOCALIZED_CLASS_NAMES_MALE) do
+ groupAliases[string.lower(token)] = name
+ end
+
+ local groupList = {}
+ local function getAuraGroup(info)
+ for k in pairs(groupList) do groupList[k] = nil end
+ for name in pairs(ShadowUF.db.profile.auraIndicators.auras) do
+ local aura = Indicators.auraConfig[name]
+ groupList[aura.group] = aura.group
end
- }
- local noSpells = {
- order = 0,
- type = "description",
- name = L["This filter has no auras in it, you will have to add some using the dialog above."],
- }
+ return groupList
+ end
- -- 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+)"))
+ 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
- }
-
- 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,
+ 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",
- inline = true,
- hidden = function() return not hasWhitelist and not hasBlacklist end,
- name = function(info) return AREA_NAMES[info[#(info)]] or L["Global"] end,
- set = function(info, value)
- local filter = filterMap[info[#(info)]]
- local zone = info[#(info) - 1]
- local unit = info[#(info) - 2]
- local filterKey = ShadowUF.db.profile.filters.whitelists[filter] and "zonewhite" or "zoneblack"
-
- for _, zoneConfig in pairs(zoneList) do
- if( zone == "global" or zoneConfig == zone ) then
- if( unit == "global" ) then
- globalSettings[zoneConfig .. filterKey] = value and filter or false
-
- for _, unit in pairs(ShadowUF.unitList) do
- ShadowUF.db.profile.filters[filterKey][zoneConfig .. unit] = value and filter or nil
- end
- else
- ShadowUF.db.profile.filters[filterKey][zoneConfig .. unit] = value and filter or nil
- end
+ name = function(info)
+ local name = groupName(groupMap[info[#(info)]])
+
+ local token = reverseClassMap[name]
+ if( not token ) then return name end
+
+ return ShadowUF:Hex(ShadowUF.db.profile.classColors[token]) .. name .. "|r"
+ end,
+ desc = function(info)
+ local group = groupMap[info[#(info)]]
+ local totalInGroup = 0
+ for _, aura in pairs(Indicators.auraConfig) do
+ if( type(aura) == "table" and aura.group == group ) then
+ totalInGroup = totalInGroup + 1
end
end
-
- if( zone == "global" ) then
- globalSettings[zone .. unit .. filterKey] = value and filter or false
- end
-
- reloadUnitAuras()
+
+ return string.format(L["%d auras in group"], totalInGroup)
end,
- get = function(info)
- local filter = filterMap[info[#(info)]]
- local zone = info[#(info) - 1]
- local unit = info[#(info) - 2]
-
- if( unit == "global" or zone == "global" ) then
- local id = zone == "global" and zone .. unit or zone
- local filterKey = ShadowUF.db.profile.filters.whitelists[filter] and "zonewhite" or "zoneblack"
-
- if( info[#(info)] == "nofilter" ) then
- return globalSettings[id .. "zonewhite"] == false and globalSettings[id .. "zoneblack"] == false
- end
+ args = {},
+ }
- return globalSettings[id .. filterKey] == filter
+ 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
-
- if( info[#(info)] == "nofilter" ) then
- return not ShadowUF.db.profile.filters.zonewhite[zone .. unit] and not ShadowUF.db.profile.filters.zoneblack[zone .. unit]
+
+ Indicators.auraConfig[aura][key] = value
+ writeAuraTable(aura)
+ ShadowUF.Layout:Reload()
+ end,
+ get = function(info)
+ local aura = auraMap[info[#(info) - 1]]
+ local key = info[#(info)]
+ local config = Indicators.auraConfig[aura]
+ if( key == "color" ) then
+ return config.r, config.g, config.b, config.alpha
+ elseif( key == "selfColor" ) then
+ if( not config.selfColor ) then return 0, 0, 0, 1 end
+ return config.selfColor.r, config.selfColor.g, config.selfColor.b, config.selfColor.alpha
end
-
- return ShadowUF.db.profile.filters.zonewhite[zone .. unit] == filter or ShadowUF.db.profile.filters.zoneblack[zone .. unit] == filter
+
+ return config[key]
end,
args = {
- nofilter = {
- order = 0,
- type = "toggle",
- name = L["Don't use a filter"],
+ indicator = {
+ order = 1,
+ type = "select",
+ name = L["Show inside"],
+ desc = L["Indicator this aura should be displayed in."],
+ values = getIndicatorList,
hidden = false,
- set = function(info, value)
- local filter = filterMap[info[#(info)]]
- local zone = info[#(info) - 1]
- local unit = info[#(info) - 2]
-
- for _, zoneConfig in pairs(zoneList) do
- if( zone == "global" or zoneConfig == zone ) then
- if( unit == "global" ) then
- globalSettings[zoneConfig .. "zonewhite"] = false
- globalSettings[zoneConfig .. "zoneblack"] = false
-
- for _, unit in pairs(ShadowUF.unitList) do
- ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unit] = nil
- ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unit] = nil
- end
- else
- ShadowUF.db.profile.filters.zonewhite[zoneConfig .. unit] = nil
- ShadowUF.db.profile.filters.zoneblack[zoneConfig .. unit] = nil
- end
- end
- end
-
- if( zone == "global" ) then
- globalSettings[zone .. unit .. "zonewhite"] = false
- globalSettings[zone .. unit .. "zoneblack"] = false
- end
-
- reloadUnitAuras()
- end,
},
- white = {
- order = 1,
- type = "header",
- name = "|cffffffff" .. L["Whitelists"] .. "|r",
- hidden = function(info) return not hasWhitelist end
+ 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,
},
- black = {
+ sep1 = {
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
+ type = "description",
+ name = "",
+ width = "full",
+ hidden = false,
},
- },
- }
-
- -- Toggle used for set filter zones to enable filters
- local filterToggle = {
- order = function(info) return ShadowUF.db.profile.filters.whitelists[filterMap[info[#(info)]]] and 2 or 4 end,
- type = "toggle",
- name = function(info) return filterMap[info[#(info)]] end,
- desc = function(info)
- local filter = filterMap[info[#(info)]]
- filter = ShadowUF.db.profile.filters.whitelists[filter] or ShadowUF.db.profile.filters.blacklists[filter]
- if( filter.buffs and filter.debuffs ) then
- return L["Filtering both buffs and debuffs"]
- elseif( filter.buffs ) then
- return L["Filtering buffs only"]
- elseif( filter.debuffs ) then
- return L["Filtering debuffs only"]
- end
-
- return L["This filter has no aura types set to filter out."]
- end,
- }
-
- -- Load existing filters in
- -- This needs to be cleaned up later
- local filterID, spellID = 0, 0
- local function buildList(type)
- local manageFiltersTable = {
- order = type == "whitelists" and 1 or 2,
- type = "group",
- name = type == "whitelists" and L["Whitelists"] or L["Blacklists"],
- args = {
- groups = {
- order = 0,
- type = "group",
- inline = true,
- name = function(info) return info[#(info) - 1] == "whitelists" and L["Whitelist filters"] or L["Blacklist filters"] end,
- args = {
- },
- },
+ 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,
},
- }
-
- local hasFilters
- for name, spells in pairs(ShadowUF.db.profile.filters[type]) do
- hasFilters = true
- filterID = filterID + 1
- filterMap[tostring(filterID)] = name
- filterMap[filterID .. "label"] = name
- filterMap[filterID .. "row"] = name
-
- manageFiltersTable.args[tostring(filterID)] = CopyTable(filterEditTable)
- manageFiltersTable.args.groups.args[filterID .. "label"] = filterLabel
- manageFiltersTable.args.groups.args[filterID .. "row"] = filterRow
- filterTable.args[tostring(filterID)] = filterToggle
-
- local hasSpells
- for spellName in pairs(spells) do
- if( spellName ~= "buffs" and spellName ~= "debuffs" ) then
- hasSpells = true
- spellID = spellID + 1
- spellMap[tostring(spellID)] = spellName
- spellMap[spellID .. "label"] = spellName
-
- manageFiltersTable.args[tostring(filterID)].args.spells.args[spellID .. "label"] = spellLabel
- manageFiltersTable.args[tostring(filterID)].args.spells.args[tostring(spellID)] = spellRow
- end
- end
-
- if( not hasSpells ) then
- manageFiltersTable.args[tostring(filterID)].args.spells.args.noSpells = noSpells
- end
- end
-
- if( not hasFilters ) then
- if( type == "whitelists" ) then hasWhitelist = nil else hasBlacklist = nil end
- manageFiltersTable.args.groups.args.noFilters = noFilters
- end
-
- return manageFiltersTable
- end
-
- rebuildFilters = function()
- for id in pairs(filterMap) do filterTable.args[id] = nil end
-
- spellID = 0
- filterID = 0
- hasBlacklist = true
- hasWhitelist = true
-
- table.wipe(filterMap)
- table.wipe(spellMap)
-
- options.args.filter.args.filters.args.whitelists = buildList("whitelists")
- options.args.filter.args.filters.args.blacklists = buildList("blacklists")
- end
-
- local unitFilterSelection = {
- order = function(info) return info[#(info)] == "global" and 1 or (getUnitOrder(info) + 1) end,
+ 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",
- name = function(info) return info[#(info)] == "global" and L["Global"] or getName(info) end,
- disabled = function(info)
- if( info[#(info)] == "global" ) then
- return false
+ 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 not hasWhitelist and not hasBlacklist
+
+ return ShadowUF.db.profile.auraIndicators.filters[indicator][filter][key]
end,
args = {
help = {
order = 0,
type = "group",
- inline = true,
name = L["Help"],
- hidden = function() return hasWhitelist or hasBlacklist end,
+ inline = true,
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",
+ name = L["Auras matching a criteria will automatically show up in the indicator when enabled."]
}
- },
- },
- header = {
- order = 0,
- type = "header",
- name = function(info) return (info[#(info) - 1] == "global" and L["Global"] or L.units[info[#(info) - 1]]) end,
- hidden = function() return not hasWhitelist and not hasBlacklist end,
+ }
},
- global = filterTable,
- none = filterTable,
- pvp = filterTable,
- arena = filterTable,
- party = filterTable,
- raid = filterTable,
- }
- }
-
- local addFilter = {type = "whitelists"}
-
- options.args.filter = {
- type = "group",
- name = L["Aura filters"],
- childGroups = "tab",
- desc = getPageDescription,
- args = {
- groups = {
+ boss = {
order = 1,
type = "group",
- name = L["Set filter zones"],
+ name = L["Boss Auras"],
+ inline = true,
args = {
- help = {
- order = 0,
- type = "group",
- inline = true,
- name = L["Help"],
- args = {
- help = {
- type = "description",
- name = L["You can set what unit frame should use what filter group and in what zone type here, if you want to change what auras goes into what group then see the \"Manage aura groups\" option."],
- width = "full",
- }
- },
+ enabled = {
+ order = 1,
+ type = "toggle",
+ name = L["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
+ }
}
},
- filters = {
+ curable = {
order = 2,
type = "group",
- name = L["Manage aura filters"],
- childGroups = "tree",
+ name = L["Curable Auras"],
+ inline = true,
args = {
- manage = {
+ enabled = {
order = 1,
- type = "group",
- name = L["Management"],
- args = {
- help = {
- order = 0,
- type = "group",
- inline = true,
- name = L["Help"],
- args = {
- help = {
- type = "description",
- name = L["Whitelists will hide any aura not in the filter group.|nBlacklists will hide auras that are in the filter group."],
- width = "full",
- }
- },
- },
- error = {
- order = 1,
- type = "group",
- inline = true,
- hidden = function() return not addFilter.error end,
- name = L["Error"],
- args = {
- error = {
- order = 0,
- type = "description",
- name = function() return addFilter.error end,
- width = "full",
- },
- },
- },
- add = {
- order = 2,
- type = "group",
- inline = true,
- name = L["New filter"],
- get = function(info) return addFilter[info[#(info)]] end,
- args = {
- name = {
- order = 0,
- type = "input",
- name = L["Name"],
- set = function(info, value)
- addFilter[info[#(info)]] = string.trim(value) ~= "" and value or nil
- addFilter.error = nil
- end,
- get = function(info) return addFilter.errorName or addFilter.name end,
- validate = function(info, value)
- local name = string.lower(string.trim(value))
- for filter in pairs(ShadowUF.db.profile.filters.whitelists) do
- if( string.lower(filter) == name ) then
- addFilter.error = string.format(L["The whitelist \"%s\" already exists."], value)
- addFilter.errorName = value
- AceRegistry:NotifyChange("ShadowedUF")
- return ""
- end
- end
+ 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
+ }
+ }
+ }
+ }
+ }
- for filter in pairs(ShadowUF.db.profile.filters.blacklists) do
- if( string.lower(filter) == name ) then
- addFilter.error = string.format(L["The blacklist \"%s\" already exists."], value)
- addFilter.errorName = value
- AceRegistry:NotifyChange("ShadowedUF")
- return ""
- end
- end
-
- addFilter.error = nil
- addFilter.errorName = nil
- return true
- end,
- },
- type = {
- order = 1,
- type = "select",
- name = L["Filter type"],
- set = function(info, value) addFilter[info[#(info)]] = value end,
- values = {["whitelists"] = L["Whitelist"], ["blacklists"] = L["Blacklist"]},
- },
- add = {
- order = 2,
- type = "execute",
- name = L["Create"],
- disabled = function(info) return not addFilter.name end,
- func = function(info)
- ShadowUF.db.profile.filters[addFilter.type][addFilter.name] = {buffs = true, debuffs = true}
- rebuildFilters()
-
- local id
- for key, value in pairs(filterMap) do
- if( value == addFilter.name ) then
- id = key
- break
- end
- end
-
- AceDialog.Status.ShadowedUF.children.filter.children.filters.status.groups.groups[addFilter.type] = true
- selectTabGroup("filter", "filters", addFilter.type .. "\001" .. id)
-
- table.wipe(addFilter)
- addFilter.type = "whitelists"
- end,
- },
- },
- },
- },
+ 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 = {}, {}, {}, {}
- options.args.filter.args.groups.args.global = unitFilterSelection
- for _, unit in pairs(ShadowUF.unitList) do
- options.args.filter.args.groups.args[unit] = unitFilterSelection
- end
+ -- 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
- rebuildFilters()
-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 = {},
+ },
+ }
+ }
----------------------
--- TAG CONFIGURATION
----------------------
-local function loadTagOptions()
- local tagData = {search = ""}
- local function set(info, value, key)
- local key = key or info[#(info)]
- if( ShadowUF.Tags.defaultHelp[tagData.name] ) then
- return
- end
-
- -- Reset loaded function + reload tags
- if( key == "funct" ) then
- ShadowUF.tagFunc[tagData.name] = nil
- ShadowUF.Tags:Reload()
- elseif( key == "category" ) then
- local cat = ShadowUF.db.profile.tags[tagData.name][key]
- if( cat and cat ~= value ) then
- Config.tagTextTable.args[cat].args[tagData.name] = nil
- Config.tagTextTable.args[value].args[tagData.name] = Config.tagTable
+ local 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
+ end,
+ get = function(info, value) return not globalConfig["filter-" .. info[#(info)]] end
+ }
- ShadowUF.db.profile.tags[tagData.name][key] = value
- end
-
- local function stripCode(text)
- if( not text ) then
- return ""
- end
-
- return string.gsub(string.gsub(text, "|", "||"), "\t", "")
- end
-
- local function get(info, key)
- local key = key or info[#(info)]
-
- if( key == "help" and ShadowUF.Tags.defaultHelp[tagData.name] ) then
- return ShadowUF.Tags.defaultHelp[tagData.name] or ""
- elseif( key == "events" and ShadowUF.Tags.defaultEvents[tagData.name] ) then
- return ShadowUF.Tags.defaultEvents[tagData.name] or ""
- elseif( key == "frequency" and ShadowUF.Tags.defaultFrequents[tagData.name] ) then
- return ShadowUF.Tags.defaultFrequents[tagData.name] or ""
- elseif( key == "category" and ShadowUF.Tags.defaultCategories[tagData.name] ) then
- return ShadowUF.Tags.defaultCategories[tagData.name] or ""
- elseif( key == "name" and ShadowUF.Tags.defaultNames[tagData.name] ) then
- return ShadowUF.Tags.defaultNames[tagData.name] or ""
- elseif( key == "funct" and ShadowUF.Tags.defaultTags[tagData.name] ) then
- return ShadowUF.Tags.defaultTags[tagData.name] or ""
- end
-
- return ShadowUF.db.profile.tags[tagData.name] and ShadowUF.db.profile.tags[tagData.name][key] or ""
- end
-
- local function isSearchHidden(info)
- return tagData.search ~= "" and not string.match(info[#(info)], tagData.search) or false
- end
-
- local function editTag(info)
- tagData.name = info[#(info)]
-
- if( ShadowUF.Tags.defaultHelp[tagData.name] ) then
- tagData.error = L["You cannot edit this tag because it is one of the default ones included in this mod. This function is here to provide an example for your own custom tags."]
- end
-
- selectDialogGroup("tags", "edit")
- end
-
- -- Create all of the tag editor options, if it's a default tag will show it after any custom ones
- local tagTable = {
- type = "execute",
- order = function(info) return ShadowUF.Tags.defaultTags[info[#(info)]] and 100 or 1 end,
- name = getTagName,
- desc = getTagHelp,
- hidden = isSearchHidden,
- func = editTag,
+ 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 tagCategories = {}
- local function getTagCategories(info)
- for k in pairs(tagCategories) do tagCategories[k] = nil end
-
- for _, cat in pairs(ShadowUF.Tags.defaultCategories) do
- tagCategories[cat] = TAG_GROUPS[cat]
+
+ local 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 tagCategories
+
+ return enabledUnits
end
-
- -- Tag configuration
- options.args.tags = {
+
+ local widthReset
+
+ -- Actual tab view thing
+ options.args.auraIndicators = {
+ order = 4.5,
type = "group",
+ name = L["Aura Indicators"],
+ desc = L["For configuring aura indicators on unit frames."],
childGroups = "tab",
- name = L["Add tags"],
- desc = getPageDescription,
- hidden = hideAdvancedOption,
+ hidden = false,
args = {
- general = {
- order = 0,
+ indicators = {
+ order = 1,
type = "group",
- name = L["Tag list"],
+ name = L["Indicators"],
+ childGroups = "tree",
args = {
- help = {
+ add = {
order = 0,
type = "group",
- inline = true,
- name = L["Help"],
- hidden = function() return ShadowUF.db.profile.advanced end,
+ name = L["Add Indicator"],
args = {
- description = {
+ add = {
order = 0,
- type = "description",
- name = L["You can add new custom tags through this page, if you're looking to change what tags are used in text look under the Text tab for an Units configuration."],
- },
- },
- },
- search = {
- order = 1,
- type = "group",
- inline = true,
- name = L["Search"],
- args = {
- search = {
- order = 1,
- type = "input",
- name = L["Search tags"],
- set = function(info, text) tagData.search = text end,
- get = function(info) return tagData.search end,
+ type = "group",
+ inline = true,
+ name = L["Add new indicator"],
+ args = {
+ name = {
+ order = 0,
+ type = "input",
+ name = L["Indicator name"],
+ width = "full",
+ set = function(info, value)
+ local id = string.format("%d", GetTime() + math.random(100))
+ ShadowUF.db.profile.auraIndicators.indicators[id] = {enabled = true, friendly = true, hostile = true, name = value, anchorPoint = "C", anchorTo = "$parent", height = 10, width = 10, alpha = 1.0, x = 0, y = 0}
+ ShadowUF.db.profile.auraIndicators.filters[id] = {boss = {}, curable = {}}
+
+ options.args.auraIndicators.args.indicators.args[id] = indicatorTable
+ options.args.auraIndicators.args.auras.args.filters.args[id] = auraFilterConfigTable
+
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.indicators.status.groups.selected = id
+ AceRegistry:NotifyChange("ShadowedUF")
+ end,
+ get = function() return "" end,
+ },
+ },
},
},
},
- list = {
- order = 2,
- type = "group",
- inline = true,
- name = L["Tags"],
- args = {},
- },
},
},
- add = {
- order = 1,
+ auras = {
+ order = 2,
type = "group",
- name = L["Add new tag"],
+ name = L["Auras"],
+ hidden = function(info)
+ if( not widthReset and AceDialog.Status.ShadowedUF.children.auraIndicators ) then
+ if( AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras ) then
+ widthReset = true
+
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.treewidth = 230
+
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.groups = {}
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.groups.filters = true
+ AceDialog.Status.ShadowedUF.children.auraIndicators.children.auras.status.groups.groups.groups = true
+
+ AceRegistry:NotifyChange("ShadowedUF")
+ end
+ end
+
+ return false
+ end,
args = {
- help = {
- order = 0,
- type = "group",
- inline = true,
- name = L["Help"],
- args = {
- help = {
- order = 0,
- type = "description",
- name = L["You can find more information on creating your own custom tags in the \"Help\" tab above."],
- },
- },
- },
add = {
- order = 1,
+ order = 0,
type = "group",
- inline = true,
- name = L["Add new tag"],
+ name = L["Add Aura"],
+ set = function(info, value) addAura[info[#(info)]] = value end,
+ get = function(info) return addAura[info[#(info)]] end,
args = {
- error = {
+ name = {
order = 0,
- type = "description",
- name = function() return tagData.addError or "" end,
- hidden = function() return not tagData.addError end,
- },
- errorHeader = {
- order = 0.50,
- type = "header",
- name = "",
- hidden = function() return not tagData.addError end,
+ type = "input",
+ name = L["Spell Name/ID"],
+ desc = L["If name is entered, it must be exact as it is case sensitive. Alternatively, you can use spell id instead."]
},
- tag = {
+ group = {
order = 1,
- type = "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
+ 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")
- 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")
+
+ ShadowUF.Layout:Reload()
end,
},
},
},
+ filters = {
+ order = 1,
+ type = "group",
+ name = L["Automatic Auras"],
+ args = {}
+ },
+ groups = {
+ order = 2,
+ type = "group",
+ name = L["Groups"],
+ args = {}
+ },
},
},
- edit = {
- order = 2,
+ linked = {
+ order = 3,
type = "group",
- name = L["Edit tag"],
- hidden = function() return not tagData.name end,
+ name = L["Linked spells"],
+ childGroups = "tree",
+ hidden = true,
args = {
help = {
order = 0,
type = "group",
- inline = true,
name = L["Help"],
+ inline = true,
args = {
help = {
order = 0,
type = "description",
- name = L["You can find more information on creating your own custom tags in the \"Help\" tab above.|nSUF will attempt to automatically detect what events your tag will need, so you do not generally need to fill out the events field."],
+ name = L["You can link auras together using this, for example you can link Mark of the Wild to Gift of the Wild so if the player has Mark of the Wild but not Gift of the Wild, it will still show Mark of the Wild as if they had Gift of the Wild."],
+ width = "full",
},
},
},
- tag = {
+ add = {
order = 1,
type = "group",
+ name = L["Add link"],
inline = true,
- name = function() return string.format(L["Editing %s"], tagData.name or "") end,
+ set = function(info, value)
+ addLink[info[#(info)] ] = value
+ end,
+ get = function(info) return addLink[info[#(info)] ] end,
args = {
- error = {
+ from = {
order = 0,
- type = "description",
- name = function() return tagData.error or "" end,
- hidden = function() return not tagData.error end,
- },
- errorHeader = {
- order = 1,
- type = "header",
- name = "",
- hidden = function() return not tagData.error end,
- },
- discovery = {
- order = 1,
- type = "toggle",
- name = L["Disable event discovery"],
- desc = L["This will disable the automatic detection of what events this tag will need, you should leave this unchecked unless you know what you are doing."],
- set = function(info, value) tagData.discovery = value end,
- get = function() return tagData.discovery end,
- width = "full",
- },
- frequencyEnable = {
- order = 1.10,
- type = "toggle",
- name = L["Enable frequent updates"],
- desc = L["Flags the tag for frequent updating, it will update the tag on a timer regardless of any events firing."],
- set = function(info, value)
- tagData.frequency = value and 5 or nil
- set(info, tagData.frequency, "frequency")
- end,
- get = function(info) return get(info, "frequency") ~= "" and true or false end,
- width = "full",
- },
- frequency = {
- order = 1.20,
- type = "input",
- name = L["Update interval"],
- desc = L["How many seconds between updates.|n[WARNING] By setting the frequency to 0 it will update every single frame redraw, if you want to disable frequent updating uncheck it don't set this to 0."],
- disabled = function(info) return get(info) == "" end,
- validate = function(info, value)
- value = tonumber(value)
- if( not value ) then
- tagData.error = L["Invalid interval entered, must be a number."]
- elseif( value < 0 ) then
- tagData.error = L["You must enter a number that is 0 or higher, negative numbers are not allowed."]
- else
- tagData.error = nil
- end
-
- if( tagData.error ) then
- AceRegistry:NotifyChange("ShadowedUF")
- return ""
- end
-
- return true
- end,
- set = function(info, value)
- tagData.frequency = tonumber(value)
- tagData.frequency = tagData.frequency < 0 and 0 or tagData.frequency
-
- set(info, tagData.frequency)
- end,
- get = function(info) return tostring(get(info) or "") end,
- width = "half",
- },
- name = {
- order = 2,
type = "input",
- name = L["Tag name"],
- set = set,
- get = get,
+ name = L["Link from"],
+ desc = L["Spell you want to link to a primary aura, the casing must be exact."],
},
- category = {
- order = 2.5,
+ to = {
+ order = 1,
type = "select",
- name = L["Category"],
- values = getTagCategories,
- set = set,
- get = get,
- },
-
- sep = {
- order = 2.75,
- type = "description",
- name = "",
- width = "full",
+ name = L["Link to"],
+ values = getAuraList,
},
- events = {
+ link = {
order = 3,
- type = "input",
- name = L["Events"],
- desc = L["Events that should be used to trigger an update of this tag. Separate each event with a single space."],
- width = "full",
- validate = function(info, text)
- if( ShadowUF.Tags.defaultTags[tagData.name] ) then
- return true
+ 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( 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 ""
+ if( not pID ) then
+ linkID = linkID + 1
+ pID = linkID
+ linkMap[tostring(linkID)] = addLink.to
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
+
+ if( not lID ) then
+ linkID = linkID + 1
+ lID = linkID
+ linkMap[tostring(linkID)] = addLink.from
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")
+ ShadowUF.db.profile.auraIndicators.linked[addLink.from] = addLink.to
+ options.args.auraIndicators.args.linked.args[tostring(pID)] = parentLinkTable
+ parentLinkTable.args[tostring(lID)] = childLinkTable
+
+ addLink.from = nil
+ addLink.to = nil
+
+ ShadowUF.Layout:Reload()
end,
},
},
},
},
},
- help = {
- order = 3,
+ units = {
+ order = 4,
type = "group",
- name = L["Help"],
+ name = L["Enable Indicators"],
args = {
- general = {
+ help = {
order = 0,
type = "group",
- name = L["General"],
+ name = L["Help"],
inline = true,
args = {
- general = {
+ help = {
order = 0,
type = "description",
- name = L["See the documentation below for information and examples on creating tags, if you just want basic Lua or WoW API information then see the Programming in Lua and WoW Programming links."],
+ name = L["You can disable aura filters and groups for units here. For example, you could set an aura group that shows DPS debuffs to only show on the target."],
+ width = "full",
},
},
},
- documentation = {
- order = 1,
+ global = {
+ order = 0,
type = "group",
- name = L["Documentation"],
- inline = true,
+ name = L["Global"],
+ desc = L["Global configurating will let you mass enable or disable aura groups for multiple units at once."],
args = {
- doc = {
+ units = {
order = 0,
- type = "input",
- name = L["Documentation"],
- set = false,
- get = function() return "http://wiki.github.com/Shadowed/ShadowedUnitFrames/tag-documentation" end,
- width = "full",
+ type = "multiselect",
+ name = L["Units to change"],
+ desc = L["Units that should have the aura groups settings changed below."],
+ values = getEnabledUnits,
+ set = function(info, unit, enabled) setGlobalUnits[unit] = enabled or nil end,
+ get = function(info, unit) return setGlobalUnits[unit] end,
+ },
+ filters = {
+ order = 1,
+ type = "group",
+ inline = true,
+ name = L["Aura filters"],
+ args = {}
+ },
+ groups = {
+ order = 2,
+ type = "group",
+ inline = true,
+ name = L["Aura groups"],
+ args = {}
},
},
},
- resources = {
- order = 2,
+ },
+ },
+ classes = {
+ order = 5,
+ type = "group",
+ name = L["Disable Auras by Class"],
+ childGroups = "tree",
+ args = {
+ help = {
+ order = 0,
type = "group",
+ name = L["Help"],
inline = true,
- name = L["Resources"],
args = {
- lua = {
+ help = {
order = 0,
- type = "input",
- name = L["Programming in Lua"],
- desc = L["This is a good guide on how to get started with programming in Lua, while you do not need to read the entire thing it is a helpful for understanding the basics of Lua syntax and API's."],
- set = false,
- get = function() return "http://www.lua.org/pil/" end,
- width = "full",
- },
- wow = {
- order = 1,
- type = "input",
- name = L["WoW Programming"],
- desc = L["WoW Programming is a good resource for finding out what difference API's do and how to call them."],
- set = false,
- get = function() return "http://wowprogramming.com/docs" end,
+ type = "description",
+ name = L["You can override what aura is enabled on a per-class basis, note that if the aura is disabled through the main listing, then your class settings here will not matter."],
width = "full",
},
},
- },
+ }
},
},
},
}
-
- -- 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 = {
+ local classTable = {
+ order = 1,
type = "group",
- order = function(info) return info[#(info)] == "none" and 2 or 1 end,
- childGroups = "tree",
name = function(info)
- return AREA_NAMES[info[#(info)]]
+ return ShadowUF:Hex(ShadowUF.db.profile.classColors[info[#(info)]]) .. LOCALIZED_CLASS_NAMES_MALE[info[#(info)]] .. "|r"
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 = {
+
+ local classAuraTable = {
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)
+ 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,
- arg = 1,
}
-
- for key, module in pairs(ShadowUF.modules) do
- if( module.moduleName ) then
- Config.visibilityTable.args[key] = moduleTable
+
+ -- 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
-
- areaTable.args.global = Config.visibilityTable
- for _, unit in pairs(ShadowUF.unitList) do
- if( not unitBlacklist[unit] ) then
- areaTable.args[unit] = Config.visibilityTable
+
+ -- 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
-
- 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,
- },
- }
+
+ -- 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()
@@ -5016,35 +7579,46 @@ local function loadOptions()
loadHideOptions()
loadTagOptions()
loadFilterOptions()
- loadVisibilityOptions()
-
+ 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()
-
- LibStub("AceConfig-3.0"):RegisterOptionsTable("ShadowedUF", options)
- AceDialog:SetDefaultSize("ShadowedUF", 835, 525)
+
+ AceRegistry:RegisterOptionsTable("ShadowedUF", options, true)
+ AceDialog:SetDefaultSize("ShadowedUF", 895, 570)
registered = true
end
-
+
AceDialog:Open("ShadowedUF")
-end
\ No newline at end of file
+
+ if( not defaultToggles ) then
+ defaultToggles = true
+
+ AceDialog.Status.ShadowedUF.status.groups.groups.units = true
+ AceRegistry:NotifyChange("ShadowedUF")
+ end
+end