pokeruby/src/battle_anim_special.c
Eduardo Quezada f6e2a5901e
Some checks failed
CI / build (push) Has been cancelled
Port Wally Controller documentation from pokeemerald (#891)
2026-02-19 21:49:14 -05:00

2099 lines
58 KiB
C
Executable File

#include "global.h"
#include "battle.h"
#include "battle_anim.h"
#include "battle_anim_special.h"
#include "battle_interface.h"
#include "blend_palette.h"
#include "decompress.h"
#include "ewram.h"
#include "m4a.h"
#include "main.h"
#include "palette.h"
#include "pokeball.h"
#include "rom_8077ABC.h"
#include "sound.h"
#include "sprite.h"
#include "task.h"
#include "trig.h"
#include "util.h"
#include "constants/items.h"
#include "constants/songs.h"
int gUnknown_03005F0C;
u16 gUnknown_03005F10;
u16 gUnknown_03005F14;
extern s16 gBattleAnimArgs[];
extern u8 gBattleAnimAttacker;
extern u8 gBattleAnimTarget;
extern u8 gHealthboxSpriteIds[];
extern u8 gBattlerSpriteIds[];
extern u16 gBattlerPartyIndexes[];
extern u16 gLastUsedItem;
extern u8 gDoingBattleAnim;
extern u8 gEffectBattler;
extern const u8 gUnknown_08D2EE48[];
extern const u8 gUnknown_08D2EDFC[];
extern const u16 gUnknown_08D2E150[];
extern const struct SpriteTemplate gSpriteTemplates_840B3B4[];
extern const struct SpriteTemplate gSpriteTemplate_8402500;
extern const struct SpriteTemplate gBattleAnimSpriteTemplate_84024E8;
extern const struct CompressedSpriteSheet gBattleAnimPicTable[];
extern const struct CompressedSpritePalette gBattleAnimPaletteTable[];
static void sub_813F300(u8 taskId);
static void sub_813F6CC(u8 taskId);
static void sub_813FD34(u8 taskId);
static void sub_813FD90(struct Sprite *sprite);
static void sub_813FB7C(u8 taskId);
static void sub_813FCBC(u8 taskId);
static void sub_813FDC0(struct Sprite *sprite);
static void sub_813FE70(struct Sprite *sprite);
static void sub_81407B8(struct Sprite *sprite);
static void sub_813FEC8(struct Sprite *sprite);
static void sub_8140014(struct Sprite *sprite);
static void sub_8140058(struct Sprite *sprite);
static void sub_8140410(struct Sprite *sprite);
static void sub_8140158(struct Sprite *sprite);
static void sub_81401A0(struct Sprite *sprite);
static void sub_8140434(struct Sprite *sprite);
static void sub_81405F4(struct Sprite *sprite);
static void sub_8140454(struct Sprite *sprite);
static void sub_81404E4(struct Sprite *sprite);
static void sub_81405C8(struct Sprite *sprite);
static void sub_81406BC(struct Sprite *sprite);
static void sub_81407F4(struct Sprite *sprite);
static void PokeBallOpenParticleAnimation_Step1(struct Sprite *sprite);
static void PokeBallOpenParticleAnimation_Step2(struct Sprite *sprite);
static void DestroyBallOpenAnimationParticle(struct Sprite *sprite);
static void FanOutBallOpenParticles_Step1(struct Sprite *sprite);
static void RepeatBallOpenParticleAnimation_Step1(struct Sprite *sprite);
static void PremierBallOpenParticleAnimation_Step1(struct Sprite *sprite);
static void sub_81413DC(u8 taskId);
static void sub_814146C(u8 taskId);
static void sub_81414BC(u8 taskId);
static void sub_814191C(u8 taskId);
static void sub_8141B20(struct Sprite *sprite);
static void sub_8141B74(struct Sprite *sprite);
static void sub_8141AD8(u8 taskId);
static void sub_8141CBC(struct Sprite *sprite);
static void sub_8141CF4(struct Sprite *sprite);
static void sub_8141D20(struct Sprite *sprite);
extern const u8 gBattleAnimSpriteSheet_Particles[];
const struct CompressedSpriteSheet gBallOpenParticleSpritesheets[] =
{
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6EC},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6ED},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6EE},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6EF},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6F0},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6F1},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6F2},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6F3},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6F4},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6F5},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6F6},
{gBattleAnimSpriteSheet_Particles, 0x100, 0xD6F7},
};
extern const u8 gBattleAnimSpritePalette_136[];
const struct CompressedSpritePalette gBallOpenParticlePalettes[] =
{
{gBattleAnimSpritePalette_136, 0xD6EC},
{gBattleAnimSpritePalette_136, 0xD6ED},
{gBattleAnimSpritePalette_136, 0xD6EE},
{gBattleAnimSpritePalette_136, 0xD6EF},
{gBattleAnimSpritePalette_136, 0xD6F0},
{gBattleAnimSpritePalette_136, 0xD6F1},
{gBattleAnimSpritePalette_136, 0xD6F2},
{gBattleAnimSpritePalette_136, 0xD6F3},
{gBattleAnimSpritePalette_136, 0xD6F4},
{gBattleAnimSpritePalette_136, 0xD6F5},
{gBattleAnimSpritePalette_136, 0xD6F6},
{gBattleAnimSpritePalette_136, 0xD6F7},
};
const union AnimCmd gSpriteAnim_840B318[] =
{
ANIMCMD_FRAME(0, 1),
ANIMCMD_FRAME(1, 1),
ANIMCMD_FRAME(2, 1),
ANIMCMD_FRAME(0, 1, .hFlip = TRUE),
ANIMCMD_FRAME(2, 1),
ANIMCMD_FRAME(1, 1),
ANIMCMD_JUMP(0),
};
const union AnimCmd gSpriteAnim_840B334[] =
{
ANIMCMD_FRAME(3, 1),
ANIMCMD_END,
};
const union AnimCmd gSpriteAnim_840B33C[] =
{
ANIMCMD_FRAME(4, 1),
ANIMCMD_END,
};
const union AnimCmd gSpriteAnim_840B344[] =
{
ANIMCMD_FRAME(5, 1),
ANIMCMD_END,
};
const union AnimCmd gSpriteAnim_840B34C[] =
{
ANIMCMD_FRAME(6, 4),
ANIMCMD_FRAME(7, 4),
ANIMCMD_JUMP(0),
};
const union AnimCmd gSpriteAnim_840B358[] =
{
ANIMCMD_FRAME(7, 4),
ANIMCMD_END,
};
const union AnimCmd *const gSpriteAnimTable_840B360[] =
{
gSpriteAnim_840B318,
gSpriteAnim_840B334,
gSpriteAnim_840B33C,
gSpriteAnim_840B344,
gSpriteAnim_840B34C,
gSpriteAnim_840B358,
};
const u8 gBallOpenParticleAnimNums[] =
{
0,
0,
0,
5,
1,
2,
2,
3,
5,
5,
4,
4,
};
void PokeBallOpenParticleAnimation(u8);
void GreatBallOpenParticleAnimation(u8);
void SafariBallOpenParticleAnimation(u8);
void UltraBallOpenParticleAnimation(u8);
void MasterBallOpenParticleAnimation(u8);
void SafariBallOpenParticleAnimation(u8);
void DiveBallOpenParticleAnimation(u8);
void UltraBallOpenParticleAnimation(u8);
void RepeatBallOpenParticleAnimation(u8);
void TimerBallOpenParticleAnimation(u8);
void GreatBallOpenParticleAnimation(u8);
void PremierBallOpenParticleAnimation(u8);
const TaskFunc gBallOpenParticleAnimationFuncs[] =
{
PokeBallOpenParticleAnimation,
GreatBallOpenParticleAnimation,
SafariBallOpenParticleAnimation,
UltraBallOpenParticleAnimation,
MasterBallOpenParticleAnimation,
SafariBallOpenParticleAnimation,
DiveBallOpenParticleAnimation,
UltraBallOpenParticleAnimation,
RepeatBallOpenParticleAnimation,
TimerBallOpenParticleAnimation,
GreatBallOpenParticleAnimation,
PremierBallOpenParticleAnimation,
};
const struct SpriteTemplate gSpriteTemplates_840B3B4[] =
{
{
.tileTag = 55020,
.paletteTag = 55020,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55021,
.paletteTag = 55021,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55022,
.paletteTag = 55022,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55023,
.paletteTag = 55023,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55024,
.paletteTag = 55024,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55025,
.paletteTag = 55025,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55026,
.paletteTag = 55026,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55027,
.paletteTag = 55027,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55028,
.paletteTag = 55028,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55029,
.paletteTag = 55029,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55030,
.paletteTag = 55030,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
{
.tileTag = 55031,
.paletteTag = 55031,
.oam = &gOamData_837DF24,
.anims = gSpriteAnimTable_840B360,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
};
const u16 gUnknown_0840B4D4[] =
{
0x7ADF,
0x7AF0,
0x53D7,
0x3FFF,
0x7297,
0x67F5,
0x7B2C,
0x2B7E,
0x431F,
0x7BDD,
0x2A3F,
0x293F,
0x0000,
0x0201,
0x0403,
0x0101,
0x0100,
0x0503,
0x0506,
0x0004,
};
static void sub_8141C30(struct Sprite *sprite);
const struct SpriteTemplate gBattleAnimSpriteTemplate_840B4FC =
{
.tileTag = ANIM_TAG_UNUSED_RED_BRICK,
.paletteTag = ANIM_TAG_UNUSED_RED_BRICK,
.oam = &gOamData_837DF2C,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = sub_8141C30,
};
void unref_sub_813F0F4(u8 taskId)
{
struct Struct_sub_8078914 subStruct;
u8 healthBoxSpriteId;
u8 battler;
u8 spriteId1, spriteId2, spriteId3, spriteId4;
battler = gBattleAnimAttacker;
gBattle_WIN0H = 0;
gBattle_WIN0V = 0;
REG_WININ = 0x3F3F;
REG_WINOUT = 0x3F3D;
REG_DISPCNT |= DISPCNT_OBJWIN_ON;
REG_BLDCNT = 0x3F42;
REG_BLDALPHA = 0x1000;
REG_BG1CNT_BITFIELD.priority = 0;
REG_BG1CNT_BITFIELD.screenSize = 0;
REG_BG1CNT_BITFIELD.areaOverflowMode = 1;
REG_BG1CNT_BITFIELD.charBaseBlock = 1;
healthBoxSpriteId = gHealthboxSpriteIds[battler];
spriteId1 = gSprites[healthBoxSpriteId].oam.affineParam;
spriteId2 = gSprites[healthBoxSpriteId].data[5];
spriteId3 = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy);
spriteId4 = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy);
gSprites[healthBoxSpriteId].oam.priority = 1;
gSprites[spriteId1].oam.priority = 1;
gSprites[spriteId2].oam.priority = 1;
gSprites[spriteId3] = gSprites[healthBoxSpriteId];
gSprites[spriteId4] = gSprites[spriteId1];
gSprites[spriteId3].oam.objMode = ST_OAM_OBJ_WINDOW;
gSprites[spriteId4].oam.objMode = ST_OAM_OBJ_WINDOW;
gSprites[spriteId3].callback = SpriteCallbackDummy;
gSprites[spriteId4].callback = SpriteCallbackDummy;
sub_8078914(&subStruct);
DmaFill32Defvars(3, 0, subStruct.field_4, 0x1000);
LZDecompressVram(&gUnknown_08D2EE48, subStruct.field_4);
LZDecompressVram(&gUnknown_08D2EDFC, subStruct.field_0);
LoadCompressedPalette(gUnknown_08D2E150, subStruct.field_8 << 4, 32);
gBattle_BG1_X = -gSprites[spriteId3].x + 32;
gBattle_BG1_Y = -gSprites[spriteId3].y - 32;
gTasks[taskId].data[1] = 640;
gTasks[taskId].data[0] = spriteId3;
gTasks[taskId].data[2] = spriteId4;
gTasks[taskId].func = sub_813F300;
}
static void sub_813F300(u8 taskId)
{
struct Struct_sub_8078914 subStruct;
u8 spriteId1, spriteId2;
u8 battler;
battler = gBattleAnimAttacker;
gTasks[taskId].data[13] += gTasks[taskId].data[1];
gBattle_BG1_Y += (u16)gTasks[taskId].data[13] >> 8;
gTasks[taskId].data[13] &= 0xFF;
switch (gTasks[taskId].data[15])
{
case 0:
if (gTasks[taskId].data[11]++ > 1)
{
gTasks[taskId].data[11] = 0;
gTasks[taskId].data[12]++;
REG_BLDALPHA = ((16 - gTasks[taskId].data[12]) << 8) | gTasks[taskId].data[12];
if (gTasks[taskId].data[12] == 8)
gTasks[taskId].data[15]++;
}
break;
case 1:
if (++gTasks[taskId].data[10] == 30)
gTasks[taskId].data[15]++;
break;
case 2:
if (gTasks[taskId].data[11]++ > 1)
{
gTasks[taskId].data[11] = 0;
gTasks[taskId].data[12]--;
REG_BLDALPHA = ((16 - gTasks[taskId].data[12]) << 8) | gTasks[taskId].data[12];
if (gTasks[taskId].data[12] == 0)
{
sub_8076464(0);
gBattle_WIN0H = 0;
gBattle_WIN0V = 0;
REG_WININ = 0x3F3F;
REG_WINOUT = 0x3F3F;
if (!IsContest())
REG_BG1CNT_BITFIELD.charBaseBlock = 0;
REG_DISPCNT ^= DISPCNT_OBJWIN_ON;
REG_BLDCNT = 0;
REG_BLDALPHA = 0;
DestroySprite(&gSprites[gTasks[taskId].data[0]]);
DestroySprite(&gSprites[gTasks[taskId].data[2]]);
sub_8078914(&subStruct);
DmaFill32Defvars(3, 0, subStruct.field_4, 0x800);
REG_BG1CNT_BITFIELD.areaOverflowMode = 0;
spriteId1 = gSprites[gHealthboxSpriteIds[battler]].oam.affineParam;
spriteId2 = gSprites[gHealthboxSpriteIds[battler]].data[5];
gSprites[gHealthboxSpriteIds[battler]].oam.priority = 1;
gSprites[spriteId1].oam.priority = 1;
gSprites[spriteId2].oam.priority = 1;
DestroyAnimVisualTask(taskId);
}
}
break;
}
}
void sub_813F4EC(u8 taskId)
{
u8 healthBoxSpriteId;
u8 spriteId1, spriteId2;
u8 paletteNum1, paletteNum2;
u16 offset1, offset2;
healthBoxSpriteId = gHealthboxSpriteIds[gBattleAnimAttacker];
spriteId1 = gSprites[healthBoxSpriteId].oam.affineParam;
spriteId2 = gSprites[healthBoxSpriteId].data[5];
paletteNum1 = AllocSpritePalette(0xD709);
paletteNum2 = AllocSpritePalette(0xD70A);
offset1 = (gSprites[healthBoxSpriteId].oam.paletteNum * 16) + 0x100;
offset2 = (gSprites[spriteId2].oam.paletteNum * 16) + 0x100;
LoadPalette(&gPlttBufferUnfaded[offset1], paletteNum1 * 16 + 0x100, 0x20);
LoadPalette(&gPlttBufferUnfaded[offset2], paletteNum2 * 16 + 0x100, 0x20);
gSprites[healthBoxSpriteId].oam.paletteNum = paletteNum1;
gSprites[spriteId1].oam.paletteNum = paletteNum1;
gSprites[spriteId2].oam.paletteNum = paletteNum2;
DestroyAnimVisualTask(taskId);
}
void sub_813F5E8(u8 taskId)
{
u8 healthBoxSpriteId;
u8 spriteId1, spriteId2;
u8 paletteIndex1, paletteIndex2;
healthBoxSpriteId = gHealthboxSpriteIds[gBattleAnimAttacker];
spriteId1 = gSprites[healthBoxSpriteId].oam.affineParam;
spriteId2 = gSprites[healthBoxSpriteId].data[5];
FreeSpritePaletteByTag(0xD709);
FreeSpritePaletteByTag(0xD70A);
paletteIndex1 = IndexOfSpritePaletteTag(0xD6FF);
paletteIndex2 = IndexOfSpritePaletteTag(0xD704);
gSprites[healthBoxSpriteId].oam.paletteNum = paletteIndex1;
gSprites[spriteId1].oam.paletteNum = paletteIndex1;
gSprites[spriteId2].oam.paletteNum = paletteIndex2;
DestroyAnimVisualTask(taskId);
}
void sub_813F6A0(u8 taskId)
{
gTasks[taskId].data[10] = gBattleAnimArgs[0];
gTasks[taskId].data[11] = gBattleAnimArgs[1];
gTasks[taskId].func = sub_813F6CC;
}
static void sub_813F6CC(u8 taskId)
{
u8 paletteNum;
int paletteOffset, colorOffset;
gTasks[taskId].data[0]++;
if (gTasks[taskId].data[0]++ >= gTasks[taskId].data[11])
{
gTasks[taskId].data[0] = 0;
paletteNum = IndexOfSpritePaletteTag(0xD709);
colorOffset = gTasks[taskId].data[10] == 0 ? 6 : 2;
switch (gTasks[taskId].data[1])
{
case 0:
gTasks[taskId].data[2] += 2;
if (gTasks[taskId].data[2] > 16)
gTasks[taskId].data[2] = 16;
paletteOffset = paletteNum * 16 + 0x100;
BlendPalette(paletteOffset + colorOffset, 1, gTasks[taskId].data[2], RGB(20, 27, 31));
if (gTasks[taskId].data[2] == 16)
gTasks[taskId].data[1]++;
break;
case 1:
gTasks[taskId].data[2] -= 2;
if (gTasks[taskId].data[2] < 0)
gTasks[taskId].data[2] = 0;
paletteOffset = paletteNum * 16 + 0x100;
BlendPalette(paletteOffset + colorOffset, 1, gTasks[taskId].data[2], RGB(20, 27, 31));
if (gTasks[taskId].data[2] == 0)
DestroyAnimVisualTask(taskId);
break;
}
}
}
void sub_813F798(u8 taskId)
{
u8 spriteId;
spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
switch (gTasks[taskId].data[0])
{
case 0:
PrepareBattlerSpriteForRotScale(spriteId, 0);
gTasks[taskId].data[10] = 0x100;
gTasks[taskId].data[0]++;
break;
case 1:
gTasks[taskId].data[10] += 0x30;
obj_id_set_rotscale(spriteId, gTasks[taskId].data[10], gTasks[taskId].data[10], 0);
sub_8079A64(spriteId);
if (gTasks[taskId].data[10] >= 0x2D0)
gTasks[taskId].data[0]++;
break;
case 2:
sub_8078F40(spriteId);
gSprites[spriteId].invisible = TRUE;
DestroyAnimVisualTask(taskId);
break;
}
}
void sub_813F844(u8 taskId)
{
u8 spriteId;
u16 ball;
u8 ballIndex;
u8 x, y;
u8 priority, subpriority;
u32 selectedPalettes;
spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
ball = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_POKEBALL);
else
ball = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_POKEBALL);
ballIndex = ball_number_to_ball_processing_index(ball);
switch (gTasks[taskId].data[0])
{
case 0:
x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0);
y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1);
priority = gSprites[spriteId].oam.priority;
subpriority = gSprites[spriteId].subpriority;
gTasks[taskId].data[10] = AnimateBallOpenParticles(x, y + 32, priority, subpriority, ballIndex);
selectedPalettes = sub_80791A8(1, 0, 0, 0, 0, 0, 0);
gTasks[taskId].data[11] = sub_8141314(0, gBattleAnimAttacker, selectedPalettes, ballIndex);
gTasks[taskId].data[0]++;
break;
case 1:
if (!gTasks[gTasks[taskId].data[10]].isActive && !gTasks[gTasks[taskId].data[11]].isActive)
DestroyAnimVisualTask(taskId);
break;
}
}
void sub_813F990(u8 taskId)
{
u8 ballIndex = ball_number_to_ball_processing_index(gLastUsedItem);
LoadBallGraphics(ballIndex);
DestroyAnimVisualTask(taskId);
}
void sub_813F9B8(u8 taskId)
{
u8 ballIndex = ball_number_to_ball_processing_index(gLastUsedItem);
FreeBallGraphics(ballIndex);
DestroyAnimVisualTask(taskId);
}
void sub_813F9E0(u8 taskId)
{
if (ewram17840.unk8 == 5)
gBattleAnimArgs[7] = -1;
else
gBattleAnimArgs[7] = 0;
DestroyAnimVisualTask(taskId);
}
u8 ball_number_to_ball_processing_index(u16 ballItem)
{
switch (ballItem)
{
case ITEM_MASTER_BALL:
return 4;
case ITEM_ULTRA_BALL:
return 3;
case ITEM_GREAT_BALL:
return 1;
case ITEM_SAFARI_BALL:
return 2;
case ITEM_NET_BALL:
return 5;
case ITEM_DIVE_BALL:
return 6;
case ITEM_NEST_BALL:
return 7;
case ITEM_REPEAT_BALL:
return 8;
case ITEM_TIMER_BALL:
return 9;
case ITEM_LUXURY_BALL:
return 10;
case ITEM_PREMIER_BALL:
return 11;
case ITEM_POKE_BALL:
default:
return 0;
}
}
void sub_813FA94(u8 taskId)
{
u8 ballIndex;
u8 spriteId;
ballIndex = ball_number_to_ball_processing_index(gLastUsedItem);
spriteId = CreateSprite(&gBallSpriteTemplates[ballIndex], 32, 80, 29);
gSprites[spriteId].data[0] = 34;
gSprites[spriteId].data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, 0);
gSprites[spriteId].data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 1) - 16;
gSprites[spriteId].callback = sub_813FD90;
ewram17840.unk9_1 = gSprites[gBattlerSpriteIds[gBattleAnimTarget]].invisible;
gTasks[taskId].data[0] = spriteId;
gTasks[taskId].func = sub_813FB7C;
}
static void sub_813FB7C(u8 taskId)
{
u8 spriteId = gTasks[taskId].data[0];
if ((u16)gSprites[spriteId].data[0] == 0xFFFF)
DestroyAnimVisualTask(taskId);
}
void sub_813FBB8(u8 taskId)
{
int x, y;
u8 ballIndex;
u8 subpriority;
u8 spriteId;
if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
{
x = 32;
y = 11;
}
else
{
x = 23;
y = 5;
}
ballIndex = ball_number_to_ball_processing_index(gLastUsedItem);
subpriority = GetBattlerSpriteSubpriority(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)) + 1;
spriteId = CreateSprite(&gBallSpriteTemplates[ballIndex], x + 32, y | 80, subpriority);
gSprites[spriteId].data[0] = 34;
gSprites[spriteId].data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, 0);
gSprites[spriteId].data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 1) - 16;
gSprites[spriteId].callback = SpriteCallbackDummy;
StartSpriteAnim(&gSprites[gBattlerSpriteIds[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]], 1);
gTasks[taskId].data[0] = spriteId;
gTasks[taskId].func = sub_813FCBC;
}
static void sub_813FCBC(u8 taskId)
{
if (gSprites[gBattlerSpriteIds[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]].animCmdIndex == 1)
{
PlaySE12WithPanning(SE_BALL_THROW, 0);
gSprites[gTasks[taskId].data[0]].callback = sub_813FD90;
CreateTask(sub_813FD34, 10);
gTasks[taskId].func = sub_813FB7C;
}
}
static void sub_813FD34(u8 taskId)
{
if (gSprites[gBattlerSpriteIds[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]].animEnded)
{
StartSpriteAnim(&gSprites[gBattlerSpriteIds[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]], 0);
DestroyTask(taskId);
}
}
static void sub_813FD90(struct Sprite *sprite)
{
u16 temp = sprite->data[1];
u16 temp2 = sprite->data[2];
sprite->data[1] = sprite->x;
sprite->data[2] = temp;
sprite->data[3] = sprite->y;
sprite->data[4] = temp2;
sprite->data[5] = -40;
InitAnimArcTranslation(sprite);
sprite->callback = sub_813FDC0;
}
static void sub_813FDC0(struct Sprite *sprite)
{
int i;
u8 ballIndex;
int ballIndex2; // extra var needed to match
if (TranslateAnimArc(sprite))
{
if (ewram17840.unk8 == 5)
{
sprite->callback = sub_81407B8;
}
else
{
StartSpriteAnim(sprite, 1);
sprite->x += sprite->x2;
sprite->y += sprite->y2;
sprite->x2 = 0;
sprite->y2 = 0;
for (i = 0; i < 8; i++)
{
sprite->data[i] = 0;
}
sprite->data[5] = 0;
sprite->callback = sub_813FE70;
ballIndex = ball_number_to_ball_processing_index(gLastUsedItem);
ballIndex2 = ballIndex;
if (ballIndex2 > 11)
return;
if (ballIndex2 < 0)
return;
AnimateBallOpenParticles(sprite->x, sprite->y - 5, 1, 28, ballIndex);
sub_8141314(0, gBattleAnimTarget, 14, ballIndex);
}
}
}
static void sub_813FE70(struct Sprite *sprite)
{
if (++sprite->data[5] == 10)
{
sprite->data[5] = CreateTask(TaskDummy, 50);
sprite->callback = sub_813FEC8;
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].data[1] = 0;
}
}
static void sub_813FEC8(struct Sprite *sprite)
{
u8 spriteId;
u8 taskId;
spriteId = gBattlerSpriteIds[gBattleAnimTarget];
taskId = sprite->data[5];
if (++gTasks[taskId].data[1] == 11)
PlaySE(SE_BALL_TRADE);
switch (gTasks[taskId].data[0])
{
case 0:
PrepareBattlerSpriteForRotScale(spriteId, 0);
gTasks[taskId].data[10] = 256;
gUnknown_03005F0C = 28;
gUnknown_03005F14 = (gSprites[spriteId].y + gSprites[spriteId].y2) - (sprite->y + sprite->y2);
gUnknown_03005F10 = (u32)(gUnknown_03005F14 * 256) / 28;
gTasks[taskId].data[2] = gUnknown_03005F10;
gTasks[taskId].data[0]++;
break;
case 1:
gTasks[taskId].data[10] += 0x20;
obj_id_set_rotscale(spriteId, gTasks[taskId].data[10], gTasks[taskId].data[10], 0);
gTasks[taskId].data[3] += gTasks[taskId].data[2];
gSprites[spriteId].y2 = -gTasks[taskId].data[3] >> 8;
if (gTasks[taskId].data[10] >= 0x480)
gTasks[taskId].data[0]++;
break;
case 2:
sub_8078F40(spriteId);
gSprites[spriteId].invisible = TRUE;
gTasks[taskId].data[0]++;
break;
default:
if (gTasks[taskId].data[1] > 10)
{
DestroyTask(taskId);
StartSpriteAnim(sprite, 2);
sprite->data[5] = 0;
sprite->callback = sub_8140014;
}
break;
}
}
static void sub_8140014(struct Sprite *sprite)
{
int angle;
if (sprite->animEnded)
{
sprite->data[3] = 0;
sprite->data[4] = 32;
sprite->data[5] = 0;
angle = 0;
sprite->y += Cos(angle, 32);
sprite->y2 = -Cos(angle, sprite->data[4]);
sprite->callback = sub_8140058;
}
}
static void sub_8140058(struct Sprite *sprite)
{
bool8 lastBounce;
int bounceCount;
lastBounce = 0;
switch (sprite->data[3] & 0xFF)
{
case 0:
sprite->y2 = -Cos(sprite->data[5], sprite->data[4]);
sprite->data[5] += (sprite->data[3] >> 8) + 4;
if (sprite->data[5] >= 64)
{
sprite->data[4] -= 10;
sprite->data[3] += 257;
bounceCount = sprite->data[3] >> 8;
if (bounceCount == 4)
lastBounce = 1;
// Play a different sound effect for each pokeball bounce.
switch (bounceCount)
{
case 1:
PlaySE(SE_BALL_BOUNCE_1);
break;
case 2:
PlaySE(SE_BALL_BOUNCE_2);
break;
case 3:
PlaySE(SE_BALL_BOUNCE_3);
break;
default:
PlaySE(SE_BALL_BOUNCE_4);
break;
}
}
break;
case 1:
sprite->y2 = -Cos(sprite->data[5], sprite->data[4]);
sprite->data[5] -= (sprite->data[3] >> 8) + 4;
if (sprite->data[5] <= 0)
{
sprite->data[5] = 0;
sprite->data[3] &= -0x100;
}
break;
}
if (lastBounce)
{
sprite->data[3] = 0;
sprite->y += Cos(64, 32);
sprite->y2 = 0;
if (ewram17840.unk8 == 0)
{
sprite->data[5] = 0;
sprite->callback = sub_8140410;
}
else
{
sprite->callback = sub_8140158;
sprite->data[4] = 1;
sprite->data[5] = 0;
}
}
}
static void sub_8140158(struct Sprite *sprite)
{
if (++sprite->data[3] == 31)
{
sprite->data[3] = 0;
sprite->affineAnimPaused = 1;
StartSpriteAffineAnim(sprite, 1);
ewram17840.unkC = 0;
sprite->callback = sub_81401A0;
PlaySE(SE_BALL);
}
}
static void sub_81401A0(struct Sprite *sprite)
{
s8 state;
u16 var0;
switch (sprite->data[3] & 0xFF)
{
case 0:
if ((s16)ewram17840.unkC > 0xFF)
{
sprite->x2 += sprite->data[4];
ewram17840.unkC &= 0xFF;
}
else
{
ewram17840.unkC += 0xB0;
}
sprite->data[5]++;
sprite->affineAnimPaused = 0;
var0 = sprite->data[5] + 7;
if (var0 > 14)
{
ewram17840.unkC = 0;
sprite->data[3]++;
sprite->data[5] = 0;
}
break;
case 1:
if (++sprite->data[5] == 1)
{
sprite->data[5] = 0;
sprite->data[4] = -sprite->data[4];
sprite->data[3]++;
sprite->affineAnimPaused = 0;
if (sprite->data[4] < 0)
ChangeSpriteAffineAnim(sprite, 2);
else
ChangeSpriteAffineAnim(sprite, 1);
}
else
{
sprite->affineAnimPaused = 1;
}
break;
case 2:
if ((s16)ewram17840.unkC > 0xFF)
{
sprite->x2 += sprite->data[4];
ewram17840.unkC &= 0xFF;
}
else
{
ewram17840.unkC += 0xB0;
}
sprite->data[5]++;
sprite->affineAnimPaused = 0;
var0 = sprite->data[5] + 12;
if (var0 > 24)
{
ewram17840.unkC = 0;
sprite->data[3]++;
sprite->data[5] = 0;
}
break;
case 3:
if (sprite->data[5]++ < 0)
{
sprite->affineAnimPaused = 1;
break;
}
sprite->data[5] = 0;
sprite->data[4] = -sprite->data[4];
sprite->data[3]++;
sprite->affineAnimPaused = 0;
if (sprite->data[4] < 0)
ChangeSpriteAffineAnim(sprite, 2);
else
ChangeSpriteAffineAnim(sprite, 1);
// fall through
case 4:
if ((s16)ewram17840.unkC > 0xFF)
{
sprite->x2 += sprite->data[4];
ewram17840.unkC &= 0xFF;
}
else
{
ewram17840.unkC += 0xB0;
}
sprite->data[5]++;
sprite->affineAnimPaused = 0;
var0 = sprite->data[5] + 4;
if (var0 > 8)
{
ewram17840.unkC = 0;
sprite->data[3]++;
sprite->data[5] = 0;
sprite->data[4] = -sprite->data[4];
}
break;
case 5:
sprite->data[3] += 0x100;
state = sprite->data[3] >> 8;
if (state == ewram17840.unk8)
{
sprite->affineAnimPaused = 1;
sprite->callback = sub_8140410;
}
else
{
if (ewram17840.unk8 == 4 && state == 3)
{
sprite->callback = sub_8140434;
sprite->affineAnimPaused = 1;
}
else
{
sprite->data[3]++;
sprite->affineAnimPaused = 1;
}
}
break;
case 6:
default:
if (++sprite->data[5] == 31)
{
sprite->data[5] = 0;
sprite->data[3] &= -0x100;
StartSpriteAffineAnim(sprite, 3);
if (sprite->data[4] < 0)
StartSpriteAffineAnim(sprite, 2);
else
StartSpriteAffineAnim(sprite, 1);
PlaySE(SE_BALL);
}
break;
}
}
static void sub_8140410(struct Sprite *sprite)
{
if (++sprite->data[5] == 31)
{
sprite->data[5] = 0;
sprite->callback = sub_81405F4;
}
}
static void sub_8140434(struct Sprite *sprite)
{
sprite->animPaused = 1;
sprite->callback = sub_8140454;
sprite->data[3] = 0;
sprite->data[4] = 0;
sprite->data[5] = 0;
}
static void sub_8140454(struct Sprite *sprite)
{
u8 *battler = &gBattleAnimTarget;
sprite->data[4]++;
if (sprite->data[4] == 40)
return;
if (sprite->data[4] == 95)
{
gDoingBattleAnim = 0;
UpdateOamPriorityInAllHealthboxes(1);
m4aMPlayAllStop();
PlaySE(MUS_EVOLVED);
}
else if (sprite->data[4] == 315)
{
FreeOamMatrix(gSprites[gBattlerSpriteIds[*battler]].oam.matrixNum);
DestroySprite(&gSprites[gBattlerSpriteIds[*battler]]);
sprite->data[0] = 0;
sprite->callback = sub_81404E4;
}
}
static void sub_81404E4(struct Sprite *sprite)
{
u8 paletteIndex;
switch (sprite->data[0])
{
case 0:
sprite->data[1] = 0;
sprite->data[2] = 0;
sprite->oam.objMode = ST_OAM_OBJ_BLEND;
REG_BLDCNT = 0x3F40;
REG_BLDALPHA = 0x0010;
paletteIndex = IndexOfSpritePaletteTag(sprite->template->paletteTag);
BeginNormalPaletteFade(1 << (paletteIndex + 0x10), 0, 0, 16, RGB(31, 31, 31));
sprite->data[0]++;
break;
case 1:
if (sprite->data[1]++ > 0)
{
sprite->data[1] = 0;
sprite->data[2]++;
REG_BLDALPHA = (sprite->data[2] << 8) | (16 - sprite->data[2]);
if (sprite->data[2] == 16)
sprite->data[0]++;
}
break;
case 2:
sprite->invisible = TRUE;
sprite->data[0]++;
break;
default:
if (!gPaletteFade.active)
{
REG_BLDCNT = 0;
REG_BLDALPHA = 0;
sprite->data[0] = 0;
sprite->callback = sub_81405C8;
}
break;
}
}
static void sub_81405C8(struct Sprite *sprite)
{
if (sprite->data[0] == 0)
{
sprite->data[0] = -1;
}
else
{
FreeSpriteOamMatrix(sprite);
DestroySprite(sprite);
}
}
// fakematching. I think the return type of ball_number_to_ball_processing_index()
// is wrong because of the weird required casting.
static void sub_81405F4(struct Sprite *sprite)
{
u8 ballIndex;
int ballIndex2; // extra var needed to match
StartSpriteAnim(sprite, 1);
StartSpriteAffineAnim(sprite, 0);
sprite->callback = sub_81406BC;
ballIndex = ball_number_to_ball_processing_index(gLastUsedItem);
ballIndex2 = ballIndex;
if (ballIndex2 > 11)
goto LABEL;
if (ballIndex2 < 0)
goto LABEL;
AnimateBallOpenParticles(sprite->x, sprite->y - 5, 1, 28, ballIndex);
sub_8141314(1, gBattleAnimTarget, 14, ballIndex);
LABEL:
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].invisible = FALSE;
StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[gBattleAnimTarget]], 1);
AnimateSprite(&gSprites[gBattlerSpriteIds[gBattleAnimTarget]]);
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].data[1] = 0x1000;
}
static void sub_81406BC(struct Sprite *sprite)
{
int next = FALSE;
if (sprite->animEnded)
sprite->invisible = TRUE;
if (gSprites[gBattlerSpriteIds[gBattleAnimTarget]].affineAnimEnded)
{
StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[gBattleAnimTarget]], 0);
next = TRUE;
}
else
{
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].data[1] -= 288;
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].y2 = gSprites[gBattlerSpriteIds[gBattleAnimTarget]].data[1] >> 8;
}
if (sprite->animEnded && next)
{
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].y2 = 0;
gSprites[gBattlerSpriteIds[gBattleAnimTarget]].invisible = ewram17840.unk9_1;
sprite->data[0] = 0;
sprite->callback = sub_81405C8;
gDoingBattleAnim = 0;
UpdateOamPriorityInAllHealthboxes(1);
}
}
static void sub_81407B8(struct Sprite *sprite)
{
int i;
sprite->x += sprite->x2;
sprite->y += sprite->y2;
sprite->y2 = 0;
sprite->x2 = 0;
for (i = 0; i < 6; i++)
sprite->data[i] = 0;
sprite->callback = sub_81407F4;
}
static void sub_81407F4(struct Sprite *sprite)
{
s16 var0 = sprite->data[0] + 0x800;
s16 var1 = sprite->data[1] + 0x680;
sprite->x2 -= var1 >> 8;
sprite->y2 += var0 >> 8;
sprite->data[0] = (sprite->data[0] + 0x800) & 0xFF;
sprite->data[1] = (sprite->data[1] + 0x680) & 0xFF;
if (sprite->y + sprite->y2 > 160
|| sprite->x + sprite->x2 < -8)
{
sprite->data[0] = 0;
sprite->callback = sub_81405C8;
gDoingBattleAnim = 0;
UpdateOamPriorityInAllHealthboxes(1);
}
}
u8 AnimateBallOpenParticles(u8 x, u8 y, u8 priority, u8 subpriority, u8 ballIndex)
{
u8 taskId;
if (GetSpriteTileStartByTag(gBallOpenParticleSpritesheets[ballIndex].tag) == 0xFFFF)
{
LoadCompressedObjectPic(&gBallOpenParticleSpritesheets[ballIndex]);
LoadCompressedObjectPalette(&gBallOpenParticlePalettes[ballIndex]);
}
taskId = CreateTask(gBallOpenParticleAnimationFuncs[ballIndex], 5);
gTasks[taskId].data[1] = x;
gTasks[taskId].data[2] = y;
gTasks[taskId].data[3] = priority;
gTasks[taskId].data[4] = subpriority;
gTasks[taskId].data[15] = ballIndex;
PlaySE(SE_BALL_OPEN);
if (gMain.inBattle)
ewram17840.unkA++;
return taskId;
}
void PokeBallOpenParticleAnimation(u8 taskId)
{
u8 spriteId;
u8 x, y;
u8 priority, subpriority;
u8 ballIndex;
u8 var0;
ballIndex = gTasks[taskId].data[15];
if (gTasks[taskId].data[0] < 16)
{
x = gTasks[taskId].data[1];
y = gTasks[taskId].data[2];
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
spriteId = CreateSprite(&gSpriteTemplates_840B3B4[ballIndex], x, y, subpriority);
StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballIndex]);
gSprites[spriteId].callback = PokeBallOpenParticleAnimation_Step1;
gSprites[spriteId].oam.priority = priority;
var0 = (u8)gTasks[taskId].data[0];
if (var0 >= 8)
var0 -= 8;
gSprites[spriteId].data[0] = var0 * 32;
if (gTasks[taskId].data[0] == 15)
{
gSprites[spriteId].data[7] = 1;
DestroyTask(taskId);
return;
}
}
gTasks[taskId].data[0]++;
}
static void PokeBallOpenParticleAnimation_Step1(struct Sprite *sprite)
{
if (sprite->data[1] == 0)
sprite->callback = PokeBallOpenParticleAnimation_Step2;
else
sprite->data[1]--;
}
static void PokeBallOpenParticleAnimation_Step2(struct Sprite *sprite)
{
sprite->x2 = Sin(sprite->data[0], sprite->data[1]);
sprite->y2 = Cos(sprite->data[0], sprite->data[1]);
sprite->data[1] += 2;
if (sprite->data[1] == 50)
DestroyBallOpenAnimationParticle(sprite);
}
void TimerBallOpenParticleAnimation(u8 taskId)
{
u8 i;
u8 x, y, priority, subpriority, ballIndex;
u8 spriteId;
ballIndex = gTasks[taskId].data[15];
x = gTasks[taskId].data[1];
y = gTasks[taskId].data[2];
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
for (i = 0; i < 8; i++)
{
spriteId = CreateSprite(&gSpriteTemplates_840B3B4[ballIndex], x, y, subpriority);
StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballIndex]);
gSprites[spriteId].callback = FanOutBallOpenParticles_Step1;
gSprites[spriteId].oam.priority = priority;
gSprites[spriteId].data[0] = i * 32;
gSprites[spriteId].data[4] = 10;
gSprites[spriteId].data[5] = 2;
gSprites[spriteId].data[6] = 1;
}
gSprites[spriteId].data[7] = 1;
DestroyTask(taskId);
}
void DiveBallOpenParticleAnimation(u8 taskId)
{
u8 i;
u8 x, y, priority, subpriority, ballIndex;
u8 spriteId;
ballIndex = gTasks[taskId].data[15];
x = gTasks[taskId].data[1];
y = gTasks[taskId].data[2];
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
for (i = 0; i < 8; i++)
{
spriteId = CreateSprite(&gSpriteTemplates_840B3B4[ballIndex], x, y, subpriority);
StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballIndex]);
gSprites[spriteId].callback = FanOutBallOpenParticles_Step1;
gSprites[spriteId].oam.priority = priority;
gSprites[spriteId].data[0] = i * 32;
gSprites[spriteId].data[4] = 10;
gSprites[spriteId].data[5] = 1;
gSprites[spriteId].data[6] = 2;
}
gSprites[spriteId].data[7] = 1;
DestroyTask(taskId);
}
void SafariBallOpenParticleAnimation(u8 taskId)
{
u8 i;
u8 x, y, priority, subpriority, ballIndex;
u8 spriteId;
ballIndex = gTasks[taskId].data[15];
x = gTasks[taskId].data[1];
y = gTasks[taskId].data[2];
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
for (i = 0; i < 8; i++)
{
spriteId = CreateSprite(&gSpriteTemplates_840B3B4[ballIndex], x, y, subpriority);
StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballIndex]);
gSprites[spriteId].callback = FanOutBallOpenParticles_Step1;
gSprites[spriteId].oam.priority = priority;
gSprites[spriteId].data[0] = i * 32;
gSprites[spriteId].data[4] = 4;
gSprites[spriteId].data[5] = 1;
gSprites[spriteId].data[6] = 1;
}
gSprites[spriteId].data[7] = 1;
DestroyTask(taskId);
}
void UltraBallOpenParticleAnimation(u8 taskId)
{
u8 i;
u8 x, y, priority, subpriority, ballIndex;
u8 spriteId;
ballIndex = gTasks[taskId].data[15];
x = gTasks[taskId].data[1];
y = gTasks[taskId].data[2];
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
for (i = 0; i < 10; i++)
{
spriteId = CreateSprite(&gSpriteTemplates_840B3B4[ballIndex], x, y, subpriority);
StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballIndex]);
gSprites[spriteId].callback = FanOutBallOpenParticles_Step1;
gSprites[spriteId].oam.priority = priority;
gSprites[spriteId].data[0] = i * 25;
gSprites[spriteId].data[4] = 5;
gSprites[spriteId].data[5] = 1;
gSprites[spriteId].data[6] = 1;
}
gSprites[spriteId].data[7] = 1;
DestroyTask(taskId);
}
void GreatBallOpenParticleAnimation(u8 taskId)
{
u8 i;
u8 x, y, priority, subpriority, ballIndex;
u8 spriteId;
if (gTasks[taskId].data[7])
{
gTasks[taskId].data[7]--;
}
else
{
ballIndex = gTasks[taskId].data[15];
x = gTasks[taskId].data[1];
y = gTasks[taskId].data[2];
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
for (i = 0; i < 8; i++)
{
spriteId = CreateSprite(&gSpriteTemplates_840B3B4[ballIndex], x, y, subpriority);
StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballIndex]);
gSprites[spriteId].callback = FanOutBallOpenParticles_Step1;
gSprites[spriteId].oam.priority = priority;
gSprites[spriteId].data[0] = i * 32;
gSprites[spriteId].data[4] = 8;
gSprites[spriteId].data[5] = 2;
gSprites[spriteId].data[6] = 2;
}
gTasks[taskId].data[7] = 8;
if (++gTasks[taskId].data[0] == 2)
{
gSprites[spriteId].data[7] = 1;
DestroyTask(taskId);
}
}
}
static void FanOutBallOpenParticles_Step1(struct Sprite *sprite)
{
sprite->x2 = Sin(sprite->data[0], sprite->data[1]);
sprite->y2 = Cos(sprite->data[0], sprite->data[2]);
sprite->data[0] = (sprite->data[0] + sprite->data[4]) & 0xFF;
sprite->data[1] += sprite->data[5];
sprite->data[2] += sprite->data[6];
if (++sprite->data[3] == 51)
DestroyBallOpenAnimationParticle(sprite);
}
void RepeatBallOpenParticleAnimation(u8 taskId)
{
u8 i;
u8 x, y, priority, subpriority, ballIndex;
u8 spriteId;
ballIndex = gTasks[taskId].data[15];
x = gTasks[taskId].data[1];
y = gTasks[taskId].data[2];
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
for (i = 0; i < 12; i++)
{
spriteId = CreateSprite(&gSpriteTemplates_840B3B4[ballIndex], x, y, subpriority);
StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballIndex]);
gSprites[spriteId].callback = RepeatBallOpenParticleAnimation_Step1;
gSprites[spriteId].oam.priority = priority;
gSprites[spriteId].data[0] = i * 21;
}
gSprites[spriteId].data[7] = 1;
DestroyTask(taskId);
}
static void RepeatBallOpenParticleAnimation_Step1(struct Sprite *sprite)
{
sprite->x2 = Sin(sprite->data[0], sprite->data[1]);
sprite->y2 = Cos(sprite->data[0], Sin(sprite->data[0], sprite->data[2]));
sprite->data[0] = (sprite->data[0] + 6) & 0xFF;
sprite->data[1]++;
sprite->data[2]++;
if (++sprite->data[3] == 51)
DestroyBallOpenAnimationParticle(sprite);
}
void MasterBallOpenParticleAnimation(u8 taskId)
{
u8 i, j;
u8 x, y, priority, subpriority, ballIndex;
u8 spriteId;
ballIndex = gTasks[taskId].data[15];
x = gTasks[taskId].data[1];
y = gTasks[taskId].data[2];
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
for (j = 0; j < 2; j++)
{
for (i = 0; i < 8; i++)
{
spriteId = CreateSprite(&gSpriteTemplates_840B3B4[ballIndex], x, y, subpriority);
StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballIndex]);
gSprites[spriteId].callback = FanOutBallOpenParticles_Step1;
gSprites[spriteId].oam.priority = priority;
gSprites[spriteId].data[0] = i * 32;
gSprites[spriteId].data[4] = 8;
if (j == 0)
{
gSprites[spriteId].data[5] = 2;
gSprites[spriteId].data[6] = 1;
}
else
{
gSprites[spriteId].data[5] = 1;
gSprites[spriteId].data[6] = 2;
}
}
}
gSprites[spriteId].data[7] = 1;
DestroyTask(taskId);
}
void PremierBallOpenParticleAnimation(u8 taskId)
{
u8 i;
u8 x, y, priority, subpriority, ballIndex;
u8 spriteId;
ballIndex = gTasks[taskId].data[15];
x = gTasks[taskId].data[1];
y = gTasks[taskId].data[2];
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
for (i = 0; i < 8; i++)
{
spriteId = CreateSprite(&gSpriteTemplates_840B3B4[ballIndex], x, y, subpriority);
StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballIndex]);
gSprites[spriteId].callback = PremierBallOpenParticleAnimation_Step1;
gSprites[spriteId].oam.priority = priority;
gSprites[spriteId].data[0] = i * 32;
}
gSprites[spriteId].data[7] = 1;
DestroyTask(taskId);
}
static void PremierBallOpenParticleAnimation_Step1(struct Sprite *sprite)
{
sprite->x2 = Sin(sprite->data[0], sprite->data[1]);
sprite->y2 = Cos(sprite->data[0], Sin(sprite->data[0] & 0x3F, sprite->data[2]));
sprite->data[0] = (sprite->data[0] + 10) & 0xFF;
sprite->data[1]++;
sprite->data[2]++;
if (++sprite->data[3] == 51)
DestroyBallOpenAnimationParticle(sprite);
}
static void DestroyBallOpenAnimationParticle(struct Sprite *sprite)
{
int i;
int temp;
if (!gMain.inBattle)
{
temp = sprite->data[7]; // temp var needed to match
if (temp == 1)
DestroySpriteAndFreeResources(sprite);
else
DestroySprite(sprite);
}
else if (sprite->data[7] == 1)
{
if (--ewram17840.unkA == 0)
{
for (i = 0; i < 12; i++)
{
FreeSpriteTilesByTag(gBallOpenParticleSpritesheets[i].tag);
FreeSpritePaletteByTag(gBallOpenParticlePalettes[i].tag);
}
DestroySprite(sprite);
}
else
DestroySprite(sprite);
}
else
DestroySprite(sprite);
}
u8 sub_8141314(u8 arg0, u8 battler, u32 selectedPalettes, u8 ballIndex)
{
u8 taskId;
taskId = CreateTask(sub_81413DC, 5);
gTasks[taskId].data[15] = ballIndex;
gTasks[taskId].data[3] = battler;
gTasks[taskId].data[10] = selectedPalettes;
gTasks[taskId].data[11] = selectedPalettes >> 16;
if (!arg0)
{
BlendPalette(battler * 16 + 0x100, 16, 0, gUnknown_0840B4D4[ballIndex]);
gTasks[taskId].data[1] = 1;
}
else
{
BlendPalette(battler * 16 + 0x100, 16, 16, gUnknown_0840B4D4[ballIndex]);
gTasks[taskId].data[0] = 16;
gTasks[taskId].data[1] = -1;
gTasks[taskId].func = sub_814146C;
}
BeginNormalPaletteFade(selectedPalettes, 0, 0, 16, RGB(31, 31, 31));
return taskId;
}
static void sub_81413DC(u8 taskId)
{
u8 ballIndex = gTasks[taskId].data[15];
if (gTasks[taskId].data[2] <= 16)
{
BlendPalette(gTasks[taskId].data[3] * 16 + 0x100, 16, gTasks[taskId].data[0], gUnknown_0840B4D4[ballIndex]);
gTasks[taskId].data[0] += gTasks[taskId].data[1];
gTasks[taskId].data[2]++;
}
else if (!gPaletteFade.active)
{
u32 selectedPalettes = (u16)gTasks[taskId].data[10] | ((u16)gTasks[taskId].data[11] << 16);
BeginNormalPaletteFade(selectedPalettes, 0, 16, 0, RGB(31, 31, 31));
DestroyTask(taskId);
}
}
static void sub_814146C(u8 taskId)
{
if (!gPaletteFade.active)
{
u32 selectedPalettes = (u16)gTasks[taskId].data[10] | ((u16)gTasks[taskId].data[11] << 16);
BeginNormalPaletteFade(selectedPalettes, 0, 16, 0, RGB(31, 31, 31));
gTasks[taskId].func = sub_81414BC;
}
}
static void sub_81414BC(u8 taskId)
{
u8 ballIndex = gTasks[taskId].data[15];
if (gTasks[taskId].data[2] <= 16)
{
BlendPalette(gTasks[taskId].data[3] * 16 + 0x100, 16, gTasks[taskId].data[0], gUnknown_0840B4D4[ballIndex]);
gTasks[taskId].data[0] += gTasks[taskId].data[1];
gTasks[taskId].data[2]++;
}
else
{
DestroyTask(taskId);
}
}
void sub_814151C(u8 taskId)
{
u8 spriteId;
u32 x;
u32 done;
done = FALSE;
spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
switch (gTasks[taskId].data[10])
{
case 0:
gTasks[taskId].data[11] = gBattleAnimArgs[0];
gTasks[taskId].data[0] += 0x500;
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
gSprites[spriteId].x2 += gTasks[taskId].data[0] >> 8;
else
gSprites[spriteId].x2 -= gTasks[taskId].data[0] >> 8;
gTasks[taskId].data[0] &= 0xFF;
x = gSprites[spriteId].x + gSprites[spriteId].x2 + 32;
if (x > 304)
gTasks[taskId].data[10]++;
break;
case 1:
refresh_graphics_maybe(gBattleAnimAttacker, gTasks[taskId].data[11], spriteId);
gTasks[taskId].data[10]++;
break;
case 2:
gTasks[taskId].data[0] += 0x500;
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
gSprites[spriteId].x2 -= gTasks[taskId].data[0] >> 8;
else
gSprites[spriteId].x2 += gTasks[taskId].data[0] >> 8;
gTasks[taskId].data[0] &= 0xFF;
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
{
if (gSprites[spriteId].x2 <= 0)
{
gSprites[spriteId].x2 = 0;
// done = FALSE; // fakematching--can't get the tail merge correct
goto DONE;
}
}
else
{
if (gSprites[spriteId].x2 >= 0)
{
gSprites[spriteId].x2 = 0;
done = TRUE;
}
}
if (done)
{
DONE:
DestroyAnimVisualTask(taskId);
}
break;
}
}
void sub_81416C4(u8 taskId)
{
u8 spriteId;
switch (gTasks[taskId].data[15])
{
case 0:
if (GetBattlerPosition_permutated(gBattleAnimAttacker) == 1)
REG_BLDCNT = 0x3F42;
else
REG_BLDCNT = 0x3F44;
REG_BLDALPHA = 0x0010;
gTasks[taskId].data[15]++;
break;
case 1:
if (gTasks[taskId].data[1]++ > 1)
{
gTasks[taskId].data[1] = 0;
gTasks[taskId].data[0]++;
REG_BLDALPHA = (gTasks[taskId].data[0] << 8) | (16 - gTasks[taskId].data[0]);
if (gTasks[taskId].data[0] == 16)
gTasks[taskId].data[15]++;
}
break;
case 2:
spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
DmaClear32(3, (void *)OBJ_VRAM0 + gSprites[spriteId].oam.tileNum * TILE_SIZE_4BPP, 0x800);
sub_80324E0(gBattleAnimAttacker);
DestroyAnimVisualTask(taskId);
break;
}
}
void sub_81417D8(u8 taskId)
{
gBattleAnimArgs[7] = gBattleSpriteInfo[gBattleAnimAttacker].behindSubstitute;
DestroyAnimVisualTask(taskId);
}
void sub_8141808(u8 taskId)
{
gBattleAnimTarget = gEffectBattler;
DestroyAnimVisualTask(taskId);
}
void TryShinyAnimation(u8 battler, struct Pokemon *mon)
{
int isShiny;
u32 otId, personality;
u32 shinyValue;
u8 taskId1, taskId2;
isShiny = 0;
gBattleHealthBoxInfo[battler].triedShinyMonAnim = TRUE;
otId = GetMonData(mon, MON_DATA_OT_ID);
personality = GetMonData(mon, MON_DATA_PERSONALITY);
if (IsAnimBankSpriteVisible(battler))
{
shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
if (shinyValue < 8)
isShiny = TRUE;
if (isShiny)
{
if (GetSpriteTileStartByTag(0x27F9) == 0xFFFF)
{
LoadCompressedObjectPic(&gBattleAnimPicTable[233]);
LoadCompressedObjectPalette(&gBattleAnimPaletteTable[233]);
}
taskId1 = CreateTask(sub_814191C, 10);
taskId2 = CreateTask(sub_814191C, 10);
gTasks[taskId1].data[0] = battler;
gTasks[taskId2].data[0] = battler;
gTasks[taskId1].data[1] = 0;
gTasks[taskId2].data[1] = 1;
return;
}
}
gBattleHealthBoxInfo[battler].finishedShinyMonAnim = TRUE;
}
static void sub_814191C(u8 taskId)
{
u8 battler;
u8 x, y;
u8 spriteId;
u16 counter;
s16 state;
u8 pan;
if (gTasks[taskId].data[13] < 60)
{
gTasks[taskId].data[13]++;
return;
}
if (ewram17840.unkA)
return;
counter = gTasks[taskId].data[10]++;
if (counter & 3)
return;
battler = gTasks[taskId].data[0];
x = GetBattlerSpriteCoord(battler, 0);
y = GetBattlerSpriteCoord(battler, 1);
state = gTasks[taskId].data[11];
if (state == 0)
{
spriteId = CreateSprite(&gBattleAnimSpriteTemplate_84024E8, x, y, 5);
}
else if (state >= 0 && gTasks[taskId].data[11] < 4)
{
spriteId = CreateSprite(&gSpriteTemplate_8402500, x, y, 5);
gSprites[spriteId].oam.tileNum += 4;
}
else
{
spriteId = CreateSprite(&gSpriteTemplate_8402500, x, y, 5);
gSprites[spriteId].oam.tileNum += 5;
}
if (gTasks[taskId].data[1] == 0)
{
gSprites[spriteId].callback = sub_8141B20;
}
else
{
gSprites[spriteId].callback = sub_8141B74;
gSprites[spriteId].x2 = -32;
gSprites[spriteId].y2 = 32;
gSprites[spriteId].invisible = TRUE;
if (gTasks[taskId].data[11] == 0)
{
if (GetBattlerSide(battler) == B_SIDE_PLAYER)
pan = 192;
else
pan = 63;
PlaySE12WithPanning(SE_SHINY, pan);
}
}
gSprites[spriteId].data[0] = taskId;
gTasks[taskId].data[11]++;
gTasks[taskId].data[12]++;
if (gTasks[taskId].data[11] == 5)
gTasks[taskId].func = sub_8141AD8;
}
static void sub_8141AD8(u8 taskId)
{
u8 battler;
if (gTasks[taskId].data[12] == 0)
{
if (gTasks[taskId].data[1] == 1)
{
battler = gTasks[taskId].data[0];
gBattleHealthBoxInfo[battler].finishedShinyMonAnim = TRUE;
}
DestroyTask(taskId);
}
}
static void sub_8141B20(struct Sprite *sprite)
{
sprite->x2 = Sin(sprite->data[1], 24);
sprite->y2 = Cos(sprite->data[1], 24);
sprite->data[1] += 12;
if (sprite->data[1] > 0xFF)
{
gTasks[sprite->data[0]].data[12]--;
FreeSpriteOamMatrix(sprite);
DestroySprite(sprite);
}
}
static void sub_8141B74(struct Sprite *sprite)
{
if (sprite->data[1] < 4)
{
sprite->data[1]++;
}
else
{
sprite->invisible = FALSE;
sprite->x2 += 5;
sprite->y2 -= 5;
if (sprite->x2 > 32)
{
gTasks[sprite->data[0]].data[12]--;
FreeSpriteOamMatrix(sprite);
DestroySprite(sprite);
}
}
}
void sub_8141BD4(u8 taskId)
{
u8 paletteIndex;
LoadCompressedObjectPic(&gBattleAnimPicTable[269]);
LoadCompressedObjectPalette(&gBattleAnimPaletteTable[269]);
paletteIndex = IndexOfSpritePaletteTag(0x281D); // unused
DestroyAnimVisualTask(taskId);
}
void sub_8141C08(u8 taskId)
{
FreeSpriteTilesByTag(0x281D);
FreeSpritePaletteByTag(0x281D);
DestroyAnimVisualTask(taskId);
}
static void sub_8141C30(struct Sprite *sprite)
{
InitAnimSpritePos(sprite, 0);
sprite->data[0] = 30;
sprite->data[2] = GetBattlerSpriteCoord(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), 0) + gBattleAnimArgs[2];
sprite->data[4] = GetBattlerSpriteCoord(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), 1) + gBattleAnimArgs[3];
sprite->data[5] = -32;
InitAnimArcTranslation(sprite);
StartSpriteAnim(&gSprites[gBattlerSpriteIds[gBattleAnimAttacker]], 1);
sprite->callback = sub_8141CBC;
}
static void sub_8141CBC(struct Sprite *sprite)
{
if (gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].animCmdIndex == 1)
sprite->callback = sub_8141CF4;
}
static void sub_8141CF4(struct Sprite *sprite)
{
if (TranslateAnimArc(sprite))
{
sprite->data[0] = 0;
sprite->invisible = TRUE;
sprite->callback = sub_8141D20;
}
}
static void sub_8141D20(struct Sprite *sprite)
{
if (gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].animEnded)
{
if (++sprite->data[0] > 0)
{
StartSpriteAnim(&gSprites[gBattlerSpriteIds[gBattleAnimAttacker]], 0);
DestroyAnimSprite(sprite);
}
}
}
void sub_8141D7C(u8 taskId)
{
gBattleAnimAttacker = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
gBattleAnimTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
DestroyAnimVisualTask(taskId);
}
void sub_8141DAC(u8 taskId)
{
if (ewram17840.unk0 == 83)
gBattleAnimArgs[0] = 1;
else if (ewram17840.unk0 == 250)
gBattleAnimArgs[0] = 2;
else if (ewram17840.unk0 == 128)
gBattleAnimArgs[0] = 3;
else if (ewram17840.unk0 == 328)
gBattleAnimArgs[0] = 4;
else
gBattleAnimArgs[0] = 0;
DestroyAnimVisualTask(taskId);
}
void sub_8141E10(u8 taskId)
{
gBattleAnimAttacker = ewram17840.unk0;
gBattleAnimTarget = ewram17840.unk0 >> 8;
DestroyAnimVisualTask(taskId);
}