Fix Protosynthesis stat boosts ignoring speed drops (#8277)

This commit is contained in:
moostoet 2025-11-23 16:31:19 +01:00 committed by GitHub
parent 51a750e61a
commit 935817bf37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 323 additions and 29 deletions

View File

@ -134,7 +134,7 @@ struct DisableStruct
u8 endured:1;
u8 octolockedBy:3;
u8 tryEjectPack:1;
u8 padding:4;
u8 paradoxBoostedStat:4;
};
// Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects

View File

@ -69,6 +69,8 @@ u32 GetNaturePowerMove(u32 battler);
void StealTargetItem(u8 battlerStealer, u8 battlerItem);
u8 GetCatchingBattler(void);
u32 GetHighestStatId(u32 battlerId);
u32 GetParadoxHighestStatId(u32 battlerId);
u32 GetParadoxBoostedStatId(u32 battlerId);
bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType);
bool32 IsMoveNotAllowedInSkyBattles(u32 move);
bool32 DoSwitchInAbilities(u32 battlerId);

View File

@ -4770,9 +4770,9 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h
else if (ability == ABILITY_SLOW_START && gDisableStructs[battler].slowStartTimer != 0)
speed /= 2;
else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].volatiles.transformed) && ((gBattleWeather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battler].boosterEnergyActivated))
speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
speed = (GetParadoxBoostedStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].volatiles.transformed) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivated))
speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
speed = (GetParadoxBoostedStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
else if (ability == ABILITY_UNBURDEN && gDisableStructs[battler].unburdenActive)
speed *= 2;

View File

@ -9408,25 +9408,6 @@ u32 IsAbilityStatusProtected(u32 battler, u32 ability)
|| IsFlowerVeilProtected(battler);
}
u32 GetHighestStatId(u32 battler)
{
u32 i, highestId = STAT_ATK, highestStat = gBattleMons[battler].attack;
for (i = STAT_DEF; i < NUM_STATS; i++)
{
u16 *statVal = &gBattleMons[battler].attack + (i - 1);
if (*statVal > highestStat && i != STAT_SPEED)
{
highestStat = *statVal;
highestId = i;
}
}
if (gBattleMons[battler].speed > highestStat)
highestId = STAT_SPEED;
return highestId;
}
static bool32 IsRototillerAffected(u32 battler)
{
if (!IsBattlerAlive(battler))

View File

@ -68,6 +68,8 @@ static bool32 CanBeInfinitelyConfused(u32 battler);
static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum FunctionCallOption option);
static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum FunctionCallOption option);
static bool32 IsOpposingSideEmpty(u32 battler);
static void ResetParadoxWeatherStat(u32 battler);
static void ResetParadoxTerrainStat(u32 battler);
ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12(u32 percent);
ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12_Floored(u32 percent);
@ -249,7 +251,10 @@ bool32 EndOrContinueWeather(void)
{
gBattleWeather = B_WEATHER_NONE;
for (u32 battler = 0; battler < gBattlersCount; battler++)
{
gDisableStructs[battler].weatherAbilityDone = FALSE;
ResetParadoxWeatherStat(battler);
}
gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].endMessage;
BattleScriptExecute(BattleScript_WeatherFaded);
return TRUE;
@ -1718,6 +1723,7 @@ void TryToRevertMimicryAndFlags(void)
for (u32 battler = 0; battler < gBattlersCount; battler++)
{
gDisableStructs[battler].terrainAbilityDone = FALSE;
ResetParadoxTerrainStat(battler);
if (IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MIMICRY))
RESTORE_BATTLER_TYPE(battler);
}
@ -2810,7 +2816,10 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, u32 ability)
{
gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag;
for (u32 i = 0; i < gBattlersCount; i++)
{
gDisableStructs[i].weatherAbilityDone = FALSE;
ResetParadoxWeatherStat(i);
}
return TRUE;
}
else
@ -2824,7 +2833,10 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, u32 ability)
else
gWishFutureKnock.weatherDuration = 5;
for (u32 i = 0; i < gBattlersCount; i++)
{
gDisableStructs[i].weatherAbilityDone = FALSE;
ResetParadoxWeatherStat(i);
}
return TRUE;
}
@ -2841,7 +2853,10 @@ bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag)
gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY;
gFieldStatuses |= statusFlag;
for (u32 i = 0; i < gBattlersCount; i++)
{
gDisableStructs[i].terrainAbilityDone = FALSE;
ResetParadoxTerrainStat(i);
}
if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER)
gFieldTimers.terrainTimer = gBattleTurnCounter + 8;
else
@ -5224,7 +5239,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& !gDisableStructs[battler].boosterEnergyActivated)
{
gDisableStructs[battler].weatherAbilityDone = TRUE;
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
gDisableStructs[battler].paradoxBoostedStat = GetParadoxHighestStatId(battler);
PREPARE_STAT_BUFFER(gBattleTextBuff1, gDisableStructs[battler].paradoxBoostedStat);
gBattleScripting.battler = battler;
BattleScriptPushCursorAndCallback(BattleScript_ProtosynthesisActivates);
effect++;
@ -5253,7 +5269,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& !gDisableStructs[battler].boosterEnergyActivated)
{
gDisableStructs[battler].terrainAbilityDone = TRUE;
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
gDisableStructs[battler].paradoxBoostedStat = GetParadoxHighestStatId(battler);
PREPARE_STAT_BUFFER(gBattleTextBuff1, gDisableStructs[battler].paradoxBoostedStat);
gBattlerAbility = gBattleScripting.battler = battler;
BattleScriptPushCursorAndCallback(BattleScript_QuarkDriveActivates);
effect++;
@ -5546,6 +5563,108 @@ bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, u32 abilityDef)
return FALSE;
}
u32 GetHighestStatId(u32 battler)
{
u32 highestId = STAT_ATK;
u32 highestStat = gBattleMons[battler].attack;
for (u32 stat = STAT_DEF; stat < NUM_STATS; stat++)
{
if (stat == STAT_SPEED)
continue;
u16 *statVal = &gBattleMons[battler].attack + (stat - 1);
if (*statVal > highestStat)
{
highestStat = *statVal;
highestId = stat;
}
}
if (gBattleMons[battler].speed > highestStat)
highestId = STAT_SPEED;
return highestId;
}
static u32 GetStatValueWithStages(u32 battler, u32 stat)
{
u32 statValue;
switch (stat)
{
case STAT_ATK:
statValue = gBattleMons[battler].attack;
break;
case STAT_DEF:
statValue = gBattleMons[battler].defense;
break;
case STAT_SPATK:
statValue = gBattleMons[battler].spAttack;
break;
case STAT_SPDEF:
statValue = gBattleMons[battler].spDefense;
break;
case STAT_SPEED:
statValue = gBattleMons[battler].speed;
break;
default:
return 0;
}
statValue *= gStatStageRatios[gBattleMons[battler].statStages[stat]][0];
statValue /= gStatStageRatios[gBattleMons[battler].statStages[stat]][1];
return statValue;
}
u32 GetParadoxHighestStatId(u32 battler)
{
u32 highestId = STAT_ATK;
u32 highestStat = GetStatValueWithStages(battler, STAT_ATK);
for (u32 stat = STAT_DEF; stat < NUM_STATS; stat++)
{
if (stat == STAT_SPEED)
continue;
u32 statValue = GetStatValueWithStages(battler, stat);
if (statValue > highestStat)
{
highestStat = statValue;
highestId = stat;
}
}
u32 speed = GetStatValueWithStages(battler, STAT_SPEED);
if (speed > highestStat)
highestId = STAT_SPEED;
return highestId;
}
static void ResetParadoxWeatherStat(u32 battler)
{
if (gBattleMons[battler].ability == ABILITY_PROTOSYNTHESIS
&& !gDisableStructs[battler].boosterEnergyActivated)
gDisableStructs[battler].paradoxBoostedStat = 0;
}
static void ResetParadoxTerrainStat(u32 battler)
{
if (gBattleMons[battler].ability == ABILITY_QUARK_DRIVE
&& !gDisableStructs[battler].boosterEnergyActivated)
gDisableStructs[battler].paradoxBoostedStat = 0;
}
u32 GetParadoxBoostedStatId(u32 battler)
{
if (gDisableStructs[battler].paradoxBoostedStat == 0)
gDisableStructs[battler].paradoxBoostedStat = GetParadoxHighestStatId(battler);
return gDisableStructs[battler].paradoxBoostedStat;
}
bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef)
{
if (CanSetNonVolatileStatus(
@ -6195,7 +6314,8 @@ u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID)
if (((ability == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect()))
|| ((ability == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)))
{
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
gDisableStructs[battler].paradoxBoostedStat = GetParadoxHighestStatId(battler);
PREPARE_STAT_BUFFER(gBattleTextBuff1, gDisableStructs[battler].paradoxBoostedStat);
gBattlerAbility = gBattleScripting.battler = battler;
gDisableStructs[battler].boosterEnergyActivated = TRUE;
gLastUsedItem = ITEM_BOOSTER_ENERGY;
@ -8407,7 +8527,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx)
break;
case ABILITY_PROTOSYNTHESIS:
{
u8 defHighestStat = GetHighestStatId(battlerDef);
u32 defHighestStat = GetParadoxBoostedStatId(battlerDef);
if (((ctx->weather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battlerDef].boosterEnergyActivated)
&& ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF))
&& !(gBattleMons[battlerDef].volatiles.transformed))
@ -8416,7 +8536,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx)
break;
case ABILITY_QUARK_DRIVE:
{
u8 defHighestStat = GetHighestStatId(battlerDef);
u32 defHighestStat = GetParadoxBoostedStatId(battlerDef);
if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerDef].boosterEnergyActivated)
&& ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF))
&& !(gBattleMons[battlerDef].volatiles.transformed))
@ -8685,7 +8805,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx)
case ABILITY_PROTOSYNTHESIS:
if (!(gBattleMons[battlerAtk].volatiles.transformed))
{
u32 atkHighestStat = GetHighestStatId(battlerAtk);
u32 atkHighestStat = GetParadoxBoostedStatId(battlerAtk);
if (((ctx->weather & B_WEATHER_SUN) && HasWeatherEffect()) || gDisableStructs[battlerAtk].boosterEnergyActivated)
{
if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK))
@ -8696,7 +8816,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx)
case ABILITY_QUARK_DRIVE:
if (!(gBattleMons[battlerAtk].volatiles.transformed))
{
u32 atkHighestStat = GetHighestStatId(battlerAtk);
u32 atkHighestStat = GetParadoxBoostedStatId(battlerAtk);
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerAtk].boosterEnergyActivated)
{
if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK))

