Fix substitute/defog interactions (#8418)

This commit is contained in:
FosterProgramming 2025-12-04 15:24:53 +01:00 committed by GitHub
parent 142a5ef08c
commit f3d43e286d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 96 additions and 11 deletions

View File

@ -1493,12 +1493,17 @@ BattleScript_EffectHitEnemyHealAlly::
BattleScript_EffectDefog::
setstatchanger STAT_EVASION, 1, TRUE
attackcanceler
jumpifgenconfiglowerthan CONFIG_DEFOG_EFFECT_CLEARING, GEN_5, BattleScript_DefogAfterSubstituteCheck
jumpifsubstituteblocks BattleScript_DefogIfCanClearHazards
BattleScript_DefogAfterSubstituteCheck:
jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_EVASION, MIN_STAT_STAGE, BattleScript_DefogWorks
BattleScript_DefogIfCanClearHazards:
trydefog FALSE, BattleScript_ButItFailed
BattleScript_DefogWorks:
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
jumpifgenconfiglowerthan CONFIG_DEFOG_EFFECT_CLEARING, GEN_5, BattleScript_DefogWorksAfterSubstituteCheck
jumpifsubstituteblocks BattleScript_DefogTryHazardsWithAnim
BattleScript_DefogWorksAfterSubstituteCheck:
statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_DefogTryHazardsWithAnim
jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefogDoAnim
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_DefogTryHazardsWithAnim
@ -1508,7 +1513,9 @@ BattleScript_DefogWorks:
BattleScript_DefogDoAnim::
attackanimation
waitanimation
call BattleScript_SwapFromSubstitute
statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_DefogTryHazards
call BattleScript_SwapToSubstitute
BattleScript_DefogPrintString::
printfromtable gStatDownStringIds
waitmessage B_WAIT_TIME_LONG

View File

@ -111,7 +111,7 @@
#define B_BURN_HIT_THAW GEN_LATEST // In Gen6+, damaging moves with a chance of burn will thaw the target, regardless if they're fire-type moves or not.
#define B_HEALING_WISH_SWITCH GEN_LATEST // In Gen5+, the mon receiving Healing Wish is sent out at the end of the turn.
// Additionally, in gen8+ the Healing Wish's effect will be stored until the user switches into a statused or hurt mon.
#define B_DEFOG_EFFECT_CLEARING GEN_LATEST // In Gen6+, Defog clears Spikes, Toxic Spikes, Stealth Rock and Sticky Web from both sides. In Gen8+, Defog also clears active Terrain.
#define B_DEFOG_EFFECT_CLEARING GEN_LATEST // In Gen5+, Defog does not lower Evasion of target behind Subsitute. In Gen6+, Defog clears Spikes, Toxic Spikes, Stealth Rock and Sticky Web from both sides. In Gen8+, Defog also clears active Terrain.
#define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp. Defense stats. Once Spit Up / Swallow is used, these stat changes are lost.
#define B_TRANSFORM_SHINY GEN_LATEST // In Gen4+, Transform will copy the shiny state of the opponent instead of maintaining its own shiny state.
#define B_TRANSFORM_FORM_CHANGES GEN_LATEST // In Gen5+, Transformed Pokemon cannot change forms.

View File

@ -557,6 +557,7 @@ static bool8 ShouldAnimBeDoneRegardlessOfSubstitute(u8 animId)
case B_ANIM_SNOW_CONTINUES:
case B_ANIM_FOG_CONTINUES:
case B_ANIM_SNATCH_MOVE:
case B_ANIM_STATS_CHANGE:
return TRUE;
default:
return FALSE;

View File

@ -9392,14 +9392,20 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear)
}
if (gBattleWeather & B_WEATHER_FOG)
{
gBattleWeather &= ~B_WEATHER_FOG;
BattleScriptCall(BattleScript_FogEnded_Ret);
if (clear)
{
gBattleWeather &= ~B_WEATHER_FOG;
BattleScriptCall(BattleScript_FogEnded_Ret);
}
return TRUE;
}
if (GetConfig(CONFIG_DEFOG_EFFECT_CLEARING) >= GEN_8 && (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY))
{
RemoveAllTerrains();
BattleScriptCall(BattleScript_TerrainEnds_Ret);
if (clear)
{
RemoveAllTerrains();
BattleScriptCall(BattleScript_TerrainEnds_Ret);
}
return TRUE;
}
}

View File

@ -34,20 +34,92 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 stage")
}
}
SINGLE_BATTLE_TEST("Defog does not lower evasiveness if target behind Substitute")
SINGLE_BATTLE_TEST("Defog fails if target has minimum evasion stat change")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) {Ability(ABILITY_SIMPLE);};
} WHEN {
TURN { MOVE(player, MOVE_DEFOG); }
TURN { MOVE(player, MOVE_DEFOG); }
TURN { MOVE(player, MOVE_DEFOG); }
TURN { MOVE(player, MOVE_DEFOG); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's evasiveness harshly fell!");
MESSAGE("But it failed!");
}
}
SINGLE_BATTLE_TEST("Defog lowers evasiveness of target behind Substitute (Gen4-)")
{
GIVEN {
WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, GEN_4);
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
} WHEN {
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_DEFOG); }
} SCENE {
MESSAGE("The opposing Wobbuffet used Substitute!");
NOT MESSAGE("But it failed!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's evasiveness fell!");
}
}
SINGLE_BATTLE_TEST("Defog fails if target has minimum evasion stat change behind Substitute (Gen4-)")
{
GIVEN {
WITH_CONFIG(CONFIG_DEFOG_EFFECT_CLEARING, GEN_4);
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); Ability(ABILITY_SIMPLE);}
} WHEN {
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_DEFOG); }
TURN { MOVE(player, MOVE_DEFOG); }
TURN { MOVE(player, MOVE_DEFOG); }
TURN { MOVE(player, MOVE_DEFOG); }
} SCENE {
MESSAGE("The opposing Wobbuffet used Substitute!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's evasiveness harshly fell!");
MESSAGE("But it failed!");
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's evasiveness fell!");
}
}
SINGLE_BATTLE_TEST("Defog does not lower evasiveness if target behind Substitute (Gen5+)")
{
u32 move;
PARAMETRIZE { move = MOVE_LIGHT_SCREEN; }
PARAMETRIZE { move = MOVE_CELEBRATE; }
GIVEN {
ASSUME(CONFIG_DEFOG_EFFECT_CLEARING >= GEN_5);
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
} WHEN {
TURN { MOVE(opponent, move); }
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_DEFOG); }
} SCENE {
MESSAGE("The opposing Wobbuffet used Substitute!");
if (move == MOVE_CELEBRATE)
{
MESSAGE("But it failed!");
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's evasiveness fell!");
}
}
else
{
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's evasiveness fell!");
}
}
}
}
@ -423,7 +495,6 @@ SINGLE_BATTLE_TEST("Defog is used on the correct side if opposing mon is behind
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent);
MESSAGE("Wobbuffet used Defog!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, player);
MESSAGE("The opposing Wobbuffet's evasiveness fell!");
MESSAGE("The opposing team's Light Screen wore off!");
}
}