Merge branch 'rattled' into stamina_fix

This commit is contained in:
DizzyEggg 2023-07-26 09:36:46 +02:00
commit a3d6e31227
16 changed files with 634 additions and 52 deletions

View File

@ -636,7 +636,7 @@ struct BattleStruct
bool8 friskedAbility; // If identifies two mons, show the ability pop-up only once.
u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used.
u16 moveEffect2; // For Knock Off
u16 changedSpecies[PARTY_SIZE]; // For Zygarde or future forms when multiple mons can change into the same pokemon.
u16 changedSpecies[NUM_BATTLE_SIDES][PARTY_SIZE]; // For forms when multiple mons can change into the same pokemon.
u8 quickClawBattlerId;
struct LostItem itemLost[PARTY_SIZE]; // Player's team that had items consumed or stolen (two bytes per party member)
u8 blunderPolicy:1; // should blunder policy activate

View File

@ -210,6 +210,7 @@ void BufferStatChange(u8 battlerId, u8 statId, u8 stringId);
bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget);
u16 GetUsedHeldItem(u8 battler);
bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags);
u32 ApplyWeatherDamageMultiplier(u8 battlerAtk, u16 move, u8 moveType, u32 dmg, u16 holdEffectAtk, u16 holdEffectDef);
u32 GetBattlerMoveTargetType(u8 battlerId, u16 move);
bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move);
bool8 IsMoveAffectedByParentalBond(u16 move, u8 battlerId);

View File

@ -10,6 +10,7 @@
#define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8+, the Vitamins no longer have a cap of 100 EV per stat.
#define I_BERRY_EV_JUMP GEN_LATEST // In Gen4 only, EV-lowering Berries lower a stat's EV to 100 if it is above 100.
#define I_GRISEOUS_ORB_FORM_CHANGE GEN_LATEST // In Gen9+, the Griseous Orb no longer changes Giratina's form when held.
#define I_GEM_BOOST_POWER GEN_LATEST // In Gen5+, the Gem boost power was reduced from 50% to 30%.
#define I_USE_EVO_HELD_ITEMS_FROM_BAG FALSE // If TRUE, items such as Razor Claw or Electirizer will be usable from the bag to evolve a Pokémon just like in LA.
// TM config

View File

@ -5434,7 +5434,8 @@ static void HandleEndTurn_FinishBattle(void)
changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE);
// Clear original species field
gBattleStruct->changedSpecies[i] = SPECIES_NONE;
gBattleStruct->changedSpecies[B_SIDE_PLAYER][i] = SPECIES_NONE;
gBattleStruct->changedSpecies[B_SIDE_OPPONENT][i] = SPECIES_NONE;
#if B_RECALCULATE_STATS >= GEN_5
// Recalculate the stats of every party member before the end

View File

