Registrarse

[ASM] Modificar PS de los Pokemon del equipo

MetalKaktus

A la luz del quinto día, mira al este
Miembro insignia
Modificar PS de los Pokemon del equipo
El objetivo de este tutorial es explicar como podemos editar los Puntos de Salud de los Pokémon de nuestro equipo. Como bien sabréis Jpan hizo una rutina para cumplir este propósito. Pero su rutina no era nada practica.

Esa rutina resta un valor absoluto de PS al Pokémon seleccionado del equipo. Pero al ser un valor absoluto y al ignorar por completo los Puntos de Salud máximos del Pokemon en cuestión la rutina pierde eficacia.

La rutina que os explicaré en este tema hace lo mismo que la rutina de Jpan pero en vez de restar un valor absoluto resta un porcentaje del total de Puntos de Salud del Pokemon.

Antes de nada, si a alguien le interesa como he hecho la rutina y los pasos que he seguido dejaré en un spoiler el diario de investigación. Aclaro que no es necesario para seguir el tutorial, leedlo solo si tenéis interés (os lo recomiendo solo si tenéis un nivel aceptable de ASM).

Primero quiero aclarar los parámetros que tiene la rutina. La variable 0x8004 será la posición del Pokémon del equipo con el que trabajaremos. Por otro lado, la variable 0x8005 almacenará en porcentaje que vayamos a restarle a los PS actuales al Pokemon en cuestión.

Ahora paso a explicar como calcularemos el valor absoluto de PS a restar respecto al PS máximos. Nuestra herramienta será la clásica regla de tres.


Antes de nada quiero decir que todos los datos deberán estar en hexadecimal . Es decir, el 100 será 64 y todas esas cosas. Bien, pues para calcular x (PS a restar, valor absoluto) solo debemos multiplicar el valor de la variable 0x8005 y los PS máximos. A continuación habrá que dividir ese resultado entre 100 (64 en hex). La multiplicación es fácil, usaremos el comando mul. Pero la división la haremos usando una función de la BIOS, en este caso swi 0x6.

swi 0x6

Parámetros de entrada: r0 (numerador, el de arriba de la división) y r1 (divisor, el de abajo).

Parámetros de salida: r0 (valor sin comas del resultado) y r1 (resto, pero que nosotros ignoraremos)

Aclarado la obtención de los PS a restar paso a explicar el algoritmo a usar.

1. Cargar en un registro los PS absolutos a restar
2. Cargar los PS actuales y restarle lo obtenido en el primer paso
3. Cargar en la RAM el resultado

Ahora explicaré como se almacenan los datos de los offset que vayamos a usar.

Var_8004 y Var:8005

Simplemente son half words, no tiene más mismterio


PS y Psmax

Primero os mostraré estos offsets en la RAM, para ello usaré el comando mb del debugger (VBA-SDL-H)


En mi caso tengo un Miltank con un total de vidas de 313, que en hex es 01 39. Si permutamos estos dos bytes conseguiremos lo que hay en esa dirección de la memoria. Esto ocurre con los PS máximos y con los actuales. Por lo tanto, en la rutina habrá que cargar estos datos de una forma concreta, haciendo uso de los comandos lsl, lsr y orr.

Aclarada la forma de calcular los PS a restar y la estructura de los datos no hay más que hacer la rutina. Notese que hay una comparación la rutina. Esto debe a que en determinados casos los PS a restar e¡son más que los actuales, por lo tanto, al hacer la resta ya no nos funcionará la rutina. Por eso, comparamos si los PS a restar son más que los acutales, y en caso afirmativo saltaremos a la etiqueta not, donde simplemente en los PS actuales pondrémon 00 00. Aquí dejo la rutina explicada:

Código:
.text
.align 2
.thumb

main:
	push {r0-r3, lr}
	ldr r0, var_8004
	ldrh r0, [r0]
	mov r1, #0x64
	mul r0, r0, r1
	ldr r1, PSmax
	add r0, r0, r1		@cargamos el offset de los PS maximos del Pokemon en r0
	mov r1, r0		@hacemos un backup del offset, para ahorrar lines mas tarde
	add r0, r0, #0x1
	ldrb r0, [r0]
	lsl r0, r0, #0x8
	ldrb r1, [r1]
	orr r0, r0, r1		@r0 = PS máximos
	ldr r1, var_8005
	ldrh r1, [r1]
	mul r0, r0, r1
	mov r1, #0x64
	swi 0x6		@una vez ejecutado nos devolverá en r0 el valor de los PS a restar
	ldr r1, var_8004
	ldrh r1, [r1]
	mov r2, #0x64
	mul r1, r1, r2
	ldr r2, PS
	add r1, r1, r2		@cargamos el offset de los PS actuales
	mov r2, r1
	mov r3, r1
	add r1, r1, #0x1
	ldrb r1, [r1]
	lsl r1, r1, #0x8
	ldrb r2, [r2]
	orr r1, r1, r2		@r1 =PS actuales
	cmp r0, r1	@lo dicho antes, nos aseguramos que la resta será positiva, de lo contrario saltamos not
	bhi not
	sub r1, r1, r0
	mov r0, r1
	lsl r0, r0, #0x18
	lsr r0, r0, #0x18
	mov r2, r3
	strb r0, [r2]	@guardar un byte del PS nuevos
	mov r0, r1
	lsl r0, r0, #0x10
	lsr r0, r0, #0x18
	add r2, r2, #0x1
	strb r0, [r2]		@guardar el otro  byte, aquí ya está completa la acción
	b end

