Perfil
BienvenidaPreferenciasAvatarFirma
Recargar
¿No quieres problemas? pásate y lee esto.
¿Eres nuevo? Que esperas preséntate acá.
Visitamos en nuestra pagina de Facebook y dale me gusta! aquí!
Síguenos en Twitter y entérate de que pasa en nuestra comunidad!

Ver el tema anterior Ver el tema siguiente Ir abajo  Mensaje [Página 1 de 1.]

1default el Jue Nov 18, 2010 2:26 pm - [GUIA] Jass

Notas acerca del Tuto



    • Este tutorial va a tratar de explicar como programar en JASS.
    • La Traducción esta hecha por mi, si tiene alguna duda la pueden postear.
    • El autor de este tutorial, no habla precisamente el ingles (o sea le cuesta escribir un poco en ingles), algunas palabras son muy repetitivas y trate de cambiarlas un poco con mis palabras.
    • Si ven algo mal traducido o que les parece que no esta bien, posteenlo
    • La razón por la que lo traduje es que faltaba una guía.
    • Espero que lo sepan apreciar ya que me tardo un buen tiempo traducirlo y por demoras como el estudio y demás
    • La fuente de la pagina es de wc3campaings.net






------------------------------------------------------------------------------------------------------
Aprendiendo JASS

Link de Descarga: --->[Tienes que estar registrado y conectado para ver este vínculo]







            Introduccion a JASS





¿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 el 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. [Tienes que estar registrado y conectado para ver esa imagen]

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.

Bien, aprendí lo básico. ¿Y ahora que?
-Si tu quieres aprender mas, leé los tutoriales siguientes, por Wyrmlord. Es casi un maestro de las funciones básicas. También habrá tutoriales intermedios y mas adelantes para mas avanzados.

----------------------------------------------------------------------------------------------------------------------------------------------



        Lección nº 1: Una Función Simple








            Descripcion General






En esta lección, Se vera una función muy fácil de hacer como ejemplo. Se explicara lo que necesitara saber acerca de esto y al final habrá un desafío como ejercicio. Contendrá conocimientos para pasar a la próxima lección.
Ahora que miraste la introducción a JASS, probablemente estarás ansioso por empezar a programar,¿Correcto? Ahora, olvidar GUI ('triggers' comunes), JASS es diferente de GUI, se tratara de otra manera. Ahora, abrir un editor de texto editor como el Bloque de Notas o algún otro dependiendo el que te guste o el que tengas a mano.
Para comenzar mostrare un código. Podrá ser un poco confuso al principio, pero explicare de qué se trata en esta lección.


function HolaMundo takes nothing returns nothing

    call BJDebugMsg("Hola Mundo")
endfunction

No pongas esto en el editor todavía porque no esta completo. Antes que nada, comienza con la primer línea. JASS, como muchos lenguajes de programación esta hecho a partir de una serie de funciones. No entraremos en detalles aun, por el momento solo sabremos que estamos declarando o creando una función.

La siguiente Linea:

call BJDebugMsg("Hola Mundo")

Esta línea 'call' llama a una función. Funciones son como acciones, si usaste GUI antes esto ejecutara un comando. Esta particular función pone el texto "Hola Mundo" (sin las comillas) en la pantalla.

endfunction
La línea final es simple, cuando declaras/creas una función es necesaria para finalizar en determinado lugar. Dice la función termina acá.

Siguiendo, Hemos visto un ejemplo básico de JASS, si tu deseas crear esta función en el World Edit. Los pasos a seguir son:
    1. Crear un nuevo mapa
    2. Ir al editor de Detonadores
    3. Clickea sobre el icono (mapa) arriba de todos los triguers.
    4. Pega el código anterior.

Ahora, crear un trigger, puedes hacer este evento siempre que tu quieras, se sugiere que se active cuando tocas una flecha del teclado. Para la acción, debes poner en custom script, en la caja de texto:

call HolaMundo()
Entonces podrás probarlo.

Importante: como puedes llamar una función en esa línea. Se retomara un poco la declaración de funciones. Cuando llamas a una función

'call ( , , )'

Básicamente dice como se usa un tipo call, seguido por el nombre de la función y paréntesis '()'. Si la función requieres cierta información (se pondrá en paréntesis) es para una información especificada. Cada uno de estos separados por coma ','

Esta función en particular solo requiere una cadena de texto (mensaje (string)) para mostrar en la pantalla
:
function HolaMundo takes nothing returns nothing

Cuando una función contiene el texto 'takes nothing', significa que no necesitas ningún valor en los paréntesis al llamarlos.
El return es un valor que devuelve la función. Como si crearas una función CrearUnidad devuelve una unidad. Si estas confundido, no te preocupes ya que se profundizara en la próxima lección.

Ya tiene la libertad para modificar la función HolaMundo, agregar mas calls a el BJDebugMsg, mostrara el texto que quieras. El texto deberá estar dentro de las comillas de esta manera “texto”.

Desafío para Trabajo #1: Modificar la función HolaMundo para mostrar otra información:
Acá un ejemplo:

function HolaMundo takes nothing returns nothing

    call BJDebugMsg("Hola, me llamo Pablo.")
    call BJDebugMsg("Tengo 2 años")
//Puedes dejar comentarios de esta manera para poder acordarse de algunas cosas o explicar
//Puedes dejar comentarios después de '//'

endfunction

Puede parecer una pérdida de tiempo, pero cuanto más JASS practique más se familiarizara con él.

----------------------------------------------------------------------------------------------------------------------------------------------




          Lección nº 2: Variables







          Por: Darkwulfv,




¿Qué es una variable?
-Una variable es como una especie de lugar de almacenamiento para un dato u otro objeto. Hay dos tipos de variables. Locales y Globales.

¿Cual es la diferencia entre variable Locales y variables Globales?
-Las Locales son variables solamente usadas por la función. Estas mismas se declaran adentro de esa función. Son usadas para tener mas limpia y rápida la memoria (se explicara después), hace los códigos mas ligeros, y hace script Multi – instancias. Puede haber en funciones distintas var Locales con el mismo nombre.
-Las Globales son variables con el cual puede ser accedida por cualquier función, también puede ser modificada por cualquier función. Puede tener sus contras en casos multi-instancias (no referiremos como MUI), se discutirá mas adelante.

¿Cómo crear una variable Local?

-Estas son dos ejemplos de crear/establecer una variable Local.
function varLoc takes nothing returns nothing

    local unit u = Createunit()
endfunction

Este método crea y luego modifica la variable, estas van al comienzo de la función.


function varLoc takes nothing returns nothing
    local unit u
set u = Createunit(…..) //Crea una unidad y modifica la variable
endfunction

Y este metodo creara un variable en blanco, que se modificara después sobre la funcion.

Si quiero que el valor cambie, ¿significa que debemos crear otra variable?-No, no necesariamente. Se necesita poner “set tu_variable = nuevo_valor”
Un ejemplo:


function variable takes nothing returns nothing
    local unit u = Createunit(…)
    //Otra accion
    set u = otra_unidad //la variable sera alguna otra unidad, no es tan necesario este ejemplo
endfunction

Recordar aunque, el viejo valor no modificara la variable, entonces si queres 2 diferentes unidades, usa 2 diferentes variables.

Tengo mi var Local. ¿Qué sigue ahora?-Un ejemplo.


function Killunit takes unit u returns nothing

-Si notaste, Killunit necesita una unidad. Por lo tanto, puedes completar esto con muchas cosas, como GetTriggerunit(), GetSpellAbilityunit(), o alguna función que devolverá una unidad. Sin embargo, una variable puede ser una unidad, entonces puedes ponerla en vez de la otra. Acá una comparación parte por parte.


function variable_testA takes nothing returns nothing
    local unit u = GetTriggerunit()

    call Killunit(u)
endfunction


function variable_testB takes nothing returns nothing
    call Killunit(GetTriggerunit())
endfunction

Ambos trabajan igual, solo debes elegir cual preferir.
Nombrando variables
Cuando nombramos variables, no puedes usar cualquier nombre. Primero, solamente caracteres que se usan en el alfabeto, cualquier numero, y el carácter especial (_). El primer carácter en el nombre de la variable debe ser una letra (a,b,c etc), después se pueden añadir números, letras, y (_). No se pueden poner espacios en el nombre de la variable.

¿Qué es una variable Global?
-Las variables Globales son creadas por el Editor de Variables, adentro del Editor de Detonadores. Estas variables pueden ser usadas en cualquier función, a diferencia de las locales. Ejemplo:


function A takes nothing returns nothing
    call Killunit(udg_u)
endfunction


function B takes nothing returns nothing
    call Killunit(udg_u)
endfunction

Esto es básicamente lo que significa. Una variable comienza con “udg_” usualmente significa que es global. Puedes hacer estas cosas con las var locales, pero no es aconsejable. Si necesitas hacer referencia a la misma unidad en una función diferente, hay formas de hacerlo que se discutirán más adelante. Los nombres de las variables que se crea será udg_Nombre_Var. Los supuestos espacios en blanco podrá ser diferencia con '_'.

¿Qué es una perdida de memoria?
- Siempre que una variable, handle, o string es creada, el juego debe hacer un espacio para su uso. Para deshacerse de ese espacio, existen varios métodos que puede usarse en función del objeto.
Por ejemplo, si había un efecto especial, puede ser borrado y liberado todo el espacio que estaba usando. Las pérdidas de memoria se producen cuando un objeto no está en condiciones de ser borrado, y se quedará en la memoria hasta el final del juego.
Otro ejemplo: supongamos que creara otro efecto especial, y una variable se modifica en si misma. El efecto especial que se esta usando en la memoria (incluso si no puede ser visto), es incapaz de ser borrada, y seguirá utilizando la memoria hasta el final del juego. Las variables Locales que no son enteras, reales, o booleanas seria demasiado. La solución para ellos es simplemente el establecimiento de un valor null (nulo o cero) al final de la función. Los strings consumen memoria, pero no se puede hacer mucho con esto.

¿Cómo arreglar estos errores?
En próximas lecciones se especificara acerca de esto mas detalladamente.


Arreglos (Formación, Array, Matrices etc.). ¿Qué significa?
-Un arreglo es una variable con más de una opción del mismo tipo. Es como un índice de para tipos de variables, una especie de librería donde se almacenan. Para acceder a esas variables, se tiene que indicar un número de índice.

Ejemplo:

function variable_test takes nothing returns nothing
    local unit array u
    set u[1] = GetTriggerunit()
    set u[2] = GetSpellTargetunit()
    call Killunit(u[1])
    call Killunit(u[2])
    set u[1] = null
    set u[2] = null
endfunction

Las funciones pueden tener adentro unos corchetes [] (como en el ejemplo) es ahí donde va el índice de la ubicación donde se encuentra, y para establecerles un valor.

Aclaraciones:
Esto es sólo para tener las mimas explicaciones, por posiblemente lectores confundidos. Los Arreglos son un montón de variables comprimidas dentro de una sola. Para ser exacto, 8192 variables.(valor max)
Para declarar un “array” en JASS, debes hacer algo como esto:
local integer array arreglo_entero
La diferencia es agregar la palabra "array" antes del nombre de la variable. No podrás darle un valor al array en la misma línea donde lo declaraste, recuérdalo.
Necesitaras saber como acceder y modificar las 8192 partes de cada arreglo (o los que necesites). Hazlo como una variable normal, solamente pon los corchetes [] después de la variable con un entero entre un numero de 0 a 8191.
Un ejemplo:


local integer array misEnteros //declaración del entero de arreglo
set Enteros[0] = 5 //Dando a la posición 0 un valor 5 dentro del array
set Enteros[1] = Enteros [0] + 2 //Da en la posición 1 del array el valor de la posición 0 del array + 2
set Enteros[Enteros[1]] = 2
//Esto esta mostrando que puedes usar una variable dentro de los corchetes, no es necesario que sea de arreglo


No se recomienda usar arreglos para algo tan simple como esto. Un arreglo puede contener 8192 valores, no mas ni menos. Los arreglos deben ser usados para casos mas puntuales.

Si deseas ver una lista de todas las variables, abrir el common.j en el archivo Patch.mpq. O si no estas seguro en la herramienta JassCraft, tiene el listado de estos programas en su base de datos. Sobre el botón "show options". Clic, y luego desmarque en todo el "search for" excepto types. Luego "hide options" y buscar los tipos de variables.

Existen algunas variables principalmente de estos tipos: entero (integer), real, cadena de caracteres (string), boolean (verdadero o falso), y handle. Detalles de los números enteros (deberían saberlo no?) como: 1, 145, -37. Un numero real tiene decimales como: 3.14, -15.78, 11.1134. Un string, como deberían saber es un mensaje o texto: "Hola", "Esto es un string". Una variable booleana tiene dos valores: true o false. Una variable handle, es una referencia a un objeto como una unidad. No directamente se usa el tipo handle, pero se usa la extensión el tipo handle. Handles incluye: units, special effects, timers, groups, players, y algunos mas.


TRABAJO:
Pon las variables correctamente (no hace falta arrays)
Completa en las lineas.

function desafio_leccion2 takes nothing returns nothing
local ____ _ = GetTriggerunit()
call Killunit(_)
set _ = ____
endfunction


------------------------------------------------------------------------------------------------------------------------------------------------








            Lección nº 3: Funciones










              Descripción General





En esta lección, se vera los siguientes contenidos:
    • Crear funciones
    • Llamar funciones
    • Ejemplos conceptuales



    1º Parte: Creando una función



Probablemente querrá saber cómo crear funciones.
Para crear funciones, primero necesitas tienes que decirle al programa que estas creando una función, entonces ahí que declarar una función. Hay que decirle al programa el nombre de la función, que valor necesita cuando será llamada, y que devolverá. Tomaremos la siguiente función:



function MostrarUnMensaje takes string mensaje returns nothing
    call BJDebugMsg(mensaje)
endfunction

La palabra 'function' dice al programa que vas a empezar a declarar una funcion. Lo que sigue es el nombre de la funcion. Necesitas estar seguro que la funcion tiene un unico nombre entre las otras, o causara un error cuando quieras guardar tu mapa. No puede tener palabras reservadas como unit o tipos de variables.
Luego deber decirle a la funcion del programa en 'takes' lo que necesita. En este caso 'takes' lleva un string, que es básicamente un mensaje de algun tipo. Despues pones el tipo de funcion que necesitas, tienes que poner un nombre para esto (para que puedas referenciarla dentro de la funcion en este caso se llama mensaje, no necesariamente se tiene que llamar asi). Por ultimo, deves poner el valor a devolver en return. Podrias hacer esto en string, integer, real, y demas. Sin embargo, si no devuelve un valor deberas poner 'nothing '.
Despues de declarar una funcion, dentro de la funcion tendras que poner que es lo que hara, de otra manera sería bastante inútil. Esta función simplemente llama a otra función utilizando el string que se necesita para llamarlo. Al final, para cerrar o finalizar la funcion debes poner 'endfunction'.


    2º Parte: Llamando a las funciones

Se puede llamar a una funcion de diferentes formas, pero comensaremos por la mas sencilla, la que utiliza directamente la palabra 'call'.


call MostrarUnMensaje ("hola")

Esta sentencia llama a la función que le he mostrado. Cuando se llama una funcion de esta manera, se coloca la palabra 'call' seguido por el nombre de la funcion el cual esta seguido por parentesis con el valor de la functon que toma ‘takes’ dentro de la misma. Si una funcion tiene mas de un valor, estan tendras que estar separadas por una coma ','.
Importante:
Trabaja de la misma manera cuando se declaran también funciones. (No se habia dicho antes)

Veremos mas acerca de el return (retorno o lo q devuelve) en la funcion. Es algo sencillo, aunque no quiero que nadie se confunda acerca de alguna cosa.
Cuando una funcion tiene un valor return, podras establecer que variables son del mismo tipo que el del valor de retorno paraa esa función.

Ejemplo:
local string nombre_jugador = GetPlayerName(Player(0))


Veremos que no se necesita la palabra “call” para el return. Tambien, si tu quieres pasar
el valor de retorno de una función dentro de otra función de llamada, no es necesario poner la palabra "call", vimos que en la funcion Player hubo que necesitar parametros en la funcion GetPlayerName.
Cabe aclarar que sólo puede tener 1 llamada ‘call’ por sentencia (linea, oracion), y call no puede ser usado si tienes otra palabra antes como: 'set', o que hayas declarado en una variable local.

Tambien, esto es importante, cuando declares una funcion, si la función declarada establece que la función devuelve un valor, en algún lugar de la función debe haber una línea que devuelve el valor ‘return’, de este modo:


function PruebaReturn takes nothing returns integer
    return 5
endfunction

Cuando una función llega a la sentencia del return, devuelve un valor especifico y termina (el ultimo codigo por lo general)

Una ultima cosa para saber, cuando llamas una funcion, puedes llamar solamenta a una funcion que esta encima de otra, osea tienen un orden. No puedes llamar a una funcion que esta depues de la que la llama.

Ejemplo:


function AlgunaFuncion takes nothing returns nothing
endfunction


function AlgunaOtraFuncion takes nothing returns nothing
endfunction

Esto sólo se utiliza como un ejemplo visual que fácil describir lo que esta diciendo.Recuerda “Sólo se puede llamar una función que está antes de la función que se encuentran actualmente “. Tambien, 'AlgunaOtraFuncion' puede llamar a 'AlgunaFuncion'. Sin embargo, 'AlgunaFuncion' no puede llamar a 'AlgunaOtraFuncion'
Tiempo de un Trabajito!
Por ahora los trabajos fueron sencillos (Supongo), lo que pasa que todavia no as aprendido lo suficiente. Espero este desafío le haga pensar más de lo normal. El siguiente codigo tiene unos pocos errores, encuentralos. Hay 5 errores en el siguiente código, ¿Puedes encontrarlos?




function Funcion2 takes nothing returns string
    local string message = AlgunaFuncion("Hola Mundo")
endfunction


function AlgunaFuncion takes string returns nothing
    local string un mensaje
    un mensaje = 'Algo esta mal'
    call DisplayTextToPlayer(Player(0), 0, 0, un mensaje)
endfunction

-----------------------------------------------------------------------------------------------------------------------------------------------





          Lección nº 4: Estructuras de decisión y repetición









            if/then/else Y loop











                By Moyack






Estos tipos de estructuras son importantes dentro de cualquier lenguaje de programación. En JASS, estas estructuras son bastantes versátiles y útiles.
ESTRUCTURA DE DESICION
Veamos la primera estructura: if/then/else

Para trabajar con él, podemos escribir de este modo.

Estructura: if/then/else


if then



elseif then



...

else



endif
Podemos ver que es muy versátil.
Como puedes ver, las condiciones deben ser una funcion al cual tendra que devolver una valor booleano (true/false) o una variable booleana. Otro punto de interes, es que puede ser utilizado como un seleccionador de multi condiciones, algo muy útil en muchos casos.

Con el fin de garantizar la comprensión de esta estructura, este es un pequeño ejemplo que muestra el if/then/else en accion.

Ejemplo:


function Establecer_Danio_de_Unidad takes integer nivel returns real
    // este ejemplo establece la cantidad de daño en un hechizo, dependiendo del nivel// (unidad level, habilidad level, etc)
    local real dam
    if nivel < 2 then
    set dam = 0
    elseif nivel == 1 then // para hacer una igualación se hara con == a diferencia de la asignación con un solo =
    set dam = 50.
    // probablemente notaste el punto después del numero. es usado para indicar que el numero sea real y contenga decimales.
    // Es una buena práctica de programación que se hace con el fin de evitar la molestia de depurar errores

    elseif nivel == 2 then
    set dam = 63.
    elseif nivel == 3 then
    set dam = 125.
    else
    set dam = 125. + 50. * (level - 1)
    return dam
endfunction

Aquí estamos usando una variable local que tendrá un valor de acuerdo con el argumento de entrada a la función y, a continuación, esa variable será devuelta por la función.

Nota importante
Si el IF o ELSEIF son aplicables a la sentencia sin una comparacion, entonces el ELSE podra ser evitado. Este ejemplo anterior tiene un supuesto bug, con el fin de explicar las caracteristicas. si nivel = 1, entonces la primera condicion se ejecutará (set dam = 0). A continuación, la segunda condición se ejecutará y será tambien true (elseif level == 1), entonces se ejecutara la segundo condicion (set dam = 50). Con esto podemos ver que la estructura IFTHENELSE puede ser usada para hacer el filtrado o procesado de datos, por este caso con mayor facilidad.

Otra Nota Importante
El caracter '=' es usado cuando se establece un valor, el operador '==' es usado cuando comparas valores. En otras palabras, no hacer: if x = 5 then... por que Wc3 no puede leer o adivinar lo que pensas o lo que quieras hacer. Esto esta diciendo "if (set x = 5) then..." y no tiene sentido.

ESTRUCTURA DE REPETICION
Ahora veremos la estructura LOOP. (rulo , bucle, for en GUI o.O)


Los Loops en programacion son usados para hacer un conjunto de instrucciones que sera ejecutado varias veces, los loops pueden ser clasificados por finitos y infinitos. El loop finito es el que tiene un número definido de ejecuciones repetitivas, controlados por un control de salida. El loop infinito al contrario del otro, se ejecutara el contenido del codigo script indefinidamente.

El bucle se estructura del siguiente modo:


loop
    //Aca puedes poner tu codigo [Tienes que estar registrado y conectado para ver esa imagen]
    exitwhen funcion o variable>
    //tu proceso iterativo
endloop

Esta estructura es bastante flexible como se puede ver, porque puedes poner la accion “exitwhen” en cualquier lugar dentro del bucle.

Loop Ejemplo:



function CurarGrupo_Unidad_ takes group g returns nothing
    // este ejemplo curara todas las unidades en un grupo.
    local unit u // variable local de una unidad

    loop
    set u = FirstOfGroup(g) //Selecciona la la primer unidad en el grupo.

    exitwhen u == null // el bucle terminara cuando el grupo este vacio.
    // cuando la funcion FirstOfGroup() devuelva null

    call SetunitState(u, UNIT_STATE_LIFE, GetunitState(u, UNIT_STATE_MAX_LIFE))
    //establece la vida de la unidad seleccionada en su maximo.
    call GroupRemoveunit(g, u) // borra la unidad del grupo
    endloop
    call DestroyGroup(g) // para evitar errores en los grupos, debemos eliminar la variable grupo.
endfunction

El uso de FirstOfGroup y grupo de funciones dentro del bucle es muy comunn en hechizos de AOE, con ellos podemos hacer varias cosas a un unit group
.
Algunos consejos con los bucles
A veces, queremos utilizar los bucles como una manera de hacer un efecto de hechizo. Si queres agregar special effects dentro de un bucle, hay una gran posibilidad de que el código produsca lag, con el fin de evitar esto, tu deberas usar la funcion TriggerSleepAction(),que dara al motor del sistema de WC3 una pequeña pausa para procesar otras tareas. Puedes crear una infinito e imparable bucle que utilice sólo las instrucciones loop y endloop sin un comando exitwhen


Ejercicio
Crear una funcion que que muestre todos los numeros por el cual puede ser dividido perfectamente a un numero cualquiera dado. La funcion debera ser de esta forma:


function DividirNumeros takes integer n returns nothing

    // Tu codigo

endfunction

Por ejemplo, si hacemos
DividirNumeros(12)
Deberiamos ver en la pantalla de ejecución del juego algo como esto:

1, 2, 3, 4, 6, 12
-Tambien, sería útil que le informe sobre la funcion ModoloInteger. Esta funcion retorna el resto de una división. ModoloInteger(10, 3) devolvera - return 1.


-----------------------------------------------------------------------------------------------------------------------------------------------







            Lección nº 5: Triggers en JASS











                Descripcion General







GUI es sólo un sistema de triggers, ¿pero que es exactamente un triggers? Esta leccion servira para convertir triggers a JASS y como usarlos.

¿Que es un Trigger (Detonador)?

Estoy seguro que sabras lo que es un trigger si has utilizado anteriormente GUI, pero GUI esconde algunas cosas importantes. Un trigger es en realidad sólo un objeto, como una unidad o un special effect. Hacer triggers tiene de tiene la ventaja de detector eventos. Sin triggers, no podrias hacer demasiado en el editor sin muchos problemas. Un ejemplo de hacer un trigger en JASS:


function InitTrig_JASSTrigger takes nothing returns nothing
    local trigger miTrigger = CreateTrigger()
    call TriggerRegisterPlayerEvent(miTrigger, Player(0), EVENT_PLAYER_END_CINEMATIC)
    call TriggerAddAction(miTrigger, function MiFuncion)
    set miTrigger = null
endfunction

Ahora, esto puede ser un poco abrumador en la primera vez, pero se tratara de explicarlo lo mejor posible. En primer lugar, va a crear una variable local para el trigger. Esto está bien si no necesita de otros triggers para ejecutar, TriggerExecute, en este trigger (TriggerExecute funcion que ejecuta un trigger). Ahora, cuando creas un nuevo trigger, debe utilizar la función CreateTrigger(). Es como usar la funcion Createunit para crear una unidad.
Ahora que ha creado un trigger, tendrás que añadir algunas cosas a lo que serían de útilidad. La siguiente sentencia añade un evento en el trigger.
TriggerRegisterPlayerEvent toma 3 valores, que son el trigger que queres añadir al evento, el jugador aplicado a este evento, y el evento específico.
Hay muchos otros TriggerRegister (detonadores de registro)...funciones que podra experimentar despues, pero por ahora esto estara bien. La siguiente sentencia añade una acción que es básicamente decir el trigger llama a esa función cuando el evento ocurre.
No se muestra la función MiFuncion, pero lo que necesitas saber es que debe tomar nada ('take' nothing ) y regresar nada ('return' nothing ). Ahora, la última línea establece la variable local a null, lo cual es necesario para las variables locales que se manejan de modo que los errores de memoria puedan prevenirse. Si no sabe lo que es una falla de memoria, se va a solucionar en la leccion que viene.

Bien, probablemente todavía sigue usando trigger de GUI para ejecutar sus funciones de prueba en custom script. Este trigger JASS hace casi exactamente la misma cosa que en GUI, por lo que puede ser remplazado. Basta con crear un nuevo trigger, y luego ir a Edicion -> Convertir a texto personalizado.
Lo que veras es algo similar a la función que aparece arriba, sólo se establece una variable global generada por el editor para un detonador y basta con añadir sólo una acción.. Borra todo el código y hace una nueva función que tenga el nombre: InitTrig_[el nombre del triguer aca]. Si el nombre de su detonador fue JASSTrigger, su función tendría que ser: function InitTrig_JASSTrigger takes nothing returns nothing Es importante que lo nombre de esta forma para que sea llamado, mientras el mapa este cargando.

Explicaremos como agregar una condicion. No convertir un trigger de GUI a uno de JASS para ver como se hace la condicion, es ineficiente. Hay más código que realmente necesitas usar. Mostrare un ejemplo:



function Funcion_Condicion takes nothing returns boolean
    return GetTriggerPlayer() == Player(0)
endfunction



function InitTrig_JASSTrigger takes nothing returns nothing
    local trigger miTrigger = CreateTrigger()
    call TriggerRegisterPlayerEvent(miTrigger, Player(0), EVENT_PLAYER_END_CINEMATIC)
    call TriggerAddCondicion(miTrigger, Condition(function Funcion_Condicion))
    call TriggerAddAction(miTrigger, function MiFuncion)
    set myTrigger = null
endfunction