@ -10669,7 +10669,7 @@ static void Cmd_various(void)
{
gBattleStruct->battleBondTransformed[GET_BATTLER_SIDE2(gBattlerAttacker)] |= gBitTable[gBattlerPartyIndexes[gBattlerAttacker]];
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].species);
gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species;
gBattleStruct->changedSpecies[GET_BATTLER_SIDE2(gBattlerAttacker)][gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species;
gBattleMons[gBattlerAttacker].species = SPECIES_GRENINJA_ASH;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_BattleBondActivatesOnMoveEndAttacker;

View File

@ -8866,14 +8866,16 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
case ABILITY_PROTOSYNTHESIS:
{
u8 atkHighestStat = GetHighestStatId(battlerAtk);
if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT && (atkHighestStat == STAT_ATK || atkHighestStat == STAT_SPATK))
if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT
&& ((IS_MOVE_PHYSICAL(move) && atkHighestStat == STAT_ATK) || (IS_MOVE_SPECIAL(move) && atkHighestStat == STAT_SPATK)))
MulModifier(&modifier, UQ_4_12(1.3));
}
break;
case ABILITY_QUARK_DRIVE:
{
u8 atkHighestStat = GetHighestStatId(battlerAtk);
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && (atkHighestStat == STAT_ATK || atkHighestStat == STAT_SPATK))
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN
&& ((IS_MOVE_PHYSICAL(move) && atkHighestStat == STAT_ATK) || (IS_MOVE_SPECIAL(move) && atkHighestStat == STAT_SPATK)))
MulModifier(&modifier, UQ_4_12(1.3));
}
break;
@ -8964,14 +8966,16 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
case ABILITY_PROTOSYNTHESIS:
{
u8 defHighestStat = GetHighestStatId(battlerDef);
if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT && (defHighestStat == STAT_DEF || defHighestStat == STAT_SPDEF))
if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT
&& ((IS_MOVE_PHYSICAL(move) && defHighestStat == STAT_DEF) || (IS_MOVE_SPECIAL(move) && defHighestStat == STAT_SPDEF)))
MulModifier(&modifier, UQ_4_12(0.7));
}
break;
case ABILITY_QUARK_DRIVE:
{
u8 defHighestStat = GetHighestStatId(battlerDef);
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && (defHighestStat == STAT_DEF || defHighestStat == STAT_SPDEF))
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN
&& ((IS_MOVE_PHYSICAL(move) && defHighestStat == STAT_DEF) || (IS_MOVE_SPECIAL(move) && defHighestStat == STAT_SPDEF)))
MulModifier(&modifier, UQ_4_12(0.7));
}
break;
@ -9015,10 +9019,6 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
#endif
MulModifier(&modifier, holdEffectModifier);
break;
case HOLD_EFFECT_GEMS:
if (gSpecialStatuses[battlerAtk].gemBoost && gBattleMons[battlerAtk].item)
MulModifier(&modifier, UQ_4_12(1.0) + sPercentToModifier[gSpecialStatuses[battlerAtk].gemParam]);
break;
case HOLD_EFFECT_BUG_POWER:
case HOLD_EFFECT_STEEL_POWER:
case HOLD_EFFECT_GROUND_POWER:
@ -9109,6 +9109,8 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
// various effects
if (gProtectStructs[battlerAtk].helpingHand)
MulModifier(&modifier, UQ_4_12(1.5));
if (gSpecialStatuses[battlerAtk].gemBoost)
MulModifier(&modifier, UQ_4_12(1.0) + sPercentToModifier[gSpecialStatuses[battlerAtk].gemParam]);
if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP && moveType == TYPE_ELECTRIC)
MulModifier(&modifier, UQ_4_12(2.0));
if (gStatuses3[battlerAtk] & STATUS3_ME_FIRST)
@ -9505,6 +9507,8 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
u32 defSide = GET_BATTLER_SIDE(battlerDef);
u16 finalModifier = UQ_4_12(1.0);
u16 itemDef = gBattleMons[battlerDef].item;
u16 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE);
u16 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE);
// check multiple targets in double battle
if (GetMoveTargetCount(move, battlerAtk, battlerDef) >= 2)
@ -9534,28 +9538,15 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
// check frostbite
if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && !IS_MOVE_PHYSICAL(move)
if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && IS_MOVE_SPECIAL(move)
#if B_BURN_FACADE_DMG >= GEN_6
&& gBattleMoves[move].effect != EFFECT_FACADE
#endif
&& abilityAtk != ABILITY_GUTS)
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
// check sunny/rain weather
if (IsBattlerWeatherAffected(battlerAtk, B_WEATHER_RAIN))
{
if (moveType == TYPE_FIRE)
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
else if (moveType == TYPE_WATER)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
}
else if (IsBattlerWeatherAffected(battlerAtk, B_WEATHER_SUN))
{
if (moveType == TYPE_FIRE || gBattleMoves[move].effect == EFFECT_HYDRO_STEAM)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
else if (moveType == TYPE_WATER)
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
}
// check weather
dmg = ApplyWeatherDamageMultiplier(battlerAtk, move, moveType, dmg, holdEffectAtk, holdEffectDef);
// check stab
if (IS_BATTLER_OF_TYPE(battlerAtk, moveType) && move != MOVE_STRUGGLE && move != MOVE_NONE)
@ -9640,7 +9631,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
}
// attacker's hold effect
switch (GetBattlerHoldEffect(battlerAtk, TRUE))
switch (holdEffectAtk)
{
case HOLD_EFFECT_METRONOME:
percentBoost = min((gBattleStruct->sameMoveTurns[battlerAtk] * GetBattlerHoldEffectParam(battlerAtk)), 100);
@ -9656,7 +9647,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
}
// target's hold effect
switch (GetBattlerHoldEffect(battlerDef, TRUE))
switch (holdEffectDef)
{
// berries reducing dmg
case HOLD_EFFECT_RESIST_BERRY:
@ -10235,8 +10226,8 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method)
if (targetSpecies != SPECIES_NONE)
{
// Saves the original species on the first form change for the player.
if (side == B_SIDE_PLAYER && gBattleStruct->changedSpecies[monId] == SPECIES_NONE)
gBattleStruct->changedSpecies[monId] = gBattleMons[battlerId].species;
if (gBattleStruct->changedSpecies[side][monId] == SPECIES_NONE)
gBattleStruct->changedSpecies[side][monId] = gBattleMons[battlerId].species;
TryToSetBattleFormChangeMoves(&party[monId], method);
SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies);
@ -10244,7 +10235,7 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method)
RecalcBattlerStats(battlerId, &party[monId]);
return TRUE;
}
else if (gBattleStruct->changedSpecies[monId] != SPECIES_NONE)
else if (gBattleStruct->changedSpecies[side][monId] != SPECIES_NONE)
{
bool8 restoreSpecies = FALSE;
@ -10260,7 +10251,7 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method)
{
// Reverts the original species
TryToSetBattleFormChangeMoves(&party[monId], method);
SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]);
SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[side][monId]);
RecalcBattlerStats(battlerId, &party[monId]);
return TRUE;
}
@ -10855,6 +10846,34 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags)
return FALSE;
}
// Utility Umbrella holders take normal damage from what would be rain- and sun-weakened attacks.
u32 ApplyWeatherDamageMultiplier(u8 battlerAtk, u16 move, u8 moveType, u32 dmg, u16 holdEffectAtk, u16 holdEffectDef)
{
if (WEATHER_HAS_EFFECT)
{
if (gBattleMoves[move].effect == EFFECT_HYDRO_STEAM && (gBattleWeather & B_WEATHER_SUN) && holdEffectAtk != HOLD_EFFECT_UTILITY_UMBRELLA)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
else if (holdEffectDef != HOLD_EFFECT_UTILITY_UMBRELLA)
{
if (gBattleWeather & B_WEATHER_RAIN)
{
if (moveType == TYPE_FIRE)
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
else if (moveType == TYPE_WATER)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
}
else if (gBattleWeather & B_WEATHER_SUN)
{
if (moveType == TYPE_FIRE)
dmg = ApplyModifier(UQ_4_12(1.5), dmg);
else if (moveType == TYPE_WATER)
dmg = ApplyModifier(UQ_4_12(0.5), dmg);
}
}
}
return dmg;
}
// Gets move target before redirection effects etc. are applied
// Possible return values are defined in battle.h following MOVE_TARGET_SELECTED
u32 GetBattlerMoveTargetType(u8 battlerId, u16 move)

