Registrarse

FR/E | [Finalizada] Pokémon errantes

Lo primero, un saludo a todo el foro. Éste es mi primer mensaje y mi primera aportación al RH, espero que os sirva de ayuda.

El caso, que llevo tiempo buscando la forma de añadir Pokémon errantes al Esmeralda (en español, es la ROM que utilizo). He buscado en este foro y en foro de PokemonCommunity, y no he conseguido encontrar nada. Así que empecé a investigar la forma en que aparecían Latios y Latias en el juego. A continuación dejo los pasos que he seguido durante mi investigación, por si a alguien le interesa o le pueda servir de ayuda. Si sólo quieres saber cómo se meten pokémon errantes, sáltate este paso.

En mi búsqueda, encontré la dirección del script de cuando te pasas la liga y tu madre te pregunta de qué color era el pokémon de la tele, si rojo o azul. Concretamente, el script es éste:

Código:
#org 0x29793E
lockall
checkgender
compare LASTRESULT 0x0
if 0x1 call 0x8297AC2
compare LASTRESULT 0x1
if 0x1 call 0x8297AD2
compare 0x8008 0x0
if 0x1 call 0x8297B54
compare 0x8008 0x1
if 0x1 call 0x8297B5F
applymovement 0x8009 0x82763A2
waitmovement 0x0
sound 0x15
applymovement 0x8009 0x827639C
waitmovement 0x0
applymovement 0x8009 0x827639E
waitmovement 0x0
pause 0x14
compare 0x8008 0x0
if 0x1 call 0x8297AE2
compare 0x8008 0x1
if 0x1 call 0x8297AED
msgbox 0x81F87BF MSG_KEEPOPEN '"PAPÁ: ¿Eh?\p¡Pero si es mi [player..."
giveitem 0x109 0x1 MSG_OBTAIN
msgbox 0x81F8896 MSG_KEEPOPEN '"PAPÁ: ¿Un TICKET para el ferry?\pS..."
closeonkeypress
pause 0x14
compare 0x8008 0x0
if 0x1 call 0x8297AF8
compare 0x8008 0x1
if 0x1 call 0x8297B0D
msgbox 0x81F88FF MSG_KEEPOPEN '"Mejor vuelvo al GIMNASIO de PETALI..."
closeonkeypress
compare 0x8008 0x0
if 0x1 call 0x8297B22
compare 0x8008 0x1
if 0x1 call 0x8297B3B
sound 0x8
hidesprite 0x8009
setflag 0x123
pause 0x1E
compare 0x8008 0x0
if 0x1 call 0x8297B94
compare 0x8008 0x1
if 0x1 call 0x8297BA9
pause 0x14
msgbox 0x81F8965 MSG_KEEPOPEN '"MAMÁ: Este padre tuyo[.]\pCuando p..."
closeonkeypress
setflag 0x8BD
special 0x1F6
pause 0x3C
compare 0x8008 0x0
if 0x1 call 0x8297BBE
compare 0x8008 0x1
if 0x1 call 0x8297BC9
msgbox 0x81F8A08 MSG_KEEPOPEN '"MAMÁ: ¿Un especial informativo?"
closeonkeypress
compare 0x8008 0x0
if 0x1 call 0x8297B6A
compare 0x8008 0x1
if 0x1 call 0x8297B7F
msgbox 0x81F8A28 MSG_KEEPOPEN '"¡Interrumpimos la programación par..."
closeonkeypress
clearflag 0x8BD
setflag 0xFF
special 0x41
compare 0x8008 0x0
if 0x1 call 0x8297BD4
compare 0x8008 0x1
if 0x1 call 0x8297BE9
msgbox 0x81F8B40 MSG_KEEPOPEN '"MAMÁ: [player], ¿has oído eso?\p¿D..."
multichoice 0x16 0x8 0x6C 0x1
copyvar 0x8004 LASTRESULT
special 0x12B
copyvar 0x40D5 LASTRESULT
msgbox 0x81F8B93 MSG_KEEPOPEN '"MAMÁ: ¡Ver para creer!\n¡Aún hay P..."
closeonkeypress
setvar 0x4082 0x4
setvar 0x408C 0x4
releaseall
end

'---------------
#org 0x297AC2
setvar 0x8008 0x0
setvar 0x8009 0x5
setvar 0x800A 0x1
return

'---------------
#org 0x297AD2
setvar 0x8008 0x1
setvar 0x8009 0x5
setvar 0x800A 0x1
return

'---------------
#org 0x297B54
applymovement MOVE_PLAYER 0x8297C12
waitmovement 0x0
return

'---------------
#org 0x297B5F
applymovement MOVE_PLAYER 0x8297C1D
waitmovement 0x0
return

'---------------
#org 0x297AE2
applymovement 0x8009 0x8297BFE
waitmovement 0x0
return

'---------------
#org 0x297AED
applymovement 0x8009 0x8297C01
waitmovement 0x0
return

'---------------
#org 0x297AF8
applymovement 0x800A 0x82977D5
waitmovement 0x0
applymovement 0x8009 0x8297C04
waitmovement 0x0
return

'---------------
#org 0x297B0D
applymovement 0x800A 0x82977DD
waitmovement 0x0
applymovement 0x8009 0x8297C06
waitmovement 0x0
return

'---------------
#org 0x297B22
applymovement MOVE_PLAYER 0x8297C18
applymovement 0x800A 0x8297C18
applymovement 0x8009 0x8297C08
waitmovement 0x0
return

'---------------
#org 0x297B3B
applymovement MOVE_PLAYER 0x8297C18
applymovement 0x800A 0x8297C18
applymovement 0x8009 0x8297C0D
waitmovement 0x0
return

'---------------
#org 0x297B94
applymovement 0x800A 0x82977E5
waitmovement 0x0
applymovement MOVE_PLAYER 0x82763A8
waitmovement 0x0
return

'---------------
#org 0x297BA9
applymovement 0x800A 0x82977E7
waitmovement 0x0
applymovement MOVE_PLAYER 0x82763AC
waitmovement 0x0
return

'---------------
#org 0x297BBE
applymovement 0x800A 0x82977E9
waitmovement 0x0
return

'---------------
#org 0x297BC9
applymovement 0x800A 0x82977F2
waitmovement 0x0
return

'---------------
#org 0x297B6A
applymovement MOVE_PLAYER 0x8297C23
waitmovement 0x0
applymovement 0x800A 0x82763A8
waitmovement 0x0
return

'---------------
#org 0x297B7F
applymovement MOVE_PLAYER 0x8297C2A
waitmovement 0x0
applymovement 0x800A 0x82763AC
waitmovement 0x0
return

'---------------
#org 0x297BD4
applymovement 0x800A 0x82977FB
waitmovement 0x0
applymovement MOVE_PLAYER 0x82763AC
waitmovement 0x0
return

'---------------
#org 0x297BE9
applymovement 0x800A 0x82977FF
waitmovement 0x0
applymovement MOVE_PLAYER 0x82763A8
waitmovement 0x0
return


