Registrarse

[Scripting] Givepokemon con mote predeterminado

MetalKaktus

A la luz del quinto día, mira al este
Miembro insignia
Este tutorial surge a raíz de la duda de un usuario sobre si es posible o no poner un givepokemon con mote, y en base a eso me puse a inverstigar y lo conseguí. Voy a hacer el tutorial lo más simple posible.

Más o menos se trata de usar condiciones dependiendo de la cantidad de pokemon que hay en tu equipo te lleva a unos writebytetoofset u otros. Dejaré el script para que podais editarlo a vuestro gusto. El script es para Fire Red, pues las direcciones de la RAM están hechas para dicha ROM.

Script en cuestión:
Código:
#dynamic 0x800000

#org @start
givepokemon 0x(número de pokedex de nuestro pokemon) 0x(nivel) 0x(objeto) 0x0 0x0 0x0
countpokemon
compare LASTRESULT 0x1
if 0x1 call @snippet1
compare LASTRESULT 0x2
if 0x1 call @snippet2
compare LASTRESULT 0x3
if 0x1 call @snippet3
compare LASTRESULT 0x4
if 0x1 call @snippet4
compare LASTRESULT 0x5
if 0x1 call @snippet5
compare LASTRESULT 0x6
if 0x1 call @snippet6

#org @snippet1
writebytetooffset 0x 0x202428C
writebytetooffset 0x 0x202428D
writebytetooffset 0x 0x202428E
writebytetooffset 0x 0x202428F
writebytetooffset 0x 0x2024290
writebytetooffset 0x 0x2024291
writebytetooffset 0x 0x2024292
writebytetooffset 0x 0x2024293
writebytetooffset 0x 0x2024294
writebytetooffset 0x 0x2024295
return

#org @snippet2
writebytetooffset 0x 0x20242F0
writebytetooffset 0x 0x20242F1
writebytetooffset 0x 0x20242F2
writebytetooffset 0x 0x20242F3
writebytetooffset 0x 0x20242F4
writebytetooffset 0x 0x20242F5
writebytetooffset 0x 0x20242F6
writebytetooffset 0x 0x20242F7
writebytetooffset 0x 0x20242F8
writebytetooffset 0x 0x20242F9
return

#org @snippet3
writebytetooffset 0x 0x2024354
writebytetooffset 0x 0x2024355
writebytetooffset 0x 0x2024356
writebytetooffset 0x 0x2024357
writebytetooffset 0x 0x2024358
writebytetooffset 0x 0x2024359
writebytetooffset 0x 0x202435A
writebytetooffset 0x 0x202435B
writebytetooffset 0x 0x202435C
writebytetooffset 0x 0x202435D
return

#org @snippet4
writebytetooffset 0x 0x20243B8
writebytetooffset 0x 0x20243B9
writebytetooffset 0x 0x20243BA
writebytetooffset 0x 0x20243BB
writebytetooffset 0x 0x20243BC
writebytetooffset 0x 0x20243BD
writebytetooffset 0x 0x20243BE
writebytetooffset 0x 0x20243BF
writebytetooffset 0x 0x20243C0
writebytetooffset 0x 0x20243C1
return

#org @snippet5
writebytetooffset 0x 0X202441C
writebytetooffset 0x 0X202441D
writebytetooffset 0x 0X202441E
writebytetooffset 0x 0X202441F
writebytetooffset 0x 0X2024420
writebytetooffset 0x 0X2024421
writebytetooffset 0x 0X2024422
writebytetooffset 0x 0X2024423
writebytetooffset 0x 0X2024424
writebytetooffset 0x 0X2024425
return

#org @snippet6
writebytetooffset 0x 0x2024480
writebytetooffset 0x 0x2024481
writebytetooffset 0x 0x2024482
writebytetooffset 0x 0x2024483
writebytetooffset 0x 0x2024484
writebytetooffset 0x 0x2024485
writebytetooffset 0x 0x2024486
writebytetooffset 0x 0x2024487
writebytetooffset 0x 0x2024488
writebytetooffset 0x 0x2024489
return
Ahora solo teneís que editar los 0x antes de cada writebytetoofset con números hexadecimales paraque formen palabras. A continuación os dejo la lista de la equivalencia entre letras y números a los caracteres hexadecimales.

