From 6d45c487ed0192e8403f44ac279d44d4a5930bbf Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Sun, 5 Mar 2023 15:38:34 -0500 Subject: [PATCH] Codechange: Add string control codes for wallclock mode --- src/lang/english.txt | 7 +++++ src/strgen/strgen_base.cpp | 27 +++++++++++++++++ src/strings.cpp | 61 ++++++++++++++++++++++++++++++++++++++ src/table/control_codes.h | 6 ++++ src/table/strgen_tables.h | 8 +++++ 5 files changed, 109 insertions(+) diff --git a/src/lang/english.txt b/src/lang/english.txt index c4c9b2e025..e8cace4b89 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -255,10 +255,17 @@ STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +# Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}day{P "" s} STR_UNITS_SECONDS :{COMMA}{NBSP}second{P "" s} STR_UNITS_TICKS :{COMMA}{NBSP}tick{P "" s} +STR_UNITS_MONTHS :{NUM}{NBSP}month{P "" s} +STR_UNITS_MINUTES :{NUM}{NBSP}minute{P "" s} + +STR_UNITS_YEARS :{NUM}{NBSP}year{P "" s} +STR_UNITS_PERIODS :{NUM}{NBSP}period{P "" s} + # Common window strings STR_LIST_FILTER_TITLE :{BLACK}Filter: STR_LIST_FILTER_OSKTITLE :{BLACK}Enter one or more keywords to filter the list for diff --git a/src/strgen/strgen_base.cpp b/src/strgen/strgen_base.cpp index 8edcfb3d52..f4d888c2b2 100644 --- a/src/strgen/strgen_base.cpp +++ b/src/strgen/strgen_base.cpp @@ -377,6 +377,33 @@ void EmitPlural(Buffer *buffer, char *buf, int) EmitWordList(buffer, words, nw); } +/** + * Handle the selection of timekeeping units based on the timekeeping setting. + * This uses the string control character {TKM [value if calendar] [value if wallclock]}, e.g. {TKM month minute}. + * @param buffer The output buffer + * @param buf The input buffer + * @param Unused + */ +void EmitTKM(Buffer* buffer, char* buf, int) +{ + /* The correct number of words is 2, but we'll check for more in case of typos. */ + std::vector words(3, nullptr); + + /* Parse each string. */ + uint nw = 0; + for (nw = 0; nw < 3; nw++) { + words[nw] = ParseWord(&buf); + if (words[nw] == nullptr) break; + } + + /* Warn about the wrong number of parameters. */ + if (nw != 2) { + StrgenFatal("%s: Invalid number of TKM options. Expecting %d, found %d.", _cur_ident, 2, nw); + } + + buffer->AppendUtf8(SCC_TIMEKEEPING_MODE_LIST); + EmitWordList(buffer, words, 2); +} void EmitGender(Buffer *buffer, char *buf, int) { diff --git a/src/strings.cpp b/src/strings.cpp index ba12476434..af23786050 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -802,6 +802,30 @@ static const Units _units_height[] = { { { 1.0 }, STR_UNITS_HEIGHT_SI, 0 }, }; +/** Unit conversions for time in calendar days or wallclock seconds */ +static const Units _units_time_days_or_seconds[] = { + { { 1 }, STR_UNITS_DAYS, 0 }, + { { 2 }, STR_UNITS_SECONDS, 0 }, +}; + +/** Unit conversions for time in calendar months or wallclock minutes */ +static const Units _units_time_months_or_minutes[] = { + { { 1 }, STR_UNITS_MONTHS, 0 }, + { { 1 }, STR_UNITS_MINUTES, 0 }, +}; + +/** Unit conversions for time in calendar years or economic periods */ +static const Units _units_time_years_or_periods[] = { + { { 1 }, STR_UNITS_YEARS, 0 }, + { { 1 }, STR_UNITS_PERIODS, 0 }, +}; + +/** Unit conversions for time in calendar years or wallclock minutes */ +static const Units _units_time_years_or_minutes[] = { + { { 1 }, STR_UNITS_YEARS, 0 }, + { { 12 }, STR_UNITS_MINUTES, 0 }, +}; + /** * Get index for velocity conversion units for a vehicle type. * @param type VehicleType to convert velocity for. @@ -1374,6 +1398,43 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara break; } + case SCC_UNITS_DAYS_OR_SECONDS: { // {UNITS_DAYS_OR_SECONDS} + uint8_t realtime = TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU); + const auto &x = _units_time_days_or_seconds[realtime]; + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); + FormatString(builder, GetStringPtr(x.s), tmp_params); + break; + } + + case SCC_UNITS_MONTHS_OR_MINUTES: { // {UNITS_MONTHS_OR_MINUTES} + uint8_t realtime = TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU); + const auto &x = _units_time_months_or_minutes[realtime]; + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); + FormatString(builder, GetStringPtr(x.s), tmp_params); + break; + } + + case SCC_UNITS_YEARS_OR_PERIODS: { // {UNITS_YEARS_OR_PERIODS} + uint8_t realtime = TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU); + const auto &x = _units_time_years_or_periods[realtime]; + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); + FormatString(builder, GetStringPtr(x.s), tmp_params); + break; + } + + case SCC_UNITS_YEARS_OR_MINUTES: { // {UNITS_YEARS_OR_MINUTES} + uint8_t realtime = TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU); + const auto &x = _units_time_years_or_minutes[realtime]; + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); + FormatString(builder, GetStringPtr(x.s), tmp_params); + break; + } + + case SCC_TIMEKEEPING_MODE_LIST: { // {TKM} + str = ParseStringChoice(str, (uint8_t)TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU), builder); + break; + } + case SCC_COMPANY_NAME: { // {COMPANY} const Company *c = Company::GetIfValid(args.GetNextParameter()); if (c == nullptr) break; diff --git a/src/table/control_codes.h b/src/table/control_codes.h index 5ef2b02a60..c79264a265 100644 --- a/src/table/control_codes.h +++ b/src/table/control_codes.h @@ -65,6 +65,12 @@ enum StringControlCode { SCC_VELOCITY, SCC_HEIGHT, + SCC_UNITS_DAYS_OR_SECONDS, + SCC_UNITS_MONTHS_OR_MINUTES, + SCC_UNITS_YEARS_OR_PERIODS, + SCC_UNITS_YEARS_OR_MINUTES, + SCC_TIMEKEEPING_MODE_LIST, + SCC_DATE_TINY, SCC_DATE_SHORT, SCC_DATE_LONG, diff --git a/src/table/strgen_tables.h b/src/table/strgen_tables.h index 60fcf80060..4685eaa627 100644 --- a/src/table/strgen_tables.h +++ b/src/table/strgen_tables.h @@ -30,6 +30,7 @@ struct CmdStruct { }; extern void EmitSingleChar(Buffer *buffer, char *buf, int value); +extern void EmitTKM(Buffer* buffer, char* buf, int value); extern void EmitPlural(Buffer *buffer, char *buf, int value); extern void EmitGender(Buffer *buffer, char *buf, int value); @@ -88,6 +89,13 @@ static const CmdStruct _cmd_structs[] = { {"VELOCITY", EmitSingleChar, SCC_VELOCITY, 1, 0, C_NONE}, {"HEIGHT", EmitSingleChar, SCC_HEIGHT, 1, 0, C_NONE}, + {"UNITS_DAYS_OR_SECONDS", EmitSingleChar, SCC_UNITS_DAYS_OR_SECONDS, 1, 0, C_NONE}, + {"UNITS_MONTHS_OR_MINUTES", EmitSingleChar, SCC_UNITS_MONTHS_OR_MINUTES, 1, 0, C_NONE}, + {"UNITS_YEARS_OR_PERIODS", EmitSingleChar, SCC_UNITS_YEARS_OR_PERIODS, 1, 0, C_NONE}, + {"UNITS_YEARS_OR_MINUTES", EmitSingleChar, SCC_UNITS_YEARS_OR_MINUTES, 1, 0, C_NONE}, + + {"TKM", EmitTKM, 0, 0, -1, C_DONTCOUNT}, // Timekeeping mode string selection, e.g. "{TKM month minute}" + {"P", EmitPlural, 0, 0, -1, C_DONTCOUNT}, // plural specifier {"G", EmitGender, 0, 0, -1, C_DONTCOUNT}, // gender specifier