diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6b4b18f48a..b26d2905da 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1171,24 +1171,59 @@ BattleScript_EffectSpectralThiefFromDamage: BattleScript_EffectPartingShot:: attackcanceler jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_ATK, MIN_STAT_STAGE, BattleScript_EffectPartingShotTryAtk - jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MIN_STAT_STAGE, BattleScript_CantLowerMultipleStats + jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MIN_STAT_STAGE, BattleScript_EffectPartingShotCantLowerMultipleStats BattleScript_EffectPartingShotTryAtk: accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE attackanimation waitanimation + setbyte sB_ANIM_TARGETS_HIT, 0 setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectPartingShotTrySpAtk, BIT_SPATK - printfromtable gStatDownStringIds - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectPartingShotMaybePrintStat BattleScript_EffectPartingShotTrySpAtk: setstatchanger STAT_SPATK, 1, TRUE - statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectPartingShotSwitch - printfromtable gStatDownStringIds - waitmessage B_WAIT_TIME_LONG + statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectPartingShotMaybeSwitch + call BattleScript_EffectPartingShotMaybePrintStat +BattleScript_EffectPartingShotMaybeSwitch: + jumpifgenconfiglowerthan CONFIG_PARTING_SHOT_SWITCH, GEN_7, BattleScript_EffectPartingShotSwitch + jumpifbyte CMP_NOT_EQUAL, sB_ANIM_TARGETS_HIT, 0, BattleScript_EffectPartingShotSwitch + goto BattleScript_MoveEnd + BattleScript_EffectPartingShotSwitch: moveendall goto BattleScript_MoveSwitchPursuitEnd +BattleScript_EffectPartingShotCantLowerMultipleStats: + pause B_WAIT_TIME_SHORT + setmoveresultflags MOVE_RESULT_FAILED + call BattleScript_EffectPartingShotPrintWontDecrease + setbyte sB_ANIM_TARGETS_HIT, 0 + goto BattleScript_EffectPartingShotMaybeSwitch + +BattleScript_EffectPartingShotMaybePrintStat: + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_ATTACKER_STAT_CHANGED, BattleScript_EffectPartingShotPrintStat + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_EffectPartingShotPrintStat + return + +BattleScript_EffectPartingShotPrintStat: + setbyte sB_ANIM_TARGETS_HIT, 1 + printfromtable gStatDownStringIds + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_EffectPartingShotPrintWontDecrease: + jumpifability BS_TARGET, ABILITY_CONTRARY, BattleScript_EffectPartingShotPrintWontDecreaseContrary + printstring STRINGID_STATSWONTDECREASE2 + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_EffectPartingShotPrintWontDecreaseContrary: + swapattackerwithtarget + printstring STRINGID_STATSWONTDECREASE2 + waitmessage B_WAIT_TIME_LONG + swapattackerwithtarget + return + BattleScript_EffectPowder:: attackcanceler accuracycheck BattleScript_MoveMissedPause, NO_ACC_CALC_CHECK_LOCK_ON diff --git a/include/config/battle.h b/include/config/battle.h index b5d11a9b3e..874817a5ab 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -96,6 +96,7 @@ #define B_CAN_SPITE_FAIL GEN_LATEST // In Gen4+, Spite can no longer fail if the foe's last move only has 1 remaining PP. #define B_CRASH_IF_TARGET_IMMUNE GEN_LATEST // In Gen4+, moves with crash damage will crash if the user attacks a target that is immune due to their typing. #define B_MEMENTO_FAIL GEN_LATEST // In Gen4+, Memento no longer fails if the target already has -6 Attack and Special Attack. Additionally, in Gen5+, it fails if there is no target, or if the target is protected or behind a Substitute. +#define B_PARTING_SHOT_SWITCH GEN_LATEST // In Gen7+, the user won't switch out if Parting Shot fails to lower the target's stats. #define B_GLARE_GHOST GEN_LATEST // In Gen4+, Glare can hit Ghost-type Pokémon normally. #define B_SKILL_SWAP GEN_LATEST // In Gen4+, Skill Swap triggers switch-in abilities after use. #define B_BRICK_BREAK GEN_LATEST // In Gen4+, you can destroy your own side's screens. In Gen 5+, screens are not removed if the target is immune. diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 81ff4bece6..f8ef227c4a 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -89,6 +89,7 @@ F(CAN_SPITE_FAIL, canSpiteFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ F(CRASH_IF_TARGET_IMMUNE, crashIfTargetImmune, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ F(MEMENTO_FAIL, mementoFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ + F(PARTING_SHOT_SWITCH, partingShotSwitch, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ F(GLARE_GHOST, glareGhost, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ F(SKILL_SWAP, skillSwap, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ F(BRICK_BREAK, brickBreak, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \ diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 97e324b25c..0dee3f9320 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10395,6 +10395,8 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, enum Stat statId, union St } else if (battlerAbility == ABILITY_MIRROR_ARMOR && !flags.mirrorArmored && gBattlerAttacker != gBattlerTarget && battler == gBattlerTarget) { + if (GetMoveEffect(gCurrentMove) == EFFECT_PARTING_SHOT) + gBattleScripting.animTargetsHit = 1; if (flags.allowPtr) { SET_STATCHANGER(statId, GET_STAT_BUFF_VALUE(statValue) | STAT_BUFF_NEGATIVE, TRUE); diff --git a/test/battle/move_effect/parting_shot.c b/test/battle/move_effect/parting_shot.c index 4d55d09315..58c5ba5218 100644 --- a/test/battle/move_effect/parting_shot.c +++ b/test/battle/move_effect/parting_shot.c @@ -1,4 +1,385 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Parting Shot (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_PARTING_SHOT) == EFFECT_PARTING_SHOT); +} + +SINGLE_BATTLE_TEST("Parting Shot: Passes Substitute and switches the user out") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT, MOVE_CELEBRATE); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SUBSTITUTE, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SUBSTITUTE); } + TURN { MOVE(player, MOVE_PARTING_SHOT); MOVE(opponent, MOVE_CELEBRATE); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, player); + SEND_IN_MESSAGE("Wynaut"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(player->species, SPECIES_WYNAUT); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Soundproof and Good as Gold block Parting Shot") +{ + u16 species, ability; + + PARAMETRIZE { species = SPECIES_EXPLOUD; ability = ABILITY_SOUNDPROOF; } + PARAMETRIZE { species = SPECIES_GHOLDENGO; ability = ABILITY_GOOD_AS_GOLD; } + + GIVEN { + ASSUME(IsSoundMove(MOVE_PARTING_SHOT)); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(species) { Ability(ability); Moves(MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_PARTING_SHOT); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(opponent, ability); + if (ability == ABILITY_SOUNDPROOF) + MESSAGE("The opposing Exploud's Soundproof blocks Parting Shot!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, player); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WOBBUFFET); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Hyper Cutter blocks Attack drop but still switches") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } + } WHEN { + TURN { MOVE(player, MOVE_PARTING_SHOT); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, player); + SEND_IN_MESSAGE("Wynaut"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(player->species, SPECIES_WYNAUT); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Magic Coat bounces it and switches the target out") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_MAGIC_COAT); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_MAGIC_COAT); MOVE(player, MOVE_PARTING_SHOT); SEND_OUT(opponent, 1); } + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(opponent->species, SPECIES_WYNAUT); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Magic Bounce bounces it and switches the target out") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT); } + OPPONENT(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_PARTING_SHOT); SEND_OUT(opponent, 1); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_MAGIC_BOUNCE); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(opponent->species, SPECIES_WYNAUT); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Mirror Armor switches the user even if reflected drops fail") +{ + u16 species, ability, item; + + PARAMETRIZE { species = SPECIES_METAGROSS; ability = ABILITY_CLEAR_BODY; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_LUCARIO; ability = ABILITY_INNER_FOCUS; item = ITEM_CLEAR_AMULET; } + + GIVEN { + ASSUME(gItemsInfo[ITEM_CLEAR_AMULET].holdEffect == HOLD_EFFECT_CLEAR_AMULET); + PLAYER(species) { Ability(ability); Item(item); Moves(MOVE_PARTING_SHOT); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); } + } WHEN { + TURN { MOVE(player, MOVE_PARTING_SHOT); SEND_OUT(player, 1); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_MIRROR_ARMOR); + if (ability == ABILITY_CLEAR_BODY) { + ABILITY_POPUP(player, ABILITY_CLEAR_BODY); + MESSAGE("Metagross's Clear Body prevents stat loss!"); + } else if (ability == ABILITY_WHITE_SMOKE) { + ABILITY_POPUP(player, ABILITY_WHITE_SMOKE); + MESSAGE("Torkoal's White Smoke prevents stat loss!"); + } else if (ability == ABILITY_FULL_METAL_BODY) { + ABILITY_POPUP(player, ABILITY_FULL_METAL_BODY); + MESSAGE("Solgaleo's Full Metal Body prevents stat loss!"); + } else if (item == ITEM_CLEAR_AMULET) { + MESSAGE("The effects of the Clear Amulet held by Lucario prevents its stats from being lowered!"); + } + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WYNAUT); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Mirror Armor switches even if reflected stats are at minimum") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT, MOVE_SHELL_SMASH, MOVE_CELEBRATE); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); Moves(MOVE_TOPSY_TURVY, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_SHELL_SMASH); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_SHELL_SMASH); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_SHELL_SMASH); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TOPSY_TURVY); } + TURN { MOVE(player, MOVE_PARTING_SHOT); SEND_OUT(player, 1); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_MIRROR_ARMOR); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WYNAUT); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Does not switch if both stats are at minimum (Gen7+)") +{ + GIVEN { + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_7); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT, MOVE_TOPSY_TURVY, MOVE_CELEBRATE); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_OMASTAR) { Moves(MOVE_SHELL_SMASH, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_TOPSY_TURVY); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_PARTING_SHOT); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + MESSAGE("The opposing Omastar's stats won't go any lower!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], MIN_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], MIN_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WOBBUFFET); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Does not switch if Contrary is at maximum stats (Gen7+)") +{ + GIVEN { + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_7); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT, MOVE_TOPSY_TURVY, MOVE_CELEBRATE); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_INKAY) { Ability(ABILITY_CONTRARY); Moves(MOVE_SHELL_SMASH, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_TOPSY_TURVY); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_PARTING_SHOT); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + MESSAGE("The opposing Inkay's stats won't go any higher!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], MAX_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], MAX_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WOBBUFFET); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Stat drop prevention by abilities/items does not switch (Gen7+)") +{ + u16 species, ability, item; + + PARAMETRIZE { species = SPECIES_METAGROSS; ability = ABILITY_CLEAR_BODY; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_LUCARIO; ability = ABILITY_INNER_FOCUS; item = ITEM_CLEAR_AMULET; } + + GIVEN { + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_7); + ASSUME(gItemsInfo[ITEM_CLEAR_AMULET].holdEffect == HOLD_EFFECT_CLEAR_AMULET); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(species) { Ability(ability); Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_PARTING_SHOT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, player); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WOBBUFFET); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Mist prevents stat drops and does not switch (Gen7+)") +{ + GIVEN { + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_7); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT, MOVE_CELEBRATE); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_MIST, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_MIST); MOVE(player, MOVE_CELEBRATE); } + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_PARTING_SHOT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, player); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WOBBUFFET); + } +} + +DOUBLE_BATTLE_TEST("Parting Shot: Flower Veil prevents stat drops and does not switch (Gen7+)") +{ + GIVEN { + ASSUME(GetSpeciesType(SPECIES_BULBASAUR, 0) == TYPE_GRASS); + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_7); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT); } + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_BULBASAUR); + OPPONENT(SPECIES_COMFEY) { Ability(ABILITY_FLOWER_VEIL); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_PARTING_SHOT, target: opponentLeft); MOVE(playerRight, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, playerLeft); + } THEN { + EXPECT_EQ(opponentLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponentLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(playerLeft->species, SPECIES_WOBBUFFET); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Switches if both stats are at minimum (Gen6)") +{ + GIVEN { + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_6); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT, MOVE_TOPSY_TURVY, MOVE_CELEBRATE); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_OMASTAR) { Moves(MOVE_SHELL_SMASH, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_TOPSY_TURVY); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_PARTING_SHOT); MOVE(opponent, MOVE_CELEBRATE); SEND_OUT(player, 1); } + } SCENE { + MESSAGE("The opposing Omastar's stats won't go any lower!"); + SEND_IN_MESSAGE("Wynaut"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], MIN_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], MIN_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WYNAUT); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Switches if Contrary is at maximum stats (Gen6)") +{ + GIVEN { + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_6); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT, MOVE_TOPSY_TURVY, MOVE_CELEBRATE); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_INKAY) { Ability(ABILITY_CONTRARY); Moves(MOVE_SHELL_SMASH, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_TOPSY_TURVY); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_PARTING_SHOT); MOVE(opponent, MOVE_CELEBRATE); SEND_OUT(player, 1); } + } SCENE { + MESSAGE("The opposing Inkay's stats won't go any higher!"); + SEND_IN_MESSAGE("Wynaut"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], MAX_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], MAX_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WYNAUT); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Stat drop prevention by abilities/items switches (Gen6)") +{ + u16 species, ability, item; + + PARAMETRIZE { species = SPECIES_METAGROSS; ability = ABILITY_CLEAR_BODY; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_LUCARIO; ability = ABILITY_INNER_FOCUS; item = ITEM_CLEAR_AMULET; } + + GIVEN { + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_6); + ASSUME(gItemsInfo[ITEM_CLEAR_AMULET].holdEffect == HOLD_EFFECT_CLEAR_AMULET); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(species) { Ability(ability); Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_PARTING_SHOT); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, player); + SEND_IN_MESSAGE("Wynaut"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WYNAUT); + } +} + +SINGLE_BATTLE_TEST("Parting Shot: Mist prevents stat drops and switches (Gen6)") +{ + GIVEN { + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_6); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT, MOVE_CELEBRATE); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_MIST, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_MIST); MOVE(player, MOVE_CELEBRATE); } + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_PARTING_SHOT); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, player); + SEND_IN_MESSAGE("Wynaut"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->species, SPECIES_WYNAUT); + } +} + +DOUBLE_BATTLE_TEST("Parting Shot: Flower Veil prevents stat drops and switches (Gen6)") +{ + GIVEN { + WITH_CONFIG(CONFIG_PARTING_SHOT_SWITCH, GEN_6); + ASSUME(GetSpeciesType(SPECIES_BULBASAUR, 0) == TYPE_GRASS); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_PARTING_SHOT); } + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_PIKACHU); + OPPONENT(SPECIES_BULBASAUR); + OPPONENT(SPECIES_COMFEY) { Ability(ABILITY_FLOWER_VEIL); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_PARTING_SHOT, target: opponentLeft); MOVE(playerRight, MOVE_CELEBRATE); SEND_OUT(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, playerLeft); + SEND_IN_MESSAGE("Pikachu"); + } THEN { + EXPECT_EQ(opponentLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponentLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(playerLeft->species, SPECIES_PIKACHU); + } +}