summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/settings.cpp449
-rw-r--r--src/settings_table.cpp473
-rw-r--r--src/settings_table.h38
-rw-r--r--src/table/settings/company_settings.ini2
-rw-r--r--src/table/settings/currency_settings.ini2
-rw-r--r--src/table/settings/gameopt_settings.ini7
-rw-r--r--src/table/settings/misc_settings.ini2
-rw-r--r--src/table/settings/network_private_settings.ini2
-rw-r--r--src/table/settings/network_secrets_settings.ini2
-rw-r--r--src/table/settings/network_settings.ini2
-rw-r--r--src/table/settings/settings.ini2
-rw-r--r--src/table/settings/win32_settings.ini2
-rw-r--r--src/table/settings/window_settings.ini2
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]