1 /*
2 C-Dogs SDL
3 A port of the legendary (and fun) action/arcade cdogs.
4
5 Copyright (c) 2013-2014, 2016-2018 Cong Xu
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10
11 Redistributions of source code must retain the above copyright notice, this
12 list of conditions and the following disclaimer.
13 Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation
15 and/or other materials provided with the distribution.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
28 */
29 #include "config.h"
30
31 #include <limits.h>
32 #include <stdio.h>
33
34 #include "blit.h"
35 #include "config_json.h"
36 #include "config_old.h"
37 #include "keyboard.h"
38 #include "music.h"
39 #include "sounds.h"
40 #include "utils.h"
41
42
DifficultyStr(int d)43 const char *DifficultyStr(int d)
44 {
45 switch (d)
46 {
47 T2S(DIFFICULTY_VERYEASY, "Easiest");
48 T2S(DIFFICULTY_EASY, "Easy");
49 T2S(DIFFICULTY_NORMAL, "Normal");
50 T2S(DIFFICULTY_HARD, "Hard");
51 T2S(DIFFICULTY_VERYHARD, "Very hard");
52 default:
53 return "";
54 }
55 }
StrDifficulty(const char * s)56 int StrDifficulty(const char *s)
57 {
58 S2T(DIFFICULTY_VERYEASY, "Easiest");
59 S2T(DIFFICULTY_EASY, "Easy");
60 S2T(DIFFICULTY_NORMAL, "Normal");
61 S2T(DIFFICULTY_HARD, "Hard");
62 S2T(DIFFICULTY_VERYHARD, "Very hard");
63 return DIFFICULTY_NORMAL;
64 }
FireMoveStyleStr(int s)65 const char *FireMoveStyleStr(int s)
66 {
67 switch (s)
68 {
69 T2S(FIREMOVE_STOP, "Stop");
70 T2S(FIREMOVE_NORMAL, "Normal");
71 T2S(FIREMOVE_STRAFE, "Strafe");
72 default:
73 return "";
74 }
75 }
StrFireMoveStyle(const char * s)76 int StrFireMoveStyle(const char *s)
77 {
78 S2T(FIREMOVE_STOP, "Stop");
79 S2T(FIREMOVE_NORMAL, "Normal");
80 S2T(FIREMOVE_STRAFE, "Strafe");
81 return FIREMOVE_STOP;
82 }
SwitchMoveStyleStr(int s)83 const char *SwitchMoveStyleStr(int s)
84 {
85 switch (s)
86 {
87 T2S(SWITCHMOVE_SLIDE, "Slide");
88 T2S(SWITCHMOVE_STRAFE, "Strafe");
89 T2S(SWITCHMOVE_NONE, "None");
90 default:
91 return "";
92 }
93 }
StrSwitchMoveStyle(const char * s)94 int StrSwitchMoveStyle(const char *s)
95 {
96 S2T(SWITCHMOVE_SLIDE, "Slide");
97 S2T(SWITCHMOVE_STRAFE, "Strafe");
98 S2T(SWITCHMOVE_NONE, "None");
99 return SWITCHMOVE_SLIDE;
100 }
ScaleModeStr(int s)101 const char *ScaleModeStr(int s)
102 {
103 switch (s)
104 {
105 T2S(SCALE_MODE_NN, "Nearest neighbor");
106 T2S(SCALE_MODE_BILINEAR, "Bilinear");
107 default:
108 return "";
109 }
110 }
StrScaleMode(const char * s)111 int StrScaleMode(const char *s)
112 {
113 S2T(SCALE_MODE_NN, "Nearest neighbor");
114 S2T(SCALE_MODE_BILINEAR, "Bilinear");
115 return SCALE_MODE_NN;
116 }
GoreAmountStr(int g)117 const char *GoreAmountStr(int g)
118 {
119 switch (g)
120 {
121 T2S(GORE_NONE, "None");
122 T2S(GORE_LOW, "Trickle");
123 T2S(GORE_MEDIUM, "Buckets");
124 T2S(GORE_HIGH, "Torrents");
125 default:
126 return "";
127 }
128 }
StrGoreAmount(const char * s)129 int StrGoreAmount(const char *s)
130 {
131 S2T(GORE_NONE, "None");
132 S2T(GORE_LOW, "Trickle");
133 S2T(GORE_MEDIUM, "Buckets");
134 S2T(GORE_HIGH, "Torrents");
135 return GORE_NONE;
136 }
LaserSightStr(int l)137 const char *LaserSightStr(int l)
138 {
139 switch (l)
140 {
141 T2S(LASER_SIGHT_NONE, "None");
142 T2S(LASER_SIGHT_PLAYERS, "Players only");
143 T2S(LASER_SIGHT_ALL, "All");
144 default:
145 return "";
146 }
147 }
StrLaserSight(const char * s)148 int StrLaserSight(const char *s)
149 {
150 S2T(LASER_SIGHT_NONE, "None");
151 S2T(LASER_SIGHT_PLAYERS, "Players only");
152 S2T(LASER_SIGHT_ALL, "All");
153 return LASER_SIGHT_NONE;
154 }
SplitscreenStyleStr(int s)155 const char *SplitscreenStyleStr(int s)
156 {
157 switch (s)
158 {
159 T2S(SPLITSCREEN_NORMAL, "Normal");
160 T2S(SPLITSCREEN_ALWAYS, "Always");
161 T2S(SPLITSCREEN_NEVER, "Never");
162 default:
163 return "";
164 }
165 }
StrSplitscreenStyle(const char * s)166 int StrSplitscreenStyle(const char *s)
167 {
168 S2T(SPLITSCREEN_NORMAL, "Normal");
169 S2T(SPLITSCREEN_ALWAYS, "Always");
170 S2T(SPLITSCREEN_NEVER, "Never");
171 return SPLITSCREEN_NORMAL;
172 }
AIChatterStr(int c)173 const char *AIChatterStr(int c)
174 {
175 switch (c)
176 {
177 T2S(AICHATTER_NONE, "None");
178 T2S(AICHATTER_SELDOM, "Seldom");
179 T2S(AICHATTER_OFTEN, "Often");
180 T2S(AICHATTER_ALWAYS, "Always");
181 default:
182 return "";
183 }
184 }
StrAIChatter(const char * s)185 int StrAIChatter(const char *s)
186 {
187 S2T(AICHATTER_NONE, "None");
188 S2T(AICHATTER_SELDOM, "Seldom");
189 S2T(AICHATTER_OFTEN, "Often");
190 S2T(AICHATTER_ALWAYS, "Always");
191 return AICHATTER_NONE;
192 }
QuickPlayQuantityStr(int q)193 const char *QuickPlayQuantityStr(int q)
194 {
195 switch (q)
196 {
197 T2S(QUICKPLAY_QUANTITY_ANY, "Any");
198 T2S(QUICKPLAY_QUANTITY_SMALL, "Small");
199 T2S(QUICKPLAY_QUANTITY_MEDIUM, "Medium");
200 T2S(QUICKPLAY_QUANTITY_LARGE, "Large");
201 default:
202 return "";
203 }
204 }
StrQuickPlayQuantity(const char * s)205 int StrQuickPlayQuantity(const char *s)
206 {
207 S2T(QUICKPLAY_QUANTITY_ANY, "Any");
208 S2T(QUICKPLAY_QUANTITY_SMALL, "Small");
209 S2T(QUICKPLAY_QUANTITY_MEDIUM, "Medium");
210 S2T(QUICKPLAY_QUANTITY_LARGE, "Large");
211 return QUICKPLAY_QUANTITY_ANY;
212 }
213
214
215 Config gConfig;
216
217 static Config ConfigNew(const char *name, const ConfigType type);
ConfigNewString(const char * name,const char * defaultValue)218 Config ConfigNewString(const char *name, const char *defaultValue)
219 {
220 Config c = ConfigNew(name, CONFIG_TYPE_STRING);
221 UNUSED(defaultValue);
222 CASSERT(false, "unimplemented");
223 return c;
224 }
ConfigNewInt(const char * name,const int defaultValue,const int minValue,const int maxValue,const int increment,int (* strToInt)(const char *),char * (* intToStr)(int))225 Config ConfigNewInt(
226 const char *name, const int defaultValue,
227 const int minValue, const int maxValue, const int increment,
228 int (*strToInt)(const char *), char *(*intToStr)(int))
229 {
230 Config c = ConfigNew(name, CONFIG_TYPE_INT);
231 c.u.Int.Default = c.u.Int.Value = c.u.Int.Last = defaultValue;
232 c.u.Int.Min = minValue;
233 c.u.Int.Max = maxValue;
234 c.u.Int.Increment = increment;
235 c.u.Int.StrToInt = strToInt ? strToInt : atoi;
236 c.u.Int.IntToStr = intToStr ? intToStr : IntStr;
237 return c;
238 }
ConfigNewFloat(const char * name,const double defaultValue,const double minValue,const double maxValue,const double increment)239 Config ConfigNewFloat(
240 const char *name, const double defaultValue,
241 const double minValue, const double maxValue, const double increment)
242 {
243 Config c = ConfigNew(name, CONFIG_TYPE_FLOAT);
244 c.u.Float.Default = c.u.Float.Value = c.u.Float.Last = defaultValue;
245 c.u.Float.Min = minValue;
246 c.u.Float.Max = maxValue;
247 c.u.Float.Increment = increment;
248 return c;
249 }
ConfigNewBool(const char * name,const bool defaultValue)250 Config ConfigNewBool(const char *name, const bool defaultValue)
251 {
252 Config c = ConfigNew(name, CONFIG_TYPE_BOOL);
253 c.u.Bool.Default = c.u.Bool.Value = c.u.Bool.Last = defaultValue;
254 return c;
255 }
ConfigNewEnum(const char * name,const int defaultValue,const int minValue,const int maxValue,int (* strToEnum)(const char *),const char * (* enumToStr)(int))256 Config ConfigNewEnum(
257 const char *name, const int defaultValue,
258 const int minValue, const int maxValue,
259 int (*strToEnum)(const char *), const char *(*enumToStr)(int))
260 {
261 Config c = ConfigNew(name, CONFIG_TYPE_ENUM);
262 c.u.Enum.Default = c.u.Enum.Value = c.u.Enum.Last = defaultValue;
263 c.u.Enum.Min = minValue;
264 c.u.Enum.Max = maxValue;
265 c.u.Enum.StrToEnum = strToEnum;
266 c.u.Enum.EnumToStr = enumToStr;
267 return c;
268 }
ConfigNewGroup(const char * name)269 Config ConfigNewGroup(const char *name)
270 {
271 Config c = ConfigNew(name, CONFIG_TYPE_GROUP);
272 CArrayInit(&c.u.Group, sizeof(Config));
273 return c;
274 }
ConfigNew(const char * name,const ConfigType type)275 static Config ConfigNew(const char *name, const ConfigType type)
276 {
277 Config c;
278 memset(&c, 0, sizeof c);
279 if (name != NULL)
280 {
281 CSTRDUP(c.Name, name);
282 }
283 c.Type = type;
284 return c;
285 }
286
ConfigDestroy(Config * c)287 void ConfigDestroy(Config *c)
288 {
289 CFREE(c->Name);
290 if (c->Type == CONFIG_TYPE_GROUP)
291 {
292 CA_FOREACH(Config, child, c->u.Group)
293 ConfigDestroy(child);
294 CA_FOREACH_END()
295 CArrayTerminate(&c->u.Group);
296 }
297 }
298
ConfigGroupAdd(Config * group,Config child)299 void ConfigGroupAdd(Config *group, Config child)
300 {
301 CASSERT(group->Type == CONFIG_TYPE_GROUP, "Invalid config type");
302 CArrayPushBack(&group->u.Group, &child);
303 }
304
ConfigGetVersion(FILE * f)305 int ConfigGetVersion(FILE *f)
306 {
307 if (ConfigIsOld(f))
308 {
309 return 0;
310 }
311 rewind(f);
312 return ConfigGetJSONVersion(f);
313 }
314
ConfigGet(Config * c,const char * name)315 Config *ConfigGet(Config *c, const char *name)
316 {
317 char *nameCopy;
318 CSTRDUP(nameCopy, name);
319 char *pch = strtok(nameCopy, ".");
320 while (pch != NULL)
321 {
322 if (c->Type != CONFIG_TYPE_GROUP)
323 {
324 CASSERT(false, "Invalid config type");
325 goto bail;
326 }
327 bool found = false;
328 CA_FOREACH(Config, child, c->u.Group)
329 if (strcmp(child->Name, pch) == 0)
330 {
331 c = child;
332 found = true;
333 break;
334 }
335 CA_FOREACH_END()
336 if (!found)
337 {
338 CASSERT(false, "Config not found");
339 goto bail;
340 }
341 pch = strtok(NULL, ".");
342 }
343 bail:
344 CFREE(nameCopy);
345 return c;
346 }
347
ConfigChanged(const Config * c)348 bool ConfigChanged(const Config *c)
349 {
350 switch (c->Type)
351 {
352 case CONFIG_TYPE_STRING:
353 return strcmp(c->u.String.Value, c->u.String.Last) != 0;
354 case CONFIG_TYPE_INT:
355 return c->u.Int.Value != c->u.Int.Last;
356 case CONFIG_TYPE_FLOAT:
357 return c->u.Float.Value != c->u.Float.Last;
358 case CONFIG_TYPE_BOOL:
359 return c->u.Bool.Value != c->u.Bool.Last;
360 case CONFIG_TYPE_ENUM:
361 return c->u.Enum.Value != c->u.Enum.Last;
362 case CONFIG_TYPE_GROUP:
363 CA_FOREACH(Config, child, c->u.Group)
364 if (ConfigChanged(child))
365 {
366 return true;
367 }
368 CA_FOREACH_END()
369 return false;
370 default:
371 CASSERT(false, "Unknown config type");
372 return false;
373 }
374 }
375
ConfigResetChanged(Config * c)376 void ConfigResetChanged(Config *c)
377 {
378 switch (c->Type)
379 {
380 case CONFIG_TYPE_STRING:
381 CFREE(c->u.String.Value);
382 if (c->u.String.Last != NULL)
383 {
384 CSTRDUP(c->u.String.Value, c->u.String.Last);
385 }
386 break;
387 case CONFIG_TYPE_INT:
388 c->u.Int.Value = c->u.Int.Last;
389 break;
390 case CONFIG_TYPE_FLOAT:
391 c->u.Float.Value = c->u.Float.Last;
392 break;
393 case CONFIG_TYPE_BOOL:
394 c->u.Bool.Value = c->u.Bool.Last;
395 break;
396 case CONFIG_TYPE_ENUM:
397 c->u.Enum.Value = c->u.Enum.Last;
398 break;
399 case CONFIG_TYPE_GROUP:
400 CA_FOREACH(Config, child, c->u.Group)
401 ConfigResetChanged(child);
402 CA_FOREACH_END()
403 break;
404 default:
405 CASSERT(false, "Unknown config type");
406 break;
407 }
408 }
409
ConfigSetChanged(Config * c)410 void ConfigSetChanged(Config *c)
411 {
412 switch (c->Type)
413 {
414 case CONFIG_TYPE_STRING:
415 CFREE(c->u.String.Last);
416 if (c->u.String.Value != NULL)
417 {
418 CSTRDUP(c->u.String.Last, c->u.String.Value);
419 }
420 break;
421 case CONFIG_TYPE_INT:
422 c->u.Int.Last = c->u.Int.Value;
423 break;
424 case CONFIG_TYPE_FLOAT:
425 c->u.Float.Last = c->u.Float.Value;
426 break;
427 case CONFIG_TYPE_BOOL:
428 c->u.Bool.Last = c->u.Bool.Value;
429 break;
430 case CONFIG_TYPE_ENUM:
431 c->u.Enum.Last = c->u.Enum.Value;
432 break;
433 case CONFIG_TYPE_GROUP:
434 CA_FOREACH(Config, child, c->u.Group)
435 ConfigSetChanged(child);
436 CA_FOREACH_END()
437 break;
438 default:
439 CASSERT(false, "Unknown config type");
440 break;
441 }
442 }
443
ConfigResetDefault(Config * c)444 void ConfigResetDefault(Config *c)
445 {
446 switch (c->Type)
447 {
448 case CONFIG_TYPE_STRING:
449 CFREE(c->u.String.Value);
450 if (c->u.String.Default != NULL)
451 {
452 CSTRDUP(c->u.String.Value, c->u.String.Default);
453 }
454 break;
455 case CONFIG_TYPE_INT:
456 c->u.Int.Value = c->u.Int.Default;
457 break;
458 case CONFIG_TYPE_FLOAT:
459 c->u.Float.Value = c->u.Float.Default;
460 break;
461 case CONFIG_TYPE_BOOL:
462 c->u.Bool.Value = c->u.Bool.Default;
463 break;
464 case CONFIG_TYPE_ENUM:
465 c->u.Enum.Value = c->u.Enum.Default;
466 break;
467 case CONFIG_TYPE_GROUP:
468 CA_FOREACH(Config, child, c->u.Group)
469 ConfigResetDefault(child);
470 CA_FOREACH_END()
471 break;
472 default:
473 CASSERT(false, "Unknown config type");
474 break;
475 }
476 }
477
ConfigGetString(Config * c,const char * name)478 const char *ConfigGetString(Config *c, const char *name)
479 {
480 c = ConfigGet(c, name);
481 CASSERT(c->Type == CONFIG_TYPE_STRING, "wrong config type");
482 return c->u.String.Value;
483 }
ConfigGetInt(Config * c,const char * name)484 int ConfigGetInt(Config *c, const char *name)
485 {
486 c = ConfigGet(c, name);
487 CASSERT(c->Type == CONFIG_TYPE_INT, "wrong config type");
488 return c->u.Int.Value;
489 }
ConfigGetFloat(Config * c,const char * name)490 double ConfigGetFloat(Config *c, const char *name)
491 {
492 c = ConfigGet(c, name);
493 CASSERT(c->Type == CONFIG_TYPE_FLOAT, "wrong config type");
494 return c->u.Float.Value;
495 }
ConfigGetBool(Config * c,const char * name)496 bool ConfigGetBool(Config *c, const char *name)
497 {
498 c = ConfigGet(c, name);
499 CASSERT(c->Type == CONFIG_TYPE_BOOL, "wrong config type");
500 return c->u.Bool.Value;
501 }
ConfigGetEnum(Config * c,const char * name)502 int ConfigGetEnum(Config *c, const char *name)
503 {
504 c = ConfigGet(c, name);
505 CASSERT(c->Type == CONFIG_TYPE_ENUM, "wrong config type");
506 return c->u.Enum.Value;
507 }
ConfigGetGroup(Config * c,const char * name)508 CArray *ConfigGetGroup(Config *c, const char *name)
509 {
510 c = ConfigGet(c, name);
511 CASSERT(c->Type == CONFIG_TYPE_GROUP, "wrong config type");
512 return &c->u.Group;
513 }
514
ConfigSetInt(Config * c,const char * name,const int value)515 void ConfigSetInt(Config *c, const char *name, const int value)
516 {
517 c = ConfigGet(c, name);
518 CASSERT(c->Type == CONFIG_TYPE_INT, "wrong config type");
519 c->u.Int.Value = CLAMP(value, c->u.Int.Min, c->u.Int.Max);
520 }
521
ConfigSetFloat(Config * c,const char * name,const double value)522 void ConfigSetFloat(Config *c, const char *name, const double value)
523 {
524 c = ConfigGet(c, name);
525 CASSERT(c->Type == CONFIG_TYPE_FLOAT, "wrong config type");
526 c->u.Float.Value = CLAMP(value, c->u.Float.Min, c->u.Float.Max);
527 }
528
ConfigTrySetFromString(Config * c,const char * name,const char * value)529 bool ConfigTrySetFromString(Config *c, const char *name, const char *value)
530 {
531 Config *child = ConfigGet(c, name);
532 switch (child->Type)
533 {
534 case CONFIG_TYPE_STRING:
535 CASSERT(false, "unimplemented");
536 return false;
537 case CONFIG_TYPE_INT:
538 ConfigSetInt(c, name, atoi(value));
539 return true;
540 case CONFIG_TYPE_FLOAT:
541 ConfigSetFloat(c, name, atof(value));
542 return true;
543 case CONFIG_TYPE_BOOL:
544 child->u.Bool.Value = strcmp(value, "true") == 0;
545 return false;
546 case CONFIG_TYPE_ENUM:
547 CASSERT(false, "unimplemented");
548 return false;
549 case CONFIG_TYPE_GROUP:
550 CASSERT(false, "Cannot set group config");
551 return false;
552 default:
553 CASSERT(false, "Unknown config type");
554 return false;
555 }
556 }
557
558
ConfigDefault(void)559 Config ConfigDefault(void)
560 {
561 Config root = ConfigNewGroup(NULL);
562
563 Config game = ConfigNewGroup("Game");
564 ConfigGroupAdd(&game, ConfigNewBool("FriendlyFire", false));
565 ConfigGroupAdd(&game,
566 ConfigNewInt("RandomSeed", 0, 0, INT_MAX, 1, NULL, NULL));
567 ConfigGroupAdd(&game, ConfigNewEnum(
568 "Difficulty", DIFFICULTY_NORMAL,
569 DIFFICULTY_VERYEASY, DIFFICULTY_VERYHARD,
570 StrDifficulty, DifficultyStr));
571 ConfigGroupAdd(&game, ConfigNewInt("FPS", 70, 10, 120, 10, NULL, NULL));
572 ConfigGroupAdd(&game, ConfigNewBool("Superhot(tm)Mode", false));
573 ConfigGroupAdd(&game,
574 ConfigNewInt("EnemyDensity", 100, 25, 200, 25, NULL, PercentStr));
575 ConfigGroupAdd(&game,
576 ConfigNewInt("NonPlayerHP", 100, 25, 200, 25, NULL, PercentStr));
577 ConfigGroupAdd(&game,
578 ConfigNewInt("PlayerHP", 75, 25, 200, 25, NULL, PercentStr));
579 ConfigGroupAdd(&game,
580 ConfigNewInt("Lives", 2, 1, 5, 1, NULL, NULL));
581 ConfigGroupAdd(&game, ConfigNewBool("HealthPickups", true));
582 ConfigGroupAdd(&game, ConfigNewBool("Fog", true));
583 ConfigGroupAdd(&game,
584 ConfigNewInt("SightRange", 15, 8, 40, 1, NULL, NULL));
585 ConfigGroupAdd(&game, ConfigNewEnum(
586 "FireMoveStyle", FIREMOVE_STOP, FIREMOVE_STOP, FIREMOVE_STRAFE,
587 StrFireMoveStyle, FireMoveStyleStr));
588 ConfigGroupAdd(&game, ConfigNewEnum(
589 "SwitchMoveStyle", SWITCHMOVE_SLIDE,
590 SWITCHMOVE_SLIDE, SWITCHMOVE_NONE,
591 StrSwitchMoveStyle, SwitchMoveStyleStr));
592 ConfigGroupAdd(&game, ConfigNewEnum(
593 "AllyCollision", ALLYCOLLISION_REPEL,
594 ALLYCOLLISION_NORMAL, ALLYCOLLISION_NONE,
595 StrAllyCollision, AllyCollisionStr));
596 ConfigGroupAdd(&game, ConfigNewEnum(
597 "LaserSight", LASER_SIGHT_NONE, LASER_SIGHT_NONE, LASER_SIGHT_ALL,
598 StrLaserSight, LaserSightStr));
599 ConfigGroupAdd(&root, game);
600
601 Config dm = ConfigNewGroup("Deathmatch");
602 ConfigGroupAdd(&dm, ConfigNewInt("Lives", 10, 1, 20, 1, NULL, NULL));
603 ConfigGroupAdd(&root, dm);
604
605 Config df = ConfigNewGroup("Dogfight");
606 ConfigGroupAdd(&df,
607 ConfigNewInt("PlayerHP", 100, 25, 200, 25, NULL, PercentStr));
608 ConfigGroupAdd(&df, ConfigNewInt("FirstTo", 5, 1, 10, 1, NULL, NULL));
609 ConfigGroupAdd(&root, df);
610
611 Config gfx = ConfigNewGroup("Graphics");
612 ConfigGroupAdd(&gfx, ConfigNewInt(
613 "Brightness", 0, BLIT_BRIGHTNESS_MIN, BLIT_BRIGHTNESS_MAX, 1,
614 NULL, NULL));
615
616 ConfigGroupAdd(&gfx, ConfigNewBool("Fullscreen",
617 #ifdef __GCWZERO__
618 true
619 #else
620 false
621 #endif
622 ));
623
624 ConfigGroupAdd(&gfx,
625 ConfigNewInt("WindowWidth", 640, 320, 4096, 0, NULL, NULL));
626 ConfigGroupAdd(&gfx,
627 ConfigNewInt("WindowHeight", 480, 200, 2160, 0, NULL, NULL));
628 ConfigGroupAdd(&gfx, ConfigNewInt("ScaleFactor",
629 #ifdef __GCWZERO__
630 1
631 #else
632 2
633 #endif
634 , 1, 16, 1, NULL, NULL));
635 ConfigGroupAdd(&gfx,
636 ConfigNewInt("ShakeMultiplier", 1, 0, 10, 1, NULL, NULL));
637 ConfigGroupAdd(&gfx, ConfigNewBool("ShowHUD", true));
638 ConfigGroupAdd(&gfx, ConfigNewEnum(
639 "ScaleMode", SCALE_MODE_NN, SCALE_MODE_NN, SCALE_MODE_BILINEAR,
640 StrScaleMode, ScaleModeStr));
641 ConfigGroupAdd(&gfx, ConfigNewBool("Shadows", true));
642 ConfigGroupAdd(&gfx, ConfigNewEnum(
643 "Gore", GORE_LOW, GORE_NONE, GORE_HIGH, StrGoreAmount, GoreAmountStr));
644 ConfigGroupAdd(&gfx, ConfigNewBool("Brass", true));
645 ConfigGroupAdd(&gfx, ConfigNewBool("SecondWindow", false));
646 ConfigGroupAdd(&root, gfx);
647
648 Config input = ConfigNewGroup("Input");
649 Config pk0 = ConfigNewGroup("PlayerCodes0");
650 ConfigGroupAdd(&pk0, ConfigNewInt("left", SDL_SCANCODE_LEFT, 0, 0, 0, NULL, NULL));
651 ConfigGroupAdd(&pk0, ConfigNewInt("right", SDL_SCANCODE_RIGHT, 0, 0, 0, NULL, NULL));
652 ConfigGroupAdd(&pk0, ConfigNewInt("up", SDL_SCANCODE_UP, 0, 0, 0, NULL, NULL));
653 ConfigGroupAdd(&pk0, ConfigNewInt("down", SDL_SCANCODE_DOWN, 0, 0, 0, NULL, NULL));
654 #ifdef __GCWZERO__
655 ConfigGroupAdd(&pk0, ConfigNewInt("button1", SDL_SCANCODE_LCTRL, 0, 0, 0, NULL, NULL));
656 ConfigGroupAdd(&pk0, ConfigNewInt("button2", SDL_SCANCODE_LALT, 0, 0, 0, NULL, NULL));
657 ConfigGroupAdd(&pk0, ConfigNewInt("grenade", SDL_SCANCODE_BACKSPACE, 0, 0, 0, NULL, NULL));
658 ConfigGroupAdd(&pk0, ConfigNewInt("map", SDL_SCANCODE_TAB, 0, 0, 0, NULL, NULL));
659 #else
660 ConfigGroupAdd(&pk0, ConfigNewInt("button1", SDL_SCANCODE_X, 0, 0, 0, NULL, NULL));
661 ConfigGroupAdd(&pk0, ConfigNewInt("button2", SDL_SCANCODE_Z, 0, 0, 0, NULL, NULL));
662 ConfigGroupAdd(&pk0, ConfigNewInt("grenade", SDL_SCANCODE_S, 0, 0, 0, NULL, NULL));
663 ConfigGroupAdd(&pk0, ConfigNewInt("map", SDL_SCANCODE_A, 0, 0, 0, NULL, NULL));
664 #endif
665 ConfigGroupAdd(&input, pk0);
666 Config pk1 = ConfigNewGroup("PlayerCodes1");
667 ConfigGroupAdd(&pk1, ConfigNewInt("left", SDL_SCANCODE_KP_4, 0, 0, 0, NULL, NULL));
668 ConfigGroupAdd(&pk1, ConfigNewInt("right", SDL_SCANCODE_KP_6, 0, 0, 0, NULL, NULL));
669 ConfigGroupAdd(&pk1, ConfigNewInt("up", SDL_SCANCODE_KP_8, 0, 0, 0, NULL, NULL));
670 ConfigGroupAdd(&pk1, ConfigNewInt("down", SDL_SCANCODE_KP_2, 0, 0, 0, NULL, NULL));
671 ConfigGroupAdd(&pk1, ConfigNewInt("button1", SDL_SCANCODE_KP_ENTER, 0, 0, 0, NULL, NULL));
672 ConfigGroupAdd(&pk1, ConfigNewInt("button2", SDL_SCANCODE_KP_PERIOD, 0, 0, 0, NULL, NULL));
673 ConfigGroupAdd(&pk1, ConfigNewInt("grenade", SDL_SCANCODE_KP_3, 0, 0, 0, NULL, NULL));
674 ConfigGroupAdd(&pk1, ConfigNewInt("map", SDL_SCANCODE_KP_0, 0, 0, 0, NULL, NULL));
675 ConfigGroupAdd(&input, pk1);
676 ConfigGroupAdd(&root, input);
677
678 Config itf = ConfigNewGroup("Interface");
679 ConfigGroupAdd(&itf, ConfigNewBool("ShowFPS", false));
680 ConfigGroupAdd(&itf, ConfigNewBool("ShowTime", false));
681 ConfigGroupAdd(&itf, ConfigNewBool("ShowHUDMap", true));
682 ConfigGroupAdd(&itf, ConfigNewEnum(
683 "AIChatter", AICHATTER_SELDOM, AICHATTER_NONE, AICHATTER_ALWAYS,
684 StrAIChatter, AIChatterStr));
685 ConfigGroupAdd(&itf, ConfigNewEnum(
686 "Splitscreen", SPLITSCREEN_NEVER,
687 SPLITSCREEN_NORMAL, SPLITSCREEN_NEVER,
688 StrSplitscreenStyle, SplitscreenStyleStr));
689 ConfigGroupAdd(&itf, ConfigNewBool("SplitscreenAI", false));
690 ConfigGroupAdd(&root, itf);
691
692 Config snd = ConfigNewGroup("Sound");
693 ConfigGroupAdd(&snd,
694 ConfigNewInt("MusicVolume", 32, 0, 64, 8, NULL, Div8Str));
695 ConfigGroupAdd(&snd,
696 ConfigNewInt("SoundVolume", 64, 0, 64, 8, NULL, Div8Str));
697 ConfigGroupAdd(&snd, ConfigNewBool("Footsteps", true));
698 ConfigGroupAdd(&snd, ConfigNewBool("Reloads", true));
699 ConfigGroupAdd(&root, snd);
700
701 Config qp = ConfigNewGroup("QuickPlay");
702 ConfigGroupAdd(&qp, ConfigNewEnum(
703 "MapSize", QUICKPLAY_QUANTITY_ANY,
704 QUICKPLAY_QUANTITY_ANY, QUICKPLAY_QUANTITY_LARGE,
705 StrQuickPlayQuantity, QuickPlayQuantityStr));
706 ConfigGroupAdd(&qp, ConfigNewEnum(
707 "WallCount", QUICKPLAY_QUANTITY_ANY,
708 QUICKPLAY_QUANTITY_ANY, QUICKPLAY_QUANTITY_LARGE,
709 StrQuickPlayQuantity, QuickPlayQuantityStr));
710 ConfigGroupAdd(&qp, ConfigNewEnum(
711 "WallLength", QUICKPLAY_QUANTITY_ANY,
712 QUICKPLAY_QUANTITY_ANY, QUICKPLAY_QUANTITY_LARGE,
713 StrQuickPlayQuantity, QuickPlayQuantityStr));
714 ConfigGroupAdd(&qp, ConfigNewEnum(
715 "RoomCount", QUICKPLAY_QUANTITY_ANY,
716 QUICKPLAY_QUANTITY_ANY, QUICKPLAY_QUANTITY_LARGE,
717 StrQuickPlayQuantity, QuickPlayQuantityStr));
718 ConfigGroupAdd(&qp, ConfigNewEnum(
719 "SquareCount", QUICKPLAY_QUANTITY_ANY,
720 QUICKPLAY_QUANTITY_ANY, QUICKPLAY_QUANTITY_LARGE,
721 StrQuickPlayQuantity, QuickPlayQuantityStr));
722 ConfigGroupAdd(&qp, ConfigNewEnum(
723 "EnemyCount", QUICKPLAY_QUANTITY_ANY,
724 QUICKPLAY_QUANTITY_ANY, QUICKPLAY_QUANTITY_LARGE,
725 StrQuickPlayQuantity, QuickPlayQuantityStr));
726 ConfigGroupAdd(&qp, ConfigNewEnum(
727 "EnemySpeed", QUICKPLAY_QUANTITY_ANY,
728 QUICKPLAY_QUANTITY_ANY, QUICKPLAY_QUANTITY_LARGE,
729 StrQuickPlayQuantity, QuickPlayQuantityStr));
730 ConfigGroupAdd(&qp, ConfigNewEnum(
731 "EnemyHealth", QUICKPLAY_QUANTITY_ANY,
732 QUICKPLAY_QUANTITY_ANY, QUICKPLAY_QUANTITY_LARGE,
733 StrQuickPlayQuantity, QuickPlayQuantityStr));
734 ConfigGroupAdd(&qp, ConfigNewBool("EnemiesWithExplosives", true));
735 ConfigGroupAdd(&qp, ConfigNewEnum(
736 "ItemCount", QUICKPLAY_QUANTITY_ANY,
737 QUICKPLAY_QUANTITY_ANY, QUICKPLAY_QUANTITY_LARGE,
738 StrQuickPlayQuantity, QuickPlayQuantityStr));
739 ConfigGroupAdd(&root, qp);
740
741 ConfigGroupAdd(&root, ConfigNewBool("StartServer", false));
742
743 return root;
744 }
745