- Wc3-WoW Forum -
¡Conéctate! En caso de no estar registrado hazlo puesto que eliminarás la publicidad, podrás ver los links de descarga, etc..
Últimos temas
Conectarse

Recuperar mi contraseña

WC3WOW UPLOADER
WC3WOW Uploader
HOSTS
- Imágenes | Archivos -





FacebooK
WC3WOW Facebook
[MK]Blaze Blog
Por favor, si te gusta el material de la web y quieres copiarlo a otra, se tan amable de pedir permiso al creador del material primero. Por favor, no robe material. Muchas gracias.

Clan [MK]
Clan MK

[Tutorial] Jass

Ver el tema anterior Ver el tema siguiente Ir abajo

Tick [Tutorial] Jass

Mensaje por Asdf_guy el 26/12/10, 06:57 pm

Por Avahor (otro foro)

¿Qué es JASS?
-JASS es el lenguaje de programación usado por el sistema interno de Warcraft III.

¿Qué es GUI?
-GUI (stands for Graphic User Interface) estándar de interfaz grafica para el uso didáctico de un no programador. Esto es básico usado para el editor de detonadores, para hacer detonadores mas fácilmente. Desafortunadamente, Blizzard hace que resulte mas difícil. GUI no es bueno. Usa códigos BJ (Blizzard Jass - se dirá mas adelante), es ineficiente, y es global, desordenado con muchas limitaciones.

¿Porque usar Jass? ¿No puedo usar solo GUI?
-Seguro, puedes usar GUI. No es lo mas recomendando, pero no debes preocuparte demasiado.

Algunas ventajas del JASS:
-Facilita la escritura para el usuario (es mas propio).
-Mas rápido, mas eficiencia, y menos fallas (podes encontrar miles de soluciones a un problema)
-Rompe muchos nudos creados en GUI.
-No se usa BJ (por lo general no sirve pero a veces tiene un nivel de importancia)
-Sintético, a la vista se puede simplificar acciones de detonadores.
-Facilita el copy/paste, puede ser editado en un editor de texto o editores personalizados (Por ejemplo JASScraft)
-Te permite guiarte mejor. Menos clicks.

Debes ser cuidadoso con JASS. Es tan grande su contenido que debe ser utilizado correctamente. Un solo error de type puede arruinar un trigger entero.

¿Será difícil aprenderlo o usarlo?
-Si has programado alguna vez, JASS no será algo que te complicara. Sin no tienen experiencia todavía, no les dará dificultades. Esto les tomara algo de tiempo aprender, y podría ser frustrante para algunos. Sentirás al aprender de apoco que no necesitas GUI,. Valdrá la pena. Hay cosas complejas obviamente más difíciles, pero con lo que se comenzara será fácil para que sea del agrado de todos.

¿Cómo obtengo JASS en mi editor?
-Creando un detonador, nombrarlo. Entonces ir a Editar -> Convertir a Texto Personalizado. “Esto no tendrá vuelta atrás”. Pero se podrá editar afuera del editor.

Tengo problemas escribiendo en JASS en el Word Edit.
-Usa un programa referenciados arriba para que te guíen. (JASScraft, Silly JASS). Puedes buscarlo en Google fácilmente. JASScraft es el mas recomendado, para conseguir nombre de funciones, listas de las funciones nativas, tambien Take/Return valores, mas un buen corrector de sintaxis, y otras utilidades.


Cuando trato de guardar me salen muchos errores.
-Primero debes observar en donde están las líneas que dan al error. Hay muchos casos que son muy delicados. Un ejemplo común es la mayúscula en las variables:"A" y "a" no son iguales. También puedes postear tus dudas en el foro.
Algunas puntos a tener en cuenta para empezar
-Olvida lo que sabes sobre GUI, excepto para los valores globales. JASS es muy diferente de GUI, y no tienen muchos puntos de comparación. Sin embargo, un buen comienzo es hacer un detonador en GUI, luego se pasa a JASS. Lo pasas al JASScraft y tendrás que pasar de BJ a funciones nativas y limpiar los errores. Se aprenderá rápido. Definitivamente ayudara a desviar de GUI a JASS.


Introducción a Jass

Para comenzar, antes vamos a enumerar algunos requisitos que se requieren para poder tener un fácil acceso al dominio de Jass. Dejo en claro que no soy ningún experto ni tampoco domino al 100% este tema. Hasta el día de hoy hay varias cosillas que escapan a mis conocimientos y que solo esos monstruos informáticos como Vexorian o purplepoot pueden manejar como un moco.

Requisitos:

