Merge branch 'RHH/master' into RHH/upcoming

# Conflicts:
#	src/battle_script_commands.c
This commit is contained in:
Eduardo Quezada 2023-10-19 08:10:49 -03:00
commit 6348c24be1
26 changed files with 832 additions and 151 deletions

View File

@ -15675,7 +15675,7 @@ bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler)
{
if (move != MOVE_NONE && move != MOVE_STRUGGLE
&& gBattleMoves[move].split != SPLIT_STATUS
&& gBattleMoves[move].strikeCount <= 2)
&& gBattleMoves[move].strikeCount < 2)
{
u32 i;
for (i = 0; i < ARRAY_COUNT(sParentalBondBannedEffects); i++)

View File

@ -8993,18 +8993,6 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32
modifier = uq4_12_multiply(modifier, UQ_4_12(1.33));
}
if (IsAbilityOnField(ABILITY_VESSEL_OF_RUIN) && atkAbility != ABILITY_VESSEL_OF_RUIN && IS_MOVE_SPECIAL(gCurrentMove))
modifier = uq4_12_multiply(modifier, UQ_4_12(0.75));
if (IsAbilityOnField(ABILITY_SWORD_OF_RUIN) && defAbility != ABILITY_SWORD_OF_RUIN && IS_MOVE_PHYSICAL(gCurrentMove))
modifier = uq4_12_multiply(modifier, UQ_4_12(1.25));
if (IsAbilityOnField(ABILITY_TABLETS_OF_RUIN) && atkAbility != ABILITY_TABLETS_OF_RUIN && IS_MOVE_PHYSICAL(gCurrentMove))
modifier = uq4_12_multiply(modifier, UQ_4_12(0.75));
if (IsAbilityOnField(ABILITY_BEADS_OF_RUIN) && defAbility != ABILITY_BEADS_OF_RUIN && IS_MOVE_SPECIAL(gCurrentMove))
modifier = uq4_12_multiply(modifier, UQ_4_12(1.25));
// attacker partner's abilities
if (IsBattlerAlive(BATTLE_PARTNER(battlerAtk)))
{
@ -9288,6 +9276,13 @@ static inline u32 CalcAttackStat(u32 move, u32 battlerAtk, u32 battlerDef, u32 m
}
}
// field abilities
if (IsAbilityOnField(ABILITY_VESSEL_OF_RUIN) && atkAbility != ABILITY_VESSEL_OF_RUIN && IS_MOVE_SPECIAL(move))
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75));
if (IsAbilityOnField(ABILITY_TABLETS_OF_RUIN) && atkAbility != ABILITY_TABLETS_OF_RUIN && IS_MOVE_PHYSICAL(move))
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75));
// attacker's hold effect
switch (holdEffectAtk)
{
@ -9435,6 +9430,13 @@ static inline u32 CalcDefenseStat(u32 move, u32 battlerAtk, u32 battlerDef, u32
}
}
// field abilities
if (IsAbilityOnField(ABILITY_SWORD_OF_RUIN) && defAbility != ABILITY_SWORD_OF_RUIN && usesDefStat)
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75));
if (IsAbilityOnField(ABILITY_BEADS_OF_RUIN) && defAbility != ABILITY_BEADS_OF_RUIN && !usesDefStat)
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75));
// target's hold effects
switch (holdEffectDef)
{

View File

@ -25,7 +25,7 @@ SINGLE_BATTLE_TEST("Beads of Ruin reduces Sp. Def", s16 damage)
}
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.25), results[1].damage);
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.33), results[1].damage);
}
}

View File

@ -0,0 +1,17 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Harvest has a 50% chance to restore a Berry at the end of the turn");
TO_DO_BATTLE_TEST("Harvest always restores a Berry in Sunlight");
TO_DO_BATTLE_TEST("Harvest restores a Berry even after being switched out and back in");
TO_DO_BATTLE_TEST("Harvest restores a Berry consumed by Fling");
TO_DO_BATTLE_TEST("Harvest restores a Berry consumed by Natural Gift");
TO_DO_BATTLE_TEST("Harvest only works once per turn"); // Check for berries that are consumed immediately, like Pecha Berry
TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry when destroyed by Incinerate");
TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry when knocked off by Knock Off");
TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry when eaten by Bug Bite/Pluck");
TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry that's collected via Pickup");
TO_DO_BATTLE_TEST("Harvest order is affected by speed");
TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry when transfered to another Pokémon");
TO_DO_BATTLE_TEST("Harvest can restore a Berry that was transferred from another Pokémon");
TO_DO_BATTLE_TEST("Harvest can only restore the newest berry consumed that was transferred from another Pokémon instead of its original Berry");

