Tests for 6 more abilities (#3399)

* Tests for 6 more abilities

* Fix most of Egg's comments

* Update Purifying Salt and Leaf Guard

* Parenthesis fixes
This commit is contained in:
Bassoonian 2023-10-13 20:50:48 +02:00 committed by GitHub
parent f5b149b971
commit 231ebea3f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 236 additions and 39 deletions

View File

@ -3853,6 +3853,7 @@ BattleScript_EffectRest::
jumpifuproarwakes BattleScript_RestCantSleep jumpifuproarwakes BattleScript_RestCantSleep
jumpifability BS_TARGET, ABILITY_INSOMNIA, BattleScript_InsomniaProtects jumpifability BS_TARGET, ABILITY_INSOMNIA, BattleScript_InsomniaProtects
jumpifability BS_TARGET, ABILITY_VITAL_SPIRIT, BattleScript_InsomniaProtects jumpifability BS_TARGET, ABILITY_VITAL_SPIRIT, BattleScript_InsomniaProtects
jumpifability BS_ATTACKER, ABILITY_PURIFYING_SALT, BattleScript_InsomniaProtects
.if B_LEAF_GUARD_PREVENTS_REST >= GEN_5 .if B_LEAF_GUARD_PREVENTS_REST >= GEN_5
jumpifleafguardprotected BS_TARGET, BattleScript_LeafGuardPreventsRest jumpifleafguardprotected BS_TARGET, BattleScript_LeafGuardPreventsRest
.endif .endif

View File

@ -92,6 +92,7 @@ enum RandomTag
RNG_TRI_ATTACK, RNG_TRI_ATTACK,
RNG_TRIPLE_ARROWS_DEFENSE_DOWN, RNG_TRIPLE_ARROWS_DEFENSE_DOWN,
RNG_TRIPLE_ARROWS_FLINCH, RNG_TRIPLE_ARROWS_FLINCH,
RNG_QUICK_DRAW,
}; };
#define RandomWeighted(tag, ...) \ #define RandomWeighted(tag, ...) \

View File

@ -4745,7 +4745,7 @@ u32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov
// Battler 1 // Battler 1
// Quick Draw // Quick Draw
if (!ignoreChosenMoves && ability1 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler1]) && Random() % 100 < 30) if (!ignoreChosenMoves && ability1 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler1]) && RandomPercentage(RNG_QUICK_DRAW, 30))
gProtectStructs[battler1].quickDraw = TRUE; gProtectStructs[battler1].quickDraw = TRUE;
// Quick Claw and Custap Berry // Quick Claw and Custap Berry
if (!gProtectStructs[battler1].quickDraw if (!gProtectStructs[battler1].quickDraw
@ -4755,7 +4755,7 @@ u32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov
// Battler 2 // Battler 2
// Quick Draw // Quick Draw
if (!ignoreChosenMoves && ability2 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler2]) && Random() % 100 < 30) if (!ignoreChosenMoves && ability2 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler2]) && RandomPercentage(RNG_QUICK_DRAW, 30))
gProtectStructs[battler2].quickDraw = TRUE; gProtectStructs[battler2].quickDraw = TRUE;
// Quick Claw and Custap Berry // Quick Claw and Custap Berry
if (!gProtectStructs[battler2].quickDraw if (!gProtectStructs[battler2].quickDraw

View File

@ -0,0 +1,43 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(P_GEN_7_POKEMON == TRUE); // Because only Ultra Beasts have this ability
}
SINGLE_BATTLE_TEST("Beast Boost boosts the most proficient stat when knocking out a target")
{
u8 stats[] = {1, 1, 1, 1, 1};
PARAMETRIZE { stats[0] = 255; }
PARAMETRIZE { stats[1] = 255; }
PARAMETRIZE { stats[2] = 255; }
PARAMETRIZE { stats[3] = 255; }
PARAMETRIZE { stats[4] = 255; }
GIVEN {
PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Attack(stats[0]); Defense(stats[1]); SpAttack(stats[2]); SpDefense(stats[3]); Speed(stats[4]); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(1); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }
} WHEN {
TURN { MOVE(player, MOVE_TACKLE); SEND_OUT(opponent, 1); }
} SCENE {
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
switch(i) {
case 0:
MESSAGE("Nihilego's Beast Boost raised its Attack!");
break;
case 1:
MESSAGE("Nihilego's Beast Boost raised its Defense!");
break;
case 2:
MESSAGE("Nihilego's Beast Boost raised its Sp. Atk!");
break;
case 3:
MESSAGE("Nihilego's Beast Boost raised its Sp. Def!");
break;
case 4:
MESSAGE("Nihilego's Beast Boost raised its Speed!");
break;
}
}
}

View File

