diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 9d4f679208..8819c8afad 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1136,6 +1136,19 @@ static inline bool32 IsBattlerUsingBeakBlast(u32 battler) return !HasBattlerActedThisTurn(battler); } +static inline bool32 IsInstructBannedChargingMove(u32 battler) +{ + enum BattleMoveEffects moveEffect; + + if (gChosenActionByBattler[battler] != B_ACTION_USE_MOVE || HasBattlerActedThisTurn(battler)) + return FALSE; + + moveEffect = GetMoveEffect(gChosenMoveByBattler[battler]); + return moveEffect == EFFECT_FOCUS_PUNCH + || moveEffect == EFFECT_BEAK_BLAST + || moveEffect == EFFECT_SHELL_TRAP; +} + static void Cmd_attackcanceler(void) { CMD_ARGS(); @@ -17379,6 +17392,9 @@ void BS_TryInstruct(void) u16 move = gLastPrintedMoves[gBattlerTarget]; if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || MoveHasAdditionalEffectSelf(move, MOVE_EFFECT_RECHARGE) || IsMoveInstructBanned(move) + || IsInstructBannedChargingMove(gBattlerTarget) + || gBattleMons[gBattlerTarget].volatiles.bideTurns != 0 + || gBattleMons[gBattlerTarget].volatiles.semiInvulnerable == STATE_SKY_DROP || gBattleMoveEffects[GetMoveEffect(move)].twoTurnEffect || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) || IsZMove(move) diff --git a/test/battle/move_effect/beak_blast.c b/test/battle/move_effect/beak_blast.c index 4cbea8a596..5a9d43df71 100644 --- a/test/battle/move_effect/beak_blast.c +++ b/test/battle/move_effect/beak_blast.c @@ -144,6 +144,7 @@ SINGLE_BATTLE_TEST("Beak Blast doesn't burn fire types") { GIVEN { ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_ARCANINE].types[1] == TYPE_FIRE); + ASSUME(MoveMakesContact(MOVE_SCRATCH)); PLAYER(SPECIES_ARCANINE); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -159,6 +160,7 @@ SINGLE_BATTLE_TEST("Beak Blast doesn't burn after being used") { GIVEN { ASSUME(GetMovePriority(MOVE_COUNTER) < GetMovePriority(MOVE_BEAK_BLAST)); + ASSUME(MoveMakesContact(MOVE_COUNTER)); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -169,44 +171,29 @@ SINGLE_BATTLE_TEST("Beak Blast doesn't burn after being used") } } -DOUBLE_BATTLE_TEST("Beak Blast doesn't burn if the target is protected") +DOUBLE_BATTLE_TEST("Beak Blast doesn't burn if the target is protected by Mat Block") { - u32 move; - - PARAMETRIZE { move = MOVE_SPIKY_SHIELD; } - PARAMETRIZE { move = MOVE_BANEFUL_BUNKER; } - PARAMETRIZE { move = MOVE_BURNING_BULWARK; } - PARAMETRIZE { move = MOVE_SILK_TRAP; } - GIVEN { - ASSUME(GetMoveEffect(move) == EFFECT_PROTECT); - ASSUME(GetMoveEffect(MOVE_INSTRUCT) == EFFECT_INSTRUCT); - ASSUME(GetMovePriority(MOVE_BEAK_BLAST) > GetMovePriority(MOVE_TRICK_ROOM)); + ASSUME(GetMoveEffect(MOVE_MAT_BLOCK) == EFFECT_MAT_BLOCK); + ASSUME(GetMoveProtectMethod(MOVE_MAT_BLOCK) == PROTECT_MAT_BLOCK); + ASSUME(MoveMakesContact(MOVE_POUND)); PLAYER(SPECIES_WOBBUFFET) { Speed(1); } PLAYER(SPECIES_WYNAUT) { Speed(2); } OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } OPPONENT(SPECIES_WYNAUT) { Speed(10); } } WHEN { - TURN { MOVE(opponentLeft, move); } - TURN { MOVE(opponentRight, MOVE_INSTRUCT, target: opponentLeft, WITH_RNG(RNG_PROTECT_FAIL, 0)); - MOVE(opponentLeft, MOVE_BEAK_BLAST, target: playerLeft); - MOVE(playerRight, MOVE_TRICK_ROOM); - MOVE(playerLeft, MOVE_POUND, target: opponentLeft); } + TURN { + MOVE(opponentRight, MOVE_MAT_BLOCK); + MOVE(opponentLeft, MOVE_BEAK_BLAST, target: playerLeft); + MOVE(playerLeft, MOVE_POUND, target: opponentLeft); + } } SCENE { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_BEAK_BLAST_SETUP, opponentLeft); - ANIMATION(ANIM_TYPE_MOVE, MOVE_INSTRUCT, opponentRight); - ANIMATION(ANIM_TYPE_MOVE, move, opponentLeft); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft); - if (move == MOVE_SPIKY_SHIELD) { - HP_BAR(playerLeft); - } else if (move == MOVE_BANEFUL_BUNKER) { - STATUS_ICON(playerLeft, STATUS1_POISON); - } else if (move == MOVE_BURNING_BULWARK) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAT_BLOCK, opponentRight); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft); STATUS_ICON(playerLeft, STATUS1_BURN); - } else if (move == MOVE_SILK_TRAP) { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); } - NOT STATUS_ICON(playerLeft, STATUS1_BURN); } } @@ -216,6 +203,7 @@ DOUBLE_BATTLE_TEST("Beak Blast doesn't burn if the target is protected by Quick ASSUME(GetMoveEffect(MOVE_QUICK_GUARD) == EFFECT_PROTECT); ASSUME(GetMoveProtectMethod(MOVE_QUICK_GUARD) == PROTECT_QUICK_GUARD); ASSUME(GetMovePriority(MOVE_QUICK_ATTACK) > 0); + ASSUME(MoveMakesContact(MOVE_QUICK_ATTACK)); PLAYER(SPECIES_WOBBUFFET) { Speed(1); } PLAYER(SPECIES_WYNAUT) { Speed(2); } OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } diff --git a/test/battle/move_effect/instruct.c b/test/battle/move_effect/instruct.c index b0bd715ddd..9bb4eab9de 100644 --- a/test/battle/move_effect/instruct.c +++ b/test/battle/move_effect/instruct.c @@ -52,6 +52,57 @@ DOUBLE_BATTLE_TEST("Instruct fails if move is banned by Instruct") } } +TO_DO_BATTLE_TEST("Instruct fails if target is in the middle of Bide"); + +DOUBLE_BATTLE_TEST("Instruct fails if target is preparing Focus Punch, Beak Blast or Shell Trap") +{ + u32 move, Anim; + PARAMETRIZE { move = MOVE_FOCUS_PUNCH; Anim = B_ANIM_FOCUS_PUNCH_SETUP; } + PARAMETRIZE { move = MOVE_BEAK_BLAST; Anim = B_ANIM_BEAK_BLAST_SETUP; } + PARAMETRIZE { move = MOVE_SHELL_TRAP; Anim = B_ANIM_SHELL_TRAP_SETUP; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_FOCUS_PUNCH) == EFFECT_FOCUS_PUNCH); + ASSUME(GetMoveEffect(MOVE_BEAK_BLAST) == EFFECT_BEAK_BLAST); + ASSUME(GetMoveEffect(MOVE_SHELL_TRAP) == EFFECT_SHELL_TRAP); + PLAYER(SPECIES_WOBBUFFET) { Speed(4); Moves(MOVE_INSTRUCT, MOVE_CELEBRATE); } + PLAYER(SPECIES_WOBBUFFET) { Speed(3); Moves(MOVE_POUND, move); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + } WHEN { + TURN { MOVE(playerRight, MOVE_POUND, target: opponentLeft); } + TURN { + if (move == MOVE_SHELL_TRAP) + MOVE(playerRight, move); + else + MOVE(playerRight, move, target: opponentLeft); + MOVE(playerLeft, MOVE_INSTRUCT, target: playerRight); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight); + ANIMATION(ANIM_TYPE_GENERAL, Anim, playerRight); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_INSTRUCT, playerLeft); + } +} + +DOUBLE_BATTLE_TEST("Instruct fails if target is picked up by Sky Drop even if one of the battlers has No Guard") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_SKY_DROP) == EFFECT_SKY_DROP); + PLAYER(SPECIES_WOBBUFFET) { Speed(3); Moves(MOVE_INSTRUCT, MOVE_CELEBRATE); } + PLAYER(SPECIES_MACHAMP) { Speed(2); Ability(ABILITY_NO_GUARD); Moves(MOVE_SCRATCH, MOVE_CELEBRATE); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(4); Moves(MOVE_SKY_DROP, MOVE_CELEBRATE); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_CELEBRATE); MOVE(playerRight, MOVE_SCRATCH, target: opponentLeft); } + TURN { MOVE(opponentLeft, MOVE_SKY_DROP, target: playerRight); MOVE(playerLeft, MOVE_INSTRUCT, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, opponentLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_INSTRUCT, playerLeft); + } +} + DOUBLE_BATTLE_TEST("Instruct-called move targets the target of the move picked on its last use") { GIVEN {