00=(espacio)
01=À
02=Á
03=Â
04=Ç
05=È
06=É
07=Ê
08=Ë
09=Ì
0B=Î
0C=Ï
0D=Ò
0E=Ó
0F=Ô
10=Œ
11=Ù
12=Ú
13=Û
14=Ñ
15=ß
16=à
17=á
19=ç
1A=è
1B=é
1C=ê
1D=ë
1E=ì
20=î
21=ï
22=ò
23=ó
24=ô
25=œ
26=ù
27=ú
28=û
29=ñ
2A=º
2B=ª
2D=&
2E=+
34=[Lv]
35==
36=;
51=¿
52=¡
53=[pk]
54=[mn]
55=[po]
56=[ké]
57=[bl]
58=[oc]
59=[k]
5A=Í
5B=%
5C=(
5D=)
68=â
6F=í
79=
7A=[D]
7B=[L]
7C=[R]
85=<
86=>
A1=0
A2=1
A3=2
A4=3
A5=4
A6=5
A7=6
A8=7
A9=8
AA=9
AB=!
AC=?
AD=.
AE=-
AF=·
B0=[.]
B1=[""]
B2=""
B3=[']
B4='
B5=[m]
B6=[f]
B7=[$]
B8=,
B9=[x]
BA=/
BB=A
BC=B
BD=C
BE=D
BF=E
C0=F
C1=G
C2=H
C3=I
C4=J
C5=K
C6=L
C7=M
C8=N
C9=O
CA=P
CB=Q
CC=R
CD=S
CE=T
CF=U
D0=V
D1=W
D2=X
D3=Y
D4=Z
D5=a
D6=b
D7=c
D8=d
D9=e
DA=f
DB=g
DC=h
DD=i
DE=j
DF=k
E0=l
E1=m
E2=n
E3=o
E4=p
E5=q
E6=r
E7=s
E8=t
E9=u
EA=v
EB=w
EC=x
ED=y
EE=z
EF=[>]
F0=:
F1=Ä
F2=Ö
F3=Ü
F4=ä
F5=ö
F6=ü
F7=
F8=[d]
F9=[l]


Para rellenar los espacios libres del nombre (no todos los nombres ocupan los 10 espacios evidentemente) solo rellenad los 0x con el valor 0, que se usa de relleno.

Por ejemplo, ABRA: BB BC CC BB 00 00 00 00 00 00

Y se coloca cada byte en uno de los diez WBTO que hay por cada snippet.


En cada uno de los diez writebytetoofset poned el mismo patrón de números. Es decir, lo que pongais en los 0x del primer snippet, lo repetis en los demás snippets (preguntad si no se entiende).

Si encontrais los offsets de los datos para Ruby y Emerald funcionará igual igual.

Desconozco si hay otra forma más eficaz de hacerlo, pero al carecer de conocimientos de ASM esto es lo que se e ha ocurrido. Si alguien sabe optimizar este método que lo diga sin dudarlo.
---------------------------------------------------------
Otro método


Ahora que he aprendido algo de ASM he conseguido cumplir el mismo objetivo, y ocupando mucho menos espacio.

1) Definir los nombres

Simplemente tenéis que insertar en un lugar vacío de la ROM el nombre que queráis poner automáticamente. Recordad que el nombre debe ocupar 10 bytes, y tenéis que usar la tabla de equivalencias antes dada para pasar de nuestro alfabeto al hexadecimal.

2) Insertad esta rutina en vuestra ROM

Código:
0F B5 09 48 00 88 01 38 64 21 41 43 07 48 40 18 07 49 00 22 09 2A 05 D0 0B 1C 09 78 81 54 59 1C 01 32 F7 E7 0F BD C0 46 D0 70 03 02 8C 42 02 02 [offset permutado]
Cambiando donde pone offset permutado por el offset del vuestro nombre pero permutado. Por ejemplo, si está en el 804E52 simplemente cambiad el [offset permutado] por 52 4E 80 08

3) El script

Solo tenéis que usar este script, recordad que esto no funciona si ya tenéis seis pokemon antes de que os entregue uno, cambiará el nombre del sexto pokemon. Por lo tanto, recordad tener un máximo de cinco pokemon antes de ejecutar la rutina.

Dicho lo cual, el script es este:

Código:
#dynamic 0x800000

#org @start
givepokemon 0x(especie) 0x(nivel) 0x(objeto) 0x0 0x0 0x0
countpokemon
callasm 0x(offset de la rutina + 1)
end
------------------------------------------------------------------------------

Código:
.align 2
.thumb
.thumb_func
.global rutina

