mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-26 11:44:17 +01:00
Document minigame countdown
This commit is contained in:
parent
69f7882b5e
commit
b1a69d95ea
Before Width: | Height: | Size: 778 B After Width: | Height: | Size: 778 B |
@ -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
|
||||
|
@ -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())
|
||||
|
@ -149,12 +149,14 @@ enum {
|
||||
#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:
|
||||
|
@ -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)
|
||||
|
@ -135,10 +135,12 @@ enum {
|
||||
#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_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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user