View File

@ -218,3 +218,95 @@ SINGLE_BATTLE_TEST("Protosynthesis activates after weather was reset")
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
}
}
SINGLE_BATTLE_TEST("Protosynthesis accounts for Sticky Web when determining the boosted stat")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(1); }
PLAYER(SPECIES_FLUTTER_MANE) { Ability(ABILITY_PROTOSYNTHESIS); Attack(50); Defense(50); SpAttack(150); SpDefense(140); Speed(180); }
OPPONENT(SPECIES_GALVANTULA) { Speed(60); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }
} WHEN {
TURN { MOVE(opponent, MOVE_STICKY_WEB); MOVE(player, MOVE_SUNNY_DAY); }
TURN { SWITCH(player, 1); MOVE(opponent, MOVE_SPLASH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player);
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
MESSAGE("The harsh sunlight activated Flutter Mane's Protosynthesis!");
MESSAGE("Flutter Mane's Sp. Atk was heightened!");
}
}
SINGLE_BATTLE_TEST("Protosynthesis keeps its initial boosted stat after Speed is lowered")
{
s16 damage[2];
GIVEN {
PLAYER(SPECIES_FLUTTER_MANE) { Ability(ABILITY_PROTOSYNTHESIS); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); Moves(MOVE_ROUND); }
OPPONENT(SPECIES_NINETALES) { Ability(ABILITY_DROUGHT); Moves(MOVE_ICY_WIND, MOVE_CELEBRATE); Speed(100); }
} WHEN {
TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_ICY_WIND); }
TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_DROUGHT);
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player);
HP_BAR(opponent, captureDamage: &damage[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ICY_WIND, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player);
HP_BAR(opponent, captureDamage: &damage[1]);
} THEN {
EXPECT_EQ(damage[0], damage[1]);
}
}
SINGLE_BATTLE_TEST("Protosynthesis recalculates the boosted stat after Neutralizing Gas leaves the field")
{
GIVEN {
PLAYER(SPECIES_FLUTTER_MANE) { Ability(ABILITY_PROTOSYNTHESIS); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); }
OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); Moves(MOVE_ICY_WIND); Speed(70); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }
} WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_ICY_WIND); }
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player);
NOT ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ICY_WIND, opponent);
MESSAGE("The effects of the neutralizing gas wore off!");
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
MESSAGE("The harsh sunlight activated Flutter Mane's Protosynthesis!");
MESSAGE("Flutter Mane's Sp. Atk was heightened!");
}
}
SINGLE_BATTLE_TEST("Protosynthesis retains its boosted stat after Neutralizing Gas briefly suppresses it")
{
s16 damage[2];
GIVEN {
PLAYER(SPECIES_FLUTTER_MANE) { Ability(ABILITY_PROTOSYNTHESIS); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); Moves(MOVE_SUNNY_DAY, MOVE_ROUND, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(1); }
OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); Moves(MOVE_CELEBRATE); Speed(70); }
} WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_CELEBRATE); SWITCH(opponent, 1); }
TURN { MOVE(player, MOVE_CELEBRATE); SWITCH(opponent, 0); }
TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player);
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player);
HP_BAR(opponent, captureDamage: &damage[0]);
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!");
MESSAGE("The effects of the neutralizing gas wore off!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player);
HP_BAR(opponent, captureDamage: &damage[1]);
} THEN {
EXPECT_EQ(damage[0], damage[1]);
}
}

