Fix badge boost not applying in gen1 and 2 (#8013)

This commit is contained in:
FosterProgramming 2025-10-22 22:57:04 +02:00 committed by GitHub
parent dc0d910182
commit 1343ddf7c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 185 additions and 8 deletions

View File

@ -311,6 +311,7 @@ u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pok
bool32 SetIllusionMon(struct Pokemon *mon, u32 battler);
u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID);
bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler);
uq4_12_t GetBadgeBoostModifier(void);
enum DamageCategory GetBattleMoveCategory(u32 move);
void SetDynamicMoveCategory(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 CanFling(u32 battler);

View File

@ -19,7 +19,7 @@
#define B_LEVEL_UP_NOTIFICATION GEN_LATEST // In Gen9+, if the Pokémon gets enough experience to level up multiple times, the message is only displayed once.
// Stat settings
#define B_BADGE_BOOST GEN_LATEST // In Gen4+, Gym Badges no longer boost a Pokémon's stats.
#define B_BADGE_BOOST GEN_LATEST // In Gen4+, Gym Badges no longer boost a Pokémon's stats. (Gen2 does not include the additional boost to the type matching the gym the badge is from)
#define B_FRIENDSHIP_BOOST FALSE // In LGPE only, all stats except HP are boosted up to 10% based on Friendship. Unlike B_BADGE_BOOST, these boosts are accounted when calculating base stats.
#define B_MAX_LEVEL_EV_GAINS GEN_LATEST // In Gen5+, Lv100 Pokémon can obtain Effort Values normally.
#define B_RECALCULATE_STATS GEN_LATEST // In Gen5+, the stats of the Pokémon who participate in battle are recalculated at the end of each battle.

View File

@ -45,6 +45,7 @@ enum GenConfigTag
GEN_CONFIG_OBLIVIOUS_TAUNT,
GEN_CONFIG_TOXIC_NEVER_MISS,
GEN_CONFIG_PARALYZE_ELECTRIC,
GEN_CONFIG_BADGE_BOOST,
GEN_CONFIG_COUNT
};

View File

@ -48,6 +48,7 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] =
[GEN_CONFIG_OBLIVIOUS_TAUNT] = B_OBLIVIOUS_TAUNT,
[GEN_CONFIG_TOXIC_NEVER_MISS] = B_TOXIC_NEVER_MISS,
[GEN_CONFIG_PARALYZE_ELECTRIC] = B_PARALYZE_ELECTRIC,
[GEN_CONFIG_BADGE_BOOST] = B_BADGE_BOOST
};
#if TESTING

View File

@ -4770,7 +4770,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h
&& ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_SPEED, battler)
&& IsOnPlayerSide(battler))
{
speed = (speed * 110) / 100;
speed = uq4_12_multiply_by_int_half_down(GetBadgeBoostModifier(), speed);
}
// item effects

View File

@ -8766,9 +8766,9 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx)
// The offensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the corresponding flags set (eg. Badges)
if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_ATTACK, battlerAtk) && IsBattleMovePhysical(move))
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.1));
modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier());
if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_SPATK, battlerAtk) && IsBattleMoveSpecial(move))
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.1));
modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier());
return uq4_12_multiply_by_int_half_down(modifier, atkStat);
}
@ -8942,11 +8942,11 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx)
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SNOW) && usesDefStat)
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5));
// The offensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the corresponding flags set (eg. Badges)
// The defensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the corresponding flags set (eg. Badges)
if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_DEFENSE, battlerDef) && IsBattleMovePhysical(move))
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.1));
modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier());
if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_SPDEF, battlerDef) && IsBattleMoveSpecial(move))
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.1));
modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier());
return uq4_12_multiply_by_int_half_down(modifier, defStat);
}
@ -10432,9 +10432,17 @@ u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID)
return 0;
}
uq4_12_t GetBadgeBoostModifier(void)
{
if (GetGenConfig(GEN_CONFIG_BADGE_BOOST) < GEN_3)
return UQ_4_12(1.125);
else
return UQ_4_12(1.1);
}
bool32 ShouldGetStatBadgeBoost(u16 badgeFlag, u32 battler)
{
if (B_BADGE_BOOST == GEN_3 && badgeFlag != 0)
if (GetGenConfig(GEN_CONFIG_BADGE_BOOST) <= GEN_3 && badgeFlag != 0)
{
if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_FRONTIER))
return FALSE;

166
test/battle/badge_boost.c Normal file
View File

