Trainer 781
Guest
- 0
- Posts
Eh, why not? Any way to test it? A patch? YAFRH?
It is not there in YAFRH. If the source (or a GBA ROM having protean) is not available, there is no way of testing it.
Eh, why not? Any way to test it? A patch? YAFRH?
A little improvement of Tlachtli's routine for Protean. This one is for Emerald :
Now the user turn systematically to mono type, unless he's asleep or can't move because paralyzed etc. Weather ball/hidden power are correctly handled too.
Thank's to touched for the fixing bug and display correctly the [Pokemon] transformed into [X] Type
.text
.align 2
.thumb
.thumb_func
.global protean
AbilityBufferUser:
push {r0-r5}
ldr r0, .Bank
ldrb r0, [r0]
mov r1, #0x58
ldr r2, .BattleData
mul r0, r1
add r2, r0, r2
ldrb r0, [r2]
ProteanCheck:
cmp r0, #0xA9
bne Return
BufferType:
ldrb r0, [r2, #0x1]
ldrb r1, [r2, #0x2]
CheckVariableTypeMoves:
ldr r4, .CheckTypeLoc
ldr r4, [r4]
ldrb r4, [r4, #0x13]
mov r5, #0x3F
and r4, r5
cmp r4, #0x0
beq CheckMove
b CheckSameType
CheckMove:
ldr r3, .MoveIndex
ldrh r3, [r3]
cmp r3, #0xA5
beq Return
GetMoveType:
ldr r4, .MoveData
mov r5, #0xC
mul r5, r3
add r4, r4, r5
ldrb r4, [r4, #0x2]
CheckSameType:
cmp r0, r4
bne ChangeType
cmp r1, r4
beq Return
ChangeType:
strb r4, [r2, #0x1]
strb r4, [r2, #0x2]
ldr r3, =0xFF0003FD
lsl r4, #0x10
add r3, r4
ldr r0, .BufferTypeLoc
str r3, [r0]
BufferMessage:
mov r0, #0x49
ldr r1, .Bank
ldrb r1, [r1]
bl DisplayMessage
Return:
pop {r0-r5}
ldrb r1, [r0]
str r2, [sp]
mov r0, #0x2
mov r2, #0x0
ldr r3, .Return
bx r3
DisplayMessage:
ldr r2, .DisplayMessageBL
bx r2
.align 2
.Bank: .word 0x02023D6B
.BattleData: .word 0x02023C04
.MoveIndex: .word 0x02023D4A
.CheckTypeLoc: .word 0x02023FE8
.MoveData: .word 0x8250C04
.BufferTypeLoc: .word 0x02022AB8
.Return: .word 0x0801D7E1
.DisplayMessageBL: .word 0x080173AD
*Insert 00 49 08 47 xx xx xx 08 at 1D7D8
.text
.align 2
.thumb
.thumb_func
.global protean
AbilityBufferUser:
push {r0-r5}
ldr r0, .Bank
ldrb r0, [r0]
mov r1, #0x58
ldr r2, .BattleData
mul r0, r1
add r2, r0, r2
ldrb r0, [r2]
ProteanCheck:
cmp r0, #0xA9
bne Return
BufferType:
ldrb r0, [r2, #0x1]
ldrb r1, [r2, #0x2]
CheckVariableTypeMoves:
ldr r4, .CheckTypeLoc
ldr r4, [r4]
ldrb r4, [r4, #0x13]
mov r5, #0x3F
and r4, r5
cmp r4, #0x0
beq CheckMove
b CheckSameType
CheckMove:
ldr r3, .MoveIndex
ldrh r3, [r3]
cmp r3, #0xA5
beq Return
GetMoveType:
ldr r4, .MoveData
mov r5, #0xC
mul r5, r3
add r4, r4, r5
ldrb r4, [r4, #0x2]
CheckSameType:
cmp r0, r4
bne ChangeType
cmp r1, r4
beq Return
ChangeType:
strb r4, [r2, #0x1]
strb r4, [r2, #0x2]
ldr r3, =0xFF0003FD
lsl r4, #0x10
add r3, r4
ldr r0, .BufferTypeLoc
str r3, [r0]
BufferMessage:
mov r0, #0x49
ldr r1, .Bank
ldrb r1, [r1]
bl DisplayMessage
Return:
pop {r0-r5}
ldrb r1, [r0]
str r2, [sp]
mov r0, #0x2
mov r2, #0x0
ldr r3, .Return
bx r3
DisplayMessage:
ldr r2, .DisplayMessageBL
bx r2
.align 2
.Bank: .word 0x0202420B
.BattleData: .word 0x020240A4
.MoveIndex: .word 0x020241EA
.CheckTypeLoc: .word 0x0202449C
.MoveData: .word 0x831C898
.BufferTypeLoc: .word 0x02022F58
.Return: .word 0x0804607D
.DisplayMessageBL: .word 0x0803F965
*Insert 00 49 08 47 xx xx xx 08 at 46074
Great work both of you! Also thanks for sharing the string display bl.
The ability looks like it will work properly, just leaving a few corner cases which I will mention:
1. .CheckTypeLoc should not be specified directly because it is Dynamically Allocated (it rarely changes but has a chance to change). The type should be loaded via the x2023FE8 offset i.e. ldr r3, =0x02023FE8; ldr r3, [r3, 0x13]
2. Also, shouldn't the dynamic type be generalized (not just for Weatherball and Hidden Power but for new Moves like Natural Gift and possibly for some future Generation VII moves that might come).
The idea is to load the dynamic type, then 'and'ing it with #0x3F (this automatically cover's subtracting C0 or 80 from r3) Then if results comes out to be zero check the type of the move from the move table. (The vanilla type effectiveness routine does this)
This way there is no need to handle different type changing moves differently.
3. Also, by directly returning instead of checking the move table, if the register is zero, we won't get a normal Weather Ball transforming the Protean mon to a Normal Type.
Really?! <3 Ah you've just made my day :DI will actually be including all the abilities you want in the future, though I can't say when.
As Kleenex said, there is no effects table, just the move names and descriptions which Sky High has written a tutorial about (linked in the first post).
But you will need a Battle Script Editor (get BSP), a Hex Editor, and some sort of Ability Name and Description editor if you aren't comfortable in writing names and descriptions in Hex.
Reserving this post for the absorb Type damage abilities such as Dry Skin, Sap Sipper etc.
What is it at 46074 and what makes it ok to overwrite it?
.
EDIT: I've briefly tested kleenexfeu's routine, it doesn't show the message if the user already has the type of the move it's using (in this case Greninja (Water/Dark) using Scald), not sure if it changes into mono-type, tho.
Also please note that Struggle don't trigger Protean, if it already is then please ignore this for I haven't tested yet
Really?! <3 Ah you've just made my day :D
I shall wait patiently for your releases and leave adding these abilities until the end!
Adding the abilities into the game is straight forward it's just learning ASM to make the abilities... it's so simple it's difficult xD
Hey, I'm having some issues getting Protean to work.
Firstly, it refused to compile for a bit due to having two sections titled "GetMoveType"; it compiled after I changed one of them to GetMoveType2, but I don't know if that changed anything.
Secondly, whenever something with Protean uses an attack, the game freezes. I don't know why precisely this happens (I tried putting both the address and the addres +1 in reverse hex at 1D7D8), but might it have something to do with me using MrDollSteak's rombase? The MoveIndex, MoveData, and possibly the things related to type might need to be changed.
08046074 is a part of the attack canceler, we branching from here and make the changing/checks accordingly to the situation.
And what makes it ok to be overwritten?
Great work both of you! Also thanks for sharing the string display bl.
The ability looks like it will work properly, just leaving a few corner cases which I will mention:
1. .CheckTypeLoc should not be specified directly because it is Dynamically Allocated (it rarely changes but has a chance to change). The type should be loaded via the x2023FE8 offset i.e. ldr r3, =0x02023FE8; ldr r3, [r3, 0x13]
Thanks for that, I changed it in my routine
2. Also, shouldn't the dynamic type be generalized (not just for Weatherball and Hidden Power but for new Moves like Natural Gift and possibly for some future Generation VII moves that might come).
The idea is to load the dynamic type, then 'and'ing it with #0x3F (this automatically cover's subtracting C0 or 80 from r3) Then if results comes out to be zero check the type of the move from the move table. (The vanilla type effectiveness routine does this)
This way there is no need to handle different type changing moves differently.
Makes sense. I saw that in the original routine but I didn't understand how it worked, that's why I choose to substract. Now edited.
3. Also, by directly returning instead of checking the move table, if the register is zero, we won't get a normal Weather Ball transforming the Protean mon to a Normal Type.
Actually it's never 0 when those move are used, it was for safety. When weather ball is normal type, 0x80 is used and hidden power cannot be normal. but I changed that too. It's cleaner, thanks again
Good work Kleenexfeu! I've edited your routine to touch up the mistakes, as well as to optimise it, and finally port it to Fire Red.
Just need to handle Struggle as Germaniac said, then this routine is set (should not activate protean) and also you do not need to check for Weather Ball or Hidden Power. Just check the dynamic type then the move table.
Also, for toxic (if you are using mamamama's Battle Script) and Curse, the order of attackercanceler and jumpiftype command in their BS should be swapped. Though curse can be leaved as it is unless there is a Protean pokemon learning it.
Sturdy code here[/SPOILER][/SPOILER]
Curse is almost impossible to handle in double. You have to choose the target when your ghost type, and before using it, your not ghost type. Just have to edit curse battlescript. EDIT : Done, but you can't chose your target.
Toxic works already with mamamama's script.
Struggle is handled too, I'll just edit the individual check. EDIT : Done
The work you guys have been doing here is amazing, so I'll sticky this. Keep it up!
I know that Sturdy isn't complete yet but I wanted to get you know about something. Pokemon with that ability cannot be taken out with full hp no matter what. What I mean is, if its HP goes down to 1 HP and then he hits itself in confusion or takes poison/burn damage it still lives(so it actually doesn't take any damage from it at all). If you were aware of that, sorry.
.text
.text
.align 2
.thumb
.thumb_func
.global victorystar
CheckBattleType:
ldr r0, .BattleType
ldrb r0, [r0]
mov r1, #0x1
and r0, r1
cmp r0, #0x0
bne DoubleBattle
SingleBattle:
ldr r0, .Bank
ldrb r0, [r0]
mov r5, #0x58
mul r0, r5
add r0, r0, r7
add r0, #0x20
ldrb r0, [r0]
b VictoryStarCheck
DoubleBattle:
ldr r0, .Bank
ldrb r0, [r0]
and r0, r1
cmp r0, #0x0
bne CheckFoeTeam
CheckUserTeam:
mov r0, #0x0
b DoupleLoop
CheckFoeTeam:
mov r0, #0x1
DoupleLoop:
mov r5, #0x58
mul r0, r5
add r1, r0, r7
add r1, #0x20
ldrb r0, [r1]
cmp r0, #0xA3
beq VictoryStar
add r1, r1, #0xB0
ldrb r0, [r1]
VictoryStarCheck:
cmp r0, #0xA3
bne BufferAbility
VictoryStar:
mov r0, #0x6E
mov r1, #0x64
mul r0, r4
bl Divide
lsl r0, r0, #0x10
lsr r4, r0, #0x10
BufferAbility:
ldr r0, .Bank
ldrb r0, [r0]
mov r5, #0x58
mul r0, r5
add r0, r0, r7
add r0, #0x20
ldrb r0, [r0]
CompoundEyesCheck:
cmp r0, #0xE
bne Return
CompoundEyes:
ldr r0, .Return
bx r0
Return:
ldr r0, .Return2
bx r0
Divide:
ldr r2, .DivideBL
bx r2
.align 2
.BattleType: .word 0x2022B4C
.Bank: .word 0x02023D6B
.Return: .word 0x0801E041
.Return2: .word 0x0801E051
.DivideBL: .word 0x081E4019
Insert 01 48 00 47 00 00 xx xx xx 08 at 0801E02E
.text
.text
.align 2
.thumb
.thumb_func
.global victorystar
CheckBattleType:
ldr r0, .BattleType
ldrb r0, [r0]
mov r1, #0x1
and r0, r1
cmp r0, #0x0
bne DoubleBattle
SingleBattle:
ldr r0, .Bank
ldrb r0, [r0]
mov r5, #0x58
mul r0, r5
add r0, r0, r7
add r0, #0x20
ldrb r0, [r0]
b VictoryStarCheck
DoubleBattle:
ldr r0, .Bank
ldrb r0, [r0]
and r0, r1
cmp r0, #0x0
bne CheckFoeTeam
CheckUserTeam:
mov r0, #0x0
b DoupleLoop
CheckFoeTeam:
mov r0, #0x1
DoupleLoop:
mov r5, #0x58
mul r0, r5
add r1, r0, r7
add r1, #0x20
ldrb r0, [r1]
cmp r0, #0xA3
beq VictoryStar
add r1, r1, #0xB0
ldrb r0, [r1]
VictoryStarCheck:
cmp r0, #0xA3
bne BufferAbility
VictoryStar:
mov r0, #0x6E
mov r1, #0x64
mul r0, r4
bl Divide
lsl r0, r0, #0x10
lsr r4, r0, #0x10
BufferAbility:
ldr r0, .Bank
ldrb r0, [r0]
mov r5, #0x58
mul r0, r5
add r0, r0, r7
add r0, #0x20
ldrb r0, [r0]
CompoundEyesCheck:
cmp r0, #0xE
bne Return
CompoundEyes:
ldr r0, .Return
bx r0
Return:
ldr r0, .Return2
bx r0
Divide:
ldr r2, .DivideBL
bx r2
.align 2
.BattleType: .word 0x2022FEC
.Bank: .word 0x0202420B
.Return: .word 0x080468651
.Return2: .word 0x08046861
.DivideBL: .word 0x082E7541
Insert 01 48 00 47 00 00 xx xx xx 08 at 0804683E
.text
.text
.align 2
.thumb
.thumb_func
.global wonderskin
BufferAbility:
ldr r0, .TargetBank
ldrb r0, [r0]
mul r0, r2
add r0, r0, r3
add r0, #0x20
ldrb r0, [r0]
ldrb r3, [r7, #0x3]
CheckWonderSkin:
cmp r0, #0x94
bne Return
WonderSkin:
ldrb r0, [r7, #0xA]
cmp r0, #0x2
bne Return
cmp r3, #0x32
ble Return
mov r3, #0x32
Return:
mov r8, r3
mov r0, #0x0
str r0, [sp]
mov r0, #0x13
ldr r1, .Return
bx r1
.align 2
.TargetBank: .word 0x02023D6C
.Return: .word 0x0801DFD5
Insert 01 48 00 47 00 00 xx xx xx 08 at 0801DFCA
.text
.text
.align 2
.thumb
.thumb_func
.global wonderskin
BufferAbility:
ldr r0, .TargetBank
ldrb r0, [r0]
mul r0, r2
add r0, r0, r3
add r0, #0x20
ldrb r0, [r0]
ldrb r3, [r7, #0x3]
CheckWonderSkin:
cmp r0, #0x94
bne Return
WonderSkin:
ldrb r0, [r7, #0xA]
cmp r0, #0x2
bne Return
cmp r3, #0x32
ble Return
mov r3, #0x32
Return:
mov r8, r3
mov r0, #0x0
str r0, [sp]
mov r0, #0x13
ldr r1, .Return
bx r1
.align 2
.TargetBank: .word 0x0202420C
.Return: .word 0x080467E5
Insert 01 48 00 47 00 00 xx xx xx 08 at 080467DA
.text
.text
.align 2
.thumb
.thumb_func
.global snowcloak
BufferAbility:
ldr r0, .TargetBank
ldrb r0, [r0]
mul r0, r5
add r0, r0, r7
add r0, #0x20
ldrb r0, [r0]
SandVeilCheck:
cmp r0, #0x8
bne SnowCloakCheck
SandVeil:
ldr r0, .Return
bx r0
SnowCloakCheck:
cmp r0, #0x52
bne Return
SnowCloak:
ldr r0, .WeatherLoc
ldrh r1, [r0]
mov r0, #0x18
lsl r0, r0, #0x4
and r0, r1
cmp r0, #0x0
beq Return
ldr r1, .Return2
bx r1
Return:
ldr r0, .Return3
bx r0
.align 2
.TargetBank: .word 0x02023D6C
.Return: .word 0x0801E08D
.WeatherLoc: .word 0x02023F1C
.Return2: .word 0x0801E099
.Return3: .word 0x0801E0A9
Insert 00 48 00 47 xx xx xx 08 at 0801E07C
.text
.text
.align 2
.thumb
.thumb_func
.global preventhaildamage
BufferAbility:
mov r0, r2
add r0, #0x20
ldrb r0, [r0]
SnowCloakCheck:
cmp r0, #0x52
beq NoDamage
MagicGuardCheck:
cmp r0, #0x63
beq NoDamage
IceBodyCheck:
cmp r0, #0x74
beq NoDamage
OvercoatCheck:
cmp r0, #0x8F
beq NoDamage
BufferPrimaryType:
mov r0, r2
add r0, #0x21
ldrb r0, [r0]
CheckPrimaryTypeIce:
cmp r0, #0xF
bne Return
NoDamage:
ldr r1, .Return
bx r1
Return:
ldr r0, .Return2
bx r0
.align 2
.Return: .word 0x08028E3D
.Return2: .word 0x08028DFB
Insert 00 48 00 47 xx xx xx 08 at 08028DF0
.text
.text
.align 2
.thumb
.thumb_func
.global snowcloak
BufferAbility:
ldr r0, .TargetBank
ldrb r0, [r0]
mul r0, r5
add r0, r0, r7
add r0, #0x20
ldrb r0, [r0]
SandVeilCheck:
cmp r0, #0x8
bne SnowCloakCheck
SandVeil:
ldr r0, .Return
bx r0
SnowCloakCheck:
cmp r0, #0x52
bne Return
SnowCloak:
ldr r0, .WeatherLoc
ldrh r1, [r0]
mov r0, #0x18
lsl r0, r0, #0x4
and r0, r1
cmp r0, #0x0
beq Return
ldr r1, .Return2
bx r1
Return:
ldr r0, .Return3
bx r0
.align 2
.TargetBank: .word 0x0202420C
.Return: .word 0x0804689D
.WeatherLoc: .word 0x020243CC
.Return2: .word 0x080468A9
.Return3: .word 0x080468B9
Insert 00 48 00 47 xx xx xx 08 at 0804688C
.text
.text
.align 2
.thumb
.thumb_func
.global preventhaildamage
BufferAbility:
mov r0, r2
add r0, #0x20
ldrb r0, [r0]
SnowCloakCheck:
cmp r0, #0x52
beq NoDamage
MagicGuardCheck:
cmp r0, #0x63
beq NoDamage
IceBodyCheck:
cmp r0, #0x74
beq NoDamage
OvercoatCheck:
cmp r0, #0x8F
beq NoDamage
BufferPrimaryType:
mov r0, r2
add r0, #0x21
ldrb r0, [r0]
CheckPrimaryTypeIce:
cmp r0, #0xF
bne Return
NoDamage:
ldr r1, .Return
bx r1
Return:
ldr r0, .Return2
bx r0
.align 2
.Return: .word 0x08051C3D
.Return2: .word 0x08051BFB
Insert 00 48 00 47 xx xx xx 08 at 08051BF0
.text
.text
.align 2
.thumb
.thumb_func
.global tangledfeet
BufferAbility:
mov r0, r2
mul r0, r7
mov r3, r9
add r1, r0, r3
mov r0, r1
add r0, #0x20
ldrb r0, [r0]
TangledFeetCheck:
cmp r0, #0x4E
bne Return
mov r0, r1
add r0, #0x50
ldr r0, [r0]
cmp r0, #0x0
beq Return
EvasionBoost:
lsl r0, r4, #0x2
add r0, r0, r4
lsl r0, r0, #0x4
mov r1, #0x64
bl Divide
lsl r0, r0, #0x10
lsr r4, r0, #0x10
Return:
ldr r0, .Return
bx r0
Divide:
ldr r2, .DivideBL
bx r2
.align 2
.Return: .word 0x0801E0E5
.DivideBL: .word 0x081E4019
Insert 00 49 08 47 xx xx xx 08 at 0801E0DC
.text
.text
.align 2
.thumb
.thumb_func
.global tangledfeet
BufferAbility:
mov r0, r2
mul r0, r7
mov r3, r9
add r1, r0, r3
mov r0, r1
add r0, #0x20
ldrb r0, [r0]
TangledFeetCheck:
cmp r0, #0x4E
bne Return
mov r0, r1
add r0, #0x50
ldr r0, [r0]
cmp r0, #0x0
beq Return
EvasionBoost:
lsl r0, r4, #0x2
add r0, r0, r4
lsl r0, r0, #0x4
mov r1, #0x64
bl Divide
lsl r0, r0, #0x10
lsr r4, r0, #0x10
Return:
ldr r0, .Return
bx r0
Divide:
ldr r2, .DivideBL
bx r2
.align 2
.Return: .word 0x080468F5
.DivideBL: .word 0x082E7541
Insert 00 49 08 47 xx xx xx 08 at 080468EC
I'll edit the post I made with your routines to match this.
Also I wouldn't use Mamamama's Toxic Battle Script, there's no real need, I've included it in the 'victory star / wonder skin' routine along with Blizzard (in hail) and a few other moves.
0F 10 11 12 13 14 15 27 28 29 2A 2B 2C 2D 8F 90 91 92 93 94 95 A7 A8 A9 AA AB AC AD 16 17 18 19 1A 1B 1C 2E 2F 30 31 32 33 34 96 97 98 99 9A 9B 9C AE AF B0 B1 B2 B3 B4
16 17 18 19 1A 1B 1C 2E 2F 30 31 32 33 34 96 97 98 99 9A 9B 9C AE AF B0 B1 B2 B3 B4 0F 10 11 12 13 14 15 27 28 29 2A 2B 2C 2D 8F 90 91 92 93 94 95 A7 A8 A9 AA AB AC AD
4F 50 51 52 53 54 55 67 68 69 6A 6B 6C 6D CF D0 D1 D2 D3 D4 D5 E7 E8 E9 EA EB EC ED 56 57 58 59 5A 5B 5C 6E 6F 70 71 72 73 74 D6 D7 D8 D9 DA DB DC EE EF F0 F1 F2 F3 F4
56 57 58 59 5A 5B 5C 6E 6F 70 71 72 73 74 D6 D7 D8 D9 DA DB DC EE EF F0 F1 F2 F3 F4 4F 50 51 52 53 54 55 67 68 69 6A 6B 6C 6D CF D0 D1 D2 D3 D4 D5 E7 E8 E9 EA EB EC ED
.text
.align 2
.thumb
.thumb_func
.global contraryeasypart
CheckAppliedStats:
push {r0-r2}
ldrb r1, [r2, #1]
mov r2, #0x40
and r2, r1
cmp r2, #0
beq Target
ldr r0, BankUser
b CheckContrary
Target:
ldr r0, BankTarget
CheckContrary:
ldrb r0, [r0]
ldr r1, BattleDataAbility
mov r2, #0x58
mul r0, r2
add r1, r0
ldrb r0, [r1]
cmp r0, #[I][U]0x7F[/U][/I] /*ability contrary*/
bne ClassicRoutine
InversesStats:
pop {r0-r2}
orr r3, r0
ldr r0, ByteStatChangeClassic
ldrb r4, [r0, #0x1A]
cmp r4, #0x81
bge Substract
add r4, #0x80
b Return
Substract:
sub r4, #0x80
b Return
ClassicRoutine:
pop {r0-r2}
orr r3, r0
ldr r0, ByteStatChangeClassic
ldrb r4, [r0, #0x1A]
Return:
strb r4, [r0, #0x1A]
mov r0, #0xF0
and r0, r4
lsl r0, r0, #0x18
asr r0, r0, #0x18
ldr r1, Back
bx r1
.align 2
ByteStatChangeClassic: .word 0x02024474
BankUser: .word 0x0202420B
BankTarget: .word 0x0202420C
BattleDataAbility: .word 0x020240A4
CurrentBS: .word 0x02024214
Back: .word 0x08050EC6+1
/* 00 4C 20 47 xx+1 xx xx 08 at 08050EB8*/
.text
.align 2
.thumb
.thumb_func
.global contraryannoyingpart
Start:
ldr r3, ByteStatChange
ldrb r2, [r3, #3]
CheckEffect:
push {r0, r1, r3, r4, r5}
mov r1, #0
mov r3, #0
mov r5, #0
LoadTableTarget:
ldr r0, TargetTable
add r3, r0, r1
ldrb r0, [r3]
mov r4, #0xFF
cmp r0, r4
beq LoadTableUser
cmp r0, r2
beq ContraryTargetCheck
mov r3, #0
add r1, #1
add r5, #1
b LoadTableTarget
ContraryTargetCheck:
ldr r1, BankTarget
ldrb r1, [r1]
ldr r3, BattleDataAbility
mov r4, #0x58
mul r1, r4
add r3, r1
ldrb r1, [r3]
cmp r1, #[I][U]0x7F[/U][/I] /*Ability contrary*/
bne Unapplicable
ldr r0, TableTargetContrary
add r0, r5
ldrb r0, [r0]
mov r2, r0
b ReturnSuccess
LoadTableUser:
mov r1, #0
mov r3, #0
mov r5, #0
Reload:
ldr r0, UserTable
add r3, r0, r1
ldrb r0, [r3]
mov r4, #0xFF
cmp r0, r4
beq Unapplicable
cmp r0, r2
beq ContraryUserCheck
mov r3, #0
add r1, #1
add r5, #1
b Reload
ContraryUserCheck:
ldr r1, BankUser
ldrb r1, [r1]
ldr r3, BattleDataAbility
mov r4, #0x58
mul r1, r4
add r3, r1
ldrb r1, [r3]
cmp r1, #[I][U]0x7F[/U][/I] /*Ability contrary*/
bne Unapplicable
ldr r0, TableUserContrary
add r0, r5
ldrb r0, [r0]
mov r2, r0
ReturnSuccess:
ldr r3, ByteStatChange
strb r2, [r3, #3]
pop {r0, r1, r3, r4, r5}
ldr r3, ByteStatChange
ldrb r2, [r3, #3]
mov r0, #0x80
and r0, r2
ldr r1, =(0x08049A28+1)
bx r1
Unapplicable:
pop {r0, r1, r3, r4, r5}
ClassicRoutine:
mov r0, #0x80
and r0, r2
ldr r1, =(0x08049A28+1)
bx r1
.align 2
TargetTable: .word 0x08A1F3F0 /*Change it accordingly to your table*/
TableTargetContrary: .word 0x08A1F470 /*Change it accordingly to your table*/
UserTable: .word 0x08A1F4F0 /*Change it accordingly to your table*/
TableUserContrary: .word 0x08A1F570 /*Change it accordingly to your table*/
BankUser: .word 0x0202420B
BankTarget: .word 0x0202420C
BattleDataAbility: .word 0x020240A4
ByteStatChange: .word 0x02024332
/*00 4B 18 47 xx+1 xx xx 08 at 08049A20*/
.text
.align 2
.thumb
.thumb_func
.global jumpifstats
Start:
ldr r3, [r4]
mov r1, #0x58
mul r0, r1
ldrb r1, [r3, #3]
push {r0}
add r0, r2
add r0, #0x20
ldrb r0, [r0]
cmp r0, #[I][U]0x7F[/U][/I] /*Index number of your ability contrary*/
beq Inverse
pop {r0}
add r0, r0, r1
add r2, #0x18
add r0, r0, r2
ldrb r2, [r0]
ldrb r0, [r3, #2]
Back:
ldr r1, Return
bx r1
Inverse:
pop {r0}
add r0, r0, r1
add r2, #0x18
add r0, r0, r2
ldrb r2, [r0]
cmp r2, #6
beq Back
mov r0, #0xC
sub r0, r2
mov r2, r0
ldrb r0, [r3, #2]
cmp r0, #2
beq Three
cmp r0, #3
beq Two
b Back
Two:
mov r0, #2
b Back
Three:
mov r0, #3
b Back
.align 2
Return: .word 0x0804A17A+1
/*00 4B 18 47 xx+1 xx xx 08 at 0804A168*/
.text
.align 2
.thumb
.thumb_func
.global playstatschangeanimation
Start:
ldr r4, BattleData
mov r1, #0x58
mul r0, r1
add r0, r4
add r0, #0x20
ldrb r0, [r0]
cmp r0, #[I][U]0x7F[/U][/I] /*Index number of your ability contrary*/
beq Inverse
ldr r0, [r5]
ldrb r4, [r0, #2]
ldrb r1, [r0, #3]
Returning:
mov r0, #1
ldr r3, Return
bx r3
Inverse:
ldr r0, [r5]
ldrb r4, [r0, #2]
ldrb r1, [r0, #3]
mov r0, #1
and r0, r1
cmp r0, #0
beq Add
sub r1, #1
b Returning
Add:
add r1, #1
b Returning
.align 2
Return: .word 0x0804BA04+1
BattleData: .word 0x02024084
/*00 49 08 47 xx+1 xx xx 08 at 0804B9FC*/
Battle Script at XX YY ZZ:
#include abilities.bsh
#dynamic 0xYourOffset
#freespace 0xFF
#org @start
jumpifsecondarystatus 0x0 0x1000000 0x82DB510
jumpifability 0x0 0x1D 0x82DB51C
jumpifability 0x0 0x34 0x82DB51C
jumpifability 0x0 0x49 0x82DB51C
statbuffchange 0x21 false 0x82DB510
jumpifbyte 0x2 0x2024337 0x1 0x82DB510
cmd47
playanimation 0x0 0x1 0x2024484
jumpifability 0x0 [I][U]0x7F[/U][/I] @othermessage //0x7F = index number of your ability contrary
printstring 0xCD
waitmessage 0x40
goto 0x2DB510
#org @othermessage
setword 0x203E320 0x8[I][U]QQQQQQ[/U][/I]
printstring 0x184
waitmessage 0x40
goto 0x2DB510
At 082DB4D2
28 ZZ YY XX 08
At QQ QQ QQ:
FD 10 B4 E7 00 D5 E8 E8 D5 D7 DF 00 E6 E3 E7 D9 AB
"Buffer's attack rose"
.text
.align 2
.thumb
.thumb_func
.global swaggeraltering
Start:
push {r1}
add r1, #0x20
ldrb r1, [r1]
cmp r1, #[I][U]0x7F[/U][/I] /*Index number of your ability Contrary*/
beq Contrary
pop {r1}
add r1, #0x18
add r0, r0, r1
ldrb r0, [r0]
lsl r0, r0, #0x18
ldr r1, Back
bx r1
Contrary:
pop {r1}
add r1, #0x18
add r0, r0, r1
ldrb r0, [r0]
lsl r0, r0, #0x18
asr r0, r0, #0x18
cmp r0, #0x0
bne CanPlay
ldr r1, BackPlusTwo
bx r1
CanPlay:
ldr r0, PlayBattleScript
bx r0
.align 2
Back: .word 0x08053AC0+1
BackPlusTwo: .word 0x08053AC2+1
PlayBattleScript: .word 0x08053AEC+1
/*00 4D 28 47 xx+1 xx xx 08 at 08053AB8*/
.text
.align 2
.thumb
.thumb_func
.global altermemento
Start:
ldr r0, BankTarget
ldrb r1, [r0]
mov r0, #0x58
mul r0, r1
add r1, r0, r2
push {r1}
add r1, #0x20
ldrb r1, [r1]
cmp r1, #[I][U]0x7F[/U][/I] /*Index number of your ability Contrary*/
bne Classic
pop {r1}
mov r0, #0x19
ldrsb r0, [r1, r0]
mov r3, r2
cmp r0, #0xC
bne PlayMemento
mov r0, #0x1C
ldrsb r0, [r1, r0]
cmp r0, #0xC
bne PlayMemento
ldr r0, Back
bx r0
Classic:
ldr r0, Return
bx r0
PlayMemento:
ldr r0, BackPlay
bx r0
.align 2
BankTarget: .word 0x0202420C
Return: .word 0x08054AAE+1
BackPlay: .word 0x08054AF4+1
Back: .word 0x08054AC0+1
/*00 48 00 47 xx+1 xx xx 08 at 08054AA4*/
.text
.align 2
.thumb
.thumb_func
.global alterbellydrum
Start:
push {r2}
add r2, #0x20
ldrb r1, [r2]
pop {r2}
cmp r1, #[I][U]0x7F[/U][/I] /*Index number of your ability Contrary*/
bne Return
mov r0, #0
b Back
Return:
mov r0, #0xC
Back:
strb r0, [r2, #0x19]
ldr r1, StoreDamage
ldrb r0, [r4]
mul r0, r3
add r0, r0, r5
push {r0}
ldr r0, BranchBack
bx r0
.align 2
StoreDamage: .word 0x020241F0
BranchBack: .word 0x080540E4+1
/*00 48 00 47 xx+1 xx xx 08 01 BC at 080540DC*/
Also, in some battle scripts, cmd 0x45 (the play animation command), with some specific parameters, is also responsible for playing stat changing animations.
.text
.align 2
.thumb
.thumb_func
.global simple
Start:
ldr r2, =(0x02024064)
ldrb r0, [r2]
mov r4, #0x58
mov r1, r0
mul r1, r4
push {r1, r2}
add r1, #0x40
add r2, r1
ldrb r1, [r2]
cmp r1, #0x57 /*Number of ability Simple*/
bne ClassicRoutine
Simple:
pop {r1, r2}
add r1, r7, r1
mov r3, r10
add r3, #0x18
add r1, r1, r3
cmp r6, #0x81
bge HandleNegative
lsl r0, r6, #0x19
ldr r6, Return
bx r6
HandleNegative:
mov r0, #0xFF
add r0, #1
sub r0, r0, r6
lsl r0, #1
mov r6, #0xFF
add r6, #1
sub r6, r6, r0
lsl r0, r6, #0x18
ldr r6, Return
bx r6
ClassicRoutine:
pop {r1, r2}
ldr r0, Back
bx r0
.align 2
Return: .word 0x08050E24+1
Back: .word 0x08050E1A+1
/*00 4A 10 47 xx+1 xx xx 08 at 08050E10*/
.text
.align 2
.thumb
.thumb_func
.global altercopyfoestats
Start:
pop {r0}
mul r0, r4
add r0, r2, r0
add r0, r0, r3
push {r0-r2}
ldr r0, BattleData
ldr r1, BankUser
mov r2, #0x58
ldrb r1, [r1]
mul r1, r2
add r1, r0
add r1, #0x20
ldrb r1, [r1]
cmp r1, #[I][U]0x57[/U][/I] /*Index number of your ability simple*/
beq Double
pop {r0-r2}
ldrb r0, [r0]
Continue:
strb r0, [r1]
add r2, #1
push {r0}
ldr r0, Return
bx r0
Double:
pop {r0-r2}
ldrb r0, [r0]
cmp r0, #5
ble Neg
cmp r0, #7
bge Pos
b Continue
Neg:
cmp r0, #3
ble Zero
push {r1}
mov r1, #6
sub r1, r0
lsl r1, #1
mov r0, r1
mov r1, #6
sub r1, r0
mov r0, r1
pop {r1}
b Continue
Zero:
mov r0, #0
b Continue
Pos:
cmp r0, #9
bge Max
push {r1}
mov r1, #6
sub r0, r1
lsl r0, #1
add r0, r1
pop {r1}
b Continue
Max:
mov r0, #0xC
b Continue
.align 2
Return: .word 0x08054158+1
BattleData: .word 0x02024084
BankUser: .word 0x0202420B
/*01 B4 00 48 00 47 xx+1 xx xx 08 01 BC at 0805414E*/
Contrary
.text
.text
.align 2
.thumb
.thumb_func
.global snowwarning
BufferAbility:
ldrb r0, [r1]
cmp r0, #0x76
beq SnowWarning
SandStreamCheck:
cmp r0, #0x2D
bne ReturnChecks
SandStream:
ldr r2, .Return
bx r2
ReturnChecks:
ldr r4, .Return2
bx r4
SnowWarning:
CheckWeather:
ldr r2, .WeatherLoc
ldrh r1, [r2]
mov r0, #0x80
and r0, r1
CheckHail:
cmp r0, #0x0
beq Continue
bl EndScript
SetHail:
mov r0, #0x80
strh r0, [r2]
ldr r2, .Place
mov r0, #0x0
strb r0, [r2]
ldr r0, .SnowWarningBS
bl PlayScript
ldr r0, .Place2
mov r1, r10
strb r1, [r0, #0x17]
bl OtherBL
EndScript:
ldr r4, .EndScriptBL
bx r4
PlayScript:
ldr r2, .PlayScriptBL
bx r2
OtherBL:
ldr r0, .OtherBL
bx r0
.align 2
.Return: .word 0x0801A2AD
.Return2: .word 0x0801A149
.WeatherLoc: .word 0x02023F1C
.Place: .word 0x02023F48
.SnowWarningBS: .word 0x08CCCCCC
.Place2: .word 0x02023FC4
.EndScriptBL: .word 0x0801BBAB
.PlayScriptBL: .word 0x0801BC25
.OtherBL: .word 0x0801BB5B
#Insert 00 48 00 47 xx xx xx 08 at 1A140