Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --local DEBUG = true
- local EHN,ns = ...
- EventHorizon = ns
- local class = select(2,UnitClass('player'))
- local playername = UnitName('player')..' - '..GetRealmName('player')
- local Cataclysm = select(4,GetBuildInfo()) >= 40000
- local Mop = select(4,GetBuildInfo()) >= 50000
- ns.defaultDB = {
- point = {'CENTER', 'UIParent', 'CENTER'},
- isActive = true,
- version = 4,
- }
- ns.defaultDBG = {
- profiles = {
- default = {},
- },
- itemInfo = {},
- profilePerChar = {},
- defaultProfile = 'default',
- version = 4,
- }
- ns.db = {
- point = {'CENTER', 'UIParent', 'CENTER'},
- isActive = true,
- version = 4,
- }
- ns.frames = {
- config = {}, -- validated barframe config entries - format = ns.frames.config[i] = {barconfig}
- frames = {}, -- all loaded barframes
- active = {}, -- refs to barframes currently collecting information (matches talent spec)
- shown = {}, -- refs to barframes currently visible to the player (matches stance)
- mouseover = {}, -- refs to barframes requiring mouseover target information
- }
- ns.defaultconfig = {
- showTrinketBars = {
- default = true,
- boolean = true,
- name = 'Show Trinket Bars',
- desc = 'When enabled, displays trinkets in addition to spells and abilities.',
- },
- castLine = {
- default = true,
- boolean = true,
- number = true,
- name = 'End-of-Cast Line',
- desc = 'When enabled, adds a vertical line which marks the end of any spellcast in progress.',
- },
- gcdStyle = {
- default = 'line',
- valid = {'line','bar',false},
- name = 'Global Cooldown Style',
- desc = 'When set to Line, a vertical line will mark the end of the current GCD. \n When set to Bar, a textured bar is used instead. \n Can also be disabled to neither track or display the GCD.',
- },
- enableRedshift = {
- default = false,
- boolean = true,
- name = 'Enable Redshift',
- desc = 'An optional module which hides Axis untless certain conditions, such as combat or targeting, are met.',
- },
- Redshift = {
- name = 'Redshift States',
- desc = 'Conditions for the Redshift Module to show Axis.',
- sub = {
- showCombat = {
- default = true,
- boolean = true,
- name = 'Show in Combat',
- desc = 'When enabled, displays Axis when in combat.',
- },
- showHarm = {
- default = true,
- boolean = true,
- name = 'Show Harmful Units',
- desc = 'When enabled, displays Axis when an attackable unit is targeted.',
- },
- showHelp = {
- default = false,
- boolean = true,
- name = 'Show Helpful Units',
- desc = 'When enabled, displays Axis when a friendly unit is targeted.',
- },
- showBoss = {
- default = true,
- boolean = true,
- name = 'Show on Boss',
- desc = 'When enabled, displays Axis when a boss-level unit is targeted.',
- },
- showFocus = {
- default = false,
- boolean = true,
- name = 'Show on Focus',
- desc = 'When enabled, displays Axis when you have a focus target.'
- },
- hideVehicle = {
- default = true,
- boolean = true,
- name = 'Hide in Vehicle',
- desc = 'When enabled, HIDES Axis when using a vehicle with its own actionbar.',
- },
- hideVitals = {
- default = true,
- boolean = true,
- name = 'Hide Vitals',
- desc = 'When enabled, the Vitals display is hidden whenever Axis is hidden.',
- },
- },
- },
- -- Pulse = 0.5,
- -- PulseIntensity = 0.5,
- -- PulseFPS = 30,
- Lines = {
- default = false,
- boolean = true,
- table = true,
- name = 'Static Lines',
- desc = 'When enabled, enables the Lines Module.',
- },
- LinesColor = {
- default = {1,1,1,0.5},
- table = true,
- name = 'Static Line Colors',
- desc = 'The color of any static lines being displayed by the Lines Axis Module.'
- },
- anchor = {
- default = {"TOPRIGHT", "EventHorizonHandle", "BOTTOMRIGHT"},
- table = true,
- name = 'Anchor Position',
- desc = "Axis' Handle Information",
- },
- width = {
- default = 150,
- number = true,
- name = 'Bar Width',
- desc = 'Set the width of shown bars. Icons add to the actual width of the window.'
- },
- height = {
- default = 18,
- number = true,
- name = 'Bar Height',
- desc = 'Set the height of each individual bar. Also sets the width of icons.',
- },
- spacing = {
- default = 0,
- number = true,
- name = 'Bar Spacing',
- desc = 'Set the spacing between each shown bar.',
- },
- staticheight = {
- default = false,
- number = true,
- boolean = true,
- name = 'Static Height',
- desc = 'When set, Axis will resize its bars to fit this height. \n When disabled, Axis will grow or shrink depending on the number of shown bars.'
- },
- hideIcons = {
- default = false,
- boolean = true,
- name = 'Hide Bar Icons',
- desc = 'When enabled, Icons are not shown, however stack-text is still shown.',
- },
- past = {
- default = -3,
- number = true,
- name = 'Past Time',
- desc = 'How many seconds in the past for Axis to display.',
- },
- future = {
- default = 12,
- number = true,
- name = 'Future Time',
- desc = 'How many seconds in the future for Axis to display.'
- },
- texturedbars = {
- default = true,
- boolean = true,
- name = 'Textured Bars',
- desc = 'When enabled, Axis displays textured bars according to the Bar Texture option. \n When disabled, Axis displays the bars as a solid color.',
- },
- bartexture = {
- default = "Interface\\Addons\\EventHorizon\\Smooth",
- string = true,
- name = 'Bar Texture',
- desc = 'Set the texture to use for each bar.',
- },
- texturealphamultiplier = {
- default = 2,
- number = true,
- name = 'Texture Alpha-Multiplier',
- desc = 'This option directly influences the opacity of textured bars to account for varying degrees of visibility.'
- },
- backdrop = {
- default = true,
- boolean = true,
- name = 'Show Backdrop',
- desc = 'When enabled, Axis displays the backdrop.',
- },
- padding = {
- default = 3,
- number = true,
- name = 'Backdrop Padding',
- desc = 'Set the padding between the backdrop and bar edges.'
- },
- bg = {
- default = "Interface\\ChatFrame\\ChatFrameBackground",
- string = true,
- name = 'Backdrop Texture',
- desc = 'Set the texture to use for the backdrop.',
- },
- border = {
- default = "Interface\\Tooltips\\UI-Tooltip-Border",
- string = true,
- name = 'Backdrop Border Texture',
- desc = 'Set the texture to use for the backdrop border.',
- },
- edgesize = {
- default = 8,
- number = true,
- name = 'Backdrop Edge Size',
- desc = 'Set the thickness of the backdrop border.',
- },
- inset = {
- default = {top = 2, bottom = 2, left = 2, right = 2},
- table = true,
- name = 'Backdrop Insets',
- desc = 'Trim the backdrop texture to account for its border.',
- },
- stackFont = {
- default = false,
- boolean = true,
- string = true,
- name = 'Stack Text Font',
- desc = 'Sets the font of the stack text shown on bar icons.',
- },
- stackFontSize = {
- default = false,
- boolean = true,
- number = true,
- name = 'Stack Text Size',
- desc = 'Set the size of the stack text shown on bar icons.',
- },
- stackFontOutline = {
- default = false,
- valid = {'OUTLINE','THICKOUTLINE','MONOCHROME',false},
- name = 'Stack Text Outline',
- desc = 'Set the outline of the stack text shown on bar icons.',
- },
- stackFontColor = {
- default = false,
- table = true,
- name = 'Stack Text Color',
- desc = 'Sets the color of the stack text shown on bar icons.',
- },
- stackFontShadow = {
- default = false,
- table = true,
- boolean = true,
- name = 'Stack Text Shadow',
- desc = 'Apply a shadow effect to the stack text shown on bar icons. \n This option adjusts the shadow color and can be left at default for black.',
- },
- stackFontShadowOffset = {
- default = false,
- table = true,
- boolean = true,
- name = 'Stack Text Shadow Offset',
- desc = 'Set the offset of the stack text shadow.',
- },
- stackOnRight = {
- default = false,
- boolean = true,
- name = 'Stack Text on Right',
- desc = 'When enabled the stack text is displayed on the right-hand side of the bars. \n When disabled, stack text is shown on the left side, as default.',
- },
- }
- ns.defaultcolors = {
- sent = {true,class == 'PRIEST' and 0.7 or 1,1},
- tick = {true,class == 'PRIEST' and 0.7 or 1,1},
- casting = {0,1,0.2,0.25},
- castLine = {0,1,0.2,0.3},
- cooldown = {0.6,0.8,1,0.3},
- debuffmine = {true,class == 'PRIEST' and 0.7 or 1,0.3},
- debuff = {true,0.5,0.3},
- playerbuff = {true,class == 'PRIEST' and 0.7 or 1,0.3},
- nowLine = {1,1,1,0.3},
- bgcolor = {0,0,0,0.6},
- bordercolor = {1,1,1,1},
- gcdColor = {1,1,1,0.5},
- }
- ns.defaultlayouts = {
- tick = {
- top = 0,
- bottom = 0.2,
- },
- smalldebuff = {
- top = 0.2,
- bottom = 0.35,
- },
- cantcast = {
- top = 0.35,
- bottom = 1,
- },
- default = {
- top = 0.2,
- bottom = 1,
- },
- }
- ns.config = {Redshift = {}, blendModes = {}}
- ns.layouts = {}
- ns.colors = {}
- ns.glyphs = {} -- currently active glyph storage. format = ns.glyphs[i] = glyphID
- ns.otherIDs = {} -- combatlog events either not directly tied to bars, or using spells other than bar.spellID
- ns.modules = {} -- storage for loaded modules - format = module = ns.modules[string.lower(moduleName)] = {namespace}
- ns.vars = { -- storage for widely used vars/math/etc - format = ns.vars[var] = val
- config = {},
- onepixelwide = 1,
- visibleFrame = true,
- numframes = 0,
- buff = {},
- debuff = {},
- }
- local vars = ns.vars
- local UnitDebuff = UnitDebuff
- local UnitBuff = UnitBuff
- local SpellFrame = {}
- local EventHorizonFrame = CreateFrame('Frame','EventHorizonFrame',UIParent)
- local mainframe = CreateFrame('Frame',nil,EventHorizonFrame)
- local frame = CreateFrame('Frame')
- local frame2 = CreateFrame('Frame')
- local frame3 = CreateFrame('Frame')
- ns.mainframe = mainframe
- -- Frames to be created on demand
- local handle
- local function printhelp(...) if select('#',...)>0 then return tostring((select(1,...))), printhelp(select(2,...)) end end
- local function debug(...)
- print(...)
- end
- local function print(...)
- ChatFrame1:AddMessage('EventHorizon: '..strjoin(',',printhelp(...)))
- end
- local draworder = {
- default = -8,
- cooldown = -7,
- debuff = -6,
- playerbuff = -5,
- debuffmine = -4,
- casting = -3,
- sent = -2,
- tick = -1,
- channeltick = 0,
- now = 1,
- gcd = 2,
- nowI = 7,
- }
- local auraids = {
- tick = true,
- cantcast = true,
- debuff = true,
- playerbuff = true,
- debuffmine = true,
- }
- local customColors = {
- debuff = true,
- debuffmine = true,
- playerbuff = true,
- }
- local exemptColors = {
- default = true,
- sent = true,
- tick = true,
- channeltick = true,
- castLine = true,
- nowLine = true,
- bgcolor = true,
- bordercolor = true,
- gcdColor = true,
- }
- local equipSlots = {
- ["ChestSlot"] = 5,
- ["FeetSlot"] = 8,
- ["Finger0Slot"] = 11,
- ["Finger1Slot"] = 12,
- ["HandsSlot"] = 10,
- ["HeadSlot"] = 1,
- ["LegsSlot"] = 7,
- ["MainHandSlot"] = 16,
- ["NeckSlot"] = 2,
- ["RangedSlot"] = 18,
- ["SecondaryHandSlot"] = 17,
- ["ShirtSlot"] = 4,
- ["ShoulderSlot"] = 3,
- ["TabardSlot"] = 19,
- ["Trinket0Slot"] = 13,
- ["Trinket1Slot"] = 14,
- ["WaistSlot"] = 6,
- ["WristSlot"] = 9,
- }
- local mainframeEvents = {
- ['COMBAT_LOG_EVENT_UNFILTERED'] = true,
- ['PLAYER_TALENT_UPDATE'] = true,
- ['UPDATE_SHAPESHIFT_FORM'] = true,
- ['UPDATE_SHAPESHIFT_FORMS'] = true,
- ['SPELL_UPDATE_COOLDOWN'] = true,
- ['PLAYER_LEVEL_UP'] = true,
- ['PLAYER_TARGET_CHANGED'] = true,
- ['UNIT_AURA'] = true,
- }
- local reloadEvents = {
- ['GLYPH_ADDED'] = true,
- ['GLYPH_ENABLED'] = true,
- ['GLYPH_REMOVED'] = true,
- ['GLYPH_UPDATED'] = true,
- ['GLYPH_DISABLED'] = true,
- ['PLAYER_REGEN_DISABLED'] = true,
- ['PLAYER_REGEN_ENABLED'] = true,
- ['ZONE_CHANGED_NEW_AREA'] = true,
- ['ZONE_CHANGED_INDOORS'] = true,
- ['LFG_LOCK_INFO_RECEIVED'] = true,
- }
- local tickevents = {
- ['SPELL_PERIODIC_DAMAGE'] = true,
- ['SPELL_PERIODIC_HEAL'] = true,
- ['SPELL_PERIODIC_ENERGIZE'] = true,
- ['SPELL_PERIODIC_DRAIN'] = true,
- ['SPELL_PERIODIC_LEACH'] = true,
- ['SPELL_DAMAGE'] = true,
- ['SPELL_HEAL'] = true,
- --['SPELL_AURA_APPLIED'] = true,
- }
- -- Dispatch event to method of the event's name.
- local EventHandler = function (self, event, ...)
- local f = self[event]
- if f then
- --if event ~= 'COMBAT_LOG_EVENT_UNFILTERED' then print(event) end
- f(self,...)
- if event ~= 'COMBAT_LOG_EVENT_UNFILTERED' then
- ns:ModuleEvent(event,...)
- end
- end
- end
- local Clone = function (t)
- local new = {}
- local i, v = next(t, nil) -- i is an index of t, v = t[i]
- while i do
- new[i] = v
- i, v = next(t, i)
- end
- return new
- end
- -- pairs(t) for metatable usage. Doesn't return numeric index unless value is keyless.
- function mpairs(t)
- local visited = {}
- local f
- f = function(_, k)
- if not t then
- return
- end
- while true do
- local k2, v2 = next(t, k)
- if k2 == nil then
- break
- end
- if not visited[k2] then
- visited[k2] = true
- return k2, v2
- end
- k = k2
- end
- local mt = getmetatable(t)
- if mt then
- local indextable = mt.__index
- if type(indextable) == "table" then
- t = indextable
- return f()
- end
- end
- t = nil
- end
- return f
- end
- -- Since Blizzard doesn't provide the ability to look up a slot name from a slotID...
- local GetSlotName = function (slot)
- for k,v in pairs(equipSlots) do
- if v == slot then return k end
- end
- end
- local mainframe_UNIT_AURA = function (self,unit)
- if vars.buff[unit] then
- table.wipe(vars.buff[unit])
- for i = 1,50 do
- local name, _, icon, count, _, duration, expirationTime, source, _, _, spellID = UnitBuff(unit,i)
- --print(name,icon,count,duration,expirationTime,source,spellID)
- if not (name and spellID) then break end
- table.insert(vars.buff[unit],{
- name = name,
- icon = icon,
- count = count,
- duration = duration,
- expirationTime = expirationTime,
- source = source,
- spellID = spellID,
- })
- end
- end
- if vars.debuff[unit] then
- table.wipe(vars.debuff[unit])
- for i = 1,100 do
- local name, _, icon, count, _, duration, expirationTime, source, _, _, spellID = UnitDebuff(unit,i)
- if not (name and spellID) then break end
- table.insert(vars.debuff[unit], {
- name = name,
- icon = icon,
- count = count,
- duration = duration,
- expirationTime = expirationTime,
- source = source,
- spellID = spellID,
- })
- end
- end
- for i,spellframe in pairs(ns.frames.frames) do
- if (spellframe.auraunit and spellframe.auraunit == unit) then
- spellframe:UNIT_AURA(unit)
- end
- end
- end
- local GetAura = function (self)
- local s = self.isType == 'playerbuff' and 'buff' or 'debuff'
- local a = vars[s][self.auraunit]
- if not a then return end
- if type(self.auraname) == 'table' then
- for k,aura in pairs(a) do
- for i = 1,#self.auraname do
- if (aura.name == self.auraname[i]) and (aura.source == 'player' or self.unique) and (not(self.uniqueID) or self.uniqueID == aura.spellID) then
- return aura.name, aura.icon, aura.count, aura.duration, aura.expirationTime, aura.source, aura.spellID
- end
- end
- end
- else
- for k,aura in pairs(a) do
- if (aura.name == self.auraname) and (aura.source == 'player' or self.unique) and (not(self.uniqueID) or self.uniqueID == aura.spellID) then
- return aura.name, aura.icon, aura.count, aura.duration, aura.expirationTime, aura.source, aura.spellID
- end
- end
- end
- end
- ns.GetAura = function (self,auralist,auratype,unit)
- if not auratype and unit then return error('Invalid arg in EventHorizon:GetAura(self,auralist,auratype,unit)') end
- local a = vars[auratype][unit]
- if not a then return end
- if type(auralist) == 'table' then
- for k,aura in pairs(a) do
- for i = 1,#auralist do
- local t = type(auralist[i])
- if (t == 'string' and aura.name or t == 'number' and aura.spellID) == auralist[i] then
- return aura.name, aura.icon, aura.count, aura.duration, aura.expirationTime, aura.source, aura.spellID
- end
- end
- end
- else
- for k,aura in pairs(a) do
- local t = type(auralist)
- if (t == 'string' and aura.name or t == 'number' and aura.spellID) == auralist then
- return aura.name, aura.icon, aura.count, aura.duration, aura.expirationTime, aura.source, aura.spellID
- end
- end
- end
- end
- -- SpellFrame - All spell bar frames inherit from this class.
- --Indicators represent a point or range of time. There are different types. The type determines the color and position.
- local typeparent = {}
- local SetStacks = function (self,count)
- if count>1 then
- self.stacks:SetFormattedText('%d',count)
- elseif self.glyphstacks then
- if self.glyphstacks[guid] and (self.glyphstacks[guid] > 0) then
- self.stacks:SetText(self.glyphstacks[guid])
- else
- self.stacks:SetText()
- end
- else
- self.stacks:SetText()
- end
- end
- local SpellFrame_NotInteresting = function (self, unitid, spellname)
- return unitid ~= 'player' or spellname ~= self.spellname
- end
- -- FindItemInfo:
- local SpellFrame_FindItemInfo = function (self,slotID)
- local itemID = self.itemID or GetInventoryItemID('player',slotID or self.slotID)
- if itemID then
- local dbI = EventHorizonDBG.itemInfo[itemID]
- if dbI and (dbI.name and dbI.tex) then
- return itemID,dbI.name,dbI.tex
- else
- local name,_,_,_,_,_,_,_,_,tex = GetItemInfo(itemID)
- if (name and tex) then
- EventHorizonDBG.itemInfo[itemID] = {name = name, tex = tex}
- return itemID,name,tex
- end
- end
- end
- end
- local SpellFrame_AddIndicator = function (self, typeid, layoutid, time, usetexture)
- local indicator
- local parent = typeparent[typeid]
- local ndtex, ndcol
- if usetexture and self.bartexture then ndtex = self.bartexture end
- if typeid and customColors[typeid] then
- if self.barcolorunique and typeid == 'debuff' then
- ndcol = self.barcolorunique
- elseif self.barcolor then
- ndcol = self.barcolor
- end
- end
- if not parent then
- --print'creating indicator parent'
- parent = {}
- parent.unused = {}
- typeparent[typeid] = parent
- --if DEBUG and typeid=='tick' then parent.numchildren=0 end--]]
- end
- if #parent.unused>0 then
- indicator = tremove(parent.unused)
- indicator:ClearAllPoints()
- indicator.time = nil
- indicator.start = nil
- indicator.stop = nil
- indicator.happened = nil
- --if DEBUG and typeid=='tick' then debug('reusing indicator',indicator.frameindex) end--]]
- else
- indicator = mainframe:CreateTexture(nil, 'ARTWORK', nil, draworder[typeid])
- indicator.parent = parent
- --if DEBUG and typeid=='tick' then parent.numchildren=parent.numchildren+1 indicator.frameindex=parent.numchildren debug('adding indicator',indicator.frameindex) end--]]
- end
- -- Layout
- local layouts = ns.layouts
- local layout = layouts[layoutid] or layouts.default
- local color = ndcol or ns.colors[typeid] or ns.colors.default
- if layoutid == 'frameline' then
- color = typeid == 'sent' and ns.colors.castLine or ns.colors[typeid]
- indicator:SetPoint('TOP',ns.mainframe)
- indicator:SetPoint('BOTTOM',ns.mainframe)
- else
- indicator:SetPoint('TOP',self, 'TOP', 0, -layout.top*vars.barheight)
- indicator:SetPoint('BOTTOM',self, 'TOP', 0, -layout.bottom*vars.barheight)
- end
- if usetexture then
- indicator:SetTexture(ndtex or vars.bartexture)
- indicator:SetTexCoord(unpack(layout.texcoords))
- else
- indicator:SetTexture(1,1,1,1)
- end
- indicator:SetVertexColor(unpack(ndcol or color))
- if ns.config.blendModes[typeid] and type(ns.config.blendModes[typeid]) == 'string' then
- indicator:SetBlendMode(ns.config.blendModes[typeid])
- end
- indicator:Hide()
- indicator:SetWidth(vars.onepixelwide)
- indicator.time = time
- indicator.typeid = typeid
- indicator.layoutid = layoutid
- if indicator then
- tinsert(self.indicators, indicator)
- end
- return indicator
- end
- local SpellFrame_AddSegment = function (self, typeid, layoutid, start, stop, start2)
- if stop<start then return end
- local indicator = self:AddIndicator(typeid, layoutid, start, vars.texturedbars)
- indicator.time = nil
- indicator.start = start
- indicator.stop = stop
- --debug(start,stop)
- return indicator
- end
- local SpellFrame_Remove = function (self,indicator)
- if type(indicator)=='number' then
- local index, indicator = indicator, self.indicators[indicator]
- indicator:Hide()
- --if DEBUG and indicator.typeid=='tick' then debug('deleting',indicator.frameindex) end--]]
- tinsert(indicator.parent.unused, tremove(self.indicators, index))
- else
- for index=1,#self.indicators do
- if self.indicators[index]==indicator then
- indicator:Hide()
- --if DEBUG and indicator.typeid=='tick' then debug('deleting',indicator.frameindex) end--]]
- tinsert(indicator.parent.unused, tremove(self.indicators,index))
- break
- end
- end
- end
- end
- local SpellFrame_OnUpdate = function (self,elapsed)
- local now = GetTime()
- local diff = now+vars.past
- -- spellframe.nexttick is used to schedule the creation of predicted ticks as soon as they scroll past now+future.
- local nexttick = self.nexttick
- if nexttick and nexttick <= now+vars.future then
- if nexttick<=self.lasttick then
- self:AddIndicator('tick', 'tick', nexttick)
- self.latesttick = nexttick
- self.nexttick = nexttick + (self.dotMod or self.dot)
- else
- self.nexttick = nil
- end
- end
- for k=#self.indicators,1,-1 do
- local indicator = self.indicators[k]
- local time = indicator.time
- if time then
- -- Example:
- -- [-------|------->--------]
- -- past now time future
- -- now=795, time=800, past=-3, then time is time-now-past after past.
- local p = (time-diff)*vars.scale
- local remove = p<0 or (time<=now and indicator.typeid=='tick' and not indicator.happened)
- if remove then
- indicator:Hide()
- --if DEBUG and indicator.typeid=='tick' then debug('deleting',indicator.frameindex) end--]]
- tinsert(indicator.parent.unused, tremove(self.indicators,k))
- elseif p<=1 then
- indicator:SetPoint('LEFT', self, 'LEFT', p*vars.barwidth, 0)
- indicator:Show()
- end
- else
- local start, stop = indicator.start, indicator.stop
- local p1 = (start-diff)*vars.scale
- local p2 = (stop-diff)*vars.scale
- if p2<0 then
- indicator:Hide()
- --if DEBUG and indicator.typeid=='tick' then debug('deleting',indicator.frameindex) end--]]
- tinsert(indicator.parent.unused, tremove(self.indicators,k))
- elseif 1<p1 then
- indicator:Hide()
- else
- indicator:Show()
- indicator:SetPoint('LEFT', self, 'LEFT', 0<=p1 and p1*vars.barwidth or 0, 0)
- indicator:SetPoint('RIGHT', self, 'LEFT', p2<=1 and p2*vars.barwidth+1 or vars.barwidth, 0)
- end
- end
- end
- end
- local SpellFrame_UNIT_SPELLCAST_SENT = function (self, unitid, spellname, spellrank, spelltarget)
- if ((self.cast and not(self.cast[spellname])) or (spellname ~= self.spellname)) or unitid ~= 'player' then return end
- local now = GetTime()
- self:AddIndicator('sent', 'default', now)
- end
- local Cast_Start = function (self, unitid, spellname, spellrank)
- if not(self.cast[spellname]) or unitid ~= 'player' then return end
- local _,_,_,_,startTime,endTime,_ = self.cast[spellname].func(unitid)
- if not(startTime and endTime) then return end
- startTime, endTime = startTime/1000, endTime/1000
- self.casting = self:AddSegment('casting', 'default', startTime, endTime)
- local name,_,icon = GetSpellInfo(self.cast[spellname].id)
- self.lastcast = name
- if not(self.keepIcon) then
- self.icon:SetTexture(icon)
- end
- if vars.castLine and (endTime - startTime > vars.castLine) then
- self.castLine = self:AddIndicator('sent', 'frameline', endTime)
- end
- local numhits = self.cast[spellname].numhits and self.cast[spellname].numhits ~= true and self.cast[spellname].numhits
- if numhits then
- local casttime = endTime - startTime
- local tick = casttime/numhits
- if numhits and numhits ~= true then
- for i=1,numhits do
- self:AddIndicator('channeltick', 'channeltick', startTime + i*tick)
- end
- end
- end
- end
- local Cast_Update = function (self, unitid, spellname, spellrank)
- --debug('UNIT_SPELLCAST_CHANNEL_UPDATE',unitid, spellname, spellrank)
- if not(self.cast[spellname]) or unitid ~= 'player' then return end
- local _,_,_,_,startTime,endTime,_ = self.cast[spellname].func(unitid)
- if not (startTime and endTime) then return end
- startTime, endTime = startTime/1000, endTime/1000
- if self.casting then
- self.casting.stop = endTime
- if vars.castLine and self.castLine then
- self.castLine.time = endTime
- end
- end
- self:RemoveChannelTicksAfter(endTime)
- end
- local Cast_Stop = function (self, unitid, spellname, spellrank)
- if not(self.cast[spellname]) or unitid ~= 'player' then return end
- local now = GetTime()
- if self.casting then
- self.casting.stop = now
- if vars.castLine and self.castLine then
- self.castLine.time = now
- end
- self.casting = nil
- end
- self:RemoveChannelTicksAfter(now)
- end
- local SpellFrame_UNIT_AURA = function (self, unitid)
- if unitid~=self.auraunit then return end
- if not (self.spellname and self.auraname) then return end
- local name, icon, count, duration, expirationTime, source, spellID = GetAura(self,unitid)
- --print(name, icon, count, duration, expirationTime, source, spellID)
- local afflicted = name and (self.unique or source=='player') and (not self.minstacks or count>=self.minstacks)
- local addnew
- local now = GetTime()
- local start
- local targ = UnitName(self.auraunit)
- if self.uniqueID and self.uniqueID ~= spellID then
- return
- end
- if self.aurasegment and expirationTime == 0 and duration == 0 then -- Timeless aura, bar exists (Overkill)
- for i = #self.indicators,1,-1 do
- self:Remove(i)
- end
- self.aurasegment = nil
- self.nexttick = nil
- self.stacks:SetText()
- return
- end
- if expirationTime == 0 then
- return
- end
- if afflicted then
- start = expirationTime-duration
- if icon and not(self.cast or self.slotID or self.keepIcon) then self.icon:SetTexture(icon) end
- if self.aurasegment and (self.aurasegment.lastunit == targ) then
- -- The aura is currently displayed
- if expirationTime~=self.aurasegment.stop then
- if self.alwaysrefresh and not self.cast then -- alwaysrefresh = buff. Cast + buff - HoT = BAD. Buffs with cast time and no HoT component are treated much differently.
- if self.dot then -- ...check to see if it's a HoT. If so, it's treated as a DoT.
- self.aurasegment.stop = start-0.2
- if self.cast and self.useSmalldebuff then
- self.cantcast.stop = start-0.2
- end
- self:RemoveTicksAfter(start)
- addnew = true
- else
- -- If it's a buff with no cast time or HoT component, no special handling needed, move along.
- self.aurasegment.stop = expirationTime
- end
- else
- -- The aura was replaced.
- self.aurasegment.stop = start-0.2
- if self.cast and self.useSmalldebuff then
- self.cantcast.stop = start-0.2
- end
- self:RemoveTicksAfter(start)
- addnew = true
- end
- if self.internalcooldown and type(self.internalcooldown) == 'number' then
- local stop = now + self.internalcooldown
- if start > stop then
- start = now
- end
- self:AddSegment('cooldown', 'cooldown', start, stop)
- end
- end
- else
- addnew = true
- if self.internalcooldown and type(self.internalcooldown) == 'number' then
- local stop = now + self.internalcooldown
- if start > stop then
- start = now
- end
- self:AddSegment('cooldown', 'cooldown', start, stop)
- end
- end
- SetStacks(self,count)
- else
- if self.aurasegment then
- if math.abs(self.aurasegment.stop - now)>0.3 then
- self.aurasegment.stop = now
- if self.cast and self.useSmalldebuff then
- self.cantcast.stop = now-0.2
- end
- end
- self:RemoveTicksAfter(now)
- self.aurasegment = nil
- self.stacks:SetText()
- end
- end
- self:UpdateDoT(addnew, source, now, start, expirationTime, duration, name)
- end
- local mainframe_PLAYER_TARGET_CHANGED = function (self)
- local exists = UnitExists('target')
- local dead
- if exists then
- dead = UnitIsDead('target')
- end
- for i,spellframe in pairs(ns.frames.frames) do
- if spellframe.auraunit == 'target' then
- if spellframe.aurasegment then
- for i = #spellframe.indicators,1,-1 do
- local ind = spellframe.indicators[i]
- if auraids[ind.typeid] then
- spellframe:Remove(i)
- end
- end
- spellframe.aurasegment = nil
- spellframe.targetdebuff = nil
- spellframe.nexttick = nil
- spellframe.recenttick = nil
- spellframe.stacks:SetText()
- end
- if spellframe.refreshable then
- if exists then
- if dead then
- spellframe.debuffs[UnitGUID('target')] = nil
- else
- spellframe.targetdebuff = spellframe.debuffs[UnitGUID('target')]
- end
- end
- end
- end
- end
- if UnitExists('target') then
- self:UNIT_AURA('target')
- end
- end
- local SpellFrame_RemoveTicksAfter = function (self, min)
- local indicators = self.indicators
- for i = #indicators,1,-1 do
- local ind = indicators[i]
- if (ind.typeid == 'tick') and ind.time>min then
- self:Remove(i)
- end
- end
- --print('removing ticks after',min)
- self.nexttick = nil
- end
- local SpellFrame_RemoveChannelTicksAfter = function (self, min)
- local indicators = self.indicators
- for i = #indicators,1,-1 do
- local ind = indicators[i]
- if ind.typeid == 'channeltick' and ind.time>min then
- self:Remove(i)
- end
- end
- self.nextchanneltick = nil
- end
- local mainframe_CLEU_OtherInterestingSpell = function (self, time, event, hideCaster, srcguid, srcname, srcflags, destguid, destname, destflags, spellid, spellname)
- local now = GetTime()
- if ns.otherIDs[spellname] then
- local id = ns.otherIDs[spellname]
- local bf = ns.frames.frames
- if event == 'SPELL_DAMAGE' and id.isChannel then
- for i in pairs(bf) do
- if bf[i].cast and bf[i].cast[spellname] then
- local tick = bf[i]:AddIndicator('tick', 'tick', now)
- tick.happened = true
- break
- end
- end
- elseif event == 'SPELL_CAST_SUCCESS' or event == 'SPELL_DAMAGE' and id.isGlyph then -- Glyph refresh
- if id.last and (now < (id.last + 0.9)) then -- Throttle heavily, don't want stacks getting blown
- --debug("Ignoring "..event.." from "..spellname.." at "..now)
- return
- else
- --debug("Interesting spell potentially not in frame detected! Spell: "..spellname,event)
- id.last = now
- for i in pairs(bf) do
- local gr = bf[i].glyphrefresh or nil
- local gs = bf[i].glyphstacks or nil
- if gr and (gr[3] == spellname) then
- if gs[destguid] then
- gs[destguid] = gs[destguid] - 1
- bf[i].stacks:SetText(gs[destguid] > 0 and gs[destguid] or nil)
- end
- --debug("SUCCESS! "..gr[3].." has triggered "..frame[i].auraname)
- end
- end
- end
- end
- end
- end
- local AddTicks = {}
- AddTicks.stop = function (self,now,fresh)
- local nexttick = self.start
- while nexttick<=self.stop+0.1 do
- if now+vars.future<nexttick then
- self.nexttick = nexttick
- self.lasttick = self.stop
- break
- end
- if now+vars.past<=nexttick then
- self:AddIndicator('tick', 'tick', nexttick)
- self.latesttick = nexttick
- end
- nexttick = nexttick+(self.dotMod or self.dot)
- end
- end
- AddTicks.start = function (self,now)
- local nexttick = now+(self.dotMod or self.dot)
- while nexttick<=(self.stop+0.2) do
- if now+vars.future<nexttick then
- -- The next tick is not visible yet.
- self.nexttick = nexttick
- self.lasttick = self.stop
- break
- end
- if now+vars.past<=nexttick then
- local tick = self:AddIndicator('tick', 'tick', nexttick)
- self.latesttick = nexttick
- end
- nexttick = nexttick+(self.dotMod or self.dot)
- end
- end
- local SpellFrame_COMBAT_LOG_EVENT_UNFILTERED = function (self, timestamp, event, hideCaster, srcguid,srcname,srcflags, destguid,destname,destflags, spellid,spellname)
- local now = GetTime()
- if event == 'SPELL_AURA_REMOVED' then
- if self.glyphrefresh then
- self.glyphstacks[destguid] = 0
- end
- end
- if event == 'SPELL_CAST_SUCCESS' then
- --debug('SPELL_CAST_SUCCESS',destguid)
- self.castsuccess[destguid] = now
- if self.glyphrefresh then
- for i = 1,6 do
- if ns.glyphs[i] == self.glyphrefresh[2] then
- self.glyphstacks[destguid] = self.glyphrefresh[1]
- SetStacks()
- end
- end
- end
- elseif tickevents[event] then
- local isInvalid = not(self.dot) and (self.cast and self.cast[spellname] and not(self.cast[spellname].numhits)) -- filter out cast+channel bars
- if isInvalid then return end
- if UnitGUID(self.auraunit or 'target')==destguid then
- local tick = self:AddIndicator('tick', 'tick', now)
- tick.happened = true
- if (self.dot and (self.stop and self.stop ~= nil)) then
- if self.isHasted and self.ticks then
- self.dotMod = self.ticks.last and (now - self.ticks.last) or self.dot
- self.dotMod = self.dotMod > self.dot and self.dot or self.dotMod
- self.ticks.last = now
- end
- self:RemoveTicksAfter(now) -- Reconstruct ticks from spellframe info
- local nexttick = now+(self.dotMod or self.dot)
- self.nexttick = nil
- self.recenttick = now
- while nexttick<=(self.stop+0.2) do -- Account for lag
- if now+vars.future<nexttick then
- -- The next tick is not visible yet.
- self.nexttick = nexttick
- self.lasttick = self.stop
- break
- end
- if now+vars.past<=nexttick then
- -- The next tick is visible.
- local tick = self:AddIndicator('tick', 'tick', nexttick)
- if nexttick<=now then
- tick.happened = true
- end
- self.latesttick = nexttick
- end
- nexttick=nexttick+(self.dotMod or self.dot)
- end
- end
- end
- end
- end
- local SpellFrame_UNIT_AURA_refreshable = function (self, unitid)
- if unitid~=self.auraunit then return end
- if not(self.auraname and self.spellname) then return end
- local name, icon, count, duration, expirationTime, source, spellID = GetAura(self,unitid)
- local afflicted = name and (self.unique or source=='player') and (not self.minstacks or count>=self.minstacks)
- local addnew, refresh
- local now = GetTime()
- local guid = UnitGUID(self.auraunit or 'target')
- --print(name,source,self.spellname,self.auraname)
- -- First find out if the debuff was refreshed.
- if self.aurasegment and expirationTime == 0 and duration == 0 then -- Timeless aura, bar exists (Overkill)
- for i = #self.indicators,1,-1 do
- self:Remove(i)
- end
- self.aurasegment = nil
- self.nexttick = nil
- self.stacks:SetText()
- return
- end
- if expirationTime == 0 then
- return
- end
- if afflicted then
- start = expirationTime-duration
- if icon and not(self.cast or self.slotID or self.keepIcon) then self.icon:SetTexture(icon) end
- if self.targetdebuff then
- if self.targetdebuff.stop == expirationTime then
- start = self.targetdebuff.start
- else
- -- Check for refresh.
- if start < self.targetdebuff.stop then
- local totalduration = self.targetdebuff.stop - self.targetdebuff.start
- local lasttick = self.targetdebuff.stop - math.fmod(totalduration, self.dotMod or self.dot)
- local success = self.castsuccess[guid]
- local not_recast = true -- Poisons are never actually recast, so we default to true here, because success will always be nil.
- if success then
- not_recast = math.abs(success-start)>0.5
- end
- if not_recast and start < lasttick then
- -- The current debuff was refreshed.
- start = self.targetdebuff.start
- refresh = true
- end
- end
- end
- end
- if self.aurasegment then
- if expirationTime~=self.aurasegment.stop and not refresh then
- -- The current debuff was replaced.
- self.aurasegment.stop = start-0.2
- self:RemoveTicksAfter(start)
- --debug('replaced')
- addnew = true
- end
- else
- addnew = true
- end
- SetStacks(self,count)
- else
- if self.aurasegment then
- if math.abs(self.aurasegment.stop - now)>0.3 then
- -- The current debuff ended.
- self.aurasegment.stop = now
- if self.cantcast then
- self.cantcast.stop = now
- end
- end
- self:RemoveTicksAfter(now)
- self.aurasegment = nil
- self.cantcast = nil
- self.targetdebuff = nil
- self.recenttick = nil
- self.stacks:SetText()
- end
- end
- self:UpdateDoT(addnew, source, now, start, expirationTime, duration, name, refresh, guid)
- end
- local SpellFrame_UpdateDoT = function (self, addnew, source, now, start, expirationTime, duration, name, refresh, guid)
- local addticks
- local isHasted
- local checkDoT = self.auranamePrimary or name
- local isPrimary = checkDoT == name or nil
- self.start, self.stop, self.duration = start, expirationTime, duration
- local targ = UnitName(self.auraunit)
- if addnew then
- --debug('addnew', start, expirationTime)
- local typeid = (source=='player' and self.isType) or (source~='player' and 'debuff')
- if self.cast and self.useSmalldebuff then
- self.aurasegment = self:AddSegment(typeid, 'smalldebuff', start, expirationTime)
- local hastedcasttime = select(7, GetSpellInfo(self.lastcast or self.spellname))/1000
- self.cantcast = self:AddSegment(typeid, 'cantcast', start, expirationTime-hastedcasttime)
- self.aurasegment.lastunit = targ
- else
- self.aurasegment = self:AddSegment(typeid, 'default', start, expirationTime)
- self.aurasegment.lastunit = targ
- end
- -- Add visible ticks.
- if self.dot and isPrimary then
- addticks = start
- end
- if self.debuffs then
- -- Refreshable only.
- self.targetdebuff = {start=start, stop=expirationTime}
- self.debuffs[guid] = self.targetdebuff
- end
- self.recenttick = now
- elseif refresh then
- -- debug('refresh', start, expirationTime)
- -- Note: refresh requires afflicted and self.targetdebuff. Also, afflicted and not self.debuff implies addnew.
- -- So we can get here only if afflicted and self.debuff and self.targetdebuff.
- self.aurasegment.stop = expirationTime
- self.targetdebuff.stop = expirationTime
- if self.cantcast then
- self.cantcast.start = start
- self.cantcast.stop = expirationTime-(select(7, GetSpellInfo(self.lastcast or self.spellname))/1000)
- end
- if self.latesttick then
- addticks = self.latesttick
- end
- end
- if addticks then
- addticks = self.recenttick or addticks
- local nexttick = addticks+(self.dotMod or self.dot)
- self.nexttick = nil
- if self.hasted then
- if type(self.hasted) == 'number' then
- for i = 1,6 do
- if ns.glyphs[i] == self.hasted then isHasted = true end
- end
- elseif self.hasted == true then
- isHasted = true
- end
- end
- if isHasted and self.expectedTicks then -- Using expectedTicks
- self.dotMod = (expirationTime - start)/self.expectedTicks
- local magearmor = UnitBuff(self.auraunit, "Mage Armor")
- if self.dot and magearmor and self.dotMod <= 1.5 then self.dotMod = self.dotMod * 2 end -- Adjust for mage armor rank 5+ 50% duration reduction, use number comparison to make sure we're not changing something that shouldn't be.
- elseif isHasted then
- local bct = ns.config.hastedSpellID[2]
- local hct = select(7, GetSpellInfo(ns.config.hastedSpellID[1]))/1000
- self.dotMod = self.dot*(hct/bct)
- --[[ if ns.config.nonAffectingHaste then
- for i,nah in ipairs(ns.config.nonAffectingHaste) do
- local name,_,_,_,_,source = ns:GetAura(nah[1],'buff','player')
- if name and (source == 'player') then
- self.dotMod = self.dotMod * nah[2]
- end
- end
- end--]]
- end
- self:RemoveTicksAfter(now)
- --self:AddTicks(now)
- if self.hasted then
- if type(self.hasted) == 'number' then
- for i = 1,6 do
- if ns.glyphs[i] == self.hasted then isHasted = true end
- end
- elseif self.hasted == true then
- isHasted = true
- end
- end
- if isHasted and self.ticks then -- Tick-process haste handling
- self.ticks.last = self.ticks.last or now
- self.dotMod = self.dotMod and self.dotMod or self.dot
- if (self.dotMod > self.dot) or (self.dotMod < 1.5) then self.dotMod = self.dot end
- self.isHasted = true
- elseif isHasted and self.expectedTicks then -- Using expectedTicks
- self.dotMod = (expirationTime - start)/self.expectedTicks
- end
- while nexttick<=(self.stop+0.2) do -- Account for lag
- if now+vars.future<nexttick then
- -- The next tick is not visible yet.
- self.nexttick = nexttick
- self.lasttick = self.stop
- break
- end
- if now+vars.past<=nexttick then
- -- The next tick is visible.
- local tick = self:AddIndicator('tick', 'tick', nexttick)
- if nexttick<=now then
- tick.happened = true
- end
- self.latesttick = nexttick
- end
- nexttick=nexttick+(self.dotMod or self.dot)
- end
- end
- end
- local SpellFrame_PLAYER_REGEN_ENABLED = function (self)
- local thresh = GetTime() - 10
- local remove = {}
- for guid,data in pairs(self.debuffs) do
- if data.stop < thresh then
- tinsert(remove, guid)
- end
- end
- for _,guid in ipairs(remove) do
- --debug('removing',guid,self.spellname)
- self.debuffs[guid]=nil
- end
- end
- local SpellFrame_SPELL_UPDATE_COOLDOWN = function (self)
- -- print(self.spellname,self.cooldownID,'SPELL_UPDATE_COOLDOWN')
- if self.slotID and self.cooldownID and not(self.spellname) then -- item is equipped but has none of the needed info, so rescan it.
- return self:PLAYER_EQUIPMENT_CHANGED(self.slotID)
- end
- if not(self.cooldownID or self.spellname) then return end
- local start
- local duration
- local enabled
- local ready
- -- if type(self.cooldown) == "table" then -- we choose the one with the longer CD (This is mostly for sfiend/mindbender bar)
- -- print("test")
- -- for i,cooldown in pairs(self.cooldown) do
- -- start2, duration2, enabled2 = self.CooldownFunction(cooldown)
- --print(start2, duration2, enabled2, ready2)
- -- if start2+duration2 > start+duration then
- -- start = start2
- -- duration = duration2
- -- enabled = enabled2
- -- ready = (enabled==1 and start~=0 and duration) and start+duration
- -- end
- --print(start, duration, enabled, ready)
- -- end
- --print(start, duration, enabled, ready)
- -- else
- start, duration, enabled = self.CooldownFunction(self.cooldownID or self.spellname)
- ready = enabled==1 and start~=0 and duration and start+duration
- -- end
- --print(start, duration, enabled, ready)
- if ready and duration>1.5 then
- -- The spell is on cooldown, but not just because of the GCD.
- if self.cooldownID then
- end
- if self.cooldown ~= ready then -- The CD has changed since last check
- if not(self.coolingdown) then -- No CD bar exists.
- self.coolingdown = self:AddSegment('cooldown', self.smallCooldown and 'smallCooldown' or 'cooldown', start, ready)
- elseif self.coolingdown.stop and self.coolingdown.stop ~= ready then -- cd exists but has changed
- self.coolingdown.start = start
- self.coolingdown.stop = ready
- end
- self.cooldown = ready
- end
- else
- if self.coolingdown then
- -- Spell is off cooldown or cd expires during GCD window
- local now = GetTime()
- -- See when the cooldown is ready. If the spell is currently on GCD, check the GCD end; otherwise check now.
- if self.cooldown > (ready or now) then
- -- The cooldown ended earlier.
- self.coolingdown.stop = now
- end
- self.coolingdown = nil
- end
- self.cooldown = nil
- end
- end
- local SpellFrame_PLAYER_EQUIPMENT_CHANGED = function (self,slot,equipped)
- if not (slot or self.slotID) or (self.slotID ~= slot) then return end
- for i = #self.indicators,1,-1 do
- self:Remove(i)
- end
- self.aurasegment = nil
- self.nexttick = nil
- self.stacks:SetText()
- self.cooldown = nil
- self.coolingdown = nil
- self.playerbuff = nil
- self.spellname = nil
- self.auraname = nil
- self.internalcooldown = true
- local itemID,name,tex = self:FindItemInfo()
- self.cooldownID = itemID
- if (itemID and name and tex) and not(ns.trinkets.blacklist[name]) then
- self.spellname = name
- self.icon:SetTexture(tex)
- self.stance = true -- Always show
- if ns.trinkets[name] then
- if type(ns.trinkets[name]) == 'number' then
- self.playerbuff = ns.trinkets[name]
- elseif type(ns.trinkets[name]) == 'table' then
- self.playerbuff = ns.trinkets[name][1]
- self.internalcooldown = ns.trinkets[name][2]
- end
- elseif self.slotID == 10 then
- self.playerbuff = 54758 -- Engy gloves
- elseif self.slotID == 8 then
- self.playerbuff = 54861 -- Nitro Boosts
- end
- if type(self.playerbuff)=='number' then
- self.auraname = (GetSpellInfo(self.playerbuff))
- elseif type(self.playerbuff)=='table' then
- self.auraname = {}
- self.auranamePrimary = (GetSpellInfo(self.playerbuff[1]))
- for i,id in ipairs(self.playerbuff) do
- tinsert(self.auraname, (GetSpellInfo(id)))
- end
- self.AuraFunction = UnitBuffUnique
- else
- self.auraname = self.spellname
- end
- self:SPELL_UPDATE_COOLDOWN()
- else
- self.stance = 50 -- More efficient than other methods of hiding the bar.
- self.icon:SetTexture(0,0,0,0)
- end
- -- Throttle equipment checks to every 2 seconds. This should decrease overall cpu load while making equipment checks more reliable on beta/ptr.
- -- vars.EQCframes = vars.EQCframes or {}
- -- table.insert(vars.EQCframes,self)
- --print('equipment update - slot '..self.slotID)
- if not(vars.currentEQcheck) then
- frame2.elapsed = 0
- vars.currentEQcheck = true
- frame2:SetScript('OnUpdate', function (self,elapsed)
- self.elapsed = self.elapsed + elapsed
- if self.elapsed >= 2 then
- mainframe:UPDATE_SHAPESHIFT_FORM()
- --[[ for i,v in ipairs(vars.EQCframes) do
- v:SPELL_UPDATE_COOLDOWN()
- end ]]--
- vars.currentEQcheck = nil
- -- vars.EQCframes = nil
- --print('equipment check onupdate complete and cleared')
- self:SetScript('OnUpdate',nil)
- end
- end)
- end
- end
- --[[
- Things get ugly again here.
- UNIT_AURA does not fire for mouseover units, so we need to emulate it.
- UPDATE_MOUSEOVER_UNIT does not fire when a mouseover unit is cleared, so we need to emulate that as well.
- The UMU check is unthrottled by necessity. UNIT_AURA doesn't really need to be run more than 10 times per second, so it gets throttled to save cycles.
- ]]--
- local TTL,TSLU = 0.15,0
- local UpdateMouseover = function (self,elapsed)
- TSLU = TSLU+elapsed
- if not(UnitExists('mouseover')) then
- ns:CheckMouseover()
- frame:SetScript('OnUpdate',nil)
- else
- if (TSLU >= TTL) then
- mainframe:UNIT_AURA('mouseover')
- TSLU = 0
- end
- end
- end
- local SpellFrame_UPDATE_MOUSEOVER_UNIT = function (self)
- --print("UPDATE_MOUSEOVER_UNIT")
- if UnitExists('mouseover') then
- vars.isMouseover = true
- self.auraunit = 'mouseover'
- else
- vars.isMouseover = nil
- self.auraunit = self.baseunit
- end
- frame:SetScript('OnUpdate',UpdateMouseover)
- if self.aurasegment then
- for i = #self.indicators,1,-1 do
- local ind = self.indicators[i]
- if auraids[ind.typeid] then
- self:Remove(i)
- end
- end
- self.aurasegment = nil
- self.nexttick = nil
- self.stacks:SetText()
- end
- if self.refreshable then
- if UnitExists(self.auraunit) then
- local guid = UnitGUID(self.auraunit)
- if UnitIsDead(self.auraunit) then
- self.debuffs[guid] = nil
- else
- self.targetdebuff = self.debuffs[guid]
- --if self.targetdebuff then debug(self.spellname, 'have old') end
- mainframe:UNIT_AURA(self.auraunit)
- --if self.aurasegment then debug(self.spellname, 'added new') end
- if self.glyphstacks and self.aurasegment then
- local count = self.glyphstacks[guid]
- if self.glyphstacks[guid] and ( count > 0) then
- self.stacks:SetText(self.glyphstacks[UnitGUID(self.auraunit)])
- end
- end
- end
- end
- elseif UnitExists(self.auraunit) then
- mainframe:UNIT_AURA(self.auraunit)
- end
- end
- -- A SpellFrame is active (i.e. listening to events) iff the talent requirements are met.
- -- The table EventHorizon.frames.active contains all the active frames.
- -- If the stance requirement is not met, the frame is hidden, but still active.
- local SpellFrame_Deactivate = function (self)
- if not self.isActive then return end
- --debug('unregistering events for', self.spellname)
- self:UnregisterAllEvents()
- if self.interestingCLEU then
- mainframe.framebyspell[self.spellname] = nil
- end
- self:Hide()
- for index=#self.indicators,1,-1 do
- self:Remove(index)
- end
- self.isActive = nil
- end
- local SpellFrame_Activate = function (self)
- if self.isActive then return end
- --debug('registering events for', self.spellname)
- for event in pairs(self.interestingEvent) do
- self:RegisterEvent(event)
- end
- if self.interestingCLEU then
- mainframe.framebyspell[self.spellname] = self
- end
- self:Show()
- self.isActive = true
- end
- local timer = 0
- local checkInProgress
- function ns:CheckTalents()
- if checkInProgress then return end
- checkInProgress = true
- frame3:SetScript('OnUpdate', function (f,elapsed)
- timer = timer + elapsed
- if timer >= 2 then
- timer = 0
- checkInProgress = nil
- ns:CheckRequirements()
- f:SetScript('OnUpdate',nil)
- end
- end)
- end
- function ns:SetFrameDimensions()
- local left,right,top,bottom = 0.07, 0.93, 0.07, 0.93
- local barheight2 = self.config.height
- local modHeight = self.config.height
- local sfn = type(self.config.staticframes) == 'number' and self.config.staticframes or 0
- local sfi = self.config.hideIcons == true
- if (#ns.frames.shown >= sfn) and type(self.config.staticheight) == 'number' then
- mainframe:SetHeight(self.config.staticheight)
- vars.barheight = (self.config.staticheight - (vars.barspacing*(vars.numframes - 1)))/vars.numframes
- modHeight = vars.barheight
- local ratio = vars.barheight/barheight2
- ratio = math.abs( (1-(1/ratio))/2 ) -- Yes, this was a bitch to figure out.
- if vars.barheight > barheight2 then -- icon is taller than it is wide
- left = left + ratio
- right = right - ratio
- else
- top = top + ratio
- bottom = bottom - ratio
- end
- else
- vars.barheight = barheight2
- mainframe:SetHeight(vars.numframes * (vars.barheight+vars.barspacing) - vars.barspacing)
- end
- vars.nowleft = -vars.past/(vars.future-vars.past)*vars.barwidth-0.5 + (ns.config.hideIcons and 0 or ns.config.height)
- if ns.frames.nowIndicator then
- ns.frames.nowIndicator:SetPoint('BOTTOM',mainframe,'BOTTOM')
- ns.frames.nowIndicator:SetPoint('TOPLEFT',mainframe,'TOPLEFT', vars.nowleft, 0)
- ns.frames.nowIndicator:SetWidth(vars.onepixelwide)
- ns.frames.nowIndicator:SetTexture(unpack(self.colors.nowLine))
- end
- local shownframes = #ns.frames.shown > 0
- if shownframes then
- for i = 1,#ns.frames.shown do
- local spellframe = ns.frames.shown[i]
- if spellframe then
- --spellframe:ClearAllPoints()
- spellframe:SetHeight(vars.barheight)
- spellframe:SetWidth(vars.barwidth)
- spellframe.icon:ClearAllPoints()
- spellframe:SetPoint('RIGHT', mainframe, 'RIGHT')
- if i == 1 then
- spellframe:SetPoint('TOPLEFT', mainframe, 'TOPLEFT', sfi and 0 or barheight2, 0)
- else
- spellframe:SetPoint('TOPLEFT', ns.frames.shown[i-1], 'BOTTOMLEFT', 0, -vars.barspacing)
- end
- if not(sfi) then
- spellframe.icon:SetPoint('TOPRIGHT',spellframe,'TOPLEFT')
- spellframe.icon:SetWidth(barheight2)
- spellframe.icon:SetHeight(modHeight)
- spellframe.icon:SetTexCoord(left,right,top,bottom)
- end
- local indicators = #spellframe.indicators > 0
- if indicators then
- for i=1,#spellframe.indicators do
- local indicator = spellframe.indicators[i]
- if indicator then
- local ndtex, ndcol
- local typeid = indicator.typeid
- local layoutid = indicator.layoutid
- local usetexture
- if not(exemptColors[typeid]) and self.bartexture then ndtex = self.bartexture end
- if typeid and customColors[typeid] then
- usetexture = true
- if spellframe.barcolorunique and typeid == 'debuff' then
- ndcol = spellframe.barcolorunique
- elseif spellframe.barcolor then
- ndcol = spellframe.barcolor
- end
- elseif typeid == 'cooldown' then
- usetexture = true
- end
- usetexture = usetexture and vars.texturedbars
- -- Layout
- local layouts = ns.layouts
- local layout = layouts[layoutid] or layouts.default
- local color = ndcol or ns.colors[typeid] or ns.colors.default
- if layoutid == 'frameline' then
- color = typeid == 'sent' and ns.colors.castLine or ns.colors[typeid]
- indicator:SetPoint('TOP',ns.mainframe)
- indicator:SetPoint('BOTTOM',ns.mainframe)
- else
- indicator:SetPoint('TOP',spellframe, 'TOP', 0, -layout.top*vars.barheight)
- indicator:SetPoint('BOTTOM',spellframe, 'TOP', 0, -layout.bottom*vars.barheight)
- end
- if usetexture then
- indicator:SetTexture(ndtex or vars.bartexture)
- indicator:SetTexCoord(unpack(layout.texcoords))
- else
- indicator:SetTexture(1,1,1,1)
- end
- indicator:SetVertexColor(unpack(ndcol or color))
- --if typeid == 'casting' then print(unpack(ndcol or color)) end
- end
- end
- end
- end
- end
- end
- end
- --[[
- function ns:AddCheckedTalent(tab,index)
- local required = true
- for k,v in ipairs(self.talents) do
- if (v[1] == tab) and (v[2] == index) then
- required = nil
- end
- end
- if required then
- table.insert(self.talents,{tab,index})
- end
- end
- ]]
- function ns:CheckRequirements()
- --print('CheckTalents')
- table.wipe(self.frames.active)
- table.wipe(self.frames.mouseover)
- --print('checkrequirements')
- --print(GetTime())
- EventHorizonDB.charInfo = EventHorizonDB.charInfo or {}
- local cc = EventHorizonDB.charInfo
- vars.activeTree = GetSpecialization()
- vars.activeTalentGroup = GetActiveSpecGroup('player')
- vars.currentLevel = UnitLevel('player')
- self.glyphs = {}
- for i = 1,6 do
- local enabled,_,gsID,_ = GetGlyphSocketInfo(i)
- if enabled and gsID then
- self.glyphs[i] = gsID
- else
- self.glyphs[i] = nil
- end
- end
- for i,config in ipairs(self.frames.config) do
- local rG = config.requiredGlyph
- local rS = config.requiredTree
- local rL = config.requiredLevel or 1
- local haveGlyphReq = true
- local haveSpecReq = true
- local haveLevelReq = rL <= vars.currentLevel
- if rG then
- haveGlyphReq = nil
- for i,glyph in ipairs(self.glyphs) do
- if rG == glyph then haveGlyphReq = true end
- end
- end
- if rS then
- haveSpecReq = nil
- if type(rS) == 'number' then
- rS = {rS}
- end
- --print(config.spellID,rS)
- for i,spec in ipairs(rS) do
- if spec == vars.activeTree then
- haveSpecReq = true
- end
- end
- end
- -- Check if there already is a frame
- local spellframe = self.frames.frames[i]
- local frameExists = spellframe~=nil
- if haveGlyphReq and haveSpecReq and haveLevelReq then
- if frameExists then
- spellframe:Activate()
- else
- spellframe = self:CreateSpellBar(config)
- self.frames.frames[i] = spellframe
- end
- table.insert(self.frames.active, spellframe)
- if spellframe.usemouseover then
- table.insert(self.frames.mouseover, spellframe)
- end
- if spellframe.cooldownTable then -- We need to update the spellID again
- spellframe.cooldownID = IsUsableSpell(config.cooldown[2]) and config.cooldown[2] or config.cooldown[1]
- spellframe.cooldown = true
- end
- else
- if frameExists then
- spellframe:Deactivate()
- end
- end
- end
- local activate = #self.frames.active > 0
- self:Activate(activate)
- if activate then
- mainframe:UPDATE_SHAPESHIFT_FORM()
- end
- ns:ModuleEvent('CheckTalents')
- end
- local mainframe_UPDATE_SHAPESHIFT_FORM = function (self)
- local stance = GetShapeshiftForm()
- -- On PLAYER_LOGIN, GetShapeshiftForm() sometimes returns a bogus value (2 on a priest with 1 form). Ignored for Warlocks and cached information.
- if not(stance) or (GetNumShapeshiftForms() and class ~= 'WARLOCK' and stance>GetNumShapeshiftForms()) then return end
- mainframe:SetHeight(1)
- table.wipe(ns.frames.shown)
- EventHorizonDB.charInfo.stance = stance
- vars.numframes = 0
- for i,spellframe in ipairs(ns.frames.active) do
- local shown = spellframe:IsShown()
- if spellframe.stance then
- shown = false
- if type(spellframe.stance) == 'table' then
- shown = false
- for i in ipairs(spellframe.stance) do
- if spellframe.stance[i] == stance then
- shown = true
- end
- end
- elseif spellframe.stance == true then
- shown = true
- elseif spellframe.stance == stance and not shown then
- shown = true
- elseif spellframe.stance and spellframe.stance ~= stance and shown then
- shown = false
- end
- end
- if spellframe.notstance then
- shown = true
- if spellframe.notstance and type(spellframe.notstance) == 'table' then
- for i in ipairs(spellframe.notstance) do
- if spellframe.notstance[i] == stance then
- shown = false
- end
- end
- elseif spellframe.notstance == stance then
- shown = false
- end
- end
- if shown then
- spellframe:Show()
- vars.numframes = vars.numframes+1
- table.insert(ns.frames.shown,spellframe)
- else
- spellframe:Hide()
- for i,indicator in ipairs(spellframe.indicators) do
- indicator:Hide()
- end
- end
- end
- if vars.numframes>0 then
- ns:SetFrameDimensions()
- if (EventHorizonDB.redshift) and (ns.modules.redshift.isReady and EventHorizonDB.redshift.isActive == true) then
- ns.modules.redshift:Check()
- elseif ns.isActive and vars.visibleFrame then
- mainframe:Show()
- end
- else
- mainframe:Hide()
- end
- return true
- end
- function ns:CheckMouseover()
- for i,spellframe in ipairs(self.frames.mouseover) do
- spellframe:UPDATE_MOUSEOVER_UNIT()
- end
- end
- -- GCD indicator
- local mainframe_SPELL_UPDATE_COOLDOWN = function (self)
- if ns.frames.gcd then
- local start, duration = GetSpellCooldown(vars.gcdSpellName)
- local sfi = ns.config.hideIcons
- --print(start,duration)
- if start and duration and duration>0 then
- vars.gcdend = start+duration
- mainframe:SetScript('OnUpdate', function (self, elapsed)
- if vars.gcdend then
- local now = GetTime()
- if vars.gcdend<=now then
- vars.gcdend = nil
- ns.frames.gcd:Hide()
- else
- local diff = now+vars.past
- local p = (vars.gcdend-diff)*vars.scale
- if p<=1 then
- ns.frames.gcd:SetPoint('RIGHT', self, 'RIGHT',(p-1)*vars.barwidth+vars.onepixelwide, 0)
- ns.frames.gcd:Show()
- end
- end
- end
- end)
- else
- vars.gcdend = nil
- ns.frames.gcd:Hide()
- mainframe:SetScript('OnUpdate', nil)
- end
- end
- end
- -- Dispatch the CLEU.
- local mainframe_COMBAT_LOG_EVENT_UNFILTERED = function (self,time, event, hideCaster, srcguid,srcname,srcflags, destguid,destname,destflags, spellid,spellname)
- if srcguid~=vars.playerguid or event:sub(1,5)~='SPELL' then return end
- local spellframe = self.framebyspell[spellname]
- if ns.otherIDs[spellname] then
- mainframe:CLEU_OtherInterestingSpell(time, event, hideCaster, srcguid,srcname,srcflags, destguid,destname,destflags, spellid,spellname)
- end
- if spellframe then
- if spellframe.interestingCLEU[event] then
- spellframe:COMBAT_LOG_EVENT_UNFILTERED(time, event, hideCaster, srcguid,srcname,srcflags, destguid,destname,destflags, spellid,spellname)
- end
- end
- end
- function ns:LoadClassModule()
- local class = select(2,UnitClass('player'))
- class = class:sub(1,1)..class:sub(2):lower() -- 'WARLOCK' -> 'Warlock'
- local name, _, _, enabled, loadable = GetAddOnInfo('EventHorizon_'..class)
- DisableAddOn('EventHorizon_Redshift')
- DisableAddOn('EventHorizon_Lines')
- if not enabled or not loadable then
- return
- end
- local loaded, reason = LoadAddOn(name)
- if loaded and self.InitializeClass then
- return true
- end
- end
- --[[
- spellid: number, rank doesn't matter
- abbrev: string
- config: table
- {
- cast = <boolean>,
- channeled = <boolean>,
- numhits = <number of hits per channel>,
- cooldown = <boolean>,
- debuff = <boolean>,
- dot = <tick interval in s, requires debuff>,
- refreshable = <boolean>,
- }
- --]]
- function ns:NewSpell(config)
- local spellid = config.spellID or config.itemID or config.slotID
- if type(spellid)~='number' then
- return
- end
- table.insert(self.frames.config, config)
- end
- --Set spellframe attributes separately from bar creation. Helps keep things tidy and all, y'know?
- local function SetSpellAttributes(spellframe,config)
- local interestingEvent = {}
- local interestingCLEU = {}
- local config = config
- local otherids = ns.otherIDs
- local spellname = spellframe.spellname
- interestingEvent['UNIT_SPELLCAST_SENT'] = true
- if config.itemID or config.slotID then
- spellframe.cooldown = true -- Not getting out of this one. It's an item, what else do you watch?
- spellframe.cooldownID = config.itemID
- spellframe.CooldownFunction = GetItemCooldown
- interestingEvent['SPELL_UPDATE_COOLDOWN'] = true
- interestingEvent['BAG_UPDATE_COOLDOWN'] = true
- if config.slotID then
- config.playerbuff = true
- config.internalcooldown = true -- Failsafe
- interestingEvent['PLAYER_EQUIPMENT_CHANGED'] = true
- end
- end
- if config.cast or config.channeled then
- spellframe.cast = {}
- if config.channeled then
- -- Register for the CLEU tick event.
- interestingCLEU.SPELL_DAMAGE = true
- -- Register event functions
- interestingEvent['UNIT_SPELLCAST_CHANNEL_START'] = true
- interestingEvent['UNIT_SPELLCAST_CHANNEL_STOP'] = true
- interestingEvent['UNIT_SPELLCAST_CHANNEL_UPDATE'] = true
- local tcc = type(config.channeled)
- if config.channeled == true then -- defaults
- spellframe.cast[spellname] = {
- numhits = config.numhits or true, -- use numhits as an indicator that the cast is channeled and not to change smalldebuff, or something.
- func = UnitChannelInfo,
- id = config.spellID,
- }
- elseif tcc == 'number' then
- local sn = GetSpellInfo(config.channeled)
- spellframe.cast[sn] = {
- numhits = config.numhits or true, -- use numhits as an indicator that the cast is channeled and not to change smalldebuff, or something.
- func = UnitChannelInfo,
- id = config.channeled,
- }
- otherids[sn] = {isChannel = true}
- elseif tcc == 'table' then
- local channel = type(config.channeled[1]) == 'table' and config.channeled or {config.channeled}
- for _,v in ipairs(channel) do
- local sn = GetSpellInfo(v[1])
- spellframe.cast[sn] = {
- numhits = v[2] or config.numhits or true,
- func = UnitChannelInfo,
- id = v[1],
- }
- otherids[sn] = {isChannel = true}
- end
- end
- end
- if config.cast then
- interestingEvent['UNIT_SPELLCAST_START'] = true
- interestingEvent['UNIT_SPELLCAST_STOP'] = true
- interestingEvent['UNIT_SPELLCAST_DELAYED'] = true
- spellframe.useSmalldebuff = config.recast
- if ((config.debuff or config.playerbuff) and type(config.debuff or config.playerbuff) == 'boolean') then
- spellframe.useSmalldebuff = true
- end
- if config.cast == true then
- spellframe.cast[spellname] = {
- func = UnitCastingInfo,
- id = config.spellID
- }
- else
- config.cast = type(config.cast) == 'table' and config.cast or {config.cast}
- for _,id in ipairs(config.cast) do
- spellframe.cast[GetSpellInfo(id)] = {
- func = UnitCastingInfo,
- id = id
- }
- end
- end
- end
- end
- if config.cooldown then
- if type(config.cooldown) == 'number' then
- spellframe.cooldownID = config.cooldown
- spellframe.cooldown = true
- elseif type(config.cooldown) == 'table' then -- If the second spellID entered is actually usable, then use that otherwise use the other
- spellframe.cooldownID = IsUsableSpell(config.cooldown[2]) and config.cooldown[2] or config.cooldown[1]
- spellframe.cooldownTable = true
- spellframe.cooldown = true
- end
- spellframe.CooldownFunction = GetSpellCooldown
- interestingEvent['SPELL_UPDATE_COOLDOWN'] = true
- end
- if config.debuff then
- spellframe.isType = 'debuffmine'
- spellframe.AuraFunction = UnitDebuff
- spellframe.auraunit = config.auraunit or 'target'
- vars.debuff[spellframe.auraunit] = {}
- if spellframe.auraunit == 'mouseover' then
- interestingEvent['UPDATE_MOUSEOVER_UNIT'] = true
- spellframe.usemouseover = true
- spellframe.baseunit = config.baseunit or 'target'
- end
- local tcd = type(config.debuff)
- if tcd == 'number' then
- spellframe.auraname = (GetSpellInfo(config.debuff))
- elseif tcd == 'table' then
- spellframe.auranamePrimary = (GetSpellInfo(config.spellID))
- spellframe.auraname = {}
- for i,id in ipairs(config.debuff) do
- tinsert(spellframe.auraname, (GetSpellInfo(id)))
- end
- spellframe.AuraFunction = UnitDebuffUnique
- else
- spellframe.auraname = spellname
- end
- -- interestingEvent['UNIT_AURA'] = true
- -- interestingEvent['PLAYER_TARGET_CHANGED'] = true
- if config.dot then
- spellframe.dot = config.dot
- interestingCLEU.SPELL_PERIODIC_DAMAGE = true
- spellframe.AddTicks = AddTicks.stop
- if config.refreshable then
- spellframe.refreshable = true
- spellframe.UNIT_AURA = SpellFrame.UNIT_AURA_refreshable
- -- spellframe.PLAYER_TARGET_CHANGED = SpellFrame.PLAYER_TARGET_CHANGED_refreshable
- interestingEvent['PLAYER_REGEN_ENABLED'] = true
- interestingCLEU.SPELL_CAST_SUCCESS=true
- spellframe.debuffs = {}
- spellframe.castsuccess = {}
- end
- end
- elseif config.playerbuff then
- spellframe.isType = 'playerbuff'
- spellframe.AuraFunction = UnitBuff
- spellframe.auraunit = config.auraunit or 'player'
- vars.buff[spellframe.auraunit] = {}
- if config.auraunit then
- -- interestingEvent['PLAYER_TARGET_CHANGED'] = true
- end
- if spellframe.auraunit == 'mouseover' then
- interestingEvent['UPDATE_MOUSEOVER_UNIT'] = true
- spellframe.usemouseover = true
- spellframe.baseunit = config.baseunit or 'target'
- end
- spellframe.alwaysrefresh = true
- -- interestingEvent['UNIT_AURA'] = true
- local tcp = type(config.playerbuff)
- if tcp == 'number' then
- spellframe.auraname = (GetSpellInfo(config.playerbuff))
- elseif tcp == 'table' then
- spellframe.auraname = {}
- spellframe.auranamePrimary = (GetSpellInfo(config.spellID))
- for i,id in ipairs(config.playerbuff) do
- tinsert(spellframe.auraname, (GetSpellInfo(id)))
- end
- spellframe.AuraFunction = UnitBuffUnique
- else
- spellframe.auraname = spellname
- end
- if config.dot then -- Register for periodic effect intervals.
- spellframe.dot = config.dot
- spellframe.AddTicks = AddTicks.stop
- interestingCLEU.SPELL_PERIODIC_HEAL = true
- if config.refreshable then
- spellframe.refreshable = true
- spellframe.UNIT_AURA = SpellFrame.UNIT_AURA_refreshable
- -- spellframe.PLAYER_TARGET_CHANGED = SpellFrame.PLAYER_TARGET_CHANGED_refreshable
- interestingEvent['PLAYER_REGEN_ENABLED'] = true
- interestingCLEU.SPELL_CAST_SUCCESS=true
- spellframe.debuffs = {}
- spellframe.castsuccess = {}
- end
- end
- end
- if config.cleu or config.event then -- Register custom CLEU events.
- if config.event then -- Optional alias for the forgetful.
- config.cleu = config.event
- end
- local cleu = type(config.cleu)
- if cleu == 'string' then -- Single event
- interestingCLEU[config.cleu] = true
- elseif cleu == 'table' then
- for i in pairs(config.cleu) do -- Multiple events
- interestingCLEU[ config.cleu[i] ] = true
- end
- end
- end
- if type(config.glyphrefresh) == 'table' then
- spellframe.glyphrefresh = config.glyphrefresh
- spellframe.glyphstacks = {}
- if not otherids[config.glyphrefresh[3]] then
- otherids[config.glyphrefresh[3]] = {}
- end
- otherids[config.glyphrefresh[3]][spellname] = true
- otherids[config.glyphrefresh[3]].isGlyph = true
- interestingCLEU.SPELL_AURA_REMOVED = true
- end
- spellframe.hasted = config.hasted
- spellframe.minstacks = config.minstacks
- spellframe.stance = config.stance
- spellframe.notstance = config.notstance
- spellframe.internalcooldown = config.internalcooldown
- spellframe.bartexture = config.bartexture
- spellframe.barcolor = config.barcolor
- spellframe.barcolorunique = config.barcolorunique
- spellframe.unique = config.unique
- spellframe.uniqueID = config.uniqueID
- spellframe.keepIcon = config.keepIcon
- spellframe.smallCooldown = config.smallCooldown
- spellframe.interestingCLEU = interestingCLEU
- return interestingEvent
- end
- function ns:CreateSpellBar(config)
- local spellid = config.spellID
- local invid = config.itemID
- local csid = config.slotID
- local slotname, spellname, tex, _
- local spellframe = CreateFrame('Frame', nil, mainframe)
- mainframe.numframes = mainframe.numframes+1
- if spellid then
- spellname, _, tex = GetSpellInfo(spellid)
- elseif invid then
- spellname,_,_,_,_,_,_,_,_,tex,_ = GetItemInfo(invid)
- elseif csid then
- slotname = GetSlotName(csid)
- spellframe.slotID = csid
- spellframe.slotName = slotname
- local itemID = GetInventoryItemID('player',csid)
- if itemID then
- spellname,_,_,_,_,_,_,_,_,tex,_ = GetItemInfo(itemID)
- else
- spellname = slotName
- tex = nil
- end
- end
- local basename = slotname or spellname
- --debug('creating frame for ',spellname)
- spellframe.spellname = spellname
- -- Create the bar.
- spellframe.indicators = {}
- if ns.config.barbg then
- spellframe:SetBackdrop{bgFile = vars.bartexture}
- spellframe:SetBackdropColor(unpack(ns.colors.barbgcolor))
- end
- -- Create and set the spell icon.
- if config.icon then
- local t = type(config.icon)
- if t == 'number' then
- if spellid then
- _,_,tex = GetSpellInfo(config.icon)
- elseif invid then
- tex = select(10,GetItemInfo(config.icon))
- end
- elseif t == 'string' then
- tex = config.icon
- end
- config.keepIcon = true
- end
- spellframe.icon = spellframe:CreateTexture(nil, 'BORDER')
- spellframe.icon:SetTexture(tex)
- spellframe.stacks = spellframe:CreateFontString(nil, 'OVERLAY')
- if vars.stackFont then
- spellframe.stacks:SetFont(vars.stackFont,vars.stackFontSize)
- if vars.stackFontShadow then
- spellframe.stacks:SetShadowColor(unpack(vars.stackFontShadow))
- spellframe.stacks:SetShadowOffset(unpack(vars.stackFontShadowOffset))
- end
- else
- spellframe.stacks:SetFontObject('NumberFontNormalSmall')
- end
- spellframe.stacks:SetVertexColor(unpack(vars.stackFontColor))
- for k,v in pairs(SpellFrame) do
- if not spellframe[k] then spellframe[k] = v end
- end
- spellframe.interestingEvent = SetSpellAttributes(spellframe,config)
- spellframe:SetScript('OnEvent', EventHandler)
- spellframe:SetScript('OnUpdate', spellframe.OnUpdate)
- local sfi = self.config.hideIcons
- local sor = self.config.stackOnRight
- -- Layout
- spellframe.stacks:SetPoint((sfi and not(sor)) and 'BOTTOMLEFT' or 'BOTTOMRIGHT', (sfi or sor) and spellframe or spellframe.icon, (sfi and not(sor)) and 'BOTTOMLEFT' or 'BOTTOMRIGHT')
- spellframe.stacks:SetJustifyH(sor and 'LEFT' or 'RIGHT')
- spellframe:Activate()
- if config.slotID then
- spellframe:PLAYER_EQUIPMENT_CHANGED(config.slotID) -- Initialize trinkets and such if needed.
- end
- return spellframe
- end
- function ns:LoadModules()
- for i,module in pairs(self.modules) do
- if not EventHorizonDB[i] then EventHorizonDB[i] = { isActive = true } end
- if (EventHorizonDB[i] and EventHorizonDB[i].isActive == true) or module.alwaysLoad then
- if not(self.modules[i].Enable) then self.modules[i].Enable = function () end end
- if not(self.modules[i].Disable) then self.modules[i].Disable = function () end end
- self.modules[i]:Init()
- self.modules[i]:Enable()
- vars.modulesLoaded = true
- end
- end
- end
- function ns:ActivateModule(module,slash)
- if EventHorizonDB[module].isActive ~= true then
- self.modules[module].isActive = true
- EventHorizonDB[module].isActive = true
- if not(self.modules[module].isReady == true) then self.modules[module].Init() end
- self.modules[module].Enable(slash)
- end
- end
- function ns:DeactivateModule(module,slash)
- if EventHorizonDB[module].isActive == true then
- self.modules[module].isActive = false
- EventHorizonDB[module].isActive = false
- if not(self.modules[module].isReady == true) then self.modules[module].Init() end
- self.modules[module].Disable(slash)
- end
- end
- function ns:ToggleModule(module,slash)
- if EventHorizonDB[module].isActive ~= true then
- self:ActivateModule(module,slash)
- else
- self:DeactivateModule(module,slash)
- end
- end
- -- External event handler for modules, same rules as EH's event handler (passes self, extra args, event is presumed known)
- function ns:ModuleEvent(event, ...)
- for i,module in pairs(self.modules) do
- local f = module[event]
- if f then
- f(module,...)
- end
- end
- end
- function ns:Activate(...)
- local activate = select('#',...) == 0 or ...
- --debug('Activate',activate, ...)
- if not activate then
- return self:Deactivate()
- end
- for k,v in pairs(mainframeEvents) do
- mainframe:RegisterEvent(k)
- end
- self.isActive = true
- vars.visibleFrame = true
- if (self.modules.redshift.isReady and EventHorizonDB.redshift.isActive == true) then
- self.modules.redshift:Check()
- else
- mainframe:Show()
- end
- end
- function ns:Deactivate()
- if self.isActive==false then
- return
- end
- mainframe:UnregisterAllEvents()
- mainframe:RegisterEvent('PLAYER_TALENT_UPDATE')
- mainframe:Hide()
- self.isActive = false
- end
- function ns:InitDB()
- if not EventHorizonDB then EventHorizonDB = self.defaultDB end
- -- print('initdb')
- local reset
- -- Upgrade DB.
- if EventHorizonDB and not EventHorizonDB.version then
- EventHorizonDB.version = 0
- end
- if EventHorizonDB.version ~= EventHorizon.defaultDB.version then
- reset = true
- table.wipe(EventHorizonDB)
- EventHorizonDB = Clone(ns.defaultDB)
- end
- if not EventHorizonDBG then EventHorizonDBG = self.defaultDBG end
- -- Upgrade DB.
- if EventHorizonDBG and not EventHorizonDBG.version then
- EventHorizonDBG.version = 0
- end
- if EventHorizonDBG.version ~= EventHorizon.defaultDBG.version then
- reset = true
- table.wipe(EventHorizonDBG)
- EventHorizonDBG = Clone(ns.defaultDBG)
- end
- -- If profile doesn't exist, set it to the default.
- EventHorizonDBG.profilePerChar[playername] = EventHorizonDBG.profilePerChar[playername] or EventHorizonDBG.defaultProfile
- local ppc = EventHorizonDBG.profilePerChar[playername]
- if not EventHorizonDBG.profiles[ppc] then
- EventHorizonDBG.profiles[ppc] = {}
- end
- self.vars.currentProfile = EventHorizonDBG.profiles[ppc]
- if reset then
- print('Your savedvariables have been reset due to potential conflicts with older versions.')
- end
- self.db = EventHorizonDB
- self.dbg = EventHorizonDBG
- end
- --[[
- Should only be called after the DB is loaded and spell and talent information is available.
- --]]
- function ns:Initialize()
- -- Make sure this function is called only once.
- --self.Initialize = nil
- --print('initialize')
- self:InitDB()
- --debug('GetTalentInfo(1,1)',GetTalentInfo(1,1))
- vars.playerguid = UnitGUID('player')
- -- Create the main and spell frames.
- mainframe:SetHeight(1)
- mainframe.numframes = 0
- mainframe.framebyspell= {}
- mainframe:SetScript('OnEvent', EventHandler)
- mainframe:SetScale(self.config.scale or 1)
- vars.buff.player = {}
- if not self:LoadClassModule() then
- return
- end
- self:ApplyConfig()
- self:InitializeClass()
- if self.config.showTrinketBars and self.config.showTrinketBars == true then
- self:NewSpell({slotID = 13})
- self:NewSpell({slotID = 14})
- end
- local sfi = self.config.hideIcons
- mainframe:SetWidth(vars.barwidth + (sfi and 0 or self.config.height))
- self:SetupStyleFrame() -- Spawn backdrop frame.
- -- Create the indicator for the current time.
- -- Bugfix: When the UI scale is at a very low setting, textures with a width of 1
- -- were not visible in some resolutions.
- local effectiveScale = mainframe:GetEffectiveScale()
- if effectiveScale then
- vars.onepixelwide = 1/effectiveScale
- end
- --nowI = CreateFrame('Frame',nil,mainframe)
- --nowI:SetFrameLevel(20)
- ns.frames.nowIndicator = mainframe:CreateTexture(nil, 'ARTWORK', nil, draworder.nowI)
- ns.frames.nowIndicator:SetPoint('BOTTOM',mainframe,'BOTTOM')
- ns.frames.nowIndicator:SetPoint('TOPLEFT',mainframe,'TOPLEFT', vars.nowleft, 0)
- ns.frames.nowIndicator:SetWidth(vars.onepixelwide)
- ns.frames.nowIndicator:SetTexture(unpack(self.colors.nowLine))
- if self.config.blendModes.nowLine and type(self.config.blendModes.nowLine) == 'string' then
- ns.frames.nowIndicator:SetBlendMode(self.config.blendModes.nowLine)
- end
- local anchor = self.config.anchor or {'TOPRIGHT', 'EventHorizonHandle', 'BOTTOMRIGHT'}
- if anchor[2]=='EventHorizonHandle' then
- -- Create the handle to reposition the frame.
- handle = CreateFrame('Frame', 'EventHorizonHandle', mainframe)
- handle:SetFrameStrata('HIGH')
- handle:SetWidth(10)
- handle:SetHeight(5)
- handle:EnableMouse(true)
- handle:SetClampedToScreen(1)
- handle:RegisterForDrag('LeftButton')
- handle:SetScript('OnDragStart', function(handle, button) handle:StartMoving() end)
- handle:SetScript('OnDragStop', function(handle)
- handle:StopMovingOrSizing()
- local a,b,c,d,e = handle:GetPoint(1)
- if type(b)=='frame' then
- b=b:GetName()
- end
- EventHorizonDB.point = {a,b,c,d,e}
- end)
- handle:SetMovable(true)
- mainframe:SetPoint(unpack(anchor))
- handle:SetPoint(unpack(EventHorizonDB.point))
- handle.tex = handle:CreateTexture(nil, 'ARTWORK', nil, 7)
- handle.tex:SetAllPoints()
- handle:SetScript('OnEnter',function(frame) frame.tex:SetTexture(1,1,1,1) end)
- handle:SetScript('OnLeave',function(frame) frame.tex:SetTexture(1,1,1,0.1) end)
- handle.tex:SetTexture(1,1,1,0.1)
- if EventHorizonDB.isLocked then
- handle:Hide()
- end
- end
- vars.gcdSpellName = self.config.gcdSpellID and (GetSpellInfo(self.config.gcdSpellID))
- if vars.gcdSpellName and self.config.gcdStyle then
- -- Create the GCD indicator, register cooldown event.
- ns.frames.gcd = mainframe:CreateTexture(nil, 'ARTWORK',nil,draworder.gcd)
- ns.frames.gcd:SetPoint('BOTTOM',mainframe,'BOTTOM')
- ns.frames.gcd:SetPoint('TOP',mainframe,'TOP')
- ns.frames.gcd:Hide()
- if self.config.gcdStyle == 'line' then
- ns.frames.gcd:SetWidth(vars.onepixelwide)
- else
- ns.frames.gcd:SetPoint('LEFT',mainframe,'LEFT', vars.nowleft, 0)
- end
- local gcdColor = self.colors.gcdColor or {.5,.5,.5,.3}
- ns.frames.gcd:SetTexture(unpack(gcdColor))
- if self.config.blendModes.gcdColor and type(self.config.blendModes.gcdColor) == 'string' then
- ns.frames.gcd:SetBlendMode(self.config.blendModes.gcdColor)
- end
- end
- mainframe:SetPoint(unpack(anchor))
- SLASH_EVENTHORIZON1 = '/eventhorizon'
- SLASH_EVENTHORIZON2 = '/ehz'
- SlashCmdList['EVENTHORIZON'] = function(msg)
- local cmd = string.lower(msg)
- local toggle = not(msg) or cmd == ''
- if cmd == 'help' then
- debug'Use "/eventhorizon" or "/ehz" to show or hide EventHorizon.'
- debug'To enable or disable a module, use "/ehz ModuleName". For example, "/ehz redshift".'
- debug'To see a list of currently installed modules and visible bars, use "/ehz status".'
- if anchor[2]=='EventHorizonHandle' then
- debug(' EventHorizon is currently '..(EventHorizonDB.isLocked and 'locked.' or 'movable.'))
- debug(' To '..(EventHorizonDB.isLocked and 'unlock ' or 'lock ')..'EventHorizon, use "/ehz lock".')
- debug' If you are unable see or move EventHorizon, use "/ehz reset".'
- end
- elseif cmd == 'status' then
- print('Installed plugins:')
- for i in pairs(self.modules) do debug(' '..i) end
- print('Visible bars:')
- for i,v in pairs(self.frames.shown) do debug(' '..v.spellname) end
- elseif cmd == 'reset' then
- if anchor[2]=='EventHorizonHandle' then
- debug'Resetting EventHorizon\'s position.'
- EventHorizonHandle:SetPoint(unpack(self.defaultDB.point))
- self:CheckTalents()
- else
- print"The frame is otherwise anchored. Adjust config.anchor in [my]config.lua to move EventHorizon."
- end
- elseif cmd == 'lock' then
- if anchor[2]=='EventHorizonHandle' then
- if EventHorizonHandle:IsShown() then
- EventHorizonHandle:Hide()
- EventHorizonDB.isLocked = true
- else
- EventHorizonHandle:Show()
- EventHorizonDB.isLocked = nil
- end
- print("The frame is now "..(EventHorizonDB.isLocked and 'locked.' or 'unlocked.'))
- else
- print"The frame is otherwise anchored. Adjust config.anchor in [my]config.lua to move EventHorizon."
- end
- elseif self.modules[cmd] then
- self:ToggleModule(string.lower(msg))
- print(string.lower(msg)..' has been turned '..((self.modules[string.lower(msg)].isActive == true) and 'ON' or 'OFF')..'.')
- elseif toggle then
- if self.isActive then
- print('Deactivating EventHorizon. Use "/ehz help" to see what else you can do.')
- self:Deactivate()
- mainframe:UnregisterEvent('PLAYER_TALENT_UPDATE')
- else
- print('Activating EventHorizon. Use "/ehz help" to see what else you can do.')
- self:Activate()
- self:CheckTalents()
- end
- else
- print('Invalid command. Use "/ehz" alone to show or hide EventHorizon, or "/ehz help" to see a list of commands.')
- end
- EventHorizonDB.isActive = self.isActive
- end
- ns.isActive = EventHorizonDB.isActive
- if not EventHorizonDB.isActive then
- self:Deactivate()
- mainframe:UnregisterEvent('PLAYER_TALENT_UPDATE')
- end
- self:CheckRequirements()
- self:LoadModules()
- if not(ns.config.hastedSpellID and type(ns.config.hastedSpellID) == 'table') then
- vars.useOldHaste = true
- end
- if ns.config.nonAffectingHaste then
- if type(ns.config.nonAffectingHaste[1]) == 'number' then
- ns.config.nonAffectingHaste = {ns.config.nonAffectingHaste}
- end
- end
- self.isReady = true
- end
- function ns:ApplyConfig()
- table.wipe(ns.vars.config)
- local config = {}
- local ppc = EventHorizonDBG.profilePerChar[playername] -- EventHorizonDBG.profilePerChar[playername] = 'ProfileName'
- if ppc then
- config = EventHorizonDBG.profiles[ppc] -- EventHorizon.profiles[ProfileName] = {overriddenConfig}
- end
- setmetatable(config,{__index = ns.config}) -- Set non-overridden values to what is in [my]config.lua
- vars.past = -math.abs(config.past) or -3 -- We really don't want config.past to be positive, so negative absolute values work great here.
- vars.future = math.abs(config.future) or 9
- vars.barheight = config.height or 18
- vars.barwidth = config.width or 150
- vars.barspacing = config.spacing or 0
- vars.scale = 1/(vars.future-vars.past)
- vars.bartexture = config.bartexture or 'Interface\\Addons\\EventHorizon\\Smooth'
- vars.texturedbars = config.texturedbars
- vars.texturealpha = config.texturealphamultiplier or 1
- vars.classburn = config.classburn or 0.7
- vars.classalpha = config.classalpha or 0.3
- vars.castLine = config.castLine and ((type(config.castLine) == 'number' and config.castLine) or config.castLine == true and 0) or nil
- vars.nowleft = -vars.past/(vars.future-vars.past)*vars.barwidth-0.5 + (config.hideIcons and 0 or config.height)
- local classcolors = CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS
- self.classcolor = Clone(classcolors[select(2,UnitClass('player'))])
- vars.stackFont = config.stackFont
- vars.stackFontSize = config.stackFontSize
- vars.stackFontColor = config.stackFontColor == true and {1,1,1,1} or config.stackFontColor or {1,1,1,1}
- vars.stackFontShadow = config.stackFontShadow == true and {0,0,0,0.5} or config.stackFontShadow or {0,0,0,0.5}
- vars.stackFontShadowOffset = config.stackFontShadowOffset == true and {1,-1} or config.stackFontShadowOffset or {1,-1}
- for colorid,color in pairs(self.colors) do
- if color[1] == true then
- if color[2] then
- self.colors[colorid] = {self.classcolor.r * color[2], self.classcolor.g * color[2], self.classcolor.b * color[2], color[3] or vars.classalpha} -- For really bad reasons, this took a very long time to get right...
- else
- self.colors[colorid] = {self.classcolor.r, self.classcolor.g, self.classcolor.b, vars.classalpha}
- end
- end
- end
- if vars.texturedbars then
- for colorid,color in pairs(self.colors) do
- if color[4] and not(exemptColors[colorid]) then
- color[4] = vars.texturealpha*color[4]
- end
- end
- end
- local layouts = self.layouts
- layouts.frameline = {
- top = 0,
- bottom = 1,
- }
- local default = layouts.default
- for typeid,layout in pairs(layouts) do
- if typeid~='default' then
- for k,v in pairs(default) do
- if layout[k]==nil then
- layout[k] = v
- end
- end
- end
- layout.texcoords = {0, 1, layout.top, layout.bottom}
- end
- ns:ModuleEvent('ApplyConfig')
- end
- function ns:UpdateConfig()
- if not(self.isReady) then return end
- self:ApplyConfig()
- mainframe:SetScale(self.config.scale or 1)
- local effectiveScale = mainframe:GetEffectiveScale()
- if effectiveScale then
- vars.onepixelwide = 1/effectiveScale
- end
- self:SetupStyleFrame() -- Spawn backdrop frame.
- vars.nowleft = -vars.past/(vars.future-vars.past)*vars.barwidth-0.5 + (ns.config.hideIcons and 0 or ns.config.height)
- --nowI:SetFrameLevel(20)
- ns.frames.nowIndicator:SetPoint('BOTTOM',mainframe,'BOTTOM')
- ns.frames.nowIndicator:SetPoint('TOPLEFT',mainframe,'TOPLEFT', vars.nowleft, 0)
- ns.frames.nowIndicator:SetTexture(unpack(self.colors.nowLine))
- local anchor = self.config.anchor or {'TOPRIGHT', 'EventHorizonHandle', 'BOTTOMRIGHT'}
- if anchor[2]=='EventHorizonHandle' then
- -- Create the handle to reposition the frame.
- handle = handle or CreateFrame('Frame', 'EventHorizonHandle', mainframe)
- handle:SetFrameStrata('HIGH')
- handle:SetWidth(10)
- handle:SetHeight(5)
- handle:EnableMouse(true)
- handle:SetClampedToScreen(1)
- handle:RegisterForDrag('LeftButton')
- handle:SetScript('OnDragStart', function(handle, button) handle:StartMoving() end)
- handle:SetScript('OnDragStop', function(handle)
- handle:StopMovingOrSizing()
- local a,b,c,d,e = handle:GetPoint(1)
- if type(b)=='frame' then
- b=b:GetName()
- end
- EventHorizonDB.point = {a,b,c,d,e}
- end)
- handle:SetMovable(true)
- mainframe:SetPoint(unpack(anchor))
- handle:SetPoint(unpack(EventHorizonDB.point))
- handle.tex = handle:CreateTexture(nil, 'BORDER')
- handle.tex:SetAllPoints()
- handle:SetScript('OnEnter',function(frame) frame.tex:SetTexture(1,1,1,1) end)
- handle:SetScript('OnLeave',function(frame) frame.tex:SetTexture(1,1,1,0.1) end)
- handle.tex:SetTexture(1,1,1,0.1)
- end
- vars.gcdSpellName = self.config.gcdSpellID and (GetSpellInfo(self.config.gcdSpellID))
- if vars.gcdSpellName and self.config.gcdStyle then
- -- Create the GCD indicator, register cooldown event.
- ns.frames.gcd = mainframe:CreateTexture('EventHorizonns.frames.gcd', 'BORDER')
- ns.frames.gcd:SetPoint('BOTTOM',mainframe,'BOTTOM')
- ns.frames.gcd:SetPoint('TOP',mainframe,'TOP')
- ns.frames.gcd:Hide()
- if self.config.gcdStyle == 'line' then
- ns.frames.gcd:SetWidth(vars.onepixelwide)
- else
- ns.frames.gcd:SetPoint('LEFT',mainframe,'LEFT', vars.nowleft, 0)
- end
- local gcdColor = self.colors.gcdColor or {.5,.5,.5,.3}
- ns.frames.gcd:SetTexture(unpack(gcdColor))
- end
- mainframe:SetPoint(unpack(anchor))
- self:SetFrameDimensions()
- end
- local glyphCheck = function ()
- if ns.isActive == true then
- ns:CheckTalents()
- for i,spellframe in pairs(ns.frames.shown) do
- if spellframe.slotID then spellframe:PLAYER_EQUIPMENT_CHANGED(spellframe.slotID) end
- end
- end
- end
- function ns:SetupStyleFrame()
- local c = self.config.backdrop
- if c then
- if not(self.styleframe) then self.styleframe = CreateFrame('Frame',nil,mainframe) end
- else
- if self.styleframe then self.styleframe:Hide() end
- return
- end
- local styleframe = self.styleframe
- local stylebg = self.config.bg or 'Interface\\ChatFrame\\ChatFrameBackground'
- local styleborder = self.config.border or 'Interface\\Tooltips\\UI-Tooltip-Border'
- local stylebgcolor = self.colors.bgcolor or {0,0,0,0.6}
- local stylebordercolor = self.colors.bordercolor or {1,1,1,1}
- local styleinset = self.config.inset or {top = 2, bottom = 2, left = 2, right = 2}
- local stylepadding = self.config.padding or 3
- local styleedge = self.config.edgesize or 8
- styleframe:SetFrameStrata('BACKGROUND')
- styleframe:SetPoint('TOPRIGHT', mainframe, 'TOPRIGHT', stylepadding, stylepadding)
- styleframe:SetPoint('BOTTOMLEFT', mainframe, 'BOTTOMLEFT', -stylepadding, -stylepadding)
- styleframe:SetBackdrop({
- bgFile = stylebg,
- edgeFile = styleborder, tileSize = 0, edgeSize = styleedge,
- insets = styleinset,
- })
- styleframe:SetBackdropColor(unpack(stylebgcolor))
- styleframe:SetBackdropBorderColor(unpack(stylebordercolor))
- end
- function ns:RegisterModule(module,namespace)
- if not(module and namespace) then
- print("Module registration failed. Usage: EventHorizon:RegisterModule(module,namespace)")
- end
- local module = string.lower(module)
- self.modules[module] = namespace
- end
- frame:SetScript('OnEvent', EventHandler)
- frame:RegisterEvent('PLAYER_LOGIN')
- frame.PLAYER_ALIVE = function (self)
- self:SetScript('OnUpdate', UpdateMouseover)
- frame2:SetScript('OnEvent', EventHandler)
- for k,v in pairs(reloadEvents) do
- frame2:RegisterEvent(k)
- frame2[k] = glyphCheck
- end
- if not(ns.isReady) then
- ns:Initialize()
- else
- ns:LoadModules()
- end
- self:UnregisterEvent('PLAYER_ALIVE')
- end
- frame.PLAYER_LOGIN = function (self)
- local talents = GetTalentInfo(1)
- if talents then
- self:UnregisterEvent('PLAYER_LOGIN')
- self:SetScript('OnUpdate', UpdateMouseover)
- frame2:SetScript('OnEvent', EventHandler)
- for k,v in pairs(reloadEvents) do
- frame2:RegisterEvent(k)
- frame2[k] = glyphCheck
- end
- if not(ns.isReady) then
- ns:Initialize()
- else
- ns:LoadModules()
- end
- else
- self:UnregisterEvent('PLAYER_LOGIN')
- self:RegisterEvent('PLAYER_ALIVE')
- end
- end
- mainframe.CLEU_OtherInterestingSpell = mainframe_CLEU_OtherInterestingSpell
- mainframe.UPDATE_SHAPESHIFT_FORM = mainframe_UPDATE_SHAPESHIFT_FORM
- mainframe.SPELL_UPDATE_COOLDOWN = mainframe_SPELL_UPDATE_COOLDOWN
- mainframe.COMBAT_LOG_EVENT_UNFILTERED = mainframe_COMBAT_LOG_EVENT_UNFILTERED
- mainframe.UPDATE_SHAPESHIFT_FORMS = mainframe_UPDATE_SHAPESHIFT_FORM
- mainframe.PLAYER_TALENT_UPDATE = ns.CheckTalents
- mainframe.PLAYER_LEVEL_UP = ns.CheckTalents
- mainframe.PLAYER_TARGET_CHANGED = mainframe_PLAYER_TARGET_CHANGED
- mainframe.UNIT_AURA = mainframe_UNIT_AURA
- SpellFrame.NotInteresting = SpellFrame_NotInteresting
- SpellFrame.AddSegment = SpellFrame_AddSegment
- SpellFrame.AddIndicator = SpellFrame_AddIndicator
- SpellFrame.Remove = SpellFrame_Remove
- SpellFrame.RemoveTicksAfter = SpellFrame_RemoveTicksAfter
- SpellFrame.RemoveChannelTicksAfter = SpellFrame_RemoveChannelTicksAfter
- SpellFrame.OnUpdate = SpellFrame_OnUpdate
- SpellFrame.UpdateDoT = SpellFrame_UpdateDoT
- SpellFrame.Activate = SpellFrame_Activate
- SpellFrame.Deactivate = SpellFrame_Deactivate
- SpellFrame.FindItemInfo = SpellFrame_FindItemInfo
- SpellFrame.UNIT_AURA = SpellFrame_UNIT_AURA
- SpellFrame.UNIT_AURA_refreshable = SpellFrame_UNIT_AURA_refreshable
- SpellFrame.COMBAT_LOG_EVENT_UNFILTERED = SpellFrame_COMBAT_LOG_EVENT_UNFILTERED
- SpellFrame.UNIT_SPELLCAST_SENT = SpellFrame_UNIT_SPELLCAST_SENT
- SpellFrame.UNIT_SPELLCAST_CHANNEL_START = Cast_Start
- SpellFrame.UNIT_SPELLCAST_CHANNEL_UPDATE = Cast_Update
- SpellFrame.UNIT_SPELLCAST_CHANNEL_STOP = Cast_Stop
- SpellFrame.UNIT_SPELLCAST_START = Cast_Start
- SpellFrame.UNIT_SPELLCAST_STOP = Cast_Stop
- SpellFrame.UNIT_SPELLCAST_DELAYED = Cast_Update
- --SpellFrame.PLAYER_TARGET_CHANGED = SpellFrame_PLAYER_TARGET_CHANGED
- --SpellFrame.PLAYER_TARGET_CHANGED_refreshable = SpellFrame_PLAYER_TARGET_CHANGED_refreshable
- SpellFrame.PLAYER_REGEN_ENABLED = SpellFrame_PLAYER_REGEN_ENABLED
- SpellFrame.SPELL_UPDATE_COOLDOWN = SpellFrame_SPELL_UPDATE_COOLDOWN
- SpellFrame.BAG_UPDATE_COOLDOWN = SpellFrame_SPELL_UPDATE_COOLDOWN
- SpellFrame.PLAYER_EQUIPMENT_CHANGED = SpellFrame_PLAYER_EQUIPMENT_CHANGED
- SpellFrame.UPDATE_MOUSEOVER_UNIT = SpellFrame_UPDATE_MOUSEOVER_UNIT
- local Redshift = {}
- Redshift.Check = function (self)
- if EventHorizonDB.redshift.isActive ~= true then
- return Redshift:Disable()
- end
- if not(Redshift.frame) then
- Redshift.frame = CreateFrame("FRAME",nil,UIParent)
- Redshift.frame:SetScript('OnEvent',EventHandler)
- for k,v in pairs(Redshift.Events) do
- if v then
- Redshift.frame:RegisterEvent(k)
- Redshift.frame[k] = Redshift.Check
- end
- end
- end
- local s = Redshift.states
- showState = nil
- local attackable = UnitCanAttack("player","target")
- local targeting = UnitExists("target")
- local focusing = UnitExists("focus")
- local classify = UnitClassification("target")
- local dead = UnitIsDeadOrGhost("target")
- local vehicle = UnitHasVehicleUI("player")
- if(s.showCombat and UnitAffectingCombat("player")) then
- showState = true
- end
- if (s.showFocus and UnitExists("focus")) then
- showState = true
- end
- if targeting then
- if(s.showHelp and not attackable) and not dead then
- showState = true
- end
- if(s.showHarm and attackable) and not dead then
- showState = true
- end
- if(s.showBoss and classify == "worldboss") and not dead then
- showState = true
- end
- end
- if (s.hideVehicle and UnitHasVehicleUI("player")) then
- showState = nil
- end
- if showState then
- vars.visibleFrame = true
- mainframe:Show()
- if EventHorizon_VitalsFrame and s.hideVitals then
- EventHorizon_VitalsFrame:Show()
- end
- else
- vars.visibleFrame = false
- mainframe:Hide()
- if EventHorizon_VitalsFrame and s.hideVitals then
- EventHorizon_VitalsFrame:Hide()
- end
- end
- end
- Redshift.Init = function ()
- local settingsChanged = EventHorizonDB.redshift.lastConfig ~= ns.config.enableRedshift
- EventHorizonDB.redshift.lastConfig = ns.config.enableRedshift
- if settingsChanged then
- local ends = ns.config.enableRedshift and 'enabled' or 'disabled'
- local settingsString = "Redshift has been "..ends.." via config.lua. Ingame settings have been adjusted to match. Use /ehz redshift to enable or disable Redshift as needed."
- EventHorizonDB.redshift.isActive = ns.config.enableRedshift
- end
- local db = EventHorizonDB.redshift.isActive
- if not (db) then return end
- Redshift.states = {}
- Redshift.Events = {
- ["PLAYER_REGEN_DISABLED"] = true,
- ["PLAYER_REGEN_ENABLED"] = true,
- ["PLAYER_TARGET_CHANGED"] = true,
- ["PLAYER_GAINS_VEHICLE_DATA"] = true,
- ["PLAYER_LOSES_VEHICLE_DATA"] = true,
- ["UNIT_ENTERED_VEHICLE"] = true,
- ["UNIT_EXITED_VEHICLE"] = true,
- ["UNIT_ENTERING_VEHICLE"] = true,
- ["UNIT_EXITING_VEHICLE"] = true,
- ["VEHICLE_PASSENGERS_CHANGED"] = true,
- }
- for k,v in pairs(ns.config.Redshift) do
- if v then
- Redshift.states[k] = true
- end
- end
- if (EventHorizonDB.redshift.isActive == true) then Redshift:Check() end
- Redshift.isReady = true
- end
- Redshift.Enable = function (slash)
- if EventHorizonDB.redshift.isActive and not(Redshift.isReady) then
- Redshift:Init()
- Redshift:Check()
- elseif EventHorizonDB.redshift.isActive then
- Redshift:Check()
- end
- if Redshift.frame then Redshift.frame:SetScript('OnEvent',EventHandler) end
- end
- Redshift.Disable = function (slash)
- vars.visibleFrame = true
- if Redshift.frame then Redshift.frame:SetScript('OnEvent',nil) end
- if ns.isActive == true then mainframe:Show() end
- end
- local Lines = {}
- Lines.CreateLines = function ()
- if Lines.frame then return end
- local c = ns.config.Lines
- local db = EventHorizonDB.lines.isActive == true
- if not(c and db) then return
- elseif type(c) == 'number' then c = {c} -- Turn numbers into delicious tables.
- elseif type(c) ~= 'table' then return -- Turn away everything else.
- end
- Lines.frame = CreateFrame('Frame',nil,UIParent)
- Lines.line = {}
- local multicolor
- local color = ns.config.LinesColor
- if color and type(color) == 'table' then
- if type(color[1]) == 'table' then
- multicolor = true -- trying not to further complicate things
- for i,v in ipairs(c) do
- if not(color[i]) then
- color[i] = color[i-1] -- if we have more lines than colors, we need moar colors
- end
- end
- end
- else
- color = {1,1,1,0.5}
- end
- local now = -vars.past/(vars.future-vars.past)*vars.barwidth-0.5 + vars.barheight
- local pps = (vars.barwidth+vars.barheight-now)/vars.future
- for i = 1, #c do
- local seconds = c[i]
- local position = now+(pps*seconds)
- Lines.line[i] = mainframe:CreateTexture(nil,"OVERLAY")
- Lines.line[i]:SetPoint('TOPLEFT', mainframe, 'TOPLEFT', position, 0)
- if multicolor then
- Lines.line[i]:SetTexture(unpack(color[i]))
- else
- Lines.line[i]:SetTexture(unpack(color))
- end
- Lines.line[i]:SetWidth(vars.onepixelwide)
- Lines.line[i]:SetPoint('BOTTOM', mainframe, 'BOTTOM')
- end
- Lines.Enable = function ()
- for i = 1,#Lines.line do
- Lines.line[i]:Show()
- end
- end
- Lines.Disable = function ()
- for i = 1,#Lines.line do
- Lines.line[i]:Hide()
- end
- end
- end
- Lines.Init = function ()
- Lines.CreateLines()
- Lines.isReady = true
- end
- --[[
- local Pulse = {
- cache = {}, -- subframe storage
- frames = {}, -- framerefs
- alwaysLoad = true, -- Flag EH to load the module even when db.isActive ~= true
- }
- Pulse.Enable = function ()
- local cv = ns.config.Pulse
- local sv = ns.db.pulse
- local int = ns.config.PulseIntensity
- local fps = ns.config.PulseFPS
- if not(fps) or (type(fps) ~= 'number' or fps == 0) then
- fps = ns.defaultconfig.PulseFPS
- end
- if not Pulse.frame then
- Pulse.frame = CreateFrame('Frame',nil,mainframe)
- end
- Pulse.duration = (cv and sv.isActive) and ((cv == true or type(cv) ~= 'number') and ns.defaultconfig.Pulse or type(cv) == 'number' and cv)
- Pulse.intensity = int and (type(int) == 'number' and int > 0 and int) or ns.defaultconfig.PulseIntensity
- Pulse.TTL = (1000/fps)/1000
- if Pulse.duration and not(Pulse.framesCreated) then
- local ehf = EventHorizon.frames.frames
- -- for k,v in pairs(ns.frames.frames) do print(k,v) end
- for k,bar in pairs(ns.frames.frames) do -- Use frametable since we want actual bar refs. Don't use ipairs here (will need to fix in other places, likely), as it won't fully iterate.
- -- local bar = ehf[i]
- if bar and bar.cooldown then
- local temp = {
- spellframe = bar,
- ['SPELL_UPDATE_COOLDOWN'] = true,
- }
- table.insert(Pulse.frames,temp)
- elseif bar and (bar.slotID or bar.internalcooldown) then -- Check for slotID first, since it doesn't always use internalcooldown
- local temp = {
- spellframe = bar,
- ['UNIT_AURA'] = true,
- }
- table.insert(Pulse.frames,temp)
- end
- end
- Pulse.framesCreated = true
- end
- Pulse.frame:SetScript('OnEvent',Pulse.OnEvent)
- Pulse.frame:RegisterEvent('UNIT_AURA')
- Pulse.frame:RegisterEvent('SPELL_UPDATE_COOLDOWN')
- end
- Pulse.Disable = function ()
- Pulse.duration = nil
- end
- Pulse.OnFlash = function (self,elapsed)
- self.TSLU = self.TSLU + elapsed
- while self.TSLU >= Pulse.TTL do
- self.current = self.current and (self.current - self.TSLU) or Pulse.duration
- self.alpha = self.current >= 0 and self.current/(Pulse.duration*Pulse.intensity) or 0
- self.tex:SetAlpha(self.alpha)
- self.TSLU = self.TSLU - Pulse.TTL
- if self.current <= 0 then
- self:SetScript('OnUpdate',nil)
- self.current = nil
- self.alpha = nil
- print('clearing onupdates')
- end
- end
- end
- Pulse.OnAura = function (self,elapsed)
- self.remaining = self.remaining - elapsed
- if self.current and self.alpha then -- finish off any remaining pulse
- self.TSLU = self.TSLU + elapsed
- while self.TSLU >= Pulse.TTL do
- self.current = self.current and (self.current - self.TSLU) or Pulse.duration
- self.alpha = self.current >= 0 and self.current/(Pulse.duration*Pulse.intensity) or 0
- self.tex:SetAlpha(self.alpha)
- self.TSLU = self.TSLU - Pulse.TTL
- if self.current <= 0 then
- self.current = nil
- self.alpha = nil
- end
- end
- end
- if self.remaining <= 0 and Pulse.duration then
- self.activeCD = nil
- self.remaining = nil
- self.TSLU = 0
- self:SetAllPoints(self.parent)
- self.tex:SetAllPoints(self)
- print('setting Pulse.OnFlash')
- self:SetScript('OnUpdate',Pulse.OnFlash)
- elseif self.remaining <= 0 then
- self.activeCD = nil
- self.remaining = nil
- self:SetScript('OnUpdate',nil)
- end
- end
- Pulse.OnEvent = function (self,event,unit)
- if event == 'UNIT_AURA' and unit ~= 'player' then return end
- for i = 1,#Pulse.frames do
- local frame = Pulse.frames[i]
- local f = Pulse.frames[i].spellframe
- if f then
- local icd = f.internalcooldown
- local cdTime
- local apply
- local now = GetTime()
- if icd and icd == true then
- icd = nil
- end
- if icd and event == 'UNIT_AURA' then
- local _,_,_,_,_,_,expirationTime,active = f.AuraFunction('player',f.auraname)
- local activeCD = frame.activeCD
- if active and expirationTime and (frame.flash and not(frame.flash.activeCD) or not(frame.flash)) then
- apply = true
- frame.activeCD = true
- cdTime = f.internalcooldown
- local start = expirationTime
- local stop = now + f.internalcooldown
- if start > stop then
- start = now
- end
- f:AddSegment('cooldown', 'cooldown', start, stop)
- end
- elseif event == 'SPELL_UPDATE_COOLDOWN' and not(icd) then
- local start, duration, enabled = f.CooldownFunction(f.cooldownID or f.spellname)
- local onCooldown = enabled == 1 and start ~= duration and start > 0 and duration > 1.5 -- Check duration against GCD to ensure we're not pulsing every time the char does something
- cdTime = duration
- if onCooldown and not(frame.activeCD) then
- apply = true
- print(onCooldown,frame.activeCD,start,duration,enabled)
- elseif (frame.flash and frame.flash.remaining) and not(onCooldown) then -- cooldown expired before pulse went off
- frame.flash.remaining = 0 -- flash at next opportunity
- --print'flash'
- elseif (frame.flash and frame.flash.remaining) and (frame.flash.remaining > (start+duration-now+1)) then -- HOPEFULLY this will catch elemental shaman 2t10.
- frame.flash.remaining = start+duration-now
- end
- frame.activeCD = onCooldown
- end
- if apply and cdTime and Pulse.duration then -- check for fresh application, make sure a cooldown time exists, and don't do anything if pulses are disabled
- if not(frame.flash) then
- frame.flash = CreateFrame('Frame',nil,f)
- frame.flash.tex = frame.flash:CreateTexture(nil,'BACKGROUND')
- frame.flash.tex:SetTexture(vars.texturedbars and vars.bartexture or unpack{1,1,1,1})
- frame.flash.tex:SetAlpha(0)
- frame.flash.TSLU = 0
- end
- frame.flash.parent = f
- frame.flash.TSLU = (frame.flash.current and frame.flash.alpha) and frame.flash.TSLU or 0
- frame.flash.remaining = cdTime
- frame.flash.activeCD = true
- frame.flash:SetScript('OnUpdate',Pulse.OnAura)
- end
- end
- end
- end
- Pulse.Init = function ()
- if Pulse.frame then return end
- Pulse:Enable()
- Pulse.isReady = true
- end
- ]]--
- ns:RegisterModule('lines',Lines)
- ns:RegisterModule('redshift',Redshift)
- --ns:RegisterModule('pulse',Pulse)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement