pokeemerald/src/party_menu.c

6356 lines
200 KiB
C
Raw Normal View History

2018-10-12 03:23:39 +02:00
#include "global.h"
#include "malloc.h"
2018-10-18 02:03:02 +02:00
#include "battle.h"
2018-12-17 08:39:17 +01:00
#include "battle_anim.h"
2018-12-07 20:47:20 +01:00
#include "battle_controllers.h"
2018-12-17 08:39:17 +01:00
#include "battle_gfx_sfx_util.h"
2018-12-07 05:14:33 +01:00
#include "battle_interface.h"
2018-12-10 08:38:23 +01:00
#include "battle_pike.h"
2018-12-13 04:55:39 +01:00
#include "battle_pyramid.h"
2018-12-17 08:39:17 +01:00
#include "battle_pyramid_bag.h"
2018-10-12 03:23:39 +02:00
#include "bg.h"
2018-10-18 02:03:02 +02:00
#include "contest.h"
2019-04-04 23:53:06 +02:00
#include "data.h"
2018-10-12 03:23:39 +02:00
#include "decompress.h"
2018-12-13 04:55:39 +01:00
#include "easy_chat.h"
2018-10-18 02:03:02 +02:00
#include "event_data.h"
2018-12-17 08:39:17 +01:00
#include "evolution_scene.h"
2018-12-13 04:55:39 +01:00
#include "field_control_avatar.h"
#include "field_effect.h"
#include "field_player_avatar.h"
2018-12-17 08:39:17 +01:00
#include "field_screen_effect.h"
2018-12-10 08:38:23 +01:00
#include "field_specials.h"
2018-12-17 08:39:17 +01:00
#include "field_weather.h"
2018-12-13 04:55:39 +01:00
#include "fieldmap.h"
2018-12-24 21:59:05 +01:00
#include "fldeff.h"
#include "fldeff_misc.h"
2018-12-17 08:39:17 +01:00
#include "frontier_util.h"
2018-10-12 03:23:39 +02:00
#include "gpu_regs.h"
#include "graphics.h"
2018-10-18 02:03:02 +02:00
#include "international_string_util.h"
2018-12-07 05:14:33 +01:00
#include "item.h"
2018-10-18 02:03:02 +02:00
#include "item_menu.h"
#include "item_use.h"
2018-12-13 04:55:39 +01:00
#include "link.h"
#include "link_rfu.h"
2018-12-07 05:14:33 +01:00
#include "mail.h"
2018-12-17 08:39:17 +01:00
#include "main.h"
2018-10-12 03:23:39 +02:00
#include "menu.h"
#include "menu_helpers.h"
#include "menu_specialized.h"
2018-12-13 04:55:39 +01:00
#include "metatile_behavior.h"
#include "overworld.h"
2018-10-12 03:23:39 +02:00
#include "palette.h"
2018-10-18 02:03:02 +02:00
#include "party_menu.h"
2019-03-05 12:06:20 +01:00
#include "player_pc.h"
2018-10-12 03:23:39 +02:00
#include "pokemon.h"
#include "pokemon_icon.h"
#include "pokemon_jump.h"
2018-12-18 11:38:08 +01:00
#include "pokemon_storage_system.h"
2018-12-10 08:38:23 +01:00
#include "pokemon_summary_screen.h"
2018-12-13 04:55:39 +01:00
#include "region_map.h"
2018-12-17 08:39:17 +01:00
#include "reshow_battle_screen.h"
2018-10-12 03:23:39 +02:00
#include "scanline_effect.h"
2018-12-18 11:38:08 +01:00
#include "script.h"
2018-10-18 02:03:02 +02:00
#include "sound.h"
2018-10-12 03:23:39 +02:00
#include "sprite.h"
2018-12-10 08:38:23 +01:00
#include "start_menu.h"
2018-10-18 02:03:02 +02:00
#include "string_util.h"
2018-10-21 02:25:28 +02:00
#include "strings.h"
2018-10-12 03:23:39 +02:00
#include "task.h"
#include "text.h"
2018-12-07 05:14:33 +01:00
#include "text_window.h"
2018-12-13 04:55:39 +01:00
#include "trade.h"
#include "union_room.h"
2018-10-12 03:23:39 +02:00
#include "window.h"
2018-12-17 08:39:17 +01:00
#include "constants/battle.h"
#include "constants/battle_frontier.h"
2019-02-27 19:45:31 +01:00
#include "constants/easy_chat.h"
2018-12-17 08:39:17 +01:00
#include "constants/field_effects.h"
2019-04-14 17:20:26 +02:00
#include "constants/item_effects.h"
2018-12-17 08:39:17 +01:00
#include "constants/items.h"
#include "constants/maps.h"
#include "constants/moves.h"
2019-10-18 01:22:03 +02:00
#include "constants/party_menu.h"
2018-12-17 08:39:17 +01:00
#include "constants/rgb.h"
#include "constants/songs.h"
2018-10-12 03:23:39 +02:00
2019-10-18 01:22:03 +02:00
#define PARTY_PAL_SELECTED (1 << 0)
#define PARTY_PAL_FAINTED (1 << 1)
#define PARTY_PAL_TO_SWITCH (1 << 2)
#define PARTY_PAL_MULTI_ALT (1 << 3)
#define PARTY_PAL_SWITCHING (1 << 4)
#define PARTY_PAL_TO_SOFTBOIL (1 << 5)
#define PARTY_PAL_NO_MON (1 << 6)
#define PARTY_PAL_UNUSED (1 << 7)
2019-10-26 03:55:01 +02:00
#define MENU_DIR_DOWN 1
#define MENU_DIR_UP -1
#define MENU_DIR_RIGHT 2
#define MENU_DIR_LEFT -2
2018-12-24 21:59:05 +01:00
enum
{
2018-12-18 11:38:08 +01:00
CAN_LEARN_MOVE,
CANNOT_LEARN_MOVE,
ALREADY_KNOWS_MOVE,
CANNOT_LEARN_MOVE_IS_EGG
};
2019-10-18 01:22:03 +02:00
struct PartyMenuBoxInfoRects
2018-12-24 21:59:05 +01:00
{
2019-10-18 01:22:03 +02:00
void (*blitFunc)(u8, u8, u8, u8, u8, u8);
u8 dimensions[24];
u8 descTextLeft;
u8 descTextTop;
u8 descTextWidth;
u8 descTextHeight;
2018-10-12 03:23:39 +02:00
};
2019-10-18 01:22:03 +02:00
struct PartyMenuInternal
2018-12-24 21:59:05 +01:00
{
2019-05-13 00:41:25 +02:00
TaskFunc task;
2018-12-18 11:38:08 +01:00
MainCallback exitCallback;
2019-10-18 01:22:03 +02:00
u32 chooseHalf:1;
2019-10-26 03:55:01 +02:00
u32 lastSelectedSlot:3; // Used to return to same slot when going left/right bewtween columns
2019-10-18 01:22:03 +02:00
u32 spriteIdConfirmPokeball:7;
u32 spriteIdCancelPokeball:7;
2019-05-13 00:41:25 +02:00
u32 messageId:14;
u8 windowId[3];
2019-05-12 18:21:19 +02:00
u8 actions[8];
2019-10-18 01:22:03 +02:00
u8 numActions;
2019-06-21 18:38:11 +02:00
// In vanilla Emerald, only the first 0xB0 hwords (0x160 bytes) are actually used.
// However, a full 0x100 hwords (0x200 bytes) are allocated.
// It is likely that the 0x160 value used below is a constant defined by
// bin2c, the utility used to encode the compressed palette data.
u16 palBuffer[BG_PLTT_SIZE / sizeof(u16)];
2018-12-18 11:38:08 +01:00
s16 data[16];
2018-10-12 03:23:39 +02:00
};
2019-10-18 01:22:03 +02:00
struct PartyMenuBox
2018-12-24 21:59:05 +01:00
{
2019-10-18 01:22:03 +02:00
const struct PartyMenuBoxInfoRects *infoRects;
const u8 *spriteCoords;
2018-12-18 11:38:08 +01:00
u8 windowId;
2019-05-13 00:41:25 +02:00
u8 monSpriteId;
u8 itemSpriteId;
u8 pokeballSpriteId;
u8 statusSpriteId;
2018-10-12 03:23:39 +02:00
};
2019-02-02 12:44:00 +01:00
// EWRAM vars
2019-10-18 01:22:03 +02:00
static EWRAM_DATA struct PartyMenuInternal *sPartyMenuInternal = NULL;
EWRAM_DATA struct PartyMenu gPartyMenu = {0};
static EWRAM_DATA struct PartyMenuBox *sPartyMenuBoxes = NULL;
static EWRAM_DATA u8 *sPartyBgGfxTilemap = NULL;
static EWRAM_DATA u8 *sPartyBgTilemapBuffer = NULL;
2019-10-26 03:55:01 +02:00
EWRAM_DATA bool8 gPartyMenuUseExitCallback = 0;
2019-10-31 19:11:55 +01:00
EWRAM_DATA u8 gSelectedMonPartyId = 0;
2018-12-18 11:38:08 +01:00
EWRAM_DATA MainCallback gPostMenuFieldCallback = NULL;
2019-10-18 01:22:03 +02:00
static EWRAM_DATA u16 *sSlot1TilemapBuffer = 0; // for switching party slots
static EWRAM_DATA u16 *sSlot2TilemapBuffer = 0; //
2020-04-09 21:18:53 +02:00
EWRAM_DATA u8 gSelectedOrderFromParty[MAX_FRONTIER_PARTY_SIZE] = {0};
2019-10-18 01:22:03 +02:00
static EWRAM_DATA u16 sPartyMenuItemId = 0;
static EWRAM_DATA u16 sUnused = 0;
2019-11-01 02:33:01 +01:00
EWRAM_DATA u8 gBattlePartyCurrentOrder[PARTY_SIZE / 2] = {0}; // bits 0-3 are the current pos of Slot 1, 4-7 are Slot 2, and so on
2018-10-12 03:23:39 +02:00
2019-02-02 12:44:00 +01:00
// IWRAM common
2019-10-18 01:22:03 +02:00
void (*gItemUseCB)(u8, TaskFunc);
2018-10-18 02:03:02 +02:00
2019-10-18 01:22:03 +02:00
static void ResetPartyMenu(void);
static void CB2_InitPartyMenu(void);
static bool8 ShowPartyMenu(void);
static void SetPartyMonsAllowedInMinigame(void);
static void ExitPartyMenu(void);
2018-12-24 00:02:29 +01:00
static bool8 AllocPartyMenuBg(void);
2019-10-18 01:22:03 +02:00
static bool8 AllocPartyMenuBgGfx(void);
static void InitPartyMenuWindows(u8);
static void InitPartyMenuBoxes(u8);
2018-12-24 00:02:29 +01:00
static void LoadPartyMenuPokeballGfx(void);
static void LoadPartyMenuAilmentGfx(void);
2019-10-26 03:55:01 +02:00
static bool8 CreatePartyMonSpritesLoop(void);
2018-12-24 00:02:29 +01:00
static bool8 RenderPartyMenuBoxes(void);
2019-10-18 01:22:03 +02:00
static void CreateCancelConfirmPokeballSprites(void);
2019-10-26 03:55:01 +02:00
static void CreateCancelConfirmWindows(u8);
2019-10-18 01:22:03 +02:00
static void Task_ExitPartyMenu(u8);
2018-12-24 00:02:29 +01:00
static void FreePartyPointers(void);
static void PartyPaletteBufferCopy(u8);
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDataForMultiBattle(u8);
static void LoadPartyBoxPalette(struct PartyMenuBox *, u8);
2019-05-13 00:41:25 +02:00
static void DrawEmptySlot(u8 windowId);
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDataForRelearner(u8);
static void DisplayPartyPokemonDataForContest(u8);
static void DisplayPartyPokemonDataForChooseHalf(u8);
static void DisplayPartyPokemonDataForWirelessMinigame(u8);
static void DisplayPartyPokemonDataForBattlePyramidHeldItem(u8);
static bool8 DisplayPartyPokemonDataForMoveTutorOrEvolutionItem(u8);
2018-12-24 00:02:29 +01:00
static void DisplayPartyPokemonData(u8);
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonNickname(struct Pokemon *, struct PartyMenuBox *, u8);
static void DisplayPartyPokemonLevelCheck(struct Pokemon *, struct PartyMenuBox *, u8);
static void DisplayPartyPokemonGenderNidoranCheck(struct Pokemon *, struct PartyMenuBox *, u8);
static void DisplayPartyPokemonHPCheck(struct Pokemon *, struct PartyMenuBox *, u8);
static void DisplayPartyPokemonMaxHPCheck(struct Pokemon *, struct PartyMenuBox *, u8);
static void DisplayPartyPokemonHPBarCheck(struct Pokemon *, struct PartyMenuBox *);
static void DisplayPartyPokemonDescriptionText(u8, struct PartyMenuBox *, u8);
static bool8 IsMonAllowedInMinigame(u8);
static void DisplayPartyPokemonDataToTeachMove(u8, u16, u8);
2018-12-24 21:59:05 +01:00
static u8 CanMonLearnTMTutor(struct Pokemon *, u16, u8);
static void DisplayPartyPokemonBarDetail(u8, const u8*, u8, const u8*);
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonLevel(u8, struct PartyMenuBox *);
static void DisplayPartyPokemonGender(u8, u16, u8*, struct PartyMenuBox *);
static void DisplayPartyPokemonHP(u16, struct PartyMenuBox *);
static void DisplayPartyPokemonMaxHP(u16, struct PartyMenuBox *);
static void DisplayPartyPokemonHPBar(u16, u16, struct PartyMenuBox *);
2019-10-26 03:55:01 +02:00
static void CreatePartyMonIconSpriteParameterized(u16, u32, struct PartyMenuBox *, u8, u32);
static void CreatePartyMonHeldItemSpriteParameterized(u16, u16, struct PartyMenuBox *);
static void CreatePartyMonPokeballSpriteParameterized(u16, struct PartyMenuBox *);
static void CreatePartyMonStatusSpriteParameterized(u16, u8, struct PartyMenuBox *);
// These next 4 functions are essentially redundant with the above 4
// The only difference is that rather than receive the data directly they retrieve it from the mon struct
static void CreatePartyMonHeldItemSprite(struct Pokemon *, struct PartyMenuBox *);
static void CreatePartyMonPokeballSprite(struct Pokemon *, struct PartyMenuBox *);
static void CreatePartyMonIconSprite(struct Pokemon *, struct PartyMenuBox *, u32);
static void CreatePartyMonStatusSprite(struct Pokemon *, struct PartyMenuBox *);
static u8 CreateSmallPokeballButtonSprite(u8, u8);
static void DrawCancelConfirmButtons(void);
static u8 CreatePokeballButtonSprite(u8, u8);
2018-12-24 00:02:29 +01:00
static void AnimateSelectedPartyIcon(u8, u8);
2019-10-18 01:22:03 +02:00
static void PartyMenuStartSpriteAnim(u8, u8);
static u8 GetPartyBoxPaletteFlags(u8, u8);
2018-12-24 00:02:29 +01:00
static bool8 PartyBoxPal_ParnterOrDisqualifiedInArena(u8);
2019-10-18 01:22:03 +02:00
static u8 GetPartyIdFromBattleSlot(u8);
static void Task_ClosePartyMenuAndSetCB2(u8);
2019-10-18 01:22:03 +02:00
static void UpdatePartyToFieldOrder(void);
2019-10-26 03:55:01 +02:00
static void MoveCursorToConfirm(void);
2019-10-18 01:22:03 +02:00
static void HandleChooseMonCancel(u8, s8*);
static void HandleChooseMonSelection(u8, s8*);
2018-12-24 00:02:29 +01:00
static u16 PartyMenuButtonHandler(s8*);
2019-10-18 01:22:03 +02:00
static s8* GetCurrentPartySlotPtr(void);
static bool8 IsSelectedMonNotEgg(u8*);
static void PartyMenuRemoveWindow(u8*);
2019-10-18 01:22:03 +02:00
static void CB2_SetUpExitToBattleScreen(void);
static void Task_ClosePartyMenuAfterText(u8);
static void TryTutorSelectedMon(u8);
static void TryGiveMailToSelectedMon(u8);
2019-10-26 03:55:01 +02:00
static void TryGiveItemOrMailToSelectedMon(u8);
2019-10-18 01:22:03 +02:00
static void SwitchSelectedMons(u8);
static void TryEnterMonForMinigame(u8, u8);
static void Task_TryCreateSelectionWindow(u8);
static void FinishTwoMonAction(u8);
static void CancelParticipationPrompt(u8);
static bool8 DisplayCancelChooseMonYesNo(u8);
static const u8* GetFacilityCancelString(void);
static void Task_CancelChooseMonYesNo(u8);
static void PartyMenuDisplayYesNoMenu(void);
static void Task_HandleCancelChooseMonYesNoInput(u8);
static void Task_ReturnToChooseMonAfterText(u8);
2018-12-24 00:02:29 +01:00
static void UpdateCurrentPartySelection(s8*, s8);
2019-10-18 01:22:03 +02:00
static void UpdatePartySelectionSingleLayout(s8*, s8);
static void UpdatePartySelectionDoubleLayout(s8*, s8);
2019-10-26 03:55:01 +02:00
static s8 GetNewSlotDoubleLayout(s8, s8);
static void PartyMenuPrintText(const u8*);
2019-10-18 01:22:03 +02:00
static void Task_PrintAndWaitForText(u8);
2019-10-11 10:14:09 +02:00
static bool16 IsMonAllowedInPokemonJump(struct Pokemon*);
2019-10-18 01:22:03 +02:00
static bool16 IsMonAllowedInDodrioBerryPicking(struct Pokemon*);
static void Task_CancelParticipationYesNo(u8);
static void Task_HandleCancelParticipationYesNoInput(u8);
2018-12-24 21:59:05 +01:00
static bool8 CanLearnTutorMove(u16, u8);
static u16 GetTutorMove(u8);
2019-10-26 03:55:01 +02:00
static bool8 ShouldUseChooseMonText(void);
2019-10-18 01:22:03 +02:00
static void SetPartyMonFieldSelectionActions(struct Pokemon*, u8);
static u8 GetPartyMenuActionsTypeInBattle(struct Pokemon*);
static u8 GetPartySlotEntryStatus(s8);
static void Task_UpdateHeldItemSprite(u8);
static void Task_HandleSelectionMenuInput(u8);
static void CB2_ShowPokemonSummaryScreen(void);
static void UpdatePartyToBattleOrder(void);
static void CB2_ReturnToPartyMenuFromSummaryScreen(void);
static void SlidePartyMenuBoxOneStep(u8);
static void Task_SlideSelectedSlotsOffscreen(u8);
static void SwitchPartyMon(void);
static void Task_SlideSelectedSlotsOnscreen(u8);
static void CB2_SelectBagItemToGive(void);
static void CB2_GiveHoldItem(void);
static void CB2_WriteMailToGiveMon(void);
static void Task_SwitchHoldItemsPrompt(u8);
static void Task_GiveHoldItem(u8);
static void Task_SwitchItemsYesNo(u8);
static void Task_HandleSwitchItemsYesNoInput(u8);
static void Task_WriteMailToGiveMonAfterText(u8);
static void CB2_ReturnToPartyMenuFromWritingMail(void);
2019-10-26 03:55:01 +02:00
static void Task_DisplayGaveMailFromPartyMessage(u8);
2019-10-18 01:22:03 +02:00
static void UpdatePartyMonHeldItemSprite(struct Pokemon*, struct PartyMenuBox*);
static void Task_TossHeldItemYesNo(u8 taskId);
static void Task_HandleTossHeldItemYesNoInput(u8);
static void Task_TossHeldItem(u8);
2019-10-26 03:55:01 +02:00
static void CB2_ReadHeldMail(void);
static void CB2_ReturnToPartyMenuFromReadingMail(void);
static void Task_SendMailToPCYesNo(u8);
static void Task_HandleSendMailToPCYesNoInput(u8);
static void Task_LoseMailMessageYesNo(u8);
static void Task_HandleLoseMailMessageYesNoInput(u8);
2019-10-18 01:22:03 +02:00
static bool8 TrySwitchInPokemon(void);
static void Task_SpinTradeYesNo(u8);
static void Task_HandleSpinTradeYesNoInput(u8);
static void Task_CancelAfterAorBPress(u8);
static void DisplayFieldMoveExitAreaMessage(u8);
static void DisplayCantUseFlashMessage(void);
static void DisplayCantUseSurfMessage(void);
static void Task_FieldMoveExitAreaYesNo(u8);
static void Task_HandleFieldMoveExitAreaYesNoInput(u8);
static void Task_FieldMoveWaitForFade(u8);
static u16 GetFieldMoveMonSpecies(void);
static void UpdatePartyMonHPBar(u8, struct Pokemon*);
2019-10-26 03:55:01 +02:00
static void SpriteCB_UpdatePartyMonIcon(struct Sprite*);
static void SpriteCB_BouncePartyMonIcon(struct Sprite*);
2019-10-18 01:22:03 +02:00
static void ShowOrHideHeldItemSprite(u16, struct PartyMenuBox*);
2019-10-07 04:58:25 +02:00
static void CreateHeldItemSpriteForTrade(u8, bool8);
2019-05-13 00:41:25 +02:00
static void SpriteCB_HeldItem(struct Sprite*);
2019-10-18 01:22:03 +02:00
static void SetPartyMonAilmentGfx(struct Pokemon*, struct PartyMenuBox*);
static void UpdatePartyMonAilmentGfx(u8, struct PartyMenuBox*);
static u8 GetPartyLayoutFromBattleType(void);
2019-10-26 03:55:01 +02:00
static void Task_SetSacredAshCB(u8);
2019-10-18 01:22:03 +02:00
static void CB2_ReturnToBagMenu(void);
static void Task_DisplayHPRestoredMessage(u8);
2019-04-14 17:20:26 +02:00
static u16 ItemEffectToMonEv(struct Pokemon*, u8);
static void ItemEffectToStatString(u8, u8*);
2019-10-18 01:22:03 +02:00
static void ReturnToUseOnWhichMon(u8);
static void SetSelectedMoveForPPItem(u8);
static void TryUsePPItem(u8);
static void Task_LearnedMove(u8);
static void Task_ReplaceMoveYesNo(u8);
static void Task_DoLearnedMoveFanfareAfterText(u8);
static void Task_LearnNextMoveOrClosePartyMenu(u8);
static void Task_TryLearningNextMove(u8);
static void Task_HandleReplaceMoveYesNoInput(u8);
static void Task_ShowSummaryScreenToForgetMove(u8);
static void StopLearningMovePrompt(u8);
static void CB2_ShowSummaryScreenToForgetMove(void);
static void CB2_ReturnToPartyMenuWhileLearningMove(void);
static void Task_ReturnToPartyMenuWhileLearningMove(u8);
static void DisplayPartyMenuForgotMoveMessage(u8);
static void Task_PartyMenuReplaceMove(u8);
static void Task_StopLearningMoveYesNo(u8);
static void Task_HandleStopLearningMoveYesNoInput(u8);
static void Task_TryLearningNextMoveAfterText(u8);
static void BufferMonStatsToTaskData(struct Pokemon*, s16*);
static void UpdateMonDisplayInfoAfterRareCandy(u8, struct Pokemon*);
static void Task_DisplayLevelUpStatsPg1(u8);
static void DisplayLevelUpStatsPg1(u8);
static void Task_DisplayLevelUpStatsPg2(u8);
static void DisplayLevelUpStatsPg2(u8);
static void Task_TryLearnNewMoves(u8);
static void PartyMenuTryEvolution(u8);
static void DisplayMonNeedsToReplaceMove(u8);
static void DisplayMonLearnedMove(u8, u16);
2019-10-26 03:55:01 +02:00
static void UseSacredAsh(u8);
static void Task_SacredAshLoop(u8);
2019-10-18 01:22:03 +02:00
static void Task_SacredAshDisplayHPRestored(u8);
2019-10-26 03:55:01 +02:00
static void GiveItemOrMailToSelectedMon(u8);
static void DisplayItemMustBeRemovedFirstMessage(u8);
static void Task_SwitchItemsFromBagYesNo(u8);
2019-10-18 01:22:03 +02:00
static void RemoveItemToGiveFromBag(u16);
static void CB2_WriteMailToGiveMonFromBag(void);
2019-10-26 03:55:01 +02:00
static void GiveItemToSelectedMon(u8);
2019-10-18 01:22:03 +02:00
static void Task_UpdateHeldItemSpriteAndClosePartyMenu(u8);
static void CB2_ReturnToPartyOrBagMenuFromWritingMail(void);
2019-10-26 03:55:01 +02:00
static bool8 ReturnGiveItemToBagOrPC(u16);
static void Task_DisplayGaveMailFromBagMessage(u8);
static void Task_HandleSwitchItemsFromBagYesNoInput(u8);
2019-10-18 01:22:03 +02:00
static void Task_ValidateChosenHalfParty(u8);
2018-12-24 00:02:29 +01:00
static bool8 GetBattleEntryEligibility(struct Pokemon*);
2019-10-18 01:22:03 +02:00
static bool8 HasPartySlotAlreadyBeenSelected(u8);
static u8 GetBattleEntryLevelCap(void);
static u8 GetMaxBattleEntries(void);
static u8 GetMinBattleEntries(void);
static void Task_ContinueChoosingHalfParty(u8);
2019-10-31 19:11:55 +01:00
static void BufferBattlePartyOrder(u8*, bool8);
static void BufferBattlePartyOrderBySide(u8*, u8, u8);
2019-10-18 01:22:03 +02:00
static void Task_InitMultiPartnerPartySlideIn(u8);
static void Task_MultiPartnerPartySlideIn(u8);
static void SlideMultiPartyMenuBoxSpritesOneStep(u8);
static void Task_WaitAfterMultiPartnerPartySlideIn(u8);
static void BufferMonSelection(void);
static void Task_PartyMenuWaitForFade(u8 taskId);
static void Task_ChooseContestMon(u8 taskId);
static void CB2_ChooseContestMon(void);
static void Task_ChoosePartyMon(u8 taskId);
2019-10-31 19:11:55 +01:00
static void Task_ChooseMonForMoveRelearner(u8);
2019-10-18 01:22:03 +02:00
static void CB2_ChooseMonForMoveRelearner(void);
2019-10-31 19:11:55 +01:00
static void Task_BattlePyramidChooseMonHeldItems(u8);
2019-10-18 01:22:03 +02:00
static void ShiftMoveSlot(struct Pokemon*, u8, u8);
2019-10-31 19:11:55 +01:00
static void BlitBitmapToPartyWindow_LeftColumn(u8, u8, u8, u8, u8, u8);
static void BlitBitmapToPartyWindow_RightColumn(u8, u8, u8, u8, u8, u8);
static void CursorCb_Summary(u8);
static void CursorCb_Switch(u8);
static void CursorCb_Cancel1(u8);
static void CursorCb_Item(u8);
static void CursorCb_Give(u8);
static void CursorCb_TakeItem(u8);
static void CursorCb_Mail(u8);
static void CursorCb_Read(u8);
static void CursorCb_TakeMail(u8);
static void CursorCb_Cancel2(u8);
static void CursorCb_SendMon(u8);
static void CursorCb_Enter(u8);
static void CursorCb_NoEntry(u8);
static void CursorCb_Store(u8);
static void CursorCb_Register(u8);
static void CursorCb_Trade1(u8);
static void CursorCb_Trade2(u8);
static void CursorCb_Toss(u8);
static void CursorCb_FieldMove(u8);
2018-12-24 21:59:05 +01:00
static bool8 SetUpFieldMove_Surf(void);
static bool8 SetUpFieldMove_Fly(void);
static bool8 SetUpFieldMove_Waterfall(void);
static bool8 SetUpFieldMove_Dive(void);
// static const data
#include "data/pokemon/tutor_learnsets.h"
2019-10-31 19:16:43 +01:00
#include "data/party_menu.h"
2018-12-24 21:59:05 +01:00
// code
2019-10-18 01:22:03 +02:00
static void InitPartyMenu(u8 menuType, u8 layout, u8 partyAction, bool8 keepCursorPos, u8 messageId, TaskFunc task, MainCallback callback)
2018-10-12 03:23:39 +02:00
{
u16 i;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
ResetPartyMenu();
sPartyMenuInternal = Alloc(sizeof(struct PartyMenuInternal));
if (sPartyMenuInternal == NULL)
2018-10-12 03:23:39 +02:00
{
2018-12-18 11:38:08 +01:00
SetMainCallback2(callback);
2018-10-12 03:23:39 +02:00
}
else
{
2019-10-18 01:22:03 +02:00
gPartyMenu.menuType = menuType;
gPartyMenu.exitCallback = callback;
gPartyMenu.action = partyAction;
sPartyMenuInternal->messageId = messageId;
sPartyMenuInternal->task = task;
sPartyMenuInternal->exitCallback = NULL;
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->lastSelectedSlot = 0;
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->spriteIdConfirmPokeball = 0x7F;
sPartyMenuInternal->spriteIdCancelPokeball = 0x7F;
if (menuType == PARTY_MENU_TYPE_CHOOSE_HALF)
sPartyMenuInternal->chooseHalf = TRUE;
2018-10-12 03:23:39 +02:00
else
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->chooseHalf = FALSE;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (layout != KEEP_PARTY_LAYOUT)
gPartyMenu.layout = layout;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
for (i = 0; i < ARRAY_COUNT(sPartyMenuInternal->data); i++)
sPartyMenuInternal->data[i] = 0;
for (i = 0; i < ARRAY_COUNT(sPartyMenuInternal->windowId); i++)
sPartyMenuInternal->windowId[i] = 0xFF;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (!keepCursorPos)
gPartyMenu.slotId = 0;
else if (gPartyMenu.slotId > PARTY_SIZE - 1 || GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES) == SPECIES_NONE)
gPartyMenu.slotId = 0;
2018-12-22 17:32:21 +01:00
2018-12-07 20:47:20 +01:00
gTextFlags.autoScroll = 0;
2018-10-12 03:23:39 +02:00
CalculatePlayerPartyCount();
2019-10-18 01:22:03 +02:00
SetMainCallback2(CB2_InitPartyMenu);
2018-10-12 03:23:39 +02:00
}
}
2019-10-18 01:22:03 +02:00
static void CB2_UpdatePartyMenu(void)
2018-10-12 03:23:39 +02:00
{
RunTasks();
AnimateSprites();
BuildOamBuffer();
DoScheduledBgTilemapCopiesToVram();
2018-10-12 03:23:39 +02:00
UpdatePaletteFade();
}
2019-10-18 01:22:03 +02:00
static void VBlankCB_PartyMenu(void)
2018-10-12 03:23:39 +02:00
{
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
}
2019-10-18 01:22:03 +02:00
static void CB2_InitPartyMenu(void)
2018-10-12 03:23:39 +02:00
{
while (TRUE)
{
2020-05-14 10:37:09 +02:00
if (MenuHelpers_CallLinkSomething() == TRUE || ShowPartyMenu() == TRUE || MenuHelpers_LinkSomething() == TRUE)
2018-10-12 03:23:39 +02:00
break;
}
}
2019-10-18 01:22:03 +02:00
static bool8 ShowPartyMenu(void)
2018-10-12 03:23:39 +02:00
{
switch (gMain.state)
{
2018-12-22 17:32:21 +01:00
case 0:
SetVBlankHBlankCallbacksToNull();
ResetVramOamAndBgCntRegs();
ClearScheduledBgCopiesToVram();
2018-12-22 17:32:21 +01:00
gMain.state++;
break;
case 1:
ScanlineEffect_Stop();
gMain.state++;
break;
case 2:
ResetPaletteFade();
gPaletteFade.bufferTransferDisabled = TRUE;
gMain.state++;
break;
case 3:
ResetSpriteData();
gMain.state++;
break;
case 4:
FreeAllSpritePalettes();
gMain.state++;
break;
case 5:
2020-05-14 10:37:09 +02:00
if (!MenuHelpers_LinkSomething())
2018-12-22 17:32:21 +01:00
ResetTasks();
gMain.state++;
break;
case 6:
2019-10-18 01:22:03 +02:00
SetPartyMonsAllowedInMinigame();
2018-12-22 17:32:21 +01:00
gMain.state++;
break;
case 7:
if (!AllocPartyMenuBg())
{
2019-10-18 01:22:03 +02:00
ExitPartyMenu();
2018-12-22 17:32:21 +01:00
return TRUE;
}
else
{
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->data[0] = 0;
2018-10-12 03:23:39 +02:00
gMain.state++;
2018-12-22 17:32:21 +01:00
}
break;
case 8:
2019-10-18 01:22:03 +02:00
if (AllocPartyMenuBgGfx())
2018-10-12 03:23:39 +02:00
gMain.state++;
2018-12-22 17:32:21 +01:00
break;
case 9:
2019-10-18 01:22:03 +02:00
InitPartyMenuWindows(gPartyMenu.layout);
2018-12-22 17:32:21 +01:00
gMain.state++;
break;
case 10:
2019-10-18 01:22:03 +02:00
InitPartyMenuBoxes(gPartyMenu.layout);
sPartyMenuInternal->data[0] = 0;
2018-12-22 17:32:21 +01:00
gMain.state++;
break;
case 11:
LoadHeldItemIcons();
gMain.state++;
break;
case 12:
LoadPartyMenuPokeballGfx();
gMain.state++;
break;
case 13:
LoadPartyMenuAilmentGfx();
gMain.state++;
break;
case 14:
LoadMonIconPalettes();
gMain.state++;
break;
case 15:
2019-10-26 03:55:01 +02:00
if (CreatePartyMonSpritesLoop())
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->data[0] = 0;
2018-10-12 03:23:39 +02:00
gMain.state++;
2018-12-22 17:32:21 +01:00
}
break;
case 16:
if (RenderPartyMenuBoxes())
{
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->data[0] = 0;
2018-10-12 03:23:39 +02:00
gMain.state++;
2018-12-22 17:32:21 +01:00
}
break;
case 17:
2019-10-18 01:22:03 +02:00
CreateCancelConfirmPokeballSprites();
2018-12-22 17:32:21 +01:00
gMain.state++;
break;
case 18:
2019-10-26 03:55:01 +02:00
CreateCancelConfirmWindows(sPartyMenuInternal->chooseHalf);
2018-12-22 17:32:21 +01:00
gMain.state++;
break;
case 19:
gMain.state++;
break;
case 20:
2019-10-18 01:22:03 +02:00
CreateTask(sPartyMenuInternal->task, 0);
DisplayPartyMenuStdMessage(sPartyMenuInternal->messageId);
2018-12-22 17:32:21 +01:00
gMain.state++;
break;
case 21:
BlendPalettes(0xFFFFFFFF, 16, 0);
gPaletteFade.bufferTransferDisabled = FALSE;
gMain.state++;
break;
case 22:
BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
gMain.state++;
break;
default:
2019-10-18 01:22:03 +02:00
SetVBlankCallback(VBlankCB_PartyMenu);
SetMainCallback2(CB2_UpdatePartyMenu);
2018-12-22 17:32:21 +01:00
return TRUE;
2018-10-12 03:23:39 +02:00
}
return FALSE;
}
2019-10-18 01:22:03 +02:00
static void ExitPartyMenu(void)
2018-10-12 03:23:39 +02:00
{
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
2019-10-18 01:22:03 +02:00
CreateTask(Task_ExitPartyMenu, 0);
SetVBlankCallback(VBlankCB_PartyMenu);
SetMainCallback2(CB2_UpdatePartyMenu);
2018-10-12 03:23:39 +02:00
}
2019-10-18 01:22:03 +02:00
static void Task_ExitPartyMenu(u8 taskId)
2018-10-12 03:23:39 +02:00
{
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
SetMainCallback2(gPartyMenu.exitCallback);
2018-12-18 11:38:08 +01:00
FreePartyPointers();
2018-10-12 03:23:39 +02:00
DestroyTask(taskId);
}
}
2019-10-18 01:22:03 +02:00
static void ResetPartyMenu(void)
2018-10-12 03:23:39 +02:00
{
2019-10-18 01:22:03 +02:00
sPartyMenuInternal = NULL;
sPartyBgTilemapBuffer = NULL;
sPartyMenuBoxes = NULL;
sPartyBgGfxTilemap = NULL;
2018-10-12 03:23:39 +02:00
}
2018-12-24 00:02:29 +01:00
static bool8 AllocPartyMenuBg(void)
2018-10-12 03:23:39 +02:00
{
2019-10-18 01:22:03 +02:00
sPartyBgTilemapBuffer = Alloc(0x800);
if (sPartyBgTilemapBuffer == NULL)
2018-10-12 03:23:39 +02:00
return FALSE;
2018-12-24 21:59:05 +01:00
2019-10-18 01:22:03 +02:00
memset(sPartyBgTilemapBuffer, 0, 0x800);
2018-10-12 03:23:39 +02:00
ResetBgsAndClearDma3BusyFlags(0);
2019-10-18 01:22:03 +02:00
InitBgsFromTemplates(0, sPartyMenuBgTemplates, ARRAY_COUNT(sPartyMenuBgTemplates));
SetBgTilemapBuffer(1, sPartyBgTilemapBuffer);
2018-10-12 03:23:39 +02:00
ResetAllBgsCoordinates();
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(1);
2018-10-12 03:23:39 +02:00
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
SetGpuReg(REG_OFFSET_BLDCNT, 0);
ShowBg(0);
ShowBg(1);
ShowBg(2);
return TRUE;
}
2019-10-18 01:22:03 +02:00
static bool8 AllocPartyMenuBgGfx(void)
2018-10-12 03:23:39 +02:00
{
2019-07-19 02:46:00 +02:00
u32 sizeout;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
switch (sPartyMenuInternal->data[0])
2018-10-12 03:23:39 +02:00
{
2018-12-22 17:32:21 +01:00
case 0:
2019-10-18 01:22:03 +02:00
sPartyBgGfxTilemap = malloc_and_decompress(gPartyMenuBg_Gfx, &sizeout);
LoadBgTiles(1, sPartyBgGfxTilemap, sizeout, 0);
sPartyMenuInternal->data[0]++;
2018-12-22 17:32:21 +01:00
break;
case 1:
if (!IsDma3ManagerBusyWithBgCopy())
{
2019-10-18 01:22:03 +02:00
LZDecompressWram(gPartyMenuBg_Tilemap, sPartyBgTilemapBuffer);
sPartyMenuInternal->data[0]++;
2018-12-22 17:32:21 +01:00
}
break;
case 2:
2019-10-18 01:22:03 +02:00
LoadCompressedPalette(gPartyMenuBg_Pal, 0, 0x160);
CpuCopy16(gPlttBufferUnfaded, sPartyMenuInternal->palBuffer, 0x160);
sPartyMenuInternal->data[0]++;
2018-12-22 17:32:21 +01:00
break;
case 3:
PartyPaletteBufferCopy(4);
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->data[0]++;
2018-12-22 17:32:21 +01:00
break;
case 4:
PartyPaletteBufferCopy(5);
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->data[0]++;
2018-12-22 17:32:21 +01:00
break;
case 5:
PartyPaletteBufferCopy(6);
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->data[0]++;
2018-12-22 17:32:21 +01:00
break;
case 6:
PartyPaletteBufferCopy(7);
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->data[0]++;
2018-12-22 17:32:21 +01:00
break;
case 7:
PartyPaletteBufferCopy(8);
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->data[0]++;
2018-12-22 17:32:21 +01:00
break;
default:
return TRUE;
2018-10-12 03:23:39 +02:00
}
return FALSE;
}
2018-12-24 00:02:29 +01:00
static void PartyPaletteBufferCopy(u8 offset)
2018-10-12 03:23:39 +02:00
{
offset *= 16;
CpuCopy16(&gPlttBufferUnfaded[0x30], &gPlttBufferUnfaded[offset], 32);
CpuCopy16(&gPlttBufferUnfaded[0x30], &gPlttBufferFaded[offset], 32);
}
2018-12-24 00:02:29 +01:00
static void FreePartyPointers(void)
2018-10-12 03:23:39 +02:00
{
2019-10-18 01:22:03 +02:00
if (sPartyMenuInternal)
Free(sPartyMenuInternal);
if (sPartyBgTilemapBuffer)
Free(sPartyBgTilemapBuffer);
if (sPartyBgGfxTilemap)
Free(sPartyBgGfxTilemap);
if (sPartyMenuBoxes)
Free(sPartyMenuBoxes);
2018-10-12 03:23:39 +02:00
FreeAllWindowBuffers();
}
2019-10-18 01:22:03 +02:00
static void InitPartyMenuBoxes(u8 layout)
2018-10-12 03:23:39 +02:00
{
u8 i;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
sPartyMenuBoxes = Alloc(sizeof(struct PartyMenuBox[PARTY_SIZE]));
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
for (i = 0; i < PARTY_SIZE; i++)
2018-10-12 03:23:39 +02:00
{
2019-10-18 01:22:03 +02:00
sPartyMenuBoxes[i].infoRects = &sPartyBoxInfoRects[PARTY_BOX_RIGHT_COLUMN];
sPartyMenuBoxes[i].spriteCoords = sPartyMenuSpriteCoords[layout][i];
sPartyMenuBoxes[i].windowId = i;
sPartyMenuBoxes[i].monSpriteId = 0xFF;
sPartyMenuBoxes[i].itemSpriteId = 0xFF;
sPartyMenuBoxes[i].pokeballSpriteId = 0xFF;
sPartyMenuBoxes[i].statusSpriteId = 0xFF;
2018-10-12 03:23:39 +02:00
}
2019-10-18 01:22:03 +02:00
// The first party mon goes in the left column
sPartyMenuBoxes[0].infoRects = &sPartyBoxInfoRects[PARTY_BOX_LEFT_COLUMN];
if (layout == PARTY_LAYOUT_MULTI_SHOWCASE)
sPartyMenuBoxes[3].infoRects = &sPartyBoxInfoRects[PARTY_BOX_LEFT_COLUMN];
else if (layout != PARTY_LAYOUT_SINGLE)
sPartyMenuBoxes[1].infoRects = &sPartyBoxInfoRects[PARTY_BOX_LEFT_COLUMN];
2018-10-12 03:23:39 +02:00
}
2018-12-24 00:02:29 +01:00
static void RenderPartyMenuBox(u8 slot)
2018-10-12 03:23:39 +02:00
{
2019-11-01 02:33:01 +01:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_MULTI_SHOWCASE && slot >= MULTI_PARTY_SIZE)
2018-10-12 03:23:39 +02:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDataForMultiBattle(slot);
2019-11-01 02:33:01 +01:00
if (gMultiPartnerParty[slot - MULTI_PARTY_SIZE].species == SPECIES_NONE)
2019-10-18 01:22:03 +02:00
LoadPartyBoxPalette(&sPartyMenuBoxes[slot], PARTY_PAL_NO_MON);
2018-10-12 03:23:39 +02:00
else
2019-10-18 01:22:03 +02:00
LoadPartyBoxPalette(&sPartyMenuBoxes[slot], PARTY_PAL_MULTI_ALT);
CopyWindowToVram(sPartyMenuBoxes[slot].windowId, 2);
PutWindowTilemap(sPartyMenuBoxes[slot].windowId);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-10-12 03:23:39 +02:00
}
else
{
2018-10-18 02:03:02 +02:00
if (GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES) == SPECIES_NONE)
2018-10-12 03:23:39 +02:00
{
2019-10-18 01:22:03 +02:00
DrawEmptySlot(sPartyMenuBoxes[slot].windowId);
LoadPartyBoxPalette(&sPartyMenuBoxes[slot], PARTY_PAL_NO_MON);
CopyWindowToVram(sPartyMenuBoxes[slot].windowId, 2);
2018-10-12 03:23:39 +02:00
}
else
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_MOVE_RELEARNER)
DisplayPartyPokemonDataForRelearner(slot);
else if (gPartyMenu.menuType == PARTY_MENU_TYPE_CONTEST)
DisplayPartyPokemonDataForContest(slot);
else if (gPartyMenu.menuType == PARTY_MENU_TYPE_CHOOSE_HALF)
DisplayPartyPokemonDataForChooseHalf(slot);
else if (gPartyMenu.menuType == PARTY_MENU_TYPE_MINIGAME)
DisplayPartyPokemonDataForWirelessMinigame(slot);
else if (gPartyMenu.menuType == PARTY_MENU_TYPE_STORE_PYRAMID_HELD_ITEMS)
DisplayPartyPokemonDataForBattlePyramidHeldItem(slot);
else if (!DisplayPartyPokemonDataForMoveTutorOrEvolutionItem(slot))
2018-12-18 11:38:08 +01:00
DisplayPartyPokemonData(slot);
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_MULTI_SHOWCASE)
2019-10-18 01:22:03 +02:00
AnimatePartySlot(slot, 0);
else if (gPartyMenu.slotId == slot)
AnimatePartySlot(slot, 1);
2018-10-12 03:23:39 +02:00
else
2019-10-18 01:22:03 +02:00
AnimatePartySlot(slot, 0);
2018-10-12 03:23:39 +02:00
}
2019-10-18 01:22:03 +02:00
PutWindowTilemap(sPartyMenuBoxes[slot].windowId);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2018-10-12 03:23:39 +02:00
}
}
2018-12-24 00:02:29 +01:00
static void DisplayPartyPokemonData(u8 slot)
2018-10-18 02:03:02 +02:00
{
if (GetMonData(&gPlayerParty[slot], MON_DATA_IS_EGG))
{
2019-10-18 01:22:03 +02:00
sPartyMenuBoxes[slot].infoRects->blitFunc(sPartyMenuBoxes[slot].windowId, 0, 0, 0, 0, TRUE);
DisplayPartyPokemonNickname(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
2018-10-18 02:03:02 +02:00
}
else
{
2019-10-18 01:22:03 +02:00
sPartyMenuBoxes[slot].infoRects->blitFunc(sPartyMenuBoxes[slot].windowId, 0, 0, 0, 0, FALSE);
DisplayPartyPokemonNickname(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
DisplayPartyPokemonLevelCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
DisplayPartyPokemonGenderNidoranCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
DisplayPartyPokemonHPCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
DisplayPartyPokemonMaxHPCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
DisplayPartyPokemonHPBarCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
2018-10-18 02:03:02 +02:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDescriptionData(u8 slot, u8 stringID)
2018-10-18 02:03:02 +02:00
{
2018-12-18 11:38:08 +01:00
struct Pokemon *mon = &gPlayerParty[slot];
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
sPartyMenuBoxes[slot].infoRects->blitFunc(sPartyMenuBoxes[slot].windowId, 0, 0, 0, 0, TRUE);
DisplayPartyPokemonNickname(mon, &sPartyMenuBoxes[slot], 0);
2018-12-18 11:38:08 +01:00
if (!GetMonData(mon, MON_DATA_IS_EGG))
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonLevelCheck(mon, &sPartyMenuBoxes[slot], 0);
DisplayPartyPokemonGenderNidoranCheck(mon, &sPartyMenuBoxes[slot], 0);
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionText(stringID, &sPartyMenuBoxes[slot], 0);
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDataForChooseHalf(u8 slot)
2018-10-18 02:03:02 +02:00
{
u8 i;
2018-12-18 11:38:08 +01:00
struct Pokemon *mon = &gPlayerParty[slot];
2019-10-18 01:22:03 +02:00
u8 *order = gSelectedOrderFromParty;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
if (!GetBattleEntryEligibility(mon))
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NOT_ABLE);
2018-10-18 02:03:02 +02:00
return;
}
else
{
2019-10-18 01:22:03 +02:00
for (i = 0; i < GetMaxBattleEntries(); i++)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
if (order[i] != 0 && (order[i] - 1) == slot)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, i + PARTYBOX_DESC_FIRST);
2018-10-18 02:03:02 +02:00
return;
}
}
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_ABLE_3);
2018-10-18 02:03:02 +02:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDataForContest(u8 slot)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
switch (GetContestEntryEligibility(&gPlayerParty[slot]))
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
case CANT_ENTER_CONTEST:
case CANT_ENTER_CONTEST_EGG:
case CANT_ENTER_CONTEST_FAINTED:
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NOT_ABLE);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case CAN_ENTER_CONTEST_EQUAL_RANK:
case CAN_ENTER_CONTEST_HIGH_RANK:
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_ABLE);
2018-12-22 17:32:21 +01:00
break;
2018-10-18 02:03:02 +02:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDataForRelearner(u8 slot)
2018-10-18 02:03:02 +02:00
{
2018-12-07 05:14:33 +01:00
if (GetNumberOfRelearnableMoves(&gPlayerParty[slot]) == 0)
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NOT_ABLE_2);
2018-10-18 02:03:02 +02:00
else
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_ABLE_2);
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDataForWirelessMinigame(u8 slot)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
if (IsMonAllowedInMinigame(slot) == TRUE)
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_ABLE);
2018-10-18 02:03:02 +02:00
else
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NOT_ABLE);
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDataForBattlePyramidHeldItem(u8 slot)
2018-10-18 02:03:02 +02:00
{
if (GetMonData(&gPlayerParty[slot], MON_DATA_HELD_ITEM))
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_HAVE);
2018-10-18 02:03:02 +02:00
else
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_DONT_HAVE);
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
// Returns TRUE if teaching move or cant evolve with item (i.e. description data is shown), FALSE otherwise
static bool8 DisplayPartyPokemonDataForMoveTutorOrEvolutionItem(u8 slot)
2018-10-18 02:03:02 +02:00
{
struct Pokemon *currentPokemon = &gPlayerParty[slot];
u16 item = gSpecialVar_ItemId;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (gPartyMenu.action == PARTY_ACTION_MOVE_TUTOR)
2018-10-18 02:03:02 +02:00
{
gSpecialVar_Result = FALSE;
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDataToTeachMove(slot, 0, gSpecialVar_0x8005);
2018-10-18 02:03:02 +02:00
}
else
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.action != PARTY_ACTION_USE_ITEM)
2018-10-18 02:03:02 +02:00
return FALSE;
2018-12-22 17:32:21 +01:00
2018-10-18 02:03:02 +02:00
switch (CheckIfItemIsTMHMOrEvolutionStone(item))
{
2018-12-22 17:32:21 +01:00
default:
return FALSE;
2019-10-18 01:22:03 +02:00
case 1: // TM/HM
DisplayPartyPokemonDataToTeachMove(slot, item, 0);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case 2: // Evolution stone
2021-02-12 20:54:11 +01:00
if (!GetMonData(currentPokemon, MON_DATA_IS_EGG) && GetEvolutionTargetSpecies(currentPokemon, EVO_MODE_ITEM_CHECK, item) != SPECIES_NONE)
2018-10-18 02:03:02 +02:00
return FALSE;
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NO_USE);
2018-12-22 17:32:21 +01:00
break;
2018-10-18 02:03:02 +02:00
}
}
return TRUE;
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDataToTeachMove(u8 slot, u16 item, u8 tutor)
2018-10-18 02:03:02 +02:00
{
2018-12-24 21:59:05 +01:00
switch (CanMonLearnTMTutor(&gPlayerParty[slot], item, tutor))
2018-10-18 02:03:02 +02:00
{
2018-12-22 17:32:21 +01:00
case CANNOT_LEARN_MOVE:
case CANNOT_LEARN_MOVE_IS_EGG:
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NOT_ABLE_2);
2018-12-22 17:32:21 +01:00
break;
case ALREADY_KNOWS_MOVE:
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_LEARNED);
2018-12-22 17:32:21 +01:00
break;
default:
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_ABLE_2);
2018-12-22 17:32:21 +01:00
break;
2018-10-18 02:03:02 +02:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDataForMultiBattle(u8 slot)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
struct PartyMenuBox *menuBox = &sPartyMenuBoxes[slot];
u8 actualSlot = slot - (3);
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (gMultiPartnerParty[actualSlot].species == SPECIES_NONE)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
DrawEmptySlot(menuBox->windowId);
2018-10-18 02:03:02 +02:00
}
else
{
2019-10-18 01:22:03 +02:00
menuBox->infoRects->blitFunc(menuBox->windowId, 0, 0, 0, 0, FALSE);
StringCopy(gStringVar1, gMultiPartnerParty[actualSlot].nickname);
2018-10-18 02:03:02 +02:00
StringGetEnd10(gStringVar1);
2019-10-31 19:11:55 +01:00
sub_81DB52C(gStringVar1);
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonBarDetail(menuBox->windowId, gStringVar1, 0, menuBox->infoRects->dimensions);
DisplayPartyPokemonLevel(gMultiPartnerParty[actualSlot].level, menuBox);
DisplayPartyPokemonGender(gMultiPartnerParty[actualSlot].gender, gMultiPartnerParty[actualSlot].species, gMultiPartnerParty[actualSlot].nickname, menuBox);
DisplayPartyPokemonHP(gMultiPartnerParty[actualSlot].hp, menuBox);
DisplayPartyPokemonMaxHP(gMultiPartnerParty[actualSlot].maxhp, menuBox);
DisplayPartyPokemonHPBar(gMultiPartnerParty[actualSlot].hp, gMultiPartnerParty[actualSlot].maxhp, menuBox);
2018-10-18 02:03:02 +02:00
}
}
2018-12-24 00:02:29 +01:00
static bool8 RenderPartyMenuBoxes(void)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
RenderPartyMenuBox(sPartyMenuInternal->data[0]);
if (++sPartyMenuInternal->data[0] == PARTY_SIZE)
2018-10-18 02:03:02 +02:00
return TRUE;
2019-02-01 19:25:10 +01:00
else
return FALSE;
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
static u8* GetPartyMenuBgTile(u16 tileId)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
return &sPartyBgGfxTilemap[tileId << 5];
2018-10-18 02:03:02 +02:00
}
2019-10-26 03:55:01 +02:00
static void CreatePartyMonSprites(u8 slot)
2018-10-18 02:03:02 +02:00
{
u8 actualSlot;
2018-12-22 17:32:21 +01:00
2019-11-01 02:33:01 +01:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_MULTI_SHOWCASE && slot >= MULTI_PARTY_SIZE)
2018-10-18 02:03:02 +02:00
{
u8 status;
2019-11-01 02:33:01 +01:00
actualSlot = slot - MULTI_PARTY_SIZE;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (gMultiPartnerParty[actualSlot].species != SPECIES_NONE)
2018-10-18 02:03:02 +02:00
{
2019-10-26 03:55:01 +02:00
CreatePartyMonIconSpriteParameterized(gMultiPartnerParty[actualSlot].species, gMultiPartnerParty[actualSlot].personality, &sPartyMenuBoxes[slot], 0, FALSE);
CreatePartyMonHeldItemSpriteParameterized(gMultiPartnerParty[actualSlot].species, gMultiPartnerParty[actualSlot].heldItem, &sPartyMenuBoxes[slot]);
CreatePartyMonPokeballSpriteParameterized(gMultiPartnerParty[actualSlot].species, &sPartyMenuBoxes[slot]);
2019-10-18 01:22:03 +02:00
if (gMultiPartnerParty[actualSlot].hp == 0)
2018-10-18 02:03:02 +02:00
status = AILMENT_FNT;
else
2019-10-18 01:22:03 +02:00
status = GetAilmentFromStatus(gMultiPartnerParty[actualSlot].status);
2019-10-26 03:55:01 +02:00
CreatePartyMonStatusSpriteParameterized(gMultiPartnerParty[actualSlot].species, status, &sPartyMenuBoxes[slot]);
2018-10-18 02:03:02 +02:00
}
}
else if (GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES) != SPECIES_NONE)
{
2019-10-26 03:55:01 +02:00
CreatePartyMonIconSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot], slot);
CreatePartyMonHeldItemSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
CreatePartyMonPokeballSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
CreatePartyMonStatusSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
2018-10-18 02:03:02 +02:00
}
}
2019-10-26 03:55:01 +02:00
static bool8 CreatePartyMonSpritesLoop(void)
2018-10-18 02:03:02 +02:00
{
2019-10-26 03:55:01 +02:00
CreatePartyMonSprites(sPartyMenuInternal->data[0]);
2019-10-18 01:22:03 +02:00
if (++sPartyMenuInternal->data[0] == PARTY_SIZE)
2018-10-18 02:03:02 +02:00
return TRUE;
2019-02-01 19:25:10 +01:00
else
return FALSE;
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
static void CreateCancelConfirmPokeballSprites(void)
2018-10-18 02:03:02 +02:00
{
2019-10-26 03:55:01 +02:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_MULTI_SHOWCASE)
2018-10-18 02:03:02 +02:00
{
2019-10-26 03:55:01 +02:00
// The showcase has no Cancel/Confirm buttons
2018-10-18 02:03:02 +02:00
FillBgTilemapBufferRect(1, 14, 23, 17, 7, 2, 1);
}
else
{
2019-10-18 01:22:03 +02:00
if (sPartyMenuInternal->chooseHalf)
2018-10-18 02:03:02 +02:00
{
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->spriteIdConfirmPokeball = CreateSmallPokeballButtonSprite(0xBF, 0x88);
DrawCancelConfirmButtons();
sPartyMenuInternal->spriteIdCancelPokeball = CreateSmallPokeballButtonSprite(0xBF, 0x98);
2018-10-18 02:03:02 +02:00
}
else
{
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->spriteIdCancelPokeball = CreatePokeballButtonSprite(198, 148);
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
AnimatePartySlot(gPartyMenu.slotId, 1);
2018-10-18 02:03:02 +02:00
}
}
2019-10-18 01:22:03 +02:00
void AnimatePartySlot(u8 slot, u8 animNum)
2018-10-18 02:03:02 +02:00
{
u8 spriteId;
2018-12-22 17:32:21 +01:00
2018-10-18 02:03:02 +02:00
switch (slot)
{
2018-12-22 17:32:21 +01:00
default:
if (GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES) != SPECIES_NONE)
{
2019-10-18 01:22:03 +02:00
LoadPartyBoxPalette(&sPartyMenuBoxes[slot], GetPartyBoxPaletteFlags(slot, animNum));
AnimateSelectedPartyIcon(sPartyMenuBoxes[slot].monSpriteId, animNum);
PartyMenuStartSpriteAnim(sPartyMenuBoxes[slot].pokeballSpriteId, animNum);
2018-12-22 17:32:21 +01:00
}
return;
2019-10-26 03:55:01 +02:00
case PARTY_SIZE: // Confirm
2019-10-18 01:22:03 +02:00
if (animNum == 0)
2019-10-26 03:55:01 +02:00
SetBgTilemapPalette(1, 23, 16, 7, 2, 1);
2018-12-22 17:32:21 +01:00
else
2019-10-26 03:55:01 +02:00
SetBgTilemapPalette(1, 23, 16, 7, 2, 2);
2019-10-18 01:22:03 +02:00
spriteId = sPartyMenuInternal->spriteIdConfirmPokeball;
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_SIZE + 1: // Cancel
2019-10-26 03:55:01 +02:00
// The position of the Cancel button changes if Confirm is present
2019-10-18 01:22:03 +02:00
if (!sPartyMenuInternal->chooseHalf)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
if (animNum == 0)
2019-10-26 03:55:01 +02:00
SetBgTilemapPalette(1, 23, 17, 7, 2, 1);
2018-10-18 02:03:02 +02:00
else
2019-10-26 03:55:01 +02:00
SetBgTilemapPalette(1, 23, 17, 7, 2, 2);
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
else if (animNum == 0)
2018-12-22 17:32:21 +01:00
{
2019-10-26 03:55:01 +02:00
SetBgTilemapPalette(1, 23, 18, 7, 2, 1);
2018-12-22 17:32:21 +01:00
}
else
{
2019-10-26 03:55:01 +02:00
SetBgTilemapPalette(1, 23, 18, 7, 2, 2);
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
spriteId = sPartyMenuInternal->spriteIdCancelPokeball;
2018-12-22 17:32:21 +01:00
break;
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
PartyMenuStartSpriteAnim(spriteId, animNum);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(1);
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
static u8 GetPartyBoxPaletteFlags(u8 slot, u8 animNum)
2018-10-12 03:23:39 +02:00
{
2019-10-18 01:22:03 +02:00
u8 palFlags = 0;
2019-02-01 19:25:10 +01:00
2019-10-18 01:22:03 +02:00
if (animNum == 1)
palFlags |= PARTY_PAL_SELECTED;
2018-10-18 02:03:02 +02:00
if (GetMonData(&gPlayerParty[slot], MON_DATA_HP) == 0)
2019-10-18 01:22:03 +02:00
palFlags |= PARTY_PAL_FAINTED;
2018-12-18 11:38:08 +01:00
if (PartyBoxPal_ParnterOrDisqualifiedInArena(slot) == TRUE)
2019-10-18 01:22:03 +02:00
palFlags |= PARTY_PAL_MULTI_ALT;
if (gPartyMenu.action == PARTY_ACTION_SWITCHING)
palFlags |= PARTY_PAL_SWITCHING;
if (gPartyMenu.action == PARTY_ACTION_SWITCH)
2018-10-12 03:23:39 +02:00
{
2019-10-18 01:22:03 +02:00
if (slot == gPartyMenu.slotId || slot == gPartyMenu.slotId2)
palFlags |= PARTY_PAL_TO_SWITCH;
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
if (gPartyMenu.action == PARTY_ACTION_SOFTBOILED && slot == gPartyMenu.slotId )
palFlags |= PARTY_PAL_TO_SOFTBOIL;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
return palFlags;
2018-10-18 02:03:02 +02:00
}
2018-12-24 00:02:29 +01:00
static bool8 PartyBoxPal_ParnterOrDisqualifiedInArena(u8 slot)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.layout == PARTY_LAYOUT_MULTI && (slot == 1 || slot == 4 || slot == 5))
2018-10-18 02:03:02 +02:00
return TRUE;
2018-12-22 17:32:21 +01:00
2019-11-01 02:33:01 +01:00
if (slot < MULTI_PARTY_SIZE && (gBattleTypeFlags & BATTLE_TYPE_ARENA) && gMain.inBattle && (gBattleStruct->arenaLostPlayerMons >> GetPartyIdFromBattleSlot(slot) & 1))
2018-10-18 02:03:02 +02:00
return TRUE;
2018-12-22 17:32:21 +01:00
2018-10-18 02:03:02 +02:00
return FALSE;
}
2019-10-26 03:55:01 +02:00
static void DrawCancelConfirmButtons(void)
2018-10-18 02:03:02 +02:00
{
2019-10-26 03:55:01 +02:00
CopyToBgTilemapBufferRect_ChangePalette(1, sConfirmButton_Tilemap, 23, 16, 7, 2, 17);
CopyToBgTilemapBufferRect_ChangePalette(1, sCancelButton_Tilemap, 23, 18, 7, 2, 17);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(1);
2018-10-18 02:03:02 +02:00
}
2018-12-18 11:38:08 +01:00
bool8 IsMultiBattle(void)
2018-10-18 02:03:02 +02:00
{
2018-12-22 17:32:21 +01:00
if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattleTypeFlags & BATTLE_TYPE_TRAINER && gMain.inBattle)
2018-10-18 02:03:02 +02:00
return TRUE;
2018-12-22 17:32:21 +01:00
else
return FALSE;
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
static void SwapPartyPokemon(struct Pokemon *mon1, struct Pokemon *mon2)
2018-10-18 02:03:02 +02:00
{
struct Pokemon *temp = Alloc(sizeof(struct Pokemon));
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
*temp = *mon1;
*mon1 = *mon2;
*mon2 = *temp;
2018-12-22 17:32:21 +01:00
2018-10-18 02:03:02 +02:00
Free(temp);
}
static void Task_ClosePartyMenu(u8 taskId)
2018-10-18 02:03:02 +02:00
{
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
gTasks[taskId].func = Task_ClosePartyMenuAndSetCB2;
2018-10-18 02:03:02 +02:00
}
static void Task_ClosePartyMenuAndSetCB2(u8 taskId)
2018-10-18 02:03:02 +02:00
{
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
UpdatePartyToFieldOrder();
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
if (sPartyMenuInternal->exitCallback != NULL)
2019-10-18 01:22:03 +02:00
SetMainCallback2(sPartyMenuInternal->exitCallback);
2018-10-18 02:03:02 +02:00
else
2019-10-18 01:22:03 +02:00
SetMainCallback2(gPartyMenu.exitCallback);
2018-12-22 17:32:21 +01:00
2018-10-18 02:03:02 +02:00
ResetSpriteData();
2018-12-18 11:38:08 +01:00
FreePartyPointers();
2018-10-18 02:03:02 +02:00
DestroyTask(taskId);
}
}
u8 GetCursorSelectionMonId(void)
{
2019-10-18 01:22:03 +02:00
return gPartyMenu.slotId;
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
u8 GetPartyMenuType(void)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
return gPartyMenu.menuType;
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
void Task_HandleChooseMonInput(u8 taskId)
2018-10-18 02:03:02 +02:00
{
2020-05-14 10:37:09 +02:00
if (!gPaletteFade.active && MenuHelpers_CallLinkSomething() != TRUE)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
s8 *slotPtr = GetCurrentPartySlotPtr();
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
switch (PartyMenuButtonHandler(slotPtr))
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
case 1: // Selected mon
HandleChooseMonSelection(taskId, slotPtr);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case 2: // Selected Cancel
HandleChooseMonCancel(taskId, slotPtr);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case 8: // Start button
if (sPartyMenuInternal->chooseHalf)
2018-12-22 17:32:21 +01:00
{
PlaySE(SE_SELECT);
2019-10-26 03:55:01 +02:00
MoveCursorToConfirm();
2018-12-22 17:32:21 +01:00
}
break;
2018-10-18 02:03:02 +02:00
}
}
}
2019-10-18 01:22:03 +02:00
static s8* GetCurrentPartySlotPtr(void)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.action == PARTY_ACTION_SWITCH || gPartyMenu.action == PARTY_ACTION_SOFTBOILED)
return &gPartyMenu.slotId2;
2019-02-01 19:25:10 +01:00
else
2019-10-18 01:22:03 +02:00
return &gPartyMenu.slotId;
2018-10-18 02:03:02 +02:00
}
2019-10-18 01:22:03 +02:00
static void HandleChooseMonSelection(u8 taskId, s8 *slotPtr)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
if (*slotPtr == PARTY_SIZE)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
gPartyMenu.task(taskId);
2018-10-12 03:23:39 +02:00
}
else
{
switch (gPartyMenu.action)
2018-10-18 02:03:02 +02:00
{
case PARTY_ACTION_SOFTBOILED:
2019-10-18 01:22:03 +02:00
if (IsSelectedMonNotEgg((u8*)slotPtr))
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
Task_TryUseSoftboiledOnPartyMon(taskId);
2018-12-22 17:32:21 +01:00
}
break;
case PARTY_ACTION_USE_ITEM:
2019-10-18 01:22:03 +02:00
if (IsSelectedMonNotEgg((u8*)slotPtr))
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
sPartyMenuInternal->exitCallback = CB2_SetUpExitToBattleScreen;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
gItemUseCB(taskId, Task_ClosePartyMenuAfterText);
2018-12-22 17:32:21 +01:00
}
break;
case PARTY_ACTION_MOVE_TUTOR:
2019-10-18 01:22:03 +02:00
if (IsSelectedMonNotEgg((u8*)slotPtr))
2018-12-22 17:32:21 +01:00
{
2018-10-18 02:03:02 +02:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
TryTutorSelectedMon(taskId);
2018-12-22 17:32:21 +01:00
}
break;
case PARTY_ACTION_GIVE_MAILBOX_MAIL:
2019-10-18 01:22:03 +02:00
if (IsSelectedMonNotEgg((u8*)slotPtr))
2018-12-22 17:32:21 +01:00
{
2018-10-18 02:03:02 +02:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
TryGiveMailToSelectedMon(taskId);
2018-12-22 17:32:21 +01:00
}
break;
case PARTY_ACTION_GIVE_ITEM:
case PARTY_ACTION_GIVE_PC_ITEM:
2019-10-18 01:22:03 +02:00
if (IsSelectedMonNotEgg((u8*)slotPtr))
2018-12-22 17:32:21 +01:00
{
2018-10-18 02:03:02 +02:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
2019-10-26 03:55:01 +02:00
TryGiveItemOrMailToSelectedMon(taskId);
2018-12-22 17:32:21 +01:00
}
break;
case PARTY_ACTION_SWITCH:
2018-12-22 17:32:21 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
SwitchSelectedMons(taskId);
2018-12-22 17:32:21 +01:00
break;
case PARTY_ACTION_CHOOSE_AND_CLOSE:
2018-12-22 17:32:21 +01:00
PlaySE(SE_SELECT);
Task_ClosePartyMenu(taskId);
2018-12-22 17:32:21 +01:00
break;
case PARTY_ACTION_MINIGAME:
2019-10-18 01:22:03 +02:00
if (IsSelectedMonNotEgg((u8*)slotPtr))
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
TryEnterMonForMinigame(taskId, (u8)*slotPtr);
2018-12-22 17:32:21 +01:00
}
break;
default:
case PARTY_ACTION_ABILITY_PREVENTS:
case PARTY_ACTION_SWITCHING:
2018-12-22 17:32:21 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
Task_TryCreateSelectionWindow(taskId);
2018-12-22 17:32:21 +01:00
break;
2018-10-18 02:03:02 +02:00
}
}
}
2019-10-18 01:22:03 +02:00
static bool8 IsSelectedMonNotEgg(u8 *slotPtr)
2018-10-18 02:03:02 +02:00
{
if (GetMonData(&gPlayerParty[*slotPtr], MON_DATA_IS_EGG) == TRUE)
{
2020-08-21 00:02:00 +02:00
PlaySE(SE_FAILURE);
2018-10-18 02:03:02 +02:00
return FALSE;
2018-10-12 03:23:39 +02:00
}
2018-10-18 02:03:02 +02:00
return TRUE;
2018-10-12 03:23:39 +02:00
}
2018-10-18 02:03:02 +02:00
2019-10-18 01:22:03 +02:00
static void HandleChooseMonCancel(u8 taskId, s8 *slotPtr)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
switch (gPartyMenu.action)
2018-10-18 02:03:02 +02:00
{
2019-10-18 01:22:03 +02:00
case PARTY_ACTION_SEND_OUT:
2020-08-21 00:02:00 +02:00
PlaySE(SE_FAILURE);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_ACTION_SWITCH:
case PARTY_ACTION_SOFTBOILED:
2018-12-22 17:32:21 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
FinishTwoMonAction(taskId);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_ACTION_MINIGAME:
2018-12-22 17:32:21 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
CancelParticipationPrompt(taskId);
2018-12-22 17:32:21 +01:00
break;
default:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
if (DisplayCancelChooseMonYesNo(taskId) != TRUE)
2018-12-22 17:32:21 +01:00
{
2020-05-14 10:37:09 +02:00
if (!MenuHelpers_LinkSomething())
2019-10-18 01:22:03 +02:00
gSpecialVar_0x8004 = PARTY_SIZE + 1;
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = FALSE;
2019-10-18 01:22:03 +02:00
*slotPtr = PARTY_SIZE + 1;
Task_ClosePartyMenu(taskId);
2018-12-22 17:32:21 +01:00
}
break;
2018-10-18 02:03:02 +02:00
}
2018-12-22 17:32:21 +01:00
}
2018-10-21 02:25:28 +02:00
2019-10-18 01:22:03 +02:00
static bool8 DisplayCancelChooseMonYesNo(u8 taskId)
2018-10-21 02:25:28 +02:00
{
const u8* stringPtr = NULL;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_CONTEST)
2018-10-21 02:25:28 +02:00
stringPtr = gText_CancelParticipation;
2019-10-18 01:22:03 +02:00
else if (gPartyMenu.menuType == PARTY_MENU_TYPE_CHOOSE_HALF)
stringPtr = GetFacilityCancelString();
2018-12-22 17:32:21 +01:00
2018-10-21 02:25:28 +02:00
if (stringPtr == NULL)
return FALSE;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
2018-10-21 02:25:28 +02:00
StringExpandPlaceholders(gStringVar4, stringPtr);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_CancelChooseMonYesNo;
2018-10-21 02:25:28 +02:00
return TRUE;
}
2019-10-18 01:22:03 +02:00
static void Task_CancelChooseMonYesNo(u8 taskId)
2018-10-21 02:25:28 +02:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-10-21 02:25:28 +02:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
gTasks[taskId].func = Task_HandleCancelChooseMonYesNoInput;
2018-10-21 02:25:28 +02:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_HandleCancelChooseMonYesNoInput(u8 taskId)
2018-10-21 02:25:28 +02:00
{
2018-12-07 20:47:20 +01:00
switch (Menu_ProcessInputNoWrapClearOnChoose())
2018-10-21 02:25:28 +02:00
{
2018-12-22 17:32:21 +01:00
case 0:
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = FALSE;
2019-10-18 01:22:03 +02:00
gPartyMenu.slotId = PARTY_SIZE + 1;
ClearSelectedPartyOrder();
Task_ClosePartyMenu(taskId);
2018-12-22 17:32:21 +01:00
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2018-12-22 17:32:21 +01:00
case 1:
2019-10-18 01:22:03 +02:00
Task_ReturnToChooseMonAfterText(taskId);
2018-12-22 17:32:21 +01:00
break;
2018-10-21 02:25:28 +02:00
}
}
2019-10-18 01:22:03 +02:00
static u16 PartyMenuButtonHandler(s8 *slotPtr)
2018-10-21 02:25:28 +02:00
{
2018-12-18 11:38:08 +01:00
s8 movementDir;
2018-12-22 17:32:21 +01:00
2018-10-21 02:25:28 +02:00
switch (gMain.newAndRepeatedKeys)
{
2018-12-22 17:32:21 +01:00
case DPAD_UP:
2019-10-26 03:55:01 +02:00
movementDir = MENU_DIR_UP;
2018-12-22 17:32:21 +01:00
break;
case DPAD_DOWN:
2019-10-26 03:55:01 +02:00
movementDir = MENU_DIR_DOWN;
2018-12-22 17:32:21 +01:00
break;
case DPAD_LEFT:
2019-10-26 03:55:01 +02:00
movementDir = MENU_DIR_LEFT;
2018-12-22 17:32:21 +01:00
break;
case DPAD_RIGHT:
2019-10-26 03:55:01 +02:00
movementDir = MENU_DIR_RIGHT;
2018-12-22 17:32:21 +01:00
break;
default:
2019-10-18 01:22:03 +02:00
switch (GetLRKeysPressedAndHeld())
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
case MENU_L_PRESSED:
2019-10-26 03:55:01 +02:00
movementDir = MENU_DIR_UP;
2018-10-21 02:25:28 +02:00
break;
2019-10-18 01:22:03 +02:00
case MENU_R_PRESSED:
2019-10-26 03:55:01 +02:00
movementDir = MENU_DIR_DOWN;
2018-10-21 02:25:28 +02:00
break;
default:
2018-12-22 17:32:21 +01:00
movementDir = 0;
break;
}
break;
2018-10-21 02:25:28 +02:00
}
2018-12-22 17:32:21 +01:00
2020-09-05 03:11:55 +02:00
if (JOY_NEW(START_BUTTON))
2018-10-21 02:25:28 +02:00
return 8;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
if (movementDir)
2018-10-21 02:25:28 +02:00
{
2019-10-18 01:22:03 +02:00
UpdateCurrentPartySelection(slotPtr, movementDir);
2018-10-21 02:25:28 +02:00
return 0;
}
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
// Pressed Cancel
2020-09-05 03:11:55 +02:00
if ((JOY_NEW(A_BUTTON)) && *slotPtr == PARTY_SIZE + 1)
2018-10-21 02:25:28 +02:00
return 2;
2018-12-22 17:32:21 +01:00
2020-09-05 03:11:55 +02:00
return JOY_NEW(A_BUTTON | B_BUTTON);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void UpdateCurrentPartySelection(s8 *slotPtr, s8 movementDir)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
s8 newSlotId = *slotPtr;
u8 layout = gPartyMenu.layout;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (layout == PARTY_LAYOUT_SINGLE)
UpdatePartySelectionSingleLayout(slotPtr, movementDir);
2019-10-26 03:55:01 +02:00
else
2019-10-18 01:22:03 +02:00
UpdatePartySelectionDoubleLayout(slotPtr, movementDir);
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (*slotPtr != newSlotId)
2018-12-07 05:14:33 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
AnimatePartySlot(newSlotId, 0);
AnimatePartySlot(*slotPtr, 1);
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void UpdatePartySelectionSingleLayout(s8 *slotPtr, s8 movementDir)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
// PARTY_SIZE + 1 is Cancel, PARTY_SIZE is Confirm
2019-10-18 01:22:03 +02:00
switch (movementDir)
2018-12-07 05:14:33 +01:00
{
2019-10-26 03:55:01 +02:00
case MENU_DIR_UP:
2019-10-18 01:22:03 +02:00
if (*slotPtr == 0)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = PARTY_SIZE + 1;
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
else if (*slotPtr == PARTY_SIZE)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = gPlayerPartyCount - 1;
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
else if (*slotPtr == PARTY_SIZE + 1)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
if (sPartyMenuInternal->chooseHalf)
*slotPtr = PARTY_SIZE;
2018-12-22 17:32:21 +01:00
else
2019-10-18 01:22:03 +02:00
*slotPtr = gPlayerPartyCount - 1;
2018-12-22 17:32:21 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
(*slotPtr)--;
2018-12-22 17:32:21 +01:00
}
break;
2019-10-26 03:55:01 +02:00
case MENU_DIR_DOWN:
2019-10-18 01:22:03 +02:00
if (*slotPtr == PARTY_SIZE + 1)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = 0;
2018-12-22 17:32:21 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
if (*slotPtr == gPlayerPartyCount - 1)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (sPartyMenuInternal->chooseHalf)
*slotPtr = PARTY_SIZE;
2018-12-07 05:14:33 +01:00
else
2019-10-18 01:22:03 +02:00
*slotPtr = PARTY_SIZE + 1;
2018-12-07 05:14:33 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
(*slotPtr)++;
2018-12-07 05:14:33 +01:00
}
2018-12-22 17:32:21 +01:00
}
break;
2019-10-26 03:55:01 +02:00
case MENU_DIR_RIGHT:
2019-10-18 01:22:03 +02:00
if (gPlayerPartyCount != 1 && *slotPtr == 0)
2018-12-22 17:32:21 +01:00
{
2019-10-26 03:55:01 +02:00
if (sPartyMenuInternal->lastSelectedSlot == 0)
2019-10-18 01:22:03 +02:00
*slotPtr = 1;
2018-12-07 05:14:33 +01:00
else
2019-10-26 03:55:01 +02:00
*slotPtr = sPartyMenuInternal->lastSelectedSlot;
2018-12-22 17:32:21 +01:00
}
break;
2019-10-26 03:55:01 +02:00
case MENU_DIR_LEFT:
2019-10-18 01:22:03 +02:00
if (*slotPtr != 0 && *slotPtr != PARTY_SIZE && *slotPtr != PARTY_SIZE + 1)
2018-12-22 17:32:21 +01:00
{
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->lastSelectedSlot = *slotPtr;
2019-10-18 01:22:03 +02:00
*slotPtr = 0;
2018-12-22 17:32:21 +01:00
}
break;
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void UpdatePartySelectionDoubleLayout(s8 *slotPtr, s8 movementDir)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
// PARTY_SIZE + 1 is Cancel, PARTY_SIZE is Confirm
2019-10-26 03:55:01 +02:00
// newSlot is used temporarily as a movement direction during its later assignment
s8 newSlot = movementDir;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
switch (movementDir)
2018-12-07 05:14:33 +01:00
{
2019-10-26 03:55:01 +02:00
case MENU_DIR_UP:
2019-10-18 01:22:03 +02:00
if (*slotPtr == 0)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = PARTY_SIZE + 1;
2018-12-22 17:32:21 +01:00
break;
}
2019-10-18 01:22:03 +02:00
else if (*slotPtr == PARTY_SIZE)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = gPlayerPartyCount - 1;
2018-12-22 17:32:21 +01:00
break;
}
2019-10-18 01:22:03 +02:00
else if (*slotPtr == PARTY_SIZE + 1)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
if (sPartyMenuInternal->chooseHalf)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = PARTY_SIZE;
2018-12-22 17:32:21 +01:00
break;
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
(*slotPtr)--;
2018-12-22 17:32:21 +01:00
}
2019-10-26 03:55:01 +02:00
newSlot = GetNewSlotDoubleLayout(*slotPtr, newSlot);
if (newSlot != -1)
*slotPtr = newSlot;
2018-12-22 17:32:21 +01:00
break;
2019-10-26 03:55:01 +02:00
case MENU_DIR_DOWN:
2019-10-18 01:22:03 +02:00
if (*slotPtr == PARTY_SIZE)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = PARTY_SIZE + 1;
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
else if (*slotPtr == PARTY_SIZE + 1)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = 0;
2018-12-22 17:32:21 +01:00
}
else
{
2019-10-26 03:55:01 +02:00
newSlot = GetNewSlotDoubleLayout(*slotPtr, MENU_DIR_DOWN);
if (newSlot == -1)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (sPartyMenuInternal->chooseHalf)
*slotPtr = PARTY_SIZE;
2018-12-07 05:14:33 +01:00
else
2019-10-18 01:22:03 +02:00
*slotPtr = PARTY_SIZE + 1;
2018-12-07 05:14:33 +01:00
}
else
{
2019-10-26 03:55:01 +02:00
*slotPtr = newSlot;
2018-12-07 05:14:33 +01:00
}
2018-12-22 17:32:21 +01:00
}
break;
2019-10-26 03:55:01 +02:00
case MENU_DIR_RIGHT:
2019-10-18 01:22:03 +02:00
if (*slotPtr == 0)
2018-12-22 17:32:21 +01:00
{
2019-10-26 03:55:01 +02:00
if (sPartyMenuInternal->lastSelectedSlot == 3)
2018-12-07 05:14:33 +01:00
{
2018-12-22 17:32:21 +01:00
if (GetMonData(&gPlayerParty[3], MON_DATA_SPECIES) != SPECIES_NONE)
2019-10-18 01:22:03 +02:00
*slotPtr = 3;
2018-12-07 05:14:33 +01:00
}
2018-12-22 17:32:21 +01:00
else if (GetMonData(&gPlayerParty[2], MON_DATA_SPECIES) != SPECIES_NONE)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = 2;
2018-12-07 05:14:33 +01:00
}
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
else if (*slotPtr == 1)
2018-12-22 17:32:21 +01:00
{
2019-10-26 03:55:01 +02:00
if (sPartyMenuInternal->lastSelectedSlot == 5)
2018-12-07 05:14:33 +01:00
{
2018-12-22 17:32:21 +01:00
if (GetMonData(&gPlayerParty[5], MON_DATA_SPECIES) != SPECIES_NONE)
2019-10-18 01:22:03 +02:00
*slotPtr = 5;
2018-12-07 05:14:33 +01:00
}
2018-12-22 17:32:21 +01:00
else if (GetMonData(&gPlayerParty[4], MON_DATA_SPECIES) != SPECIES_NONE)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
*slotPtr = 4;
2018-12-07 05:14:33 +01:00
}
2018-12-22 17:32:21 +01:00
}
break;
2019-10-26 03:55:01 +02:00
case MENU_DIR_LEFT:
2019-10-18 01:22:03 +02:00
if (*slotPtr == 2 || *slotPtr == 3)
2018-12-22 17:32:21 +01:00
{
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->lastSelectedSlot = *slotPtr;
2019-10-18 01:22:03 +02:00
*slotPtr = 0;
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
else if (*slotPtr == 4 || *slotPtr == 5)
2018-12-22 17:32:21 +01:00
{
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->lastSelectedSlot = *slotPtr;
2019-10-18 01:22:03 +02:00
*slotPtr = 1;
2018-12-22 17:32:21 +01:00
}
break;
2018-12-07 05:14:33 +01:00
}
}
2019-10-26 03:55:01 +02:00
static s8 GetNewSlotDoubleLayout(s8 slotId, s8 movementDir)
2018-12-07 05:14:33 +01:00
{
while (TRUE)
{
2019-10-26 03:55:01 +02:00
slotId += movementDir;
2019-10-18 01:22:03 +02:00
if ((u8)slotId >= PARTY_SIZE)
2018-12-07 05:14:33 +01:00
return -1;
2019-10-18 01:22:03 +02:00
if (GetMonData(&gPlayerParty[slotId], MON_DATA_SPECIES) != SPECIES_NONE)
return slotId;
2018-12-07 05:14:33 +01:00
}
}
u8* GetMonNickname(struct Pokemon *mon, u8 *dest)
{
GetMonData(mon, MON_DATA_NICKNAME, dest);
return StringGetEnd10(dest);
}
2019-10-18 01:22:03 +02:00
#define tKeepOpen data[0]
u8 DisplayPartyMenuMessage(const u8* str, bool8 keepOpen)
2018-12-07 05:14:33 +01:00
{
u8 taskId;
2018-12-22 17:32:21 +01:00
PartyMenuPrintText(str);
2019-10-18 01:22:03 +02:00
taskId = CreateTask(Task_PrintAndWaitForText, 1);
gTasks[taskId].tKeepOpen = keepOpen;
2018-12-07 05:14:33 +01:00
return taskId;
}
2019-10-18 01:22:03 +02:00
static void Task_PrintAndWaitForText(u8 taskId)
2018-12-07 05:14:33 +01:00
{
if (RunTextPrintersRetIsActive(6) != TRUE)
{
2019-10-18 01:22:03 +02:00
if (gTasks[taskId].tKeepOpen == FALSE)
2018-12-07 05:14:33 +01:00
{
ClearStdWindowAndFrameToTransparent(6, 0);
2018-12-07 05:14:33 +01:00
ClearWindowTilemap(6);
}
DestroyTask(taskId);
}
}
2019-10-18 01:22:03 +02:00
#undef tKeepOpen
bool8 IsPartyMenuTextPrinterActive(void)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
return FuncIsActiveTask(Task_PrintAndWaitForText);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_WaitForLinkAndReturnToChooseMon(u8 taskId)
2018-12-07 05:14:33 +01:00
{
2020-05-14 10:37:09 +02:00
if (MenuHelpers_CallLinkSomething() != TRUE)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
gTasks[taskId].func = Task_HandleChooseMonInput;
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_ReturnToChooseMonAfterText(u8 taskId)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-07 05:14:33 +01:00
{
ClearStdWindowAndFrameToTransparent(6, 0);
2018-12-07 05:14:33 +01:00
ClearWindowTilemap(6);
2020-05-14 10:37:09 +02:00
if (MenuHelpers_LinkSomething() == TRUE)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_WaitForLinkAndReturnToChooseMon;
2018-12-07 05:14:33 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
gTasks[taskId].func = Task_HandleChooseMonInput;
2018-12-07 05:14:33 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
static void DisplayGaveHeldItemMessage(struct Pokemon *mon, u16 item, bool8 keepOpen, u8 unused)
2018-12-07 05:14:33 +01:00
{
GetMonNickname(mon, gStringVar1);
CopyItemName(item, gStringVar2);
StringExpandPlaceholders(gStringVar4, gText_PkmnWasGivenItem);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, keepOpen);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayTookHeldItemMessage(struct Pokemon *mon, u16 item, bool8 keepOpen)
2018-12-07 05:14:33 +01:00
{
GetMonNickname(mon, gStringVar1);
CopyItemName(item, gStringVar2);
2019-01-03 02:54:55 +01:00
StringExpandPlaceholders(gStringVar4, gText_ReceivedItemFromPkmn);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, keepOpen);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayAlreadyHoldingItemSwitchMessage(struct Pokemon *mon, u16 item, bool8 keepOpen)
2018-12-07 05:14:33 +01:00
{
GetMonNickname(mon, gStringVar1);
CopyItemName(item, gStringVar2);
2019-10-18 01:22:03 +02:00
StringExpandPlaceholders(gStringVar4, gText_PkmnAlreadyHoldingItemSwitch);
DisplayPartyMenuMessage(gStringVar4, keepOpen);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplaySwitchedHeldItemMessage(u16 item, u16 item2, bool8 keepOpen)
2018-12-07 05:14:33 +01:00
{
CopyItemName(item, gStringVar1);
CopyItemName(item2, gStringVar2);
StringExpandPlaceholders(gStringVar4, gText_SwitchedPkmnItem);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, keepOpen);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void GiveItemToMon(struct Pokemon *mon, u16 item)
2018-12-07 05:14:33 +01:00
{
u8 itemBytes[2];
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
if (ItemIsMail(item) == TRUE)
{
if (GiveMailToMon(mon, item) == 0xFF)
return;
}
itemBytes[0] = item;
itemBytes[1] = item >> 8;
SetMonData(mon, MON_DATA_HELD_ITEM, itemBytes);
}
2019-02-01 19:25:10 +01:00
static u8 TryTakeMonItem(struct Pokemon* mon)
2018-12-07 05:14:33 +01:00
{
u16 item = GetMonData(mon, MON_DATA_HELD_ITEM);
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
if (item == ITEM_NONE)
return 0;
if (AddBagItem(item, 1) == FALSE)
return 1;
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
item = ITEM_NONE;
SetMonData(mon, MON_DATA_HELD_ITEM, &item);
return 2;
}
2019-10-18 01:22:03 +02:00
static void BufferBagFullCantTakeItemMessage(u16 itemUnused)
2018-12-07 05:14:33 +01:00
{
StringExpandPlaceholders(gStringVar4, gText_BagFullCouldNotRemoveItem);
}
2019-10-18 01:22:03 +02:00
#define tHP data[0]
#define tMaxHP data[1]
#define tHPIncrement data[2]
#define tHPToAdd data[3]
#define tPartyId data[4]
#define tStartHP data[5]
static void Task_PartyMenuModifyHP(u8 taskId)
2018-12-07 05:14:33 +01:00
{
s16 *data = gTasks[taskId].data;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
tHP += tHPIncrement;
tHPToAdd--;
SetMonData(&gPlayerParty[tPartyId], MON_DATA_HP, &tHP);
DisplayPartyPokemonHPCheck(&gPlayerParty[tPartyId], &sPartyMenuBoxes[tPartyId], 1);
DisplayPartyPokemonHPBarCheck(&gPlayerParty[tPartyId], &sPartyMenuBoxes[tPartyId]);
if (tHPToAdd == 0 || tHP == 0 || tHP == tMaxHP)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
// If HP was recovered, buffer the amount recovered
if (tHP > tStartHP)
ConvertIntToDecimalStringN(gStringVar2, tHP - tStartHP, STR_CONV_MODE_LEFT_ALIGN, 3);
2018-12-07 05:14:33 +01:00
SwitchTaskToFollowupFunc(taskId);
}
}
2019-10-31 19:11:55 +01:00
void PartyMenuModifyHP(u8 taskId, u8 slot, s8 hpIncrement, s16 hpDifference, TaskFunc task)
2018-12-07 05:14:33 +01:00
{
struct Pokemon *mon = &gPlayerParty[slot];
s16 *data = gTasks[taskId].data;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
tHP = GetMonData(mon, MON_DATA_HP);
tMaxHP = GetMonData(mon, MON_DATA_MAX_HP);
tHPIncrement = hpIncrement;
tHPToAdd = hpDifference;
tPartyId = slot;
tStartHP = tHP;
2019-10-31 19:11:55 +01:00
SetTaskFuncWithFollowupFunc(taskId, Task_PartyMenuModifyHP, task);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
// The usage of hp in this function is mostly nonsense
// Because caseId is always passed 0, none of the other cases ever occur
static void ResetHPTaskData(u8 taskId, u8 caseId, u32 hp)
2018-12-07 05:14:33 +01:00
{
s16 *data = gTasks[taskId].data;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
switch (caseId) // always zero
2018-12-07 05:14:33 +01:00
{
case 0:
2019-10-18 01:22:03 +02:00
tHP = hp;
tStartHP = hp;
2018-12-07 05:14:33 +01:00
break;
case 1:
2019-10-18 01:22:03 +02:00
tMaxHP = hp;
2018-12-07 05:14:33 +01:00
break;
case 2:
2019-10-18 01:22:03 +02:00
tHPIncrement = hp;
2018-12-07 05:14:33 +01:00
break;
case 3:
2019-10-18 01:22:03 +02:00
tHPToAdd = hp;
2018-12-07 05:14:33 +01:00
break;
case 4:
2019-10-18 01:22:03 +02:00
tPartyId = hp;
2018-12-07 05:14:33 +01:00
break;
case 5:
2019-10-18 01:22:03 +02:00
SetTaskFuncWithFollowupFunc(taskId, Task_PartyMenuModifyHP, (TaskFunc)hp); // >casting hp as a taskfunc
2018-12-07 05:14:33 +01:00
break;
}
}
2019-10-18 01:22:03 +02:00
#undef tHP
#undef tMaxHP
#undef tHPIncrement
#undef tHPToAdd
#undef tPartyId
#undef tStartHP
u8 GetAilmentFromStatus(u32 status)
2018-12-07 05:14:33 +01:00
{
if (status & STATUS1_PSN_ANY)
return AILMENT_PSN;
if (status & STATUS1_PARALYSIS)
return AILMENT_PRZ;
if (status & STATUS1_SLEEP)
return AILMENT_SLP;
if (status & STATUS1_FREEZE)
return AILMENT_FRZ;
if (status & STATUS1_BURN)
return AILMENT_BRN;
return AILMENT_NONE;
}
u8 GetMonAilment(struct Pokemon *mon)
2018-12-07 05:14:33 +01:00
{
u8 ailment;
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
if (GetMonData(mon, MON_DATA_HP) == 0)
return AILMENT_FNT;
2019-10-18 01:22:03 +02:00
ailment = GetAilmentFromStatus(GetMonData(mon, MON_DATA_STATUS));
2018-12-07 05:14:33 +01:00
if (ailment != AILMENT_NONE)
return ailment;
if (CheckPartyPokerus(mon, 0))
return AILMENT_PKRS;
return AILMENT_NONE;
}
2019-10-18 01:22:03 +02:00
static void SetPartyMonsAllowedInMinigame(void)
2018-12-07 05:14:33 +01:00
{
u16 *ptr;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_MINIGAME)
2018-12-07 05:14:33 +01:00
{
u8 i;
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
ptr = &gPartyMenu.data1;
gPartyMenu.data1 = 0;
2018-12-07 05:14:33 +01:00
if (gSpecialVar_0x8005 == 0)
{
for (i = 0; i < gPlayerPartyCount; i++)
2019-10-11 10:14:09 +02:00
*ptr += IsMonAllowedInPokemonJump(&gPlayerParty[i]) << i;
2018-12-07 05:14:33 +01:00
}
else
{
for (i = 0; i < gPlayerPartyCount; i++)
2019-10-18 01:22:03 +02:00
*ptr += IsMonAllowedInDodrioBerryPicking(&gPlayerParty[i]) << i;
2018-12-07 05:14:33 +01:00
}
}
}
2019-10-11 10:14:09 +02:00
static bool16 IsMonAllowedInPokemonJump(struct Pokemon *mon)
2018-12-07 05:14:33 +01:00
{
2019-10-11 10:14:09 +02:00
if (GetMonData(mon, MON_DATA_IS_EGG) != TRUE && IsSpeciesAllowedInPokemonJump(GetMonData(mon, MON_DATA_SPECIES)))
2018-12-07 05:14:33 +01:00
return TRUE;
return FALSE;
}
2019-10-18 01:22:03 +02:00
static bool16 IsMonAllowedInDodrioBerryPicking(struct Pokemon *mon)
2018-12-07 05:14:33 +01:00
{
if (GetMonData(mon, MON_DATA_IS_EGG) != TRUE && GetMonData(mon, MON_DATA_SPECIES) == SPECIES_DODRIO)
return TRUE;
return FALSE;
}
2019-10-18 01:22:03 +02:00
static bool8 IsMonAllowedInMinigame(u8 slot)
2018-12-07 05:14:33 +01:00
{
2019-10-26 03:55:01 +02:00
if (!((gPartyMenu.data1 >> slot) & 1))
2018-12-07 05:14:33 +01:00
return FALSE;
return TRUE;
}
2019-10-18 01:22:03 +02:00
static void TryEnterMonForMinigame(u8 taskId, u8 slot)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsMonAllowedInMinigame(slot) == TRUE)
2018-12-07 05:14:33 +01:00
{
PlaySE(SE_SELECT);
gSpecialVar_0x8004 = slot;
Task_ClosePartyMenu(taskId);
2018-12-07 05:14:33 +01:00
}
else
{
2020-08-21 00:02:00 +02:00
PlaySE(SE_FAILURE);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_PkmnCantParticipate, FALSE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void CancelParticipationPrompt(u8 taskId)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_CancelParticipation, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_CancelParticipationYesNo;
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_CancelParticipationYesNo(u8 taskId)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
gTasks[taskId].func = Task_HandleCancelParticipationYesNoInput;
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_HandleCancelParticipationYesNoInput(u8 taskId)
2018-12-07 05:14:33 +01:00
{
2018-12-07 20:47:20 +01:00
switch (Menu_ProcessInputNoWrapClearOnChoose())
2018-12-07 05:14:33 +01:00
{
2018-12-22 17:32:21 +01:00
case 0:
2019-10-18 01:22:03 +02:00
gSpecialVar_0x8004 = PARTY_SIZE + 1;
Task_ClosePartyMenu(taskId);
2018-12-22 17:32:21 +01:00
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2018-12-22 17:32:21 +01:00
case 1:
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-22 17:32:21 +01:00
break;
2018-12-07 05:14:33 +01:00
}
}
2018-12-24 21:59:05 +01:00
static u8 CanMonLearnTMTutor(struct Pokemon *mon, u16 item, u8 tutor)
2018-12-07 05:14:33 +01:00
{
u16 move;
2018-12-22 17:32:21 +01:00
2018-12-20 02:27:44 +01:00
if (GetMonData(mon, MON_DATA_IS_EGG))
2018-12-18 11:38:08 +01:00
return CANNOT_LEARN_MOVE_IS_EGG;
2018-12-24 21:59:05 +01:00
2021-01-14 09:41:28 +01:00
if (item >= ITEM_TM01)
2018-12-07 05:14:33 +01:00
{
2021-01-14 09:41:28 +01:00
if (!CanMonLearnTMHM(mon, item - ITEM_TM01))
2018-12-18 11:38:08 +01:00
return CANNOT_LEARN_MOVE;
2020-09-13 09:02:41 +02:00
else
move = ItemIdToBattleMoveId(item);
2018-12-07 05:14:33 +01:00
}
else
{
2020-09-13 09:02:41 +02:00
if (!CanLearnTutorMove(GetMonData(mon, MON_DATA_SPECIES), tutor))
return CANNOT_LEARN_MOVE;
else
move = GetTutorMove(tutor);
2018-12-07 05:14:33 +01:00
}
2018-12-22 17:32:21 +01:00
2018-12-24 21:59:05 +01:00
if (MonKnowsMove(mon, move) == TRUE)
2018-12-18 11:38:08 +01:00
return ALREADY_KNOWS_MOVE;
2018-12-24 21:59:05 +01:00
else
return CAN_LEARN_MOVE;
2018-12-07 05:14:33 +01:00
}
2018-12-24 21:59:05 +01:00
static u16 GetTutorMove(u8 tutor)
2018-12-07 05:14:33 +01:00
{
2018-12-24 21:59:05 +01:00
return gTutorMoves[tutor];
2018-12-07 05:14:33 +01:00
}
2018-12-24 21:59:05 +01:00
static bool8 CanLearnTutorMove(u16 species, u8 tutor)
2018-12-07 05:14:33 +01:00
{
2018-12-24 21:59:05 +01:00
if (sTutorLearnsets[species] & (1 << tutor))
2018-12-07 05:14:33 +01:00
return TRUE;
2018-12-24 21:59:05 +01:00
else
return FALSE;
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void InitPartyMenuWindows(u8 layout)
2018-12-07 05:14:33 +01:00
{
u8 i;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
switch (layout)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
case PARTY_LAYOUT_SINGLE:
InitWindows(sSinglePartyMenuWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_LAYOUT_DOUBLE:
InitWindows(sDoublePartyMenuWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_LAYOUT_MULTI:
InitWindows(sMultiPartyMenuWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
default: // PARTY_LAYOUT_MULTI_SHOWCASE
InitWindows(sShowcaseMultiPartyMenuWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
2018-12-07 05:14:33 +01:00
}
DeactivateAllTextPrinters();
2018-12-18 11:38:08 +01:00
for (i = 0; i < PARTY_SIZE; i++)
FillWindowPixelBuffer(i, PIXEL_FILL(0));
2018-12-07 05:14:33 +01:00
LoadUserWindowBorderGfx(0, 0x4F, 0xD0);
LoadPalette(GetOverworldTextboxPalettePtr(), 0xE0, 0x20);
LoadPalette(gUnknown_0860F074, 0xF0, 0x20);
}
2019-10-26 03:55:01 +02:00
static void CreateCancelConfirmWindows(bool8 chooseHalf)
2018-12-07 05:14:33 +01:00
{
2019-10-26 03:55:01 +02:00
u8 confirmWindowId;
u8 cancelWindowId;
2018-12-07 05:14:33 +01:00
u8 offset;
u8 mainOffset;
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
if (gPartyMenu.menuType != PARTY_MENU_TYPE_MULTI_SHOWCASE)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (chooseHalf == TRUE)
2018-12-07 05:14:33 +01:00
{
2019-10-26 03:55:01 +02:00
confirmWindowId = AddWindow(&sConfirmButtonWindowTemplate);
FillWindowPixelBuffer(confirmWindowId, PIXEL_FILL(0));
2018-12-07 05:14:33 +01:00
mainOffset = GetStringCenterAlignXOffset(0, gMenuText_Confirm, 48);
2019-10-26 03:55:01 +02:00
AddTextPrinterParameterized4(confirmWindowId, 0, mainOffset, 1, 0, 0, sFontColorTable[0], -1, gMenuText_Confirm);
PutWindowTilemap(confirmWindowId);
CopyWindowToVram(confirmWindowId, 2);
cancelWindowId = AddWindow(&sMultiCancelButtonWindowTemplate);
2018-12-07 05:14:33 +01:00
offset = 0;
}
else
{
2019-10-26 03:55:01 +02:00
cancelWindowId = AddWindow(&sCancelButtonWindowTemplate);
2018-12-07 05:14:33 +01:00
offset = 3;
}
2019-10-26 03:55:01 +02:00
FillWindowPixelBuffer(cancelWindowId, PIXEL_FILL(0));
// Branches are functionally identical. Second branch is never reached, Spin Trade wasnt fully implemented
2019-10-18 01:22:03 +02:00
if (gPartyMenu.menuType != PARTY_MENU_TYPE_SPIN_TRADE)
2018-12-07 05:14:33 +01:00
{
mainOffset = GetStringCenterAlignXOffset(0, gText_Cancel, 48);
2019-10-26 03:55:01 +02:00
AddTextPrinterParameterized3(cancelWindowId, 0, mainOffset + offset, 1, sFontColorTable[0], -1, gText_Cancel);
2018-12-07 05:14:33 +01:00
}
else
{
mainOffset = GetStringCenterAlignXOffset(0, gText_Cancel2, 48);
2019-10-26 03:55:01 +02:00
AddTextPrinterParameterized3(cancelWindowId, 0, mainOffset + offset, 1, sFontColorTable[0], -1, gText_Cancel2);
2018-12-07 05:14:33 +01:00
}
2019-10-26 03:55:01 +02:00
PutWindowTilemap(cancelWindowId);
CopyWindowToVram(cancelWindowId, 2);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static u16* GetPartyMenuPalBufferPtr(u8 paletteId)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
return &sPartyMenuInternal->palBuffer[paletteId];
2018-12-07 05:14:33 +01:00
}
2018-12-24 21:59:05 +01:00
static void BlitBitmapToPartyWindow(u8 windowId, const u8 *b, u8 c, u8 x, u8 y, u8 width, u8 height)
2018-12-07 05:14:33 +01:00
{
u8 *pixels = AllocZeroed(height * width * 32);
u8 i, j;
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
if (pixels != NULL)
{
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
2019-10-18 01:22:03 +02:00
CpuCopy16(GetPartyMenuBgTile(b[x + j + ((y + i) * c)]), &pixels[(i * width + j) * 32], 32);
2018-12-07 05:14:33 +01:00
}
BlitBitmapToWindow(windowId, pixels, x * 8, y * 8, width * 8, height * 8);
Free(pixels);
}
}
2019-10-18 01:22:03 +02:00
static void BlitBitmapToPartyWindow_LeftColumn(u8 windowId, u8 x, u8 y, u8 width, u8 height, u8 isEgg)
2018-12-07 05:14:33 +01:00
{
if (width == 0 && height == 0)
{
width = 10;
height = 7;
}
2019-05-13 00:41:25 +02:00
if (isEgg == FALSE)
BlitBitmapToPartyWindow(windowId, sMainSlotTileNums, 10, x, y, width, height);
2018-12-07 05:14:33 +01:00
else
2019-05-13 00:41:25 +02:00
BlitBitmapToPartyWindow(windowId, sMainSlotTileNums_Egg, 10, x, y, width, height);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void BlitBitmapToPartyWindow_RightColumn(u8 windowId, u8 x, u8 y, u8 width, u8 height, u8 isEgg)
2018-12-07 05:14:33 +01:00
{
if (width == 0 && height == 0)
{
width = 18;
height = 3;
}
2019-05-13 00:41:25 +02:00
if (isEgg == FALSE)
BlitBitmapToPartyWindow(windowId, sOtherSlotsTileNums, 18, x, y, width, height);
2018-12-07 05:14:33 +01:00
else
2019-05-13 00:41:25 +02:00
BlitBitmapToPartyWindow(windowId, sOtherSlotsTileNums_Egg, 18, x, y, width, height);
2018-12-07 05:14:33 +01:00
}
2019-05-13 00:41:25 +02:00
static void DrawEmptySlot(u8 windowId)
2018-12-07 05:14:33 +01:00
{
2019-05-13 00:41:25 +02:00
BlitBitmapToPartyWindow(windowId, sEmptySlotTileNums, 18, 0, 0, 18, 3);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
#define LOAD_PARTY_BOX_PAL(paletteIds, paletteOffsets) \
{ \
LoadPalette(GetPartyMenuPalBufferPtr(paletteIds[0]), paletteOffsets[0] + palNum, 2); \
LoadPalette(GetPartyMenuPalBufferPtr(paletteIds[1]), paletteOffsets[1] + palNum, 2); \
LoadPalette(GetPartyMenuPalBufferPtr(paletteIds[2]), paletteOffsets[2] + palNum, 2); \
2020-05-18 14:03:01 +02:00
}
2019-10-18 01:22:03 +02:00
static void LoadPartyBoxPalette(struct PartyMenuBox *menuBox, u8 palFlags)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
u8 palNum = GetWindowAttribute(menuBox->windowId, WINDOW_PALETTE_NUM) * 16;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (palFlags & PARTY_PAL_NO_MON)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxNoMonPalIds, sPartyBoxNoMonPalOffsets);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
else if (palFlags & PARTY_PAL_TO_SOFTBOIL)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (palFlags & PARTY_PAL_SELECTED)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
else
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
else if (palFlags & PARTY_PAL_SWITCHING)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
else if (palFlags & PARTY_PAL_TO_SWITCH)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (palFlags & PARTY_PAL_SELECTED)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
else
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
else if (palFlags & PARTY_PAL_FAINTED)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (palFlags & PARTY_PAL_SELECTED)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionFaintedPalIds, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
else
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxFaintedPalIds1, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxFaintedPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
else if (palFlags & PARTY_PAL_MULTI_ALT)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (palFlags & PARTY_PAL_SELECTED)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionMultiPalIds, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
else
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxMultiPalIds1, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxMultiPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
else if (palFlags & PARTY_PAL_SELECTED)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds1, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
else
{
2019-10-31 19:11:55 +01:00
LOAD_PARTY_BOX_PAL(sPartyBoxEmptySlotPalIds1, sPartyBoxPalOffsets1);
LOAD_PARTY_BOX_PAL(sPartyBoxEmptySlotPalIds2, sPartyBoxPalOffsets2);
2018-12-07 05:14:33 +01:00
}
}
2018-12-24 21:59:05 +01:00
static void DisplayPartyPokemonBarDetail(u8 windowId, const u8 *str, u8 color, const u8 *align)
2018-12-07 05:14:33 +01:00
{
2019-05-13 00:41:25 +02:00
AddTextPrinterParameterized3(windowId, 0, align[0], align[1], sFontColorTable[color], 0, str);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonNickname(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
2018-12-07 05:14:33 +01:00
{
u8 nickname[POKEMON_NAME_LENGTH + 1];
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
{
if (c == 1)
2019-10-18 01:22:03 +02:00
menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->dimensions[0] >> 3, menuBox->infoRects->dimensions[1] >> 3, menuBox->infoRects->dimensions[2] >> 3, menuBox->infoRects->dimensions[3] >> 3, FALSE);
2018-12-07 05:14:33 +01:00
GetMonNickname(mon, nickname);
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonBarDetail(menuBox->windowId, nickname, 0, menuBox->infoRects->dimensions);
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonLevelCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
2018-12-07 05:14:33 +01:00
{
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
{
u8 ailment = GetMonAilment(mon);
2018-12-20 02:27:44 +01:00
if (ailment == AILMENT_NONE || ailment == AILMENT_PKRS)
2018-12-07 05:14:33 +01:00
{
if (c != 0)
2019-10-18 01:22:03 +02:00
menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->dimensions[4] >> 3, (menuBox->infoRects->dimensions[5] >> 3) + 1, menuBox->infoRects->dimensions[6] >> 3, menuBox->infoRects->dimensions[7] >> 3, FALSE);
2018-12-07 05:14:33 +01:00
if (c != 2)
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonLevel(GetMonData(mon, MON_DATA_LEVEL), menuBox);
2018-12-07 05:14:33 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonLevel(u8 level, struct PartyMenuBox *menuBox)
2018-12-07 05:14:33 +01:00
{
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar2, level, STR_CONV_MODE_LEFT_ALIGN, 3);
2018-12-07 05:14:33 +01:00
StringCopy(gStringVar1, gText_LevelSymbol);
StringAppend(gStringVar1, gStringVar2);
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonBarDetail(menuBox->windowId, gStringVar1, 0, &menuBox->infoRects->dimensions[4]);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonGenderNidoranCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
2018-12-07 05:14:33 +01:00
{
u8 nickname[POKEMON_NAME_LENGTH + 1];
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
if (c == 1)
2019-10-18 01:22:03 +02:00
menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->dimensions[8] >> 3, (menuBox->infoRects->dimensions[9] >> 3) + 1, menuBox->infoRects->dimensions[10] >> 3, menuBox->infoRects->dimensions[11] >> 3, FALSE);
2018-12-07 05:14:33 +01:00
GetMonNickname(mon, nickname);
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonGender(GetMonGender(mon), GetMonData(mon, MON_DATA_SPECIES), nickname, menuBox);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonGender(u8 gender, u16 species, u8 *nickname, struct PartyMenuBox *menuBox)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
u8 palNum = GetWindowAttribute(menuBox->windowId, WINDOW_PALETTE_NUM) * 16;
2018-12-22 17:32:21 +01:00
2018-12-20 02:50:36 +01:00
if (species == SPECIES_NONE)
return;
if ((species == SPECIES_NIDORAN_M || species == SPECIES_NIDORAN_F) && StringCompare(nickname, gSpeciesNames[species]) == 0)
2018-12-07 05:14:33 +01:00
return;
switch (gender)
{
2018-12-22 17:32:21 +01:00
case MON_MALE:
2019-10-18 01:22:03 +02:00
LoadPalette(GetPartyMenuPalBufferPtr(sGenderMalePalIds[0]), sGenderPalOffsets[0] + palNum, 2);
LoadPalette(GetPartyMenuPalBufferPtr(sGenderMalePalIds[1]), sGenderPalOffsets[1] + palNum, 2);
DisplayPartyPokemonBarDetail(menuBox->windowId, gText_MaleSymbol, 2, &menuBox->infoRects->dimensions[8]);
2018-12-22 17:32:21 +01:00
break;
case MON_FEMALE:
2019-10-18 01:22:03 +02:00
LoadPalette(GetPartyMenuPalBufferPtr(sGenderFemalePalIds[0]), sGenderPalOffsets[0] + palNum, 2);
LoadPalette(GetPartyMenuPalBufferPtr(sGenderFemalePalIds[1]), sGenderPalOffsets[1] + palNum, 2);
DisplayPartyPokemonBarDetail(menuBox->windowId, gText_FemaleSymbol, 2, &menuBox->infoRects->dimensions[8]);
2018-12-22 17:32:21 +01:00
break;
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonHPCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
2018-12-07 05:14:33 +01:00
{
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
{
if (c != 0)
2019-10-18 01:22:03 +02:00
menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->dimensions[12] >> 3, (menuBox->infoRects->dimensions[13] >> 3) + 1, menuBox->infoRects->dimensions[14] >> 3, menuBox->infoRects->dimensions[15] >> 3, FALSE);
2018-12-07 05:14:33 +01:00
if (c != 2)
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonHP(GetMonData(mon, MON_DATA_HP), menuBox);
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonHP(u16 hp, struct PartyMenuBox *menuBox)
2018-12-07 05:14:33 +01:00
{
2019-09-30 21:43:44 +02:00
u8 *strOut = ConvertIntToDecimalStringN(gStringVar1, hp, STR_CONV_MODE_RIGHT_ALIGN, 3);
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
strOut[0] = CHAR_SLASH;
strOut[1] = EOS;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonBarDetail(menuBox->windowId, gStringVar1, 0, &menuBox->infoRects->dimensions[12]);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonMaxHPCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
2018-12-07 05:14:33 +01:00
{
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
{
if (c != 0)
2019-10-18 01:22:03 +02:00
menuBox->infoRects->blitFunc(menuBox->windowId, (menuBox->infoRects->dimensions[16] >> 3) + 1, (menuBox->infoRects->dimensions[17] >> 3) + 1, menuBox->infoRects->dimensions[18] >> 3, menuBox->infoRects->dimensions[19] >> 3, FALSE);
2018-12-07 05:14:33 +01:00
if (c != 2)
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonMaxHP(GetMonData(mon, MON_DATA_MAX_HP), menuBox);
2018-12-07 05:14:33 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonMaxHP(u16 maxhp, struct PartyMenuBox *menuBox)
2018-12-07 05:14:33 +01:00
{
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar2, maxhp, STR_CONV_MODE_RIGHT_ALIGN, 3);
2018-12-07 05:14:33 +01:00
StringCopy(gStringVar1, gText_Slash);
StringAppend(gStringVar1, gStringVar2);
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonBarDetail(menuBox->windowId, gStringVar1, 0, &menuBox->infoRects->dimensions[16]);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonHPBarCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox)
2018-12-07 05:14:33 +01:00
{
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonHPBar(GetMonData(mon, MON_DATA_HP), GetMonData(mon, MON_DATA_MAX_HP), menuBox);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonHPBar(u16 hp, u16 maxhp, struct PartyMenuBox *menuBox)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
u8 palNum = GetWindowAttribute(menuBox->windowId, WINDOW_PALETTE_NUM) * 16;
2018-12-07 05:14:33 +01:00
u8 hpFraction;
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
switch (GetHPBarLevel(hp, maxhp))
{
2018-12-22 17:32:21 +01:00
case HP_BAR_GREEN:
case HP_BAR_FULL:
2019-10-18 01:22:03 +02:00
LoadPalette(GetPartyMenuPalBufferPtr(sHPBarGreenPalIds[0]), sHPBarPalOffsets[0] + palNum, 2);
LoadPalette(GetPartyMenuPalBufferPtr(sHPBarGreenPalIds[1]), sHPBarPalOffsets[1] + palNum, 2);
2018-12-22 17:32:21 +01:00
break;
case HP_BAR_YELLOW:
2019-10-18 01:22:03 +02:00
LoadPalette(GetPartyMenuPalBufferPtr(sHPBarYellowPalIds[0]), sHPBarPalOffsets[0] + palNum, 2);
LoadPalette(GetPartyMenuPalBufferPtr(sHPBarYellowPalIds[1]), sHPBarPalOffsets[1] + palNum, 2);
2018-12-22 17:32:21 +01:00
break;
default:
2019-10-18 01:22:03 +02:00
LoadPalette(GetPartyMenuPalBufferPtr(sHPBarRedPalIds[0]), sHPBarPalOffsets[0] + palNum, 2);
LoadPalette(GetPartyMenuPalBufferPtr(sHPBarRedPalIds[1]), sHPBarPalOffsets[1] + palNum, 2);
2018-12-22 17:32:21 +01:00
break;
2018-12-07 05:14:33 +01:00
}
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
hpFraction = GetScaledHPFraction(hp, maxhp, menuBox->infoRects->dimensions[22]);
FillWindowPixelRect(menuBox->windowId, sHPBarPalOffsets[1], menuBox->infoRects->dimensions[20], menuBox->infoRects->dimensions[21], hpFraction, 1);
FillWindowPixelRect(menuBox->windowId, sHPBarPalOffsets[0], menuBox->infoRects->dimensions[20], menuBox->infoRects->dimensions[21] + 1, hpFraction, 2);
if (hpFraction != menuBox->infoRects->dimensions[22])
2018-12-07 05:14:33 +01:00
{
// This appears to be an alternating fill
2019-10-18 01:22:03 +02:00
FillWindowPixelRect(menuBox->windowId, 0x0D, menuBox->infoRects->dimensions[20] + hpFraction, menuBox->infoRects->dimensions[21], menuBox->infoRects->dimensions[22] - hpFraction, 1);
FillWindowPixelRect(menuBox->windowId, 0x02, menuBox->infoRects->dimensions[20] + hpFraction, menuBox->infoRects->dimensions[21] + 1, menuBox->infoRects->dimensions[22] - hpFraction, 2);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
CopyWindowToVram(menuBox->windowId, 2);
2018-12-07 05:14:33 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyPokemonDescriptionText(u8 stringID, struct PartyMenuBox *menuBox, u8 c)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (c)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
int width = ((menuBox->infoRects->descTextLeft % 8) + menuBox->infoRects->descTextWidth + 7) / 8;
int height = ((menuBox->infoRects->descTextTop % 8) + menuBox->infoRects->descTextHeight + 7) / 8;
menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->descTextLeft >> 3, menuBox->infoRects->descTextTop >> 3, width, height, TRUE);
2018-12-07 05:14:33 +01:00
}
if (c != 2)
2019-10-18 01:22:03 +02:00
AddTextPrinterParameterized3(menuBox->windowId, 1, menuBox->infoRects->descTextLeft, menuBox->infoRects->descTextTop, sFontColorTable[0], 0, sDescriptionStringTable[stringID]);
2018-12-07 05:14:33 +01:00
}
static void PartyMenuRemoveWindow(u8 *ptr)
2018-12-07 05:14:33 +01:00
{
if (*ptr != 0xFF)
{
ClearStdWindowAndFrameToTransparent(*ptr, 0);
2018-12-07 05:14:33 +01:00
RemoveWindow(*ptr);
*ptr = 0xFF;
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-07 05:14:33 +01:00
}
}
2019-10-31 19:11:55 +01:00
void DisplayPartyMenuStdMessage(u32 stringId)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
u8 *windowPtr = &sPartyMenuInternal->windowId[1];
2018-12-22 17:32:21 +01:00
2018-12-07 05:14:33 +01:00
if (*windowPtr != 0xFF)
PartyMenuRemoveWindow(windowPtr);
2018-12-22 17:32:21 +01:00
2019-10-31 19:11:55 +01:00
if (stringId != PARTY_MSG_NONE)
2018-12-07 05:14:33 +01:00
{
2019-10-31 19:11:55 +01:00
switch (stringId)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
case PARTY_MSG_DO_WHAT_WITH_MON:
*windowPtr = AddWindow(&sDoWhatWithMonMsgWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MSG_DO_WHAT_WITH_ITEM:
*windowPtr = AddWindow(&sDoWhatWithItemMsgWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MSG_DO_WHAT_WITH_MAIL:
*windowPtr = AddWindow(&sDoWhatWithMailMsgWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MSG_RESTORE_WHICH_MOVE:
case PARTY_MSG_BOOST_PP_WHICH_MOVE:
*windowPtr = AddWindow(&sWhichMoveMsgWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MSG_ALREADY_HOLDING_ONE:
*windowPtr = AddWindow(&sAlreadyHoldingOneMsgWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
default:
2019-10-18 01:22:03 +02:00
*windowPtr = AddWindow(&sDefaultPartyMsgWindowTemplate);
2018-12-22 17:32:21 +01:00
break;
2018-12-07 05:14:33 +01:00
}
2019-10-26 03:55:01 +02:00
2019-10-31 19:11:55 +01:00
if (stringId == PARTY_MSG_CHOOSE_MON)
2018-12-07 05:14:33 +01:00
{
2019-10-18 01:22:03 +02:00
if (sPartyMenuInternal->chooseHalf)
2019-10-31 19:11:55 +01:00
stringId = PARTY_MSG_CHOOSE_MON_AND_CONFIRM;
2019-10-26 03:55:01 +02:00
else if (!ShouldUseChooseMonText())
2019-10-31 19:11:55 +01:00
stringId = PARTY_MSG_CHOOSE_MON_OR_CANCEL;
2018-12-07 05:14:33 +01:00
}
DrawStdFrameWithCustomTileAndPalette(*windowPtr, FALSE, 0x4F, 0xD);
2019-10-31 19:11:55 +01:00
StringExpandPlaceholders(gStringVar4, sActionStringTable[stringId]);
2018-12-07 05:14:33 +01:00
AddTextPrinterParameterized(*windowPtr, 1, gStringVar4, 0, 1, 0, 0);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-07 05:14:33 +01:00
}
}
2019-10-26 03:55:01 +02:00
static bool8 ShouldUseChooseMonText(void)
2018-12-07 05:14:33 +01:00
{
struct Pokemon *party = gPlayerParty;
u8 i;
2019-10-18 01:22:03 +02:00
u8 numAliveMons = 0;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (gPartyMenu.action == PARTY_ACTION_SEND_OUT)
2018-12-07 05:14:33 +01:00
return TRUE;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
for (i = 0; i < PARTY_SIZE; i++)
2018-12-07 05:14:33 +01:00
{
2018-12-20 02:27:44 +01:00
if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE && (GetMonData(&party[i], MON_DATA_HP) != 0 || GetMonData(&party[i], MON_DATA_IS_EGG)))
2019-10-18 01:22:03 +02:00
numAliveMons++;
if (numAliveMons > 1)
2018-12-07 05:14:33 +01:00
return TRUE;
}
return FALSE;
}
2018-12-10 08:38:23 +01:00
2019-10-18 01:22:03 +02:00
static u8 DisplaySelectionWindow(u8 windowType)
2018-12-10 08:38:23 +01:00
{
struct WindowTemplate window;
u8 cursorDimension;
u8 fontAttribute;
u8 i;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
switch (windowType)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
case SELECTWINDOW_ACTIONS:
SetWindowTemplateFields(&window, 2, 19, 19 - (sPartyMenuInternal->numActions * 2), 10, sPartyMenuInternal->numActions * 2, 14, 0x2E9);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case SELECTWINDOW_ITEM:
window = sItemGiveTakeWindowTemplate;
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case SELECTWINDOW_MAIL:
window = sMailReadTakeWindowTemplate;
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
default: // SELECTWINDOW_MOVES
window = sMoveSelectWindowTemplate;
2018-12-22 17:32:21 +01:00
break;
2018-12-10 08:38:23 +01:00
}
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->windowId[0] = AddWindow(&window);
DrawStdFrameWithCustomTileAndPalette(sPartyMenuInternal->windowId[0], FALSE, 0x4F, 13);
2019-10-26 03:55:01 +02:00
if (windowType == SELECTWINDOW_MOVES)
2019-10-18 01:22:03 +02:00
return sPartyMenuInternal->windowId[0];
2018-12-10 08:38:23 +01:00
cursorDimension = GetMenuCursorDimensionByFont(1, 0);
fontAttribute = GetFontAttribute(1, 2);
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
for (i = 0; i < sPartyMenuInternal->numActions; i++)
2018-12-10 08:38:23 +01:00
{
2019-10-26 03:55:01 +02:00
u8 fontColorsId = (sPartyMenuInternal->actions[i] >= MENU_FIELD_MOVES) ? 4 : 3;
AddTextPrinterParameterized4(sPartyMenuInternal->windowId[0], 1, cursorDimension, (i * 16) + 1, fontAttribute, 0, sFontColorTable[fontColorsId], 0, sCursorOptions[sPartyMenuInternal->actions[i]].text);
2018-12-10 08:38:23 +01:00
}
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
InitMenuInUpperLeftCorner(sPartyMenuInternal->windowId[0], sPartyMenuInternal->numActions, 0, 1);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
return sPartyMenuInternal->windowId[0];
2018-12-10 08:38:23 +01:00
}
static void PartyMenuPrintText(const u8 *text)
2018-12-10 08:38:23 +01:00
{
DrawStdFrameWithCustomTileAndPalette(6, FALSE, 0x4F, 13);
2018-12-10 08:38:23 +01:00
gTextFlags.canABSpeedUpPrint = TRUE;
AddTextPrinterParameterized2(6, 1, text, GetPlayerTextSpeedDelay(), 0, 2, 1, 3);
}
2019-10-18 01:22:03 +02:00
static void PartyMenuDisplayYesNoMenu(void)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
CreateYesNoMenu(&sPartyMenuYesNoWindowTemplate, 0x4F, 13, 0);
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static u8 CreateLevelUpStatsWindow(void)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->windowId[0] = AddWindow(&sLevelUpStatsWindowTemplate);
DrawStdFrameWithCustomTileAndPalette(sPartyMenuInternal->windowId[0], FALSE, 0x4F, 13);
return sPartyMenuInternal->windowId[0];
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static void RemoveLevelUpStatsWindow(void)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
ClearWindowTilemap(sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static void SetPartyMonSelectionActions(struct Pokemon *mons, u8 slotId, u8 action)
2018-12-10 08:38:23 +01:00
{
u8 i;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (action == ACTIONS_NONE)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
SetPartyMonFieldSelectionActions(mons, slotId);
2018-12-10 08:38:23 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->numActions = sPartyMenuActionCounts[action];
for (i = 0; i < sPartyMenuInternal->numActions; i++)
sPartyMenuInternal->actions[i] = sPartyMenuActions[action][i];
2018-12-10 08:38:23 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void SetPartyMonFieldSelectionActions(struct Pokemon *mons, u8 slotId)
2018-12-10 08:38:23 +01:00
{
u8 i, j;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->numActions = 0;
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SUMMARY);
// Add field moves to action list
2018-12-17 08:39:17 +01:00
for (i = 0; i < MAX_MON_MOVES; i++)
2018-12-10 08:38:23 +01:00
{
2018-12-24 21:59:05 +01:00
for (j = 0; sFieldMoves[j] != FIELD_MOVE_TERMINATOR; j++)
2018-12-10 08:38:23 +01:00
{
2019-05-13 00:41:25 +02:00
if (GetMonData(&mons[slotId], i + MON_DATA_MOVE1) == sFieldMoves[j])
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, j + MENU_FIELD_MOVES);
2018-12-10 08:38:23 +01:00
break;
}
}
}
2018-12-24 21:59:05 +01:00
2018-12-10 08:38:23 +01:00
if (!InBattlePike())
{
if (GetMonData(&mons[1], MON_DATA_SPECIES) != SPECIES_NONE)
2019-10-18 01:22:03 +02:00
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SWITCH);
2019-05-13 00:41:25 +02:00
if (ItemIsMail(GetMonData(&mons[slotId], MON_DATA_HELD_ITEM)))
2019-10-18 01:22:03 +02:00
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_MAIL);
2018-12-10 08:38:23 +01:00
else
2019-10-18 01:22:03 +02:00
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_ITEM);
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_CANCEL1);
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static u8 GetPartyMenuActionsType(struct Pokemon *mon)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
u32 actionType;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
switch (gPartyMenu.menuType)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
case PARTY_MENU_TYPE_FIELD:
2019-12-14 09:58:20 +01:00
if (InMultiPartnerRoom() == TRUE || GetMonData(mon, MON_DATA_IS_EGG))
2019-10-18 01:22:03 +02:00
actionType = ACTIONS_SWITCH;
2018-12-22 17:32:21 +01:00
else
2019-10-18 01:22:03 +02:00
actionType = ACTIONS_NONE; // actions populated by SetPartyMonFieldSelectionActions
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MENU_TYPE_IN_BATTLE:
actionType = GetPartyMenuActionsTypeInBattle(mon);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MENU_TYPE_CHOOSE_HALF:
switch (GetPartySlotEntryStatus(gPartyMenu.slotId))
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
default: // Not eligible
actionType = ACTIONS_SUMMARY_ONLY;
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case 0: // Eligible
actionType = ACTIONS_ENTER;
2018-12-10 08:38:23 +01:00
break;
2019-10-18 01:22:03 +02:00
case 1: // Already selected
actionType = ACTIONS_NO_ENTRY;
2018-12-10 08:38:23 +01:00
break;
2018-12-22 17:32:21 +01:00
}
break;
2019-10-18 01:22:03 +02:00
case PARTY_MENU_TYPE_DAYCARE:
actionType = (GetMonData(mon, MON_DATA_IS_EGG)) ? ACTIONS_SUMMARY_ONLY : ACTIONS_STORE;
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MENU_TYPE_UNION_ROOM_REGISTER:
actionType = ACTIONS_REGISTER;
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MENU_TYPE_UNION_ROOM_TRADE:
actionType = ACTIONS_TRADE;
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MENU_TYPE_SPIN_TRADE:
actionType = ACTIONS_SPIN_TRADE;
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case PARTY_MENU_TYPE_STORE_PYRAMID_HELD_ITEMS:
actionType = ACTIONS_TAKEITEM_TOSS;
2018-12-22 17:32:21 +01:00
break;
2019-10-26 03:55:01 +02:00
// The following have no selection actions (i.e. they exit immediately upon selection)
2019-10-18 01:22:03 +02:00
// PARTY_MENU_TYPE_CONTEST
// PARTY_MENU_TYPE_CHOOSE_MON
2019-10-26 03:55:01 +02:00
// PARTY_MENU_TYPE_MULTI_SHOWCASE
2019-10-18 01:22:03 +02:00
// PARTY_MENU_TYPE_MOVE_RELEARNER
// PARTY_MENU_TYPE_MINIGAME
2018-12-22 17:32:21 +01:00
default:
2019-10-18 01:22:03 +02:00
actionType = ACTIONS_NONE;
2018-12-22 17:32:21 +01:00
break;
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
return actionType;
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static bool8 CreateSelectionWindow(u8 taskId)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-10 08:38:23 +01:00
u16 item;
2018-12-22 17:32:21 +01:00
2018-12-10 08:38:23 +01:00
GetMonNickname(mon, gStringVar1);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
if (gPartyMenu.menuType != PARTY_MENU_TYPE_STORE_PYRAMID_HELD_ITEMS)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, GetPartyMenuActionsType(mon));
DisplaySelectionWindow(SELECTWINDOW_ACTIONS);
DisplayPartyMenuStdMessage(PARTY_MSG_DO_WHAT_WITH_MON);
2018-12-10 08:38:23 +01:00
}
else
{
item = GetMonData(mon, MON_DATA_HELD_ITEM);
if (item != ITEM_NONE)
{
2019-10-18 01:22:03 +02:00
SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, GetPartyMenuActionsType(mon));
DisplaySelectionWindow(SELECTWINDOW_ITEM);
2018-12-10 08:38:23 +01:00
CopyItemName(item, gStringVar2);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_ALREADY_HOLDING_ONE);
2018-12-10 08:38:23 +01:00
}
else
{
StringExpandPlaceholders(gStringVar4, gText_PkmnNotHolding);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_UpdateHeldItemSprite;
2018-12-10 08:38:23 +01:00
return FALSE;
}
}
return TRUE;
}
2019-10-18 01:22:03 +02:00
static void Task_TryCreateSelectionWindow(u8 taskId)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
if (CreateSelectionWindow(taskId))
2018-12-10 08:38:23 +01:00
{
gTasks[taskId].data[0] = 0xFF;
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_HandleSelectionMenuInput;
2018-12-10 08:38:23 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_HandleSelectionMenuInput(u8 taskId)
2018-12-10 08:38:23 +01:00
{
2020-05-14 10:37:09 +02:00
if (!gPaletteFade.active && MenuHelpers_CallLinkSomething() != TRUE)
2018-12-10 08:38:23 +01:00
{
2018-12-24 21:59:05 +01:00
s8 input;
s16 *data = gTasks[taskId].data;
2019-10-18 01:22:03 +02:00
if (sPartyMenuInternal->numActions <= 3)
2018-12-10 08:38:23 +01:00
input = Menu_ProcessInputNoWrapAround_other();
else
input = ProcessMenuInput_other();
2018-12-24 21:59:05 +01:00
2018-12-20 22:53:08 +01:00
data[0] = Menu_GetCursorPos();
2018-12-24 21:59:05 +01:00
switch (input)
2018-12-10 08:38:23 +01:00
{
2018-12-24 21:59:05 +01:00
case MENU_NOTHING_CHOSEN:
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[2]);
sCursorOptions[sPartyMenuInternal->actions[sPartyMenuInternal->numActions - 1]].func(taskId);
2018-12-24 21:59:05 +01:00
break;
default:
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[2]);
sCursorOptions[sPartyMenuInternal->actions[input]].func(taskId);
2018-12-24 21:59:05 +01:00
break;
2018-12-10 08:38:23 +01:00
}
}
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Summary(u8 taskId)
2018-12-10 08:38:23 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->exitCallback = CB2_ShowPokemonSummaryScreen;
Task_ClosePartyMenu(taskId);
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static void CB2_ShowPokemonSummaryScreen(void)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
UpdatePartyToBattleOrder();
2020-05-18 14:03:01 +02:00
ShowPokemonSummaryScreen(PSS_MODE_LOCK_MOVES, gPlayerParty, gPartyMenu.slotId, gPlayerPartyCount - 1, CB2_ReturnToPartyMenuFromSummaryScreen);
2018-12-10 08:38:23 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
ShowPokemonSummaryScreen(PSS_MODE_NORMAL, gPlayerParty, gPartyMenu.slotId, gPlayerPartyCount - 1, CB2_ReturnToPartyMenuFromSummaryScreen);
2018-12-10 08:38:23 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void CB2_ReturnToPartyMenuFromSummaryScreen(void)
2018-12-10 08:38:23 +01:00
{
gPaletteFade.bufferTransferDisabled = TRUE;
2019-10-18 01:22:03 +02:00
gPartyMenu.slotId = gLastViewedMonIndex;
InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_DO_WHAT_WITH_MON, Task_TryCreateSelectionWindow, gPartyMenu.exitCallback);
2018-12-10 08:38:23 +01:00
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Switch(u8 taskId)
2018-12-10 08:38:23 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
gPartyMenu.action = PARTY_ACTION_SWITCH;
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
DisplayPartyMenuStdMessage(PARTY_MSG_MOVE_TO_WHERE);
AnimatePartySlot(gPartyMenu.slotId, 1);
gPartyMenu.slotId2 = gPartyMenu.slotId;
gTasks[taskId].func = Task_HandleChooseMonInput;
}
#define tSlot1Left data[0]
#define tSlot1Top data[1]
#define tSlot1Width data[2]
#define tSlot1Height data[3]
#define tSlot2Left data[4]
#define tSlot2Top data[5]
#define tSlot2Width data[6]
#define tSlot2Height data[7]
#define tSlot1Offset data[8]
#define tSlot2Offset data[9]
#define tSlot1SlideDir data[10]
#define tSlot2SlideDir data[11]
static void SwitchSelectedMons(u8 taskId)
2018-12-10 08:38:23 +01:00
{
s16 *data = gTasks[taskId].data;
u8 windowIds[2];
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (gPartyMenu.slotId2 == gPartyMenu.slotId)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
FinishTwoMonAction(taskId);
2018-12-10 08:38:23 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
// Initialize switching party mons slide animation
windowIds[0] = sPartyMenuBoxes[gPartyMenu.slotId].windowId;
tSlot1Left = GetWindowAttribute(windowIds[0], WINDOW_TILEMAP_LEFT);
tSlot1Top = GetWindowAttribute(windowIds[0], WINDOW_TILEMAP_TOP);
tSlot1Width = GetWindowAttribute(windowIds[0], WINDOW_WIDTH);
tSlot1Height = GetWindowAttribute(windowIds[0], WINDOW_HEIGHT);
tSlot1Offset = 0;
if (tSlot1Width == 10)
tSlot1SlideDir = -1;
2018-12-10 08:38:23 +01:00
else
2019-10-18 01:22:03 +02:00
tSlot1SlideDir = 1;
windowIds[1] = sPartyMenuBoxes[gPartyMenu.slotId2].windowId;
tSlot2Left = GetWindowAttribute(windowIds[1], WINDOW_TILEMAP_LEFT);
tSlot2Top = GetWindowAttribute(windowIds[1], WINDOW_TILEMAP_TOP);
tSlot2Width = GetWindowAttribute(windowIds[1], WINDOW_WIDTH);
tSlot2Height = GetWindowAttribute(windowIds[1], WINDOW_HEIGHT);
tSlot2Offset = 0;
if (tSlot2Width == 10)
tSlot2SlideDir = -1;
2018-12-10 08:38:23 +01:00
else
2019-10-18 01:22:03 +02:00
tSlot2SlideDir = 1;
sSlot1TilemapBuffer = Alloc(tSlot1Width * (tSlot1Height << 1));
sSlot2TilemapBuffer = Alloc(tSlot2Width * (tSlot2Height << 1));
CopyToBufferFromBgTilemap(0, sSlot1TilemapBuffer, tSlot1Left, tSlot1Top, tSlot1Width, tSlot1Height);
CopyToBufferFromBgTilemap(0, sSlot2TilemapBuffer, tSlot2Left, tSlot2Top, tSlot2Width, tSlot2Height);
2018-12-10 08:38:23 +01:00
ClearWindowTilemap(windowIds[0]);
ClearWindowTilemap(windowIds[1]);
2019-10-18 01:22:03 +02:00
gPartyMenu.action = PARTY_ACTION_SWITCHING;
AnimatePartySlot(gPartyMenu.slotId, 1);
AnimatePartySlot(gPartyMenu.slotId2, 1);
SlidePartyMenuBoxOneStep(taskId);
gTasks[taskId].func = Task_SlideSelectedSlotsOffscreen;
2018-12-10 08:38:23 +01:00
}
}
2019-10-18 01:22:03 +02:00
// returns FALSE if the slot has slid fully offscreen / back onscreen
2019-10-31 19:11:55 +01:00
static bool8 TryMovePartySlot(s16 x, s16 width, u8 *leftMove, u8 *newX, u8 *newWidth)
2018-12-10 08:38:23 +01:00
{
2019-10-31 19:11:55 +01:00
if ((x + width) < 0)
2018-12-10 08:38:23 +01:00
return FALSE;
2019-10-31 19:11:55 +01:00
if (x > 31)
2018-12-22 17:32:21 +01:00
return FALSE;
2019-10-31 19:11:55 +01:00
if (x < 0)
2018-12-10 08:38:23 +01:00
{
2019-10-31 19:11:55 +01:00
*leftMove = x * -1;
*newX = 0;
*newWidth = width + x;
2018-12-10 08:38:23 +01:00
}
else
{
2019-10-31 19:11:55 +01:00
*leftMove = 0;
*newX = x;
if ((x + width) > 31)
*newWidth = 32 - x;
2018-12-10 08:38:23 +01:00
else
2019-10-31 19:11:55 +01:00
*newWidth = width;
2018-12-22 17:32:21 +01:00
}
return TRUE;
2018-12-10 08:38:23 +01:00
}
2019-10-31 19:11:55 +01:00
static void MoveAndBufferPartySlot(const void *rectSrc, s16 x, s16 y, s16 width, s16 height, s16 dir)
2018-12-10 08:38:23 +01:00
{
2019-10-31 19:11:55 +01:00
// The use of the dimension parameters here is a mess
u8 leftMove, newX, newWidth; // leftMove is used as a srcX, newX is used as both x and srcHeight, newWidth is used as both width and destY
2018-12-22 17:32:21 +01:00
2019-10-31 19:11:55 +01:00
if (TryMovePartySlot(x, width, &leftMove, &newX, &newWidth))
2018-12-10 08:38:23 +01:00
{
2019-10-31 19:11:55 +01:00
FillBgTilemapBufferRect_Palette0(0, 0, newX, y, newWidth, height);
if (TryMovePartySlot(x + dir, width, &leftMove, &newX, &newWidth))
CopyRectToBgTilemapBufferRect(0, rectSrc, leftMove, 0, width, height, newX, y, newWidth, height, 17, 0, 0);
2018-12-10 08:38:23 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void MovePartyMenuBoxSprites(struct PartyMenuBox *menuBox, s16 offset)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
gSprites[menuBox->pokeballSpriteId].pos2.x += offset * 8;
gSprites[menuBox->itemSpriteId].pos2.x += offset * 8;
gSprites[menuBox->monSpriteId].pos2.x += offset * 8;
gSprites[menuBox->statusSpriteId].pos2.x += offset * 8;
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static void SlidePartyMenuBoxSpritesOneStep(u8 taskId)
2018-12-10 08:38:23 +01:00
{
s16 *data = gTasks[taskId].data;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (tSlot1SlideDir != 0)
MovePartyMenuBoxSprites(&sPartyMenuBoxes[gPartyMenu.slotId], tSlot1SlideDir);
if (tSlot2SlideDir != 0)
MovePartyMenuBoxSprites(&sPartyMenuBoxes[gPartyMenu.slotId2], tSlot2SlideDir);
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static void SlidePartyMenuBoxOneStep(u8 taskId)
2018-12-10 08:38:23 +01:00
{
s16 *data = gTasks[taskId].data;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (tSlot1SlideDir != 0)
MoveAndBufferPartySlot(sSlot1TilemapBuffer, tSlot1Left + tSlot1Offset, tSlot1Top, tSlot1Width, tSlot1Height, tSlot1SlideDir);
if (tSlot2SlideDir != 0)
MoveAndBufferPartySlot(sSlot2TilemapBuffer, tSlot2Left + tSlot2Offset, tSlot2Top, tSlot2Width, tSlot2Height, tSlot2SlideDir);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_SlideSelectedSlotsOffscreen(u8 taskId)
2018-12-10 08:38:23 +01:00
{
s16 *data = gTasks[taskId].data;
2019-10-18 01:22:03 +02:00
u16 slidingSlotPositions[2];
SlidePartyMenuBoxOneStep(taskId);
SlidePartyMenuBoxSpritesOneStep(taskId);
tSlot1Offset += tSlot1SlideDir;
tSlot2Offset += tSlot2SlideDir;
slidingSlotPositions[0] = tSlot1Left + tSlot1Offset;
slidingSlotPositions[1] = tSlot2Left + tSlot2Offset;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
// Both slots have slid offscreen
if (slidingSlotPositions[0] > 33 && slidingSlotPositions[1] > 33)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
tSlot1SlideDir *= -1;
tSlot2SlideDir *= -1;
SwitchPartyMon();
DisplayPartyPokemonData(gPartyMenu.slotId);
DisplayPartyPokemonData(gPartyMenu.slotId2);
PutWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId].windowId);
PutWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId2].windowId);
CopyToBufferFromBgTilemap(0, sSlot1TilemapBuffer, tSlot1Left, tSlot1Top, tSlot1Width, tSlot1Height);
CopyToBufferFromBgTilemap(0, sSlot2TilemapBuffer, tSlot2Left, tSlot2Top, tSlot2Width, tSlot2Height);
ClearWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId].windowId);
ClearWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId2].windowId);
gTasks[taskId].func = Task_SlideSelectedSlotsOnscreen;
2018-12-10 08:38:23 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_SlideSelectedSlotsOnscreen(u8 taskId)
2018-12-10 08:38:23 +01:00
{
s16 *data = gTasks[taskId].data;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
SlidePartyMenuBoxOneStep(taskId);
SlidePartyMenuBoxSpritesOneStep(taskId);
2020-05-18 14:03:01 +02:00
2019-10-18 01:22:03 +02:00
// Both slots have slid back onscreen
if (tSlot1SlideDir == 0 && tSlot2SlideDir == 0)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
PutWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId].windowId);
PutWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId2].windowId);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2019-10-18 01:22:03 +02:00
Free(sSlot1TilemapBuffer);
Free(sSlot2TilemapBuffer);
FinishTwoMonAction(taskId);
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
// Continue sliding
2018-12-10 08:38:23 +01:00
else
{
2019-10-18 01:22:03 +02:00
tSlot1Offset += tSlot1SlideDir;
tSlot2Offset += tSlot2SlideDir;
if (tSlot1Offset == 0)
tSlot1SlideDir = 0;
if (tSlot2Offset == 0)
tSlot2SlideDir = 0;
2018-12-10 08:38:23 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void SwitchMenuBoxSprites(u8 *spriteIdPtr1, u8 *spriteIdPtr2)
2018-12-10 08:38:23 +01:00
{
u8 spriteIdBuffer = *spriteIdPtr1;
u16 xBuffer1, yBuffer1, xBuffer2, yBuffer2;
2018-12-22 17:32:21 +01:00
2018-12-10 08:38:23 +01:00
*spriteIdPtr1 = *spriteIdPtr2;
*spriteIdPtr2 = spriteIdBuffer;
xBuffer1 = gSprites[*spriteIdPtr1].pos1.x;
yBuffer1 = gSprites[*spriteIdPtr1].pos1.y;
xBuffer2 = gSprites[*spriteIdPtr1].pos2.x;
yBuffer2 = gSprites[*spriteIdPtr1].pos2.y;
gSprites[*spriteIdPtr1].pos1.x = gSprites[*spriteIdPtr2].pos1.x;
gSprites[*spriteIdPtr1].pos1.y = gSprites[*spriteIdPtr2].pos1.y;
gSprites[*spriteIdPtr1].pos2.x = gSprites[*spriteIdPtr2].pos2.x;
gSprites[*spriteIdPtr1].pos2.y = gSprites[*spriteIdPtr2].pos2.y;
gSprites[*spriteIdPtr2].pos1.x = xBuffer1;
gSprites[*spriteIdPtr2].pos1.y = yBuffer1;
gSprites[*spriteIdPtr2].pos2.x = xBuffer2;
2018-12-22 17:32:21 +01:00
gSprites[*spriteIdPtr2].pos2.y = yBuffer2;
2018-12-10 08:38:23 +01:00
}
2019-10-18 01:22:03 +02:00
static void SwitchPartyMon(void)
2018-12-10 08:38:23 +01:00
{
2019-10-18 01:22:03 +02:00
struct PartyMenuBox *menuBoxes[2];
2018-12-10 08:38:23 +01:00
struct Pokemon *mon1, *mon2;
struct Pokemon *monBuffer;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
menuBoxes[0] = &sPartyMenuBoxes[gPartyMenu.slotId];
menuBoxes[1] = &sPartyMenuBoxes[gPartyMenu.slotId2];
mon1 = &gPlayerParty[gPartyMenu.slotId];
mon2 = &gPlayerParty[gPartyMenu.slotId2];
2018-12-10 08:38:23 +01:00
monBuffer = Alloc(sizeof(struct Pokemon));
*monBuffer = *mon1;
*mon1 = *mon2;
*mon2 = *monBuffer;
Free(monBuffer);
2019-10-18 01:22:03 +02:00
SwitchMenuBoxSprites(&menuBoxes[0]->pokeballSpriteId, &menuBoxes[1]->pokeballSpriteId);
SwitchMenuBoxSprites(&menuBoxes[0]->itemSpriteId, &menuBoxes[1]->itemSpriteId);
SwitchMenuBoxSprites(&menuBoxes[0]->monSpriteId, &menuBoxes[1]->monSpriteId);
SwitchMenuBoxSprites(&menuBoxes[0]->statusSpriteId, &menuBoxes[1]->statusSpriteId);
}
// Finish switching mons or using Softboiled
static void FinishTwoMonAction(u8 taskId)
{
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
gPartyMenu.action = PARTY_ACTION_CHOOSE_MON;
AnimatePartySlot(gPartyMenu.slotId, 0);
gPartyMenu.slotId = gPartyMenu.slotId2;
AnimatePartySlot(gPartyMenu.slotId2, 1);
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
gTasks[taskId].func = Task_HandleChooseMonInput;
}
#undef tSlot1Left
#undef tSlot1Top
#undef tSlot1Width
#undef tSlot1Height
#undef tSlot2Left
#undef tSlot2Top
#undef tSlot2Width
#undef tSlot2Height
#undef tSlot1Offset
#undef tSlot2Offset
#undef tSlot1SlideDir
#undef tSlot2SlideDir
2018-12-10 08:38:23 +01:00
2018-12-24 21:59:05 +01:00
static void CursorCb_Cancel1(u8 taskId)
2018-12-10 08:38:23 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
if (gPartyMenu.menuType == PARTY_MENU_TYPE_DAYCARE)
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON_2);
2018-12-10 08:38:23 +01:00
else
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
gTasks[taskId].func = Task_HandleChooseMonInput;
2018-12-10 08:38:23 +01:00
}
2018-12-13 04:55:39 +01:00
2018-12-24 21:59:05 +01:00
static void CursorCb_Item(u8 taskId)
2018-12-13 04:55:39 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, ACTIONS_ITEM);
DisplaySelectionWindow(SELECTWINDOW_ITEM);
DisplayPartyMenuStdMessage(PARTY_MSG_DO_WHAT_WITH_ITEM);
2018-12-13 04:55:39 +01:00
gTasks[taskId].data[0] = 0xFF;
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_HandleSelectionMenuInput;
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Give(u8 taskId)
2018-12-13 04:55:39 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->exitCallback = CB2_SelectBagItemToGive;
Task_ClosePartyMenu(taskId);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
static void CB2_SelectBagItemToGive(void)
2018-12-13 04:55:39 +01:00
{
if (InBattlePyramid() == FALSE)
2020-05-14 10:37:09 +02:00
GoToBagMenu(ITEMMENULOCATION_PARTY, POCKETS_COUNT, CB2_GiveHoldItem);
2018-12-13 04:55:39 +01:00
else
2019-10-18 01:22:03 +02:00
GoToBattlePyramidBagMenu(2, CB2_GiveHoldItem);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
static void CB2_GiveHoldItem(void)
2018-12-13 04:55:39 +01:00
{
if (gSpecialVar_ItemId == ITEM_NONE)
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_NONE, Task_TryCreateSelectionWindow, gPartyMenu.exitCallback);
2018-12-13 04:55:39 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
sPartyMenuItemId = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM);
// Already holding item
if (sPartyMenuItemId != ITEM_NONE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_NONE, Task_SwitchHoldItemsPrompt, gPartyMenu.exitCallback);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
// Give mail
2018-12-20 02:27:44 +01:00
else if (ItemIsMail(gSpecialVar_ItemId))
2018-12-13 04:55:39 +01:00
{
RemoveBagItem(gSpecialVar_ItemId, 1);
2019-10-18 01:22:03 +02:00
GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId);
CB2_WriteMailToGiveMon();
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
// Give item
2018-12-13 04:55:39 +01:00
else
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_NONE, Task_GiveHoldItem, gPartyMenu.exitCallback);
2018-12-13 04:55:39 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
static void Task_GiveHoldItem(u8 taskId)
2018-12-13 04:55:39 +01:00
{
u16 item;
2018-12-22 17:32:21 +01:00
2018-12-13 04:55:39 +01:00
if (!gPaletteFade.active)
{
item = gSpecialVar_ItemId;
2019-10-18 01:22:03 +02:00
DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], item, FALSE, 0);
GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], item);
2018-12-13 04:55:39 +01:00
RemoveBagItem(item, 1);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_UpdateHeldItemSprite;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_SwitchHoldItemsPrompt(u8 taskId)
2018-12-13 04:55:39 +01:00
{
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
DisplayAlreadyHoldingItemSwitchMessage(&gPlayerParty[gPartyMenu.slotId], sPartyMenuItemId, TRUE);
gTasks[taskId].func = Task_SwitchItemsYesNo;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_SwitchItemsYesNo(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
gTasks[taskId].func = Task_HandleSwitchItemsYesNoInput;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_HandleSwitchItemsYesNoInput(u8 taskId)
2018-12-13 04:55:39 +01:00
{
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
2019-10-18 01:22:03 +02:00
case 0: // Yes, switch items
2018-12-22 17:32:21 +01:00
RemoveBagItem(gSpecialVar_ItemId, 1);
2020-05-18 14:03:01 +02:00
2019-10-18 01:22:03 +02:00
// No room to return held item to bag
if (AddBagItem(sPartyMenuItemId, 1) == FALSE)
2018-12-22 17:32:21 +01:00
{
AddBagItem(gSpecialVar_ItemId, 1);
2019-10-18 01:22:03 +02:00
BufferBagFullCantTakeItemMessage(sPartyMenuItemId);
DisplayPartyMenuMessage(gStringVar4, FALSE);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
// Giving mail
2018-12-22 17:32:21 +01:00
else if (ItemIsMail(gSpecialVar_ItemId))
{
2019-10-18 01:22:03 +02:00
GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId);
gTasks[taskId].func = Task_WriteMailToGiveMonAfterText;
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
// Giving item
2018-12-22 17:32:21 +01:00
else
{
2019-10-18 01:22:03 +02:00
GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId);
DisplaySwitchedHeldItemMessage(gSpecialVar_ItemId, sPartyMenuItemId, TRUE);
gTasks[taskId].func = Task_UpdateHeldItemSprite;
2018-12-22 17:32:21 +01:00
}
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
case 1: // No
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-22 17:32:21 +01:00
break;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_WriteMailToGiveMonAfterText(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->exitCallback = CB2_WriteMailToGiveMon;
Task_ClosePartyMenu(taskId);
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void CB2_WriteMailToGiveMon(void)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
u8 mail = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_MAIL);
2018-12-22 17:32:21 +01:00
2019-02-27 19:45:31 +01:00
DoEasyChatScreen(
2019-10-26 03:55:01 +02:00
EASY_CHAT_TYPE_MAIL,
gSaveBlock1Ptr->mail[mail].words,
CB2_ReturnToPartyMenuFromWritingMail,
EASY_CHAT_PERSON_DISPLAY_NONE);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
static void CB2_ReturnToPartyMenuFromWritingMail(void)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-13 04:55:39 +01:00
u16 item = GetMonData(mon, MON_DATA_HELD_ITEM);
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
// Canceled writing mail
2018-12-13 04:55:39 +01:00
if (gSpecialVar_Result == FALSE)
{
TakeMailFromMon(mon);
2019-10-18 01:22:03 +02:00
SetMonData(mon, MON_DATA_HELD_ITEM, &sPartyMenuItemId);
RemoveBagItem(sPartyMenuItemId, 1);
2018-12-13 04:55:39 +01:00
AddBagItem(item, 1);
2019-10-18 01:22:03 +02:00
InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_CHOOSE_MON, Task_TryCreateSelectionWindow, gPartyMenu.exitCallback);
2018-12-13 04:55:39 +01:00
}
2019-10-26 03:55:01 +02:00
// Wrote mail
2018-12-13 04:55:39 +01:00
else
{
2019-10-26 03:55:01 +02:00
InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_NONE, Task_DisplayGaveMailFromPartyMessage, gPartyMenu.exitCallback);
2018-12-13 04:55:39 +01:00
}
}
2019-10-26 03:55:01 +02:00
// Nearly redundant with Task_DisplayGaveMailFromBagMessgae
static void Task_DisplayGaveMailFromPartyMessage(u8 taskId)
2018-12-13 04:55:39 +01:00
{
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
if (sPartyMenuItemId == ITEM_NONE)
DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId, FALSE, 0);
2018-12-13 04:55:39 +01:00
else
2019-10-18 01:22:03 +02:00
DisplaySwitchedHeldItemMessage(gSpecialVar_ItemId, sPartyMenuItemId, FALSE);
gTasks[taskId].func = Task_UpdateHeldItemSprite;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_UpdateHeldItemSprite(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
UpdatePartyMonHeldItemSprite(mon, &sPartyMenuBoxes[gPartyMenu.slotId]);
if (gPartyMenu.menuType == PARTY_MENU_TYPE_STORE_PYRAMID_HELD_ITEMS)
2018-12-13 04:55:39 +01:00
{
if (GetMonData(mon, MON_DATA_HELD_ITEM) != ITEM_NONE)
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionText(PARTYBOX_DESC_HAVE, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
2018-12-13 04:55:39 +01:00
else
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionText(PARTYBOX_DESC_DONT_HAVE, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
Task_ReturnToChooseMonAfterText(taskId);
2018-12-13 04:55:39 +01:00
}
}
2018-12-24 21:59:05 +01:00
static void CursorCb_TakeItem(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-13 04:55:39 +01:00
u16 item = GetMonData(mon, MON_DATA_HELD_ITEM);
2018-12-22 17:32:21 +01:00
2018-12-13 04:55:39 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
2019-02-01 19:25:10 +01:00
switch (TryTakeMonItem(mon))
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
case 0: // Not holding item
2018-12-22 17:32:21 +01:00
GetMonNickname(mon, gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_PkmnNotHolding);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case 1: // No room to take item
BufferBagFullCantTakeItemMessage(item);
DisplayPartyMenuMessage(gStringVar4, TRUE);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
default: // Took item
DisplayTookHeldItemMessage(mon, item, TRUE);
2018-12-22 17:32:21 +01:00
break;
2018-12-13 04:55:39 +01:00
}
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_UpdateHeldItemSprite;
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Toss(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-13 04:55:39 +01:00
u16 item = GetMonData(mon, MON_DATA_HELD_ITEM);
2018-12-22 17:32:21 +01:00
2018-12-13 04:55:39 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
2018-12-13 04:55:39 +01:00
if (item == ITEM_NONE)
{
GetMonNickname(mon, gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_PkmnNotHolding);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_UpdateHeldItemSprite;
2018-12-13 04:55:39 +01:00
}
else
{
CopyItemName(item, gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_ThrowAwayItem);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_TossHeldItemYesNo;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_TossHeldItemYesNo(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
gTasks[taskId].func = Task_HandleTossHeldItemYesNoInput;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_HandleTossHeldItemYesNoInput(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-22 17:32:21 +01:00
2018-12-13 04:55:39 +01:00
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
2018-12-22 17:32:21 +01:00
case 0:
CopyItemName(GetMonData(mon, MON_DATA_HELD_ITEM), gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_ItemThrownAway);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, FALSE);
gTasks[taskId].func = Task_TossHeldItem;
2018-12-22 17:32:21 +01:00
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2018-12-22 17:32:21 +01:00
case 1:
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-22 17:32:21 +01:00
break;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_TossHeldItem(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-13 04:55:39 +01:00
{
2018-12-24 21:59:05 +01:00
u16 item = ITEM_NONE;
SetMonData(mon, MON_DATA_HELD_ITEM, &item);
2019-10-18 01:22:03 +02:00
UpdatePartyMonHeldItemSprite(mon, &sPartyMenuBoxes[gPartyMenu.slotId]);
DisplayPartyPokemonDescriptionText(PARTYBOX_DESC_DONT_HAVE, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-13 04:55:39 +01:00
}
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Mail(u8 taskId)
2018-12-13 04:55:39 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, ACTIONS_MAIL);
DisplaySelectionWindow(SELECTWINDOW_MAIL);
DisplayPartyMenuStdMessage(PARTY_MSG_DO_WHAT_WITH_MAIL);
2018-12-13 04:55:39 +01:00
gTasks[taskId].data[0] = 0xFF;
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_HandleSelectionMenuInput;
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Read(u8 taskId)
2018-12-13 04:55:39 +01:00
{
PlaySE(SE_SELECT);
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->exitCallback = CB2_ReadHeldMail;
Task_ClosePartyMenu(taskId);
2018-12-13 04:55:39 +01:00
}
2019-10-26 03:55:01 +02:00
static void CB2_ReadHeldMail(void)
2018-12-13 04:55:39 +01:00
{
2019-10-26 03:55:01 +02:00
ReadMail(&gSaveBlock1Ptr->mail[GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_MAIL)], CB2_ReturnToPartyMenuFromReadingMail, 1);
2018-12-13 04:55:39 +01:00
}
2019-10-26 03:55:01 +02:00
static void CB2_ReturnToPartyMenuFromReadingMail(void)
2018-12-13 04:55:39 +01:00
{
gPaletteFade.bufferTransferDisabled = TRUE;
2019-10-18 01:22:03 +02:00
InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_DO_WHAT_WITH_MON, Task_TryCreateSelectionWindow, gPartyMenu.exitCallback);
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static void CursorCb_TakeMail(u8 taskId)
2018-12-13 04:55:39 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
DisplayPartyMenuMessage(gText_SendMailToPC, TRUE);
2019-10-26 03:55:01 +02:00
gTasks[taskId].func = Task_SendMailToPCYesNo;
2018-12-13 04:55:39 +01:00
}
2019-10-26 03:55:01 +02:00
static void Task_SendMailToPCYesNo(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
2019-10-26 03:55:01 +02:00
gTasks[taskId].func = Task_HandleSendMailToPCYesNoInput;
2018-12-13 04:55:39 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void Task_HandleSendMailToPCYesNoInput(u8 taskId)
2018-12-13 04:55:39 +01:00
{
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
2019-10-26 03:55:01 +02:00
case 0: // Yes, send to PC
2019-10-18 01:22:03 +02:00
if (TakeMailFromMon2(&gPlayerParty[gPartyMenu.slotId]) != 0xFF)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_MailSentToPC, FALSE);
gTasks[taskId].func = Task_UpdateHeldItemSprite;
2018-12-22 17:32:21 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_PCMailboxFull, FALSE);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-22 17:32:21 +01:00
}
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2018-12-22 17:32:21 +01:00
case 1:
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_MailMessageWillBeLost, TRUE);
2019-10-26 03:55:01 +02:00
gTasks[taskId].func = Task_LoseMailMessageYesNo;
2018-12-22 17:32:21 +01:00
break;
2018-12-13 04:55:39 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void Task_LoseMailMessageYesNo(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
2019-10-26 03:55:01 +02:00
gTasks[taskId].func = Task_HandleLoseMailMessageYesNoInput;
2018-12-13 04:55:39 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void Task_HandleLoseMailMessageYesNoInput(u8 taskId)
2018-12-13 04:55:39 +01:00
{
u16 item;
2018-12-22 17:32:21 +01:00
2018-12-13 04:55:39 +01:00
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
2019-10-26 03:55:01 +02:00
case 0: // Yes, lose mail message
2019-10-18 01:22:03 +02:00
item = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM);
2018-12-22 17:32:21 +01:00
if (AddBagItem(item, 1) == TRUE)
{
2019-10-18 01:22:03 +02:00
TakeMailFromMon(&gPlayerParty[gPartyMenu.slotId]);
DisplayPartyMenuMessage(gText_MailTakenFromPkmn, FALSE);
gTasks[taskId].func = Task_UpdateHeldItemSprite;
2018-12-22 17:32:21 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
BufferBagFullCantTakeItemMessage(item);
DisplayPartyMenuMessage(gStringVar4, FALSE);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-22 17:32:21 +01:00
}
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2018-12-22 17:32:21 +01:00
case 1:
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-22 17:32:21 +01:00
break;
2018-12-13 04:55:39 +01:00
}
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Cancel2(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-22 17:32:21 +01:00
2018-12-13 04:55:39 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, GetPartyMenuActionsType(mon));
if (gPartyMenu.menuType != PARTY_MENU_TYPE_STORE_PYRAMID_HELD_ITEMS)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
DisplaySelectionWindow(SELECTWINDOW_ACTIONS);
DisplayPartyMenuStdMessage(PARTY_MSG_DO_WHAT_WITH_MON);
2018-12-13 04:55:39 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
DisplaySelectionWindow(SELECTWINDOW_ITEM);
2018-12-13 04:55:39 +01:00
CopyItemName(GetMonData(mon, MON_DATA_HELD_ITEM), gStringVar2);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_ALREADY_HOLDING_ONE);
2018-12-13 04:55:39 +01:00
}
gTasks[taskId].data[0] = 0xFF;
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_HandleSelectionMenuInput;
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static void CursorCb_SendMon(u8 taskId)
2018-12-13 04:55:39 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
if (TrySwitchInPokemon() == TRUE)
2018-12-13 04:55:39 +01:00
{
Task_ClosePartyMenu(taskId);
2018-12-13 04:55:39 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
// gStringVar4 below is the error message buffered by TrySwitchInPokemon
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-13 04:55:39 +01:00
}
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Enter(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
u8 maxBattlers;
2018-12-13 04:55:39 +01:00
u8 i;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
maxBattlers = GetMaxBattleEntries();
for (i = 0; i < maxBattlers; i++)
2018-12-13 04:55:39 +01:00
{
if (gSelectedOrderFromParty[i] == 0)
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
gSelectedOrderFromParty[i] = gPartyMenu.slotId + 1;
DisplayPartyPokemonDescriptionText(i + PARTYBOX_DESC_FIRST, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
if (i == (maxBattlers - 1))
2019-10-26 03:55:01 +02:00
MoveCursorToConfirm();
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
gTasks[taskId].func = Task_HandleChooseMonInput;
2018-12-13 04:55:39 +01:00
return;
}
}
2019-10-18 01:22:03 +02:00
ConvertIntToDecimalStringN(gStringVar1, maxBattlers, STR_CONV_MODE_LEFT_ALIGN, 1);
2018-12-13 04:55:39 +01:00
StringExpandPlaceholders(gStringVar4, gText_NoMoreThanVar1Pkmn);
2020-08-21 00:02:00 +02:00
PlaySE(SE_FAILURE);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-13 04:55:39 +01:00
}
2019-10-26 03:55:01 +02:00
static void MoveCursorToConfirm(void)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
AnimatePartySlot(gPartyMenu.slotId, 0);
gPartyMenu.slotId = PARTY_SIZE;
AnimatePartySlot(gPartyMenu.slotId, 1);
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static void CursorCb_NoEntry(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
u8 maxBattlers;
2018-12-13 04:55:39 +01:00
u8 i, j;
2018-12-22 17:32:21 +01:00
2018-12-13 04:55:39 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
maxBattlers = GetMaxBattleEntries();
for (i = 0; i < maxBattlers; i++)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
if (gSelectedOrderFromParty[i] == (gPartyMenu.slotId + 1))
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
for (j = i; j < (maxBattlers - 1); j++)
2018-12-13 04:55:39 +01:00
gSelectedOrderFromParty[j] = gSelectedOrderFromParty[j + 1];
gSelectedOrderFromParty[j] = 0;
break;
}
}
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionText(PARTYBOX_DESC_ABLE_3, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
for (i = 0; i < (maxBattlers - 1); i++)
2018-12-13 04:55:39 +01:00
{
if (gSelectedOrderFromParty[i] != 0)
2019-10-18 01:22:03 +02:00
DisplayPartyPokemonDescriptionText(i + PARTYBOX_DESC_FIRST, &sPartyMenuBoxes[gSelectedOrderFromParty[i] - 1], 1);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
gTasks[taskId].func = Task_HandleChooseMonInput;
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Store(u8 taskId)
2018-12-13 04:55:39 +01:00
{
PlaySE(SE_SELECT);
Task_ClosePartyMenu(taskId);
2018-12-13 04:55:39 +01:00
}
// Register mon for the Trading Board in Union Room
2018-12-24 21:59:05 +01:00
static void CursorCb_Register(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
u16 species2 = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES2);
u16 species = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES);
u8 isEventLegal = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_EVENT_LEGAL);
2018-12-22 17:32:21 +01:00
switch (CanRegisterMonForTradingBoard(*(struct GFtgtGnameSub *)GetHostRFUtgtGname(), species2, species, isEventLegal))
2018-12-13 04:55:39 +01:00
{
case CANT_REGISTER_MON:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnCantBeTradedNow);
break;
case CANT_REGISTER_EGG:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_EggCantBeTradedNow);
break;
default:
PlaySE(SE_SELECT);
Task_ClosePartyMenu(taskId);
2018-12-22 17:32:21 +01:00
return;
2018-12-13 04:55:39 +01:00
}
2020-08-21 00:02:00 +02:00
PlaySE(SE_FAILURE);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
2018-12-13 04:55:39 +01:00
StringAppend(gStringVar4, gText_PauseUntilPress);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static void CursorCb_Trade1(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
u16 species2 = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES2);
u16 species = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES);
u8 isEventLegal = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_EVENT_LEGAL);
u32 stringId = GetUnionRoomTradeMessageId(*(struct GFtgtGnameSub *)GetHostRFUtgtGname(), gPartnerTgtGnameSub, species2, gUnionRoomOfferedSpecies, gUnionRoomRequestedMonType, species, isEventLegal);
2018-12-22 17:32:21 +01:00
2019-10-04 23:24:03 +02:00
if (stringId != UR_TRADE_MSG_NONE)
2018-12-13 04:55:39 +01:00
{
2019-10-04 23:24:03 +02:00
StringExpandPlaceholders(gStringVar4, sUnionRoomTradeMessages[stringId - 1]);
2020-08-21 00:02:00 +02:00
PlaySE(SE_FAILURE);
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
2018-12-13 04:55:39 +01:00
StringAppend(gStringVar4, gText_PauseUntilPress);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-13 04:55:39 +01:00
}
else
{
PlaySE(SE_SELECT);
Task_ClosePartyMenu(taskId);
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
// Spin Trade (based on the translation of the Japanese trade prompt)
// Not fully implemented, and normally unreachable because PARTY_MENU_TYPE_SPIN_TRADE is never used
2018-12-24 21:59:05 +01:00
static void CursorCb_Trade2(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
switch (CanSpinTradeMon(gPlayerParty, gPartyMenu.slotId))
2018-12-13 04:55:39 +01:00
{
2019-10-10 09:50:51 +02:00
case CANT_TRADE_LAST_MON:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_OnlyPkmnForBattle);
break;
2019-10-10 09:50:51 +02:00
case CANT_TRADE_NATIONAL:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnCantBeTradedNow);
break;
2019-10-18 01:22:03 +02:00
case CANT_TRADE_EGG_YET:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_EggCantBeTradedNow);
break;
2019-10-18 01:22:03 +02:00
default: // CAN_TRADE_MON
2018-12-22 17:32:21 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
StringExpandPlaceholders(gStringVar4, gJPText_AreYouSureYouWantToSpinTradeMon);
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_SpinTradeYesNo;
2018-12-22 17:32:21 +01:00
return;
2018-12-13 04:55:39 +01:00
}
2020-08-21 00:02:00 +02:00
PlaySE(SE_FAILURE);
2018-12-13 04:55:39 +01:00
StringAppend(gStringVar4, gText_PauseUntilPress);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_SpinTradeYesNo(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
gTasks[taskId].func = Task_HandleSpinTradeYesNoInput;
2018-12-13 04:55:39 +01:00
}
}
2019-10-31 19:11:55 +01:00
// See comment on CursorCb_Trade2. Because no callback is set, selecting YES (0) to spin trade just closes the party menu
2019-10-18 01:22:03 +02:00
static void Task_HandleSpinTradeYesNoInput(u8 taskId)
2018-12-13 04:55:39 +01:00
{
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
2018-12-22 17:32:21 +01:00
case 0:
Task_ClosePartyMenu(taskId);
2018-12-22 17:32:21 +01:00
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2018-12-22 17:32:21 +01:00
case 1:
2019-10-18 01:22:03 +02:00
Task_ReturnToChooseMonAfterText(taskId);
2018-12-22 17:32:21 +01:00
break;
2018-12-13 04:55:39 +01:00
}
}
2018-12-24 21:59:05 +01:00
static void CursorCb_FieldMove(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
u8 fieldMove = sPartyMenuInternal->actions[Menu_GetCursorPos()] - MENU_FIELD_MOVES;
2018-12-22 17:32:21 +01:00
const struct MapHeader *mapHeader;
2018-12-13 04:55:39 +01:00
PlaySE(SE_SELECT);
2018-12-24 21:59:05 +01:00
if (sFieldMoveCursorCallbacks[fieldMove].fieldMoveFunc == NULL)
return;
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
2020-05-14 10:37:09 +02:00
if (MenuHelpers_LinkSomething() == TRUE || InUnionRoom() == TRUE)
2018-12-13 04:55:39 +01:00
{
2018-12-24 21:59:05 +01:00
if (fieldMove == FIELD_MOVE_MILK_DRINK || fieldMove == FIELD_MOVE_SOFT_BOILED)
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_CANT_USE_HERE);
2018-12-24 21:59:05 +01:00
else
DisplayPartyMenuStdMessage(sFieldMoveCursorCallbacks[fieldMove].msgId);
2018-12-24 21:59:05 +01:00
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_CancelAfterAorBPress;
2018-12-24 21:59:05 +01:00
}
else
{
// All field moves before WATERFALL are HMs.
if (fieldMove <= FIELD_MOVE_WATERFALL && FlagGet(FLAG_BADGE01_GET + fieldMove) != TRUE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_CantUseUntilNewBadge, TRUE);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
else if (sFieldMoveCursorCallbacks[fieldMove].fieldMoveFunc() == TRUE)
2018-12-13 04:55:39 +01:00
{
2018-12-24 21:59:05 +01:00
switch (fieldMove)
2018-12-13 04:55:39 +01:00
{
2018-12-24 21:59:05 +01:00
case FIELD_MOVE_MILK_DRINK:
case FIELD_MOVE_SOFT_BOILED:
2019-10-18 01:22:03 +02:00
ChooseMonForSoftboiled(taskId);
2018-12-24 21:59:05 +01:00
break;
case FIELD_MOVE_TELEPORT:
mapHeader = Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->lastHealLocation.mapGroup, gSaveBlock1Ptr->lastHealLocation.mapNum);
2019-10-18 01:22:03 +02:00
GetMapNameGeneric(gStringVar1, mapHeader->regionMapSectionId);
2018-12-24 21:59:05 +01:00
StringExpandPlaceholders(gStringVar4, gText_ReturnToHealingSpot);
2019-10-18 01:22:03 +02:00
DisplayFieldMoveExitAreaMessage(taskId);
sPartyMenuInternal->data[0] = fieldMove;
2018-12-24 21:59:05 +01:00
break;
case FIELD_MOVE_DIG:
2018-12-27 23:30:47 +01:00
mapHeader = Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->escapeWarp.mapGroup, gSaveBlock1Ptr->escapeWarp.mapNum);
2019-10-18 01:22:03 +02:00
GetMapNameGeneric(gStringVar1, mapHeader->regionMapSectionId);
2018-12-24 21:59:05 +01:00
StringExpandPlaceholders(gStringVar4, gText_EscapeFromHere);
2019-10-18 01:22:03 +02:00
DisplayFieldMoveExitAreaMessage(taskId);
sPartyMenuInternal->data[0] = fieldMove;
2018-12-24 21:59:05 +01:00
break;
case FIELD_MOVE_FLY:
2020-02-05 08:47:32 +01:00
gPartyMenu.exitCallback = CB2_OpenFlyMap;
Task_ClosePartyMenu(taskId);
2018-12-24 21:59:05 +01:00
break;
default:
2019-10-18 01:22:03 +02:00
gPartyMenu.exitCallback = CB2_ReturnToField;
Task_ClosePartyMenu(taskId);
2018-12-24 21:59:05 +01:00
break;
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
}
2019-10-18 01:22:03 +02:00
// Cant use Field Move
2018-12-24 21:59:05 +01:00
else
{
switch (fieldMove)
2018-12-13 04:55:39 +01:00
{
2018-12-24 21:59:05 +01:00
case FIELD_MOVE_SURF:
2019-10-18 01:22:03 +02:00
DisplayCantUseSurfMessage();
2018-12-24 21:59:05 +01:00
break;
case FIELD_MOVE_FLASH:
2019-10-18 01:22:03 +02:00
DisplayCantUseFlashMessage();
2018-12-24 21:59:05 +01:00
break;
default:
DisplayPartyMenuStdMessage(sFieldMoveCursorCallbacks[fieldMove].msgId);
2018-12-24 21:59:05 +01:00
break;
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_CancelAfterAorBPress;
2018-12-13 04:55:39 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
static void DisplayFieldMoveExitAreaMessage(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
gTasks[taskId].func = Task_FieldMoveExitAreaYesNo;
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_FieldMoveExitAreaYesNo(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
gTasks[taskId].func = Task_HandleFieldMoveExitAreaYesNoInput;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_HandleFieldMoveExitAreaYesNoInput(u8 taskId)
2018-12-13 04:55:39 +01:00
{
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
2018-12-22 17:32:21 +01:00
case 0:
2019-10-18 01:22:03 +02:00
gPartyMenu.exitCallback = CB2_ReturnToField;
Task_ClosePartyMenu(taskId);
2018-12-22 17:32:21 +01:00
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2018-12-22 17:32:21 +01:00
case 1:
gFieldCallback2 = NULL;
gPostMenuFieldCallback = NULL;
2019-10-18 01:22:03 +02:00
Task_ReturnToChooseMonAfterText(taskId);
2018-12-22 17:32:21 +01:00
break;
2018-12-13 04:55:39 +01:00
}
}
bool8 FieldCallback_PrepareFadeInFromMenu(void)
{
2019-12-17 09:24:44 +01:00
FadeInFromBlack();
2019-10-18 01:22:03 +02:00
CreateTask(Task_FieldMoveWaitForFade, 8);
2018-12-13 04:55:39 +01:00
return TRUE;
}
2019-10-18 01:22:03 +02:00
static void Task_FieldMoveWaitForFade(u8 taskId)
2018-12-13 04:55:39 +01:00
{
if (IsWeatherNotFadingIn() == TRUE)
{
2019-10-18 01:22:03 +02:00
gFieldEffectArguments[0] = GetFieldMoveMonSpecies();
2018-12-13 04:55:39 +01:00
gPostMenuFieldCallback();
DestroyTask(taskId);
}
}
2019-10-18 01:22:03 +02:00
static u16 GetFieldMoveMonSpecies(void)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
return GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_CancelAfterAorBPress(u8 taskId)
2018-12-13 04:55:39 +01:00
{
2020-09-05 03:11:55 +02:00
if ((JOY_NEW(A_BUTTON)) || (JOY_NEW(B_BUTTON)))
2018-12-24 21:59:05 +01:00
CursorCb_Cancel1(taskId);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayCantUseFlashMessage(void)
2018-12-13 04:55:39 +01:00
{
if (FlagGet(FLAG_SYS_USE_FLASH) == TRUE)
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_ALREADY_IN_USE);
2018-12-13 04:55:39 +01:00
else
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_CANT_USE_HERE);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
static void FieldCallback_Surf(void)
2018-12-13 04:55:39 +01:00
{
gFieldEffectArguments[0] = GetCursorSelectionMonId();
2018-12-17 08:39:17 +01:00
FieldEffectStart(FLDEFF_USE_SURF);
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static bool8 SetUpFieldMove_Surf(void)
2018-12-13 04:55:39 +01:00
{
if (PartyHasMonWithSurf() == TRUE && IsPlayerFacingSurfableFishableWater() == TRUE)
{
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
2019-10-18 01:22:03 +02:00
gPostMenuFieldCallback = FieldCallback_Surf;
2018-12-13 04:55:39 +01:00
return TRUE;
}
return FALSE;
}
2019-10-18 01:22:03 +02:00
static void DisplayCantUseSurfMessage(void)
2018-12-13 04:55:39 +01:00
{
2018-12-24 21:59:05 +01:00
if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING))
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_ALREADY_SURFING);
2018-12-13 04:55:39 +01:00
else
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_CANT_SURF_HERE);
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static bool8 SetUpFieldMove_Fly(void)
2018-12-13 04:55:39 +01:00
{
if (Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE)
return TRUE;
2018-12-24 21:59:05 +01:00
else
return FALSE;
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
void CB2_ReturnToPartyMenuFromFlyMap(void)
2018-12-13 04:55:39 +01:00
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, TRUE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_ReturnToFieldWithOpenMenu);
2018-12-13 04:55:39 +01:00
}
2019-10-18 01:22:03 +02:00
static void FieldCallback_Waterfall(void)
2018-12-13 04:55:39 +01:00
{
gFieldEffectArguments[0] = GetCursorSelectionMonId();
2018-12-17 08:39:17 +01:00
FieldEffectStart(FLDEFF_USE_WATERFALL);
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static bool8 SetUpFieldMove_Waterfall(void)
2018-12-13 04:55:39 +01:00
{
s16 x, y;
2018-12-22 17:32:21 +01:00
2018-12-13 04:55:39 +01:00
GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
if (MetatileBehavior_IsWaterfall(MapGridGetMetatileBehaviorAt(x, y)) == TRUE && IsPlayerSurfingNorth() == TRUE)
{
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
2019-10-18 01:22:03 +02:00
gPostMenuFieldCallback = FieldCallback_Waterfall;
2018-12-13 04:55:39 +01:00
return TRUE;
}
return FALSE;
}
2019-10-18 01:22:03 +02:00
static void FieldCallback_Dive(void)
2018-12-13 04:55:39 +01:00
{
gFieldEffectArguments[0] = GetCursorSelectionMonId();
2018-12-17 08:39:17 +01:00
FieldEffectStart(FLDEFF_USE_DIVE);
2018-12-13 04:55:39 +01:00
}
2018-12-24 21:59:05 +01:00
static bool8 SetUpFieldMove_Dive(void)
2018-12-13 04:55:39 +01:00
{
gFieldEffectArguments[1] = TrySetDiveWarp();
if (gFieldEffectArguments[1] != 0)
{
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
2019-10-18 01:22:03 +02:00
gPostMenuFieldCallback = FieldCallback_Dive;
2018-12-13 04:55:39 +01:00
return TRUE;
}
return FALSE;
}
2019-10-26 03:55:01 +02:00
static void CreatePartyMonIconSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox, u32 slot)
2018-12-13 04:55:39 +01:00
{
2019-10-26 03:55:01 +02:00
bool32 handleDeoxys = TRUE;
2018-12-13 04:55:39 +01:00
u16 species2;
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
// If in a multi battle, show partners Deoxys icon as Normal forme
2018-12-20 02:27:44 +01:00
if (IsMultiBattle() == TRUE && gMain.inBattle)
2019-10-26 03:55:01 +02:00
handleDeoxys = (sMultiBattlePartnersPartyMask[slot] ^ handleDeoxys) ? TRUE : FALSE;
2018-12-13 04:55:39 +01:00
species2 = GetMonData(mon, MON_DATA_SPECIES2);
2019-10-26 03:55:01 +02:00
CreatePartyMonIconSpriteParameterized(species2, GetMonData(mon, MON_DATA_PERSONALITY), menuBox, 1, handleDeoxys);
2019-10-18 01:22:03 +02:00
UpdatePartyMonHPBar(menuBox->monSpriteId, mon);
2018-12-13 04:55:39 +01:00
}
2019-10-26 03:55:01 +02:00
static void CreatePartyMonIconSpriteParameterized(u16 species, u32 pid, struct PartyMenuBox *menuBox, u8 priority, bool32 handleDeoxys)
2018-12-13 04:55:39 +01:00
{
if (species != SPECIES_NONE)
{
2019-10-31 19:11:55 +01:00
menuBox->monSpriteId = CreateMonIcon(species, SpriteCB_MonIcon, menuBox->spriteCoords[0], menuBox->spriteCoords[1], 4, pid, handleDeoxys);
2019-10-18 01:22:03 +02:00
gSprites[menuBox->monSpriteId].oam.priority = priority;
2018-12-13 04:55:39 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void UpdateHPBar(u8 spriteId, u16 hp, u16 maxhp)
2018-12-13 04:55:39 +01:00
{
switch (GetHPBarLevel(hp, maxhp))
{
2018-12-22 17:32:21 +01:00
case HP_BAR_FULL:
2019-10-04 01:39:37 +02:00
SetPartyHPBarSprite(&gSprites[spriteId], 0);
2018-12-22 17:32:21 +01:00
break;
case HP_BAR_GREEN:
2019-10-04 01:39:37 +02:00
SetPartyHPBarSprite(&gSprites[spriteId], 1);
2018-12-22 17:32:21 +01:00
break;
case HP_BAR_YELLOW:
2019-10-04 01:39:37 +02:00
SetPartyHPBarSprite(&gSprites[spriteId], 2);
2018-12-22 17:32:21 +01:00
break;
case HP_BAR_RED:
2019-10-04 01:39:37 +02:00
SetPartyHPBarSprite(&gSprites[spriteId], 3);
2018-12-22 17:32:21 +01:00
break;
default:
2019-10-04 01:39:37 +02:00
SetPartyHPBarSprite(&gSprites[spriteId], 4);
2018-12-22 17:32:21 +01:00
break;
2018-12-13 04:55:39 +01:00
}
}
2018-12-17 08:39:17 +01:00
2019-10-18 01:22:03 +02:00
static void UpdatePartyMonHPBar(u8 spriteId, struct Pokemon *mon)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
UpdateHPBar(spriteId, GetMonData(mon, MON_DATA_HP), GetMonData(mon, MON_DATA_MAX_HP));
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void AnimateSelectedPartyIcon(u8 spriteId, u8 animNum)
2018-12-22 17:32:21 +01:00
{
2018-12-17 08:39:17 +01:00
gSprites[spriteId].data[0] = 0;
2019-10-18 01:22:03 +02:00
if (animNum == 0)
2018-12-17 08:39:17 +01:00
{
if (gSprites[spriteId].pos1.x == 16)
{
gSprites[spriteId].pos2.x = 0;
gSprites[spriteId].pos2.y = -4;
}
else
{
gSprites[spriteId].pos2.x = -4;
gSprites[spriteId].pos2.y = 0;
}
2019-10-26 03:55:01 +02:00
gSprites[spriteId].callback = SpriteCB_UpdatePartyMonIcon;
2018-12-17 08:39:17 +01:00
}
else
{
gSprites[spriteId].pos2.x = 0;
gSprites[spriteId].pos2.y = 0;
2019-10-26 03:55:01 +02:00
gSprites[spriteId].callback = SpriteCB_BouncePartyMonIcon;
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void SpriteCB_BouncePartyMonIcon(struct Sprite *sprite)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
u8 animCmd = UpdateMonIconFrame(sprite);
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
if (animCmd != 0)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
if (animCmd & 1) // % 2 also matches
2018-12-17 08:39:17 +01:00
sprite->pos2.y = -3;
else
sprite->pos2.y = 1;
}
}
2019-10-26 03:55:01 +02:00
static void SpriteCB_UpdatePartyMonIcon(struct Sprite *sprite)
2018-12-17 08:39:17 +01:00
{
UpdateMonIconFrame(sprite);
}
2019-10-26 03:55:01 +02:00
static void CreatePartyMonHeldItemSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
{
2019-10-18 01:22:03 +02:00
menuBox->itemSpriteId = CreateSprite(&sSpriteTemplate_HeldItem, menuBox->spriteCoords[2], menuBox->spriteCoords[3], 0);
UpdatePartyMonHeldItemSprite(mon, menuBox);
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void CreatePartyMonHeldItemSpriteParameterized(u16 species, u16 item, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
if (species != SPECIES_NONE)
{
2019-10-18 01:22:03 +02:00
menuBox->itemSpriteId = CreateSprite(&sSpriteTemplate_HeldItem, menuBox->spriteCoords[2], menuBox->spriteCoords[3], 0);
gSprites[menuBox->itemSpriteId].oam.priority = 0;
ShowOrHideHeldItemSprite(item, menuBox);
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void UpdatePartyMonHeldItemSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
ShowOrHideHeldItemSprite(GetMonData(mon, MON_DATA_HELD_ITEM), menuBox);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void ShowOrHideHeldItemSprite(u16 item, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
if (item == ITEM_NONE)
{
2019-10-18 01:22:03 +02:00
gSprites[menuBox->itemSpriteId].invisible = TRUE;
2018-12-17 08:39:17 +01:00
}
else
{
2018-12-20 02:27:44 +01:00
if (ItemIsMail(item))
2019-10-18 01:22:03 +02:00
StartSpriteAnim(&gSprites[menuBox->itemSpriteId], 1);
2018-12-17 08:39:17 +01:00
else
2019-10-18 01:22:03 +02:00
StartSpriteAnim(&gSprites[menuBox->itemSpriteId], 0);
gSprites[menuBox->itemSpriteId].invisible = FALSE;
2018-12-17 08:39:17 +01:00
}
}
2018-12-18 11:38:08 +01:00
void LoadHeldItemIcons(void)
2018-12-17 08:39:17 +01:00
{
2019-05-13 00:41:25 +02:00
LoadSpriteSheet(&sSpriteSheet_HeldItem);
LoadSpritePalette(&sSpritePalette_HeldItem);
2018-12-17 08:39:17 +01:00
}
2019-10-11 00:46:42 +02:00
void DrawHeldItemIconsForTrade(u8 *partyCounts, u8 *partySpriteIds, u8 whichParty)
2018-12-17 08:39:17 +01:00
{
u16 i;
u16 item;
2018-12-22 17:32:21 +01:00
2019-10-11 00:46:42 +02:00
switch (whichParty)
2018-12-17 08:39:17 +01:00
{
2019-10-07 04:58:25 +02:00
case TRADE_PLAYER:
for (i = 0; i < partyCounts[TRADE_PLAYER]; i++)
2018-12-22 17:32:21 +01:00
{
item = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
if (item != ITEM_NONE)
2019-10-07 04:58:25 +02:00
CreateHeldItemSpriteForTrade(partySpriteIds[i], ItemIsMail(item));
2018-12-22 17:32:21 +01:00
}
break;
2019-10-07 04:58:25 +02:00
case TRADE_PARTNER:
for (i = 0; i < partyCounts[TRADE_PARTNER]; i++)
2018-12-22 17:32:21 +01:00
{
item = GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM);
if (item != ITEM_NONE)
2019-10-07 04:58:25 +02:00
CreateHeldItemSpriteForTrade(partySpriteIds[i + PARTY_SIZE], ItemIsMail(item));
2018-12-22 17:32:21 +01:00
}
break;
2018-12-17 08:39:17 +01:00
}
}
2019-10-07 04:58:25 +02:00
static void CreateHeldItemSpriteForTrade(u8 spriteId, bool8 isMail)
2018-12-17 08:39:17 +01:00
{
u8 subpriority = gSprites[spriteId].subpriority;
2019-05-13 00:41:25 +02:00
u8 newSpriteId = CreateSprite(&sSpriteTemplate_HeldItem, 250, 170, subpriority - 1);
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
gSprites[newSpriteId].pos2.x = 4;
gSprites[newSpriteId].pos2.y = 10;
2019-05-13 00:41:25 +02:00
gSprites[newSpriteId].callback = SpriteCB_HeldItem;
2018-12-17 08:39:17 +01:00
gSprites[newSpriteId].data[7] = spriteId;
StartSpriteAnim(&gSprites[newSpriteId], isMail);
gSprites[newSpriteId].callback(&gSprites[newSpriteId]);
}
2019-05-13 00:41:25 +02:00
static void SpriteCB_HeldItem(struct Sprite *sprite)
2018-12-17 08:39:17 +01:00
{
u8 otherSpriteId = sprite->data[7];
2018-12-22 17:32:21 +01:00
2018-12-20 02:27:44 +01:00
if (gSprites[otherSpriteId].invisible)
2018-12-17 08:39:17 +01:00
{
sprite->invisible = TRUE;
}
else
{
sprite->invisible = FALSE;
sprite->pos1.x = gSprites[otherSpriteId].pos1.x + gSprites[otherSpriteId].pos2.x;
sprite->pos1.y = gSprites[otherSpriteId].pos1.y + gSprites[otherSpriteId].pos2.y;
}
}
2019-10-26 03:55:01 +02:00
static void CreatePartyMonPokeballSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
2019-10-18 01:22:03 +02:00
menuBox->pokeballSpriteId = CreateSprite(&sSpriteTemplate_MenuPokeball, menuBox->spriteCoords[6], menuBox->spriteCoords[7], 8);
2018-12-17 08:39:17 +01:00
}
2019-10-26 03:55:01 +02:00
static void CreatePartyMonPokeballSpriteParameterized(u16 species, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
if (species != SPECIES_NONE)
{
2019-10-18 01:22:03 +02:00
menuBox->pokeballSpriteId = CreateSprite(&sSpriteTemplate_MenuPokeball, menuBox->spriteCoords[6], menuBox->spriteCoords[7], 8);
gSprites[menuBox->pokeballSpriteId].oam.priority = 0;
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
// For Cancel when Confirm isnt present
static u8 CreatePokeballButtonSprite(u8 x, u8 y)
2018-12-17 08:39:17 +01:00
{
2019-05-13 00:41:25 +02:00
u8 spriteId = CreateSprite(&sSpriteTemplate_MenuPokeball, x, y, 8);
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
gSprites[spriteId].oam.priority = 2;
return spriteId;
}
2019-10-26 03:55:01 +02:00
// For Confirm and Cancel when both are present
static u8 CreateSmallPokeballButtonSprite(u8 x, u8 y)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
return CreateSprite(&sSpriteTemplate_MenuPokeballSmall, x, y, 8);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void PartyMenuStartSpriteAnim(u8 spriteId, u8 animNum)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
StartSpriteAnim(&gSprites[spriteId], animNum);
2018-12-17 08:39:17 +01:00
}
2019-10-26 03:55:01 +02:00
// Unused. Might explain the large blank section in gPartyMenuPokeballSmall_Gfx
// At the very least this is how the unused anim cmds for sSpriteAnimTable_MenuPokeballSmall were meant to be accessed
static void SpriteCB_BounceConfirmCancelButton(u8 spriteId, u8 spriteId2, u8 animNum)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
if (animNum == 0)
2018-12-17 08:39:17 +01:00
{
StartSpriteAnim(&gSprites[spriteId], 2);
StartSpriteAnim(&gSprites[spriteId2], 4);
gSprites[spriteId].pos2.y = 0;
gSprites[spriteId2].pos2.y = 0;
}
else
{
StartSpriteAnim(&gSprites[spriteId], 3);
StartSpriteAnim(&gSprites[spriteId2], 5);
gSprites[spriteId].pos2.y = -4;
gSprites[spriteId2].pos2.y = 4;
}
}
2018-12-24 00:02:29 +01:00
static void LoadPartyMenuPokeballGfx(void)
2018-12-17 08:39:17 +01:00
{
2019-05-13 00:41:25 +02:00
LoadCompressedSpriteSheet(&sSpriteSheet_MenuPokeball);
LoadCompressedSpriteSheet(&sSpriteSheet_MenuPokeballSmall);
LoadCompressedSpritePalette(&sSpritePalette_MenuPokeball);
2018-12-17 08:39:17 +01:00
}
2019-10-26 03:55:01 +02:00
static void CreatePartyMonStatusSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
{
2019-10-18 01:22:03 +02:00
menuBox->statusSpriteId = CreateSprite(&sSpriteTemplate_StatusIcons, menuBox->spriteCoords[4], menuBox->spriteCoords[5], 0);
SetPartyMonAilmentGfx(mon, menuBox);
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void CreatePartyMonStatusSpriteParameterized(u16 species, u8 status, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
if (species != SPECIES_NONE)
{
2019-10-18 01:22:03 +02:00
menuBox->statusSpriteId = CreateSprite(&sSpriteTemplate_StatusIcons, menuBox->spriteCoords[4], menuBox->spriteCoords[5], 0);
UpdatePartyMonAilmentGfx(status, menuBox);
gSprites[menuBox->statusSpriteId].oam.priority = 0;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void SetPartyMonAilmentGfx(struct Pokemon *mon, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
UpdatePartyMonAilmentGfx(GetMonAilment(mon), menuBox);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void UpdatePartyMonAilmentGfx(u8 status, struct PartyMenuBox *menuBox)
2018-12-17 08:39:17 +01:00
{
switch (status)
{
2018-12-22 17:32:21 +01:00
case AILMENT_NONE:
case AILMENT_PKRS:
2019-10-18 01:22:03 +02:00
gSprites[menuBox->statusSpriteId].invisible = TRUE;
2018-12-22 17:32:21 +01:00
break;
default:
2019-10-18 01:22:03 +02:00
StartSpriteAnim(&gSprites[menuBox->statusSpriteId], status - 1);
gSprites[menuBox->statusSpriteId].invisible = FALSE;
2018-12-22 17:32:21 +01:00
break;
2018-12-17 08:39:17 +01:00
}
}
2018-12-24 00:02:29 +01:00
static void LoadPartyMenuAilmentGfx(void)
2018-12-17 08:39:17 +01:00
{
2019-05-13 00:41:25 +02:00
LoadCompressedSpriteSheet(&sSpriteSheet_StatusIcons);
LoadCompressedSpritePalette(&sSpritePalette_StatusIcons);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
void CB2_ShowPartyMenuForItemUse(void)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
MainCallback callback = CB2_ReturnToBagMenu;
u8 partyLayout;
u8 menuType;
2018-12-17 08:39:17 +01:00
u8 i;
2019-10-18 01:22:03 +02:00
u8 msgId;
2019-02-01 19:25:10 +01:00
TaskFunc task;
2018-12-22 17:32:21 +01:00
2018-12-20 02:27:44 +01:00
if (gMain.inBattle)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
menuType = PARTY_MENU_TYPE_IN_BATTLE;
partyLayout = GetPartyLayoutFromBattleType();
2018-12-17 08:39:17 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
menuType = PARTY_MENU_TYPE_FIELD;
partyLayout = PARTY_LAYOUT_SINGLE;
2018-12-17 08:39:17 +01:00
}
2019-02-01 19:25:10 +01:00
2019-04-14 17:20:26 +02:00
if (GetItemEffectType(gSpecialVar_ItemId) == ITEM_EFFECT_SACRED_ASH)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
gPartyMenu.slotId = 0;
2018-12-17 08:39:17 +01:00
for (i = 0; i < PARTY_SIZE; i++)
{
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != SPECIES_NONE && GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0)
{
2019-10-18 01:22:03 +02:00
gPartyMenu.slotId = i;
2018-12-17 08:39:17 +01:00
break;
}
}
2019-10-26 03:55:01 +02:00
task = Task_SetSacredAshCB;
2019-10-18 01:22:03 +02:00
msgId = PARTY_MSG_NONE;
2018-12-17 08:39:17 +01:00
}
else
{
2019-02-01 19:25:10 +01:00
if (GetPocketByItemId(gSpecialVar_ItemId) == POCKET_TM_HM)
2019-10-18 01:22:03 +02:00
msgId = PARTY_MSG_TEACH_WHICH_MON;
2019-02-01 19:25:10 +01:00
else
2019-10-18 01:22:03 +02:00
msgId = PARTY_MSG_USE_ON_WHICH_MON;
2019-02-01 19:25:10 +01:00
2019-10-18 01:22:03 +02:00
task = Task_HandleChooseMonInput;
2018-12-17 08:39:17 +01:00
}
2019-02-01 19:25:10 +01:00
2019-10-18 01:22:03 +02:00
InitPartyMenu(menuType, partyLayout, PARTY_ACTION_USE_ITEM, TRUE, msgId, task, callback);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void CB2_ReturnToBagMenu(void)
2018-12-17 08:39:17 +01:00
{
if (InBattlePyramid() == FALSE)
2020-05-14 10:37:09 +02:00
GoToBagMenu(ITEMMENULOCATION_LAST, POCKETS_COUNT, NULL);
2018-12-17 08:39:17 +01:00
else
2019-10-18 01:22:03 +02:00
GoToBattlePyramidBagMenu(4, gPyramidBagCursorData.callback);
2018-12-17 08:39:17 +01:00
}
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
static void Task_SetSacredAshCB(u8 taskId)
2018-12-22 17:32:21 +01:00
{
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
sPartyMenuInternal->exitCallback = CB2_SetUpExitToBattleScreen;
2019-10-26 03:55:01 +02:00
gItemUseCB(taskId, Task_ClosePartyMenuAfterText); // ItemUseCB_SacredAsh in this case
2018-12-22 17:32:21 +01:00
}
}
2018-12-24 00:02:29 +01:00
static bool8 IsHPRecoveryItem(u16 item)
2018-12-22 17:32:21 +01:00
{
const u8 *effect;
if (item == ITEM_ENIGMA_BERRY)
effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
effect = gItemEffectTable[item - ITEM_POTION];
2019-02-01 19:25:10 +01:00
2019-04-14 17:20:26 +02:00
if (effect[4] & ITEM4_HEAL_HP)
2018-12-22 17:32:21 +01:00
return TRUE;
2019-02-01 19:25:10 +01:00
else
return FALSE;
2018-12-22 17:32:21 +01:00
}
2018-12-24 00:02:29 +01:00
static void GetMedicineItemEffectMessage(u16 item)
2018-12-22 17:32:21 +01:00
{
switch (GetItemEffectType(item))
{
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_CURE_POISON:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnCuredOfPoison);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_CURE_SLEEP:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnWokeUp2);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_CURE_BURN:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnBurnHealed);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_CURE_FREEZE:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnThawedOut);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_CURE_PARALYSIS:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnCuredOfParalysis);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_CURE_CONFUSION:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnSnappedOutOfConfusion);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_CURE_INFATUATION:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnGotOverInfatuation);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_CURE_ALL_STATUS:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnBecameHealthy);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_HP_EV:
2018-12-22 17:32:21 +01:00
StringCopy(gStringVar2, gText_HP3);
StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_ATK_EV:
2018-12-22 17:32:21 +01:00
StringCopy(gStringVar2, gText_Attack3);
StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_DEF_EV:
2018-12-22 17:32:21 +01:00
StringCopy(gStringVar2, gText_Defense3);
StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_SPEED_EV:
2018-12-22 17:32:21 +01:00
StringCopy(gStringVar2, gText_Speed2);
StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_SPATK_EV:
2018-12-22 17:32:21 +01:00
StringCopy(gStringVar2, gText_SpAtk3);
StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_SPDEF_EV:
2018-12-22 17:32:21 +01:00
StringCopy(gStringVar2, gText_SpDef3);
StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_PP_UP:
case ITEM_EFFECT_PP_MAX:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_MovesPPIncreased);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_HEAL_PP:
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_PPWasRestored);
break;
default:
StringExpandPlaceholders(gStringVar4, gText_WontHaveEffect);
break;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static bool8 NotUsingHPEVItemOnShedinja(struct Pokemon *mon, u16 item)
2018-12-17 08:39:17 +01:00
{
2019-04-14 17:20:26 +02:00
if (GetItemEffectType(item) == ITEM_EFFECT_HP_EV && GetMonData(mon, MON_DATA_SPECIES) == SPECIES_SHEDINJA)
2018-12-17 08:39:17 +01:00
return FALSE;
return TRUE;
}
2019-04-14 17:20:26 +02:00
static bool8 IsItemFlute(u16 item)
2018-12-17 08:39:17 +01:00
{
if (item == ITEM_BLUE_FLUTE || item == ITEM_RED_FLUTE || item == ITEM_YELLOW_FLUTE)
return TRUE;
return FALSE;
}
2019-10-18 01:22:03 +02:00
static bool8 ExecuteTableBasedItemEffect_(u8 partyMonIndex, u16 item, u8 monMoveIndex)
2018-12-22 17:32:21 +01:00
{
2018-12-20 02:27:44 +01:00
if (gMain.inBattle)
2019-10-18 01:22:03 +02:00
return ExecuteTableBasedItemEffect(&gPlayerParty[partyMonIndex], item, GetPartyIdFromBattleSlot(partyMonIndex), monMoveIndex);
2018-12-17 08:39:17 +01:00
else
return ExecuteTableBasedItemEffect(&gPlayerParty[partyMonIndex], item, partyMonIndex, monMoveIndex);
}
void ItemUseCB_Medicine(u8 taskId, TaskFunc task)
{
u16 hp = 0;
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-17 08:39:17 +01:00
u16 item = gSpecialVar_ItemId;
2020-10-21 21:07:34 +02:00
bool8 canHeal, cannotUse;
2018-12-22 17:32:21 +01:00
2020-10-21 21:07:34 +02:00
if (NotUsingHPEVItemOnShedinja(mon, item) == FALSE)
{
cannotUse = TRUE;
}
else
2018-12-17 08:39:17 +01:00
{
canHeal = IsHPRecoveryItem(item);
if (canHeal == TRUE)
{
hp = GetMonData(mon, MON_DATA_HP);
if (hp == GetMonData(mon, MON_DATA_MAX_HP))
canHeal = FALSE;
}
2020-10-21 21:07:34 +02:00
cannotUse = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, item, 0);
2018-12-17 08:39:17 +01:00
}
2020-10-21 21:07:34 +02:00
if (cannotUse != FALSE)
2018-12-17 08:39:17 +01:00
{
2020-10-21 21:07:34 +02:00
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = task;
2018-12-17 08:39:17 +01:00
}
else
{
2020-10-21 21:07:34 +02:00
gPartyMenuUseExitCallback = TRUE;
if (!IsItemFlute(item))
{
PlaySE(SE_USE_ITEM);
if (gPartyMenu.action != PARTY_ACTION_REUSABLE_ITEM)
RemoveBagItem(item, 1);
}
else
{
PlaySE(SE_GLASS_FLUTE);
}
SetPartyMonAilmentGfx(mon, &sPartyMenuBoxes[gPartyMenu.slotId]);
if (gSprites[sPartyMenuBoxes[gPartyMenu.slotId].statusSpriteId].invisible)
DisplayPartyPokemonLevelCheck(mon, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
if (canHeal == TRUE)
{
if (hp == 0)
AnimatePartySlot(gPartyMenu.slotId, 1);
PartyMenuModifyHP(taskId, gPartyMenu.slotId, 1, GetMonData(mon, MON_DATA_HP) - hp, Task_DisplayHPRestoredMessage);
ResetHPTaskData(taskId, 0, hp);
return;
}
else
{
GetMonNickname(mon, gStringVar1);
GetMedicineItemEffectMessage(item);
DisplayPartyMenuMessage(gStringVar4, TRUE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = task;
}
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_DisplayHPRestoredMessage(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
2018-12-17 08:39:17 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnHPRestoredByVar2);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, FALSE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
HandleBattleLowHpMusicChange();
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_ClosePartyMenuAfterText(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
if (gPartyMenuUseExitCallback == FALSE)
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->exitCallback = NULL;
Task_ClosePartyMenu(taskId);
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
void ItemUseCB_ReduceEV(u8 taskId, TaskFunc task)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-17 08:39:17 +01:00
u16 item = gSpecialVar_ItemId;
u8 effectType = GetItemEffectType(item);
u16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP);
2019-10-18 01:22:03 +02:00
u16 ev = ItemEffectToMonEv(mon, effectType);
bool8 cannotUseEffect = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, item, 0);
2018-12-17 08:39:17 +01:00
u16 newFriendship = GetMonData(mon, MON_DATA_FRIENDSHIP);
2019-10-18 01:22:03 +02:00
u16 newEv = ItemEffectToMonEv(mon, effectType);
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (cannotUseEffect || (friendship == newFriendship && ev == newEv))
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = FALSE;
2018-12-17 08:39:17 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
gTasks[taskId].func = task;
}
else
{
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = TRUE;
2020-08-21 00:02:00 +02:00
PlaySE(SE_USE_ITEM);
2018-12-17 08:39:17 +01:00
RemoveBagItem(item, 1);
GetMonNickname(mon, gStringVar1);
2019-04-14 17:20:26 +02:00
ItemEffectToStatString(effectType, gStringVar2);
2018-12-17 08:39:17 +01:00
if (friendship != newFriendship)
{
2019-10-18 01:22:03 +02:00
if (ev != newEv)
2018-12-17 08:39:17 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnFriendlyBaseVar2Fell);
else
StringExpandPlaceholders(gStringVar4, gText_PkmnFriendlyBaseVar2CantFall);
}
else
{
StringExpandPlaceholders(gStringVar4, gText_PkmnAdoresBaseVar2Fell);
}
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
gTasks[taskId].func = task;
}
}
2019-04-14 17:20:26 +02:00
static u16 ItemEffectToMonEv(struct Pokemon *mon, u8 effectType)
2018-12-17 08:39:17 +01:00
{
2018-12-20 02:08:01 +01:00
switch (effectType)
2018-12-17 08:39:17 +01:00
{
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_HP_EV:
2018-12-22 17:32:21 +01:00
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_SHEDINJA)
return GetMonData(mon, MON_DATA_HP_EV);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_ATK_EV:
2018-12-22 17:32:21 +01:00
return GetMonData(mon, MON_DATA_ATK_EV);
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_DEF_EV:
2018-12-22 17:32:21 +01:00
return GetMonData(mon, MON_DATA_DEF_EV);
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_SPEED_EV:
2018-12-22 17:32:21 +01:00
return GetMonData(mon, MON_DATA_SPEED_EV);
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_SPATK_EV:
2018-12-22 17:32:21 +01:00
return GetMonData(mon, MON_DATA_SPATK_EV);
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_SPDEF_EV:
2018-12-22 17:32:21 +01:00
return GetMonData(mon, MON_DATA_SPDEF_EV);
2018-12-17 08:39:17 +01:00
}
return 0;
}
2019-04-14 17:20:26 +02:00
static void ItemEffectToStatString(u8 effectType, u8 *dest)
2018-12-17 08:39:17 +01:00
{
2018-12-20 02:08:01 +01:00
switch (effectType)
2018-12-17 08:39:17 +01:00
{
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_HP_EV:
2018-12-22 17:32:21 +01:00
StringCopy(dest, gText_HP3);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_ATK_EV:
2018-12-22 17:32:21 +01:00
StringCopy(dest, gText_Attack3);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_DEF_EV:
2018-12-22 17:32:21 +01:00
StringCopy(dest, gText_Defense3);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_SPEED_EV:
2018-12-22 17:32:21 +01:00
StringCopy(dest, gText_Speed2);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_SPATK_EV:
2018-12-22 17:32:21 +01:00
StringCopy(dest, gText_SpAtk3);
break;
2019-04-14 17:20:26 +02:00
case ITEM_EFFECT_SPDEF_EV:
2018-12-22 17:32:21 +01:00
StringCopy(dest, gText_SpDef3);
break;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void ShowMoveSelectWindow(u8 slot)
2018-12-17 08:39:17 +01:00
{
u8 i;
u8 moveCount = 0;
u8 fontId = 1;
2019-10-18 01:22:03 +02:00
u8 windowId = DisplaySelectionWindow(SELECTWINDOW_MOVES);
2018-12-17 08:39:17 +01:00
u16 move;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
for (i = 0; i < MAX_MON_MOVES; i++)
{
move = GetMonData(&gPlayerParty[slot], MON_DATA_MOVE1 + i);
2019-10-18 01:22:03 +02:00
AddTextPrinterParameterized(windowId, fontId, gMoveNames[move], 8, (i * 16) + 1, TEXT_SPEED_FF, NULL);
2018-12-17 08:39:17 +01:00
if (move != MOVE_NONE)
moveCount++;
}
InitMenuInUpperLeftCornerPlaySoundWhenAPressed(windowId, moveCount, 0);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_HandleWhichMoveInput(u8 taskId)
2018-12-17 08:39:17 +01:00
{
s8 input = Menu_ProcessInput();
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
if (input != MENU_NOTHING_CHOSEN)
{
if (input == MENU_B_PRESSED)
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
ReturnToUseOnWhichMon(taskId);
2018-12-17 08:39:17 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
SetSelectedMoveForPPItem(taskId);
2018-12-17 08:39:17 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
void ItemUseCB_PPRecovery(u8 taskId, TaskFunc task)
2018-12-17 08:39:17 +01:00
{
const u8 *effect;
u16 item = gSpecialVar_ItemId;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
if (item == ITEM_ENIGMA_BERRY)
effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
effect = gItemEffectTable[item - ITEM_POTION];
2019-02-01 19:25:10 +01:00
2019-04-14 17:20:26 +02:00
if (!(effect[4] & ITEM4_HEAL_PP_ONE))
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
gPartyMenu.data1 = 0;
2019-10-18 01:22:03 +02:00
TryUsePPItem(taskId);
2018-12-17 08:39:17 +01:00
}
else
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_RESTORE_WHICH_MOVE);
ShowMoveSelectWindow(gPartyMenu.slotId);
gTasks[taskId].func = Task_HandleWhichMoveInput;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void SetSelectedMoveForPPItem(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
2019-10-26 03:55:01 +02:00
gPartyMenu.data1 = Menu_GetCursorPos();
2019-10-18 01:22:03 +02:00
TryUsePPItem(taskId);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void ReturnToUseOnWhichMon(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_HandleChooseMonInput;
sPartyMenuInternal->exitCallback = NULL;
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
DisplayPartyMenuStdMessage(PARTY_MSG_USE_ON_WHICH_MON);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void TryUsePPItem(u8 taskId)
2018-12-17 08:39:17 +01:00
{
u16 move = MOVE_NONE;
2019-10-26 03:55:01 +02:00
s16 *moveSlot = &gPartyMenu.data1;
2018-12-17 08:39:17 +01:00
u16 item = gSpecialVar_ItemId;
2019-10-18 01:22:03 +02:00
struct PartyMenu *ptr = &gPartyMenu;
2018-12-17 08:39:17 +01:00
struct Pokemon *mon;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (ExecuteTableBasedItemEffect_(ptr->slotId, item, *moveSlot))
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = FALSE;
2018-12-17 08:39:17 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
2018-12-17 08:39:17 +01:00
}
else
{
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = TRUE;
2019-05-13 00:41:25 +02:00
mon = &gPlayerParty[ptr->slotId];
2020-08-21 00:02:00 +02:00
PlaySE(SE_USE_ITEM);
2018-12-17 08:39:17 +01:00
RemoveBagItem(item, 1);
2019-10-18 01:22:03 +02:00
move = GetMonData(mon, MON_DATA_MOVE1 + *moveSlot);
2018-12-17 08:39:17 +01:00
StringCopy(gStringVar1, gMoveNames[move]);
GetMedicineItemEffectMessage(item);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
void ItemUseCB_PPUp(u8 taskId, TaskFunc task)
2018-12-17 08:39:17 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_BOOST_PP_WHICH_MOVE);
ShowMoveSelectWindow(gPartyMenu.slotId);
gTasks[taskId].func = Task_HandleWhichMoveInput;
2018-12-17 08:39:17 +01:00
}
u16 ItemIdToBattleMoveId(u16 item)
{
2021-01-14 09:41:28 +01:00
u16 tmNumber = item - ITEM_TM01;
2019-10-18 01:22:03 +02:00
return sTMHMMoves[tmNumber];
2018-12-17 08:39:17 +01:00
}
2018-12-24 21:59:05 +01:00
bool8 IsMoveHm(u16 move)
2018-12-17 08:39:17 +01:00
{
u8 i;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
for (i = 0; i < NUM_HIDDEN_MACHINES; i++)
{
2019-10-18 01:22:03 +02:00
if (sTMHMMoves[i + NUM_TECHNICAL_MACHINES] == move)
2018-12-17 08:39:17 +01:00
return TRUE;
}
return FALSE;
}
2018-12-24 21:59:05 +01:00
bool8 MonKnowsMove(struct Pokemon *mon, u16 move)
2018-12-17 08:39:17 +01:00
{
u8 i;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (GetMonData(mon, MON_DATA_MOVE1 + i) == move)
return TRUE;
}
return FALSE;
}
2019-10-18 01:22:03 +02:00
static void DisplayLearnMoveMessage(const u8 *str)
2018-12-17 08:39:17 +01:00
{
StringExpandPlaceholders(gStringVar4, str);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayLearnMoveMessageAndClose(u8 taskId, const u8 *str)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
DisplayLearnMoveMessage(str);
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
2018-12-17 08:39:17 +01:00
}
// move[1] doesn't use constants cause I don't know if it's actually a move ID storage
2019-10-18 01:22:03 +02:00
void ItemUseCB_TMHM(u8 taskId, TaskFunc task)
2018-12-17 08:39:17 +01:00
{
struct Pokemon *mon;
s16 *move;
u16 item;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
mon = &gPlayerParty[gPartyMenu.slotId];
2019-10-26 03:55:01 +02:00
move = &gPartyMenu.data1;
2018-12-17 08:39:17 +01:00
item = gSpecialVar_ItemId;
GetMonNickname(mon, gStringVar1);
move[0] = ItemIdToBattleMoveId(item);
StringCopy(gStringVar2, gMoveNames[move[0]]);
move[1] = 0;
2018-12-24 21:59:05 +01:00
switch (CanMonLearnTMTutor(mon, item, 0))
2018-12-17 08:39:17 +01:00
{
2018-12-22 17:32:21 +01:00
case CANNOT_LEARN_MOVE:
2019-10-18 01:22:03 +02:00
DisplayLearnMoveMessageAndClose(taskId, gText_PkmnCantLearnMove);
2018-12-22 17:32:21 +01:00
return;
case ALREADY_KNOWS_MOVE:
2019-10-18 01:22:03 +02:00
DisplayLearnMoveMessageAndClose(taskId, gText_PkmnAlreadyKnows);
2018-12-22 17:32:21 +01:00
return;
2018-12-17 08:39:17 +01:00
}
2018-12-24 21:59:05 +01:00
2019-10-18 01:22:03 +02:00
if (GiveMoveToMon(mon, move[0]) != MON_HAS_MAX_MOVES)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_LearnedMove;
2018-12-17 08:39:17 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
DisplayLearnMoveMessage(gText_PkmnNeedsToReplaceMove);
gTasks[taskId].func = Task_ReplaceMoveYesNo;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_LearnedMove(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2019-10-26 03:55:01 +02:00
s16 *move = &gPartyMenu.data1;
2018-12-17 08:39:17 +01:00
u16 item = gSpecialVar_ItemId;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
if (move[1] == 0)
{
2020-02-02 19:28:54 +01:00
AdjustFriendship(mon, FRIENDSHIP_EVENT_LEARN_TMHM);
2018-12-17 08:39:17 +01:00
if (item < ITEM_HM01_CUT)
RemoveBagItem(item, 1);
}
GetMonNickname(mon, gStringVar1);
StringCopy(gStringVar2, gMoveNames[move[0]]);
StringExpandPlaceholders(gStringVar4, gText_PkmnLearnedMove3);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_DoLearnedMoveFanfareAfterText;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_DoLearnedMoveFanfareAfterText(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-17 08:39:17 +01:00
{
2020-08-21 00:02:00 +02:00
PlayFanfare(MUS_LEVEL_UP);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_LearnNextMoveOrClosePartyMenu;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_LearnNextMoveOrClosePartyMenu(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2020-09-05 03:11:55 +02:00
if (IsFanfareTaskInactive() && ((JOY_NEW(A_BUTTON)) || (JOY_NEW(B_BUTTON))))
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.learnMoveState == 1)
Task_TryLearningNextMove(taskId);
2018-12-17 08:39:17 +01:00
else
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.learnMoveState == 2) // never occurs
2018-12-17 08:39:17 +01:00
gSpecialVar_Result = TRUE;
Task_ClosePartyMenu(taskId);
2018-12-17 08:39:17 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
static void Task_ReplaceMoveYesNo(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
gTasks[taskId].func = Task_HandleReplaceMoveYesNoInput;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_HandleReplaceMoveYesNoInput(u8 taskId)
2018-12-17 08:39:17 +01:00
{
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
2018-12-22 17:32:21 +01:00
case 0:
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_WhichMoveToForget, TRUE);
gTasks[taskId].func = Task_ShowSummaryScreenToForgetMove;
2018-12-22 17:32:21 +01:00
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2018-12-22 17:32:21 +01:00
case 1:
2019-10-18 01:22:03 +02:00
StopLearningMovePrompt(taskId);
2018-12-22 17:32:21 +01:00
break;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_ShowSummaryScreenToForgetMove(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->exitCallback = CB2_ShowSummaryScreenToForgetMove;
Task_ClosePartyMenu(taskId);
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void CB2_ShowSummaryScreenToForgetMove(void)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
ShowSelectMovePokemonSummaryScreen(gPlayerParty, gPartyMenu.slotId, gPlayerPartyCount - 1, CB2_ReturnToPartyMenuWhileLearningMove, gPartyMenu.data1);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void CB2_ReturnToPartyMenuWhileLearningMove(void)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, TRUE, PARTY_MSG_NONE, Task_ReturnToPartyMenuWhileLearningMove, gPartyMenu.exitCallback);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_ReturnToPartyMenuWhileLearningMove(u8 taskId)
2018-12-17 08:39:17 +01:00
{
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
if (GetMoveSlotToReplace() != MAX_MON_MOVES)
DisplayPartyMenuForgotMoveMessage(taskId);
2018-12-17 08:39:17 +01:00
else
2019-10-18 01:22:03 +02:00
StopLearningMovePrompt(taskId);
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayPartyMenuForgotMoveMessage(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
u16 move = GetMonData(mon, MON_DATA_MOVE1 + GetMoveSlotToReplace());
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
GetMonNickname(mon, gStringVar1);
StringCopy(gStringVar2, gMoveNames[move]);
2019-10-18 01:22:03 +02:00
DisplayLearnMoveMessage(gText_12PoofForgotMove);
gTasks[taskId].func = Task_PartyMenuReplaceMove;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_PartyMenuReplaceMove(u8 taskId)
2018-12-17 08:39:17 +01:00
{
struct Pokemon *mon;
u16 move;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
mon = &gPlayerParty[gPartyMenu.slotId];
RemoveMonPPBonus(mon, GetMoveSlotToReplace());
2019-10-26 03:55:01 +02:00
move = gPartyMenu.data1;
2019-10-18 01:22:03 +02:00
SetMonMoveSlot(mon, move, GetMoveSlotToReplace());
Task_LearnedMove(taskId);
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void StopLearningMovePrompt(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
StringCopy(gStringVar2, gMoveNames[gPartyMenu.data1]);
2018-12-17 08:39:17 +01:00
StringExpandPlaceholders(gStringVar4, gText_StopLearningMove2);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_StopLearningMoveYesNo;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_StopLearningMoveYesNo(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
gTasks[taskId].func = Task_HandleStopLearningMoveYesNoInput;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_HandleStopLearningMoveYesNoInput(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
2018-12-22 17:32:21 +01:00
case 0:
GetMonNickname(mon, gStringVar1);
2019-10-26 03:55:01 +02:00
StringCopy(gStringVar2, gMoveNames[gPartyMenu.data1]);
2018-12-22 17:32:21 +01:00
StringExpandPlaceholders(gStringVar4, gText_MoveNotLearned);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
if (gPartyMenu.learnMoveState == 1)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_TryLearningNextMoveAfterText;
2018-12-22 17:32:21 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.learnMoveState == 2) // never occurs
2018-12-22 17:32:21 +01:00
gSpecialVar_Result = FALSE;
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
2018-12-22 17:32:21 +01:00
}
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2018-12-22 17:32:21 +01:00
case 1:
GetMonNickname(mon, gStringVar1);
2019-10-26 03:55:01 +02:00
StringCopy(gStringVar2, gMoveNames[gPartyMenu.data1]);
2019-10-18 01:22:03 +02:00
DisplayLearnMoveMessage(gText_PkmnNeedsToReplaceMove);
gTasks[taskId].func = Task_ReplaceMoveYesNo;
2018-12-22 17:32:21 +01:00
break;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_TryLearningNextMoveAfterText(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
Task_TryLearningNextMove(taskId);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
void ItemUseCB_RareCandy(u8 taskId, TaskFunc task)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
struct PartyMenuInternal *ptr = sPartyMenuInternal;
2018-12-18 11:38:08 +01:00
s16 *arrayPtr = ptr->data;
2018-12-17 08:39:17 +01:00
u16 *itemPtr = &gSpecialVar_ItemId;
bool8 cannotUseEffect;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
if (GetMonData(mon, MON_DATA_LEVEL) != MAX_LEVEL)
{
2019-10-18 01:22:03 +02:00
BufferMonStatsToTaskData(mon, arrayPtr);
cannotUseEffect = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, *itemPtr, 0);
2019-10-26 03:55:01 +02:00
BufferMonStatsToTaskData(mon, &ptr->data[NUM_STATS]);
2018-12-17 08:39:17 +01:00
}
else
{
cannotUseEffect = TRUE;
}
PlaySE(SE_SELECT);
2018-12-20 02:08:01 +01:00
if (cannotUseEffect)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = FALSE;
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
gTasks[taskId].func = task;
}
else
{
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = TRUE;
2018-12-17 08:39:17 +01:00
PlayFanfareByFanfareNum(0);
2019-10-18 01:22:03 +02:00
UpdateMonDisplayInfoAfterRareCandy(gPartyMenu.slotId, mon);
2018-12-17 08:39:17 +01:00
RemoveBagItem(gSpecialVar_ItemId, 1);
GetMonNickname(mon, gStringVar1);
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar2, GetMonData(mon, MON_DATA_LEVEL), STR_CONV_MODE_LEFT_ALIGN, 3);
2018-12-17 08:39:17 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnElevatedToLvVar2);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_DisplayLevelUpStatsPg1;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void UpdateMonDisplayInfoAfterRareCandy(u8 slot, struct Pokemon *mon)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
SetPartyMonAilmentGfx(mon, &sPartyMenuBoxes[slot]);
if (gSprites[sPartyMenuBoxes[slot].statusSpriteId].invisible)
DisplayPartyPokemonLevelCheck(mon, &sPartyMenuBoxes[slot], 1);
DisplayPartyPokemonHPCheck(mon, &sPartyMenuBoxes[slot], 1);
DisplayPartyPokemonMaxHPCheck(mon, &sPartyMenuBoxes[slot], 1);
DisplayPartyPokemonHPBarCheck(mon, &sPartyMenuBoxes[slot]);
UpdatePartyMonHPBar(sPartyMenuBoxes[slot].monSpriteId, mon);
AnimatePartySlot(slot, 1);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_DisplayLevelUpStatsPg1(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2020-09-05 03:11:55 +02:00
if (WaitFanfare(FALSE) && IsPartyMenuTextPrinterActive() != TRUE && ((JOY_NEW(A_BUTTON)) || (JOY_NEW(B_BUTTON))))
2018-12-17 08:39:17 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
DisplayLevelUpStatsPg1(taskId);
gTasks[taskId].func = Task_DisplayLevelUpStatsPg2;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_DisplayLevelUpStatsPg2(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2020-09-05 03:11:55 +02:00
if ((JOY_NEW(A_BUTTON)) || (JOY_NEW(B_BUTTON)))
2018-12-17 08:39:17 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
DisplayLevelUpStatsPg2(taskId);
gTasks[taskId].func = Task_TryLearnNewMoves;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayLevelUpStatsPg1(u8 taskId)
2018-12-17 08:39:17 +01:00
{
s16 *arrayPtr = sPartyMenuInternal->data;
2018-12-22 17:32:21 +01:00
arrayPtr[12] = CreateLevelUpStatsWindow();
2019-12-10 19:48:20 +01:00
DrawLevelUpWindowPg1(arrayPtr[12], arrayPtr, &arrayPtr[6], TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY, TEXT_COLOR_LIGHT_GREY);
2018-12-17 08:39:17 +01:00
CopyWindowToVram(arrayPtr[12], 2);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayLevelUpStatsPg2(u8 taskId)
2018-12-17 08:39:17 +01:00
{
s16 *arrayPtr = sPartyMenuInternal->data;
2018-12-22 17:32:21 +01:00
2019-12-10 19:48:20 +01:00
DrawLevelUpWindowPg2(arrayPtr[12], &arrayPtr[6], TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY, TEXT_COLOR_LIGHT_GREY);
2018-12-17 08:39:17 +01:00
CopyWindowToVram(arrayPtr[12], 2);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_TryLearnNewMoves(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
u16 learnMove;
2018-12-22 17:32:21 +01:00
2020-09-05 03:11:55 +02:00
if (WaitFanfare(0) && ((JOY_NEW(A_BUTTON)) || (JOY_NEW(B_BUTTON))))
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
RemoveLevelUpStatsWindow();
learnMove = MonTryLearningNewMove(&gPlayerParty[gPartyMenu.slotId], TRUE);
gPartyMenu.learnMoveState = 1;
switch (learnMove)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
case 0: // No moves to learn
PartyMenuTryEvolution(taskId);
2018-12-17 08:39:17 +01:00
break;
2019-10-18 01:22:03 +02:00
case MON_HAS_MAX_MOVES:
DisplayMonNeedsToReplaceMove(taskId);
2018-12-17 08:39:17 +01:00
break;
2019-10-18 01:22:03 +02:00
case MON_ALREADY_KNOWS_MOVE:
gTasks[taskId].func = Task_TryLearningNextMove;
2018-12-22 17:32:21 +01:00
break;
2018-12-17 08:39:17 +01:00
default:
2019-10-18 01:22:03 +02:00
DisplayMonLearnedMove(taskId, learnMove);
2018-12-17 08:39:17 +01:00
break;
2018-12-22 17:32:21 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
static void Task_TryLearningNextMove(u8 taskId)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
u16 result = MonTryLearningNewMove(&gPlayerParty[gPartyMenu.slotId], FALSE);
2018-12-22 17:32:21 +01:00
switch (result)
{
2019-10-18 01:22:03 +02:00
case 0: // No moves to learn
PartyMenuTryEvolution(taskId);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case MON_HAS_MAX_MOVES:
DisplayMonNeedsToReplaceMove(taskId);
2018-12-22 17:32:21 +01:00
break;
2019-10-18 01:22:03 +02:00
case MON_ALREADY_KNOWS_MOVE:
2018-12-22 17:32:21 +01:00
return;
default:
2019-10-18 01:22:03 +02:00
DisplayMonLearnedMove(taskId, result);
2018-12-22 17:32:21 +01:00
break;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void PartyMenuTryEvolution(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2021-02-12 20:54:11 +01:00
u16 targetSpecies = GetEvolutionTargetSpecies(mon, EVO_MODE_NORMAL, ITEM_NONE);
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
if (targetSpecies != SPECIES_NONE)
{
2018-12-18 11:38:08 +01:00
FreePartyPointers();
2019-10-18 01:22:03 +02:00
gCB2_AfterEvolution = gPartyMenu.exitCallback;
2021-02-12 20:54:11 +01:00
BeginEvolutionScene(mon, targetSpecies, TRUE, gPartyMenu.slotId);
2018-12-17 08:39:17 +01:00
DestroyTask(taskId);
}
else
{
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void DisplayMonNeedsToReplaceMove(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
2018-12-17 08:39:17 +01:00
StringCopy(gStringVar2, gMoveNames[gMoveToLearn]);
StringExpandPlaceholders(gStringVar4, gText_PkmnNeedsToReplaceMove);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-26 03:55:01 +02:00
gPartyMenu.data1 = gMoveToLearn;
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ReplaceMoveYesNo;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void DisplayMonLearnedMove(u8 taskId, u16 move)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
2018-12-17 08:39:17 +01:00
StringCopy(gStringVar2, gMoveNames[move]);
StringExpandPlaceholders(gStringVar4, gText_PkmnLearnedMove3);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-26 03:55:01 +02:00
gPartyMenu.data1 = move;
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_DoLearnedMoveFanfareAfterText;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void BufferMonStatsToTaskData(struct Pokemon *mon, s16 *data)
2018-12-17 08:39:17 +01:00
{
data[0] = GetMonData(mon, MON_DATA_MAX_HP);
data[1] = GetMonData(mon, MON_DATA_ATK);
data[2] = GetMonData(mon, MON_DATA_DEF);
data[4] = GetMonData(mon, MON_DATA_SPATK);
data[5] = GetMonData(mon, MON_DATA_SPDEF);
data[3] = GetMonData(mon, MON_DATA_SPEED);
}
2019-10-26 03:55:01 +02:00
#define tUsedOnSlot data[0]
#define tHadEffect data[1]
#define tLastSlotUsed data[2]
2019-10-18 01:22:03 +02:00
void ItemUseCB_SacredAsh(u8 taskId, TaskFunc task)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->tUsedOnSlot = FALSE;
sPartyMenuInternal->tHadEffect = FALSE;
sPartyMenuInternal->tLastSlotUsed = gPartyMenu.slotId;
UseSacredAsh(taskId);
2018-12-17 08:39:17 +01:00
}
2019-10-26 03:55:01 +02:00
static void UseSacredAsh(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-17 08:39:17 +01:00
u16 hp;
2018-12-22 17:32:21 +01:00
if (GetMonData(mon, MON_DATA_SPECIES) == SPECIES_NONE)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
gTasks[taskId].func = Task_SacredAshLoop;
2018-12-22 17:32:21 +01:00
return;
2018-12-17 08:39:17 +01:00
}
2018-12-22 17:32:21 +01:00
hp = GetMonData(mon, MON_DATA_HP);
2019-10-18 01:22:03 +02:00
if (ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, 0))
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
gTasks[taskId].func = Task_SacredAshLoop;
2018-12-17 08:39:17 +01:00
return;
}
2018-12-22 17:32:21 +01:00
2020-08-21 00:02:00 +02:00
PlaySE(SE_USE_ITEM);
2019-10-18 01:22:03 +02:00
SetPartyMonAilmentGfx(mon, &sPartyMenuBoxes[gPartyMenu.slotId]);
if (gSprites[sPartyMenuBoxes[gPartyMenu.slotId].statusSpriteId].invisible)
DisplayPartyPokemonLevelCheck(mon, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
2019-10-26 03:55:01 +02:00
AnimatePartySlot(sPartyMenuInternal->tLastSlotUsed, 0);
2019-10-18 01:22:03 +02:00
AnimatePartySlot(gPartyMenu.slotId, 1);
PartyMenuModifyHP(taskId, gPartyMenu.slotId, 1, GetMonData(mon, MON_DATA_HP) - hp, Task_SacredAshDisplayHPRestored);
ResetHPTaskData(taskId, 0, hp);
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->tUsedOnSlot = TRUE;
sPartyMenuInternal->tHadEffect = TRUE;
2018-12-17 08:39:17 +01:00
}
2019-10-26 03:55:01 +02:00
static void Task_SacredAshLoop(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
if (sPartyMenuInternal->tUsedOnSlot == TRUE)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
sPartyMenuInternal->tUsedOnSlot = FALSE;
sPartyMenuInternal->tLastSlotUsed = gPartyMenu.slotId;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
if (++(gPartyMenu.slotId) == PARTY_SIZE)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
if (sPartyMenuInternal->tHadEffect == FALSE)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = FALSE;
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
}
else
{
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = TRUE;
2018-12-17 08:39:17 +01:00
RemoveBagItem(gSpecialVar_ItemId, 1);
}
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
gPartyMenu.slotId = 0;
2018-12-17 08:39:17 +01:00
}
else
{
2019-10-26 03:55:01 +02:00
UseSacredAsh(taskId);
2018-12-17 08:39:17 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
static void Task_SacredAshDisplayHPRestored(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
2018-12-17 08:39:17 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnHPRestoredByVar2);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gStringVar4, FALSE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-26 03:55:01 +02:00
gTasks[taskId].func = Task_SacredAshLoop;
2018-12-17 08:39:17 +01:00
}
2019-10-26 03:55:01 +02:00
#undef tUsedOnSlot
#undef tHadEffect
#undef tLastSlotUsed
2019-10-18 01:22:03 +02:00
void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task)
2018-12-17 08:39:17 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
gCB2_AfterEvolution = gPartyMenu.exitCallback;
if (ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, 0))
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = FALSE;
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2018-12-17 08:39:17 +01:00
gTasks[taskId].func = task;
}
else
{
RemoveBagItem(gSpecialVar_ItemId, 1);
2018-12-18 11:38:08 +01:00
FreePartyPointers();
2018-12-17 08:39:17 +01:00
}
}
u8 GetItemEffectType(u16 item)
{
const u8 *itemEffect;
2019-02-01 19:25:10 +01:00
u32 statusCure;
2018-12-17 08:39:17 +01:00
2019-04-14 17:20:26 +02:00
if (!ITEM_HAS_EFFECT(item))
return ITEM_EFFECT_NONE;
2019-02-01 19:25:10 +01:00
// Read the item's effect properties.
if (item == ITEM_ENIGMA_BERRY)
itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
2018-12-17 08:39:17 +01:00
else
2019-02-01 19:25:10 +01:00
itemEffect = gItemEffectTable[item - ITEM_POTION];
2018-12-17 08:39:17 +01:00
2019-12-22 01:01:38 +01:00
if ((itemEffect[0] & (ITEM0_DIRE_HIT | ITEM0_X_ATTACK)) || itemEffect[1] || itemEffect[2] || (itemEffect[3] & ITEM3_GUARD_SPEC))
2019-04-14 17:20:26 +02:00
return ITEM_EFFECT_X_ITEM;
else if (itemEffect[0] & ITEM0_SACRED_ASH)
return ITEM_EFFECT_SACRED_ASH;
else if (itemEffect[3] & ITEM3_LEVEL_UP)
return ITEM_EFFECT_RAISE_LEVEL;
2018-12-17 08:39:17 +01:00
2019-04-14 17:20:26 +02:00
statusCure = itemEffect[3] & ITEM3_STATUS_ALL;
2019-02-01 19:25:10 +01:00
if (statusCure || (itemEffect[0] >> 7))
{
2019-04-14 17:20:26 +02:00
if (statusCure == ITEM3_SLEEP)
return ITEM_EFFECT_CURE_SLEEP;
else if (statusCure == ITEM3_POISON)
return ITEM_EFFECT_CURE_POISON;
else if (statusCure == ITEM3_BURN)
return ITEM_EFFECT_CURE_BURN;
else if (statusCure == ITEM3_FREEZE)
return ITEM_EFFECT_CURE_FREEZE;
else if (statusCure == ITEM3_PARALYSIS)
return ITEM_EFFECT_CURE_PARALYSIS;
else if (statusCure == ITEM3_CONFUSION)
return ITEM_EFFECT_CURE_CONFUSION;
2019-02-01 19:25:10 +01:00
else if (itemEffect[0] >> 7 && !statusCure)
2019-04-14 17:20:26 +02:00
return ITEM_EFFECT_CURE_INFATUATION;
2019-02-01 19:25:10 +01:00
else
2019-04-14 17:20:26 +02:00
return ITEM_EFFECT_CURE_ALL_STATUS;
}
if (itemEffect[4] & (ITEM4_REVIVE | ITEM4_HEAL_HP))
return ITEM_EFFECT_HEAL_HP;
else if (itemEffect[4] & ITEM4_EV_ATK)
return ITEM_EFFECT_ATK_EV;
else if (itemEffect[4] & ITEM4_EV_HP)
return ITEM_EFFECT_HP_EV;
else if (itemEffect[5] & ITEM5_EV_SPATK)
return ITEM_EFFECT_SPATK_EV;
else if (itemEffect[5] & ITEM5_EV_SPDEF)
return ITEM_EFFECT_SPDEF_EV;
else if (itemEffect[5] & ITEM5_EV_SPEED)
return ITEM_EFFECT_SPEED_EV;
else if (itemEffect[5] & ITEM5_EV_DEF)
return ITEM_EFFECT_DEF_EV;
else if (itemEffect[4] & ITEM4_EVO_STONE)
return ITEM_EFFECT_EVO_STONE;
else if (itemEffect[4] & ITEM4_PP_UP)
return ITEM_EFFECT_PP_UP;
else if (itemEffect[5] & ITEM5_PP_MAX)
return ITEM_EFFECT_PP_MAX;
2021-02-12 20:54:11 +01:00
else if (itemEffect[4] & (ITEM4_HEAL_PP | ITEM4_HEAL_PP_ONE))
2019-04-14 17:20:26 +02:00
return ITEM_EFFECT_HEAL_PP;
2019-02-01 19:25:10 +01:00
else
2019-04-14 17:20:26 +02:00
return ITEM_EFFECT_NONE;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void TryTutorSelectedMon(u8 taskId)
2018-12-17 08:39:17 +01:00
{
struct Pokemon *mon;
s16 *move;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
mon = &gPlayerParty[gPartyMenu.slotId];
2019-10-26 03:55:01 +02:00
move = &gPartyMenu.data1;
2018-12-17 08:39:17 +01:00
GetMonNickname(mon, gStringVar1);
2019-10-26 03:55:01 +02:00
gPartyMenu.data1 = GetTutorMove(gSpecialVar_0x8005);
StringCopy(gStringVar2, gMoveNames[gPartyMenu.data1]);
2018-12-17 08:39:17 +01:00
move[1] = 2;
2018-12-24 21:59:05 +01:00
switch (CanMonLearnTMTutor(mon, 0, gSpecialVar_0x8005))
2018-12-17 08:39:17 +01:00
{
2018-12-22 17:32:21 +01:00
case CANNOT_LEARN_MOVE:
2019-10-18 01:22:03 +02:00
DisplayLearnMoveMessageAndClose(taskId, gText_PkmnCantLearnMove);
2018-12-22 17:32:21 +01:00
return;
case ALREADY_KNOWS_MOVE:
2019-10-18 01:22:03 +02:00
DisplayLearnMoveMessageAndClose(taskId, gText_PkmnAlreadyKnows);
2018-12-22 17:32:21 +01:00
return;
default:
2019-10-26 03:55:01 +02:00
if (GiveMoveToMon(mon, gPartyMenu.data1) != MON_HAS_MAX_MOVES)
2018-12-22 17:32:21 +01:00
{
2019-10-18 01:22:03 +02:00
Task_LearnedMove(taskId);
2018-12-17 08:39:17 +01:00
return;
2018-12-22 17:32:21 +01:00
}
break;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
DisplayLearnMoveMessage(gText_PkmnNeedsToReplaceMove);
gTasks[taskId].func = Task_ReplaceMoveYesNo;
2018-12-17 08:39:17 +01:00
}
}
void CB2_PartyMenuFromStartMenu(void)
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_ReturnToFieldWithOpenMenu);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
// Giving an item by selecting Give from the bag menu
// As opposted to by selecting Give in the party menu, which is handled by CursorCb_Give
void CB2_ChooseMonToGiveItem(void)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
MainCallback callback = (InBattlePyramid() == FALSE) ? CB2_ReturnToBagMenu : CB2_ReturnToPyramidBagMenu;
InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_GIVE_ITEM, FALSE, PARTY_MSG_GIVE_TO_WHICH_MON, Task_HandleChooseMonInput, callback);
gPartyMenu.bagItem = gSpecialVar_ItemId;
2018-12-17 08:39:17 +01:00
}
2019-10-26 03:55:01 +02:00
static void TryGiveItemOrMailToSelectedMon(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
sPartyMenuItemId = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM);
if (sPartyMenuItemId == ITEM_NONE)
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
GiveItemOrMailToSelectedMon(taskId);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
else if (ItemIsMail(sPartyMenuItemId))
2018-12-17 08:39:17 +01:00
{
2019-10-26 03:55:01 +02:00
DisplayItemMustBeRemovedFirstMessage(taskId);
2018-12-17 08:39:17 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
DisplayAlreadyHoldingItemSwitchMessage(&gPlayerParty[gPartyMenu.slotId], sPartyMenuItemId, TRUE);
2019-10-26 03:55:01 +02:00
gTasks[taskId].func = Task_SwitchItemsFromBagYesNo;
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void GiveItemOrMailToSelectedMon(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (ItemIsMail(gPartyMenu.bagItem))
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
RemoveItemToGiveFromBag(gPartyMenu.bagItem);
sPartyMenuInternal->exitCallback = CB2_WriteMailToGiveMonFromBag;
Task_ClosePartyMenu(taskId);
2018-12-17 08:39:17 +01:00
}
else
{
2019-10-26 03:55:01 +02:00
GiveItemToSelectedMon(taskId);
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void GiveItemToSelectedMon(u8 taskId)
2018-12-17 08:39:17 +01:00
{
u16 item;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
item = gPartyMenu.bagItem;
DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], item, FALSE, 1);
GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], item);
RemoveItemToGiveFromBag(item);
gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_UpdateHeldItemSpriteAndClosePartyMenu(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
s8 slot = gPartyMenu.slotId;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
UpdatePartyMonHeldItemSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
Task_ClosePartyMenu(taskId);
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void CB2_WriteMailToGiveMonFromBag(void)
2018-12-17 08:39:17 +01:00
{
u8 mail;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], gPartyMenu.bagItem);
mail = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_MAIL);
2019-02-27 19:45:31 +01:00
DoEasyChatScreen(
2019-10-26 03:55:01 +02:00
EASY_CHAT_TYPE_MAIL,
gSaveBlock1Ptr->mail[mail].words,
CB2_ReturnToPartyOrBagMenuFromWritingMail,
EASY_CHAT_PERSON_DISPLAY_NONE);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void CB2_ReturnToPartyOrBagMenuFromWritingMail(void)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-17 08:39:17 +01:00
u16 item = GetMonData(mon, MON_DATA_HELD_ITEM);
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
// Canceled writing mail
2018-12-17 08:39:17 +01:00
if (gSpecialVar_Result == FALSE)
{
TakeMailFromMon(mon);
2019-10-18 01:22:03 +02:00
SetMonData(mon, MON_DATA_HELD_ITEM, &sPartyMenuItemId);
RemoveBagItem(sPartyMenuItemId, 1);
2019-10-26 03:55:01 +02:00
ReturnGiveItemToBagOrPC(item);
2019-10-18 01:22:03 +02:00
SetMainCallback2(gPartyMenu.exitCallback);
2018-12-17 08:39:17 +01:00
}
2019-10-26 03:55:01 +02:00
// Wrote mail
2018-12-17 08:39:17 +01:00
else
{
2019-10-26 03:55:01 +02:00
InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_NONE, Task_DisplayGaveMailFromBagMessage, gPartyMenu.exitCallback);
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void Task_DisplayGaveMailFromBagMessage(u8 taskId)
2018-12-17 08:39:17 +01:00
{
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
if (sPartyMenuItemId != ITEM_NONE)
DisplaySwitchedHeldItemMessage(gPartyMenu.bagItem, sPartyMenuItemId, FALSE);
2018-12-17 08:39:17 +01:00
else
2019-10-18 01:22:03 +02:00
DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], gPartyMenu.bagItem, FALSE, 1);
gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void Task_SwitchItemsFromBagYesNo(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (IsPartyMenuTextPrinterActive() != TRUE)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
PartyMenuDisplayYesNoMenu();
2019-10-26 03:55:01 +02:00
gTasks[taskId].func = Task_HandleSwitchItemsFromBagYesNoInput;
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void Task_HandleSwitchItemsFromBagYesNoInput(u8 taskId)
2018-12-17 08:39:17 +01:00
{
u16 item;
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
switch (Menu_ProcessInputNoWrapClearOnChoose())
{
2019-10-26 03:55:01 +02:00
case 0: // Yes, switch items
2019-10-18 01:22:03 +02:00
item = gPartyMenu.bagItem;
RemoveItemToGiveFromBag(item);
if (AddBagItem(sPartyMenuItemId, 1) == FALSE)
2018-12-22 17:32:21 +01:00
{
2019-10-26 03:55:01 +02:00
ReturnGiveItemToBagOrPC(item);
2019-10-18 01:22:03 +02:00
BufferBagFullCantTakeItemMessage(sPartyMenuItemId);
DisplayPartyMenuMessage(gStringVar4, FALSE);
gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
2018-12-22 17:32:21 +01:00
}
else if (ItemIsMail(item))
{
2019-10-18 01:22:03 +02:00
sPartyMenuInternal->exitCallback = CB2_WriteMailToGiveMonFromBag;
Task_ClosePartyMenu(taskId);
2018-12-22 17:32:21 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], item);
DisplaySwitchedHeldItemMessage(item, sPartyMenuItemId, TRUE);
gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
2018-12-22 17:32:21 +01:00
}
break;
case MENU_B_PRESSED:
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
// fallthrough
2019-10-26 03:55:01 +02:00
case 1: // No, dont switch items
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
2018-12-22 17:32:21 +01:00
break;
2018-12-17 08:39:17 +01:00
}
}
2019-10-26 03:55:01 +02:00
static void DisplayItemMustBeRemovedFirstMessage(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_RemoveMailBeforeItem, TRUE);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void RemoveItemToGiveFromBag(u16 item)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.action == PARTY_ACTION_GIVE_PC_ITEM) // Unused, never occurs
2018-12-17 08:39:17 +01:00
RemovePCItem(item, 1);
else
RemoveBagItem(item, 1);
}
2019-10-26 03:55:01 +02:00
// Returns FALSE if there was no space to return the item
// but there always should be, and the return is ignored in all uses
static bool8 ReturnGiveItemToBagOrPC(u16 item)
2018-12-17 08:39:17 +01:00
{
2020-05-18 14:03:01 +02:00
if (gPartyMenu.action == PARTY_ACTION_GIVE_ITEM)
2018-12-17 08:39:17 +01:00
return AddBagItem(item, 1);
else
return AddPCItem(item, 1);
}
2019-10-18 01:22:03 +02:00
void ChooseMonToGiveMailFromMailbox(void)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_GIVE_MAILBOX_MAIL, FALSE, PARTY_MSG_GIVE_TO_WHICH_MON, Task_HandleChooseMonInput, Mailbox_ReturnToMailListAfterDeposit);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static void TryGiveMailToSelectedMon(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
2018-12-17 08:39:17 +01:00
struct MailStruct *mail;
2018-12-22 17:32:21 +01:00
2019-10-26 03:55:01 +02:00
gPartyMenuUseExitCallback = FALSE;
2018-12-17 08:39:17 +01:00
mail = &gSaveBlock1Ptr->mail[playerPCItemPageInfo.itemsAbove + 6 + playerPCItemPageInfo.cursorPos];
if (GetMonData(mon, MON_DATA_HELD_ITEM) != ITEM_NONE)
{
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_PkmnHoldingItemCantHoldMail, TRUE);
2018-12-17 08:39:17 +01:00
}
else
{
GiveMailToMon2(mon, mail);
ClearMailStruct(mail);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuMessage(gText_MailTransferredFromMailbox, TRUE);
2018-12-17 08:39:17 +01:00
}
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(2);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
2018-12-17 08:39:17 +01:00
}
void InitChooseHalfPartyForBattle(u8 unused)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
ClearSelectedPartyOrder();
InitPartyMenu(PARTY_MENU_TYPE_CHOOSE_HALF, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, gMain.savedCallback);
gPartyMenu.task = Task_ValidateChosenHalfParty;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
void ClearSelectedPartyOrder(void)
2018-12-17 08:39:17 +01:00
{
2018-12-24 00:02:29 +01:00
memset(gSelectedOrderFromParty, 0, sizeof(gSelectedOrderFromParty));
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static u8 GetPartySlotEntryStatus(s8 slot)
2018-12-17 08:39:17 +01:00
{
2018-12-18 11:38:08 +01:00
if (GetBattleEntryEligibility(&gPlayerParty[slot]) == FALSE)
2018-12-17 08:39:17 +01:00
return 2;
2019-10-18 01:22:03 +02:00
if (HasPartySlotAlreadyBeenSelected(slot + 1) == TRUE)
2018-12-17 08:39:17 +01:00
return 1;
return 0;
}
2018-12-24 00:02:29 +01:00
static bool8 GetBattleEntryEligibility(struct Pokemon *mon)
2018-12-17 08:39:17 +01:00
{
u16 i = 0;
u16 species;
2018-12-22 17:32:21 +01:00
if (GetMonData(mon, MON_DATA_IS_EGG)
2019-10-18 01:22:03 +02:00
|| GetMonData(mon, MON_DATA_LEVEL) > GetBattleEntryLevelCap()
2018-12-22 17:32:21 +01:00
|| (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(BATTLE_FRONTIER_BATTLE_PYRAMID_LOBBY)
&& gSaveBlock1Ptr->location.mapNum == MAP_NUM(BATTLE_FRONTIER_BATTLE_PYRAMID_LOBBY)
&& GetMonData(mon, MON_DATA_HELD_ITEM) != ITEM_NONE))
{
2018-12-17 08:39:17 +01:00
return FALSE;
2018-12-22 17:32:21 +01:00
}
2019-10-18 01:22:03 +02:00
switch (VarGet(VAR_FRONTIER_FACILITY))
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
case FACILITY_MULTI_OR_EREADER:
2018-12-22 17:32:21 +01:00
if (GetMonData(mon, MON_DATA_HP) != 0)
2018-12-17 08:39:17 +01:00
return TRUE;
2018-12-22 17:32:21 +01:00
return FALSE;
2019-10-18 01:22:03 +02:00
case FACILITY_UNION_ROOM:
2018-12-22 17:32:21 +01:00
return TRUE;
2019-10-18 01:22:03 +02:00
default: // Battle Frontier
2018-12-22 17:32:21 +01:00
species = GetMonData(mon, MON_DATA_SPECIES);
for (; gFrontierBannedSpecies[i] != 0xFFFF; i++)
{
if (gFrontierBannedSpecies[i] == species)
return FALSE;
}
return TRUE;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static u8 CheckBattleEntriesAndGetMessage(void)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
u8 maxBattlers;
2018-12-17 08:39:17 +01:00
u8 i, j;
2018-12-22 17:32:21 +01:00
u8 facility;
struct Pokemon *party = gPlayerParty;
2019-10-18 01:22:03 +02:00
u8 minBattlers = GetMinBattleEntries();
2018-12-22 17:32:21 +01:00
u8 *order = gSelectedOrderFromParty;
2019-10-18 01:22:03 +02:00
if (order[minBattlers - 1] == 0)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
if (minBattlers == 1)
return PARTY_MSG_NO_MON_FOR_BATTLE;
ConvertIntToDecimalStringN(gStringVar1, minBattlers, STR_CONV_MODE_LEFT_ALIGN, 1);
return PARTY_MSG_X_MONS_ARE_NEEDED;
2018-12-17 08:39:17 +01:00
}
2018-12-22 17:32:21 +01:00
facility = VarGet(VAR_FRONTIER_FACILITY);
2019-10-18 01:22:03 +02:00
if (facility == FACILITY_UNION_ROOM || facility == FACILITY_MULTI_OR_EREADER)
2018-12-22 17:32:21 +01:00
return 0xFF;
2019-10-18 01:22:03 +02:00
maxBattlers = GetMaxBattleEntries();
for (i = 0; i < maxBattlers - 1; i++)
2018-12-17 08:39:17 +01:00
{
2018-12-22 17:32:21 +01:00
u16 species = GetMonData(&party[order[i] - 1], MON_DATA_SPECIES);
u16 item = GetMonData(&party[order[i] - 1], MON_DATA_HELD_ITEM);
2019-10-18 01:22:03 +02:00
for (j = i + 1; j < maxBattlers; j++)
2018-12-17 08:39:17 +01:00
{
2018-12-22 17:32:21 +01:00
if (species == GetMonData(&party[order[j] - 1], MON_DATA_SPECIES))
2019-10-18 01:22:03 +02:00
return PARTY_MSG_MONS_CANT_BE_SAME;
2018-12-22 17:32:21 +01:00
if (item != ITEM_NONE && item == GetMonData(&party[order[j] - 1], MON_DATA_HELD_ITEM))
2019-10-18 01:22:03 +02:00
return PARTY_MSG_NO_SAME_HOLD_ITEMS;
2018-12-17 08:39:17 +01:00
}
}
2018-12-22 17:32:21 +01:00
2018-12-17 08:39:17 +01:00
return 0xFF;
}
2019-10-18 01:22:03 +02:00
static bool8 HasPartySlotAlreadyBeenSelected(u8 slot)
2018-12-17 08:39:17 +01:00
{
u8 i;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
for (i = 0; i < ARRAY_COUNT(gSelectedOrderFromParty); i++)
2018-12-17 08:39:17 +01:00
{
if (gSelectedOrderFromParty[i] == slot)
return TRUE;
}
return FALSE;
}
2019-10-18 01:22:03 +02:00
static void Task_ValidateChosenHalfParty(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
u8 msgId = CheckBattleEntriesAndGetMessage();
2018-12-22 17:32:21 +01:00
2018-12-24 21:59:05 +01:00
if (msgId != 0xFF)
2018-12-17 08:39:17 +01:00
{
2020-08-21 00:02:00 +02:00
PlaySE(SE_FAILURE);
DisplayPartyMenuStdMessage(msgId);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_ContinueChoosingHalfParty;
2018-12-17 08:39:17 +01:00
}
else
{
PlaySE(SE_SELECT);
Task_ClosePartyMenu(taskId);
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static void Task_ContinueChoosingHalfParty(u8 taskId)
2018-12-17 08:39:17 +01:00
{
2020-09-05 03:11:55 +02:00
if ((JOY_NEW(A_BUTTON)) || (JOY_NEW(B_BUTTON)))
2018-12-17 08:39:17 +01:00
{
PlaySE(SE_SELECT);
2019-10-18 01:22:03 +02:00
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
gTasks[taskId].func = Task_HandleChooseMonInput;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static u8 GetMaxBattleEntries(void)
2018-12-17 08:39:17 +01:00
{
switch (VarGet(VAR_FRONTIER_FACILITY))
{
2019-10-18 01:22:03 +02:00
case FACILITY_MULTI_OR_EREADER:
2020-04-09 21:18:53 +02:00
return MULTI_PARTY_SIZE;
2019-10-18 01:22:03 +02:00
case FACILITY_UNION_ROOM:
2020-04-09 21:18:53 +02:00
return UNION_ROOM_PARTY_SIZE;
2019-10-18 01:22:03 +02:00
default: // Battle Frontier
2018-12-22 17:32:21 +01:00
return gSpecialVar_0x8005;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static u8 GetMinBattleEntries(void)
2018-12-17 08:39:17 +01:00
{
switch (VarGet(VAR_FRONTIER_FACILITY))
{
2019-10-18 01:22:03 +02:00
case FACILITY_MULTI_OR_EREADER:
2018-12-22 17:32:21 +01:00
return 1;
2019-10-18 01:22:03 +02:00
case FACILITY_UNION_ROOM:
2020-04-09 21:18:53 +02:00
return UNION_ROOM_PARTY_SIZE;
2019-10-18 01:22:03 +02:00
default: // Battle Frontier
2018-12-22 17:32:21 +01:00
return gSpecialVar_0x8005;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static u8 GetBattleEntryLevelCap(void)
2018-12-17 08:39:17 +01:00
{
switch (VarGet(VAR_FRONTIER_FACILITY))
{
2019-10-18 01:22:03 +02:00
case FACILITY_MULTI_OR_EREADER:
return MAX_LEVEL;
case FACILITY_UNION_ROOM:
2018-12-22 17:32:21 +01:00
return 30;
2019-10-18 01:22:03 +02:00
default: // Battle Frontier
if (gSpecialVar_0x8004 == FRONTIER_LVL_50)
2018-12-22 17:32:21 +01:00
return 50;
2019-10-18 01:22:03 +02:00
return MAX_LEVEL;
2018-12-17 08:39:17 +01:00
}
}
2019-10-18 01:22:03 +02:00
static const u8* GetFacilityCancelString(void)
2018-12-17 08:39:17 +01:00
{
u8 facilityNum = VarGet(VAR_FRONTIER_FACILITY);
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
if (!(facilityNum != FACILITY_UNION_ROOM && facilityNum != FACILITY_MULTI_OR_EREADER))
2018-12-17 08:39:17 +01:00
return gText_CancelBattle;
2018-12-24 21:59:05 +01:00
else if (facilityNum == FRONTIER_FACILITY_DOME && gSpecialVar_0x8005 == 2)
2018-12-17 08:39:17 +01:00
return gText_ReturnToWaitingRoom;
2018-12-24 21:59:05 +01:00
else
return gText_CancelChallenge;
2018-12-17 08:39:17 +01:00
}
2019-10-31 19:11:55 +01:00
void ChooseMonForTradingBoard(u8 menuType, MainCallback callback)
2018-12-17 08:39:17 +01:00
{
2019-10-31 19:11:55 +01:00
InitPartyMenu(menuType, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, callback);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
void ChooseMonForMoveTutor(void)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_MOVE_TUTOR, FALSE, PARTY_MSG_TEACH_WHICH_MON, Task_HandleChooseMonInput, CB2_ReturnToFieldContinueScriptPlayMapMusic);
2018-12-17 08:39:17 +01:00
}
2019-10-11 10:14:09 +02:00
void ChooseMonForWirelessMinigame(void)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_MINIGAME, PARTY_LAYOUT_SINGLE, PARTY_ACTION_MINIGAME, FALSE, PARTY_MSG_CHOOSE_MON_OR_CANCEL, Task_HandleChooseMonInput, CB2_ReturnToFieldContinueScriptPlayMapMusic);
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static u8 GetPartyLayoutFromBattleType(void)
2018-12-17 08:39:17 +01:00
{
if (IsDoubleBattle() == FALSE)
2019-10-18 01:22:03 +02:00
return PARTY_LAYOUT_SINGLE;
2018-12-18 11:38:08 +01:00
if (IsMultiBattle() == TRUE)
2019-10-18 01:22:03 +02:00
return PARTY_LAYOUT_MULTI;
return PARTY_LAYOUT_DOUBLE;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
void OpenPartyMenuInBattle(u8 partyAction)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), partyAction, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_SetUpReshowBattleScreenAfterMenu);
2021-01-23 02:03:21 +01:00
ReshowBattleScreenDummy();
2019-10-18 01:22:03 +02:00
UpdatePartyToBattleOrder();
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
void ChooseMonForInBattleItem(void)
2018-12-17 08:39:17 +01:00
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), PARTY_ACTION_USE_ITEM, FALSE, PARTY_MSG_USE_ON_WHICH_MON, Task_HandleChooseMonInput, CB2_ReturnToBagMenu);
2021-01-23 02:03:21 +01:00
ReshowBattleScreenDummy();
2019-10-18 01:22:03 +02:00
UpdatePartyToBattleOrder();
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static u8 GetPartyMenuActionsTypeInBattle(struct Pokemon *mon)
2018-12-17 08:39:17 +01:00
{
if (GetMonData(&gPlayerParty[1], MON_DATA_SPECIES) != SPECIES_NONE && GetMonData(mon, MON_DATA_IS_EGG) == FALSE)
{
2019-10-18 01:22:03 +02:00
if (gPartyMenu.action == PARTY_ACTION_SEND_OUT)
return ACTIONS_SEND_OUT;
2018-12-17 08:39:17 +01:00
if (!(gBattleTypeFlags & BATTLE_TYPE_ARENA))
2019-10-18 01:22:03 +02:00
return ACTIONS_SHIFT;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
return ACTIONS_SUMMARY_ONLY;
2018-12-17 08:39:17 +01:00
}
2019-10-18 01:22:03 +02:00
static bool8 TrySwitchInPokemon(void)
2018-12-17 08:39:17 +01:00
{
u8 slot = GetCursorSelectionMonId();
u8 newSlot;
u8 i;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
// In a multi battle, slots 1, 4, and 5 are the partner's pokemon
2018-12-18 11:38:08 +01:00
if (IsMultiBattle() == TRUE && (slot == 1 || slot == 4 || slot == 5))
2018-12-17 08:39:17 +01:00
{
StringCopy(gStringVar1, GetTrainerPartnerName());
StringExpandPlaceholders(gStringVar4, gText_CantSwitchWithAlly);
return FALSE;
}
if (GetMonData(&gPlayerParty[slot], MON_DATA_HP) == 0)
{
GetMonNickname(&gPlayerParty[slot], gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_PkmnHasNoEnergy);
return FALSE;
}
for (i = 0; i < gBattlersCount; i++)
{
2019-10-18 01:22:03 +02:00
if (GetBattlerSide(i) == B_SIDE_PLAYER && GetPartyIdFromBattleSlot(slot) == gBattlerPartyIndexes[i])
2018-12-17 08:39:17 +01:00
{
GetMonNickname(&gPlayerParty[slot], gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_PkmnAlreadyInBattle);
return FALSE;
}
}
2018-12-20 02:27:44 +01:00
if (GetMonData(&gPlayerParty[slot], MON_DATA_IS_EGG))
2018-12-17 08:39:17 +01:00
{
StringExpandPlaceholders(gStringVar4, gText_EggCantBattle);
return FALSE;
}
2021-01-23 02:03:21 +01:00
if (GetPartyIdFromBattleSlot(slot) == gBattleStruct->prevSelectedPartySlot)
2018-12-17 08:39:17 +01:00
{
GetMonNickname(&gPlayerParty[slot], gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_PkmnAlreadySelected);
return FALSE;
}
2019-10-18 01:22:03 +02:00
if (gPartyMenu.action == PARTY_ACTION_ABILITY_PREVENTS)
2018-12-17 08:39:17 +01:00
{
SetMonPreventsSwitchingString();
return FALSE;
}
2019-10-18 01:22:03 +02:00
if (gPartyMenu.action == PARTY_ACTION_CANT_SWITCH)
2018-12-17 08:39:17 +01:00
{
2018-12-24 21:59:05 +01:00
u8 currBattler = gBattlerInMenuId;
2019-10-26 03:55:01 +02:00
GetMonNickname(&gPlayerParty[GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[currBattler])], gStringVar1);
2018-12-17 08:39:17 +01:00
StringExpandPlaceholders(gStringVar4, gText_PkmnCantSwitchOut);
return FALSE;
}
2019-10-26 03:55:01 +02:00
gSelectedMonPartyId = GetPartyIdFromBattleSlot(slot);
gPartyMenuUseExitCallback = TRUE;
newSlot = GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[gBattlerInMenuId]);
2019-10-18 01:22:03 +02:00
SwitchPartyMonSlots(newSlot, slot);
SwapPartyPokemon(&gPlayerParty[newSlot], &gPlayerParty[slot]);
2018-12-17 08:39:17 +01:00
return TRUE;
}
2018-12-18 11:38:08 +01:00
2019-10-31 19:11:55 +01:00
void BufferBattlePartyCurrentOrder(void)
2018-12-18 11:38:08 +01:00
{
2019-10-31 19:11:55 +01:00
BufferBattlePartyOrder(gBattlePartyCurrentOrder, GetPlayerFlankId());
2018-12-18 11:38:08 +01:00
}
2019-10-31 19:11:55 +01:00
static void BufferBattlePartyOrder(u8 *partyBattleOrder, u8 flankId)
2018-12-18 11:38:08 +01:00
{
2019-10-31 19:11:55 +01:00
u8 partyIds[PARTY_SIZE];
2018-12-18 11:38:08 +01:00
int i, j;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
if (IsMultiBattle() == TRUE)
{
2019-10-31 19:11:55 +01:00
// Party ids are packed in 4 bits at a time
// i.e. the party id order below would be 0, 3, 5, 4, 2, 1, and the two parties would be 0,5,4 and 3,2,1
if (flankId != 0)
2018-12-18 11:38:08 +01:00
{
2019-10-18 01:22:03 +02:00
partyBattleOrder[0] = 0 | (3 << 4);
partyBattleOrder[1] = 5 | (4 << 4);
partyBattleOrder[2] = 2 | (1 << 4);
2018-12-18 11:38:08 +01:00
}
else
{
2019-10-18 01:22:03 +02:00
partyBattleOrder[0] = 3 | (0 << 4);
partyBattleOrder[1] = 2 | (1 << 4);
partyBattleOrder[2] = 5 | (4 << 4);
2018-12-18 11:38:08 +01:00
}
return;
}
else if (IsDoubleBattle() == FALSE)
{
j = 1;
2019-10-31 19:11:55 +01:00
partyIds[0] = gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)];
2018-12-18 11:38:08 +01:00
for (i = 0; i < PARTY_SIZE; i++)
{
2019-10-31 19:11:55 +01:00
if (i != partyIds[0])
2018-12-18 11:38:08 +01:00
{
2019-10-31 19:11:55 +01:00
partyIds[j] = i;
2018-12-18 11:38:08 +01:00
j++;
}
}
}
else
{
j = 2;
2019-10-31 19:11:55 +01:00
partyIds[0] = gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)];
partyIds[1] = gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT)];
2018-12-18 11:38:08 +01:00
for (i = 0; i < PARTY_SIZE; i++)
{
2019-10-31 19:11:55 +01:00
if (i != partyIds[0] && i != partyIds[1])
2018-12-18 11:38:08 +01:00
{
2019-10-31 19:11:55 +01:00
partyIds[j] = i;
2018-12-18 11:38:08 +01:00
j++;
}
}
}
2019-10-18 01:22:03 +02:00
for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++)
2019-10-31 19:11:55 +01:00
partyBattleOrder[i] = (partyIds[0 + (i * 2)] << 4) | partyIds[1 + (i * 2)];
2018-12-18 11:38:08 +01:00
}
2019-10-31 19:11:55 +01:00
void BufferBattlePartyCurrentOrderBySide(u8 battlerId, u8 flankId)
2018-12-18 11:38:08 +01:00
{
2019-10-31 19:11:55 +01:00
BufferBattlePartyOrderBySide(gBattleStruct->field_60[battlerId], flankId, battlerId);
2018-12-18 11:38:08 +01:00
}
2019-10-31 19:11:55 +01:00
// when GetBattlerSide(battlerId) == B_SIDE_PLAYER, this function is identical the one above
static void BufferBattlePartyOrderBySide(u8 *partyBattleOrder, u8 flankId, u8 battlerId)
2018-12-18 11:38:08 +01:00
{
2019-10-18 01:22:03 +02:00
u8 partyIndexes[PARTY_SIZE];
2018-12-18 11:38:08 +01:00
int i, j;
u8 leftBattler;
u8 rightBattler;
2018-12-22 17:32:21 +01:00
2018-12-24 00:02:29 +01:00
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
2018-12-18 11:38:08 +01:00
{
leftBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
rightBattler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
}
else
{
leftBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
rightBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
}
2018-12-24 00:02:29 +01:00
2018-12-18 11:38:08 +01:00
if (IsMultiBattle() == TRUE)
{
2019-10-31 19:11:55 +01:00
if (flankId != 0)
2018-12-18 11:38:08 +01:00
{
2019-10-31 19:11:55 +01:00
partyBattleOrder[0] = 0 | (3 << 4);
partyBattleOrder[1] = 5 | (4 << 4);
partyBattleOrder[2] = 2 | (1 << 4);
2018-12-18 11:38:08 +01:00
}
else
{
2019-10-31 19:11:55 +01:00
partyBattleOrder[0] = 3 | (0 << 4);
partyBattleOrder[1] = 2 | (1 << 4);
partyBattleOrder[2] = 5 | (4 << 4);
2018-12-18 11:38:08 +01:00
}
return;
}
else if (IsDoubleBattle() == FALSE)
{
j = 1;
partyIndexes[0] = gBattlerPartyIndexes[leftBattler];
for (i = 0; i < PARTY_SIZE; i++)
{
if (i != partyIndexes[0])
{
partyIndexes[j] = i;
j++;
}
}
}
else
{
j = 2;
partyIndexes[0] = gBattlerPartyIndexes[leftBattler];
partyIndexes[1] = gBattlerPartyIndexes[rightBattler];
for (i = 0; i < PARTY_SIZE; i++)
{
if (i != partyIndexes[0] && i != partyIndexes[1])
{
partyIndexes[j] = i;
j++;
}
}
}
2018-12-24 00:02:29 +01:00
2018-12-18 11:38:08 +01:00
for (i = 0; i < 3; i++)
2019-10-31 19:11:55 +01:00
partyBattleOrder[i] = (partyIndexes[0 + (i * 2)] << 4) | partyIndexes[1 + (i * 2)];
2018-12-18 11:38:08 +01:00
}
2019-10-31 19:11:55 +01:00
void SwitchPartyOrderLinkMulti(u8 battlerId, u8 slot, u8 slot2)
2018-12-18 11:38:08 +01:00
{
2019-10-31 19:11:55 +01:00
u8 partyIds[PARTY_SIZE];
u8 tempSlot = 0;
2018-12-18 11:38:08 +01:00
int i, j;
2019-10-31 19:11:55 +01:00
u8 *partyBattleOrder;
u8 partyIdBuffer;
2018-12-22 17:32:21 +01:00
2018-12-20 02:27:44 +01:00
if (IsMultiBattle())
2018-12-18 11:38:08 +01:00
{
2019-10-31 19:11:55 +01:00
partyBattleOrder = gBattleStruct->field_60[battlerId];
2018-12-18 11:38:08 +01:00
for (i = j = 0; i < 3; j++, i++)
{
2019-10-31 19:11:55 +01:00
partyIds[j] = partyBattleOrder[i] >> 4;
2018-12-18 11:38:08 +01:00
j++;
2019-10-31 19:11:55 +01:00
partyIds[j] = partyBattleOrder[i] & 0xF;
2018-12-18 11:38:08 +01:00
}
2019-10-31 19:11:55 +01:00
partyIdBuffer = partyIds[slot2];
2018-12-18 11:38:08 +01:00
for (i = 0; i < PARTY_SIZE; i++)
{
2019-10-31 19:11:55 +01:00
if (partyIds[i] == slot)
2018-12-18 11:38:08 +01:00
{
2019-10-31 19:11:55 +01:00
tempSlot = partyIds[i];
partyIds[i] = partyIdBuffer;
2018-12-18 11:38:08 +01:00
break;
}
}
if (i != PARTY_SIZE)
{
2019-10-31 19:11:55 +01:00
partyIds[slot2] = tempSlot;
partyBattleOrder[0] = (partyIds[0] << 4) | partyIds[1];
partyBattleOrder[1] = (partyIds[2] << 4) | partyIds[3];
partyBattleOrder[2] = (partyIds[4] << 4) | partyIds[5];
2018-12-18 11:38:08 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
static u8 GetPartyIdFromBattleSlot(u8 slot)
2018-12-18 11:38:08 +01:00
{
u8 modResult = slot & 1;
u8 retVal;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
slot /= 2;
if (modResult != 0)
2019-10-18 01:22:03 +02:00
retVal = gBattlePartyCurrentOrder[slot] & 0xF;
2018-12-18 11:38:08 +01:00
else
2019-10-18 01:22:03 +02:00
retVal = gBattlePartyCurrentOrder[slot] >> 4;
2018-12-18 11:38:08 +01:00
return retVal;
}
2019-10-18 01:22:03 +02:00
static void SetPartyIdAtBattleSlot(u8 slot, u8 setVal)
2018-12-18 11:38:08 +01:00
{
bool32 modResult = slot & 1;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
slot /= 2;
if (modResult != 0)
2019-10-18 01:22:03 +02:00
gBattlePartyCurrentOrder[slot] = (gBattlePartyCurrentOrder[slot] & 0xF0) | setVal;
2018-12-18 11:38:08 +01:00
else
2019-10-18 01:22:03 +02:00
gBattlePartyCurrentOrder[slot] = (gBattlePartyCurrentOrder[slot] & 0xF) | (setVal << 4);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
void SwitchPartyMonSlots(u8 slot, u8 slot2)
2018-12-18 11:38:08 +01:00
{
2019-10-18 01:22:03 +02:00
u8 partyId = GetPartyIdFromBattleSlot(slot);
SetPartyIdAtBattleSlot(slot, GetPartyIdFromBattleSlot(slot2));
SetPartyIdAtBattleSlot(slot2, partyId);
2018-12-18 11:38:08 +01:00
}
2019-10-26 03:55:01 +02:00
u8 GetPartyIdFromBattlePartyId(u8 battlePartyId)
2018-12-18 11:38:08 +01:00
{
u8 i, j;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
for (j = i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); j++, i++)
2018-12-18 11:38:08 +01:00
{
2019-10-26 03:55:01 +02:00
if ((gBattlePartyCurrentOrder[i] >> 4) != battlePartyId)
2018-12-18 11:38:08 +01:00
{
j++;
2019-10-26 03:55:01 +02:00
if ((gBattlePartyCurrentOrder[i] & 0xF) == battlePartyId)
2018-12-18 11:38:08 +01:00
return j;
}
else
{
return j;
}
}
return 0;
}
2019-10-18 01:22:03 +02:00
static void UpdatePartyToBattleOrder(void)
2018-12-18 11:38:08 +01:00
{
struct Pokemon *partyBuffer = Alloc(sizeof(gPlayerParty));
u8 i;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
memcpy(partyBuffer, gPlayerParty, sizeof(gPlayerParty));
for (i = 0; i < PARTY_SIZE; i++)
2019-10-26 03:55:01 +02:00
memcpy(&gPlayerParty[GetPartyIdFromBattlePartyId(i)], &partyBuffer[i], sizeof(struct Pokemon));
2018-12-18 11:38:08 +01:00
Free(partyBuffer);
}
2019-10-18 01:22:03 +02:00
static void UpdatePartyToFieldOrder(void)
2018-12-18 11:38:08 +01:00
{
struct Pokemon *partyBuffer = Alloc(sizeof(gPlayerParty));
u8 i;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
memcpy(partyBuffer, gPlayerParty, sizeof(gPlayerParty));
for (i = 0; i < PARTY_SIZE; i++)
2019-10-18 01:22:03 +02:00
memcpy(&gPlayerParty[GetPartyIdFromBattleSlot(i)], &partyBuffer[i], sizeof(struct Pokemon));
2018-12-18 11:38:08 +01:00
Free(partyBuffer);
}
2019-10-18 01:22:03 +02:00
// Unused
static void SwitchAliveMonIntoLeadSlot(void)
2018-12-18 11:38:08 +01:00
{
u8 i;
struct Pokemon *mon;
2019-10-18 01:22:03 +02:00
u8 partyId;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
for (i = 1; i < PARTY_SIZE; i++)
{
2019-10-18 01:22:03 +02:00
mon = &gPlayerParty[GetPartyIdFromBattleSlot(i)];
2018-12-18 11:38:08 +01:00
if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE && GetMonData(mon, MON_DATA_HP) != 0)
{
2019-10-18 01:22:03 +02:00
partyId = GetPartyIdFromBattleSlot(0);
SwitchPartyMonSlots(0, i);
SwapPartyPokemon(&gPlayerParty[partyId], mon);
2018-12-18 11:38:08 +01:00
break;
}
}
}
2019-10-18 01:22:03 +02:00
static void CB2_SetUpExitToBattleScreen(void)
2018-12-18 11:38:08 +01:00
{
2019-10-18 01:22:03 +02:00
SetMainCallback2(CB2_SetUpReshowBattleScreenAfterMenu);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
void ShowPartyMenuToShowcaseMultiBattleParty(void)
2018-12-18 11:38:08 +01:00
{
2019-10-26 03:55:01 +02:00
InitPartyMenu(PARTY_MENU_TYPE_MULTI_SHOWCASE, PARTY_LAYOUT_MULTI_SHOWCASE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_NONE, Task_InitMultiPartnerPartySlideIn, gMain.savedCallback);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
#define tXPos data[0]
static void Task_InitMultiPartnerPartySlideIn(u8 taskId)
2018-12-18 11:38:08 +01:00
{
2019-10-18 01:22:03 +02:00
// The first slide step also sets the sprites offscreen
gTasks[taskId].tXPos = 256;
SlideMultiPartyMenuBoxSpritesOneStep(taskId);
2018-12-18 11:38:08 +01:00
ChangeBgX(2, 0x10000, 0);
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_MultiPartnerPartySlideIn;
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_MultiPartnerPartySlideIn(u8 taskId)
2018-12-18 11:38:08 +01:00
{
s16 *data = gTasks[taskId].data;
u8 i;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
if (!gPaletteFade.active)
{
2019-10-18 01:22:03 +02:00
tXPos -= 8;
SlideMultiPartyMenuBoxSpritesOneStep(taskId);
if (tXPos == 0)
2018-12-18 11:38:08 +01:00
{
2020-04-09 21:18:53 +02:00
for (i = MULTI_PARTY_SIZE; i < PARTY_SIZE; i++)
2018-12-18 11:38:08 +01:00
{
2019-11-01 02:33:01 +01:00
if (gMultiPartnerParty[i - MULTI_PARTY_SIZE].species != SPECIES_NONE)
2019-10-18 01:22:03 +02:00
AnimateSelectedPartyIcon(sPartyMenuBoxes[i].monSpriteId, 0);
2018-12-18 11:38:08 +01:00
}
2020-08-21 00:02:00 +02:00
PlaySE(SE_M_HARDEN); // The Harden SE plays once the partners party mons have slid on screen
2019-10-18 01:22:03 +02:00
gTasks[taskId].func = Task_WaitAfterMultiPartnerPartySlideIn;
2018-12-18 11:38:08 +01:00
}
}
}
2019-10-18 01:22:03 +02:00
static void Task_WaitAfterMultiPartnerPartySlideIn(u8 taskId)
2018-12-18 11:38:08 +01:00
{
s16 *data = gTasks[taskId].data;
2018-12-22 17:32:21 +01:00
2019-10-18 01:22:03 +02:00
// data[0] used as a timer afterwards rather than the x pos
if (++data[0] == 256)
Task_ClosePartyMenu(taskId);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
static void MoveMultiPartyMenuBoxSprite(u8 spriteId, s16 x)
2018-12-18 11:38:08 +01:00
{
if (x >= 0)
gSprites[spriteId].pos2.x = x;
}
2019-10-18 01:22:03 +02:00
static void SlideMultiPartyMenuBoxSpritesOneStep(u8 taskId)
2018-12-18 11:38:08 +01:00
{
s16 *data = gTasks[taskId].data;
u8 i;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
for (i = 3; i < PARTY_SIZE; i++)
{
2019-11-01 02:33:01 +01:00
if (gMultiPartnerParty[i - MULTI_PARTY_SIZE].species != SPECIES_NONE)
2018-12-18 11:38:08 +01:00
{
2019-10-18 01:22:03 +02:00
MoveMultiPartyMenuBoxSprite(sPartyMenuBoxes[i].monSpriteId, tXPos - 8);
MoveMultiPartyMenuBoxSprite(sPartyMenuBoxes[i].itemSpriteId, tXPos - 8);
MoveMultiPartyMenuBoxSprite(sPartyMenuBoxes[i].pokeballSpriteId, tXPos - 8);
MoveMultiPartyMenuBoxSprite(sPartyMenuBoxes[i].statusSpriteId, tXPos - 8);
2018-12-18 11:38:08 +01:00
}
}
ChangeBgX(2, 0x800, 1);
}
2019-10-18 01:22:03 +02:00
#undef tXpos
void ChooseMonForDaycare(void)
2018-12-18 11:38:08 +01:00
{
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_DAYCARE, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON_2, Task_HandleChooseMonInput, BufferMonSelection);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
// Unused
static void ChoosePartyMonByMenuType(u8 menuType)
2018-12-18 11:38:08 +01:00
{
2019-10-18 01:22:03 +02:00
gFieldCallback2 = CB2_FadeFromPartyMenu;
InitPartyMenu(menuType, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_AND_CLOSE, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_ReturnToField);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
static void BufferMonSelection(void)
2018-12-18 11:38:08 +01:00
{
gSpecialVar_0x8004 = GetCursorSelectionMonId();
if (gSpecialVar_0x8004 >= PARTY_SIZE)
gSpecialVar_0x8004 = 0xFF;
2019-10-18 01:22:03 +02:00
gFieldCallback2 = CB2_FadeFromPartyMenu;
2018-12-18 11:38:08 +01:00
SetMainCallback2(CB2_ReturnToField);
}
2019-10-18 01:22:03 +02:00
bool8 CB2_FadeFromPartyMenu(void)
2018-12-18 11:38:08 +01:00
{
2019-12-17 09:24:44 +01:00
FadeInFromBlack();
2019-10-18 01:22:03 +02:00
CreateTask(Task_PartyMenuWaitForFade, 10);
2018-12-18 11:38:08 +01:00
return TRUE;
}
2019-10-18 01:22:03 +02:00
static void Task_PartyMenuWaitForFade(u8 taskId)
2018-12-18 11:38:08 +01:00
{
2018-12-20 02:27:44 +01:00
if (IsWeatherNotFadingIn())
2018-12-18 11:38:08 +01:00
{
DestroyTask(taskId);
ScriptContext2_Disable();
EnableBothScriptContexts();
}
}
2019-10-18 01:22:03 +02:00
void ChooseContestMon(void)
2018-12-18 11:38:08 +01:00
{
ScriptContext2_Enable();
FadeScreen(FADE_TO_BLACK, 0);
2019-10-18 01:22:03 +02:00
CreateTask(Task_ChooseContestMon, 10);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_ChooseContestMon(u8 taskId)
2018-12-18 11:38:08 +01:00
{
if (!gPaletteFade.active)
{
2018-12-27 23:30:47 +01:00
CleanupOverworldWindowsAndTilemaps();
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_CONTEST, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_AND_CLOSE, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_ChooseContestMon);
2018-12-18 11:38:08 +01:00
DestroyTask(taskId);
}
}
2019-10-18 01:22:03 +02:00
static void CB2_ChooseContestMon(void)
2018-12-18 11:38:08 +01:00
{
2019-01-03 18:54:22 +01:00
gContestMonPartyIndex = GetCursorSelectionMonId();
if (gContestMonPartyIndex >= PARTY_SIZE)
gContestMonPartyIndex = 0xFF;
gSpecialVar_0x8004 = gContestMonPartyIndex;
2019-10-18 01:22:03 +02:00
gFieldCallback2 = CB2_FadeFromPartyMenu;
2018-12-18 11:38:08 +01:00
SetMainCallback2(CB2_ReturnToField);
}
2019-10-18 01:22:03 +02:00
// Used as a script special for showing a party mon to various npcs (e.g. in-game trades, move deleter)
void ChoosePartyMon(void)
2018-12-18 11:38:08 +01:00
{
ScriptContext2_Enable();
FadeScreen(FADE_TO_BLACK, 0);
2019-10-18 01:22:03 +02:00
CreateTask(Task_ChoosePartyMon, 10);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_ChoosePartyMon(u8 taskId)
2018-12-18 11:38:08 +01:00
{
if (!gPaletteFade.active)
{
2018-12-27 23:30:47 +01:00
CleanupOverworldWindowsAndTilemaps();
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_CHOOSE_MON, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_AND_CLOSE, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, BufferMonSelection);
2018-12-18 11:38:08 +01:00
DestroyTask(taskId);
}
}
2019-10-18 01:22:03 +02:00
void ChooseMonForMoveRelearner(void)
2018-12-18 11:38:08 +01:00
{
ScriptContext2_Enable();
FadeScreen(FADE_TO_BLACK, 0);
2019-10-18 01:22:03 +02:00
CreateTask(Task_ChooseMonForMoveRelearner, 10);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_ChooseMonForMoveRelearner(u8 taskId)
2018-12-18 11:38:08 +01:00
{
if (!gPaletteFade.active)
{
2018-12-27 23:30:47 +01:00
CleanupOverworldWindowsAndTilemaps();
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_MOVE_RELEARNER, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_AND_CLOSE, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_ChooseMonForMoveRelearner);
2018-12-18 11:38:08 +01:00
DestroyTask(taskId);
}
}
2019-10-18 01:22:03 +02:00
static void CB2_ChooseMonForMoveRelearner(void)
2018-12-18 11:38:08 +01:00
{
gSpecialVar_0x8004 = GetCursorSelectionMonId();
if (gSpecialVar_0x8004 >= PARTY_SIZE)
gSpecialVar_0x8004 = 0xFF;
else
gSpecialVar_0x8005 = GetNumberOfRelearnableMoves(&gPlayerParty[gSpecialVar_0x8004]);
2019-10-18 01:22:03 +02:00
gFieldCallback2 = CB2_FadeFromPartyMenu;
2018-12-18 11:38:08 +01:00
SetMainCallback2(CB2_ReturnToField);
}
2019-10-18 01:22:03 +02:00
void DoBattlePyramidMonsHaveHeldItem(void)
2018-12-18 11:38:08 +01:00
{
u8 i;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
gSpecialVar_Result = FALSE;
2019-11-01 02:33:01 +01:00
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
2018-12-18 11:38:08 +01:00
{
if (GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM) != ITEM_NONE)
{
gSpecialVar_Result = TRUE;
break;
}
}
}
2019-10-18 01:22:03 +02:00
// Can be called if the Battle Pyramid Bag is full on exiting and at least one party mon still has held items
// The player can then select to toss items from the bag or take/toss held items from the party
void BattlePyramidChooseMonHeldItems(void)
2018-12-18 11:38:08 +01:00
{
ScriptContext2_Enable();
FadeScreen(FADE_TO_BLACK, 0);
2019-10-18 01:22:03 +02:00
CreateTask(Task_BattlePyramidChooseMonHeldItems, 10);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
static void Task_BattlePyramidChooseMonHeldItems(u8 taskId)
2018-12-18 11:38:08 +01:00
{
if (!gPaletteFade.active)
{
2018-12-27 23:30:47 +01:00
CleanupOverworldWindowsAndTilemaps();
2019-10-18 01:22:03 +02:00
InitPartyMenu(PARTY_MENU_TYPE_STORE_PYRAMID_HELD_ITEMS, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, BufferMonSelection);
2018-12-18 11:38:08 +01:00
DestroyTask(taskId);
}
}
2019-10-18 01:22:03 +02:00
void MoveDeleterChooseMoveToForget(void)
2018-12-18 11:38:08 +01:00
{
ShowPokemonSummaryScreen(PSS_MODE_SELECT_MOVE, gPlayerParty, gSpecialVar_0x8004, gPlayerPartyCount - 1, CB2_ReturnToField);
2019-12-17 09:24:44 +01:00
gFieldCallback = FieldCB_ContinueScriptHandleMusic;
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
void GetNumMovesSelectedMonHas(void)
2018-12-18 11:38:08 +01:00
{
u8 i;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
gSpecialVar_Result = 0;
for (i = 0; i < MAX_MON_MOVES; i++)
{
2019-10-18 01:22:03 +02:00
if (GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_MOVE1 + i) != MOVE_NONE)
2018-12-18 11:38:08 +01:00
gSpecialVar_Result++;
}
}
2019-10-18 01:22:03 +02:00
void BufferMoveDeleterNicknameAndMove(void)
2018-12-18 11:38:08 +01:00
{
struct Pokemon *mon = &gPlayerParty[gSpecialVar_0x8004];
u16 move = GetMonData(mon, MON_DATA_MOVE1 + gSpecialVar_0x8005);
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
GetMonNickname(mon, gStringVar1);
StringCopy(gStringVar2, gMoveNames[move]);
}
2019-10-18 01:22:03 +02:00
void MoveDeleterForgetMove(void)
2018-12-18 11:38:08 +01:00
{
u16 i;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
SetMonMoveSlot(&gPlayerParty[gSpecialVar_0x8004], MOVE_NONE, gSpecialVar_0x8005);
RemoveMonPPBonus(&gPlayerParty[gSpecialVar_0x8004], gSpecialVar_0x8005);
for (i = gSpecialVar_0x8005; i < MAX_MON_MOVES - 1; i++)
2019-10-18 01:22:03 +02:00
ShiftMoveSlot(&gPlayerParty[gSpecialVar_0x8004], i, i + 1);
2018-12-18 11:38:08 +01:00
}
2019-10-18 01:22:03 +02:00
static void ShiftMoveSlot(struct Pokemon *mon, u8 slotTo, u8 slotFrom)
2018-12-18 11:38:08 +01:00
{
u16 move1 = GetMonData(mon, MON_DATA_MOVE1 + slotTo);
u16 move0 = GetMonData(mon, MON_DATA_MOVE1 + slotFrom);
u8 pp1 = GetMonData(mon, MON_DATA_PP1 + slotTo);
u8 pp0 = GetMonData(mon, MON_DATA_PP1 + slotFrom);
u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES);
u8 ppBonusMask1 = gPPUpGetMask[slotTo];
2018-12-18 11:38:08 +01:00
u8 ppBonusMove1 = (ppBonuses & ppBonusMask1) >> (slotTo * 2);
u8 ppBonusMask2 = gPPUpGetMask[slotFrom];
2018-12-18 11:38:08 +01:00
u8 ppBonusMove2 = (ppBonuses & ppBonusMask2) >> (slotFrom * 2);
ppBonuses &= ~ppBonusMask1;
ppBonuses &= ~ppBonusMask2;
ppBonuses |= (ppBonusMove1 << (slotFrom * 2)) + (ppBonusMove2 << (slotTo * 2));
SetMonData(mon, MON_DATA_MOVE1 + slotTo, &move0);
SetMonData(mon, MON_DATA_MOVE1 + slotFrom, &move1);
SetMonData(mon, MON_DATA_PP1 + slotTo, &pp0);
SetMonData(mon, MON_DATA_PP1 + slotFrom, &pp1);
SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses);
}
2019-10-18 01:22:03 +02:00
void IsSelectedMonEgg(void)
2018-12-18 11:38:08 +01:00
{
2018-12-20 02:27:44 +01:00
if (GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_IS_EGG))
2018-12-18 11:38:08 +01:00
gSpecialVar_Result = TRUE;
else
gSpecialVar_Result = FALSE;
}
2019-10-18 01:22:03 +02:00
void IsLastMonThatKnowsSurf(void)
2018-12-18 11:38:08 +01:00
{
u16 move;
u32 i, j;
2018-12-22 17:32:21 +01:00
2018-12-18 11:38:08 +01:00
gSpecialVar_Result = FALSE;
move = GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_MOVE1 + gSpecialVar_0x8005);
if (move == MOVE_SURF)
{
for (i = 0; i < CalculatePlayerPartyCount(); i++)
{
if (i != gSpecialVar_0x8004)
{
for (j = 0; j < MAX_MON_MOVES; j++)
{
if (GetMonData(&gPlayerParty[i], MON_DATA_MOVE1 + j) == MOVE_SURF)
return;
}
}
}
2018-12-20 22:53:08 +01:00
if (AnyStorageMonWithMove(move) != TRUE)
2018-12-18 11:38:08 +01:00
gSpecialVar_Result = TRUE;
}
}