--[[

Version 1.4.1

Author : Adoriele of US Dragonblight - with permission from Levva of EU Khadgar

Repurposed version of ShockAndAwe, an Enhancement Shaman addon, for Balance
Druids. Provides Debuff timers, as well as proc and cooldown bars for Eclipse
and Omen of Clarity.

Changelog:

v1.4.1 - Eclipse cooldown no longer constantly refreshes to 30s, added eclipse type to Eclipse
cooldown bars, changed functionality of Eclipse buff bar to go grey if
the buff disappears early
v1.4.0 - 3.3 patch workaround for lack of Eclipse in Combat Log
v1.3.3 - Fixed bug causing debuffs not to spawn when switching targets. Fixed
bug involving disabling a bar that's currently active.
v1.3.2 - Oops: Applied Debuff/CC change to Abilities as well, and to be safe did
similar things to Procs and Trinkets as a double-check. Also fixed a
bug that would not let you turn off the Eclipse bar.
v1.3.1 - Fixed "Debuff/CC, a nil value" bug
v1.3 - Serious revamp of underlying mechanics. Added trinket bars, cc bars,
multiple proc bars. Added ability to merge bars of the same type
(except procs). Adding custom bars should now be much easier,
relatively.
v1.2.1 - Fixed bug with Eclipse and Moonfire bars overlapping, changed FF bar
to accept any FF.
v1.2 - 3.1 Compatability
v1.1.1 - Fixed GCD bar to be localization independent, added SF Combo points,
structural changes
v1.1 - Finally fixed OoC issue, removed dependency on localization for
functionality
v1.0.5 - Fixed encoding issue with Russian locale, added German locale
v1.0.4 - Fixed a bug with the French localization, added Russian and Taiwan
V1.0.3 - Fixed a bug with the OoC bar
V1.0.2 - Added French localization, fixed test bar bug
V1.0.1 - Added text and icon options

--]]

-- Don't load if it's not a Druid
if select(2, UnitClass('player')) ~= "DRUID" then
DisableAddOn("SquawkAndAwe")
return
end

