#include "global.h" #include "contest.h" #include "data2.h" #include "ewram.h" #include "field_fadetransition.h" #include "main.h" #include "menu.h" #include "menu_cursor.h" #include "move_tutor_menu.h" #include "overworld.h" #include "palette.h" #include "pokemon.h" #include "pokemon_summary_screen.h" #include "script.h" #include "sound.h" #include "sprite.h" #include "string_util.h" #include "strings.h" #include "strings2.h" #include "task.h" #include "trig.h" #include "constants/songs.h" extern u16 gSpecialVar_0x8004; extern u16 gSpecialVar_0x8005; extern u8 gTileBuffer[]; extern const struct WindowTemplate gMenuTextWindowTemplate; extern const struct WindowTemplate gMoveTutorMenuFramesWindowTemplate; extern const u8 *const gContestEffectStrings[]; extern const u8 *const gMoveDescriptions[]; extern const u8 gTypeNames[][7]; extern const u8 *const gContestCategoryNames[]; #ifdef GERMAN extern const u8 deuOtherText_ForgotAndLearned[]; #endif static void InitMoveTutorMenuWaitFade(u8); static void CB2_InitMoveTutorMenu(void); static void CB2_MoveTutorMenu(void); static void MoveTutorMain(void); static void DrawLearnMoveMenuWindow(void); static void DrawBattleMoveInfoHeaders(bool8); static u8 ChangeToContestMoveInfoWindow(void); static void DrawContestMoveInfoHeaders(bool8); static u8 ChangeToBattleMoveInfoWindow(void); static void ResetMoveTutorMenu(void); static void InitMoveTutorMenuSprites(void); static void InitMoveTutorMenuStrings(void); static void HandleMoveTutorMenuInput(void); static void DrawMoveSelectionWindow(void); static void DrawMoveInfoWindow(bool8, int); static void RedrawMoveInfoWindow(void); static void UpdateMoveTutorMenuCursorPosition(struct Sprite *); struct MoveTutorMenu { u8 state; u8 filler1; u8 unk2; u8 spriteIDs[20]; u8 filler17; u8 cursorPos; u8 curMenuChoice; u8 numMenuChoices; u8 menuSelection; u8 previousCursorPos; bool8 redrawCursor; bool8 redrawMoveSelectionWindow; u16 movesToLearn[MAX_MOVE_TUTOR_MOVES]; u8 filler48[10]; u8 moveNames[6][25]; u8 fillerE8[475]; bool8 redrawMoveInfoWindow; bool8 showContestInfo; u8 partyMonIndex; u8 forgetMoveIndex; }; static struct MoveTutorMenu *sMoveTutorMenu; const u16 gMoveTutorMenuArrows_Pal[] = INCBIN_U16("graphics/move_tutor_menu/arrows.gbapal"); const u8 gMoveTutorMenuArrows_Gfx[] = INCBIN_U8("graphics/move_tutor_menu/arrows.4bpp"); const u8 gMoveTutorMenuWindowFrameDimensions[][4] = { { 0, 0, 9, 13}, {10, 0, 29, 7}, { 2, 14, 27, 19}, {10, 8, 29, 13}, }; struct MoveTutorMoveInfoHeaders { const u8 *text; u8 left; u8 right; u8 index; // unused }; const struct MoveTutorMoveInfoHeaders gMoveTutorMoveInfoHeaders[][4] = { { {OtherText_Battle, 1, 1, 0}, {OtherText_Power, 1, 4, 1}, {OtherText_Accuracy, 1, 9, 2}, {NULL, 0, 0, 0}, }, { {OtherText_Contest, 1, 1, 0}, {OtherText_Appeal, 1, 4, 1}, {OtherText_Jam, 1, 9, 2}, {NULL, 0, 0, 0}, }, }; // XXX: What are these for? const u32 unkDataFF00FFEF = 0xFF00FFEF; const u8 *const gTileBuffer_ = gTileBuffer; const struct OamData gOamData_8402D50 = {.shape = 0}; const struct OamData gOamData_8402D58 = {.shape = 2}; const struct OamData gOamData_8402D60 = {.shape = 1}; const union AnimCmd gSpriteAnim_8402D68[] = { ANIMCMD_FRAME(2, 5), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_8402D70[] = { ANIMCMD_FRAME(0, 5), ANIMCMD_END, }; const union AnimCmd *const gSpriteAnimTable_8402D78[] = { gSpriteAnim_8402D68, gSpriteAnim_8402D70, }; const struct SpriteSheet gMoveTutorMenuArrowsSpriteSheet = {gMoveTutorMenuArrows_Gfx, sizeof(gMoveTutorMenuArrows_Gfx), 5525}; const struct SpritePalette gMoveTutorMenuArrowsPalette = {gMoveTutorMenuArrows_Pal, 5526}; const struct SpriteTemplate gSpriteTemplate_8402D90 = { .tileTag = 5525, .paletteTag = 5526, .oam = &gOamData_8402D58, .anims = gSpriteAnimTable_8402D78, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = UpdateMoveTutorMenuCursorPosition, }; const union AnimCmd gSpriteAnim_8402DA8[] = { ANIMCMD_FRAME(4, 5), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_8402DB0[] = { ANIMCMD_FRAME(6, 5), ANIMCMD_END, }; const union AnimCmd *const gSpriteAnimTable_8402DB8[] = { gSpriteAnim_8402DA8, gSpriteAnim_8402DB0, }; const struct SpriteTemplate gSpriteTemplate_8402DC0 = { .tileTag = 5525, .paletteTag = 5526, .oam = &gOamData_8402D60, .anims = gSpriteAnimTable_8402DB8, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = UpdateMoveTutorMenuCursorPosition, }; const union AnimCmd gSpriteAnim_8402DD8[] = { ANIMCMD_FRAME(8, 5), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_8402DE0[] = { ANIMCMD_FRAME(9, 5), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_8402DE8[] = { ANIMCMD_FRAME(10, 5), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_8402DF0[] = { ANIMCMD_FRAME(11, 5), ANIMCMD_END, }; const union AnimCmd *const gSpriteAnimTable_8402DF8[] = { gSpriteAnim_8402DD8, gSpriteAnim_8402DE0, gSpriteAnim_8402DE8, gSpriteAnim_8402DF0, }; const struct SpriteTemplate gSpriteTemplate_8402E08 = { .tileTag = 5525, .paletteTag = 5526, .oam = &gOamData_8402D50, .anims = gSpriteAnimTable_8402DF8, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = UpdateMoveTutorMenuCursorPosition, }; const u8 gString_AkitoMori[] = _("あきと"); // programmer Akito Mori? static void VBlankCB_MoveTutorMenu(void) { LoadOam(); ProcessSpriteCopyRequests(); TransferPlttBuffer(); } void DisplayMoveTutorMenu(void) { ScriptContext2_Enable(); CreateTask(InitMoveTutorMenuWaitFade, 10); BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB(0, 0, 0)); } static void InitMoveTutorMenuWaitFade(u8 taskId) { if (!gPaletteFade.active) { SetMainCallback2(CB2_InitMoveTutorMenu); gFieldCallback = sub_8080990; DestroyTask(taskId); } } static void CB2_InitMoveTutorMenu(void) { REG_DISPCNT = 0; ResetSpriteData(); FreeAllSpritePalettes(); ResetTasks(); sMoveTutorMenu = eMoveTutorMenu; ResetMoveTutorMenu(); sMoveTutorMenu->partyMonIndex = gSpecialVar_0x8004; InitMoveTutorMenuStrings(); SetVBlankCallback(VBlankCB_MoveTutorMenu); Text_LoadWindowTemplate(&gMoveTutorMenuFramesWindowTemplate); InitMenuWindow(&gMoveTutorMenuFramesWindowTemplate); Menu_EraseScreen(); Text_LoadWindowTemplate(&gMenuTextWindowTemplate); InitMenuWindow(&gMenuTextWindowTemplate); Menu_EraseScreen(); REG_BG0VOFS = 0; REG_BG0VOFS = 0; REG_BG1HOFS = 0; REG_BG1HOFS = 0; LoadSpriteSheet(&gMoveTutorMenuArrowsSpriteSheet); LoadSpritePalette(&gMoveTutorMenuArrowsPalette); InitMoveTutorMenuSprites(); FillPalette(0, 0, 2); RunTasks(); AnimateSprites(); BuildOamBuffer(); UpdatePaletteFade(); SetMainCallback2(CB2_MoveTutorMenu); } void CB2_ReturnToMoveTutorMenu(void) { ResetSpriteData(); FreeAllSpritePalettes(); ResetTasks(); sMoveTutorMenu = eMoveTutorMenu; InitMoveTutorMenuStrings(); sMoveTutorMenu->forgetMoveIndex = gSpecialVar_0x8005; SetVBlankCallback(VBlankCB_MoveTutorMenu); Text_LoadWindowTemplate(&gMoveTutorMenuFramesWindowTemplate); InitMenuWindow(&gMoveTutorMenuFramesWindowTemplate); Menu_EraseScreen(); Text_LoadWindowTemplate(&gMenuTextWindowTemplate); InitMenuWindow(&gMenuTextWindowTemplate); Menu_EraseScreen(); REG_DISPCNT = DISPCNT_OBJ_ON | DISPCNT_BG0_ON | DISPCNT_BG1_ON | DISPCNT_OBJ_1D_MAP; REG_BG0VOFS = 0; REG_BG0HOFS = 0; REG_BG1HOFS = 0; REG_BG1HOFS = 0; LoadSpriteSheet(&gMoveTutorMenuArrowsSpriteSheet); LoadSpritePalette(&gMoveTutorMenuArrowsPalette); InitMoveTutorMenuSprites(); FillPalette(0, 0, 2); RunTasks(); AnimateSprites(); BuildOamBuffer(); UpdatePaletteFade(); SetMainCallback2(CB2_MoveTutorMenu); } static void CB2_MoveTutorMenu(void) { MoveTutorMain(); if (sMoveTutorMenu->redrawCursor) { sMoveTutorMenu->redrawCursor = FALSE; MenuCursor_SetPos814AD7C(0x58, (sMoveTutorMenu->cursorPos * 2 + 1) * 8); } if (sMoveTutorMenu->redrawMoveSelectionWindow) { sMoveTutorMenu->redrawMoveSelectionWindow = 0; DrawMoveSelectionWindow(); } if (sMoveTutorMenu->redrawMoveInfoWindow) { DrawMoveInfoWindow(sMoveTutorMenu->showContestInfo, 1); sMoveTutorMenu->redrawMoveInfoWindow = FALSE; } RunTasks(); AnimateSprites(); BuildOamBuffer(); UpdatePaletteFade(); } static void PrintMainMoveTutorMenuText(const u8 *str) { StringExpandPlaceholders(gStringVar4, str); MenuPrintMessage(gStringVar4, 3, 15); } static void MoveTutorMain(void) { switch (sMoveTutorMenu->state) { case 0: sMoveTutorMenu->state++; DrawLearnMoveMenuWindow(); DrawBattleMoveInfoHeaders(FALSE); DrawMoveSelectionWindow(); gSprites[1].x = 0x48; sMoveTutorMenu->redrawMoveInfoWindow = TRUE; BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB(0, 0, 0)); REG_DISPCNT = DISPCNT_OBJ_ON | DISPCNT_BG0_ON | DISPCNT_BG1_ON | DISPCNT_OBJ_1D_MAP; break; case 1: if (!gPaletteFade.active) sMoveTutorMenu->state = 4; break; case 2: sMoveTutorMenu->state++; break; case 3: DrawBattleMoveInfoHeaders(FALSE); DrawMoveSelectionWindow(); sMoveTutorMenu->redrawMoveInfoWindow = TRUE; sMoveTutorMenu->state++; gSprites[1].x = 0x48; break; case 4: if (!ChangeToContestMoveInfoWindow()) HandleMoveTutorMenuInput(); return; case 5: DrawContestMoveInfoHeaders(FALSE); DrawMoveSelectionWindow(); sMoveTutorMenu->redrawMoveInfoWindow = TRUE; gSprites[1].x = 0x48; sMoveTutorMenu->state++; break; case 6: if (!ChangeToBattleMoveInfoWindow()) HandleMoveTutorMenuInput(); break; case 8: if (Menu_UpdateWindowText()) { DisplayYesNoMenu(21, 7, 1); sMoveTutorMenu->state++; } break; case 9: { s8 selection = Menu_ProcessInputNoWrap_(); if (selection == 0) { RedrawMoveInfoWindow(); if (GiveMoveToMon(&gPlayerParty[sMoveTutorMenu->partyMonIndex], sMoveTutorMenu->movesToLearn[sMoveTutorMenu->menuSelection]) != 0xFFFF) { PrintMainMoveTutorMenuText(gOtherText_PokeLearnedMove); gSpecialVar_0x8004 = 1; sMoveTutorMenu->state = 31; } else { sMoveTutorMenu->state = 16; } } else if (selection == -1 || selection == 1) { RedrawMoveInfoWindow(); if (sMoveTutorMenu->showContestInfo == FALSE) sMoveTutorMenu->state = 3; if (sMoveTutorMenu->showContestInfo == TRUE) sMoveTutorMenu->state = 5; } } break; case 12: if (Menu_UpdateWindowText()) { DisplayYesNoMenu(21, 7, 1); sMoveTutorMenu->state++; } break; case 13: { s8 selection = Menu_ProcessInputNoWrap_(); if (selection == 0) { RedrawMoveInfoWindow(); gSpecialVar_0x8004 = selection; sMoveTutorMenu->state = 14; } else if (selection == -1 || selection == 1) { RedrawMoveInfoWindow(); if (sMoveTutorMenu->showContestInfo == FALSE) sMoveTutorMenu->state = 3; if (sMoveTutorMenu->showContestInfo == TRUE) sMoveTutorMenu->state = 5; } } break; case 16: PrintMainMoveTutorMenuText(gOtherText_DeleteOlderMove); sMoveTutorMenu->state++; break; case 17: if (Menu_UpdateWindowText()) { DisplayYesNoMenu(21, 7, 1); sMoveTutorMenu->state = 18; } break; case 18: { s8 var = Menu_ProcessInputNoWrap_(); if (var == 0) { RedrawMoveInfoWindow(); PrintMainMoveTutorMenuText(gOtherText_WhichMoveToForget); sMoveTutorMenu->state = 19; } else if (var == -1 || var == 1) { RedrawMoveInfoWindow(); sMoveTutorMenu->state = 24; } } break; case 24: PrintMainMoveTutorMenuText(gOtherText_StopLearningMove); sMoveTutorMenu->state++; break; case 25: if (Menu_UpdateWindowText()) { sMoveTutorMenu->state = 26; DisplayYesNoMenu(21, 7, 1); } break; case 26: { s8 var = Menu_ProcessInputNoWrap_(); if (var == 0) { RedrawMoveInfoWindow(); sMoveTutorMenu->state = 27; } else if (var == -1 || var == 1) { RedrawMoveInfoWindow(); // What's the point? It gets set to 16, anyway. if (sMoveTutorMenu->showContestInfo == FALSE) sMoveTutorMenu->state = 3; if (sMoveTutorMenu->showContestInfo == TRUE) sMoveTutorMenu->state = 5; sMoveTutorMenu->state = 16; } } break; case 27: if (Menu_UpdateWindowText()) { if (sMoveTutorMenu->showContestInfo == FALSE) sMoveTutorMenu->state = 3; if (sMoveTutorMenu->showContestInfo == TRUE) sMoveTutorMenu->state = 5; } break; case 19: if (Menu_UpdateWindowText()) { sMoveTutorMenu->state = 20; BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB(0, 0, 0)); } break; case 20: if (!gPaletteFade.active) { ShowSelectMovePokemonSummaryScreen(gPlayerParty, sMoveTutorMenu->partyMonIndex, gPlayerPartyCount - 1, CB2_ReturnToMoveTutorMenu, sMoveTutorMenu->movesToLearn[sMoveTutorMenu->menuSelection]); sMoveTutorMenu->state = 28; } break; case 21: if (Menu_UpdateWindowText()) sMoveTutorMenu->state = 14; break; case 22: BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB(0, 0, 0)); break; case 14: BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB(0, 0, 0)); sMoveTutorMenu->state++; break; case 15: if (!gPaletteFade.active) SetMainCallback2(CB2_ReturnToField); break; case 28: BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB(0, 0, 0)); sMoveTutorMenu->state++; DrawLearnMoveMenuWindow(); DrawMoveSelectionWindow(); if (sMoveTutorMenu->showContestInfo == FALSE) DrawBattleMoveInfoHeaders(TRUE); if (sMoveTutorMenu->showContestInfo == TRUE) { gSprites[1].x = 0x48; DrawContestMoveInfoHeaders(TRUE); } DrawMoveInfoWindow(sMoveTutorMenu->showContestInfo, 1); break; case 29: if (!gPaletteFade.active) { if (sMoveTutorMenu->forgetMoveIndex == 4) { sMoveTutorMenu->state = 24; } else { u16 moveId = GetMonData(&gPlayerParty[sMoveTutorMenu->partyMonIndex], MON_DATA_MOVE1 + sMoveTutorMenu->forgetMoveIndex); StringCopy(gStringVar3, gMoveNames[moveId]); RemoveMonPPBonus(&gPlayerParty[sMoveTutorMenu->partyMonIndex], sMoveTutorMenu->forgetMoveIndex); SetMonMoveSlot(&gPlayerParty[sMoveTutorMenu->partyMonIndex], sMoveTutorMenu->movesToLearn[sMoveTutorMenu->menuSelection], sMoveTutorMenu->forgetMoveIndex); StringCopy(gStringVar2, gMoveNames[sMoveTutorMenu->movesToLearn[sMoveTutorMenu->menuSelection]]); PrintMainMoveTutorMenuText(gOtherText_ForgotMove123); sMoveTutorMenu->state = 30; gSpecialVar_0x8004 = 1; } } break; case 30: if (Menu_UpdateWindowText()) { #ifdef GERMAN PrintMainMoveTutorMenuText(deuOtherText_ForgotAndLearned); #else PrintMainMoveTutorMenuText(gOtherText_ForgotOrDidNotLearnMove); #endif sMoveTutorMenu->state = 31; PlayFanfare(MUS_LEVEL_UP); } break; case 31: if (Menu_UpdateWindowText()) { PlayFanfare(MUS_LEVEL_UP); sMoveTutorMenu->state = 32; } break; case 32: if (IsFanfareTaskInactive()) sMoveTutorMenu->state = 33; break; case 33: if (gMain.newKeys & A_BUTTON) { PlaySE(SE_SELECT); sMoveTutorMenu->state = 14; } break; } } static void DrawLearnMoveMenuWindow(void) { u32 i; BasicInitMenuWindow(&gMoveTutorMenuFramesWindowTemplate); for (i = 0; i < 4; i++) { Menu_DrawStdWindowFrame( gMoveTutorMenuWindowFrameDimensions[i][0], gMoveTutorMenuWindowFrameDimensions[i][1], gMoveTutorMenuWindowFrameDimensions[i][2], gMoveTutorMenuWindowFrameDimensions[i][3]); } BasicInitMenuWindow(&gMenuTextWindowTemplate); } static void DrawBattleMoveInfoHeaders(bool8 noTeachMoveText) { s32 i; gSprites[sMoveTutorMenu->spriteIDs[0]].invisible = FALSE; gSprites[sMoveTutorMenu->spriteIDs[1]].invisible = FALSE; for (i = 0; i < 16; i++) gSprites[sMoveTutorMenu->spriteIDs[i + 4]].invisible = TRUE; for (i = 0; gMoveTutorMoveInfoHeaders[0][i].text != NULL; i++) { AlignStringInMenuWindow(gTileBuffer, gMoveTutorMoveInfoHeaders[0][i].text, 64, 2); Menu_PrintText(gTileBuffer, gMoveTutorMoveInfoHeaders[0][i].left, gMoveTutorMoveInfoHeaders[0][i].right); } if (!noTeachMoveText) sub_8072AB0(gOtherText_TeachWhichMove, 24, 120, 192, 32, 1); } static u8 ChangeToContestMoveInfoWindow(void) { u32 result = (gMain.newKeys & DPAD_LEFT) || (gMain.newKeys & DPAD_RIGHT); if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR && ((gMain.newKeys & L_BUTTON) || (gMain.newKeys & R_BUTTON))) result++; if (result != 0) { PlaySE(SE_SELECT); sMoveTutorMenu->state = 5; sMoveTutorMenu->showContestInfo = TRUE; } return result; } static void DrawContestMoveInfoHeaders(bool8 noTeachMoveText) { s32 i; gSprites[sMoveTutorMenu->spriteIDs[0]].invisible = FALSE; gSprites[sMoveTutorMenu->spriteIDs[1]].invisible = FALSE; for (i = 0; i < 16; i++) gSprites[sMoveTutorMenu->spriteIDs[i + 4]].invisible = FALSE; for (i = 0; gMoveTutorMoveInfoHeaders[0][i].text != NULL; i++) { AlignStringInMenuWindow(gTileBuffer, gMoveTutorMoveInfoHeaders[1][i].text, 64, 2); Menu_PrintText(gTileBuffer, gMoveTutorMoveInfoHeaders[1][i].left, gMoveTutorMoveInfoHeaders[1][i].right); if (i != 0) { Menu_EraseWindowRect( gMoveTutorMoveInfoHeaders[1][i].left, gMoveTutorMoveInfoHeaders[1][i].right + 2, gMoveTutorMoveInfoHeaders[1][i].left + 7, gMoveTutorMoveInfoHeaders[1][i].right + 3); } } if (!noTeachMoveText) sub_8072AB0(gOtherText_TeachWhichMove, 24, 120, 192, 32, 1); } static u8 ChangeToBattleMoveInfoWindow(void) { u32 result = (gMain.newKeys & DPAD_LEFT) || (gMain.newKeys & DPAD_RIGHT); if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR && ((gMain.newKeys & L_BUTTON) || (gMain.newKeys & R_BUTTON))) result++; if (result != 0) { PlaySE(SE_SELECT); sMoveTutorMenu->state = 3; sMoveTutorMenu->showContestInfo = FALSE; } return result; } static void ResetMoveTutorMenu(void) { s32 i; sMoveTutorMenu->state = 0; sMoveTutorMenu->unk2 = 0; sMoveTutorMenu->curMenuChoice = 0; sMoveTutorMenu->cursorPos = 0; sMoveTutorMenu->previousCursorPos = 0; sMoveTutorMenu->numMenuChoices = 0; sMoveTutorMenu->menuSelection = 0; sMoveTutorMenu->redrawCursor = FALSE; sMoveTutorMenu->redrawMoveSelectionWindow = 0; sMoveTutorMenu->redrawMoveInfoWindow = FALSE; sMoveTutorMenu->showContestInfo = FALSE; for (i = 0; i < MAX_MOVE_TUTOR_MOVES; i++) sMoveTutorMenu->movesToLearn[i] = 0; } static void UpdateMoveTutorMenuCursorPosition(struct Sprite *sprite) { s16 var = (sprite->data[1] * 10) & 0xFF; switch (sprite->data[0]) { case 0: break; case 1: sprite->x2 = Sin(var, 3) * sprite->data[2]; break; case 2: sprite->y2 = Sin(var, 1) * sprite->data[2]; break; } sprite->data[1]++; } static void InitMoveTutorMenuSprites(void) { s32 i; sMoveTutorMenu->spriteIDs[0] = CreateSprite(&gSpriteTemplate_8402D90, 8, 16, 0); gSprites[sMoveTutorMenu->spriteIDs[0]].data[0] = 1; gSprites[sMoveTutorMenu->spriteIDs[0]].data[2] = -1; sMoveTutorMenu->spriteIDs[1] = CreateSprite(&gSpriteTemplate_8402D90, 72, 16, 0); StartSpriteAnim(&gSprites[sMoveTutorMenu->spriteIDs[1]], 1); gSprites[sMoveTutorMenu->spriteIDs[1]].data[0] = 1; gSprites[sMoveTutorMenu->spriteIDs[1]].data[2] = 1; sMoveTutorMenu->spriteIDs[2] = CreateSprite(&gSpriteTemplate_8402DC0, 160, 4, 0); StartSpriteAnim(&gSprites[sMoveTutorMenu->spriteIDs[2]], 1); gSprites[sMoveTutorMenu->spriteIDs[2]].data[0] = 2; gSprites[sMoveTutorMenu->spriteIDs[2]].data[2] = -1; sMoveTutorMenu->spriteIDs[3] = CreateSprite(&gSpriteTemplate_8402DC0, 160, 60, 0); gSprites[sMoveTutorMenu->spriteIDs[3]].data[0] = 2; gSprites[sMoveTutorMenu->spriteIDs[3]].data[2] = 1; for (i = 0; i < 8; i++) { sMoveTutorMenu->spriteIDs[i + 4] = CreateSprite(&gSpriteTemplate_8402E08, (i - (i / 4) * 4) * 8 + 0x1C, (i / 4) * 8 + 0x34, 0); StartSpriteAnim(&gSprites[sMoveTutorMenu->spriteIDs[i + 4]], 2); } for (i = 0; i < 8; i++) { sMoveTutorMenu->spriteIDs[i + 12] = CreateSprite(&gSpriteTemplate_8402E08, (i - (i / 4) * 4) * 8 + 0x1C, (i / 4) * 8 + 0x5C, 0); StartSpriteAnim(&gSprites[sMoveTutorMenu->spriteIDs[i + 12]], 2); } for (i = 0; i < 20; i++) gSprites[sMoveTutorMenu->spriteIDs[i]].invisible = TRUE; CreateBlendedOutlineCursor(16, 0xFFFF, 12, 0x2D9F, 18); } static void InitMoveTutorMenuStrings(void) { s32 i; u8 nickname[POKEMON_NAME_LENGTH + 1]; sMoveTutorMenu->numMenuChoices = GetMoveTutorMoves(&gPlayerParty[sMoveTutorMenu->partyMonIndex], sMoveTutorMenu->movesToLearn); for (i = 0; i < sMoveTutorMenu->numMenuChoices; i++) StringCopy(sMoveTutorMenu->moveNames[i], gMoveNames[sMoveTutorMenu->movesToLearn[i]]); GetMonData(&gPlayerParty[sMoveTutorMenu->partyMonIndex], MON_DATA_NICKNAME, nickname); StringCopy10(gStringVar1, nickname); StringCopy(sMoveTutorMenu->moveNames[sMoveTutorMenu->numMenuChoices], gOtherText_Exit); sMoveTutorMenu->numMenuChoices++; } static void MoveCursorPos(s8 delta) { sMoveTutorMenu->previousCursorPos = sMoveTutorMenu->cursorPos; sMoveTutorMenu->cursorPos += delta; sMoveTutorMenu->redrawCursor = TRUE; } static void HandleMoveTutorMenuInput(void) { if (gMain.newAndRepeatedKeys & DPAD_UP) { if (sMoveTutorMenu->menuSelection != 0) { PlaySE(SE_SELECT); sMoveTutorMenu->menuSelection--; sMoveTutorMenu->redrawMoveInfoWindow = TRUE; if (sMoveTutorMenu->cursorPos != 0) { MoveCursorPos(-1); } else if (sMoveTutorMenu->curMenuChoice != 0) { sMoveTutorMenu->curMenuChoice--; sMoveTutorMenu->redrawMoveSelectionWindow++; } } } else if (gMain.newAndRepeatedKeys & DPAD_DOWN) { if (sMoveTutorMenu->menuSelection < sMoveTutorMenu->numMenuChoices - 1) { PlaySE(SE_SELECT); sMoveTutorMenu->menuSelection++; sMoveTutorMenu->redrawMoveInfoWindow = TRUE; if (sMoveTutorMenu->cursorPos != 2) { MoveCursorPos(1); } else if (sMoveTutorMenu->curMenuChoice != sMoveTutorMenu->numMenuChoices - 3) { sMoveTutorMenu->curMenuChoice++; sMoveTutorMenu->redrawMoveSelectionWindow++; } } } else if (gMain.newKeys & A_BUTTON) { PlaySE(SE_SELECT); if (sMoveTutorMenu->menuSelection != sMoveTutorMenu->numMenuChoices - 1) { sMoveTutorMenu->state = 8; StringCopy(gStringVar2, sMoveTutorMenu->moveNames[sMoveTutorMenu->menuSelection]); StringExpandPlaceholders(gStringVar4, gOtherText_TeachSpecificMove); MenuPrintMessage(gStringVar4, 3, 15); } else { StringExpandPlaceholders(gStringVar4, gOtherText_GiveUpTeachingMove); MenuPrintMessage(gStringVar4, 3, 15); sMoveTutorMenu->state = 12; } } else if (gMain.newKeys & B_BUTTON) { PlaySE(SE_SELECT); sMoveTutorMenu->state = 12; StringExpandPlaceholders(gStringVar4, gOtherText_GiveUpTeachingMove); MenuPrintMessage(gStringVar4, 3, 15); } if (sMoveTutorMenu->numMenuChoices > 3) { gSprites[2].invisible = FALSE; gSprites[3].invisible = FALSE; if (sMoveTutorMenu->curMenuChoice == 0) gSprites[2].invisible = TRUE; else if (sMoveTutorMenu->curMenuChoice == sMoveTutorMenu->numMenuChoices - 3) gSprites[3].invisible = TRUE; } } static void DrawMoveSelectionWindow(void) { u8 menuChoice = sMoveTutorMenu->curMenuChoice; u8 *str = gTileBuffer; s32 i; for (i = 0; i < 3; i++) { if (menuChoice >= sMoveTutorMenu->numMenuChoices) { str = AlignStringInMenuWindow(str, gEmptyString_81E72B0, 0x90, 0); } else if (menuChoice == sMoveTutorMenu->numMenuChoices - 1) { str = AlignStringInMenuWindow(str, gOtherText_Exit, 0x90, 0); } else { u16 moveId = sMoveTutorMenu->movesToLearn[menuChoice]; if (sMoveTutorMenu->showContestInfo) str = AlignStringInMenuWindow(str, gContestCategoryNames[gContestMoves[moveId].contestCategory], 0x27, 0); else str = AlignStringInMenuWindow(str, gTypeNames[gBattleMoves[moveId].type], 0x27, 0); str = AlignStringInMenuWindow(str, sMoveTutorMenu->moveNames[menuChoice], 0x72, 0); str[0] = CHAR_P; str[1] = CHAR_P; str[2] = CHAR_SLASH; str += 3; str = AlignInt1InMenuWindow(str, gBattleMoves[moveId].pp, 0x90, 0); } *str++ = CHAR_NEWLINE; menuChoice++; } *str = EOS; Menu_PrintText(gTileBuffer, 11, 1); MoveCursorPos(0); } static const u8 sMoveInfoTextCoords[7][3] = { {11, 1, 1}, { 3, 6, 2}, {24, 1, 3}, { 3, 11, 4}, { 5, 4, 5}, { 3, 6, 6}, { 3, 11, 7}, }; static const u8 sBattleMoveInfoCoordIds[] = {0, 1, 2, 3}; static const u8 sContestMoveInfoCoordIds[] = {4, 5, 6}; void PrintMoveInfo(u16 moveId, const u8 *moveInfoCoords) { u8 str[0x34]; u8 numHearts; u8 i; StringCopy(str, gExpandedPlaceholder_Empty); switch (moveInfoCoords[2]) { case 1: break; case 2: if (gBattleMoves[moveId].power < 2) AlignStringInMenuWindow(str, gOtherText_ThreeDashes2, 32, 2); else AlignInt1InMenuWindow(str, gBattleMoves[moveId].power, 32, 2); Menu_PrintText(str, moveInfoCoords[0], moveInfoCoords[1]); break; case 4: if (gBattleMoves[moveId].accuracy == 0) AlignStringInMenuWindow(str, gOtherText_ThreeDashes2, 32, 2); else AlignInt1InMenuWindow(str, gBattleMoves[moveId].accuracy, 32, 2); Menu_PrintText(str, moveInfoCoords[0], moveInfoCoords[1]); break; case 6: Menu_EraseWindowRect(moveInfoCoords[0], moveInfoCoords[1], moveInfoCoords[0], moveInfoCoords[1] + 1); numHearts = gContestEffects[gContestMoves[moveId].effect].appeal / 10; if (numHearts == 255) numHearts = 0; for (i = 0; i < 8; i++) { if (i < numHearts) StartSpriteAnim(&gSprites[sMoveTutorMenu->spriteIDs[i + 4]], 1); else StartSpriteAnim(&gSprites[sMoveTutorMenu->spriteIDs[i + 4]], 0); } break; case 7: Menu_EraseWindowRect(moveInfoCoords[0], moveInfoCoords[1], moveInfoCoords[0], moveInfoCoords[1] + 1); numHearts = gContestEffects[gContestMoves[moveId].effect].jam / 10; if (numHearts == 255) numHearts = 0; for (i = 0; i < 8; i++) { if (i < numHearts) StartSpriteAnim(&gSprites[sMoveTutorMenu->spriteIDs[i + 12]], 3); else StartSpriteAnim(&gSprites[sMoveTutorMenu->spriteIDs[i + 12]], 2); } break; } } static void DrawMoveInfoWindow(bool8 contestInfo, int unused) { u16 i; if (sMoveTutorMenu->menuSelection != sMoveTutorMenu->numMenuChoices - 1) { u16 moveId = sMoveTutorMenu->movesToLearn[sMoveTutorMenu->menuSelection]; if (contestInfo) { for (i = 0; i < 16; i++) gSprites[sMoveTutorMenu->spriteIDs[i + 4]].invisible = FALSE; for (i = 0; i < 3; i++) PrintMoveInfo(moveId, sMoveInfoTextCoords[sContestMoveInfoCoordIds[i]]); sub_8072AB0(gContestEffectStrings[gContestMoves[moveId].effect], 0x58, 0x48, 0x90, 32, 1); } else { u8 var; for (i = 0; i < 4; i++) PrintMoveInfo(moveId, sMoveInfoTextCoords[sBattleMoveInfoCoordIds[i]]); var = sub_8072A18(gMoveDescriptions[moveId - 1], 0x58, 0x48, 0x90, 1); if (var < 2) { u8 r1 = var * 2 + 9; Menu_BlankWindowRect(11, r1, 28, 12); } } } else { if (contestInfo) { Menu_EraseWindowRect(sMoveInfoTextCoords[5][0], sMoveInfoTextCoords[5][1], sMoveInfoTextCoords[5][0], sMoveInfoTextCoords[5][1] + 1); Menu_EraseWindowRect(sMoveInfoTextCoords[6][0], sMoveInfoTextCoords[6][1], sMoveInfoTextCoords[6][0], sMoveInfoTextCoords[6][1] + 1); for (i = 0; i < 16; i++) gSprites[sMoveTutorMenu->spriteIDs[i + 4]].invisible = TRUE; } else { Menu_EraseWindowRect(sMoveInfoTextCoords[1][0], sMoveInfoTextCoords[1][1], sMoveInfoTextCoords[1][0] + 3, sMoveInfoTextCoords[1][1] + 1); Menu_EraseWindowRect(sMoveInfoTextCoords[3][0], sMoveInfoTextCoords[3][1], sMoveInfoTextCoords[3][0] + 3, sMoveInfoTextCoords[3][1] + 1); } Menu_EraseWindowRect(11, 9, 28, 12); } } static void RedrawMoveInfoWindow(void) { Menu_EraseWindowRect(21, 7, 27, 12); DrawMoveInfoWindow(sMoveTutorMenu->showContestInfo, 0); }