Merge branch 'master' into master-upcoming

This commit is contained in:
Hedara 2024-12-29 21:43:07 +01:00
commit 2088f2a12d
33 changed files with 634 additions and 347 deletions

View File

@ -415,13 +415,13 @@ BattleScript_SaltCureExtraDamage::
call BattleScript_HurtTarget_NoString
printstring STRINGID_TARGETISHURTBYSALTCURE
waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_TARGET
end2
BattleScript_HurtTarget_NoString:
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE
healthbarupdate BS_TARGET
datahpupdate BS_TARGET
tryfaintmon BS_TARGET
return
BattleScript_EffectCorrosiveGas::
@ -7560,13 +7560,8 @@ BattleScript_AbilityPopUp:
return
BattleScript_AbilityPopUpScripting:
.if B_ABILITY_POP_UP == TRUE
showabilitypopup BS_SCRIPTING
pause 40
.endif
recordability BS_SCRIPTING
sethword sABILITY_OVERWRITE, 0
return
copybyte gBattlerAbility, sBATTLER
goto BattleScript_AbilityPopUp
BattleScript_AbilityPopUpOverwriteThenNormal:
setbyte sFIXED_ABILITY_POPUP, TRUE

View File

@ -858,6 +858,24 @@ static const u16 sPecharuntTeachableLearnset[] = {
#endif
```
_NOTE: At the top of this file, you will probably see this warning:_
```
//
// DO NOT MODIFY THIS FILE! It is auto-generated from tools/learnset_helpers/teachable.py`
//
```
The expansion includes a tool called the learnset helper, which aims to automate the generation of valid teachable moves. At the time of writing, this tool only supports generating TM and Tutor learnsets. However, in the future it may be expanded to deal with level up learnsets and egg moves.
Ignore the warning shown above the first time you're adding your teachable moves (as otherwise the compiler will complain about the array not existing), but in the future (if you're using the learnset helper) simply edit what teachable moves your Pokémon can learn in one of the JSON files found in `tools/learnset_helpers/porymoves_files`. It doesn't really matter which one you add your new Pokémon to, as the tool pulls from all of the files in this folder.
The learnset helper is useful if you plan on changing and/or increasing the available TMs and Tutor moves in your game. As an example, Bulbasaur learns Rage by TM in Red/Blue/Yellow, but in Emerald this TM does not exist. But since `tools/learnset_helpers/porymoves_files/rby.json` defines "MOVE_RAGE" as a TM move for Bulbasaur, that move would automatically be added to the `sBulbasaurTeachableLearnset` array if you were to add a Rage TM at any point.
The learnset helper can be toggled on/off in `include/config/pokemon.h`:
```
// Learnset helper toggles
#define P_LEARNSET_HELPER_TEACHABLE TRUE // If TRUE, teachable_learnsets.h will be populated by tools/learnset_helpers/teachable.py using the included JSON files based on available TMs and tutors.
```
Once more, we need to register the learnset in `gSpeciesInfo`:
```diff

View File

@ -839,6 +839,24 @@ static const u16 sPecharuntTeachableLearnset[] = {
#endif
```
_NOTE: At the top of this file, you will probably see this warning:_
```
//
// DO NOT MODIFY THIS FILE! It is auto-generated from tools/learnset_helpers/teachable.py`
//
```
The expansion includes a tool called the learnset helper, which aims to automate the generation of valid teachable moves. At the time of writing, this tool only supports generating TM and Tutor learnsets. However, in the future it may be expanded to deal with level up learnsets and egg moves.
Ignore the warning shown above the first time you're adding your teachable moves (as otherwise the compiler will complain about the array not existing), but in the future (if you're using the learnset helper) simply edit what teachable moves your Pokémon can learn in one of the JSON files found in `tools/learnset_helpers/porymoves_files`. It doesn't really matter which one you add your new Pokémon to, as the tool pulls from all of the files in this folder.
The learnset helper is useful if you plan on changing and/or increasing the available TMs and Tutor moves in your game. As an example, Bulbasaur learns Rage by TM in Red/Blue/Yellow, but in Emerald this TM does not exist. But since `tools/learnset_helpers/porymoves_files/rby.json` defines "MOVE_RAGE" as a TM move for Bulbasaur, that move would automatically be added to the `sBulbasaurTeachableLearnset` array if you were to add a Rage TM at any point.
The learnset helper can be toggled on/off in `include/config/pokemon.h`:
```
// Learnset helper toggles
#define P_LEARNSET_HELPER_TEACHABLE TRUE // If TRUE, teachable_learnsets.h will be populated by tools/learnset_helpers/teachable.py using the included JSON files based on available TMs and tutors.
```
Once more, we need to register the learnset in `gSpeciesInfo`:
```diff

View File

@ -742,7 +742,7 @@ extern struct BattleTestRunnerState *const gBattleTestRunnerState;
/* Test */
#define TO_DO_BATTLE_TEST(_name) \
TEST("TODO: " _name) \
TEST(_name) \
{ \
TO_DO; \
}

View File

@ -1185,7 +1185,7 @@ void CreateEnemyShadowSprite(u32 battler)
{
gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary = CreateSprite(&gSpriteTemplate_EnemyShadow,
GetBattlerSpriteCoord(battler, BATTLER_COORD_X),
GetBattlerSpriteCoord(battler, BATTLER_COORD_Y),
GetBattlerSpriteCoord(battler, BATTLER_COORD_Y) + 29,
0xC8);
if (gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary < MAX_SPRITES)
{
@ -1247,9 +1247,11 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite)
return;
}
s8 xOffset = 0, yOffset = 0, size = SHADOW_SIZE_S;
s8 xOffset = 0, UNUSED yOffset = 0, size = SHADOW_SIZE_S;
if (gAnimScriptActive || battlerSprite->invisible)
{
invisible = TRUE;
}
else if (transformSpecies != SPECIES_NONE)
{
xOffset = gSpeciesInfo[transformSpecies].enemyShadowXOffset;
@ -1267,21 +1269,19 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite)
yOffset = gSpeciesInfo[species].enemyShadowYOffset + 16;
size = gSpeciesInfo[species].enemyShadowSize;
}
else
{
yOffset = 29;
}
if (gBattleSpritesDataPtr->battlerData[battler].behindSubstitute)
invisible = TRUE;
shadowSprite->x = battlerSprite->x + xOffset;
shadowSprite->x2 = battlerSprite->x2;
shadowSprite->y = battlerSprite->y + yOffset;
shadowSprite->invisible = invisible;
if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE)
{
shadowSprite->oam.tileNum = shadowSprite->tBaseTileNum + (8 * size);
shadowSprite->y = battlerSprite->y + yOffset;
}
}
#undef tBattlerId

View File

@ -0,0 +1,112 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Liquid Ooze causes Absorb users to lose HP instead of heal")
{
s16 damage;
s16 healed;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
} WHEN {
TURN { MOVE(player, MOVE_ABSORB); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player);
HP_BAR(opponent, captureDamage: &damage);
HP_BAR(player, captureDamage: &healed);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
} THEN {
EXPECT_MUL_EQ(damage, Q_4_12(0.5), healed);
}
}
SINGLE_BATTLE_TEST("Liquid Ooze causes Leech Seed users to lose HP instead of heal")
{
s16 damage;
s16 healed;
GIVEN {
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
} WHEN {
TURN { MOVE(player, MOVE_LEECH_SEED); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, player);
HP_BAR(opponent, captureDamage: &damage);
HP_BAR(player, captureDamage: &healed);
} THEN {
EXPECT_EQ(damage, healed);
}
}
DOUBLE_BATTLE_TEST("Liquid Ooze causes Matcha Gatcha users to lose HP instead of heal")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_MATCHA_GOTCHA].effect == EFFECT_ABSORB);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(playerLeft);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
MESSAGE("Wobbuffet fainted!");
}
}
DOUBLE_BATTLE_TEST("Liquid Ooze will faint Matcha Gatcha users if it deals enough damage")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_MATCHA_GOTCHA].effect == EFFECT_ABSORB);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(playerLeft);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
MESSAGE("Wobbuffet fainted!");
}
}
SINGLE_BATTLE_TEST("Liquid Ooze causes Strength Sap users to lose HP instead of heal")
{
s16 lostHp;
s32 atkStat;
PARAMETRIZE { atkStat = 100; }
PARAMETRIZE { atkStat = 490; } // Checks that attacker can faint with no problems.
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Attack(atkStat); Ability(ABILITY_LIQUID_OOZE); }
} WHEN {
TURN { MOVE(player, MOVE_STRENGTH_SAP); if (atkStat == 490) { SEND_OUT(player, 1); } }
} SCENE {
MESSAGE("Wobbuffet used Strength Sap!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_STRENGTH_SAP, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's Attack fell!");
ABILITY_POPUP(opponent, ABILITY_LIQUID_OOZE);
HP_BAR(player, captureDamage: &lostHp);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
if (atkStat >= 490) {
MESSAGE("Wobbuffet fainted!");
SEND_IN_MESSAGE("Wobbuffet");
}
} THEN {
EXPECT_EQ(lostHp, atkStat);
}
}
TO_DO_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4");
TO_DO_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+");

View File

@ -271,76 +271,3 @@ SINGLE_BATTLE_TEST("Crit Chance: Focus Energy increases critical hit ratio by tw
MESSAGE("A critical hit!");
}
}
SINGLE_BATTLE_TEST("Crit Chance: Dragon Cheer fails in a single battle")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_DRAGON_CHEER); }
} SCENE {
MESSAGE("But it failed!");
}
}
DOUBLE_BATTLE_TEST("Crit Chance: Dragon Cheer increases critical hit ratio by one on non Dragon types")
{
PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT);
GIVEN {
ASSUME(B_CRIT_CHANCE >= GEN_7);
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CHEER, target: playerRight); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerLeft);
MESSAGE("Wynaut is getting pumped!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
MESSAGE("A critical hit!");
}
}
DOUBLE_BATTLE_TEST("Crit Chance: Dragon Cheer increases critical hit ratio by two on Dragon types")
{
PASSES_RANDOMLY(1, 2, RNG_CRITICAL_HIT);
GIVEN {
ASSUME(B_CRIT_CHANCE >= GEN_7);
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_DRATINI);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CHEER, target: playerRight); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerLeft);
MESSAGE("Dratini is getting pumped!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
MESSAGE("A critical hit!");
}
}
DOUBLE_BATTLE_TEST("Crit Chance: Dragon Cheer fails if critical hit stage was already increased by Focus Energy")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_SLASH].criticalHitStage == 1);
ASSUME(gMovesInfo[MOVE_FOCUS_ENERGY].effect == EFFECT_FOCUS_ENERGY);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_FOCUS_ENERGY); MOVE(playerRight, MOVE_DRAGON_CHEER, target: playerLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FOCUS_ENERGY, playerLeft);
MESSAGE("But it failed!");
}
}

View File