not:
	mov r0, #0x0
	strh r0, [r3]		@guardar un cero el los PS nuevos

end:
	pop {r0-r3, pc}

.align 2
	var_8004:	.word 0x020370C0
	var_8005:	.word 0x020370C2
	PS:	.word 0x020242DA
	PSmax:	.word 0x020242DC
Mirad la rutina las veces que haga falta y entenderéis como lo he hecho.

La rutina para Fire Red es esta:

Código:
.text
.align 2
.thumb

main:
	push {r0-r3, lr}
	ldr r0, var_8004
	ldrh r0, [r0]
	mov r1, #0x64
	mul r0, r0, r1
	ldr r1, PSmax
	add r0, r0, r1
	mov r1, r0
	add r0, r0, #0x1
	ldrb r0, [r0]
	lsl r0, r0, #0x8
	ldrb r1, [r1]
	orr r0, r0, r1
	ldr r1, var_8005
	ldrh r1, [r1]
	mul r0, r0, r1
	mov r1, #0x64
	swi 0x6
	ldr r1, var_8004
	ldrh r1, [r1]
	mov r2, #0x64
	mul r1, r1, r2
	ldr r2, PS
	add r1, r1, r2
	mov r2, r1
	mov r3, r1
	add r1, r1, #0x1
	ldrb r1, [r1]
	lsl r1, r1, #0x8
	ldrb r2, [r2]
	orr r1, r1, r2
	cmp r0, r1
	bhi not
	sub r1, r1, r0
	mov r0, r1
	lsl r0, r0, #0x18
	lsr r0, r0, #0x18
	mov r2, r3
	strb r0, [r2]
	mov r0, r1
	lsl r0, r0, #0x10
	lsr r0, r0, #0x18
	add r2, r2, #0x1
	strb r0, [r2]
	b end

not:
	mov r0, #0x0
	strh r0, [r3]

end:
	pop {r0-r3, pc}

.align 2
	var_8004:	.word 0x020370C0
	var_8005:	.word 0x020370C2
	PS:	.word 0x020242DA
	PSmax:	.word 0x020242DC
Si alguien me facilita los offset necesarios para Emeralda y Ruby estaré encantado de editar el tema y añadirlo.

Y aquí está la rutina compilada:

Código:
0F B5 17 48 00 88 64 21 48 43 18 49 40 18 01 1C 01 30 00 78 00 02 09 78 08 43 12 49 09 88 48 43 64 21 06 DF 0E 49 09 88 64 22 51 43 0E 4A 89 18 0A 1C 0B 1C 01 31 09 78 09 02 12 78 11 43 88 42 0B D8 09 1A 08 1C 00 06 00 0E 1A 1C 10 70 08 1C 00 04 00 0E 01 32 10 70 01 E0 00 20 18 80 0F BD C0 70 03 02 C2 70 03 02 DA 42 02 02 DC 42 02 02

Parámetros de la rutina:

Variable 0x8004: Posición del Pokémon a editar sus PS (recordar que el primero Pokemon tendrá la posición 0, y así sucesivamente)

Variable 0x8005: Porcentaje (en hexadecimal) a restar respecto a los PS máximos
Os pondré un script de ejemplo:

Código:
#dynamic 0x800000

#org @start
lock
faceplayer
setvar 0x8004 0x2
setvar 0x8005 0x32
callasm 0x800001
release
end
En este caso quiero restar al Pokemon número 3 la mitad de sus PS máximos a sus PS actuales. La rutina está en el offset 0x800000.

Si quieres hacer esto para todo el equipo usad un loop dentro del script o repetid el callasm para cada uno de los integrantes del equipo.

Créditos @Heavy Metal Kaktus por la rutina.