View File

@ -6,6 +6,12 @@
#define EVO_HELD_ITEM_FIELD_FUNC ItemUseOutOfBattle_CannotUse
#endif
#if I_GEM_BOOST_POWER >= GEN_5
#define GEM_BOOST_PARAM 30
#else
#define GEM_BOOST_PARAM 50
#endif
const struct Item gItems[] =
{
[ITEM_NONE] =
@ -4416,7 +4422,7 @@ const struct Item gItems[] =
.itemId = ITEM_NORMAL_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sNormalGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4430,7 +4436,7 @@ const struct Item gItems[] =
.itemId = ITEM_FIRE_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sFireGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4444,7 +4450,7 @@ const struct Item gItems[] =
.itemId = ITEM_WATER_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sWaterGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4458,7 +4464,7 @@ const struct Item gItems[] =
.itemId = ITEM_ELECTRIC_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sElectricGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4472,7 +4478,7 @@ const struct Item gItems[] =
.itemId = ITEM_GRASS_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sGrassGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4486,7 +4492,7 @@ const struct Item gItems[] =
.itemId = ITEM_ICE_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sIceGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4500,7 +4506,7 @@ const struct Item gItems[] =
.itemId = ITEM_FIGHTING_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sFightingGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4514,7 +4520,7 @@ const struct Item gItems[] =
.itemId = ITEM_POISON_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sPoisonGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4528,7 +4534,7 @@ const struct Item gItems[] =
.itemId = ITEM_GROUND_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sGroundGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4542,7 +4548,7 @@ const struct Item gItems[] =
.itemId = ITEM_FLYING_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sFlyingGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4556,7 +4562,7 @@ const struct Item gItems[] =
.itemId = ITEM_PSYCHIC_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sPsychicGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4570,7 +4576,7 @@ const struct Item gItems[] =
.itemId = ITEM_BUG_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sBugGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4584,7 +4590,7 @@ const struct Item gItems[] =
.itemId = ITEM_ROCK_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sRockGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4598,7 +4604,7 @@ const struct Item gItems[] =
.itemId = ITEM_GHOST_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sGhostGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4612,7 +4618,7 @@ const struct Item gItems[] =
.itemId = ITEM_DRAGON_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sDragonGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4626,7 +4632,7 @@ const struct Item gItems[] =
.itemId = ITEM_DARK_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sDarkGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4640,7 +4646,7 @@ const struct Item gItems[] =
.itemId = ITEM_STEEL_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sSteelGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,
@ -4654,7 +4660,7 @@ const struct Item gItems[] =
.itemId = ITEM_FAIRY_GEM,
.price = 4000,
.holdEffect = HOLD_EFFECT_GEMS,
.holdEffectParam = 30,
.holdEffectParam = GEM_BOOST_PARAM,
.description = sFairyGemDesc,
.pocket = POCKET_ITEMS,
.type = ITEM_USE_BAG_MENU,

View File

@ -8507,7 +8507,7 @@ bool32 TryFormChange(u32 monId, u32 side, u16 method)
targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0);
if (targetSpecies == SPECIES_NONE && gBattleStruct != NULL)
targetSpecies = gBattleStruct->changedSpecies[monId];
targetSpecies = gBattleStruct->changedSpecies[side][monId];
if (targetSpecies != SPECIES_NONE)
{

View File

@ -0,0 +1,87 @@
#include "global.h"
#include "test_battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL);
ASSUME(gBattleMoves[MOVE_ROUND].split == SPLIT_SPECIAL);
}
SINGLE_BATTLE_TEST("Protosynthesis boosts the highest stat")
{
GIVEN {
PLAYER(SPECIES_ABRA) { Ability(ABILITY_PROTOSYNTHESIS); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player);
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
MESSAGE("The harsh sunlight activated Abra's Protosynthesis!");
MESSAGE("Abra's Sp. Atk was heightened!");
}
}
SINGLE_BATTLE_TEST("Protosynthesis boosts either Attack or Special Attack, not both")
{
u16 species;
u32 move;
u16 damage[2];
PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_TACKLE; }
PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_ROUND; }
PARAMETRIZE { species = SPECIES_ABRA; move = MOVE_TACKLE; }
PARAMETRIZE { species = SPECIES_ABRA; move = MOVE_ROUND; }
GIVEN {
PLAYER(species) { Ability(ABILITY_PROTOSYNTHESIS); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent, captureDamage: &damage[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent);
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent, captureDamage: &damage[1]);
} THEN {
if ((move == MOVE_TACKLE && species == SPECIES_BELLSPROUT) || (move == MOVE_ROUND && species == SPECIES_ABRA))
EXPECT_MUL_EQ(damage[0], Q_4_12(1.3), damage[1]);
else
EXPECT_EQ(damage[0], damage[1]);
}
}
SINGLE_BATTLE_TEST("Protosynthesis either boosts Defense or Special Defense, not both")
{
u16 species;
u32 move;
u16 damage[2];
PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_TACKLE; }
PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_ROUND; }
PARAMETRIZE { species = SPECIES_BLASTOISE; move = MOVE_TACKLE; }
PARAMETRIZE { species = SPECIES_BLASTOISE; move = MOVE_ROUND; }
GIVEN {
PLAYER(species) { Ability(ABILITY_PROTOSYNTHESIS); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); }
TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
HP_BAR(player, captureDamage: &damage[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player);
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
HP_BAR(player, captureDamage: &damage[1]);
} THEN {
if ((move == MOVE_TACKLE && species == SPECIES_ONIX) || (move == MOVE_ROUND && species == SPECIES_BLASTOISE))
EXPECT_MUL_EQ(damage[0], Q_4_12(0.7), damage[1]);
else
EXPECT_EQ(damage[0], damage[1]);
}
}

