Fixes Nightmare not affecting Comatose and adds various missing tests (#8859)

This commit is contained in:
GGbond 2026-01-11 23:02:41 +08:00 committed by GitHub
parent 41038cbc88
commit b671adf85f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 1295 additions and 78 deletions

View File

@ -3336,9 +3336,9 @@ BattleScript_EffectMeanLook::
accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON
jumpifvolatile BS_TARGET, VOLATILE_ESCAPE_PREVENTION, BattleScript_ButItFailed
jumpifsubstituteblocks BattleScript_ButItFailed
.if B_GHOSTS_ESCAPE >= GEN_6
jumpifgenconfiglowerthan CONFIG_GHOSTS_ESCAPE, GEN_6, BattleScript_EffectMeanLookGen5
jumpiftype BS_TARGET, TYPE_GHOST, BattleScript_ButItFailed
.endif
BattleScript_EffectMeanLookGen5:
attackanimation
waitanimation
seteffectprimary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_PREVENT_ESCAPE

View File

@ -2045,7 +2045,7 @@ static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposi
static bool32 CanAbilityTrapOpponent(enum Ability ability, u32 opponent)
{
if ((B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(opponent, TYPE_GHOST)))
if ((GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(opponent, TYPE_GHOST)))
return FALSE;
else if (ability == ABILITY_SHADOW_TAG)
{

View File

@ -474,7 +474,7 @@ bool32 AI_CanBattlerEscape(u32 battler)
{
enum HoldEffect holdEffect = gAiLogicData->holdEffects[battler];
if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
return TRUE;
if (holdEffect == HOLD_EFFECT_SHED_SHELL)
return TRUE;
@ -3091,7 +3091,9 @@ static u32 GetLeechSeedDamage(u32 battler)
static u32 GetNightmareDamage(u32 battlerId)
{
u32 damage = 0;
if (gBattleMons[battlerId].volatiles.nightmare && gBattleMons[battlerId].status1 & STATUS1_SLEEP)
if (gBattleMons[battlerId].volatiles.nightmare
&& ((gBattleMons[battlerId].status1 & STATUS1_SLEEP)
|| gAiLogicData->abilities[battlerId] == ABILITY_COMATOSE))
{
damage = GetNonDynamaxMaxHP(battlerId) / 4;
if (damage == 0)

View File

@ -574,7 +574,7 @@ static bool32 HandleEndTurnNightmare(u32 battler)
&& IsBattlerAlive(battler)
&& !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD))
{
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
if (gBattleMons[battler].status1 & STATUS1_SLEEP || GetBattlerAbility(battler) == ABILITY_COMATOSE)
{
SetPassiveDamageAmount(battler, GetNonDynamaxMaxHP(battler) / 4);
BattleScriptExecute(BattleScript_NightmareTurnDmg);

View File

@ -4106,7 +4106,7 @@ u8 IsRunningFromBattleImpossible(u32 battler)
if (holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN)
return BATTLE_RUN_SUCCESS;
if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
return BATTLE_RUN_SUCCESS;
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
return BATTLE_RUN_SUCCESS;

View File

@ -695,7 +695,7 @@ bool32 TryRunFromBattle(u32 battler)
gProtectStructs[battler].fleeType = FLEE_ITEM;
effect++;
}
else if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
else if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
{
effect++;
}
@ -5804,7 +5804,7 @@ u32 IsAbilityOnFieldExcept(u32 battler, enum Ability ability)
u32 IsAbilityPreventingEscape(u32 battler)
{
if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
return 0;
bool32 isBattlerGrounded = IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler));
@ -5832,7 +5832,7 @@ bool32 CanBattlerEscape(u32 battler) // no ability check
{
if (gBattleStruct->battlerState[battler].commanderSpecies != SPECIES_NONE)
return FALSE;
else if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
else if (GetConfig(CONFIG_GHOSTS_ESCAPE) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
return TRUE;
else if (gBattleMons[battler].volatiles.escapePrevention)
return FALSE;

View File

@ -75,12 +75,16 @@ SINGLE_BATTLE_TEST("Anticipation doesn't consider Scrappy into their effectivene
ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING);
ASSUME(GetSpeciesType(SPECIES_DOUBLADE, 0) == TYPE_STEEL);
ASSUME(GetSpeciesType(SPECIES_DOUBLADE, 1) == TYPE_GHOST);
PLAYER(SPECIES_DOUBLADE) { Ability(ABILITY_ANTICIPATION); }
OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); Moves(MOVE_CLOSE_COMBAT, MOVE_CELEBRATE); }
PLAYER(SPECIES_WORMADAM_TRASH) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_SKILL_SWAP, MOVE_CELEBRATE); }
PLAYER(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); Moves(MOVE_CLOSE_COMBAT, MOVE_CELEBRATE); }
OPPONENT(SPECIES_DOUBLADE) { Ability(ABILITY_NO_GUARD); Moves(MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {}
TURN { MOVE(player, MOVE_SKILL_SWAP, target: opponent); MOVE(opponent, MOVE_CELEBRATE); }
TURN { SWITCH(player, 1); SWITCH(opponent, 1); }
TURN { SWITCH(opponent, 0); }
} SCENE {
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
NOT ABILITY_POPUP(opponent, ABILITY_ANTICIPATION);
}
}

View File

@ -1,11 +1,141 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Arena Trap prevents grounded adjacent opponents from switching out");
TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs if the Pokémon is switched in the same turn the opponent decided to switch out");
TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs via moves that switch out"); // Baton Pass, U-Turn, Volt Switch, Flip Turn, Parting Shot
TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs via Shed Shell, but not via Teleport");
TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs via Run Away");
TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs via Smoke Ball");
TO_DO_BATTLE_TEST("Arena Trap prevents switch outs from Ghost-type Pokémon (Gen3-5)");
TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs from Ghost-type Pokémon (Gen6+)");
SINGLE_BATTLE_TEST("Arena Trap prevents grounded adjacent opponents from switching out")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); }
} THEN {
u32 battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
u32 trapper = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
EXPECT_EQ(IsAbilityPreventingEscape(battler), trapper + 1);
}
}
SINGLE_BATTLE_TEST("Arena Trap doesn't prevent switch outs if the Pokémon is switched in the same turn the opponent decided to switch out")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
PLAYER(SPECIES_WYNAUT) { Speed(10); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); Speed(5); }
} WHEN {
TURN { SWITCH(player, 1); SWITCH(opponent, 1); }
} SCENE {
SWITCH_OUT_MESSAGE("Wobbuffet");
SEND_IN_MESSAGE("Wynaut");
} THEN {
EXPECT_EQ(player->species, SPECIES_WYNAUT);
EXPECT_EQ(opponent->species, SPECIES_DIGLETT);
}
}
SINGLE_BATTLE_TEST("Arena Trap doesn't prevent switch outs via moves that switch out")
{
u16 move, effect;
PARAMETRIZE { move = MOVE_BATON_PASS; effect = EFFECT_BATON_PASS; }
PARAMETRIZE { move = MOVE_U_TURN; effect = EFFECT_HIT_ESCAPE; }
PARAMETRIZE { move = MOVE_VOLT_SWITCH; effect = EFFECT_HIT_ESCAPE; }
PARAMETRIZE { move = MOVE_FLIP_TURN; effect = EFFECT_HIT_ESCAPE; }
PARAMETRIZE { move = MOVE_PARTING_SHOT; effect = EFFECT_PARTING_SHOT; }
PARAMETRIZE { move = MOVE_TELEPORT; effect = EFFECT_TELEPORT; }
PARAMETRIZE { move = MOVE_SHED_TAIL; effect = EFFECT_SHED_TAIL; }
PARAMETRIZE { move = MOVE_CHILLY_RECEPTION; effect = EFFECT_CHILLY_RECEPTION; }
GIVEN {
ASSUME(GetMoveEffect(move) == effect);
ASSUME(GetMoveEffect(MOVE_SOAK) == EFFECT_SOAK);
WITH_CONFIG(CONFIG_TELEPORT_BEHAVIOR, GEN_8);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
} WHEN {
if (move == MOVE_VOLT_SWITCH)
TURN { MOVE(player, MOVE_SOAK); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, move); SEND_OUT(player, 1); }
} SCENE {
if (move == MOVE_VOLT_SWITCH)
ANIMATION(ANIM_TYPE_MOVE, MOVE_SOAK, player);
ANIMATION(ANIM_TYPE_MOVE, move, player);
SEND_IN_MESSAGE("Wynaut");
}
}
SINGLE_BATTLE_TEST("Arena Trap doesn't prevent switch outs via Shed Shell")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_SHED_SHELL].holdEffect == HOLD_EFFECT_SHED_SHELL);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SHED_SHELL); } // Grounded
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
} WHEN {
TURN { SWITCH(player, 1); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
SWITCH_OUT_MESSAGE("Wobbuffet");
SEND_IN_MESSAGE("Wynaut");
}
}
WILD_BATTLE_TEST("Arena Trap prevents switching but Run Away allows fleeing")
{
GIVEN {
PLAYER(SPECIES_RATTATA) { Ability(ABILITY_RUN_AWAY); }
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); }
} THEN {
u32 battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
u32 trapper = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
EXPECT_EQ(IsAbilityPreventingEscape(battler), trapper + 1);
EXPECT_EQ(IsRunningFromBattleImpossible(battler), BATTLE_RUN_SUCCESS);
}
}
WILD_BATTLE_TEST("Arena Trap prevents switching but Smoke Ball allows fleeing")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_SMOKE_BALL].holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SMOKE_BALL); }
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); }
} THEN {
u32 battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
u32 trapper = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
EXPECT_EQ(IsAbilityPreventingEscape(battler), trapper + 1);
EXPECT_EQ(IsRunningFromBattleImpossible(battler), BATTLE_RUN_SUCCESS);
}
}
SINGLE_BATTLE_TEST("Arena Trap prevents switch outs from Ghost-type Pokémon (Gen3-5)")
{
GIVEN {
ASSUME(GetSpeciesType(SPECIES_SHUPPET, 0) == TYPE_GHOST);
WITH_CONFIG(CONFIG_GHOSTS_ESCAPE, GEN_5);
PLAYER(SPECIES_SHUPPET);
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); }
} THEN {
u32 battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
u32 trapper = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
EXPECT_EQ(IsAbilityPreventingEscape(battler), trapper + 1);
}
}
SINGLE_BATTLE_TEST("Arena Trap doesn't prevent switch outs from Ghost-type Pokémon (Gen6+)")
{
GIVEN {
ASSUME(GetSpeciesType(SPECIES_SHUPPET, 0) == TYPE_GHOST);
WITH_CONFIG(CONFIG_GHOSTS_ESCAPE, GEN_6);
PLAYER(SPECIES_SHUPPET);
OPPONENT(SPECIES_DIGLETT) { Ability(ABILITY_ARENA_TRAP); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); }
} THEN {
u32 battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
EXPECT_EQ(IsAbilityPreventingEscape(battler), 0);
}
}

