Registrarse

[pokeemerald] Tutorial de Scripting

Kaktus

Miembro insignia
Miembro insignia




TUTORIAL DE SCRIPTING PARA POKEEMERALD





NOTA: Si estás usando métodos y herramientas para el hacking binario/tradicional, este tutorial no es relevante para ti.
Esto es para aquellos quien están usando pokeemerald. Si usas XSE, ¡este es el tutorial que estás buscando!


[hr][/hr]


Si ya has hackeado alguna vez con el método convencional, no deberías tener muchos problemas para scriptear en proyectos decompilados. Sin embargo, si eres totalmente nuevo en el mundillo del rom hacking y quieres empezar con pokeemerald, ¡con suerte esta guía te será de utilidad!​


¿Cuáles son las diferencias entre scripting en hacking convencional y hacking en pokeemerald?
En los proyectos de decompilación hay muchas ventajas. Lo primero de todo, es que no necesitas ninguna herramienta específica para poder scriptear, como XSE - todo lo que necesitas es un editor de texto, como podría ser Notepad++. Lo segundo, es que los scripts existentes son muy fáciles de editar - simplemente, editas el archivo “scripts.inc” y haces clic en "Guardar". El hacking binario requerirá que repuntees el script, lo que me lleva a la siguiente ventaja. No hay necesidad de preocuparse por buscar espacio libre y offsets, ya que el proceso de construcción de la ROM se encarga de todo por ti. ¡Preocuparse por el espacio libre o borrar accidentalmente algo es cosa del pasado!

[hr][/hr]

Este tema fue escrito originalmente por Avara en Pokecommunity y posteriormente traducido por mi. El post original está en desarrollo, por lo que a medida que salgan nuevas entregas, iré traduciéndolo y subiéndolo aquí. Por tanto, el mérito lo tiene ella mayormente, por haberlo escrito y estructurado, mi única labor es la traducción.

Para instalar pokeemerald, sigue estos pasos (en inglés). ¡Una vez todo instalado, solo necesitarás un editor de texto medianamente decente, como puede ser Notepad++, y PoryMap!

[hr][/hr]

CONTENIDO

*En construcción*
 
Última edición por un moderador:

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting

etiquetas para los eventos

Si miras en la carpeta “data/maps”, verás que se encuentran los archivos de cada mapa del juego. Cada carpeta de todos los mapas tiene un archivo “scripts.inc”, donde se encuentran los scripts de los respectivos mapas. También puedes abrir el script de cada mapa dando clic izquierdo a "Open Map Scripts" en la esquina superior derecha del menú "Eventos" de PoryMap.



Siempre y cuando no repitas el nombre de las etiquetas, puedes nombrarlas como quieras, aunque es recomendable seguir algún tipo de patrón a la hora de nombrarlos para estar más organizados y evitar liarnos en un futuro. Yo en lo persona, el esta guía usaré "Script_Algo" para scripts de diálogos y "Text_Algo" para los propios diálogos. Si echas un vistazo a los scripts originales, verás que siguen el patrón de "NombreDelMapa_Algo"/"NombreDelMapa_AlgoText" (o al menos, en el momento en el que estoy escribiendo esto).
Para asignar un script a un objeto del mapa, sólo hay que seleccionar al propio objeto, para más tarde seleccionar el propio nombre del script que hemos asignado previamente desde el input de "Script" (se puede ver a lo que me refiero en el cuadrado rojo de la imagen de arriba).

[POST="438993"]⤒
[/POST]

 
Última edición:

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting



Scripts simples de texto


Primero, os enseñaré un script bastante simple, y luego, lo desglosaremos para entenderlo.
Código:
Script_SimpleMsgScript::
	lock
	faceplayer
	msgbox Text_SimpleMsgScript, MSGBOX_DEFAULT
	release
	end

Text_SimpleMsgScript:
	.string "¡Hola!\n"
	.string "Me llamo Avara.\l"
	.string "¿Tú cómo te llamas?\p"
	.string "¡Encantada de conocerte, {PLAYER}!$"
Os explico:
  • lock bloquea al jugador para que no se pueda mover.
  • Alternativamente, lockall bloquea a todos los NPC's para que no se muevan.
  • faceplayer hace que el NPC al que le hablas te mire.
  • release hace que el jugador pueda volver a moverse.
  • En caso de haber usado lockall, se usará releaseall.
  • end indica que ahí acaba el script (obviamente).
Para la parte del texto, os explicaré algunos parámetros:
  • .string indica una nueva línea en el diálogo.
  • \n salta a la siguiente línea.
  • \l se usa sólo después de usar \n, que sirve para desplazar el texto hacia arriba y mostrar la siguiente línea (lo correcto sería hacer ese desplazamiento cuando ya hay dos líneas, por ello que sea recomendable usar primero \n)
  • \p muestra la siguiente línea, limpiando lo que se ve en la textbox (por lo que es como si fuera otro "párrafo", para ejemplificar).
  • $ indica el final del texto.


La línea del msgbox contiene primero la dirección de donde tomará el texto, y el tipo de textbox en el que lo mostrará - que en el ejemplo de abajo es MSGBOX_DEFAULT. Como podrás imaginar, {PLAYER} muestra el nombre del jugador.

[hr][/hr]


Aquí hay más ejemplos para los otros tipos de msgbox:
Código:
Script_SimpleNPCScript::
	msgbox Text_SimpleNPCScript, MSGBOX_NPC
	end

Text_SimpleNPCScript:
	.string "¡Hola!\n"
	.string "Me llamo Avara.$"
MSGBOX_NPC no necesita ni lock ni faceplayer ni release (ojo, end ), cuando MSGBOX_DEFAULT, sí lo necesita. Creo que es lo suficientemente intuitivo como para saber que estos son generalmente usados en NPC's

[hr][/hr]


Código:
Script_SignpostScript::
	msgbox Text_SignpostScript, MSGBOX_SIGN
	end

Text_SignpostScript:
	.string "Tienda de Hierbas Pokémon\n"
	.string "¡Cuanto más amargo, más\l"
	.string "cura!$"
MSGBOX_SIGN se utiliza para carteles; al igual que MSGBOX_NPC, No necesitas usar lock, faceplayer o release.

[hr][/hr]


Bien, ahora vamos a ver el tipo de mensaje "SI/NO", o "YES/NO"; que nos puede ser de utilidad para muchas cosas.

Código:
Script_SimpleYesNoScript::
	lock
	faceplayer
	msgbox Text_SimpleYesNoScriptQuestion, MSGBOX_YESNO
	compare VAR_RESULT, 0
	goto_if_eq Script_PlayerAnsweredNo
	msgbox Text_PlayerAnsweredYes, MSGBOX_DEFAULT
	release
	end

Script_PlayerAnsweredNo::
	msgbox Text_PlayerAnsweredNo, MSGBOX_DEFAULT
	release
	end

Text_SimpleYesNoScriptQuestion:
	.string "¡Los Pokémon de tipo Dragón\n"
	.string "son los mejores!\p"
	.string "¿No crees?$"

Text_PlayerAnsweredYes:
	.string "¡Eso es! ¡Los dragones manda!$"

Text_PlayerAnsweredNo:
	.string "¡Diría que no has usado\n"
	.string "en tu vida!$"

Vale, aquí hay algunos comandos nuevos. El primero es compare VAR_RESULT, este compara es lo que ha contestado el jugador - 0 si ha dicho "No", 1 si ha dicho "Si". Pero ahora mismo no toca hablar de variables, ya hablaremos de ellas más tarde.
La línea goto_if_eq indica al script que debe ir a otra sección si se cumple la condición que le hemos especificado, en este caso, 0, es decir, que haya dicho que no. Si no es igual a 0, el script continuará con normalidad, sin saltar a dicha sección (matizar que una vez salta a esa sección, el código que seguía después del goto_if_eq no se ejecutará)

[POST="438993"]⤒
[/POST]

 
Última edición:

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting



Buffers


Empezaremos con bufferleadmonspeciesname, que lo que hace es tomar la especie del primer Pokémon de tu equipo

Código:
bufferleadmonspeciesname [NÚMERO]
El [NUMERO] será el "lugar" donde se almacene el nombre de tu Pokémon. Y para que entendáis mejor a lo que me refiero, pondré un ejemplo: para usar {STR_VAR_1} usaríamos el número 0, para {STR_VAR_2} sería el 1, etc. {STR_VAR_1} será lo que usemos en los textos como variables para mostrar el nombre que hemos almacenado, tal que así:
Código:
Script_ElLiderDelEquipoEsMono::
bufferleadmonspeciesname 0
msgbox Text_ElLiderDelEquipoEsMono, MSGBOX_NPC
end

Text_ElLiderDelEquipoEsMono:
.string "¡Aww, tu {STR_VAR_1} es monísimo!$"


¿En serio pensabais que no iba a elegir a Mudkip?

La línea del bufferleadmonspeciesname siempre antes que el msgbox que lo usa, en caso contrario, no sabrá que nombre escribir y por tanto tendrás como resultado un glitch en el texto. Es prácticamente lo mismo para todos los comandos "buffers", incluido el siguiente, bufferspeciesname:

Código:
bufferspeciesname [NÚMERO], [SPECIES_]
Es exactamente igual que antes, sólo que ahora estás añadiendo una coma, y el número de la pokédex que tiene el Pokémon del cuál quieres almacenar su nombre.
Ahora, combinemos bufferleadmonspeciesname y bufferspeciesname en un script:

Código:
Script_CombinandoBuffers::
bufferleadmonspeciesname 0
bufferspeciesname 1, SPECIES_TOTODILE
msgbox Text_CombinandoBuffers, MSGBOX_NPC
end

Text_CombinandoBuffers:
.string "¡ Tu {STR_VAR_1} es guay, pero\n"
.string "mi {STR_VAR_2} es mucho mejor!$"


En este script, lo único que hemos hecho es guardar la especie del primer Pokémon de nuestro equipo(y no su mote, por si cabe lugar a dudas) en {STR_VAR_1} y la especie de "Totodile" en {STR_VAR_2}. Por si lo necesitarais, la lista de "defines" de los Pokémon está en “include/constants/species.h”. ¿Empezáis a entenderlo? ¡Espero que sí!

[POST="438993"]⤒
[/POST]

 
Última edición:

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting



Flags


Pensad en las flags como un interruptor - sólo puede estar enchufado ("ON") y apagado ("OFF"), y nada más. Estos pueden ser usados por ejemplo para comprobar el progreso del jugador en el juego, si el jugador ya ha realizado cierto evento, o incluso para mostrar o esconder objetos en el mapa.

Activar y desactivar flags es bastante sencillo; lo único que necesitamos hacer es:
Código:
setflag [Flag]
para activar una flag, y:
Código:
clearflag [Flag]
para desactivarla.

Para comprobar si una flag está activada
Código:
goto_if_set [Flag], [Script_Al_Que_Ir]
Si en la carpeta de tu proyecto de pokeemerald abres “include/constants/flags.h”, encontrarás una lista de todas las variables del juego. Algunas flags tienen usos especiales, por ejemplo para activar las zapatillas de correr, o para activar ciertos menús. En este script de prueba vamos a activar la flag que te activa la Pokédex:
Código:
Script_ComprobarFlagDex::
	lock
	faceplayer
	goto_if_set FLAG_SYS_POKEDEX_GET, Script_FlagDexActivada
	msgbox Text_FlagDexDesactivada, MSGBOX_DEFAULT
	setflag FLAG_SYS_POKEDEX_GET
	release
	end
	
Script_FlagDexActivada::
	msgbox Text_FlagDexActivada, MSGBOX_DEFAULT
	release
	end
	
Text_FlagDexDesactivada:
	.string "La flag de la Pokédex\n"
	.string "está desactivada.\p"
	.string "Activando...$"
	
Text_FlagDexActivada:
	.string "La flag de la Pokédex\n"
	.string "ya está activada.$"
Si la flag ya está activada, el script salta a Script_FlagDexActivada y te avisa de que la flag de la Pokédex ya estaba previamente activada. Si estaba desactivada, el script continua, y te muestra "La flag de la Pokédex está desactivada. Activando..." y la activa.



[POST="438993"]⤒
[/POST]

 
Última edición:

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting



Dependencia del género


Como bien dice el título, en este entrega vamos a aprender a mostrar un mensaje en función de si tu jugador es masculino o femenino. Podrás usar esto para eventos que dependan del género del jugador. El script se vería algo así:

Código:
checkplayergender
compare VAR_RESULT, [Gender]
goto_if_eq [Script Label]

[hr][/hr]

Un ejemplo más visual:
Código:
Script_DependenciaDelGenero::
	checkplayergender
	compare VAR_RESULT, MALE
	goto_if_eq Script_EjemploMasculino
	msgbox Text_EjemploFemenino, MSGBOX_NPC
	end

Script_EjemploMasculino::
	msgbox Text_EjemploMasculino, MSGBOX_NPC
	end

Text_EjemploFemenino:
	.string "Estás jugando como chica.$"
	
Text_EjemploMasculino:
	.string "Estás jugando como chico.$"

Puedes escribirlo al contrario, claramente:
Código:
Script_DependenciaDelGenero::
	checkplayergender
	compare VAR_RESULT, FEMALE
	goto_if_eq Script_EjemploFemenino
	msgbox Text_EjemploMasculino, MSGBOX_NPC
	end

Script_EjemploFemenino::
	msgbox Text_EjemploFemenino, MSGBOX_NPC
	end

Text_EjemploMasculino:
	.string "Estás jugando como chico.$"

Text_EjemploFemenino:
	.string "Estás jugando como chica.$"


Atendiendo al primer ejemplo del script, lo único que hemos hecho es usar el checkplayergender (que almacena en la variable temporal VAR_RESULT el resultado) y luego más tarde hemos comprobado con COMPARE si el resultado de VAR_RESULT es MALE (es decir, masculino), y en caso de que sí, va al script que muestra el mensaje de que estás jugando como chico, claramente, en caso contrario, como hemos explicado anteriormente, continuaría el script, por lo que mostraría el texto que dice que somos chica.

[POST="438993"]⤒
[/POST]

 
Última edición:

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting



Mostrar/Ocultar Objetos del mapa


