LUA Basico para Blitzkrieg 1 -...

27
LUA Basico para Blitzkrieg 1 por ElGotele, mayo 2007 traducción del documento Basic Lessons in Writing Scripts for Blitzkrieg 1 by hitandrun, June 2006

Transcript of LUA Basico para Blitzkrieg 1 -...

Page 1: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

LUA Basico para Blitzkrieg 1por ElGotele, mayo 2007

traducción del documento

Basic Lessons in Writing Scripts for Blitzkrieg 1 by hitandrun, June 2006

Page 2: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

IntroducciónCuando el juego Blitzkrieg se lanzó al mercado, el Editor de Mapas y Recursos fueron incluidos como características extras en el juego.

La Ayuda del Editor era limitada y no había ninguna instrucción para escribir el código que controla las acciones en las misiones personalizadas.

Por tanto sacar provecho, del Editor, solo fue posible a traves de los conocimientos compartidos por los jugadores en los diversos foros.

Igualmente desentrañar el leguaje de programación, LUA, se consiguio a base de analizar el codigo, prueba y error, y compartir los descubrimientos.

Muchas de las personas que han desarrollado la tarea de desentrañar LUA, han tenido la costumbre de crear un manual detallado, haciendo mucho más facil para todos su aprendizaje. Aunque muchos de estos pioneros ya no están activos en BK1, todo aquel que juega un mapa personalizado o intenta crearlo, deben la posibilidad de hacerlo, al trabajo duro de unos cuantos aficionados que fueron lo suficientemente generosos para compartir sus conocimientos con el resto de la comunidad.

Uno de los acontecimientos más importantes para poner en claro el código de LUA fue la publicación de Calvin's Blitzkrieg Guide to Programming Lua Function. Esto hizo posible que todo el mundo dispusiera de una lista de los comandos de BK1 y una guía de como usarlos.

Como esta guia es necesaria para cualquiera que escriba programas de BK1, DEBE descargarse.

