WoWInterface (
-   Lua/XML Help (
-   -   Catching spellcasting reliably (

Gorak 10-05-05 04:14 AM

Catching spellcasting reliably
Hello !

As we know, spells with casting time generate two event, SPELLCAST_START when begun and SPELLCAST_STOP when stopped. Instant-cast spells only generate SPELLCAST_STOP. Channeled spells generate SPELLCAST_CHANNEL_START, SPELLCAST_CHANNEL_UPDATE and SPELLCAST_STOP.

For interruptions, SPELLCAST_INTERRUPTED is posted when an external operator, such as a skill or spell interrupts casting (Rogue kicks or mage counterspells). SPELLCAST_FAILED is posted when a spell gets resisted, for all spells, including instant cast. This information is available from WoW Wiki.

Now, a common scenario to accomplish catching spellcasting is to use a SPELLCAST_STOP-event logger in conjuction with a function hook to CastSpell and UseAction. However, if the player interrupts a casting-time or channeled spell by moving, it seems that SPELLCAST_STOP is generated first, immediately followed by SPELLCAST_INTERRUPTED.

Now, does anyone know what really happens if spellcasting is interrupted by an external operator ? Do we still receive SPELLCAST_STOP and SPELLCAST_INTERRUPTED right after each other ? And what about spell getting resisted ? Do we receive SPELLCAST_STOP and SPELLCAST_FAILED in sequence ? What is the logic behind all these events ?

Littlejohn 10-05-05 07:14 AM

I can't answer your question, but I can give you advice. ;) Many people have tried to catch spellcasting with mixed success -- there seem to be many corner cases to trip on. I doubt the existing implementation and event ordering is Blizzard's final solution, so you should probably avoid as many dependencies on this as possible. For example, instead of hooking functions, you may want to write explicit wrapper functions that can be used with macros and buttons.

Gorak 10-05-05 10:23 AM

It might be that Blizzard will change the behaviour at some point. I do hope there'll be Patch Notes that warrant these changes, though..

However, I have done a huge amount of work already on an add-on and changing it completely at this point doesn't seem valid.

I did some extensive testing today, and here are the results of the tests. I hope they will help people to develop their add-ons. Also, if someone has a WoW Wiki account, I would be very grateful if they uploaded the data into the database. The events are in upper case, followed immediately by the arguments found in paranthesis. Remember that other events might happen simultaneously with these. Regardless, the events posted are relevant only to the current thing the player is doing.

When casting a spell which has a casting time, following identifiable cases were found:
- Started casting a spell: SPELLCAST_START (arg1 = spell name, arg2 = casting time in msec)
- Spellcast delayed due to damage: SPELLCAST_DELAYED (arg1 = time delayed, in msec)
- Completed casting a spell: SPELLCAST_STOP (no arguments)
- Player moves while casting: SPELLCAST_STOP (no arguments). Followed immediately by CHAT_MSG_SPELL_FAILED_LOCALPLAYER (arg1 = "You fail to cast <spellname>: Interrupted."). Followed by SPELLCAST_INTERRUPTED (no arguments)

When channeling a spell:
- Started channeling: SPELLCAST_CHANNEL_START (arg1 = channeling duration in msec, arg2 = "Channeling"). Followed immediately by SPELLCAST_STOP (no arguments)
- Losing channeling time due to damage: SPELLCAST_CHANNEL_UPDATE (arg1 = remaining duration in msec)
- Completed channeling: SPELLCAST_CHANNEL_UPDATE (arg1 = 0). Followed immediately by SPELLCAST_STOP.
- Player moves while channeling: SPELLCAST_CHANNEL_UPDATE (arg1 = 0). Followed immediately by SPELLCAST_STOP.

When casting a spell without casting time (instacast)
- Started/finished casting: SPELLCAST_STOP (no arguments)

The following are universal cases:
- Target of spell is invalid, such as friendly or you have a more powerful buff active: SPELLCAST_FAILED (no arguments). This is preceded by an appropriate CHAT_MSG_SPELL_ message. For example, CHAT_MSG_SPELL_FAILED_LOCALPLAYER (arg1 = "You fail to cast <spellname>: Invalid target."). Followed by SPELLCAST_FAILED.

- Player moving before casting a spell with casting time: CHAT_MSG_FAILED_LOCALPLAYER (arg1 = "You fail to cast <spellname>: Can't do that while moving.). Followed by SPELLCAST_FAILED (no arguments).

- Finished casting a spell (instant or otherwise) but target is immune: SPELLCAST_START (non-instants), SPELLCAST_STOP, followed by CHAT_MSG_SPELL_SELF_DAMAGE (arg1 = "Your <spellname> failed, <targetname> is immune.")

- Finished casting a spell (instant or otherwise) but target resists. SPELLCAST_START (non-instants), SPELLCAST_STOP, followed by CHAT_MSG_SPELL_SELF_DAMAGE(arg1 = "Your <spellname> was resisted by <targetname>.")

I hope all this data will be helpful to someone. It was helpful to me. Now my add-on can detect 90% of cases it needs with reliable accuracy :)
And yeah, hooking CastSpell and UseAction will catch the following situations: casting spell from Action Bar (UseAction), creating tradeskill item (CastSpell), casting spell from spell book (CastSpell).

- Gorak

All times are GMT -6. The time now is 02:57 PM.

vBulletin © 2022, Jelsoft Enterprises Ltd
© 2004 - 2021 MMOUI