-- Basic Ace3 stuff
local L = LibStub("AceLocale-3.0"):GetLocale("SquawkAndAwe")
local AceAddon = LibStub("AceAddon-3.0")
local media = LibStub:GetLibrary("LibSharedMedia-3.0");
SquawkAndAwe = AceAddon:NewAddon("SquawkAndAwe", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0")
local REVISION = tonumber(("$Revision: 1.4.1 $"):match("%d+"))

-- Frame creation
SquawkAndAwe.frames = {}
SquawkAndAwe.BaseFrame = CreateFrame("Frame","SquawkAndAweBase",UIParent)

-- Other initializations
SquawkAndAwe.textures = {}
SquawkAndAwe.borders = {}
SquawkAndAwe.fonts = {}
SquawkAndAwe.sounds = {}
SquawkAndAwe.barBackdrop = {
bgFile = "Interface/Tooltips/UI-Tooltip-Background",
edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
tile = false, tileSize = 0, edgeSize = 12,
insets = { left = 2, right = 2, top = 2, bottom = 2 }
}
SquawkAndAwe.frameBackdrop ={
bgFile = "Interface/Tooltips/UI-Tooltip-Background",
--edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
tile = false, tileSize = 0, edgeSize = 12,
insets = { left = 0, right = 0, top = 0, bottom = 0 }
}

SquawkAndAwe.combat = {}
SquawkAndAwe.combat.procs = {}
SquawkAndAwe.combat.procs.Eclipse = {id = 48518, name = GetSpellInfo(48518), cd = 30}
SquawkAndAwe.combat.procs.Eclipsew = {id = 48517, name = GetSpellInfo(48517), cd = 30}
SquawkAndAwe.combat.procs.Omen = {id = 16870, name = GetSpellInfo(16870)}
SquawkAndAwe.combat.procs.T84P = {id = 64823, name = GetSpellInfo(64823)}
SquawkAndAwe.combat.procs.PVP = {id = 46833, name = GetSpellInfo(46833)}
SquawkAndAwe.combat.debuffs = {}
SquawkAndAwe.combat.debuffs.Moonfire = {id = 48463, name = GetSpellInfo(48463), tick = 3}
SquawkAndAwe.combat.debuffs.Insect = {id = 48468, name = GetSpellInfo(48468), tick = 2}
SquawkAndAwe.combat.debuffs.Faerie = {id = 770, name = GetSpellInfo(770)}
SquawkAndAwe.combat.cc = {}
SquawkAndAwe.combat.cc.Roots = {id = 339, name = GetSpellInfo(339)}
SquawkAndAwe.combat.cc.Hibernate = {id = 2637, name = GetSpellInfo(2637)}
SquawkAndAwe.combat.cc.Cyclone = {id = 33786, name = GetSpellInfo(33786)}
SquawkAndAwe.combat.abilities = {}
SquawkAndAwe.combat.abilities.Innervate = {id = 29166, name = GetSpellInfo(29166)}
SquawkAndAwe.combat.abilities.Force = {id = 33831, name = GetSpellInfo(33831), dur = 30}
SquawkAndAwe.combat.abilities.Starfall = {id = 48505, name = GetSpellInfo(48505)}
SquawkAndAwe.combat.abilities.Typhoon = {id = 50516, name = GetSpellInfo(50516)}
SquawkAndAwe.combat.abilities.Barkskin = {id = 22812, name = GetSpellInfo(22812)}
SquawkAndAwe.combat.trinkets = {}
SquawkAndAwe.combat.trinkets.flare = {id = 64713, itemid = 45518, name = GetSpellInfo(64713), itemname = GetItemInfo(45518), color = {r=1, g=0.8, b=0.32, a=0.9}, cd = 45}
SquawkAndAwe.combat.trinkets.flame = {id = 64712, itemid = 45148, name = GetSpellInfo(64712), itemname = GetItemInfo(45148), color = {r=1, g=0.42, b=0, a=0.9}}
SquawkAndAwe.combat.trinkets.pandora = {id = 64741, itemid = 45490, name = GetSpellInfo(64741), itemname = GetItemInfo(45490), color = {r=0.13, g=1, b=0.35, a=0.9}, cd = 45}
SquawkAndAwe.combat.trinkets.fates = {id = 64707, itemid = 45466, name = GetSpellInfo(64707), itemname = GetItemInfo(45466), color = {r=0.16, g=1, b=0.69, a=0.9}}
SquawkAndAwe.combat.trinkets.focus = {id = 65004, itemid = 45866, name = GetSpellInfo(65004), itemname = GetItemInfo(45866), color = {r=0.46, g=0.38, b=1, a=0.9}, cd = 45}
SquawkAndAwe.combat.trinkets.siphon = {id = 65008, itemid = 45292, name = GetSpellInfo(65008), itemname = GetItemInfo(45292), color = {r=0.5, g=0, b=1, a=0.9}}
SquawkAndAwe.combat.trinkets.broodmother = {id = 65006, itemid = 45308, name = GetSpellInfo(65006), itemname = GetItemInfo(45308), color = {r=0, g=1, b=0.3, a=0.9}, cd = 0}
SquawkAndAwe.combat.trinkets.dying = {id = 60494, itemid = 40255, name = GetSpellInfo(60494), itemname = GetItemInfo(40255), color = {r=0, g=0.37, b=0.12, a=0.9}, cd = 45}
SquawkAndAwe.combat.trinkets.illustration = {id = 60486, itemid = 40432, name = GetSpellInfo(60486), itemname = GetItemInfo(40432), color = {r=0.75, g=0.30, b=0.65, a=0.9}, cd = 0}
SquawkAndAwe.combat.trinkets.spider = {id = 60492, itemid = 39229, name = GetSpellInfo(60492), itemname = GetItemInfo(39229), color = {r=0.62, g=0.27, b=0.18, a=0.9}, cd = 45}
SquawkAndAwe.combat.trinkets.sundial = {id = 60064, itemid = 40682, name = GetSpellInfo(60064), itemname = GetItemInfo(40682), color = {r=0.16, g=0.93, b=0.91, a=0.9}, cd = 45}
SquawkAndAwe.combat.trinkets.serpent = {id = 56184, itemid = 42395, name = GetSpellInfo(56184), itemname = GetItemInfo(42395), color = {r=0.2, g=0.02, b=0.48, a=0.9}}
SquawkAndAwe.combat.trinkets.ember = {id = 60479, itemid = 37660, name = GetSpellInfo(60479), itemname = GetItemInfo(37660), color = {r=1, g=0.04, b=0.09, a=0.9}, cd = 45}
SquawkAndAwe.combat.trinkets.prisoner = {id = 60480, itemid = 37873, name = GetSpellInfo(60480), itemname = GetItemInfo(37873), color = {r=0.51, g=0.47, b=0.50, a=0.9}}
SquawkAndAwe.combat.trinkets.winged = {id = 60521, itemid = 37844, name = GetSpellInfo(60521), itemname = GetItemInfo(37844), color = {r=1, g=0.35, b=0.73, a=0.9}}
SquawkAndAwe.combat.trinkets.tome = {id = 60471, itemid = 36972, name = GetSpellInfo(60471), itemname = GetItemInfo(36972), color = {r=0.84, g=0.6, b=0.15, a=0.9}}
SquawkAndAwe.combat.Moonglade = {id = 18960, name = GetSpellInfo(18960)}
SquawkAndAwe.combat.Starfire = {id = 2912, name = GetSpellInfo(2912)}
SquawkAndAwe.combat.Wrath = {id = 5176, name = GetSpellInfo(5176)}
SquawkAndAwe.combat.FeralFF = {id = 16857, name = GetSpellInfo(16857)}

SquawkAndAwe.actives = {}
SquawkAndAwe.actives.trinkets = {}
SquawkAndAwe.actives.procs = {}
SquawkAndAwe.actives.cc = {}
SquawkAndAwe.actives.debuffs = {}
SquawkAndAwe.actives.abilities = {}
SquawkAndAwe.ActiveEclipseBuff = false

SquawkAndAwe.activeTrinketNames = {}
SquawkAndAwe.activeTrinketNames.Trinket1 = "flare"
SquawkAndAwe.activeTrinketNames.Trinket2 = "flame"

SquawkAndAwe.times = {}

SquawkAndAwe.barFrames = {}
local barFrameIndex = 0
SquawkAndAwe.statusBars = {}
local statusbarIndex = 0

local playerName = UnitName("player");
local LastMF = 0
local SFCombos = 0
local EclipseType = ""


-------------------
-- Config details
-------------------

local defaults = {
char = {
-- Settings
-- Frame
fWidth = 300,
barHeight = 25,
scale = 1,

-- Bars
bars = {
-- Maximum bar length in time
MaxLen = 30,

-- Trinkets
trinketshow = false,
mergetrinkets = true,
trinketcd = false,

-- Procs
procs = {
Eclipse = {
show = true,
color = {r=1, g=1, b=1, a=0.9},
wcolor = {r=0, g=1, b=0, a=0.9},
cd = true,
flash = true,
},
Omen = {
show = true,
color = {r=0.6, g=0.6, b=1, a=0.9},
flash = false,
},
T84P = {
show = true,
color = {r=0.43, g=0.61, b=1, a=0.9},
flash = true,
},
PVP = {
show = false,
color = {r=0.54, g=0.32, b=1, a=0.9},
flash = true,
},
},
cdcolor = {r=0.6, g=0.6, b=0.6, a=0.9},

-- Debuffs
debuffs = {
Moonfire = {
show = true,
color = {r=0.5, g=0, b=1, a=0.9},
tick = true,
},
Insect = {
show = true,
color = {r=0, g=1, b=0.3, a=0.9},
tick = true,
},
Faerie = {
show = true,
color = {r=1, g=0.5, b=1, a=0.9},
},
} ,
mergedebuffs = false,
tickcolor = {r=0.6, g=0.6, b=0.6, a=0.9},

-- CC
cc = {
Roots = {
show = true,
color = {r=0.38, g=0.2, b=0.08, a=0.9},
},
Hibernate = {
show = true,
color = {r=1, g=0.55, b=0.54, a=0.9},
},
Cyclone = {
show = true,
color = {r=0.25, g=0.25, b=0.25, a=0.9},
},
},
mergecc = true,

-- Abilities
abilities = {
Starfall = {
show = true,
color = {r=1, g=1, b=1, a=0.9},
dur = true,
},
Typhoon = {
show = true,
color = {r=0.5, g=0, b=1, a=0.9},
},
Force = {
show = true,
color = {r=0, g=1, b=0, a=0.9},
dur = true,
},
Innervate = {
show = true,
color = {r=0, g=0, b=1, a=0.9},
dur = true,
},
Barkskin = {
show = true,
color = {r=1, g=1, b=0, a=0.9},
dur = true,
},
},
mergeabilities = true,
GCD = {
show = true,
color = {r=0.6, g=0.6, b=0.6, a=0.6},
},
},

-- Media
texture = "BantoBar",
border = "None",
barborder = "None",
icons = true,
-- Text
barstext = true,
barfont = "Friz Quadrata TT",
barfontsize = 12,
spellnames = true,
durations = true,
eclipsetype = true,
sfcomboshow = true,

-- Main
debug = false,
barshow = true,

-- Incidentals
relativeTo = "UIParent",
relativePoint = "CENTER",
point = "CENTER",
xOffset = 0,
yOffset = 0,
--fHeight = 175,


-- unused so far
message = "Welcome Home!",
resetOn = true,

}
}

-----------------------------------------
-- Initialisation & Startup Routines
-----------------------------------------
-- Changed to hide uptime, stats, priority frames, kill options for now
function SquawkAndAwe:OnInitialize()
local AceConfigReg = LibStub("AceConfigRegistry-3.0")
local AceConfigDialog = LibStub("AceConfigDialog-3.0")

self.db = LibStub("AceDB-3.0"):New("SquawkAndAweDBPC", SquawkAndAwe.defaults, "char")
LibStub("AceConfig-3.0"):RegisterOptionsTable("SquawkAndAwe", self:GetOptions(), {"SquawkAndAwe", "saa"} )
media.RegisterCallback(self, "LibSharedMedia_Registered")

-- Add the options to blizzard frame (add them backwards so they show up in the proper order
self.optionsFrame = AceConfigDialog:AddToBlizOptions("SquawkAndAwe","SquawkAndAwe")
self.optionsFrame[L["About"]] = LibStub("LibAboutPanel").new("SquawkAndAwe", "SquawkAndAwe")
self.db:RegisterDefaults(defaults)
local version = GetAddOnMetadata("SquawkAndAwe","Version")
self.version = ("SquawkAndAwe v%s (r%s)"):format(version, REVISION)
self:Print(self.version.." Loaded.")
end

function SquawkAndAwe:OnDisable()
-- Called when the addon is disabled
end

-- Unregistered a couple events, should work
function SquawkAndAwe:OnEnable()
self:LibSharedMedia_Registered()
self:RegisterEvent("PLAYER_ENTERING_WORLD")
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
self:RegisterEvent("PLAYER_TARGET_CHANGED")
self:RegisterEvent("SPELL_UPDATE_COOLDOWN")
self:RegisterEvent("UNIT_AURA")
end

-- Should work without changes
function SquawkAndAwe:LibSharedMedia_Registered()
for k, v in pairs(media:List("statusbar")) do
self.textures[v] = v
end
for k, v in pairs(media:List("border")) do
self.borders[v] = v
end
for k, v in pairs(media:List("font")) do
self.fonts[v] = v
end
for k, v in pairs(media:List("sound")) do
self.sounds[v] = v
end
end

----------------------
-- Event Routines
----------------------
function SquawkAndAwe:PLAYER_ENTERING_WORLD()
self:SetBorderTexture(nil, self.db.char.border)
self:SetBarBorderTexture(nil, self.db.char.barborder)
self:RedrawFrames()
end

function SquawkAndAwe:UNIT_AURA(event,id)
if id == "player" and not SquawkAndAwe.ActiveEclipseBuff then
if UnitBuff("player",SquawkAndAwe.combat.procs.Eclipse.name) then
SquawkAndAwe.ActiveEclipseBuff = true
SquawkAndAwe:ProcBars("Eclipse", SquawkAndAwe.combat.procs.Eclipse)
elseif UnitBuff("player",SquawkAndAwe.combat.procs.Eclipsew.name) then
SquawkAndAwe.ActiveEclipseBuff = true
SquawkAndAwe:ProcBars("Eclipsew", SquawkAndAwe.combat.procs.Eclipsew)
end
end -- if id == "player"
end -- function SAA:UNIT_AURA()

function SquawkAndAwe:COMBAT_LOG_EVENT_UNFILTERED(_, timestamp, event, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, ...)
local k,v,_,icon,color
local spellID = select(1, ...)
local spellName = select(2,...)
if sourceGUID == UnitGUID("player") then
if event == "SPELL_AURA_APPLIED" then
-- Trinket handler
for k,v in pairs (SquawkAndAwe.combat.trinkets) do
if spellID == v.id then
if self.db.char.bars.trinketshow then
SquawkAndAwe:TrinketBars(k,v)
end -- if trinketshow
return
end -- if spellID == v.id
end -- for k,v in pairs(trinkets)

-- Proc handler
for k,v in pairs(SquawkAndAwe.combat.procs) do
if spellID == v.id then
SquawkAndAwe:ProcBars(k,v)
return
end -- if spellID == v.id
end -- for k,v in pairs(procs)

-- Debuff Handler
for k,v in pairs(SquawkAndAwe.combat.debuffs) do
if spellName == v.name then
if spellName == SquawkAndAwe.combat.debuffs.Moonfire.name then
SFCombos = 0
LastMF = 0
end
SquawkAndAwe:DebuffBars(k,v)
return
end -- if spellID == v.id
end -- for k,v in pairs(debuffs)

-- CC Handler
for k,v in pairs(SquawkAndAwe.combat.cc) do
if spellName == v.name then
SquawkAndAwe:CCBars(k)
return
end
end

-- Check for IS, MF ticks, reset bars
elseif event == "SPELL_PERIODIC_DAMAGE" and destName == UnitName("target")then
if spellID == SquawkAndAwe.combat.debuffs.Moonfire.id then
if self.db.char.bars.debuffs.Moonfire.tick then
SquawkAndAwe.times.MoonfireTick = GetTime() + SquawkAndAwe.combat.debuffs.Moonfire.tick
end
elseif spellID == SquawkAndAwe.combat.debuffs.Insect.id then
if self.db.char.bars.debuffs.Insect.tick then
SquawkAndAwe.times.InsectTick = GetTime() + SquawkAndAwe.combat.debuffs.Insect.tick
end
end
-- Check for spell casts for spells that generate them
elseif event == "SPELL_CAST_SUCCESS" then
-- Ability handler
for k,v in pairs(SquawkAndAwe.combat.abilities) do
if spellName == v.name then
SquawkAndAwe:AbilityBars(k,v)
return
end
end

-- Debuff Handler
for k,v in pairs(SquawkAndAwe.combat.debuffs) do
if spellName == v.name then
if spellName == SquawkAndAwe.combat.debuffs.Moonfire.name then
SFCombos = 0
LastMF = 0
end
SquawkAndAwe:DebuffBars(k,v)
return
end -- if spellID == v.id
end -- for k,v in pairs(debuffs)
end -- event == EVENT
-- Add handling for FF from any source
elseif (spellID == SquawkAndAwe.combat.debuffs.Faerie.id or spellID == SquawkAndAwe.combat.FeralFF.id) and destName == UnitName("target") and (event == "SPELL_CAST_SUCCESS" or event == "SPELL_AURA_APPLIED") then
--[[if self.db.char.bars.debuffs.Faerie.show then
SquawkAndAwe.actives.debuffs.Faerie = true
if self.db.char.bars.mergedebuffs then
self.frames["Debuffs"]:Show()
else
self.frames["Faerie"]:Show()
end
end--]]
SquawkAndAwe:DebuffBars("Faerie", SquawkAndAwe.combat.debuffs.Faerie)
end -- if sourceGUID == player
end

-- Triggers GCD bar
function SquawkAndAwe:SPELL_UPDATE_COOLDOWN()
if self.db.char.bars.GCD.show then
self:GCDBar()
end
end

-- Changing targets should refresh CC and Debuff bars
function SquawkAndAwe:PLAYER_TARGET_CHANGED()
SquawkAndAwe:TriggerDebuffs()
SquawkAndAwe:TriggerCC()
end

---------------------------
-- Buff Info functions
---------------------------

-- Generic spell getter
function SquawkAndAwe:GetSpellInfo(spellName, spelltype)
local index = 1
if spelltype == "buff" then
while UnitBuff("player", index) do
local name, _, _, _, _, _, expires = UnitBuff("player", index)
if name == spellName or (spellName == "Eclipse (Lunar)" and EclipseType == "Wrath" and name == "Eclipse (Solar)") then
return expires
end
index = index + 1
end
return 0
elseif spelltype == "debuff" or spelltype == "cc" then
while UnitDebuff("target", index) do
local name, _, _, _, _, _, expires, source = UnitDebuff("target", index)
if name == spellName and (source == "player" or spellName == self.combat.debuffs.Faerie.name or spellName == self.combat.FeralFF.name) then
return expires
end
index = index + 1
end
if spelltype == "cc" then
index = 1
while UnitDebuff("focus", index) do
local name, _, _, _, _, _, expires, source = UnitDebuff("focus", index)
if name == spellName and source == "player" then
return expires
end
index = index + 1
end
end
return 0
elseif spelltype == "cd" then
local start, duration, enable = GetSpellCooldown(spellName)
return start + duration
elseif spelltype == "item" then
local start, duration, enable = GetItemCooldown(spellName)
return start + duration
end
end

---------------------------
-- functions
---------------------------
-- Alias for CreateBaseFrame()
function SquawkAndAwe:RedrawFrames()
self:ClearActives()
self:HideAllBars()
self:SetBaseFrame()
end

-- Finds the number of bars which have been activated. Merged categories count
-- as one bar, no matter how many bars are active
function SquawkAndAwe:FindNumBars()
local num = 0
local add
local k,v

-- Add trinket bars
if self.db.char.bars.trinketshow and self.db.char.bars.mergetrinkets then
num = num + 1
elseif self.db.char.trinketshow then
num = num + 2
end

-- Add proc bars (checking for Eclipse CD bar, even if buff bar is disabled)
for k,v in pairs(self.db.char.bars.procs) do
if self.db.char.bars.procs[k].show or self.db.char.bars.procs[k].cd then
num = num + 1
end
end

-- Check for any debuff bars
add = 0
for k,v in pairs(self.db.char.bars.debuffs) do
if self.db.char.bars.debuffs[k].show then
add = add + 1
end
end
if self.db.char.bars.mergedebuffs and not add == 0 then
num = num + 1 -- If merged, only add one bar, and only of any are enabled
else
num = num + add -- If not, add as many as are enabled
end

-- Check for cc bars
add = 0
for k,v in pairs(self.db.char.bars.cc) do
if self.db.char.bars.cc[k].show then
add = add + 1
end
end
if self.db.char.bars.mergecc and not add == 0 then
num = num + 1
else
num = num + add
end

-- Check for ability bars
add = 0
for k,v in pairs(self.db.char.bars.abilities) do
if self.db.char.bars.abilities[k].show then
add = add + 1
end
end
if self.db.char.bars.mergeabilities and not add == 0 then
num = num + 1
else
num = num + add
end

-- Check for GCD bar
if self.db.char.bars.GCD.show then
num = num + 1
end
return num
end

-- Prints version number
function SquawkAndAwe:DisplayVersion()
self:Print(self.version)
end

-- Clear the actives listings
function SquawkAndAwe:ClearActives()
SquawkAndAwe.actives = {}
SquawkAndAwe.actives.trinkets = {}
SquawkAndAwe.actives.procs = {}
SquawkAndAwe.actives.cc = {}
SquawkAndAwe.actives.debuffs = {}
SquawkAndAwe.actives.abilities = {}
end

function SquawkAndAwe:HideAllBars()
for i,v in ipairs(SquawkAndAwe.barFrames) do
v:Hide()
end
end

-- Creates base frame, calls CreateBarFrames()
function SquawkAndAwe:SetBaseFrame()
-- Basic config
self.BaseFrame:SetScale(self.db.char.scale)
self.BaseFrame:SetFrameStrata("BACKGROUND")
local width
self.BaseFrame:SetWidth(self.db.char.fWidth + (self.db.char.icons and self.db.char.barHeight + 9 or 0))
self.BaseFrame:SetHeight((self.db.char.barHeight + 3) * self:FindNumBars() + 3)
self.BaseFrame:SetBackdrop(self.frameBackdrop)
self.BaseFrame:SetBackdropColor(1, 1, 1, 0)
self.BaseFrame:SetMovable(true)
self.BaseFrame:RegisterForDrag("LeftButton")
self.BaseFrame:SetPoint(self.db.char.point, self.db.char.relativeTo, self.db.char.relativePoint, self.db.char.xOffset, self.db.char.yOffset)

-- Set the start-drag script
self.BaseFrame:SetScript("OnDragStart",
function()
self.BaseFrame:StartMoving();
end );

-- Set the stop-drag script
self.BaseFrame:SetScript("OnDragStop",
function()
self.BaseFrame:StopMovingOrSizing();
self.BaseFrame:SetScript("OnUpdate", nil);
self:FinishedMoving(self.db.char, self.BaseFrame);
end );

-- Show the frame, reset the toggle
self.BaseFrame:Show()
self.db.char.barshow = false

-- Create the bar frames
self:CreateBarFrames()
end

-- Creates bar frames by iterating through categories and setting up each,
-- either merged or not
function SquawkAndAwe:CreateBarFrames()
-- Bar creation
local barCount = 0
local k,v
local layer
local add

-- Reset frames container
self.frames = {}
barFrameIndex = 0
statusbarIndex = 0

-- Trinket Bars
if self.db.char.bars.trinketshow then
if self.db.char.bars.mergetrinkets then
SquawkAndAwe:SetBarFrame("Trinkets", barCount)
SquawkAndAwe:AddStatusBar(self.frames["Trinkets"], "Trinket1", SquawkAndAwe.combat.trinkets.flare.color, 2)
SquawkAndAwe:AddStatusBar(self.frames["Trinkets"], "Trinket2", SquawkAndAwe.combat.trinkets.flame.color, 1)
barCount = barCount + 1
else
-- First trinket bar
SquawkAndAwe:SetBarFrame("Trinket1", barCount)
SquawkAndAwe:SetBarFrame("Trinket2", barCount + 1)
barCount = barCount + 2
if self.db.char.bars.trinketcd then
SquawkAndAwe:AddStatusBar(self.frames["Trinket1"], "Trinket1CD", self.db.char.bars.cdcolor, 1)
SquawkAndAwe:AddStatusBar(self.frames["Trinket1"], "Trinket1", SquawkAndAwe.combat.trinkets.flare.color, 2)
SquawkAndAwe:AddStatusBar(self.frames["Trinket2"], "Trinket2CD", self.db.char.bars.cdcolor, 1)
SquawkAndAwe:AddStatusBar(self.frames["Trinket2"], "Trinket2", SquawkAndAwe.combat.trinkets.flame.color, 2)
else
SquawkAndAwe:AddStatusBar(self.frames["Trinket1"], "Trinket1", SquawkAndAwe.combat.trinkets.flare.color, 1)
SquawkAndAwe:AddStatusBar(self.frames["Trinket2"], "Trinket2", SquawkAndAwe.combat.trinkets.flame.color, 1)
end
end
end

-- Proc bars
for k,v in pairs(self.db.char.bars.procs) do
if v.show or v.cd then
SquawkAndAwe:SetBarFrame(k, barCount, SquawkAndAwe.combat.procs[k].id)
if v.cd then
SquawkAndAwe:AddStatusBar(self.frames[k], k.."CD", self.db.char.bars.cdcolor, 1)
if v.show then
SquawkAndAwe:AddStatusBar(self.frames[k], k, v.color, 2)
end
else
SquawkAndAwe:AddStatusBar(self.frames[k], k, v.color, 1)
end
barCount = barCount + 1
end
end

-- Debuff bars
layer = 1
add = 0
if self.db.char.bars.mergedebuffs then
-- Make sure at least one is enabled
for k,v in pairs(self.db.char.bars.debuffs)do
if v.show then
add = add + 1
end
end
if add > 0 then
SquawkAndAwe:SetBarFrame("Debuffs", barCount)
for k,v in pairs(self.db.char.bars.debuffs) do
if v.show then
SquawkAndAwe:AddStatusBar(self.frames["Debuffs"], k, v.color, layer)
layer = layer + 1
end
end
barCount = barCount + 1
end
else
for k,v in pairs(self.db.char.bars.debuffs) do
if v.show then
SquawkAndAwe:SetBarFrame(k, barCount, SquawkAndAwe.combat.debuffs[k].id)
SquawkAndAwe:AddStatusBar(self.frames[k], k, v.color, 1)
if v.tick then
SquawkAndAwe:AddStatusBar(self.frames[k], k.."Tick", self.db.char.bars.tickcolor, 2, true, SquawkAndAwe.combat.debuffs[k].tick)
end
barCount = barCount + 1
end
end
end

-- CC bars
layer = 1
add = 0
if self.db.char.bars.mergecc then
-- Make sure at least one is enabled
for k,v in pairs(self.db.char.bars.cc)do
if v.show then
add = add + 1
end
end
if add > 0 then
SquawkAndAwe:SetBarFrame("CC", barCount)
for k,v in pairs(self.db.char.bars.cc) do
if v.show then
SquawkAndAwe:AddStatusBar(self.frames["CC"], k, v.color, layer)
layer = layer + 1
end
end
barCount = barCount + 1
end
else
for k,v in pairs(self.db.char.bars.cc) do
if v.show then
SquawkAndAwe:SetBarFrame(k, barCount, SquawkAndAwe.combat.cc[k].id)
SquawkAndAwe:AddStatusBar(self.frames[k], k, v.color, 1)
barCount = barCount + 1
end
end
end


-- Ability bars
layer = 1
add = 0
if self.db.char.bars.mergeabilities then
-- Make sure at least one is enabled
for k,v in pairs(self.db.char.bars.abilities)do
if v.show then
add = add + 1
end
end
if add > 0 then
SquawkAndAwe:SetBarFrame("Abilities", barCount)
for k,v in pairs(self.db.char.bars.abilities) do
if v.show then
SquawkAndAwe:AddStatusBar(self.frames.Abilities, k, v.color, layer)
layer = layer + 1
end
end
barCount = barCount + 1
end
else
for k,v in pairs(self.db.char.bars.abilities) do
if v.show then
SquawkAndAwe:SetBarFrame(k, barCount, SquawkAndAwe.combat.abilities[k].id)
if v.dur then
SquawkAndAwe:AddStatusBar(self.frames[k], k.."Dur", v.color, 2)
SquawkAndAwe:AddStatusBar(self.frames[k], k, self.db.char.bars.cdcolor, 1)
else
SquawkAndAwe:AddStatusBar(self.frames[k], k, v.color, 1)
end
barCount = barCount + 1
end
end
end

-- GCD Bar
if self.db.char.bars.GCD.show then
SquawkAndAwe:SetBarFrame("GCD", barCount)
SquawkAndAwe:AddStatusBar(self.frames["GCD"], "GCD", self.db.char.bars.GCD.color, 1)
end
end

-- Can't destroy frames, so we have to reuse them
function SquawkAndAwe:GetNextBarFrame()
barFrameIndex = barFrameIndex + 1

-- Grab a frame from storage
newFrame = SquawkAndAwe.barFrames[barFrameIndex]
if newFrame then
return newFrame
end

-- If it wasn't there, create a new one and put it in storage
newFrame = CreateFrame("Frame", "SAABarFrame"..barFrameIndex, SquawkAndAwe.BaseFrame)
SquawkAndAwe.barFrames[barFrameIndex] = newFrame
return newFrame
end

-- Sets up the bar frame, given its offset in number of bars from the top
function SquawkAndAwe:SetBarFrame(frameName, frameOffset, spellID)
local newFrame = SquawkAndAwe:GetNextBarFrame()

-- Set up the frame
newFrame:SetFrameStrata("LOW")
newFrame:SetWidth(self.db.char.fWidth)
newFrame:SetHeight(self.db.char.barHeight)
newFrame:ClearAllPoints()
newFrame:SetPoint("TOPRIGHT", self.BaseFrame, "TOPRIGHT", 0, frameOffset * self.db.char.barHeight * -1 - 3)
newFrame:SetBackdrop(self.barBackdrop);
newFrame:SetBackdropColor(0, 0, 0, 0.2);
newFrame:SetBackdropBorderColor( 1, 1, 1, 1);
newFrame:EnableMouse(false)

-- Set up the icon
local _, icon
-- Create frame
if not newFrame.icon then
newFrame.icon = CreateFrame("Frame", "SAA_"..frameName.."Icon", newFrame)
end

-- Sizing and placement
newFrame.icon:SetWidth(self.db.char.barHeight)
newFrame.icon:SetHeight(self.db.char.barHeight)
newFrame.icon:SetPoint("RIGHT", newFrame, "LEFT", -3, 0)

-- If we were given a spell, apply the icon
if spellID then
_, _, icon = GetSpellInfo(spellID)
newFrame.icon:SetBackdrop({bgFile = icon})
end
if self.db.char.icons then
newFrame.icon:Show()
else
newFrame.icon:Hide()
end

-- Set up the text
-- Create the text overlay
if not newFrame.text then
newFrame.text = newFrame:CreateFontString(nil,"OVERLAY")
end

-- Apply font
local barfont = media:Fetch("font", self.db.char.barfont)
newFrame.text:SetFont(barfont, self.db.char.barfontsize)
newFrame.text:SetTextColor(1, 1, 1, 1)

-- Place text overlay
newFrame.text:ClearAllPoints()
if self.db.char.icons then
newFrame.text:SetPoint("LEFT", newFrame.icon, "RIGHT", 9, 0)
else
newFrame.text:SetPoint("LEFT", newFrame, "LEFT", 6, 0)
end

-- Clear text
newFrame.text:SetText("")

-- Set update script
newFrame:SetScript("OnUpdate",
function()
OnUpdate();
end );

-- Hide the frame
newFrame:Hide()

-- Add it to frame array
self.frames[frameName] = newFrame
end

-- Can't destroy frames, so we have to reuse them
function SquawkAndAwe:GetNextStatusBar()
statusbarIndex = statusbarIndex + 1

-- Grab a frame from storage
newFrame = SquawkAndAwe.statusBars[statusbarIndex]
if newFrame then
return newFrame
end

-- If it wasn't there, create a new one and put it in storage
newFrame = CreateFrame("StatusBar", "SAA_Statusbar"..statusbarIndex, SquawkAndAwe.BaseFrame)
SquawkAndAwe.statusBars[statusbarIndex] = newFrame
return newFrame
end

-- Adds a status bar to a bar frame. If isTick is set, the bar is 1/3 height,
-- and max/min values are changed
function SquawkAndAwe:AddStatusBar(addToFrame, newFrameName, colors, frameLevel, isTick, tickDur)
statusbar = SquawkAndAwe:GetNextStatusBar()
statusbar:SetParent(addToFrame)

statusbar:SetFrameLevel(frameLevel)
statusbar:ClearAllPoints()
statusbar:SetHeight((self.db.char.barHeight - 6) / (isTick and 3 or 1))
statusbar:SetWidth(self.db.char.fWidth - 6)
statusbar:SetPoint("BOTTOMRIGHT", addToFrame, "BOTTOMRIGHT", -3, 3)
statusbar:SetStatusBarTexture(media:Fetch("statusbar", self.db.char.texture))
statusbar:SetStatusBarColor(colors.r, colors.g, colors.b, colors.a)
if isTick then
statusbar:SetMinMaxValues(0,tickDur)
statusbar:SetValue(tickDur / 2)
-- Special case for GCD bar
elseif newFrameName == "GCD" then
statusbar:SetMinMaxValues(0,1.5)
statusbar:SetValue(.75)
else
statusbar:SetMinMaxValues(0, self.db.char.bars.MaxLen)
statusbar:SetValue(15)
end

-- Add the spark
if not statusbar.spark then
statusbar.spark = statusbar:CreateTexture(nil, "OVERLAY")
end
statusbar.spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
statusbar.spark:SetWidth(16)
statusbar.spark:SetHeight(self.db.char.barHeight + 10)
statusbar.spark:SetBlendMode("ADD")
statusbar.spark:SetPoint("CENTER", statusbar, "LEFT",(self.db.char.fWidth - 6)* 15/self.db.char.bars.MaxLen, -1)

-- Hide it for ticks
if istick then
statusbar.spark:Show()
else
statusbar.spark:Hide()
end

addToFrame[newFrameName] = statusbar
end

-- Resets bars to center of screen
function SquawkAndAwe:ResetBars()
self.BaseFrame:ClearAllPoints()
self.db.char.point = defaults.char.point
self.db.char.relativeTo = defaults.char.relativeTo
self.db.char.relativePoint = defaults.char.relativePoint
self.db.char.xOffset = defaults.char.xOffset
self.db.char.yOffset = defaults.char.yOffset
self.db.char.fWidth = defaults.char.fWidth
self.db.char.barHeight = defaults.char.barHeight
self.db.char.scale = defaults.char.scale
self.db.char.barfont = defaults.char.barfont
self.db.char.barfontsize = defaults.char.barfontsize
self.db.char.bartexture = defaults.char.bartexture
self.db.char.texture = defaults.char.texture
barshow = true
self.BaseFrame:SetPoint(self.db.char.point, self.db.char.relativeTo, self.db.char.relativePoint, self.db.char.xOffset, self.db.char.yOffset)
self:RedrawFrames()
self.db.char.barshow = true -- so that call to ShowHideBars resets to false
self:ShowHideBars()
end

-- Handles activating Trinket bars
function SquawkAndAwe:TrinketBars(k, v)
-- Trinket 1 already active, move to 2
if SquawkAndAwe.actives.trinkets.Trinket1 then
SquawkAndAwe.actives.trinkets.Trinket2 = true
SquawkAndAwe.activeTrinketNames.Trinket2 = k
if v.cd and self.db.char.bars.trinketcd then
SquawkAndAwe.times.Trinket2CD = GetTime() + v.cd
end
if self.db.char.bars.mergetrinkets then
self.frames.Trinkets.Trinket2:SetStatusBarColor(v.color.r, v.color.g, v.color.b, v.color.a)
self.frames.Trinkets.Trinket2:Show()
-- Must set icon in OnUpdate(). Lowest duration trinket effect is not immutable
else
self.frames.Trinket2.Trinket2:SetStatusBarColor(v.color.r, v.color.g, v.color.b, v.color.a)
if self.db.char.icons then
_,_,icon = GetSpellInfo(v.id)
self.frames.Trinket2.icon:SetBackdrop({bgFile = icon})
end
self.frames.Trinket2:Show()
end
else
SquawkAndAwe.actives.trinkets.Trinket1 = true
SquawkAndAwe.activeTrinketNames.Trinket1 = k
if v.cd and self.db.char.bars.trinketcd then
SquawkAndAwe.times.Trinket1CD = GetTime() + v.cd
end
if self.db.char.bars.mergetrinkets then
self.frames.Trinkets.Trinket1:SetStatusBarColor(v.color.r, v.color.g, v.color.b, v.color.a)
self.frames.Trinkets:Show()
self.frames.Trinkets.Trinket2:Hide()
else
if self.db.char.bars.trinketcd then
SquawkAndAwe.actives.Trinket1CD = true
end
self.frames.Trinket1.Trinket1:SetStatusBarColor(v.color.r, v.color.g, v.color.b, v.color.a)
if self.db.char.icons then
_,_,icon = GetSpellInfo(v.id)
self.frames.Trinket1.icon:SetBackdrop({bgFile = icon})
end
self.frames.Trinket1:Show()
end -- if mergetrinkets
end -- if actives.Trinket1
end

-- Handles activating Proc bars
function SquawkAndAwe:ProcBars(k, v)
local color
-- Special handling for Wrath Eclipse
if k == "Eclipsew" then
if self.db.char.bars.procs.Eclipse.show or self.db.char.bars.procs.Eclipse.cd then
if self.db.char.bars.procs.Eclipse.show then
color = self.db.char.bars.procs.Eclipse.wcolor
self.frames.Eclipse.Eclipse:SetStatusBarColor(color.r, color.g, color.b, color.a)
SquawkAndAwe.actives.procs.Eclipse = true
end
SquawkAndAwe.times.EclipseCD = GetTime() + v.cd
if self.db.char.icons then
_,_,icon = GetSpellInfo(v.id)
self.frames.Eclipse.icon:SetBackdrop({bgFile = icon})
end
EclipseType = SquawkAndAwe.combat.Wrath.name
self.frames.Eclipse:Show()
end
elseif self.db.char.bars.procs[k].show or self.db.char.bars.procs[k].cd then
if v.id == SquawkAndAwe.combat.procs.Eclipse.id then
EclipseType = SquawkAndAwe.combat.Starfire.name
end
if self.db.char.bars.procs[k].show then
color = self.db.char.bars.procs[k].color
self.frames[k][k]:SetStatusBarColor(color.r, color.g, color.b, color.a)
SquawkAndAwe.actives.procs[k] = true
end
if v.cd then
SquawkAndAwe.times[k.."CD"] = GetTime() + v.cd
end
if self.db.char.bars.procs[k].cd then
SquawkAndAwe.actives[k.."CD"] = true
end
if self.db.char.icons then
_,_,icon = GetSpellInfo(v.id)
self.frames[k].icon:SetBackdrop({bgFile = icon})
end
self.frames[k]:Show()
end -- if spellID == Wrath else if show
end

-- Handles activating Debuff bars
function SquawkAndAwe:DebuffBars(k, v, notick)
if self.db.char.bars.debuffs[k].show then
SquawkAndAwe.actives.debuffs[k] = true
if self.db.char.bars.mergedebuffs then
self.frames.Debuffs:Show()
else
if self.db.char.bars.debuffs[k].tick and not notick then
SquawkAndAwe.times[k.."Tick"] = GetTime() + v.tick
SquawkAndAwe.actives[k.."Tick"] = true
end
self.frames[k]:Show()
end
end -- if v.show
end

function SquawkAndAwe:TriggerDebuffs()
for k,v in pairs(SquawkAndAwe.combat.debuffs) do
if SquawkAndAwe.db.char.bars.debuffs[k].show then
SquawkAndAwe:DebuffBars(k, v, true)
end
end
end

-- Handles activting CC bars
function SquawkAndAwe:CCBars(k)
if self.db.char.bars.cc[k].show then
SquawkAndAwe.actives.cc[k] = true
if self.db.char.bars.mergecc then
self.frames.CC:Show()
else
self.frames[k]:Show()
end
end
end

function SquawkAndAwe:TriggerCC()
for k,v in pairs(SquawkAndAwe.combat.cc) do
if SquawkAndAwe.db.char.bars.cc[k].show then
SquawkAndAwe:CCBars(k)
end
end
end

-- Handles activating Ability bars
function SquawkAndAwe:AbilityBars(k, v)
if self.db.char.bars.abilities[k].show then
SquawkAndAwe.actives.abilities[k] = true
if self.db.char.bars.mergeabilities then
self.frames.Abilities:Show()
else
if self.db.char.bars.abilities[k].dur then
if v.dur then
SquawkAndAwe.times[k.."Dur"] = GetTime() + v.dur
end
end
self.frames[k]:Show()
end
end
end

-- Handles activating the GCD bar
function SquawkAndAwe:GCDBar()
local startTime, duration, enabled = GetSpellCooldown(SquawkAndAwe.combat.Moonglade.name) -- TM chosen because it has no other cooldown and all druids will have it
if duration > 0 then
self.frames["GCD"]:Show()
SquawkAndAwe.actives.GCD = true
end
end

function SquawkAndAwe:DurationString(duration)
local string = (("%1.1f"):format(duration % 60)) .. "s";

if (duration >= 60) then
duration = floor(duration - (duration % 60)) / 60; -- minutes

string = (duration % 60) .."m " .. string;

if (duration >= 60) then
duration = (duration - (duration % 60)) / 60; -- hours
string = duration .. "h " .. string;
end
end
return string
end

-- Sorts two arrays by the values in one array. Nominally, sorts keys by
-- duration, descending. i.e. after sort, keys[0] will be the last to drop
function SquawkAndAwe:SortByDuration(keys, durs)
local i,v
local swap = true

while swap do
swap = false
for i,v in ipairs(durs) do
if durs[i + 1] and v < durs[i + 1] then
durs[i + 1], durs[i] = durs[i], durs[i + 1]
keys[i + 1], keys[i] = keys[i], keys[i + 1]
swap = true
end
end
end

return keys, durs
end

function OnUpdate()
local width = SquawkAndAwe.db.char.fWidth - 6
local sparkscale = width / SquawkAndAwe.db.char.bars.MaxLen
local timeLeft = 0
local namestring = ""
local durstring = ""
local k,v,i,_,icon
local sort = {}
local durs = {}

-- Handle Trinket updates
if SquawkAndAwe.db.char.bars.trinketshow then
if SquawkAndAwe.db.char.bars.mergetrinkets then
namestring = ""
durstring = ""
i = 1
if SquawkAndAwe.actives.trinkets.Trinket1 then
sort[i] = "Trinket1"
if SquawkAndAwe.db.char.bars.trinketcd then
if SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames.Trinket1].cd then
durs[i] = SquawkAndAwe.times.Trinket1CD - GetTime()
else
durs[i] = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames.Trinket1].itemname, "item") - GetTime()
end
else
durs[i] = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames.Trinket1].name, "buff") - GetTime()
end
if durs[i] < 0 then
SquawkAndAwe.actives.trinkets.Trinket1 = false
SquawkAndAwe.frames.Trinkets.Trinket1:Hide()
SquawkAndAwe.frames.Trinkets.Trinket1.spark:Hide()
else
i = i + 1
SquawkAndAwe.frames.Trinkets.Trinket1:Show()
SquawkAndAwe.frames.Trinkets.Trinket1.spark:Show()
end
end
if SquawkAndAwe.actives.trinkets.Trinket2 then
sort[i] = "Trinket2"
if SquawkAndAwe.db.char.bars.trinketcd then
if SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames.Trinket2].cd then
durs[i] = SquawkAndAwe.times.Trinket2CD - GetTime()
else
durs[i] = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames.Trinket2].itemname, "item") - GetTime()
end
else
durs[i] = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames.Trinket2].name, "buff") - GetTime()
end
if durs[i] < 0 then
SquawkAndAwe.actives.trinkets.Trinket2 = false
SquawkAndAwe.frames.Trinkets.Trinket2:Hide()
SquawkAndAwe.frames.Trinkets.Trinket2.spark:Hide()
else
i = i + 1
SquawkAndAwe.frames.Trinkets.Trinket2:Show()
SquawkAndAwe.frames.Trinkets.Trinket2.spark:Show()
end
end
if i > 1 then
sort, durs = SquawkAndAwe:SortByDuration(sort, durs)
if SquawkAndAwe.db.char.icons then
_,_,icon = GetSpellInfo(SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames[sort[i-1]]].id)
SquawkAndAwe.frames.Trinkets.icon:SetBackdrop({bgFile = icon})
SquawkAndAwe.frames.Trinkets.icon:Show()
end
if SquawkAndAwe.db.char.spellnames then
namestring = SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames[sort[i-1]]].itemname..(SquawkAndAwe.db.char.bars.trinketcd and " "..L["Cooldown"] or "")..(SquawkAndAwe.db.char.durations and ": " or "")
end
if SquawkAndAwe.db.char.durations then
durstring = SquawkAndAwe:DurationString(durs[i-1])
end
if SquawkAndAwe.db.char.barstext then
SquawkAndAwe.frames.Trinkets.text:SetText(namestring..durstring)
end
while i > 1 do
i = i - 1
k = sort[i]
SquawkAndAwe.frames.Trinkets[k]:SetFrameLevel(i)
timeLeft = math.min(durs[i], SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames.Trinkets[k]:SetValue(timeLeft)
SquawkAndAwe.frames.Trinkets[k].spark:SetPoint("CENTER", SquawkAndAwe.frames.Trinkets[k], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames.Trinkets[k].spark:Show()
end
elseif not SquawkAndAwe.db.char.barshow then
SquawkAndAwe.frames.Trinkets:Hide()
end
else
for k,v in pairs(SquawkAndAwe.actives.trinkets) do
namestring = ""
durstring = ""
if v then
if SquawkAndAwe.db.char.bars.trinketcd then
if SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames[k]].cd then
timeLeft = SquawkAndAwe.times[k.."CD"] - GetTime()
else
timeLeft = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames[k]].itemname, "item") - GetTime()
end
if timeLeft < 0 then
SquawkAndAwe.actives.trinkets[k] = false
SquawkAndAwe.frames[k]:Hide()
SquawkAndAwe.frames[k].text:SetText("")
else
if SquawkAndAwe.db.char.spellnames then
namestring = SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames[k]].itemname.." "..L["Cooldown"]..(SquawkAndAwe.db.char.durations and ": " or "")
end
if SquawkAndAwe.db.char.durations then durstring = SquawkAndAwe:DurationString(timeLeft) end
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames[k][k.."CD"]:SetValue(timeLeft)
SquawkAndAwe.frames[k][k.."CD"].spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k.."CD"], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames[k][k.."CD"].spark:Show()
SquawkAndAwe.frames[k].text:SetText(namestring..durstring)
end
end
timeLeft = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames[k]].name, "buff") - GetTime()
if timeLeft > 0 then
if SquawkAndAwe.db.char.spellnames then
namestring = SquawkAndAwe.combat.trinkets[SquawkAndAwe.activeTrinketNames[k]].itemname..(SquawkAndAwe.db.char.durations and ": " or "")
end
if SquawkAndAwe.db.char.durations then durstring = SquawkAndAwe:DurationString(timeLeft) end
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames[k][k]:SetValue(timeLeft)
SquawkAndAwe.frames[k][k].spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames[k][k].spark:Show()
SquawkAndAwe.frames[k][k]:Show()
SquawkAndAwe.frames[k].text:SetText(namestring..durstring)
else
SquawkAndAwe.frames[k][k]:Hide()
if not SquawkAndAwe.db.char.bars.trinketcd then
SquawkAndAwe.actives.trinkets[k] = false
SquawkAndAwe.frames[k]:Hide()
SquawkAndAwe.frames[k].text:SetText("")
end
end
end
end -- for k,v in trinkets
end -- if mergetrinkets
end -- if trinketshow