main:

	push {r0-r3,lr}
	ldr r0, .lastresult
	ldrh r0, [r0]
	sub r0, r0, #0x1
	mov r1, #0x64       [MENTION=25158]Lon[/MENTION]gitud de datos de cada PKMN
	mul r1, r1, r0
	ldr r0, =0x202428C     @inicio de los datos de los PKMN del equipo
	add r0, r0, r1
	ldr r1, =0x(offset del nombre)
	mov r2, #0x0

loop:
	
	cmp r2, #0x9
	bEQ end
	mov r3, r1
	ldrb r1, [r1]
	strb r1, [r0, r2]     @guardamos en el nombre del PKMN la letra número n donde n es el valor de r2
	add r1, r3, #0x1
	add r2, r2, #0x1
	b loop

end:

	pop {r0-r3,pc}
	
.align 2

.lastresult:                            
	.word 0x020270B6 + (0x800D * 2)

Créditos a @Metal Kaktus por la rutina

-------------------------------------------------------------------

Espero que os haya gustado, y si hay alguna duda no dudeis en preguntar ;)

Hasta otra!
 
Última edición:
¡Eres un grande!

Lo que me ha quedado una duda, espero que no sea muy tonta :p

Entonces, si por ejemplo quiero que el POKéMON se llame, yo que sé, Juan (xD) tendría que poner cada una de las letras en Hexadecimal y poner cada valor en el writebytetooffset y, en todos los snippets, poner los writebytetooffset de Juan (¿?)
 

BLAx501!

A veces comento en temas :3
Miembro de honor
Usuario de Platino
¡Eres un grande!

Lo que me ha quedado una duda, espero que no sea muy tonta :p

Entonces, si por ejemplo quiero que el POKéMON se llame, yo que sé, Juan (xD) tendría que poner cada una de las letras en Hexadecimal y poner cada valor en el writebytetooffset y, en todos los snippets, poner los writebytetooffset de Juan (¿?)
En efecto. Ese script básicamente comprueba en qué posición se ubica el Pokémon que se ha otorgado y en función de ello, haciendo uso del comando writebytetoofset (WBTO para abreviar) modifica el fragmento de la RAM que almacena dicho dato.

Es un procedimiento bastante engorroso y con ensamblador se podría reducir bastante ya que para poder hacerlo vía scripts tienes que "desmembrar" la operación a cambios sobre bytes, pero funciona :cool:
 

Sayer301!

UnityLord!
Miembro de honor
Sublime, para una persona como yo, esto es 10/10.

Odio las rutinas, le quitan lo esencial al ROM hacking, que es el ingenio para conseguir lo cosas mucho mejores al juego original, usando sus mismos recursos, como haces tú.

A mi las rutinas me parece que no molan un pescao, ya que como cada rutina la hace una persona y pensando en lo que le viene bien a el pues siempre hay alguna que acaba solapandose.

En fin un buen trabajazo! Espero que sea de utilidad a muchos usuarios.... Sigue asi niggi!
 

BLAx501!

A veces comento en temas :3
Miembro de honor
Usuario de Platino
Odio las rutinas, le quitan lo esencial al ROM hacking, que es el ingenio para conseguir lo cosas mucho mejores al juego original, usando sus mismos recursos, como haces tú.
Usar una rutina es usar ingenio, a fin de cuentas, modificas los datos de la ROM igual que con comandos de scripting, con la diferencia de que con las rutinas tienes más libertad.

Es algo más complicado aprender ASM que aprender a scriptear con XSE, pero una cosa no quita la otra xD
 

Dani_SR_17

¡Pokémon LionHeart!
Muy útil, aunque algo costoso, sobretodo si quieres poner varios motes.
Pero le veo una pega, que no consideras el caso de que el equipo estuviera completo antes de recibir el Pokémon.
El countpokemon habría que hacerlo antes del givepokemon, y lo suyo sería almacenar el resultado en una variable que no sea dinámica (por si las moscas).
Para optimizarlo quizás con loadpointer se podría mejorar, pero habría que estudiarlo más detenidamente.
 

MetalKaktus

A la luz del quinto día, mira al este
Miembro insignia
Re: Respuesta: Givepokemon con mote predeterminado

Muy útil, aunque algo costoso, sobretodo si quieres poner varios motes.
Pero le veo una pega, que no consideras el caso de que el equipo estuviera completo antes de recibir el Pokémon.
El countpokemon habría que hacerlo antes del givepokemon, y lo suyo sería almacenar el resultado en una variable que no sea dinámica (por si las moscas).
Para optimizarlo quizás con loadpointer se podría mejorar, pero habría que estudiarlo más detenidamente.
Es algo en lo que ya había pensado, creo que estaría bien añadir una condición de que deberías tener una posición libre en el equipo para que te puedan dar el Pokémon.