La Guia es como un diccionario de LUA, pero eso no proporciona instrucciones precisas de como los comandos se combinan en un programa (Calvin incluye un ejemplo que apenas puede ser definido como “introductorio” y es mejor no tenerlo en cuenta para cualquier nuevo programador.Calvin's Blitzkrieg Guide to Programming Lua Function puede descargarse desde el portal de Blitzkrieg.

Wespex fué el primero en escribir un manual de instrucciones integrado para hacer un mapa, escribir el programa y crear un juego que podría ser compartido con otros jugadores.

Este tutorial (reeditado varias veces y en combinación con la Guia de Calvin) es una buena primera introducción para cualquiera que quiera hacer mapas personalizados.

Despues de la publicación del tutorial, Wespex editó una serie muy completa de respuestas razonadas paras las preguntas que hacen, quienes escriben programas, en el foro de BK1.

La característica más valiosa, del Tutorial y Repuestas, son las notas explicativas, acompañadas de ejemplos de codigo que no solo proporcionan una plantilla del codigo sino que clarifican como opera el programa.

Probablemente es acertado decir que para la inmensa mayoria de las personas que escriben programas, de BK1, han aprendido siguiendo el Tutorial.

Estas Lecciones Basicas han sido escritas en respuesta a numeroso comentarios en los foros del portal de Blitzkrieg y a las dificultades, que aparentemente, experimetan muchos creadores de mapas cuando empiezan a escribir sus programas.

Las Lecciones Basicas intentan demostrar los principios más simples de LUA y mostrar como construir un programa dando las bases para construir un mapa personalizado.Intentan hacer esto, al tiempo que desmitifican algunos terminos tecnicos.

Page 3: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Puntos a considerarComo alguien que lleva poco tiempo escribiendo en LUA, estoy familiarizado con el obstaculo que supone empezar y la frustación que se siente cuando el codigo no funciona correctamente. Sin embargo hay que tener en cuenta algunos puntos:

● LUA es un lenguaje y es necesario conocer el significado de las palabras y como utilizarlas. Esto no quiere decir que haga falta un trabajo arduo para aprender el vocabulario y la gramatica.

● Al contrario que en los lenguajes humanos, un pequeño error puede hace que el programa sea completamente inentiligible para el ordenador. La mayor frustación, cuando se empieza a programar, es cuando despues de escribir un programa, este no funcione. La reacción más normal es pensar que el programa no es correcto o que el ordenador no funcionas. En el 99% o 100% de los casos el problema es que hay un error mecanografico o gramatical.

● Crear un mapa y ver como el programa lo hace empezar a funcionar es muy divertido. Hacer operativo un programa no siempre es divertido. Los mejores programadores de la comunidad BK1 admiten que gastan mucho tiempo poniendo a punto sus creaciones. No todo el mundo tiene la paciencia para escribir un programa, linea a linea, buscar un letra fuera de su sitio, un corchete que falta o un punto y coma de más. Quien quiera programa tiene que aceptar esto como algo necesario y nadie puede hacer que sea más facil.

● Una vez que se ha asimilado lo basico de LUA, la mejor forma de aprender es acceder a una misión con el Editor e ir linea por linea (con una copia de la Guia de Calvin al lado) working out what is going on

● Cuando se quiera probar alguna función nueva “prestada” de otro progamador, no hay que probarlo en la mitad del gran mapa de 26x 26. Es mejor hacer una prueba creando un mapa de 4x4, con un número minimo de unidades y escribiendo un único bloque de programa con el nuevo codigo. De esta forma si no surte el efecto deseado se puede revisar rápidamente sin tener que comprobar otro codigo, ni creando interferencias con el resto del programa. Este es el metodo que se sigue en las lecciones que siguen.

● En las ocasiones en que realmente se esté en un “atasco” (despues de utlizar el BKP's Debugging Notes, que acompaña a ests lecciones) se puede buscar en el Foro, muchos de los problemas que se presenten habrán sido reportados anterioremente. Si no se encuentra lo que se busca, se puede realizar una pregunta en Map Making Questions and Answers. Si la pregunta es concreta (acompañada de una copia del codigo afectado) es probable que se obtenga una rapida respuesta de uno de los dioses de las programación que ayudará, generosamente, a los meros mortales.

Page 4: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Como se trabaja con las Lecciones BasicasCada una de las lecciones tiene un fichero .bzm con el mapa y un fichero .lua con el codigo del programa, ambos con el mismo nombre. Todos ellos se incluyen con este documento.

Tanto los fichros .bzm como los ficheros .lua debe copiarse en la carpeta Blitzkrieg \ Run \ Data \ Maps del ordenador. Es la misma carpeta donde se salvan los mapas y programas personalizados.

Para seguir las lecciones es necesario abrir los ficheros .bzm con el Editor y los .lua con el programa SciTe.

Una vez que se han repasado las lecciones y revisado el codigo y el mapa, se debe pulsar el botón Run Blitzkrieg en la barra de herramientas del Editor para ver como se ejecuta el programa.

Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente con el fin de mostrar el desarrollo del mapa y el programa. Las últimas dos lecciones están separadas y cubren los temas que a menudo surgen en el Foro de BKP.

Estas lecciones se presentan asumiendo que se trabaja con el editor de Blitzkrieg SciTe. La versión actual de este editor es gratuita y su tamaño permite descargarlo facilmente desde las paginas de BKP, por lo que no hay ninguna razon para no usarlo. No escribira el programa solo, no encontrará errores en el codigo y no descubrirá cuando un programa no va a funcionar correctamente, pero es muy util para escribir y verificar el codigo. Puede descargarse ahora desde este enlace. Blitzkrieg SciTE Editor

Nota.- al trabajar con el editor SciTE hay que añadir el sufijo .lua al nombre del fichero, de lo contrario se guardará como .xml.

Page 5: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Principios Basicos El programa se escribe en un fichero .lua. Este fichero se enlaza con el mapa utilizando el botón con una llave inglesa y una letra A en el menú general del editor.

Un programa contiene una serie de instrucciones, llamadas funciones, las cuales hacen que ocurran cosas cuando se está ejecutando el mapa. Las funciones pueden ser muy simple, haciendo que pase algo concreto en un momento determinado, o mas complejas, probando que se den ciertas condiciones y luego haciendo cosas distintas de acuerdo con el resultado de la prueba.

Nota.- Una lista de las funciones especificas de Blitzkrieg se encuentra en el Apendice A

Para que las funciones interactúen con las unidades del mapa, soldados, vehiculos, edificios.., hay que asignarles un ScriptID en el editor del mapa.

Con la pestaña de Objetos seleccionada, se hace doble click en una unidad y aparece la ventana de propiedades (Property), se vuelve a hacer doble click sobre la etiqueta ScriptID y se edita el valor actual (Value) para la unidad. Se escribe directamente el codigo que se quiere asignar a la unidad, cerrando a continuación la ventana de propiedades.

Recomendación.- Hacer listas de las unidades con sus ScriptID. Algunos creadores de mapas incluyen estas listas como comentarios al principio del programa.

Recomendación.- Es de gran ayuda diferenciar claramente con series distitnas (p.e 1nn jugador y 2nn IA) los números asignados a las unidades del jugador humano de las unidades controladas por la IA.

Muchas funciones utilizan ScriptAreas. Estos elementos se definen en el Editor de Mapas utlizando la pestaña Map Tools.

Activar el control Script Area Tool y a continuacion arrastrar el cursor sobre el mapa marcando la zona deseada, a continuación introducir el nombre del area. Al escribir el programa se ha de utilizar el nombre del mapa tal y como se ha escrito en el Editor, respetando mayusculas y espacios.

Recomendación.- Dar a las ScriptAreas nombres significativos a fin de que no se confundan con el texto del programa (p.e Granja y Ciudad no Area1 y Area2).

Lenguaje LUALa sintaxis para LUA es simple y consistente. Debe ser respetada exactamente. Cualquier error de ortografia, espaciado o acentuación tendrá como resultado que el programa no funcione correctamente. La mayor parte de los problemas en los programas responden a errores de tecleo o sintaxis.

Las palabras siguientes tienen un significado especial en LUA, son conocidas como palabras clave:

and break do else elseif if end false for function in local nil not or repeat return then true until while

No tiene relevancia lo que significan estas palabras en el mundo real, en LUA tienen un uso determinado, enlazando las funciones del lenguaje y solo pueden ser utilizadas de esta forma. El uso de algunas de estas palabras se clarifica en estas Lecciones Basicas. Por convención las palabras clave se escriben siempre en minuscula.

Hay tambien algunas palabras clave como “RunScript”, “LandReinforcement”, “Win” y “Loose”. Estas hay que escribirlas con la inicial en mayusculas y el resto de la palabra en minusculas, sin separación entre las palabras cuando van más de dos juntas. La Guia de Calvin es el diccionario para aprender la forma correcta de escribirlas.

Recomendación.- Si se utiliza el editor SciTE todas las palabras clave aparecerán en azul sobre un fondo azul claro cuando hayan sido escritas correctamente.

Page 6: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Los nombre de las cosas (funciones) que define el programador son denominados nombres (names). Pueden componerse con números y letras, aunque no pueden empezar con un número. Por convección la primera letra debe ir en mayuscula. Por ejemplo en la lección 1 se escribe la function MoveCar(). Donde “function” es la palabra clave y MoveCar es el nombre.

Recomendación.- Si se utliza el editor SciTE los nombres (names) aparecerán en negrita.

Una vez que un nombre (name) ha sido definido como función, puede ser llamado a lo largo del programa, pero cuando se escriba esa llamada el nombre (name) debe ir entre comillas.

Por ejemplo en la lección 1 cuando se hace la llamada a la función MoveCar se escribe RunScript(“MoveCar”, 3000), donde “RunScript” es una palabra clave de BK1 y “MoveCar” es una cadena de caracteres (string) que se aplica a una función que ha sido definida en otra parte del programa.

Es esencial que las cadenas de caracteres (string) sean escrito tal y como se escribieron al definir la función, en caso contrario el programa no los reconocerá. Por eso puede ser conveniente utilizar las funciones de copia y pegar, evitando asi los errores mecanograficos. No puede haber espacios entre las comillas y el nombre (name).

Recomendación.- Si se utliza el editor SciTE las cadenas de caracteres (string) aparecerán en color purpura cuando las comillas están correctamente situadas. Si el color purpura se extiende mas alla de la cadena de caracteres indica que falta una de las comillas. SciTE no controla si la cadena de caracteres se ha escrito correctamente.

Las funciones y palabras claves están calificadas por parámetros. Para entender la idea de parametro de la función o palabra clave hay que pensar en alguien diciendo a otro “Haz”. Pero ¿hacer que?, por si sola la expresión “Haz” no tiene sentido si no se acompaña de otra condición que determine que es lo que hay que hacer. Estas condiciones calificativas son los parámetros.

En LUA los parámetros se especifican siempre entre parentesis y separados por comas, marcar esta separación es muy importantes y el programa no funcionará si esta no se escribe. En el ejemplo RunScript(“MoveCar”, 3000), la palabra clave “RunScript” necesita saber cual es la función a ejecutar y cuando debe hacerlo. Por tanto los parámetros son la cadena de caracteres “MoveCar” y el valor 3000, el significado de este último se explica más adelante.

Recomendación.- Si se utliza el editor SciTE los parámetros que corresponden a valores se visualizan en color azul.

Algunas palabras clave y funciones no necesitan de parámetros, son autoexplicativa para el programa y no han de calificarse. En este caso sigue siendo necesario escribir los parentesis, aunque sin nada entre ellos. p.e., suicide(). La falta de uno o de los dos parentesis hará que el programa no funcione correctamente.

Las sangrias son muy utilizadas por los programadores pero no son necesarias y no tienen ningún efecto sobre el programa. Es una forma muy util de organizar el codigo y hacer más clara su lectura. Cada programador tiene, o puede tener su propio estilo de identar (sangrar) el texto.

Por convención cada linea de texto finaliza con un punto y coma, excepto cuando una palabra clave opera en la/s linea/s siguientes a la que está escrita como en “well – covered” en la lección 3.

Los comentarios son incluidos en el texto del programa para anotar aclaraciones y documentar el codigo. Un comentario comienza y finaliza con dos guiones seguidos (--comentario--). Los comentarios no son leidos por el programa. Por consiguiente anotando dos guiones al principio y final de una linea de programa hace que esta sea desactivada lo que puede ser muy util para hacer pruebas.

Recomendación.- Si se utliza el editor SciTE los comentarios se visualizan en color verde.

Page 7: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Lección 1.- Escribiendo una función y ejecutandolaEsta lección hara que una unidad se mueva desde el punto donde se encuentra a otro determinado.

Lección 1 .- Mapa (.bzm)Hay un coche con el ScriptID=100 (doble click sobre la unidad para ver el valor del ScriptID) y un edificio hacia el cual se moverá el coche.

Lección 1 .- Programa (.lua)function MoveCar()

Cmd(0, 100, 916, 1516); Suicide();

end;

function Init() RunScript("MoveCar", 3000);

end;

Nota.- El codigo ejecutable está empaquetado en los archivos .lua y se puede copiar y pegar en los programas que se estén realizando. Nunca deben escribirse programas en Word ya que llevan codigos embebidos que pueden hacer inoperativo el codigo a la hora de ejecutarlo.

Explicaciónfunction MoveCar() Establece el nombre de la función “MoveCar”, que posteriormente será llamada por el programa.

Cmd(0, 100, 916, 1516); Da la orden de movimiento (0) a la unidad (ID 100), hasta la posición x, y (916 este, 1516 norte).

Suicide(); Dice al programa que la función debe interrumpirse y no continuar ejecutandose.

end; Finaliza una parte del programa, en este caso la función “MoveCar”.

function Init()Esta el la función INICIAL del programa, todos deben tener una función Init o el programa no arrancará.

RunScript("MoveCar", 3000);Hace que se ejecute una parte del programa, en este caso la función “MoveCar” y además dice cuando debe ejecutarse (3000 milisegundos, 3 segundos, despues de arrancar el programa.

end; Finaliza una parte del programa, en este caso la función “Init”.

Nota.- Una lista de los comandos que pueden utilizarse y la forma de usarlos está descrita en la Guia Calvin.

Page 8: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Lección 2.- Adicionando una segunda función con multiples comandosEsta lección hará que una segunda unidad realize una serie de movimientos en momentos distintos a los de la primera unidad.

Lección 2 .- Mapa (.bzm)Hay un coche con ScriptID=100, el de la lección anterior, un camión con ScriptID=101, y un arbol y un monumento hacia el que el camión se dirigirá pasando alrededor del edificio.

Lección 2 .- Programa (.lua)function MoveCar()

Cmd(0, 100, 916, 1516); Suicide();

end;

function MoveTruck() Cmd(0, 101, 1583, 223); QCmd(0, 101, 1890, 1570); QCmd(0, 101, 1100, 1890); Suicide();

end;

function Init() RunScript("MoveCar", 3000); RunScript("MoveTruck", 7000);

end;

Explicaciónfunction MoveCar()

Cmd(0, 100, 916, 1516); Suicide();

end;

function MoveTruck()Una nueva función definida de la misma forma que la anterior pero con un nuevo nombre.

Cmd(0, 101, 1583, 223); La orden de movimiento (0) es la misma que para el coche pero con el ScriptID de el camión (101), tambien son diferentes las coordenadas que indican el destino.

QCmd(0, 101, 1890, 1570);QCmd es un comando similar a Cmd pero con la particularidad de que solo se ejecuta una vez finalice el comando previo. Esta orden tambien se dirige al camión (101) y lo envia al nuevo destino que marcan coordenadas.

QCmd(0, 101, 1100, 1890); Suicide(); end;

function Init() RunScript("MoveCar", 3000); RunScript("MoveTruck", 7000);

La instrucción para ejecutar la nueva función se añade a la función de inicio (Init), pero esta vez se ejecutará 7 segundos despues de que arranque el programa.

end;

Nota.- La segunda función tambien podría comenzar en la primera como se muestra a continuación. Esta tecnica se usa a menudo cuando se quiere que la segunda función no comience antes de que llame desde la primera. Es mejor no tener multiples funciones ejecutandose (utilizando potencia del procesador) y solo se arrancan cuando sean necesarias.

Page 9: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

.lua Script function MoveCar()

Cmd(0, 100, 916, 1516); RunScript("MoveTruck", 4000); Suicide();

end;

function MoveTruck() Cmd(0, 101, 1583, 223); QCmd(0, 101, 1890, 1570); QCmd(0, 101, 1100, 1890); Suicide();

end;

function Init() RunScript("MoveCar", 3000);

end;

Explicaciónfunction MoveCar()

Cmd(0, 100, 916, 1516); RunScript("MoveTruck", 4000);

La segunda función se llama ahora desde aquí. Para hacer que el movimiento del camión se produzca 7 segundos despues de que el juego arranque es necesario cambiar el parametro de tiempo a 4000 porque la función “MoveCar” ya arranca 3 segundos depues del inicio del juego.

Suicide(); end;

function MoveTruck() Cmd(0, 101, 1583, 223);QCmd(0, 101, 1890, 1570); QCmd(0, 101, 1100, 1890); Suicide(); end;

function Init() RunScript("MoveCar", 3000);

El comando para arrancar la función “MoveTruck” no debe figurar ahora en la función “Init”.

end;

Page 10: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Lección 3.- Comprobando una condiciónEn esta lección se comprueba si una condición se ha cumplido y se arranca una acción nueva dependiendo de la respuesta. Este es un proceso muy útil y muy utilizado en los mapas de Blitzkrieg.

Lección 3 .- Mapa (.bzm)Este es el mismo mapa de la lección 2 con un ScriptArea llamado “Farm”, marcado alrededor del edificio y dos pelotones de refuerzos con los ScriptID “103 “ y “104”. Ambos forman parte del grupo de refuerzo (reinforcement group) “103”. Pulsando en el Editor en la pestaña Reinforcement Groups y seleccionado la etiqueta GroupN103, se visualiza en la ventana Group Property los ScriptID de las dos unidades.Esta disposición permite dar ordenes diferentes a cada una de las unidades o bien al grupo completo.El edificio ahora tiene el ScriptID “10”.

Lección 3 .- Programa (.lua)function MoveCar()

Cmd(0, 100, 916, 1516); RunScript("MoveTruck", 4000); Suicide();

end;

function MoveTruck() Cmd(0, 101, 1583, 223); QCmd(0, 101, 1890, 1570); QCmd(0, 101, 1100, 1890); Suicide();

end;

function FarmCheck() if GetNUnitsInArea(0, "Farm") == 2 then

RunScript("SquadArrive", 1000); Suicide();

end; end;

function SquadArrive() LandReinforcement(103); RunScript("SquadMove", 2000); Suicide();

end;

function SquadMove() Cmd(0, 103, 1530, 1320); Cmd(6, 104, 10); Suicide(); end;

function Init() RunScript("MoveCar", 3000); RunScript("FarmCheck", 2000);

end;

ExplicaciónUnicamente los nuevos elementos del programa serán presentados y explicado a partir de ahora.

function FarmCheck() if GetNUnitsInArea(0, "Farm") == 2 then

“if” es una palabra clave que se utiliza para comprobar una condición y devuelve uno de las dos posibles respuestas: Verdadero (True) o Falso (False).En este caso la condición comprobada es el número de unidades en el area. “GetNUnitInArea” es el parámetro para saber cuantas unidades (“0” es el codigo del jugador al que pertenecen las unidades) y el segundo parámetro especifica cual es el area a comprobar (“Farm”, no deben olvidarse las comillas).La condición es “==2”, es decir que se pregunta si el número de unidades en el area es igual a 2 (ver la Nota al final de

Page 11: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

esta lección para conocer los simbolos que pueden utilizarse).“then” es una palabra clave que indica que la respuesta obtenida es verdadera (true), es decir la condición se cumple. Como “then” opera en la/s proxima/s linea/s del codigo no es necesario finalizarla con punto y coma (;).

RunScript("SquadArrive", 1000); La consecuencia de que se cumpla la condición es el arranque de otra función (“ScuadArrive”). Si la respuesa no fuese verdadera (False) esta función no arrancaría ni tampoco se ejecutaría la palabra clave Suicide(), aunque el programa seguiría ejecuatandose.

Suicide(); end;

Este “end” finaliza el “if”. Como regla es necesario un “end” para cada “if”, más uno para la finalizar la función.end; Este “end” finaliza la función.

function SquadArrive()LandReinforcement(103);

Este comando llama al grupo de refuerzo “103”, para que aparezca en el mapa.

RunScript("SquadMove", 2000); Suicide();

end;

function SquadMove() Cmd(0, 103, 1530, 1320);

Este comando hace que la unidad “103” se mueva (0), a la posición de las coordenada “1530, 1320”.

Cmd(6, 104, 10); Este comnado hace que la unidad “104” entre (6) en el edificio “10”.

Suicide(); end;

function Init() RunScript("MoveCar", 3000); RunScript("FarmCheck", 2000);

Este comnado ejecuta la función “FarmCheck 2 segundos despues del inicio del juego.Debido a que en esta función hay una condición al inicio de la misma, hasta que no se cumpla la condición no tendrán efecto las acciones que dependen de la condición.

Recomendación.- Si se utliza el editor SciTe, este coloca un guión a la izquierda de cualquier linea que requiera una sentencia “end;”. En los ejemplos se emplazan todos los “end” a la izquierda para facilitar el que se escriban todos.

Nota.- En las funciones condicionales los simbolos que se pueden utilizar son los siguientes:

a == b a es igual que b a > b a es mayor que b a < b a es menor que b a >= b a es mayor o igual que b a <= b a es menor o igual que b a ~= b a no es igual que b

Nota.- Esta función es muy util ya que representa una gran ayuda para las pruebasfunction DebugView

Password("Panzerklein"); DisplayTrace("any text you like"); ShowActiveScripts(); -- God(0, 2); Suicide();

end;

Page 12: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

function Init() Runscript(“DebugView”, 1000);

end;

Explicaciónfunction DebugView

Password("Panzerklein");Este comando hace que las otras sentencias se ejecuten.

Nota.- Si se ejecuta Blitzkrieg con el fichero ailogic.dll de Stalingrad (la unidades se han modificado para que puedan hacer fuego a través de los edificios) se debe utilizar el comando Password(“www.dtf.ru”).

DisplayTrace("cualquier texto"); Visualiza, durante el juego, el texto que está entre las comillas. Se utiliza aquí porque esta función arrancará al inicio del juego, por tanto si no se visualiza es que el progrma no arranca.

ShowActiveScripts(); En el modo consola, durante el juego, se visualizará el texto de las sentencias del programa que se están ejecutando. Para activar el modo consola cuando Blitzkrieg está activo pulsar el tabulador.

-- God(0, 2);Este comando es un truco. El parametro “0” indica el jugador sobre el que tendrá efecto y el parámetro “2” especifica que sus fuerzas pueden matar al contrario de un golpe y que no pueden ser dañadas por las fuerzas del otro jugador. Se requiere una contraseña para ejecutarse. Los dos guiones delante indican que actualmente la sentencia es inactiva y será considerada un comentario por el programa.Para hacerla operativa (en pruebas) eliminar los dos guiones y salvar el fichero.

Suicide(); end;

function Init() Runscript(“DebugView”, 1000);

end;

DebugView debe ser arrancada desde la función Init sin que esta contenga ninguna otra función.

Nota.- Al utilizar DisplayTrace el mensaje a visualizar debe ir entre comillas doble (“), por tanto no deben incluirse dobles comillas en el contenido del mensaje. Para resaltar alguna palabra deben utilizarse simples comillas (').

Page 13: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Lección 4.- Utilizando los ObjetivosEsta lección trata del uso de los Objetivos y Variables.Objectives are the triggered to appear by the script pero el texto que nombra el objetivo y la colocación de la flecha que lo señalan en el minimapa son gestionados por el Editor de Recursos. Como definir y salvar objetivos se explica en otro momento, esta lección se centra en señalar los objetivos y en presentar el mensaje de Objetivos Completados. Las Variables Globales guardan los datos que posteriormente pueden ser utilizados. En esta lección solo utilizaremos las Variables Globales, otros tipos de variables se detallan en la Guia de Calvin.

Lección 4 .- Mapa (.bzm)Está basado en el mapa de la Lección 3 con las escuadras enemigas de la IA (jugador 1) en una trinchera, y una nueva ScriptArea llamada “Trench”.

Lección 4 .- Programa (.lua)En este programa se han señalado las nuevas funciones y comandos con una nota (--NEW--).

function DebugView() -- NEW -- Password("Panzerklein"); DisplayTrace("Amazing! This really works"); ShowActiveScripts(); --God(0, 2); Suicide();

end;

function MoveCar() Cmd(0, 100, 916, 1516); RunScript("MoveTruck", 4000); Suicide();

end;

function MoveTruck() Cmd(0, 101, 1583, 223); QCmd(0, 101, 1890, 1570); QCmd(0, 101, 1100, 1890); RunScript("ReavealObjective0", 10000); -- NEW -- Suicide();

end;

function ReavealObjective0() -- NEW --ObjectiveChanged(0, 0); DisplayTrace("Off we go"); RunScript("Objective0Check", 2000); -- NEW -- RunScript("Objective0Complete", 3000); -- NEW -- Suicide()

end;

function FarmCheck() if GetNUnitsInArea(0, "Farm") == 2 then

RunScript("SquadArrive", 1000); Suicide();

end; end;

function SquadArrive() LandReinforcement(103); RunScript("SquadMove", 2000); Suicide();

end;

function SquadMove() Cmd(3, 103, 2530, 2850); Cmd(6, 104, 10);

Page 14: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Suicide(); end;

function Objective0Check() -- NEW -- if GetNScriptUnitsInArea(130, "Trench") >=1 then

SetIGlobalVar("Mission0", 1); Suicide();

end; end;

function Objective0Complete() -- NEW -- if GetIGlobalVar("Mission0", 0) == 1 then

ObjectiveChanged(0, 1); Suicide()

end; end;

function Init() RunScript("DebugView", 1000); RunScript("MoveCar", 3000); RunScript("FarmCheck", 2000);

end;

Explicaciónfunction ReavealObjective0() -- NEW --

ObjectiveChanged(0, 0); Los parametros especifican cual es el objetivo (0), y cual es el cambio, en este caso mostrarlo (0).

DisplayTrace("Vamos"); Se visualiza un mensaje con el texto entrecomillado. Puede omitirse.

RunScript("Objective0Check", 2000); -- NEW – Ejecuta la función que comprueba una condición. En este caso si hay unidades con ScriptID=130 en el area “Trench”.

RunScript("Objective0Complete", 3000); -- NEW – Arranca la función que comprueba si el objetivo ha sido completado y si es asi muestra un mensaje.

Suicide() end;

function Objective0Check() -- NEW -- if GetNScriptUnitsInArea(130, "Trench") >=1 then

Función distinta a GetNUnitsInArea, con esta se comprueba si algún miembro de una unidad especifica (ScriptID =130) está dentro del area “Trench”.

SetIGlobalVar("Mission0", 1); Cuando se utiliza esta palabra clave se crea y salva una variable con el nombre y el valor especificados en los parámetros, en este caso el nombre = “Mission0” y el valor = 1. Tel valor puede ser cualquier número entero.

Suicide(); end; end; Dos “end” debido a que esta función contiene un “if”.

function Objective0Complete() -- NEW -- if GetIGlobalVar("Mission0", 0) == 1 then

Esta palabra clave devuelve los parámetros previamente salvados por “SetIGlobalVar”. El primer parámetro es el nombre de la variable global salvada y el segundo es siempre cero (0). En resumen esta línea evoca el valor de la variable que llamada ” Mission0 ” y comprueba si su valor corresponde a 1. Si la respuesta es cierta (true) la siguiente sentencia de la rutina se ejecutará. Si la respuesta no es cierta (false) el programa saltará hasta la linea siguiente al

Page 15: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

“end” que corresponde a este “if” y continuará la ejecución del programa.

ObjectiveChanged(0, 1); Los parametros (0, 1) indican, el primero el número del objetivo “0” y el segundo establece que ha sido completado “1”.

Suicide() end; end;

Nota.- No es necesario utilizar Variables Globarles para lanzar el mensaje de Objetivo Completado, pero se utilizan, a menudo, para comprobar si todos los objetivos de la misión han sido completados de la forma que se verá más adelante.

Una posible alternativa para comprobar si el objetivo ha sido alcanzado sería:

function Objective0Check() -- NEW -- if GetNScriptUnitsInArea(130, "Trench") >=1 then ObjectiveChanged(0, 1); Suicide();

end;end;

Page 16: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Lección 5.- Uniendo todas las piezasEsta lección pone en práctica las lecciones previas con condiciones para los objetivos, diferentes tipos de pruebas y multiples refuerzos. Se explica el uso de “if ... else” y “if... elseif”. Se añaden las condiciones Win y Loose y las llamadas a Variables Globales para probar si se cumplen las condiciones esperadas. Puede ser la base para muchas misiones con la utilización repetida de las pruebas en las diferentes ScriptAreas y con los distintos ScriptIDs.

Lección 5 .- Mapa (.bzm)Basado en el mapa de la Lección 4

Lección 5 .- Programa (.lua)

function DebugView() Password("Panzerklein"); DisplayTrace("Lua realmente no da ningún miedo!"); ShowActiveScripts(); --God(0, 2); Suicide();

end;

function MoveCar() Cmd(0, 100, 916, 1516); RunScript("MoveTruck", 4000); Suicide();

end;

function MoveTruck() Cmd(0, 101, 1583, 223); QCmd(0, 101, 1890, 1570);QCmd(0, 101, 1100, 1890); RunScript("ReavealObjective0", 10000); Suicide();

end;

function ReavealObjective0() ObjectiveChanged(0, 0); DisplayTrace("Vamos"); RunScript("Objective0Check", 2000); RunScript("Objective0Complete", 3000); Suicide()

end;

function FarmCheck() if GetNUnitsInArea(0, "Farm") == 2 then

RunScript("SquadArrive", 1000); Suicide();

end; end;

function SquadArrive() LandReinforcement(103); RunScript("SquadMove", 2000); Suicide();

end;

function SquadMove() Cmd(3, 103, 2530, 2850); Cmd(6, 104, 10); Suicide();

end;

function Objective0Check() if GetNScriptUnitsInArea(103, "Trench") >= 1 then

SetIGlobalVar("Mission0", 1); Suicide();

Page 17: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

end; end;

function Objective0Complete() if GetIGlobalVar("Mission0", 0) == 1 then

ObjectiveChanged(0, 1); RunScript("Objective1", 2000); -- NEW -- Suicide();

end; end;

function Objective1() -- NEW -- ObjectiveChanged(1, 0); RunScript("Objective1Complete", 3000); DisplayTrace("Eliminar a todos los americanos del area"); LandReinforcement(105); Cmd(3, 105,2335, 3015); RunScript("HeavyArmourDeploy", 30000); Suicide();

end;

function Objective1Complete() -- NEW -- if GetNUnitsInParty(1) <= 3 then

ObjectiveChanged(1, 1); SetIGlobalVar("Mission1", 1); Suicide();

end; end;

function HeavyArmourDeploy() -- NEW -- LandReinforcement(106); RunScript("HeavyArmourMove", 2000); Suicide();

end;

function HeavyArmourMove() -- NEW -- if GetNUnitsInArea(1, "Trench") > 0 then

Cmd(3, 106, GetScriptAreaParams(“Trench”)); else

Cmd(3, 106, 393, 3777); Suicide();

end; end;

function USCounterattack() -- NEW -- if GetNUnitsInArea(1, "Trench") <= 20 then

RunScript("USTanks", 3000); Suicide();

end; end;

function USTanks() -- NEW -- LandReinforcement(200); Suicide();

end;

function WinLoose() -- NEW -- if GetIGlobalVar("Mission0", 0) * GetIGlobalVar("Mission1", 0) == 1 then

Win(0); elseif

GetNUnitsInScriptGroup(103) + GetNUnitsInScriptGroup(105) +GetNUnitsInScriptGroup(106) == 0 and GetIGlobalVar("Mission0", 0) == 1 then

Loose(0); Suicide();

Page 18: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

end; end;

function Init() RunScript("DebugView", 1000); RunScript("MoveCar", 3000); RunScript("FarmCheck", 2000); RunScript("USCounterattack", 2000); --NEW-- RunScript("WinLoose", 3000); --NEW--

end;

Explicaciónfunction Objective1() -- NEW --

ObjectiveChanged(1, 0); Como pasaba con el “Objetivo 0” explicado en Lección 4, esta palabra clave provoca que aparezca el mensaje de objetivo 1 y la flecha que lo señala en el minimapa.

RunScript("Objective1Complete", 3000); Arranca la función (a los 3 segundos de iniciar el juego) que comprueba si el objetivo 1 ha sido completado.

DisplayTrace("Eliminar a todos los americanos del area"); Visualiza el mensaje con el texto entrecomillado. Podría omitirse si la función anterior determinara que el juego ha terminado.

LandReinforcement(105); Función que hace entrar los refuerzos de AFVs ligeros (ScriptGroup=105).

Cmd(3, 105, 2335, 3015); Mueve, de forma agresiva (3), el grupo de refuerzo (105) a la nuevas coordenadas “x, y”.

RunScript("HeavyArmourDeploy", 30000); Arranca la función “HeavyArmourDeploy” despues de 30 segundos (30000 milisegundos).

Suicide(); end;

function Objective1Complete() -- NEW -- if GetNUnitsInParty(1) <= 3 then

Comprueba si el número de unidades enemigas, manejadas por la IA (“1”) es menor o igual a 3.ObjectiveChanged(1, 1);

Si la condición comprobada es cierta (True) el objetivo 1 está ha sido completado.SetIGlobalVar("Mission1", 1);

Además, al cumplirse la condición, este comando crea y salva una variable con el nombre y el valor especificados en los parámetros, en este caso el nombre es “Mission1” y el valor es 1.

Suicide(); end; end;

function HeavyArmourDeploy() -- NEW -- LandReinforcement(106);

Esta función hace entrar en el juego a los tanques (ScriptGroup=106).RunScript("HeavyArmourMove", 2000);

A los 2 segundos de juego arranca la función que hace moverse a los tanques.Suicide(); end;

function HeavyArmourMove() -- NEW -- if GetNUnitsInArea(1, "Trench") > 0 then

Comprueba si quedan unidades de la IA en el area “Trench”.Cmd(3, 106, GetScriptAreaParams(“Trench”));

Si la respuesta de la condición es verdadera, los tanuqes (ScriptGroup 106) se mueven en formación de ataque (3) a las coordenadas del ScriptArea “Trench”.

else Cmd(3, 106, 393, 3777);

Page 19: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

“else” por el contrario si la respuesta de la condición anterior no es verdadera, (a menudo no existe la posibilidad de preguntar para obtener directamente una respuesta falsa por lo que hay que utilizar “else), en este caso los tanques se moverán a las coordenadas “x, y” (393, 3777).

Suicide(); end; end;

function USCounterattack() -- NEW -- if GetNUnitsInArea(1, "Trench") <= 20 then RunScript("USTanks", 3000); Suicide();

end; end;

function USTanks() -- NEW -- LandReinforcement(200); Suicide(); end;

function WinLoose() -- NEW – if GetIGlobalVar("Mission0", 0) * GetIGlobalVar("Mission1", 0) == 1 then

En esta condición se comprueban si las dos misiones han sido completadas (1 multiplicado por 1 debe es igual a 1) Las variables globales “Mission0” y Mission 1 habrán actualizados sus valores a 1 al completarse.

Win(0); Si la respuesta a la condición es verdaedera (True) el jugador “0” gana y el mensaje “You Win” es visualizado.

elseif GetNUnitsInScriptGroup(103) + GetNUnitsInScriptGroup(105) +GetNUnitsInScriptGroup(106) == 0 andSi la respuesta a la primera condición no es verdadera (False) entonces “elseif” se plantea una segunda condición que comprueba si todas las unidades del jugador humano han sido eliminadas. La utilización de la palabra clave “and” une esta condición con otra y ambas deben ser ciertas (True) para que el resulatado de la condición sea verdadero.

GetIGlobalVar("Mission0", 0) == 1 then Comprueba si el primer objetivo ha sido completado. Esta comprobación es necesaria debido a que al función “WinLoose()” se está ejecutando durante todo el juego (arranca en la función “Init”) y los refuerzos de los jugadores no deben llegar hasta que el primer objetivo está completo. Por tanto sin esta comprobación adicional la función se ejecutaría 3 segundos despues de empezar el juego, su objetivo es que los refuerzos pendientes de llegar sean igual a 0 antes de ejecutar la siguiente linea.

Loose(0); Si la respuesta de la segunda condición es verdadera (True) el jugador humano pierde y el mensaje You Lost se visualiza.

Suicide(); end; end; Dos “end” debido a que esta función contiene un “if”, pero solamente dos ya que “elsif” no supone una nueva condición logica, es unicamente la respuesa falsa (False) a un “if”.

function Init() RunScript("DebugView", 1000); RunScript("MoveCar", 3000); RunScript("FarmCheck", 2000); RunScript("USCounterattack", 2000); --NEW-- RunScript("WinLoose", 3000); --NEW--

end;

Nota.- La función WinLoose podría haber sido escrita tambien de la siguiente forma:function WinLoose() -- NEW --

if GetIGlobalVar("Mission0", 0) * GetIGlobalVar("Mission1", 0) == 1 then Win(0); if GetNUnitsInScriptGroup(103) + GetNUnitsInScriptGroup(105) +GetNUnitsInScriptGroup(106)

== 0 and GetIGlobalVar("Mission0", 0) == 1 then Loose(0); Suicide();

Page 20: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

end; end; end;Tres “end”, uno por cada condición “if” más otro por la función.

Page 21: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Lección AvionesEsta lección muestra como utilizar la programación para llamar a la aviación en respuesta a un evento del mapa.

Lección Aviones .- Mapa (.bzm)Esta es una posición defensiva rodeada por el MapArea llamada “Bunker”. La aviación ha sido asignada al jugador humano utilizando la opción Edit Units Creation del Editor de Mapas (parece que … adecuadamente no estoy seguro … un tipo de hongo cabeza abajo). Hacer clic en el botón del avión para desplegar el menú, clic de nuevo en el simbolo “+” del Player [0], clic en el simbolo “+” de Aviation. Seleccionar el tipo de avión y cuantos aviones de cada tipo seleccionado, de esta forma se definen las unidades que serán utilizadas.Lo más importante es seleccionar el “Punto de aparición”, debe ser establecido para poder utilizar la aviacion. Hacer doble clic en la linea “Appear points” y seleccionar “Add”. A continuación deben introducirse los valores de las coordenadas “x, y” donde los aviones deben aparecer. Notese que estos valores se introducen como coordenadas VIS y no como coordenada Script (en la parte inferior de la pantalla, del editor, se visualizan los valores de ambos sistemas de coordenadas). Una vez seleccionado el punto de aparición, cerrar el menu desplegable.

Lección Aviación .- Programa (.lua)function DebugView()

Password("Panzerklein"); DisplayTrace("Here come the planes"); ShowActiveScripts(); --God(0, 2); Suicide();

end;

function PlaneTrigger() if GetNUnitsInArea(1, "Bunker") >= 1 then

Cmd(36, 999, 0, 1100, 2070); -- Cmd(36, 999, 0, GetScriptAreaParams("Bunker")); Suicide();

end; end;

function Init() RunScript("DebugView", 1000); RunScript("PlaneTrigger", 3000);

end;

Explicaciónfunction PlaneTrigger()

if GetNUnitsInArea(1, "Bunker") >= 1 then Esta condición comprueba si el número de unidades de la IA, en el area “Bunker” es igual o mayor que 1.

Cmd(36, 999, 0, 1100, 2070); Este comando llama a la aviación (36) con el codigo de ataque a tierra (ver la Guia Calvin para una lista completa), la ID 999 es una identificación temporal para la aviación (podría ser cualquier número pero por convención los creadores de mapas reservan los números 99, 999, 9999 para la aviación), “0” es el codigo que identifica al jugador, “1100, 2070” son las coordenadas del punto del mapa por donde aparecerán los aviones (en coordenadas Script)

-- Cmd(36, 999, 0, GetScriptAreaParams("Bunker")); Esta linea no se utiliza por tener dos guiones al principio. Es una alternativa para llamar a los aviones, en lugar de enviarlos a las coordenadas “x,y” determinadas, se envian a las coordenadas que corresponden al ScriptArea “Bunker”.

Suicide(); end; end; Dos “end”, uno por el “if” y el otro por la función.

Page 22: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Lección PatrullaEsta lección muestra como crear una ruta de patrulla. En el ejemplo solamente una unidad compone la patrulla, pero pueden incluirse cualquier número de unidades. Si la/s unidad/es que componen la patrulla tienen capacidad de ataque, se enfrentarán a las unidades enemigas que encuentren y una vez finalizado el combate continuarán con la patrulla (si sobreviven).

Lección Patrulla .- Mapa (.bzm)En el mapa hay una tanqueta de reconocimiento con ScriptID 100, dentro del ScriptArea “Starting Point”.

Lección Patrulla .- Programa (.lua)Nota.- Este programa fue creado por Wespex en respuesta a un pregunta den los foros del Portal Blitzkrieg, además se incluye una forma alternativa de conseguir el mismo objetivo.

function PatrolArea() if GetNScriptUnitsInArea(100, "Starting Point") > 0 then

Cmd (3, 100, 765, 681); QCmd (3, 100, 288, 356); QCmd (3, 100, 545, 1145); QCmd (3, 100, 299, 1807); QCmd (3, 100, 1631, 1479); QCmd (3, 100, 1351, 647); RunScript("PatrolArea", 2000); Suicide();

end; end;

function Init() RunScript("PatrolArea", 5000);

end;

Explicaciónfunction PatrolArea()

if GetNScriptUnitsInArea(100, "Starting Point") > 0 then Se comprueba que la unidad de patrulla (ScriptID 100), existe y se encuentra en su posición inicial (ScriptArea Starting Point).

Cmd (3, 100, 765, 681); Orden de movimiento en modo de ataque (3) para la unidad (100) hasta las coordenadas (x=765, y=681).

QCmd (3, 100, 288, 356); Orden de movimiento en modo de ataque (3) para la unidad (100) hasta las coordenadas (x=288, y=356) una vez que se ha completado la orden de anterior (QCmd).

QCmd (3, 100, 545, 1145); Igual que la anterior.

QCmd (3, 100, 299, 1807); Igual que la anterior.

QCmd (3, 100, 1631, 1479); Igual que la anterior.

QCmd (3, 100, 1351, 647); Igual que la anterior pero como este es la última orden de movimiento las coordenadas de destino debe estar en el interior del ScriptArea “Starting Point”.

RunScript("PatrolArea", 2000); Vuelve a ejecutar de nuevo la función.

Suicide(); end; end; Dos “end”, uno por el “if” y el otro por la función.Nota.- Una patrulla puede tener cualquier número de movimientos en cada circuito, simplemente añadiendo o quitando lineas “Qcmd(3, ScriptID, x, y). Lo importante es que el último movimiento deje a la unidad de patrulla dentro del ScriptArea que es comprobada en la primera línea de la función.

Page 23: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Depurando el programaDepurar es el proceso de encontrar y eliminar errores en el codigo. En el mundo de la programación los pasos a realizar para depurar un programa son:

● Reconocer que existe un error.● Aislar la fuente (las lineas de codigo) del error.● Identificar la causa del error.● Determinar un arreglo para el error.● Aplicar el arreglo del error.

Los programas necesitan ser depurados si tienen cualquier imperfección, esto es, si no se comporta como se espera. Un programa tendrá problemas cuando cualquiera de los objetivos planteados en el codigo no se cumpla como se espera en ejecución del juego.Es aconsejable incluir alguna sentencia DisplayTrace en la función Init que visualice un texto parecido a “Programa en ejecución....” . Si el programa es correcto este mensaje se visualizará inmediatamente. Si no aparece el programa tiene problemas que impiden su ejecución. La sentencia puede ser eliminada, o dejada como comentario, una vez que el codigo esté libre de errores.

Consejo 1Cuando un programa no se ejecute adecuadamente no es necesario salir de Blitzkrieg. Se puede volver a Windows, manteniendo la ejecución en segundo plano, depurar y editar el programa, salvarlo y entonces seleccionar “Restart Mission”, opción que vuelve a iniciar la ejecución del programa desde el inicio.Nota.- Esta opción no funcionará si el fichero del programa se encuentra dentro de un fichero .pak ya que estos ficheros están bloqueados cuando el editor y/o el juego están activos.

Consejo 2No incluir el mapa en un fichero .pak hasta que no esté completamente depurado. Cualquier mapa que sea abierto, con el Editor, estando almacenado en un fichero .pak es salvado directamente en la carpeta Data del editor y puede, facilmente, quedar excluido del .pak a menos que el programador se acuerde de incluir los ficheros modificados.

Al depurar los programas es necesario chequear los errores más comunes:● Funciones que no tienen un “end” al final.● Lineas de comentarios con un solo guion en lugar de los dos que son necesarios.● Bloque de comprobación que no tienen su propio “end” al final. Por ejemplo:

function CheckTown() if GetNUnitsInArea(0, "Town") == 0 then ObjectiveChanged(0,1); RunScript( "Objective1", 5000);

end;El codigo anterior es erroneo debido a que al bloque "if GetNUnits..." le falta el “end”. Cada bloque requiere su proio “end”.

● Uso incorrecto de mayusculas / minusculas: el comando “if” debe ir en minusculas, no es correcto teclear “If”.● Sentencias no finalizadas con punto y coma “;”. Esta regla no aplica a las funciones y palabras clave.● Valores (o cadenas de texto) que no se finalizan correctamente. Por ejemplo GetUnitsInArea(0, "Town) es

erroneo debido a que el nombre del ScriptArea no tiene las dobles comillas de cierre. ● El uso incorrecto de las doble comillas en DisplayTrace. Por ejemplo: DisplayTrace( "Comandante, los "Tigers"

han llegado."); es incorrecto porque al cerrar la palabra Tigers con dobles comillas se está indicando al programa que visualize "Comandante, los "

● Funciones y palabras clave embebidos entre parentesis, cuando no se escriben el número correcto de parentesis de apertura o cierre. Por ejemplo: if (GetNScriptUnitsInArea (1, "finalattack") == 1 then, es incorrecto debido a que la función GetNScriptUnitsInArea no se ha finalizado con un parentesis.

● Teclear Lose(); en lugar de Loose(); aún cuando la ortografia correcta para palabra que indica perder es Lose , la palabra clave correcta es Loose.

● Win(), en esta sentencia falta el número del jugado.

Para ahorrar tiempo durante el proceso de depuración es util sabe que errores siguientes NO “rompen” el programa:● Enviar al mapa un grupo de refuerzos inexistente.● Llamar a ejecución a una función que no existe (utilizando RunScript).

Page 24: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Depurando programas que se comportan de forma inesperadaAlgunas veces un programa no se comportará exactamente como se esperaba. Por ejemplo, los objetivos no se complentan habiendo satisfecho los requisitos o un grupo de refuerzo se presenta repetidas veces.

A continuación se presentan algunos de los errores más comunes que se dan en los programas:● Si se da el caso de que una acción en particular o un evento (por ejemplo, un grupo de refuerzo continua

apareciendo repetidamente en el mapa) es muy posible que falte la sentencia Suicide();. Esta sentencia hace que una función se detenga y su uso es critico para asegurar la correcta ejecución de los programas. Ejemplo:

function Init() RunScript(“MyCheck”, 5000); …

end;

function MyCheck() if GetNUnitsInArea(0, “Town”) > 0 then

RunScript(Reinforcements,5000); end; end;

function Reinforcements() LandReinforcement(100)

end; La ejecución de MyCheck se produce cada 5 segundos. Esta función comprueba que el jugador 0 tenga una o más unidades en el area “Town”. Si se cumple la condición la función Reinforcements es llamada para hacer aparece el grupo de refuerzo 100. No obstante, en el ejemplo, el grupo de refuerzo será llamado repetidas veces mientras el jugaor 0 disponga de alguna unidad en el area “Town” debido a que la función MyChechk no contiene una orden de finalizar una vez que la condición se ha cumplido una vez.El codigo correcto sería :

function MyCheck() if GetNUnitsInArea(0, “Town”) > 0 then

RunScript(Reinforcements,5000); Suicide();

end; end;

La sentencia Suicide(); dice al procesador que finalice la ejecución de la función MyCheck una vez que se ha cumplido la condición y los refuerzos han sido llamados.

● “Objective Received: Unknown Objective” . Este mensaje aparecerá en el mapa si la entrada correspondiente al objetivo falta en el fichero de mapas .xml. Sin embargo, este mensaje es normal si se ejecuta el mapa directamente desde el editor ya que Blitzkrieg no procesa los ficheros en las carpetas scenarios\custom\missions\nombre misión.

● Si al comprobar el número de unidades en un area, no se obtienen resultados hay que chequear que no existen dos areas definidas con el mismo nombre.

● Si las unidades de aviación no aparecen, despues de haber sido llamadas con la función Cmd, hay que comprobar que la aviación no ha sido, previamente desactivada, con la función DisableAviation(), en otro punto del programa.

Page 25: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Apendice A – Lista de Funciones Blitzkrieg (por Wespex)

Funciones Valores requeridos Valores devueltosAddIronMan (iScriptID) -ChangeFormation (iScriptID, iFormation) -ChangePlayer (iScriptID, iParty) -ChangeWarFog (iParty) -Cmd|GiveCommand (iAction, iScriptID, xLoc, yLoc) -DamageObject (iScriptID, fDamage) -DeleteReinforcement (iScriptID) -DisableAviation (iParty, iAviationType) -DisplayTrace (strText, params, ...) Texto en pantallaDraw - -EnableAviation (iParty, iAviationType) -FlagReinforcement (nParty) -GetActiveShellType (iScriptID) Tipo de munición utilizada por la artilleriaGetAviationState (iPlayer) Última llamada a la aviación realizada por el jugadorGetFGlobalVar (strGlobalVarName, 0) Nombre y valor de la variableGetFrontDir (iScriptID) Dirección a la que la unidad está mirandoGetIGlobalVar (strGlobalVarName,0) Nombre y valor de la variableGetMapSize - Tamaño del mapa en puntos scriptGetNAmmo (iScriptID) Niveles de munición (primario y secundario)GetNAntitankInScriptArea (strScriptAreaName) Número de obstaculos antitanque en el areaGetNAPFencesInScriptArea (strScriptAreaName) Número de alambradas de espino en el areaGetNFencesInScriptArea (strScriptAreaName) Número de vallas y muros en el areaGetNMinesInScriptArea (strScriptAreaName) Número de minas en el area (AT y AP)GetNScriptUnitsInArea (iScriptID, strScriptAreaName) Número de unidades con el ScriptID en el areaGetNTrenchesInScriptArea (strScriptAreaName) Número de trincheras en el areaGetNUnitsInArea (iPlayer, strScriptAreaName) Número de unidades del jugador en el areaGetNUnitsInCircle (iPlayer, X, Y, Radius) Número de unidades del jugadoe en las coordenadasGetNUnitsInParty (iPlayer) Número de unidades del jugador en el mapaGetNUnitsInScriptGroup (iScriptID, iPlayer) Número de unidades con el ScriptIDGetNUnitsOfType (strUnitType, iPlayer) Tipo de infanteriaGetObjCoord (iScriptID) Localización de los objetosGetObjectHPs (iScriptID_Static) Puntos de salud de los objetosGetScriptAreaParams (strScriptAreaName) Parámetros del areaGetSGlobalVar (strGlobalVarName, 0) Nombre y valor de la variableGetSquadInfo (iScriptID) Formación de las unidadesGetUnitState (iScriptID) Estado de la unidadGod (iParty, iMode) -IsEntrenched (iScriptID) Si la unidad está atrincherada = 1, si no = 0IsFollowing (iScriptID) Si la unidad sigue a otra = 1, si no = 0, si no existe -1IsStandGround (iScriptID) Si la unidad está atrincherada = 1, si no = 0Custom Function Input Value Valor salidaIsWarehouseConnected (iScript_StorageID) Si deposito de campaña conectado con deposito

principal = 1, si no = 0KillScript (strScriptFunctionName) -LandReinforcement (iReinfID) -Loose - -ObjectiveChanged (iObjNum, iState) Estado del objetivo, si = 0 -> visualizado; si = 1 ->

alcanzado, si = 2 -> no comprobadoPassword (strName) -QCmd|GiveQCommand : (iAction, iScriptID, params) -RandomFloat - Número decimal entre 0 y 1RandomInt (n) Número aleatorio entre 0 y nReserveAviationForTimes (iParty, iTime) -RunScript (strFunctionName, iTime, iTurns) -

Page 26: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Funciones Valores requeridos Valores devueltosSetCheatDifficultyLevel (n) -SetDifficultyLevel (n) -SetFGlobalVar (strGlobalVarName, fVar) -SetGameSpeed (n) -SetIGlobalVar (strGlobalVarName, iVar) -SetSGlobalVar (strGlobalVarName, sVar) -ShowActiveScripts - Visualiza en la consola el texto del programa que está

ejecutandoseSuicide - -SwitchWeather (iState) -SwitchWeatherAutomatic (iState) -Trace (strText, params) Visualiza un texto en la consolaViewZone (strScriptAreaName, iParam) -Win (iParty) -

Page 27: LUA Basico para Blitzkrieg 1 - underpop.free.frunderpop.free.fr/l/lua/docs/lua-basico-para-blitzkrieg.pdf · Cada uno de las primeras cinco lecciones se fundamenta en lo dicho previamente

Apendice B – Enlaces útiles

Editor SciTe para BlitzkriegGuia de Calvin para la Programación en LUATutorial para Mapas de un solo jugador por Wespex Otros Tutoriales en el Portal Blitzkrieg Creando un Mapa, Preguntas y Respuestas. Foros del Portal Blitzkrieg