pokefirered/src/oak_speech.c

2187 lines
70 KiB
C

#include "global.h"
#include "gflib.h"
#include "decompress.h"
#include "task.h"
#include "blend_palette.h"
#include "text_window.h"
#include "menu.h"
#include "help_system.h"
#include "new_menu_helpers.h"
#include "event_scripts.h"
#include "scanline_effect.h"
#include "pokeball.h"
#include "naming_screen.h"
#include "math_util.h"
#include "overworld.h"
#include "random.h"
#include "data.h"
#include "constants/songs.h"
#define INTRO_SPECIES SPECIES_NIDORAN_F
enum
{
WIN_INTRO_TEXTBOX,
WIN_INTRO_BOYGIRL,
WIN_INTRO_YESNO,
WIN_INTRO_NAMES,
NUM_INTRO_WINDOWS,
};
struct OakSpeechResources
{
void *oakSpeechBackgroundTiles;
void *trainerPicTilemap;
void *pikachuIntroTilemap;
void *unused1;
u16 hasPlayerBeenNamed;
u16 currentPage;
u16 windowIds[NUM_INTRO_WINDOWS];
u8 textColor[3];
u8 textSpeed;
u8 unused2[0x1800];
u8 bg2TilemapBuffer[0x400];
u8 bg1TilemapBuffer[0x800];
};
static EWRAM_DATA struct OakSpeechResources *sOakSpeechResources = NULL;
static void Task_NewGameScene(u8);
static void ControlsGuide_LoadPage1(void);
static void Task_ControlsGuide_HandleInput(u8);
static void Task_ControlsGuide_ChangePage(u8);
static void Task_ControlsGuide_Clear(u8);
static void Task_PikachuIntro_LoadPage1(u8);
static void Task_PikachuIntro_HandleInput(u8);
static void Task_PikachuIntro_Clear(u8);
static void Task_OakSpeech_Init(u8);
static void Task_OakSpeech_WelcomeToTheWorld(u8);
static void Task_OakSpeech_ThisWorld(u8);
static void Task_OakSpeech_ReleaseNidoranFFromPokeBall(u8);
static void Task_OakSpeech_IsInhabitedFarAndWide(u8);
static void Task_OakSpeech_IStudyPokemon(u8);
static void Task_OakSpeech_ReturnNidoranFToPokeBall(u8);
static void Task_OakSpeech_TellMeALittleAboutYourself(u8);
static void Task_OakSpeech_FadeOutOak(u8);
static void Task_OakSpeech_AskPlayerGender(u8);
static void Task_OakSpeech_ShowGenderOptions(u8);
static void Task_OakSpeech_HandleGenderInput(u8);
static void Task_OakSpeech_ClearGenderWindows(u8);
static void Task_OakSpeech_LoadPlayerPic(u8);
static void Task_OakSpeech_YourNameWhatIsIt(u8);
static void Task_OakSpeech_FadeOutForPlayerNamingScreen(u8);
static void Task_OakSpeech_HandleRivalNameInput(u8);
static void Task_OakSpeech_DoNamingScreen(u8);
static void Task_OakSpeech_ConfirmName(u8);
static void Task_OakSpeech_HandleConfirmNameInput(u8);
static void Task_OakSpeech_FadeOutPlayerPic(u8);
static void Task_OakSpeech_FadeOutRivalPic(u8);
static void Task_OakSpeech_FadeInRivalPic(u8);
static void Task_OakSpeech_AskRivalsName(u8);
static void Task_OakSpeech_ReshowPlayersPic(u8);
static void Task_OakSpeech_LetsGo(u8);
static void Task_OakSpeech_FadeOutBGM(u8);
static void Task_OakSpeech_SetUpExitAnimation(u8);
static void Task_OakSpeech_SetUpShrinkPlayerPic(u8);
static void Task_OakSpeech_ShrinkPlayerPic(u8);
static void Task_OakSpeech_SetUpDestroyPlatformSprites(u8);
static void Task_OakSpeech_DestroyPlatformSprites(u8);
static void Task_OakSpeech_SetUpFadePlayerPicWhite(u8);
static void Task_OakSpeech_FadePlayerPicWhite(u8);
static void Task_OakSpeech_FadePlayerPicToBlack(u8);
static void Task_OakSpeech_WaitForFade(u8);
static void Task_OakSpeech_FreeResources(u8);
static void CB2_ReturnFromNamingScreen(void);
static void CreateNidoranFSprite(u8);
static void CreatePikachuOrPlatformSprites(u8, u8);
static void DestroyPikachuOrPlatformSprites(u8, u8);
static void LoadTrainerPic(u16, u16);
static void ClearTrainerPic(void);
static void CreateFadeInTask(u8, u8);
static void CreateFadeOutTask(u8, u8);
static void PrintNameChoiceOptions(u8, u8);
static void GetDefaultName(u8, u8);
extern const u8 gText_Controls[];
extern const u8 gText_ABUTTONNext[];
extern const u8 gText_ABUTTONNext_BBUTTONBack[];
extern const u8 gText_Boy[];
extern const u8 gText_Girl[];
extern const struct OamData gOamData_AffineOff_ObjBlend_32x32;
extern const struct OamData gOamData_AffineOff_ObjNormal_32x32;
extern const struct OamData gOamData_AffineOff_ObjNormal_32x16;
extern const struct OamData gOamData_AffineOff_ObjNormal_16x8;
static const u16 sOakSpeech_Background_Pals[] = INCBIN_U16("graphics/oak_speech/bg_tiles.gbapal"); // Shared by the Controls Guide, Pikachu Intro and Oak Speech scenes
static const u32 sControlsGuide_PikachuIntro_Background_Tiles[] = INCBIN_U32("graphics/oak_speech/bg_tiles.4bpp.lz");
static const u32 sPikachuIntro_Background_Tilemap[] = INCBIN_U32("graphics/oak_speech/pikachu_intro/tilemap.bin.lz");
static const u32 sOakSpeech_Background_Tiles[] = INCBIN_U32("graphics/oak_speech/oak_speech_bg.4bpp.lz");
static const u32 sOakSpeech_Background_Tilemap[] = INCBIN_U32("graphics/oak_speech/oak_speech_bg.bin.lz");
static const u16 sControlsGuide_Tilemap_Page2[] = INCBIN_U16("graphics/oak_speech/controls_guide_page_2.bin");
static const u16 sControlsGuide_Tilemap_Page3[] = INCBIN_U16("graphics/oak_speech/controls_guide_page_3.bin");
static const u16 sOakSpeech_Leaf_Pal[] = INCBIN_U16("graphics/oak_speech/leaf/pal.gbapal");
static const u32 sOakSpeech_Leaf_Tiles[] = INCBIN_U32("graphics/oak_speech/leaf/pic.8bpp.lz");
static const u16 sOakSpeech_Red_Pal[] = INCBIN_U16("graphics/oak_speech/red/pal.gbapal");
static const u32 sOakSpeech_Red_Tiles[] = INCBIN_U32("graphics/oak_speech/red/pic.8bpp.lz");
static const u16 sOakSpeech_Oak_Pal[] = INCBIN_U16("graphics/oak_speech/oak/pal.gbapal");
static const u32 sOakSpeech_Oak_Tiles[] = INCBIN_U32("graphics/oak_speech/oak/pic.8bpp.lz");
static const u16 sOakSpeech_Rival_Pal[] = INCBIN_U16("graphics/oak_speech/rival/pal.gbapal");
static const u32 sOakSpeech_Rival_Tiles[] = INCBIN_U32("graphics/oak_speech/rival/pic.8bpp.lz");
static const u16 sOakSpeech_Platform_Pal[] = INCBIN_U16("graphics/oak_speech/platform.gbapal");
static const u16 sPikachuIntro_Pikachu_Pal[] = INCBIN_U16("graphics/oak_speech/pikachu_intro/pikachu.gbapal");
static const u32 sOakSpeech_Platform_Gfx[] = INCBIN_U32("graphics/oak_speech/platform.4bpp.lz");
static const u32 sPikachuIntro_PikachuBody_Gfx[] = INCBIN_U32("graphics/oak_speech/pikachu_intro/body.4bpp.lz");
static const u32 sPikachuIntro_PikachuEars_Gfx[] = INCBIN_U32("graphics/oak_speech/pikachu_intro/ears.4bpp.lz");
static const u32 sPikachuIntro_PikachuEyes_Gfx[] = INCBIN_U32("graphics/oak_speech/pikachu_intro/eyes.4bpp.lz");
static const struct BgTemplate sBgTemplates[] =
{
{
.bg = 0,
.charBaseIndex = 2,
.mapBaseIndex = 31,
.screenSize = 0,
.paletteMode = 0,
.priority = 0,
.baseTile = 0
},
{
.bg = 1,
.charBaseIndex = 0,
.mapBaseIndex = 30,
.screenSize = 0,
.paletteMode = 0,
.priority = 2,
.baseTile = 0
},
{
.bg = 2,
.charBaseIndex = 0,
.mapBaseIndex = 28,
.screenSize = 1,
.paletteMode = 1,
.priority = 1,
.baseTile = 0
}
};
enum
{
CONTROLS_GUIDE_PAGE_1_WINDOW,
NUM_CONTROLS_GUIDE_PAGE_1_WINDOWS,
};
static const struct WindowTemplate sControlsGuide_WindowTemplate_Page1[NUM_CONTROLS_GUIDE_PAGE_1_WINDOWS + 1] =
{
[CONTROLS_GUIDE_PAGE_1_WINDOW] =
{
.bg = 0,
.tilemapLeft = 0,
.tilemapTop = 7,
.width = 30,
.height = 4,
.paletteNum = 15,
.baseBlock = 1
},
DUMMY_WIN_TEMPLATE
};
enum
{
CONTROLS_GUIDE_PAGES_2_3_WINDOW_TOP,
CONTROLS_GUIDE_PAGES_2_3_WINDOW_MIDDLE,
CONTROLS_GUIDE_PAGES_2_3_WINDOW_BOTTOM,
NUM_CONTROLS_GUIDE_PAGES_2_3_WINDOWS,
};
static const struct WindowTemplate sControlsGuide_WindowTemplate_Page2[NUM_CONTROLS_GUIDE_PAGES_2_3_WINDOWS + 1] =
{
[CONTROLS_GUIDE_PAGES_2_3_WINDOW_TOP] =
{
.bg = 0,
.tilemapLeft = 6,
.tilemapTop = 3,
.width = 24,
.height = 6,
.paletteNum = 15,
.baseBlock = 1
},
[CONTROLS_GUIDE_PAGES_2_3_WINDOW_MIDDLE] =
{
.bg = 0,
.tilemapLeft = 6,
.tilemapTop = 10,
.width = 24,
.height = 4,
.paletteNum = 15,
.baseBlock = 146
},
[CONTROLS_GUIDE_PAGES_2_3_WINDOW_BOTTOM] =
{
.bg = 0,
.tilemapLeft = 6,
.tilemapTop = 15,
.width = 24,
.height = 4,
.paletteNum = 15,
.baseBlock = 243
},
DUMMY_WIN_TEMPLATE
};
static const struct WindowTemplate sControlsGuide_WindowTemplate_Page3[NUM_CONTROLS_GUIDE_PAGES_2_3_WINDOWS + 1] =
{
[CONTROLS_GUIDE_PAGES_2_3_WINDOW_TOP] =
{
.bg = 0,
.tilemapLeft = 6,
.tilemapTop = 3,
.width = 24,
.height = 4,
.paletteNum = 15,
.baseBlock = 1
},
[CONTROLS_GUIDE_PAGES_2_3_WINDOW_MIDDLE] =
{
.bg = 0,
.tilemapLeft = 6,
.tilemapTop = 8,
.width = 24,
.height = 4,
.paletteNum = 15,
.baseBlock = 98
},
[CONTROLS_GUIDE_PAGES_2_3_WINDOW_BOTTOM] =
{
.bg = 0,
.tilemapLeft = 6,
.tilemapTop = 13,
.width = 24,
.height = 6,
.paletteNum = 15,
.baseBlock = 195
},
DUMMY_WIN_TEMPLATE
};
enum
{
CONTROLS_GUIDE_PAGE_1,
CONTROLS_GUIDE_PAGE_2,
CONTROLS_GUIDE_PAGE_3,
NUM_CONTROLS_GUIDE_PAGES,
};
static const struct WindowTemplate *const sControlsGuide_WindowTemplates[NUM_CONTROLS_GUIDE_PAGES] =
{
[CONTROLS_GUIDE_PAGE_1] = sControlsGuide_WindowTemplate_Page1,
[CONTROLS_GUIDE_PAGE_2] = sControlsGuide_WindowTemplate_Page2,
[CONTROLS_GUIDE_PAGE_3] = sControlsGuide_WindowTemplate_Page3
};
static const struct WindowTemplate sIntro_WindowTemplates[NUM_INTRO_WINDOWS + 1] =
{
[WIN_INTRO_TEXTBOX] =
{
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 4,
.width = 28,
.height = 15,
.paletteNum = 15,
.baseBlock = 1
},
[WIN_INTRO_BOYGIRL] =
{
.bg = 0,
.tilemapLeft = 18,
.tilemapTop = 9,
.width = 9,
.height = 4,
.paletteNum = 15,
.baseBlock = 372
},
[WIN_INTRO_YESNO] =
{
.bg = 0,
.tilemapLeft = 2,
.tilemapTop = 2,
.width = 6,
.height = 4,
.paletteNum = 15,
.baseBlock = 384
},
[WIN_INTRO_NAMES] =
{
.bg = 0,
.tilemapLeft = 2,
.tilemapTop = 2,
.width = 12,
.height = 10,
.paletteNum = 15,
.baseBlock = 1
},
DUMMY_WIN_TEMPLATE
};
static const u8 sTextColor_White[] = { 0, 1, 2, 0 };
static const u8 sTextColor_DarkGray[] = { 0, 2, 3, 0 };
enum
{
PIKACHU_INTRO_PAGE_1,
PIKACHU_INTRO_PAGE_2,
PIKACHU_INTRO_PAGE_3,
NUM_PIKACHU_INTRO_PAGES,
};
static const u8 *const sPikachuIntro_Strings[NUM_PIKACHU_INTRO_PAGES] =
{
[PIKACHU_INTRO_PAGE_1] = gPikachuIntro_Text_Page1,
[PIKACHU_INTRO_PAGE_2] = gPikachuIntro_Text_Page2,
[PIKACHU_INTRO_PAGE_3] = gPikachuIntro_Text_Page3
};
#define GFX_TAG_PLATFORM 0x1000
#define GFX_TAG_PIKACHU 0x1001
#define GFX_TAG_PIKACHU_EARS 0x1002
#define GFX_TAG_PIKACHU_EYES 0x1003
#define PAL_TAG_PLATFORM 0x1000
#define PAL_TAG_PIKACHU 0x1001
enum
{
SPRITE_TYPE_PIKACHU,
SPRITE_TYPE_PLATFORM,
};
enum
{
PIKACHU_BODY_PLATFORM_LEFT,
PIKACHU_EARS_PLATFORM_MIDDLE,
PIKACHU_EYES_PLATFORM_RIGHT,
NUM_PIKACHU_PLATFORM_SPRITES,
};
static const struct CompressedSpriteSheet sPikachuIntro_Pikachu_SpriteSheets[] =
{
[PIKACHU_BODY_PLATFORM_LEFT] =
{
.data = sPikachuIntro_PikachuBody_Gfx,
.size = 0x400,
.tag = GFX_TAG_PIKACHU
},
[PIKACHU_EARS_PLATFORM_MIDDLE] =
{
.data = sPikachuIntro_PikachuEars_Gfx,
.size = 0x200,
.tag = GFX_TAG_PIKACHU_EARS
},
[PIKACHU_EYES_PLATFORM_RIGHT] =
{
.data = sPikachuIntro_PikachuEyes_Gfx,
.size = 0x80,
.tag = GFX_TAG_PIKACHU_EYES
},
};
static const struct CompressedSpriteSheet sOakSpeech_Platform_SpriteSheet =
{
.data = sOakSpeech_Platform_Gfx,
.size = 0x600,
.tag = GFX_TAG_PLATFORM
};
static const struct SpritePalette sPikachuIntro_Pikachu_SpritePalette =
{
.data = sPikachuIntro_Pikachu_Pal,
.tag = PAL_TAG_PIKACHU
};
static const struct SpritePalette sOakSpeech_Platform_SpritePalette =
{
.data = sOakSpeech_Platform_Pal,
.tag = PAL_TAG_PLATFORM
};
static const union AnimCmd sOakSpeech_PlatformLeft_Anim[] =
{
ANIMCMD_FRAME( 0, 0),
ANIMCMD_END
};
static const union AnimCmd sOakSpeech_PlatformMiddle_Anim[] =
{
ANIMCMD_FRAME(16, 0),
ANIMCMD_END
};
static const union AnimCmd sOakSpeech_PlatformRight_Anim[] =
{
ANIMCMD_FRAME(32, 0),
ANIMCMD_END
};
static const union AnimCmd *const sOakSpeech_PlatformLeft_Anims[] =
{
sOakSpeech_PlatformLeft_Anim
};
static const union AnimCmd *const sOakSpeech_PlatformMiddle_Anims[] =
{
sOakSpeech_PlatformMiddle_Anim
};
static const union AnimCmd *const sOakSpeech_PlatformRight_Anims[] =
{
sOakSpeech_PlatformRight_Anim
};
static const struct SpriteTemplate sOakSpeech_Platform_SpriteTemplates[] =
{
[PIKACHU_BODY_PLATFORM_LEFT] =
{
.tileTag = GFX_TAG_PLATFORM,
.paletteTag = PAL_TAG_PLATFORM,
.oam = &gOamData_AffineOff_ObjBlend_32x32,
.anims = sOakSpeech_PlatformLeft_Anims,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
},
[PIKACHU_EARS_PLATFORM_MIDDLE] =
{
.tileTag = GFX_TAG_PLATFORM,
.paletteTag = PAL_TAG_PLATFORM,
.oam = &gOamData_AffineOff_ObjBlend_32x32,
.anims = sOakSpeech_PlatformMiddle_Anims,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
},
[PIKACHU_EYES_PLATFORM_RIGHT] =
{
.tileTag = GFX_TAG_PLATFORM,
.paletteTag = PAL_TAG_PLATFORM,
.oam = &gOamData_AffineOff_ObjBlend_32x32,
.anims = sOakSpeech_PlatformRight_Anims,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
},
};
static const union AnimCmd sPikachuIntro_PikachuBody_Anim[] =
{
ANIMCMD_FRAME( 0, 30),
ANIMCMD_FRAME(16, 30),
ANIMCMD_JUMP(0)
};
static const union AnimCmd sPikachuIntro_PikachuEars_Anim[] =
{
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(8, 12),
ANIMCMD_FRAME(0, 12),
ANIMCMD_FRAME(8, 12),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(8, 12),
ANIMCMD_FRAME(0, 12),
ANIMCMD_FRAME(8, 12),
ANIMCMD_JUMP(0)
};
static const union AnimCmd sPikachuIntro_PikachuEyes_Anim[] =
{
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(2, 8),
ANIMCMD_FRAME(0, 8),
ANIMCMD_FRAME(2, 8),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(0, 60),
ANIMCMD_FRAME(2, 8),
ANIMCMD_FRAME(0, 8),
ANIMCMD_FRAME(2, 8),
ANIMCMD_JUMP(0)
};
static const union AnimCmd *const sPikachuIntro_PikachuBody_Anims[] =
{
sPikachuIntro_PikachuBody_Anim
};
static const union AnimCmd *const sPikachuIntro_PikachuEars_Anims[] =
{
sPikachuIntro_PikachuEars_Anim
};
static const union AnimCmd *const sPikachuIntro_PikachuEyes_Anims[] =
{
sPikachuIntro_PikachuEyes_Anim
};
static const struct SpriteTemplate sPikachuIntro_Pikachu_SpriteTemplates[NUM_PIKACHU_PLATFORM_SPRITES] =
{
[PIKACHU_BODY_PLATFORM_LEFT] =
{
.tileTag = GFX_TAG_PIKACHU,
.paletteTag = PAL_TAG_PIKACHU,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = sPikachuIntro_PikachuBody_Anims,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
},
[PIKACHU_EARS_PLATFORM_MIDDLE] =
{
.tileTag = GFX_TAG_PIKACHU_EARS,
.paletteTag = PAL_TAG_PIKACHU,
.oam = &gOamData_AffineOff_ObjNormal_32x16,
.anims = sPikachuIntro_PikachuEars_Anims,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
},
[PIKACHU_EYES_PLATFORM_RIGHT] =
{
.tileTag = GFX_TAG_PIKACHU_EYES,
.paletteTag = PAL_TAG_PIKACHU,
.oam = &gOamData_AffineOff_ObjNormal_16x8,
.anims = sPikachuIntro_PikachuEyes_Anims,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
}
};
#define CONTROLS_GUIDE_STRINGS_PER_PAGE 3
static const u8 *const sControlsGuide_Pages2And3_Strings[CONTROLS_GUIDE_STRINGS_PER_PAGE * 2] =
{
// Page 2
gControlsGuide_Text_DPad,
gControlsGuide_Text_AButton,
gControlsGuide_Text_BButton,
// Page 3
gControlsGuide_Text_StartButton,
gControlsGuide_Text_SelectButton,
gControlsGuide_Text_LRButtons
};
static const u8 *const sMaleNameChoices[] =
{
#if defined(FIRERED)
gNameChoice_Red,
gNameChoice_Fire,
gNameChoice_Ash,
gNameChoice_Kene,
gNameChoice_Geki,
#elif defined(LEAFGREEN)
gNameChoice_Green,
gNameChoice_Leaf,
gNameChoice_Gary,
gNameChoice_Kaz,
gNameChoice_Toru,
#endif
gNameChoice_Jak,
gNameChoice_Janne,
gNameChoice_Jonn,
gNameChoice_Kamon,
gNameChoice_Karl,
gNameChoice_Taylor,
gNameChoice_Oscar,
gNameChoice_Hiro,
gNameChoice_Max,
gNameChoice_Jon,
gNameChoice_Ralph,
gNameChoice_Kay,
gNameChoice_Tosh,
gNameChoice_Roak
};
static const u8 *const sFemaleNameChoices[] =
{
#if defined(FIRERED)
gNameChoice_Red,
gNameChoice_Fire,
#elif defined(LEAFGREEN)
gNameChoice_Green,
gNameChoice_Leaf,
#endif
gNameChoice_Omi,
gNameChoice_Jodi,
gNameChoice_Amanda,
gNameChoice_Hillary,
gNameChoice_Makey,
gNameChoice_Michi,
gNameChoice_Paula,
gNameChoice_June,
gNameChoice_Cassie,
gNameChoice_Rey,
gNameChoice_Seda,
gNameChoice_Kiko,
gNameChoice_Mina,
gNameChoice_Norie,
gNameChoice_Sai,
gNameChoice_Momo,
gNameChoice_Suzi
};
static const u8 *const sRivalNameChoices[] =
{
#if defined(FIRERED)
gNameChoice_Green,
gNameChoice_Gary,
gNameChoice_Kaz,
gNameChoice_Toru
#elif defined(LEAFGREEN)
gNameChoice_Red,
gNameChoice_Ash,
gNameChoice_Kene,
gNameChoice_Geki
#endif
};
enum
{
MALE_PLAYER_PIC,
FEMALE_PLAYER_PIC,
RIVAL_PIC,
OAK_PIC
};
static void VBlankCB_NewGameScene(void)
{
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
}
static void CB2_NewGameScene(void)
{
RunTasks();
RunTextPrinters();
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
}
void StartNewGameScene(void)
{
gPlttBufferUnfaded[0] = RGB_BLACK;
gPlttBufferFaded[0] = RGB_BLACK;
CreateTask(Task_NewGameScene, 0);
SetMainCallback2(CB2_NewGameScene);
}
#define tSpriteTimer data[0]
#define tTrainerPicPosX data[1]
#define tTrainerPicFadeState data[2]
#define tTimer data[3]
#define tNidoranFSpriteId data[4]
#define tTextCursorSpriteId data[5]
#define tPokeBallSpriteId data[6]
#define tPikachuPlatformSpriteId(i) data[7 + i] // Pikachu and the platform are built of three sprites,
// data[8] // so these are used to hold their sprite IDs
// data[9] //
#define tMenuWindowId data[13]
#define tTextboxWindowId data[14]
#define tDelta data[15]
static void Task_NewGameScene(u8 taskId)
{
switch (gMain.state)
{
case 0:
SetVBlankCallback(NULL);
SetHBlankCallback(NULL);
DmaFill16(3, 0, VRAM, VRAM_SIZE);
DmaFill32(3, 0, OAM, OAM_SIZE);
DmaFill16(3, 0, PLTT + sizeof(u16), PLTT_SIZE - 2);
ResetPaletteFade();
ScanlineEffect_Stop();
ResetSpriteData();
FreeAllSpritePalettes();
ResetTempTileDataBuffers();
SetHelpContext(HELPCONTEXT_NEW_GAME);
break;
case 1:
sOakSpeechResources = AllocZeroed(sizeof(*sOakSpeechResources));
CreateMonSpritesGfxManager(1, 1);
break;
case 2:
SetGpuReg(REG_OFFSET_WIN0H, 0);
SetGpuReg(REG_OFFSET_WIN0V, 0);
SetGpuReg(REG_OFFSET_WIN1H, 0);
SetGpuReg(REG_OFFSET_WIN1V, 0);
SetGpuReg(REG_OFFSET_WININ, 0);
SetGpuReg(REG_OFFSET_WINOUT, 0);
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
SetGpuReg(REG_OFFSET_BLDY, 0);
break;
case 3:
ResetBgsAndClearDma3BusyFlags(0);
InitBgsFromTemplates(1, sBgTemplates, ARRAY_COUNT(sBgTemplates));
SetBgTilemapBuffer(1, sOakSpeechResources->bg1TilemapBuffer);
SetBgTilemapBuffer(2, sOakSpeechResources->bg2TilemapBuffer);
ChangeBgX(1, 0, BG_COORD_SET);
ChangeBgY(1, 0, BG_COORD_SET);
ChangeBgX(2, 0, BG_COORD_SET);
ChangeBgY(2, 0, BG_COORD_SET);
gSpriteCoordOffsetX = 0;
gSpriteCoordOffsetY = 0;
break;
case 4:
gPaletteFade.bufferTransferDisabled = TRUE;
InitStandardTextBoxWindows();
InitTextBoxGfxAndPrinters();
Menu_LoadStdPalAt(BG_PLTT_ID(13));
LoadPalette(sOakSpeech_Background_Pals, BG_PLTT_ID(0), sizeof(sOakSpeech_Background_Pals));
LoadPalette(GetTextWindowPalette(2) + 15, BG_PLTT_ID(0), PLTT_SIZEOF(1));
break;
case 5:
sOakSpeechResources->textSpeed = GetTextSpeedSetting();
gTextFlags.canABSpeedUpPrint = TRUE;
DecompressAndCopyTileDataToVram(1, sControlsGuide_PikachuIntro_Background_Tiles, 0, 0, 0);
break;
case 6:
if (FreeTempTileDataBuffersIfPossible())
return;
ClearDialogWindowAndFrame(WIN_INTRO_TEXTBOX, TRUE);
FillBgTilemapBufferRect_Palette0(1, 0, 0, 0, 32, 32);
CopyBgTilemapBufferToVram(1);
break;
case 7:
CreateTopBarWindowLoadPalette(0, 30, 0, 13, 0x1C4);
FillBgTilemapBufferRect_Palette0(1, 0xD00F, 0, 0, 30, 2);
FillBgTilemapBufferRect_Palette0(1, 0xD002, 0, 2, 30, 1);
FillBgTilemapBufferRect_Palette0(1, 0xD00E, 0, 19, 30, 1);
ControlsGuide_LoadPage1();
gPaletteFade.bufferTransferDisabled = FALSE;
gTasks[taskId].tTextCursorSpriteId = CreateTextCursorSprite(0, 230, 149, 0, 0);
BlendPalettes(PALETTES_ALL, 16, RGB_BLACK);
break;
case 10:
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
ShowBg(0);
ShowBg(1);
SetVBlankCallback(VBlankCB_NewGameScene);
PlayBGM(MUS_NEW_GAME_INSTRUCT);
gTasks[taskId].func = Task_ControlsGuide_HandleInput;
gMain.state = 0;
return;
}
gMain.state++;
}
static void ControlsGuide_LoadPage1(void)
{
TopBarWindowPrintTwoStrings(gText_Controls, gText_ABUTTONNext, FALSE, 0, TRUE);
sOakSpeechResources->windowIds[0] = AddWindow(sControlsGuide_WindowTemplates[sOakSpeechResources->currentPage]);
PutWindowTilemap(sOakSpeechResources->windowIds[0]);
FillWindowPixelBuffer(sOakSpeechResources->windowIds[0], PIXEL_FILL(0));
AddTextPrinterParameterized4(sOakSpeechResources->windowIds[0], FONT_NORMAL, 2, 0, 1, 1, sTextColor_White, 0, gControlsGuide_Text_Intro);
CopyWindowToVram(sOakSpeechResources->windowIds[0], COPYWIN_FULL);
FillBgTilemapBufferRect_Palette0(1, 0x3000, 1, 3, 5, 16);
CopyBgTilemapBufferToVram(1);
}
static void Task_ControlsGuide_LoadPage(u8 taskId)
{
u8 currWindow = 0;
u8 page2Or3 = sOakSpeechResources->currentPage - 1; // 0 if page 2, 1 if page 3
if (sOakSpeechResources->currentPage == CONTROLS_GUIDE_PAGE_1)
{
ControlsGuide_LoadPage1();
}
else
{
TopBarWindowPrintString(gText_ABUTTONNext_BBUTTONBack, 0, TRUE);
for (currWindow = CONTROLS_GUIDE_PAGES_2_3_WINDOW_TOP; currWindow < NUM_CONTROLS_GUIDE_PAGES_2_3_WINDOWS; currWindow++)
{
sOakSpeechResources->windowIds[currWindow] = AddWindow(&sControlsGuide_WindowTemplates[sOakSpeechResources->currentPage][currWindow]);
PutWindowTilemap(sOakSpeechResources->windowIds[currWindow]);
FillWindowPixelBuffer(sOakSpeechResources->windowIds[currWindow], PIXEL_FILL(0));
AddTextPrinterParameterized4(sOakSpeechResources->windowIds[currWindow], FONT_NORMAL, 6, 0, 1, 1, sTextColor_White, 0, sControlsGuide_Pages2And3_Strings[currWindow + page2Or3 * CONTROLS_GUIDE_STRINGS_PER_PAGE]);
CopyWindowToVram(sOakSpeechResources->windowIds[currWindow], COPYWIN_FULL);
}
if (sOakSpeechResources->currentPage == CONTROLS_GUIDE_PAGE_2)
CopyToBgTilemapBufferRect(1, sControlsGuide_Tilemap_Page2, 1, 3, 5, 16);
else // CONTROLS_GUIDE_PAGE_3
CopyToBgTilemapBufferRect(1, sControlsGuide_Tilemap_Page3, 1, 3, 5, 16);
CopyBgTilemapBufferToVram(1);
}
BeginNormalPaletteFade(PALETTES_OBJECTS | 0xDFFF, -1, 16, 0, GetTextWindowPalette(2)[15]);
gTasks[taskId].func = Task_ControlsGuide_HandleInput;
}
static void Task_ControlsGuide_HandleInput(u8 taskId)
{
if (!gPaletteFade.active)
{
if(JOY_NEW((A_BUTTON | B_BUTTON)))
{
if (JOY_NEW(A_BUTTON))
{
gTasks[taskId].tDelta = 1;
if (sOakSpeechResources->currentPage < CONTROLS_GUIDE_PAGE_3)
BeginNormalPaletteFade(PALETTES_OBJECTS | 0xDFFF, -1, 0, 16, GetTextWindowPalette(2)[15]);
}
else // B_BUTTON
{
if (sOakSpeechResources->currentPage == CONTROLS_GUIDE_PAGE_1)
return;
gTasks[taskId].tDelta = -1;
BeginNormalPaletteFade(PALETTES_OBJECTS | 0xDFFF, -1, 0, 16, GetTextWindowPalette(2)[15]);
}
PlaySE(SE_SELECT);
gTasks[taskId].func = Task_ControlsGuide_ChangePage;
}
}
}
static void Task_ControlsGuide_ChangePage(u8 taskId)
{
u8 numWindows = 0;
u8 i;
if (!gPaletteFade.active)
{
switch (sOakSpeechResources->currentPage)
{
case CONTROLS_GUIDE_PAGE_1:
numWindows = NUM_CONTROLS_GUIDE_PAGE_1_WINDOWS;
break;
case CONTROLS_GUIDE_PAGE_2:
case CONTROLS_GUIDE_PAGE_3:
numWindows = NUM_CONTROLS_GUIDE_PAGES_2_3_WINDOWS;
break;
}
sOakSpeechResources->currentPage += gTasks[taskId].tDelta;
if (sOakSpeechResources->currentPage < NUM_CONTROLS_GUIDE_PAGES)
{
for (i = 0; i < numWindows; i++)
{
FillWindowPixelBuffer(sOakSpeechResources->windowIds[i], PIXEL_FILL(0));
ClearWindowTilemap(sOakSpeechResources->windowIds[i]);
CopyWindowToVram(sOakSpeechResources->windowIds[i], COPYWIN_FULL);
RemoveWindow(sOakSpeechResources->windowIds[i]);
sOakSpeechResources->windowIds[i] = 0;
}
gTasks[taskId].func = Task_ControlsGuide_LoadPage;
}
else
{
BeginNormalPaletteFade(PALETTES_ALL, 2, 0, 16, 0);
gTasks[taskId].func = Task_ControlsGuide_Clear;
}
}
}
#undef tDelta
static void Task_ControlsGuide_Clear(u8 taskId)
{
u8 i = 0;
if (!gPaletteFade.active)
{
for (i = 0; i < NUM_CONTROLS_GUIDE_PAGES_2_3_WINDOWS; i++)
{
FillWindowPixelBuffer(sOakSpeechResources->windowIds[i], PIXEL_FILL(0));
ClearWindowTilemap(sOakSpeechResources->windowIds[i]);
CopyWindowToVram(sOakSpeechResources->windowIds[i], COPYWIN_FULL);
RemoveWindow(sOakSpeechResources->windowIds[i]);
sOakSpeechResources->windowIds[i] = 0;
}
FillBgTilemapBufferRect_Palette0(1, 0, 0, 2, 30, 18);
CopyBgTilemapBufferToVram(1);
DestroyTextCursorSprite(gTasks[taskId].tTextCursorSpriteId);
sOakSpeechResources->windowIds[0] = RGB_BLACK;
LoadPalette(sOakSpeechResources->windowIds, BG_PLTT_ID(0), PLTT_SIZEOF(1));
gTasks[taskId].tTimer = 32;
gTasks[taskId].func = Task_PikachuIntro_LoadPage1;
}
}
enum
{
PIKACHU_INTRO_SET_GPU_REGS,
PIKACHU_INTRO_HANDLE_INPUT,
PIKACHU_INTRO_PRINT_PAGE_TEXT,
PIKACHU_INTRO_FADE_IN_PAGE,
PIKACHU_INTRO_EXIT,
};
#define tBlendTarget data[15]
static void Task_PikachuIntro_LoadPage1(u8 taskId)
{
s16 *data = gTasks[taskId].data;
u32 size = 0;
if (tTimer != 0)
{
tTimer--;
}
else
{
PlayBGM(MUS_NEW_GAME_INTRO);
ClearTopBarWindow();
TopBarWindowPrintString(gText_ABUTTONNext, 0, 1);
sOakSpeechResources->pikachuIntroTilemap = MallocAndDecompress(sPikachuIntro_Background_Tilemap, &size);
CopyToBgTilemapBufferRect(1, sOakSpeechResources->pikachuIntroTilemap, 0, 2, 30, 19);
CopyBgTilemapBufferToVram(1);
Free(sOakSpeechResources->pikachuIntroTilemap);
sOakSpeechResources->pikachuIntroTilemap = NULL;
tTextboxWindowId = AddWindow(&sIntro_WindowTemplates[WIN_INTRO_TEXTBOX]);
PutWindowTilemap(tTextboxWindowId);
FillWindowPixelBuffer(tTextboxWindowId, PIXEL_FILL(0));
CopyWindowToVram(tTextboxWindowId, COPYWIN_FULL);
sOakSpeechResources->currentPage = PIKACHU_INTRO_PAGE_1;
gMain.state = PIKACHU_INTRO_SET_GPU_REGS;
tBlendTarget = 16;
AddTextPrinterParameterized4(tTextboxWindowId, FONT_NORMAL, 3, 5, 1, 0, sTextColor_DarkGray, 0, sPikachuIntro_Strings[PIKACHU_INTRO_PAGE_1]);
tTextCursorSpriteId = CreateTextCursorSprite(0, 226, 145, 0, 0);
gSprites[tTextCursorSpriteId].oam.objMode = ST_OAM_OBJ_BLEND;
gSprites[tTextCursorSpriteId].oam.priority = 0;
CreatePikachuOrPlatformSprites(taskId, SPRITE_TYPE_PIKACHU);
BeginNormalPaletteFade(PALETTES_ALL, 2, 16, 0, 0);
gTasks[taskId].func = Task_PikachuIntro_HandleInput;
}
}
static void Task_PikachuIntro_HandleInput(u8 taskId)
{
s16 *data = gTasks[taskId].data;
switch (gMain.state)
{
case PIKACHU_INTRO_SET_GPU_REGS:
if (!gPaletteFade.active)
{
SetGpuReg(REG_OFFSET_WIN0H, DISPLAY_WIDTH);
SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(16, DISPLAY_HEIGHT));
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_CLR | WININ_WIN0_OBJ);
SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ);
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
gMain.state = PIKACHU_INTRO_HANDLE_INPUT;
}
break;
case PIKACHU_INTRO_HANDLE_INPUT:
if (JOY_NEW((A_BUTTON | B_BUTTON)))
{
if (JOY_NEW(A_BUTTON))
{
sOakSpeechResources->currentPage++;
}
else // B_BUTTON
{
if (sOakSpeechResources->currentPage != PIKACHU_INTRO_PAGE_1)
sOakSpeechResources->currentPage--;
else
break;
}
PlaySE(SE_SELECT);
if (sOakSpeechResources->currentPage == NUM_PIKACHU_INTRO_PAGES)
{
gMain.state = PIKACHU_INTRO_EXIT;
}
else
{
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1);
SetGpuReg(REG_OFFSET_BLDALPHA, (16 - tBlendTarget) | tBlendTarget);
gMain.state++;
}
}
break;
case PIKACHU_INTRO_PRINT_PAGE_TEXT:
tBlendTarget -= 2;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(tBlendTarget, 16 - tBlendTarget));
if (tBlendTarget <= 0)
{
FillWindowPixelBuffer(tTextboxWindowId, PIXEL_FILL(0));
AddTextPrinterParameterized4(tTextboxWindowId, FONT_NORMAL, 3, 5, 1, 0, sTextColor_DarkGray, 0, sPikachuIntro_Strings[sOakSpeechResources->currentPage]);
if (sOakSpeechResources->currentPage == PIKACHU_INTRO_PAGE_1)
{
ClearTopBarWindow();
TopBarWindowPrintString(gText_ABUTTONNext, 0, 1);
}
else
{
ClearTopBarWindow();
TopBarWindowPrintString(gText_ABUTTONNext_BBUTTONBack, 0, 1);
}
gMain.state++;
}
break;
case PIKACHU_INTRO_FADE_IN_PAGE:
tBlendTarget += 2;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(tBlendTarget, 16 - tBlendTarget));
if (tBlendTarget >= 16)
{
tBlendTarget = 16;
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
gMain.state = PIKACHU_INTRO_HANDLE_INPUT;
}
break;
case PIKACHU_INTRO_EXIT:
DestroyTextCursorSprite(gTasks[taskId].tTextCursorSpriteId);
PlayBGM(MUS_NEW_GAME_EXIT);
tBlendTarget = 24;
gMain.state++;
break;
default:
if (tBlendTarget != 0)
{
tBlendTarget--;
}
else
{
gMain.state = 0;
sOakSpeechResources->currentPage = 0;
SetGpuReg(REG_OFFSET_WIN0H, 0);
SetGpuReg(REG_OFFSET_WIN0V, 0);
SetGpuReg(REG_OFFSET_WININ, 0);
SetGpuReg(REG_OFFSET_WINOUT, 0);
ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
BeginNormalPaletteFade(PALETTES_ALL, 2, 0, 16, RGB_BLACK);
gTasks[taskId].func = Task_PikachuIntro_Clear;
}
break;
}
}
#undef tBlendTarget
static void Task_PikachuIntro_Clear(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (!gPaletteFade.active)
{
DestroyTopBarWindow();
FillWindowPixelBuffer(tTextboxWindowId, PIXEL_FILL(0));
ClearWindowTilemap(tTextboxWindowId);
CopyWindowToVram(tTextboxWindowId, COPYWIN_FULL);
RemoveWindow(tTextboxWindowId);
tTextboxWindowId = 0;
FillBgTilemapBufferRect_Palette0(1, 0, 0, 0, 30, 20);
CopyBgTilemapBufferToVram(1);
DestroyPikachuOrPlatformSprites(taskId, SPRITE_TYPE_PIKACHU);
tTimer = 80;
gTasks[taskId].func = Task_OakSpeech_Init;
}
}
static void Task_OakSpeech_Init(u8 taskId)
{
s16 *data = gTasks[taskId].data;
u32 size = 0;
if (tTimer != 0)
{
tTimer--;
}
else
{
sOakSpeechResources->oakSpeechBackgroundTiles = MallocAndDecompress(sOakSpeech_Background_Tiles, &size);
LoadBgTiles(1, sOakSpeechResources->oakSpeechBackgroundTiles, size, 0);
CopyToBgTilemapBuffer(1, sOakSpeech_Background_Tilemap, 0, 0);
CopyBgTilemapBufferToVram(1);
CreateNidoranFSprite(taskId);
LoadTrainerPic(OAK_PIC, 0);
CreatePikachuOrPlatformSprites(taskId, SPRITE_TYPE_PLATFORM);
PlayBGM(MUS_ROUTE24);
BeginNormalPaletteFade(PALETTES_ALL, 5, 16, 0, RGB_BLACK);
tTimer = 80;
ShowBg(2);
gTasks[taskId].func = Task_OakSpeech_WelcomeToTheWorld;
}
}
#define OakSpeechPrintMessage(str, speed) ({ \
DrawDialogueFrame(WIN_INTRO_TEXTBOX, FALSE); \
if (str != gStringVar4) \
{ \
StringExpandPlaceholders(gStringVar4, str); \
AddTextPrinterParameterized2(WIN_INTRO_TEXTBOX, FONT_MALE, gStringVar4, speed, NULL, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); \
} \
else \
{ \
AddTextPrinterParameterized2(WIN_INTRO_TEXTBOX, FONT_MALE, str, speed, NULL, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); \
} \
CopyWindowToVram(WIN_INTRO_TEXTBOX, COPYWIN_FULL); \
})
static void Task_OakSpeech_WelcomeToTheWorld(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (!gPaletteFade.active)
{
if (tTimer != 0)
{
tTimer--;
}
else
{
OakSpeechPrintMessage(gOakSpeech_Text_WelcomeToTheWorld, sOakSpeechResources->textSpeed);
gTasks[taskId].func = Task_OakSpeech_ThisWorld;
}
}
}
static void Task_OakSpeech_ThisWorld(u8 taskId)
{
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
OakSpeechPrintMessage(gOakSpeech_Text_ThisWorld, sOakSpeechResources->textSpeed);
gTasks[taskId].tTimer = 30;
gTasks[taskId].func = Task_OakSpeech_ReleaseNidoranFFromPokeBall;
}
}
static void Task_OakSpeech_ReleaseNidoranFFromPokeBall(u8 taskId)
{
s16 *data = gTasks[taskId].data;
u8 spriteId;
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
if (tTimer != 0)
tTimer--;
spriteId = gTasks[taskId].tNidoranFSpriteId;
gSprites[spriteId].invisible = FALSE;
gSprites[spriteId].tSpriteTimer = 0;
CreatePokeballSpriteToReleaseMon(spriteId, gSprites[spriteId].oam.paletteNum, 100, 66, 0, 0, 32, 0xFFFF1FFF);
gTasks[taskId].func = Task_OakSpeech_IsInhabitedFarAndWide;
gTasks[taskId].tTimer = 0;
}
}
static void Task_OakSpeech_IsInhabitedFarAndWide(u8 taskId)
{
if (IsCryFinished())
{
if (gTasks[taskId].tTimer >= 96)
gTasks[taskId].func = Task_OakSpeech_IStudyPokemon;
}
if (gTasks[taskId].tTimer < 0x4000)
{
gTasks[taskId].tTimer++;
if (gTasks[taskId].tTimer == 32)
{
OakSpeechPrintMessage(gOakSpeech_Text_IsInhabitedFarAndWide, sOakSpeechResources->textSpeed);
PlayCry_Normal(INTRO_SPECIES, 0);
}
}
}
static void Task_OakSpeech_IStudyPokemon(u8 taskId)
{
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
OakSpeechPrintMessage(gOakSpeech_Text_IStudyPokemon, sOakSpeechResources->textSpeed);
gTasks[taskId].func = Task_OakSpeech_ReturnNidoranFToPokeBall;
}
}
static void Task_OakSpeech_ReturnNidoranFToPokeBall(u8 taskId)
{
u8 spriteId;
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
ClearDialogWindowAndFrame(WIN_INTRO_TEXTBOX, TRUE);
spriteId = gTasks[taskId].tNidoranFSpriteId;
gTasks[taskId].tPokeBallSpriteId = CreateTradePokeballSprite(spriteId, gSprites[spriteId].oam.paletteNum, 100, 66, 0, 0, 32, 0xFFFF1F3F);
gTasks[taskId].tTimer = 48;
gTasks[taskId].tSpriteTimer = 64;
gTasks[taskId].func = Task_OakSpeech_TellMeALittleAboutYourself;
}
}
static void Task_OakSpeech_TellMeALittleAboutYourself(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (tSpriteTimer != 0)
{
if (tSpriteTimer < 24)
gSprites[tNidoranFSpriteId].y--;
tSpriteTimer--;
}
else
{
if (tTimer == 48)
{
DestroySprite(&gSprites[tNidoranFSpriteId]);
DestroySprite(&gSprites[tPokeBallSpriteId]);
}
if (tTimer != 0)
{
tTimer--;
}
else
{
OakSpeechPrintMessage(gOakSpeech_Text_TellMeALittleAboutYourself, sOakSpeechResources->textSpeed);
gTasks[taskId].func = Task_OakSpeech_FadeOutOak;
}
}
}
static void Task_OakSpeech_FadeOutOak(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
ClearDialogWindowAndFrame(WIN_INTRO_TEXTBOX, 1);
CreateFadeInTask(taskId, 2);
tTimer = 48;
gTasks[taskId].func = Task_OakSpeech_AskPlayerGender;
}
}
static void Task_OakSpeech_AskPlayerGender(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (tTrainerPicFadeState != 0)
{
if (tTimer != 0)
{
tTimer--;
}
else
{
tTrainerPicPosX = -60;
ClearTrainerPic();
OakSpeechPrintMessage(gOakSpeech_Text_AskPlayerGender, sOakSpeechResources->textSpeed);
gTasks[taskId].func = Task_OakSpeech_ShowGenderOptions;
}
}
}
static void Task_OakSpeech_ShowGenderOptions(u8 taskId)
{
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
gTasks[taskId].tMenuWindowId = AddWindow(&sIntro_WindowTemplates[WIN_INTRO_BOYGIRL]);
PutWindowTilemap(gTasks[taskId].tMenuWindowId);
DrawStdFrameWithCustomTileAndPalette(gTasks[taskId].tMenuWindowId, TRUE, GetStdWindowBaseTileNum(), 14);
FillWindowPixelBuffer(gTasks[taskId].tMenuWindowId, PIXEL_FILL(1));
sOakSpeechResources->textColor[0] = 1;
sOakSpeechResources->textColor[1] = 2;
sOakSpeechResources->textColor[2] = 3;
AddTextPrinterParameterized3(gTasks[taskId].tMenuWindowId, FONT_NORMAL, 8, 1, sOakSpeechResources->textColor, 0, gText_Boy);
sOakSpeechResources->textColor[0] = 1;
sOakSpeechResources->textColor[1] = 2;
sOakSpeechResources->textColor[2] = 3;
AddTextPrinterParameterized3(gTasks[taskId].tMenuWindowId, FONT_NORMAL, 8, 17, sOakSpeechResources->textColor, 0, gText_Girl);
Menu_InitCursor(gTasks[taskId].tMenuWindowId, FONT_NORMAL, 0, 1, GetFontAttribute(FONT_NORMAL, FONTATTR_MAX_LETTER_HEIGHT) + 2, 2, 0);
CopyWindowToVram(gTasks[taskId].tMenuWindowId, COPYWIN_FULL);
gTasks[taskId].func = Task_OakSpeech_HandleGenderInput;
}
}
static void Task_OakSpeech_HandleGenderInput(u8 taskId)
{
s8 input = Menu_ProcessInputNoWrapAround();
switch (input)
{
case 0: // BOY
gSaveBlock2Ptr->playerGender = MALE;
break;
case 1: // GIRL
gSaveBlock2Ptr->playerGender = FEMALE;
break;
case MENU_B_PRESSED:
case MENU_NOTHING_CHOSEN:
return;
}
gTasks[taskId].func = Task_OakSpeech_ClearGenderWindows;
}
static void Task_OakSpeech_ClearGenderWindows(u8 taskId)
{
s16 *data = gTasks[taskId].data;
ClearStdWindowAndFrameToTransparent(tMenuWindowId, TRUE);
RemoveWindow(tMenuWindowId);
tMenuWindowId = WIN_INTRO_TEXTBOX;
ClearDialogWindowAndFrame(tMenuWindowId, TRUE);
FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20);
CopyBgTilemapBufferToVram(0);
gTasks[taskId].func = Task_OakSpeech_LoadPlayerPic;
}
static void Task_OakSpeech_LoadPlayerPic(u8 taskId)
{
if (gSaveBlock2Ptr->playerGender == MALE)
LoadTrainerPic(MALE_PLAYER_PIC, 0);
else
LoadTrainerPic(FEMALE_PLAYER_PIC, 0);
CreateFadeOutTask(taskId, 2);
gTasks[taskId].tTimer = 32;
gTasks[taskId].func = Task_OakSpeech_YourNameWhatIsIt;
}
static void Task_OakSpeech_YourNameWhatIsIt(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (tTrainerPicFadeState != 0)
{
if (tTimer != 0)
{
tTimer--;
}
else
{
tTrainerPicPosX = 0;
OakSpeechPrintMessage(gOakSpeech_Text_YourNameWhatIsIt, sOakSpeechResources->textSpeed);
gTasks[taskId].func = Task_OakSpeech_FadeOutForPlayerNamingScreen;
}
}
}
static void Task_OakSpeech_FadeOutForPlayerNamingScreen(u8 taskId)
{
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
sOakSpeechResources->hasPlayerBeenNamed = FALSE;
gTasks[taskId].func = Task_OakSpeech_DoNamingScreen;
}
}
static void Task_OakSpeech_MoveRivalDisplayNameOptions(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
if (tTrainerPicPosX > -60)
{
tTrainerPicPosX -= 2;
gSpriteCoordOffsetX += 2;
ChangeBgX(2, 0x200, BG_COORD_SUB);
}
else
{
tTrainerPicPosX = -60;
PrintNameChoiceOptions(taskId, sOakSpeechResources->hasPlayerBeenNamed);
gTasks[taskId].func = Task_OakSpeech_HandleRivalNameInput;
}
}
}
static void Task_OakSpeech_RepeatNameQuestion(u8 taskId)
{
PrintNameChoiceOptions(taskId, sOakSpeechResources->hasPlayerBeenNamed);
if (sOakSpeechResources->hasPlayerBeenNamed == FALSE)
OakSpeechPrintMessage(gOakSpeech_Text_YourNameWhatIsIt, 0);
else
OakSpeechPrintMessage(gOakSpeech_Text_YourRivalsNameWhatWasIt, 0);
gTasks[taskId].func = Task_OakSpeech_HandleRivalNameInput;
}
#define tNameNotConfirmed data[15]
static void Task_OakSpeech_HandleRivalNameInput(u8 taskId)
{
s16 *data = gTasks[taskId].data;
s8 input = Menu_ProcessInput();
switch (input)
{
case 0: // NEW NAME
PlaySE(SE_SELECT);
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
gTasks[taskId].func = Task_OakSpeech_DoNamingScreen;
break;
case 1: // Default name options
case 2: //
case 3: //
case 4: //
PlaySE(SE_SELECT);
ClearStdWindowAndFrameToTransparent(tMenuWindowId, TRUE);
RemoveWindow(tMenuWindowId);
GetDefaultName(sOakSpeechResources->hasPlayerBeenNamed, input - 1);
tNameNotConfirmed = TRUE;
gTasks[taskId].func = Task_OakSpeech_ConfirmName;
break;
case MENU_B_PRESSED:
break;
}
}
static void Task_OakSpeech_DoNamingScreen(u8 taskId)
{
if (!gPaletteFade.active)
{
GetDefaultName(sOakSpeechResources->hasPlayerBeenNamed, 0);
if (sOakSpeechResources->hasPlayerBeenNamed == FALSE)
{
DoNamingScreen(NAMING_SCREEN_PLAYER, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnFromNamingScreen);
}
else
{
ClearStdWindowAndFrameToTransparent(gTasks[taskId].tMenuWindowId, TRUE);
RemoveWindow(gTasks[taskId].tMenuWindowId);
DoNamingScreen(NAMING_SCREEN_RIVAL, gSaveBlock1Ptr->rivalName, 0, 0, 0, CB2_ReturnFromNamingScreen);
}
DestroyPikachuOrPlatformSprites(taskId, SPRITE_TYPE_PLATFORM);
FreeAllWindowBuffers();
}
}
static void Task_OakSpeech_ConfirmName(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (!gPaletteFade.active)
{
if (tNameNotConfirmed == TRUE)
{
if (sOakSpeechResources->hasPlayerBeenNamed == FALSE)
StringExpandPlaceholders(gStringVar4, gOakSpeech_Text_SoYourNameIsPlayer);
else
StringExpandPlaceholders(gStringVar4, gOakSpeech_Text_ConfirmRivalName);
OakSpeechPrintMessage(gStringVar4, sOakSpeechResources->textSpeed);
tNameNotConfirmed = FALSE;
tTimer = 25;
}
else if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
if (tTimer != 0)
{
tTimer--;
}
else
{
CreateYesNoMenu(&sIntro_WindowTemplates[WIN_INTRO_YESNO], FONT_NORMAL, 0, 2, GetStdWindowBaseTileNum(), 14, 0);
gTasks[taskId].func = Task_OakSpeech_HandleConfirmNameInput;
}
}
}
}
static void Task_OakSpeech_HandleConfirmNameInput(u8 taskId)
{
s8 input = Menu_ProcessInputNoWrapClearOnChoose();
switch (input)
{
case 0: // YES
PlaySE(SE_SELECT);
gTasks[taskId].tTimer = 40;
if (sOakSpeechResources->hasPlayerBeenNamed == FALSE)
{
ClearDialogWindowAndFrame(WIN_INTRO_TEXTBOX, TRUE);
CreateFadeInTask(taskId, 2);
gTasks[taskId].func = Task_OakSpeech_FadeOutPlayerPic;
}
else
{
StringExpandPlaceholders(gStringVar4, gOakSpeech_Text_RememberRivalsName);
OakSpeechPrintMessage(gStringVar4, sOakSpeechResources->textSpeed);
gTasks[taskId].func = Task_OakSpeech_FadeOutRivalPic;
}
break;
case 1: // NO
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
if (sOakSpeechResources->hasPlayerBeenNamed == FALSE)
gTasks[taskId].func = Task_OakSpeech_FadeOutForPlayerNamingScreen;
else
gTasks[taskId].func = Task_OakSpeech_RepeatNameQuestion;
break;
}
}
static void Task_OakSpeech_FadeOutPlayerPic(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (tTrainerPicFadeState != 0)
{
ClearTrainerPic();
if (tTimer != 0)
tTimer--;
else
gTasks[taskId].func = Task_OakSpeech_FadeInRivalPic;
}
}
static void Task_OakSpeech_FadeOutRivalPic(u8 taskId)
{
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
ClearDialogWindowAndFrame(WIN_INTRO_TEXTBOX, TRUE);
CreateFadeInTask(taskId, 2);
gTasks[taskId].func = Task_OakSpeech_ReshowPlayersPic;
}
}
static void Task_OakSpeech_FadeInRivalPic(u8 taskId)
{
ChangeBgX(2, 0, BG_COORD_SET);
gTasks[taskId].tTrainerPicPosX = 0;
gSpriteCoordOffsetX = 0;
LoadTrainerPic(RIVAL_PIC, 0);
CreateFadeOutTask(taskId, 2);
gTasks[taskId].func = Task_OakSpeech_AskRivalsName;
}
static void Task_OakSpeech_AskRivalsName(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (tTrainerPicFadeState != 0)
{
OakSpeechPrintMessage(gOakSpeech_Text_WhatWasHisName, sOakSpeechResources->textSpeed);
sOakSpeechResources->hasPlayerBeenNamed = TRUE;
gTasks[taskId].func = Task_OakSpeech_MoveRivalDisplayNameOptions;
}
}
static void Task_OakSpeech_ReshowPlayersPic(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (tTrainerPicFadeState != 0)
{
ClearTrainerPic();
if (tTimer != 0)
{
tTimer--;
}
else
{
if (gSaveBlock2Ptr->playerGender == MALE)
LoadTrainerPic(MALE_PLAYER_PIC, 0);
else
LoadTrainerPic(FEMALE_PLAYER_PIC, 0);
gTasks[taskId].tTrainerPicPosX = 0;
gSpriteCoordOffsetX = 0;
ChangeBgX(2, 0, BG_COORD_SET);
CreateFadeOutTask(taskId, 2);
gTasks[taskId].func = Task_OakSpeech_LetsGo;
}
}
}
static void Task_OakSpeech_LetsGo(u8 taskId)
{
if (gTasks[taskId].tTrainerPicFadeState != 0)
{
StringExpandPlaceholders(gStringVar4, gOakSpeech_Text_LetsGo);
OakSpeechPrintMessage(gStringVar4, sOakSpeechResources->textSpeed);
gTasks[taskId].tTimer = 30;
gTasks[taskId].func = Task_OakSpeech_FadeOutBGM;
}
}
static void Task_OakSpeech_FadeOutBGM(u8 taskId)
{
if (!IsTextPrinterActive(WIN_INTRO_TEXTBOX))
{
if (gTasks[taskId].tTimer != 0)
{
gTasks[taskId].tTimer--;
}
else
{
FadeOutBGM(4);
gTasks[taskId].func = Task_OakSpeech_SetUpExitAnimation;
}
}
}
// The sOakSpeechResources struct's currentPage field is reused below as a timer for shrinking the player pic
#define shrinkTimer currentPage
static void Task_OakSpeech_SetUpExitAnimation(u8 taskId)
{
sOakSpeechResources->shrinkTimer = 0;
Task_OakSpeech_SetUpDestroyPlatformSprites(taskId);
Task_OakSpeech_SetUpFadePlayerPicWhite(taskId);
Task_OakSpeech_SetUpShrinkPlayerPic(taskId);
}
#define tPlayerPicFadeOutTimer data[0]
#define tScaleDelta data[2]
#define tPlayerIsShrunk data[15]
static void Task_OakSpeech_SetUpShrinkPlayerPic(u8 taskId)
{
s16 *data = gTasks[taskId].data;
SetBgAttribute(2, BG_ATTR_WRAPAROUND, 1);
tPlayerPicFadeOutTimer = 0;
data[1] = 0; // assigned, but never read
tScaleDelta = 256;
tPlayerIsShrunk = FALSE;
gTasks[taskId].func = Task_OakSpeech_ShrinkPlayerPic;
}
static void Task_OakSpeech_ShrinkPlayerPic(u8 taskId)
{
s16 *data = gTasks[taskId].data;
s16 x, y;
u16 oldScaleDelta;
sOakSpeechResources->shrinkTimer++;
if (sOakSpeechResources->shrinkTimer % 20 == 0)
{
if (sOakSpeechResources->shrinkTimer == 40)
PlaySE(SE_WARP_IN);
oldScaleDelta = tScaleDelta;
tScaleDelta -= 32;
x = Q_8_8_inv(oldScaleDelta - 8);
y = Q_8_8_inv(tScaleDelta - 16);
SetBgAffine(2, 0x7800, 0x5400, 120, 84, x, y, 0);
if (tScaleDelta <= 96)
{
tPlayerIsShrunk = TRUE;
tPlayerPicFadeOutTimer = 36;
gTasks[taskId].func = Task_OakSpeech_FadePlayerPicToBlack;
}
}
}
#define tBGFadeStarted data[1]
static void Task_OakSpeech_SetUpDestroyPlatformSprites(u8 taskId)
{
u8 taskId2 = CreateTask(Task_OakSpeech_DestroyPlatformSprites, 1);
s16 *data = gTasks[taskId2].data;
data[0] = 0; // assigned, but never read
tBGFadeStarted = 0;
data[2] = 0; // assigned, but never read
data[15] = 0; // assigned, but never read
BeginNormalPaletteFade(PALETTES_OBJECTS | 0x0FCF, 4, 0, 16, RGB_BLACK);
}
static void Task_OakSpeech_DestroyPlatformSprites(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (!gPaletteFade.active)
{
if (tBGFadeStarted != 0)
{
DestroyTask(taskId);
// As this function's taskId is in fact taskId2 above, in
// Task_OakSpeech_SetUpDestroyPlatformSprites, the platform sprite
// IDs have not been assigned to this task's data[7], data[8] and
// data[9].
// As a result, the function below will only delete the sprite with
// ID 0.
// This can be verified by looking at the sprite viewer in an
// emulator at the end of the Oak speech.
DestroyPikachuOrPlatformSprites(taskId, SPRITE_TYPE_PLATFORM);
}
else
{
tBGFadeStarted++;
BeginNormalPaletteFade(0x0000 | 0xF000, 0, 0, 16, RGB_BLACK);
}
}
}
#undef tBGFadeStarted
#define tPlayerPicFadeWhiteTimer data[0]
#define tUnderflowingTimer data[1]
#define tSecondaryTimer data[2]
#define tBlendCoefficient data[14]
static void Task_OakSpeech_SetUpFadePlayerPicWhite(u8 taskId)
{
u8 taskId2 = CreateTask(Task_OakSpeech_FadePlayerPicWhite, 2);
s16 *data = gTasks[taskId2].data;
tPlayerPicFadeWhiteTimer = 8;
tUnderflowingTimer = 0;
tSecondaryTimer = 8;
tBlendCoefficient = 0;
data[15] = 0; // assigned, but never read
}
static void Task_OakSpeech_FadePlayerPicWhite(u8 taskId)
{
s16 *data = gTasks[taskId].data;
u8 i;
if (tPlayerPicFadeWhiteTimer != 0)
{
tPlayerPicFadeWhiteTimer--;
}
else
{
if (tUnderflowingTimer <= 0 && tSecondaryTimer != 0)
tSecondaryTimer--;
BlendPalette(BG_PLTT_ID(4), 0x20, tBlendCoefficient, RGB_WHITE);
tBlendCoefficient++;
tUnderflowingTimer--;
tPlayerPicFadeWhiteTimer = tSecondaryTimer;
if (tBlendCoefficient > 14)
{
for (i = 0; i < 32; i++)
{
gPlttBufferFaded[i + BG_PLTT_ID(4)] = RGB_WHITE;
gPlttBufferUnfaded[i + BG_PLTT_ID(4)] = RGB_WHITE;
}
DestroyTask(taskId);
}
}
}
static void Task_OakSpeech_FadePlayerPicToBlack(u8 taskId)
{
if (gTasks[taskId].tPlayerPicFadeOutTimer != 0)
{
gTasks[taskId].tPlayerPicFadeOutTimer--;
}
else
{
BeginNormalPaletteFade(0x0000 | 0x0030, 2, 0, 16, RGB_BLACK);
gTasks[taskId].func = Task_OakSpeech_WaitForFade;
}
}
static void Task_OakSpeech_WaitForFade(u8 taskId)
{
if (!gPaletteFade.active)
gTasks[taskId].func = Task_OakSpeech_FreeResources;
}
static void Task_OakSpeech_FreeResources(u8 taskId)
{
FreeAllWindowBuffers();
DestroyMonSpritesGfxManager();
Free(sOakSpeechResources);
sOakSpeechResources = NULL;
gTextFlags.canABSpeedUpPrint = FALSE;
SetMainCallback2(CB2_NewGame);
DestroyTask(taskId);
}
static void CB2_ReturnFromNamingScreen(void)
{
u8 taskId;
switch (gMain.state)
{
case 0:
SetVBlankCallback(NULL);
DmaFill16(3, 0, VRAM, VRAM_SIZE);
DmaFill32(3, 0, OAM, OAM_SIZE);
DmaFill16(3, RGB_BLACK, PLTT + sizeof(u16), PLTT_SIZE - sizeof(u16));
ResetPaletteFade();
ScanlineEffect_Stop();
ResetSpriteData();
FreeAllSpritePalettes();
ResetTempTileDataBuffers();
break;
case 1:
ResetBgsAndClearDma3BusyFlags(0);
InitBgsFromTemplates(1, sBgTemplates, ARRAY_COUNT(sBgTemplates));
SetBgTilemapBuffer(1, sOakSpeechResources->bg1TilemapBuffer);
SetBgTilemapBuffer(2, sOakSpeechResources->bg2TilemapBuffer);
ChangeBgX(1, 0, BG_COORD_SET);
ChangeBgY(1, 0, BG_COORD_SET);
ChangeBgX(2, 0, BG_COORD_SET);
ChangeBgY(2, 0, BG_COORD_SET);
break;
case 2:
SetGpuReg(REG_OFFSET_WIN0H, 0);
SetGpuReg(REG_OFFSET_WIN0V, 0);
SetGpuReg(REG_OFFSET_WININ, 0);
SetGpuReg(REG_OFFSET_WINOUT, 0);
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
SetGpuReg(REG_OFFSET_BLDY, 0);
break;
case 3:
FreeAllWindowBuffers();
InitStandardTextBoxWindows();
InitTextBoxGfxAndPrinters();
// Below is reading 48 colors beyond the background palette (into the tiles that follow it).
// This color range is used by the player and rival pic, which will overwrite them with the correct colors.
#ifdef BUGFIX
LoadPalette(sOakSpeech_Background_Pals, BG_PLTT_ID(0), sizeof(sOakSpeech_Background_Pals));
#else
LoadPalette(sOakSpeech_Background_Pals, BG_PLTT_ID(0), sizeof(sOakSpeech_Background_Pals) + PLTT_SIZEOF(48));
#endif
break;
case 4:
DecompressAndCopyTileDataToVram(1, sOakSpeech_Background_Tiles, 0, 0, 0);
break;
case 5:
if (FreeTempTileDataBuffersIfPossible())
return;
FillBgTilemapBufferRect_Palette0(1, 0, 0, 0, 30, 20);
CopyToBgTilemapBuffer(1, sOakSpeech_Background_Tilemap, 0, 0);
FillBgTilemapBufferRect_Palette0(2, 0, 0, 0, 30, 20);
CopyBgTilemapBufferToVram(1);
CopyBgTilemapBufferToVram(2);
break;
case 6:
taskId = CreateTask(Task_OakSpeech_ConfirmName, 0);
if (sOakSpeechResources->hasPlayerBeenNamed == FALSE)
{
if (gSaveBlock2Ptr->playerGender == MALE)
LoadTrainerPic(MALE_PLAYER_PIC, 0);
else
LoadTrainerPic(FEMALE_PLAYER_PIC, 0);
}
else
{
LoadTrainerPic(RIVAL_PIC, 0);
}
gTasks[taskId].tTrainerPicPosX = -60;
gSpriteCoordOffsetX += 60;
ChangeBgX(2, 0xFFFFC400, BG_COORD_SET);
CreatePikachuOrPlatformSprites(taskId, SPRITE_TYPE_PLATFORM);
gTasks[taskId].tNameNotConfirmed = TRUE;
break;
case 7:
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
ShowBg(0);
ShowBg(1);
ShowBg(2);
EnableInterrupts(INTR_FLAG_VBLANK);
SetVBlankCallback(VBlankCB_NewGameScene);
gTextFlags.canABSpeedUpPrint = TRUE;
SetMainCallback2(CB2_NewGameScene);
return;
}
gMain.state++;
}
static void CreateNidoranFSprite(u8 taskId)
{
u8 spriteId;
LoadSpecialPokePic(MonSpritesGfxManager_GetSpritePtr(0), INTRO_SPECIES, 0, TRUE);
LoadCompressedSpritePaletteUsingHeapWithTag(GetMonSpritePalStructFromOtIdPersonality(INTRO_SPECIES, 0, SHINY_ODDS), INTRO_SPECIES);
SetMultiuseSpriteTemplateToPokemon(INTRO_SPECIES, 0);
spriteId = CreateSprite(&gMultiuseSpriteTemplate, 96, 96, 1);
gSprites[spriteId].callback = SpriteCallbackDummy;
gSprites[spriteId].oam.priority = 1;
gSprites[spriteId].invisible = TRUE;
gTasks[taskId].tNidoranFSpriteId = spriteId;
}
#define sBodySpriteId data[0]
static void SpriteCB_Pikachu(struct Sprite *sprite)
{
sprite->y2 = gSprites[sprite->sBodySpriteId].animCmdIndex;
}
static void CreatePikachuOrPlatformSprites(u8 taskId, u8 spriteType)
{
u8 spriteId;
u8 i = 0;
switch (spriteType)
{
case SPRITE_TYPE_PIKACHU:
LoadCompressedSpriteSheet(&sPikachuIntro_Pikachu_SpriteSheets[PIKACHU_BODY_PLATFORM_LEFT]);
LoadCompressedSpriteSheet(&sPikachuIntro_Pikachu_SpriteSheets[PIKACHU_EARS_PLATFORM_MIDDLE]);
LoadCompressedSpriteSheet(&sPikachuIntro_Pikachu_SpriteSheets[PIKACHU_EYES_PLATFORM_RIGHT]);
LoadSpritePalette(&sPikachuIntro_Pikachu_SpritePalette);
spriteId = CreateSprite(&sPikachuIntro_Pikachu_SpriteTemplates[PIKACHU_BODY_PLATFORM_LEFT], 16, 17, 2);
gSprites[spriteId].oam.priority = 0;
gTasks[taskId].tPikachuPlatformSpriteId(PIKACHU_BODY_PLATFORM_LEFT) = spriteId;
spriteId = CreateSprite(&sPikachuIntro_Pikachu_SpriteTemplates[PIKACHU_EARS_PLATFORM_MIDDLE], 16, 9, 3);
gSprites[spriteId].oam.priority = 0;
gSprites[spriteId].sBodySpriteId = gTasks[taskId].tPikachuPlatformSpriteId(PIKACHU_BODY_PLATFORM_LEFT);
gSprites[spriteId].callback = SpriteCB_Pikachu;
gTasks[taskId].tPikachuPlatformSpriteId(PIKACHU_EARS_PLATFORM_MIDDLE) = spriteId;
spriteId = CreateSprite(&sPikachuIntro_Pikachu_SpriteTemplates[PIKACHU_EYES_PLATFORM_RIGHT], 24, 13, 1);
gSprites[spriteId].oam.priority = 0;
gSprites[spriteId].sBodySpriteId = gTasks[taskId].tPikachuPlatformSpriteId(PIKACHU_BODY_PLATFORM_LEFT);
gSprites[spriteId].callback = SpriteCB_Pikachu;
gTasks[taskId].tPikachuPlatformSpriteId(PIKACHU_EYES_PLATFORM_RIGHT) = spriteId;
break;
case SPRITE_TYPE_PLATFORM:
LoadCompressedSpriteSheet(&sOakSpeech_Platform_SpriteSheet);
LoadSpritePalette(&sOakSpeech_Platform_SpritePalette);
for (i = PIKACHU_BODY_PLATFORM_LEFT; i < NUM_PIKACHU_PLATFORM_SPRITES; i++)
{
spriteId = CreateSprite(&sOakSpeech_Platform_SpriteTemplates[i], i * 32 + 88, 112, 1);
gSprites[spriteId].oam.priority = 2;
gSprites[spriteId].animPaused = TRUE;
gSprites[spriteId].coordOffsetEnabled = TRUE;
gTasks[taskId].tPikachuPlatformSpriteId(i) = spriteId;
}
break;
}
}
static void DestroyPikachuOrPlatformSprites(u8 taskId, u8 spriteType)
{
u8 i;
for (i = PIKACHU_BODY_PLATFORM_LEFT; i < NUM_PIKACHU_PLATFORM_SPRITES; i++)
DestroySprite(&gSprites[gTasks[taskId].tPikachuPlatformSpriteId(i)]);
switch (spriteType)
{
case SPRITE_TYPE_PIKACHU:
FreeSpriteTilesByTag(GFX_TAG_PIKACHU_EYES);
FreeSpriteTilesByTag(GFX_TAG_PIKACHU_EARS);
FreeSpriteTilesByTag(GFX_TAG_PIKACHU);
FreeSpritePaletteByTag(PAL_TAG_PIKACHU);
break;
case SPRITE_TYPE_PLATFORM:
FreeSpriteTilesByTag(GFX_TAG_PLATFORM);
FreeSpritePaletteByTag(PAL_TAG_PLATFORM);
break;
}
}
static void LoadTrainerPic(u16 whichPic, u16 tileOffset)
{
u32 i;
switch (whichPic)
{
case MALE_PLAYER_PIC:
LoadPalette(sOakSpeech_Red_Pal, BG_PLTT_ID(4), sizeof(sOakSpeech_Red_Pal));
LZ77UnCompVram(sOakSpeech_Red_Tiles, (void *)VRAM + 0x600 + tileOffset);
break;
case FEMALE_PLAYER_PIC:
LoadPalette(sOakSpeech_Leaf_Pal, BG_PLTT_ID(4), sizeof(sOakSpeech_Leaf_Pal));
LZ77UnCompVram(sOakSpeech_Leaf_Tiles, (void *)VRAM + 0x600 + tileOffset);
break;
case RIVAL_PIC:
LoadPalette(sOakSpeech_Rival_Pal, BG_PLTT_ID(6), sizeof(sOakSpeech_Rival_Pal));
LZ77UnCompVram(sOakSpeech_Rival_Tiles, (void *)VRAM + 0x600 + tileOffset);
break;
case OAK_PIC:
LoadPalette(sOakSpeech_Oak_Pal, BG_PLTT_ID(6), sizeof(sOakSpeech_Oak_Pal));
LZ77UnCompVram(sOakSpeech_Oak_Tiles, (void *)VRAM + 0x600 + tileOffset);
break;
default:
return;
}
sOakSpeechResources->trainerPicTilemap = AllocZeroed(0x60);
for (i = 0; i < 0x60; i++)
((u8 *)sOakSpeechResources->trainerPicTilemap)[i] = i;
FillBgTilemapBufferRect(2, 0, 0, 0, 32, 32, 16);
CopyRectToBgTilemapBufferRect(2, sOakSpeechResources->trainerPicTilemap, 0, 0, 8, 12, 11, 2, 8, 12, 16, (tileOffset / 64) + 24, 0);
CopyBgTilemapBufferToVram(2);
Free(sOakSpeechResources->trainerPicTilemap);
sOakSpeechResources->trainerPicTilemap = 0;
}
static void ClearTrainerPic(void)
{
FillBgTilemapBufferRect(2, 0, 11, 1, 8, 12, 16);
CopyBgTilemapBufferToVram(2);
}
#define tParentTaskId data[0]
#define tBlendTarget1 data[1]
#define tBlendTarget2 data[2]
#define tUnusedState data[3]
#define tFadeTimer data[4]
static void Task_SlowFadeIn(u8 taskId)
{
u8 i = 0;
if (gTasks[taskId].tBlendTarget1 == 0)
{
gTasks[gTasks[taskId].tParentTaskId].tTrainerPicFadeState = 1;
DestroyTask(taskId);
for (i = PIKACHU_BODY_PLATFORM_LEFT; i < NUM_PIKACHU_PLATFORM_SPRITES; i++)
gSprites[gTasks[taskId].tPikachuPlatformSpriteId(i)].invisible = TRUE;
}
else
{
if (gTasks[taskId].tFadeTimer != 0)
{
gTasks[taskId].tFadeTimer--;
}
else
{
gTasks[taskId].tFadeTimer = gTasks[taskId].tTimer;
gTasks[taskId].tBlendTarget1--;
gTasks[taskId].tBlendTarget2++;
if (gTasks[taskId].tBlendTarget1 == 8)
{
for (i = PIKACHU_BODY_PLATFORM_LEFT; i < NUM_PIKACHU_PLATFORM_SPRITES; i++)
gSprites[gTasks[taskId].tPikachuPlatformSpriteId(i)].invisible ^= TRUE;
}
SetGpuReg(REG_OFFSET_BLDALPHA, (gTasks[taskId].tBlendTarget2 * 256) + gTasks[taskId].tBlendTarget1);
}
}
}
static void CreateFadeInTask(u8 taskId, u8 delay)
{
u8 taskId2;
u8 i = 0;
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_OBJ);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0));
SetGpuReg(REG_OFFSET_BLDY, 0);
gTasks[taskId].tTrainerPicFadeState = 0;
taskId2 = CreateTask(Task_SlowFadeIn, 0);
gTasks[taskId2].tParentTaskId = taskId;
gTasks[taskId2].tBlendTarget1 = 16;
gTasks[taskId2].tBlendTarget2 = 0;
gTasks[taskId2].tUnusedState = delay; // assigned, but never read
gTasks[taskId2].tFadeTimer = delay;
for (i = PIKACHU_BODY_PLATFORM_LEFT; i < NUM_PIKACHU_PLATFORM_SPRITES; i++)
gTasks[taskId2].tPikachuPlatformSpriteId(i) = gTasks[taskId].tPikachuPlatformSpriteId(i);
}
static void Task_SlowFadeOut(u8 taskId)
{
u8 i = 0;
if (gTasks[taskId].tBlendTarget1 == 16)
{
if (!gPaletteFade.active)
{
gTasks[gTasks[taskId].tParentTaskId].tTrainerPicFadeState = 1;
DestroyTask(taskId);
}
}
else
{
if (gTasks[taskId].tFadeTimer != 0)
{
gTasks[taskId].tFadeTimer--;
}
else
{
gTasks[taskId].tFadeTimer = gTasks[taskId].tTimer;
gTasks[taskId].tBlendTarget1 += 2;
gTasks[taskId].tBlendTarget2 -= 2;
if (gTasks[taskId].tBlendTarget1 == 8)
{
for (i = PIKACHU_BODY_PLATFORM_LEFT; i < NUM_PIKACHU_PLATFORM_SPRITES; i++)
gSprites[gTasks[taskId].tPikachuPlatformSpriteId(i)].invisible ^= TRUE;
}
SetGpuReg(REG_OFFSET_BLDALPHA, (gTasks[taskId].tBlendTarget2 * 256) + gTasks[taskId].tBlendTarget1);
}
}
}
static void CreateFadeOutTask(u8 taskId, u8 delay)
{
u8 taskId2;
u8 i = 0;
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_OBJ);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16));
SetGpuReg(REG_OFFSET_BLDY, 0);
gTasks[taskId].tTrainerPicFadeState = 0;
taskId2 = CreateTask(Task_SlowFadeOut, 0);
gTasks[taskId2].tParentTaskId = taskId;
gTasks[taskId2].tBlendTarget1 = 0;
gTasks[taskId2].tBlendTarget2 = 16;
gTasks[taskId2].tUnusedState = delay; // assigned, but never read
gTasks[taskId2].tFadeTimer = delay;
for (i = PIKACHU_BODY_PLATFORM_LEFT; i < NUM_PIKACHU_PLATFORM_SPRITES; i++)
gTasks[taskId2].tPikachuPlatformSpriteId(i) = gTasks[taskId].tPikachuPlatformSpriteId(i);
}
static void PrintNameChoiceOptions(u8 taskId, u8 hasPlayerBeenNamed)
{
s16 *data = gTasks[taskId].data;
const u8 *const *textPtrs;
u8 i;
tMenuWindowId = AddWindow(&sIntro_WindowTemplates[WIN_INTRO_NAMES]);
PutWindowTilemap(tMenuWindowId);
DrawStdFrameWithCustomTileAndPalette(tMenuWindowId, 1, GetStdWindowBaseTileNum(), 14);
FillWindowPixelBuffer(gTasks[taskId].tMenuWindowId, PIXEL_FILL(1));
AddTextPrinterParameterized(tMenuWindowId, FONT_NORMAL, gOtherText_NewName, 8, 1, 0, NULL);
if (hasPlayerBeenNamed == FALSE)
textPtrs = gSaveBlock2Ptr->playerGender == MALE ? sMaleNameChoices : sFemaleNameChoices;
else
textPtrs = sRivalNameChoices;
for (i = 0; i < ARRAY_COUNT(sRivalNameChoices); i++)
AddTextPrinterParameterized(tMenuWindowId, FONT_NORMAL, textPtrs[i], 8, 16 * (i + 1) + 1, 0, NULL);
Menu_InitCursor(tMenuWindowId, FONT_NORMAL, 0, 1, 16, 5, 0);
CopyWindowToVram(tMenuWindowId, COPYWIN_FULL);
}
static void GetDefaultName(u8 hasPlayerBeenNamed, u8 rivalNameChoice)
{
const u8 *src;
u8 *dest;
u8 i;
if (hasPlayerBeenNamed == FALSE)
{
if (gSaveBlock2Ptr->playerGender == MALE)
src = sMaleNameChoices[Random() % ARRAY_COUNT(sMaleNameChoices)];
else
src = sFemaleNameChoices[Random() % ARRAY_COUNT(sFemaleNameChoices)];
dest = gSaveBlock2Ptr->playerName;
}
else
{
src = sRivalNameChoices[rivalNameChoice];
dest = gSaveBlock1Ptr->rivalName;
}
for (i = 0; i < PLAYER_NAME_LENGTH && src[i] != EOS; i++)
dest[i] = src[i];
for (; i < PLAYER_NAME_LENGTH + 1; i++)
dest[i] = EOS;
}
#undef tSpriteTimer
#undef tTrainerPicPosX
#undef tTrainerPicFadeState
#undef tTimer
#undef tNidoranFSpriteId
#undef tTextCursorSpriteId
#undef tPokeBallSpriteId
#undef tMenuWindowId
#undef tTextboxWindowId
#undef tDelta
#undef tPlayerPicFadeOutTimer
#undef tScaleDelta
#undef tPlayerIsShrunk
#undef shrinkTimer
#undef tPlayerPicFadeWhiteTimer
#undef tUnderflowingTimer
#undef tSecondaryTimer
#undef tBlendCoefficient
#undef tNameNotConfirmed
#undef sBodySpriteId
#undef tParentTaskId
#undef tBlendTarget1
#undef tBlendTarget2
#undef tUnusedState
#undef tFadeTimer