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