diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index c4bfea9a5f..b524104a36 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2465,6 +2465,12 @@ 1: .endm + .macro jumpifabilitycantbesuppressed battler:req, jumpInstr:req + callnative BS_JumpIfAbilityCantBeSuppressed + .byte \battler + .4byte \jumpInstr + .endm + .macro setallytonexttarget jumpInstr:req jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f addbyte gBattlerTarget, 0x2 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e7e494008a..a10dfaa40c 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -9520,9 +9520,12 @@ BattleScript_NeutralizingGasExits:: setbyte gBattlerAttacker, 0 BattleScript_NeutralizingGasExitsLoop: copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 + jumpifabilitycantbesuppressed BS_TARGET, BattleScript_NeutralizingGasExitsLoopIncrement + jumpifability BS_TARGET, ABILITY_IMPOSTER, BattleScript_NeutralizingGasExitsLoopIncrement @ Imposter only activates when first entering the field saveattacker switchinabilities BS_TARGET restoreattacker +BattleScript_NeutralizingGasExitsLoopIncrement: addbyte gBattlerAttacker, 1 jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_NeutralizingGasExitsLoop restoreattacker diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4e6109e93b..bd2ef1509e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7653,7 +7653,7 @@ static void Cmd_switchindataupdate(void) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif @@ -16542,6 +16542,9 @@ static void Cmd_tryworryseed(void) } else { + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_INSOMNIA; gBattlescriptCurrInstr = cmd->nextInstr; @@ -18742,3 +18745,14 @@ void BS_JumpIfNoWhiteOut(void) else gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_JumpIfAbilityCantBeSuppressed(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/battle_util.c b/src/battle_util.c index 715f8bb3da..ebb11c4c7f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3505,7 +3505,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 u32 diagonalBattler = BATTLE_OPPOSITE(battler); if (IsDoubleBattle()) diagonalBattler = BATTLE_PARTNER(diagonalBattler); - if (IsBattlerAlive(diagonalBattler) + + // Imposter only activates when the battler first switches in + if (gDisableStructs[battler].isFirstTurn == 2 + && !gDisableStructs[battler].overwrittenAbility + && IsBattlerAlive(diagonalBattler) && !(gBattleMons[diagonalBattler].status2 & (STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE)) && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && gBattleStruct->illusion[diagonalBattler].state != ILLUSION_ON diff --git a/test/battle/ability/neutralizing_gas.c b/test/battle/ability/neutralizing_gas.c index 6338bfbeca..f83e928c4a 100644 --- a/test/battle/ability/neutralizing_gas.c +++ b/test/battle/ability/neutralizing_gas.c @@ -256,7 +256,8 @@ SINGLE_BATTLE_TEST("Neutralizing Gas prevents Trace from copying it") SINGLE_BATTLE_TEST("Neutralizing Gas prevents Contrary inverting stat boosts") { GIVEN { - ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST); + ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2); + ASSUME(GetMoveEffect(MOVE_LEER) == EFFECT_DEFENSE_DOWN); PLAYER(SPECIES_INKAY) { Ability(ABILITY_CONTRARY); } OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } } WHEN { @@ -271,3 +272,41 @@ SINGLE_BATTLE_TEST("Neutralizing Gas prevents Contrary inverting stat boosts") EXPECT_LT(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); } } + +SINGLE_BATTLE_TEST("Neutralizing Gas exiting the field does not activate abilities that were not suppressed by it again") +{ + u32 species, ability; + // These are the only abilities that could immediately activate again + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + + GIVEN { + ASSUME(gAbilitiesInfo[ability].cantBeSuppressed); + PLAYER(species) { Ability(ability); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(opponent, 1); } + } SCENE { + ABILITY_POPUP(player, ability); + MESSAGE("The effects of the neutralizing gas wore off!"); + NOT ABILITY_POPUP(player, ability); + } +} + +SINGLE_BATTLE_TEST("Neutralizing Gas exiting the field does not activate Imposter even if it did not activate before") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_DITTO) { Ability(ABILITY_IMPOSTER); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(player, 1); SWITCH(opponent, 1); } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_IMPOSTER); + MESSAGE("The effects of the neutralizing gas wore off!"); + NOT ABILITY_POPUP(player, ABILITY_IMPOSTER); + } +}