@ -102,22 +102,6 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon cannot be hit by OHKO moves")
}
}
// can't be used at all in Raid, see "Documenting Dynamax"
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon are not affected by Destiny Bond")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(50); };
OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(100); }
} WHEN {
TURN { MOVE(opponent, MOVE_DESTINY_BOND); MOVE(player, MOVE_TACKLE, gimmick: GIMMICK_DYNAMAX); }
} SCENE {
MESSAGE("The opposing Wobbuffet used Destiny Bond!");
MESSAGE("Wobbuffet used Max Strike!");
MESSAGE("The opposing Wobbuffet fainted!");
NONE_OF { HP_BAR(player); }
}
}
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon are affected by Grudge")
{
GIVEN {
@ -362,24 +346,6 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon lose their substitutes")
}
}
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon take double damage from Dynamax Cannon", s16 damage)
{
u32 dynamax;
PARAMETRIZE { dynamax = GIMMICK_NONE; }
PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; }
GIVEN {
ASSUME(gMovesInfo[MOVE_DYNAMAX_CANNON].effect == EFFECT_DYNAMAX_DOUBLE_DMG);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE, gimmick: dynamax); MOVE(opponent, MOVE_DYNAMAX_CANNON); }
} SCENE {
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("(DYNAMAX) Max Moves deal 1/4 damage through protect", s16 damage)
{
bool32 protected;

View File

@ -24,25 +24,6 @@ SINGLE_BATTLE_TEST("Absorb recovers 50% of the damage dealt")
}
}
SINGLE_BATTLE_TEST("Absorb deals 50% of the damage dealt to user agains Liquid Ooze")
{
s16 damage;
s16 healed;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
} WHEN {
TURN { MOVE(player, MOVE_ABSORB); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player);
HP_BAR(opponent, captureDamage: &damage);
HP_BAR(player, captureDamage: &healed);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
} THEN {
EXPECT_MUL_EQ(damage, Q_4_12(0.5), healed);
}
}
SINGLE_BATTLE_TEST("Absorb fails if Heal Block applies")
{
GIVEN {
@ -88,25 +69,6 @@ DOUBLE_BATTLE_TEST("Matcha Gatcha recovers 50% of the damage dealt from both tar
}
}
DOUBLE_BATTLE_TEST("Matcha Gatcha will faint the pokemon if Liquid Ooze drain deals enough damage")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_MATCHA_GOTCHA].effect == EFFECT_ABSORB);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(playerLeft);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
MESSAGE("Wobbuffet fainted!");
}
}
SINGLE_BATTLE_TEST("Draining Kiss recovers 75% of the damage dealt")
{
s16 damage;

View File

@ -277,6 +277,8 @@ DOUBLE_BATTLE_TEST("Ally switch swaps opposing sky drop targets if partner is be
}
}
// Test passes in isolation but fails on CI
/*
DOUBLE_BATTLE_TEST("Ally Switch swaps Illusion data")
{
KNOWN_FAILING; // Test passes in isolation but fails on CI
@ -293,6 +295,7 @@ DOUBLE_BATTLE_TEST("Ally Switch swaps Illusion data")
EXPECT(&gPlayerParty[2] == gBattleStruct->illusion[0].mon);
}
}
*/
// Triple Battles required to test
//TO_DO_BATTLE_TEST("Ally Switch fails if the user is in the middle of the field in a Triple Battle");

View File

@ -39,9 +39,6 @@ TO_DO_BATTLE_TEST("Baton Pass doesn't pass ability changes");
//
TO_DO_BATTLE_TEST("Baton Pass passes confusion status"); // test/battle/status2/confusion.c
TO_DO_BATTLE_TEST("Baton Pass passes Cursed status"); // test/battle/move_effect/curse.c
TO_DO_BATTLE_TEST("Baton Pass doesn't pass Disable's effect"); // test/battle/move_effect/disable.c
TO_DO_BATTLE_TEST("Baton Pass passes Dragon Cheer's effect"); // test/battle/move_effect/dragon_cheer.c
TO_DO_BATTLE_TEST("Baton Pass passes Fairy lock's escape prevention effect"); // test/battle/move_effect/fairy_lock.c
TO_DO_BATTLE_TEST("Baton Pass passes Focus Energy's effect"); // test/battle/move_effect/focus_energy.c
TO_DO_BATTLE_TEST("Baton Pass passes Heal Block's effect"); // test/battle/move_effect/heal_block.c

View File

@ -67,3 +67,5 @@ SINGLE_BATTLE_TEST("Curse applies to the opponent if user is afflicted by Trick-
HP_BAR(opponent, damage: opponentMaxHP / 4);
}
}
TO_DO_BATTLE_TEST("Baton Pass passes Cursed status");

View File

@ -0,0 +1,42 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_DARK_VOID].effect == EFFECT_DARK_VOID);
}
SINGLE_BATTLE_TEST("Dark Void inflicts 1-3 turns of sleep")
{
u32 turns, count;
ASSUME(B_SLEEP_TURNS >= GEN_5);
PARAMETRIZE { turns = 1; }
PARAMETRIZE { turns = 2; }
PARAMETRIZE { turns = 3; }
PASSES_RANDOMLY(1, 3, RNG_SLEEP_TURNS);
GIVEN {
PLAYER(SPECIES_DARKRAI);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_DARK_VOID); MOVE(opponent, MOVE_CELEBRATE); }
for (count = 0; count < turns; ++count)
TURN {}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DARK_VOID, player);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent);
MESSAGE("The opposing Wobbuffet fell asleep!");
STATUS_ICON(opponent, sleep: TRUE);
for (count = 0; count < turns; ++count)
{
if (count < turns - 1)
MESSAGE("The opposing Wobbuffet is fast asleep.");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent);
}
MESSAGE("The opposing Wobbuffet woke up!");
STATUS_ICON(opponent, none: TRUE);
}
}
TO_DO_BATTLE_TEST("Dark Void can only be used by Darkrai (Gen7+)");
TO_DO_BATTLE_TEST("Dark Void can be used by Pokémon other than Darkrai (Gen4-6)");
TO_DO_BATTLE_TEST("Dark Void can be used by a Pokémon transformed into Darkrai");

