summaryrefslogtreecommitdiff
path: root/src/battle/anim
diff options
context:
space:
mode:
Diffstat (limited to 'src/battle/anim')
-rw-r--r--src/battle/anim/battle_intro.c7
-rw-r--r--src/battle/anim/flying.c291
-rw-r--r--src/battle/anim/ground.c704
3 files changed, 961 insertions, 41 deletions
diff --git a/src/battle/anim/battle_intro.c b/src/battle/anim/battle_intro.c
index d96dc7ea8..a189b1425 100644
--- a/src/battle/anim/battle_intro.c
+++ b/src/battle/anim/battle_intro.c
@@ -12,11 +12,6 @@
#include "trig.h"
extern u16 gBattleTypeFlags;
-extern u16 gBattle_BG1_X;
-extern u16 gBattle_BG1_Y;
-extern u16 gBattle_BG2_X;
-extern u16 gBattle_BG2_Y;
-extern u16 gBattle_WIN0V;
extern u16 gUnknown_02024DE8;
extern u8 gBattleMonForms[];
@@ -376,7 +371,7 @@ static void BattleIntroTask_ScrollAndFadeScenery(u8 taskId)
REG_BLDALPHA = gTasks[taskId].data[4];
}
-// Seems to only be used for link battles.
+// Seems to only be used for link battles.
static void BattleIntroTask_80E4C34(u8 taskId)
{
s32 i;
diff --git a/src/battle/anim/flying.c b/src/battle/anim/flying.c
index ec40e26c4..e8c50816c 100644
--- a/src/battle/anim/flying.c
+++ b/src/battle/anim/flying.c
@@ -1,17 +1,26 @@
#include "global.h"
-#include "rom_8077ABC.h"
+#include "battle.h"
#include "battle_anim.h"
+#include "palette.h"
+#include "rom_8077ABC.h"
+#include "trig.h"
extern s16 gBattleAnimArgs[];
extern u8 gAnimBankAttacker;
extern u8 gAnimBankTarget;
+extern u8 gAnimVisualTaskCount;
+void sub_80785E4(struct Sprite *sprite);
void sub_80DA034(struct Sprite *sprite);
+void sub_80DA05C(struct Sprite *sprite);
void sub_80DA16C(struct Sprite *sprite);
+void sub_80DA1EC(struct Sprite *sprite);
void sub_80DA208(struct Sprite *sprite);
void sub_80DA300(struct Sprite *sprite);
+void sub_80DA348(struct Sprite *sprite);
void sub_80DA38C(struct Sprite *sprite);
void sub_80DA4D8(struct Sprite *sprite);
+void sub_80DA410(struct Sprite *sprite);
void sub_80DAD30(struct Sprite *sprite);
void sub_80DAD84(struct Sprite *sprite);
void sub_80DB000(struct Sprite *sprite);
@@ -23,6 +32,8 @@ void sub_80DB458(struct Sprite *sprite);
void sub_80DB564(struct Sprite *sprite);
void sub_80DB5E4(struct Sprite *sprite);
+void sub_80DA0DC(u8 taskId);
+
const struct SpriteTemplate gBattleAnimSpriteTemplate_83DA380 =
{
.tileTag = 10009,
@@ -344,3 +355,281 @@ const struct SpriteTemplate gBattleAnimSpriteTemplate_83DA65C =
.affineAnims = gDummySpriteAffineAnimTable,
.callback = sub_80DB5E4,
};
+
+void sub_80DA034(struct Sprite *sprite)
+{
+ sub_8078764(sprite, 0);
+ sprite->pos1.y += 20;
+ sprite->data[1] = 0xBF;
+ sprite->callback = sub_80DA05C;
+ sub_80DA05C(sprite);
+}
+
+void sub_80DA05C(struct Sprite *sprite)
+{
+ sprite->pos2.x = Sin(sprite->data[1], 0x20);
+ sprite->pos2.y = Cos(sprite->data[1], 0x8);
+ sprite->data[1] = (sprite->data[1] + 5) & 0xFF;
+ if(++sprite->data[0] == 0x47)
+ {
+ DestroyAnimSprite(sprite);
+ }
+}
+
+void sub_80DA09C(u8 taskId)
+{
+ gTasks[taskId].data[0] = gBattleAnimArgs[1];
+ gTasks[taskId].data[1] = gBattleAnimArgs[0];
+ gTasks[taskId].data[2] = IndexOfSpritePaletteTag(0x2719);
+ gTasks[taskId].func = sub_80DA0DC;
+}
+
+#ifdef NONMATCHING
+void sub_80DA0DC(u8 taskId)
+{
+ gTasks[taskId].data[10]++;
+ if(gTasks[taskId].data[10] == gTasks[taskId].data[1])
+ {
+ u16 r0;
+ u16 r2;
+ s32 i;
+
+ gTasks[taskId].data[10] = 0;
+ r0 = gTasks[taskId].data[2];
+ r2 = gPlttBufferFaded[r0 * 8];
+ for(i = 0; i < 8; i++)
+ gPlttBufferFaded[r0 * 8 + i + 0x107] = gPlttBufferFaded[r0 * 8 + i + 0x107];
+ gTasks[taskId].data[2] = ((r0 + 0x101) * 2) + r2;
+ }
+ gTasks[taskId].data[0] = gTasks[taskId].data[0] * 32;
+ if(gTasks[taskId].data[0] == 0)
+ {
+ DestroyAnimVisualTask(taskId);
+ }
+}
+#else
+NAKED
+void sub_80DA0DC(u8 taskId)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ ldr r2, _080DA15C @ =gTasks\n\
+ lsls r0, r5, 2\n\
+ adds r0, r5\n\
+ lsls r0, 3\n\
+ adds r3, r0, r2\n\
+ ldrh r0, [r3, 0x1C]\n\
+ adds r1, r0, 0x1\n\
+ strh r1, [r3, 0x1C]\n\
+ lsls r0, 16\n\
+ asrs r0, 16\n\
+ movs r4, 0xA\n\
+ ldrsh r1, [r3, r4]\n\
+ adds r7, r2, 0\n\
+ cmp r0, r1\n\
+ bne _080DA13A\n\
+ movs r0, 0\n\
+ strh r0, [r3, 0x1C]\n\
+ ldrb r0, [r3, 0xC]\n\
+ ldr r2, _080DA160 @ =gPlttBufferFaded\n\
+ lsls r0, 4\n\
+ movs r3, 0x84\n\
+ lsls r3, 1\n\
+ adds r1, r0, r3\n\
+ lsls r1, 1\n\
+ adds r1, r2\n\
+ ldrh r6, [r1]\n\
+ movs r4, 0x7\n\
+ mov r12, r0\n\
+ ldr r0, _080DA164 @ =0x00000107\n\
+ add r0, r12\n\
+ lsls r0, 1\n\
+ adds r3, r0, r2\n\
+_080DA122:\n\
+ ldrh r0, [r3]\n\
+ strh r0, [r1]\n\
+ subs r3, 0x2\n\
+ subs r1, 0x2\n\
+ subs r4, 0x1\n\
+ cmp r4, 0\n\
+ bgt _080DA122\n\
+ ldr r0, _080DA168 @ =0x00000101\n\
+ add r0, r12\n\
+ lsls r0, 1\n\
+ adds r0, r2\n\
+ strh r6, [r0]\n\
+_080DA13A:\n\
+ lsls r0, r5, 2\n\
+ adds r0, r5\n\
+ lsls r0, 3\n\
+ adds r0, r7\n\
+ ldrh r1, [r0, 0x8]\n\
+ subs r1, 0x1\n\
+ strh r1, [r0, 0x8]\n\
+ lsls r1, 16\n\
+ cmp r1, 0\n\
+ bne _080DA154\n\
+ adds r0, r5, 0\n\
+ bl DestroyAnimVisualTask\n\
+_080DA154:\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_080DA15C: .4byte gTasks\n\
+_080DA160: .4byte gPlttBufferFaded\n\
+_080DA164: .4byte 0x00000107\n\
+_080DA168: .4byte 0x00000101\n\
+ .syntax divided\n");
+}
+#endif
+
+void sub_80DA16C(struct Sprite *sprite)
+{
+ InitAnimSpritePos(sprite, 1);
+ if (GetBattlerSide(gAnimBankAttacker) != B_SIDE_PLAYER)
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ sprite->data[0] = gBattleAnimArgs[4];
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[2] = GetBattlerSpriteCoord(gAnimBankTarget, 2) + gBattleAnimArgs[2];
+ sprite->data[3] = sprite->pos1.y;
+ sprite->data[4] = GetBattlerSpriteCoord(gAnimBankTarget, 3) + gBattleAnimArgs[3];
+ InitAnimSpriteTranslationDeltas(sprite);
+ sprite->callback = sub_80785E4;
+ StoreSpriteCallbackInData(sprite, sub_80DA1EC);
+}
+
+void sub_80DA1EC(struct Sprite *sprite)
+{
+ if (TranslateAnimSpriteByDeltas(sprite) != 0)
+ {
+ DestroyAnimSprite(sprite);
+ }
+}
+
+void sub_80DA208(struct Sprite *sprite)
+{
+ if (GetBattlerSide(gAnimBankAttacker) != B_SIDE_PLAYER)
+ {
+ gBattleAnimArgs[0] = -gBattleAnimArgs[0];
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ gBattleAnimArgs[3] = -gBattleAnimArgs[3];
+ }
+
+ if (IsContest())
+ {
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ gBattleAnimArgs[3] = -gBattleAnimArgs[3];
+ }
+
+ sprite->pos1.x = GetBattlerSpriteCoord(gAnimBankAttacker, 2);
+ sprite->pos1.y = GetBattlerSpriteCoord(gAnimBankAttacker, 3);
+ sprite->pos1.x += gBattleAnimArgs[0];
+ sprite->pos1.y += gBattleAnimArgs[1];
+ sprite->data[0] = gBattleAnimArgs[4];
+
+ if (gBattleAnimArgs[6] == 0)
+ {
+ sprite->data[2] = GetBattlerSpriteCoord(gAnimBankTarget, 2);
+ sprite->data[4] = GetBattlerSpriteCoord(gAnimBankTarget, 3);
+ }
+ else
+ {
+ SetAverageBattlerPositions(gAnimBankTarget, 1, &sprite->data[2], &sprite->data[4]);
+ }
+
+ sprite->data[2] = sprite->data[2] + gBattleAnimArgs[2];
+ sprite->data[4] = sprite->data[4] + gBattleAnimArgs[3];
+ sprite->callback = StartTranslateAnimSpriteByDeltas;
+
+ StoreSpriteCallbackInData(sprite, DestroyAnimSprite);
+ SeekSpriteAnim(sprite, gBattleAnimArgs[5]);
+}
+
+void sub_80DA300(struct Sprite *sprite)
+{
+ InitAnimSpritePos(sprite, 1);
+ sprite->data[0] = gBattleAnimArgs[2];
+ sprite->data[1] = gBattleAnimArgs[3];
+ sprite->callback = sub_80DA348;
+ gSprites[GetAnimBattlerSpriteId(0)].invisible = 1;
+}
+
+void sub_80DA348(struct Sprite *sprite)
+{
+ if (sprite->data[0] > 0)
+ {
+ sprite->data[0]--;
+ }
+ else
+ {
+ sprite->data[2] += sprite->data[1];
+ sprite->pos2.y -= (sprite->data[2] >> 8);
+ }
+
+ if (sprite->pos1.y + sprite->pos2.y < -32)
+ {
+ DestroyAnimSprite(sprite);
+ }
+}
+
+void sub_80DA38C(struct Sprite *sprite)
+{
+ if (GetBattlerSide(gAnimBankAttacker) != B_SIDE_PLAYER)
+ {
+ sprite->pos1.x = 272;
+ sprite->pos1.y = -32;
+ StartSpriteAffineAnim(sprite, 1);
+ }
+ else
+ {
+ sprite->pos1.x = -32;
+ sprite->pos1.y = -32;
+ }
+
+ sprite->data[0] = gBattleAnimArgs[0];
+ sprite->data[1] = sprite->pos1.x;
+ sprite->data[2] = GetBattlerSpriteCoord(gAnimBankTarget, 2);
+ sprite->data[3] = sprite->pos1.y;
+ sprite->data[4] = GetBattlerSpriteCoord(gAnimBankTarget, 3);
+
+ InitAnimSpriteTranslationDeltas(sprite);
+ sprite->callback = sub_80DA410;
+}
+
+void sub_80DA410(struct Sprite *sprite)
+{
+ sprite->data[0] = 1;
+ TranslateAnimSpriteByDeltas(sprite);
+
+ if (((u16)sprite->data[3] >> 8) > 200)
+ {
+ sprite->pos1.x += sprite->pos2.x;
+ sprite->pos2.x = 0;
+ sprite->data[3] &= 0xFF;
+ }
+
+ if ((u32)(sprite->pos1.x + sprite->pos2.x + 32) > 304 || sprite->pos1.y + sprite->pos2.y > 160)
+ {
+ gSprites[GetAnimBattlerSpriteId(0)].invisible = 0;
+ DestroyAnimSprite(sprite);
+ }
+}
+
+void sub_80DA48C(struct Sprite *sprite)
+{
+ if (sprite->data[0]-- <= 0)
+ {
+ if (sprite->oam.affineMode & 1)
+ {
+ FreeOamMatrix(sprite->oam.matrixNum);
+ sprite->oam.affineMode = 0;
+ }
+
+ DestroySprite(sprite);
+ gAnimVisualTaskCount--;
+ }
+}
diff --git a/src/battle/anim/ground.c b/src/battle/anim/ground.c
index a523df20e..67b4c9c9c 100644
--- a/src/battle/anim/ground.c
+++ b/src/battle/anim/ground.c
@@ -1,64 +1,90 @@
#include "global.h"
-#include "rom_8077ABC.h"
+#include "battle.h"
#include "battle_anim.h"
+#include "scanline_effect.h"
+#include "random.h"
+#include "rom_8077ABC.h"
+#include "task.h"
+#include "trig.h"
extern s16 gBattleAnimArgs[];
extern u8 gAnimBankAttacker;
extern u8 gAnimBankTarget;
+extern u16 gBattle_BG1_X;
+extern u16 gBattle_BG1_Y;
+extern u16 gBattle_BG2_X;
+extern u16 gBattle_BG2_Y;
+extern u16 gBattle_BG3_X;
+extern u16 gBattle_BG3_Y;
+extern u16 gAnimMovePower;
+extern u8 gBankSpriteIds[];
-void sub_80E0F1C(struct Sprite *sprite);
-void sub_80E1004(struct Sprite *sprite);
-void sub_80E1078(struct Sprite *sprite);
-void sub_80E1078(struct Sprite *sprite);
-void sub_80E1108(struct Sprite *sprite);
-void sub_80E1728(struct Sprite *sprite);
-void sub_80E17CC(struct Sprite *sprite);
+static void AnimBonemerangProjectile(struct Sprite *sprite);
+static void AnimBonemerangProjectileStep(struct Sprite *sprite);
+static void AnimBonemerangProjectileEnd(struct Sprite *sprite);
+static void AnimBoneHitProjectile(struct Sprite *sprite);
+static void AnimDirtScatter(struct Sprite *sprite);
+static void AnimMudSportDirt(struct Sprite *sprite);
+static void AnimMudSportDirtRising(struct Sprite *sprite);
+static void AnimMudSportDirtFalling(struct Sprite *sprite);
+static void sub_80E1284(u8 taskId);
+static void sub_80E1668(u8, s16, s16);
+static void sub_80E143C(u8 taskId);
+static void sub_80E14DC(u8 taskId);
+static void sub_80E1560(u8 taskId);
+static void AnimFissureDirtPlumeParticle(struct Sprite *sprite);
+static void AnimFissureDirtPlumeParticleStep(struct Sprite *sprite);
+static void AnimDigDirtMound(struct Sprite *sprite);
+static void sub_80E1934(u8 taskId);
+static void sub_80E1A2C(u8 taskId);
+static void sub_80E1B10(struct Task *task);
+static void sub_80E1C58(u8 taskId);
-const union AffineAnimCmd gSpriteAffineAnim_83DB2A0[] =
+const union AffineAnimCmd gBonemerangSpriteAffineAnim[] =
{
AFFINEANIMCMD_FRAME(0x0, 0x0, 15, 1),
AFFINEANIMCMD_JUMP(0),
};
-const union AffineAnimCmd gSpriteAffineAnim_83DB2B0[] =
+const union AffineAnimCmd gBoneHitSpriteAffineAnim[] =
{
AFFINEANIMCMD_FRAME(0x0, 0x0, 20, 1),
AFFINEANIMCMD_JUMP(0),
};
-const union AffineAnimCmd *const gSpriteAffineAnimTable_83DB2C0[] =
+const union AffineAnimCmd *const gBonemerangSpriteAffineAnimTable[] =
{
- gSpriteAffineAnim_83DB2A0,
+ gBonemerangSpriteAffineAnim,
};
-const union AffineAnimCmd *const gSpriteAffineAnimTable_83DB2C4[] =
+const union AffineAnimCmd *const gBoneHitSpriteAffineAnimTable[] =
{
- gSpriteAffineAnim_83DB2B0,
+ gBoneHitSpriteAffineAnim,
};
-const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB2C8 =
+const struct SpriteTemplate gBonemerangSpriteTemplate =
{
.tileTag = 10000,
.paletteTag = 10000,
.oam = &gOamData_837DF94,
.anims = gDummySpriteAnimTable,
.images = NULL,
- .affineAnims = gSpriteAffineAnimTable_83DB2C0,
- .callback = sub_80E0F1C,
+ .affineAnims = gBonemerangSpriteAffineAnimTable,
+ .callback = AnimBonemerangProjectile,
};
-const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB2E0 =
+const struct SpriteTemplate gBoneHitSpriteTemplate =
{
.tileTag = 10000,
.paletteTag = 10000,
.oam = &gOamData_837DF94,
.anims = gDummySpriteAnimTable,
.images = NULL,
- .affineAnims = gSpriteAffineAnimTable_83DB2C4,
- .callback = sub_80E1004,
+ .affineAnims = gBoneHitSpriteAffineAnimTable,
+ .callback = AnimBoneHitProjectile,
};
-const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB2F8 =
+const struct SpriteTemplate gSandAttackDirtSpriteTemplate =
{
.tileTag = 10074,
.paletteTag = 10074,
@@ -66,32 +92,32 @@ const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB2F8 =
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
- .callback = sub_80E1078,
+ .callback = AnimDirtScatter,
};
-const union AnimCmd gSpriteAnim_83DB310[] =
+const union AnimCmd gMudSlapDirtSpriteAnim[] =
{
ANIMCMD_FRAME(1, 1),
ANIMCMD_END,
};
-const union AnimCmd *const gSpriteAnimTable_83DB318[] =
+const union AnimCmd *const gMudSlapDirtSpriteAnimTable[] =
{
- gSpriteAnim_83DB310,
+ gMudSlapDirtSpriteAnim,
};
-const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB31C =
+const struct SpriteTemplate gMudSlapDirtSpriteTemplate =
{
.tileTag = 10074,
.paletteTag = 10074,
.oam = &gOamData_837DF2C,
- .anims = gSpriteAnimTable_83DB318,
+ .anims = gMudSlapDirtSpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
- .callback = sub_80E1078,
+ .callback = AnimDirtScatter,
};
-const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB334 =
+const struct SpriteTemplate gMudSportDirtSpriteTemplate =
{
.tileTag = 10074,
.paletteTag = 10074,
@@ -99,10 +125,10 @@ const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB334 =
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
- .callback = sub_80E1108,
+ .callback = AnimMudSportDirt,
};
-const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB34C =
+const struct SpriteTemplate gDirtPlumeSpriteTemplate =
{
.tileTag = 10074,
.paletteTag = 10074,
@@ -110,10 +136,10 @@ const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB34C =
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
- .callback = sub_80E1728,
+ .callback = AnimFissureDirtPlumeParticle,
};
-const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB364 =
+const struct SpriteTemplate gDigDirtMoundSpriteTemplate =
{
.tileTag = 10281,
.paletteTag = 10281,
@@ -121,5 +147,615 @@ const struct SpriteTemplate gBattleAnimSpriteTemplate_83DB364 =
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
- .callback = sub_80E17CC,
+ .callback = AnimDigDirtMound,
};
+
+// Moves a bone projectile towards the target mon, which moves like
+// a boomerang. After hitting the target mon, it comes back to the user.
+static void AnimBonemerangProjectile(struct Sprite *sprite)
+{
+ sprite->pos1.x = GetBattlerSpriteCoord(gAnimBankAttacker, 2);
+ sprite->pos1.y = GetBattlerSpriteCoord(gAnimBankAttacker, 3);
+ sprite->data[0] = 20;
+ sprite->data[2] = GetBattlerSpriteCoord(gAnimBankTarget, 2);
+ sprite->data[4] = GetBattlerSpriteCoord(gAnimBankTarget, 3);
+ sprite->data[5] = -40;
+ InitAnimSpriteTranslationOverDuration(sprite);
+ sprite->callback = AnimBonemerangProjectileStep;
+}
+
+static void AnimBonemerangProjectileStep(struct Sprite *sprite)
+{
+ if (TranslateAnimSpriteLinearAndSine(sprite))
+ {
+ sprite->pos1.x += sprite->pos2.x;
+ sprite->pos1.y += sprite->pos2.y;
+ sprite->pos2.y = 0;
+ sprite->pos2.x = 0;
+ sprite->data[0] = 20;
+ sprite->data[2] = GetBattlerSpriteCoord(gAnimBankAttacker, 2);
+ sprite->data[4] = GetBattlerSpriteCoord(gAnimBankAttacker, 3);
+ sprite->data[5] = 40;
+ InitAnimSpriteTranslationOverDuration(sprite);
+ sprite->callback = AnimBonemerangProjectileEnd;
+ }
+}
+
+static void AnimBonemerangProjectileEnd(struct Sprite *sprite)
+{
+ if (TranslateAnimSpriteLinearAndSine(sprite))
+ DestroyAnimSprite(sprite);
+}
+
+// Moves a bone projectile towards the target mon, starting right next to
+// the target mon.
+// arg 0: initial x pixel offset
+// arg 1: initial y pixel offset
+// arg 2: target x pixel offset
+// arg 3: target y pixel offset
+// arg 4: duration
+static void AnimBoneHitProjectile(struct Sprite *sprite)
+{
+ sub_8078764(sprite, 1);
+ if (GetBattlerSide(gAnimBankAttacker) != B_SIDE_PLAYER)
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+
+ sprite->data[0] = gBattleAnimArgs[4];
+ sprite->data[2] = GetBattlerSpriteCoord(gAnimBankTarget, 2) + gBattleAnimArgs[2];
+ sprite->data[4] = GetBattlerSpriteCoord(gAnimBankTarget, 3) + gBattleAnimArgs[3];
+ sprite->callback = StartTranslateAnimSpriteByDeltas;
+ StoreSpriteCallbackInData(sprite, DestroyAnimSprite);
+}
+
+// Moves a small dirt projectile towards the target mon.
+// arg 0: initial x pixel offset
+// arg 1: initial y pixel offset
+// arg 2: duration
+// arg 3: target x pixel offset
+// arg 4: target y pixel offset
+static void AnimDirtScatter(struct Sprite *sprite)
+{
+ u8 targetXPos, targetYPos;
+ s16 xOffset, yOffset;
+
+ InitAnimSpritePos(sprite, 1);
+
+ targetXPos = sub_8077EE4(gAnimBankTarget, 2);
+ targetYPos = sub_8077EE4(gAnimBankTarget, 3);
+
+ xOffset = Random() & 0x1F;
+ yOffset = Random() & 0x1F;
+ if (xOffset > 16)
+ xOffset = 16 - xOffset;
+ if (yOffset > 16)
+ yOffset = 16 - yOffset;
+
+ sprite->data[0] = gBattleAnimArgs[2];
+ sprite->data[2] = targetXPos + xOffset;
+ sprite->data[4] = targetYPos + yOffset;
+ sprite->callback = StartTranslateAnimSpriteByDeltas;
+ StoreSpriteCallbackInData(sprite, move_anim_8074EE0);
+}
+
+// Moves a particle of dirt in the Mud Sport animation.
+// The dirt can either be rising upward, or falling down.
+// arg 0: 0 = dirt is rising into the air, 1 = dirt is falling down
+// arg 1: initial x pixel offset
+// arg 2: initial y pixel offset
+static void AnimMudSportDirt(struct Sprite *sprite)
+{
+ sprite->oam.tileNum++;
+ if (gBattleAnimArgs[0] == 0)
+ {
+ sprite->pos1.x = GetBattlerSpriteCoord(gAnimBankAttacker, 2) + gBattleAnimArgs[1];
+ sprite->pos1.y = GetBattlerSpriteCoord(gAnimBankAttacker, 3) + gBattleAnimArgs[2];
+ sprite->data[0] = gBattleAnimArgs[1] > 0 ? 1 : -1;
+ sprite->callback = AnimMudSportDirtRising;
+ }
+ else
+ {
+ sprite->pos1.x = gBattleAnimArgs[1];
+ sprite->pos1.y = gBattleAnimArgs[2];
+ sprite->pos2.y = -gBattleAnimArgs[2];
+ sprite->callback = AnimMudSportDirtFalling;
+ }
+}
+
+static void AnimMudSportDirtRising(struct Sprite *sprite)
+{
+ if (++sprite->data[1] > 1)
+ {
+ sprite->data[1] = 0;
+ sprite->pos1.x += sprite->data[0];
+ }
+
+ sprite->pos1.y -= 4;
+ if (sprite->pos1.y < -4)
+ DestroyAnimSprite(sprite);
+}
+
+static void AnimMudSportDirtFalling(struct Sprite *sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ sprite->pos2.y += 4;
+ if (sprite->pos2.y >= 0)
+ {
+ sprite->pos2.y = 0;
+ sprite->data[0]++;
+ }
+ break;
+ case 1:
+ if (++sprite->data[1] > 0)
+ {
+ sprite->data[1] = 0;
+ sprite->invisible ^= 1;
+ if (++sprite->data[2] == 10)
+ DestroyAnimSprite(sprite);
+ }
+ break;
+ }
+}
+
+void sub_80E1244(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ if (gBattleAnimArgs[0] == 0)
+ task->func = sub_80E1284;
+ else
+ task->func = sub_80E143C;
+
+ task->func(taskId);
+}
+
+static void sub_80E1284(u8 taskId)
+{
+ u8 var0;
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ task->data[10] = GetAnimBattlerSpriteId(0);
+ task->data[11] = GetBattlerPosition_permutated(gAnimBankAttacker);
+ if (task->data[11] == 1)
+ {
+ task->data[12] = gBattle_BG1_X;
+ task->data[13] = gBattle_BG1_Y;
+ }
+ else
+ {
+ task->data[12] = gBattle_BG2_X;
+ task->data[13] = gBattle_BG2_Y;
+ }
+
+ var0 = sub_8077FC0(gAnimBankAttacker);
+ task->data[14] = var0 - 32;
+ task->data[15] = var0 + 32;
+ if (task->data[14] < 0)
+ task->data[14] = 0;
+
+ gSprites[task->data[10]].invisible = 1;
+ task->data[0]++;
+ break;
+ case 1:
+ sub_80E1668(task->data[11], task->data[14], task->data[15]);
+ task->data[0]++;
+ break;
+ case 2:
+ task->data[2] = (task->data[2] + 6) & 0x7F;
+ if (++task->data[4] > 2)
+ {
+ task->data[4] = 0;
+ task->data[3]++;
+ }
+
+ task->data[5] = task->data[3] + (gSineTable[task->data[2]] >> 4);
+ if (task->data[11] == 1)
+ gBattle_BG1_Y = task->data[13] - task->data[5];
+ else
+ gBattle_BG2_Y = task->data[13] - task->data[5];
+
+ if (task->data[5] > 63)
+ {
+ task->data[5] = 120 - task->data[14];
+ if (task->data[11] == 1)
+ gBattle_BG1_Y = task->data[13] - task->data[5];
+ else
+ gBattle_BG2_Y = task->data[13] - task->data[5];
+
+ gSprites[task->data[10]].pos2.x = 272 - gSprites[task->data[10]].pos1.x;
+ task->data[0]++;
+ }
+ break;
+ case 3:
+ gScanlineEffect.state = 3;
+ task->data[0]++;
+ break;
+ case 4:
+ DestroyAnimVisualTask(taskId);
+ gSprites[task->data[10]].invisible = 1;
+ break;
+ }
+}
+
+static void sub_80E143C(u8 taskId)
+{
+ u8 spriteId = GetAnimBattlerSpriteId(0);
+ gSprites[spriteId].invisible = 1;
+ gSprites[spriteId].pos2.x = 0;
+ gSprites[spriteId].pos2.y = 0;
+
+ if (GetBattlerPosition_permutated(gAnimBankAttacker) == 1)
+ gBattle_BG1_Y = 0;
+ else
+ gBattle_BG2_Y = 0;
+
+ DestroyAnimVisualTask(taskId);
+}
+
+void sub_80E149C(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ if (gBattleAnimArgs[0] == 0)
+ task->func = sub_80E14DC;
+ else
+ task->func = sub_80E1560;
+
+ task->func(taskId);
+}
+
+static void sub_80E14DC(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ task->data[10] = GetAnimBattlerSpriteId(0);
+ gSprites[task->data[10]].invisible = 0;
+ gSprites[task->data[10]].pos2.x = 0;
+ gSprites[task->data[10]].pos2.y = 160 - gSprites[task->data[10]].pos1.y;
+ task->data[0]++;
+ break;
+ case 1:
+ DestroyAnimVisualTask(taskId);
+ }
+}
+
+static void sub_80E1560(u8 taskId)
+{
+ u8 var0;
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ task->data[10] = GetAnimBattlerSpriteId(0);
+ task->data[11] = GetBattlerPosition_permutated(gAnimBankAttacker);
+ if (task->data[11] == 1)
+ task->data[12] = gBattle_BG1_X;
+ else
+ task->data[12] = gBattle_BG2_X;
+
+ var0 = sub_8077FC0(gAnimBankAttacker);
+ task->data[14] = var0 - 32;
+ task->data[15] = var0 + 32;
+ task->data[0]++;
+ break;
+ case 1:
+ sub_80E1668(task->data[11], 0, task->data[15]);
+ task->data[0]++;
+ break;
+ case 2:
+ gSprites[task->data[10]].pos2.y = 96;
+ task->data[0]++;
+ break;
+ case 3:
+ gSprites[task->data[10]].pos2.y -= 8;
+ if (gSprites[task->data[10]].pos2.y == 0)
+ {
+ gScanlineEffect.state = 3;
+ task->data[0]++;
+ }
+ break;
+ case 4:
+ DestroyAnimVisualTask(taskId);
+ break;
+ }
+}
+
+static void sub_80E1668(u8 useBG1, s16 y, s16 endY)
+{
+ s16 bgX;
+ struct ScanlineEffectParams scanlineParams;
+
+ if (useBG1 == 1)
+ {
+ bgX = gBattle_BG1_X;
+ scanlineParams.dmaDest = &REG_BG1HOFS;
+ }
+ else
+ {
+ bgX = gBattle_BG2_X;
+ scanlineParams.dmaDest = &REG_BG2HOFS;
+ }
+
+ if (y < 0)
+ y = 0;
+
+ while (y < endY)
+ {
+ gScanlineEffectRegBuffers[0][y] = bgX;
+ gScanlineEffectRegBuffers[1][y] = bgX;
+ y++;
+ }
+
+ while (y < 160)
+ {
+ gScanlineEffectRegBuffers[0][y] = bgX + 240;
+ gScanlineEffectRegBuffers[1][y] = bgX + 240;
+ y++;
+ }
+
+ scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT;
+ scanlineParams.initState = 1;
+ scanlineParams.unused9 = 0;
+ ScanlineEffect_SetParams(scanlineParams);
+}
+
+// Moves a particle of dirt in a plume of dirt. Used in Fissure and Dig.
+// arg 0: which mon (0 = attacker, 1 = target)
+// arg 1: which side of mon (0 = left, 1 = right)
+// arg 2: target x offset
+// arg 3: target y offset
+// arg 4: wave amplitude
+// arg 5: duration
+static void AnimFissureDirtPlumeParticle(struct Sprite *sprite)
+{
+ s8 battler;
+ s16 xOffset;
+
+ if (gBattleAnimArgs[0] == 0)
+ battler = gAnimBankAttacker;
+ else
+ battler = gAnimBankTarget;
+
+ xOffset = 24;
+ if (gBattleAnimArgs[1] == 1)
+ {
+ xOffset *= -1;
+ gBattleAnimArgs[2] *= -1;
+ }
+
+ sprite->pos1.x = GetBattlerSpriteCoord(battler, 2) + xOffset;
+ sprite->pos1.y = sub_8077FC0(battler) + 30;
+ sprite->data[0] = gBattleAnimArgs[5];
+ sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2];
+ sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[3];
+ sprite->data[5] = gBattleAnimArgs[4];
+ InitAnimSpriteTranslationOverDuration(sprite);
+ sprite->callback = AnimFissureDirtPlumeParticleStep;
+}
+
+static void AnimFissureDirtPlumeParticleStep(struct Sprite *sprite)
+{
+ if (TranslateAnimSpriteLinearAndSine(sprite))
+ DestroyAnimSprite(sprite);
+}
+
+// Displays the dirt mound seen in the move Dig for set duration.
+// The dirt mound image is too large for a single sprite, so two
+// sprites are lined up next to each other.
+// arg 0: which mon (0 = attacker, 1 = target)
+// arg 1: oam tile num (0 = left half of image, 1 = right half of image)
+// arg 2: duration
+static void AnimDigDirtMound(struct Sprite *sprite)
+{
+ s8 battler;
+
+ if (gBattleAnimArgs[0] == 0)
+ battler = gAnimBankAttacker;
+ else
+ battler = gAnimBankTarget;
+
+ sprite->pos1.x = GetBattlerSpriteCoord(battler, 0) - 16 + (gBattleAnimArgs[1] * 32);
+ sprite->pos1.y = sub_8077FC0(battler) + 32;
+ sprite->oam.tileNum += gBattleAnimArgs[1] * 8;
+ StoreSpriteCallbackInData(sprite, DestroyAnimSprite);
+ sprite->data[0] = gBattleAnimArgs[2];
+ sprite->callback = WaitAnimForDuration;
+}
+
+void sub_80E1864(u8 taskId)
+{
+ u16 i;
+ struct Task *task = &gTasks[taskId];
+
+ if (gBattleAnimArgs[1])
+ task->data[14] = task->data[15] = gBattleAnimArgs[1] + 3;
+ else
+ task->data[14] = task->data[15] = (gAnimMovePower / 10) + 3;
+
+ task->data[3] = gBattleAnimArgs[2];
+ switch (gBattleAnimArgs[0])
+ {
+ case 5:
+ task->data[13] = gBattle_BG3_X;
+ task->func = sub_80E1934;
+ break;
+ case 4:
+ task->data[13] = 0;
+ for (i = 0; i < 4; i++)
+ {
+ if (IsAnimBankSpriteVisible(i))
+ {
+ task->data[task->data[13] + 9] = gBankSpriteIds[i];
+ task->data[13]++;
+ }
+ }
+ task->func = sub_80E1A2C;
+ break;
+ default:
+ task->data[9] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
+ if (task->data[9] == 0xFF)
+ {
+ DestroyAnimVisualTask(taskId);
+ }
+ else
+ {
+ task->data[13] = 1;
+ task->func = sub_80E1A2C;
+ }
+
+ break;
+ }
+}
+
+static void sub_80E1934(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ if (++task->data[1] > 1)
+ {
+ task->data[1] = 0;
+ if ((task->data[2] & 1) == 0)
+ gBattle_BG3_X = task->data[13] + task->data[15];
+ else
+ gBattle_BG3_X = task->data[13] - task->data[15];
+
+ if (++task->data[2] == task->data[3])
+ {
+ task->data[2] = 0;
+ task->data[14]--;
+ task->data[0]++;
+ }
+ }
+ break;
+ case 1:
+ if (++task->data[1] > 1)
+ {
+ task->data[1] = 0;
+ if ((task->data[2] & 1) == 0)
+ gBattle_BG3_X = task->data[13] + task->data[14];
+ else
+ gBattle_BG3_X = task->data[13] - task->data[14];
+
+ if (++task->data[2] == 4)
+ {
+ task->data[2] = 0;
+ if (--task->data[14] == 0)
+ task->data[0]++;
+ }
+ }
+ break;
+ case 2:
+ gBattle_BG3_X = task->data[13];
+ DestroyAnimVisualTask(taskId);
+ break;
+ }
+}
+
+static void sub_80E1A2C(u8 taskId)
+{
+ u16 i;
+ struct Task *task = &gTasks[taskId];
+
+ switch (task->data[0])
+ {
+ case 0:
+ if (++task->data[1] > 1)
+ {
+ task->data[1] = 0;
+ sub_80E1B10(task);
+ if (++task->data[2] == task->data[3])
+ {
+ task->data[2] = 0;
+ task->data[14]--;
+ task->data[0]++;
+ }
+ }
+ break;
+ case 1:
+ if (++task->data[1] > 1)
+ {
+ task->data[1] = 0;
+ sub_80E1B10(task);
+ if (++task->data[2] == 4)
+ {
+ task->data[2] = 0;
+ if (--task->data[14] == 0)
+ task->data[0]++;
+ }
+ }
+ break;
+ case 2:
+ for (i = 0; i < task->data[13]; i++)
+ gSprites[task->data[9 + i]].pos2.x = 0;
+
+ DestroyAnimVisualTask(taskId);
+ break;
+ }
+}
+
+static void sub_80E1B10(struct Task *task)
+{
+ u16 i;
+ u16 xOffset;
+
+ if ((task->data[2] & 1) == 0)
+ xOffset = (task->data[14] / 2) + (task->data[14] & 1);
+ else
+ xOffset = -(task->data[14] / 2);
+
+ for (i = 0; i < task->data[13]; i++)
+ {
+ gSprites[task->data[9 + i]].pos2.x = xOffset;
+ }
+}
+
+void sub_80E1B88(u8 taskId)
+{
+ gBattleAnimArgs[15] = gAnimMovePower > 99;
+ DestroyAnimVisualTask(taskId);
+}
+
+void sub_80E1BB0(u8 taskId)
+{
+ struct Task *newTask;
+ u8 battler = (gBattleAnimArgs[0] & 1) ? gAnimBankTarget : gAnimBankAttacker;
+
+ if (gBattleAnimArgs[0] > 1)
+ battler ^= 2;
+
+ newTask = &gTasks[CreateTask(sub_80E1C58, gBattleAnimArgs[1])];
+ newTask->data[1] = (32 - GetBattlerSpriteCoord(battler, 2)) & 0x1FF;
+ newTask->data[2] = (64 - GetBattlerSpriteCoord(battler, 3)) & 0xFF;
+ gBattle_BG3_X = newTask->data[1];
+ gBattle_BG3_Y = newTask->data[2];
+ newTask->data[3] = gBattleAnimArgs[2];
+ DestroyAnimVisualTask(taskId);
+}
+
+static void sub_80E1C58(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ if (gBattleAnimArgs[7] == task->data[3])
+ {
+ gBattle_BG3_X = 0;
+ gBattle_BG3_Y = 0;
+ DestroyTask(taskId);
+ }
+ else
+ {
+ gBattle_BG3_X = task->data[1];
+ gBattle_BG3_Y = task->data[2];
+ }
+}