¿Necesitas hacer desaparecer un overworld?
Código:
removeobject [ID_del_Objeto]
¡Pues puedes hacerlo con esa simple línea!
Para encontrar el "ID_del_Objeto", entra a PoryMap, entra al mapa correspondiente y selecciona al overworld, y fíjate en esta parte, donde encontraremos el número que buscamos:




Para hacer que el sprite sea invisible por defecto y tengamos que activarlo, usaremos showobjectat:
Código:
showobjectat [ID_del_Objeto], [Mapa]
, que es ligeramente diferente - a parte del ID del objeto, también necesitas la ID del mapa donde aparecerá el objeto.
En caso de querer hacerlo desaparecer permanentemente (ya que en los caso anteriores sólo desaparecen hasta que sales del mapa), tendríamos que hacer algo más. Si vuelves a la pestaña de objetos de PoryMap en la que nos encontrábamos antes, verás algo así.

Aquí lo que haremos será asignar una flag al overworld (puedes encontrar ejemplos ya existentes en el propio pokeemerald).

Para ocultarlo permanentemente :
Código:
...
removeobject [ID_del_Objeto]
setflag [Flag]
...
En caso de que queramos que se vuelva a ver más tarde, sólo tendríamos que usar:
Código:
...
clearflag [Flag]
showobjectat [ID_del_Objeto], [Mapa]
...
[POST="438993"]⤒
[/POST]

 
Última edición:

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting



Variables


La lista de variables se puede encontrar en “include\constants\vars.h”.

Una variable sirve para almacenar un valor, al igual que las flags sirven para almacenar ("0") o ("1"), pero en este caso va desde el cero a un número bastante más grande.

Código:
setvar [Variable], [Valor_al_que_setearla]
Como podrás imaginar, el comando setvar establece el valor numérico a la variable que indiques. Si quisieramos sumar un valor al propio valor actual de la variable, usaríamos addvar:
Código:
addvar [Variable], [Valor_a_Añadir]
Por ejemplo, imaginemos que quiero aumentar el valor de VAR_ASH_GATHER_COUNT en 500 - Tendría:
Código:
addvar VAR_ASH_GATHER_COUNT, 500
Intuitivamente, deducimos que para restar un valor al valor ya existente de la variable, usaríamos subvar, que tiene la misma estructura:
Código:
subvar [Variable], [Valor_a_Restar]
Para comprobar si una variable tiene X valor:
Código:
compare [Variable], [Valor]
goto_if_[Condición] [Script_al_que_ir]
Y aquí os dejo una lista de diferentes goto_if/call_if:
Código:
goto_if_lt = Menor que
goto_if_eq = Igual a
goto_if_gt = Mayor que
goto_if_le = Menor [I]o[/I] Igual a
goto_if_ge = Mayor [I]o[/I] Igual a
[POST="438993"]⤒
[/POST]

 
Última edición:

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting



Give, Take y Check para Items


Antes de ponerte a pensar sobre la cantidad inmensa de objetos que le vas a dar a tu jugador, debes comprobar si tiene espacio para recibir dichos objetos.
Hay dos maneras de hacerlo.
Código:
checkitemspace [Item], [Cantidad]
compare VAR_RESULT, 0
goto_if_eq [ScriptAlQueIr]

Este comando comprueba si hay espacio suficiente para la cantidad que se ha especificado del objeto que queremos dar, en caso de que no haya suficiente espacio, la última línea del comando nos llevará a otro script. Comprobemos por ejemplo si tenemos espacio para al menos 5 Poké Balls en la bolsa:
Código:
checkitemspace ITEM_POKE_BALL, 5
compare VAR_RESULT, 0
goto_if_eq ScriptSinEspacio

Con esto hemos aprendido a comprobar si el jugador tiene espacio para recibir el objeto, ya que en caso de que no lo tenga, se podría seguir ejecutando el script, no recibir el objeto, y perder la oportunidad de recibirlo. Ahora, vamos a lo que realmente hemos venido; dar objetos:
Código:
giveitem_std [Item], [Cantidad]

Lo único que necesitas es la línea de arriba, bastante simple. Para los vagos, deciros que este comando ya genera un texto notificando que hemos recibido un objeto, por lo que no tendremos que preocuparnos de ello. Ahora... ¿recordáis cuando decía que habían dos métodos para comprobar si el jugador tiene suficiente espacio para recibir los objetos? (no me había olvidado c:<)
Pues ahora puedes matar dos pájaros de un tiro:
Código:
giveitem_std ITEM_POKE_BALL, 5
compare VAR_RESULT, 0
goto_if_eq Script_MochilaLlena

Con esto, estamos intentando darle 5 Poké Balls, peeeero, en caso de que no haya suficiente espacio, el script salta a Script_MochilaLLena.


Para eliminar un objeto:
Código:
takeitem [Item], [Cantidad]

Podemos comprobar si el jugador tiene o no un objeto en su mochila con el comando checkitem:
Código:
checkitem [Item], [Cantidad]
compare VAR_RESULT, 1
goto_if_eq [Script]

