Blah
Free supporter
- 1,924
- Posts
- 12
- Years
- Unknown Island
- Seen Feb 19, 2025
R&D on Pokemon Trainer's Interrupting battles:
Before I begin, skip to 5:50 and watch till 5:55 of this video to see what I'm talking about: https://www.youtube.com/watch?v=W609NJs9h-o
I want to implement that in Fire Red. So recently I've been reading, researching and tracking down different routines in battles in FireRed to basically find a point in the game which is run once per turn. Well I found that point. The game seems to have a "turn counter" which is incremented once at the end of each turn at 0x8013CB0
From there I need to call my own routine. A routine whose purpose was simply to check if the opponent was on their last Pokemon, and to check if their last Pokemon is lower than Half health.
In the newer games this, "trainer interrupt" happens 100% in these two conditions vs important NPCs.
So I should do an interrupt at those two stages.
The next problem is knowing which text to execute. The solution to that imo is simple. I decided the best way to do it, is to make a table of pointers to strings, and just use a variable to browse these pointers. (Getting the battle to display this string is another issue in itself).
The last, and probably the biggest problem is the trainer sliding in and out in both of these scenarios.
So right now, what I have done is the main routine that does the check of whether or not to do the trainer sliding process, and a helper function which basically just gives information about the opponents team.
Code for Main:
Spoiler:
Code:
.text
.align 2
.thumb
.thumb_func
@Main function. This checks whether to execute a slide + text and then does it.
@If no slide + text to be executed, restores previous instructions
@Uses a separate called checkPokemon which I wrote
main:
push {r2-r5, lr}
ldr r0, .checkPokemon @check trainer's pokemon
bl checkPokemon
cmp r1, #0x0 @check if last pokemon
bne skip
mov r1, #0x39
mov r3, r0 @save r0
ldr r5, VAR2
cmp r5, #0x0 @if last Pokemon and we haven't displayed text before display
beq text
ldr r2, = (0x803FBE8 + 1) @check if last Pokemon less than half
bl linkerTwo
mov r4, r0 @r4 = currentHP
mov r0, r3
mov r1, #3A
bl linkerTwo
mov r1, #0x2
mul r4, r4, r1
cmp r0, r4
ble skip @if more than half, no text display
text:
@slide trainer (todo)
@
@below is the text, for some reason it appears to come on screen delayed :/
@
mov r0, #0x1 @set a flag (cover cases player spamming growl, doing no dmg..ect)
strb r0, [r5]
ldr r1, .VAR @get pointer number var from table. Var is index
ldrb r1, [r1]
ldr r0, .TABLE
lsl r1, #0x2
add r0, r0, r1
ldr r0, [r0] @r0 contains pointer
mov r1, #0x0 @check that it's a valid pointer, not free space
ldrb r0, [r1]
cmp r1, #0xFF
beq skip
ldr r1, =(0x80D77F4 +1) @battle text functions
bl linkerOne
mov r1, #0x18
ldr r2, =(0x80D87BC +1)
bl linkerTwo
@unslide trainer (todo)
skip:
ldr r1, = 0x3004F90
ldrb r0, [r1, #0x13]
cmp r0, #0xFE
bhi replacer
add r0, #0x1
strb r0, [r1, #0x13]
replacer:
ldr r2, = (0x8013CBC + 1)
linkerTwo:
bx r2
linkerOne:
bx r1
.align 2
.VAR:
.word 0x020270B4 + (0x8001 * 2)
.VAR2:
.word 0x020270B4 + (0x8002 * 2)
.TABLE:
.word (0x8xxxxxx) @table of string pointers
.checkPokemon
.word (0x8xxxxxx) @need to insert still
Here's the checkPokemon used in the routine above:
Spoiler:
Code:
.text
.align 2
.thumb
.thumb_func
@Loops trainers pokemon, returns amount alive
@if last pokemon, return's that pokemon's address in r0
@else gives scalar number of pokemon alive in r0
@ready for checking last pokemon is half HP flag
main:
push {lr}
mov r3, #0x0 @pokeslot zero
mov r2, r3 @r2 holds number of alive pokemon
b loop
loop:
cmp r3, #0x5 @if all pokemon looped through, finish
bge finalizeReturn
ldr r0, =(0x202402C) @get pokemon at slot
mov r1, #0x64
mul r1, r1, r3
add r0, r0, r1
mov r1, #0x39
ldr r4, =(0x803FBE8 +1)
bl caller
cmp r0, #0x0 @check current HP zero
bne increment @if not zero increment r2
add r3, r3, #0x1 @go next slot
b loop
increment:
add r2, r2, #0x1
add r3, r3, #0x1 @also have to do slot increment
mov r5, r0 @store in r5, last alive pokemon's location
b loop
caller:
bx r4
finalizeReturn:
cmp r2, #0x1 @check if only 1 alive
bne end
mov r0, r5 @if 1 pokemon alive it must be in r5, put it in r0
mov r1, #0x0 @r1 is a boolean r1: 0 means 1 alive pokemon
pop {pc}
end
mov r0, r2 @r0 = number of alive pokemon
mov r1, #0x1 @r1: 1 means more than 1 alive
pop {pc}
.align 2
As you can tell, all I have to really do is to "Slide trainer" and "Unslide" the trainer in the battle. Followed by, fixing the text glitch I'm getting.
Basically the text comes out at the same time as the normal battle text. And one is overwriting pieces of the other, which causes this:
![[PokeCommunity.com] Trainer interrupting battles [PokeCommunity.com] Trainer interrupting battles](https://i.imgur.com/mKezo5B.png?1)
I have looked into battlescripts, but honestly, I don't know if I really even need to use one. Maybe using one would help with the text appearing, I haven't tested (and don't have experience on it to really know)
The reason I'm making the thread is to seek help/expertise of someone who's done this kind of thing before. Or perhaps knows how. Currently I'm at a wall, and am not quite sure what to do.
Things I've tried (though maybe unsuccessfully):
calling 0803227C: trainer enter field
Using Oak's tutorial text routines
If you have questions, optimizations, suggestions or solutions please do voice them :)