Pero bueno, si en algún momento se te ocurre como se podría optimizar el script me gustaría saberlo.

Se que es un método un poco pesado, pero como dice Blaxie al menos funciona, ahora solo queda mejorarlo más.

Gracias por pasarte a comtar ;)
 

MetalKaktus

A la luz del quinto día, mira al este
Miembro insignia
Ahora que he aprendido algo de ASM he conseguido cumplir el mismo objetivo, y ocupando mucho menos espacio.

1) Definir los nombres

Simplemente tenéis que insertar en un lugar vacío de la ROM el nombre que queráis poner automáticamente. Recordad que el nombre debe ocupar 10 bytes, y tenéis que usar la tabla de equivalencias antes dada para pasar de nuestro alfabeto al hexadecimal.

2) Insertad esta rutina en vuestra ROM

Código:
0F B5 09 48 00 88 01 38 64 21 41 43 07 48 40 18 07 49 00 22 09 2A 05 D0 0B 1C 09 78 81 54 59 1C 01 32 F7 E7 0F BD C0 46 D0 70 03 02 8C 42 02 02 [offset permutado]
Cambiando donde pone offset permutado por el offset del vuestro nombre pero permutado. Por ejemplo, si está en el 804E52 simplemente cambiad el [offset permutado] por 52 4E 80 08

3) El script

Solo tenéis que usar este script, recordad que esto no funciona si ya tenéis seis pokemon antes de que os entregue uno, cambiará el nombre del sexto pokemon. Por lo tanto, recordad tener un máximo de cinco pokemon antes de ejecutar la rutina.

Dicho lo cual, el script es este:

Código:
#dynamic 0x800000

#org @start
givepokemon 0x(especie) 0x(nivel) 0x(objeto) 0x0 0x0 0x0
countpokemon
callasm 0x(offset de la rutina + 1)
end
------------------------------------------------------------------------------

Código:
.align 2
.thumb
.thumb_func
.global rutina

main:

	push {r0-r3,lr}
	ldr r0, .lastresult
	ldrh r0, [r0]
	sub r0, r0, #0x1
	mov r1, #0x64    @ Longitud de datos de cada PKMN
	mul r1, r1, r0
	ldr r0, =0x202428C     @inicio de los datos de los PKMN del equipo
	add r0, r0, r1
	ldr r1, =0x(offset del nombre)
	mov r2, #0x0

loop:
	
	cmp r2, #0x9
	bEQ end
	mov r3, r1
	ldrb r1, [r1]
	strb r1, [r0, r2]     @guardamos en el nombre del PKMN la letra número n donde n es el valor de r2
	add r1, r3, #0x1
	add r2, r2, #0x1
	b loop

end:

	pop {r0-r3,pc}
	
.align 2

.lastresult:                            
	.word 0x020270B6 + (0x800D * 2)

Créditos a @Metal Kaktus por la rutina
 

Erunan

Caballero de espada verde
Buen aporte yo estaba buscando algo así en mucho tiempo pero una duda es posible definir el género del pokemon con mote
 

MetalKaktus

A la luz del quinto día, mira al este
Miembro insignia
Re: Respuesta: Givepokemon con mote predeterminado

Buen aporte yo estaba buscando algo así en mucho tiempo pero una duda es posible definir el género del pokemon con mote
Que quieres decir exactamente? El género del Pokémon está en sus datos de la RAM pero no entiendo como quieres poner el género en función del mote

Edito: Quieres cambiar el mote y el género a la vez? Si es así lo del genero, aunque posible no te lo voy a garantizar. Te explico, cuando tu alteras ciertos valores de los datos de un pokemon este se convierte en un huevo malo a no ser que vuelvas a recalcular una cosa (no voy a entrar en detalles). Dejame intentarlo y te diré el resultado, pero espera a mañana que ya es tarde.
 
Última edición:

Naren Jr.

Puto amo
Usuario de Platino
Wow no había visto este tutorial y que @Finrod Felagund estuviese tan adentrado en todo esto.

Es un detalle bastante genial, de hecho en el proyecto que estoy llevando ahora fijo quería entregar un Pokémon con un mote distinto y venga que esto me viene al pelo!
 
Arriba