@ -0,0 +1,35 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(P_GEN_8_POKEMON == TRUE); // Because only Frosmoth can have this ability.
}
SINGLE_BATTLE_TEST("Ice Scales halves the damage from special moves", s16 damage)
{
u32 move;
u16 ability;
PARAMETRIZE { ability = ABILITY_SHIELD_DUST; move = MOVE_PSYCHIC; }
PARAMETRIZE { ability = ABILITY_ICE_SCALES; move = MOVE_PSYCHIC; }
PARAMETRIZE { ability = ABILITY_SHIELD_DUST; move = MOVE_PSYSHOCK; }
PARAMETRIZE { ability = ABILITY_ICE_SCALES; move = MOVE_PSYSHOCK; }
PARAMETRIZE { ability = ABILITY_SHIELD_DUST; move = MOVE_TACKLE; }
PARAMETRIZE { ability = ABILITY_ICE_SCALES; move = MOVE_TACKLE; }
GIVEN {
ASSUME(gBattleMoves[MOVE_PSYCHIC].split == SPLIT_SPECIAL);
ASSUME(gBattleMoves[MOVE_PSYSHOCK].split == SPLIT_SPECIAL);
ASSUME(gBattleMoves[MOVE_PSYSHOCK].effect == EFFECT_PSYSHOCK);
ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_FROSMOTH) { Ability(ability); }
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage); // Ice Scales halves the damage of Psychic
EXPECT_MUL_EQ(results[2].damage, UQ_4_12(0.5), results[3].damage); // Ice Scales halves the damage of Psyshock, even if it targets Defense
EXPECT_EQ(results[4].damage, results[5].damage); // Ice Scales doesn't affect the damage of physical moves
}
}

View File

@ -4,11 +4,12 @@
SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun") SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun")
{ {
u32 move; u32 move;
PARAMETRIZE { move = MOVE_WILL_O_WISP; } u16 status;
PARAMETRIZE { move = MOVE_HYPNOSIS; } PARAMETRIZE { move = MOVE_WILL_O_WISP; status = STATUS1_BURN; }
PARAMETRIZE { move = MOVE_THUNDER_WAVE; } PARAMETRIZE { move = MOVE_HYPNOSIS; status = STATUS1_SLEEP; }
PARAMETRIZE { move = MOVE_TOXIC; } PARAMETRIZE { move = MOVE_THUNDER_WAVE; status = STATUS1_PARALYSIS; }
PARAMETRIZE { move = MOVE_POWDER_SNOW; } PARAMETRIZE { move = MOVE_TOXIC; status = STATUS1_TOXIC_POISON; }
PARAMETRIZE { move = MOVE_POWDER_SNOW; status = STATUS1_FREEZE; }
GIVEN { GIVEN {
ASSUME(gBattleMoves[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP); ASSUME(gBattleMoves[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP);
ASSUME(gBattleMoves[MOVE_HYPNOSIS].effect == EFFECT_SLEEP); ASSUME(gBattleMoves[MOVE_HYPNOSIS].effect == EFFECT_SLEEP);
@ -20,39 +21,14 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun")
} WHEN { } WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, move); } TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, move); }
} SCENE { } SCENE {
switch (move) if (move != MOVE_POWDER_SNOW) {
{ NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent);
case MOVE_WILL_O_WISP:
MESSAGE("Foe Wobbuffet used Will-o-Wisp!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WILL_O_WISP, opponent);
ABILITY_POPUP(player, ABILITY_LEAF_GUARD); ABILITY_POPUP(player, ABILITY_LEAF_GUARD);
MESSAGE("It doesn't affect Leafeon…"); MESSAGE("It doesn't affect Leafeon…");
break; } else {
case MOVE_HYPNOSIS: NOT ABILITY_POPUP(player, ABILITY_LEAF_GUARD);
MESSAGE("Foe Wobbuffet used Hypnosis!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPNOSIS, opponent);
ABILITY_POPUP(player, ABILITY_LEAF_GUARD);
MESSAGE("It doesn't affect Leafeon…");
break;
case MOVE_THUNDER_WAVE:
MESSAGE("Foe Wobbuffet used Thunder Wave!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, opponent);
ABILITY_POPUP(player, ABILITY_LEAF_GUARD);
MESSAGE("It doesn't affect Leafeon…");
break;
case MOVE_TOXIC:
MESSAGE("Foe Wobbuffet used Toxic!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, opponent);
ABILITY_POPUP(player, ABILITY_LEAF_GUARD);
MESSAGE("It doesn't affect Leafeon…");
break;
case MOVE_POWDER_SNOW:
MESSAGE("Foe Wobbuffet used Powder Snow!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER_SNOW, opponent);
MESSAGE("It's super effective!");
break;
} }
NONE_OF { STATUS_ICON(player, status1: TRUE); } NOT STATUS_ICON(player, status);
} }
} }

View File

@ -0,0 +1,30 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(P_GEN_7_POKEMON == TRUE); // Because only Necrozma can have this ability.
}
SINGLE_BATTLE_TEST("Neuroforce increases the strength of super-effective moves by 25%", s16 damage)
{
u32 move;
u16 ability;
PARAMETRIZE { ability = ABILITY_NEUROFORCE; move = MOVE_SHADOW_BALL; }
PARAMETRIZE { ability = ABILITY_KLUTZ; move = MOVE_SHADOW_BALL; }
PARAMETRIZE { ability = ABILITY_NEUROFORCE; move = MOVE_TACKLE; }
PARAMETRIZE { ability = ABILITY_KLUTZ; move = MOVE_TACKLE; }
GIVEN {
ASSUME(gBattleMoves[MOVE_SHADOW_BALL].type == TYPE_GHOST);
ASSUME(gBattleMoves[MOVE_TACKLE].type == TYPE_NORMAL);
PLAYER(SPECIES_NECROZMA_ULTRA) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[1].damage, UQ_4_12(1.25), results[0].damage); // Neuroforce boosts the power of super-effective moves
EXPECT_EQ(results[2].damage, results[3].damage); // Neuroforce doesn't boost the power of other moves
}
}