View File

@ -36,6 +36,7 @@ SINGLE_BATTLE_TEST("Chlorophyll doesn't double speed if Cloud Nine/Air Lock is o
SINGLE_BATTLE_TEST("Chlorophyll doesn't double speed if they have an Utility Umbrella")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA);
PLAYER(SPECIES_VENUSAUR) { Ability(ABILITY_CHLOROPHYLL); Speed(100); Item(ITEM_UTILITY_UMBRELLA); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(199); }
} WHEN {

View File

@ -88,7 +88,91 @@ SINGLE_BATTLE_TEST("Comatose Pokémon don't get poisoned by Toxic Spikes on swit
}
}
TO_DO_BATTLE_TEST("Comatose makes Rest fail")
TO_DO_BATTLE_TEST("Comatose isn't affected by Mold Breaker, Turboblaze or Teravolt")
TO_DO_BATTLE_TEST("Comatose isn't affected by Poison Touch + Sunsteel Strike")
TO_DO_BATTLE_TEST("Comatose boosts Dream Ball's multiplier")
SINGLE_BATTLE_TEST("Comatose makes Rest fail")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST);
PLAYER(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); HP(1); MaxHP(100); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_REST); }
} SCENE {
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, player);
HP_BAR(player);
}
} THEN {
EXPECT_EQ(player->hp, 1);
EXPECT_EQ(player->status1, STATUS1_NONE);
}
}
SINGLE_BATTLE_TEST("Comatose isn't affected by Mold Breaker, Turboblaze or Teravolt")
{
enum Ability ability;
u16 species;
PARAMETRIZE { ability = ABILITY_MOLD_BREAKER; species = SPECIES_PINSIR; }
PARAMETRIZE { ability = ABILITY_TURBOBLAZE; species = SPECIES_RESHIRAM; }
PARAMETRIZE { ability = ABILITY_TERAVOLT; species = SPECIES_ZEKROM; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_TOXIC) == EFFECT_NON_VOLATILE_STATUS);
ASSUME(GetMoveNonVolatileStatus(MOVE_TOXIC) == MOVE_EFFECT_TOXIC);
PLAYER(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); }
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { MOVE(opponent, MOVE_TOXIC); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, opponent);
ABILITY_POPUP(player, ABILITY_COMATOSE);
MESSAGE("It doesn't affect Komala…");
} THEN {
EXPECT_EQ(player->status1, STATUS1_NONE);
}
}
SINGLE_BATTLE_TEST("Comatose isn't affected by Poison Touch + Sunsteel Strike")
{
GIVEN {
ASSUME(MoveIgnoresTargetAbility(MOVE_SUNSTEEL_STRIKE));
ASSUME(MoveMakesContact(MOVE_SUNSTEEL_STRIKE));
PLAYER(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); }
OPPONENT(SPECIES_CROAGUNK) { Ability(ABILITY_POISON_TOUCH); }
} WHEN {
TURN { MOVE(opponent, MOVE_SUNSTEEL_STRIKE, WITH_RNG(RNG_POISON_TOUCH, 1)); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNSTEEL_STRIKE, opponent);
HP_BAR(player);
NOT STATUS_ICON(player, poison: TRUE);
} THEN {
EXPECT_EQ(player->status1, STATUS1_NONE);
}
}
WILD_BATTLE_TEST("Comatose boosts Dream Ball's multiplier")
{
enum Ability ability;
u16 species;
bool32 shouldCatch;
const u16 rng = 50000;
PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; shouldCatch = TRUE; }
PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; shouldCatch = FALSE; }
GIVEN {
ASSUME(B_DREAM_BALL_MODIFIER >= GEN_8);
ASSUME(gSpeciesInfo[species].catchRate == 45);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(species) { Ability(ability); MaxHP(100); HP(1); }
} WHEN {
TURN { USE_ITEM(player, ITEM_DREAM_BALL, WITH_RNG(RNG_BALLTHROW_SHAKE, rng)); }
} SCENE {
ANIMATION(ANIM_TYPE_SPECIAL, B_ANIM_BALL_THROW, player);
} THEN {
if (shouldCatch)
EXPECT_EQ(gBattleResults.caughtMonSpecies, species);
else
EXPECT_EQ(gBattleResults.caughtMonSpecies, SPECIES_NONE);
}
}