View File

@ -0,0 +1,5 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Decorate raises the target's Attack by 2 stages");
TO_DO_BATTLE_TEST("Decorate raises the target's Sp. Attack by 2 stages");

View File

@ -0,0 +1,37 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_DEFENSE_CURL].effect == EFFECT_DEFENSE_CURL);
}
SINGLE_BATTLE_TEST("Defense Curl raises Defense by 1 stage", s16 damage)
{
bool32 raiseDefense;
PARAMETRIZE { raiseDefense = FALSE; }
PARAMETRIZE { raiseDefense = TRUE; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
if (raiseDefense) TURN { MOVE(player, MOVE_DEFENSE_CURL); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
if (raiseDefense) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFENSE_CURL, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Defense rose!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[1].damage, Q_4_12(1.5), results[0].damage);
}
}
TO_DO_BATTLE_TEST("Defense Curl doubles the power of Rollout and Ice Ball");
TO_DO_BATTLE_TEST("Defense Curl's effect cannot be stacked");
TO_DO_BATTLE_TEST("Defense Curl's effect is removed when switching out");
TO_DO_BATTLE_TEST("Baton Pass doesn't pass Defense Curl's effect");

View File

@ -6,7 +6,7 @@ ASSUMPTIONS
ASSUME(gMovesInfo[MOVE_TAIL_WHIP].effect == EFFECT_DEFENSE_DOWN);
}
SINGLE_BATTLE_TEST("Tail Whip lowers Defense", s16 damage)
SINGLE_BATTLE_TEST("Tail Whip lowers Defense by 1 stage", s16 damage)
{
bool32 lowerDefense;
PARAMETRIZE { lowerDefense = FALSE; }

View File

@ -0,0 +1,32 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_SCREECH].effect == EFFECT_DEFENSE_DOWN_2);
}
SINGLE_BATTLE_TEST("Screech lowers Defense by 2 stages", s16 damage)
{
bool32 lowerDefense;
PARAMETRIZE { lowerDefense = FALSE; }
PARAMETRIZE { lowerDefense = TRUE; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
if (lowerDefense) TURN { MOVE(player, MOVE_SCREECH); }
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
if (lowerDefense) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCREECH, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's Defense harshly fell!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}

View File

@ -6,7 +6,7 @@ ASSUMPTIONS
ASSUME(gMovesInfo[MOVE_HARDEN].effect == EFFECT_DEFENSE_UP);
}
SINGLE_BATTLE_TEST("Harden raises Defense", s16 damage)
SINGLE_BATTLE_TEST("Harden raises Defense by 1 stage", s16 damage)
{
bool32 raiseDefense;
PARAMETRIZE { raiseDefense = FALSE; }

View File

@ -0,0 +1,32 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_IRON_DEFENSE].effect == EFFECT_DEFENSE_UP_2);
}
SINGLE_BATTLE_TEST("Iron Defense raises Defense by 2 stages", s16 damage)
{
bool32 raiseDefense;
PARAMETRIZE { raiseDefense = FALSE; }
PARAMETRIZE { raiseDefense = TRUE; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
if (raiseDefense) TURN { MOVE(player, MOVE_IRON_DEFENSE); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
if (raiseDefense) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_IRON_DEFENSE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Defense sharply rose!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[1].damage, Q_4_12(2.0), results[0].damage);
}
}

View File

@ -0,0 +1,32 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_COTTON_GUARD].effect == EFFECT_DEFENSE_UP_3);
}
SINGLE_BATTLE_TEST("Cotton Guard raises Defense by 3 stages", s16 damage)
{
bool32 raiseDefense;
PARAMETRIZE { raiseDefense = FALSE; }
PARAMETRIZE { raiseDefense = TRUE; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
if (raiseDefense) TURN { MOVE(player, MOVE_COTTON_GUARD); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
if (raiseDefense) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_COTTON_GUARD, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Defense drastically rose!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[1].damage, Q_4_12(2.5), results[0].damage);
}
}

View File