View File

@ -0,0 +1,87 @@
#include "global.h"
#include "test_battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL);
ASSUME(gBattleMoves[MOVE_ROUND].split == SPLIT_SPECIAL);
}
SINGLE_BATTLE_TEST("Quark Drive boosts the highest stat")
{
GIVEN {
PLAYER(SPECIES_ABRA) { Ability(ABILITY_QUARK_DRIVE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player);
ABILITY_POPUP(player, ABILITY_QUARK_DRIVE);
MESSAGE("The Electric Terrain activated Abra's Quark Drive!");
MESSAGE("Abra's Sp. Atk was heightened!");
}
}
SINGLE_BATTLE_TEST("Quark Drive boosts either Attack or Special Attack, not both")
{
u16 species;
u32 move;
u16 damage[2];
PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_TACKLE; }
PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_ROUND; }
PARAMETRIZE { species = SPECIES_ABRA; move = MOVE_TACKLE; }
PARAMETRIZE { species = SPECIES_ABRA; move = MOVE_ROUND; }
GIVEN {
PLAYER(species) { Ability(ABILITY_QUARK_DRIVE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
TURN { MOVE(opponent, MOVE_ELECTRIC_TERRAIN); MOVE(player, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent, captureDamage: &damage[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, opponent);
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent, captureDamage: &damage[1]);
} THEN {
if ((move == MOVE_TACKLE && species == SPECIES_BELLSPROUT) || (move == MOVE_ROUND && species == SPECIES_ABRA))
EXPECT_MUL_EQ(damage[0], Q_4_12(1.3), damage[1]);
else
EXPECT_EQ(damage[0], damage[1]);
}
}
SINGLE_BATTLE_TEST("Quark Drive either boosts Defense or Special Defense, not both")
{
u16 species;
u32 move;
u16 damage[2];
PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_TACKLE; }
PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_ROUND; }
PARAMETRIZE { species = SPECIES_BLASTOISE; move = MOVE_TACKLE; }
PARAMETRIZE { species = SPECIES_BLASTOISE; move = MOVE_ROUND; }
GIVEN {
PLAYER(species) { Ability(ABILITY_QUARK_DRIVE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); }
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
HP_BAR(player, captureDamage: &damage[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player);
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
HP_BAR(player, captureDamage: &damage[1]);
} THEN {
if ((move == MOVE_TACKLE && species == SPECIES_ONIX) || (move == MOVE_ROUND && species == SPECIES_BLASTOISE))
EXPECT_MUL_EQ(damage[0], Q_4_12(0.7), damage[1]);
else
EXPECT_EQ(damage[0], damage[1]);
}
}

93
test/ability_rattled.c Normal file
View File

@ -0,0 +1,93 @@
#include "global.h"
#include "test_battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_FURY_CUTTER].type == TYPE_BUG);
ASSUME(gBattleMoves[MOVE_FURY_CUTTER].power != 0);
ASSUME(gBattleMoves[MOVE_FEINT_ATTACK].type == TYPE_DARK);
ASSUME(gBattleMoves[MOVE_FEINT_ATTACK].power != 0);
ASSUME(gBattleMoves[MOVE_SHADOW_PUNCH].type == TYPE_GHOST);
ASSUME(gBattleMoves[MOVE_SHADOW_PUNCH].power != 0);
ASSUME(gBattleMoves[MOVE_TACKLE].type == TYPE_NORMAL);
ASSUME(gBattleMoves[MOVE_TACKLE].power != 0);
}
SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when hit by Bug, Dark or Ghost type move")
{
u16 move;
PARAMETRIZE { move = MOVE_FURY_CUTTER; }
PARAMETRIZE { move = MOVE_FEINT_ATTACK; }
PARAMETRIZE { move = MOVE_SHADOW_PUNCH; }
PARAMETRIZE { move = MOVE_TACKLE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) {Speed(42) ;}
OPPONENT(SPECIES_SUDOWOODO) {Speed(40); Ability(ABILITY_RATTLED);}
} WHEN {
TURN { MOVE(player, move); }
TURN { MOVE(player, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
if (move != MOVE_TACKLE) {
ABILITY_POPUP(opponent, ABILITY_RATTLED);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Sudowoodo's Speed rose!");
}
MESSAGE("Foe Sudowoodo used Celebrate!");
// Sudowoodo is now faster
if (move != MOVE_TACKLE){
MESSAGE("Foe Sudowoodo used Celebrate!");
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
ABILITY_POPUP(opponent, ABILITY_RATTLED);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Sudowoodo's Speed rose!");
}
else {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
MESSAGE("Foe Sudowoodo used Celebrate!");
}
}
}
SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when affected by Intimidate")
{
GIVEN {
ASSUME(B_UPDATED_INTIMIDATE >= GEN_8);
PLAYER(SPECIES_GYARADOS) {Ability(ABILITY_INTIMIDATE); }
OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); }
} WHEN {
TURN {}
} SCENE {
ABILITY_POPUP(player, ABILITY_INTIMIDATE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Gyarados's Intimidate cuts Foe Sudowoodo's attack!");
ABILITY_POPUP(opponent, ABILITY_RATTLED);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Sudowoodo's Speed rose!");
}
}
SINGLE_BATTLE_TEST("Rattled triggers correctly when hit by U-Turn") // Specific test here, because of #3124
{
GIVEN {
ASSUME(gBattleMoves[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE);
ASSUME(gBattleMoves[MOVE_U_TURN].type == TYPE_BUG);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); }
OPPONENT(SPECIES_SUDOWOODO);
} WHEN {
TURN { MOVE(player, MOVE_U_TURN); SEND_OUT(player, 1); }
} SCENE {
MESSAGE("Wobbuffet used U-Turn!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player);
HP_BAR(opponent);
ABILITY_POPUP(opponent, ABILITY_RATTLED);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Sudowoodo's Speed rose!");
MESSAGE("Go! Wynaut!");
}
}