View File

@ -0,0 +1,58 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Parental Bond converts Tackle into a two-strike move")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_TACKLE].split != SPLIT_STATUS);
ASSUME(gBattleMoves[MOVE_TACKLE].strikeCount < 2);
ASSUME(gBattleMoves[MOVE_TACKLE].effect == EFFECT_HIT);
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE, megaEvolve: TRUE); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
MESSAGE("Kangaskhan's Kangaskhanite is reacting to 1's Mega Ring!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, player);
MESSAGE("Kangaskhan has Mega Evolved into Mega Kangaskhan!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
} THEN {
EXPECT_EQ(player->species, SPECIES_KANGASKHAN_MEGA);
}
}
TO_DO_BATTLE_TEST("Parental Bond tests");
// Temporary TODO: Convert Bulbapedia description into tests.
/*
In battle
Parental Bond causes most damaging moves used by the Pokémon to become two-strike moves. It does not affect multi-strike moves.
If a move could hit multiple targets (including allies), such as Earthquake and Rock Slide, it will not strike twice; however, if it can only hit a single Pokémon, such as in a Single Battle or if using a move that can hit multiple targets when only one target is in range, it will strike twice. If a move could hit multiple Pokémon but only hits one due to missing the other Pokémon, it will only strike once.
Since Parental Bond turns moves into two-hit multi-strike moves, each strike has a separate chance to be a critical hit, items and Abilities that trigger upon strike or contact such as Cursed Body and Rocky Helmet occur for each strike, and Spiky Shield and King's Shield only damage and decrease Attack (respectively) once if they protect a Pokémon from a contact move used by a Pokémon with Parental Bond. Additionally, there is only one accuracy check, so either both strikes hit or both strikes miss.
Any attack which has a secondary effect (except Secret Power) has the same secondary effect on both strikes (such as Power-Up Punch); if a secondary effect has a certain chance of occurring, each strike has an independent chance of activating that effect. Even if the Pokémon's Ability is changed to Mummy after the first strike, it will continue to make a second strike regardless. Pay Day scatters coins after the first strike only. Incinerate destroys applicable held items after each strike.
Unlike other secondary effects, Secret Power's secondary effect can only occur after the final strike. If a move has recoil damage, the recoil will be based on the damage dealt by both strikes, but will be taken after the final strike; Struggle will inflict recoil damage equal to half the user's maximum HP (after the final strike). Moves that switch the target out and moves that switch the user out strike twice, then force a Pokémon to switch out after both strikes are conducted. Thief, Covet, Bug Bite, and Pluck do not steal or eat the target's held item until after the final strike, so if the target could use its item after the first strike (e.g. due to low HP), it will use it before the attacker can steal or eat it. Smelling Salts, Wake-Up Slap, and Knock Off do not cure the target's status condition or remove its held item (respectively) until after the final strike, so both strikes get the increased power. Fire-type moves, Scald, and Steam Eruption thaw a frozen target after the final strike (so a frozen target cannot be thawed and then burned by the same move). Smack Down and Thousand Arrows only cause the target to fall to the ground after the final strike. If Meloetta has Parental Bond and uses Relic Song, it will change Forme only once, after the final strike. Burn Up does not remove the user's Fire type until after the second strike (so both strikes receive same-type attack bonus).
If a Pokémon with Parental Bond uses an Electric-type move on a Pokémon with Lightning Rod, or a Water-type move on a Pokémon with Storm Drain, the effect of raising the target's Special Attack will only happen once.
If Present heals the target it will only strike once, but if it damages the target it will strike twice (the second strike will always damage the target). Fixed-damage moves (such as Seismic Toss and Dragon Rage) deal the full amount of damage for both strikes. The damage dealt by Psywave is generated separately for each strike, and the second strike's damage is not halved. Each strike of Super Fang halves the target's HP (effectively quartering it if HP is not changed between strikes). Counter, Mirror Coat, Metal Burst, and Bide deal the full amount of damage for both strikes. The first strike of Assurance counts as previously taking damage for the second strike, giving it increased power. Fury Cutter and Echoed Voice only consider uses of the move rather than hits, so the second strike's power is not boosted by the first strike. Grass Pledge, Fire Pledge, and Water Pledge strike twice, even when used as a combination move. Natural Gift and Spit Up strike twice. Moves that require recharging after use strike twice, but the user only needs to recharge for one turn.
One-hit knockout moves, Fling, Self-Destruct, Explosion, Final Gambit, Uproar, Rollout, and Ice Ball only strike once. (Other consecutively executed moves, such as Outrage, can strike twice.) Moves with a charging turn (such as Fly and Solar Beam) only strike once, even if the Pokémon becomes fully charged in one turn (such as with a Power Herb). Endeavor also only strikes once, even if the user or target's HP is changed after it strikes (such as by Iron Barbs or the Sitrus Berry). Confusion damage only occurs once.
Spirit Shackle and Anchor Shot only trap the target after the final strike.
Generation VI
The second strike has its damage halved (unless it is a set-damage move)
Generation VII onward
The second strike now deals 25% of its usual damage (unless it is a set-damage move).
Parental Bond does not affect Z-Moves or Max Moves.
*/
// TONS OF TESTS NEEDED. FOR NOW, THIS SINGLE TEST IS MADE TO MAKE SURE AN ISSUE WAS FIXED.

