--[[ |
Blessed |
by Ailae of Emeriss-EU |
|
Credits to zork (of Roth UI) for texture. |
]] |
|
local ADDON, ns = ... |
local pguid |
local locked = true |
|
-- default position |
local defaults = { |
framePoint = "CENTER", |
xOfs = 0, |
yOfs = -150, |
} |
local db |
|
-- cosmetics |
local font = SystemFont_Shadow_Med1 |
local fontTimer = SystemFont_Shadow_Large |
local iconSize = 36 |
|
local Blessed = CreateFrame("Frame", "Blessed_Anchor", UIParent) |
Blessed:RegisterEvent("ADDON_LOADED") |
|
Blessed:SetScript("OnEvent", function(self, event, ...) |
self[event](self, ...) |
end) |
|
-- Add a prefix |
local function Print(output) |
print("|cff00aaffBlessed:|r " .. output) |
end |
|
-- Format: [spell] = (duration) |
local spells = { |
[1044] = 6, -- Hand of Freedom |
[1022] = 10, -- Hand of Protection |
[6940] = 12, -- Hand of Sacrifice |
[1038] = 10, -- Hand of Salvation |
[53563] = 300, -- Light's Beacon |
[54428] = 15, -- Divine Plea |
[53657] = 60, -- Judgement of the Pure (Rank 3, but who hasn't got 3/3 in this?) |
[87342] = 20, -- Holy Shield |
[84963] = 12, -- Inquisition |
[82327] = 10, -- Holy Radiance |
-- [88819] = 12, -- Daybreak |
[85433] = 15, -- Sacred Duty |
[94686] = 15, -- Crusader |
[54149] = 15, -- Infusion of Light |
} |
|
-- Empty tables for our frames |
local frames = {} |
local framePool = {} |
|
function Blessed:Init() |
self:SetBackdrop({ |
bgFile = [=[Interface\ChatFrame\ChatFrameBackground]=], |
insets = {top = 0, left = 0, bottom = 0, right = 0}, |
}) |
self:SetBackdropColor(1, 1, 1, 0) |
|
self:SetWidth(iconSize) |
self:SetHeight(iconSize) |
self:SetPoint(db.framePoint, db.xOfs, db.yOfs) |
|
self:SetMovable(true) |
|
-- yeh bebe, move it! |
self:SetScript("OnMouseDown", function() |
if(IsShiftKeyDown() and not locked) then |
self:ClearAllPoints() |
self:StartMoving() |
end |
end) |
|
self:SetScript("OnMouseUp", function() |
self:StopMovingOrSizing() |
db.framePoint, _, _, db.xOfs, db.yOfs = self:GetPoint() |
end) |
|
local text = self:CreateFontString(nil, "OVERLAY") |
text:SetFontObject(font) |
text:SetPoint("TOP", self, "TOP", 0, 16) |
text:SetTextColor(1, 0.82, 0) |
text:SetText("") |
self.header = text |
end |
|
function Blessed:ADDON_LOADED(name) |
if name ~= "Blessed" then return end |
self:UnregisterEvent("ADDON_LOADED") |
|
BlessedDB = BlessedDB or defaults |
db = BlessedDB |
|
local class = select(2, UnitClass("player")) |
if class == "PALADIN" then -- only do stuff if player is a paladin |
self:RegisterEvent("PLAYER_ENTERING_WORLD") |
self:Init() |
|
SLASH_Blessed1 = "/blessed" |
SlashCmdList.Blessed = function(input) |
local input = string.lower(input) |
if (input == "test") then |
self:SetupIcon(54428, "Test Icon", pguid, pguid) |
Print("Showing test-timer.") |
elseif (input == "lock") then |
if locked then |
self:EnableMouse(true) |
locked = false |
self.header:SetText("Blessed") |
self:SetBackdropColor(1, 1, 1, 0.25) |
Print("Unlocked. Press down SHIFT and drag the square to move.") |
else |
self:EnableMouse(false) |
locked = true |
self.header:SetText("") |
self:SetBackdropColor(1, 1, 1, 0) |
Print("Locked.") |
end |
elseif (input == "debug") then |
Print("Number of frames in the pool: " .. (#framePool or 0)) |
Print("Current durations:") |
for k, v in pairs(spells) do |
local name, _, _, _, _, _, _, _, _ = GetSpellInfo(k) |
if not name then Print("No value for key: " .. k) end |
Print(name .. ": " .. v) |
end |
else |
Print("Incorrect or no command given. Please use '/blessed test' (display a test-timer) or '/blessed lock' (to toggle lock).") |
end |
end |
else |
print("This addon has no use for any other class than a Paladin, you should consider disabling it for this character.") |
end |
end |
|
-- Only activate buff-tracking if the player is a paladin |
function Blessed:PLAYER_ENTERING_WORLD() |
self:UnregisterEvent("PLAYER_ENTERING_WORLD") |
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") |
|
pguid = UnitGUID("player") |
|
-- this is to make sure talents are loaded or if we need |
-- to delay the check |
if (GetNumTalentTabs() == 0) then |
self:RegisterEvent("PLAYER_ALIVE") |
else |
self:UpdateDurations() |
end |
|
self:RegisterEvent("CHARACTER_POINTS_CHANGED") |
self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED") |
end |
|
-- Talents are only available at this point when you're logging in |
-- so we need to update durations. |
function Blessed:PLAYER_ALIVE() |
self:UpdateDurations() |
self:UnregisterEvent("PLAYER_ALIVE") |
end |
|
-- Check talents for updates |
function Blessed:UpdateDurations() |
-- Hand of Freedom |
local _, _, _, _, rank, maxRank, _, _ = GetTalentInfo(3, 4) |
if rank == maxRank then |
spells[1044] = 10 |
else |
spells[1044] = 6 |
end |
end |
|
-- Perform checks for all these events |
Blessed.CHARACTER_POINTS_CHANGED = Blessed.UpdateDurations |
Blessed.ACTIVE_TALENT_GROUP_CHANGED = Blessed.UpdateDurations |
|
-- Handle stuff, plx |
function Blessed:COMBAT_LOG_EVENT_UNFILTERED(timestamp, combatEvent, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, ...) |
if sourceGUID and sourceGUID ~= pguid then return end |
|
if (combatEvent == "SPELL_AURA_REMOVED") then |
local spellID, _, _, _ = select(1, ...) |
if spells[spellID] then |
self:RemoveFrame(spellID .. sourceGUID .. destGUID) |
end |
elseif (combatEvent == "SPELL_AURA_APPLIED") then |
local spellID, spellName, _, _ = select(1, ...) |
if (spells[spellID]) then |
-- special handling for Inquisition, sigh |
if spellID == 84963 and spellName then |
local duration, expirationTime = select(6, UnitAura("player", spellName)) |
spells[84963] = duration |
end |
self:SetupIcon(spellID, destName, sourceGUID, destGUID) |
end |
elseif (combatEvent == "SPELL_AURA_REFRESH") then |
local spellID, spellName, _, _ = select(1, ...) |
if (spells[spellID]) then |
self:RemoveFrame(spellID .. sourceGUID .. destGUID) |
-- special handling for Inquisition, sigh |
if spellID == 84963 and spellName then |
local duration, expirationTime = select(6, UnitAura("player", spellName)) |
spells[84963] = duration |
end |
self:SetupIcon(spellID, destName, sourceGUID, destGUID) |
end |
end |
end |
|
-- Reanchor frames |
-- If it's frame #1, anchor it to anchorframe (teehee). If it's frame #n (!1) anchor it to the right of frame #n-1. |
function Blessed:UpdateFrames() |
if #frames == 0 then return end |
|
for i, frame in ipairs(frames) do |
frame:ClearAllPoints() |
if i > 1 then |
frame:SetPoint("LEFT", frames[i - 1], "RIGHT", 15, 0) |
else |
frame:SetPoint("CENTER", self, "CENTER") |
end |
end |
end |
|
-- Remove bar |
function Blessed:RemoveFrame(id) |
if #frames == 0 then return end |
|
for i, frame in pairs(frames) do |
if frame.id == id then |
frame:Hide() |
table.remove(frames, i) |
table.insert(framePool, frame) |
self:UpdateFrames() -- reanchor frames |
end |
end |
end |
|
-- Update barinfo |
local function update(self, elapsed) |
self.time = GetTime() |
if self.time - self.lastUpdate < 1 then return end |
|
self.duration = self.duration - (self.time - self.lastUpdate) |
self.lastUpdate = self.time |
self.timer:SetTextColor(1, 1, 1) |
if self.duration > 60 then |
self.timer:SetFormattedText("%.0fm", ceil(self.duration/60)) |
else |
self.timer:SetFormattedText("%.0f", floor(self.duration)) |
end |
|
|
if self.duration <= 0 then |
Blessed:RemoveFrame(self.id) |
elseif self.duration <= 5 then -- indicate that there is equalorless than 5 secs left |
self.timer:SetTextColor(1, 0, 0) |
end |
end |
|
-- Framemananger, return a new frame if there's no old frame available |
function Blessed:GetFrame() |
if (#framePool > 0) then |
return table.remove(framePool, 1) |
end |
|
local frame = CreateFrame("Frame", nil, UIParent) |
frame:SetHeight(iconSize) |
frame:SetWidth(iconSize) |
frame:SetPoint("CENTER", self) |
|
-- Icon |
frame.icon = frame:CreateTexture(nil, "ARTWORK") |
frame.icon:SetHeight(iconSize) |
frame.icon:SetWidth(iconSize) |
frame.icon:SetTexCoord(0.03, 0.97, 0.02, 0.97) |
frame.icon:SetAllPoints(frame) |
|
-- Targettext |
frame.target = frame:CreateFontString(nil, "OVERLAY") |
frame.target:SetFontObject(font) |
frame.target:SetPoint("BOTTOM", frame, "TOP", 0, 5) |
frame.target:SetTextColor(1, 1, 1) |
frame.target:SetShadowOffset(1, -1) |
|
-- Timertext |
frame.timer = frame:CreateFontString(nil, "OVERLAY") |
frame.timer:SetFontObject(fontTimer) |
frame.timer:SetPoint("TOP", frame, "BOTTOM", 0, -5) |
frame.timer:SetTextColor(1, 1, 1) |
frame.timer:SetShadowOffset(1, -1) |
|
-- Cooldown-model (beta) |
frame.cd = CreateFrame("Cooldown", nil, frame, "CooldownFrameTemplate") |
frame.cd:SetHeight(iconSize) |
frame.cd:SetWidth(iconSize) |
frame.cd:SetPoint("TOPLEFT", frame, "TOPLEFT", 2, -2) |
frame.cd:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 2) |
frame.cd.noCooldownCount = true -- prevent OmniCC if present |
|
-- Overlay |
frame.overlay = CreateFrame("Frame", nil, frame) |
frame.overlay:SetAllPoints(frame) |
frame.overlay:SetParent(frame) |
|
-- Border |
frame.border = frame.overlay:CreateTexture(nil, "OVERLAY") |
frame.border:SetParent(frame) |
frame.border:SetTexture('Interface\\AddOns\\Blessed\\simplesquare_roth') |
frame.border:SetPoint('TOPRIGHT', frame, 2, 2) |
frame.border:SetPoint('BOTTOMLEFT', frame, -2, -2) |
frame.border:SetVertexColor(0.3, 0.3, 0.3) |
|
return frame |
end |
|
-- Setup a timer |
local color = {} |
function Blessed:SetupIcon(spellID, targetName, sourceGUID, targetGUID) |
local frame = self:GetFrame() |
local duration = spells[spellID] |
local icon = select(3, GetSpellInfo(spellID)) |
|
targetName = string.sub(targetName, 0, 3) |
local class = select(2, GetPlayerInfoByGUID(targetGUID)) |
|
if targetGUID == pguid then |
targetName = "You!" |
class = "PALADIN" |
end |
|
frame.icon:SetTexture(icon) |
|
color = RAID_CLASS_COLORS[class] or { r = 1, g = 1, b =1 } |
frame.target:SetTextColor(color.r, color.g, color.b) |
frame.target:SetText(targetName or "Unknown") |
|
if duration > 60 then |
frame.timer:SetFormattedText("%.0fm", ceil(duration/60)) |
else |
frame.timer:SetFormattedText("%.0f", floor(duration)) |
end |
frame.timer:SetTextColor(1, 1, 1) |
|
-- Nifty stuff |
frame.duration = duration |
frame.id = spellID .. sourceGUID .. targetGUID |
frame.lastUpdate = GetTime() |
frame.cd:SetCooldown(GetTime(), duration) |
table.insert(frames, frame) |
|
frame:SetScript("OnUpdate", update) |
|
-- when a frame is shown, reanchor all the frames accordingly |
self:UpdateFrames() |
|
frame:Show() |
end |