'---------
' Strings
'---------
#org 0x1F87BF
= PAPÁ: ¿Eh?\p¡Pero si es mi [player]!\pHace un siglo que no te veo[.]\n¡Si pareces mucho más fuerte!\pÉsa es la impresión que das, ¡pero\ntu padre aún puede dar guerra!\pAh, sí, tengo algo para ti.\nTe lo envía un tal SR. ARENQUE.

#org 0x1F8896
= PAPÁ: ¿Un TICKET para el ferry?\pSi recuerdo bien, los puertos donde\natraca son CIUDAD PORTUAL y CALAGUA.

#org 0x1F88FF
= Mejor vuelvo al GIMNASIO de PETALIA.\pCariño, gracias por ocuparte\nde la casa mientras yo estoy fuera.

#org 0x1F8965
= MAMÁ: Este padre tuyo[.]\pCuando por fin viene un poco a casa,\nsólo se le ocurre hablar de POKéMON.\pDebería relajarse un poco y quedarse\nmás tiempo aquí tranquilito[.]

#org 0x1F8A08
= MAMÁ: ¿Un especial informativo?

#org 0x1F8A28
= ¡Interrumpimos la programación para\ntraerles las últimas noticias!\pHay noticias confusas sobre supuestos\navistamientos de un POKéMON azzzrt[.]\lvolando en distintos puntos de HOENN.\pActualmente se desconoce la identidad\ndel POKéMON.\pY ahora les dejamos con la programación\nhabitual.

#org 0x1F8B40
= MAMÁ: [player], ¿has oído eso?\p¿De qué color ha dicho el de\nla tele que era ese POKéMON?

#org 0x1F8B93
= MAMÁ: ¡Ver para creer!\n¡Aún hay POKéMON desconocidos!


'-----------
' Movements
'-----------
#org 0x2763A2
#raw 0x3E 'Face Player
#raw 0xFE 'End of Movements

#org 0x27639C
#raw 0x56 'Exclamation Mark (!)
#raw 0xFE 'End of Movements

#org 0x27639E
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0xFE 'End of Movements

#org 0x297C12
#raw 0x14 'Delay5
#raw 0x8 'Step Down (Normal)
#raw 0x8 'Step Down (Normal)
#raw 0x8 'Step Down (Normal)
#raw 0x27 'Step on the Spot Left (Fastest)
#raw 0xFE 'End of Movements

#org 0x297C1D
#raw 0x14 'Delay5
#raw 0x8 'Step Down (Normal)
#raw 0x8 'Step Down (Normal)
#raw 0x8 'Step Down (Normal)
#raw 0x28 'Step on the Spot Right (Fastest)
#raw 0xFE 'End of Movements

#org 0x297BFE
#raw 0xB 'Step Right (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0xFE 'End of Movements

#org 0x297C01
#raw 0xA 'Step Left (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0xFE 'End of Movements

#org 0x2977D5
#raw 0x9 'Step Up (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0x8 'Step Down (Normal)
#raw 0x28 'Step on the Spot Right (Fastest)
#raw 0xFE 'End of Movements

#org 0x297C04
#raw 0x2 'Face Left
#raw 0xFE 'End of Movements

#org 0x2977DD
#raw 0x9 'Step Up (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0x8 'Step Down (Normal)
#raw 0x27 'Step on the Spot Left (Fastest)
#raw 0xFE 'End of Movements

#org 0x297C06
#raw 0x3 'Face Right
#raw 0xFE 'End of Movements

#org 0x297C18
#raw 0x13 'Delay4
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0x25 'Step on the Spot Down (Fastest)
#raw 0xFE 'End of Movements

#org 0x297C08
#raw 0x8 'Step Down (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0x8 'Step Down (Normal)
#raw 0x13 'Delay4
#raw 0xFE 'End of Movements

#org 0x297C0D
#raw 0x8 'Step Down (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0x8 'Step Down (Normal)
#raw 0x13 'Delay4
#raw 0xFE 'End of Movements

#org 0x2977E5
#raw 0xB 'Step Right (Normal)
#raw 0xFE 'End of Movements

#org 0x2763A8
#raw 0x27 'Step on the Spot Left (Fastest)
#raw 0xFE 'End of Movements

#org 0x2977E7
#raw 0xA 'Step Left (Normal)
#raw 0xFE 'End of Movements

#org 0x2763AC
#raw 0x28 'Step on the Spot Right (Fastest)
#raw 0xFE 'End of Movements

#org 0x2977E9
#raw 0x27 'Step on the Spot Left (Fastest)
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0x28 'Step on the Spot Right (Fastest)
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0xFE 'End of Movements

#org 0x2977F2
#raw 0x28 'Step on the Spot Right (Fastest)
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0x27 'Step on the Spot Left (Fastest)
#raw 0x14 'Delay5
#raw 0x14 'Delay5
#raw 0xFE 'End of Movements

#org 0x297C23
#raw 0x9 'Step Up (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0x26 'Step on the Spot Up (Fastest)
#raw 0xFE 'End of Movements

#org 0x297C2A
#raw 0x9 'Step Up (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0x26 'Step on the Spot Up (Fastest)
#raw 0xFE 'End of Movements

#org 0x2977FB
#raw 0x9 'Step Up (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0xA 'Step Left (Normal)
#raw 0xFE 'End of Movements

#org 0x2977FF
#raw 0x9 'Step Up (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0xB 'Step Right (Normal)
#raw 0xFE 'End of Movements

A nosotros nos interesa esta parte:

Código:
multichoice 0x16 0x8 0x6C 0x1
copyvar 0x8004 LASTRESULT
special 0x12B
copyvar 0x40D5 LASTRESULT
El special 0x12B tiene como variable de entrada la 0x8004. Lo que hace el special es lo siguiente: si 0x8004 es igual a 0, el pokémon errante que aparece es Latias; si es igual a 1, aparece Latios (por lo que he probado, cualquier valor distinto de 0 hace que aparezca Latios). La variable 0x40D5 no nos interesa, lo que hace es guardar el valor que hemos escogido para más tarde, en la isla del sur, que aparezca el pokémon que no hayamos elegido.

El special 0x12B nos lleva a la dirección 0x8161961 y ejecuta el código en ASM que se encuentra allí. Pensé que la información del pokémon que nos aparece se guardaba en alguna parte de ese código, pero he estado buscando y no he encontrado nada (aunque tampoco sé como funciona el código). El código en cuestión es éste:


Como no encontré nada buscando en el interior de la ROM, pasé a buscar en la memoria RAM. Para eso, hay que usar el buscador de cheats del emulador VBA (Ctrl + C). El valor de Latias en hexadecimal es 0x197, así que mi idea fue ejecutar el siguiente script:

Código:
#org @inicio
setvar 0x8004 0x0
special 0x12B
end
Que hace que aparezca Latias. Después de activar el special, busqué en el buscador de cheats el valor 0197, y me apareció la siguiente dirección:


Si abrimos el Tools > Memory Viewer, y nos vamos a esa dirección…


Parece ser que esos números tienen que ver con el pokémon errante que nos aparece. Algunos se pueden deducir a primera vista, otros he tenido que investigarlos un poco:

Azul: número del pokémon errante invertido (Latias: 197, que invertido es 97 01)
Verde: vitalidad actual. Cuando hieres a un pokémon errante y se escapa, la próxima vez que te lo encuentras sigue con la misma vida. Pues parece ser que es aquí donde se guarda ese valor (en HEX, por supuesto).
Amarillo: nivel del pokémon, 28 en hex es 40 en decimal.
Marrón: el estado del pokémon, que también se guarda de un combate a otro.
Naranja: disponibilidad del pokémon (1 = vivo y salvaje, 0 = capturado o debilitado)
Rojo: información encriptada que definen los valores iniciales, la naturaleza y posiblemente el género.

Visto esto, mi primera idea fue bien simple, sustituir el número 0197 por el valor del nuevo pokémon. Después de investigar un poco acerca de las flags y las variables noté que la memoria donde se aloja la información del pokémon errante coincide con la memoria usada para las variables, es decir, que los pokémon errantes se guardan en variables. Las variables son:

- Variable del pokémon: Esmeralda 0x4F24; RF 0x506C
- Variable de la vitalidad: Esmeralda 0x4F25; RF 0x506D
- Variable del nivel y estado: Esmeralda 0x4F26; RF 0x506E
- Variable de la disponibilidad (0x100 = disponible, 0x0 = no disponible) = Esmeralda 0x5F29; FR 0x5071

Así que en teoría podríamos elegir al pokémon errante sólo editando las variables de antes con "setvar". En mi caso empecé probando con un Raikou, cuyo valor es 00F3. Ejecutando el script:

Código:
#org @inicio
special 0x12B
setvar 0x4F24 0xF3
end

Debería de aparecernos un Raikou errante.


Efectivamente, nuestro script ha sustituido el 0197 por nuestro 00F3 que le habíamos dicho. Entonces… ¿Debería de aparecernos un Raikou errante? Vamos a consultar en la pokédex…

(Nota: para facilitar el proceso, antes programé un "wildbattle" contra un Raikou para que me saliera en la pokédex, y que después me diera una masterball):


Efectivamente aparece el área de Raikou en la pokédex, y además va cambiando cada vez que nos movemos. Pero y si lo buscamos, ¿que nos encontramos?






¡Toma, a la primera! ¡Nos ha salido un Raikou perfecto!
Ahora se pueden sustituir los valores del pokémon que nos encontramos por los que nosotros queramos usando sólo "setvar". Ésa es la sección que viene a continuación.

Bueno, el Raikou no es del todo perfecto... ¿Habéis notado ese trocito de vida que le falta? Eso es porque sólo he cambiado el pokémon que aparece, pero no la vida (¿os acordáis del 0076 que estaba marcado en verde? no es casualidad que 76 en HEX sea 118 en decimal). Por tanto, el pokémon tiene la misma vida que cuando era un Latias, y como Raikou tiene más vida máxima que Latias... ¿Entendéis?

De momento no he encontrado una solución permanente para esto. He provado a ponerle una vida mayor que la máxima, pero lo que pasa es que si hieres al pokémon, durante un tiempo parecerá que no le restas vida... Lo único que se me ocurre es que si quieres poner X pokemon al nivel Y, busques en una calculadora de estadísticas la vida que debería de tener a ese nivel con valores iniciales al máximo, para asegurarte de que no te quedas corto, y así tampoco te pasas mucho de la vida máxima.



Script del Pokémon Errante


Hacer que aparezca un pokémon errante es tan simple como ejecutar un script. En Esmeralda el special 0x12B hace que aparezca un pokémon errante u otro dependiendo del valor que hay en la variable 0x8004: si es 0, aparece Latias, y si es 1 aparece Latios. En FR se usa el special 0x129 y la variable de entrada que utiliza es la 0x4031, que es donde se guarda el pokémon inicial que escogiste, y hace que aparezca Raikou, Entei o Suicune. Lo que vamos a hacer es llamar al special, hacer que aparezca uno de éstos pokemon como errante y sustituirlo por el pokemon que queramos.

Los datos del pokémon errante se guardan en variables, así que conociendo estas variables podemos editar al pokémon errante como queramos. Concretamente, las variables son éstas:


- Variable del pokémon: Esmeralda 0x4F24; RF 0x506C
- Variable de la vitalidad: Esmeralda 0x4F25; RF 0x506D
- Variable del nivel y estado: Esmeralda 0x4F26; RF 0x506E
- Variable de la disponibilidad (0x100 = disponible, 0x0 = no disponible) = Esmeralda 0x5F29; FR 0x5071


Ahora explicaré qué significa cada variable y los pasos a seguir en Esmeralda, para Fire Red los pasos a seguir son idénticos. El script del pokémon es el siguiente:

Código:
#org inicio
special 0x12B
setvar 0x4F24 0x'(nº del pokémon que quieras que sea errante)
setvar 0x4F25 0x'(vitalidad del pokémon)
setvar 0x4F26 0xXXYY'(YY es el nivel y XX es el estado)
end

Código:
#org inicio
special 0x129
setvar 0x506C 0x'(nº del pokémon que quieras que sea errante)
setvar 0x506D 0x'(vitalidad del pokémon)
setvar 0x506E 0xXXYY'(YY es el nivel y XX es el estado)
end

Voy a explicar para qué sirve cada variable:

La primera indica el pokémon que nos aparecerá por la región. Por poner un ejemplo, yo quiero que me aparezca Raikou, cuyo número es F3, pues en mi caso pondré setvar 0x4F24 0xF3.

La segunda determina la vida con la que nos encontramos al pokémon. Esto es muy importante, porque un valor muy alto provocaría que, al herir al pokémon, durante un tiempo su vida no decrezca (dependiendo de lo mucho que te hayas pasado de su vida máxima), y con un valor bajo te encontraías al pokémon con escasa vida. Para elegir un valor adecuado, podéis usar la siguiente calculadora Pokéxperto; Calculadora DS/Advance de IV's & Stats

Eliges el pokémon, su nivel, y a la derecha donde dice Resultados, en PS escribes 31, y pulsa "calcular stats"


A mí me ha salido a la izquierda, en PS, 165. Pues paso este valor a hexadecimal (165 = A5 en HEX) y ya está. Lo que tengo que poner es setvar 0x4F25 0xA5.

La tercera variable es complicada. En una misma variable se guarda el nivel y el estado (envenenamiento, parálisis...). El nivel es simple: escoge un nivel de 1 a 100 y lo pasas a hexadecimal. En mi caso quiero que salga al 50, que en HEX es 32, luego YY = 32. El estado es algo difícil; si no te interesa modificar el estado, ignora el siguiente spoiler y haz XX = 00.

El XX es lo más difícil, establece el estado del pokémon. El estado se determina con la siguiente tabla, sacada de Pokémon data structure in Generation III - Bulbapedia, the community-driven Pokémon encyclopedia


Para poner un estado, escribe ocho ceros:

00000000

Esto es un número binario de ocho bits, donde cada uno puede tomar un valor entre 0 y 1. La tabla indica, para un número de 8 bits, qué estado aplica cada bit, leído de derecha a izquierda. Por ejemplo, este número

00001000

Tiene el cuarto bit igual a 1, y el resto 0. Según la tabla, el cuarto bit es envenenamiento, así que nuestro pokémon con este código estará envenenado (Notad que la tabla dice 3 para Poison, no 4, pero hay que tener en cuenta que empieza a contar desde 0, no desde 1).