@ -19,7 +19,7 @@ ASSUMPTIONS
ASSUME(gMovesInfo[MOVE_GUST].category == DAMAGE_CATEGORY_SPECIAL);
}
SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1")
SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 stage")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
@ -51,7 +51,8 @@ SINGLE_BATTLE_TEST("Defog does not lower evasiveness if target behind Substitute
}
}
DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Reflect and Light Screen from opponent's side", s16 damagePhysical, s16 damageSpecial)
TO_DO_BATTLE_TEST("Defog doesn't remove Reflect or Light Screen from the user's side");
DOUBLE_BATTLE_TEST("Defog removes Reflect and Light Screen from target's side", s16 damagePhysical, s16 damageSpecial)
{
u16 move;
@ -71,8 +72,6 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Reflect and Light
ANIMATION(ANIM_TYPE_MOVE, MOVE_LIGHT_SCREEN, opponentRight);
ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
if (move == MOVE_DEFOG) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
MESSAGE("The opposing Wobbuffet's evasiveness fell!");
MESSAGE("The opposing team's Reflect wore off!");
MESSAGE("The opposing team's Light Screen wore off!");
}
@ -86,7 +85,8 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Reflect and Light
}
}
DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Mist and Safeguard from opponent's side")
TO_DO_BATTLE_TEST("Defog doesn't remove Mist or Safeguard from the user's side");
DOUBLE_BATTLE_TEST("Defog removes Mist and Safeguard from target's side")
{
u16 move;
@ -105,7 +105,6 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Mist and Safeguard
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIST, opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SAFEGUARD, opponentRight);
if (move == MOVE_DEFOG) {
MESSAGE("The opposing Wobbuffet is protected by the mist!");
ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
MESSAGE("The opposing team's Mist wore off!");
MESSAGE("The opposing team's Safeguard wore off!");
@ -131,7 +130,9 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Mist and Safeguard
}
}
DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and Sticky Web from player's side (Gen 6+)")
TO_DO_BATTLE_TEST("Defog removes Stealth Rock and Sticky Web from target's side");
TO_DO_BATTLE_TEST("Defog doesn't remove Stealth Rock or Sticky Web from user's side (Gen 4-5)");
DOUBLE_BATTLE_TEST("Defog removes Stealth Rock and Sticky Web from user's side (Gen 6+)")
{
u16 move;
@ -151,13 +152,9 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and S
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentRight);
ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
if (move == MOVE_DEFOG) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
MESSAGE("The opposing Wobbuffet's evasiveness fell!");
if (B_DEFOG_EFFECT_CLEARING >= GEN_6) {
MESSAGE("The pointed stones disappeared from around your team!");
MESSAGE("The sticky web has disappeared from the ground around your team!");
}
if (move == MOVE_DEFOG && B_DEFOG_EFFECT_CLEARING >= GEN_6) {
MESSAGE("The pointed stones disappeared from around your team!");
MESSAGE("The sticky web has disappeared from the ground around your team!");
}
// Switch happens
SWITCH_OUT_MESSAGE("Wobbuffet");
@ -181,7 +178,9 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and S
}
}
SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Spikes from player's side")
TO_DO_BATTLE_TEST("Defog removes Spikes from target's side");
TO_DO_BATTLE_TEST("Defog doesn't remove Spikes from user's side (Gen 4-5)");
SINGLE_BATTLE_TEST("Defog removes Spikes from user's side (Gen 6+)")
{
u16 move;
@ -197,12 +196,8 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Spikes from player
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent);
ANIMATION(ANIM_TYPE_MOVE, move, player);
if (move == MOVE_DEFOG) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's evasiveness fell!");
if (B_DEFOG_EFFECT_CLEARING >= GEN_6)
MESSAGE("The spikes disappeared from the ground around your team!");
}
if (move == MOVE_DEFOG && B_DEFOG_EFFECT_CLEARING >= GEN_6)
MESSAGE("The spikes disappeared from the ground around your team!");
// Switch happens
SWITCH_OUT_MESSAGE("Wobbuffet");
SEND_IN_MESSAGE("Wobbuffet");
@ -219,7 +214,8 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Spikes from player
}
}
SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes terrain (Gen 8+)")
TO_DO_BATTLE_TEST("Defog doesn't remove terrain (Gen 4-7)");
SINGLE_BATTLE_TEST("Defog removes terrain (Gen 8+)")
{
u16 move;
@ -235,8 +231,6 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes terrain (Gen 8+)")
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's evasiveness fell!");
if (B_DEFOG_EFFECT_CLEARING >= GEN_8) {
if (move == MOVE_PSYCHIC_TERRAIN) {
MESSAGE("The weirdness disappeared from the battlefield!");
@ -263,7 +257,9 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes terrain (Gen 8+)")
}
}
SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Toxic Spikes from opponent's side")
TO_DO_BATTLE_TEST("Defog removes Toxic Spikes from target's side");
TO_DO_BATTLE_TEST("Defog doesn't remove Toxic Spikes from user's side (Gen 4-5)");
SINGLE_BATTLE_TEST("Defog removes Toxic Spikes from user's side (Gen 6+)")
{
u16 move;
@ -279,12 +275,8 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Toxic Spikes from
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, player);
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
if (move == MOVE_DEFOG) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's evasiveness fell!");
if (B_DEFOG_EFFECT_CLEARING >= GEN_6)
MESSAGE("The poison spikes disappeared from the ground around the opposing team!");
}
if (move == MOVE_DEFOG && B_DEFOG_EFFECT_CLEARING >= GEN_6)
MESSAGE("The poison spikes disappeared from the ground around the opposing team!");
// Switch happens
MESSAGE("2 sent out Wobbuffet!");
if (move != MOVE_DEFOG || B_DEFOG_EFFECT_CLEARING <= GEN_5) {
@ -302,7 +294,8 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Toxic Spikes from
}
}
DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Aurora Veil from player's side", s16 damagePhysical, s16 damageSpecial)
TO_DO_BATTLE_TEST("Defog doesn't remove Aurora Veil from the user's side");
DOUBLE_BATTLE_TEST("Defog removes Aurora Veil from target's side", s16 damagePhysical, s16 damageSpecial)
{
u16 move;
@ -338,7 +331,7 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Aurora Veil from p
}
}
DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes everything it can")
DOUBLE_BATTLE_TEST("Defog removes everything it can")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL);

View File