Ahora, veamos como nos quedaría un script de items. Este concretamente, comprobará si el jugador tiene alguna poción, en caso de que no, le dará una.
Código:
Script_ItemDemonstration::
	lock
	faceplayer
	msgbox Text_RegaloItem, MSGBOX_DEFAULT
	checkitem ITEM_POTION, 1
	compare VAR_RESULT, 1
	goto_if_ge Script_YaTienesPociones
	msgbox Text_DarPocion, MSGBOX_DEFAULT
	giveitem_std ITEM_POTION, 1
	compare VAR_RESULT, 0
	goto_if_eq Script_MochilaLlena
	release
	end

Script_YaTienesPociones::
	msgbox Text_YaTienesPociones, MSGBOX_DEFAULT
	release
	end

Script_MochilaLlena::
	msgbox Text_MochilaLlena, MSGBOX_DEFAULT
	release
	end

Text_RegaloItem:
	.string "Hoy el POKéMART está\n"
	.string "regalando una POCIÓN.$"

Text_DarPocion:
	.string "¡Aquí tienes!$"

Text_YaTienesPociones:
	.string "Ya tienes una POCIÓN.\n"
	.string "¡No seas avaricioso!$"

Text_MochilaLlena:
	.string "Tu MOCHILA está llena.$"

He usado goto_if_ge en lugar de goto_if_eq porque lo quería, no era comprobar si el jugador tenía exactamente una - quería comprobar si tenía una o más antes de llegar a Script_YaTienesPociones. El ge equivale a mayor o igual que. Si el jugador no tiene suficiente espacio en la mochila, el script irá a Script_MochilaLlena. Si el jugador tiene suficiente espacio en la mochila, y no tiene pociones, le dará una.
En caso de que no recuerdes como funcionaban los condicionales, te vuelvo a dejar la lista de goto_if/call_if:

goto_if_lt = Menor que
goto_if_eq = Igual a
goto_if_gt = Mayor que
goto_if_le = Menor o Igual a
goto_if_ge = Mayor o Igual a
Por último, si no sabéis que ID le pertenece a cada item, podéis encontrar la lista en “include/constants/items.h”.


[POST="438993"]⤒
[/POST]

 

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting



Dar Pokémon

¿Quieres dar un Pokémon al jugador? Bien, pues para ello, necesitaremos dos comandos.
El primero: getpartysize.
Código:
getpartysize
compare VAR_RESULT, [Número]
goto_if_eq [Script]
El compare VAR_RESULT comprueba si hay la cantidad de Pokémon especificada en tu equipo. Por ejemplo, compare VAR_RESULT, 6 servirá para comprobar si tienes seis Pokémon en el equipo. Si has leído el resto de entregas de este tema, ya sabrás que goto_if_eq significa que si el jugador sí que tiene la cantidad especificada de Pokémon, te redireccionará a otro script. ¿Y para qué hacemos esto? Pues muy sencillo, si el jugador tiene el equipo lleno (6), no podrá recibir el "regalo" (un Pokémon) en su equipo; así que haremos que vaya al PC (en pokeemerald, no sé seguro si para el resto de juegos decompilados se sigue el mismo proceso). De cualquier modo, depende de cómo quieras usarlo - si quieres dar un Pokémon cuando el jugador ya tenga seis en su equipo, sólo necesitarás que el script al que le redirija, le diga que su Pokémon va a ser almacenado en el PC. Si quieres que sólo lo reciba cuando tenga espacio en el equipo, puedes simplemente hacer que diga: "¡Vaya! no tienes espacio en tu equipo." Depende de lo que quieras en tu juego - realmente puedes usar ambas opciones, son válidas las dos.

Bueno, pues aquí el comando para dar un Pokémon
Código:
givemon [Pokémon], [Nivel], [Objeto equipado], 0x0, 0x0, 0
Abre “include/constants/species.h” para ver las especies de los Pokémon, y “include/constants/items.h” para la lista de los objetos. Si no quieres que tenga objetos equipados, sólo ponle ITEM_NONE. Y ahora, un ejemplo de como usar los dos comandos juntos: getpartysize y givemon:

Código:
Script_GivePokemonDemo::
	lock
	faceplayer
	msgbox Text_DarDratini, MSGBOX_DEFAULT
	getpartysize
	compare VAR_RESULT, 6
	goto_if_eq Script_EquipoLleno
	givemon SPECIES_DRATINI, 5, ITEM_DRAGON_FANG, 0x0, 0x0, 0
	playfanfare MUS_FANFA4
	msgbox Text_DratiniRecibido, MSGBOX_DEFAULT
	waitfanfare
	release
	end

Script_EquipoLleno::
	msgbox Text_EquipoLleno, MSGBOX_DEFAULT
	release
	end

Text_DarDratini:
	.string "Por favor, acepta este Dratini.$"