Si por ejemplo, aplicamos este código

00010000

El quinto bit indica quemado, es decir, nos encontraremos al pokémon quemado. También podemos mezclar algunos estados, por ejemplo:

01100000

Hará que el pokémon esté congelado, y cuando se descongele estará paralizado.

El sueño ocupa 3 bits. Esto es porque además determina los turnos que quedan para que el pokémon se despierte. Por ejemplo, 001 en binario es 1, así que el próximo turno se despertará; 101 en binario es 5, así que dormirá durante 5 turnos, etc...

Vale, muy bonito esto de los bits, pero… ¿cómo se aplica?

Simple. Una vez que tengas tu código de 8 cifras en binario, lo pasas de binario a hexadecimal en la calculadora. Yo quiero que mi Raikou esté congelado. El código para congelamiento es 00100000, que en hexadecimal es 20. Por tanto, XX = 20.

Entiendo que este procedimiento es bastante confuso. Si no te ha quedado claro y tienes alguna duda, deja tu pregunta en los comentarios ;)

Nota: Si lo que tienes pensado es dormir o congelar al pokémon para que no se escape... Olvídate, porque se va a escapar igualmente. Y si no, que le pregunten a este pobre hombre ... (min 8:00) Pokémon FireRed - Episode 37 - Suicune - YouTube

La variable 0x4F29 indica si el pokémon está disponible (0x100 salvaje y vivo) o no (0x0 debilitado o capturado). Cuando llamas al "special" este valor es automáticamente 0x100, así que en principio no hace falta tocarlo. Lo que sí puede servir es para saber si ya hemos capturado o debilitado al pokémon (para interactuar con la historia de nuestro hack o cosas así).

A modo de ejemplo, mi script queda de la siguiente forma:

Código:
#org inicio
special 0x12B
setvar 0x4F24 0xF3
setvar 0x4F25 0xA5
setvar 0x4F26 0x2032 'o si no quieres poner ningún estado, simplemente 0x32
end
Ejecutamos el script y...

...

Vaya, parece que no ha pasado nada. Sin embargo, yo me he adelantado y antes programé un wildbattle contra Raikou para que me apareciera en la Pokédex. El resultado es el siguiente...


o_O


o_O o_O o_O o_O o_O

¡¡Funciona!!

Bueno, si y no. Todavía queda investigar las zonas donde aparece, y poder hacer que aparezca más de un pokémon errante a la vez. Pero... yo diría que es un buen comienzo, ¿no te parece? :)

Aquí dejo algunos ejemplos más, donde se ve que tampoco hace falta poner siempre la vida máxima al pokémon:







Editando la localización


Para esta parte recomiendo que tengáis experiencia manejando editores hexadecimales. Cuando ejecutes el script de antes, el pokémon errante aparecerá por unos mapas específicos que están predefinidos en la ROM. Concretamente hay una tabla que indica las rutas por donde se mueve el poke:

Código:
Offset 5D1A04:

19 1A 20 21 31 FF
1A 19 20 21 FF FF
20 1A 19 21 FF FF
21 20 19 1A 22 26
22 21 23 FF FF FF
23 22 24 FF FF FF
24 23 25 26 FF FF
25 24 26 FF FF FF
26 25 21 FF FF FF
27 24 28 29 FF FF
28 27 2A FF FF FF
29 27 2A FF FF FF
2A 28 29 2B FF FF
2B 2A 2C FF FF FF
2C 2B 2D FF FF FF
2D 2C 2E FF FF FF
2E 2D 2F FF FF FF
2F 2E 30 FF FF FF
30 2F 31 FF FF FF
31 30 19 FF FF FF

Código:
Offset 466C58:

13 14 27 29 FF FF FF
14 13 15 29 FF FF FF
15 14 16 FF FF FF FF
16 15 17 1B 2B FF FF
17 16 18 19 1A 1B 2B
18 17 19 1A 1D FF FF
19 17 18 1A 22 FF FF
1A 17 18 19 1C 1E FF
1B 16 17 1C 2B FF FF
1C 1A 1B 1E FF FF FF
1D 18 1E FF FF FF FF
1E 1C 1D 1F FF FF FF
1F 1E 20 FF FF FF FF
20 1F 21 FF FF FF FF
21 20 24 25 FF FF FF
22 19 23 FF FF FF FF
23 22 24 FF FF FF FF
24 21 23 25 FF FF FF
25 21 24 26 FF FF FF
26 25 27 FF FF FF FF
27 13 26 FF FF FF FF
29 13 14 2A FF FF FF
2A 29 14 FF FF FF FF
2B 16 17 1B FF FF FF
2C 2B 1B FF FF FF FF

Cada fila de la tabla tiene la siguiente información:

  • [*]Primer byte: nº de mapa en hex donde se encuentra el pokémon.​
    [*]Resto de bytes: nº de mapa en hex donde estará el pokémon cuando cambiemos de mapa.​
    [*]FF: todos los bytes que sean FF son ignorados.​

Además, nos encontramos con tres limitaciones:

  • El nº de filas de la tabla indica el nº máximo de posibles localizaciones del pokémon. Por ejemplo, en esmeralda la tabla tiene 20 filas, así que el poke no podrá aparecer en más de 20 rutas. Ésta limitación se puede saltar.
  • El ancho de la tabla - 1 indica el nº máximo de rutas a las que puede estar conectada una ruta. En esmeralda cada fila tiene 6 bytes, pues como máximo una ruta podrá estar conectada a 6 - 1 = 5 posibles rutas. Ésta limitación no se puede saltar.
  • Cada fila tiene como mínimo 3 bytes distintos de FF. Es decir, cada ruta está conectada como mínimo con otras 2. Esto tiene una explicación curiosa, resulta que la rutina que calcula el área del pokemon errante está programada para que el poke no pueda aparecer donde tú estuviste hace 2 localizaciones. De esta forma se evita eso de alternar constantemente entre dos rutas hasta que aparezca el poke. Si un pokémon solo puede ir de una ruta a otra, y tu estuviste en esa ruta hace 2 mapas, el juego se queda pillado. Ésta limitación se puede saltar, pero requiere conocimientos de ASM y no lo recomiendo.

Ya estamos en condiciones de editar la localización. Para editar esta tabla hará falta un editor hexadecimal, yo utilizo HxD. Primero debes tener una idea de las zonas donde se moverá el poke. Yo haré que el poke se mueva por este mapa (cortesía de Dani_SR_17):

-Pueblo Paleta - Ruta 1 - Ciudad Verde - Ruta 2
____ __ _ _ __- Ruta 3 -


Abre Advance Map y apunta el nº de cada mapa, y conviértelos a hexadecimal con la calculadora de windows:

Pueblo Paleta: 0 --> 0
Ciudad verde: 1 --> 1
Ruta 1: 19 --> 13
Ruta 2: 20 --> 14
Ruta 3: 21 --> 15

Ahora tenemos que hacer la tabla. Tenemos 5 localizaciones, así que la tabla tendrá 5 filas. No os preocupéis por el número de filas, podéis poner hasta 256 (LOL). Cada fila empieza con una localización, y los números siguientes son las localizaciones a las que se puede mover el poke. Mi tabla queda así:

00 13
01 13 14
13 00 01 15
14 01
15 13

Pero esta tabla puede hacer que el juego se trabe, porque hay filas con sólo 2 bytes y el mínimo es 3. En efecto, pueblo paleta y las rutas 2 y 3 sólo tienen una conexión, y el mínimo son 2 conexiones. Así que conectaré la ruta 2 con pueblo paleta y la ruta 3 con ciudad verde:

00 13 14
01 13 14
13 00 01 15
14 01 00
15 13 01

Rellena de FF hasta que cada fila tenga 7 bytes en FR, o hasta 6 bytes en esmeralda:

00 13 14 FF FF FF FF
01 13 14 FF FF FF FF
13 00 01 15 FF FF FF
14 01 00 FF FF FF FF
15 13 01 FF FF FF FF

Ya tenemos nuestra tabla lista. Ahora abre la ROM con tu editor hexadecimal y ve al offset donde se encuentra la tabla. Si tu tabla es más corta que la tabla original (como es mi caso), simplemente pégala sobreescribiendo la tabla original, y rellena de FF hasta borrar por completo la tabla anterior.

Si es más grande tendrás que buscar un espacio libre en la ROM terminado en 0, 4, 8, o C. El offset A00003 está vacío, pero no es válido porque termina en 3, pero el offset A00000 sí que nos sirve. Imaginemos que vas a pegar tu tabla en A00000. Ahora tendrás que hacer un repoint. Si usas HxD, ve a Buscar -> Reemplazar... Busca los pointers 58 6C 46 08 en FR, o 04 1A 5D 08 en esmeralda, y en reemplazar escribe el offset donde hayas puesto tu tabla, pero invertido: A00000 -> 00 00 A0 08. Tipo de datos: valores hexadecimales, Dirección Todo, y cuando esté todo listo Reemplazar todo.

El último paso es decirle a la rutina la nueva longitud de la tabla. ¿Habéis visto que la tabla de FR mide 25 filas? 25 en hex es 19. Hay 3 bytes que indican el nº de filas de la tabla, aquí se indica la dirección donde se encuentran:

En 161928: 14
En 1619c6: 14
En 161a82: 13

En 141d6e: 19
En 141df6: 19
En 141eae: 18

La nueva longitud de la tabla es 5 filas, que en hex es 5 :D Así que cambiamos esos tres bytes por sus nuevos valores:

En 141d6e: 05
En 141df6: 05
En 141eae: 04

Y listo, ya hemos definido los mapas por donde se mueve el pokemon errante.

Hay que tener en cuenta que todos los números de mapa están referidos al banco 0 en esmeralda y al banco 3 en FR. Es decir, que nuestro poke sólo se podrá mover por los mapas del banco 0 en esmeralda y el banco 3 en FR. Si por algún motivo quieres que aparezca en un mapa fuera de ese banco (una cueva, una casa, la zona safari...) puedes ejecutar el siguiente script a la entrada del mapa:

Código:
#org @inicio
writebytetooffset 0x(banco del mapa) 0x203BC86
writebytetooffset 0x(nº de mapa) 0x203BC87
end

Código:
#org @inicio
writebytetooffset 0x(banco del mapa) 0x203F3AE
writebytetooffset 0x(nº de mapa) 0x203F3AF
end

Pero al cambiar de mapa el pokémon volverá a rondar por las rutas de la tabla.

Varios Pokémon Errantes​


Con lo que se ha explicado hasta ahora sería bastante para hacer que aparezca el pokémon errante que quieras en el estado que quieras y donde quieras. Pero parece que hay una pequeña limitación... y es que el juego no está pensado para que aparezca más de un pokémon errante a la vez. Así que en principio hacer que aparezca más de un pokémon errante a la vez no es posible. Pero bueno, tampoco hace falta llevarse las manos a la cabeza. Lo que sí podemos hacer es elegir el pokémon que aparece en cualquier momento, con sólo ejecutar un script.

Pondré un ejemplo: imagina que quieres que aparezcan un Lugia y un Ho-ho errantes por tu región, y que puedas elegir en cualquier momento cuál de los dos aparece. Primero tendrás que asignarle una flag a cada pokémon para establecer si ya se ha capturado o debilitado, en mi ejemplo la de Ho-ho es la 0x1100 y la de Lugia la 0x1101. Ahora puedes hacer que hayan dos personajes (o carteles, o lo que sea), de tal forma que el primero haga aparecer a Lugia y el segundo a Ho-ho. El script para el primero sería algo así:

Código:
#org @inicio
lock
faceplayer
compare 0x4F24 0xFA              'Comprueba si el errante actual es Ho-ho
if 0x1 goto Cambiarhohoporlugia 'Si lo es salta a esa línea
compare 0x4F29 0x0     'Si el errante no es Ho-ho, entonces es Lugia. Esto comprueba si Lugia está disponible
if 0x1 goto @capturado 'Si no está disponible, el hombre dice que está capturado
msgbox @a 0x6          'Si está disponible, el hombre dice que está suelto
release
end

#org Cambiarhohoporlugia
checkflag 0x1101     'En esta flag está guardada la disponibilidad de Lugia
if 0x1 goto @capturado 'Si es 1 ya lo hemos capturado (o debilitado :P)
special 0x12B
setvar 0x4F24 0xF9 'Lugia
setvar 0x4F25 0xD7 'con 215 de vitalidad
setvar 0x4F26 0x3C 'al nivel 60
msgbox @a 0x6      'El jipi nos dice que está disponible
release
end

#org @capturado
setflag 0x1101
msgbox @b 0x6
release
end

#org @a
= Ahora mismo hay un LUGIA salvaje\nrondando por HOENN.

#org @b
= Parece que alguien ha capturado al\nLUGIA que merodeaba por HOENN.

El script para el segundo sería parecido. Este script es simple y te permite tener dos pokémon errantes, de tal forma que el jugador elige cuál de los dos quiere capturar en cualquier momento. Desafortunadamente no guarda los datos de vitalidad y estado, así que cuando se cambie a Lugia por Ho-ho o viceversa volverán a tener la vida máxima y ningún problema de estado (es decir, se "curarán"). Esto tampoco es un gran problema, si quieres guardar la salud del pokémon tendrías que guardar su vitalidad y estado en dos variables con el comando "copyvar". Pero por ejemplo en mi hack ya hay 6 pokémon errantes diferentes, si quisiera que se guardaran el estado y vit. de cada pokémon me harían falta 12 variables, y los script serían eternos. Así que no guardar el estado el errante es mucho más fácil de hacer y además tampoco supone un gran problema.

Si quieres que tus pokemon errantes aparezcan por rutas distintas, te recomiendo que uses el script que se explica al final de esta página. Así, puedes hacer que cada pokémon aparezca por rutas distintas.

¿Te ha parecido complicado? ¿No lo has entendido? ¿Se te ha ocurrido una idea pero no sabes cómo llevarla a cabo? Pues no te lo pienses y déjame un comentario, que estaré encantado de ayudarte :)