Quiero agradecer a @Cheve_X su tutorial de ASM desde donde saque los offsets y a @Kate, AliKate por responder mis innumerables dudas.

Espero que os haya gustado el tutorial, y si tenéis cualquier duda o cualquier cosa que decir no dudeis en comentar ;)
 

Juanemba

El Aspirante al campeonato y al éxito
Respuesta: [ASM] Modificar PS de los Pokemon del equipo

Muchas Gracias Por tu aporte intentaré hacer esto para ver si me resulta xd!
 

Dani_SR_17

¡Pokémon LionHeart!
Respuesta: [ASM] Modificar PS de los Pokemon del equipo

Un aporte bastante útil sin duda, no tengo mucho tiempo para leer la rutina así que preguntaré (y sino ya luego lo miraré yo), ¿el tema del porcentaje que tipo de redondeo usa?
Ya que estamos en modo tiquismiquis, estaría bien que agregaras un checkeo de cuantos Pokémon quedan con vida, vaya a ser que al usar esto se debiliten todos.
 

MetalKaktus

A la luz del quinto día, mira al este
Miembro insignia
Re: Respuesta: [ASM] Modificar PS de los Pokemon del equipo

Un aporte bastante útil sin duda, no tengo mucho tiempo para leer la rutina así que preguntaré (y sino ya luego lo miraré yo), ¿el tema del porcentaje que tipo de redondeo usa?
Ya que estamos en modo tiquismiquis, estaría bien que agregaras un checkeo de cuantos Pokémon quedan con vida, vaya a ser que al usar esto se debiliten todos.
Imagina que en r0 tengo 7 y en r1 2. Entonces, al hacer swi 0x6 hará 7/2. Que el resultado es 3,5. Pero en hexadecimal se usan siempre números enteros. Por eso, como parámetro te devuelve en r0 el número antes de la coma, en este caso 3 y en r1 lo que queda, en este caso 5.

Yo he ignorado ese resto, por lo tanto el redondeo en todos los casos es hacia abajo. No me parecía importante este redondeo la verdad, pues un PS más o menos es irrelevante. Pero si alguien quiere tenerlo en cuanta puede editar la rutina.

Y respecto a lo segundo. Pues no había pensado en ello la verdad. Pero bueno, con el comando de scripting comparefarbytetobyte puedes comprobar si los PS de todos los pokes es cero y a partir de ahí seguir el script o no.

Siempre prefiero usar el ASM para lo indispensable pues si algo se puede se puede hacer con scripting es recomendable hacerlo así, pues es mucho más sencillo que el ASM.
 

Dani_SR_17

¡Pokémon LionHeart!
Respuesta: Re: Respuesta: [ASM] Modificar PS de los Pokemon del equipo

Imagina que en r0 tengo 7 y en r1 2. Entonces, al hacer swi 0x6 hará 7/2. Que el resultado es 3,5. Pero en hexadecimal se usan siempre números enteros. Por eso, como parámetro te devuelve en r0 el número antes de la coma, en este caso 3 y en r1 lo que queda, en este caso 5.

Yo he ignorado ese resto, por lo tanto el redondeo en todos los casos es hacia abajo. No me parecía importante este redondeo la verdad, pues un PS más o menos es irrelevante. Pero si alguien quiere tenerlo en cuanta puede editar la rutina.

Y respecto a lo segundo. Pues no había pensado en ello la verdad. Pero bueno, con el comando de scripting comparefarbytetobyte puedes comprobar si los PS de todos los pokes es cero y a partir de ahí seguir el script o no.

Siempre prefiero usar el ASM para lo indispensable pues si algo se puede se puede hacer con scripting es recomendable hacerlo así, pues es mucho más sencillo que el ASM.
Lo del redondeo lo decía porque creo que sería más apropiado redondear hacia arriba, más que nada porque imagínate, le pones que quite un 99% y el Pokémon tiene tan pocos PS que se queda 0,9. No queda bien que en ese caso muera, pero bueno, con la explicación que has dado es fácil editar la rutina para adaptar este detalle.
 

MetalKaktus

A la luz del quinto día, mira al este
Miembro insignia
Re: Respuesta: Re: Respuesta: [ASM] Modificar PS de los Pokemon del equipo

Lo del redondeo lo decía porque creo que sería más apropiado redondear hacia arriba, más que nada porque imagínate, le pones que quite un 99% y el Pokémon tiene tan pocos PS que se queda 0,9. No queda bien que en ese caso muera, pero bueno, con la explicación que has dado es fácil editar la rutina para adaptar este detalle.
Levas razón. Claro que algo así se puede editar con un WBTO pero es más practico editar la rutina. Y hacer algo así es muy fácil. Gracias por avisar ;)
 
Arriba