mirror of
https://github.com/pret/pokeplatinum.git
synced 2026-05-23 13:26:25 -05:00
1646 lines
52 KiB
C
1646 lines
52 KiB
C
#include "contest.h"
|
|
|
|
#include <nitro.h>
|
|
#include <string.h>
|
|
|
|
#include "constants/contests.h"
|
|
#include "constants/heap.h"
|
|
#include "generated/accessories.h"
|
|
#include "generated/game_records.h"
|
|
#include "generated/object_events_gfx.h"
|
|
#include "generated/pokemon_contest_ranks.h"
|
|
#include "generated/trainer_score_events.h"
|
|
|
|
#include "struct_decls/tv_broadcast.h"
|
|
#include "struct_defs/contest_camera_flash_task.h"
|
|
#include "struct_defs/contest_player_mon_dto.h"
|
|
#include "struct_defs/image_clips.h"
|
|
#include "struct_defs/struct_02029C88.h"
|
|
#include "struct_defs/visual_competition_app_args.h"
|
|
|
|
#include "field/field_system.h"
|
|
#include "overlay006/ov6_022489E4.h"
|
|
#include "overlay006/struct_ov6_02248DD8.h"
|
|
#include "overlay017/ov17_0223B140.h"
|
|
#include "overlay017/ov17_0223CB1C.h"
|
|
#include "overlay017/ov17_0223DAD0.h"
|
|
#include "overlay017/ov17_0224F4D4.h"
|
|
#include "overlay022/ov22_02255D44.h"
|
|
#include "pch/global_pch.h"
|
|
#include "savedata/save_table.h"
|
|
|
|
#include "assert.h"
|
|
#include "brightness_controller.h"
|
|
#include "chatot_cry.h"
|
|
#include "communication_information.h"
|
|
#include "communication_system.h"
|
|
#include "field_task.h"
|
|
#include "field_transition.h"
|
|
#include "game_records.h"
|
|
#include "heap.h"
|
|
#include "journal.h"
|
|
#include "link_contest_records.h"
|
|
#include "math_util.h"
|
|
#include "party.h"
|
|
#include "pokedex.h"
|
|
#include "pokemon.h"
|
|
#include "ribbon.h"
|
|
#include "rtc.h"
|
|
#include "savedata.h"
|
|
#include "sound_playback.h"
|
|
#include "string_gf.h"
|
|
#include "string_template.h"
|
|
#include "sys_task.h"
|
|
#include "sys_task_manager.h"
|
|
#include "system_flags.h"
|
|
#include "trainer_info.h"
|
|
#include "tv_segment.h"
|
|
#include "unk_020298BC.h"
|
|
#include "unk_020363E8.h"
|
|
#include "unk_02094EDC.h"
|
|
#include "unk_02095AF0.h"
|
|
#include "vars_flags.h"
|
|
|
|
FS_EXTERN_OVERLAY(overlay17);
|
|
FS_EXTERN_OVERLAY(overlay22);
|
|
|
|
typedef struct ContestTaskEnv {
|
|
Contest *contest;
|
|
int state;
|
|
} ContestTaskEnv;
|
|
|
|
static Contest *Contest_New(void);
|
|
static void Contest_InternalFree(Contest *contest);
|
|
static void Contest_SetLCRNGSeed(Contest *contest);
|
|
u16 Contest_GetRNGNext(Contest *contest);
|
|
BOOL Contest_SetUpLinkContest(Contest *contest);
|
|
static BOOL Contest_IsCommTaskDoneInternal(Contest *contest);
|
|
static void sub_02093C6C(SysTask *param0, void *param1);
|
|
static BOOL FieldTask_RunContest(FieldTask *param0);
|
|
static BOOL FieldTask_RunPracticeCompetition(FieldTask *param0);
|
|
void Contest_GetVisualCompetitionAppArgs(Contest *contest);
|
|
void Contest_VisualCompetitionAppArgsFree(Contest *contest);
|
|
static void sub_020944E8(Contest *contest);
|
|
static void sub_0209451C(SysTask *param0, void *param1);
|
|
static void sub_02094EB4(Contest *contest, int contestantID, UnkStruct_ov6_02248DD8 *param2);
|
|
static void SysTask_DoContestCameraFlash(SysTask *sysTask, void *contestParam);
|
|
static int CalcMonContestFame(Pokemon *mon, enum PokemonContestType contestType);
|
|
static void sub_020939E0(Contest *contest, int isGameCompleted, int isNatDexObtained);
|
|
|
|
const ApplicationManagerTemplate ActingCompetitionAppTemplate = {
|
|
ActingCompetition_Init,
|
|
ActingCompetition_Main,
|
|
ActingCompetition_Exit,
|
|
FS_OVERLAY_ID(overlay17)
|
|
};
|
|
|
|
const ApplicationManagerTemplate DanceCompetitionAppTemplate = {
|
|
DanceCompetition_Init,
|
|
DanceCompetition_Main,
|
|
DanceCompetition_Exit,
|
|
FS_OVERLAY_ID(overlay17)
|
|
};
|
|
|
|
const ApplicationManagerTemplate VisualCompetitionScoringAppTemplate = {
|
|
VisualCompetitonScoring_Init,
|
|
VisualCompetitionScoring_Main,
|
|
VisualCompetitionScoring_Exit,
|
|
FS_OVERLAY_ID(overlay17)
|
|
};
|
|
|
|
const ApplicationManagerTemplate ContestFinalScoringAppTemplate = {
|
|
ContestFinalScoring_Init,
|
|
ContestFinalScoring_Main,
|
|
ContestFinalScoring_Exit,
|
|
FS_OVERLAY_ID(overlay17)
|
|
};
|
|
|
|
const ApplicationManagerTemplate VisualCompetitionAppTemplate = {
|
|
VisualCompetition_Init,
|
|
VisualCompetition_Main,
|
|
VisualCompetition_Exit,
|
|
FS_OVERLAY_ID(overlay22)
|
|
};
|
|
|
|
#define CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR 0xFF
|
|
|
|
ALIGN_4 static const u8 sNormalRankCameraFrameDelays[][3] = {
|
|
{ 0x14, 0x14, CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR },
|
|
{ 0xF, 0x19, CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR }
|
|
};
|
|
|
|
ALIGN_4 static const u8 sGreatRankCameraFrameDelays[][4] = {
|
|
{ 0xA, 0xA, 0x1E, CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR },
|
|
{ 0xF, 0xF, 0xF, CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR }
|
|
};
|
|
|
|
ALIGN_4 static const u8 sUltraRankCameraFrameDelays[][5] = {
|
|
{ 0xA, 0x8, 0x14, 0x1C, CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR },
|
|
{ 0xF, 0xF, 0x8, 0x8, CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR }
|
|
};
|
|
|
|
ALIGN_4 static const u8 sLinkMasterRankCameraFrameDelays[][6] = {
|
|
{ 0x8, 0x8, 0x8, 0x8, 0x1E, CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR },
|
|
{ 0xF, 0xF, 0x8, 0x8, 0x14, CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR }
|
|
};
|
|
|
|
void FieldTask_InitRunContestTask(FieldTask *fieldTask, Contest *contest)
|
|
{
|
|
ContestTaskEnv *taskEnv = Heap_AllocAtEnd(HEAP_ID_FIELD2, sizeof(ContestTaskEnv));
|
|
|
|
MI_CpuClear8(taskEnv, sizeof(ContestTaskEnv));
|
|
taskEnv->contest = contest;
|
|
|
|
switch (contest->unk_00.competitionType) {
|
|
case CONTEST_COMPETITION_UNK0:
|
|
case CONTEST_COMPETITION_UNK1:
|
|
case CONTEST_COMPETITION_LINK_OR_OFFICIAL:
|
|
FieldTask_InitCall(fieldTask, FieldTask_RunContest, taskEnv);
|
|
break;
|
|
default:
|
|
FieldTask_InitCall(fieldTask, FieldTask_RunPracticeCompetition, taskEnv);
|
|
break;
|
|
}
|
|
}
|
|
|
|
enum ContestManagerState {
|
|
CONTEST_MANAGER_STATE_START,
|
|
CONTEST_MANAGER_STATE_WAIT_FOR_COMM_TASK,
|
|
CONTEST_MANAGER_STATE_START_COMM_SYNC_0,
|
|
CONTEST_MANAGER_STATE_CONFIRM_COMM_SYNC_0,
|
|
CONTEST_MANAGER_STATE_RUN_APP_VISUAL_COMPETITION,
|
|
CONTEST_MANAGER_STATE_5,
|
|
CONTEST_MANAGER_STATE_WAIT_FOR_COMM_TASK_2,
|
|
CONTEST_MANAGER_STATE_RUN_APP_VISUAL_COMPETITION_SCORING,
|
|
CONTEST_MANAGER_STATE_RUN_APP_DANCE_COMPETITION,
|
|
CONTEST_MANAGER_STATE_RUN_APP_ACTING_COMPETITION,
|
|
CONTEST_MANAGER_STATE_RUN_APP_FINAL_SCORING,
|
|
CONTEST_MANAGER_STATE_WAIT_ONE_FRAME,
|
|
CONTEST_MANAGER_STATE_RETURN_TO_MAP,
|
|
CONTEST_MANAGER_STATE_END
|
|
};
|
|
|
|
static BOOL FieldTask_RunContest(FieldTask *fieldTask)
|
|
{
|
|
FieldSystem *fieldSystem = FieldTask_GetFieldSystem(fieldTask);
|
|
ContestTaskEnv *taskEnv = FieldTask_GetEnv(fieldTask);
|
|
|
|
switch (taskEnv->state) {
|
|
case CONTEST_MANAGER_STATE_START:
|
|
FieldTransition_FinishMap(fieldTask);
|
|
taskEnv->state++;
|
|
break;
|
|
case CONTEST_MANAGER_STATE_WAIT_FOR_COMM_TASK:
|
|
if (taskEnv->contest->isLinkContest == FALSE || Contest_IsCommTaskDoneInternal(taskEnv->contest) == 1) {
|
|
taskEnv->state++;
|
|
}
|
|
break;
|
|
case CONTEST_MANAGER_STATE_START_COMM_SYNC_0:
|
|
if (taskEnv->contest->isLinkContest == TRUE) {
|
|
CommTiming_StartSync(0);
|
|
}
|
|
|
|
taskEnv->state++;
|
|
break;
|
|
case CONTEST_MANAGER_STATE_CONFIRM_COMM_SYNC_0:
|
|
if (taskEnv->contest->isLinkContest == TRUE) {
|
|
if (CommTiming_IsSyncState(0) == TRUE) {
|
|
taskEnv->state++;
|
|
}
|
|
} else {
|
|
taskEnv->state++;
|
|
}
|
|
break;
|
|
case CONTEST_MANAGER_STATE_RUN_APP_VISUAL_COMPETITION:
|
|
Contest_GetVisualCompetitionAppArgs(taskEnv->contest);
|
|
FieldTask_RunApplication(fieldTask, &VisualCompetitionAppTemplate, taskEnv->contest->visualCompetitionAppArgs);
|
|
taskEnv->state++;
|
|
break;
|
|
case CONTEST_MANAGER_STATE_5:
|
|
Contest_VisualCompetitionAppArgsFree(taskEnv->contest);
|
|
|
|
if (taskEnv->contest->isLinkContest == TRUE) {
|
|
sub_020944E8(taskEnv->contest);
|
|
taskEnv->state++;
|
|
} else {
|
|
taskEnv->state = CONTEST_MANAGER_STATE_WAIT_FOR_COMM_TASK_2;
|
|
}
|
|
break;
|
|
case CONTEST_MANAGER_STATE_WAIT_FOR_COMM_TASK_2:
|
|
if (taskEnv->contest->isLinkContest == FALSE || Contest_IsCommTaskDoneInternal(taskEnv->contest) == TRUE) {
|
|
taskEnv->state++;
|
|
}
|
|
break;
|
|
case CONTEST_MANAGER_STATE_RUN_APP_VISUAL_COMPETITION_SCORING:
|
|
FieldTask_RunApplication(fieldTask, &VisualCompetitionScoringAppTemplate, taskEnv->contest);
|
|
taskEnv->state++;
|
|
break;
|
|
case CONTEST_MANAGER_STATE_RUN_APP_DANCE_COMPETITION:
|
|
if (taskEnv->contest->unk_00.competitionType == CONTEST_COMPETITION_UNK1 || taskEnv->contest->unk_00.competitionType == CONTEST_COMPETITION_LINK_OR_OFFICIAL) {
|
|
FieldTask_RunApplication(fieldTask, &DanceCompetitionAppTemplate, taskEnv->contest);
|
|
}
|
|
|
|
taskEnv->state++;
|
|
break;
|
|
case CONTEST_MANAGER_STATE_RUN_APP_ACTING_COMPETITION:
|
|
if (taskEnv->contest->unk_00.competitionType == CONTEST_COMPETITION_UNK0 || taskEnv->contest->unk_00.competitionType == CONTEST_COMPETITION_LINK_OR_OFFICIAL) {
|
|
FieldTask_RunApplication(fieldTask, &ActingCompetitionAppTemplate, taskEnv->contest);
|
|
}
|
|
|
|
taskEnv->state++;
|
|
break;
|
|
case CONTEST_MANAGER_STATE_RUN_APP_FINAL_SCORING:
|
|
FieldTask_RunApplication(fieldTask, &ContestFinalScoringAppTemplate, taskEnv->contest);
|
|
taskEnv->state++;
|
|
break;
|
|
case CONTEST_MANAGER_STATE_WAIT_ONE_FRAME:
|
|
taskEnv->state++;
|
|
break;
|
|
case CONTEST_MANAGER_STATE_RETURN_TO_MAP:
|
|
FieldTransition_StartMap(fieldTask);
|
|
taskEnv->state++;
|
|
break;
|
|
default:
|
|
GF_ASSERT(0);
|
|
case CONTEST_MANAGER_STATE_END:
|
|
Heap_Free(taskEnv);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL FieldTask_RunPracticeCompetition(FieldTask *fieldTask)
|
|
{
|
|
FieldSystem *fieldSystem = FieldTask_GetFieldSystem(fieldTask);
|
|
ContestTaskEnv *taskEnv = FieldTask_GetEnv(fieldTask);
|
|
|
|
switch (taskEnv->state) {
|
|
case 0:
|
|
FieldTransition_FinishMap(fieldTask);
|
|
taskEnv->state++;
|
|
break;
|
|
case 1:
|
|
switch (taskEnv->contest->unk_00.competitionType) {
|
|
case CONTEST_COMPETITION_PRACTICE_VISUAL:
|
|
case CONTEST_COMPETITION_VISUAL:
|
|
Contest_GetVisualCompetitionAppArgs(taskEnv->contest);
|
|
FieldTask_RunApplication(fieldTask, &VisualCompetitionAppTemplate, taskEnv->contest->visualCompetitionAppArgs);
|
|
break;
|
|
}
|
|
|
|
taskEnv->state++;
|
|
break;
|
|
case 2:
|
|
switch (taskEnv->contest->unk_00.competitionType) {
|
|
case CONTEST_COMPETITION_PRACTICE_VISUAL:
|
|
case CONTEST_COMPETITION_VISUAL:
|
|
Contest_VisualCompetitionAppArgsFree(taskEnv->contest);
|
|
break;
|
|
}
|
|
|
|
taskEnv->state++;
|
|
break;
|
|
case 3:
|
|
taskEnv->state++;
|
|
break;
|
|
case 4:
|
|
switch (taskEnv->contest->unk_00.competitionType) {
|
|
case CONTEST_COMPETITION_PRACTICE_VISUAL:
|
|
case CONTEST_COMPETITION_VISUAL:
|
|
FieldTask_RunApplication(fieldTask, &VisualCompetitionScoringAppTemplate, taskEnv->contest);
|
|
break;
|
|
}
|
|
|
|
taskEnv->state++;
|
|
break;
|
|
case 5:
|
|
switch (taskEnv->contest->unk_00.competitionType) {
|
|
case CONTEST_COMPETITION_PRACTICE_DANCE:
|
|
case CONTEST_COMPETITION_DANCE:
|
|
sub_02095338(taskEnv->contest);
|
|
FieldTask_RunApplication(fieldTask, &DanceCompetitionAppTemplate, taskEnv->contest);
|
|
break;
|
|
}
|
|
|
|
taskEnv->state++;
|
|
break;
|
|
case 6:
|
|
switch (taskEnv->contest->unk_00.competitionType) {
|
|
case CONTEST_COMPETITION_PRACTICE_ACTING:
|
|
case CONTEST_COMPETITION_ACTING:
|
|
FieldTask_RunApplication(fieldTask, &ActingCompetitionAppTemplate, taskEnv->contest);
|
|
break;
|
|
}
|
|
|
|
taskEnv->state++;
|
|
break;
|
|
case 7: {
|
|
s32 v2[4];
|
|
int v3, v4;
|
|
|
|
switch (taskEnv->contest->unk_00.competitionType) {
|
|
case CONTEST_COMPETITION_PRACTICE_VISUAL:
|
|
case CONTEST_COMPETITION_VISUAL:
|
|
for (v3 = 0; v3 < 4; v3++) {
|
|
v2[v3] = sub_02095928(taskEnv->contest, v3)
|
|
+ sub_0209598C(taskEnv->contest, v3);
|
|
}
|
|
break;
|
|
case CONTEST_COMPETITION_PRACTICE_DANCE:
|
|
case CONTEST_COMPETITION_DANCE:
|
|
for (v3 = 0; v3 < 4; v3++) {
|
|
v2[v3] = taskEnv->contest->unk_00.unk_118[v3].unk_04;
|
|
}
|
|
break;
|
|
case CONTEST_COMPETITION_PRACTICE_ACTING:
|
|
case CONTEST_COMPETITION_ACTING:
|
|
for (v3 = 0; v3 < 4; v3++) {
|
|
v2[v3] = taskEnv->contest->unk_00.unk_118[v3].unk_06;
|
|
}
|
|
break;
|
|
}
|
|
|
|
v4 = 0;
|
|
|
|
for (v3 = 1; v3 < 4; v3++) {
|
|
if (v2[0] < v2[v3]) {
|
|
v4++;
|
|
}
|
|
}
|
|
|
|
taskEnv->contest->unk_00.unk_118[0].contestPlacement = v4;
|
|
}
|
|
taskEnv->state++;
|
|
break;
|
|
case 8:
|
|
FieldTransition_StartMap(fieldTask);
|
|
taskEnv->state++;
|
|
break;
|
|
default:
|
|
GF_ASSERT(0);
|
|
case 9:
|
|
Heap_Free(taskEnv);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static Contest *Contest_New(void)
|
|
{
|
|
Contest *contest = Heap_Alloc(HEAP_ID_20, sizeof(Contest));
|
|
MI_CpuClear8(contest, sizeof(Contest));
|
|
|
|
contest->unk_00.playerContestantID = PLAYER_CONTESTANT_ID;
|
|
contest->unk_00.connectionCount = 1;
|
|
contest->unk_00.npcCount = CONTEST_NUM_PARTICIPANTS - 1;
|
|
|
|
return contest;
|
|
}
|
|
|
|
static void Contest_InternalFree(Contest *contest)
|
|
{
|
|
Heap_Free(contest);
|
|
}
|
|
|
|
Contest *Contest_Init(const PlayerMonContestDTO *playerMonContestDTO)
|
|
{
|
|
Heap_Create(HEAP_ID_FIELD2, HEAP_ID_20, 0x3000 + 0x1000);
|
|
|
|
Contest *contest = Contest_New();
|
|
contest->rngSeed = LCRNG_GetSeed();
|
|
|
|
Contest_SetLCRNGSeed(contest);
|
|
|
|
contest->unk_00.contestType = playerMonContestDTO->contestType;
|
|
contest->unk_00.contestRank = playerMonContestDTO->contestRank;
|
|
contest->unk_00.competitionType = playerMonContestDTO->competitionType;
|
|
contest->unk_00.unk_112 = sub_02095A74(playerMonContestDTO->contestRank, FALSE);
|
|
contest->unk_00.unk_10C = contest->unk_00.playerContestantID;
|
|
contest->unk_00.unk_115 = 110;
|
|
contest->unk_00.unk_10D = contest->unk_00.unk_115;
|
|
contest->unk_00.unk_10E = 1;
|
|
contest->imageClips = playerMonContestDTO->imageClips;
|
|
contest->options = playerMonContestDTO->options;
|
|
contest->saveData = playerMonContestDTO->saveData;
|
|
contest->playerMon = playerMonContestDTO->mon;
|
|
contest->monPartySlot = playerMonContestDTO->monPartySlot;
|
|
contest->trainerInfo = playerMonContestDTO->trainerInfo;
|
|
contest->isGameCompleted = playerMonContestDTO->isGameCompleted;
|
|
contest->isNatDexObtained = playerMonContestDTO->isNatDexObtained;
|
|
|
|
int i;
|
|
for (i = 0; i < 4; i++) {
|
|
contest->unk_00.unk_E8[i] = sub_02029C88(HEAP_ID_20);
|
|
}
|
|
|
|
sub_020954F0(contest, HEAP_ID_FIELD2, contest->unk_00.unk_10E, contest->unk_00.contestType, contest->unk_00.contestRank);
|
|
contest->party = Party_New(HEAP_ID_20);
|
|
|
|
for (i = 0; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
contest->unk_00.contestMons[i] = Pokemon_New(HEAP_ID_20);
|
|
}
|
|
|
|
for (i = 0; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
contest->chatotCry[i] = ChatotCry_New(HEAP_ID_20);
|
|
}
|
|
|
|
ChatotCry_Copy(contest->chatotCry[PLAYER_CONTESTANT_ID], playerMonContestDTO->chatotCry);
|
|
|
|
{
|
|
Pokemon_Copy(playerMonContestDTO->mon, contest->unk_00.contestMons[PLAYER_CONTESTANT_ID]);
|
|
contest->unk_00.trainerNames[PLAYER_CONTESTANT_ID] = String_Init(8, HEAP_ID_20);
|
|
String_Copy(contest->unk_00.trainerNames[PLAYER_CONTESTANT_ID], playerMonContestDTO->trainerName);
|
|
|
|
contest->unk_00.trainerGenders[PLAYER_CONTESTANT_ID] = TrainerInfo_Gender(playerMonContestDTO->trainerInfo);
|
|
contest->unk_00.unk_FC[PLAYER_CONTESTANT_ID] = 0;
|
|
contest->unk_00.monContestFame[PLAYER_CONTESTANT_ID] = CalcMonContestFame(contest->unk_00.contestMons[PLAYER_CONTESTANT_ID], contest->unk_00.contestType);
|
|
|
|
if (Contest_IsPracticeCompetition(contest) == FALSE) {
|
|
if (TrainerInfo_Gender(playerMonContestDTO->trainerInfo) == GENDER_MALE) {
|
|
contest->unk_00.contestantObjEventGFX[PLAYER_CONTESTANT_ID] = OBJ_EVENT_GFX_PLAYER_M_CONTEST;
|
|
} else {
|
|
contest->unk_00.contestantObjEventGFX[PLAYER_CONTESTANT_ID] = OBJ_EVENT_GFX_PLAYER_F_CONTEST;
|
|
}
|
|
} else {
|
|
if (TrainerInfo_Gender(playerMonContestDTO->trainerInfo) == GENDER_MALE) {
|
|
contest->unk_00.contestantObjEventGFX[PLAYER_CONTESTANT_ID] = OBJ_EVENT_GFX_PLAYER_M;
|
|
} else {
|
|
contest->unk_00.contestantObjEventGFX[PLAYER_CONTESTANT_ID] = OBJ_EVENT_GFX_PLAYER_F;
|
|
}
|
|
}
|
|
}
|
|
|
|
sub_020939E0(contest, playerMonContestDTO->isGameCompleted, playerMonContestDTO->isNatDexObtained);
|
|
|
|
if (Contest_IsPracticeCompetition(contest) == TRUE) {
|
|
for (i = 0; i < 4; i++) {
|
|
contest->unk_156[i] = 4 - i - 1;
|
|
}
|
|
} else {
|
|
for (i = 0; i < 4; i++) {
|
|
contest->unk_156[i] = i;
|
|
}
|
|
}
|
|
|
|
return contest;
|
|
}
|
|
|
|
static void sub_020939E0(Contest *contest, int isGameCompleted, int isNatDexObtained)
|
|
{
|
|
int v0 = 4 - 1;
|
|
int i;
|
|
|
|
sub_02094F04(contest, HEAP_ID_FIELD2, v0, contest->unk_00.contestType, contest->unk_00.contestRank, contest->unk_00.competitionType, isGameCompleted, isNatDexObtained);
|
|
|
|
// starts at 1, because 0 was already initialized for player
|
|
for (i = 1; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
sub_02095380(&contest->unk_00.unk_10[i], contest->unk_00.contestMons[i], HEAP_ID_20);
|
|
}
|
|
|
|
for (i = 1; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
if (contest->unk_00.trainerNames[i] == NULL) {
|
|
contest->unk_00.trainerNames[i] = String_Init(8, HEAP_ID_20);
|
|
}
|
|
|
|
Pokemon_GetValue(contest->unk_00.contestMons[i], MON_DATA_OT_NAME_STRING, contest->unk_00.trainerNames[i]);
|
|
}
|
|
|
|
for (i = 1; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
contest->unk_00.trainerGenders[i] = contest->unk_00.unk_10[i].unk_20_12;
|
|
}
|
|
|
|
for (i = 1; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
contest->unk_00.unk_FC[i] = contest->unk_00.unk_10[i].unk_20_14;
|
|
}
|
|
|
|
for (i = 1; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
contest->unk_00.monContestFame[i] = contest->unk_00.unk_10[i].unk_2E;
|
|
}
|
|
|
|
for (i = 1; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
contest->unk_00.contestantObjEventGFX[i] = contest->unk_00.unk_10[i].unk_08;
|
|
}
|
|
|
|
sub_020951B0(contest, HEAP_ID_FIELD2);
|
|
}
|
|
|
|
void Contest_Free(Contest *contest)
|
|
{
|
|
Heap_Free(contest->party);
|
|
|
|
for (int i = 0; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
Heap_Free(contest->unk_00.contestMons[i]);
|
|
String_Free(contest->unk_00.trainerNames[i]);
|
|
Heap_Free(contest->unk_00.unk_E8[i]);
|
|
Heap_Free(contest->chatotCry[i]);
|
|
}
|
|
|
|
LCRNG_SetSeed(contest->rngSeed);
|
|
Contest_InternalFree(contest);
|
|
Heap_Destroy(HEAP_ID_20);
|
|
}
|
|
|
|
static int CalcMonContestFame(Pokemon *mon, enum PokemonContestType contestType)
|
|
{
|
|
int ribbon;
|
|
int fame = 1;
|
|
|
|
for (int i = 0; i <= CONTEST_NUM_RANKS; i++) {
|
|
switch (contestType) {
|
|
case CONTEST_TYPE_COOL:
|
|
ribbon = Pokemon_GetValue(mon, MON_DATA_SUPER_COOL_RIBBON + i, NULL);
|
|
break;
|
|
case CONTEST_TYPE_BEAUTY:
|
|
ribbon = Pokemon_GetValue(mon, MON_DATA_SUPER_BEAUTY_RIBBON + i, NULL);
|
|
break;
|
|
case CONTEST_TYPE_CUTE:
|
|
ribbon = Pokemon_GetValue(mon, MON_DATA_SUPER_CUTE_RIBBON + i, NULL);
|
|
break;
|
|
case CONTEST_TYPE_SMART:
|
|
ribbon = Pokemon_GetValue(mon, MON_DATA_SUPER_SMART_RIBBON + i, NULL);
|
|
break;
|
|
case CONTEST_TYPE_TOUGH:
|
|
ribbon = Pokemon_GetValue(mon, MON_DATA_SUPER_TOUGH_RIBBON + i, NULL);
|
|
break;
|
|
default:
|
|
GF_ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
if (ribbon == 0) {
|
|
break;
|
|
}
|
|
|
|
fame++;
|
|
}
|
|
|
|
return fame;
|
|
}
|
|
|
|
void Contest_GetVisualCompetitionAppArgs(Contest *contest)
|
|
{
|
|
VisualCompetitionAppArgs *appArgs;
|
|
|
|
sub_0202A25C(contest->unk_00.unk_E8[contest->unk_00.playerContestantID]);
|
|
|
|
appArgs = Heap_Alloc(HEAP_ID_20, sizeof(VisualCompetitionAppArgs));
|
|
MI_CpuClear8(appArgs, sizeof(VisualCompetitionAppArgs));
|
|
|
|
appArgs->mon = contest->unk_00.contestMons[contest->unk_00.playerContestantID];
|
|
appArgs->unk_04 = contest->unk_00.unk_E8[contest->unk_00.playerContestantID];
|
|
appArgs->unk_08 = contest->unk_00.unk_112;
|
|
|
|
if (contest->isLinkContest == TRUE) {
|
|
appArgs->contestRank = CONTEST_RANK_LINK;
|
|
} else {
|
|
appArgs->contestRank = contest->unk_00.contestRank;
|
|
}
|
|
|
|
appArgs->competitionType = contest->unk_00.competitionType;
|
|
appArgs->contestType = contest->unk_00.contestType;
|
|
appArgs->fashionCase = ImageClips_GetFashionCase(contest->imageClips);
|
|
appArgs->unk_1C = &contest->unk_1984;
|
|
appArgs->options = contest->options;
|
|
appArgs->trainerInfo = contest->trainerInfo;
|
|
|
|
contest->visualCompetitionAppArgs = appArgs;
|
|
}
|
|
|
|
void Contest_VisualCompetitionAppArgsFree(Contest *contest)
|
|
{
|
|
Heap_Free(contest->visualCompetitionAppArgs);
|
|
contest->visualCompetitionAppArgs = NULL;
|
|
}
|
|
|
|
static void sub_02093C6C(SysTask *sysTask, void *param1)
|
|
{
|
|
Contest *contest = param1;
|
|
|
|
switch (contest->linkState) {
|
|
case 0:
|
|
CommTiming_StartSync(5);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 1:
|
|
if (CommTiming_IsSyncState(5) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (ov6_02248A64(contest) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (contest->unk_568 >= contest->unk_00.connectionCount) {
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 4:
|
|
CommTiming_StartSync(6);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 5:
|
|
if (CommTiming_IsSyncState(6) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 6:
|
|
if (ov6_02248AF0(contest, contest->unk_00.playerContestantID, contest->unk_00.contestMons[PLAYER_CONTESTANT_ID]) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 7:
|
|
if (contest->unk_568 >= contest->unk_00.connectionCount) {
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 8:
|
|
CommTiming_StartSync(7);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 9:
|
|
if (CommTiming_IsSyncState(7) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 10:
|
|
if (contest->unk_00.playerContestantID == contest->unk_00.unk_10C) {
|
|
if (ov6_02248B70(contest, contest->unk_00.contestMons) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
} else {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 11:
|
|
if (contest->unk_568 > 0) {
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 12:
|
|
CommTiming_StartSync(8);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 13:
|
|
if (CommTiming_IsSyncState(8) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 14:
|
|
if (ov6_02248BE8(contest, contest->unk_00.playerContestantID, &contest->unk_00.unk_10[0]) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 15:
|
|
if (contest->unk_568 >= contest->unk_00.connectionCount) {
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 16:
|
|
CommTiming_StartSync(9);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 17:
|
|
if (CommTiming_IsSyncState(9) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 18:
|
|
if (contest->unk_00.playerContestantID == contest->unk_00.unk_10C) {
|
|
if (ov6_02248BE8(contest, contest->unk_15C, &contest->unk_00.unk_10[contest->unk_15C]) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
} else {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 19:
|
|
if (contest->unk_568 > 0) {
|
|
contest->unk_568 = 0;
|
|
contest->unk_15C++;
|
|
|
|
if (contest->unk_15C < 4) {
|
|
contest->linkState--;
|
|
} else {
|
|
contest->unk_15C = 0;
|
|
contest->linkState++;
|
|
}
|
|
}
|
|
break;
|
|
case 20:
|
|
CommTiming_StartSync(10);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 21:
|
|
if (CommTiming_IsSyncState(10) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 22:
|
|
if (ov6_02248CE8(contest, contest->unk_00.playerContestantID, contest->unk_00.trainerNames[PLAYER_CONTESTANT_ID]) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 23:
|
|
if (contest->unk_568 >= contest->unk_00.connectionCount) {
|
|
{
|
|
int netID;
|
|
const TrainerInfo *v2;
|
|
|
|
for (netID = 0; netID < contest->unk_00.connectionCount; netID++) {
|
|
v2 = CommInfo_TrainerInfo(netID);
|
|
String_Clear(contest->unk_00.trainerNames[netID]);
|
|
TrainerInfo_NameString(v2, contest->unk_00.trainerNames[netID]);
|
|
}
|
|
}
|
|
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 24:
|
|
CommTiming_StartSync(11);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 25:
|
|
if (CommTiming_IsSyncState(11) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 26:
|
|
if (contest->unk_00.playerContestantID == contest->unk_00.unk_10C) {
|
|
if (ov6_02248CE8(contest, contest->unk_15C, contest->unk_00.trainerNames[contest->unk_15C]) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
} else {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 27:
|
|
if (contest->unk_568 > 0) {
|
|
contest->unk_568 = 0;
|
|
contest->unk_15C++;
|
|
|
|
if (contest->unk_15C < 4) {
|
|
contest->linkState--;
|
|
} else {
|
|
contest->unk_15C = 0;
|
|
contest->linkState++;
|
|
}
|
|
}
|
|
break;
|
|
case 28:
|
|
MI_CpuCopy8(contest->chatotCry[PLAYER_CONTESTANT_ID], contest->unk_569, ChatotCry_SaveSize());
|
|
CommTiming_StartSync(12);
|
|
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 29:
|
|
if (CommTiming_IsSyncState(12) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 30:
|
|
if (ov6_02248D64(contest, contest->unk_00.playerContestantID, NULL) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 31:
|
|
if (contest->unk_568 >= contest->unk_00.connectionCount) {
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 32:
|
|
CommTiming_StartSync(13);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 33:
|
|
if (CommTiming_IsSyncState(13) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 34:
|
|
if (contest->unk_00.playerContestantID == contest->unk_00.unk_10C) {
|
|
if (ov6_02248D64(contest, contest->unk_15C, contest->chatotCry[contest->unk_15C]) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
} else {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 35:
|
|
if (contest->unk_568 > 0) {
|
|
contest->unk_568 = 0;
|
|
contest->unk_15C++;
|
|
|
|
if (contest->unk_15C < 4) {
|
|
contest->linkState--;
|
|
} else {
|
|
contest->unk_15C = 0;
|
|
contest->linkState++;
|
|
}
|
|
}
|
|
break;
|
|
case 36:
|
|
CommTiming_StartSync(14);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 37:
|
|
if (CommTiming_IsSyncState(14) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 38: {
|
|
UnkStruct_ov6_02248DD8 v3;
|
|
|
|
sub_02094EB4(contest, 0, &v3);
|
|
|
|
if (ov6_02248DD8(contest, contest->unk_00.playerContestantID, &v3) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
} break;
|
|
case 39:
|
|
if (contest->unk_568 >= contest->unk_00.connectionCount) {
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 40:
|
|
CommTiming_StartSync(15);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 41:
|
|
if (CommTiming_IsSyncState(15) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 42:
|
|
if (contest->unk_00.playerContestantID == contest->unk_00.unk_10C) {
|
|
UnkStruct_ov6_02248DD8 v4;
|
|
|
|
sub_02094EB4(contest, contest->unk_15C, &v4);
|
|
|
|
if (ov6_02248DD8(contest, contest->unk_15C, &v4) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
} else {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 43:
|
|
if (contest->unk_568 > 0) {
|
|
contest->unk_568 = 0;
|
|
contest->unk_15C++;
|
|
|
|
if (contest->unk_15C < 4) {
|
|
contest->linkState--;
|
|
} else {
|
|
contest->unk_15C = 0;
|
|
contest->linkState++;
|
|
}
|
|
}
|
|
break;
|
|
case 44:
|
|
CommTiming_StartSync(16);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 45:
|
|
if (CommTiming_IsSyncState(16) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 46:
|
|
if (ov6_02248C68(contest, contest->unk_00.playerContestantID, contest->unk_00.unk_C0) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 47:
|
|
if (contest->unk_568 >= contest->unk_00.connectionCount) {
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
default: {
|
|
int contestantID;
|
|
const TrainerInfo *trainerInfo;
|
|
|
|
for (contestantID = 0; contestantID < contest->unk_00.connectionCount; contestantID++) {
|
|
trainerInfo = CommInfo_TrainerInfo(contestantID);
|
|
contest->unk_00.trainerGenders[contestantID] = TrainerInfo_Gender(trainerInfo);
|
|
}
|
|
|
|
for (; contestantID < CONTEST_NUM_PARTICIPANTS; contestantID++) {
|
|
contest->unk_00.trainerGenders[contestantID] = contest->unk_00.unk_10[contestantID].unk_20_12;
|
|
}
|
|
}
|
|
|
|
contest->unk_1984.unk_14 = contest->unk_00.unk_10C;
|
|
contest->unk_1984.unk_15 = contest->unk_00.unk_114;
|
|
contest->unk_1984.unk_16 = 1;
|
|
contest->unk_1984.unk_17 = contest->unk_00.connectionCount;
|
|
|
|
contest->commTask = NULL;
|
|
contest->linkState = 0;
|
|
|
|
SysTask_Done(sysTask);
|
|
return;
|
|
}
|
|
}
|
|
|
|
BOOL Contest_SetUpLinkContest(Contest *contest)
|
|
{
|
|
if (CommSys_IsInitialized() == FALSE) {
|
|
return FALSE;
|
|
}
|
|
|
|
contest->isLinkContest = TRUE;
|
|
|
|
int connectionCount = CommSys_ConnectedCount();
|
|
int netID = CommSys_CurNetId();
|
|
|
|
{
|
|
int i;
|
|
TrainerInfo *connectedTrainerInfo;
|
|
|
|
for (i = 0; i < connectionCount; i++) {
|
|
connectedTrainerInfo = CommInfo_TrainerInfo(i);
|
|
GF_ASSERT(connectedTrainerInfo != NULL);
|
|
|
|
if (TrainerInfo_IsMainStoryCleared(connectedTrainerInfo) == FALSE) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i != connectionCount) {
|
|
contest->isGameCompleted = FALSE;
|
|
} else {
|
|
contest->isGameCompleted = TRUE;
|
|
}
|
|
|
|
for (i = 0; i < connectionCount; i++) {
|
|
connectedTrainerInfo = CommInfo_TrainerInfo(i);
|
|
GF_ASSERT(connectedTrainerInfo != NULL);
|
|
|
|
if (TrainerInfo_HasNationalDex(connectedTrainerInfo) == FALSE) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i != connectionCount) {
|
|
contest->isNatDexObtained = FALSE;
|
|
} else {
|
|
contest->isNatDexObtained = TRUE;
|
|
}
|
|
|
|
sub_020939E0(contest, contest->isGameCompleted, contest->isNatDexObtained);
|
|
|
|
for (i = 0; i < connectionCount; i++) {
|
|
connectedTrainerInfo = CommInfo_TrainerInfo(i);
|
|
|
|
if (TrainerInfo_GameCode(connectedTrainerInfo) == 0) {
|
|
contest->unk_15B++;
|
|
}
|
|
}
|
|
}
|
|
|
|
contest->unk_00.unk_114 = netID;
|
|
contest->unk_00.npcCount = CONTEST_NUM_PARTICIPANTS - connectionCount;
|
|
contest->unk_00.connectionCount = connectionCount;
|
|
contest->unk_00.playerContestantID = netID;
|
|
contest->unk_00.unk_115 = 110;
|
|
contest->unk_00.unk_112 = sub_02095A74(contest->unk_00.contestRank, TRUE);
|
|
|
|
sub_02095AF0(contest);
|
|
|
|
contest->commTask = SysTask_Start(sub_02093C6C, contest, 10);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Contest_IsCommTaskDone(Contest *contest)
|
|
{
|
|
return Contest_IsCommTaskDoneInternal(contest);
|
|
}
|
|
|
|
BOOL Contest_IsCommTaskDoneInternal(Contest *contest)
|
|
{
|
|
if (contest->commTask == NULL) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void sub_020944E8(Contest *contest)
|
|
{
|
|
GF_ASSERT(contest->commTask == NULL);
|
|
|
|
contest->linkState = 0;
|
|
contest->commTask = SysTask_Start(sub_0209451C, contest, 10);
|
|
}
|
|
|
|
static void sub_0209451C(SysTask *sysTask, void *param1)
|
|
{
|
|
Contest *contest = param1;
|
|
|
|
switch (contest->linkState) {
|
|
case 0:
|
|
CommTiming_StartSync(17);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 1:
|
|
if (CommTiming_IsSyncState(17) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (sub_02095B5C(contest, contest->unk_00.playerContestantID, contest->unk_00.unk_E8[contest->unk_00.playerContestantID]) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (contest->unk_568 >= contest->unk_00.connectionCount) {
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 4:
|
|
CommTiming_StartSync(18);
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
break;
|
|
case 5:
|
|
if (CommTiming_IsSyncState(18) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 6:
|
|
if (contest->unk_00.playerContestantID == contest->unk_00.unk_10C) {
|
|
if (sub_02095BEC(contest, contest->unk_00.unk_E8) == 1) {
|
|
contest->linkState++;
|
|
}
|
|
} else {
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
case 7:
|
|
if (contest->unk_568 > 0) {
|
|
contest->unk_568 = 0;
|
|
contest->linkState++;
|
|
}
|
|
break;
|
|
default:
|
|
contest->commTask = NULL;
|
|
contest->linkState = 0;
|
|
SysTask_Done(sysTask);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void Contest_BufferJudgeName(Contest *contest, int judgeID, StringTemplate *strTemplate, u32 idx)
|
|
{
|
|
StringTemplate_SetContestJudgeName(strTemplate, idx, contest->unk_00.unk_C0[judgeID].judgeNameMessageID);
|
|
}
|
|
|
|
void Contest_BufferContestantTrainerName(Contest *contest, int contestantEntryNum, StringTemplate *strTemplate, u32 idx)
|
|
{
|
|
int contestantID = Contest_ContestantEntryNumToContestantID(contestantEntryNum);
|
|
StringTemplate_SetString(strTemplate, idx, contest->unk_00.trainerNames[contestantID], contest->unk_00.trainerGenders[contestantID], 1, GAME_LANGUAGE);
|
|
}
|
|
|
|
void Contest_BufferMonNickname(Contest *contest, int contestantEntryNum, StringTemplate *strTemplate, u32 idx)
|
|
{
|
|
BoxPokemon *boxMon;
|
|
int contestantID = Contest_ContestantEntryNumToContestantID(contestantEntryNum);
|
|
boxMon = Pokemon_GetBoxPokemon(contest->unk_00.contestMons[contestantID]);
|
|
|
|
StringTemplate_SetNickname(strTemplate, idx, boxMon);
|
|
}
|
|
|
|
void Contest_BufferContestRank(Contest *contest, StringTemplate *strTemplate, u32 idx)
|
|
{
|
|
u32 contestRankMessageID = Contest_GetContestRankTitleMessageID(contest->unk_00.contestRank, contest->unk_00.competitionType, contest->isLinkContest);
|
|
StringTemplate_SetContestRankName(strTemplate, idx, contestRankMessageID);
|
|
}
|
|
|
|
void Contest_BufferContestType(Contest *contest, StringTemplate *strTemplate, u32 idx)
|
|
{
|
|
u32 contestTypeMessageID = Contest_GetFullContestTypeMessageID(contest->unk_00.contestType, contest->unk_00.competitionType);
|
|
StringTemplate_SetContestTypeName(strTemplate, idx, contestTypeMessageID);
|
|
}
|
|
|
|
void Contest_BufferWinningContestantTrainerName(Contest *contest, StringTemplate *strTemplate, u32 param2)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
if (contest->unk_00.unk_118[i].contestPlacement == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
int contestantID = i;
|
|
int contestantEntryNum = Contest_ContestantIDToContestantEntryNum(contestantID);
|
|
|
|
Contest_BufferContestantTrainerName(contest, contestantEntryNum, strTemplate, param2);
|
|
}
|
|
|
|
void Contest_BufferWinningContestantMonName(Contest *contest, StringTemplate *strTemplate, u32 idx)
|
|
{
|
|
int contestantID, contestantEntryNum;
|
|
int i;
|
|
|
|
for (i = 0; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
if (contest->unk_00.unk_118[i].contestPlacement == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
contestantID = i;
|
|
contestantEntryNum = Contest_ContestantIDToContestantEntryNum(contestantID);
|
|
|
|
Contest_BufferMonNickname(contest, contestantEntryNum, strTemplate, idx);
|
|
}
|
|
|
|
BOOL Contest_True(Contest *contest)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
void Contest_StartCommSync(Contest *contest, u8 syncNo)
|
|
{
|
|
if (contest->isLinkContest == FALSE) {
|
|
return;
|
|
}
|
|
|
|
CommTiming_StartSync(syncNo);
|
|
}
|
|
|
|
BOOL Contest_IsSyncState(Contest *contest, u8 syncState)
|
|
{
|
|
if (contest->isLinkContest == FALSE) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (CommTiming_IsSyncState(syncState) == TRUE) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
int Contest_GetPlayerContestPlacement(Contest *contest)
|
|
{
|
|
return contest->unk_00.unk_118[contest->unk_00.playerContestantID].contestPlacement;
|
|
}
|
|
|
|
int Contest_GetWinningContestantEntryNum(Contest *contest)
|
|
{
|
|
int contestantID;
|
|
|
|
for (contestantID = 0; contestantID < CONTEST_NUM_PARTICIPANTS; contestantID++) {
|
|
if (contest->unk_00.unk_118[contestantID].contestPlacement == 0) {
|
|
return Contest_ContestantIDToContestantEntryNum(contestantID);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Contest_GetPlayerContestantEntryNum(Contest *contest)
|
|
{
|
|
return Contest_ContestantIDToContestantEntryNum(contest->unk_00.playerContestantID);
|
|
}
|
|
|
|
int Contest_GetContestantObjEventGFX(Contest *contest, int contestantEntryNum)
|
|
{
|
|
int contestantID = Contest_ContestantEntryNumToContestantID(contestantEntryNum);
|
|
int contestantObjEventGFX = contest->unk_00.contestantObjEventGFX[contestantID];
|
|
|
|
return contestantObjEventGFX;
|
|
}
|
|
|
|
int Contest_GetContestantMonContestFame(Contest *contest, int contestantEntryNum)
|
|
{
|
|
int ContestantID = Contest_ContestantEntryNumToContestantID(contestantEntryNum);
|
|
return contest->unk_00.monContestFame[ContestantID];
|
|
}
|
|
|
|
int Contest_GetContestMode(Contest *contest)
|
|
{
|
|
if (contest->isLinkContest == TRUE) {
|
|
return CONTEST_MODE_LINK;
|
|
}
|
|
|
|
if (Contest_IsPracticeCompetition(contest) == TRUE) {
|
|
return CONTEST_MODE_PRACTICE;
|
|
}
|
|
|
|
return CONTEST_MODE_OFFICIAL;
|
|
}
|
|
|
|
void Contest_GetContestInfo(Contest *contest, u16 *contestRank, u16 *contestType, u16 *competitionType, u16 *monPartySlot)
|
|
{
|
|
*contestRank = contest->unk_00.contestRank;
|
|
*contestType = contest->unk_00.contestType;
|
|
*competitionType = contest->unk_00.competitionType;
|
|
*monPartySlot = contest->monPartySlot;
|
|
}
|
|
|
|
void Contest_LockAutoScrollForLinkContests(Contest *contest)
|
|
{
|
|
SetLockTextWithAutoScroll(contest->isLinkContest);
|
|
}
|
|
|
|
void Contest_LockTextSpeed(Contest *contest)
|
|
{
|
|
LockTextSpeed();
|
|
}
|
|
|
|
BOOL Contest_CheckPlayerMonHasRibbon(Contest *contest)
|
|
{
|
|
u32 monDataRibbon = CalcMonDataRibbon(contest->unk_00.contestRank, contest->unk_00.contestType);
|
|
|
|
if (Pokemon_GetValue(contest->playerMon, monDataRibbon, NULL) == FALSE) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void Contest_SetRibbonName(Contest *contest, StringTemplate *string, u32 idx, int unused)
|
|
{
|
|
u32 ribbonID, ribbon;
|
|
|
|
switch (contest->unk_00.contestType) {
|
|
case CONTEST_TYPE_COOL:
|
|
ribbonID = RIBBON_COOL + contest->unk_00.contestRank;
|
|
break;
|
|
case CONTEST_TYPE_BEAUTY:
|
|
ribbonID = RIBBON_BEAUTY + contest->unk_00.contestRank;
|
|
break;
|
|
case CONTEST_TYPE_CUTE:
|
|
ribbonID = RIBBON_CUTE + contest->unk_00.contestRank;
|
|
break;
|
|
case CONTEST_TYPE_SMART:
|
|
ribbonID = RIBBON_SMART + contest->unk_00.contestRank;
|
|
break;
|
|
case CONTEST_TYPE_TOUGH:
|
|
ribbonID = RIBBON_TOUGH + contest->unk_00.contestRank;
|
|
break;
|
|
default:
|
|
GF_ASSERT(FALSE);
|
|
return;
|
|
}
|
|
|
|
ribbon = Ribbon_GetData(ribbonID, RIBBON_DATA_NAME_ID);
|
|
StringTemplate_SetRibbonName(string, idx, ribbon);
|
|
}
|
|
|
|
u32 Contest_CalcFirstTimeVictoryAccessoryReward(Contest *contest)
|
|
{
|
|
u32 accessoryID = ACCESSORY_COUNT;
|
|
|
|
if (contest->unk_00.unk_118[contest->unk_00.playerContestantID].contestPlacement > 0) {
|
|
return 0xffff;
|
|
}
|
|
|
|
switch (contest->unk_00.contestType) {
|
|
case CONTEST_TYPE_COOL:
|
|
switch (contest->unk_00.contestRank) {
|
|
case CONTEST_RANK_NORMAL:
|
|
accessoryID = ACCESSORY_RED_BARRETTE;
|
|
break;
|
|
case CONTEST_RANK_GREAT:
|
|
accessoryID = ACCESSORY_RED_BALLOONS;
|
|
break;
|
|
case CONTEST_RANK_ULTRA:
|
|
accessoryID = ACCESSORY_TOP_HAT;
|
|
break;
|
|
case CONTEST_RANK_MASTER:
|
|
accessoryID = ACCESSORY_GOLD_PEDESTAL;
|
|
break;
|
|
}
|
|
break;
|
|
case CONTEST_TYPE_BEAUTY:
|
|
switch (contest->unk_00.contestRank) {
|
|
case CONTEST_RANK_NORMAL:
|
|
accessoryID = ACCESSORY_BLUE_BARRETTE;
|
|
break;
|
|
case CONTEST_RANK_GREAT:
|
|
accessoryID = ACCESSORY_BLUE_BALLOONS;
|
|
break;
|
|
case CONTEST_RANK_ULTRA:
|
|
accessoryID = ACCESSORY_SILK_VEIL;
|
|
break;
|
|
case CONTEST_RANK_MASTER:
|
|
accessoryID = ACCESSORY_GLASS_STAGE;
|
|
break;
|
|
}
|
|
break;
|
|
case CONTEST_TYPE_CUTE:
|
|
switch (contest->unk_00.contestRank) {
|
|
case CONTEST_RANK_NORMAL:
|
|
accessoryID = ACCESSORY_PINK_BARRETTE;
|
|
break;
|
|
case CONTEST_RANK_GREAT:
|
|
accessoryID = ACCESSORY_PINK_BALLOON;
|
|
break;
|
|
case CONTEST_RANK_ULTRA:
|
|
accessoryID = ACCESSORY_LACE_HEADDRESS;
|
|
break;
|
|
case CONTEST_RANK_MASTER:
|
|
accessoryID = ACCESSORY_FLOWER_STAGE;
|
|
break;
|
|
}
|
|
break;
|
|
case CONTEST_TYPE_SMART:
|
|
switch (contest->unk_00.contestRank) {
|
|
case CONTEST_RANK_NORMAL:
|
|
accessoryID = ACCESSORY_GREEN_BARRETTE;
|
|
break;
|
|
case CONTEST_RANK_GREAT:
|
|
accessoryID = ACCESSORY_GREEN_BALLOONS;
|
|
break;
|
|
case CONTEST_RANK_ULTRA:
|
|
accessoryID = ACCESSORY_PROFESSOR_HAT;
|
|
break;
|
|
case CONTEST_RANK_MASTER:
|
|
accessoryID = ACCESSORY_CUBE_STAGE;
|
|
break;
|
|
}
|
|
break;
|
|
case CONTEST_TYPE_TOUGH:
|
|
switch (contest->unk_00.contestRank) {
|
|
case CONTEST_RANK_NORMAL:
|
|
accessoryID = ACCESSORY_YELLOW_BARRETTE;
|
|
break;
|
|
case CONTEST_RANK_GREAT:
|
|
accessoryID = ACCESSORY_YELLOW_BALLOONS;
|
|
break;
|
|
case CONTEST_RANK_ULTRA:
|
|
accessoryID = ACCESSORY_HEROIC_HEADBAND;
|
|
break;
|
|
case CONTEST_RANK_MASTER:
|
|
accessoryID = ACCESSORY_AWARD_PODIUM;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
GF_ASSERT(accessoryID != ACCESSORY_COUNT);
|
|
|
|
ImageClips *imageClips = SaveData_GetImageClips(contest->saveData);
|
|
FashionCase *fashionCase = ImageClips_GetFashionCase(imageClips);
|
|
|
|
if (!FashionCase_CanFitAccessoryCount(fashionCase, accessoryID, 1)) {
|
|
return 0xffff;
|
|
}
|
|
|
|
return accessoryID;
|
|
}
|
|
|
|
void Contest_StartCameraFlashTask(Contest *contest, int contestantEntryNum)
|
|
{
|
|
ContestCameraFlashTask *cameraFlashTask;
|
|
|
|
GF_ASSERT(contest->cameraFlashTask == NULL);
|
|
|
|
cameraFlashTask = Heap_AllocAtEnd(HEAP_ID_FIELD1, sizeof(ContestCameraFlashTask));
|
|
MI_CpuClear8(cameraFlashTask, sizeof(ContestCameraFlashTask));
|
|
cameraFlashTask->contestantID = Contest_ContestantEntryNumToContestantID(contestantEntryNum);
|
|
|
|
int varianceIndex = contest->unk_00.unk_FC[cameraFlashTask->contestantID] & 1;
|
|
|
|
if (contest->isLinkContest == TRUE) {
|
|
cameraFlashTask->cameraFlashFrameDelays = sLinkMasterRankCameraFrameDelays[varianceIndex];
|
|
} else {
|
|
switch (contest->unk_00.contestRank) {
|
|
case CONTEST_RANK_NORMAL:
|
|
cameraFlashTask->cameraFlashFrameDelays = sNormalRankCameraFrameDelays[varianceIndex];
|
|
break;
|
|
case CONTEST_RANK_GREAT:
|
|
cameraFlashTask->cameraFlashFrameDelays = sGreatRankCameraFrameDelays[varianceIndex];
|
|
break;
|
|
case CONTEST_RANK_ULTRA:
|
|
cameraFlashTask->cameraFlashFrameDelays = sUltraRankCameraFrameDelays[varianceIndex];
|
|
break;
|
|
case CONTEST_RANK_MASTER:
|
|
default:
|
|
cameraFlashTask->cameraFlashFrameDelays = sLinkMasterRankCameraFrameDelays[varianceIndex];
|
|
break;
|
|
}
|
|
}
|
|
|
|
cameraFlashTask->sysTask = SysTask_Start(SysTask_DoContestCameraFlash, contest, 100);
|
|
contest->cameraFlashTask = cameraFlashTask;
|
|
}
|
|
|
|
BOOL Contest_CameraFlashTaskDone(Contest *contest)
|
|
{
|
|
return contest->cameraFlashTask == NULL;
|
|
}
|
|
|
|
static void SysTask_DoContestCameraFlash(SysTask *sysTask, void *contestParam)
|
|
{
|
|
Contest *contest = contestParam;
|
|
ContestCameraFlashTask *cameraFlashTask = contest->cameraFlashTask;
|
|
|
|
if (BrightnessController_IsTransitionComplete(BRIGHTNESS_MAIN_SCREEN) == FALSE) {
|
|
return;
|
|
}
|
|
|
|
switch (cameraFlashTask->state) {
|
|
case 0:
|
|
cameraFlashTask->frameCounter++;
|
|
|
|
if (cameraFlashTask->frameCounter > cameraFlashTask->cameraFlashFrameDelays[cameraFlashTask->flashCounter]) {
|
|
BrightnessController_StartTransition(6, 0, 4, GX_BLEND_PLANEMASK_BG0 | GX_BLEND_PLANEMASK_BG1 | GX_BLEND_PLANEMASK_BG2 | GX_BLEND_PLANEMASK_BG3 | GX_BLEND_PLANEMASK_OBJ | GX_BLEND_PLANEMASK_BD, BRIGHTNESS_MAIN_SCREEN);
|
|
Sound_PlayEffect(SEQ_SE_DP_CON_014); // camera shutter sound
|
|
cameraFlashTask->flashCounter++;
|
|
cameraFlashTask->frameCounter = 0;
|
|
|
|
if (cameraFlashTask->cameraFlashFrameDelays[cameraFlashTask->flashCounter] == CAMERA_FLASH_FRAME_DELAY_ARRAY_TERMINATOR) {
|
|
cameraFlashTask->state++;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
Heap_Free(contest->cameraFlashTask);
|
|
contest->cameraFlashTask = NULL;
|
|
SysTask_Done(sysTask);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void sub_02094BB4(Contest *contest, int *destWinningContestantEntryNum, BOOL *destIsLinkContest, int *param3, BOOL *destIsPracticeCompetition, int *param5)
|
|
{
|
|
int winningContestantID;
|
|
int contestantID;
|
|
|
|
for (contestantID = 0; contestantID < CONTEST_NUM_PARTICIPANTS; contestantID++) {
|
|
if (contest->unk_00.unk_118[contestantID].contestPlacement == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
winningContestantID = contestantID;
|
|
|
|
*destWinningContestantEntryNum = Contest_ContestantIDToContestantEntryNum(winningContestantID);
|
|
*destIsLinkContest = contest->isLinkContest;
|
|
|
|
if (winningContestantID >= contest->unk_00.connectionCount) {
|
|
*param3 = 1;
|
|
} else {
|
|
*param3 = 0;
|
|
}
|
|
|
|
*destIsPracticeCompetition = FALSE;
|
|
*param5 = 0;
|
|
|
|
switch (contest->unk_00.competitionType) {
|
|
case CONTEST_COMPETITION_PRACTICE_VISUAL:
|
|
case CONTEST_COMPETITION_PRACTICE_DANCE:
|
|
case CONTEST_COMPETITION_PRACTICE_ACTING:
|
|
*destIsPracticeCompetition = TRUE;
|
|
break;
|
|
case CONTEST_COMPETITION_VISUAL:
|
|
case CONTEST_COMPETITION_DANCE:
|
|
case CONTEST_COMPETITION_ACTING:
|
|
*param5 = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Contest_EndContest(Contest *contest, SaveData *saveData, u32 mapID, JournalEntry *journalEntry)
|
|
{
|
|
BOOL ribbonWon = FALSE;
|
|
|
|
switch (contest->unk_00.competitionType) {
|
|
case CONTEST_COMPETITION_PRACTICE_VISUAL:
|
|
case CONTEST_COMPETITION_VISUAL:
|
|
case CONTEST_COMPETITION_PRACTICE_DANCE:
|
|
case CONTEST_COMPETITION_DANCE:
|
|
case CONTEST_COMPETITION_PRACTICE_ACTING:
|
|
case CONTEST_COMPETITION_ACTING:
|
|
return;
|
|
}
|
|
|
|
if (contest->isLinkContest == FALSE) {
|
|
VarsFlags *varsFlags = SaveData_GetVarsFlags(contest->saveData);
|
|
|
|
if (contest->unk_00.competitionType == CONTEST_COMPETITION_LINK_OR_OFFICIAL && contest->unk_00.contestRank >= CONTEST_RANK_MASTER && Contest_GetPlayerContestPlacement(contest) == 0
|
|
&& SystemFlag_CheckContestMaster(varsFlags, contest->unk_00.contestType) == FALSE) {
|
|
SystemFlag_SetContestMaster(varsFlags, contest->unk_00.contestType);
|
|
}
|
|
|
|
if (Contest_GetPlayerContestPlacement(contest) == 0) {
|
|
u8 v3 = 1;
|
|
int monDataRibbon = CalcMonDataRibbon(contest->unk_00.contestRank, contest->unk_00.contestType);
|
|
|
|
if (Pokemon_GetValue(contest->playerMon, monDataRibbon, NULL) == 0) {
|
|
ribbonWon = TRUE;
|
|
}
|
|
|
|
Pokemon_SetValue(contest->playerMon, monDataRibbon, &v3);
|
|
sub_0206DDB8(contest->saveData, contest->playerMon, monDataRibbon);
|
|
}
|
|
|
|
TVBroadcast *broadcast = SaveData_GetTVBroadcast(contest->saveData);
|
|
TVBroadcast_SetContestHallShowInfo(broadcast, contest->playerMon, contest->unk_00.contestType, contest->unk_00.contestRank, contest->unk_00.unk_118[contest->unk_00.playerContestantID].contestPlacement + 1);
|
|
|
|
GameRecords *gameRecords = SaveData_GetGameRecords(contest->saveData);
|
|
GameRecords_IncrementRecordValue(gameRecords, RECORD_SUPER_CONTEST_PARTICIPATIONS);
|
|
|
|
if (Contest_GetPlayerContestPlacement(contest) == 0) {
|
|
GameRecords_IncrementRecordValue(gameRecords, RECORD_OFFICIAL_CONTEST_WINS);
|
|
GameRecords_IncrementTrainerScore(gameRecords, TRAINER_SCORE_EVENT_WIN_OFFICIAL_CONTEST);
|
|
}
|
|
|
|
if (ribbonWon == TRUE) {
|
|
GameRecords_IncrementRecordValue(gameRecords, RECORD_RIBBONS_WON);
|
|
}
|
|
|
|
Pokedex *pokedex = SaveData_GetPokedex(contest->saveData);
|
|
|
|
for (int i = contest->unk_00.connectionCount; i < CONTEST_NUM_PARTICIPANTS; i++) {
|
|
Pokedex_Encounter(pokedex, contest->unk_00.contestMons[i]);
|
|
}
|
|
} else {
|
|
LinkContestRecords_IncrementSavaData(contest->saveData, contest->unk_00.contestType, contest->unk_00.unk_118[contest->unk_00.playerContestantID].contestPlacement);
|
|
|
|
GameRecords *records = SaveData_GetGameRecords(contest->saveData);
|
|
GameRecords_IncrementRecordValue(records, RECORD_LINK_CONTEST_PARTICIPATIONS);
|
|
|
|
if (Contest_GetPlayerContestPlacement(contest) == 0) {
|
|
GameRecords_IncrementRecordValue(records, RECORD_LINK_CONTEST_WINS);
|
|
GameRecords_IncrementTrainerScore(records, TRAINER_SCORE_EVENT_WIN_LINK_CONTEST);
|
|
}
|
|
|
|
void *journalEntryOnlineEvent = JournalEntry_CreateEventPlacedInContest(contest->unk_00.unk_118[contest->unk_00.playerContestantID].contestPlacement + 1, HEAP_ID_FIELD2);
|
|
JournalEntry *unused = SaveData_GetJournal(contest->saveData);
|
|
|
|
JournalEntry_SaveData(journalEntry, journalEntryOnlineEvent, JOURNAL_ONLINE_EVENT);
|
|
}
|
|
|
|
if (Contest_GetPlayerContestPlacement(contest) == 0) {
|
|
ImageClips *imageClips = SaveData_GetImageClips(contest->saveData);
|
|
UnkStruct_02029C88 *v12 = sub_02029CD0(imageClips, contest->unk_00.contestType);
|
|
|
|
sub_0202A25C(v12);
|
|
sub_0202A390(v12, contest->unk_00.unk_E8[contest->unk_00.playerContestantID]);
|
|
sub_0202A240(v12);
|
|
}
|
|
|
|
if (Contest_GetPlayerContestPlacement(contest) == 0) {
|
|
Pokemon_UpdateFriendship(contest->playerMon, FRIENDSHIP_EVENT_CONTEST_WIN, mapID);
|
|
}
|
|
}
|
|
|
|
static void Contest_SetLCRNGSeed(Contest *contest)
|
|
{
|
|
LCRNG_SetSeed((GetSecondsSinceMidnight() * (LCRNG_GetSeed() + 10)) & 0xffff);
|
|
}
|
|
|
|
u16 Contest_GetRNGNext(Contest *contest)
|
|
{
|
|
return LCRNG_Next();
|
|
}
|
|
|
|
u16 Contest_GetSeededRNGNext(u32 seed, u32 *destRNGVal)
|
|
{
|
|
u32 rngVal = ARNG_Next(seed);
|
|
*destRNGVal = rngVal;
|
|
|
|
return rngVal / LCRNG_DIVISOR;
|
|
}
|
|
|
|
static void sub_02094EB4(Contest *contest, int contestantID, UnkStruct_ov6_02248DD8 *param2)
|
|
{
|
|
param2->trainerGender = contest->unk_00.trainerGenders[contestantID];
|
|
param2->unk_01 = contest->unk_00.unk_FC[contestantID];
|
|
param2->monContestFame = contest->unk_00.monContestFame[contestantID];
|
|
param2->contestantObjEventGFX = contest->unk_00.contestantObjEventGFX[contestantID];
|
|
}
|