diff --git a/graphics/link_games/321start_2.png b/graphics/link_games/321start_static.png similarity index 100% rename from graphics/link_games/321start_2.png rename to graphics/link_games/321start_static.png diff --git a/include/link.h b/include/link.h index 086bf787b..34710597f 100644 --- a/include/link.h +++ b/include/link.h @@ -62,7 +62,7 @@ #define LINKCMD_0x6666 0x6666 #define LINKCMD_0x7777 0x7777 #define LINKCMD_BLENDER_PLAY_AGAIN 0x7779 -#define LINKCMD_0x7FFF 0x7FFF +#define LINKCMD_COUNTDOWN 0x7FFF #define LINKCMD_CONT_BLOCK 0x8888 #define LINKCMD_BLENDER_NO_BERRIES 0x9999 #define LINKCMD_BLENDER_NO_PBLOCK_SPACE 0xAAAA diff --git a/src/berry_crush.c b/src/berry_crush.c index 9732e1205..4aaa95e26 100755 --- a/src/berry_crush.c +++ b/src/berry_crush.c @@ -38,6 +38,8 @@ #include "constants/rgb.h" #include "constants/songs.h" +#define TAG_COUNTDOWN 0x1000 + struct BerryCrushGame_Player { u8 unk0[PLAYER_NAME_LENGTH + 1 + 4]; @@ -2295,7 +2297,7 @@ static u32 sub_80232EC(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r case 1: if (!IsLinkTaskFinished()) return 0; - StartMinigameCountdown(0x1000, 0x1000, 120, 80, 0); + StartMinigameCountdown(TAG_COUNTDOWN, TAG_COUNTDOWN, 120, 80, 0); break; case 2: if (IsMinigameCountdownRunning()) diff --git a/src/dodrio_berry_picking.c b/src/dodrio_berry_picking.c index fb6f1a421..d3244f4b9 100644 --- a/src/dodrio_berry_picking.c +++ b/src/dodrio_berry_picking.c @@ -145,16 +145,18 @@ enum { // the values 0-9 are unique 'valid' columns #define NUM_BERRY_COLUMNS 11 -#define GFXTAG_DODRIO 0 -#define GFXTAG_STATUS 1 -#define GFXTAG_BERRIES 2 -#define GFXTAG_CLOUD 5 +#define GFXTAG_DODRIO 0 +#define GFXTAG_STATUS 1 +#define GFXTAG_BERRIES 2 +#define GFXTAG_CLOUD 5 +#define GFXTAG_COUNTDOWN 7 #define PALTAG_DODRIO_NORMAL 0 #define PALTAG_DODRIO_SHINY 1 #define PALTAG_STATUS 2 #define PALTAG_BERRIES 3 #define PALTAG_CLOUD 6 +#define PALTAG_COUNTDOWN 8 #define NUM_CLOUDS 2 @@ -871,7 +873,7 @@ static void DoCountdown(void) switch (sGame->state) { case 0: - StartMinigameCountdown(7, 8, 120, 80, 0); + StartMinigameCountdown(GFXTAG_COUNTDOWN, PALTAG_COUNTDOWN, 120, 80, 0); sGame->state++; break; case 1: diff --git a/src/minigame_countdown.c b/src/minigame_countdown.c index 01fb05fd8..f7dad4800 100644 --- a/src/minigame_countdown.c +++ b/src/minigame_countdown.c @@ -5,15 +5,366 @@ #include "sound.h" #include "task.h" #include "trig.h" +#include "minigame_countdown.h" #include "constants/songs.h" +/* + This file contains two types of '3-2-1 Start' countdowns intended for use by the wireless minigames. + + One is static, where the numbers simply appear and disappear without moving. This version is unused. + The other (used) version has the numbers squish and bounce up as they appear. +*/ + +#define TAG_STATIC_COUNTDOWN 0x2000 + +enum { + STATE_IDLE = 1, + STATE_START, + STATE_RUN, + STATE_END, +}; + +enum { + FUNC_INIT, + FUNC_FREE, + FUNC_START, + FUNC_RUN, +}; + +enum { + ANIM_THREE, + ANIM_TWO, + ANIM_ONE, + ANIM_START_LEFT, + ANIM_START_MID, + ANIM_START_RIGHT, +}; + extern const struct OamData gOamData_AffineOff_ObjNormal_32x32; -static void sub_802E6D0(u8 taskId); -static void sub_802E83C(u8 taskId); -static void sub_802E8C8(u8 taskId); -static void sub_802EA50(u8 taskId); -static void sub_802EAB0(u8 taskId); +static void Task_StaticCountdown(u8 taskId); +static void Task_StaticCountdown_Init(u8 taskId); +static void Task_StaticCountdown_Free(u8 taskId); +static void Task_StaticCountdown_Start(u8 taskId); +static void Task_StaticCountdown_Run(u8 taskId); + +static const u16 s321Start_Static_Pal[] = INCBIN_U16("graphics/link_games/321start_static.gbapal"); +static const u32 s321Start_Static_Gfx[] = INCBIN_U32("graphics/link_games/321start_static.4bpp.lz"); + +static const struct CompressedSpriteSheet sSpriteSheet_321Start_Static[] = +{ + {s321Start_Static_Gfx, 0xC00, TAG_STATIC_COUNTDOWN}, + {}, +}; + +static const struct SpritePalette sSpritePalette_321Start_Static[] = +{ + {s321Start_Static_Pal, TAG_STATIC_COUNTDOWN}, + {}, +}; + +static const union AnimCmd sAnim_StaticCountdown_Three[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END +}; + +static const union AnimCmd sAnim_StaticCountdown_Two[] = +{ + ANIMCMD_FRAME(16, 0), + ANIMCMD_END +}; + +static const union AnimCmd sAnim_StaticCountdown_One[] = +{ + ANIMCMD_FRAME(32, 0), + ANIMCMD_END +}; + +static const union AnimCmd sAnim_StaticCountdown_StartLeft[] = +{ + ANIMCMD_FRAME(64, 0), + ANIMCMD_END +}; + +static const union AnimCmd sAnim_StaticCountdown_StartMid[] = +{ + ANIMCMD_FRAME(48, 0), + ANIMCMD_END +}; + +static const union AnimCmd sAnim_StaticCountdown_StartRight[] = +{ + ANIMCMD_FRAME(80, 0), + ANIMCMD_END +}; + +static const union AnimCmd *const sAnims_StaticCountdown[] = +{ + [ANIM_THREE] = sAnim_StaticCountdown_Three, + [ANIM_TWO] = sAnim_StaticCountdown_Two, + [ANIM_ONE] = sAnim_StaticCountdown_One, + [ANIM_START_LEFT] = sAnim_StaticCountdown_StartLeft, + [ANIM_START_MID] = sAnim_StaticCountdown_StartMid, + [ANIM_START_RIGHT] = sAnim_StaticCountdown_StartRight +}; + +static const struct SpriteTemplate sSpriteTemplate_StaticCountdown[] = +{ + { + .tileTag = TAG_STATIC_COUNTDOWN, + .paletteTag = TAG_STATIC_COUNTDOWN, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_StaticCountdown, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, +}; + +static const TaskFunc sStaticCountdownFuncs[][4] = +{ + { + [FUNC_INIT] = Task_StaticCountdown_Init, + [FUNC_FREE] = Task_StaticCountdown_Free, + [FUNC_START] = Task_StaticCountdown_Start, + [FUNC_RUN] = Task_StaticCountdown_Run + }, +}; + +#define tState data[0] +#define tFuncSetId data[1] // These 4 data elements are indexes into +#define tSpriteTemplateId data[2] // arrays that only have 1 element with +#define tSpriteSheetId data[3] // data. As such their only legal value +#define tSpritePalId data[4] // is 0. Unclear why they were used. +#define tInterval data[5] +#define tPriority data[6] +#define tSubpriority data[7] +#define tNumSprites data[8] +#define tX data[9] +#define tY data[10] +#define tPrevTime data[10] // Re-used +#define tTimer data[11] +#define tLinkTimer data[12] +// 13-15 hold sprite ids +// tSpriteIds(0) is used for the number sprites, and the leftmost part of 'Start' +// tSpriteIds(1) is used for the middle part of 'Start' +// tSpriteIds(2) is used for for the rightmost part of 'Start' +#define tSpriteIds(i) data[13 + i] + +#define sInterval data[1] // Never read +#define sAnimNum data[2] +#define sTaskId data[3] +#define sId data[4] // Never read +#define sNumberSpriteId data[5] // Never read + +// Unused +static u32 CreateStaticCountdownTask(u8 funcSetId, u8 taskPriority) +{ + u8 taskId = CreateTask(Task_StaticCountdown, taskPriority); + struct Task *task = &gTasks[taskId]; + + task->tState = STATE_IDLE; + task->tFuncSetId = funcSetId; + sStaticCountdownFuncs[funcSetId][FUNC_INIT](taskId); + return taskId; +} + +static bool32 StartStaticCountdown(void) +{ + u8 taskId = FindTaskIdByFunc(Task_StaticCountdown); + if (taskId == TASK_NONE) + return FALSE; + + gTasks[taskId].tState = STATE_START; + return TRUE; +} + +static bool32 IsStaticCountdownRunning(void) +{ + return FuncIsActiveTask(Task_StaticCountdown); +} + +static void Task_StaticCountdown(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (tState) + { + // STATE_IDLE does nothing; wait until started + case STATE_START: + sStaticCountdownFuncs[tFuncSetId][FUNC_START](taskId); + tState = STATE_RUN; + break; + case STATE_RUN: + sStaticCountdownFuncs[tFuncSetId][FUNC_RUN](taskId); + break; + case STATE_END: + sStaticCountdownFuncs[tFuncSetId][FUNC_FREE](taskId); + DestroyTask(taskId); + break; + } +} + +static void StaticCountdown_CreateSprites(u8 taskId, s16 *data) +{ + u8 i; + struct Sprite *sprite; + + LoadCompressedSpriteSheet(&sSpriteSheet_321Start_Static[tSpriteSheetId]); + LoadSpritePalette(&sSpritePalette_321Start_Static[tSpritePalId]); + for (i = 0; i < tNumSprites; i++) + tSpriteIds(i) = CreateSprite(&sSpriteTemplate_StaticCountdown[tSpriteTemplateId], tX, tY, tSubpriority); + for (i = 0; i < tNumSprites; i++) + { + sprite = &gSprites[tSpriteIds(i)]; + sprite->oam.priority = tPriority; + sprite->invisible = TRUE; + sprite->sInterval = tInterval; + sprite->sTaskId = taskId; + sprite->sId = i; + sprite->sNumberSpriteId = tSpriteIds(0); + } +} + +static void Task_StaticCountdown_Init(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + tSpriteTemplateId = 0; + tSpriteSheetId = 0; + tSpritePalId = 0; + tInterval = 60; + tPriority = 0; + tSubpriority = 0; + tNumSprites = 3; + tX = 120; + tY = 88; + StaticCountdown_CreateSprites(taskId, data); + + StartSpriteAnim(&gSprites[tSpriteIds(1)], ANIM_START_MID); + gSprites[tSpriteIds(1)].pos2.x = -32; + + StartSpriteAnim(&gSprites[tSpriteIds(2)], ANIM_START_RIGHT); + gSprites[tSpriteIds(2)].pos2.x = 32; +} + +static void Task_StaticCountdown_Free(u8 taskId) +{ + u8 i = 0; + s16 *data = gTasks[taskId].data; + + for (i = 0; i < tNumSprites; i++) + DestroySprite(&gSprites[tSpriteIds(i)]); + FreeSpriteTilesByTag(sSpriteSheet_321Start_Static[tSpriteSheetId].tag); + FreeSpritePaletteByTag(sSpritePalette_321Start_Static[tSpritePalId].tag); +} + +static void SpriteCB_StaticCountdown(struct Sprite *sprite) +{ + s16 *data = gTasks[sprite->sTaskId].data; + + if (tTimer % tInterval != 0) + return; + if (tTimer == tPrevTime) + return; + + tPrevTime = tTimer; + switch (sprite->sAnimNum) + { + case ANIM_THREE: + sprite->invisible = FALSE; + case ANIM_TWO: + case ANIM_ONE: + // Set sprite to a number + PlaySE(SE_BALL_BOUNCE_1); + StartSpriteAnim(sprite, sprite->sAnimNum); + break; + case ANIM_START_LEFT: + // Set sprite to 'Start' + PlaySE(SE_PIN); + StartSpriteAnim(sprite, sprite->sAnimNum); + gSprites[tSpriteIds(1)].invisible = FALSE; + gSprites[tSpriteIds(2)].invisible = FALSE; + break; + case ANIM_START_LEFT + 1: // End + // Hide countdown + sprite->invisible = TRUE; + gSprites[tSpriteIds(1)].invisible = TRUE; + gSprites[tSpriteIds(2)].invisible = TRUE; + tState = STATE_END; + return; + } + sprite->sAnimNum++; +} + +static void Task_StaticCountdown_Start(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + PlaySE(SE_BALL_BOUNCE_1); + gSprites[tSpriteIds(0)].callback = SpriteCB_StaticCountdown; + gSprites[tSpriteIds(0)].invisible = FALSE; + gTasks[taskId].tState = STATE_RUN; +} + +// Increment timer for progressing the countdown. +// If the player is the link leader, increment a +// separate timer and send it to group members for +// them to read and use. +static void Task_StaticCountdown_Run(u8 taskId) +{ + u16 packet[RFU_PACKET_SIZE]; + s16 *data = gTasks[taskId].data; + + if (gReceivedRemoteLinkPlayers != 0) + { + // Read link timer + if (gRecvCmds[0][1] == LINKCMD_COUNTDOWN) + tTimer = gRecvCmds[0][2]; + + if (GetMultiplayerId() == 0) + { + // Player is link leader. + // Send timer to group members + tLinkTimer++; + memset(packet, 0, sizeof(packet)); + packet[0] = LINKCMD_COUNTDOWN; + packet[1] = tLinkTimer; + Rfu_SendPacket(packet); + } + } + else + { + // Local, just increment own timer + tTimer++; + } +} + +#undef tState +#undef tFuncSetId +#undef tSpriteTemplateId +#undef tSpriteSheetId +#undef tSpritePalId +#undef tInterval +#undef tPriority +#undef tSubpriority +#undef tNumSprites +#undef tX +#undef tY +#undef tPrevTime +#undef tTimer +#undef tLinkTimer +#undef tSpriteIds +#undef sInterval +#undef sAnimNum +#undef sTaskId +#undef sId +#undef sNumberSpriteId + +/* + The countdown that actually gets used by + the wireless minigames starts here +*/ + static void Task_MinigameCountdown(u8 taskId); static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId); static bool32 IsStartGraphicAnimRunning(u8 spriteId); @@ -23,260 +374,8 @@ static void CreateStartSprite(u16 tileTag, u16 palTag, s16 x, s16 y, u8 subprior static void InitStartGraphic(u8 spriteId1, u8 spriteId2, u8 spriteId3); static void SpriteCB_Start(struct Sprite *sprite); -static const u16 sSpritePal_321Start_2[] = INCBIN_U16("graphics/link_games/321start_2.gbapal"); -static const u32 sSpriteSheet_321Start_2[] = INCBIN_U32("graphics/link_games/321start_2.4bpp.lz"); - -static const struct CompressedSpriteSheet gUnknown_082FE6C8[] = -{ - {sSpriteSheet_321Start_2, 0xC00, 0x2000}, - {}, -}; - -static const struct SpritePalette gUnknown_082FE6D8[] = -{ - {sSpritePal_321Start_2, 0x2000}, - {}, -}; - -static const union AnimCmd sSpriteAnim_82FE6E8[] = -{ - ANIMCMD_FRAME(0, 0), - ANIMCMD_END -}; - -static const union AnimCmd sSpriteAnim_82FE6F0[] = -{ - ANIMCMD_FRAME(16, 0), - ANIMCMD_END -}; - -static const union AnimCmd sSpriteAnim_82FE6F8[] = -{ - ANIMCMD_FRAME(32, 0), - ANIMCMD_END -}; - -static const union AnimCmd sSpriteAnim_82FE700[] = -{ - ANIMCMD_FRAME(64, 0), - ANIMCMD_END -}; - -static const union AnimCmd sSpriteAnim_82FE708[] = -{ - ANIMCMD_FRAME(48, 0), - ANIMCMD_END -}; - -static const union AnimCmd sSpriteAnim_82FE710[] = -{ - ANIMCMD_FRAME(80, 0), - ANIMCMD_END -}; - -static const union AnimCmd *const sSpriteAnimTable_82FE718[] = -{ - sSpriteAnim_82FE6E8, - sSpriteAnim_82FE6F0, - sSpriteAnim_82FE6F8, - sSpriteAnim_82FE700, - sSpriteAnim_82FE708, - sSpriteAnim_82FE710 -}; - -static const struct SpriteTemplate gUnknown_082FE730[] = -{ - { - .tileTag = 0x2000, - .paletteTag = 0x2000, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sSpriteAnimTable_82FE718, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = SpriteCallbackDummy, - }, -}; - -static const TaskFunc gUnknown_082FE748[][4] = -{ - { - sub_802E83C, - sub_802E8C8, - sub_802EA50, - sub_802EAB0 - }, -}; - -static const u16 sSpritePal_321Start[] = INCBIN_U16("graphics/link_games/321start.gbapal"); -static const u32 sSpriteSheet_321Start[] = INCBIN_U32("graphics/link_games/321start.4bpp.lz"); - -// Unused -static u32 sub_802E63C(u8 funcSetId, u8 taskPriority) -{ - u8 taskId = CreateTask(sub_802E6D0, taskPriority); - struct Task *task = &gTasks[taskId]; - - task->data[0] = 1; - task->data[1] = funcSetId; - gUnknown_082FE748[funcSetId][0](taskId); - return taskId; -} - -static bool32 sub_802E688(void) -{ - u8 taskId = FindTaskIdByFunc(sub_802E6D0); - if (taskId == TASK_NONE) - return FALSE; - - gTasks[taskId].data[0] = 2; - return TRUE; -} - -static bool32 sub_802E6BC(void) -{ - return FuncIsActiveTask(sub_802E6D0); -} - -static void sub_802E6D0(u8 taskId) -{ - s16 *data = gTasks[taskId].data; - - switch (data[0]) - { - case 2: - gUnknown_082FE748[data[1]][2](taskId); - data[0] = 3; - break; - case 3: - gUnknown_082FE748[data[1]][3](taskId); - break; - case 4: - gUnknown_082FE748[data[1]][1](taskId); - DestroyTask(taskId); - break; - } -} - -static void sub_802E75C(u8 taskId, s16 *data) -{ - u8 i; - struct Sprite *sprite; - - LoadCompressedSpriteSheet(&gUnknown_082FE6C8[data[3]]); - LoadSpritePalette(&gUnknown_082FE6D8[data[4]]); - for (i = 0; i < data[8]; i++) - data[13 + i] = CreateSprite(&gUnknown_082FE730[data[2]], data[9], data[10], data[7]); - for (i = 0; i < data[8]; i++) - { - sprite = &gSprites[data[13 + i]]; - sprite->oam.priority = data[6]; - sprite->invisible = TRUE; - sprite->data[1] = data[5]; - sprite->data[3] = taskId; - sprite->data[4] = i; - sprite->data[5] = data[13]; - } -} - -static void sub_802E83C(u8 taskId) -{ - s16 *data = gTasks[taskId].data; - data[2] = 0; - data[3] = 0; - data[4] = 0; - data[5] = 60; - data[6] = 0; - data[7] = 0; - data[8] = 3; - data[9] = 120; - data[10] = 88; - sub_802E75C(taskId, data); - - StartSpriteAnim(&gSprites[data[14]], 4); - gSprites[data[14]].pos2.x = -32; - - StartSpriteAnim(&gSprites[data[15]], 5); - gSprites[data[15]].pos2.x = 32; -} - -static void sub_802E8C8(u8 taskId) -{ - u8 i = 0; - s16 *data = gTasks[taskId].data; - - for (i = 0; i < data[8]; i++) - DestroySprite(&gSprites[data[13 + i]]); - FreeSpriteTilesByTag(gUnknown_082FE6C8[data[3]].tag); - FreeSpritePaletteByTag(gUnknown_082FE6D8[data[4]].tag); -} - -static void sub_802E938(struct Sprite *sprite) -{ - s16 *data = gTasks[sprite->data[3]].data; - - if (data[11] % data[5] != 0) - return; - if (data[11] == data[10]) - return; - - data[10] = data[11]; - switch (sprite->data[2]) - { - case 0: - sprite->invisible = FALSE; - case 1: - case 2: - PlaySE(SE_BALL_BOUNCE_1); - StartSpriteAnim(sprite, sprite->data[2]); - break; - case 3: - PlaySE(SE_PIN); - StartSpriteAnim(sprite, sprite->data[2]); - gSprites[data[14]].invisible = FALSE; - gSprites[data[15]].invisible = FALSE; - break; - case 4: - sprite->invisible = TRUE; - gSprites[data[14]].invisible = TRUE; - gSprites[data[15]].invisible = TRUE; - data[0] = 4; - return; - } - sprite->data[2]++; -} - -static void sub_802EA50(u8 taskId) -{ - s16 *data = gTasks[taskId].data; - PlaySE(SE_BALL_BOUNCE_1); - gSprites[data[13]].callback = sub_802E938; - gSprites[data[13]].invisible = FALSE; - gTasks[taskId].data[0] = 3; -} - -static void sub_802EAB0(u8 taskId) -{ - u16 packet[6]; - s16 *data = gTasks[taskId].data; - - if (gReceivedRemoteLinkPlayers != 0) - { - if (gRecvCmds[0][1] == LINKCMD_0x7FFF) - data[11] = gRecvCmds[0][2]; - if (GetMultiplayerId() == 0) - { - data[12]++; - memset(packet, 0, sizeof(packet)); - packet[0] = LINKCMD_0x7FFF; - packet[1] = data[12]; - Rfu_SendPacket(packet); - } - } - else - { - data[11]++; - } -} +static const u16 s321Start_Pal[] = INCBIN_U16("graphics/link_games/321start.gbapal"); +static const u32 s321Start_Gfx[] = INCBIN_U32("graphics/link_games/321start.4bpp.lz"); #define tState data[0] #define tTilesTag data[2] @@ -288,7 +387,7 @@ static void sub_802EAB0(u8 taskId) #define tSpriteId2 data[8] #define tSpriteId3 data[9] -void StartMinigameCountdown(s16 tilesTag, s16 palTag, s16 x, s16 y, u8 subpriority) +void StartMinigameCountdown(u16 tilesTag, u16 palTag, s16 x, s16 y, u8 subpriority) { u8 taskId = CreateTask(Task_MinigameCountdown, 80); gTasks[taskId].tTilesTag = tilesTag; @@ -337,69 +436,82 @@ static void Task_MinigameCountdown(u8 taskId) } } +#define sState data[0] +#define sTimer data[2] +#define sAnimNum data[4] + static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId) { struct Sprite *sprite = &gSprites[spriteId]; - switch (sprite->data[0]) + switch (sprite->sState) { case 0: sub_8007E18(sprite, 0x800, 0x1A); - sprite->data[0]++; + sprite->sState++; // fallthrough case 1: - if (sprite->data[2] == 0) + if (sprite->sTimer == 0) PlaySE(SE_BALL_BOUNCE_2); - if (++sprite->data[2] >= 20) + + if (++sprite->sTimer >= 20) { - sprite->data[2] = 0; + // Ready for jump + sprite->sTimer = 0; StartSpriteAffineAnim(sprite, 1); - sprite->data[0]++; + sprite->sState++; } break; case 2: if (sprite->affineAnimEnded) - sprite->data[0]++; + sprite->sState++; break; case 3: - if (++sprite->data[2] >= 4) + if (++sprite->sTimer >= 4) { - sprite->data[2] = 0; - sprite->data[0]++; + // Start jump + sprite->sTimer = 0; + sprite->sState++; StartSpriteAffineAnim(sprite, 2); } break; case 4: + // Moving up from jump sprite->pos1.y -= 4; - if (++sprite->data[2] >= 8) + if (++sprite->sTimer >= 8) { - if (sprite->data[4] <= 1) + if (sprite->sAnimNum < 2) { - StartSpriteAnim(sprite, sprite->data[4] + 1); - sprite->data[2] = 0; - sprite->data[0]++; + // Swap to the next number + StartSpriteAnim(sprite, sprite->sAnimNum + 1); + sprite->sTimer = 0; + sprite->sState++; } else { - sprite->data[0] = 7; + // End + sprite->sState = 7; return FALSE; } } break; case 5: + // Falling after jump sprite->pos1.y += 4; - if (++sprite->data[2] >= 8) + if (++sprite->sTimer >= 8) { - sprite->data[2] = 0; + // Land from jump + sprite->sTimer = 0; StartSpriteAffineAnim(sprite, 3); - sprite->data[0]++; + sprite->sState++; } break; case 6: if (sprite->affineAnimEnded) { - sprite->data[4]++; - sprite->data[0] = 1; + // Restart for next number + sprite->sAnimNum++; + sprite->sState = 1; } break; case 7: @@ -409,6 +521,10 @@ static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId) return TRUE; } +#undef sState +#undef sTimer +#undef sAnimNum + // First argument is unused. static void InitStartGraphic(u8 spriteId1, u8 spriteId2, u8 spriteId3) { @@ -425,60 +541,70 @@ static bool32 IsStartGraphicAnimRunning(u8 spriteId) return gSprites[spriteId].callback == SpriteCB_Start; } +#define sState data[0] +#define sTimer data[1] +#define sYSpeed data[4] +#define sY data[5] + static void SpriteCB_Start(struct Sprite *sprite) { int y; s16 *data = sprite->data; - switch (data[0]) + switch (sState) { case 0: - data[4] = 64; - data[5] = sprite->pos2.y << 4; - data[0]++; + sYSpeed = 64; + sY = sprite->pos2.y << 4; + sState++; case 1: - data[5] += data[4]; - data[4]++; - sprite->pos2.y = data[5] >> 4; + sY += sYSpeed; + sYSpeed++; + sprite->pos2.y = sY >> 4; if (sprite->pos2.y >= 0) { PlaySE(SE_BALL_BOUNCE_2); sprite->pos2.y = 0; - data[0]++; + sState++; } break; case 2: - data[1] += 12; - if (data[1] >= 128) + sTimer += 12; + if (sTimer >= 128) { PlaySE(SE_BALL_BOUNCE_2); - data[1] = 0; - data[0]++; + sTimer = 0; + sState++; } - y = gSineTable[data[1]]; + y = gSineTable[sTimer]; sprite->pos2.y = -(y >> 4); break; case 3: - data[1] += 16; - if (data[1] >= 128) + sTimer += 16; + if (sTimer >= 128) { PlaySE(SE_BALL_BOUNCE_2); - data[1] = 0; - data[0]++; + sTimer = 0; + sState++; } - sprite->pos2.y = -(gSineTable[data[1]] >> 5); + sprite->pos2.y = -(gSineTable[sTimer] >> 5); break; case 4: - if (++data[1] > 40) + if (++sTimer > 40) sprite->callback = SpriteCallbackDummy; break; } } +#undef sState +#undef sTimer +#undef sYSpeed +#undef sY + static void Load321StartGfx(u16 tileTag, u16 palTag) { - struct CompressedSpriteSheet spriteSheet = {sSpriteSheet_321Start, 0xE00, 0}; - struct SpritePalette spritePalette = {sSpritePal_321Start, 0}; + struct CompressedSpriteSheet spriteSheet = {s321Start_Gfx, 0xE00, 0}; + struct SpritePalette spritePalette = {s321Start_Pal, 0}; spriteSheet.tag = tileTag; spritePalette.tag = palTag; @@ -564,26 +690,26 @@ static const union AnimCmd *const sAnimTable_Start[] = sAnim_StartRight }; -static const union AffineAnimCmd sAffineAnim_Numbers_0[] = +static const union AffineAnimCmd sAffineAnim_Numbers_Normal[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 0), AFFINEANIMCMD_END }; -static const union AffineAnimCmd sAffineAnim_Numbers_1[] = +static const union AffineAnimCmd sAffineAnim_Numbers_Squash[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 0), AFFINEANIMCMD_FRAME(16, -16, 0, 8), AFFINEANIMCMD_END }; -static const union AffineAnimCmd sAffineAnim_Numbers_2[] = +static const union AffineAnimCmd sAffineAnim_Numbers_Stretch[] = { AFFINEANIMCMD_FRAME(-18, 18, 0, 8), AFFINEANIMCMD_END }; -static const union AffineAnimCmd sAffineAnim_Numbers_3[] = +static const union AffineAnimCmd sAffineAnim_Numbers_Land[] = { AFFINEANIMCMD_FRAME( 6, -6, 0, 8), AFFINEANIMCMD_FRAME( -4, 4, 0, 8), @@ -593,10 +719,10 @@ static const union AffineAnimCmd sAffineAnim_Numbers_3[] = static const union AffineAnimCmd *const sAffineAnimTable_Numbers[] = { - sAffineAnim_Numbers_0, - sAffineAnim_Numbers_1, - sAffineAnim_Numbers_2, - sAffineAnim_Numbers_3 + sAffineAnim_Numbers_Normal, + sAffineAnim_Numbers_Squash, // Push down before the jump + sAffineAnim_Numbers_Stretch, // Stretch up for the jump + sAffineAnim_Numbers_Land // Land after the jump }; static u8 CreateNumberSprite(u16 tileTag, u16 palTag, s16 x, s16 y, u8 subpriority) diff --git a/src/pokemon_jump.c b/src/pokemon_jump.c index 01eb7d608..33f08f590 100755 --- a/src/pokemon_jump.c +++ b/src/pokemon_jump.c @@ -131,14 +131,16 @@ enum { #define TAG_MON4 3 #define TAG_MON5 4 -#define GFXTAG_VINE1 5 -#define GFXTAG_VINE2 6 -#define GFXTAG_VINE3 7 -#define GFXTAG_VINE4 8 -#define GFXTAG_STAR 10 +#define GFXTAG_VINE1 5 +#define GFXTAG_VINE2 6 +#define GFXTAG_VINE3 7 +#define GFXTAG_VINE4 8 +#define GFXTAG_COUNTDOWN 9 +#define GFXTAG_STAR 10 -#define PALTAG_1 5 -#define PALTAG_2 6 +#define PALTAG_1 5 +#define PALTAG_2 6 +#define PALTAG_COUNTDOWN 7 #define TAG_DIGITS 800 @@ -3007,7 +3009,7 @@ static void UpdateVineAnim(struct PokemonJumpGfx *jumpGfx, int vineState) static void StartPokeJumpCountdown(struct PokemonJumpGfx *jumpGfx) { - StartMinigameCountdown(9, 7, 120, 80, 0); + StartMinigameCountdown(GFXTAG_COUNTDOWN, PALTAG_COUNTDOWN, 120, 80, 0); Gfx_ResetMonSpriteSubpriorities(jumpGfx); }