View File

@ -0,0 +1,30 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon")
{
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_UMBREON].types[0] == TYPE_DARK);
PLAYER(SPECIES_UMBREON);
OPPONENT(SPECIES_MURKROW) { Ability(ABILITY_PRANKSTER); }
} WHEN {
TURN { MOVE(opponent, MOVE_CONFUSE_RAY); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, player);
MESSAGE("It doesn't affect Umbreon…");
}
}
TO_DO_BATTLE_TEST("Prankster-affected moves affect Ally Dark-type Pokémon")
TO_DO_BATTLE_TEST("Prankster-affected moves called via Assist don't affect Dark-type Pokémon");
TO_DO_BATTLE_TEST("Prankster-affected moves called via Nature Power don't affect Dark-type Pokémon");
TO_DO_BATTLE_TEST("Prankster-affected moves called via Instruct affect Dark-type Pokémon");
TO_DO_BATTLE_TEST("Prankster-affected moves called via After you affect Dark-type Pokémon");
TO_DO_BATTLE_TEST("Prankster-affected moves that are bounced back by Magic Bounce/Coat can affect Dark-type Pokémon");
TO_DO_BATTLE_TEST("Prankster-affected moves that are bounced back by Magic Coat from a Pokémon with Prankster can't affect Dark-type Pokémon");
TO_DO_BATTLE_TEST("Prankster-affected moves that target all Pokémon are successful regardless of the presence of Dark-type Pokémon");
TO_DO_BATTLE_TEST("Prankster-affected moves that target all Pokémon are successful regardless of the presence of Dark-type Pokémon");
TO_DO_BATTLE_TEST("Prankster-affected move effects don't affect Dark-type Pokémon");
TO_DO_BATTLE_TEST("Prankster increases the priority of moves by 1");
TO_DO_BATTLE_TEST("Prankster increases the priority of status Z-Moves by 1");
TO_DO_BATTLE_TEST("Prankster increases the priority of Extreme Evoboost by 1");
TO_DO_BATTLE_TEST("Prankster is blocked by Quick Guard in Gen5+");

View File

@ -25,7 +25,7 @@ SINGLE_BATTLE_TEST("Sword of Ruin reduces Defense", s16 damage)
}
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.25), results[1].damage);
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.33), results[1].damage);
}
}

View File

@ -10,7 +10,6 @@ SINGLE_BATTLE_TEST("Safety Goggles block powder and spore moves")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_STUN_SPORE].powderMove);
ASSUME(gItems[ITEM_SAFETY_GOGGLES].holdEffect == HOLD_EFFECT_SAFETY_GOGGLES);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_ABRA) { Item(ITEM_SAFETY_GOGGLES); }
} WHEN {
@ -21,6 +20,28 @@ SINGLE_BATTLE_TEST("Safety Goggles block powder and spore moves")
}
}
TO_DO_BATTLE_TEST("Safety Goggles blocks damage from hail");
TO_DO_BATTLE_TEST("Safety Goggles blocks damage from sandstorm");
SINGLE_BATTLE_TEST("Safety Goggles blocks damage from Hail")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(player, MOVE_HAIL); }
} SCENE {
NOT MESSAGE("Foe Wobbuffet is pelted by HAIL!");
}
}
SINGLE_BATTLE_TEST("Safety Goggles blocks damage from Sandstorm")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(player, MOVE_SANDSTORM); }
} SCENE {
NOT MESSAGE("Foe Wobbuffet is buffeted by the sandstorm!");
}
}
TO_DO_BATTLE_TEST("Safety Goggles blocks Effect Spore's effect");

