Le eché mano al pokeruby gracias a la Introducción a Pokeruby y he ido probando cositas, y como vi que no había ningún tutorial al respecto por aquí decidí escribirlo. El proceso funciona exactamente igual para pokeruby y pokeemerald aunque el código pueda variar ligeramente. En este tutorial usaré pokeruby pero no debería haber dificultad alguna de seguirlo en pokeemerald.
Intentaré dar descripciones detalladas, ya que la idea es impulsar a los nuevos usuarios (y a los no tan nuevos) a meterse en este campo y a no verlo con miedo (miedo me daría a mí a seguir perdiendo el tiempo modificando archivos binarios).
Antes, un par de aclaraciones para los que no tengan mucha idea del tema:
Función: conjunto de instrucciones que pueden ser llamadas. Pueden retornar un valor y en ocasiones requerir una serie de parámetros.
Comentario: línea que es ignorada por el compilador.
s8: tipo que indica que el valor es signed y que ocupa 8 bits. Es decir, que puede ser positivo o negativo y ocupa un byte.
Desactivando la escena del camión
Nos vamos al archivo pokeruby/src/overworld.c y buscamos la función CB2_NewGame() (por defecto en pokeruby está en la línea 1256 y en pokeemerald en la 1547), y encontraremos esto:
Basta con convertir en un comentario (añadir // delante de la línea) o eliminar gFieldCallback = ExecuteTruckSequence;. Tal que así:
Y... ya está. Compilamos y vemos que todo funciona correctamente. Podemos usar NODEP ya que no hemos modificado archivos que no sean .c .s
La función que nos interesa modificar en este caso está localizada en pokeruby/src/new_game.c, y se llama NewGameInitData() (por defecto está en la línea 161 en pokeruby, línea 155 en pokeemerald). Es un poco larga y lo que nos interesa solo está en las últimas líneas, así que solo copiaré un pedazo:
Podemos ver una llamada a la función WarpToTruck() que es la que se encarga de hacer el warp de nuestro jugador justo al empezar la partida, la cual está definida unas líneas antes de esta (por defecto en la línea 137 en pokeruby, línea 133 en pokeemerald):
Overworld_SetWarpDestination() prepara el warp y es necesario que le pasemos una serie de argumentos que ahora explicaré, mientras que WarpIntoMap() en pokeruby, o como se llama en pokeemerald, warp_in(), lo realiza.
Para cambiar el punto de inicio basta con modificar los argumentos de Overworld_SetWarpDestination() que van entre los paréntesis, y cada uno va separado por una coma. Los explicaré brevemente aunque los nombres son muy sugerentes y a los hackers os sonarán particularmente familiares:
s8 mapGroup: el grupo del mapa al que nos teletransportaremos.
s8 mapNum: el número del mapa al que nos teletransportaremos.
s8 warpId: la ID del warp que usaremos. Si no usamos ninguna, vamos a poner -1.
s8 x: la coordenada X del mapa al que nos teletransportaremos, -1 si no la indicaremos.
s8 y: la coordenada Y del mapa al que nos teletransportaremos, -1 si no la indicaremos.
Podemos editar esa línea de WarpToTruck() y problema resuelto, pero también podemos renombrar la función a un nombre más adecuado ya que no será el teletransporte al mítico camión. Yo en mi caso la renombraré. Iré a CB2_NewGame() y cambiaré su nombre, WarpToInitialMap(), por ejemplo.
Una vez hecho esto debemos cambiar también el nombre donde WarpToTruck() estaba definida:
Ahora solo nos queda cambiar los argumentos en la llamada a la función Overworld_SetWarpDestination(). Para ello, primero vamos a cambiar el grupo y el número del mapa. Podríamos usar el valor de cada mapa en caso de conocerlo directamente, pero lo mejor es hacer uso de las constantes que ya hay definidas. Podemos encontrarlas en pokeruby/include/constants/maps.h. Justo al principio del archivo nos encontraremos esto:
Y así todo el archivo en la gran mayoría. En este caso, voy a realizar el teletransporte a Petalburg city misma. Vamos a hacer uso de MAP_GROUP y MAP_NUM los cuales retornarán el grupo del mapa y el número del mapa respectivamente, al pasarle el nombre de la constante sin el MAP_ precedido. Aquí un ejemplo donde cambié el mapa del camión por el de Petalburg city:
Si ahora mismo compilamos y probamos, nos daremos cuenta de que aparecemos en ese mapa, pero solo en su centro. Tenemos que indicarle también en qué coordenadas a la función. Podemos hacer uso de valores decimales con normalidad, o con hexadecimales si añadimos el 0x delante del valor.
Y con esto ya estará, solo falta compilar. Al igual que en el cambio en el que se elimina la escena del camión, no realizamos cambios en archivos que no sean .s o .c, así que podemos ahorrar tiempo con NODEP.
Y eso es todo. ¡Nos vemos! Miau revoir~.
Intentaré dar descripciones detalladas, ya que la idea es impulsar a los nuevos usuarios (y a los no tan nuevos) a meterse en este campo y a no verlo con miedo (miedo me daría a mí a seguir perdiendo el tiempo modificando archivos binarios).
Antes, un par de aclaraciones para los que no tengan mucha idea del tema:
Función: conjunto de instrucciones que pueden ser llamadas. Pueden retornar un valor y en ocasiones requerir una serie de parámetros.
Comentario: línea que es ignorada por el compilador.
s8: tipo que indica que el valor es signed y que ocupa 8 bits. Es decir, que puede ser positivo o negativo y ocupa un byte.
Desactivando la escena del camión
Nos vamos al archivo pokeruby/src/overworld.c y buscamos la función CB2_NewGame() (por defecto en pokeruby está en la línea 1256 y en pokeemerald en la 1547), y encontraremos esto:
Código:
void CB2_NewGame(void)
{
FieldClearVBlankHBlankCallbacks();
StopMapMusic();
ResetSafariZoneFlag_();
NewGameInitData();
ResetInitialPlayerAvatarState();
PlayTimeCounter_Start();
ScriptContext1_Init();
ScriptContext2_Disable();
gFieldCallback = ExecuteTruckSequence;
do_load_map_stuff_loop(&gMain.state);
SetFieldVBlankCallback();
set_callback1(c1_overworld);
SetMainCallback2(c2_overworld);
}
Código:
void CB2_NewGame(void)
{
FieldClearVBlankHBlankCallbacks();
StopMapMusic();
ResetSafariZoneFlag_();
NewGameInitData();
ResetInitialPlayerAvatarState();
PlayTimeCounter_Start();
ScriptContext1_Init();
ScriptContext2_Disable();
// gFieldCallback = ExecuteTruckSequence;
do_load_map_stuff_loop(&gMain.state);
SetFieldVBlankCallback();
set_callback1(c1_overworld);
SetMainCallback2(c2_overworld);
}
Cambiando mapa inicialmake NODEP=1
La función que nos interesa modificar en este caso está localizada en pokeruby/src/new_game.c, y se llama NewGameInitData() (por defecto está en la línea 161 en pokeruby, línea 155 en pokeemerald). Es un poco larga y lo que nos interesa solo está en las últimas líneas, así que solo copiaré un pedazo:
Código:
void NewGameInitData(void)
{
[...]
ResetFanClub();
ResetLotteryCorner();
WarpToTruck();
ScriptContext2_RunNewScript(gUnknown_0819FA81);
}
Código:
void WarpToTruck(void)
{
Overworld_SetWarpDestination(MAP_GROUP(INSIDE_OF_TRUCK), MAP_NUM(INSIDE_OF_TRUCK), -1, -1, -1);
WarpIntoMap();
}
Para cambiar el punto de inicio basta con modificar los argumentos de Overworld_SetWarpDestination() que van entre los paréntesis, y cada uno va separado por una coma. Los explicaré brevemente aunque los nombres son muy sugerentes y a los hackers os sonarán particularmente familiares:
s8 mapGroup: el grupo del mapa al que nos teletransportaremos.
s8 mapNum: el número del mapa al que nos teletransportaremos.
s8 warpId: la ID del warp que usaremos. Si no usamos ninguna, vamos a poner -1.
s8 x: la coordenada X del mapa al que nos teletransportaremos, -1 si no la indicaremos.
s8 y: la coordenada Y del mapa al que nos teletransportaremos, -1 si no la indicaremos.
Podemos editar esa línea de WarpToTruck() y problema resuelto, pero también podemos renombrar la función a un nombre más adecuado ya que no será el teletransporte al mítico camión. Yo en mi caso la renombraré. Iré a CB2_NewGame() y cambiaré su nombre, WarpToInitialMap(), por ejemplo.
Código:
void NewGameInitData(void)
{
[...]
ResetFanClub();
ResetLotteryCorner();
WarpToInitialMap();
ScriptContext2_RunNewScript(gUnknown_0819FA81);
}
Código:
void WarpToInitialMap(void)
{
Overworld_SetWarpDestination(MAP_GROUP(INSIDE_OF_TRUCK), MAP_NUM(INSIDE_OF_TRUCK), -1, -1, -1);
WarpIntoMap();
}
Código:
#ifndef GUARD_CONSTANTS_MAPS_H
#define GUARD_CONSTANTS_MAPS_H
// Map Group 0
#define MAP_PETALBURG_CITY (0 | (0 << 8))
#define MAP_SLATEPORT_CITY (1 | (0 << 8))
#define MAP_MAUVILLE_CITY (2 | (0 << 8))
#define MAP_RUSTBORO_CITY (3 | (0 << 8))
#define MAP_FORTREE_CITY (4 | (0 << 8))
#define MAP_LILYCOVE_CITY (5 | (0 << 8))
[...]
Código:
Overworld_SetWarpDestination(MAP_GROUP(PETALBURG_CITY), MAP_NUM(PETALBURG_CITY), -1, -1, -1);
Código:
Overworld_SetWarpDestination(MAP_GROUP(PETALBURG_CITY), MAP_NUM(PETALBURG_CITY), -1, 15, 9);
Y eso es todo. ¡Nos vemos! Miau revoir~.