| 
Nenue@6
 | 
     1 --- Turok
 | 
| 
Nenue@6
 | 
     2 -- Castbar.lua
 | 
| 
Nenue@6
 | 
     3 -- Created: 12/4/2015 11:17 PM
 | 
| 
Nenue@6
 | 
     4 -- @file-author@
 | 
| 
Nenue@6
 | 
     5 -- @project-revision@ @project-hash@
 | 
| 
Nenue@6
 | 
     6 -- @file-revision@ @file-hash@
 | 
| 
Nenue@6
 | 
     7 -- Deals with casting events and works the castingbar interface
 | 
| 
Nenue@6
 | 
     8 local print, tostring, tonumber, rep, pairs, min, format, unpack, select, strpad = print, tostring, tonumber, string.rep, pairs, math.min, string.format, unpack, select, string.rep
 | 
| 
Nenue@6
 | 
     9 local GetTime, UnitCastingInfo, UnitChannelInfo, GetSpellInfo, GetSpellTabInfo = GetTime, UnitCastingInfo, UnitChannelInfo, GetSpellInfo, GetSpellTabInfo
 | 
| 
Nenue@6
 | 
    10 local floor = math.floor
 | 
| 
Nenue@9
 | 
    11 local T, _G = Turok, _G
 | 
| 
Nenue@6
 | 
    12 local db
 | 
| 
Nenue@6
 | 
    13 local PING_CEILING = 190 -- transpacific
 | 
| 
Nenue@6
 | 
    14 local PING_MIDLINE = 100
 | 
| 
Nenue@6
 | 
    15 local PING_FLOOR = 10 -- transcontinental
 | 
| 
Nenue@6
 | 
    16 --@debug
 | 
| 
Nenue@6
 | 
    17 local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
 | 
| 
Nenue@6
 | 
    18 local print = function(...)
 | 
| 
Nenue@6
 | 
    19   if _G.Devian and _G.DevianDB.workspace ~= 1 then
 | 
| 
Nenue@6
 | 
    20     _G.print('Tek', ...)
 | 
| 
Nenue@6
 | 
    21   end
 | 
| 
Nenue@6
 | 
    22 end
 | 
| 
Nenue@9
 | 
    23 local uprint = function(...)
 | 
| 
Nenue@9
 | 
    24   if _G.Devian and _G.DevianDB.workspace ~= 1 then
 | 
| 
Nenue@9
 | 
    25     _G.print('Update', ...)
 | 
| 
Nenue@9
 | 
    26   end
 | 
| 
Nenue@9
 | 
    27 end
 | 
| 
Nenue@9
 | 
    28 local mprint = function(...)
 | 
| 
Nenue@9
 | 
    29   if _G.Devian and _G.DevianDB.workspace ~= 1 then
 | 
| 
Nenue@9
 | 
    30     _G.print('Main', ...)
 | 
| 
Nenue@9
 | 
    31   end
 | 
| 
Nenue@9
 | 
    32 end
 | 
| 
Nenue@6
 | 
    33 
 | 
| 
Nenue@6
 | 
    34 local EVENT_COLOR = '|cFF44FF44'
 | 
| 
Nenue@6
 | 
    35 local EVENT_COLOR2 = '|cFF88FF88'
 | 
| 
Nenue@6
 | 
    36 local DATA_COLOR = '|cFFDD77DD'
 | 
| 
Nenue@6
 | 
    37 --@end-debug@
 | 
| 
Nenue@6
 | 
    38 
 | 
| 
Nenue@6
 | 
    39 local mod = T:NewModule("Tek")
 | 
| 
Nenue@6
 | 
    40 function mod:OnInitialize()
 | 
| 
Nenue@6
 | 
    41   self.db = T.db.tek
 | 
| 
Nenue@6
 | 
    42   self.castbar = {}
 | 
| 
Nenue@6
 | 
    43   self.UNIT_SPELLCAST_SENT          = self.SpellCastRequest
 | 
| 
Nenue@6
 | 
    44   self.UNIT_SPELLCAST_START           = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    45   self.UNIT_SPELLCAST_DELAYED         = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    46   self.UNIT_SPELLCAST_SUCCEEDED       = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    47   self.UNIT_SPELLCAST_STOP            = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    48   self.UNIT_SPELLCAST_FAILED          = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    49   self.UNIT_SPELLCAST_INTERRUPTED     = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    50   self.UNIT_SPELLCAST_CHANNEL_START   = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    51   self.UNIT_SPELLCAST_CHANNEL_STOP    = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    52   self.UNIT_SPELLCAST_CHANNEL_UPDATE  = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    53   self.UNIT_SPELLCAST_INTERRUPTIBLE   = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    54   self.UNIT_SPELLCAST_UNINTERRUPTIBLE = self.SpellCastEvent
 | 
| 
Nenue@6
 | 
    55 end
 | 
| 
Nenue@6
 | 
    56 
 | 
| 
Nenue@6
 | 
    57 --- events & units
 | 
| 
Nenue@6
 | 
    58 local TRACKED_UNITS = {'player', 'target', 'focus', 'pet'}
 | 
| 
Nenue@6
 | 
    59 local FADE_OUT_TIME, FADE_IN_TIME = 1, .2
 | 
| 
Nenue@6
 | 
    60 
 | 