View File

@ -269,4 +269,22 @@ AI_SINGLE_BATTLE_TEST("AI sees Contrary-effected moves correctly in MoveEffectIn
}
}
TO_DO_BATTLE_TEST("Contrary does not invert stat changes that have been Baton-passed")
SINGLE_BATTLE_TEST("Contrary does not invert stat changes that have been Baton-passed")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SNIVY) { Ability(ABILITY_CONTRARY); }
} WHEN {
TURN { MOVE(opponent, MOVE_SWORDS_DANCE); }
TURN { MOVE(opponent, MOVE_BATON_PASS); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_BATON_PASS, opponent);
MESSAGE("2 sent out Snivy!");
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
}
}

View File

@ -119,5 +119,60 @@ DOUBLE_BATTLE_TEST("Costar copies an ally's Dragon Cheer critical hit boost")
}
// Copy from Ruin ability tests
TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Player");
TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Opponent");
DOUBLE_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Player")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
PLAYER(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(opponentLeft, MOVE_EXPLOSION);
SEND_OUT(playerLeft, 2);
SEND_OUT(opponentLeft, 2);
SEND_OUT(playerRight, 3);
SEND_OUT(opponentRight, 3);
}
} SCENE {
MESSAGE("The opposing Wobbuffet used Explosion!");
ABILITY_POPUP(playerLeft, ABILITY_INTREPID_SWORD);
MESSAGE("Zacian's Intrepid Sword raised its Attack!");
ABILITY_POPUP(playerRight, ABILITY_COSTAR);
MESSAGE("Flamigo copied Zacian's stat changes!");
}
}
DOUBLE_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Opponent")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
OPPONENT(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); }
} WHEN {
TURN {
MOVE(playerLeft, MOVE_EXPLOSION);
SEND_OUT(playerLeft, 2);
SEND_OUT(opponentLeft, 2);
SEND_OUT(playerRight, 3);
SEND_OUT(opponentRight, 3);
}
} SCENE {
MESSAGE("Wobbuffet used Explosion!");
ABILITY_POPUP(opponentLeft, ABILITY_INTREPID_SWORD);
MESSAGE("The opposing Zacian's Intrepid Sword raised its Attack!");
ABILITY_POPUP(opponentRight, ABILITY_COSTAR);
MESSAGE("The opposing Flamigo copied the opposing Zacian's stat changes!");
}
}

View File

@ -48,4 +48,28 @@ SINGLE_BATTLE_TEST("Cud Chew will activate Oran Berry effect again on the next t
}
}
TO_DO_BATTLE_TEST("Cud Chew will activate Lum Berry effect again on the next turn")
SINGLE_BATTLE_TEST("Cud Chew will activate Lum Berry effect again on the next turn")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_LUM_BERRY].holdEffect == HOLD_EFFECT_CURE_STATUS);
ASSUME(GetMoveEffect(MOVE_THUNDER_WAVE) == EFFECT_NON_VOLATILE_STATUS);
ASSUME(GetMoveNonVolatileStatus(MOVE_THUNDER_WAVE) == MOVE_EFFECT_PARALYSIS);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_TAUROS_PALDEA_COMBAT) { Ability(ABILITY_CUD_CHEW); Item(ITEM_LUM_BERRY); }
} WHEN {
TURN { MOVE(player, MOVE_THUNDER_WAVE); }
TURN { MOVE(player, MOVE_THUNDER_WAVE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, player);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponent);
STATUS_ICON(opponent, paralysis: TRUE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
STATUS_ICON(opponent, paralysis: FALSE);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, player);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponent);
STATUS_ICON(opponent, paralysis: TRUE);
ABILITY_POPUP(opponent, ABILITY_CUD_CHEW);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
STATUS_ICON(opponent, paralysis: FALSE);
}
}

View File

@ -87,6 +87,46 @@ SINGLE_BATTLE_TEST("Cursed Body does not stop a multistrike move mid-execution")
}
}
TO_DO_BATTLE_TEST("Cursed Body disables the move that called another move instead of the called move")
TO_DO_BATTLE_TEST("Cursed Body disables damaging Z-Moves, but not the base move") // Rotom Powers can restore Z-Moves
TO_DO_BATTLE_TEST("Cursed Body disables the base move of a status Z-Move")
SINGLE_BATTLE_TEST("Cursed Body disables the move that called another move instead of the called move")
{
PASSES_RANDOMLY(3, 10, RNG_CURSED_BODY);
GIVEN {
ASSUME(GetMoveEffect(MOVE_SLEEP_TALK) == EFFECT_SLEEP_TALK);
ASSUME(GetMoveType(MOVE_SHADOW_BALL) == TYPE_GHOST);
ASSUME(IsMoveSleepTalkBanned(MOVE_FLY));
ASSUME(IsMoveSleepTalkBanned(MOVE_DIG));
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); Moves(MOVE_SLEEP_TALK, MOVE_SHADOW_BALL, MOVE_FLY, MOVE_DIG); }
OPPONENT(SPECIES_FRILLISH) { Ability(ABILITY_CURSED_BODY); }
} WHEN {
TURN { MOVE(player, MOVE_SLEEP_TALK); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SLEEP_TALK, player);
ABILITY_POPUP(opponent, ABILITY_CURSED_BODY);
MESSAGE("Wobbuffet's Sleep Talk was disabled by the opposing Frillish's Cursed Body!");
} THEN {
EXPECT_EQ(gDisableStructs[B_POSITION_PLAYER_LEFT].disabledMove, MOVE_SLEEP_TALK);
}
}
SINGLE_BATTLE_TEST("Cursed Body disables the base move of a status Z-Move")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_NATURE_POWER) == EFFECT_NATURE_POWER);
ASSUME(GetMoveEffect(MOVE_ELECTRIC_TERRAIN) == EFFECT_ELECTRIC_TERRAIN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); }
OPPONENT(SPECIES_FRILLISH) { Ability(ABILITY_CURSED_BODY); }
} WHEN {
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_NATURE_POWER, gimmick: GIMMICK_Z_MOVE, WITH_RNG(RNG_CURSED_BODY, 1)); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ZMOVE_ACTIVATE, player);
HP_BAR(opponent);
ABILITY_POPUP(opponent, ABILITY_CURSED_BODY);
MESSAGE("Wobbuffet's Nature Power was disabled by the opposing Frillish's Cursed Body!");
} THEN {
EXPECT_EQ(gDisableStructs[B_POSITION_PLAYER_LEFT].disabledMove, MOVE_NATURE_POWER);
}
}
TO_DO_BATTLE_TEST("Cursed Body disables damaging Z-Moves, but not the base move")

View File

