summaryrefslogtreecommitdiff
path: root/src/battle_anim_fight.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/battle_anim_fight.c')
-rw-r--r--src/battle_anim_fight.c1043
1 files changed, 1043 insertions, 0 deletions
diff --git a/src/battle_anim_fight.c b/src/battle_anim_fight.c
new file mode 100644
index 000000000..5211860e0
--- /dev/null
+++ b/src/battle_anim_fight.c
@@ -0,0 +1,1043 @@
+#include "global.h"
+#include "battle_anim.h"
+#include "gpu_regs.h"
+#include "random.h"
+#include "task.h"
+#include "trig.h"
+#include "constants/rgb.h"
+
+static void unc_080B08A0(struct Sprite *);
+static void AnimSlideHandOrFootToTarget(struct Sprite *);
+static void AnimJumpKick(struct Sprite *);
+static void AnimBasicFistOrFoot(struct Sprite *);
+static void AnimFistOrFootRandomPos(struct Sprite *);
+static void AnimFistOrFootRandomPos_Step(struct Sprite *);
+static void AnimCrossChopHand(struct Sprite *);
+static void AnimCrossChopHand_Step(struct Sprite *);
+static void AnimSlidingKick(struct Sprite *);
+static void AnimSlidingKick_Step(struct Sprite *);
+static void AnimSpinningKickOrPunch(struct Sprite *);
+static void AnimStompFoot(struct Sprite *);
+static void AnimStompFoot_Step(struct Sprite *);
+static void AnimStompFoot_End(struct Sprite *);
+static void AnimDizzyPunchDuck(struct Sprite *);
+static void AnimBrickBreakWall(struct Sprite *);
+static void AnimBrickBreakWall_Step(struct Sprite *);
+static void AnimBrickBreakWallShard(struct Sprite *);
+static void AnimBrickBreakWallShard_Step(struct Sprite *);
+static void AnimSuperpowerOrb(struct Sprite *);
+static void AnimSuperpowerOrb_Step(struct Sprite *);
+static void AnimSuperpowerRock(struct Sprite *);
+static void AnimSuperpowerRock_Step1(struct Sprite *);
+static void AnimSuperpowerRock_Step2(struct Sprite *);
+static void AnimSuperpowerFireball(struct Sprite *);
+static void AnimArmThrustHit(struct Sprite *);
+static void AnimArmThrustHit_Step(struct Sprite *sprite);
+static void AnimRevengeScratch(struct Sprite *);
+static void AnimFocusPunchFist(struct Sprite *);
+static void AnimSpinningKickOrPunchFinish(struct Sprite *);
+
+extern struct SpriteTemplate gBasicHitSplatSpriteTemplate;
+
+// Unused
+const struct SpriteTemplate gUnknown_08595E14 =
+{
+ .tileTag = ANIM_TAG_HUMANOID_FOOT,
+ .paletteTag = ANIM_TAG_HUMANOID_FOOT,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = unc_080B08A0,
+};
+
+static const union AnimCmd sAnim_HandOrFoot[] =
+{
+ ANIMCMD_FRAME(0, 1),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sAnim_SlidingKick_0[] =
+{
+ ANIMCMD_FRAME(16, 1),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sAnim_SlidingKick_1[] =
+{
+ ANIMCMD_FRAME(32, 1),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sAnim_CrossChopHand_0[] =
+{
+ ANIMCMD_FRAME(48, 1),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sAnim_CrossChopHand_1[] =
+{
+ ANIMCMD_FRAME(48, 1, .hFlip = TRUE),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sAnims_HandOrFoot[] =
+{
+ sAnim_HandOrFoot,
+};
+
+static const union AnimCmd *const sAnims_SlidingKick[] =
+{
+ sAnim_SlidingKick_0,
+ sAnim_SlidingKick_1,
+};
+
+static const union AnimCmd *const sAnims_CrossChopHand[] =
+{
+ sAnim_CrossChopHand_0,
+ sAnim_CrossChopHand_1,
+};
+
+const struct SpriteTemplate gKarateChopSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = sAnims_HandOrFoot,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimSlideHandOrFootToTarget,
+};
+
+const struct SpriteTemplate gJumpKickSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = sAnims_HandOrFoot,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimJumpKick,
+};
+
+const struct SpriteTemplate gFistFootSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = sAnims_HandOrFoot,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimBasicFistOrFoot,
+};
+
+const struct SpriteTemplate gFistFootRandomPosSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = sAnims_HandOrFoot,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimFistOrFootRandomPos,
+};
+
+const struct SpriteTemplate gCrossChopHandSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = sAnims_CrossChopHand,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimCrossChopHand,
+};
+
+const struct SpriteTemplate gSlidingKickSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = sAnims_SlidingKick,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimSlidingKick,
+};
+
+static const union AffineAnimCmd sAffineAnim_SpinningHandOrFoot[] =
+{
+ AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 20, 1),
+ AFFINEANIMCMD_JUMP(1),
+};
+
+static const union AffineAnimCmd *const sAffineAnims_SpinningHandOrFoot[] =
+{
+ sAffineAnim_SpinningHandOrFoot,
+};
+
+// Blaze Kick / Meteor Mash
+const struct SpriteTemplate gSpinningHandOrFootSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineDouble_ObjNormal_32x32,
+ .anims = sAnims_HandOrFoot,
+ .images = NULL,
+ .affineAnims = sAffineAnims_SpinningHandOrFoot,
+ .callback = AnimSpinningKickOrPunch,
+};
+
+static const union AffineAnimCmd sAffineAnim_MegaPunchKick[] =
+{
+ AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME(0xFFFC, 0xFFFC, 20, 1),
+ AFFINEANIMCMD_JUMP(1),
+};
+
+static const union AffineAnimCmd *const sAffineAnims_MegaPunchKick[] =
+{
+ sAffineAnim_MegaPunchKick,
+};
+
+const struct SpriteTemplate gMegaPunchKickSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineDouble_ObjNormal_32x32,
+ .anims = sAnims_HandOrFoot,
+ .images = NULL,
+ .affineAnims = sAffineAnims_MegaPunchKick,
+ .callback = AnimSpinningKickOrPunch,
+};
+
+const struct SpriteTemplate gStompFootSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = sAnims_SlidingKick,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimStompFoot,
+};
+
+const struct SpriteTemplate gDizzyPunchDuckSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_DUCK,
+ .paletteTag = ANIM_TAG_DUCK,
+ .oam = &gOamData_AffineOff_ObjNormal_16x16,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimDizzyPunchDuck,
+};
+
+const struct SpriteTemplate gBrickBreakWallSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_BLUE_LIGHT_WALL,
+ .paletteTag = ANIM_TAG_BLUE_LIGHT_WALL,
+ .oam = &gOamData_AffineOff_ObjBlend_64x64,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimBrickBreakWall,
+};
+
+const struct SpriteTemplate gBrickBreakWallShardSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_TORN_METAL,
+ .paletteTag = ANIM_TAG_TORN_METAL,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimBrickBreakWallShard,
+};
+
+static const union AffineAnimCmd sAffineAnim_SuperpowerOrb[] =
+{
+ AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0),
+ AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 64),
+ AFFINEANIMCMD_FRAME(0xFFFA, 0xFFFA, 0, 8),
+ AFFINEANIMCMD_FRAME(0x6, 0x6, 0, 8),
+ AFFINEANIMCMD_JUMP(2),
+};
+
+static const union AffineAnimCmd *const sAffineAnims_SuperpowerOrb[] =
+{
+ sAffineAnim_SuperpowerOrb,
+};
+
+const struct SpriteTemplate gSuperpowerOrbSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT,
+ .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT,
+ .oam = &gOamData_AffineDouble_ObjBlend_64x64,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = sAffineAnims_SuperpowerOrb,
+ .callback = AnimSuperpowerOrb,
+};
+
+const struct SpriteTemplate gSuperpowerRockSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_FLAT_ROCK,
+ .paletteTag = ANIM_TAG_FLAT_ROCK,
+ .oam = &gOamData_AffineOff_ObjNormal_16x16,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimSuperpowerRock,
+};
+
+const struct SpriteTemplate gSuperpowerFireballSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_METEOR,
+ .paletteTag = ANIM_TAG_METEOR,
+ .oam = &gOamData_AffineOff_ObjNormal_64x64,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimSuperpowerFireball,
+};
+
+const struct SpriteTemplate gArmThrustHandSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = sAnims_HandOrFoot,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimArmThrustHit,
+};
+
+static const union AnimCmd sAnim_RevengeSmallScratch_0[] =
+{
+ ANIMCMD_FRAME(0, 4),
+ ANIMCMD_FRAME(16, 4),
+ ANIMCMD_FRAME(32, 4),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sAnim_RevengeSmallScratch_1[] =
+{
+ ANIMCMD_FRAME(0, 4, .vFlip = TRUE),
+ ANIMCMD_FRAME(16, 4, .vFlip = TRUE),
+ ANIMCMD_FRAME(32, 4, .vFlip = TRUE),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sAnim_RevengeSmallScratch_2[] =
+{
+ ANIMCMD_FRAME(0, 4, .hFlip = TRUE),
+ ANIMCMD_FRAME(16, 4, .hFlip = TRUE),
+ ANIMCMD_FRAME(32, 4, .hFlip = TRUE),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sAnims_RevengeSmallScratch[] =
+{
+ sAnim_RevengeSmallScratch_0,
+ sAnim_RevengeSmallScratch_1,
+ sAnim_RevengeSmallScratch_2,
+};
+
+const struct SpriteTemplate gRevengeSmallScratchSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_PURPLE_SCRATCH,
+ .paletteTag = ANIM_TAG_PURPLE_SCRATCH,
+ .oam = &gOamData_AffineOff_ObjNormal_32x32,
+ .anims = sAnims_RevengeSmallScratch,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimRevengeScratch,
+};
+
+static const union AnimCmd sAnim_RevengeBigScratch_0[] =
+{
+ ANIMCMD_FRAME(0, 6),
+ ANIMCMD_FRAME(64, 6),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sAnim_RevengeBigScratch_1[] =
+{
+ ANIMCMD_FRAME(0, 6, .vFlip = TRUE, .hFlip = TRUE),
+ ANIMCMD_FRAME(64, 6, .vFlip = TRUE, .hFlip = TRUE),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sAnim_RevengeBigScratch_2[] =
+{
+ ANIMCMD_FRAME(0, 6, .hFlip = TRUE),
+ ANIMCMD_FRAME(64, 6, .hFlip = TRUE),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sAnims_RevengeBigScratch[] =
+{
+ sAnim_RevengeBigScratch_0,
+ sAnim_RevengeBigScratch_1,
+ sAnim_RevengeBigScratch_2,
+};
+
+const struct SpriteTemplate gRevengeBigScratchSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_PURPLE_SWIPE,
+ .paletteTag = ANIM_TAG_PURPLE_SWIPE,
+ .oam = &gOamData_AffineOff_ObjNormal_64x64,
+ .anims = sAnims_RevengeBigScratch,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = AnimRevengeScratch,
+};
+
+static const union AffineAnimCmd sAffineAnim_FocusPunchFist[] =
+{
+ AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0),
+ AFFINEANIMCMD_FRAME(0xFFE0, 0xFFE0, 0, 8),
+ AFFINEANIMCMD_END,
+};
+
+static const union AffineAnimCmd *const sAffineAnims_FocusPunchFist[] =
+{
+ sAffineAnim_FocusPunchFist,
+};
+
+const struct SpriteTemplate gFocusPunchFistSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_HANDS_AND_FEET,
+ .paletteTag = ANIM_TAG_HANDS_AND_FEET,
+ .oam = &gOamData_AffineDouble_ObjNormal_32x32,
+ .anims = sAnims_HandOrFoot,
+ .images = NULL,
+ .affineAnims = sAffineAnims_FocusPunchFist,
+ .callback = AnimFocusPunchFist,
+};
+
+static void unc_080B08A0(struct Sprite *sprite)
+{
+ SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]);
+ sprite->pos1.y += gBattleAnimArgs[1];
+ sprite->data[0] = 15;
+ sprite->callback = WaitAnimForDuration;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+static void AnimSlideHandOrFootToTarget(struct Sprite *sprite)
+{
+ if (gBattleAnimArgs[7] == 1 && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ {
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ gBattleAnimArgs[3] = -gBattleAnimArgs[3];
+ }
+
+ StartSpriteAnim(sprite, gBattleAnimArgs[6]);
+ gBattleAnimArgs[6] = 0;
+ AnimTravelDiagonally(sprite);
+}
+
+static void AnimJumpKick(struct Sprite *sprite)
+{
+ if (IsContest())
+ {
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ gBattleAnimArgs[3] = -gBattleAnimArgs[3];
+ }
+
+ AnimSlideHandOrFootToTarget(sprite);
+}
+
+// Displays a basic fist or foot sprite for a given duration.
+// Used by many fighting moves (and elemental "punch" moves).
+// arg 0: initial x pixel offset
+// arg 1: initial y pixel offset
+// arg 2: duration
+// arg 3: ? (todo: related to initial pixel offsets)
+// arg 4: anim num
+static void AnimBasicFistOrFoot(struct Sprite *sprite)
+{
+ StartSpriteAnim(sprite, gBattleAnimArgs[4]);
+
+ if (gBattleAnimArgs[3] == 0)
+ InitSpritePosToAnimAttacker(sprite, 1);
+ else
+ InitSpritePosToAnimTarget(sprite, TRUE);
+
+ sprite->data[0] = gBattleAnimArgs[2];
+ sprite->callback = WaitAnimForDuration;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+static void AnimFistOrFootRandomPos(struct Sprite *sprite)
+{
+ u8 battler;
+ s16 xMod, yMod;
+ s16 x, y;
+
+ if (gBattleAnimArgs[0] == 0)
+ battler = gBattleAnimAttacker;
+ else
+ battler = gBattleAnimTarget;
+
+ if (gBattleAnimArgs[2] < 0)
+ gBattleAnimArgs[2] = Random2() % 5;
+
+ StartSpriteAnim(sprite, gBattleAnimArgs[2]);
+ sprite->pos1.x = GetBattlerSpriteCoord(battler, 2);
+ sprite->pos1.y = GetBattlerSpriteCoord(battler, 3);
+
+ xMod = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_WIDTH) / 2;
+ yMod = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_HEIGHT) / 4;
+
+ x = Random2() % xMod;
+ y = Random2() % yMod;
+
+ if (Random2() & 1)
+ x *= -1;
+ if (Random2() & 1)
+ y *= -1;
+
+ if ((gBattlerPositions[battler] & BIT_SIDE) == B_SIDE_PLAYER)
+ y += 0xFFF0;
+
+ sprite->pos1.x += x;
+ sprite->pos1.y += y;
+
+ sprite->data[0] = gBattleAnimArgs[1];
+ sprite->data[7] = CreateSprite(&gBasicHitSplatSpriteTemplate, sprite->pos1.x, sprite->pos1.y, sprite->subpriority + 1);
+ if (sprite->data[7] != 64)
+ {
+ StartSpriteAffineAnim(&gSprites[sprite->data[7]], 0);
+ gSprites[sprite->data[7]].callback = SpriteCallbackDummy;
+ }
+
+ sprite->callback = AnimFistOrFootRandomPos_Step;
+}
+
+static void AnimFistOrFootRandomPos_Step(struct Sprite *sprite)
+{
+ if (sprite->data[0] == 0)
+ {
+ if (sprite->data[7] != 64)
+ {
+ FreeOamMatrix(gSprites[sprite->data[7]].oam.matrixNum);
+ DestroySprite(&gSprites[sprite->data[7]]);
+ }
+
+ DestroyAnimSprite(sprite);
+ }
+ else
+ {
+ sprite->data[0]--;
+ }
+}
+
+static void AnimCrossChopHand(struct Sprite *sprite)
+{
+ InitSpritePosToAnimTarget(sprite, TRUE);
+ sprite->data[0] = 30;
+
+ if (gBattleAnimArgs[2] == 0)
+ {
+ sprite->data[2] = sprite->pos1.x - 20;
+ }
+ else
+ {
+ sprite->data[2] = sprite->pos1.x + 20;
+ sprite->hFlip = 1;
+ }
+
+ sprite->data[4] = sprite->pos1.y - 20;
+ sprite->callback = StartAnimLinearTranslation;
+ StoreSpriteCallbackInData6(sprite, AnimCrossChopHand_Step);
+}
+
+static void AnimCrossChopHand_Step(struct Sprite *sprite)
+{
+ if (++sprite->data[5] == 11)
+ {
+ sprite->data[2] = sprite->pos1.x - sprite->pos2.x;
+ sprite->data[4] = sprite->pos1.y - sprite->pos2.y;
+ sprite->data[0] = 8;
+ sprite->pos1.x += sprite->pos2.x;
+ sprite->pos1.y += sprite->pos2.y;
+ sprite->pos2.y = 0;
+ sprite->pos2.x = 0;
+
+ sprite->callback = StartAnimLinearTranslation;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+ }
+}
+
+// Rolling Kick / Low Kick
+static void AnimSlidingKick(struct Sprite *sprite)
+{
+ if (BATTLE_PARTNER(gBattleAnimAttacker) == gBattleAnimTarget && GetBattlerPosition(gBattleAnimTarget) < B_POSITION_PLAYER_RIGHT)
+ gBattleAnimArgs[0] *= -1;
+
+ InitSpritePosToAnimTarget(sprite, TRUE);
+
+ if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+
+ sprite->data[0] = gBattleAnimArgs[3];
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2];
+ sprite->data[3] = sprite->pos1.y;
+ sprite->data[4] = sprite->pos1.y;
+
+ InitAnimLinearTranslation(sprite);
+
+ sprite->data[5] = gBattleAnimArgs[5];
+ sprite->data[6] = gBattleAnimArgs[4];
+ sprite->data[7] = 0;
+
+ sprite->callback = AnimSlidingKick_Step;
+}
+
+static void AnimSlidingKick_Step(struct Sprite *sprite)
+{
+ if (!AnimTranslateLinear(sprite))
+ {
+ sprite->pos2.y += Sin(sprite->data[7] >> 8, sprite->data[5]);
+ sprite->data[7] += sprite->data[6];
+ }
+ else
+ {
+ DestroyAnimSprite(sprite);
+ }
+}
+
+// Animates the spinning, shrinking kick or punch, which then
+// reappears at full size. Used by moves such as MOVE_MEGA_PUNCH and MOVE_MEGA_KICK.
+// arg 0: initial x pixel offset
+// arg 1: initial y pixel offset
+// arg 2: anim num
+// arg 3: spin duration
+static void AnimSpinningKickOrPunch(struct Sprite *sprite)
+{
+ InitSpritePosToAnimTarget(sprite, TRUE);
+ StartSpriteAnim(sprite, gBattleAnimArgs[2]);
+ sprite->data[0] = gBattleAnimArgs[3];
+
+ sprite->callback = WaitAnimForDuration;
+ StoreSpriteCallbackInData6(sprite, AnimSpinningKickOrPunchFinish);
+}
+
+static void AnimSpinningKickOrPunchFinish(struct Sprite *sprite)
+{
+ StartSpriteAffineAnim(sprite, 0);
+ sprite->affineAnimPaused = 1;
+ sprite->data[0] = 20;
+
+ sprite->callback = WaitAnimForDuration;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+// Animates MOVE_STOMP's foot that slides downward.
+// arg 0: initial x pixel offset
+// arg 1: initial y pixel offset
+// arg 2: initial wait duration
+static void AnimStompFoot(struct Sprite *sprite)
+{
+ InitSpritePosToAnimTarget(sprite, TRUE);
+ sprite->data[0] = gBattleAnimArgs[2];
+
+ sprite->callback = AnimStompFoot_Step;
+}
+
+static void AnimStompFoot_Step(struct Sprite *sprite)
+{
+ if (--sprite->data[0] == -1)
+ {
+ sprite->data[0] = 6;
+ sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2);
+ sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3);
+
+ sprite->callback = StartAnimLinearTranslation;
+ StoreSpriteCallbackInData6(sprite, AnimStompFoot_End);
+ }
+}
+
+static void AnimStompFoot_End(struct Sprite *sprite)
+{
+ sprite->data[0] = 15;
+
+ sprite->callback = WaitAnimForDuration;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+static void AnimDizzyPunchDuck(struct Sprite *sprite)
+{
+ if (sprite->data[0] == 0)
+ {
+ InitSpritePosToAnimTarget(sprite, TRUE);
+ sprite->data[1] = gBattleAnimArgs[2];
+ sprite->data[2] = gBattleAnimArgs[3];
+ sprite->data[0]++;
+ }
+ else
+ {
+ sprite->data[4] += sprite->data[1];
+ sprite->pos2.x = sprite->data[4] >> 8;
+ sprite->pos2.y = Sin(sprite->data[3], sprite->data[2]);
+ sprite->data[3] = (sprite->data[3] + 3) & 0xFF;
+
+ if (sprite->data[3] > 100)
+ sprite->invisible = sprite->data[3] % 2;
+
+ if (sprite->data[3] > 120)
+ DestroyAnimSprite(sprite);
+ }
+}
+
+// The wall that appears when Brick Break is going to shatter the target's defensive wall
+static void AnimBrickBreakWall(struct Sprite *sprite)
+{
+ if (gBattleAnimArgs[0] == ANIM_ATTACKER)
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0);
+ sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1);
+ }
+ else
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0);
+ sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1);
+ }
+
+ sprite->pos1.x += gBattleAnimArgs[1];
+ sprite->pos1.y += gBattleAnimArgs[2];
+
+ sprite->data[0] = 0;
+ sprite->data[1] = gBattleAnimArgs[3];
+ sprite->data[2] = gBattleAnimArgs[4];
+ sprite->data[3] = 0;
+ sprite->callback = AnimBrickBreakWall_Step;
+}
+
+static void AnimBrickBreakWall_Step(struct Sprite *sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ if (--sprite->data[1] == 0)
+ {
+ if (sprite->data[2] == 0)
+ DestroyAnimSprite(sprite);
+ else
+ sprite->data[0]++;
+ }
+ break;
+ case 1:
+ if (++sprite->data[1] > 1)
+ {
+ sprite->data[1] = 0;
+ sprite->data[3]++;
+ if (sprite->data[3] & 1)
+ sprite->pos2.x = 2;
+ else
+ sprite->pos2.x = -2;
+ }
+
+ if (--sprite->data[2] == 0)
+ DestroyAnimSprite(sprite);
+ break;
+ }
+}
+
+// Piece of shattered defensive wall flies off. Used by Brick Break when the target has a defensive wall
+static void AnimBrickBreakWallShard(struct Sprite *sprite)
+{
+ if (gBattleAnimArgs[0] == ANIM_ATTACKER)
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0) + gBattleAnimArgs[2];
+ sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + gBattleAnimArgs[3];
+ }
+ else
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0) + gBattleAnimArgs[2];
+ sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + gBattleAnimArgs[3];
+ }
+
+ sprite->oam.tileNum += gBattleAnimArgs[1] * 16;
+ sprite->data[0] = 0;
+
+ switch (gBattleAnimArgs[1])
+ {
+ case 0:
+ sprite->data[6] = -3;
+ sprite->data[7] = -3;
+ break;
+ case 1:
+ sprite->data[6] = 3;
+ sprite->data[7] = -3;
+ break;
+ case 2:
+ sprite->data[6] = -3;
+ sprite->data[7] = 3;
+ break;
+ case 3:
+ sprite->data[6] = 3;
+ sprite->data[7] = 3;
+ break;
+ default:
+ DestroyAnimSprite(sprite);
+ return;
+ }
+
+ sprite->callback = AnimBrickBreakWallShard_Step;
+}
+
+static void AnimBrickBreakWallShard_Step(struct Sprite *sprite)
+{
+ sprite->pos1.x += sprite->data[6];
+ sprite->pos1.y += sprite->data[7];
+
+ if (++sprite->data[0] > 40)
+ DestroyAnimSprite(sprite);
+}
+
+static void AnimSuperpowerOrb(struct Sprite *sprite)
+{
+ if (gBattleAnimArgs[0] == ANIM_ATTACKER)
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord(gBattlerAttacker, 2);
+ sprite->pos1.y = GetBattlerSpriteCoord(gBattlerAttacker, 3);
+ sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker);
+ sprite->data[7] = gBattleAnimTarget;
+ }
+ else
+ {
+ sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget);
+ sprite->data[7] = gBattleAnimAttacker;
+ }
+
+ sprite->data[0] = 0;
+ sprite->data[1] = 12;
+ sprite->data[2] = 8;
+ sprite->callback = AnimSuperpowerOrb_Step;
+}
+
+static void AnimSuperpowerOrb_Step(struct Sprite *sprite)
+{
+ if (++sprite->data[0] == 180)
+ {
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+
+ sprite->data[0] = 16;
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[2] = GetBattlerSpriteCoord(sprite->data[7], 2);
+ sprite->data[3] = sprite->pos1.y;
+ sprite->data[4] = GetBattlerSpriteCoord(sprite->data[7], 3);
+
+ InitAnimLinearTranslation(sprite);
+ StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix);
+ sprite->callback = sub_80A6F98;
+ }
+}
+
+// Floating rock that flies off to hit the target. Used by Superpower
+static void AnimSuperpowerRock(struct Sprite *sprite)
+{
+ sprite->pos1.x = gBattleAnimArgs[0];
+ sprite->pos1.y = 120;
+
+ sprite->data[0] = gBattleAnimArgs[3];
+ StorePointerInVars(&sprite->data[4], &sprite->data[5], (void *)(sprite->pos1.y << 8));
+
+ sprite->data[6] = gBattleAnimArgs[1];
+ sprite->oam.tileNum += gBattleAnimArgs[2] * 4;
+
+ sprite->callback = AnimSuperpowerRock_Step1;
+}
+
+static void AnimSuperpowerRock_Step1(struct Sprite *sprite)
+{
+ void *var0;
+
+ if (sprite->data[0] != 0)
+ {
+ var0 = LoadPointerFromVars(sprite->data[4], sprite->data[5]);
+ var0 -= sprite->data[6];
+ StorePointerInVars(&sprite->data[4], &sprite->data[5], var0);
+
+ var0 = (void *)(((intptr_t)var0) >> 8);
+ sprite->pos1.y = (intptr_t)var0;
+ if (sprite->pos1.y < -8)
+ DestroyAnimSprite(sprite);
+ else
+ sprite->data[0]--;
+ }
+ else
+ {
+ s16 pos0 = GetBattlerSpriteCoord(gBattleAnimAttacker, 2);
+ s16 pos1 = GetBattlerSpriteCoord(gBattleAnimAttacker, 3);
+ s16 pos2 = GetBattlerSpriteCoord(gBattleAnimTarget, 2);
+ s16 pos3 = GetBattlerSpriteCoord(gBattleAnimTarget, 3);
+
+ sprite->data[0] = pos2 - pos0;
+ sprite->data[1] = pos3 - pos1;
+ sprite->data[2] = sprite->pos1.x << 4;
+ sprite->data[3] = sprite->pos1.y << 4;
+
+ sprite->callback = AnimSuperpowerRock_Step2;
+ }
+}
+
+static void AnimSuperpowerRock_Step2(struct Sprite *sprite)
+{
+ u16 edgeX;
+
+ sprite->data[2] += sprite->data[0];
+ sprite->data[3] += sprite->data[1];
+ sprite->pos1.x = sprite->data[2] >> 4;
+ sprite->pos1.y = sprite->data[3] >> 4;
+
+ edgeX = sprite->pos1.x + 8;
+ if (edgeX > 256 || sprite->pos1.y < -8 || sprite->pos1.y > 120)
+ DestroyAnimSprite(sprite);
+}
+
+static void AnimSuperpowerFireball(struct Sprite *sprite)
+{
+ u8 battler;
+
+ if (gBattleAnimArgs[0] == ANIM_ATTACKER)
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord(gBattlerAttacker, 2);
+ sprite->pos1.y = GetBattlerSpriteCoord(gBattlerAttacker, 3);
+ battler = gBattleAnimTarget;
+ sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker);
+ }
+ else
+ {
+ battler = gBattleAnimAttacker;
+ sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget);
+ }
+
+ if (IsContest())
+ sprite->oam.matrixNum |= ST_OAM_HFLIP;
+ else if (GetBattlerSide(battler) == B_SIDE_PLAYER)
+ sprite->oam.matrixNum |= (ST_OAM_HFLIP | ST_OAM_VFLIP);
+
+ sprite->data[0] = 16;
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[2] = GetBattlerSpriteCoord(battler, 2);
+ sprite->data[3] = sprite->pos1.y;
+ sprite->data[4] = GetBattlerSpriteCoord(battler, 3);
+
+ InitAnimLinearTranslation(sprite);
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+ sprite->callback = sub_80A6F98;
+}
+
+static void AnimArmThrustHit_Step(struct Sprite *sprite)
+{
+ if (sprite->data[0] == sprite->data[4])
+ DestroyAnimSprite(sprite);
+
+ sprite->data[0]++;
+}
+
+static void AnimArmThrustHit(struct Sprite *sprite)
+{
+ u8 turn;
+
+ sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2);
+ sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3);
+ sprite->data[1] = gBattleAnimArgs[3];
+ sprite->data[2] = gBattleAnimArgs[0];
+ sprite->data[3] = gBattleAnimArgs[1];
+ sprite->data[4] = gBattleAnimArgs[2];
+
+ turn = gAnimMoveTurn;
+ if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)
+ turn++;
+
+ if (turn & 1)
+ {
+ sprite->data[2] = -sprite->data[2];
+ sprite->data[1]++;
+ }
+
+ StartSpriteAnim(sprite, sprite->data[1]);
+ sprite->pos2.x = sprite->data[2];
+ sprite->pos2.y = sprite->data[3];
+ sprite->callback = AnimArmThrustHit_Step;
+}
+
+static void AnimRevengeScratch(struct Sprite *sprite)
+{
+ if (gBattleAnimArgs[2] == ANIM_ATTACKER)
+ InitSpritePosToAnimAttacker(sprite, 0);
+ else
+ InitSpritePosToAnimTarget(sprite, FALSE);
+
+ if (IsContest())
+ {
+ StartSpriteAnim(sprite, 2);
+ }
+ else if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ {
+ StartSpriteAnim(sprite, 1);
+ }
+
+ sprite->callback = RunStoredCallbackWhenAnimEnds;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+// Fist shrinks toward target and shakes
+static void AnimFocusPunchFist(struct Sprite *sprite)
+{
+ if (sprite->affineAnimEnded)
+ {
+ sprite->data[1] = (sprite->data[1] + 40) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data[1], 2);
+ if (++sprite->data[0] > 40)
+ DestroyAnimSprite(sprite);
+ }
+}
+
+void AnimTask_MoveSkyUppercutBg(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ sub_80A6DAC(0);
+ task->data[8] = gBattleAnimArgs[0];
+ task->data[0]++;
+ break;
+ case 1:
+ if (--task->data[8] == -1)
+ task->data[0]++;
+ break;
+ case 2:
+ default:
+ task->data[9] += 1280;
+ break;
+ }
+
+ task->data[10] += 2816;
+
+ if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)
+ gBattle_BG3_X += task->data[9] >> 8;
+ else
+ gBattle_BG3_X -= task->data[9] >> 8;
+
+ gBattle_BG3_Y += task->data[10] >> 8;
+ task->data[9] &= 0xFF;
+ task->data[10] &= 0xFF;
+
+ if (gBattleAnimArgs[7] == -1)
+ {
+ gBattle_BG3_X = 0;
+ gBattle_BG3_Y = 0;
+ sub_80A6DAC(1);
+ DestroyAnimVisualTask(taskId);
+ }
+}