| 
Nenue@6
 | 
    61 local TEXTURE_SUFFIX = {
 | 
| 
Nenue@6
 | 
    62   ['CHANNEL_START'] = '_channeling',
 | 
| 
Nenue@6
 | 
    63   ['CHANNEL_UPDATE'] = '_channeling',
 | 
| 
Nenue@6
 | 
    64   ['CHANNEL_STOPPED'] = '_channeling',
 | 
| 
Nenue@6
 | 
    65   ['START'] = '_casting',
 | 
| 
Nenue@6
 | 
    66   ['INTERRUPTED'] = '_interrupted',
 | 
| 
Nenue@6
 | 
    67   ['SUCCEEDED'] = '_finished',
 | 
| 
Nenue@6
 | 
    68 }
 | 
| 
Nenue@6
 | 
    69 
 | 
| 
Nenue@6
 | 
    70 function mod:OnEnable()
 | 
| 
Nenue@6
 | 
    71   db = self.db
 | 
| 
Nenue@6
 | 
    72   -- setup castingbar frames
 | 
| 
Nenue@6
 | 
    73   local c = self.castbar
 | 
| 
Nenue@6
 | 
    74   for _, unit in pairs(TRACKED_UNITS) do
 | 
| 
Nenue@6
 | 
    75     local cdb = db[unit]
 | 
| 
Nenue@6
 | 
    76     --@debug@
 | 
| 
Nenue@6
 | 
    77     print(DATA_COLOR .. unit .. '|r castbar creation')--@end-debug@
 | 
| 
Nenue@6
 | 
    78 
 | 
| 
Nenue@6
 | 
    79     -- Set frames
 | 
| 
Nenue@6
 | 
    80     local fn = 'Tek' .. unit .. 'CastBar'
 | 
| 
Nenue@6
 | 
    81     c[unit] = CreateFrame('Frame', fn, _G[cdb.parent], 'TurokCastingBar')
 | 
| 
Nenue@6
 | 
    82 
 | 
| 
Nenue@6
 | 
    83     local pc = c[unit]
 | 
| 
Nenue@6
 | 
    84     T.SetFrameLayout(pc, cdb)
 | 
| 
Nenue@6
 | 
    85     T.SetTextureLayout(pc.icon, cdb.icon or db.icon)
 | 
| 
Nenue@6
 | 
    86     T.SetStatusTextures(pc, cdb.statusbar or db.statusbar)
 | 
| 
Nenue@6
 | 
    87 
 | 
| 
Nenue@6
 | 
    88     if unit == 'player' then
 | 
| 
Nenue@6
 | 
    89       T.SetFontLayout(pc.ping, db.ping)
 | 
| 
Nenue@6
 | 
    90       T.SetFontLayout(pc.downtime, db.downtime)
 | 
| 
Nenue@6
 | 
    91       pc.pingbar:ClearAllPoints()
 | 
| 
Nenue@6
 | 
    92       pc.pingbar:SetPoint('TOPRIGHT', pc.background, 'TOPRIGHT', 0, 0)
 | 
| 
Nenue@6
 | 
    93       pc.pingbar:SetHeight(pc.background:GetHeight())
 | 
| 
Nenue@6
 | 
    94     else
 | 
| 
Nenue@6
 | 
    95       if pc.interrupt then
 | 
| 
Nenue@6
 | 
    96         pc.interrupt:SetSize(pc.icon.size*3, pc.icon.size* 3)
 | 
| 
Nenue@6
 | 
    97       end
 | 
| 
Nenue@6
 | 
    98 
 | 
| 
Nenue@6
 | 
    99     end
 | 
| 
Nenue@6
 | 
   100 
 | 
| 
Nenue@6
 | 
   101     T.SetFontLayout(pc.casttime, cdb.casttime or db.casttime)
 | 
| 
Nenue@6
 | 
   102     T.SetFontLayout(pc.spelltext, cdb.spelltext or db.spelltext)
 | 
| 
Nenue@6
 | 
   103 
 | 
| 
Nenue@6
 | 
   104     pc:SetAlpha(0)
 | 
| 
Nenue@6
 | 
   105     pc.last = nil
 | 
| 
Nenue@6
 | 
   106     pc.sent = {}
 | 
| 
Nenue@6
 | 
   107     pc.unit = unit
 | 
| 
Nenue@6
 | 
   108     pc.SetSpell = self.SetSpell
 | 
| 
Nenue@6
 | 
   109     pc.SetState = self.SetState
 | 
| 
Nenue@6
 | 
   110     pc.Update = self.Update
 | 
| 
Nenue@6
 | 
   111   end
 | 
| 
Nenue@6
 | 
   112 
 | 
| 
Nenue@6
 | 
   113 
 | 
| 
Nenue@6
 | 
   114   -- kill default casting bar
 | 
| 
Nenue@6
 | 
   115   -- T.cbscripts = {CastingBarFrame:GetScript('OnUpdate'), CastingBarFrame:GetScript('OnEvent')}
 | 
| 
Nenue@6
 | 
   116   CastingBarFrame:SetScript('OnUpdate', nil)
 | 
| 
Nenue@6
 | 
   117   CastingBarFrame:SetScript('OnEvent', nil)
 | 
| 
Nenue@6
 | 
   118   CastingBarFrame:Hide()
 | 
| 
Nenue@6
 | 
   119   PetCastingBarFrame:SetScript('OnUpdate', nil)
 | 
| 
Nenue@6
 | 
   120   PetCastingBarFrame:SetScript('OnEvent', nil)
 | 
| 
Nenue@6
 | 
   121   PetCastingBarFrame:Hide()
 | 
| 
Nenue@6
 | 
   122 end
 | 
| 
Nenue@6
 | 
   123 
 | 
| 
Nenue@6
 | 
   124 function mod:UpdateLocked()
 | 
| 
Nenue@6
 | 
   125     for k, v in pairs(self.castbar) do
 | 
