diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e4e980276..8f11d1d67 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7803,7 +7803,7 @@ BattleScript_AnnounceAirLockCloudNine:: end3 BattleScript_RedCardActivates:: - jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_RedCardEnd + jumpifcantswitch BS_ATTACKER, BattleScript_RedCardEnd playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_REDCARDACTIVATE waitmessage 0x40 @@ -7829,3 +7829,24 @@ BattleScript_RedCardSuctionCups: swapattackerwithtarget return +BattleScript_EjectButtonActivates:: + jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd + makevisible BS_ATTACKER + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL + printstring STRINGID_EJECTBUTTONACTIVATE + waitmessage 0x40 + removeitem BS_SCRIPTING + openpartyscreen BS_SCRIPTING, BattleScript_EjectButtonEnd + switchoutabilities BS_SCRIPTING + waitstate + switchhandleorder BS_SCRIPTING 0x2 + returntoball BS_SCRIPTING + getswitchedmondata BS_SCRIPTING + switchindataupdate BS_SCRIPTING + hpthresholds BS_SCRIPTING + printstring 0x3 + switchinanim BS_SCRIPTING 0x1 + waitstate + switchineffects BS_SCRIPTING +BattleScript_EjectButtonEnd: + return diff --git a/include/battle_ai_script_commands.h b/include/battle_ai_script_commands.h index be3787398..dc5459cab 100644 --- a/include/battle_ai_script_commands.h +++ b/include/battle_ai_script_commands.h @@ -23,5 +23,6 @@ void RecordAbilityBattle(u8 battlerId, u16 abilityId); void ClearBattlerAbilityHistory(u8 battlerId); void RecordItemEffectBattle(u8 battlerId, u8 itemEffect); void ClearBattlerItemEffectHistory(u8 battlerId); +s32 CountUsablePartyMons(u8 battlerId); #endif // GUARD_BATTLE_AI_SCRIPT_COMMANDS_H diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 2c5134ade..88ffe3505 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -353,5 +353,6 @@ extern const u8 BattleScript_CheekPouchActivates[]; extern const u8 BattleScript_AnnounceAirLockCloudNine[]; extern const u8 BattleScript_AttackerItemStatRaise[]; extern const u8 BattleScript_RedCardActivates[]; +extern const u8 BattleScript_EjectButtonActivates[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 76ac13940..a634e7f77 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -559,8 +559,9 @@ #define STRINGID_COMATOSEENTERS 555 #define STRINGID_SCREENCLEANERENTERS 556 #define STRINGID_REDCARDACTIVATE 557 +#define STRINGID_EJECTBUTTONACTIVATE 558 -#define BATTLESTRINGS_COUNT 558 +#define BATTLESTRINGS_COUNT 559 //// multichoice message IDs // switch in ability message diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c index 8a5f423a4..93a5e33db 100644 --- a/src/battle_ai_script_commands.c +++ b/src/battle_ai_script_commands.c @@ -54,7 +54,6 @@ static void RecordLastUsedMoveByTarget(void); static void BattleAI_DoAIProcessing(void); static void AIStackPushVar(const u8 *); static bool8 AIStackPop(void); -static s32 CountUsablePartyMons(u8 battlerId); static s32 AI_GetAbility(u32 battlerId, bool32 guess); static void Cmd_if_random_less_than(void); @@ -1614,7 +1613,7 @@ static void Cmd_nullsub_2B(void) { } -static s32 CountUsablePartyMons(u8 battlerId) +s32 CountUsablePartyMons(u8 battlerId) { s32 battlerOnField1, battlerOnField2, i, ret; struct Pokemon *party; diff --git a/src/battle_message.c b/src/battle_message.c index 4a35e2939..f52c30cca 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -686,9 +686,11 @@ static const u8 sText_AuraBreakActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} static const u8 sText_ComatoseActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is drowsing!"); static const u8 sText_ScreenCleanerActivates[] = _("All screens on the field were\ncleansed!"); static const u8 sText_RedCardActivate[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} held up its {B_LAST_ITEM}\nagainst {B_ATK_NAME_WITH_PREFIX}!"); +static const u8 sText_EjectButtonActivate[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is switched\nout with the {B_LAST_ITEM}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_EJECTBUTTONACTIVATE - 12] = sText_EjectButtonActivate, [STRINGID_REDCARDACTIVATE - 12] = sText_RedCardActivate, [STRINGID_STATWASNOTLOWERED - 12] = sText_StatWasNotLowered, [STRINGID_CLOAKEDINAFREEZINGLIGHT - 12] = sText_CloakedInAFreezingLight, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a5e959d9b..0c72c581d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5010,6 +5010,36 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_EJECT_BUTTON: + if (gCurrentMove != MOVE_DRAGON_TAIL + && gCurrentMove != MOVE_CIRCLE_THROW + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && IsBattlerAlive(gBattlerAttacker) + && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove) + && (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER || (gBattleTypeFlags & BATTLE_TYPE_TRAINER))) + { + u8 battlers[4] = {0, 1, 2, 3}; + SortBattlersBySpeed(battlers, FALSE); + for (i = 0; i < gBattlersCount; i++) + { + u8 battler = battlers[i]; + // attacker is the damage-dealer, battler is mon to be switched out + if (IsBattlerAlive(battler) + && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_EJECT_BUTTON + && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) + && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) + && CountUsablePartyMons(battler) > 0) + { + gActiveBattler = gBattleScripting.battler = battler; + gLastUsedItem = gBattleMons[battler].item; + if (gBattleMoves[gCurrentMove].effect == EFFECT_HIT_ESCAPE) + gBattlescriptCurrInstr = BattleScript_MoveEnd; // prevent user switch-in selection + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EjectButtonActivates; + effect = TRUE; + break; // only the fastest Eject Button activates + } + } + } gBattleScripting.moveendState++; break; case MOVEEND_RED_CARD: @@ -5030,7 +5060,8 @@ static void Cmd_moveend(void) && IsBattlerAlive(battler) && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RED_CARD - && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0)) + && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) + && CountUsablePartyMons(battler) > 0) { gLastUsedItem = gBattleMons[battler].item; gActiveBattler = gBattleScripting.battler = battler; // battler with red card