Spell handling in TC

This article is meant to introduce you to the concept of a spellcast. It's an important thing for every scripter to know in brief how this works because spells are one of the main  "channel of interaction" between objects ingame. Whenever you pick someone's pocket as a rouge, init a trade with other player, use an item or simply hurt someone's ass using magic - a spell is involved. Each spell is identified by it's spellId entry in spell.dbc. SpellInfo class is a C++ interface to that table (among other related dbc and sql tables). Most of the cast process is handled inside a Spell class representing dynamic state of each cast. Behavior of that class can be affected using SpellScript class objects. A mechanism with such big impact on everything is complex, so to simplify our view of what's going on, let's split it into several phases. Ingame, they occur in the same order as in this article.

Spell prepare phase

This phase is responsible for handling the "request" from a spell caster - object which has initiated the cast. A request can be made from player client (see SpellHandler.cpp), or from the game objects itself (GameObject::CastSpell, Unit::CastSpell, etc). At this phase gameserver validates and prepares explicit target of the spell being cast. What is Explicit spell target? Ingame example is: your character has a spell, which has effect on an object you choose - by selecting the object with your character. In essence explicit spell target is the target, relatively to which spell selects who's going to be affected by the spell. As mentioned above, for client casts is most often the object you select. Serverside explicit target is selected by first parameter of Unit::CastSpell function. Not all spells require explicit targets though, a simple example is an AOE, no matter what you select ingame, targets around you are affected. Therefore, explicit spell target can be null, and that's natural. In case of many spells explicit target can be also a position on the ground, "blizzard" mage spell for example. What decides whether spell needs explicit target? As you may have read in Spell system , database decides about most of the spell's behavior, so is in this case. Spell.dbc's target, implicitTargetA, implicitTargetB decide about that, briefly - flag in target field or implicitTargetX set to one of TARGET_XXX_TARGET (TARGET_UNIT_TARGET for example) target modes mean spell requires an explicit target. The most important consequence of this is that you CANNOT cast anything you want on anything you wish, it's all precisely decided by client database and only thing you can do is to follow those rules. Besides explicit spell target validation and preparation there are also done some premature checks for correctness of cast request - a Spell::CheckCast funcion is called (which uses db data for checks), there are also some checks done in cast request functions unfortunately spread all over the core. On failure, error is sent, otherwise spell is enqueued for execution on next object update, or handled immediately in case of triggered spells. Triggered is a kind of "system" cast, it's not precisely defined what that means exactly as the term is overused too much to have any specific meaning, but setting the triggered cast flag alters a lot of spell's behavior and db data interpretation. As an example, spells cast with triggered flag (a parameter of CastSpell()) will ignore item requirements set in dbc,  some caster state requirements and so on. After spell is prepared successfully casting begins, you see castbar ingame. You can follow the code of this phase by searching for Spell::Prepare function occurrences in core.

Spell cast phase

Once castbar is full (in case of instant spells immediately) the cast phase begins. During that phase there are done several things, one of the most important is: spell implicit target selection. Spell implicit targets are ingame objects which will be affected by your spell. Their selection is based on implicitTargetX columns of Spell.dbc, conditions table and OnObject(Area)TargetSelect hooks of SpellScript. There's nothing done to the targets at this point (please don't break that rule while using scripts - it's unblizzlike), they're just selected for future processing. At the beginning of this phase another important thing is done: second call of Spell::CheckCast (which you can affect by using OnCheckCast spell script hook and conditions db table). Also, required items and power is taken in this phase from the caster. You can hook on this phase using BeforeCast, OnCast, AfterCast hooks. the whole phase is handled in Spell::cast.

Spell launch phase

Launch comes immediately after cast is finished, it's the moment when spell "leaves hands of the caster", you can notice that for spells which are flying for some amount of time before they reach targets. Some spell effects are handled during this phase, for example damage from caster must be calculated at the moment spell is being launched instead of the moment of hit, charge must begin at launch, etc. When (and if) your spell reaches it's target (immediately for spells with no delay) the next (hit) phase begins. Launch is handled in Spell::HandleLaunchPhase. You can affect execution of spell effects during this phase by using OnEffectLaunch and OnEffectLaunchTarget hooks. The difference between those two is that OnEffectLaunch is called once for each spell effect the spell has, regardless of it's targets; while OnEffectLaunchTarget is called once for every available implicit target of the spell (selected in cast phase before). 

Spell hit phase

Hit is the phase where most of effects of the spell are handled. Spell effects are small operations affecting either caster of the spell or implicit spell targets. Each spell entry has EffectX columns (in dbc) which contain id of effects that spell applies to it's target. Each effect has it's own separate target list, so a single spell can operate on many different objects at once. For example, a spell may apply heal effect to your friends and give you a buff aura at once. Similarly to launch phase, you can override behavior of spell effects in this phase by OnEffectHit and OnEffectHitTarget SpellScript hooks. You can also use: BeforeHit, OnHit and AfterHit hooks. Important thing during this phase is spell proc - special event trigger system which does things accordingly to what auras are applied to caster and implicit target of the spell. Some parts of proc system should be handled by the proc system in other spell cast phases, but that's not implemented atm.

Spell finish phase

The finish phase occurs after all spell targets are processed, it's just a cleanup, just a few relevant events happen in this phase.