Files
Pokemon-Firered/src/hall_of_fame.c
T
2021-07-07 09:05:48 -04:00

1285 lines
35 KiB
C

#include "global.h"
#include "gflib.h"
#include "decompress.h"
#include "scanline_effect.h"
#include "task.h"
#include "save.h"
#include "data.h"
#include "m4a.h"
#include "help_system.h"
#include "hall_of_fame.h"
#include "quest_log.h"
#include "pc_screen_effect.h"
#include "new_menu_helpers.h"
#include "strings.h"
#include "credits.h"
#include "event_data.h"
#include "overworld.h"
#include "trainer_pokemon_sprites.h"
#include "text_window.h"
#include "field_fadetransition.h"
#include "menu.h"
#include "string_util.h"
#include "trig.h"
#include "random.h"
#include "graphics.h"
#include "constants/songs.h"
#include "constants/maps.h"
struct HallofFameMon
{
u32 tid;
u32 personality;
u16 species:9;
u16 lvl:7;
u8 nick[10];
};
struct HallofFameTeam
{
struct HallofFameMon mon[PARTY_SIZE];
};
struct HofGfx
{
u16 state;
u8 field_2[4];
u8 tilemap1[0x1000];
u8 tilemap2[0x1000];
};
static EWRAM_DATA u32 sSelectedPaletteIndices = 0;
static EWRAM_DATA struct HallofFameTeam * sHofMonPtr = NULL;
static EWRAM_DATA struct HofGfx * sHofGfxPtr = NULL;
#define HALL_OF_FAME_MAX_TEAMS 50
#define HALL_OF_FAME_BG_PAL (RGB(22, 24, 29))
static void Task_Hof_InitMonData(u8 taskId);
static void Task_Hof_InitTeamSaveData(u8 taskId);
static void Task_Hof_TrySaveData(u8 taskId);
static void Task_Hof_DelayAfterSave(u8 taskId);
static void Task_Hof_StartDisplayingMons(u8 taskId);
static void Task_Hof_DisplayMon(u8 taskId);
static void Task_Hof_PlayMonCryAndPrintInfo(u8 taskId);
static void Task_Hof_TryDisplayAnotherMon(u8 taskId);
static void Task_Hof_PaletteFadeAndPrintWelcomeText(u8 taskId);
static void Task_Hof_ApplauseAndConfetti(u8 taskId);
static void Task_Hof_WaitBorderFadeAway(u8 taskId);
static void Task_Hof_SpawnPlayerPic(u8 taskId);
static void Task_Hof_WaitAndPrintPlayerInfo(u8 taskId);
static void Task_Hof_ExitOnKeyPressed(u8 taskId);
static void Task_Hof_HandlePaletteOnExit(u8 taskId);
static void Task_Hof_HandleExit(u8 taskId);
static void SetWarpsToRollCredits(void);
static void Task_HofPC_CopySaveData(u8 taskId);
static void Task_HofPC_DrawSpritesPrintText(u8 taskId);
static void Task_HofPC_PrintMonInfo(u8 taskId);
static void Task_HofPC_HandleInput(u8 taskId);
static void Task_HofPC_HandlePaletteOnExit(u8 taskId);
static void Task_HofPC_HandleExit(u8 taskId);
static void Task_HofPC_PrintDataIsCorrupted(u8 taskId);
static void Task_HofPC_ExitOnButtonPress(u8 taskId);
static void HallOfFame_PrintWelcomeText(u8 a0, u8 a1);
static void HallOfFame_PrintMonInfo(struct HallofFameMon * hofMon, u8 a1, u8 a2);
static void HallOfFame_PrintPlayerInfo(u8 a0, u8 a1);
static void ClearVramOamPltt_LoadHofPal(void);
static void HofInit_ResetGpuBuffersAndLoadConfettiGfx(void);
static void Hof_InitBgs(void);
static bool8 DrawHofBackground(void);
static void SpriteCB_GetOnScreen(struct Sprite * sprite);
static void SpriteCB_Confetti(struct Sprite * sprite);
static bool8 Hof_SpawnConfetti(void);
static const struct BgTemplate sHof_BgTemplates[] = {
{
.bg = 0,
.charBaseIndex = 2,
.mapBaseIndex = 31,
.screenSize = 0,
.paletteMode = 0,
.priority = 0,
.baseTile = 0x000
},
{
.bg = 1,
.charBaseIndex = 0,
.mapBaseIndex = 30,
.screenSize = 0,
.paletteMode = 0,
.priority = 1,
.baseTile = 0x000
},
{
.bg = 3,
.charBaseIndex = 0,
.mapBaseIndex = 29,
.screenSize = 0,
.paletteMode = 0,
.priority = 3,
.baseTile = 0x000
}
};
static const struct WindowTemplate sWindowTemplate = {
.bg = 0,
.tilemapLeft = 2,
.tilemapTop = 2,
.width = 17,
.height = 6,
.paletteNum = 13,
.baseBlock = 0x001
};
static const u8 sTextColors[][4] = {
{ 0, 1, 2 },
{ 0, 2, 3 },
{ 4, 5, 0 }
};
static const struct CompressedSpriteSheet sHallOfFame_ConfettiSpriteSheet[] = {
{gFile_graphics_misc_confetti_sheet, 0x220, 1001},
{}
};
static const struct CompressedSpritePalette sHallOfFame_ConfettiSpritePalette[] = {
{gFile_graphics_misc_confetti_palette, 1001},
{}
};
static const s16 sHallOfFame_MonFullTeamPositions[6][4] =
{
{120, 210, 120, 40},
{326, 220, 56, 40},
{-86, 220, 184, 40},
{120, -62, 120, 88},
{-70, -92, 200, 88},
{310, -92, 40, 88}
};
static const s16 sHallOfFame_MonHalfTeamPositions[3][4] =
{
{120, 234, 120, 64},
{326, 244, 56, 64},
{-86, 244, 184, 64}
};
static const struct OamData sOamData_Confetti = {
.shape = SPRITE_SHAPE(8x8),
.size = SPRITE_SIZE(8x8)
};
static const union AnimCmd sAnimCmd_Frame00[] = {
ANIMCMD_FRAME( 0, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame01[] = {
ANIMCMD_FRAME( 1, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame02[] = {
ANIMCMD_FRAME( 2, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame03[] = {
ANIMCMD_FRAME( 3, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame04[] = {
ANIMCMD_FRAME( 4, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame05[] = {
ANIMCMD_FRAME( 5, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame06[] = {
ANIMCMD_FRAME( 6, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame07[] = {
ANIMCMD_FRAME( 7, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame08[] = {
ANIMCMD_FRAME( 8, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame09[] = {
ANIMCMD_FRAME( 9, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame10[] = {
ANIMCMD_FRAME(10, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame11[] = {
ANIMCMD_FRAME(11, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame12[] = {
ANIMCMD_FRAME(12, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame13[] = {
ANIMCMD_FRAME(13, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame14[] = {
ANIMCMD_FRAME(14, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame15[] = {
ANIMCMD_FRAME(15, 30),
ANIMCMD_END
};
static const union AnimCmd sAnimCmd_Frame16[] = {
ANIMCMD_FRAME(16, 30),
ANIMCMD_END
};
static const union AnimCmd *const sSpriteAnimTable_Confetti[] = {
sAnimCmd_Frame00,
sAnimCmd_Frame01,
sAnimCmd_Frame02,
sAnimCmd_Frame03,
sAnimCmd_Frame04,
sAnimCmd_Frame05,
sAnimCmd_Frame06,
sAnimCmd_Frame07,
sAnimCmd_Frame08,
sAnimCmd_Frame09,
sAnimCmd_Frame10,
sAnimCmd_Frame11,
sAnimCmd_Frame12,
sAnimCmd_Frame13,
sAnimCmd_Frame14,
sAnimCmd_Frame15,
sAnimCmd_Frame16
};
static const struct SpriteTemplate sSpriteTemplate_Confetti = {
.tileTag = 1001,
.paletteTag = 1001,
.oam = &sOamData_Confetti,
.anims = sSpriteAnimTable_Confetti,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCB_Confetti
};
static const u16 sHallOfFame_Pal[] = INCBIN_U16("graphics/hall_of_fame/hall_of_fame.gbapal");
static const u32 sHallOfFame_Gfx[] = INCBIN_U32("graphics/hall_of_fame/hall_of_fame.4bpp.lz");
static const struct HallofFameMon sDummyHofMon = {
.tid = 0x03EA03EA, // (u16[]){1002, 1002} corrupted sprite template?
.personality = 0,
.species = SPECIES_NONE,
.lvl = 0,
.nick = __(" ")
};
static const u8 sUnused[] = {2, 1, 3, 6, 4, 5};
static void VBlankCB_HofIdle(void)
{
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
}
static void CB2_HofIdle(void)
{
RunTasks();
RunTextPrinters();
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
}
static bool8 InitHallOfFameScreen(void)
{
switch (gMain.state)
{
case 0:
gHelpSystemEnabled = FALSE;
SetVBlankCallback(NULL);
ClearVramOamPltt_LoadHofPal();
sHofGfxPtr = AllocZeroed(sizeof(struct HofGfx));
gMain.state = 1;
break;
case 1:
HofInit_ResetGpuBuffersAndLoadConfettiGfx();
gMain.state++;
break;
case 2:
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 7));
SetGpuReg(REG_OFFSET_BLDY, 0);
Hof_InitBgs();
sHofGfxPtr->state = 0;
gMain.state++;
break;
case 3:
if (!DrawHofBackground())
{
SetVBlankCallback(VBlankCB_HofIdle);
BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
gMain.state++;
}
break;
case 4:
UpdatePaletteFade();
if (!gPaletteFade.active)
{
SetMainCallback2(CB2_HofIdle);
PlayBGM(MUS_HALL_OF_FAME);
return FALSE;
}
break;
}
return TRUE;
}
void CB2_DoHallOfFameScreen(void)
{
u8 taskId;
if (!InitHallOfFameScreen())
{
taskId = CreateTask(Task_Hof_InitMonData, 0);
gTasks[taskId].data[0] = FALSE;
sHofMonPtr = AllocZeroed(sizeof(struct HallofFameTeam));
}
}
void CB2_DoHallOfFameScreenDontSaveData(void)
{
u8 taskId;
if (!InitHallOfFameScreen())
{
taskId = CreateTask(Task_Hof_InitMonData, 0);
gTasks[taskId].data[0] = TRUE;
}
}
static void Task_Hof_InitMonData(u8 taskId)
{
u16 i;
u16 j;
u8 nick[11];
gTasks[taskId].data[2] = 0;
for (i = 0; i < PARTY_SIZE; i++)
{
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != SPECIES_NONE)
{
sHofMonPtr[0].mon[i].species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
sHofMonPtr[0].mon[i].tid = GetMonData(&gPlayerParty[i], MON_DATA_OT_ID);
sHofMonPtr[0].mon[i].personality = GetMonData(&gPlayerParty[i], MON_DATA_PERSONALITY);
sHofMonPtr[0].mon[i].lvl = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
GetMonData(&gPlayerParty[i], MON_DATA_NICKNAME, nick);
for (j = 0; j < 10; j++)
sHofMonPtr[0].mon[i].nick[j] = nick[j];
gTasks[taskId].data[2]++;
}
else
{
sHofMonPtr[0].mon[i].species = SPECIES_NONE;
sHofMonPtr[0].mon[i].tid = 0;
sHofMonPtr[0].mon[i].personality = 0;
sHofMonPtr[0].mon[i].lvl = 0;
sHofMonPtr[0].mon[i].nick[0] = EOS;
}
}
sSelectedPaletteIndices = 0;
gTasks[taskId].data[1] = 0;
gTasks[taskId].data[4] = 0xFF;
for (i = 0; i < 6; i++)
gTasks[taskId].data[i + 5] = 0xFF;
if (gTasks[taskId].data[0])
gTasks[taskId].func = Task_Hof_StartDisplayingMons;
else
gTasks[taskId].func = Task_Hof_InitTeamSaveData;
}
static void Task_Hof_InitTeamSaveData(u8 taskId)
{
u16 i;
struct HallofFameTeam* lastSavedTeam = (struct HallofFameTeam *)(gDecompressionBuffer);
SaveQuestLogData();
if (!gHasHallOfFameRecords)
{
memset(gDecompressionBuffer, 0, 0x2000);
}
else
{
if (Save_LoadGameData(SAVE_HALL_OF_FAME) != TRUE)
memset(gDecompressionBuffer, 0, 0x2000);
}
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, lastSavedTeam++)
{
if (lastSavedTeam[0].mon[0].species == SPECIES_NONE)
break;
}
if (i >= HALL_OF_FAME_MAX_TEAMS)
{
struct HallofFameTeam *afterTeam = (struct HallofFameTeam*)(gDecompressionBuffer);
struct HallofFameTeam *beforeTeam = (struct HallofFameTeam*)(gDecompressionBuffer);
afterTeam++;
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS - 1; i++, beforeTeam++, afterTeam++)
{
*beforeTeam = *afterTeam;
}
lastSavedTeam--;
}
*lastSavedTeam = *sHofMonPtr;
DrawDialogueFrame(0, 0);
AddTextPrinterParameterized2(0, 2, gText_SavingDontTurnOffThePower2, 0, NULL, 2, 1, 3);
CopyWindowToVram(0, COPYWIN_BOTH);
gTasks[taskId].func = Task_Hof_TrySaveData;
}
static void Task_Hof_TrySaveData(u8 taskId)
{
gGameContinueCallback = CB2_DoHallOfFameScreenDontSaveData;
TrySavingData(SAVE_HALL_OF_FAME);
PlaySE(SE_SAVE);
gTasks[taskId].func = Task_Hof_DelayAfterSave;
gTasks[taskId].data[3] = 32;
}
static void Task_Hof_DelayAfterSave(u8 taskId)
{
if (gTasks[taskId].data[3] != 0)
gTasks[taskId].data[3]--;
else
gTasks[taskId].func = Task_Hof_StartDisplayingMons;
}
static void Task_Hof_StartDisplayingMons(u8 taskId)
{
gTasks[taskId].func = Task_Hof_DisplayMon;
}
static void Task_Hof_DisplayMon(u8 taskId)
{
u8 spriteId;
s16 srcX;
s16 srcY;
s16 dstX;
s16 dstY;
u16 currMonId = gTasks[taskId].data[1];
struct HallofFameMon* currMon = &sHofMonPtr[0].mon[currMonId];
if (gTasks[taskId].data[2] > 3)
{
srcX = sHallOfFame_MonFullTeamPositions[currMonId][0];
srcY = sHallOfFame_MonFullTeamPositions[currMonId][1];
dstX = sHallOfFame_MonFullTeamPositions[currMonId][2];
dstY = sHallOfFame_MonFullTeamPositions[currMonId][3];
}
else
{
srcX = sHallOfFame_MonHalfTeamPositions[currMonId][0];
srcY = sHallOfFame_MonHalfTeamPositions[currMonId][1];
dstX = sHallOfFame_MonHalfTeamPositions[currMonId][2];
dstY = sHallOfFame_MonHalfTeamPositions[currMonId][3];
}
spriteId = CreateMonPicSprite_HandleDeoxys(currMon->species, currMon->tid, currMon->personality, 1, srcX, srcY, currMonId, 0xFFFF);
gSprites[spriteId].data[1] = dstX;
gSprites[spriteId].data[2] = dstY;
gSprites[spriteId].data[0] = 0;
gSprites[spriteId].callback = SpriteCB_GetOnScreen;
gTasks[taskId].data[5 + currMonId] = spriteId;
ClearDialogWindowAndFrame(0, TRUE);
gTasks[taskId].func = Task_Hof_PlayMonCryAndPrintInfo;
}
static void Task_Hof_PlayMonCryAndPrintInfo(u8 taskId)
{
u16 currMonId = gTasks[taskId].data[1];
struct HallofFameMon* currMon = &sHofMonPtr[0].mon[currMonId];
if (gSprites[gTasks[taskId].data[5 + currMonId]].data[0])
{
if (currMon->species != SPECIES_EGG)
PlayCry1(currMon->species, 0);
HallOfFame_PrintMonInfo(currMon, 0, 14);
gTasks[taskId].data[3] = 120;
gTasks[taskId].func = Task_Hof_TryDisplayAnotherMon;
}
}
static void Task_Hof_TryDisplayAnotherMon(u8 taskId)
{
u16 currPokeId = gTasks[taskId].data[1];
struct HallofFameMon* currMon = &sHofMonPtr[0].mon[currPokeId];
if (gTasks[taskId].data[3] != 0)
{
gTasks[taskId].data[3]--;
}
else
{
sSelectedPaletteIndices |= (0x10000 << gSprites[gTasks[taskId].data[5 + currPokeId]].oam.paletteNum);
if (gTasks[taskId].data[1] < PARTY_SIZE - 1 && currMon[1].species != SPECIES_NONE) // there is another pokemon to display
{
gTasks[taskId].data[1]++;
BeginNormalPaletteFade(sSelectedPaletteIndices, 0, 12, 12, HALL_OF_FAME_BG_PAL);
gSprites[gTasks[taskId].data[5 + currPokeId]].oam.priority = 1;
gTasks[taskId].func = Task_Hof_DisplayMon;
}
else
{
gTasks[taskId].func = Task_Hof_PaletteFadeAndPrintWelcomeText;
}
}
}
static void Task_Hof_PaletteFadeAndPrintWelcomeText(u8 taskId)
{
u16 i;
BeginNormalPaletteFade(0xFFFF0000, 0, 0, 0, RGB_BLACK);
for (i = 0; i < PARTY_SIZE; i++)
{
if (gTasks[taskId].data[5 + i] != 0xFF)
gSprites[gTasks[taskId].data[5 + i]].oam.priority = 0;
}
HallOfFame_PrintWelcomeText(0, 15);
PlaySE(SE_APPLAUSE);
gTasks[taskId].data[3] = 400;
gTasks[taskId].func = Task_Hof_ApplauseAndConfetti;
}
static void Task_Hof_ApplauseAndConfetti(u8 taskId)
{
if (gTasks[taskId].data[3] != 0)
{
gTasks[taskId].data[3]--;
if ((gTasks[taskId].data[3] & 3) == 0 && gTasks[taskId].data[3] > 110)
Hof_SpawnConfetti();
}
else
{
u16 i;
for (i = 0; i < PARTY_SIZE; i++)
{
if (gTasks[taskId].data[5 + i] != 0xFF)
gSprites[gTasks[taskId].data[5 + i]].oam.priority = 1;
}
BeginNormalPaletteFade(sSelectedPaletteIndices, 0, 12, 12, HALL_OF_FAME_BG_PAL);
FillWindowPixelBuffer(0, PIXEL_FILL(0));
CopyWindowToVram(0, COPYWIN_BOTH);
gTasks[taskId].data[3] = 7;
gTasks[taskId].func = Task_Hof_WaitBorderFadeAway;
}
}
static void Task_Hof_WaitBorderFadeAway(u8 taskId)
{
if (gTasks[taskId].data[3] > 15)
{
gTasks[taskId].func = Task_Hof_SpawnPlayerPic;
}
else
{
gTasks[taskId].data[3]++;
SetGpuReg(REG_OFFSET_BLDALPHA, 256 * gTasks[taskId].data[3]);
}
}
static void Task_Hof_SpawnPlayerPic(u8 taskId)
{
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
ShowBg(0);
ShowBg(1);
ShowBg(3);
gTasks[taskId].data[4] = CreateTrainerPicSprite(PlayerGenderToFrontTrainerPicId_Debug(gSaveBlock2Ptr->playerGender, TRUE), TRUE, 0x78, 0x48, 6, 0xFFFF);
AddWindow(&sWindowTemplate);
TextWindow_SetStdFrame0_WithPal(1, 0x21D, 0xD0);
gTasks[taskId].data[3] = 120;
gTasks[taskId].func = Task_Hof_WaitAndPrintPlayerInfo;
}
static void Task_Hof_WaitAndPrintPlayerInfo(u8 taskId)
{
if (gTasks[taskId].data[3] != 0)
{
gTasks[taskId].data[3]--;
}
else if (gSprites[gTasks[taskId].data[4]].x != 192)
{
gSprites[gTasks[taskId].data[4]].x++;
}
else
{
FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 0x20, 0x20);
HallOfFame_PrintPlayerInfo(1, 2);
DrawDialogueFrame(0, 0);
AddTextPrinterParameterized2(0, 2, gText_LeagueChamp, 0, NULL, 2, 1, 3);
CopyWindowToVram(0, COPYWIN_BOTH);
gTasks[taskId].func = Task_Hof_ExitOnKeyPressed;
}
}
static void Task_Hof_ExitOnKeyPressed(u8 taskId)
{
if (JOY_NEW(A_BUTTON))
{
FadeOutBGM(4);
gTasks[taskId].func = Task_Hof_HandlePaletteOnExit;
}
}
static void Task_Hof_HandlePaletteOnExit(u8 taskId)
{
CpuCopy16(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_BUFFER_SIZE * sizeof(u16));
BeginNormalPaletteFade(0xFFFFFFFF, 8, 0, 16, RGB_BLACK);
gTasks[taskId].func = Task_Hof_HandleExit;
}
static void Task_Hof_HandleExit(u8 taskId)
{
if (!gPaletteFade.active)
{
s32 i;
for (i = 0; i < PARTY_SIZE; i++)
{
u8 spriteId = gTasks[taskId].data[5 + i];
if (spriteId != 0xFF)
{
FreeAndDestroyMonPicSprite(spriteId);
}
}
FreeAndDestroyTrainerPicSprite(gTasks[taskId].data[4]);
HideBg(0);
HideBg(1);
HideBg(3);
FreeAllWindowBuffers();
UnsetBgTilemapBuffer(1);
UnsetBgTilemapBuffer(3);
ResetBgsAndClearDma3BusyFlags(0);
DestroyTask(taskId);
if (sHofGfxPtr != NULL)
FREE_AND_SET_NULL(sHofGfxPtr);
if (sHofMonPtr != NULL)
FREE_AND_SET_NULL(sHofMonPtr);
SetWarpsToRollCredits();
}
}
static void SetWarpsToRollCredits(void)
{
VarSet(VAR_MAP_SCENE_INDIGO_PLATEAU_EXTERIOR, 1);
FlagSet(FLAG_DONT_SHOW_MAP_NAME_POPUP);
gDisableMapMusicChangeOnMapLoad = 2;
SetWarpDestination(MAP_GROUP(INDIGO_PLATEAU_EXTERIOR), MAP_NUM(INDIGO_PLATEAU_EXTERIOR), -1, 11, 6);
DoWarp();
ResetInitialPlayerAvatarState();
}
void CB2_InitHofPC(void)
{
switch (gMain.state)
{
default:
case 0:
SetVBlankCallback(NULL);
ClearVramOamPltt_LoadHofPal();
sHofGfxPtr = AllocZeroed(sizeof(struct HofGfx));
gMain.state = 1;
break;
case 1:
HofInit_ResetGpuBuffersAndLoadConfettiGfx();
gMain.state++;
break;
case 2:
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
SetGpuReg(REG_OFFSET_BLDY, 0);
Hof_InitBgs();
gMain.state++;
break;
case 3:
if (!DrawHofBackground())
{
BeginPCScreenEffect_TurnOn(0, 0, 0);
SetVBlankCallback(VBlankCB_HofIdle);
gMain.state++;
}
break;
case 4:
RunTasks();
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
if (!IsPCScreenEffectRunning_TurnOn())
gMain.state++;
break;
case 5:
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 7));
SetGpuReg(REG_OFFSET_BLDY, 0);
CreateTask(Task_HofPC_CopySaveData, 0);
sHofMonPtr = AllocZeroed(0x2000);
SetMainCallback2(CB2_HofIdle);
break;
}
}
static void Task_HofPC_CopySaveData(u8 taskId)
{
u16 i;
struct HallofFameTeam* savedTeams;
CreateTopBarWindowLoadPalette(0, 30, 0, 0x0C, 0x226);
if (Save_LoadGameData(SAVE_HALL_OF_FAME) != SAVE_STATUS_OK)
{
gTasks[taskId].func = Task_HofPC_PrintDataIsCorrupted;
}
else
{
CpuCopy16(gDecompressionBuffer, sHofMonPtr, 0x2000);
savedTeams = sHofMonPtr;
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, savedTeams++)
{
if (savedTeams->mon[0].species == SPECIES_NONE)
break;
}
if (i < HALL_OF_FAME_MAX_TEAMS)
gTasks[taskId].data[0] = i - 1;
else
gTasks[taskId].data[0] = HALL_OF_FAME_MAX_TEAMS - 1;
gTasks[taskId].data[1] = GetGameStat(GAME_STAT_ENTERED_HOF);
gTasks[taskId].func = Task_HofPC_DrawSpritesPrintText;
}
}
static void Task_HofPC_DrawSpritesPrintText(u8 taskId)
{
struct HallofFameTeam *savedTeams = sHofMonPtr;
struct HallofFameMon *currMon;
u16 i;
for (i = 0; i < gTasks[taskId].data[0]; i++)
savedTeams++;
currMon = &savedTeams->mon[0];
sSelectedPaletteIndices = 0;
gTasks[taskId].data[2] = 0;
gTasks[taskId].data[4] = 0;
for (i = 0; i < PARTY_SIZE; i++, currMon++)
{
if (currMon->species != SPECIES_NONE)
gTasks[taskId].data[4]++;
}
currMon = &savedTeams->mon[0];
for (i = 0; i < PARTY_SIZE; i++, currMon++)
{
if (currMon->species != SPECIES_NONE)
{
u16 spriteId;
s16 posX, posY;
if (gTasks[taskId].data[4] > 3)
{
posX = sHallOfFame_MonFullTeamPositions[i][2];
posY = sHallOfFame_MonFullTeamPositions[i][3];
}
else
{
posX = sHallOfFame_MonHalfTeamPositions[i][2];
posY = sHallOfFame_MonHalfTeamPositions[i][3];
}
spriteId = CreateMonPicSprite_HandleDeoxys(currMon->species, currMon->tid, currMon->personality, TRUE, posX,
posY, i, 0xFFFF);
gSprites[spriteId].oam.priority = 1;
gTasks[taskId].data[5 + i] = spriteId;
}
else
{
gTasks[taskId].data[5 + i] = 0xFF;
}
}
BlendPalettes(0xFFFF0000, 0xC, HALL_OF_FAME_BG_PAL);
ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].data[1], STR_CONV_MODE_LEFT_ALIGN, 3);
StringExpandPlaceholders(gStringVar4, gText_HOFNumber);
if (gTasks[taskId].data[0] <= 0)
TopBarWindowPrintTwoStrings(gStringVar4, gText_UPDOWNPick_ABUTTONBBUTTONCancel, 0, 0, TRUE);
else
TopBarWindowPrintTwoStrings(gStringVar4, gText_UPDOWNPick_ABUTTONNext_BBUTTONBack, 0, 0, TRUE);
gTasks[taskId].func = Task_HofPC_PrintMonInfo;
}
static void Task_HofPC_PrintMonInfo(u8 taskId)
{
struct HallofFameTeam* savedTeams = sHofMonPtr;
struct HallofFameMon* currMon;
u16 i;
u16 currMonId;
for (i = 0; i < gTasks[taskId].data[0]; i++)
savedTeams++;
for (i = 0; i < PARTY_SIZE; i++)
{
u16 spriteId = gTasks[taskId].data[5 + i];
if (spriteId != 0xFF)
gSprites[spriteId].oam.priority = 1;
}
currMonId = gTasks[taskId].data[5 + gTasks[taskId].data[2]];
gSprites[currMonId].oam.priority = 0;
sSelectedPaletteIndices = (0x10000 << gSprites[currMonId].oam.paletteNum) ^ 0xFFFF0000;
BlendPalettesUnfaded(sSelectedPaletteIndices, 0xC, HALL_OF_FAME_BG_PAL);
currMon = &savedTeams->mon[gTasks[taskId].data[2]];
if (currMon->species != SPECIES_EGG)
{
StopCryAndClearCrySongs();
PlayCry1(currMon->species, 0);
}
HallOfFame_PrintMonInfo(currMon, 0, 14);
gTasks[taskId].func = Task_HofPC_HandleInput;
}
static void Task_HofPC_HandleInput(u8 taskId)
{
u16 i;
if (JOY_NEW(A_BUTTON))
{
if (gTasks[taskId].data[0] != 0) // prepare another team to view
{
gTasks[taskId].data[0]--;
for (i = 0; i < 6; i++)
{
u8 spriteId = gTasks[taskId].data[5 + i];
if (spriteId != 0xFF)
{
FreeAndDestroyMonPicSprite(spriteId);
}
}
if (gTasks[taskId].data[1] != 0)
gTasks[taskId].data[1]--;
gTasks[taskId].func = Task_HofPC_DrawSpritesPrintText;
}
else // no more teams to view, turn off hall of fame PC
{
if (IsCryPlayingOrClearCrySongs())
{
StopCryAndClearCrySongs();
m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x100);
}
gTasks[taskId].func = Task_HofPC_HandlePaletteOnExit;
}
}
else if (JOY_NEW(B_BUTTON)) // turn off hall of fame PC
{
if (IsCryPlayingOrClearCrySongs())
{
StopCryAndClearCrySongs();
m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x100);
}
gTasks[taskId].func = Task_HofPC_HandlePaletteOnExit;
}
else if (JOY_NEW(DPAD_UP) && gTasks[taskId].data[2] != 0) // change mon -1
{
gTasks[taskId].data[2]--;
gTasks[taskId].func = Task_HofPC_PrintMonInfo;
}
else if (JOY_NEW(DPAD_DOWN) && gTasks[taskId].data[2] < gTasks[taskId].data[4] - 1) // change mon +1
{
gTasks[taskId].data[2]++;
gTasks[taskId].func = Task_HofPC_PrintMonInfo;
}
}
static void Task_HofPC_HandlePaletteOnExit(u8 taskId)
{
struct HallofFameTeam* fameTeam;
CpuCopy16(gPlttBufferFaded, gPlttBufferUnfaded, 0x400);
BeginPCScreenEffect_TurnOff(0, 0, 0);
gTasks[taskId].func = Task_HofPC_HandleExit;
}
static void Task_HofPC_HandleExit(u8 taskId)
{
if (!IsPCScreenEffectRunning_TurnOff())
{
HideBg(0);
HideBg(1);
HideBg(3);
DestroyTopBarWindow();
FreeAllWindowBuffers();
UnsetBgTilemapBuffer(1);
UnsetBgTilemapBuffer(3);
ResetBgsAndClearDma3BusyFlags(FALSE);
DestroyTask(taskId);
if (sHofGfxPtr != NULL)
FREE_AND_SET_NULL(sHofGfxPtr);
if (sHofMonPtr != NULL)
FREE_AND_SET_NULL(sHofMonPtr);
ReturnFromHallOfFamePC();
}
}
static void Task_HofPC_PrintDataIsCorrupted(u8 taskId)
{
TopBarWindowPrintString(gText_ABUTTONExit, 8, TRUE);
DrawDialogueFrame(0, 0);
AddTextPrinterParameterized2(0, 2, gText_HOFCorrupted, 0, NULL, 2, 1, 3);
CopyWindowToVram(0, COPYWIN_BOTH);
gTasks[taskId].func = Task_HofPC_ExitOnButtonPress;
}
static void Task_HofPC_ExitOnButtonPress(u8 taskId)
{
if (JOY_NEW(A_BUTTON))
gTasks[taskId].func = Task_HofPC_HandlePaletteOnExit;
}
static void HallOfFame_PrintWelcomeText(u8 not, u8 used)
{
u8 x = (0xD0 - GetStringWidth(2, gText_WelcomeToHOF, 0)) / 2;
FillWindowPixelBuffer(0, PIXEL_FILL(0));
PutWindowTilemap(0);
AddTextPrinterParameterized3(0, 2, x, 1, sTextColors[0], 0, gText_WelcomeToHOF);
CopyWindowToVram(0, COPYWIN_BOTH);
}
static void HallOfFame_PrintMonInfo(struct HallofFameMon* currMon, u8 unused1, u8 unused2)
{
u8 text[16];
u8 text2[24];
u16 i;
u8 *stringPtr;
u16 dexNumber;
u8 gender;
s32 width;
s32 x;
FillWindowPixelBuffer(0, PIXEL_FILL(0));
PutWindowTilemap(0);
// dex number
if (currMon->species != SPECIES_EGG)
{
StringCopy(text2, gText_Number);
dexNumber = SpeciesToPokedexNum(currMon->species);
if (dexNumber != 0xFFFF)
{
text[0] = (dexNumber / 100) + CHAR_0;
text[1] = ((dexNumber %= 100) / 10) + CHAR_0;
text[2] = (dexNumber % 10) + CHAR_0;
}
else
{
text[0] = text[1] = text[2] = CHAR_QUESTION_MARK;
}
text[3] = EOS;
StringAppend(text2, text);
AddTextPrinterParameterized3(0, 2, 0x10, 1, sTextColors[0], 0, text2);
}
// nick, species names, gender and lvl
i = 0;
if (currMon->nick[0] != EOS)
{
for (i = 0; i < 10 && currMon->nick[i] != EOS; i++)
{
text[i] = currMon->nick[i];
}
}
text[i] = EOS;
width = GetStringWidth(2, text, GetFontAttribute(2, FONTATTR_LETTER_SPACING));
if (currMon->species == SPECIES_EGG)
x = 0x80 - width / 2;
else
x = 0x80 - width;
AddTextPrinterParameterized3(0, 2, x, 1, sTextColors[0], 0, text);
if (currMon->species != SPECIES_EGG)
{
text[0] = CHAR_SLASH;
stringPtr = StringCopy(text + 1, gSpeciesNames[currMon->species]);
if (currMon->species == SPECIES_NIDORAN_M || currMon->species == SPECIES_NIDORAN_F)
gender = MON_GENDERLESS;
else
gender = GetGenderFromSpeciesAndPersonality(currMon->species, currMon->personality);
switch (gender)
{
case MON_MALE:
*stringPtr++ = CHAR_MALE;
break;
case MON_FEMALE:
*stringPtr++ = CHAR_FEMALE;
break;
default:
*stringPtr++ = CHAR_SPACE;
break;
}
*stringPtr = EOS;
AddTextPrinterParameterized3(0, 2, 0x80, 1, sTextColors[0], 0, text);
stringPtr = StringCopy(text, gText_Level);
ConvertIntToDecimalStringN(stringPtr, currMon->lvl, STR_CONV_MODE_LEFT_ALIGN, 3);
AddTextPrinterParameterized3(0, 2, 0x20, 0x11, sTextColors[0], 0, text);
stringPtr = StringCopy(text, gText_IDNumber);
ConvertIntToDecimalStringN(stringPtr, (u16)(currMon->tid), STR_CONV_MODE_LEADING_ZEROS, 5);
AddTextPrinterParameterized3(0, 2, 0x60, 0x11, sTextColors[0], 0, text);
}
CopyWindowToVram(0, COPYWIN_BOTH);
}
static void HallOfFame_PrintPlayerInfo(u8 unused1, u8 unused2)
{
u8 text[20];
u16 trainerId;
s32 textWidth = sWindowTemplate.width * 8 - 6;
FillWindowPixelBuffer(1, PIXEL_FILL(1));
PutWindowTilemap(1);
DrawStdFrameWithCustomTileAndPalette(1, FALSE, 0x21D, 0xD);
AddTextPrinterParameterized4(1, 2, 4, 3, 0, 0, sTextColors[1], 0, gText_Name);
AddTextPrinterParameterized3(1, 2, textWidth - GetStringWidth(2, gSaveBlock2Ptr->playerName, 0), 3, sTextColors[1], 0, gSaveBlock2Ptr->playerName);
trainerId = (gSaveBlock2Ptr->playerTrainerId[0]) | (gSaveBlock2Ptr->playerTrainerId[1] << 8);
AddTextPrinterParameterized3(1, 2, 4, 18, sTextColors[1], 0, gText_IDNumber);
text[0] = (trainerId % 100000) / 10000 + CHAR_0;
text[1] = (trainerId % 10000) / 1000 + CHAR_0;
text[2] = (trainerId % 1000) / 100 + CHAR_0;
text[3] = (trainerId % 100) / 10 + CHAR_0;
text[4] = (trainerId % 10) / 1 + CHAR_0;
text[5] = EOS;
AddTextPrinterParameterized3(1, 2, textWidth - 30, 18, sTextColors[1], 0, text);
AddTextPrinterParameterized3(1, 2, 4, 32, sTextColors[1], 0, gText_MainMenuTime);
text[0] = (gSaveBlock2Ptr->playTimeHours / 100) + CHAR_0;
text[1] = (gSaveBlock2Ptr->playTimeHours % 100) / 10 + CHAR_0;
text[2] = (gSaveBlock2Ptr->playTimeHours % 10) + CHAR_0;
if (text[0] == CHAR_0)
text[0] = CHAR_SPACE;
if (text[0] == CHAR_SPACE && text[1] == CHAR_0)
text[1] = CHAR_SPACE;
text[3] = CHAR_COLON;
text[4] = (gSaveBlock2Ptr->playTimeMinutes % 100) / 10 + CHAR_0;
text[5] = (gSaveBlock2Ptr->playTimeMinutes % 10) + CHAR_0;
text[6] = EOS;
AddTextPrinterParameterized3(1, 2, textWidth - 36, 32, sTextColors[1], 0, text);
CopyWindowToVram(1, COPYWIN_BOTH);
}
static void ClearVramOamPltt_LoadHofPal(void)
{
u32 vramOffset, oamOffset, plttOffset;
u32 vramSize, oamSize, plttSize;
vramOffset = (VRAM);
vramSize = VRAM_SIZE;
while (TRUE)
{
DmaFill16(3, 0, vramOffset, 0x1000);
vramOffset += 0x1000;
vramSize -= 0x1000;
if (vramSize <= 0x1000)
{
DmaFill16(3, 0, vramOffset, vramSize);
break;
}
}
oamOffset = OAM;
oamSize = OAM_SIZE;
DmaFill32(3, 0, oamOffset, oamSize);
plttOffset = PLTT;
plttSize = PLTT_SIZE;
DmaFill16(3, 0, plttOffset, plttSize);
ResetPaletteFade();
LoadPalette(sHallOfFame_Pal, 0, 0x20);
}
static void HofInit_ResetGpuBuffersAndLoadConfettiGfx(void)
{
ScanlineEffect_Stop();
ResetTasks();
ResetSpriteData();
ResetTempTileDataBuffers();
ResetAllPicSprites();
FreeAllSpritePalettes();
gReservedSpritePaletteCount = 8;
LoadCompressedSpriteSheet(sHallOfFame_ConfettiSpriteSheet);
LoadCompressedSpritePalette(sHallOfFame_ConfettiSpritePalette);
}
static void Hof_InitBgs(void)
{
ResetBgsAndClearDma3BusyFlags(0);
InitBgsFromTemplates(0, sHof_BgTemplates, NELEMS(sHof_BgTemplates));
SetBgTilemapBuffer(1, sHofGfxPtr->tilemap1);
SetBgTilemapBuffer(3, sHofGfxPtr->tilemap2);
ChangeBgX(0, 0, 0);
ChangeBgY(0, 0, 0);
ChangeBgX(1, 0, 0);
ChangeBgY(1, 0, 0);
ChangeBgX(3, 0, 0);
ChangeBgY(3, 0, 0);
}
static bool8 DrawHofBackground(void)
{
switch (sHofGfxPtr->state)
{
case 0:
DecompressAndCopyTileDataToVram(1, sHallOfFame_Gfx, 0, 0, 0);
break;
case 1:
if (FreeTempTileDataBuffersIfPossible())
return TRUE;
break;
case 2:
FillBgTilemapBufferRect_Palette0(1, 1, 0, 0, 0x20, 2);
FillBgTilemapBufferRect_Palette0(1, 0, 0, 3, 0x20, 0xB);
FillBgTilemapBufferRect_Palette0(1, 1, 0, 0xE, 0x20, 6);
FillBgTilemapBufferRect_Palette0(3, 2, 0, 0, 0x20, 0x20);
CopyBgTilemapBufferToVram(1);
CopyBgTilemapBufferToVram(3);
break;
case 3:
InitStandardTextBoxWindows();
InitTextBoxGfxAndPrinters();
break;
case 4:
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
ShowBg(0);
ShowBg(1);
ShowBg(3);
sHofGfxPtr->state = 0;
return FALSE;
}
sHofGfxPtr->state++;
return TRUE;
}
static void SpriteCB_EndGetOnScreen(struct Sprite * sprite)
{
}
static void SpriteCB_GetOnScreen(struct Sprite * sprite)
{
if (sprite->x != sprite->data[1]
|| sprite->y != sprite->data[2])
{
if (sprite->x < sprite->data[1])
sprite->x += 15;
if (sprite->x > sprite->data[1])
sprite->x -= 15;
if (sprite->y < sprite->data[2])
sprite->y += 10;
if (sprite->y > sprite->data[2])
sprite->y -= 10;
}
else
{
sprite->data[0] = 1;
sprite->callback = SpriteCB_EndGetOnScreen;
}
}
static void SpriteCB_Confetti(struct Sprite* sprite)
{
if (sprite->y2 > 120)
{
DestroySprite(sprite);
}
else
{
u16 rand;
u8 tableID;
sprite->y2++;
sprite->y2 += sprite->data[1];
tableID = sprite->data[0];
rand = (Random() % 4) + 8;
sprite->x2 = rand * gSineTable[tableID] / 256;
sprite->data[0] += 4;
}
}
static bool8 Hof_SpawnConfetti(void)
{
u8 spriteId;
struct Sprite* sprite;
s16 posX = Random() % 240;
s16 posY = -(Random() % 8);
spriteId = CreateSprite(&sSpriteTemplate_Confetti, posX, posY, 0);
sprite = &gSprites[spriteId];
StartSpriteAnim(sprite, Random() % 17);
if (Random() & 3)
sprite->data[1] = 0;
else
sprite->data[1] = 1;
return FALSE;
}