Im also gonna post main OmniBar.lua code if it pertinent.
Code:
-- OmniBar by Jordon
OmniBar = LibStub("AceAddon-3.0"):NewAddon("OmniBar", "AceEvent-3.0", "AceHook-3.0")
OmniBar.cooldowns = {
[47476] = { default = true, duration = 60, class = "DEATHKNIGHT" }, -- Strangulate
[47481] = { default = false, duration = 60, class = "DEATHKNIGHT", specID = { 252 } }, -- Gnaw (Ghoul)
[47482] = { default = false, duration = 30, class = "DEATHKNIGHT", specID = { 252 } }, -- Leap (Ghoul)
[47528] = { default = true, duration = 15, class = "DEATHKNIGHT" }, -- Mind Freeze
[48707] = { default = false, duration = 45, class = "DEATHKNIGHT" }, -- Anti-Magic Shell
[48743] = { default = false, duration = 120, class = "DEATHKNIGHT" }, -- Death Pact
[48792] = { default = false, duration = 180, class = "DEATHKNIGHT" }, -- Icebound Fortitude
[49028] = { default = false, duration = 90, class = "DEATHKNIGHT", specID = { 250 } }, -- Dancing Rune Weapon
[49039] = { default = false, duration = 120, class = "DEATHKNIGHT" }, -- Lichborne
[49576] = { default = false, duration = 25, class = "DEATHKNIGHT" }, -- Death Grip
[51052] = { default = false, duration = 120, class = "DEATHKNIGHT" }, -- Anti-Magic Zone
[51271] = { default = false, duration = 60, class = "DEATHKNIGHT", specID = { 251 } }, -- Pillar of Frost
[55233] = { default = false, duration = 60, class = "DEATHKNIGHT", specID = { 250 } }, -- Vampiric Blood
[77606] = { default = false, duration = 30, class = "DEATHKNIGHT" }, -- Dark Simulacrum
[91802] = { default = true, duration = 30, class = "DEATHKNIGHT", specID = { 252 } }, -- Shambling Rush
[96268] = { default = false, duration = 30, class = "DEATHKNIGHT" }, -- Death's Advance
[108194] = { default = false, duration = 30, class = "DEATHKNIGHT" }, -- Asphyxiate
[108201] = { default = false, duration = 120, class = "DEATHKNIGHT" }, -- Desecrated Ground
[152279] = { default = false, duration = 120, class = "DEATHKNIGHT" }, -- Breath of Sindragosa
[498] = { default = false, duration = 30, class = "PALADIN" }, -- Divine Protection
[642] = { default = false, duration = 150, class = "PALADIN" }, -- Divine Shield
[853] = { default = false, duration = 60, class = "PALADIN" }, -- Hammer of Justice
[105593] = { parent = 853, duration = 30 }, -- Fist of Justice
[1022] = { default = false, duration = 300, class = "PALADIN", charges = 2 }, -- Hand of Protection
[1044] = { default = false, duration = 25, class = "PALADIN", charges = 2 }, -- Hand of Freedom
[6940] = { default = false, duration = { default = 90, [65] = 110 }, class = "PALADIN", charges = 2 }, -- Hand of Sacrifice
[20066] = { default = false, duration = 15, class = "PALADIN" }, -- Repentance
[31821] = { default = false, duration = 180, class = "PALADIN", specID = { 65 } }, -- Devotion Aura
[31884] = { default = false, duration = 120, class = "PALADIN" }, -- Avenging Wrath
[96231] = { default = true, duration = 15, class = "PALADIN" }, -- Rebuke
[114039] = { default = false, duration = 30, class = "PALADIN" }, -- Hand of Purity
[114157] = { default = false, duration = 60, class = "PALADIN" }, -- Execution Sentence
[115750] = { default = false, duration = 120, class = "PALADIN" }, -- Blinding Light
[871] = { default = false, duration = 180, class = "WARRIOR", specID = { 73 } }, -- Shield Wall
[1719] = { default = false, duration = 180, class = "WARRIOR", specID = { 71, 72 } }, -- Recklessness
[3411] = { default = false, duration = 30, class = "WARRIOR" }, -- Intervene
[5246] = { default = false, duration = 90, class = "WARRIOR" }, -- Intimidating Shout
[6544] = { default = false, duration = 45, class = "WARRIOR" }, -- Heroic Leap
[6552] = { default = true, duration = 15, class = "WARRIOR" }, -- Pummel
[18499] = { default = false, duration = 30, class = "WARRIOR" }, -- Berserker Rage
[23920] = { default = false, duration = 25, class = "WARRIOR" }, -- Spell Reflection
[114028] = { parent = 23920, duration = 30 }, -- Mass Spell Reflection
[46968] = { default = false, duration = 20, class = "WARRIOR" }, -- Shockwave
[107570] = { default = false, duration = 30, class = "WARRIOR" }, -- Storm Bolt
[107574] = { default = false, duration = 90, class = "WARRIOR" }, -- Avatar
[114029] = { default = false, duration = 30, class = "WARRIOR" }, -- Safeguard
[118000] = { default = false, duration = 60, class = "WARRIOR" }, -- Dragon Roar
[118038] = { default = false, duration = 120, class = "WARRIOR", specID = { 71, 72 } }, -- Die by the Sword
[99] = { default = false, duration = 30, class = "DRUID" }, -- Disorienting Roar
[740] = { default = false, duration = 180, class = "DRUID" }, -- Tranquility
[5211] = { default = false, duration = 50, class = "DRUID" }, -- Bash
[22812] = { default = false, duration = 60, class = "DRUID", specID = { 102, 104, 105 } }, -- Barkskin
[33891] = { default = false, duration = 180, class = "DRUID", specID = { 105 } }, -- Incarnation: Tree of Life
[50334] = { default = false, duration = 180, class = "DRUID", specID = { 103, 104 } }, -- Berserk
[61336] = { default = false, duration = 180, class = "DRUID", specID = { 103, 104 }, charges = 2 }, -- Survival Instincts
[78675] = { default = true, duration = 60, class = "DRUID", specID = { 102 } }, -- Solar Beam
[102280] = { default = false, duration = 30, class = "DRUID" }, -- Displacer Beast
[102342] = { default = false, duration = 60, class = "DRUID", specID = { 105 } }, -- Ironbark
[102359] = { default = false, duration = 30, class = "DRUID" }, -- Mass Entanglement
[102543] = { default = false, duration = 180, class = "DRUID", specID = { 103 } }, -- Incarnation: King of the Jungle
[102560] = { default = false, duration = 180, class = "DRUID", specID = { 102 } }, -- Incarnation: Chosen of Elune
[106839] = { default = true, duration = 15, class = "DRUID", specID = { 103, 104 } }, -- Skull Bash
[108291] = { default = false, duration = 360, class = "DRUID" }, -- Heart of the Wild (Balance)
[108292] = { parent = 108291 }, -- Heart of the Wild (Feral)
[108293] = { parent = 108291 }, -- Heart of the Wild (Guardian)
[108294] = { parent = 108291 }, -- Heart of the Wild (Resto)
[112071] = { default = false, duration = 180, class = "DRUID", specID = { 102 } }, -- Celestial Alignment
[124974] = { default = false, duration = 90, class = "DRUID" }, -- Nature's Vigil
[132158] = { default = false, duration = 60, class = "DRUID", specID = { 105 } }, -- Nature's Swiftness
[132469] = { default = false, duration = 30, class = "DRUID" }, -- Typhoon
[159630] = { default = false, duration = 90, class = "PRIEST", specID = { 256, 257 } }, -- Shadow Magic
[8122] = { default = false, duration = 30, class = "PRIEST" }, -- Psychic Scream
[15487] = { default = true, duration = 45, class = "PRIEST", specID = { 256, 258 } }, -- Silence
[33206] = { default = false, duration = 120, class = "PRIEST", specID = { 256 } }, -- Pain Suppression
[47585] = { default = false, duration = 120, class = "PRIEST", specID = { 258 } }, -- Dispersion
[47788] = { default = false, duration = 180, class = "PRIEST", specID = { 257 } }, -- Guardian Spirit
[64044] = { default = false, duration = 45, class = "PRIEST", specID = { 258 } }, -- Psychic Horror
[73325] = { default = false, duration = 90, class = "PRIEST" }, -- Leap of Faith
[5484] = { default = false, duration = 40, class = "WARLOCK" }, -- Howl of Terror
[6360] = { default = false, duration = 25, class = "WARLOCK" }, -- Whiplash
[6789] = { default = false, duration = 45, class = "WARLOCK" }, -- Mortal Coil
[19505] = { default = false, duration = 15, class = "WARLOCK" }, -- Devour Magic (Felhunter)
[30283] = { default = false, duration = 30, class = "WARLOCK" }, -- Shadowfury
[48020] = { default = false, duration = 26, class = "WARLOCK" }, -- Demonic Portal
[89766] = { default = false, duration = 30, class = "WARLOCK" }, -- Axe Toss
[108482] = { default = false, duration = 120, class = "WARLOCK" }, -- Unbound Will
[119910] = { default = true, duration = 24, class = "WARLOCK" }, -- Spell Lock (Command Demon)
[19647] = { parent = 119910 }, -- Spell Lock (Felhunter)
[119911] = { parent = 119910 }, -- Optical Blast (Command Demon)
[115781] = { parent = 119910 }, -- Optical Blast (Observer)
[132409] = { parent = 119910 }, -- Spell Lock (Grimoire of Sacrifice)
[171138] = { parent = 119910 }, -- Shadow Lock (Doomguard)
[171139] = { parent = 119910 }, -- Shadow Lock (Grimoire of Sacrifice)
[171140] = { parent = 119910 }, -- Shadow Lock (Command Demon)
[111859] = { default = false, duration = 120, class = "WARLOCK" }, -- Grimoire: Imp
[111896] = { default = false, duration = 120, class = "WARLOCK" }, -- Grimoire: Succubus
[111897] = { default = true, duration = 120, class = "WARLOCK" }, -- Grimoire: Felhunter
[77801] = { default = false, duration = 120, class = "WARLOCK", charges = 2 }, -- Dark Soul
[113858] = { parent = 77801 }, -- Dark Soul: Instability
[113860] = { parent = 77801 }, -- Dark Soul: Misery
[113861] = { parent = 77801 }, -- Dark Soul: Knowledge
[115284] = { default = false, duration = 15, class = "WARLOCK" }, -- Clone Magic (Observer)
[115770] = { default = false, duration = 25, class = "WARLOCK" }, -- Fellash
[8143] = { default = false, duration = 60, class = "SHAMAN" }, -- Tremor Totem
[8177] = { default = false, duration = 25, class = "SHAMAN" }, -- Grounding Totem
[30823] = { default = false, duration = 60, class = "SHAMAN", specID = { 262, 263 } }, -- Shamanistic Rage
[51490] = { default = false, duration = 45, class = "SHAMAN", specID = { 262, 263 } }, -- Thunderstorm
[51514] = { default = false, duration = 45, class = "SHAMAN" }, -- Hex
[57994] = { default = true, duration = 12, class = "SHAMAN" }, -- Wind Shear
[98008] = { default = false, duration = 180, class = "SHAMAN" }, -- Spirit Link Totem
[108269] = { default = false, duration = 45, class = "SHAMAN" }, -- Capacitor Totem
[108271] = { default = false, duration = 90, class = "SHAMAN" }, -- Astral Shift
[108273] = { default = false, duration = 60, class = "SHAMAN" }, -- Windwalk Totem
[108285] = { default = false, duration = 180, class = "SHAMAN" }, -- Call of the Elements
[114049] = { default = false, duration = 180, class = "SHAMAN" }, -- Ascendance
[114050] = { parent = 114049 }, -- Ascendance (Elemental)
[114051] = { parent = 114049 }, -- Ascendance (Enhancement)
[114052] = { parent = 114049 }, -- Ascendance (Restoration)
[1499] = { default = false, duration = { default = 20, [253] = 30, [254] = 30 }, class = "HUNTER" }, -- Freezing Trap
[60192] = { parent = 1499 }, -- Freezing Trap (Trap Launcher)
[13813] = { default = false, duration = { default = 20, [253] = 30, [254] = 30 }, class = "HUNTER" }, -- Explosive Trap
[82939] = { parent = 13813 }, -- Explosive Trap (Trap Launcher)
[19263] = { default = false, duration = 180, class = "HUNTER", charges = 2 }, -- Deterrence
[19386] = { default = false, duration = 45, class = "HUNTER" }, -- Wyvern Sting
[19574] = { default = false, duration = 60, class = "HUNTER", specID = { 253 } }, -- Bestial Wrath
[53480] = { default = false, duration = 60, class = "HUNTER" }, -- Roar of Sacrifice
[131894] = { default = false, duration = 60, class = "HUNTER" }, -- A Murder of Crows
[147362] = { default = true, duration = 24, class = "HUNTER" }, -- Counter Shot
[66] = { default = false, duration = 300, class = "MAGE" }, -- Invisibility
[1953] = { default = false, duration = 15, class = "MAGE" }, -- Blink
[2139] = { default = true, duration = 24, class = "MAGE" }, -- Counterspell
[11129] = { default = false, duration = 45, class = "MAGE", specID = { 63 } }, -- Combustion
[11958] = { default = false, duration = 180, class = "MAGE" }, -- Cold Snap
[12043] = { default = false, duration = 90, class = "MAGE", specID = { 62 } }, -- Presence of Mind
[12472] = { default = false, duration = 180, class = "MAGE", specID = { 64 } }, -- Icy Veins
[31661] = { default = false, duration = 20, class = "MAGE", specID = { 63 } }, -- Dragon's Breath
[44572] = { default = false, duration = 30, class = "MAGE", specID = { 64 } }, -- Deep Freeze
[45438] = { default = false, duration = 300, class = "MAGE" }, -- Ice Block
[84714] = { default = false, duration = 60, class = "MAGE", specID = { 64 } }, -- Frozen Orb
[102051] = { default = false, duration = 20, class = "MAGE" }, -- Frostjaw
[113724] = { default = false, duration = 45, class = "MAGE" }, -- Ring of Frost
[157997] = { default = false, duration = 25, class = "MAGE", specID = { 64 }, charges = 2 }, -- Ice Nova
[408] = { default = false, duration = 20, class = "ROGUE" }, -- Kidney Shot
[1766] = { default = true, duration = 15, class = "ROGUE" }, -- Kick
[1856] = { default = false, duration = { default = 60, [261] = 120 }, class = "ROGUE" }, -- Vanish
[2094] = { default = false, duration = 120, class = "ROGUE" }, -- Blind
[2983] = { default = false, duration = 60, class = "ROGUE" }, -- Sprint
[5277] = { default = false, duration = 180, class = "ROGUE" }, -- Evasion
[13750] = { default = false, duration = 180, class = "ROGUE", specID = { 260 } }, -- Adrenaline Rush
[14185] = { default = false, duration = 300, class = "ROGUE" }, -- Preparation
[31224] = { default = false, duration = 60, class = "ROGUE" }, -- Cloak of Shadows
[36554] = { default = false, duration = 20, class = "ROGUE" }, -- Shadow Step
[51690] = { default = false, duration = 120, class = "ROGUE", specID = { 260} }, -- Killing Spree
[51713] = { default = false, duration = 60, class = "ROGUE", specID = { 261 } }, -- Shadow Dance
[74001] = { default = false, duration = 120, class = "ROGUE" }, -- Combat Readiness
[76577] = { default = false, duration = 180, class = "ROGUE" }, -- Smoke Bomb
[113656] = { default = false, duration = 25, class = "MONK", specID = { 269 } }, -- Fists of Fury
[115176] = { default = false, duration = 180, class = "MONK", specID = { 268, 269 } }, -- Zen Meditation
[115203] = { default = false, duration = 180, class = "MONK" }, -- Fortifying Brew
[115310] = { default = false, duration = 180, class = "MONK" }, -- Revival
[116705] = { default = true, duration = 15, class = "MONK" }, -- Spear Hand Strike
[116844] = { default = false, duration = 45, class = "MONK" }, -- Ring of Peace
[116849] = { default = false, duration = 55, class = "MONK", specID = { 270 } }, -- Life Cocoon
[119381] = { default = false, duration = 45, class = "MONK" }, -- Leg Sweep
[119996] = { default = false, duration = 25, class = "MONK" }, -- Transcendence: Transfer
[122470] = { default = false, duration = 90, class = "MONK", specID = { 269 } }, -- Touch of Karma
[122783] = { default = false, duration = 90, class = "MONK" }, -- Diffuse Magic
[137562] = { default = false, duration = 120, class = "MONK" }, -- Nimble Brew
}
local cooldowns = OmniBar.cooldowns
local order = {
["DEATHKNIGHT"] = 1,
["PALADIN"] = 2,
["WARRIOR"] = 3,
["DRUID"] = 4,
["PRIEST"] = 5,
["WARLOCK"] = 6,
["SHAMAN"] = 7,
["HUNTER"] = 8,
["MAGE"] = 9,
["ROGUE"] = 10,
["MONK"] = 11,
}
local resets = {
--[[ Summon Felhunter
- Spell Lock
]]
[691] = { 119910 },
--[[ Cold Snap
- Ice Block
- Presence of Mind
- Dragon's Breath
]]
[11958] = { 45438, 12043, 31661 },
--[[ Preparation
- Sprint
- Vanish
- Evasion
]]
[14185] = { 2983, 1856, 5277 },
--[[ Call of the Elements
- Tremor Totem
- Grounding Totem
- Capacitor Totem
- Windwalk Totem
]]
[108285] = { 8143, 8177, 108269, 108273 },
}
-- Defaults
local defaults = {
size = 40,
columns = 8,
padding = 2,
locked = false,
center = false,
border = true,
highlightTarget = true,
highlightFocus = false,
growUpward = true,
showUnused = false,
adaptive = false,
unusedAlpha = 0.45,
swipeAlpha = 0.65,
cooldownCount = true,
arena = true,
ratedBattleground = true,
battleground = true,
world = true,
ashran = true,
multiple = true,
glow = true,
tooltips = true,
names = false,
maxIcons = 500,
align = "CENTER",
}
local SETTINGS_VERSION = 3
local MAX_DUPLICATE_ICONS = 5
local BASE_ICON_SIZE = 36
local ASHRAN_MAP_ID = 978
local _
OmniBar.index = 1
OmniBar.bars = {}
function OmniBar:OnEnable()
if not OmniBarDB or not OmniBarDB.version or OmniBarDB.version < SETTINGS_VERSION then OmniBarDB = { version = SETTINGS_VERSION } end
self.db = LibStub("AceDB-3.0"):New("OmniBarDB", { profile = { bars = {} } }, true)
self.index = 1
for i = #self.bars, 1, -1 do
OmniBar:Delete(self.bars[i].key, true)
table.remove(self.bars, i)
end
for key,_ in pairs(self.db.profile.bars) do
self:Initialize(key)
self.index = self.index + 1
end
-- Create a default bar if none exist
if self.index == 1 then
self:Initialize("OmniBar1", "OmniBar")
self.index = 2
end
if not self.registered then
self.db.RegisterCallback(self, "OnProfileChanged", "OnEnable")
self.db.RegisterCallback(self, "OnProfileCopied", "OnEnable")
self.db.RegisterCallback(self, "OnProfileReset", "OnEnable")
self:SetupOptions()
self.registered = true
end
for key,_ in pairs(self.db.profile.bars) do
self:AddBarToOptions(key)
end
self:Refresh(true)
end
function OmniBar:Delete(key, keepProfile)
local bar = _G[key]
if not bar then return end
bar:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
bar:UnregisterEvent("PLAYER_ENTERING_WORLD")
bar:UnregisterEvent("ZONE_CHANGED_NEW_AREA")
bar:UnregisterEvent("PLAYER_TARGET_CHANGED")
bar:UnregisterEvent("PLAYER_FOCUS_CHANGED")
bar:UnregisterEvent("PLAYER_REGEN_DISABLED")
bar:UnregisterEvent("ARENA_OPPONENT_UPDATE")
bar:UnregisterEvent("ARENA_PREP_OPPONENT_SPECIALIZATIONS")
bar:UnregisterEvent("UPDATE_BATTLEFIELD_SCORE")
bar:UnregisterEvent("UPDATE_BATTLEFIELD_STATUS")
bar:Hide()
if not keepProfile then self.db.profile.bars[key] = nil end
self.options.args.bars.args[key] = nil
LibStub("AceConfigRegistry-3.0"):NotifyChange("OmniBar")
end
function OmniBar:Initialize(key, name)
if not self.db.profile.bars[key] then
self.db.profile.bars[key] = { name = name }
for a,b in pairs(defaults) do
self.db.profile.bars[key][a] = b
end
end
local f = _G[key] or CreateFrame("Frame", key, UIParent, "OmniBarTemplate")
f:Show()
f.settings = self.db.profile.bars[key]
f.settings.align = f.settings.align or "CENTER"
f.settings.maxIcons = f.settings.maxIcons or 500
f.key = key
f.icons = {}
f.active = {}
f.cooldowns = cooldowns
f.detected = {}
f.specs = {}
f.BASE_ICON_SIZE = BASE_ICON_SIZE
f.numIcons = 0
f:RegisterForDrag("LeftButton")
local name = f.settings.name
f.anchor.text:SetText(name)
-- Load the settings
OmniBar_LoadSettings(f)
-- Create the icons
for spellID,_ in pairs(cooldowns) do
if OmniBar_IsSpellEnabled(f, spellID) then
OmniBar_CreateIcon(f)
end
end
-- Create the duplicate icons
for i = 1, MAX_DUPLICATE_ICONS do
OmniBar_CreateIcon(f)
end
OmniBar_ShowAnchor(f)
OmniBar_RefreshIcons(f)
OmniBar_UpdateIcons(f)
OmniBar_Center(f)
f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
f:RegisterEvent("PLAYER_ENTERING_WORLD")
f:RegisterEvent("ZONE_CHANGED_NEW_AREA")
f:RegisterEvent("PLAYER_TARGET_CHANGED")
f:RegisterEvent("PLAYER_FOCUS_CHANGED")
f:RegisterEvent("PLAYER_REGEN_DISABLED")
f:RegisterEvent("ARENA_OPPONENT_UPDATE")
f:RegisterEvent("ARENA_PREP_OPPONENT_SPECIALIZATIONS")
f:RegisterEvent("UPDATE_BATTLEFIELD_SCORE")
f:RegisterEvent("UPDATE_BATTLEFIELD_STATUS")
table.insert(self.bars, f)
end
function OmniBar:Create()
local key
while true do
key = "OmniBar"..self.index
self.index = self.index + 1
if not self.db.profile.bars[key] then
self:Initialize(key, "OmniBar "..self.index - 1)
self:AddBarToOptions(key, true)
return
end
end
end
function OmniBar:Refresh(full)
for key,_ in pairs(self.db.profile.bars) do
local f = _G[key]
if f then
f.container:SetScale(f.settings.size/BASE_ICON_SIZE)
if full then
OmniBar_OnEvent(f, "PLAYER_ENTERING_WORLD")
else
OmniBar_LoadPosition(f)
OmniBar_UpdateIcons(f)
OmniBar_Center(f)
end
end
end
end
local Masque = LibStub and LibStub("Masque", true)
for spellID,_ in pairs(cooldowns) do
local name, _, icon = GetSpellInfo(spellID)
cooldowns[spellID].icon = icon
cooldowns[spellID].name = name
end
-- create a lookup table to translate spec names into IDs
local specNames = {}
for classID = 1, MAX_CLASSES do
local _, classToken = GetClassInfoByID(classID)
specNames[classToken] = {}
for i = 1, GetNumSpecializationsForClassID(classID) do
local id, name = GetSpecializationInfoForClassID(classID, i)
specNames[classToken][name] = id
end
end
local function IsHostilePlayer(unit)
if not unit then return end
local reaction = UnitReaction("player", unit)
if not reaction then return end -- out of range
return UnitIsPlayer(unit) and reaction < 4 and not UnitIsPossessed(unit)
end
function OmniBar_ShowAnchor(self)
if self.disabled or self.settings.locked or #self.active > 0 then
self.anchor:Hide()
else
local width = self.anchor.text:GetWidth() + 29
self.anchor:SetSize(width, 30)
self.anchor:Show()
end
end
function OmniBar_CreateIcon(self)
if InCombatLockdown() then return end
self.numIcons = self.numIcons + 1
local name = self:GetName()
local key = name.."Icon"..self.numIcons
local f = _G[key] or CreateFrame("Button", key, _G[name.."Icons"], "OmniBarButtonTemplate")
table.insert(self.icons, f)
end
local function SpellBelongsToSpec(spellID, specID)
if not specID then return true end
if not cooldowns[spellID].specID then return true end
for i = 1, #cooldowns[spellID].specID do
if cooldowns[spellID].specID[i] == specID then return true end
end
return false
end
function OmniBar_AddIconsByClass(self, class, sourceGUID, specID)
for spellID, spell in pairs(cooldowns) do
if OmniBar_IsSpellEnabled(self, spellID) and spell.class == class and SpellBelongsToSpec(spellID, specID) then
OmniBar_AddIcon(self, spellID, sourceGUID, nil, true, nil, specID)
end
end
end
local function IconIsSource(iconGUID, guid)
if not guid then return end
if string.len(iconGUID) == 1 then
-- arena target
return UnitGUID("arena"..iconGUID) == guid
end
return iconGUID == guid
end
function OmniBar_UpdateBorders(self)
for i = 1, #self.active do
local border
local guid = self.active[i].sourceGUID
if guid then
if self.settings.highlightFocus and IconIsSource(guid, UnitGUID("focus")) then
self.active[i].FocusTexture:SetAlpha(1)
border = true
else
self.active[i].FocusTexture:SetAlpha(0)
end
if self.settings.highlightTarget and IconIsSource(guid, UnitGUID("target")) then
self.active[i].FocusTexture:SetAlpha(0)
self.active[i].TargetTexture:SetAlpha(1)
border = true
else
self.active[i].TargetTexture:SetAlpha(0)
end
else
local class = select(2, UnitClass("focus"))
if self.settings.highlightFocus and class and IsHostilePlayer("focus") and class == self.active[i].class then
self.active[i].FocusTexture:SetAlpha(1)
border = true
else
self.active[i].FocusTexture:SetAlpha(0)
end
class = select(2, UnitClass("target"))
if self.settings.highlightTarget and class and IsHostilePlayer("target") and class == self.active[i].class then
self.active[i].FocusTexture:SetAlpha(0)
self.active[i].TargetTexture:SetAlpha(1)
border = true
else
self.active[i].TargetTexture:SetAlpha(0)
end
end
-- Set dim
self.active[i]:SetAlpha(self.settings.unusedAlpha and self.active[i].cooldown:GetCooldownTimes() == 0 and not border and
self.settings.unusedAlpha or 1)
end
end
function OmniBar_UpdateArenaSpecs(self)
if self.zone ~= "arena" then return end
for i = 1, 5 do
local specID = GetArenaOpponentSpec(i)
if specID and specID > 0 then
local name = GetUnitName("arena"..i, true)
if name then self.specs[name] = specID end
end
end
end
function OmniBar_SetZone(self, refresh)
local disabled = self.disabled
local _, zone = IsInInstance()
if zone == "none" then
SetMapToCurrentZone()
zone = GetCurrentMapAreaID()
end
self.zone = zone
local rated = IsRatedBattleground()
self.disabled = (zone == "arena" and not self.settings.arena) or
(rated and not self.settings.ratedBattleground) or
(zone == "pvp" and not self.settings.battleground and not rated) or
(zone == ASHRAN_MAP_ID and not self.settings.ashran) or
(zone ~= "arena" and zone ~= "pvp" and zone ~= ASHRAN_MAP_ID and not self.settings.world)
if refresh or disabled ~= self.disabled then
OmniBar_LoadPosition(self)
OmniBar_RefreshIcons(self)
OmniBar_UpdateIcons(self)
OmniBar_ShowAnchor(self)
if zone == "arena" and not self.disabled then
wipe(self.detected)
wipe(self.specs)
OmniBar_OnEvent(self, "ARENA_OPPONENT_UPDATE")
end
end
end
function OmniBar_OnEvent(self, event, ...)
if event == "COMBAT_LOG_EVENT_UNFILTERED" then
local _, event, _, sourceGUID, sourceName, sourceFlags, _,_,_,_,_, spellID = ...
if self.disabled then return end
if event == "SPELL_CAST_SUCCESS" and bit.band(sourceFlags, COMBATLOG_OBJECT_REACTION_HOSTILE) ~= 0 then
if cooldowns[spellID] then
OmniBar_UpdateArenaSpecs(self)
OmniBar_AddIcon(self, spellID, sourceGUID, sourceName)
end
-- Check if we need to reset any cooldowns
if resets[spellID] then
for i = 1, #self.active do
if self.active[i] and self.active[i].spellID and self.active[i].sourceGUID and self.active[i].sourceGUID == sourceGUID and self.active[i].cooldown:IsVisible() then
-- cooldown belongs to this source
for j = 1, #resets[spellID] do
if resets[spellID][j] == self.active[i].spellID then
self.active[i].cooldown:Hide()
OmniBar_CooldownFinish(self.active[i].cooldown, true)
return
end
end
end
end
end
end
elseif event == "PLAYER_ENTERING_WORLD" then
OmniBar_SetZone(self, true)
elseif event == "ZONE_CHANGED_NEW_AREA" then
OmniBar_SetZone(self, true)
elseif event == "UPDATE_BATTLEFIELD_STATUS" then -- IsRatedBattleground() doesn't return valid response until this event
OmniBar_SetZone(self)
elseif event == "UPDATE_BATTLEFIELD_SCORE" then
for i = 1, GetNumBattlefieldScores() do
local name, _,_,_,_,_,_,_, classToken, _,_,_,_,_,_, talentSpec = GetBattlefieldScore(i)
if name and specNames[classToken] and specNames[classToken][talentSpec] then
self.specs[name] = specNames[classToken][talentSpec]
end
end
elseif event == "ARENA_PREP_OPPONENT_SPECIALIZATIONS" or event == "ARENA_OPPONENT_UPDATE" then
if self.disabled or not self.settings.adaptive then return end
for i = 1, 5 do
local specID = GetArenaOpponentSpec(i)
if specID and specID > 0 then
-- only add icons if show unused is checked
if not self.settings.showUnused then return end
if not self.detected[i] then
local class = select(7, GetSpecializationInfoByID(specID))
OmniBar_AddIconsByClass(self, class, i, specID)
self.detected[i] = class
end
end
end
elseif event == "PLAYER_TARGET_CHANGED" or event == "PLAYER_FOCUS_CHANGED" or event == "PLAYER_REGEN_DISABLED" then
if self.disabled then return end
-- update icon borders
OmniBar_UpdateBorders(self)
-- we don't need to add in arena
if self.zone == "arena" then return end
-- only add icons if show adaptive is checked
if not self.settings.showUnused or not self.settings.adaptive then return end
-- only add icons when we're in combat
--if event == "PLAYER_TARGET_CHANGED" and not InCombatLockdown() then return end
local unit = "playertarget"
if IsHostilePlayer(unit) then
local guid = UnitGUID(unit)
local _, class = UnitClass(unit)
if class then
if self.detected[guid] then return end
self.detected[guid] = class
OmniBar_AddIconsByClass(self, class)
end
end
end
end
function OmniBar_LoadSettings(self)
-- Set the scale
self.container:SetScale(self.settings.size/BASE_ICON_SIZE)
OmniBar_LoadPosition(self)
OmniBar_RefreshIcons(self)
OmniBar_UpdateIcons(self)
OmniBar_Center(self)
end
function OmniBar_SavePosition(self, set)
local point, relativeTo, relativePoint, xOfs, yOfs = self:GetPoint()
local frameStrata = self:GetFrameStrata()
relativeTo = relativeTo and relativeTo:GetName() or "UIParent"
if set then
if set.point then point = set.point end
if set.relativeTo then relativeTo = set.relativeTo end
if set.relativePoint then relativePoint = set.relativePoint end
if set.xOfs then xOfs = set.xOfs end
if set.yOfs then yOfs = set.yOfs end
if set.frameStrata then frameStrata = set.frameStrata end
end
if not self.settings.position then
self.settings.position = {}
end
self.settings.position.point = point
self.settings.position.relativeTo = relativeTo
self.settings.position.relativePoint = relativePoint
self.settings.position.xOfs = xOfs
self.settings.position.yOfs = yOfs
self.settings.position.frameStrata = frameStrata
end
function OmniBar_LoadPosition(self)
self:ClearAllPoints()
if self.settings.position then
local relativeTo = self.settings.position.relativeTo and self.settings.position.relativeTo or "UIParent"
self:SetPoint(self.settings.position.point, self.settings.position.relativeTo, self.settings.position.relativePoint,
self.settings.position.xOfs, self.settings.position.yOfs)
if not self.settings.position.frameStrata then self.settings.position.frameStrata = "MEDIUM" end
self:SetFrameStrata(self.settings.position.frameStrata)
else
self:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
OmniBar_SavePosition(self)
end
end
function OmniBar_IsSpellEnabled(self, spellID)
if not spellID then return end
-- Check for an explicit rule
local key = "spell"..spellID
if type(self.settings[key]) == "boolean" then
if self.settings[key] then
return true
end
elseif not self.settings.noDefault and cooldowns[spellID].default then
-- Not user-set, but a default cooldown
return true
end
end
function OmniBar_Center(self)
local parentWidth = UIParent:GetWidth()
local clamp = self.settings.center and (1 - parentWidth)/2 or 0
self:SetClampRectInsets(clamp, -clamp, 0, 0)
clamp = self.settings.center and (self.anchor:GetWidth() - parentWidth)/2 or 0
self.anchor:SetClampRectInsets(clamp, -clamp, 0, 0)
end
function OmniBar_CooldownFinish(self, force)
local icon = self:GetParent()
if icon.cooldown and icon.cooldown:GetCooldownTimes() > 0 and not force then return end -- not complete
local charges = icon.charges
if charges then
charges = charges - 1
if charges > 0 then
-- remove a charge
icon.charges = charges
icon.Count:SetText(charges)
OmniBar_StartCooldown(icon:GetParent():GetParent(), icon, GetTime())
return
end
end
local bar = icon:GetParent():GetParent()
local flash = icon.flashAnim
local newItemGlowAnim = icon.newitemglowAnim
if flash:IsPlaying() or newItemGlowAnim:IsPlaying() then
flash:Stop()
newItemGlowAnim:Stop()
end
if not bar.settings.showUnused then
icon:Hide()
else
if icon.TargetTexture:GetAlpha() == 0 and
icon.FocusTexture:GetAlpha() == 0 and
bar.settings.unusedAlpha then
icon:SetAlpha(bar.settings.unusedAlpha)
end
end
bar:StopMovingOrSizing()
OmniBar_Position(bar)
end
function OmniBar_RefreshIcons(self)
-- Hide all the icons
for i = 1, self.numIcons do
if self.icons[i].MasqueGroup then
--self.icons[i].MasqueGroup:Delete()
self.icons[i].MasqueGroup = nil
end
self.icons[i].TargetTexture:SetAlpha(0)
self.icons[i].FocusTexture:SetAlpha(0)
self.icons[i].flash:SetAlpha(0)
self.icons[i].NewItemTexture:SetAlpha(0)
self.icons[i].cooldown:SetCooldown(0, 0)
self.icons[i].cooldown:Hide()
self.icons[i]:Hide()
end
wipe(self.active)
if self.disabled then return end
if self.settings.showUnused and not self.settings.adaptive then
for spellID,_ in pairs(cooldowns) do
if OmniBar_IsSpellEnabled(self, spellID) then
OmniBar_AddIcon(self, spellID, nil, nil, true)
end
end
end
OmniBar_Position(self)
end
function OmniBar_StartCooldown(self, icon, start)
icon.cooldown:SetCooldown(start, icon.duration)
icon.cooldown.finish = start + icon.duration
icon.cooldown:SetSwipeColor(0, 0, 0, self.settings.swipeAlpha or 0.65)
icon:SetAlpha(1)
end
function OmniBar_AddIcon(self, spellID, sourceGUID, sourceName, init, test, specID)
-- Check for parent spellID
local originalSpellID = spellID
if cooldowns[spellID].parent then spellID = cooldowns[spellID].parent end
if not OmniBar_IsSpellEnabled(self, spellID) then return end
local icon, duplicate
-- Try to reuse a visible frame
for i = 1, #self.active do
if self.active[i].spellID == spellID then
duplicate = true
-- check if we can use this icon, but not when initializing arena opponents
if not init or self.zone ~= "arena" then
-- use icon if not bound to a sourceGUID
if not self.active[i].sourceGUID then
duplicate = nil
icon = self.active[i]
break
end
-- if it's the same source, reuse the icon
if sourceGUID and IconIsSource(self.active[i].sourceGUID, sourceGUID) then
duplicate = nil
icon = self.active[i]
break
end
end
end
end
-- We couldn't find a visible frame to reuse, try to find an unused
if not icon then
if #self.active >= self.settings.maxIcons then return end
if not self.settings.multiple and duplicate then return end
for i = 1, #self.icons do
if not self.icons[i]:IsVisible() then
icon = self.icons[i]
icon.specID = nil
break
end
end
end
-- We couldn't find a frame to use
if not icon then return end
local now = GetTime()
if specID then
icon.specID = specID
else
if sourceName and sourceName ~= COMBATLOG_FILTER_STRING_UNKNOWN_UNITS and self.specs[sourceName] then
icon.specID = self.specs[sourceName]
end
end
icon.class = cooldowns[spellID].class
icon.sourceGUID = sourceGUID
icon.icon:SetTexture(cooldowns[spellID].icon)
icon.spellID = spellID
icon.added = now
if icon.charges and cooldowns[originalSpellID].charges and icon:IsVisible() then
local start, duration = icon.cooldown:GetCooldownTimes()
if icon.cooldown.finish and icon.cooldown.finish - GetTime() > 1 then
-- add a charge
local charges = icon.charges + 1
icon.charges = charges
icon.Count:SetText(charges)
if self.settings.glow then
icon.flashAnim:Play()
icon.newitemglowAnim:Play()
end
return icon
end
elseif cooldowns[originalSpellID].charges then
icon.charges = 1
icon.Count:SetText("1")
else
icon.charges = nil
icon.Count:SetText(nil)
end
local name = self.settings.names and sourceGUID and select(6, GetPlayerInfoByGUID(sourceGUID))
if test and self.settings.names then name = "Name" end
icon.Name:SetText(name)
if cooldowns[originalSpellID].duration then
if type(cooldowns[originalSpellID].duration) == "table" then
if icon.specID and cooldowns[originalSpellID].duration[icon.specID] then
icon.duration = cooldowns[originalSpellID].duration[icon.specID]
else
icon.duration = cooldowns[originalSpellID].duration.default
end
else
icon.duration = cooldowns[originalSpellID].duration
end
else -- child doesn't have a custom duration, use parent
if type(cooldowns[spellID].duration) == "table" then
if icon.specID and cooldowns[spellID].duration[icon.specID] then
icon.duration = cooldowns[spellID].duration[icon.specID]
else
icon.duration = cooldowns[spellID].duration.default
end
else
icon.duration = cooldowns[spellID].duration
end
end
-- We don't want duration to be too long if we're just testing
if test then icon.duration = math.random(5,30) end
-- Masque
if Masque then
icon.MasqueGroup = Masque:Group("OmniBar", cooldowns[spellID].name)
icon.MasqueGroup:AddButton(icon, {
FloatingBG = false,
Icon = icon.icon,
Cooldown = icon.cooldown,
Flash = false,
Pushed = false,
Normal = icon:GetNormalTexture(),
Disabled = false,
Checked = false,
Border = _G[icon:GetName().."Border"],
AutoCastable = false,
Highlight = false,
Hotkey = false,
Count = false,
Name = false,
Duration = false,
AutoCast = false,
})
end
icon:Show()
if not init then
OmniBar_StartCooldown(self, icon, now)
if self.settings.glow then
icon.flashAnim:Play()
icon.newitemglowAnim:Play()
end
end
return icon
end
function OmniBar_UpdateIcons(self)
for i = 1, self.numIcons do
-- Set show text
self.icons[i].cooldown:SetHideCountdownNumbers(not self.settings.cooldownCount and true or false)
self.icons[i].cooldown.noCooldownCount = self.settings.cooldownCount and false
-- Set swipe alpha
self.icons[i].cooldown:SetSwipeColor(0, 0, 0, self.settings.swipeAlpha or 0.65)
-- Set border
if self.settings.border then
self.icons[i].icon:SetTexCoord(0, 0, 0, 1, 1, 0, 1, 1)
else
self.icons[i].icon:SetTexCoord(0.07, 0.9, 0.07, 0.9)
end
-- Set dim
self.icons[i]:SetAlpha(self.settings.unusedAlpha and self.icons[i].cooldown:GetCooldownTimes() == 0 and
self.settings.unusedAlpha or 1)
-- Masque
if self.icons[i].MasqueGroup then self.icons[i].MasqueGroup:ReSkin() end
end
end
function OmniBar_Test(self)
self.disabled = nil
OmniBar_RefreshIcons(self)
for k,v in pairs(cooldowns) do
OmniBar_AddIcon(self, k, nil, nil, nil, true)
end
end
local function ExtractDigits(str)
if not str then return 0 end
if type(str) == "number" then return str end
local num = str:gsub("%D", "")
return tonumber(num) or 0
end
function OmniBar_Position(self)
local numActive = #self.active
if numActive == 0 then
-- Show the anchor if needed
OmniBar_ShowAnchor(self)
return
end
-- Keep cooldowns together by class
if self.settings.showUnused then
table.sort(self.active, function(a, b)
local x, y = ExtractDigits(a.sourceGUID), ExtractDigits(b.sourceGUID)
if a.class == b.class then
if x < y then return true end
if x == y then return a.spellID < b.spellID end
end
return order[a.class] < order[b.class]
end)
else
-- if we aren't showing unused, just sort by added time
table.sort(self.active, function(a, b) return a.added == b.added and a.spellID < b.spellID or a.added < b.added end)
end
local count, rows = 0, 1
local grow = self.settings.growUpward and 1 or -1
local padding = self.settings.padding and self.settings.padding or 0
for i = 1, numActive do
if self.settings.locked then
self.active[i]:EnableMouse(false)
else
self.active[i]:EnableMouse(true)
end
self.active[i]:ClearAllPoints()
local columns = self.settings.columns and self.settings.columns > 0 and self.settings.columns < numActive and
self.settings.columns or numActive
if i > 1 then
count = count + 1
if count >= columns then
if self.settings.align == "CENTER" then
self.active[i]:SetPoint("CENTER", self.anchor, "CENTER", (-BASE_ICON_SIZE-padding)*(columns-1)/2, (BASE_ICON_SIZE+padding)*rows*grow)
else
self.active[i]:SetPoint(self.settings.align, self.anchor, self.settings.align, 0, (BASE_ICON_SIZE+padding)*rows*grow)
end
count = 0
rows = rows + 1
else
if self.settings.align == "RIGHT" then
self.active[i]:SetPoint("TOPRIGHT", self.active[i-1], "TOPLEFT", -1 * padding, 0)
else
self.active[i]:SetPoint("TOPLEFT", self.active[i-1], "TOPRIGHT", padding, 0)
end
end
else
if self.settings.align == "CENTER" then
self.active[i]:SetPoint("CENTER", self.anchor, "CENTER", (-BASE_ICON_SIZE-padding)*(columns-1)/2, 0)
else
self.active[i]:SetPoint(self.settings.align, self.anchor, self.settings.align, 0, 0)
end
end
end
OmniBar_ShowAnchor(self)
end
function OmniBar:Test()
for key,_ in pairs(self.db.profile.bars) do
OmniBar_Test(_G[key])
end
end
SLASH_OmniBar1 = "/ob"
SLASH_OmniBar2 = "/omnibar"
SlashCmdList.OmniBar = function()
InterfaceOptionsFrame_OpenToCategory("OmniBar")
InterfaceOptionsFrame_OpenToCategory("OmniBar")
end