@ -1,5 +1,6 @@
#include "global.h"
#include "test/battle.h"
#include "constants/battle_z_move_effects.h"
SINGLE_BATTLE_TEST("Dancer can copy a dance move immediately after it was used and allow the user of Dancer to still use its move")
{
@ -79,8 +80,59 @@ DOUBLE_BATTLE_TEST("Dancer triggers from slowest to fastest")
}
}
TO_DO_BATTLE_TEST("Dancer triggers from slowest to fastest during Trick Room")
TO_DO_BATTLE_TEST("Dancer triggering ignores Lagging Tail")
DOUBLE_BATTLE_TEST("Dancer triggers from slowest to fastest during Trick Room")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_TRICK_ROOM) == EFFECT_TRICK_ROOM);
ASSUME(IsDanceMove(MOVE_DRAGON_DANCE));
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); }
PLAYER(SPECIES_WOBBUFFET) { Speed(1); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(20); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(5); }
} WHEN {
TURN { MOVE(playerRight, MOVE_TRICK_ROOM); }
TURN { MOVE(playerRight, MOVE_DRAGON_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK_ROOM, playerRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerRight);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
ABILITY_POPUP(opponentRight, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, opponentRight);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
ABILITY_POPUP(playerLeft, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
ABILITY_POPUP(opponentLeft, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, opponentLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
}
}
DOUBLE_BATTLE_TEST("Dancer triggering ignores Lagging Tail")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_DRAGON_DANCE));
ASSUME(gItemsInfo[ITEM_LAGGING_TAIL].holdEffect == HOLD_EFFECT_LAGGING_TAIL);
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); Item(ITEM_LAGGING_TAIL); }
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(5); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(20); }
} WHEN {
TURN { MOVE(playerRight, MOVE_DRAGON_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerRight);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
ABILITY_POPUP(opponentLeft, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, opponentLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
ABILITY_POPUP(playerLeft, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
ABILITY_POPUP(opponentRight, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, opponentRight);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
}
}
SINGLE_BATTLE_TEST("Dancer doesn't trigger if the original user flinches")
{
@ -194,8 +246,54 @@ DOUBLE_BATTLE_TEST("Dancer doesn't trigger on a snatched move")
}
}
TO_DO_BATTLE_TEST("Dancer-called moves can be snatched")
TO_DO_BATTLE_TEST("Dancer-called moves can be reflected by Magic Bounce/Coat")
DOUBLE_BATTLE_TEST("Dancer doesn't trigger when an ally snatches the move")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_DRAGON_DANCE));
ASSUME(GetMoveEffect(MOVE_SNATCH) == EFFECT_SNATCH);
ASSUME(MoveCanBeSnatched(MOVE_DRAGON_DANCE));
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
PLAYER(SPECIES_WOBBUFFET) { Speed(20); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_SNATCH); MOVE(playerRight, MOVE_DRAGON_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SNATCH, playerLeft);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
NONE_OF {
ABILITY_POPUP(opponentLeft, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, opponentLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
}
} THEN {
EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
EXPECT_EQ(playerLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Dancer-called moves can be reflected by Magic Bounce")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_FEATHER_DANCE));
PLAYER(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); }
} WHEN {
TURN { MOVE(player, MOVE_FEATHER_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FEATHER_DANCE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
ABILITY_POPUP(player, ABILITY_MAGIC_BOUNCE);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_FEATHER_DANCE, opponent);
MESSAGE("The opposing Oricorio's Feather Dance was bounced back by Espeon's Magic Bounce!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FEATHER_DANCE, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 4);
}
}
DOUBLE_BATTLE_TEST("Dancer triggers on Instructed dance moves")
{
@ -252,8 +350,61 @@ DOUBLE_BATTLE_TEST("Dancer-called move doesn't update move to be Instructed")
}
}
TO_DO_BATTLE_TEST("Dancer-called moves doesn't update move to be called by Mimick")
TO_DO_BATTLE_TEST("Dancer-called moves doesn't update move to be called by Mirror Move")
DOUBLE_BATTLE_TEST("Dancer-called moves do not update move to be called by Mimic")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_DRAGON_DANCE));
ASSUME(GetMoveEffect(MOVE_MIMIC) == EFFECT_MIMIC);
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(50); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
} WHEN {
TURN {
MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft);
MOVE(playerRight, MOVE_DRAGON_DANCE);
MOVE(playerLeft, MOVE_MIMIC, target: opponentLeft);
}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft);
HP_BAR(playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerRight);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
ABILITY_POPUP(opponentLeft, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, opponentLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIMIC, playerLeft);
MESSAGE("Wobbuffet learned Scratch!");
NOT MESSAGE("Wobbuffet learned Dragon Dance!");
}
}
DOUBLE_BATTLE_TEST("Dancer-called moves doesn't update move to be called by Mirror Move")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_DRAGON_DANCE));
ASSUME(GetMoveEffect(MOVE_MIRROR_MOVE) == EFFECT_MIRROR_MOVE);
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(50); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
} WHEN {
TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft); MOVE(playerRight, MOVE_DRAGON_DANCE); }
TURN { MOVE(playerLeft, MOVE_MIRROR_MOVE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft);
HP_BAR(playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerRight);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
ABILITY_POPUP(opponentLeft, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, opponentLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
MESSAGE("Wobbuffet used Mirror Move!");
MESSAGE("Wobbuffet used Scratch!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerLeft);
NOT MESSAGE("Wobbuffet used Dragon Dance!");
}
}
DOUBLE_BATTLE_TEST("Dancer doesn't call a move that didn't execute due to Powder")
{
@ -306,7 +457,7 @@ DOUBLE_BATTLE_TEST("Dancer still activates after Red Card")
DOUBLE_BATTLE_TEST("Dancer still activate after Red Card even if blocked by Suction Cups")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_SUCTION_CUPS); }
PLAYER(SPECIES_OCTILLERY) { Ability(ABILITY_SUCTION_CUPS); }
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); }
PLAYER(SPECIES_CHANSEY);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
@ -315,13 +466,13 @@ DOUBLE_BATTLE_TEST("Dancer still activate after Red Card even if blocked by Suct
} WHEN {
TURN { MOVE(playerLeft, MOVE_FIERY_DANCE, target: opponentLeft); }
} SCENE {
MESSAGE("Wobbuffet used Fiery Dance!");
MESSAGE("Octillery used Fiery Dance!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIERY_DANCE, playerLeft);
HP_BAR(opponentLeft);
// red card trigger
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentLeft);
MESSAGE("The opposing Wobbuffet held up its Red Card against Wobbuffet!");
MESSAGE("Wobbuffet anchors itself with Suction Cups!");
MESSAGE("The opposing Wobbuffet held up its Red Card against Octillery!");
MESSAGE("Octillery anchors itself with Suction Cups!");
NOT MESSAGE("Chansey was dragged out!");
// Dancer
ABILITY_POPUP(playerRight, ABILITY_DANCER);
@ -364,15 +515,292 @@ DOUBLE_BATTLE_TEST("Dancer correctly restores move targets")
}
}
TO_DO_BATTLE_TEST("Dancer-called damaging moves are considered for Counter/Mirror Coat/Metal Burst")
DOUBLE_BATTLE_TEST("Dancer-called damaging moves are considered for Counter/Mirror Coat/Metal Burst")
{
u32 danceMove, retaliateMove;
TO_DO_BATTLE_TEST("Dancer copies a status Z-Move's base move without gaining an additional Z-Power effect")
TO_DO_BATTLE_TEST("Dancer user may hit itself in confusion instead of copying a move if it's confused")
TO_DO_BATTLE_TEST("Dancer tries to copy a move but fails if it's being forced into a different move - Rampage move") // Test with Petal Dance, Thrash
TO_DO_BATTLE_TEST("Dancer tries to copy a move but fails if it's being forced into a different move - Rollout")
TO_DO_BATTLE_TEST("Dancer tries to copy a move but fails if it's being forced into a different move - Choice items")
TO_DO_BATTLE_TEST("Dancer tries to copy a move but fails if it's being forced into a different move - Encore")
TO_DO_BATTLE_TEST("Dancer tries to copy a status move but fails if it's under Taunt's effect")
TO_DO_BATTLE_TEST("Dancer can still copy status moves if the user is holding an Assault Vest")
TO_DO_BATTLE_TEST("Dancer copies Lunar Dance after the original user faints, but before the replacement is sent out")
TO_DO_BATTLE_TEST("Dancer doesn't activate Feather Dance if it was reflected by Magic Bounce/Coat")
PARAMETRIZE { danceMove = MOVE_AQUA_STEP; retaliateMove = MOVE_COUNTER; }
PARAMETRIZE { danceMove = MOVE_FIERY_DANCE; retaliateMove = MOVE_MIRROR_COAT; }
PARAMETRIZE { danceMove = MOVE_FIERY_DANCE; retaliateMove = MOVE_METAL_BURST; }
GIVEN {
ASSUME(IsDanceMove(danceMove));
if (retaliateMove == MOVE_COUNTER)
ASSUME(GetMoveCategory(danceMove) == DAMAGE_CATEGORY_PHYSICAL);
else if (retaliateMove == MOVE_MIRROR_COAT)
ASSUME(GetMoveCategory(danceMove) == DAMAGE_CATEGORY_SPECIAL);
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(20); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
} WHEN {
TURN { MOVE(playerLeft, danceMove, target: opponentLeft); MOVE(opponentLeft, retaliateMove); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, danceMove, playerLeft);
HP_BAR(opponentLeft);
ABILITY_POPUP(playerRight, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, danceMove, playerRight);
HP_BAR(opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, retaliateMove, opponentLeft);
HP_BAR(playerRight);
NOT HP_BAR(playerLeft);
}
}
SINGLE_BATTLE_TEST("Dancer copies a status Z-Move's base move without gaining an additional Z-Power effect")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_SWORDS_DANCE));
ASSUME(GetMoveEffect(MOVE_SCREECH) == EFFECT_DEFENSE_DOWN_2);
ASSUME(GetMoveZEffect(MOVE_SWORDS_DANCE) == Z_EFFECT_RESET_STATS);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); }
} WHEN {
TURN { MOVE(player, MOVE_SCREECH); }
TURN { MOVE(player, MOVE_SWORDS_DANCE, gimmick: GIMMICK_Z_MOVE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCREECH, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ZMOVE_ACTIVATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
} THEN {
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE - 2);
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
}
}
SINGLE_BATTLE_TEST("Dancer user may hit itself in confusion instead of copying a move if it's confused")
{
u32 genConfig, pctChance;
PARAMETRIZE { genConfig = GEN_6; pctChance = 50; }
PARAMETRIZE { genConfig = GEN_7; pctChance = 33; }
PASSES_RANDOMLY(pctChance, 100, RNG_CONFUSION);
GIVEN {
WITH_CONFIG(CONFIG_CONFUSION_SELF_DMG_CHANCE, genConfig);
ASSUME(IsDanceMove(MOVE_DRAGON_DANCE));
ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE);
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); }
} WHEN {
TURN { MOVE(player, MOVE_CONFUSE_RAY); }
TURN { MOVE(player, MOVE_DRAGON_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, player);
MESSAGE("The opposing Oricorio became confused!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
MESSAGE("The opposing Oricorio is confused!");
MESSAGE("It hurt itself in its confusion!");
HP_BAR(opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
}
}
}
SINGLE_BATTLE_TEST("Dancer can still copy a move even if it's being forced into a different move - Rampage move")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_SWORDS_DANCE));
ASSUME(IsDanceMove(MOVE_PETAL_DANCE));
ASSUME(MoveHasAdditionalEffectSelf(MOVE_PETAL_DANCE, MOVE_EFFECT_THRASH));
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); }
} WHEN {
TURN { MOVE(opponent, MOVE_PETAL_DANCE); }
TURN { MOVE(player, MOVE_SWORDS_DANCE); FORCED_MOVE(opponent); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_DANCE, opponent);
HP_BAR(player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
}
}
SINGLE_BATTLE_TEST("Dancer can still copy a move even if it's being forced into a different move - Rollout")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_SWORDS_DANCE));
ASSUME(GetMoveEffect(MOVE_ROLLOUT) == EFFECT_ROLLOUT);
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); }
} WHEN {
TURN { MOVE(opponent, MOVE_ROLLOUT); }
TURN { MOVE(player, MOVE_SWORDS_DANCE); FORCED_MOVE(opponent); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROLLOUT, opponent);
HP_BAR(player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
}
}
SINGLE_BATTLE_TEST("Dancer can still copy a move even if it's being forced into a different move - Choice items")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_SWORDS_DANCE));
ASSUME(GetItemHoldEffect(ITEM_CHOICE_BAND) == HOLD_EFFECT_CHOICE_BAND);
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); Item(ITEM_CHOICE_BAND); }
} WHEN {
TURN { MOVE(opponent, MOVE_SCRATCH); }
TURN { MOVE(player, MOVE_SWORDS_DANCE); MOVE(opponent, MOVE_SCRATCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent);
HP_BAR(player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
}
}
SINGLE_BATTLE_TEST("Dancer can still copy a move even if it's being forced into a different move - Encore")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_SWORDS_DANCE));
ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE);
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); }
} WHEN {
TURN { MOVE(opponent, MOVE_SCRATCH); }
TURN { MOVE(player, MOVE_ENCORE, target: opponent); MOVE(opponent, MOVE_SCRATCH); }
TURN { MOVE(player, MOVE_SWORDS_DANCE); MOVE(opponent, MOVE_SCRATCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent);
HP_BAR(player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, player);
MESSAGE("The opposing Oricorio must do an encore!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
}
}
SINGLE_BATTLE_TEST("Dancer tries to copy a status move but fails if it's under Taunt's effect")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_SWORDS_DANCE));
ASSUME(GetMoveEffect(MOVE_TAUNT) == EFFECT_TAUNT);
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); }
} WHEN {
TURN { MOVE(player, MOVE_TAUNT); }
TURN { MOVE(player, MOVE_SWORDS_DANCE); MOVE(opponent, MOVE_SCRATCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TAUNT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
}
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
}
}
SINGLE_BATTLE_TEST("Dancer can still copy status moves if the user is holding an Assault Vest")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_SWORDS_DANCE));
ASSUME(GetItemHoldEffect(ITEM_ASSAULT_VEST) == HOLD_EFFECT_ASSAULT_VEST);
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); Item(ITEM_ASSAULT_VEST); }
} WHEN {
TURN { MOVE(player, MOVE_SWORDS_DANCE); MOVE(opponent, MOVE_SCRATCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
}
}
DOUBLE_BATTLE_TEST("Dancer copies Lunar Dance after the original user faints, but before the replacement is sent out")
{
GIVEN {
WITH_CONFIG(CONFIG_HEALING_WISH_SWITCH, GEN_7);
ASSUME(GetMoveEffect(MOVE_LUNAR_DANCE) == EFFECT_LUNAR_DANCE);
PLAYER(SPECIES_WOBBUFFET) { Speed(50); }
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(20); }
PLAYER(SPECIES_WYNAUT) { Speed(5); }
PLAYER(SPECIES_CHANSEY) { Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_LUNAR_DANCE); SEND_OUT(playerLeft, 2); SEND_OUT(playerRight, 3); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_LUNAR_DANCE, playerLeft);
HP_BAR(playerLeft, hp: 0);
MESSAGE("Wobbuffet fainted!");
ABILITY_POPUP(playerRight, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_LUNAR_DANCE, playerRight);
HP_BAR(playerRight, hp: 0);
MESSAGE("Oricorio fainted!");
SEND_IN_MESSAGE("Wynaut");
SEND_IN_MESSAGE("Chansey");
}
}
DOUBLE_BATTLE_TEST("Dancer doesn't activate Feather Dance if it was reflected by Magic Bounce/Coat")
{
bool32 useMagicCoat;
PARAMETRIZE { useMagicCoat = FALSE; }
PARAMETRIZE { useMagicCoat = TRUE; }
GIVEN {
ASSUME(IsDanceMove(MOVE_FEATHER_DANCE));
ASSUME(GetMoveEffect(MOVE_MAGIC_COAT) == EFFECT_MAGIC_COAT);
PLAYER(SPECIES_WOBBUFFET) { Speed(20); }
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
if (useMagicCoat)
OPPONENT(SPECIES_WOBBUFFET) { Speed(30); }
else
OPPONENT(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE); Speed(30); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(5); }
} WHEN {
if (useMagicCoat)
TURN { MOVE(opponentLeft, MOVE_MAGIC_COAT); MOVE(playerLeft, MOVE_FEATHER_DANCE, target: opponentLeft); }
else
TURN { MOVE(playerLeft, MOVE_FEATHER_DANCE, target: opponentLeft); }
} SCENE {
if (useMagicCoat)
ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGIC_COAT, opponentLeft);
else
ABILITY_POPUP(opponentLeft, ABILITY_MAGIC_BOUNCE);
NONE_OF {
ABILITY_POPUP(opponentRight, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_FEATHER_DANCE, opponentRight);
}
} THEN {
EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 2);
}
}

