[Tuto - GBA] Changer l’espèce d'un pokémon avec un script dans Club | Pokémon Trash
[Tuto - GBA] Changer l’espèce d'un pokémon avec un script
TheCaptainSnow - 7 mars 2013 à 15:03
Changer l’espèce d'un pokémon
Dans ce tuto je vais vous apprendre à changer l’espèce du premier pokémon de l'équipe.
Pourquoi faire me direz vous? Ou encore que l'ont peut faire la même chose avec un échange.
Mais l'avantage ici c'est que seul l’espèce du pokémon change, il conserve donc toute les autres caractéristique telle que les EV, IV, shiny, nature, ruban, bref toute les caractéristique (où presque mais je reparlerai de l'xp plus loin).
L’intérêt de changer d’espèce prend tout sont sens quand vous voulez inclure toute les formes d'un pokémon dans votre hack-rom. Et des pokémon comme sa il y en à plein: Deoxys, Motisma, Keldeo, Cheniti, Vivaldaim, Sancoki, ...
Vous pouvez aussi utiliser cette méthode pour faire évoluer certains pokémons, qui requiert des conditions spécial non présente dans les versions GBA, je pense notamment aux évolutions d'évolie qui demande de se trouver dans des lieux précis (de plus il est impossible d'inclure toutes les évolutions d'évolie de manière normal, alors qu'avec sa c'est possible).
Une autre utilisation peut être en remplacement au évolutions par échange, ont vois trop souvent des gens qui transforme les évolutions par échange en évolutions par niveau ou par pierre. Personnellement je trouve que cela diminue la "rareté" de ces évolutions alors maintenant vous pourrez trouvez d'autres moyens pour faire évoluer ces pokémons (après une mini quête par exemple).
Bon maintenant que j'ai fais ma petite introduction ont va pouvoir s’attaquer au tuto en lui même.
Logiciel requis:
Un editeur Hexadecimal (Hex edit par exemple)
XSE
Etape 1: Mise en place
Il n'est pas possible d'utiliser un simple script pour appliquer ce genre de modifications, il faut donc utiliser l'ASM (pour ce qui ne savent pas ce qu'est l'ASM ce n'est pas grave, vous arriverai quand même au bout de ce tuto sans souci).
Je vas donc falloir inclure 3 code ASM déjà compilé dans la rom grâce à votre editeur hexa.
Pour la suite je vais donner des codes pour la version Rouge Feu (fr) uniquement, pour les autres versions ne vous inquiéter pas j’expliquerais comment les adapter facilement.
Les parties colorées seront celle à changer pour adapter le code aux autres versions, mais je vous expliquerais en détailles plus loin.
Il faut maintenant que vous alliez inclure ce code dans votre rom et bien sur dans un espace libre (taille = 308 octets), j’espère que vous savez déjà trouver un espace libre dans votre rom (avec FSF ou editeur Hexa).
Noter bien à quelle offset vous avez inclus ce code car on en aura besoin pour la suite.
On passe maintenant à la 2eme routine de JPAN:
[spoiler]
Encore une fois il faut inclure ce code dans votre rom (taille = 88 octets) et noter l'offset correspondant.
Maintenant une petite explication sur les parties colorés: Ce sont les partie à changé en fonction de votre version, voila ce qu'il faut mettre à la place:
[table]
[tr]
[td]Version[/td]
[td]Rouge Feu[/td]
[td]Vert Feuille[/td]
[td]Ruby[/td]
[td]Saphire[/td]
[td]Emeraude[/td]
[/tr]
[tr]
[td]En rouge[/td]
[td]C0 70 03 02[/td]
[td]C0 70 03 02[/td]
[td]CC E8 02 02[/td]
[td]CC E8 02 02[/td]
[td]E4 75 03 02[/td]
[/tr]
[tr]
[td]En orange[/td]
[td]84 42 02 02[/td]
[td]84 42 02 02[/td]
[td]70 43 00 03[/td]
[td]70 43 00 03[/td]
[td]EC 44 02 02[/td]
[/tr]
[/table]
Pour votre information les données des pokémons sont crypté et on ne peut pas les modifier n'importe comment sous peine d'obtenir un BadEgg, ces routines sont justement la pour décrypter et ré-encrypter ces données sans provoquer de BadEgg. Merci JPAN
Il reste encore une routine à insérer, cette fois-ci elle est de moi, c'est celle-la qui modifie l’espèce d'un pokémon:
[spoiler]
Comme pour les 2 premières routine il faut l'insérer à un espace libre, et noter l'offset.
Il faut aussi changer les portions colorés en fonction de vos version:
[table]
[tr]
[td]Version[/td]
[td]Rouge Feu[/td]
[td]Vert Feuille[/td]
[td]Ruby[/td]
[td]Saphire[/td]
[td]Emeraude[/td]
[/tr]
[tr]
[td]En vert[/td]
[td]C2 70 03 02[/td]
[td]C2 70 03 02[/td]
[td]CE E8 02 02[/td]
[td]CE E8 02 02[/td]
[td]E2 75 03 02[/td]
[/tr]
[tr]
[td]En bleu[/td]
[td]E7 EB 24 08[/td]
[td]C3 EB 24 08[/td]
[td]77 70 20 08[/td]
[td]07 70 20 08[/td]
[td]4F 7F 32 08[/td]
[/tr]
[/table]
Et voila, votre rom est prête pour modifié l’espèce d'un pokémon dans un script.
Etape 2: Application dans un script
Le script de base en lui même est assez simple et à toujours la même forme:
callasm 0x08(offset JPAN 1 + 1)setvar 0x8005 0xno nouveau pokémon (en hexa)callasm 0x08(offset "ma routine" + 1)callasm 0x08(offset JPAN 2 + 1)
J’imagine qu'il va falloir donner quelque explication, à commencer par les offsets qui suivent les callasm:
Il vous suffit de prendre l'offset auquel vous avez insérer la routine et d'y ajouter 1, par exemple si j'ai insérer la première routine à l'offset
#0x7105C0 je devrai écrire callasm 0x087105C1
Par exemple si j'avais j'avais insérer aux offsets suivant:
[spoiler]
routine JPAN 1: #0x7105C0
routine JPAN 2: #0x710760
ma routine: #0x711200
[/spoiler]
mon script ressemblerai à sa:
callasm 0x087105C1setvar 0x8005 0xno nouveau pokémon (en hexa)callasm 0x08711201callasm 0x08710761
Ensuite le "no nouveau pokémon" j'imagine que vous l'avez compris par vous même, si je veux que le pokémon deviennent un Grolem (n°76 dans le pokedex) je convertit en hexa ce qui me donne #0x4C, dans mon script j'aurais donc setvar 0x8005 0x4C
Petite parenthèse pour ce qui voudrait mieux comprendre ce script :
[spoiler]Sachez que le 1er callasm permet de décrypter les donné du pokémon, le 2eme callasm utilise le contenue de la variable #0x8005 pour changer l’espèce du pokémon et le dernier callasm encrypte les nouvelles donnés tous en recalculant le checksum pour éviter un Badegg.[/spoiler]
Vous savez maintenant comment changer l’espèce du premier pokémon de l'équipe, mais ce n'est pas très pratique car le script s’exécute quelle que soit le pokémon en première position, on se retrouverai alors avec des Rattatas qui se transformerons en Grolem, or nous on veut que seul les Gravalanch puissent se transformais. On va donc voire quelque instructions qui peuvent être pratique pour vérifier quelle pokémon est en première position ou encore sont niveau.
Avant de peaufiner votre script essayer le comme sa pour vérifier qu'il fonctionnent, une fois cela fais vous pourrez passer à la suite, mais si votre script de marche pas vérifier que vous avez bien fais les premières étapes.
Etape 3: Quelques conditions
Vérifier l’espèce d'un pokémon
Il existe un spécial qui permet de récupérer l’espèce d'un pokemon, le spécial #0x147. Ce spécial utilise la variable #0x8004 pour savoir à quelle position il doit chercher (de 0 à 5). de plus il à une petite particularité, il faut utiliser l'instruction special2 0xvariable 0x147.
Pour vérifier quelle pokémon est en première position il faut donc écrire:
setvar 0x8004 0x0 on place 0 dans la variable 8004
special2 0x8005 0x147 Ici le special 147 vérifie le pokemon à la position de la variable 0x8004, donc à la position 0. L’espèce du pokemon est ensuite stocker dans la variable 0x8005
Maintenant que l'ont à récupérer l’espèce du pokémon il suffit d'utiliser compare pour vérifier si c'est un Gravalanch, pour sa je part du principe que vous savez l'utiliser, j’obtiens donc le script suivant:
[spoiler]
'---------------#org 0x710900setvar 0x8004 0x0special2 0x8005 0x147compare 0x8005 0x4Bif 0x1 goto 0x8710A00msgbox 0x8710B00 MSG_FACE '"Cette pierre ressemble à un fragme..."end'---------------#org 0x710A00callasm 0x87105C1setvar 0x8005 0x4Ccallasm 0x8711201callasm 0x8710761msgbox 0x8710C00 MSG_FACE '"Au contact de la pierre\nGRAVALANC..."end'---------' Strings'---------#org 0x710B00= Cette pierre ressemble à un fragment de GROLEM.#org 0x710C00= Au contact de la pierre\nGRAVALANCH réagit. Comment?\lMon GRAVALANCH c'est transformé\nen GROLEM.
[/spoiler]
Vérifier le niveau d'un pokémon
Pour le moment je n'ai pas trouvé de moyen de vérifier le level d'un pokémon autrement qu'avec l'ASM et j'ai la flemme de le faire maintenant, je compléterai cette partie quand j'aurais fais le code. Même chose pour les offsets des autres versions.
Remarque importante
Il y à un point qu'il faut aussi que je traite avec vous par rapport à l’expérience du pokémon, je vais différencier 3 cas:
Le pokémon est niveau 100, dans ce cas pas de problème il aura exactement la bonne xp
L'ancien et le nouveau pokémon ont le même pallier d'xp, dans ce cas la pas de problème l'xp reste la même (donc le niveau aussi)
ce cas sera le plus fréquent car une même ligné à toujours le même palier, par exemple si kaiminus à un palier de type 3 (xp max = 1 059 860 exp) alors crocodile et aligatueur auront le même palier. (sauf si vous avez changez ces palier et dans ce cas la vous êtes un boulet)
Le dernier cas est le plus génant, comme les paliers d'xp ne sont pas les même pour tous les pokémon il à fallu que je recalcule l'xp à chaque changement d’espèce pour que le pokémon garde sont niveau, malheureusement les limites de la GBA font que je ne peut pas effectuer ce calcule avec précision, en général ce manque de précision est faible mais il se peut que les pokémon qui viennent tous juste de up se retrouve au niveau d'en dessous (à quelque points d'xp prêt).
Ce problème est rare quand le niveau du pokémon est élevée, mais quand le pokémon à un niveau très bas (1 à 30) ce problème devient très fréquent, je vous conseille donc de fixer un niveau minimum pour éviter ce genre de probléme.
Attention je parle bien d'un probléme, sa ne fera pas planter votre jeu mais pour le joueur sa peut être gênant d'avoir un pokémon niveau 34, et que celui-ci se retrouve niveau 33 après avoir changé sont espèce.
Je tien à rappeler en que cette explication n'est valable que pour le cas où l'ancien pokémon n'est pas niveau 100 et que le nouveau et l'ancien ne sont pas de la même ligné, c'est donc une situation très rare mais qui peut arriver (par exemple si pour des raison de scenario vous voulez transformer mew en mewtwo, car ces pokémon n'ont pas le même palier).
Voila ce tutoriel touche à sa fin, il est possible que je modifie le code ASM fais par moi pour lui apporter des améliorations (surtout au niveau de l’imprécision sur l'xp).
Pour ce qui voudrait avoir les codes ASM non compilé ou des liens pour mieux comprendre le fonctionnement c'est sous spoil mais si vous n'y connaissait rien à l'ASM ou encore à l'hexadecimal ce n'est pas la peine de regarder:
[spoiler]
Liens utile:
main:
push {r0-r3, lr}
ldr r0, .poke_struct Cette première partie permet de changer l’espèce du pokémon
ldr r0, [r0]
ldrh r2, [r0] J'en profite pour récupérer l’espèce du pokémon qui servira à obtenir sont paliers d'xp
ldr r1, .var_8005
ldrh r1, [r1]
strh r1, [r0]
Le changement d’espèce est terminer, il faut maintenant recalculer l'xp
ldr r1, .growth_rate
mov r0, #0x1C Chaque stats de base d'un pokemon est codé sur #0x1C bytes
mul r0, r2 Il faut donc multiplier sa par le numero du pokémon avant changement
add r1, r0 Et l'ajouter au debut des paliers d'xp pour avoir le palier d'xp du pokémon avant changement
mov r3, #0x0
get_growth: A partir de ce palier on récupère l'xp max
ldrb r1, [r1]
cmp r1, #0x0
beq medium_fast
cmp r1, #0x1
beq erratic
cmp r1, #0x2
beq fluctuating
cmp r1, #0x3
beq medium_slow
cmp r1, #0x4
beq fast
cmp r1, #0x5
beq slow
medium_fast:
ldr r1, .medium_fast
b next
erratic:
ldr r1, .erratic
b next
fluctuating:
ldr r1, .fluctuating
b next
medium_slow:
ldr r1, .medium_slow
b next
fast:
ldr r1, .fast
b next
slow:
ldr r1, .slow
b next
next:
cmp r3, #0x0 On verifie si r3 contient déjà l'xp max de l'ancien pokémon
bne next2
mov r3, r1
ldr r1, .growth_rate Maintenant il faut récupérer le palier d'xp du nouveau pokémon
mov r0, #0x1C
ldr r2, .var_8005
ldrh r2, [r2]
mul r2, r0
add r1, r2
b get_growth Et on récupère sont xp max
next2:
ldr r0, .poke_struct On récupére l'ancienne xp
ldr r0, [r0]
add r0, #0x4
ldr r2, [r0]
cmp r2, r3 Si l'ancienne xp est egal à l'ancienne xp max alors le pokémon est lvl 100, donc pas besoin
beq end de recalculer la nouvelle xp, elle est forcément la nouvelle xp max
cmp r3, r1 Si l'ancienne xp max est egal à la nouvelle xp max alors pas besoin de calculer la nouvelle xp
beq same_growth car elle reste identique
lsr r1, #0x5 Division par 32 pour éviter que la multiplication suivante donne un résultat supérieur
lsr r2, #0x5 à 32bit (limite d'un registre), d'où la perte de prècision
lsr r3, #0xA
mul r2, r1
mov r1, #0x0
divise:
sub r2, r3
bmi end
add r1, #0x1
b divise
end:
str r1, [r0]
pop {r0-r3, pc}
same_growth:
mov r1, r2
b end
ADDON : ne pas avoir à appliquer dans chaque script
Je viens d'ailleurs de penser à autre chose, plutôt que de devoir récrire à chaque script ces 4 lignes:
callasm 0x08(offset JPAN 1 + 1)setvar 0x8005 0xno nouveau pokémon (en hexa)callasm 0x08(offset "ma routine" + 1)callasm 0x08(offset JPAN 2 + 1)
il suffirait de les placer quelque par dans la rom et comme sa on aurait juste à les appeler avec l'instruction call.
Sa ferait un gain de place si vous voulez utilisez sa dans plusieurs scripts et sa rendrait ces scripts plus lisible.
Sa donnerais quelque chose comme sa:
[spoiler]
'---------------#org 0x710900setvar 0x8004 0x0special2 0x8005 0x147compare 0x8005 0x4Bif 0x1 goto 0x8710A00msgbox 0x8710B00 MSG_FACE '"Cette pierre ressemble à un fragme..."end'---------------#org 0x710A00setvar 0x8005 0x4Ccall 0x720000msgbox 0x8710C00 MSG_FACE '"Au contact de la pierre\nGRAVALANC..."end'---------------#org 0x720000callasm 0x87105C1callasm 0x8711201callasm 0x8710761return'---------' Strings'---------#org 0x710B00= Cette pierre ressemble à un fragment de GROLEM.#org 0x710C00= Au contact de la pierre\nGRAVALANCH réagit. Comment?\lMon GRAVALANCH c'est transformé\nen GROLEM.
Et si je veut encore changer l’espèce d'un pokémon dans un autre script j'aurais juste à faire:
setvar 0x8005 0xXX
call 0x720000
[/spoiler]
mystogan640 - 7 mars 2013 à 15:48
J'ai tout lu, plus ou moins tout compris, bref excellent tuto. T'as réussi a rendre une chose difficile de prime abord, assez facile a comprendre ou du moins a appliquer. Bref, vraiment bien joué.
darklives - 7 mars 2013 à 16:28
Super tuto! Tout lu, je teste de suite. Ca ouvre beaucoup de possibilités de scénario, je vais voir si j'arrive à intégrer ça dans un Level Script (pour par exemple changer la forme de Deoxys en allant à un certain endroit).
EDIT: Ca marche nickel
hremeraude - 7 mars 2013 à 19:26
ça à l'air simple et bien en effet
Je testerais une fois que tu aura fait pour Emeraude
TheCaptainSnow - 7 mars 2013 à 20:06
Merci de vos retour positif
@darklives: Deoxys était moi aussi la principal raison pour lequel je me suis lancé la dedans, c'est seulement après que j'ai chercher d'autre application
@hremeraude: normalement j’aurai ajouter sa pour ce soir.
Je viens d'ailleurs de penser à autre chose, plutôt que de devoir récrire à chaque script ces 4 lignes:
callasm 0x08(offset JPAN 1 + 1)setvar 0x8005 0xno nouveau pokémon (en hexa)callasm 0x08(offset "ma routine" + 1)callasm 0x08(offset JPAN 2 + 1)
il suffirait de les placer quelque par dans la rom et comme sa on aurait juste à les appeler avec l'instruction call.
Sa ferait un gain de place si vous voulez utilisez sa dans plusieurs scripts et sa rendrait ces scripts plus lisible.
Sa donnerais quelque chose comme sa:
[spoiler]
'---------------#org 0x710900setvar 0x8004 0x0special2 0x8005 0x147compare 0x8005 0x4Bif 0x1 goto 0x8710A00msgbox 0x8710B00 MSG_FACE '"Cette pierre ressemble à un fragme..."end'---------------#org 0x710A00setvar 0x8005 0x4Ccall 0x720000msgbox 0x8710C00 MSG_FACE '"Au contact de la pierre\nGRAVALANC..."end'---------------#org 0x720000callasm 0x87105C1callasm 0x8711201callasm 0x8710761end'---------' Strings'---------#org 0x710B00= Cette pierre ressemble à un fragment de GROLEM.#org 0x710C00= Au contact de la pierre\nGRAVALANCH réagit. Comment?\lMon GRAVALANCH c'est transformé\nen GROLEM.
Et si je veut encore changer l’espèce d'un pokémon dans un autre script j'aurais juste à faire:
setvar 0x8005 0xXX
call 0x720000
[/spoiler]
Je n'ajoute pas sa dans le tuto parce-que je pense que sa peut en embrouillez certains mais je voulait quand même en parler.
darklives - 7 mars 2013 à 20:32
Je viens d'ailleurs de penser à autre chose, plutôt que de devoir récrire à chaque script ces 4 lignes:
callasm 0x08(offset JPAN 1 + 1)setvar 0x8005 0xno nouveau pokémon (en hexa)callasm 0x08(offset "ma routine" + 1)callasm 0x08(offset JPAN 2 + 1)
il suffirait de les placer quelque par dans la rom et comme sa on aurait juste à les appeler avec l'instruction call.
Sa ferait un gain de place si vous voulez utilisez sa dans plusieurs scripts et sa rendrait ces scripts plus lisible.
Sa donnerais quelque chose comme sa:
[spoiler]
'---------------#org 0x710900setvar 0x8004 0x0special2 0x8005 0x147compare 0x8005 0x4Bif 0x1 goto 0x8710A00msgbox 0x8710B00 MSG_FACE '"Cette pierre ressemble à un fragme..."end'---------------#org 0x710A00setvar 0x8005 0x4Ccall 0x720000msgbox 0x8710C00 MSG_FACE '"Au contact de la pierre\nGRAVALANC..."end'---------------#org 0x720000callasm 0x87105C1callasm 0x8711201callasm 0x8710761end'---------' Strings'---------#org 0x710B00= Cette pierre ressemble à un fragment de GROLEM.#org 0x710C00= Au contact de la pierre\nGRAVALANCH réagit. Comment?\lMon GRAVALANCH c'est transformé\nen GROLEM.
Et si je veut encore changer l’espèce d'un pokémon dans un autre script j'aurais juste à faire:
setvar 0x8005 0xXX
call 0x720000
[/spoiler]
Je n'ajoute pas sa dans le tuto parce-que je pense que sa peut en embrouillez certains mais je voulait quand même en parler.
Hey, sépakon du tout ça Par contre, tu les places dans un script alakon que tu fous n'importe où ou il fera pas chier, c'est ça?
hremeraude - 7 mars 2013 à 22:18
Merci pour avoir mis emeraude je testerais ça demain
yushi56 - 8 mars 2013 à 16:26
pas mal ca à l'air tres bien :D
Groud - 8 mars 2013 à 21:17
J'édit ton post pour rajouter la partie sur la simplification de script, mais compte sur moi pour te faire passer à la postérité en postant ton tutorial sur PT à ton nom dès que j'en ai la possibilité
TheCaptainSnow - 8 mars 2013 à 21:45
Merci à toi
J'editerais ce que rajouter plus tard parce qu'il manque un petit truc pour que ce soit correct.
La je peux pas comme je suis sur portable.
hremeraude - 16 mars 2013 à 12:15
Si j'ai bien compris, faut insérer les 3 routines dans le jeu avec XSE,
Ce que je ne comprends pas :
callasm 0x08(offset JPAN 1 + 1)
setvar 0x8005 0xno nouveau pokémon (en hexa)
callasm 0x08(offset "ma routine" + 1)
callasm 0x08(offset JPAN 2 + 1)
il faut mettre 0xoffset+1 ?
juste mettre ça ferais en sorte de juste changer l'espece en cliquant quelque part ?
TheCaptainSnow - 16 mars 2013 à 14:14
Heu non, les routine ne sont pas à insérer avec XSE mais avec un editeur hexadecimal.
Ensuite sa:
callasm 0x08(offset JPAN 1 + 1)setvar 0x8005 0xno nouveau pokémon (en hexa)callasm 0x08(offset "ma routine" + 1)callasm 0x08(offset JPAN 2 + 1)
Enfaite c'est cette partie que tu dois mettre dans un script (avec XSE), tu ne doit recopier sa bêtement mais remplacer les offset+1 par ton offset à toi. Par exemple si tu insère la 1ere routine que j'ai donnée à l'offset A0 00 00 tu devra écrire callasm 0x08A00001 dans ton script.
hremeraude - 16 mars 2013 à 20:45
Ok et t'aurais pas le lien d'un éditeur héxadécimal ?