Fix Protosynthesis/Quark Drive defensive boost calculation (#8875)

Co-authored-by: Hedara <hedara90@gmail.com>
This commit is contained in:
hedara90 2026-01-11 21:14:51 +01:00 committed by GitHub
parent 39bec6fa0c
commit b213d430e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 19 deletions

View File

@ -7512,24 +7512,6 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx)
if (moveType == TYPE_FIRE)
modifier = uq4_12_multiply(modifier, UQ_4_12(1.25));
break;
case ABILITY_PROTOSYNTHESIS:
{
enum Stat 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))
modifier = uq4_12_multiply(modifier, UQ_4_12(0.7));
}
break;
case ABILITY_QUARK_DRIVE:
{
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))
modifier = uq4_12_multiply(modifier, UQ_4_12(0.7));
}
break;
default:
break;
}
@ -8036,6 +8018,24 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx)
if (gBattleMons[battlerDef].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SUN) && !usesDefStat)
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5));
break;
case ABILITY_PROTOSYNTHESIS:
{
enum Stat 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))
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
}
break;
case ABILITY_QUARK_DRIVE:
{
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))
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
}
break;
default:
break;
}

View File

@ -312,3 +312,38 @@ SINGLE_BATTLE_TEST("Protosynthesis retains its boosted stat after Neutralizing G
EXPECT_EQ(damage[0], damage[1]);
}
}
SINGLE_BATTLE_TEST("Protosynthesis damage calculation is correct")
{
s16 dmg;
s16 expectedDamage;
PARAMETRIZE { expectedDamage = 127; }
PARAMETRIZE { expectedDamage = 126; }
PARAMETRIZE { expectedDamage = 124; }
PARAMETRIZE { expectedDamage = 123; }
PARAMETRIZE { expectedDamage = 121; }
PARAMETRIZE { expectedDamage = 120; }
PARAMETRIZE { expectedDamage = 118; }
PARAMETRIZE { expectedDamage = 118; }
PARAMETRIZE { expectedDamage = 117; }
PARAMETRIZE { expectedDamage = 115; }
PARAMETRIZE { expectedDamage = 114; }
PARAMETRIZE { expectedDamage = 112; }
PARAMETRIZE { expectedDamage = 111; }
PARAMETRIZE { expectedDamage = 109; }
PARAMETRIZE { expectedDamage = 109; }
PARAMETRIZE { expectedDamage = 108; }
GIVEN {
ASSUME(GetMoveCategory(MOVE_CLOSE_COMBAT) == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_GOUGING_FIRE) { Ability(ABILITY_PROTOSYNTHESIS); Item(ITEM_BOOSTER_ENERGY); }
OPPONENT(SPECIES_URSHIFU_RAPID_STRIKE);
} WHEN {
TURN { MOVE(opponent, MOVE_CLOSE_COMBAT, WITH_RNG(RNG_DAMAGE_MODIFIER, i)); }
} SCENE {
HP_BAR(player, captureDamage: &dmg);
} THEN {
EXPECT_EQ(expectedDamage, dmg);
}
}

View File

@ -225,7 +225,8 @@ SINGLE_BATTLE_TEST("Booster Energy increases special defense by 30% if it is the
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.7), results[1].damage);
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.77), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.77), results[3].damage);
}
}