@ -77,3 +77,35 @@ SINGLE_BATTLE_TEST("Destiny Bond does not fail if used after failing in Gen 7+")
ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player);
}
}
// can't be used at all in Raid, see "Documenting Dynamax"
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon are not affected by Destiny Bond")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(50); };
OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(100); }
} WHEN {
TURN { MOVE(opponent, MOVE_DESTINY_BOND); MOVE(player, MOVE_TACKLE, gimmick: GIMMICK_DYNAMAX); }
} SCENE {
MESSAGE("The opposing Wobbuffet used Destiny Bond!");
MESSAGE("Wobbuffet used Max Strike!");
MESSAGE("The opposing Wobbuffet fainted!");
NONE_OF { HP_BAR(player); }
}
}
TO_DO_BATTLE_TEST("Destiny Bond's effect disappears if the user takes a new turn - Move");
TO_DO_BATTLE_TEST("Destiny Bond's effect disappears if the user takes a new turn - Sleep");
TO_DO_BATTLE_TEST("Destiny Bond's effect disappears if the user takes a new turn - Paralysis");
TO_DO_BATTLE_TEST("Destiny Bond's effect disappears if the user takes a new turn - Flinching");
TO_DO_BATTLE_TEST("Destiny Bond's effect doesn't trigger on indirect damage - Sandstorm");
TO_DO_BATTLE_TEST("Destiny Bond's effect doesn't trigger on indirect damage - Leech Seed");
TO_DO_BATTLE_TEST("Destiny Bond's effect doesn't trigger on indirect damage - Future Sight");
TO_DO_BATTLE_TEST("Destiny Bond's effect bypasses Focus Sash");
TO_DO_BATTLE_TEST("Destiny Bond's effect bypasses Sturdy");
TO_DO_BATTLE_TEST("Destiny Bond's effect bypasses Magic Guard");
TO_DO_BATTLE_TEST("Destiny Bond's effect can trigger on the next turn if the user hasn't moved yet");
TO_DO_BATTLE_TEST("Destiny Bond can be used multiple times in a row (Gen 2-6)");
TO_DO_BATTLE_TEST("Destiny Bond always fails if it was successfully used the previous turn (Gen 7+)");
TO_DO_BATTLE_TEST("Destiny Bond cannot be used in Raids");

View File

@ -0,0 +1,20 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Disable prevents the target from using a random move (Gen 1)");
TO_DO_BATTLE_TEST("Disable prevents the target from using the last move used (Gen 2+)");
TO_DO_BATTLE_TEST("Disable fails if one of the target's moves is already disabled");
TO_DO_BATTLE_TEST("Disable fails if the target haven't used a move yet (Gen 2+)");
TO_DO_BATTLE_TEST("Disable fails if the last move used was Struggle (Gen 2+)");
TO_DO_BATTLE_TEST("Disable fails if the last move used was a Max Move");
TO_DO_BATTLE_TEST("Disabled moves can still be used via Sleep Talk");
TO_DO_BATTLE_TEST("Disabled moves can still be used via Metronome");
TO_DO_BATTLE_TEST("Disabled moves can still be used via Mirror Move");
TO_DO_BATTLE_TEST("Disable lasts 0-7 turns (Gen 1)");
TO_DO_BATTLE_TEST("Disable lasts 2-8 turns (Gen 2)");
TO_DO_BATTLE_TEST("Disable lasts 2-5 turns (Gen 3)");
TO_DO_BATTLE_TEST("Disable lasts 4-7 turns (Gen 4)");
TO_DO_BATTLE_TEST("Disable lasts 4 turns (Gen 5+)");
TO_DO_BATTLE_TEST("Disable's timer only counts down when trying to use a move (Gen 1-2)");
TO_DO_BATTLE_TEST("Disable's timer counts down regardless of the action (Gen 3+)");
TO_DO_BATTLE_TEST("Baton Pass doesn't pass Disable's effect");

View File

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Splash does nothing");

View File

@ -0,0 +1,77 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Dragon Cheer fails in a single battle")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_DRAGON_CHEER); }
} SCENE {
MESSAGE("But it failed!");
}
}
DOUBLE_BATTLE_TEST("Dragon Cheer increases critical hit ratio by one on non-Dragon types")
{
PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT);
GIVEN {
ASSUME(B_CRIT_CHANCE >= GEN_7);
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CHEER, target: playerRight); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerLeft);
MESSAGE("Wynaut is getting pumped!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
MESSAGE("A critical hit!");
}
}
DOUBLE_BATTLE_TEST("Dragon Cheer increases critical hit ratio by two on Dragon types")
{
PASSES_RANDOMLY(1, 2, RNG_CRITICAL_HIT);
GIVEN {
ASSUME(B_CRIT_CHANCE >= GEN_7);
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_DRATINI);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CHEER, target: playerRight); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerLeft);
MESSAGE("Dratini is getting pumped!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
MESSAGE("A critical hit!");
}
}
DOUBLE_BATTLE_TEST("Dragon Cheer fails if critical hit stage was already increased by Focus Energy")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_SLASH].criticalHitStage == 1);
ASSUME(gMovesInfo[MOVE_FOCUS_ENERGY].effect == EFFECT_FOCUS_ENERGY);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_FOCUS_ENERGY); MOVE(playerRight, MOVE_DRAGON_CHEER, target: playerLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FOCUS_ENERGY, playerLeft);
MESSAGE("But it failed!");
}
}
TO_DO_BATTLE_TEST("Baton Pass passes Dragon Cheer's effect");

View File

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Dragon Dance increases Attack and Speed by one stage each");

View File