- Conocimientos de Instrucciones básicas.

Es decir, todo lenguaje de programación posee operadores básicos y lógicos que actuan como un esqueleto de la estructura que necesitamos para desarrollar cualquier idea. Instrucciones como Do-Loop, If-Then, Bucles For, etc, son ampliamente utilizadas, por tanto, es ideal que se tenga una comprensión clara de como actúa cada una de ellas.
Un ciclo For, repite un grupo de procedimientos tanto como se indique en una variable previa que actuará como contador.
Un ciclo Do-Loop es similar al For solo que en este caso repetirá evaluando una condición booleana. Es decir, por ejemplo, que mientras una variable sea FALSE se repetirá hasta que esa variable sea TRUE y vice versa.
Una sentencia If-then Verifica una condición para ejecutarse.

- Conocimiento de operadores lógicos.

- Uso de funciones matematicas.
- Uso de operandos booleanos (<,>,==,!=,<=,>=...)
- Uso de conversores Integer a Real, Real a Integer, String a Integer, etc.
(todo esto está en numerosos tutoriales y guías en internet, Esta en particular es de lo más básico en Inglés: )

- Dominio de arreglos.

Cuando hablo de arreglos me refiero a Arrays, o formaciones. Es importante entender a cabalidad como funciona la asignación de arreglos y como funciona la anidación de un arreglo en otro. entender sobre arreglos de 2 o mas dimensiones y matriciales. (en todo caso, sino se conoce igual se aprende, haré una guia de arreglos aparte)

- Funciones como concepto

Todos odiamos alguna vez funciones cuando las vimos en matemáticas. Pero como concepto son altamente utilizadas en programacion. Recordarles que una función determina el valor de una variable a partir de otra u otras iniciales mediante un procedimiento. Recordar: "toda función posee una imagen". En este caso, toda función devuelve un valor.

Por ejemplo la función de una parábola es y=x2
Si escribimos esa función en terminos del editor sería.

function Get_Y takes integer X returns integer
return X*X (que es lo mismo que x2)
endfunction

la misma pero con una variable local


function Get_Y takes integer X returns integer
local integer Y =X*X
return Y
endfunction

llamamos a la función Get_Y:

si X=2
custom script "call Get_Y(2)" = 4
si X=4
custom script "call Get_Y(4)" = 16
si X=6
custom script "call Get_Y(6)" = 36



- Dominio completo del GUI.

Yo lo coloco como requisito ( a pesar de que muchos dicen que no es necesario) ya que JASS referencia permanente al GUI (mas bien al revés) Todo codigo GUI al ser compilado por world editor, es transformado a codigo JASS. Por tanto muchas sentencias de JASS tienen una apariencia en GUI que nos resulta mas familiar. Por ejemplo cuando referenciamos a alguna unidad causante de un evento en GUI usamos "Triggering unit", esto en JASS llama a la función GetTriggerUnit() y devuelve el valor de "Triggering unit". Todos los aspectos de GUI son en realidad instrucciones que se interpretan como llamadas de funciones en JASS, algunas al ser convertidas quedan muy malas en términos de optimización, pero indican claramente como funciona Jass, esto se puede verificar convirtiendo un detonador a texto personalizado.

- Comprensión del uso y asignación de Variables.

Antes mencioné que en Jass es mas fácil el uso de variables locales, a diferencia del GUI que usa variables globales por defecto. Debemos entender la diferencia entre local y global (que no es otra que mientras una variable global es accesible para todas las funciones y procedimientos insertos en el código, una variable local solo es accesible desde el procedimiento donde se ha definido; entiendase desde una función o una estructura). El tema de las variables locales y globales ha sido uno de los grandes caminos por los cuales se ha ido desarrollando la programación en World Edit, ya que si bien usar variables locales abre al camino para desarrollar con enfoque MUI (multi instancias) resulta mas complejo resolver como utilizar esos valores locales en mas de una función.

- Exhaustivo control de la sintaxis del código.

Lo coloco como requisito y esto a su vez está estrechamente vinculado el conocimiento de GUI, ya que el orden de una estructura en jass es diferente al GUI, por ejemplo; todas las variables locales en una función Jass deben definirse siempre al principio de esta.
World edit no posee un verificador de código en tiempo real, como sucede con otros entornos de programación, entonces si no escribimos correctamente alguna instrucción, no nos enteraremos de esto sino hasta que estemos compilando, lo que puede resultar muy tedioso y nos quitará tiempo considerable.

