From c3dc27e37e177675c8a54ef507de48b61ed6da2c Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 28 Feb 2021 15:41:03 +0100 Subject: [PATCH] Add: settings to limit your fast-forward game speed By default this setting is set to 2500% normal game speed. --- 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 50f00805e7..30efc947c1 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -34,7 +34,7 @@ byte _support8bpp; CursorVars _cursor; bool _ctrl_pressed; ///< Is Ctrl pressed? bool _shift_pressed; ///< Is Shift pressed? -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? @@ -1905,3 +1905,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 8695fa0e28..e8f7d0345a 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -54,7 +54,7 @@ extern byte _support8bpp; extern CursorVars _cursor; extern bool _ctrl_pressed; ///< Is Ctrl pressed? extern bool _shift_pressed; ///< Is Shift pressed? -extern byte _fast_forward; +extern uint16 _game_speed; extern bool _left_button_down; extern bool _left_button_clicked; @@ -73,6 +73,7 @@ void HandleTextInput(const char *str, bool marked = false, const char *caret = n void HandleCtrlChanged(); 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 524dbbd2c6..9935f3a568 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1453,6 +1453,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_SOUND_TICKER :News ticker: {STRING2} STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Play sound for summarised news messages diff --git a/src/misc.cpp b/src/misc.cpp index dcb04fa026..c46a1c11d4 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -64,7 +64,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin AllocateMap(size_x, size_y); _pause_mode = PM_UNPAUSED; - _fast_forward = 0; + _game_speed = 100; _tick_counter = 0; _cur_tileloop_tile = 1; _thd.redsq = INVALID_TILE; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 18f7a17b1c..dcfcc9f431 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -208,7 +208,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. }; @@ -2442,8 +2442,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); @@ -2453,7 +2453,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 bec549890c..f89b3f7187 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1468,6 +1468,7 @@ static SettingsContainer &GetSettingsTree() construction->Add(new SettingEntry("gui.default_rail_type")); } + interface->Add(new SettingEntry("gui.fast_forward_speed_limit")); interface->Add(new SettingEntry("gui.autosave")); interface->Add(new SettingEntry("gui.toolbar_pos")); interface->Add(new SettingEntry("gui.statusbar_pos")); diff --git a/src/settings_type.h b/src/settings_type.h index 11298cfa70..f2c591f642 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -148,6 +148,7 @@ struct GUISettings { 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. uint16 console_backlog_timeout; ///< the minimum amount of time items should be in the console backlog before they will be removed in ~3 seconds granularity. uint16 console_backlog_length; ///< the minimum amount of items in the console backlog before items will be removed. diff --git a/src/table/settings.ini b/src/table/settings.ini index 5907c09a72..52602a3dfe 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -3364,6 +3364,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 6a851d2b5d..ea50661e4c 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -283,7 +283,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; } @@ -2127,7 +2128,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); } @@ -2508,7 +2509,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 208de06c4b..a01a9a5e7c 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" @@ -457,17 +456,12 @@ void VideoDriver_Allegro::InputLoop() _shift_pressed = !!(key_shifts & KB_SHIFT_FLAG); #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 dd49cd2110..523a408b1f 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" @@ -420,14 +419,10 @@ void VideoDriver_Cocoa::InputLoop() _shift_pressed = (cur_mods & NSShiftKeyMask) != 0; #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(); } diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index 81d634ce58..22b9dbb1ab 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -277,7 +277,7 @@ void VideoDriver_Dedicated::MainLoop() while (!_exit_game) { 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 af20e8420e..f122a2921b 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" @@ -604,17 +603,12 @@ void VideoDriver_SDL_Base::InputLoop() _shift_pressed = !!(mod & KMOD_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 51327be162..f9ec2a86c4 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" @@ -662,17 +661,12 @@ void VideoDriver_SDL::InputLoop() _shift_pressed = !!(mod & KMOD_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 d528bbec7f..bcd646abdf 100644 --- a/src/video/video_driver.cpp +++ b/src/video/video_driver.cpp @@ -10,6 +10,7 @@ #include "../stdafx.h" #include "../debug.h" #include "../core/random_func.hpp" +#include "../network/network.h" #include "../gfx_func.h" #include "../progress.h" #include "../thread.h" @@ -20,14 +21,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. */ @@ -55,6 +52,16 @@ bool VideoDriver::Tick() while (this->PollEvent()) {} 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(); @@ -67,16 +74,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 2e478def99..938dd84bf3 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 @@ -268,7 +269,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() @@ -278,6 +284,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 131a991f38..d5f752be97 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" @@ -831,17 +830,12 @@ void VideoDriver_Win32Base::InputLoop() _shift_pressed = this->has_focus && GetAsyncKeyState(VK_SHIFT) < 0; #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 (this->has_focus && GetAsyncKeyState(VK_TAB) < 0 && GetAsyncKeyState(VK_MENU) >= 0) + this->fast_forward_key_pressed = this->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 (this->has_focus) {