From f183ded9fedbe7d26a55d86fa0aa6ffdfae57140 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 28 Feb 2021 14:41:03 +0000 Subject: [PATCH] Add: settings to limit your fast-forward game speed By default this setting is set to 2500% normal game speed. (cherry picked from commit c3dc27e37e177675c8a54ef507de48b61ed6da2c) # Conflicts: # src/gfx.cpp # src/gfx_func.h # src/settings_type.h # src/video/cocoa/cocoa_v.mm # src/video/video_driver.cpp # src/video/win32_v.cpp --- src/gfx.cpp | 11 ++++++++++- src/gfx_func.h | 3 ++- src/lang/english.txt | 4 ++++ src/misc.cpp | 2 +- src/saveload/saveload.cpp | 8 ++++---- src/settings_gui.cpp | 1 + src/settings_type.h | 1 + src/table/settings.ini | 14 +++++++++++++ src/toolbar_gui.cpp | 7 ++++--- src/video/allegro_v.cpp | 10 ++-------- src/video/cocoa/cocoa_v.mm | 9 ++------- src/video/dedicated_v.cpp | 2 +- src/video/sdl2_v.cpp | 10 ++-------- src/video/sdl_v.cpp | 10 ++-------- src/video/video_driver.cpp | 40 +++++++++++++++++++++----------------- src/video/video_driver.hpp | 11 ++++++++++- src/video/win32_v.cpp | 10 ++-------- 17 files changed, 84 insertions(+), 69 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index 87660d3041..1a51408ebf 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -40,7 +40,7 @@ bool _ctrl_pressed; ///< Is Ctrl pressed? bool _shift_pressed; ///< Is Shift pressed? bool _invert_ctrl; bool _invert_shift; -byte _fast_forward; +uint16 _game_speed = 100; ///< Current game-speed; 100 is 1x, 0 is infinite. 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? @@ -2212,3 +2212,12 @@ void UpdateGUIZoom() _font_zoom = static_cast(_font_zoom_cfg); } } + +void ChangeGameSpeed(bool enable_fast_forward) +{ + if (enable_fast_forward) { + _game_speed = _settings_client.gui.fast_forward_speed_limit; + } else { + _game_speed = 100; + } +} diff --git a/src/gfx_func.h b/src/gfx_func.h index 91cd2ff091..c6c8927b74 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -56,7 +56,7 @@ extern bool _ctrl_pressed; ///< Is Ctrl pressed? extern bool _shift_pressed; ///< Is Shift pressed? extern bool _invert_ctrl; extern bool _invert_shift; -extern byte _fast_forward; +extern uint16 _game_speed; extern bool _left_button_down; extern bool _left_button_clicked; @@ -76,6 +76,7 @@ void HandleCtrlChanged(); void HandleShiftChanged(); void HandleMouseEvents(); void UpdateWindows(); +void ChangeGameSpeed(bool enable_fast_forward); void DrawMouseCursor(); void ScreenSizeChanged(); diff --git a/src/lang/english.txt b/src/lang/english.txt index 1f0362658a..19b4d49524 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1629,6 +1629,10 @@ STR_CONFIG_SETTING_EXPENSES_LAYOUT :Group expenses STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Define the layout for the company expenses window STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Automatically remove signals during rail construction: {STRING2} STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Automatically remove signals during rail construction if the signals are in the way. Note that this can potentially lead to train crashes. +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT :Fast forward speed limit: {STRING2} +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT :Limit on how fast the game goes when fast forward is enabled. 0 = no limit (as fast as your computer allows). Values below 100% slow the game down. The upper-limit depends on the specification of your computer and can vary depending on the game. +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}% normal game speed +STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :No limit (as fast as your computer allows) STR_CONFIG_SETTING_ENABLE_BUILD_RIVER :Enable building rivers: {STRING2} STR_CONFIG_SETTING_ENABLE_BUILD_RIVER_HELPTEXT :Enable building rivers outside of the scenario editor diff --git a/src/misc.cpp b/src/misc.cpp index bfb4342ad1..fd1e1bf78e 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -76,7 +76,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin ClearDesyncMsgLog(); _pause_mode = PM_UNPAUSED; - _fast_forward = 0; + _game_speed = 100; _tick_counter = 0; _tick_skip_counter = 0; _cur_tileloop_tile = 1; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 6ebab2caba..8fcba5a945 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -228,7 +228,7 @@ struct SaveLoadParams { StringID error_str; ///< the translatable error message to show char *extra_msg; ///< the error message - byte ff_state; ///< The state of fast-forward when saving started. + uint16 game_speed; ///< The game speed when saving started. bool saveinprogress; ///< Whether there is currently a save in progress. bool networkserversave; ///< Whether this save is being sent to a network client }; @@ -2907,8 +2907,8 @@ static inline void ClearSaveLoadState() */ static void SaveFileStart() { - _sl.ff_state = _fast_forward; - _fast_forward = 0; + _sl.game_speed = _game_speed; + _game_speed = 100; SetMouseCursorBusy(true); InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START); @@ -2918,7 +2918,7 @@ static void SaveFileStart() /** Update the gui accordingly when saving is done and release locks on saveload. */ static void SaveFileDone() { - if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state; + if (_game_mode != GM_MENU) _game_speed = _sl.game_speed; SetMouseCursorBusy(false); InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH); diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 0af90f06aa..9c59ba677d 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1624,6 +1624,7 @@ static SettingsContainer &GetSettingsTree() advsig->Add(new SettingEntry("gui.show_adv_tracerestrict_features")); } + interface->Add(new SettingEntry("gui.fast_forward_speed_limit")); interface->Add(new SettingEntry("gui.autosave")); interface->Add(new SettingEntry("gui.autosave_on_network_disconnect")); interface->Add(new SettingEntry("gui.savegame_overwrite_confirm")); diff --git a/src/settings_type.h b/src/settings_type.h index fedbad0273..115d709510 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -197,6 +197,7 @@ struct GUISettings : public TimeSettings { bool show_newgrf_name; ///< Show the name of the NewGRF in the build vehicle window bool auto_remove_signals; ///< automatically remove signals when in the way during rail construction uint16 refresh_rate; ///< How often we refresh the screen (time between draw-ticks). + uint16 fast_forward_speed_limit; ///< Game speed to use when fast-forward is enabled. bool show_vehicle_route_steps; ///< when a window related to a specific vehicle is focused, show route steps bool show_vehicle_list_company_colour; ///< show the company colour of vehicles which have an owner different to the owner of the vehicle list bool enable_single_veh_shared_order_gui; ///< enable showing a single vehicle in the shared order GUI window diff --git a/src/table/settings.ini b/src/table/settings.ini index d3c98761b8..bf936f90fa 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -5202,6 +5202,20 @@ max = 1000 cat = SC_EXPERT startup = true +[SDTC_VAR] +var = gui.fast_forward_speed_limit +type = SLE_UINT16 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_0ISDISABLED | SGF_NO_NETWORK +def = 2500 +min = 0 +max = 100000 +interval = 10 +str = STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT +strhelp = STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_HELPTEXT +strval = STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL +cat = SC_BASIC + [SDTC_BOOL] var = sound.news_ticker flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index b944e40754..e1bd4dab5d 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -290,7 +290,8 @@ static CallBackFunction ToolbarPauseClick(Window *w) */ static CallBackFunction ToolbarFastForwardClick(Window *w) { - _fast_forward ^= true; + ChangeGameSpeed(_game_speed == 100); + if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -2177,7 +2178,7 @@ struct MainToolbarWindow : Window { this->SetWidgetDirty(WID_TN_PAUSE); } - if (this->IsWidgetLowered(WID_TN_FAST_FORWARD) != !!_fast_forward) { + if (this->IsWidgetLowered(WID_TN_FAST_FORWARD) != (_game_speed != 100)) { this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD); this->SetWidgetDirty(WID_TN_FAST_FORWARD); } @@ -2564,7 +2565,7 @@ struct ScenarioEditorToolbarWindow : Window { this->SetDirty(); } - if (this->IsWidgetLowered(WID_TE_FAST_FORWARD) != !!_fast_forward) { + if (this->IsWidgetLowered(WID_TE_FAST_FORWARD) != (_game_speed != 100)) { this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD); this->SetDirty(); } diff --git a/src/video/allegro_v.cpp b/src/video/allegro_v.cpp index b74449dc37..23f3b33319 100644 --- a/src/video/allegro_v.cpp +++ b/src/video/allegro_v.cpp @@ -19,7 +19,6 @@ #include "../gfx_func.h" #include "../rev.h" #include "../blitter/factory.hpp" -#include "../network/network.h" #include "../core/random_func.hpp" #include "../core/math_func.hpp" #include "../framerate_type.h" @@ -455,17 +454,12 @@ void VideoDriver_Allegro::InputLoop() _shift_pressed = !!(key_shifts & KB_SHIFT_FLAG) != _invert_shift; #if defined(_DEBUG) - if (_shift_pressed) + this->fast_forward_key_pressed = _shift_pressed; #else /* Speedup when pressing tab, except when using ALT+TAB * to switch to another application. */ - if (key[KEY_TAB] && (key_shifts & KB_ALT_FLAG) == 0) + this->fast_forward_key_pressed = key[KEY_TAB] && (key_shifts & KB_ALT_FLAG) == 0; #endif - { - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } /* Determine which directional keys are down. */ _dirkeys = diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 629b9fe7f2..9c60989483 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -33,7 +33,6 @@ #include "cocoa_wnd.h" #include "../../blitter/factory.hpp" #include "../../framerate_type.h" -#include "../../network/network.h" #include "../../gfx_func.h" #include "../../thread.h" #include "../../core/random_func.hpp" @@ -606,14 +605,10 @@ void VideoDriver_Cocoa::InputLoop() _shift_pressed = ((cur_mods & NSShiftKeyMask) != 0) != _invert_shift; #if defined(_DEBUG) - if (_shift_pressed) { + this->fast_forward_key_pressed = _shift_pressed; #else - if (_tab_is_down) { + this->fast_forward_key_pressed = _tab_is_down; #endif - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); if (old_shift_pressed != _shift_pressed) HandleShiftChanged(); diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index df3c413673..d264e7c940 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -279,7 +279,7 @@ void VideoDriver_Dedicated::MainLoop() if (!_dedicated_forks) DedicatedHandleKeyInput(); - _fast_forward = _ddc_fastforward; + ChangeGameSpeed(_ddc_fastforward); this->Tick(); this->SleepTillNextTick(); } diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 4f06c6ebb3..2f823a4b20 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -12,7 +12,6 @@ #include "../gfx_func.h" #include "../rev.h" #include "../blitter/factory.hpp" -#include "../network/network.h" #include "../thread.h" #include "../progress.h" #include "../core/random_func.hpp" @@ -1076,17 +1075,12 @@ void VideoDriver_SDL::InputLoop() _shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift; #if defined(_DEBUG) - if (_shift_pressed) + this->fast_forward_key_pressed = _shift_pressed; #else /* Speedup when pressing tab, except when using ALT+TAB * to switch to another application. */ - if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0) + this->fast_forward_key_pressed = keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0; #endif /* defined(_DEBUG) */ - { - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } /* Determine which directional keys are down. */ _dirkeys = diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp index 89ec78964a..f6b2dd6cac 100644 --- a/src/video/sdl_v.cpp +++ b/src/video/sdl_v.cpp @@ -14,7 +14,6 @@ #include "../gfx_func.h" #include "../rev.h" #include "../blitter/factory.hpp" -#include "../network/network.h" #include "../thread.h" #include "../progress.h" #include "../core/random_func.hpp" @@ -668,17 +667,12 @@ void VideoDriver_SDL::InputLoop() _shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift; #if defined(_DEBUG) - if (_shift_pressed) + this->fast_forward_key_pressed = _shift_pressed; #else /* Speedup when pressing tab, except when using ALT+TAB * to switch to another application. */ - if (keys[SDLK_TAB] && (mod & KMOD_ALT) == 0) + this->fast_forward_key_pressed = keys[SDLK_TAB] && (mod & KMOD_ALT) == 0; #endif /* defined(_DEBUG) */ - { - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } /* Determine which directional keys are down. */ _dirkeys = diff --git a/src/video/video_driver.cpp b/src/video/video_driver.cpp index d769651245..7bbf088f47 100644 --- a/src/video/video_driver.cpp +++ b/src/video/video_driver.cpp @@ -9,6 +9,7 @@ #include "../stdafx.h" #include "../debug.h" +#include "../network/network.h" #include "../gfx_func.h" #include "../progress.h" #include "../thread.h" @@ -19,14 +20,10 @@ bool VideoDriver::Tick() { auto cur_ticks = std::chrono::steady_clock::now(); - if (cur_ticks >= this->next_game_tick || (_fast_forward && !_pause_mode)) { - if (_fast_forward && !_pause_mode) { - this->next_game_tick = cur_ticks + this->GetGameInterval(); - } else { - this->next_game_tick += this->GetGameInterval(); - /* Avoid next_game_tick getting behind more and more if it cannot keep up. */ - if (this->next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) this->next_game_tick = cur_ticks; - } + if (cur_ticks >= this->next_game_tick) { + this->next_game_tick += this->GetGameInterval(); + /* Avoid next_game_tick getting behind more and more if it cannot keep up. */ + if (this->next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) this->next_game_tick = cur_ticks; /* The game loop is the part that can run asynchronously. * The rest except sleeping can't. */ @@ -50,6 +47,16 @@ bool VideoDriver::Tick() if (this->next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) this->next_draw_tick = cur_ticks; this->InputLoop(); + + /* Check if the fast-forward button is still pressed. */ + if (fast_forward_key_pressed && !_networking && _game_mode != GM_MENU) { + ChangeGameSpeed(true); + this->fast_forward_via_key = true; + } else if (this->fast_forward_via_key) { + ChangeGameSpeed(false); + this->fast_forward_via_key = false; + } + ::InputLoop(); UpdateWindows(); this->CheckPaletteAnim(); @@ -62,16 +69,13 @@ bool VideoDriver::Tick() void VideoDriver::SleepTillNextTick() { - /* If we are not in fast-forward, create some time between calls to ease up CPU usage. */ - if (!_fast_forward || _pause_mode) { - /* See how much time there is till we have to process the next event, and try to hit that as close as possible. */ - auto next_tick = std::min(this->next_draw_tick, this->next_game_tick); - auto now = std::chrono::steady_clock::now(); + /* See how much time there is till we have to process the next event, and try to hit that as close as possible. */ + auto next_tick = std::min(this->next_draw_tick, this->next_game_tick); + auto now = std::chrono::steady_clock::now(); - if (next_tick > now) { - this->UnlockVideoBuffer(); - std::this_thread::sleep_for(next_tick - now); - this->LockVideoBuffer(); - } + if (next_tick > now) { + this->UnlockVideoBuffer(); + std::this_thread::sleep_for(next_tick - now); + this->LockVideoBuffer(); } } diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp index fad40b4e65..5bb9a61467 100644 --- a/src/video/video_driver.hpp +++ b/src/video/video_driver.hpp @@ -13,6 +13,7 @@ #include "../driver.h" #include "../core/geometry_type.hpp" #include "../core/math_func.hpp" +#include "../gfx_func.h" #include "../settings_type.h" #include "../zoom_type.h" #include @@ -202,7 +203,12 @@ protected: std::chrono::steady_clock::duration GetGameInterval() { - return std::chrono::milliseconds(MILLISECONDS_PER_TICK); + /* If we are paused, run on normal speed. */ + if (_pause_mode) return std::chrono::milliseconds(MILLISECONDS_PER_TICK); + /* Infinite speed, as quickly as you can. */ + if (_game_speed == 0) return std::chrono::microseconds(0); + + return std::chrono::microseconds(MILLISECONDS_PER_TICK * 1000 * 100 / _game_speed); } std::chrono::steady_clock::duration GetDrawInterval() @@ -212,6 +218,9 @@ protected: std::chrono::steady_clock::time_point next_game_tick; std::chrono::steady_clock::time_point next_draw_tick; + + bool fast_forward_key_pressed; ///< The fast-forward key is being pressed. + bool fast_forward_via_key; ///< The fast-forward was enabled by key press. }; #endif /* VIDEO_VIDEO_DRIVER_HPP */ diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 8b384ecb36..6734f73023 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -13,7 +13,6 @@ #include "../os/windows/win32.h" #include "../rev.h" #include "../blitter/factory.hpp" -#include "../network/network.h" #include "../core/geometry_func.hpp" #include "../core/math_func.hpp" #include "../core/random_func.hpp" @@ -911,17 +910,12 @@ void VideoDriver_Win32Base::InputLoop() _shift_pressed = (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0) != _invert_shift; #if defined(_DEBUG) - if (_shift_pressed) + this->fast_forward_key_pressed = _shift_pressed; #else /* Speedup when pressing tab, except when using ALT+TAB * to switch to another application. */ - if (_wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0 && GetAsyncKeyState(VK_MENU) >= 0) + this->fast_forward_key_pressed = _wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0 && GetAsyncKeyState(VK_MENU) >= 0; #endif - { - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } /* Determine which directional keys are down. */ if (_wnd.has_focus) {