Skip to content

Commit

Permalink
Fixes Synchronize's OW effect and adds configs (#3480)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bassoonian committed Oct 29, 2023
1 parent 0dd2230 commit ab25e6b
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 37 deletions.
1 change: 0 additions & 1 deletion include/config/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
14 changes: 14 additions & 0 deletions include/config/overworld.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions include/wild_encounter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
26 changes: 15 additions & 11 deletions src/pokemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
22 changes: 18 additions & 4 deletions src/script_pokemon_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -164,15 +172,21 @@ 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;
heldItem1[1] = item1 >> 8;
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;
Expand Down
41 changes: 20 additions & 21 deletions src/wild_encounter.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ static u16 GetCurrentMapWildMonHeaderId(void)
return HEADER_NONE;
}

static u8 PickWildMonNature(void)
u8 PickWildMonNature(void)
{
u8 i;
u8 j;
Expand Down Expand Up @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit ab25e6b

Please sign in to comment.