Files @ r25751:3154638283de
Branch filter:

Location: cpp/openttd-patchpack/source/src/table/settings/gameopt_settings.ini

Patric Stout
Feature: framework to make savegames self-descriptive

We won't be able to make it fully self-descriptive (looking at you
MAP-chunks), but anything else can. With this framework, we can
add headers for each chunk explaining how each chunk looks like
in detail.

They also will all be tables, making it a lot easier to read in
external tooling, and opening the way to consider a database
(like SQLite) to use as savegame format.

Lastly, with the headers in the savegame, you can freely add
fields without needing a savegame version bump; older versions
of OpenTTD will simply ignore the new field. This also means
we can remove all the SLE_CONDNULL, as they are irrelevant.

The next few commits will start using this framework.
; 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/>.
;

; Settings that used to be saved in the savegame under the OPTS chunk and
; under "gameopts" in the configuration file, but no longer are. Most of these
; are now moved to other places.
;
; For backwards compatability, this file dictates how both were saved. When
; a configuration files contains these entries, they are read once, and removed
; from the configuration file afterwards. Those that are still supported will
; 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];
uint8 _old_diff_level;                                 ///< Old difficulty level from old savegames
uint8 _old_units;                                      ///< Old units from old savegames

/* Most of these strings are used both for gameopt-backward compatibility
 * and the settings tables. The rest is here for consistency. */
static std::initializer_list<const char*> _locale_currencies{"GBP", "USD", "EUR", "YEN", "ATS", "BEF", "CHF", "CZK", "DEM", "DKK", "ESP", "FIM", "FRF", "GRD", "HUF", "ISK", "ITL", "NLG", "NOK", "PLN", "RON", "RUR", "SIT", "SEK", "YTL", "SKK", "BRL", "EEK", "custom"};
static std::initializer_list<const char*> _locale_units{"imperial", "metric", "si", "gameunits"};
static std::initializer_list<const char*> _town_names{"english", "french", "german", "american", "latin", "silly", "swedish", "dutch", "finnish", "polish", "slovak", "norwegian", "hungarian", "austrian", "romanian", "czech", "swiss", "danish", "turkish", "italian", "catalan"};
static std::initializer_list<const char*> _climates{"temperate", "arctic", "tropic", "toyland"};
static std::initializer_list<const char*> _autosave_interval{"off", "monthly", "quarterly", "half year", "yearly"};
static std::initializer_list<const char*> _roadsides{"left", "right"};
static std::initializer_list<const char*> _savegame_date{"long", "short", "iso"};
static std::initializer_list<const char*> _osk_activation{"disabled", "double", "single", "immediately"};
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[] = {
/* 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
 * same-sized members
 * XXX - To save file-space and since values are never bigger than about 10? only
 * save the first 16 bits in the savegame. Question is why the values are still int32
 * and why not byte for example?
 * 'SLE_FILE_I16 | SLE_VAR_U16' in "diff_custom" is needed to get around SlCopy() hack
 * for savegames version 0 - though it is an array, it has to go through the byteswap process */
[post-amble]
};
[templates]
SDTG_LIST    =  SDTG_LIST($name,              $type, $flags, $var, $def, $length, $from, $to, $cat, $extra, $startup),
SDTG_VAR     =   SDTG_VAR($name,              $type, $flags, $var, $def, $min, $max, $interval,  $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $extra, $startup),
SDT_NULL     =   SDT_NULL(                                                          $length,                                                            $from, $to),
SDTC_OMANY   = SDTC_OMANY(              $var, $type, $flags, $def,       $max, $full,            $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to,        $cat, $extra, $startup),
SDTG_OMANY   = SDTG_OMANY($name,              $type, $flags, $var, $def, $max, $full,            $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to,        $cat, $extra, $startup),
SDT_OMANY    =  SDT_OMANY(GameSettings, $var, $type, $flags, $def,       $max, $full,            $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $load, $cat, $extra, $startup),
SDT_VAR      =    SDT_VAR(GameSettings, $var, $type, $flags, $def, $min, $max,        $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to,        $cat, $extra, $startup),

[validation]
SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
SDTC_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var exceeds storage size");
SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for GameSettings.$var exceeds storage size");

[defaults]
flags    = SF_NONE
interval = 0
str      = STR_NULL
strhelp  = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT
strval   = STR_NULL
pre_cb   = nullptr
post_cb  = nullptr
load     = nullptr
from     = SL_MIN_VERSION
to       = SL_MAX_VERSION
cat      = SC_ADVANCED
extra    = 0
startup  = false



[SDTG_LIST]
name     = ""diff_custom""
sdt_cmd  = SDT_INTLIST
sle_cmd  = SL_ARR
type     = SLE_FILE_I16 | SLE_VAR_U16
flags    = SF_NOT_IN_CONFIG
var      = _old_diff_custom
length   = 17
def      = nullptr
to       = SLV_4

[SDTG_LIST]
name     = ""diff_custom""
sdt_cmd  = SDT_INTLIST
sle_cmd  = SL_ARR
type     = SLE_UINT16
flags    = SF_NOT_IN_CONFIG
var      = _old_diff_custom
length   = 18
def      = nullptr
full     = nullptr
from     = SLV_4

[SDTG_VAR]
name     = ""diff_level""
var      = _old_diff_level
type     = SLE_UINT8
flags    = SF_NOT_IN_CONFIG
def      = SP_CUSTOM
min      = SP_EASY
max      = SP_CUSTOM
cat      = SC_BASIC

[SDT_OMANY]
var      = locale.currency
type     = SLE_UINT8
flags    = SF_NO_NETWORK_SYNC
def      = 0
max      = CURRENCY_END - 1
full     = _locale_currencies
cat      = SC_BASIC

[SDTG_OMANY]
name     = ""units""
var      = _old_units
type     = SLE_UINT8
flags    = SF_NOT_IN_CONFIG
def      = 1
max      = 2
full     = _locale_units
cat      = SC_BASIC

# There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow
# these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI.
[SDT_OMANY]
var      = game_creation.town_name
type     = SLE_UINT8
def      = 0
max      = 255
full     = _town_names
cat      = SC_BASIC

[SDT_OMANY]
var      = game_creation.landscape
type     = SLE_UINT8
def      = 0
max      = 3
full     = _climates
load     = ConvertLandscape
cat      = SC_BASIC

[SDT_VAR]
var      = game_creation.snow_line_height
type     = SLE_UINT8
def      = DEF_SNOWLINE_HEIGHT * TILE_HEIGHT
min      = MIN_SNOWLINE_HEIGHT * TILE_HEIGHT
# "max" used to be MAX_SNOWLINE_HEIGHT * TILE_HEIGHT, but this would overflow the storage.
max      = UINT8_MAX
to       = SLV_22

[SDT_NULL]
length   = 1
from     = SLV_22
to       = SLV_165

[SDT_NULL]
length   = 1
to       = SLV_23

[SDTC_OMANY]
var      = gui.autosave
type     = SLE_UINT8
flags    = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC
def      = 1
max      = 4
full     = _autosave_interval
cat      = SC_BASIC

[SDT_OMANY]
var      = vehicle.road_side
type     = SLE_UINT8
def      = 1
max      = 1
full     = _roadsides
cat      = SC_BASIC