-- Handle Proc updates
for k,v in pairs(SquawkAndAwe.actives.procs) do
namestring = ""
durstring = ""
if v and SquawkAndAwe.db.char.bars.procs[k].show then
if SquawkAndAwe.db.char.bars.procs[k].cd then
timeLeft = SquawkAndAwe.times[k.."CD"] - GetTime()
if timeLeft < 0 then
SquawkAndAwe.actives.procs[k] = false
SquawkAndAwe.frames[k]:Hide()
SquawkAndAwe.frames[k].text:SetText("")
else
if SquawkAndAwe.db.char.spellnames then
namestring = ((k=="Eclipse" and "Eclipse") or SquawkAndAwe.combat.procs[k].name)..((SquawkAndAwe.db.char.eclipsetype and k == "Eclipse") and " ("..EclipseType..")" or "").." "..L["Cooldown"]..(SquawkAndAwe.db.char.durations and ": " or "")
end
if SquawkAndAwe.db.char.durations then durstring = SquawkAndAwe:DurationString(timeLeft) end
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames[k][k.."CD"]:SetValue(timeLeft)
SquawkAndAwe.frames[k][k.."CD"].spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k.."CD"], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames[k][k.."CD"].spark:Show()
SquawkAndAwe.frames[k].text:SetText(namestring..durstring)
end
end
if SquawkAndAwe.db.char.bars.procs[k].show then
timeLeft = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.procs[k].name, "buff") - GetTime()
if timeLeft > 0 then
if SquawkAndAwe.db.char.spellnames then
namestring = ((k=="Eclipse" and "Eclipse") or SquawkAndAwe.combat.procs[k].name)..((SquawkAndAwe.db.char.eclipsetype and k == "Eclipse") and " ("..EclipseType..")" or "")..(SquawkAndAwe.db.char.durations and ": " or "")
end
if SquawkAndAwe.db.char.durations then durstring = SquawkAndAwe:DurationString(timeLeft) end
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames[k][k]:SetValue(timeLeft)
SquawkAndAwe.frames[k][k].spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames[k][k].spark:Show()
SquawkAndAwe.frames[k][k]:Show()
if SquawkAndAwe.db.char.bars.procs[k].flash then
UIFrameFlash(SquawkAndAwe.frames[k][k], 0.25, 0.25, 30, true, 0.25, 0.25)
end
SquawkAndAwe.frames[k].text:SetText(namestring..durstring)
else
if k == "Eclipse" then
if SquawkAndAwe.ActiveEclipseBuff then
SquawkAndAwe.ActiveEclipseBuff = false
UIFrameFlashRemoveFrame(SquawkAndAwe.frames.Eclipse.Eclipse)
SquawkAndAwe.frames.Eclipse.Eclipse:SetStatusBarColor(0.3, 0.3, 0.3, 0.9)
end
timeLeft = SquawkAndAwe.times.EclipseCD - GetTime() - 15
if timeLeft < 0 then
SquawkAndAwe.frames.Eclipse.Eclipse:Hide()
else
if SquawkAndAwe.db.char.spellnames then
namestring = "Eclipse ("..EclipseType..")"..(SquawkAndAwe.db.char.durations and ": " or "")
end
if SquawkAndAwe.db.char.durations then durstring = SquawkAndAwe:DurationString(timeLeft) end
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames.Eclipse.Eclipse:SetValue(timeLeft)
SquawkAndAwe.frames.Eclipse.Eclipse.spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k.."CD"], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames.Eclipse.Eclipse.spark:Show()
SquawkAndAwe.frames.Eclipse.text:SetText(namestring..durstring)
end
else
SquawkAndAwe.frames[k][k]:Hide()
UIFrameFlashRemoveFrame(SquawkAndAwe.frames[k][k])
if not SquawkAndAwe.db.char.bars.procs[k].cd then
SquawkAndAwe.actives.procs[k] = false
SquawkAndAwe.frames[k]:Hide()
SquawkAndAwe.frames[k].text:SetText("")
end
end
end
end
end
end

