diff --git a/config.asm b/config.asm index 8786a96..6fcac81 100644 --- a/config.asm +++ b/config.asm @@ -90,6 +90,9 @@ ; Auto-change to lowercase after first letter in naming screen. .definelabel AUTOCASE, 1 +; Adds an item which allows you to see your Pokemon's base stats, IVs and EVs. +.definelabel STATS_VIEWER, 1 + ; Bugfixes ; -------- diff --git a/include/constants/items.h b/include/constants/items.h index cfa929d..9e5a64c 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -232,7 +232,7 @@ #define ITEM_GASEOUS_ZINC 223 #define ITEM_POKEGEAR 224 #define ITEM_PACHI_SWORD 225 -#define ITEM_0E2 226 +#define ITEM_STATS_VIEWER 226 #define ITEM_0E3 227 #define ITEM_0E4 228 #define ITEM_0E5 229 diff --git a/include/naming_screen.h b/include/naming_screen.h index 659d603..381dc6b 100644 --- a/include/naming_screen.h +++ b/include/naming_screen.h @@ -2,11 +2,11 @@ #include "main.h" -#define KBEVENT_NONE 0 -#define KBEVENT_PRESSED_A 5 -#define KBEVENT_PRESSED_B 6 +#define KBEVENT_NONE 0 +#define KBEVENT_PRESSED_A 5 +#define KBEVENT_PRESSED_B 6 #define KBEVENT_PRESSED_SELECT 8 -#define KBEVENT_PRESSED_START 9 +#define KBEVENT_PRESSED_START 9 enum { @@ -36,27 +36,27 @@ enum struct NamingScreen { - /*0x00*/ u8 state; - /*0x01*/ u8 templateNum; - /*0x02*/ u16 nameLeftOffset; - /*0x04*/ u16 bg1vOffset; - /*0x06*/ u16 bg2vOffset; - /*0x08*/ u16 bg1Priority; - /*0x0A*/ u16 bg2Priority; - /*0x0C*/ u8 bgToReveal; - /*0x0D*/ u8 bgToHide; - /*0x0E*/ u8 currentPage; - /*0x0F*/ u8 cursorSpriteId; - /*0x10*/ u8 pageIndicatorSpriteId; - /*0x11*/ u8 textBuffer[0x10]; - /*0x21*/ u8 filler21[0x13]; - /*0x34*/ const struct NamingScreenTemplate *template; - /*0x38*/ u8 *destBuffer; - /*0x3C*/ u16 keyRepeatStartDelayCopy; - /*0x3E*/ u16 speciesOrPlayerGender; - /*0x40*/ u16 monGender; - /*0x42*/ u32 monPersonality; - /*0x46*/ MainCallback returnCallback; + /*0x00*/ u8 state; + /*0x01*/ u8 templateNum; + /*0x02*/ u16 nameLeftOffset; + /*0x04*/ u16 bg1vOffset; + /*0x06*/ u16 bg2vOffset; + /*0x08*/ u16 bg1Priority; + /*0x0A*/ u16 bg2Priority; + /*0x0C*/ u8 bgToReveal; + /*0x0D*/ u8 bgToHide; + /*0x0E*/ u8 currentPage; + /*0x0F*/ u8 cursorSpriteId; + /*0x10*/ u8 pageIndicatorSpriteId; + /*0x11*/ u8 textBuffer[0x10]; + /*0x21*/ u8 filler21[0x13]; + /*0x34*/ const struct NamingScreenTemplate *template; + /*0x38*/ u8 *destBuffer; + /*0x3C*/ u16 keyRepeatStartDelayCopy; + /*0x3E*/ u16 speciesOrPlayerGender; + /*0x40*/ u16 monGender; + /*0x42*/ u32 monPersonality; + /*0x46*/ MainCallback returnCallback; }; void LONG_CALL TryStartButtonFlash(u8, u8, u8); diff --git a/include/stats_viewer.h b/include/stats_viewer.h new file mode 100644 index 0000000..3dd59c5 --- /dev/null +++ b/include/stats_viewer.h @@ -0,0 +1,4 @@ +#pragma once + +void GoToStatsViewerFromOverworld(void); +void GoToStatsViewerFromBag(void); \ No newline at end of file diff --git a/linker/text.ld b/linker/text.ld index 47f2242..216cb55 100644 --- a/linker/text.ld +++ b/linker/text.ld @@ -270,3 +270,4 @@ SquishCursor = 0x80b6914 | 1; SetInputState = 0x80b6210 | 1; MainState_StartPageSwap = 0x80b61c8 | 1; GetTextEntryPosition = 0x80b6f44 | 1; +sub_80F9368 = 0x80f9368 | 1; diff --git a/main.asm b/main.asm index 871476b..5a47243 100644 --- a/main.asm +++ b/main.asm @@ -74,6 +74,7 @@ .include "scripts/repel_prompt.asm" .include "scripts/reusable_tms.asm" .include "scripts/save_flash_failed.asm" +.include "scripts/stats_viewer.asm" .include "scripts/summary_screen.asm" .close \ No newline at end of file diff --git a/scripts/ability_changer.asm b/scripts/ability_changer.asm index 2abfc5b..8294953 100644 --- a/scripts/ability_changer.asm +++ b/scripts/ability_changer.asm @@ -1,8 +1,4 @@ .if ABILITY_CHANGER .org 0x88189F1 s_goto EventScript_AbilityChanger - -.org 0x8152F2E -s_callnative (DrawFrameTest | 1) -s_end .endif \ No newline at end of file diff --git a/scripts/include/items.asm b/scripts/include/items.asm index 057615d..3c4d6ff 100644 --- a/scripts/include/items.asm +++ b/scripts/include/items.asm @@ -231,7 +231,7 @@ ITEM_POKEPHONE equ 222 ITEM_GASEOUS_ZINC equ 223 ITEM_POKEGEAR equ 224 ITEM_PACHI_SWORD equ 225 -ITEM_0E2 equ 226 +ITEM_STATS_VIEWER equ 226 ITEM_0E3 equ 227 ITEM_0E4 equ 228 ITEM_0E5 equ 229 diff --git a/scripts/stats_viewer.asm b/scripts/stats_viewer.asm new file mode 100644 index 0000000..09971c7 --- /dev/null +++ b/scripts/stats_viewer.asm @@ -0,0 +1,25 @@ +.if STATS_VIEWER + +.org 0x83c5564 + (44 * ITEM_STATS_VIEWER) +.area 0xE, 0x0 +.string "STATS VIEWER" +.endarea + +.org 0x83c5564 + (44 * ITEM_STATS_VIEWER) + 28 +.word (ItemUseOutOfBattle_StatsViewer | 1) + +.org 0x83c5564 + (44 * ITEM_STATS_VIEWER) + 24 +.byte 0x1, 0x1 + +.org 0x83c5564 + (44 * ITEM_STATS_VIEWER) + 26 +.byte 0x5 + +.org 0x83c5564 + (44 * ITEM_STATS_VIEWER) + 20 +.word @StatsViewer_Desc + +.autoregion +@StatsViewer_Desc: +.string "A device which lets\nyou see your\nPOKeMON's stats." +.endautoregion + +.endif \ No newline at end of file diff --git a/src/item_use.c b/src/item_use.c index 24d4316..192fb2f 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1,6 +1,9 @@ #include "types.h" #include "item_use.h" +#include "palette.h" +#include "stats_viewer.h" #include "task.h" +#include "constants/gba.h" extern u8 gExpAllEnabled; @@ -12,4 +15,31 @@ void ItemUseOutOfBattle_ExpShare(u8 taskId) gExpAllEnabled = !gExpAllEnabled; DisplayItemUseMessage( taskId, gTasks[taskId].data[2], gExpAllEnabled ? sText_EnabledExpShare : sText_DisabledExpShare); +} + +#define tState data[0] +#define tSelectedItem data[2] + +#include "bios.h" +void Task_HandleStatsViewerPaletteFade(u8 taskId); + +void ItemUseOutOfBattle_StatsViewer(u8 taskId) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); + gTasks[taskId].func = Task_HandleStatsViewerPaletteFade; +} + +void Task_HandleStatsViewerPaletteFade(u8 taskId) +{ + if (gPaletteFade.active) return; + + s16 *data = gTasks[taskId].data; + + if (tSelectedItem) + GoToStatsViewerFromOverworld(); + else + GoToStatsViewerFromBag(); + + DmaFill16(3, 0x0, VRAM, VRAM_SIZE); + DestroyTask(taskId); } \ No newline at end of file diff --git a/src/naming_screen.c b/src/naming_screen.c index 7adef05..622d0ae 100644 --- a/src/naming_screen.c +++ b/src/naming_screen.c @@ -10,7 +10,7 @@ u8 KeyboardKeyHandler_Character(u8 event) { u8 textFull = AddTextCharacter(); - if (gNamingScreenPtr ->currentPage == PAGE_UPPER && GetTextEntryPosition() == 1) + if (gNamingScreenPtr->currentPage == PAGE_UPPER && GetTextEntryPosition() == 1) MainState_StartPageSwap(); SquishCursor(); diff --git a/src/stats_viewer.c b/src/stats_viewer.c index 4056cd1..2f31199 100644 --- a/src/stats_viewer.c +++ b/src/stats_viewer.c @@ -7,6 +7,7 @@ #include "palette.h" #include "pokemon.h" #include "pokemon_pic.h" +#include "stats_viewer.h" #include "scanline_effect.h" #include "script.h" #include "sound.h" @@ -27,20 +28,21 @@ const u8 sText_SpDef[] = _("Sp. Def"); extern const u8 OtherText_MaleSymbol[]; extern const u8 OtherText_FemaleSymbol[]; -static EWRAM_DATA struct StatViewer +static EWRAM_DATA struct StatsViewer { u8 monSpriteId; u8 selectedMon; -} sStatViewer = { MAX_SPRITES, 0 }; + MainCallback exitCallback; +} sStatsViewer = { MAX_SPRITES, 0, NULL }; -static bool8 SetupStatViewer(void); +static bool8 SetupStatsViewer(void); static void CB2_StatsViewer(void); static void CB2_StatsViewerRun(void); static void VBlank_StatsViewerRun(void); -static void Task_StatViewer_UpdateScreen(u8 taskId); -static void Task_StatViewer_HandleInput(u8 taskId); -static void Task_StatViewer_ChangePokemon(u8 taskId); -static void StatViewer_PrintStatLabels(void); +static void Task_StatsViewer_UpdateScreen(u8 taskId); +static void Task_StatsViewer_HandleInput(u8 taskId); +static void Task_StatsViewer_ChangePokemon(u8 taskId); +static void StatsViewer_PrintStatLabels(void); extern const u8 gOtherText_TwoDashes[]; @@ -53,7 +55,7 @@ static const u8 *sText_StatLabels[] = { sText_Speed, }; -static void StatViewer_PrintPokemonBaseStats(struct Pokemon *mon) +static void StatsViewer_PrintPokemonBaseStats(struct Pokemon *mon) { u16 species = GetMonData(mon, MON_DATA_SPECIES); @@ -92,7 +94,7 @@ static const u8 sText_BaseLabel[] = _("Base"); static const u8 sText_IVLabel[] = _("IVs"); static const u8 sText_EVLabel[] = _("EVs"); -static void StatViewer_PrintPokemonIV(struct Pokemon *mon) +static void StatsViewer_PrintPokemonIV(struct Pokemon *mon) { for (u8 i = 0; i < 6; ++i) { @@ -125,7 +127,7 @@ static void StatViewer_PrintPokemonIV(struct Pokemon *mon) } } -static void StatViewer_PrintPokemonEV(struct Pokemon *mon) +static void StatsViewer_PrintPokemonEV(struct Pokemon *mon) { for (u8 i = 0; i < 6; ++i) { @@ -158,7 +160,7 @@ static void StatViewer_PrintPokemonEV(struct Pokemon *mon) } } -static void StatViewer_PrintPokemonEmpty(u8 x) +static void StatsViewer_PrintPokemonEmpty(u8 x) { for (u8 i = 0; i < 6; ++i) { @@ -166,10 +168,10 @@ static void StatViewer_PrintPokemonEmpty(u8 x) } } -static void StatViewer_PrintPokemonCount(void) +static void StatsViewer_PrintPokemonCount(void) { u8 *ptr = gStringVar4; - ptr = ConvertIntToDecimalString(ptr, sStatViewer.selectedMon + 1); + ptr = ConvertIntToDecimalString(ptr, sStatsViewer.selectedMon + 1); *(ptr++) = CHAR_SPACE; *(ptr++) = CHAR_SLASH; *(ptr++) = CHAR_SPACE; @@ -177,10 +179,10 @@ static void StatViewer_PrintPokemonCount(void) MenuPrint_Centered(gStringVar4, 4, 17, StringLength(gStringVar4)); } -static void StatViewer_PrintPokemonInfo(void) +static void StatsViewer_PrintPokemonInfo(void) { u8 *ptr; - struct Pokemon *mon = &gPlayerParty[sStatViewer.selectedMon]; + struct Pokemon *mon = &gPlayerParty[sStatsViewer.selectedMon]; u16 length = GetMonData(mon, MON_DATA_NICKNAME, gStringVar4); ptr = gStringVar4 + length; @@ -233,41 +235,52 @@ static void StatViewer_PrintPokemonInfo(void) Menu_PrintText(gStringVar4, 3, 5); - StatViewer_PrintPokemonBaseStats(mon); - StatViewer_PrintPokemonIV(mon); - StatViewer_PrintPokemonEV(mon); + StatsViewer_PrintPokemonBaseStats(mon); + StatsViewer_PrintPokemonIV(mon); + StatsViewer_PrintPokemonEV(mon); } else { Menu_BlankWindowRect(1, 3, 6, 6); - StatViewer_PrintPokemonEmpty(20); - StatViewer_PrintPokemonEmpty(24); - StatViewer_PrintPokemonEmpty(28); + StatsViewer_PrintPokemonEmpty(20); + StatsViewer_PrintPokemonEmpty(24); + StatsViewer_PrintPokemonEmpty(28); } } -void DrawFrameTest(void) +void GoToStatsViewer(MainCallback exitCallback) { + sStatsViewer.exitCallback = exitCallback; SetMainCallback2(CB2_StatsViewer); } -static void StatViewer_DrawMonSprite(void) +void GoToStatsViewerFromOverworld(void) { - struct Pokemon *mon = &gPlayerParty[sStatViewer.selectedMon]; + GoToStatsViewer(CB2_ReturnToField); +} + +void GoToStatsViewerFromBag(void) +{ + GoToStatsViewer((MainCallback)(0x80A53F8 | 1)); +} + +static void StatsViewer_DrawMonSprite(void) +{ + struct Pokemon *mon = &gPlayerParty[sStatsViewer.selectedMon]; u16 species = GetMonData(mon, MON_DATA_SPECIES); - sStatViewer.monSpriteId = CreateMonSprite_PicBox(species, 38, 96, 0); + sStatsViewer.monSpriteId = CreateMonSprite_PicBox(species, 38, 96, 0); - if (sStatViewer.monSpriteId != MAX_SPRITES) + if (sStatsViewer.monSpriteId != MAX_SPRITES) { - gSprites[sStatViewer.monSpriteId].callback = SpriteCallbackDummy; - gSprites[sStatViewer.monSpriteId].oam.priority = 0; + gSprites[sStatsViewer.monSpriteId].callback = SpriteCallbackDummy; + gSprites[sStatsViewer.monSpriteId].oam.priority = 0; u8 markings = GetMonData(mon, MON_DATA_MARKINGS); - StartSpriteAnim(&gSprites[sStatViewer.monSpriteId], markings); + StartSpriteAnim(&gSprites[sStatsViewer.monSpriteId], markings); } } -static void StatViewer_BlankStats(void) +static void StatsViewer_BlankStats(void) { Menu_BlankWindowRect(16, 4, 29, 14); } @@ -275,36 +288,36 @@ static void StatViewer_BlankStats(void) #define tState data[0] #define tDelay data[1] -static void StatViewer_ChangePokemon(u8 taskId) +static void StatsViewer_ChangePokemon(u8 taskId) { gTasks[taskId].tState = 0; gTasks[taskId].tDelay = 3; - gTasks[taskId].func = Task_StatViewer_ChangePokemon; + gTasks[taskId].func = Task_StatsViewer_ChangePokemon; } -static void Task_StatViewer_ChangePokemon(u8 taskId) +static void Task_StatsViewer_ChangePokemon(u8 taskId) { s16 *data = gTasks[taskId].data; switch (tState) { case 0: - if (sStatViewer.monSpriteId != MAX_SPRITES) - FreeResourcesAndDestroySprite(&gSprites[sStatViewer.monSpriteId]); + if (sStatsViewer.monSpriteId != MAX_SPRITES) + FreeResourcesAndDestroySprite(&gSprites[sStatsViewer.monSpriteId]); tState++; break; case 1: - StatViewer_DrawMonSprite(); + StatsViewer_DrawMonSprite(); tState++; break; case 2: - StatViewer_BlankStats(); + StatsViewer_BlankStats(); tState++; break; case 3: - StatViewer_PrintStatLabels(); - StatViewer_PrintPokemonCount(); - StatViewer_PrintPokemonInfo(); + StatsViewer_PrintStatLabels(); + StatsViewer_PrintPokemonCount(); + StatsViewer_PrintPokemonInfo(); tState++; break; case 4: @@ -313,12 +326,12 @@ static void Task_StatViewer_ChangePokemon(u8 taskId) tState++; break; default: - gTasks[taskId].func = Task_StatViewer_HandleInput; + gTasks[taskId].func = Task_StatsViewer_HandleInput; break; } } -static void Task_StatViewer_Close(u8 taskId) +static void Task_StatsViewer_Close(u8 taskId) { s16 *data = gTasks[taskId].data; @@ -333,55 +346,55 @@ static void Task_StatViewer_Close(u8 taskId) tState++; break; case 2: - FreeResourcesAndDestroySprite(&gSprites[sStatViewer.monSpriteId]); + FreeResourcesAndDestroySprite(&gSprites[sStatsViewer.monSpriteId]); tState++; break; default: - SetMainCallback2(CB2_ReturnToField); + if (sStatsViewer.exitCallback) SetMainCallback2(sStatsViewer.exitCallback); DestroyTask(taskId); break; } } -static void Task_StatViewer_HandleInput(u8 taskId) +static void Task_StatsViewer_HandleInput(u8 taskId) { if (gPaletteFade.active) return; if (gMain.newKeys & DPAD_DOWN) { - sStatViewer.selectedMon = - (sStatViewer.selectedMon + 1) > (gPlayerPartyCount - 1) ? 0 : sStatViewer.selectedMon + 1; - StatViewer_ChangePokemon(taskId); + sStatsViewer.selectedMon = + (sStatsViewer.selectedMon + 1) > (gPlayerPartyCount - 1) ? 0 : sStatsViewer.selectedMon + 1; + StatsViewer_ChangePokemon(taskId); PlaySE(SE_SELECT); } else if (gMain.newKeys & DPAD_UP) { - sStatViewer.selectedMon = - (sStatViewer.selectedMon - 1) < 0 ? (gPlayerPartyCount - 1) : sStatViewer.selectedMon - 1; - StatViewer_ChangePokemon(taskId); + sStatsViewer.selectedMon = + (sStatsViewer.selectedMon - 1) < 0 ? (gPlayerPartyCount - 1) : sStatsViewer.selectedMon - 1; + StatsViewer_ChangePokemon(taskId); PlaySE(SE_SELECT); } else if (gMain.newKeys & B_BUTTON) { PlaySE(SE_SELECT); gTasks[taskId].tState = 0; - gTasks[taskId].func = Task_StatViewer_Close; + gTasks[taskId].func = Task_StatsViewer_Close; } } #undef tState #undef tDelay -static void StatViewer_PrintStatTypeLabels(void) +static void StatsViewer_PrintStatTypeLabels(void) { MenuPrint_RightAligned(sText_BaseLabel, 20, 2); MenuPrint_RightAligned(sText_IVLabel, 24, 2); MenuPrint_RightAligned(sText_EVLabel, 28, 2); } -static void StatViewer_PrintStatLabels(void) +static void StatsViewer_PrintStatLabels(void) { - struct Pokemon *mon = &gPlayerParty[sStatViewer.selectedMon]; + struct Pokemon *mon = &gPlayerParty[sStatsViewer.selectedMon]; u8 nature = GetNature(mon); bool8 isEgg = GetMonData(mon, MON_DATA_IS_EGG); u8 *ptr; @@ -418,9 +431,9 @@ static void StatViewer_PrintStatLabels(void) } } -ALIGNED(4) static const u8 sStatViewer_Tiles[] = INCBIN_U8("assets/stats_viewer.4bpp.lz"); -ALIGNED(4) static const u8 sStatViewer_Tilemap[] = INCBIN_U8("assets/stats_viewer.bin.lz"); -ALIGNED(4) static const u8 sStatViewer_Pal[] = INCBIN_U8("assets/stats_viewer.gbapal.lz"); +ALIGNED(4) static const u8 sStatsViewer_Tiles[] = INCBIN_U8("assets/stats_viewer.4bpp.lz"); +ALIGNED(4) static const u8 sStatsViewer_Tilemap[] = INCBIN_U8("assets/stats_viewer.bin.lz"); +ALIGNED(4) static const u8 sStatsViewer_Pal[] = INCBIN_U8("assets/stats_viewer.gbapal.lz"); const struct WindowTemplate sWindowTemplate_StatsViewer = { 0, // BG number @@ -442,7 +455,9 @@ const struct WindowTemplate sWindowTemplate_StatsViewer = { BG_SCREEN_ADDR(31), // tilemap }; -static bool8 SetupStatViewer(void) +void LONG_CALL sub_80F9368(void); + +static bool8 SetupStatsViewer(void) { u8 spriteId; switch (gMain.state) @@ -450,6 +465,7 @@ static bool8 SetupStatViewer(void) case 0: SetVBlankHBlankCallbacksToNull(); ResetSpriteData(); + sub_80F9368(); ResetTasks(); gMain.state++; break; @@ -473,19 +489,19 @@ static bool8 SetupStatViewer(void) Text_LoadWindowTemplate(&sWindowTemplate_StatsViewer); InitMenuWindow(&sWindowTemplate_StatsViewer); // Menu_BlankWindowRect(0, 0, 29, 19); - LZDecompressVram(sStatViewer_Tiles, (void *)(BG_CHAR_ADDR(0))); - LZDecompressVram(sStatViewer_Tilemap, (void *)(BG_SCREEN_ADDR(8))); - LoadCompressedPalette(sStatViewer_Pal, 0x0, 32); + LZDecompressVram(sStatsViewer_Tiles, (void *)(BG_CHAR_ADDR(0))); + LZDecompressVram(sStatsViewer_Tilemap, (void *)(BG_SCREEN_ADDR(8))); + LoadCompressedPalette(sStatsViewer_Pal, 0x0, 32); REG_BG1CNT = BGCNT_PRIORITY(1) | BGCNT_TXT256x256 | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(8); gMain.state++; break; case 5: - StatViewer_DrawMonSprite(); - StatViewer_PrintStatTypeLabels(); - StatViewer_PrintStatLabels(); - StatViewer_PrintPokemonCount(); + StatsViewer_DrawMonSprite(); + StatsViewer_PrintStatTypeLabels(); + StatsViewer_PrintStatLabels(); + StatsViewer_PrintPokemonCount(); - StatViewer_PrintPokemonInfo(); + StatsViewer_PrintPokemonInfo(); gMain.state++; break; default: @@ -495,7 +511,7 @@ static bool8 SetupStatViewer(void) REG_BG1HOFS = 0; REG_BG1VOFS = 0; - CreateTask(Task_StatViewer_HandleInput, 0x0); + CreateTask(Task_StatsViewer_HandleInput, 0x0); SetVBlankCallback(VBlank_StatsViewerRun); SetMainCallback2(CB2_StatsViewerRun); return TRUE; @@ -506,7 +522,7 @@ static bool8 SetupStatViewer(void) static void CB2_StatsViewer(void) { - while (SetupStatViewer() != TRUE) + while (SetupStatsViewer() != TRUE) { } }