Implement better gender-iv conversion

This commit is contained in:
Lorenzooone 2023-02-05 17:13:29 +01:00
parent d4901a4324
commit 29084a8bf7
6 changed files with 45 additions and 19 deletions

View File

@ -17,6 +17,7 @@ u16 get_mon_index_gen1_to_3(u8);
u16 calc_stats_gen1(u16, u8, u8, u8, u16);
u16 calc_stats_gen2(u16, u32, u8, u8, u8, u16);
u8 get_gender_thresholds_gen12(u8);
u8 get_gender_useless_atk_ivs_gen12(u8);
u8 get_pokemon_gender_gen2(u8, u8, u8, u8);
u8 get_pokemon_gender_kind_gen2(u8, u8, u8);
const u8* get_pokemon_name_gen2(int, u8, u8, u8*);

View File

@ -29,9 +29,9 @@
#define M_GENDER 0
#define F_GENDER 1
#define U_GENDER 2
#define M_INDEX 1
#define F_INDEX 6
#define U_INDEX 7
#define M_GENDER_INDEX 1
#define F_GENDER_INDEX 6
#define U_GENDER_INDEX 7
#define NIDORAN_M_GENDER_INDEX 8
#define NIDORAN_F_GENDER_INDEX 9
#define TOTAL_GENDER_KINDS 10

View File