Text_DratiniRecibido:
	.string "¡{PLAYER} recibió un Dratini!$"

Text_EquipoLleno:
	.string "¡Vaya! no tienes espacio en\n"
	.string "tu equipo.$"

Con el comando getpartysize, hemos comprobado si tiene el equipo lleno, y si lo tiene, el script salta a Script_EquipoLleno, en donde no te da el Pokémon y te dice que tienes el equipo lleno. En caso de que no tenga los seis Pokémon en el equipo, te dará un Dratini de nivel 5 que lleva equipado un "Colmillo Dragón". Si ya tienes algo de experiencia con el scripting, te darás cuenta de que este script te dará Dratinis infinitos siempre que tengas hueco en el equipo. Y bueno, mi idea fue que si os habéis leído la sección de [POST="439012"]Flags[/POST], podréis arreglar eso por vuestra cuenta ;)

[POST="438993"]⤒
[/POST]

 

Kaktus

Miembro insignia
Miembro insignia
Respuesta: [pokeemerald] Tutorial de Scripting



Dar Huevos

Está sección abarcará cómo dar un huevo al jugador.

Código:
giveegg [Pokémon]
Super fácil.

Código:
Script_GiveEggDemo::
	lock
	faceplayer
	msgbox Text_PreguntaHuevo, MSGBOX_YESNO
	compare VAR_RESULT, 0
	goto_if_eq Script_RespuestaNo
	getpartysize
	compare VAR_RESULT, 6
	goto_if_eq Script_EquipoLleno
	giveegg SPECIES_LARVITAR
	playfanfare MUS_FANFA4
	msgbox Text_HuevoRecibido, MSGBOX_DEFAULT
	waitfanfare
	release
	end

Script_EquipoLleno::
	msgbox Text_EquipoLleno, MSGBOX_DEFAULT
	release
	end

Script_RespuestaNo::
	msgbox Text_RespuestaNo, MSGBOX_DEFAULT
	release
	end

Text_PreguntaHuevo:
	.string "¿Quieres este huevo?$"

Text_RespuestaNo:
	.string "Oh, que mal...$"

Text_HuevoRecibido:
	.string "¡{PLAYER} recibió un\n"
	.string "huevo!$"

Text_EquipoLleno:
	.string "¡Vaya! no tienes espacio en\n"
	.string "tu equipo.$"

Si has leído las entregas anteriores, entenderás que en este script le estamos preguntando al jugador si quiere o no quiere un huevo. Después de esto, si responde que "SI", primero el script comprobará si tiene suficiente espacio en el equipo para recibirlo. Ya he explicado como usar getpartysize en la sección [POST="439342"]Dar Pokémon[/POST], así que no veo necesario explicarlo de nuevo.


[POST="438993"]⤒
[/POST]

 

Diego Mertens

Dartrix Joven
Creo que estaría bien que incluyeran tutoriales que no están en el original, como trainerbattles, doubletrainerbattles, hacer cosas específicas como elegir Pokémon del equipo y que se reduzca a esa cantidad, etc...
 

Samu

Miembro insignia
Miembro insignia
Re: Respuesta: Tutorial de Scripting

Creo que estaría bien que incluyeran tutoriales que no están en el original, como trainerbattles, doubletrainerbattles, hacer cosas específicas como elegir Pokémon del equipo y que se reduzca a esa cantidad, etc...
He linkeado esto tantas veces y en tantos sitios que ya soy hasta pesado.

Wiki Scripting Decomp

En ese enlace tienes una lista completa de los comandos de pokeemerald y lo que hacen, Es posible que el nombre de algunos haya cambiado, ya que ahora mismo están avanzando con la documentación, y se modifican algunos de los identificadores.

Desafortundamente IK no está activo desde hace unos meses, por lo que ese post es lo mejor que vas a tener en Español. Al menos hasta que a alguien le apetezca hacer una guía completa de scripting para Decomp.
 

Juan Kio

Aprendiendo decomp...
Respuesta: [pokeemerald] Tutorial de Scripting




Scripts simples de texto


Primero, os enseñaré un script bastante simple, y luego, lo desglosaremos para entenderlo.
Código:
Script_SimpleMsgScript::
    lock
    faceplayer
    msgbox Text_SimpleMsgScript, MSGBOX_DEFAULT
    release
    end

Text_SimpleMsgScript:
    .string "¡Hola!\n"
    .string "Me llamo Avara.\l"
    .string "¿Tú cómo te llamas?\p"
    .string "¡Encantada de conocerte, {PLAYER}!$"
Os explico:
  • lock bloquea al jugador para que no se pueda mover.
  • Alternativamente, lockall bloquea a todos los NPC's para que no se muevan.
  • faceplayer hace que el NPC al que le hablas te mire.
  • release hace que el jugador pueda volver a moverse.
  • En caso de haber usado lockall, se usará releaseall.
  • end indica que ahí acaba el script (obviamente).
