Bueno, pues por fin os traigo está rutina. Resumiendo un poco lo que hace es cambiar los niveles de los pokemon enemigos, tanto los salvajes como de los entrenadores, en función del nivel máximo de los pokemon de tu equipo. Adicionalmente, si hacéis algún givepokemon, su nivel también se verá afectado por la rutina.
Decir que @eing ya hizo algo parecido hace tiempo (Me lo comentó @Mr. Nanren cuando ya tenía la rutina prácticamente acabada).
Aquí la rutina para cada uno de los rom.
Funcionamiento de la rutina:
La rutina irá comparando el nivel de cada uno de los pokemon de vuestro equipo para quedarse con el nivel máximo del mismo. Una vez tenga este dato, lo utilizará para alterar el nivel del pokemon enemigo. La rutina puede activarse o desactivarse utilizando un flag.
Si alguien tiene algún problema modificando la rutina tiene alguna duda que lo ponga por aquí e intentaré ayudarle.
Al final se me ha hecho muy tarde, pero dije que lo subía y lo subo. Aunque solo sea por lo poco que queda de mi orgullo. Y puede que también porque llevo un mes sin postear¿?¿?¿?.
Decir que he puesto el flag a petición de @kakarotto y creo que nada más. Mañana subo el otro tutorial que dije que iba a subir este fin de semana (xD). Ah si, también summonear a @Ωmega que dijo que quería verlo.
Edit: Me gustaría saber porque el foro se empeña en dar por culo y joderme las tabulaciones del notepad++.
Edit2: De verdad tenía que haber un usuario llamado @Camb que me joda los comentarios del ASM por que pilla @ cambiar como una mención? Mi bida es miserable. Cuando sea anciano crearé a dark Miutu y dejaré huérfano a alguien.
EDIT: Añadida versión para ruby.
Decir que @eing ya hizo algo parecido hace tiempo (Me lo comentó @Mr. Nanren cuando ya tenía la rutina prácticamente acabada).
No obstante al probar su rutina, no me funcionaba (probablemente porque sea parte de un sistema de rutinas) y en vez de dedicarme a ver que fallaba simplemente terminé la mía.
Por lo que he podido ver ahora mismo, la rutina de Eing solo estaba pensada para pokemon salvajes. De hecho, estoy casi seguro, que de utilizarla para un pokemon con movimientos custom (los de casitodos los trainer) iba a crashear el juego. Su función pisa el registro 7 antes de pushearlo (que si bien no se usa para los pokemon salvajes, si se usa para los pokes con custom moves).
El que quiera ver su rutina: [PD: es para ruby]:
El registro r7 lo pisa en el hook (ldr r7, bx r7).
Por lo que he podido ver ahora mismo, la rutina de Eing solo estaba pensada para pokemon salvajes. De hecho, estoy casi seguro, que de utilizarla para un pokemon con movimientos custom (los de casitodos los trainer) iba a crashear el juego. Su función pisa el registro 7 antes de pushearlo (que si bien no se usa para los pokemon salvajes, si se usa para los pokes con custom moves).
El que quiera ver su rutina: [PD: es para ruby]:
Código:
.align 2
.thumb
main:
push {r4-r7,lr}
mov r7,r8
push {r7}
add sp,#0x1c @-#0x1c
push {r0-r5}
ldr r0,.var_lvl
ldrh r0,[r0,#0x0]
cmp r0,#0x0
beq fin2
cmp r0,#0x1
beq avg
sub r0,#0x1
mov r7,r0
b fin
avg: @Mismo nivel +fuerte equipo
mov r10,lr
ldr r0,.pkamount @Cargamos pointer pokemon encima
ldrb r0,[r0,#0x0] @Cantidad pk
cmp r0,#0x0 @Comparamos si son 0
beq nopoke @Si son 0;Nivel 5
mov r1, #0x0 @posicion en el equipo
mov r2, #0x0 @nivel máximo
ldr r3, .lvl @Pointer nivel equipo
mov r4,#0x0 @Contador
bl bucle @BL a bucle
mov r0,r2 @Movemos nivel a r0
b fin @Vamos a fin
addlevel:
mov r2,r5 @Añadimos nivel
add r1,#0x1 @Añadimos 1 a posicion
mov r4,#0x64 @Añadimos 64 al contador
cmp r1, r0 @Comparamos si no es pkamount
bne bucle @Si no bucle
bx lr
bucle: @Bucle para determinar cual nivel es el mas alto
add r3,r4 @Sumamos Pointer+posicion
ldrb r5,[r3,#0x0] @Cargamos lvl
cmp r5,r2 @Comparamos nivel poke con nivel actual máximo
bgt addlevel @Si es mayor; ponemos el nuevo nivel
add r1,#0x1 @Añadimos 1 a posicion
mov r4,#0x64 @Añadimos 64 al contador
cmp r1, r0 @Comparamos si no es pkamount
bne bucle @Si no bucle
bx lr @Volvemos al BL
nopoke: [MENTION=25868]sin[/MENTION] pokemon; Nivel 5
mov r0,#0x5
b fin
fin: @Fin rutina
mov r7,r0 @Movemos nivel a r7
pop {r0-r5} @Popeamos registros
mov r2,r7 @Movemos nivel a r2
ldr r4, .fin @Vamos al punto donde estaba la rutina
bx r4
fin2:
pop {r0-r5}
ldr r4, .fin @Vamos al punto donde estaba la rutina
bx r4
.align 2
.pkamount: .word 0x03004350 @Pointer pk_amount
.segundos: .word 0x02024EB5 @Segundos
.lvl: .word 0x030043B4 @Pointer nivel
.fin: .word 0x0803a7a1 @Rutina de retorno
.var_lvl: .word 0x02026c52 @Var decide lvl
SetEnemyPokeLevel??
La rutina que os traigo es una "plantilla" que tiene lo básico, para que podáis personalizarla según vuestras necesidades o dejarla tal cual está (de no hacerlo así tendría que subir 200 versiones distintas de la rutina. Yo creo que es mejor subir una "base" con lo "difícil", y ya cada uno que cambie 4 números distintos para hacer lo que quiera).Aquí la rutina para cada uno de los rom.
Código:
.thumb
.align 2
/********** setEnemyLevel = maxPartyLevel |@RUBY|********
Establece el nivel de los pokemon enemigos (salvajes y entrenadores) de forma
dinámica, igualándolo al nivel máximo existente entre los pokemon de tu equipo
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Instrucciones de uso:
-Ir a la dirección 0x0803A798 (función CreateMon)
-Cambiar "F0 B5 47 46 80 B4 87 B0" por "80 B4 01 4F 38 47 C0 46 XX+1 XX XX 08"
siendo "XX+1 XX XX 08" el pointer permutado a esta rutina. y el resto las instrucciones:
********************
push {r7}
ldr r7, =08XXXXXX+1
bx r7
nop
********************
-Elige un flag para controlar la rutina.
-Resta (o suma) la cantidad de niveles de diferencia deseado
-Compilar esta rutina e insertarla en "08 XX XX XX+1".
*/
/**********************
El juego crea todos los pokemon con la función "CreateMon" (@pokegba) en 08067B4C,
uno de los argumentos pasados a esta función es el nivel del pokemon, que es pasado
por el registro r2. Esta rutina modifica según nuestra conveniencia el valor de r2,
dejando el resto intacto y modificando así el nivel de los pokemon generados por el
juego.
***********************/
no_crash:
pop {r7}
@Instrucciones de la rutina original
push {r4-r7, r14}
mov r7, r8
push {r7}
add sp, #-0x1C
mov r8, r0
mov r6, r1
flag_check: @Se encarga de comprobar si hemos activado el flag
push {r0-r2}
ldr r0, flag_number
ldr r2, flag_routine
push {r1-r3}
bl linker
pop {r1-r3}
cmp r0, #0x1
bne routine_off
pop {r0-r2}
main:
push {r3-r5}
ldr r3, party_lvl @carga el puntero al nivel de los pokemon en r3
ldrb r2, [r3] @Carga el nivel del pokemon en r2
mov r5, #0x5 @Establece el contador a 5 en r5
loop:
add r3, #0x64 @Suma 0x64 al puntero para pasar al siguiente nivel
ldrb r4, [r3] @Carga el valor del segundo nivel en r4
cmp r4, r2 @Compara ambos niveles
ble continue @Si el nivel de r4 es menor al de r2 lo deja tal cual está
mov r2, r4 @Si el nivel de r4 es mayor lo escribe en r2-r5
continue:
sub r5, r5, #0x1 @Resta uno al contador
cmp r5, #0x0 @compara el contador con 0
bne loop @Si el contador no ha llegado a 0 sigue ejecutando el bucle
ajuste:
sub r2, r2, #0x0 @ Cambiar #0x0 por la cantidad de niveles a restar (cambiar la instrucción por add si queremos sumar)
cmp r2, #0x0
beq fixed_min
cmp r2, #0x64
bge fixed_max
end:
pop {r3-r5} @Popea los registros utilizados
return:
ldr r4, return_dir @Vuelve a la rutina original
bx r4
routine_off:
pop {r0-r2}
b return
linker:
bx r2
fixed_max: @Evita pokemon con nivel superior al 100
mov r2, #0x64
b end
fixed_min: @Evita pokemon con niveles inferiores a 1
mov r2, #0x1
b end
.align 2
party_lvl: @Puntero a los niveles del equipo
.word 0x03004360 + 0x54
return_dir: @Dirección de retorno de la rutina
.word 0x0803A7A5
flag_routine: @Dirección de la rutina que checkea el flag
.word 0x08069340 +1
flag_number: @Número del flag utilizado en la rutina
.word 0x00000[XXX] @Pon aquí el número de flag que desees, EJ: 406
Código:
.thumb
.align 2
/********** setEnemyLevel = maxPartyLevel |@FRED|********
Establece el nivel de los pokemon enemigos (salvajes y entrenadores) de forma
dinámica, igualándolo al nivel máximo existente entre los pokemon de tu equipo
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Instrucciones de uso:
-Ir a la dirección 0x0803DA54 (función CreateMon)
-Cambiar "F0 B5 47 46 80 B4 87 B0" por "80 B4 01 4F 38 47 C0 46 XX+1 XX XX 08"
siendo "XX+1 XX XX 08" el pointer permutado a esta rutina. y el resto las instrucciones:
********************
push {r7}
ldr r7, =08XXXXXX+1
bx r7
nop
********************
-Compilar esta rutina e insertarla en "08 XX XX XX+1".
*/
/**********************
El juego crea todos los pokemon con la función "CreateMon" (@pokegba) en 0803DA54,
uno de los argumentos pasados a esta función es el nivel del pokemon, que es pasado
por el registro r2. Esta rutina modifica según nuestra conveniencia el valor de r2,
dejando el resto intacto y modificando así el nivel de los pokemon generados por el
juego.
***********************/
no_crash:
pop {r7}
@Instrucciones de la rutina original
push {r4-r7, r14}
mov r7, r8
push {r7}
add sp, #-0x1C
mov r8, r0
mov r6, r1
flag_check: @Se encarga de comprobar si hemos activado el flag
push {r0-r2}
ldr r0, flag_number
ldr r2, flag_routine
push {r1-r3}
bl linker
pop {r1-r3}
cmp r0, #0x1
bne routine_off
pop {r0-r2}
main:
push {r3-r5}
ldr r3, party_lvl @carga el puntero al nivel de los pokemon en r3
ldrb r2, [r3] @Carga el nivel del pokemon en r2
mov r5, #0x5 @Establece el contador a 5 en r5
loop:
add r3, #0x64 @Suma 0x64 al puntero para pasar al siguiente nivel
ldrb r4, [r3] @Carga el valor del segundo nivel en r4
cmp r4, r2 @Compara ambos niveles
ble continue @Si el nivel de r4 es menor al de r2 lo deja tal cual está
mov r2, r4 @Si el nivel de r4 es mayor lo escribe en r2-r5
continue:
sub r5, r5, #0x1 @Resta uno al contador
cmp r5, #0x0 @compara el contador con 0
bne loop @Si el contador no ha llegado a 0 sigue ejecutando el bucle
ajuste:
sub r2, r2, #0x0 @ Cambiar #0x0 por la cantidad de niveles a restar (cambiar la instrucción por add si queremos sumar)
cmp r2, #0x0
beq fixed_min
cmp r2, #0x64
bge fixed_max
end:
pop {r3-r5} @Popea los registros utilizados
return:
ldr r4, return_dir @Vuelve a la rutina original
bx r4
routine_off:
pop {r0-r2}
b return
linker:
bx r2
fixed_max: @Evita pokemon con nivel superior al 100
mov r2, #0x64
b end
fixed_min: @Evita pokemon con niveles inferiores a 1
mov r2, #0x1
b end
.align 2
party_lvl: @Puntero a los niveles del equipo
.word 0x02024284 + 0x54
return_dir: @Dirección de retorno de la rutina
.word 0x0803DA60 + 1
flag_routine: @Dirección de la rutina que checkea el flag
.word 0x0806E6D0 + 1
flag_number: @Número del flag utilizado en la rutina
.word 0x00000[XXX] @Pon aquí el número de flag que desees, EJ: 406
Código:
.thumb
.align 2
/********** setEnemyLevel = maxPartyLevel |@EMERALD|********
Establece el nivel de los pokemon enemigos (salvajes y entrenadores) de forma
dinámica, igualándolo al nivel máximo existente entre los pokemon de tu equipo
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Instrucciones de uso:
-Ir a la dirección 0x08067B4C (función CreateMon)
-Cambiar "F0 B5 47 46 80 B4 87 B0" por "80 B4 01 4F 38 47 C0 46 XX+1 XX XX 08"
siendo "XX+1 XX XX 08" el pointer permutado a esta rutina. y el resto las instrucciones:
********************
push {r7}
ldr r7, =08XXXXXX+1
bx r7
nop
********************
-Elige un flag para controlar la rutina.
-Resta (o suma) la cantidad de niveles de diferencia deseado
-Compilar esta rutina e insertarla en "08 XX XX XX+1".
*/
/**********************
El juego crea todos los pokemon con la función "CreateMon" (@pokegba) en 08067B4C,
uno de los argumentos pasados a esta función es el nivel del pokemon, que es pasado
por el registro r2. Esta rutina modifica según nuestra conveniencia el valor de r2,
dejando el resto intacto y modificando así el nivel de los pokemon generados por el
juego.
***********************/
no_crash:
pop {r7}
@Instrucciones de la rutina original
push {r4-r7, r14}
mov r7, r8
push {r7}
add sp, #-0x1C
mov r8, r0
mov r6, r1
flag_check: @Se encarga de comprobar si hemos activado el flag
push {r0-r2}
ldr r0, flag_number
ldr r2, flag_routine
push {r1-r3}
bl linker
pop {r1-r3}
cmp r0, #0x1
bne routine_off
pop {r0-r2}
main:
push {r3-r5}
ldr r3, party_lvl @carga el puntero al nivel de los pokemon en r3
ldrb r2, [r3] @Carga el nivel del pokemon en r2
mov r5, #0x5 @Establece el contador a 5 en r5
loop:
add r3, #0x64 @Suma 0x64 al puntero para pasar al siguiente nivel
ldrb r4, [r3] @Carga el valor del segundo nivel en r4
cmp r4, r2 @Compara ambos niveles
ble continue @Si el nivel de r4 es menor al de r2 lo deja tal cual está
mov r2, r4 @Si el nivel de r4 es mayor lo escribe en r2-r5
continue:
sub r5, r5, #0x1 @Resta uno al contador
cmp r5, #0x0 @compara el contador con 0
bne loop @Si el contador no ha llegado a 0 sigue ejecutando el bucle
ajuste:
sub r2, r2, #0x0 @ Cambiar #0x0 por la cantidad de niveles a restar (cambiar la instrucción por add si queremos sumar)
cmp r2, #0x0
beq fixed_min
cmp r2, #0x64
bge fixed_max
end:
pop {r3-r5} @Popea los registros utilizados
return:
ldr r4, return_dir @Vuelve a la rutina original
bx r4
routine_off:
pop {r0-r2}
b return
linker:
bx r2
fixed_max: @Evita pokemon con nivel superior al 100
mov r2, #0x64
b end
fixed_min: @Evita pokemon con niveles inferiores a 1
mov r2, #0x1
b end
.align 2
party_lvl: @Puntero a los niveles del equipo
.word 0x020244EC + 0x54
return_dir: @Dirección de retorno de la rutina
.word 0x08067B59
flag_routine: @Dirección de la rutina que checkea el flag
.word 0x0809D790 +1
flag_number: @Número del flag utilizado en la rutina
.word 0x00000[XXX] @Pon aquí el número de flag que desees, EJ: 406
Funcionamiento de la rutina:
La rutina irá comparando el nivel de cada uno de los pokemon de vuestro equipo para quedarse con el nivel máximo del mismo. Una vez tenga este dato, lo utilizará para alterar el nivel del pokemon enemigo. La rutina puede activarse o desactivarse utilizando un flag.
En primer abrimos el rom con HxD y vamos a "0803DA54" (FRED) o "08067B4C" (EM) y escribimos los siguientes bytes:
Una vez realizados estos cambios dentro del rom, vamos a modificar la rutina ASM según nuestras necesidades:
-Colocar el Flag que deseamos utilizar para activar/desactivar la rutina
-Elegir la cantidad de niveles por debajo (o por encima) a los que debe encontrarse el pokemon rival.
-Compilamos la rutina y la insertamos en "08XXXXXX". Cuando el flag seleccionado este activado (setflag 0x???) la rutina modificará el nivel de los pokemon generados por el juego.
Código:
80 B4 01 4F 38 47 C0 46 XX+1 XX XX 08
@XX+1 XX XX 08 es el offset permutado +1 donde vayáis a insertar la rutina
Una vez realizados estos cambios dentro del rom, vamos a modificar la rutina ASM según nuestras necesidades:
-Colocar el Flag que deseamos utilizar para activar/desactivar la rutina
Código:
flag_number:
.word 0x00000[XXX] @En XXX escribir el número del flag EJ: 406
-Elegir la cantidad de niveles por debajo (o por encima) a los que debe encontrarse el pokemon rival.
Código:
sub r2, r2, #0x0 [MENTION=26827]Camb[/MENTION]iar #0x0 por la cantidad de niveles a restar (cambiar la instrucción por add si queremos sumar)
-Compilamos la rutina y la insertamos en "08XXXXXX". Cuando el flag seleccionado este activado (setflag 0x???) la rutina modificará el nivel de los pokemon generados por el juego.
Como ya os he dicho, esta rutina es una base que podéis hacer crecer para cumplir vuestras necesidades, sin tener que saber prácticamente nada de ASM (solo lo más básico). Algunas de las posibles modificaciones que se me ocurren (algunas las he llevado a cabo yo en mi propia rutina) son las siguientes:
- -Utilizar el nivel medio de tu equipo para calcular el nivel de los pokemon salvajes en lugar del nivel máximo del equipo. (Tan fácil como sumar los niveles de todos los pokemon del equipo, dividirlo entre el número de pokemon y pasar el resultado a r2). Para dividir utilizar la instrucción "SWI 0xC" que realizará la operación r0/r1 dando el resultado en r0.
- -Introducir un factor aleatorio que le sume o le reste algo a los niveles.(como generador de números aleatorios podéis utilizar los milisegundos del reloj del juego).
- Hacer distintas cosas en función del tipo de pokemon que se va a generar (el número del pokemon en HEX está en el r1)
Si alguien tiene algún problema modificando la rutina tiene alguna duda que lo ponga por aquí e intentaré ayudarle.
Al final se me ha hecho muy tarde, pero dije que lo subía y lo subo. Aunque solo sea por lo poco que queda de mi orgullo. Y puede que también porque llevo un mes sin postear¿?¿?¿?.
Decir que he puesto el flag a petición de @kakarotto y creo que nada más. Mañana subo el otro tutorial que dije que iba a subir este fin de semana (xD). Ah si, también summonear a @Ωmega que dijo que quería verlo.
Edit: Me gustaría saber porque el foro se empeña en dar por culo y joderme las tabulaciones del notepad++.
Edit2: De verdad tenía que haber un usuario llamado @Camb que me joda los comentarios del ASM por que pilla @ cambiar como una mención? Mi bida es miserable. Cuando sea anciano crearé a dark Miutu y dejaré huérfano a alguien.
EDIT: Añadida versión para ruby.
Última edición: