diff options
Diffstat (limited to 'src/battle_anim_special.c')
-rwxr-xr-x | src/battle_anim_special.c | 2170 |
1 files changed, 2170 insertions, 0 deletions
diff --git a/src/battle_anim_special.c b/src/battle_anim_special.c new file mode 100755 index 000000000..7d158f671 --- /dev/null +++ b/src/battle_anim_special.c @@ -0,0 +1,2170 @@ +#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" + +extern int gUnknown_03005F0C; +extern u16 gUnknown_03005F10; +extern u16 gUnknown_03005F14; + +extern s16 gBattleAnimArgs[]; +extern u8 gBattleAnimAttacker; +extern u8 gBattleAnimTarget; +extern u8 gHealthboxIDs[]; +extern u8 gBankSpriteIds[]; +extern u16 gBattlerPartyIndexes[]; +extern u16 gLastUsedItem; +extern u8 gDoingBattleAnim; +extern u8 gEffectBank; + +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 = gHealthboxIDs[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].pos1.x + 32; + gBattle_BG1_Y = -gSprites[spriteId3].pos1.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[gHealthboxIDs[battler]].oam.affineParam; + spriteId2 = gSprites[gHealthboxIDs[battler]].data[5]; + gSprites[gHealthboxIDs[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 = gHealthboxIDs[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 = gHealthboxIDs[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 = gBankSpriteIds[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 = 1; + DestroyAnimVisualTask(taskId); + break; + } +} + +void sub_813F844(u8 taskId) +{ + u8 spriteId; + u16 ball; + u8 ballIndex; + u8 x, y; + u8 priority, subpriority; + u32 selectedPalettes; + + spriteId = gBankSpriteIds[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[gBankSpriteIds[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 = GetBattlerSubpriority(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[gBankSpriteIds[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]], 1); + gTasks[taskId].data[0] = spriteId; + gTasks[taskId].func = sub_813FCBC; +} + +static void sub_813FCBC(u8 taskId) +{ + if (gSprites[gBankSpriteIds[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]].animCmdIndex == 1) + { + PlaySE12WithPanning(SE_NAGERU, 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[gBankSpriteIds[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]].animEnded) + { + StartSpriteAnim(&gSprites[gBankSpriteIds[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->pos1.x; + sprite->data[2] = temp; + sprite->data[3] = sprite->pos1.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->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = 0; + sprite->pos2.y = 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->pos1.x, sprite->pos1.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[gBankSpriteIds[gBattleAnimTarget]].data[1] = 0; + } +} + +static void sub_813FEC8(struct Sprite *sprite) +{ + u8 spriteId; + u8 taskId; + + spriteId = gBankSpriteIds[gBattleAnimTarget]; + taskId = sprite->data[5]; + + if (++gTasks[taskId].data[1] == 11) + PlaySE(SE_SUIKOMU); + + switch (gTasks[taskId].data[0]) + { + case 0: + PrepareBattlerSpriteForRotScale(spriteId, 0); + gTasks[taskId].data[10] = 256; + gUnknown_03005F0C = 28; + gUnknown_03005F14 = (gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y) - (sprite->pos1.y + sprite->pos2.y); + 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].pos2.y = -gTasks[taskId].data[3] >> 8; + if (gTasks[taskId].data[10] >= 0x480) + gTasks[taskId].data[0]++; + break; + case 2: + sub_8078F40(spriteId); + gSprites[spriteId].invisible = 1; + 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->pos1.y += Cos(angle, 32); + sprite->pos2.y = -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->pos2.y = -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_KON); + break; + case 2: + PlaySE(SE_KON2); + break; + case 3: + PlaySE(SE_KON3); + break; + default: + PlaySE(SE_KON4); + break; + } + } + break; + case 1: + sprite->pos2.y = -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->pos1.y += Cos(64, 32); + sprite->pos2.y = 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_BOWA); + } +} + +static void sub_81401A0(struct Sprite *sprite) +{ + s8 state; + u16 var0; + + switch (sprite->data[3] & 0xFF) + { + case 0: + if ((s16)ewram17840.unkC > 0xFF) + { + sprite->pos2.x += 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->pos2.x += 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->pos2.x += 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_BOWA); + } + 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_FANFA5); + } + else if (sprite->data[4] == 315) + { + FreeOamMatrix(gSprites[gBankSpriteIds[*battler]].oam.matrixNum); + DestroySprite(&gSprites[gBankSpriteIds[*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 = 1; + 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->pos1.x, sprite->pos1.y - 5, 1, 28, ballIndex); + sub_8141314(1, gBattleAnimTarget, 14, ballIndex); + + LABEL: + gSprites[gBankSpriteIds[gBattleAnimTarget]].invisible = 0; + StartSpriteAffineAnim(&gSprites[gBankSpriteIds[gBattleAnimTarget]], 1); + AnimateSprite(&gSprites[gBankSpriteIds[gBattleAnimTarget]]); + gSprites[gBankSpriteIds[gBattleAnimTarget]].data[1] = 0x1000; +} + +static void sub_81406BC(struct Sprite *sprite) +{ + int next = FALSE; + + if (sprite->animEnded) + sprite->invisible = 1; + + if (gSprites[gBankSpriteIds[gBattleAnimTarget]].affineAnimEnded) + { + StartSpriteAffineAnim(&gSprites[gBankSpriteIds[gBattleAnimTarget]], 0); + next = TRUE; + } + else + { + gSprites[gBankSpriteIds[gBattleAnimTarget]].data[1] -= 288; + gSprites[gBankSpriteIds[gBattleAnimTarget]].pos2.y = gSprites[gBankSpriteIds[gBattleAnimTarget]].data[1] >> 8; + } + + if (sprite->animEnded && next) + { + gSprites[gBankSpriteIds[gBattleAnimTarget]].pos2.y = 0; + gSprites[gBankSpriteIds[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->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + for (i = 0; i < 6; i++) + sprite->data[i] = 0; + + sprite->callback = sub_81407F4; +} + +#ifdef NONMATCHING +// there is some weird typing going on with var0 and var1. +static void sub_81407F4(struct Sprite *sprite) +{ + s16 var0, var1; + + var0 = sprite->data[0] + 0x800; + var1 = sprite->data[1] + 0x680; + sprite->pos2.x -= var1 >> 8; + sprite->pos2.y += var0 >> 8; + sprite->data[0] = var0 & 0xFF; + sprite->data[1] = var1 & 0xFF; + + if (sprite->pos1.y + sprite->pos2.y > 160 + || sprite->pos1.x + sprite->pos2.x < -8) + { + sprite->data[0] = 0; + sprite->callback = sub_81405C8; + gDoingBattleAnim = 0; + UpdateOamPriorityInAllHealthboxes(1); + } +} +#else +NAKED +static void sub_81407F4(struct Sprite *sprite) +{ + asm(".syntax unified\n\ + push {r4,lr}\n\ + adds r4, r0, 0\n\ + movs r0, 0x80\n\ + lsls r0, 4\n\ + adds r2, r0, 0\n\ + ldrh r1, [r4, 0x2E]\n\ + adds r2, r1\n\ + movs r0, 0xD0\n\ + lsls r0, 3\n\ + adds r3, r0, 0\n\ + ldrh r1, [r4, 0x30]\n\ + adds r3, r1\n\ + lsls r1, r3, 16\n\ + asrs r1, 24\n\ + ldrh r0, [r4, 0x24]\n\ + subs r0, r1\n\ + strh r0, [r4, 0x24]\n\ + lsls r0, r2, 16\n\ + asrs r0, 24\n\ + ldrh r1, [r4, 0x26]\n\ + adds r0, r1\n\ + strh r0, [r4, 0x26]\n\ + movs r0, 0xFF\n\ + ands r2, r0\n\ + strh r2, [r4, 0x2E]\n\ + ands r3, r0\n\ + strh r3, [r4, 0x30]\n\ + movs r2, 0x22\n\ + ldrsh r0, [r4, r2]\n\ + movs r2, 0x26\n\ + ldrsh r1, [r4, r2]\n\ + adds r0, r1\n\ + cmp r0, 0xA0\n\ + bgt _0814084A\n\ + movs r1, 0x20\n\ + ldrsh r0, [r4, r1]\n\ + movs r2, 0x24\n\ + ldrsh r1, [r4, r2]\n\ + adds r0, r1\n\ + movs r1, 0x8\n\ + negs r1, r1\n\ + cmp r0, r1\n\ + bge _0814085E\n\ +_0814084A:\n\ + movs r0, 0\n\ + strh r0, [r4, 0x2E]\n\ + ldr r0, _08140864 @ =sub_81405C8\n\ + str r0, [r4, 0x1C]\n\ + ldr r1, _08140868 @ =gDoingBattleAnim\n\ + movs r0, 0\n\ + strb r0, [r1]\n\ + movs r0, 0x1\n\ + bl UpdateOamPriorityInAllHealthboxes\n\ +_0814085E:\n\ + pop {r4}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08140864: .4byte sub_81405C8\n\ +_08140868: .4byte gDoingBattleAnim\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +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_BOWA2); + 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->pos2.x = Sin(sprite->data[0], sprite->data[1]); + sprite->pos2.y = 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->pos2.x = Sin(sprite->data[0], sprite->data[1]); + sprite->pos2.y = 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->pos2.x = Sin(sprite->data[0], sprite->data[1]); + sprite->pos2.y = 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->pos2.x = Sin(sprite->data[0], sprite->data[1]); + sprite->pos2.y = 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 = gBankSpriteIds[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].pos2.x += gTasks[taskId].data[0] >> 8; + else + gSprites[spriteId].pos2.x -= gTasks[taskId].data[0] >> 8; + + gTasks[taskId].data[0] &= 0xFF; + x = gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x + 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].pos2.x -= gTasks[taskId].data[0] >> 8; + else + gSprites[spriteId].pos2.x += gTasks[taskId].data[0] >> 8; + + gTasks[taskId].data[0] &= 0xFF; + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + if (gSprites[spriteId].pos2.x <= 0) + { + gSprites[spriteId].pos2.x = 0; + // done = FALSE; // fakematching--can't get the tail merge correct + goto DONE; + } + } + else + { + if (gSprites[spriteId].pos2.x >= 0) + { + gSprites[spriteId].pos2.x = 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 = gBankSpriteIds[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] = ewram17800[gBattleAnimAttacker].substituteSprite; + DestroyAnimVisualTask(taskId); +} + +void sub_8141808(u8 taskId) +{ + gBattleAnimTarget = gEffectBank; + DestroyAnimVisualTask(taskId); +} + +void sub_8141828(u8 battler, struct Pokemon *mon) +{ + int isShiny; + u32 otId, personality; + u32 shinyValue; + u8 taskId1, taskId2; + + isShiny = 0; + ewram17810[battler].unk0_7 = 1; + 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; + } + } + + ewram17810[battler].unk1_0 = 1; +} + +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].pos2.x = -32; + gSprites[spriteId].pos2.y = 32; + gSprites[spriteId].invisible = 1; + if (gTasks[taskId].data[11] == 0) + { + if (GetBattlerSide(battler) == B_SIDE_PLAYER) + pan = 192; + else + pan = 63; + + PlaySE12WithPanning(SE_REAPOKE, 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]; + ewram17810[battler].unk1_0 = 1; + } + + DestroyTask(taskId); + } +} + +static void sub_8141B20(struct Sprite *sprite) +{ + sprite->pos2.x = Sin(sprite->data[1], 24); + sprite->pos2.y = 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 = 0; + sprite->pos2.x += 5; + sprite->pos2.y -= 5; + if (sprite->pos2.x > 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[gBankSpriteIds[gBattleAnimAttacker]], 1); + sprite->callback = sub_8141CBC; +} + +static void sub_8141CBC(struct Sprite *sprite) +{ + if (gSprites[gBankSpriteIds[gBattleAnimAttacker]].animCmdIndex == 1) + sprite->callback = sub_8141CF4; +} + +static void sub_8141CF4(struct Sprite *sprite) +{ + if (TranslateAnimArc(sprite)) + { + sprite->data[0] = 0; + sprite->invisible = 1; + sprite->callback = sub_8141D20; + } +} + +static void sub_8141D20(struct Sprite *sprite) +{ + if (gSprites[gBankSpriteIds[gBattleAnimAttacker]].animEnded) + { + if (++sprite->data[0] > 0) + { + StartSpriteAnim(&gSprites[gBankSpriteIds[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); +} |