@ -15,6 +15,7 @@
u8 stat_index_conversion_gen2[] = {0, 1, 2, 5, 3, 4};
u8 gender_thresholds_gen12[TOTAL_GENDER_KINDS] = {8, 0, 2, 4, 12, 14, 16, 17, 0, 16};
u8 gender_useful_atk_ivs[TOTAL_GENDER_KINDS] = {3, 4, 1, 2, 2, 1, 4, 4, 4, 4};
const struct stats_gen_23* stats_table_gen2 = (const struct stats_gen_23*)pokemon_stats_bin;
const struct stats_gen_1* stats_table_gen1 = (const struct stats_gen_1*)pokemon_stats_gen1_bin;
@ -160,6 +161,12 @@ u8 get_gender_thresholds_gen12(u8 gender_kind) {
return gender_thresholds_gen12[gender_kind];
}
u8 get_gender_useless_atk_ivs_gen12(u8 gender_kind) {
if(gender_kind >= TOTAL_GENDER_KINDS)
gender_kind = 0;
return 4-gender_useful_atk_ivs[gender_kind];
}
u8 get_pokemon_gender_kind_gen2(u8 index, u8 is_egg, u8 curr_gen) {
if(curr_gen == 1)
return pokemon_gender_bin[get_mon_index_gen2_1(index)];
@ -183,13 +190,13 @@ const u8* get_pokemon_name_gen2(int index, u8 is_egg, u8 is_jp, u8* buffer) {
u8 get_pokemon_gender_gen2(u8 index, u8 atk_ivs, u8 is_egg, u8 curr_gen) {
u8 gender_kind = get_pokemon_gender_kind_gen2(index, is_egg, curr_gen);
switch(gender_kind){
case M_INDEX:
case M_GENDER_INDEX:
case NIDORAN_M_GENDER_INDEX:
return M_GENDER;
case F_INDEX:
case F_GENDER_INDEX:
case NIDORAN_F_GENDER_INDEX:
return F_GENDER;
case U_INDEX:
case U_GENDER_INDEX:
return U_GENDER;
default:
if(atk_ivs >= get_gender_thresholds_gen12(gender_kind))

View File

@ -307,11 +307,15 @@ void convert_evs_to_gen3(struct gen3_mon_evs* evs, u16* UNUSED(old_evs)) {
u16 convert_ivs_of_gen3(struct gen3_mon_misc* misc, u16 species, u32 pid, u8 is_shiny, u8 gender, u8 gender_kind, u8 is_gen2) {
if(((is_gen2) && (species > LAST_VALID_GEN_2_MON)) || ((!is_gen2) && (species > LAST_VALID_GEN_1_MON)))
return 0;
// Prepare gender related data
u8 gender_threshold = get_gender_thresholds_gen12(gender_kind);
u8 gender_useless_ivs = get_gender_useless_atk_ivs_gen12(gender_kind);
// Assign IVs
// Keep in mind: Unown letter, gender and shinyness
// Hidden Power calculations are too restrictive
u8 atk_ivs = misc->atk_ivs >> 1;
u8 atk_ivs = (((misc->atk_ivs >> 1)>>gender_useless_ivs) | ((misc->atk_ivs >> 1)<<gender_useless_ivs)) & 0xF;
u8 def_ivs = misc->def_ivs >> 1;
u8 spa_ivs = (misc->spa_ivs + misc->spd_ivs) >> 2;
u8 spe_ivs = misc->spe_ivs >> 1;
@ -347,12 +351,26 @@ u16 convert_ivs_of_gen3(struct gen3_mon_misc* misc, u16 species, u32 pid, u8 is_
}
// Gender
// TODO: Remake this to offer a more fair conversion
if(gender != U_GENDER && gender_kind != M_INDEX && gender_kind != F_INDEX) {
if(gender == F_GENDER && atk_ivs >= get_gender_thresholds_gen12(gender_kind))
atk_ivs = get_gender_thresholds_gen12(gender_kind) - 1;
else if(gender == M_GENDER && atk_ivs < get_gender_thresholds_gen12(gender_kind))
atk_ivs = get_gender_thresholds_gen12(gender_kind);
if((gender_threshold > 0) && (gender_threshold < 16)) {
if(gender == F_GENDER) {
if(atk_ivs >= gender_threshold) {
u8 is_power_of_2 = 0;
for(int i = 0; i < 4; i++)
if(gender_threshold == (1 << i)) {
is_power_of_2 = 1;
break;
}
if(is_power_of_2)
atk_ivs &= (gender_threshold - 1);
else {
if(is_shiny && (gender_useless_ivs > (4-2)))
gender_useless_ivs = 4-2;
atk_ivs &= ~(1<<(4-gender_useless_ivs));
}
}
}
else
atk_ivs |= gender_threshold;
}
// Shinyness
@ -362,6 +380,7 @@ u16 convert_ivs_of_gen3(struct gen3_mon_misc* misc, u16 species, u32 pid, u8 is_
spa_ivs = 10;
spe_ivs = 10;
}
if(!is_shiny && is_shiny_gen2(atk_ivs, def_ivs, spa_ivs, spe_ivs))
spe_ivs = 11;

View File

@ -347,13 +347,13 @@ u8 make_moves_legal_gen3(struct gen3_mon_attacks* attacks){
u8 get_pokemon_gender_gen3(int index, u32 pid, u8 is_egg, u8 deoxys_form){
u8 gender_kind = get_pokemon_gender_kind_gen3(index, pid, is_egg, deoxys_form);
switch(gender_kind){
case M_INDEX:
case M_GENDER_INDEX:
case NIDORAN_M_GENDER_INDEX:
return M_GENDER;
case F_INDEX:
case F_GENDER_INDEX:
case NIDORAN_F_GENDER_INDEX:
return F_GENDER;
case U_INDEX:
case U_GENDER_INDEX:
return U_GENDER;
default:
if((pid & 0xFF) >= gender_thresholds_gen3[gender_kind])

View File

@ -32,7 +32,6 @@ u8 search_unown_pid_masks(u32, u8, u32*, u32*);
void _generate_unown_shiny_info(u8, u16, u8, u32*, u32*, u32);
// Nidoran M is special, it has to have 0x8000 set in the lower PID
u8 gender_useful_atk_ivs[] = {3, 4, 1, 2, 2, 1, 4, 4, 4, 4};
u16 gender_values[] = {0x7F, 0, 0x1F, 0x3F, 0xBF, 0xDF, 0, 0, 0x7FFF, 0};
const u8 wanted_nature_shiny_table[NUM_NATURES] = {0, 1, 2, 3, 4, 5, 6, 7, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x15, 0x16, 0x17, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45};
@ -123,7 +122,7 @@ IWRAM_CODE MAX_OPTIMIZE u32 generate_ot(u16 tid, u8* name) {
IWRAM_CODE MAX_OPTIMIZE void _generate_egg_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u8 gender, u8 gender_kind, u32* dst_pid, u32* dst_ivs, u32 start_seed) {
// Worst case: 0, 0x2113, 0, 0, 0, 34
u8 atk_ivs = ((((wanted_ivs>>4) & 0xF)<<(4-gender_useful_atk_ivs[gender_kind])) & 0xF)<<1;
u8 atk_ivs = ((((wanted_ivs>>4) & 0xF)<<get_gender_useless_atk_ivs_gen12(gender_kind)) & 0xF)<<1;
u8 def_ivs = ((wanted_ivs) & 0xF)<<1;
u8 spe_ivs = ((wanted_ivs>>12) & 0xF)<<1;
u8 spa_ivs = ((wanted_ivs>>8) & 0xF)<<1;
@ -158,7 +157,7 @@ IWRAM_CODE MAX_OPTIMIZE void _generate_egg_info(u8 wanted_nature, u16 wanted_ivs
u32 seed = (k<<31) | (new_spe_ivs << 16) | (new_spa_ivs << 21) | (new_spd_ivs << 26) | l;
u16 generated_ivs = get_prev_seed(seed) >> 16;
u8 new_atk_ivs = (((generated_ivs >> 5)&0x1F)>>(1+(4-gender_useful_atk_ivs[gender_kind]))) << (1+(4-gender_useful_atk_ivs[gender_kind]));
u8 new_atk_ivs = (((generated_ivs >> 5)&0x1F)>>(1+get_gender_useless_atk_ivs_gen12(gender_kind))) << (1+get_gender_useless_atk_ivs_gen12(gender_kind));
u8 new_def_ivs = (((generated_ivs >> 10)&0x1F)>>1) << 1;
if(new_atk_ivs == atk_ivs && new_def_ivs == def_ivs) {