diff --git a/include/config/battle.h b/include/config/battle.h index ad5d091617..43f8138c1e 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -117,7 +117,6 @@ #define B_SHADOW_TAG_ESCAPE GEN_LATEST // In Gen4+, if both sides have a Pokémon with Shadow Tag, all battlers can escape. Before, neither side could escape this situation. #define B_MOODY_ACC_EVASION GEN_LATEST // In Gen8, Moody CANNOT raise Accuracy and Evasion anymore. #define B_FLASH_FIRE_FROZEN GEN_LATEST // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before. -#define B_SYNCHRONIZE_NATURE GEN_LATEST // In Gen8, if a Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same Nature, as opposed to 50% previously. In Gen9, it has no out-of-battle effect. #define B_SYNCHRONIZE_TOXIC GEN_LATEST // In Gen5+, if a Pokémon with Synchronize is badly poisoned, the opponent will also become badly poisoned. Previously, the opponent would become regular poisoned. #define B_UPDATED_INTIMIDATE GEN_LATEST // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities. It also activates Rattled. #define B_OBLIVIOUS_TAUNT GEN_LATEST // In Gen6+, Pokémon with Oblivious can't be taunted. diff --git a/include/config/overworld.h b/include/config/overworld.h index e8056236a0..5002be3d28 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -10,6 +10,20 @@ // PC settings #define OW_PC_PRESS_B GEN_LATEST // In Gen4, pressing B when holding a Pokémon is equivalent to placing it. In Gen3, it gives the "You're holding a Pokémon!" error. +// Out-of-battle Ability effects +#define OW_SYNCHRONIZE_NATURE GEN_LATEST // In Gen8, if a Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same Nature, as opposed to 50% previously. Stationary Pokémon are excluded in Gen3. In Gen6, all No Eggs Discovered gift Pokémon will have the same Nature, while in Gen7 all gift Pokémon will, regardless of Egg Group - In Gen 8, no gift Pokémon are affected. In Gen9, this ability has no out-of-battle effect. +#define OW_COMPOUND_EYES GEN_LATEST // Prior to Gen9, if a Pokémon with Compound Eyes is leading the party, the wild held item rate is increased to 60%/20%. +#define OW_SUPER_LUCK GEN_LATEST // In Gen8, if a Pokémon with Super Luck is leading the party, the wild held item rate is increased to 60%/20%. +#define OW_CUTE_CHARM GEN_LATEST // Prior to Gen9, if a Pokémon with Cute Charm is leading the party, wild encounters have a 66.7% chance to be forced to be of the opposite gender. +#define OW_ILLUMINATE GEN_LATEST // Prior to Gen9, if a Pokémon with Illuminate is leading the party, the wild encounter rate is doubled. +#define OW_INFILTRATOR GEN_LATEST // In Gen8, if a Pokémon with Infiltrator is leading the party, the wild encounter rate is halved. +#define OW_HARVEST GEN_LATEST // In Gen8, if a Pokémon with Harvest is leading the party, there is a 50% chance to encounter a Grass-type Pokémon. +#define OW_LIGHTNING_ROD GEN_LATEST // In Gen8, if a Pokémon with Lightning Rod is leading the party, there is a 50% chance to encounter an Electric-type Pokémon. +#define OW_STORM_DRAIN GEN_LATEST // In Gen8, if a Pokémon with Storm Drain is leading the party, there is a 50% chance to encounter a Water-type Pokémon. +#define OW_FLASH_FIRE GEN_LATEST // In Gen8, if a Pokémon with Flash Fire is leading the party, there is a 50% chance to encounter a Fire-type Pokémon. +#define OW_MAGNET_PULL GEN_LATEST // Prior to Gen9, if a Pokémon with Magnet Pull is leading the party, there is a 50% chance to encounter a Steel-type Pokémon. +#define OW_STATIC GEN_LATEST // Prior to Gen9, if a Pokémon with Static is leading the party, there is a 50% chance to encounter an Electric-type Pokémon. + // Overworld flags // To use the following features in scripting, replace the 0s 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. diff --git a/include/wild_encounter.h b/include/wild_encounter.h index bef89d8950..13e7600684 100644 --- a/include/wild_encounter.h +++ b/include/wild_encounter.h @@ -31,6 +31,7 @@ extern bool8 gIsFishingEncounter; extern bool8 gIsSurfingEncounter; void DisableWildEncounters(bool8 disabled); +u8 PickWildMonNature(void); bool8 StandardWildEncounter(u16 currMetaTileBehavior, u16 previousMetaTileBehavior); bool8 SweetScentWildEncounter(void); bool8 DoesCurrentMapHaveFishingMons(void); diff --git a/src/pokemon.c b/src/pokemon.c index 3eef17995d..e250d7abb1 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8070,29 +8070,33 @@ static s32 GetWildMonTableIdInAlteringCave(u16 species) return 0; } +static inline bool32 CanFirstMonBoostHeldItemRarity(void) +{ + if (GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) + return FALSE; + else if ((OW_COMPOUND_EYES < GEN_9) && GetMonAbility(&gPlayerParty[0]) == ABILITY_COMPOUND_EYES) + return TRUE; + else if ((OW_SUPER_LUCK == GEN_8) && GetMonAbility(&gPlayerParty[0]) == ABILITY_SUPER_LUCK) + return TRUE; + return FALSE; +} + void SetWildMonHeldItem(void) { if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE))) { u16 rnd; u16 species; - u16 chanceNoItem = 45; - u16 chanceNotRare = 95; u16 count = (WILD_DOUBLE_BATTLE) ? 2 : 1; u16 i; - - if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG, 0) - && (GetMonAbility(&gPlayerParty[0]) == ABILITY_COMPOUND_EYES - || GetMonAbility(&gPlayerParty[0]) == ABILITY_SUPER_LUCK)) - { - chanceNoItem = 20; - chanceNotRare = 80; - } + bool32 itemHeldBoost = CanFirstMonBoostHeldItemRarity(); + u16 chanceNoItem = itemHeldBoost ? 20 : 45; + u16 chanceNotRare = itemHeldBoost ? 80 : 95; for (i = 0; i < count; i++) { if (GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, NULL) != ITEM_NONE) - continue; // prevent ovewriting previously set item + continue; // prevent overwriting previously set item rnd = Random() % 100; species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES, 0); diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index ee3cc559f8..19b187bddf 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -21,6 +21,7 @@ #include "sprite.h" #include "string_util.h" #include "tv.h" +#include "wild_encounter.h" #include "constants/items.h" #include "constants/battle_frontier.h" @@ -66,7 +67,11 @@ u8 ScriptGiveMon(u16 species, u8 level, u16 item, u32 unused1, u32 unused2, u8 u struct Pokemon mon; u16 targetSpecies; - CreateMon(&mon, species, level, USE_RANDOM_IVS, FALSE, 0, OT_ID_PLAYER_ID, 0); + if (OW_SYNCHRONIZE_NATURE >= GEN_6 && (gSpeciesInfo[species].eggGroups[0] == EGG_GROUP_UNDISCOVERED || OW_SYNCHRONIZE_NATURE == GEN_7)) + CreateMonWithNature(&mon, species, level, USE_RANDOM_IVS, PickWildMonNature()); + else + CreateMon(&mon, species, level, USE_RANDOM_IVS, FALSE, 0, OT_ID_PLAYER_ID, 0); + heldItem[0] = item; heldItem[1] = item >> 8; SetMonData(&mon, MON_DATA_HELD_ITEM, heldItem); @@ -149,7 +154,10 @@ void CreateScriptedWildMon(u16 species, u8 level, u16 item) u8 heldItem[2]; ZeroEnemyPartyMons(); - CreateMon(&gEnemyParty[0], species, level, USE_RANDOM_IVS, 0, 0, OT_ID_PLAYER_ID, 0); + if (OW_SYNCHRONIZE_NATURE > GEN_3) + CreateMonWithNature(&gEnemyParty[0], species, level, USE_RANDOM_IVS, PickWildMonNature()); + else + CreateMon(&gEnemyParty[0], species, level, USE_RANDOM_IVS, 0, 0, OT_ID_PLAYER_ID, 0); if (item) { heldItem[0] = item; @@ -164,7 +172,10 @@ void CreateScriptedDoubleWildMon(u16 species1, u8 level1, u16 item1, u16 species ZeroEnemyPartyMons(); - CreateMon(&gEnemyParty[0], species1, level1, 32, 0, 0, OT_ID_PLAYER_ID, 0); + if (OW_SYNCHRONIZE_NATURE > GEN_3) + CreateMonWithNature(&gEnemyParty[0], species1, level1, 32, PickWildMonNature()); + else + CreateMon(&gEnemyParty[0], species1, level1, 32, 0, 0, OT_ID_PLAYER_ID, 0); if (item1) { heldItem1[0] = item1; @@ -172,7 +183,10 @@ void CreateScriptedDoubleWildMon(u16 species1, u8 level1, u16 item1, u16 species SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, heldItem1); } - CreateMon(&gEnemyParty[1], species2, level2, 32, 0, 0, OT_ID_PLAYER_ID, 0); + if (OW_SYNCHRONIZE_NATURE > GEN_3) + CreateMonWithNature(&gEnemyParty[1], species2, level2, 32, PickWildMonNature()); + else + CreateMon(&gEnemyParty[1], species2, level2, 32, 0, 0, OT_ID_PLAYER_ID, 0); if (item2) { heldItem2[0] = item2; diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 8335b37e7d..e3a284c850 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -383,7 +383,7 @@ static u16 GetCurrentMapWildMonHeaderId(void) return HEADER_NONE; } -static u8 PickWildMonNature(void) +u8 PickWildMonNature(void) { u8 i; u8 j; @@ -415,15 +415,14 @@ static u8 PickWildMonNature(void) } } } -#if B_SYNCHRONIZE_NATURE < GEN_9 // check synchronize for a pokemon with the same ability - if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG) + if (OW_SYNCHRONIZE_NATURE < GEN_9 + && !GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG) && GetMonAbility(&gPlayerParty[0]) == ABILITY_SYNCHRONIZE - && (B_SYNCHRONIZE_NATURE >= GEN_8 || Random() % 2 == 0)) + && (OW_SYNCHRONIZE_NATURE == GEN_8 || Random() % 2 == 0)) { return GetMonData(&gPlayerParty[0], MON_DATA_PERSONALITY) % NUM_NATURES; } -#endif // random nature return Random() % NUM_NATURES; @@ -434,7 +433,7 @@ static void CreateWildMon(u16 species, u8 level) bool32 checkCuteCharm; ZeroEnemyPartyMons(); - checkCuteCharm = TRUE; + checkCuteCharm = OW_CUTE_CHARM < GEN_9; switch (gSpeciesInfo[species].genderRatio) { @@ -480,33 +479,33 @@ static bool8 TryGenerateWildMon(const struct WildPokemonInfo *wildMonInfo, u8 ar switch (area) { case WILD_AREA_LAND: - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_STEEL, ABILITY_MAGNET_PULL, &wildMonIndex, LAND_WILD_COUNT)) + if (OW_MAGNET_PULL < GEN_9 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_STEEL, ABILITY_MAGNET_PULL, &wildMonIndex, LAND_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_ELECTRIC, ABILITY_STATIC, &wildMonIndex, LAND_WILD_COUNT)) + if (OW_STATIC < GEN_9 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_ELECTRIC, ABILITY_STATIC, &wildMonIndex, LAND_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_ELECTRIC, ABILITY_LIGHTNING_ROD, &wildMonIndex, LAND_WILD_COUNT)) + if (OW_LIGHTNING_ROD == GEN_8 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_ELECTRIC, ABILITY_LIGHTNING_ROD, &wildMonIndex, LAND_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_FIRE, ABILITY_FLASH_FIRE, &wildMonIndex, LAND_WILD_COUNT)) + if (OW_FLASH_FIRE == GEN_8 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_FIRE, ABILITY_FLASH_FIRE, &wildMonIndex, LAND_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_GRASS, ABILITY_HARVEST, &wildMonIndex, LAND_WILD_COUNT)) + if (OW_HARVEST == GEN_8 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_GRASS, ABILITY_HARVEST, &wildMonIndex, LAND_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_WATER, ABILITY_STORM_DRAIN, &wildMonIndex, LAND_WILD_COUNT)) + if (OW_STORM_DRAIN == GEN_8 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_WATER, ABILITY_STORM_DRAIN, &wildMonIndex, LAND_WILD_COUNT)) break; wildMonIndex = ChooseWildMonIndex_Land(); break; case WILD_AREA_WATER: - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_STEEL, ABILITY_MAGNET_PULL, &wildMonIndex, WATER_WILD_COUNT)) + if (OW_MAGNET_PULL < GEN_9 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_STEEL, ABILITY_MAGNET_PULL, &wildMonIndex, WATER_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_ELECTRIC, ABILITY_STATIC, &wildMonIndex, WATER_WILD_COUNT)) + if (OW_STATIC < GEN_9 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_ELECTRIC, ABILITY_STATIC, &wildMonIndex, WATER_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_ELECTRIC, ABILITY_LIGHTNING_ROD, &wildMonIndex, WATER_WILD_COUNT)) + if (OW_LIGHTNING_ROD == GEN_8 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_ELECTRIC, ABILITY_LIGHTNING_ROD, &wildMonIndex, WATER_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_FIRE, ABILITY_FLASH_FIRE, &wildMonIndex, WATER_WILD_COUNT)) + if (OW_FLASH_FIRE == GEN_8 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_FIRE, ABILITY_FLASH_FIRE, &wildMonIndex, WATER_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_GRASS, ABILITY_HARVEST, &wildMonIndex, WATER_WILD_COUNT)) + if (OW_HARVEST == GEN_8 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_GRASS, ABILITY_HARVEST, &wildMonIndex, WATER_WILD_COUNT)) break; - if (TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_WATER, ABILITY_STORM_DRAIN, &wildMonIndex, WATER_WILD_COUNT)) + if (OW_STORM_DRAIN == GEN_8 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_WATER, ABILITY_STORM_DRAIN, &wildMonIndex, WATER_WILD_COUNT)) break; wildMonIndex = ChooseWildMonIndex_WaterRock(); @@ -587,7 +586,7 @@ static bool8 WildEncounterCheck(u32 encounterRate, bool8 ignoreAbility) encounterRate = encounterRate * 3 / 4; else if (ability == ABILITY_STENCH) encounterRate /= 2; - else if (ability == ABILITY_ILLUMINATE) + else if (ability == ABILITY_ILLUMINATE && OW_ILLUMINATE < GEN_9) encounterRate *= 2; else if (ability == ABILITY_WHITE_SMOKE) encounterRate /= 2; @@ -599,10 +598,10 @@ static bool8 WildEncounterCheck(u32 encounterRate, bool8 ignoreAbility) encounterRate /= 2; else if (ability == ABILITY_QUICK_FEET) encounterRate /= 2; - else if (ability == ABILITY_INFILTRATOR) + else if (ability == ABILITY_INFILTRATOR && OW_INFILTRATOR == GEN_8) encounterRate /= 2; else if (ability == ABILITY_NO_GUARD) - encounterRate = encounterRate * 3 / 2; + encounterRate *= 2; } if (encounterRate > MAX_ENCOUNTER_RATE) encounterRate = MAX_ENCOUNTER_RATE;