View File

@ -54,6 +54,59 @@ SINGLE_BATTLE_TEST("Quark Drive boosts either Attack or Special Attack, not both
}
}
SINGLE_BATTLE_TEST("Quark Drive keeps its initial boosted stat after Speed is lowered")
{
s16 damage[2];
GIVEN {
PLAYER(SPECIES_IRON_MOTH) { Ability(ABILITY_QUARK_DRIVE); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); Moves(MOVE_ROUND, MOVE_CELEBRATE); }
OPPONENT(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); Moves(MOVE_CELEBRATE, MOVE_ICY_WIND); Speed(100); }
} WHEN {
TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_ICY_WIND); }
TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_ELECTRIC_SURGE);
ABILITY_POPUP(player, ABILITY_QUARK_DRIVE);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player);
HP_BAR(opponent, captureDamage: &damage[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ICY_WIND, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player);
HP_BAR(opponent, captureDamage: &damage[1]);
} THEN {
EXPECT_EQ(damage[0], damage[1]);
}
}
SINGLE_BATTLE_TEST("Quark Drive retains its boosted stat after Neutralizing Gas briefly suppresses it")
{
s16 damage[2];
GIVEN {
PLAYER(SPECIES_IRON_MOTH) { Ability(ABILITY_QUARK_DRIVE); Attack(10); Defense(10); SpAttack(150); SpDefense(120); Speed(180); Moves(MOVE_ELECTRIC_TERRAIN, MOVE_ROUND, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(1); }
OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); Moves(MOVE_CELEBRATE); Speed(70); }
} WHEN {
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_CELEBRATE); SWITCH(opponent, 1); }
TURN { MOVE(player, MOVE_CELEBRATE); SWITCH(opponent, 0); }
TURN { MOVE(player, MOVE_ROUND); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player);
ABILITY_POPUP(player, ABILITY_QUARK_DRIVE);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player);
HP_BAR(opponent, captureDamage: &damage[0]);
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!");
MESSAGE("The effects of the neutralizing gas wore off!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, player);
HP_BAR(opponent, captureDamage: &damage[1]);
} THEN {
EXPECT_EQ(damage[0], damage[1]);
}
}
SINGLE_BATTLE_TEST("Quark Drive ability pop up activates only once during the duration of electric terrain")
{
u16 turns;

View File

@ -65,6 +65,29 @@ SINGLE_BATTLE_TEST("Booster Energy will activate Protosynthesis after harsh sunl
}
}
SINGLE_BATTLE_TEST("Booster Energy's Protosynthesis boost is preserved when weather changes")
{
GIVEN {
PLAYER(SPECIES_RAGING_BOLT) { Attack(110); Defense(100); Speed(100); SpAttack(100); SpDefense(100); Ability(ABILITY_PROTOSYNTHESIS); Item(ITEM_BOOSTER_ENERGY); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(50); Moves(MOVE_SUNNY_DAY, MOVE_CELEBRATE); }
} WHEN {
TURN { MOVE(opponent, MOVE_SUNNY_DAY); }
TURN { }
TURN { }
TURN { }
TURN { }
TURN { }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Raging Bolt used its Booster Energy to activate Protosynthesis!");
MESSAGE("Raging Bolt's Attack was heightened!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent);
MESSAGE("The sunlight faded.");
} THEN {
EXPECT(gDisableStructs[B_POSITION_PLAYER_LEFT].paradoxBoostedStat == STAT_ATK);
}
}
SINGLE_BATTLE_TEST("Booster Energy activates Protosynthesis and increases highest stat")
{
u32 attack, defense, speed, spAttack, spDefense;
@ -131,6 +154,29 @@ SINGLE_BATTLE_TEST("Booster Energy activates Quark Drive and increases highest s
}
}
SINGLE_BATTLE_TEST("Booster Energy's Quark Drive boost is preserved when terrain changes")
{
GIVEN {
PLAYER(SPECIES_IRON_MOTH) { Attack(110); Defense(100); Speed(100); SpAttack(100); SpDefense(100); Ability(ABILITY_QUARK_DRIVE); Item(ITEM_BOOSTER_ENERGY); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(50); Moves(MOVE_GRASSY_TERRAIN, MOVE_CELEBRATE); }
} WHEN {
TURN { MOVE(opponent, MOVE_GRASSY_TERRAIN); }
TURN { }
TURN { }
TURN { }
TURN { }
TURN { }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Iron Moth used its Booster Energy to activate Quark Drive!");
MESSAGE("Iron Moth's Attack was heightened!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRASSY_TERRAIN, opponent);
MESSAGE("The grass disappeared from the battlefield.");
} THEN {
EXPECT(gDisableStructs[B_POSITION_PLAYER_LEFT].paradoxBoostedStat == STAT_ATK);
}
}
SINGLE_BATTLE_TEST("Booster Energy increases special attack by 30% if it is the highest stat", s16 damage)
{
u32 species;