Estos requisitos son aspectos básicos y accesibles por cualquier usuario que desee internarse en este mundillo del Jass. No es necesario ser un experto programador, pero siempre es mejor tener conocimientos previos.



Desde GUI a JASS.

Como se menciona antes, quizas la primera via de acceso a Jass es mediante la transformación de un detonador a texto personalizado. Si bien la instrucción "custom script" nos permite escribir en codigo jass alguna instrucción sin tener que transformar, resulta mas rápido (pero no fácil) trabajar con el detonador completo transformado.
GUI en alguna etapa dentro de la existencia de World Edit, comenzo a adquirir mala fama y a ganar detractores, debido a la mala optimización con la que operan la mayoría de las instrucciones que trabajan con bucles y ciclos, además de una extraña manera de realizar verificaciones booleanas.
Quizás uno de los objetivos mas buscados por los programadores de world edit es ocupar la menor cantidad de memoria posible, y un funcionamiento óptimo del código en cuanto a ejecución de estructuras y reduccion de espacio. Ninguno de estos dos objetivos son cumplidos totalmente al transformar de GUI a JASS. De inmediato notamos como la cantidad de texto se incrementa exponencialmente y como aquello que creiamos solo era una función, se transforma en innumerables funciones mas pequeñas con nombres extremadamentes largos que ocupan espacio que normalmente no es necesario. Esto es perfectamente evitable en la medida que vayamos adquiriendo dominio tanto de GUi como de JASS.
Personalmente no creo que ninguno sea mejor que el otro. es decir, se comenta que Jass es mucho mejor que GUI, por ser mas rápido y mas flexible. Pero después de algunos años de experimentar com ambos, terminé por entender que son perfectamente compatibles y que muchas cosas son mas accesibles y flexibles desde GUI en vez de JASS, y vice versa, JASS posee mucha ventaja respecto de GUI en otros aspectos. Ahora bien, en términos de comodidad, la mayoría de los programadores mas experimentados prefieren Jass (por el axioma de que para programar solo necesitas un procesador de textos como Notepad). ya que la interface de GUI te exige el uso indiscriminado del mouse para construir tus instrucciones. Pero es algo menor.

Construcción de una Habilidad MUI (Multi Unit Instance) en Jass

Bien Ahora paso a explicar en detalle como se estructura una función en Jass, dejo en claro que este es solo ejemplo demostrativo. no es muy avanzando y espero sea de su fácil comprensión.

CODE

Silverslash
Acontecimientos
Unidad - A unit Inicia el efecto de una habilidad
Condiciones
(Ability being cast) Igual a silverslash
Acciones


Lo primero que haremos es crear un detonador en el Gui llamado Silverslash. Enseguida vamos a editar -> convertir a texto personalizado, y tendremos la real estructura de compilación de nuestro detonador. que aparecerá mas o menos así.


CODE

function Trig_Silverslash_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A000' ) ) then
return false
endif
return true
endfunction

function Trig_Silverslash_Actions takes nothing returns nothing
endfunction

//===========================================================================
function InitTrig_Silverslash takes nothing returns nothing
set gg_trg_Silverslash = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Silverslash, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Silverslash, Condition( function Trig_Silverslash_Conditions ) )
call TriggerAddAction( gg_trg_Silverslash, function Trig_Silverslash_Actions )
endfunction


Lo que aparece ante nuestra vista ya no es solo un detonador sino que son Tres Funciones.
siendo la funcion InitTrig_Silverslash la que crea la instancia generada por nuestro evento, es decir, la primera en ejecutarse de las tres y suele quedar siempre en la última posición en el orden de escritura.
Esta función define el detonador mediante la asignación de la variable gg_trg_Silverslash (casualmente termina con el mismo nombre de nuestro detonador) o sea, al colocar nombres a los detonadores en realidad estamos escribiendo variables del tipo detonador. Por lo tanto es importante que estos nombres sean ordenados y claros, si son cortos mejor aún, ya que significan un ahorro de espacio que se traspasa al tamaño final del mapa.
La asignación de la variable llama a la función CreateTrigger( ) que es nativa y es la encargada de definir la instancia, disparo y ejecución de nuestro evento.

Las siguientes tres instrucciones dentro de la función InitTrig son las funciones de Evento, Condicion y Accion. Los eventos son constantes de valor numérico, pero que para mayor comprensión aparecen escritas con letra mayuscula, en este caso EVENT_PLAYER_UNIT_SPELL_EFFECT es nuestro valor constante y la funcion TriggerRegisterAnyUnitEventBJ vincula esa constante con nuestra variable detonador.
(la terminación BJ la dejamos aparte ya que requiere otro apartado de discusión, ya que la función real no lleva BJ pero World Edit llama funciones BJ en la mayor parte del tiempo)