View File

@ -0,0 +1,65 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Purifying Salt halves damage from Ghost-type moves", s16 damage)
{
u16 ability;
PARAMETRIZE { ability = ABILITY_STURDY; }
PARAMETRIZE { ability = ABILITY_PURIFYING_SALT; }
GIVEN {
ASSUME(gBattleMoves[MOVE_SHADOW_BALL].type == TYPE_GHOST);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Ability(ability); }
} WHEN {
TURN { MOVE(player, MOVE_SHADOW_BALL); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Purifying Salt makes Rest fail")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_PURIFYING_SALT); HP(1); MaxHP(100);}
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_REST); }
} SCENE {
NONE_OF {
MESSAGE("Wobbuffet went to sleep!");
}
}
}
SINGLE_BATTLE_TEST("Purifying Salt grants immunity to status effects")
{
u32 move;
u16 status;
PARAMETRIZE { move = MOVE_WILL_O_WISP; status = STATUS1_BURN; }
PARAMETRIZE { move = MOVE_HYPNOSIS; status = STATUS1_SLEEP; }
PARAMETRIZE { move = MOVE_THUNDER_WAVE; status = STATUS1_PARALYSIS; }
PARAMETRIZE { move = MOVE_TOXIC; status = STATUS1_TOXIC_POISON; }
PARAMETRIZE { move = MOVE_POWDER_SNOW; status = STATUS1_FREEZE; }
GIVEN {
ASSUME(gBattleMoves[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP);
ASSUME(gBattleMoves[MOVE_HYPNOSIS].effect == EFFECT_SLEEP);
ASSUME(gBattleMoves[MOVE_THUNDER_WAVE].effect == EFFECT_PARALYZE);
ASSUME(gBattleMoves[MOVE_TOXIC].effect == EFFECT_TOXIC);
ASSUME(gBattleMoves[MOVE_POWDER_SNOW].effect == EFFECT_FREEZE_HIT);
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_PURIFYING_SALT); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); }
} SCENE {
if (move != MOVE_POWDER_SNOW) {
NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent);
ABILITY_POPUP(player, ABILITY_PURIFYING_SALT);
MESSAGE("It doesn't affect Wobbuffet…");
} else {
NOT ABILITY_POPUP(player, ABILITY_PURIFYING_SALT);
}
NOT STATUS_ICON(player, status);
}
}

View File

@ -0,0 +1,17 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Quick Draw has a 30% chance of going first")
{
PASSES_RANDOMLY(3, 10, RNG_QUICK_DRAW);
GIVEN {
PLAYER(SPECIES_SLOWBRO_GALARIAN) { Ability(ABILITY_QUICK_DRAW); Speed(1); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); }
} WHEN {
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
ABILITY_POPUP(player, ABILITY_QUICK_DRAW);
MESSAGE("Slowbro used Tackle!");
MESSAGE("Foe Wobbuffet used Celebrate!");
}
}

View File

@ -0,0 +1,29 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(P_GEN_4_POKEMON == TRUE); // Because no <Gen4 mons have this ability
}
SINGLE_BATTLE_TEST("Sharpness increases the power of cutting moves", s16 damage)
{
u32 move;
u16 ability;
PARAMETRIZE { move = MOVE_AERIAL_ACE; ability = ABILITY_SHARPNESS; }
PARAMETRIZE { move = MOVE_AERIAL_ACE; ability = ABILITY_STEADFAST; }
PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_SHARPNESS; }
PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_STEADFAST; }
GIVEN {
PLAYER(SPECIES_GALLADE) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[1].damage, Q_4_12(1.5), results[0].damage); // Sharpness affects slicing moves
EXPECT_EQ(results[2].damage, results[3].damage); // Sharpness does not affect non-slicing moves
}
}