| 
Nenue@6
 | 
   126       if T.unlocked then
 | 
| 
Nenue@6
 | 
   127         local name, texture, offset, numSpells = GetSpellTabInfo(T.specPage)
 | 
| 
Nenue@6
 | 
   128         v.value = offset
 | 
| 
Nenue@6
 | 
   129         v.duration = numSpells
 | 
| 
Nenue@6
 | 
   130         v.spelltext:SetText(k)
 | 
| 
Nenue@6
 | 
   131         v.icon:SetTexture(texture)
 | 
| 
Nenue@6
 | 
   132         v:SetAlpha(1)
 | 
| 
Nenue@6
 | 
   133         v:Show()
 | 
| 
Nenue@6
 | 
   134         v:EnableMouse(true)
 | 
| 
Nenue@6
 | 
   135         v:SetMovable(true)
 | 
| 
Nenue@6
 | 
   136         v:RegisterForDrag("LeftButton")
 | 
| 
Nenue@6
 | 
   137         v:SetScript('OnDragStart', function(self)  self:StartMoving() end)
 | 
| 
Nenue@6
 | 
   138         v:SetScript('OnDragStop', function(self) self:StopMovingOrSizing() end)
 | 
| 
Nenue@6
 | 
   139       else
 | 
| 
Nenue@6
 | 
   140 
 | 
| 
Nenue@6
 | 
   141         v:SetScript('OnDragStart', nil)
 | 
| 
Nenue@6
 | 
   142         v:SetScript('OnDragStop', nil)
 | 
| 
Nenue@6
 | 
   143         v:EnableMouse(false)
 | 
| 
Nenue@6
 | 
   144         v:SetMovable(false)
 | 
| 
Nenue@6
 | 
   145 
 | 
| 
Nenue@6
 | 
   146         print('Saving bar coordinates post unlock')
 | 
| 
Nenue@6
 | 
   147 
 | 
| 
Nenue@6
 | 
   148         db[k].x = v:GetLeft()
 | 
| 
Nenue@6
 | 
   149         db[k].y = v:GetTop()
 | 
| 
Nenue@6
 | 
   150         db[k].anchor = 'BOTTOMLEFT'
 | 
| 
Nenue@6
 | 
   151         db[k].anchorTo = 'BOTTOMLEFT'
 | 
| 
Nenue@6
 | 
   152         db[k].parent = 'UIParent'
 | 
| 
Nenue@6
 | 
   153       end
 | 
| 
Nenue@6
 | 
   154     end
 | 
| 
Nenue@6
 | 
   155 end
 | 
| 
Nenue@6
 | 
   156 
 | 
| 
Nenue@6
 | 
   157 --- Store spell requests for use in tracking lag time
 | 
| 
Nenue@6
 | 
   158 function mod:SpellCastRequest(e, unit, spellName, rank, target, castID)
 | 
| 
Nenue@6
 | 
   159   print('|cFFFF4400Request sent:|r ', spellName, castID, target)
 | 
| 
Nenue@6
 | 
   160   self.castbar.player.sent[castID] = {
 | 
| 
Nenue@6
 | 
   161     spellName = spellName,
 | 
| 
Nenue@6
 | 
   162     castID = castID,
 | 
| 
Nenue@6
 | 
   163     sendTime = GetTime()*1000,
 | 
| 
Nenue@6
 | 
   164   }
 | 
| 
Nenue@6
 | 
   165 end
 | 
| 
Nenue@6
 | 
   166 
 | 
| 
Nenue@6
 | 
   167 --- Handle events pertaining to a cast bar
 | 
| 
Nenue@6
 | 
   168 function mod:SpellCastEvent(event, unit, ...)
 | 
| 
Nenue@6
 | 
   169   if not self.castbar[unit] then
 | 
| 
Nenue@6
 | 
   170     return
 | 
| 
Nenue@6
 | 
   171   end
 | 
| 
Nenue@6
 | 
   172 
 | 
| 
Nenue@6
 | 
   173   local u = T.unit[unit]
 | 
| 
Nenue@6
 | 
   174   local c = self.castbar[unit]
 | 
| 
Nenue@6
 | 
   175 
 | 
| 
Nenue@6
 | 
   176   --- doubling as an invocation source test
 | 
| 
Nenue@6
 | 
   177   local spellName, rank, castID, spellID = ...
 | 
| 
Nenue@6
 | 
   178 
 | 
| 
Nenue@6
 | 
   179   local channelinfo = T.unit[unit].channeling
 | 
| 
Nenue@6
 | 
   180   local castinginfo = T.unit[unit].casting
 | 
| 
Nenue@6
 | 
   181   local sendq = c.sent
 | 
| 
Nenue@6
 | 
   182   local castd = c.last
 | 
| 
Nenue@6
 | 
   183   local timestamp = GetTime()*1000
 | 
| 
Nenue@6
 | 
   184 
 | 
| 
Nenue@6
 | 
   185   --todo: remove truncation
 | 
| 
Nenue@6
 | 
   186   local e = event:match("UNIT_SPELLCAST_([%a_]+)")
 | 
