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