Esto puede tener un aspecto confuso, o no. Se va a revisar su contenido.
Para empezar, Voy a examinar cómo configurar una función para que pueda ser utilizado como una condición en un detonador. Puedes nombrar la función como quieras, pero tiene que tomar nada y devolver boolean. Esta funcion devuelve GetTriggerPlayer() == Player(0). La primera parte se lleva el jugador que provocó el evento (el jugador presiona escape). Y finalmente, el == Player(0) esta parte comprueba si el jugador es Player(0) (Jugador 1 (Rojo)). Dado que este es una declaración booleana, significa que será verdadera o falsa, puede ser utilizado como valor de retorno.

Por ultimo, hemos añadido la sentencia en la función InitTrig_JASSTrigger. La funcion TriggerAddCondition toma un trigger y un boolexpr (expresion booleana). No necesitaras saberpara que sirve boolexpr aun, lo que necesita saber es solo poner Condition(function [inserter el nombre del trigger]) y retornara un boolexpr el cual es usado para la condicions en el triggers.

Desafio

Este desafío requerirá un poco de investigación de funciones de JASS, por lo que recomendamos que consiga una herramienta como JassCraft. Bueno, te doy tres posibles desafíos. El primer desafío es para crear un detonador en JASS que ejecutará una función creada (cualquiera). Después de que lo tenga armado un poco, abrir el JassCraft o un programa similar donde se puede buscar funciones de JASS.
Su próximo reto será crear un detonador que se desactive cuando escribas "-empezar" o cualquier tipo de mensaje de texto en el juego. Te doy un poco de ayuda la función que está buscando para añadir el evento es TriggerRegisterPlayerChatEvent, Sin embargo, depende de vos saber como usarlo. Si has resuelto ese problema, entonces hacer un detonador que se activa cuando el mensaje de un jugador contiene el tipo de caracteres "-" o cualquier letra que quieras. En la acción, mostrará el valor el mensaje el jugador que hizo la accion (escribir). Sugerencias para este desafío, seguir utilizando la misma función para añadir el evento, sólo es necesario cambiar un valor o dos.
Y supongo que también sera útil decirles que GetEventPlayerChatString puede ser usado para obtener la cadena de caracteres que el jugador escribio (utilizado cuando la función llamada del detonador esta apagado).


----------------------------------------------------------------------------------------------------------------------------------------------








            Lección 6: Fallas de Memoria










              By: Darkwulfv






¿Que es una falla de memoria?
-Una falla de memoria es causada por una mala codificación, donde un manejamiento que fue alamacenado en memoria donde se pierde la reference. Básicamente, es algo que se ha colocado en la memoria usada por wc3, que no se borro, y que no está en condiciones de ser eliminado.

¿Como aparece un error de memoria?- Una pérdida de memoria añade una diminuta porcion de memoria usada al Wc3 cuando está andando. Si hay suficiente perdidas de memoria, el mapa va a tener lag.

¿Cuál es la causa de una perdida de memoria?
-Cuando un handle es creado, es almacenado en la memoria. Si no es destruido o removido de una vez cuando termines de usarlo, luego quedara ahi, usando memoria.

¿Cómo se supone que lo arreglaremos?
- Bueno, hay varias formas de hacerlo, depende.



function PerdidadeMemory takes nothing returns nothing
    call AddSpecialEffect(…) //Crea un efecto especial
endfunction

La nativa AddSpecialEffect(…) crea un efecto. Si no destruis este efecto con la funcion correcta, esta quedará almacenado en la memoria, y por lo tanto, utilizando la memoria. Ahora, una perdida es insignificante. Pero si tu mapa tiene hecho muchas perdidas seguidas, notaremos un gran cambio.

Una forma de arreglar una perdida:





function PerdidadeMemory takes nothing returns nothing
    local effect mi_efecto = AddSpecialEffect(...) //Crea un efecto especial
    call DestroyEffect(mi_efecto) //Destruye el efecto, lo remueve de la memoria
    set mi_efecto = null //Tienes que dejarlo el valor local en null para terminar la funcion, o tambien finalizar la perdida
endfunction

//Otra alternativa, de puede ser usado


function PerdidadeMemory takes nothing
    call DestroyEffect(AddSpecialEffect(...))
    //Agrega un efecto especial y lo destruye it de una vez. Esto todavía muestran la animación una vez, para la mayoría (no necesariamente todos) los efectos, y no requiere el uso de una variable
    //Sin embargo, si quieres ver la animación entera, debes esperar a que la duración del efecto de la animacion'stand'

endfunction

Este metodo servira para cualquier momento que estes usando un handle (cualquier variable que no sea real, integer, boolean, code, o string).
Sin embargo, la destrucción/eliminación de cambian de función segun cada tipo de handle. Una lista de tipos variables y la forma de eliminarlos se dará más adelante para que tengas referencia.

NOTA:
Cuando destroy/remove un objecto, estaras removiendo/destroyendo un objeto especifico y no la variable misma. La variable sólo apunta a la ubicación en la memoria cuando el objeto se almacena.
Una perdida puede definirse como un objeto que se crea, no se elimina, no puede ser removido durante el juego (suponiendo que la eliminación es inevitable). Si se utiliza sólomente una vez como unidades dummy (titere), regiones, grupos, etc) y luego removerlas. Si no es así, deberian despedirse de él. (Al igual que para los hechizos, no quiten el caster!)
Todas las no variables handle, excepto los strings, no tendras fallas. Las perdidas en String no puede ser arreglada, pero por lo general, no es necesario preocuparse por eso.
So memory leaks only apply when you create things?

Una pérdida de memoria no sólo sucede cuando se crean las cosas. También ocurre cuando haces una variable handle, se debe poner en un valor, y no es nulo.

