1 /*
2 * Created by Hassan "Karajorma" Kazmi for the FreeSpace2 Source Code Project.
3 * You may not sell or otherwise commercially exploit the source or things you
4 * create based on the source.
5 *
6 * This file is in charge of the "game_settings.tbl", colloquially referred to
7 * as the "mod table", and contains many misc FSO specific settings.
8 */
9
10 #include "gamesnd/eventmusic.h"
11 #include "def_files/def_files.h"
12 #include "globalincs/version.h"
13 #include "localization/localize.h"
14 #include "mission/missioncampaign.h"
15 #include "mission/missionload.h"
16 #include "mission/missionmessage.h"
17 #include "missionui/fictionviewer.h"
18 #include "mod_table/mod_table.h"
19 #include "parse/parselo.h"
20 #include "sound/sound.h"
21 #include "playerman/player.h"
22
23 int Directive_wait_time;
24 bool True_loop_argument_sexps;
25 bool Fixed_turret_collisions;
26 bool Damage_impacted_subsystem_first;
27 bool Cutscene_camera_displays_hud;
28 bool Alternate_chaining_behavior;
29 int Default_ship_select_effect;
30 int Default_weapon_select_effect;
31 int Default_fiction_viewer_ui;
32 bool Enable_external_shaders;
33 bool Enable_external_default_scripts;
34 int Default_detail_level;
35 bool Full_color_head_anis;
36 bool Weapons_inherit_parent_collision_group;
37 bool Flight_controls_follow_eyepoint_orientation;
38 int FS2NetD_port;
39 float Briefing_window_FOV;
40 bool Disable_hc_message_ani;
41 bool Red_alert_applies_to_delayed_ships;
42 bool Beams_use_damage_factors;
43 float Generic_pain_flash_factor;
44 float Shield_pain_flash_factor;
45 gameversion::version Targetted_version; // Defaults to retail
46 SCP_string Window_title;
47 bool Unicode_text_mode;
48 bool Use_tabled_strings_for_default_language;
49 bool Dont_preempt_training_voice;
50 SCP_string Movie_subtitle_font;
51 bool Enable_scripts_in_fred; // By default FRED does not initialize the scripting system
52 SCP_string Window_icon_path;
53 bool Disable_built_in_translations;
54 bool Weapon_shockwaves_respect_huge;
55 bool Using_in_game_options;
56 float Dinky_shockwave_default_multiplier;
57 bool Shockwaves_always_damage_bombs;
58 bool Shockwaves_damage_all_obj_types_once;
59 std::tuple<ubyte, ubyte, ubyte> Arc_color_damage_p1;
60 std::tuple<ubyte, ubyte, ubyte> Arc_color_damage_p2;
61 std::tuple<ubyte, ubyte, ubyte> Arc_color_damage_s1;
62 std::tuple<ubyte, ubyte, ubyte> Arc_color_emp_p1;
63 std::tuple<ubyte, ubyte, ubyte> Arc_color_emp_p2;
64 std::tuple<ubyte, ubyte, ubyte> Arc_color_emp_s1;
65 bool Use_engine_wash_intensity;
66 bool Framerate_independent_turning; // an in-depth explanation how this flag is supposed to work can be found in #2740 PR description
67 bool Ai_respect_tabled_turntime_rotdamp;
68 bool Swarmers_lead_targets;
69 bool Chase_view_default;
70 SCP_vector<gr_capability> Required_render_ext;
71 float Weapon_SS_Threshold_Turret_Inaccuracy;
72 bool Render_player_mflash;
73 bool Neb_affects_beams;
74 bool Neb_affects_weapons;
75 bool Neb_affects_particles;
76 bool Neb_affects_fireballs;
77 std::tuple<float, float, float, float> Shadow_distances;
78 std::tuple<float, float, float, float> Shadow_distances_cockpit;
79 bool Custom_briefing_icons_always_override_standard_icons;
80
81 SCP_vector<std::pair<SCP_string, gr_capability>> req_render_ext_pairs = {
82 std::make_pair("BPTC Texture Compression", CAPABILITY_BPTC)
83 };
84
parse_mod_table(const char * filename)85 void parse_mod_table(const char *filename)
86 {
87 // SCP_vector<SCP_string> lines;
88
89 try
90 {
91 if (filename == NULL)
92 read_file_text_from_default(defaults_get_file("game_settings.tbl"));
93 else
94 read_file_text(filename, CF_TYPE_TABLES);
95
96 reset_parse();
97
98 // start parsing
99 optional_string("#GAME SETTINGS");
100
101 if (optional_string("$Minimum version:") || optional_string("$Target Version:")) {
102 Targetted_version = gameversion::parse_version();
103
104 mprintf(("Game Settings Table: Parsed target version of %s\n", gameversion::format_version(Targetted_version).c_str()));
105
106 if (!gameversion::check_at_least(Targetted_version)) {
107 Error(LOCATION, "This modification needs at least version %s of FreeSpace Open. However, the current is only %s!",
108 gameversion::format_version(Targetted_version).c_str(),
109 gameversion::format_version(gameversion::get_executable_version()).c_str());
110 }
111 }
112
113 if (optional_string("$Window title:")) {
114 stuff_string(Window_title, F_NAME);
115 }
116
117 if (optional_string("$Window icon:")) {
118 stuff_string(Window_icon_path, F_NAME);
119 }
120
121 if (optional_string("$Unicode mode:")) {
122 stuff_boolean(&Unicode_text_mode);
123
124 mprintf(("Game Settings Table: Unicode mode: %s\n", Unicode_text_mode ? "yes" : "no"));
125 }
126
127 optional_string("#LOCALIZATION SETTINGS");
128
129 if (optional_string("$Use tabled strings for the default language:")) {
130 stuff_boolean(&Use_tabled_strings_for_default_language);
131
132 mprintf(("Game Settings Table: Use tabled strings (translations) for the default language: %s\n", Use_tabled_strings_for_default_language ? "yes" : "no"));
133 }
134
135 if (optional_string("$Don't pre-empt training message voice:")) {
136 stuff_boolean(&Dont_preempt_training_voice);
137
138 mprintf(("Game Settings Table: %sre-empting training message voice\n", Dont_preempt_training_voice ? "Not p" : "P"));
139 }
140
141 optional_string("#CAMPAIGN SETTINGS");
142
143 if (optional_string("$Default Campaign File Name:")) {
144 char temp[MAX_FILENAME_LEN];
145 stuff_string(temp, F_NAME, MAX_FILENAME_LEN);
146
147 // remove extension?
148 if (drop_extension(temp)) {
149 mprintf(("Game Settings Table: Removed extension on default campaign file name %s\n", temp));
150 }
151
152 // check length
153 size_t maxlen = (MAX_FILENAME_LEN - 4);
154 auto len = strlen(temp);
155 if (len > maxlen) {
156 error_display(0, "Token too long: [%s]. Length = " SIZE_T_ARG ". Max is " SIZE_T_ARG ".", temp, len, maxlen);
157 temp[maxlen] = 0;
158 }
159
160 strcpy_s(Default_campaign_file_name, temp);
161 }
162
163 if (optional_string("#Ignored Campaign File Names")) {
164 SCP_string campaign_name;
165
166 while (optional_string("$Campaign File Name:")) {
167 stuff_string(campaign_name, F_NAME);
168
169 // remove extension?
170 if (drop_extension(campaign_name)) {
171 mprintf(("Game Settings Table: Removed extension on ignored campaign file name %s\n", campaign_name.c_str()));
172 }
173
174 // we want case-insensitive matching, so make this lowercase
175 SCP_tolower(campaign_name);
176
177 Ignored_campaigns.push_back(campaign_name);
178 }
179 }
180
181 // Note: this feature does not ignore missions that are contained in campaigns
182 if (optional_string("#Ignored Mission File Names")) {
183 SCP_string mission_name;
184
185 while (optional_string("$Mission File Name:")) {
186 stuff_string(mission_name, F_NAME);
187
188 // remove extension?
189 if (drop_extension(mission_name)) {
190 mprintf(("Game Settings Table: Removed extension on ignored mission file name %s\n", mission_name.c_str()));
191 }
192
193 // we want case-insensitive matching, so make this lowercase
194 SCP_tolower(mission_name);
195
196 Ignored_missions.push_back(mission_name);
197 }
198 }
199
200 if (optional_string("$Red-alert applies to delayed ships:")) {
201 stuff_boolean(&Red_alert_applies_to_delayed_ships);
202 if (Red_alert_applies_to_delayed_ships) {
203 mprintf(("Game Settings Table: Red-alert stats will be loaded for ships that arrive later in missions\n"));
204 }
205 else {
206 mprintf(("Game Settings Table: Red-alert stats will NOT be loaded for ships that arrive later in missions (this is retail behavior)\n"));
207 }
208 }
209
210 optional_string("#HUD SETTINGS");
211
212 // how long should the game wait before displaying a directive?
213 if (optional_string("$Directive Wait Time:")) {
214 stuff_int(&Directive_wait_time);
215 }
216
217 if (optional_string("$Cutscene camera displays HUD:")) {
218 stuff_boolean(&Cutscene_camera_displays_hud);
219 }
220 // compatibility
221 if (optional_string("$Cutscene camera disables HUD:")) {
222 mprintf(("Game Settings Table: \"$$Cutscene camera disables HUD\" is deprecated in favor of \"$Cutscene camera displays HUD\"\n"));
223 bool temp;
224 stuff_boolean(&temp);
225 Cutscene_camera_displays_hud = !temp;
226 }
227
228 if (optional_string("$Full color head animations:")) {
229 stuff_boolean(&Full_color_head_anis);
230 }
231 // compatibility
232 if (optional_string("$Color head animations with hud colors:")) {
233 mprintf(("Game Settings Table: \"$Color head animations with hud colors\" is deprecated in favor of \"$Full color head animations\"\n"));
234 bool temp;
235 stuff_boolean(&temp);
236 Full_color_head_anis = !temp;
237 }
238
239 optional_string("#SEXP SETTINGS");
240
241 if (optional_string("$Loop SEXPs Then Arguments:")) {
242 stuff_boolean(&True_loop_argument_sexps);
243 if (True_loop_argument_sexps) {
244 mprintf(("Game Settings Table: Using Reversed Loops For SEXP Arguments\n"));
245 }
246 else {
247 mprintf(("Game Settings Table: Using Standard Loops For SEXP Arguments\n"));
248 }
249 }
250
251 if (optional_string("$Use Alternate Chaining Behavior:")) {
252 stuff_boolean(&Alternate_chaining_behavior);
253 if (Alternate_chaining_behavior) {
254 mprintf(("Game Settings Table: Using alternate event chaining behavior\n"));
255 }
256 else {
257 mprintf(("Game Settings Table: Using standard event chaining behavior\n"));
258 }
259 }
260
261 optional_string("#GRAPHICS SETTINGS");
262
263 if (optional_string("$Enable External Shaders:")) {
264 stuff_boolean(&Enable_external_shaders);
265 if (Enable_external_shaders) {
266 mprintf(("Game Settings Table: External shaders are enabled\n"));
267 } else {
268 mprintf(("Game Settings Table: External shaders are DISABLED\n"));
269 }
270 }
271
272 if (optional_string("$Default Detail Level:")) {
273 int detail_level;
274
275 stuff_int(&detail_level);
276
277 mprintf(("Game Settings Table: Setting default detail level to %i of %i-%i\n", detail_level, 0, NUM_DEFAULT_DETAIL_LEVELS - 1));
278
279 if (detail_level < 0 || detail_level > NUM_DEFAULT_DETAIL_LEVELS - 1) {
280 error_display(0, "Invalid detail level: %i, setting to %i", detail_level, Default_detail_level);
281 }
282 else {
283 Default_detail_level = detail_level;
284 }
285 }
286
287 if (optional_string("$Briefing Window FOV:")) {
288 float fov;
289
290 stuff_float(&fov);
291
292 mprintf(("Game Settings Table: Setting briefing window FOV from %f to %f\n", Briefing_window_FOV, fov));
293
294 Briefing_window_FOV = fov;
295 }
296
297 if (optional_string("$Generic Pain Flash Factor:")) {
298 stuff_float(&Generic_pain_flash_factor);
299 if (Generic_pain_flash_factor != 1.0f)
300 mprintf(("Game Settings Table: Setting generic pain flash factor to %.2f\n", Generic_pain_flash_factor));
301 }
302
303 if (optional_string("$Shield Pain Flash Factor:")) {
304 stuff_float(&Shield_pain_flash_factor);
305 if (Shield_pain_flash_factor != 0.0f)
306 mprintf(("Game Settings Table: Setting shield pain flash factor to %.2f\n", Shield_pain_flash_factor));
307 }
308
309 if (optional_string("$BMPMAN Slot Limit:")) {
310 int tmp;
311 stuff_int(&tmp);
312
313 mprintf(("Game Settings Table: $BMPMAN Slot Limit is deprecated and should be removed. It is not needed anymore.\n"));
314 }
315
316 if (optional_string("$EMP Arc Color:")) {
317 if (optional_string("+Primary Color Option 1:")) {
318 int rgb[3];
319 stuff_int_list(rgb, 3);
320 if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
321 Arc_color_emp_p1 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
322 } else {
323 error_display(0, "$EMP Arc Color: +Primary Color Option 1 is %i, %i, %i. "
324 "One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
325 }
326 }
327 if (optional_string("+Primary Color Option 2:")) {
328 int rgb[3];
329 stuff_int_list(rgb, 3);
330 if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
331 Arc_color_emp_p2 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
332 } else {
333 error_display(0, "$EMP Arc Color: +Primary Color Option 2 is %i, %i, %i. "
334 "One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
335 }
336 }
337 if (optional_string("+Secondary Color Option 1:")) {
338 int rgb[3];
339 stuff_int_list(rgb, 3);
340 if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
341 Arc_color_emp_s1 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
342 } else {
343 error_display(0,"$EMP Arc Color: +Secondary Color Option 1 is %i, %i, %i. "
344 "One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
345 }
346 }
347 }
348
349 if (optional_string("$Damage Arc Color:")) {
350 if (optional_string("+Primary Color Option 1:")) {
351 int rgb[3];
352 stuff_int_list(rgb, 3);
353 if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
354 Arc_color_damage_p1 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
355 } else {
356 error_display(0, "Damage Arc Color: +Primary Color Option 1 is %i, %i, %i. "
357 "One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
358 }
359 }
360 if (optional_string("+Primary Color Option 2:")) {
361 int rgb[3];
362 stuff_int_list(rgb, 3);
363 if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
364 Arc_color_damage_p2 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
365 } else {
366 error_display(0, "$Damage Arc Color: +Primary Color Option 2 is %i, %i, %i. "
367 "One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
368 }
369 }
370 if (optional_string("+Secondary Color Option 1:")) {
371 int rgb[3];
372 stuff_int_list(rgb, 3);
373 if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
374 Arc_color_damage_s1 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
375 } else {
376 error_display(0, "$Damage Arc Color: +Secondary Color Option 1 is %i, %i, %i. "
377 "One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
378 }
379 }
380 }
381
382 if (optional_string("$Requires Rendering Feature:")) {
383 SCP_vector<SCP_string> ext_strings;
384 stuff_string_list(ext_strings);
385
386 for (auto& ext_str : ext_strings) {
387 auto ext = std::find_if(req_render_ext_pairs.begin(), req_render_ext_pairs.end(),
388 [ext_str](const std::pair<SCP_string, gr_capability> &ext_pair) { return !stricmp(ext_pair.first.c_str(), ext_str.c_str()); });
389 if (ext != req_render_ext_pairs.end()) {
390 Required_render_ext.push_back(ext->second);
391 }
392 }
393 }
394
395 if (optional_string("$Render player muzzle flashes in cockpit:")) {
396 stuff_boolean(&Render_player_mflash);
397 }
398
399 if (optional_string("$Beams affected by nebula visibility:")) {
400 stuff_boolean(&Neb_affects_beams);
401 }
402
403 if (optional_string("$Weapons affected by nebula visibility:")) {
404 stuff_boolean(&Neb_affects_weapons);
405 }
406
407 if (optional_string("$Particles affected by nebula visibility:")) {
408 stuff_boolean(&Neb_affects_particles);
409 }
410
411 if (optional_string("$Fireballs affected by nebula visibility:")) {
412 stuff_boolean(&Neb_affects_fireballs);
413 }
414
415 if (optional_string("$Shadow Cascade Distances:")) {
416 float dis[4];
417 stuff_float_list(dis, 4);
418 if ((dis[0] >= 0) && (dis[1] > dis[0]) && (dis[2] > dis[1]) && (dis[3] > dis[2])) {
419 Shadow_distances = std::make_tuple((dis[0]), (dis[1]), (dis[2]), (dis[3]));
420 } else {
421 error_display(0, "$Shadow Cascade Distances are %f, %f, %f, %f. One or more are < 0, and/or values are not increasing. Assuming default distances.", dis[0], dis[1], dis[2], dis[3]);
422 }
423 }
424
425 if (optional_string("$Shadow Cascade Distances Cockpit:")) {
426 float dis[4];
427 stuff_float_list(dis, 4);
428 if ((dis[0] >= 0) && (dis[1] > dis[0]) && (dis[2] > dis[1]) && (dis[3] > dis[2])) {
429 Shadow_distances_cockpit = std::make_tuple((dis[0]), (dis[1]), (dis[2]), (dis[3]));
430 }
431 else {
432 error_display(0, "$Shadow Cascade Distances Cockpit are %f, %f, %f, %f. One or more are < 0, and/or values are not increasing. Assuming default distances.", dis[0], dis[1], dis[2], dis[3]);
433 }
434 }
435
436 optional_string("#NETWORK SETTINGS");
437
438 if (optional_string("$FS2NetD port:")) {
439 stuff_int(&FS2NetD_port);
440 if (FS2NetD_port)
441 mprintf(("Game Settings Table: FS2NetD connecting to port %i\n", FS2NetD_port));
442 }
443
444 optional_string("#SOUND SETTINGS");
445
446 if (optional_string("$Default Sound Volume:")) {
447 stuff_float(&Master_sound_volume);
448 }
449
450 if (optional_string("$Default Music Volume:")) {
451 stuff_float(&Master_event_music_volume);
452 }
453
454 if (optional_string("$Default Voice Volume:")) {
455 stuff_float(&Master_voice_volume);
456 }
457
458 optional_string("#FRED SETTINGS");
459
460 if (optional_string("$Disable Hard Coded Message Head Ani Files:")) {
461 stuff_boolean(&Disable_hc_message_ani);
462 if (Disable_hc_message_ani) {
463 mprintf(("Game Settings Table: FRED - Disabling Hard Coded Message Ani Files\n"));
464 }
465 else {
466 mprintf(("Game Settings Table: FRED - Using Hard Coded Message Ani Files\n"));
467
468 }
469 }
470
471 if (optional_string("$Enable scripting in FRED:")) {
472 stuff_boolean(&Enable_scripts_in_fred);
473 if (Enable_scripts_in_fred) {
474 mprintf(("Game Settings Table: FRED - Scripts will be executed when running FRED.\n"));
475 }
476 else {
477 mprintf(("Game Settings Table: FRED - Scripts will not be executed when running FRED.\n"));
478 }
479 }
480
481 optional_string("#OTHER SETTINGS");
482
483 if (optional_string("$Fixed Turret Collisions:")) {
484 stuff_boolean(&Fixed_turret_collisions);
485 }
486
487 if (optional_string("$Damage Impacted Subsystem First:")) {
488 stuff_boolean(&Damage_impacted_subsystem_first);
489 }
490
491 if (optional_string("$Default ship select effect:")) {
492 char effect[NAME_LENGTH];
493 stuff_string(effect, F_NAME, NAME_LENGTH);
494 if (!stricmp(effect, "FS2"))
495 Default_ship_select_effect = 2;
496 else if (!stricmp(effect, "FS1"))
497 Default_ship_select_effect = 1;
498 else if (!stricmp(effect, "off"))
499 Default_ship_select_effect = 0;
500 }
501
502 if (optional_string("$Default weapon select effect:")) {
503 char effect[NAME_LENGTH];
504 stuff_string(effect, F_NAME, NAME_LENGTH);
505 if (!stricmp(effect, "FS2"))
506 Default_weapon_select_effect = 2;
507 else if (!stricmp(effect, "FS1"))
508 Default_weapon_select_effect = 1;
509 else if (!stricmp(effect, "off"))
510 Default_weapon_select_effect = 0;
511 }
512
513 if (optional_string("$Weapons inherit parent collision group:")) {
514 stuff_boolean(&Weapons_inherit_parent_collision_group);
515 if (Weapons_inherit_parent_collision_group)
516 mprintf(("Game Settings Table: Weapons inherit parent collision group\n"));
517 }
518
519 if (optional_string("$Flight controls follow eyepoint orientation:")) {
520 stuff_boolean(&Flight_controls_follow_eyepoint_orientation);
521 if (Flight_controls_follow_eyepoint_orientation)
522 mprintf(("Game Settings Table: Flight controls follow eyepoint orientation\n"));
523 }
524
525 if (optional_string("$Beams Use Damage Factors:")) {
526 stuff_boolean(&Beams_use_damage_factors);
527 if (Beams_use_damage_factors) {
528 mprintf(("Game Settings Table: Beams will use Damage Factors\n"));
529 }
530 else {
531 mprintf(("Game Settings Table: Beams will ignore Damage Factors (retail behavior)\n"));
532 }
533 }
534
535 if (optional_string("$Default fiction viewer UI:")) {
536 char ui_name[NAME_LENGTH];
537 stuff_string(ui_name, F_NAME, NAME_LENGTH);
538 if (!stricmp(ui_name, "auto"))
539 Default_fiction_viewer_ui = -1;
540 else {
541 int ui_index = fiction_viewer_ui_name_to_index(ui_name);
542 if (ui_index >= 0)
543 Default_fiction_viewer_ui = ui_index;
544 else
545 error_display(0, "Unrecognized fiction viewer UI: %s", ui_name);
546 }
547 }
548
549 if (optional_string("$Movie subtitle font:")) {
550 // Fonts have not been parsed at this point so we can't validate the font name here
551 stuff_string(Movie_subtitle_font, F_NAME);
552 }
553
554 if (optional_string("$Disable built-in translations:")) {
555 stuff_boolean(&Disable_built_in_translations);
556 }
557
558 if (optional_string("$Weapon shockwave damage respects huge ship flags:")) {
559 stuff_boolean(&Weapon_shockwaves_respect_huge);
560 }
561
562 if (optional_string("$Enable external default scripts:")) {
563 stuff_boolean(&Enable_external_default_scripts);
564
565 if (Enable_external_default_scripts) {
566 mprintf(("Game Settings Table: Enabled external default scripts.\n"));
567 } else {
568 mprintf(("Game Settings Table: Disabled external default scripts.\n"));
569 }
570 }
571
572 if (optional_string("$Player warpout speed:")) {
573 stuff_float(&Player_warpout_speed);
574 }
575
576 if (optional_string("$Target warpout match percent:")) {
577 stuff_float(&Target_warpout_match_percent);
578 }
579
580 if (optional_string("$Minimum player warpout time:")) {
581 stuff_float(&Minimum_player_warpout_time);
582 }
583
584 if (optional_string("$Enable in-game options:")) {
585 stuff_boolean(&Using_in_game_options);
586
587 if (Using_in_game_options) {
588 mprintf(("Game Settings Table: Using in-game options system.\n"));
589 } else {
590 mprintf(("Game Settings Table: Not using in-game options system.\n"));
591 }
592 }
593
594 if (optional_string("$Dinky Shockwave Default Multiplier:")) {
595 stuff_float(&Dinky_shockwave_default_multiplier);
596 if (Dinky_shockwave_default_multiplier != 1.0f) {
597 mprintf(("Game Settings Table: Setting default dinky shockwave multiplier to %.2f.\n", Dinky_shockwave_default_multiplier));
598 }
599 }
600
601 if (optional_string("$Shockwaves Always Damage Bombs:")) {
602 stuff_boolean(&Shockwaves_always_damage_bombs);
603 }
604
605 if (optional_string("$Shockwaves Damage All Object Types Once:")) {
606 stuff_boolean(&Shockwaves_damage_all_obj_types_once);
607 }
608
609 if (optional_string("$Use Engine Wash Intensity:")) {
610 stuff_boolean(&Use_engine_wash_intensity);
611 }
612
613 if (optional_string("$Swarmers Lead Targets:")) {
614 stuff_boolean(&Swarmers_lead_targets);
615 }
616
617 if (optional_string("$Damage Threshold for Weapons Subsystems to Trigger Turret Inaccuracy:")) {
618 float weapon_ss_threshold;
619 stuff_float(&weapon_ss_threshold);
620 if ( (weapon_ss_threshold >= 0.0f) && (weapon_ss_threshold <= 1.0f) ) {
621 Weapon_SS_Threshold_Turret_Inaccuracy = weapon_ss_threshold;
622 } else {
623 mprintf(("Game Settings Table: '$Damage Threshold for Weapons Subsystems to Trigger Turret Inaccuracy:' value of %.2f is not between 0 and 1. Using default value of 0.70.\n", weapon_ss_threshold));
624 }
625 }
626
627 if (optional_string("$AI use framerate independent turning:")) {
628 stuff_boolean(&Framerate_independent_turning);
629 }
630
631 if (optional_string("+AI respect tabled turn time and rotdamp:")) {
632 stuff_boolean(&Ai_respect_tabled_turntime_rotdamp);
633 if (!Framerate_independent_turning) {
634 Warning(LOCATION, "\'AI respect tabled turn time and rotdamp\' requires \'AI use framerate independent turning\' in order to function.\n");
635 }
636 }
637
638 if (optional_string("$Player starts in third person/chase view by default:")) {
639 stuff_boolean(&Chase_view_default);
640 }
641
642 if (optional_string("$Custom briefing icons always override standard icons:")) {
643 stuff_boolean(&Custom_briefing_icons_always_override_standard_icons);
644 }
645
646 required_string("#END");
647 }
648 catch (const parse::ParseException& e)
649 {
650 mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", (filename) ? filename : "<default game_settings.tbl>", e.what()));
651 return;
652 }
653 }
654
mod_table_init()655 void mod_table_init()
656 {
657 mod_table_reset();
658
659 // first parse the default table
660 parse_mod_table(NULL);
661
662 // if a mod.tbl exists read it
663 if (cf_exists_full("game_settings.tbl", CF_TYPE_TABLES)) {
664 parse_mod_table("game_settings.tbl");
665 }
666
667 // parse any modular tables
668 parse_modular_table("*-mod.tbm", parse_mod_table);
669 }
670
mod_supports_version(int major,int minor,int build)671 bool mod_supports_version(int major, int minor, int build)
672 {
673 return Targetted_version >= gameversion::version(major, minor, build, 0);
674 }
675
mod_table_reset()676 void mod_table_reset()
677 {
678 Directive_wait_time = 3000;
679 True_loop_argument_sexps = false;
680 Fixed_turret_collisions = false;
681 Damage_impacted_subsystem_first = false;
682 Cutscene_camera_displays_hud = false;
683 Alternate_chaining_behavior = false;
684 Default_ship_select_effect = 2;
685 Default_weapon_select_effect = 2;
686 Default_fiction_viewer_ui = -1;
687 Enable_external_shaders = false;
688 Enable_external_default_scripts = false;
689 Default_detail_level = 3; // "very high" seems a reasonable default in 2012 -zookeeper
690 Full_color_head_anis = false;
691 Weapons_inherit_parent_collision_group = false;
692 Flight_controls_follow_eyepoint_orientation = false;
693 FS2NetD_port = 0;
694 Briefing_window_FOV = 0.29375f;
695 Disable_hc_message_ani = false;
696 Red_alert_applies_to_delayed_ships = false;
697 Beams_use_damage_factors = false;
698 Generic_pain_flash_factor = 1.0f;
699 Shield_pain_flash_factor = 0.0f;
700 Targetted_version = gameversion::version(2, 0, 0, 0); // Defaults to retail
701 Window_title = "";
702 Unicode_text_mode = false;
703 Use_tabled_strings_for_default_language = false;
704 Dont_preempt_training_voice = false;
705 Movie_subtitle_font = "font01.vf";
706 Enable_scripts_in_fred = false;
707 Window_icon_path = "app_icon_sse";
708 Disable_built_in_translations = false;
709 Weapon_shockwaves_respect_huge = false;
710 Using_in_game_options = false;
711 Dinky_shockwave_default_multiplier = 1.0f;
712 Shockwaves_always_damage_bombs = false;
713 Shockwaves_damage_all_obj_types_once = false;
714 Arc_color_damage_p1 = std::make_tuple(static_cast<ubyte>(64), static_cast<ubyte>(64), static_cast<ubyte>(225));
715 Arc_color_damage_p2 = std::make_tuple(static_cast<ubyte>(128), static_cast<ubyte>(128), static_cast<ubyte>(255));
716 Arc_color_damage_s1 = std::make_tuple(static_cast<ubyte>(200), static_cast<ubyte>(200), static_cast<ubyte>(255));
717 Arc_color_emp_p1 = std::make_tuple(static_cast<ubyte>(64), static_cast<ubyte>(64), static_cast<ubyte>(5));
718 Arc_color_emp_p2 = std::make_tuple(static_cast<ubyte>(128), static_cast<ubyte>(128), static_cast<ubyte>(10));
719 Arc_color_emp_s1 = std::make_tuple(static_cast<ubyte>(255), static_cast<ubyte>(255), static_cast<ubyte>(10));
720 Use_engine_wash_intensity = false;
721 Framerate_independent_turning = true;
722 Ai_respect_tabled_turntime_rotdamp = false;
723 Chase_view_default = false;
724 Swarmers_lead_targets = false;
725 Required_render_ext.clear();
726 Weapon_SS_Threshold_Turret_Inaccuracy = 0.7f; // Defaults to retail value of 0.7 --wookieejedi
727 Render_player_mflash = false;
728 Neb_affects_beams = false;
729 Neb_affects_weapons = false;
730 Neb_affects_particles = false;
731 Neb_affects_fireballs = false;
732 Shadow_distances = std::make_tuple(200.0f, 600.0f, 2500.0f, 8000.0f); // Default values tuned by Swifty and added here by wookieejedi
733 Shadow_distances_cockpit = std::make_tuple(0.25f, 0.75f, 1.5f, 3.0f); // Default values tuned by wookieejedi and added here by Lafiel
734 Custom_briefing_icons_always_override_standard_icons = false;
735 }
736