vanilla-wow-addons – Blame information for rev 1
?pathlinks?
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 |