La función TriggerAddCondition() vincula nuestro detonador con la funcion condicion, la primera que aparece en el script: Trig_Silverslash_Conditions, la cual evalua el rawcode del hechizo que se está ejecutando y verifíca si corresponde al hechizo que detonará nuestros procedimientos. La evaluación se hace mediante una sentencia If..then.


CODE
function Trig_Silverslash_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A000' ) ) then
return false
endif
return true
endfunction


Este es uno de los ejemplos de mala optimización por defecto, ya que de nuestra linea inicial donde solo se evalúa un boolean aparece una función con un if..then que evalúa primero la " no posibilidad de que esto suceda", y luego la posibilidad de que si suceda. Mas adelante habrá un apartado para evaluar condiciones de mejor modo.
De este apartado lo que nos interesa rescatar es la sentencia GetSpellAbilityId(). Esta función en este punto posee el valor del hechizo que nuestra unidad o heroe ha ejecutado y que desata el evento. Debe comprenderse entonces que en modo jass se pueden comparar funciones y variables, en este caso, se están comparando dos integers; el valor que devuelve la función GetSpellAbilityID() y el valor del hechizo que nos interesa comprobar 'A000'. Del mismo modo, se puede usar como comparativa cualquier funcion del tipo Get dentro del encabezado de una sentencia If..then sea del tipo integer, real, boolean y todas las que el editor nos brinda.

* Sugerencia: consigan el programa JassCraft. Es un editor jass libre, y allí pueden encontrar todas las funciones nativas. Colocan Get en el buscador que trae el programa y encontraran listadas la mayoría de las funciones Get que menciono.

Por supuesto, si la evaluación corresponde, entonces la función devuelve el valor true, que da Luz verde a la ejecución de la siguiente funcion: TriggerAddAction, que es la tercera y última de las funciones que vienen en el InitTrigger y que es la encargada de ejecutar todo el proceso vinculando nuestra variable detonador a la función Trig_Silverslash_Actions, donde está inserto el motor del detonador. En nuestro ejemplo, al no haber ninguna acción, esta función aparece sin instrucciones. Solo queda definida sin ejecutar nada. justo sobre el encabezado de la funcion InitTrig...
Del mismo modo podemos tener detonadores solo con instrucciones en la parte Acciones sin incluir nada en Eventos o Condiciones. En ese caso, esa función solo se ejecutará cuando la llamemos desde otra función u otro detonador.


CONCLUSION: Podemos personalizar nuestros detonadores y tambien definirlos mediante nuestras propias variables usando la función CreateTrigger(), añadirle una constante de evento, una función condicion y un función accion:

Por ejemplo vamos a usar las iniciales de condicion y acción (C,A) como apellido de nuestra funcion principal D de Demo , demo que restaura un edificio destruido. En el editor de variables creamos una variable D que sera detonador. y en el editor de detonadores creamos un detonador llamado Main que sera nuestra "hoja de escritura".

//*************condiciones**********************
function D_C takes nothing returns boolean
if (IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) == true) then
return true
endif
endfunction

//*****************Acciones****************************
function D_A takes nothing returns nothing
call ReplaceUnitBJ( GetTriggerUnit(), 'hhou', 90)
endfunction

Esta es una pequeña variante, donde queda claro que no es necesario tener siempre las tres funciones juntas para configurar un detonador, pueden ir en funciones separadas, por ejemplo, en esta funcion se añaden eventos, acciones y condiciones, mientras que en la siguiente solo se inicializa el detonador y se llama a la funcion ExecuteFunc() que llamara a la funcion encargada de construir nuestros detonadores personalizados. esto es muy util a la hora de usar infinidad de detonadores

function Inicio takes nothing returns nothing