Ejemplo:



function PerdidadeMemoria takes nothing returns nothing
    local unit u
    //acciones
endfunction
Este ejemplo no tiene perdidas, como el handle no se definió la variable a un valor. Sin embargo, si se hubiera fijado a un valor, como:



local unit u = GetTriggerunit()

Tendra fallas. Para solucionar este problema, configure su variable a null. (Reales, enteros, booleans y no se puede ser nulo, y no necesita ser como la memoria estas son elimandas automáticamente)
Para una variable nula, simplemente pon



set tuvariable = null

No es necesario para establecer una variable nula después de eliminar cada objeto. Tan sólo es necesario anularla una vez, esto es lo que se suele hacer al final de una función.



function PerdidadeMemoria takes nothing returns nothing
    local group g = CreateGroup()

    //Algun codigo

    set g = null
endfunction

NOTA: Para satisfacer a aquellos que quieran saber por qué las variables handle dan perdidas (no se refiere al objeto, me estoy refiriendo a la variable). Cuando estableces una igualdad de handle a un valor, los puntos handle tendran un lugar para el valor que se almacenó en memoriaSe siguen apuntando a que ese valor se almacenara a menos que se ponga un null (es decir 0, no apuntando a un lugar específico en la memoria.)

¿Y con respecto a los Globales?
- Puesto que se hace siempre en la memoria al principio, y siempre están disponibles, no cuentan como perdidas (y no necesitan ser anuladas).

¿Qué debo hacer acerca de las variables no handles?
-No tiene problemas algunos.

Conclusion:
-Siempre limpia los fallos. Si no lo haces, y hay suficiente perdidas, te darás cuenta de los efectos.

Desafio!
-Limpia la funcion de todos las perdidas:



function DesafioPerdMem takes nothing returns nothing
    local unit u = GetTriggerunit()
    //Esta unidad esta en el juego, que necesita para mantenerse (pista)

    local effect SFX = AddSpecialEffect(…)

    local group g = CreateGroup()

    local unit u2
    // este va a ser una unidad dummy y debe eliminarse (pista)

    local real r = 4
    //acciones
    //(pista) sólo una de estas variables no sera anulada

endfunction


----------------------------------------------------------------------------------------------------------------------------------------------







            Leccion 7: Comenzando un Spell en JASS









            Descripción General





Las bases han sido prácticamente cubiertas, y ahora probablemente querrás utilizar JASS para crear hechizos o algo. En esta lección, vamos a hacer el proceso de hacer un hechizo similar a la habilidad Omnislash, que se encuentra en el DotA. (No he visto la habilidad, pero sé algo cómo funciona) Esto le mostrará algunas cosas básicas utilizadas en JASS y lugares que se dejará para ser capaz de modificar el hechizo más adelante.

Empezando
Antes de realizar un hechizo, tendrá que saber como funcionará, lo que está sucediendo paso a paso. En primer lugar, necesitamos el trigger para detonar cuando una unidad arroja un cierto hechizo. Y entonces podamos empezar a pensar en las acciones. En el hechizo, pensaremos que el héroe se mueve en torno a un área y este golpeando una cantidad de unidades, pero nunca la misma unidad dos veces (si hay más de una). Si estas buscando el hechizo que se hizo en el juego, podría parecer confuso, o tal vez no. Tienes que descubrir las cosas poco a poco.
Aquí hay un código para que ahora empecemos y voy a añadirle mas cosas a medida que progrese la lección:



function Slash_Condicion takes nothing returns boolean

    return GetSpellAbilityId() == 'A000'
    //Compara la habilidad Id de la habilidad lanzada a la Id de nuestro spell Slash.

endfunction


function Slash_Acciones takes nothing returns nothing
endfunction


function InitTrig_Slash takes nothing returns nothing
    set gg_trg_Slash = CreateTrigger()
    //Configura la var global que esta creara para nuestro call TriggerRegisterAnyunitEventBJ(gg_trg_Slash, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    //Esta funcion BJ registra un evento para cuando una unidad inicia el efecto
    //de una habilidad para nuestro trigger

    call TriggerAddCondition(gg_trg_Slash, Condition(function Slash_Condicion))
    call TriggerAddAction(gg_trg_Slash, function Slash_Acciones)
endfunction

Hasta el momento todo lo que tenemos es la base de activación establecida que se apagará cuando la habilidad se este lanzando. Debe asegurarse de que haya creado una habilidad (preferiblemente basado con "canal"(habilidad canalizar) con los valores establecidos correctamente, si necesita saber más acerca de channel, por favor preguntar). Ahora vamos a crear los efectos reales del hechizo, tendrás que pensar "lo que ocurre en el hechizo". Esto es lo que sucede: el héroe se mueve en torno y dentro de un área determinada, sólo se movería a los enemigos, se movera para cada unidad, causara daño, y al final volvera a la posición con la que comenzó. Lo primero que hay que hacer es crear una variable local para los que se necesita hacer un seguimiento. Esto a mi criterio: una variable unit (unidad), para el héroe, un location (ubicación) para donde comience el héroe, un group (grupo) para mantener a todos los enemigos del héroe que golpeara, y otra variable unit (unidad) para tener temporalmente las unidades que se encontraron. Es posible que no alcanzara el punto de la última variable, pero pronto te mostraré cómo se usa.
Esto es lo que deberíamos tener ahora:




function Slash_Acciones takes nothing returns nothing

    local unit lanzar //mantendra nuestro lanzador de hechizos
    local location posicion_inicial //Contendra la posición con que comienza el heroe
    local group enemigos //tendra el grupo de unidades de los enemigos de nuestro heroe a las que golpeara
    local unit temp //Usado para cuando se hayan pasado al grupo (se explica mas adelante)