FIN​
El humano (?)

Para terminar, me gustaría aclarar que para los que uséis FR (que sereis la mayoría) hay un pequeño cabo suelto en mi investigación. Resulta que si buscáis en la pokédex el área del pokémon errante no aparecerá. Sin embargo sí que os saldrá el área de uno de los tres perros legendarios. De momento no he podido cambiar ese pequeño gran detalle, y me temo que no puedo asegurar que consiga arreglarlo... Si sois capaces de aceptar este defecto entonces no tendréis ningún problema. Aquí unas imágenes, donde se ve que aunque el área que aparece en la pokédex es la de Raikou, si lo buscamos nos encontramos al pokémon que hemos definido con la rutina:






Y creo que nada mas... Espero haberte ayudado a hacer lo que querías en tu hack. Pero si no has conseguido lo que querías ya sabes, ¡¡coméntamelo!! Lo único que te pido a cambio es que si has seguido este tutorial me menciones en los créditos de tu hack (que aunque antes ya era chulo, ahora que has metido esto seguro que te ha quedado mejor :D)


Gracias a todos los que os habéis tragado este tocho ;) Y sobre todo a esta comunidad, que aunque éste sea mi primer mensaje he aprendido todo lo que sé de RH gracias a todos los tutoriales, las preguntas y las respuestas que hacéis continuamente.

Si os queda alguna duda, o veis algún fallo, mandadme un MP o comentadlo!!

Un saludo!!!
 

Corbitto

hackromer
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

wow, que buena investigación, esta demasiado completa la verdad es que sera muy util, aunque no se si también lo hicieras para firered, que es la base mas popular del momento.
 

Dr._Seuss

Average RomHacker
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

Veo que no eres tan novato en ASM, como sabras por aca casi nadie ocupa Esmeralda, y menos Español.

Para portearlo a Fire Red se me ocurre comparar la funcion del Special que activa a Latios con el de los perros legendarios de FR, en base a tu investigacion hallar las direcciones para Fire Red, vere si este finde puedo ponerme a trabajar en ello, pero gracias a ti por hacer la investigacion
 
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

Gracias por comentar,

Sí, entiendo que Fire Red es la más usada. El caso es que empecé un pequeñísimo proyecto en el esmeralda, y claro, poco a poco ha ido creciendo...

Supongo que una vez conocido el procedimiento, es relativamente fácil llevarlo a FR. Con cambiar un par de offsets y un poco la rutina de ASM, en principio debería de funcionar.
 

RedMort

He vuelto!
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

Mae mia, a esto le llamo yo mensaje de presentación, a ver si más gente sigue tu ejemplo xD.
Con respecto al aporte, yo tenía una idea en mi mente pero no tan pro xD
Gran investigación-tutorial, espero que sigas aportando, que te entretengas con nosotros y que alguien lo adapte a Ruby, o si no es muy dificil ya lo intentaré yo xD

Saludos, y bienvenido al foro! ^^
 
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

He estado trabajando en el tema, y he descubierto un par de cosas:

- En el offset 0203BC86 se guarda el banco del mapa donde se encuentra el pokémon, y en el offset 0203BC87 (el siguiente) se guarda el nº del mapa. Por poner un ejemplo, he ejecutado el siguiente script:

Código:
#org @inicio
writebytetooffset 0x1A 0x203BC86
writebytetooffset 0x3 0x203BC87
end
Aparecerá en el mapa 3 del banco 1A = 26 en decimal, esto es, el primer mapa de la zona safari. Ha funcionado y me ha aparecido, aunque ahora mismo no puedo subir imágenes :( El problema es que cuando salgas del mapa, volverá a rondar los mapas de siempre, pero de momento es un avance. Podría hacerse un script de "On entering map" que ejecute el script cada vez que entres en el mapa, de tal forma que el pokémon "siempre" estará ahí.


- ¿Os acordáis de la línea donde se encuentra la información del pokémon errante? Me refiero a esto de aquí:


¿Y os habéis fijado en ese pequeño "01" que hay debajo del 36? Pues bien, cuando vale 1 significa que el pokémon está disponible (vivo y salvaje), mientras que si vale 0 no nos lo podremos encontrar (debilitado o capturado).


- He intentado aplicar la rutina en firered. La variable de entrada, en vez de 0x8004, es la variable 0x4031, que tiene que ver con el pokémon inicial que elegiste. En cualquier caso, la rutina funciona, es decir, sustituye los valores del pokémon errante por los que nosotros queramos. Sin embargo, parece que el pokémon no cambia.
Pongo un ejemplo: estoy intentando cambiar a Entei (00F4) por Rayquaza (0196). La rutina consigue cambiar el 00F3 por el 0196, pero cuando miro la pokédex no me aparece el área de Rayquaza, pero sí la de Entei... Tampoco entiendo muy bien cómo funciona FR, así que si alguien más especializado que yo le interesa este tema, le agradecería que retomara la investigación.

Seguiré investigando, a ver si soy capaz de hacer más cositas :)
 

Dani_SR_17

¡Pokémon LionHeart!
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

Una investigación muy útil e impresionante, un trabajo magnífico, a ver si consigues entenderlo también en Fire Red.

Sobre lo que dijiste de los mapas, lo que se podría hacer es por ejemplo:
(No sé ASM, lo que te digo es con mis conocimientos de scripts normales)
Con scripts de nivel, al entrar en un determinado mapa comprobar en que mapa está el Pokémon (ya lo has predefinido antes en esa variable).
Y mediante un random, "seleccionar" uno de los mapas contiguos a dicho mapa. Y guardar en otra variable dicho mapa contiguo, al cambiar a otro mapa, usamos la variable del mapa contiguo y hacemos con lo que has explicado que el Pokémon en cuestión aparezca en dicho mapa contiguo, y así sucesivamente.

No sé si me he explicado bien, si no se entiende, lo puedo decir de otra forma ;)

PD: Bienvenido al foro.
 
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

Con scripts de nivel, al entrar en un determinado mapa comprobar en que mapa está el Pokémon (ya lo has predefinido antes en esa variable).
Y mediante un random, "seleccionar" uno de los mapas contiguos a dicho mapa. Y guardar en otra variable dicho mapa contiguo, al cambiar a otro mapa, usamos la variable del mapa contiguo y hacemos con lo que has explicado que el Pokémon en cuestión aparezca en dicho mapa contiguo, y así sucesivamente.
Se lo que quieres decir, a mí se me habia ocurrido algo parecido, con randoms y scripts de nivel. En principio es una buena idea y se podría hacer... Pero es muuuy tedioso hacer un script de nivel para cada mapa. Quiero saber si se puede hacer una rutina en ASM que se ejecute cada vez que cambias de mapa, y que haga eso mismo que tu dices (o algo parecido). Pienso que esta forma es mucho más eficiente, pero hasta entonces, con scripts de nivel nos las podemos apañar.
 

Dani_SR_17

¡Pokémon LionHeart!
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