89
test/hold_effect_gems.c Normal file
View File

@ -0,0 +1,89 @@
#include "global.h"
#include "test_battle.h"
ASSUMPTIONS
{
ASSUME(gItems[ITEM_NORMAL_GEM].holdEffect == HOLD_EFFECT_GEMS);
}
SINGLE_BATTLE_TEST("Gem is consumed when it corresponds to the type of a move")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMAL_GEM); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_EMBER); }
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Fire Gem strengthened Wobbuffet's power!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Normal Gem strengthened Wobbuffet's power!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
}
}
SINGLE_BATTLE_TEST("Gem boost is only applied once")
{
s16 boostedHit;
s16 normalHit;
GIVEN {
ASSUME(I_GEM_BOOST_POWER >= GEN_5);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMAL_GEM); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Normal Gem strengthened Wobbuffet's power!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent, captureDamage: &boostedHit);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent, captureDamage: &normalHit);
} THEN {
EXPECT_MUL_EQ(normalHit, Q_4_12(1.3), boostedHit);
}
}
SINGLE_BATTLE_TEST("Gem modifier is used for all hits of Multi Hit Moves")
{
s16 firstHit;
s16 secondHit;
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMAL_GEM); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(player, MOVE_DOUBLE_HIT);
}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_HIT, player);
HP_BAR(opponent, captureDamage: &firstHit);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_HIT, player);
HP_BAR(opponent, captureDamage: &secondHit);
} THEN {
EXPECT_EQ(firstHit, secondHit);
}
}
SINGLE_BATTLE_TEST("Gem is consumed if the move type is changed")
{
GIVEN {
PLAYER(SPECIES_DELCATTY) { Ability(ABILITY_NORMALIZE); Item(ITEM_NORMAL_GEM); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(player, MOVE_FEINT_ATTACK);
}
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Normal Gem strengthened Delcatty's power!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FEINT_ATTACK, player);
}
}

