diff --git a/src/settings.cpp b/src/settings.cpp index 5b04e5c087..e01fa50e7f 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2066,24 +2066,27 @@ bool SetSettingValue(uint index, const char *value, bool force_newgame) /** * Given a name of setting, return a setting description of it. - * @param name Name of the setting to return a setting description of - * @param i Pointer to an integer that will contain the index of the setting after the call, if it is successful. + * @param name Name of the setting to return a setting description of + * @param i Pointer to an integer that will contain the index of the setting after the call, if it is successful. + * @param ignore_version Return a setting even if it not valid for the current savegame version * @return Pointer to the setting description of setting \a name if it can be found, * \c NULL indicates failure to obtain the description */ -const SettingDesc *GetSettingFromName(const char *name, uint *i) +const SettingDesc *GetSettingFromName(const char *name, uint *i, bool ignore_version) { const SettingDesc *sd; /* First check all full names */ for (*i = 0, sd = _settings; sd->save.cmd != SL_END; sd++, (*i)++) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to, sd->save.ext_feature_test)) continue; + if (sd->desc.name == NULL) continue; + if (!ignore_version && !SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to, sd->save.ext_feature_test)) continue; if (strcmp(sd->desc.name, name) == 0) return sd; } /* Then check the shortcut variant of the name. */ for (*i = 0, sd = _settings; sd->save.cmd != SL_END; sd++, (*i)++) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to, sd->save.ext_feature_test)) continue; + if (sd->desc.name == NULL) continue; + if (!ignore_version && !SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to, sd->save.ext_feature_test)) continue; const char *short_name = strchr(sd->desc.name, '.'); if (short_name != NULL) { short_name++; @@ -2094,7 +2097,8 @@ const SettingDesc *GetSettingFromName(const char *name, uint *i) if (strncmp(name, "company.", 8) == 0) name += 8; /* And finally the company-based settings */ for (*i = 0, sd = _company_settings; sd->save.cmd != SL_END; sd++, (*i)++) { - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to, sd->save.ext_feature_test)) continue; + if (sd->desc.name == NULL) continue; + if (!ignore_version && !SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to, sd->save.ext_feature_test)) continue; if (strcmp(sd->desc.name, name) == 0) return sd; } @@ -2206,6 +2210,29 @@ void IConsoleListSettings(const char *prefilter) IConsolePrintF(CC_WARNING, "Use 'setting' command to change a value"); } +/** + * Load handler for settings, which don't go in the PATX chunk, and which are a cross-reference to another setting + * @param osd SettingDesc struct containing all information + * @param object can be either NULL in which case we load global variables or + * a pointer to a struct which is getting saved + */ +static void LoadSettingsXref(const SettingDesc *osd, void *object) { + DEBUG(sl, 3, "PATS chunk: Loading xref setting: '%s'", osd->xref); + uint index = 0; + const SettingDesc *setting_xref = GetSettingFromName(osd->xref, &index, true); + assert(setting_xref != NULL); + + // Generate a new SaveLoad from the xref target using the version params from the source + SaveLoad sld = setting_xref->save; + sld.version_from = osd->save.version_from; + sld.version_to = osd->save.version_to; + sld.ext_feature_test = osd->save.ext_feature_test; + void *ptr = GetVariableAddress(object, &sld); + + if (!SlObjectMember(ptr, &sld)) return; + if (IsNumericType(sld.conv)) Write_ValidateSetting(ptr, setting_xref, ReadValue(ptr, sld.conv)); +} + /** * Save and load handler for settings, except for those which go in the PATX chunk * @param osd SettingDesc struct containing all information @@ -2214,9 +2241,15 @@ void IConsoleListSettings(const char *prefilter) */ static void LoadSettings(const SettingDesc *osd, void *object) { + extern uint16 _sl_version; + for (; osd->save.cmd != SL_END; osd++) { if (osd->patx_name != NULL) continue; const SaveLoad *sld = &osd->save; + if (osd->xref != NULL) { + if (sld->ext_feature_test.IsFeaturePresent(_sl_version, sld->version_from, sld->version_to)) LoadSettingsXref(osd, object); + continue; + } void *ptr = GetVariableAddress(object, sld); if (!SlObjectMember(ptr, sld)) continue; @@ -2238,6 +2271,7 @@ static void SaveSettings(const SettingDesc *sd, void *object) size_t length = 0; for (i = sd; i->save.cmd != SL_END; i++) { if (i->patx_name != NULL) continue; + if (i->xref != NULL) continue; length += SlCalcObjMemberLength(object, &i->save); } SlSetLength(length); diff --git a/src/settings_internal.h b/src/settings_internal.h index e356e7e5e6..2f0021392f 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -112,6 +112,7 @@ struct SettingDesc { SettingDescBase desc; ///< Settings structure (going to configuration file) SaveLoad save; ///< Internal structure (going to savegame, parts to config) const char *patx_name; ///< Name to save/load setting from in PATX chunk, if NULL save/load from PATS chunk as normal + const char *xref; ///< Name of SettingDesc to use instead of the contents of this one, useful for loading legacy savegames, if NULL save/load as normal bool IsEditable(bool do_command = false) const; SettingType GetType() const; @@ -126,7 +127,7 @@ struct SettingDesc { * offset in a certain struct */ typedef SettingDesc SettingDescGlobVarList; -const SettingDesc *GetSettingFromName(const char *name, uint *i); +const SettingDesc *GetSettingFromName(const char *name, uint *i, bool ignore_version = false); bool SetSettingValue(uint index, int32 value, bool force_newgame = false); bool SetSettingValue(uint index, const char *value, bool force_newgame = false); void SetCompanySetting(uint index, int32 value); diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index ed67d43c30..9e78a500ff 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -62,7 +62,7 @@ static size_t ConvertLandscape(const char *value); /* Macros for various objects to go in the configuration file. * This section is for global variables */ #define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat, extver, patxname)\ - {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, NULL, cat), SLEG_GENERAL_X(sle_cmd, var, type | flags, length, from, to, extver), patxname} + {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, NULL, cat), SLEG_GENERAL_X(sle_cmd, var, type | flags, length, from, to, extver), patxname, NULL} #define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extver, patxname)\ SDTG_GENERAL(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, NULL, str, strhelp, strval, proc, from, to, cat, extver, patxname) @@ -83,14 +83,14 @@ static size_t ConvertLandscape(const char *value); SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, strhelp, strval, proc, from, to, cat, extver, patxname) #define SDTG_NULL(length, from, to, extver)\ - {{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, STR_NULL, NULL, NULL, SC_NONE}, SLEG_NULL_X(length, from, to, extver), NULL} + {{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, STR_NULL, NULL, NULL, SC_NONE}, SLEG_NULL_X(length, from, to, extver), NULL, NULL} -#define SDTG_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, STR_NULL, NULL, NULL, SC_NONE}, SLEG_END(), NULL} +#define SDTG_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, STR_NULL, NULL, NULL, SC_NONE}, SLEG_END(), NULL, NULL} /* Macros for various objects to go in the configuration file. * This section is for structures where their various members are saved */ #define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extver, patxname)\ - {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, load, cat), SLE_GENERAL_X(sle_cmd, base, var, type | flags, length, from, to, extver), patxname} + {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, load, cat), SLE_GENERAL_X(sle_cmd, base, var, type | flags, length, from, to, extver), patxname, NULL} #define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extver, patxname)\ SDT_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, base, var, 1, def, min, max, interval, NULL, str, strhelp, strval, proc, NULL, from, to, cat, extver, patxname) @@ -114,7 +114,7 @@ static size_t ConvertLandscape(const char *value); SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, strhelp, strval, proc, NULL, from, to, cat, extver, patxname) #define SDT_NULL(length, from, to, extver)\ - {{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, STR_NULL, NULL, NULL, SC_NONE}, SLE_CONDNULL_X(length, from, to, extver), NULL} + {{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, STR_NULL, NULL, NULL, SC_NONE}, SLE_CONDNULL_X(length, from, to, extver), NULL, NULL} #define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extver, patxname)\ @@ -132,5 +132,8 @@ static size_t ConvertLandscape(const char *value); #define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, cat, extver, patxname)\ SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat, extver, patxname) -#define SDT_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, STR_NULL, NULL, NULL, SC_NONE}, SLE_END(), NULL} +#define SDT_XREF(from, to, extver, xref)\ + {{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, STR_NULL, NULL, NULL, SC_NONE}, SLE_CONDNULL_X(0, from, to, extver), NULL, xref} + +#define SDT_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, STR_NULL, NULL, NULL, SC_NONE}, SLE_END(), NULL, NULL} diff --git a/src/table/settings.ini b/src/table/settings.ini index bfd7ae3055..f63fc001df 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -81,6 +81,7 @@ SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname), SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname), SDT_NULL = SDT_NULL($length, $from, $to, $extver), +SDT_XREF = SDT_XREF( $from, $to, $extver, $xref), SDT_END = SDT_END() [defaults] @@ -97,6 +98,7 @@ to = SL_MAX_VERSION cat = SC_ADVANCED extver = {} patxname = NULL +xref = @@ -335,22 +337,12 @@ min = 0 max = 3 cat = SC_BASIC -[SDT_BOOL] -base = GameSettings -var = order.timetable_automated -def = true -str = STR_CONFIG_SETTING_TIMETABLE_AUTOMATED -strhelp = STR_CONFIG_SETTING_TIMETABLE_AUTOMATED_HELPTEXT -cat = SC_EXPERT +[SDT_XREF] +xref = ""order.timetable_automated"" extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) -[SDT_BOOL] -base = GameSettings -var = order.timetable_separation -def = true -str = STR_CONFIG_SETTING_TIMETABLE_SEPARATION -strhelp = STR_CONFIG_SETTING_TIMETABLE_SEPARATION_HELPTEXT -cat = SC_EXPERT +[SDT_XREF] +xref = ""order.timetable_separation"" extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) [SDT_BOOL] @@ -616,9 +608,8 @@ from = 0 cat = SC_BASIC patxname = ""signal_tunnel_bridge.construction.simulated_wormhole_signals"" -;; construction.maximum_signal_evaluations -[SDT_NULL] -length = 2 +[SDT_XREF] +xref = ""construction.maximum_signal_evaluations"" extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) ;; construction.longbridges @@ -682,9 +673,8 @@ def = true str = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT -;; economy.town_cargo_factor -[SDT_NULL] -length = 1 +[SDT_XREF] +xref = ""economy.town_cargo_factor"" extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) [SDT_VAR] @@ -1254,6 +1244,10 @@ strhelp = STR_CONFIG_SETTING_PLANE_CRASHES_HELPTEXT strval = STR_CONFIG_SETTING_PLANE_CRASHES_NONE cat = SC_BASIC +[SDT_XREF] +xref = ""vehicle.improved_breakdowns"" +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) + [SDT_BOOL] base = GameSettings var = vehicle.improved_breakdowns @@ -1262,11 +1256,6 @@ def = false str = STR_CONFIG_SETTING_IMPROVED_BREAKDOWNS patxname = ""improved_breakdowns.vehicle.improved_breakdowns"" -;; vehicle.improved_breakdowns -[SDT_NULL] -length = 1 -extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) - ; station.join_stations [SDT_NULL] length = 1 @@ -1579,9 +1568,8 @@ strhelp = STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT strval = STR_CONFIG_SETTING_PERCENTAGE cat = SC_EXPERT -;; economy.day_length_factor -[SDT_NULL] -length = 1 +[SDT_XREF] +xref = ""economy.day_length_factor"" extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) ;; economy.price_mult[0-70] @@ -1599,11 +1587,17 @@ extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) length = 16 extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) -;; economy.pay_for_repair -;; economy.repair_cost +[SDT_XREF] +xref = ""vehicle.pay_for_repair"" +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) + +[SDT_XREF] +xref = ""vehicle.repair_cost"" +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) + ;; economy.town_consumption_rate [SDT_NULL] -length = 3 +length = 1 extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) ;; economy.town_pop_* @@ -1673,19 +1667,41 @@ from = 77 def = true cat = SC_EXPERT -;; economy.infrastructure_sharing[0-3] -[SDT_NULL] -length = 4 + +[SDT_XREF] +xref = ""economy.infrastructure_sharing[0]"" extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) -;; economy.sharing_fee[0-3] -[SDT_NULL] -length = 16 +[SDT_XREF] +xref = ""economy.infrastructure_sharing[1]"" extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) -;; economy.sharing_payment_in_debt -[SDT_NULL] -length = 1 +[SDT_XREF] +xref = ""economy.infrastructure_sharing[2]"" +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) + +[SDT_XREF] +xref = ""economy.infrastructure_sharing[3]"" +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) + +[SDT_XREF] +xref = ""economy.sharing_fee[0]"" +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) + +[SDT_XREF] +xref = ""economy.sharing_fee[1]"" +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) + +[SDT_XREF] +xref = ""economy.sharing_fee[2]"" +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) + +[SDT_XREF] +xref = ""economy.sharing_fee[3]"" +extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) + +[SDT_XREF] +xref = ""economy.sharing_payment_in_debt"" extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP) [SDT_VAR]