From 5dd99fb046921933375333e470ed7906a11ddc2a Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 22 May 2023 18:40:46 +0100 Subject: [PATCH] Add setting for milliseconds per game tick mode --- src/date_type.h | 4 ++-- src/economy_type.h | 7 +++++++ src/framerate_gui.cpp | 6 ++---- src/gfx.cpp | 8 ++++++++ src/gfx_func.h | 3 +++ src/gfx_type.h | 8 ++++++-- src/lang/extra/english.txt | 5 +++++ src/openttd.cpp | 4 +++- src/saveload/afterload.cpp | 6 ++++++ src/saveload/extended_ver_sl.cpp | 1 + src/saveload/extended_ver_sl.h | 1 + src/settings_gui.cpp | 1 + src/settings_type.h | 1 + src/table/settings/settings.ini | 15 +++++++++++++++ 14 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/date_type.h b/src/date_type.h index 8542128cd2..8ecadfcf12 100644 --- a/src/date_type.h +++ b/src/date_type.h @@ -24,8 +24,8 @@ typedef uint8 Day; ///< Type for the day of the month, note: 1 based, first d /** * 1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885. On * an overflow the new day begun and 65535 / 885 = 74. - * 1 tick is approximately 30 ms. - * 1 day is thus about 2 seconds (74 * 30 = 2220) on a machine that can run OpenTTD normally + * 1 tick is approximately 27 ms. + * 1 day is thus about 2 seconds (74 * 27 = 1998) on a machine that can run OpenTTD normally */ static const int DAY_TICKS = 74; ///< ticks per day static const int DAYS_IN_YEAR = 365; ///< days per year diff --git a/src/economy_type.h b/src/economy_type.h index 7cbeb72d2f..3a994d6451 100644 --- a/src/economy_type.h +++ b/src/economy_type.h @@ -241,4 +241,11 @@ enum CargoPaymentAlgorithm : byte { CPA_END, ///< Used for iterations and limit testing }; +enum TickRateMode : byte { + TRM_BEGIN = 0, ///< Used for iterations and limit testing + TRM_TRADITIONAL = 0, ///< Traditional value (30ms) + TRM_MODERN, ///< Modern value (27ms) + TRM_END, ///< Used for iterations and limit testing +}; + #endif /* ECONOMY_TYPE_H */ diff --git a/src/framerate_gui.cpp b/src/framerate_gui.cpp index 86d46b9ad4..75286d9688 100644 --- a/src/framerate_gui.cpp +++ b/src/framerate_gui.cpp @@ -183,16 +183,13 @@ namespace { } }; - /** %Game loop rate, cycles per second */ - static const double GL_RATE = 1000.0 / MILLISECONDS_PER_TICK; - /** * Storage for all performance element measurements. * Elements are initialized with the expected rate in recorded values per second. * @hideinitializer */ PerformanceData _pf_data[PFE_MAX] = { - PerformanceData(GL_RATE), // PFE_GAMELOOP + PerformanceData(1), // PFE_GAMELOOP PerformanceData(1), // PFE_ACC_GL_ECONOMY PerformanceData(1), // PFE_ACC_GL_TRAINS PerformanceData(1), // PFE_ACC_GL_ROADVEHS @@ -479,6 +476,7 @@ struct FramerateWindow : Window { void UpdateData() { + _pf_data[PFE_GAMELOOP].expected_rate = _ticks_per_second; double gl_rate = _pf_data[PFE_GAMELOOP].GetRate(); bool have_script = false; this->rate_gameloop.SetRate(gl_rate, _pf_data[PFE_GAMELOOP].expected_rate); diff --git a/src/gfx.cpp b/src/gfx.cpp index df6bc0116f..edbb80d007 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -46,6 +46,8 @@ bool _shift_pressed; ///< Is Shift pressed? bool _invert_ctrl; bool _invert_shift; uint16 _game_speed = 100; ///< Current game-speed; 100 is 1x, 0 is infinite. +uint8 _milliseconds_per_tick = 27; ///< Milliseconds per tick +float _ticks_per_second; ///< Ticks per second bool _left_button_down; ///< Is left mouse button pressed? bool _left_button_clicked; ///< Is left mouse button clicked? bool _right_button_down; ///< Is right mouse button pressed? @@ -2439,3 +2441,9 @@ void ChangeGameSpeed(bool enable_fast_forward) _game_speed = 100; } } + +void SetupTickRate() +{ + _milliseconds_per_tick = (_settings_game.economy.tick_rate == TRM_MODERN) ? 27 : 30; + _ticks_per_second = 1000.0f / _milliseconds_per_tick; +} diff --git a/src/gfx_func.h b/src/gfx_func.h index a6446cd583..23259e5e77 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -56,6 +56,8 @@ extern bool _shift_pressed; ///< Is Shift pressed? extern bool _invert_ctrl; extern bool _invert_shift; extern uint16 _game_speed; +extern uint8 _milliseconds_per_tick; +extern float _ticks_per_second; extern bool _left_button_down; extern bool _left_button_clicked; @@ -79,6 +81,7 @@ void HandleShiftChanged(); void HandleMouseEvents(); void UpdateWindows(); void ChangeGameSpeed(bool enable_fast_forward); +void SetupTickRate(); void DrawMouseCursor(); void ScreenSizeChanged(); diff --git a/src/gfx_type.h b/src/gfx_type.h index 00fb951351..919be84485 100644 --- a/src/gfx_type.h +++ b/src/gfx_type.h @@ -317,8 +317,12 @@ enum SpriteType : byte { ST_INVALID = 4, ///< Pseudosprite or other unusable sprite, used only internally }; -/** The number of milliseconds per game tick. */ -static const uint MILLISECONDS_PER_TICK = 30; +/** + * The number of milliseconds per game tick. + * The value 27 together with a day length of 74 ticks makes one day 1998 milliseconds, almost exactly 2 seconds. + * With a 2 second day, one standard month is 1 minute, and one standard year is slightly over 12 minutes. + */ +#define MILLISECONDS_PER_TICK ((uint)_milliseconds_per_tick) /** Information about the currently used palette. */ struct Palette { diff --git a/src/lang/extra/english.txt b/src/lang/extra/english.txt index c8cc9d00c6..912dff4a0d 100644 --- a/src/lang/extra/english.txt +++ b/src/lang/extra/english.txt @@ -599,6 +599,11 @@ STR_CONFIG_SETTING_CARGO_PAYMENT_ALGORITHM_HELPTEXT :The algorithm t STR_CONFIG_SETTING_CARGO_PAYMENT_ALGORITHM_TRADITIONAL :Traditional STR_CONFIG_SETTING_CARGO_PAYMENT_ALGORITHM_MODERN :Modern +STR_CONFIG_SETTING_TICK_RATE :Game tick rate: {STRING2} +STR_CONFIG_SETTING_TICK_RATE_HELPTEXT :Number of milliseconds per game tick. +STR_CONFIG_SETTING_TICK_RATE_TRADITIONAL :30 ms/tick (traditional) +STR_CONFIG_SETTING_TICK_RATE_MODERN :27 ms/tick (modern) + STR_CONFIG_SETTING_TOWN_MIN_DISTANCE :Minimum distance between towns: {STRING2} STR_CONFIG_SETTING_TOWN_MIN_DISTANCE_HELPTEXT :Set the minimum distance in tiles between towns for map generation and random founding diff --git a/src/openttd.cpp b/src/openttd.cpp index 87c4ab56e8..a03ed219ce 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -568,6 +568,8 @@ void MakeNewgameSettingsLive() if (_settings_newgame.game_config != nullptr) { _settings_game.game_config = new GameConfig(_settings_newgame.game_config); } + + SetupTickRate(); } void OpenBrowser(const char *url) @@ -2027,7 +2029,7 @@ void StateGameLoop() _scaled_date_ticks++; // This must update in lock-step with _tick_skip_counter, such that it always matches what SetScaledTickVariables would return. if (_settings_client.gui.autosave == 6 && !(_game_mode == GM_MENU || _game_mode == GM_BOOTSTRAP) && - (_scaled_date_ticks % (_settings_client.gui.autosave_custom_minutes * (60000 / MILLISECONDS_PER_TICK))) == 0) { + (_scaled_date_ticks % (_settings_client.gui.autosave_custom_minutes * (_settings_game.economy.tick_rate == TRM_MODERN ? (60000 / 27) : (60000 / 30)))) == 0) { _do_autosave = true; _check_special_modes = true; SetWindowDirty(WC_STATUS_BAR, 0); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 843135dcdd..bc0142a15c 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -4191,6 +4191,10 @@ bool AfterLoadGame() _settings_game.economy.payment_algorithm = IsSavegameVersionBefore(SLV_MORE_CARGO_AGE) ? CPA_TRADITIONAL : CPA_MODERN; } + if (SlXvIsFeatureMissing(XSLFI_VARIABLE_TICK_RATE)) { + _settings_game.economy.tick_rate = IsSavegameVersionUntil(SLV_MORE_CARGO_AGE) ? TRM_TRADITIONAL : TRM_MODERN; + } + InitializeRoadGUI(); /* This needs to be done after conversion. */ @@ -4207,6 +4211,8 @@ bool AfterLoadGame() GamelogPrintDebug(1); + SetupTickRate(); + InitializeWindowsAndCaches(); /* Restore the signals */ ResetSignalHandlers(); diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index b01aa14183..ca4d5f6047 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -188,6 +188,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_MULTI_CARGO_SHIPS, XSCF_NULL, 1, 1, "multi_cargo_ships", nullptr, nullptr, nullptr }, { XSLFI_REMAIN_NEXT_ORDER_STATION, XSCF_IGNORABLE_UNKNOWN, 1, 1, "remain_next_order_station", nullptr, nullptr, nullptr }, { XSLFI_LABEL_ORDERS, XSCF_NULL, 2, 2, "label_orders", nullptr, nullptr, nullptr }, + { XSLFI_VARIABLE_TICK_RATE, XSCF_IGNORABLE_ALL, 1, 1, "variable_tick_rate", nullptr, nullptr, nullptr }, { XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr }, { XSLFI_U64_TICK_COUNTER, XSCF_NULL, 1, 1, "u64_tick_counter", nullptr, nullptr, nullptr }, { XSLFI_LINKGRAPH_TRAVEL_TIME, XSCF_NULL, 1, 1, "linkgraph_travel_time", nullptr, nullptr, nullptr }, diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index 08f1c4c42d..48761631e2 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -139,6 +139,7 @@ enum SlXvFeatureIndex { XSLFI_MULTI_CARGO_SHIPS, ///< Multi-cargo ships XSLFI_REMAIN_NEXT_ORDER_STATION, ///< Remain in station if next order is for same station XSLFI_LABEL_ORDERS, ///< Label orders + XSLFI_VARIABLE_TICK_RATE, ///< Variable tick rate XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64 XSLFI_U64_TICK_COUNTER, ///< See: SLV_U64_TICK_COUNTER diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index d46188e400..2777dab433 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -2295,6 +2295,7 @@ static SettingsContainer &GetSettingsTree() environment->Add(new SettingEntry("station.catchment_increase")); environment->Add(new SettingEntry("station.cargo_class_rating_wait_time")); environment->Add(new SettingEntry("station.station_size_rating_cargo_amount")); + environment->Add(new SettingEntry("economy.tick_rate")); } SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI)); diff --git a/src/settings_type.h b/src/settings_type.h index fa020d33cd..3784fbe2d1 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -706,6 +706,7 @@ struct EconomySettings { uint16 random_road_reconstruction; ///< chance out of 1000 per tile loop for towns to start random road re-construction bool disable_inflation_newgrf_flag; ///< Disable NewGRF inflation flag CargoPaymentAlgorithm payment_algorithm; ///< Cargo payment algorithm + TickRateMode tick_rate; ///< Tick rate mode }; struct LinkGraphSettings { diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index 4dc949d018..7f29a3a333 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -3251,6 +3251,21 @@ strval = STR_CONFIG_SETTING_CARGO_PAYMENT_ALGORITHM_TRADITIONAL cat = SC_BASIC patxname = ""economy.payment_algorithm"" +[SDT_VAR] +var = economy.tick_rate +type = SLE_UINT8 +flags = SF_GUI_DROPDOWN +def = TRM_TRADITIONAL +min = TRM_BEGIN +max = TRM_END - 1 +interval = 1 +str = STR_CONFIG_SETTING_TICK_RATE +strhelp = STR_CONFIG_SETTING_TICK_RATE_HELPTEXT +strval = STR_CONFIG_SETTING_TICK_RATE_TRADITIONAL +cat = SC_EXPERT +post_cb = [](auto) { SetupTickRate(); } +patxname = ""economy.tick_rate"" + ## [SDT_VAR] var = pf.wait_for_pbs_path