View File

@ -1,5 +1,6 @@
#include "global.h"
#include "test/battle.h"
#include "constants/battle_z_move_effects.h"
ASSUMPTIONS
{
@ -124,11 +125,154 @@ SINGLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail prevent Protean act
// Listed on Bulbapedia as "Moves that target all Pokémon (except Perish Song, Flower Shield, and Rototiller),"
// Despite the fact that there's only 2 remaining moves from that list, being Haze and Teatime
TO_DO_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block Haze")
TO_DO_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block Teatime")
SINGLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block Haze")
{
u32 species;
enum Ability ability;
TO_DO_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block a move's Z-Status effect") // Z-Baby-Doll eyes increases Def but doesn't reduce Atk
TO_DO_BATTLE_TEST("Mold Breaker ignores Dazzling, Queenly Majesty and Armor Tail")
TO_DO_BATTLE_TEST("Instruct-called moves keep their priority, which is considered for Dazzling, Queenly Majesty and Armor Tail")
PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; }
PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; }
PARAMETRIZE { species = SPECIES_TSAREENA; ability = ABILITY_QUEENLY_MAJESTY; }
TO_DO_BATTLE_TEST(" Dazzling, Queenly Majesty and Armor Tail do not block high-priority moves called by other moves") // Metronome, Assist, Nature Power, etc.
GIVEN {
ASSUME(GetMoveEffect(MOVE_HAZE) == EFFECT_HAZE);
PLAYER(SPECIES_MURKROW) { Ability(ABILITY_PRANKSTER); }
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { MOVE(player, MOVE_SWORDS_DANCE); }
TURN { MOVE(player, MOVE_HAZE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_HAZE, player);
NOT ABILITY_POPUP(opponent, ability);
} THEN {
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
}
}
SINGLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block Teatime")
{
u32 species;
enum Ability ability;
PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; }
PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; }
PARAMETRIZE { species = SPECIES_TSAREENA; ability = ABILITY_QUEENLY_MAJESTY; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_TEATIME) == EFFECT_TEATIME);
ASSUME(GetItemHoldEffect(ITEM_ORAN_BERRY) == HOLD_EFFECT_RESTORE_HP);
PLAYER(SPECIES_MURKROW) { Ability(ABILITY_PRANKSTER); Item(ITEM_ORAN_BERRY); HP(1); MaxHP(100); }
OPPONENT(species) { Ability(ability); Item(ITEM_ORAN_BERRY); HP(1); MaxHP(100); }
} WHEN {
TURN { MOVE(player, MOVE_TEATIME); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TEATIME, player);
NOT ABILITY_POPUP(opponent, ability);
} THEN {
EXPECT_EQ(player->item, ITEM_NONE);
EXPECT_EQ(opponent->item, ITEM_NONE);
}
}
SINGLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block a move's Z-Status effect")
{
u32 species;
enum Ability ability;
PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; }
PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; }
PARAMETRIZE { species = SPECIES_TSAREENA; ability = ABILITY_QUEENLY_MAJESTY; }
GIVEN {
ASSUME(GetMoveZEffect(MOVE_BABY_DOLL_EYES) == Z_EFFECT_DEF_UP_1);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_FAIRIUM_Z); }
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { MOVE(player, MOVE_BABY_DOLL_EYES, gimmick: GIMMICK_Z_MOVE); }
} SCENE {
ABILITY_POPUP(opponent, ability);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_BABY_DOLL_EYES, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1);
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
}
}
SINGLE_BATTLE_TEST("Mold Breaker ignores Dazzling, Queenly Majesty and Armor Tail")
{
u32 species;
enum Ability ability;
PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; }
PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; }
PARAMETRIZE { species = SPECIES_TSAREENA; ability = ABILITY_QUEENLY_MAJESTY; }
GIVEN {
PLAYER(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); }
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { MOVE(player, MOVE_QUICK_ATTACK); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, player);
HP_BAR(opponent);
NOT ABILITY_POPUP(opponent, ability);
}
}
DOUBLE_BATTLE_TEST("Instruct-called moves keep their priority, which is considered for Dazzling, Queenly Majesty and Armor Tail")
{
u32 species;
enum Ability ability;
PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; }
PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; }
PARAMETRIZE { species = SPECIES_TSAREENA; ability = ABILITY_QUEENLY_MAJESTY; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_INSTRUCT) == EFFECT_INSTRUCT);
ASSUME(GetItemHoldEffect(ITEM_EJECT_BUTTON) == HOLD_EFFECT_EJECT_BUTTON);
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
PLAYER(SPECIES_WOBBUFFET) { Speed(30); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_BUTTON); Speed(20); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
OPPONENT(species) { Ability(ability); Speed(15); }
} WHEN {
TURN { MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); MOVE(playerLeft, MOVE_INSTRUCT, target: playerRight); SEND_OUT(opponentLeft, 2); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, playerRight);
HP_BAR(opponentLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentLeft);
MESSAGE("The opposing Wobbuffet is switched out with the Eject Button!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_INSTRUCT, playerLeft);
ABILITY_POPUP(opponentLeft, ability);
MESSAGE("Wobbuffet cannot use Quick Attack!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, playerRight);
}
}
SINGLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail do not block high-priority moves called by other moves")
{
u32 species;
enum Ability ability;
PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; }
PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; }
PARAMETRIZE { species = SPECIES_TSAREENA; ability = ABILITY_QUEENLY_MAJESTY; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_METRONOME) == EFFECT_METRONOME);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { MOVE(player, MOVE_METRONOME, WITH_RNG(RNG_METRONOME, MOVE_QUICK_ATTACK)); }
} SCENE {
MESSAGE("Wobbuffet used Metronome!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_METRONOME, player);
MESSAGE("Waggling a finger let it use Quick Attack!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, player);
HP_BAR(opponent);
NOT ABILITY_POPUP(opponent, ability);
}
}

View File

@ -104,7 +104,24 @@ SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from secondary damage without
}
}
TO_DO_BATTLE_TEST("Disguised Mimikyu takes damage from secondary damage without breaking the disguise - Weather")
SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from secondary damage without breaking the disguise - Weather")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SANDSTORM) == EFFECT_SANDSTORM);
ASSUME(GetSpeciesType(SPECIES_GEODUDE, 0) == TYPE_ROCK || GetSpeciesType(SPECIES_GEODUDE, 1) == TYPE_ROCK);
PLAYER(SPECIES_GEODUDE);
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); }
OPPONENT(SPECIES_GEODUDE);
} WHEN {
TURN { MOVE(opponent, MOVE_SANDSTORM); }
TURN { SWITCH(player, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SANDSTORM, opponent);
HP_BAR(player);
} THEN {
EXPECT_EQ(player->species, SPECIES_MIMIKYU_DISGUISED);
}
}
SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from Rocky Helmet without breaking the disguise")
{

View File

@ -15,7 +15,28 @@ SINGLE_BATTLE_TEST("Dry Skin causes 1/8th Max HP damage in Sun")
}
}
TO_DO_BATTLE_TEST("Dry Skin doesn't get damaged in Sun if Cloud Nine/Air Lock is on the field");
SINGLE_BATTLE_TEST("Dry Skin doesn't get damaged in Sun if Cloud Nine/Air Lock is on the field")
{
u16 species;
enum Ability ability;
PARAMETRIZE { species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; }
PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; }
GIVEN {
PLAYER(SPECIES_PARASECT) { Ability(ABILITY_DRY_SKIN); HP(100); MaxHP(200); }
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player);
NONE_OF {
ABILITY_POPUP(player, ABILITY_DRY_SKIN);
HP_BAR(player);
MESSAGE("Parasect's Dry Skin takes its toll!");
}
}
}
SINGLE_BATTLE_TEST("Dry Skin heals 1/8th Max HP in Rain")
{
@ -31,7 +52,28 @@ SINGLE_BATTLE_TEST("Dry Skin heals 1/8th Max HP in Rain")
}
}
TO_DO_BATTLE_TEST("Dry Skin doesn't heal in Rain if Cloud Nine/Air Lock is on the field");
SINGLE_BATTLE_TEST("Dry Skin doesn't heal in Rain if Cloud Nine/Air Lock is on the field")
{
u16 species;
enum Ability ability;
PARAMETRIZE { species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; }
PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; }
GIVEN {
PLAYER(SPECIES_PARASECT) { Ability(ABILITY_DRY_SKIN); HP(100); MaxHP(200); }
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { MOVE(player, MOVE_RAIN_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAIN_DANCE, player);
NONE_OF {
ABILITY_POPUP(player, ABILITY_DRY_SKIN);
HP_BAR(player);
MESSAGE("Parasect's Dry Skin restored its HP a little!");
}
}
}
SINGLE_BATTLE_TEST("Dry Skin increases damage taken from Fire-type moves by 25%", s16 damage)
{

View File

@ -17,7 +17,28 @@ SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim in harsh sunlight")
}
}
TO_DO_BATTLE_TEST("Flower Gift doesn't transform Cherrim if Cloud Nine/Air Lock is on the field");
SINGLE_BATTLE_TEST("Flower Gift doesn't transform Cherrim if Cloud Nine/Air Lock is on the field")
{
u32 species = 0;
enum Ability ability = 0;
PARAMETRIZE { species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; }
PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; }
GIVEN {
PLAYER(SPECIES_CHERRIM_OVERCAST) { Ability(ABILITY_FLOWER_GIFT); }
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { MOVE(opponent, MOVE_SUNNY_DAY); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent);
NONE_OF {
ABILITY_POPUP(player, ABILITY_FLOWER_GIFT);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
MESSAGE("Cherrim transformed!");
}
} THEN {
EXPECT_EQ(player->species, SPECIES_CHERRIM_OVERCAST);
}
}
SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim back to normal when weather changes")
{
@ -219,4 +240,19 @@ DOUBLE_BATTLE_TEST("Flower Gift reverts Cherrim back after Teraform Zero clears
}
}
TO_DO_BATTLE_TEST("Flower Gift does not transform Cherrim back to normal when suppressed if Cherrim is Dynamaxed");
SINGLE_BATTLE_TEST("Flower Gift does not transform Cherrim back to normal when suppressed if Cherrim is Dynamaxed")
{
GIVEN {
ASSUME(B_WEATHER_FORMS >= GEN_5);
ASSUME(GetMoveEffect(MOVE_GASTRO_ACID) == EFFECT_GASTRO_ACID);
PLAYER(SPECIES_CHERRIM_OVERCAST) { Ability(ABILITY_FLOWER_GIFT); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SUNNY_DAY); }
TURN { MOVE(player, MOVE_SCRATCH, gimmick: GIMMICK_DYNAMAX); }
TURN { MOVE(opponent, MOVE_GASTRO_ACID); }
} SCENE {
} THEN {
EXPECT_EQ(player->species, SPECIES_CHERRIM_SUNSHINE);
}
}