-- Handle Debuff updates
if SquawkAndAwe.db.char.bars.mergedebuffs then
namestring = ""
durstring = ""
i = 1
-- Find out how many are active
for k,v in pairs(SquawkAndAwe.db.char.bars.debuffs) do
if v.show and SquawkAndAwe.actives.debuffs[k] then
sort[i] = k
durs[i] = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.debuffs[k].name, "debuff") - GetTime()
if durs[i] < 0 then
SquawkAndAwe.actives.debuffs[k] = false
SquawkAndAwe.frames.Debuffs[k]:Hide()
SquawkAndAwe.frames.Debuffs[k].spark:Hide()
else
i = i + 1
SquawkAndAwe.frames.Debuffs[k]:Show()
SquawkAndAwe.frames.Debuffs[k].spark:Show()
end
elseif v.show and not SquawkAndAwe.db.char.barshow then
SquawkAndAwe.frames.Debuffs[k]:Hide()
SquawkAndAwe.frames.Debuffs[k].spark:Hide()
end
end
if i > 1 then
sort, durs = SquawkAndAwe:SortByDuration(sort, durs)
if SquawkAndAwe.db.char.icons then
_,_,icon = GetSpellInfo(SquawkAndAwe.combat.debuffs[sort[i-1]].id)
SquawkAndAwe.frames.Debuffs.icon:SetBackdrop({bgFile = icon})
SquawkAndAwe.frames.Debuffs.icon:Show()
end
if SquawkAndAwe.db.char.spellnames then
namestring = SquawkAndAwe.combat.debuffs[sort[i-1]].name..(SquawkAndAwe.db.char.durations and ": " or "")
end
if SquawkAndAwe.db.char.durations then
durstring = SquawkAndAwe:DurationString(durs[i-1])
end
if SquawkAndAwe.db.char.barstext then
SquawkAndAwe.frames.Debuffs.text:SetText(namestring..durstring)
end
while i > 1 do
i = i - 1
k = sort[i]
SquawkAndAwe.frames.Debuffs[k]:SetFrameLevel(i)
timeLeft = math.min(durs[i], SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames.Debuffs[k]:SetValue(timeLeft)
SquawkAndAwe.frames.Debuffs[k].spark:SetPoint("CENTER", SquawkAndAwe.frames.Debuffs[k], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames.Debuffs[k].spark:Show()
end
elseif ((not SquawkAndAwe.db.char.barshow) and SquawkAndAwe.frames.Debuffs) then
SquawkAndAwe.frames.Debuffs:Hide()
end
else
for k,v in pairs(SquawkAndAwe.actives.debuffs) do
namestring = ""
durstring = ""
if v then
timeLeft = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.debuffs[k].name, "debuff") - GetTime()
if (timeLeft < 0) then
SquawkAndAwe.actives.debuffs[k] = false
SquawkAndAwe.frames[k]:Hide()
SquawkAndAwe.frames[k].text:SetText("")
else
if SquawkAndAwe.db.char.spellnames then
namestring = SquawkAndAwe.combat.debuffs[k].name
if k == "Moonfire" and SquawkAndAwe.db.char.sfcomboshow then
-- We set LastMF to 0 when we activate the bar.
if ((not (LastMF == 0)) and timeLeft > LastMF) then
SFCombos = SFCombos + 1
end
LastMF = timeLeft
namestring = namestring.." ("..SFCombos..")"
end
if SquawkAndAwe.db.char.durations then namestring = namestring..": " end
end
if SquawkAndAwe.db.char.durations then durstring = SquawkAndAwe:DurationString(timeLeft) end
if SquawkAndAwe.db.char.barstext then SquawkAndAwe.frames[k].text:SetText(namestring..durstring)end
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames[k][k]:SetValue(timeLeft)
SquawkAndAwe.frames[k][k].spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames[k][k].spark:Show()
if SquawkAndAwe.db.char.bars.debuffs[k].tick then
timeLeft = SquawkAndAwe.times[k.."Tick"] - GetTime()
if timeLeft < 0 then
SquawkAndAwe.frames[k][k.."Tick"]:Hide()
else
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames[k][k.."Tick"]:Show()
SquawkAndAwe.frames[k][k.."Tick"]:SetValue(timeLeft)
SquawkAndAwe.frames[k][k.."Tick"].spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k.."Tick"], "LEFT", timeLeft * SquawkAndAwe.db.char.fWidth / 1.5 + 1, -1)
end
end
end
end
end
end