| 
Nenue@6
 | 
   187   print(GetTime(), '|cFFFF8747'..e..(strpad(' ',12-#e))..'|r |cFFDDFF00#'..tostring(castID)..'|r', spellName, spellID)
 | 
| 
Nenue@6
 | 
   188 
 | 
| 
Nenue@6
 | 
   189   c.channeling = channelinfo and channelinfo[1] or nil
 | 
| 
Nenue@6
 | 
   190   c.casting    = castinginfo and castinginfo[1] or nil
 | 
| 
Nenue@6
 | 
   191   if c.channeling then
 | 
| 
Nenue@6
 | 
   192     -- {name, subText, text, texture, startTime, endTime, isTradeSkill, notInterruptible}
 | 
| 
Nenue@6
 | 
   193     c.startTime = channelinfo[5]
 | 
| 
Nenue@6
 | 
   194     c.endTime = channelinfo[6]
 | 
| 
Nenue@6
 | 
   195     c.nonInterruptible = channelinfo[8]
 | 
| 
Nenue@6
 | 
   196   elseif c.casting then
 | 
| 
Nenue@6
 | 
   197     --name, subText, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible
 | 
| 
Nenue@6
 | 
   198     c.startTime = castinginfo[5]
 | 
| 
Nenue@6
 | 
   199     c.endTime = castinginfo[6]
 | 
| 
Nenue@6
 | 
   200     c.castID = castinginfo[8]
 | 
| 
Nenue@6
 | 
   201     c.nonInterruptible = castinginfo[9]
 | 
| 
Nenue@6
 | 
   202   else
 | 
| 
Nenue@6
 | 
   203     print('  |cFFFF7700internal data was nil|r')
 | 
| 
Nenue@6
 | 
   204   end
 | 
| 
Nenue@6
 | 
   205 
 | 
| 
Nenue@6
 | 
   206   --- process the "event"
 | 
| 
Nenue@6
 | 
   207   local setSpell, setState
 | 
| 
Nenue@6
 | 
   208   if e == 'START' then
 | 
| 
Nenue@6
 | 
   209     setSpell = true
 | 
| 
Nenue@6
 | 
   210     setState = true
 | 
| 
Nenue@6
 | 
   211 
 | 
| 
Nenue@6
 | 
   212     -- player data calculations
 | 
| 
Nenue@6
 | 
   213     if unit == 'player' then
 | 
| 
Nenue@6
 | 
   214       if sendq[castID] and sendq[castID].spellName == spellName then
 | 
| 
Nenue@6
 | 
   215         local sent = sendq[castID]
 | 
| 
Nenue@6
 | 
   216         print('  |cFF00AAFFmatched:|r', sent.spellName, castID)
 | 
| 
Nenue@6
 | 
   217         c.pingTime = c.startTime - sent.sendTime
 | 
| 
Nenue@6
 | 
   218         print('    ping:', c.pingTime)
 | 
| 
Nenue@6
 | 
   219         for cid, cdata in pairs(sendq) do
 | 
| 
Nenue@6
 | 
   220           if cdata.sendTime <= sent.sendTime then
 | 
| 
Nenue@6
 | 
   221             --print('    forgetting #'..cdata.sendTime, cid, cdata.spellName)
 | 
| 
Nenue@6
 | 
   222             sendq[cid] = nil
 | 
| 
Nenue@6
 | 
   223           end
 | 
| 
Nenue@6
 | 
   224         end
 | 
| 
Nenue@6
 | 
   225 
 | 
| 
Nenue@6
 | 
   226         if castd ~= nil then
 | 
| 
Nenue@6
 | 
   227           print('   downtime calc hit')
 | 
| 
Nenue@6
 | 
   228           c.downTime = timestamp - castd.endTime
 | 
| 
Nenue@6
 | 
   229           castd = nil
 | 
| 
Nenue@6
 | 
   230         else
 | 
| 
Nenue@6
 | 
   231           c.downTime = nil
 | 
| 
Nenue@6
 | 
   232         end
 | 
| 
Nenue@6
 | 
   233         c.castID = castID
 | 
| 
Nenue@6
 | 
   234       end
 | 
| 
Nenue@6
 | 
   235     end
 | 
| 
Nenue@6
 | 
   236   elseif e == 'CHANNEL_START' or e == 'CHANNEL_UPDATE' then
 | 
| 
Nenue@6
 | 
   237     setSpell = true
 | 
| 
Nenue@6
 | 
   238     setState = true
 | 
| 
Nenue@6
 | 
   239     c.event = e
 | 
| 
Nenue@6
 | 
   240 
 | 
| 
Nenue@6
 | 
   241   elseif e == 'STOP' then
 | 
| 
Nenue@6
 | 
   242     setState = true
 | 
| 
Nenue@6
 | 
   243     c.casting = nil
 | 
| 
Nenue@6
 | 
   244     castd = {
 | 
| 
Nenue@6
 | 
   245       spellName = spellName,
 | 
| 
Nenue@6
 | 
   246       spellID = spellID,
 | 
| 
Nenue@6
 | 
   247       castID = castID,
 | 
| 
Nenue@6
 | 
   248       endTime = timestamp,
 | 
| 
Nenue@6
 | 
   249     }
 | 
| 
Nenue@6
 | 
   250     print('    |cFFFFFF00found', timestamp, spellName)
 | 
| 
Nenue@6
 | 
   251 
 | 
| 
Nenue@6
 | 
   252   elseif e == 'CHANNEL_STOP' then
 | 
| 
Nenue@6
 | 
   253     setState = true
 | 
| 
Nenue@6
 | 
   254     c.channeling = nil
 | 
| 
Nenue@6
 | 
   255     castd = {
 | 
| 
Nenue@6
 | 
   256       spellName = spellName,
 | 
| 
Nenue@6
 | 
   257       spellID = spellID,
 | 
| 
Nenue@6
 | 
   258       castID = castID,
 | 
| 
Nenue@6
 | 
   259       endTime = timestamp,
 | 
| 
Nenue@6
 | 
   260     }
 | 
| 
Nenue@6
 | 
   261     print('    |cFFFF0088found', timestamp, spellName)
 | 
| 
Nenue@6
 | 
   262 
 | 
| 
Nenue@6
 | 
   263   elseif e == 'SUCCEEDED'  then
 | 
| 
Nenue@6
 | 
   264     if c.spellName == spellName and not c.channeling then
 | 
| 
Nenue@6
 | 
   265       setState = true
 | 
| 
Nenue@6
 | 
   266       print('      |cFFFF4400',c.spellName,'=',spellName,' pushing event', e)
 | 
| 
Nenue@6
 | 
   267     end
 | 
| 
Nenue@6
 | 
   268     -- if there are 'send' args when this fires, it means it's an instant cast
 | 
| 
Nenue@6
 | 
   269     if sendq[castID] and sendq[castID].spellName == spellName then
 | 
| 
Nenue@6
 | 
   270       castd = {
 | 
| 
Nenue@6
 | 
   271         spellName = spellName,
 | 
| 
Nenue@6
 | 
   272         spellID = spellID,
 | 
| 
Nenue@6
 | 
   273         castID = castID,
 | 
| 
Nenue@6
 | 
   274         endTime = timestamp,
 | 
| 
Nenue@6
 | 
   275       }
 | 
| 
Nenue@6
 | 
   276       print('    |cFFFFAA00found', timestamp, spellName)
 | 
| 
Nenue@6
 | 
   277     end
 | 
| 
Nenue@6
 | 
   278 
 | 
| 
Nenue@6
 | 
   279   elseif e =='FAILED' then
 | 
| 
Nenue@6
 | 
   280     if spellName == c.spellName and not c.channeling then
 | 
| 
Nenue@6
 | 
   281       setState = true
 | 
| 
Nenue@6
 | 
   282     end
 | 
| 
Nenue@6
 | 
   283 
 | 
| 
Nenue@6
 | 
   284   elseif e == 'INTERRUPTED' then
 | 
| 
Nenue@6
 | 
   285     setState = true
 | 
| 
Nenue@6
 | 
   286 
 | 
| 
Nenue@6
 | 
   287   end
 | 
| 
Nenue@6
 | 
   288 
 | 
| 
Nenue@6
 | 
   289 
 | 
| 
Nenue@6
 | 
   290 
 | 
| 
Nenue@6
 | 
   291 
 | 
| 
Nenue@6
 | 
   292   if setSpell then
 | 
| 
Nenue@6
 | 
   293     print('      |cFF44FF00setting spell', spellName)
 | 
| 
Nenue@6
 | 
   294   end
 | 
| 
Nenue@6
 | 
   295   if setState then
 | 
| 
Nenue@6
 | 
   296     print('      |cFFFF4400pushing event', e)
 | 
| 
Nenue@6
 | 
   297   end
 | 
| 
Nenue@6
 | 
   298 
 | 
| 
Nenue@6
 | 
   299   if setSpell then
 | 
| 
Nenue@6
 | 
   300     c:SetSpell(e)
 | 
| 
Nenue@6
 | 
   301   end
 | 
| 
Nenue@6
 | 
   302   if setState then
 | 
| 
Nenue@6
 | 
   303     c:SetState(e)
 | 
| 
Nenue@6
 | 
   304   end
 | 
| 
Nenue@6
 | 
   305 end
 | 
| 
Nenue@6
 | 
   306 
 | 
| 
Nenue@6
 | 
   307 
 | 
| 
Nenue@6
 | 
   308 --- Sets all the static elements of the casting bar, such as config values, icon texture, and name
 | 
| 
Nenue@6
 | 
   309 function mod.SetSpell(c, event)
 | 
| 
Nenue@6
 | 
   310   local _
 | 
| 
Nenue@6
 | 
   311   local time, alpha = GetTime(), c:GetAlpha()
 | 
| 
Nenue@6
 | 
   312   local u, cdb  = T.unit[c.unit], c.db
 | 
| 
Nenue@6
 | 
   313 
 | 
| 
Nenue@6
 | 
   314   c.stopped = nil
 | 
| 
Nenue@6
 | 
   315   c.stopping = nil
 | 
| 
Nenue@6
 | 
   316   print('New spell:', c.spellName)
 | 
| 
Nenue@6
 | 
   317   --- use only internal info
 | 
| 
Nenue@6
 | 
   318   local data = (event == 'CHANNEL_START' or event == 'CHANNEL_UPDATE' or event == 'CHANNEL_STOP') and u.channeling or u.casting
 | 
| 
Nenue@6
 | 
   319   local spellName, rank, displayName, texture, startTime, endTime, isTradeSkill, castID, nonInterruptible = unpack(data)
 | 
| 
Nenue@6
 | 
   320 
 | 
| 
Nenue@6
 | 
   321 
 | 
| 
Nenue@6
 | 
   322   if spellName == nil then
 | 
| 
Nenue@6
 | 
   323     print("  Can't do arithmetic, no data.")
 | 
| 
Nenue@6
 | 
   324   else
 | 
| 
Nenue@6
 | 
   325     print(cText("  Arithmetic vars:"), cNum(startTime), cNum(endTime))
 | 
| 
Nenue@6
 | 
   326   end
 | 
| 
Nenue@6
 | 
   327 
 | 
| 
Nenue@6
 | 
   328          c.spellName = spellName
 | 
| 
Nenue@6
 | 
   329             c.castID = castID or 0
 | 
| 
Nenue@6
 | 
   330               c.rank = rank
 | 
| 
Nenue@6
 | 
   331        c.displayName = displayName
 | 
| 
Nenue@6
 | 
   332            c.texture = texture
 | 
| 
Nenue@6
 | 
   333   c.nonInterruptible = nonInterruptible
 | 
| 
Nenue@6
 | 
   334       c.isTradeSkill = isTradeSkill
 | 
| 
Nenue@6
 | 
   335            c.endTime = endTime   or 0
 | 
| 
Nenue@6
 | 
   336          c.startTime = startTime or 0
 | 
| 
Nenue@6
 | 
   337           c.duration = c.endTime - c.startTime
 | 
| 
Nenue@6
 | 
   338 
 | 
| 
Nenue@6
 | 
   339   if c.unit == 'player' then
 | 
| 
Nenue@6
 | 
   340     if c.pingTime then
 | 
| 
Nenue@6
 | 
   341       print('     ping',c.pingTime, endTime, startTime, c.duration)
 | 
| 
Nenue@6
 | 
   342       local draw_dist = (c.pingTime / c.duration) * (c.fill_width)
 | 
| 
Nenue@6
 | 
   343       if draw_dist > c.fill_width then
 | 
| 
Nenue@6
 | 
   344         draw_dist = c.fill_width
 | 
| 
Nenue@6
 | 
   345       end
 | 
| 
Nenue@6
 | 
   346       print('SET AND SHOW PING ', c.pingTime,'on', c.pingbar:GetName())
 | 
| 
Nenue@6
 | 
   347       c.pingbar:SetWidth(draw_dist)
 | 
| 
Nenue@6
 | 
   348       c.pingbar:Show()
 | 
| 
Nenue@6
 | 
   349 
 | 
| 
Nenue@6
 | 
   350       local rv = c.pingTime - PING_FLOOR
 | 
| 
Nenue@6
 | 
   351       local rr = PING_MIDLINE - PING_FLOOR
 | 
| 
Nenue@6
 | 
   352       local gv = c.pingTime   - PING_MIDLINE
 | 
| 
Nenue@6
 | 
   353       local gr = PING_CEILING - PING_MIDLINE
 | 
| 
Nenue@6
 | 
   354       local r = c.pingTime > PING_MIDLINE and 1 or (c.pingTime < PING_FLOOR and 0 or (rv / rr))
 | 
| 
Nenue@6
 | 
   355       local g = c.pingTime < PING_MIDLINE and 1 or (c.pingTime > PING_CEILING and 0 or 1-(gv / gr))
 | 
| 
Nenue@6
 | 
   356       print(c.pingTime, rv, '/', rr, '=', r)
 | 
| 
Nenue@6
 | 
   357       print(c.pingTime, gv, '/', gr, '=', g)
 | 
| 
Nenue@6
 | 
   358 
 | 
| 
Nenue@6
 | 
   359       c.ping:SetText(floor(c.pingTime))
 | 
| 
Nenue@6
 | 
   360       c.ping:SetTextColor(r,g,0)
 | 
| 
Nenue@6
 | 
   361       c.ping:Show()
 | 
| 
Nenue@6
 | 
   362     else
 | 
| 
Nenue@6
 | 
   363       c.pingbar:Hide()
 | 
| 
Nenue@6
 | 
   364       c.ping:Hide()
 | 
| 
Nenue@6
 | 
   365     end
 | 
| 
Nenue@6
 | 
   366     if c.downTime then
 | 
| 
Nenue@6
 | 
   367       c.downtime:Show()
 | 
| 
Nenue@6
 | 
   368       if c.downTime > 1500 then
 | 
| 
Nenue@6
 | 
   369         c.downtime:SetText(nil)
 | 
| 
Nenue@6
 | 
   370       else
 | 
| 
Nenue@6
 | 
   371         c.downtime:SetText(c.downTime)
 | 
| 
Nenue@6
 | 
   372       end
 | 
| 
Nenue@6
 | 
   373     else
 | 
| 
Nenue@6
 | 
   374       c.downtime:Hide()
 | 
| 
Nenue@6
 | 
   375     end
 | 
| 
Nenue@6
 | 
   376   else
 | 
| 
Nenue@6
 | 
   377     if c.nonInterruptible then
 | 
| 
Nenue@6
 | 
   378       c.interrupt:Show()
 | 
| 
Nenue@6
 | 
   379     else
 | 
| 
Nenue@6
 | 
   380       c.interrupt:Hide()
 | 
| 
Nenue@6
 | 
   381     end
 | 
| 
Nenue@6
 | 
   382   end
 | 
| 
Nenue@6
 | 
   383 
 | 
| 
Nenue@6
 | 
   384   c.icon:SetTexture(texture)
 | 
| 
Nenue@6
 | 
   385   c.spelltext:Show()
 | 
| 
Nenue@6
 | 
   386   c.spelltext:SetText(spellName)
 | 
| 
Nenue@6
 | 
   387 
 | 
| 
Nenue@6
 | 
   388   c.fill_inverse = c.channeling
 | 
| 
Nenue@6
 | 
   389   -- set timers
 | 
| 
Nenue@6
 | 
   390 end
 | 
| 
Nenue@6
 | 
   391 
 | 
| 
Nenue@6
 | 
   392 --- Deals with failed/succeeded/interrupted visuals and fading cues
 | 
| 
Nenue@6
 | 
   393 -- Fired by one of those events, or cast/channel info is returning nothing
 | 
| 
Nenue@6
 | 
   394 function mod:SetState(event)
 | 
| 
Nenue@6
 | 
   395   if T.unlocked then
 | 
| 
Nenue@6
 | 
   396     return
 | 
| 
Nenue@6
 | 
   397   end
 | 
| 
Nenue@6
 | 
   398 
 | 
| 
Nenue@6
 | 
   399   local time = GetTime() * 1000
 | 
| 
Nenue@6
 | 
   400   print(' ',self:GetName(), '|cFF44FF00event trigger:|r', event)
 | 
| 
Nenue@6
 | 
   401 
 | 
| 
Nenue@6
 | 
   402   -- We want these to be updating no matter what is happening
 | 
| 
Nenue@6
 | 
   403   if TEXTURE_SUFFIX[event] then
 | 
| 
Nenue@6
 | 
   404     local cdb = self.db
 | 
| 
Nenue@6
 | 
   405     if cdb.foreground_texture then
 | 
| 
Nenue@6
 | 
   406       print('   |cFF00AAFFevent|r '..event..', |cFF00AAFFtexture|r ', cdb.foreground_texture)
 | 
| 
Nenue@6
 | 
   407       self.foreground:SetVertexColor(unpack(cdb['foreground' .. TEXTURE_SUFFIX[event]] and cdb['foreground' .. TEXTURE_SUFFIX[event]] or cdb.foreground_color))
 | 
| 
Nenue@6
 | 
   408     else
 | 
| 
Nenue@6
 | 
   409       self.foreground:SetTexture(unpack(cdb['foreground' .. TEXTURE_SUFFIX[event]] and cdb['foreground' .. TEXTURE_SUFFIX[event]] or cdb.foreground_color))
 | 
| 
Nenue@6
 | 
   410     end
 | 
| 
Nenue@6
 | 
   411 
 | 
| 
Nenue@6
 | 
   412     if cdb.background_texture then
 | 
| 
Nenue@6
 | 
   413       print('  texture=', cdb.background_texture)
 | 
| 
Nenue@6
 | 
   414       self.background:SetVertexColor(unpack(cdb['background' .. TEXTURE_SUFFIX[event]] and cdb['background' .. TEXTURE_SUFFIX[event]] or cdb.background_color))
 | 
| 
Nenue@6
 | 
   415     else
 | 
| 
Nenue@6
 | 
   416       self.background:SetTexture(unpack(cdb['background' .. TEXTURE_SUFFIX[event]] and cdb['background' .. TEXTURE_SUFFIX[event]] or cdb.background_color))
 | 
| 
Nenue@6
 | 
   417     end
 | 
| 
Nenue@6
 | 
   418   end
 | 
| 
Nenue@6
 | 
   419 
 | 
| 
Nenue@6
 | 
   420   -- are we starting or stopping
 | 
| 
Nenue@6
 | 
   421   if event == 'START' or event == 'CHANNEL_START' then
 | 
| 
Nenue@6
 | 
   422     print('   |cFF00AAFFStarting display|r ', self.spellName)
 | 
| 
Nenue@6
 | 
   423     self:Show()
 | 
| 
Nenue@6
 | 
   424     if self.__fade:IsPlaying() then
 | 
| 
Nenue@6
 | 
   425       self.__fade:Stop()
 | 
| 
Nenue@6
 | 
   426     end
 | 
| 
Nenue@6
 | 
   427 
 | 
| 
Nenue@6
 | 
   428     self:Fade(FADE_IN_TIME, self.alpha)
 | 
| 
Nenue@6
 | 
   429   else
 | 
| 
Nenue@6
 | 
   430     if event == 'SUCCEEDED' and not self.channeling then
 | 
| 
Nenue@6
 | 
   431       print('   |cFF00AAFFsuccess deduced values|r', self.value, 'to', self.duration)
 | 
| 
Nenue@6
 | 
   432       self.percent = 1
 | 
| 
Nenue@6
 | 
   433       self.value = self.duration
 | 
| 
Nenue@6
 | 
   434     end
 | 
| 
Nenue@6
 | 
   435 
 | 
| 
Nenue@6
 | 
   436     -- Actual fading out begins here, anything else is statistical sugar
 | 
| 
Nenue@6
 | 
   437     if event == 'STOP' or event == 'CHANNEL_STOP' then
 | 
| 
Nenue@6
 | 
   438       print('yeah we done')
 | 
| 
Nenue@6
 | 
   439       if self.__fade:IsPlaying() then
 | 
| 
Nenue@6
 | 
   440         self.__fade:Stop()
 | 
| 
Nenue@6
 | 
   441       end
 | 
| 
Nenue@6
 | 
   442       self:Fade(FADE_OUT_TIME, 0)
 | 
| 
Nenue@6
 | 
   443     end
 | 
| 
Nenue@6
 | 
   444   end
 | 
| 
Nenue@6
 | 
   445 end
 | 
| 
Nenue@6
 | 
   446 
 | 
| 
Nenue@6
 | 
   447 --- Animation loop
 | 
| 
Nenue@6
 | 
   448 function mod:Update()
 | 
| 
Nenue@6
 | 
   449   local time = GetTime() * 1000
 | 
| 
Nenue@6
 | 
   450   local u = self.unit
 | 
| 
Nenue@6
 | 
   451   local s = self
 | 
| 
Nenue@6
 | 
   452 
 | 
| 
Nenue@6
 | 
   453   -- update vals
 | 
| 
Nenue@6
 | 
   454   if s.casting or s.channeling then
 | 
| 
Nenue@6
 | 
   455     self.value = s.casting and (time - s.startTime) or (s.endTime - time)
 | 
| 
Nenue@6
 | 
   456     self.percent = (time - s.startTime) / self.duration
 | 
| 
Nenue@6
 | 
   457     if time > s.endTime then
 | 
| 
Nenue@6
 | 
   458       self.value = self.fill_inverse and 0 or s.duration
 | 
| 
Nenue@6
 | 
   459       self.percent = self.fill_inverse and 0 or 1
 | 
| 
Nenue@6
 | 
   460       self.elapsed = time - s.endTime
 | 
| 
Nenue@6
 | 
   461     end
 | 
| 
Nenue@9
 | 
   462     uprint('   ',self.unit, self.value, self.percent)
 | 
| 
Nenue@6
 | 
   463   else
 | 
| 
Nenue@6
 | 
   464     self.value = 1000
 | 
| 
Nenue@6
 | 
   465     self.percent = 1
 | 
| 
Nenue@6
 | 
   466   end
 | 
| 
Nenue@6
 | 
   467   self.casttime:SetText(format("%.2f", self.value / 1000))
 | 
| 
Nenue@6
 | 
   468 
 | 
| 
Nenue@6
 | 
   469   self:SetProgress(self.percent)
 | 
| 
Nenue@6
 | 
   470 end
 | 
| 
Nenue@6
 | 
   471 
 | 
| 
Nenue@6
 | 
   472 --- Refresh the CastingBar for things like target change, pet despawn, etc.
 | 
| 
Nenue@6
 | 
   473 -- Will attempt to flush out any existing cast action data, then re-invoke SpellCastEvent() with as much data can be acquired.
 | 
| 
Nenue@6
 | 
   474 -- There is no event data such as spellID directly available, so this is essentially the biggest constraint we have on what
 | 
| 
Nenue@6
 | 
   475 -- the castingbar can depend on.
 | 
| 
Nenue@6
 | 
   476 function mod:UpdateUnit(unit)
 | 
| 
Nenue@9
 | 
   477   local print = function(...) uprint(...) end
 | 
| 
Nenue@6
 | 
   478   print(cText 'GUID changed:|cFFFFFF99', unit)
 | 
| 
Nenue@6
 | 
   479   local c = mod.castbar[unit]
 | 
| 
Nenue@6
 | 
   480   if c.channeling or c.casting then
 | 
| 
Nenue@6
 | 
   481     print(cText '  was casting a spell, run STOP event and hide completely')
 | 
| 
Nenue@6
 | 
   482     c:SetState(c.casting and 'STOP' or 'CHANNEL_STOP')
 | 
| 
Nenue@6
 | 
   483     c.channeling = nil
 | 
| 
Nenue@6
 | 
   484     c.casting = nil
 | 
| 
Nenue@6
 | 
   485     c:Hide()
 | 
| 
Nenue@6
 | 
   486   end
 | 
| 
Nenue@6
 | 
   487 
 | 
| 
Nenue@6
 | 
   488   if T.unit[unit].casting then
 | 
| 
Nenue@6
 | 
   489     print(cText('  new target is CASTING'))
 | 
| 
Nenue@6
 | 
   490     mod:SpellCastEvent('UNIT_SPELLCAST_START', unit)
 | 
| 
Nenue@6
 | 
   491   end
 | 
| 
Nenue@6
 | 
   492   if T.unit[unit].channeling then
 | 
| 
Nenue@6
 | 
   493     print(cText('  new target is CHANNELING'))
 | 
| 
Nenue@6
 | 
   494     mod:SpellCastEvent('UNIT_SPELLCAST_CHANNEL_START', unit)
 | 
| 
Nenue@6
 | 
   495   end
 | 
| 
Nenue@6
 | 
   496 
 | 
| 
Nenue@6
 | 
   497   T:UNIT_SPELLCAST(unit)-- name, subText, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible
 | 
| 
Nenue@6
 | 
   498   T:UNIT_CHANNEL(unit)  -- name, subText, text, texture, startTime, endTime, isTradeSkill, notInterruptible
 | 
| 
Nenue@6
 | 
   499 
 | 
| 
Nenue@6
 | 
   500 end
 | 
| 
Nenue@6
 | 
   501 
 | 
| 
Nenue@6
 | 
   502 function mod:UpdateInterrupt(e, unit, ...)
 | 
| 
Nenue@6
 | 
   503     mod.castbar[unit].nonInterruptible = (e == 'UNIT_SPELLCAST_UNINTERRUPTIBLE') and true or false
 | 
| 
Nenue@6
 | 
   504   if unit ~= 'player' and unit ~='pet' then
 | 
| 
Nenue@6
 | 
   505 
 | 
| 
Nenue@6
 | 
   506   end
 | 
| 
Nenue@6
 | 
   507 end
 | 
| 
Nenue@6
 | 
   508 
 | 
| 
Nenue@6
 | 
   509 mod.UNIT_PET = function(self, e, unit)
 | 
| 
Nenue@6
 | 
   510   if unit == 'player' then
 | 
| 
Nenue@6
 | 
   511     self:UpdateUnit('pet')
 | 
| 
Nenue@6
 | 
   512   end
 | 
| 
Nenue@6
 | 
   513 end
 | 
| 
Nenue@6
 | 
   514 mod.PLAYER_TARGET_CHANGED = function(self, ...)
 | 
| 
Nenue@9
 | 
   515   mprint(cPink(self),...)
 | 
| 
Nenue@6
 | 
   516   self:UpdateUnit('target')
 | 
| 
Nenue@6
 | 
   517 end
 | 
| 
Nenue@6
 | 
   518 mod.PLAYER_FOCUS_CHANGED = function(self)
 | 
| 
Nenue@6
 | 
   519   self:UpdateUnit('focus')
 | 
| 
Nenue@6
 | 
   520 end |