Fix issues and add more ability tests

This commit is contained in:
Bassoonian 2023-10-06 15:13:26 +02:00
parent 9735c5d68e
commit cee84f0f74
10 changed files with 215 additions and 6 deletions

View File

@ -126,6 +126,7 @@
#define B_ABSORBING_ABILITY_STRING GEN_LATEST // In Gen5+, the abilities that absorb moves of a certain type use a generic string for stat increases and decreases.
#define B_LEAF_GUARD_PREVENTS_REST GEN_LATEST // In Gen5+, Leaf Guard prevents the use of Rest in harsh sunlight.
#define B_SNOW_WARNING GEN_LATEST // In Gen9+, Snow Warning will summon snow instead of hail.
#define B_TRANSISTOR GEN_LATEST // In Gen9+, Transistor will only boost Electric-type moves by 1.3x as opposed to 1.5x.
// Item settings
#define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore hp activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn.

View File

@ -8964,7 +8964,11 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32
break;
case ABILITY_TRANSISTOR:
if (moveType == TYPE_ELECTRIC)
#if B_TRANSISTOR >= GEN_9
modifier = uq4_12_multiply(modifier, UQ_4_12(5325 / 4096));
#else
modifier = uq4_12_multiply(modifier, UQ_4_12(1.5));
#endif
break;
case ABILITY_DRAGONS_MAW:
if (moveType == TYPE_DRAGON)

View File

@ -43,4 +43,4 @@ SINGLE_BATTLE_TEST("Defeatist halves Special Attack when HP <= 50%", s16 damage)
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
}

View File

@ -0,0 +1,33 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Dragon's Maw increases Dragon-type move damage", s16 damage)
{
u32 move;
u16 ability;
PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_KLUTZ; }
PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_DRAGONS_MAW; }
PARAMETRIZE { move = MOVE_DRAGON_CLAW; ability = ABILITY_KLUTZ; }
PARAMETRIZE { move = MOVE_DRAGON_CLAW; ability = ABILITY_DRAGONS_MAW; }
PARAMETRIZE { move = MOVE_DRAGON_BREATH; ability = ABILITY_KLUTZ; }
PARAMETRIZE { move = MOVE_DRAGON_BREATH; ability = ABILITY_DRAGONS_MAW; }
GIVEN {
ASSUME(gBattleMoves[MOVE_TACKLE].type == TYPE_NORMAL);
ASSUME(gBattleMoves[MOVE_DRAGON_CLAW].type == TYPE_DRAGON);
ASSUME(gBattleMoves[MOVE_DRAGON_BREATH].type == TYPE_DRAGON);
ASSUME(gBattleMoves[MOVE_DRAGON_CLAW].split == SPLIT_PHYSICAL);
ASSUME(gBattleMoves[MOVE_DRAGON_BREATH].split == SPLIT_SPECIAL);
PLAYER(SPECIES_REGIDRAGO) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_EQ(results[0].damage, results[1].damage); // Tackle should be unaffected
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); // Dragon Claw should be affected
EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.5), results[5].damage); // Dragon Breath should be affected
}
}

View File

@ -0,0 +1,46 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Earth Eater heals 25% when hit by ground type moves")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_MUD_SLAP].type == TYPE_GROUND);
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_EARTH_EATER); HP(1); MaxHP(100); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_MUD_SLAP); }
} SCENE {
ABILITY_POPUP(player, ABILITY_EARTH_EATER);
HP_BAR(player, damage: -25);
MESSAGE("Wobbuffet restored HP using its Earth Eater!");
}
}
SINGLE_BATTLE_TEST("Earth Eater does not activate if protected")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_MUD_SLAP].type == TYPE_GROUND);
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_EARTH_EATER); HP(1); MaxHP(100); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_PROTECT); MOVE(opponent, MOVE_MUD_SLAP); }
} SCENE {
NONE_OF { ABILITY_POPUP(player, ABILITY_EARTH_EATER); HP_BAR(player); MESSAGE("Wobbuffet restored HP using its Earth Eater!"); }
}
}
SINGLE_BATTLE_TEST("Earth Eater activates on status moves")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_SAND_ATTACK].type == TYPE_GROUND);
ASSUME(gBattleMoves[MOVE_SAND_ATTACK].split == SPLIT_STATUS);
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_EARTH_EATER); HP(1); MaxHP(100); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SAND_ATTACK); }
} SCENE {
ABILITY_POPUP(player, ABILITY_EARTH_EATER);
HP_BAR(player, damage: -25);
MESSAGE("Wobbuffet restored HP using its Earth Eater!");
}
}

