From 83d6f1ad5ec77c146eae92af505da46038e33605 Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Sat, 16 Sep 2023 08:35:05 -0400 Subject: [PATCH] Feature: Wallclock timekeeping --- src/lang/english.txt | 6 ++++++ src/saveload/afterload.cpp | 3 +++ src/saveload/saveload.h | 1 + src/settings_gui.cpp | 1 + src/settings_type.h | 7 +++++++ src/table/settings/economy_settings.ini | 12 ++++++++++++ src/timer/timer_game_economy.cpp | 12 ++++++++++++ src/timer/timer_game_economy.h | 1 + 8 files changed, 43 insertions(+) diff --git a/src/lang/english.txt b/src/lang/english.txt index 35600f0b19..c4c9b2e025 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1455,6 +1455,12 @@ STR_CONFIG_SETTING_WARN_INCOME_LESS_HELPTEXT :When enabled, a STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES :Vehicles never expire: {STRING2} STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT :When enabled, all vehicle models remain available forever after their introduction +STR_CONFIG_SETTING_TIMEKEEPING_UNITS :Timekeeping: {STRING2} +STR_CONFIG_SETTING_TIMEKEEPING_UNITS_HELPTEXT :Select the timekeeping units of the game. This cannot be changed later.{}{}Calendar-based is the classic OpenTTD experience, with a year consisting of 12 months, and each month having 28-31 days.{}{}In Wallclock-based time, vehicle movement, cargo production, and financials are instead based on one-minute increments, which is about as long as a 30 day month takes in Calendar-based mode. These are grouped into 12-minute periods, equivalent to a year in Calendar-based mode.{}{}In either mode there is always a classic calendar, which is used for introduction dates of vehicles, houses, and other infrastructure. +###length 2 +STR_CONFIG_SETTING_TIMEKEEPING_UNITS_CALENDAR :Calendar +STR_CONFIG_SETTING_TIMEKEEPING_UNITS_WALLCLOCK :Wallclock + STR_CONFIG_SETTING_AUTORENEW_VEHICLE :Autorenew vehicle when it gets old: {STRING2} STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT :When enabled, a vehicle nearing its end of life gets automatically replaced when the renew conditions are fulfilled diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index cbebf87329..31052fcc52 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -735,6 +735,9 @@ bool AfterLoadGame() * must be done before loading sprites as some newgrfs check it */ TimerGameCalendar::SetDate(TimerGameCalendar::date, TimerGameCalendar::date_fract); + /* Only new games can use wallclock units. */ + if (IsSavegameVersionBefore(SLV_ECONOMY_MODE_TIMEKEEPING_UNITS)) _settings_game.economy.timekeeping_units = TKU_CALENDAR; + /* Update economy year. If we don't have a separate economy date saved, follow the calendar date. */ if (IsSavegameVersionBefore(SLV_ECONOMY_DATE)) { TimerGameEconomy::SetDate(TimerGameCalendar::date.base(), TimerGameCalendar::date_fract); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 97625fb482..912aac6c97 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -369,6 +369,7 @@ enum SaveLoadVersion : uint16_t { SLV_WATER_REGION_EVAL_SIMPLIFIED, ///< 325 PR#11750 Simplified Water Region evaluation. SLV_ECONOMY_DATE, ///< 326 PR#10700 Split calendar and economy timers and dates. + SLV_ECONOMY_MODE_TIMEKEEPING_UNITS, ///< 327 PR#11341 Mode to display economy measurements in wallclock units. SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 15519b62f5..1e20918a5c 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -2015,6 +2015,7 @@ static SettingsContainer &GetSettingsTree() { SettingsPage *time = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TIME)); { + time->Add(new SettingEntry("economy.timekeeping_units")); time->Add(new SettingEntry("game_creation.ending_year")); time->Add(new SettingEntry("gui.pause_on_newgame")); time->Add(new SettingEntry("gui.fast_forward_speed_limit")); diff --git a/src/settings_type.h b/src/settings_type.h index b90eaacab3..82efe5fd39 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -64,6 +64,12 @@ enum IndustryDensity { ID_END, ///< Number of industry density settings. }; +/** Possible values for the "timekeeping_units" setting. */ +enum TimekeepingUnits : uint8_t { + TKU_CALENDAR = 0, + TKU_WALLCLOCK, +}; + /** Possible values for "use_relay_service" setting. */ enum UseRelayService : uint8_t { URS_NEVER = 0, @@ -551,6 +557,7 @@ struct EconomySettings { uint16_t town_noise_population[4]; ///< population to base decision on noise evaluation (@see town_council_tolerance) bool allow_town_level_crossings; ///< towns are allowed to build level crossings bool infrastructure_maintenance; ///< enable monthly maintenance fee for owner infrastructure + TimekeepingUnits timekeeping_units; ///< time units to use for the game economy, either calendar or wallclock }; struct LinkGraphSettings { diff --git a/src/table/settings/economy_settings.ini b/src/table/settings/economy_settings.ini index 8456fa6030..4737befc0a 100644 --- a/src/table/settings/economy_settings.ini +++ b/src/table/settings/economy_settings.ini @@ -280,3 +280,15 @@ str = STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE strhelp = STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT post_cb = [](auto) { InvalidateWindowClassesData(WC_COMPANY_INFRASTRUCTURE); } cat = SC_BASIC + +[SDT_VAR] +var = economy.timekeeping_units +type = SLE_UINT8 +flags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY | SF_SCENEDIT_TOO +def = TKU_CALENDAR +min = TKU_CALENDAR +max = TKU_WALLCLOCK +str = STR_CONFIG_SETTING_TIMEKEEPING_UNITS +strval = STR_CONFIG_SETTING_TIMEKEEPING_UNITS_CALENDAR +strhelp = STR_CONFIG_SETTING_TIMEKEEPING_UNITS_HELPTEXT +cat = SC_BASIC diff --git a/src/timer/timer_game_economy.cpp b/src/timer/timer_game_economy.cpp index 28ef7b4c70..3ce004bae6 100644 --- a/src/timer/timer_game_economy.cpp +++ b/src/timer/timer_game_economy.cpp @@ -54,6 +54,18 @@ TimerGameEconomy::DateFract TimerGameEconomy::date_fract = {}; TimerGameEconomy::month = ymd.month; } +/** + * Check if we are using wallclock units. + * @param newgame Should we check the settings for a new game (since we are in the main menu)? + * @return True if the game is using wallclock units, or false if the game is using calendar units. + */ +/* static */ bool TimerGameEconomy::UsingWallclockUnits(bool newgame) +{ + if (newgame) return (_settings_newgame.economy.timekeeping_units == TKU_WALLCLOCK); + + return (_settings_game.economy.timekeeping_units == TKU_WALLCLOCK); +} + template<> void IntervalTimer::Elapsed(TimerGameEconomy::TElapsed trigger) { diff --git a/src/timer/timer_game_economy.h b/src/timer/timer_game_economy.h index 14a693e512..4c723c0fd4 100644 --- a/src/timer/timer_game_economy.h +++ b/src/timer/timer_game_economy.h @@ -38,6 +38,7 @@ public: static DateFract date_fract; ///< Fractional part of the day. static void SetDate(Date date, DateFract fract); + static bool UsingWallclockUnits(bool newgame = false); }; /**