forked from flipperdevices/flipperzero-firmware
-
-
Notifications
You must be signed in to change notification settings - Fork 540
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
attribute: combine calculated attributes to single file
Handles gender, pokerus, shiny, and unown form Signed-off-by: Kris Bahnsen <[email protected]>
- Loading branch information
1 parent
eafd365
commit aca6bdf
Showing
15 changed files
with
289 additions
and
325 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
#include <stdint.h> | ||
#include <src/include/pokemon_app.h> | ||
#include <src/include/pokemon_data.h> | ||
#include <src/include/pokemon_attribute.h> | ||
|
||
|
||
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); | ||
} |
Oops, something went wrong.