OpenTTD
script_config.cpp
Go to the documentation of this file.
1 /* $Id: script_config.cpp 26509 2014-04-25 15:40:32Z rubidium $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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  */
9 
12 #include "../stdafx.h"
13 #include "../settings_type.h"
14 #include "../core/random_func.hpp"
15 #include "script_info.hpp"
16 #include "../textfile_gui.h"
17 #include "../string_func.h"
18 
19 #include "../safeguards.h"
20 
21 void ScriptConfig::Change(const char *name, int version, bool force_exact_match, bool is_random)
22 {
23  free(this->name);
24  this->name = (name == NULL) ? NULL : stredup(name);
25  this->info = (name == NULL) ? NULL : this->FindInfo(this->name, version, force_exact_match);
26  this->version = (info == NULL) ? -1 : info->GetVersion();
27  this->is_random = is_random;
28  if (this->config_list != NULL) delete this->config_list;
29  this->config_list = (info == NULL) ? NULL : new ScriptConfigItemList();
30  if (this->config_list != NULL) this->PushExtraConfigList();
31 
32  this->ClearConfigList();
33 
34  if (_game_mode == GM_NORMAL && this->info != NULL) {
35  /* If we're in an existing game and the Script is changed, set all settings
36  * for the Script that have the random flag to a random value. */
37  for (ScriptConfigItemList::const_iterator it = this->info->GetConfigList()->begin(); it != this->info->GetConfigList()->end(); it++) {
38  if ((*it).flags & SCRIPTCONFIG_RANDOM) {
39  this->SetSetting((*it).name, InteractiveRandomRange((*it).max_value - (*it).min_value) + (*it).min_value);
40  }
41  }
42  this->AddRandomDeviation();
43  }
44 }
45 
46 ScriptConfig::ScriptConfig(const ScriptConfig *config)
47 {
48  this->name = (config->name == NULL) ? NULL : stredup(config->name);
49  this->info = config->info;
50  this->version = config->version;
51  this->config_list = NULL;
52  this->is_random = config->is_random;
53 
54  for (SettingValueList::const_iterator it = config->settings.begin(); it != config->settings.end(); it++) {
55  this->settings[stredup((*it).first)] = (*it).second;
56  }
57  this->AddRandomDeviation();
58 }
59 
61 {
62  free(this->name);
63  this->ResetSettings();
64  if (this->config_list != NULL) delete this->config_list;
65 }
66 
68 {
69  return this->info;
70 }
71 
73 {
74  if (this->info != NULL) return this->info->GetConfigList();
75  if (this->config_list == NULL) {
76  this->config_list = new ScriptConfigItemList();
77  this->PushExtraConfigList();
78  }
79  return this->config_list;
80 }
81 
83 {
84  for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
85  free((*it).first);
86  }
87  this->settings.clear();
88 }
89 
91 {
92  for (ScriptConfigItemList::const_iterator it = this->GetConfigList()->begin(); it != this->GetConfigList()->end(); it++) {
93  if (((*it).flags & SCRIPTCONFIG_INGAME) == 0) {
94  this->SetSetting((*it).name, this->GetSetting((*it).name));
95  }
96  }
97 }
98 
99 int ScriptConfig::GetSetting(const char *name) const
100 {
101  SettingValueList::const_iterator it = this->settings.find(name);
102  if (it == this->settings.end()) return this->info->GetSettingDefaultValue(name);
103  return (*it).second;
104 }
105 
106 void ScriptConfig::SetSetting(const char *name, int value)
107 {
108  /* You can only set Script specific settings if an Script is selected. */
109  if (this->info == NULL) return;
110 
111  const ScriptConfigItem *config_item = this->info->GetConfigItem(name);
112  if (config_item == NULL) return;
113 
114  value = Clamp(value, config_item->min_value, config_item->max_value);
115 
116  SettingValueList::iterator it = this->settings.find(name);
117  if (it != this->settings.end()) {
118  (*it).second = value;
119  } else {
120  this->settings[stredup(name)] = value;
121  }
122 }
123 
125 {
126  for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
127  free((*it).first);
128  }
129  this->settings.clear();
130 }
131 
133 {
134  for (ScriptConfigItemList::const_iterator it = this->GetConfigList()->begin(); it != this->GetConfigList()->end(); it++) {
135  if ((*it).random_deviation != 0) {
136  this->SetSetting((*it).name, InteractiveRandomRange((*it).random_deviation * 2) - (*it).random_deviation + this->GetSetting((*it).name));
137  }
138  }
139 }
140 
142 {
143  return this->info != NULL;
144 }
145 
147 {
148  return this->is_random;
149 }
150 
151 const char *ScriptConfig::GetName() const
152 {
153  return this->name;
154 }
155 
157 {
158  return this->version;
159 }
160 
161 void ScriptConfig::StringToSettings(const char *value)
162 {
163  char *value_copy = stredup(value);
164  char *s = value_copy;
165 
166  while (s != NULL) {
167  /* Analyze the string ('name=value,name=value\0') */
168  char *item_name = s;
169  s = strchr(s, '=');
170  if (s == NULL) break;
171  if (*s == '\0') break;
172  *s = '\0';
173  s++;
174 
175  char *item_value = s;
176  s = strchr(s, ',');
177  if (s != NULL) {
178  *s = '\0';
179  s++;
180  }
181 
182  this->SetSetting(item_name, atoi(item_value));
183  }
184  free(value_copy);
185 }
186 
187 void ScriptConfig::SettingsToString(char *string, const char *last) const
188 {
189  char *s = string;
190  *s = '\0';
191  for (SettingValueList::const_iterator it = this->settings.begin(); it != this->settings.end(); it++) {
192  char no[10];
193  seprintf(no, lastof(no), "%d", (*it).second);
194 
195  /* Check if the string would fit in the destination */
196  size_t needed_size = strlen((*it).first) + 1 + strlen(no);
197  /* If it doesn't fit, skip the next settings */
198  if (string + needed_size > last) break;
199 
200  s = strecat(s, (*it).first, last);
201  s = strecat(s, "=", last);
202  s = strecat(s, no, last);
203  s = strecat(s, ",", last);
204  }
205 
206  /* Remove the last ',', but only if at least one setting was saved. */
207  if (s != string) s[-1] = '\0';
208 }
209 
210 const char *ScriptConfig::GetTextfile(TextfileType type, CompanyID slot) const
211 {
212  if (slot == INVALID_COMPANY || this->GetInfo() == NULL) return NULL;
213 
214  return ::GetTextfile(type, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR, this->GetInfo()->GetMainScript());
215 }