HUBOL ‐ Trainer Sliding Messages & In‐Battle Music Changes - haven1433/HexManiacAdvance GitHub Wiki

Click here for HUBOL's main page. HUBOL is short for "Haven's Unofficial Build of Leon's dynamic Pokémon expansion."

Credits: Defa, DontJoelMe - OceanBlue, and Invis

Instructions

First, add this anchor in free space:

data.cfru.trainerslides[trainerID:data.trainers.stats lastMonSong:songnames firstMonDown<""> lastSwitchIn<""> lastLowHp<"">]1

Legend

  • trainerID: the Trainer from data.trainers.stats
  • lastMonSong: the music played when the last Pokémon enters the battlefield
  • firstMonDown: message shown after the first Pokémon faints
  • lastSwitchIn: message shown when the last Pokémon enters the battlefield
  • lastLowHp: message shown when the last Pokémon has less than or equal to 25% HP

Notes

  • You do not have to set the lastSwitchIn message if you set a music in lastMonSong: they are not tied together.
  • If you set it to mus_dummy or to 65535, the background music will not change.
  • Ideally, you should choose songs with names that start with "mus_vs" or "mus_rs." ("rs" means music from Ruby/Sapphire)

Leave two FF bytes after the table to mark its end.

To add a message, click on the "Create new data" button on the left; if you do not see this button when having the fields set to <F7FFFFFF>, then change them to <null>.

You do not have to set all three messages for each Trainer, you can choose to show only one or two messages. To not show a message, type <null> in the message field, or leave four FF bytes (shown as <F7FFFFFF> in red).

If a Trainer has only one Pokémon in party, the messages lastLowHp and firstMonDown will be shown, while lastSwitchIn will not be shown.

Important

When creating any new message, type \pn at the end of the string: this makes the text stop during battle and wait for player input. If you do not add \pn, the message will disappear immediately as soon as the game finishes printing the text string.

Routine (v1.2)

Add the following routine in free space, and note the offset.

Go to address 1490938, and change 08 4B 1B 68 70 B5 04 00 to 00 4B 18 47 <offset+1>. Also, go to 1490A81, and change D0 to E0.

    ldr   r3, =0x02022B4C @gBattleTypeFlags
    ldr   r3, [r3, #0]
    push  {r4-r6, lr}
    lsl   r5, r0, #0
    lsl   r6, r1, #0
    lsl   r4, r2, #0
    lsl   r3, r3, #28
    bmi   battletypetrainer
false:
    mov   r0, #0
    b     end
battletypetrainer:
    ldr   r3, =0x080751C5 @GetBattleSide
    bl    linker
    cmp   r0, #1
    bne   false
    ldr   r0, slidestable
    ldr   r1, tableend
looptrainerid:
    ldrh  r2, [r0] @.trainerID
    cmp   r2, r1
    beq   false
    cmp   r6, r2
    beq   switchcaseid
    add   r0, r0, #16 @next row
    b     looptrainerid
switchcaseid:
    ldr   r3, =0x02023FC4 @gBattleScripting
    strb  r5, [r3, #23] @.bank
    ldr   r2, empty
    cmp   r4, #1
    beq   slidelastlowhp
    cmp   r4, #0
    beq   slidelastswitchin
    cmp   r4, #2
    bne   false
    ldr   r3, freeram
    mov   r1, #0 @clear last switch-in flag
    strb  r1, [r3]
    ldr   r4, [r0, #4] @firstMonDown
    cmp   r4, #0
    beq   false
    cmp   r4, r2
    beq   false
    mov   r0, #1
    ldr   r3, GetEnemyMonCount
    bl    linker
    lsl   r5, r0, #0
    mov   r0, #0
    ldr   r3, GetEnemyMonCount
    bl    linker
    sub   r0, r0, #1
    cmp   r5, r0
    bne   false
    ldr   r3, gBattleStringLoader
    str   r4, [r3, #0]
    b     true
slidelastswitchin:
    lsl   r4, r0, #0
    mov   r0, #1
    ldr   r3, GetEnemyMonCount
    bl    linker
    ldr   r1, =0x02022B4C @gBattleTypeFlags
    ldr   r1, [r1]
    mov   r2, #1 @BATTLE_TYPE_DOUBLE
    tst   r1, r2
    beq   checksinglebattle
    ldr   r3, freeram
    cmp   r0, #2
    bhi   false @clearflagfordouble
    ldrb  r0, [r3]
    cmp   r0, #0
    beq   setflagfordouble
    mov   r0, #0
    strb  r0, [r3]
    b     false
setflagfordouble:
     mov   r0, #1
     strb  r0, [r3]
     b     setsong
checksinglebattle:
    cmp   r0, #1
    bne   false
setsong:
    ldrh  r0, [r4, #2] @lastMonSong
    cmp   r0, #0
    beq   checkmsg
    ldr   r1, tableend
    cmp   r0, r1
    beq   checkmsg
    ldr   r3, =0x08044091 @PlayMapChosenOrBattleBGM
    bl    linker
checkmsg:
    ldr   r0, [r4, #8] @lastSwitchIn
    cmp   r0, #0
    beq   false
    ldr   r2, empty
    cmp   r0, r2
    beq   false
    ldr   r3, gBattleStringLoader
    str   r0, [r3, #0]
    mov   r0, #1
end:
    pop   {r4-r6, pc}
linker: bx r3
slidelastlowhp:
    ldr   r6, [r0, #12] @lastLowHp
    cmp   r6, #0
    beq   false
    cmp   r6, r2
    beq   false
    mov   r0, #1
    ldr   r3, GetEnemyMonCount
    bl    linker
    cmp   r0, #1
    bne   false
    mov   r2, #88
    mul   r2, r5
    ldr   r3, =0x02023BE4 @gBattleMons
    add   r5, r3, r2
    mov   r2, #100
    ldrh  r3, [r5, #40] @current HP
    cmp   r3, #0
    beq   gotofalse
    ldrh  r1, [r5, #44] @max HP
    lsl   r0, r2, #0
    mul   r0, r3
    ldr   r3, =0x081E460D @udivsi3
    bl    linker
    cmp   r0, #24 @current HP <= 25% max HP
    bls   haslowhp
gotofalse:
    b     false @too far above for conditional branch
haslowhp:
    ldr   r3, =0x0203E038 @gNewBS
    ldr   r3, [r3, #0]
    lsl   r2, r3, #0
    add   r2, r2, #216
    ldrb  r2, [r2, #0]
    cmp   r2, #127
    bhi   gotofalse
    mov   r2, #128
    add   r3, r3, #213
    ldrb  r1, [r3, #3]
    neg   r2, r2
    orr   r2, r1
    strb  r2, [r3, #3]
    ldr   r3, gBattleStringLoader
    str   r6, [r3, #0]
true:
    mov   r0, #1
    b     end
tableend: .word 0x0000FFFF
empty: .word 0xFFFFFFFF
slidestable: .word <data.cfru.trainerslides>
freeram: .word 0x0203B7AB
gBattleStringLoader: .word 0x0203E020
GetEnemyMonCount: .word 0x0951EDBC +1
⚠️ **GitHub.com Fallback** ⚠️