Para la parte del texto, os explicaré algunos parámetros:
  • .string indica una nueva línea en el diálogo.
  • \n salta a la siguiente línea.
  • \l se usa sólo después de usar \n, que sirve para desplazar el texto hacia arriba y mostrar la siguiente línea (lo correcto sería hacer ese desplazamiento cuando ya hay dos líneas, por ello que sea recomendable usar primero \n)
  • \p muestra la siguiente línea, limpiando lo que se ve en la textbox (por lo que es como si fuera otro "párrafo", para ejemplificar).
  • $ indica el final del texto.


La línea del msgbox contiene primero la dirección de donde tomará el texto, y el tipo de textbox en el que lo mostrará - que en el ejemplo de abajo es MSGBOX_DEFAULT. Como podrás imaginar, {PLAYER} muestra el nombre del jugador.

[hr][/hr]


Aquí hay más ejemplos para los otros tipos de msgbox:
Código:
Script_SimpleNPCScript::
    msgbox Text_SimpleNPCScript, MSGBOX_NPC
    end

Text_SimpleNPCScript:
    .string "¡Hola!\n"
    .string "Me llamo Avara.$"
MSGBOX_NPC no necesita ni lock ni faceplayer ni release (ojo, end ), cuando MSGBOX_DEFAULT, sí lo necesita. Creo que es lo suficientemente intuitivo como para saber que estos son generalmente usados en NPC's

[hr][/hr]


Código:
Script_SignpostScript::
    msgbox Text_SignpostScript, MSGBOX_SIGN
    end

Text_SignpostScript:
    .string "Tienda de Hierbas Pokémon\n"
    .string "¡Cuanto más amargo, más\l"
    .string "cura!$"
MSGBOX_SIGN se utiliza para carteles; al igual que MSGBOX_NPC, No necesitas usar lock, faceplayer o release.

[hr][/hr]


Bien, ahora vamos a ver el tipo de mensaje "SI/NO", o "YES/NO"; que nos puede ser de utilidad para muchas cosas.

Código:
Script_SimpleYesNoScript::
    lock
    faceplayer
    msgbox Text_SimpleYesNoScriptQuestion, MSGBOX_YESNO
    compare VAR_RESULT, 0
    goto_if_eq Script_PlayerAnsweredNo
    msgbox Text_PlayerAnsweredYes, MSGBOX_DEFAULT
    release
    end

Script_PlayerAnsweredNo::
    msgbox Text_PlayerAnsweredNo, MSGBOX_DEFAULT
    release
    end

Text_SimpleYesNoScriptQuestion:
    .string "¡Los Pokémon de tipo Dragón\n"
    .string "son los mejores!\p"
    .string "¿No crees?$"

Text_PlayerAnsweredYes:
    .string "¡Eso es! ¡Los dragones manda!$"

Text_PlayerAnsweredNo:
    .string "¡Diría que no has usado\n"
    .string "en tu vida!$"

Vale, aquí hay algunos comandos nuevos. El primero es compare VAR_RESULT, este compara es lo que ha contestado el jugador - 0 si ha dicho "No", 1 si ha dicho "Si". Pero ahora mismo no toca hablar de variables, ya hablaremos de ellas más tarde.
La línea goto_if_eq indica al script que debe ir a otra sección si se cumple la condición que le hemos especificado, en este caso, 0, es decir, que haya dicho que no. Si no es igual a 0, el script continuará con normalidad, sin saltar a dicha sección (matizar que una vez salta a esa sección, el código que seguía después del goto_if_eq no se ejecutará)

[POST="438993"]⤒
[/POST]

Cual seria el comando para poner de color el texto?
 

Kaktus

Miembro insignia
Miembro insignia
Cual seria el comando para poner de color el texto?
Si te fijas en la carpeta charmap.txt que está en la raíz del proyecto, verás que podrás encontrar toda la información sobre posibles tags para las strings. En concreto, para el color del texto encontramos tres utilidades: COLOR, HIGHLIGHT y SHADOW, que se definen por sí mismas. Tienes la opción de setear las tres a la vez con COLOR_HIGHLIGHT_SHADOW, que recibe tres paráemtros, uno por cada propiedad.

Los posibles parámetros (que sirven por igual para los cuatro tags) son los siguientes

Código:
TRANSPARENT
WHITE
DARK_GREY
LIGHT_GREY
RED
LIGHT_RED
GREEN
LIGHT_GREEN
BLUE

Por tanto, si por ejemplo quisieras poner el color frontal blanco, y el de la sombra con un rojo clarito, una string cualquiera te quedaría así
C:
const u8 gText_ExampleForKio[] = _("{COLOR WHITE}{SHADOW LIGHT_RED}EJEMPLO.");
Si después quisieras que volviera a usar el color por defecto, o usar otro color, tendrías que reestablecerlo manualmente.
 

JDreamMaker

