branch | gamebalance |
changeset 9908 | 0fa543611bbe |
parent 9907 | 3b068c3a1c74 |
child 9909 | dce9a6923bb7 |
9907:3b068c3a1c74 | 9908:0fa543611bbe |
---|---|
1 /* $Id$ */ |
1 /* $Id$ */ |
2 |
2 |
3 /** @file |
3 /** @file settings.cpp |
4 * All actions handling saving and loading of the settings/configuration goes on in this file. |
4 * All actions handling saving and loading of the settings/configuration goes on in this file. |
5 * The file consists of four parts: |
5 * The file consists of four parts: |
6 * <ol> |
6 * <ol> |
7 * <li>Parsing the configuration file (openttd.cfg). This is achieved with the ini_ functions which |
7 * <li>Parsing the configuration file (openttd.cfg). This is achieved with the ini_ functions which |
8 * handle various types, such as normal 'key = value' pairs, lists and value combinations of |
8 * handle various types, such as normal 'key = value' pairs, lists and value combinations of |
93 uint pos; |
93 uint pos; |
94 SettingsMemoryPool *p = *pool; |
94 SettingsMemoryPool *p = *pool; |
95 |
95 |
96 size = ALIGN(size, sizeof(void*)); |
96 size = ALIGN(size, sizeof(void*)); |
97 |
97 |
98 // first check if there's memory in the next pool |
98 /* first check if there's memory in the next pool */ |
99 if (p->next && p->next->pos + size <= p->next->size) { |
99 if (p->next && p->next->pos + size <= p->next->size) { |
100 p = p->next; |
100 p = p->next; |
101 // then check if there's not memory in the cur pool |
101 /* then check if there's not memory in the cur pool */ |
102 } else if (p->pos + size > p->size) { |
102 } else if (p->pos + size > p->size) { |
103 SettingsMemoryPool *n = pool_new(size); |
103 SettingsMemoryPool *n = pool_new(size); |
104 *pool = n; |
104 *pool = n; |
105 n->next = p; |
105 n->next = p; |
106 p = n; |
106 p = n; |
128 free(p); |
128 free(p); |
129 p = n; |
129 p = n; |
130 } |
130 } |
131 } |
131 } |
132 |
132 |
133 // structs describing the ini format. |
133 /** structs describing the ini format. */ |
134 struct IniItem { |
134 struct IniItem { |
135 char *name; |
135 char *name; |
136 char *value; |
136 char *value; |
137 char *comment; |
137 char *comment; |
138 IniItem *next; |
138 IniItem *next; |
139 }; |
139 }; |
140 |
140 |
141 struct IniGroup { |
141 struct IniGroup { |
142 char *name; // name of group |
142 char *name; ///< name of group |
143 char *comment; //comment for group |
143 char *comment; ///<comment for group |
144 IniItem *item, **last_item; |
144 IniItem *item, **last_item; |
145 IniGroup *next; |
145 IniGroup *next; |
146 IniFile *ini; |
146 IniFile *ini; |
147 IniGroupType type; // type of group |
147 IniGroupType type; ///< type of group |
148 }; |
148 }; |
149 |
149 |
150 struct IniFile { |
150 struct IniFile { |
151 SettingsMemoryPool *pool; |
151 SettingsMemoryPool *pool; |
152 IniGroup *group, **last_group; |
152 IniGroup *group, **last_group; |
153 char *comment; // last comment in file |
153 char *comment; ///< last comment in file |
154 }; |
154 }; |
155 |
155 |
156 // allocate an inifile object |
156 /** allocate an inifile object */ |
157 static IniFile *ini_alloc() |
157 static IniFile *ini_alloc() |
158 { |
158 { |
159 IniFile *ini; |
159 IniFile *ini; |
160 SettingsMemoryPool *pool; |
160 SettingsMemoryPool *pool; |
161 pool_init(&pool); |
161 pool_init(&pool); |
165 ini->last_group = &ini->group; |
165 ini->last_group = &ini->group; |
166 ini->comment = NULL; |
166 ini->comment = NULL; |
167 return ini; |
167 return ini; |
168 } |
168 } |
169 |
169 |
170 // allocate an ini group object |
170 /** allocate an ini group object */ |
171 static IniGroup *ini_group_alloc(IniFile *ini, const char *grpt, int len) |
171 static IniGroup *ini_group_alloc(IniFile *ini, const char *grpt, int len) |
172 { |
172 { |
173 IniGroup *grp = (IniGroup*)pool_alloc(&ini->pool, sizeof(IniGroup)); |
173 IniGroup *grp = (IniGroup*)pool_alloc(&ini->pool, sizeof(IniGroup)); |
174 grp->ini = ini; |
174 grp->ini = ini; |
175 grp->name = (char*)pool_strdup(&ini->pool, grpt, len); |
175 grp->name = (char*)pool_strdup(&ini->pool, grpt, len); |
197 *group->last_item = item; |
197 *group->last_item = item; |
198 group->last_item = &item->next; |
198 group->last_item = &item->next; |
199 return item; |
199 return item; |
200 } |
200 } |
201 |
201 |
202 // load an ini file into the "abstract" format |
202 /** load an ini file into the "abstract" format */ |
203 static IniFile *ini_load(const char *filename) |
203 static IniFile *ini_load(const char *filename) |
204 { |
204 { |
205 char buffer[1024], c, *s, *t, *e; |
205 char buffer[1024], c, *s, *t, *e; |
206 FILE *in; |
206 FILE *in; |
207 IniFile *ini; |
207 IniFile *ini; |
215 ini = ini_alloc(); |
215 ini = ini_alloc(); |
216 |
216 |
217 in = fopen(filename, "r"); |
217 in = fopen(filename, "r"); |
218 if (in == NULL) return ini; |
218 if (in == NULL) return ini; |
219 |
219 |
220 // for each line in the file |
220 /* for each line in the file */ |
221 while (fgets(buffer, sizeof(buffer), in)) { |
221 while (fgets(buffer, sizeof(buffer), in)) { |
222 |
222 |
223 // trim whitespace from the left side |
223 /* trim whitespace from the left side */ |
224 for (s = buffer; *s == ' ' || *s == '\t'; s++); |
224 for (s = buffer; *s == ' ' || *s == '\t'; s++); |
225 |
225 |
226 // trim whitespace from right side. |
226 /* trim whitespace from right side. */ |
227 e = s + strlen(s); |
227 e = s + strlen(s); |
228 while (e > s && ((c=e[-1]) == '\n' || c == '\r' || c == ' ' || c == '\t')) e--; |
228 while (e > s && ((c=e[-1]) == '\n' || c == '\r' || c == ' ' || c == '\t')) e--; |
229 *e = '\0'; |
229 *e = '\0'; |
230 |
230 |
231 // skip comments and empty lines |
231 /* skip comments and empty lines */ |
232 if (*s == '#' || *s == ';' || *s == '\0') { |
232 if (*s == '#' || *s == ';' || *s == '\0') { |
233 uint ns = comment_size + (e - s + 1); |
233 uint ns = comment_size + (e - s + 1); |
234 uint a = comment_alloc; |
234 uint a = comment_alloc; |
235 uint pos; |
235 uint pos; |
236 // add to comment |
236 /* add to comment */ |
237 if (ns > a) { |
237 if (ns > a) { |
238 a = max(a, 128U); |
238 a = max(a, 128U); |
239 do a*=2; while (a < ns); |
239 do a*=2; while (a < ns); |
240 comment = ReallocT(comment, comment_alloc = a); |
240 comment = ReallocT(comment, comment_alloc = a); |
241 } |
241 } |
244 comment[pos + e - s] = '\n'; // comment newline |
244 comment[pos + e - s] = '\n'; // comment newline |
245 memcpy(comment + pos, s, e - s); // copy comment contents |
245 memcpy(comment + pos, s, e - s); // copy comment contents |
246 continue; |
246 continue; |
247 } |
247 } |
248 |
248 |
249 // it's a group? |
249 /* it's a group? */ |
250 if (s[0] == '[') { |
250 if (s[0] == '[') { |
251 if (e[-1] != ']') { |
251 if (e[-1] != ']') { |
252 ShowInfoF("ini: invalid group name '%s'", buffer); |
252 ShowInfoF("ini: invalid group name '%s'", buffer); |
253 } else { |
253 } else { |
254 e--; |
254 e--; |
258 if (comment_size) { |
258 if (comment_size) { |
259 group->comment = (char*)pool_strdup(&ini->pool, comment, comment_size); |
259 group->comment = (char*)pool_strdup(&ini->pool, comment, comment_size); |
260 comment_size = 0; |
260 comment_size = 0; |
261 } |
261 } |
262 } else if (group) { |
262 } else if (group) { |
263 // find end of keyname |
263 /* find end of keyname */ |
264 for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++); |
264 if (*s == '\"') { |
265 |
265 s++; |
266 // it's an item in an existing group |
266 for (t = s; *t != '\0' && *t != '\"'; t++); |
267 if (*t == '\"') *t = ' '; |
|
268 } else { |
|
269 for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++); |
|
270 } |
|
271 |
|
272 /* it's an item in an existing group */ |
|
267 item = ini_item_alloc(group, s, t-s); |
273 item = ini_item_alloc(group, s, t-s); |
268 if (comment_size) { |
274 if (comment_size) { |
269 item->comment = (char*)pool_strdup(&ini->pool, comment, comment_size); |
275 item->comment = (char*)pool_strdup(&ini->pool, comment, comment_size); |
270 comment_size = 0; |
276 comment_size = 0; |
271 } |
277 } |
272 |
278 |
273 // find start of parameter |
279 /* find start of parameter */ |
274 while (*t == '=' || *t == ' ' || *t == '\t') t++; |
280 while (*t == '=' || *t == ' ' || *t == '\t') t++; |
275 |
281 |
276 |
282 |
277 // remove starting quotation marks |
283 /* remove starting quotation marks */ |
278 if (*t == '\"') t++; |
284 if (*t == '\"') t++; |
279 // remove ending quotation marks |
285 /* remove ending quotation marks */ |
280 e = t + strlen(t); |
286 e = t + strlen(t); |
281 if (e > t && e[-1] == '\"') e--; |
287 if (e > t && e[-1] == '\"') e--; |
282 *e = '\0'; |
288 *e = '\0'; |
283 |
289 |
284 item->value = (char*)pool_strdup(&ini->pool, t, e - t); |
290 item->value = (char*)pool_strdup(&ini->pool, t, e - t); |
285 } else { |
291 } else { |
286 // it's an orphan item |
292 /* it's an orphan item */ |
287 ShowInfoF("ini: '%s' outside of group", buffer); |
293 ShowInfoF("ini: '%s' outside of group", buffer); |
288 } |
294 } |
289 } |
295 } |
290 |
296 |
291 if (comment_size > 0) { |
297 if (comment_size > 0) { |
297 fclose(in); |
303 fclose(in); |
298 |
304 |
299 return ini; |
305 return ini; |
300 } |
306 } |
301 |
307 |
302 // lookup a group or make a new one |
308 /** lookup a group or make a new one */ |
303 static IniGroup *ini_getgroup(IniFile *ini, const char *name, int len) |
309 static IniGroup *ini_getgroup(IniFile *ini, const char *name, int len) |
304 { |
310 { |
305 IniGroup *group; |
311 IniGroup *group; |
306 |
312 |
307 if (len == -1) len = strlen(name); |
313 if (len == -1) len = strlen(name); |
308 |
314 |
309 // does it exist already? |
315 /* does it exist already? */ |
310 for (group = ini->group; group; group = group->next) |
316 for (group = ini->group; group; group = group->next) |
311 if (!memcmp(group->name, name, len) && group->name[len] == 0) |
317 if (!memcmp(group->name, name, len) && group->name[len] == 0) |
312 return group; |
318 return group; |
313 |
319 |
314 // otherwise make a new one |
320 /* otherwise make a new one */ |
315 group = ini_group_alloc(ini, name, len); |
321 group = ini_group_alloc(ini, name, len); |
316 group->comment = (char*)pool_strdup(&ini->pool, "\n", 1); |
322 group->comment = (char*)pool_strdup(&ini->pool, "\n", 1); |
317 return group; |
323 return group; |
318 } |
324 } |
319 |
325 |
320 // lookup an item or make a new one |
326 /** lookup an item or make a new one */ |
321 static IniItem *ini_getitem(IniGroup *group, const char *name, bool create) |
327 static IniItem *ini_getitem(IniGroup *group, const char *name, bool create) |
322 { |
328 { |
323 IniItem *item; |
329 IniItem *item; |
324 uint len = strlen(name); |
330 uint len = strlen(name); |
325 |
331 |
326 for (item = group->item; item; item = item->next) |
332 for (item = group->item; item; item = item->next) |
327 if (strcmp(item->name, name) == 0) return item; |
333 if (strcmp(item->name, name) == 0) return item; |
328 |
334 |
329 if (!create) return NULL; |
335 if (!create) return NULL; |
330 |
336 |
331 // otherwise make a new one |
337 /* otherwise make a new one */ |
332 return ini_item_alloc(group, name, len); |
338 return ini_item_alloc(group, name, len); |
333 } |
339 } |
334 |
340 |
335 // save ini file from the "abstract" format. |
341 /** save ini file from the "abstract" format. */ |
336 static bool ini_save(const char *filename, IniFile *ini) |
342 static bool ini_save(const char *filename, IniFile *ini) |
337 { |
343 { |
338 FILE *f; |
344 FILE *f; |
339 IniGroup *group; |
345 IniGroup *group; |
340 IniItem *item; |
346 IniItem *item; |
347 fprintf(f, "[%s]\n", group->name); |
353 fprintf(f, "[%s]\n", group->name); |
348 for (item = group->item; item != NULL; item = item->next) { |
354 for (item = group->item; item != NULL; item = item->next) { |
349 assert(item->value != NULL); |
355 assert(item->value != NULL); |
350 if (item->comment != NULL) fputs(item->comment, f); |
356 if (item->comment != NULL) fputs(item->comment, f); |
351 |
357 |
358 /* protect item->name with quotes if needed */ |
|
359 if (strchr(item->name, ' ') != NULL) { |
|
360 fprintf(f, "\"%s\"", item->name); |
|
361 } else { |
|
362 fprintf(f, "%s", item->name); |
|
363 } |
|
364 |
|
352 /* Don't give an equal sign to list items that don't have a parameter */ |
365 /* Don't give an equal sign to list items that don't have a parameter */ |
353 if (group->type == IGT_LIST && *item->value == '\0') { |
366 if (group->type == IGT_LIST && *item->value == '\0') { |
354 fprintf(f, "%s\n", item->name); |
367 fprintf(f, "\n"); |
355 } else { |
368 } else { |
356 fprintf(f, "%s = %s\n", item->name, item->value); |
369 fprintf(f, " = %s\n", item->value); |
357 } |
370 } |
358 } |
371 } |
359 } |
372 } |
360 if (ini->comment) fputs(ini->comment, f); |
373 if (ini->comment) fputs(ini->comment, f); |
361 |
374 |
378 const char *s; |
391 const char *s; |
379 int idx; |
392 int idx; |
380 |
393 |
381 if (onelen == -1) onelen = strlen(one); |
394 if (onelen == -1) onelen = strlen(one); |
382 |
395 |
383 // check if it's an integer |
396 /* check if it's an integer */ |
384 if (*one >= '0' && *one <= '9') |
397 if (*one >= '0' && *one <= '9') |
385 return strtoul(one, NULL, 0); |
398 return strtoul(one, NULL, 0); |
386 |
399 |
387 idx = 0; |
400 idx = 0; |
388 for (;;) { |
401 for (;;) { |
389 // find end of item |
402 /* find end of item */ |
390 s = many; |
403 s = many; |
391 while (*s != '|' && *s != 0) s++; |
404 while (*s != '|' && *s != 0) s++; |
392 if (s - many == onelen && !memcmp(one, many, onelen)) return idx; |
405 if (s - many == onelen && !memcmp(one, many, onelen)) return idx; |
393 if (*s == 0) return -1; |
406 if (*s == 0) return -1; |
394 many = s + 1; |
407 many = s + 1; |
406 const char *s; |
419 const char *s; |
407 int r; |
420 int r; |
408 uint32 res = 0; |
421 uint32 res = 0; |
409 |
422 |
410 for (;;) { |
423 for (;;) { |
411 // skip "whitespace" |
424 /* skip "whitespace" */ |
412 while (*str == ' ' || *str == '\t' || *str == '|') str++; |
425 while (*str == ' ' || *str == '\t' || *str == '|') str++; |
413 if (*str == 0) break; |
426 if (*str == 0) break; |
414 |
427 |
415 s = str; |
428 s = str; |
416 while (*s != 0 && *s != ' ' && *s != '\t' && *s != '|') s++; |
429 while (*s != 0 && *s != ' ' && *s != '\t' && *s != '|') s++; |
520 * @param id the value of the variable and whose string-representation must be found */ |
533 * @param id the value of the variable and whose string-representation must be found */ |
521 static void make_oneofmany(char *buf, const char *many, int id) |
534 static void make_oneofmany(char *buf, const char *many, int id) |
522 { |
535 { |
523 int orig_id = id; |
536 int orig_id = id; |
524 |
537 |
525 // Look for the id'th element |
538 /* Look for the id'th element */ |
526 while (--id >= 0) { |
539 while (--id >= 0) { |
527 for (; *many != '|'; many++) { |
540 for (; *many != '|'; many++) { |
528 if (*many == '\0') { // not found |
541 if (*many == '\0') { // not found |
529 sprintf(buf, "%d", orig_id); |
542 sprintf(buf, "%d", orig_id); |
530 return; |
543 return; |
531 } |
544 } |
532 } |
545 } |
533 many++; // pass the |-character |
546 many++; // pass the |-character |
534 } |
547 } |
535 |
548 |
536 // copy string until next item (|) or the end of the list if this is the last one |
549 /* copy string until next item (|) or the end of the list if this is the last one */ |
537 while (*many != '\0' && *many != '|') *buf++ = *many++; |
550 while (*many != '\0' && *many != '|') *buf++ = *many++; |
538 *buf = '\0'; |
551 *buf = '\0'; |
539 } |
552 } |
540 |
553 |
541 /** Convert a MANYofMANY structure to a string representation. |
554 /** Convert a MANYofMANY structure to a string representation. |
683 const SettingDescBase *sdb = &sd->desc; |
696 const SettingDescBase *sdb = &sd->desc; |
684 const SaveLoad *sld = &sd->save; |
697 const SaveLoad *sld = &sd->save; |
685 |
698 |
686 if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; |
699 if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; |
687 |
700 |
688 // XXX - wtf is this?? (group override?) |
701 /* XXX - wtf is this?? (group override?) */ |
689 s = strchr(sdb->name, '.'); |
702 s = strchr(sdb->name, '.'); |
690 if (s != NULL) { |
703 if (s != NULL) { |
691 group = ini_getgroup(ini, sdb->name, s - sdb->name); |
704 group = ini_getgroup(ini, sdb->name, s - sdb->name); |
692 s++; |
705 s++; |
693 } else { |
706 } else { |
759 /* If the setting is not saved to the configuration |
772 /* If the setting is not saved to the configuration |
760 * file, just continue with the next setting */ |
773 * file, just continue with the next setting */ |
761 if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; |
774 if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; |
762 if (sld->conv & SLF_CONFIG_NO) continue; |
775 if (sld->conv & SLF_CONFIG_NO) continue; |
763 |
776 |
764 // XXX - wtf is this?? (group override?) |
777 /* XXX - wtf is this?? (group override?) */ |
765 s = strchr(sdb->name, '.'); |
778 s = strchr(sdb->name, '.'); |
766 if (s != NULL) { |
779 if (s != NULL) { |
767 group = ini_getgroup(ini, sdb->name, s - sdb->name); |
780 group = ini_getgroup(ini, sdb->name, s - sdb->name); |
768 s++; |
781 s++; |
769 } else { |
782 } else { |
774 |
787 |
775 item = ini_getitem(group, s, true); |
788 item = ini_getitem(group, s, true); |
776 ptr = GetVariableAddress(object, sld); |
789 ptr = GetVariableAddress(object, sld); |
777 |
790 |
778 if (item->value != NULL) { |
791 if (item->value != NULL) { |
779 // check if the value is the same as the old value |
792 /* check if the value is the same as the old value */ |
780 const void *p = string_to_val(sdb, item->value); |
793 const void *p = string_to_val(sdb, item->value); |
781 |
794 |
782 /* The main type of a variable/setting is in bytes 8-15 |
795 /* The main type of a variable/setting is in bytes 8-15 |
783 * The subtype (what kind of numbers do we have there) is in 0-7 */ |
796 * The subtype (what kind of numbers do we have there) is in 0-7 */ |
784 switch (sdb->cmd) { |
797 switch (sdb->cmd) { |
927 * We have two types of list: |
940 * We have two types of list: |
928 * 1. SDTG_something |
941 * 1. SDTG_something |
929 * 2. SDT_something |
942 * 2. SDT_something |
930 * The 'G' stands for global, so this is the one you will use for a |
943 * The 'G' stands for global, so this is the one you will use for a |
931 * SettingDescGlobVarList section meaning global variables. The other uses a |
944 * SettingDescGlobVarList section meaning global variables. The other uses a |
932 * Base/Offset and runtime variable selection mechanism, known from the saveload * convention (it also has global so it should not be hard). |
945 * Base/Offset and runtime variable selection mechanism, known from the saveload |
946 * convention (it also has global so it should not be hard). |
|
933 * Of each type there are again two versions, the normal one and one prefixed |
947 * Of each type there are again two versions, the normal one and one prefixed |
934 * with 'COND'. |
948 * with 'COND'. |
935 * COND means that the setting is only valid in certain savegame versions |
949 * COND means that the setting is only valid in certain savegame versions |
936 * (since patches are saved to the savegame, this bookkeeping is necessary. |
950 * (since patches are saved to the savegame, this bookkeeping is necessary. |
937 * Now there are a lot of types. Easy ones are: |
951 * Now there are a lot of types. Easy ones are: |
1050 #define SDT_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL, NULL}, SLE_END()} |
1064 #define SDT_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL, NULL}, SLE_END()} |
1051 |
1065 |
1052 /* Shortcuts for macros below. Logically if we don't save the value |
1066 /* Shortcuts for macros below. Logically if we don't save the value |
1053 * we also don't sync it in a network game */ |
1067 * we also don't sync it in a network game */ |
1054 #define S SLF_SAVE_NO | SLF_NETWORK_NO |
1068 #define S SLF_SAVE_NO | SLF_NETWORK_NO |
1055 #define NS SLF_SAVE_NO |
|
1056 #define C SLF_CONFIG_NO |
1069 #define C SLF_CONFIG_NO |
1057 #define N SLF_NETWORK_NO |
1070 #define N SLF_NETWORK_NO |
1058 |
1071 |
1059 #define D0 SGF_0ISDISABLED |
1072 #define D0 SGF_0ISDISABLED |
1060 #define NC SGF_NOCOMMA |
1073 #define NC SGF_NOCOMMA |
1067 /* Begin - Callback Functions for the various settings */ |
1080 /* Begin - Callback Functions for the various settings */ |
1068 #include "window.h" |
1081 #include "window.h" |
1069 #include "gui.h" |
1082 #include "gui.h" |
1070 #include "town.h" |
1083 #include "town.h" |
1071 #include "gfx.h" |
1084 #include "gfx.h" |
1072 // virtual PositionMainToolbar function, calls the right one. |
1085 /* virtual PositionMainToolbar function, calls the right one.*/ |
1073 static int32 v_PositionMainToolbar(int32 p1) |
1086 static int32 v_PositionMainToolbar(int32 p1) |
1074 { |
1087 { |
1075 if (_game_mode != GM_MENU) PositionMainToolbar(NULL); |
1088 if (_game_mode != GM_MENU) PositionMainToolbar(NULL); |
1076 return 0; |
1089 return 0; |
1077 } |
1090 } |
1203 SDTG_END() |
1216 SDTG_END() |
1204 }; |
1217 }; |
1205 #endif /* WIN32 */ |
1218 #endif /* WIN32 */ |
1206 |
1219 |
1207 static const SettingDescGlobVarList _misc_settings[] = { |
1220 static const SettingDescGlobVarList _misc_settings[] = { |
1208 SDTG_MMANY("display_opt", SLE_UINT8, S, 0, _display_opt, (DO_SHOW_TOWN_NAMES|DO_SHOW_STATION_NAMES|DO_SHOW_SIGNS|DO_FULL_ANIMATION|DO_FULL_DETAIL|DO_TRANS_BUILDINGS|DO_WAYPOINTS), "SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|TRANS_BUILDINGS|FULL_DETAIL|WAYPOINTS", STR_NULL, NULL), |
1221 SDTG_MMANY("display_opt", SLE_UINT8, S, 0, _display_opt, (DO_SHOW_TOWN_NAMES|DO_SHOW_STATION_NAMES|DO_SHOW_SIGNS|DO_FULL_ANIMATION|DO_FULL_DETAIL|DO_WAYPOINTS), "SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|FULL_DETAIL|WAYPOINTS", STR_NULL, NULL), |
1209 SDTG_BOOL("news_ticker_sound", S, 0, _news_ticker_sound, true, STR_NULL, NULL), |
1222 SDTG_BOOL("news_ticker_sound", S, 0, _news_ticker_sound, true, STR_NULL, NULL), |
1210 SDTG_BOOL("fullscreen", S, 0, _fullscreen, false, STR_NULL, NULL), |
1223 SDTG_BOOL("fullscreen", S, 0, _fullscreen, false, STR_NULL, NULL), |
1211 SDTG_STR("videodriver", SLE_STRB,C|S,0, _ini_videodriver, NULL, STR_NULL, NULL), |
1224 SDTG_STR("videodriver", SLE_STRB,C|S,0, _ini_videodriver, NULL, STR_NULL, NULL), |
1212 SDTG_STR("musicdriver", SLE_STRB,C|S,0, _ini_musicdriver, NULL, STR_NULL, NULL), |
1225 SDTG_STR("musicdriver", SLE_STRB,C|S,0, _ini_musicdriver, NULL, STR_NULL, NULL), |
1213 SDTG_STR("sounddriver", SLE_STRB,C|S,0, _ini_sounddriver, NULL, STR_NULL, NULL), |
1226 SDTG_STR("sounddriver", SLE_STRB,C|S,0, _ini_sounddriver, NULL, STR_NULL, NULL), |
1378 SDT_VAR(Patches, colored_news_year,SLE_INT32, 0,NC, 2000, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,NULL), |
1391 SDT_VAR(Patches, colored_news_year,SLE_INT32, 0,NC, 2000, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,NULL), |
1379 SDT_VAR(Patches, starting_year, SLE_INT32, 0,NC, 1950, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_STARTING_YEAR,NULL), |
1392 SDT_VAR(Patches, starting_year, SLE_INT32, 0,NC, 1950, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_STARTING_YEAR,NULL), |
1380 SDT_VAR(Patches, ending_year, SLE_INT32,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_ENDING_YEAR, NULL), |
1393 SDT_VAR(Patches, ending_year, SLE_INT32,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_ENDING_YEAR, NULL), |
1381 SDT_BOOL(Patches, smooth_economy, 0, 0, true, STR_CONFIG_PATCHES_SMOOTH_ECONOMY, NULL), |
1394 SDT_BOOL(Patches, smooth_economy, 0, 0, true, STR_CONFIG_PATCHES_SMOOTH_ECONOMY, NULL), |
1382 SDT_BOOL(Patches, allow_shares, 0, 0, false, STR_CONFIG_PATCHES_ALLOW_SHARES, NULL), |
1395 SDT_BOOL(Patches, allow_shares, 0, 0, false, STR_CONFIG_PATCHES_ALLOW_SHARES, NULL), |
1396 SDT_CONDVAR(Patches, town_growth_rate, SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0, 4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH, NULL), |
|
1397 SDT_CONDVAR(Patches, larger_towns, SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS, NULL), |
|
1383 |
1398 |
1384 /***************************************************************************/ |
1399 /***************************************************************************/ |
1385 /* AI section of the GUI-configure patches window */ |
1400 /* AI section of the GUI-configure patches window */ |
1386 SDT_BOOL(Patches, ainew_active, 0, 0, false, STR_CONFIG_PATCHES_AINEW_ACTIVE, AiNew_PatchActive_Warning), |
1401 SDT_BOOL(Patches, ainew_active, 0, 0, false, STR_CONFIG_PATCHES_AINEW_ACTIVE, AiNew_PatchActive_Warning), |
1387 SDT_BOOL(Patches, ai_in_multiplayer, 0, 0, false, STR_CONFIG_PATCHES_AI_IN_MULTIPLAYER, Ai_In_Multiplayer_Warning), |
1402 SDT_BOOL(Patches, ai_in_multiplayer, 0, 0, false, STR_CONFIG_PATCHES_AI_IN_MULTIPLAYER, Ai_In_Multiplayer_Warning), |
1459 SDT_VAR(Patches, npf_crossing_penalty, SLE_UINT, 0, 0, (3 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), |
1474 SDT_VAR(Patches, npf_crossing_penalty, SLE_UINT, 0, 0, (3 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), |
1460 /* This is the penalty for drive-through road, stops. */ |
1475 /* This is the penalty for drive-through road, stops. */ |
1461 SDT_CONDVAR (Patches, npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * NPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1476 SDT_CONDVAR (Patches, npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * NPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1462 |
1477 |
1463 |
1478 |
1464 // The maximum number of nodes to search |
1479 /* The maximum number of nodes to search */ |
1465 SDT_CONDBOOL(Patches, yapf.disable_node_optimization , 28, SL_MAX_VERSION, 0, 0, false , STR_NULL, NULL), |
1480 SDT_CONDBOOL(Patches, yapf.disable_node_optimization , 28, SL_MAX_VERSION, 0, 0, false , STR_NULL, NULL), |
1466 SDT_CONDVAR (Patches, yapf.max_search_nodes , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10000 , 500, 1000000, 0, STR_NULL, NULL), |
1481 SDT_CONDVAR (Patches, yapf.max_search_nodes , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10000 , 500, 1000000, 0, STR_NULL, NULL), |
1467 SDT_CONDBOOL(Patches, yapf.rail_firstred_twoway_eol , 28, SL_MAX_VERSION, 0, 0, true , STR_NULL, NULL), |
1482 SDT_CONDBOOL(Patches, yapf.rail_firstred_twoway_eol , 28, SL_MAX_VERSION, 0, 0, true , STR_NULL, NULL), |
1468 SDT_CONDVAR (Patches, yapf.rail_firstred_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1483 SDT_CONDVAR (Patches, yapf.rail_firstred_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1469 SDT_CONDVAR (Patches, yapf.rail_firstred_exit_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 100 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1484 SDT_CONDVAR (Patches, yapf.rail_firstred_exit_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 100 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1471 SDT_CONDVAR (Patches, yapf.rail_lastred_exit_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 100 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1486 SDT_CONDVAR (Patches, yapf.rail_lastred_exit_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 100 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1472 SDT_CONDVAR (Patches, yapf.rail_station_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 30 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1487 SDT_CONDVAR (Patches, yapf.rail_station_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 30 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1473 SDT_CONDVAR (Patches, yapf.rail_slope_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1488 SDT_CONDVAR (Patches, yapf.rail_slope_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1474 SDT_CONDVAR (Patches, yapf.rail_curve45_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1489 SDT_CONDVAR (Patches, yapf.rail_curve45_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1475 SDT_CONDVAR (Patches, yapf.rail_curve90_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 6 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1490 SDT_CONDVAR (Patches, yapf.rail_curve90_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 6 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1476 // This penalty is applied when a train reverses inside a depot |
1491 /* This penalty is applied when a train reverses inside a depot */ |
1477 SDT_CONDVAR (Patches, yapf.rail_depot_reverse_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 50 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1492 SDT_CONDVAR (Patches, yapf.rail_depot_reverse_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 50 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1478 // This is the penalty for level crossings (for trains only) |
1493 /* This is the penalty for level crossings (for trains only) */ |
1479 SDT_CONDVAR (Patches, yapf.rail_crossing_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1494 SDT_CONDVAR (Patches, yapf.rail_crossing_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1480 // look-ahead how many signals are checked |
1495 /* look-ahead how many signals are checked */ |
1481 SDT_CONDVAR (Patches, yapf.rail_look_ahead_max_signals, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10 , 1, 100, 0, STR_NULL, NULL), |
1496 SDT_CONDVAR (Patches, yapf.rail_look_ahead_max_signals, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10 , 1, 100, 0, STR_NULL, NULL), |
1482 // look-ahead n-th red signal penalty polynomial: penalty = p2 * n^2 + p1 * n + p0 |
1497 /* look-ahead n-th red signal penalty polynomial: penalty = p2 * n^2 + p1 * n + p0 */ |
1483 SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p0 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, 500 , -1000000, 1000000, 0, STR_NULL, NULL), |
1498 SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p0 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, 500 , -1000000, 1000000, 0, STR_NULL, NULL), |
1484 SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p1 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, -100 , -1000000, 1000000, 0, STR_NULL, NULL), |
1499 SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p1 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, -100 , -1000000, 1000000, 0, STR_NULL, NULL), |
1485 SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p2 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, 5 , -1000000, 1000000, 0, STR_NULL, NULL), |
1500 SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p2 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, 5 , -1000000, 1000000, 0, STR_NULL, NULL), |
1486 // penalties for too long or too short station platforms |
1501 /* penalties for too long or too short station platforms */ |
1487 SDT_CONDVAR (Patches, yapf.rail_longer_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), |
1502 SDT_CONDVAR (Patches, yapf.rail_longer_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), |
1488 SDT_CONDVAR (Patches, yapf.rail_longer_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), |
1503 SDT_CONDVAR (Patches, yapf.rail_longer_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), |
1489 SDT_CONDVAR (Patches, yapf.rail_shorter_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 40 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), |
1504 SDT_CONDVAR (Patches, yapf.rail_shorter_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 40 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), |
1490 SDT_CONDVAR (Patches, yapf.rail_shorter_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), |
1505 SDT_CONDVAR (Patches, yapf.rail_shorter_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), |
1491 // road vehicles - penalties |
1506 /* road vehicles - penalties */ |
1492 SDT_CONDVAR (Patches, yapf.road_slope_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1507 SDT_CONDVAR (Patches, yapf.road_slope_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1493 SDT_CONDVAR (Patches, yapf.road_curve_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1508 SDT_CONDVAR (Patches, yapf.road_curve_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1494 SDT_CONDVAR (Patches, yapf.road_crossing_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1509 SDT_CONDVAR (Patches, yapf.road_crossing_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1495 SDT_CONDVAR (Patches, yapf.road_stop_penalty , SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1510 SDT_CONDVAR (Patches, yapf.road_stop_penalty , SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), |
1496 |
1511 |
1575 |
1590 |
1576 if (group == NULL) return NULL; |
1591 if (group == NULL) return NULL; |
1577 |
1592 |
1578 for (item = group->item; item != NULL; item = item->next) { |
1593 for (item = group->item; item != NULL; item = item->next) { |
1579 GRFConfig *c = CallocT<GRFConfig>(1); |
1594 GRFConfig *c = CallocT<GRFConfig>(1); |
1580 c->filename = strdup(item->name); |
1595 c->full_path = strdup(item->name); |
1581 |
1596 |
1582 /* Parse parameters */ |
1597 /* Parse parameters */ |
1583 if (*item->value != '\0') { |
1598 if (*item->value != '\0') { |
1584 c->num_params = parse_intlist(item->value, (int*)c->param, lengthof(c->param)); |
1599 c->num_params = parse_intlist(item->value, (int*)c->param, lengthof(c->param)); |
1585 if (c->num_params == (byte)-1) { |
1600 if (c->num_params == (byte)-1) { |
1652 |
1667 |
1653 for (c = list; c != NULL; c = c->next) { |
1668 for (c = list; c != NULL; c = c->next) { |
1654 char params[512]; |
1669 char params[512]; |
1655 GRFBuildParamList(params, c, lastof(params)); |
1670 GRFBuildParamList(params, c, lastof(params)); |
1656 |
1671 |
1657 *item = ini_item_alloc(group, c->filename, strlen(c->filename)); |
1672 *item = ini_item_alloc(group, c->full_path, strlen(c->full_path)); |
1658 (*item)->value = (char*)pool_strdup(&ini->pool, params, strlen(params)); |
1673 (*item)->value = (char*)pool_strdup(&ini->pool, params, strlen(params)); |
1659 item = &(*item)->next; |
1674 item = &(*item)->next; |
1660 } |
1675 } |
1661 } |
1676 } |
1662 |
1677 |
1828 |
1843 |
1829 IConsolePrintF(_icolour_warn, "Current value for '%s' is: '%s' (min: %s%d, max: %d)", |
1844 IConsolePrintF(_icolour_warn, "Current value for '%s' is: '%s' (min: %s%d, max: %d)", |
1830 name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max); |
1845 name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max); |
1831 } |
1846 } |
1832 |
1847 |
1848 void IConsoleListPatches() |
|
1849 { |
|
1850 IConsolePrintF(_icolour_warn, "All patches with their current value:"); |
|
1851 |
|
1852 for (const SettingDesc *sd = _patch_settings; sd->save.cmd != SL_END; sd++) { |
|
1853 char value[80]; |
|
1854 const void *ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_patches_newgame : &_patches, &sd->save); |
|
1855 |
|
1856 if (sd->desc.cmd == SDT_BOOLX) { |
|
1857 snprintf(value, lengthof(value), (*(bool*)ptr == 1) ? "on" : "off"); |
|
1858 } else { |
|
1859 snprintf(value, lengthof(value), "%d", (uint32)ReadValue(ptr, sd->save.conv)); |
|
1860 } |
|
1861 IConsolePrintF(_icolour_def, "%s = %s", sd->desc.name, value); |
|
1862 } |
|
1863 |
|
1864 IConsolePrintF(_icolour_warn, "Use 'patch' command to change a value"); |
|
1865 } |
|
1866 |
|
1833 /** Save and load handler for patches/settings |
1867 /** Save and load handler for patches/settings |
1834 * @param osd SettingDesc struct containing all information |
1868 * @param osd SettingDesc struct containing all information |
1835 * @param object can be either NULL in which case we load global variables or |
1869 * @param object can be either NULL in which case we load global variables or |
1836 * a pointer to a struct which is getting saved */ |
1870 * a pointer to a struct which is getting saved */ |
1837 static void LoadSettings(const SettingDesc *osd, void *object) |
1871 static void LoadSettings(const SettingDesc *osd, void *object) |