View File

@ -0,0 +1,33 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_AURORA_VEIL].effect == EFFECT_AURORA_VEIL);
}
SINGLE_BATTLE_TEST("Aurora Veil can only be used in Hail and Snow")
{
u32 move;
PARAMETRIZE { move = MOVE_CELEBRATE; }
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_AURORA_VEIL); }
} SCENE {
if (move == MOVE_CELEBRATE)
MESSAGE("But it failed!");
else
NOT MESSAGE("But it failed!");
}
}
TO_DO_BATTLE_TEST("Aurora Veil reduces damage done to the user by half in singles")
TO_DO_BATTLE_TEST("Aurora Veil reduces damage done to the user by roughly a third in doubles")
TO_DO_BATTLE_TEST("Aurora Veil's damage reduction is ignored by Critical Hits")
TO_DO_BATTLE_TEST("Aurora Veil's damage reduction doesn't stack with Reflect or Light Screen")
TO_DO_BATTLE_TEST("Aurora Veil doesn't reduce confusion damage")
TO_DO_BATTLE_TEST("Aurora Veil doesn't reduce damage done by moves that do direct damage") // Bide, Counter, Endeavor, Final Gambit, Metal Burst, Mirror Coat, Psywave, Seismic Toss, Sonic Boom, Super Fang

View File

@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("Ember inflicts burn")
}
}
SINGLE_BATTLE_TEST("Ember cannot burn a Fire-type")
SINGLE_BATTLE_TEST("Ember cannot burn a Fire-type Pokémon")
{
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_CHARMANDER].types[0] == TYPE_FIRE);

View File

@ -4,6 +4,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_POWDER_SNOW].effect == EFFECT_FREEZE_HIT);
ASSUME(gBattleMoves[MOVE_BLIZZARD].accuracy == 70);
}
SINGLE_BATTLE_TEST("Powder Snow inflicts freeze")
@ -21,7 +22,7 @@ SINGLE_BATTLE_TEST("Powder Snow inflicts freeze")
}
}
SINGLE_BATTLE_TEST("Powder Snow cannot freeze an Ice-type")
SINGLE_BATTLE_TEST("Powder Snow cannot freeze an Ice-type Pokémon")
{
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_SNORUNT].types[0] == TYPE_ICE);
@ -36,3 +37,30 @@ SINGLE_BATTLE_TEST("Powder Snow cannot freeze an Ice-type")
NOT STATUS_ICON(opponent, freeze: TRUE);
}
}
SINGLE_BATTLE_TEST("Freeze cannot be inflicted in Sunlight")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, MOVE_ICE_BEAM); }
} SCENE {
NOT MESSAGE("Wobbuffet was frozen solid!");
}
}
SINGLE_BATTLE_TEST("Blizzard bypasses accuracy checks in Hail and Snow")
{
u32 move;
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_BLIZZARD); }
} SCENE {
NONE_OF { MESSAGE("Wobbuffet's attack missed!"); }
}
}

View File

@ -0,0 +1,35 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_HURRICANE].effect == EFFECT_HURRICANE);
ASSUME(gBattleMoves[MOVE_HURRICANE].accuracy == 70);
}
SINGLE_BATTLE_TEST("Hurricane's accuracy is lowered to 50% in Sunlight")
{
PASSES_RANDOMLY(50, 100, RNG_ACCURACY);
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_HURRICANE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HURRICANE, opponent);
}
}
SINGLE_BATTLE_TEST("Hurricane bypasses accuracy checks in Rain")
{
PASSES_RANDOMLY(100, 100, RNG_ACCURACY);
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_RAIN_DANCE); MOVE(player, MOVE_HURRICANE); }
} SCENE {
NONE_OF { MESSAGE("Wobbuffet's attack missed!"); }
}
}
TO_DO_BATTLE_TEST("Hurricane Veil can hit airborne targets") // Fly, Bounce, Sky Drop

