From 1e6a533131b97e20bb06c7541d1732db6e954a74 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 3 Sep 2025 13:23:23 -0400 Subject: [PATCH 1/2] Fix most failed tests with `GEN_LATEST` = `GEN_7` (#7688) --- asm/macros/battle_script.inc | 7 ++++ data/battle_scripts_1.s | 23 +++++++------ include/constants/generational_changes.h | 5 +++ include/generational_changes.h | 5 +++ src/battle_ai_util.c | 2 +- src/battle_script_commands.c | 17 +++++++--- src/battle_util.c | 6 ++-- test/battle/ability/disguise.c | 21 +++++++++++- test/battle/ability/inner_focus.c | 33 ++++++++++++++++-- test/battle/ability/oblivious.c | 24 +++++++++++-- test/battle/ability/own_tempo.c | 22 ++++++++++-- test/battle/ability/rattled.c | 24 +++++++++++-- test/battle/ability/scrappy.c | 34 +++++++++++++++++-- test/battle/ability/sheer_force.c | 3 +- test/battle/ability/shield_dust.c | 6 ++-- test/battle/ai/ai_calc_best_move_score.c | 9 +++-- test/battle/ai/ai_switching.c | 3 +- test/battle/hold_effect/covert_cloak.c | 6 ++-- test/battle/move_effect/after_you.c | 27 ++++++++++++++- test/battle/move_effect/attack_up_user_ally.c | 9 +++-- test/battle/move_effect/healing_wish.c | 26 +++++++++++--- test/battle/move_effect/pursuit.c | 1 + test/battle/move_effect/quash.c | 4 +-- test/battle/move_effect/rage_fist.c | 31 ++++++++++++++++- test/battle/move_effect/tailwind.c | 22 ++++++++++-- test/battle/move_effect/teleport.c | 29 ++++++++++++++-- 26 files changed, 339 insertions(+), 60 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 4a332f5b43..a689c8a94d 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2524,3 +2524,10 @@ callnative BS_TryBoosterEnergy .byte \onFieldStatus .endm + + .macro jumpifgenconfiglowerthan tag:req, gen:req, jumpInstr:req + callnative BS_JumpIfGenConfigLowerThan + .2byte \tag + .byte \gen + .4byte \jumpInstr + .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f066f52ae8..8851a6a8c7 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -14,6 +14,7 @@ #include "constants/game_stat.h" #include "constants/trainers.h" #include "constants/species.h" +#include "constants/generational_changes.h" .include "asm/macros.inc" .include "asm/macros/battle_script.inc" .include "constants/constants.inc" @@ -2278,7 +2279,11 @@ BattleScript_EffectHealingWish:: setatkhptozero tryfaintmon BS_ATTACKER storehealingwish BS_ATTACKER -.if B_HEALING_WISH_SWITCH <= GEN_4 + jumpifgenconfiglowerthan GEN_CONFIG_HEALING_WISH_SWITCH, GEN_5, BattleScript_EffectHealingWishGen4 +BattleScript_EffectHealingWishEnd: + moveendall + end +BattleScript_EffectHealingWishGen4: openpartyscreen BS_ATTACKER, BattleScript_EffectHealingWishEnd waitstate switchhandleorder BS_ATTACKER, 2 @@ -2292,10 +2297,7 @@ BattleScript_EffectHealingWish:: switchinanim BS_ATTACKER, FALSE, TRUE waitstate switchineffects BS_ATTACKER -.endif -BattleScript_EffectHealingWishEnd: - moveendall - end + goto BattleScript_EffectHealingWishEnd BattleScript_HealingWishActivates:: setbyte cMULTISTRING_CHOOSER, 0 @@ -4222,12 +4224,13 @@ BattleScript_EffectFutureSight:: goto BattleScript_MoveEnd BattleScript_EffectTeleport:: -.if B_TELEPORT_BEHAVIOR >= GEN_8 + jumpifgenconfiglowerthan GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8, BattleScript_EffectTeleportGen7 jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_EffectBatonPass jumpifside BS_ATTACKER, B_SIDE_PLAYER, BattleScript_EffectBatonPass -.else + goto BattleScript_DoEffectTeleport +BattleScript_EffectTeleportGen7:: jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_FailedFromAtkCanceler -.endif +BattleScript_DoEffectTeleport:: attackcanceler attackstring ppreduce @@ -6573,10 +6576,10 @@ BattleScript_CudChewActivates:: end3 BattleScript_ApplyDisguiseFormChangeHPLoss:: -.if B_DISGUISE_HP_LOSS >= GEN_8 + jumpifgenconfiglowerthan GEN_CONFIG_DISGUISE_HP_LOSS, GEN_8, BattleScript_ApplyDisguiseFormChangeHPLossReturn healthbarupdate BS_SCRIPTING datahpupdate BS_SCRIPTING -.endif +BattleScript_ApplyDisguiseFormChangeHPLossReturn: return BattleScript_TargetFormChangeNoPopup: diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 83c9caa203..0478240320 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -30,6 +30,11 @@ enum GenConfigTag GEN_ALLY_SWITCH_FAIL_CHANCE, GEN_DREAM_EATER_LIQUID_OOZE, GEN_CONFIG_TRANSISTOR_BOOST, + GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, + GEN_CONFIG_UPDATED_INTIMIDATE, + GEN_CONFIG_DISGUISE_HP_LOSS, + GEN_CONFIG_AFTER_YOU_TURN_ORDER, + GEN_CONFIG_HEALING_WISH_SWITCH, GEN_CONFIG_COUNT }; diff --git a/include/generational_changes.h b/include/generational_changes.h index a6f3a56ef7..c3667d1af5 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -33,6 +33,11 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_ALLY_SWITCH_FAIL_CHANCE] = B_ALLY_SWITCH_FAIL_CHANCE, [GEN_DREAM_EATER_LIQUID_OOZE] = B_DREAM_EATER_LIQUID_OOZE, [GEN_CONFIG_TRANSISTOR_BOOST] = B_TRANSISTOR_BOOST, + [GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS] = B_RECALC_TURN_AFTER_ACTIONS, + [GEN_CONFIG_UPDATED_INTIMIDATE] = B_UPDATED_INTIMIDATE, + [GEN_CONFIG_DISGUISE_HP_LOSS] = B_DISGUISE_HP_LOSS, + [GEN_CONFIG_AFTER_YOU_TURN_ORDER] = B_AFTER_YOU_TURN_ORDER, + [GEN_CONFIG_HEALING_WISH_SWITCH] = B_HEALING_WISH_SWITCH, }; #if TESTING diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 84d247a617..6bf1245922 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2769,7 +2769,7 @@ bool32 IsSwitchOutEffect(enum BattleMoveEffects effect) switch (effect) { case EFFECT_TELEPORT: - if (B_TELEPORT_BEHAVIOR >= GEN_8) + if (GetGenConfig(GEN_CONFIG_TELEPORT_BEHAVIOR) >= GEN_8) return TRUE; case EFFECT_HIT_ESCAPE: case EFFECT_PARTING_SHOT: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6845e760f4..f271bc4c28 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2358,7 +2358,7 @@ static void Cmd_datahpupdate(void) gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED_TOTEM; else gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED; - if (B_DISGUISE_HP_LOSS >= GEN_8) + if (GetGenConfig(GEN_CONFIG_DISGUISE_HP_LOSS) >= GEN_8) gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; BattleScriptPush(cmd->nextInstr); gBattlescriptCurrInstr = BattleScript_TargetFormChange; @@ -7756,7 +7756,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) // Healing Wish activates before hazards. // Starting from Gen8 - it heals only pokemon which can be healed. In gens 5,6,7 the effect activates anyways. else if ((gBattleStruct->battlerState[battler].storedHealingWish || gBattleStruct->battlerState[battler].storedLunarDance) - && (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1 != 0 || B_HEALING_WISH_SWITCH < GEN_8)) + && (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1 != 0 || GetGenConfig(GEN_CONFIG_HEALING_WISH_SWITCH) < GEN_8)) { gBattlerAttacker = battler; if (gBattleStruct->battlerState[battler].storedHealingWish) @@ -9453,7 +9453,7 @@ static bool32 ChangeOrderTargetAfterAttacker(void) if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) return FALSE; if (GetBattlerTurnOrderNum(gBattlerAttacker) + 1 == GetBattlerTurnOrderNum(gBattlerTarget)) - return B_AFTER_YOU_TURN_ORDER >= GEN_8; + return GetGenConfig(GEN_CONFIG_AFTER_YOU_TURN_ORDER) >= GEN_8; for (i = 0; i < MAX_BATTLERS_COUNT; i++) { @@ -16562,7 +16562,7 @@ void BS_JumpIfIntimidateAbilityPrevented(void) case ABILITY_SCRAPPY: case ABILITY_OWN_TEMPO: case ABILITY_OBLIVIOUS: - if (B_UPDATED_INTIMIDATE >= GEN_8) + if (GetGenConfig(GEN_CONFIG_UPDATED_INTIMIDATE) >= GEN_8) { hasAbility = TRUE; gBattlescriptCurrInstr = BattleScript_IntimidatePrevented; @@ -18347,3 +18347,12 @@ void BS_BattlerItemToLastUsedItem(void) gBattleMons[gBattlerTarget].item = gLastUsedItem; gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_JumpIfGenConfigLowerThan(void) +{ + NATIVE_ARGS(u16 tag, u8 gen, const u8 *jumpInstr); + if (GetGenConfig(cmd->tag) < cmd->gen) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/battle_util.c b/src/battle_util.c index de7cec8d58..16b335e701 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -919,7 +919,7 @@ void HandleAction_ActionFinished(void) gBattleResources->battleScriptsStack->size = 0; gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE; - if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet()) + if (GetGenConfig(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS) >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet()) { // i starts at `gCurrentTurnActionNumber` because we don't want to recalculate turn order for mon that have already // taken action. It's been previously increased, which we want in order to not recalculate the turn of the mon that just finished its action @@ -1201,7 +1201,9 @@ void PrepareStringBattle(enum StringID stringId, u32 battler) else SET_STATCHANGER(STAT_SPATK, 2, FALSE); } - else if (B_UPDATED_INTIMIDATE >= GEN_8 && stringId == STRINGID_PKMNCUTSATTACKWITH && targetAbility == ABILITY_RATTLED + else if (GetGenConfig(GEN_CONFIG_UPDATED_INTIMIDATE) >= GEN_8 + && stringId == STRINGID_PKMNCUTSATTACKWITH + && targetAbility == ABILITY_RATTLED && CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) { gBattlerAbility = gBattlerTarget; diff --git a/test/battle/ability/disguise.c b/test/battle/ability/disguise.c index ef00c1fe93..0d73fdf9ae 100644 --- a/test/battle/ability/disguise.c +++ b/test/battle/ability/disguise.c @@ -6,11 +6,30 @@ ASSUMPTIONS ASSUME(GetMoveCategory(MOVE_AERIAL_ACE) == DAMAGE_CATEGORY_PHYSICAL); } -SINGLE_BATTLE_TEST("Disguised Mimikyu will lose 1/8 of its max HP upon changing to its busted form") +SINGLE_BATTLE_TEST("Disguised Mimikyu doesn't lose 1/8 of its max HP upon changing to its busted form (Gen7)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_DISGUISE_HP_LOSS, GEN_7); + PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_AERIAL_ACE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AERIAL_ACE, opponent); + NOT HP_BAR(player); + ABILITY_POPUP(player, ABILITY_DISGUISE); + } THEN { + EXPECT_EQ(player->species, SPECIES_MIMIKYU_BUSTED); + EXPECT_EQ(player->hp, player->maxHP); + } +} + +SINGLE_BATTLE_TEST("Disguised Mimikyu will lose 1/8 of its max HP upon changing to its busted form (Gen8+)") { s16 disguiseDamage; GIVEN { + WITH_CONFIG(GEN_CONFIG_DISGUISE_HP_LOSS, GEN_8); PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ability/inner_focus.c b/test/battle/ability/inner_focus.c index e6370f019a..75c7c113d0 100644 --- a/test/battle/ability/inner_focus.c +++ b/test/battle/ability/inner_focus.c @@ -1,13 +1,40 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Inner Focus prevents intimidate") +SINGLE_BATTLE_TEST("Inner Focus doesn't prevent intimidate (Gen3-7)") { s16 turnOneHit; s16 turnTwoHit; GIVEN { - ASSUME(B_UPDATED_INTIMIDATE >= GEN_8); + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }; + } WHEN { + TURN { MOVE(opponent, MOVE_SCRATCH); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_SCRATCH); } + + } SCENE { + // Turn 1 + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Ekans's Intimidate cuts the opposing Zubat's Attack!"); + // Turn 2 + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_GT(turnOneHit, turnTwoHit); + } +} + +SINGLE_BATTLE_TEST("Inner Focus prevents intimidate (Gen8+)") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; OPPONENT(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }; @@ -18,7 +45,7 @@ SINGLE_BATTLE_TEST("Inner Focus prevents intimidate") } SCENE { HP_BAR(player, captureDamage: &turnOneHit); ABILITY_POPUP(player, ABILITY_INTIMIDATE); - NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); } ABILITY_POPUP(opponent, ABILITY_INNER_FOCUS); MESSAGE("The opposing Zubat's Inner Focus prevents stat loss!"); HP_BAR(player, captureDamage: &turnTwoHit); diff --git a/test/battle/ability/oblivious.c b/test/battle/ability/oblivious.c index a787ec6578..40506e1967 100644 --- a/test/battle/ability/oblivious.c +++ b/test/battle/ability/oblivious.c @@ -50,10 +50,30 @@ SINGLE_BATTLE_TEST("Oblivious prevents Taunt") } } -SINGLE_BATTLE_TEST("Oblivious prevents Intimidate") +SINGLE_BATTLE_TEST("Oblivious doesn't prevent Intimidate (Gen3-7)") { GIVEN { - ASSUME(B_UPDATED_INTIMIDATE >= GEN_8); + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); + PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OBLIVIOUS); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { SWITCH(opponent, 1); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); + NONE_OF { + ABILITY_POPUP(player, ABILITY_OBLIVIOUS); + MESSAGE("Slowpoke's Oblivious prevents stat loss!"); + } + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("The opposing Ekans's Intimidate cuts Slowpoke's Attack!"); + } +} + +SINGLE_BATTLE_TEST("Oblivious prevents Intimidate (Gen8+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OBLIVIOUS); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } diff --git a/test/battle/ability/own_tempo.c b/test/battle/ability/own_tempo.c index ef358a172e..bbd709c57b 100644 --- a/test/battle/ability/own_tempo.c +++ b/test/battle/ability/own_tempo.c @@ -1,10 +1,28 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Own Tempo prevents Intimidate but no other stat down changes") +SINGLE_BATTLE_TEST("Own Tempo doesn't prevent Intimidate (Gen3-7)") { GIVEN { - ASSUME(B_UPDATED_INTIMIDATE >= GEN_8); + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); + ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE); + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }; + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_OWN_TEMPO); + MESSAGE("The opposing Slowpoke's Own Tempo prevents stat loss!"); + } + } +} + +SINGLE_BATTLE_TEST("Own Tempo prevents Intimidate but no other stat down changes (Gen8+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE); PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }; diff --git a/test/battle/ability/rattled.c b/test/battle/ability/rattled.c index d957dec66a..a2cc61536e 100644 --- a/test/battle/ability/rattled.c +++ b/test/battle/ability/rattled.c @@ -52,10 +52,30 @@ SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when hit by Bug, Dark or Ghost typ } } -SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when affected by Intimidate") +SINGLE_BATTLE_TEST("Rattled does not boost speed by 1 when affected by Intimidate (Gen5-7)") { GIVEN { - ASSUME(B_UPDATED_INTIMIDATE >= GEN_8); + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); + PLAYER(SPECIES_GYARADOS) {Ability(ABILITY_INTIMIDATE); } + OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); } + } WHEN { + TURN {} + } SCENE { + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Gyarados's Intimidate cuts the opposing Sudowoodo's Attack!"); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_RATTLED); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Sudowoodo's Speed rose!"); + } + } +} + +SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when affected by Intimidate (Gen8+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); PLAYER(SPECIES_GYARADOS) {Ability(ABILITY_INTIMIDATE); } OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); } } WHEN { diff --git a/test/battle/ability/scrappy.c b/test/battle/ability/scrappy.c index 919ee486b9..9476f93926 100644 --- a/test/battle/ability/scrappy.c +++ b/test/battle/ability/scrappy.c @@ -1,13 +1,13 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Scrappy prevents intimidate") +SINGLE_BATTLE_TEST("Scrappy doesn't prevent Intimidate (Gen4-7)") { s16 turnOneHit; s16 turnTwoHit; GIVEN { - ASSUME(B_UPDATED_INTIMIDATE >= GEN_8); + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_7); PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); }; @@ -18,7 +18,35 @@ SINGLE_BATTLE_TEST("Scrappy prevents intimidate") } SCENE { HP_BAR(player, captureDamage: &turnOneHit); ABILITY_POPUP(player, ABILITY_INTIMIDATE); - NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_SCRAPPY); + MESSAGE("The opposing Kangaskhan's Scrappy prevents stat loss!"); + } + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_GT(turnOneHit, turnTwoHit); + } +} + +SINGLE_BATTLE_TEST("Scrappy prevents Intimidate (Gen8+)") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + WITH_CONFIG(GEN_CONFIG_UPDATED_INTIMIDATE, GEN_8); + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); }; + } WHEN { + TURN { MOVE(opponent, MOVE_SCRATCH); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_SCRATCH); } + + } SCENE { + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); } ABILITY_POPUP(opponent, ABILITY_SCRAPPY); MESSAGE("The opposing Kangaskhan's Scrappy prevents stat loss!"); HP_BAR(player, captureDamage: &turnTwoHit); diff --git a/test/battle/ability/sheer_force.c b/test/battle/ability/sheer_force.c index 8e99361296..d14d53571d 100644 --- a/test/battle/ability/sheer_force.c +++ b/test/battle/ability/sheer_force.c @@ -567,7 +567,6 @@ static inline bool32 IsMoveSheerForceBoosted(u32 move) case MOVE_POWDER_SNOW: case MOVE_PSYSHIELD_BASH: case MOVE_PYRO_BALL: - case MOVE_RAPID_SPIN: case MOVE_RELIC_SONG: case MOVE_ROLLING_KICK: case MOVE_SACRED_FIRE: @@ -605,6 +604,8 @@ static inline bool32 IsMoveSheerForceBoosted(u32 move) case MOVE_ELECTRO_SHOT: case MOVE_PSYCHIC_NOISE: return TRUE; + case MOVE_RAPID_SPIN: + return B_SPEED_BUFFING_RAPID_SPIN >= GEN_8; } return FALSE; } diff --git a/test/battle/ability/shield_dust.c b/test/battle/ability/shield_dust.c index 828e596525..2d7358335d 100644 --- a/test/battle/ability/shield_dust.c +++ b/test/battle/ability/shield_dust.c @@ -88,12 +88,12 @@ SINGLE_BATTLE_TEST("Shield Dust does not block self-targeting effects, primary o { u16 move; PARAMETRIZE { move = MOVE_POWER_UP_PUNCH; } - PARAMETRIZE { move = MOVE_RAPID_SPIN; } + PARAMETRIZE { move = MOVE_FLAME_CHARGE; } PARAMETRIZE { move = MOVE_LEAF_STORM; } PARAMETRIZE { move = MOVE_METEOR_ASSAULT; } GIVEN { - ASSUME(GetMoveEffect(MOVE_RAPID_SPIN) == EFFECT_RAPID_SPIN); + ASSUME(MoveHasAdditionalEffectSelf(MOVE_FLAME_CHARGE, MOVE_EFFECT_SPD_PLUS_1) == TRUE); ASSUME(MoveHasAdditionalEffectSelf(MOVE_POWER_UP_PUNCH, MOVE_EFFECT_ATK_PLUS_1) == TRUE); ASSUME(MoveHasAdditionalEffectSelf(MOVE_LEAF_STORM, MOVE_EFFECT_SP_ATK_MINUS_2) == TRUE); ASSUME(MoveHasAdditionalEffectSelf(MOVE_METEOR_ASSAULT, MOVE_EFFECT_RECHARGE) == TRUE); @@ -110,7 +110,7 @@ SINGLE_BATTLE_TEST("Shield Dust does not block self-targeting effects, primary o switch (move) { case MOVE_POWER_UP_PUNCH: - case MOVE_RAPID_SPIN: + case MOVE_FLAME_CHARGE: case MOVE_LEAF_STORM: ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); break; diff --git a/test/battle/ai/ai_calc_best_move_score.c b/test/battle/ai/ai_calc_best_move_score.c index a4a13c283f..cfad45a0aa 100644 --- a/test/battle/ai/ai_calc_best_move_score.c +++ b/test/battle/ai/ai_calc_best_move_score.c @@ -11,7 +11,8 @@ AI_SINGLE_BATTLE_TEST("AI will not further increase Attack / Sp. Atk stat if it GIVEN { ASSUME(GetMovePower(MOVE_SKY_UPPERCUT) == 85); - ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); + ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP + || GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); ASSUME(GetMoveEffect(MOVE_CALM_MIND) == EFFECT_CALM_MIND); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_COMBUSKEN) { Speed(15); Moves(MOVE_SKY_UPPERCUT, MOVE_CELEBRATE); }; @@ -31,7 +32,8 @@ AI_SINGLE_BATTLE_TEST("AI will not further increase Attack / Sp. Atk stat if it GIVEN { ASSUME(GetMovePower(MOVE_SKY_UPPERCUT) == 85); - ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); + ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP + || GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); ASSUME(GetMoveEffect(MOVE_CALM_MIND) == EFFECT_CALM_MIND); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_COMBUSKEN) { Speed(20); Moves(MOVE_DOUBLE_KICK, MOVE_CELEBRATE); }; @@ -63,7 +65,8 @@ AI_SINGLE_BATTLE_TEST("AI will not waste a turn setting up if it knows target ca GIVEN { ASSUME(GetMovePower(MOVE_SKY_UPPERCUT) == 85); - ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); + ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP + || GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); ASSUME(GetMoveEffect(MOVE_CALM_MIND) == EFFECT_CALM_MIND); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); PLAYER(SPECIES_COMBUSKEN) { Speed(15); Moves(MOVE_SKY_UPPERCUT, MOVE_DOUBLE_KICK, MOVE_FLAME_WHEEL, MOVE_CELEBRATE); }; diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 8db6fa9479..a0532a5df3 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -839,10 +839,9 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has an PARAMETRIZE { aiMon = SPECIES_BRONZONG; absorbingAbility = ABILITY_LEVITATE; move = MOVE_EARTHQUAKE;} PARAMETRIZE { aiMon = SPECIES_ELECTRODE; absorbingAbility = ABILITY_SOUNDPROOF; move = MOVE_HYPER_VOICE;} PARAMETRIZE { aiMon = SPECIES_CHESNAUGHT; absorbingAbility = ABILITY_BULLETPROOF; move = MOVE_SLUDGE_BOMB;} - PARAMETRIZE { aiMon = SPECIES_SHIFTRY; absorbingAbility = ABILITY_WIND_RIDER; move = MOVE_HURRICANE;} + PARAMETRIZE { aiMon = SPECIES_BRAMBLEGHAST; absorbingAbility = ABILITY_WIND_RIDER; move = MOVE_HURRICANE;} GIVEN { ASSUME(B_REDIRECT_ABILITY_IMMUNITY >= GEN_5); - ASSUME(P_UPDATED_ABILITIES >= GEN_9); //For the predicted ability for Shiftry AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); PLAYER(SPECIES_ZIGZAGOON) { Moves(move); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); } diff --git a/test/battle/hold_effect/covert_cloak.c b/test/battle/hold_effect/covert_cloak.c index 0b3d0c2ed6..64f75703cc 100644 --- a/test/battle/hold_effect/covert_cloak.c +++ b/test/battle/hold_effect/covert_cloak.c @@ -92,12 +92,12 @@ SINGLE_BATTLE_TEST("Covert Cloak does not block self-targeting effects, primary { u16 move; PARAMETRIZE { move = MOVE_POWER_UP_PUNCH; } - PARAMETRIZE { move = MOVE_RAPID_SPIN; } + PARAMETRIZE { move = MOVE_FLAME_CHARGE; } PARAMETRIZE { move = MOVE_LEAF_STORM; } PARAMETRIZE { move = MOVE_METEOR_ASSAULT; } GIVEN { - ASSUME(GetMoveEffect(MOVE_RAPID_SPIN) == EFFECT_RAPID_SPIN); + ASSUME(MoveHasAdditionalEffectSelf(MOVE_FLAME_CHARGE, MOVE_EFFECT_SPD_PLUS_1) == TRUE); ASSUME(MoveHasAdditionalEffectSelf(MOVE_POWER_UP_PUNCH, MOVE_EFFECT_ATK_PLUS_1) == TRUE); ASSUME(MoveHasAdditionalEffectSelf(MOVE_LEAF_STORM, MOVE_EFFECT_SP_ATK_MINUS_2) == TRUE); ASSUME(MoveHasAdditionalEffectSelf(MOVE_METEOR_ASSAULT, MOVE_EFFECT_RECHARGE) == TRUE); @@ -113,7 +113,7 @@ SINGLE_BATTLE_TEST("Covert Cloak does not block self-targeting effects, primary HP_BAR(opponent); switch (move) { case MOVE_POWER_UP_PUNCH: - case MOVE_RAPID_SPIN: + case MOVE_FLAME_CHARGE: case MOVE_LEAF_STORM: ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); break; diff --git a/test/battle/move_effect/after_you.c b/test/battle/move_effect/after_you.c index 222b94c7b6..9d0464f72a 100644 --- a/test/battle/move_effect/after_you.c +++ b/test/battle/move_effect/after_you.c @@ -86,10 +86,35 @@ DOUBLE_BATTLE_TEST("After You calculates correct turn order if only one Pokémon } } +DOUBLE_BATTLE_TEST("After You fails if the turn order remains the same after After You (Gen5-7)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_AFTER_YOU_TURN_ORDER, GEN_7); + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + PLAYER(SPECIES_WYNAUT) { Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WYNAUT) { Speed(3); } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_CELEBRATE); + MOVE(playerRight, MOVE_CELEBRATE); + MOVE(opponentLeft, MOVE_CELEBRATE); + MOVE(opponentRight, MOVE_AFTER_YOU, target: opponentLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); + MESSAGE("The opposing Wynaut used After You!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_AFTER_YOU, opponentRight); + MESSAGE("But it failed!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + } +} + DOUBLE_BATTLE_TEST("After You doesn't fail if the turn order remains the same after After You (Gen8+)") { GIVEN { - ASSUME(B_AFTER_YOU_TURN_ORDER >= GEN_8); + WITH_CONFIG(GEN_CONFIG_AFTER_YOU_TURN_ORDER, GEN_8); PLAYER(SPECIES_WOBBUFFET) { Speed(4); } PLAYER(SPECIES_WYNAUT) { Speed(1); } OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } diff --git a/test/battle/move_effect/attack_up_user_ally.c b/test/battle/move_effect/attack_up_user_ally.c index ed3fedb261..767e9fdef7 100644 --- a/test/battle/move_effect/attack_up_user_ally.c +++ b/test/battle/move_effect/attack_up_user_ally.c @@ -1,17 +1,14 @@ #include "global.h" #include "test/battle.h" -ASSUMPTIONS -{ - ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); -} - SINGLE_BATTLE_TEST("Howl raises user's Attack by 1 stage", s16 damage) { bool32 raiseAttack; PARAMETRIZE { raiseAttack = FALSE; } PARAMETRIZE { raiseAttack = TRUE; } GIVEN { + ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP + || GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -37,6 +34,7 @@ DOUBLE_BATTLE_TEST("Howl raises user's and partner's Attack by 1 stage", s16 dam PARAMETRIZE { raiseAttack = FALSE; } PARAMETRIZE { raiseAttack = TRUE; } GIVEN { + ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL); PLAYER(SPECIES_WOBBUFFET) { Speed(15); } PLAYER(SPECIES_WYNAUT) { Speed(10); } @@ -69,6 +67,7 @@ DOUBLE_BATTLE_TEST("Howl does not work on partner if it has Soundproof") s16 damage[2]; GIVEN { + ASSUME(GetMoveEffect(MOVE_HOWL) == EFFECT_ATTACK_UP_USER_ALLY); ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL); PLAYER(SPECIES_WOBBUFFET) { Speed(15); } PLAYER(SPECIES_VOLTORB) { Speed(10); Ability(ABILITY_SOUNDPROOF); } diff --git a/test/battle/move_effect/healing_wish.c b/test/battle/move_effect/healing_wish.c index f303456a38..31dfebb342 100644 --- a/test/battle/move_effect/healing_wish.c +++ b/test/battle/move_effect/healing_wish.c @@ -49,10 +49,28 @@ DOUBLE_BATTLE_TEST("Lunar Dance causes the user to faint and fully heals the rep } } -SINGLE_BATTLE_TEST("Healing Wish effect activates only if the switched Pokémon can be healed") +SINGLE_BATTLE_TEST("Healing Wish effect activates even if the the switched Pokémon can't be healed (Gen4-7)") { GIVEN { - ASSUME(B_HEALING_WISH_SWITCH >= GEN_8); + WITH_CONFIG(GEN_CONFIG_HEALING_WISH_SWITCH, GEN_7); + PLAYER(SPECIES_GARDEVOIR) { Speed(300); } + PLAYER(SPECIES_NINJASK) { Speed(400); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } + } WHEN { + TURN { MOVE(player, MOVE_HEALING_WISH); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HEALING_WISH, player); + HP_BAR(player, hp: 0); + MESSAGE("Gardevoir fainted!"); + MESSAGE("The healing wish came true for Ninjask!"); + MESSAGE("Ninjask regained health!"); + } +} + +SINGLE_BATTLE_TEST("Healing Wish effect activates only if the switched Pokémon can be healed (Gen8+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_HEALING_WISH_SWITCH, GEN_8); PLAYER(SPECIES_GARDEVOIR) { Speed(300); } PLAYER(SPECIES_NINJASK) { Speed(400); } PLAYER(SPECIES_WYNAUT) { HP(50); MaxHP(100); Status1(STATUS1_PARALYSIS); Speed(50); } @@ -65,8 +83,8 @@ SINGLE_BATTLE_TEST("Healing Wish effect activates only if the switched Pokémon HP_BAR(player, hp: 0); MESSAGE("Gardevoir fainted!"); NONE_OF { - MESSAGE("The healing wish came true for Wynaut!"); - MESSAGE("Wynaut's HP was restored."); + MESSAGE("The healing wish came true for Ninjask!"); + MESSAGE("Ninjask regained health!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player); MESSAGE("The healing wish came true for Wynaut!"); diff --git a/test/battle/move_effect/pursuit.c b/test/battle/move_effect/pursuit.c index b18aa74b09..27303d95ce 100644 --- a/test/battle/move_effect/pursuit.c +++ b/test/battle/move_effect/pursuit.c @@ -51,6 +51,7 @@ DOUBLE_BATTLE_TEST("Pursuit doesn't attack a foe using Teleport / Baton Pass to PARAMETRIZE { move = MOVE_TELEPORT; } PARAMETRIZE { move = MOVE_BATON_PASS; } GIVEN { + WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); ASSUME(GetMoveEffect(MOVE_QUASH) == EFFECT_QUASH); ASSUME(GetMoveEffect(MOVE_TELEPORT) == EFFECT_TELEPORT); ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS); diff --git a/test/battle/move_effect/quash.c b/test/battle/move_effect/quash.c index 0869b45aeb..a6032b43c4 100644 --- a/test/battle/move_effect/quash.c +++ b/test/battle/move_effect/quash.c @@ -26,7 +26,7 @@ DOUBLE_BATTLE_TEST("Quash-affected target will move last in the priority bracket DOUBLE_BATTLE_TEST("Quash is not affected by dynamic speed") { GIVEN { - ASSUME(B_RECALC_TURN_AFTER_ACTIONS >= GEN_8); + WITH_CONFIG(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_8); ASSUME(GetMoveEffect(MOVE_TAILWIND) == EFFECT_TAILWIND); PLAYER(SPECIES_VOLBEAT) { Speed(10); Ability(ABILITY_PRANKSTER); } PLAYER(SPECIES_WOBBUFFET) { Speed(30); } @@ -112,7 +112,7 @@ DOUBLE_BATTLE_TEST("Quash-affected targets move from fastest to slowest (Gen 8+) DOUBLE_BATTLE_TEST("Quash-affected mon that acted early via After You is not affected by dynamic speed") { GIVEN { - ASSUME(B_RECALC_TURN_AFTER_ACTIONS >= GEN_8); + WITH_CONFIG(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_8); ASSUME(GetMoveEffect(MOVE_TAILWIND) == EFFECT_TAILWIND); ASSUME(GetMoveEffect(MOVE_AFTER_YOU) == EFFECT_AFTER_YOU); PLAYER(SPECIES_VOLBEAT) { Speed(20); Ability(ABILITY_PRANKSTER); } diff --git a/test/battle/move_effect/rage_fist.c b/test/battle/move_effect/rage_fist.c index ed21a9097c..5d92544e53 100644 --- a/test/battle/move_effect/rage_fist.c +++ b/test/battle/move_effect/rage_fist.c @@ -249,7 +249,35 @@ SINGLE_BATTLE_TEST("Rage Fist base power is not increased if move had no affect" } } -SINGLE_BATTLE_TEST("Rage Fist base power is increased if Disguise breaks") +SINGLE_BATTLE_TEST("Rage Fist base power is increased if Disguise breaks (Gen7)") +{ + KNOWN_FAILING; + s16 timesGotHit[2]; + u16 species = SPECIES_NONE; + + PARAMETRIZE { species = SPECIES_MIMIKYU_DISGUISED; } + PARAMETRIZE { species = SPECIES_MIMIKYU_TOTEM_DISGUISED; } + + GIVEN { + WITH_CONFIG(GEN_CONFIG_DISGUISE_HP_LOSS, GEN_7); + PLAYER(species) { Ability(ABILITY_DISGUISE); } + OPPONENT(SPECIES_REGIROCK); + } WHEN { + TURN { MOVE(player, MOVE_RAGE_FIST); MOVE(opponent, MOVE_ROCK_THROW); } + TURN { MOVE(player, MOVE_RAGE_FIST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGE_FIST, player); + HP_BAR(opponent, captureDamage: ×GotHit[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_THROW, opponent); + ABILITY_POPUP(player, ABILITY_DISGUISE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGE_FIST, player); + HP_BAR(opponent, captureDamage: ×GotHit[1]); + } THEN { + EXPECT_MUL_EQ(timesGotHit[0], Q_4_12(2.0), timesGotHit[1]); + } +} + +SINGLE_BATTLE_TEST("Rage Fist base power is increased if Disguise breaks (Gen8+)") { s16 timesGotHit[2]; u16 species = SPECIES_NONE; @@ -258,6 +286,7 @@ SINGLE_BATTLE_TEST("Rage Fist base power is increased if Disguise breaks") PARAMETRIZE { species = SPECIES_MIMIKYU_TOTEM_DISGUISED; } GIVEN { + WITH_CONFIG(GEN_CONFIG_DISGUISE_HP_LOSS, GEN_8); PLAYER(species) { Ability(ABILITY_DISGUISE); } OPPONENT(SPECIES_REGIROCK); } WHEN { diff --git a/test/battle/move_effect/tailwind.c b/test/battle/move_effect/tailwind.c index f105c9612a..7968bc25ef 100644 --- a/test/battle/move_effect/tailwind.c +++ b/test/battle/move_effect/tailwind.c @@ -36,10 +36,28 @@ SINGLE_BATTLE_TEST("Tailwind applies for 4 turns") } } -DOUBLE_BATTLE_TEST("Tailwind affects partner on first turn") +DOUBLE_BATTLE_TEST("Tailwind doesn't affect the partner on the same turn it's used (Gen4-7)") { GIVEN { - ASSUME(B_RECALC_TURN_AFTER_ACTIONS); + WITH_CONFIG(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_7); + PLAYER(SPECIES_WOBBUFFET) { Speed(20); } + PLAYER(SPECIES_WYNAUT) { Speed(10); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(15); } + OPPONENT(SPECIES_WYNAUT) { Speed(14); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_TAILWIND); } + } SCENE { + MESSAGE("Wobbuffet used Tailwind!"); + MESSAGE("The opposing Wobbuffet used Celebrate!"); + MESSAGE("The opposing Wynaut used Celebrate!"); + MESSAGE("Wynaut used Celebrate!"); + } +} + +DOUBLE_BATTLE_TEST("Tailwind affects the partner on the same turn it's used (Gen8+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, GEN_8); PLAYER(SPECIES_WOBBUFFET) { Speed(20); } PLAYER(SPECIES_WYNAUT) { Speed(10); } OPPONENT(SPECIES_WOBBUFFET) { Speed(15); } diff --git a/test/battle/move_effect/teleport.c b/test/battle/move_effect/teleport.c index 76fb499722..83d2142e67 100644 --- a/test/battle/move_effect/teleport.c +++ b/test/battle/move_effect/teleport.c @@ -6,9 +6,10 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_TELEPORT) == EFFECT_TELEPORT); } -SINGLE_BATTLE_TEST("Teleport fails when there is no Pokémon to switch in") +SINGLE_BATTLE_TEST("Teleport fails to switch out when there is no Pokémon to switch in (Gen 8+)") { GIVEN { + WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -18,9 +19,10 @@ SINGLE_BATTLE_TEST("Teleport fails when there is no Pokémon to switch in") } } -SINGLE_BATTLE_TEST("Teleport fails when there no alive Pokémon left") +SINGLE_BATTLE_TEST("Teleport fails to switch out the user when there no alive Pokémon left (Gen 8+)") { GIVEN { + WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT) { HP(0); } @@ -31,9 +33,29 @@ SINGLE_BATTLE_TEST("Teleport fails when there no alive Pokémon left") } } -SINGLE_BATTLE_TEST("Teleport forces the Pokémon to switch out") +SINGLE_BATTLE_TEST("Teleport fails in Trainer Battles (Gen 1-7)") { GIVEN { + WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_7); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_TELEPORT); } + } SCENE { + MESSAGE("The opposing Wobbuffet used Teleport!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TELEPORT, opponent); + MESSAGE("2 sent out Wynaut!"); + } + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Teleport forces the Pokémon to switch out in Trainer Battles (Gen 8+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); @@ -48,6 +70,7 @@ SINGLE_BATTLE_TEST("Teleport forces the Pokémon to switch out") SINGLE_BATTLE_TEST("Teleport does not fail if the user is trapped") { GIVEN { + WITH_CONFIG(GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); From 6e18c2f06e89a6bd8f099cd205c06a84ed721e6b Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Thu, 4 Sep 2025 14:18:51 +0100 Subject: [PATCH 2/2] Tidy up CanTargetFaintAiWithMod and CanTargetMoveFaintAi (#7693) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_ai_util.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 6bf1245922..f92112063d 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1559,7 +1559,8 @@ bool32 CanTargetMoveFaintAi(u32 move, u32 battlerDef, u32 battlerAtk, u32 nHits) u32 indexSlot = GetMoveSlot(GetMovesArray(battlerDef), move); if (indexSlot < MAX_MON_MOVES) { - if (GetNoOfHitsToKO(AI_GetDamage(battlerDef, battlerAtk, indexSlot, AI_DEFENDING, gAiLogicData), gBattleMons[battlerAtk].hp) <= nHits) + u32 hitsToKO = GetNoOfHitsToKO(AI_GetDamage(battlerDef, battlerAtk, indexSlot, AI_DEFENDING, gAiLogicData), gBattleMons[battlerAtk].hp); + if (hitsToKO <= nHits && hitsToKO != 0 && !(CanEndureHit(battlerDef, battlerAtk, move) && hitsToKO == 1)) return TRUE; } return FALSE; @@ -1588,8 +1589,15 @@ bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dm if (dmgMod) dmg *= dmgMod; - if (dmg >= hpCheck) + // Applies modified HP percent to AI data for consideration when running CanEndureHit + gAiLogicData->hpPercents[battlerAtk] = (hpCheck/gBattleMons[battlerAtk].maxHP)*100; + + if (dmg >= hpCheck && !(CanEndureHit(battlerDef, battlerAtk, moves[moveIndex]) && (dmgMod <= 1))) + { + gAiLogicData->hpPercents[battlerAtk] = (gBattleMons[battlerAtk].hp / gBattleMons[battlerAtk].maxHP) * 100; return TRUE; + } + gAiLogicData->hpPercents[battlerAtk] = (gBattleMons[battlerAtk].hp / gBattleMons[battlerAtk].maxHP) * 100; } return FALSE;