Se lo que quieres decir, a mí se me habia ocurrido algo parecido, con randoms y scripts de nivel. En principio es una buena idea y se podría hacer... Pero es muuuy tedioso hacer un script de nivel para cada mapa. Quiero saber si se puede hacer una rutina en ASM que se ejecute cada vez que cambias de mapa, y que haga eso mismo que tu dices (o algo parecido). Pienso que esta forma es mucho más eficiente, pero hasta entonces, con scripts de nivel nos las podemos apañar.
Realmente sería el mismo script para todos los mapas, lo jodio sería que habría que recrear mediante comparaciones el mapa con todas las zonas del Hack.


Un ejemplo. Tenemos el siguiente mapa:

-Pueblo Paleta - Ruta 1 - Ciudad Verde - Ruta 2
____ __ _ _ __- Ruta 3 -


Imagínate que aparece en "Ruta 1".

Primero hay que asignar un valor a cada zona, ejemplo.
Pueblo Paleta = 0
Ruta 1 = 1
Ciudad verde = 2
Ruta 2 = 3
Ruta 3 = 4

Hacemos una comparación de una variable para reconocer en que mapa esta.

En este caso estaría en "1".
Como está en uno, puede ir a 3 zonas: Pueblo Paleta, Ruta 3 o Ciudad Verde.
Usamos un "random 0x3", imagínate que sale 2.
Pues ahora en las variables para el siguiente mapa ponemos los datos de "Ruta 3".

Bien, empezamos en Pueblo Paleta y ya ha ocurrido eso, ahora vamos a "Ruta 1"
Vuelve a ejecutar el mismo script, ahora copiamos las variables de los datos de la "Ruta 3", para que aparezca en dicha ruta. Esta vez la variable de "posición" vale 4, y el único mapa posible desde ahí es "Ruta 1", luego ya sin random ni nada, almacenamos en las variables para el siguiente mapa los datos de "Ruta 1"

Y así sucesivamente.

Además es un método bastante eficiente.

Solo se usan:
- Las 2 variables que determinan el banco y el mapa en el que está actualmente el Poké en cuestión.
- Las 2 variables que determinan el siguiente banco y mapa.
- La variable para crear el "mapa" virtual.

Es más, podríamos suprimir incluso 2 variables de las anteriores.
 
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

Visto así, es más fácil de lo que imaginaba. He hecho un script con tu ejemplo y no ha sido tan difícil:

Código:
#org @inicio			'Esto comprueba la posición "virtual" del  
copyvar 0x8004 0x5000		'pokemon, que se guarda en la variable 0x5000
comparevar 0x8004 0x0
if 0x1 call @pueblopaleta
comparevar 0x8004 0x1
if 0x1 call @ruta1
comparevar 0x8004 0x2
if 0x1 call @ciudadverde
comparevar 0x8004 0x3
if 0x1 call @ruta2
comparevar 0x8004 0x4
if 0x1 call @ruta3
copybite 0x20370B8 0x203BC86	'Aquí copia la información de la variable 0x8000
copybite 0x20370B9 0x203BC87	'al offset que determina la localización del pokemon
end

'Lo que viene a continuación calcula aleatoriamente la siguiente posición

#org @pueblopaleta
goto @2ruta1

#org @ruta1
random 0x3
compare LASTRESULT 0x0
if 0x1 goto @2pueblopaleta
compare LASTRESULT 0x1
if 0x1 goto @2ciudadverde
compare LASTRESULT 0x2
if 0x1 goto @2ruta3

#org @ciudadverde
random 0x2
compare LASTRESULT 0x0
if 0x1 goto @2ruta1
compare LASTRESULT 0x1
if 0x1 goto @2ruta2

#org @ruta2
goto @2ciudadverde

#org @ruta3
goto @2ruta1

'Una vez calculada la nueva posición, aquí se asigna la nueva posición a la
'variable 0x8000 y se guarda la nueva posición virtual en la variable 0x5000
'El 2 delante del nombre es para diferenciarlo de los de arriba

#org @2pueblopaleta
setvar 0x8000 0x0003
setvar 0x5000 0x0
return

#org @2ruta1
setvar 0x8000 0x1903
setvar 0x5000 0x1
return

#org @2ciudadverde
setvar 0x8000 0x0103
setvar 0x5000 0x2
return

#org @2ruta2
setvar 0x8000 0x2003
setvar 0x5000 0x3
return

#org @2ruta3
setvar 0x8000 0x2103
setvar 0x5000 0x4
return

Creo que era esto a lo que te referías, no? Una vez implantado el script en la ROM es tan fácil como hacer call 0xoffsetdelscript a la entrada de un nivel.

EDITO:

- He descubierto que los 8 números marcados en rojo tienen que ver con los valores iniciales (hp, atk, def, atk esp, def esp y vel) y la naturaleza (¿posiblemente también el género?). Pero la información está encriptada, así que no es tan fácil como cambiar los valores directamente. Para hacer que sea shiny habría que descifrar antes esta información y editar los valores. De momento no tengo interés (ni capacidad) de descifrarlo. Si alguien está dispuesto a retomar este punto le estaría agradecido.

- He cambiado todos los números que se me han ocurrido y no he conseguido que el pokémon lleve un objeto equipado, así que he llegado a la conclusión de que NO se puede equipar un objeto a un pokemon errante (estoy un 90% seguro de que no se puede, pero si alguien cree que me equivoco por favor que me lo diga).

- Se me ha ocurrido una idea para hacer que aparezcan varios pokémon errantes, en cuanto pueda intentaré llevarla a cabo. El problema es que no parece posible que aparezcan todos a la vez en la pokédex. Me explico: Si tienes un Latias y un Latios errantes a la vez, podrás ver el área de Latios, pero no la de Latias. Sin embargo, eso no quita que te puedas encontrar a Latias, sólo afectaría al área de la pokédex.

- Sé que estais esperando a que investigue el tema en FR. Ahora mismo estoy muy liado, pero en cuando pueda retomaré este punto.
 

Dani_SR_17

¡Pokémon LionHeart!
Respuesta: Pokémon Errantes (Roaming Pokemon) [Investigación Esmeralda]

Visto así, es más fácil de lo que imaginaba. He hecho un script con tu ejemplo y no ha sido tan difícil:

Código:
#org @inicio			'Esto comprueba la posición "virtual" del  
copyvar 0x8004 0x6000		'pokemon, que se guarda en la variable 0x6000
comparevar 0x8004 0x0
if 0x1 call @pueblopaleta
comparevar 0x8004 0x1
if 0x1 call @ruta1
comparevar 0x8004 0x2
if 0x1 call @ciudadverde
comparevar 0x8004 0x3
if 0x1 call @ruta2
comparevar 0x8004 0x4
if 0x1 call @ruta3
copybite 0x20370B8 0x203BC86	'Aquí copia la información de la variable 0x8000
copybite 0x20370B9 0x203BC87	'al offset que determina la localización del pokemon
end

'Lo que viene a continuación calcula aleatoriamente la siguiente posición

#org @pueblopaleta
goto @2ruta1

#org @ruta1
random 0x3
compare LASTRESULT 0x0
if 0x1 goto @2pueblopaleta
compare LASTRESULT 0x1
if 0x1 goto @2ciudadverde
compare LASTRESULT 0x2
if 0x1 goto @2ruta3