View File

@ -0,0 +1,26 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_LEECH_SEED].effect == EFFECT_LEECH_SEED);
}
SINGLE_BATTLE_TEST("Leech Seed doesn't affect Grass-type Pokémon")
{
PASSES_RANDOMLY(90, 100, RNG_ACCURACY);
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_GRASS);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_ODDISH);
} WHEN {
TURN { MOVE(player, MOVE_LEECH_SEED); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, player);
MESSAGE("It doesn't affect Foe Oddish…");
}
}
TO_DO_BATTLE_TEST("Leech Seed doesn't affect already seeded targets")
TO_DO_BATTLE_TEST("Leech Seeded targets lose 1/8 of its max HP every turn and give it to the user")
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

@ -0,0 +1,48 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_MOONLIGHT].effect == EFFECT_MOONLIGHT);
}
SINGLE_BATTLE_TEST("Moonlight recovers 1/2 of the user's max HP")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(200); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_MOONLIGHT); }
} SCENE {
HP_BAR(player, damage: -(200 / 2));
}
}
SINGLE_BATTLE_TEST("Moonlight recovers 2/3 of the user's max HP in Sunlight")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(300); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, MOVE_MOONLIGHT); }
} SCENE {
HP_BAR(player, damage: -(300 / 1.5));
}
}
SINGLE_BATTLE_TEST("Moonlight recovers 1/4 of the user's max HP in Rain, Sandstorm, Hail, and Snow")
{
u32 move;
PARAMETRIZE { move = MOVE_RAIN_DANCE; }
PARAMETRIZE { move = MOVE_SANDSTORM; }
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_MOONLIGHT); }
} SCENE {
HP_BAR(player, damage: -(400 / 4));
}
}

View File

@ -0,0 +1,48 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_MORNING_SUN].effect == EFFECT_MORNING_SUN);
}
SINGLE_BATTLE_TEST("Morning Sun recovers 1/2 of the user's max HP")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(200); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_MORNING_SUN); }
} SCENE {
HP_BAR(player, damage: -(200 / 2));
}
}
SINGLE_BATTLE_TEST("Morning Sun recovers 2/3 of the user's max HP in Sunlight")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(300); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, MOVE_MORNING_SUN); }
} SCENE {
HP_BAR(player, damage: -(300 / 1.5));
}
}
SINGLE_BATTLE_TEST("Morning Sun recovers 1/4 of the user's max HP in Rain, Sandstorm, Hail, and Snow")
{
u32 move;
PARAMETRIZE { move = MOVE_RAIN_DANCE; }
PARAMETRIZE { move = MOVE_SANDSTORM; }
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_MORNING_SUN); }
} SCENE {
HP_BAR(player, damage: -(400 / 4));
}
}

View File

@ -0,0 +1,26 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_SHEER_COLD].effect == EFFECT_OHKO);
}
SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon")
{
GIVEN {
ASSUME(B_SHEER_COLD_IMMUNITY >= GEN_7);
ASSUME(gSpeciesInfo[SPECIES_GLALIE].types[0] == TYPE_ICE);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_GLALIE);
} WHEN {
TURN { MOVE(player, MOVE_SHEER_COLD); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
MESSAGE("It doesn't affect Foe Glalie…");
}
}
TO_DO_BATTLE_TEST("Fissure faints the target, skipping regular damage calculations")
TO_DO_BATTLE_TEST("Fissure always fails if the target has a higher level than the user")
TO_DO_BATTLE_TEST("Fissure's accuracy increases by 1% for every level the user has over the target")
TO_DO_BATTLE_TEST("Fissure's ignores non-stage accuracy modifiers") // Gravity, Wide Lens, Compound Eyes

View File