View File

@ -16,9 +16,11 @@ SINGLE_BATTLE_TEST("Gale Wings only grants priority at full HP")
} SCENE {
if (hp == 100) {
MESSAGE("Talonflame used Aerial Ace!");
MESSAGE("Foe Wobbuffet used Celebrate!");
}
else {
MESSAGE("Foe Wobbuffet used Celebrate!");
MESSAGE("Talonflame used Aerial Ace!");
}
}
}
@ -39,9 +41,13 @@ SINGLE_BATTLE_TEST("Gale Wings only grants priority to Flying-type moves")
} SCENE {
if (move == MOVE_AERIAL_ACE) {
MESSAGE("Talonflame used Aerial Ace!");
MESSAGE("Foe Wobbuffet used Celebrate!");
}
else {
MESSAGE("Foe Wobbuffet used Celebrate!");
MESSAGE("Talonflame used Flare Blitz!");
}
}
}
TO_DO_BATTLE_TEST("Gale Wings doesn't increase priority of Flying-type Hidden Power, Natural Gift, Judgment or Tera Blast");

View File

@ -1,10 +1,14 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Poison Heal heals from Poison damage")
SINGLE_BATTLE_TEST("Poison Heal heals from (Toxic) Poison damage")
{
u8 status;
PARAMETRIZE { status=STATUS1_POISON; }
PARAMETRIZE { status=STATUS1_TOXIC_POISON; }
GIVEN {
PLAYER(SPECIES_SHROOMISH) { Ability(ABILITY_POISON_HEAL); Status1(STATUS1_POISON); HP(1), MaxHP(400); }
PLAYER(SPECIES_SHROOMISH) { Ability(ABILITY_POISON_HEAL); Status1(status); HP(1), MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); }
@ -15,17 +19,27 @@ SINGLE_BATTLE_TEST("Poison Heal heals from Poison damage")
}
}
SINGLE_BATTLE_TEST("Poison Heal heals from Toxic Poison damage")
SINGLE_BATTLE_TEST("Poison Heal heals from Toxic Poison damage are constant")
{
s16 turnOneHit;
s16 turnTwoHit;
GIVEN {
PLAYER(SPECIES_SHROOMISH) { Ability(ABILITY_POISON_HEAL); Status1(STATUS1_TOXIC_POISON); HP(1), MaxHP(400); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_CELEBRATE); }
} SCENE {
ABILITY_POPUP(player, ABILITY_POISON_HEAL);
MESSAGE("The poisoning healed Shroomish a little bit!");
HP_BAR(player, damage: -50);
HP_BAR(player, captureDamage: &turnOneHit);
ABILITY_POPUP(player, ABILITY_POISON_HEAL);
MESSAGE("The poisoning healed Shroomish a little bit!");
HP_BAR(player, captureDamage: &turnTwoHit);
} THEN {
EXPECT_EQ(turnOneHit, turnTwoHit);
}
}
@ -57,6 +71,7 @@ SINGLE_BATTLE_TEST("Poison Heal activates before Toxic Orb")
ABILITY_POPUP(player, ABILITY_POISON_HEAL);
MESSAGE("The poisoning healed Shroomish a little bit!");
HP_BAR(player, damage: -50);
HP_BAR(player, damage: 50);
}
}
}
}

View File

