diff --git a/data/scripts/maps/Route101.inc b/data/scripts/maps/Route101.inc index 6840c45f4b..aa15933377 100644 --- a/data/scripts/maps/Route101.inc +++ b/data/scripts/maps/Route101.inc @@ -204,6 +204,7 @@ Route101_Movement_14EA58:: @ 814EA58 Route101_EventScript_14EA64:: @ 814EA64 msgbox Route101_Text_16D25E, 2 + setflag FLAG_SET_SHINY_MON end Route101_EventScript_14EA6D:: @ 814EA6D diff --git a/include/constants/flags.h b/include/constants/flags.h index a8067f6cab..a96c6afcc8 100644 --- a/include/constants/flags.h +++ b/include/constants/flags.h @@ -880,6 +880,8 @@ #define FLAG_LANDMARK_BERRY_MASTERS_HOUSE (SYSTEM_FLAGS + 0x63) +#define FLAG_SET_SHINY_MON (SYSTEM_FLAGS + 0x64) + // Daily Flags. These 64 flags are cleared once per day. #define DAILY_FLAGS_START (SYSTEM_FLAGS + 0xC0) diff --git a/include/pokemon.h b/include/pokemon.h index 169045c0ca..c95299bfce 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -623,6 +623,7 @@ bool8 IsPokeSpriteNotFlipped(u16); u8 GetLevelUpMovesBySpecies(u16, u16 *); u8 TryIncrementMonLevel(struct Pokemon *); bool8 IsShiny(struct Pokemon *mon); +bool8 IsShinyOtIdPersonality(u32 otId, u32 personality); void RandomlyGivePartyPokerus(struct Pokemon *party); void PartySpreadPokerus(struct Pokemon *party); diff --git a/src/pokemon_1.c b/src/pokemon_1.c index a23bb33245..a4dc05777e 100644 --- a/src/pokemon_1.c +++ b/src/pokemon_1.c @@ -1,9 +1,11 @@ #include "global.h" #include "data2.h" #include "constants/abilities.h" +#include "constants/flags.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/species.h" +#include "event_data.h" #include "main.h" #include "pokemon.h" #include "random.h" @@ -82,6 +84,8 @@ const s8 gNatureStatTable[][5] = #include "data/pokemon/evolution.h" #include "data/pokemon/level_up_learnset_pointers.h" +static u32 ForceShinyPersonality(u32 personality); + void ZeroBoxMonData(struct BoxPokemon *boxMon) { u8 *raw = (u8 *)boxMon; @@ -239,12 +243,46 @@ void CreateMonWithNature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, do { personality = Random32(); + if (FlagGet(FLAG_SET_SHINY_MON)) + { + personality = ForceShinyPersonality(personality); + } } while (nature != GetNatureFromPersonality(personality)); CreateMon(mon, species, level, fixedIV, 1, personality, 0, 0); } +static u32 ForceShinyPersonality(u32 personality) +{ + int currentBit; + u32 playerOT = gSaveBlock2.playerTrainerId[0] + | (gSaveBlock2.playerTrainerId[1] << 8) + | (gSaveBlock2.playerTrainerId[2] << 16) + | (gSaveBlock2.playerTrainerId[3] << 24); + u16 otVal = (playerOT >> 16) ^ (playerOT & 0xFFFF); + + u16 bitSelector = Random(); + u16 personalityVal = (personality >> 16) ^ (personality & 0xFFFF); + for (currentBit = 3; currentBit < 16; currentBit++) + { + int shiftedBit = 1 << currentBit; + int otBitSet = (otVal & shiftedBit) != 0; + int personalityBitSet = (personalityVal & shiftedBit) != 0; + if (otBitSet + personalityBitSet == 1) + { + // Bits are different, so let's arbitrarily flip one of them such + // that the XOR of the folded OT and personality values will be 0. + if (bitSelector & shiftedBit) + personality ^= shiftedBit; + else + personality ^= (shiftedBit << 16); + } + } + + return personality; +} + void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 gender, u8 nature, u8 unownLetter) { u32 personality; diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 19778e29b6..73657b767a 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -3982,6 +3982,7 @@ static void CreateWildMon(u16 species, u8 b) { ZeroEnemyPartyMons(); CreateMonWithNature(&gEnemyParty[0], species, b, 0x20, PickWildMonNature()); + FlagClear(FLAG_SET_SHINY_MON); } static bool8 GenerateWildMon(const struct WildPokemonInfo *wildMonInfo, u8 area, bool8 checkRepel)