@ -4,6 +4,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_POISON_STING].effect == EFFECT_POISON_HIT);
ASSUME(gBattleMoves[MOVE_TWINEEDLE].effect == EFFECT_POISON_HIT);
}
SINGLE_BATTLE_TEST("Poison Sting inflicts poison")
@ -22,16 +23,20 @@ SINGLE_BATTLE_TEST("Poison Sting inflicts poison")
}
}
SINGLE_BATTLE_TEST("Poison Sting cannot poison Poison-type")
SINGLE_BATTLE_TEST("Poison cannot be inflicted on Poison and Steel-type Pokémon")
{
u32 mon;
PARAMETRIZE { mon = SPECIES_NIDORAN_M; }
PARAMETRIZE { mon = SPECIES_REGISTEEL; }
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_NIDORAN_M].types[0] == TYPE_POISON);
ASSUME(gSpeciesInfo[SPECIES_REGISTEEL].types[0] == TYPE_STEEL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_NIDORAN_M);
OPPONENT(mon);
} WHEN {
TURN { MOVE(player, MOVE_POISON_STING); }
TURN { MOVE(player, MOVE_TWINEEDLE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_STING, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TWINEEDLE, player);
HP_BAR(opponent);
NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
NOT STATUS_ICON(opponent, poison: TRUE);

View File

@ -0,0 +1,167 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_SOLAR_BEAM].effect == EFFECT_SOLAR_BEAM);
ASSUME(gBattleMoves[MOVE_SOLAR_BLADE].effect == EFFECT_SOLAR_BEAM);
}
SINGLE_BATTLE_TEST("Solar Beam and Solar Blade can be used instantly in Sunlight")
{
u32 move;
PARAMETRIZE { move = MOVE_SOLAR_BEAM; }
PARAMETRIZE { move = MOVE_SOLAR_BLADE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, move); }
} SCENE {
NOT MESSAGE("Wobbuffet took in sunlight!");
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in Rain", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in Rain", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in a Sandstorm", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SANDSTORM; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in a Sandstorm", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SANDSTORM; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in Hail", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_HAIL; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in Hail", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_HAIL; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Beam's power is halved in Snow", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Solar Blade's power is halved in Snow", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}

View File

@ -0,0 +1,48 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_SYNTHESIS].effect == EFFECT_SYNTHESIS);
}
SINGLE_BATTLE_TEST("Synthesis recovers 1/2 of the user's max HP")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(200); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SYNTHESIS); }
} SCENE {
HP_BAR(player, damage: -(200 / 2));
}
}
SINGLE_BATTLE_TEST("Synthesis recovers 2/3 of the user's max HP in Sunlight")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(300); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, MOVE_SYNTHESIS); }
} SCENE {
HP_BAR(player, damage: -(300 / 1.5));
}
}
SINGLE_BATTLE_TEST("Synthesis recovers 1/4 of the user's max HP in Rain, Sandstorm, Hail, and Snow")
{
u32 move;
PARAMETRIZE { move = MOVE_RAIN_DANCE; }
PARAMETRIZE { move = MOVE_SANDSTORM; }
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SYNTHESIS); }
} SCENE {
HP_BAR(player, damage: -(400 / 4));
}
}

View File

@ -0,0 +1,34 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_THUNDER].effect == EFFECT_THUNDER);
ASSUME(gBattleMoves[MOVE_THUNDER].accuracy == 70);
}
SINGLE_BATTLE_TEST("Thunder's accuracy is lowered to 50% in Sunlight")
{
PASSES_RANDOMLY(50, 100, RNG_ACCURACY);
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_THUNDER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER, opponent);
}
}
SINGLE_BATTLE_TEST("Thunder bypasses accuracy checks in Rain")
{
PASSES_RANDOMLY(100, 100, RNG_ACCURACY);
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_RAIN_DANCE); MOVE(player, MOVE_THUNDER); }
} SCENE {
NONE_OF { MESSAGE("Wobbuffet's attack missed!"); }
}
}

View File