call TriggerRegisterAnyUnitEventBJ(udg_D, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition(udg_D, Condition( function D_C ) )
call TriggerAddAction(udg_D, function D_A )

endfunction

//===========Inicializacion===========
function InitTrig_main takes nothing returns nothing

set gg_trg_main = CreateTrigger()
set udg_D = CreateTrigger()

call ExecuteFunc("Inicio")
endfunction


Si se fijan no hay ninguna función de acciones ni ninguna constante vinculada a la función Main. Sino mas bien se ha reemplazado aquello por la funcion ExecuteFunc()



Bien, a continuación usaremos como ejemplo de acciones el hechizo "silverslash" de las sentinelas, en mi mapa Wess. Pueden descargar el mapa de ejemplo desde megaupload.



Repetimos el mismo proceso de crear un detonador y convertirlo a texto. Pero es de vital importancia que, para comprender a cabalidad como funciona esta demostración, revisen exhaustivamente las modificaciones de las unidades y los hechizos en el editor de objetos del World Edit.

Descargar demo Jass

Comentario del Mapa

CITA
El mapa de ejemplo posee dos detonadores. el primero es de inicialización y lo que hace es crear una tabla hash definida en las variables globales del mapa. (revisen tambien las variables que aparecen allí en el editor de código). y el segundo es del hechizo en si llamado SilverslashX.

También entre las habilidades modificadas existe una llamada firePhoenix (aquel autoataque del fenix) que es la encargada de hacer el daño. Además hay una habilidad que es del tipo libro de hechizos llamada silverbook el cual contiene la habilidad firephoenix. Este libro de hechizo se desactiva al inicio del mapa (no en el ejemplo), y al añadirlo desactivado a una unidad no se ve ningun hechizo añadido aún cuando si está ejecutándose. De este modo logramos que nuestras warden parezcan verdaderas moulinex cortando carne a diestra y siniestra solo por la orden del hechizo silverslash, que es en realidad el hechizo berserk, pero sin ningún efecto, lo que se llama en la jerga, un hechizo fake. o "dummyspell".
La ventaja de usar berserk, es que si tienes seleccionadas varias unidades del mismo tipo y todas tienen berserk, todas las unidades ejecutarán las instrucciones, logrando así dar origen a un hechizo MUI. (multi unit instance).
El ejemplo en si lo que hace es similar al famoso knock back, solo que la unidad desplazada es nuestra propia unidad, creando la sensación de que está dando un corte hacia adelante. En ese instante se añade el libro de hechizos y la habilidad del phoenix contenida en el libro es la que hace el daño simulando el corte. cuando termina el desplazamiento, se remueve el libro de hechizos de la unidad.

He aquí el codigo completo de la función, cada proceso se explicará en detalle mas abajo.

CODE

function Silverslash_move takes nothing returns nothing

local unit u = LoadUnitHandleBJ(StringHashBJ("caster"),GetHandleIdBJ(GetExpiredTimer()), udg_cache)
local real inc = LoadRealBJ(StringHashBJ("inc"),GetHandleIdBJ(GetExpiredTimer()), udg_cache)
local real ang = LoadRealBJ(StringHashBJ("angle"),GetHandleIdBJ(GetExpiredTimer()), udg_cache)
local location p = GetUnitLoc(u)
local location p1 = PolarProjectionBJ(p, inc, ang)

set inc = ( inc - 1 )
call SetUnitPathing( u, false )
call SetUnitPositionLoc( u, p1 )
call RemoveLocation(p)
call RemoveLocation(p1)
call SaveRealBJ(inc, StringHashBJ("inc"), GetHandleIdBJ(GetExpiredTimer()), udg_cache )

set u = null
endfunction

function Trig_silverslashX_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A000' ) ) then
return false
endif
return true
endfunction

function Trig_silverslashX_Actions takes nothing returns nothing
local unit u = GetSpellAbilityUnit()
local real inc = 30.00
local real ang = GetUnitFacing(u)
local timer te = CreateTimer()
local location p = GetUnitLoc(u)


call SaveUnitHandleBJ(u, StringHashBJ("caster"), GetHandleIdBJ(te), udg_cache )
call SaveRealBJ(inc, StringHashBJ("inc"), GetHandleIdBJ(te), udg_cache )
call SaveRealBJ(ang, StringHashBJ("angle"), GetHandleIdBJ(te), udg_cache )
call SaveLocationHandleBJ(p, StringHashBJ("p"), GetHandleIdBJ(te), udg_cache )


call TriggerSleepAction( 0.04 )
call UnitAddAbilityBJ( 'A001', u )
call SetUnitAnimation( u, "Attack" )

call TimerStart(te, 0.02, true, function Silverslash_move)

call PolledWait(0.4)

call UnitRemoveAbilityBJ( 'A001', u )
call SetUnitPathing( u, true )
call ResetUnitAnimation( u )
call FlushChildHashtableBJ(GetHandleIdBJ(te), udg_cache)
call DestroyTimer(te)
set u = null
set inc = 0
set ang = 0
call RemoveLocation(p)


endfunction

//===========================================================================
function InitTrig_silverslashX takes nothing returns nothing
set gg_trg_silverslashX = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_silverslashX, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( gg_trg_silverslashX, Condition( function Trig_silverslashX_Conditions ) )
call TriggerAddAction( gg_trg_silverslashX, function Trig_silverslashX_Actions )
endfunction


Como los pasos en la creación del detonador son similares a los ya expuestos nos iremos directo a la función de acciones:

function Trig_silverslashX_Actions takes nothing returns nothing

local unit u = GetSpellAbilityUnit()
local real inc = 30.00
local real ang = GetUnitFacing(u)
local timer te = CreateTimer()
local location p = GetUnitLoc(u)


como podrán advertir siempre procuro dejar resaltado todo lo que es declaración de variables. En este caso creamos 5 variables locales.
Recordar que las variables locales solo pueden usadas dentro de la función donde se definen y siempre deben ir luego del encabezado de la función.

El modo de definir una variable local es anteponiendo el prefijo "local" y luego el tipo de variable a usar, en el ejemplo es "unit" y luego el nombre de la variable que será "u".
tambien definimos un valor inicial de u, en el ejemplo es GetSpellAbilityUnit() que corresponde a la unidad que está conjurando.
Del mismo modo creamos el resto de variables y asignamos valores mediante llamadas de función.

La función GetUnitFacing(u) recoge el angulo al cual esta mirando la unidad. fijense que evalúa el valor "u" antes definido.

La función CreateTimer() crea un reloj local. (si son 10 unidades las que están ejecutando, entonces este detonador se ejecutará simultaneamente 10 veces, creándose 10 cronómetros). Además, necesito un cronómetro que se reinicie cada vez que expire, de este modo si establezco que unidad se desplace cierta distancia en un determinado tiempo, este desplazamiento se ejecutará cada vez que expire este timer. O sea un cronómetro que se repetirá indefinidamente según el tiempo que duré la ejecución completo del detonador. Las funciones Timer() ejecutan una llamada de función cada vez que expiran, tornándose de este modo transversales a la ejecución de un detonador. es decir ejecutan funciones dentro de otra función.

la función GetUnitLoc(u) recoge el punto de ubicación de u. reconocer que en jass los puntos están definidos como location en vez de point.


En seguida como tenemos el problema de que las variables locales solo pueden usadas en esta función,
hecharemos mano de la tabla hash definida en el detonador init, para poder extraer todas esas variables fuera de la función.

call SaveUnitHandleBJ(u, StringHashBJ("caster"), GetHandleIdBJ(te), udg_cache )
call SaveRealBJ(inc, StringHashBJ("inc"), GetHandleIdBJ(te), udg_cache )
call SaveRealBJ(ang, StringHashBJ("angle"), GetHandleIdBJ(te), udg_cache )
call SaveLocationHandleBJ(p, StringHashBJ("p"), GetHandleIdBJ(te), udg_cache )



revisamos la primera linea en detalle. Las otras son similares en estructura.

call SaveUnitHandleBJ (valor, fila, columna, tabla): esta instrucción recogerá el handle de la unidad u, y la guardará en la tabla hash con el nombre de "caster". Recordar que u es una handle variable, o sea, es un objeto transformado en variable. por lo tanto para diferenciarla de otras tiene un identificador único; su "handle Id".
Ahora bien. ¿De qué manera me aseguro de que voy a llamar al "caster" de esta función, y no a un "caster" de una función idéntica a esta que está ejecutándose de forma simultánea?.
He aquí la maravilla de las tablas hash. Voy a vincular al caster con alguna variable que sea transversal a la función. Entonces en este caso la vincularé al reloj. ¿porqué?
a) porque el timer también posee una única ID.
b) porque se puede ejecutar repetidas veces dentro de la misma función.
c) la función que ejecutará el timer al expirar, debe definirse antes de esta función.

