From 81a73deb767e31756504c1426357faf5a566457c Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:40:35 +0200 Subject: [PATCH] Fixes Quash (#4419) * Fixes Quash * Update test/battle/move_effect/quash.c Co-authored-by: Bassoonian * Update test/battle/move_effect/quash.c Co-authored-by: Bassoonian --------- Co-authored-by: Bassoonian --- asm/macros/battle_script.inc | 10 +- include/constants/battle_script_commands.h | 213 ++++++++++----------- src/battle_script_commands.c | 47 +++-- test/battle/move_effect/quash.c | 45 +++++ 4 files changed, 189 insertions(+), 126 deletions(-) create mode 100644 test/battle/move_effect/quash.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 25e0110a51..260257fc61 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1636,6 +1636,11 @@ callnative BS_TryGulpMissile .endm + .macro tryquash failInstr:req + callnative BS_TryQuash + .4byte \failInstr + .endm + @ various command changed to more readable macros .macro cancelmultiturnmoves battler:req various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES @@ -1827,11 +1832,6 @@ various \battler, VARIOUS_SET_LAST_USED_ABILITY .endm - .macro tryquash failInstr:req - various BS_ATTACKER, VARIOUS_TRY_QUASH - .4byte \failInstr - .endm - .macro tryafteryou failInstr:req various BS_ATTACKER, VARIOUS_AFTER_YOU .4byte \failInstr diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 641e644ebc..ef8803ce42 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -131,113 +131,112 @@ #define VARIOUS_SET_SIMPLE_BEAM 39 #define VARIOUS_TRY_ENTRAINMENT 40 #define VARIOUS_SET_LAST_USED_ABILITY 41 -#define VARIOUS_TRY_QUASH 42 -#define VARIOUS_INVERT_STAT_STAGES 43 -#define VARIOUS_TRY_ME_FIRST 44 -#define VARIOUS_JUMP_IF_BATTLE_END 45 -#define VARIOUS_TRY_ELECTRIFY 46 -#define VARIOUS_TRY_REFLECT_TYPE 47 -#define VARIOUS_TRY_SOAK 48 -#define VARIOUS_HANDLE_MEGA_EVO 49 -#define VARIOUS_TRY_LAST_RESORT 50 -#define VARIOUS_SET_ARG_TO_BATTLE_DAMAGE 51 -#define VARIOUS_TRY_HIT_SWITCH_TARGET 52 -#define VARIOUS_TRY_AUTOTOMIZE 53 -#define VARIOUS_ABILITY_POPUP 54 -#define VARIOUS_JUMP_IF_TARGET_ALLY 55 -#define VARIOUS_TRY_SYNCHRONOISE 56 -#define VARIOUS_PSYCHO_SHIFT 57 -#define VARIOUS_CURE_STATUS 58 -#define VARIOUS_POWER_TRICK 59 -#define VARIOUS_AFTER_YOU 60 -#define VARIOUS_BESTOW 61 -#define VARIOUS_JUMP_IF_NOT_GROUNDED 62 -#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 63 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 64 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 65 -#define VARIOUS_SET_AURORA_VEIL 66 -#define VARIOUS_TRY_THIRD_TYPE 67 -#define VARIOUS_ACUPRESSURE 68 -#define VARIOUS_SET_POWDER 69 -#define VARIOUS_SPECTRAL_THIEF 70 -#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 71 -#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 72 -#define VARIOUS_JUMP_IF_ROAR_FAILS 73 -#define VARIOUS_TRY_INSTRUCT 74 -#define VARIOUS_JUMP_IF_NOT_BERRY 75 -#define VARIOUS_TRACE_ABILITY 76 -#define VARIOUS_UPDATE_NICK 77 -#define VARIOUS_TRY_ILLUSION_OFF 78 -#define VARIOUS_SET_SPRITEIGNORE0HP 79 -#define VARIOUS_HANDLE_FORM_CHANGE 80 -#define VARIOUS_GET_STAT_VALUE 81 -#define VARIOUS_JUMP_IF_FULL_HP 82 -#define VARIOUS_LOSE_TYPE 83 -#define VARIOUS_TRY_ACTIVATE_SOULHEART 84 -#define VARIOUS_TRY_ACTIVATE_RECEIVER 85 -#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 86 -#define VARIOUS_TRY_FRISK 87 -#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 88 -#define VARIOUS_TRY_FAIRY_LOCK 89 -#define VARIOUS_JUMP_IF_NO_ALLY 90 -#define VARIOUS_POISON_TYPE_IMMUNITY 91 -#define VARIOUS_JUMP_IF_HOLD_EFFECT 92 -#define VARIOUS_INFATUATE_WITH_BATTLER 93 -#define VARIOUS_SET_LAST_USED_ITEM 94 -#define VARIOUS_PARALYZE_TYPE_IMMUNITY 95 -#define VARIOUS_JUMP_IF_ABSENT 96 -#define VARIOUS_DESTROY_ABILITY_POPUP 97 -#define VARIOUS_TOTEM_BOOST 98 -#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 99 -#define VARIOUS_MOVEEND_ITEM_EFFECTS 100 -#define VARIOUS_TERRAIN_SEED 101 -#define VARIOUS_MAKE_INVISIBLE 102 -#define VARIOUS_ROOM_SERVICE 103 -#define VARIOUS_EERIE_SPELL_PP_REDUCE 104 -#define VARIOUS_JUMP_IF_TEAM_HEALTHY 105 -#define VARIOUS_TRY_HEAL_QUARTER_HP 106 -#define VARIOUS_REMOVE_TERRAIN 107 -#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 108 -#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 109 -#define VARIOUS_GET_ROTOTILLER_TARGETS 110 -#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 111 -#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 112 -#define VARIOUS_CONSUME_BERRY 113 -#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 114 -#define VARIOUS_JUMP_IF_SPECIES 115 -#define VARIOUS_UPDATE_ABILITY_POPUP 116 -#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 117 -#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 118 -#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 119 -#define VARIOUS_SHELL_SIDE_ARM_CHECK 120 -#define VARIOUS_TRY_NO_RETREAT 121 -#define VARIOUS_TRY_TAR_SHOT 122 -#define VARIOUS_CAN_TAR_SHOT_WORK 123 -#define VARIOUS_CHECK_POLTERGEIST 124 -#define VARIOUS_CUT_1_3_HP_RAISE_STATS 125 -#define VARIOUS_TRY_END_NEUTRALIZING_GAS 126 -#define VARIOUS_JUMP_IF_UNDER_200 127 -#define VARIOUS_SET_SKY_DROP 128 -#define VARIOUS_CLEAR_SKY_DROP 129 -#define VARIOUS_SKY_DROP_YAWN 130 -#define VARIOUS_CURE_CERTAIN_STATUSES 131 -#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 132 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 133 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 134 -#define VARIOUS_SAVE_BATTLER_ITEM 135 -#define VARIOUS_RESTORE_BATTLER_ITEM 136 -#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 137 -#define VARIOUS_SET_BEAK_BLAST 138 -#define VARIOUS_SWAP_SIDE_STATUSES 139 -#define VARIOUS_SWAP_STATS 140 -#define VARIOUS_TEATIME_INVUL 141 -#define VARIOUS_TEATIME_TARGETS 142 -#define VARIOUS_TRY_WIND_RIDER_POWER 143 -#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 144 -#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 145 -#define VARIOUS_STORE_HEALING_WISH 146 -#define VARIOUS_HIT_SWITCH_TARGET_FAILED 147 -#define VARIOUS_TRY_REVIVAL_BLESSING 148 +#define VARIOUS_INVERT_STAT_STAGES 42 +#define VARIOUS_TRY_ME_FIRST 43 +#define VARIOUS_JUMP_IF_BATTLE_END 44 +#define VARIOUS_TRY_ELECTRIFY 45 +#define VARIOUS_TRY_REFLECT_TYPE 46 +#define VARIOUS_TRY_SOAK 47 +#define VARIOUS_HANDLE_MEGA_EVO 48 +#define VARIOUS_TRY_LAST_RESORT 49 +#define VARIOUS_SET_ARG_TO_BATTLE_DAMAGE 50 +#define VARIOUS_TRY_HIT_SWITCH_TARGET 51 +#define VARIOUS_TRY_AUTOTOMIZE 52 +#define VARIOUS_ABILITY_POPUP 53 +#define VARIOUS_JUMP_IF_TARGET_ALLY 54 +#define VARIOUS_TRY_SYNCHRONOISE 55 +#define VARIOUS_PSYCHO_SHIFT 56 +#define VARIOUS_CURE_STATUS 57 +#define VARIOUS_POWER_TRICK 58 +#define VARIOUS_AFTER_YOU 59 +#define VARIOUS_BESTOW 60 +#define VARIOUS_JUMP_IF_NOT_GROUNDED 61 +#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 62 +#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 63 +#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 64 +#define VARIOUS_SET_AURORA_VEIL 65 +#define VARIOUS_TRY_THIRD_TYPE 66 +#define VARIOUS_ACUPRESSURE 67 +#define VARIOUS_SET_POWDER 68 +#define VARIOUS_SPECTRAL_THIEF 69 +#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 70 +#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 71 +#define VARIOUS_JUMP_IF_ROAR_FAILS 72 +#define VARIOUS_TRY_INSTRUCT 73 +#define VARIOUS_JUMP_IF_NOT_BERRY 74 +#define VARIOUS_TRACE_ABILITY 75 +#define VARIOUS_UPDATE_NICK 76 +#define VARIOUS_TRY_ILLUSION_OFF 77 +#define VARIOUS_SET_SPRITEIGNORE0HP 78 +#define VARIOUS_HANDLE_FORM_CHANGE 79 +#define VARIOUS_GET_STAT_VALUE 80 +#define VARIOUS_JUMP_IF_FULL_HP 81 +#define VARIOUS_LOSE_TYPE 82 +#define VARIOUS_TRY_ACTIVATE_SOULHEART 83 +#define VARIOUS_TRY_ACTIVATE_RECEIVER 84 +#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 85 +#define VARIOUS_TRY_FRISK 86 +#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 87 +#define VARIOUS_TRY_FAIRY_LOCK 88 +#define VARIOUS_JUMP_IF_NO_ALLY 89 +#define VARIOUS_POISON_TYPE_IMMUNITY 90 +#define VARIOUS_JUMP_IF_HOLD_EFFECT 91 +#define VARIOUS_INFATUATE_WITH_BATTLER 92 +#define VARIOUS_SET_LAST_USED_ITEM 93 +#define VARIOUS_PARALYZE_TYPE_IMMUNITY 94 +#define VARIOUS_JUMP_IF_ABSENT 95 +#define VARIOUS_DESTROY_ABILITY_POPUP 96 +#define VARIOUS_TOTEM_BOOST 97 +#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 98 +#define VARIOUS_MOVEEND_ITEM_EFFECTS 99 +#define VARIOUS_TERRAIN_SEED 100 +#define VARIOUS_MAKE_INVISIBLE 101 +#define VARIOUS_ROOM_SERVICE 102 +#define VARIOUS_EERIE_SPELL_PP_REDUCE 103 +#define VARIOUS_JUMP_IF_TEAM_HEALTHY 104 +#define VARIOUS_TRY_HEAL_QUARTER_HP 105 +#define VARIOUS_REMOVE_TERRAIN 106 +#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 107 +#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 108 +#define VARIOUS_GET_ROTOTILLER_TARGETS 109 +#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 110 +#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 111 +#define VARIOUS_CONSUME_BERRY 112 +#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 113 +#define VARIOUS_JUMP_IF_SPECIES 114 +#define VARIOUS_UPDATE_ABILITY_POPUP 115 +#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 116 +#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 117 +#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 118 +#define VARIOUS_SHELL_SIDE_ARM_CHECK 119 +#define VARIOUS_TRY_NO_RETREAT 120 +#define VARIOUS_TRY_TAR_SHOT 121 +#define VARIOUS_CAN_TAR_SHOT_WORK 122 +#define VARIOUS_CHECK_POLTERGEIST 123 +#define VARIOUS_CUT_1_3_HP_RAISE_STATS 124 +#define VARIOUS_TRY_END_NEUTRALIZING_GAS 125 +#define VARIOUS_JUMP_IF_UNDER_200 126 +#define VARIOUS_SET_SKY_DROP 127 +#define VARIOUS_CLEAR_SKY_DROP 128 +#define VARIOUS_SKY_DROP_YAWN 129 +#define VARIOUS_CURE_CERTAIN_STATUSES 130 +#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 131 +#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 132 +#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 133 +#define VARIOUS_SAVE_BATTLER_ITEM 134 +#define VARIOUS_RESTORE_BATTLER_ITEM 135 +#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 136 +#define VARIOUS_SET_BEAK_BLAST 137 +#define VARIOUS_SWAP_SIDE_STATUSES 138 +#define VARIOUS_SWAP_STATS 139 +#define VARIOUS_TEATIME_INVUL 140 +#define VARIOUS_TEATIME_TARGETS 141 +#define VARIOUS_TRY_WIND_RIDER_POWER 142 +#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 143 +#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 144 +#define VARIOUS_STORE_HEALING_WISH 145 +#define VARIOUS_HIT_SWITCH_TARGET_FAILED 146 +#define VARIOUS_TRY_REVIVAL_BLESSING 147 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d91f1d35d2..28d75cd161 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9585,20 +9585,6 @@ static void Cmd_various(void) gLastUsedAbility = gBattleMons[battler].ability; break; } - case VARIOUS_TRY_QUASH: - { - VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) // It's true if foe is faster, has a bigger priority, or switches - { - gBattlescriptCurrInstr = cmd->failInstr; // This replaces the current battlescript with the "fail" script. - } - else // If the condition is not true, it means we are faster than the foe, so we can set the quash bit - { - gProtectStructs[gBattlerTarget].quash = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; // and then we proceed with the rest of our battlescript - } - return; - } case VARIOUS_INVERT_STAT_STAGES: { VARIOUS_ARGS(); @@ -16839,3 +16825,36 @@ void BS_TryGulpMissile(void) else gBattlescriptCurrInstr = cmd->nextInstr; } + + +void BS_TryQuash(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u32 i; + + // It's true if foe is faster, has a bigger priority, or switches + if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) + { + gBattlescriptCurrInstr = cmd->failInstr; + return; + } + + // If the above condition is not true, it means we are faster than the foe, so we can set the quash bit + gProtectStructs[gBattlerTarget].quash = TRUE; + for (i = 0; i < gBattlersCount; i++) + { + gBattlerByTurnOrder[i] = i; + } + for (i = 0; i < gBattlersCount - 1; i++) + { + s32 j; + for (j = i + 1; j < gBattlersCount; j++) + { + if (!gProtectStructs[i].quash + && !gProtectStructs[j].quash + && GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1) + SwapTurnOrder(i, j); + } + } + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/test/battle/move_effect/quash.c b/test/battle/move_effect/quash.c new file mode 100644 index 0000000000..fd2bd9d877 --- /dev/null +++ b/test/battle/move_effect/quash.c @@ -0,0 +1,45 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_QUASH].effect == EFFECT_QUASH); +} + +DOUBLE_BATTLE_TEST("Quash-affected target will move last in the priority bracket") +{ + GIVEN { + PLAYER(SPECIES_VOLBEAT) { Speed(10); Ability(ABILITY_PRANKSTER); } + PLAYER(SPECIES_WOBBUFFET) { Speed(30); } + OPPONENT(SPECIES_TORCHIC) { Speed(20); } + OPPONENT(SPECIES_TREECKO) { Speed(40); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_QUASH, target: opponentRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_QUASH, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); + } +} + +DOUBLE_BATTLE_TEST("Quash is not affected by dynamic speed") +{ + GIVEN { + ASSUME(B_RECALC_TURN_AFTER_ACTIONS >= GEN_8); + ASSUME(gMovesInfo[MOVE_TAILWIND].effect == EFFECT_TAILWIND); + PLAYER(SPECIES_VOLBEAT) { Speed(10); Ability(ABILITY_PRANKSTER); } + PLAYER(SPECIES_WOBBUFFET) { Speed(30); } + OPPONENT(SPECIES_TORCHIC) { Speed(50); } + OPPONENT(SPECIES_TREECKO) { Speed(40); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_QUASH, target: opponentRight); + MOVE(opponentLeft, MOVE_TAILWIND); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_QUASH, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); + } +}