diff options
author | GriffinR <griffin.g.richards@gmail.com> | 2020-06-18 18:01:32 -0400 |
---|---|---|
committer | GriffinR <griffin.g.richards@gmail.com> | 2020-06-18 18:01:32 -0400 |
commit | d2a760afdbb4555e0b831598491e5fe1f410251d (patch) | |
tree | e527b0fa70a20e2f9aadd12cc77892985c8b0537 /src/contest_util.c | |
parent | 24569583e49e66fefd0aeaeac68d2ba9bf206145 (diff) |
Rename contest_link_80FC4F4, 80F57C4, and 81D9DE4
Diffstat (limited to 'src/contest_util.c')
-rw-r--r-- | src/contest_util.c | 2533 |
1 files changed, 2533 insertions, 0 deletions
diff --git a/src/contest_util.c b/src/contest_util.c new file mode 100644 index 000000000..22074e1a1 --- /dev/null +++ b/src/contest_util.c @@ -0,0 +1,2533 @@ +#include "global.h" +#include "malloc.h" +#include "battle.h" +#include "battle_gfx_sfx_util.h" +#include "bg.h" +#include "contest.h" +#include "contest_util.h" +#include "contest_link.h" +#include "data.h" +#include "decompress.h" +#include "dma3.h" +#include "event_data.h" +#include "field_specials.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "international_string_util.h" +#include "link.h" +#include "link_rfu.h" +#include "load_save.h" +#include "main.h" +#include "overworld.h" +#include "palette.h" +#include "pokedex.h" +#include "pokemon.h" +#include "pokemon_icon.h" +#include "random.h" +#include "save.h" +#include "scanline_effect.h" +#include "script.h" +#include "sound.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "text.h" +#include "trig.h" +#include "tv.h" +#include "util.h" +#include "window.h" +#include "constants/field_specials.h" +#include "constants/game_stat.h" +#include "constants/rgb.h" +#include "constants/songs.h" +#include "constants/tv.h" +#include "constants/vars.h" +#include "contest.h" + +enum { + SLIDING_TEXT_OFFSCREEN, + SLIDING_TEXT_ENTERING, + SLIDING_TEXT_ARRIVED, + SLIDING_TEXT_EXITING, +}; + +enum { + SLIDING_MON_ENTERED = 1, + SLIDING_MON_EXITED, +}; + +#define GET_CONTEST_WINNER_ID(i) { for ((i) = 0; (i) < CONTESTANT_COUNT && gContestFinalStandings[(i)] != 0; (i)++); } + +#define TAG_CONFETTI 3017 + +#define MAX_BAR_LENGTH 87 + +struct ContestResultsInternal +{ + u8 slidingTextBoxSpriteId; + u8 linkTextBoxSpriteId; + u8 showResultsTaskId; + u8 highlightWinnerTaskId; + u8 slidingTextBoxState; + u8 numStandingsPrinted; + u8 winnerMonSlidingState; + u8 confettiCount; + u8 winnerMonSpriteId; + bool8 destroyConfetti; + bool8 pointsFlashing; + s16 unkC[CONTESTANT_COUNT]; + u8 numBarsUpdating; +}; + +struct ContestMonResults +{ + int relativePreliminaryPoints; + int relativeRound2Points; + u32 barLengthPreliminary; + u32 barLengthRound2; + bool8 lostPoints; + u8 numStars; + u8 numHearts; +}; + +struct ContestResults +{ + struct ContestResultsInternal *data; + struct ContestMonResults (*monResults)[CONTESTANT_COUNT]; + u8 *unusedBg; // Allocated/freed, never used + u8 *tilemapBuffers[4]; + u8 *unused; // Allocated/freed, never used +}; + +static EWRAM_DATA struct ContestResults *sContestResults = NULL; + +static void LoadAllContestMonIconPalettes(void); +static void LoadContestResultsTilemaps(void); +static u8 GetNumPreliminaryPoints(u8, bool8); +static s8 GetNumRound2Points(u8, bool8); +static void AddContestTextPrinter(int, u8 *, int); +static void AllocContestResults(void); +static void FreeContestResults(void); +static void LoadAllContestMonIcons(u8, u8); +static void LoadContestResultSprites(void); +static void TryCreateWirelessSprites(void); +static void Task_StartShowContestResults(u8 taskId); +static void CB2_StartShowContestResults(void); +static void Task_ShowContestResults(u8); +static void CB2_ShowContestResults(void); +static void VBlankCB_ShowContestResults(void); +static void Task_SlideContestResultsBg(u8); +static void Task_WaitForLinkPartnersBeforeResults(u8); +static void sub_80F5F14(u8); +static void sub_80F5F30(u8); +static void Task_AnnouncePreliminaryResults(u8); +static void Task_FlashStarsAndHearts(u8); +static void Task_ShowPreliminaryResults(u8); +static void Task_AnnounceRound2Results(u8); +static void Task_ShowRound2Results(u8); +static void Task_AnnounceWinner(u8); +static void Task_DrawFinalStandingNumber(u8); +static void Task_StartHighlightWinnersBox(u8); +static void Task_HighlightWinnersBox(u8); +static void Task_ShowWinnerMonBanner(u8); +static void Task_SetSeenWinnerMon(u8); +static void Task_TryDisconnectLinkPartners(u8); +static void Task_WaitForLinkPartnersDisconnect(u8); +static void Task_TrySetContestInterviewData(u8); +static void Task_EndShowContestResults(u8); +static void CalculateContestantsResultData(void); +static void ShowLinkResultsTextBox(const u8 *); +static void HideLinkResultsTextBox(void); +static s32 DrawResultsTextWindow(const u8 *, u8); +static void StartTextBoxSlideIn(s16, u16, u16, u16); +static void UpdateContestResultBars(bool8, u8); +static void Task_UpdateContestResultBar(u8); +static void StartTextBoxSlideOut(u16); +static void BounceMonIconInBox(u8, u8); +static void Task_BounceMonIconInBox(u8); +static void SpriteCB_WinnerMonSlideIn(struct Sprite *); +static void SpriteCB_WinnerMonSlideOut(struct Sprite *); +static void Task_CreateConfetti(u8); +static void SpriteCB_TextBoxSlideIn(struct Sprite *); +static void SpriteCB_TextBoxSlideOut(struct Sprite *); +static void SpriteCB_EndTextBoxSlideIn(struct Sprite *); +static void sub_80F8508(u8); +static void sub_80F8568(u8); +static void sub_80F8584(u8); +static void sub_80F85A0(u8); +static void sub_80F85BC(u8); +static void sub_80F86B8(u8); +static void sub_80F878C(u8); +static void sub_80F87B4(u8); +static void SpriteCB_Confetti(struct Sprite *sprite); + +static const u16 sUnknown_0858D6B0[] = INCBIN_U16("graphics/unknown/unknown_58D6B0.gbapal"); +static const u8 sUnknown_0858D6D0[] = INCBIN_U8("graphics/unknown/unknown_58D6D0.4bpp"); +static const u16 sMiscBlank_Pal[] = INCBIN_U16("graphics/interface/blank.gbapal"); + +static const struct OamData sOamData_858D7F0 = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = SPRITE_SHAPE(64x32), + .x = 0, + .matrixNum = 0, + .size = SPRITE_SIZE(64x32), + .tileNum = 0, + .priority = 3, + .paletteNum = 2, + .affineParam = 0, +}; + +static const struct SpriteTemplate sSpriteTemplate_858D7F8 = +{ + .tileTag = 3009, + .paletteTag = 3009, + .oam = &sOamData_858D7F0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy +}; + +static const struct SpriteSheet sUnknown_0858D810[] = +{ + { .data = gMiscBlank_Gfx, .size = 0x400, .tag = 3009 }, + { .data = gMiscBlank_Gfx, .size = 0x400, .tag = 3010 }, + { .data = gMiscBlank_Gfx, .size = 0x400, .tag = 3011 }, + { .data = gMiscBlank_Gfx, .size = 0x400, .tag = 3012 }, + { .data = gMiscBlank_Gfx, .size = 0x400, .tag = 3013 }, + { .data = gMiscBlank_Gfx, .size = 0x400, .tag = 3014 }, + { .data = gMiscBlank_Gfx, .size = 0x400, .tag = 3015 }, + { .data = gMiscBlank_Gfx, .size = 0x400, .tag = 3016 }, +}; + +static const struct SpritePalette sUnknown_0858D850 = +{ + .data = sMiscBlank_Pal, + .tag = 3009, +}; + +static const struct OamData sOamData_Confetti = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = SPRITE_SHAPE(8x8), + .x = 0, + .matrixNum = 0, + .size = SPRITE_SIZE(8x8), + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct SpriteTemplate sSpriteTemplate_Confetti = +{ + .tileTag = TAG_CONFETTI, + .paletteTag = TAG_CONFETTI, + .oam = &sOamData_Confetti, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_Confetti +}; + +static const struct CompressedSpriteSheet sSpriteSheet_Confetti = +{ + .data = gConfetti_Gfx, + .size = 0x220, + .tag = TAG_CONFETTI +}; + + +static const struct CompressedSpritePalette sSpritePalette_Confetti = +{ + .data = gConfetti_Pal, + .tag = TAG_CONFETTI +}; + +static const struct BgTemplate sBgTemplates[] = +{ + { + .bg = 0, + .charBaseIndex = 0, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0, + }, + { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 24, + .screenSize = 0, + .paletteMode = 0, + .priority = 3, + .baseTile = 0, + }, + { + .bg = 2, + .charBaseIndex = 0, + .mapBaseIndex = 28, + .screenSize = 0, + .paletteMode = 0, + .priority = 3, + .baseTile = 0, + }, + { + .bg = 3, + .charBaseIndex = 0, + .mapBaseIndex = 26, + .screenSize = 0, + .paletteMode = 0, + .priority = 3, + .baseTile = 0, + } +}; + +static const struct WindowTemplate sWindowTemplates[] = +{ + { + .bg = 1, + .tilemapLeft = 7, + .tilemapTop = 4, + .width = 12, + .height = 2, + .paletteNum = 15, + .baseBlock = 770 + }, + { + .bg = 1, + .tilemapLeft = 7, + .tilemapTop = 7, + .width = 12, + .height = 2, + .paletteNum = 15, + .baseBlock = 794 + }, + { + .bg = 1, + .tilemapLeft = 7, + .tilemapTop = 10, + .width = 12, + .height = 2, + .paletteNum = 15, + .baseBlock = 818 + }, + { + .bg = 1, + .tilemapLeft = 7, + .tilemapTop = 13, + .width = 12, + .height = 2, + .paletteNum = 15, + .baseBlock = 842 + }, + DUMMY_WIN_TEMPLATE, +}; + +static const struct OamData sUnknown_0858D8C0 = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = SPRITE_SHAPE(16x16), + .x = 0, + .matrixNum = 0, + .size = SPRITE_SIZE(16x16), + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + + +static const struct SpriteTemplate sSpriteTemplate_858D8C8 = +{ + .tileTag = 22222, + .paletteTag = 0, + .oam = &sUnknown_0858D8C0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy +}; + +static const struct SpriteSheet sUnknown_0858D8E0 = +{ + .data = gMiscBlank_Gfx, + .size = 0x200, + .tag = 22222 +}; + +static const u8 sContestLinkTextColors[4] = {TEXT_COLOR_WHITE, TEXT_DYNAMIC_COLOR_6, TEXT_DYNAMIC_COLOR_5}; + + +static void InitContestResultsDisplay(void) +{ + int i; + + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP); + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); + for (i = 0; i < (int)ARRAY_COUNT(sContestResults->tilemapBuffers); i++) + SetBgTilemapBuffer(i, sContestResults->tilemapBuffers[i]); + + InitWindows(sWindowTemplates); + DeactivateAllTextPrinters(); + SetGpuReg(REG_OFFSET_MOSAIC, 0); + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG1 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR); + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN0V, 0); + SetGpuReg(REG_OFFSET_WIN1H, 0); + SetGpuReg(REG_OFFSET_WIN1V, 0); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG3HOFS, 0); + SetGpuReg(REG_OFFSET_BG3VOFS, 0); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_WIN1_ON | DISPCNT_OBJWIN_ON); + gBattle_BG0_X = 0; + gBattle_BG0_Y = 0; + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + gBattle_BG2_X = 0; + gBattle_BG2_Y = 0; + gBattle_BG3_X = 0; + gBattle_BG3_Y = 0; + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + gBattle_WIN1H = 0; + gBattle_WIN1V = 0; +} + +static void LoadContestResultsBgGfx(void) +{ + int i, j; + s8 numStars, round2Points; + u16 tile1, tile2; + + LZDecompressVram(gContestResults_Gfx, (void *)BG_CHAR_ADDR(0)); + CopyToBgTilemapBuffer(3, gUnknown_08C1A12C, 0, 0); + CopyToBgTilemapBuffer(2, gUnknown_08C1A000, 0, 0); + CopyToBgTilemapBuffer(0, gUnknown_08C19EEC, 0, 0); + LoadContestResultsTilemaps(); + LoadCompressedPalette(gContestResults_Pal, 0, 0x200); + LoadPalette(sUnknown_0858D6B0, 0xF0, 0x20); + + for (i = 0; i < CONTESTANT_COUNT; i++) + { + numStars = GetNumPreliminaryPoints(i, TRUE); + round2Points = GetNumRound2Points(i, TRUE); + for (j = 0; j < 10; j++) + { + tile1 = 0x60B2; + if (j < numStars) + tile1 += 2; + + // Abs of round2Points is number of hearts + if (j < abs(round2Points)) + { + tile2 = 0x60A4; + if (round2Points < 0) + tile2 += 2; + } + else + { + tile2 = 0x60A2; + } + + FillBgTilemapBufferRect_Palette0(1, tile1, j + 19, i * 3 + 5, 1, 1); + FillBgTilemapBufferRect_Palette0(1, tile2, j + 19, i * 3 + 6, 1, 1); + } + } + + CopyBgTilemapBufferToVram(0); + CopyBgTilemapBufferToVram(1); + CopyBgTilemapBufferToVram(2); + CopyBgTilemapBufferToVram(3); + ShowBg(0); + ShowBg(1); + ShowBg(2); + ShowBg(3); +} + +static void LoadContestMonName(u8 monIndex) +{ + struct ContestPokemon *mon = &gContestMons[monIndex]; + u8 *str = gDisplayedStringBattle; + if (monIndex == gContestPlayerMonIndex) + str = StringCopy(gDisplayedStringBattle, gText_ColorDarkGrey); + + StringCopy(str, mon->nickname); + AddContestTextPrinter(monIndex, gDisplayedStringBattle, 0); + StringCopy(str, gText_Slash); + StringAppend(str, mon->trainerName); + AddContestTextPrinter(monIndex, gDisplayedStringBattle, 50); +} + +static void LoadAllContestMonNames(void) +{ + int i; + + for (i = 0; i < CONTESTANT_COUNT; i++) + LoadContestMonName(i); + + CopyBgTilemapBufferToVram(1); +} + +static void CB2_StartShowContestResults(void) +{ + gPaletteFade.bufferTransferDisabled = TRUE; + SetVBlankCallback(NULL); + AllocContestResults(); + InitContestResultsDisplay(); + ScanlineEffect_Clear(); + ResetPaletteFade(); + ResetSpriteData(); + ResetTasks(); + FreeAllSpritePalettes(); + LoadContestResultsBgGfx(); + LoadAllContestMonIconPalettes(); + LoadAllContestMonIcons(0, TRUE); + LoadAllContestMonNames(); + memset(sContestResults->data, 0, sizeof(*sContestResults->data)); + memset(sContestResults->monResults, 0, sizeof(*sContestResults->monResults)); + LoadContestResultSprites(); + TryCreateWirelessSprites(); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); + gPaletteFade.bufferTransferDisabled = FALSE; + sContestResults->data->showResultsTaskId = CreateTask(Task_ShowContestResults, 5); + SetMainCallback2(CB2_ShowContestResults); + gBattle_WIN1H = 0x00F0; + gBattle_WIN1V = 0x80A0; + CreateTask(Task_SlideContestResultsBg, 20); + CalculateContestantsResultData(); + if (gLinkContestFlags & LINK_CONTEST_FLAG_IS_WIRELESS) + gPaletteFade.bufferTransferDisabled = TRUE; + else + PlayBGM(MUS_CON_K); + + SetVBlankCallback(VBlankCB_ShowContestResults); +} + +static void CB2_ShowContestResults(void) +{ + AnimateSprites(); + BuildOamBuffer(); + RunTasks(); + UpdatePaletteFade(); + CopyBgTilemapBufferToVram(1); + CopyBgTilemapBufferToVram(2); +} + +static void VBlankCB_ShowContestResults(void) +{ + SetGpuReg(REG_OFFSET_BG0HOFS, gBattle_BG0_X); + SetGpuReg(REG_OFFSET_BG0VOFS, gBattle_BG0_Y); + SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); + SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); + SetGpuReg(REG_OFFSET_BG2HOFS, gBattle_BG2_X); + SetGpuReg(REG_OFFSET_BG2VOFS, gBattle_BG2_Y); + SetGpuReg(REG_OFFSET_BG3HOFS, gBattle_BG3_X); + SetGpuReg(REG_OFFSET_BG3VOFS, gBattle_BG3_Y); + SetGpuReg(REG_OFFSET_WIN0H, gBattle_WIN0H); + SetGpuReg(REG_OFFSET_WIN0V, gBattle_WIN0V); + SetGpuReg(REG_OFFSET_WIN1H, gBattle_WIN1H); + SetGpuReg(REG_OFFSET_WIN1V, gBattle_WIN1V); + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); + ScanlineEffect_InitHBlankDmaTransfer(); +} + +#define tState data[0] +#define tTimer data[1] +#define tCounter data[2] + +static void Task_ShowContestResults(u8 taskId) +{ + u16 var; + + if (gLinkContestFlags & LINK_CONTEST_FLAG_IS_LINK) + { + switch (gTasks[taskId].tState) + { + case 0: + SaveLinkContestResults(); + if (gContestFinalStandings[gContestPlayerMonIndex] == 0) + { + IncrementGameStat(GAME_STAT_WON_LINK_CONTEST); + gSpecialVar_0x8005 = TVSHOW_CONTEST_LIVE_UPDATES; + InterviewBefore(); + if (gSpecialVar_Result != TRUE) + InterviewAfter(); + } + + TryGainNewFanFromCounter(FANCOUNTER_FINISHED_CONTEST); + sub_80DEDA8(gSpecialVar_ContestRank); + sub_80DEDA8(0xFE); + gUnknown_02039F5C = TRUE; + gUnknown_02039F5D = sub_80DEFA8(0xFE, 0); + var = VarGet(VAR_CONTEST_HALL_STATE); + VarSet(VAR_CONTEST_HALL_STATE, 0); + SetContinueGameWarpStatusToDynamicWarp(); + TrySavingData(SAVE_LINK); + ClearContinueGameWarpStatus2(); + VarSet(VAR_CONTEST_HALL_STATE, var); + gTasks[taskId].tState++; + break; + case 1: + gTasks[taskId].tState++; + if (!(gLinkContestFlags & LINK_CONTEST_FLAG_IS_WIRELESS)) + gTasks[taskId].tState = 100; + break; + case 2: + if (IsLinkTaskFinished()) + { + sub_800ADF8(); + gTasks[taskId].tState++; + } + return; + case 3: + if (IsLinkTaskFinished() == TRUE) + { + PlayBGM(MUS_CON_K); + gPaletteFade.bufferTransferDisabled = FALSE; + gTasks[taskId].tState++; + break; + } + return; + } + } + + if (!gPaletteFade.active) + { + gTasks[taskId].tState = 0; + if (gLinkContestFlags & LINK_CONTEST_FLAG_IS_LINK) + { + ShowLinkResultsTextBox(gText_CommunicationStandby); + gTasks[taskId].func = Task_WaitForLinkPartnersBeforeResults; + } + else + { + IncrementGameStat(GAME_STAT_ENTERED_CONTEST); + if (gContestFinalStandings[gContestPlayerMonIndex] == 0) + IncrementGameStat(GAME_STAT_WON_CONTEST); + + sub_80DEDA8(gSpecialVar_ContestRank); + sub_80DEDA8(0xFE); + gUnknown_02039F5C = TRUE; + gUnknown_02039F5D = sub_80DEFA8(0xFE, 0); + TryGainNewFanFromCounter(FANCOUNTER_FINISHED_CONTEST); + gTasks[taskId].func = Task_AnnouncePreliminaryResults; + } + } +} + +static void Task_WaitForLinkPartnersBeforeResults(u8 taskId) +{ + if (gReceivedRemoteLinkPlayers) + { + CreateTask(sub_80F5F14, 0); + gTasks[taskId].func = TaskDummy; + } +} + +static void sub_80F5F14(u8 taskId) +{ + SetTaskFuncWithFollowupFunc(taskId, sub_80FC998, sub_80F5F30); +} + +static void sub_80F5F30(u8 taskId) +{ + if (IsLinkTaskFinished()) + { + DestroyTask(taskId); + gTasks[sContestResults->data->showResultsTaskId].func = Task_AnnouncePreliminaryResults; + HideLinkResultsTextBox(); + } +} + +static void Task_AnnouncePreliminaryResults(u8 taskId) +{ + s16 x; + + if (gTasks[taskId].tState == 0) + { + CreateTask(Task_FlashStarsAndHearts, 20); + x = DrawResultsTextWindow(gText_AnnouncingResults, sContestResults->data->slidingTextBoxSpriteId); + StartTextBoxSlideIn(x, 144, 120, 1088); + gTasks[taskId].tState++; + } + else if (gTasks[taskId].tState == 1) + { + // Wait for "Announcing Results" text to leave + if (sContestResults->data->slidingTextBoxState == SLIDING_TEXT_OFFSCREEN) + { + gTasks[taskId].tTimer = 0; + gTasks[taskId].tState++; + } + } + else if (gTasks[taskId].tState == 2) + { + if (++gTasks[taskId].tTimer == 21) + { + gTasks[taskId].tTimer = 0; + gTasks[taskId].tState++; + } + } + else if (gTasks[taskId].tState == 3) + { + x = DrawResultsTextWindow(gText_PreliminaryResults, sContestResults->data->slidingTextBoxSpriteId); + StartTextBoxSlideIn(x, 144, -1, 1088); + gTasks[taskId].tState++; + } + else if (gTasks[taskId].tState == 4) + { + if (sContestResults->data->slidingTextBoxState == SLIDING_TEXT_ARRIVED) + { + gTasks[taskId].tState = 0; + gTasks[taskId].func = Task_ShowPreliminaryResults; + } + } +} + +static void Task_ShowPreliminaryResults(u8 taskId) +{ + switch (gTasks[taskId].tState) + { + case 0: + if (!sContestResults->data->pointsFlashing) + { + UpdateContestResultBars(FALSE, gTasks[taskId].tCounter++); + if (sContestResults->data->numBarsUpdating == 0) + gTasks[taskId].tState = 2; + else + gTasks[taskId].tState++; + } + break; + case 1: + if (sContestResults->data->numBarsUpdating == 0) + gTasks[taskId].tState = 0; + break; + case 2: + StartTextBoxSlideOut(1088); + gTasks[taskId].tState = 0; + gTasks[taskId].tCounter = 0; + gTasks[taskId].func = Task_AnnounceRound2Results; + break; + } +} + +static void Task_AnnounceRound2Results(u8 taskId) +{ + s16 x; + + if (sContestResults->data->slidingTextBoxState == SLIDING_TEXT_OFFSCREEN) + { + if (++gTasks[taskId].tTimer == 21) + { + gTasks[taskId].tTimer = 0; + x = DrawResultsTextWindow(gText_Round2Results, sContestResults->data->slidingTextBoxSpriteId); + StartTextBoxSlideIn(x, 144, -1, 1088); + } + } + else if (sContestResults->data->slidingTextBoxState == SLIDING_TEXT_ARRIVED) + { + gTasks[taskId].func = Task_ShowRound2Results; + } +} + +static void Task_ShowRound2Results(u8 taskId) +{ + switch (gTasks[taskId].tState) + { + case 0: + if (!sContestResults->data->pointsFlashing) + { + UpdateContestResultBars(TRUE, gTasks[taskId].tCounter++); + if (sContestResults->data->numBarsUpdating == 0) + gTasks[taskId].tState = 2; + else + gTasks[taskId].tState++; + } + break; + case 1: + if (sContestResults->data->numBarsUpdating == 0) + gTasks[taskId].tState = 0; + break; + case 2: + StartTextBoxSlideOut(1088); + gTasks[taskId].tState = 0; + gTasks[taskId].func = Task_AnnounceWinner; + break; + } +} + +// Task data for Task_DrawFinalStandingNumber +#define tFinalStanding data[0] +#define tMonIndex data[1] + +static void Task_AnnounceWinner(u8 taskId) +{ + int i; + switch (gTasks[taskId].tState) + { + case 0: + if (sContestResults->data->slidingTextBoxState == SLIDING_TEXT_OFFSCREEN) + gTasks[taskId].tState++; + break; + case 1: + if (++gTasks[taskId].tTimer == 31) + { + gTasks[taskId].tTimer = 0; + gTasks[taskId].tState++; + } + break; + case 2: + for (i = 0; i < CONTESTANT_COUNT; i++) + { + u8 newTaskId = CreateTask(Task_DrawFinalStandingNumber, 10); + gTasks[newTaskId].tFinalStanding = gContestFinalStandings[i]; + gTasks[newTaskId].tMonIndex = i; + } + gTasks[taskId].tState++; + break; + case 3: + if (sContestResults->data->numStandingsPrinted == CONTESTANT_COUNT) + { + if (++gTasks[taskId].tTimer == 31) + { + gTasks[taskId].tTimer = 0; + CreateTask(Task_StartHighlightWinnersBox, 10); + gTasks[taskId].tState++; + GET_CONTEST_WINNER_ID(i); + BounceMonIconInBox(i, 14); + } + } + break; + case 4: + if (++gTasks[taskId].tTimer == 21) + { + u8 winnerTextBuffer[100]; + s16 x; + gTasks[taskId].tTimer = 0; + GET_CONTEST_WINNER_ID(i); + StringCopy(gStringVar1, gContestMons[i].trainerName); + sub_81DB5AC(gStringVar1); + StringCopy(gStringVar2, gContestMons[i].nickname); + StringExpandPlaceholders(winnerTextBuffer, gText_ContestantsMonWon); + x = DrawResultsTextWindow(winnerTextBuffer, sContestResults->data->slidingTextBoxSpriteId); + StartTextBoxSlideIn(x, 144, -1, 1088); + gTasks[taskId].tState++; + } + break; + case 5: + gTasks[taskId].tState = 0; + gTasks[taskId].func = Task_ShowWinnerMonBanner; + break; + } +} + +static void Task_ShowWinnerMonBanner(u8 taskId) +{ + int i; + u8 spriteId; + u16 species; + u32 otId; + u32 personality; + const struct CompressedSpritePalette *pokePal; + + switch (gTasks[taskId].tState) + { + case 0: + gBattle_WIN0H = 0x00F0; + gBattle_WIN0V = 0x5050; + + GET_CONTEST_WINNER_ID(i); + species = gContestMons[i].species; + personality = gContestMons[i].personality; + otId = gContestMons[i].otId; + if (i == gContestPlayerMonIndex) + { + HandleLoadSpecialPokePic_2( + &gMonFrontPicTable[species], + gMonSpritesGfxPtr->sprites[1], + species, + personality); + } + else + { + HandleLoadSpecialPokePic_DontHandleDeoxys( + &gMonFrontPicTable[species], + gMonSpritesGfxPtr->sprites[1], + species, + personality); + } + + pokePal = GetMonSpritePalStructFromOtIdPersonality(species, otId, personality); + LoadCompressedSpritePalette(pokePal); + SetMultiuseSpriteTemplateToPokemon(species, B_POSITION_OPPONENT_LEFT); + gMultiuseSpriteTemplate.paletteTag = pokePal->tag; + spriteId = CreateSprite(&gMultiuseSpriteTemplate, 272, 80, 10); + gSprites[spriteId].data[1] = species; + gSprites[spriteId].oam.priority = 0; + gSprites[spriteId].callback = SpriteCB_WinnerMonSlideIn; + sContestResults->data->winnerMonSpriteId = spriteId; + LoadCompressedSpriteSheet(&sSpriteSheet_Confetti); + LoadCompressedSpritePalette(&sSpritePalette_Confetti); + CreateTask(Task_CreateConfetti, 10); + gTasks[taskId].tState++; + break; + case 1: + if (++gTasks[taskId].data[3] == 1) + { + u8 counter; + gTasks[taskId].data[3] = 0; + gTasks[taskId].tCounter += 2; + if (gTasks[taskId].tCounter > 32) + gTasks[taskId].tCounter = 32; + + counter = gTasks[taskId].tCounter; + gBattle_WIN0V = ((80 - counter) << 8) | (80 + counter); + if (counter == 32) + gTasks[taskId].tState++; + } + break; + case 2: + if (sContestResults->data->winnerMonSlidingState == SLIDING_MON_ENTERED) + gTasks[taskId].tState++; + break; + case 3: + if (++gTasks[taskId].tTimer == 121) + { + gTasks[taskId].tTimer = 0; + gSprites[sContestResults->data->winnerMonSpriteId].callback = SpriteCB_WinnerMonSlideOut; + gTasks[taskId].tState++; + } + break; + case 4: + if (sContestResults->data->winnerMonSlidingState == SLIDING_MON_EXITED) + { + u8 top = (gBattle_WIN0V >> 8); + top += 2; + if (top > 80) + top = 80; + + gBattle_WIN0V = (top << 8) | (160 - top); + if (top == 80) + gTasks[taskId].tState++; + } + break; + case 5: + if (sContestResults->data->winnerMonSlidingState == SLIDING_MON_EXITED) + { + sContestResults->data->destroyConfetti = TRUE; + gTasks[taskId].tState = 0; + gTasks[taskId].func = Task_SetSeenWinnerMon; + } + break; + } +} + +static void Task_SetSeenWinnerMon(u8 taskId) +{ + int i, nationalDexNum; + + if (JOY_NEW(A_BUTTON)) + { + if (!(gLinkContestFlags & LINK_CONTEST_FLAG_IS_LINK)) + { + for (i = 0; i < CONTESTANT_COUNT; i++) + { + nationalDexNum = SpeciesToNationalPokedexNum(gContestMons[i].species); + GetSetPokedexFlag(nationalDexNum, FLAG_SET_SEEN); + } + } + + gTasks[taskId].data[10] = 0; + gTasks[taskId].func = Task_TryDisconnectLinkPartners; + } +} + +static void Task_TryDisconnectLinkPartners(u8 taskId) +{ + if (gLinkContestFlags & LINK_CONTEST_FLAG_IS_LINK) + { + if (!gTasks[taskId].data[10]) + { + ShowLinkResultsTextBox(gText_CommunicationStandby); + sub_800AC34(); + gTasks[taskId].func = Task_WaitForLinkPartnersDisconnect; + } + } + else + { + gTasks[taskId].func = Task_TrySetContestInterviewData; + } +} + +static void Task_WaitForLinkPartnersDisconnect(u8 taskId) +{ + if (!gReceivedRemoteLinkPlayers) + { + if (gLinkContestFlags & LINK_CONTEST_FLAG_IS_WIRELESS) + DestroyWirelessStatusIndicatorSprite(); + + HideLinkResultsTextBox(); + gTasks[taskId].func = Task_TrySetContestInterviewData; + } +} + +static void Task_TrySetContestInterviewData(u8 taskId) +{ + if (!(gLinkContestFlags & LINK_CONTEST_FLAG_IS_LINK)) + BravoTrainerPokemonProfile_BeforeInterview2(gContestFinalStandings[gContestPlayerMonIndex]); + + BeginHardwarePaletteFade(0xFF, 0, 0, 16, 0); + gTasks[taskId].func = Task_EndShowContestResults; +} + +static void Task_EndShowContestResults(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (gTasks[taskId].tTimer == 0) + { + DestroyTask(sContestResults->data->highlightWinnerTaskId); + BlendPalettes(0x0000FFFF, 16, RGB_BLACK); + gTasks[taskId].tTimer++; + } + else if (gTasks[taskId].tTimer == 1) + { + BlendPalettes(0xFFFF0000, 16, RGB_BLACK); + gTasks[taskId].tTimer++; + } + else + { + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + DestroyTask(taskId); + FreeAllWindowBuffers(); + SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); + FreeContestResults(); + } + } +} + +#undef tState +#undef tTimer +#undef tCounter + +static void Task_SlideContestResultsBg(u8 taskId) +{ + gBattle_BG3_X += 2; + gBattle_BG3_Y += 1; + if (gBattle_BG3_X > 255) + gBattle_BG3_X -= 255; + if (gBattle_BG3_Y > 255) + gBattle_BG3_Y -= 255; +} + +#define tDelay data[0] +#define tCoeff data[1] +#define tDecreasing data[2] + +static void Task_FlashStarsAndHearts(u8 taskId) +{ + if (++gTasks[taskId].tDelay == 2) + { + gTasks[taskId].tDelay = 0; + if (!gTasks[taskId].tDecreasing) + gTasks[taskId].tCoeff++; + else + gTasks[taskId].tCoeff--; + + if (gTasks[taskId].tCoeff == 16) + gTasks[taskId].tDecreasing = TRUE; + else if (gTasks[taskId].tCoeff == 0) + gTasks[taskId].tDecreasing = FALSE; + + BlendPalette(0x6B, 1, gTasks[taskId].tCoeff, RGB(30, 22, 11)); + BlendPalette(0x68, 1, gTasks[taskId].tCoeff, RGB_WHITE); + BlendPalette(0x6E, 1, gTasks[taskId].tCoeff, RGB(30, 29, 29)); + } + + if (gTasks[taskId].tCoeff == 0) + sContestResults->data->pointsFlashing = FALSE; + else + sContestResults->data->pointsFlashing = TRUE; +} + +static void LoadContestMonIcon(u16 species, u8 monIndex, u8 srcOffset, u8 useDmaNow, u32 personality) +{ + const u8 *iconPtr; + u16 var0, var1, frameNum; + + if (monIndex == gContestPlayerMonIndex) + frameNum = 1; + else + frameNum = 0; + + iconPtr = GetMonIconPtr(species, personality, frameNum); + iconPtr += srcOffset * 0x200 + 0x80; + if (useDmaNow) + { + RequestDma3Copy(iconPtr, (void *)BG_CHAR_ADDR(1) + monIndex * 0x200, 0x180, 1); + var0 = ((monIndex + 10) << 12); + var1 = (monIndex * 0x10 + 0x200); + WriteSequenceToBgTilemapBuffer(1, var1 | var0, 3, monIndex * 3 + 4, 4, 3, 17, 1); + } + else + { + RequestDma3Copy(iconPtr, (void *)BG_CHAR_ADDR(1) + monIndex * 0x200, 0x180, 1); + } +} + +static void LoadAllContestMonIcons(u8 srcOffset, bool8 useDmaNow) +{ + int i; + + for (i = 0; i < CONTESTANT_COUNT; i++) + LoadContestMonIcon(gContestMons[i].species, i, srcOffset, useDmaNow, gContestMons[i].personality); +} + +static void LoadAllContestMonIconPalettes(void) +{ + int i, species; + + for (i = 0; i < CONTESTANT_COUNT; i++) + { + species = gContestMons[i].species; + LoadPalette(gMonIconPalettes[gMonIconPaletteIndices[GetIconSpecies(species, 0)]], i * 0x10 + 0xA0, 0x20); + } +} + +static void TryCreateWirelessSprites(void) +{ + u16 sheet; + u8 spriteId; + + if (gLinkContestFlags & LINK_CONTEST_FLAG_IS_WIRELESS) + { + LoadWirelessStatusIndicatorSpriteGfx(); + CreateWirelessStatusIndicatorSprite(8, 8); + gSprites[gWirelessStatusIndicatorSpriteId].subpriority = 1; + sheet = LoadSpriteSheet(&sUnknown_0858D8E0); + RequestDma3Fill(0xFFFFFFFF, (void *)BG_CHAR_ADDR(4) + sheet * 0x20, 0x80, 1); + spriteId = CreateSprite(&sSpriteTemplate_858D8C8, 8, 8, 0); + gSprites[spriteId].oam.objMode = ST_OAM_OBJ_WINDOW; + } +} + +// Functionally equivalent, the same except compiler generated variables from +// src are placed on different stack positions. + +#ifdef NONMATCHING +static s32 DrawResultsTextWindow(const u8 *text, u8 spriteId) +{ + u8 *windowTilesPtr; + u16 windowId; + int origWidth; + struct WindowTemplate windowTemplate; + int strWidth; + u8 *spriteTilePtrs[4]; + u8 *dst; + int i; + struct Sprite *sprite; + const u8 *src; // The culprit. + + memset(&windowTemplate, 0, sizeof(windowTemplate)); + windowTemplate.width = 30; + windowTemplate.height = 2; + windowId = AddWindow(&windowTemplate); + FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); + + origWidth = GetStringWidth(1, text, 0); + strWidth = (origWidth + 9) / 8; + if (strWidth > 30) + strWidth = 30; + + AddTextPrinterParameterized3(windowId, 1, (strWidth * 8 - origWidth) / 2, 1, sContestLinkTextColors, -1, text); + windowTilesPtr = (u8 *)(GetWindowAttribute(windowId, WINDOW_TILE_DATA)); + src = (u8 *)(sUnknown_0858D6D0); + + sprite = &gSprites[spriteId]; + spriteTilePtrs[0] = (u8 *)(sprite->oam.tileNum * 32 + VRAM + 0x10000); + + for (i = 1; i < 4; i++) + spriteTilePtrs[i] = (void*)(gSprites[sprite->data[i - 1]].oam.tileNum * 32 + VRAM + 0x10000); + + for (i = 0; i < 4; i++) + CpuFill32(0, spriteTilePtrs[i], 0x400); + + dst = spriteTilePtrs[0]; + CpuCopy32(src, dst, 0x20); + CpuCopy32(src + 128, dst + 0x100, 0x20); + CpuCopy32(src + 128, dst + 0x200, 0x20); + CpuCopy32(src + 64, dst + 0x300, 0x20); + + for (i = 0; i < strWidth; i++) + { + dst = &spriteTilePtrs[(i + 1) / 8][((i + 1) % 8) * 32]; + CpuCopy32(src + 192, dst, 0x20); + CpuCopy32(windowTilesPtr, dst + 0x100, 0x20); + CpuCopy32(windowTilesPtr + 960, dst + 0x200, 0x20); + CpuCopy32(src + 224, dst + 0x300, 0x20); + windowTilesPtr += 0x20; + } + + dst = &spriteTilePtrs[(i + 1) / 8][((i + 1) % 8) * 32]; + CpuCopy32(src + 32, dst, 0x20); + CpuCopy32(src + 160, dst + 0x100, 0x20); + CpuCopy32(src + 160, dst + 0x200, 0x20); + CpuCopy32(src + 96, dst + 0x300, 0x20); + RemoveWindow(windowId); + + return (240 - (strWidth + 2) * 8) / 2; +} + +#else +NAKED +static s32 DrawResultsTextWindow(const u8 *text, u8 spriteId) +{ + asm_unified("\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x44\n\ + adds r5, r0, 0\n\ + lsls r1, 24\n\ + lsrs r7, r1, 24\n\ + add r4, sp, 0x20\n\ + adds r0, r4, 0\n\ + movs r1, 0\n\ + movs r2, 0x8\n\ + bl memset\n\ + movs r0, 0x1E\n\ + strb r0, [r4, 0x3]\n\ + movs r0, 0x2\n\ + strb r0, [r4, 0x4]\n\ + adds r0, r4, 0\n\ + bl AddWindow\n\ + lsls r6, r0, 24\n\ + lsrs r4, r6, 24\n\ + adds r0, r4, 0\n\ + movs r1, 0x11\n\ + bl FillWindowPixelBuffer\n\ + movs r0, 0x1\n\ + adds r1, r5, 0\n\ + movs r2, 0\n\ + bl GetStringWidth\n\ + adds r2, r0, 0\n\ + adds r2, 0x9\n\ + cmp r2, 0\n\ + bge _080F6BC4\n\ + adds r2, 0x7\n\ +_080F6BC4:\n\ + asrs r2, 3\n\ + mov r10, r2\n\ + cmp r2, 0x1E\n\ + ble _080F6BD0\n\ + movs r1, 0x1E\n\ + mov r10, r1\n\ +_080F6BD0:\n\ + mov r1, r10\n\ + lsls r2, r1, 3\n\ + subs r2, r0\n\ + lsrs r0, r2, 31\n\ + adds r2, r0\n\ + asrs r2, 1\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + ldr r0, =sContestLinkTextColors\n\ + str r0, [sp]\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + str r0, [sp, 0x4]\n\ + str r5, [sp, 0x8]\n\ + adds r0, r4, 0\n\ + movs r1, 0x1\n\ + movs r3, 0x1\n\ + bl AddTextPrinterParameterized3\n\ + adds r0, r4, 0\n\ + movs r1, 0x7\n\ + bl GetWindowAttribute\n\ + mov r9, r0\n\ + ldr r2, =sUnknown_0858D6D0\n\ + mov r8, r2\n\ + lsls r1, r7, 4\n\ + adds r1, r7\n\ + lsls r1, 2\n\ + ldr r3, =gSprites\n\ + adds r1, r3\n\ + ldrh r0, [r1, 0x4]\n\ + lsls r0, 22\n\ + lsrs r0, 17\n\ + ldr r2, =0x06010000\n\ + adds r0, r2\n\ + str r0, [sp, 0xC]\n\ + str r6, [sp, 0x38]\n\ + mov r7, sp\n\ + adds r7, 0x1C\n\ + str r7, [sp, 0x2C]\n\ + mov r0, r10\n\ + adds r0, 0x2\n\ + str r0, [sp, 0x30]\n\ + movs r5, 0\n\ + add r7, sp, 0x10\n\ + mov r12, r7\n\ + adds r6, r1, 0\n\ + adds r6, 0x2E\n\ + movs r4, 0x2\n\ +_080F6C34:\n\ + adds r0, r6, r5\n\ + movs r7, 0\n\ + ldrsh r1, [r0, r7]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r3\n\ + ldrh r0, [r0, 0x4]\n\ + lsls r0, 22\n\ + lsrs r0, 17\n\ + adds r0, r2\n\ + mov r1, r12\n\ + adds r1, 0x4\n\ + mov r12, r1\n\ + subs r1, 0x4\n\ + stm r1!, {r0}\n\ + adds r5, 0x2\n\ + subs r4, 0x1\n\ + cmp r4, 0\n\ + bge _080F6C34\n\ + mov r7, r8\n\ + adds r7, 0x80\n\ + mov r2, r8\n\ + adds r2, 0x40\n\ + str r2, [sp, 0x28]\n\ + mov r0, r8\n\ + adds r0, 0x20\n\ + str r0, [sp, 0x3C]\n\ + mov r1, r8\n\ + adds r1, 0xA0\n\ + str r1, [sp, 0x40]\n\ + adds r2, 0x20\n\ + str r2, [sp, 0x34]\n\ + add r5, sp, 0xC\n\ + movs r6, 0\n\ + movs r4, 0x3\n\ +_080F6C7C:\n\ + str r6, [sp, 0x1C]\n\ + ldm r5!, {r1}\n\ + ldr r0, [sp, 0x2C]\n\ + ldr r2, =0x05000100\n\ + bl CpuSet\n\ + subs r4, 0x1\n\ + cmp r4, 0\n\ + bge _080F6C7C\n\ + ldr r5, [sp, 0xC]\n\ + ldr r6, =0x04000008\n\ + mov r0, r8\n\ + adds r1, r5, 0\n\ + adds r2, r6, 0\n\ + bl CpuSet\n\ + movs r0, 0x80\n\ + lsls r0, 1\n\ + adds r1, r5, r0\n\ + adds r0, r7, 0\n\ + adds r2, r6, 0\n\ + bl CpuSet\n\ + movs r2, 0x80\n\ + lsls r2, 2\n\ + adds r1, r5, r2\n\ + adds r0, r7, 0\n\ + adds r2, r6, 0\n\ + bl CpuSet\n\ + movs r7, 0xC0\n\ + lsls r7, 2\n\ + adds r1, r5, r7\n\ + ldr r0, [sp, 0x28]\n\ + adds r2, r6, 0\n\ + bl CpuSet\n\ + movs r4, 0\n\ + cmp r4, r10\n\ + bge _080F6D32\n\ + adds r7, r6, 0\n\ +_080F6CCE:\n\ + adds r6, r4, 0x1\n\ + adds r0, r6, 0\n\ + cmp r6, 0\n\ + bge _080F6CDA\n\ + adds r0, r4, 0\n\ + adds r0, 0x8\n\ +_080F6CDA:\n\ + asrs r0, 3\n\ + lsls r1, r0, 2\n\ + add r1, sp\n\ + adds r1, 0xC\n\ + lsls r0, 3\n\ + subs r0, r6, r0\n\ + lsls r0, 5\n\ + ldr r1, [r1]\n\ + adds r5, r1, r0\n\ + mov r0, r8\n\ + adds r0, 0xC0\n\ + adds r1, r5, 0\n\ + adds r2, r7, 0\n\ + bl CpuSet\n\ + movs r0, 0x80\n\ + lsls r0, 1\n\ + adds r1, r5, r0\n\ + mov r0, r9\n\ + adds r2, r7, 0\n\ + bl CpuSet\n\ + movs r0, 0xF0\n\ + lsls r0, 2\n\ + add r0, r9\n\ + movs r2, 0x80\n\ + lsls r2, 2\n\ + adds r1, r5, r2\n\ + adds r2, r7, 0\n\ + bl CpuSet\n\ + movs r0, 0xC0\n\ + lsls r0, 2\n\ + adds r1, r5, r0\n\ + mov r0, r8\n\ + adds r0, 0xE0\n\ + adds r2, r7, 0\n\ + bl CpuSet\n\ + movs r1, 0x20\n\ + add r9, r1\n\ + adds r4, r6, 0\n\ + cmp r4, r10\n\ + blt _080F6CCE\n\ +_080F6D32:\n\ + adds r2, r4, 0x1\n\ + adds r0, r2, 0\n\ + cmp r2, 0\n\ + bge _080F6D3E\n\ + adds r0, r4, 0\n\ + adds r0, 0x8\n\ +_080F6D3E:\n\ + asrs r0, 3\n\ + lsls r1, r0, 2\n\ + add r1, sp\n\ + adds r1, 0xC\n\ + lsls r0, 3\n\ + subs r0, r2, r0\n\ + lsls r0, 5\n\ + ldr r1, [r1]\n\ + adds r5, r1, r0\n\ + ldr r4, =0x04000008\n\ + ldr r0, [sp, 0x3C]\n\ + adds r1, r5, 0\n\ + adds r2, r4, 0\n\ + bl CpuSet\n\ + movs r2, 0x80\n\ + lsls r2, 1\n\ + adds r1, r5, r2\n\ + ldr r0, [sp, 0x40]\n\ + adds r2, r4, 0\n\ + bl CpuSet\n\ + movs r7, 0x80\n\ + lsls r7, 2\n\ + adds r1, r5, r7\n\ + ldr r0, [sp, 0x40]\n\ + adds r2, r4, 0\n\ + bl CpuSet\n\ + movs r0, 0xC0\n\ + lsls r0, 2\n\ + adds r1, r5, r0\n\ + ldr r0, [sp, 0x34]\n\ + adds r2, r4, 0\n\ + bl CpuSet\n\ + ldr r1, [sp, 0x38]\n\ + lsrs r0, r1, 24\n\ + bl RemoveWindow\n\ + ldr r2, [sp, 0x30]\n\ + lsls r1, r2, 3\n\ + movs r0, 0xF0\n\ + subs r0, r1\n\ + asrs r0, 1\n\ + add sp, 0x44\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .pool"); +} +#endif // NONMATCHING + +static void LoadContestResultSprites(void) +{ + int i; + struct SpriteTemplate template; + u8 spriteIds[ARRAY_COUNT(sUnknown_0858D810)]; + + template = sSpriteTemplate_858D7F8; + for (i = 0; i < (int)ARRAY_COUNT(sUnknown_0858D810); i++) + LoadSpriteSheet(&sUnknown_0858D810[i]); + + LoadSpritePalette(&sUnknown_0858D850); + for (i = 0; i < (int)ARRAY_COUNT(sUnknown_0858D810); i++) + { + spriteIds[i] = CreateSprite(&template, 272, 144, 10); + template.tileTag++; + } + + gSprites[spriteIds[0]].data[0] = spriteIds[1]; + gSprites[spriteIds[0]].data[1] = spriteIds[2]; + gSprites[spriteIds[0]].data[2] = spriteIds[3]; + + gSprites[spriteIds[4]].data[0] = spriteIds[5]; + gSprites[spriteIds[4]].data[1] = spriteIds[6]; + gSprites[spriteIds[4]].data[2] = spriteIds[7]; + + sContestResults->data->slidingTextBoxSpriteId = spriteIds[0]; + sContestResults->data->slidingTextBoxState = SLIDING_TEXT_OFFSCREEN; + sContestResults->data->linkTextBoxSpriteId = spriteIds[4]; + HideLinkResultsTextBox(); +} + +#define sTargetX data[4] +#define sSlideOutTimer data[5] +#define sSlideIncrement data[6] +#define sDistance data[7] + +// If slideOutTimer is -1, it will not automatically slide out +static void StartTextBoxSlideIn(s16 x, u16 y, u16 slideOutTimer, u16 slideIncrement) +{ + struct Sprite *sprite = &gSprites[sContestResults->data->slidingTextBoxSpriteId]; + sprite->pos1.x = 272; + sprite->pos1.y = y; + sprite->pos2.x = 0; + sprite->pos2.y = 0; + sprite->sTargetX = x + 32; + sprite->sSlideOutTimer = slideOutTimer; + sprite->sSlideIncrement = slideIncrement; + sprite->sDistance = 0; + sprite->callback = SpriteCB_TextBoxSlideIn; + sContestResults->data->slidingTextBoxState = SLIDING_TEXT_ENTERING; +} + +static void StartTextBoxSlideOut(u16 slideIncrement) +{ + struct Sprite *sprite = &gSprites[sContestResults->data->slidingTextBoxSpriteId]; + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + sprite->sSlideIncrement = slideIncrement; + sprite->sDistance = 0; + sprite->callback = SpriteCB_TextBoxSlideOut; + sContestResults->data->slidingTextBoxState = SLIDING_TEXT_EXITING; +} + +static void EndTextBoxSlideOut(struct Sprite *sprite) +{ + sprite->pos1.x = 272; + sprite->pos1.y = 144; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + sprite->callback = SpriteCallbackDummy; + sContestResults->data->slidingTextBoxState = SLIDING_TEXT_OFFSCREEN; +} + +static void SpriteCB_TextBoxSlideIn(struct Sprite *sprite) +{ + int i; + + s16 delta = sprite->sDistance + sprite->sSlideIncrement; + sprite->pos1.x -= delta >> 8; + sprite->sDistance += sprite->sSlideIncrement; + sprite->sDistance &= 0xFF; + + // Prevent overshooting target + if (sprite->pos1.x < sprite->sTargetX) + sprite->pos1.x = sprite->sTargetX; + + for (i = 0; i < 3; i++) + { + struct Sprite *sprite2 = &gSprites[sprite->data[i]]; + sprite2->pos1.x = sprite->pos1.x + sprite->pos2.x + (i + 1) * 64; + } + + if (sprite->pos1.x == sprite->sTargetX) + sprite->callback = SpriteCB_EndTextBoxSlideIn; +} + +static void SpriteCB_EndTextBoxSlideIn(struct Sprite *sprite) +{ + sContestResults->data->slidingTextBoxState = SLIDING_TEXT_ARRIVED; + if ((u16)sprite->sSlideOutTimer != 0xFFFF) + { + if (--sprite->sSlideOutTimer == -1) + StartTextBoxSlideOut(sprite->sSlideIncrement); + } +} + +static void SpriteCB_TextBoxSlideOut(struct Sprite *sprite) +{ + int i; + s16 delta; + + delta = sprite->sDistance + sprite->sSlideIncrement; + sprite->pos1.x -= delta >> 8; + sprite->sDistance += sprite->sSlideIncrement; + sprite->sDistance &= 0xFF; + for (i = 0; i < 3; i++) + { + struct Sprite *sprite2 = &gSprites[sprite->data[i]]; + sprite2->pos1.x = sprite->pos1.x + sprite->pos2.x + (i + 1) * 64; + } + + if (sprite->pos1.x + sprite->pos2.x < -224) + EndTextBoxSlideOut(sprite); +} + +static void ShowLinkResultsTextBox(const u8 *text) +{ + int i; + u16 x; + struct Sprite *sprite; + + x = DrawResultsTextWindow(text, sContestResults->data->linkTextBoxSpriteId); + sprite = &gSprites[sContestResults->data->linkTextBoxSpriteId]; + sprite->pos1.x = x + 32; + sprite->pos1.y = 80; + sprite->invisible = FALSE; + for (i = 0; i < 3; i++) + { + gSprites[sprite->data[i]].pos1.x = sprite->pos1.x + sprite->pos2.x + (i + 1) * 64; + gSprites[sprite->data[i]].pos1.y = sprite->pos1.y; + gSprites[sprite->data[i]].invisible = FALSE; + } + + gBattle_WIN0H = 0x00F0; + gBattle_WIN0V = ((sprite->pos1.y - 16) << 8) | (sprite->pos1.y + 16); + SetGpuReg(REG_OFFSET_WININ, WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR + | WININ_WIN0_BG1 | WININ_WIN0_BG2 | WININ_WIN0_BG3 | WININ_WIN0_OBJ | WININ_WIN0_CLR); +} + +static void HideLinkResultsTextBox(void) +{ + int i; + struct Sprite *sprite; + + sprite = &gSprites[sContestResults->data->linkTextBoxSpriteId]; + sprite->invisible = TRUE; + for (i = 0; i < 3; i++) + gSprites[sprite->data[i]].invisible = TRUE; + + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + SetGpuReg(REG_OFFSET_WIN0H, gBattle_WIN0H); + SetGpuReg(REG_OFFSET_WIN0V, gBattle_WIN0V); + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR + | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); +} + +static void LoadContestResultsTilemaps(void) +{ + u8 palette; + int x, y; + + x = 5; + y = 1; + if (gLinkContestFlags & LINK_CONTEST_FLAG_IS_LINK) + { + CopyToBgTilemapBufferRect(2, gLinkContestResults_Tilemap, 5, 1, 5, 2); + x = 10; + } + else if (gSpecialVar_ContestRank == CONTEST_RANK_NORMAL) + { + CopyToBgTilemapBufferRect(2, gNormalContestResults_Tilemap, 5, 1, 10, 2); + x = 15; + } + else if (gSpecialVar_ContestRank == CONTEST_RANK_SUPER) + { + CopyToBgTilemapBufferRect(2, gSuperContestResults_Tilemap, 5, 1, 10, 2); + x = 15; + } + else if (gSpecialVar_ContestRank == CONTEST_RANK_HYPER) + { + CopyToBgTilemapBufferRect(2, gHyperContestResults_Tilemap, 5, 1, 10, 2); + x = 15; + } + else // CONTEST_RANK_MASTER + { + CopyToBgTilemapBufferRect(2, gMasterContestResults_Tilemap, 5, 1, 10, 2); + x = 15; + } + + if (gSpecialVar_ContestCategory == CONTEST_CATEGORY_COOL) + { + palette = 0; + CopyToBgTilemapBufferRect(2, gCoolContestResults_Tilemap, x, y, 5, 2); + } + else if (gSpecialVar_ContestCategory == CONTEST_CATEGORY_BEAUTY) + { + palette = 1; + CopyToBgTilemapBufferRect(2, gBeautyContestResults_Tilemap, x, y, 5, 2); + } + else if (gSpecialVar_ContestCategory == CONTEST_CATEGORY_CUTE) + { + palette = 2; + CopyToBgTilemapBufferRect(2, gCuteContestResults_Tilemap, x, y, 5, 2); + } + else if (gSpecialVar_ContestCategory == CONTEST_CATEGORY_SMART) + { + palette = 3; + CopyToBgTilemapBufferRect(2, gSmartContestResults_Tilemap, x, y, 5, 2); + } + else // CONTEST_CATEGORY_TOUGH + { + palette = 4; + CopyToBgTilemapBufferRect(2, gToughContestResults_Tilemap, x, y, 5, 2); + } + + x += 5; + CopyToBgTilemapBufferRect(2, gContestResults_Tilemap, x, y, 6, 2); + CopyToBgTilemapBufferRect_ChangePalette(2, sContestResults->tilemapBuffers[2], 0, 0, 32, 4, palette); +} + +// Represented on results board as stars +static u8 GetNumPreliminaryPoints(u8 monIndex, bool8 capPoints) +{ + u32 condition = gContestMonConditions[monIndex] << 16; + u32 numStars = condition / 0x3F; + + if (numStars & 0xFFFF) + numStars += 0x10000; + + numStars >>= 16; + if (numStars == 0 && condition) + numStars = 1; + + if (capPoints && numStars > 10) + numStars = 10; + + return numStars; +} + +// Represented on results board as hearts +static s8 GetNumRound2Points(u8 monIndex, bool8 capPoints) +{ + u32 r4, numHearts; + s16 results; + s8 points; + + results = gContestMonRound2Points[monIndex]; + if (results < 0) + r4 = -results << 16; + else + r4 = results << 16; + + numHearts = r4 / 80; + if (numHearts & 0xFFFF) + numHearts += 0x10000; + + numHearts >>= 16; + if (numHearts == 0 && r4 != 0) + numHearts = 1; + + if (capPoints && numHearts > 10) + numHearts = 10; + + if (gContestMonRound2Points[monIndex] < 0) + points = -numHearts; + else + points = numHearts; + + return points; +} + +#define tState data[10] + +static void Task_DrawFinalStandingNumber(u8 taskId) +{ + u16 firstTileNum; + + if (gTasks[taskId].tState == 0) + { + gTasks[taskId].data[11] = (3 - gTasks[taskId].tFinalStanding) * 40; + gTasks[taskId].tState++; + } + else if (gTasks[taskId].tState == 1) + { + if (--gTasks[taskId].data[11] == -1) + { + firstTileNum = gTasks[taskId].tFinalStanding * 2 + 0x5043; + WriteSequenceToBgTilemapBuffer(2, firstTileNum, 1, gTasks[taskId].tMonIndex * 3 + 5, 2, 1, 17, 1); + WriteSequenceToBgTilemapBuffer(2, firstTileNum + 0x10, 1, gTasks[taskId].tMonIndex * 3 + 6, 2, 1, 17, 1); + sContestResults->data->numStandingsPrinted++; + DestroyTask(taskId); + PlaySE(SE_JYUNI); + } + } +} + +#undef tFinalStanding +#undef tMonIndex +#undef tState + +static void Task_StartHighlightWinnersBox(u8 taskId) +{ + int i; + GET_CONTEST_WINNER_ID(i); + CopyToBgTilemapBufferRect_ChangePalette(2, i * 0xC0 + 0x100 + sContestResults->tilemapBuffers[2], 0, i * 3 + 4, 32, 3, 9); + gTasks[taskId].data[10] = i; + gTasks[taskId].data[12] = 1; + gTasks[taskId].func = Task_HighlightWinnersBox; + sContestResults->data->highlightWinnerTaskId = taskId; +} + +static void Task_HighlightWinnersBox(u8 taskId) +{ + if (++gTasks[taskId].data[11] == 1) + { + gTasks[taskId].data[11] = 0; + BlendPalette(0x91, 1, gTasks[taskId].data[12], RGB(13, 28, 27)); + if (gTasks[taskId].data[13] == 0) + { + if (++gTasks[taskId].data[12] == 16) + gTasks[taskId].data[13] = 1; + } + else + { + if (--gTasks[taskId].data[12] == 0) + gTasks[taskId].data[13] = 0; + } + } +} + +static void SpriteCB_WinnerMonSlideIn(struct Sprite *sprite) +{ + if (sprite->data[0] < 10) + { + if (++sprite->data[0] == 10) + { + PlayCry1(sprite->data[1], 0); + sprite->data[1] = 0; + } + } + else + { + s16 delta = sprite->data[1] + 0x600; + sprite->pos1.x -= delta >> 8; + sprite->data[1] += 0x600; + sprite->data[1] &= 0xFF; + if (sprite->pos1.x < 120) + sprite->pos1.x = 120; + + if (sprite->pos1.x == 120) + { + sprite->callback = SpriteCallbackDummy; + sprite->data[1] = 0; + sContestResults->data->winnerMonSlidingState = SLIDING_MON_ENTERED; + } + } +} + +static void SpriteCB_WinnerMonSlideOut(struct Sprite *sprite) +{ + s16 delta = sprite->data[1] + 0x600; + sprite->pos1.x -= delta >> 8; + sprite->data[1] += + 0x600; + sprite->data[1] &= 0xFF; + if (sprite->pos1.x < -32) + { + sprite->callback = SpriteCallbackDummy; + sprite->invisible = TRUE; + sContestResults->data->winnerMonSlidingState = SLIDING_MON_EXITED; + } +} + +static void Task_CreateConfetti(u8 taskId) +{ + if (++gTasks[taskId].data[0] == 5) + { + gTasks[taskId].data[0] = 0; + if (sContestResults->data->confettiCount < 40) + { + u8 spriteId = CreateSprite(&sSpriteTemplate_Confetti, (Random() % 240) - 20, 44, 5); + gSprites[spriteId].data[0] = Random() % 512; + gSprites[spriteId].data[1] = (Random() % 24) + 16; + gSprites[spriteId].data[2] = (Random() % 256) + 48; + gSprites[spriteId].oam.tileNum += Random() % 17; + sContestResults->data->confettiCount++; + } + } + + if (sContestResults->data->destroyConfetti) + DestroyTask(taskId); +} + +static void SpriteCB_Confetti(struct Sprite *sprite) +{ + s16 delta; + + sprite->data[3] += sprite->data[0]; + sprite->pos2.x = Sin(sprite->data[3] >> 8, sprite->data[1]); + delta = sprite->data[4] + sprite->data[2]; + sprite->pos1.x += delta >> 8; + sprite->data[4] += sprite->data[2]; + sprite->data[4] &= 0xff; + + sprite->pos1.y++; + if (sContestResults->data->destroyConfetti) + sprite->invisible = TRUE; + + if (sprite->pos1.x > 248 || sprite->pos1.y > 116) + { + DestroySprite(sprite); + sContestResults->data->confettiCount--; + } +} + +#define tMonIndex data[0] +#define tNumFrames data[1] +#define tSpecies data[2] +#define tTimer data[10] +#define tBounced data[11] + +static void BounceMonIconInBox(u8 monIndex, u8 numFrames) +{ + u8 taskId = CreateTask(Task_BounceMonIconInBox, 8); + gTasks[taskId].tMonIndex = monIndex; + gTasks[taskId].tNumFrames = numFrames; + gTasks[taskId].tSpecies = gContestMons[monIndex].species; +} + +static void Task_BounceMonIconInBox(u8 taskId) +{ + u8 monIndex = gTasks[taskId].tMonIndex; + if (gTasks[taskId].tTimer++ == gTasks[taskId].tNumFrames) + { + gTasks[taskId].tTimer = 0; + LoadContestMonIcon(gTasks[taskId].tSpecies, monIndex, gTasks[taskId].tBounced, FALSE, gContestMons[monIndex].personality); + gTasks[taskId].tBounced ^= 1; + } +} + +#undef tMonIndex +#undef tNumFrames +#undef tSpecies +#undef tTimer +#undef tBounced + +static void CalculateContestantsResultData(void) +{ + int i, relativePoints; + u32 barLength; + s16 highestPoints; + s8 round2Points; + + highestPoints = gContestMonTotalPoints[0]; + for (i = 1; i < CONTESTANT_COUNT; i++) + { + if (highestPoints < gContestMonTotalPoints[i]) + highestPoints = gContestMonTotalPoints[i]; + } + + if (highestPoints < 0) + { + highestPoints = gContestMonTotalPoints[0]; + for (i = 1; i < CONTESTANT_COUNT; i++) + { + if (highestPoints > gContestMonTotalPoints[i]) + highestPoints = gContestMonTotalPoints[i]; + } + } + + for (i = 0; i < CONTESTANT_COUNT; i++) + { + relativePoints = (gContestMonConditions[i] * 1000) / abs(highestPoints); + if (relativePoints % 10 > 4) + relativePoints += 10; + (*sContestResults->monResults)[i].relativePreliminaryPoints = relativePoints / 10; + + relativePoints = (abs(gContestMonRound2Points[i]) * 1000) / abs(highestPoints); + if (relativePoints % 10 > 4) + relativePoints += 10; + (*sContestResults->monResults)[i].relativeRound2Points = relativePoints / 10; + + if (gContestMonRound2Points[i] < 0) + (*sContestResults->monResults)[i].lostPoints = TRUE; + + barLength = ((*sContestResults->monResults)[i].relativePreliminaryPoints * 0x5800) / 100; + if ((barLength & 0xFF) > 0x7F) + barLength += 0x100; + (*sContestResults->monResults)[i].barLengthPreliminary = barLength >> 8; + + barLength = ((*sContestResults->monResults)[i].relativeRound2Points * 0x5800) / 100; + if ((barLength & 0xFF) > 0x7F) + barLength += 0x100; + (*sContestResults->monResults)[i].barLengthRound2 = barLength >> 8; + + (*sContestResults->monResults)[i].numStars = GetNumPreliminaryPoints(i, TRUE); + round2Points = GetNumRound2Points(i, TRUE); + (*sContestResults->monResults)[i].numHearts = abs(round2Points); + + if (gContestFinalStandings[i]) + { + s16 barLengthPreliminary = (*sContestResults->monResults)[i].barLengthPreliminary; + s16 barLengthRound2 = (*sContestResults->monResults)[i].barLengthRound2; + + if ((*sContestResults->monResults)[i].lostPoints) + barLengthRound2 *= -1; + + if (barLengthPreliminary + barLengthRound2 == MAX_BAR_LENGTH + 1) + { + if (barLengthRound2 > 0) + (*sContestResults->monResults)[i].barLengthRound2--; + else if (barLengthPreliminary > 0) + (*sContestResults->monResults)[i].barLengthPreliminary--; + } + } + } +} + +#define tMonId data[0] +#define tTarget data[1] +#define tDecreasing data[2] + +static void UpdateContestResultBars(bool8 isRound2, u8 numUpdates) +{ + int i, taskId; + u32 target; + u8 numIncreasing = 0, numDecreasing = 0; + + if (!isRound2) + { + for (i = 0; i < CONTESTANT_COUNT; i++) + { + u8 numStars = (*sContestResults->monResults)[i].numStars; + if (numUpdates < numStars) + { + FillBgTilemapBufferRect_Palette0(1, 0x60B3, ((19 + numStars) - numUpdates) - 1, i * 3 + 5, 1, 1); + taskId = CreateTask(Task_UpdateContestResultBar, 10); + + target = (((*sContestResults->monResults)[i].barLengthPreliminary << 16) / (*sContestResults->monResults)[i].numStars) * (numUpdates + 1); + if ((target & 0xFFFF) > 0x7FFF) + target += 0x10000; + + gTasks[taskId].tMonId = i; + gTasks[taskId].tTarget = target >> 16; + sContestResults->data->numBarsUpdating++; + numIncreasing++; + } + } + } + else + { + for (i = 0; i < CONTESTANT_COUNT; i++) + { + s8 numHearts = (*sContestResults->monResults)[i].numHearts; + u32 tile = (*sContestResults->monResults)[i].lostPoints ? 0x60A5 : 0x60A3; + if (numUpdates < numHearts) + { + FillBgTilemapBufferRect_Palette0(1, tile, ((19 + numHearts) - numUpdates) - 1, i * 3 + 6, 1, 1); + taskId = CreateTask(Task_UpdateContestResultBar, 10); + + target = (((*sContestResults->monResults)[i].barLengthRound2 << 16) / (*sContestResults->monResults)[i].numHearts) * (numUpdates + 1); + if ((target & 0xFFFF) > 0x7FFF) + target += 0x10000; + + gTasks[taskId].tMonId = i; + if ((*sContestResults->monResults)[i].lostPoints) + { + gTasks[taskId].tDecreasing = TRUE; + numDecreasing++; + } + else + { + numIncreasing++; + } + + if ((*sContestResults->monResults)[i].lostPoints) + gTasks[taskId].tTarget = -(target >> 16) + (*sContestResults->monResults)[i].barLengthPreliminary; + else + gTasks[taskId].tTarget = (target >> 16) + (*sContestResults->monResults)[i].barLengthPreliminary; + + sContestResults->data->numBarsUpdating++; + } + } + } + + if (numDecreasing) + PlaySE(SE_BOO); + if (numIncreasing) + PlaySE(SE_PIN); +} + +static void Task_UpdateContestResultBar(u8 taskId) +{ + int i; + bool32 minMaxReached = FALSE; + bool32 targetReached = FALSE; + u8 monId = gTasks[taskId].tMonId; + s16 target = gTasks[taskId].tTarget; + s16 decreasing = gTasks[taskId].tDecreasing; + + if (decreasing) + { + if (sContestResults->data->unkC[monId] <= 0) + minMaxReached = TRUE; + } + else + { + if (sContestResults->data->unkC[monId] > MAX_BAR_LENGTH) + minMaxReached = TRUE; + } + + if (sContestResults->data->unkC[monId] == target) + targetReached = TRUE; + + if (!targetReached) + { + if (minMaxReached) + sContestResults->data->unkC[monId] = target; + else if (decreasing) + sContestResults->data->unkC[monId] = sContestResults->data->unkC[monId] - 1; + else + sContestResults->data->unkC[monId] = sContestResults->data->unkC[monId] + 1; + } + + if (!minMaxReached && !targetReached) + { + u8 var0; + u16 tileNum; + for (i = 0; i < 11; i++) + { + if (sContestResults->data->unkC[monId] >= (i + 1) * 8) + var0 = 8; + else if (sContestResults->data->unkC[monId] >= i * 8) + var0 = sContestResults->data->unkC[monId] % 8; + else + var0 = 0; + + if (var0 < 4) + tileNum = 0x504C + var0; + else + tileNum = 0x5057 + var0; + + FillBgTilemapBufferRect_Palette0(2, tileNum, i + 7, monId * 3 + 6, 1, 1); + } + } + + if (targetReached) + { + sContestResults->data->numBarsUpdating--; + DestroyTask(taskId); + } +} + +#undef tMonId +#undef tTarget +#undef tDecreasing + +static void AllocContestResults(void) +{ + sContestResults = AllocZeroed(sizeof(*sContestResults)); + sContestResults->data = AllocZeroed(sizeof(*sContestResults->data)); + sContestResults->monResults = AllocZeroed(sizeof(*sContestResults->monResults)); + sContestResults->unusedBg = AllocZeroed(BG_SCREEN_SIZE); + sContestResults->tilemapBuffers[0] = AllocZeroed(BG_SCREEN_SIZE); + sContestResults->tilemapBuffers[1] = AllocZeroed(BG_SCREEN_SIZE); + sContestResults->tilemapBuffers[2] = AllocZeroed(BG_SCREEN_SIZE); + sContestResults->tilemapBuffers[3] = AllocZeroed(BG_SCREEN_SIZE); + sContestResults->unused = AllocZeroed(0x1000); + AllocateMonSpritesGfx(); +} + +static void FreeContestResults(void) +{ + FREE_AND_SET_NULL(sContestResults->data); + FREE_AND_SET_NULL(sContestResults->monResults); + FREE_AND_SET_NULL(sContestResults->unusedBg); + FREE_AND_SET_NULL(sContestResults->tilemapBuffers[0]); + FREE_AND_SET_NULL(sContestResults->tilemapBuffers[1]); + FREE_AND_SET_NULL(sContestResults->tilemapBuffers[2]); + FREE_AND_SET_NULL(sContestResults->tilemapBuffers[3]); + FREE_AND_SET_NULL(sContestResults->unused); + FREE_AND_SET_NULL(sContestResults); + FreeMonSpritesGfx(); +} + +static void AddContestTextPrinter(int windowId, u8 *str, int x) +{ + struct TextPrinterTemplate textPrinter; + textPrinter.currentChar = str; + textPrinter.windowId = windowId; + textPrinter.fontId = 7; + textPrinter.x = x; + textPrinter.y = 2; + textPrinter.currentX = x; + textPrinter.currentY = 2; + textPrinter.letterSpacing = 0; + textPrinter.lineSpacing = 0; + textPrinter.unk = 0; + textPrinter.fgColor = 1; + textPrinter.bgColor = 0; + textPrinter.shadowColor = 8; + AddTextPrinter(&textPrinter, 0, NULL); + PutWindowTilemap(windowId); +} + +void TryEnterContestMon(void) +{ + u8 eligibility = GetContestEntryEligibility(&gPlayerParty[gContestMonPartyIndex]); + + // Nonzero eligibility can still be non-eligibile, if mon is fainted or egg + if (eligibility) + { + sub_80DAB8C(gSpecialVar_ContestCategory, gSpecialVar_ContestRank); + sub_80DB09C(gSpecialVar_ContestCategory); + } + + gSpecialVar_Result = eligibility; +} + +u16 HasMonWonThisContestBefore(void) +{ + u16 hasRankRibbon = FALSE; + struct Pokemon *mon = &gPlayerParty[gContestMonPartyIndex]; + switch (gSpecialVar_ContestCategory) + { + case CONTEST_CATEGORY_COOL: + if (GetMonData(mon, MON_DATA_COOL_RIBBON) > gSpecialVar_ContestRank) + hasRankRibbon = TRUE; + break; + case CONTEST_CATEGORY_BEAUTY: + if (GetMonData(mon, MON_DATA_BEAUTY_RIBBON) > gSpecialVar_ContestRank) + hasRankRibbon = TRUE; + break; + case CONTEST_CATEGORY_CUTE: + if (GetMonData(mon, MON_DATA_CUTE_RIBBON) > gSpecialVar_ContestRank) + hasRankRibbon = TRUE; + break; + case CONTEST_CATEGORY_SMART: + if (GetMonData(mon, MON_DATA_SMART_RIBBON) > gSpecialVar_ContestRank) + hasRankRibbon = TRUE; + break; + case CONTEST_CATEGORY_TOUGH: + if (GetMonData(mon, MON_DATA_TOUGH_RIBBON) > gSpecialVar_ContestRank) + hasRankRibbon = TRUE; + break; + } + + return hasRankRibbon; +} + +void GiveMonContestRibbon(void) +{ + u8 ribbonData; + + if (gContestFinalStandings[gContestPlayerMonIndex] != 0) + return; + + switch (gSpecialVar_ContestCategory) + { + case CONTEST_CATEGORY_COOL: + ribbonData = GetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_COOL_RIBBON); + if (ribbonData <= gSpecialVar_ContestRank && ribbonData < 4) + { + ribbonData++; + SetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_COOL_RIBBON, &ribbonData); + if (GetRibbonCount(&gPlayerParty[gContestMonPartyIndex]) > NUM_CUTIES_RIBBONS) + TryPutSpotTheCutiesOnAir(&gPlayerParty[gContestMonPartyIndex], MON_DATA_COOL_RIBBON); + } + break; + case CONTEST_CATEGORY_BEAUTY: + ribbonData = GetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_BEAUTY_RIBBON); + if (ribbonData <= gSpecialVar_ContestRank && ribbonData < 4) + { + ribbonData++; + SetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_BEAUTY_RIBBON, &ribbonData); + if (GetRibbonCount(&gPlayerParty[gContestMonPartyIndex]) > NUM_CUTIES_RIBBONS) + TryPutSpotTheCutiesOnAir(&gPlayerParty[gContestMonPartyIndex], MON_DATA_BEAUTY_RIBBON); + } + break; + case CONTEST_CATEGORY_CUTE: + ribbonData = GetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_CUTE_RIBBON); + if (ribbonData <= gSpecialVar_ContestRank && ribbonData < 4) + { + ribbonData++; + SetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_CUTE_RIBBON, &ribbonData); + if (GetRibbonCount(&gPlayerParty[gContestMonPartyIndex]) > NUM_CUTIES_RIBBONS) + TryPutSpotTheCutiesOnAir(&gPlayerParty[gContestMonPartyIndex], MON_DATA_CUTE_RIBBON); + } + break; + case CONTEST_CATEGORY_SMART: + ribbonData = GetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_SMART_RIBBON); + if (ribbonData <= gSpecialVar_ContestRank && ribbonData < 4) + { + ribbonData++; + SetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_SMART_RIBBON, &ribbonData); + if (GetRibbonCount(&gPlayerParty[gContestMonPartyIndex]) > NUM_CUTIES_RIBBONS) + TryPutSpotTheCutiesOnAir(&gPlayerParty[gContestMonPartyIndex], MON_DATA_SMART_RIBBON); + } + break; + case CONTEST_CATEGORY_TOUGH: + ribbonData = GetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_TOUGH_RIBBON); + if (ribbonData <= gSpecialVar_ContestRank && ribbonData < 4) + { + ribbonData++; + SetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_TOUGH_RIBBON, &ribbonData); + if (GetRibbonCount(&gPlayerParty[gContestMonPartyIndex]) > NUM_CUTIES_RIBBONS) + TryPutSpotTheCutiesOnAir(&gPlayerParty[gContestMonPartyIndex], MON_DATA_TOUGH_RIBBON); + } + break; + } +} + +void BufferContestantTrainerName(void) +{ + StringCopy(gStringVar1, gContestMons[gSpecialVar_0x8006].trainerName); + sub_81DB5AC(gStringVar1); +} + +void BufferContestantMonNickname(void) +{ + StringCopy(gStringVar3, gContestMons[gSpecialVar_0x8006].nickname); +} + +// Unused script special +void GetContestMonConditionRanking(void) +{ + u8 i, rank; + + for (i = 0, rank = 0; i < CONTESTANT_COUNT; i++) + { + if (gContestMonConditions[gSpecialVar_0x8006] < gContestMonConditions[i]) + rank++; + } + + gSpecialVar_0x8004 = rank; +} + +void GetContestMonCondition(void) +{ + gSpecialVar_0x8004 = gContestMonConditions[gSpecialVar_0x8006]; +} + +void GetContestWinnerId(void) +{ + u8 i; + GET_CONTEST_WINNER_ID(i); + gSpecialVar_0x8005 = i; +} + +void BufferContestWinnerTrainerName(void) +{ + u8 i; + GET_CONTEST_WINNER_ID(i); + StringCopy(gStringVar3, gContestMons[i].trainerName); + sub_81DB5AC(gStringVar3); +} + +void BufferContestWinnerMonName(void) +{ + u8 i; + GET_CONTEST_WINNER_ID(i); + StringCopy(gStringVar1, gContestMons[i].nickname); +} + +void CB2_SetStartContestCallback(void) +{ + SetMainCallback2(CB2_StartContest); +} + +static void Task_StartContest(u8 taskId) +{ + if (!gPaletteFade.active) + { + DestroyTask(taskId); + SetMainCallback2(CB2_SetStartContestCallback); + } +} + +void StartContest(void) +{ + ScriptContext2_Enable(); + CreateTask(Task_StartContest, 10); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); +} + +void BufferContestantMonSpecies(void) +{ + gSpecialVar_0x8004 = gContestMons[gSpecialVar_0x8006].species; +} + +static void Task_StartShowContestResults(u8 taskId) +{ + if (!gPaletteFade.active) + { + DestroyTask(taskId); + SetMainCallback2(CB2_StartShowContestResults); + } +} + +void ShowContestResults(void) +{ + ScriptContext2_Enable(); + CreateTask(Task_StartShowContestResults, 10); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); +} + +void GetContestPlayerId(void) +{ + gSpecialVar_0x8004 = gContestPlayerMonIndex; +} + +void ContestLinkTransfer(u8 taskId) +{ + u8 newTaskId; + ScriptContext2_Enable(); + newTaskId = CreateTask(sub_80FC580, 0); + SetTaskFuncWithFollowupFunc(newTaskId, sub_80FC580, sub_80F8508); + gTasks[newTaskId].data[9] = taskId; +} + +static void sub_80F8508(u8 taskId) +{ + if (gLinkContestFlags & LINK_CONTEST_FLAG_HAS_RS_PLAYER) + { + sub_80DA8C8(gContestMonPartyIndex); + SetTaskFuncWithFollowupFunc(taskId, sub_80FC6BC, sub_80F8568); + } + else + { + sub_80DA8C8(gContestMonPartyIndex); + gTasks[taskId].func = sub_81D9DE4; + } +} + +static void sub_80F8568(u8 taskId) +{ + SetTaskFuncWithFollowupFunc(taskId, sub_80FC804, sub_80F8584); +} + +static void sub_80F8584(u8 taskId) +{ + SetTaskFuncWithFollowupFunc(taskId, sub_80FCE48, sub_80F85A0); +} + +static void sub_80F85A0(u8 taskId) +{ + SetTaskFuncWithFollowupFunc(taskId, sub_80FC894, sub_80F85BC); +} + +static void sub_80F85BC(u8 taskId) +{ + u8 i; + u8 sp0[4]; + u8 sp4[4]; + + memset(sp0, 0, sizeof(sp0)); + memset(sp4, 0, sizeof(sp4)); + + for (i = 0; i < gNumLinkContestPlayers; i++) + sp0[i] = gTasks[taskId].data[i + 1]; + + for (i = 0; i < gNumLinkContestPlayers;) + { + i++; + if (i >= gNumLinkContestPlayers || sp0[0] != sp0[i]) + break; + } + + if (i == gNumLinkContestPlayers) + gSpecialVar_0x8004 = 0; + else + gSpecialVar_0x8004 = 1; + + for (i = 0; i < gNumLinkContestPlayers; i++) + sp4[i] = gTasks[taskId].data[i + 5]; + + gUnknown_02039F2B = sub_80F86E0(sp4); + sub_80DB09C(gSpecialVar_ContestCategory); + SetTaskFuncWithFollowupFunc(taskId, sub_80FCF40, sub_80F86B8); +} + +static void sub_80F86B8(u8 taskId) +{ + SortContestants(FALSE); + SetTaskFuncWithFollowupFunc(taskId, sub_80FCFD0, sub_80F8714); +} + +u8 sub_80F86E0(u8 *arg0) +{ + int i; + u8 result = 0; + + for (i = 1; i < gNumLinkContestPlayers; i++) + { + if (arg0[result] < arg0[i]) + result = i; + } + + return result; +} + +void sub_80F8714(u8 taskId) +{ + int i; + + if (gSpecialVar_0x8004 == 1) + { + if (IsLinkTaskFinished()) + gTasks[taskId].func = sub_80F878C; + } + else + { + for (i = 0; i < CONTESTANT_COUNT; i++) + StringGetEnd10(gContestMons[i].nickname); + + DestroyTask(taskId); + SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1); + ScriptContext2_Disable(); + EnableBothScriptContexts(); + } +} + +static void sub_80F878C(u8 taskId) +{ + sub_800AC34(); + gTasks[taskId].func = sub_80F87B4; +} + +static void sub_80F87B4(u8 taskId) +{ + if (!gReceivedRemoteLinkPlayers) + { + DestroyTask(taskId); + ScriptContext2_Disable(); + EnableBothScriptContexts(); + } +} |