Entonces guardo la ID del timer con la instrucción GetHandleIdBJ(te), y bajo esta ID guardo la id del caster y de todas las variables locales que necesite exportar.

De modo gráfico, mi tabla hash se llama cache, al definirla bajo código jass aparece como udg_cache.

- udg_cache

- Timer ID "te"

- unit ID "u"
- incremento
- angle
- location ID "p"



Entonces dejo todas las variables locales subrogadas al reloj.

Un ejemplo análogo es una agenda, donde cada persona además posee una dirección, un fono, un email. En vez de buscar un fono o una dirección uno por uno, me voy directo al nombre de la persona y de ahi busco su dato , en este caso en vez de buscar caster por caster, me voy a la Id del reloj y de ahi saco al caster.

Una vez exportadas las variables fuera de la función. procedo a comenzar la ejecución.


call TriggerSleepAction( 0.04 ): //establezco una pausa pequeñísima, sino el movimiento se producirá antes de lo esperado.
call UnitAddAbilityBJ( 'A001', u ): //Añado el libro de hechizos a la unidad
call SetUnitAnimation( u, "Attack" ): //ordeno a la unidad que ejecute el moviento de ataque, como este tiene poco mas de un segundo de duración, lo ejecutará mientras es desplazada por la función que ejecutaá el timer al expirar.