#org @ciudadverde
random 0x2
compare LASTRESULT 0x0
if 0x1 goto @2ruta1
compare LASTRESULT 0x1
if 0x1 goto @2ruta2

#org @ruta2
goto @2ciudadverde

#org @ruta3
goto @2ruta1

'Una vez calculada la nueva posición, aquí se asigna la nueva posición a la
'variable 0x8000 y se guarda la nueva posición virtual en la variable 0x6000
'El 2 delante del nombre es para diferenciarlo de los de arriba

#org @2pueblopaleta
setvar 0x8000 0x0003
setvar 0x6000 0x0
return

#org @2ruta1
setvar 0x8000 0x1903
setvar 0x6000 0x1
return

#org @2ciudadverde
setvar 0x8000 0x0103
setvar 0x6000 0x2
return

#org @2ruta2
setvar 0x8000 0x2003
setvar 0x6000 0x3
return

#org @2ruta3
setvar 0x8000 0x2103
setvar 0x6000 0x4
return

Creo que era esto a lo que te referías, no? Una vez implantado el script en la ROM es tan fácil como hacer call 0xoffsetdelscript a la entrada de un nivel.

Gracias por la explicación, pensaba que era más complicado. He tardado nada en hacerlo, y cuando le coges el truco acaba siendo bastante simple. Esto puede servir de mucha ayuda :D

A ver si entre todos conseguimos hacerlo funcionar en firered, que esto tiene mucho potencial!

Exacto, esa es la idea, y como ves es bastante sencillo :D
 

Dani_SR_17

¡Pokémon LionHeart!
Respuesta: Pokémon Errantes [Investigación Fire Red y Esmeralda FINALIZADA!!]

Me alegro de que una investigación tan útil esté completa, que pena que por ahora no me sirva para mi hack...., aunque quizás le de algún uso pero a pequeña escala, como que un Pokémon ronde por ciertas zonas.

Pues eso, enhorabuena por completarla y me alegro de poder haber ayudado :D
 

eing

Miembro de honor
Miembro de honor
Respuesta: Pokémon Errantes [Investigación Fire Red y Esmeralda FINALIZADA!!]

La investigación está muy bien,y la forma de hayar los datos me ha sorprendido.
Enhorabuena, de verdad.

Pero ahora viene la pregunta del millón .. ¿Cuantas veces habrás de poner ese script?
¿Una vez por cada pokémon errante? Y cuando tu pones la ruta, pones la ruta inicial, pero imagino que al hacer vuelo cambiará de ubicación, ¿no? En ese caso, ¿Para que asignarla si volverá a ser calculado?

Son duads que tengo, no te lo tomes a mal que me gustaría que me explicases, es que estoy perezoso..
 

Jack Johnson

qÀF qÀF qÀF qÀF qÀF qÀF
Respuesta: Pokémon Errantes [Investigación Fire Red y Esmeralda FINALIZADA!!]

Puedes solucionar el problema de la pokedex para varios errantes, si usas un objeto "detector de pokemon", que diga la zona según la variable.
 
Respuesta: Pokémon Errantes [Investigación Fire Red y Esmeralda FINALIZADA!!]

eing: Bueno, el script una vez que lo has hecho sólo lo tienes que poner una vez, y después tienes que guardarte el offset donde se ha puesto. Ahora es tan simple como pegar el offset en todos los mapas donde quieras que aparezca el pokémon, en nuestro ejemplo serían 5 mapas: pueblo paleta, ciudad verde, rutas 1 2 y 3. El script lo que hace es asignar la posición cada vez que entres en el mapa, independientemente de si entras andando normal y corriente, usando vuelo, por una puerta, saliendo de una cueva, o lo que sea.

Creo que a lo que te refieres es que si usas vuelo el pokémon aparecerá en otro mapa aleatorio fuera de las rutas 1 2 y 3, ¿no? Eso no importa, porque tenemos guardada la posición "virtual" en la variable 0x5000 que puede valer desde 0 (se encuentra en pueblo paleta) hasta 4 (se encuentra en la ruta 3). Cuando vuelvas a entrar digamos en la ruta 1 se ejecutará el script, que mira el valor de la variable 0x5000 para saber dónde está el pokémon dentro de nuestro "mapa virtual". A continuación elige uno de los mapas vecinos aleatoriamente, guarda la nueva posición virtual en la variable 0x5000 y asigna la nueva posición real independientemente de la posición actual del pokémon.

Un ejemplo: imagina que pones un Zapdos errante que se mueva por las zonas del ejemplo, y que ahora mismo se encuentra en Ciudad Verde (0x5000 = 2). Cuando vueles a Ciudad Celeste, aparecerá en una ruta aleatoria, imagina que es la ruta 17. Pero cuando entres en la ruta 2 se ejecutará el script, verá que la variable vale 2 y a partir de ahí calculará una nueva posición, que podrá ser de forma aleatoria la ruta 1 o la ruta 2. Igualmente, pasará lo mismo si vuelas a pueblo paleta o a ciudad verde, o si entras en las rutas 1 y 3.

Espero haberte aclarado la duda.

Un saludo!

Jack Johnson: una idea genial! tendría que ver cómo ejecutar scripts o rutinas de ASM desde el menú de objetos. Gracias!
 

Dr._Seuss

Average RomHacker
Respuesta: Pokémon Errantes [Investigación Fire Red y Esmeralda FINALIZADA!!]

Puedes solucionar el problema de la pokedex para varios errantes, si usas un objeto "detector de pokemon", que diga la zona según la variable.
Es una genial idea, pero la veo mas complicada ya que deberia de agregarse esa funcion ASM a la de los items existentes, para mi es mas viable solucionar el problema directamente y no metiendote a uno mas complicado.

Y la rutina sera muy util para muchos, aunque yo no piense usarla la veo genial.
 

Ryuzaki-sama

Te voy a comer >:D
Respuesta: Pokémon Errantes [Investigación Fire Red y Esmeralda FINALIZADA!!]

Nice One!
Gran info para los que están haciendo un hack en estos momentos y tambien para los que van a hacer uno.
Ultimamente no he abierto las pouertas de mi hack, pero tal vez lo haga, otro dia.
Ahora estoy haciendo histórias.​
 
Respuesta: Pokémon Errantes [Investigación Fire Red y Esmeralda FINALIZADA!!]

Post actualizado.

He descubierto que el pokémon errante se guarda en una serie de variables. Así que simplemente ejecutando un script con el comando "setvar" podemos definir al pokémon errante que nos encontramos. Este procedimiento es mucho más simple que todo lo que había antes de ASM, así que he editado el post principal y he quitado mucha información que ya no es relevante.

También me he dado cuenta de que, si ponemos varios errantes, no hace falta guardar los datos de vitalidad y estado, así que el script para cambiar entre dos pokémon errantes es más simple. Por otra parte esto provoca que al cambiar de errante el nuevo aparezca con la salud a tope, y no con la que tenía antes, pero esto tampoco es un gran problema. De hecho GameFreak ya tuvo ese problema con los pokémon y el PC, de tal forma que si guardas un pokémon en el PC y lo sacas automáticamente se curará, y ellos no hicieron nada para arreglarlo ^^.

Comentad con cualquier duda que tengáis!
 
Arriba