diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_anim.c | 2 | ||||
-rwxr-xr-x | src/battle_anim_8170478.c | 2267 | ||||
-rw-r--r-- | src/battle_anim_utility_funcs.c | 8 | ||||
-rw-r--r-- | src/battle_intro.c | 741 | ||||
-rw-r--r-- | src/battle_main.c | 4 | ||||
-rw-r--r-- | src/easy_chat.c | 3 | ||||
-rw-r--r-- | src/pokeball.c | 12 | ||||
-rw-r--r-- | src/pokemon.c | 12 |
8 files changed, 3006 insertions, 43 deletions
diff --git a/src/battle_anim.c b/src/battle_anim.c index 95c6f7b3c..5e62c0957 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -26,8 +26,6 @@ extern struct MusicPlayerInfo gMPlayInfo_SE2; extern const u16 gMovesWithQuietBGM[]; extern const u8 *const gBattleAnims_Moves[]; -extern const struct CompressedSpriteSheet gBattleAnimPicTable[]; -extern const struct CompressedSpritePalette gBattleAnimPaletteTable[]; extern const struct BattleAnimBackground gBattleAnimBackgroundTable[]; // this file's functions diff --git a/src/battle_anim_8170478.c b/src/battle_anim_8170478.c new file mode 100755 index 000000000..6c91ff934 --- /dev/null +++ b/src/battle_anim_8170478.c @@ -0,0 +1,2267 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_controllers.h" +#include "battle_interface.h" +#include "decompress.h" +#include "dma3.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "m4a.h" +#include "main.h" +#include "palette.h" +#include "pokeball.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" +#include "util.h" +#include "constants/rgb.h" +#include "constants/items.h" +#include "constants/songs.h" + +// iwram +int gUnknown_030062DC; +u16 gUnknown_030062E0; +u16 gUnknown_030062E4; + +static void sub_8170660(u8); +static void sub_8170A38(u8); +static void sub_8170EF0(u8); +static void sub_8171104(struct Sprite *); +static void sub_8171030(u8); +static void sub_81710A8(u8); +static void sub_8171134(struct Sprite *); +static void sub_8171CAC(struct Sprite *); +static void sub_81711E8(struct Sprite *); +static void sub_8171240(struct Sprite *); +static void sub_817138C(struct Sprite *); +static void sub_81713D0(struct Sprite *); +static void sub_81717B4(struct Sprite *); +static void sub_81714D4(struct Sprite *); +static void sub_8171520(struct Sprite *); +static void sub_81717D8(struct Sprite *); +static void sub_8171AE4(struct Sprite *); +static void sub_81717F8(struct Sprite *); +static void sub_81719EC(struct Sprite *); +static void sub_81718D8(struct Sprite *); +static void sub_81719C0(struct Sprite *); +static void sub_8171D60(u8); +static void sub_8171AAC(struct Sprite *); +static void sub_8171BAC(struct Sprite *); +static void sub_8171CE8(struct Sprite *); +static void PokeBallOpenParticleAnimation_Step1(struct Sprite *); +static void PokeBallOpenParticleAnimation_Step2(struct Sprite *); +static void DestroyBallOpenAnimationParticle(struct Sprite *); +static void FanOutBallOpenParticles_Step1(struct Sprite *); +static void RepeatBallOpenParticleAnimation_Step1(struct Sprite *); +static void PremierBallOpenParticleAnimation_Step1(struct Sprite *); +static void sub_8172AB0(u8); +static void sub_8172B40(u8); +static void sub_8172B90(u8); +static void sub_8172FEC(u8); +static void sub_81731FC(struct Sprite *); +static void sub_8173250(struct Sprite *); +static void sub_81731B0(u8); +static void sub_817339C(struct Sprite *); +static void sub_81733D4(struct Sprite *); +static void sub_8173400(struct Sprite *); +static void PokeBallOpenParticleAnimation(u8); +static void GreatBallOpenParticleAnimation(u8); +static void SafariBallOpenParticleAnimation(u8); +static void UltraBallOpenParticleAnimation(u8); +static void MasterBallOpenParticleAnimation(u8); +static void DiveBallOpenParticleAnimation(u8); +static void RepeatBallOpenParticleAnimation(u8); +static void TimerBallOpenParticleAnimation(u8); +static void PremierBallOpenParticleAnimation(u8); +static void sub_817330C(struct Sprite *); + +struct BallCaptureSuccessStarData +{ + s8 xOffset; + s8 yOffset; + s8 unk2; +}; + +static const struct BallCaptureSuccessStarData sBallCaptureSuccessStarData[] = +{ + { + .xOffset = 10, + .yOffset = 2, + .unk2 = -3, + }, + { + .xOffset = 15, + .yOffset = 0, + .unk2 = -4, + }, + { + .xOffset = -10, + .yOffset = 2, + .unk2 = -4, + }, +}; + +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}, +}; + +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 gUnknown_085E5154[] = +{ + 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 gUnknown_085E5170[] = +{ + ANIMCMD_FRAME(3, 1), + ANIMCMD_END, +}; + +const union AnimCmd gUnknown_085E5178[] = +{ + ANIMCMD_FRAME(4, 1), + ANIMCMD_END, +}; + +const union AnimCmd gUnknown_085E5180[] = +{ + ANIMCMD_FRAME(5, 1), + ANIMCMD_END, +}; + +const union AnimCmd gUnknown_085E5188[] = +{ + ANIMCMD_FRAME(6, 4), + ANIMCMD_FRAME(7, 4), + ANIMCMD_JUMP(0), +}; + +const union AnimCmd gUnknown_085E5194[] = +{ + ANIMCMD_FRAME(7, 4), + ANIMCMD_END, +}; + +const union AnimCmd *const gUnknown_085E519C[] = +{ + gUnknown_085E5154, + gUnknown_085E5170, + gUnknown_085E5178, + gUnknown_085E5180, + gUnknown_085E5188, + gUnknown_085E5194, +}; + +const u8 gBallOpenParticleAnimNums[] = +{ + 0, + 0, + 0, + 5, + 1, + 2, + 2, + 3, + 5, + 5, + 4, + 4, +}; + +const TaskFunc gBallOpenParticleAnimationFuncs[] = +{ + PokeBallOpenParticleAnimation, + GreatBallOpenParticleAnimation, + SafariBallOpenParticleAnimation, + UltraBallOpenParticleAnimation, + MasterBallOpenParticleAnimation, + SafariBallOpenParticleAnimation, + DiveBallOpenParticleAnimation, + UltraBallOpenParticleAnimation, + RepeatBallOpenParticleAnimation, + TimerBallOpenParticleAnimation, + GreatBallOpenParticleAnimation, + PremierBallOpenParticleAnimation, +}; + +const struct SpriteTemplate gUnknown_085E51F0[] = +{ + { + .tileTag = 55020, + .paletteTag = 55020, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55021, + .paletteTag = 55021, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55022, + .paletteTag = 55022, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55023, + .paletteTag = 55023, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55024, + .paletteTag = 55024, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55025, + .paletteTag = 55025, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55026, + .paletteTag = 55026, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55027, + .paletteTag = 55027, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55028, + .paletteTag = 55028, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55029, + .paletteTag = 55029, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55030, + .paletteTag = 55030, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 55031, + .paletteTag = 55031, + .oam = &gUnknown_08524904, + .anims = gUnknown_085E519C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, +}; + +const u16 gUnknown_085E5310[] = +{ + RGB(31, 22, 30), + RGB(16, 23, 30), + RGB(23, 30, 20), + RGB(31, 31, 15), + RGB(23, 20, 28), + RGB(21, 31, 25), + RGB(12, 25, 30), + RGB(30, 27, 10), + RGB(31, 24, 16), + RGB(29, 30, 30), + RGB(31, 17, 10), + RGB(31, 9, 10), + RGB(0, 0, 0), + RGB(1, 16, 0), + RGB(3, 0, 1), + RGB(1, 8, 0), + RGB(0, 8, 0), + RGB(3, 8, 1), + RGB(6, 8, 1), + RGB(4, 0, 0), +}; + +const struct SpriteTemplate gBattleAnimSpriteTemplate_85E5338 = +{ + .tileTag = ANIM_TAG_UNUSED_RED_BRICK, + .paletteTag = ANIM_TAG_UNUSED_RED_BRICK, + .oam = &gUnknown_0852490C, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_817330C, +}; + +const union AnimCmd gUnknown_085E5350[] = +{ + ANIMCMD_FRAME(64, 1), + ANIMCMD_END, +}; + +const union AnimCmd *const gUnknown_085E5358[] = { + gUnknown_085E5350, +}; + +const struct SpriteTemplate gBattleAnimSpriteTemplate_085E535C = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gUnknown_08524914, + .anims = gUnknown_085E5358, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_817330C, +}; + +extern const struct SpriteTemplate gUnknown_085CE388; +extern const struct SpriteTemplate gUnknown_085CE3A0; + +void unref_sub_8170478(u8 taskId) +{ + struct UnknownAnimStruct2 unknownStruct; + u8 healthBoxSpriteId; + u8 battler; + u8 spriteId1, spriteId2, spriteId3, spriteId4; + + battler = gBattleAnimAttacker; + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG0 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 0); + SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); + SetAnimBgAttribute(1, BG_ANIM_AREA_OVERFLOW_MODE, 1); + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 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_80A6B30(&unknownStruct); + sub_80A6D48(unknownStruct.bgId, gUnknown_08C2EA9C); + sub_80A6CC0(unknownStruct.bgId, gUnknown_08C2EA50, unknownStruct.tilesOffset); + LoadCompressedPalette(gUnknown_08C2DDA4, unknownStruct.unk8 << 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_8170660; +} + +static void sub_8170660(u8 taskId) +{ + 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]++; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[12], 16 - 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]--; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[12], 16 - gTasks[taskId].data[12])); + if (gTasks[taskId].data[12] == 0) + { + sub_80A477C(0); + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR); + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); + + SetGpuReg(REG_OFFSET_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) ^ DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); + DestroySprite(&gSprites[gTasks[taskId].data[0]]); + DestroySprite(&gSprites[gTasks[taskId].data[2]]); + SetAnimBgAttribute(1, BG_ANIM_AREA_OVERFLOW_MODE, 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; + } +} + +static void sub_8170834(u8 *paletteId1, u8 *paletteId2, u8 battler) +{ + u8 healthBoxSpriteId; + u8 spriteId1, spriteId2; + u16 offset1, offset2; + + healthBoxSpriteId = gHealthboxSpriteIds[battler]; + spriteId1 = gSprites[healthBoxSpriteId].oam.affineParam; + spriteId2 = gSprites[healthBoxSpriteId].data[5]; + *paletteId1 = AllocSpritePalette(0xD709); + *paletteId2 = AllocSpritePalette(0xD70A); + + offset1 = (gSprites[healthBoxSpriteId].oam.paletteNum * 16) + 0x100; + offset2 = (gSprites[spriteId2].oam.paletteNum * 16) + 0x100; + LoadPalette(&gPlttBufferUnfaded[offset1], *paletteId1 * 16 + 0x100, 0x20); + LoadPalette(&gPlttBufferUnfaded[offset2], *paletteId2 * 16 + 0x100, 0x20); + + gSprites[healthBoxSpriteId].oam.paletteNum = *paletteId1; + gSprites[spriteId1].oam.paletteNum = *paletteId1; + gSprites[spriteId2].oam.paletteNum = *paletteId2; +} + +void sub_8170920(u8 taskId) +{ + u8 paletteId1, paletteId2; + sub_8170834(&paletteId1, &paletteId2, gBattleAnimAttacker); + DestroyAnimVisualTask(taskId); +} + +static void sub_817094C(u8 battler) +{ + u8 healthBoxSpriteId; + u8 spriteId1, spriteId2; + u8 paletteId1, paletteId2; + + healthBoxSpriteId = gHealthboxSpriteIds[battler]; + spriteId1 = gSprites[healthBoxSpriteId].oam.affineParam; + spriteId2 = gSprites[healthBoxSpriteId].data[5]; + + FreeSpritePaletteByTag(0xD709); + FreeSpritePaletteByTag(0xD70A); + paletteId1 = IndexOfSpritePaletteTag(0xD6FF); + paletteId2 = IndexOfSpritePaletteTag(0xD704); + gSprites[healthBoxSpriteId].oam.paletteNum = paletteId1; + gSprites[spriteId1].oam.paletteNum = paletteId1; + gSprites[spriteId2].oam.paletteNum = paletteId2; +} + +void sub_81709EC(u8 taskId) +{ + sub_817094C(gBattleAnimAttacker); + DestroyAnimVisualTask(taskId); +} + +void sub_8170A0C(u8 taskId) +{ + gTasks[taskId].data[10] = gBattleAnimArgs[0]; + gTasks[taskId].data[11] = gBattleAnimArgs[1]; + gTasks[taskId].func = sub_8170A38; +} + +static void sub_8170A38(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_8170B04(u8 taskId) +{ + u8 spriteId; + + spriteId = gBattlerSpriteIds[gBattleAnimAttacker]; + switch (gTasks[taskId].data[0]) + { + case 0: + sub_80A7270(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_80A7E6C(spriteId); + if (gTasks[taskId].data[10] >= 0x2D0) + gTasks[taskId].data[0]++; + break; + case 2: + sub_80A7344(spriteId); + gSprites[spriteId].invisible = 1; + DestroyAnimVisualTask(taskId); + break; + } +} + +void sub_8170BB0(u8 taskId) +{ + u8 spriteId; + u16 ball; + u8 ballId; + 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); + + ballId = ItemIdToBallId(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, ballId); + selectedPalettes = sub_80A75AC(1, 0, 0, 0, 0, 0, 0); + gTasks[taskId].data[11] = LaunchBallFadeMonTask(0, gBattleAnimAttacker, selectedPalettes, ballId); + 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_8170CFC(u8 taskId) +{ + u8 ballId = ItemIdToBallId(gLastUsedItem); + LoadBallGfx(ballId); + DestroyAnimVisualTask(taskId); +} + +void sub_8170D24(u8 taskId) +{ + u8 ballId = ItemIdToBallId(gLastUsedItem); + FreeBallGfx(ballId); + DestroyAnimVisualTask(taskId); +} + +void AnimTask_IsBallBlockedByTrainer(u8 taskId) +{ + if (gBattleSpritesDataPtr->animationData->ballThrowCaseId == BALL_TRAINER_BLOCK) + gBattleAnimArgs[7] = -1; + else + gBattleAnimArgs[7] = 0; + + DestroyAnimVisualTask(taskId); +} + +u8 ItemIdToBallId(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_8170E04(u8 taskId) +{ + u8 ballId; + u8 spriteId; + + ballId = ItemIdToBallId(gLastUsedItem); + spriteId = CreateSprite(&gBallSpriteTemplates[ballId], 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_8171104; + gBattleSpritesDataPtr->animationData->field_9_x2 = gSprites[gBattlerSpriteIds[gBattleAnimTarget]].invisible; + gTasks[taskId].data[0] = spriteId; + gTasks[taskId].func = sub_8170EF0; +} + +static void sub_8170EF0(u8 taskId) +{ + u8 spriteId = gTasks[taskId].data[0]; + if ((u16)gSprites[spriteId].data[0] == 0xFFFF) + DestroyAnimVisualTask(taskId); +} + +void sub_8170F2C(u8 taskId) +{ + int x, y; + u8 ballId; + u8 subpriority; + u8 spriteId; + + if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) + { + x = 32; + y = 11; + } + else + { + x = 23; + y = 5; + } + + ballId = ItemIdToBallId(gLastUsedItem); + subpriority = sub_80A82E4(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)) + 1; + spriteId = CreateSprite(&gBallSpriteTemplates[ballId], 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; + gSprites[gBattlerSpriteIds[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]].callback = sub_8039E84; + gTasks[taskId].data[0] = spriteId; + gTasks[taskId].func = sub_8171030; +} + +static void sub_8171030(u8 taskId) +{ + if (gSprites[gBattlerSpriteIds[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]].animCmdIndex == 1) + { + PlaySE12WithPanning(SE_NAGERU, 0); + gSprites[gTasks[taskId].data[0]].callback = sub_8171104; + CreateTask(sub_81710A8, 10); + gTasks[taskId].func = sub_8170EF0; + } +} + +static void sub_81710A8(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_8171104(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_8171134; +} + +static void sub_8171134(struct Sprite *sprite) +{ + int i; + u8 ballId; + int ballId2; // extra var needed to match + + if (TranslateAnimArc(sprite)) + { + if (gBattleSpritesDataPtr->animationData->ballThrowCaseId == BALL_TRAINER_BLOCK) + { + sprite->callback = sub_8171CAC; + } + 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_81711E8; + ballId = ItemIdToBallId(gLastUsedItem); + ballId2 = ballId; + if (ballId2 > 11) + return; + if (ballId2 < 0) + return; + + AnimateBallOpenParticles(sprite->pos1.x, sprite->pos1.y - 5, 1, 28, ballId); + LaunchBallFadeMonTask(0, gBattleAnimTarget, 14, ballId); + } + } +} + +static void sub_81711E8(struct Sprite *sprite) +{ + if (++sprite->data[5] == 10) + { + sprite->data[5] = CreateTask(TaskDummy, 50); + sprite->callback = sub_8171240; + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].data[1] = 0; + } +} + +static void sub_8171240(struct Sprite *sprite) +{ + u8 spriteId; + u8 taskId; + + spriteId = gBattlerSpriteIds[gBattleAnimTarget]; + taskId = sprite->data[5]; + + if (++gTasks[taskId].data[1] == 11) + PlaySE(SE_SUIKOMU); + + switch (gTasks[taskId].data[0]) + { + case 0: + sub_80A7270(spriteId, 0); + gTasks[taskId].data[10] = 256; + gUnknown_030062DC = 28; + gUnknown_030062E4 = (gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y) - (sprite->pos1.y + sprite->pos2.y); + gUnknown_030062E0 = (u32)(gUnknown_030062E4 * 256) / 28; + gTasks[taskId].data[2] = gUnknown_030062E0; + 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_80A7344(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_817138C; + } + break; + } +} + +static void sub_817138C(struct Sprite *sprite) +{ + int angle; + + if (sprite->animEnded) + { + sprite->data[3] = 0; + sprite->data[4] = 40; + sprite->data[5] = 0; + angle = 0; + sprite->pos1.y += Cos(angle, 40); + sprite->pos2.y = -Cos(angle, sprite->data[4]); + sprite->callback = sub_81713D0; + } +} + +static void sub_81713D0(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, 40); + sprite->pos2.y = 0; + if (gBattleSpritesDataPtr->animationData->ballThrowCaseId == BALL_NO_SHAKES) + { + sprite->data[5] = 0; + sprite->callback = sub_81717B4; + } + else + { + sprite->callback = sub_81714D4; + sprite->data[4] = 1; + sprite->data[5] = 0; + } + } +} + +static void sub_81714D4(struct Sprite *sprite) +{ + if (++sprite->data[3] == 31) + { + sprite->data[3] = 0; + sprite->affineAnimPaused = 1; + StartSpriteAffineAnim(sprite, 1); + gBattleSpritesDataPtr->animationData->field_C = 0; + sprite->callback = sub_8171520; + PlaySE(SE_BOWA); + } +} + +static void sub_8171520(struct Sprite *sprite) +{ + s8 state; + u16 var0; + + switch (sprite->data[3] & 0xFF) + { + case 0: + if (gBattleSpritesDataPtr->animationData->field_C > 0xFF) + { + sprite->pos2.x += sprite->data[4]; + gBattleSpritesDataPtr->animationData->field_C &= 0xFF; + } + else + { + gBattleSpritesDataPtr->animationData->field_C += 0xB0; + } + + sprite->data[5]++; + sprite->affineAnimPaused = 0; + var0 = sprite->data[5] + 7; + if (var0 > 14) + { + gBattleSpritesDataPtr->animationData->field_C = 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 (gBattleSpritesDataPtr->animationData->field_C > 0xFF) + { + sprite->pos2.x += sprite->data[4]; + gBattleSpritesDataPtr->animationData->field_C &= 0xFF; + } + else + { + gBattleSpritesDataPtr->animationData->field_C += 0xB0; + } + + sprite->data[5]++; + sprite->affineAnimPaused = 0; + var0 = sprite->data[5] + 12; + if (var0 > 24) + { + gBattleSpritesDataPtr->animationData->field_C = 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 (gBattleSpritesDataPtr->animationData->field_C > 0xFF) + { + sprite->pos2.x += sprite->data[4]; + gBattleSpritesDataPtr->animationData->field_C &= 0xFF; + } + else + { + gBattleSpritesDataPtr->animationData->field_C += 0xB0; + } + + sprite->data[5]++; + sprite->affineAnimPaused = 0; + var0 = sprite->data[5] + 4; + if (var0 > 8) + { + gBattleSpritesDataPtr->animationData->field_C = 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 == gBattleSpritesDataPtr->animationData->ballThrowCaseId) + { + sprite->affineAnimPaused = 1; + sprite->callback = sub_81717B4; + } + else + { + if (gBattleSpritesDataPtr->animationData->ballThrowCaseId == BALL_3_SHAKES_SUCCESS && state == 3) + { + sprite->callback = sub_81717D8; + 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_81717B4(struct Sprite *sprite) +{ + if (++sprite->data[5] == 31) + { + sprite->data[5] = 0; + sprite->callback = sub_8171AE4; + } +} + +static void sub_81717D8(struct Sprite *sprite) +{ + sprite->animPaused = 1; + sprite->callback = sub_81717F8; + sprite->data[3] = 0; + sprite->data[4] = 0; + sprite->data[5] = 0; +} + +static void sub_81717F8(struct Sprite *sprite) +{ + u8 *battler = &gBattleAnimTarget; + + sprite->data[4]++; + if (sprite->data[4] == 40) + { + PlaySE(SE_RG_GETTING); + BlendPalettes(0x10000 << sprite->oam.paletteNum, 6, RGB(0, 0, 0)); + sub_81719EC(sprite); + } + else if (sprite->data[4] == 60) + { + BeginNormalPaletteFade(0x10000 << sprite->oam.paletteNum, 2, 6, 0, RGB(0, 0, 0)); + } + else if (sprite->data[4] == 95) + { + gDoingBattleAnim = 0; + UpdateOamPriorityInAllHealthboxes(1); + m4aMPlayAllStop(); + PlaySE(MUS_RG_FAN6); + } + else if (sprite->data[4] == 315) + { + FreeOamMatrix(gSprites[gBattlerSpriteIds[*battler]].oam.matrixNum); + DestroySprite(&gSprites[gBattlerSpriteIds[*battler]]); + sprite->data[0] = 0; + sprite->callback = sub_81718D8; + } +} + +static void sub_81718D8(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; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + 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]++; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16 - sprite->data[2], 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) + { + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + sprite->data[0] = 0; + sprite->callback = sub_81719C0; + } + break; + } +} + +static void sub_81719C0(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + sprite->data[0] = -1; + } + else + { + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + } +} + +static void sub_81719EC(struct Sprite *sprite) +{ + u32 i; + u8 subpriority; + + if (sprite->subpriority) + { + subpriority = sprite->subpriority - 1; + } + else + { + subpriority = 0; + sprite->subpriority = 1; + } + + sub_8171D60(4); + for (i = 0; i < 3; i++) + { + u8 spriteId = CreateSprite(&gUnknown_085E51F0[4], sprite->pos1.x, sprite->pos1.y, subpriority); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].data[0] = 24; + gSprites[spriteId].data[2] = sprite->pos1.x + sBallCaptureSuccessStarData[i].xOffset; + gSprites[spriteId].data[4] = sprite->pos1.y + sBallCaptureSuccessStarData[i].yOffset; + gSprites[spriteId].data[5] = sBallCaptureSuccessStarData[i].unk2; + InitAnimArcTranslation(&gSprites[spriteId]); + gSprites[spriteId].callback = sub_8171AAC; + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[4]); + } + } +} + +static void sub_8171AAC(struct Sprite *sprite) +{ + sprite->invisible = !sprite->invisible; + if (TranslateAnimArc(sprite)) + DestroySprite(sprite); +} + +// fakematching. I think the return type of ItemIdToBallId() +// is wrong because of the weird required casting. +static void sub_8171AE4(struct Sprite *sprite) +{ + u8 ballId; + int ballId2; // extra var needed to match + + StartSpriteAnim(sprite, 1); + StartSpriteAffineAnim(sprite, 0); + sprite->callback = sub_8171BAC; + + ballId = ItemIdToBallId(gLastUsedItem); + ballId2 = ballId; + if (ballId2 > 11) + goto LABEL; + if (ballId2 < 0) + goto LABEL; + + AnimateBallOpenParticles(sprite->pos1.x, sprite->pos1.y - 5, 1, 28, ballId); + LaunchBallFadeMonTask(1, gBattleAnimTarget, 14, ballId); + + LABEL: + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].invisible = 0; + StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[gBattleAnimTarget]], 1); + AnimateSprite(&gSprites[gBattlerSpriteIds[gBattleAnimTarget]]); + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].data[1] = 0x1000; +} + +static void sub_8171BAC(struct Sprite *sprite) +{ + int next = FALSE; + + if (sprite->animEnded) + sprite->invisible = 1; + + if (gSprites[gBattlerSpriteIds[gBattleAnimTarget]].affineAnimEnded) + { + StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[gBattleAnimTarget]], 0); + next = TRUE; + } + else + { + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].data[1] -= 288; + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].pos2.y = gSprites[gBattlerSpriteIds[gBattleAnimTarget]].data[1] >> 8; + } + + if (sprite->animEnded && next) + { + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].pos2.y = 0; + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].invisible = gBattleSpritesDataPtr->animationData->field_9_x2; + sprite->data[0] = 0; + sprite->callback = sub_81719C0; + gDoingBattleAnim = 0; + UpdateOamPriorityInAllHealthboxes(1); + } +} + +static void sub_8171CAC(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_8171CE8; +} + +static void sub_8171CE8(struct Sprite *sprite) +{ + s16 var0 = sprite->data[0] + 0x800; + s16 var1 = sprite->data[1] + 0x680; + sprite->pos2.x -= var1 >> 8; + sprite->pos2.y += var0 >> 8; + sprite->data[0] = (sprite->data[0] + 0x800) & 0xFF; + sprite->data[1] = (sprite->data[1] + 0x680) & 0xFF; + + if (sprite->pos1.y + sprite->pos2.y > 160 + || sprite->pos1.x + sprite->pos2.x < -8) + { + sprite->data[0] = 0; + sprite->callback = sub_81719C0; + gDoingBattleAnim = 0; + UpdateOamPriorityInAllHealthboxes(1); + } +} + +static void sub_8171D60(u8 ballId) +{ + u8 taskId; + + if (GetSpriteTileStartByTag(gBallOpenParticleSpritesheets[ballId].tag) == 0xFFFF) + { + LoadCompressedObjectPicUsingHeap(&gBallOpenParticleSpritesheets[ballId]); + LoadCompressedObjectPaletteUsingHeap(&gBallOpenParticlePalettes[ballId]); + } +} + +u8 AnimateBallOpenParticles(u8 x, u8 y, u8 priority, u8 subpriority, u8 ballId) +{ + u8 taskId; + + sub_8171D60(ballId); + taskId = CreateTask(gBallOpenParticleAnimationFuncs[ballId], 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] = ballId; + PlaySE(SE_BOWA2); + + return taskId; +} + +void sub_8171E20(void) +{ + if (gMain.inBattle) + gBattleSpritesDataPtr->animationData->field_A++; +} + +static void PokeBallOpenParticleAnimation(u8 taskId) +{ + u8 spriteId; + u8 x, y; + u8 priority, subpriority; + u8 ballId; + u8 var0; + + ballId = 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(&gUnknown_085E51F0[ballId], x, y, subpriority); + if (spriteId != MAX_SPRITES) + { + sub_8171E20(); + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballId]); + 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) + { + if (!gMain.inBattle) + 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); +} + +static void TimerBallOpenParticleAnimation(u8 taskId) +{ + u8 i; + u8 x, y, priority, subpriority, ballId; + u8 spriteId; + + ballId = 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(&gUnknown_085E51F0[ballId], x, y, subpriority); + if (spriteId != MAX_SPRITES) + { + sub_8171E20(); + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballId]); + 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; + } + } + + if (!gMain.inBattle) + gSprites[spriteId].data[7] = 1; + + DestroyTask(taskId); +} + +static void DiveBallOpenParticleAnimation(u8 taskId) +{ + u8 i; + u8 x, y, priority, subpriority, ballId; + u8 spriteId; + + ballId = 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(&gUnknown_085E51F0[ballId], x, y, subpriority); + if (spriteId != MAX_SPRITES) + { + sub_8171E20(); + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballId]); + 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; + } + } + + if (!gMain.inBattle) + gSprites[spriteId].data[7] = 1; + + DestroyTask(taskId); +} + +// Also used for Net Ball +static void SafariBallOpenParticleAnimation(u8 taskId) +{ + u8 i; + u8 x, y, priority, subpriority, ballId; + u8 spriteId; + + ballId = 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(&gUnknown_085E51F0[ballId], x, y, subpriority); + if (spriteId != MAX_SPRITES) + { + sub_8171E20(); + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballId]); + 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; + } + } + + if (!gMain.inBattle) + gSprites[spriteId].data[7] = 1; + + DestroyTask(taskId); +} + +// Also used for Nest Ball +static void UltraBallOpenParticleAnimation(u8 taskId) +{ + u8 i; + u8 x, y, priority, subpriority, ballId; + u8 spriteId; + + ballId = 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(&gUnknown_085E51F0[ballId], x, y, subpriority); + if (spriteId != MAX_SPRITES) + { + sub_8171E20(); + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballId]); + 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; + } + } + + if (!gMain.inBattle) + gSprites[spriteId].data[7] = 1; + + DestroyTask(taskId); +} + +// Also used for Luxury Ball +static void GreatBallOpenParticleAnimation(u8 taskId) +{ + u8 i; + u8 x, y, priority, subpriority, ballId; + u8 spriteId; + + if (gTasks[taskId].data[7]) + { + gTasks[taskId].data[7]--; + } + else + { + ballId = 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(&gUnknown_085E51F0[ballId], x, y, subpriority); + if (spriteId != MAX_SPRITES) + { + sub_8171E20(); + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballId]); + 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) + { + if (!gMain.inBattle) + 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); +} + +static void RepeatBallOpenParticleAnimation(u8 taskId) +{ + u8 i; + u8 x, y, priority, subpriority, ballId; + u8 spriteId; + + ballId = 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(&gUnknown_085E51F0[ballId], x, y, subpriority); + if (spriteId != MAX_SPRITES) + { + sub_8171E20(); + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballId]); + gSprites[spriteId].callback = RepeatBallOpenParticleAnimation_Step1; + gSprites[spriteId].oam.priority = priority; + gSprites[spriteId].data[0] = i * 21; + } + } + + if (!gMain.inBattle) + 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); +} + +static void MasterBallOpenParticleAnimation(u8 taskId) +{ + u8 i, j; + u8 x, y, priority, subpriority, ballId; + u8 spriteId; + + ballId = 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(&gUnknown_085E51F0[ballId], x, y, subpriority); + if (spriteId != MAX_SPRITES) + { + sub_8171E20(); + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballId]); + 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; + } + } + } + } + + if (!gMain.inBattle) + gSprites[spriteId].data[7] = 1; + + DestroyTask(taskId); +} + +static void PremierBallOpenParticleAnimation(u8 taskId) +{ + u8 i; + u8 x, y, priority, subpriority, ballId; + u8 spriteId; + + ballId = 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(&gUnknown_085E51F0[ballId], x, y, subpriority); + if (spriteId != MAX_SPRITES) + { + sub_8171E20(); + StartSpriteAnim(&gSprites[spriteId], gBallOpenParticleAnimNums[ballId]); + gSprites[spriteId].callback = PremierBallOpenParticleAnimation_Step1; + gSprites[spriteId].oam.priority = priority; + gSprites[spriteId].data[0] = i * 32; + } + } + + if (!gMain.inBattle) + 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, j; + int temp; + + if (!gMain.inBattle) + { + temp = sprite->data[7]; // temp var needed to match + if (temp == 1) + DestroySpriteAndFreeResources(sprite); + else + DestroySprite(sprite); + } + else + { + gBattleSpritesDataPtr->animationData->field_A--; + if (gBattleSpritesDataPtr->animationData->field_A == 0) + { + for (i = 0; i < 12; i++) + { + if (FuncIsActiveTask(gBallOpenParticleAnimationFuncs[i]) == TRUE) + break; + } + + if (i == 12) + { + for (j = 0; j < 12; j++) + { + FreeSpriteTilesByTag(gBallOpenParticleSpritesheets[j].tag); + FreeSpritePaletteByTag(gBallOpenParticlePalettes[j].tag); + } + } + + DestroySprite(sprite); + } + else + { + DestroySprite(sprite); + } + } +} + +u8 LaunchBallFadeMonTask(u8 unfadeLater, u8 battler, u32 selectedPalettes, u8 ballId) +{ + u8 taskId; + + taskId = CreateTask(sub_8172AB0, 5); + gTasks[taskId].data[15] = ballId; + gTasks[taskId].data[3] = battler; + gTasks[taskId].data[10] = selectedPalettes; + gTasks[taskId].data[11] = selectedPalettes >> 16; + + if (!unfadeLater) + { + BlendPalette(battler * 16 + 0x100, 16, 0, gUnknown_085E5310[ballId]); + gTasks[taskId].data[1] = 1; + } + else + { + BlendPalette(battler * 16 + 0x100, 16, 16, gUnknown_085E5310[ballId]); + gTasks[taskId].data[0] = 16; + gTasks[taskId].data[1] = -1; + gTasks[taskId].func = sub_8172B40; + } + + BeginNormalPaletteFade(selectedPalettes, 0, 0, 16, RGB(31, 31, 31)); + return taskId; +} + +static void sub_8172AB0(u8 taskId) +{ + u8 ballId = gTasks[taskId].data[15]; + + if (gTasks[taskId].data[2] <= 16) + { + BlendPalette(gTasks[taskId].data[3] * 16 + 0x100, 16, gTasks[taskId].data[0], gUnknown_085E5310[ballId]); + 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_8172B40(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_8172B90; + } +} + +static void sub_8172B90(u8 taskId) +{ + u8 ballId = gTasks[taskId].data[15]; + + if (gTasks[taskId].data[2] <= 16) + { + BlendPalette(gTasks[taskId].data[3] * 16 + 0x100, 16, gTasks[taskId].data[0], gUnknown_085E5310[ballId]); + gTasks[taskId].data[0] += gTasks[taskId].data[1]; + gTasks[taskId].data[2]++; + } + else + { + DestroyTask(taskId); + } +} + +void sub_8172BF0(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].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: + LoadBattleMonGfxAndAnimate(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_8172D98(u8 taskId) +{ + u8 spriteId; + + switch (gTasks[taskId].data[15]) + { + case 0: + if (sub_80A8364(gBattleAnimAttacker) == B_POSITION_OPPONENT_LEFT) + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + else + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + gTasks[taskId].data[15]++; + break; + case 1: + if (gTasks[taskId].data[1]++ > 1) + { + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[0]++; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16 - gTasks[taskId].data[0], gTasks[taskId].data[0])); + if (gTasks[taskId].data[0] == 16) + gTasks[taskId].data[15]++; + } + break; + case 2: + spriteId = gBattlerSpriteIds[gBattleAnimAttacker]; + RequestDma3Fill(0, (void *)OBJ_VRAM0 + gSprites[spriteId].oam.tileNum * TILE_SIZE_4BPP, 0x800, 1); + ClearBehindSubstituteBit(gBattleAnimAttacker); + DestroyAnimVisualTask(taskId); + break; + } +} + +void sub_8172E9C(u8 taskId) +{ + gBattleAnimArgs[7] = gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].behindSubstitute; + DestroyAnimVisualTask(taskId); +} + +void sub_8172ED0(u8 taskId) +{ + gBattleAnimTarget = gEffectBattler; + DestroyAnimVisualTask(taskId); +} + +void sub_8172EF0(u8 battler, struct Pokemon *mon) +{ + int isShiny; + u32 otId, personality; + u32 shinyValue; + u8 taskId1, taskId2; + + isShiny = 0; + gBattleSpritesDataPtr->healthBoxesData[battler].flag_x80 = 1; + otId = GetMonData(mon, MON_DATA_OT_ID); + personality = GetMonData(mon, MON_DATA_PERSONALITY); + + if (IsBattlerSpriteVisible(battler)) + { + shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); + if (shinyValue < 8) + isShiny = TRUE; + + if (isShiny) + { + if (GetSpriteTileStartByTag(0x27F9) == 0xFFFF) + { + LoadCompressedObjectPicUsingHeap(&gBattleAnimPicTable[233]); + LoadCompressedObjectPaletteUsingHeap(&gBattleAnimPaletteTable[233]); + } + + taskId1 = CreateTask(sub_8172FEC, 10); + taskId2 = CreateTask(sub_8172FEC, 10); + gTasks[taskId1].data[0] = battler; + gTasks[taskId2].data[0] = battler; + gTasks[taskId1].data[1] = 0; + gTasks[taskId2].data[1] = 1; + return; + } + } + + gBattleSpritesDataPtr->healthBoxesData[battler].field_1_x1 = 1; +} + +static void sub_8172FEC(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 (gBattleSpritesDataPtr->animationData->field_A) + 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(&gUnknown_085CE388, x, y, 5); + } + else if (state >= 0 && gTasks[taskId].data[11] < 4) + { + spriteId = CreateSprite(&gUnknown_085CE3A0, x, y, 5); + gSprites[spriteId].oam.tileNum += 4; + } + else + { + spriteId = CreateSprite(&gUnknown_085CE3A0, x, y, 5); + gSprites[spriteId].oam.tileNum += 5; + } + + if (gTasks[taskId].data[1] == 0) + { + gSprites[spriteId].callback = sub_81731FC; + } + else + { + gSprites[spriteId].callback = sub_8173250; + 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]++; + if (spriteId != MAX_SPRITES) + gTasks[taskId].data[12]++; + + if (gTasks[taskId].data[11] == 5) + gTasks[taskId].func = sub_81731B0; +} + +static void sub_81731B0(u8 taskId) +{ + u8 battler; + + if (gTasks[taskId].data[12] == 0) + { + if (gTasks[taskId].data[1] == 1) + { + battler = gTasks[taskId].data[0]; + gBattleSpritesDataPtr->healthBoxesData[battler].field_1_x1 = 1; + } + + DestroyTask(taskId); + } +} + +static void sub_81731FC(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_8173250(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_81732B0(u8 taskId) +{ + u8 paletteIndex; + + LoadCompressedObjectPicUsingHeap(&gBattleAnimPicTable[269]); + LoadCompressedObjectPaletteUsingHeap(&gBattleAnimPaletteTable[269]); + paletteIndex = IndexOfSpritePaletteTag(0x281D); // unused + DestroyAnimVisualTask(taskId); +} + +void sub_81732E4(u8 taskId) +{ + FreeSpriteTilesByTag(0x281D); + FreeSpritePaletteByTag(0x281D); + DestroyAnimVisualTask(taskId); +} + +static void sub_817330C(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); + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].callback = sub_8039E84; + sprite->callback = sub_817339C; +} + +static void sub_817339C(struct Sprite *sprite) +{ + if (gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].animCmdIndex == 1) + sprite->callback = sub_81733D4; +} + +static void sub_81733D4(struct Sprite *sprite) +{ + if (TranslateAnimArc(sprite)) + { + sprite->data[0] = 0; + sprite->invisible = 1; + sprite->callback = sub_8173400; + } +} + +static void sub_8173400(struct Sprite *sprite) +{ + if (gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].animEnded) + { + if (++sprite->data[0] > 0) + { + StartSpriteAnim(&gSprites[gBattlerSpriteIds[gBattleAnimAttacker]], 0); + DestroyAnimSprite(sprite); + } + } +} + +void sub_817345C(u8 taskId) +{ + switch (gBattleAnimArgs[0]) + { + case 0: + gBattleAnimAttacker = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + gBattleAnimTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + break; + case 1: + gBattleAnimAttacker = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + gBattleAnimTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + break; + } + + DestroyAnimVisualTask(taskId); +} + +void AnimTask_GetTrappedMoveAnimId(u8 taskId) +{ + if (gBattleSpritesDataPtr->animationData->animArg == 83) + gBattleAnimArgs[0] = 1; + else if (gBattleSpritesDataPtr->animationData->animArg == 250) + gBattleAnimArgs[0] = 2; + else if (gBattleSpritesDataPtr->animationData->animArg == 128) + gBattleAnimArgs[0] = 3; + else if (gBattleSpritesDataPtr->animationData->animArg == 328) + gBattleAnimArgs[0] = 4; + else + gBattleAnimArgs[0] = 0; + + DestroyAnimVisualTask(taskId); +} + +void sub_817351C(u8 taskId) +{ + gBattleAnimAttacker = gBattleSpritesDataPtr->animationData->animArg; + gBattleAnimTarget = gBattleSpritesDataPtr->animationData->animArg >> 8; + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_anim_utility_funcs.c b/src/battle_anim_utility_funcs.c index c3d0fe90f..85ff692b3 100644 --- a/src/battle_anim_utility_funcs.c +++ b/src/battle_anim_utility_funcs.c @@ -40,10 +40,10 @@ static void sub_8117FD0(u8); const u16 gUnknown_08597418 = RGB(31, 31, 31); -// no clue what these are... -// possibly some register offsets -const u8 gUnknown_0859741A[] = {0x08, 0x0a, 0x0c, 0x0e}; -const u8 gUnknown_0859741E[] = {0x08, 0x0a, 0x0c, 0x0e}; +// These belong in battle_intro.c, but there putting them there causes 2 bytes of alignment padding +// between the two .rodata segments. Perhaps battle_intro.c actually belongs in this file, too. +const u8 gUnknown_0859741A[] = {REG_OFFSET_BG0CNT, REG_OFFSET_BG1CNT, REG_OFFSET_BG2CNT, REG_OFFSET_BG3CNT}; +const u8 gUnknown_0859741E[] = {REG_OFFSET_BG0CNT, REG_OFFSET_BG1CNT, REG_OFFSET_BG2CNT, REG_OFFSET_BG3CNT}; void sub_8116620(u8 taskId) { diff --git a/src/battle_intro.c b/src/battle_intro.c index 0ccc7e828..736e35a87 100644 --- a/src/battle_intro.c +++ b/src/battle_intro.c @@ -1,21 +1,728 @@ #include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_main.h" +#include "battle_setup.h" +#include "bg.h" +#include "gpu_regs.h" +#include "main.h" +#include "scanline_effect.h" #include "task.h" +#include "trig.h" +#include "constants/trainers.h" -extern void task_battle_intro_80BC47C(u8); -extern void task00_battle_intro_80BC6C8(u8); -extern void task_battle_intro_80BC47C(u8); -extern void task_battle_intro_anim(u8); - -const TaskFunc gUnknown_08597424[] = -{ - task_battle_intro_80BC47C, - task_battle_intro_80BC47C, - task00_battle_intro_80BC6C8, - task00_battle_intro_80BC6C8, - task00_battle_intro_80BC6C8, - task_battle_intro_80BC47C, - task_battle_intro_80BC47C, - task_battle_intro_80BC47C, - task_battle_intro_anim, - task_battle_intro_anim, +static EWRAM_DATA u16 sBgCnt = 0; + +extern const u8 gUnknown_0859741A[]; +extern const u8 gUnknown_0859741E[]; + +static void BattleIntroSlide1(u8); +static void BattleIntroSlide2(u8); +static void BattleIntroSlide3(u8); +static void BattleIntroSlideLink(u8); +static void BattleIntroSlidePartner(u8); + +static const TaskFunc sBattleIntroSlideFuncs[] = +{ + BattleIntroSlide1, // BATTLE_TERRAIN_GRASS + BattleIntroSlide1, // BATTLE_TERRAIN_LONG_GRASS + BattleIntroSlide2, // BATTLE_TERRAIN_SAND + BattleIntroSlide2, // BATTLE_TERRAIN_UNDERWATER + BattleIntroSlide2, // BATTLE_TERRAIN_WATER + BattleIntroSlide1, // BATTLE_TERRAIN_POND + BattleIntroSlide1, // BATTLE_TERRAIN_MOUNTAIN + BattleIntroSlide1, // BATTLE_TERRAIN_CAVE + BattleIntroSlide3, // BATTLE_TERRAIN_BUILDING + BattleIntroSlide3, // BATTLE_TERRAIN_PLAIN }; + +void SetAnimBgAttribute(u8 bgId, u8 attributeId, u8 value) +{ + if (bgId < 4) + { + sBgCnt = GetGpuReg(gUnknown_0859741A[bgId]); + switch (attributeId) + { + case BG_ANIM_SCREEN_SIZE: + ((struct BgCnt *)&sBgCnt)->screenSize = value; + break; + case BG_ANIM_AREA_OVERFLOW_MODE: + ((struct BgCnt *)&sBgCnt)->areaOverflowMode = value; + break; + case BG_ANIM_MOSAIC: + ((struct BgCnt *)&sBgCnt)->mosaic = value; + break; + case BG_ANIM_CHAR_BASE_BLOCK: + ((struct BgCnt *)&sBgCnt)->charBaseBlock = value; + break; + case BG_ANIM_PRIORITY: + ((struct BgCnt *)&sBgCnt)->priority = value; + break; + case BG_ANIM_PALETTES_MODE: + ((struct BgCnt *)&sBgCnt)->palettes = value; + break; + case BG_ANIM_SCREEN_BASE_BLOCK: + ((struct BgCnt *)&sBgCnt)->screenBaseBlock = value; + break; + } + + SetGpuReg(gUnknown_0859741A[bgId], sBgCnt); + } +} + +int GetAnimBgAttribute(u8 bgId, u8 attributeId) +{ + u16 bgCnt; + + if (bgId < 4) + { + bgCnt = GetGpuReg(gUnknown_0859741E[bgId]); + switch (attributeId) + { + case BG_ANIM_SCREEN_SIZE: + return ((struct BgCnt *)&bgCnt)->screenSize; + case BG_ANIM_AREA_OVERFLOW_MODE: + return ((struct BgCnt *)&bgCnt)->areaOverflowMode; + case BG_ANIM_MOSAIC: + return ((struct BgCnt *)&bgCnt)->mosaic; + case BG_ANIM_CHAR_BASE_BLOCK: + return ((struct BgCnt *)&bgCnt)->charBaseBlock; + case BG_ANIM_PRIORITY: + return ((struct BgCnt *)&bgCnt)->priority; + case BG_ANIM_PALETTES_MODE: + return ((struct BgCnt *)&bgCnt)->palettes; + case BG_ANIM_SCREEN_BASE_BLOCK: + return ((struct BgCnt *)&bgCnt)->screenBaseBlock; + } + } + + return 0; +} + +void HandleIntroSlide(u8 terrain) +{ + u8 taskId; + + if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) && gPartnerTrainerId != TRAINER_STEVEN_PARTNER) + { + taskId = CreateTask(BattleIntroSlidePartner, 0); + } + else if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + taskId = CreateTask(BattleIntroSlideLink, 0); + } + else if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) + { + taskId = CreateTask(BattleIntroSlide3, 0); + } + else if ((gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON) && gGameVersion != VERSION_RUBY) + { + terrain = BATTLE_TERRAIN_UNDERWATER; + taskId = CreateTask(BattleIntroSlide2, 0); + } + else + { + taskId = CreateTask(sBattleIntroSlideFuncs[terrain], 0); + } + + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = terrain; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[4] = 0; + gTasks[taskId].data[5] = 0; + gTasks[taskId].data[6] = 0; +} + +void sub_811828C(u8 taskId) +{ + DestroyTask(taskId); + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + gBattle_BG2_X = 0; + gBattle_BG2_Y = 0; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR); +} + +static void BattleIntroSlide1(u8 taskId) +{ + int i; + + gBattle_BG1_X += 6; + switch (gTasks[taskId].data[0]) + { + case 0: + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gTasks[taskId].data[2] = 16; + gTasks[taskId].data[0]++; + } + else + { + gTasks[taskId].data[2] = 1; + gTasks[taskId].data[0]++; + } + break; + case 1: + if (--gTasks[taskId].data[2] == 0) + { + gTasks[taskId].data[0]++; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); + } + break; + case 2: + gBattle_WIN0V -= 0xFF; + if ((gBattle_WIN0V & 0xFF00) == 0x3000) + { + gTasks[taskId].data[0]++; + gTasks[taskId].data[2] = 240; + gTasks[taskId].data[3] = 32; + gIntroSlideFlags &= ~1; + } + break; + case 3: + if (gTasks[taskId].data[3]) + { + gTasks[taskId].data[3]--; + } + else + { + if (gTasks[taskId].data[1] == 1) + { + if (gBattle_BG1_Y != 0xFFB0) + gBattle_BG1_Y -= 2; + } + else + { + if (gBattle_BG1_Y != 0xFFC8) + gBattle_BG1_Y -= 1; + } + } + + if (gBattle_WIN0V & 0xFF00) + gBattle_WIN0V -= 0x3FC; + + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2] -= 2; + + // Scanline settings have already been set in CB2_InitBattleInternal() + for (i = 0; i < 80; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gTasks[taskId].data[2]; + + for (; i < 160; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = -gTasks[taskId].data[2]; + + if (!gTasks[taskId].data[2]) + { + gScanlineEffect.state = 3; + gTasks[taskId].data[0]++; + CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE); + SetBgAttribute(1, BG_CTRL_ATTR_VISIBLE, 0); + SetBgAttribute(2, BG_CTRL_ATTR_VISIBLE, 0); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + } + break; + case 4: + sub_811828C(taskId); + break; + } +} + +static void BattleIntroSlide2(u8 taskId) +{ + int i; + + switch (gTasks[taskId].data[1]) + { + case 2: + case 4: + gBattle_BG1_X += 8; + break; + case 3: + gBattle_BG1_X += 6; + break; + } + + if (gTasks[taskId].data[1] == 4) + { + gBattle_BG1_Y = Cos2(gTasks[taskId].data[6]) / 512 - 8; + if (gTasks[taskId].data[6] < 180) + gTasks[taskId].data[6] += 4; + else + gTasks[taskId].data[6] += 6; + + if (gTasks[taskId].data[6] == 360) + gTasks[taskId].data[6] = 0; + } + + switch (gTasks[taskId].data[0]) + { + case 0: + gTasks[taskId].data[4] = 16; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gTasks[taskId].data[2] = 16; + gTasks[taskId].data[0]++; + } + else + { + gTasks[taskId].data[2] = 1; + gTasks[taskId].data[0]++; + } + break; + case 1: + if (--gTasks[taskId].data[2] == 0) + { + gTasks[taskId].data[0]++; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); + } + break; + case 2: + gBattle_WIN0V -= 0xFF; + if ((gBattle_WIN0V & 0xFF00) == 0x3000) + { + gTasks[taskId].data[0]++; + gTasks[taskId].data[2] = 240; + gTasks[taskId].data[3] = 32; + gTasks[taskId].data[5] = 1; + gIntroSlideFlags &= ~1; + } + break; + case 3: + if (gTasks[taskId].data[3]) + { + if (--gTasks[taskId].data[3] == 0) + { + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(15, 0)); + SetGpuReg(REG_OFFSET_BLDY, 0); + } + } + else + { + if ((gTasks[taskId].data[4] & 0x1F) && --gTasks[taskId].data[5] == 0) + { + gTasks[taskId].data[4] += 0xFF; + gTasks[taskId].data[5] = 4; + } + } + + if (gBattle_WIN0V & 0xFF00) + gBattle_WIN0V -= 0x3FC; + + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2] -= 2; + + // Scanline settings have already been set in CB2_InitBattleInternal() + for (i = 0; i < 80; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gTasks[taskId].data[2]; + + for (; i < 160; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = -gTasks[taskId].data[2]; + + if (!gTasks[taskId].data[2]) + { + gScanlineEffect.state = 3; + gTasks[taskId].data[0]++; + CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE); + SetBgAttribute(1, BG_CTRL_ATTR_VISIBLE, 0); + SetBgAttribute(2, BG_CTRL_ATTR_VISIBLE, 0); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + } + break; + case 4: + sub_811828C(taskId); + break; + } + + if (gTasks[taskId].data[0] != 4) + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[4], 0)); +} + +static void BattleIntroSlide3(u8 taskId) +{ + int i; + + gBattle_BG1_X += 8; + switch (gTasks[taskId].data[0]) + { + case 0: + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(8, 8)); + SetGpuReg(REG_OFFSET_BLDY, 0); + gTasks[taskId].data[4] = BLDALPHA_BLEND(8, 8); + if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)) + { + gTasks[taskId].data[2] = 16; + gTasks[taskId].data[0]++; + } + else + { + gTasks[taskId].data[2] = 1; + gTasks[taskId].data[0]++; + } + break; + case 1: + if (--gTasks[taskId].data[2] == 0) + { + gTasks[taskId].data[0]++; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); + } + break; + case 2: + gBattle_WIN0V -= 0xFF; + if ((gBattle_WIN0V & 0xFF00) == 0x3000) + { + gTasks[taskId].data[0]++; + gTasks[taskId].data[2] = 240; + gTasks[taskId].data[3] = 32; + gTasks[taskId].data[5] = 1; + gIntroSlideFlags &= ~1; + } + break; + case 3: + if (gTasks[taskId].data[3]) + { + gTasks[taskId].data[3]--; + } + else + { + if ((gTasks[taskId].data[4] & 0xF) && --gTasks[taskId].data[5] == 0) + { + gTasks[taskId].data[4] += 0xFF; + gTasks[taskId].data[5] = 6; + } + } + + if (gBattle_WIN0V & 0xFF00) + gBattle_WIN0V -= 0x3FC; + + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2] -= 2; + + // Scanline settings have already been set in CB2_InitBattleInternal() + for (i = 0; i < 80; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gTasks[taskId].data[2]; + + for (; i < 160; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = -gTasks[taskId].data[2]; + + if (!gTasks[taskId].data[2]) + { + gScanlineEffect.state = 3; + gTasks[taskId].data[0]++; + CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE); + SetBgAttribute(1, BG_CTRL_ATTR_VISIBLE, 0); + SetBgAttribute(2, BG_CTRL_ATTR_VISIBLE, 0); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + } + break; + case 4: + sub_811828C(taskId); + break; + } + + if (gTasks[taskId].data[0] != 4) + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[4], 0)); +} + +static void BattleIntroSlideLink(u8 taskId) +{ + int i; + + if (gTasks[taskId].data[0] > 1 && !gTasks[taskId].data[4]) + { + u16 var0 = gBattle_BG1_X & 0x8000; + if (var0 || gBattle_BG1_X < 80) + { + gBattle_BG1_X += 3; + gBattle_BG2_X -= 3; + } + else + { + CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE); + CpuFill32(0, (void *)BG_SCREEN_ADDR(30), BG_SCREEN_SIZE); + gTasks[taskId].data[4] = 1; + } + } + + switch (gTasks[taskId].data[0]) + { + case 0: + gTasks[taskId].data[2] = 32; + gTasks[taskId].data[0]++; + break; + case 1: + if (--gTasks[taskId].data[2] == 0) + { + gTasks[taskId].data[0]++; + gSprites[gBattleStruct->field_7D].oam.objMode = ST_OAM_OBJ_WINDOW; + gSprites[gBattleStruct->field_7D].callback = sub_8038B74; + gSprites[gBattleStruct->field_7E].oam.objMode = ST_OAM_OBJ_WINDOW; + gSprites[gBattleStruct->field_7E].callback = sub_8038B74; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG1 | WINOUT_WIN01_BG2); + } + break; + case 2: + gBattle_WIN0V -= 0xFF; + if ((gBattle_WIN0V & 0xFF00) == 0x3000) + { + gTasks[taskId].data[0]++; + gTasks[taskId].data[2] = 240; + gTasks[taskId].data[3] = 32; + gIntroSlideFlags &= ~1; + } + break; + case 3: + if (gBattle_WIN0V & 0xFF00) + gBattle_WIN0V -= 0x3FC; + + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2] -= 2; + + // Scanline settings have already been set in CB2_InitBattleInternal() + for (i = 0; i < 80; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gTasks[taskId].data[2]; + + for (; i < 160; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = -gTasks[taskId].data[2]; + + if (!gTasks[taskId].data[2]) + { + gScanlineEffect.state = 3; + gTasks[taskId].data[0]++; + SetBgAttribute(1, BG_CTRL_ATTR_VISIBLE, 0); + SetBgAttribute(2, BG_CTRL_ATTR_VISIBLE, 0); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + } + break; + case 4: + sub_811828C(taskId); + break; + } +} + +static void BattleIntroSlidePartner(u8 taskId) +{ + switch (gTasks[taskId].data[0]) + { + case 0: + gTasks[taskId].data[2] = 1; + gTasks[taskId].data[0]++; + break; + case 1: + if (--gTasks[taskId].data[2] == 0) + { + gTasks[taskId].data[0]++; + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(2) | BGCNT_CHARBASE(2) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT512x256); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(2) | BGCNT_CHARBASE(2) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + SetGpuReg(REG_OFFSET_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) | DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_WIN1_ON | DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_WININ, WININ_WIN1_BG1 | WININ_WIN1_BG2 | WININ_WIN1_BG3 | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR); + gBattle_BG0_Y = -48; + gBattle_BG1_X = 240; + gBattle_BG2_X = -240; + } + break; + case 2: + gBattle_WIN0V += 0x100; + if ((gBattle_WIN0V & 0xFF00) != 0x100) + gBattle_WIN0V--; + + if ((gBattle_WIN0V & 0xFF00) == 0x2000) + { + gTasks[taskId].data[0]++; + gTasks[taskId].data[2] = 240; + gIntroSlideFlags &= ~1; + } + break; + case 3: + if ((gBattle_WIN0V & 0xFF00) != 0x4C00) + gBattle_WIN0V += 0x3FC; + + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2] -= 2; + + gBattle_BG1_X = gTasks[taskId].data[2]; + gBattle_BG2_X = -gTasks[taskId].data[2]; + if (!gTasks[taskId].data[2]) + gTasks[taskId].data[0]++; + break; + case 4: + gBattle_BG0_Y += 2; + gBattle_BG2_Y += 2; + if ((gBattle_WIN0V & 0xFF00) != 0x5000) + gBattle_WIN0V += 0xFF; + + if (!gBattle_BG0_Y) + { + CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE * 4); + SetGpuReg(REG_OFFSET_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) & ~DISPCNT_WIN1_ON); + SetBgAttribute(1, BG_CTRL_ATTR_VISIBLE, 0); + SetBgAttribute(2, BG_CTRL_ATTR_VISIBLE, 0); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + gScanlineEffect.state = 3; + gTasks[taskId].data[0]++; + } + break; + case 5: + sub_811828C(taskId); + break; + } +} + +void sub_8118FBC(int bgId, u8 arg1, u8 arg2, u8 battlerPosition, u8 arg4, u8 *arg5, u16 *arg6, u16 tilesOffset) +{ + int i, j; + u8 battler = GetBattlerAtPosition(battlerPosition); + int offset = tilesOffset; + CpuCopy16(gMonSpritesGfxPtr->sprites[battlerPosition] + BG_SCREEN_SIZE * gBattleMonForms[battler], arg5, BG_SCREEN_SIZE); + LoadBgTiles(bgId, arg5, 0x1000, tilesOffset); + for (i = arg2; i < arg2 + 8; i++) + { + for (j = arg1; j < arg1 + 8; j++) + { + arg6[i * 32 + j] = offset | (arg4 << 12); + offset++; + } + } + + LoadBgTilemap(bgId, arg6, BG_SCREEN_SIZE, 0); +} + +#ifdef NONMATCHING +void unref_sub_8119094(u8 arg0, u8 arg1, u8 battlerPosition, u8 arg3, u8 arg4, u16 arg5, u8 arg6, u8 arg7) +{ + int i, j; + int offset; + DmaCopy16(3, gMonSpritesGfxPtr->sprites[battlerPosition] + BG_SCREEN_SIZE * arg3, (void *)BG_SCREEN_ADDR(0) + arg5, BG_SCREEN_SIZE); + offset = (arg5 >> 5) - (arg7 << 9); + for (i = arg1; i < arg1 + 8; i++) + { + for (j = arg0; j < arg0 + 8; j++) + { + ((u16 *)BG_VRAM)[i * 32 + j + (arg6 * 0x400) + arg0] = offset | (arg4 << 12); + offset++; + } + } +} +#else +NAKED +void unref_sub_8119094(u8 arg0, u8 arg1, u8 battlerPosition, u8 arg3, u8 arg4, u16 arg5, u8 arg6, u8 arg7) +{ + asm_unified("\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x4\n\ + ldr r4, [sp, 0x24]\n\ + ldr r5, [sp, 0x28]\n\ + mov r8, r5\n\ + ldr r5, [sp, 0x2C]\n\ + ldr r6, [sp, 0x30]\n\ + mov r9, r6\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r12, r0\n\ + lsls r1, 24\n\ + lsls r2, 24\n\ + lsls r3, 24\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + mov r10, r4\n\ + mov r7, r8\n\ + lsls r7, 16\n\ + lsrs r6, r7, 16\n\ + lsls r5, 24\n\ + lsrs r5, 24\n\ + mov r0, r9\n\ + lsls r0, 24\n\ + mov r9, r0\n\ + ldr r4, =0x040000d4\n\ + ldr r0, =gMonSpritesGfxPtr\n\ + ldr r0, [r0]\n\ + lsrs r2, 22\n\ + adds r0, 0x4\n\ + adds r0, r2\n\ + lsrs r3, 13\n\ + ldr r0, [r0]\n\ + adds r0, r3\n\ + str r0, [r4]\n\ + movs r0, 0xC0\n\ + lsls r0, 19\n\ + adds r6, r0\n\ + str r6, [r4, 0x4]\n\ + ldr r0, =0x80000400\n\ + str r0, [r4, 0x8]\n\ + ldr r0, [r4, 0x8]\n\ + adds r2, r7, 0\n\ + lsrs r2, 21\n\ + mov r6, r9\n\ + lsrs r6, 15\n\ + subs r4, r2, r6\n\ + lsrs r0, r1, 24\n\ + adds r1, r0, 0\n\ + adds r1, 0x8\n\ + cmp r0, r1\n\ + bge _08119148\n\ + mov r9, r1\n\ + mov r7, r12\n\ + lsls r7, 1\n\ + mov r8, r7\n\ + lsls r5, 11\n\ + str r5, [sp]\n\ +_08119110:\n\ + mov r2, r12\n\ + adds r3, r2, 0\n\ + adds r3, 0x8\n\ + adds r5, r0, 0x1\n\ + cmp r2, r3\n\ + bge _08119142\n\ + mov r1, r10\n\ + lsls r6, r1, 12\n\ + lsls r0, 6\n\ + movs r7, 0xC0\n\ + lsls r7, 19\n\ + adds r0, r7\n\ + ldr r1, [sp]\n\ + adds r0, r1, r0\n\ + mov r7, r8\n\ + adds r1, r7, r0\n\ + subs r2, r3, r2\n\ +_08119132:\n\ + adds r0, r4, 0\n\ + orrs r0, r6\n\ + strh r0, [r1]\n\ + adds r4, 0x1\n\ + adds r1, 0x2\n\ + subs r2, 0x1\n\ + cmp r2, 0\n\ + bne _08119132\n\ +_08119142:\n\ + adds r0, r5, 0\n\ + cmp r0, r9\n\ + blt _08119110\n\ +_08119148:\n\ + add sp, 0x4\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool"); +} +#endif diff --git a/src/battle_main.c b/src/battle_main.c index 9b7f58023..fb2e5105a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -81,7 +81,7 @@ extern const u8 *const gBattlescriptsForBallThrow[]; extern const u8 *const gBattlescriptsForRunningByItem[]; extern const u8 *const gBattlescriptsForUsingItem[]; extern const u8 *const gBattlescriptsForSafariActions[]; -extern const struct ScanlineEffectParams gUnknown_0831AC70; +extern const struct ScanlineEffectParams gBattleIntroSlideScanlineEffectParams; // strings extern const u8 gText_LinkStandby3[]; @@ -633,7 +633,7 @@ static void CB2_InitBattleInternal(void) gScanlineEffectRegBuffers[1][i] = 0xFF10; } - ScanlineEffect_SetParams(gUnknown_0831AC70); + ScanlineEffect_SetParams(gBattleIntroSlideScanlineEffectParams); } ResetPaletteFade(); diff --git a/src/easy_chat.c b/src/easy_chat.c index 25ef069e4..c4bc02e42 100644 --- a/src/easy_chat.c +++ b/src/easy_chat.c @@ -51,6 +51,9 @@ EWRAM_DATA struct u16 ecWordBuffer[9]; } *gUnknown_0203A118 = NULL; +EWRAM_DATA void *gUnknown_0203A11C = 0; +EWRAM_DATA void *gUnknown_0203A120 = 0; + // Static ROM declarations static void sub_811A2C0(u8); diff --git a/src/pokeball.c b/src/pokeball.c index ad839e6af..82d2f2cea 100644 --- a/src/pokeball.c +++ b/src/pokeball.c @@ -426,7 +426,7 @@ static void SpriteCB_TestBallThrow(struct Sprite *sprite) sprite->pos2.y = 0; sprite->data[5] = 0; ballId = ItemIdToBallId(GetBattlerPokeballItemId(opponentBattler)); - LaunchBallStarsTask(sprite->pos1.x, sprite->pos1.y - 5, 1, 0x1C, ballId); + AnimateBallOpenParticles(sprite->pos1.x, sprite->pos1.y - 5, 1, 0x1C, ballId); sprite->data[0] = LaunchBallFadeMonTask(FALSE, opponentBattler, 14, ballId); sprite->sBattler = opponentBattler; sprite->data[7] = noOfShakes; @@ -737,7 +737,7 @@ static void SpriteCB_ReleaseMonFromBall(struct Sprite *sprite) StartSpriteAnim(sprite, 1); ballId = ItemIdToBallId(GetBattlerPokeballItemId(battlerId)); - LaunchBallStarsTask(sprite->pos1.x, sprite->pos1.y - 5, 1, 0x1C, ballId); + AnimateBallOpenParticles(sprite->pos1.x, sprite->pos1.y - 5, 1, 0x1C, ballId); sprite->data[0] = LaunchBallFadeMonTask(1, sprite->sBattler, 14, ballId); sprite->callback = HandleBallAnimEnd; @@ -985,9 +985,9 @@ static void SpriteCB_OpponentMonSendOut(struct Sprite *sprite) #undef sBattler -static u8 LaunchBallStarsTaskForPokeball(u8 x, u8 y, u8 kindOfStars, u8 d) +static u8 AnimateBallOpenParticlesForPokeball(u8 x, u8 y, u8 kindOfStars, u8 d) { - return LaunchBallStarsTask(x, y, kindOfStars, d, BALL_POKE); + return AnimateBallOpenParticles(x, y, kindOfStars, d, BALL_POKE); } static u8 LaunchBallFadeMonTaskForPokeball(bool8 unFadeLater, u8 battlerId, u32 arg2) @@ -1036,7 +1036,7 @@ static void sub_8076524(struct Sprite *sprite) r5 = 0; StartSpriteAnim(sprite, 1); - LaunchBallStarsTaskForPokeball(sprite->pos1.x, sprite->pos1.y - 5, sprite->oam.priority, r5); + AnimateBallOpenParticlesForPokeball(sprite->pos1.x, sprite->pos1.y - 5, sprite->oam.priority, r5); sprite->data[1] = LaunchBallFadeMonTaskForPokeball(1, battlerId, r4); sprite->callback = sub_80765E0; gSprites[r7].invisible = FALSE; @@ -1129,7 +1129,7 @@ static void sub_80767D4(struct Sprite *sprite) r6 = 0; StartSpriteAnim(sprite, 1); - LaunchBallStarsTaskForPokeball(sprite->pos1.x, sprite->pos1.y - 5, sprite->oam.priority, r6); + AnimateBallOpenParticlesForPokeball(sprite->pos1.x, sprite->pos1.y - 5, sprite->oam.priority, r6); sprite->data[1] = LaunchBallFadeMonTaskForPokeball(1, r8, r5); sprite->callback = sub_807687C; StartSpriteAffineAnim(&gSprites[r7], 2); diff --git a/src/pokemon.c b/src/pokemon.c index 46fe7b0d0..de3eaba75 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -45,12 +45,6 @@ struct SpeciesItem u16 item; }; -// Extracts the upper 16 bits of a 32-bit number -#define HIHALF(n) (((n) & 0xFFFF0000) >> 16) - -// Extracts the lower 16 bits of a 32-bit number -#define LOHALF(n) ((n) & 0xFFFF) - extern const struct OamData gUnknown_0831ACB0; extern const struct OamData gUnknown_0831ACA8; extern const struct SpriteFrameImage gUnknown_082FF3A8[]; @@ -6707,12 +6701,6 @@ const u32 *GetMonFrontSpritePal(struct Pokemon *mon) return GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality); } -// Extracts the upper 16 bits of a 32-bit number -#define HIHALF(n) (((n) & 0xFFFF0000) >> 16) - -// Extracts the lower 16 bits of a 32-bit number -#define LOHALF(n) ((n) & 0xFFFF) - const u32 *GetFrontSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality) { u32 shinyValue; |