@ -0,0 +1,166 @@
#include "global.h"
#include "event_data.h"
#include "test/battle.h"
WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_ATTACK boost Attack", s16 dmg)
{
u32 badge = 0;
u32 genConfig = 0;
for (u32 gen = GEN_1; gen <= GEN_LATEST; gen++)
{
PARAMETRIZE{badge = FALSE; genConfig = gen;}
PARAMETRIZE{badge = TRUE; genConfig = gen;}
}
GIVEN {
if (badge)
FlagSet(B_FLAG_BADGE_BOOST_ATTACK);
else
FlagClear(B_FLAG_BADGE_BOOST_ATTACK);
WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig);
PLAYER(SPECIES_WOBBUFFET) {}
OPPONENT(SPECIES_WOBBUFFET) {}
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].dmg);
} FINALLY {
for (u32 gen = GEN_1; gen <= GEN_LATEST; gen++)
{
if (gen <= GEN_3)
EXPECT_GT(results[2 * gen + 1].dmg, results[2 * gen].dmg);
else
EXPECT_EQ(results[2 * gen + 1].dmg, results[2 * gen].dmg);
}
}
}
WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_SPATK boost Special Attack", s16 dmg)
{
u32 badge = 0;
u32 genConfig = 0;
for (u32 gen = GEN_1; gen <= GEN_LATEST; gen++)
{
PARAMETRIZE{badge = FALSE; genConfig = gen;}
PARAMETRIZE{badge = TRUE; genConfig = gen;}
}
GIVEN {
if (badge)
FlagSet(B_FLAG_BADGE_BOOST_SPATK);
else
FlagClear(B_FLAG_BADGE_BOOST_SPATK);
WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig);
PLAYER(SPECIES_WOBBUFFET) {}
OPPONENT(SPECIES_WOBBUFFET) {}
} WHEN {
TURN { MOVE(player, MOVE_THUNDER_SHOCK); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].dmg);
} FINALLY {
for (u32 gen = GEN_1; gen <= GEN_LATEST; gen++)
{
if (gen <= GEN_3)
EXPECT_GT(results[2 * gen + 1].dmg, results[2 * gen].dmg);
else
EXPECT_EQ(results[2 * gen + 1].dmg, results[2 * gen].dmg);
}
}
}
WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_DEFENSE boost Defense", s16 dmg)
{
u32 badge = 0;
u32 genConfig = 0;
for (u32 gen = GEN_1; gen <= GEN_LATEST; gen++)
{
PARAMETRIZE{badge = FALSE; genConfig = gen;}
PARAMETRIZE{badge = TRUE; genConfig = gen;}
}
GIVEN {
if (badge)
FlagSet(B_FLAG_BADGE_BOOST_DEFENSE);
else
FlagClear(B_FLAG_BADGE_BOOST_DEFENSE);
WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig);
PLAYER(SPECIES_WOBBUFFET) {}
OPPONENT(SPECIES_WOBBUFFET) {}
} WHEN {
TURN { MOVE(opponent, MOVE_SCRATCH); }
} SCENE {
HP_BAR(player, captureDamage: &results[i].dmg);
} FINALLY {
for (u32 gen = GEN_1; gen <= GEN_LATEST; gen++)
{
if (gen <= GEN_3)
EXPECT_LT(results[2 * gen + 1].dmg, results[2 * gen].dmg);
else
EXPECT_EQ(results[2 * gen + 1].dmg, results[2 * gen].dmg);
}
}
}
WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_SPDEF boost Special Defense", s16 dmg)
{
u32 badge = 0;
u32 genConfig = 0;
for (u32 gen = GEN_1; gen <= GEN_LATEST; gen++)
{
PARAMETRIZE{badge = FALSE; genConfig = gen;}
PARAMETRIZE{badge = TRUE; genConfig = gen;}
}
GIVEN {
if (badge)
FlagSet(B_FLAG_BADGE_BOOST_SPDEF);
else
FlagClear(B_FLAG_BADGE_BOOST_SPDEF);
WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig);
PLAYER(SPECIES_WOBBUFFET) {}
OPPONENT(SPECIES_WOBBUFFET) {}
} WHEN {
TURN { MOVE(opponent, MOVE_THUNDER_SHOCK); }
} SCENE {
HP_BAR(player, captureDamage: &results[i].dmg);
} FINALLY {
for (u32 gen = GEN_1; gen <= GEN_LATEST; gen++)
{
if (gen <= GEN_3)
EXPECT_LT(results[2 * gen + 1].dmg, results[2 * gen].dmg);
else
EXPECT_EQ(results[2 * gen + 1].dmg, results[2 * gen].dmg);
}
}
}
WILD_BATTLE_TEST("Badge boost: B_FLAG_BADGE_BOOST_SPEED boost Speed", s16 dmg)
{
u32 badge = 0;
u32 genConfig = 0;
for (u32 gen = GEN_1; gen <= GEN_LATEST; gen++)
{
PARAMETRIZE{badge = FALSE; genConfig = gen;}
PARAMETRIZE{badge = TRUE; genConfig = gen;}
}
GIVEN {
if (badge)
FlagSet(B_FLAG_BADGE_BOOST_SPEED);
else
FlagClear(B_FLAG_BADGE_BOOST_SPEED);
WITH_CONFIG(GEN_CONFIG_BADGE_BOOST, genConfig);
PLAYER(SPECIES_WOBBUFFET) { Speed(100); HP(1); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(101); HP(1); }
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); MOVE(opponent, MOVE_SCRATCH);}
} THEN {
if (badge && genConfig <= GEN_3)
{
EXPECT_EQ(opponent->hp, 0);
EXPECT_EQ(player->hp, 1);
}
else
{
EXPECT_EQ(opponent->hp, 1);
EXPECT_EQ(player->hp, 0);
}
}
}