diff --git a/graphics/summary_screen/iv_ev_tiles.png b/graphics/summary_screen/iv_ev_tiles.png new file mode 100644 index 0000000000..66774f1438 Binary files /dev/null and b/graphics/summary_screen/iv_ev_tiles.png differ diff --git a/include/config/pokemon.h b/include/config/pokemon.h index 0b5d3828ad..3288065f7c 100644 --- a/include/config/pokemon.h +++ b/include/config/pokemon.h @@ -60,18 +60,15 @@ #define P_ONLY_OBTAINABLE_SHINIES FALSE // If TRUE, Pokémon encountered in the Battle Pyramid won't be shiny. #define P_NO_SHINIES_WITHOUT_POKEBALLS FALSE // If TRUE, Pokémon encountered when the player is out of Poké Balls won't be shiny #define P_SHOW_DYNAMIC_TYPES FALSE // If TRUE, all moves with dynamic type changes will be reflected as their current type in battle/summary screens instead of just select ones like in vanilla. -#define P_SUMMARY_SCREEN_MOVE_RELEARNER TRUE // If TRUE, shows an option for Pokémon to relearn moves on the summary screen moves page. -#define P_SUMMARY_MOVE_RELEARNER_FULL_PP TRUE // If TRUE, the move relearner in the summary screen restores relearned moves' PP to full. -#define P_SUMMARY_SCREEN_RENAME TRUE // If TRUE, an option to change Pokémon nicknames replaces the cancel prompt on the summary screen info page. // Learnset helper toggles -#define P_LEARNSET_HELPER_TEACHABLE TRUE // If TRUE, teachable_learnsets.h will be populated by tools/learnset_helpers/teachable.py using the included JSON files based on available TMs and tutors. +#define P_LEARNSET_HELPER_TEACHABLE TRUE // If TRUE, teachable_learnsets.h will be populated by tools/learnset_helpers/teachable.py using the included JSON files based on available TMs and tutors. // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. // Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature. -#define P_FLAG_FORCE_SHINY 0 // If this flag is set, all wild and gift Pokémon will forced into being Shiny. -#define P_FLAG_FORCE_NO_SHINY 0 // If this flag is set, all wild and gift Pokémon will forced into NOT being Shiny. +#define P_FLAG_FORCE_SHINY 0 // If this flag is set, all wild and gift Pokémon will forced into being Shiny. +#define P_FLAG_FORCE_NO_SHINY 0 // If this flag is set, all wild and gift Pokémon will forced into NOT being Shiny. // Go here if you want to disable specific families of Pokémon. #include "config/species_enabled.h" diff --git a/include/config/summary_screen.h b/include/config/summary_screen.h new file mode 100644 index 0000000000..9407d93c7e --- /dev/null +++ b/include/config/summary_screen.h @@ -0,0 +1,30 @@ +#ifndef GUARD_CONFIG_SUMMARY_SCREEN_H +#define GUARD_CONFIG_SUMMARY_SCREEN_H + +// Settings +#define P_SUMMARY_SCREEN_MOVE_RELEARNER TRUE // If TRUE, shows an option for Pokémon to relearn moves on the summary screen moves page. +#define P_SUMMARY_MOVE_RELEARNER_FULL_PP TRUE // If TRUE, the move relearner in the summary screen restores relearned moves' PP to full. +#define P_SUMMARY_SCREEN_RENAME TRUE // If TRUE, an option to change Pokémon nicknames replaces the cancel prompt on the summary screen info page. +#define P_SUMMARY_SCREEN_IV_EV_INFO FALSE // If TRUE, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page. +#define P_SUMMARY_SCREEN_IV_EV_BOX_ONLY FALSE // If TRUE, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page, but only in the PC storage box. +#define P_SUMMARY_SCREEN_IV_EV_TILESET FALSE // If TRUE, loads an alternate tileset to allow changing the "STATS" label in the summary screen skills page. Note: if it's still loading the alternate tileset after changing this and recompiling, you may need a `make clean` before compilation. +#define P_SUMMARY_SCREEN_IV_EV_VALUES FALSE // If TRUE, will show the actual IV value instead of the letter grade. +/* +LETTER GRADE GUIDE: + + F = 0 + D = 1 - 15 + C = 16 - 25 + B = 26 - 29 + A = 30 + S = 31 + +Info taken from https://bulbapedia.bulbagarden.net/wiki/Stats_judge. +*/ +#define P_SUMMARY_SCREEN_IV_ONLY FALSE // If TRUE, will only show IV info in the summary screen. +#define P_SUMMARY_SCREEN_EV_ONLY FALSE // If TRUE, will only show EV info in the summary screen. + +// Flags +#define P_FLAG_SUMMARY_SCREEN_IV_EV_INFO 0 // If this flag is set, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page. Note: if P_SUMMARY_SCREEN_IV_EV_INFO is TRUE, this flag does nothing. + +#endif // GUARD_CONFIG_SUMMARY_SCREEN_H diff --git a/include/constants/global.h b/include/constants/global.h index 76e6847c40..9adb46db23 100644 --- a/include/constants/global.h +++ b/include/constants/global.h @@ -9,6 +9,7 @@ #include "config/pokemon.h" #include "config/overworld.h" #include "config/dexnav.h" +#include "config/summary_screen.h" // Invalid Versions show as "----------" in Gen 4 and Gen 5's summary screen. // In Gens 6 and 7, invalid versions instead show "a distant land" in the summary screen. diff --git a/include/pokemon_summary_screen.h b/include/pokemon_summary_screen.h index 1f286698a5..3aa8460a17 100755 --- a/include/pokemon_summary_screen.h +++ b/include/pokemon_summary_screen.h @@ -2,6 +2,7 @@ #define GUARD_POKEMON_SUMMARY_SCREEN_H #include "main.h" +#include "config/summary_screen.h" extern u8 gLastViewedMonIndex; @@ -40,4 +41,11 @@ enum PokemonSummaryScreenPage PSS_PAGE_COUNT, }; +enum PokemonSummarySkillsMode +{ + SUMMARY_SKILLS_MODE_STATS, + SUMMARY_SKILLS_MODE_IVS, + SUMMARY_SKILLS_MODE_EVS, +}; + #endif // GUARD_POKEMON_SUMMARY_SCREEN_H diff --git a/src/graphics.c b/src/graphics.c index 5aafa8ae45..bc510d9d96 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1683,7 +1683,11 @@ const u32 gMoveTypes_Pal[] = INCBIN_U32("graphics/types/move_types.gbapal.lz"); const u32 gSummaryMoveSelect_Gfx[] = INCBIN_U32("graphics/summary_screen/move_select.4bpp.lz"); const u32 gSummaryMoveSelect_Pal[] = INCBIN_U32("graphics/summary_screen/move_select.gbapal.lz"); +#if P_SUMMARY_SCREEN_IV_EV_TILESET +const u32 gSummaryScreen_Gfx[] = INCBIN_U32("graphics/summary_screen/iv_ev_tiles.4bpp.lz"); +#else const u32 gSummaryScreen_Gfx[] = INCBIN_U32("graphics/summary_screen/tiles.4bpp.lz"); +#endif // P_SUMMARY_SCREEN_IV_EV_TILESET const u32 gSummaryScreen_Pal[] = INCBIN_U32("graphics/summary_screen/tiles.gbapal.lz"); const u32 gSummaryPage_Info_Tilemap[] = INCBIN_U32("graphics/summary_screen/page_info.bin.lz"); const u32 gSummaryPage_Skills_Tilemap[] = INCBIN_U32("graphics/summary_screen/page_skills.bin.lz"); diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index f0c65dc2a7..3636d2f0ae 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -59,9 +59,9 @@ #define PSS_LABEL_WINDOW_CONTEST_MOVES_TITLE 3 // Button control text (upper right) -#define PSS_LABEL_WINDOW_PROMPT_CANCEL 4 // Also handles the "rename" prompt if P_SUMMARY_SCREEN_RENAME is true -#define PSS_LABEL_WINDOW_PROMPT_INFO 5 -#define PSS_LABEL_WINDOW_PROMPT_SWITCH 6 +#define PSS_LABEL_WINDOW_PROMPT_UTILITY 4 // Handles "Switch", "Info", and "Cancel" prompts. Also handles the "Rename" and "IVs"/"EVs"/"STATS" prompts if P_SUMMARY_SCREEN_RENAME and P_SUMMARY_SCREEN_IV_EV_INFO are true, respectively +#define PSS_LABEL_WINDOW_PROMPT_INFO 5 // unused +#define PSS_LABEL_WINDOW_PROMPT_SWITCH 6 // unused #define PSS_LABEL_WINDOW_UNUSED1 7 // Info screen @@ -169,6 +169,7 @@ static EWRAM_DATA struct PokemonSummaryScreenData } summary; u16 bgTilemapBuffers[PSS_PAGE_COUNT][2][0x400]; u8 mode; + u8 skillsPageMode; bool8 isBoxMon; u8 curMonIndex; u8 maxMonIndex; @@ -317,9 +318,22 @@ static void KeepMoveSelectorVisible(u8); static void SummaryScreen_DestroyAnimDelayTask(void); static bool32 ShouldShowMoveRelearner(void); static bool32 ShouldShowRename(void); -static void ShowCancelOrRenamePrompt(void); +static bool32 ShouldShowIvEvPrompt(void); +static void BufferLeftColumnIvEvStats(void); static void CB2_ReturnToSummaryScreenFromNamingScreen(void); static void CB2_PssChangePokemonNickname(void); +static void ShowUtilityPrompt(s16 mode); +static void ShowMonSkillsInfo(u8 taskId, s16 mode); +static void WriteToStatsTilemapBuffer(u32 length, u32 block, u32 statsCoordX, u32 statsCoordY); +void ExtractMonSkillStatsData(struct Pokemon *mon, struct PokeSummary *sum); +void ExtractMonSkillIvData(struct Pokemon *mon, struct PokeSummary *sum); +void ExtractMonSkillEvData(struct Pokemon *mon, struct PokeSummary *sum); +static void PrintTextOnWindow(u8 windowId, const u8 *string, u8 x, u8 y, u8 lineSpacing, u8 colorId); +static void PrintTextOnWindowWithFont(u8 windowId, const u8 *string, u8 x, u8 y, u8 lineSpacing, u8 colorId, u32 fontId); +static const u8 *GetLetterGrade(u32 stat); +static u8 AddWindowFromTemplateList(const struct WindowTemplate *template, u8 templateId); +static u8 IncrementSkillsStatsMode(u8 mode); +static void ClearStatLabel(u32 length, u32 statsCoordX, u32 statsCoordY); static const struct BgTemplate sBgTemplates[] = { @@ -427,7 +441,7 @@ static const struct WindowTemplate sSummaryTemplate[] = .paletteNum = 6, .baseBlock = 67, }, - [PSS_LABEL_WINDOW_PROMPT_CANCEL] = { + [PSS_LABEL_WINDOW_PROMPT_UTILITY] = { .bg = 0, .tilemapLeft = 22, .tilemapTop = 0, @@ -731,6 +745,7 @@ static void (*const sTextPrinterTasks[])(u8 taskId) = static const u8 sMemoNatureTextColor[] = _("{COLOR LIGHT_RED}{SHADOW GREEN}"); static const u8 sMemoMiscTextColor[] = _("{COLOR WHITE}{SHADOW DARK_GRAY}"); // This is also affected by palettes, apparently static const u8 sStatsLeftColumnLayout[] = _("{DYNAMIC 0}/{DYNAMIC 1}\n{DYNAMIC 2}\n{DYNAMIC 3}"); +static const u8 sStatsLeftIVEVColumnLayout[] = _("{DYNAMIC 0}\n{DYNAMIC 1}\n{DYNAMIC 2}"); static const u8 sStatsRightColumnLayout[] = _("{DYNAMIC 0}\n{DYNAMIC 1}\n{DYNAMIC 2}"); static const u8 sMovesPPLayout[] = _("{PP}{DYNAMIC 0}/{DYNAMIC 1}"); @@ -1504,30 +1519,7 @@ static bool8 ExtractMonDataToSummaryStruct(struct Pokemon *mon) sum->ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES); break; case 2: - if (sMonSummaryScreen->monList.mons == gPlayerParty || sMonSummaryScreen->mode == SUMMARY_MODE_BOX || sMonSummaryScreen->handleDeoxys == TRUE) - { - sum->nature = GetNature(mon); - sum->mintNature = GetMonData(mon, MON_DATA_HIDDEN_NATURE); - sum->currentHP = GetMonData(mon, MON_DATA_HP); - sum->maxHP = GetMonData(mon, MON_DATA_MAX_HP); - sum->atk = GetMonData(mon, MON_DATA_ATK); - sum->def = GetMonData(mon, MON_DATA_DEF); - sum->spatk = GetMonData(mon, MON_DATA_SPATK); - sum->spdef = GetMonData(mon, MON_DATA_SPDEF); - sum->speed = GetMonData(mon, MON_DATA_SPEED); - } - else - { - sum->nature = GetNature(mon); - sum->mintNature = GetMonData(mon, MON_DATA_HIDDEN_NATURE); - sum->currentHP = GetMonData(mon, MON_DATA_HP); - sum->maxHP = GetMonData(mon, MON_DATA_MAX_HP); - sum->atk = GetMonData(mon, MON_DATA_ATK2); - sum->def = GetMonData(mon, MON_DATA_DEF2); - sum->spatk = GetMonData(mon, MON_DATA_SPATK2); - sum->spdef = GetMonData(mon, MON_DATA_SPDEF2); - sum->speed = GetMonData(mon, MON_DATA_SPEED2); - } + ExtractMonSkillStatsData(mon, sum); break; case 3: GetMonData(mon, MON_DATA_OT_NAME, sum->OTName); @@ -1640,6 +1632,58 @@ static void CloseSummaryScreen(u8 taskId) } } +// Update skills page tilemap +static void ChangeStatLabel(s16 mode) +{ + if (!P_SUMMARY_SCREEN_IV_EV_TILESET) + return; + + u32 statsBlock = 169; + u32 ivsBlock = 221; + u32 evsBlock = 218; + + u32 statsCoordX = 44; + u32 statsCoordY = 102; + + u32 statsLength = 3; + u32 ivEvLength = 2; + + ClearStatLabel(statsLength, statsCoordX, statsCoordY); + + switch (mode) + { + case SUMMARY_SKILLS_MODE_STATS: + WriteToStatsTilemapBuffer(statsLength, statsBlock, statsCoordX, statsCoordY); + break; + case SUMMARY_SKILLS_MODE_IVS: + WriteToStatsTilemapBuffer(ivEvLength, ivsBlock, statsCoordX, statsCoordY); + break; + case SUMMARY_SKILLS_MODE_EVS: + WriteToStatsTilemapBuffer(ivEvLength, evsBlock, statsCoordX, statsCoordY); + break; + } + CopyBgTilemapBufferToVram(1); +} + +static void WriteToStatsTilemapBuffer(u32 length, u32 block, u32 statsCoordX, u32 statsCoordY) +{ + u32 i; + + for (i = 0; i <= length; i++) + FillBgTilemapBufferRect(1, block + i, statsCoordX + i, statsCoordY, 1, 1, 2); +} + +static void ClearStatLabel(u32 length, u32 statsCoordX, u32 statsCoordY) +{ + u32 blankStatsBlock = 1241; + + u32 i; + u32 blankOffset = 3; + + for (i = 0; i <= length; i++) + FillBgTilemapBufferRect(1, blankStatsBlock, statsCoordX + blankOffset + i, statsCoordY, 1, 1, 2); +} + static void Task_HandleInput(u8 taskId) { if (MenuHelpers_ShouldWaitForLinkRecv() != TRUE && !gPaletteFade.active) @@ -1676,12 +1720,21 @@ static void Task_HandleInput(u8 taskId) PlaySE(SE_SELECT); BeginCloseSummaryScreen(taskId); } - else // Contest or Battle Moves + else if (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES + || sMonSummaryScreen->currPageIndex == PSS_PAGE_CONTEST_MOVES) { PlaySE(SE_SELECT); SwitchToMoveSelection(taskId); } } + if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS) + { + if (ShouldShowIvEvPrompt()) + { + ShowMonSkillsInfo(taskId, IncrementSkillsStatsMode(sMonSummaryScreen->skillsPageMode)); + PlaySE(SE_SELECT); + } + } } else if (JOY_NEW(B_BUTTON)) { @@ -1710,6 +1763,125 @@ static void Task_HandleInput(u8 taskId) } } +static u8 IncrementSkillsStatsMode(u8 mode) +{ + switch (mode) + { + case SUMMARY_SKILLS_MODE_STATS: + if (P_SUMMARY_SCREEN_EV_ONLY) + { + sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_EVS; + return SUMMARY_SKILLS_MODE_EVS; + } + else + { + sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_IVS; + return SUMMARY_SKILLS_MODE_IVS; + } + + case SUMMARY_SKILLS_MODE_IVS: + if (P_SUMMARY_SCREEN_IV_ONLY) + { + sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_STATS; + return SUMMARY_SKILLS_MODE_STATS; + } + else + { + sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_EVS; + return SUMMARY_SKILLS_MODE_EVS; + } + case SUMMARY_SKILLS_MODE_EVS: + default: + sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_STATS; + return SUMMARY_SKILLS_MODE_STATS; + } + +} + +static void ShowMonSkillsInfo(u8 taskId, s16 mode) +{ + struct PokeSummary *sum = &sMonSummaryScreen->summary; + struct Pokemon *mon = &sMonSummaryScreen->currentMon; + + FillWindowPixelBuffer(sMonSummaryScreen->windowIds[PSS_DATA_WINDOW_SKILLS_STATS_LEFT], 0); + FillWindowPixelBuffer(sMonSummaryScreen->windowIds[PSS_DATA_WINDOW_SKILLS_STATS_RIGHT], 0); + + if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS) + { + ChangeStatLabel(mode); + ShowUtilityPrompt(mode); + } + + if (mode == SUMMARY_SKILLS_MODE_STATS) + { + ExtractMonSkillStatsData(mon, sum); + BufferLeftColumnStats(); + } + else if (mode == SUMMARY_SKILLS_MODE_IVS) + { + ExtractMonSkillIvData(mon, sum); + BufferLeftColumnIvEvStats(); + } + else if (mode == SUMMARY_SKILLS_MODE_EVS) + { + ExtractMonSkillEvData(mon, sum); + BufferLeftColumnIvEvStats(); + } + + PrintLeftColumnStats(); + BufferRightColumnStats(); + PrintRightColumnStats(); + gTasks[taskId].func = Task_HandleInput; +} + +void ExtractMonSkillStatsData(struct Pokemon *mon, struct PokeSummary *sum) +{ + if (sMonSummaryScreen->monList.mons == gPlayerParty || sMonSummaryScreen->mode == SUMMARY_MODE_BOX || sMonSummaryScreen->handleDeoxys == TRUE) + { + sum->nature = GetNature(mon); + sum->mintNature = GetMonData(mon, MON_DATA_HIDDEN_NATURE); + sum->currentHP = GetMonData(mon, MON_DATA_HP); + sum->maxHP = GetMonData(mon, MON_DATA_MAX_HP); + sum->atk = GetMonData(mon, MON_DATA_ATK); + sum->def = GetMonData(mon, MON_DATA_DEF); + sum->spatk = GetMonData(mon, MON_DATA_SPATK); + sum->spdef = GetMonData(mon, MON_DATA_SPDEF); + sum->speed = GetMonData(mon, MON_DATA_SPEED); + } + else + { + sum->nature = GetNature(mon); + sum->mintNature = GetMonData(mon, MON_DATA_HIDDEN_NATURE); + sum->currentHP = GetMonData(mon, MON_DATA_HP); + sum->maxHP = GetMonData(mon, MON_DATA_MAX_HP); + sum->atk = GetMonData(mon, MON_DATA_ATK2); + sum->def = GetMonData(mon, MON_DATA_DEF2); + sum->spatk = GetMonData(mon, MON_DATA_SPATK2); + sum->spdef = GetMonData(mon, MON_DATA_SPDEF2); + sum->speed = GetMonData(mon, MON_DATA_SPEED2); + } +} + +void ExtractMonSkillIvData(struct Pokemon *mon, struct PokeSummary *sum) +{ + sum->currentHP = GetMonData(mon, MON_DATA_HP_IV); + sum->atk = GetMonData(mon, MON_DATA_ATK_IV); + sum->def = GetMonData(mon, MON_DATA_DEF_IV); + sum->spatk = GetMonData(mon, MON_DATA_SPATK_IV); + sum->spdef = GetMonData(mon, MON_DATA_SPDEF_IV); + sum->speed = GetMonData(mon, MON_DATA_SPEED_IV); +} + +void ExtractMonSkillEvData(struct Pokemon *mon, struct PokeSummary *sum) +{ + sum->currentHP = GetMonData(mon, MON_DATA_HP_EV); + sum->atk = GetMonData(mon, MON_DATA_ATK_EV); + sum->def = GetMonData(mon, MON_DATA_DEF_EV); + sum->spatk = GetMonData(mon, MON_DATA_SPATK_EV); + sum->spdef = GetMonData(mon, MON_DATA_SPDEF_EV); + sum->speed = GetMonData(mon, MON_DATA_SPEED_EV); +} + static void ChangeSummaryPokemon(u8 taskId, s8 delta) { s8 monId; @@ -1781,6 +1953,13 @@ static void Task_ChangeSummaryMon(u8 taskId) sMonSummaryScreen->switchCounter = 0; break; case 4: + if (P_SUMMARY_SCREEN_RENAME && sMonSummaryScreen->currPageIndex == PSS_PAGE_INFO) + ShowUtilityPrompt(SUMMARY_MODE_NORMAL); + if (ShouldShowIvEvPrompt() && sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS) + { + sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_STATS; + ChangeStatLabel(SUMMARY_SKILLS_MODE_STATS); + } if (ExtractMonDataToSummaryStruct(&sMonSummaryScreen->currentMon) == FALSE) { return; @@ -1826,12 +2005,6 @@ static void Task_ChangeSummaryMon(u8 taskId) case 11: PrintPageSpecificText(sMonSummaryScreen->currPageIndex); LimitEggSummaryPageDisplay(); - if (P_SUMMARY_SCREEN_RENAME && sMonSummaryScreen->currPageIndex == PSS_PAGE_INFO) - { - FillWindowPixelBuffer(PSS_LABEL_WINDOW_PROMPT_CANCEL, PIXEL_FILL(0)); - ShowCancelOrRenamePrompt(); - PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_CANCEL); - } break; case 12: gSprites[sMonSummaryScreen->spriteIds[SPRITE_ARR_ID_MON]].data[2] = 0; @@ -1934,6 +2107,24 @@ static void ChangePage(u8 taskId, s8 delta) SetTaskFuncWithFollowupFunc(taskId, PssScrollLeft, gTasks[taskId].func); CreateTextPrinterTask(sMonSummaryScreen->currPageIndex); HidePageSpecificSprites(); + + if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS + || (sMonSummaryScreen->currPageIndex + delta) == PSS_PAGE_SKILLS) + { + struct Pokemon *mon = &sMonSummaryScreen->currentMon; + + if (sMonSummaryScreen->skillsPageMode != SUMMARY_SKILLS_MODE_STATS) + sMonSummaryScreen->skillsPageMode = SUMMARY_SKILLS_MODE_STATS; + + ShowUtilityPrompt(sMonSummaryScreen->skillsPageMode); + ExtractMonSkillStatsData(mon, summary); + BufferLeftColumnStats(); + BufferRightColumnStats(); + } + else + { + ShowUtilityPrompt(SUMMARY_MODE_NORMAL); + } } static void PssScrollRight(u8 taskId) // Scroll right @@ -1982,6 +2173,9 @@ static void PssScrollRightEnd(u8 taskId) // display right static void PssScrollLeft(u8 taskId) // Scroll left { s16 *data = gTasks[taskId].data; + // to fix a specific lag in writing to the stat label + if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS) + ChangeStatLabel(SUMMARY_SKILLS_MODE_STATS); if (data[0] == 0) { if (sMonSummaryScreen->bgDisplayOrder == 0) @@ -2045,13 +2239,19 @@ static void SwitchToMoveSelection(u8 taskId) ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATUS); HandlePowerAccTilemap(9, -3); HandleAppealJamTilemap(9, -3, move); + if (!sMonSummaryScreen->lockMovesFlag) { - ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO); if (ShouldShowMoveRelearner()) ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); - PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_SWITCH); + + ShowUtilityPrompt(SUMMARY_MODE_SELECT_MOVE); } + else + { + ShowUtilityPrompt(SUMMARY_MODE_NORMAL); + } + TilemapFiveMovesDisplay(sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_BATTLE_MOVES][0], 3, FALSE); TilemapFiveMovesDisplay(sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_CONTEST_MOVES][0], 1, FALSE); PrintMoveDetails(move); @@ -2083,14 +2283,16 @@ static void Task_HandleInput_MoveSelect(u8 taskId) else if (JOY_NEW(A_BUTTON)) { if (sMonSummaryScreen->lockMovesFlag == TRUE - || (sMonSummaryScreen->newMove == MOVE_NONE && sMonSummaryScreen->firstMoveIndex == MAX_MON_MOVES)) + || (sMonSummaryScreen->newMove == MOVE_NONE && sMonSummaryScreen->firstMoveIndex == MAX_MON_MOVES)) { PlaySE(SE_SELECT); + ShowUtilityPrompt(SUMMARY_MODE_NORMAL); CloseMoveSelectMode(taskId); } else if (HasMoreThanOneMove() == TRUE) { PlaySE(SE_SELECT); + ShowUtilityPrompt(SUMMARY_MODE_SELECT_MOVE); SwitchToMovePositionSwitchMode(taskId); } else @@ -2178,10 +2380,10 @@ static void ChangeSelectedMove(s16 *taskData, s8 direction, u8 *moveIndexPtr) static void CloseMoveSelectMode(u8 taskId) { DestroyMoveSelectorSprites(SPRITE_ARR_ID_MOVE_SELECTOR1); - ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_SWITCH); - PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO); if (ShouldShowMoveRelearner()) PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); + + ShowUtilityPrompt(SUMMARY_MODE_NORMAL); PrintMoveDetails(0); TilemapFiveMovesDisplay(sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_BATTLE_MOVES][0], 3, TRUE); TilemapFiveMovesDisplay(sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_CONTEST_MOVES][0], 1, TRUE); @@ -2999,8 +3201,6 @@ static void PrintAOrBButtonIcon(u8 windowId, bool8 bButton, u32 x) static void PrintPageNamesAndStats(void) { - int stringXPos; - int iconXPos; int statsXPos; PrintTextOnWindow(PSS_LABEL_WINDOW_POKEMON_INFO_TITLE, gText_PkmnInfo, 2, 1, 0, 1); @@ -3008,21 +3208,7 @@ static void PrintPageNamesAndStats(void) PrintTextOnWindow(PSS_LABEL_WINDOW_BATTLE_MOVES_TITLE, gText_BattleMoves, 2, 1, 0, 1); PrintTextOnWindow(PSS_LABEL_WINDOW_CONTEST_MOVES_TITLE, gText_ContestMoves, 2, 1, 0, 1); - ShowCancelOrRenamePrompt(); - - stringXPos = GetStringRightAlignXOffset(FONT_NORMAL, gText_Info, 62); - iconXPos = stringXPos - 16; - if (iconXPos < 0) - iconXPos = 0; - PrintAOrBButtonIcon(PSS_LABEL_WINDOW_PROMPT_INFO, FALSE, iconXPos); - PrintTextOnWindow(PSS_LABEL_WINDOW_PROMPT_INFO, gText_Info, stringXPos, 1, 0, 0); - - stringXPos = GetStringRightAlignXOffset(FONT_NORMAL, gText_Switch, 62); - iconXPos = stringXPos - 16; - if (iconXPos < 0) - iconXPos = 0; - PrintAOrBButtonIcon(PSS_LABEL_WINDOW_PROMPT_SWITCH, FALSE, iconXPos); - PrintTextOnWindow(PSS_LABEL_WINDOW_PROMPT_SWITCH, gText_Switch, stringXPos, 1, 0, 0); + ShowUtilityPrompt(SUMMARY_MODE_NORMAL); PrintTextOnWindow(PSS_LABEL_WINDOW_POKEMON_INFO_RENTAL, gText_RentalPkmn, 0, 1, 0, 1); PrintTextOnWindow(PSS_LABEL_WINDOW_POKEMON_INFO_TYPE, gText_TypeSlash, 0, 1, 0, 0); @@ -3061,7 +3247,7 @@ static void PutPageWindowTilemaps(u8 page) { case PSS_PAGE_INFO: PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_TITLE); - PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_CANCEL); + PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY); if (InBattleFactory() == TRUE || InSlateportBattleTent() == TRUE) PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_RENTAL); PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_TYPE); @@ -3071,9 +3257,12 @@ static void PutPageWindowTilemaps(u8 page) PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATS_LEFT); PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATS_RIGHT); PutWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_EXP); + if (ShouldShowIvEvPrompt()) + PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY); break; case PSS_PAGE_BATTLE_MOVES: PutWindowTilemap(PSS_LABEL_WINDOW_BATTLE_MOVES_TITLE); + PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY); if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE) { if (sMonSummaryScreen->newMove != MOVE_NONE || sMonSummaryScreen->firstMoveIndex != MAX_MON_MOVES) @@ -3081,13 +3270,13 @@ static void PutPageWindowTilemaps(u8 page) } else { - PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO); if (ShouldShowMoveRelearner()) PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); } break; case PSS_PAGE_CONTEST_MOVES: PutWindowTilemap(PSS_LABEL_WINDOW_CONTEST_MOVES_TITLE); + PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY); if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE) { if (sMonSummaryScreen->newMove != MOVE_NONE || sMonSummaryScreen->firstMoveIndex != MAX_MON_MOVES) @@ -3095,7 +3284,6 @@ static void PutPageWindowTilemaps(u8 page) } else { - PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO); if (ShouldShowMoveRelearner()) PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); } @@ -3115,7 +3303,7 @@ static void ClearPageWindowTilemaps(u8 page) switch (page) { case PSS_PAGE_INFO: - ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_CANCEL); + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY); if (InBattleFactory() == TRUE || InSlateportBattleTent() == TRUE) ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_RENTAL); ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_INFO_TYPE); @@ -3124,6 +3312,8 @@ static void ClearPageWindowTilemaps(u8 page) ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATS_LEFT); ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_STATS_RIGHT); ClearWindowTilemap(PSS_LABEL_WINDOW_POKEMON_SKILLS_EXP); + if (ShouldShowIvEvPrompt()) + ClearPageWindowTilemaps(PSS_LABEL_WINDOW_PROMPT_UTILITY); break; case PSS_PAGE_BATTLE_MOVES: if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE) @@ -3136,7 +3326,6 @@ static void ClearPageWindowTilemaps(u8 page) } else { - ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO); if (ShouldShowMoveRelearner()) ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); } @@ -3149,7 +3338,6 @@ static void ClearPageWindowTilemaps(u8 page) } else { - ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_INFO); if (ShouldShowMoveRelearner()) ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); } @@ -3477,6 +3665,8 @@ static void PrintSkillsPageText(void) { PrintHeldItemName(); PrintRibbonCount(); + if(ShouldShowIvEvPrompt()) + ShowUtilityPrompt(SUMMARY_SKILLS_MODE_STATS); BufferLeftColumnStats(); PrintLeftColumnStats(); BufferRightColumnStats(); @@ -3497,21 +3687,24 @@ static void Task_PrintSkillsPage(u8 taskId) PrintRibbonCount(); break; case 3: - BufferLeftColumnStats(); + ChangeStatLabel(SUMMARY_SKILLS_MODE_STATS); break; case 4: - PrintLeftColumnStats(); + BufferLeftColumnStats(); break; case 5: - BufferRightColumnStats(); + PrintLeftColumnStats(); break; case 6: - PrintRightColumnStats(); + BufferRightColumnStats(); break; case 7: - PrintExpPointsNextLevel(); + PrintRightColumnStats(); break; case 8: + PrintExpPointsNextLevel(); + break; + case 9: DestroyTask(taskId); return; } @@ -3581,10 +3774,38 @@ static void BufferStat(u8 *dst, u8 statIndex, u32 stat, u32 strId, u32 n) else txtPtr = StringCopy(dst, sTextNatureNeutral); - ConvertIntToDecimalStringN(txtPtr, stat, STR_CONV_MODE_RIGHT_ALIGN, n); + if (!P_SUMMARY_SCREEN_IV_EV_VALUES + && sMonSummaryScreen->skillsPageMode == SUMMARY_SKILLS_MODE_IVS) + StringAppend(dst, GetLetterGrade(stat)); + else + ConvertIntToDecimalStringN(txtPtr, stat, STR_CONV_MODE_RIGHT_ALIGN, n); + DynamicPlaceholderTextUtil_SetPlaceholderPtr(strId, dst); } +static const u8 *GetLetterGrade(u32 stat) +{ + static const u8 gText_GradeF[] = _("F"); + static const u8 gText_GradeD[] = _("D"); + static const u8 gText_GradeC[] = _("C"); + static const u8 gText_GradeB[] = _("B"); + static const u8 gText_GradeA[] = _("A"); + static const u8 gText_GradeS[] = _("S"); + + if (stat > 0 && stat <= 15) + return gText_GradeD; + else if (stat > 15 && stat <= 25) + return gText_GradeC; + else if (stat > 26 && stat <= 29) + return gText_GradeB; + else if (stat == 30) + return gText_GradeA; + else if (stat == 31) + return gText_GradeS; + else + return gText_GradeF; +} + static void BufferLeftColumnStats(void) { u8 *currentHPString = Alloc(20); @@ -3593,10 +3814,12 @@ static void BufferLeftColumnStats(void) u8 *defenseString = Alloc(20); DynamicPlaceholderTextUtil_Reset(); - BufferStat(currentHPString, 0, sMonSummaryScreen->summary.currentHP, 0, 3); - BufferStat(maxHPString, 0, sMonSummaryScreen->summary.maxHP, 1, 3); + + BufferStat(currentHPString, STAT_HP, sMonSummaryScreen->summary.currentHP, 0, 3); + BufferStat(maxHPString, STAT_HP, sMonSummaryScreen->summary.maxHP, 1, 3); BufferStat(attackString, STAT_ATK, sMonSummaryScreen->summary.atk, 2, 7); BufferStat(defenseString, STAT_DEF, sMonSummaryScreen->summary.def, 3, 7); + DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsLeftColumnLayout); Free(currentHPString); @@ -3605,23 +3828,58 @@ static void BufferLeftColumnStats(void) Free(defenseString); } +static void BufferLeftColumnIvEvStats(void) +{ + u8 *hpIvEvString = Alloc(20); + u8 *attackIvEvString = Alloc(20); + u8 *defenseIvEvString = Alloc(20); + + DynamicPlaceholderTextUtil_Reset(); + + BufferStat(hpIvEvString, STAT_HP, sMonSummaryScreen->summary.currentHP, 0, 7); + BufferStat(attackIvEvString, STAT_ATK, sMonSummaryScreen->summary.atk, 1, 7); + BufferStat(defenseIvEvString, STAT_DEF, sMonSummaryScreen->summary.def, 2, 7); + + DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsLeftIVEVColumnLayout); + + Free(hpIvEvString); + Free(attackIvEvString); + Free(defenseIvEvString); +} + static void PrintLeftColumnStats(void) { - PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_STATS_LEFT), gStringVar4, 4, 1, 0, 0); + int x; + + if (sMonSummaryScreen->skillsPageMode == SUMMARY_SKILLS_MODE_IVS && !P_SUMMARY_SCREEN_IV_EV_VALUES) + x = GetStringRightAlignXOffset(FONT_NORMAL, gStringVar4, 46); + else + x = 4; + + PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_STATS_LEFT), gStringVar4, x, 1, 0, 0); } static void BufferRightColumnStats(void) { DynamicPlaceholderTextUtil_Reset(); + BufferStat(gStringVar1, STAT_SPATK, sMonSummaryScreen->summary.spatk, 0, 3); BufferStat(gStringVar2, STAT_SPDEF, sMonSummaryScreen->summary.spdef, 1, 3); BufferStat(gStringVar3, STAT_SPEED, sMonSummaryScreen->summary.speed, 2, 3); + DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsRightColumnLayout); } static void PrintRightColumnStats(void) { - PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_STATS_RIGHT), gStringVar4, 2, 1, 0, 0); + int x; + + if (sMonSummaryScreen->skillsPageMode == SUMMARY_SKILLS_MODE_IVS && !P_SUMMARY_SCREEN_IV_EV_VALUES) + x = GetStringRightAlignXOffset(FONT_NORMAL, gStringVar4, 20); + else + x = 2; + + PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_STATS_RIGHT), gStringVar4, x, 1, 0, 0); } static void PrintExpPointsNextLevel(void) @@ -3651,7 +3909,6 @@ static void PrintBattleMoves(void) PrintMoveNameAndPP(1); PrintMoveNameAndPP(2); PrintMoveNameAndPP(3); - if (sMonSummaryScreen->mode == SUMMARY_MODE_SELECT_MOVE) { PrintNewMoveDetailsOrCancelText(); @@ -4385,6 +4642,7 @@ static inline bool32 ShouldShowMoveRelearner(void) { return (P_SUMMARY_SCREEN_MOVE_RELEARNER && !sMonSummaryScreen->lockMovesFlag + && !sMonSummaryScreen->isBoxMon && sMonSummaryScreen->mode != SUMMARY_MODE_BOX && sMonSummaryScreen->mode != SUMMARY_MODE_BOX_CURSOR && sMonSummaryScreen->relearnableMovesNum > 0 @@ -4397,6 +4655,7 @@ static inline bool32 ShouldShowRename(void) return (P_SUMMARY_SCREEN_RENAME && !sMonSummaryScreen->lockMovesFlag && !sMonSummaryScreen->summary.isEgg + && !sMonSummaryScreen->isBoxMon && sMonSummaryScreen->mode != SUMMARY_MODE_BOX && sMonSummaryScreen->mode != SUMMARY_MODE_BOX_CURSOR && !InBattleFactory() @@ -4404,17 +4663,84 @@ static inline bool32 ShouldShowRename(void) && GetPlayerIDAsU32() == sMonSummaryScreen->summary.OTID); } -static void ShowCancelOrRenamePrompt(void) +static inline bool32 ShouldShowIvEvPrompt(void) { - const u8 *promptText = ShouldShowRename() ? gText_Rename : gText_Cancel2; + if (P_SUMMARY_SCREEN_IV_EV_BOX_ONLY) + { + return (P_SUMMARY_SCREEN_IV_EV_INFO || FlagGet(P_FLAG_SUMMARY_SCREEN_IV_EV_INFO)) + && (sMonSummaryScreen->mode == SUMMARY_MODE_BOX|| sMonSummaryScreen->mode == SUMMARY_MODE_BOX_CURSOR); + } + else if (!P_SUMMARY_SCREEN_IV_EV_BOX_ONLY) + { + return (P_SUMMARY_SCREEN_IV_EV_INFO || FlagGet(P_FLAG_SUMMARY_SCREEN_IV_EV_INFO)); + } + return FALSE; +} + +static inline void ShowUtilityPrompt(s16 mode) +{ + const u8* promptText = NULL; + const u8* gText_SkillPageIvs = COMPOUND_STRING("IVs"); + const u8* gText_SkillPageEvs = COMPOUND_STRING("EVs"); + const u8* gText_SkillPageStats = COMPOUND_STRING("STATS"); + + if (sMonSummaryScreen->currPageIndex == PSS_PAGE_INFO) + { + if (ShouldShowRename()) + promptText = gText_Rename; + else + promptText = gText_Cancel2; + } + else if (sMonSummaryScreen->currPageIndex == PSS_PAGE_SKILLS) + { + if (ShouldShowIvEvPrompt()) + { + if (mode == SUMMARY_SKILLS_MODE_STATS) + { + if (P_SUMMARY_SCREEN_EV_ONLY) + promptText = gText_SkillPageEvs; + else + promptText = gText_SkillPageIvs; + } + else if (mode == SUMMARY_SKILLS_MODE_IVS) + { + if (P_SUMMARY_SCREEN_IV_ONLY) + promptText = gText_SkillPageStats; + else + promptText = gText_SkillPageEvs; + } + else if (mode == SUMMARY_SKILLS_MODE_EVS) + { + promptText = gText_SkillPageStats; + } + } + } + else if (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES + || sMonSummaryScreen->currPageIndex == PSS_PAGE_CONTEST_MOVES) + { + if (mode == SUMMARY_MODE_SELECT_MOVE && !sMonSummaryScreen->lockMovesFlag) + promptText = gText_Switch; + else + promptText = gText_Info; + } + + if (promptText == NULL) + { + ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY); + FillWindowPixelBuffer(PSS_LABEL_WINDOW_PROMPT_UTILITY, PIXEL_FILL(0)); + return; + } + + FillWindowPixelBuffer(PSS_LABEL_WINDOW_PROMPT_UTILITY, PIXEL_FILL(0)); + PutWindowTilemap(PSS_LABEL_WINDOW_PROMPT_UTILITY); int stringXPos = GetStringRightAlignXOffset(FONT_NORMAL, promptText, 62); int iconXPos = stringXPos - 16; if (iconXPos < 0) iconXPos = 0; - PrintAOrBButtonIcon(PSS_LABEL_WINDOW_PROMPT_CANCEL, FALSE, iconXPos); - PrintTextOnWindow(PSS_LABEL_WINDOW_PROMPT_CANCEL, promptText, stringXPos, 1, 0, 0); + PrintAOrBButtonIcon(PSS_LABEL_WINDOW_PROMPT_UTILITY, FALSE, iconXPos); + PrintTextOnWindow(PSS_LABEL_WINDOW_PROMPT_UTILITY, promptText, stringXPos, 1, 0, 0); } static void CB2_ReturnToSummaryScreenFromNamingScreen(void)