Este art铆culo pretende introducirte al concepto de un lanzamiento de hechizo (spellcast). Es algo importante que todo scripter debe conocer en resumen, porque los hechizos son uno de los principales "canales de interacci贸n" entre objetos del juego. Cada vez que robas el bolsillo de alguien como p铆caro (rouge), inicias un intercambio con otro jugador, usas un objeto o simplemente le haces da帽o a alguien usando magia, hay un hechizo involucrado. Cada hechizo se identifica por su entry spellId en spell.dbc. La clase SpellInfo es una interfaz C++ de esa tabla (entre otras tablas dbc y sql relacionadas). La mayor parte del proceso de lanzamiento se maneja dentro de una clase Spell que representa el estado din谩mico de cada lanzamiento. El comportamiento de esa clase puede verse afectado usando objetos de la clase SpellScript. Un mecanismo con un impacto tan grande sobre todo es complejo, as铆 que para simplificar nuestra visi贸n de lo que ocurre, divid谩moslo en varias fases. En el juego, ocurren en el mismo orden que en este art铆culo.
Esta fase es responsable de manejar la "petici贸n" de un lanzador de hechizo: el objeto que ha iniciado el lanzamiento. Una petici贸n puede hacerse desde el cliente de un jugador (ver SpellHandler.cpp), o desde los propios gameobjects. (GameObject::CastSpell, Unit::CastSpell, etc). Aqu铆, el worldserver valida y prepara un objetivo expl铆cito al que apunta el hechizo.
Dicho de forma simple, un objetivo de hechizo expl铆cito es el objetivo afectado por un hechizo. Por ejemplo, el objetivo de hechizo expl铆cito del Golpe heroico de un Guerrero es la unidad seleccionada actualmente, ya sea un jugador o un personaje no jugable.
El objetivo expl铆cito del lado del servidor se selecciona mediante el primer par谩metro de la funci贸n Unit::CastSpell.
Sin embargo, 隆no todos los hechizos requieren objetivos expl铆citos! Un ejemplo puede ser un hechizo de 谩rea de efecto, que no importa qu茅 selecciones en el juego, afecta a los objetivos que te rodean. Por tanto, el objetivo de hechizo expl铆cito puede ser null, y eso es natural.
En el caso de muchos otros hechizos, un objetivo expl铆cito puede ser tambi茅n una posici贸n en el suelo, como es el caso del hechizo de mago blizzard.
Como puede que hayas le铆do en el sistema de hechizos (Spell system), la base de datos decide la mayor parte del comportamiento del hechizo, y as铆 ocurre en este caso. El target, implicitTargetA e implicitTargetB de Spell.dbc deciden eso; brevemente: un flag en el campo target o un implicitTargetX puesto a uno de los modos de objetivo TARGET_XXX_TARGET (TARGET_UNIT_TARGET por ejemplo) significa que el hechizo requiere un objetivo expl铆cito. La consecuencia m谩s importante de esto es que NO PUEDES lanzar lo que quieras sobre lo que desees; todo lo decide con precisi贸n la base de datos del cliente y lo 煤nico que puedes hacer es seguir esas reglas. Adem谩s de la validaci贸n y preparaci贸n del objetivo expl铆cito del hechizo, tambi茅n se hacen algunas comprobaciones prematuras de la correcci贸n de la petici贸n de lanzamiento: se llama a una funci贸n Spell::CheckCast (que usa datos de la db para las comprobaciones); tambi茅n hay algunas comprobaciones hechas en las funciones de petici贸n de lanzamiento, desafortunadamente repartidas por todo el core. En caso de fallo, se env铆a un error; de lo contrario, el hechizo se encola para ejecutarse en la siguiente actualizaci贸n del objeto, o se maneja inmediatamente en el caso de los hechizos activados (triggered). Triggered es una especie de lanzamiento de "sistema"; no est谩 definido con precisi贸n qu茅 significa eso exactamente, ya que el t茅rmino se usa en exceso para tener un significado espec铆fico, pero establecer el flag de lanzamiento triggered altera mucho el comportamiento del hechizo y la interpretaci贸n de los datos de la db. Por ejemplo, los hechizos lanzados con el flag triggered (un par谩metro de CastSpell()) ignorar谩n los requisitos de objeto establecidos en el dbc, algunos requisitos de estado del lanzador, etc. Despu茅s de que el hechizo se prepara con 茅xito comienza el lanzamiento, ves la barra de lanzamiento en el juego. Puedes seguir el c贸digo de esta fase buscando las apariciones de la funci贸n Spell::Prepare en el core.
Una vez que la barra de lanzamiento se llena (en el caso de los hechizos instant谩neos, inmediatamente) comienza la fase de lanzamiento (cast). Durante esa fase se hacen varias cosas; una de las m谩s importantes es: la selecci贸n de objetivos impl铆citos del hechizo. Los objetivos impl铆citos del hechizo son los objetos del juego que se ver谩n afectados por tu hechizo. Su selecci贸n se basa en las columnas implicitTargetX de Spell.dbc, la tabla conditions y los hooks OnObject(Area)TargetSelect de SpellScript. No se hace nada a los objetivos en este punto (por favor, no rompas esa regla al usar scripts, no es blizzlike), simplemente se seleccionan para su procesamiento futuro. Al comienzo de esta fase se hace otra cosa importante: la segunda llamada a Spell::CheckCast (que puedes afectar usando el hook de spell script OnCheckCast y la tabla db conditions). Tambi茅n, los objetos requeridos y el poder se toman del lanzador en esta fase. Puedes engancharte a esta fase usando los hooks BeforeCast, OnCast, AfterCast. La fase entera se maneja en Spell::cast.
El lanzamiento (launch) viene inmediatamente despu茅s de que el cast termina; es el momento en que el hechizo "abandona las manos del lanzador", puedes notarlo en los hechizos que est谩n volando durante cierto tiempo antes de alcanzar los objetivos. Algunos efectos de hechizo se manejan durante esta fase; por ejemplo, el da帽o del lanzador debe calcularse en el momento en que el hechizo se lanza en lugar del momento del impacto, la carga debe comenzar en el launch, etc. Cuando (y si) tu hechizo alcanza su objetivo (inmediatamente para los hechizos sin retardo) comienza la siguiente fase (de impacto). El launch se maneja en Spell::HandleLaunchPhase. Puedes afectar la ejecuci贸n de los efectos de hechizo durante esta fase usando los hooks OnEffectLaunch y OnEffectLaunchTarget. La diferencia entre esos dos es que OnEffectLaunch se llama una vez por cada efecto de hechizo que tiene el hechizo, independientemente de sus objetivos; mientras que OnEffectLaunchTarget se llama una vez por cada objetivo impl铆cito disponible del hechizo (seleccionado en la fase de cast anterior).
El impacto (hit) es la fase donde se manejan la mayor铆a de los efectos del hechizo. Los efectos de hechizo son peque帽as operaciones que afectan al lanzador del hechizo o a los objetivos impl铆citos del hechizo. Cada entry de hechizo tiene columnas EffectX (en el dbc) que contienen el id de los efectos que ese hechizo aplica a su objetivo. Cada efecto tiene su propia lista de objetivos separada, as铆 que un 煤nico hechizo puede operar sobre muchos objetos diferentes a la vez. Por ejemplo, un hechizo puede aplicar un efecto de curaci贸n a tus amigos y darte a ti un aura de buff a la vez. De forma similar a la fase de launch, puedes sobrescribir el comportamiento de los efectos de hechizo en esta fase mediante los hooks de SpellScript OnEffectHit y OnEffectHitTarget. Tambi茅n puedes usar: los hooks BeforeHit, OnHit y AfterHit. Algo importante durante esta fase es el proc del hechizo: un sistema especial de activaci贸n de eventos que hace cosas seg煤n qu茅 auras est谩n aplicadas al lanzador y al objetivo impl铆cito del hechizo. Algunas partes del sistema de proc deber铆an manejarse por el sistema de proc en otras fases del lanzamiento del hechizo, pero eso no est谩 implementado por ahora.
La fase de finalizaci贸n (finish) ocurre despu茅s de que se procesan todos los objetivos del hechizo; es solo una limpieza, solo ocurren unos pocos eventos relevantes en esta fase.