Fix Instruct Missing Checks for Focus Punch, Beak Blast, Shell Trap, and Sky Drop (#9152)

This commit is contained in:
GGbond 2026-02-10 03:26:14 +08:00 committed by GitHub
parent ac7e45351d
commit abeb86837a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 82 additions and 27 deletions

View File

@ -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)

View File

@ -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); }

View File

@ -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 {