@ -23,156 +23,134 @@ SINGLE_BATTLE_TEST("Dragon Darts strikes twice")
DOUBLE_BATTLE_TEST("Dragon Darts strikes each opponent once in a double battle")
{
struct BattlePokemon *chosenTarget = NULL;
struct BattlePokemon *secondaryTarget = NULL;
PARAMETRIZE { chosenTarget = opponentLeft; secondaryTarget = opponentRight; }
PARAMETRIZE { chosenTarget = opponentRight; secondaryTarget = opponentLeft; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: chosenTarget); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(chosenTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(secondaryTarget);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes the ally twice if the target protects")
{
struct BattlePokemon *chosenTarget = NULL;
struct BattlePokemon *secondaryTarget = NULL;
PARAMETRIZE { chosenTarget = opponentLeft; secondaryTarget = opponentRight; }
PARAMETRIZE { chosenTarget = opponentRight; secondaryTarget = opponentLeft; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_PROTECT); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
TURN { MOVE(chosenTarget, MOVE_PROTECT); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, chosenTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(secondaryTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(secondaryTarget);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes the right ally twice if the target is a fairy type")
DOUBLE_BATTLE_TEST("Dragon Darts strikes an opponent twice if the other one is Fairy-type")
{
struct BattlePokemon *chosenTarget = NULL;
struct BattlePokemon *finalTarget = NULL;
u32 speciesLeft, speciesRight;
PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentRight; speciesLeft = SPECIES_CLEFAIRY; speciesRight = SPECIES_WOBBUFFET; }
PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentRight; speciesLeft = SPECIES_CLEFAIRY; speciesRight = SPECIES_WOBBUFFET; }
PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentLeft; speciesLeft = SPECIES_WOBBUFFET; speciesRight = SPECIES_CLEFAIRY; }
PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentLeft; speciesLeft = SPECIES_WOBBUFFET; speciesRight = SPECIES_CLEFAIRY; }
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_CLEFAIRY].types[0] == TYPE_FAIRY || gSpeciesInfo[SPECIES_CLEFAIRY].types[1] == TYPE_FAIRY);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_CLEFAIRY);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(speciesLeft);
OPPONENT(speciesRight);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: chosenTarget); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(finalTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(finalTarget);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes the left ally twice if the target is a fairy type")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_CLEFAIRY);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentRight); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes left ally twice if electrified and right ally has Volt Absorb")
DOUBLE_BATTLE_TEST("Dragon Darts strikes an opponent twice if electrified and the other one has Volt Absorb")
{
struct BattlePokemon *chosenTarget = NULL;
struct BattlePokemon *finalTarget = NULL;
u32 abilityLeft, abilityRight;
PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentLeft; abilityLeft = ABILITY_WATER_ABSORB; abilityRight = ABILITY_VOLT_ABSORB; }
PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentLeft; abilityLeft = ABILITY_WATER_ABSORB; abilityRight = ABILITY_VOLT_ABSORB; }
PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentRight; abilityLeft = ABILITY_VOLT_ABSORB; abilityRight = ABILITY_WATER_ABSORB; }
PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentRight; abilityLeft = ABILITY_VOLT_ABSORB; abilityRight = ABILITY_WATER_ABSORB; }
GIVEN {
ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_LANTURN) { Ability(ABILITY_VOLT_ABSORB); };
OPPONENT(SPECIES_LANTURN) { Ability(abilityLeft); };
OPPONENT(SPECIES_LANTURN) { Ability(abilityRight); };
} WHEN {
TURN { MOVE(opponentRight, MOVE_ELECTRIFY, target: playerLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentRight); }
TURN { MOVE(opponentRight, MOVE_ELECTRIFY, target: playerLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: chosenTarget); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(finalTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(finalTarget);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes right ally twice if electrified and left ally has Volt Absorb")
DOUBLE_BATTLE_TEST("Dragon Darts strikes an opponent twice if electrified and the other one has Motor Drive")
{
struct BattlePokemon *chosenTarget = NULL;
struct BattlePokemon *finalTarget = NULL;
u32 abilityLeft, abilityRight;
PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentLeft; abilityLeft = ABILITY_VITAL_SPIRIT; abilityRight = ABILITY_MOTOR_DRIVE; }
PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentLeft; abilityLeft = ABILITY_VITAL_SPIRIT; abilityRight = ABILITY_MOTOR_DRIVE; }
PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentRight; abilityLeft = ABILITY_MOTOR_DRIVE; abilityRight = ABILITY_VITAL_SPIRIT; }
PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentRight; abilityLeft = ABILITY_MOTOR_DRIVE; abilityRight = ABILITY_VITAL_SPIRIT; }
GIVEN {
ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_LANTURN) { Ability(ABILITY_VOLT_ABSORB); };
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_ELECTIVIRE) { Ability(abilityLeft); };
OPPONENT(SPECIES_ELECTIVIRE) { Ability(abilityRight); };
} WHEN {
TURN { MOVE(opponentRight, MOVE_ELECTRIFY, target: playerLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentRight); }
TURN { MOVE(opponentRight, MOVE_ELECTRIFY, target: playerLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: chosenTarget); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(finalTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(finalTarget);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes left ally twice if electrified and right ally has Motor Drive")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_ELECTIVIRE) { Ability(ABILITY_MOTOR_DRIVE); };
} WHEN {
TURN { MOVE(opponentRight, MOVE_ELECTRIFY, target: playerLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentRight); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentLeft);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes right ally twice if electrified and left ally has Motor Drive")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_ELECTIVIRE) { Ability(ABILITY_MOTOR_DRIVE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentRight, MOVE_ELECTRIFY, target: playerLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentRight); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes the ally twice if the target is in a semi-invulnerable turn")
DOUBLE_BATTLE_TEST("Dragon Darts strikes an opponent twice if the other one is in a semi-invulnerable turn")
{
struct BattlePokemon *chosenTarget = NULL;
struct BattlePokemon *finalTarget = NULL;
PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentRight; }
PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentLeft; }
GIVEN {
ASSUME(gMovesInfo[MOVE_FLY].effect == EFFECT_SEMI_INVULNERABLE);
PLAYER(SPECIES_WOBBUFFET);
@ -180,13 +158,13 @@ DOUBLE_BATTLE_TEST("Dragon Darts strikes the ally twice if the target is in a se
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_FLY, target: playerLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
TURN { MOVE(chosenTarget, MOVE_FLY, target: playerLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: chosenTarget); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLY, opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLY, chosenTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(finalTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(finalTarget);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
@ -210,39 +188,49 @@ DOUBLE_BATTLE_TEST("Dragon Darts is not effected by Wide Guard")
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes hit the ally if the target fainted")
DOUBLE_BATTLE_TEST("Dragon Darts strikes an opponent twice if the other one is fainted")
{
struct BattlePokemon *chosenTarget = NULL;
struct BattlePokemon *finalTarget = NULL;
u32 hpLeft, hpRight;
PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentRight; hpLeft = 1; hpRight = 101; }
PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentLeft; hpLeft = 101; hpRight = 1; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(hpLeft); }
OPPONENT(SPECIES_WOBBUFFET) { HP(hpRight); }
} WHEN {
TURN { MOVE(playerRight, MOVE_SONIC_BOOM, target: opponentLeft); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentLeft); }
TURN { MOVE(playerRight, MOVE_SONIC_BOOM, target: chosenTarget); MOVE(playerLeft, MOVE_DRAGON_DARTS, target: chosenTarget); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SONIC_BOOM, playerRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(finalTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentRight);
HP_BAR(finalTarget);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}
DOUBLE_BATTLE_TEST("Dragon Darts strikes left ally twice if one strike misses")
{
struct BattlePokemon *chosenTarget = NULL;
struct BattlePokemon *finalTarget = NULL;
u32 itemLeft, itemRight;
PARAMETRIZE { chosenTarget = opponentLeft; finalTarget = opponentRight; itemLeft = ITEM_BRIGHT_POWDER; itemRight = ITEM_NONE; }
PARAMETRIZE { chosenTarget = opponentRight; finalTarget = opponentLeft; itemLeft = ITEM_NONE; itemRight = ITEM_BRIGHT_POWDER; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_BRIGHT_POWDER); };
OPPONENT(SPECIES_WOBBUFFET) { Item(itemLeft); };
OPPONENT(SPECIES_WOBBUFFET) { Item(itemRight); };
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: opponentRight, hit: FALSE); }
TURN { MOVE(playerLeft, MOVE_DRAGON_DARTS, target: chosenTarget, hit: FALSE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(finalTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(finalTarget);
MESSAGE("The Pokémon was hit 2 time(s)!");
}
}

View File

@ -54,3 +54,7 @@ SINGLE_BATTLE_TEST("Dream Eater fails if Heal Block applies")
}
}
}
TO_DO_BATTLE_TEST("Dream Eater works on targets with Comatose");
TO_DO_BATTLE_TEST("Dream Eater fails if the target is behind a Substitute (Gen 1-4)");
TO_DO_BATTLE_TEST("Dream Eater works if the target is behind a Substitute (Gen 5+)");

