diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a1ccf6f2b1..15ebaf7ece 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -440,6 +440,7 @@ gBattleScriptsForMoveEffects:: BattleScript_EffectSaltCure: call BattleScript_EffectHit_Ret + tryfaintmon BS_TARGET jumpiffainted BS_TARGET, TRUE, BattleScript_EffectSaltCure_End applysaltcure BS_TARGET printstring STRINGID_TARGETISBEINGSALTCURED diff --git a/include/battle_util.h b/include/battle_util.h index 62e7d1a2a3..275a27303b 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -248,6 +248,7 @@ bool32 ChangeTypeBasedOnTerrain(u32 battler); void RemoveConfusionStatus(u32 battler); u8 GetBattlerGender(u32 battler); bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2); +bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2); u32 CalcSecondaryEffectChance(u32 battler, u8 secondaryEffectChance); u8 GetBattlerType(u32 battler, u8 typeIndex); diff --git a/include/config/item.h b/include/config/item.h index 08e5e4d3bb..55de3fdb60 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -19,6 +19,8 @@ #define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1. // Exp. Share config +// To use this feature, replace the 0 with the flag ID you're assigning it to. +// Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature. #define I_EXP_SHARE_FLAG 0 // If this flag is set, every Pokémon in the party will gain experience, regardless if they participated in the battle or not. #define I_EXP_SHARE_ITEM GEN_5 // In Gen6+, the Exp. Share was changed from a held item to a Key item that toggles the effect described above. diff --git a/src/battle_util.c b/src/battle_util.c index 5e4598329a..5de2523c29 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8907,9 +8907,9 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_RIVALRY: - if (AreBattlersOfOppositeGender(battlerAtk, battlerDef)) + if (AreBattlersOfSameGender(battlerAtk, battlerDef)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.25)); - else + else if (AreBattlersOfOppositeGender(battlerAtk, battlerDef)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.75)); break; case ABILITY_ANALYTIC: @@ -11176,6 +11176,14 @@ bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2) return (gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS && gender1 != gender2); } +bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2) +{ + u8 gender1 = GetBattlerGender(battler1); + u8 gender2 = GetBattlerGender(battler2); + + return (gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS && gender1 == gender2); +} + u32 CalcSecondaryEffectChance(u32 battler, u8 secondaryEffectChance) { if (GetBattlerAbility(battler) == ABILITY_SERENE_GRACE) @@ -11191,7 +11199,7 @@ bool32 IsAlly(u32 battlerAtk, u32 battlerDef) bool32 IsGen6ExpShareEnabled(void) { -#if I_EXP_SHARE_ITEM < GEN_6 +#if I_EXP_SHARE_FLAG <= TEMP_FLAGS_END return FALSE; #else return FlagGet(I_EXP_SHARE_FLAG); diff --git a/src/data/pokemon/species_info.h b/src/data/pokemon/species_info.h index 76904ecff0..7e77540565 100644 --- a/src/data/pokemon/species_info.h +++ b/src/data/pokemon/species_info.h @@ -16972,9 +16972,9 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_FAST, #if P_UPDATED_EGG_GROUPS >= GEN_8 - .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MONSTER}, - #else .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MINERAL}, + #else + .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MONSTER}, #endif .abilities = {ABILITY_OWN_TEMPO, ABILITY_ICE_BODY, ABILITY_STURDY}, .bodyColor = BODY_COLOR_BLUE, @@ -16998,9 +16998,9 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_FAST, #if P_UPDATED_EGG_GROUPS >= GEN_8 - .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MONSTER}, - #else .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MINERAL}, + #else + .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MONSTER}, #endif .abilities = {ABILITY_OWN_TEMPO, ABILITY_ICE_BODY, ABILITY_STURDY}, .bodyColor = BODY_COLOR_BLUE, @@ -20921,7 +20921,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_FAST, .eggGroups = { EGG_GROUP_BUG, EGG_GROUP_BUG}, - .abilities = {ABILITY_SWARM, ABILITY_SHEER_FORCE, ABILITY_STEADFAST}, + .abilities = {ABILITY_SWARM, ABILITY_SHEER_FORCE, ABILITY_SHARPNESS}, .bodyColor = BODY_COLOR_BROWN, .noFlip = FALSE, }, @@ -21010,7 +21010,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = 35, .growthRate = GROWTH_MEDIUM_SLOW, .eggGroups = { EGG_GROUP_FIELD, EGG_GROUP_FIELD}, - .abilities = {ABILITY_PRESSURE, ABILITY_NONE, ABILITY_POISON_TOUCH}, + .abilities = {ABILITY_PRESSURE, ABILITY_UNBURDEN, ABILITY_POISON_TOUCH}, .bodyColor = BODY_COLOR_BLUE, .noFlip = FALSE, }, @@ -23130,7 +23130,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_INTIMIDATE, ABILITY_FLASH_FIRE, ABILITY_ROCK_HEAD}, .bodyColor = BODY_COLOR_BROWN, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_ARCANINE_HISUIAN] = @@ -23153,7 +23153,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_INTIMIDATE, ABILITY_FLASH_FIRE, ABILITY_ROCK_HEAD}, .bodyColor = BODY_COLOR_BROWN, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_VOLTORB_HISUIAN] = @@ -23176,7 +23176,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_SOUNDPROOF, ABILITY_STATIC, ABILITY_AFTERMATH}, .bodyColor = BODY_COLOR_RED, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_ELECTRODE_HISUIAN] = @@ -23199,7 +23199,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_SOUNDPROOF, ABILITY_STATIC, ABILITY_AFTERMATH}, .bodyColor = BODY_COLOR_RED, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_TYPHLOSION_HISUIAN] = @@ -23222,7 +23222,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_BLAZE, ABILITY_NONE, ABILITY_FRISK}, .bodyColor = BODY_COLOR_YELLOW, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_QWILFISH_HISUIAN] = @@ -23237,7 +23237,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .catchRate = 45, .expYield = 88, .evYield_Attack = 1, - .itemRare = ITEM_POISON_BARB, + .itemRare = ITEM_POISON_BARB, .genderRatio = PERCENT_FEMALE(50), .eggCycles = 20, .friendship = STANDARD_FRIENDSHIP, @@ -23246,7 +23246,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_POISON_POINT, ABILITY_SWIFT_SWIM, ABILITY_INTIMIDATE}, .bodyColor = BODY_COLOR_GRAY, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_SNEASEL_HISUIAN] = @@ -23267,10 +23267,10 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = 35, .growthRate = GROWTH_MEDIUM_SLOW, .eggGroups = { EGG_GROUP_FIELD, EGG_GROUP_FIELD}, - .abilities = {ABILITY_INNER_FOCUS, ABILITY_KEEN_EYE, ABILITY_POISON_TOUCH}, + .abilities = {ABILITY_INNER_FOCUS, ABILITY_KEEN_EYE, ABILITY_PICKPOCKET}, .bodyColor = BODY_COLOR_BLACK, .noFlip = TRUE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, #if P_GEN_5_POKEMON == TRUE @@ -23294,7 +23294,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_TORRENT, ABILITY_NONE, ABILITY_SHARPNESS}, .bodyColor = BODY_COLOR_BLUE, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_LILLIGANT_HISUIAN] = @@ -23318,7 +23318,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_CHLOROPHYLL, ABILITY_HUSTLE, ABILITY_LEAF_GUARD}, .bodyColor = BODY_COLOR_GREEN, .noFlip = TRUE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_ZORUA_HISUIAN] = @@ -23341,7 +23341,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_ILLUSION, ABILITY_NONE}, .bodyColor = BODY_COLOR_GRAY, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_ZOROARK_HISUIAN] = @@ -23364,7 +23364,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_ILLUSION, ABILITY_NONE}, .bodyColor = BODY_COLOR_GRAY, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_BRAVIARY_HISUIAN] = @@ -23387,7 +23387,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_KEEN_EYE, ABILITY_SHEER_FORCE, ABILITY_TINTED_LENS}, .bodyColor = BODY_COLOR_RED, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, #endif @@ -23413,7 +23413,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_SAP_SIPPER, ABILITY_SHELL_ARMOR, ABILITY_GOOEY}, .bodyColor = BODY_COLOR_PURPLE, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_GOODRA_HISUIAN] = @@ -23436,7 +23436,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_SAP_SIPPER, ABILITY_SHELL_ARMOR, ABILITY_GOOEY}, .bodyColor = BODY_COLOR_PURPLE, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_AVALUGG_HISUIAN] = @@ -23459,7 +23459,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_STRONG_JAW, ABILITY_ICE_BODY, ABILITY_STURDY}, .bodyColor = BODY_COLOR_BLUE, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, #endif @@ -23484,7 +23484,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_OVERGROW, ABILITY_NONE, ABILITY_SCRAPPY}, .bodyColor = BODY_COLOR_BROWN, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, #endif diff --git a/test/battle/ability/rivalry.c b/test/battle/ability/rivalry.c new file mode 100644 index 0000000000..a7f4216ce0 --- /dev/null +++ b/test/battle/ability/rivalry.c @@ -0,0 +1,99 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gSpeciesInfo[SPECIES_NIDOKING].genderRatio == MON_MALE); + ASSUME(gSpeciesInfo[SPECIES_NIDOQUEEN].genderRatio == MON_FEMALE); + ASSUME(gSpeciesInfo[SPECIES_PORYGON].genderRatio == MON_GENDERLESS); +} + +SINGLE_BATTLE_TEST("Rivalry increases power by x1.25 towards Pokémon of the same gender", s16 damage) +{ + u16 species, ability; + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_RIVALRY; } + + GIVEN { + PLAYER(species) { Ability(ability); } + OPPONENT(species); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.25), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.25), results[3].damage); + } +} + +SINGLE_BATTLE_TEST("Rivalry decreases power by x0.75 towards Pokémon of different gender", s16 damage) +{ + u16 species1, species2, ability; + PARAMETRIZE { species1 = SPECIES_NIDOKING; species2 = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species1 = SPECIES_NIDOKING; species2 = SPECIES_NIDOQUEEN; ability = ABILITY_RIVALRY; } + PARAMETRIZE { species1 = SPECIES_NIDOQUEEN; species2 = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species1 = SPECIES_NIDOQUEEN; species2 = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } + + GIVEN { + PLAYER(species1) { Ability(ability); } + OPPONENT(species2); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.75), results[3].damage); + } +} + +SINGLE_BATTLE_TEST("Rivalry doesn't modify power if the attacker is genderless", s16 damage) +{ + u16 species, ability; + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_RIVALRY; } + + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_PORYGON].abilities[0] == ABILITY_TRACE); + PLAYER(SPECIES_PORYGON) { Ability(ABILITY_TRACE); } // No genderless mon naturally gets Rivalry + OPPONENT(species) { Ability(ability); }; + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT(results[0].damage == results[1].damage); + EXPECT(results[2].damage == results[3].damage); + } +} + + +SINGLE_BATTLE_TEST("Rivalry doesn't modify power if the target is genderless", s16 damage) +{ + u16 species, ability; + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_RIVALRY; } + + GIVEN { + PLAYER(species) { Ability(ability); }; + OPPONENT(SPECIES_PORYGON); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT(results[0].damage == results[1].damage); + EXPECT(results[2].damage == results[3].damage); + } +} diff --git a/test/battle/move_effect/salt_cure.c b/test/battle/move_effect/salt_cure.c index fcf240631a..c24703fa26 100644 --- a/test/battle/move_effect/salt_cure.c +++ b/test/battle/move_effect/salt_cure.c @@ -70,3 +70,17 @@ SINGLE_BATTLE_TEST("Salt Cure is removed when the afflicted Pokémon is switched } } } + +SINGLE_BATTLE_TEST("If Salt Cure faints the target no status will be applied") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_SALT_CURE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SALT_CURE, player); + NOT MESSAGE("Foe Wobbuffet is being salt cured!"); + MESSAGE("Foe Wobbuffet fainted!"); + } +}