To empepinao
Respuesta: [pokeemerald] Tutorial de Scripting




Dar Pokémon

¿Quieres dar un Pokémon al jugador? Bien, pues para ello, necesitaremos dos comandos.
El primero: getpartysize.
Código:
getpartysize
compare VAR_RESULT, [Número]
goto_if_eq [Script]
El compare VAR_RESULT comprueba si hay la cantidad de Pokémon especificada en tu equipo. Por ejemplo, compare VAR_RESULT, 6 servirá para comprobar si tienes seis Pokémon en el equipo. Si has leído el resto de entregas de este tema, ya sabrás que goto_if_eq significa que si el jugador sí que tiene la cantidad especificada de Pokémon, te redireccionará a otro script. ¿Y para qué hacemos esto? Pues muy sencillo, si el jugador tiene el equipo lleno (6), no podrá recibir el "regalo" (un Pokémon) en su equipo; así que haremos que vaya al PC (en pokeemerald, no sé seguro si para el resto de juegos decompilados se sigue el mismo proceso). De cualquier modo, depende de cómo quieras usarlo - si quieres dar un Pokémon cuando el jugador ya tenga seis en su equipo, sólo necesitarás que el script al que le redirija, le diga que su Pokémon va a ser almacenado en el PC. Si quieres que sólo lo reciba cuando tenga espacio en el equipo, puedes simplemente hacer que diga: "¡Vaya! no tienes espacio en tu equipo." Depende de lo que quieras en tu juego - realmente puedes usar ambas opciones, son válidas las dos.

Bueno, pues aquí el comando para dar un Pokémon
Código:
givemon [Pokémon], [Nivel], [Objeto equipado], 0x0, 0x0, 0
Abre “include/constants/species.h” para ver las especies de los Pokémon, y “include/constants/items.h” para la lista de los objetos. Si no quieres que tenga objetos equipados, sólo ponle ITEM_NONE. Y ahora, un ejemplo de como usar los dos comandos juntos: getpartysize y givemon:

Código:
Script_GivePokemonDemo::
    lock
    faceplayer
    msgbox Text_DarDratini, MSGBOX_DEFAULT
    getpartysize
    compare VAR_RESULT, 6
    goto_if_eq Script_EquipoLleno
    givemon SPECIES_DRATINI, 5, ITEM_DRAGON_FANG, 0x0, 0x0, 0
    playfanfare MUS_FANFA4
    msgbox Text_DratiniRecibido, MSGBOX_DEFAULT
    waitfanfare
    release
    end

Script_EquipoLleno::
    msgbox Text_EquipoLleno, MSGBOX_DEFAULT
    release
    end

Text_DarDratini:
    .string "Por favor, acepta este Dratini.$"

Text_DratiniRecibido:
    .string "¡{PLAYER} recibió un Dratini!$"

Text_EquipoLleno:
    .string "¡Vaya! no tienes espacio en\n"
    .string "tu equipo.$"

Con el comando getpartysize, hemos comprobado si tiene el equipo lleno, y si lo tiene, el script salta a Script_EquipoLleno, en donde no te da el Pokémon y te dice que tienes el equipo lleno. En caso de que no tenga los seis Pokémon en el equipo, te dará un Dratini de nivel 5 que lleva equipado un "Colmillo Dragón". Si ya tienes algo de experiencia con el scripting, te darás cuenta de que este script te dará Dratinis infinitos siempre que tengas hueco en el equipo. Y bueno, mi idea fue que si os habéis leído la sección de [POST="439012"]Flags[/POST], podréis arreglar eso por vuestra cuenta ;)

[POST="438993"]⤒
[/POST]

Buenos días:

En primer lugar gracias por el tutorial, Messirve muchísimo.

Estoy tratando de hacer que un NPC pueda darte un Pokémon y/o un huevo con una características predeterminadas (IVs determinados, presencia o no de Pokérus, que sea o no shiny, movimientos, naturaleza, etc,) y he visto que la función "givemon" tiene 6 inputs pero tanto en la wiki de Scripts como en tu tutorial solo habláis de los 3 primeros (especie, nivel y objeto), me gustaría también saber qué son los otros 3 (0x0, 0x0, 0) y si alguien sabe cómo puedo hacer lo que quiero.

(No penséis mal, la historia de mi hackroom se mueve en torno a la genética de los Pokémon.)

Muchísimas gracias de antemano.
 

Kalen

Usuario habitual
Buenas, soy nuevo en esto, y entiendo un poco tu tutorial, pero estoy usando la base de pokeemerald pero no consigo en el archivos “scripts.inc” para editar, uso notepad++
 

kakarotto

Leyenda de WaH
Buenas, soy nuevo en esto, y entiendo un poco tu tutorial, pero estoy usando la base de pokeemerald pero no consigo en el archivos “scripts.inc” para editar, uso notepad++

Lee el principio. Hay que leer.
 
Arriba