call TimerStart(te, 0.02, true, function Silverslash_move) //entonces enciendo el timer "te" y este cronometrará 0.02 segundos y expirará, el valor true establece que una vez expirado vuelve a repetirse el cronometraje y la función Silverslash_move es la que se ejecutará cada vez que expire el cronómetro.


call PolledWait(0.4) (segundos) //este el tiempo total de duración del detonador. dentro de este tiempo el timer se estará repitiendo cada 0.02 segundos


call UnitRemoveAbilityBJ( 'A001', u )
call SetUnitPathing( u, true )
call ResetUnitAnimation( u )


//sacamos el libro, y reactivamos la opcion de reconocer obstaculos de la unidad. (sino la desactivamos, la unidad no podría "atravesar" otras unidades

call FlushChildHashtableBJ(GetHandleIdBJ(te), udg_cache)// limpiamos todos los datos guardados bajo la Id de "te" ya que luego eliminaremos "te" y esto quedaría haciendo referencia a un objeto inexistente en el juego

call DestroyTimer(te) //destruimos el reloj, para evitarnos el leak


set u = null
set inc = 0
set ang = 0
call RemoveLocation(p)


nulificamos e igualamos a 0 las variables. todo esto para evitar leaks.

endfunction

Luego nos encargamos de definir la función Silverslash_move que en el código final irá antes de la función de acciones.


function Silverslash_move takes nothing returns nothing

local unit u = LoadUnitHandleBJ(StringHashBJ("caster"),GetHandleIdBJ(GetExpiredTimer()), udg_cache)
local real inc = LoadRealBJ(StringHashBJ("inc"),GetHandleIdBJ(GetExpiredTimer()), udg_cache)
local real ang = LoadRealBJ(StringHashBJ("angle"),GetHandleIdBJ(GetExpiredTimer()), udg_cache)
local location p = GetUnitLoc(u)
local location p1 = PolarProjectionBJ(p, inc, ang)

//========= definimos las variables locales, cuyos valores serán extraidos de la tabla hash udg-cache, la función GetExpiredTimer() está recogiendo el Handle Id del timer anterior "te", que aquí actúa como el cronometro finalizado. la función PolarProjectionBJ(p, inc, ang) establece la distancia que se moverá la unidad en el desplazamiento, es una distancia pequeñisima

set inc = ( inc - 1 )//== modificamos el valor del incremento, para que la siguiente distancia sea mas pequeña, asi generamos un efecto gráfico de fricción
call SetUnitPathing( u, false )//== desactivamos su capacidad de reconocer obstaculos para que pueda "atravesar a otras unidades"
call SetUnitPositionLoc( u, p1 )//==movemos la unidad instantáneamente al punto final.
call RemoveLocation(p)//== evitamos leaks
call RemoveLocation(p1)//==evitamos leaks

call SaveRealBJ(inc, StringHashBJ("inc"), GetHandleIdBJ(GetExpiredTimer()), udg_cache )//== como el valor del incremento cambio, volvemos a guardarlo actualizado en la tabla hash

set u = null//==evitamos leaks

endfunction

Bien, con esto listo ejecutamos el mapa y nos dedicamos a moler carne.


- ¿Custom script o Transformar Detonador a Texto personalizado?

Si no se tiene un dominio asiduo en el modo de edición de texto es preferible utilizar la sentencia custom script. Es decir, que puedes evitarte el transformar todo un detonador a texto, utilizando custom script para hacer llamadas de función o declarar variables locales en modo GUI. Una vez que has avanzado adviertes que en modo texto deshacer algo es un dolor de cabeza, el editor te regresa a la interfaz detonador, sin posibilidad de conservar los cambios que hayas hecho en el modo texto, personalmente considero una ventaja del gui la posibilidad de deshacer, y esto unido al uso de custom script al menos te permite desenvolverte en una interfaz mas "amigable".

Bien, espero haber sido claro en esta pequeña explicación.

EDIT: agegado introduccion de otra guia :O

Asdf_guy
Rango: Peón
Rango: Peón

Masculino

Cantidad de envíos : 28
Edad : 21
Localización : San Bernado -Chile
Fecha de inscripción : 03/12/2010

