diff --git a/src/command.cpp b/src/command.cpp index 2ad8e14169..85d1cfd4c8 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -145,6 +145,7 @@ DEF_COMMAND(CmdRenameTown); DEF_COMMAND(CmdDoTownAction); DEF_COMMAND(CmdChangeSetting); +DEF_COMMAND(CmdChangeCompanySetting); DEF_COMMAND(CmdSellShip); DEF_COMMAND(CmdBuildShip); @@ -317,6 +318,7 @@ static const Command _command_proc_table[] = { {CmdGiveMoney, 0}, // CMD_GIVE_MONEY {CmdChangeSetting, CMD_SERVER}, // CMD_CHANGE_SETTING + {CmdChangeCompanySetting, 0}, // CMD_CHANGE_COMPANY_SETTING {CmdSetAutoReplace, 0}, // CMD_SET_AUTOREPLACE {CmdCloneVehicle, CMD_NO_TEST}, // CMD_CLONE_VEHICLE; NewGRF callbacks influence building and refitting making it impossible to correctly estimate the cost {CmdStartStopVehicle, 0}, // CMD_START_STOP_VEHICLE diff --git a/src/command_type.h b/src/command_type.h index c4ebde6d65..fb9488a7f8 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -264,6 +264,7 @@ enum { CMD_GIVE_MONEY, ///< give money to another company CMD_CHANGE_SETTING, ///< change a setting + CMD_CHANGE_COMPANY_SETTING, ///< change a company etting CMD_SET_AUTOREPLACE, ///< set an autoreplace entry diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 4fbcfe7c30..abecf27992 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -75,13 +75,6 @@ void SetLocalCompany(CompanyID new_company) _local_company = new_company; - /* Do not update the settings if we are in the intro GUI */ - const Company *c = Company::GetIfValid(new_company); - if (_game_mode != GM_MENU && c != NULL) { - _settings_client.company = c->settings; - InvalidateWindow(WC_GAME_OPTIONS, 0); - } - /* Delete any construction windows... */ DeleteConstructionWindows(); diff --git a/src/settings.cpp b/src/settings.cpp index 4a1c0e042b..c59a4bd8e9 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -724,24 +724,6 @@ static bool CheckInterval(int32 p1) return true; } -static bool EngineRenewUpdate(int32 p1) -{ - DoCommandP(0, 0, _settings_client.company.engine_renew, CMD_SET_AUTOREPLACE); - return true; -} - -static bool EngineRenewMonthsUpdate(int32 p1) -{ - DoCommandP(0, 1, _settings_client.company.engine_renew_months, CMD_SET_AUTOREPLACE); - return true; -} - -static bool EngineRenewMoneyUpdate(int32 p1) -{ - DoCommandP(0, 2, _settings_client.company.engine_renew_money, CMD_SET_AUTOREPLACE); - return true; -} - static bool TrainAccelerationModelChanged(int32 p1) { Vehicle *v; @@ -1275,6 +1257,7 @@ static void HandleSettingDescs(IniFile *ini, SettingDescProc *proc, SettingDescP proc(ini, _settings, "patches", &_settings_newgame); proc(ini, _currency_settings,"currency", &_custom_currency); + proc(ini, _company_settings, "company", &_settings_client.company); #ifdef ENABLE_NETWORK proc_list(ini, "server_bind_addresses", &_network_bind_list); @@ -1433,6 +1416,40 @@ CommandCost CmdChangeSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uin return CommandCost(); } +/** Change one of the per-company settings. + * @param tile unused + * @param flags operation to perform + * @param p1 the index of the setting in the _company_settings array which identifies it + * @param p2 the new value for the setting + * The new value is properly clamped to its minimum/maximum when setting + */ +CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + if (p1 >= lengthof(_company_settings)) return CMD_ERROR; + const SettingDesc *sd = &_company_settings[p1]; + + if (flags & DC_EXEC) { + void *var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd->save); + + int32 oldval = (int32)ReadValue(var, sd->save.conv); + int32 newval = (int32)p2; + + Write_ValidateSetting(var, sd, newval); + newval = (int32)ReadValue(var, sd->save.conv); + + if (oldval == newval) return CommandCost(); + + if (sd->desc.proc != NULL && !sd->desc.proc(newval)) { + WriteValue(var, sd->save.conv, (int64)oldval); + return CommandCost(); + } + + InvalidateWindow(WC_GAME_OPTIONS, 0); + } + + return CommandCost(); +} + /** Top function to save the new value of an element of the Settings struct * @param index offset in the SettingDesc array of the Settings struct which * identifies the setting member we want to change @@ -1467,6 +1484,23 @@ bool SetSettingValue(uint index, int32 value) return false; } +/** Top function to save the new value of an element of the Settings struct + * @param index offset in the SettingDesc array of the CompanySettings struct + * which identifies the setting member we want to change + * @param object pointer to a valid CompanySettings struct that has its settings changed. + * @param value new value of the setting */ +void SetCompanySetting(uint index, int32 value) +{ + const SettingDesc *sd = &_company_settings[index]; + if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { + DoCommandP(0, index, value, CMD_CHANGE_COMPANY_SETTING); + } else { + void *var = GetVariableAddress(&_settings_client.company, &sd->save); + Write_ValidateSetting(var, sd, value); + if (sd->desc.proc != NULL) sd->desc.proc((int32)ReadValue(var, sd->save.conv)); + } +} + /** * Set a setting value with a string. * @param index the settings index. @@ -1512,6 +1546,13 @@ 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)) continue; + if (strcmp(sd->desc.name, name) == 0) return sd; + } + return NULL; } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 6b834cf349..202e2e8d0f 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -26,6 +26,8 @@ #include "station_func.h" #include "highscore.h" #include "gfxinit.h" +#include "company_base.h" +#include "company_func.h" #include #include "table/sprites.h" @@ -981,6 +983,19 @@ uint SettingEntry::Draw(GameSettings *settings_ptr, int base_x, int base_y, int return cur_row; } +const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd) +{ + if ((sd->desc.flags & SGF_PER_COMPANY) != 0) { + if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) { + return GetVariableAddress(&Company::Get(_local_company)->settings, &sd->save); + } else { + return GetVariableAddress(&_settings_client.company, &sd->save); + } + } else { + return GetVariableAddress(settings_ptr, &sd->save); + } +} + /** * Private function to draw setting value (button + text + current value) * @param settings_ptr Pointer to current values of all settings @@ -993,7 +1008,7 @@ uint SettingEntry::Draw(GameSettings *settings_ptr, int base_x, int base_y, int void SettingEntry::DrawSetting(GameSettings *settings_ptr, const SettingDesc *sd, int x, int y, int max_x, int state) { const SettingDescBase *sdb = &sd->desc; - const void *var = GetVariableAddress(settings_ptr, &sd->save); + const void *var = ResolveVariableAddress(settings_ptr, sd); bool editable = true; bool disabled = false; @@ -1435,7 +1450,7 @@ struct GameSettingsWindow : Window { if ((sd->desc.flags & SGF_NETWORK_ONLY) && !_networking) return; if ((sd->desc.flags & SGF_NO_NETWORK) && _networking) return; - void *var = GetVariableAddress(settings_ptr, &sd->save); + const void *var = ResolveVariableAddress(settings_ptr, sd); int32 value = (int32)ReadValue(var, sd->save.conv); /* clicked on the icon on the left side. Either scroller or bool on/off */ @@ -1486,7 +1501,11 @@ struct GameSettingsWindow : Window { } if (value != oldvalue) { - SetSettingValue(pe->d.entry.index, value); + if ((sd->desc.flags & SGF_PER_COMPANY) != 0) { + SetCompanySetting(pe->d.entry.index, value); + } else { + SetSettingValue(pe->d.entry.index, value); + } this->SetDirty(); } } else { diff --git a/src/settings_internal.h b/src/settings_internal.h index df35972260..cd45dd8d36 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -28,7 +28,7 @@ typedef SimpleTinyEnumT SettingDescType; enum SettingGuiFlagLong { - /* 8 bytes allocated for a maximum of 8 flags + /* 1 byte allocated for a maximum of 8 flags * Flags directing saving/loading of a variable */ SGF_NONE = 0, SGF_0ISDISABLED = 1 << 0, ///< a value of zero means the feature is disabled @@ -38,7 +38,7 @@ enum SettingGuiFlagLong { SGF_CURRENCY = 1 << 4, ///< the number represents money, so when reading value multiply by exchange rate SGF_NO_NETWORK = 1 << 5, ///< this setting does not apply to network games; it may not be changed during the game SGF_NEWGAME_ONLY = 1 << 6, ///< this setting cannot be changed in inside a game - SGF_END = 1 << 7, + SGF_PER_COMPANY = 1 << 7, ///< this setting can be different for each company (saved in company struct) }; DECLARE_ENUM_AS_BIT_SET(SettingGuiFlagLong); typedef SimpleTinyEnumT SettingGuiFlag; @@ -78,5 +78,6 @@ typedef SettingDesc SettingDescGlobVarList; const SettingDesc *GetSettingFromName(const char *name, uint *i); bool SetSettingValue(uint index, int32 value); bool SetSettingValue(uint index, const char *value); +void SetCompanySetting(uint index, int32 value); #endif /* SETTINGS_H */ diff --git a/src/table/settings.h b/src/table/settings.h index 5fe05dba38..22632d7859 100644 --- a/src/table/settings.h +++ b/src/table/settings.h @@ -14,9 +14,6 @@ static bool InvalidateTownViewWindow(int32 p1); static bool DeleteSelectStationWindow(int32 p1); static bool UpdateConsists(int32 p1); static bool CheckInterval(int32 p1); -static bool EngineRenewUpdate(int32 p1); -static bool EngineRenewMonthsUpdate(int32 p1); -static bool EngineRenewMoneyUpdate(int32 p1); static bool TrainAccelerationModelChanged(int32 p1); static bool DragSignalsDensityChanged(int32); static bool DifficultyReset(int32 level); @@ -208,6 +205,7 @@ static bool UpdateClientConfigValues(int32 p1); #define CR SGF_CURRENCY #define NN SGF_NO_NETWORK #define NG SGF_NEWGAME_ONLY +#define PC SGF_PER_COMPANY static const SettingDesc _music_settings[] = { SDT_VAR(MusicFileSettings, playlist, SLE_UINT8, S, 0, 0, 0, 5, 1, STR_NULL, NULL), @@ -547,9 +545,6 @@ const SettingDesc _settings[] = { SDTC_BOOL(gui.vehicle_income_warn, S, 0, true, STR_CONFIG_SETTING_WARN_INCOME_LESS, NULL), SDTC_VAR(gui.order_review_system, SLE_UINT8, S, MS, 2, 0, 2, 0, STR_CONFIG_SETTING_ORDER_REVIEW, NULL), SDTC_BOOL(gui.lost_train_warn, S, 0, true, STR_CONFIG_SETTING_WARN_LOST_TRAIN, NULL), - SDTC_BOOL(company.engine_renew, S, 0, false, STR_CONFIG_SETTING_AUTORENEW_VEHICLE, EngineRenewUpdate), - SDTC_VAR(company.engine_renew_months, SLE_INT16, S, 0, 6, -12, 12, 0, STR_CONFIG_SETTING_AUTORENEW_MONTHS, EngineRenewMonthsUpdate), - SDTC_VAR(company.engine_renew_money, SLE_UINT, S, CR,100000, 0, 2000000, 0, STR_CONFIG_SETTING_AUTORENEW_MONEY, EngineRenewMoneyUpdate), SDTC_BOOL(gui.always_build_infrastructure, S, 0, false, STR_CONFIG_SETTING_ALWAYS_BUILD_INFRASTRUCTURE, RedrawScreen), SDTC_BOOL(gui.new_nonstop, S, 0, false, STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT, NULL), SDTC_VAR(gui.stop_location, SLE_UINT8, S, MS, 2, 0, 2, 1, STR_CONFIG_SETTING_STOP_LOCATION, NULL), @@ -619,6 +614,13 @@ const SettingDesc _settings[] = { SDT_END() }; +static const SettingDesc _company_settings[] = { + SDT_BOOL(CompanySettings, engine_renew, 0, PC, false, STR_CONFIG_SETTING_AUTORENEW_VEHICLE, NULL), + SDT_VAR(CompanySettings, engine_renew_months, SLE_INT16, 0, PC, 6, -12, 12, 0, STR_CONFIG_SETTING_AUTORENEW_MONTHS, NULL), + SDT_VAR(CompanySettings, engine_renew_money, SLE_UINT, 0, PC|CR,100000, 0, 2000000, 0, STR_CONFIG_SETTING_AUTORENEW_MONEY, NULL), + SDT_END() +}; + static const SettingDesc _currency_settings[] = { SDT_VAR(CurrencySpec, rate, SLE_UINT16, S, 0, 1, 0, UINT16_MAX, 0, STR_NULL, NULL), SDT_CHR(CurrencySpec, separator, S, 0, ".", STR_NULL, NULL),