View File

@ -0,0 +1,54 @@
#include "global.h"
#include "test_battle.h"
// Please add Utility Umbrella interactions with move, item and ability effects on their respective files.
ASSUMPTIONS
{
ASSUME(gItems[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA);
ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE);
ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER);
}
SINGLE_BATTLE_TEST("Utility Umbrella blocks Sun damage modifiers", s16 damage)
{
u16 setupMove, attackingMove, heldItem;
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_EMBER; heldItem = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_EMBER; heldItem = ITEM_NONE; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_NONE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(heldItem); };
} WHEN {
TURN { MOVE(opponent, setupMove); }
TURN { MOVE(player, attackingMove); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, attackingMove, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[3].damage);
}
}
SINGLE_BATTLE_TEST("Utility Umbrella blocks Rain damage modifiers", s16 damage)
{
u16 setupMove, attackingMove, heldItem;
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_EMBER; heldItem = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_EMBER; heldItem = ITEM_NONE; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_NONE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(heldItem); };
} WHEN {
TURN { MOVE(opponent, setupMove); }
TURN { MOVE(player, attackingMove); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, attackingMove, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage);
}
}

View File

@ -0,0 +1,50 @@
#include "global.h"
#include "test_battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_HYDRO_STEAM].effect == EFFECT_HYDRO_STEAM);
}
SINGLE_BATTLE_TEST("Hydro Steam deals 1.5x damage under both Sunlight and Rain", s16 damage)
{
u16 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_HYDRO_STEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYDRO_STEAM, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[2].damage);
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Hydro Steam is affected by Utility Umbrella", s16 damage)
{
u32 itemPlayer;
u32 itemOpponent;
PARAMETRIZE { itemPlayer = ITEM_UTILITY_UMBRELLA; itemOpponent = ITEM_NONE; }
PARAMETRIZE { itemPlayer = ITEM_NONE; itemOpponent = ITEM_UTILITY_UMBRELLA; }
PARAMETRIZE { itemPlayer = ITEM_UTILITY_UMBRELLA; itemOpponent = ITEM_UTILITY_UMBRELLA; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(itemPlayer); };
OPPONENT(SPECIES_WOBBUFFET) {Item(itemOpponent); };
} WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); }
TURN { MOVE(player, MOVE_HYDRO_STEAM); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYDRO_STEAM, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[0].damage);
}
}

47
test/weather_rain.c Normal file
View File

@ -0,0 +1,47 @@
#include "global.h"
#include "test_battle.h"
// Please add Rain interactions with move, item and ability effects on their respective files.
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE);
ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER);
}
SINGLE_BATTLE_TEST("Rain multiplies the power of Fire-type moves by 0.5x", s16 damage)
{
u32 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_EMBER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
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("Rain multiplies the power of Water-type moves by 1.5x", s16 damage)
{
u32 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_WATER_GUN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}

47
test/weather_sunlight.c Normal file
View File

@ -0,0 +1,47 @@
#include "global.h"
#include "test_battle.h"
// Please add Sunlight interactions with move, item and ability effects on their respective files.
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE);
ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER);
}
SINGLE_BATTLE_TEST("Sunlight multiplies the power of Fire-type moves by 1.5x", s16 damage)
{
u32 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_EMBER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
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("Sunlight multiplies the power of Water-type moves by 0.5x", s16 damage)
{
u32 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, setupMove); }
TURN { MOVE(player, MOVE_WATER_GUN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}