From 4f655301efaeed31685da4c16b460595642abad5 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 7 Nov 2025 23:27:50 +0100 Subject: [PATCH 01/19] add cawtds as a contributor for code (#8166) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ CREDITS.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index a54e1caefd..0ae8f41116 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -450,6 +450,15 @@ "contributions": [ "code" ] + }, + { + "login": "cawtds", + "name": "cawtds", + "avatar_url": "https://avatars.githubusercontent.com/u/38510667?v=4", + "profile": "https://github.com/cawtds", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index 547b5bd52d..64a31a4077 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -75,6 +75,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d ghostyboyy97
ghostyboyy97

💻 Marky
Marky

💻 MandL27
MandL27

💻 + cawtds
cawtds

💻 From 0bd9dd6ee83a956ace9d048f7799a42b37febab7 Mon Sep 17 00:00:00 2001 From: ghostyboyy97 <106448956+ghostyboyy97@users.noreply.github.com> Date: Sat, 8 Nov 2025 11:21:16 -0500 Subject: [PATCH 02/19] fix (contrary): Contrary stat down handling in MoveEffectInPlus (#8165) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_ai_util.c | 43 ++++++++++++++++++++++++++++++++++ test/battle/ability/contrary.c | 27 +++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index d866e5b0d0..353705cefc 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1041,6 +1041,49 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 { switch (additionalEffect->moveEffect) { + case MOVE_EFFECT_ATK_MINUS_1: + case MOVE_EFFECT_ATK_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK)) + return TRUE; + break; + case MOVE_EFFECT_DEF_MINUS_1: + case MOVE_EFFECT_DEF_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK)) + return TRUE; + break; + case MOVE_EFFECT_SPD_MINUS_1: + case MOVE_EFFECT_SPD_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_DEF)) + return TRUE; + break; + case MOVE_EFFECT_SP_ATK_MINUS_1: + case MOVE_EFFECT_SP_ATK_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPATK)) + return TRUE; + break; + case MOVE_EFFECT_SP_DEF_MINUS_1: + case MOVE_EFFECT_SP_DEF_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPDEF)) + return TRUE; + break; + case MOVE_EFFECT_EVS_MINUS_1: + case MOVE_EFFECT_EVS_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_EVASION)) + return TRUE; + break; + case MOVE_EFFECT_ACC_MINUS_1: + case MOVE_EFFECT_ACC_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ACC)) + return TRUE; + break; + case MOVE_EFFECT_ATK_DEF_DOWN: + if (abilityAtk == ABILITY_CONTRARY && (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK) || BattlerStatCanRise(battlerAtk, abilityAtk, STAT_DEF))) + return TRUE; + break; + case MOVE_EFFECT_DEF_SPDEF_DOWN: + if (abilityAtk == ABILITY_CONTRARY && (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_DEF) || BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPDEF))) + return TRUE; + break; case MOVE_EFFECT_ATK_PLUS_1: case MOVE_EFFECT_ATK_PLUS_2: if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK)) diff --git a/test/battle/ability/contrary.c b/test/battle/ability/contrary.c index c69360a1e1..850ca60734 100644 --- a/test/battle/ability/contrary.c +++ b/test/battle/ability/contrary.c @@ -242,4 +242,31 @@ SINGLE_BATTLE_TEST("Sticky Web raises Speed by 1 for Contrary mon on switch-in") } } +AI_SINGLE_BATTLE_TEST("AI sees Contrary-effected moves correctly in MoveEffectInPlus instead of as a neutral effect") +{ + GIVEN{ + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_HERACROSS){ + Level(44); + HP(1); + Speed(5); + Nature(NATURE_ADAMANT); + Item(ITEM_LOADED_DICE); + Moves(MOVE_PIN_MISSILE); + } + OPPONENT(SPECIES_SERPERIOR){ + Level(44); + Speed(10); + Nature(NATURE_TIMID); + Ability(ABILITY_CONTRARY); + Moves(MOVE_DRAGON_PULSE, MOVE_SPIN_OUT, MOVE_HIDDEN_POWER, MOVE_GLARE); + } + } WHEN { + TURN{ + MOVE(player, MOVE_PIN_MISSILE); + EXPECT_MOVE(opponent, MOVE_SPIN_OUT); // previously all 107, now sees speed can rise w/ Contrary + } + } +} + TO_DO_BATTLE_TEST("Contrary does not invert stat changes that have been Baton-passed") From c2c0c06a6f3aef07a7a5bda4af5f13b30ad5bb2b Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Sat, 8 Nov 2025 17:22:47 +0100 Subject: [PATCH 03/19] Fix gba sprites trying load non existent female versions (#7996) --- .../pokemon/species_info/gen_1_families.h | 96 +++++++++---------- .../pokemon/species_info/gen_2_families.h | 76 +++++++-------- .../pokemon/species_info/gen_3_families.h | 68 ++++++------- 3 files changed, 120 insertions(+), 120 deletions(-) diff --git a/src/data/pokemon/species_info/gen_1_families.h b/src/data/pokemon/species_info/gen_1_families.h index daae4cc252..ce9cdce188 100644 --- a/src/data/pokemon/species_info/gen_1_families.h +++ b/src/data/pokemon/species_info/gen_1_families.h @@ -200,12 +200,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Venusaur, .iconSprite = gMonIcon_Venusaur, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 1 : 4, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_VenusaurF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_VenusaurF, .backPicSizeFemale = MON_COORDS_SIZE(64, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(2, 6, SHADOW_SIZE_XL_BATTLE_ONLY) FOOTPRINT(Venusaur) @@ -1336,12 +1336,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Butterfree, .iconSprite = gMonIcon_Butterfree, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_ButterfreeF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_ButterfreeF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-3, 13, SHADOW_SIZE_S) FOOTPRINT(Butterfree) @@ -2100,12 +2100,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Rattata, .iconSprite = gMonIcon_Rattata, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_RattataF, .frontPicSizeFemale = MON_COORDS_SIZE(40, 40), .backPicFemale = gMonBackPic_RattataF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_FAST, SHADOW(1, -3, SHADOW_SIZE_S) FOOTPRINT(Rattata) @@ -2192,12 +2192,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Raticate, .iconSprite = gMonIcon_Raticate, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 1 : 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_RaticateF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_RaticateF, .backPicSizeFemale = MON_COORDS_SIZE(64, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_FAST, SHADOW(0, 8, SHADOW_SIZE_L) FOOTPRINT(Raticate) @@ -2916,7 +2916,7 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Pikachu, .iconSprite = gMonIcon_Pikachu, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_PikachuF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 48), .backPicFemale = gMonBackPic_PikachuF, @@ -2925,7 +2925,7 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .iconSpriteFemale = gMonIcon_PikachuF, .iconPalIndexFemale = 2, #endif //P_CUSTOM_GENDER_DIFF_ICONS -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NORMAL, SHADOW(-3, 5, SHADOW_SIZE_M) OVERWORLD( @@ -5604,12 +5604,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Zubat, .iconSprite = gMonIcon_Zubat, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_ZubatF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 48), .backPicFemale = gMonBackPic_ZubatF, .backPicSizeFemale = MON_COORDS_SIZE(56, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-4, 11, SHADOW_SIZE_S) FOOTPRINT(Zubat) @@ -5703,12 +5703,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Golbat, .iconSprite = gMonIcon_Golbat, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_GolbatF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_GolbatF, .backPicSizeFemale = MON_COORDS_SIZE(56, 40), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(2, 14, SHADOW_SIZE_M) FOOTPRINT(Golbat) @@ -5954,12 +5954,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Gloom, .iconSprite = gMonIcon_Gloom, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_GloomF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 48), .backPicFemale = gMonBackPic_GloomF, .backPicSizeFemale = MON_COORDS_SIZE(64, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-1, 3, SHADOW_SIZE_M) FOOTPRINT(Gloom) @@ -6047,12 +6047,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Vileplume, .iconSprite = gMonIcon_Vileplume, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_VileplumeF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 56), .backPicFemale = gMonBackPic_VileplumeF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-1, 7, SHADOW_SIZE_L) FOOTPRINT(Vileplume) @@ -8219,12 +8219,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Politoed, .iconSprite = gMonIcon_Politoed, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_PolitoedF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 56), .backPicFemale = gMonBackPic_PolitoedF, .backPicSizeFemale = MON_COORDS_SIZE(56, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(1, 9, SHADOW_SIZE_M) FOOTPRINT(Politoed) @@ -8382,12 +8382,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Kadabra, .iconSprite = gMonIcon_Kadabra, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_KadabraF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_KadabraF, .backPicSizeFemale = MON_COORDS_SIZE(64, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(1, 6, SHADOW_SIZE_L) FOOTPRINT(Kadabra) @@ -8481,12 +8481,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Alakazam, .iconSprite = gMonIcon_Alakazam, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_AlakazamF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_AlakazamF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-1, 9, SHADOW_SIZE_L) FOOTPRINT(Alakazam) @@ -10991,12 +10991,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Doduo, .iconSprite = gMonIcon_Doduo, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_DoduoF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_DoduoF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(6, 5, SHADOW_SIZE_M) FOOTPRINT(Doduo) @@ -11084,12 +11084,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Dodrio, .iconSprite = gMonIcon_Dodrio, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_DodrioF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_DodrioF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(3, 12, SHADOW_SIZE_L) FOOTPRINT(Dodrio) @@ -12187,12 +12187,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Steelix, .iconSprite = gMonIcon_Steelix, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_SteelixF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_SteelixF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(2, 12, SHADOW_SIZE_XL_BATTLE_ONLY) FOOTPRINT(Steelix) @@ -12429,12 +12429,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Hypno, .iconSprite = gMonIcon_Hypno, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 1 : 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_HypnoF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_HypnoF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-3, 9, SHADOW_SIZE_L) FOOTPRINT(Hypno) @@ -14188,12 +14188,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Rhyhorn, .iconSprite = gMonIcon_Rhyhorn, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_RhyhornF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 40), .backPicFemale = gMonBackPic_RhyhornF, .backPicSizeFemale = MON_COORDS_SIZE(64, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(0, 0, SHADOW_SIZE_L) FOOTPRINT(Rhyhorn) @@ -14269,12 +14269,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Rhydon, .iconSprite = gMonIcon_Rhydon, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_RhydonF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_RhydonF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(3, 9, SHADOW_SIZE_XL_BATTLE_ONLY) FOOTPRINT(Rhydon) @@ -15215,12 +15215,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Goldeen, .iconSprite = gMonIcon_Goldeen, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_GoldeenF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 40), .backPicFemale = gMonBackPic_GoldeenF, .backPicSizeFemale = MON_COORDS_SIZE(64, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-6, 0, SHADOW_SIZE_XL_BATTLE_ONLY) FOOTPRINT(Goldeen) @@ -15300,12 +15300,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Seaking, .iconSprite = gMonIcon_Seaking, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_SeakingF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_SeakingF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(0, 8, SHADOW_SIZE_XL_BATTLE_ONLY) FOOTPRINT(Seaking) @@ -17178,12 +17178,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Magikarp, .iconSprite = gMonIcon_Magikarp, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_MagikarpF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 56), .backPicFemale = gMonBackPic_MagikarpF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(1, 7, SHADOW_SIZE_M) FOOTPRINT(Magikarp) @@ -17260,12 +17260,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Gyarados, .iconSprite = gMonIcon_Gyarados, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_GyaradosF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_GyaradosF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(5, 9, SHADOW_SIZE_XL_BATTLE_ONLY) FOOTPRINT(Gyarados) @@ -17622,12 +17622,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Eevee, .iconSprite = gMonIcon_Eevee, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_EeveeF, .frontPicSizeFemale = MON_COORDS_SIZE(40, 48), .backPicFemale = gMonBackPic_EeveeF, .backPicSizeFemale = MON_COORDS_SIZE(56, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NORMAL, SHADOW(-2, 2, SHADOW_SIZE_S) FOOTPRINT(Eevee) @@ -17777,7 +17777,7 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .shinyPalette = gMonShinyPalette_Eevee, .iconSprite = gMonIcon_EeveePartner, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_EeveeF, .frontPicSizeFemale = MON_COORDS_SIZE(40, 48), .backPicFemale = gMonBackPic_EeveeF, @@ -17786,7 +17786,7 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .iconSpriteFemale = gMonIcon_EeveePartnerF, .iconPalIndexFemale = 2, #endif -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NORMAL, SHADOW(-2, 2, SHADOW_SIZE_S) FOOTPRINT(Eevee) diff --git a/src/data/pokemon/species_info/gen_2_families.h b/src/data/pokemon/species_info/gen_2_families.h index f95197332a..702b907451 100644 --- a/src/data/pokemon/species_info/gen_2_families.h +++ b/src/data/pokemon/species_info/gen_2_families.h @@ -198,12 +198,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Meganium, .iconSprite = gMonIcon_Meganium, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_MeganiumF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 64), .backPicFemale = gMonBackPic_MeganiumF, .backPicSizeFemale = MON_COORDS_SIZE(56, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(0, 13, SHADOW_SIZE_M) FOOTPRINT(Meganium) @@ -1074,12 +1074,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Ledyba, .iconSprite = gMonIcon_Ledyba, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_LedybaF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 48), .backPicFemale = gMonBackPic_LedybaF, .backPicSizeFemale = MON_COORDS_SIZE(56, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(2, 4, SHADOW_SIZE_M) FOOTPRINT(Ledyba) @@ -1158,12 +1158,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Ledian, .iconSprite = gMonIcon_Ledian, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_LedianF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 56), .backPicFemale = gMonBackPic_LedianF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(0, 15, SHADOW_SIZE_S) FOOTPRINT(Ledian) @@ -2522,12 +2522,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Sudowoodo, .iconSprite = gMonIcon_Sudowoodo, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_SudowoodoF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 56), .backPicFemale = gMonBackPic_SudowoodoF, .backPicSizeFemale = MON_COORDS_SIZE(48, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-2, 7, SHADOW_SIZE_S) FOOTPRINT(Sudowoodo) @@ -2842,12 +2842,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Aipom, .iconSprite = gMonIcon_Aipom, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_AipomF, .frontPicSizeFemale = MON_COORDS_SIZE(32, 64), .backPicFemale = gMonBackPic_AipomF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-1, 12, SHADOW_SIZE_S) FOOTPRINT(Aipom) @@ -2927,12 +2927,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Ambipom, .iconSprite = gMonIcon_Ambipom, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_AmbipomF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_AmbipomF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-1, 13, SHADOW_SIZE_S) FOOTPRINT(Ambipom) @@ -3347,12 +3347,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Wooper, .iconSprite = gMonIcon_Wooper, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_WooperF, .frontPicSizeFemale = MON_COORDS_SIZE(40, 32), .backPicFemale = gMonBackPic_WooperF, .backPicSizeFemale = MON_COORDS_SIZE(64, 40), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_SLOW, SHADOW(1, -2, SHADOW_SIZE_S) FOOTPRINT(Wooper) @@ -3429,12 +3429,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Quagsire, .iconSprite = gMonIcon_Quagsire, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_QuagsireF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_QuagsireF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(0, 8, SHADOW_SIZE_M) FOOTPRINT(Quagsire) @@ -3647,12 +3647,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Murkrow, .iconSprite = gMonIcon_Murkrow, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_MurkrowF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 40), .backPicFemale = gMonBackPic_MurkrowF, .backPicSizeFemale = MON_COORDS_SIZE(40, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-2, 8, SHADOW_SIZE_S) FOOTPRINT(Murkrow) @@ -4134,7 +4134,7 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Wobbuffet, .iconSprite = gMonIcon_Wobbuffet, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_WobbuffetF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_WobbuffetF, @@ -4143,7 +4143,7 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .iconSpriteFemale = gMonIcon_WobbuffetF, .iconPalIndexFemale = 0, #endif -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-3, 8, SHADOW_SIZE_M) FOOTPRINT(Wobbuffet) @@ -4221,12 +4221,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Girafarig, .iconSprite = gMonIcon_Girafarig, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_GirafarigF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 64), .backPicFemale = gMonBackPic_GirafarigF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(2, 13, SHADOW_SIZE_M) FOOTPRINT(Girafarig) @@ -4728,12 +4728,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Gligar, .iconSprite = gMonIcon_Gligar, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 2 : 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_GligarF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 56), .backPicFemale = gMonBackPic_GligarF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(0, 15, SHADOW_SIZE_S) FOOTPRINT(Gligar) @@ -5332,12 +5332,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Heracross, .iconSprite = gMonIcon_Heracross, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 2 : 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_HeracrossF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_HeracrossF, .backPicSizeFemale = MON_COORDS_SIZE(48, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-1, 10, SHADOW_SIZE_M) FOOTPRINT(Heracross) @@ -5493,12 +5493,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Sneasel, .iconSprite = gMonIcon_Sneasel, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_SneaselF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 48), .backPicFemale = gMonBackPic_SneaselF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-1, 5, SHADOW_SIZE_S) FOOTPRINT(Sneasel) @@ -5888,12 +5888,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Ursaring, .iconSprite = gMonIcon_Ursaring, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_UrsaringF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_UrsaringF, .backPicSizeFemale = MON_COORDS_SIZE(56, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(1, 14, SHADOW_SIZE_L) FOOTPRINT(Ursaring) @@ -6323,12 +6323,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Piloswine, .iconSprite = gMonIcon_Piloswine, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_PiloswineF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 56), .backPicFemale = gMonBackPic_PiloswineF, .backPicSizeFemale = MON_COORDS_SIZE(64, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-1, 3, SHADOW_SIZE_M) FOOTPRINT(Piloswine) @@ -6791,12 +6791,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Octillery, .iconSprite = gMonIcon_Octillery, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_OctilleryF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 48), .backPicFemale = gMonBackPic_OctilleryF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(1, 4, SHADOW_SIZE_M) FOOTPRINT(Octillery) @@ -7229,12 +7229,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Houndoom, .iconSprite = gMonIcon_Houndoom, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_HoundoomF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_HoundoomF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-5, 13, SHADOW_SIZE_L) FOOTPRINT(Houndoom) @@ -7456,12 +7456,12 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .shinyPalette = gMonShinyPalette_Donphan, .iconSprite = gMonIcon_Donphan, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_DonphanF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 48), .backPicFemale = gMonBackPic_DonphanF, .backPicSizeFemale = MON_COORDS_SIZE(64, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(7, 2, SHADOW_SIZE_L) FOOTPRINT(Donphan) diff --git a/src/data/pokemon/species_info/gen_3_families.h b/src/data/pokemon/species_info/gen_3_families.h index 6ad30646cf..566f79b404 100644 --- a/src/data/pokemon/species_info/gen_3_families.h +++ b/src/data/pokemon/species_info/gen_3_families.h @@ -347,10 +347,10 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Torchic, .iconSprite = gMonIcon_Torchic, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .backPicFemale = gMonBackPic_TorchicF, .backPicSizeFemale = MON_COORDS_SIZE(40, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_SLOW, SHADOW(-1, 1, SHADOW_SIZE_S) FOOTPRINT(Torchic) @@ -428,12 +428,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Combusken, .iconSprite = gMonIcon_Combusken, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_CombuskenF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 64), .backPicFemale = gMonBackPic_CombuskenF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-1, 8, SHADOW_SIZE_M) FOOTPRINT(Combusken) @@ -517,12 +517,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Blaziken, .iconSprite = gMonIcon_Blaziken, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_BlazikenF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 64), .backPicFemale = gMonBackPic_BlazikenF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(4, 8, SHADOW_SIZE_M) FOOTPRINT(Blaziken) @@ -1644,12 +1644,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Beautifly, .iconSprite = gMonIcon_Beautifly, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_BeautiflyF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_BeautiflyF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-5, 12, SHADOW_SIZE_S) FOOTPRINT(Beautifly) @@ -1825,12 +1825,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Dustox, .iconSprite = gMonIcon_Dustox, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 1 : 5, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_DustoxF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 48), .backPicFemale = gMonBackPic_DustoxF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-2, 11, SHADOW_SIZE_S) FOOTPRINT(Dustox) @@ -2059,12 +2059,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Ludicolo, .iconSprite = gMonIcon_Ludicolo, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_LudicoloF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 64), .backPicFemale = gMonBackPic_LudicoloF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-3, 14, SHADOW_SIZE_M) FOOTPRINT(Ludicolo) @@ -2224,12 +2224,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Nuzleaf, .iconSprite = gMonIcon_Nuzleaf, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_NuzleafF, .frontPicSizeFemale = MON_COORDS_SIZE(40, 56), .backPicFemale = gMonBackPic_NuzleafF, .backPicSizeFemale = MON_COORDS_SIZE(56, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-3, 5, SHADOW_SIZE_S) FOOTPRINT(Nuzleaf) @@ -2316,12 +2316,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Shiftry, .iconSprite = gMonIcon_Shiftry, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 0 : 5, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_ShiftryF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_ShiftryF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-5, 5, SHADOW_SIZE_M) FOOTPRINT(Shiftry) @@ -5202,12 +5202,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Meditite, .iconSprite = gMonIcon_Meditite, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_MedititeF, .frontPicSizeFemale = MON_COORDS_SIZE(48, 48), .backPicFemale = gMonBackPic_MedititeF, .backPicSizeFemale = MON_COORDS_SIZE(48, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_SLOW, SHADOW(0, 1, SHADOW_SIZE_S) FOOTPRINT(Meditite) @@ -5288,12 +5288,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Medicham, .iconSprite = gMonIcon_Medicham, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_MedichamF, .frontPicSizeFemale = MON_COORDS_SIZE(40, 64), .backPicFemale = gMonBackPic_MedichamF, .backPicSizeFemale = MON_COORDS_SIZE(56, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(-2, 13, SHADOW_SIZE_S) FOOTPRINT(Medicham) @@ -6046,12 +6046,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Roselia, .iconSprite = gMonIcon_Roselia, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 0 : 4, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_RoseliaF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 48), .backPicFemale = gMonBackPic_RoseliaF, .backPicSizeFemale = MON_COORDS_SIZE(64, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_SLOW, SHADOW(-2, 3, SHADOW_SIZE_S) FOOTPRINT(Roselia) @@ -6227,12 +6227,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Gulpin, .iconSprite = gMonIcon_Gulpin, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_GulpinF, .frontPicSizeFemale = MON_COORDS_SIZE(40, 48), .backPicFemale = gMonBackPic_GulpinF, .backPicSizeFemale = MON_COORDS_SIZE(56, 48), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_SLOW, SHADOW(1, -2, SHADOW_SIZE_S) FOOTPRINT(Gulpin) @@ -6312,12 +6312,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Swalot, .iconSprite = gMonIcon_Swalot, .iconPalIndex = 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_SwalotF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 56), .backPicFemale = gMonBackPic_SwalotF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(4, 3, SHADOW_SIZE_L) FOOTPRINT(Swalot) @@ -6769,12 +6769,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Numel, .iconSprite = gMonIcon_Numel, .iconPalIndex = 1, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_NumelF, .frontPicSizeFemale = MON_COORDS_SIZE(40, 48), .backPicFemale = gMonBackPic_NumelF, .backPicSizeFemale = MON_COORDS_SIZE(56, 56), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_SLOW, SHADOW(4, 2, SHADOW_SIZE_S) FOOTPRINT(Numel) @@ -6860,12 +6860,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Camerupt, .iconSprite = gMonIcon_Camerupt, .iconPalIndex = 0, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_CameruptF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 56), .backPicFemale = gMonBackPic_CameruptF, .backPicSizeFemale = MON_COORDS_SIZE(64, 40), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(2, 4, SHADOW_SIZE_L) FOOTPRINT(Camerupt) @@ -9112,12 +9112,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Milotic, .iconSprite = gMonIcon_Milotic, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 0 : 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_MiloticF, .frontPicSizeFemale = MON_COORDS_SIZE(64, 64), .backPicFemale = gMonBackPic_MiloticF, .backPicSizeFemale = MON_COORDS_SIZE(64, 64), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(0, 12, SHADOW_SIZE_M) FOOTPRINT(Milotic) @@ -11201,12 +11201,12 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .shinyPalette = gMonShinyPalette_Relicanth, .iconSprite = gMonIcon_Relicanth, .iconPalIndex = P_GBA_STYLE_SPECIES_ICONS ? 1 : 2, -#if P_GENDER_DIFFERENCES +#if P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .frontPicFemale = gMonFrontPic_RelicanthF, .frontPicSizeFemale = MON_COORDS_SIZE(56, 56), .backPicFemale = gMonBackPic_RelicanthF, .backPicSizeFemale = MON_COORDS_SIZE(64, 40), -#endif //P_GENDER_DIFFERENCES +#endif //P_GENDER_DIFFERENCES && !P_GBA_STYLE_SPECIES_GFX .pokemonJumpType = PKMN_JUMP_TYPE_NONE, SHADOW(0, 3, SHADOW_SIZE_M) FOOTPRINT(Relicanth) From bdaf4ae3b387460b910e5a82e8b5039c23ce87bf Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Sun, 9 Nov 2025 15:03:43 +0100 Subject: [PATCH 04/19] Fix destiny knot behavior and add tests (#8174) --- asm/macros/battle_script.inc | 6 --- data/battle_scripts_1.s | 16 ++++--- src/battle_message.c | 2 +- src/battle_script_commands.c | 9 ---- test/battle/hold_effect/destiny_knot.c | 66 ++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 22 deletions(-) create mode 100644 test/battle/hold_effect/destiny_knot.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 6203c3a7bf..e5da506a4d 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1970,12 +1970,6 @@ .4byte \jumpInstr .endm - .macro infatuatewithbattler battler:req, infatuateWith:req - callnative BS_InfatuateWithBattler - .byte \battler - .byte \infatuateWith - .endm - .macro setlastuseditem battler:req callnative BS_SetLastUsedItem .byte \battler diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index b47a683f2c..cc00828984 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -4025,26 +4025,27 @@ BattleScript_FuryCutterHit: BattleScript_TryDestinyKnotTarget: jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_DESTINY_KNOT, BattleScript_TryDestinyKnotTargetRet - infatuatewithbattler BS_TARGET, BS_ATTACKER playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT waitanimation + printstring STRINGID_DESTINYKNOTACTIVATES + tryinfatuating BattleScript_ButItFailed volatileanimation BS_TARGET, VOLATILE_INFATUATION waitanimation - printstring STRINGID_DESTINYKNOTACTIVATES waitmessage B_WAIT_TIME_LONG BattleScript_TryDestinyKnotTargetRet: return BattleScript_TryDestinyKnotAttacker: - jumpifnoholdeffect BS_TARGET, HOLD_EFFECT_DESTINY_KNOT, BattleScript_TryDestinyKnotAttackerRet - infatuatewithbattler BS_ATTACKER, BS_TARGET + jumpifnoholdeffect BS_TARGET, HOLD_EFFECT_DESTINY_KNOT, BattleScript_TryDestinyKnotTargetRet playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT waitanimation + swapattackerwithtarget + printstring STRINGID_DESTINYKNOTACTIVATES + tryinfatuating BattleScript_SwapTargetAttackerButItFailed + swapattackerwithtarget volatileanimation BS_ATTACKER, VOLATILE_INFATUATION waitanimation - printstring STRINGID_DESTINYKNOTACTIVATES waitmessage B_WAIT_TIME_LONG -BattleScript_TryDestinyKnotAttackerRet: return BattleScript_EffectAttract:: @@ -4378,6 +4379,9 @@ BattleScript_RestoreAttackerButItFailed: BattleScript_RestoreTargetButItFailed: restoretarget goto BattleScript_ButItFailed +BattleScript_SwapTargetAttackerButItFailed: + swapattackerwithtarget + goto BattleScript_ButItFailed BattleScript_NotAffected:: pause B_WAIT_TIME_SHORT diff --git a/src/battle_message.c b/src/battle_message.c index 0eb8c85791..fc33a06414 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -705,7 +705,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_RECEIVERABILITYTAKEOVER] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} was taken over!"), [STRINGID_PKNMABSORBINGPOWER] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is absorbing power!"), [STRINGID_NOONEWILLBEABLETORUNAWAY] = COMPOUND_STRING("No one will be able to run away during the next turn!"), - [STRINGID_DESTINYKNOTACTIVATES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} fell in love because of the {B_LAST_ITEM}!"), + [STRINGID_DESTINYKNOTACTIVATES] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} fell in love because of the {B_LAST_ITEM}!"), [STRINGID_CLOAKEDINAFREEZINGLIGHT] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} became cloaked in a freezing light!"), [STRINGID_CLEARAMULETWONTLOWERSTATS] = COMPOUND_STRING("The effects of the {B_LAST_ITEM} held by {B_SCR_NAME_WITH_PREFIX2} prevents its stats from being lowered!"), [STRINGID_FERVENTWISHREACHED] = COMPOUND_STRING("{B_ATK_TRAINER_NAME}'s fervent wish has reached {B_ATK_NAME_WITH_PREFIX2}!"), diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f3a4cbd803..3d4bd61613 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -16848,15 +16848,6 @@ void BS_JumpIfNoAlly(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_InfatuateWithBattler(void) -{ - NATIVE_ARGS(u8 battler, u8 infatuateWith); - u32 battler = GetBattlerForBattleScript(cmd->battler); - gBattleScripting.battler = battler; - gBattleMons[battler].volatiles.infatuation = INFATUATED_WITH(GetBattlerForBattleScript(cmd->infatuateWith)); - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_SetLastUsedItem(void) { NATIVE_ARGS(u8 battler); diff --git a/test/battle/hold_effect/destiny_knot.c b/test/battle/hold_effect/destiny_knot.c new file mode 100644 index 0000000000..b8097c6012 --- /dev/null +++ b/test/battle/hold_effect/destiny_knot.c @@ -0,0 +1,66 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_DESTINY_KNOT].holdEffect == HOLD_EFFECT_DESTINY_KNOT); +} + +SINGLE_BATTLE_TEST("Destiny Knot infatuates back when holder is targeted") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); } + OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); Item(ITEM_DESTINY_KNOT); } + } WHEN { + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("Wobbuffet fell in love because of the Destiny Knot!"); + } THEN { + EXPECT(player->volatiles.infatuation); + } +} + +SINGLE_BATTLE_TEST("Destiny Knot infatuates back when holder is attacking") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); Item(ITEM_DESTINY_KNOT);} + OPPONENT(SPECIES_CLEFAIRY) { Gender(MON_FEMALE); Ability(ABILITY_CUTE_CHARM);} + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("The opposing Clefairy fell in love because of the Destiny Knot!"); + } THEN { + EXPECT(opponent->volatiles.infatuation); + } +} + + +SINGLE_BATTLE_TEST("Destiny Knot procs but fails if the target is already infatuated") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); } + OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); Item(ITEM_DESTINY_KNOT); } + } WHEN { + TURN { MOVE(opponent, MOVE_ATTRACT); MOVE(player, MOVE_ATTRACT, WITH_RNG(RNG_INFATUATION, FALSE)); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Destiny Knot procs but fails if the target is oblivious") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); Ability(ABILITY_OBLIVIOUS); } + OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); Item(ITEM_DESTINY_KNOT); } + } WHEN { + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + ABILITY_POPUP(player, ABILITY_OBLIVIOUS); + } THEN { + EXPECT(!player->volatiles.infatuation); + } +} From 43f9a78da5a3991691a5e302e978c732cf7b9451 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Sun, 9 Nov 2025 17:46:22 +0100 Subject: [PATCH 05/19] Fix recharge moves + add recharge move tests (#8181) --- include/constants/battle.h | 1 - src/battle_ai_util.c | 2 +- src/battle_debug.c | 1 - src/battle_main.c | 9 ++-- src/battle_script_commands.c | 1 - src/battle_util.c | 6 +-- test/battle/move_effect_secondary/recharge.c | 52 ++++++++++++++++++++ 7 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 test/battle/move_effect_secondary/recharge.c diff --git a/include/constants/battle.h b/include/constants/battle.h index 012b8986ef..d2913d6fc6 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -160,7 +160,6 @@ enum VolatileFlags F(VOLATILE_INFATUATION, infatuation, (enum BattlerId, MAX_BITS(4))) \ F(VOLATILE_DEFENSE_CURL, defenseCurl, (u32, 1)) \ F(VOLATILE_TRANSFORMED, transformed, (u32, 1)) \ - F(VOLATILE_RECHARGE, recharge, (u32, 1)) \ F(VOLATILE_RAGE, rage, (u32, 1)) \ F(VOLATILE_SUBSTITUTE, substitute, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_DESTINY_BOND, destinyBond, (u32, 1)) \ diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 353705cefc..8bed0234ee 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -3435,7 +3435,7 @@ bool32 IsBattlerIncapacitated(u32 battler, u32 ability) if (gBattleMons[battler].status1 & STATUS1_SLEEP && !HasMoveWithEffect(battler, EFFECT_SLEEP_TALK)) return TRUE; - if (gBattleMons[battler].volatiles.recharge || (ability == ABILITY_TRUANT && gDisableStructs[battler].truantCounter != 0)) + if (gDisableStructs[battler].rechargeTimer > 0 || (ability == ABILITY_TRUANT && gDisableStructs[battler].truantCounter != 0)) return TRUE; return FALSE; diff --git a/src/battle_debug.c b/src/battle_debug.c index 149cb4065c..b160dd9d78 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -361,7 +361,6 @@ static const struct ListMenuItem sVolatileStatusListItems[] = {COMPOUND_STRING("Torment"), VOLATILE_TORMENT}, {COMPOUND_STRING("Powder"), VOLATILE_POWDER}, {COMPOUND_STRING("DefenseCurl"), VOLATILE_DEFENSE_CURL}, - {COMPOUND_STRING("Recharge"), VOLATILE_RECHARGE}, {COMPOUND_STRING("Rage"), VOLATILE_RAGE}, {COMPOUND_STRING("DestinyBond"), VOLATILE_DESTINY_BOND}, {COMPOUND_STRING("EscapePrevention"), VOLATILE_ESCAPE_PREVENTION}, diff --git a/src/battle_main.c b/src/battle_main.c index 15dfe0a3e4..702550c22d 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4213,7 +4213,7 @@ static void HandleTurnActionSelectionState(void) else { if (gBattleMons[battler].volatiles.multipleTurns - || gBattleMons[battler].volatiles.recharge) + || gDisableStructs[battler].rechargeTimer > 0) { gChosenActionByBattler[battler] = B_ACTION_USE_MOVE; gBattleCommunication[battler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY; @@ -4368,7 +4368,7 @@ static void HandleTurnActionSelectionState(void) gBattleCommunication[GetPartnerBattler(battler)] = STATE_BEFORE_ACTION_CHOSEN; RecordedBattle_ClearBattlerAction(battler, 1); if (gBattleMons[GetPartnerBattler(battler)].volatiles.multipleTurns - || gBattleMons[GetPartnerBattler(battler)].volatiles.recharge) + || gDisableStructs[GetPartnerBattler(battler)].rechargeTimer > 0) { BtlController_EmitEndBounceEffect(battler, B_COMM_TO_CONTROLLER); MarkBattlerForControllerExec(battler); @@ -5132,11 +5132,8 @@ static void TurnValuesCleanUp(bool8 var0) gDisableStructs[i].isFirstTurn--; if (gDisableStructs[i].rechargeTimer) - { gDisableStructs[i].rechargeTimer--; - if (gDisableStructs[i].rechargeTimer == 0) - gBattleMons[i].volatiles.recharge = FALSE; - } + gBattleStruct->battlerState[i].canPickupItem = FALSE; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3d4bd61613..ca7f490f11 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3314,7 +3314,6 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (B_SKIP_RECHARGE == GEN_1 && !IsBattlerAlive(gBattlerTarget)) // Skip recharge if gen 1 and foe is KO'd break; - gBattleMons[gEffectBattler].volatiles.recharge = TRUE; gDisableStructs[gEffectBattler].rechargeTimer = 2; gLockedMoves[gEffectBattler] = gCurrentMove; gBattlescriptCurrInstr++; diff --git a/src/battle_util.c b/src/battle_util.c index c3cd8c5b54..f6a61ffde4 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -406,7 +406,7 @@ void HandleAction_UseMove(void) gHitMarker |= HITMARKER_NO_PPDEDUCT; gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(MOVE_STRUGGLE, NO_TARGET_OVERRIDE); } - else if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns || gBattleMons[gBattlerAttacker].volatiles.recharge) + else if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns || gDisableStructs[gBattlerAttacker].rechargeTimer > 0) { gCurrentMove = gChosenMove = gLockedMoves[gBattlerAttacker]; } @@ -1928,10 +1928,8 @@ static enum MoveCanceller CancellerSkyDrop(void) static enum MoveCanceller CancellerRecharge(void) { - if (gBattleMons[gBattlerAttacker].volatiles.recharge) + if (gDisableStructs[gBattlerAttacker].rechargeTimer > 0) { - gBattleMons[gBattlerAttacker].volatiles.recharge = FALSE; - gDisableStructs[gBattlerAttacker].rechargeTimer = 0; CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; diff --git a/test/battle/move_effect_secondary/recharge.c b/test/battle/move_effect_secondary/recharge.c new file mode 100644 index 0000000000..9146083675 --- /dev/null +++ b/test/battle/move_effect_secondary/recharge.c @@ -0,0 +1,52 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(MoveHasAdditionalEffectSelf(MOVE_METEOR_ASSAULT, MOVE_EFFECT_RECHARGE) == TRUE); +} + +SINGLE_BATTLE_TEST("Recharge moves make the user unable to attack for exactly one turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { } + OPPONENT(SPECIES_WOBBUFFET) { } + } WHEN { + TURN { MOVE(player, MOVE_METEOR_ASSAULT);} + TURN { SKIP_TURN(player);} + TURN { MOVE(player, MOVE_TACKLE);} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_METEOR_ASSAULT, player); + MESSAGE("Wobbuffet must recharge!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + } +} + +SINGLE_BATTLE_TEST("Recharge moves don't timeout when all battlers are recharging") +{ + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { } + OPPONENT(SPECIES_WOBBUFFET) { } + } WHEN { + TURN { MOVE(player, MOVE_METEOR_ASSAULT); MOVE(opponent, MOVE_METEOR_ASSAULT);} + } +} + +DOUBLE_BATTLE_TEST("Recharge moves don't timeout when all battlers are recharging (doubles") +{ + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { } + PLAYER(SPECIES_WYNAUT) { } + OPPONENT(SPECIES_WOBBUFFET) { } + OPPONENT(SPECIES_WYNAUT) { } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_METEOR_ASSAULT, target: opponentLeft); + MOVE(playerRight, MOVE_METEOR_ASSAULT, target: opponentRight); + MOVE(opponentLeft, MOVE_METEOR_ASSAULT, target: playerLeft); + MOVE(opponentRight, MOVE_METEOR_ASSAULT, target: playerRight); + } + } +} From 6c383fac96e36841e4aee8f8de0207573ef5ac52 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 9 Nov 2025 18:10:11 +0100 Subject: [PATCH 06/19] Fixes Magician for spread moves (#8170) --- data/battle_scripts_1.s | 3 +- src/battle_message.c | 2 +- src/battle_script_commands.c | 81 ++++++++++++++++++++++++---------- test/battle/ability/magician.c | 28 ++++++++++++ 4 files changed, 88 insertions(+), 26 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index cc00828984..a353b44ba8 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7111,7 +7111,7 @@ BattleScript_RecoilEnd:: return BattleScript_ItemSteal:: - playanimation BS_TARGET, B_ANIM_ITEM_STEAL + playanimation BS_EFFECT_BATTLER, B_ANIM_ITEM_STEAL printstring STRINGID_PKMNSTOLEITEM waitmessage B_WAIT_TIME_LONG return @@ -9122,6 +9122,7 @@ BattleScript_Pickpocket:: call BattleScript_AbilityPopUp jumpifability BS_ATTACKER, ABILITY_STICKY_HOLD, BattleScript_PickpocketPrevented swapattackerwithtarget + copybyte gEffectBattler, gBattlerTarget call BattleScript_ItemSteal swapattackerwithtarget activateitemeffects diff --git a/src/battle_message.c b/src/battle_message.c index fc33a06414..aeb32f259f 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -303,7 +303,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNTRYINGTOTAKEFOE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is hoping to take its attacker down with it!"), [STRINGID_PKMNTOOKFOE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} took its attacker down with it!"), [STRINGID_PKMNREDUCEDPP] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s PP was reduced!"), - [STRINGID_PKMNSTOLEITEM] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} stole {B_DEF_NAME_WITH_PREFIX2}'s {B_LAST_ITEM}!"), + [STRINGID_PKMNSTOLEITEM] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} stole {B_EFF_NAME_WITH_PREFIX2}'s {B_LAST_ITEM}!"), [STRINGID_TARGETCANTESCAPENOW] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} can no longer escape!"), [STRINGID_PKMNFELLINTONIGHTMARE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} began having a nightmare!"), [STRINGID_PKMNLOCKEDINNIGHTMARE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is locked in a nightmare!"), diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ca7f490f11..face6eeb08 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2831,11 +2831,11 @@ static void CheckSetUnburden(u8 battler) gDisableStructs[battler].unburdenActive = TRUE; } -// battlerStealer steals the item of battlerItem -void StealTargetItem(u8 battlerStealer, u8 battlerItem) +// battlerStealer steals the item of itemBattler +void StealTargetItem(u8 battlerStealer, u8 itemBattler) { - gLastUsedItem = gBattleMons[battlerItem].item; - gBattleMons[battlerItem].item = ITEM_NONE; + gLastUsedItem = gBattleMons[itemBattler].item; + gBattleMons[itemBattler].item = ITEM_NONE; if (GetGenConfig(GEN_STEAL_WILD_ITEMS) >= GEN_9 && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)) @@ -2854,16 +2854,16 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem) MarkBattlerForControllerExec(battlerStealer); } - RecordItemEffectBattle(battlerItem, ITEM_NONE); - CheckSetUnburden(battlerItem); + RecordItemEffectBattle(itemBattler, ITEM_NONE); + CheckSetUnburden(itemBattler); - BtlController_EmitSetMonData(battlerItem, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[battlerItem].item); // remove target item - MarkBattlerForControllerExec(battlerItem); + BtlController_EmitSetMonData(itemBattler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[itemBattler].item), &gBattleMons[itemBattler].item); // remove target item + MarkBattlerForControllerExec(itemBattler); - if (GetBattlerAbility(gBattlerTarget) != ABILITY_GORILLA_TACTICS) - gBattleStruct->choicedMove[gBattlerTarget] = MOVE_NONE; + if (GetBattlerAbility(itemBattler) != ABILITY_GORILLA_TACTICS) + gBattleStruct->choicedMove[itemBattler] = MOVE_NONE; - TrySaveExchangedItem(battlerItem, gLastUsedItem); + TrySaveExchangedItem(itemBattler, gLastUsedItem); } static inline bool32 TrySetReflect(u32 battler) @@ -5597,22 +5597,54 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move switch (abilityAtk) { case ABILITY_MAGICIAN: - if (move != MOVE_FLING && move != MOVE_NATURAL_GIFT + if (GetMoveEffect(move) != EFFECT_FLING + && GetMoveEffect(move) != EFFECT_NATURAL_GIFT && gBattleMons[battlerAtk].item == ITEM_NONE - && gBattleMons[battlerDef].item != ITEM_NONE && IsBattlerAlive(battlerAtk) - && IsBattlerTurnDamaged(battlerDef) - && CanStealItem(battlerAtk, battlerDef, gBattleMons[battlerDef].item) - && !gSpecialStatuses[battlerAtk].gemBoost // In base game, gems are consumed after magician would activate. - && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(battlerDef)] & (1u << gBattlerPartyIndexes[battlerDef])) - && !DoesSubstituteBlockMove(battlerAtk, battlerDef, move) - && (GetBattlerAbility(battlerDef) != ABILITY_STICKY_HOLD || !IsBattlerAlive(battlerDef))) + && !gSpecialStatuses[battlerAtk].gemBoost) // In base game, gems are consumed after magician would activate. { - StealTargetItem(battlerAtk, battlerDef); - gBattleScripting.battler = gBattlerAbility = battlerAtk; - gEffectBattler = battlerDef; - BattleScriptCall(BattleScript_MagicianActivates); - effect = TRUE; + u32 numMagicianTargets = 0; + u32 magicianTargets = 0; + + for (u32 i = 0; i < gBattlersCount; i++) + { + if (gBattleMons[i].item != ITEM_NONE + && i != battlerAtk + && IsBattlerTurnDamaged(i) + && CanStealItem(battlerAtk, i, gBattleMons[i].item) + && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(i)] & (1u << gBattlerPartyIndexes[i])) + && !DoesSubstituteBlockMove(battlerAtk, i, move) + && (GetBattlerAbility(i) != ABILITY_STICKY_HOLD || !IsBattlerAlive(i))) + { + magicianTargets |= 1u << i; + numMagicianTargets++; + } + } + + if (numMagicianTargets == 0) + { + effect = FALSE; + break; + } + + u8 battlers[4] = {0, 1, 2, 3}; + if (numMagicianTargets > 1) + SortBattlersBySpeed(battlers, FALSE); + + for (u32 i = 0; i < gBattlersCount; i++) + { + u32 battler = battlers[i]; + + if (!(magicianTargets & 1u << battler)) + continue; + + StealTargetItem(battlerAtk, battler); + gBattlerAbility = battlerAtk; + gEffectBattler = battler; + BattleScriptCall(BattleScript_MagicianActivates); + effect = TRUE; + break; // found target to steal from + } } break; case ABILITY_MOXIE: @@ -5775,6 +5807,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later } + gEffectBattler = gBattlerTarget; BattleScriptCall(BattleScript_ItemSteal); effect = TRUE; } diff --git a/test/battle/ability/magician.c b/test/battle/ability/magician.c index 9e80120025..a54ba2df7d 100644 --- a/test/battle/ability/magician.c +++ b/test/battle/ability/magician.c @@ -25,3 +25,31 @@ SINGLE_BATTLE_TEST("Magician gets self-damage recoil after stealing Life Orb") } } +DOUBLE_BATTLE_TEST("Magician steal the item from the fastest possible target") +{ + u32 playerRightSpeed = 0; + u32 opponentLeftSpeed = 0; + u32 opponentRightSpeed = 0; + + PARAMETRIZE { playerRightSpeed = 4; opponentLeftSpeed = 2; opponentRightSpeed = 3; } + PARAMETRIZE { playerRightSpeed = 3; opponentLeftSpeed = 4; opponentRightSpeed = 2; } + PARAMETRIZE { playerRightSpeed = 2; opponentLeftSpeed = 3; opponentRightSpeed = 4; } + + GIVEN { + PLAYER(SPECIES_DELPHOX) { Speed(1); Ability(ABILITY_MAGICIAN); Item(ITEM_NONE); } + PLAYER(SPECIES_WOBBUFFET) { Speed(playerRightSpeed); Item(ITEM_POKE_BALL); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(opponentLeftSpeed); Item(ITEM_GREAT_BALL); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(opponentRightSpeed); Item(ITEM_ULTRA_BALL); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SURF); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_MAGICIAN); + } THEN { + if (playerRightSpeed == 4) + EXPECT(playerLeft->item == ITEM_POKE_BALL); + else if (opponentLeftSpeed == 4) + EXPECT(playerLeft->item == ITEM_GREAT_BALL); + else if (playerRightSpeed == 4) + EXPECT(playerLeft->item == ITEM_ULTRA_BALL); + } +} From 3e583f8addacf89f8e0d8c99b6bfdfe21c6ae27b Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Sun, 9 Nov 2025 18:10:44 +0100 Subject: [PATCH 07/19] Fix tera tint not applying on activation (#8135) --- data/battle_anim_scripts.s | 18 +++++++++--------- include/battle_gfx_sfx_util.h | 2 +- include/constants/battle_anim.h | 8 ++++++++ src/battle_anim_effects_3.c | 16 +++------------- src/battle_gfx_sfx_util.c | 13 ++++++++++--- 5 files changed, 31 insertions(+), 26 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 61d0d99933..4df85854dc 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -29002,7 +29002,7 @@ gBattleAnimMove_Transform:: monbg ANIM_ATTACKER playsewithpan SE_M_TELEPORT, SOUND_PAN_ATTACKER waitplaysewithpan SE_M_MINIMIZE, SOUND_PAN_ATTACKER, 48 - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, SPECIES_GFX_CHANGE_TRANSFORM waitforvisualfinish clearmonbg ANIM_ATTACKER end @@ -31513,14 +31513,14 @@ gBattleAnimGeneral_SimpleHeal:: gBattleAnimGeneral_IllusionOff:: monbg ANIM_TARGET - createvisualtask AnimTask_TransformMon, 2, 1, 0 + createvisualtask AnimTask_TransformMon, 2, SPECIES_GFX_CHANGE_ILLUSION_OFF waitforvisualfinish clearmonbg ANIM_TARGET end gBattleAnimGeneral_FormChange:: monbg ANIM_ATTACKER - createvisualtask AnimTask_TransformMon, 2, 1, 0 + createvisualtask AnimTask_TransformMon, 2, SPECIES_GFX_CHANGE_FORM_CHANGE waitforvisualfinish clearmonbg ANIM_ATTACKER end @@ -31552,7 +31552,7 @@ gBattleAnimGeneral_MegaEvolution:: createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish createvisualtask SoundTask_PlayNormalCry, 0 - createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 + createvisualtask AnimTask_HideSwapSprite, 2 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 createsprite gMegaSymbolSpriteTemplate ANIM_ATTACKER, 3, 0, 0, ANIM_ATTACKER @@ -31637,7 +31637,7 @@ gBattleAnimGeneral_TeraActivate:: createvisualtask AnimTask_SetOpponentShadowCallbacks, 2 @ Restore shadows hidden in the charge script loadspritegfx ANIM_TAG_TERA_SYMBOL loadspritegfx ANIM_TAG_SPARKLE_6 - createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 + createvisualtask AnimTask_HideSwapSprite, 2 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 createvisualtask SoundTask_PlayNormalCry, 0 @@ -31777,7 +31777,7 @@ General_PrimalReversion_Alpha: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 + createvisualtask AnimTask_HideSwapSprite, 2 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 createvisualtask SoundTask_PlayNormalCry, 0 @@ -31810,7 +31810,7 @@ General_PrimalReversion_Omega: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 + createvisualtask AnimTask_HideSwapSprite, 2 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 createvisualtask SoundTask_PlayNormalCry, 0 @@ -31850,7 +31850,7 @@ gBattleAnimGeneral_PowerConstruct:: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 + createvisualtask AnimTask_HideSwapSprite, 2 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 createvisualtask SoundTask_PlayNormalCry, 0 @@ -31920,7 +31920,7 @@ gBattleAnimGeneral_UltraBurst:: createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA createsprite gUltraBurstSymbolSpriteTemplate, ANIM_ATTACKER, 0x0, 0x0, 0x0, 0x0, 0x0 waitforvisualfinish - createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 + createvisualtask AnimTask_HideSwapSprite, 2 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 createvisualtask SoundTask_PlayNormalCry, 0 diff --git a/include/battle_gfx_sfx_util.h b/include/battle_gfx_sfx_util.h index ae71eb5b50..eb713779c2 100644 --- a/include/battle_gfx_sfx_util.h +++ b/include/battle_gfx_sfx_util.h @@ -22,7 +22,7 @@ bool8 BattleInitAllSprites(u8 *state1, u8 *battler); void ClearSpritesHealthboxAnimData(void); void CopyAllBattleSpritesInvisibilities(void); void CopyBattleSpriteInvisibility(u8 battler); -void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bool8 trackEnemyPersonality); +void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, u8 changeType); void BattleLoadSubstituteOrMonSpriteGfx(u8 battler, bool8 loadMonSprite); void LoadBattleMonGfxAndAnimate(u8 battler, bool8 loadMonSprite, u8 spriteId); void TrySetBehindSubstituteSpriteBit(u8 battler, u16 move); diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 3d514b1936..74683a70b6 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -667,6 +667,14 @@ #define ANIM_ORDER_UP_DROOPY 2 #define ANIM_ORDER_UP_STRETCHY 3 +// AnimTask_TransformMon variations +enum SpeciesGfxChange +{ + SPECIES_GFX_CHANGE_TRANSFORM, + SPECIES_GFX_CHANGE_FORM_CHANGE, + SPECIES_GFX_CHANGE_ILLUSION_OFF, +}; + // Flags given to various functions to indicate which palettes to consider. // Handled by UnpackSelectedBattlePalettes #define F_PAL_BG (1 << 0) diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index 65de36237b..e30a8afd15 100644 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -2484,11 +2484,10 @@ void AnimTask_HideSwapSprite(u8 taskId) case 0: gTasks[taskId].data[11] = gSprites[spriteId].x; // Save battler position gSprites[spriteId].x = -64; // hide it from screen to avoid the blip/glitch effect when swapping the sprite. - gTasks[taskId].data[10] = gBattleAnimArgs[0]; gTasks[taskId].data[0]++; break; case 1: - HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, gTasks[taskId].data[10], gBattleAnimArgs[1]); + HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, SPECIES_GFX_CHANGE_FORM_CHANGE); GetBgDataForTransform(&animBg, gBattleAnimAttacker); if (IsContest()) @@ -2536,14 +2535,6 @@ void AnimTask_HideSwapSprite(u8 taskId) break; case 2: gSprites[spriteId].x = gTasks[taskId].data[11]; // restores battler position - if (!IsContest()) - { - if (!IsOnPlayerSide(gBattleAnimAttacker)) - { - if (gTasks[taskId].data[10] == 0) - SetBattlerShadowSpriteCallback(gBattleAnimAttacker, gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies); - } - } DestroyAnimVisualTask(taskId); break; @@ -2596,7 +2587,6 @@ void AnimTask_TransformMon(u8 taskId) SetAnimBgAttribute(2, BG_ANIM_MOSAIC, 1); gTasks[taskId].data[10] = gBattleAnimArgs[0]; - gTasks[taskId].data[11] = gBattleAnimArgs[1]; gTasks[taskId].data[0]++; break; case 1: @@ -2611,7 +2601,7 @@ void AnimTask_TransformMon(u8 taskId) } break; case 2: - HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, gTasks[taskId].data[10], gTasks[taskId].data[11]); + HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, gTasks[taskId].data[10]); GetBgDataForTransform(&animBg, gBattleAnimAttacker); if (IsContest()) @@ -2680,7 +2670,7 @@ void AnimTask_TransformMon(u8 taskId) { if (!IsOnPlayerSide(gBattleAnimAttacker)) { - if (gTasks[taskId].data[10] == 0) + if (gTasks[taskId].data[10] == SPECIES_GFX_CHANGE_TRANSFORM) SetBattlerShadowSpriteCallback(gBattleAnimAttacker, gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies); } } diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 1beaee4cc4..a6362bb24f 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -906,7 +906,7 @@ void CopyBattleSpriteInvisibility(u8 battler) gBattleSpritesDataPtr->battlerData[battler].invisible = gSprites[gBattlerSpriteIds[battler]].invisible; } -void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bool8 trackEnemyPersonality) +void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, u8 changeType) { u32 personalityValue, position, paletteOffset, targetSpecies; bool32 isShiny; @@ -947,7 +947,7 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo targetSpecies = gBattleSpritesDataPtr->battlerData[battlerAtk].transformSpecies; } - if (trackEnemyPersonality) + if (changeType == SPECIES_GFX_CHANGE_TRANSFORM) { personalityValue = gDisableStructs[battlerAtk].transformedMonPersonality; isShiny = gDisableStructs[battlerAtk].transformedMonShininess; @@ -969,7 +969,7 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo paletteData = GetMonSpritePalFromSpeciesAndPersonality(targetSpecies, isShiny, personalityValue); LoadPalette(paletteData, paletteOffset, PLTT_SIZE_4BPP); - if (!megaEvo) + if (changeType == SPECIES_GFX_CHANGE_TRANSFORM) { BlendPalette(paletteOffset, 16, 6, RGB_WHITE); CpuCopy32(&gPlttBufferFaded[paletteOffset], &gPlttBufferUnfaded[paletteOffset], PLTT_SIZEOF(16)); @@ -986,6 +986,13 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, PLTT_SIZEOF(16)); } + // Terastallization's tint + if (changeType != SPECIES_GFX_CHANGE_ILLUSION_OFF && GetActiveGimmick(battlerAtk) == GIMMICK_TERA) + { + BlendPalette(paletteOffset, 16, 8, GetTeraTypeRGB(GetBattlerTeraType(battlerAtk))); + CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, PLTT_SIZEOF(16)); + } + gSprites[gBattlerSpriteIds[battlerAtk]].y = GetBattlerSpriteDefault_Y(battlerAtk); StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerAtk]], 0); } From 8eea132406f53e5857d1eec72181867b469bddfc Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Sun, 9 Nov 2025 18:16:19 +0100 Subject: [PATCH 08/19] Fix missing FREE_MATCH_CALL (#8171) Co-authored-by: Zimmermann Gyula --- src/battle_setup.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/battle_setup.c b/src/battle_setup.c index 1103818c05..1505f6af65 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1128,8 +1128,12 @@ bool32 GetTrainerFlagFromScriptPointer(const u8 *data) bool32 GetRematchFromScriptPointer(const u8 *data) { +#if FREE_MATCH_CALL + return FALSE; +#else TrainerBattleParameter *temp = (TrainerBattleParameter*)(data + OPCODE_OFFSET); return ShouldTryRematchBattleForTrainerId(temp->params.opponentA); +#endif } #undef OPCODE_OFFSET @@ -1793,11 +1797,13 @@ static bool8 WasSecondRematchWon(const struct RematchTrainer *table, u16 firstBa return FALSE; if (!HasTrainerBeenFought(table[tableId].trainerIds[1])) return FALSE; +#if FREE_MATCH_CALL == FALSE if (I_VS_SEEKER_CHARGING) { if (gSaveBlock1Ptr->trainerRematches[tableId] == 0) return FALSE; } +#endif return TRUE; } From 459b3cbb2f3a8dba7f21f2d781a040bf4d61cb6a Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sun, 9 Nov 2025 22:21:55 +0100 Subject: [PATCH 09/19] Adjust label workflow to only run if PR is approved (#8183) Co-authored-by: Hedara --- .github/workflows/labels.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index 325e72950d..3cc4ee57a7 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -3,10 +3,12 @@ name: Labels on: pull_request: types: [opened, synchronize, labeled, unlabeled] + pull_request_review: + types: [submitted] jobs: label: - if: github.actor != 'allcontributors[bot]' + if: ${{ github.actor != 'allcontributors[bot]' && github.event.review.state == 'approved' }} runs-on: ubuntu-latest steps: - name: check labels From 65f241995cdd9e61a041144d5c4da1174acfd0fc Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Mon, 10 Nov 2025 10:39:06 +0100 Subject: [PATCH 10/19] Fix scroll prompt sometimes being off-screen with automatic line breaks (#8182) Co-authored-by: Hedara --- src/line_break.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/line_break.c b/src/line_break.c index a4dd6475af..bb601a0d76 100644 --- a/src/line_break.c +++ b/src/line_break.c @@ -176,7 +176,6 @@ void BreakSubStringNaive(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enum Free(allWords); } -#undef SCROLL_PROMPT_WIDTH void BreakSubStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enum ToggleScrollPrompt toggleScrollPrompt) { @@ -246,6 +245,9 @@ void BreakSubStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, for (u32 i = 1; i < numWords; i++) totalWidth += allWords[i].width + spaceWidth; + if (toggleScrollPrompt == SHOW_SCROLL_PROMPT) + totalWidth += SCROLL_PROMPT_WIDTH; + // If it doesn't fit on 1 line, do fancy line break calculation // NOTE: Currently the line break calculation isn't fancy if (totalWidth > maxWidth) @@ -256,6 +258,8 @@ void BreakSubStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, bool32 shouldTryAgain; for (currWordIndex = 0; currWordIndex < numWords; currWordIndex++) { + if (toggleScrollPrompt == SHOW_SCROLL_PROMPT && currWordIndex + 1 == numWords) + currLineWidth += SCROLL_PROMPT_WIDTH; if (currLineWidth + allWords[currWordIndex].length > maxWidth) { totalLines++; @@ -266,6 +270,10 @@ void BreakSubStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, currLineWidth += allWords[currWordIndex].width + spaceWidth; } } + + if (currLineWidth > maxWidth) + totalLines++; + // LINE LAYOUT STARTS HERE struct StringLine *stringLines; do @@ -424,3 +432,4 @@ bool32 StringHasManualBreaks(u8 *src) } return FALSE; } +#undef SCROLL_PROMPT_WIDTH From 49b45ec6c397a31a0fa5577a499a33f08b3a6f2e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 10 Nov 2025 06:39:47 -0300 Subject: [PATCH 11/19] Fix gcc11 again (#8188) --- src/vs_seeker.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs_seeker.c b/src/vs_seeker.c index 1fcf5fdfcc..d9e4497421 100644 --- a/src/vs_seeker.c +++ b/src/vs_seeker.c @@ -725,6 +725,7 @@ static u16 GetTrainerFlagFromScript(const u8 *script) trainerFlag |= script[1] << 8; break; case SCR_OP_CALLNATIVE: + { u32 callnativeFunc = (((((script[4] << 8) + script[3]) << 8) + script[2]) << 8) + script[1]; if (callnativeFunc == ((u32)NativeVsSeekerRematchId | 0xA000000)) // | 0xA000000 corresponds to the request_effects=1 version of the function { @@ -737,6 +738,7 @@ static u16 GetTrainerFlagFromScript(const u8 *script) trainerFlag = TRAINER_NONE; } break; + } default: trainerFlag = TRAINER_NONE; break; From 59d131f599586d0b911a37cab5e4ab04fdc3c4c5 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 10 Nov 2025 10:40:47 +0100 Subject: [PATCH 12/19] Fixes wrongly assigned count for Semi Invulnerable state (#8175) --- include/constants/battle.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index d2913d6fc6..8527ec800f 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -169,7 +169,7 @@ enum VolatileFlags F(VOLATILE_FORESIGHT, foresight, (u32, 1)) \ F(VOLATILE_DRAGON_CHEER, dragonCheer, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_FOCUS_ENERGY, focusEnergy, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_SEMI_INVULNERABLE, semiInvulnerable, (u32, 5)) \ + F(VOLATILE_SEMI_INVULNERABLE, semiInvulnerable, (u32, SEMI_INVULNERABLE_COUNT - 1)) \ F(VOLATILE_ELECTRIFIED, electrified, (u32, 1)) \ F(VOLATILE_MUD_SPORT, mudSport, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_WATER_SPORT, waterSport, (u32, 1), V_BATON_PASSABLE) \ @@ -224,6 +224,7 @@ enum SemiInvulnerableState STATE_PHANTOM_FORCE, STATE_SKY_DROP, STATE_COMMANDER, + SEMI_INVULNERABLE_COUNT, }; enum SemiInvulnerableExclusion From 625f67be336130b10ad87894eedf1eec6bbdd4e4 Mon Sep 17 00:00:00 2001 From: Frank DeBlasio <35279583+fdeblasio@users.noreply.github.com> Date: Mon, 10 Nov 2025 09:56:40 -0500 Subject: [PATCH 13/19] Fixed Uproar's description and spacing (#8187) --- src/data/moves_info.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/data/moves_info.h b/src/data/moves_info.h index d521622efb..162a408528 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -6706,12 +6706,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Uproar"), .description = COMPOUND_STRING( - #if B_UPROAR_TURNS >= GEN_5 - "Causes an uproar for 2 to 5\n" - #else - "Causes an uproar for 3\n" - #endif - "turns and prevents sleep."), + #if B_UPROAR_TURNS >= GEN_5 + "Causes an uproar for 3\n" + #else + "Causes an uproar for 2 to 5\n" + #endif + "turns and prevents sleep."), .effect = EFFECT_UPROAR, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 90 : 50, .type = TYPE_NORMAL, From ffc2c04ea6ef65a0c5cf89dae37568053539fc4c Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 10 Nov 2025 11:58:42 -0300 Subject: [PATCH 14/19] Added Soundproof and Bulletproof tests (#8189) --- test/battle/ability/bulletproof.c | 18 +++++++++++- test/battle/ability/soundproof.c | 18 +++++++++++- test/battle/item_effect/poke_flute.c | 43 ++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 test/battle/item_effect/poke_flute.c diff --git a/test/battle/ability/bulletproof.c b/test/battle/ability/bulletproof.c index 733eb63a11..37d59b468e 100644 --- a/test/battle/ability/bulletproof.c +++ b/test/battle/ability/bulletproof.c @@ -1,4 +1,20 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Bulletproof makes ballistic moves fail against the ability user"); +SINGLE_BATTLE_TEST("Bulletproof makes ballistic moves fail against the ability user") +{ + GIVEN { + ASSUME(IsBallisticMove(MOVE_ELECTRO_BALL)); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CHESPIN) { Ability(ABILITY_BULLETPROOF); } + } WHEN { + TURN { MOVE(player, MOVE_ELECTRO_BALL); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_BULLETPROOF); + MESSAGE("The opposing Chespin's Bulletproof blocks Electro Ball!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRO_BALL, player); + HP_BAR(opponent); + } + } +} diff --git a/test/battle/ability/soundproof.c b/test/battle/ability/soundproof.c index a7135942d1..6af6231cc2 100644 --- a/test/battle/ability/soundproof.c +++ b/test/battle/ability/soundproof.c @@ -1,4 +1,20 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Soundproof (Ability) test titles") +SINGLE_BATTLE_TEST("Soundproof makes sound moves fail against the ability user") +{ + GIVEN { + ASSUME(IsSoundMove(MOVE_BOOMBURST)); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXPLOUD) { Ability(ABILITY_SOUNDPROOF); } + } WHEN { + TURN { MOVE(player, MOVE_BOOMBURST); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_SOUNDPROOF); + MESSAGE("The opposing Exploud's Soundproof blocks Boomburst!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BOOMBURST, player); + HP_BAR(opponent); + } + } +} diff --git a/test/battle/item_effect/poke_flute.c b/test/battle/item_effect/poke_flute.c new file mode 100644 index 0000000000..c9aebed5d3 --- /dev/null +++ b/test/battle/item_effect/poke_flute.c @@ -0,0 +1,43 @@ +#include "global.h" +#include "test/battle.h" +#include "constants/item_effects.h" + +DOUBLE_BATTLE_TEST("Poke Flute heals all battlers from being asleep") +{ + GIVEN { + ASSUME(gItemsInfo[ITEM_POKE_FLUTE].battleUsage == EFFECT_ITEM_USE_POKE_FLUTE); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); } + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); } + } WHEN { + TURN { USE_ITEM(playerLeft, ITEM_POKE_FLUTE, partyIndex: 0); } + } SCENE { + MESSAGE("The Pokémon hearing the flute awoke!"); + } THEN { + EXPECT_EQ(playerLeft->status1, STATUS1_NONE); + EXPECT_EQ(playerRight->status1, STATUS1_NONE); + EXPECT_EQ(opponentLeft->status1, STATUS1_NONE); + EXPECT_EQ(opponentRight->status1, STATUS1_NONE); + } +} + +DOUBLE_BATTLE_TEST("Poke Flute does not heal battlers with Soundproof from being asleep") +{ + GIVEN { + ASSUME(gItemsInfo[ITEM_POKE_FLUTE].battleUsage == EFFECT_ITEM_USE_POKE_FLUTE); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); } + PLAYER(SPECIES_EXPLOUD) { Ability(ABILITY_SOUNDPROOF); Status1(STATUS1_SLEEP); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); } + OPPONENT(SPECIES_EXPLOUD) { Ability(ABILITY_SOUNDPROOF); Status1(STATUS1_SLEEP); } + } WHEN { + TURN { USE_ITEM(playerLeft, ITEM_POKE_FLUTE, partyIndex: 0); } + } SCENE { + MESSAGE("The Pokémon hearing the flute awoke!"); + } THEN { + EXPECT_EQ(playerLeft->status1, STATUS1_NONE); + EXPECT_NE(playerRight->status1, STATUS1_NONE); + EXPECT_EQ(opponentLeft->status1, STATUS1_NONE); + EXPECT_NE(opponentRight->status1, STATUS1_NONE); + } +} From ecafd762e1cc0d56e72997280deea6ad8f539dd4 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:59:44 +0100 Subject: [PATCH 15/19] Add include/constants/script_commands.h to gitignore (#8169) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2d699f8e98..686677dac2 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ prefabs.json /pokeemerald-*.png src/data/map_group_count.h include/constants/heal_locations.h +include/constants/script_commands.h tools/trainerproc/trainerproc src/data/battle_partners.h src/data/trainers.h From 29fb4f292ad3055f8ca108c406d5f841145bc242 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Mon, 10 Nov 2025 17:26:08 +0100 Subject: [PATCH 16/19] Fixed decompression error reporter OOB window creation (#8199) Co-authored-by: Hedara --- src/decompress_error_handler.c | 37 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/decompress_error_handler.c b/src/decompress_error_handler.c index 74e28e3ca1..ff332618ff 100644 --- a/src/decompress_error_handler.c +++ b/src/decompress_error_handler.c @@ -47,14 +47,14 @@ static const struct BgTemplate sBgTemplates[3] = }, }; -static void DecompressErrorScreenTextPrint(const u8 *text, u8 x, u8 y) +static void DecompressErrorScreenTextPrint(u32 window, const u8 *text, u8 x, u8 y) { u8 color[3]; color[0] = TEXT_COLOR_TRANSPARENT; color[1] = TEXT_DYNAMIC_COLOR_6; color[2] = TEXT_COLOR_LIGHT_GRAY; - AddTextPrinterParameterized4(0, FONT_NORMAL, x * 8, y * 8 + 1, 0, 0, color, 0, text); + AddTextPrinterParameterized4(window, FONT_NORMAL, x * 8, y * 8 + 1, 0, 0, color, 0, text); } static void GetHexStringFromU32(u8 *str, u32 value) @@ -121,20 +121,19 @@ static void GetHexStringFromU32(u8 *str, u32 value) } } +static const struct WindowTemplate sTextWin = +{ + .bg = 0, + .tilemapLeft = 3, + .tilemapTop = 2, + .width = 24, + .height = 16, + .paletteNum = 15, + .baseBlock = 1, +}; + void DecompressionError_CB2(void) { - static const struct WindowTemplate textWin[] = - { - { - .bg = 0, - .tilemapLeft = 3, - .tilemapTop = 2, - .width = 24, - .height = 16, - .paletteNum = 15, - .baseBlock = 1, - } - }; if (sErrorAddress == 0) return; @@ -159,20 +158,20 @@ void DecompressionError_CB2(void) ResetPaletteFade(); LoadPalette(gTextWindowFrame1_Pal, 0xE0, 0x20); LoadPalette(gStandardMenuPalette, 0xF0, 0x20); - InitWindows(textWin); - DrawStdFrameWithCustomTileAndPalette(0, TRUE, 0x214, 0xE); + u32 window = AddWindow(&sTextWin); + DrawStdFrameWithCustomTileAndPalette(window, TRUE, 0x214, 0xE); static const u8 romCheckFailMessage[] =_( "{COLOR RED}ERROR! {COLOR DARK_GRAY}Decompression Failed!\n" "\n" "Address:\n" "Error:\n"); - DecompressErrorScreenTextPrint(romCheckFailMessage, 1, 0); + DecompressErrorScreenTextPrint(window, romCheckFailMessage, 1, 0); u8 addressStr[11]; u8 errorStr[11]; GetHexStringFromU32(addressStr, sErrorAddress); GetHexStringFromU32(errorStr, sCompressionError); - DecompressErrorScreenTextPrint(addressStr, 7, 4); - DecompressErrorScreenTextPrint(errorStr, 7, 6); + DecompressErrorScreenTextPrint(window, addressStr, 7, 4); + DecompressErrorScreenTextPrint(window, errorStr, 7, 6); TransferPlttBuffer(); *(u16*)PLTT = RGB(17, 18, 31); ShowBg(0); From d31e59d96e1f1f076547a033b164dff78482c1b7 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 19:02:16 +0100 Subject: [PATCH 17/19] add fdeblasio as a contributor for code (#8200) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ CREDITS.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 0ae8f41116..52810517f1 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -459,6 +459,15 @@ "contributions": [ "code" ] + }, + { + "login": "fdeblasio", + "name": "Frank DeBlasio", + "avatar_url": "https://avatars.githubusercontent.com/u/35279583?v=4", + "profile": "https://github.com/fdeblasio", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index 64a31a4077..31f2302313 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -76,6 +76,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Marky
Marky

💻 MandL27
MandL27

💻 cawtds
cawtds

💻 + Frank DeBlasio
Frank DeBlasio

💻 From 649798449e2706339ae10d262d8898e09972a615 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Mon, 10 Nov 2025 20:01:35 +0000 Subject: [PATCH 18/19] Powder Move blocking cleanup (#8194) --- data/battle_scripts_1.s | 3 ++- include/battle_ai_util.h | 1 - include/battle_util.h | 1 + include/config/battle.h | 1 + include/constants/generational_changes.h | 1 + include/generational_changes.h | 1 + src/battle_ai_main.c | 4 +-- src/battle_ai_util.c | 10 -------- src/battle_script_commands.c | 32 ++++++------------------ src/battle_util.c | 18 +++++++++---- test/battle/ability/overcoat.c | 2 +- 11 files changed, 30 insertions(+), 44 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a353b44ba8..26ee741f71 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6834,10 +6834,11 @@ BattleScript_PowderMoveNoEffect:: pause B_WAIT_TIME_SHORT jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_PowderMoveNoEffectPrint jumpifability BS_TARGET, ABILITY_OVERCOAT, BattleScript_PowderMoveNoEffectOvercoat + setlastuseditem BS_TARGET printstring STRINGID_SAFETYGOGGLESPROTECTED goto BattleScript_PowderMoveNoEffectWaitMsg BattleScript_PowderMoveNoEffectOvercoat: - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpTarget BattleScript_PowderMoveNoEffectPrint: printstring STRINGID_ITDOESNTAFFECT BattleScript_PowderMoveNoEffectWaitMsg: diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 1964e45d53..46e1e2d7b7 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -151,7 +151,6 @@ u32 CountPositiveStatStages(u32 battlerId); u32 CountNegativeStatStages(u32 battlerId); // move checks -bool32 IsAffectedByPowder(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory category); enum MoveComparisonResult AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, enum AIConsiderGimmick considerGimmickAtk, enum AIConsiderGimmick considerGimmickDef); diff --git a/include/battle_util.h b/include/battle_util.h index 7bb8bc7292..fc88ee02c6 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -416,5 +416,6 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander); bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move); bool32 HasPartnerTrainer(u32 battler); +bool32 IsAffectedByPowderMove(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/config/battle.h b/include/config/battle.h index 2b9e9fdecc..67008ba027 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -166,6 +166,7 @@ #define B_BATTLE_BOND GEN_LATEST // In Gen9+, Battle Bond increases Atk, SpAtk and Speed by one stage, once per battle #define B_ATE_MULTIPLIER GEN_LATEST // In Gen7+, -ate abilities (Aerilate, Galvanize, Normalize, Pixilate, Refrigerate) multiply damage by 1.2. Otherwise, it's 1.3, except Normalize which has no multiplier. #define B_DEFIANT_STICKY_WEB GEN_LATEST // In Gen9+, Defiant activates on Sticky Web regardless of who set it up. In Gen8, Defiant does not activate on Sticky Web set up by an ally after Court Change swaps its side. +#define B_POWDER_OVERCOAT GEN_LATEST // In Gen6+, Overcoat blocks powder and spore moves from affecting the user. // 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. diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 7be7998d9e..88584e9978 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -42,6 +42,7 @@ enum GenConfigTag GEN_CONFIG_DESTINY_BOND_FAIL, GEN_CONFIG_POWDER_RAIN, GEN_CONFIG_POWDER_GRASS, + GEN_CONFIG_POWDER_OVERCOAT, GEN_CONFIG_OBLIVIOUS_TAUNT, GEN_CONFIG_TOXIC_NEVER_MISS, GEN_CONFIG_PARALYZE_ELECTRIC, diff --git a/include/generational_changes.h b/include/generational_changes.h index 9b6b385c7e..e8b701d096 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -45,6 +45,7 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_CONFIG_DESTINY_BOND_FAIL] = B_DESTINY_BOND_FAIL, [GEN_CONFIG_POWDER_RAIN] = B_POWDER_RAIN, [GEN_CONFIG_POWDER_GRASS] = B_POWDER_GRASS, + [GEN_CONFIG_POWDER_OVERCOAT] = B_POWDER_OVERCOAT, [GEN_CONFIG_OBLIVIOUS_TAUNT] = B_OBLIVIOUS_TAUNT, [GEN_CONFIG_TOXIC_NEVER_MISS] = B_TOXIC_NEVER_MISS, [GEN_CONFIG_PARALYZE_ELECTRIC] = B_PARALYZE_ELECTRIC, diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 0c8c0bb1cd..23c008fdc3 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1089,7 +1089,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); - if (IsPowderMove(move) && !IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) + if (IsPowderMove(move) && !IsAffectedByPowderMove(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) RETURN_SCORE_MINUS(10); if (!BreaksThroughSemiInvulnerablity(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) @@ -4768,7 +4768,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (hasPartner && GetMoveTarget(move) == MOVE_TARGET_USER && !IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) - && (!IsPowderMove(move) || IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef]))) + && (!IsPowderMove(move) || IsAffectedByPowderMove(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef]))) // Rage Powder doesn't affect powder immunities { u32 predictedMoveOnPartner = gLastMoves[BATTLE_PARTNER(battlerAtk)]; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 8bed0234ee..fe97577ac7 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -530,16 +530,6 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) return FALSE; } -// move checks -bool32 IsAffectedByPowder(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) -{ - if (ability == ABILITY_OVERCOAT - || (GetGenConfig(GEN_CONFIG_POWDER_GRASS) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) - || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES) - return FALSE; - return TRUE; -} - // This function checks if all physical/special moves are either unusable or unreasonable to use. // Consider a pokemon boosting their attack against a ghost pokemon having only normal-type physical attacks. bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory category) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index face6eeb08..a98e023ff6 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1040,31 +1040,15 @@ u32 NumFaintedBattlersByAttacker(u32 battlerAtk) return numMonsFainted; } -bool32 IsMovePowderBlocked(u32 battlerAtk, u32 battlerDef, u32 move) +bool32 IsPowderMoveBlocked(u32 battlerAtk, u32 battlerDef, u32 move) { - bool32 effect = FALSE; + if (!IsPowderMove(move) + || battlerAtk == battlerDef + || IsAffectedByPowderMove(battlerDef, GetBattlerAbility(battlerDef), GetBattlerHoldEffect(battlerDef, TRUE))) + return FALSE; - if (IsPowderMove(move) && (battlerAtk != battlerDef)) - { - if (GetGenConfig(GEN_CONFIG_POWDER_GRASS) >= GEN_6 - && (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || GetBattlerAbility(battlerDef) == ABILITY_OVERCOAT)) - { - gBattlerAbility = battlerDef; - RecordAbilityBattle(gBattlerTarget, ABILITY_OVERCOAT); - effect = TRUE; - } - else if (GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_SAFETY_GOGGLES) - { - RecordItemEffectBattle(battlerDef, HOLD_EFFECT_SAFETY_GOGGLES); - gLastUsedItem = gBattleMons[battlerDef].item; - effect = TRUE; - } - - if (effect) - gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; - } - - return effect; + gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; + return TRUE; } bool32 EmergencyExitCanBeTriggered(u32 battler) @@ -1151,7 +1135,7 @@ static void Cmd_attackcanceler(void) return; } - if (IsMovePowderBlocked(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + if (IsPowderMoveBlocked(gBattlerAttacker, gBattlerTarget, gCurrentMove)) return; if (!gBattleMons[gBattlerAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE diff --git a/src/battle_util.c b/src/battle_util.c index f6a61ffde4..a5039231e4 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -310,7 +310,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) if (effect == EFFECT_PURSUIT && IsPursuitTargetSet()) return FALSE; - if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE))) + if (gSideTimers[defSide].followmePowder && !IsAffectedByPowderMove(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE))) return FALSE; return TRUE; @@ -4689,9 +4689,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_EFFECT_SPORE: { u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); - if ((GetGenConfig(GEN_CONFIG_POWDER_GRASS) < GEN_6 || !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GRASS)) - && abilityAtk != ABILITY_OVERCOAT - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES) + enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + if (IsAffectedByPowderMove(gBattlerAttacker, abilityAtk, holdEffectAtk)) { u32 poison, paralysis, sleep; @@ -4718,7 +4717,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && CanBeSlept(gBattlerTarget, gBattlerAttacker, abilityAtk, NOT_BLOCKED_BY_SLEEP_CLAUSE) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, holdEffectAtk, move)) { if (IsSleepClauseEnabled()) gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE; @@ -11965,3 +11964,12 @@ static bool32 IsOpposingSideEmpty(u32 battler) return FALSE; return TRUE; } + +bool32 IsAffectedByPowderMove(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +{ + if ((GetGenConfig(GEN_CONFIG_POWDER_OVERCOAT) >= GEN_6 && ability == ABILITY_OVERCOAT) + || (GetGenConfig(GEN_CONFIG_POWDER_GRASS) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) + || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES) + return FALSE; + return TRUE; +} diff --git a/test/battle/ability/overcoat.c b/test/battle/ability/overcoat.c index 6d7b5f2a8d..cfdbad7de3 100644 --- a/test/battle/ability/overcoat.c +++ b/test/battle/ability/overcoat.c @@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Overcoat blocks powder and spore moves (Gen6+)") PARAMETRIZE { gen = GEN_5; } PARAMETRIZE { gen = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, gen); + WITH_CONFIG(GEN_CONFIG_POWDER_OVERCOAT, gen); ASSUME(IsPowderMove(MOVE_STUN_SPORE)); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_PINECO) { Ability(ABILITY_OVERCOAT); } From 927101a5fc562175a79e76c213565251b803d9ec Mon Sep 17 00:00:00 2001 From: Maxime Grouazel <116717026+MaximeGr00@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:10:53 +0100 Subject: [PATCH 19/19] Added check for parental bond killing through sturdy (#8206) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_ai_util.c | 2 +- test/battle/ai/ai_trytofaint.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index fe97577ac7..db7ab937b1 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1433,7 +1433,7 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 aiMoveConsidered, u32 pla bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move) { enum BattleMoveEffects effect = GetMoveEffect(move); - if (!AI_BattlerAtMaxHp(battlerTarget) || effect == EFFECT_MULTI_HIT) + if (!AI_BattlerAtMaxHp(battlerTarget) || effect == EFFECT_MULTI_HIT || gAiLogicData->abilities[battler] == ABILITY_PARENTAL_BOND) return FALSE; if (GetMoveStrikeCount(move) > 1 && !(effect == EFFECT_DRAGON_DARTS && !HasTwoOpponents(battler))) return FALSE; diff --git a/test/battle/ai/ai_trytofaint.c b/test/battle/ai/ai_trytofaint.c index a1a23efdec..50ab376503 100644 --- a/test/battle/ai/ai_trytofaint.c +++ b/test/battle/ai/ai_trytofaint.c @@ -59,3 +59,17 @@ AI_SINGLE_BATTLE_TEST("AI sees Loaded Dice damage increase from multi hit moves" MESSAGE("Wobbuffet fainted!"); } } + +AI_SINGLE_BATTLE_TEST("AI sees Parental Bond killing through sturdy") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY); + PLAYER(SPECIES_MAGNEZONE){Level(64); Ability(ABILITY_STURDY); Moves(MOVE_TACKLE, MOVE_LIGHT_SCREEN); } + OPPONENT(SPECIES_KANGASKHAN_MEGA){Level(64); Moves(MOVE_DRAIN_PUNCH, MOVE_TAUNT); } + } WHEN { + TURN{ MOVE(player, MOVE_TACKLE); + EXPECT_MOVE(opponent, MOVE_DRAIN_PUNCH); // AI should see drain punch as a kill due to multi hit, outscoring taunt + } + } +} +