View File

@ -63,4 +63,22 @@ DOUBLE_BATTLE_TEST("Flower Veil prevents status on allied Grass-types - left tar
}
}
TO_DO_BATTLE_TEST("Flower Veil's stat reduction protection considers Contrary") // Eg. If a move would reduce stats due to Contrary, it will be protected by Mist.
DOUBLE_BATTLE_TEST("Flower Veil's stat reduction protection considers Contrary") // Eg. If a move would reduce stats due to Contrary, it will be protected by Mist.
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SWAGGER) == EFFECT_SWAGGER);
ASSUME(GetSpeciesType(SPECIES_SNIVY, 0) == TYPE_GRASS || GetSpeciesType(SPECIES_SNIVY, 1) == TYPE_GRASS);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_COMFEY) { Ability(ABILITY_FLOWER_VEIL); }
OPPONENT(SPECIES_SNIVY) { Ability(ABILITY_CONTRARY); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_SWAGGER, target: opponentRight); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWAGGER, playerLeft);
ABILITY_POPUP(opponentLeft, ABILITY_FLOWER_VEIL);
MESSAGE("The opposing Snivy surrounded itself with a veil of petals!");
} THEN {
EXPECT_EQ(opponentRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
}
}

View File

@ -173,6 +173,7 @@ SINGLE_BATTLE_TEST("Protosynthesis doesn't activate for a transformed battler")
SINGLE_BATTLE_TEST("Protosynthesis activates even if the Pokémon is holding an Utility Umbrella")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA);
PLAYER(SPECIES_GREAT_TUSK) { Ability(ABILITY_PROTOSYNTHESIS); Item(ITEM_UTILITY_UMBRELLA); }
OPPONENT(SPECIES_NINETALES) { Ability(ABILITY_DROUGHT); }
} WHEN {

View File

@ -1,6 +1,57 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Swift Swim doubles speed if it's raining");
TO_DO_BATTLE_TEST("Swift Swim doesn't double speed if Cloud Nine/Air Lock is on the field");
TO_DO_BATTLE_TEST("Swift Swim doesn't double speed if they have an Utility Umbrella");
SINGLE_BATTLE_TEST("Swift Swim doubles speed if it's raining")
{
GIVEN {
PLAYER(SPECIES_LUDICOLO) { Ability(ABILITY_SWIFT_SWIM); Speed(100); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(199); }
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_RAIN_DANCE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAIN_DANCE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
}
}
SINGLE_BATTLE_TEST("Swift Swim doesn't double speed if Cloud Nine/Air Lock is on the field")
{
u16 species;
enum Ability ability;
PARAMETRIZE { species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; }
PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; }
GIVEN {
PLAYER(SPECIES_LUDICOLO) { Ability(ABILITY_SWIFT_SWIM); Speed(100); }
OPPONENT(species) { Speed(199); Ability(ability); }
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_RAIN_DANCE); }
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAIN_DANCE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
}
}
SINGLE_BATTLE_TEST("Swift Swim doesn't double speed if they have an Utility Umbrella")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA);
PLAYER(SPECIES_LUDICOLO) { Ability(ABILITY_SWIFT_SWIM); Speed(100); Item(ITEM_UTILITY_UMBRELLA); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(199); }
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_RAIN_DANCE); }
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAIN_DANCE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
}
}

