diff options
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/settings.cpp | 449 | ||||
-rw-r--r-- | src/settings_table.cpp | 473 | ||||
-rw-r--r-- | src/settings_table.h | 38 | ||||
-rw-r--r-- | src/table/settings/company_settings.ini | 2 | ||||
-rw-r--r-- | src/table/settings/currency_settings.ini | 2 | ||||
-rw-r--r-- | src/table/settings/gameopt_settings.ini | 7 | ||||
-rw-r--r-- | src/table/settings/misc_settings.ini | 2 | ||||
-rw-r--r-- | src/table/settings/network_private_settings.ini | 2 | ||||
-rw-r--r-- | src/table/settings/network_secrets_settings.ini | 2 | ||||
-rw-r--r-- | src/table/settings/network_settings.ini | 2 | ||||
-rw-r--r-- | src/table/settings/settings.ini | 2 | ||||
-rw-r--r-- | src/table/settings/win32_settings.ini | 2 | ||||
-rw-r--r-- | src/table/settings/window_settings.ini | 2 |
14 files changed, 529 insertions, 458 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 801a92cb3..631eaf6de 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -338,6 +338,8 @@ add_files( settings_gui.cpp settings_gui.h settings_internal.h + settings_table.h + settings_table.cpp settings_type.h ship.h ship_cmd.cpp diff --git a/src/settings.cpp b/src/settings.cpp index 64ce47828..a2ab8ae33 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -22,62 +22,31 @@ */ #include "stdafx.h" -#include <array> #include <charconv> -#include <limits> +#include "settings_table.h" +#include "debug.h" #include "currency.h" -#include "screenshot.h" #include "network/network.h" #include "network/network_func.h" -#include "settings_internal.h" #include "command_func.h" #include "console_func.h" -#include "pathfinder/pathfinder_type.h" #include "genworld.h" -#include "train.h" -#include "news_func.h" #include "window_func.h" -#include "sound_func.h" #include "company_func.h" #include "rev.h" -#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) -#include "fontcache.h" -#endif -#include "textbuf_gui.h" -#include "rail_gui.h" -#include "elrail_func.h" #include "error.h" -#include "town.h" -#include "video/video_driver.hpp" -#include "sound/sound_driver.hpp" -#include "music/music_driver.hpp" -#include "blitter/factory.hpp" -#include "base_media_base.h" #include "gamelog.h" #include "settings_func.h" #include "ini_type.h" #include "ai/ai_config.hpp" -#include "ai/ai.hpp" #include "game/game_config.hpp" -#include "game/game.hpp" -#include "ship.h" -#include "smallmap_gui.h" -#include "roadveh.h" +#include "newgrf_config.h" #include "fios.h" -#include "strings_func.h" -#include "vehicle_func.h" +#include "fileio_func.h" #include "saveload/compat/settings_sl_compat.h" -#include "void_map.h" -#include "station_base.h" - -#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) -#define HAS_TRUETYPE_FONT -#endif - #include "table/strings.h" -#include "table/settings.h" #include "safeguards.h" @@ -92,8 +61,6 @@ std::string _secrets_file; ///< Secrets configuration file of OpenTTD. typedef std::list<ErrorMessageData> ErrorList; static ErrorList _settings_error_list; ///< Errors while loading minimal settings. -typedef span<const SettingVariant> SettingTable; - /** * List of all the generic setting tables. * @@ -865,227 +832,6 @@ const StringSettingDesc *SettingDesc::AsStringSetting() const return static_cast<const StringSettingDesc *>(this); } -/* Begin - Callback Functions for the various settings. */ - -/** Reposition the main toolbar as the setting changed. */ -static void v_PositionMainToolbar(int32 new_value) -{ - if (_game_mode != GM_MENU) PositionMainToolbar(nullptr); -} - -/** Reposition the statusbar as the setting changed. */ -static void v_PositionStatusbar(int32 new_value) -{ - if (_game_mode != GM_MENU) { - PositionStatusbar(nullptr); - PositionNewsMessage(nullptr); - PositionNetworkChatWindow(nullptr); - } -} - -/** - * Redraw the smallmap after a colour scheme change. - * @param p1 Callback parameter. - */ -static void RedrawSmallmap(int32 new_value) -{ - BuildLandLegend(); - BuildOwnerLegend(); - SetWindowClassesDirty(WC_SMALLMAP); -} - -static void StationSpreadChanged(int32 p1) -{ - InvalidateWindowData(WC_SELECT_STATION, 0); - InvalidateWindowData(WC_BUILD_STATION, 0); -} - -static void CloseSignalGUI(int32 new_value) -{ - if (new_value == 0) { - CloseWindowByClass(WC_BUILD_SIGNAL); - } -} - -static void UpdateConsists(int32 new_value) -{ - for (Train *t : Train::Iterate()) { - /* Update the consist of all trains so the maximum speed is set correctly. */ - if (t->IsFrontEngine() || t->IsFreeWagon()) t->ConsistChanged(CCF_TRACK); - } - InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0); -} - -/* Check service intervals of vehicles, newvalue is value of % or day based servicing */ -static void UpdateAllServiceInterval(int32 new_value) -{ - bool update_vehicles; - VehicleDefaultSettings *vds; - if (_game_mode == GM_MENU || !Company::IsValidID(_current_company)) { - vds = &_settings_client.company.vehicle; - update_vehicles = false; - } else { - vds = &Company::Get(_current_company)->settings.vehicle; - update_vehicles = true; - } - - if (new_value != 0) { - vds->servint_trains = 50; - vds->servint_roadveh = 50; - vds->servint_aircraft = 50; - vds->servint_ships = 50; - } else { - vds->servint_trains = 150; - vds->servint_roadveh = 150; - vds->servint_aircraft = 100; - vds->servint_ships = 360; - } - - if (update_vehicles) { - const Company *c = Company::Get(_current_company); - for (Vehicle *v : Vehicle::Iterate()) { - if (v->owner == _current_company && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) { - v->SetServiceInterval(CompanyServiceInterval(c, v->type)); - v->SetServiceIntervalIsPercent(new_value != 0); - } - } - } - - SetWindowClassesDirty(WC_VEHICLE_DETAILS); -} - -static bool CanUpdateServiceInterval(VehicleType type, int32 &new_value) -{ - VehicleDefaultSettings *vds; - if (_game_mode == GM_MENU || !Company::IsValidID(_current_company)) { - vds = &_settings_client.company.vehicle; - } else { - vds = &Company::Get(_current_company)->settings.vehicle; - } - - /* Test if the interval is valid */ - int32 interval = GetServiceIntervalClamped(new_value, vds->servint_ispercent); - return interval == new_value; -} - -static void UpdateServiceInterval(VehicleType type, int32 new_value) -{ - if (_game_mode != GM_MENU && Company::IsValidID(_current_company)) { - for (Vehicle *v : Vehicle::Iterate()) { - if (v->owner == _current_company && v->type == type && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) { - v->SetServiceInterval(new_value); - } - } - } - - SetWindowClassesDirty(WC_VEHICLE_DETAILS); -} - -static void TrainAccelerationModelChanged(int32 new_value) -{ - for (Train *t : Train::Iterate()) { - if (t->IsFrontEngine()) { - t->tcache.cached_max_curve_speed = t->GetCurveSpeedLimit(); - t->UpdateAcceleration(); - } - } - - /* These windows show acceleration values only when realistic acceleration is on. They must be redrawn after a setting change. */ - SetWindowClassesDirty(WC_ENGINE_PREVIEW); - InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0); - SetWindowClassesDirty(WC_VEHICLE_DETAILS); -} - -/** - * This function updates the train acceleration cache after a steepness change. - * @param new_value Unused new value of setting. - */ -static void TrainSlopeSteepnessChanged(int32 new_value) -{ - for (Train *t : Train::Iterate()) { - if (t->IsFrontEngine()) t->CargoChanged(); - } -} - -/** - * This function updates realistic acceleration caches when the setting "Road vehicle acceleration model" is set. - * @param new_value Unused new value of setting. - */ -static void RoadVehAccelerationModelChanged(int32 new_value) -{ - if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) { - for (RoadVehicle *rv : RoadVehicle::Iterate()) { - if (rv->IsFrontEngine()) { - rv->CargoChanged(); - } - } - } - - /* These windows show acceleration values only when realistic acceleration is on. They must be redrawn after a setting change. */ - SetWindowClassesDirty(WC_ENGINE_PREVIEW); - InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0); - SetWindowClassesDirty(WC_VEHICLE_DETAILS); -} - -/** - * This function updates the road vehicle acceleration cache after a steepness change. - * @param new_value Unused new value of setting. - */ -static void RoadVehSlopeSteepnessChanged(int32 new_value) -{ - for (RoadVehicle *rv : RoadVehicle::Iterate()) { - if (rv->IsFrontEngine()) rv->CargoChanged(); - } -} - -static void TownFoundingChanged(int32 new_value) -{ - if (_game_mode != GM_EDITOR && _settings_game.economy.found_town == TF_FORBIDDEN) { - CloseWindowById(WC_FOUND_TOWN, 0); - } else { - InvalidateWindowData(WC_FOUND_TOWN, 0); - } -} - -static void ZoomMinMaxChanged(int32 new_value) -{ - extern void ConstrainAllViewportsZoom(); - ConstrainAllViewportsZoom(); - GfxClearSpriteCache(); - if (_settings_client.gui.zoom_min > _gui_zoom) { - /* Restrict GUI zoom if it is no longer available. */ - _gui_zoom = _settings_client.gui.zoom_min; - UpdateCursorSize(); - LoadStringWidthTable(); - } -} - -static void SpriteZoomMinChanged(int32 new_value) -{ - GfxClearSpriteCache(); - /* Force all sprites to redraw at the new chosen zoom level */ - MarkWholeScreenDirty(); -} - -/** - * Update any possible saveload window and delete any newgrf dialogue as - * its widget parts might change. Reinit all windows as it allows access to the - * newgrf debug button. - * @param new_value unused. - */ -static void InvalidateNewGRFChangeWindows(int32 new_value) -{ - InvalidateWindowClassesData(WC_SAVELOAD); - CloseWindowByClass(WC_GAME_OPTIONS); - ReInitAllWindows(_gui_zoom_cfg); -} - -static void InvalidateCompanyLiveryWindow(int32 new_value) -{ - InvalidateWindowClassesData(WC_COMPANY_COLOUR, -1); - ResetVehicleColourMap(); -} - /** Checks if any settings are set to incorrect values, and sets them to correct values in that case. */ static void ValidateSettings() { @@ -1096,193 +842,6 @@ static void ValidateSettings() } } -static void DifficultyNoiseChange(int32 new_value) -{ - if (_game_mode == GM_NORMAL) { - UpdateAirportsNoise(); - if (_settings_game.economy.station_noise_level) { - InvalidateWindowClassesData(WC_TOWN_VIEW, 0); - } - } -} - -static void MaxNoAIsChange(int32 new_value) -{ - if (GetGameSettings().difficulty.max_no_competitors != 0 && - AI::GetInfoList()->size() == 0 && - (!_networking || _network_server)) { - ShowErrorMessage(STR_WARNING_NO_SUITABLE_AI, INVALID_STRING_ID, WL_CRITICAL); - } - - InvalidateWindowClassesData(WC_GAME_OPTIONS, 0); -} - -/** - * Check whether the road side may be changed. - * @param new_value unused - * @return true if the road side may be changed. - */ -static bool CheckRoadSide(int32 &new_value) -{ - extern bool RoadVehiclesAreBuilt(); - return _game_mode == GM_MENU || !RoadVehiclesAreBuilt(); -} - -/** - * Conversion callback for _gameopt_settings_game.landscape - * It converts (or try) between old values and the new ones, - * without losing initial setting of the user - * @param value that was read from config file - * @return the "hopefully" converted value - */ -static size_t ConvertLandscape(const char *value) -{ - /* try with the old values */ - static std::vector<std::string> _old_landscape_values{"normal", "hilly", "desert", "candy"}; - return OneOfManySettingDesc::ParseSingleValue(value, strlen(value), _old_landscape_values); -} - -static bool CheckFreeformEdges(int32 &new_value) -{ - if (_game_mode == GM_MENU) return true; - if (new_value != 0) { - for (Ship *s : Ship::Iterate()) { - /* Check if there is a ship on the northern border. */ - if (TileX(s->tile) == 0 || TileY(s->tile) == 0) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_EMPTY, INVALID_STRING_ID, WL_ERROR); - return false; - } - } - for (const BaseStation *st : BaseStation::Iterate()) { - /* Check if there is a non-deleted buoy on the northern border. */ - if (st->IsInUse() && (TileX(st->xy) == 0 || TileY(st->xy) == 0)) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_EMPTY, INVALID_STRING_ID, WL_ERROR); - return false; - } - } - } else { - for (uint i = 0; i < MapMaxX(); i++) { - if (TileHeight(TileXY(i, 1)) != 0) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); - return false; - } - } - for (uint i = 1; i < MapMaxX(); i++) { - if (!IsTileType(TileXY(i, MapMaxY() - 1), MP_WATER) || TileHeight(TileXY(1, MapMaxY())) != 0) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); - return false; - } - } - for (uint i = 0; i < MapMaxY(); i++) { - if (TileHeight(TileXY(1, i)) != 0) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); - return false; - } - } - for (uint i = 1; i < MapMaxY(); i++) { - if (!IsTileType(TileXY(MapMaxX() - 1, i), MP_WATER) || TileHeight(TileXY(MapMaxX(), i)) != 0) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); - return false; - } - } - } - return true; -} - -static void UpdateFreeformEdges(int32 new_value) -{ - if (_game_mode == GM_MENU) return; - - if (new_value != 0) { - for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0)); - for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y)); - } else { - /* Make tiles at the border water again. */ - for (uint i = 0; i < MapMaxX(); i++) { - SetTileHeight(TileXY(i, 0), 0); - SetTileType(TileXY(i, 0), MP_WATER); - } - for (uint i = 0; i < MapMaxY(); i++) { - SetTileHeight(TileXY(0, i), 0); - SetTileType(TileXY(0, i), MP_WATER); - } - } - MarkWholeScreenDirty(); -} - -/** - * Changing the setting "allow multiple NewGRF sets" is not allowed - * if there are vehicles. - */ -static bool CheckDynamicEngines(int32 &new_value) -{ - if (_game_mode == GM_MENU) return true; - - if (!EngineOverrideManager::ResetToCurrentNewGRFConfig()) { - ShowErrorMessage(STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES, INVALID_STRING_ID, WL_ERROR); - return false; - } - - return true; -} - -static bool CheckMaxHeightLevel(int32 &new_value) -{ - if (_game_mode == GM_NORMAL) return false; - if (_game_mode != GM_EDITOR) return true; - - /* Check if at least one mountain on the map is higher than the new value. - * If yes, disallow the change. */ - for (TileIndex t = 0; t < MapSize(); t++) { - if ((int32)TileHeight(t) > new_value) { - ShowErrorMessage(STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN, INVALID_STRING_ID, WL_ERROR); - /* Return old, unchanged value */ - return false; - } - } - - return true; -} - -static void StationCatchmentChanged(int32 new_value) -{ - Station::RecomputeCatchmentForAll(); - MarkWholeScreenDirty(); -} - -static void MaxVehiclesChanged(int32 new_value) -{ - InvalidateWindowClassesData(WC_BUILD_TOOLBAR); - MarkWholeScreenDirty(); -} - -static void InvalidateShipPathCache(int32 new_value) -{ - for (Ship *s : Ship::Iterate()) { - s->path.clear(); - } -} - -/** - * Replace a passwords that are a literal asterisk with an empty string. - * @param newval The new string value for this password field. - * @return Always true. - */ -static bool ReplaceAsteriskWithEmptyPassword(std::string &newval) -{ - if (newval.compare("*") == 0) newval.clear(); - return true; -} - -/** Update the game info, and send it to the clients when we are running as a server. */ -static void UpdateClientConfigValues() -{ - NetworkServerUpdateGameInfo(); - if (_network_server) NetworkServerSendConfigUpdate(); -} - -/* End - Callback Functions */ - /** * Prepare for reading and old diff_custom by zero-ing the memory. */ diff --git a/src/settings_table.cpp b/src/settings_table.cpp new file mode 100644 index 000000000..bc1e588cd --- /dev/null +++ b/src/settings_table.cpp @@ -0,0 +1,473 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * @file settings_table.cpp The tables of all the settings as well as the implementation of most of their callbacks. + */ + +#include "stdafx.h" +#include "settings_table.h" +#include "currency.h" +#include "screenshot.h" +#include "network/network.h" +#include "network/network_func.h" +#include "pathfinder/pathfinder_type.h" +#include "genworld.h" +#include "train.h" +#include "news_func.h" +#include "window_func.h" +#include "company_func.h" +#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) +#define HAS_TRUETYPE_FONT +#include "fontcache.h" +#endif +#include "textbuf_gui.h" +#include "rail_gui.h" +#include "elrail_func.h" +#include "error.h" +#include "town.h" +#include "video/video_driver.hpp" +#include "sound/sound_driver.hpp" +#include "music/music_driver.hpp" +#include "blitter/factory.hpp" +#include "base_media_base.h" +#include "ai/ai_config.hpp" +#include "ai/ai.hpp" +#include "game/game_config.hpp" +#include "ship.h" +#include "smallmap_gui.h" +#include "roadveh.h" +#include "vehicle_func.h" +#include "void_map.h" + +#include "table/strings.h" +#include "table/settings.h" + +#include "safeguards.h" + +SettingTable _settings{ _settings_table }; +SettingTable _network_settings{ _network_settings_table }; +SettingTable _network_private_settings{ _network_private_settings_table }; +SettingTable _network_secrets_settings{ _network_secrets_settings_table }; + +SettingTable _company_settings{ _company_settings_table }; +SettingTable _currency_settings{ _currency_settings_table }; +SettingTable _gameopt_settings{ _gameopt_settings_table }; +SettingTable _misc_settings{ _misc_settings_table }; +SettingTable _window_settings{ _window_settings_table }; +#if defined(_WIN32) && !defined(DEDICATED) +SettingTable _win32_settings{ _win32_settings_table }; +#endif /* _WIN32 */ + + +/* Begin - Callback Functions for the various settings. */ + +/** Reposition the main toolbar as the setting changed. */ +static void v_PositionMainToolbar(int32 new_value) +{ + if (_game_mode != GM_MENU) PositionMainToolbar(nullptr); +} + +/** Reposition the statusbar as the setting changed. */ +static void v_PositionStatusbar(int32 new_value) +{ + if (_game_mode != GM_MENU) { + PositionStatusbar(nullptr); + PositionNewsMessage(nullptr); + PositionNetworkChatWindow(nullptr); + } +} + +/** + * Redraw the smallmap after a colour scheme change. + * @param p1 Callback parameter. + */ +static void RedrawSmallmap(int32 new_value) +{ + BuildLandLegend(); + BuildOwnerLegend(); + SetWindowClassesDirty(WC_SMALLMAP); +} + +static void StationSpreadChanged(int32 p1) +{ + InvalidateWindowData(WC_SELECT_STATION, 0); + InvalidateWindowData(WC_BUILD_STATION, 0); +} + +static void CloseSignalGUI(int32 new_value) +{ + if (new_value == 0) { + CloseWindowByClass(WC_BUILD_SIGNAL); + } +} + +static void UpdateConsists(int32 new_value) +{ + for (Train *t : Train::Iterate()) { + /* Update the consist of all trains so the maximum speed is set correctly. */ + if (t->IsFrontEngine() || t->IsFreeWagon()) t->ConsistChanged(CCF_TRACK); + } + InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0); +} + +/* Check service intervals of vehicles, newvalue is value of % or day based servicing */ +static void UpdateAllServiceInterval(int32 new_value) +{ + bool update_vehicles; + VehicleDefaultSettings *vds; + if (_game_mode == GM_MENU || !Company::IsValidID(_current_company)) { + vds = &_settings_client.company.vehicle; + update_vehicles = false; + } else { + vds = &Company::Get(_current_company)->settings.vehicle; + update_vehicles = true; + } + + if (new_value != 0) { + vds->servint_trains = 50; + vds->servint_roadveh = 50; + vds->servint_aircraft = 50; + vds->servint_ships = 50; + } else { + vds->servint_trains = 150; + vds->servint_roadveh = 150; + vds->servint_aircraft = 100; + vds->servint_ships = 360; + } + + if (update_vehicles) { + const Company *c = Company::Get(_current_company); + for (Vehicle *v : Vehicle::Iterate()) { + if (v->owner == _current_company && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) { + v->SetServiceInterval(CompanyServiceInterval(c, v->type)); + v->SetServiceIntervalIsPercent(new_value != 0); + } + } + } + + SetWindowClassesDirty(WC_VEHICLE_DETAILS); +} + +static bool CanUpdateServiceInterval(VehicleType type, int32 &new_value) +{ + VehicleDefaultSettings *vds; + if (_game_mode == GM_MENU || !Company::IsValidID(_current_company)) { + vds = &_settings_client.company.vehicle; + } else { + vds = &Company::Get(_current_company)->settings.vehicle; + } + + /* Test if the interval is valid */ + int32 interval = GetServiceIntervalClamped(new_value, vds->servint_ispercent); + return interval == new_value; +} + +static void UpdateServiceInterval(VehicleType type, int32 new_value) +{ + if (_game_mode != GM_MENU && Company::IsValidID(_current_company)) { + for (Vehicle *v : Vehicle::Iterate()) { + if (v->owner == _current_company && v->type == type && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) { + v->SetServiceInterval(new_value); + } + } + } + + SetWindowClassesDirty(WC_VEHICLE_DETAILS); +} + +static void TrainAccelerationModelChanged(int32 new_value) +{ + for (Train *t : Train::Iterate()) { + if (t->IsFrontEngine()) { + t->tcache.cached_max_curve_speed = t->GetCurveSpeedLimit(); + t->UpdateAcceleration(); + } + } + + /* These windows show acceleration values only when realistic acceleration is on. They must be redrawn after a setting change. */ + SetWindowClassesDirty(WC_ENGINE_PREVIEW); + InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0); + SetWindowClassesDirty(WC_VEHICLE_DETAILS); +} + +/** + * This function updates the train acceleration cache after a steepness change. + * @param new_value Unused new value of setting. + */ +static void TrainSlopeSteepnessChanged(int32 new_value) +{ + for (Train *t : Train::Iterate()) { + if (t->IsFrontEngine()) t->CargoChanged(); + } +} + +/** + * This function updates realistic acceleration caches when the setting "Road vehicle acceleration model" is set. + * @param new_value Unused new value of setting. + */ +static void RoadVehAccelerationModelChanged(int32 new_value) +{ + if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) { + for (RoadVehicle *rv : RoadVehicle::Iterate()) { + if (rv->IsFrontEngine()) { + rv->CargoChanged(); + } + } + } + + /* These windows show acceleration values only when realistic acceleration is on. They must be redrawn after a setting change. */ + SetWindowClassesDirty(WC_ENGINE_PREVIEW); + InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0); + SetWindowClassesDirty(WC_VEHICLE_DETAILS); +} + +/** + * This function updates the road vehicle acceleration cache after a steepness change. + * @param new_value Unused new value of setting. + */ +static void RoadVehSlopeSteepnessChanged(int32 new_value) +{ + for (RoadVehicle *rv : RoadVehicle::Iterate()) { + if (rv->IsFrontEngine()) rv->CargoChanged(); + } +} + +static void TownFoundingChanged(int32 new_value) +{ + if (_game_mode != GM_EDITOR && _settings_game.economy.found_town == TF_FORBIDDEN) { + CloseWindowById(WC_FOUND_TOWN, 0); + } else { + InvalidateWindowData(WC_FOUND_TOWN, 0); + } +} + +static void ZoomMinMaxChanged(int32 new_value) +{ + extern void ConstrainAllViewportsZoom(); + ConstrainAllViewportsZoom(); + GfxClearSpriteCache(); + if (_settings_client.gui.zoom_min > _gui_zoom) { + /* Restrict GUI zoom if it is no longer available. */ + _gui_zoom = _settings_client.gui.zoom_min; + UpdateCursorSize(); + LoadStringWidthTable(); + } +} + +static void SpriteZoomMinChanged(int32 new_value) +{ + GfxClearSpriteCache(); + /* Force all sprites to redraw at the new chosen zoom level */ + MarkWholeScreenDirty(); +} + +/** + * Update any possible saveload window and delete any newgrf dialogue as + * its widget parts might change. Reinit all windows as it allows access to the + * newgrf debug button. + * @param new_value unused. + */ +static void InvalidateNewGRFChangeWindows(int32 new_value) +{ + InvalidateWindowClassesData(WC_SAVELOAD); + CloseWindowByClass(WC_GAME_OPTIONS); + ReInitAllWindows(_gui_zoom_cfg); +} + +static void InvalidateCompanyLiveryWindow(int32 new_value) +{ + InvalidateWindowClassesData(WC_COMPANY_COLOUR, -1); + ResetVehicleColourMap(); +} + +static void DifficultyNoiseChange(int32 new_value) +{ + if (_game_mode == GM_NORMAL) { + UpdateAirportsNoise(); + if (_settings_game.economy.station_noise_level) { + InvalidateWindowClassesData(WC_TOWN_VIEW, 0); + } + } +} + +static void MaxNoAIsChange(int32 new_value) +{ + if (GetGameSettings().difficulty.max_no_competitors != 0 && + AI::GetInfoList()->size() == 0 && + (!_networking || _network_server)) { + ShowErrorMessage(STR_WARNING_NO_SUITABLE_AI, INVALID_STRING_ID, WL_CRITICAL); + } + + InvalidateWindowClassesData(WC_GAME_OPTIONS, 0); +} + +/** + * Check whether the road side may be changed. + * @param new_value unused + * @return true if the road side may be changed. + */ +static bool CheckRoadSide(int32 &new_value) +{ + extern bool RoadVehiclesAreBuilt(); + return _game_mode == GM_MENU || !RoadVehiclesAreBuilt(); +} + +/** + * Conversion callback for _gameopt_settings_game.landscape + * It converts (or try) between old values and the new ones, + * without losing initial setting of the user + * @param value that was read from config file + * @return the "hopefully" converted value + */ +static size_t ConvertLandscape(const char *value) +{ + /* try with the old values */ + static std::vector<std::string> _old_landscape_values{"normal", "hilly", "desert", "candy"}; + return OneOfManySettingDesc::ParseSingleValue(value, strlen(value), _old_landscape_values); +} + +static bool CheckFreeformEdges(int32 &new_value) +{ + if (_game_mode == GM_MENU) return true; + if (new_value != 0) { + for (Ship *s : Ship::Iterate()) { + /* Check if there is a ship on the northern border. */ + if (TileX(s->tile) == 0 || TileY(s->tile) == 0) { + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_EMPTY, INVALID_STRING_ID, WL_ERROR); + return false; + } + } + for (const BaseStation *st : BaseStation::Iterate()) { + /* Check if there is a non-deleted buoy on the northern border. */ + if (st->IsInUse() && (TileX(st->xy) == 0 || TileY(st->xy) == 0)) { + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_EMPTY, INVALID_STRING_ID, WL_ERROR); + return false; + } + } + } else { + for (uint i = 0; i < MapMaxX(); i++) { + if (TileHeight(TileXY(i, 1)) != 0) { + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); + return false; + } + } + for (uint i = 1; i < MapMaxX(); i++) { + if (!IsTileType(TileXY(i, MapMaxY() - 1), MP_WATER) || TileHeight(TileXY(1, MapMaxY())) != 0) { + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); + return false; + } + } + for (uint i = 0; i < MapMaxY(); i++) { + if (TileHeight(TileXY(1, i)) != 0) { + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); + return false; + } + } + for (uint i = 1; i < MapMaxY(); i++) { + if (!IsTileType(TileXY(MapMaxX() - 1, i), MP_WATER) || TileHeight(TileXY(MapMaxX(), i)) != 0) { + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); + return false; + } + } + } + return true; +} + +static void UpdateFreeformEdges(int32 new_value) +{ + if (_game_mode == GM_MENU) return; + + if (new_value != 0) { + for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0)); + for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y)); + } else { + /* Make tiles at the border water again. */ + for (uint i = 0; i < MapMaxX(); i++) { + SetTileHeight(TileXY(i, 0), 0); + SetTileType(TileXY(i, 0), MP_WATER); + } + for (uint i = 0; i < MapMaxY(); i++) { + SetTileHeight(TileXY(0, i), 0); + SetTileType(TileXY(0, i), MP_WATER); + } + } + MarkWholeScreenDirty(); +} + +/** + * Changing the setting "allow multiple NewGRF sets" is not allowed + * if there are vehicles. + */ +static bool CheckDynamicEngines(int32 &new_value) +{ + if (_game_mode == GM_MENU) return true; + + if (!EngineOverrideManager::ResetToCurrentNewGRFConfig()) { + ShowErrorMessage(STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES, INVALID_STRING_ID, WL_ERROR); + return false; + } + + return true; +} + +static bool CheckMaxHeightLevel(int32 &new_value) +{ + if (_game_mode == GM_NORMAL) return false; + if (_game_mode != GM_EDITOR) return true; + + /* Check if at least one mountain on the map is higher than the new value. + * If yes, disallow the change. */ + for (TileIndex t = 0; t < MapSize(); t++) { + if ((int32)TileHeight(t) > new_value) { + ShowErrorMessage(STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN, INVALID_STRING_ID, WL_ERROR); + /* Return old, unchanged value */ + return false; + } + } + + return true; +} + +static void StationCatchmentChanged(int32 new_value) +{ + Station::RecomputeCatchmentForAll(); + MarkWholeScreenDirty(); +} + +static void MaxVehiclesChanged(int32 new_value) +{ + InvalidateWindowClassesData(WC_BUILD_TOOLBAR); + MarkWholeScreenDirty(); +} + +static void InvalidateShipPathCache(int32 new_value) +{ + for (Ship *s : Ship::Iterate()) { + s->path.clear(); + } +} + +/** + * Replace a passwords that are a literal asterisk with an empty string. + * @param newval The new string value for this password field. + * @return Always true. + */ +static bool ReplaceAsteriskWithEmptyPassword(std::string &newval) +{ + if (newval.compare("*") == 0) newval.clear(); + return true; +} + +/** Update the game info, and send it to the clients when we are running as a server. */ +static void UpdateClientConfigValues() +{ + NetworkServerUpdateGameInfo(); + if (_network_server) NetworkServerSendConfigUpdate(); +} + +/* End - Callback Functions */ diff --git a/src/settings_table.h b/src/settings_table.h new file mode 100644 index 000000000..ace0ec7a2 --- /dev/null +++ b/src/settings_table.h @@ -0,0 +1,38 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * @file settings_table.h Definition of the configuration tables of the settings. + */ + +#ifndef SETTINGS_TABLE_H +#define SETTINGS_TABLE_H + +#include <array> +#include "settings_internal.h" + +typedef span<const SettingVariant> SettingTable; + +extern SettingTable _settings; +extern SettingTable _network_settings; +extern SettingTable _network_private_settings; +extern SettingTable _network_secrets_settings; + +extern SettingTable _company_settings; +extern SettingTable _currency_settings; +extern SettingTable _gameopt_settings; +extern SettingTable _misc_settings; +extern SettingTable _window_settings; +#if defined(_WIN32) && !defined(DEDICATED) +extern SettingTable _win32_settings; +#endif /* _WIN32 */ + +static const uint GAME_DIFFICULTY_NUM = 18; +extern const std::array<std::string, GAME_DIFFICULTY_NUM> _old_diff_settings; +extern uint16 _old_diff_custom[GAME_DIFFICULTY_NUM]; + +#endif /* SETTINGS_TABLE_H */ diff --git a/src/table/settings/company_settings.ini b/src/table/settings/company_settings.ini index e5019305f..52920e6e6 100644 --- a/src/table/settings/company_settings.ini +++ b/src/table/settings/company_settings.ini @@ -12,7 +12,7 @@ static void UpdateAllServiceInterval(int32 new_value); static bool CanUpdateServiceInterval(VehicleType type, int32 &new_value); static void UpdateServiceInterval(VehicleType type, int32 new_value); -static const SettingVariant _company_settings[] = { +static const SettingVariant _company_settings_table[] = { [post-amble] }; [templates] diff --git a/src/table/settings/currency_settings.ini b/src/table/settings/currency_settings.ini index d0950db8e..03c6425b2 100644 --- a/src/table/settings/currency_settings.ini +++ b/src/table/settings/currency_settings.ini @@ -7,7 +7,7 @@ ; Settings for the in-game custom currency. [pre-amble] -static const SettingVariant _currency_settings[] = { +static const SettingVariant _currency_settings_table[] = { [post-amble] }; [templates] diff --git a/src/table/settings/gameopt_settings.ini b/src/table/settings/gameopt_settings.ini index a30400e85..83e7c6395 100644 --- a/src/table/settings/gameopt_settings.ini +++ b/src/table/settings/gameopt_settings.ini @@ -14,9 +14,8 @@ ; be saved in their new place. [pre-amble] -static const uint GAME_DIFFICULTY_NUM = 18; -static const std::array<std::string, GAME_DIFFICULTY_NUM> _old_diff_settings{"max_no_competitors", "competitor_start_time", "number_towns", "industry_density", "max_loan", "initial_interest", "vehicle_costs", "competitor_speed", "competitor_intelligence", "vehicle_breakdowns", "subsidy_multiplier", "construction_cost", "terrain_type", "quantity_sea_lakes", "economy", "line_reverse_mode", "disasters", "town_council_tolerance"}; -static uint16 _old_diff_custom[GAME_DIFFICULTY_NUM]; +const std::array<std::string, GAME_DIFFICULTY_NUM> _old_diff_settings{"max_no_competitors", "competitor_start_time", "number_towns", "industry_density", "max_loan", "initial_interest", "vehicle_costs", "competitor_speed", "competitor_intelligence", "vehicle_breakdowns", "subsidy_multiplier", "construction_cost", "terrain_type", "quantity_sea_lakes", "economy", "line_reverse_mode", "disasters", "town_council_tolerance"}; +uint16 _old_diff_custom[GAME_DIFFICULTY_NUM]; uint8 _old_diff_level; ///< Old difficulty level from old savegames uint8 _old_units; ///< Old units from old savegames @@ -33,7 +32,7 @@ static std::initializer_list<const char*> _osk_activation{"disabled", "double", static std::initializer_list<const char*> _settings_profiles{"easy", "medium", "hard"}; static std::initializer_list<const char*> _news_display{ "off", "summarized", "full"}; -static const SettingVariant _gameopt_settings[] = { +static const SettingVariant _gameopt_settings_table[] = { /* In version 4 a new difficulty setting has been added to the difficulty settings, * town attitude towards demolishing. Needs special handling because some dimwit thought * it funny to have the GameDifficulty struct be an array while it is a struct of diff --git a/src/table/settings/misc_settings.ini b/src/table/settings/misc_settings.ini index 9f73573b2..daca4a817 100644 --- a/src/table/settings/misc_settings.ini +++ b/src/table/settings/misc_settings.ini @@ -20,7 +20,7 @@ extern bool _allow_hidpi_window; #define WITHOUT_COCOA #endif -static const SettingVariant _misc_settings[] = { +static const SettingVariant _misc_settings_table[] = { [post-amble] }; [templates] diff --git a/src/table/settings/network_private_settings.ini b/src/table/settings/network_private_settings.ini index 76fbd373a..cae43330f 100644 --- a/src/table/settings/network_private_settings.ini +++ b/src/table/settings/network_private_settings.ini @@ -7,7 +7,7 @@ ; Network settings as stored in the private configuration file ("private.cfg"). [pre-amble] -static const SettingVariant _network_private_settings[] = { +static const SettingVariant _network_private_settings_table[] = { [post-amble] }; [templates] diff --git a/src/table/settings/network_secrets_settings.ini b/src/table/settings/network_secrets_settings.ini index a408bad40..fced9240e 100644 --- a/src/table/settings/network_secrets_settings.ini +++ b/src/table/settings/network_secrets_settings.ini @@ -9,7 +9,7 @@ [pre-amble] static bool ReplaceAsteriskWithEmptyPassword(std::string &newval); -static const SettingVariant _network_secrets_settings[] = { +static const SettingVariant _network_secrets_settings_table[] = { [post-amble] }; [templates] diff --git a/src/table/settings/network_settings.ini b/src/table/settings/network_settings.ini index 1317edbc7..45459b6e1 100644 --- a/src/table/settings/network_settings.ini +++ b/src/table/settings/network_settings.ini @@ -9,7 +9,7 @@ [pre-amble] static void UpdateClientConfigValues(); -static const SettingVariant _network_settings[] = { +static const SettingVariant _network_settings_table[] = { [post-amble] }; [templates] diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index fae6e5636..984668e51 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -46,7 +46,7 @@ static void InvalidateShipPathCache(int32 new_value); * assigns its own value. If the setting was company-based, that would mean that * vehicles could decide on different moments that they are heading back to a * service depot, causing desyncs on a massive scale. */ -static const SettingVariant _settings[] = { +static const SettingVariant _settings_table[] = { [post-amble] }; [templates] diff --git a/src/table/settings/win32_settings.ini b/src/table/settings/win32_settings.ini index 51b579629..4256528dd 100644 --- a/src/table/settings/win32_settings.ini +++ b/src/table/settings/win32_settings.ini @@ -12,7 +12,7 @@ #if defined(_WIN32) && !defined(DEDICATED) extern bool _window_maximize; -static const SettingVariant _win32_settings[] = { +static const SettingVariant _win32_settings_table[] = { [post-amble] }; #endif /* _WIN32 */ diff --git a/src/table/settings/window_settings.ini b/src/table/settings/window_settings.ini index d9327aa92..aba8d3dba 100644 --- a/src/table/settings/window_settings.ini +++ b/src/table/settings/window_settings.ini @@ -9,7 +9,7 @@ [pre-amble] -static const SettingVariant _window_settings[] = { +static const SettingVariant _window_settings_table[] = { [post-amble] }; [templates] |