I've worked out how to have the Gen IV Roost effect in Emerald. This is how it is achieved:
1. First, in the battle script for Recover, it checks if the move ID is Roost (by having Recover's script, the AI can use Roost properly). If the move ID is Roost, then it branches to a near identical script that also calls a custom routine
2. The custom routine checks if the attacking Pokémon has Flying type in either of its slots and then changes it to the ??? type (0x9). If it's a pure Flying type, then it will become a pure ??? type.
3. Another custom routine is run at the end of every turn that checks for any ???-type Pokémon, and changes it back to Flying.
Here's how to implement it:
1. First, you need Jambo51's callasm routine for Battle Script Pro. It is found
right here. Despite Jambo writing the routine for FireRed, it works for Emerald too. However, you need to change the "scriptlocation" offset to
0x02024214. Also this is very important, but unlike FireRed, your new command is not going to be 0xF8! Your new command will be 0xF9. It appears that Emerald has an extra battle command, most likely due to the Battle Frontier.
2. Now to get BSP to recognize our new command, open up the folder where BSP is located, and then there should be another folder called "Data". Then you should see a file called, "commands.bsh". Open it up with Notepad, and put this in:
#command callasm 0xF9 0x1 "Offset of routine" 0x4
This might be confusing, but DO NOT change anything in the quotation marks! That's just there to show minor info in BSP's command list. I repeat,
DO NOT CHANGE A SINGLE THING IN THAT QUOTE!!! Also note that if you were using FireRed, your command would be 0xF8, not 0xF9.
3. Now, put in this routine somewhere:
Code:
.text
.align 2
.thumb
.thumb_func
/*What this routine does is check if the attacking PKMN
is Flying-type. It then changes its Flying-type to
the ???-type.*/
GetPkmnType1:
push {r0-r5}
ldr r1, .BattleData
ldr r0, .CurPokeIndex
ldrb r0, [r0]
mov r2, #0x58
mul r2, r0
add r1, #0x21
add r1, r2
ldrb r0, [r1]
ldrb r2, [r1, #0x1]
mov r3, #0x2
cmp r0, r3
beq ChangeType1
cmp r2, r3
beq ChangeType2
b End
ChangeType1:
mov r4, #0x9
strb r4, [r1]
cmp r2, r3
beq ChangeType2
b End
ChangeType2:
mov r4, #0x9
strb r4, [r1, #0x1]
b End
End:
pop {r0-r5}
bx lr
.align 2
.BattleData: .word 0x02024084
.CurPokeIndex: .word 0x0202420B
4. Now open up BSP, and open up Recover's battle script. Replace it with this:
#dynamic 0x9C5CE0
#freespacebyte 0xFF
#org @start
jumpifhalfword 0x0 0x20241EA 0x163 @RoostHandle
attackcanceler
attackstring
ppreduce
setdamageasrestorehalfmaxhp @full 0x1
attackanimation
waitanimation
orword 0x2024280 0x100
graphicalhpupdate 0x1
datahpupdate 0x1
printstring 0x4B
waitmessage 0x40
goto @finish
#org @full
pause 0x20
printstring 0x4C
waitmessage 0x40
goto @finish
#org @finish
setbyte 0x2024488 0x0
cmd49 0x0 0x0
end
#org @RoostHandle
attackcanceler
attackstring
ppreduce
setdamageasrestorehalfmaxhp @fullroost 0x1
attackanimation
waitanimation
orword 0x2024280 0x100
graphicalhpupdate 0x1
datahpupdate 0x1
printstring 0x4B
waitmessage 0x40
jumpiftype2 0x1 0x2 @changetype
goto @finishroost
#org @fullroost
pause 0x20
printstring 0x4C
waitmessage 0x40
goto @finishroost
#org @changetype
callasm 0x(offset of your routine +1)
goto @finishroost
#org @finishroost
setbyte 0x2024488 0x0
cmd49 0x0 0x0
end
A couple things to note: At the top, we have "jumpifhalfword 0x0 0x20241EA 0x163 @RoostHandle".
Replace 0x163 with your move ID for Roost.
Towards the bottom, at "#org @changetype", you see "callasm 0x(offset of your routine +1)". Obviously, put in the offset of the routine we added earlier, but add 0x1 to the offset.
So far, we have made it so that every time a Flying-type Pokémon uses Roost, it will turn into a ???-type. (If it was part-Flying, it would become part-???, and if it was pure-Flying, it would become pure-???).
5. Now we're going to insert another routine. This second routine will be called at the end of every turn and simply checks to see if there are any ???-type Pokémon, and then changes them back to Flying types.
Code:
.text
.align 2
.thumb
.thumb_func
HandlePoke1:
push {r0-r5}
mov r3, #0x9
ldr r1, .Poke1Type
ldrb r0, [r1]
ldrb r2, [r1, #0x1]
cmp r0, r3
beq Poke1ChangeType1
cmp r2, r3
beq Poke1ChangeType2
b HandlePoke2
Poke1ChangeType1:
mov r4, #0x2
strb r4, [r1]
cmp r2, r3
beq Poke1ChangeType2
b HandlePoke2
Poke1ChangeType2:
mov r4, #0x2
strb r4, [r1, #0x1]
b HandlePoke2
HandlePoke2:
ldr r1, .Poke2Type
ldrb r0, [r1]
ldrb r2, [r1, #0x1]
cmp r0, r3
beq Poke2ChangeType1
cmp r2, r3
beq Poke2ChangeType2
b HandlePoke3
Poke2ChangeType1:
mov r4, #0x2
strb r4, [r1]
cmp r2, r3
beq Poke2ChangeType2
b HandlePoke3
Poke2ChangeType2:
mov r4, #0x2
strb r4, [r1, #0x1]
b HandlePoke3
HandlePoke3:
ldr r1, .Poke3Type
ldrb r0, [r1]
ldrb r2, [r1, #0x1]
cmp r0, r3
beq Poke3ChangeType1
cmp r2, r3
beq Poke3ChangeType2
b HandlePoke4
Poke3ChangeType1:
mov r4, #0x2
strb r4, [r1]
cmp r2, r3
beq Poke3ChangeType2
b HandlePoke4
Poke3ChangeType2:
mov r4, #0x2
strb r4, [r1, #0x1]
b HandlePoke4
HandlePoke4:
ldr r1, .Poke4Type
ldrb r0, [r1]
ldrb r2, [r1, #0x1]
cmp r0, r3
beq Poke4ChangeType1
cmp r2, r3
beq Poke4ChangeType2
b End
Poke4ChangeType1:
mov r4, #0x2
strb r4, [r1]
cmp r2, r3
beq Poke4ChangeType2
b End
Poke4ChangeType2:
mov r4, #0x2
strb r4, [r1, #0x1]
b End
End:
pop {r0-r5}
ldr r0, .ReturnAddress
bx r0
.align 2
.Poke1Type: .word 0x020240A5
.Poke2Type: .word 0x020240FD
.Poke3Type: .word 0x02024155
.Poke4Type: .word 0x020241AD
.ReturnAddress: .word 0x080405B1
6. At 0x402A0, change the bytes there to point to where you inserted the
second routine (the one right above).
DO NOT ADD +1 TO THE OFFSET. I REPEAT, DO NOT ADD +1. This is because the code that is executed before this appears to already account for that.
And now we have a fully working Roost with Generation IV's effect, and the AI can use it properly too, since we're using Recover's battle script slot, but the battle script is designed so that Recover will still function separately from Roost.
A couple things to note, this routine replicates the Generation IV effect of Roost where if the user was pure-Flying, it would become ??? type upon using Roost. In Generation V+, a pure-Flying type using Roost would become Normal-type.. If anyone wants to mod my routine to have the Generation V effect, feel free to do so.
Credits:
Chaos Rush
DoesntKnowHowToPlay - for the idea of the method to achieve this
Shiny Quagsire - for suggesting to me that Emerald might have more battle commands than FireRed due to the Battle Frontier
Tchlatli - I looked at his custom Protean code to figure out how to correctly calculate the type offset of the attacking Pokémon
JPAN - his documentation on FireRed battle-related RAM offsets helped me find the Emerald offsets
To verify that it's working properly, here are some useful RAM offsets:
02024084 - Battle Data (check out
this post to see how its structured.)
020240A5 - Your(1) Type 1
020240A6 - Your(1) Type 2
020240FD - Opponent(1) Type 1
020240FE - Opponent(1) Type 2
02024155 - Your(2) Type 1
02024156 - Your(2) Type 2
020241AD - Opponent(2) Type 1
020241AE - Opponent(2) Type 2