From 43bce41796f8298aea53813c21ebf144f371dcae Mon Sep 17 00:00:00 2001 From: Zatsu <118256341+fakuzatsu@users.noreply.github.com> Date: Sat, 8 Feb 2025 23:54:58 +0000 Subject: [PATCH] Add caught mon to full party by sending a different mon to the Box (#6058) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- asm/macros/battle_script.inc | 6 +- data/battle_scripts_2.s | 6 +- data/text/pc_transfer.inc | 6 + include/config/battle.h | 2 + include/constants/battle_string_ids.h | 14 +- include/constants/party_menu.h | 4 +- include/naming_screen.h | 2 + include/strings.h | 5 + src/battle_controller_player.c | 3 +- src/battle_message.c | 11 +- src/battle_script_commands.c | 178 +++++++++++++++++++++----- src/data/party_menu.h | 1 + src/naming_screen.c | 22 ++-- src/party_menu.c | 74 ++++++++++- src/strings.c | 2 + 15 files changed, 268 insertions(+), 68 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index ae47761d7c..63b1be9f76 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1277,8 +1277,9 @@ .byte 0xef .endm - .macro givecaughtmon + .macro givecaughtmon passInstr:req .byte 0xf0 + .4byte \passInstr .endm .macro trysetcaughtmondexflags failInstr:req @@ -1290,9 +1291,8 @@ .byte 0xf2 .endm - .macro trygivecaughtmonnick successInstr:req + .macro trygivecaughtmonnick .byte 0xf3 - .4byte \successInstr .endm .macro subattackerhpbydmg diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index bd87dbf3ef..572d076fab 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -195,13 +195,13 @@ BattleScript_TryNicknameCaughtMon:: printstring STRINGID_GIVENICKNAMECAPTURED waitstate setbyte gBattleCommunication, 0 - trygivecaughtmonnick BattleScript_GiveCaughtMonEnd - givecaughtmon + trygivecaughtmonnick + givecaughtmon BattleScript_SuccessBallThrowEnd printfromtable gCaughtMonStringIds waitmessage B_WAIT_TIME_LONG goto BattleScript_SuccessBallThrowEnd BattleScript_GiveCaughtMonEnd:: - givecaughtmon + givecaughtmon BattleScript_SuccessBallThrowEnd BattleScript_SuccessBallThrowEnd:: setbyte gBattleOutcome, B_OUTCOME_CAUGHT finishturn diff --git a/data/text/pc_transfer.inc b/data/text/pc_transfer.inc index 3fa255340b..b6995d1111 100644 --- a/data/text/pc_transfer.inc +++ b/data/text/pc_transfer.inc @@ -22,6 +22,12 @@ gText_PkmnTransferredLanettesPCBoxFull:: .string "{STR_VAR_2} was transferred to\n" .string "BOX “{STR_VAR_1}.”$" +gText_PkmnSentToPCAfterCatch:: + .string "{STR_VAR_2} was sent to\n" + .string "{B_PC_CREATOR_NAME} PC.\p" + .string "It was placed in \n" + .string "BOX “{STR_VAR_1}”.$" + gText_NoMoreRoomForPokemon:: .string "There's no more room for POKéMON!\p" .string "The POKéMON BOXES are full and\n" diff --git a/include/config/battle.h b/include/config/battle.h index 898fc4416b..f7b2825b0b 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -250,6 +250,8 @@ #define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented #define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball. #define B_LAST_USED_BALL_CYCLE TRUE // If TRUE, then holding B_LAST_USED_BALL_BUTTON while pressing the D-Pad cycles through the balls +#define B_CATCH_SWAP_INTO_PARTY GEN_LATEST // In Gen 7+, the option to swap the caught wild mon to the party will appear, allowing you to send a different mon to the box. +#define B_CATCH_SWAP_CHECK_HMS TRUE // If TRUE, the catch swap feature above will prevent returning mons to the box if they know HMs. // Other settings #define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index a70ccbe5e8..3ba637c690 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -727,8 +727,10 @@ #define STRINGID_SUPEREFFECTIVETWOFOES 725 #define STRINGID_NOTVERYEFFECTIVETWOFOES 726 #define STRINGID_ITDOESNTAFFECTTWOFOES 727 +#define STRINGID_SENDCAUGHTMONPARTYORBOX 728 +#define STRINGID_PKMNSENTTOPCAFTERCATCH 729 -#define BATTLESTRINGS_COUNT 728 +#define BATTLESTRINGS_COUNT 730 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, @@ -892,10 +894,12 @@ #define B_MSG_WEAKEN_FIRE 1 // gCaughtMonStringIds -#define B_MSG_SENT_SOMEONES_PC 0 -#define B_MSG_SENT_LANETTES_PC 1 -#define B_MSG_SOMEONES_BOX_FULL 2 -#define B_MSG_LANETTES_BOX_FULL 3 +#define B_MSG_NO_MESSSAGE_SKIP 0 +#define B_MSG_SENT_SOMEONES_PC 1 +#define B_MSG_SENT_LANETTES_PC 2 +#define B_MSG_SOMEONES_BOX_FULL 3 +#define B_MSG_LANETTES_BOX_FULL 4 +#define B_MSG_SWAPPED_INTO_PARTY 5 // gPrimalWeatherBlocksStringIds #define B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN 0 diff --git a/include/constants/party_menu.h b/include/constants/party_menu.h index e997dd566d..76360d8ee8 100644 --- a/include/constants/party_menu.h +++ b/include/constants/party_menu.h @@ -48,7 +48,7 @@ #define PARTY_ACTION_CHOOSE_AND_CLOSE 11 #define PARTY_ACTION_MOVE_TUTOR 12 #define PARTY_ACTION_MINIGAME 13 -#define PARTY_ACTION_REUSABLE_ITEM 14 // Unused. The only reusable items are handled separately +#define PARTY_ACTION_SEND_MON_TO_BOX 14 #define PARTY_ACTION_CHOOSE_FAINTED_MON 15 // IDs for DisplayPartyMenuStdMessage, to display the message at the bottom of the party menu @@ -82,6 +82,8 @@ #define PARTY_MSG_WHICH_APPLIANCE 27 #define PARTY_MSG_CHOOSE_SECOND_FUSION 28 #define PARTY_MSG_NO_POKEMON 29 +#define PARTY_MSG_CHOOSE_MON_FOR_BOX 30 + #define PARTY_MSG_NONE 127 // IDs for DisplayPartyPokemonDescriptionText, to display a message in the party pokemon's box diff --git a/include/naming_screen.h b/include/naming_screen.h index a0cd3cf74b..315868c3ab 100644 --- a/include/naming_screen.h +++ b/include/naming_screen.h @@ -12,6 +12,8 @@ enum { NAMING_SCREEN_CODE, }; +extern void BattleMainCB2(void); + void DoNamingScreen(u8 templateNum, u8 *destBuffer, u16 monSpecies, u16 monGender, u32 monPersonality, MainCallback returnCallback); #endif // GUARD_NAMING_SCREEN_H diff --git a/include/strings.h b/include/strings.h index 9eb678d23e..588d513d4b 100644 --- a/include/strings.h +++ b/include/strings.h @@ -1538,6 +1538,7 @@ extern const u8 gText_PkmnTransferredSomeonesPCBoxFull[]; extern const u8 gText_PkmnTransferredLanettesPCBoxFull[]; extern const u8 gText_PkmnTransferredSomeonesPC[]; extern const u8 gText_PkmnTransferredLanettesPC[]; +extern const u8 gText_PkmnSentToPCAfterCatch[]; // hall of fame extern const u8 gText_LeagueChamp[]; @@ -1571,6 +1572,7 @@ extern const u8 gDaycareText_PlayOther[]; extern const u8 gText_ChoosePokemon[]; extern const u8 gText_ChoosePokemonCancel[]; extern const u8 gText_ChoosePokemonConfirm[]; +extern const u8 gText_SendWhichMonToPC[]; extern const u8 gText_MoveToWhere[]; extern const u8 gText_TeachWhichPokemon[]; extern const u8 gText_UseOnWhichPokemon[]; @@ -2416,4 +2418,7 @@ extern const u8 gText_PlayerScurriedBackHome[]; extern const u8 gText_Relearn[]; // move relearner from summary screen extern const u8 gText_Rename[]; // change nickname from summary screen +// Switch Caught Mon into Party +extern const u8 gText_CannotSendMonToBoxHM[]; + #endif // GUARD_STRINGS_H diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 13b9213b8e..78b7852374 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2174,7 +2174,8 @@ static void PlayerHandleChoosePokemon(u32 battler) gBattlePartyCurrentOrder[i] = gBattleResources->bufferA[battler][4 + i]; if (gBattleTypeFlags & BATTLE_TYPE_ARENA && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CANT_SWITCH - && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CHOOSE_FAINTED_MON) + && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CHOOSE_FAINTED_MON + && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_SEND_MON_TO_BOX) { BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, gBattlerPartyIndexes[battler] + 1, gBattlePartyCurrentOrder); PlayerBufferExecCompleted(battler); diff --git a/src/battle_message.c b/src/battle_message.c index 1538aec1c9..c463474d40 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -891,6 +891,8 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_SUPEREFFECTIVETWOFOES] = COMPOUND_STRING("It's super effective on {B_DEF_NAME_WITH_PREFIX2} and {B_DEF_PARTNER_NAME}!"), [STRINGID_NOTVERYEFFECTIVETWOFOES] = COMPOUND_STRING("It's not very effective on {B_DEF_NAME_WITH_PREFIX2} and {B_DEF_PARTNER_NAME}!"), [STRINGID_ITDOESNTAFFECTTWOFOES] = COMPOUND_STRING("It doesn't affect {B_DEF_NAME_WITH_PREFIX2} and {B_DEF_PARTNER_NAME}…"), + [STRINGID_SENDCAUGHTMONPARTYORBOX] = COMPOUND_STRING("Add {B_DEF_NAME} to your party?"), + [STRINGID_PKMNSENTTOPCAFTERCATCH] = gText_PkmnSentToPCAfterCatch, }; const u16 gTrainerUsedItemStringIds[] = @@ -1361,10 +1363,11 @@ const u16 gFlashFireStringIds[] = const u16 gCaughtMonStringIds[] = { - [B_MSG_SENT_SOMEONES_PC] = STRINGID_PKMNTRANSFERREDSOMEONESPC, - [B_MSG_SENT_LANETTES_PC] = STRINGID_PKMNTRANSFERREDLANETTESPC, - [B_MSG_SOMEONES_BOX_FULL] = STRINGID_PKMNBOXSOMEONESPCFULL, - [B_MSG_LANETTES_BOX_FULL] = STRINGID_PKMNBOXLANETTESPCFULL, + [B_MSG_SENT_SOMEONES_PC] = STRINGID_PKMNTRANSFERREDSOMEONESPC, + [B_MSG_SENT_LANETTES_PC] = STRINGID_PKMNTRANSFERREDLANETTESPC, + [B_MSG_SOMEONES_BOX_FULL] = STRINGID_PKMNBOXSOMEONESPCFULL, + [B_MSG_LANETTES_BOX_FULL] = STRINGID_PKMNBOXLANETTESPCFULL, + [B_MSG_SWAPPED_INTO_PARTY] = STRINGID_PKMNSENTTOPCAFTERCATCH, }; const u16 gRoomsStringIds[] = diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b0fe3281bf..6efa734d10 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -302,6 +302,16 @@ static const u16 sTrappingMoves[NUM_TRAPPING_MOVES] = static const u16 sWhiteOutBadgeMoney[9] = { 8, 16, 24, 36, 48, 64, 80, 100, 120 }; +enum GiveCaughtMonStates +{ + GIVECAUGHTMON_CHECK_PARTY_SIZE, + GIVECAUGHTMON_ASK_ADD_TO_PARTY, + GIVECAUGHTMON_HANDLE_INPUT, + GIVECAUGHTMON_DO_CHOOSE_MON, + GIVECAUGHTMON_HANDLE_CHOSEN_MON, + GIVECAUGHTMON_GIVE_AND_SHOW_MSG, +}; + #define STAT_CHANGE_WORKED 0 #define STAT_CHANGE_DIDNT_WORK 1 @@ -16111,41 +16121,145 @@ static void Cmd_handleballthrow(void) static void Cmd_givecaughtmon(void) { - CMD_ARGS(); + CMD_ARGS(const u8 *passInstr); + enum GiveCaughtMonStates state = gBattleCommunication[MULTIUSE_STATE]; - if (B_RESTORE_HELD_BATTLE_ITEMS >= GEN_9) + switch (state) { - u16 lostItem = gBattleStruct->itemLost[B_SIDE_OPPONENT][gBattlerPartyIndexes[GetCatchingBattler()]].originalItem; - if (lostItem != ITEM_NONE && ItemId_GetPocket(lostItem) != POCKET_BERRIES) - SetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_HELD_ITEM, &lostItem); // Restore non-berry items - } - - if (GiveMonToPlayer(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]]) != MON_GIVEN_TO_PARTY) - { - if (!ShouldShowBoxWasFullMessage()) + case GIVECAUGHTMON_CHECK_PARTY_SIZE: + if (CalculatePlayerPartyCount() == PARTY_SIZE && B_CATCH_SWAP_INTO_PARTY >= GEN_7) { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SENT_SOMEONES_PC; - StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON))); - GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_NICKNAME, gStringVar2); + PrepareStringBattle(STRINGID_SENDCAUGHTMONPARTYORBOX, gBattlerAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_ASK_ADD_TO_PARTY; } else { - StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON))); // box the mon was sent to - GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_NICKNAME, gStringVar2); - StringCopy(gStringVar3, GetBoxNamePtr(GetPCBoxToSendMon())); //box the mon was going to be sent to - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOMEONES_BOX_FULL; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NO_MESSSAGE_SKIP; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + break; + case GIVECAUGHTMON_ASK_ADD_TO_PARTY: + HandleBattleWindow(YESNOBOX_X_Y, 0); + BattlePutTextOnWindow(gText_BattleYesNoChoice, B_WIN_YESNO); + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_HANDLE_INPUT; + gBattleCommunication[CURSOR_POSITION] = 0; + BattleCreateYesNoCursorAt(0); + break; + case GIVECAUGHTMON_HANDLE_INPUT: + if (JOY_NEW(DPAD_UP) && gBattleCommunication[CURSOR_POSITION] != 0) + { + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); + gBattleCommunication[CURSOR_POSITION] = 0; + BattleCreateYesNoCursorAt(0); + } + if (JOY_NEW(DPAD_DOWN) && gBattleCommunication[CURSOR_POSITION] == 0) + { + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); + gBattleCommunication[CURSOR_POSITION] = 1; + BattleCreateYesNoCursorAt(1); + } + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if (gBattleCommunication[CURSOR_POSITION] == 0) + { + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_DO_CHOOSE_MON; + } + else + { + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + break; + case GIVECAUGHTMON_DO_CHOOSE_MON: + if (!gPaletteFade.active) + { + BtlController_EmitChoosePokemon(gBattlerAttacker, BUFFER_A, PARTY_ACTION_SEND_MON_TO_BOX, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gBattlerAttacker]); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_HANDLE_CHOSEN_MON; + } + break; + case GIVECAUGHTMON_HANDLE_CHOSEN_MON: + if (gSelectedMonPartyId != PARTY_SIZE) + { + if (gSelectedMonPartyId > PARTY_SIZE) + { + // Choosing Pokemon was cancelled + gSelectedMonPartyId = PARTY_SIZE; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + else + { + // Mon chosen, try to put it in the PC + if (CopyMonToPC(&gPlayerParty[gSelectedMonPartyId]) == MON_GIVEN_TO_PC) + { + GetMonNickname(&gPlayerParty[gSelectedMonPartyId], gStringVar2); + StringCopy(gStringVar1, GetBoxNamePtr(GetPCBoxToSendMon())); + ZeroMonData(&gPlayerParty[gSelectedMonPartyId]); + gBattleStruct->itemLost[B_SIDE_PLAYER][gSelectedMonPartyId].originalItem = ITEM_NONE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWAPPED_INTO_PARTY; + gSelectedMonPartyId = PARTY_SIZE; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + else + { + gSelectedMonPartyId = PARTY_SIZE; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + } + } + break; + case GIVECAUGHTMON_GIVE_AND_SHOW_MSG: + if (B_RESTORE_HELD_BATTLE_ITEMS >= GEN_9) + { + u16 lostItem = gBattleStruct->itemLost[B_SIDE_OPPONENT][gBattlerPartyIndexes[GetCatchingBattler()]].originalItem; + if (lostItem != ITEM_NONE && ItemId_GetPocket(lostItem) != POCKET_BERRIES) + SetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_HELD_ITEM, &lostItem); // Restore non-berry items } - // Change to B_MSG_SENT_LANETTES_PC or B_MSG_LANETTES_BOX_FULL - if (FlagGet(FLAG_SYS_PC_LANETTE)) - gBattleCommunication[MULTISTRING_CHOOSER]++; + if (GiveMonToPlayer(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]]) != MON_GIVEN_TO_PARTY + && gBattleCommunication[MULTISTRING_CHOOSER] != B_MSG_SWAPPED_INTO_PARTY) + { + if (!ShouldShowBoxWasFullMessage()) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SENT_SOMEONES_PC; + StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON))); + GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_NICKNAME, gStringVar2); + } + else + { + StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON))); // box the mon was sent to + GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_NICKNAME, gStringVar2); + StringCopy(gStringVar3, GetBoxNamePtr(GetPCBoxToSendMon())); //box the mon was going to be sent to + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOMEONES_BOX_FULL; + } + + // Change to B_MSG_SENT_LANETTES_PC or B_MSG_LANETTES_BOX_FULL + if (FlagGet(FLAG_SYS_PC_LANETTE)) + gBattleCommunication[MULTISTRING_CHOOSER]++; + } + + gBattleResults.caughtMonSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_SPECIES, NULL); + GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_NICKNAME, gBattleResults.caughtMonNick); + gBattleResults.caughtMonBall = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_POKEBALL, NULL); + + gSelectedMonPartyId = PARTY_SIZE; + gBattleCommunication[MULTIUSE_STATE] = 0; + + if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_NO_MESSSAGE_SKIP) + gBattlescriptCurrInstr = cmd->passInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; + break; } - - gBattleResults.caughtMonSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_SPECIES, NULL); - GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_NICKNAME, gBattleResults.caughtMonNick); - gBattleResults.caughtMonBall = GetMonData(&gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]], MON_DATA_POKEBALL, NULL); - - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_trysetcaughtmondexflags(void) @@ -16288,7 +16402,7 @@ void BattleDestroyYesNoCursorAt(u8 cursorPosition) static void Cmd_trygivecaughtmonnick(void) { - CMD_ARGS(const u8 *successInstr); + CMD_ARGS(); switch (gBattleCommunication[MULTIUSE_STATE]) { @@ -16343,7 +16457,7 @@ static void Cmd_trygivecaughtmonnick(void) GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_SPECIES), GetMonGender(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]), GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_PERSONALITY, NULL), - BattleMainCB2); + ReshowBattleScreenAfterMenu); gBattleCommunication[MULTIUSE_STATE]++; } @@ -16352,14 +16466,12 @@ static void Cmd_trygivecaughtmonnick(void) if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) { SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_NICKNAME, gBattleStruct->caughtMonNick); - gBattlescriptCurrInstr = cmd->successInstr; + gBattleCommunication[MULTIUSE_STATE]++; } break; case 4: - if (CalculatePlayerPartyCount() == PARTY_SIZE) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->successInstr; + gBattleCommunication[MULTIUSE_STATE] = 0; + gBattlescriptCurrInstr = cmd->nextInstr; break; } } diff --git a/src/data/party_menu.h b/src/data/party_menu.h index 168387dbf4..ec7026fcb5 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -660,6 +660,7 @@ static const u8 *const sActionStringTable[] = [PARTY_MSG_WHICH_APPLIANCE] = gText_WhichAppliance, [PARTY_MSG_CHOOSE_SECOND_FUSION] = gText_NextFusionMon, [PARTY_MSG_NO_POKEMON] = COMPOUND_STRING("You have no POKéMON."), + [PARTY_MSG_CHOOSE_MON_FOR_BOX] = gText_SendWhichMonToPC, }; static const u8 *const sDescriptionStringTable[] = diff --git a/src/naming_screen.c b/src/naming_screen.c index f5f780ed1c..e1307aa658 100644 --- a/src/naming_screen.c +++ b/src/naming_screen.c @@ -672,18 +672,8 @@ static bool8 MainState_PressedOKButton(void) SetInputState(INPUT_STATE_DISABLED); SetCursorFlashing(FALSE); TryStartButtonFlash(BUTTON_COUNT, FALSE, TRUE); - if (sNamingScreen->templateNum == NAMING_SCREEN_CAUGHT_MON - && CalculatePlayerPartyCount() >= PARTY_SIZE) - { - DisplaySentToPCMessage(); - sNamingScreen->state = STATE_WAIT_SENT_TO_PC_MESSAGE; - return FALSE; - } - else - { - sNamingScreen->state = STATE_FADE_OUT; - return TRUE; - } + sNamingScreen->state = STATE_FADE_OUT; + return TRUE; } static bool8 MainState_FadeOut(void) @@ -699,7 +689,11 @@ static bool8 MainState_Exit(void) { if (sNamingScreen->templateNum == NAMING_SCREEN_PLAYER) SeedRngAndSetTrainerId(); - SetMainCallback2(sNamingScreen->returnCallback); + if (sNamingScreen->templateNum == NAMING_SCREEN_CAUGHT_MON + && CalculatePlayerPartyCount() < PARTY_SIZE) + SetMainCallback2(BattleMainCB2); + else + SetMainCallback2(sNamingScreen->returnCallback); DestroyTask(FindTaskIdByFunc(Task_NamingScreen)); FreeAllWindowBuffers(); FREE_AND_SET_NULL(sNamingScreen); @@ -707,7 +701,7 @@ static bool8 MainState_Exit(void) return FALSE; } -static void DisplaySentToPCMessage(void) +static UNUSED void DisplaySentToPCMessage(void) { u8 stringToDisplay = 0; diff --git a/src/party_menu.c b/src/party_menu.c index bda62ba3d1..784f13acdd 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -174,6 +174,14 @@ enum { #define MENU_DIR_RIGHT 2 #define MENU_DIR_LEFT -2 +#define HM_MOVES_END 0xFFFF + +static const u16 sHMMoves[] = +{ + MOVE_CUT, MOVE_FLY, MOVE_SURF, MOVE_STRENGTH, MOVE_FLASH, + MOVE_ROCK_SMASH, MOVE_WATERFALL, MOVE_DIVE, HM_MOVES_END +}; + enum { CAN_LEARN_MOVE, CANNOT_LEARN_MOVE, @@ -320,6 +328,7 @@ static void HandleChooseMonSelection(u8, s8 *); static u16 PartyMenuButtonHandler(s8 *); static s8 *GetCurrentPartySlotPtr(void); static bool8 IsSelectedMonNotEgg(u8 *); +static bool8 DoesSelectedMonKnowHM(u8 *); static void PartyMenuRemoveWindow(u8 *); static void CB2_SetUpExitToBattleScreen(void); static void Task_ClosePartyMenuAfterText(u8); @@ -1524,6 +1533,30 @@ static void HandleChooseMonSelection(u8 taskId, s8 *slotPtr) } break; } + case PARTY_ACTION_SEND_MON_TO_BOX: + { + u8 partyId = GetPartyIdFromBattleSlot((u8)*slotPtr); + if (partyId == 0 || ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && partyId == 2) + || ((gBattleTypeFlags & BATTLE_TYPE_MULTI) && partyId >= (PARTY_SIZE / 2))) + { + // Can't select if mon is currently on the field, or doesn't belong to you + PlaySE(SE_FAILURE); + } + else if (DoesSelectedMonKnowHM((u8 *)slotPtr)) + { + PlaySE(SE_FAILURE); + DisplayPartyMenuMessage(gText_CannotSendMonToBoxHM, FALSE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = Task_ReturnToChooseMonAfterText; + } + else + { + PlaySE(SE_SELECT); + gSelectedMonPartyId = partyId; + Task_ClosePartyMenu(taskId); + } + break; + } default: case PARTY_ACTION_ABILITY_PREVENTS: case PARTY_ACTION_SWITCHING: @@ -1544,6 +1577,25 @@ static bool8 IsSelectedMonNotEgg(u8 *slotPtr) return TRUE; } +static bool8 DoesSelectedMonKnowHM(u8 *slotPtr) +{ + if (B_CATCH_SWAP_CHECK_HMS == FALSE) + return FALSE; + + for (u32 i = 0; i < MAX_MON_MOVES; i++) + { + u32 j = 0; + u16 move = GetMonData(&gPlayerParty[*slotPtr], MON_DATA_MOVE1 + i); + + while (sHMMoves[j] != HM_MOVES_END) + { + if (sHMMoves[j++] == move) + return TRUE; + } + } + return FALSE; +} + static void HandleChooseMonCancel(u8 taskId, s8 *slotPtr) { switch (gPartyMenu.action) @@ -1561,6 +1613,11 @@ static void HandleChooseMonCancel(u8 taskId, s8 *slotPtr) PlaySE(SE_SELECT); CancelParticipationPrompt(taskId); break; + case PARTY_ACTION_SEND_MON_TO_BOX: + PlaySE(SE_SELECT); + gSelectedMonPartyId = PARTY_SIZE + 1; + Task_ClosePartyMenu(taskId); + break; default: PlaySE(SE_SELECT); if (DisplayCancelChooseMonYesNo(taskId) != TRUE) @@ -1924,7 +1981,10 @@ static void Task_ReturnToChooseMonAfterText(u8 taskId) } else { - DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON); + if (gPartyMenu.action == PARTY_ACTION_SEND_MON_TO_BOX) + DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON_FOR_BOX); + else + DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON); gTasks[taskId].func = Task_HandleChooseMonInput; } } @@ -4665,8 +4725,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task) if (!IsItemFlute(item)) { PlaySE(SE_USE_ITEM); - if (gPartyMenu.action != PARTY_ACTION_REUSABLE_ITEM) - RemoveBagItem(item, 1); + RemoveBagItem(item, 1); } else { @@ -7124,7 +7183,14 @@ static u8 GetPartyLayoutFromBattleType(void) void OpenPartyMenuInBattle(u8 partyAction) { - InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), partyAction, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_SetUpReshowBattleScreenAfterMenu); + u8 partyMessage; + + if (partyAction == PARTY_ACTION_SEND_MON_TO_BOX) + partyMessage = PARTY_MSG_CHOOSE_MON_FOR_BOX; + else + partyMessage = PARTY_MSG_CHOOSE_MON; + + InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), partyAction, FALSE, partyMessage, Task_HandleChooseMonInput, CB2_SetUpReshowBattleScreenAfterMenu); ReshowBattleScreenDummy(); UpdatePartyToBattleOrder(); } diff --git a/src/strings.c b/src/strings.c index 37feea0da0..c112db4616 100644 --- a/src/strings.c +++ b/src/strings.c @@ -319,6 +319,7 @@ const u8 gText_CurrentIsTooFast[] = _("The current is much too fast!"); const u8 gText_DoWhatWithMail[] = _("Do what with the MAIL?"); const u8 gText_ChoosePokemonCancel[] = _("Choose POKéMON or CANCEL."); const u8 gText_ChoosePokemonConfirm[] = _("Choose POKéMON and confirm."); +const u8 gText_SendWhichMonToPC[] = _("Send which POKéMON to the PC?"); const u8 gText_EnjoyCycling[] = _("Let's enjoy cycling!"); const u8 gText_InUseAlready_PM[] = _("This is in use already."); const u8 gText_AlreadyHoldingOne[] = _("{STR_VAR_1} is already holding\none {STR_VAR_2}."); @@ -1293,3 +1294,4 @@ const u8 gText_AM[] = _("AM"); const u8 gText_PM[] = _("PM"); const u8 gText_Relearn[] = _("{START_BUTTON} RELEARN"); // future note: don't decap this, because it mimics the summary screen BG graphics which will not get decapped const u8 gText_Rename[] = _("RENAME"); +const u8 gText_CannotSendMonToBoxHM[] = _("Cannot send that mon to the box,\nbecause it knows a HM move.{PAUSE_UNTIL_PRESS}");