From aca6bdfc64df0b94d271db2802c9efd0847b56d1 Mon Sep 17 00:00:00 2001 From: Kris Bahnsen Date: Sun, 14 Jul 2024 20:53:38 -0700 Subject: [PATCH] attribute: combine calculated attributes to single file Handles gender, pokerus, shiny, and unown form Signed-off-by: Kris Bahnsen --- .../{pokemon_gender.h => pokemon_attribute.h} | 21 +- src/include/pokemon_pokerus.h | 14 - src/include/pokemon_shiny.h | 10 - src/include/unown_form.h | 13 - src/pokemon_attribute.c | 265 ++++++++++++++++++ src/pokemon_gender.c | 91 ------ src/pokemon_pokerus.c | 51 ---- src/pokemon_shiny.c | 61 ---- src/pokemon_table.c | 2 +- src/scenes/pokemon_gen.c | 5 +- src/scenes/pokemon_gender.c | 2 +- src/scenes/pokemon_name_input.c | 2 +- src/scenes/pokemon_pokerus.c | 2 +- src/scenes/pokemon_shiny.c | 2 +- src/unown_form.c | 73 ----- 15 files changed, 289 insertions(+), 325 deletions(-) rename src/include/{pokemon_gender.h => pokemon_attribute.h} (64%) delete mode 100644 src/include/pokemon_pokerus.h delete mode 100644 src/include/pokemon_shiny.h delete mode 100644 src/include/unown_form.h create mode 100644 src/pokemon_attribute.c delete mode 100644 src/pokemon_gender.c delete mode 100644 src/pokemon_pokerus.c delete mode 100644 src/pokemon_shiny.c delete mode 100644 src/unown_form.c diff --git a/src/include/pokemon_gender.h b/src/include/pokemon_attribute.h similarity index 64% rename from src/include/pokemon_gender.h rename to src/include/pokemon_attribute.h index a97d19e8363..516cd99e324 100644 --- a/src/include/pokemon_gender.h +++ b/src/include/pokemon_attribute.h @@ -1,5 +1,5 @@ -#ifndef POKEMON_GENDER_H -#define POKEMON_GENDER_H +#ifndef POKEMON_ATTRIBUTE_H +#define POKEMON_ATTRIBUTE_H #pragma once @@ -36,4 +36,19 @@ const char* pokemon_gender_get(PokemonData* pdata); void pokemon_gender_set(PokemonData* pdata, Gender gender); -#endif // POKEMON_GENDER_H +const char* pokerus_get_status_str(PokemonData* pdata); + +void pokerus_set_strain(PokemonData* pdata, uint8_t strain); + +void pokerus_set_days(PokemonData *pdata, uint8_t days); + +bool pokemon_is_shiny(PokemonData* pdata); + +void pokemon_set_shiny(PokemonData *pdata, bool shiny); + +/* Returns ascii char, or 0 if unown is not the current pokemon */ +char unown_form_get(PokemonData* pdata); + +void unown_form_set(PokemonData* pdata, char letter); + +#endif // POKEMON_ATTRIBUTE_H diff --git a/src/include/pokemon_pokerus.h b/src/include/pokemon_pokerus.h deleted file mode 100644 index 2b385bab4a9..00000000000 --- a/src/include/pokemon_pokerus.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef POKEMON_POKERUS_H -#define POKEMON_POKERUS_H - -#include - -#pragma once - -const char* pokerus_get_status_str(PokemonData* pdata); - -void pokerus_set_strain(PokemonData* pdata, uint8_t strain); - -void pokerus_set_days(PokemonData *pdata, uint8_t days); - -#endif // POKEMON_POKERUS_H diff --git a/src/include/pokemon_shiny.h b/src/include/pokemon_shiny.h deleted file mode 100644 index bc86184cbbe..00000000000 --- a/src/include/pokemon_shiny.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef POKEMON_SHINY_H -#define POKEMON_SHINY_H - -#pragma once - -bool pokemon_is_shiny(PokemonData* pdata); - -void pokemon_set_shiny(PokemonData *pdata, bool shiny); - -#endif // POKEMON_SHINY_H diff --git a/src/include/unown_form.h b/src/include/unown_form.h deleted file mode 100644 index 438a8e5180e..00000000000 --- a/src/include/unown_form.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef UNOWN_FORM_H -#define UNOWN_FORM_H - -#pragma once - -#include - -/* Returns ascii char, or 0 if unown is not the current pokemon */ -char unown_form_get(PokemonData* pdata); - -void unown_form_set(PokemonData* pdata, char letter); - -#endif // UNOWN_FORM_H diff --git a/src/pokemon_attribute.c b/src/pokemon_attribute.c new file mode 100644 index 00000000000..b7126ef6d77 --- /dev/null +++ b/src/pokemon_attribute.c @@ -0,0 +1,265 @@ +#include +#include +#include +#include + + +static const char* gender_str[] = { + "Unknown", + "Female", + "Male", +}; + +/* This returns a string pointer if the gender is static, NULL if it is not and + * the gender needs to be calculated. + */ +const char* pokemon_gender_is_static(PokemonData* pdata, uint8_t ratio) { + switch(ratio) { + case 0xFF: + return gender_str[0]; + case 0xFE: + return gender_str[1]; + case 0x00: + if(pokemon_stat_get(pdata, STAT_NUM, NONE) != 0xEB) { // Tyrogue can be either gender + return gender_str[2]; + } + break; + default: + break; + } + + return NULL; +} + +const char* pokemon_gender_get(PokemonData* pdata) { + uint8_t ratio = table_stat_base_get( + pdata->pokemon_table, + pokemon_stat_get(pdata, STAT_NUM, NONE), + STAT_BASE_GENDER_RATIO, + NONE); + uint8_t atk_iv; + const char* rc; + + rc = pokemon_gender_is_static(pdata, ratio); + if(rc) return rc; + + /* Falling through here means now we need to calculate the gender from + * its ratio and ATK_IV. + */ + atk_iv = pokemon_stat_get(pdata, STAT_ATK_IV, NONE); + if(atk_iv * 17 <= ratio) + return gender_str[1]; + else + return gender_str[2]; +} + +void pokemon_gender_set(PokemonData* pdata, Gender gender) { + + uint8_t ratio = table_stat_base_get( + pdata->pokemon_table, + pokemon_stat_get(pdata, STAT_NUM, NONE), + STAT_BASE_GENDER_RATIO, + NONE); + uint8_t atk_iv = pokemon_stat_get(pdata, STAT_ATK_IV, NONE); + + /* If we need to make the pokemon a male, increase atk IV until it exceeds + * the gender ratio. + * + * Note that, there is no checking here for impossible situations as the + * scene enter function will immediately quit if its not possible to change + * the gender (the extremes of gender_ratio value). + * + * The check for gender is a percentage, if ATK_IV*(255/15) <= the ratio, + * then the pokemon is a female. The gender ratio values end up being: + * DEF GENDER_F0 EQU 0 percent + * DEF GENDER_F12_5 EQU 12 percent + 1 + * DEF GENDER_F25 EQU 25 percent + * DEF GENDER_F50 EQU 50 percent + * DEF GENDER_F75 EQU 75 percent + * DEF GENDER_F100 EQU 100 percent - 1 + * Where percent is (255/100) + */ + if(gender == GENDER_MALE) { + while((atk_iv * 17) <= ratio) atk_iv++; + } else { + while((atk_iv * 17) > ratio) atk_iv--; + } + + pokemon_stat_set(pdata, STAT_ATK_IV, NONE, atk_iv); +} + +static const char* pokerus_states[] = { + "Clean", + "Infected", + "Cured", + "", +}; + +const char* pokerus_get_status_str(PokemonData* pdata) { + uint8_t pokerus; + + pokerus = pokemon_stat_get(pdata, STAT_POKERUS, NONE); + + if(pokerus == 0x00) + return pokerus_states[0]; + + if((pokerus & 0x0f) != 0x00) + return pokerus_states[1]; + + return pokerus_states[2]; +} + +void pokerus_set_strain(PokemonData* pdata, uint8_t strain) { + uint8_t pokerus; + + /* Need to read/modify/write the existing stat */ + pokerus = pokemon_stat_get(pdata, STAT_POKERUS, NONE); + pokerus &= 0x0f; + pokerus |= (strain << 4); + + if((pokerus & 0xf0) == 0x00) + pokerus = 0; + + pokemon_stat_set(pdata, STAT_POKERUS, NONE, pokerus); +} + +void pokerus_set_days(PokemonData *pdata, uint8_t days) { + uint8_t pokerus; + + days &= 0x0f; + + /* Need to read/modify/write the existing stat */ + pokerus = pokemon_stat_get(pdata, STAT_POKERUS, NONE); + pokerus &= 0xf0; + pokerus |= days; + pokemon_stat_set(pdata, STAT_POKERUS, NONE, pokerus); +} + +/* This just assumes gen ii for now */ +/* For a Gen II pokemon to be shiny, the following must be met: + * Spd, Def, and Spc must all be 10 + * Atk must be 2, 3, 6, 7, 10, 11, 14, or 15 + */ +bool pokemon_is_shiny(PokemonData* pdata) { + uint8_t atk_iv = pokemon_stat_get(pdata, STAT_ATK_IV, NONE); + uint8_t def_iv = pokemon_stat_get(pdata, STAT_DEF_IV, NONE); + uint8_t spd_iv = pokemon_stat_get(pdata, STAT_SPD_IV, NONE); + uint8_t spc_iv = pokemon_stat_get(pdata, STAT_SPC_IV, NONE); + bool rc = 1; + + if(spd_iv != 10) rc = 0; + if(def_iv != 10) rc = 0; + if(spc_iv != 10) rc = 0; + switch(atk_iv) { + case 0: + case 1: + case 4: + case 5: + case 8: + case 9: + case 12: + case 13: + rc = 0; + break; + default: + break; + } + + return rc; +} + +void pokemon_set_shiny(PokemonData* pdata, bool shiny) { + + if(!shiny) { + do { + /* First, reset the IV to the selected stat */ + pokemon_stat_set(pdata, STAT_SEL, NONE, pokemon_stat_get(pdata, STAT_SEL, NONE)); + + /* XXX: This may not be right? */ + /* Next, ensure the current IVs wouldn't make the pokemon shiny */ + } while(pokemon_is_shiny(pdata)); + } else { + /* Set Def, Spd, Spc to 10 */ + pokemon_stat_set(pdata, STAT_DEF_IV, NONE, 10); + pokemon_stat_set(pdata, STAT_SPD_IV, NONE, 10); + pokemon_stat_set(pdata, STAT_SPC_IV, NONE, 10); + + /* Increase ATK IV until we hit a shiny number. Note that, this only + * affects IVs that are randomly generated, max IV will already be set + * at 15 which will make it shiny. + */ + while(!pokemon_is_shiny(pdata)) { + pokemon_stat_set( + pdata, STAT_ATK_IV, NONE, pokemon_stat_get(pdata, STAT_ATK_IV, NONE) + 1); + } + } +} + +/* This is used to get the current IVs from the trade struct. + * Unown form is calculated by taking the middle bytes of each nibble of IV, + * pressing them in order to a single byte, and dividing that by 10 (rounded + * down/floor). This will create a value from 0 to 25 that is a 1:1 mapping + * of the English alphabet and is how Unown forms are represented. + * + * C integer division truncates to 0 rather than does any proper rounding. + * + * https://bulbapedia.bulbagarden.net/wiki/Individual_values#Unown's_letter + */ +static uint8_t unown_ivs_get(PokemonData* pdata) { + furi_assert(pdata); + uint16_t ivs = pokemon_stat_get(pdata, STAT_IV, NONE); + uint8_t ivs_mid; + + ivs_mid = + (((ivs & 0x6000) >> 7) | ((ivs & 0x0600) >> 5) | ((ivs & 0x0060) >> 3) | + ((ivs & 0x0006) >> 1)); + + return ivs_mid; +} + +static void unown_ivs_set(PokemonData* pdata, uint8_t ivs_mid) { + furi_assert(pdata); + uint16_t ivs = pokemon_stat_get(pdata, STAT_IV, NONE); + + /* Clear the middle bits of each nibble */ + ivs &= ~(0x6666); + + /* Set the updated ivs_mid in to those cleared bits */ + ivs |= + (((ivs_mid & 0xC0) << 7) | ((ivs_mid & 0x30) << 5) | ((ivs_mid & 0x0C) << 3) | + ((ivs_mid & 0x03) << 1)); + pokemon_stat_set(pdata, STAT_IV, NONE, ivs); +} + +char unown_form_get(PokemonData* pdata) { + uint8_t form = unown_ivs_get(pdata); + + /* The forumula is specifically the center two bits of each IV slapped + * together and floor(/10) + */ + form /= 10; + form += 'A'; + + return form; +} + +/* Try and get to the desired form by adding/subtracting the current IVs */ +void unown_form_set(PokemonData* pdata, char letter) { + uint8_t ivs = unown_ivs_get(pdata); + uint8_t form; + + letter = toupper(letter); + furi_check(isalpha(letter)); + + while(1) { + form = ((ivs / 10) + 'A'); + if(form == letter) break; + if(form > letter) + ivs--; + else + ivs++; + } + + /* form is now the target letter, set IVs back up */ + unown_ivs_set(pdata, ivs); +} diff --git a/src/pokemon_gender.c b/src/pokemon_gender.c deleted file mode 100644 index 7c24fb791cc..00000000000 --- a/src/pokemon_gender.c +++ /dev/null @@ -1,91 +0,0 @@ -#include - -#include -#include -#include - -#include - -static const char* gender_str[] = { - "Unknown", - "Female", - "Male", -}; - -/* This returns a string pointer if the gender is static, NULL if it is not and - * the gender needs to be calculated. - */ -const char* pokemon_gender_is_static(PokemonData* pdata, uint8_t ratio) { - switch(ratio) { - case 0xFF: - return gender_str[0]; - case 0xFE: - return gender_str[1]; - case 0x00: - if(pokemon_stat_get(pdata, STAT_NUM, NONE) != 0xEB) { // Tyrogue can be either gender - return gender_str[2]; - } - break; - default: - break; - } - - return NULL; -} - -const char* pokemon_gender_get(PokemonData* pdata) { - uint8_t ratio = table_stat_base_get( - pdata->pokemon_table, - pokemon_stat_get(pdata, STAT_NUM, NONE), - STAT_BASE_GENDER_RATIO, - NONE); - uint8_t atk_iv; - const char* rc; - - rc = pokemon_gender_is_static(pdata, ratio); - if(rc) return rc; - - /* Falling through here means now we need to calculate the gender from - * its ratio and ATK_IV. - */ - atk_iv = pokemon_stat_get(pdata, STAT_ATK_IV, NONE); - if(atk_iv * 17 <= ratio) - return gender_str[1]; - else - return gender_str[2]; -} - -void pokemon_gender_set(PokemonData* pdata, Gender gender) { - - uint8_t ratio = table_stat_base_get( - pdata->pokemon_table, - pokemon_stat_get(pdata, STAT_NUM, NONE), - STAT_BASE_GENDER_RATIO, - NONE); - uint8_t atk_iv = pokemon_stat_get(pdata, STAT_ATK_IV, NONE); - - /* If we need to make the pokemon a male, increase atk IV until it exceeds - * the gender ratio. - * - * Note that, there is no checking here for impossible situations as the - * scene enter function will immediately quit if its not possible to change - * the gender (the extremes of gender_ratio value). - * - * The check for gender is a percentage, if ATK_IV*(255/15) <= the ratio, - * then the pokemon is a female. The gender ratio values end up being: - * DEF GENDER_F0 EQU 0 percent - * DEF GENDER_F12_5 EQU 12 percent + 1 - * DEF GENDER_F25 EQU 25 percent - * DEF GENDER_F50 EQU 50 percent - * DEF GENDER_F75 EQU 75 percent - * DEF GENDER_F100 EQU 100 percent - 1 - * Where percent is (255/100) - */ - if(gender == GENDER_MALE) { - while((atk_iv * 17) <= ratio) atk_iv++; - } else { - while((atk_iv * 17) > ratio) atk_iv--; - } - - pokemon_stat_set(pdata, STAT_ATK_IV, NONE, atk_iv); -} diff --git a/src/pokemon_pokerus.c b/src/pokemon_pokerus.c deleted file mode 100644 index 6ab5ac67d7f..00000000000 --- a/src/pokemon_pokerus.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include - -#include - -static const char* pokerus_states[] = { - "Clean", - "Infected", - "Cured", - "", -}; - -const char* pokerus_get_status_str(PokemonData* pdata) { - uint8_t pokerus; - - pokerus = pokemon_stat_get(pdata, STAT_POKERUS, NONE); - - if(pokerus == 0x00) - return pokerus_states[0]; - - if((pokerus & 0x0f) != 0x00) - return pokerus_states[1]; - - return pokerus_states[2]; -} - -void pokerus_set_strain(PokemonData* pdata, uint8_t strain) { - uint8_t pokerus; - - /* Need to read/modify/write the existing stat */ - pokerus = pokemon_stat_get(pdata, STAT_POKERUS, NONE); - pokerus &= 0x0f; - pokerus |= (strain << 4); - - if((pokerus & 0xf0) == 0x00) - pokerus = 0; - - pokemon_stat_set(pdata, STAT_POKERUS, NONE, pokerus); -} - -void pokerus_set_days(PokemonData *pdata, uint8_t days) { - uint8_t pokerus; - - days &= 0x0f; - - /* Need to read/modify/write the existing stat */ - pokerus = pokemon_stat_get(pdata, STAT_POKERUS, NONE); - pokerus &= 0xf0; - pokerus |= days; - pokemon_stat_set(pdata, STAT_POKERUS, NONE, pokerus); -} diff --git a/src/pokemon_shiny.c b/src/pokemon_shiny.c deleted file mode 100644 index cc7b6670fe4..00000000000 --- a/src/pokemon_shiny.c +++ /dev/null @@ -1,61 +0,0 @@ -#include - -/* This just assumes gen ii for now */ -/* For a Gen II pokemon to be shiny, the following must be met: - * Spd, Def, and Spc must all be 10 - * Atk must be 2, 3, 6, 7, 10, 11, 14, or 15 - */ -bool pokemon_is_shiny(PokemonData* pdata) { - uint8_t atk_iv = pokemon_stat_get(pdata, STAT_ATK_IV, NONE); - uint8_t def_iv = pokemon_stat_get(pdata, STAT_DEF_IV, NONE); - uint8_t spd_iv = pokemon_stat_get(pdata, STAT_SPD_IV, NONE); - uint8_t spc_iv = pokemon_stat_get(pdata, STAT_SPC_IV, NONE); - bool rc = 1; - - if(spd_iv != 10) rc = 0; - if(def_iv != 10) rc = 0; - if(spc_iv != 10) rc = 0; - switch(atk_iv) { - case 0: - case 1: - case 4: - case 5: - case 8: - case 9: - case 12: - case 13: - rc = 0; - break; - default: - break; - } - - return rc; -} - -void pokemon_set_shiny(PokemonData* pdata, bool shiny) { - - if(!shiny) { - do { - /* First, reset the IV to the selected stat */ - pokemon_stat_set(pdata, STAT_SEL, NONE, pokemon_stat_get(pdata, STAT_SEL, NONE)); - - /* XXX: This may not be right? */ - /* Next, ensure the current IVs wouldn't make the pokemon shiny */ - } while(pokemon_is_shiny(pdata)); - } else { - /* Set Def, Spd, Spc to 10 */ - pokemon_stat_set(pdata, STAT_DEF_IV, NONE, 10); - pokemon_stat_set(pdata, STAT_SPD_IV, NONE, 10); - pokemon_stat_set(pdata, STAT_SPC_IV, NONE, 10); - - /* Increase ATK IV until we hit a shiny number. Note that, this only - * affects IVs that are randomly generated, max IV will already be set - * at 15 which will make it shiny. - */ - while(!pokemon_is_shiny(pdata)) { - pokemon_stat_set( - pdata, STAT_ATK_IV, NONE, pokemon_stat_get(pdata, STAT_ATK_IV, NONE) + 1); - } - } -} diff --git a/src/pokemon_table.c b/src/pokemon_table.c index b1ed9dae3e5..4ff9d93fa31 100644 --- a/src/pokemon_table.c +++ b/src/pokemon_table.c @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include diff --git a/src/scenes/pokemon_gen.c b/src/scenes/pokemon_gen.c index 4fa879674f2..e5acc32a3dc 100644 --- a/src/scenes/pokemon_gen.c +++ b/src/scenes/pokemon_gen.c @@ -10,10 +10,7 @@ #include #include -#include -#include -#include -#include +#include static void scene_change_from_main_cb(void* context, uint32_t index) { PokemonFap* pokemon_fap = (PokemonFap*)context; diff --git a/src/scenes/pokemon_gender.c b/src/scenes/pokemon_gender.c index 92c95b06562..30a4f9e77d0 100644 --- a/src/scenes/pokemon_gender.c +++ b/src/scenes/pokemon_gender.c @@ -2,7 +2,7 @@ #include #include -#include +#include #include diff --git a/src/scenes/pokemon_name_input.c b/src/scenes/pokemon_name_input.c index 5b096b4682c..1e6af4f3593 100644 --- a/src/scenes/pokemon_name_input.c +++ b/src/scenes/pokemon_name_input.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include diff --git a/src/scenes/pokemon_pokerus.c b/src/scenes/pokemon_pokerus.c index d6f25b74a2b..8fde7fcb9c2 100644 --- a/src/scenes/pokemon_pokerus.c +++ b/src/scenes/pokemon_pokerus.c @@ -4,7 +4,7 @@ #include #include -#include +#include static const char* strains[] = { "None", diff --git a/src/scenes/pokemon_shiny.c b/src/scenes/pokemon_shiny.c index f7958ad68d8..0263ea65754 100644 --- a/src/scenes/pokemon_shiny.c +++ b/src/scenes/pokemon_shiny.c @@ -1,7 +1,7 @@ #include #include -#include +#include #include diff --git a/src/unown_form.c b/src/unown_form.c deleted file mode 100644 index be57079583b..00000000000 --- a/src/unown_form.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include - -#include - -/* This is used to get the current IVs from the trade struct. - * Unown form is calculated by taking the middle bytes of each nibble of IV, - * pressing them in order to a single byte, and dividing that by 10 (rounded - * down/floor). This will create a value from 0 to 25 that is a 1:1 mapping - * of the English alphabet and is how Unown forms are represented. - * - * C integer division truncates to 0 rather than does any proper rounding. - * - * https://bulbapedia.bulbagarden.net/wiki/Individual_values#Unown's_letter - */ -static uint8_t unown_ivs_get(PokemonData* pdata) { - furi_assert(pdata); - uint16_t ivs = pokemon_stat_get(pdata, STAT_IV, NONE); - uint8_t ivs_mid; - - ivs_mid = - (((ivs & 0x6000) >> 7) | ((ivs & 0x0600) >> 5) | ((ivs & 0x0060) >> 3) | - ((ivs & 0x0006) >> 1)); - - return ivs_mid; -} - -static void unown_ivs_set(PokemonData* pdata, uint8_t ivs_mid) { - furi_assert(pdata); - uint16_t ivs = pokemon_stat_get(pdata, STAT_IV, NONE); - - /* Clear the middle bits of each nibble */ - ivs &= ~(0x6666); - - /* Set the updated ivs_mid in to those cleared bits */ - ivs |= - (((ivs_mid & 0xC0) << 7) | ((ivs_mid & 0x30) << 5) | ((ivs_mid & 0x0C) << 3) | - ((ivs_mid & 0x03) << 1)); - pokemon_stat_set(pdata, STAT_IV, NONE, ivs); -} - -char unown_form_get(PokemonData* pdata) { - uint8_t form = unown_ivs_get(pdata); - - /* The forumula is specifically the center two bits of each IV slapped - * together and floor(/10) - */ - form /= 10; - form += 'A'; - - return form; -} - -/* Try and get to the desired form by adding/subtracting the current IVs */ -void unown_form_set(PokemonData* pdata, char letter) { - uint8_t ivs = unown_ivs_get(pdata); - uint8_t form; - - letter = toupper(letter); - furi_check(isalpha(letter)); - - while(1) { - form = ((ivs / 10) + 'A'); - if(form == letter) break; - if(form > letter) - ivs--; - else - ivs++; - } - - /* form is now the target letter, set IVs back up */ - unown_ivs_set(pdata, ivs); -}