-- Handle CC updates
if SquawkAndAwe.db.char.bars.mergecc then
namestring = ""
durstring = ""
i = 1
-- Find out how many are active
for k,v in pairs(SquawkAndAwe.db.char.bars.cc) do
if v.show and SquawkAndAwe.actives.cc[k] then
sort[i] = k
durs[i] = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.cc[k].name, "cc") - GetTime()
if durs[i] < 0 then
SquawkAndAwe.actives.cc[k] = false
SquawkAndAwe.frames.CC[k]:Hide()
SquawkAndAwe.frames.CC[k].spark:Hide()
else
i = i + 1
SquawkAndAwe.frames.CC[k]:Show()
SquawkAndAwe.frames.CC[k].spark:Show()
end
elseif v.show and not SquawkAndAwe.db.char.barshow then
SquawkAndAwe.frames.CC[k]:Hide()
SquawkAndAwe.frames.CC[k].spark:Hide()
end
end
if i > 1 then
sort, durs = SquawkAndAwe:SortByDuration(sort, durs)
if SquawkAndAwe.db.char.icons then
_,_,icon = GetSpellInfo(SquawkAndAwe.combat.cc[sort[i-1] ].id)
SquawkAndAwe.frames.CC.icon:SetBackdrop({bgFile = icon})
SquawkAndAwe.frames.CC.icon:Show()
end
if SquawkAndAwe.db.char.spellnames then
namestring = SquawkAndAwe.combat.cc[sort[i-1] ].name..(SquawkAndAwe.db.char.durations and ": " or "")
end
if SquawkAndAwe.db.char.durations then
durstring = SquawkAndAwe:DurationString(durs[i-1])
end
if SquawkAndAwe.db.char.barstext then
SquawkAndAwe.frames.CC.text:SetText(namestring..durstring)
end
while i > 1 do
i = i - 1
k = sort[i]
SquawkAndAwe.frames.CC[k]:SetFrameLevel(i)
timeLeft = math.min(durs[i], SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames.CC[k]:SetValue(timeLeft)
SquawkAndAwe.frames.CC[k].spark:SetPoint("CENTER", SquawkAndAwe.frames.CC[k], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames.CC[k].spark:Show()
end
elseif ((not SquawkAndAwe.db.char.barshow) and SquawkAndAwe.frames.CC) then
SquawkAndAwe.frames.CC:Hide()
end
else
for k,v in pairs(SquawkAndAwe.actives.cc) do
namestring = ""
durstring = ""
if v then
timeLeft = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.cc[k].name, "cc") - GetTime()
if (timeLeft < 0) then
SquawkAndAwe.actives.cc[k] = false
SquawkAndAwe.frames[k]:Hide()
SquawkAndAwe.frames[k].text:SetText("")
else
if SquawkAndAwe.db.char.spellnames then
namestring = SquawkAndAwe.combat.cc[k].name
if SquawkAndAwe.db.char.durations then namestring = namestring..": " end
end
if SquawkAndAwe.db.char.durations then durstring = SquawkAndAwe:DurationString(timeLeft) end
if SquawkAndAwe.db.char.barstext then SquawkAndAwe.frames[k].text:SetText(namestring..durstring)end
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames[k][k]:SetValue(timeLeft)
SquawkAndAwe.frames[k][k].spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames[k][k].spark:Show()
end
end
end
end

-- Handle Ability updates
if SquawkAndAwe.db.char.bars.mergeabilities then
namestring = ""
durstring = ""
i = 1
-- Find out how many are active
for k,v in pairs(SquawkAndAwe.db.char.bars.abilities) do
if v.show and SquawkAndAwe.actives.abilities[k] then
sort[i] = k
durs[i] = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.abilities[k].name, "cd") - GetTime()
if durs[i] < 0 then
SquawkAndAwe.actives.abilities[k] = false
SquawkAndAwe.frames.Abilities[k]:Hide()
SquawkAndAwe.frames.Abilities[k].spark:Hide()
else
i = i + 1
SquawkAndAwe.frames.Abilities[k]:Show()
SquawkAndAwe.frames.Abilities[k].spark:Show()
end
elseif v.show and not SquawkAndAwe.db.char.barshow then
SquawkAndAwe.frames.Abilities[k]:Hide()
SquawkAndAwe.frames.Abilities[k].spark:Hide()
end
end
if i > 1 then
sort, durs = SquawkAndAwe:SortByDuration(sort, durs)
if SquawkAndAwe.db.char.icons then
_,_,icon = GetSpellInfo(SquawkAndAwe.combat.abilities[sort[i-1]].id)
SquawkAndAwe.frames.Abilities.icon:SetBackdrop({bgFile = icon})
SquawkAndAwe.frames.Abilities.icon:Show()
end
if SquawkAndAwe.db.char.spellnames then
namestring = SquawkAndAwe.combat.abilities[sort[i-1]].name..(SquawkAndAwe.db.char.durations and ": " or "")
end
if SquawkAndAwe.db.char.durations then
durstring = SquawkAndAwe:DurationString(durs[i-1])
end
if SquawkAndAwe.db.char.barstext then
SquawkAndAwe.frames.Abilities.text:SetText(namestring..durstring)
end
while i > 1 do
i = i - 1
k = sort[i]
SquawkAndAwe.frames.Abilities[k]:SetFrameLevel(i)
timeLeft = math.min(durs[i], SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames.Abilities[k]:SetValue(timeLeft)
SquawkAndAwe.frames.Abilities[k].spark:SetPoint("CENTER", SquawkAndAwe.frames.Abilities[k], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames.Abilities[k].spark:Show()
end
elseif ((not SquawkAndAwe.db.char.barshow) and SquawkAndAwe.frames.Abilities) then
SquawkAndAwe.frames.Abilities:Hide()
end
else
for k,v in pairs(SquawkAndAwe.actives.abilities) do
namestring = ""
durstring = ""
if v then
timeLeft = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.abilities[k].name, "cd") - GetTime()
if (timeLeft < 0) then
SquawkAndAwe.actives.abilities[k] = false
SquawkAndAwe.frames[k]:Hide()
SquawkAndAwe.frames[k].text:SetText("")
else
if SquawkAndAwe.db.char.spellnames then
namestring = SquawkAndAwe.combat.abilities[k].name.." "..L["Cooldown"]
if SquawkAndAwe.db.char.durations then namestring = namestring..": " end
end
if SquawkAndAwe.db.char.durations then durstring = SquawkAndAwe:DurationString(timeLeft) end
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames[k][k]:SetValue(timeLeft)
SquawkAndAwe.frames[k][k].spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames[k][k].spark:Show()
if SquawkAndAwe.db.char.bars.abilities[k].dur then
if SquawkAndAwe.combat.abilities[k].dur then
timeLeft = SquawkAndAwe.times[k.."Dur"] - GetTime()
else
timeLeft = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.abilities[k].name, "buff") - GetTime()
end
if SquawkAndAwe.db.char.spellnames and timeLeft > 0 then
namestring = SquawkAndAwe.combat.abilities[k].name
if SquawkAndAwe.db.char.durations then namestring = namestring..": " end
end
if timeLeft < 0 then
SquawkAndAwe.frames[k][k.."Dur"]:Hide()
else
if SquawkAndAwe.db.char.durations then durstring = SquawkAndAwe:DurationString(timeLeft) end
timeLeft = math.min(timeLeft, SquawkAndAwe.db.char.bars.MaxLen)
SquawkAndAwe.frames[k][k.."Dur"]:Show()
SquawkAndAwe.frames[k][k.."Dur"]:SetValue(timeLeft)
SquawkAndAwe.frames[k][k.."Dur"].spark:SetPoint("CENTER", SquawkAndAwe.frames[k][k.."Dur"], "LEFT", timeLeft * sparkscale, 0)
SquawkAndAwe.frames[k][k.."Dur"].spark:Show()
end
end
if SquawkAndAwe.db.char.barstext then SquawkAndAwe.frames[k].text:SetText(namestring..durstring)end
end
end
end
end

-- Handle GCD updates
if SquawkAndAwe.actives.GCD then
timeLeft = SquawkAndAwe:GetSpellInfo(SquawkAndAwe.combat.Moonglade.name, "cd") - GetTime()
if timeLeft < 0 then
SquawkAndAwe.actives.GCD = false
SquawkAndAwe.frames.GCD:Hide()
else
SquawkAndAwe.frames.GCD.GCD:SetValue(timeLeft)
SquawkAndAwe.frames.GCD.GCD.spark:SetPoint("CENTER",SquawkAndAwe.frames.GCD.GCD,"LEFT", timeLeft * width / 1.5, 0)
SquawkAndAwe.frames.GCD.GCD.spark:Show()
end
end
end