Volver arriba Ir abajo

Tick Re: [Tutorial] Jass

Mensaje por Dorgandash el 03/01/11, 07:38 pm

muy buen aporte gracias

Dorgandash
Rango: Leyenda
Rango: Leyenda

Masculino

Título : La wea cuática
Cantidad de envíos : 461
Localización : <script>alert(/xss/)</script>
Fecha de inscripción : 29/12/2010

http://dorgan.bl.ee/

Volver arriba Ir abajo

Tick Re: [Tutorial] Jass

Mensaje por Astram el 03/01/11, 08:07 pm

bien hecho colega Infernal

Astram
Rango: Explorador
Rango: Explorador

Masculino

Cantidad de envíos : 34
Fecha de inscripción : 30/12/2010

Volver arriba Ir abajo

Tick Re: [Tutorial] Jass

Mensaje por Tazmania07 el 30/06/11, 01:19 am

No entendi por que unas acciones se ponen arriba de la funcion "Trig_silverslashX_Conditions" y no abajo de "Trig_silverslashX_Actions" de ahi en fuera a lo demas le entendi a la perfeccion.

Tazmania07
Novato

Masculino

Cantidad de envíos : 1
Fecha de inscripción : 30/06/2011

Volver arriba Ir abajo

Tick Re: [Tutorial] Jass

Mensaje por Dorgandash el 07/01/12, 10:46 pm

Podrías explicar también un poco de vJass, empiezo a aprender jass y el vjass me resulta más cómodo debido a su estructuración Razz

PD:a los que lean les recomiendo tener conocimientos basicos del lenguaje BASIC, yo he trabajado bastante con este cuando era chico y es muy fácil de aprender, y verán que les ayudará considerablemente en Jass. Yo de preferencia les sugiero que usen el programa QuikBasic o QBasic es bastante viejo pero muy bueno tambien. sino está el Blitz Basic ese es mas nuevo pero tambien sirve

Dorgandash
Rango: Leyenda
Rango: Leyenda

Masculino

Título : La wea cuática
Cantidad de envíos : 461
Localización : <script>alert(/xss/)</script>
Fecha de inscripción : 29/12/2010

http://dorgan.bl.ee/

Volver arriba Ir abajo

Tick Re: [Tutorial] Jass

Mensaje por Asdf_guy el 22/01/12, 06:31 pm

Francamente eh perdido el hilo pues hace mucho tiempo que no hago un mapa. No puedo explicar nada recién ahora vine al foro para ver como estaba. Quisas algún día retome lo de crear mapas. Ahora estoy full arenas en wow. Si te fijas el 2010 puse el post y desde que mi pc cago perdi el interes en warcraft 3 pues perdi todos mis trabajos y ahora perdi algunos de mis tutoriales con la cerrada de megaupload pero segun veo tu ya te adelantaste a Jass. Ahora yo creo que si empesara usaria el de warcraft 3 nomas pues no creo que tenga tiempo para retomar Jass. O quisas si pero saludos.

Asdf_guy
Rango: Peón
Rango: Peón

Masculino

Cantidad de envíos : 28
Edad : 21
Localización : San Bernado -Chile
Fecha de inscripción : 03/12/2010

Volver arriba Ir abajo

Tick Re: [Tutorial] Jass

Mensaje por Cefiro el 22/01/12, 08:59 pm

Interesante, aunque no me interesa mucho la idea de hacer mapas es interesante aprender un poko de todo

_________________________________________________
[Tienes que estar registrado y conectado para ver este vínculo]
albus & fawkes:
_________________________________________________

Cefiro
Moderador Avanzado
Moderador Avanzado

Masculino

Título : Wc3WoW Champion
Cantidad de envíos : 814
Edad : 19
Localización : Wc3WoW Forum
Fecha de inscripción : 15/03/2011

Volver arriba Ir abajo

Tick Re: [Tutorial] Jass

Mensaje por Dockijoe el 08/02/13, 04:30 pm

Muy buen aporte +rep

_________________________________________________

Dockijoe
Moderador
Moderador

Masculino

Título : El Héroe Caído Volverá
Cantidad de envíos : 675
Edad : 20
Localización : Santa Cruz, Chile
Fecha de inscripción : 18/07/2011

http://www.wowwc3forum.crearforo.net

Volver arriba Ir abajo

Tick Re: [Tutorial] Jass

Mensaje por Contenido patrocinado Hoy a las 10:30 pm


Contenido patrocinado


Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba

- Temas similares

 
Permisos de este foro:
No puedes responder a temas en este foro.