View File

@ -0,0 +1,20 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Dynamax Cannon causes double damage to Dynamaxed Pokemon", s16 damage)
{
u32 dynamax;
PARAMETRIZE { dynamax = GIMMICK_NONE; }
PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; }
GIVEN {
ASSUME(gMovesInfo[MOVE_DYNAMAX_CANNON].effect == EFFECT_DYNAMAX_DOUBLE_DMG);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE, gimmick: dynamax); MOVE(opponent, MOVE_DYNAMAX_CANNON); }
} SCENE {
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(2.0), results[1].damage);
}
}

View File

@ -58,25 +58,6 @@ SINGLE_BATTLE_TEST("Leech Seed recovery is prevented by Heal Block")
}
}
SINGLE_BATTLE_TEST("Leech Seed recovery will drain the hp of user if leech seeded mon has Liquid Ooze")
{
s16 damage;
s16 healed;
GIVEN {
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
} WHEN {
TURN { MOVE(player, MOVE_LEECH_SEED); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, player);
HP_BAR(opponent, captureDamage: &damage);
HP_BAR(player, captureDamage: &healed);
} THEN {
EXPECT_EQ(damage, healed);
}
}
TO_DO_BATTLE_TEST("Leech Seed doesn't affect already seeded targets")
TO_DO_BATTLE_TEST("Leech Seed's effect is paused until a new battler replaces the original user's position") // Faint, can't be replaced, then revived.
TO_DO_BATTLE_TEST("Leech Seed's effect pause still prevents it from being seeded again")

View File

@ -117,3 +117,18 @@ SINGLE_BATTLE_TEST("Salt Cure residual damage does not inflict any damage agains
}
}
}
SINGLE_BATTLE_TEST("If Salt Cure faints the target, messages will be applied in the correct order")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(25); }
} WHEN {
TURN { MOVE(player, MOVE_SALT_CURE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SALT_CURE, player);
MESSAGE("The opposing Wobbuffet is being salt cured!");
MESSAGE("The opposing Wobbuffet is hurt by Salt Cure!");
MESSAGE("The opposing Wobbuffet fainted!");
}
}

View File

@ -165,34 +165,3 @@ SINGLE_BATTLE_TEST("Strength Sap restores more HP if Big Root is held", s16 hp)
EXPECT_GT(abs(results[1].hp), abs(results[0].hp));
}
}
SINGLE_BATTLE_TEST("Strength Sap makes attacker lose HP if target's ability is Liquid Ooze")
{
s16 lostHp;
s32 atkStat;
PARAMETRIZE { atkStat = 100; }
PARAMETRIZE { atkStat = 490; } // Checks that attacker can faint with no problems.
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Attack(atkStat); Ability(ABILITY_LIQUID_OOZE); }
} WHEN {
TURN { MOVE(player, MOVE_STRENGTH_SAP); if (atkStat == 490) { SEND_OUT(player, 1); } }
} SCENE {
MESSAGE("Wobbuffet used Strength Sap!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_STRENGTH_SAP, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's Attack fell!");
ABILITY_POPUP(opponent, ABILITY_LIQUID_OOZE);
HP_BAR(player, captureDamage: &lostHp);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
if (atkStat >= 490) {
MESSAGE("Wobbuffet fainted!");
SEND_IN_MESSAGE("Wobbuffet");
}
} THEN {
EXPECT_EQ(lostHp, atkStat);
}
}