#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 = 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[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].substituteSprite; DestroyAnimVisualTask(taskId); } void sub_8141808(u8 taskId) { gBattleAnimTarget = gEffectBattler; 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].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]; ewram17810[battler].unk1_0 = 1; } 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); }