From 35a2ee34bbaa03c2f98485ce150ddc7601ebad18 Mon Sep 17 00:00:00 2001 From: Marky <143505183+HashtagMarky@users.noreply.github.com> Date: Tue, 3 Mar 2026 23:26:59 +0000 Subject: [PATCH] Separate Perfect IV Logic Into New Function (#9173) --- docs/tutorials/mon_generation.md | 2 +- include/pokemon.h | 1 + src/dexnav.c | 21 ++------------- src/pokemon.c | 44 ++++++++++++++++++++------------ 4 files changed, 32 insertions(+), 36 deletions(-) diff --git a/docs/tutorials/mon_generation.md b/docs/tutorials/mon_generation.md index 3c1bc176dd..dc76ddc66a 100644 --- a/docs/tutorials/mon_generation.md +++ b/docs/tutorials/mon_generation.md @@ -94,7 +94,7 @@ The values set by `CreateMon` and `CreateBoxMon` are the gender, ability num, te ### Setting IVs and EVs -Usually, you will want to use `SetBoxMonIVs(mon->box, ivs)` to set the ivs of the pokemon you are generating. The reason is that not only can you quickly set all ivs of your mon to a single value: `SetBoxMonIVs(mon->box, 15)` will set all IVs to 15. You can also use the special argument `USE_RANDOM_IVS`. When used with `USE_RANDOM_IVS`, `SetBoxMonIvs` will not only pick a random value between 0 and 31 for each stat, it will also allocate some perfect iv if the species of the mon has a perfectIvCount set in the species data. For example if you are generating a legendary with a perfectIvCount of 3, using `SetBoxMonIVs(mon->box, USE_RANDOM_IVS)` will guarantee that at least 3 IVs are set to 31 +Usually, you will want to use `SetBoxMonIVs(mon->box, ivs)` to set the ivs of the pokemon you are generating. The reason is that not only can you quickly set all ivs of your mon to a single value: `SetBoxMonIVs(mon->box, 15)` will set all IVs to 15. You can also use the special argument `USE_RANDOM_IVS`. When used with `USE_RANDOM_IVS`, `SetBoxMonIvs` will not only pick a random value between 0 and 31 for each stat, it will also allocate some perfect iv if the species of the mon has a perfectIvCount set in the species data. For example if you are generating a legendary with a perfectIvCount of 3, using `SetBoxMonIVs(mon->box, USE_RANDOM_IVS)` will guarantee that at least 3 IVs are set to 31. This is done using the function `SetBoxMonPerfectIVs`, which can also be used elsewhere to assign a number of random perfect IVs. The other way to assign IV is to use `SetMonData`, for example: `SetMonData(mon, MON_DATA_HP_IV, 15)` with the stats being in order `MON_DATA_HP_IV`, `MON_DATA_ATK_IV`, `MON_DATA_DEF_IV`, `MON_DATA_SPEED_IV`, `MON_DATA_SPATK_IV` and `MON_DATA_SPDEF_IV` diff --git a/include/pokemon.h b/include/pokemon.h index 1f903b5a89..91f094cf2e 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -736,6 +736,7 @@ void CreateRandomMonWithIVs(struct Pokemon *mon, u16 species, u8 level, u8 fixed void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u32 personality, struct OriginalTrainerId); void CreateMonWithIVs(struct Pokemon *mon, u16 species, u8 level, u32 personality, struct OriginalTrainerId trainerId, u8 fixedIV); void SetBoxMonIVs(struct BoxPokemon *mon, u8 fixedIV); +void SetBoxMonPerfectIVs(struct BoxPokemon *mon, u32 numPerfect); void CreateMaleMon(struct Pokemon *mon, u16 species, u8 level); void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 ivs, u32 personality); void CreateBattleTowerMon(struct Pokemon *mon, struct BattleTowerPokemon *src); diff --git a/src/dexnav.c b/src/dexnav.c index e823bed1ef..fdec156c8b 100644 --- a/src/dexnav.c +++ b/src/dexnav.c @@ -1182,26 +1182,9 @@ static void DexNavUpdateSearchWindow(u8 proximity, u8 searchLevel) static void CreateDexNavWildMon(u16 species, u8 potential, u8 level, u8 abilityNum, enum Item item, enum Move *moves) { struct Pokemon *mon = &gEnemyParty[0]; - u8 iv[3] = {NUM_STATS}; - u8 i; - u8 perfectIv = 31; CreateWildMon(species, level); // shiny rate bonus handled in CreateBoxMon - - // Pick random, unique IVs to set to 31. The number of perfect IVs that are assigned is equal to the potential - iv[0] = Random() % NUM_STATS; // choose 1st perfect stat - do { - iv[1] = Random() % NUM_STATS; - iv[2] = Random() % NUM_STATS; - } while ((iv[1] == iv[0]) // unique 2nd perfect stat - || (iv[2] == iv[0] || iv[2] == iv[1])); // unique 3rd perfect stat - - if (potential > 2 && iv[2] != NUM_STATS) - SetMonData(mon, MON_DATA_HP_IV + iv[2], &perfectIv); - if (potential > 1 && iv[1] != NUM_STATS) - SetMonData(mon, MON_DATA_HP_IV + iv[1], &perfectIv); - if (potential > 0 && iv[0] != NUM_STATS) - SetMonData(mon, MON_DATA_HP_IV + iv[0], &perfectIv); + SetBoxMonPerfectIVs(&mon->box, min(3, potential)); // Will not exceed 3 Perfect IVs //Set ability SetMonData(mon, MON_DATA_ABILITY_NUM, &abilityNum); @@ -1211,7 +1194,7 @@ static void CreateDexNavWildMon(u16 species, u8 potential, u8 level, u8 abilityN SetMonData(mon, MON_DATA_HELD_ITEM, &item); //Set moves - for (i = 0; i < MAX_MON_MOVES; i++) + for (u32 i = 0; i < MAX_MON_MOVES; i++) SetMonMoveSlot(mon, moves[i], i); CalculateMonStats(mon); diff --git a/src/pokemon.c b/src/pokemon.c index 2c923a5b54..0c15e99ee9 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -1320,8 +1320,6 @@ void CreateMonWithIVs(struct Pokemon *mon, u16 species, u8 level, u32 personalit void SetBoxMonIVs(struct BoxPokemon *mon, u8 fixedIV) { u32 i, value; - enum Stat availableIVs[NUM_STATS]; - enum Stat selectedIvs[NUM_STATS]; if (fixedIV < USE_RANDOM_IVS) { @@ -1351,21 +1349,35 @@ void SetBoxMonIVs(struct BoxPokemon *mon, u8 fixedIV) iv = (value & (MAX_IV_MASK << 10)) >> 10; SetBoxMonData(mon, MON_DATA_SPDEF_IV, &iv); - if (gSpeciesInfo[species].perfectIVCount != 0) - { - iv = MAX_PER_STAT_IVS; - // Initialize a list of IV indices. - for (i = 0; i < NUM_STATS; i++) - availableIVs[i] = i; + SetBoxMonPerfectIVs(mon, gSpeciesInfo[species].perfectIVCount); +} - // Select the IVs that will be perfected. - for (i = 0; i < NUM_STATS && i < gSpeciesInfo[species].perfectIVCount; i++) - { - u8 index = Random() % (NUM_STATS - i); - selectedIvs[i] = availableIVs[index]; - RemoveIVIndexFromList(availableIVs, index); - SetBoxMonData(mon, MON_DATA_HP_IV + selectedIvs[i], &iv); - } +void SetBoxMonPerfectIVs(struct BoxPokemon *mon, u32 numPerfect) +{ + if (!numPerfect) + return; + + u32 i, iv = MAX_PER_STAT_IVS; + if (numPerfect >= NUM_STATS) + { + for (i = 0; i < NUM_STATS; i++) + SetBoxMonData(mon, MON_DATA_HP_IV + i, &iv); + return; + } + + enum Stat availableIVs[NUM_STATS]; + enum Stat selectedIvs[NUM_STATS]; + // Initialize a list of IV indices. + for (i = 0; i < NUM_STATS; i++) + availableIVs[i] = i; + + // Select the IVs that will be perfected. + for (i = 0; i < numPerfect; i++) + { + u8 index = Random() % (NUM_STATS - i); + selectedIvs[i] = availableIVs[index]; + RemoveIVIndexFromList(availableIVs, index); + SetBoxMonData(mon, MON_DATA_HP_IV + selectedIvs[i], &iv); } }