Nenue@1: -- User: Krakyn Nenue@1: -- Created: 12/8/2015 7:30 PM Nenue@1: local T = LibStub("AceAddon-3.0"):GetAddon("Turok") Nenue@1: local TL = 'Spirit' Nenue@1: local print = function(...) _G.print(TL, ...) end Nenue@1: local LSM = LibStub("LibSharedMedia-3.0") Nenue@1: local mod = T:NewModule("Spirit", "AceTimer-3.0") Nenue@1: local time = _G.ct Nenue@1: local auras = { Nenue@1: 168811, -- sniper training Nenue@1: 168809, -- sniper training: recently moved Nenue@1: 13159, -- aspect of the pack, Nenue@1: 187615, -- Maalus Nenue@1: } Nenue@1: local spells = { Nenue@1: 3045, -- rapid fire, Nenue@1: 26297, -- berserking, Nenue@1: 121818, -- stampede, Nenue@1: Nenue@1: } Nenue@1: local FRAME_PREFIX = 'TkSpirit' Nenue@1: local FADE_TIME = 0.5 Nenue@1: -- local repetitive tasks Nenue@1: local function FindSpirit(id) Nenue@1: local db = T.db Nenue@1: local c = db.spirit Nenue@1: local isIcon = false Nenue@1: if db.spirit.progressbar[id] then Nenue@1: c = db.spirit.progressbar[id] Nenue@1: elseif db.spirit.icon[id] then Nenue@1: c = db.spirit.icon[id] Nenue@1: isIcon = true Nenue@1: end Nenue@1: local name, rank, icon, castingTime, minRange, maxRange, spellID = GetSpellInfo(id) Nenue@1: local s = { Nenue@1: name = name, Nenue@1: rank = rank, Nenue@1: icon = icon, Nenue@1: castingTime = castingTime, Nenue@1: minRange = minRange, Nenue@1: maxRange = maxRange, Nenue@1: spellID = spellID Nenue@1: } Nenue@1: Nenue@1: return s, c, isIcon Nenue@1: end Nenue@1: Nenue@1: function mod:OnEnable() Nenue@1: local db = _G.TurokData Nenue@1: self.aura_watch = {} Nenue@1: self.cooldown_watch = {} Nenue@1: self.item_watch = {} Nenue@1: self.myGUID = UnitGUID('player') Nenue@1: Nenue@1: Nenue@1: db.spirit = { Nenue@1: foreground_color = {1, 1, 1, 0.7}, Nenue@1: foreground_texture = 'Cilo', Nenue@1: foreground_blend = 'BLEND', Nenue@1: foreground_inset = -1, Nenue@1: background_color = {0, 0, 0, 0.7}, Nenue@1: background_blend = 'BLEND', Nenue@1: background_texture = 'Cilo', Nenue@1: icon_show = true, Nenue@1: width = 250, height = 20, Nenue@1: anchor = 'CENTER', parent = 'UIParent', anchorTo = 'CENTER', Nenue@1: posX = 0, posY = -150, Nenue@1: label_color = {1, 1, 1, 1}, Nenue@1: label_font = 'turok', Nenue@1: label_size = 14, Nenue@1: label_inset = -2, Nenue@1: label_point = 'LEFT', Nenue@1: label_outline = 'OUTLINE', Nenue@1: label_string = '%n %p', Nenue@1: label_strata = 'HIGH', Nenue@1: expire_sound = LSM:Fetch('sound'), Nenue@1: strata = 'LOW', Nenue@1: icon = { Nenue@1: [13159] = { -- Aspect of the Pack Nenue@1: posX = 20, posY = 20, width = 140, height = 140, Nenue@1: }, Nenue@1: [3045] = { Nenue@1: parent = 13159, anchor = 'RIGHT', anchorTo = 'LEFT', Nenue@1: posx = 0, posY = 0, width = 64, height = 64, Nenue@1: } Nenue@1: }, Nenue@1: progressbar = { Nenue@1: [168811] = { -- Sniper Training (duration) Nenue@1: background_color = {0,0,0,0}, Nenue@1: foreground_color = {1,0,0,1}, Nenue@1: anchor = 'BOTTOMLEFT', parent = 'TkFocusBar', anchorTo = 'TOPLEFT', Nenue@1: posX = 0, posY = 0, height = 16, width = 250, Nenue@1: label_string = '', Nenue@1: label_point = 'TOPLEFT', Nenue@1: strata = 'LOW', Nenue@1: attach = {{ Nenue@1: width_relative = 0.5, Nenue@1: height_relative = 1, Nenue@1: background_color = {1,0,0,1}, Nenue@1: foreground_color = {1,1,0.5, 1}, Nenue@1: background_blend = 'ADD', Nenue@1: foreground_blend = 'ADD', Nenue@1: Nenue@1: anchor = 'LEFT', Nenue@1: anchorTo = 'LEFT', Nenue@1: strata = 'MEDIUM', Nenue@1: }} Nenue@1: }, Nenue@1: [168809] = { -- Sniper Training: Recently Moved Nenue@1: background_color = {0,0,0,0 }, Nenue@1: foreground_color = {1,1,1,1}, Nenue@1: foreground_blend = 'ADD', Nenue@1: anchor = 'BOTTOMLEFT', parent = 'TkFocusBar', anchorTo = 'TOPLEFT', Nenue@1: strata = 'HIGH', Nenue@1: posX = 0, posY = 0, height = 16, width = 125, Nenue@1: icon_show = false, Nenue@1: label_string = '', Nenue@1: exceptions = { Nenue@1: function(aura) Nenue@1: return (mod.aura_watch[168811].expires < aura.expires) Nenue@1: end Nenue@1: }, Nenue@1: }, Nenue@1: }, Nenue@1: } Nenue@1: Nenue@1: for _, id in pairs(auras) do Nenue@1: -- store spellinfo fetch Nenue@1: self.aura_watch[id] = self:CreateSpiritFrame(id) Nenue@1: self.aura_watch[id].count = 0 Nenue@1: self.aura_watch[id].duration = 0 Nenue@1: self.aura_watch[id].expires = 0 Nenue@1: self.aura_watch[id].caster = 0 Nenue@1: print('AURA', id, self.aura_watch[id].name) Nenue@1: end Nenue@1: Nenue@1: for _, id in ipairs(spells) do Nenue@1: self.cooldown_watch[id] = self:CreateSpiritFrame(id) Nenue@1: print('COOLDOWN', id, self.cooldown_watch[id].name) Nenue@1: end Nenue@1: Nenue@1: self:SpiritScan() Nenue@1: self:RegisterEvent('UNIT_AURA') Nenue@1: self:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED') Nenue@1: self:RegisterEvent('PLAYER_REGEN_DISABLED') Nenue@1: self:RegisterEvent('PLAYER_REGEN_ENABLED') Nenue@1: end Nenue@1: Nenue@1: -- StatusBar factory Nenue@1: function mod:CreateSpiritFrame(id) Nenue@1: local s, c, isIcon = FindSpirit(id) Nenue@1: Nenue@1: -- how much frame do we need? Nenue@1: local f Nenue@1: if isIcon then Nenue@1: f = CreateFrame('Frame', FRAME_PREFIX..id, UIParent) Nenue@1: f.db = c Nenue@1: function f:Update() end Nenue@1: else Nenue@1: f = T:CreateBar('TkAuraBar'..id, c) Nenue@1: f.isTimer = true Nenue@1: if (c.label_string ~= '') then Nenue@1: print('has label, add it', id) Nenue@1: T:AddLabel(f, c) Nenue@1: end Nenue@1: end Nenue@1: f:Hide() Nenue@1: Nenue@1: -- general display Nenue@1: f:SetPoint(c.anchor, c.parent, c.anchorTo, c.posX, c.posY) Nenue@1: f:SetSize(c.width, c.height) Nenue@1: f:SetFrameStrata(c.strata) Nenue@1: Nenue@1: -- icon? Nenue@1: f.icon = s.icon Nenue@1: T:CreateStatusIcon(f) Nenue@1: Nenue@1: -- attachment frames? Nenue@1: if c.attach then Nenue@1: for i, e in ipairs(c.attach) do Nenue@1: local ef = CreateFrame('Frame', 'TkExtra'..id, f) Nenue@1: f[i] = ef Nenue@1: ef:SetPoint(e.anchor, f, e.anchorTo) Nenue@1: ef:SetSize(c.width * e.width_relative or e.width, c.height * e.height_relative or e.height) Nenue@1: ef:SetFrameStrata(e.strata or c.strata) Nenue@1: T:CreateStatusTextures(ef, e) Nenue@1: end Nenue@1: end Nenue@1: Nenue@1: -- setup suppression checking Nenue@1: if c.exceptions then Nenue@1: function s:ExceptionCheck () Nenue@1: for i, func in ipairs(c.exceptions) do Nenue@1: if not func(self) then Nenue@1: return false, i Nenue@1: end Nenue@1: end Nenue@1: return true Nenue@1: end Nenue@1: else Nenue@1: function s:ExceptionCheck () return true end Nenue@1: end Nenue@1: Nenue@1: -- access linkage Nenue@1: f.format = c.label_string Nenue@1: f.spirit = s Nenue@1: f.name = s.name Nenue@1: s.frame = f Nenue@1: return s Nenue@1: end Nenue@1: Nenue@1: function mod:UNIT_AURA(e, unit) Nenue@1: if unit == 'player' then Nenue@1: self:SpiritScan() Nenue@1: end Nenue@1: end Nenue@1: Nenue@1: -- Updates aura watches Nenue@1: function mod:SpiritScan() Nenue@1: local db = _G.TurokData Nenue@1: for id, aura in pairs(self.aura_watch) do Nenue@1: local c = aura.conf Nenue@1: local f = aura.frame Nenue@1: Nenue@1: local name, _, _, count, _, duration, expires, caster = UnitAura('player', aura.name) Nenue@1: Nenue@1: if name then Nenue@1: aura.duration = duration Nenue@1: aura.expires = expires Nenue@1: aura.caster = caster Nenue@1: aura.count = count Nenue@1: local test, i = aura:ExceptionCheck() Nenue@1: print(name, duration, expires) Nenue@1: if not test then Nenue@1: print('suppressing '..aura.name..' (failed test #'..i..')') Nenue@1: else Nenue@1: f.name = name Nenue@1: f:Update(nil, duration, expires) Nenue@1: f:Show() Nenue@1: end Nenue@1: end Nenue@1: end Nenue@1: end Nenue@1: Nenue@1: function mod:PLAYER_REGEN_ENABLED() Nenue@1: for id, aura in pairs(self.aura_watch) do Nenue@1: print('non-combat alpha for #', id, aura.name, 'is', aura.frame.db.alpha_ooc) Nenue@1: aura.frame.fadeTo = aura.frame.db.alpha_ooc Nenue@1: aura.frame.fadeDuration = FADE_TIME Nenue@1: end Nenue@1: end Nenue@1: Nenue@1: function mod:PLAYER_REGEN_DISABLED() Nenue@1: for id, aura in pairs(self.aura_watch) do Nenue@1: print('combat alpha for #', id, aura.name, 'is', aura.frame.db.alpha) Nenue@1: aura.frame.fadeTo = aura.frame.db.alpha Nenue@1: aura.frame.fadeDuration = FADE_TIME Nenue@1: end Nenue@1: end Nenue@1: Nenue@1: -- This is the most reliable way of catching item and spell uses, other events are delayed or too vague to be useful Nenue@1: function mod:COMBAT_LOG_EVENT_UNFILTERED(e, ...) Nenue@1: local timestamp, combatEvent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = Nenue@1: ...; -- Those arguments appear for all combat event variants. Nenue@1: local eventPrefix, eventSuffix = combatEvent:match("^(.-)_?([^_]*)$"); Nenue@1: if eventPrefix ~= 'SPELL_' or sourceGUID ~= self.myGUID then Nenue@1: return Nenue@1: end Nenue@1: Nenue@1: local spellid, name, count, type = select(13, select('#', ...), ...) Nenue@1: local kc = '' Nenue@1: for i=1,4 do Nenue@1: kc = kc .. string.format('%X',((string.byte(eventSuffix,i) % 8) + 8)) Nenue@1: end Nenue@1: print('|cFFFF'..kc..eventSuffix..'|r', sourceName, destName, spellid, name) Nenue@1: end