TerraNet
CEO TN!
Crear Spells AoE (forma en GUI y vJASS)
Buenas, viendo un comentario de un usuario nuevo, se me ocurrió la idea de crear un tutorial para crear habilidades en AoE (esas que tienen area de efecto). Vamos a ver como hacer esto de una forma bien sencilla (les doy la base, después ustedes hacen lo que realmente quieran ), de las dos formas, en GUI y en vJASS.
GUI
Primero vamos con GUI. Les comento, que vamos a hacer una habilidad, en la que el caster, lanzará la habilidad, y todas las unidades, que estén en un AoE (Area de efecto) de X (275 por ejemplo) rango se quemarán.
Antes que nada, vamos a necesitar algunas variables en GUI:
[Tienes que estar registrado y conectado para ver esa imagen]
Una vez que las tenemos, pasamos a crear las habilidades. Para este caso, necesitamos crear la habilidad principal (a base de Silence) y una habilidad dummy (para el quemado).
Después de que creamos las habilidades, necesitamos crear 1 unidad dummy.
Si no quieren hacer todo esto, bajense mi map, y seguimos...
[Tienes que estar registrado y conectado para ver este vínculo]
Bien, ya que tenemos todo, pasamos a los detonadores:
Creamos un nuevo detonador llamado AoE (o como ustedes quieran), y le ponemos lo siguiente:
[gui]AoE
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Spell
Actions
Set i = (i + 1)
[/gui]
Se preguntarán, ¿para qué la variable i que se suma a +1? Para que el spell sea MUI.
Bien, seguimos:
[gui]AoE
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Spell
Actions
Set i = (i + 1)
Set caster[i] = (Triggering unit)
Set pTmp[i] = (Target point of ability being cast)
Set gTmp[i] = (Units within 275.00 of pTmp[i] matching (((Owner of (Triggering unit)) is an enemy of (Owner of (Matching unit))) Equal to True))
[/gui]
caster = Unidad que lanzó la habilidad
pTmp = Punto a donde se lanzó la habilidad (p = punto - Tmp = temporal)
gTmp = Grupo en donde almacenaremos a todas las unidades que esten en el AoE del spell
Como se podrán dar cuenta, cuando le dimos valor a gTmp, le dijimos que guardara a todas las unidades en un rango de 275 que cumplan con una condición. ¿Cuál es esa condición?, que la unidad que está queriendo ser guardad, sea ENEMIGA de la unidad que lanzó la habilidad.
Ahora que ya tenemos todas las unidades en el grupo, vamos a trabajar con ellas quemándolas :
[gui]AoE
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Spell
Actions
Set i = (i + 1)
Set caster[i] = (Triggering unit)
Set pTmp[i] = (Target point of ability being cast)
Set gTmp[i] = (Units within 275.00 of pTmp[i] matching (((Owner of (Triggering unit)) is an enemy of (Owner of (Matching unit))) Equal to True))
Custom script: call RemoveLocation(udg_pTmp[udg_i])
Unit Group - Pick every unit in gTmp[i] and do (Actions)
Loop - Actions
Set pTmp[i] = (Position of (Picked unit))
Unit - Create 1 dummy for (Owner of (Triggering unit)) at pTmp[i] facing Default building facing degrees
Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
Unit - Add Quemado dummy to (Last created unit)
Unit - Order (Last created unit) to Neutral Fire Lord - Soul Burn (Picked unit)
Custom script: call RemoveLocation(udg_pTmp[udg_i])
Custom script: call DestroyGroup(udg_gTmp[udg_i])
Set caster[i] = No unit
Set i = (i - 1)
[/gui]
¿Para qué son los custom scripts que se llaman en este detonador?
Para evitar leaks (recuerden, si su mapa tiene leaks, a la larga se laguea el mapa. Si tienen muchos, hasta se puede llegar a cerrar el Warcraft 3).
Como mencioné arriba, lo que hacemos en este último detonador, es trabajar con todas las unidades que estén en el grupo de unidades afectadas.
Lo que hacemos, es crear 1 unidad dummy, ponerle tiempo de expiración (cuando se termina ese tiempo, la unidad desaparece), y darle la habilidad de quemado que creamos anteriormente.
Vean bien el detonador así lo entienden con claridad .
Mapa de ejemplo: [Tienes que estar registrado y conectado para ver este vínculo]
Como pueden ver, no es nada complicado, y les recuerdo que la habilidad que acabamos de crear es completamente MUI (es decir, que la pueden lanzar varias unidades al mismo tiempo, y no habrá ningún inconveniente).
vJASS
Ahora le tocó el turno a vJASS, vamos a hacer lo mismo .
Primero que nada, si no leyeron lo de arriba, bajense este mapa: [Tienes que estar registrado y conectado para ver este vínculo] (contiene unidades, spells y demás que vamos a usar acá).
Pasamos directamente al código:
[jass]library AoE initializer Init
private function Conditions takes nothing returns boolean
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endlibrary[/jass]
Por ahora nada del otro mundo, simplemente creamos el detonador y le pusimos 1 condición.
Vamos a crear algunas globales para simplificar el trabajo:
[jass]library AoE initializer Init
globals
private constant integer RAWCODE = 'A000'
private constant integer DUMMY = 'h000'
private constant integer RAWCODEQUEMADO = 'A001'
endglobals
private function Conditions takes nothing returns boolean
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endlibrary[/jass]
Simples globales para almacenar el rawcode de las habilidades y de la unidad dummy.
Ahora si, pasamos a lo importante :
[jass]library AoE initializer Init
globals
private constant integer RAWCODE = 'A000'
private constant integer DUMMY = 'h000'
private constant integer RAWCODEQUEMADO = 'A001'
endglobals
private function Conditions takes nothing returns boolean
local unit caster
local real x
local real y
local group g
local unit j
local unit dummy
if GetSpellAbilityId() == RAWCODE then
set caster = GetTriggerUnit()
set x = GetSpellTargetX()
set y = GetSpellTargetY()
set g = CreateGroup()
call GroupEnumUnitsInRange(g, x, y, 275.)
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endlibrary[/jass]
caster = Unidad que lanzó el spell
x = Coordenada x de a dónde lanzó el spell
y = Coordenada y de a dónde lanzó el spell
g = Grupo en el que almacenaremos todas las unidades afectadas por el spell
j = Esta variable nos servirá para trabajar despues con el grupo
dummy = Unidad dummy
Seguimos un poco más:
[jass]library AoE initializer Init
globals
private constant integer RAWCODE = 'A000'
private constant integer DUMMY = 'h000'
private constant integer RAWCODEQUEMADO = 'A001'
endglobals
private function Conditions takes nothing returns boolean
local unit caster
local real x
local real y
local group g
local unit j
local unit dummy
if GetSpellAbilityId() == RAWCODE then
set caster = GetTriggerUnit()
set x = GetSpellTargetX()
set y = GetSpellTargetY()
set g = CreateGroup()
call GroupEnumUnitsInRange(g, x, y, 275., null)
loop
set j = FirstOfGroup(g)
exitwhen j == null
call GroupRemoveUnit(g, j)
endloop
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endlibrary[/jass]
En vJASS ésta es la forma de trabajar con grupos, mediante loops. Lo que hacemos, es darle valor a la variable "j", ¿qué valor?, la primera unidad del grupo "g". Luego de darle valor, removemos a la unidad "j" del grupo "g" y así hasta que no haya ninguna unidad en el grupo.
Seguimos (parte final):
[jass]library AoE initializer Init
globals
private constant integer RAWCODE = 'A000'
private constant integer DUMMY = 'h000'
private constant integer RAWCODEQUEMADO = 'A001'
endglobals
private function Conditions takes nothing returns boolean
local unit caster
local real x
local real y
local group g
local unit j
local unit dummy
if GetSpellAbilityId() == RAWCODE then
set caster = GetTriggerUnit()
set x = GetSpellTargetX()
set y = GetSpellTargetY()
set g = CreateGroup()
call GroupEnumUnitsInRange(g, x, y, 275., null)
loop
set j = FirstOfGroup(g)
exitwhen j == null
call GroupRemoveUnit(g, j)
if IsUnitEnemy(j, GetTriggerPlayer()) then
set dummy = CreateUnit(GetTriggerPlayer(), DUMMY, GetUnitX(j), GetUnitY(j), 0.)
call UnitApplyTimedLife(dummy, 'BTLF', 2.)
call UnitAddAbility(dummy, RAWCODEQUEMADO)
call IssueTargetOrder(dummy, "soulburn", j)
set dummy = null
endif
endloop
call DestroyGroup(g)
set caster = null
set g = null
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endlibrary[/jass]
Bueno, y acá ya terminamos.
Como podemos ver, si la unidad j (dentro del loop) es enemiga del jugador que lanzó la habilidad, entonces creamos 1 dummy, le damos tiempo de expiración y le agregamos la habilidad.
Por último, le ordenamos a la unidad dummy que lance la habilidad dummy de quemado.
Luego de eso, nulleamos variables para evitarnos los leaks .
Mapa de ejemplo (contiene el detonador en GUI y en vJASS): [Tienes que estar registrado y conectado para ver este vínculo]
Saludos
Créditos para Suron!