vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 Name: SpellStatus-1.0
3 Revision: $Rev: 14589 $
4 Author(s): Nightdew (denzsolnightdew@gmail.com)
5 Website: http://www.wowace.com/index.php/SpellStatus-1.0
6 Documentation: http://www.wowace.com/index.php/SpellStatus-1.0
7 SVN: http://svn.wowace.com/root/trunk/SpellStatusLib/SpellStatus-1.0
8 Description: Status library that simplifies retrieving spell status information from the player
9 Dependencies: AceLibrary, AceDebug-2.0, AceEvent-2.0, AceHook-2.1, Deformat-2.0, Gratuity-2.0, SpellCache-1.0, (optional) SpellStatus-AimedShot-1.0
10 ]]
11  
12 local MAJOR_VERSION = "SpellStatus-1.0"
13 local MINOR_VERSION = "$Revision: 14589 $"
14  
15 if (not AceLibrary) then
16 error(MAJOR_VERSION .. " requires AceLibrary.")
17 end
18  
19 if (not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION)) then
20 return
21 end
22  
23 local function CheckDependency(dependencies)
24 for index, value in ipairs(dependencies) do
25 if (not AceLibrary:HasInstance(value)) then
26 error(format("%s requires %s to function properly", MAJOR_VERSION, value))
27 end
28 end
29 end
30  
31 local dependencyLibraries = {
32 "AceDebug-2.0",
33 "AceEvent-2.0",
34 "AceHook-2.1",
35 "Deformat-2.0",
36 "Gratuity-2.0",
37 "SpellCache-1.0"
38 }
39  
40 CheckDependency(dependencyLibraries)
41  
42 local deformat = AceLibrary("Deformat-2.0")
43 local gratuity = AceLibrary("Gratuity-2.0")
44 local spellcache = AceLibrary("SpellCache-1.0")
45  
46 --Create Library Object
47 local SpellStatus = {}
48  
49 --Embed all needed mixins into the Library Object SpellStatus
50 AceLibrary("AceDebug-2.0"):embed(SpellStatus)
51 AceLibrary("AceEvent-2.0"):embed(SpellStatus)
52 AceLibrary("AceHook-2.1"):embed(SpellStatus)
53  
54 --
55 -- Local functions not to be called from outside
56 --
57  
58 local function InitializeHooks(self)
59 self:Hook("CastSpell")
60 self:Hook("CastSpellByName")
61 self:Hook("UseAction")
62 self:Hook("CastShapeshiftForm")
63 self:Hook("UseInventoryItem")
64 self:Hook("UseContainerItem")
65 self:Hook("ToggleGameMenu")
66 self:Hook("SpellStopCasting")
67 end
68  
69 local function InitializeEventRegisters(self)
70 self:RegisterEvent("SPELLCAST_START")
71 self:RegisterEvent("SPELLCAST_STOP")
72 self:RegisterEvent("SPELLCAST_INTERRUPTED")
73 self:RegisterEvent("SPELLCAST_FAILED")
74 self:RegisterEvent("SPELLCAST_DELAYED")
75 self:RegisterEvent("SPELLCAST_CHANNEL_START")
76 self:RegisterEvent("SPELLCAST_CHANNEL_STOP")
77 self:RegisterEvent("SPELLCAST_CHANNEL_UPDATE")
78 self:RegisterEvent("UI_ERROR_MESSAGE")
79 self:RegisterEvent("CHAT_MSG_SPELL_FAILED_LOCALPLAYER")
80 self:RegisterEvent("CHAT_MSG_SPELL_AURA_GONE_SELF")
81  
82 self:RegisterEvent("CHAT_MSG_COMBAT_SELF_HITS")
83 self:RegisterEvent("CHAT_MSG_COMBAT_SELF_MISSES")
84  
85 self:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
86  
87 --SPELLLOGSELFOTHER
88  
89 --Used to determine if we are wanding.
90 self:RegisterEvent("START_AUTOREPEAT_SPELL")
91 self:RegisterEvent("STOP_AUTOREPEAT_SPELL")
92  
93 self:RegisterEvent("PLAYER_ENTER_COMBAT")
94 self:RegisterEvent("PLAYER_LEAVE_COMBAT")
95  
96 self:RegisterEvent("PLAYER_REGEN_DISABLED")
97 self:RegisterEvent("PLAYER_REGEN_ENABLED")
98  
99 self:RegisterEvent("SpellCache_Updated")
100 end
101  
102 local function ResetActiveVariables(self)
103 self:LevelDebug(2, "ResetActiveVariables")
104 --Active Spell
105 self.vars.ActiveId = nil
106 self.vars.ActiveName = nil
107 self.vars.ActiveRank = nil
108 self.vars.ActiveFullName = nil
109 self.vars.ActiveCastStartTime = nil
110 self.vars.ActiveCastStopTime = nil
111 self.vars.ActiveCastDuration = nil
112  
113 --Casting
114 self.vars.ActiveCastDelay = nil
115 self.vars.ActiveCastDelayTotal = nil
116  
117 --Channeling
118 self.vars.ActiveAction = nil
119 self.vars.ActiveCastDisruption = nil
120 self.vars.ActiveCastDisruptionTotal = nil
121  
122 --NextMelee
123 self.vars.NextMeleeId = nil
124 self.vars.NextMeleeName = nil
125 self.vars.NextMeleeRank = nil
126 self.vars.NextMeleeFullName = nil
127 end
128  
129 local function ResetVariables(self)
130 self:LevelDebug(2, "ResetVariables")
131  
132 --Spell Attempted to cast
133 self.vars.AttemptId = nil
134 self.vars.AttemptName = nil
135 self.vars.AttemptRank = nil
136 self.vars.AttemptFullName = nil
137  
138 ResetActiveVariables(self)
139  
140 --UI_ERROR_MESSAGE
141 self.vars.UIEM_Message = nil
142 --CHATMSGSPELLFAILEDLOCALPLAYER
143 self.vars.CMSFLP_SpellName = nil
144 self.vars.CMSFLP_Message = nil
145  
146 end
147  
148 local function InitializeVariables(self)
149 self:LevelDebug(2, "InitializeVariables")
150  
151 self.vars = {}
152  
153 --True while data is assigned until fail or stop or start and no SpellId
154 self.vars.Using = false
155 --True while data is assigned until fail or stop or start and SpellId
156 self.vars.Preparing = false
157 --Only true for spell with a casting time
158 self.vars.Casting = false
159 --Only true for channeling spells
160 self.vars.Channeling = false
161 --Only true for spells that are next melee
162 self.vars.NextMeleeing = false
163  
164 --Whether or not the character is auto repeating
165 self.vars.AutoRepeating = false
166 --Are we attacking currently
167 self.vars.Attacking = false
168 --Are we currently in combat
169 self.vars.Combating = false
170  
171 self.vars.Targeting = false
172  
173 --True when hooked into ToggleGameMenu
174 self.vars.CancelTargeting = false
175 self.vars.CancelCasting = false
176 self.vars.CancelChanneling = false
177  
178 ResetVariables(self)
179 end
180  
181 --
182 -- Activate method
183 --
184  
185 local function activate(self, oldLib, oldDeactivate)
186 --self:SetDebugging(true)
187 --self:SetDebugLevel(3)
188  
189 self:LevelDebug(2, "SpellStatus - activate")
190  
191 if (oldLib) then
192 oldLib:UnregisterAllEvents()
193 oldLib:UnhookAll()
194 end
195  
196 --Default code to clean up the oldlib
197 if (oldDeactivate) then
198 oldDeactivate(oldLib)
199 end
200  
201 InitializeVariables(self)
202 InitializeHooks(self)
203 InitializeEventRegisters(self)
204 end
205  
206  
207 function SpellStatus:Report()
208 self:LevelDebug(3,
209 format("Using: %s", tostring(self.vars.Using)),
210 format("Preparing: %s", tostring(self.vars.Preparing)),
211 format("Casting: %s", tostring(self.vars.Casting)),
212 format("Channeling: %s", tostring(self.vars.Channeling)),
213 format("SpellName: %s", tostring(self:GetActiveSpellName()))
214 )
215 end
216  
217 function SpellStatus:IsUsing()
218 return self.vars.Using == true
219 end
220  
221 function SpellStatus:IsPreparing()
222 return self.vars.Preparing == true
223 end
224  
225 function SpellStatus:IsCasting()
226 return self.vars.Casting == true
227 end
228  
229 function SpellStatus:IsChanneling()
230 return self.vars.Channeling == true
231 end
232  
233 function SpellStatus:IsNextMeleeing()
234 return self.vars.NextMeleeing == true
235 end
236  
237 function SpellStatus:IsCastingOrChanneling()
238 return self:IsCasting() or self:IsChanneling()
239 end
240  
241 function SpellStatus:IsPreparingOrCastingOrChanneling()
242 return self:IsPreparing() or self:IsCasting() or self:IsChanneling()
243 end
244  
245 function SpellStatus:IsAutoRepeating()
246 return self.vars.AutoRepeating == true
247 end
248  
249 function SpellStatus:IsWanding()
250 return ((self.vars.AutoRepeating == true) and HasWandEquipped()) and true or false
251 end
252  
253 function SpellStatus:IsAttacking()
254 return self.vars.Attacking == true
255 end
256  
257 function SpellStatus:IsCombating()
258 return self.vars.Combating == true
259 end
260  
261 function SpellStatus:IsActiveSpell(spellId, spellName)
262 local sId, sName = self:GetActiveSpellData()
263 self:LevelDebug(2, "IsActiveSpell", spellId, sId, spellName, sName)
264 --sId and spellId might be nil
265 return (sId == spellId) and (sName == spellName)
266 end
267  
268 function SpellStatus:GetActiveSpellData()
269 return self.vars.ActiveId, self.vars.ActiveName, self.vars.ActiveRank, self.vars.ActiveFullName,
270 self.vars.ActiveCastStartTime, self.vars.ActiveCastStopTime, self.vars.ActiveCastDuration,
271 self.vars.ActiveAction
272 end
273  
274 function SpellStatus:GetActiveSpellName()
275 local _, spellName = self:GetActiveSpellData()
276 return spellName
277 end
278  
279 function SpellStatus:GetNextMeleeSpellData()
280 return self.vars.NextMeleeId, self.vars.NextMeleeName, self.vars.NextMeleeRank, self.vars.NextMeleeFullName
281 end
282  
283 --
284 -- Function Hooking
285 --
286  
287 function SpellStatus:SpellCache_Updated()
288 end
289  
290 local function AssignNextMeleeSpellData(self, spellId, spellName, spellRank, spellFullName)
291 if (not spellId) then
292 return false
293 end
294  
295 gratuity:SetSpell(spellId, BOOKTYPE_SPELL)
296 if (gratuity:Find(SPELL_ON_NEXT_SWING, 2, 3, false, true, true) == nil) then
297 return false
298 end
299  
300 self:LevelDebug(1, "AssignNextMeleeSpellData", spellId, spellName, spellRank, spellFullName)
301  
302 self.vars.NextMeleeing = true
303  
304 self.vars.NextMeleeId = spellId
305 self.vars.NextMeleeName = spellName
306 self.vars.NextMeleeRank = spellRank
307 self.vars.NextMeleeFullName = spellFullName
308 return true
309 end
310  
311  
312 local function AssignSpellData(self, spellId, spellName, spellRank, spellFullName)
313 --self:LevelDebug(1, "AssignSpellData", spellId, spellName, spellRank, spellFullName)
314  
315 --If Next Melee spell stop dont continue
316 if (AssignNextMeleeSpellData(self, spellId, spellName, spellRank, spellFullName)) then
317 return
318 end
319  
320 if (self.vars.Preparing or self.vars.Casting or self.vars.Channeling) then
321 return
322 end
323  
324 if (self.vars.Using and (spellName == self.vars.ActiveName)) then
325 return
326 end
327  
328  
329 self:LevelDebug(1, "AssignSpellData", spellId, spellName, spellRank, spellFullName)
330  
331 ResetVariables(self)
332  
333 self.vars.ActiveId = spellId
334 self.vars.ActiveName = spellName
335 self.vars.ActiveRank = spellRank
336 self.vars.ActiveFullName = spellFullName
337  
338 self.vars.Preparing = spellId ~= nil
339 self.vars.Using = not self.vars.Preparing
340  
341 --Only preparing if you have a spellId
342 if (self.vars.Preparing) then
343 local aimedShot = AceLibrary:HasInstance("SpellStatus-AimedShot-1.0") and AceLibrary("SpellStatus-AimedShot-1.0") or nil
344 if (aimedShot and aimedShot:Active()) then
345 local aimedShotId, aimedShotDuration = aimedShot:MatchSpellId(spellId)
346 if (aimedShotId) then
347 self:SPELLCAST_START(spellName, aimedShotDuration)
348 end
349 end
350 end
351 end
352  
353 local function TriggerFailureEvent(self, overrideHasMessage)
354 overrideHasMessage = overrideHasMessage == true
355 --self:LevelDebug(2, "TriggerFailureEvent", overrideHasMessage)
356  
357 local hasMessage = self.vars.UIEM_Message or self.vars.CMSFLP_Message
358  
359 self:LevelDebug(2, "TriggerFailureEvent", hasMessage, overrideHasMessage)
360  
361 if (not (hasMessage or overrideHasMessage)) then
362 return false
363 end
364  
365 self:LevelDebug(2, "TriggerFailureEvent", overrideHasMessage)
366  
367 local isActiveSpell = false
368 local sId, sName, sRank, sFullName
369  
370 if (self.vars.AttemptName) then
371 sId = self.vars.AttemptId
372 sName = self.vars.AttemptName
373 sRank = self.vars.AttemptRank
374 sFullName = self.vars.AttemptFullName
375 self:LevelDebug(2, "TriggerFailureEvent Attempt", sId, sName, sRank, sFullName)
376 self.vars.Using = false
377 self.vars.Preparing = false
378 self.vars.NextMeleeing = false
379 --Necessary because the error might happen through multiple paths
380 self.vars.AttemptCastFailure = true
381 elseif (self.vars.CMSFLP_SpellName and (self.vars.CMSFLP_SpellName == self.vars.NextMeleeName)) then
382 sId = self.vars.NextMeleeId
383 sName = self.vars.NextMeleeName
384 sRank = self.vars.NextMeleeRank
385 sFullName = self.vars.NextMeleeFullName
386 self:LevelDebug(2, "TriggerFailureEvent NextMelee", sId, sName, sRank, sFullName)
387 self.vars.NextMeleeing = false
388 elseif (overrideHasMessage or (self.vars.CMSFLP_SpellName and (self.vars.CMSFLP_SpellName == self.vars.ActiveName))) then
389 isActiveSpell = true
390 sId = self.vars.ActiveId
391 sName = self.vars.ActiveName
392 sRank = self.vars.ActiveRank
393 sFullName = self.vars.ActiveFullName
394 self:LevelDebug(2, "TriggerFailureEvent Active", sId, sName, sRank, sFullName)
395 self.vars.Using = false
396 self.vars.Preparing = false
397 self.vars.Casting = false
398 self.vars.Channeling = false
399 else --must have been unrelated
400 return false
401 end
402  
403 self:TriggerEvent("SpellStatus_SpellCastFailure",
404 sId, sName, sRank, sFullName, isActiveSpell,
405 self.vars.UIEM_Message, self.vars.CMSFLP_SpellName, self.vars.CMSFLP_Message
406 )
407  
408 self.vars.UIEM_Message = nil
409 self.vars.CMSFLP_SpellName = nil
410 self.vars.CMSFLP_Message = nil
411  
412 return true
413 end
414  
415 function ResetCastOriginal(self, sId, sName, sRank, sFullName)
416 --setup variables if failing immediately
417 self.vars.AttemptId = sId
418 self.vars.AttemptName = sName
419 self.vars.AttemptRank = sRank
420 self.vars.AttemptFullName = sFullName
421  
422 --reset Error Message
423 self.vars.UIEM_Message = nil
424 self.vars.CMSFLP_SpellName = nil
425 self.vars.CMSFLP_Message = nil
426  
427 self.vars.AttemptCastFailure = false
428 end
429  
430 function CastOriginal(self, methodName, param1, param2, param3, sId, sName, sRank, sFullName)
431 self:LevelDebug(1, ">>>> CastOriginal",
432 methodName, param1, param2, param3,
433 sId, sName, sRank, sFullName)
434  
435 ResetCastOriginal(self, sId, sName, sRank, sFullName)
436  
437 self:LevelDebug(3, "-> CastOriginal")
438 self.hooks[methodName](param1, param2, param3)
439 self:LevelDebug(3, "<- CastOriginal")
440  
441 TriggerFailureEvent(self)
442 if (not self.vars.AttemptCastFailure) then
443 AssignSpellData(self, sId, sName, sRank, sFullName)
444 end
445  
446 ResetCastOriginal(self, nil, nil, nil, nil)
447  
448 self:LevelDebug(1, "<<<< CastOriginal",
449 methodName, param1, param2, param3,
450 sId, sName, sRank, sFullName)
451 end
452  
453 function SpellStatus:CastSpellByName(spellName, onSelf)
454 self:LevelDebug(2, ">>>> CastSpellByName", spellName, onSelf)
455  
456 local sName, sId, sRank, sFullName
457 sName, sRank, sId, sFullName = spellcache:GetSpellData(spellName)
458  
459 CastOriginal(self, "CastSpellByName", spellName, onSelf, nil, sId, sName, sRank, sFullName)
460  
461 self:LevelDebug(2, "<<<< CastSpellByName2", spellName, onSelf)
462 end
463  
464 function SpellStatus:CastSpell(spellId, spellbookType)
465 self:LevelDebug(2, ">>>> CastSpell", spellId, spellbookType)
466  
467 local sId, sName, sRank, sFullName
468 if (spellbookType == BOOKTYPE_SPELL) then
469 sName, sRank, sId, sFullName = spellcache:GetSpellData(spellId)
470 end
471  
472 CastOriginal(self, "CastSpell", spellId, spellbookType, nil, sId, sName, sRank, sFullName)
473  
474 self:LevelDebug(2, "<<<< CastSpell", spellId, spellbookType)
475 end
476  
477 --When using UseAction through clicking an actiobar button, we need to get in
478 local function GetGratuitySpellData(self, slotId)
479 local spellName = gratuity:GetLine(1)
480 local spellRank = gratuity:GetLine(1, true)
481 --empty slot?
482 if (not spellName) then
483 return
484 end
485  
486 self:LevelDebug(3, "GetGratuitySpellData", spellName, spellRank)
487 local sName, sRank, sId, sFullName = spellcache:GetSpellData(spellName, spellRank)
488 if (sName) then
489 return sId, sName, sRank, sFullName
490 else
491 return nil, spellName, nil, nil
492 end
493 end
494  
495 function SpellStatus:UseAction(slotId, checkCursor, onSelf)
496 self:LevelDebug(1, ">>>> UseAction", slotId, checkCursor, onSelf)
497  
498 local actionText = GetActionText(slotId)
499 local isMacro = actionText ~= nil
500 --self:LevelDebug(2, "UseAction", actionText, tostring(isMacro))
501  
502 if (isMacro) then
503 self.hooks["UseAction"](slotId, checkCursor, onSelf)
504 else
505 gratuity:SetAction(slotId)
506 local sId, sName, sRank, sFullName = GetGratuitySpellData(self, slotId)
507 if (sName) then
508 CastOriginal(self, "UseAction", slotId, checkCursor, onSelf, sId, sName, sRank, sFullName)
509 else
510 self.hooks["UseAction"](slotId, checkCursor, onSelf)
511 end
512 end
513  
514 self:LevelDebug(1, "<<<< UseAction", slotId, checkCursor, onSelf)
515 end
516  
517 function SpellStatus:CastShapeshiftForm(index)
518 self:LevelDebug(2, ">>>> CastShapeshiftForm", index)
519  
520 gratuity:SetShapeshift(index)
521 local sId, sName, sRank, sFullName = GetGratuitySpellData(self, slotId)
522 if (sName) then
523 CastOriginal(self, "CastShapeshiftForm", index, nil, nil, sId, sName, sRank, sFullName)
524 else
525 self.hooks["CastShapeshiftForm"](index)
526 end
527  
528 self:LevelDebug(2, "<<<< CastShapeshiftForm", index)
529 end
530  
531 local function GetItemLinkData(slotId, bagId)
532 local itemLink = nil
533  
534 if (bagId == nil) then
535 itemLink = GetInventoryItemLink("player", slotId)
536 else
537 itemLink = GetContainerItemLink(bagId, slotId)
538 end
539  
540 if (itemLink) then
541 local _, _, itemName = string.find(itemLink, "^.*%[(.*)%].*$")
542 return itemName, itemLink
543 end
544 end
545  
546 function SpellStatus:UseInventoryItem(slotId)
547 self:LevelDebug(2, ">>>> UseInventoryItem", slotId)
548  
549 local itemName, itemLink = GetItemLinkData(slotId)
550  
551 if (itemLink) then
552 CastOriginal(self, "UseInventoryItem", slotId, nil, nil, nil, itemName, nil, itemLink)
553 else
554 self.hooks["UseInventoryItem"](slotId)
555 end
556  
557 self:LevelDebug(2, "<<<< UseInventoryItem", slotId)
558 end
559  
560 function SpellStatus:UseContainerItem(bagId, slotId)
561 self:LevelDebug(2, ">>>> UseContainerItem", bagId, slotId)
562  
563 local itemName, itemLink = GetItemLinkData(slotId, bagId)
564  
565 if (itemLink) then
566 CastOriginal(self, "UseContainerItem", bagId, slotId, nil, nil, itemName, nil, itemLink)
567 else
568 self.hooks["UseContainerItem"](bagId, slotId)
569 end
570  
571 self:LevelDebug(2, "<<<< UseContainerItem", bagId, slotId)
572 end
573  
574 function SpellStatus:ToggleGameMenu()
575 --self:LevelDebug(3, "ToggleGameMenu1", SpellIsTargeting())
576  
577 --If these hook is called and targeting, targeting will always be killed first
578 self.vars.CancelTargeting = SpellIsTargeting()
579 self.vars.CancelCasting = self.vars.Casting
580 self.vars.CancelChanneling = self.vars.Channeling
581  
582 self.hooks["ToggleGameMenu"]()
583  
584 self.vars.CancelTargeting = false
585 self.vars.CancelCasting = false
586 self.vars.CancelChanneling = false
587  
588 --self:LevelDebug(3, "ToggleGameMenu2", SpellIsTargeting())
589 end
590  
591 function SpellStatus:SpellStopCasting()
592 self:LevelDebug(2, ">>>> SpellStopCasting")
593 if (self:IsCastingOrChanneling()) then
594 self.vars.SpellStopCastingActiveName = self.vars.ActiveName
595 end
596 self.hooks["SpellStopCasting"]()
597 self:LevelDebug(2, "<<<< SpellStopCasting")
598 end
599  
600 function SpellStatus:SPELLCAST_START(spellName, duration)
601 self:LevelDebug(1, "SPELLCAST_START", spellName, duration)
602  
603 self.vars.SpellStopCastingActiveName = nil
604 self.vars.Using = false
605 self.vars.Preparing = false
606 self.vars.Casting = true
607  
608 if (self.vars.ActiveName ~= spellName) then
609 ResetActiveVariables(self)
610 self.vars.ActiveName = spellName
611 self.vars.ActiveFullName = spellName
612 end
613  
614  
615 self.vars.ActiveCastStartTime = GetTime()
616 self.vars.ActiveCastDuration = duration
617 self.vars.ActiveCastStopTime = self.vars.ActiveCastStartTime + (self.vars.ActiveCastDuration/1000)
618  
619 self.vars.ActiveCastDelay = nil
620 self.vars.ActiveCastDelayTotal = nil
621  
622 self:TriggerEvent(
623 "SpellStatus_SpellCastCastingStart",
624 self.vars.ActiveId,
625 self.vars.ActiveName,
626 self.vars.ActiveRank,
627 self.vars.ActiveFullName,
628 self.vars.ActiveCastStartTime,
629 self.vars.ActiveCastStopTime,
630 self.vars.ActiveCastDuration
631 )
632 end
633  
634 function SpellStatus:SPELLCAST_DELAYED(delay)
635 self:LevelDebug(1, "SPELLCAST_DELAYED", delay)
636  
637 if (self.vars.ActiveCastStopTime == nil) then
638 return
639 end
640  
641 self.vars.ActiveCastDelay = delay/1000
642 self.vars.ActiveCastDelayTotal = (self.vars.ActiveCastDelayTotal or 0) + self.vars.ActiveCastDelay
643 self.vars.ActiveCastStopTime = self.vars.ActiveCastStopTime + self.vars.ActiveCastDelay
644  
645 self:TriggerEvent(
646 "SpellStatus_SpellCastCastingChange",
647 self.vars.ActiveId,
648 self.vars.ActiveName,
649 self.vars.ActiveRank,
650 self.vars.ActiveFullName,
651 self.vars.ActiveCastStartTime,
652 self.vars.ActiveCastStopTime,
653 self.vars.ActiveCastDuration,
654 self.vars.ActiveCastDelay,
655 self.vars.ActiveCastDelayTotal
656 )
657 end
658  
659 function SpellStatus:SPELLCAST_STOP()
660 self:LevelDebug(1, "SPELLCAST_STOP")
661  
662 --If canceling targeting.. ignore stop!
663 if (self.vars.CancelTargeting or self.vars.CancelCasting or self.vars.CancelChanneling) then
664 return
665 end
666  
667 --if (self.vars.ActiveId == nil) then
668 if (self.vars.ActiveName == nil) then
669 return
670 end
671  
672 --Player probably moved initiating a client and server side SPELLCAST_STOP
673 if (not( self.vars.Using or
674 self.vars.Preparing or
675 self.vars.Casting or
676 self.vars.Channeling or
677 self.vars.AutoRepeating )) then
678 return
679 end
680  
681 if (TriggerFailureEvent(self)) then
682 return
683 end
684  
685 self.vars.Using = false
686 self.vars.Preparing = false
687  
688 --Second SPELLCAST_STOP received from server after SpellStopCasting was called
689 if ((not self.vars.Casting) and
690 self.vars.SpellStopCastingActiveName and
691 (self.vars.ActiveName == self.vars.SpellStopCastingActiveName)) then
692 self.vars.SpellStopCastingActiveName = nil
693 return
694 end
695  
696 local castingInstant = (not self.vars.Casting) and (not self.vars.Channeling)
697 self.vars.Casting = false
698  
699 --Generate Finish Event if not channeling
700 if (not self.vars.Channeling) then
701 local sD = castingInstant and self or self.vars.ActiveCastingData
702  
703 self.vars.ActiveCastStartTime = self.vars.ActiveCastStartTime or GetTime()
704 self.vars.ActiveCastStopTime = GetTime()
705  
706 self:TriggerEvent(
707 castingInstant and "SpellStatus_SpellCastInstant" or "SpellStatus_SpellCastCastingFinish",
708 self.vars.ActiveId,
709 self.vars.ActiveName,
710 self.vars.ActiveRank,
711 self.vars.ActiveFullName,
712 self.vars.ActiveCastStartTime,
713 self.vars.ActiveCastStopTime,
714 self.vars.ActiveCastDuration,
715 self.vars.ActiveCastDelayTotal
716 )
717 --We cant reset because maybe we have a failure!!!
718 --ResetActiveVariables(self)
719 end
720 end
721  
722 function SpellStatus:SPELLCAST_CHANNEL_START(duration, action)
723 self:LevelDebug(2, "SPELLCAST_CHANNEL_START", duration, action)
724  
725 self.vars.SpellStopCastingActiveName = nil
726 self.vars.Using = false
727 self.vars.Preparing = false
728 self.vars.Channeling = true
729  
730 local sD = self.vars.ActiveChannelingData
731  
732 self.vars.ActiveCastStartTime = GetTime()
733 self.vars.ActiveCastDuration = duration / 1000
734 self.vars.ActiveCastStopTime = self.vars.ActiveCastStartTime + self.vars.ActiveCastDuration
735 self.vars.ActiveAction = action
736  
737 self.vars.ActiveId = self.vars.ActiveId
738 self.vars.ActiveName = self.vars.ActiveName
739 self.vars.ActiveRank = self.vars.ActiveRank
740 self.vars.ActiveFullName = self.vars.ActiveFullName
741  
742 self.vars.ActiveCastDisruption = nil
743 self.vars.ActiveCastDisruptionTotal = nil
744  
745 self:TriggerEvent(
746 "SpellStatus_SpellCastChannelingStart",
747 self.vars.ActiveId,
748 self.vars.ActiveName,
749 self.vars.ActiveRank,
750 self.vars.ActiveFullName,
751 self.vars.ActiveCastStartTime,
752 self.vars.ActiveCastStopTime,
753 self.vars.ActiveCastDuration,
754 self.vars.ActiveAction
755 )
756 end
757  
758 --Any changes while channeling will come through this event
759 function SpellStatus:SPELLCAST_CHANNEL_UPDATE(duration)
760 self:LevelDebug(2, "SPELLCAST_CHANNEL_UPDATE", duration)
761  
762 local sD = self.vars.ActiveChannelingData
763  
764 local timeStamp = GetTime()
765  
766 --New Duration
767 local spellCastDuration = duration / 1000
768 self:LevelDebug(3, "spellCastDuration", spellCastDuration)
769 --Store old stop time
770 local spellCastStopTime = self.vars.ActiveCastStopTime
771 --Time Passed since Channeling
772 local spellCastTimePassed = timeStamp - self.vars.ActiveCastStartTime
773 self:LevelDebug(3, "spellCastTimePassed", spellCastTimePassed)
774 --What channel time did we loose
775 self.vars.ActiveCastDisruption = self.vars.ActiveCastDuration - spellCastDuration - spellCastTimePassed
776 self.vars.ActiveCastDisruptionTotal = (self.vars.ActiveCastDisruptionTotal or 0) + self.vars.ActiveCastDisruption
777 self.vars.ActiveCastStopTime = timeStamp + spellCastDuration
778  
779 self:TriggerEvent(
780 "SpellStatus_SpellCastChannelingChange",
781 self.vars.ActiveId,
782 self.vars.ActiveName,
783 self.vars.ActiveRank,
784 self.vars.ActiveFullName,
785 self.vars.ActiveCastStartTime,
786 self.vars.ActiveCastStopTime,
787 self.vars.ActiveCastDuration,
788 self.vars.ActiveAction,
789 self.vars.ActiveCastDisruption,
790 self.vars.ActiveCastDisruptionTotal
791 )
792 end
793  
794 function SpellStatus:SPELLCAST_CHANNEL_STOP()
795 self:LevelDebug(2, "SPELLCAST_CHANNEL_STOP")
796  
797 self.vars.Using = false
798 self.vars.Preparing = false
799 self.vars.Channeling = false
800  
801 self.vars.ActiveCastStopTime = GetTime()
802  
803 self:TriggerEvent(
804 "SpellStatus_SpellCastChannelingFinish",
805 self.vars.ActiveId,
806 self.vars.ActiveName,
807 self.vars.ActiveRank,
808 self.vars.ActiveFullName,
809 self.vars.ActiveCastStartTime,
810 self.vars.ActiveCastStopTime,
811 self.vars.ActiveCastDuration,
812 self.vars.ActiveAction,
813 self.vars.ActiveCastDisruptionTotal
814 )
815 end
816  
817 --Always thrown before CHAT_MSG_SPELL_FAILED_LOCALPLAYER which might be thrown
818 function SpellStatus:UI_ERROR_MESSAGE(message)
819 self:LevelDebug(2, "UI_ERROR_MESSAGE", message)
820  
821 self.vars.UIEM_Message = message
822 end
823  
824 local FAILUREMESSAGE = {
825 SPELLFAILCASTSELF,
826 SPELLFAILPERFORMSELF
827 }
828  
829 function SpellStatus:CHAT_MSG_SPELL_FAILED_LOCALPLAYER(message)
830 self:LevelDebug(2, "CHAT_MSG_SPELL_FAILED_LOCALPLAYER", message)
831  
832 table.foreach(FAILUREMESSAGE,
833 function(key, value)
834 local spellName, spellFailureMessage = deformat:Deformat(message, value)
835 if (spellName) then
836 self.vars.CMSFLP_SpellName = spellName
837 self.vars.CMSFLP_Message = spellFailureMessage
838 end
839 --if returning ~= nil the foreach will stop.
840 return spellName
841 end
842 )
843 end
844  
845 local CHAT_MSG_SPELL_SELF_DAMAGEMESSAGES = {
846 IMMUNESPELLSELFOTHER,
847 SIMPLECASTSELFOTHER,
848 SIMPLEPERFORMSELFOTHER,
849 SPELLBLOCKEDSELFOTHER,
850 SPELLDODGEDSELFOTHER,
851 SPELLEVADEDSELFOTHER,
852 SPELLIMMUNESELFOTHER,
853 SPELLINTERRUPTSELFOTHER,
854 SPELLLOGABSORBSELFOTHER,
855 SPELLLOGABSORBSELFSELF,
856 SPELLLOGCRITSCHOOLSELFOTHER,
857 SPELLLOGCRITSCHOOLSELFSELF,
858 SPELLLOGCRITSELFOTHER,
859 SPELLLOGSCHOOLSELFOTHER,
860 SPELLLOGSCHOOLSELFSELF,
861 SPELLLOGSELFOTHER,
862 SPELLMISSSELFOTHER,
863 SPELLPARRIEDSELFOTHER,
864 SPELLREFLECTSELFOTHER,
865 SPELLRESISTSELFOTHER,
866 SPELLRESISTSELFSELF,
867 SPELLTERSEPERFORM_SELF,
868 SPELLTERSE_SELF
869 }
870  
871 local CHAT_MSG_SPELL_SELF_DAMAGEMESSAGETRAILERS = {
872 "",
873 ABSORB_TRAILER,
874 BLOCK_TRAILER,
875 CRUSHING_TRAILER,
876 GLANCING_TRAILER,
877 RESIST_TRAILER,
878 VULNERABLE_TRAILER
879 }
880  
881 function ParseCHAT_MSG_SPELL_SELF_DAMAGE(self, message, damageMessage, damageMessageTrailer)
882 local spellName = deformat:Deformat(message, damageMessage..damageMessageTrailer)
883 --self:LevelDebug(2, "ParseCHAT_MSG_SPELL_SELF_DAMAGE", self.vars.NextMeleeing, self.vars.NextMeleeName, spellName)
884 if (spellName and (spellName == self.vars.NextMeleeName)) then
885 self.vars.NextMeleeing = false
886  
887 self:TriggerEvent(
888 "SpellStatus_SpellCastInstant",
889 self.vars.NextMeleeId,
890 self.vars.NextMeleeName,
891 self.vars.NextMeleeRank,
892 self.vars.NextMeleeFullName
893 )
894 end
895 end
896  
897 function SpellStatus:CHAT_MSG_SPELL_SELF_DAMAGE(message)
898 self:LevelDebug(2, "CHAT_MSG_SPELL_SELF_DAMAGE", message)
899  
900 if (not self.vars.NextMeleeing) then
901 return
902 end
903  
904 table.foreach(
905 CHAT_MSG_SPELL_SELF_DAMAGEMESSAGES,
906 function(_, damageMessage)
907 table.foreach(
908 CHAT_MSG_SPELL_SELF_DAMAGEMESSAGETRAILERS,
909 function(_, damageMessageTrailer)
910 ParseCHAT_MSG_SPELL_SELF_DAMAGE(self, message, damageMessage, damageMessageTrailer)
911 if (not self.vars.NextMeleeing) then
912 return true
913 end
914 end
915 )
916 if (not self.vars.NextMeleeing) then
917 return true
918 end
919 end
920 )
921 end
922  
923 function SpellStatus:CHAT_MSG_SPELL_AURA_GONE_SELF(message)
924 self:LevelDebug(2, "CHAT_MSG_SPELL_AURA_GONE_SELF", message)
925  
926 if (not(self.vars.Using or self.vars.Preparing or self.vars.Casting or self.vars.Channeling)) then
927 return
928 end
929  
930 local spellName = deformat:Deformat(message, AURAREMOVEDSELF)
931 if ((not spellName) or (spellName ~= self.vars.ActiveName)) then
932 return
933 end
934  
935 self.vars.Using = false
936 self.vars.Preparing = false
937 self.vars.Casting = false
938 self.vars.Channeling = false
939  
940 self:TriggerEvent(
941 "SpellStatus_SpellCastCancelAura",
942 self.vars.ActiveId, self.vars.ActiveName, self.vars.ActiveRank,
943 self.vars.ActiveFullName or self.vars.ActiveName, GetTime()
944 )
945 end
946  
947 --Failed is called only when it was semi possible to cast the spell
948 function SpellStatus:SPELLCAST_INTERRUPTED()
949 self:LevelDebug(2, "SPELLCAST_INTERRUPTED")
950  
951 TriggerFailureEvent(self, true)
952 end
953  
954 function SpellStatus:SPELLCAST_FAILED()
955 self:LevelDebug(2, "SPELLCAST_FAILED")
956  
957 TriggerFailureEvent(self, true)
958 end
959  
960 function SpellStatus:START_AUTOREPEAT_SPELL()
961 self:LevelDebug(2, "START_AUTOREPEAT_SPELL")
962  
963 self.vars.AutoRepeating = true
964 end
965  
966 function SpellStatus:STOP_AUTOREPEAT_SPELL()
967 self:LevelDebug(2, "STOP_AUTOREPEAT_SPELL")
968  
969 self.vars.AutoRepeating = false
970 end
971  
972 function SpellStatus:PLAYER_ENTER_COMBAT()
973 self:LevelDebug(2, "PLAYER_ENTER_COMBAT")
974  
975 self.vars.Attacking = true
976 end
977  
978 function SpellStatus:PLAYER_LEAVE_COMBAT()
979 self:LevelDebug(2, "PLAYER_LEAVE_COMBAT")
980  
981 self.vars.Attacking = false
982 end
983  
984 function SpellStatus:PLAYER_REGEN_DISABLED()
985 self:LevelDebug(2, "PLAYER_REGEN_DISABLED")
986  
987 self.vars.Combating = true
988 end
989  
990 function SpellStatus:PLAYER_REGEN_ENABLED()
991 self:LevelDebug(2, "PLAYER_REGEN_ENABLED")
992  
993 self.vars.Combating = false
994 end
995  
996 function SpellStatus:CHAT_MSG_COMBAT_SELF_HITS(chatMessage)
997 self:LevelDebug(2, "CHAT_MSG_COMBAT_SELF_HITS", chatMessage)
998 end
999  
1000 function SpellStatus:CHAT_MSG_COMBAT_SELF_MISSES(chatMessage)
1001 self:LevelDebug(2, "CHAT_MSG_COMBAT_SELF_MISSES", chatMessage)
1002 end
1003  
1004  
1005 --
1006 -- Final Registration of the library.
1007 --
1008 AceLibrary:Register(SpellStatus, MAJOR_VERSION, MINOR_VERSION, activate)
1009 SpellStatus = AceLibrary(MAJOR_VERSION)
1010  
1011