Advertiser Content

Development Move Animations General

Started by DizzyEgg December 12th, 2016 9:25 AM
  • 4377 views
  • 8 replies

DizzyEgg

Age 21
Male
Poland
Seen 12 Hours Ago
Posted 2 Weeks Ago
769 posts
5.4 Years
I know move animations are already present in the move resource thread however I think they deserve their own.

I also made this thread, because I think it's the time we moved from animations as series of bytes to a scripting language. After all, that's how they were done. There are about 50(a bit less) commands in total and I'll go briefly about them. Note that I am not sure how some of them work.

Commands:
Spoiler:

00 loadparticle: [halfword]
Args:
Particle ID

This command lets us use particles throughout the animation script. The 'particle' is a rather small graphic that contains things like a water drop, a thunder, a note, cotton, etc. Basically particles are everything that appears on the screen while using a move. They're OAMs.

01 unloadparticle: [halfword]
Args:
Particle ID

Frees up the graphic that we loaded in the previous command. Only used in Synthesis, Revenge and Heal Bell. All other scripts do not use it, no reason why.

02 launchtemplate [word] [byte][byte] [...halfwords...]
Args:
Pointer to objtemplate structure
Unkown
Number of arguments
[Arguments]

Moving particles around, changing their size, rotating, etc. All those things are done by this command. Not directly of course, it's done by a function in the template structure which is as the following:
00000000 objtemplate     struc @ (sizeof=0x18, mappedto_243) @ XREF: ROM:stru_82F433C/r
00000000                                         @ ROM:stru_831C3C0/r ...
00000000 tiles_tag:      .short ?                @particle ID
00000002 pal_tag:        .short ?                @particle ID
00000004 oam:            .long ?                 @ offset (00000000)
00000008 image_anims:    .long ?                 @ offset (00000000)
0000000C gfx_table:      .long ?                 @ offset (00000000)
00000010 rotscale_anims: .long ?                 @ offset (00000000)
00000014 callback:       .long ?                 @ offset (00000000)
00000018 objtemplate     ends
This and the third command are the most important in move animation scripting.

03 launchtask [word][byte][byte][...halfwords..]
Args:
Pointer to an animation task
Priority
Number of arguments
[Arguments]

Animation tasks usually modify graphically pokemon sprites and backgrounds. They're also used to get information about battle and moves(for example the turn and power). The information is usually stored in the seventh argument.

04 pause [byte]
Args:
Amount of time to wait

Simply pauses a bit.

05 waitanimation
No Args

Waits for an animation to be finished. Similar to the overworld waitstate command.

06 - no command
07 - no command

08 endanimation
No Args

Finishes the script execution.

09 playsound1 [halfword]
Args:
Song ID

Plays a sound.

0A pokespritetoBG [byte]
Args:
bank or side

A very useful command.
Now a quick lesson on how GBA displays graphics. There are 4 layers of backgrounds and max 128 objects on screen. Objects appear on backgrounds and are the most 'visible' things on the screen. Now, all move 'particles' aka those things that move use such as bubbles, mud tiles, pokeballs, flames, etc. are objects. And poke sprites are also objects. And that's where a problem arises. Because if say, water was to hit a pokemon, it would replace some of the sprite with said water. It would ugly. So Gamefreak came with a solution, they created a command that allows you to temporarily move one(or two) sprites into a background. Now if water hits a pokemon, it appears as it really hits it and not modifies the sprite.
If you want to see a graphical representation of what I said, modify the Water Gun script and you'll exactly see what I mean.
As an argument it can take either one bank(target and attacker) or the whole side(target and its partner, attacker and its partner).

0B pokespritefromBG [byte]
Args:
bank or side

A counterpart of command 0xA. It restores a sprite from background to an object. The argument must obviously be the same as in the 0xA command.

0C setblends [halfword]
Args:
value to set BLDCNT

Sets BLDALPHA to 0x3F40 and BLDCNT to the given value.

0D resetblends
No Args

Sets both BLDALPHA and BLDCNT to 0;
Those are LCD registers, btw.

0E call [word]
Args:
Pointer to a script

Same as in the overworld scripting we call a piece of code, it gets executed and it gets back to us. Note that we can only call one script at a time, no nested calls.

0F return
No Args

Returns to the script that called it.

10 setarg [byte] [value]
Args:
Argument ID, starting from 0
Value to set

There are 8 arguments that the script can use. Launchtask, lanchsoundtask and launchtemplate use them for example for how fast to move an object or where to move it.

11 choosetwoturnanim [word] [word]
Args:
Pointer to script for the first turn/preparation turn
Pointer to script for the second turn/hit turn

The name may be misleading but it's best I came up with. :P There's a byte that could be said to be some sort of a turn counter that also works as a value that tells the script which animation to use if a move uses several animations(think multi-hits moves and two-turn moves).

12 jumpifmoveturnEQ [byte] [word]
Args:
Number of 'turns', counted from 0
Script ptr to jump

Jumps to the given script if the hit turn is equal. Used only in Triple Kick, Swallow and Spit Up(but obviously could be used in any move with multiple animations). Similarly as the above command, the name doesn't fully gives what it does, but I hope you get the idea. :P

13 goto [word]
Args:
Script ptr to jump

Does the same what an overworld goto. Jumps to a script and continues execution from there.

14 loadBG1 [byte]
Args:
Which background to load

Changes battle background to the one given in argument. Has a very similar command hence the '1'.

15 loaddefaultBG
No Args

Changes battle background to the one default one for that terrain. Think how when you use a ghost move the background temporarily changes and goes back to normal later.

16 waitforBG
No Args

Waits for background to get loaded.

17 waitfortransparentBG
No Args

Similar to above but makes the background transparent.(or at least that's what I think)

18 loadBG2 [byte]
Args:
Which background to load

Not sure what's the difference between this one and the 14th command. Used only for loading 'impact' background.

19 playsound2 [halfword] [byte]
Args:
Song ID
pan

Similar to playsound1 but let's you change pan pot.

1A pancontrol [byte]
Args:
pan

Changes the pan pot to the one in argument unless you're in contests or a poke is behind substitute. Then it may change the value accordingly.

1B playsoundpanchange [halfword] [byte] [byte] [byte] [byte]
Args:
Song ID
pan1
pan2
Unkown - honestly doesn't see a difference when I change that value in scripts
Unkown - something related to waiting after the sound or before the sound is finished I guess

Another playsound command. This one changes the song's pan while it's playing between it's pan1 and pan2 value.

1C soundcomplex [halfword] [byte] [byte] [byte]
Song ID
pan
How much to wait between playing sounds(note that they can play all at once or such as one starts while the other is in the middle)
Amount of times the sound will play

A more advanced version of playsound.

1D playsound3 [halfword] [byte] [byte]
SongID
pan
time to wait for the sound to play

Same as playsound2 except can set the time the sound will play.

1E set_BLDCNT [halfword]
Args:
Value to set

Sets the LCD register BLDCNT to the given value.

1F launchsoundtask [word][byte][...halfwords..]
Args:
Pointer to an animation task
Number of arguments
[Arguments]

Similar to launchtask, except it's used for tasks that are related to sounds.

20 waitforsound
No Args

Seems to wait for sound to be finished.

21 jumpifargmatches [byte] [halfword] [word]
Args:
Arg ID
Arg value
Pointer to script to jump

Jumps to a script if given argument is equal.

22 anim22 [byte]
Args:
bank or side(same as in 0xA command)

Hmm...Not sure.

23 anim23 [byte]
Args:
bank or side(same as in 0xB command)

A counterpart of 0x22.

24 jumpifnotinbattle [word]
Args:
Pointer to a script

Jumps to a given script if we are currently not in a battle. (And that implies a move has been used during contests).

25 chooseBG [byte] [byte] [byte]
Args:
bgID
bgID
bgID

A command created only for Guillotine. It acts the same way as loadBG1, except it chooses a background to load depending on specific conditions. It loads the background in the:
1. First argument if a move was used against an opponent's side
2. Second argument if a move was used against the player's side
3. Third argument if a move was used during contests

This command actually comes in handy, but if you look in the scripts you'll see that GF always used tasks to load correct BG depending on above conditions. My best guess is that later someone came up with that super idea for this command, but didn't bother to change already written scripts. :P

26 playsoundpanchange2 [halfword] [byte] [byte] [byte] [byte]
Args:
Song ID
pan1
pan2
Unkown
Unkown

Very similar to playsoundpanchange. Cant really tell what a difference is.

27 playsoundpanchange3 [halfword] [byte] [byte] [byte] [byte]
Args:
Song ID
pan1
pan2
Unkown
Unkown

Same as above.

28 leftbankBG_over_partnerBG [byte]
Args:
Bank

Remember how the 0xA command can move whole side's sprites to background? Well this one simply makes the left bank(first player poke or second opponent poke) appear 'on top' its partner. Honestly can't say there's much difference with and without that command.
If the bank isn't the one at left, does nothing.

29 bankBG_over_partnerBG
No Args

Same as 28 except works for all banks. Obviously this and the command above work only in battles. They do nothing in contests.

2A leftopponentbankBG_over_partnerBG [byte]
Args:
Bank

Same as 0x28 but the target and the attacker must be from other sides. Name's could be better, so I'm open to suggestions. :P

2B makebankinvisible [byte]
Args:
bank

Makes a pokemon sprite invisible.

2C makebankvisible [byte]
Args:
bank

Makes a pokemon sprite visible.

2D [byte]
2E [byte]
Two unused commands. Both do nothing if used in contests, not in a double battle or target and attacker are from different side. Too lazy to look into what they do in detail.

2F: stopmusic
No Args

Appears to stop music.


Now some terms I've used while explaining commands not everyone may get.
Spoiler:

Bank - used to distinguish the animation attacker(0) and target(1). Note that both may be the same in moves like Harden, etc.
Bank or side - attacker(0) and target(1), attacker side (2), target side(3). Used in commands 0xA, 0xB, 0x22 and 0x23.
Animation Arguments - an array of 8 halfwords that's used in various commands. In Emerald the location is at 0x0203841E
Task - a function that gets executed repeatedly every frame until it's stopped.
Pan - in sound functions, a value between -126 and 127. The smaller it is, the more sound is going to play in the left speaker, similarly the higher the value the more intense the sound will be in the right speaker


All offsets below are for Emerald.

A list of all move animation tasks that are used: (Soon to add descriptions on what they do)
Spoiler:

Animation Tasks: (note they all end up + 1, their actual address is even)
Spoiler:

0x80d51ad - AnimTask_move_bank(bank, X move, Y move, duration, ?)

Moves the poke sprite by specified values in arguments and then puts it back to its original position.

0x8116621
0x80d52d1
0x8117e61 - AnimTask_arg7_is_in_contests
0x815a8c9 - AnimTask_arg7_is_target_player
0x8115f11
0x80d5831
0x8115d95
0x810ded9
0x80d5739
0x80d5db1
0x80d5eb9
0x80d6065
0x80d5485
0x80d6135
0x8117661 - AnimTask_scroll_background(Horizontal, Vertical, Neg, Stop)

One of the most important animation tasks, this one makes the background scroll.
Horizontal = a signed 16-bit value to tell how fast to move horizontally
Vertical= a signed 16-bit value to tell how fast to move vertically
Neg - a bool, if it's set and bank it's from opponent side, the value will be reversed, so 90 would become -90, etc.
Stop - A value arg7 has to have in order to stop the task. (You must set arg7 to that value before the script ends or the background will be scrolling forever :P)

0x80d5c51
0x8104c39
0x8104ca5
0x8158e9d
0x8159079
0x8102be9
0x8102ca1
0x81045b1
0x8115a05
0x81076c9
0x8107955 - AnimTask_surf_wave(bool muddy_water_pal)
0x8158c59
0x8117755 - AnimTask_arg7_is_attacker_opponent
0x815a505 - AnimTask_prepare_moving_psychicBG

Takes no args. Used to achieve a scrolling background effect for the psychic BG.

0x8107529
0x80d622d
0x810eb89
0x81114ed
0x811152d
0x8111591
0x80d5645
0x80fea59
0x810a7dd
0x810a095

0x81152dd - AnimTask_screen_shake(what_to_shake, power, duration)
what_to_shake = 0, 1, 2, 3 - chosen bank, 4 - all banks, 5 -
power = basically move_power / 10, if 0 power will be read from current move's power
duration - time for it to shake

0x8115629
0x8114cbd
0x8114f15
0x810f7d5
0x81169c1
0x80a7b99
0x80d6389
0x810f83d
0x811188d
0x80ff459
0x81029b5
0x81144f9 - AnimTask_steel_sprite(nochangeback, metalic, colour)

Creates a polishing like steeling effect to the sprite of the attacker.
nochangeback - bool, if set, the sprite's colour wont return to its default one
metalic - bool, if set, it uses the 'metallic' colour such as in moves like Steel Wing or Harden
colour - value for the 'steeling' effect if the above bool is false

0x8104675
0x815a161
0x8159279
0x8115c81
0x81036a1 - AnimTask_withdraw

No args. Whole Withdraw move animation.

0x811489d
0x815b339
0x810c0a1 - AnimTask_create_haze
0x8158b31
0x8101c95
0x815e115
0x81064f9
0x815e47d
0x81177ad
0x8116665
0x81136e9
0x8159245
0x8159211
0x81137e5
0x815b7d1
0x80fee1d
0x8117495 - AnimTask_flash_anim

No args. Basically the whole Flash move animation is this task.

0x8104939 - AnimTask_splash_down(bank, amount_of_splashes)
0x815d241
0x81022d5
0x815f20d
0x8104e75
0x8111c51
0x8112759
0x8116b15
0x815c771
0x81023e1
0x8111e51
0x80a8bc5
0x8117f61
0x8113889
0x81123c5
0x8110bcd
0x815c479
0x8110f75
0x8104ab5
0x8107145 - AnimTask_arg7_is_furycutter_hit_even
0x8107169 - AnimTask_arg7_to_furycutter_timer
0x81062e9
0x8105cb5
0x8105d61
0x815f8a1
0x815a905 - AnimTask_arg7_is_move_healing
0x80a8141
0x815c3a9
0x815ca21
0x8115601 - AnimTask_argF_is_power_above_99
0x815abed
0x8116961
0x815ac8d
0x815adb1
0x815bb85
0x80a7a75
0x81025c1
0x8107189
0x8115b0d
0x810577d
0x8105811
0x8105aad
0x810599d
0x8105eb1
0x8106021
0x8106d91
0x815b65d
0x815b6b5
0x815b779
0x8116849
0x810a061
0x8109dbd
0x810c919
0x815aff1
0x81143c1
0x8113bad
0x8114471
0x8113e79
0x815dca5
0x815df0d
0x815e841
0x810aafd
0x815ec49
0x81060b1
0x815ced9
0x815d64d
0x8109461
0x810fbf1
0x810f941
0x815dfcd
0x8112c6d
0x8117c25 - AnimTask_arg0_to_background
0x81007c5
0x811675d
0x815a5c9 - AnimTask_prepare_moving_psychicBG2

No args. Similar to AnimTask_prepare_moving_psychicBG, but the scrolling is a bit different.

0x810c325
0x8160165
0x810cdfd - AnimTask_get_rollout_timer(arg ID)

Stores attacker's rollout counter in the animation argument specified in the argument.

0x8160545 - AnimTask_SlackOff
0x81590b9
0x81162a5
0x81604f1 - AnimTask_arg7_weather_case
0x8103cf1
0x8117c45
0x8117ca1
0x8117dd9
0x8117d3d
0x8117c71
0x815f621
0x8117781 - AnimTask_arg7_is_target_opponent
0x8117611
0x81080e5
0x81085c9
0x810fe15
0x8110035
0x810dabd
0x80a9ef5
0x8158d8d - AnimTask_play_howl_cry(bank, ?)
0x810afcd
0x810ae5d
0x81088e5
0x81177e5
0x80fffc1
0x81133e9
0x80a7cb5
0x810b29d
0x810b55d
0x8114961
0x81734b5 - AnimTask_arg0_to_trapped_move_case

Sets arg0 to:
0 - if trapped move is different from ones below
1 - if trapped move is Fire Spin
2 - if trapped move is Whirlpool
3 - if trapped move is Clamp
4 - if trapped move is Sand Tomb


Syntax used:
Spoiler:

All animations tasks' names begin with "AnimTask_" which is followed by a brief description of what it does.
'argX_to_Y' means the task stores information about Y in the argument X.
'argX_is_Y' means the task checks if Y is true. If it is, argument X contains 1, otherwise 0.
'argX_Y_case' means the task stores a switch-like(0, 1, 2 ,3, etc.) value in argument X.


Similarly a list of all templates:
Spoiler:

Templates:
0x8597358
0x8595e68
0x8595e98
0x8597274
0x8595f48
0x859728c
0x85934d8
0x85934f0
0x8595368
0x8595380
0x8595ae8
0x8595ad0
0x8595b68
0x8595b80
0x85956c0
0x85ce020
0x8593590
0x85935d0
0x8593550
0x85962d4
0x8593380
0x8592a1c
0x8596270
0x85962a4
0x857fe70
0x857fe58
0x85963d4
0x8596340
0x8596358
0x85928d0
0x857fe28
0x85928e8
0x8595f60
0x8595eb0
0x8595e80
0x8595ee0
0x85971a8
0x8592cd8
0x85973e8
0x8592f44
0x857fe40
0x8596a44
0x8596240
0x8597370
0x8596a5c
0x85ce150
0x8597080
0x85ce7d4
0x8593008
0x8593428
0x8593398
0x853ee84
0x85961c0
0x859620c
0x85954d4
0x85954ec
0x8595158
0x8595c2c
0x8595208
0x8597388
0x8595220
0x85950e4
0x8595b2c
0x8595b14
0x8595b98
0x8595bb0
0x859663c
0x8595068
0x8596258
0x85950b4
0x8592288
0x8596cb0
0x8592270
0x8592f2c
0x85922bc
0x8592390
0x85923d8
0x85921e0
0x85921f8
0x8592148
0x8592130
0x8592118
0x859231c
0x8592334
0x85969f8
0x85969e0
0x8596f80
0x8596f28
0x8596b88
0x8595810
0x85957e0
0x85957f8
0x8595840
0x85972d8
0x8596b04
0x85971fc
0x8597214
0x8596134
0x859368c
0x85924dc
0x8593440
0x85ce050
0x85ce038
0x8596d14
0x8596d2c
0x85ce338
0x85965a8
0x8596560
0x8596624
0x8596578
0x85965f4
0x8592d8c
0x8593114
0x85931bc
0x859371c
0x8593488
0x8596d8c
0x8595c44
0x85961a8
0x8597190
0x859551c
0x859556c
0x8595238
0x8595250
0x8597098
0x8592404
0x857fe88
0x8592494
0x8596744
0x85966dc
0x8593344
0x85937b0
0x859381c
0x8593a84
0x8595c9c
0x85969c8
0x8593af0
0x8593ac0
0x8596514
0x8595f78
0x85922ec
0x8595170
0x8593b38
0x8597178
0x8592c88
0x85ce1dc
0x8592de4
0x8592e74
0x85ce2f8
0x8595410
0x8592f74
0x8592d2c
0x8593b80
0x85936d4
0x8596a2c
0x85ce07c
0x85ce094
0x85ce0ac
0x8595584
0x85936ec
0x8596dd0
0x8596de8
0x85973a0
0x8592ea4
0x85ce5d8
0x8595bc8
0x8592adc
0x8593aa8
0x85939b8
0x859309c
0x8593068
0x85961d8
0x85971cc
0x8592dfc
0x8592e30
0x85ce11c
0x8595764
0x8595790
0x85ce8c4
0x8593c0c
0x8593c24
0x8595c04
0x8592ca0
0x8592cb8
0x8596e7c
0x8596ba0
0x8593970
0x8592d44
0x8592d5c
0x8593658
0x8592b3c
0x859574c
0x85ce104
0x85939a0
0x85939d0
0x85ce190
0x8593938
0x8593958
0x8592b94
0x8593868
0x8592610
0x8592658
0x85ce4d0
0x8593c64
0x85ce590
0x8595428
0x85953f8
0x8596974
0x8596ef4
0x85ce370
0x85ce22c
0x85ce244
0x85ce25c
0x85ce288
0x85ce544
0x8597138
0x85ce48c
0x8592b7c
0x8592ebc
0x8592eec
0x8593a04
0x8593a1c
0x8595ec8
0x85973d0
0x85923a8
0x8596cc8
0x85954a0
0x8596590
0x8596548
0x85973b8
0x8596c10
0x8596d58
0x8596b1c
0x8596b70
0x8593898
0x8593bb8
0x8592244
0x8593a50
0x85ce418
0x85ce5c0
0x85ce5a8
0x859563c
0x859566c
0x8596104
0x85ce864
0x85ce894
0x85931d4
0x859595c
0x859598c
0x859324c
0x85ce8ac
0x85926e8
0x85ce388
0x85ce804
0x859254c
0x859258c
0x8595fec
0x8596004
0x859601c
0x85965c0
0x85ce9b0
0x8596088
0x85960d0
0x8597400
0x8595f90
0x8595fa8
0x85ce68c
0x85ce984
0x85955e8
0x85967ac
0x8592888
0x85950fc
0x8596490
0x85964cc
0x85964e4
0x8596034
0x8596ac8
0x8596898
0x8595c70
0x8596388
0x8593050
0x8595f14
0x85971e4
0x8595de4
0x8595dfc
0x8593880
0x85951c0
0x85951d8
0x85ce8dc
0x853ee38
0x853ee50
0x859559c
0x8595328
0x8596ce0
0x8595d44
0x85927ac
0x85927c4
0x85970e8
0x8592a34
0x8596fb0
0x8596c58
0x8592830
0x8592848
0x8592860
0x8593458
0x8595114
0x859512c
0x8596b34
0x859351c
0x8596a74
0x85ce90c
0x8592564
0x8596420
0x859644c
0x85959a4
0x8593850
0x8596f98
0x8596c98
0x8595a18
0x85952f8
0x8593470
0x8596920


Now, I'd like to give you the most important thing in this post that I believe could make animation scripting MUCH much easier. And that is all move animation scripts decompiled. Link
They were decompiled in Emerald, but they look the same in other games, the difference being offsets.
I also attached the file in case someone can't get pastebin to work.

How to write scripts using those commands?
There is no script editor that supports custom commands, but it doesn't mean we have to write our scripts in hex. We can use ASM for that. Here's an ASM file that contains all defines and command as macros. All you'd have to do is include it at the top of your ASM file.
Spoiler:

.text

@banks
.equ bank_attacker, 0x0
.equ bank_target, 0x1
.equ attacker_partner, 0x2
.equ target_partner, 0x3

@sides for commands A, B
.equ side_attacker, 0x2
.equ side_target, 0x3

@background IDs
.equ BG_DARK, 0x1
.equ BG_GHOST, 0x2
.equ BG_PSYCHIC, 0x3
.equ BG_IMPACT_ON_OPPONENT, 0x4
.equ BG_IMPACT_ON_PLAYER, 0x5
.equ BG_IMPACT_CONTESTS, 0x6
.equ BG_DRILL_BATTLE, 0x7
.equ BG_DRILL_CONTESTS, 0x8
.equ BG_HIGHSPEED_ON_OPPONENT, 0x9
.equ BG_HIGHSPEED_ON_PLAYER, 0xA
.equ BG_THUNDER, 0xB
.equ BG_GUILLOTINE_ON_OPPONENT, 0xC
.equ BG_GUILLOTINE_ON_PLAYER, 0xD
.equ BG_GUILLOTINE_CONTESTS, 0xE
.equ BG_ICE, 0xF
.equ BG_COSMIC, 0x10
.equ BG_SEISMICTOSS_SKUUPPERCUT, 0x11
.equ BG_FLYING_BATTLE, 0x12
.equ BG_FLYING_CONTESTS, 0x13
.equ BG_AURORABEAM, 0x14
.equ BG_FISSURE, 0x15
.equ BG_BUG_ON_OPPONENT, 0x16
.equ BG_BUG_ON_PLAYER, 0x17
.equ BG_SOLARBEAM_ON_OPPONENT, 0x18
.equ BG_SOLARBEAM_ON_PLAYER, 0x19
.equ BG_SOLARBEAM_CONTESTS, 0x1A

@pals for pal fading tasks
.equ PAL_BG, 0x1
.equ PAL_ATK, 0x2
.equ PAL_DEF, 0x4
.equ PAL_ATK_PARTNER, 0x8
.equ PAL_DEF_PARTNER, 0x10
.equ PAL_ALL_BANKS, 0x780
.equ PAL_PLAYER1, 0x80
.equ PAL_PLAYER2, 0x100
.equ PAL_OPPONENT1, 0x200
.equ PAL_OPPONENT2, 0x400

@commands
.macro loadparticle loadparticleID
.byte 0x0
.hword \loadparticleID
.endm

.macro unloadparticle unloadparticleID
.byte 0x1
.hword \unloadparticleID
.endm

.macro launchtemplate launchtemplatePtr launchtemplatePriority launchtemplateArgsNo launchtemplatearg0 launchtemplatearg1 launchtemplatearg2 launchtemplatearg3 launchtemplatearg4 launchtemplatearg5 launchtemplatearg6 launchtemplatearg7 launchtemplatearg8
.byte 0x2
.word \launchtemplatePtr
.byte \launchtemplatePriority
.byte \launchtemplateArgsNo
.hword \launchtemplatearg0
.hword \launchtemplatearg1
.hword \launchtemplatearg2
.hword \launchtemplatearg3
.hword \launchtemplatearg4
.hword \launchtemplatearg5
.hword \launchtemplatearg6
.hword \launchtemplatearg7
.hword \launchtemplatearg8
.endm

.macro launchtask launchtaskPtr launchtaskPriority launchtaskArgsNo launchtaskarg0 launchtaskarg1 launchtaskarg2 launchtaskarg3 launchtaskarg4 launchtaskarg5 launchtaskarg6 launchtaskarg7 launchtaskarg8
.byte 0x3
.word \launchtaskPtr
.byte \launchtaskPriority
.byte \launchtaskArgsNo
.hword \launchtaskarg0
.hword \launchtaskarg1
.hword \launchtaskarg2
.hword \launchtaskarg3
.hword \launchtaskarg4
.hword \launchtaskarg5
.hword \launchtaskarg6
.hword \launchtaskarg7
.hword \launchtaskarg8
.endm

.macro pause pause_cmdToWait
.byte 0x4
.byte \pause_cmdToWait
.endm

.macro waitanimation
.byte 0x5
.endm

.macro endanimation
.byte 0x8
.endm

.macro playsound1 playsound1ID
.byte 0x9
.hword \playsound1ID
.endm

.macro pokespritetoBG animABank
.byte 0xA
.byte \animABank
.endm

.macro pokespritefromBG animBBank
.byte 0xB
.byte \animBBank
.endm

.macro setblends setblends_value
.byte 0xC
.hword \setblends_value
.endm

.macro resetblends
.byte 0xD
.endm

.macro call call_cmd_ptr
.byte 0xE
.word \call_cmd_ptr
.endm

.macro return
.byte 0xF
.endm

.macro setarg setargID setargValue
.byte 0x10
.byte \setargID
.hword \setargValue
.endm

.macro choosetwoturnanim choosetwoturnanim1 choosetwoturnanim2
.byte 0x11
.word \choosetwoturnanim1
.word \choosetwoturnanim2
.endm

.macro jumpifmoveturnEQ jumpifmoveturnEQturn jumpifmoveturnEQPTR
.byte 0x12
.byte \jumpifmoveturnEQturn
.word \jumpifmoveturnEQPTR
.endm

.macro goto goto_cmdPtr
.byte 0x13
.word \goto_cmdPtr
.endm

.macro loadBG1 loadBG1ID
.byte 0x14
.byte \loadBG1ID
.endm

.macro loaddefaultBG
.byte 0x15
.endm

.macro waitforBG
.byte 0x16
.endm

.macro waitfortransparentBG
.byte 0x17
.endm

.macro loadBG2 loadBG2ID
.byte 0x18
.byte \loadBG2ID
.endm

.macro playsound2 playsound2ID playsound2Unkown
.byte 0x19
.hword \playsound2ID
.byte \playsound2Unkown
.endm

.macro pancontrol anim1Aarg1
.byte 0x1A
.byte \anim1Aarg1
.endm

.macro playsoundpanchange anim1BsongID anim1BArg3 anim1BArg4 anim1BArg5 anim1BArg6
.byte 0x1B
.hword \anim1BsongID
.byte \anim1BArg3
.byte \anim1BArg4
.byte \anim1BArg5
.byte \anim1BArg6
.endm

.macro soundcomplex anim1Carg1 anim1Carg2 anim1Carg3 anim1Carg4
.byte 0x1C
.hword \anim1Carg1
.byte \anim1Carg2
.byte \anim1Carg3
.byte \anim1Carg4
.endm

.macro playsound3 anim1Darg1 anim1Darg2 anim1Darg3
.byte 0x1D
.hword \anim1Darg1
.byte \anim1Darg2
.byte \anim1Darg3
.endm

.macro set_BLDCNT set_BLDCNTvalue
.byte 0x1E
.hword \set_BLDCNTvalue
.endm

.macro launchsoundtask launchsoundtaskPtr launchsoundtaskArgsNo
.byte 0x1F
.word \launchsoundtaskPtr
.byte \launchsoundtaskArgsNo
.endm

.macro waitforsound
.byte 0x20
.endm

.macro jumpifargmatches jumpifargmatchesargID jumpifargmatchesValue jumpifargmatchesPtr
.byte 0x21
.byte \jumpifargmatchesargID
.hword \jumpifargmatchesValue
.word \jumpifargmatchesPtr
.endm

.macro anim22 anim22bank
.byte 0x22
.byte \anim22bank
.endm

.macro anim23 anim23bank
.byte 0x23
.byte \anim23bank
.endm

.macro jumpifnotinbattle jumpifnotinbattlePTR
.byte 0x24
.word \jumpifnotinbattlePTR
.endm

.macro chooseBG chooseBG1 chooseBG2 chooseBG3
.byte 0x25
.byte \chooseBG1
.byte \chooseBG2
.byte \chooseBG3
.endm

.macro playsoundpanchange2 anim26H0 anim26B0 anim26B1 anim26B2 anim26B3
.byte 0x26
.hword \anim26H0
.byte \anim26B0
.byte \anim26B1
.byte \anim26B2
.byte \anim26B3
.endm

.macro playsoundpanchange3 anim27H0 anim27B0 anim27B1 anim27B2 anim27B3
.byte 0x27
.hword \anim27H0
.byte \anim27B0
.byte \anim27B1
.byte \anim27B2
.byte \anim27B3
.endm

.macro leftbankBG_over_partnerBG anim28Bank
.byte 0x28
.byte \anim28Bank
.endm

.macro bankBG_over_partnerBG
.byte 0x29
.endm

.macro leftopponentbankBG_over_partnerBG anim2Aarg
.byte 0x2A
.byte \anim2Aarg
.endm

.macro makebankinvisible makebankinvisibleBank
.byte 0x2B
.byte \makebankinvisibleBank
.endm

.macro makebankvisible makebankvisibleBank
.byte 0x2C
.byte \makebankvisibleBank
.endm

.macro stopmusic
.byte 0x2F
.endm

@objtemplate

.macro objtemplate objtemplatetiletag objtemplatepaltag objtemplateoam objtemplateimageanim objtemplategfx objtemplaterotscale objtemplatecallback
.hword \objtemplatetiletag
.hword \objtemplatepaltag
.word \objtemplateoam
.word \objtemplateimageanim
.word \objtemplategfx
.word \objtemplaterotscale
.word \objtemplatecallback
.endm

@supercommands

.macro unsetscrollingBG
loaddefaultBG
waitforBG
setarg 0x7 0xffff
waitfortransparentBG
.endm


Also task offsets for your linker(BPEE.ld) file. If you don't use a linker, you need to change them to .equ format.

Spoiler:

/*move animation tasks*/
AnimTask_arg7_is_target_opponent = 0x8117780 |1;
AnimTask_withdraw = 0x81036a0 |1;
AnimTask_flash_anim = 0x8117494 |1;
AnimTask_arg0_to_trapped_move_case = 0x81734b4 |1;
AnimTask_prepare_moving_psychicBG = 0x815a504 |1;
AnimTask_arg7_is_move_healing = 0x815a904 |1;
AnimTask_arg7_is_target_player = 0x815a8c8 |1;
AnimTask_move_bank = 0x80d51ac |1;
AnimTask_SlackOff = 0x8160544 |1;
AnimTask_create_haze = 0x810c0a0 |1;
AnimTask_play_howl_cry = 0x8158d8c |1;
AnimTask_pal_fade_complex = 0x8115a04 |1;
AnimTask_sprite_transform = 0x815b7d0 |1;
AnimTask_steel_sprite = 0x81144f8 |1;
AnimTask_arg7_is_attacker_opponent = 0x8117754 |1;
AnimTask_arg7_to_power_case = 0x81114ec |1;
AnimTask_arg7_is_furycutter_hit_even = 0x8107144 |1;
AnimTask_screen_shake = 0x81152dc |1;
AnimTask_arg7_to_frustration_case = 0x80a8140 |1;
AnimTask_arg7_is_in_contests = 0x8117e60 |1;
AnimTask_pal_fade_banks_except_attacker = 0x8117610 |1;
AnimTask_arg0_to_background = 0x8117c24 |1;
AnimTask_free_ball_tile = 0x8170d24 |1;
AnimTask_arg7_to_furycutter_timer = 0x8107168 |1;
AnimTask_pal_fade_depending_on_BG = 0x811675c |1;
AnimTask_arg7_is_target_partner = 0x81177ac |1;
AnimTask_play_growling_cry = 0x8158e9c |1;
AnimTask_arg7_weather_case = 0x81604f0 |1;
AnimTask_prepare_moving_psychicBG2 = 0x815a5c8 |1;
AnimTask_pal_fade_particle = 0x8116848 |1;
AnimTask_SwaggerBulkUP = 0x8104ab4 |1;
AnimTask_load_ball_tile = 0x8170cfc |1;
AnimTask_argF_is_power_above_99 = 0x8115600 |1;
AnimTask_pal_fade = 0x8116620 |1;
AnimTask_splash_down = 0x8104938 |1;
AnimTask_surf_wave = 0x8107954 |1;
AnimTask_arg7_to_return_case = 0x815f8a0 |1;
AnimTask_scroll_background = 0x8117660 |1;
AnimTask_get_rollout_timer = 0x810cdfc |1;
AnimTask_set_invisibility_bit_to_all_except_attacker = 0x81177e4 |1;


With that in mind I think we could easily write scripts for all moves past gen3. Even without custom tasks.

If you have questions, wrote a script or researched a command/task/template please post it here.

FBI

Free supporter

Male
Unknown Island
Seen 1 Day Ago
Posted March 30th, 2019
1,906 posts
6.4 Years
For anyone wondering, you can find some additional documentation including FireRed addresses here:
https://www.pokecommunity.com/showthread.php?t=354621

For the list of tasks as well as templates which Dizzy has posted, they were made on a case by case basis for each move so there are no tables containing these functions. Additionally, if you made a new animation script, you would be forced into reusing the tasks which GameFreak had coded, or making your own task for the object's animation.

The current move animation system seems quite poor for making new move scripts as they use a setup overly complex to achieve something simpler. I think you can make more leverage with this if you reworked the task's object transformation operations into a scripting system as well.
...

Logan

Age 24
Male
Salisbury, England
Seen 4 Weeks Ago
Posted 4 Weeks Ago
10,410 posts
10.6 Years
HAVE A STICKY

MrDollSteak

Formerly known as 11bayerf1

Age 24
Male
Hong Kong
Seen 4 Weeks Ago
Posted 4 Weeks Ago
846 posts
10.5 Years
Crazy good stuff!

I made a move, I believe it was Flash Cannon use a custom loaded object template, or an edited one at least, to slightly change its size and/or trajectory I don't even remember. Maybe have a look at that in the moveanimations.s file Dizzy to see if theres an easier way to automate that process too.

DizzyEgg

Age 21
Male
Poland
Seen 12 Hours Ago
Posted 2 Weeks Ago
769 posts
5.4 Years
Crazy good stuff!

I made a move, I believe it was Flash Cannon use a custom loaded object template, or an edited one at least, to slightly change its size and/or trajectory I don't even remember. Maybe have a look at that in the moveanimations.s file Dizzy to see if theres an easier way to automate that process too.
What process you're talking about?

MrDollSteak

Formerly known as 11bayerf1

Age 24
Male
Hong Kong
Seen 4 Weeks Ago
Posted 4 Weeks Ago
846 posts
10.5 Years
What process you're talking about?
I think its how to program the movement / size of the particle. For example with Flash Cannon I believe what I did was take the object movement from another animation but changed one of the bytes to make it bigger and / or faster. Sorry for not being more specific I'll try and explain more soon.

FBI

Free supporter

Male
Unknown Island
Seen 1 Day Ago
Posted March 30th, 2019
1,906 posts
6.4 Years
So what MrDollstead did was edit the object template to adjust the size, and then assign a different task. As you should know the Object Template is a template for the Object system to initialize an Object, and ofcourse that has an OAM field for you to scale the size. However, speed and direction are not controlled by the Object template, and rather the task.

I think you ought to make a central task for the animations and include time dependent positional delta vectors for movement and utilize GameFreak's animation scripting system for OAM animation (actually the system currently does make use of this) in addition to the rotscale scripting system (system does not make use of this).

Because the tasks themselves are doing the scaling and rotation, rather than through the script system. However, there is a good reason for this, and that reason is because there is no way to distinguish which instruction of the rotation/scaling script is currently running. So adjustments of vector positions and influencing movement based of the rotation is impossible normally.

There is a very easy solution, and that is to assign a task to assign rotation scripts one instruction at a time, while simultaneously adjusting position vectors. This is what I mean when I say make a new scripting system for animations. You want to combine both the animation script engine and the rotscale script engine GF has made in addition to the task system for positional updates. Ideally incorporating BGs as well. The result is an easy to use animation script system which abstracts all of the matrix and trigonometric calculations while maintaining nearly the same functionality (taking a minor speed hit of 1 frame per animation phase shift).

The downside is that it takes up a comparably larger amount of ROM space depending on the permutations of the rotscale scripts you plan to have and the length of the animation. You would need to somehow push the C2 callback, execute the script callback, pop C2 back and finish executing C2 (or you can make a very inefficient C2, but you would take a performance and potential FPS penalty).

I think most of this would become clear after I make another tutorial soon(TM).
...

MrDollSteak

Formerly known as 11bayerf1

Age 24
Male
Hong Kong
Seen 4 Weeks Ago
Posted 4 Weeks Ago
846 posts
10.5 Years
So what MrDollstead did was edit the object template to adjust the size, and then assign a different task. As you should know the Object Template is a template for the Object system to initialize an Object, and ofcourse that has an OAM field for you to scale the size. However, speed and direction are not controlled by the Object template, and rather the task.

I think you ought to make a central task for the animations and include time dependent positional delta vectors for movement and utilize GameFreak's animation scripting system for OAM animation (actually the system currently does make use of this) in addition to the rotscale scripting system (system does not make use of this).

Because the tasks themselves are doing the scaling and rotation, rather than through the script system. However, there is a good reason for this, and that reason is because there is no way to distinguish which instruction of the rotation/scaling script is currently running. So adjustments of vector positions and influencing movement based of the rotation is impossible normally.

There is a very easy solution, and that is to assign a task to assign rotation scripts one instruction at a time, while simultaneously adjusting position vectors. This is what I mean when I say make a new scripting system for animations. You want to combine both the animation script engine and the rotscale script engine GF has made in addition to the task system for positional updates. Ideally incorporating BGs as well. The result is an easy to use animation script system which abstracts all of the matrix and trigonometric calculations while maintaining nearly the same functionality (taking a minor speed hit of 1 frame per animation phase shift).

The downside is that it takes up a comparably larger amount of ROM space depending on the permutations of the rotscale scripts you plan to have and the length of the animation. You would need to somehow push the C2 callback, execute the script callback, pop C2 back and finish executing C2 (or you can make a very inefficient C2, but you would take a performance and potential FPS penalty).

I think most of this would become clear after I make another tutorial soon(TM).
Cheers FBI, summed it up a lot better than I could. I made the animation a while ago and sort of forgot exactly what I did. But yes the pointers there all seem a bit unoptimised having certain tasks being linked to certain sizes, though there is obviously the capability to improve this.

AkameTheBulbasaur

Akame Marukawa of Iyotono

Age 21
Male
A place :D
Seen 2 Days Ago
Posted 2 Weeks Ago
360 posts
6.1 Years
So recently I've started trying to do more in depth research into animations, specifically the various tasks and templates and how they work.

I'm not too far into this yet (due to being busy with other things), but what I do have so far which may be useful is a collection of all the backgrounds, particles and sound effects and which hex ID they have.

This should at least be useful so that you can know what things look/sound like without having to go find them manually every time.
"The human sacrificed himself, to save the Pokemon. I pitted them against each other, but not until they set aside their differences did I see the true power they all share deep inside. I see now that the circumstances of one's birth are irrelevant; it is what you do with the gift of life that determines who you are." -Mewtwo
Advertiser Content