endfunction

Probablemente quierras hacer algo como "Pick Every unit in (grupo) y hacer acciones", pero hay un problema con eso. Para poder utilizar esta función (tienes que saber como es el ForGroup en JASS), necesitaras una función separada que sea incapaz de pasar algun de los valoresAhora puedes utilizar variables globales para la transferencia de información, pero entonces el hechizo no podría ser utilizada por más de 1 unidad a la vez. Podría pensar en otras maneras en torno a esta, pero podría tomar más tiempo de lo que valdría la pena. Te daré una pista sobre cómo lo hago, yo uso un bucle. "Loop?" podría estar pensando, "¿cómo puedo usar un bucle?" porque si ha utilizado antes de GUI, los bucles iría para una longitud fija (For integer de # through #, hacer acciones), a diferencia de JASS donde un bucle sólo terminará cuando una determinada condición se cumpla. Y esa condición será que todos los enemigos en el grupo enemigo que se ataca.
Aquí hay más código para explicar un poco más de lo que quiero decir:



function Slash_Actions takes nothing returns nothing
    local unit lanzar = GetSpellAbilityunit()
    //Crea una var local y la establece en la unidad que este casteando el spell

    local location posicion_inicial = GetunitLoc(lanzar)
    //Crea la local y la asigna para la position de lanzar

    local group enemigos = CreateGroup()
    //cuando creas un grupo en JASS, es como un trigger. Primero necesitas vaciarlo, y luego añadirle cosas.

    local unit temp
    //Usado cuando da vueltas a travez del grupo

    local integer contar = 5
    //Este sera el maximo cantidad de enemigos que seran golpeados

    call GroupEnumunit[/color]sInRangeOfLoc(enemigos, position_inicial, 500.0, null)

    // GroupEnumunitsInRangeOfLoc toma un grupo, una location, un radio, y un boolexpr (una condicion, de tipo) y luego recibe las unidades dentro de dicho radio y los añade a nuestro grupo
    loop
    set temp = FirstOfGroup(enemigos)
    //FirstOfGroup devuelve una unidad de un grupo sin un orden particular

    exitwhen temp == null or contador == 0

    //Este loop se detendra cuando temp sea null (lo que significa que no hay más unidades que quedan en el grupo) o cuando golpees 5 enemigos
    call GroupRemoveunit(enemigos, temp)
    //Remueve la unidad de el grupo entonces no puede ser alcanzado en la siguiente
    endloop

    // La limpieza de fallas de memoria se pondrá aca
endfunction

En esta parte del código, hemos creado algunos más cosas básicas. Iniciamos las variables y, a continuación, llena el grupo con unidades dentro del rango de 500 de el lanzador. Siguiendo, iniciaremos un bucle y en cada ciclo en el bucle, la variable temporal unidad se va a establecer para una unidad del grupo. Entonces, vamos a decirle al bucle que saldra cuando el grupo no tinga unidades, o el lanzador haya golpeado 5 enemigos (el contador se reduciría para cada enemigo golpeado). Al final de cada bucle, la unidad utilizada se eliminará del grupo de forma que no pueda ser recogido de nuevo (y por lo tanto evitara un bucle infinito). Finalisaremos el código que se ejecuto por el bucle al final la función.

El próximo paso será agregar la función que va a agarrar cada una de las unidades. La primera cosa que tendrás que tener en cuenta es que GroupEnumunitsInRangeOfLoc agrupa todas las unidades en 500 de rango de la ubicación del héroe, incluyendo aliados y el héroe. Esto significa que tendrá que añadir una simple condición para comprobar si la unidad es un aliado antes de llevar a cabo acciones adicionales. Después de que se ha hecho, La unidad tendrá que desplazarse a cada enemigo afectado y dañarlas,
No se olvide de establecer la variable contar para contar - 1 así como, más enemigos podrían ser afectados que desearas. Antes de pasar a la siguiente trozo de código, declararemos otra variable location para mantener la posición del enemigo, voy a ponerle el nombre de temp_loc. Esto es lo que tendremos para el siguiente bucle



loop
    set temp = FirstOfGroup(enemigos)
    exitwhen temp == null or contador == 0

    if IsunitEnemy(temp, GetOwningPlayer(lanzar)) then
    // Si la unidad enemiga es un enemigo del dueño del lanzador

    set temp_loc = GetunitLoc(temp)
    // Establezca una variable de ubicación temporal para la posición del enemigo
    call SetunitPositionLoc(lanzar, temp_loc)
    // Mueve nuestra unidad instantaniamente a la ubicación del enemigo
    call unitDamageTarget(lanzar, temp, 50, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)

    //El lanzara instantaniamente daño al enemigo por 50 de daño con un ataque tipo caos
    //Puedes ignorar el tipo de daño, y el último parámetro (weapontype) es sólo para el sonido, pero sera lo correcto

    set contador = contador - 1 // Una unidad sera afectada, por lo que ahora las unidades afectadas se reducirán en 1
    endif

    call GroupRemoveunit(enemigos, temp)

endloop


Bueno, este bucle permitirá que nuestra unidad se mueva para cada unidad dentro de el tango y dañarlas. Nuestro héroe se moverá a cada una de las unidades en serie y las dañara.

Ver perfil de usuario

TerraNet  

CEO TN!
avatar

2default el Lun Nov 29, 2010 3:33 am - [GUIA] Jass

exelente guia man


- - - - - - - - - - - - - - - - - - - - - - - -

Feel Your Imagination
Ver perfil de usuario

Ver el tema anterior Ver el tema siguiente Volver arriba  Mensaje [Página 1 de 1.]

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