BabySeal |
by Ailae of Emeriss-EU |
|
Warns if you enter combat without an active |
Seal (Paladins)/Shout (Warriors)/Armor buff (Warlocks). |
Also warns if the buff expires while in combat, with |
an option to have an advance warning. |
]] |
|
local class, pguid, db |
local isBuffPlayer = false |
local addon, BabySeal = ... |
BabySeal.prefix = string.format("|cff00aaff%s|r", addon) |
BabySeal.wp = "|cffff0000Warning!|r" |
|
local BabySeal = CreateFrame("Frame", nil, UIParent) |
BabySeal:RegisterEvent("PLAYER_ENTERING_WORLD") |
local LSM = LibStub("LibSharedMedia-3.0") |
LSM:Register("sound", "RaidWarning", "Sound\\Interface\\RaidWarning.ogg") |
|
BabySeal:SetScript("OnEvent", function(self, event, ...) |
self[event](self, ...) |
end) |
|
local spells = {} |
local spellIDs = { |
["PALADIN"] = { |
31801, -- Seal of Truth |
20164, -- Seal of Justice |
20165, -- Seal of Insight |
20154, -- Seal of Righteousness |
}, |
["WARRIOR"] = { |
6673, -- Battle Shout |
8076, -- Strength of Earth (exclusive with BS) |
57330, -- Horn of Winter (exclusive with BS) |
93435, -- Roar of Courage (exclusive with BS) |
469, -- Commanding Shout |
21562, -- Power Word: Fortitude (exclusive with CS) |
90364, -- Qiraji Fortitude (exclusive with CS) |
}, |
["WARLOCK"] = { |
687, -- Demon Armor |
28176, -- Fel Armor |
}, |
["DEATHKNIGHT"] = { |
57330, -- Horn of Winter |
6673, -- Battle Shout (exclusive with HoW) |
8076, -- Strength of Earth (exclusive with HoW) |
93435, -- Roar of Courage (exclusive with HoW) |
}, |
["PRIEST"] = { |
588, -- Inner Fire |
15286, -- Vampiric Embrace |
}, |
["SHAMAN"] = { |
324, -- Lightning Shield |
52127, -- Water Shield |
}, |
} |
|
local messages = {} |
local msgs = { |
["PALADIN"] = { |
["combat"] = "No active seal.", |
["expired"] = "Seal expired.", |
["notify"] = "Seal expires soon.", |
}, |
["WARRIOR"] = { |
["combat"] = "No active shout.", |
["expired"] = "Shout expired.", |
["notify"] = "Shout expires soon.", |
}, |
["WARLOCK"] = { |
["combat"] = "No active armor buff.", |
["expired"] = "Armor buff expired.", |
["notify"] = "Armor buff expires soon.", |
}, |
["DEATHKNIGHT"] = { |
["combat"] = "No active horn.", |
["expired"] = "Horn expired.", |
["notify"] = "Horn expires soon.", |
}, |
["PRIEST"] = { |
["combat"] = "Missing armor buff.", |
["expired"] = "Armor buff expired.", |
["notify"] = "Armor buff expires soon.", |
}, |
["SHAMAN"] = { |
["combat"] = "Missing shield.", |
["expired"] = "Shield expired.", |
["notify"] = "Shield expires soon.", |
}, |
} |
|
local prefix = "|cff00aaffBabySeal:|r |cffff0000Warning!|r" |
|
-- output message |
function BabySeal:Complain(message) |
if BabySeal.db.rWframe then |
RaidNotice_AddMessage(RaidWarningFrame, message, ChatTypeInfo["RAID_WARNING"]) |
else |
print(prefix, message) |
end |
function BabySeal:PLAYER_LOGIN() |
BabySealDB = BabySealDB or { |
prewarning = true, |
raidwarning = false, |
sound = false, |
soundFile = "RaidWarning", |
} |
db = BabySealDB |
|
if BabySeal.db.playSound then |
PlaySound("RaidWarning") |
local class = select(2, UnitClass("player")) |
|
self.spells, self.messages = self:GetData(class) |
|
if self.spells then |
self:RegisterEvent("PLAYER_REGEN_DISABLED") |
self:RegisterEvent("PLAYER_REGEN_ENABLED") |
|
local timer = self.frame:CreateAnimationGroup() |
timer:SetLooping("REPEAT") |
|
local animation = timer:CreateAnimation() |
animation:SetDuration(1) |
animation:SetMaxFramerate(1) |
|
self.complained = 0 |
|
local buff, expires |
timer:SetScript("OnLoop", function(t, requested) |
buff, expires, duration = self:Inspect() |
if not buff and self.playerBuff then |
self.playerBuff = false |
self:Complain(self.messages.expired) |
end |
|
if db.prewarning then |
if expires and expires - GetTime() <= 5 and GetTime() - self.complained > 10 and self.playerBuff then |
self.complained = GetTime() |
self:Complain(self.messages.notify) |
end |
end |
end) |
self.timer = timer |
SLASH_BabySeal1 = "/babyseal" |
SLASH_BabySeal2 = "/bs" |
SlashCmdList.BabySeal = function() |
InterfaceOptionsFrame_OpenToCategory(self.panel) |
end |
end |
end |
|
-- store spells with correct locale (should work at least) |
function BabySeal:StoreSpells() |
local name |
for k, v in ipairs(spellIDs[class]) do |
name, _, _, _, _, _, _, _, _ = GetSpellInfo(v) |
if not spells[name] and name then |
spells[name] = true |
end |
function BabySeal:Complain(s) |
if db.raidwarning then |
RaidNotice_AddMessage(RaidWarningFrame, s, ChatTypeInfo["RAID_WARNING"]) |
else |
print(self.wp, s) |
end |
BabySealSpells = spells -- for debug purposes |
|
if db.sound then |
PlaySoundFile(LSM:Fetch("sound", db.soundFile)) |
end |
end |
|
-- scan if there is a seal active |
function BabySeal:ScanSpells() |
local spell, caster |
for k, v in pairs(spells) do |
spell, _, _, _, _, _, _, caster, _, _, _ = UnitAura("player", k) |
function BabySeal:Inspect() |
for k,v in pairs(self.spells) do |
local name, rank, icon, count, dispelType, duration, expires, caster, isStealable = UnitBuff("player", v) |
|
-- if we found an active seal and player cast it, bail out |
if spell and caster == "player" then |
isBuffPlayer = true |
return spell |
else |
-- if the player is a Warrior or DK and the spell exists but was not cast |
-- by the player, an equivalent is active. |
if spell and (class == "WARRIOR" or class == "DEATHKNIGHT") and not caster == "player" then |
isBuffPlayer = false |
return spell |
if name then |
if caster == "player" then |
self.playerBuff = true |
return true, expires |
else |
-- equivalent buff is active, but is not mine |
self.playerBuff = false |
return true, expires |
end |
end |
end |
|
return nil -- if we get to this point, there was no seal active |
return false |
end |
|
function BabySeal:PLAYER_ENTERING_WORLD() |
class = select(2, UnitClass("player")) |
pguid = UnitGUID("player") |
if spellIDs[class] then |
-- check that SavedVars exists, otherwise create 'em |
if not BabySealSV then |
BabySealSV = { |
playSound = false, |
rWframe = false, |
notify = true, |
} |
end |
|
messages = msgs[class] |
BabySeal.db = BabySealSV |
|
self:StoreSpells() |
self:RegisterEvent("PLAYER_REGEN_DISABLED") |
self:RegisterEvent("PLAYER_REGEN_ENABLED") |
self:RegisterEvent("SPELLS_CHANGED") |
self:UnregisterEvent("PLAYER_ENTERING_WORLD") |
end |
end |
|
local expires = 0 |
function BabySeal:ActivateNotify(spell) |
expires = select(7, UnitAura("player", spell)) |
self:SetScript("OnUpdate", BabySeal_OnUpdate) |
end |
|
local timer = 0 |
function BabySeal_OnUpdate(self, elapsed) |
timer = timer + elapsed |
if timer < 1 then return end |
|
timer = 0 |
|
if expires - GetTime() <= 5 then |
self:Complain(messages["notify"]) |
self:SetScript("OnUpdate", nil) |
end |
end |
|
-- Warn if entering combat without buff |
function BabySeal:PLAYER_REGEN_DISABLED() |
local activeSpell = BabySeal:ScanSpells() |
if not activeSpell then |
self:Complain(messages["combat"]) |
elseif BabySeal.db.notify then |
self:ActivateNotify(activeSpell) |
if not self:Inspect() then |
self:Complain(self.messages.combat) |
end |
|
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") |
self.timer:Play() |
end |
|
function BabySeal:PLAYER_REGEN_ENABLED() |
self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED") |
self:SetScript("OnUpdate", nil) -- nil this, no need to check if it's expiring when it doesn't matter |
self.timer:Stop() |
end |
|
-- CLEU-event instead of UNIT_AURA, since the idea was for it to only announce once that the seal faded |
function BabySeal:COMBAT_LOG_EVENT_UNFILTERED(timestamp, event, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellID, spellName, spellSchool, auraType, ...) |
if destGUID ~= pguid or auraType ~= "BUFF" or not spells[spellName] then return end |
|
|
if event == "SPELL_AURA_REMOVED" then |
if isBuffPlayer and not self:ScanSpells() then |
self:Complain(messages["expired"]) |
end |
elseif BabySeal.db.notify and isBuffPlayer and (event == "SPELL_AURA_APPLIED" or combatEvent == "SPELL_AURA_REFRESH") then |
self:ActivateNotify(spellName) |
end |
end |
BabySeal.frame = CreateFrame("Frame", nil, UIParent) |
BabySeal.frame:SetScript("OnEvent", function(self, event, ...) return BabySeal[event] and BabySeal[event](BabySeal, ...) end) |
|
function BabySeal:SPELLS_CHANGED() |
self:StoreSpells() |
end |
function BabySeal:RegisterEvent(event) return self.frame:RegisterEvent(event) end |
function BabySeal:UnregisterEvent(event) return self.frame:UnregisterEvent(event) end |
|
-- slash'n'hack? no? |
SlashCmdList["BabySeal"] = function() InterfaceOptionsFrame_OpenToCategory("BabySeal") end |
SLASH_BabySeal1 = "/babyseal" |
SLASH_BabySeal2 = "/bs" |