@ -0,0 +1,33 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Rocky Payload increases Rock-type move damage", s16 damage)
{
u32 move;
u16 ability;
PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_BIG_PECKS; }
PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_ROCKY_PAYLOAD; }
PARAMETRIZE { move = MOVE_ROCK_THROW; ability = ABILITY_BIG_PECKS; }
PARAMETRIZE { move = MOVE_ROCK_THROW; ability = ABILITY_ROCKY_PAYLOAD; }
PARAMETRIZE { move = MOVE_POWER_GEM; ability = ABILITY_BIG_PECKS; }
PARAMETRIZE { move = MOVE_POWER_GEM; ability = ABILITY_ROCKY_PAYLOAD; }
GIVEN {
ASSUME(gBattleMoves[MOVE_TACKLE].type == TYPE_NORMAL);
ASSUME(gBattleMoves[MOVE_ROCK_THROW].type == TYPE_ROCK);
ASSUME(gBattleMoves[MOVE_POWER_GEM].type == TYPE_ROCK);
ASSUME(gBattleMoves[MOVE_ROCK_THROW].split == SPLIT_PHYSICAL);
ASSUME(gBattleMoves[MOVE_POWER_GEM].split == SPLIT_SPECIAL);
PLAYER(SPECIES_WOBBUFFET) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_EQ(results[0].damage, results[1].damage); // Tackle should be unaffected
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); // Rock Throw should be affected
EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.5), results[5].damage); // Power Gem should be affected
}
}

View File

@ -0,0 +1,33 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Steelworker increases Steel-type move damage", s16 damage)
{
u32 move;
u16 ability;
PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_KLUTZ; }
PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_STEELWORKER; }
PARAMETRIZE { move = MOVE_ANCHOR_SHOT; ability = ABILITY_KLUTZ; }
PARAMETRIZE { move = MOVE_ANCHOR_SHOT; ability = ABILITY_STEELWORKER; }
PARAMETRIZE { move = MOVE_FLASH_CANNON; ability = ABILITY_KLUTZ; }
PARAMETRIZE { move = MOVE_FLASH_CANNON; ability = ABILITY_STEELWORKER; }
GIVEN {
ASSUME(gBattleMoves[MOVE_TACKLE].type == TYPE_NORMAL);
ASSUME(gBattleMoves[MOVE_ANCHOR_SHOT].type == TYPE_STEEL);
ASSUME(gBattleMoves[MOVE_FLASH_CANNON].type == TYPE_STEEL);
ASSUME(gBattleMoves[MOVE_ANCHOR_SHOT].split == SPLIT_PHYSICAL);
ASSUME(gBattleMoves[MOVE_FLASH_CANNON].split == SPLIT_SPECIAL);
PLAYER(SPECIES_DHELMISE) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_EQ(results[0].damage, results[1].damage); // Tackle should be unaffected
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); // Anchor Shot should be affected
EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.5), results[5].damage); // Flash Cannon should be affected
}
}

View File

@ -0,0 +1,38 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Transistor increases Electric-type move damage", s16 damage)
{
u32 move;
u16 ability;
PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_KLUTZ; }
PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_TRANSISTOR; }
PARAMETRIZE { move = MOVE_WILD_CHARGE; ability = ABILITY_KLUTZ; }
PARAMETRIZE { move = MOVE_WILD_CHARGE; ability = ABILITY_TRANSISTOR; }
PARAMETRIZE { move = MOVE_THUNDER_SHOCK; ability = ABILITY_KLUTZ; }
PARAMETRIZE { move = MOVE_THUNDER_SHOCK; ability = ABILITY_TRANSISTOR; }
GIVEN {
ASSUME(gBattleMoves[MOVE_TACKLE].type == TYPE_NORMAL);
ASSUME(gBattleMoves[MOVE_WILD_CHARGE].type == TYPE_ELECTRIC);
ASSUME(gBattleMoves[MOVE_THUNDER_SHOCK].type == TYPE_ELECTRIC);
ASSUME(gBattleMoves[MOVE_WILD_CHARGE].split == SPLIT_PHYSICAL);
ASSUME(gBattleMoves[MOVE_THUNDER_SHOCK].split == SPLIT_SPECIAL);
PLAYER(SPECIES_REGIELEKI) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_EQ(results[0].damage, results[1].damage); // Tackle should be unaffected
#if B_TRANSISTOR >= GEN_9
EXPECT_MUL_EQ(results[2].damage, Q_4_12(5325 / 4096), results[3].damage); // Wild Charge should be affected
EXPECT_MUL_EQ(results[4].damage, Q_4_12(5325 / 4096), results[5].damage); // Thunder Shock should be affected
#else
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); // Wild Charge should be affected
EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.5), results[5].damage); // Thunder Shock should be affected
#endif
}
}