2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file script_config.cpp Implementation of ScriptConfig. */
10 #include "../stdafx.h"
11 #include "../settings_type.h"
12 #include "../core/random_func.hpp"
13 #include "script_info.hpp"
14 #include "api/script_object.hpp"
15 #include "../textfile_gui.h"
16 #include "../string_func.h"
19 #include "../safeguards.h"
21 void ScriptConfig::Change(std::optional
<const std::string
> name
, int version
, bool force_exact_match
)
23 if (name
.has_value()) {
24 this->name
= std::move(name
.value());
25 this->info
= this->FindInfo(this->name
, version
, force_exact_match
);
29 this->version
= (info
== nullptr) ? -1 : info
->GetVersion();
30 this->config_list
.reset();
31 this->to_load_data
.reset();
33 this->ClearConfigList();
36 ScriptConfig::ScriptConfig(const ScriptConfig
*config
)
38 this->name
= config
->name
;
39 this->info
= config
->info
;
40 this->version
= config
->version
;
41 this->to_load_data
.reset();
43 for (const auto &item
: config
->settings
) {
44 this->settings
[item
.first
] = item
.second
;
48 ScriptConfig::~ScriptConfig()
50 this->ResetSettings();
51 this->to_load_data
.reset();
54 ScriptInfo
*ScriptConfig::GetInfo() const
59 const ScriptConfigItemList
*ScriptConfig::GetConfigList()
61 if (this->info
!= nullptr) return this->info
->GetConfigList();
62 if (this->config_list
== nullptr) {
63 this->config_list
= std::make_unique
<ScriptConfigItemList
>();
65 return this->config_list
.get();
68 void ScriptConfig::ClearConfigList()
70 this->settings
.clear();
73 void ScriptConfig::AnchorUnchangeableSettings()
75 for (const auto &item
: *this->GetConfigList()) {
76 if ((item
.flags
& SCRIPTCONFIG_INGAME
) == 0) {
77 this->SetSetting(item
.name
, this->GetSetting(item
.name
));
82 int ScriptConfig::GetSetting(const std::string
&name
) const
84 const auto it
= this->settings
.find(name
);
85 if (it
== this->settings
.end()) return this->info
->GetSettingDefaultValue(name
);
89 void ScriptConfig::SetSetting(const std::string_view name
, int value
)
91 /* You can only set Script specific settings if an Script is selected. */
92 if (this->info
== nullptr) return;
94 const ScriptConfigItem
*config_item
= this->info
->GetConfigItem(name
);
95 if (config_item
== nullptr) return;
97 value
= Clamp(value
, config_item
->min_value
, config_item
->max_value
);
99 this->settings
[std::string
{name
}] = value
;
102 void ScriptConfig::ResetSettings()
104 this->settings
.clear();
107 void ScriptConfig::ResetEditableSettings(bool yet_to_start
)
109 if (this->info
== nullptr) return ResetSettings();
111 for (SettingValueList::iterator it
= this->settings
.begin(); it
!= this->settings
.end();) {
112 const ScriptConfigItem
*config_item
= this->info
->GetConfigItem(it
->first
);
113 assert(config_item
!= nullptr);
115 bool editable
= yet_to_start
|| (config_item
->flags
& SCRIPTCONFIG_INGAME
) != 0;
116 bool visible
= _settings_client
.gui
.ai_developer_tools
|| (config_item
->flags
& SCRIPTCONFIG_DEVELOPER
) == 0;
118 if (editable
&& visible
) {
119 it
= this->settings
.erase(it
);
126 bool ScriptConfig::HasScript() const
128 return this->info
!= nullptr;
131 const std::string
&ScriptConfig::GetName() const
136 int ScriptConfig::GetVersion() const
138 return this->version
;
141 void ScriptConfig::StringToSettings(const std::string
&value
)
143 std::string_view to_process
= value
;
145 /* Analyze the string ('name=value,name=value\0') */
146 size_t pos
= to_process
.find_first_of('=');
147 if (pos
== std::string_view::npos
) return;
149 std::string_view item_name
= to_process
.substr(0, pos
);
151 to_process
.remove_prefix(pos
+ 1);
152 pos
= to_process
.find_first_of(',');
154 std::from_chars(to_process
.data(), to_process
.data() + std::min(pos
, to_process
.size()), item_value
);
156 this->SetSetting(item_name
, item_value
);
158 if (pos
== std::string_view::npos
) return;
159 to_process
.remove_prefix(pos
+ 1);
163 std::string
ScriptConfig::SettingsToString() const
165 if (this->settings
.empty()) return {};
168 for (const auto &item
: this->settings
) {
169 fmt::format_to(std::back_inserter(result
), "{}={},", item
.first
, item
.second
);
172 /* Remove the last ','. */
173 result
.resize(result
.size() - 1);
177 std::optional
<std::string
> ScriptConfig::GetTextfile(TextfileType type
, CompanyID slot
) const
179 if (slot
== INVALID_COMPANY
|| this->GetInfo() == nullptr) return std::nullopt
;
181 return ::GetTextfile(type
, (slot
== OWNER_DEITY
) ? GAME_DIR
: AI_DIR
, this->GetInfo()->GetMainScript());
184 void ScriptConfig::SetToLoadData(ScriptInstance::ScriptData
*data
)
186 this->to_load_data
.reset(data
);
189 ScriptInstance::ScriptData
*ScriptConfig::GetToLoadData()
191 return this->to_load_data
.get();