@ -151,7 +151,7 @@ SINGLE_BATTLE_TEST("Toxic Spikes do not affect Steel-types")
}
}
SINGLE_BATTLE_TEST("Toxic Spikes are removed by grounded Poison-types")
SINGLE_BATTLE_TEST("Toxic Spikes are removed by grounded Poison-type Pokémon on switch in")
{
u32 species;
u32 item = ITEM_NONE;
@ -190,7 +190,7 @@ SINGLE_BATTLE_TEST("Toxic Spikes are removed by grounded Poison-types")
// A Pokémon that gets passed magnet rise should still remove the Toxic
// Spikes even though it is airborne.
// The test currently fails, because we don't incorporate this bug.
SINGLE_BATTLE_TEST("Toxic Spikes are removed by Poison-types affected by Magnet Rise")
SINGLE_BATTLE_TEST("Toxic Spikes are removed by Poison-type Pokémon affected by Magnet Rise on switch in")
{
KNOWN_FAILING;
GIVEN {

View File

@ -0,0 +1,80 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_WEATHER_BALL].effect == EFFECT_WEATHER_BALL);
}
SINGLE_BATTLE_TEST("Weather Ball doubles its power and turns to a Fire-type move in Sunlight", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SUNNY_DAY; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_MEGANIUM);
} WHEN {
TURN { MOVE(player, move); }
TURN { MOVE(player, MOVE_WEATHER_BALL); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(6.0), results[1].damage); // double base power + type effectiveness + sun 50% boost
}
}
SINGLE_BATTLE_TEST("Weather Ball doubles its power and turns to a Water-type move in Rain", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_ARCANINE);
} WHEN {
TURN { MOVE(player, move); }
TURN { MOVE(player, MOVE_WEATHER_BALL); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(6.0), results[1].damage); // double base power + type effectiveness + rain 50% boost
}
}
SINGLE_BATTLE_TEST("Weather Ball doubles its power and turns to a Rock-type move in a Sandstorm", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SANDSTORM; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_MAGMAR) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(player, move); }
TURN { MOVE(player, MOVE_WEATHER_BALL); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(4.0), results[1].damage); // double base power + type effectiveness.
}
}
SINGLE_BATTLE_TEST("Weather Ball doubles its power and turns to an Ice-type move in Hail and Snow", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_HAIL; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_DRAGONAIR) { Item(ITEM_SAFETY_GOGGLES); };
} WHEN {
TURN { MOVE(player, move); }
TURN { MOVE(player, MOVE_WEATHER_BALL); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(4.0), results[1].damage); // double base power + type effectiveness.
}
}

View File

@ -1,7 +1,7 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Grass-type Pokémon block powder and spore moves")
SINGLE_BATTLE_TEST("Powder moves are blocked by Grass-type Pokémon")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_STUN_SPORE].powderMove);

View File

@ -0,0 +1,31 @@
#include "global.h"
#include "test/battle.h"
// Please add Hail interactions with move, item and ability effects on their respective files.
SINGLE_BATTLE_TEST("Hail deals 1/16 damage per turn")
{
s16 hailDamage;
GIVEN {
PLAYER(SPECIES_GLALIE);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {MOVE(player, MOVE_HAIL);}
} SCENE {
MESSAGE("Foe Wobbuffet is pelted by HAIL!");
HP_BAR(opponent, captureDamage: &hailDamage);
} THEN { EXPECT_EQ(hailDamage, opponent->maxHP / 16); }
}
SINGLE_BATTLE_TEST("Hail damage does not affect Ice-type Pokémon")
{
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_GLALIE].types[0] == TYPE_ICE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_GLALIE);
} WHEN {
TURN {MOVE(player, MOVE_HAIL);}
} SCENE {
NOT MESSAGE("Foe Glalie is pelted by HAIL!");
}
}

View File

@ -0,0 +1,66 @@
#include "global.h"
#include "test/battle.h"
// Please add Sandstorm interactions with move, item and ability effects on their respective files.
SINGLE_BATTLE_TEST("Sandstorm deals 1/16 damage per turn")
{
s16 sandstormDamage;
GIVEN {
PLAYER(SPECIES_SANDSLASH);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {MOVE(player, MOVE_SANDSTORM);}
} SCENE {
MESSAGE("Foe Wobbuffet is buffeted by the sandstorm!");
HP_BAR(opponent, captureDamage: &sandstormDamage);
} THEN { EXPECT_EQ(sandstormDamage, opponent->maxHP / 16); }
}
SINGLE_BATTLE_TEST("Sandstorm multiplies the special defense of Rock-types by 1.5x", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_SANDSTORM; }
PARAMETRIZE{ move = MOVE_CELEBRATE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) ;
OPPONENT(SPECIES_NOSEPASS);
} WHEN {
TURN { MOVE(opponent, move); }
TURN { MOVE(player, MOVE_SWIFT); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Sandstorm damage does not hurt Ground, Rock, and Steel-type Pokémon")
{
u32 mon;
PARAMETRIZE { mon = SPECIES_SANDSLASH; }
PARAMETRIZE { mon = SPECIES_NOSEPASS; }
PARAMETRIZE { mon = SPECIES_REGISTEEL; }
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_SANDSLASH].types[0] == TYPE_GROUND);
ASSUME(gSpeciesInfo[SPECIES_NOSEPASS].types[0] == TYPE_ROCK);
ASSUME(gSpeciesInfo[SPECIES_REGISTEEL].types[0] == TYPE_STEEL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(mon);
} WHEN {
TURN { MOVE(player, MOVE_SANDSTORM); }
} SCENE {
switch (mon)
{
case SPECIES_SANDSLASH:
NOT MESSAGE("Foe Sandslash is buffeted by the sandstorm!");
break;
case SPECIES_NOSEPASS:
NOT MESSAGE("Foe Nosepass is buffeted by the sandstorm!");
break;
case SPECIES_REGISTEEL:
NOT MESSAGE("Foe Registeel is buffeted by the sandstorm!");
break;
}
}
}

