Add configs for measurement systems and decimal separators (#4183)

* Allow developers to choose metric or imperial, and their decimal seperator of choice for Pokédex entries
- Creates  which cleans up the existing implementing of printing height and weight to the pokedex
- Developers can choose to use metric or imperial units of measurement in the Pokédex
- - Developers can choose to use any character as a decimal seperator in the Pokédex
- Allows users to define units and decimal seperators independently
- Fixes a bug in Lotad / Seedot house

* Fixed compilation issue with agbcc

* Updated to include HGSS Dex and address PR Feedback
This commit is contained in:
psf 2024-02-14 01:17:23 -08:00 committed by GitHub
parent ce99db0086
commit 7f6e1e2aea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 280 additions and 182 deletions

View file

@ -34,16 +34,6 @@
#define LOG_HANDLER (LOG_HANDLER_MGBA_PRINT)
#endif
#define ENGLISH
#ifdef ENGLISH
#define UNITS_IMPERIAL
#define CHAR_DEC_SEPARATOR CHAR_PERIOD // Period is used as a decimal separator only in the UK and the US.
#else
#define UNITS_METRIC
#define CHAR_DEC_SEPARATOR CHAR_COMMA
#endif
// Uncomment to fix some identified minor bugs
#define BUGFIX
@ -81,4 +71,11 @@
#define SUMMARY_SCREEN_NATURE_COLORS TRUE // If TRUE, nature-based stat boosts and reductions will be red and blue in the summary screen.
#define HQ_RANDOM TRUE // If TRUE, replaces the default RNG with an implementation of SFC32 RNG. May break code that relies on RNG.
// Measurement system constants to be used for UNITS
#define UNITS_IMPERIAL 0 // Inches, feet, pounds
#define UNITS_METRIC 1 // meters, kilograms
#define UNITS UNITS_IMPERIAL
#define CHAR_DEC_SEPARATOR CHAR_PERIOD // CHAR_PERIOD is used as a decimal separator only in the UK and the US. The rest of the world uses CHAR_COMMA.
#endif // GUARD_CONFIG_H

View file

@ -1307,4 +1307,24 @@ enum {
#define HOENN_DEX_COUNT (HOENN_DEX_DEOXYS + 1)
#define DECAGRAMS_IN_POUND 4536
#define CM_PER_INCH 2.54
#define CM_PER_INCH_FACTOR (CM_PER_INCH * 100)
#define INCHES_IN_FOOT 12
#define INCHES_IN_ONE_AND_HALF_FOOT (INCHES_IN_FOOT * 1.5)
#define INCHES_IN_FOOT_FACTOR (INCHES_IN_FOOT * 10)
#define WEIGHT_HEIGHT_STR_LEN 16
#define WEIGHT_HEIGHT_STR_MEM (WEIGHT_HEIGHT_STR_LEN * sizeof(u8))
#define DEX_HEADER_X 96
#define DEX_Y_TOP 57
#define DEX_Y_BOTTOM 73
#define DEX_MEASUREMENT_X 129
#define DEX_HGSS_HEADER_X_PADDING 59
#define DEX_HGSS_Y_TOP_PADDING 7
#define DEX_HGSS_Y_BOTTOM_PADDING 4
#define DEX_HGSS_MEASUREMENT_X_PADDING 51
#endif // GUARD_CONSTANTS_POKEDEX_H

View file

@ -29,5 +29,6 @@ bool16 HasAllHoennMons(void);
void ResetPokedexScrollPositions(void);
bool16 HasAllMons(void);
void CB2_OpenPokedex(void);
void PrintMonMeasurements(u16 species, u32 owned);
#endif // GUARD_POKEDEX_H

View file

@ -531,7 +531,9 @@ extern const u8 gText_PokedexRegistration[];
extern const u8 gText_NumberClear01[];
extern const u8 gText_5MarksPokemon[];
extern const u8 gText_UnkHeight[];
extern const u8 gText_UnkHeightMetric[];
extern const u8 gText_UnkWeight[];
extern const u8 gText_UnkWeightMetric[];
extern const u8 gText_HTHeight[];
extern const u8 gText_WTWeight[];
extern const u8 gText_SearchingPleaseWait[];

View file

@ -274,8 +274,19 @@ static void Task_HandleCaughtMonPageInput(u8);
static void Task_ExitCaughtMonPage(u8);
static void SpriteCB_SlideCaughtMonToCenter(struct Sprite *sprite);
static void PrintMonInfo(u32 num, u32, u32 owned, u32 newEntry);
static void PrintMonHeight(u16 height, u8 left, u8 top);
static void PrintMonWeight(u16 weight, u8 left, u8 top);
static u32 GetMeasurementTextPositions(u32 textElement);
static void PrintUnknownMonMeasurements(void);
static u8* GetUnknownMonHeightString(void);
static u8* GetUnknownMonWeightString(void);
static u8* ReplaceDecimalSeparator(const u8* originalString);
static void PrintOwnedMonMeasurements(u16 species);
static void PrintOwnedMonHeight(u16 species);
static void PrintOwnedMonWeight(u16 species);
static u8* ConvertMonHeightToImperialString(u32 height);
static u8* ConvertMonHeightToMetricString(u32 height);
static u8* ConvertMonWeightToImperialString(u32 weight);
static u8* ConvertMonWeightToMetricString(u32 weight);
static u8* ConvertMeasurementToMetricString(u16 num, u32* index);
static void ResetOtherVideoRegisters(u16);
static u8 PrintCryScreenSpeciesName(u8, u16, u8, u8);
static void PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top);
@ -4141,7 +4152,7 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
const u8 *name;
const u8 *category;
const u8 *description;
u8 digitCount = (NATIONAL_DEX_COUNT > 999 && IsNationalPokedexEnabled()) ? 4 : 3;
u8 digitCount = (NATIONAL_DEX_COUNT > 999 && IsNationalPokedexEnabled()) ? 4 : 3;
if (newEntry)
PrintInfoScreenText(gText_PokedexRegistration, GetStringCenterAlignXOffset(FONT_NORMAL, gText_PokedexRegistration, DISPLAY_WIDTH), 0);
@ -4169,18 +4180,7 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
category = gText_5MarksPokemon;
}
PrintInfoScreenText(category, 0x64, 0x29);
PrintInfoScreenText(gText_HTHeight, 0x60, 0x39);
PrintInfoScreenText(gText_WTWeight, 0x60, 0x49);
if (owned)
{
PrintMonHeight(GetSpeciesHeight(species), 0x81, 0x39);
PrintMonWeight(GetSpeciesWeight(species), 0x81, 0x49);
}
else
{
PrintInfoScreenText(gText_UnkHeight, 0x81, 0x39);
PrintInfoScreenText(gText_UnkWeight, 0x81, 0x49);
}
PrintMonMeasurements(species,owned);
if (owned)
description = GetSpeciesPokedexDescription(species);
else
@ -4188,95 +4188,279 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
PrintInfoScreenText(description, GetStringCenterAlignXOffset(FONT_NORMAL, description, DISPLAY_WIDTH), 95);
}
static void PrintMonHeight(u16 height, u8 left, u8 top)
void PrintMonMeasurements(u16 species, u32 owned)
{
u8 buffer[16];
u32 inches, feet;
u8 i = 0;
u32 x = GetMeasurementTextPositions(DEX_HEADER_X);
u32 yTop = GetMeasurementTextPositions(DEX_Y_TOP);
u32 yBottom = GetMeasurementTextPositions(DEX_Y_BOTTOM);
inches = (height * 10000) / 254;
PrintInfoScreenText(gText_HTHeight, x, yTop);
PrintInfoScreenText(gText_WTWeight, x, yBottom);
if (owned)
PrintOwnedMonMeasurements(species);
else
PrintUnknownMonMeasurements();
}
static u32 GetMeasurementTextPositions(u32 textElement)
{
if (!POKEDEX_PLUS_HGSS)
return textElement;
switch(textElement)
{
case DEX_HEADER_X:
return (DEX_HEADER_X + DEX_HGSS_HEADER_X_PADDING);
case DEX_Y_TOP:
return (DEX_Y_TOP + DEX_HGSS_Y_TOP_PADDING);
case DEX_Y_BOTTOM:
return (DEX_Y_BOTTOM + DEX_HGSS_Y_BOTTOM_PADDING);
default:
case DEX_MEASUREMENT_X:
return (DEX_MEASUREMENT_X + DEX_HGSS_MEASUREMENT_X_PADDING);
}
}
static void PrintUnknownMonMeasurements(void)
{
u8* heightString = GetUnknownMonHeightString();
u8* weightString = GetUnknownMonWeightString();
u32 x = GetMeasurementTextPositions(DEX_MEASUREMENT_X);
u32 yTop = GetMeasurementTextPositions(DEX_Y_TOP);
u32 yBottom = GetMeasurementTextPositions(DEX_Y_BOTTOM);
PrintInfoScreenText(heightString, x, yTop);
PrintInfoScreenText(weightString, x, yBottom);
Free(heightString);
Free(weightString);
}
static u8* GetUnknownMonHeightString(void)
{
if (UNITS == UNITS_IMPERIAL)
return ReplaceDecimalSeparator(gText_UnkHeight);
else
return ReplaceDecimalSeparator(gText_UnkHeightMetric);
}
static u8* GetUnknownMonWeightString(void)
{
if (UNITS == UNITS_IMPERIAL)
return ReplaceDecimalSeparator(gText_UnkWeight);
else
return ReplaceDecimalSeparator(gText_UnkWeightMetric);
}
static u8* ReplaceDecimalSeparator(const u8* originalString)
{
bool32 replaced = FALSE;
u32 length = StringLength(originalString), i;
u8* modifiedString = Alloc(WEIGHT_HEIGHT_STR_MEM);
for (i = 0; i < length; i++)
{
if ((originalString[i] != CHAR_PERIOD) || replaced)
{
modifiedString[i] = originalString[i];
continue;
}
modifiedString[i] = CHAR_DEC_SEPARATOR;
replaced = TRUE;
}
modifiedString[length] = EOS;
return modifiedString;
}
static void PrintOwnedMonMeasurements(u16 species)
{
PrintOwnedMonHeight(species);
PrintOwnedMonWeight(species);
}
static void PrintOwnedMonHeight(u16 species)
{
u32 height = GetSpeciesHeight(species);
u8* heightString;
u32 x = GetMeasurementTextPositions(DEX_MEASUREMENT_X);
u32 yTop = GetMeasurementTextPositions(DEX_Y_TOP);
if (UNITS == UNITS_IMPERIAL)
heightString = ConvertMonHeightToImperialString(height);
else
heightString = ConvertMonHeightToMetricString(height);
PrintInfoScreenText(heightString, x, yTop);
Free(heightString);
}
static void PrintOwnedMonWeight(u16 species)
{
u32 weight = GetSpeciesWeight(species);
u8* weightString;
u32 x = GetMeasurementTextPositions(DEX_MEASUREMENT_X);
u32 yBottom = GetMeasurementTextPositions(DEX_Y_BOTTOM);
if (UNITS == UNITS_IMPERIAL)
weightString = ConvertMonWeightToImperialString(weight);
else
weightString = ConvertMonWeightToMetricString(weight);
PrintInfoScreenText(weightString, x, yBottom);
Free(weightString);
}
static u8* ConvertMonHeightToImperialString(u32 height)
{
u8* heightString = Alloc(WEIGHT_HEIGHT_STR_MEM);
u32 inches, feet, index = 0;
inches = (height * 10000) / CM_PER_INCH_FACTOR;
if (inches % 10 >= 5)
inches += 10;
feet = inches / 120;
inches = (inches - (feet * 120)) / 10;
feet = inches / INCHES_IN_FOOT_FACTOR;
inches = (inches - (feet * INCHES_IN_FOOT_FACTOR)) / 10;
buffer[i++] = EXT_CTRL_CODE_BEGIN;
buffer[i++] = EXT_CTRL_CODE_CLEAR_TO;
heightString[index++] = EXT_CTRL_CODE_BEGIN;
heightString[index++] = EXT_CTRL_CODE_CLEAR_TO;
if (feet / 10 == 0)
{
buffer[i++] = 18;
buffer[i++] = feet + CHAR_0;
heightString[index++] = INCHES_IN_ONE_AND_HALF_FOOT;
heightString[index++] = feet + CHAR_0;
}
else
{
buffer[i++] = 12;
buffer[i++] = feet / 10 + CHAR_0;
buffer[i++] = (feet % 10) + CHAR_0;
heightString[index++] = INCHES_IN_FOOT;
heightString[index++] = feet / 10 + CHAR_0;
heightString[index++] = (feet % 10) + CHAR_0;
}
buffer[i++] = CHAR_SGL_QUOTE_RIGHT;
buffer[i++] = (inches / 10) + CHAR_0;
buffer[i++] = (inches % 10) + CHAR_0;
buffer[i++] = CHAR_DBL_QUOTE_RIGHT;
buffer[i++] = EOS;
PrintInfoScreenText(buffer, left, top);
heightString[index++] = CHAR_SGL_QUOTE_RIGHT;
heightString[index++] = (inches / 10) + CHAR_0;
heightString[index++] = (inches % 10) + CHAR_0;
heightString[index++] = CHAR_DBL_QUOTE_RIGHT;
heightString[index++] = EOS;
return heightString;
}
static void PrintMonWeight(u16 weight, u8 left, u8 top)
static u8* ConvertMonHeightToMetricString(u32 height)
{
u8 buffer[16];
bool8 output;
u8 i;
u32 lbs = (weight * 100000) / 4536;
u32 index = 0;
u8* heightString = ConvertMeasurementToMetricString(height, &index);
heightString[index++] = CHAR_m;
heightString[index++] = EOS;
return heightString;
}
static u8* ConvertMonWeightToImperialString(u32 weight)
{
u8* weightString = Alloc(WEIGHT_HEIGHT_STR_MEM);
bool32 output = FALSE;
u32 index = 0, lbs = (weight * 100000) / DECAGRAMS_IN_POUND;
if (lbs % 10u >= 5)
lbs += 10;
i = 0;
output = FALSE;
if ((buffer[i] = (lbs / 100000) + CHAR_0) == CHAR_0 && !output)
if ((weightString[index] = (lbs / 100000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
weightString[index++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
index++;
}
lbs %= 100000;
if ((buffer[i] = (lbs / 10000) + CHAR_0) == CHAR_0 && !output)
if ((weightString[index] = (lbs / 10000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
weightString[index++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
index++;
}
lbs %= 10000;
if ((buffer[i] = (lbs / 1000) + CHAR_0) == CHAR_0 && !output)
if ((weightString[index] = (lbs / 1000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
weightString[index++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
index++;
}
lbs %= 1000;
buffer[i++] = (lbs / 100) + CHAR_0;
weightString[index++] = (lbs / 100) + CHAR_0;
lbs %= 100;
buffer[i++] = CHAR_PERIOD;
buffer[i++] = (lbs / 10) + CHAR_0;
buffer[i++] = CHAR_SPACE;
buffer[i++] = CHAR_l;
buffer[i++] = CHAR_b;
buffer[i++] = CHAR_s;
buffer[i++] = CHAR_PERIOD;
buffer[i++] = EOS;
PrintInfoScreenText(buffer, left, top);
weightString[index++] = CHAR_DEC_SEPARATOR;
weightString[index++] = (lbs / 10) + CHAR_0;
weightString[index++] = CHAR_SPACE;
weightString[index++] = CHAR_l;
weightString[index++] = CHAR_b;
weightString[index++] = CHAR_s;
weightString[index++] = CHAR_PERIOD;
weightString[index++] = EOS;
return weightString;
}
static u8* ConvertMonWeightToMetricString(u32 weight)
{
u32 index = 0;
u8* weightString = ConvertMeasurementToMetricString(weight, &index);
weightString[index++] = CHAR_k;
weightString[index++] = CHAR_g;
weightString[index++] = CHAR_PERIOD;
weightString[index++] = EOS;
return weightString;
}
static u8* ConvertMeasurementToMetricString(u16 num, u32* index)
{
u8* string = Alloc(WEIGHT_HEIGHT_STR_MEM);
bool32 outputted = FALSE;
u32 result;
result = num / 1000;
if (result == 0)
{
string[(*index)++] = CHAR_SPACER;
outputted = FALSE;
}
else
{
string[(*index)++] = CHAR_0 + result;
outputted = TRUE;
}
result = (num % 1000) / 100;
if (result == 0 && !outputted)
{
string[(*index)++] = CHAR_SPACER;
outputted = FALSE;
}
else
{
string[(*index)++] = CHAR_0 + result;
outputted = TRUE;
}
string[(*index)++] = CHAR_0 + ((num % 1000) % 100) / 10;
string[(*index)++] = CHAR_DEC_SEPARATOR;
string[(*index)++] = CHAR_0 + ((num % 1000) % 100) % 10;
string[(*index)++] = CHAR_SPACE;
return string;
}
s8 GetSetPokedexFlag(u16 nationalDexNo, u8 caseID)

View file

@ -536,8 +536,6 @@ static void Task_HandleCaughtMonPageInput(u8);
static void Task_ExitCaughtMonPage(u8);
static void SpriteCB_SlideCaughtMonToCenter(struct Sprite *sprite);
static void PrintMonInfo(u32 num, u32, u32 owned, u32 newEntry);
static void PrintMonHeight(u16 height, u8 left, u8 top);
static void PrintMonWeight(u16 weight, u8 left, u8 top);
static void ResetOtherVideoRegisters(u16);
static u8 PrintCryScreenSpeciesName(u8, u16, u8, u8);
static void PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top);
@ -4487,18 +4485,7 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
category = gText_5MarksPokemon;
}
PrintInfoScreenText(category, 123, 31);
PrintInfoScreenText(gText_HTHeight, 155, 64);
PrintInfoScreenText(gText_WTWeight, 155, 77);
if (owned)
{
PrintMonHeight(GetSpeciesHeight(species), 180, 64);
PrintMonWeight(GetSpeciesWeight(species), 180, 77);
}
else
{
PrintInfoScreenText(gText_UnkHeight, 180, 64);
PrintInfoScreenText(gText_UnkWeight, 180, 77);
}
PrintMonMeasurements(species,owned);
if (owned)
description = GetSpeciesPokedexDescription(species);
else
@ -4510,97 +4497,6 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
PrintCurrentSpeciesTypeInfo(newEntry, species);
}
static void PrintMonHeight(u16 height, u8 left, u8 top)
{
u8 buffer[16];
u32 inches, feet;
u8 i = 0;
inches = (height * 10000) / 254;
if (inches % 10 >= 5)
inches += 10;
feet = inches / 120;
inches = (inches - (feet * 120)) / 10;
buffer[i++] = EXT_CTRL_CODE_BEGIN;
buffer[i++] = EXT_CTRL_CODE_CLEAR_TO;
if (feet / 10 == 0)
{
buffer[i++] = 18;
buffer[i++] = feet + CHAR_0;
}
else
{
buffer[i++] = 12;
buffer[i++] = feet / 10 + CHAR_0;
buffer[i++] = (feet % 10) + CHAR_0;
}
buffer[i++] = CHAR_SGL_QUOTE_RIGHT;
buffer[i++] = (inches / 10) + CHAR_0;
buffer[i++] = (inches % 10) + CHAR_0;
buffer[i++] = CHAR_DBL_QUOTE_RIGHT;
buffer[i++] = EOS;
PrintInfoScreenText(buffer, left, top);
}
static void PrintMonWeight(u16 weight, u8 left, u8 top)
{
u8 buffer[16];
bool8 output;
u8 i;
u32 lbs = (weight * 100000) / 4536;
if (lbs % 10u >= 5)
lbs += 10;
i = 0;
output = FALSE;
if ((buffer[i] = (lbs / 100000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
}
lbs %= 100000;
if ((buffer[i] = (lbs / 10000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
}
lbs %= 10000;
if ((buffer[i] = (lbs / 1000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
}
lbs %= 1000;
buffer[i++] = (lbs / 100) + CHAR_0;
lbs %= 100;
buffer[i++] = CHAR_PERIOD;
buffer[i++] = (lbs / 10) + CHAR_0;
buffer[i++] = CHAR_SPACE;
buffer[i++] = CHAR_l;
buffer[i++] = CHAR_b;
buffer[i++] = CHAR_s;
buffer[i++] = CHAR_PERIOD;
buffer[i++] = EOS;
PrintInfoScreenText(buffer, left, top);
}
// Unused in the English version, used to print height/weight in versions which use metric system.
static void UNUSED PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top)
{
@ -5294,7 +5190,7 @@ static bool8 CalculateMoves(void)
if (j >= NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES)
{
numTutorMoves++;
sStatsMoves[movesTotal] = move;
movesTotal++;
}

View file

@ -47,8 +47,6 @@ static const u8 sGiftRibbonsMonDataIds[GIFT_RIBBONS_COUNT - 4] =
extern const u8 gText_DecimalPoint[];
extern const u8 gText_Marco[];
#define CM_PER_INCH 2.54
static u32 GetMonSizeHash(struct Pokemon *pkmn)
{
u16 personality = GetMonData(pkmn, MON_DATA_PERSONALITY);
@ -95,10 +93,8 @@ static u32 GetMonSize(u16 species, u16 b)
static void FormatMonSizeRecord(u8 *string, u32 size)
{
#ifdef UNITS_IMPERIAL
//Convert size from centimeters to inches
size = (f64)(size * 10) / (CM_PER_INCH * 10);
#endif
size = (f64)(size * 10) / (CM_PER_INCH * 10);
string = ConvertIntToDecimalStringN(string, size / 10, STR_CONV_MODE_LEFT_ALIGN, 8);
string = StringAppend(string, gText_DecimalPoint);

View file

@ -101,7 +101,9 @@ const u8 gText_DefaultNameHalie[] = _("HALIE");
const u8 gText_ThisIsAPokemon[] = _("This is what we call a “POKéMON.”{PAUSE 96}\p");
const u8 gText_5MarksPokemon[] = _("????? POKéMON");
const u8 gText_UnkHeight[] = _("{CLEAR_TO 0x0C}??'??”");
const u8 gText_UnkHeightMetric[] = _("???.? m");
const u8 gText_UnkWeight[] = _("????.? lbs.");
const u8 gText_UnkWeightMetric[] = _("???.? kg.");
const u8 gText_EmptyPkmnCategory[] = _(" POKéMON"); // Unused
const u8 gText_EmptyHeight[] = _("{CLEAR_TO 0x0C} ' ”"); // Unused
const u8 gText_EmptyWeight[] = _(" . lbs."); // Unused