Versiones comparadas

Clave

  • Se ha añadido esta línea.
  • Se ha eliminado esta línea.
  • El formato se ha cambiado.
Comentarios: Correction of some typos.

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 rouguerouge, init a trade with other player, use an item or simply hurt someone's ass using magic - a spell is involved. Each spell is indentified 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. Behaviour 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 it, let's split it into several phases. Ingame, they occur in the same order same 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 decices whenever decides whether spell needs explicit target? As you may have read in Spell system , database decides about most of the spell's behaviourbehavior, 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 unfortunally 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 too overused too much to have any specific meaning, but setting the triggered cast flag alters a lot of spell's behaviour 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::(lengua)repare Prepare function occurences 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 begining beginning of this phase another important thing is done: second call of Spell::CheckCast (which you can affect by using OnCheckCast spell scrpt 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.

...

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 aplies 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 behaviour 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.

...