pokeemerald/src/use_pokeblock.c

1674 lines
46 KiB
C
Raw Normal View History

2017-12-04 23:09:44 +01:00
#include "global.h"
#include "main.h"
#include "dma3.h"
2017-12-04 23:09:44 +01:00
#include "pokeblock.h"
#include "malloc.h"
#include "decompress.h"
#include "graphics.h"
2017-12-09 21:23:40 +01:00
#include "palette.h"
#include "pokenav.h"
#include "menu_specialized.h"
2018-01-29 17:47:12 +01:00
#include "scanline_effect.h"
2017-12-09 21:23:40 +01:00
#include "text.h"
#include "bg.h"
#include "window.h"
#include "text_window.h"
2019-02-23 18:08:07 +01:00
#include "constants/rgb.h"
#include "sound.h"
#include "constants/songs.h"
#include "sprite.h"
#include "string_util.h"
#include "strings.h"
#include "menu.h"
#include "gpu_regs.h"
#include "graphics.h"
2019-04-04 23:53:06 +02:00
#include "pokemon_summary_screen.h"
#include "item_menu.h"
2017-12-04 23:09:44 +01:00
2020-08-10 19:48:16 +02:00
/*
2020-08-10 23:05:42 +02:00
This file handles the screen where the player chooses
which pokemon to give a pokeblock to. The subsequent scene
of feeding the pokeblock to the pokemon is handled by
2020-08-10 19:48:16 +02:00
pokeblock_feed.c, and the rest of the pokeblock menu (and
other pokeblock-related functions) are in pokeblock.c
*/
enum {
WIN_NAME,
WIN_NATURE,
WIN_TEXT,
WIN_COUNT
};
2020-08-10 23:05:42 +02:00
#define TAG_UP_DOWN 0
#define TAG_CONDITION 1
// At any one time, the currently selected mon and its two adjacent neighbors can be loaded
// IDs to refer to one of these 3 are called "load id" in this file
#define NUM_SELECTIONS_LOADED 3
2020-08-10 19:48:16 +02:00
struct UsePokeblockSession
2017-12-04 23:09:44 +01:00
{
2020-08-10 23:05:42 +02:00
void (*callback)(void);
void (*exitCallback)(void);
struct Pokeblock *pokeblock;
struct Pokemon *mon;
u8 stringBuffer[64];
u8 mainState;
u8 unused1;
2020-08-10 23:05:42 +02:00
u8 timer;
u8 statId;
u8 numEnhancements;
u8 unused2;
2020-08-10 23:05:42 +02:00
bool8 monInTopHalf;
u8 conditionsBeforeBlock[FLAVOR_COUNT];
u8 conditionsAfterBlock[FLAVOR_COUNT];
2020-08-10 23:05:42 +02:00
u8 enhancements[FLAVOR_COUNT];
s16 pokeblockStatBoosts[FLAVOR_COUNT];
u8 numSelections; // num in party + 1 (for Cancel)
u8 curSelection;
bool8 (*loadNewSelection)(void);
u8 helperState;
u8 unused3;
2020-08-10 23:05:42 +02:00
u8 natureText[34];
2017-12-04 23:09:44 +01:00
};
2020-08-10 19:48:16 +02:00
// This struct is identical to PokenavMonList, the struct used for managing lists of pokemon in the pokenav
// Given that this screen is essentially duplicated in the poknav, this struct was probably the same one with
// a more general name/purpose
// TODO: Once the pokenav conditions screens are documented, resolve the above
struct UsePokeblockMenuPokemon
2019-03-23 17:16:53 +01:00
{
2020-08-10 19:48:16 +02:00
u8 boxId; // Because this screen is never used for the PC this is always set to TOTAL_BOXES_COUNT to refer to party
u8 monId;
u16 data; // never read
2019-03-23 17:16:53 +01:00
};
2020-08-10 19:48:16 +02:00
struct UsePokeblockMenu
2017-12-04 23:09:44 +01:00
{
u32 unused;
u16 partyPalettes[PARTY_SIZE][0x40];
u8 partySheets[NUM_SELECTIONS_LOADED][0x2000];
u8 unusedBuffer[0x1000];
u8 tilemapBuffer[BG_SCREEN_SIZE + 2];
u8 selectionIconSpriteIds[PARTY_SIZE + 1];
s16 curMonXOffset;
u8 curMonSpriteId;
u16 curMonPalette;
u16 curMonSheet;
u8 *curMonTileStart;
struct Sprite *sparkles[MAX_CONDITION_SPARKLES];
struct Sprite *condition[2];
u8 toLoadSelection;
u8 locationStrings[NUM_SELECTIONS_LOADED][24]; // Gets an "in party" or "in box #" string that never gets printed
u8 monNameStrings[NUM_SELECTIONS_LOADED][64];
struct ConditionGraph graph;
u8 numSparkles[NUM_SELECTIONS_LOADED];
s8 curLoadId;
s8 nextLoadId;
s8 prevLoadId;
s8 toLoadId;
struct UsePokeblockMenuPokemon party[PARTY_SIZE];
struct UsePokeblockSession info;
2017-12-04 23:09:44 +01:00
};
2020-08-10 19:48:16 +02:00
static void SetUsePokeblockCallback(void (*func)(void));
static void LoadUsePokeblockMenu(void);
2020-08-10 23:05:42 +02:00
static void CB2_UsePokeblockMenu(void);
static void CB2_ReturnToUsePokeblockMenu(void);
2020-08-10 19:48:16 +02:00
static void ShowUsePokeblockMenu(void);
2020-08-10 23:05:42 +02:00
static void CB2_ShowUsePokeblockMenuForResults(void);
static void ShowUsePokeblockMenuForResults(void);
static void LoadPartyInfo(void);
static void LoadAndCreateSelectionIcons(void);
static u8 GetSelectionIdFromPartyId(u8);
2020-08-10 23:05:42 +02:00
static bool8 LoadConditionTitle(void);
static bool8 LoadUsePokeblockMenuGfx(void);
static void UpdateMonPic(u8);
2020-08-10 19:48:16 +02:00
static void UpdateMonInfoText(u16, bool8);
static void UsePokeblockMenu(void);
2020-08-10 23:05:42 +02:00
static void UpdateSelection(bool8);
2020-08-10 19:48:16 +02:00
static void CloseUsePokeblockMenu(void);
static void AskUsePokeblock(void);
static s8 HandleAskUsePokeblockInput(void);
static bool8 IsSheenMaxed(void);
static void PrintWontEatAnymore(void);
static void FeedPokeblockToMon(void);
static void EraseMenuWindow(void);
2020-08-10 23:05:42 +02:00
static u8 GetPartyIdFromSelectionId(u8);
static void ShowPokeblockResults(void);
static void CalculateConditionEnhancements(void);
static void LoadAndCreateUpDownSprites(void);
static void CalculateNumAdditionalSparkles(u8);
static void PrintFirstEnhancement(void);
static bool8 TryPrintNextEnhancement(void);
2020-08-10 19:48:16 +02:00
static void BufferEnhancedStatText(u8 *, u8, s16);
static void PrintMenuWindowText(const u8 *);
2020-08-10 23:05:42 +02:00
static void CalculatePokeblockEffectiveness(struct Pokeblock *, struct Pokemon *);
static void SpriteCB_UpDown(struct Sprite *);
static void LoadInitialMonInfo(void);
static void LoadMonInfo(s16, u8);
static bool8 LoadNewSelection_CancelToMon(void);
static bool8 LoadNewSelection_MonToCancel(void);
static bool8 LoadNewSelection_MonToMon(void);
static void SpriteCB_SelectionIconPokeball(struct Sprite *);
static void SpriteCB_SelectionIconCancel(struct Sprite *);
static void SpriteCB_MonPic(struct Sprite *);
static void SpriteCB_Condition(struct Sprite *);
2017-12-09 21:23:40 +01:00
2020-08-10 19:48:16 +02:00
extern const u16 gConditionGraphData_Pal[];
2020-08-10 23:05:42 +02:00
extern const u16 gConditionText_Pal[];
2020-08-10 19:48:16 +02:00
// The below 3 are saved for returning to the screen after feeding a pokeblock to a mon
// so that the rest of the data can be freed
static EWRAM_DATA struct UsePokeblockSession *sInfo = NULL;
static EWRAM_DATA void (*sExitCallback)(void) = NULL;
static EWRAM_DATA struct Pokeblock *sPokeblock = NULL;
EWRAM_DATA u8 gPokeblockMonId = 0;
EWRAM_DATA s16 gPokeblockGain = 0;
2020-08-10 19:48:16 +02:00
static EWRAM_DATA u8 *sGraph_Tilemap = NULL;
static EWRAM_DATA u8 *sGraph_Gfx = NULL;
static EWRAM_DATA u8 *sMonFrame_TilemapPtr = NULL;
static EWRAM_DATA struct UsePokeblockMenu *sMenu = NULL;
2017-12-10 19:02:51 +01:00
static const u32 sMonFrame_Pal[] = INCBIN_U32("graphics/pokeblock/use_screen/mon_frame_pal.bin");
2020-08-10 19:48:16 +02:00
static const u32 sMonFrame_Gfx[] = INCBIN_U32("graphics/pokeblock/use_screen/mon_frame.4bpp");
static const u32 sMonFrame_Tilemap[] = INCBIN_U32("graphics/pokeblock/use_screen/mon_frame.bin");
static const u32 sGraphData_Tilemap[] = INCBIN_U32("graphics/pokeblock/use_screen/graph_data.bin");
2019-07-31 02:21:17 +02:00
// The condition/flavors aren't listed in their normal order in this file, they're listed as shown on the graph going counter-clockwise
// Normally they would go Cool/Spicy, Beauty/Dry, Cute/Sweet, Smart/Bitter, Tough/Sour (also graph order, but clockwise)
2020-08-10 23:05:42 +02:00
static const u32 sMonDataConditions[FLAVOR_COUNT] =
2019-07-31 02:21:17 +02:00
{
2019-07-31 02:25:19 +02:00
MON_DATA_COOL,
MON_DATA_TOUGH,
MON_DATA_SMART,
MON_DATA_CUTE,
MON_DATA_BEAUTY
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const u8 sFlavors[FLAVOR_COUNT] =
2019-07-31 02:21:17 +02:00
{
2020-08-10 19:48:16 +02:00
FLAVOR_SPICY,
FLAVOR_SOUR,
FLAVOR_BITTER,
FLAVOR_SWEET,
FLAVOR_DRY
2019-07-31 02:21:17 +02:00
};
2019-12-10 19:48:20 +01:00
static const u8 sNatureTextColors[] =
2019-07-31 02:21:17 +02:00
{
2019-12-10 19:48:20 +01:00
TEXT_COLOR_TRANSPARENT,
TEXT_COLOR_BLUE,
TEXT_COLOR_WHITE
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const struct BgTemplate sBgTemplates[4] =
2019-07-31 02:21:17 +02:00
{
2019-07-31 02:25:19 +02:00
{
.bg = 0,
.charBaseIndex = 2,
.mapBaseIndex = 0x1F,
.screenSize = 0,
.paletteMode = 0,
.priority = 0,
.baseTile = 0
},
{
.bg = 1,
.charBaseIndex = 0,
.mapBaseIndex = 0x1E,
.screenSize = 0,
.paletteMode = 0,
.priority = 3,
.baseTile = 0
},
{
.bg = 3,
.charBaseIndex = 3,
.mapBaseIndex = 0x1D,
.screenSize = 0,
.paletteMode = 0,
.priority = 2,
.baseTile = 0x100
},
{
.bg = 2,
.charBaseIndex = 0,
.mapBaseIndex = 0x17,
.screenSize = 0,
.paletteMode = 0,
.priority = 1,
.baseTile = 0
}
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const struct WindowTemplate sWindowTemplates[WIN_COUNT + 1] =
2019-07-31 02:21:17 +02:00
{
2020-08-10 19:48:16 +02:00
[WIN_NAME] = {
2019-07-31 02:25:19 +02:00
.bg = 0,
2020-08-10 19:48:16 +02:00
.tilemapLeft = 13,
2019-07-31 02:25:19 +02:00
.tilemapTop = 1,
2020-08-10 19:48:16 +02:00
.width = 13,
2019-07-31 02:25:19 +02:00
.height = 4,
2020-08-10 19:48:16 +02:00
.paletteNum = 15,
2019-07-31 02:25:19 +02:00
.baseBlock = 1
},
2020-08-10 19:48:16 +02:00
[WIN_NATURE] = {
2019-07-31 02:25:19 +02:00
.bg = 0,
.tilemapLeft = 0,
2020-08-10 19:48:16 +02:00
.tilemapTop = 14,
.width = 11,
2019-07-31 02:25:19 +02:00
.height = 2,
2020-08-10 19:48:16 +02:00
.paletteNum = 15,
2019-07-31 02:25:19 +02:00
.baseBlock = 0x35
},
2020-08-10 19:48:16 +02:00
[WIN_TEXT] = {
2019-07-31 02:25:19 +02:00
.bg = 0,
.tilemapLeft = 1,
2020-08-10 19:48:16 +02:00
.tilemapTop = 17,
.width = 28,
2019-07-31 02:25:19 +02:00
.height = 2,
2020-08-10 19:48:16 +02:00
.paletteNum = 15,
2019-07-31 02:25:19 +02:00
.baseBlock = 0x4B
},
DUMMY_WIN_TEMPLATE
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const struct WindowTemplate sUsePokeblockYesNoWinTemplate =
2019-07-31 02:21:17 +02:00
{
2019-07-31 02:25:19 +02:00
.bg = 0,
2020-08-10 19:48:16 +02:00
.tilemapLeft = 24,
.tilemapTop = 11,
2019-07-31 02:25:19 +02:00
.width = 5,
.height = 4,
2020-08-10 19:48:16 +02:00
.paletteNum = 15,
2019-07-31 02:25:19 +02:00
.baseBlock = 0x83
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const u8 *const sContestStatNames[] =
2019-07-31 02:21:17 +02:00
{
2019-07-31 02:25:19 +02:00
gText_Coolness,
gText_Toughness,
gText_Smartness,
gText_Cuteness,
gText_Beauty3
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const struct SpriteSheet sSpriteSheet_UpDown =
2019-07-31 02:21:17 +02:00
{
2020-08-10 19:48:16 +02:00
gUsePokeblockUpDown_Gfx, 0x200, TAG_UP_DOWN
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const struct SpritePalette sSpritePalette_UpDown =
2019-07-31 02:21:17 +02:00
{
2020-08-10 19:48:16 +02:00
gUsePokeblockUpDown_Pal, TAG_UP_DOWN
2019-07-31 02:21:17 +02:00
};
2020-08-10 23:05:42 +02:00
static const s16 sUpDownCoordsOnGraph[FLAVOR_COUNT][2] =
2019-07-31 02:21:17 +02:00
{
2020-08-10 23:05:42 +02:00
{156, 36},
{117, 59},
{117, 118},
{197, 118},
{197, 59}
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const struct OamData sOam_UpDown =
2019-07-31 02:21:17 +02:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
.bpp = ST_OAM_4BPP,
2019-07-31 02:21:17 +02:00
.shape = SPRITE_SHAPE(32x16),
.x = 0,
.size = SPRITE_SIZE(32x16),
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
};
2020-08-10 19:48:16 +02:00
static const union AnimCmd sAnim_Up[] =
2019-07-31 02:21:17 +02:00
{
ANIMCMD_FRAME(0, 5),
ANIMCMD_END
};
2020-08-10 19:48:16 +02:00
static const union AnimCmd sAnim_Down[] =
2019-07-31 02:21:17 +02:00
{
ANIMCMD_FRAME(8, 5),
ANIMCMD_END
};
2020-08-10 19:48:16 +02:00
static const union AnimCmd *const sAnims_UpDown[] =
2019-07-31 02:21:17 +02:00
{
2020-08-10 19:48:16 +02:00
sAnim_Up,
sAnim_Down
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const struct SpriteTemplate sSpriteTemplate_UpDown =
2019-07-31 02:21:17 +02:00
{
2020-08-10 19:48:16 +02:00
.tileTag = TAG_UP_DOWN,
.paletteTag = TAG_UP_DOWN,
.oam = &sOam_UpDown,
.anims = sAnims_UpDown,
2019-07-31 02:21:17 +02:00
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
};
2020-08-10 19:48:16 +02:00
static const struct OamData sOam_Condition =
2019-07-31 02:21:17 +02:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
.bpp = ST_OAM_4BPP,
2019-07-31 02:21:17 +02:00
.shape = SPRITE_SHAPE(64x32),
.x = 0,
.size = SPRITE_SIZE(64x32),
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
};
static const union AnimCmd sAnim_Condition_0[] =
2019-07-31 02:21:17 +02:00
{
ANIMCMD_FRAME(0, 5),
ANIMCMD_END
};
static const union AnimCmd sAnim_Condition_1[] =
2019-07-31 02:21:17 +02:00
{
ANIMCMD_FRAME(32, 5),
ANIMCMD_END
};
static const union AnimCmd sAnim_Condition_2[] =
2019-07-31 02:21:17 +02:00
{
ANIMCMD_FRAME(64, 5),
ANIMCMD_END
};
2020-08-10 19:48:16 +02:00
static const union AnimCmd *const sAnims_Condition[] =
2019-07-31 02:21:17 +02:00
{
sAnim_Condition_0,
sAnim_Condition_1,
sAnim_Condition_2
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const struct SpriteTemplate sSpriteTemplate_Condition =
2019-07-31 02:21:17 +02:00
{
2020-08-10 19:48:16 +02:00
.tileTag = TAG_CONDITION,
.paletteTag = TAG_CONDITION,
.oam = &sOam_Condition,
.anims = sAnims_Condition,
2019-07-31 02:21:17 +02:00
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2020-08-10 23:05:42 +02:00
.callback = SpriteCB_Condition,
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
static const struct SpritePalette sSpritePalette_Condition =
2019-07-31 02:21:17 +02:00
{
2020-08-10 19:48:16 +02:00
gUsePokeblockCondition_Pal, TAG_CONDITION
2019-07-31 02:21:17 +02:00
};
2020-08-10 19:48:16 +02:00
// When first opening the selection screen
2017-12-09 21:23:40 +01:00
void ChooseMonToGivePokeblock(struct Pokeblock *pokeblock, void (*callback)(void))
2017-12-04 23:09:44 +01:00
{
2020-08-10 19:48:16 +02:00
sMenu = AllocZeroed(sizeof(*sMenu));
sInfo = &sMenu->info;
sInfo->pokeblock = pokeblock;
sInfo->exitCallback = callback;
SetUsePokeblockCallback(LoadUsePokeblockMenu);
2020-08-10 23:05:42 +02:00
SetMainCallback2(CB2_UsePokeblockMenu);
2017-12-04 23:09:44 +01:00
}
2017-12-09 21:23:40 +01:00
2020-08-10 19:48:16 +02:00
// When returning to the selection screen after feeding a pokeblock to a mon
static void CB2_ReturnAndChooseMonToGivePokeblock(void)
2017-12-09 21:23:40 +01:00
{
2020-08-10 19:48:16 +02:00
sMenu = AllocZeroed(sizeof(*sMenu));
sInfo = &sMenu->info;
sInfo->pokeblock = sPokeblock;
sInfo->exitCallback = sExitCallback;
gPokeblockMonId = GetSelectionIdFromPartyId(gPokeblockMonId);
2020-08-10 23:05:42 +02:00
sInfo->monInTopHalf = (gPokeblockMonId <= PARTY_SIZE / 2) ? FALSE : TRUE;
2020-08-10 19:48:16 +02:00
SetUsePokeblockCallback(LoadUsePokeblockMenu);
2020-08-10 23:05:42 +02:00
SetMainCallback2(CB2_ReturnToUsePokeblockMenu);
2017-12-09 21:23:40 +01:00
}
2020-08-10 23:05:42 +02:00
static void CB2_ReturnToUsePokeblockMenu(void)
2017-12-09 21:23:40 +01:00
{
2020-08-10 19:48:16 +02:00
sInfo->callback();
2017-12-09 21:23:40 +01:00
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
2020-08-10 19:48:16 +02:00
if (sInfo->callback == ShowUsePokeblockMenu)
2017-12-09 21:23:40 +01:00
{
2020-08-10 19:48:16 +02:00
sInfo->mainState = 0;
2020-08-10 23:05:42 +02:00
SetMainCallback2(CB2_ShowUsePokeblockMenuForResults);
2017-12-09 21:23:40 +01:00
}
}
2020-08-10 23:05:42 +02:00
static void CB2_ShowUsePokeblockMenuForResults(void)
2017-12-09 21:23:40 +01:00
{
2020-08-10 23:05:42 +02:00
ShowUsePokeblockMenuForResults();
2017-12-09 21:23:40 +01:00
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
}
2020-08-10 23:05:42 +02:00
static void CB2_UsePokeblockMenu(void)
2017-12-09 21:23:40 +01:00
{
2020-08-10 19:48:16 +02:00
sInfo->callback();
2017-12-09 21:23:40 +01:00
AnimateSprites();
BuildOamBuffer();
RunTextPrinters();
UpdatePaletteFade();
}
2020-08-10 23:05:42 +02:00
static void VBlankCB_UsePokeblockMenu(void)
2017-12-09 21:23:40 +01:00
{
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
sub_81D2108(&sMenu->graph);
2018-01-29 17:47:12 +01:00
ScanlineEffect_InitHBlankDmaTransfer();
2017-12-09 21:23:40 +01:00
}
2020-08-10 19:48:16 +02:00
static void SetUsePokeblockCallback(void (*func)(void))
2017-12-09 21:23:40 +01:00
{
2020-08-10 19:48:16 +02:00
sInfo->callback = func;
sInfo->mainState = 0;
2017-12-09 21:23:40 +01:00
}
2020-08-10 19:48:16 +02:00
static void LoadUsePokeblockMenu(void)
2017-12-09 21:23:40 +01:00
{
2020-08-10 19:48:16 +02:00
switch (sInfo->mainState)
2017-12-09 21:23:40 +01:00
{
2019-03-23 16:41:09 +01:00
case 0:
2021-02-20 06:30:37 +01:00
sMenu->curMonSpriteId = SPRITE_NONE;
2020-10-11 00:17:34 +02:00
InitConditionGraphData(&sMenu->graph);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 1:
ResetSpriteData();
FreeAllSpritePalettes();
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 2:
SetVBlankCallback(NULL);
CpuFill32(0, (void*)(VRAM), VRAM_SIZE);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 3:
ResetBgsAndClearDma3BusyFlags(0);
2020-08-10 19:48:16 +02:00
InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates));
InitWindows(sWindowTemplates);
2019-03-23 16:41:09 +01:00
DeactivateAllTextPrinters();
LoadUserWindowBorderGfx(0, 0x97, 0xE0);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 4:
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 5:
2020-08-10 23:05:42 +02:00
if (!LoadConditionTitle())
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 6:
gKeyRepeatStartDelay = 20;
2020-08-10 23:05:42 +02:00
LoadPartyInfo();
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 7:
2020-08-10 23:05:42 +02:00
if (!LoadUsePokeblockMenuGfx())
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 8:
2020-08-10 23:05:42 +02:00
UpdateMonPic(0);
LoadAndCreateSelectionIcons();
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 9:
if (!MoveConditionMonOnscreen(&sMenu->curMonXOffset))
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 10:
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 11:
2020-10-11 00:17:34 +02:00
sub_81D2754(sMenu->graph.stat[0], sMenu->graph.unk14[0]);
InitConditionGraphState(&sMenu->graph);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 12:
2020-10-11 00:17:34 +02:00
if (!SetupConditionGraphScanlineParams(&sMenu->graph))
2019-03-23 16:41:09 +01:00
{
sub_81D1F84(&sMenu->graph, sMenu->graph.unk14[0], sMenu->graph.unk14[0]);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
}
break;
case 13:
sub_81D2230(&sMenu->graph);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 14:
2020-08-10 19:48:16 +02:00
PutWindowTilemap(WIN_NAME);
PutWindowTilemap(WIN_NATURE);
UpdateMonInfoText(0, TRUE);
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 15:
2020-08-10 19:48:16 +02:00
SetUsePokeblockCallback(ShowUsePokeblockMenu);
2019-03-23 16:41:09 +01:00
break;
2017-12-09 21:23:40 +01:00
}
}
2019-02-23 18:08:07 +01:00
2020-08-10 19:48:16 +02:00
static void ShowUsePokeblockMenu(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
switch (sInfo->mainState)
2019-02-23 18:08:07 +01:00
{
2019-03-23 16:41:09 +01:00
case 0:
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
2020-08-10 23:05:42 +02:00
SetVBlankCallback(VBlankCB_UsePokeblockMenu);
2019-03-23 16:41:09 +01:00
ShowBg(0);
ShowBg(1);
ShowBg(3);
ShowBg(2);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 1:
if (!gPaletteFade.active)
{
2020-08-10 19:48:16 +02:00
ResetConditionSparkleSprites(sMenu->sparkles);
2020-08-10 23:05:42 +02:00
if (sMenu->info.curSelection != sMenu->info.numSelections - 1)
2019-03-23 16:10:51 +01:00
{
2020-08-10 23:05:42 +02:00
u8 numSparkles = sMenu->numSparkles[sMenu->curLoadId];
CreateConditionSparkleSprites(sMenu->sparkles, sMenu->curMonSpriteId, numSparkles);
2019-02-23 18:08:07 +01:00
}
2019-03-23 16:41:09 +01:00
2020-08-10 19:48:16 +02:00
SetUsePokeblockCallback(UsePokeblockMenu);
2019-03-23 16:41:09 +01:00
}
break;
2019-02-23 18:08:07 +01:00
}
}
2020-08-10 19:48:16 +02:00
enum {
STATE_HANDLE_INPUT,
STATE_UPDATE_SELECTION,
STATE_2, // unused state
STATE_CLOSE,
STATE_4, // unused state
STATE_CONFIRM_SELECTION,
STATE_HANDLE_CONFIRMATION,
STATE_WAIT_MSG,
};
static void UsePokeblockMenu(void)
{
2020-08-10 23:05:42 +02:00
bool8 loading;
2020-08-10 19:48:16 +02:00
switch (sInfo->mainState)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
case STATE_HANDLE_INPUT:
if (JOY_HELD(DPAD_UP))
2019-03-23 16:41:09 +01:00
{
PlaySE(SE_SELECT);
2020-08-10 23:05:42 +02:00
UpdateSelection(TRUE);
2020-08-10 19:48:16 +02:00
DestroyConditionSparkleSprites(sMenu->sparkles);
sInfo->mainState = STATE_UPDATE_SELECTION;
2019-03-23 16:41:09 +01:00
}
2020-08-10 19:48:16 +02:00
else if (JOY_HELD(DPAD_DOWN))
2019-03-23 16:41:09 +01:00
{
PlaySE(SE_SELECT);
2020-08-10 23:05:42 +02:00
UpdateSelection(FALSE);
2020-08-10 19:48:16 +02:00
DestroyConditionSparkleSprites(sMenu->sparkles);
sInfo->mainState = STATE_UPDATE_SELECTION;
2019-03-23 16:41:09 +01:00
}
2020-08-10 19:48:16 +02:00
else if (JOY_NEW(B_BUTTON))
2019-03-23 16:41:09 +01:00
{
PlaySE(SE_SELECT);
2020-08-10 19:48:16 +02:00
sInfo->mainState = STATE_CLOSE;
2019-03-23 16:41:09 +01:00
}
2020-08-10 19:48:16 +02:00
else if (JOY_NEW(A_BUTTON))
2019-03-23 16:41:09 +01:00
{
PlaySE(SE_SELECT);
2020-08-10 19:48:16 +02:00
// If last item, selected Cancel. Otherwise selected mon
2020-08-10 23:05:42 +02:00
if (sMenu->info.curSelection == sMenu->info.numSelections - 1)
2020-08-10 19:48:16 +02:00
sInfo->mainState = STATE_CLOSE;
2019-03-23 16:41:09 +01:00
else
2020-08-10 19:48:16 +02:00
sInfo->mainState = STATE_CONFIRM_SELECTION;
2019-03-23 16:41:09 +01:00
}
break;
2020-08-10 19:48:16 +02:00
case STATE_UPDATE_SELECTION:
2020-08-10 23:05:42 +02:00
loading = sMenu->info.loadNewSelection();
if (!loading)
2020-08-10 19:48:16 +02:00
sInfo->mainState = STATE_HANDLE_INPUT;
break;
2020-08-10 19:48:16 +02:00
case STATE_2:
2019-03-23 16:41:09 +01:00
break;
2020-08-10 19:48:16 +02:00
case STATE_CLOSE:
SetUsePokeblockCallback(CloseUsePokeblockMenu);
2019-03-23 16:41:09 +01:00
break;
2020-08-10 19:48:16 +02:00
case STATE_4:
2019-03-23 16:41:09 +01:00
break;
2020-08-10 19:48:16 +02:00
case STATE_CONFIRM_SELECTION:
AskUsePokeblock();
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
2020-08-10 19:48:16 +02:00
case STATE_HANDLE_CONFIRMATION:
switch (HandleAskUsePokeblockInput())
2019-03-23 16:41:09 +01:00
{
2020-08-10 19:48:16 +02:00
case 1: // NO
case MENU_B_PRESSED:
sInfo->mainState = STATE_HANDLE_INPUT;
2019-02-23 18:08:07 +01:00
break;
2020-08-10 19:48:16 +02:00
case 0: // YES
if (IsSheenMaxed())
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
PrintWontEatAnymore();
sInfo->mainState = STATE_WAIT_MSG;
2019-02-23 18:08:07 +01:00
}
2019-03-23 16:41:09 +01:00
else
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
SetUsePokeblockCallback(FeedPokeblockToMon);
2019-02-23 18:08:07 +01:00
}
break;
2019-03-23 16:41:09 +01:00
}
break;
2020-08-10 19:48:16 +02:00
case STATE_WAIT_MSG:
if (JOY_NEW(A_BUTTON | B_BUTTON))
2019-03-23 16:41:09 +01:00
{
2020-08-10 19:48:16 +02:00
EraseMenuWindow();
sInfo->mainState = STATE_HANDLE_INPUT;
2019-03-23 16:41:09 +01:00
}
break;
2019-02-23 18:08:07 +01:00
}
}
2020-08-10 19:48:16 +02:00
static void FeedPokeblockToMon(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
switch (sInfo->mainState)
2019-02-23 18:08:07 +01:00
{
2019-03-23 16:41:09 +01:00
case 0:
2020-08-10 23:05:42 +02:00
gPokeblockMonId = GetPartyIdFromSelectionId(sMenu->info.curSelection);
2020-08-10 19:48:16 +02:00
sExitCallback = sInfo->exitCallback;
sPokeblock = sInfo->pokeblock;
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 1:
if (!gPaletteFade.active)
{
SetVBlankCallback(NULL);
2020-08-10 19:48:16 +02:00
FREE_AND_SET_NULL(sGraph_Tilemap);
FREE_AND_SET_NULL(sGraph_Gfx);
FREE_AND_SET_NULL(sMonFrame_TilemapPtr);
FREE_AND_SET_NULL(sMenu);
2019-03-23 16:41:09 +01:00
FreeAllWindowBuffers();
gMain.savedCallback = CB2_ReturnAndChooseMonToGivePokeblock;
2021-04-12 18:33:06 +02:00
PreparePokeblockFeedScene();
2019-03-23 16:41:09 +01:00
}
break;
2019-02-23 18:08:07 +01:00
}
}
2020-08-10 23:05:42 +02:00
static void ShowUsePokeblockMenuForResults(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
bool8 loading;
2020-08-10 19:48:16 +02:00
switch (sInfo->mainState)
2019-02-23 18:08:07 +01:00
{
2019-03-23 16:41:09 +01:00
case 0:
2020-08-10 23:05:42 +02:00
if (sMenu->info.curSelection != gPokeblockMonId)
2019-03-23 16:41:09 +01:00
{
2020-08-10 23:05:42 +02:00
UpdateSelection(sInfo->monInTopHalf);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
}
else
{
2020-08-10 19:48:16 +02:00
sInfo->mainState = 3;
2019-03-23 16:41:09 +01:00
}
break;
case 1:
2020-08-10 23:05:42 +02:00
loading = sMenu->info.loadNewSelection();
if (!loading)
sInfo->mainState = 0;
2019-03-23 16:41:09 +01:00
break;
case 2:
break;
case 3:
2021-02-24 17:01:02 +01:00
BlendPalettes(PALETTES_ALL, 16, RGB_BLACK);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 4:
ShowBg(0);
ShowBg(1);
ShowBg(3);
ShowBg(2);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 5:
2020-08-10 23:05:42 +02:00
SetVBlankCallback(VBlankCB_UsePokeblockMenu);
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 6:
if (!gPaletteFade.active)
{
2020-08-10 19:48:16 +02:00
ResetConditionSparkleSprites(sMenu->sparkles);
2020-08-10 23:05:42 +02:00
SetUsePokeblockCallback(ShowPokeblockResults);
SetMainCallback2(CB2_UsePokeblockMenu);
2019-03-23 16:41:09 +01:00
}
break;
2019-02-23 18:08:07 +01:00
}
}
2020-08-10 23:05:42 +02:00
static void ShowPokeblockResults(void)
2019-02-23 18:08:07 +01:00
{
u8 var;
2020-08-10 19:48:16 +02:00
switch (sInfo->mainState)
2019-02-23 18:08:07 +01:00
{
case 0:
2020-08-10 19:48:16 +02:00
sInfo->mon = gPlayerParty;
2020-08-10 23:05:42 +02:00
sInfo->mon += sMenu->party[sMenu->info.curSelection].monId;
2020-08-10 19:48:16 +02:00
DestroyConditionSparkleSprites(sMenu->sparkles);
sInfo->mainState++;
break;
case 1:
2020-08-10 19:48:16 +02:00
if (JOY_NEW(A_BUTTON | B_BUTTON))
sInfo->mainState++;
break;
case 2:
2020-08-10 23:05:42 +02:00
CalculateConditionEnhancements();
sub_81D2754(sInfo->conditionsAfterBlock, sMenu->graph.unk14[3]);
sub_81D1F84(&sMenu->graph, sMenu->graph.unk14[sMenu->curLoadId], sMenu->graph.unk14[3]);
2020-08-10 23:05:42 +02:00
LoadAndCreateUpDownSprites();
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
break;
case 3:
var = TransitionConditionGraph(&sMenu->graph);
if (!var)
{
2020-08-10 23:05:42 +02:00
CalculateNumAdditionalSparkles(GetPartyIdFromSelectionId(sMenu->info.curSelection));
if (sMenu->info.curSelection != sMenu->info.numSelections - 1)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
u8 numSparkles = sMenu->numSparkles[sMenu->curLoadId];
CreateConditionSparkleSprites(sMenu->sparkles, sMenu->curMonSpriteId, numSparkles);
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
sInfo->timer = 0;
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
}
break;
case 4:
2020-08-10 23:05:42 +02:00
if (++sInfo->timer > 16)
{
2020-08-10 23:05:42 +02:00
PrintFirstEnhancement();
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
}
break;
case 5:
2020-08-10 23:05:42 +02:00
if (JOY_NEW(A_BUTTON | B_BUTTON) && !TryPrintNextEnhancement())
{
TryClearPokeblock((u8)gSpecialVar_ItemId);
2020-08-10 19:48:16 +02:00
SetUsePokeblockCallback(CloseUsePokeblockMenu);
}
break;
2019-02-23 18:08:07 +01:00
}
}
2020-08-10 19:48:16 +02:00
static void CloseUsePokeblockMenu(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
u8 i;
2020-08-10 19:48:16 +02:00
switch (sInfo->mainState)
{
2019-03-23 16:41:09 +01:00
case 0:
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 1:
if (!gPaletteFade.active)
2020-08-10 19:48:16 +02:00
sInfo->mainState = 2;
2019-03-23 16:41:09 +01:00
break;
case 2:
gScanlineEffect.state = 3;
ScanlineEffect_InitHBlankDmaTransfer();
2020-08-10 19:48:16 +02:00
sInfo->mainState++;
2019-03-23 16:41:09 +01:00
break;
case 3:
2020-08-10 19:48:16 +02:00
SetMainCallback2(sInfo->exitCallback);
FreeConditionSparkles(sMenu->sparkles);
2020-08-10 23:05:42 +02:00
for (i = 0; i < ARRAY_COUNT(sMenu->selectionIconSpriteIds); i++)
DestroySprite(&gSprites[sMenu->selectionIconSpriteIds[i]]);
2020-08-10 19:48:16 +02:00
FreeSpriteTilesByTag(TAG_UP_DOWN);
FreeSpriteTilesByTag(TAG_CONDITION);
FreeSpritePaletteByTag(TAG_UP_DOWN);
FreeSpritePaletteByTag(TAG_CONDITION);
2020-08-10 19:48:16 +02:00
for (i = 0; i < ARRAY_COUNT(sMenu->condition); i++)
DestroySprite(sMenu->condition[i]);
2021-02-20 06:30:37 +01:00
if (sMenu->curMonSpriteId != SPRITE_NONE)
2020-08-10 23:05:42 +02:00
DestroySprite(&gSprites[sMenu->curMonSpriteId]);
2019-03-23 16:41:09 +01:00
SetVBlankCallback(NULL);
2020-08-10 19:48:16 +02:00
FREE_AND_SET_NULL(sGraph_Tilemap);
FREE_AND_SET_NULL(sGraph_Gfx);
FREE_AND_SET_NULL(sMonFrame_TilemapPtr);
FREE_AND_SET_NULL(sMenu);
2019-03-23 16:41:09 +01:00
FreeAllWindowBuffers();
break;
2019-02-23 18:08:07 +01:00
}
}
2020-08-10 19:48:16 +02:00
static void AskUsePokeblock(void)
2019-02-23 18:08:07 +01:00
{
2019-03-23 16:41:09 +01:00
u8 stringBuffer[0x40];
2020-08-10 23:05:42 +02:00
GetMonData(&gPlayerParty[GetPartyIdFromSelectionId(sMenu->info.curSelection)], MON_DATA_NICKNAME, stringBuffer);
2019-02-23 18:08:07 +01:00
StringGetEnd10(stringBuffer);
StringAppend(stringBuffer, gText_GetsAPokeBlockQuestion);
2019-03-23 16:41:09 +01:00
StringCopy(gStringVar4, stringBuffer);
2020-08-10 19:48:16 +02:00
FillWindowPixelBuffer(WIN_TEXT, 17);
DrawTextBorderOuter(WIN_TEXT, 151, 14);
AddTextPrinterParameterized(WIN_TEXT, 1, gStringVar4, 0, 1, 0, NULL);
PutWindowTilemap(WIN_TEXT);
CopyWindowToVram(WIN_TEXT, 3);
2019-07-31 02:21:17 +02:00
CreateYesNoMenu(&sUsePokeblockYesNoWinTemplate, 151, 14, 0);
2019-02-23 18:08:07 +01:00
}
2020-08-10 19:48:16 +02:00
static s8 HandleAskUsePokeblockInput(void)
2019-02-23 18:08:07 +01:00
{
s8 menuItem = Menu_ProcessInputNoWrapClearOnChoose();
switch (menuItem)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
case 0: // YES
2019-03-23 16:41:09 +01:00
break;
case MENU_B_PRESSED:
2020-08-10 19:48:16 +02:00
case 1: // NO
2019-03-23 16:41:09 +01:00
PlaySE(SE_SELECT);
rbox_fill_rectangle(2);
ClearWindowTilemap(2);
break;
2019-02-23 18:08:07 +01:00
}
return menuItem;
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static void PrintFirstEnhancement(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
DrawTextBorderOuter(WIN_TEXT, 151, 14);
FillWindowPixelBuffer(WIN_TEXT, 17);
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
for (sInfo->statId = 0; sInfo->statId < FLAVOR_COUNT; sInfo->statId++)
{
2020-08-10 23:05:42 +02:00
if (sInfo->enhancements[sInfo->statId] != 0)
break;
}
2020-08-10 23:05:42 +02:00
if (sInfo->statId < FLAVOR_COUNT)
BufferEnhancedStatText(gStringVar4, sInfo->statId, sInfo->enhancements[sInfo->statId]);
2019-03-23 16:41:09 +01:00
else
2020-08-10 23:05:42 +02:00
BufferEnhancedStatText(gStringVar4, sInfo->statId, 0);
2020-08-10 19:48:16 +02:00
PrintMenuWindowText(gStringVar4);
PutWindowTilemap(WIN_TEXT);
CopyWindowToVram(WIN_TEXT, 3);
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static bool8 TryPrintNextEnhancement(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
FillWindowPixelBuffer(WIN_TEXT, 17);
2019-02-23 18:08:07 +01:00
while (1)
{
2020-08-10 23:05:42 +02:00
sInfo->statId++;
if (sInfo->statId < FLAVOR_COUNT)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
if (sInfo->enhancements[sInfo->statId] != 0)
2019-02-23 18:08:07 +01:00
break;
}
else
{
2020-08-10 23:05:42 +02:00
sInfo->statId = FLAVOR_COUNT;
2019-02-23 18:08:07 +01:00
return FALSE;
}
}
2020-08-10 23:05:42 +02:00
BufferEnhancedStatText(gStringVar4, sInfo->statId, sInfo->enhancements[sInfo->statId]);
2020-08-10 19:48:16 +02:00
PrintMenuWindowText(gStringVar4);
CopyWindowToVram(WIN_TEXT, 2);
2019-03-23 16:41:09 +01:00
return TRUE;
2019-02-23 18:08:07 +01:00
}
2020-08-10 19:48:16 +02:00
static void PrintWontEatAnymore(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
FillWindowPixelBuffer(WIN_TEXT, 17);
DrawTextBorderOuter(WIN_TEXT, 151, 14);
AddTextPrinterParameterized(WIN_TEXT, 1, gText_WontEatAnymore, 0, 1, 0, NULL);
PutWindowTilemap(WIN_TEXT);
CopyWindowToVram(WIN_TEXT, 3);
2019-02-23 18:08:07 +01:00
}
2020-08-10 19:48:16 +02:00
static void EraseMenuWindow(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
rbox_fill_rectangle(WIN_TEXT);
ClearWindowTilemap(WIN_TEXT);
CopyWindowToVram(WIN_TEXT, 3);
2019-02-23 18:08:07 +01:00
}
2020-08-10 19:48:16 +02:00
static void PrintMenuWindowText(const u8 *message)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
AddTextPrinterParameterized(WIN_TEXT, 1, gStringVar4, 0, 1, 0, NULL);
2019-02-23 18:08:07 +01:00
}
2020-08-10 19:48:16 +02:00
static void BufferEnhancedStatText(u8 *dest, u8 statId, s16 enhancement)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
switch (enhancement)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
case 1 ... 32767: // if > 0
enhancement = 0;
2020-04-02 07:37:22 +02:00
// fallthrough
2020-08-10 19:48:16 +02:00
case -32768 ... -1: // if < 0
if (enhancement)
dest[(u16)enhancement] += 0; // something you can't imagine
2019-03-31 14:32:26 +02:00
StringCopy(dest, sContestStatNames[statId]);
2019-02-23 18:08:07 +01:00
StringAppend(dest, gText_WasEnhanced);
2020-04-02 07:37:22 +02:00
break;
case 0:
2019-03-23 16:41:09 +01:00
StringCopy(dest, gText_NothingChanged);
2020-04-02 07:37:22 +02:00
break;
2019-03-23 16:41:09 +01:00
}
2019-02-23 18:08:07 +01:00
}
2020-08-10 19:48:16 +02:00
static void GetMonConditions(struct Pokemon *mon, u8 *data)
2019-02-23 18:08:07 +01:00
{
2019-03-23 17:16:53 +01:00
u16 i;
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
for (i = 0; i < FLAVOR_COUNT; i++)
data[i] = GetMonData(mon, sMonDataConditions[i]);
2019-02-23 18:08:07 +01:00
}
static void AddPokeblockToConditions(struct Pokeblock *pokeblock, struct Pokemon *mon)
2019-02-23 18:08:07 +01:00
{
u16 i;
s16 cstat;
u8 data;
if (GetMonData(mon, MON_DATA_SHEEN) != 255)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
CalculatePokeblockEffectiveness(pokeblock, mon);
2020-08-10 19:48:16 +02:00
for (i = 0; i < FLAVOR_COUNT; i++)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
data = GetMonData(mon, sMonDataConditions[i]);
cstat = data + sInfo->pokeblockStatBoosts[i];
2019-02-23 18:08:07 +01:00
if (cstat < 0)
cstat = 0;
if (cstat > 255)
cstat = 255;
data = cstat;
2020-08-10 23:05:42 +02:00
SetMonData(mon, sMonDataConditions[i], &data);
2019-02-23 18:08:07 +01:00
}
2019-03-23 17:16:53 +01:00
cstat = (u8)(GetMonData(mon, MON_DATA_SHEEN)) + pokeblock->feel;
2019-02-23 18:08:07 +01:00
if (cstat > 255)
cstat = 255;
2019-03-23 17:16:53 +01:00
2019-02-23 18:08:07 +01:00
data = cstat;
SetMonData(mon, MON_DATA_SHEEN, &data);
2019-02-23 18:08:07 +01:00
}
}
2020-08-10 23:05:42 +02:00
static void CalculateConditionEnhancements(void)
2019-02-23 18:08:07 +01:00
{
u16 i;
struct Pokemon *mon = gPlayerParty;
2020-08-10 23:05:42 +02:00
mon += sMenu->party[sMenu->info.curSelection].monId;
GetMonConditions(mon, sInfo->conditionsBeforeBlock);
AddPokeblockToConditions(sInfo->pokeblock, mon);
GetMonConditions(mon, sInfo->conditionsAfterBlock);
2020-08-10 19:48:16 +02:00
for (i = 0; i < FLAVOR_COUNT; i++)
sInfo->enhancements[i] = sInfo->conditionsAfterBlock[i] - sInfo->conditionsBeforeBlock[i];
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static void CalculatePokeblockEffectiveness(struct Pokeblock *pokeblock, struct Pokemon *mon)
2019-02-23 18:08:07 +01:00
{
s8 i, direction, taste;
2020-08-10 23:05:42 +02:00
sInfo->pokeblockStatBoosts[0] = pokeblock->spicy;
sInfo->pokeblockStatBoosts[1] = pokeblock->sour;
sInfo->pokeblockStatBoosts[2] = pokeblock->bitter;
sInfo->pokeblockStatBoosts[3] = pokeblock->sweet;
sInfo->pokeblockStatBoosts[4] = pokeblock->dry;
2019-02-23 18:08:07 +01:00
if (gPokeblockGain > 0)
direction = 1;
else if (gPokeblockGain < 0)
direction = -1;
else
return;
2019-03-23 17:16:53 +01:00
2020-08-10 19:48:16 +02:00
for (i = 0; i < FLAVOR_COUNT; i++)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
s16 amount = sInfo->pokeblockStatBoosts[i];
s8 boost = amount / 10;
2019-02-23 18:08:07 +01:00
if (amount % 10 >= 5) // round to the nearest
boost++;
2019-03-23 17:16:53 +01:00
2020-08-10 19:48:16 +02:00
taste = GetMonFlavorRelation(mon, sFlavors[i]);
2019-02-23 18:08:07 +01:00
if (taste == direction)
2020-08-10 23:05:42 +02:00
sInfo->pokeblockStatBoosts[i] += boost * taste;
2019-02-23 18:08:07 +01:00
}
}
2020-08-10 19:48:16 +02:00
static bool8 IsSheenMaxed(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
if (GetBoxOrPartyMonData(sMenu->party[sMenu->info.curSelection].boxId,
sMenu->party[sMenu->info.curSelection].monId,
MON_DATA_SHEEN,
NULL) == 255)
2019-02-23 18:08:07 +01:00
return TRUE;
else
return FALSE;
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static u8 GetPartyIdFromSelectionId(u8 selectionId)
2019-02-23 18:08:07 +01:00
{
u8 i;
2019-03-23 17:16:53 +01:00
for (i = 0; i < PARTY_SIZE; i++)
2019-02-23 18:08:07 +01:00
{
if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
{
2020-08-10 23:05:42 +02:00
if (selectionId == 0)
2019-02-23 18:08:07 +01:00
return i;
2020-08-10 23:05:42 +02:00
selectionId--;
2019-02-23 18:08:07 +01:00
}
}
2019-02-23 18:08:07 +01:00
return 0;
}
// Eggs are not viewable on the condition screen, so count how many are skipped over to reach the party id
static u8 GetSelectionIdFromPartyId(u8 partyId)
2019-02-23 18:08:07 +01:00
{
2019-03-23 17:16:53 +01:00
u8 i, numEggs;
for (i = 0, numEggs = 0; i < partyId; i++)
2019-02-23 18:08:07 +01:00
{
if (GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
2019-03-23 17:16:53 +01:00
numEggs++;
2019-02-23 18:08:07 +01:00
}
2019-03-23 17:16:53 +01:00
return partyId - numEggs;
2019-02-23 18:08:07 +01:00
}
2020-08-10 19:48:16 +02:00
// Unused
2020-08-10 23:05:42 +02:00
static u8 GetPartyIdFromSelectionId_(u8 selectionId)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
return GetPartyIdFromSelectionId(selectionId);
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static void LoadAndCreateUpDownSprites(void)
2019-02-23 18:08:07 +01:00
{
u16 i, spriteId;
2020-08-10 19:48:16 +02:00
LoadSpriteSheet(&sSpriteSheet_UpDown);
LoadSpritePalette(&sSpritePalette_UpDown);
sInfo->numEnhancements = 0;
2020-08-10 19:48:16 +02:00
for (i = 0; i < FLAVOR_COUNT; i++)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
if (sInfo->enhancements[i] != 0)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
spriteId = CreateSprite(&sSpriteTemplate_UpDown, sUpDownCoordsOnGraph[i][0], sUpDownCoordsOnGraph[i][1], 0);
if (spriteId != MAX_SPRITES)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
if (sInfo->enhancements[i] != 0) // Always true here
gSprites[spriteId].callback = SpriteCB_UpDown;
2020-08-10 19:48:16 +02:00
sInfo->numEnhancements++;
2019-02-23 18:08:07 +01:00
}
}
}
}
2020-08-10 23:05:42 +02:00
static void SpriteCB_UpDown(struct Sprite *sprite)
2019-02-23 18:08:07 +01:00
{
2019-03-23 17:16:53 +01:00
if (sprite->data[0] < 6)
2021-07-07 15:11:52 +02:00
sprite->y2 -= 2;
2019-03-23 17:16:53 +01:00
else if (sprite->data[0] < 12)
2021-07-07 15:11:52 +02:00
sprite->y2 += 2;
2019-03-23 17:16:53 +01:00
if (++sprite->data[0] > 60)
2019-02-23 18:08:07 +01:00
{
DestroySprite(sprite);
2020-08-10 19:48:16 +02:00
sInfo->numEnhancements--;
2019-02-23 18:08:07 +01:00
}
}
2020-08-10 23:05:42 +02:00
static void LoadPartyInfo(void)
2019-02-23 18:08:07 +01:00
{
2019-03-23 16:41:09 +01:00
u16 i;
2019-03-23 17:16:53 +01:00
u16 numMons;
for (i = 0, numMons = 0; i < CalculatePlayerPartyCount(); i++)
2019-02-23 18:08:07 +01:00
{
if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
{
2020-08-10 19:48:16 +02:00
sMenu->party[numMons].boxId = TOTAL_BOXES_COUNT;
sMenu->party[numMons].monId = i;
sMenu->party[numMons].data = 0;
2019-03-23 17:16:53 +01:00
numMons++;
2019-02-23 18:08:07 +01:00
}
}
2019-03-23 17:16:53 +01:00
2020-08-10 23:05:42 +02:00
sMenu->info.curSelection = 0;
sMenu->info.numSelections = numMons + 1;
LoadInitialMonInfo();
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static void LoadInitialMonInfo(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
s16 nextSelection, prevSelection;
2020-08-10 23:05:42 +02:00
LoadMonInfo(sMenu->info.curSelection, 0);
sMenu->curLoadId = 0;
sMenu->nextLoadId = 1;
sMenu->prevLoadId = 2;
2020-08-10 23:05:42 +02:00
nextSelection = sMenu->info.curSelection + 1;
if (nextSelection >= sMenu->info.numSelections)
nextSelection = 0;
2020-08-10 23:05:42 +02:00
prevSelection = sMenu->info.curSelection - 1;
if (prevSelection < 0)
prevSelection = sMenu->info.numSelections - 1;
2020-08-10 23:05:42 +02:00
LoadMonInfo(nextSelection, 1);
LoadMonInfo(prevSelection, 2);
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static void LoadMonInfo(s16 partyId, u8 loadId)
2019-02-23 18:08:07 +01:00
{
2020-08-10 23:05:42 +02:00
u8 boxId = sMenu->party[partyId].boxId;
u8 monId = sMenu->party[partyId].monId;
u8 numSelections = sMenu->info.numSelections;
bool8 excludesCancel = FALSE; // whether or not numSelections excludes Cancel from the count
2019-03-31 14:32:26 +02:00
2020-08-10 23:05:42 +02:00
GetConditionMenuMonNameAndLocString(sMenu->locationStrings[loadId], sMenu->monNameStrings[loadId], boxId, monId, partyId, numSelections, excludesCancel);
GetConditionMenuMonConditions(&sMenu->graph, sMenu->numSparkles, boxId, monId, partyId, loadId, numSelections, excludesCancel);
2020-08-10 23:05:42 +02:00
GetConditionMenuMonGfx(sMenu->partySheets[loadId], sMenu->partyPalettes[loadId], boxId, monId, partyId, numSelections, excludesCancel);
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static void UpdateMonPic(u8 loadId)
2019-02-23 18:08:07 +01:00
{
u8 spriteId;
struct SpriteTemplate spriteTemplate;
struct SpriteSheet spriteSheet;
struct SpritePalette spritePal;
2021-02-20 06:30:37 +01:00
if (sMenu->curMonSpriteId == SPRITE_NONE)
2019-03-23 16:41:09 +01:00
{
2020-08-10 23:05:42 +02:00
LoadConditionMonPicTemplate(&spriteSheet, &spriteTemplate, &spritePal);
spriteSheet.data = sMenu->partySheets[loadId];
spritePal.data = sMenu->partyPalettes[loadId];
sMenu->curMonPalette = LoadSpritePalette(&spritePal);
sMenu->curMonSheet = LoadSpriteSheet(&spriteSheet);
spriteId = CreateSprite(&spriteTemplate, 38, 104, 0);
2020-08-10 23:05:42 +02:00
sMenu->curMonSpriteId = spriteId;
if (spriteId == MAX_SPRITES)
2019-03-23 16:41:09 +01:00
{
FreeSpriteTilesByTag(TAG_CONDITION_MON);
FreeSpritePaletteByTag(TAG_CONDITION_MON);
2021-02-20 06:30:37 +01:00
sMenu->curMonSpriteId = SPRITE_NONE;
2019-03-23 16:41:09 +01:00
}
else
{
2020-08-10 23:05:42 +02:00
sMenu->curMonSpriteId = spriteId;
gSprites[sMenu->curMonSpriteId].callback = SpriteCB_MonPic;
2021-07-07 15:11:52 +02:00
gSprites[sMenu->curMonSpriteId].y2 -= 34;
2020-08-10 23:05:42 +02:00
sMenu->curMonTileStart = (void*)(OBJ_VRAM0 + (sMenu->curMonSheet * 32));
sMenu->curMonPalette = (sMenu->curMonPalette * 16) + 0x100;
2019-03-23 16:41:09 +01:00
}
}
else
{
2021-03-29 15:38:19 +02:00
Dma3CopyLarge16_(sMenu->partySheets[loadId], sMenu->curMonTileStart, MON_PIC_SIZE);
2020-08-10 23:05:42 +02:00
LoadPalette(sMenu->partyPalettes[loadId], sMenu->curMonPalette, 32);
2019-03-23 16:41:09 +01:00
}
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static void LoadAndCreateSelectionIcons(void)
2019-02-23 18:08:07 +01:00
{
u16 i, spriteId;
struct SpriteSheet spriteSheets[4];
struct SpriteTemplate spriteTemplate;
struct SpritePalette spritePals[3];
struct SpriteSheet spriteSheet2;
struct SpritePalette spritePal2;
2020-08-10 19:48:16 +02:00
LoadConditionSelectionIcons(spriteSheets, &spriteTemplate, spritePals);
LoadSpriteSheets(spriteSheets);
LoadSpritePalettes(spritePals);
2020-08-10 23:05:42 +02:00
// Fill pokeball selection icons up to number in party
for (i = 0; i < sMenu->info.numSelections - 1; i++)
2019-03-23 16:41:09 +01:00
{
spriteId = CreateSprite(&spriteTemplate, 226, (i * 20) + 8, 0);
if (spriteId != MAX_SPRITES)
2019-03-23 16:41:09 +01:00
{
2020-08-10 23:05:42 +02:00
sMenu->selectionIconSpriteIds[i] = spriteId;
gSprites[spriteId].data[0] = i;
2020-08-10 23:05:42 +02:00
gSprites[spriteId].callback = SpriteCB_SelectionIconPokeball;
2019-03-23 16:41:09 +01:00
}
else
{
2020-08-10 23:05:42 +02:00
sMenu->selectionIconSpriteIds[i] = -1;
2019-03-23 16:41:09 +01:00
}
}
2020-08-10 23:05:42 +02:00
// Fill placeholder icons for remaining (empty) party slots
spriteTemplate.tileTag = TAG_CONDITION_BALL_PLACEHOLDER;
2020-08-10 23:05:42 +02:00
for (; i < PARTY_SIZE; i++)
2019-03-23 16:41:09 +01:00
{
spriteId = CreateSprite(&spriteTemplate, 230, (i * 20) + 8, 0);
if (spriteId != MAX_SPRITES)
2019-03-23 16:41:09 +01:00
{
2020-08-10 23:05:42 +02:00
sMenu->selectionIconSpriteIds[i] = spriteId;
gSprites[spriteId].oam.size = 0;
2019-03-23 16:41:09 +01:00
}
else
{
2020-08-10 23:05:42 +02:00
sMenu->selectionIconSpriteIds[i] = -1;
2019-03-23 16:41:09 +01:00
}
}
2020-08-10 23:05:42 +02:00
// Add cancel selection icon at bottom
spriteTemplate.tileTag = TAG_CONDITION_CANCEL;
2020-08-10 23:05:42 +02:00
spriteTemplate.callback = SpriteCB_SelectionIconCancel;
spriteId = CreateSprite(&spriteTemplate, 222, (i * 20) + 8, 0);
if (spriteId != MAX_SPRITES)
2019-03-23 16:41:09 +01:00
{
2020-08-10 23:05:42 +02:00
sMenu->selectionIconSpriteIds[i] = spriteId;
gSprites[spriteId].oam.shape = SPRITE_SHAPE(32x16);
gSprites[spriteId].oam.size = SPRITE_SIZE(32x16);
}
else
2019-03-23 16:41:09 +01:00
{
2020-08-10 23:05:42 +02:00
sMenu->selectionIconSpriteIds[i] = -1;
2019-03-23 16:41:09 +01:00
}
2020-08-10 19:48:16 +02:00
LoadConditionSparkle(&spriteSheet2, &spritePal2);
LoadSpriteSheet(&spriteSheet2);
LoadSpritePalette(&spritePal2);
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static bool8 LoadUsePokeblockMenuGfx(void)
2019-02-23 18:08:07 +01:00
{
2020-08-10 19:48:16 +02:00
switch (sMenu->info.helperState)
{
case 0:
ChangeBgX(0, 0, 0);
ChangeBgY(0, 0, 0);
ChangeBgX(1, 0, 0);
ChangeBgY(1, 0, 0);
ChangeBgX(2, 0, 0);
ChangeBgY(2, 0, 0);
ChangeBgX(3, 0, 0);
ChangeBgY(3, 136 << 6, 0);
2020-08-10 19:48:16 +02:00
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_WIN1_ON);
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(11, 4));
break;
case 1:
2020-08-10 19:48:16 +02:00
sGraph_Gfx = Alloc(6656);
sGraph_Tilemap = Alloc(1280);
sMonFrame_TilemapPtr = Alloc(1280);
break;
case 2:
2020-08-10 19:48:16 +02:00
LZ77UnCompVram(sMonFrame_Tilemap, sMonFrame_TilemapPtr);
break;
case 3:
2020-08-10 19:48:16 +02:00
LoadBgTiles(3, sMonFrame_Gfx, 224, 0);
break;
case 4:
2020-08-10 19:48:16 +02:00
LoadBgTilemap(3, sMonFrame_TilemapPtr, 1280, 0);
break;
case 5:
2020-08-10 19:48:16 +02:00
LoadPalette(sMonFrame_Pal, 208, 32);
2020-08-10 23:05:42 +02:00
sMenu->curMonXOffset = -80;
break;
case 6:
2020-08-10 19:48:16 +02:00
LZ77UnCompVram(gUsePokeblockGraph_Gfx, sGraph_Gfx);
break;
case 7:
2020-08-10 19:48:16 +02:00
LZ77UnCompVram(gUsePokeblockGraph_Tilemap, sGraph_Tilemap);
LoadPalette(gUsePokeblockGraph_Pal, 32, 32);
break;
case 8:
2020-08-10 19:48:16 +02:00
LoadBgTiles(1, sGraph_Gfx, 6656, 160 << 2);
break;
case 9:
2020-08-10 19:48:16 +02:00
SetBgTilemapBuffer(1, sGraph_Tilemap);
CopyToBgTilemapBufferRect(1, gUsePokeblockNatureWin_Pal, 0, 13, 12, 4);
CopyBgTilemapBufferToVram(1);
break;
case 10:
2020-08-10 19:48:16 +02:00
LZ77UnCompVram(sGraphData_Tilemap, sMenu->tilemapBuffer);
break;
case 11:
2020-08-10 19:48:16 +02:00
LoadBgTilemap(2, sMenu->tilemapBuffer, 1280, 0);
LoadPalette(gConditionGraphData_Pal, 48, 32);
2020-08-10 23:05:42 +02:00
LoadPalette(gConditionText_Pal, 240, 32);
2020-10-11 00:17:34 +02:00
SetConditionGraphIOWindows(2);
break;
default:
2020-08-10 19:48:16 +02:00
sMenu->info.helperState = 0;
return FALSE;
}
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
return TRUE;
2019-02-23 18:08:07 +01:00
}
2020-08-10 23:05:42 +02:00
static void UpdateMonInfoText(u16 loadId, bool8 firstPrint)
{
u8 partyIndex;
u8 nature;
u8 *str;
2019-02-23 18:08:07 +01:00
2020-08-10 19:48:16 +02:00
FillWindowPixelBuffer(WIN_NAME, PIXEL_FILL(0));
FillWindowPixelBuffer(WIN_NATURE, PIXEL_FILL(0));
2020-08-10 23:05:42 +02:00
if (sMenu->info.curSelection != sMenu->info.numSelections - 1)
{
2020-08-10 23:05:42 +02:00
AddTextPrinterParameterized(WIN_NAME, 1, sMenu->monNameStrings[loadId], 0, 1, 0, NULL);
partyIndex = GetPartyIdFromSelectionId(sMenu->info.curSelection);
nature = GetNature(&gPlayerParty[partyIndex]);
2020-08-10 23:05:42 +02:00
str = StringCopy(sMenu->info.natureText, gText_NatureSlash);
str = StringCopy(str, gNatureNamePointers[nature]);
2020-08-10 23:05:42 +02:00
AddTextPrinterParameterized3(WIN_NATURE, 1, 2, 1, sNatureTextColors, 0, sMenu->info.natureText);
}
2019-02-23 18:08:07 +01:00
2020-08-10 19:48:16 +02:00
if (firstPrint)
{
2020-08-10 19:48:16 +02:00
CopyWindowToVram(WIN_NAME, 3);
CopyWindowToVram(WIN_NATURE, 3);
}
else
{
2020-08-10 19:48:16 +02:00
CopyWindowToVram(WIN_NAME, 2);
CopyWindowToVram(WIN_NATURE, 2);
}
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static void UpdateSelection(bool8 up)
{
2020-08-10 23:05:42 +02:00
u16 newLoadId;
bool32 startedOnMon, endedOnMon;
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
if (up)
newLoadId = sMenu->prevLoadId;
else
2020-08-10 23:05:42 +02:00
newLoadId = sMenu->nextLoadId;
2019-02-23 18:08:07 +01:00
sub_81D1F84(&sMenu->graph, sMenu->graph.unk14[sMenu->curLoadId], sMenu->graph.unk14[newLoadId]);
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
if (sMenu->info.curSelection == sMenu->info.numSelections - 1)
startedOnMon = FALSE; // moving off of Cancel
else
startedOnMon = TRUE;
if (up)
{
2020-08-10 23:05:42 +02:00
sMenu->prevLoadId = sMenu->nextLoadId; // temporarily store nextLoadId, prevLoadId no longer needed
sMenu->nextLoadId = sMenu->curLoadId;
sMenu->curLoadId = newLoadId;
sMenu->toLoadId = sMenu->prevLoadId; // next load will be the mon that's one up from new selection
// Check for wrap to bottom of list
sMenu->info.curSelection = (sMenu->info.curSelection == 0)
? sMenu->info.numSelections - 1
: sMenu->info.curSelection - 1;
sMenu->toLoadSelection = (sMenu->info.curSelection == 0)
2020-08-10 23:05:42 +02:00
? sMenu->info.numSelections - 1
: sMenu->info.curSelection - 1;
}
else
{
2020-08-10 23:05:42 +02:00
sMenu->nextLoadId = sMenu->prevLoadId; // temporarily store prevLoadId, nextLoadId no longer needed
sMenu->prevLoadId = sMenu->curLoadId;
sMenu->curLoadId = newLoadId;
sMenu->toLoadId = sMenu->nextLoadId; // next load will be the mon that's one down from new selection
// Check for wrap to top of list
sMenu->info.curSelection = (sMenu->info.curSelection < sMenu->info.numSelections - 1)
? sMenu->info.curSelection + 1
: 0;
sMenu->toLoadSelection = (sMenu->info.curSelection < sMenu->info.numSelections - 1)
2020-08-10 23:05:42 +02:00
? sMenu->info.curSelection + 1
: 0;
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
if (sMenu->info.curSelection == sMenu->info.numSelections - 1)
endedOnMon = FALSE; // moving onto Cancel
else
endedOnMon = TRUE;
2020-08-10 19:48:16 +02:00
DestroyConditionSparkleSprites(sMenu->sparkles);
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
if (!startedOnMon)
sMenu->info.loadNewSelection = LoadNewSelection_CancelToMon;
else if (!endedOnMon)
sMenu->info.loadNewSelection = LoadNewSelection_MonToCancel;
else
2020-08-10 23:05:42 +02:00
sMenu->info.loadNewSelection = LoadNewSelection_MonToMon;
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static bool8 LoadNewSelection_CancelToMon(void)
{
2020-08-10 19:48:16 +02:00
switch (sMenu->info.helperState)
{
case 0:
2020-08-10 23:05:42 +02:00
UpdateMonPic(sMenu->curLoadId);
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
break;
case 1:
2020-08-10 23:05:42 +02:00
UpdateMonInfoText(sMenu->curLoadId, FALSE);
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
break;
case 2:
if (!TryUpdateConditionMonTransitionOn(&sMenu->graph, &sMenu->curMonXOffset))
{
// Load the new adjacent pokemon (not the one being shown)
LoadMonInfo(sMenu->toLoadSelection, sMenu->toLoadId);
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
}
break;
case 3:
2020-08-10 19:48:16 +02:00
ResetConditionSparkleSprites(sMenu->sparkles);
2020-08-10 23:05:42 +02:00
if (sMenu->info.curSelection != sMenu->info.numSelections - 1)
{
2020-08-10 23:05:42 +02:00
u8 numSparkles = sMenu->numSparkles[sMenu->curLoadId];
CreateConditionSparkleSprites(sMenu->sparkles, sMenu->curMonSpriteId, numSparkles);
}
2019-02-23 18:08:07 +01:00
2020-08-10 19:48:16 +02:00
sMenu->info.helperState = 0;
return FALSE;
}
2019-02-23 18:08:07 +01:00
return TRUE;
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static bool8 LoadNewSelection_MonToCancel(void)
{
2020-08-10 19:48:16 +02:00
switch (sMenu->info.helperState)
{
case 0:
if (!TryUpdateConditionMonTransitionOff(&sMenu->graph, &sMenu->curMonXOffset))
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
break;
case 1:
2020-08-10 23:05:42 +02:00
UpdateMonInfoText(sMenu->curLoadId, FALSE);
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
break;
case 2:
LoadMonInfo(sMenu->toLoadSelection, sMenu->toLoadId);
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
break;
case 3:
2020-08-10 19:48:16 +02:00
sMenu->info.helperState = 0;
return FALSE;
}
2019-02-23 18:08:07 +01:00
return TRUE;
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static bool8 LoadNewSelection_MonToMon(void)
{
2020-08-10 19:48:16 +02:00
switch (sMenu->info.helperState)
{
case 0:
TransitionConditionGraph(&sMenu->graph);
if (!MoveConditionMonOffscreen(&sMenu->curMonXOffset))
{
2020-08-10 23:05:42 +02:00
UpdateMonPic(sMenu->curLoadId);
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
}
break;
case 1:
2020-08-10 23:05:42 +02:00
UpdateMonInfoText(sMenu->curLoadId, FALSE);
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
break;
case 2:
if (!TryUpdateConditionMonTransitionOn(&sMenu->graph, &sMenu->curMonXOffset))
{
// Load the new adjacent pokemon (not the one being shown)
LoadMonInfo(sMenu->toLoadSelection, sMenu->toLoadId);
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
}
break;
case 3:
2020-08-10 19:48:16 +02:00
ResetConditionSparkleSprites(sMenu->sparkles);
2020-08-10 23:05:42 +02:00
if (sMenu->info.curSelection != sMenu->info.numSelections - 1)
{
2020-08-10 23:05:42 +02:00
u8 numSparkles = sMenu->numSparkles[sMenu->curLoadId];
CreateConditionSparkleSprites(sMenu->sparkles, sMenu->curMonSpriteId, numSparkles);
}
2019-02-23 18:08:07 +01:00
2020-08-10 19:48:16 +02:00
sMenu->info.helperState = 0;
return FALSE;
}
2019-02-23 18:08:07 +01:00
return TRUE;
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static void SpriteCB_MonPic(struct Sprite *sprite)
{
2021-07-07 15:11:52 +02:00
sprite->x = sMenu->curMonXOffset + 38;
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static void SpriteCB_SelectionIconPokeball(struct Sprite *sprite)
{
2020-08-10 23:05:42 +02:00
if (sprite->data[0] == sMenu->info.curSelection)
StartSpriteAnim(sprite, 0);
else
StartSpriteAnim(sprite, 1);
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static void SpriteCB_SelectionIconCancel(struct Sprite *sprite)
{
2020-08-10 23:05:42 +02:00
if (sMenu->info.curSelection == sMenu->info.numSelections - 1)
sprite->oam.paletteNum = IndexOfSpritePaletteTag(TAG_CONDITION_BALL);
else
sprite->oam.paletteNum = IndexOfSpritePaletteTag(TAG_CONDITION_CANCEL);
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
// Calculate the max id for sparkles/stars that appear around the pokemon on the condition screen
// All pokemon start with 1 sparkle (added by CreateConditionSparkleSprites), so the number here +1
// is the total number of sparkles that appear
static void CalculateNumAdditionalSparkles(u8 monIndex)
{
u8 sheen = GetMonData(&gPlayerParty[monIndex], MON_DATA_SHEEN);
2020-08-10 23:05:42 +02:00
sMenu->numSparkles[sMenu->curLoadId] = (sheen != 255)
? sheen / (255 / (MAX_CONDITION_SPARKLES - 1) + 1)
: MAX_CONDITION_SPARKLES - 1;
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static void LoadConditionGfx(void)
{
struct CompressedSpriteSheet spriteSheet;
struct SpritePalette spritePalette;
2020-08-10 19:48:16 +02:00
spritePalette = sSpritePalette_Condition;
spriteSheet.data = gUsePokeblockCondition_Gfx;
spriteSheet.size = 0x800;
2020-08-10 19:48:16 +02:00
spriteSheet.tag = TAG_CONDITION;
LoadCompressedSpriteSheet(&spriteSheet);
LoadSpritePalette(&spritePalette);
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static void CreateConditionSprite(void)
{
u16 i;
s16 xDiff, xStart;
int yStart = 17;
int var = 8;
2020-08-10 19:48:16 +02:00
struct Sprite **sprites = sMenu->condition;
const struct SpriteTemplate *template = &sSpriteTemplate_Condition;
2019-02-23 18:08:07 +01:00
for (i = 0, xDiff = 64, xStart = -96; i < 2; i++)
{
u8 spriteId = CreateSprite(template, i * xDiff + xStart, yStart, 0);
if (spriteId != MAX_SPRITES)
{
gSprites[spriteId].data[0] = var;
gSprites[spriteId].data[1] = (i * xDiff) | 0x20;
gSprites[spriteId].data[2] = i;
StartSpriteAnim(&gSprites[spriteId], i);
sprites[i] = &gSprites[spriteId];
}
}
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
static bool8 LoadConditionTitle(void)
{
2020-08-10 19:48:16 +02:00
switch (sMenu->info.helperState)
{
case 0:
2020-08-10 23:05:42 +02:00
LoadConditionGfx();
2020-08-10 19:48:16 +02:00
sMenu->info.helperState++;
return TRUE;
case 1:
2020-08-10 23:05:42 +02:00
CreateConditionSprite();
2020-08-10 19:48:16 +02:00
sMenu->info.helperState = 0;
return FALSE;
}
2019-02-23 18:08:07 +01:00
return FALSE;
}
2019-02-23 18:08:07 +01:00
2020-08-10 23:05:42 +02:00
// Literally the word "Condition", the title block that appears over the mon icon
static void SpriteCB_Condition(struct Sprite *sprite)
{
2021-07-07 15:11:52 +02:00
s16 prevX = sprite->x;
2021-07-07 15:11:52 +02:00
sprite->x += sprite->data[0];
if ((prevX <= sprite->data[1] && sprite->x >= sprite->data[1])
|| (prevX >= sprite->data[1] && sprite->x <= sprite->data[1]))
{
2021-07-07 15:11:52 +02:00
sprite->x = sprite->data[1];
sprite->callback = SpriteCallbackDummy;
}
}