From 9872fd5dc8ddb386e4a7990bfa72433cc157382e Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 2 Feb 2024 19:12:32 +0100 Subject: [PATCH 1/7] Codechange: add CopyOutDParam variant for StringParameters && --- src/strings.cpp | 21 ++++ src/strings_func.h | 1 + src/strings_internal.h | 233 ---------------------------------------- src/strings_type.h | 235 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 257 insertions(+), 233 deletions(-) diff --git a/src/strings.cpp b/src/strings.cpp index 428f4a5293..8fbfffe5b7 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -186,6 +186,27 @@ void CopyOutDParam(std::vector &backup, size_t num) } } +/** + * Copy parameters into StringParameterBackup for long-term storage. + * @param backup The backup to write to. + * @param params The parameters to back up. + */ +void CopyOutDParam(std::vector &backup, StringParameters &¶ms) +{ + params.SetOffset(0); + + backup.resize(params.GetDataLeft()); + + for (size_t i = 0; i < params.GetDataLeft(); i++) { + const char *str = params.GetParamStr(i); + if (str != nullptr) { + backup[i] = str; + } else { + backup[i] = params.GetParam(i); + } + } +} + /** * Checks whether the global string parameters have changed compared to the given backup. * @param backup The backup to check against. diff --git a/src/strings_func.h b/src/strings_func.h index 21a77705d8..4cc208b991 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -100,6 +100,7 @@ void SetDParamStr(size_t n, std::string &&str); void CopyInDParam(const std::span backup); void CopyOutDParam(std::vector &backup, size_t num); +void CopyOutDParam(std::vector &backup, class StringParameters &¶ms); bool HaveDParamChanged(const std::vector &backup); uint64_t GetDParam(size_t n); diff --git a/src/strings_internal.h b/src/strings_internal.h index fc28c34716..0ebbe2e59b 100644 --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -13,239 +13,6 @@ #include "strings_func.h" #include "string_func.h" -/** The data required to format and validate a single parameter of a string. */ -struct StringParameter { - uint64_t data; ///< The data of the parameter. - const char *string_view; ///< The string value, if it has any. - std::unique_ptr string; ///< Copied string value, if it has any. - char32_t type; ///< The #StringControlCode to interpret this data with when it's the first parameter, otherwise '\0'. -}; - -class StringParameters { -protected: - StringParameters *parent = nullptr; ///< If not nullptr, this instance references data from this parent instance. - std::span parameters = {}; ///< Array with the actual parameters. - - size_t offset = 0; ///< Current offset in the parameters span. - char32_t next_type = 0; ///< The type of the next data that is retrieved. - - StringParameters(std::span parameters = {}) : - parameters(parameters) - {} - - StringParameter *GetNextParameterPointer(); - -public: - /** - * Create a new StringParameters instance that can reference part of the data of - * the given parent instance. - */ - StringParameters(StringParameters &parent, size_t size) : - parent(&parent), - parameters(parent.parameters.subspan(parent.offset, size)) - {} - - void PrepareForNextRun(); - void SetTypeOfNextParameter(char32_t type) { this->next_type = type; } - - /** - * Get the current offset, so it can be backed up for certain processing - * steps, or be used to offset the argument index within sub strings. - * @return The current offset. - */ - size_t GetOffset() { return this->offset; } - - /** - * Set the offset within the string from where to return the next result of - * \c GetInt64 or \c GetInt32. - * @param offset The offset. - */ - void SetOffset(size_t offset) - { - /* - * The offset must be fewer than the number of parameters when it is - * being set. Unless restoring a backup, then the original value is - * correct as well as long as the offset was not changed. In other - * words, when the offset was already at the end of the parameters and - * the string did not consume any parameters. - */ - assert(offset < this->parameters.size() || this->offset == offset); - this->offset = offset; - } - - /** - * Advance the offset within the string from where to return the next result of - * \c GetInt64 or \c GetInt32. - * @param advance The amount to advance the offset by. - */ - void AdvanceOffset(size_t advance) - { - this->offset += advance; - assert(this->offset <= this->parameters.size()); - } - - /** - * Get the next parameter from our parameters. - * This updates the offset, so the next time this is called the next parameter - * will be read. - * @return The next parameter's value. - */ - template - T GetNextParameter() - { - auto ptr = GetNextParameterPointer(); - return static_cast(ptr->data); - } - - /** - * Get the next string parameter from our parameters. - * This updates the offset, so the next time this is called the next parameter - * will be read. - * @return The next parameter's value. - */ - const char *GetNextParameterString() - { - auto ptr = GetNextParameterPointer(); - return ptr->string != nullptr ? ptr->string->c_str() : ptr->string_view; - } - - /** - * Get a new instance of StringParameters that is a "range" into the - * remaining existing parameters. Upon destruction the offset in the parent - * is not updated. However, calls to SetDParam do update the parameters. - * - * The returned StringParameters must not outlive this StringParameters. - * @return A "range" of the string parameters. - */ - StringParameters GetRemainingParameters() { return GetRemainingParameters(this->offset); } - - /** - * Get a new instance of StringParameters that is a "range" into the - * remaining existing parameters from the given offset. Upon destruction the - * offset in the parent is not updated. However, calls to SetDParam do - * update the parameters. - * - * The returned StringParameters must not outlive this StringParameters. - * @param offset The offset to get the remaining parameters for. - * @return A "range" of the string parameters. - */ - StringParameters GetRemainingParameters(size_t offset) - { - return StringParameters(this->parameters.subspan(offset, this->parameters.size() - offset)); - } - - /** Return the amount of elements which can still be read. */ - size_t GetDataLeft() const - { - return this->parameters.size() - this->offset; - } - - /** Get the type of a specific element. */ - char32_t GetTypeAtOffset(size_t offset) const - { - assert(offset < this->parameters.size()); - return this->parameters[offset].type; - } - - void SetParam(size_t n, uint64_t v) - { - assert(n < this->parameters.size()); - this->parameters[n].data = v; - this->parameters[n].string.reset(); - this->parameters[n].string_view = nullptr; - } - - template ::value, int> = 0> - void SetParam(size_t n, T v) - { - SetParam(n, v.base()); - } - - void SetParam(size_t n, const char *str) - { - assert(n < this->parameters.size()); - this->parameters[n].data = 0; - this->parameters[n].string.reset(); - this->parameters[n].string_view = str; - } - - void SetParam(size_t n, const std::string &str) { this->SetParam(n, str.c_str()); } - - void SetParam(size_t n, std::string &&str) - { - assert(n < this->parameters.size()); - this->parameters[n].data = 0; - this->parameters[n].string = std::make_unique(std::move(str)); - this->parameters[n].string_view = nullptr; - } - - uint64_t GetParam(size_t n) const - { - assert(n < this->parameters.size()); - assert(this->parameters[n].string_view == nullptr && this->parameters[n].string == nullptr); - return this->parameters[n].data; - } - - /** - * Get the stored string of the parameter, or \c nullptr when there is none. - * @param n The index into the parameters. - * @return The stored string. - */ - const char *GetParamStr(size_t n) const - { - assert(n < this->parameters.size()); - auto ¶m = this->parameters[n]; - return param.string != nullptr ? param.string->c_str() : param.string_view; - } -}; - -/** - * Extension of StringParameters with its own statically sized buffer for - * the parameters. - */ -template -class ArrayStringParameters : public StringParameters { - std::array params{}; ///< The actual parameters - -public: - ArrayStringParameters() - { - this->parameters = std::span(params.data(), params.size()); - } - - ArrayStringParameters(ArrayStringParameters&& other) noexcept - { - *this = std::move(other); - } - - ArrayStringParameters& operator=(ArrayStringParameters &&other) noexcept - { - this->offset = other.offset; - this->next_type = other.next_type; - this->params = std::move(other.params); - this->parameters = std::span(params.data(), params.size()); - return *this; - } - - ArrayStringParameters(const ArrayStringParameters &other) = delete; - ArrayStringParameters& operator=(const ArrayStringParameters &other) = delete; -}; - -/** - * Helper to create the StringParameters with its own buffer with the given - * parameter values. - * @param args The parameters to set for the to be created StringParameters. - * @return The constructed StringParameters. - */ -template -static auto MakeParameters(const Args&... args) -{ - ArrayStringParameters parameters; - size_t index = 0; - (parameters.SetParam(index++, std::forward(args)), ...); - return parameters; -} - /** * Equivalent to the std::back_insert_iterator in function, with some * convenience helpers for string concatenation. diff --git a/src/strings_type.h b/src/strings_type.h index 5e6d715b63..76cc294aab 100644 --- a/src/strings_type.h +++ b/src/strings_type.h @@ -10,6 +10,8 @@ #ifndef STRINGS_TYPE_H #define STRINGS_TYPE_H +#include "core/strong_typedef_type.hpp" + /** * Numeric value that represents a string, independent of the selected language. */ @@ -118,4 +120,237 @@ struct StringParameterBackup { } }; +/** The data required to format and validate a single parameter of a string. */ +struct StringParameter { + uint64_t data; ///< The data of the parameter. + const char *string_view; ///< The string value, if it has any. + std::unique_ptr string; ///< Copied string value, if it has any. + char32_t type; ///< The #StringControlCode to interpret this data with when it's the first parameter, otherwise '\0'. +}; + +class StringParameters { +protected: + StringParameters *parent = nullptr; ///< If not nullptr, this instance references data from this parent instance. + std::span parameters = {}; ///< Array with the actual parameters. + + size_t offset = 0; ///< Current offset in the parameters span. + char32_t next_type = 0; ///< The type of the next data that is retrieved. + + StringParameters(std::span parameters = {}) : + parameters(parameters) + {} + + StringParameter *GetNextParameterPointer(); + +public: + /** + * Create a new StringParameters instance that can reference part of the data of + * the given parent instance. + */ + StringParameters(StringParameters &parent, size_t size) : + parent(&parent), + parameters(parent.parameters.subspan(parent.offset, size)) + {} + + void PrepareForNextRun(); + void SetTypeOfNextParameter(char32_t type) { this->next_type = type; } + + /** + * Get the current offset, so it can be backed up for certain processing + * steps, or be used to offset the argument index within sub strings. + * @return The current offset. + */ + size_t GetOffset() { return this->offset; } + + /** + * Set the offset within the string from where to return the next result of + * \c GetInt64 or \c GetInt32. + * @param offset The offset. + */ + void SetOffset(size_t offset) + { + /* + * The offset must be fewer than the number of parameters when it is + * being set. Unless restoring a backup, then the original value is + * correct as well as long as the offset was not changed. In other + * words, when the offset was already at the end of the parameters and + * the string did not consume any parameters. + */ + assert(offset < this->parameters.size() || this->offset == offset); + this->offset = offset; + } + + /** + * Advance the offset within the string from where to return the next result of + * \c GetInt64 or \c GetInt32. + * @param advance The amount to advance the offset by. + */ + void AdvanceOffset(size_t advance) + { + this->offset += advance; + assert(this->offset <= this->parameters.size()); + } + + /** + * Get the next parameter from our parameters. + * This updates the offset, so the next time this is called the next parameter + * will be read. + * @return The next parameter's value. + */ + template + T GetNextParameter() + { + auto ptr = GetNextParameterPointer(); + return static_cast(ptr->data); + } + + /** + * Get the next string parameter from our parameters. + * This updates the offset, so the next time this is called the next parameter + * will be read. + * @return The next parameter's value. + */ + const char *GetNextParameterString() + { + auto ptr = GetNextParameterPointer(); + return ptr->string != nullptr ? ptr->string->c_str() : ptr->string_view; + } + + /** + * Get a new instance of StringParameters that is a "range" into the + * remaining existing parameters. Upon destruction the offset in the parent + * is not updated. However, calls to SetDParam do update the parameters. + * + * The returned StringParameters must not outlive this StringParameters. + * @return A "range" of the string parameters. + */ + StringParameters GetRemainingParameters() { return GetRemainingParameters(this->offset); } + + /** + * Get a new instance of StringParameters that is a "range" into the + * remaining existing parameters from the given offset. Upon destruction the + * offset in the parent is not updated. However, calls to SetDParam do + * update the parameters. + * + * The returned StringParameters must not outlive this StringParameters. + * @param offset The offset to get the remaining parameters for. + * @return A "range" of the string parameters. + */ + StringParameters GetRemainingParameters(size_t offset) + { + return StringParameters(this->parameters.subspan(offset, this->parameters.size() - offset)); + } + + /** Return the amount of elements which can still be read. */ + size_t GetDataLeft() const + { + return this->parameters.size() - this->offset; + } + + /** Get the type of a specific element. */ + char32_t GetTypeAtOffset(size_t offset) const + { + assert(offset < this->parameters.size()); + return this->parameters[offset].type; + } + + void SetParam(size_t n, uint64_t v) + { + assert(n < this->parameters.size()); + this->parameters[n].data = v; + this->parameters[n].string.reset(); + this->parameters[n].string_view = nullptr; + } + + template ::value, int> = 0> + void SetParam(size_t n, T v) + { + SetParam(n, v.base()); + } + + void SetParam(size_t n, const char *str) + { + assert(n < this->parameters.size()); + this->parameters[n].data = 0; + this->parameters[n].string.reset(); + this->parameters[n].string_view = str; + } + + void SetParam(size_t n, const std::string &str) { this->SetParam(n, str.c_str()); } + + void SetParam(size_t n, std::string &&str) + { + assert(n < this->parameters.size()); + this->parameters[n].data = 0; + this->parameters[n].string = std::make_unique(std::move(str)); + this->parameters[n].string_view = nullptr; + } + + uint64_t GetParam(size_t n) const + { + assert(n < this->parameters.size()); + assert(this->parameters[n].string_view == nullptr && this->parameters[n].string == nullptr); + return this->parameters[n].data; + } + + /** + * Get the stored string of the parameter, or \c nullptr when there is none. + * @param n The index into the parameters. + * @return The stored string. + */ + const char *GetParamStr(size_t n) const + { + assert(n < this->parameters.size()); + auto ¶m = this->parameters[n]; + return param.string != nullptr ? param.string->c_str() : param.string_view; + } +}; + +/** + * Extension of StringParameters with its own statically sized buffer for + * the parameters. + */ +template +class ArrayStringParameters : public StringParameters { + std::array params{}; ///< The actual parameters + +public: + ArrayStringParameters() + { + this->parameters = std::span(params.data(), params.size()); + } + + ArrayStringParameters(ArrayStringParameters&& other) noexcept + { + *this = std::move(other); + } + + ArrayStringParameters& operator=(ArrayStringParameters &&other) noexcept + { + this->offset = other.offset; + this->next_type = other.next_type; + this->params = std::move(other.params); + this->parameters = std::span(params.data(), params.size()); + return *this; + } + + ArrayStringParameters(const ArrayStringParameters &other) = delete; + ArrayStringParameters& operator=(const ArrayStringParameters &other) = delete; +}; + +/** + * Helper to create the StringParameters with its own buffer with the given + * parameter values. + * @param args The parameters to set for the to be created StringParameters. + * @return The constructed StringParameters. + */ +template +static auto MakeParameters(const Args&... args) +{ + ArrayStringParameters parameters; + size_t index = 0; + (parameters.SetParam(index++, std::forward(args)), ...); + return parameters; +} + #endif /* STRINGS_TYPE_H */ From bd80ff4d5776db3ff0690e3b3bf46921ae2524d9 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 2 Feb 2024 18:53:32 +0100 Subject: [PATCH 2/7] Codechange: use StringParameters to pass parameters for ErrorWindow strings --- src/ai/ai_gui.cpp | 2 +- src/ai/ai_instance.cpp | 2 +- src/bridge_gui.cpp | 2 +- src/cheat_gui.cpp | 2 +- src/command.cpp | 2 +- src/company_gui.cpp | 8 ++++---- src/depot_gui.cpp | 8 ++++---- src/engine.cpp | 5 ++--- src/error.h | 4 ++-- src/error_gui.cpp | 11 ++++++----- src/fios_gui.cpp | 6 +++--- src/game/game_gui.cpp | 2 +- src/game/game_instance.cpp | 2 +- src/heightmap.cpp | 18 +++++++++--------- src/industry_cmd.cpp | 7 +++---- src/industry_gui.cpp | 8 +++----- src/intro_gui.cpp | 4 ++-- src/misc_gui.cpp | 3 +-- src/network/core/tcp_game.cpp | 2 +- src/network/network.cpp | 4 ++-- src/network/network_client.cpp | 24 ++++++++++++------------ src/network/network_content.cpp | 6 +++--- src/network/network_content_gui.cpp | 4 ++-- src/network/network_coordinator.cpp | 6 +++--- src/newgrf_commons.cpp | 5 +---- src/newgrf_gui.cpp | 25 ++++++++++++++----------- src/newgrf_industries.cpp | 14 +++++++------- src/openttd.cpp | 11 ++++------- src/order_gui.cpp | 4 ++-- src/saveload/afterload.cpp | 6 +++--- src/saveload/saveload.cpp | 14 +++++--------- src/screenshot.cpp | 9 +++------ src/script/script_gui.cpp | 2 +- src/settings.cpp | 15 +++++---------- src/settings_gui.cpp | 8 ++++---- src/settings_table.cpp | 18 +++++++++--------- src/spriteloader/grf.cpp | 3 +-- src/strings.cpp | 9 +++------ src/town_cmd.cpp | 4 ++-- src/town_gui.cpp | 2 +- src/train_cmd.cpp | 4 +--- src/vehicle.cpp | 4 +--- 42 files changed, 136 insertions(+), 163 deletions(-) diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index a49439d2d3..582d444c08 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -276,7 +276,7 @@ struct AIConfigWindow : public Window { case WID_AIC_CONTENT_DOWNLOAD: if (!_network_available) { - ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } else { ShowNetworkContentListWindow(nullptr, CONTENT_TYPE_AI); } diff --git a/src/ai/ai_instance.cpp b/src/ai/ai_instance.cpp index a5eda5c617..33dcea91d6 100644 --- a/src/ai/ai_instance.cpp +++ b/src/ai/ai_instance.cpp @@ -68,7 +68,7 @@ void AIInstance::Died() const AIInfo *info = AIConfig::GetConfig(_current_company, AIConfig::SSS_FORCE_GAME)->GetInfo(); if (info != nullptr) { - ShowErrorMessage(STR_ERROR_AI_PLEASE_REPORT_CRASH, INVALID_STRING_ID, WL_WARNING); + ShowErrorMessage(STR_ERROR_AI_PLEASE_REPORT_CRASH, INVALID_STRING_ID, MakeParameters(), WL_WARNING); if (!info->GetURL().empty()) { ScriptLog::Info("Please report the error to the following URL:"); diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index fec724bb4c..6d163c5772 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -444,6 +444,6 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo if (!bl.empty()) { new BuildBridgeWindow(&_build_bridge_desc, start, end, transport_type, road_rail_type, std::move(bl)); } else { - ShowErrorMessage(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, errmsg, WL_INFO, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE); + ShowErrorMessage(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, errmsg, MakeParameters(), WL_INFO, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE); } } diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp index bbc518047f..6c175a203d 100644 --- a/src/cheat_gui.cpp +++ b/src/cheat_gui.cpp @@ -144,7 +144,7 @@ static int32_t ClickChangeMaxHlCheat(int32_t new_value, int32_t) * If yes, disallow the change. */ for (TileIndex t = 0; t < Map::Size(); t++) { if ((int32_t)TileHeight(t) > new_value) { - ShowErrorMessage(STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN, INVALID_STRING_ID, MakeParameters(), WL_ERROR); /* Return old, unchanged value */ return _settings_game.construction.map_height_limit; } diff --git a/src/command.cpp b/src/command.cpp index 1d6a530b8c..6116a16ba1 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -218,7 +218,7 @@ std::tuple CommandHelperBase::InternalPostBefore(Commands cmd, bool only_sending = _networking && !network_command; if (_pause_mode != PM_UNPAUSED && !IsCommandAllowedWhilePaused(cmd) && !estimate_only) { - ShowErrorMessage(err_message, STR_ERROR_NOT_ALLOWED_WHILE_PAUSED, WL_INFO, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE); + ShowErrorMessage(err_message, STR_ERROR_NOT_ALLOWED_WHILE_PAUSED, MakeParameters(), WL_INFO, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE); return { true, estimate_only, only_sending }; } else { return { false, estimate_only, only_sending }; diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 3785d11693..8aa33f23b2 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -1660,7 +1660,7 @@ public: case WID_SCMF_LOAD: this->face = _company_manager_face; ScaleAllCompanyManagerFaceBits(this->face); - ShowErrorMessage(STR_FACE_LOAD_DONE, INVALID_STRING_ID, WL_INFO); + ShowErrorMessage(STR_FACE_LOAD_DONE, INVALID_STRING_ID, MakeParameters(), WL_INFO); this->UpdateData(); this->SetDirty(); break; @@ -1674,7 +1674,7 @@ public: /* Save button */ case WID_SCMF_SAVE: _company_manager_face = this->face; - ShowErrorMessage(STR_FACE_SAVE_DONE, INVALID_STRING_ID, WL_INFO); + ShowErrorMessage(STR_FACE_SAVE_DONE, INVALID_STRING_ID, MakeParameters(), WL_INFO); break; /* Toggle gender (male/female) button */ @@ -1751,11 +1751,11 @@ public: if (!StrEmpty(str)) { this->face = std::strtoul(str, nullptr, 10); ScaleAllCompanyManagerFaceBits(this->face); - ShowErrorMessage(STR_FACE_FACECODE_SET, INVALID_STRING_ID, WL_INFO); + ShowErrorMessage(STR_FACE_FACECODE_SET, INVALID_STRING_ID, MakeParameters(), WL_INFO); this->UpdateData(); this->SetDirty(); } else { - ShowErrorMessage(STR_FACE_FACECODE_ERR, INVALID_STRING_ID, WL_INFO); + ShowErrorMessage(STR_FACE_FACECODE_ERR, INVALID_STRING_ID, MakeParameters(), WL_INFO); } } }; diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index f523825b85..ae726c920b 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -931,10 +931,10 @@ struct DepotWindow : Window { })) { OnVehicleSelect(*begin); } else { - ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_COPY_ORDER_VEHICLE_LIST, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_COPY_ORDER_VEHICLE_LIST, MakeParameters(), WL_INFO); } } else { - ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_CLONE_VEHICLE_LIST, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_CLONE_VEHICLE_LIST, MakeParameters(), WL_INFO); } } else { /* If CTRL is pressed: If all the vehicles in this list share orders, then copy orders */ @@ -946,10 +946,10 @@ struct DepotWindow : Window { })) { OnVehicleSelect(*begin); } else { - ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_SHARE_ORDER_VEHICLE_LIST, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_SHARE_ORDER_VEHICLE_LIST, MakeParameters(), WL_INFO); } } else { - ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_CLONE_VEHICLE_LIST, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_CLONE_VEHICLE_LIST, MakeParameters(), WL_INFO); } } diff --git a/src/engine.cpp b/src/engine.cpp index c46f7bb843..3a03eae196 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1298,9 +1298,8 @@ void CheckEngines() } if (min_date < INT32_MAX) { - SetDParam(0, min_date); - ShowErrorMessage(STR_ERROR_NO_VEHICLES_AVAILABLE_YET, STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION, WL_WARNING); + ShowErrorMessage(STR_ERROR_NO_VEHICLES_AVAILABLE_YET, STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION, MakeParameters(min_date), WL_WARNING); } else { - ShowErrorMessage(STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL, STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION, WL_WARNING); + ShowErrorMessage(STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL, STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION, MakeParameters(), WL_WARNING); } } diff --git a/src/error.h b/src/error.h index 0f1964fb80..29ed3e6614 100644 --- a/src/error.h +++ b/src/error.h @@ -55,7 +55,7 @@ public: void SetDParamStr(uint n, const char *str); void SetDParamStr(uint n, const std::string &str); - void CopyOutDParams(); + void CopyOutDParams(class StringParameters &¶ms); }; /** Define a queue with errors. */ @@ -65,7 +65,7 @@ void ScheduleErrorMessage(ErrorList &datas); void ScheduleErrorMessage(const ErrorMessageData &data); void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc); -void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x = 0, int y = 0, const GRFFile *textref_stack_grffile = nullptr, uint textref_stack_size = 0, const uint32_t *textref_stack = nullptr, StringID extra_msg = INVALID_STRING_ID); +void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, class StringParameters &¶ms, WarningLevel wl, int x = 0, int y = 0, const GRFFile *textref_stack_grffile = nullptr, uint textref_stack_size = 0, const uint32_t *textref_stack = nullptr, StringID extra_msg = INVALID_STRING_ID); bool HideActiveErrorMessage(); void ClearErrorMessages(); diff --git a/src/error_gui.cpp b/src/error_gui.cpp index b1cb2b0fe9..584b1b08a2 100644 --- a/src/error_gui.cpp +++ b/src/error_gui.cpp @@ -113,7 +113,7 @@ ErrorMessageData::ErrorMessageData(StringID summary_msg, StringID detailed_msg, /** * Copy error parameters from current DParams. */ -void ErrorMessageData::CopyOutDParams() +void ErrorMessageData::CopyOutDParams(StringParameters &¶ms) { if (this->detailed_msg == STR_ERROR_OWNED_BY) { /* The parameters are set by SetDParamsForOwnedBy. */ @@ -123,7 +123,7 @@ void ErrorMessageData::CopyOutDParams() /* Get parameters using type information */ if (this->textref_stack_size > 0) StartTextRefStackUsage(this->textref_stack_grffile, this->textref_stack_size, this->textref_stack); - CopyOutDParam(this->params, 20); + CopyOutDParam(this->params, std::move(params)); if (this->textref_stack_size > 0) StopTextRefStackUsage(); } @@ -366,13 +366,14 @@ void UnshowCriticalError() */ void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc) { - ShowErrorMessage(summary_msg, cc.GetErrorMessage(), WL_INFO, x, y, cc.GetTextRefStackGRF(), cc.GetTextRefStackSize(), cc.GetTextRefStack(), cc.GetExtraErrorMessage()); + ShowErrorMessage(summary_msg, cc.GetErrorMessage(), MakeParameters(), WL_INFO, x, y, cc.GetTextRefStackGRF(), cc.GetTextRefStackSize(), cc.GetTextRefStack(), cc.GetExtraErrorMessage()); } /** * Display an error message in a window. * @param summary_msg General error message showed in first line. Must be valid. * @param detailed_msg Detailed error message showed in second line. Can be INVALID_STRING_ID. + * @param params Parameters for the error message. * @param wl Message severity. * @param x World X position (TileVirtX) of the error location. Set both x and y to 0 to just center the message when there is no related error tile. * @param y World Y position (TileVirtY) of the error location. Set both x and y to 0 to just center the message when there is no related error tile. @@ -381,7 +382,7 @@ void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc) * @param textref_stack Values to put on the #TextRefStack. * @param extra_msg Extra error message shown in third line. Can be INVALID_STRING_ID. */ -void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x, int y, const GRFFile *textref_stack_grffile, uint textref_stack_size, const uint32_t *textref_stack, StringID extra_msg) +void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, StringParameters &¶ms, WarningLevel wl, int x, int y, const GRFFile *textref_stack_grffile, uint textref_stack_size, const uint32_t *textref_stack, StringID extra_msg) { assert(textref_stack_size == 0 || (textref_stack_grffile != nullptr && textref_stack != nullptr)); if (summary_msg == STR_NULL) summary_msg = STR_EMPTY; @@ -412,7 +413,7 @@ void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel if (_settings_client.gui.errmsg_duration == 0 && !is_critical) return; ErrorMessageData data(summary_msg, detailed_msg, is_critical, x, y, textref_stack_grffile, textref_stack_size, textref_stack, extra_msg); - data.CopyOutDParams(); + data.CopyOutDParams(std::move(params)); ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); if (w != nullptr) { diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index 041189711f..c9a77ab8ee 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -640,7 +640,7 @@ public: case WID_SL_MISSING_NEWGRFS: if (!_network_available) { - ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } else if (_load_check_data.HasNewGrfs()) { ShowMissingContentWindow(_load_check_data.grfconfig); } @@ -695,7 +695,7 @@ public: case WID_SL_CONTENT_DOWNLOAD: if (!_network_available) { - ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } else { assert(this->fop == SLO_LOAD); switch (this->abstract_filetype) { @@ -752,7 +752,7 @@ public: if (this->IsWidgetLowered(WID_SL_DELETE_SELECTION)) { // Delete button clicked if (!FiosDelete(this->filename_editbox.text.buf)) { - ShowErrorMessage(STR_ERROR_UNABLE_TO_DELETE_FILE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_ERROR_UNABLE_TO_DELETE_FILE, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } else { this->InvalidateData(SLIWD_RESCAN_FILES); /* Reset file name to current date on successful delete */ diff --git a/src/game/game_gui.cpp b/src/game/game_gui.cpp index 879428c0c4..a5615c5335 100644 --- a/src/game/game_gui.cpp +++ b/src/game/game_gui.cpp @@ -296,7 +296,7 @@ struct GSConfigWindow : public Window { case WID_GSC_CONTENT_DOWNLOAD: if (!_network_available) { - ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } else { ShowNetworkContentListWindow(nullptr, CONTENT_TYPE_GAME); } diff --git a/src/game/game_instance.cpp b/src/game/game_instance.cpp index 59d6e0d7d0..ceeb767d35 100644 --- a/src/game/game_instance.cpp +++ b/src/game/game_instance.cpp @@ -71,7 +71,7 @@ void GameInstance::Died() const GameInfo *info = Game::GetInfo(); if (info != nullptr) { - ShowErrorMessage(STR_ERROR_AI_PLEASE_REPORT_CRASH, INVALID_STRING_ID, WL_WARNING); + ShowErrorMessage(STR_ERROR_AI_PLEASE_REPORT_CRASH, INVALID_STRING_ID, MakeParameters(), WL_WARNING); if (!info->GetURL().empty()) { ScriptLog::Info("Please report the error to the following URL:"); diff --git a/src/heightmap.cpp b/src/heightmap.cpp index 230a090bad..55be735b46 100644 --- a/src/heightmap.cpp +++ b/src/heightmap.cpp @@ -142,20 +142,20 @@ static bool ReadHeightmapPNG(const char *filename, uint *x, uint *y, byte **map) fp = FioFOpenFile(filename, "rb", HEIGHTMAP_DIR); if (fp == nullptr) { - ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, WL_ERROR); + ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, MakeParameters(), WL_ERROR); return false; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (png_ptr == nullptr) { - ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR); + ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, MakeParameters(), WL_ERROR); fclose(fp); return false; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == nullptr || setjmp(png_jmpbuf(png_ptr))) { - ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR); + ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, MakeParameters(), WL_ERROR); fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); return false; @@ -171,7 +171,7 @@ static bool ReadHeightmapPNG(const char *filename, uint *x, uint *y, byte **map) /* Maps of wrong colour-depth are not used. * (this should have been taken care of by stripping alpha and 16-bit samples on load) */ if ((png_get_channels(png_ptr, info_ptr) != 1) && (png_get_channels(png_ptr, info_ptr) != 3) && (png_get_bit_depth(png_ptr, info_ptr) != 8)) { - ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_IMAGE_TYPE, WL_ERROR); + ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_IMAGE_TYPE, MakeParameters(), WL_ERROR); fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); return false; @@ -181,7 +181,7 @@ static bool ReadHeightmapPNG(const char *filename, uint *x, uint *y, byte **map) uint height = png_get_image_height(png_ptr, info_ptr); if (!IsValidHeightmapDimension(width, height)) { - ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, WL_ERROR); + ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, MakeParameters(), WL_ERROR); fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); return false; @@ -275,21 +275,21 @@ static bool ReadHeightmapBMP(const char *filename, uint *x, uint *y, byte **map) f = FioFOpenFile(filename, "rb", HEIGHTMAP_DIR); if (f == nullptr) { - ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, WL_ERROR); + ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, MakeParameters(), WL_ERROR); return false; } BmpInitializeBuffer(&buffer, f); if (!BmpReadHeader(&buffer, &info, &data)) { - ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, WL_ERROR); + ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, MakeParameters(), WL_ERROR); fclose(f); BmpDestroyData(&data); return false; } if (!IsValidHeightmapDimension(info.width, info.height)) { - ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, WL_ERROR); + ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, MakeParameters(), WL_ERROR); fclose(f); BmpDestroyData(&data); return false; @@ -297,7 +297,7 @@ static bool ReadHeightmapBMP(const char *filename, uint *x, uint *y, byte **map) if (map != nullptr) { if (!BmpReadBitmap(&buffer, &info, &data)) { - ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, WL_ERROR); + ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, MakeParameters(), WL_ERROR); fclose(f); BmpDestroyData(&data); return false; diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 7a4fc70d42..410b09ef12 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -2096,9 +2096,9 @@ CommandCost CmdBuildIndustry(DoCommandFlag flags, TileIndex tile, IndustryType i } if (ret.Failed() && IsLocalCompany()) { if (prospect_success) { - ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING, MakeParameters(), WL_INFO); } else { - ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_PROSPECTING_WAS_UNLUCKY, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_PROSPECTING_WAS_UNLUCKY, MakeParameters(), WL_INFO); } } } @@ -3087,8 +3087,7 @@ void CheckIndustries() if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped. const IndustrySpec *is = GetIndustrySpec(it); - SetDParam(0, is->name); - ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING); + ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, MakeParameters(is->name), WL_WARNING); count++; if (count >= 3) break; // Don't swamp the user with errors. diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 672cd03c85..15c0c42094 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -255,8 +255,7 @@ void CcBuildIndustry(Commands, const CommandCost &result, TileIndex tile, Indust if (indtype < NUM_INDUSTRYTYPES) { const IndustrySpec *indsp = GetIndustrySpec(indtype); if (indsp->enabled) { - SetDParam(0, indsp->name); - ShowErrorMessage(STR_ERROR_CAN_T_BUILD_HERE, result.GetErrorMessage(), WL_INFO, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE); + ShowErrorMessage(STR_ERROR_CAN_T_BUILD_HERE, result.GetErrorMessage(), MakeParameters(indsp->name), WL_INFO, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE); } } } @@ -600,7 +599,7 @@ public: if (!confirmed) return; if (Town::GetNumItems() == 0) { - ShowErrorMessage(STR_ERROR_CAN_T_GENERATE_INDUSTRIES, STR_ERROR_MUST_FOUND_TOWN_FIRST, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_GENERATE_INDUSTRIES, STR_ERROR_MUST_FOUND_TOWN_FIRST, MakeParameters(), WL_INFO); } else { Backup old_generating_world(_generating_world, true, FILE_LINE); BasePersistentStorageArray::SwitchMode(PSM_ENTER_GAMELOOP); @@ -701,8 +700,7 @@ public: if (_game_mode == GM_EDITOR) { /* Show error if no town exists at all */ if (Town::GetNumItems() == 0) { - SetDParam(0, indsp->name); - ShowErrorMessage(STR_ERROR_CAN_T_BUILD_HERE, STR_ERROR_MUST_FOUND_TOWN_FIRST, WL_INFO, pt.x, pt.y); + ShowErrorMessage(STR_ERROR_CAN_T_BUILD_HERE, STR_ERROR_MUST_FOUND_TOWN_FIRST, MakeParameters(indsp->name), WL_INFO, pt.x, pt.y); return; } diff --git a/src/intro_gui.cpp b/src/intro_gui.cpp index 2ffe2d4097..31f8e0d3ce 100644 --- a/src/intro_gui.cpp +++ b/src/intro_gui.cpp @@ -347,7 +347,7 @@ struct SelectGameWindow : public Window { case WID_SGI_PLAY_NETWORK: if (!_network_available) { - ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } else { ShowNetworkGameWindow(); } @@ -365,7 +365,7 @@ struct SelectGameWindow : public Window { case WID_SGI_GRF_SETTINGS: ShowNewGRFSettings(true, true, false, &_grfconfig_newgame); break; case WID_SGI_CONTENT_DOWNLOAD: if (!_network_available) { - ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } else { ShowNetworkContentListWindow(); } diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 64e1d02840..07b441ce41 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -550,8 +550,7 @@ void ShowEstimatedCostOrIncome(Money cost, int x, int y) cost = -cost; msg = STR_MESSAGE_ESTIMATED_INCOME; } - SetDParam(0, cost); - ShowErrorMessage(msg, INVALID_STRING_ID, WL_INFO, x, y); + ShowErrorMessage(msg, INVALID_STRING_ID, MakeParameters(cost), WL_INFO, x, y); } /** diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index 0f8051eef6..d94a629cdf 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -47,7 +47,7 @@ NetworkRecvStatus NetworkGameSocketHandler::CloseConnection(bool) ClientNetworkEmergencySave(); _switch_mode = SM_MENU; _networking = false; - ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); return this->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT); } diff --git a/src/network/network.cpp b/src/network/network.cpp index 2193855661..c15a91aef5 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -287,7 +287,7 @@ uint NetworkCalculateLag(const NetworkClientSocket *cs) void ShowNetworkError(StringID error_string) { _switch_mode = SM_MENU; - ShowErrorMessage(error_string, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(error_string, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); } /** @@ -845,7 +845,7 @@ bool NetworkValidateServerName(std::string &server_name) StrTrimInPlace(server_name); if (!server_name.empty()) return true; - ShowErrorMessage(STR_NETWORK_ERROR_BAD_SERVER_NAME, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_BAD_SERVER_NAME, INVALID_STRING_ID, MakeParameters(), WL_ERROR); return false; } diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 6c9fd88273..a30b051cd0 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -574,7 +574,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FULL(Packet *) Debug(net, 9, "Client::Receive_SERVER_FULL()"); /* We try to join a server which is full */ - ShowErrorMessage(STR_NETWORK_ERROR_SERVER_FULL, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_NETWORK_ERROR_SERVER_FULL, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); return NETWORK_RECV_STATUS_SERVER_FULL; } @@ -584,7 +584,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet * Debug(net, 9, "Client::Receive_SERVER_BANNED()"); /* We try to join a server where we are banned */ - ShowErrorMessage(STR_NETWORK_ERROR_SERVER_BANNED, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_NETWORK_ERROR_SERVER_BANNED, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); return NETWORK_RECV_STATUS_SERVER_BANNED; } @@ -685,10 +685,10 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error]; /* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */ if (error == NETWORK_ERROR_KICKED && p->CanReadFromPacket(1)) { - SetDParamStr(0, p->Recv_string(NETWORK_CHAT_LENGTH)); - ShowErrorMessage(err, STR_NETWORK_ERROR_KICK_MESSAGE, WL_CRITICAL); + auto message = p->Recv_string(NETWORK_CHAT_LENGTH); + ShowErrorMessage(err, STR_NETWORK_ERROR_KICK_MESSAGE, MakeParameters(message), WL_CRITICAL); } else { - ShowErrorMessage(err, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(err, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); } /* Perform an emergency save if we had already entered the game */ @@ -726,7 +726,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(P } /* NewGRF mismatch, bail out */ - ShowErrorMessage(STR_NETWORK_ERROR_NEWGRF_MISMATCH, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_NETWORK_ERROR_NEWGRF_MISMATCH, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); return ret; } @@ -883,7 +883,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet this->last_packet = std::chrono::steady_clock::now(); if (!load_success) { - ShowErrorMessage(STR_NETWORK_ERROR_SAVEGAMEERROR, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_NETWORK_ERROR_SAVEGAMEERROR, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); return NETWORK_RECV_STATUS_SAVEGAME; } /* If the savegame has successfully loaded, ALL windows have been removed, @@ -1123,7 +1123,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SHUTDOWN(Packet /* Only when we're trying to join we really * care about the server shutting down. */ if (this->status >= STATUS_JOIN) { - ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); } if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave(); @@ -1142,7 +1142,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEWGAME(Packet * Client ID modulo 16 + 1 (value 0 means no reconnect). * This way reconnects should be spread out a bit. */ _network_reconnect = _network_own_client_id % 16 + 1; - ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); } if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave(); @@ -1246,8 +1246,8 @@ void ClientNetworkGameSocketHandler::CheckConnection() if (std::chrono::duration_cast(last_lag) == std::chrono::duration_cast(lag)) return; last_lag = lag; - SetDParam(0, std::chrono::duration_cast(lag).count()); - ShowErrorMessage(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION, STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION, WL_INFO); + auto duration = std::chrono::duration_cast(lag).count(); + ShowErrorMessage(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION, STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION, MakeParameters(duration), WL_INFO); } @@ -1339,7 +1339,7 @@ bool NetworkValidateClientName(std::string &client_name) StrTrimInPlace(client_name); if (NetworkIsValidClientName(client_name)) return true; - ShowErrorMessage(STR_NETWORK_ERROR_BAD_PLAYER_NAME, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_BAD_PLAYER_NAME, INVALID_STRING_ID, MakeParameters(), WL_ERROR); return false; } diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index e4a8ea8675..3da7e14605 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -497,7 +497,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p) size_t toRead = p->RemainingBytesToTransfer(); if (toRead != 0 && (size_t)p->TransferOut(TransferOutFWrite, this->curFile) != toRead) { CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); - ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, WL_ERROR); + ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, MakeParameters(), WL_ERROR); this->CloseConnection(); fclose(this->curFile); this->curFile = nullptr; @@ -531,7 +531,7 @@ bool ClientNetworkContentSocketHandler::BeforeDownload() if (filename.empty() || (this->curFile = fopen(filename.c_str(), "wb")) == nullptr) { /* Unless that fails of course... */ CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); - ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, WL_ERROR); + ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, MakeParameters(), WL_ERROR); return false; } } @@ -571,7 +571,7 @@ void ClientNetworkContentSocketHandler::AfterDownload() this->OnDownloadComplete(this->curInfo->id); } else { - ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_EXTRACT, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_EXTRACT, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } } diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 886992130c..6285d7aee9 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -954,7 +954,7 @@ public: void OnConnect(bool success) override { if (!success) { - ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_CONNECT, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_CONNECT, INVALID_STRING_ID, MakeParameters(), WL_ERROR); this->Close(); return; } @@ -1147,7 +1147,7 @@ void ShowNetworkContentListWindow(ContentVector *cv, ContentType type1, ContentT CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST); new NetworkContentListWindow(&_network_content_list_desc, cv != nullptr, types); #else - ShowErrorMessage(STR_CONTENT_NO_ZLIB, STR_CONTENT_NO_ZLIB_SUB, WL_ERROR); + ShowErrorMessage(STR_CONTENT_NO_ZLIB, STR_CONTENT_NO_ZLIB_SUB, MakeParameters(), WL_ERROR); /* Connection failed... clean up the mess */ if (cv != nullptr) { for (ContentInfo *ci : *cv) delete ci; diff --git a/src/network/network_coordinator.cpp b/src/network/network_coordinator.cpp index b049376cc9..9dbba07e83 100644 --- a/src/network/network_coordinator.cpp +++ b/src/network/network_coordinator.cpp @@ -135,7 +135,7 @@ bool ClientNetworkCoordinatorSocketHandler::Receive_GC_ERROR(Packet *p) return false; case NETWORK_COORDINATOR_ERROR_REGISTRATION_FAILED: - ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_REGISTRATION_FAILED, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_REGISTRATION_FAILED, INVALID_STRING_ID, MakeParameters(), WL_ERROR); /* To prevent that we constantly try to reconnect, switch to local game. */ _settings_client.network.server_game_type = SERVER_GAME_TYPE_LOCAL; @@ -159,7 +159,7 @@ bool ClientNetworkCoordinatorSocketHandler::Receive_GC_ERROR(Packet *p) } case NETWORK_COORDINATOR_ERROR_REUSE_OF_INVITE_CODE: - ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_REUSE_OF_INVITE_CODE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_REUSE_OF_INVITE_CODE, INVALID_STRING_ID, MakeParameters(), WL_ERROR); /* To prevent that we constantly battle for the same invite-code, switch to local game. */ _settings_client.network.server_game_type = SERVER_GAME_TYPE_LOCAL; @@ -184,7 +184,7 @@ bool ClientNetworkCoordinatorSocketHandler::Receive_GC_REGISTER_ACK(Packet *p) _network_server_connection_type = (ConnectionType)p->Recv_uint8(); if (_network_server_connection_type == CONNECTION_TYPE_ISOLATED) { - ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_ISOLATED, STR_NETWORK_ERROR_COORDINATOR_ISOLATED_DETAIL, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_COORDINATOR_ISOLATED, STR_NETWORK_ERROR_COORDINATOR_ISOLATED_DETAIL, MakeParameters(), WL_ERROR); } /* Users can change the invite code in the settings, but this has no effect diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp index cf83224830..6caf6dce5b 100644 --- a/src/newgrf_commons.cpp +++ b/src/newgrf_commons.cpp @@ -502,10 +502,7 @@ void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res) if (!HasBit(grfconfig->grf_bugs, GBUG_UNKNOWN_CB_RESULT)) { SetBit(grfconfig->grf_bugs, GBUG_UNKNOWN_CB_RESULT); - SetDParamStr(0, grfconfig->GetName()); - SetDParam(1, cbid); - SetDParam(2, cb_res); - ShowErrorMessage(STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT, WL_CRITICAL); + ShowErrorMessage(STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT, MakeParameters(grfconfig->GetName(), cbid, cb_res), WL_CRITICAL); } /* debug output */ diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index d3d7ad4fe0..94d06bbad4 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -51,18 +51,21 @@ void ShowNewGRFError() /* Only show Fatal and Error level messages */ if (!c->error.has_value() || (c->error->severity != STR_NEWGRF_ERROR_MSG_FATAL && c->error->severity != STR_NEWGRF_ERROR_MSG_ERROR)) continue; - SetDParamStr(0, c->GetName()); - SetDParam (1, c->error->message != STR_NULL ? c->error->message : STR_JUST_RAW_STRING); - SetDParamStr(2, c->error->custom_message); - SetDParamStr(3, c->filename); - SetDParamStr(4, c->error->data); + ArrayStringParameters<20> params; + assert(c->error->param_value.size() < 20 - 5); + + params.SetParam(0, c->GetName()); + params.SetParam(1, c->error->message != STR_NULL ? c->error->message : STR_JUST_RAW_STRING); + params.SetParam(2, c->error->custom_message); + params.SetParam(3, c->filename); + params.SetParam(4, c->error->data); for (uint i = 0; i < c->error->param_value.size(); i++) { - SetDParam(5 + i, c->error->param_value[i]); + params.SetParam(5 + i, c->error->param_value[i]); } if (c->error->severity == STR_NEWGRF_ERROR_MSG_FATAL) { - ShowErrorMessage(STR_NEWGRF_ERROR_FATAL_POPUP, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_NEWGRF_ERROR_FATAL_POPUP, INVALID_STRING_ID, std::move(params), WL_CRITICAL); } else { - ShowErrorMessage(STR_NEWGRF_ERROR_POPUP, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NEWGRF_ERROR_POPUP, INVALID_STRING_ID, std::move(params), WL_ERROR); } break; } @@ -1153,7 +1156,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { case WID_NS_CONTENT_DOWNLOAD: case WID_NS_CONTENT_DOWNLOAD2: if (!_network_available) { - ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } else { this->CloseChildWindows(WC_QUERY_STRING); // Remove the parameter query window @@ -1533,14 +1536,14 @@ private: for (list = &this->actives; *list != nullptr; list = &(*list)->next, ins_pos--) { if (ins_pos == 0) entry = list; // Insert position? Save. if ((*list)->ident.grfid == this->avail_sel->ident.grfid) { - ShowErrorMessage(STR_NEWGRF_DUPLICATE_GRFID, INVALID_STRING_ID, WL_INFO); + ShowErrorMessage(STR_NEWGRF_DUPLICATE_GRFID, INVALID_STRING_ID, MakeParameters(), WL_INFO); return false; } if (!HasBit((*list)->flags, GCF_STATIC)) count++; } if (entry == nullptr) entry = list; if (count >= NETWORK_MAX_GRF_COUNT) { - ShowErrorMessage(STR_NEWGRF_TOO_MANY_NEWGRFS, INVALID_STRING_ID, WL_INFO); + ShowErrorMessage(STR_NEWGRF_TOO_MANY_NEWGRFS, INVALID_STRING_ID, MakeParameters(), WL_INFO); return false; } diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index b2db76a431..65837b120f 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -614,9 +614,7 @@ void IndustryProductionCallback(Industry *ind, int reason) * 'loop' is provided as 16 bits to the newgrf, so abort when those are exceeded. */ if (loop >= 0x10000) { /* display error message */ - SetDParamStr(0, spec->grf_prop.grffile->filename); - SetDParam(1, spec->name); - ShowErrorMessage(STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK, WL_WARNING); + ShowErrorMessage(STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK, MakeParameters(spec->grf_prop.grffile->filename, spec->name), WL_WARNING); /* abort the function early, this error isn't critical and will allow the game to continue to run */ break; @@ -629,10 +627,12 @@ void IndustryProductionCallback(Industry *ind, int reason) if (group->version == 0xFF) { /* Result was marked invalid on load, display error message */ - SetDParamStr(0, spec->grf_prop.grffile->filename); - SetDParam(1, spec->name); - SetDParam(2, ind->location.tile); - ShowErrorMessage(STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK, WL_WARNING); + auto params = MakeParameters( + spec->grf_prop.grffile->filename, + spec->name, + ind->location.tile + ); + ShowErrorMessage(STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK, std::move(params), WL_WARNING); /* abort the function early, this error isn't critical and will allow the game to continue to run */ break; diff --git a/src/openttd.cpp b/src/openttd.cpp index 3af31509e1..367bb59dcd 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1126,8 +1126,7 @@ void SwitchToMode(SwitchMode new_mode) ResetWindowSystem(); if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_NORMAL, NO_DIRECTORY)) { - SetDParamStr(0, GetSaveLoadErrorString()); - ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, MakeParameters(GetSaveLoadErrorString()), WL_CRITICAL); } else { if (_file_to_saveload.abstract_ftype == FT_SCENARIO) { OnStartScenario(); @@ -1169,8 +1168,7 @@ void SwitchToMode(SwitchMode new_mode) /* Cancel the saveload pausing */ Command::Post(PM_PAUSED_SAVELOAD, false); } else { - SetDParamStr(0, GetSaveLoadErrorString()); - ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, MakeParameters(GetSaveLoadErrorString()), WL_CRITICAL); } UpdateSocialIntegration(GM_EDITOR); @@ -1187,7 +1185,7 @@ void SwitchToMode(SwitchMode new_mode) case SM_MENU: // Switch to game intro menu LoadIntroGame(); if (BaseSounds::ini_set.empty() && BaseSounds::GetUsedSet()->fallback && SoundDriver::GetInstance()->HasOutput()) { - ShowErrorMessage(STR_WARNING_FALLBACK_SOUNDSET, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_WARNING_FALLBACK_SOUNDSET, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); BaseSounds::ini_set = BaseSounds::GetUsedSet()->name; } if (_settings_client.network.participate_survey == PS_ASK) { @@ -1205,8 +1203,7 @@ void SwitchToMode(SwitchMode new_mode) case SM_SAVE_GAME: // Save game. /* Make network saved games on pause compatible to singleplayer mode */ if (SaveOrLoad(_file_to_saveload.name, SLO_SAVE, DFT_GAME_FILE, NO_DIRECTORY) != SL_OK) { - SetDParamStr(0, GetSaveLoadErrorString()); - ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, MakeParameters(GetSaveLoadErrorString()), WL_ERROR); } else { CloseWindowById(WC_SAVELOAD, 0); } diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 62780c4850..aec8254065 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -1494,7 +1494,7 @@ public: })) { OnVehicleSelect(*begin); } else { - ShowErrorMessage(STR_ERROR_CAN_T_COPY_ORDER_LIST, STR_ERROR_CAN_T_COPY_ORDER_VEHICLE_LIST, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_COPY_ORDER_LIST, STR_ERROR_CAN_T_COPY_ORDER_VEHICLE_LIST, MakeParameters(), WL_INFO); } } else { /* If CTRL is pressed: If all the vehicles in this list share orders, then copy orders */ @@ -1503,7 +1503,7 @@ public: })) { OnVehicleSelect(*begin); } else { - ShowErrorMessage(STR_ERROR_CAN_T_SHARE_ORDER_LIST, STR_ERROR_CAN_T_SHARE_ORDER_VEHICLE_LIST, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_SHARE_ORDER_LIST, STR_ERROR_CAN_T_SHARE_ORDER_VEHICLE_LIST, MakeParameters(), WL_INFO); } } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index b81c8730d2..fec14010fb 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -723,8 +723,8 @@ bool AfterLoadGame() } switch (gcf_res) { - case GLC_COMPATIBLE: ShowErrorMessage(STR_NEWGRF_COMPATIBLE_LOAD_WARNING, INVALID_STRING_ID, WL_CRITICAL); break; - case GLC_NOT_FOUND: ShowErrorMessage(STR_NEWGRF_DISABLED_WARNING, INVALID_STRING_ID, WL_CRITICAL); _pause_mode = PM_PAUSED_ERROR; break; + case GLC_COMPATIBLE: ShowErrorMessage(STR_NEWGRF_COMPATIBLE_LOAD_WARNING, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); break; + case GLC_NOT_FOUND: ShowErrorMessage(STR_NEWGRF_DISABLED_WARNING, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); _pause_mode = PM_PAUSED_ERROR; break; default: break; } @@ -1915,7 +1915,7 @@ bool AfterLoadGame() * There would be trams without tram track under causing crashes sooner or later. */ for (RoadVehicle *v : RoadVehicle::Iterate()) { if (v->First() == v && HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM)) { - ShowErrorMessage(STR_WARNING_LOADGAME_REMOVED_TRAMS, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_WARNING_LOADGAME_REMOVED_TRAMS, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); delete v; } } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 78032edc9d..d6825f8707 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -2679,8 +2679,7 @@ static const SaveLoadFormat *GetSavegameFormat(const std::string &full_name, byt size_t processed; long level = std::stol(complevel, &processed, 10); if (processed == 0 || level != Clamp(level, slf->min_compression, slf->max_compression)) { - SetDParamStr(0, complevel); - ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, WL_CRITICAL); + ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL, MakeParameters(complevel), WL_CRITICAL); } else { *compression_level = level; } @@ -2689,9 +2688,7 @@ static const SaveLoadFormat *GetSavegameFormat(const std::string &full_name, byt } } - SetDParamStr(0, name); - SetDParamStr(1, def->name); - ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM, WL_CRITICAL); + ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM, MakeParameters(name, def->name), WL_CRITICAL); } *compression_level = def->default_compression; return def; @@ -2772,8 +2769,7 @@ const char *GetSaveLoadErrorString() /** Show a gui message when saving has failed */ static void SaveFileError() { - SetDParamStr(0, GetSaveLoadErrorString()); - ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, MakeParameters(GetSaveLoadErrorString()), WL_ERROR); SaveFileDone(); } @@ -3052,7 +3048,7 @@ SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop, /* An instance of saving is already active, so don't go saving again */ if (_sl.saveinprogress && fop == SLO_SAVE && dft == DFT_GAME_FILE && threaded) { /* if not an autosave, but a user action, show error message */ - if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR); + if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, MakeParameters(), WL_ERROR); return SL_OK; } WaitTillSaved(); @@ -3150,7 +3146,7 @@ void DoAutoOrNetsave(FiosNumberedSaveName &counter) Debug(sl, 2, "Autosaving to '{}'", filename); if (SaveOrLoad(filename, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR) != SL_OK) { - ShowErrorMessage(STR_ERROR_AUTOSAVE_FAILED, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_ERROR_AUTOSAVE_FAILED, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } } diff --git a/src/screenshot.cpp b/src/screenshot.cpp index b57e484bfe..8bfd8cec87 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -952,15 +952,12 @@ static bool RealMakeScreenshot(ScreenshotType t, std::string name, uint32_t widt if (ret) { if (t == SC_HEIGHTMAP) { - SetDParamStr(0, _screenshot_name); - SetDParam(1, _heightmap_highest_peak); - ShowErrorMessage(STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING); + ShowErrorMessage(STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY, INVALID_STRING_ID, MakeParameters(_screenshot_name, _heightmap_highest_peak), WL_WARNING); } else { - SetDParamStr(0, _screenshot_name); - ShowErrorMessage(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING); + ShowErrorMessage(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, INVALID_STRING_ID, MakeParameters(_screenshot_name), WL_WARNING); } } else { - ShowErrorMessage(STR_ERROR_SCREENSHOT_FAILED, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_ERROR_SCREENSHOT_FAILED, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } return ret; diff --git a/src/script/script_gui.cpp b/src/script/script_gui.cpp index 7712bad358..f973bc07fc 100644 --- a/src/script/script_gui.cpp +++ b/src/script/script_gui.cpp @@ -1354,7 +1354,7 @@ Window *ShowScriptDebugWindow(CompanyID show_company, bool new_window) } return new ScriptDebugWindow(&_script_debug_desc, i, show_company); } else { - ShowErrorMessage(STR_ERROR_AI_DEBUG_SERVER_ONLY, INVALID_STRING_ID, WL_INFO); + ShowErrorMessage(STR_ERROR_AI_DEBUG_SERVER_ONLY, INVALID_STRING_ID, MakeParameters(), WL_INFO); } return nullptr; diff --git a/src/settings.cpp b/src/settings.cpp index 18c4790818..635bacbf97 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1015,8 +1015,7 @@ static void GraphicsSetLoadConfig(IniFile &ini) extra_params.resize(lengthof(GRFConfig::param)); int count = ParseIntList(item->value->c_str(), &extra_params.front(), extra_params.size()); if (count < 0) { - SetDParamStr(0, BaseGraphics::ini_data.name); - ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, WL_CRITICAL); + ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, MakeParameters(BaseGraphics::ini_data.name), WL_CRITICAL); count = 0; } extra_params.resize(count); @@ -1082,8 +1081,7 @@ static GRFConfig *GRFLoadConfig(const IniFile &ini, const char *grpname, bool is if (item.value.has_value() && !item.value->empty()) { int count = ParseIntList(item.value->c_str(), c->param.data(), c->param.size()); if (count < 0) { - SetDParamStr(0, filename); - ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, WL_CRITICAL); + ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, MakeParameters(filename), WL_CRITICAL); count = 0; } c->num_params = count; @@ -1103,8 +1101,7 @@ static GRFConfig *GRFLoadConfig(const IniFile &ini, const char *grpname, bool is SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN); } - SetDParamStr(0, filename.empty() ? item.name.c_str() : filename); - ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_GRF, WL_CRITICAL); + ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_GRF, MakeParameters(filename.empty() ? item.name.c_str() : filename), WL_CRITICAL); delete c; continue; } @@ -1113,9 +1110,7 @@ static GRFConfig *GRFLoadConfig(const IniFile &ini, const char *grpname, bool is bool duplicate = false; for (const GRFConfig *gc = first; gc != nullptr; gc = gc->next) { if (gc->ident.grfid == c->ident.grfid) { - SetDParamStr(0, c->filename); - SetDParamStr(1, gc->filename); - ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_DUPLICATE_GRFID, WL_CRITICAL); + ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_DUPLICATE_GRFID, MakeParameters(c->filename, gc->filename), WL_CRITICAL); duplicate = true; break; } @@ -1130,7 +1125,7 @@ static GRFConfig *GRFLoadConfig(const IniFile &ini, const char *grpname, bool is SetBit(c->flags, GCF_STATIC); } else if (++num_grfs > NETWORK_MAX_GRF_COUNT) { /* Check we will not load more non-static NewGRFs than allowed. This could trigger issues for game servers. */ - ShowErrorMessage(STR_CONFIG_ERROR, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED, WL_CRITICAL); + ShowErrorMessage(STR_CONFIG_ERROR, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED, MakeParameters(), WL_CRITICAL); break; } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 26e56fcdbd..e3ab70b394 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -716,7 +716,7 @@ struct GameOptionsWindow : Window { case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off /* try to toggle full-screen on/off */ if (!ToggleFullScreen(!_fullscreen)) { - ShowErrorMessage(STR_ERROR_FULLSCREEN_FAILED, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_ERROR_FULLSCREEN_FAILED, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } this->SetWidgetLoweredState(WID_GO_FULLSCREEN_BUTTON, _fullscreen); this->SetWidgetDirty(WID_GO_FULLSCREEN_BUTTON); @@ -724,7 +724,7 @@ struct GameOptionsWindow : Window { case WID_GO_VIDEO_ACCEL_BUTTON: _video_hw_accel = !_video_hw_accel; - ShowErrorMessage(STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART, INVALID_STRING_ID, WL_INFO); + ShowErrorMessage(STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART, INVALID_STRING_ID, MakeParameters(), WL_INFO); this->SetWidgetLoweredState(WID_GO_VIDEO_ACCEL_BUTTON, _video_hw_accel); this->SetWidgetDirty(WID_GO_VIDEO_ACCEL_BUTTON); #ifndef __APPLE__ @@ -867,7 +867,7 @@ struct GameOptionsWindow : Window { if (!list.empty()) { ShowDropDownList(this, std::move(list), selected, widget); } else { - if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(STR_ERROR_RESOLUTION_LIST_FAILED, INVALID_STRING_ID, WL_ERROR); + if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(STR_ERROR_RESOLUTION_LIST_FAILED, INVALID_STRING_ID, MakeParameters(), WL_ERROR); } break; } @@ -923,7 +923,7 @@ struct GameOptionsWindow : Window { if (_settings_client.gui.refresh_rate > 60) { /* Show warning to the user that this refresh rate might not be suitable on * larger maps with many NewGRFs and vehicles. */ - ShowErrorMessage(STR_GAME_OPTIONS_REFRESH_RATE_WARNING, INVALID_STRING_ID, WL_INFO); + ShowErrorMessage(STR_GAME_OPTIONS_REFRESH_RATE_WARNING, INVALID_STRING_ID, MakeParameters(), WL_INFO); } break; } diff --git a/src/settings_table.cpp b/src/settings_table.cpp index 224f9a1174..321c162431 100644 --- a/src/settings_table.cpp +++ b/src/settings_table.cpp @@ -352,7 +352,7 @@ static void MaxNoAIsChange(int32_t) if (GetGameSettings().difficulty.max_no_competitors != 0 && AI::GetInfoList()->empty() && (!_networking || _network_server)) { - ShowErrorMessage(STR_WARNING_NO_SUITABLE_AI, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_WARNING_NO_SUITABLE_AI, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); } InvalidateWindowClassesData(WC_GAME_OPTIONS, 0); @@ -388,39 +388,39 @@ static bool CheckFreeformEdges(int32_t &new_value) 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); + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_EMPTY, INVALID_STRING_ID, MakeParameters(), 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); + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_EMPTY, INVALID_STRING_ID, MakeParameters(), WL_ERROR); return false; } } } else { for (uint i = 0; i < Map::MaxX(); i++) { if (TileHeight(TileXY(i, 1)) != 0) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, MakeParameters(), WL_ERROR); return false; } } for (uint i = 1; i < Map::MaxX(); i++) { if (!IsTileType(TileXY(i, Map::MaxY() - 1), MP_WATER) || TileHeight(TileXY(1, Map::MaxY())) != 0) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, MakeParameters(), WL_ERROR); return false; } } for (uint i = 0; i < Map::MaxY(); i++) { if (TileHeight(TileXY(1, i)) != 0) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, MakeParameters(), WL_ERROR); return false; } } for (uint i = 1; i < Map::MaxY(); i++) { if (!IsTileType(TileXY(Map::MaxX() - 1, i), MP_WATER) || TileHeight(TileXY(Map::MaxX(), i)) != 0) { - ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, MakeParameters(), WL_ERROR); return false; } } @@ -458,7 +458,7 @@ static bool CheckDynamicEngines(int32_t &) if (_game_mode == GM_MENU) return true; if (!EngineOverrideManager::ResetToCurrentNewGRFConfig()) { - ShowErrorMessage(STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES, INVALID_STRING_ID, MakeParameters(), WL_ERROR); return false; } @@ -474,7 +474,7 @@ static bool CheckMaxHeightLevel(int32_t &new_value) * If yes, disallow the change. */ for (TileIndex t = 0; t < Map::Size(); t++) { if ((int32_t)TileHeight(t) > new_value) { - ShowErrorMessage(STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN, INVALID_STRING_ID, MakeParameters(), WL_ERROR); /* Return old, unchanged value */ return false; } diff --git a/src/spriteloader/grf.cpp b/src/spriteloader/grf.cpp index f88182935a..bdfbc3ce61 100644 --- a/src/spriteloader/grf.cpp +++ b/src/spriteloader/grf.cpp @@ -36,8 +36,7 @@ static bool WarnCorruptSprite(const SpriteFile &file, size_t file_pos, int line) { static byte warning_level = 0; if (warning_level == 0) { - SetDParamStr(0, file.GetSimplifiedFilename()); - ShowErrorMessage(STR_NEWGRF_ERROR_CORRUPT_SPRITE, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_NEWGRF_ERROR_CORRUPT_SPRITE, INVALID_STRING_ID, MakeParameters(file.GetSimplifiedFilename()), WL_ERROR); } Debug(sprite, warning_level, "[{}] Loading corrupted sprite from {} at position {}", line, file.GetSimplifiedFilename(), file_pos); warning_level = 6; diff --git a/src/strings.cpp b/src/strings.cpp index 8fbfffe5b7..6a1205d541 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -2314,8 +2314,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) * with the colour marker. */ static std::string err_str("XXXThe current font is missing some of the characters used in the texts for this language. Using system fallback font instead."); Utf8Encode(err_str.data(), SCC_YELLOW); - SetDParamStr(0, err_str); - ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_WARNING); + ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, MakeParameters(err_str), WL_WARNING); } if (bad_font && base_font) { @@ -2335,8 +2334,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) * the string, which takes exactly three characters, so it replaces the "XXX" with the colour marker. */ static std::string err_str("XXXThe current font is missing some of the characters used in the texts for this language. Read the readme to see how to solve this."); Utf8Encode(err_str.data(), SCC_YELLOW); - SetDParamStr(0, err_str); - ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_WARNING); + ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, MakeParameters(err_str), WL_WARNING); /* Reset the font width */ LoadStringWidthTable(searcher->Monospace()); @@ -2363,8 +2361,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) if (_current_text_dir != TD_LTR) { static std::string err_str("XXXThis version of OpenTTD does not support right-to-left languages. Recompile with ICU + Harfbuzz enabled."); Utf8Encode(err_str.data(), SCC_YELLOW); - SetDParamStr(0, err_str); - ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); + ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, MakeParameters(err_str), WL_ERROR); } #endif /* !(WITH_ICU_I18N && WITH_HARFBUZZ) && !WITH_UNISCRIBE && !WITH_COCOA */ } diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index c7ab11ff3b..94129f719e 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -2338,7 +2338,7 @@ bool GenerateTowns(TownLayout layout) /* If there are no towns at all and we are generating new game, bail out */ if (Town::GetNumItems() == 0 && _game_mode != GM_EDITOR) { - ShowErrorMessage(STR_ERROR_COULD_NOT_CREATE_TOWN, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_ERROR_COULD_NOT_CREATE_TOWN, INVALID_STRING_ID, MakeParameters(), WL_CRITICAL); } return false; // we are still without a town? we failed, simply @@ -3388,7 +3388,7 @@ static CommandCost TownActionBribe(Town *t, DoCommandFlag flags) /* only show error message to the executing player. All errors are handled command.c * but this is special, because it can only 'fail' on a DC_EXEC */ - if (IsLocalCompany()) ShowErrorMessage(STR_ERROR_BRIBE_FAILED, INVALID_STRING_ID, WL_INFO); + if (IsLocalCompany()) ShowErrorMessage(STR_ERROR_BRIBE_FAILED, INVALID_STRING_ID, MakeParameters(), WL_INFO); /* decrease by a lot! * ChangeTownRating is only for stuff in demolishing. Bribe failure should diff --git a/src/town_gui.cpp b/src/town_gui.cpp index b283180dc1..3a018da732 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -1240,7 +1240,7 @@ public: Backup old_generating_world(_generating_world, true, FILE_LINE); UpdateNearestTownForRoadTiles(true); if (!GenerateTowns(this->town_layout)) { - ShowErrorMessage(STR_ERROR_CAN_T_GENERATE_TOWN, STR_ERROR_NO_SPACE_FOR_TOWN, WL_INFO); + ShowErrorMessage(STR_ERROR_CAN_T_GENERATE_TOWN, STR_ERROR_NO_SPACE_FOR_TOWN, MakeParameters(), WL_INFO); } UpdateNearestTownForRoadTiles(false); old_generating_world.Restore(); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 5d019380d2..45cf5a0cae 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -85,9 +85,7 @@ void CheckTrainsLengths() if ((w->track != TRACK_BIT_DEPOT && std::max(abs(u->x_pos - w->x_pos), abs(u->y_pos - w->y_pos)) != u->CalcNextVehicleOffset()) || (w->track == TRACK_BIT_DEPOT && TicksToLeaveDepot(u) <= 0)) { - SetDParam(0, v->index); - SetDParam(1, v->owner); - ShowErrorMessage(STR_BROKEN_VEHICLE_LENGTH, INVALID_STRING_ID, WL_CRITICAL); + ShowErrorMessage(STR_BROKEN_VEHICLE_LENGTH, INVALID_STRING_ID, MakeParameters(v->index, v->owner), WL_CRITICAL); if (!_networking && first) { first = false; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 5acb56f853..d843944835 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -324,9 +324,7 @@ void ShowNewGrfVehicleError(EngineID engine, StringID part1, StringID part2, GRF if (!HasBit(grfconfig->grf_bugs, bug_type)) { SetBit(grfconfig->grf_bugs, bug_type); - SetDParamStr(0, grfconfig->GetName()); - SetDParam(1, engine); - ShowErrorMessage(part1, part2, WL_CRITICAL); + ShowErrorMessage(part1, part2, MakeParameters(grfconfig->GetName(), engine), WL_CRITICAL); if (!_networking) Command::Do(DC_EXEC, critical ? PM_PAUSED_ERROR : PM_PAUSED_NORMAL, true); } From 5a7a1f95431f942b30098634500d0167376ce9af Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 2 Feb 2024 18:54:15 +0100 Subject: [PATCH 3/7] Codechange: use StringParameters to pass parameters for News strings --- src/aircraft_cmd.cpp | 7 +++--- src/autoreplace_cmd.cpp | 14 +++++++----- src/company_cmd.cpp | 17 +++++++-------- src/currency.cpp | 2 +- src/disaster_vehicle.cpp | 14 +++++------- src/economy.cpp | 23 ++++++++++---------- src/engine.cpp | 4 +--- src/industry_cmd.cpp | 47 ++++++++++++++++++++-------------------- src/news_func.h | 22 +++++++++---------- src/news_gui.cpp | 13 ++++++----- src/news_type.h | 2 +- src/order_cmd.cpp | 3 +-- src/roadveh_cmd.cpp | 7 +++--- src/ship_cmd.cpp | 2 +- src/station_cmd.cpp | 4 +--- src/subsidy.cpp | 40 +++++++++++++++++++--------------- src/subsidy_func.h | 2 +- src/subsidy_gui.cpp | 8 +++++-- src/town_cmd.cpp | 24 +++++++++----------- src/train_cmd.cpp | 8 +++---- src/vehicle.cpp | 19 +++++----------- src/water_cmd.cpp | 3 +-- 22 files changed, 136 insertions(+), 149 deletions(-) diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 6002a05f20..439f619b60 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -1350,7 +1350,7 @@ static void CrashAirplane(Aircraft *v) newstype = NT_ACCIDENT_OTHER; } - AddTileNewsItem(newsitem, newstype, vt, nullptr, st != nullptr ? st->index : INVALID_STATION); + AddTileNewsItem(newsitem, MakeParameters(), newstype, vt, nullptr, st != nullptr ? st->index : INVALID_STATION); ModifyStationRatingAround(vt, v->owner, -160, 30); if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v); @@ -1401,10 +1401,10 @@ static void AircraftEntersTerminal(Aircraft *v) /* Check if station was ever visited before */ if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) { st->had_vehicle_of_type |= HVOT_AIRCRAFT; - SetDParam(0, st->index); /* show newsitem of celebrating citizens */ AddVehicleNewsItem( STR_NEWS_FIRST_AIRCRAFT_ARRIVAL, + MakeParameters(st->index), (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, v->index, st->index @@ -2052,8 +2052,7 @@ static void AircraftHandleDestTooFar(Aircraft *v, bool too_far) AI::NewEvent(v->owner, new ScriptEventAircraftDestTooFar(v->index)); if (v->owner == _local_company) { /* Post a news message. */ - SetDParam(0, v->index); - AddVehicleAdviceNewsItem(STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v->index); + AddVehicleAdviceNewsItem(STR_NEWS_AIRCRAFT_DEST_TOO_FAR, MakeParameters(v->index), v->index); } } return; diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 5d6b6eeaaf..e50bbcd726 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -333,20 +333,22 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic if (!IsValidCargoID(refit_cargo)) { if (!IsLocalCompany()) return CommandCost(); - SetDParam(0, old_veh->index); + ArrayStringParameters<3> params; + + params.SetParam(0, old_veh->index); int order_id = GetIncompatibleRefitOrderIdForAutoreplace(old_veh, e); if (order_id != -1) { /* Orders contained a refit order that is incompatible with the new vehicle. */ - SetDParam(1, STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT); - SetDParam(2, order_id + 1); // 1-based indexing for display + params.SetParam(1, STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT); + params.SetParam(2, order_id + 1); // 1-based indexing for display } else { /* Current cargo is incompatible with the new vehicle. */ - SetDParam(1, STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO); - SetDParam(2, CargoSpec::Get(old_veh->cargo_type)->name); + params.SetParam(1, STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO); + params.SetParam(2, CargoSpec::Get(old_veh->cargo_type)->name); } - AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_AUTORENEW_FAILED, old_veh->index); + AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_AUTORENEW_FAILED, std::move(params), old_veh->index); return CommandCost(); } diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 8677367ff7..4277cf1155 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -424,11 +424,13 @@ set_name:; if (c->is_ai) { CompanyNewsInformation *cni = new CompanyNewsInformation(c); - SetDParam(0, STR_NEWS_COMPANY_LAUNCH_TITLE); - SetDParam(1, STR_NEWS_COMPANY_LAUNCH_DESCRIPTION); - SetDParamStr(2, cni->company_name); - SetDParam(3, t->index); - AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NT_COMPANY_INFO, NF_COMPANY, NR_TILE, c->last_build_coordinate.base(), NR_NONE, UINT32_MAX, cni); + auto params = MakeParameters( + STR_NEWS_COMPANY_LAUNCH_TITLE, + STR_NEWS_COMPANY_LAUNCH_DESCRIPTION, + cni->company_name, + t->index + ); + AddNewsItem(STR_MESSAGE_NEWS_FORMAT, std::move(params), NT_COMPANY_INFO, NF_COMPANY, NR_TILE, c->last_build_coordinate.base(), NR_NONE, UINT32_MAX, cni); } return; } @@ -940,10 +942,7 @@ CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID CompanyNewsInformation *cni = new CompanyNewsInformation(c); /* Show the bankrupt news */ - SetDParam(0, STR_NEWS_COMPANY_BANKRUPT_TITLE); - SetDParam(1, STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION); - SetDParamStr(2, cni->company_name); - AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni); + AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, MakeParameters(STR_NEWS_COMPANY_BANKRUPT_TITLE, STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION, cni->company_name), cni); /* Remove the company */ ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER); diff --git a/src/currency.cpp b/src/currency.cpp index 323d302582..4817f8b7d1 100644 --- a/src/currency.cpp +++ b/src/currency.cpp @@ -146,7 +146,7 @@ static IntervalTimer _check_switch_to_euro({TimerGameCalendar _currency_specs[_settings_game.locale.currency].to_euro != CF_ISEURO && TimerGameCalendar::year >= _currency_specs[_settings_game.locale.currency].to_euro) { _settings_game.locale.currency = 2; // this is the index of euro above. - AddNewsItem(STR_NEWS_EURO_INTRODUCTION, NT_ECONOMY, NF_NORMAL); + AddNewsItem(STR_NEWS_EURO_INTRODUCTION, MakeParameters(), NT_ECONOMY, NF_NORMAL); } }); diff --git a/src/disaster_vehicle.cpp b/src/disaster_vehicle.cpp index 98f03f9679..0a6d1ee0da 100644 --- a/src/disaster_vehicle.cpp +++ b/src/disaster_vehicle.cpp @@ -245,8 +245,7 @@ static bool DisasterTick_Zeppeliner(DisasterVehicle *v) v->state = 1; v->age = 0; - SetDParam(0, GetStationIndex(v->tile)); - AddTileNewsItem(STR_NEWS_DISASTER_ZEPPELIN, NT_ACCIDENT, v->tile); + AddTileNewsItem(STR_NEWS_DISASTER_ZEPPELIN, MakeParameters(GetStationIndex(v->tile)), NT_ACCIDENT, v->tile); AI::NewEvent(GetTileOwner(v->tile), new ScriptEventDisasterZeppelinerCrashed(GetStationIndex(v->tile))); } } @@ -380,7 +379,7 @@ static bool DisasterTick_Ufo(DisasterVehicle *v) if (u->crashed_ctr == 0) { u->Crash(); - AddTileNewsItem(STR_NEWS_DISASTER_SMALL_UFO, NT_ACCIDENT, u->tile); + AddTileNewsItem(STR_NEWS_DISASTER_SMALL_UFO, MakeParameters(), NT_ACCIDENT, u->tile); AI::NewEvent(u->owner, new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO)); Game::NewEvent(new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO)); @@ -458,8 +457,7 @@ static bool DisasterTick_Aircraft(DisasterVehicle *v, uint16_t image_override, b Industry *i = Industry::Get(v->dest_tile.base()); // Industry destructor calls ReleaseDisastersTargetingIndustry, so this is valid DestructIndustry(i); - SetDParam(0, i->town->index); - AddIndustryNewsItem(news_message, NT_ACCIDENT, i->index); + AddIndustryNewsItem(news_message, MakeParameters(i->town->index), NT_ACCIDENT, i->index); if (_settings_client.sound.disaster) SndPlayTileFx(SND_12_EXPLOSION, i->location.tile); } } else if (v->state == 0) { @@ -554,8 +552,7 @@ static bool DisasterTick_Big_Ufo(DisasterVehicle *v) } Town *t = ClosestTownFromTile(v->dest_tile, UINT_MAX); - SetDParam(0, t->index); - AddTileNewsItem(STR_NEWS_DISASTER_BIG_UFO, NT_ACCIDENT, v->tile); + AddTileNewsItem(STR_NEWS_DISASTER_BIG_UFO, MakeParameters(t->index), NT_ACCIDENT, v->tile); if (!Vehicle::CanAllocateItem(2)) { delete v; @@ -880,8 +877,7 @@ static void Disaster_CoalMine_Init() for (m = 0; m < 15; m++) { for (const Industry *i : Industry::Iterate()) { if ((GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_CAN_SUBSIDENCE) && --index < 0) { - SetDParam(0, i->town->index); - AddTileNewsItem(STR_NEWS_DISASTER_COAL_MINE_SUBSIDENCE, NT_ACCIDENT, i->location.tile + TileDiffXY(1, 1)); // keep the news, even when the mine closes + AddTileNewsItem(STR_NEWS_DISASTER_COAL_MINE_SUBSIDENCE, MakeParameters(i->town->index), NT_ACCIDENT, i->location.tile + TileDiffXY(1, 1)); // keep the news, even when the mine closes { TileIndex tile = i->location.tile; diff --git a/src/economy.cpp b/src/economy.cpp index dff71a0f48..221cfde617 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -599,10 +599,7 @@ static void CompanyCheckBankrupt(Company *c) /* Warn about bankruptcy after 3 months */ case 4: { CompanyNewsInformation *cni = new CompanyNewsInformation(c); - SetDParam(0, STR_NEWS_COMPANY_IN_TROUBLE_TITLE); - SetDParam(1, STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION); - SetDParamStr(2, cni->company_name); - AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni); + AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, MakeParameters(STR_NEWS_COMPANY_IN_TROUBLE_TITLE, STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION, cni->company_name), cni); AI::BroadcastNewEvent(new ScriptEventCompanyInTrouble(c->index)); Game::NewEvent(new ScriptEventCompanyInTrouble(c->index)); break; @@ -877,10 +874,10 @@ static void HandleEconomyFluctuations() if (_economy.fluct == 0) { _economy.fluct = -(int)GB(Random(), 0, 2); - AddNewsItem(STR_NEWS_BEGIN_OF_RECESSION, NT_ECONOMY, NF_NORMAL); + AddNewsItem(STR_NEWS_BEGIN_OF_RECESSION, MakeParameters(), NT_ECONOMY, NF_NORMAL); } else if (_economy.fluct == -12) { _economy.fluct = GB(Random(), 0, 8) + 312; - AddNewsItem(STR_NEWS_END_OF_RECESSION, NT_ECONOMY, NF_NORMAL); + AddNewsItem(STR_NEWS_END_OF_RECESSION, MakeParameters(), NT_ECONOMY, NF_NORMAL); } } @@ -2014,12 +2011,14 @@ static void DoAcquireCompany(Company *c, bool hostile_takeover) CompanyNewsInformation *cni = new CompanyNewsInformation(c, Company::Get(_current_company)); - SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE); - SetDParam(1, hostile_takeover ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION); - SetDParamStr(2, cni->company_name); - SetDParamStr(3, cni->other_company_name); - SetDParam(4, c->bankrupt_value); - AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni); + auto params = MakeParameters( + STR_NEWS_COMPANY_MERGER_TITLE, + hostile_takeover ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION, + cni->company_name, + cni->other_company_name, + c->bankrupt_value + ); + AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, std::move(params), cni); AI::BroadcastNewEvent(new ScriptEventCompanyMerger(ci, _current_company)); Game::NewEvent(new ScriptEventCompanyMerger(ci, _current_company)); diff --git a/src/engine.cpp b/src/engine.cpp index 3a03eae196..aeb8b10442 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1091,9 +1091,7 @@ static void NewVehicleAvailable(Engine *e) /* Only provide the "New Vehicle available" news paper entry, if engine can be built. */ if (!IsVehicleTypeDisabled(e->type, false) && (e->info.extra_flags & ExtraEngineFlags::NoNews) == ExtraEngineFlags::None) { - SetDParam(0, GetEngineCategoryName(index)); - SetDParam(1, PackEngineNameDParam(index, EngineNameContext::PreviewNews)); - AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, NT_NEW_VEHICLES, NF_VEHICLE, NR_ENGINE, index); + AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, MakeParameters(GetEngineCategoryName(index), PackEngineNameDParam(index, EngineNameContext::PreviewNews)), NT_NEW_VEHICLES, NF_VEHICLE, NR_ENGINE, index); } /* Update the toolbar. */ diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 410b09ef12..061a12b661 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -1728,14 +1728,15 @@ static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int t static void AdvertiseIndustryOpening(const Industry *ind) { const IndustrySpec *ind_spc = GetIndustrySpec(ind->type); - SetDParam(0, ind_spc->name); + ArrayStringParameters<3> params; + params.SetParam(0, ind_spc->name); if (ind_spc->new_industry_text > STR_LAST_STRINGID) { - SetDParam(1, STR_TOWN_NAME); - SetDParam(2, ind->town->index); + params.SetParam(1, STR_TOWN_NAME); + params.SetParam(2, ind->town->index); } else { - SetDParam(1, ind->town->index); + params.SetParam(1, ind->town->index); } - AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind->index); + AddIndustryNewsItem(ind_spc->new_industry_text, std::move(params), NT_INDUSTRY_OPEN, ind->index); AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index)); Game::NewEvent(new ScriptEventIndustryOpen(ind->index)); } @@ -2185,17 +2186,18 @@ CommandCost CmdIndustrySetProduction(DoCommandFlag flags, IndustryID ind_id, byt /* Set parameters of news string */ NewsAllocatedData *data = nullptr; + ArrayStringParameters<3> params; if (str == STR_NEWS_CUSTOM_ITEM) { NewsStringData *news = new NewsStringData(custom_news); - SetDParamStr(0, news->string); + params.SetParam(0, news->string); } else if (str > STR_LAST_STRINGID) { - SetDParam(0, STR_TOWN_NAME); - SetDParam(1, ind->town->index); - SetDParam(2, GetIndustrySpec(ind->type)->name); + params.SetParam(0, STR_TOWN_NAME); + params.SetParam(1, ind->town->index); + params.SetParam(2, GetIndustrySpec(ind->type)->name); } else { - SetDParam(0, ind->index); + params.SetParam(0, ind->index); } - AddIndustryNewsItem(str, nt, ind->index, data); + AddIndustryNewsItem(str, std::move(params), nt, ind->index, data); } } @@ -2768,11 +2770,9 @@ static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int case 2: nt = NT_INDUSTRY_COMPANY; break; default: NOT_REACHED(); } - SetDParam(2, abs(percent)); - SetDParam(0, CargoSpec::Get(type)->name); - SetDParam(1, ind->index); AddIndustryNewsItem( percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH, + MakeParameters(CargoSpec::Get(type)->name, ind->index, abs(percent)), nt, ind->index ); @@ -2974,23 +2974,24 @@ static void ChangeIndustryProduction(Industry *i, bool monthly) default: NOT_REACHED(); } } + ArrayStringParameters<3> params; /* Set parameters of news string */ if (str > STR_LAST_STRINGID) { - SetDParam(0, STR_TOWN_NAME); - SetDParam(1, i->town->index); - SetDParam(2, indspec->name); + params.SetParam(0, STR_TOWN_NAME); + params.SetParam(1, i->town->index); + params.SetParam(2, indspec->name); } else if (closeit) { - SetDParam(0, STR_FORMAT_INDUSTRY_NAME); - SetDParam(1, i->town->index); - SetDParam(2, indspec->name); + params.SetParam(0, STR_FORMAT_INDUSTRY_NAME); + params.SetParam(1, i->town->index); + params.SetParam(2, indspec->name); } else { - SetDParam(0, i->index); + params.SetParam(0, i->index); } /* and report the news to the user */ if (closeit) { - AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1)); + AddTileNewsItem(str, std::move(params), nt, i->location.tile + TileDiffXY(1, 1)); } else { - AddIndustryNewsItem(str, nt, i->index); + AddIndustryNewsItem(str, std::move(params), nt, i->index); } } } diff --git a/src/news_func.h b/src/news_func.h index 614f29cf7e..71d9ccfa74 100644 --- a/src/news_func.h +++ b/src/news_func.h @@ -15,11 +15,11 @@ #include "station_type.h" #include "industry_type.h" -void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1 = NR_NONE, uint32_t ref1 = UINT32_MAX, NewsReferenceType reftype2 = NR_NONE, uint32_t ref2 = UINT32_MAX, const NewsAllocatedData *data = nullptr); +void AddNewsItem(StringID string, class StringParameters &¶ms, NewsType type, NewsFlag flags, NewsReferenceType reftype1 = NR_NONE, uint32_t ref1 = UINT32_MAX, NewsReferenceType reftype2 = NR_NONE, uint32_t ref2 = UINT32_MAX, const NewsAllocatedData *data = nullptr); -inline void AddCompanyNewsItem(StringID string, CompanyNewsInformation *cni) +inline void AddCompanyNewsItem(StringID string, class StringParameters &¶ms, CompanyNewsInformation *cni) { - AddNewsItem(string, NT_COMPANY_INFO, NF_COMPANY, NR_NONE, UINT32_MAX, NR_NONE, UINT32_MAX, cni); + AddNewsItem(string, std::move(params), NT_COMPANY_INFO, NF_COMPANY, NR_NONE, UINT32_MAX, NR_NONE, UINT32_MAX, cni); } /** @@ -27,9 +27,9 @@ inline void AddCompanyNewsItem(StringID string, CompanyNewsInformation *cni) * * @warning The DParams may not reference the vehicle due to autoreplace stuff. See AddVehicleAdviceNewsItem for how that can be done. */ -inline void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle, StationID station = INVALID_STATION) +inline void AddVehicleNewsItem(StringID string, class StringParameters &¶ms, NewsType type, VehicleID vehicle, StationID station = INVALID_STATION) { - AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_VEHICLE, vehicle, station == INVALID_STATION ? NR_NONE : NR_STATION, station); + AddNewsItem(string, std::move(params), type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_VEHICLE, vehicle, station == INVALID_STATION ? NR_NONE : NR_STATION, station); } /** @@ -37,19 +37,19 @@ inline void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle * * @warning DParam 0 must reference the vehicle! */ -inline void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle) +inline void AddVehicleAdviceNewsItem(StringID string, class StringParameters &¶ms, VehicleID vehicle) { - AddNewsItem(string, NT_ADVICE, NF_INCOLOUR | NF_SMALL | NF_VEHICLE_PARAM0, NR_VEHICLE, vehicle); + AddNewsItem(string, std::move(params), NT_ADVICE, NF_INCOLOUR | NF_SMALL | NF_VEHICLE_PARAM0, NR_VEHICLE, vehicle); } -inline void AddTileNewsItem(StringID string, NewsType type, TileIndex tile, const NewsAllocatedData *data = nullptr, StationID station = INVALID_STATION) +inline void AddTileNewsItem(StringID string, class StringParameters &¶ms, NewsType type, TileIndex tile, const NewsAllocatedData *data = nullptr, StationID station = INVALID_STATION) { - AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_TILE, tile.base(), station == INVALID_STATION ? NR_NONE : NR_STATION, station, data); + AddNewsItem(string, std::move(params), type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_TILE, tile.base(), station == INVALID_STATION ? NR_NONE : NR_STATION, station, data); } -inline void AddIndustryNewsItem(StringID string, NewsType type, IndustryID industry, const NewsAllocatedData *data = nullptr) +inline void AddIndustryNewsItem(StringID string, class StringParameters &¶ms, NewsType type, IndustryID industry, const NewsAllocatedData *data = nullptr) { - AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_INDUSTRY, industry, NR_NONE, UINT32_MAX, data); + AddNewsItem(string, std::move(params), type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_INDUSTRY, industry, NR_NONE, UINT32_MAX, data); } void NewsLoop(); diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 01479f1872..f7ed67a1e5 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -793,6 +793,7 @@ static void DeleteNewsItem(NewsItem *ni) /** * Create a new newsitem to be shown. * @param string_id String to display. + * @param params Parameters for the string. * @param type The type of news. * @param flags Flags related to how to display the news. * @param reftype1 Type of ref1. @@ -803,17 +804,18 @@ static void DeleteNewsItem(NewsItem *ni) * * @see NewsSubtype */ -NewsItem::NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, const NewsAllocatedData *data) : +NewsItem::NewsItem(StringID string_id, StringParameters &¶ms, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, const NewsAllocatedData *data) : string_id(string_id), date(TimerGameCalendar::date), economy_date(TimerGameEconomy::date), type(type), flags(flags), reftype1(reftype1), reftype2(reftype2), ref1(ref1), ref2(ref2), data(data) { /* show this news message in colour? */ if (TimerGameCalendar::year >= _settings_client.gui.coloured_news_year) this->flags |= NF_INCOLOUR; - CopyOutDParam(this->params, 10); + CopyOutDParam(this->params, std::move(params)); } /** * Add a new newsitem to be shown. * @param string String to display + * @param params Parameters for the string. * @param type news category * @param flags display flags for the news * @param reftype1 Type of ref1 @@ -824,12 +826,12 @@ NewsItem::NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsRefere * * @see NewsSubtype */ -void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, const NewsAllocatedData *data) +void AddNewsItem(StringID string, StringParameters &¶ms, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, const NewsAllocatedData *data) { if (_game_mode == GM_MENU) return; /* Create new news item node */ - NewsItem *ni = new NewsItem(string, type, flags, reftype1, ref1, reftype2, ref2, data); + NewsItem *ni = new NewsItem(string, std::move(params), type, flags, reftype1, ref1, reftype2, ref2, data); if (_total_news++ == 0) { assert(_oldest_news == nullptr); @@ -903,8 +905,7 @@ CommandCost CmdCustomNewsItem(DoCommandFlag flags, NewsType type, NewsReferenceT if (flags & DC_EXEC) { NewsStringData *news = new NewsStringData(text); - SetDParamStr(0, news->string); - AddNewsItem(STR_NEWS_CUSTOM_ITEM, type, NF_NORMAL, reftype1, reference, NR_NONE, UINT32_MAX, news); + AddNewsItem(STR_NEWS_CUSTOM_ITEM, MakeParameters(news->string), type, NF_NORMAL, reftype1, reference, NR_NONE, UINT32_MAX, news); } return CommandCost(); diff --git a/src/news_type.h b/src/news_type.h index 53afc9be34..aa7b537f0c 100644 --- a/src/news_type.h +++ b/src/news_type.h @@ -143,7 +143,7 @@ struct NewsItem { std::vector params; ///< Parameters for string resolving. - NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, const NewsAllocatedData *data); + NewsItem(StringID string_id, class StringParameters &&, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, const NewsAllocatedData *data); }; /** Container for a single string to be passed as NewsAllocatedData. */ diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 1594065a10..1751729614 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -1726,8 +1726,7 @@ void CheckOrders(const Vehicle *v) /* We don't have a problem */ if (message == INVALID_STRING_ID) return; - SetDParam(0, v->index); - AddVehicleAdviceNewsItem(message, v->index); + AddVehicleAdviceNewsItem(message, MakeParameters(v->index), v->index); } } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 066ea84762..5611179e37 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -548,7 +548,6 @@ static void RoadVehCrash(RoadVehicle *v) AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING)); Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING)); - SetDParam(0, pass); StringID newsitem = (pass == 1) ? STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH; NewsType newstype = NT_ACCIDENT; @@ -556,7 +555,7 @@ static void RoadVehCrash(RoadVehicle *v) newstype = NT_ACCIDENT_OTHER; } - AddTileNewsItem(newsitem, newstype, v->tile); + AddTileNewsItem(newsitem, MakeParameters(pass), newstype, v->tile); ModifyStationRatingAround(v->tile, v->owner, -160, 22); if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v); @@ -689,9 +688,9 @@ static void RoadVehArrivesAt(const RoadVehicle *v, Station *st) /* Check if station was ever visited before */ if (!(st->had_vehicle_of_type & HVOT_BUS)) { st->had_vehicle_of_type |= HVOT_BUS; - SetDParam(0, st->index); AddVehicleNewsItem( RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL, + MakeParameters(st->index), (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, v->index, st->index @@ -703,9 +702,9 @@ static void RoadVehArrivesAt(const RoadVehicle *v, Station *st) /* Check if station was ever visited before */ if (!(st->had_vehicle_of_type & HVOT_TRUCK)) { st->had_vehicle_of_type |= HVOT_TRUCK; - SetDParam(0, st->index); AddVehicleNewsItem( RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL, + MakeParameters(st->index), (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, v->index, st->index diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 34d96bf273..efe7965425 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -477,9 +477,9 @@ static void ShipArrivesAt(const Vehicle *v, Station *st) if (!(st->had_vehicle_of_type & HVOT_SHIP)) { st->had_vehicle_of_type |= HVOT_SHIP; - SetDParam(0, st->index); AddVehicleNewsItem( STR_NEWS_FIRST_SHIP_ARRIVAL, + MakeParameters(st->index), (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, v->index, st->index diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index f1bcd69fd0..6f5ea81f30 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -527,10 +527,8 @@ CargoTypes GetEmptyMask(const Station *st) */ static void ShowRejectOrAcceptNews(const Station *st, CargoTypes cargoes, bool reject) { - SetDParam(0, st->index); - SetDParam(1, cargoes); StringID msg = reject ? STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_LIST : STR_NEWS_STATION_NOW_ACCEPTS_CARGO_LIST; - AddNewsItem(msg, NT_ACCEPTANCE, NF_INCOLOUR | NF_SMALL, NR_STATION, st->index); + AddNewsItem(msg, MakeParameters(st->index, cargoes), NT_ACCEPTANCE, NF_INCOLOUR | NF_SMALL, NR_STATION, st->index); } /** diff --git a/src/subsidy.cpp b/src/subsidy.cpp index 3d9a60408e..0886df01b6 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -51,11 +51,13 @@ void Subsidy::AwardTo(CompanyID company) NewsStringData *company_name = new NewsStringData(GetString(STR_COMPANY_NAME)); /* Add a news item */ - std::pair reftype = SetupSubsidyDecodeParam(this, SubsidyDecodeParamType::NewsAwarded, 1); + ArrayStringParameters<8> params; + std::pair reftype = SetupSubsidyDecodeParam(this, SubsidyDecodeParamType::NewsAwarded, params, 1); + params.SetParam(0, company_name->string); - SetDParamStr(0, company_name->string); AddNewsItem( STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier, + std::move(params), NT_SUBSIDIES, NF_NORMAL, reftype.first, this->src, reftype.second, this->dst, company_name @@ -70,47 +72,48 @@ void Subsidy::AwardTo(CompanyID company) * Setup the string parameters for printing the subsidy at the screen, and compute the news reference for the subsidy. * @param s %Subsidy being printed. * @param mode Type of subsidy news message to decide on parameter format. + * @param params String parameters to be filled. Needs to be able to contain at least 8 + parameter_offset entries. * @param parameter_offset The location/index in the String DParams to start decoding the subsidy's parameters. Defaults to 0. * @return Reference of the subsidy in the news system. */ -std::pair SetupSubsidyDecodeParam(const Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset) +std::pair SetupSubsidyDecodeParam(const Subsidy *s, SubsidyDecodeParamType mode, StringParameters ¶ms, uint parameter_offset) { NewsReferenceType reftype1 = NR_NONE; NewsReferenceType reftype2 = NR_NONE; /* Always use the plural form of the cargo name - trying to decide between plural or singular causes issues for translations */ const CargoSpec *cs = CargoSpec::Get(s->cargo_type); - SetDParam(parameter_offset, cs->name); + params.SetParam(parameter_offset, cs->name); switch (s->src_type) { case SourceType::Industry: reftype1 = NR_INDUSTRY; - SetDParam(parameter_offset + 1, STR_INDUSTRY_NAME); + params.SetParam(parameter_offset + 1, STR_INDUSTRY_NAME); break; case SourceType::Town: reftype1 = NR_TOWN; - SetDParam(parameter_offset + 1, STR_TOWN_NAME); + params.SetParam(parameter_offset + 1, STR_TOWN_NAME); break; default: NOT_REACHED(); } - SetDParam(parameter_offset + 2, s->src); + params.SetParam(parameter_offset + 2, s->src); switch (s->dst_type) { case SourceType::Industry: reftype2 = NR_INDUSTRY; - SetDParam(parameter_offset + 4, STR_INDUSTRY_NAME); + params.SetParam(parameter_offset + 4, STR_INDUSTRY_NAME); break; case SourceType::Town: reftype2 = NR_TOWN; - SetDParam(parameter_offset + 4, STR_TOWN_NAME); + params.SetParam(parameter_offset + 4, STR_TOWN_NAME); break; default: NOT_REACHED(); } - SetDParam(parameter_offset + 5, s->dst); + params.SetParam(parameter_offset + 5, s->dst); /* If the subsidy is being offered or awarded, the news item mentions the subsidy duration. */ if (mode == SubsidyDecodeParamType::NewsOffered || mode == SubsidyDecodeParamType::NewsAwarded) { - SetDParam(parameter_offset + 7, _settings_game.difficulty.subsidy_duration); + params.SetParam(parameter_offset + 7, _settings_game.difficulty.subsidy_duration); } return std::pair(reftype1, reftype2); @@ -222,8 +225,9 @@ void CreateSubsidy(CargoID cid, SourceType src_type, SourceID src, SourceType ds s->remaining = SUBSIDY_OFFER_MONTHS; s->awarded = INVALID_COMPANY; - std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsOffered); - AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); + ArrayStringParameters<8> params; + std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsOffered, params); + AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, std::move(params), NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC); SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST); AI::BroadcastNewEvent(new ScriptEventSubsidyOffer(s->index)); @@ -482,14 +486,16 @@ static IntervalTimer _economy_subsidies_monthly({TimerGameEcon for (Subsidy *s : Subsidy::Iterate()) { if (--s->remaining == 0) { if (!s->IsAwarded()) { - std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn); - AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); + ArrayStringParameters<8> params; + std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn, params); + AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, std::move(params), NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index)); Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index)); } else { if (s->awarded == _local_company) { - std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn); - AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); + ArrayStringParameters<8> params; + std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn, params); + AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, std::move(params), NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); } AI::BroadcastNewEvent(new ScriptEventSubsidyExpired(s->index)); Game::NewEvent(new ScriptEventSubsidyExpired(s->index)); diff --git a/src/subsidy_func.h b/src/subsidy_func.h index 89bf0f1fe2..61b4ff350a 100644 --- a/src/subsidy_func.h +++ b/src/subsidy_func.h @@ -17,7 +17,7 @@ #include "news_type.h" #include "subsidy_base.h" -std::pair SetupSubsidyDecodeParam(const struct Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset = 0); +std::pair SetupSubsidyDecodeParam(const struct Subsidy *s, SubsidyDecodeParamType mode, StringParameters ¶ms, uint parameter_offset = 0); void DeleteSubsidyWith(SourceType type, SourceID index); bool CheckSubsidised(CargoID cargo_type, CompanyID company, SourceType src_type, SourceID src, const Station *st); void RebuildSubsidisedSourceAndDestinationCache(); diff --git a/src/subsidy_gui.cpp b/src/subsidy_gui.cpp index 9e72fe203e..feeaee02ca 100644 --- a/src/subsidy_gui.cpp +++ b/src/subsidy_gui.cpp @@ -158,7 +158,9 @@ struct SubsidyListWindow : Window { if (!s->IsAwarded()) { if (IsInsideMM(pos, 0, cap)) { /* Displays the two offered towns */ - SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui); + extern ArrayStringParameters<20> _global_string_params; + SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui, _global_string_params); + /* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */ if (TimerGameEconomy::UsingWallclockUnits()) { SetDParam(7, STR_SUBSIDIES_OFFERED_EXPIRY_TIME); @@ -189,7 +191,9 @@ struct SubsidyListWindow : Window { for (const Subsidy *s : Subsidy::Iterate()) { if (s->IsAwarded()) { if (IsInsideMM(pos, 0, cap)) { - SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui); + extern ArrayStringParameters<20> _global_string_params; + SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui, _global_string_params); + SetDParam(7, s->awarded); /* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */ if (TimerGameEconomy::UsingWallclockUnits()) { diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 94129f719e..e1a02e0033 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -2103,16 +2103,12 @@ std::tuple CmdFoundTown(DoCommandFlag flags, TileInd assert(!random_location); if (_current_company == OWNER_DEITY) { - SetDParam(0, t->index); - AddTileNewsItem(STR_NEWS_NEW_TOWN_UNSPONSORED, NT_INDUSTRY_OPEN, tile); + AddTileNewsItem(STR_NEWS_NEW_TOWN_UNSPONSORED, MakeParameters(t->index), NT_INDUSTRY_OPEN, tile); } else { SetDParam(0, _current_company); NewsStringData *company_name = new NewsStringData(GetString(STR_COMPANY_NAME)); - SetDParamStr(0, company_name->string); - SetDParam(1, t->index); - - AddTileNewsItem(STR_NEWS_NEW_TOWN, NT_INDUSTRY_OPEN, tile, company_name); + AddTileNewsItem(STR_NEWS_NEW_TOWN, MakeParameters(company_name->string, t->index), NT_INDUSTRY_OPEN, tile, company_name); } AI::BroadcastNewEvent(new ScriptEventTownFounded(t->index)); Game::NewEvent(new ScriptEventTownFounded(t->index)); @@ -3199,11 +3195,9 @@ static CommandCost TownActionRoadRebuild(Town *t, DoCommandFlag flags) SetDParam(0, _current_company); NewsStringData *company_name = new NewsStringData(GetString(STR_COMPANY_NAME)); - SetDParam(0, t->index); - SetDParamStr(1, company_name->string); - AddNewsItem( TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_ROAD_REBUILDING_MINUTES : STR_NEWS_ROAD_REBUILDING_MONTHS, + MakeParameters(t->index, company_name->string), NT_GENERAL, NF_NORMAL, NR_TOWN, t->index, NR_NONE, UINT32_MAX, company_name); AI::BroadcastNewEvent(new ScriptEventRoadReconstruction((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); Game::NewEvent(new ScriptEventRoadReconstruction((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); @@ -3355,11 +3349,13 @@ static CommandCost TownActionBuyRights(Town *t, DoCommandFlag flags) /* Spawn news message */ CompanyNewsInformation *cni = new CompanyNewsInformation(Company::Get(_current_company)); - SetDParam(0, STR_NEWS_EXCLUSIVE_RIGHTS_TITLE); - SetDParam(1, TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MINUTES : STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MONTHS); - SetDParam(2, t->index); - SetDParamStr(3, cni->company_name); - AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NT_GENERAL, NF_COMPANY, NR_TOWN, t->index, NR_NONE, UINT32_MAX, cni); + auto params = MakeParameters( + STR_NEWS_EXCLUSIVE_RIGHTS_TITLE, + TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MINUTES : STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MONTHS, + t->index, + cni->company_name + ); + AddNewsItem(STR_MESSAGE_NEWS_FORMAT, std::move(params), NT_GENERAL, NF_COMPANY, NR_TOWN, t->index, NR_NONE, UINT32_MAX, cni); AI::BroadcastNewEvent(new ScriptEventExclusiveTransportRights((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); Game::NewEvent(new ScriptEventExclusiveTransportRights((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 45cf5a0cae..12f2fed89b 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2993,9 +2993,9 @@ static void TrainEnterStation(Train *v, StationID station) Station *st = Station::Get(station); if (!(st->had_vehicle_of_type & HVOT_TRAIN)) { st->had_vehicle_of_type |= HVOT_TRAIN; - SetDParam(0, st->index); AddVehicleNewsItem( STR_NEWS_FIRST_TRAIN_ARRIVAL, + MakeParameters(st->index), v->owner == _local_company ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, v->index, st->index @@ -3230,8 +3230,7 @@ static bool CheckTrainCollision(Train *v) /* any dead -> no crash */ if (tcc.num == 0) return false; - SetDParam(0, tcc.num); - AddTileNewsItem(STR_NEWS_TRAIN_CRASH, NT_ACCIDENT, v->tile); + AddTileNewsItem(STR_NEWS_TRAIN_CRASH, MakeParameters(tcc.num), NT_ACCIDENT, v->tile); ModifyStationRatingAround(v->tile, v->owner, -160, 30); if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_13_TRAIN_COLLISION, v); @@ -3993,8 +3992,7 @@ static bool TrainLocoHandler(Train *v, bool mode) if (HasBit(v->flags, VRF_TRAIN_STUCK) && v->wait_counter > 2 * _settings_game.pf.wait_for_pbs_path * Ticks::DAY_TICKS) { /* Show message to player. */ if (_settings_client.gui.lost_vehicle_warn && v->owner == _local_company) { - SetDParam(0, v->index); - AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_STUCK, v->index); + AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_STUCK, MakeParameters(v->index), v->index); } v->wait_counter = 0; } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index d843944835..a598fb9eb1 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -811,8 +811,7 @@ void Vehicle::HandlePathfindingResult(bool path_found) /* Notify user about the event. */ AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index)); if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) { - SetDParam(0, this->index); - AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_IS_LOST, this->index); + AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_IS_LOST, MakeParameters(this->index), this->index); } } @@ -1097,9 +1096,7 @@ void CallVehicleTicks() message = STR_NEWS_VEHICLE_AUTORENEW_FAILED; } - SetDParam(0, v->index); - SetDParam(1, error_message); - AddVehicleAdviceNewsItem(message, v->index); + AddVehicleAdviceNewsItem(message, MakeParameters(v->index, error_message), v->index); } cur_company.Restore(); @@ -1453,8 +1450,7 @@ void AgeVehicle(Vehicle *v) return; } - SetDParam(0, v->index); - AddVehicleAdviceNewsItem(str, v->index); + AddVehicleAdviceNewsItem(str, MakeParameters(v->index), v->index); } /** @@ -1609,8 +1605,7 @@ void VehicleEnterDepot(Vehicle *v) _vehicles_to_autoreplace[v] = false; if (v->owner == _local_company) { /* Notify the user that we stopped the vehicle */ - SetDParam(0, v->index); - AddVehicleAdviceNewsItem(STR_NEWS_ORDER_REFIT_FAILED, v->index); + AddVehicleAdviceNewsItem(STR_NEWS_ORDER_REFIT_FAILED, MakeParameters(v->index), v->index); } } else if (cost.GetCost() != 0) { v->profit_this_year -= cost.GetCost() << 8; @@ -1634,8 +1629,7 @@ void VehicleEnterDepot(Vehicle *v) * we shouldn't construct it when the vehicle visits the next stop. */ v->last_loading_station = INVALID_STATION; if (v->owner == _local_company) { - SetDParam(0, v->index); - AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index); + AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_WAITING + v->type, MakeParameters(v->index), v->index); } AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index)); } @@ -2848,10 +2842,9 @@ static IntervalTimer _economy_vehicles_yearly({TimerGameEconom Money profit = v->GetDisplayProfitThisYear(); if (v->age >= 730 && profit < 0) { if (_settings_client.gui.vehicle_income_warn && v->owner == _local_company) { - SetDParam(0, v->index); - SetDParam(1, profit); AddVehicleAdviceNewsItem( TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD : STR_NEWS_VEHICLE_UNPROFITABLE_YEAR, + MakeParameters(v->index, profit), v->index); } AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index)); diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 50d105dbc9..f881462ad9 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -993,8 +993,7 @@ static void FloodVehicle(Vehicle *v) AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED)); Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED)); - SetDParam(0, pass); - AddTileNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, NT_ACCIDENT, v->tile); + AddTileNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, MakeParameters(pass), NT_ACCIDENT, v->tile); CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE); if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v); } From b7bbeaf341d3cbb29c9fcfa450021732c15e3c30 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 2 Feb 2024 18:56:34 +0100 Subject: [PATCH 4/7] Codechange: use StringParameters to pass parameters for Tooltip strings --- src/autoreplace_gui.cpp | 5 ++--- src/depot_gui.cpp | 5 +---- src/industry_gui.cpp | 5 ++--- src/linkgraph/linkgraph_gui.cpp | 19 ++++++------------ src/misc_gui.cpp | 11 ++++++----- src/network/network_gui.cpp | 6 +++--- src/rail_gui.cpp | 2 +- src/vehicle_gui.cpp | 2 +- src/viewport.cpp | 34 +++++++++++++++++---------------- src/window.cpp | 4 ++-- src/window_gui.h | 2 +- 11 files changed, 43 insertions(+), 52 deletions(-) diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index 64707259d3..c7be164ddb 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -702,10 +702,9 @@ public: if (widget != WID_RV_TRAIN_WAGONREMOVE_TOGGLE) return false; if (Group::IsValidID(this->sel_group)) { - SetDParam(0, STR_REPLACE_REMOVE_WAGON_HELP); - GuiShowTooltips(this, STR_REPLACE_REMOVE_WAGON_GROUP_HELP, close_cond, 1); + GuiShowTooltips(this, STR_REPLACE_REMOVE_WAGON_GROUP_HELP, close_cond, MakeParameters(STR_REPLACE_REMOVE_WAGON_HELP)); } else { - GuiShowTooltips(this, STR_REPLACE_REMOVE_WAGON_HELP, close_cond); + GuiShowTooltips(this, STR_REPLACE_REMOVE_WAGON_HELP, close_cond, MakeParameters()); } return true; } diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index ae726c920b..aba2d3c312 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -885,10 +885,7 @@ struct DepotWindow : Window { details += GetString(STR_DEPOT_VEHICLE_TOOLTIP_CARGO); } - /* Show tooltip window */ - SetDParam(0, whole_chain ? num : v->engine_type); - SetDParamStr(1, details); - GuiShowTooltips(this, whole_chain ? STR_DEPOT_VEHICLE_TOOLTIP_CHAIN : STR_DEPOT_VEHICLE_TOOLTIP, TCC_RIGHT_CLICK, 2); + GuiShowTooltips(this, whole_chain ? STR_DEPOT_VEHICLE_TOOLTIP_CHAIN : STR_DEPOT_VEHICLE_TOOLTIP, TCC_RIGHT_CLICK, MakeParameters(whole_chain ? num : v->engine_type, details)); return true; } diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 15c0c42094..1de7153292 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -3165,7 +3165,7 @@ struct IndustryCargoesWindow : public Window { case CFT_INDUSTRY: if (fld->u.industry.ind_type < NUM_INDUSTRYTYPES && (this->ind_cargo >= NUM_INDUSTRYTYPES || fieldxy.x != 2)) { - GuiShowTooltips(this, STR_INDUSTRY_CARGOES_INDUSTRY_TOOLTIP, close_cond); + GuiShowTooltips(this, STR_INDUSTRY_CARGOES_INDUSTRY_TOOLTIP, close_cond, MakeParameters()); } return true; @@ -3174,8 +3174,7 @@ struct IndustryCargoesWindow : public Window { } if (IsValidCargoID(cid) && (this->ind_cargo < NUM_INDUSTRYTYPES || cid != this->ind_cargo - NUM_INDUSTRYTYPES)) { const CargoSpec *csp = CargoSpec::Get(cid); - SetDParam(0, csp->name); - GuiShowTooltips(this, STR_INDUSTRY_CARGOES_CARGO_TOOLTIP, close_cond, 1); + GuiShowTooltips(this, STR_INDUSTRY_CARGOES_CARGO_TOOLTIP, close_cond, MakeParameters(csp->name)); return true; } diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp index a1dfa0c8a8..7174426037 100644 --- a/src/linkgraph/linkgraph_gui.cpp +++ b/src/linkgraph/linkgraph_gui.cpp @@ -401,20 +401,15 @@ bool LinkGraphOverlay::ShowTooltip(Point pt, TooltipCloseCondition close_cond) SetDParam(0, time); tooltip_extension += GetString(STR_LINKGRAPH_STATS_TOOLTIP_TIME_EXTENSION); } - SetDParam(0, link.cargo); - SetDParam(1, link.Usage()); - SetDParam(2, i->first); - SetDParam(3, j->first); - SetDParam(4, link.Usage() * 100 / (link.capacity + 1)); - SetDParamStr(5, tooltip_extension); + GuiShowTooltips(this->window, TimerGameEconomy::UsingWallclockUnits() ? STR_LINKGRAPH_STATS_TOOLTIP_MINUTE : STR_LINKGRAPH_STATS_TOOLTIP_MONTH, - close_cond, 7); + close_cond, MakeParameters(link.cargo, link.Usage(), i->first, j->first, link.Usage() * 100 / (link.capacity + 1), tooltip_extension)); return true; } } } - GuiShowTooltips(this->window, STR_NULL, close_cond); + GuiShowTooltips(this->window, STR_NULL, close_cond, MakeParameters()); return false; } @@ -646,17 +641,15 @@ bool LinkGraphLegendWindow::OnTooltip([[maybe_unused]] Point, WidgetID widget, T { if (IsInsideMM(widget, WID_LGL_COMPANY_FIRST, WID_LGL_COMPANY_LAST + 1)) { if (this->IsWidgetDisabled(widget)) { - GuiShowTooltips(this, STR_LINKGRAPH_LEGEND_SELECT_COMPANIES, close_cond); + GuiShowTooltips(this, STR_LINKGRAPH_LEGEND_SELECT_COMPANIES, close_cond, MakeParameters()); } else { - SetDParam(0, STR_LINKGRAPH_LEGEND_SELECT_COMPANIES); - SetDParam(1, (CompanyID)(widget - WID_LGL_COMPANY_FIRST)); - GuiShowTooltips(this, STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP, close_cond, 2); + GuiShowTooltips(this, STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP, close_cond, MakeParameters(STR_LINKGRAPH_LEGEND_SELECT_COMPANIES, (CompanyID)(widget - WID_LGL_COMPANY_FIRST))); } return true; } if (IsInsideMM(widget, WID_LGL_CARGO_FIRST, WID_LGL_CARGO_LAST + 1)) { const CargoSpec *cargo = _sorted_cargo_specs[widget - WID_LGL_CARGO_FIRST]; - GuiShowTooltips(this, cargo->name, close_cond); + GuiShowTooltips(this, cargo->name, close_cond, MakeParameters()); return true; } return false; diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 07b441ce41..5bb0f07169 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -664,13 +664,14 @@ struct TooltipsWindow : public Window std::vector params; ///< The string parameters. TooltipCloseCondition close_cond; ///< Condition for closing the window. - TooltipsWindow(Window *parent, StringID str, uint paramcount, TooltipCloseCondition close_tooltip) : Window(&_tool_tips_desc) + TooltipsWindow(Window *parent, StringID str, StringParameters &¶ms, TooltipCloseCondition close_tooltip) : Window(&_tool_tips_desc) { this->parent = parent; this->string_id = str; - CopyOutDParam(this->params, paramcount); + CopyOutDParam(this->params, std::move(params)); this->close_cond = close_tooltip; + CopyInDParam(this->params); this->InitNested(); CLRBITS(this->flags, WF_WHITE_BORDER); @@ -748,15 +749,15 @@ struct TooltipsWindow : public Window * @param parent The window this tooltip is related to. * @param str String to be displayed * @param close_tooltip the condition under which the tooltip closes - * @param paramcount number of params to deal with + * @param params Parameters for the string. */ -void GuiShowTooltips(Window *parent, StringID str, TooltipCloseCondition close_tooltip, uint paramcount) +void GuiShowTooltips(Window *parent, StringID str, TooltipCloseCondition close_tooltip, StringParameters &¶ms) { CloseWindowById(WC_TOOLTIPS, 0); if (str == STR_NULL || !_cursor.in_window) return; - new TooltipsWindow(parent, str, paramcount, close_tooltip); + new TooltipsWindow(parent, str, std::move(params), close_tooltip); } void QueryString::HandleEditBox(Window *w, WidgetID wid) diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index e7a597b9b3..3fae07af1c 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1803,10 +1803,10 @@ public: if (IsInsideMM(pt.x, player_icon_x, player_icon_x + d2.width)) { if (index == this->player_self_index) { - GuiShowTooltips(this, STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP, close_cond); + GuiShowTooltips(this, STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP, close_cond, MakeParameters()); return true; } else if (index == this->player_host_index) { - GuiShowTooltips(this, STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP, close_cond); + GuiShowTooltips(this, STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP, close_cond, MakeParameters()); return true; } } @@ -1814,7 +1814,7 @@ public: ButtonCommon *button = this->GetButtonAtPoint(pt); if (button == nullptr) return false; - GuiShowTooltips(this, button->tooltip, close_cond); + GuiShowTooltips(this, button->tooltip, close_cond, MakeParameters()); return true; }; } diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 4c09c32e8d..d73c9ccca9 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -458,7 +458,7 @@ struct BuildRailToolbarWindow : Window { if (std::find(std::begin(can_build_widgets), std::end(can_build_widgets), widget) == std::end(can_build_widgets)) return false; - GuiShowTooltips(this, STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE, close_cond); + GuiShowTooltips(this, STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE, close_cond, MakeParameters()); return true; } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index de0a11f11d..4d1df21501 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2736,7 +2736,7 @@ struct VehicleDetailsWindow : Window { } else { tool_tip = widget == WID_VD_INCREASE_SERVICING_INTERVAL ? STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP_DAYS : STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP_DAYS; } - GuiShowTooltips(this, tool_tip, close_cond); + GuiShowTooltips(this, tool_tip, close_cond, MakeParameters()); return true; } diff --git a/src/viewport.cpp b/src/viewport.cpp index 77e93cb2ff..08a118f372 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -2699,12 +2699,12 @@ void UpdateTileSelection() /** * Displays the measurement tooltips when selecting multiple tiles * @param str String to be displayed - * @param paramcount number of params to deal with + * @param params Parameters of the string. */ -static inline void ShowMeasurementTooltips(StringID str, uint paramcount) +static inline void ShowMeasurementTooltips(StringID str, StringParameters &¶ms) { if (!_settings_client.gui.measure_tooltip) return; - GuiShowTooltips(_thd.GetCallbackWnd(), str, TCC_EXIT_VIEWPORT, paramcount); + GuiShowTooltips(_thd.GetCallbackWnd(), str, TCC_EXIT_VIEWPORT, std::move(params)); } static void HideMeasurementTooltips() @@ -2780,8 +2780,7 @@ void VpSetPresizeRange(TileIndex from, TileIndex to) /* show measurement only if there is any length to speak of */ if (distance > 1) { - SetDParam(0, distance); - ShowMeasurementTooltips(STR_MEASURE_LENGTH, 1); + ShowMeasurementTooltips(STR_MEASURE_LENGTH, MakeParameters(distance)); } else { HideMeasurementTooltips(); } @@ -3168,7 +3167,8 @@ static void CalcRaildirsDrawstyle(int x, int y, int method) TileIndex t0 = TileVirtXY(_thd.selstart.x, _thd.selstart.y); TileIndex t1 = TileVirtXY(x, y); uint distance = DistanceManhattan(t0, t1) + 1; - byte index = 0; + auto params = MakeParameters(0, 0); + int index = 0; if (distance != 1) { int heightdiff = CalcHeightdiff(b, distance, t0, t1); @@ -3179,11 +3179,11 @@ static void CalcRaildirsDrawstyle(int x, int y, int method) distance = CeilDiv(distance, 2); } - SetDParam(index++, distance); - if (heightdiff != 0) SetDParam(index++, heightdiff); + params.SetParam(index++, distance); + if (heightdiff != 0) params.SetParam(index++, heightdiff); } - ShowMeasurementTooltips(measure_strings_length[index], index); + ShowMeasurementTooltips(measure_strings_length[index], std::move(params)); } _thd.selend.x = x; @@ -3264,6 +3264,7 @@ calc_heightdiff_single_direction:; TileIndex t0 = TileVirtXY(sx, sy); TileIndex t1 = TileVirtXY(x, y); uint distance = DistanceManhattan(t0, t1) + 1; + auto params = MakeParameters(0, 0); byte index = 0; if (distance != 1) { @@ -3274,11 +3275,11 @@ calc_heightdiff_single_direction:; * new_style := (_thd.next_drawstyle & HT_RECT) ? HT_LINE | style : _thd.next_drawstyle; */ int heightdiff = CalcHeightdiff(HT_LINE | style, 0, t0, t1); - SetDParam(index++, distance); - if (heightdiff != 0) SetDParam(index++, heightdiff); + params.SetParam(index++, distance); + if (heightdiff != 0) params.SetParam(index++, heightdiff); } - ShowMeasurementTooltips(measure_strings_length[index], index); + ShowMeasurementTooltips(measure_strings_length[index], std::move(params)); } break; @@ -3298,6 +3299,7 @@ calc_heightdiff_single_direction:; TileIndex t1 = TileVirtXY(x, y); uint dx = Delta(TileX(t0), TileX(t1)) + 1; uint dy = Delta(TileY(t0), TileY(t1)) + 1; + auto params = MakeParameters(0, 0, 0); byte index = 0; /* If dragging an area (eg dynamite tool) and it is actually a single @@ -3343,12 +3345,12 @@ calc_heightdiff_single_direction:; if (dx != 1 || dy != 1) { int heightdiff = CalcHeightdiff(style, 0, t0, t1); - SetDParam(index++, dx - (style & HT_POINT ? 1 : 0)); - SetDParam(index++, dy - (style & HT_POINT ? 1 : 0)); - if (heightdiff != 0) SetDParam(index++, heightdiff); + params.SetParam(index++, dx - (style & HT_POINT ? 1 : 0)); + params.SetParam(index++, dy - (style & HT_POINT ? 1 : 0)); + if (heightdiff != 0) params.SetParam(index++, heightdiff); } - ShowMeasurementTooltips(measure_strings_area[index], index); + ShowMeasurementTooltips(measure_strings_area[index], std::move(params)); } break; diff --git a/src/window.cpp b/src/window.cpp index a33c3c0177..65abb2aca8 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -758,7 +758,7 @@ static void DispatchRightClickEvent(Window *w, int x, int y) /* Right-click close is enabled, but excluding sticky windows. */ w->Close(); } else if (_settings_client.gui.hover_delay_ms == 0 && !w->OnTooltip(pt, wid->index, TCC_RIGHT_CLICK) && wid->tool_tip != 0) { - GuiShowTooltips(w, wid->tool_tip, TCC_RIGHT_CLICK); + GuiShowTooltips(w, wid->tool_tip, TCC_RIGHT_CLICK, MakeParameters()); } } @@ -779,7 +779,7 @@ static void DispatchHoverEvent(Window *w, int x, int y) /* Show the tooltip if there is any */ if (!w->OnTooltip(pt, wid->index, TCC_HOVER) && wid->tool_tip != 0) { - GuiShowTooltips(w, wid->tool_tip, TCC_HOVER); + GuiShowTooltips(w, wid->tool_tip, TCC_HOVER, MakeParameters()); return; } diff --git a/src/window_gui.h b/src/window_gui.h index d4171070cf..55425031b6 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -1014,7 +1014,7 @@ Wcls *AllocateWindowDescFront(WindowDesc *desc, int window_number, bool return_e void RelocateAllWindows(int neww, int newh); -void GuiShowTooltips(Window *parent, StringID str, TooltipCloseCondition close_tooltip, uint paramcount = 0); +void GuiShowTooltips(Window *parent, StringID str, TooltipCloseCondition close_tooltip, class StringParameters &¶ms); /* widget.cpp */ WidgetID GetWidgetFromPos(const Window *w, int x, int y); From 27eeaf01606bde684c763a6ffe75f165167910cf Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 2 Feb 2024 18:58:23 +0100 Subject: [PATCH 5/7] Codechange: use StringParameters to pass parameters for QueryWindow strings --- src/depot_gui.cpp | 3 +-- src/fios_gui.cpp | 4 ++-- src/genworld_gui.cpp | 2 ++ src/group_gui.cpp | 2 +- src/industry_gui.cpp | 4 ++-- src/intro_gui.cpp | 2 ++ src/misc_cmd.cpp | 1 + src/misc_gui.cpp | 15 ++++++++------- src/network/network_content_gui.cpp | 2 +- src/network/network_gui.cpp | 11 ++++++----- src/newgrf_gui.cpp | 1 + src/screenshot.cpp | 4 +--- src/settings_gui.cpp | 1 + src/terraform_gui.cpp | 2 +- src/textbuf_gui.h | 2 +- 15 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index aba2d3c312..9b5d906008 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -809,11 +809,10 @@ struct DepotWindow : Window { case WID_D_SELL_ALL: /* Only open the confirmation window if there are anything to sell */ if (!this->vehicle_list.empty() || !this->wagon_list.empty()) { - SetDParam(0, this->type); - SetDParam(1, this->GetDepotIndex()); ShowQuery( STR_DEPOT_CAPTION, STR_DEPOT_SELL_CONFIRMATION_TEXT, + MakeParameters(this->type, this->GetDepotIndex()), this, DepotSellAllConfirmationCallback ); diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index c9a77ab8ee..549d44e89d 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -762,14 +762,14 @@ public: if (this->abstract_filetype == FT_SAVEGAME || this->abstract_filetype == FT_SCENARIO) { _file_to_saveload.name = FiosMakeSavegameName(this->filename_editbox.text.buf); if (FioCheckFileExists(_file_to_saveload.name, Subdirectory::SAVE_DIR)) { - ShowQuery(STR_SAVELOAD_OVERWRITE_TITLE, STR_SAVELOAD_OVERWRITE_WARNING, this, SaveLoadWindow::SaveGameConfirmationCallback); + ShowQuery(STR_SAVELOAD_OVERWRITE_TITLE, STR_SAVELOAD_OVERWRITE_WARNING, MakeParameters(), this, SaveLoadWindow::SaveGameConfirmationCallback); } else { _switch_mode = SM_SAVE_GAME; } } else { _file_to_saveload.name = FiosMakeHeightmapName(this->filename_editbox.text.buf); if (FioCheckFileExists(_file_to_saveload.name, Subdirectory::SAVE_DIR)) { - ShowQuery(STR_SAVELOAD_OVERWRITE_TITLE, STR_SAVELOAD_OVERWRITE_WARNING, this, SaveLoadWindow::SaveHeightmapConfirmationCallback); + ShowQuery(STR_SAVELOAD_OVERWRITE_TITLE, STR_SAVELOAD_OVERWRITE_WARNING, MakeParameters(), this, SaveLoadWindow::SaveHeightmapConfirmationCallback); } else { _switch_mode = SM_SAVE_HEIGHTMAP; } diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index c895640756..3c5cae812c 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -718,6 +718,7 @@ struct GenerateLandscapeWindow : public Window { ShowQuery( STR_WARNING_HEIGHTMAP_SCALE_CAPTION, STR_WARNING_HEIGHTMAP_SCALE_MESSAGE, + MakeParameters(), this, LandscapeGenerationCallback); } else { @@ -1397,6 +1398,7 @@ struct GenerateProgressWindow : public Window { ShowQuery( STR_GENERATION_ABORT_CAPTION, STR_GENERATION_ABORT_MESSAGE, + MakeParameters(), this, AbortGeneratingWorldCallback ); diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 50e6990fe8..8204ad005e 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -788,7 +788,7 @@ public: case WID_GL_DELETE_GROUP: { // Delete the selected group this->group_confirm = this->vli.index; - ShowQuery(STR_QUERY_GROUP_DELETE_CAPTION, STR_GROUP_DELETE_QUERY_TEXT, this, DeleteGroupCallback); + ShowQuery(STR_QUERY_GROUP_DELETE_CAPTION, STR_GROUP_DELETE_QUERY_TEXT, MakeParameters(), this, DeleteGroupCallback); break; } diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 1de7153292..b8ef844de6 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -631,14 +631,14 @@ public: case WID_DPI_CREATE_RANDOM_INDUSTRIES_WIDGET: { assert(_game_mode == GM_EDITOR); this->HandleButtonClick(WID_DPI_CREATE_RANDOM_INDUSTRIES_WIDGET); - ShowQuery(STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY, nullptr, AskManyRandomIndustriesCallback); + ShowQuery(STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY, MakeParameters(), nullptr, AskManyRandomIndustriesCallback); break; } case WID_DPI_REMOVE_ALL_INDUSTRIES_WIDGET: { assert(_game_mode == GM_EDITOR); this->HandleButtonClick(WID_DPI_REMOVE_ALL_INDUSTRIES_WIDGET); - ShowQuery(STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION, STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY, nullptr, AskRemoveAllIndustriesCallback); + ShowQuery(STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION, STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY, MakeParameters(), nullptr, AskRemoveAllIndustriesCallback); break; } diff --git a/src/intro_gui.cpp b/src/intro_gui.cpp index 31f8e0d3ce..bc7868bb12 100644 --- a/src/intro_gui.cpp +++ b/src/intro_gui.cpp @@ -481,6 +481,7 @@ void AskExitGame() ShowQuery( STR_QUIT_CAPTION, STR_QUIT_ARE_YOU_SURE_YOU_WANT_TO_EXIT_OPENTTD, + MakeParameters(), nullptr, AskExitGameCallback, true @@ -501,6 +502,7 @@ void AskExitToGameMenu() ShowQuery( STR_ABANDON_GAME_CAPTION, (_game_mode != GM_EDITOR) ? STR_ABANDON_GAME_QUERY : STR_ABANDON_SCENARIO_QUERY, + MakeParameters(), nullptr, AskExitToGameMenuCallback, true diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp index d1d79f024b..ccc31d1e0c 100644 --- a/src/misc_cmd.cpp +++ b/src/misc_cmd.cpp @@ -188,6 +188,7 @@ CommandCost CmdPause(DoCommandFlag flags, PauseMode mode, bool pause) ShowQuery( STR_NEWGRF_UNPAUSE_WARNING_TITLE, STR_NEWGRF_UNPAUSE_WARNING, + MakeParameters(), nullptr, AskUnsafeUnpauseCallback ); diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 5bb0f07169..3be247d4b1 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -1093,18 +1093,18 @@ void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *paren */ struct QueryWindow : public Window { QueryCallbackProc *proc; ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise - std::vector params; ///< local copy of #_global_string_params + std::vector params; ///< Parameters for the message. StringID message; ///< message shown for query window - QueryWindow(WindowDesc *desc, StringID caption, StringID message, Window *parent, QueryCallbackProc *callback) : Window(desc) + QueryWindow(WindowDesc *desc, StringID caption, StringID message, StringParameters &¶ms, Window *parent, QueryCallbackProc *callback) : Window(desc) { - /* Create a backup of the variadic arguments to strings because it will be - * overridden pretty often. We will copy these back for drawing */ - CopyOutDParam(this->params, 10); + CopyOutDParam(this->params, std::move(params)); this->message = message; this->proc = callback; this->parent = parent; + CopyInDParam(this->params); + this->CreateNestedTree(); this->GetWidget(WID_Q_CAPTION)->SetDataTip(caption, STR_NULL); this->FinishInitNested(WN_CONFIRM_POPUP_QUERY); @@ -1219,12 +1219,13 @@ static WindowDesc _query_desc(__FILE__, __LINE__, * The window is aligned to the centre of its parent. * @param caption string shown as window caption * @param message string that will be shown for the window + * @param params Parameters for the message. * @param parent pointer to parent window, if this pointer is nullptr the parent becomes * the main window WC_MAIN_WINDOW * @param callback callback function pointer to set in the window descriptor * @param focus whether the window should be focussed (by default false) */ -void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc *callback, bool focus) +void ShowQuery(StringID caption, StringID message, StringParameters &¶ms, Window *parent, QueryCallbackProc *callback, bool focus) { if (parent == nullptr) parent = GetMainWindow(); @@ -1238,6 +1239,6 @@ void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallback break; } - QueryWindow *q = new QueryWindow(&_query_desc, caption, message, parent, callback); + QueryWindow *q = new QueryWindow(&_query_desc, caption, message, std::move(params), parent, callback); if (focus) SetFocusedWindow(q); } diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 6285d7aee9..05e0744a33 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -869,7 +869,7 @@ public: if (_accepted_external_search) { this->OpenExternalSearch(); } else { - ShowQuery(STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER_CAPTION, STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER, this, ExternalSearchDisclaimerCallback); + ShowQuery(STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER_CAPTION, STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER, MakeParameters(), this, ExternalSearchDisclaimerCallback); } break; } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 3fae07af1c..f2ad6e3229 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1842,6 +1842,7 @@ public: case WID_CL_MATRIX: { StringID text = STR_NULL; + auto params = MakeParameters(0); QueryCallbackProc *callback = nullptr; switch (index) { @@ -1849,28 +1850,28 @@ public: _admin_client_id = this->dd_client_id; text = STR_NETWORK_CLIENT_LIST_ASK_CLIENT_KICK; callback = AdminClientKickCallback; - SetDParamStr(0, NetworkClientInfo::GetByClientID(_admin_client_id)->client_name); + params.SetParam(0, NetworkClientInfo::GetByClientID(_admin_client_id)->client_name); break; case DD_CLIENT_ADMIN_BAN: _admin_client_id = this->dd_client_id; text = STR_NETWORK_CLIENT_LIST_ASK_CLIENT_BAN; callback = AdminClientBanCallback; - SetDParamStr(0, NetworkClientInfo::GetByClientID(_admin_client_id)->client_name); + params.SetParam(0, NetworkClientInfo::GetByClientID(_admin_client_id)->client_name); break; case DD_COMPANY_ADMIN_RESET: _admin_company_id = this->dd_company_id; text = STR_NETWORK_CLIENT_LIST_ASK_COMPANY_RESET; callback = AdminCompanyResetCallback; - SetDParam(0, _admin_company_id); + params.SetParam(0, _admin_company_id); break; case DD_COMPANY_ADMIN_UNLOCK: _admin_company_id = this->dd_company_id; text = STR_NETWORK_CLIENT_LIST_ASK_COMPANY_UNLOCK; callback = AdminCompanyUnlockCallback; - SetDParam(0, _admin_company_id); + params.SetParam(0, _admin_company_id); break; default: @@ -1881,7 +1882,7 @@ public: assert(callback != nullptr); /* Always ask confirmation for all admin actions. */ - ShowQuery(STR_NETWORK_CLIENT_LIST_ASK_CAPTION, text, this, callback); + ShowQuery(STR_NETWORK_CLIENT_LIST_ASK_CAPTION, text, std::move(params), this, callback); break; } diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index 94d06bbad4..73eaf0a58c 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1124,6 +1124,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { ShowQuery( STR_NEWGRF_POPUP_CAUTION_CAPTION, STR_NEWGRF_CONFIRMATION_TEXT, + MakeParameters(), this, NewGRFConfirmationCallback ); diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 8bfd8cec87..203bec2b78 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -885,9 +885,7 @@ void MakeScreenshotWithConfirm(ScreenshotType t) if (width * height > 8192 * 8192) { /* Ask for confirmation */ _confirmed_screenshot_type = t; - SetDParam(0, width); - SetDParam(1, height); - ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, nullptr, ScreenshotConfirmationCallback); + ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, MakeParameters(width, height), nullptr, ScreenshotConfirmationCallback); } else { /* Less than 64M pixels, just do it */ MakeScreenshot(t, {}); diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index e3ab70b394..88e03f743d 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -2536,6 +2536,7 @@ struct GameSettingsWindow : Window { ShowQuery( STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION, STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT, + MakeParameters(), this, ResetAllSettingsConfirmationCallback ); diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp index e589c4f20e..8c9f4e2f9c 100644 --- a/src/terraform_gui.cpp +++ b/src/terraform_gui.cpp @@ -637,7 +637,7 @@ struct ScenarioEditorLandscapeGenerationWindow : Window { break; case WID_ETT_RESET_LANDSCAPE: // Reset landscape - ShowQuery(STR_QUERY_RESET_LANDSCAPE_CAPTION, STR_RESET_LANDSCAPE_CONFIRMATION_TEXT, nullptr, ResetLandscapeConfirmationCallback); + ShowQuery(STR_QUERY_RESET_LANDSCAPE_CAPTION, STR_RESET_LANDSCAPE_CONFIRMATION_TEXT, MakeParameters(), nullptr, ResetLandscapeConfirmationCallback); break; default: NOT_REACHED(); diff --git a/src/textbuf_gui.h b/src/textbuf_gui.h index 0284bbd57e..3b50d013b2 100644 --- a/src/textbuf_gui.h +++ b/src/textbuf_gui.h @@ -29,7 +29,7 @@ DECLARE_ENUM_AS_BIT_SET(QueryStringFlags) typedef void QueryCallbackProc(Window*, bool); void ShowQueryString(StringID str, StringID caption, uint max_len, Window *parent, CharSetFilter afilter, QueryStringFlags flags); -void ShowQuery(StringID caption, StringID message, Window *w, QueryCallbackProc *callback, bool focus = false); +void ShowQuery(StringID caption, StringID message, class StringParameters &¶ms, Window *w, QueryCallbackProc *callback, bool focus = false); /** The number of 'characters' on the on-screen keyboard. */ static const uint OSK_KEYBOARD_ENTRIES = 50; From fcc3365b1ff7efe7ca5099814ef3f12067e64673 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 2 Feb 2024 19:10:06 +0100 Subject: [PATCH 6/7] Codechange: use StringParameters to pass parameters for TextEffect strings --- src/misc_gui.cpp | 18 ++++++++---------- src/texteff.cpp | 11 ++++++----- src/texteff.hpp | 4 ++-- src/vehicle_gui.cpp | 3 ++- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 3be247d4b1..e71c4370c3 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -572,8 +572,8 @@ void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost) cost = -cost; msg = STR_INCOME_FLOAT_INCOME; } - SetDParam(0, cost); - AddTextEffect(msg, pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING); + + AddTextEffect(msg, MakeParameters(cost), pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING); } /** @@ -588,17 +588,15 @@ void ShowFeederIncomeAnimation(int x, int y, int z, Money transfer, Money income { Point pt = RemapCoords(x, y, z); - SetDParam(0, transfer); if (income == 0) { - AddTextEffect(STR_FEEDER, pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING); + AddTextEffect(STR_FEEDER, MakeParameters(transfer), pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING); } else { StringID msg = STR_FEEDER_COST; if (income < 0) { income = -income; msg = STR_FEEDER_INCOME; } - SetDParam(1, income); - AddTextEffect(msg, pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING); + AddTextEffect(msg, MakeParameters(transfer, income), pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING); } } @@ -617,8 +615,7 @@ TextEffectID ShowFillingPercent(int x, int y, int z, uint8_t percent, StringID s assert(string != STR_NULL); - SetDParam(0, percent); - return AddTextEffect(string, pt.x, pt.y, 0, TE_STATIC); + return AddTextEffect(string, MakeParameters(percent), pt.x, pt.y, 0, TE_STATIC); } /** @@ -630,8 +627,9 @@ void UpdateFillingPercent(TextEffectID te_id, uint8_t percent, StringID string) { assert(string != STR_NULL); - SetDParam(0, percent); - UpdateTextEffect(te_id, string); + auto params = MakeParameters(1); + params.SetParam(0, percent); + UpdateTextEffect(te_id, string, std::move(params)); } /** diff --git a/src/texteff.cpp b/src/texteff.cpp index 01dca6087c..001d45f2d2 100644 --- a/src/texteff.cpp +++ b/src/texteff.cpp @@ -38,7 +38,7 @@ struct TextEffect : public ViewportSign { static std::vector _text_effects; ///< Text effects are stored there /* Text Effects */ -TextEffectID AddTextEffect(StringID msg, int center, int y, uint8_t duration, TextEffectMode mode) +TextEffectID AddTextEffect(StringID msg, StringParameters &¶ms, int center, int y, uint8_t duration, TextEffectMode mode) { if (_game_mode == GM_MENU) return INVALID_TE_ID; @@ -54,24 +54,25 @@ TextEffectID AddTextEffect(StringID msg, int center, int y, uint8_t duration, Te /* Start defining this object */ te.string_id = msg; te.duration = duration; - CopyOutDParam(te.params, 2); + CopyOutDParam(te.params, std::move(params)); te.mode = mode; /* Make sure we only dirty the new area */ te.width_normal = 0; + CopyInDParam(te.params); te.UpdatePosition(center, y, msg); return static_cast(it - std::begin(_text_effects)); } -void UpdateTextEffect(TextEffectID te_id, StringID msg) +void UpdateTextEffect(TextEffectID te_id, StringID msg, StringParameters &¶ms) { /* Update details */ TextEffect &te = _text_effects[te_id]; - if (msg == te.string_id && !HaveDParamChanged(te.params)) return; te.string_id = msg; - CopyOutDParam(te.params, 2); + CopyOutDParam(te.params, std::move(params)); + CopyInDParam(te.params); te.UpdatePosition(te.center, te.top, te.string_id, te.string_id - 1); } diff --git a/src/texteff.hpp b/src/texteff.hpp index dad9b5888d..8df8de5480 100644 --- a/src/texteff.hpp +++ b/src/texteff.hpp @@ -26,10 +26,10 @@ using TextEffectID = uint16_t; static const TextEffectID INVALID_TE_ID = UINT16_MAX; -TextEffectID AddTextEffect(StringID msg, int x, int y, uint8_t duration, TextEffectMode mode); +TextEffectID AddTextEffect(StringID msg, class StringParameters &¶ms, int x, int y, uint8_t duration, TextEffectMode mode); void InitTextEffects(); void DrawTextEffects(DrawPixelInfo *dpi); -void UpdateTextEffect(TextEffectID effect_id, StringID msg); +void UpdateTextEffect(TextEffectID effect_id, StringID msg, StringParameters &¶ms); void RemoveTextEffect(TextEffectID effect_id); void UpdateAllTextEffectVirtCoords(); diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 4d1df21501..0802d20fb8 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2899,7 +2899,8 @@ void CcStartStopVehicle(Commands, const CommandCost &result, VehicleID veh_id, b StringID msg = (v->vehstatus & VS_STOPPED) ? STR_VEHICLE_COMMAND_STOPPED : STR_VEHICLE_COMMAND_STARTED; Point pt = RemapCoords(v->x_pos, v->y_pos, v->z_pos); - AddTextEffect(msg, pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING); + + AddTextEffect(msg, MakeParameters(), pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING); } /** From 0574fd767cf60b6516ce9f05ef5a30111e4571ba Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 2 Feb 2024 19:12:57 +0100 Subject: [PATCH 7/7] Codechange: remove now unused functions related to old CopyOutDParm --- src/strings.cpp | 38 ---------------------------- src/strings_func.h | 2 -- src/tests/CMakeLists.txt | 1 - src/tests/strings_func.cpp | 52 -------------------------------------- 4 files changed, 93 deletions(-) delete mode 100644 src/tests/strings_func.cpp diff --git a/src/strings.cpp b/src/strings.cpp index 6a1205d541..a88099fb73 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -168,24 +168,6 @@ void CopyInDParam(const std::span backup) } } -/** - * Copy \a num string parameters from the global string parameter array to the \a backup. - * @param backup The backup to write to. - * @param num Number of string parameters to copy. - */ -void CopyOutDParam(std::vector &backup, size_t num) -{ - backup.resize(num); - for (size_t i = 0; i < backup.size(); i++) { - const char *str = _global_string_params.GetParamStr(i); - if (str != nullptr) { - backup[i] = str; - } else { - backup[i] = _global_string_params.GetParam(i); - } - } -} - /** * Copy parameters into StringParameterBackup for long-term storage. * @param backup The backup to write to. @@ -207,26 +189,6 @@ void CopyOutDParam(std::vector &backup, StringParameters } } -/** - * Checks whether the global string parameters have changed compared to the given backup. - * @param backup The backup to check against. - * @return True when the parameters have changed, otherwise false. - */ -bool HaveDParamChanged(const std::vector &backup) -{ - bool changed = false; - for (size_t i = 0; !changed && i < backup.size(); i++) { - bool global_has_string = _global_string_params.GetParamStr(i) != nullptr; - if (global_has_string != backup[i].string.has_value()) return true; - - if (global_has_string) { - changed = backup[i].string.value() != _global_string_params.GetParamStr(i); - } else { - changed = backup[i].data != _global_string_params.GetParam(i); - } - } - return changed; -} static void StationGetSpecialString(StringBuilder &builder, StationFacility x); static void GetSpecialTownNameString(StringBuilder &builder, int ind, uint32_t seed); diff --git a/src/strings_func.h b/src/strings_func.h index 4cc208b991..4a495112a2 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -99,9 +99,7 @@ void SetDParamStr(size_t n, const std::string &str); void SetDParamStr(size_t n, std::string &&str); void CopyInDParam(const std::span backup); -void CopyOutDParam(std::vector &backup, size_t num); void CopyOutDParam(std::vector &backup, class StringParameters &¶ms); -bool HaveDParamChanged(const std::vector &backup); uint64_t GetDParam(size_t n); diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 53884be7d7..55b71946b9 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -7,7 +7,6 @@ add_test_files( mock_spritecache.cpp mock_spritecache.h string_func.cpp - strings_func.cpp test_main.cpp test_script_admin.cpp test_window_desc.cpp diff --git a/src/tests/strings_func.cpp b/src/tests/strings_func.cpp deleted file mode 100644 index dd70b0a365..0000000000 --- a/src/tests/strings_func.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 . - */ - -/** @file strings_func.cpp Test functionality from strings_func. */ - -#include "../stdafx.h" - -#include "../3rdparty/catch2/catch.hpp" - -#include "../strings_func.h" - -TEST_CASE("HaveDParamChanged") -{ - SetDParam(0, 0); - SetDParamStr(1, "some string"); - - std::vector backup; - CopyOutDParam(backup, 2); - - CHECK(HaveDParamChanged(backup) == false); - - /* A different parameter 0 (both string and numeric). */ - SetDParam(0, 1); - CHECK(HaveDParamChanged(backup) == true); - - SetDParamStr(0, "some other string"); - CHECK(HaveDParamChanged(backup) == true); - - /* Back to the original state, nothing should have changed. */ - SetDParam(0, 0); - CHECK(HaveDParamChanged(backup) == false); - - /* A different parameter 1 (both string and numeric). */ - SetDParamStr(1, "some other string"); - CHECK(HaveDParamChanged(backup) == true); - - SetDParam(1, 0); - CHECK(HaveDParamChanged(backup) == true); - - /* Back to the original state, nothing should have changed. */ - SetDParamStr(1, "some string"); - CHECK(HaveDParamChanged(backup) == false); - - /* Changing paramter 2 should not have any effect, as the backup is only 2 long. */ - SetDParam(2, 3); - CHECK(HaveDParamChanged(backup) == false); - -}