View File

@ -1,6 +1,7 @@
#include "global.h"
#include "test/battle.h"
// Please add Snow interactions with move, item and ability effects on their respective files.
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE);
@ -8,7 +9,7 @@ ASSUMPTIONS
ASSUME(gSpeciesInfo[SPECIES_GLALIE].types[0] == TYPE_ICE || gSpeciesInfo[SPECIES_GLALIE].types[1] == TYPE_ICE);
}
SINGLE_BATTLE_TEST("Snow increases the defense of Ice types by 50 %", s16 damage)
SINGLE_BATTLE_TEST("Snow multiplies the defense of Ice-types by 1.5x", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
@ -25,126 +26,3 @@ SINGLE_BATTLE_TEST("Snow increases the defense of Ice types by 50 %", s16 damage
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Snow turns Weather Ball to an Ice-type move and doubles its power", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
ASSUME(gBattleMoves[MOVE_WEATHER_BALL].effect == EFFECT_WEATHER_BALL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_DRAGONAIR);
} WHEN {
TURN { MOVE(player, move); }
TURN { MOVE(player, MOVE_WEATHER_BALL); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(4.0), results[1].damage); // double base power + type effectiveness.
}
}
SINGLE_BATTLE_TEST("Snow allows Blizzard to bypass accuracy checks")
{
PASSES_RANDOMLY(100, 100, RNG_ACCURACY);
GIVEN {
ASSUME(gBattleMoves[MOVE_BLIZZARD].accuracy == 70);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SNOWSCAPE); MOVE(player, MOVE_BLIZZARD); }
} SCENE {
NONE_OF { MESSAGE("Wobbuffet's attack missed!"); }
}
}
SINGLE_BATTLE_TEST("Snow halves the power of Solar Beam", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
ASSUME(gBattleMoves[MOVE_SOLAR_BEAM].effect == EFFECT_SOLAR_BEAM);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BEAM); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Snow halves the power of Solar Blade", s16 damage)
{
u16 move;
PARAMETRIZE{ move = MOVE_CELEBRATE; }
PARAMETRIZE{ move = MOVE_SNOWSCAPE; }
GIVEN {
ASSUME(gBattleMoves[MOVE_SOLAR_BLADE].effect == EFFECT_SOLAR_BEAM);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, move); MOVE(player, MOVE_SOLAR_BLADE); }
TURN { SKIP_TURN(player); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Snow causes Moonlight to recover 1/4 of the user's max HP")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_MOONLIGHT].effect == EFFECT_MOONLIGHT);
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SNOWSCAPE); MOVE(player, MOVE_MOONLIGHT); }
} SCENE {
HP_BAR(player, damage: -(400 / 4));
}
}
SINGLE_BATTLE_TEST("Snow causes Moonlight to recover 1/4 of the user's max HP")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_MOONLIGHT].effect == EFFECT_MOONLIGHT);
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SNOWSCAPE); MOVE(player, MOVE_MOONLIGHT); }
} SCENE {
HP_BAR(player, damage: -(400 / 4));
}
}
SINGLE_BATTLE_TEST("Snow causes Synthesis to recover 1/4 of the user's max HP")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_SYNTHESIS].effect == EFFECT_SYNTHESIS);
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SNOWSCAPE); MOVE(player, MOVE_SYNTHESIS); }
} SCENE {
HP_BAR(player, damage: -(400 / 4));
}
}
SINGLE_BATTLE_TEST("Snow causes Morning Sun to recover 1/4 of the user's max HP")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_MORNING_SUN].effect == EFFECT_MORNING_SUN);
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SNOWSCAPE); MOVE(player, MOVE_MORNING_SUN); }
} SCENE {
HP_BAR(player, damage: -(400 / 4));
}
}