mirror of
https://github.com/pret/pokefirered.git
synced 2026-05-10 14:01:52 -05:00
933 lines
30 KiB
C
933 lines
30 KiB
C
#include "global.h"
|
|
#include "gflib.h"
|
|
#include "script.h"
|
|
#include "task.h"
|
|
#include "data.h"
|
|
#include "trig.h"
|
|
#include "field_fadetransition.h"
|
|
#include "overworld.h"
|
|
#include "menu.h"
|
|
#include "list_menu.h"
|
|
#include "event_data.h"
|
|
#include "text_window.h"
|
|
#include "pokemon_summary_screen.h"
|
|
#include "graphics.h"
|
|
#include "move.h"
|
|
#include "strings.h"
|
|
#include "constants/songs.h"
|
|
#include "constants/moves.h"
|
|
|
|
/*
|
|
* Move relearner state machine
|
|
* ------------------------
|
|
*
|
|
* CB2_MoveRelearner_Init
|
|
* - Creates listMenuScrollPos to listen to right/left buttons.
|
|
* - Creates listMenuScrollRow to listen to up/down buttons.
|
|
* MoveRelearnerStateMachine: MENU_STATE_FADE_TO_BLACK
|
|
* MoveRelearnerStateMachine: MENU_STATE_WAIT_FOR_FADE
|
|
* - Go to MENU_STATE_IDLE_BATTLE_MODE
|
|
*
|
|
* MoveRelearnerStateMachine: MENU_STATE_SETUP_BATTLE_MODE
|
|
* MoveRelearnerStateMachine: MENU_STATE_IDLE_BATTLE_MODE
|
|
* - If the player selected a move (pressed A), go to MENU_STATE_PRINT_TEACH_MOVE_PROMPT.
|
|
* - If the player cancelled (pressed B), go to MENU_STATE_PRINT_GIVE_UP_PROMPT.
|
|
*
|
|
* MoveRelearnerStateMachine: MENU_STATE_PRINT_TEACH_MOVE_PROMPT
|
|
* MoveRelearnerStateMachine: MENU_STATE_TEACH_MOVE_CONFIRM
|
|
* - Wait for the player to confirm.
|
|
* - If cancelled, go to MENU_STATE_SETUP_BATTLE_MODE.
|
|
* - If confirmed and the pokemon had an empty move slot, set VAR_0x8004 to TRUE and go to
|
|
* MENU_STATE_PRINT_TEXT_THEN_FANFARE.
|
|
* - If confirmed and the pokemon doesn't have an empty move slot, go to
|
|
* MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT.
|
|
*
|
|
* MoveRelearnerStateMachine: MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT
|
|
* MoveRelearnerStateMachine: MENU_STATE_WAIT_FOR_TRYING_TO_LEARN
|
|
* MoveRelearnerStateMachine: MENU_STATE_CONFIRM_DELETE_OLD_MOVE
|
|
* - If the player confirms, go to MENU_STATE_PRINT_WHICH_MOVE_PROMPT.
|
|
* - If the player cancels, go to MENU_STATE_PRINT_STOP_TEACHING
|
|
*
|
|
* MoveRelearnerStateMachine: MENU_STATE_PRINT_STOP_TEACHING
|
|
* MoveRelearnerStateMachine: MENU_STATE_WAIT_FOR_STOP_TEACHING
|
|
* MoveRelearnerStateMachine: MENU_STATE_CONFIRM_STOP_TEACHING
|
|
* - If the player confirms, go to MENU_STATE_CHOOSE_SETUP_STATE.
|
|
* - If the player cancels, go back to MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT.
|
|
*
|
|
* MoveRelearnerStateMachine: MENU_STATE_PRINT_WHICH_MOVE_PROMPT
|
|
* MoveRelearnerStateMachine: MENU_STATE_SHOW_MOVE_SUMMARY_SCREEN
|
|
* - Go to ShowSelectMovePokemonSummaryScreen. When done, control returns to
|
|
* CB2_MoveRelearner_Resume.
|
|
*
|
|
* MoveRelearnerStateMachine: MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE
|
|
* MoveRelearnerStateMachine: MENU_STATE_PRINT_TEXT_THEN_FANFARE
|
|
* MoveRelearnerStateMachine: MENU_STATE_WAIT_FOR_FANFARE
|
|
* MoveRelearnerStateMachine: MENU_STATE_WAIT_FOR_A_BUTTON
|
|
* MoveRelearnerStateMachine: MENU_STATE_FADE_AND_RETURN
|
|
* MoveRelearnerStateMachine: MENU_STATE_RETURN_TO_FIELD
|
|
* - Clean up and go to CB2_ReturnToField.
|
|
*
|
|
* MoveRelearnerStateMachine: MENU_STATE_PRINT_GIVE_UP_PROMPT
|
|
* MoveRelearnerStateMachine: MENU_STATE_GIVE_UP_CONFIRM
|
|
* - If the player confirms, go to MENU_STATE_FADE_AND_RETURN, and set VAR_0x8004 to FALSE.
|
|
* - If the player cancels, go to MENU_STATE_SETUP_BATTLE_MODE.
|
|
*
|
|
* CB2_MoveRelearner_Resume:
|
|
* - Do most of the same stuff as CB2_MoveRelearner_Init.
|
|
* MoveRelearnerStateMachine: MENU_STATE_FADE_FROM_SUMMARY_SCREEN
|
|
* MoveRelearnerStateMachine: MENU_STATE_TRY_OVERWRITE_MOVE
|
|
* - If any of the pokemon's existing moves were chosen, overwrite the move and
|
|
* go to MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE and set VAR_0x8004 to TRUE.
|
|
* - If the chosen move is the one the player selected before the summary screen,
|
|
* go to MENU_STATE_PRINT_STOP_TEACHING.
|
|
*
|
|
*/
|
|
|
|
#define MENU_STATE_FADE_TO_BLACK 0
|
|
#define MENU_STATE_WAIT_FOR_FADE 1
|
|
#define MENU_STATE_UNREACHABLE 2
|
|
#define MENU_STATE_SETUP_BATTLE_MODE 3
|
|
#define MENU_STATE_IDLE_BATTLE_MODE 4
|
|
// States 5, 6, and 7 are skipped.
|
|
#define MENU_STATE_PRINT_TEACH_MOVE_PROMPT 8
|
|
#define MENU_STATE_TEACH_MOVE_CONFIRM 9
|
|
// States 10 and 11 are skipped.
|
|
#define MENU_STATE_PRINT_GIVE_UP_PROMPT 12
|
|
#define MENU_STATE_GIVE_UP_CONFIRM 13
|
|
#define MENU_STATE_FADE_AND_RETURN 14
|
|
#define MENU_STATE_RETURN_TO_FIELD 15
|
|
#define MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT 16
|
|
#define MENU_STATE_WAIT_FOR_TRYING_TO_LEARN 17
|
|
#define MENU_STATE_CONFIRM_DELETE_OLD_MOVE 18
|
|
#define MENU_STATE_PRINT_WHICH_MOVE_PROMPT 19
|
|
#define MENU_STATE_SHOW_MOVE_SUMMARY_SCREEN 20
|
|
// States 21, 22, and 23 are skipped.
|
|
#define MENU_STATE_PRINT_STOP_TEACHING 24
|
|
#define MENU_STATE_WAIT_FOR_STOP_TEACHING 25
|
|
#define MENU_STATE_CONFIRM_STOP_TEACHING 26
|
|
#define MENU_STATE_CHOOSE_SETUP_STATE 27
|
|
#define MENU_STATE_FADE_FROM_SUMMARY_SCREEN 28
|
|
#define MENU_STATE_TRY_OVERWRITE_MOVE 29
|
|
#define MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE 30
|
|
#define MENU_STATE_PRINT_TEXT_THEN_FANFARE 31
|
|
#define MENU_STATE_WAIT_FOR_FANFARE 32
|
|
#define MENU_STATE_WAIT_FOR_A_BUTTON 33
|
|
|
|
struct MoveTutorMoveInfoHeaders
|
|
{
|
|
const u8 *text;
|
|
u8 left;
|
|
u8 right;
|
|
u8 index; // unused
|
|
};
|
|
|
|
struct LearnMoveGfxResources
|
|
{
|
|
u8 state;
|
|
u8 unk_01;
|
|
u8 unk_02;
|
|
u8 spriteIds[2];
|
|
u8 filler_05[0x13];
|
|
u8 unk_18;
|
|
u8 scrollPositionMaybe;
|
|
u8 numLearnableMoves;
|
|
u8 unk_1B;
|
|
u8 unk_1C;
|
|
u8 unk_1D;
|
|
u8 unk_1E;
|
|
struct ListMenuItem listMenuItems[MAX_RELEARNER_MOVES + 1];
|
|
u16 learnableMoves[MAX_RELEARNER_MOVES];
|
|
u8 listMenuStrbufs[MAX_RELEARNER_MOVES][13];
|
|
bool8 scheduleMoveInfoUpdate;
|
|
u8 selectedPartyMember;
|
|
u8 selectedMoveSlot;
|
|
u8 unk_262;
|
|
u8 listMenuTaskId;
|
|
u8 bg1TilemapBuffer[BG_SCREEN_SIZE]; // 264
|
|
u8 textColor[3]; // A64
|
|
u8 selectedIndex;
|
|
u16 listMenuScrollPos;
|
|
u16 listMenuScrollRow;
|
|
};
|
|
|
|
static EWRAM_DATA struct LearnMoveGfxResources * sMoveRelearner = NULL;
|
|
|
|
static void Task_InitMoveRelearnerMenu(u8 taskId);
|
|
static void CB2_MoveRelearner_Init(void);
|
|
static void CB2_MoveRelearner(void);
|
|
static void MoveRelearnerStateMachine(void);
|
|
static void DrawTextBorderOnWindows6and7(void);
|
|
static void PrintTeachWhichMoveToStrVar1(bool8 onInit);
|
|
static void InitMoveRelearnerStateVariables(void);
|
|
static void SpriteCB_ListMenuScrollIndicators(struct Sprite *sprite);
|
|
static void SpawnListMenuScrollIndicatorSprites(void);
|
|
static void MoveRelearnerInitListMenuBuffersEtc(void);
|
|
static void MoveRelearnerMenuHandleInput(void);
|
|
static void MoveLearnerInitListMenu(void);
|
|
static void LoadMoveInfoUI(void);
|
|
static void PrintMoveInfoHandleCancel_CopyToVram(void);
|
|
static void MoveRelearnerMenu_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list);
|
|
static s8 YesNoMenuProcessInput(void);
|
|
static void PrintTextOnWindow(u8 windowId, const u8 *str, u8 x, u8 y, s32 speed, s32 colorIdx);
|
|
|
|
static const u16 sLearnMoveInterfaceSpritesPalette[] = INCBIN_U16("graphics/learn_move/interface_sprites.gbapal");
|
|
static const u16 sLearnMoveInterfaceSpritesTiles[] = INCBIN_U16("graphics/learn_move/interface_sprites.4bpp");
|
|
|
|
static const u8 sMoveTutorMenuWindowFrameDimensions[][4] =
|
|
{
|
|
{ 0, 0, 19, 13},
|
|
{20, 0, 29, 13},
|
|
{ 2, 14, 27, 19}
|
|
};
|
|
|
|
static const u8 sJPText_TatakauWaza[] = _("たたかうわざ");
|
|
static const u8 sJPText_Taipu[] = _("タイプ/");
|
|
static const u8 sJPText_PP[] = _("PP/");
|
|
static const u8 sJPText_Iryoku[] = _("いりょく/");
|
|
static const u8 sJPText_Meichuu[] = _("めいちゅう/");
|
|
|
|
static const struct MoveTutorMoveInfoHeaders sMoveTutorMoveInfoHeaders[][5] =
|
|
{
|
|
{
|
|
{sJPText_TatakauWaza, 7, 1, 0},
|
|
{sJPText_Taipu, 1, 4, 1},
|
|
{sJPText_Iryoku, 11, 4, 2},
|
|
{sJPText_PP, 2, 6, 3},
|
|
{sJPText_Meichuu, 10, 6, 4},
|
|
},
|
|
{
|
|
{NULL, 0, 0, 0},
|
|
{NULL, 0, 0, 0},
|
|
{NULL, 0, 0, 0},
|
|
{NULL, 0, 0, 0},
|
|
{NULL, 0, 0, 0},
|
|
},
|
|
};
|
|
|
|
static const struct SpriteSheet sSpriteSheet_ListMenuScrollIndicators = {
|
|
sLearnMoveInterfaceSpritesTiles, 0x180, 5525
|
|
};
|
|
|
|
static const struct SpritePalette sSpritePalette_ListMenuScrollIndicators = {
|
|
sLearnMoveInterfaceSpritesPalette, 5526
|
|
};
|
|
|
|
static const struct OamData sOamdata_MoveRelearnerListMenuScrollIndicators = {
|
|
.shape = SPRITE_SHAPE(16x8),
|
|
.size = SPRITE_SIZE(16x8)
|
|
};
|
|
|
|
static const union AnimCmd sAnimCmd_ScrollIndicatorDown[] = {
|
|
ANIMCMD_FRAME(4, 5),
|
|
ANIMCMD_END
|
|
};
|
|
|
|
static const union AnimCmd sAnimCmd_ScrollIndicatorUp[] = {
|
|
ANIMCMD_FRAME(6, 5),
|
|
ANIMCMD_END
|
|
};
|
|
|
|
static const union AnimCmd *const sSpriteAnimTable_MoveRelearnerListMenuScrollIndicators[] = {
|
|
sAnimCmd_ScrollIndicatorDown,
|
|
sAnimCmd_ScrollIndicatorUp
|
|
};
|
|
|
|
static const struct SpriteTemplate sSpriteTemplate_MoveRelearnerListMenuScrollIndicators = {
|
|
5525, 5526, &sOamdata_MoveRelearnerListMenuScrollIndicators, sSpriteAnimTable_MoveRelearnerListMenuScrollIndicators, NULL, gDummySpriteAffineAnimTable, SpriteCB_ListMenuScrollIndicators
|
|
};
|
|
|
|
static const struct BgTemplate sBgTemplates[2] = {
|
|
{
|
|
.bg = 0,
|
|
.charBaseIndex = 2,
|
|
.mapBaseIndex = 31,
|
|
.priority = 0
|
|
},
|
|
{
|
|
.bg = 1,
|
|
.charBaseIndex = 0,
|
|
.mapBaseIndex = 8,
|
|
.priority = 1
|
|
}
|
|
};
|
|
|
|
static const struct WindowTemplate sWindowTemplates[9] = {
|
|
{
|
|
.bg = 0,
|
|
.tilemapLeft = 0,
|
|
.tilemapTop = 0,
|
|
.width = 6,
|
|
.height = 7,
|
|
.paletteNum = 13,
|
|
.baseBlock = 0x014
|
|
},
|
|
{
|
|
.bg = 0,
|
|
.tilemapLeft = 10,
|
|
.tilemapTop = 0,
|
|
.width = 5,
|
|
.height = 5,
|
|
.paletteNum = 13,
|
|
.baseBlock = 0x03e
|
|
},
|
|
{
|
|
.bg = 0,
|
|
.tilemapLeft = 5,
|
|
.tilemapTop = 0,
|
|
.width = 5,
|
|
.height = 2,
|
|
.paletteNum = 13,
|
|
.baseBlock = 0x057
|
|
},
|
|
{
|
|
.bg = 0,
|
|
.tilemapLeft = 15,
|
|
.tilemapTop = 0,
|
|
.width = 3,
|
|
.height = 5,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x061
|
|
},
|
|
{
|
|
.bg = 0,
|
|
.tilemapLeft = 5,
|
|
.tilemapTop = 2,
|
|
.width = 3,
|
|
.height = 3,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x070
|
|
},
|
|
{
|
|
.bg = 0,
|
|
.tilemapLeft = 2,
|
|
.tilemapTop = 6,
|
|
.width = 15,
|
|
.height = 8,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x079
|
|
},
|
|
{
|
|
.bg = 0,
|
|
.tilemapLeft = 19,
|
|
.tilemapTop = 1,
|
|
.width = 10,
|
|
.height = 12,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x0f1
|
|
},
|
|
{
|
|
.bg = 0,
|
|
.tilemapLeft = 2,
|
|
.tilemapTop = 15,
|
|
.width = 26,
|
|
.height = 4,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x169
|
|
}, DUMMY_WIN_TEMPLATE
|
|
};
|
|
|
|
static const struct WindowTemplate sMoveRelearnerYesNoMenuTemplate = {
|
|
.bg = 0,
|
|
.tilemapLeft = 21,
|
|
.tilemapTop = 8,
|
|
.width = 6,
|
|
.height = 4,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x1d1
|
|
};
|
|
|
|
static const struct ListMenuTemplate sMoveRelearnerListMenuTemplate = {
|
|
.items = NULL,
|
|
.moveCursorFunc = MoveRelearnerMenu_MoveCursorFunc,
|
|
.itemPrintFunc = NULL,
|
|
.totalItems = 0,
|
|
.maxShowed = 7,
|
|
.windowId = 6,
|
|
.header_X = 0,
|
|
.item_X = 8,
|
|
.cursor_X = 0,
|
|
.upText_Y = 0,
|
|
.cursorPal = 2,
|
|
.fillValue = 1,
|
|
.cursorShadowPal = 3,
|
|
.lettersSpacing = 1,
|
|
.itemVerticalPadding = 0,
|
|
.scrollMultiple = 0,
|
|
.fontId = FONT_NORMAL,
|
|
.cursorKind = 0,
|
|
};
|
|
|
|
static void VBlankCB_MoveRelearner(void)
|
|
{
|
|
LoadOam();
|
|
ProcessSpriteCopyRequests();
|
|
TransferPlttBuffer();
|
|
}
|
|
|
|
void DisplayMoveTutorMenu(void)
|
|
{
|
|
LockPlayerFieldControls();
|
|
CreateTask(Task_InitMoveRelearnerMenu, 10);
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
|
}
|
|
|
|
static void Task_InitMoveRelearnerMenu(u8 taskId)
|
|
{
|
|
if (!gPaletteFade.active)
|
|
{
|
|
SetMainCallback2(CB2_MoveRelearner_Init);
|
|
gFieldCallback = FieldCB_ContinueScriptHandleMusic;
|
|
DestroyTask(taskId);
|
|
}
|
|
}
|
|
|
|
static void MoveRelearnerLoadBgGfx(void)
|
|
{
|
|
int i;
|
|
ResetBgsAndClearDma3BusyFlags(FALSE);
|
|
InitBgsFromTemplates(0, sBgTemplates, NELEMS(sBgTemplates));
|
|
ResetTempTileDataBuffers();
|
|
if (InitWindows(sWindowTemplates))
|
|
{
|
|
DeactivateAllTextPrinters();
|
|
for (i = 0; i < NELEMS(sWindowTemplates); i++)
|
|
{
|
|
ClearWindowTilemap(i);
|
|
FillWindowPixelBuffer(i, PIXEL_FILL(0));
|
|
}
|
|
FillWindowPixelBuffer(7, PIXEL_FILL(1));
|
|
FillBgTilemapBufferRect(0, 0x000, 0, 0, 30, 20, 15);
|
|
SetBgTilemapBuffer(1, sMoveRelearner->bg1TilemapBuffer);
|
|
LoadUserWindowBorderGfx(0, 1, BG_PLTT_ID(14));
|
|
ListMenuLoadStdPalAt(BG_PLTT_ID(13), 1);
|
|
LoadPalette(gMoveRelearner_Pal, BG_PLTT_ID(0), PLTT_SIZE_4BPP);
|
|
DecompressAndLoadBgGfxUsingHeap(1, gMoveRelearner_Gfx, 0, 0, 0);
|
|
CopyToBgTilemapBuffer(1, gMoveRelearner_Tilemap, 0, 0);
|
|
CopyBgTilemapBufferToVram(1);
|
|
SetGpuReg(REG_OFFSET_BG0VOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG0HOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG1VOFS, 0);
|
|
SetGpuReg(REG_OFFSET_BG1HOFS, 0);
|
|
}
|
|
}
|
|
|
|
static void CB2_MoveRelearner_Init(void)
|
|
{
|
|
SetGpuReg(REG_OFFSET_DISPCNT, 0);
|
|
ResetSpriteData();
|
|
FreeAllSpritePalettes();
|
|
ResetTasks();
|
|
sMoveRelearner = AllocZeroed(sizeof(struct LearnMoveGfxResources));
|
|
InitMoveRelearnerStateVariables();
|
|
sMoveRelearner->selectedPartyMember = gSpecialVar_0x8004;
|
|
MoveRelearnerInitListMenuBuffersEtc();
|
|
SetVBlankCallback(VBlankCB_MoveRelearner);
|
|
MoveRelearnerLoadBgGfx();
|
|
SpawnListMenuScrollIndicatorSprites();
|
|
RunTasks();
|
|
AnimateSprites();
|
|
BuildOamBuffer();
|
|
UpdatePaletteFade();
|
|
SetMainCallback2(CB2_MoveRelearner);
|
|
}
|
|
|
|
static void CB2_MoveRelearner_Resume(void)
|
|
{
|
|
SetGpuReg(REG_OFFSET_DISPCNT, 0);
|
|
ResetSpriteData();
|
|
FreeAllSpritePalettes();
|
|
ResetTasks();
|
|
MoveRelearnerInitListMenuBuffersEtc();
|
|
sMoveRelearner->selectedMoveSlot = gSpecialVar_0x8005;
|
|
SetVBlankCallback(VBlankCB_MoveRelearner);
|
|
MoveRelearnerLoadBgGfx();
|
|
SpawnListMenuScrollIndicatorSprites();
|
|
SetBackdropFromColor(RGB_BLACK);
|
|
|
|
RunTasks();
|
|
AnimateSprites();
|
|
BuildOamBuffer();
|
|
UpdatePaletteFade();
|
|
SetMainCallback2(CB2_MoveRelearner);
|
|
}
|
|
|
|
static void CB2_MoveRelearner(void)
|
|
{
|
|
if (!IsTextPrinterActive(7))
|
|
MoveRelearnerStateMachine();
|
|
if (sMoveRelearner->scheduleMoveInfoUpdate)
|
|
{
|
|
PrintMoveInfoHandleCancel_CopyToVram();
|
|
sMoveRelearner->scheduleMoveInfoUpdate = FALSE;
|
|
}
|
|
RunTasks();
|
|
RunTextPrinters();
|
|
AnimateSprites();
|
|
BuildOamBuffer();
|
|
UpdatePaletteFade();
|
|
}
|
|
|
|
static void StringExpandPlaceholdersAndPrintTextOnWindow7Color2(const u8 *str)
|
|
{
|
|
StringExpandPlaceholders(gStringVar4, str);
|
|
PrintTextOnWindow(7, gStringVar4, 0, 2, GetPlayerTextSpeedDelay(), 2);
|
|
}
|
|
|
|
static void MoveRelearnerStateMachine(void)
|
|
{
|
|
u16 move;
|
|
|
|
switch (sMoveRelearner->state)
|
|
{
|
|
case MENU_STATE_FADE_TO_BLACK:
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
|
|
ShowBg(0);
|
|
ShowBg(1);
|
|
LoadMoveInfoUI();
|
|
sMoveRelearner->state++;
|
|
DrawTextBorderOnWindows6and7();
|
|
PrintTeachWhichMoveToStrVar1(FALSE);
|
|
MoveLearnerInitListMenu();
|
|
sMoveRelearner->scheduleMoveInfoUpdate = TRUE;
|
|
break;
|
|
case MENU_STATE_WAIT_FOR_FADE:
|
|
if (!gPaletteFade.active)
|
|
sMoveRelearner->state = 4;
|
|
break;
|
|
case MENU_STATE_UNREACHABLE:
|
|
sMoveRelearner->state++;
|
|
break;
|
|
case MENU_STATE_SETUP_BATTLE_MODE:
|
|
PrintTeachWhichMoveToStrVar1(FALSE);
|
|
sMoveRelearner->scheduleMoveInfoUpdate = TRUE;
|
|
sMoveRelearner->state++;
|
|
break;
|
|
case MENU_STATE_IDLE_BATTLE_MODE:
|
|
MoveRelearnerMenuHandleInput();
|
|
break;
|
|
case MENU_STATE_PRINT_TEACH_MOVE_PROMPT:
|
|
CreateYesNoMenuAtPos(&sMoveRelearnerYesNoMenuTemplate, FONT_NORMAL_COPY_2, 0, 2, 0x001, 14, 0);
|
|
sMoveRelearner->state++;
|
|
break;
|
|
case MENU_STATE_TEACH_MOVE_CONFIRM :
|
|
switch (YesNoMenuProcessInput())
|
|
{
|
|
case 0:
|
|
if (GiveMoveToMon(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex]) != 0xFFFF)
|
|
{
|
|
StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_MonLearnedMove);
|
|
gSpecialVar_0x8004 = TRUE;
|
|
sMoveRelearner->state = 31;
|
|
}
|
|
else
|
|
{
|
|
sMoveRelearner->state = 16;
|
|
}
|
|
break;
|
|
case 1:
|
|
case -1:
|
|
sMoveRelearner->state = 3;
|
|
break;
|
|
}
|
|
break;
|
|
case MENU_STATE_PRINT_GIVE_UP_PROMPT:
|
|
CreateYesNoMenuAtPos(&sMoveRelearnerYesNoMenuTemplate, FONT_NORMAL_COPY_2, 0, 2, 0x001, 14, 0);
|
|
sMoveRelearner->state++;
|
|
break;
|
|
case MENU_STATE_GIVE_UP_CONFIRM:
|
|
switch (YesNoMenuProcessInput())
|
|
{
|
|
case 0:
|
|
gSpecialVar_0x8004 = FALSE;
|
|
sMoveRelearner->state = 14;
|
|
break;
|
|
case 1:
|
|
case -1:
|
|
sMoveRelearner->state = 3;
|
|
break;
|
|
}
|
|
break;
|
|
case MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT:
|
|
StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_MonIsTryingToLearnMove);
|
|
sMoveRelearner->state++;
|
|
break;
|
|
case MENU_STATE_WAIT_FOR_TRYING_TO_LEARN:
|
|
CreateYesNoMenuAtPos(&sMoveRelearnerYesNoMenuTemplate, FONT_NORMAL_COPY_2, 0, 2, 0x001, 14, 0);
|
|
sMoveRelearner->state = 18;
|
|
break;
|
|
case MENU_STATE_CONFIRM_DELETE_OLD_MOVE:
|
|
switch (YesNoMenuProcessInput())
|
|
{
|
|
case 0:
|
|
StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_WhichMoveShouldBeForgotten);
|
|
sMoveRelearner->state = 19;
|
|
break;
|
|
case 1:
|
|
case -1:
|
|
sMoveRelearner->state = 24;
|
|
break;
|
|
}
|
|
break;
|
|
case MENU_STATE_PRINT_STOP_TEACHING:
|
|
StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_StopLearningMove);
|
|
sMoveRelearner->state++;
|
|
break;
|
|
case MENU_STATE_WAIT_FOR_STOP_TEACHING:
|
|
CreateYesNoMenuAtPos(&sMoveRelearnerYesNoMenuTemplate, FONT_NORMAL_COPY_2, 0, 2, 0x001, 14, 0);
|
|
sMoveRelearner->state = 26;
|
|
break;
|
|
case MENU_STATE_CONFIRM_STOP_TEACHING:
|
|
switch (YesNoMenuProcessInput())
|
|
{
|
|
case 0:
|
|
sMoveRelearner->state = 27;
|
|
break;
|
|
case 1:
|
|
case -1:
|
|
sMoveRelearner->state = 16;
|
|
break;
|
|
}
|
|
break;
|
|
case MENU_STATE_CHOOSE_SETUP_STATE :
|
|
sMoveRelearner->state = 3;
|
|
break;
|
|
case MENU_STATE_PRINT_WHICH_MOVE_PROMPT:
|
|
sMoveRelearner->state = 20;
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
|
break;
|
|
case MENU_STATE_SHOW_MOVE_SUMMARY_SCREEN:
|
|
if (!gPaletteFade.active)
|
|
{
|
|
ListMenuGetScrollAndRow(sMoveRelearner->listMenuTaskId, &sMoveRelearner->listMenuScrollPos, &sMoveRelearner->listMenuScrollRow);
|
|
FreeAllWindowBuffers();
|
|
ShowSelectMovePokemonSummaryScreen(gPlayerParty, sMoveRelearner->selectedPartyMember, gPlayerPartyCount - 1, CB2_MoveRelearner_Resume, sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex]);
|
|
sMoveRelearner->state = 28;
|
|
}
|
|
break;
|
|
case 21:
|
|
sMoveRelearner->state = 14;
|
|
break;
|
|
case 22:
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
|
|
break;
|
|
case MENU_STATE_FADE_AND_RETURN:
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
|
sMoveRelearner->state++;
|
|
break;
|
|
case MENU_STATE_RETURN_TO_FIELD:
|
|
if (!gPaletteFade.active)
|
|
{
|
|
FreeAllWindowBuffers();
|
|
Free(sMoveRelearner);
|
|
SetMainCallback2(CB2_ReturnToField);
|
|
}
|
|
break;
|
|
case MENU_STATE_FADE_FROM_SUMMARY_SCREEN:
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
|
|
ShowBg(0);
|
|
ShowBg(1);
|
|
sMoveRelearner->state++;
|
|
LoadMoveInfoUI();
|
|
DrawTextBorderOnWindows6and7();
|
|
MoveLearnerInitListMenu();
|
|
PrintTeachWhichMoveToStrVar1(TRUE);
|
|
PrintMoveInfoHandleCancel_CopyToVram();
|
|
break;
|
|
case MENU_STATE_TRY_OVERWRITE_MOVE:
|
|
if (!gPaletteFade.active)
|
|
{
|
|
if (sMoveRelearner->selectedMoveSlot == 4)
|
|
{
|
|
sMoveRelearner->state = 24;
|
|
}
|
|
else
|
|
{
|
|
move = GetMonData(&gPlayerParty[sMoveRelearner->selectedPartyMember], MON_DATA_MOVE1 + sMoveRelearner->selectedMoveSlot);
|
|
StringCopy(gStringVar3, GetMoveName(move));
|
|
RemoveMonPPBonus(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->selectedMoveSlot);
|
|
SetMonMoveSlot(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex], sMoveRelearner->selectedMoveSlot);
|
|
StringCopy(gStringVar2, GetMoveName(sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex]));
|
|
StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_1_2_and_Poof);
|
|
sMoveRelearner->state = 30;
|
|
gSpecialVar_0x8004 = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE:
|
|
StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_MonForgotOldMoveAndMonLearnedNewMove);
|
|
sMoveRelearner->state = 31;
|
|
PlayFanfare(MUS_LEVEL_UP);
|
|
break;
|
|
case MENU_STATE_PRINT_TEXT_THEN_FANFARE:
|
|
PlayFanfare(MUS_LEVEL_UP);
|
|
sMoveRelearner->state = 32;
|
|
break;
|
|
case MENU_STATE_WAIT_FOR_FANFARE:
|
|
if (IsFanfareTaskInactive())
|
|
sMoveRelearner->state = 33;
|
|
break;
|
|
case MENU_STATE_WAIT_FOR_A_BUTTON:
|
|
if (JOY_NEW(A_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
sMoveRelearner->state = 14;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void DrawTextBorderOnWindows6and7(void)
|
|
{
|
|
int i;
|
|
for (i = 6; i < 8; i++)
|
|
DrawTextBorderOuter(i, 0x001, 14);
|
|
}
|
|
|
|
static void PrintTeachWhichMoveToStrVar1(bool8 onInit)
|
|
{
|
|
if (!onInit)
|
|
{
|
|
StringExpandPlaceholders(gStringVar4, gText_TeachWhichMoveToMon);
|
|
PrintTextOnWindow(7, gStringVar4, 0, 2, 0, 2);
|
|
PutWindowTilemap(7);
|
|
CopyWindowToVram(7, COPYWIN_FULL);
|
|
}
|
|
}
|
|
|
|
static void InitMoveRelearnerStateVariables(void)
|
|
{
|
|
int i;
|
|
sMoveRelearner->state = 0;
|
|
sMoveRelearner->unk_02 = 0;
|
|
sMoveRelearner->scrollPositionMaybe = 0;
|
|
sMoveRelearner->unk_18 = 0;
|
|
sMoveRelearner->unk_1C = 0;
|
|
sMoveRelearner->numLearnableMoves = 0;
|
|
sMoveRelearner->unk_1B = 0;
|
|
sMoveRelearner->unk_1D = 0;
|
|
sMoveRelearner->unk_1E = 0;
|
|
sMoveRelearner->scheduleMoveInfoUpdate = FALSE;
|
|
for (i = 0; i < 20; i++)
|
|
sMoveRelearner->learnableMoves[i] = MOVE_NONE;
|
|
}
|
|
|
|
static void SpriteCB_ListMenuScrollIndicators(struct Sprite *sprite)
|
|
{
|
|
s16 abcissa = (sprite->data[1] * 10) & 0xFF;
|
|
switch (sprite->data[0])
|
|
{
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
sprite->x2 = Sin(abcissa, 3) * sprite->data[2];
|
|
break;
|
|
case 2:
|
|
sprite->y2 = Sin(abcissa, 1) * sprite->data[2];
|
|
break;
|
|
}
|
|
sprite->data[1]++;
|
|
}
|
|
|
|
static void SpawnListMenuScrollIndicatorSprites(void)
|
|
{
|
|
int i;
|
|
LoadSpriteSheet(&sSpriteSheet_ListMenuScrollIndicators);
|
|
LoadSpritePalette(&sSpritePalette_ListMenuScrollIndicators);
|
|
sMoveRelearner->spriteIds[0] = CreateSprite(&sSpriteTemplate_MoveRelearnerListMenuScrollIndicators, 200, 4, 0);
|
|
StartSpriteAnim(&gSprites[sMoveRelearner->spriteIds[0]], 1);
|
|
gSprites[sMoveRelearner->spriteIds[0]].data[0] = 2;
|
|
gSprites[sMoveRelearner->spriteIds[0]].data[2] = -1;
|
|
|
|
// Bug: This should be using the second element of spriteIds.
|
|
sMoveRelearner->spriteIds[0] = CreateSprite(&sSpriteTemplate_MoveRelearnerListMenuScrollIndicators, 200, 108, 0);
|
|
gSprites[sMoveRelearner->spriteIds[0]].data[0] = 2;
|
|
gSprites[sMoveRelearner->spriteIds[0]].data[2] = 1;
|
|
for (i = 0; i < 2; i++)
|
|
gSprites[sMoveRelearner->spriteIds[i]].invisible = TRUE;
|
|
}
|
|
|
|
static void MoveRelearnerInitListMenuBuffersEtc(void)
|
|
{
|
|
int i;
|
|
s32 count;
|
|
u8 nickname[11];
|
|
|
|
sMoveRelearner->numLearnableMoves = GetMoveRelearnerMoves(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->learnableMoves);
|
|
count = GetMoveRelearnerMoves(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->learnableMoves);
|
|
for (i = 0; i < sMoveRelearner->numLearnableMoves; i++)
|
|
StringCopy(sMoveRelearner->listMenuStrbufs[i], gMovesInfo[sMoveRelearner->learnableMoves[i]].name);
|
|
GetMonData(&gPlayerParty[sMoveRelearner->selectedPartyMember], MON_DATA_NICKNAME, nickname);
|
|
StringCopy_Nickname(gStringVar1, nickname);
|
|
StringCopy(sMoveRelearner->listMenuStrbufs[sMoveRelearner->numLearnableMoves], gFameCheckerText_Cancel);
|
|
sMoveRelearner->numLearnableMoves++;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
sMoveRelearner->listMenuItems[i].label = sMoveRelearner->listMenuStrbufs[i];
|
|
sMoveRelearner->listMenuItems[i].index = i;
|
|
}
|
|
sMoveRelearner->listMenuItems[i].label = gFameCheckerText_Cancel;
|
|
sMoveRelearner->listMenuItems[i].index = 0xFE;
|
|
gMultiuseListMenuTemplate = sMoveRelearnerListMenuTemplate;
|
|
gMultiuseListMenuTemplate.items = sMoveRelearner->listMenuItems;
|
|
gMultiuseListMenuTemplate.totalItems = count + 1;
|
|
}
|
|
|
|
static void MoveRelearnerMenuHandleInput(void)
|
|
{
|
|
ListMenu_ProcessInput(sMoveRelearner->listMenuTaskId);
|
|
if (JOY_NEW(A_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
if (sMoveRelearner->selectedIndex != 0xFE)
|
|
{
|
|
sMoveRelearner->state = 8;
|
|
StringCopy(gStringVar2, sMoveRelearner->listMenuStrbufs[sMoveRelearner->selectedIndex]);
|
|
StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_TeachMoveQues);
|
|
}
|
|
else
|
|
{
|
|
StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_GiveUpTryingToTeachNewMove);
|
|
sMoveRelearner->state = 12;
|
|
}
|
|
}
|
|
else if (JOY_NEW(B_BUTTON))
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
sMoveRelearner->state = 12;
|
|
StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_GiveUpTryingToTeachNewMove);
|
|
}
|
|
if (sMoveRelearner->numLearnableMoves > 6)
|
|
{
|
|
gSprites[0].invisible = FALSE;
|
|
gSprites[1].invisible = FALSE;
|
|
if (sMoveRelearner->scrollPositionMaybe == 0)
|
|
gSprites[0].invisible = TRUE;
|
|
else if (sMoveRelearner->scrollPositionMaybe == sMoveRelearner->numLearnableMoves - 6)
|
|
gSprites[1].invisible = TRUE;
|
|
}
|
|
}
|
|
|
|
static void MoveLearnerInitListMenu(void)
|
|
{
|
|
sMoveRelearner->listMenuTaskId = ListMenuInit(&gMultiuseListMenuTemplate, sMoveRelearner->listMenuScrollPos, sMoveRelearner->listMenuScrollRow);
|
|
CopyWindowToVram(6, COPYWIN_MAP);
|
|
}
|
|
|
|
static void PrintMoveInfo(u16 move)
|
|
{
|
|
u8 buffer[50];
|
|
BlitMenuInfoIcon(2, gMovesInfo[move].type + 1, 1, 4);
|
|
|
|
if (gMovesInfo[move].power < 2)
|
|
{
|
|
PrintTextOnWindow(3, gText_ThreeHyphens, 1, 4, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
ConvertIntToDecimalStringN(buffer, gMovesInfo[move].power, STR_CONV_MODE_RIGHT_ALIGN, 3);
|
|
PrintTextOnWindow(3, buffer, 1, 4, 0, 0);
|
|
}
|
|
|
|
if (gMovesInfo[move].accuracy == 0)
|
|
{
|
|
PrintTextOnWindow(3, gText_ThreeHyphens, 1, 18, 0, 1);
|
|
}
|
|
else
|
|
{
|
|
ConvertIntToDecimalStringN(buffer, gMovesInfo[move].accuracy, STR_CONV_MODE_RIGHT_ALIGN, 3);
|
|
PrintTextOnWindow(3, buffer, 1, 18, 0, 1);
|
|
}
|
|
ConvertIntToDecimalStringN(buffer, gMovesInfo[move].pp, STR_CONV_MODE_LEFT_ALIGN, 2);
|
|
PrintTextOnWindow(4, buffer, 2, 2, 0, 0);
|
|
PrintTextOnWindow(5, gMovesInfo[move].description, 1, 0, 0, 0);
|
|
}
|
|
|
|
static void LoadMoveInfoUI(void)
|
|
{
|
|
BlitMenuInfoIcon(0, MENU_INFO_ICON_TYPE, 1, 4);
|
|
BlitMenuInfoIcon(1, MENU_INFO_ICON_POWER, 0, 4);
|
|
BlitMenuInfoIcon(1, MENU_INFO_ICON_ACCURACY, 0, 19);
|
|
BlitMenuInfoIcon(0, MENU_INFO_ICON_PP, 1, 19);
|
|
BlitMenuInfoIcon(0, MENU_INFO_ICON_EFFECT, 1, 34);
|
|
PutWindowTilemap(0);
|
|
PutWindowTilemap(1);
|
|
PutWindowTilemap(4);
|
|
PutWindowTilemap(3);
|
|
PutWindowTilemap(5);
|
|
PutWindowTilemap(2);
|
|
PutWindowTilemap(7);
|
|
CopyWindowToVram(0, COPYWIN_GFX);
|
|
CopyWindowToVram(1, COPYWIN_GFX);
|
|
}
|
|
|
|
static void PrintMoveInfoHandleCancel_CopyToVram(void)
|
|
{
|
|
int i;
|
|
if (sMoveRelearner->selectedIndex != 0xFE)
|
|
{
|
|
PrintMoveInfo(sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex]);
|
|
}
|
|
else
|
|
{
|
|
for (i = 2; i < 6; i++)
|
|
{
|
|
FillWindowPixelBuffer(i, PIXEL_FILL(0));
|
|
CopyWindowToVram(i, COPYWIN_GFX);
|
|
}
|
|
}
|
|
CopyWindowToVram(3, COPYWIN_GFX);
|
|
CopyWindowToVram(4, COPYWIN_GFX);
|
|
CopyWindowToVram(2, COPYWIN_GFX);
|
|
CopyWindowToVram(2, COPYWIN_GFX);
|
|
CopyWindowToVram(5, COPYWIN_GFX);
|
|
CopyWindowToVram(7, COPYWIN_FULL);
|
|
}
|
|
|
|
static void MoveRelearnerMenu_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list)
|
|
{
|
|
if (!onInit)
|
|
{
|
|
PlaySE(SE_SELECT);
|
|
sMoveRelearner->scheduleMoveInfoUpdate = TRUE;
|
|
sMoveRelearner->selectedIndex = itemIndex;
|
|
}
|
|
}
|
|
|
|
static s8 YesNoMenuProcessInput(void)
|
|
{
|
|
s8 input = Menu_ProcessInputNoWrapClearOnChoose();
|
|
if (input != -2)
|
|
{
|
|
PutWindowTilemap(6);
|
|
CopyWindowToVram(6, COPYWIN_MAP);
|
|
}
|
|
return input;
|
|
}
|
|
|
|
static void PrintTextOnWindow(u8 windowId, const u8 *str, u8 x, u8 y, s32 speed, s32 colorIdx)
|
|
{
|
|
s32 letterSpacing = 1;
|
|
s32 lineSpacing = 1;
|
|
if (colorIdx == 0 || colorIdx == 1)
|
|
{
|
|
letterSpacing = 0;
|
|
lineSpacing = 0;
|
|
}
|
|
switch (colorIdx)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
sMoveRelearner->textColor[0] = 0;
|
|
sMoveRelearner->textColor[1] = 2;
|
|
sMoveRelearner->textColor[2] = 3;
|
|
break;
|
|
case 2:
|
|
sMoveRelearner->textColor[0] = 1;
|
|
sMoveRelearner->textColor[1] = 2;
|
|
sMoveRelearner->textColor[2] = 3;
|
|
}
|
|
if (colorIdx != 1)
|
|
FillWindowPixelBuffer(windowId, PIXEL_FILL(sMoveRelearner->textColor[0]));
|
|
AddTextPrinterParameterized4(windowId, FONT_NORMAL_COPY_2, x, y, letterSpacing, lineSpacing, sMoveRelearner->textColor, speed, str);
|
|
}
|