View File

@ -135,7 +135,26 @@ SINGLE_BATTLE_TEST("Chesto Berry cures sleep when Yawn takes effect")
}
}
TO_DO_BATTLE_TEST("Chesto and Lum Berries don't trigger if the holder has Comatose")
SINGLE_BATTLE_TEST("Chesto and Lum Berries don't trigger if the holder has Comatose")
{
u16 item;
PARAMETRIZE { item = ITEM_CHESTO_BERRY; }
PARAMETRIZE { item = ITEM_LUM_BERRY; }
GIVEN {
ASSUME(gItemsInfo[ITEM_CHESTO_BERRY].holdEffect == HOLD_EFFECT_CURE_SLP);
ASSUME(gItemsInfo[ITEM_LUM_BERRY].holdEffect == HOLD_EFFECT_CURE_STATUS);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); Item(item); }
} WHEN {
TURN { }
} SCENE {
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
} THEN {
EXPECT_EQ(opponent->item, item);
}
}
SINGLE_BATTLE_TEST("Cheri and Lum Berries cure paralysis")
{
@ -181,8 +200,7 @@ SINGLE_BATTLE_TEST("Perism and Lum Berries cure confusion")
SINGLE_BATTLE_TEST("Berry hold effect cures status if a Pokémon enters a battle")
{
u16 status;
u16 item;
u16 status, item;
PARAMETRIZE { status = STATUS1_BURN; item = ITEM_RAWST_BERRY; }
PARAMETRIZE { status = STATUS1_FREEZE; item = ITEM_ASPEAR_BERRY; }

View File

@ -35,6 +35,7 @@ SINGLE_BATTLE_TEST("Hydro Steam is affected by Utility Umbrella", s16 damage)
PARAMETRIZE { itemPlayer = ITEM_NONE; itemOpponent = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { itemPlayer = ITEM_UTILITY_UMBRELLA; itemOpponent = ITEM_UTILITY_UMBRELLA; }
GIVEN {
ASSUME(gItemsInfo[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA);
PLAYER(SPECIES_WOBBUFFET) { Item(itemPlayer); }
OPPONENT(SPECIES_WOBBUFFET) { Item(itemOpponent); }
} WHEN {

View File

@ -1,6 +1,42 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Mist (Move Effect) test titles")
SINGLE_BATTLE_TEST("Mist prevents stat reductions from opposing moves")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_MIST) == EFFECT_MIST);
ASSUME(GetMoveEffect(MOVE_GROWL) == EFFECT_ATTACK_DOWN);
PLAYER(SPECIES_WOBBUFFET) { Speed(20); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
} WHEN {
TURN { MOVE(player, MOVE_MIST); MOVE(opponent, MOVE_GROWL); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIST, player);
MESSAGE("Your team became shrouded in mist!");
MESSAGE("The opposing Wobbuffet used Growl!");
MESSAGE("Wobbuffet is protected by the mist!");
} THEN {
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
}
}
TO_DO_BATTLE_TEST("Mist's protection considers Contrary") // Eg. If a move would reduce stats due to Contrary, it will be protected by Mist.
SINGLE_BATTLE_TEST("Mist's protection considers Contrary") // Eg. If a move would reduce stats due to Contrary, it will be protected by Mist.
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_MIST) == EFFECT_MIST);
ASSUME(GetMoveEffect(MOVE_SWAGGER) == EFFECT_SWAGGER);
PLAYER(SPECIES_SNIVY) { Ability(ABILITY_CONTRARY); Speed(20); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
} WHEN {
TURN { MOVE(player, MOVE_MIST); MOVE(opponent, MOVE_SWAGGER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIST, player);
MESSAGE("Your team became shrouded in mist!");
MESSAGE("The opposing Wobbuffet used Swagger!");
MESSAGE("Snivy is protected by the mist!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player);
MESSAGE("Snivy became confused!");
} THEN {
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
}
}

View File

@ -1,6 +1,40 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Nightmare (Move Effect) test titles")
SINGLE_BATTLE_TEST("Nightmare damages sleeping targets at end of turn")
{
s16 damage;
TO_DO_BATTLE_TEST("Nightmare affects Pokémon with Comatose")
GIVEN {
ASSUME(GetMoveEffect(MOVE_NIGHTMARE) == EFFECT_NIGHTMARE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP_TURN(2)); MaxHP(160); HP(160); }
} WHEN {
TURN { MOVE(player, MOVE_NIGHTMARE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_NIGHTMARE, player);
MESSAGE("The opposing Wobbuffet began having a nightmare!");
HP_BAR(opponent, captureDamage: &damage);
} THEN {
EXPECT_EQ(damage, 40);
}
}
SINGLE_BATTLE_TEST("Nightmare affects Pokémon with Comatose")
{
s16 damage;
GIVEN {
ASSUME(GetMoveEffect(MOVE_NIGHTMARE) == EFFECT_NIGHTMARE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); MaxHP(160); HP(160); }
} WHEN {
TURN { MOVE(player, MOVE_NIGHTMARE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_NIGHTMARE, player);
MESSAGE("The opposing Komala began having a nightmare!");
HP_BAR(opponent, captureDamage: &damage);
} THEN {
EXPECT_EQ(damage, 40);
}
}

View File

@ -62,5 +62,37 @@ AI_DOUBLE_BATTLE_TEST("AI does not use Purify to heal an ally with Guts")
}
}
TO_DO_BATTLE_TEST("TODO: Write Purify (Move Effect) test titles")
TO_DO_BATTLE_TEST("Purify doesn't heal HP if the target has Comatose")
SINGLE_BATTLE_TEST("Purify cures the target's status and heals the user")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_PURIFY) == EFFECT_PURIFY);
PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(100); }
OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); }
} WHEN {
TURN { MOVE(player, MOVE_PURIFY); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_PURIFY, player);
STATUS_ICON(opponent, none: TRUE);
HP_BAR(player);
} THEN {
EXPECT_EQ(player->hp, player->maxHP);
EXPECT_EQ(opponent->status1, STATUS1_NONE);
}
}
SINGLE_BATTLE_TEST("Purify doesn't heal HP if the target has Comatose")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_PURIFY) == EFFECT_PURIFY);
PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(100); }
OPPONENT(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); }
} WHEN {
TURN { MOVE(player, MOVE_PURIFY); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURIFY, player);
MESSAGE("But it failed!");
NOT HP_BAR(player);
} THEN {
EXPECT_EQ(player->hp, 50);
}
}

View File

@ -56,6 +56,7 @@ SINGLE_BATTLE_TEST("Synthesis recovers regular amount in sandstorm if holding ut
PARAMETRIZE { item = ITEM_LIFE_ORB; }
PARAMETRIZE { item = ITEM_UTILITY_UMBRELLA; }
GIVEN {
ASSUME(gItemsInfo[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA);
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); Item(item); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {