1 /*
2  * Created by WMCoolmon 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 
7 
8 
9 #include <cstddef>
10 
11 #include "cmdline/cmdline.h"
12 #include "graphics/font.h" //for gr_force_fit_string
13 #include "hud/hud.h"
14 #include "hud/hudbrackets.h"
15 #include "hud/hudconfig.h" // for retrieving user's hud config
16 #include "hud/hudescort.h"
17 #include "hud/hudets.h"
18 #include "hud/hudlock.h"
19 #include "hud/hudmessage.h"
20 #include "hud/hudparse.h" //Duh.
21 #include "hud/hudreticle.h"
22 #include "hud/hudscripting.h"
23 #include "hud/hudshield.h"
24 #include "hud/hudsquadmsg.h"
25 #include "hud/hudtarget.h"
26 #include "hud/hudtargetbox.h"
27 #include "hud/hudwingmanstatus.h"
28 #include "localization/localize.h"
29 #include "mission/missionmessage.h"
30 #include "mission/missiontraining.h"
31 #include "parse/parselo.h"
32 #include "radar/radar.h"
33 #include "radar/radardradis.h"
34 #include "radar/radarngon.h"
35 #include "radar/radarorb.h"
36 #include "radar/radarsetup.h"
37 #include "ship/ship.h" //for ship struct
38 
39 //Global stuffs
40 extern bool Ships_inited; //Need this
41 
42 float Hud_unit_multiplier = 1.0f;	//Backslash
43 float Hud_speed_multiplier = 1.0f;	//The E
44 
45 // Goober5000
46 int Hud_reticle_style = HUD_RETICLE_STYLE_FS2;
47 
48 bool Hud_retail = true;
49 bool Scale_retail_gauges = true;
50 int Force_scaling_above_res_global[2] = {-1, -1};
51 
52 int Hud_font = -1;
53 
54 bool Chase_view_only_ex = false;
55 
56 //WARNING: If you add gauges to this array, make sure to bump Num_builtin_gauges!
57 const int Num_builtin_gauges = 42;
58 static int Builtin_gauges[Num_builtin_gauges] = {
59 	HUD_OBJECT_MESSAGES,
60 	HUD_OBJECT_TRAINING_MESSAGES,
61 	HUD_OBJECT_SUPPORT,
62 	HUD_OBJECT_DAMAGE,
63 	HUD_OBJECT_WINGMAN_STATUS,
64 	HUD_OBJECT_AUTO_SPEED,
65 	HUD_OBJECT_AUTO_TARGET,
66 	HUD_OBJECT_CMEASURES,
67 	HUD_OBJECT_TALKING_HEAD,
68 	HUD_OBJECT_DIRECTIVES,
69 	HUD_OBJECT_WEAPONS,
70 	HUD_OBJECT_OBJ_NOTIFY,
71 	HUD_OBJECT_SQUAD_MSG,
72 	HUD_OBJECT_LAG,
73 	HUD_OBJECT_MINI_SHIELD,
74 	HUD_OBJECT_PLAYER_SHIELD,
75 	HUD_OBJECT_TARGET_SHIELD,
76 	HUD_OBJECT_ESCORT,
77 	HUD_OBJECT_MISSION_TIME,
78 	HUD_OBJECT_TARGET_MONITOR,
79 	HUD_OBJECT_EXTRA_TARGET_DATA,
80 	HUD_OBJECT_AFTERBURNER,
81 	HUD_OBJECT_WEAPON_ENERGY,
82 	HUD_OBJECT_TEXT_WARNINGS,
83 	HUD_OBJECT_CENTER_RETICLE,
84 	HUD_OBJECT_THROTTLE,
85 	HUD_OBJECT_THREAT,
86 	HUD_OBJECT_LEAD,
87 	HUD_OBJECT_LOCK,
88 	HUD_OBJECT_MULTI_MSG,
89 	HUD_OBJECT_VOICE_STATUS,
90 	HUD_OBJECT_PING,
91 	HUD_OBJECT_SUPERNOVA,
92 	HUD_OBJECT_OFFSCREEN,
93 	HUD_OBJECT_BRACKETS,
94 	HUD_OBJECT_ORIENTATION_TEE,
95 	HUD_OBJECT_HOSTILE_TRI,
96 	HUD_OBJECT_TARGET_TRI,
97 	HUD_OBJECT_MISSILE_TRI,
98 	HUD_OBJECT_KILLS,
99 	HUD_OBJECT_FIXED_MESSAGES,
100 	HUD_OBJECT_ETS_RETAIL
101 };
102 
103 Legacy_HUD_gauge_pair Legacy_HUD_gauges[NUM_HUD_GAUGES] =
104 {
105 	{ "LEAD_INDICATOR", HUD_OBJECT_LEAD },
106 	{ "ORIENTATION_TEE", HUD_OBJECT_ORIENTATION_TEE },
107 	{ "HOSTILE_TRIANGLE", HUD_OBJECT_HOSTILE_TRI },
108 	{ "TARGET_TRIANGLE", HUD_OBJECT_TARGET_TRI },
109 	{ "MISSION_TIME", HUD_OBJECT_MISSION_TIME },
110 	{ "RETICLE_CIRCLE", -1 },
111 	{ "THROTTLE_GAUGE", HUD_OBJECT_THROTTLE },
112 	{ "RADAR", HUD_OBJECT_RADAR_STD },
113 	{ "TARGET_MONITOR", HUD_OBJECT_TARGET_MONITOR },
114 	{ "CENTER_RETICLE", HUD_OBJECT_CENTER_RETICLE },
115 	{ "TARGET_MONITOR_EXTRA_DATA", HUD_OBJECT_EXTRA_TARGET_DATA },
116 	{ "TARGET_SHIELD_ICON", HUD_OBJECT_TARGET_SHIELD },
117 	{ "PLAYER_SHIELD_ICON", HUD_OBJECT_PLAYER_SHIELD },
118 	{ "ETS_GAUGE", HUD_OBJECT_ETS_RETAIL },
119 	{ "AUTO_TARGET", HUD_OBJECT_AUTO_TARGET },
120 	{ "AUTO_SPEED", HUD_OBJECT_AUTO_SPEED },
121 	{ "WEAPONS_GAUGE", HUD_OBJECT_WEAPONS },
122 	{ "ESCORT_VIEW", HUD_OBJECT_ESCORT },
123 	{ "DIRECTIVES_VIEW", HUD_OBJECT_DIRECTIVES },
124 	{ "THREAT_GAUGE", HUD_OBJECT_THREAT },
125 	{ "AFTERBURNER_ENERGY", HUD_OBJECT_AFTERBURNER },
126 	{ "WEAPONS_ENERGY", HUD_OBJECT_WEAPON_ENERGY },
127 	{ "WEAPON_LINKING_GAUGE", HUD_OBJECT_WEAPON_LINKING },
128 	{ "TARGER_MINI_ICON", HUD_OBJECT_MINI_SHIELD },
129 	{ "OFFSCREEN_INDICATOR", HUD_OBJECT_OFFSCREEN },
130 	{ "TALKING_HEAD", HUD_OBJECT_TALKING_HEAD },
131 	{ "DAMAGE_GAUGE", HUD_OBJECT_DAMAGE },
132 	{ "MESSAGE_LINES", HUD_OBJECT_MESSAGES },
133 	{ "MISSILE_WARNING_ARROW", HUD_OBJECT_MISSILE_TRI },
134 	{ "CMEASURE_GAUGE", HUD_OBJECT_CMEASURES },
135 	{ "OBJECTIVES_NOTIFY_GAUGE", HUD_OBJECT_OBJ_NOTIFY },
136 	{ "WINGMEN_STATUS", HUD_OBJECT_WINGMAN_STATUS },
137 	{ "OFFSCREEN RANGE", -1 },
138 	{ "KILLS GAUGE", HUD_OBJECT_KILLS },
139 	{ "ATTACKING TARGET COUNT", -1 },
140 	{ "TEXT FLASH", HUD_OBJECT_TEXT_WARNINGS },
141 	{ "MESSAGE BOX", HUD_OBJECT_SQUAD_MSG },
142 	{ "SUPPORT GUAGE", HUD_OBJECT_SUPPORT },
143 	{ "LAG GUAGE", HUD_OBJECT_LAG },
144 };
145 
146 flag_def_list Hud_gauge_types[] = {
147 	{ "Messages",			HUD_OBJECT_MESSAGES,			0},
148 	{ "Training messages",	HUD_OBJECT_TRAINING_MESSAGES,	0},		// Not in legacy list
149 	{ "Support",			HUD_OBJECT_SUPPORT,				0},
150 	{ "Damage",				HUD_OBJECT_DAMAGE,				0},
151 	{ "Wingman status",		HUD_OBJECT_WINGMAN_STATUS,		0},
152 	{ "Auto speed",			HUD_OBJECT_AUTO_SPEED,			0},
153 	{ "Auto target",		HUD_OBJECT_AUTO_TARGET,			0},
154 	{ "Countermeasures",	HUD_OBJECT_CMEASURES,			0},
155 	{ "Talking head",		HUD_OBJECT_TALKING_HEAD,		0},
156 	{ "Directives",			HUD_OBJECT_DIRECTIVES,			0},
157 	{ "Weapons",			HUD_OBJECT_WEAPONS,				0},
158 	{ "Objective notifier",	HUD_OBJECT_OBJ_NOTIFY,			0},
159 	{ "Comm menu",			HUD_OBJECT_SQUAD_MSG,			0},
160 	{ "Lag indicator",		HUD_OBJECT_LAG,					0},
161 	{ "Mini shield",		HUD_OBJECT_MINI_SHIELD,			0},
162 	{ "Player shield",		HUD_OBJECT_PLAYER_SHIELD,		0},
163 	{ "Target shield",		HUD_OBJECT_TARGET_SHIELD,		0},
164 	{ "Escort list",		HUD_OBJECT_ESCORT,				0},
165 	{ "Mission time",		HUD_OBJECT_MISSION_TIME,		0},
166 	{ "Ets weapons",		HUD_OBJECT_ETS_WEAPONS,			0},		// Not in legacy list
167 	{ "Ets shields",		HUD_OBJECT_ETS_SHIELDS,			0},		// Not in legacy list
168 	{ "Ets engines",		HUD_OBJECT_ETS_ENGINES,			0},		// Not in legacy list
169 	{ "Target monitor",		HUD_OBJECT_TARGET_MONITOR,		0},
170 	{ "Extra target data",	HUD_OBJECT_EXTRA_TARGET_DATA,	0},
171 	{ "Radar",				HUD_OBJECT_RADAR_STD,			0},
172 	{ "Radar orb",			HUD_OBJECT_RADAR_ORB,			0},		// Not in legacy list
173 	{ "Radar BSG",			HUD_OBJECT_RADAR_BSG,			0},		// Not in legacy list
174 	{ "Afterburner energy",	HUD_OBJECT_AFTERBURNER,			0},
175 	{ "Weapon energy",		HUD_OBJECT_WEAPON_ENERGY,		0},
176 	{ "Text warnings",		HUD_OBJECT_TEXT_WARNINGS,		0},
177 	{ "Center reticle",		HUD_OBJECT_CENTER_RETICLE,		0},
178 	{ "Throttle",			HUD_OBJECT_THROTTLE,			0},
179 	{ "Threat indicator",	HUD_OBJECT_THREAT,				0},
180 	{ "Lead indicator",		HUD_OBJECT_LEAD,				0},
181 	{ "Lead sight",			HUD_OBJECT_LEAD_SIGHT,			0},
182 	{ "Lock indicator",		HUD_OBJECT_LOCK,				0},		// Not in legacy list
183 	{ "Weapon linking",		HUD_OBJECT_WEAPON_LINKING,		0},
184 	{ "Multiplayer messages",	HUD_OBJECT_MULTI_MSG,			0},	// Not in legacy list
185 	{ "Voice status",		HUD_OBJECT_VOICE_STATUS,		0},		// Not in legacy list
186 	{ "Ping",				HUD_OBJECT_PING,				0},		// Not in legacy list
187 	{ "Supernova",			HUD_OBJECT_SUPERNOVA,			0},		// Not in legacy list
188 	{ "Offscreen indicator",	HUD_OBJECT_OFFSCREEN,			0},
189 	{ "Targeting brackets",	HUD_OBJECT_BRACKETS,			0},
190 	{ "Orientation",		HUD_OBJECT_ORIENTATION_TEE,		0},
191 	{ "Hostile direction",	HUD_OBJECT_HOSTILE_TRI,			0},
192 	{ "Target direction",	HUD_OBJECT_TARGET_TRI,			0},
193 	{ "Missile indicator",	HUD_OBJECT_MISSILE_TRI,			0},
194 	{ "Kills",				HUD_OBJECT_KILLS,				0},
195 	{ "Fixed messages",		HUD_OBJECT_FIXED_MESSAGES,		0},		// Not in legacy list
196 	{ "Ets retail",			HUD_OBJECT_ETS_RETAIL,			0}
197 };
198 int Num_hud_gauge_types = sizeof(Hud_gauge_types)/sizeof(flag_def_list);
199 
parse_ship_start()200 int parse_ship_start()
201 {
202 	char shipname[NAME_LENGTH];
203 	int ship_index;
204 
205 	stuff_string(shipname, F_NAME, NAME_LENGTH);
206 	ship_index = ship_info_lookup(shipname);
207 
208 	return ship_index;
209 }
210 
parse_hud_gauges_tbl(const char * filename)211 void parse_hud_gauges_tbl(const char *filename)
212 {
213 	int i;
214 	char *saved_Mp = NULL;
215 
216 	int colors[3] = {255, 255, 255};
217 	color hud_color;
218 	color ship_color;
219 	color *hud_clr_p = NULL;
220 	color *ship_clr_p = NULL;
221 	bool scale_gauge = true;
222 	bool chase_view_only = false;
223 
224 	try
225 	{
226 		read_file_text(filename, CF_TYPE_TABLES);
227 		reset_parse();
228 
229 		if (optional_string("$Load Retail Configuration:")) {
230 			stuff_boolean(&Hud_retail);
231 		}
232 
233 		if (optional_string("$Color:")) {
234 			stuff_int_list(colors, 3);
235 
236 			check_color(colors);
237 			gr_init_alphacolor(&hud_color, colors[0], colors[1], colors[2], 255);
238 			hud_clr_p = &hud_color;
239 		}
240 
241 		if (optional_string("$Font:")) {
242 			Hud_font = font::parse_font();
243 		}
244 
245 		if (optional_string("$Chase View Only:")) {
246 			stuff_boolean(&chase_view_only);
247 			Chase_view_only_ex = chase_view_only;
248 		}
249 
250 		if(optional_string("$Max Directives:")) {
251 			stuff_int(&Max_directives);
252 		}
253 
254 		if (optional_string("$Max Escort Ships:")) {
255 			stuff_int(&Max_escort_ships);
256 		}
257 
258 		if (optional_string("$Length Unit Multiplier:"))	{
259 			stuff_float(&Hud_unit_multiplier);
260 
261 			if (Hud_unit_multiplier <= 0.0f) {
262 				Warning(LOCATION, "\"$Length Unit Multiplier:\" value of \"%f\" is invalid!  Resetting to default.", Hud_unit_multiplier);
263 				Hud_unit_multiplier = 1.0f;
264 			}
265 		}
266 
267 		if (optional_string("$Speed Unit Multiplier:")) {
268 			stuff_float(&Hud_speed_multiplier);
269 
270 			if (Hud_speed_multiplier <= 0.0f) {
271 				Warning(LOCATION, "\"$Speed Unit Multiplier:\" value of \"%f\" is invalid!  Resetting to default.", Hud_speed_multiplier);
272 				Hud_speed_multiplier = 1.0f;
273 			}
274 		}
275 		else {
276 			Hud_speed_multiplier = Hud_unit_multiplier;
277 		}
278 
279 		if (optional_string("$Wireframe Targetbox:")) {
280 			stuff_int(&Targetbox_wire);
281 			if ((Targetbox_wire < 0) || (Targetbox_wire > 3)) {
282 				Targetbox_wire = 0;
283 			}
284 		}
285 
286 		if (optional_string("$Targetbox Shader Effect:")) {
287 			stuff_int(&Targetbox_shader_effect);
288 			if (Targetbox_shader_effect < 0) {
289 				Targetbox_shader_effect = 0;
290 			}
291 		}
292 
293 		if (optional_string("$Lock Wireframe Mode:")) {
294 			stuff_boolean(&Lock_targetbox_mode);
295 		}
296 
297 		if (optional_string("$Scale Gauges:")) {
298 			stuff_boolean(&scale_gauge);
299 			Scale_retail_gauges = scale_gauge;
300 		}
301 
302 		if (optional_string("$Force Scaling Above:")) {
303 			stuff_int_list(Force_scaling_above_res_global, 2);
304 		}
305 
306 		if (optional_string("$Reticle Style:")) {
307 			int temp = required_string_either("FS1", "FS2");
308 
309 			// using require_string_either won't advance the Mp pointer to the next token so force it instead
310 			skip_to_start_of_string("#Gauge Config");
311 
312 			if (temp < 0)
313 				Warning(LOCATION, "Undefined reticle style in hud_gauges.tbl!");
314 			else
315 				Hud_reticle_style = temp;
316 		}
317 
318 		int base_res[2];
319 		int force_scaling_above_res[2];
320 		int ship_idx = -1;
321 		int ship_font = -1;
322 		int gauge_type = -1;
323 		int use_font = -1;
324 		color *use_clr_p = NULL;
325 		SCP_vector<int> ship_classes;
326 		bool retail_config = false;
327 		int n_ships = 0;
328 
329 		while (optional_string("#Gauge Config")) {
330 			ship_classes.clear();
331 			switch (optional_string_either("$Ship:", "$Ships:")) {
332 			case 0:
333 				mprintf(("$Ship in hud_gauges.tbl and -hdg.tbms is deprecated. Use \"$Ships: (\"Some ship class\") instead.\n"));
334 
335 				if (!Ships_inited) {
336 					// just in case ship info has not been initialized.
337 					skip_to_start_of_string("#Gauge Config");
338 					continue;
339 				}
340 
341 				// get the ship number for this HUD configuration.
342 				ship_idx = parse_ship_start();
343 				ship_classes.push_back(ship_idx);
344 
345 				if (ship_idx >= 0) {
346 					Ship_info[ship_idx].hud_enabled = true;
347 
348 					// see if we need to load defaults for this configuration
349 					if (optional_string("$Load Retail Configuration:")) {
350 						stuff_boolean(&Ship_info[ship_idx].hud_retail);
351 					}
352 
353 					if (optional_string("$Color:")) {
354 						stuff_int_list(colors, 3);
355 
356 						check_color(colors);
357 						gr_init_alphacolor(&ship_color, colors[0], colors[1], colors[2], 255);
358 						ship_clr_p = &ship_color;
359 					}
360 
361 					if (optional_string("$Font:")) {
362 						ship_font = font::parse_font();
363 					}
364 
365 					if (optional_string("$Chase View Only:")) {
366 						stuff_boolean(&chase_view_only);
367 					}
368 				}
369 				else {
370 					// can't find ship class. move on.
371 					ship_classes.push_back(-1);
372 					skip_to_start_of_string("#Gauge Config");
373 					//skip_to_start_of_string_either("#Gauge Config", "#End");
374 					continue;
375 				}
376 				break;
377 			case 1:
378 				int shiparray[256];
379 
380 				n_ships = (int)stuff_int_list(shiparray, 256, SHIP_INFO_TYPE);
381 
382 				if (optional_string("$Load Retail Configuration:")) {
383 					stuff_boolean(&retail_config);
384 				}
385 
386 				for (i = 0; i < n_ships; ++i) {
387 					ship_classes.push_back(shiparray[i]);
388 					Ship_info[shiparray[i]].hud_enabled = true;
389 					Ship_info[shiparray[i]].hud_retail = retail_config;
390 				}
391 
392 				if (optional_string("$Color:")) {
393 					stuff_int_list(colors, 3);
394 
395 					check_color(colors);
396 					gr_init_alphacolor(&ship_color, colors[0], colors[1], colors[2], 255);
397 					ship_clr_p = &ship_color;
398 				}
399 
400 				if (optional_string("$Font:")) {
401 					ship_font = font::parse_font();
402 				}
403 				if (optional_string("$Chase View Only:")) {
404 					stuff_boolean(&chase_view_only);
405 				}
406 				break;
407 			default:
408 				// No particular ship. -1 for default HUD configuration.
409 				ship_classes.push_back(-1);
410 				ship_font = -1;
411 				ship_clr_p = NULL;
412 				break;
413 			}
414 
415 			if (ship_clr_p != NULL) {
416 				use_clr_p = ship_clr_p;
417 			}
418 			else {
419 				use_clr_p = hud_clr_p;
420 			}
421 
422 			if (ship_font >= 0) {
423 				use_font = ship_font;
424 			}
425 			else {
426 				use_font = Hud_font;
427 			}
428 
429 			// Now start going through resolution info for this HUD layout
430 			required_string("$Base:");
431 
432 			// get the base width and height describing this HUD
433 			stuff_int_list(base_res, 2, RAW_INTEGER_TYPE);
434 
435 			// gauge scaling for this base res?
436 			if (optional_string("$Scale Gauges:")) {
437 				stuff_boolean(&scale_gauge);
438 			}
439 
440 			// maximum res at which scaling can be disabled
441 			if (optional_string("$Force Scaling Above:")) {
442 				stuff_int_list(force_scaling_above_res, 2);
443 			} else {
444 				memcpy(force_scaling_above_res, Force_scaling_above_res_global, sizeof(force_scaling_above_res));
445 			}
446 
447 			// Pruning time. Let's see if the current resolution defined by the user matches the conditions set by this entry
448 			if (optional_string("$Required Aspect:")) {
449 				// filter aspect ratio.
450 				if (optional_string("Full Screen")) {
451 					if( (float)gr_screen.center_w / (float)gr_screen.center_h > 1.5) {
452 						skip_to_start_of_string("#Gauge Config");
453 						//skip_to_start_of_string_either("#Gauge Config", "#End");
454 						continue;
455 					}
456 				}
457 				else if (optional_string("Wide Screen")) {
458 					if( (float)gr_screen.center_w / (float)gr_screen.center_h <= 1.5) {
459 						skip_to_start_of_string("#Gauge Config");
460 						//skip_to_start_of_string_either("#Gauge Config", "#End");
461 						continue;
462 					}
463 				}
464 			}
465 
466 			// check minimum resolution
467 			if (optional_string("$Min:")) {
468 				int min_res[2];
469 				stuff_int_list(min_res, 2, RAW_INTEGER_TYPE);
470 
471 				if (min_res[0] > gr_screen.max_w) {
472 					skip_to_start_of_string("#Gauge Config");
473 					continue;
474 				}
475 				else if (min_res[0] == gr_screen.center_w) {
476 					if (min_res[1] > gr_screen.center_h) {
477 						skip_to_start_of_string("#Gauge Config");
478 						continue;
479 					}
480 				}
481 			}
482 
483 			// check maximum resolution
484 			if (optional_string("$Max:")) {
485 				int max_res[2];
486 				stuff_int_list(max_res, 2, RAW_INTEGER_TYPE);
487 
488 				if (max_res[0] < gr_screen.max_w) {
489 					skip_to_start_of_string("#Gauge Config");
490 					continue;
491 				}
492 				else if (max_res[0] == gr_screen.center_w) {
493 					if (max_res[1] < gr_screen.center_h) {
494 						skip_to_start_of_string("#Gauge Config");
495 						continue;
496 					}
497 				}
498 			}
499 
500 			// let's start parsing for gauges.
501 			required_string("$Gauges:");
502 
503 			while ((gauge_type = parse_gauge_type()) >= 0) {
504 				// change some of the default gauge settings to the appropriate values.
505 				gauge_settings settings;
506 				settings.font_num = use_font;
507 				settings.scale_gauge = scale_gauge;
508 				memcpy(settings.force_scaling_above_res, force_scaling_above_res, sizeof(settings.force_scaling_above_res));
509 				settings.ship_idx = &ship_classes;
510 				settings.use_clr = use_clr_p;
511 				settings.chase_view_only = chase_view_only;
512 
513 				// if "default" is specified, then the base resolution is {-1, -1},
514 				// indicating GR_640 or GR_1024 to the handlers. otherwise, change it
515 				// to the given base resolution.
516 				if (!optional_string("default")) {
517 					memcpy(settings.base_res, base_res, sizeof(settings.base_res));
518 				}
519 
520 				// then call the specific gauge load handler function for this gauge type.
521 				load_gauge(gauge_type, &settings);
522 
523 				if (saved_Mp && (saved_Mp == Mp)) {
524 					Mp++;
525 				}
526 
527 				// HACK: The previous code simply skipped invalid entries but now we try to generate a warning for that.
528 				// If we don't see either $ or + then it means that there was an invalid token somewhere in between
529 				if (!check_for_string("$") && !check_for_string("+")) {
530 					error_display(0, "Detected invalid tokens while parsing HUD gauges: [%.32s]", next_tokens());
531 					skip_to_start_of_string_either("$", "+");
532 				}
533 
534 				// stolened from AI_profiles
535 				// if we've been through once already and are at the same place, force a move
536 				saved_Mp = Mp;
537 			}
538 
539 			required_string("$End Gauges");
540 			required_string("#End");
541 		}
542 	}
543 	catch (const parse::ParseException& e)
544 	{
545 		mprintf(("TABLES: Unable to parse '%s'!  Error message = %s.\n", filename, e.what()));
546 		return;
547 	}
548 }
549 
hud_positions_init()550 void hud_positions_init()
551 {
552 	if(!Ships_inited)
553 	{
554 		Error(LOCATION, "Could not initialize hudparse.cpp as ships were not inited first.");
555 		return;
556 	}
557 
558 	default_hud_gauges.clear();
559 
560 	if (cf_exists_full("hud_gauges.tbl", CF_TYPE_TABLES))
561 		parse_hud_gauges_tbl("hud_gauges.tbl");
562 
563 	parse_modular_table(NOX("*-hdg.tbm"), parse_hud_gauges_tbl);
564 
565 	// load missing retail gauges for the default and ship-specific HUDs
566 	load_missing_retail_gauges();
567 }
568 
load_missing_retail_gauges()569 void load_missing_retail_gauges()
570 {
571 	bool retail_gauge_loaded = false;
572 
573 	// load missing retail gauges for the retail HUD if needed
574 	if(Hud_retail) {
575 		int num_loaded_gauges = (int)default_hud_gauges.size();
576 
577 		for(int i = 0; i < Num_builtin_gauges; i++) {
578 			retail_gauge_loaded = false;
579 
580 			for(int j = 0; j < num_loaded_gauges; j++) {
581 				if(Builtin_gauges[i] == default_hud_gauges[j]->getObjectType()) {
582 					retail_gauge_loaded = true;
583 					break;
584 				}
585 			}
586 
587 			if(!retail_gauge_loaded) {
588 				gauge_settings settings;
589 				load_gauge(Builtin_gauges[i], &settings);
590 			}
591 		}
592 
593 		// if we're missing a radar gauge, load either orb or standard
594 		retail_gauge_loaded = false;
595 		for(int j = 0; j < num_loaded_gauges; j++) {
596 			if(HUD_OBJECT_RADAR_STD == default_hud_gauges[j]->getObjectType() ||
597 				HUD_OBJECT_RADAR_ORB == default_hud_gauges[j]->getObjectType() ||
598 				HUD_OBJECT_RADAR_BSG == default_hud_gauges[j]->getObjectType()) {
599 				retail_gauge_loaded = true;
600 			}
601 		}
602 
603 		// load radar gauge if not loaded.
604 		if(!retail_gauge_loaded) {
605 			gauge_settings settings;
606 			load_gauge((Cmdline_orb_radar ? HUD_OBJECT_RADAR_ORB : HUD_OBJECT_RADAR_STD), &settings);
607 		}
608 
609 		// Throw in the weapon linking reticle gauge if using FS1 defaults
610 		retail_gauge_loaded = false;
611 		if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
612 			for(int j = 0; j < num_loaded_gauges; j++) {
613 				if(HUD_OBJECT_WEAPON_LINKING == default_hud_gauges[j]->getObjectType()) {
614 					retail_gauge_loaded = true;
615 				}
616 			}
617 
618 			if(!retail_gauge_loaded) {
619 				gauge_settings settings;
620 				load_gauge(HUD_OBJECT_WEAPON_LINKING, &settings);
621 			}
622 		}
623 	}
624 
625 	// for each ship class, check if their specific HUD config is enabled
626 	int k = 0;
627 	for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); k++, ++it) {
628 		SCP_vector<int> sindex;
629 		sindex.push_back(k);
630 		if(it->hud_enabled && it->hud_retail) {
631 			int num_loaded_gauges = (int)it->hud_gauges.size();
632 
633 			for(int i = 0; i < Num_builtin_gauges; i++) {
634 				for(int j = 0; j < num_loaded_gauges; j++) {
635 					if(Builtin_gauges[i] == it->hud_gauges[j]->getObjectType()) {
636 						retail_gauge_loaded = true;
637 					}
638 				}
639 
640 				if(!retail_gauge_loaded) {
641 					gauge_settings settings;
642 					settings.ship_idx = &sindex;
643 					load_gauge(Builtin_gauges[i], &settings);
644 				}
645 			}
646 
647 			// if we're missing a radar gauge, load either orb or standard
648 			retail_gauge_loaded = false;
649 			for(int j = 0; j < num_loaded_gauges; j++) {
650 				if(HUD_OBJECT_RADAR_ORB == it->hud_gauges[j]->getObjectType() ||
651 					HUD_OBJECT_RADAR_STD == it->hud_gauges[j]->getObjectType() ||
652 					HUD_OBJECT_RADAR_BSG == it->hud_gauges[j]->getObjectType()) {
653 					retail_gauge_loaded = true;
654 				}
655 			}
656 
657 			// load radar gauge if not loaded.
658 			if(!retail_gauge_loaded) {
659 				gauge_settings settings;
660 				settings.ship_idx = &sindex;
661 				load_gauge((Cmdline_orb_radar ? HUD_OBJECT_RADAR_ORB : HUD_OBJECT_RADAR_STD), &settings);
662 			}
663 
664 			// Throw in the weapon linking reticle gauge if using FS1 defaults
665 			retail_gauge_loaded = false;
666 			if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
667 				for(int j = 0; j < num_loaded_gauges; j++) {
668 					if(HUD_OBJECT_WEAPON_LINKING == it->hud_gauges[j]->getObjectType()) {
669 						retail_gauge_loaded = true;
670 					}
671 				}
672 
673 				if(!retail_gauge_loaded) {
674 					gauge_settings settings;
675 					settings.ship_idx = &sindex;
676 					load_gauge(HUD_OBJECT_WEAPON_LINKING, &settings);
677 				}
678 			}
679 		}
680 	}
681 }
682 
683 // Called once after mission load is complete. Sets initial gauge activity states.
init_hud()684 void init_hud() {
685 	int config_type;
686 	size_t i, num_gauges;
687 
688 	if(!Ship_info[Player_ship->ship_info_index].hud_gauges.empty()) {
689 		num_gauges = Ship_info[Player_ship->ship_info_index].hud_gauges.size();
690 
691 		for(i = 0; i < num_gauges; i++) {
692 			config_type = Ship_info[Player_ship->ship_info_index].hud_gauges[i]->getConfigType();
693 
694 			if ( !Ship_info[Player_ship->ship_info_index].hud_gauges[i]->isOffbyDefault() && hud_config_show_flag_is_set(config_type) )
695 				Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updateActive(true);
696 			else
697 				Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updateActive(false);
698 
699 			Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updatePopUp(hud_config_popup_flag_is_set(config_type) ? true : false);
700 			Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updateColor(
701 				HUD_config.clr[config_type].red,
702 				HUD_config.clr[config_type].green,
703 				HUD_config.clr[config_type].blue,
704 				HUD_config.clr[config_type].alpha
705 				);
706 		}
707 	} else {
708 		num_gauges = default_hud_gauges.size();
709 
710 		for(i = 0; i < num_gauges; i++) {
711 			config_type = default_hud_gauges[i]->getConfigType();
712 
713 			if ( !default_hud_gauges[i]->isOffbyDefault() && hud_config_show_flag_is_set(config_type) )
714 				default_hud_gauges[i]->updateActive(true);
715 			else
716 				default_hud_gauges[i]->updateActive(false);
717 
718 			default_hud_gauges[i]->updatePopUp(hud_config_popup_flag_is_set(config_type) ? true : false);
719 			default_hud_gauges[i]->updateColor(
720 				HUD_config.clr[config_type].red,
721 				HUD_config.clr[config_type].green,
722 				HUD_config.clr[config_type].blue,
723 				HUD_config.clr[config_type].alpha
724 				);
725 		}
726 	}
727 }
728 
729 extern void hud_init_ballistic_index();
730 
set_current_hud()731 void set_current_hud()
732 {
733 	int config_type;
734 	size_t i, num_gauges;
735 
736 	// before we load any hud gauges, see whether we're carring a ballistic weapon (Mantis #2962)
737 	hud_init_ballistic_index();
738 
739 	// go through all HUD gauges. Load gauge properties defined in the HUD config if gauge is not customized.
740 	if(!Ship_info[Player_ship->ship_info_index].hud_gauges.empty()) {
741 		num_gauges = Ship_info[Player_ship->ship_info_index].hud_gauges.size();
742 
743 		for(i = 0; i < num_gauges; i++) {
744 			HudGauge* hgp = Ship_info[Player_ship->ship_info_index].hud_gauges[i].get();
745 			config_type = hgp->getConfigType();
746 
747 			if ( ( (!hgp->isOffbyDefault() || hgp->isActive()) && hud_config_show_flag_is_set(config_type)) )
748 				hgp->updateActive(true);
749 			else
750 				hgp->updateActive(false);
751 
752 			//hgp->updateActive(hud_config_show_flag_is_set(config_type) ? true : false);
753 			hgp->updatePopUp(hud_config_popup_flag_is_set(config_type) ? true : false);
754 			hgp->updateColor(
755 				HUD_config.clr[config_type].red,
756 				HUD_config.clr[config_type].green,
757 				HUD_config.clr[config_type].blue,
758 				HUD_config.clr[config_type].alpha
759 				);
760 		}
761 	} else {
762 		num_gauges = default_hud_gauges.size();
763 
764 		for(i = 0; i < num_gauges; i++) {
765 			config_type = default_hud_gauges[i]->getConfigType();
766 
767 			if ( ( (!default_hud_gauges[i]->isOffbyDefault() || default_hud_gauges[i]->isActive()) && hud_config_show_flag_is_set(config_type)) )
768 				default_hud_gauges[i]->updateActive(true);
769 			else
770 				default_hud_gauges[i]->updateActive(false);
771 
772 			//default_hud_gauges[i]->updateActive(hud_config_show_flag_is_set(config_type) ? true : false);
773 			default_hud_gauges[i]->updatePopUp(hud_config_popup_flag_is_set(config_type) ? true : false);
774 			default_hud_gauges[i]->updateColor(
775 				HUD_config.clr[config_type].red,
776 				HUD_config.clr[config_type].green,
777 				HUD_config.clr[config_type].blue,
778 				HUD_config.clr[config_type].alpha
779 				);
780 		}
781 	}
782 }
783 
parse_gauge_type()784 int parse_gauge_type()
785 {
786 	// probably a more elegant way to do this.
787 	// Likely involving a for loop, an array of strings and only one if statement with a strcmp.
788 	if(optional_string("+Custom:"))
789 		return HUD_OBJECT_CUSTOM;
790 
791 	if(optional_string("+Messages:"))
792 		return HUD_OBJECT_MESSAGES;
793 
794 	if(optional_string("+Training Messages:"))
795 		return HUD_OBJECT_TRAINING_MESSAGES;
796 
797 	if(optional_string("+Support:"))
798 		return HUD_OBJECT_SUPPORT;
799 
800 	if(optional_string("+Damage:"))
801 		return HUD_OBJECT_DAMAGE;
802 
803 	if(optional_string("+Wingman Status:"))
804 		return HUD_OBJECT_WINGMAN_STATUS;
805 
806 	if(optional_string("+Auto Speed:"))
807 		return HUD_OBJECT_AUTO_SPEED;
808 
809 	if(optional_string("+Auto Target:"))
810 		return HUD_OBJECT_AUTO_TARGET;
811 
812 	if(optional_string("+Countermeasures:"))
813 		return HUD_OBJECT_CMEASURES;
814 
815 	if(optional_string("+Talking Head:"))
816 		return HUD_OBJECT_TALKING_HEAD;
817 
818 	if(optional_string("+Directives:"))
819 		return HUD_OBJECT_DIRECTIVES;
820 
821 	if(optional_string("+Weapons:"))
822 		return HUD_OBJECT_WEAPONS;
823 
824 	if(optional_string("+Objective Notify:"))
825 		return HUD_OBJECT_OBJ_NOTIFY;
826 
827 	if(optional_string("+Squad Message:"))
828 		return HUD_OBJECT_SQUAD_MSG;
829 
830 	if(optional_string("+Lag:"))
831 		return HUD_OBJECT_LAG;
832 
833 	if(optional_string("+Mini Target Shields:"))
834 		return HUD_OBJECT_MINI_SHIELD;
835 
836 	if(optional_string("+Player Shields:"))
837 		return HUD_OBJECT_PLAYER_SHIELD;
838 
839 	if(optional_string("+Target Shields:"))
840 		return HUD_OBJECT_TARGET_SHIELD;
841 
842 	if(optional_string("+Escort View:"))
843 		return HUD_OBJECT_ESCORT;
844 
845 	if(optional_string("+Mission Time:"))
846 		return HUD_OBJECT_MISSION_TIME;
847 
848 	if(optional_string("+ETS Weapons:"))
849 		return HUD_OBJECT_ETS_WEAPONS;
850 
851 	if(optional_string("+ETS Shields:"))
852 		return HUD_OBJECT_ETS_SHIELDS;
853 
854 	if(optional_string("+ETS Engines:"))
855 		return HUD_OBJECT_ETS_ENGINES;
856 
857 	if(optional_string("+ETS Retail:"))
858 		return HUD_OBJECT_ETS_RETAIL;
859 
860 	if(optional_string("+Target Monitor:"))
861 		return HUD_OBJECT_TARGET_MONITOR;
862 
863 	if(optional_string("+Extra Target Data:"))
864 		return HUD_OBJECT_EXTRA_TARGET_DATA;
865 
866 	if(optional_string("+Radar:")) {
867 		if(Cmdline_orb_radar) {
868 			return HUD_OBJECT_RADAR_ORB;
869 		} else {
870 			return HUD_OBJECT_RADAR_STD;
871 		}
872 	}
873 
874 	if(optional_string("+Radar Orb:"))
875 		return HUD_OBJECT_RADAR_ORB;
876 
877 	if(optional_string("+Radar BSG:"))
878 		return HUD_OBJECT_RADAR_BSG;
879 
880 	if(optional_string("+Afterburner Energy:"))
881 		return HUD_OBJECT_AFTERBURNER;
882 
883 	if(optional_string("+Weapon Energy:"))
884 		return HUD_OBJECT_WEAPON_ENERGY;
885 
886 	if(optional_string("+Text Warnings:"))
887 		return HUD_OBJECT_TEXT_WARNINGS;
888 
889 	if(optional_string("+Center Reticle:"))
890 		return HUD_OBJECT_CENTER_RETICLE;
891 
892 	if(optional_string("+Throttle:"))
893 		return HUD_OBJECT_THROTTLE;
894 
895 	if(optional_string("+Threat Indicator:"))
896 		return HUD_OBJECT_THREAT;
897 
898 	if(optional_string("+Lead Indicator:"))
899 		return HUD_OBJECT_LEAD;
900 
901 	if(optional_string("+Lead Sight:"))
902 		return HUD_OBJECT_LEAD_SIGHT;
903 
904 	if(optional_string("+Lock Indicator:"))
905 		return HUD_OBJECT_LOCK;
906 
907 	if(optional_string("+Weapon Linking:"))
908 		return HUD_OBJECT_WEAPON_LINKING;
909 
910 	if(optional_string("+Multiplayer Messages:"))
911 		return HUD_OBJECT_MULTI_MSG;
912 
913 	if(optional_string("+Voice Status:"))
914 		return HUD_OBJECT_VOICE_STATUS;
915 
916 	if(optional_string("+Ping:"))
917 		return HUD_OBJECT_PING;
918 
919 	if(optional_string("+Supernova:"))
920 		return HUD_OBJECT_SUPERNOVA;
921 
922 	if(optional_string("+Orientation Tee:"))
923 		return HUD_OBJECT_ORIENTATION_TEE;
924 
925 	if(optional_string("+Offscreen Indicator:"))
926 		return HUD_OBJECT_OFFSCREEN;
927 
928 	if(optional_string("+Target Brackets:"))
929 		return HUD_OBJECT_BRACKETS;
930 
931 	if(optional_string("+Hostile Triangle:"))
932 		return HUD_OBJECT_HOSTILE_TRI;
933 
934 	if(optional_string("+Target Triangle:"))
935 		return HUD_OBJECT_TARGET_TRI;
936 
937 	if(optional_string("+Missile Triangles:"))
938 		return HUD_OBJECT_MISSILE_TRI;
939 
940 	if(optional_string("+Kills:"))
941 		return HUD_OBJECT_KILLS;
942 
943 	if(optional_string("+Fixed Messages:"))
944 		return HUD_OBJECT_FIXED_MESSAGES;
945 
946 	if(optional_string("+Flight Path Marker:"))
947 		return HUD_OBJECT_FLIGHT_PATH;
948 
949 	if ( optional_string("+Warhead Count:") )
950 		return HUD_OBJECT_WARHEAD_COUNT;
951 
952 	if ( optional_string("+Hardpoints:") )
953 		return HUD_OBJECT_HARDPOINTS;
954 
955 	if ( optional_string("+Primary Weapons:") )
956 		return HUD_OBJECT_PRIMARY_WEAPONS;
957 
958 	if ( optional_string("+Secondary Weapons:") )
959 		return HUD_OBJECT_SECONDARY_WEAPONS;
960 
961 	if ( optional_string("+Scripted Gauge:") )
962 		return HUD_OBJECT_SCRIPTING;
963 
964 	return -1;
965 }
966 
load_gauge(int gauge,gauge_settings * settings)967 void load_gauge(int gauge, gauge_settings* settings)
968 {
969 	SCP_vector<int> ship_index;
970 	ship_index.push_back(-1);
971 	if (settings->ship_idx == NULL) {
972 		settings->ship_idx = &ship_index;
973 	}
974 	switch(gauge) {
975 	case HUD_OBJECT_CUSTOM:
976 		load_gauge_custom(settings);
977 		break;
978 	case HUD_OBJECT_MESSAGES:
979 		load_gauge_messages(settings);
980 		break;
981 	case HUD_OBJECT_TRAINING_MESSAGES:
982 		load_gauge_training_messages(settings);
983 		break;
984 	case HUD_OBJECT_SUPPORT:
985 		load_gauge_support(settings);
986 		break;
987 	case HUD_OBJECT_DAMAGE:
988 		load_gauge_damage(settings);
989 		break;
990 	case HUD_OBJECT_WINGMAN_STATUS:
991 		load_gauge_wingman_status(settings);
992 		break;
993 	case HUD_OBJECT_AUTO_SPEED:
994 		load_gauge_auto_speed(settings);
995 		break;
996 	case HUD_OBJECT_AUTO_TARGET:
997 		load_gauge_auto_target(settings);
998 		break;
999 	case HUD_OBJECT_CMEASURES:
1000 		load_gauge_countermeasures(settings);
1001 		break;
1002 	case HUD_OBJECT_TALKING_HEAD:
1003 		load_gauge_talking_head(settings);
1004 		break;
1005 	case HUD_OBJECT_DIRECTIVES:
1006 		load_gauge_directives(settings);
1007 		break;
1008 	case HUD_OBJECT_WEAPONS:
1009 		load_gauge_weapons(settings);
1010 		break;
1011 	case HUD_OBJECT_OBJ_NOTIFY:
1012 		load_gauge_objective_notify(settings);
1013 		break;
1014 	case HUD_OBJECT_SQUAD_MSG:
1015 		load_gauge_squad_message(settings);
1016 		break;
1017 	case HUD_OBJECT_LAG:
1018 		load_gauge_lag(settings);
1019 		break;
1020 	case HUD_OBJECT_MINI_SHIELD:
1021 		load_gauge_mini_shields(settings);
1022 		break;
1023 	case HUD_OBJECT_PLAYER_SHIELD:
1024 		load_gauge_player_shields(settings);
1025 		break;
1026 	case HUD_OBJECT_TARGET_SHIELD:
1027 		load_gauge_target_shields(settings);
1028 		break;
1029 	case HUD_OBJECT_ESCORT:
1030 		load_gauge_escort_view(settings);
1031 		break;
1032 	case HUD_OBJECT_MISSION_TIME:
1033 		load_gauge_mission_time(settings);
1034 		break;
1035 	case HUD_OBJECT_ETS_WEAPONS:
1036 		load_gauge_ets_weapons(settings);
1037 		break;
1038 	case HUD_OBJECT_ETS_SHIELDS:
1039 		load_gauge_ets_shields(settings);
1040 		break;
1041 	case HUD_OBJECT_ETS_ENGINES:
1042 		load_gauge_ets_engines(settings);
1043 		break;
1044 	case HUD_OBJECT_ETS_RETAIL:
1045 		load_gauge_ets_retail(settings);
1046 		break;
1047 	case HUD_OBJECT_TARGET_MONITOR:
1048 		load_gauge_target_monitor(settings);
1049 		break;
1050 	case HUD_OBJECT_EXTRA_TARGET_DATA:
1051 		load_gauge_extra_target_data(settings);
1052 		break;
1053 	case HUD_OBJECT_RADAR_STD:
1054 		load_gauge_radar_std(settings);
1055 		break;
1056 	case HUD_OBJECT_RADAR_ORB:
1057 		load_gauge_radar_orb(settings);
1058 		break;
1059 	case HUD_OBJECT_RADAR_BSG:
1060 		load_gauge_radar_dradis(settings);
1061 		break;
1062 	case HUD_OBJECT_AFTERBURNER:
1063 		load_gauge_afterburner(settings);
1064 		break;
1065 	case HUD_OBJECT_WEAPON_ENERGY:
1066 		load_gauge_weapon_energy(settings);
1067 		break;
1068 	case HUD_OBJECT_TEXT_WARNINGS:
1069 		load_gauge_text_warnings(settings);
1070 		break;
1071 	case HUD_OBJECT_CENTER_RETICLE:
1072 		load_gauge_center_reticle(settings);
1073 		break;
1074 	case HUD_OBJECT_THROTTLE:
1075 		load_gauge_throttle(settings);
1076 		break;
1077 	case HUD_OBJECT_THREAT:
1078 		load_gauge_threat_indicator(settings);
1079 		break;
1080 	case HUD_OBJECT_LEAD:
1081 		load_gauge_lead(settings);
1082 		break;
1083 	case HUD_OBJECT_LEAD_SIGHT:
1084 		load_gauge_lead_sight(settings);
1085 		break;
1086 	case HUD_OBJECT_LOCK:
1087 		load_gauge_lock(settings);
1088 		break;
1089 	case HUD_OBJECT_WEAPON_LINKING:
1090 		load_gauge_weapon_linking(settings);
1091 		break;
1092 	case HUD_OBJECT_MULTI_MSG:
1093 		load_gauge_multi_msg(settings);
1094 		break;
1095 	case HUD_OBJECT_VOICE_STATUS:
1096 		load_gauge_voice_status(settings);
1097 		break;
1098 	case HUD_OBJECT_PING:
1099 		load_gauge_ping(settings);
1100 		break;
1101 	case HUD_OBJECT_SUPERNOVA:
1102 		load_gauge_supernova(settings);
1103 		break;
1104 	case HUD_OBJECT_OFFSCREEN:
1105 		load_gauge_offscreen(settings);
1106 		break;
1107 	case HUD_OBJECT_BRACKETS:
1108 		load_gauge_brackets(settings);
1109 		break;
1110 	case HUD_OBJECT_ORIENTATION_TEE:
1111 		load_gauge_orientation_tee(settings);
1112 		break;
1113 	case HUD_OBJECT_HOSTILE_TRI:
1114 		load_gauge_hostile_tri(settings);
1115 		break;
1116 	case HUD_OBJECT_TARGET_TRI:
1117 		load_gauge_target_tri(settings);
1118 		break;
1119 	case HUD_OBJECT_MISSILE_TRI:
1120 		load_gauge_missile_tri(settings);
1121 		break;
1122 	case HUD_OBJECT_KILLS:
1123 		load_gauge_kills(settings);
1124 		break;
1125 	case HUD_OBJECT_FIXED_MESSAGES:
1126 		load_gauge_fixed_messages(settings);
1127 		break;
1128 	case HUD_OBJECT_FLIGHT_PATH:
1129 		load_gauge_flight_path(settings);
1130 		break;
1131 	case HUD_OBJECT_WARHEAD_COUNT:
1132 		load_gauge_warhead_count(settings);
1133 		break;
1134 	case HUD_OBJECT_HARDPOINTS:
1135 		load_gauge_hardpoints(settings);
1136 		break;
1137 	case HUD_OBJECT_PRIMARY_WEAPONS:
1138 		load_gauge_primary_weapons(settings);
1139 		break;
1140 	case HUD_OBJECT_SECONDARY_WEAPONS:
1141 		load_gauge_secondary_weapons(settings);
1142 		break;
1143 	case HUD_OBJECT_SCRIPTING:
1144 		load_gauge_scripting(settings);
1145 		break;
1146 	default:
1147 		// It's either -1, indicating we're ignoring a parse error, or it's a coding error.
1148 		Assertion(gauge == -1, "Invalid value '%d' passed to load_gauge(); get a coder!\n", gauge);
1149 		break;
1150 	}
1151 }
1152 
check_base_res(int * res)1153 inline bool check_base_res(int *res)
1154 {
1155 	return (res[0] >= 640) && (res[1] >= 480);
1156 }
1157 
check_color(int * colorp)1158 void check_color(int *colorp)
1159 {
1160 	int i;
1161 
1162 	for ( i = 0; i < 3; ++i ) {
1163 		if ( colorp[i] > 255 ) {
1164 			colorp[i] = 255;
1165 		} else if ( colorp[i] < 0 ) {
1166 			colorp[i] = 0;
1167 		}
1168 	}
1169 }
1170 
adjust_base_res(int * base_res,int * force_scaling_above_res,bool scaling=true)1171 void adjust_base_res(int *base_res, int *force_scaling_above_res, bool scaling = true)
1172 {
1173 	// Don't scale gauge if:
1174 	// no scaling is set and current res is between base res and "force scaling above res"
1175 	// Avoid HUD blurring caused solely by rounding errors
1176 	if ((!scaling && gr_screen.center_w >= base_res[0] && gr_screen.center_h >= base_res[1] &&
1177 			(force_scaling_above_res[0] <= 0 || force_scaling_above_res[1] <= 0 ||
1178 			gr_screen.center_w <= force_scaling_above_res[0] || gr_screen.center_h <= force_scaling_above_res[1])) ||
1179 			(gr_screen.center_w >= base_res[0] && gr_screen.center_h == base_res[1]) ||
1180 			(gr_screen.center_w == base_res[0] && gr_screen.center_h >= base_res[1])) {
1181 		base_res[0] = gr_screen.center_w;
1182 		base_res[1] = gr_screen.center_h;
1183 		return;
1184 	}
1185 
1186 	if (!scaling && force_scaling_above_res[0] > base_res[0] && force_scaling_above_res[1] > base_res[1] &&
1187 			gr_screen.center_w > force_scaling_above_res[0] && gr_screen.center_h > force_scaling_above_res[1]) {
1188 		base_res[0] = force_scaling_above_res[0];
1189 		base_res[1] = force_scaling_above_res[1];
1190 	}
1191 
1192 	float aspect_quotient = ((float)gr_screen.center_w / (float)gr_screen.center_h) / ((float)base_res[0] / (float)base_res[1]);
1193 	if (aspect_quotient >= 1.0) {
1194 		base_res[0] = (int)(base_res[0] * aspect_quotient);
1195 	} else {
1196 		base_res[1] = (int)(base_res[1] / aspect_quotient);
1197 	}
1198 }
1199 
adjust_for_multimonitor(int * base_res,bool set_position,int * coords)1200 void adjust_for_multimonitor(int *base_res, bool set_position, int *coords)
1201 {
1202 	float scale_w = (float)gr_screen.center_w / (float)base_res[0];
1203 	float scale_h = (float)gr_screen.center_h / (float)base_res[1];
1204 
1205 	base_res[0] = fl2ir(base_res[0] * ((float)gr_screen.max_w / (float)gr_screen.center_w));
1206 	base_res[1] = fl2ir(base_res[1] * ((float)gr_screen.max_h / (float)gr_screen.center_h));
1207 
1208 	if (set_position) {
1209 		coords[0] += fl2ir(gr_screen.center_offset_x / scale_w);
1210 		coords[1] += fl2ir(gr_screen.center_offset_y / scale_h);
1211 	}
1212 }
1213 
1214 template<class T>
gauge_load_common(gauge_settings * settings,T * preAllocated=NULL)1215 std::unique_ptr<T> gauge_load_common(gauge_settings* settings, T* preAllocated = NULL)
1216 {
1217 	int colors[3] = {255, 255, 255};
1218 	bool lock_color = false;
1219 
1220 	// render to texture parameters
1221 	char display_name[MAX_FILENAME_LEN] = "";
1222 	int display_size[2] = {0, 0};
1223 	int display_offset[2] = {0, 0};
1224 	int canvas_size[2] = {0, 0};
1225 
1226 	if(check_base_res(settings->base_res)) {
1227 		if (settings->set_position) {
1228 			if(optional_string("Position:")) {
1229 				stuff_int_list(settings->coords, 2);
1230 				settings->use_coords = true;
1231 			} else {
1232 				if(optional_string("Scale Gauge:")) {
1233 					stuff_boolean(&settings->scale_gauge);;
1234 				}
1235 
1236 				if(optional_string("Force Scaling Above:")) {
1237 					stuff_int_list(settings->force_scaling_above_res, 2);
1238 				}
1239 
1240 				adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
1241 
1242 				// If no positioning information is specified, use the default position
1243 				bool use_default_pos = true;
1244 
1245 				if(optional_string("Origin:")) {
1246 					stuff_float_list(settings->origin, 2);
1247 					use_default_pos = false;
1248 
1249 					required_string("Offset:");
1250 					stuff_int_list(settings->offset, 2);
1251 				}
1252 
1253 				if(optional_string("Offset:")) {
1254 					Error(LOCATION, "HUD gauges table: Offset must also have Origin defined");
1255 				}
1256 
1257 				if ( !(settings->use_coords && use_default_pos) ) {
1258 					settings->coords[0] = (int)(settings->base_res[0] * settings->origin[0]) + settings->offset[0];
1259 					settings->coords[1] = (int)(settings->base_res[1] * settings->origin[1]) + settings->offset[1];
1260 					settings->use_coords = true;
1261 				}
1262 			}
1263 		} else {
1264 			adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
1265 		}
1266 	} else {
1267 		if(gr_screen.res == GR_640) {
1268 			settings->base_res[0] = 640;
1269 			settings->base_res[1] = 480;
1270 		} else {
1271 			settings->base_res[0] = 1024;
1272 			settings->base_res[1] = 768;
1273 		}
1274 
1275 		adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
1276 
1277 		if (settings->set_position && !settings->use_coords) {
1278 			settings->coords[0] = (int)(settings->base_res[0] * settings->origin[0]) + settings->offset[0];
1279 			settings->coords[1] = (int)(settings->base_res[1] * settings->origin[1]) + settings->offset[1];
1280 			settings->use_coords = true;
1281 		}
1282 	}
1283 
1284 	if (settings->set_position) {
1285 		if ( optional_string("Cockpit Target:") && settings->ship_idx->at(0) >= 0 ) {
1286 			stuff_string(display_name, F_NAME, MAX_FILENAME_LEN);
1287 
1288 			if ( optional_string("Canvas Size:") ) {
1289 				stuff_int_list(canvas_size, 2);
1290 			}
1291 
1292 			if ( optional_string("Display Offset:") ) {
1293 				stuff_int_list(display_offset, 2);
1294 			}
1295 
1296 			required_string("Display Size:");
1297 			stuff_int_list(display_size, 2);
1298 		} else {
1299 			// adjust for multimonitor setups ONLY if not rendering gauge to a texture
1300 			adjust_for_multimonitor(settings->base_res, true, settings->coords);
1301 		}
1302 	} else {
1303 		adjust_for_multimonitor(settings->base_res, true, settings->coords);
1304 	}
1305 
1306 	if (settings->set_colour) {
1307 		if ( settings->use_clr != NULL ) {
1308 			colors[0] = settings->use_clr->red;
1309 			colors[1] = settings->use_clr->green;
1310 			colors[2] = settings->use_clr->blue;
1311 
1312 			lock_color = true;
1313 		} else if ( optional_string("Color:") ) {
1314 			stuff_int_list(colors, 3);
1315 
1316 			check_color(colors);
1317 
1318 			lock_color = true;
1319 		}
1320 	}
1321 
1322 	if (optional_string("Font:")) {
1323 		settings->font_num = font::parse_font();
1324 	} else {
1325 		if ( settings->font_num < 0 ) {
1326 			settings->font_num = font::FONT1;
1327 		}
1328 	}
1329 
1330 	if (optional_string("Chase View Only:")) {
1331 		stuff_boolean(&settings->chase_view_only);
1332 	}
1333 
1334 	if (settings->set_position) {
1335 		if(optional_string("Slew:")) {
1336 			stuff_boolean(&settings->slew);
1337 		}
1338 	}
1339 
1340 	std::unique_ptr<T> instance(preAllocated);
1341 
1342 	if (instance == NULL)
1343 	{
1344 		instance.reset(new T());
1345 	}
1346 
1347 	instance->initBaseResolution(settings->base_res[0], settings->base_res[1]);
1348 	instance->initFont(settings->font_num);
1349 	instance->initChase_view_only(settings->chase_view_only);
1350 	if (settings->set_position) {
1351 		instance->initPosition(settings->coords[0], settings->coords[1]);
1352 		instance->initSlew(settings->slew);
1353 		instance->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
1354 	}
1355 	if (settings->set_colour) {
1356 		instance->updateColor(colors[0], colors[1], colors[2]);
1357 		instance->lockConfigColor(lock_color);
1358 	}
1359 
1360 	return instance;
1361 }
1362 
1363 template<typename T>
gauge_assign_common(const gauge_settings * settings,std::unique_ptr<T> && hud_gauge)1364 void gauge_assign_common(const gauge_settings* settings, std::unique_ptr<T>&& hud_gauge) {
1365 	if(settings->ship_idx->at(0) >= 0) {
1366 		for (auto ship_index = settings->ship_idx->begin(); ship_index != settings->ship_idx->end(); ++ship_index) {
1367 			std::unique_ptr<T> instance(new T());
1368 			*instance = *hud_gauge;
1369 			Ship_info[*ship_index].hud_gauges.push_back(move(instance));
1370 		}
1371 		// Previous instance goes out of scope here and is destructed
1372 	} else {
1373 		default_hud_gauges.push_back(move(hud_gauge));
1374 	}
1375 }
1376 
load_gauge_custom(gauge_settings * settings)1377 void load_gauge_custom(gauge_settings* settings)
1378 {
1379 	int i;
1380 	char gauge_string[MAX_FILENAME_LEN];
1381 	char name[MAX_FILENAME_LEN];
1382 	char text[MAX_FILENAME_LEN];
1383 	char filename[MAX_FILENAME_LEN];
1384 	int gauge_type = HUD_CENTER_RETICLE;
1385 	bool active_by_default = true;
1386 	int txtoffset_x = 0, txtoffset_y = 0;
1387 	ubyte r = 255, g = 255, b = 255;
1388 	int colors[3] = {255, 255, 255};
1389 	bool lock_color = false;
1390 
1391 	// render to texture parameters
1392 	char display_name[MAX_FILENAME_LEN] = "";
1393 	int display_size[2] = {0, 0};
1394 	int display_offset[2] = {0, 0};
1395 	int canvas_size[2] = {0, 0};
1396 
1397 	if(check_base_res(settings->base_res)) {
1398 		if(optional_string("Position:")) {
1399 			stuff_int_list(settings->coords, 2);
1400 			settings->use_coords = true;
1401 		} else {
1402 			if(optional_string("Scale Gauge:")) {
1403 				stuff_boolean(&settings->scale_gauge);;
1404 			}
1405 
1406 			if(optional_string("Force Scaling Above:")) {
1407 				stuff_int_list(settings->force_scaling_above_res, 2);
1408 			}
1409 
1410 			adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
1411 
1412 			// If no positioning information is specified, use the default position
1413 			bool use_default_pos = true;
1414 
1415 			if(optional_string("Origin:")) {
1416 				stuff_float_list(settings->origin, 2);
1417 				use_default_pos = false;
1418 
1419 				required_string("Offset:");
1420 				stuff_int_list(settings->offset, 2);
1421 			}
1422 
1423 			if(optional_string("Offset:")) {
1424 				Error(LOCATION, "HUD gauges table: Offset must also have Origin defined");
1425 			}
1426 
1427 			if (!use_default_pos) {
1428 				settings->coords[0] = (int)(settings->base_res[0] * settings->origin[0]) + settings->offset[0];
1429 				settings->coords[1] = (int)(settings->base_res[1] * settings->origin[1]) + settings->offset[1];
1430 				settings->use_coords = true;
1431 			}
1432 		}
1433 
1434 		if ( optional_string("Cockpit Target:") && settings->ship_idx->at(0) >= 0 ) {
1435 			stuff_string(display_name, F_NAME, MAX_FILENAME_LEN);
1436 
1437 			if ( optional_string("Canvas Size:") ) {
1438 				stuff_int_list(canvas_size, 2);
1439 			}
1440 
1441 			if ( optional_string("Display Offset:") ) {
1442 				stuff_int_list(display_offset, 2);
1443 			}
1444 
1445 			required_string("Display Size:");
1446 			stuff_int_list(display_size, 2);
1447 		} else {
1448 			// adjust for multimonitor setups ONLY if not rendering gauge to a texture
1449 			adjust_for_multimonitor(settings->base_res, true, settings->coords);
1450 		}
1451 
1452 		if ( settings->use_clr != NULL ) {
1453 			colors[0] = settings->use_clr->red;
1454 			colors[1] = settings->use_clr->green;
1455 			colors[2] = settings->use_clr->blue;
1456 
1457 			lock_color = true;
1458 		} else if ( optional_string("Color:") ) {
1459 			stuff_int_list(colors, 3);
1460 
1461 			check_color(colors);
1462 
1463 			lock_color = true;
1464 		}
1465 
1466 		if (optional_string("Font:")) {
1467 			settings->font_num = font::parse_font();
1468 		} else {
1469 			if ( settings->font_num < 0 ) {
1470 				settings->font_num = font::FONT1;
1471 			}
1472 		}
1473 
1474 		if (optional_string("Chase View Only:")) {
1475 			stuff_boolean(&settings->chase_view_only);
1476 		}
1477 
1478 		required_string("Name:");
1479 		stuff_string(name, F_NAME, MAX_FILENAME_LEN);
1480 
1481 		required_string("Text:");
1482 		stuff_string(text, F_NAME, MAX_FILENAME_LEN);
1483 
1484 		if (optional_string("X Offset:")) {
1485 			stuff_int(&txtoffset_x);
1486 		}
1487 
1488 		if (optional_string("Y Offset:")) {
1489 			stuff_int(&txtoffset_y);
1490 		}
1491 
1492 		required_string("Gauge Type:");
1493 		stuff_string(gauge_string, F_NAME, MAX_FILENAME_LEN);
1494 
1495 		for(i = 0; i < NUM_HUD_GAUGES; i++) {
1496 			if(!strcmp(Legacy_HUD_gauges[i].hud_gauge_text, gauge_string)) {
1497 				gauge_type = i;
1498 				break;
1499 			}
1500 		}
1501 
1502 		if(optional_string("Slew:")) {
1503 			stuff_boolean(&settings->slew);
1504 		}
1505 
1506 		if(optional_string("Active by default:")) {
1507 			stuff_boolean(&active_by_default);
1508 		}
1509 
1510 		required_string("Filename:");
1511 		stuff_string(filename, F_NAME, MAX_FILENAME_LEN);
1512 	} else {
1513 		settings->base_res[0] = 640;
1514 		settings->base_res[1] = 480;
1515 
1516 		if ( settings->font_num < 0 ) {
1517 			settings->font_num = font::FONT1;
1518 		}
1519 	}
1520 
1521 	std::unique_ptr<HudGauge> hud_gauge(new HudGauge(gauge_type, settings->slew, r, g, b, name, text, filename, txtoffset_x, txtoffset_y));
1522 	hud_gauge->initBaseResolution(settings->base_res[0], settings->base_res[1]);
1523 	hud_gauge->initPosition(settings->coords[0], settings->coords[1]);
1524 	hud_gauge->initFont(settings->font_num);
1525 	hud_gauge->initRenderStatus(active_by_default);
1526 	hud_gauge->updateColor(colors[0], colors[1], colors[2]);
1527 	hud_gauge->lockConfigColor(lock_color);
1528 	hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
1529 	hud_gauge->initChase_view_only(settings->chase_view_only);
1530 
1531 	gauge_assign_common(settings, std::move(hud_gauge));
1532 }
1533 
load_gauge_lag(gauge_settings * settings)1534 void load_gauge_lag(gauge_settings* settings)
1535 {
1536 	char fname[MAX_FILENAME_LEN] = "netlag1";
1537 
1538 	settings->origin[0] = 0.5f;
1539 	settings->origin[1] = 0.5f;
1540 
1541 	if(gr_screen.res == GR_640) {
1542 		settings->offset[0] = 66;
1543 		settings->offset[1] = 91;
1544 	} else {
1545 		settings->offset[0] = 115;
1546 		settings->offset[1] = 145;
1547 	}
1548 
1549 	auto hud_gauge = gauge_load_common<HudGaugeLag>(settings);
1550 
1551 	if(optional_string("Filename:")) {
1552 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
1553 	}
1554 
1555 	hud_gauge->initBitmaps(fname);
1556 
1557 	gauge_assign_common(settings, std::move(hud_gauge));
1558 }
load_gauge_mini_shields(gauge_settings * settings)1559 void load_gauge_mini_shields(gauge_settings* settings)
1560 {
1561 	int Mini_3digit_offsets[2];
1562 	int Mini_1digit_offsets[2];
1563 	int Mini_2digit_offsets[2];
1564 	char fname[MAX_FILENAME_LEN] = "targhit1";
1565 
1566 	settings->origin[0] = 0.5f;
1567 	settings->origin[1] = 0.5f;
1568 	settings->slew = true;
1569 
1570 	if(gr_screen.res == GR_640) {
1571 		settings->offset[0] = -15;
1572 		settings->offset[1] = 51;
1573 
1574 		Mini_3digit_offsets[0] = 5;
1575 		Mini_3digit_offsets[1] = 7;
1576 		Mini_1digit_offsets[0] = 11;
1577 		Mini_1digit_offsets[1] = 7;
1578 		Mini_2digit_offsets[0] = 8;
1579 		Mini_2digit_offsets[1] = 7;
1580 	} else {
1581 		settings->offset[0] = -15;
1582 		settings->offset[1] = 86;
1583 
1584 		Mini_3digit_offsets[0] = 5;
1585 		Mini_3digit_offsets[1] = 7;
1586 		Mini_1digit_offsets[0] = 14;
1587 		Mini_1digit_offsets[1] = 7;
1588 		Mini_2digit_offsets[0] = 9;
1589 		Mini_2digit_offsets[1] = 7;
1590 	}
1591 
1592 	auto hud_gauge = gauge_load_common<HudGaugeShieldMini>(settings);
1593 
1594 	if(optional_string("Filename:")) {
1595 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
1596 	}
1597 	if(optional_string("3 Digit Hull Offsets:")) {
1598 		stuff_int_list(Mini_3digit_offsets, 2);
1599 	}
1600 	if(optional_string("2 Digit Hull Offsets:")) {
1601 		stuff_int_list(Mini_2digit_offsets, 2);
1602 	}
1603 	if(optional_string("1 Digit Hull Offsets:")) {
1604 		stuff_int_list(Mini_1digit_offsets, 2);
1605 	}
1606 
1607 	hud_gauge->init1DigitOffsets(Mini_1digit_offsets[0], Mini_1digit_offsets[1]);
1608 	hud_gauge->init2DigitOffsets(Mini_2digit_offsets[0], Mini_2digit_offsets[1]);
1609 	hud_gauge->init3DigitOffsets(Mini_3digit_offsets[0], Mini_3digit_offsets[1]);
1610 	hud_gauge->initBitmaps(fname);
1611 
1612 	gauge_assign_common(settings, std::move(hud_gauge));
1613 }
1614 
load_gauge_weapon_energy(gauge_settings * settings)1615 void load_gauge_weapon_energy(gauge_settings* settings)
1616 {
1617 	int Wenergy_text_offsets[2];
1618 	int Wenergy_h;
1619 	HudAlignment text_alignment = HudAlignment::NONE;
1620 	bool always_show_text = false;
1621 	bool show_ballistic = false;
1622 	bool moving_text = false;
1623 	int armed_weapon_offsets[2] = {0, 0};
1624 	int armed_weapon_h = 12;
1625 	HudAlignment weapon_alignment = HudAlignment::NONE;
1626 	bool show_weapons = false;
1627 	char fname[MAX_FILENAME_LEN];
1628 
1629 	settings->origin[0] = 0.5f;
1630 	settings->origin[1] = 0.5f;
1631 	settings->slew = true;
1632 
1633 	if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
1634 		if(gr_screen.res == GR_640) {
1635 			strcpy_s(fname, "energy2_fs1");
1636 		} else {
1637 			strcpy_s(fname, "2_energy2_fs1");
1638 		}
1639 	} else {
1640 		if(gr_screen.res == GR_640) {
1641 			strcpy_s(fname, "energy2");
1642 		} else {
1643 			strcpy_s(fname, "2_energy2");
1644 		}
1645 	}
1646 
1647 	if(gr_screen.res == GR_640) {
1648 		settings->offset[0] = 96;
1649 		settings->offset[1] = 25;
1650 
1651 		Wenergy_text_offsets[0] = 23;
1652 		Wenergy_text_offsets[1] = 53;
1653 
1654 		Wenergy_h = 60;
1655 	} else {
1656 		settings->offset[0] = 154;
1657 		settings->offset[1] = 40;
1658 
1659 		Wenergy_text_offsets[0] = 43;
1660 		Wenergy_text_offsets[1] = 85;
1661 
1662 		Wenergy_h = 96;
1663 	}
1664 
1665 	auto hud_gauge = gauge_load_common<HudGaugeWeaponEnergy>(settings);
1666 
1667 	if(optional_string("Filename:")) {
1668 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
1669 	}
1670 	if(optional_string("Foreground Clip Height:")) {
1671 		stuff_int(&Wenergy_h);
1672 	}
1673 	if(optional_string("Text Offsets:")) {
1674 		stuff_int_list(Wenergy_text_offsets, 2);
1675 
1676 		if(optional_string("Text Alignment:")) {
1677 			char temp[NAME_LENGTH];
1678 			stuff_string(temp, F_NAME, NAME_LENGTH);
1679 			text_alignment = hud_alignment_lookup(temp);
1680 		}
1681 	}
1682 	if(optional_string("Always Show Text:")) {
1683 		stuff_boolean(&always_show_text);
1684 	}
1685 	if(optional_string("Text Follows:")) {
1686 		stuff_boolean(&moving_text);
1687 	}
1688 	if(optional_string("Show Ballistic Ammo:")) {
1689 		stuff_boolean(&show_ballistic);
1690 	}
1691 	if(optional_string("Armed Guns List Offsets:")) {
1692 		stuff_int_list(armed_weapon_offsets, 2);
1693 		show_weapons = true;
1694 
1695 		if(optional_string("Armed Guns List Alignment:")) {
1696 			char temp[NAME_LENGTH];
1697 			stuff_string(temp, F_NAME, NAME_LENGTH);
1698 			weapon_alignment = hud_alignment_lookup(temp);
1699 		}
1700 
1701 		if(optional_string("Armed Guns List Entry Height:")) {
1702 			stuff_int(&armed_weapon_h);
1703 		}
1704 	}
1705 
1706 	hud_gauge->initBitmaps(fname);
1707 	hud_gauge->initEnergyHeight(Wenergy_h);
1708 	hud_gauge->initTextOffsets(Wenergy_text_offsets[0], Wenergy_text_offsets[1]);
1709 	hud_gauge->initAlignments(text_alignment, weapon_alignment);
1710 	hud_gauge->initAlwaysShowText(always_show_text);
1711 	hud_gauge->initMoveText(moving_text);
1712 	hud_gauge->initShowBallistics(show_ballistic);
1713 	hud_gauge->initArmedOffsets(armed_weapon_offsets[0], armed_weapon_offsets[1], armed_weapon_h, show_weapons);
1714 
1715 	gauge_assign_common(settings, std::move(hud_gauge));
1716 }
1717 
load_gauge_target_shields(gauge_settings * settings)1718 void load_gauge_target_shields(gauge_settings* settings)
1719 {
1720 	settings->origin[0] = 0.5f;
1721 	settings->origin[1] = 1.0f;
1722 
1723 	if(gr_screen.res == GR_640) {
1724 		settings->offset[0] = -178;
1725 		settings->offset[1] = -101;
1726 	} else {
1727 		settings->offset[0] = -220;
1728 		settings->offset[1] = -98;
1729 	}
1730 
1731 	auto hud_gauge = gauge_load_common<HudGaugeShieldTarget>(settings);
1732 
1733 	gauge_assign_common(settings, std::move(hud_gauge));
1734 }
1735 
load_gauge_player_shields(gauge_settings * settings)1736 void load_gauge_player_shields(gauge_settings* settings)
1737 {
1738 	settings->origin[0] = 0.5f;
1739 	settings->origin[1] = 1.0f;
1740 
1741 	if(gr_screen.res == GR_640) {
1742 		settings->offset[0] = 76;
1743 		settings->offset[1] = -101;
1744 	} else {
1745 		settings->offset[0] = 122;
1746 		settings->offset[1] = -98;
1747 	}
1748 
1749 	auto hud_gauge = gauge_load_common<HudGaugeShieldPlayer>(settings);
1750 
1751 	gauge_assign_common(settings, std::move(hud_gauge));
1752 }
1753 
load_gauge_escort_view(gauge_settings * settings)1754 void load_gauge_escort_view(gauge_settings* settings)
1755 {
1756 	int header_text_offsets[2];
1757 	int list_start_offsets[2];
1758 	int entry_h;
1759 	int entry_stagger_w;
1760 	int bottom_bg_offset = 0;
1761 	int ship_name_offsets[2];
1762 	int ship_name_max_w = 100;
1763 	int ship_integrity_offsets[2];
1764 	int ship_status_offsets[2];
1765 	bool right_align_names = false;
1766 	char header_text[MAX_FILENAME_LEN] = "";
1767 	char fname_top[MAX_FILENAME_LEN] = "escort1";
1768 	char fname_middle[MAX_FILENAME_LEN] = "escort2";
1769 	char fname_bottom[MAX_FILENAME_LEN] = "escort3";
1770 
1771 	settings->origin[0] = 1.0f;
1772 	settings->origin[1] = 0.5f;
1773 
1774 	if(gr_screen.res == GR_640) {
1775 		settings->offset[0] = -154;
1776 		settings->offset[1] = -40;
1777 
1778 		header_text_offsets[0] = 3;
1779 		header_text_offsets[1] = 2;
1780 		list_start_offsets[0] = 0;
1781 		list_start_offsets[1] = 13;
1782 		entry_h = 11;
1783 		entry_stagger_w = 0;
1784 		ship_name_offsets[0] = 3;
1785 		ship_name_offsets[1] = 0;
1786 		ship_integrity_offsets[0] = 118;
1787 		ship_integrity_offsets[1] = 0;
1788 		ship_status_offsets[0] = -12;
1789 		ship_status_offsets[1] = 0;
1790 	} else {
1791 		settings->offset[0] = -159;
1792 		settings->offset[1] = -54;
1793 
1794 		header_text_offsets[0] = 3;
1795 		header_text_offsets[1] = 2;
1796 		list_start_offsets[0] = 0;
1797 		list_start_offsets[1] = 13;
1798 		entry_h = 11;
1799 		entry_stagger_w = 0;
1800 		ship_name_offsets[0] = 4;
1801 		ship_name_offsets[1] = 0;
1802 		ship_integrity_offsets[0] = 116;
1803 		ship_integrity_offsets[1] = 0;
1804 		ship_status_offsets[0] = -11;
1805 		ship_status_offsets[1] = 0;
1806 	}
1807 
1808 	auto hud_gauge = gauge_load_common<HudGaugeEscort>(settings);
1809 
1810 	if(optional_string("Top Background Filename:")) {
1811 		stuff_string(fname_top, F_NAME, MAX_FILENAME_LEN);
1812 	}
1813 	if(optional_string("Entry Background Filename:")) {
1814 		stuff_string(fname_middle, F_NAME, MAX_FILENAME_LEN);
1815 	}
1816 	if(optional_string("Bottom Background Filename:")) {
1817 		stuff_string(fname_bottom, F_NAME, MAX_FILENAME_LEN);
1818 	}
1819 	if(optional_string("Entry Height:")) {
1820 		stuff_int(&entry_h);
1821 	}
1822 	if(optional_string("Entry Stagger Width:")) {
1823 		stuff_int(&entry_stagger_w);
1824 	}
1825 	if(optional_string("Bottom Background Offset:")) {
1826 		stuff_int(&bottom_bg_offset);
1827 	}
1828 	if(optional_string("Header Text:")) {
1829 		stuff_string(header_text, F_NAME, MAX_FILENAME_LEN);
1830 	}
1831 	if(optional_string("Header Offsets:")) {
1832 		stuff_int_list(header_text_offsets, 2);
1833 	}
1834 	if(optional_string("List Start Offsets:")) {
1835 		stuff_int_list(list_start_offsets, 2);
1836 	}
1837 	if(optional_string("Hull X-offset:")) {
1838 		stuff_int(&ship_integrity_offsets[0]);
1839 	}
1840 	if(optional_string("Name X-offset:")) {
1841 		stuff_int(&ship_name_offsets[0]);
1842 	}
1843 	if(optional_string("Status X-offset:")) {
1844 		stuff_int(&ship_status_offsets[0]);
1845 	}
1846 
1847 	if ( optional_string("Ship Name Max Width:") ) {
1848 		stuff_int(&ship_name_max_w);
1849 	}
1850 
1851 	if ( optional_string("Right-Align Ship Names:") ) {
1852 		stuff_boolean(&right_align_names);
1853 	}
1854 
1855 	if (header_text[0] == '\0') {
1856 		strcpy_s(header_text, XSTR("monitoring", 285));
1857 	}
1858 
1859 	hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
1860 	hud_gauge->initEntryHeight(entry_h);
1861 	hud_gauge->initEntryStaggerWidth(entry_stagger_w);
1862 	hud_gauge->initBottomBgOffset(bottom_bg_offset);
1863 	hud_gauge->initHeaderText(header_text);
1864 	hud_gauge->initHeaderTextOffsets(header_text_offsets[0], header_text_offsets[1]);
1865 	hud_gauge->initListStartOffsets(list_start_offsets[0], list_start_offsets[1]);
1866 	hud_gauge->initShipIntegrityOffsets(ship_integrity_offsets[0], ship_integrity_offsets[1]);
1867 	hud_gauge->initShipNameOffsets(ship_name_offsets[0], ship_name_offsets[1]);
1868 	hud_gauge->initShipStatusOffsets(ship_status_offsets[0], ship_status_offsets[1]);
1869 	hud_gauge->initShipNameMaxWidth(ship_name_max_w);
1870 	hud_gauge->initRightAlignNames(right_align_names);
1871 
1872 	gauge_assign_common(settings, std::move(hud_gauge));
1873 }
1874 
load_gauge_afterburner(gauge_settings * settings)1875 void load_gauge_afterburner(gauge_settings* settings)
1876 {
1877 	int energy_h;
1878 	char fname[MAX_FILENAME_LEN];
1879 
1880 	settings->origin[0] = 0.5f;
1881 	settings->origin[1] = 0.5f;
1882 	settings->slew = true;
1883 
1884 	if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
1885 		if(gr_screen.res == GR_640) {
1886 			strcpy_s(fname, "energy2_fs1");
1887 		} else {
1888 			strcpy_s(fname, "2_energy2_fs1");
1889 		}
1890 	} else {
1891 		if(gr_screen.res == GR_640) {
1892 			strcpy_s(fname, "energy2");
1893 		} else {
1894 			strcpy_s(fname, "2_energy2");
1895 		}
1896 	}
1897 
1898 	if(gr_screen.res == GR_640) {
1899 		settings->offset[0] = -149;
1900 		settings->offset[1] = 25;
1901 
1902 		energy_h = 60;
1903 	} else {
1904 		settings->offset[0] = -238;
1905 		settings->offset[1] = 40;
1906 
1907 		energy_h = 96;
1908 	}
1909 
1910 	auto hud_gauge = gauge_load_common<HudGaugeAfterburner>(settings);
1911 
1912 	if(optional_string("Filename:")) {
1913 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
1914 	}
1915 	if(optional_string("Foreground Clip Height:")) {
1916 		stuff_int(&energy_h);
1917 	}
1918 
1919 	hud_gauge->initEnergyHeight(energy_h);
1920 	hud_gauge->initBitmaps(fname);
1921 
1922 	gauge_assign_common(settings, std::move(hud_gauge));
1923 }
1924 
1925 
load_gauge_mission_time(gauge_settings * settings)1926 void load_gauge_mission_time(gauge_settings* settings)
1927 {
1928 	int time_text_offsets[2];
1929 	int time_val_offsets[2];
1930 	char fname[MAX_FILENAME_LEN] = "time1";
1931 
1932 	settings->origin[0] = 1.0f;
1933 	settings->origin[1] = 1.0f;
1934 
1935 	if(gr_screen.res == GR_640) {
1936 		settings->offset[0] = -53;
1937 		settings->offset[1] = -32;
1938 	} else {
1939 		settings->offset[0] = -55;
1940 		settings->offset[1] = -52;
1941 	}
1942 	time_text_offsets[0] = 4;
1943 	time_text_offsets[1] = 4;
1944 
1945 	time_val_offsets[0] = 26;
1946 	time_val_offsets[1] = 12;
1947 
1948 	auto hud_gauge = gauge_load_common<HudGaugeMissionTime>(settings);
1949 
1950 	if(optional_string("Filename:")) {
1951 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
1952 	}
1953 	if(optional_string("Text Offsets:")) {
1954 		stuff_int_list(time_text_offsets, 2);
1955 	}
1956 	if(optional_string("Value Offsets:")) {
1957 		stuff_int_list(time_val_offsets, 2);
1958 	}
1959 
1960 	hud_gauge->initTextOffsets(time_text_offsets[0], time_text_offsets[1]);
1961 	hud_gauge->initValueOffsets(time_val_offsets[0], time_val_offsets[1]);
1962 	hud_gauge->initBitmaps(fname);
1963 
1964 	gauge_assign_common(settings, std::move(hud_gauge));
1965 }
1966 
load_gauge_threat_indicator(gauge_settings * settings)1967 void load_gauge_threat_indicator(gauge_settings* settings)
1968 {
1969 	int Laser_warn_offsets[2];
1970 	int Lock_warn_offsets[2];
1971 	char fname_arc[MAX_FILENAME_LEN];
1972 	char fname_laser[MAX_FILENAME_LEN];
1973 	char fname_lock[MAX_FILENAME_LEN];
1974 
1975 	settings->origin[0] = 0.5f;
1976 	settings->origin[1] = 0.5f;
1977 	settings->slew = true;
1978 
1979 	if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
1980 		if(gr_screen.res == GR_640) {
1981 			settings->offset[0] = -79;
1982 			settings->offset[1] = -103;
1983 
1984 			Laser_warn_offsets[0] = 59;
1985 			Laser_warn_offsets[1] = 0;
1986 
1987 			Lock_warn_offsets[0] = 79;
1988 			Lock_warn_offsets[1] = 0;
1989 
1990 			strcpy_s(fname_arc, "toparc1_fs1");
1991 			strcpy_s(fname_laser, "toparc2_fs1");
1992 			strcpy_s(fname_lock, "toparc3_fs1");
1993 		} else {
1994 			settings->offset[0] = -126;
1995 			settings->offset[1] = -165;
1996 
1997 			Laser_warn_offsets[0] = 94;
1998 			Laser_warn_offsets[1] = 0;
1999 
2000 			Lock_warn_offsets[0] = 126;
2001 			Lock_warn_offsets[1] = 0;
2002 
2003 			strcpy_s(fname_arc, "2_toparc1_fs1");
2004 			strcpy_s(fname_laser, "2_toparc2_fs1");
2005 			strcpy_s(fname_lock, "2_toparc3_fs1");
2006 		}
2007 	} else {
2008 		if(gr_screen.res == GR_640) {
2009 			settings->offset[0] = 39;
2010 			settings->offset[1] = -72;
2011 
2012 			Laser_warn_offsets[0] = 41;
2013 			Laser_warn_offsets[1] = 77;
2014 
2015 			Lock_warn_offsets[0] = 35;
2016 			Lock_warn_offsets[1] = 93;
2017 
2018 			strcpy_s(fname_arc, "rightarc1");
2019 			strcpy_s(fname_laser, "toparc2");
2020 			strcpy_s(fname_lock, "toparc3");
2021 		} else {
2022 			settings->offset[0] = 62;
2023 			settings->offset[1] = -115;
2024 
2025 			Laser_warn_offsets[0] = 66;
2026 			Laser_warn_offsets[1] = 124;
2027 
2028 			Lock_warn_offsets[0] = 57;
2029 			Lock_warn_offsets[1] = 150;
2030 
2031 			strcpy_s(fname_arc, "2_rightarc1");
2032 			strcpy_s(fname_laser, "2_toparc2");
2033 			strcpy_s(fname_lock, "2_toparc3");
2034 		}
2035 	}
2036 
2037 	auto hud_gauge = gauge_load_common<HudGaugeThreatIndicator>(settings);
2038 
2039 	if(optional_string("Arc Filename:")) {
2040 		stuff_string(fname_arc, F_NAME, MAX_FILENAME_LEN);
2041 	}
2042 	if(optional_string("Dumbfire Filename:")) {
2043 		stuff_string(fname_laser, F_NAME, MAX_FILENAME_LEN);
2044 	}
2045 	if(optional_string("Lock Filename:")) {
2046 		stuff_string(fname_lock, F_NAME, MAX_FILENAME_LEN);
2047 	}
2048 	if(optional_string("Dumbfire Offsets:")) {
2049 		stuff_int_list(Laser_warn_offsets, 2);
2050 	}
2051 	if(optional_string("Lock Offsets:")) {
2052 		stuff_int_list(Lock_warn_offsets, 2);
2053 	}
2054 
2055 	hud_gauge->initBitmaps(fname_arc, fname_laser, fname_lock);
2056 	hud_gauge->initLaserWarnOffsets(Laser_warn_offsets[0], Laser_warn_offsets[1]);
2057 	hud_gauge->initLockWarnOffsets(Lock_warn_offsets[0], Lock_warn_offsets[1]);
2058 
2059 	gauge_assign_common(settings, std::move(hud_gauge));
2060 }
2061 
load_gauge_center_reticle(gauge_settings * settings)2062 void load_gauge_center_reticle(gauge_settings* settings)
2063 {
2064 	char fname[MAX_FILENAME_LEN];
2065 	bool firepoints = false;
2066 	int scaleX = 15;
2067 	int scaleY = 10;
2068 	int size = 5;
2069 	int autoaim_frame = -1;
2070 
2071 	settings->origin[0] = 0.5f;
2072 	settings->origin[1] = 0.5f;
2073 	settings->slew = true;
2074 
2075 	if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
2076 		if(gr_screen.res == GR_640) {
2077 			settings->offset[0] = -12;
2078 			settings->offset[1] = -5;
2079 
2080 			strcpy_s(fname, "reticle1_fs1");
2081 		} else {
2082 			settings->offset[0] = -19;
2083 			settings->offset[1] = -8;
2084 
2085 			strcpy_s(fname, "2_reticle1_fs1");
2086 		}
2087 	} else {
2088 		if(gr_screen.res == GR_640) {
2089 			settings->offset[0] = -12;
2090 			settings->offset[1] = -5;
2091 
2092 			strcpy_s(fname, "reticle1");
2093 		} else {
2094 			settings->offset[0] = -19;
2095 			settings->offset[1] = -14;
2096 
2097 			strcpy_s(fname, "2_reticle1");
2098 		}
2099 	}
2100 
2101 	auto hud_gauge = gauge_load_common<HudGaugeReticle>(settings);
2102 
2103 	if(optional_string("Filename:")) {
2104 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
2105 	}
2106 
2107 	if(optional_string("Firepoint display:"))
2108 		stuff_boolean(&firepoints);
2109 
2110 	if (optional_string("Firepoint size:"))
2111 		stuff_int(&size);
2112 
2113 	if (optional_string("Firepoint X coordinate multiplier:"))
2114 		stuff_int(&scaleX);
2115 
2116 	if (optional_string("Firepoint Y coordinate multiplier:"))
2117 		stuff_int(&scaleY);
2118 
2119 	if(optional_string("Autoaim Frame:"))
2120 		stuff_int(&autoaim_frame);
2121 
2122 	hud_gauge->initBitmaps(fname);
2123 	hud_gauge->initFirepointDisplay(firepoints, scaleX, scaleY, size);
2124 	hud_gauge->setAutoaimFrame(autoaim_frame);
2125 
2126 	gauge_assign_common(settings, std::move(hud_gauge));
2127 }
2128 
load_gauge_throttle(gauge_settings * settings)2129 void load_gauge_throttle(gauge_settings* settings)
2130 {
2131 	int bottom_offset_y;
2132 	int throttle_h, throttle_w;
2133 	int throttle_aburn_h;
2134 	int max_speed_offset[2];
2135 	bool show_max_speed = true;
2136 	int zero_speed_offset[2];
2137 	bool show_min_speed = true;
2138 	bool orbit = true;
2139 	int orbit_center_offset[2];
2140 	int orbit_radius;
2141 	int target_speed_offset[2] = {0, 0};
2142 	bool show_target_speed = false;
2143 	bool show_target_speed_percent = false;
2144 	int glide_offset[2] = {0, 0};
2145 	bool custom_glide = false;
2146 	int match_speed_offset[2] = {0, 0};
2147 	bool custom_match = false;
2148 	char fname[MAX_FILENAME_LEN];
2149 	bool show_background = false;
2150 
2151 	settings->origin[0] = 0.5f;
2152 	settings->origin[1] = 0.5f;
2153 	settings->slew = true;
2154 
2155 	// default values for the throttle
2156 	if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
2157 		if(gr_screen.res == GR_640) {
2158 			settings->offset[0] = -103;
2159 			settings->offset[1] = 4;
2160 
2161 			bottom_offset_y = 65;
2162 			throttle_h = 50;
2163 			throttle_w = 49;
2164 			throttle_aburn_h = 17;
2165 			max_speed_offset[0] = 14;
2166 			max_speed_offset[1] = 14;
2167 			zero_speed_offset[0] = 33;
2168 			zero_speed_offset[1] = 63;
2169 			orbit_center_offset[0] = 103;
2170 			orbit_center_offset[1] = -1;
2171 			orbit_radius = 104;
2172 			strcpy_s(fname, "leftarc_fs1");
2173 		} else {
2174 			settings->offset[0] = -165;
2175 			settings->offset[1] = 6;
2176 
2177 			bottom_offset_y = 104;
2178 			throttle_h = 80;
2179 			throttle_w = 78;
2180 			throttle_aburn_h = 27;
2181 			max_speed_offset[0] = 22;
2182 			max_speed_offset[1] = 22;
2183 			zero_speed_offset[0] = 53;
2184 			zero_speed_offset[1] = 101;
2185 			orbit_center_offset[0] = 165;
2186 			orbit_center_offset[1] = -1;
2187 			orbit_radius = 166;
2188 			strcpy_s(fname, "2_leftarc_fs1");
2189 		}
2190 		show_background = true;
2191 	} else {
2192 		if(gr_screen.res == GR_640) {
2193 			settings->offset[0] = -104;
2194 			settings->offset[1] = -72;
2195 
2196 			bottom_offset_y = 139;
2197 			throttle_h = 50;
2198 			throttle_w = 49;
2199 			throttle_aburn_h = 17;
2200 			max_speed_offset[0] = 20;
2201 			max_speed_offset[1] = 86;
2202 			zero_speed_offset[0] = 36;
2203 			zero_speed_offset[1] = 135;
2204 			orbit_center_offset[0] = 104;
2205 			orbit_center_offset[1] = 75;
2206 			orbit_radius = 104;
2207 			strcpy_s(fname, "leftarc");
2208 		} else {
2209 			settings->offset[0] = -166;
2210 			settings->offset[1] = -115;
2211 
2212 			bottom_offset_y = 222;
2213 			throttle_h = 80;
2214 			throttle_w = 78;
2215 			throttle_aburn_h = 27;
2216 			max_speed_offset[0] = 31;
2217 			max_speed_offset[1] = 137;
2218 			zero_speed_offset[0] = 57;
2219 			zero_speed_offset[1] = 216;
2220 			orbit_center_offset[0] = 166;
2221 			orbit_center_offset[1] = 118;
2222 			orbit_radius = 166;
2223 			strcpy_s(fname, "2_leftarc");
2224 		}
2225 	}
2226 
2227 	auto hud_gauge = gauge_load_common<HudGaugeThrottle>(settings);
2228 
2229 	if(optional_string("Filename:")) {
2230 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
2231 	}
2232 	if(optional_string("Foreground Clip Bottom Y-offset:")) {
2233 		stuff_int(&bottom_offset_y);
2234 	}
2235 	if(optional_string("Foreground Clip Width:")) {
2236 		stuff_int(&throttle_w);
2237 	}
2238 	if(optional_string("Foreground Clip Height:")) {
2239 		stuff_int(&throttle_h);
2240 	}
2241 	if(optional_string("Afterburner Clip Height:")) {
2242 		stuff_int(&throttle_aburn_h);
2243 	}
2244 	if(optional_string("Show Background:")) {
2245 		stuff_boolean(&show_background);
2246 	}
2247 	if(optional_string("Max Speed Label Offsets:")) {
2248 		stuff_int_list(max_speed_offset, 2);
2249 	}
2250 	if(optional_string("Show Max Speed Label:")) {
2251 		stuff_boolean(&show_max_speed);
2252 	}
2253 	if(optional_string("Min Speed Label Offsets:")) {
2254 		stuff_int_list(zero_speed_offset, 2);
2255 	}
2256 	if(optional_string("Show Min Speed Label:")) {
2257 		stuff_boolean(&show_min_speed);
2258 	}
2259 	if(optional_string("Orbit Center Offsets:")) {
2260 		stuff_int_list(orbit_center_offset, 2);
2261 	}
2262 	if(optional_string("Orbit Radius:")) {
2263 		stuff_int(&orbit_radius);
2264 	}
2265 	if(optional_string("Current Speed Offsets:")) {
2266 		stuff_int_list(orbit_center_offset, 2);
2267 		orbit = false;
2268 	}
2269 	if(optional_string("Target Speed Offsets:")) {
2270 		stuff_int_list(target_speed_offset, 2);
2271 		show_target_speed = true;
2272 	}
2273 	if ( optional_string("Show Percentage:") ) {
2274 		stuff_boolean(&show_target_speed_percent);
2275 	}
2276 	if(optional_string("Glide Status Offsets:")) {
2277 		stuff_int_list(glide_offset, 2);
2278 		custom_glide = true;
2279 	}
2280 	if(optional_string("Match Speed Status Offsets:")) {
2281 		stuff_int_list(match_speed_offset, 2);
2282 		custom_match = true;
2283 	}
2284 
2285 	hud_gauge->initThrottleStartY(bottom_offset_y);
2286 	hud_gauge->initThrottleSizes(throttle_w, throttle_h);
2287 	hud_gauge->initAburnHeight(throttle_aburn_h);
2288 	hud_gauge->initMaxSpeedOffsets(max_speed_offset[0], max_speed_offset[1], show_max_speed);
2289 	hud_gauge->initZeroSpeedOffsets(zero_speed_offset[0], zero_speed_offset[1], show_min_speed);
2290 	hud_gauge->initOrbitCenterOffsets(orbit_center_offset[0], orbit_center_offset[1], orbit);
2291 	hud_gauge->initOrbitRadius(orbit_radius);
2292 	hud_gauge->initTargetSpeedOffsets(target_speed_offset[0], target_speed_offset[1], show_target_speed, show_target_speed_percent);
2293 	hud_gauge->initGlideOffsets(glide_offset[0], glide_offset[1], custom_glide);
2294 	hud_gauge->initMatchSpeedOffsets(match_speed_offset[0], match_speed_offset[1], custom_match);
2295 	hud_gauge->initBitmaps(fname);
2296 	hud_gauge->showBackground(show_background);
2297 
2298 	gauge_assign_common(settings, std::move(hud_gauge));
2299 }
2300 
2301 /**
2302  * Load retail style ETS gauge
2303  * i.e. treats weapons, shields & engines gauges as a single gauge
2304  */
load_gauge_ets_retail(gauge_settings * settings)2305 void load_gauge_ets_retail(gauge_settings* settings)
2306 {
2307 	int bar_h;
2308 	int letter_offsets[2];
2309 	int top_offsets[2];
2310 	int bottom_offsets[2];
2311 	char ets_letters[num_retail_ets_gauges];
2312 	char fname[MAX_FILENAME_LEN] = "energy1";
2313 	int gauge_offset; // distance between micro gauges
2314 	int i;
2315 	int gauge_positions[num_retail_ets_gauges];
2316 
2317 	settings->origin[0] = 1.0f;
2318 	settings->origin[1] = 1.0f;
2319 
2320 	if (Lcl_gr) {
2321 		ets_letters[0] = 'G'; ets_letters[1] = 'S'; ets_letters[2] = 'A'; // German
2322 	} else if (Lcl_fr) {
2323 		ets_letters[0] = 'C'; ets_letters[1] = 'B'; ets_letters[2] = 'M'; // French
2324 	} else {
2325 		ets_letters[0] = 'G'; ets_letters[1] = 'S'; ets_letters[2] = 'E'; // English
2326 	}
2327 
2328 	// default values which may be overwritten by .tbl
2329 	if(gr_screen.res == GR_640) {
2330 		settings->offset[0] = -117;
2331 		settings->offset[1] = -100;
2332 
2333 		gauge_offset = 17;
2334 	} else {
2335 		settings->offset[0] = -144;
2336 		settings->offset[1] = -120;
2337 
2338 		gauge_offset = 18;
2339 	}
2340 	bar_h = 41;
2341 	letter_offsets[0] = 2;
2342 	letter_offsets[1] = 42;
2343 	top_offsets[0] = 0;
2344 	top_offsets[1] = 0;
2345 	bottom_offsets[0] = 0;
2346 	bottom_offsets[1] = 50;
2347 
2348 	auto hud_gauge = gauge_load_common<HudGaugeEtsRetail>(settings);
2349 
2350 	if(optional_string("Filename:")) {
2351 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
2352 	}
2353 	if(optional_string("Foreground Clip Height:")) {
2354 		stuff_int(&bar_h);
2355 	}
2356 	if(optional_string("Letter Offsets:")) {
2357 		stuff_int_list(letter_offsets, 2);
2358 	}
2359 	if(optional_string("Top Offsets:")) {
2360 		stuff_int_list(top_offsets, 2);
2361 	}
2362 	if(optional_string("Bottom Offsets:")) {
2363 		stuff_int_list(bottom_offsets, 2);
2364 	}
2365 	if(optional_string("Gauge Offset:")) {
2366 		stuff_int(&gauge_offset);
2367 	}
2368 
2369 	// calculate offsets for the three gauges from settings->coords[0], which was set by gauge_load_common
2370 	for (i = 0; i < num_retail_ets_gauges; ++i) {
2371 		gauge_positions[i] = settings->coords[0] + gauge_offset * i;
2372 	}
2373 
2374 	hud_gauge->initLetters(ets_letters);
2375 	hud_gauge->initLetterOffsets(letter_offsets[0], letter_offsets[1]);
2376 	hud_gauge->initTopOffsets(top_offsets[0], top_offsets[1]);
2377 	hud_gauge->initBottomOffsets(bottom_offsets[0], bottom_offsets[1]);
2378 	hud_gauge->initBarHeight(bar_h);
2379 	hud_gauge->initBitmaps(fname);
2380 	hud_gauge->initGaugePositions(gauge_positions);
2381 
2382 	gauge_assign_common(settings, std::move(hud_gauge));
2383 }
2384 
load_gauge_ets_weapons(gauge_settings * settings)2385 void load_gauge_ets_weapons(gauge_settings* settings)
2386 {
2387 	int bar_h;
2388 	int letter_offsets[2];
2389 	int top_offsets[2];
2390 	int bottom_offsets[2];
2391 	char letter;
2392 	char fname[MAX_FILENAME_LEN] = "energy1";
2393 
2394 	settings->origin[0] = 1.0f;
2395 	settings->origin[1] = 1.0f;
2396 
2397 	if(Lcl_gr) {
2398 		// German
2399 		letter = 'G';
2400 	} else if(Lcl_fr) {
2401 		// French
2402 		letter = 'C';
2403 	} else {
2404 		// English
2405 		letter = 'G';
2406 	}
2407 
2408 	if(gr_screen.res == GR_640) {
2409 		settings->offset[0] = -117;
2410 		settings->offset[1] = -100;
2411 	} else {
2412 		settings->offset[0] = -144;
2413 		settings->offset[1] = -120;
2414 	}
2415 	bar_h = 41;
2416 	letter_offsets[0] = 2;
2417 	letter_offsets[1] = 42;
2418 	top_offsets[0] = 0;
2419 	top_offsets[1] = 0;
2420 	bottom_offsets[0] = 0;
2421 	bottom_offsets[1] = 50;
2422 
2423 	auto hud_gauge = gauge_load_common<HudGaugeEtsWeapons>(settings);
2424 
2425 	if(optional_string("Filename:")) {
2426 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
2427 	}
2428 	if(optional_string("Foreground Clip Height:")) {
2429 		stuff_int(&bar_h);
2430 	}
2431 	if(optional_string("Letter Offsets:")) {
2432 		stuff_int_list(letter_offsets, 2);
2433 	}
2434 	if(optional_string("Top Offsets:")) {
2435 		stuff_int_list(top_offsets, 2);
2436 	}
2437 	if(optional_string("Bottom Offsets:")) {
2438 		stuff_int_list(bottom_offsets, 2);
2439 	}
2440 
2441 	hud_gauge->initLetter(letter);
2442 	hud_gauge->initLetterOffsets(letter_offsets[0], letter_offsets[1]);
2443 	hud_gauge->initTopOffsets(top_offsets[0], top_offsets[1]);
2444 	hud_gauge->initBottomOffsets(bottom_offsets[0], bottom_offsets[1]);
2445 	hud_gauge->initBarHeight(bar_h);
2446 	hud_gauge->initBitmaps(fname);
2447 
2448 	gauge_assign_common(settings, std::move(hud_gauge));
2449 }
2450 
load_gauge_ets_shields(gauge_settings * settings)2451 void load_gauge_ets_shields(gauge_settings* settings)
2452 {
2453 	int bar_h;
2454 	int letter_offsets[2];
2455 	int top_offsets[2];
2456 	int bottom_offsets[2];
2457 	char letter;
2458 	char fname[MAX_FILENAME_LEN] = "energy1";
2459 
2460 	settings->origin[0] = 1.0f;
2461 	settings->origin[1] = 1.0f;
2462 
2463 	if(Lcl_gr){
2464 		// German
2465 		letter = 'S';
2466 	} else if(Lcl_fr){
2467 		// French
2468 		letter = 'B';
2469 	} else {
2470 		// English
2471 		letter = 'S';
2472 	}
2473 
2474 	if(gr_screen.res == GR_640) {
2475 		settings->offset[0] = -100;
2476 		settings->offset[1] = -100;
2477 	} else {
2478 		settings->offset[0] = -126;
2479 		settings->offset[1] = -120;
2480 	}
2481 	bar_h = 41;
2482 
2483 	letter_offsets[0] = 2;
2484 	letter_offsets[1] = 42;
2485 	top_offsets[0] = 0;
2486 	top_offsets[1] = 0;
2487 	bottom_offsets[0] = 0;
2488 	bottom_offsets[1] = 50;
2489 
2490 	auto hud_gauge = gauge_load_common<HudGaugeEtsShields>(settings);
2491 
2492 	if(optional_string("Filename:")) {
2493 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
2494 	}
2495 	if(optional_string("Foreground Clip Height:")) {
2496 		stuff_int(&bar_h);
2497 	}
2498 	if(optional_string("Letter Offsets:")) {
2499 		stuff_int_list(letter_offsets, 2);
2500 	}
2501 	if(optional_string("Top Offsets:")) {
2502 		stuff_int_list(top_offsets, 2);
2503 	}
2504 	if(optional_string("Bottom Offsets:")) {
2505 		stuff_int_list(bottom_offsets, 2);
2506 	}
2507 
2508 	hud_gauge->initBarHeight(bar_h);
2509 	hud_gauge->initBitmaps(fname);
2510 	hud_gauge->initBottomOffsets(bottom_offsets[0], bottom_offsets[1]);
2511 	hud_gauge->initLetter(letter);
2512 	hud_gauge->initLetterOffsets(letter_offsets[0], letter_offsets[1]);
2513 	hud_gauge->initTopOffsets(top_offsets[0], top_offsets[1]);
2514 
2515 	gauge_assign_common(settings, std::move(hud_gauge));
2516 }
2517 
load_gauge_ets_engines(gauge_settings * settings)2518 void load_gauge_ets_engines(gauge_settings* settings)
2519 {
2520 	int bar_h;
2521 	int letter_offsets[2];
2522 	int top_offsets[2];
2523 	int bottom_offsets[2];
2524 	char letter;
2525 	char fname[MAX_FILENAME_LEN] = "energy1";
2526 
2527 	settings->origin[0] = 1.0f;
2528 	settings->origin[1] = 1.0f;
2529 
2530 	if(Lcl_gr){
2531 		// German
2532 		letter = 'A';
2533 	} else if(Lcl_fr){
2534 		// French
2535 		letter = 'M';
2536 	} else {
2537 		// English
2538 		letter = 'E';
2539 	}
2540 
2541 	if(gr_screen.res == GR_640) {
2542 		settings->offset[0] = -83;
2543 		settings->offset[1] = -100;
2544 	} else {
2545 		settings->offset[0] = -108;
2546 		settings->offset[1] = -120;
2547 	}
2548 
2549 	bar_h = 41;
2550 
2551 	letter_offsets[0] = 2;
2552 	letter_offsets[1] = 42;
2553 	top_offsets[0] = 0;
2554 	top_offsets[1] = 0;
2555 	bottom_offsets[0] = 0;
2556 	bottom_offsets[1] = 50;
2557 
2558 	auto hud_gauge = gauge_load_common<HudGaugeEtsEngines>(settings);
2559 
2560 	if(optional_string("Filename:")) {
2561 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
2562 	}
2563 	if(optional_string("Foreground Clip Height:")) {
2564 		stuff_int(&bar_h);
2565 	}
2566 	if(optional_string("Letter Offsets:")) {
2567 		stuff_int_list(letter_offsets, 2);
2568 	}
2569 	if(optional_string("Top Offsets:")) {
2570 		stuff_int_list(top_offsets, 2);
2571 	}
2572 	if(optional_string("Bottom Offsets:")) {
2573 		stuff_int_list(bottom_offsets, 2);
2574 	}
2575 
2576 	hud_gauge->initBarHeight(bar_h);
2577 	hud_gauge->initBitmaps(fname);
2578 	hud_gauge->initBottomOffsets(bottom_offsets[0], bottom_offsets[1]);
2579 	hud_gauge->initLetter(letter);
2580 	hud_gauge->initLetterOffsets(letter_offsets[0], letter_offsets[1]);
2581 	hud_gauge->initTopOffsets(top_offsets[0], top_offsets[1]);
2582 
2583 	gauge_assign_common(settings, std::move(hud_gauge));
2584 }
2585 
load_gauge_extra_target_data(gauge_settings * settings)2586 void load_gauge_extra_target_data(gauge_settings* settings)
2587 {
2588 	int dock_offsets[2];
2589 	int dock_max_w;
2590 	int time_offsets[2];
2591 	int bracket_offsets[2];
2592 	int order_offsets[2];
2593 	int order_max_w;
2594 	char fname[MAX_FILENAME_LEN] = "targetview3";
2595 
2596 	settings->origin[0] = 0.0f;
2597 	settings->origin[1] = 1.0f;
2598 
2599 	if(gr_screen.res == GR_640) {
2600 		settings->offset[0] = 5;
2601 		settings->offset[1] = -200;
2602 
2603 		dock_offsets[0] = 8;
2604 		dock_offsets[1] = 19;
2605 
2606 		time_offsets[0] = 8;
2607 		time_offsets[1] = 10;
2608 	} else {
2609 		settings->offset[0] = 5;
2610 		settings->offset[1] = -216;
2611 
2612 		dock_offsets[0] = 8;
2613 		dock_offsets[1] = 18;
2614 
2615 		time_offsets[0] = 8;
2616 		time_offsets[1] = 9;
2617 	}
2618 
2619 	bracket_offsets[0] = 0;
2620 	bracket_offsets[1] = 3;
2621 
2622 	order_offsets[0] = 8;
2623 	order_offsets[1] = 0;
2624 
2625 	dock_max_w = 173;
2626 	order_max_w = 162;
2627 
2628 	auto hud_gauge = gauge_load_common<HudGaugeExtraTargetData>(settings);
2629 
2630 	if(optional_string("Filename:")) {
2631 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
2632 	}
2633 	if(optional_string("Bracket Offsets:")) {
2634 		stuff_int_list(bracket_offsets, 2);
2635 	}
2636 	if(optional_string("Dock Offsets:")) {
2637 		stuff_int_list(dock_offsets, 2);
2638 	}
2639 	if(optional_string("Dock Max Width:")) {
2640 		stuff_int(&dock_max_w);
2641 	}
2642 	if(optional_string("Order Offsets:")) {
2643 		stuff_int_list(order_offsets, 2);
2644 	}
2645 	if(optional_string("Order Max Width:")) {
2646 		stuff_int(&order_max_w);
2647 	}
2648 	if(optional_string("Time Offsets:")) {
2649 		stuff_int_list(time_offsets, 2);
2650 	}
2651 
2652 	hud_gauge->initBitmaps(fname);
2653 	hud_gauge->initBracketOffsets(bracket_offsets[0], bracket_offsets[1]);
2654 	hud_gauge->initDockOffsets(dock_offsets[0], dock_offsets[1]);
2655 	hud_gauge->initDockMaxWidth(dock_max_w);
2656 	hud_gauge->initOrderOffsets(order_offsets[0], order_offsets[1]);
2657 	hud_gauge->initOrderMaxWidth(order_max_w);
2658 	hud_gauge->initTimeOffsets(time_offsets[0], time_offsets[1]);
2659 
2660 	gauge_assign_common(settings, std::move(hud_gauge));
2661 }
2662 
load_gauge_radar_std(gauge_settings * settings)2663 void load_gauge_radar_std(gauge_settings* settings)
2664 {
2665 	int Radar_blip_radius_normal;
2666 	int Radar_blip_radius_target;
2667 	int Radar_radius[2];
2668 	int Radar_dist_offsets[RR_MAX_RANGES][2];
2669 	float Radar_center_offsets[2];
2670 	char fname[MAX_FILENAME_LEN];
2671 
2672 	settings->origin[0] = 0.5f;
2673 	settings->origin[1] = 1.0f;
2674 
2675 	if(gr_screen.res == GR_640) {
2676 		settings->offset[0] = -63;
2677 		settings->offset[1] = -111;
2678 
2679 		Radar_blip_radius_normal = 2;
2680 		Radar_blip_radius_target = 5;
2681 
2682 		Radar_center_offsets[0] = 64.0f;
2683 		Radar_center_offsets[1] = 53.0f;
2684 
2685 		Radar_radius[0] = 120;
2686 		Radar_radius[1] = 100;
2687 
2688 		Radar_dist_offsets[0][0] = 110;
2689 		Radar_dist_offsets[0][1] = 92;
2690 
2691 		Radar_dist_offsets[1][0] = 107;
2692 		Radar_dist_offsets[1][1] = 92;
2693 
2694 		Radar_dist_offsets[2][0] = 111;
2695 		Radar_dist_offsets[2][1] = 92;
2696 
2697 		strcpy_s(fname, "radar1");
2698 	} else {
2699 		settings->offset[0] = -101;
2700 		settings->offset[1] = -178;
2701 
2702 		Radar_blip_radius_normal = 4;
2703 		Radar_blip_radius_target = 8;
2704 
2705 		Radar_center_offsets[0] = 104.0f;
2706 		Radar_center_offsets[1] = 85.0f;
2707 
2708 		Radar_radius[0] = 192;
2709 		Radar_radius[1] = 160;
2710 
2711 		Radar_dist_offsets[0][0] = 184;
2712 		Radar_dist_offsets[0][1] = 150;
2713 
2714 		Radar_dist_offsets[1][0] = 181;
2715 		Radar_dist_offsets[1][1] = 150;
2716 
2717 		Radar_dist_offsets[2][0] = 185;
2718 		Radar_dist_offsets[2][1] = 150;
2719 
2720 		strcpy_s(fname, "2_radar1");
2721 	}
2722 
2723 	// Ngon radar -- Cyborg17 - to fit this into gauge_load_common, we have to have this right before origin and Offset
2724 	int num_sides = 0;
2725 	float offset  = 0.0f;
2726 
2727 	if (optional_string("Ngon Sides:")) {
2728 		stuff_int(&num_sides);
2729 		if ((num_sides < RADAR_NGON_MIN_SIDES)) {
2730 			Warning(LOCATION,
2731 			        "Invalid value for 'Ngon Sides'! Value must be greater than %i.\n Using standard radar instead.\n",
2732 			        RADAR_NGON_MIN_SIDES);
2733 			num_sides = 0;
2734 		}
2735 
2736 		if (optional_string("Ngon Offset:")) {
2737 			stuff_float(&offset);
2738 		}
2739 	}
2740 
2741 	//=======================================================================================================
2742 	// Cyborg17 - not using auto here is a huge pain to get exactly right and to read. If we put this in a
2743 	// normal if block, either auto will break or hud_gauge will go out of scope before the last block below.
2744 	// The ternery operator lets us circumvent this problem by allowing us to use auto, while also loading
2745 	// the radar, creating the unique_ptr, and staying in scope.
2746 
2747 	// did we have a normal radar? If so, load the regular radar.
2748 	auto hud_gauge = (num_sides == 0)
2749 	                     ? gauge_load_common<HudGaugeRadarStd>(settings)
2750 	                     // if not *construct* and then load the ngon radar
2751 	                     : gauge_load_common<HudGaugeRadarNgon>(settings, new HudGaugeRadarNgon(num_sides, offset));
2752 
2753 	if(optional_string("Filename:")) {
2754 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
2755 	}
2756 	if(optional_string("Radar Center Offsets:")) {
2757 		stuff_float_list(Radar_center_offsets, 2);
2758 	}
2759 	if(optional_string("Radar Size:")) {
2760 		stuff_int_list(Radar_radius, 2);
2761 	}
2762 	if(optional_string("Infinity Distance Offsets:")) {
2763 		stuff_int_list(Radar_dist_offsets[2], 2);
2764 	}
2765 	if(optional_string("Long Distance Offsets:")) {
2766 		stuff_int_list(Radar_dist_offsets[1], 2);
2767 	}
2768 	if(optional_string("Short Distance Offsets:")) {
2769 		stuff_int_list(Radar_dist_offsets[0], 2);
2770 	}
2771 
2772 	// Only load this if the user hasn't specified a preference
2773 	if (Cmdline_orb_radar == 0) {
2774 		hud_gauge->initBitmaps(fname);
2775 		hud_gauge->initBlipRadius(Radar_blip_radius_normal, Radar_blip_radius_target);
2776 		hud_gauge->initCenterOffsets(Radar_center_offsets[0], Radar_center_offsets[1]);
2777 		hud_gauge->initDistanceInfinityOffsets(Radar_dist_offsets[2][0], Radar_dist_offsets[2][1]);
2778 		hud_gauge->initDistanceLongOffsets(Radar_dist_offsets[1][0], Radar_dist_offsets[1][1]);
2779 		hud_gauge->initDistanceShortOffsets(Radar_dist_offsets[0][0], Radar_dist_offsets[0][1]);
2780 		hud_gauge->initRadius(Radar_radius[0], Radar_radius[1]);
2781 		hud_gauge->initInfinityIcon();
2782 
2783 		gauge_assign_common(settings, std::move(hud_gauge));
2784 	}
2785 }
2786 
load_gauge_radar_orb(gauge_settings * settings)2787 void load_gauge_radar_orb(gauge_settings* settings)
2788 {
2789 	int Radar_blip_radius_normal;
2790 	int Radar_blip_radius_target;
2791 	int Radar_radius[2];
2792 	int Radar_dist_offsets[RR_MAX_RANGES][2];
2793 	float Radar_center_offsets[2];
2794 	char fname[MAX_FILENAME_LEN];
2795 
2796 	settings->origin[0] = 0.5f;
2797 	settings->origin[1] = 1.0f;
2798 
2799 	if(gr_screen.res == GR_640) {
2800 		settings->offset[0] = -63;
2801 		settings->offset[1] = -111;
2802 
2803 		Radar_blip_radius_normal = 2;
2804 		Radar_blip_radius_target = 5;
2805 
2806 		Radar_center_offsets[0] = 65.0f;
2807 		Radar_center_offsets[1] = 53.0f;
2808 
2809 		Radar_radius[0] = 120;
2810 		Radar_radius[1] = 100;
2811 
2812 		Radar_dist_offsets[0][0]=110;
2813 		Radar_dist_offsets[0][1]=92;
2814 
2815 		Radar_dist_offsets[1][0]=107;
2816 		Radar_dist_offsets[1][1]=92;
2817 
2818 		Radar_dist_offsets[2][0]=111;
2819 		Radar_dist_offsets[2][1]=92;
2820 
2821 		strcpy_s(fname, "radar1");
2822 	} else {
2823 		settings->offset[0] = -101;
2824 		settings->offset[1] = -178;
2825 
2826 		Radar_blip_radius_normal = 4;
2827 		Radar_blip_radius_target = 8;
2828 
2829 		Radar_center_offsets[0] = 104.0f;
2830 		Radar_center_offsets[1] = 85.0f;
2831 
2832 		Radar_radius[0] = 192;
2833 		Radar_radius[1] = 160;
2834 
2835 		Radar_dist_offsets[0][0]=184;
2836 		Radar_dist_offsets[0][1]=150;
2837 
2838 		Radar_dist_offsets[1][0]=181;
2839 		Radar_dist_offsets[1][1]=150;
2840 
2841 		Radar_dist_offsets[2][0]=185;
2842 		Radar_dist_offsets[2][1]=150;
2843 
2844 		strcpy_s(fname, "2_radar1");
2845 	}
2846 
2847 	auto hud_gauge = gauge_load_common<HudGaugeRadarOrb>(settings);
2848 
2849 	if(optional_string("Filename:")) {
2850 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
2851 	}
2852 	if(optional_string("Radar Center Offsets:")) {
2853 		stuff_float_list(Radar_center_offsets, 2);
2854 	}
2855 	if(optional_string("Radar Size:")) {
2856 		stuff_int_list(Radar_radius, 2);
2857 	}
2858 	if(optional_string("Infinity Distance Offsets:")) {
2859 		stuff_int_list(Radar_dist_offsets[2], 2);
2860 	}
2861 	if(optional_string("Long Distance Offsets:")) {
2862 		stuff_int_list(Radar_dist_offsets[1], 2);
2863 	}
2864 	if(optional_string("Short Distance Offsets:")) {
2865 		stuff_int_list(Radar_dist_offsets[0], 2);
2866 	}
2867 
2868 	//only load this if the user actually wants to use the orb radar.
2869 	if (Cmdline_orb_radar == 1) {
2870 		hud_gauge->initBitmaps(fname);
2871 		hud_gauge->initBlipRadius(Radar_blip_radius_normal, Radar_blip_radius_target);
2872 		hud_gauge->initCenterOffsets(Radar_center_offsets[0], Radar_center_offsets[1]);
2873 		hud_gauge->initDistanceInfinityOffsets(Radar_dist_offsets[2][0], Radar_dist_offsets[2][1]);
2874 		hud_gauge->initDistanceLongOffsets(Radar_dist_offsets[1][0], Radar_dist_offsets[1][1]);
2875 		hud_gauge->initDistanceShortOffsets(Radar_dist_offsets[0][0], Radar_dist_offsets[0][1]);
2876 		hud_gauge->initRadius(Radar_radius[0], Radar_radius[1]);
2877 		hud_gauge->initInfinityIcon();
2878 
2879 		gauge_assign_common(settings, std::move(hud_gauge));
2880 	}
2881 }
2882 
2883 /**
2884  * BSG style DRADIS as used by Diaspora
2885  * Unfortunately, I can't see how to make this fit the gauge_load_common function
2886  */
load_gauge_radar_dradis(gauge_settings * settings)2887 void load_gauge_radar_dradis(gauge_settings* settings)
2888 {
2889 	// basic radar gauge info
2890 	int Radar_radius[2];
2891 
2892 	// bitmap filenames for the effect
2893 	char xy_fname[MAX_FILENAME_LEN] = "dradis_xy";
2894 	char xz_yz_fname[MAX_FILENAME_LEN] = "dradis_xz_yz";
2895 	char sweep_fname[MAX_FILENAME_LEN] = "dradis_sweep";
2896 	char target_fname[MAX_FILENAME_LEN] = "dradis_target";
2897 	char unknown_fname[MAX_FILENAME_LEN] = "dradis_unknown";
2898 
2899 	// render to texture parameters
2900 	char display_name[MAX_FILENAME_LEN] = "";
2901 	int display_offset[2] = {0, 0};
2902 	int display_size[2] = {0, 0};
2903 	int canvas_size[2] = {0, 0};
2904 
2905 	gamesnd_id loop_snd;
2906 	float loop_snd_volume = 1.0f;
2907 
2908 	gamesnd_id arrival_beep_snd;
2909 	gamesnd_id departure_beep_snd;
2910 
2911 	gamesnd_id stealth_arrival_snd;
2912 	gamesnd_id stealth_departure_snd;
2913 
2914 	float arrival_beep_delay = 0.0f;
2915 	float departure_beep_delay = 0.0f;
2916 
2917 	settings->origin[0] = 0.5f;
2918 	settings->origin[1] = 1.0f;
2919 
2920 	if(gr_screen.res == GR_640) {
2921 		settings->offset[0] = -89;
2922 		settings->offset[1] = -148;
2923 	} else {
2924 		settings->offset[0] = -143;
2925 		settings->offset[1] = -237;
2926 	}
2927 
2928 	Radar_radius[0] = 281;
2929 	Radar_radius[1] = 233;
2930 
2931 	if(check_base_res(settings->base_res)) {
2932 		if(optional_string("Position:")) {
2933 			stuff_int_list(settings->coords, 2);
2934 			settings->use_coords = true;
2935 		} else {
2936 			if (optional_string("Scale Gauge:")) {
2937 				stuff_boolean(&settings->scale_gauge);
2938 			}
2939 
2940 			if (optional_string("Force Scaling Above:")) {
2941 				stuff_int_list(settings->force_scaling_above_res, 2);
2942 			}
2943 
2944 			adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
2945 
2946 			if(optional_string("Origin:")) {
2947 				stuff_float_list(settings->origin, 2);
2948 
2949 				required_string("Offset:");
2950 				stuff_int_list(settings->offset, 2);
2951 			}
2952 
2953 			if(optional_string("Offset:")) {
2954 				Error(LOCATION, "HUD gauges table: Offset must also have Origin defined");
2955 			}
2956 
2957 			settings->coords[0] = (int)(settings->base_res[0] * settings->origin[0]) + settings->offset[0];
2958 			settings->coords[1] = (int)(settings->base_res[1] * settings->origin[1]) + settings->offset[1];
2959 			settings->use_coords = true;
2960 		}
2961 	} else {
2962 		if(gr_screen.res == GR_640) {
2963 			settings->base_res[0] = 640;
2964 			settings->base_res[1] = 480;
2965 		} else {
2966 			settings->base_res[0] = 1024;
2967 			settings->base_res[1] = 768;
2968 		}
2969 
2970 		adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
2971 
2972 		settings->coords[0] = (int)(settings->base_res[0] * settings->origin[0]) + settings->offset[0];
2973 		settings->coords[1] = (int)(settings->base_res[1] * settings->origin[1]) + settings->offset[1];
2974 		settings->use_coords = true;
2975 	}
2976 
2977 	if (optional_string("Font:")) {
2978 		settings->font_num = font::parse_font();
2979 	} else {
2980 		if ( settings->font_num < 0 ) {
2981 			settings->font_num = font::FONT1;
2982 		}
2983 	}
2984 
2985 	if(optional_string("Size:")) {
2986 		stuff_int_list(Radar_radius, 2);
2987 	}
2988 	if(optional_string("XY Disc Filename:")) {
2989 		stuff_string(xy_fname, F_NAME, MAX_FILENAME_LEN);
2990 	}
2991 	if(optional_string("XZ YZ Disc Filename:")) {
2992 		stuff_string(xz_yz_fname, F_NAME, MAX_FILENAME_LEN);
2993 	}
2994 	if(optional_string("Sweep Disc Filename:")) {
2995 		stuff_string(sweep_fname, F_NAME, MAX_FILENAME_LEN);
2996 	}
2997 	if(optional_string("Default Contact Filename:")) {
2998 		stuff_string(target_fname, F_NAME, MAX_FILENAME_LEN);
2999 	}
3000 	if(optional_string("Unknown Contact Filename:")) {
3001 		stuff_string(unknown_fname, F_NAME, MAX_FILENAME_LEN);
3002 	}
3003 	if(optional_string("Cockpit Target:") && settings->ship_idx->at(0) >= 0) {
3004 		stuff_string(display_name, F_NAME, MAX_FILENAME_LEN);
3005 
3006 		if(optional_string("Canvas Size:")) {
3007 			stuff_int_list(canvas_size, 2);
3008 		}
3009 
3010 		if ( optional_string("Display Offset:") ) {
3011 			stuff_int_list(display_offset, 2);
3012 		}
3013 
3014 		required_string("Display Size:");
3015 		stuff_int_list(display_size, 2);
3016 	} else {
3017 		// adjust for multimonitor setups ONLY if not rendering gauge to a texture
3018 		adjust_for_multimonitor(settings->base_res, true, settings->coords);
3019 	}
3020 
3021 	parse_game_sound("Loop Sound:", &loop_snd);
3022 
3023 	if (optional_string("Loop Volume:"))
3024 	{
3025 		stuff_float(&loop_snd_volume);
3026 
3027 		if (loop_snd_volume <= 0.0f)
3028 		{
3029 			Warning(LOCATION, "\"Loop Volume:\" value of \"%f\" is invalid! Must be more than zero! Resetting to default.", arrival_beep_delay);
3030 			loop_snd_volume = 1.0f;
3031 		}
3032 	}
3033 
3034 	parse_game_sound("Arrival Beep Sound:", &arrival_beep_snd);
3035 	parse_game_sound("Stealth arrival Beep Sound:", &stealth_arrival_snd);
3036 
3037 	if (optional_string("Minimum Beep Delay:"))
3038 	{
3039 		stuff_float(&arrival_beep_delay);
3040 
3041 		if (arrival_beep_delay < 0.0f)
3042 		{
3043 			Warning(LOCATION, "\"Minimum Beep Delay:\" value of \"%f\" is invalid! Must be more than or equal to zero! Resetting to default.", arrival_beep_delay);
3044 			arrival_beep_delay = 0.0f;
3045 		}
3046 	}
3047 
3048 	parse_game_sound("Departure Beep Sound:", &departure_beep_snd);
3049 	parse_game_sound("Stealth departure Beep Sound:", &stealth_departure_snd);
3050 
3051 	if (optional_string("Minimum Beep Delay:"))
3052 	{
3053 		stuff_float(&departure_beep_delay);
3054 
3055 		if (departure_beep_delay < 0.0f)
3056 		{
3057 			Warning(LOCATION, "\"Minimum Beep Delay:\" value of \"%f\" is invalid! Must be more than or equal to zero! Resetting to default.", departure_beep_delay);
3058 			departure_beep_delay = 0.0f;
3059 		}
3060 	}
3061 
3062 	std::unique_ptr<HudGaugeRadarDradis> hud_gauge(new HudGaugeRadarDradis());
3063 	hud_gauge->initBaseResolution(settings->base_res[0], settings->base_res[1]);
3064 	hud_gauge->initPosition(settings->coords[0], settings->coords[1]);
3065 	hud_gauge->initRadius(Radar_radius[0], Radar_radius[1]);
3066 	hud_gauge->initBitmaps(xy_fname, xz_yz_fname, sweep_fname, target_fname, unknown_fname);
3067 	hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
3068 	hud_gauge->initFont(settings->font_num);
3069 	hud_gauge->initSound(loop_snd, loop_snd_volume, arrival_beep_snd, departure_beep_snd, stealth_arrival_snd, stealth_departure_snd, arrival_beep_delay, departure_beep_delay);
3070 	hud_gauge->initChase_view_only(settings->chase_view_only);
3071 
3072 	gauge_assign_common(settings, std::move(hud_gauge));
3073 }
3074 
load_gauge_text_warnings(gauge_settings * settings)3075 void load_gauge_text_warnings(gauge_settings* settings)
3076 {
3077 	settings->origin[0] = 0.5f;
3078 	settings->origin[1] = 0.5f;
3079 	settings->slew = true;
3080 
3081 	if(gr_screen.res == GR_640) {
3082 		settings->offset[0] = 0;
3083 		settings->offset[1] = -68;
3084 	} else {
3085 		settings->offset[0] = 0;
3086 		settings->offset[1] = -109;
3087 	}
3088 
3089 	auto hud_gauge = gauge_load_common<HudGaugeTextWarnings>(settings);
3090 
3091 	gauge_assign_common(settings, std::move(hud_gauge));
3092 }
3093 
load_gauge_target_monitor(gauge_settings * settings)3094 void load_gauge_target_monitor(gauge_settings* settings)
3095 {
3096 	int Viewport_size[2];
3097 	int Viewport_offsets[2];
3098 	int Integrity_bar_offsets[2];
3099 	int Integrity_bar_h;
3100 	int Status_offsets[2];
3101 	int Name_offsets[2];
3102 	int Class_offsets[2];
3103 	int Dist_offsets[2];
3104 	int Speed_offsets[2];
3105 	int Cargo_string_offsets[2];
3106 	int Hull_offsets[2];
3107 	int Cargo_scan_start_offsets[2];
3108 	int Cargo_scan_size[2];
3109 
3110 	int Subsys_name_offsets[2] = {0, 0};
3111 	bool Use_subsys_name_offsets = false;
3112 
3113 	int Subsys_integrity_offsets[2] = {0, 0};
3114 	bool Use_subsys_integrity_offsets = false;
3115 
3116 	int Disabled_status_offsets[2] = {0, 0};
3117 	bool Use_disabled_status_offsets = false;
3118 
3119 	bool desaturate = false;
3120 
3121 	char fname_monitor[MAX_FILENAME_LEN] = "targetview1";
3122 	char fname_integrity[MAX_FILENAME_LEN] = "targetview2";
3123 	char fname_static[MAX_FILENAME_LEN] = "TargetStatic";
3124 	char fname_monitor_mask[MAX_FILENAME_LEN] = "";
3125 
3126 	settings->origin[0] = 0.0f;
3127 	settings->origin[1] = 1.0f;
3128 
3129 	if(gr_screen.res == GR_640) {
3130 		settings->offset[0] = 5;
3131 		settings->offset[1] = -161;
3132 	} else {
3133 		settings->offset[0] = 5;
3134 		settings->offset[1] = -178;
3135 	}
3136 
3137 	Viewport_size[0] = 131;
3138 	Viewport_size[1] = 112;
3139 	Viewport_offsets[0] = 3;
3140 	Viewport_offsets[1] = 39;
3141 
3142 	Integrity_bar_offsets[0] = 133;
3143 	Integrity_bar_offsets[1] = 52;
3144 	Integrity_bar_h = 88;
3145 	Status_offsets[0] = 107;
3146 	Status_offsets[1] = 53;
3147 
3148 	Name_offsets[0] = 8;
3149 	Name_offsets[1] = -3;
3150 	Class_offsets[0] = 8;
3151 	Class_offsets[1] = 7;
3152 	Dist_offsets[0] = 8;
3153 	Dist_offsets[1] = 18;
3154 	Speed_offsets[0] = 85;
3155 	Speed_offsets[1] = 18;
3156 	Cargo_string_offsets[0] = 8;
3157 	Cargo_string_offsets[1] = 30;
3158 
3159 	// remember, below coords describe the rightmost position of their respective sub-element, not leftmost like it usually does.
3160 	Hull_offsets[0] = 134;
3161 	Hull_offsets[1] = 42;
3162 
3163 	Cargo_scan_start_offsets[0] = 2;
3164 	Cargo_scan_start_offsets[1] = 45;
3165 	Cargo_scan_size[0] = 130;
3166 	Cargo_scan_size[1] = 109;
3167 
3168 	auto hud_gauge = gauge_load_common<HudGaugeTargetBox>(settings);
3169 
3170 	if(optional_string("Monitor Filename:")) {
3171 		stuff_string(fname_monitor, F_NAME, MAX_FILENAME_LEN);
3172 	}
3173 	if(optional_string("Monitor Alpha Mask Filename:")) {
3174 		stuff_string(fname_monitor_mask, F_NAME, MAX_FILENAME_LEN);
3175 	}
3176 	if(optional_string("Integrity Bar Filename:")) {
3177 		stuff_string(fname_integrity, F_NAME, MAX_FILENAME_LEN);
3178 	}
3179 	if(optional_string("Viewport Offsets:")) {
3180 		stuff_int_list(Viewport_offsets, 2);
3181 	}
3182 	if(optional_string("Viewport Size:")) {
3183 		stuff_int_list(Viewport_size, 2);
3184 	}
3185 	if(optional_string("Integrity Bar Offsets:")) {
3186 		stuff_int_list(Integrity_bar_offsets, 2);
3187 	}
3188 	if(optional_string("Integrity Bar Foreground Clip Height:")) {
3189 		stuff_int(&Integrity_bar_h);
3190 	}
3191 	if(optional_string("Status Offsets:")) {
3192 		stuff_int_list(Status_offsets, 2);
3193 	}
3194 	if(optional_string("Name Offsets:")) {
3195 		stuff_int_list(Name_offsets, 2);
3196 	}
3197 	if(optional_string("Class Offsets:")) {
3198 		stuff_int_list(Class_offsets, 2);
3199 	}
3200 	if(optional_string("Distance Offsets:")) {
3201 		stuff_int_list(Dist_offsets, 2);
3202 	}
3203 	if(optional_string("Speed Offsets:")) {
3204 		stuff_int_list(Speed_offsets, 2);
3205 	}
3206 	if(optional_string("Hull Offsets:")) {
3207 		stuff_int_list(Hull_offsets, 2);
3208 	}
3209 	if(optional_string("Cargo Contents Offsets:")) {
3210 		stuff_int_list(Cargo_string_offsets, 2);
3211 	}
3212 	if(optional_string("Cargo Scan Start Offsets:")) {
3213 		stuff_int_list(Cargo_scan_start_offsets, 2);
3214 	}
3215 	if(optional_string("Cargo Scan Size:")) {
3216 		stuff_int_list(Cargo_scan_size, 2);
3217 	}
3218 	if ( optional_string("Subsystem Name Offsets:") ) {
3219 		stuff_int_list(Subsys_name_offsets, 2);
3220 		Use_subsys_name_offsets = true;
3221 	}
3222 	if ( optional_string("Subsystem Integrity Offsets:") ) {
3223 		stuff_int_list(Subsys_integrity_offsets, 2);
3224 		Use_subsys_integrity_offsets = true;
3225 	}
3226 	if ( optional_string("Disabled Status Offsets:") ) {
3227 		stuff_int_list(Disabled_status_offsets, 2);
3228 		Use_disabled_status_offsets = true;
3229 	}
3230 	if ( optional_string("Desaturate:") ) {
3231 		stuff_boolean(&desaturate);
3232 	}
3233 
3234 	hud_gauge->initViewportOffsets(Viewport_offsets[0], Viewport_offsets[1]);
3235 	hud_gauge->initViewportSize(Viewport_size[0], Viewport_size[1]);
3236 	hud_gauge->initIntegrityOffsets(Integrity_bar_offsets[0], Integrity_bar_offsets[1]);
3237 	hud_gauge->initIntegrityHeight(Integrity_bar_h);
3238 	hud_gauge->initStatusOffsets(Status_offsets[0], Status_offsets[1]);
3239 	hud_gauge->initNameOffsets(Name_offsets[0], Name_offsets[1]);
3240 	hud_gauge->initClassOffsets(Class_offsets[0], Class_offsets[1]);
3241 	hud_gauge->initDistOffsets(Dist_offsets[0], Dist_offsets[1]);
3242 	hud_gauge->initSpeedOffsets(Speed_offsets[0], Speed_offsets[1]);
3243 	hud_gauge->initCargoStringOffsets(Cargo_string_offsets[0], Cargo_string_offsets[1]);
3244 	hud_gauge->initHullOffsets(Hull_offsets[0], Hull_offsets[1]);
3245 	hud_gauge->initCargoScanStartOffsets(Cargo_scan_start_offsets[0], Cargo_scan_start_offsets[1]);
3246 	hud_gauge->initCargoScanSize(Cargo_scan_size[0], Cargo_scan_size[1]);
3247 	hud_gauge->initSubsysNameOffsets(Subsys_name_offsets[0], Subsys_name_offsets[1], Use_subsys_name_offsets);
3248 	hud_gauge->initSubsysIntegrityOffsets(Subsys_integrity_offsets[0], Subsys_integrity_offsets[1], Use_subsys_integrity_offsets);
3249 	hud_gauge->initDisabledStatusOffsets(Disabled_status_offsets[0], Disabled_status_offsets[1], Use_disabled_status_offsets);
3250 	hud_gauge->initDesaturate(desaturate);
3251 	hud_gauge->initBitmaps(fname_monitor, fname_monitor_mask, fname_integrity, fname_static);
3252 
3253 	gauge_assign_common(settings, std::move(hud_gauge));
3254 }
3255 
load_gauge_squad_message(gauge_settings * settings)3256 void load_gauge_squad_message(gauge_settings* settings)
3257 {
3258 	int Pgup_offsets[2];
3259 	int Pgdn_offsets[2];
3260 	int Header_offsets[2];
3261 	int Item_start_offsets[2];
3262 	int Middle_frame_start_offset_y;
3263 	int bottom_bg_offset = 0;
3264 	int Item_h;
3265 	int Item_offset_x;
3266 	char fname_top[MAX_FILENAME_LEN] = "message1";
3267 	char fname_middle[MAX_FILENAME_LEN] = "message2";
3268 	char fname_bottom[MAX_FILENAME_LEN] = "message3";
3269 
3270 	settings->origin[0] = 1.0f;
3271 	settings->origin[1] = 0.0f;
3272 
3273 	if(gr_screen.res == GR_640) {
3274 		settings->offset[0] = -195;
3275 		settings->offset[1] = 5;
3276 
3277 		Pgup_offsets[0] = 145;
3278 		Pgup_offsets[1] = 4;
3279 		Pgdn_offsets[0] = 145;
3280 		Pgdn_offsets[1] = 115;
3281 	} else {
3282 		settings->offset[0] = -197;
3283 		settings->offset[1] = 5;
3284 
3285 		Pgup_offsets[0] = 110;
3286 		Pgup_offsets[1] = 5;
3287 		Pgdn_offsets[0] = 110;
3288 		Pgdn_offsets[1] = 115;
3289 	}
3290 
3291 	Header_offsets[0] = 2;
3292 	Header_offsets[1] = 1;
3293 	Item_start_offsets[0] = 4;
3294 	Item_start_offsets[1] = 13;
3295 	Middle_frame_start_offset_y = 12;
3296 	Item_h = 10;
3297 	Item_offset_x = 17;
3298 
3299 	auto hud_gauge = gauge_load_common<HudGaugeSquadMessage>(settings);
3300 
3301 	if(optional_string("Top Background Filename:")) {
3302 		stuff_string(fname_top, F_NAME, MAX_FILENAME_LEN);
3303 	}
3304 	if(optional_string("Entry Background Filename:")) {
3305 		stuff_string(fname_middle, F_NAME, MAX_FILENAME_LEN);
3306 	}
3307 	if(optional_string("Bottom Background Filename:")) {
3308 		stuff_string(fname_bottom, F_NAME, MAX_FILENAME_LEN);
3309 	}
3310 	if(optional_string("Header Offsets:")) {
3311 		stuff_int_list(Header_offsets, 2);
3312 	}
3313 	if(optional_string("List Start Offsets:")) {
3314 		stuff_int_list(Item_start_offsets, 2);
3315 	}
3316 	if(optional_string("Top Background Height:")) {
3317 		stuff_int(&Middle_frame_start_offset_y);
3318 	}
3319 	if(optional_string("Entry Height:")) {
3320 		stuff_int(&Item_h);
3321 	}
3322 	if(optional_string("Bottom Background Offset:")) {
3323 		stuff_int(&bottom_bg_offset);
3324 	}
3325 	if(optional_string("Command X-offset:")) {
3326 		stuff_int(&Item_offset_x);
3327 	}
3328 	if(optional_string("Page Up Offsets:")) {
3329 		stuff_int_list(Pgup_offsets, 2);
3330 	}
3331 	if(optional_string("Page Down Offsets:")) {
3332 		stuff_int_list(Pgdn_offsets, 2);
3333 	}
3334 
3335 	hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
3336 	hud_gauge->initHeaderOffsets(Header_offsets[0], Header_offsets[1]);
3337 	hud_gauge->initItemStartOffsets(Item_start_offsets[0], Item_start_offsets[1]);
3338 	hud_gauge->initMiddleFrameStartOffsetY(Middle_frame_start_offset_y);
3339 	hud_gauge->initBottomBgOffset(bottom_bg_offset);
3340 	hud_gauge->initItemHeight(Item_h);
3341 	hud_gauge->initItemOffsetX(Item_offset_x);
3342 	hud_gauge->initPgUpOffsets(Pgup_offsets[0], Pgup_offsets[1]);
3343 	hud_gauge->initPgDnOffsets(Pgdn_offsets[0], Pgdn_offsets[1]);
3344 
3345 	gauge_assign_common(settings, std::move(hud_gauge));
3346 }
3347 
load_gauge_objective_notify(gauge_settings * settings)3348 void load_gauge_objective_notify(gauge_settings* settings)
3349 {
3350 	int Objective_text_offset_y;
3351 	int Objective_text_val_offset_y;
3352 	int Subspace_text_offset_y;
3353 	int Subspace_text_val_offset_y;
3354 	int Red_text_offset_y;
3355 	int Red_text_val_offset_y;
3356 	char fname[MAX_FILENAME_LEN] = "objective1";
3357 
3358 	settings->origin[0] = 0.5f;
3359 	settings->origin[1] = 0.5f;
3360 
3361 	if(gr_screen.res == GR_640) {
3362 		settings->offset[0] = -75;
3363 		settings->offset[1] = -126;
3364 
3365 		Objective_text_offset_y = 2;
3366 		Objective_text_val_offset_y = 11;
3367 		Subspace_text_offset_y = 2;
3368 		Subspace_text_val_offset_y = 10;
3369 		Red_text_offset_y = 2;
3370 		Red_text_val_offset_y = 10;
3371 	} else {
3372 		settings->offset[0] = -76;
3373 		settings->offset[1] = -200;
3374 
3375 		Objective_text_offset_y = 2;
3376 		Objective_text_val_offset_y = 11;
3377 		Subspace_text_offset_y = 2;
3378 		Subspace_text_val_offset_y = 10;
3379 		Red_text_offset_y = 2;
3380 		Red_text_val_offset_y = 10;
3381 	}
3382 
3383 	auto hud_gauge = gauge_load_common<HudGaugeObjectiveNotify>(settings);
3384 
3385 	if(optional_string("Filename:")) {
3386 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
3387 	}
3388 	if(optional_string("Objective Text Y-offset:")) {
3389 		stuff_int(&Objective_text_offset_y);
3390 	}
3391 	if(optional_string("Objective Value Y-offset:")) {
3392 		stuff_int(&Objective_text_val_offset_y);
3393 	}
3394 	if(optional_string("Subspace Text Y-offset:")) {
3395 		stuff_int(&Subspace_text_offset_y);
3396 	}
3397 	if(optional_string("Subspace Value Y-offset:")) {
3398 		stuff_int(&Subspace_text_val_offset_y);
3399 	}
3400 	if(optional_string("Red Alert Text Y-offset:")) {
3401 		stuff_int(&Red_text_offset_y);
3402 	}
3403 	if(optional_string("Red Alert Value Y-offset:")) {
3404 		stuff_int(&Red_text_val_offset_y);
3405 	}
3406 
3407 	hud_gauge->initBitmaps(fname);
3408 	hud_gauge->initObjTextOffsetY(Objective_text_offset_y);
3409 	hud_gauge->initObjValueOffsetY(Objective_text_val_offset_y);
3410 	hud_gauge->initSubspaceTextOffsetY(Subspace_text_offset_y);
3411 	hud_gauge->initSubspaceValueOffsetY(Subspace_text_val_offset_y);
3412 	hud_gauge->initRedAlertTextOffsetY(Red_text_offset_y);
3413 	hud_gauge->initRedAlertValueOffsetY(Red_text_val_offset_y);
3414 
3415 	gauge_assign_common(settings, std::move(hud_gauge));
3416 }
3417 
load_gauge_weapons(gauge_settings * settings)3418 void load_gauge_weapons(gauge_settings* settings)
3419 {
3420 	int top_offset_x[NUM_HUD_SETTINGS];
3421 	int Weapon_header_offsets[NUM_HUD_SETTINGS][2];
3422 	int frame_offset_x[NUM_HUD_SETTINGS];
3423 	int Weapon_plink_offset_x;
3424 	int Weapon_pname_offset_x;
3425 	int Weapon_pammo_offset_x;
3426 	int Weapon_sammo_offset_x;
3427 	int Weapon_sname_offset_x;
3428 	int Weapon_sreload_offset_x;
3429 	int Weapon_slinked_offset_x;
3430 	int Weapon_sunlinked_offset_x;
3431 	int top_primary_h;
3432 	int top_secondary_h;
3433 	int pname_start_offset_y;
3434 	int sname_start_offset_y;
3435 	int primary_text_h;
3436 	int secondary_text_h;
3437 
3438 	// thank god both GR640 and GR1024 use the same weapons gauge bitmaps
3439 	char fname_p_top[MAX_FILENAME_LEN] = "weapons1";
3440 	char fname_p_top_b[MAX_FILENAME_LEN] = "weapons1_b";
3441 	char fname_p_middle[MAX_FILENAME_LEN] = "weapons2";
3442 	char fname_p_middle_b[MAX_FILENAME_LEN] = "weapons2_b";
3443 	char fname_p_last[MAX_FILENAME_LEN] = "weapons6";
3444 	// The bottom portion of the primary weapons listing for the ballistic ammo version of this gauge can simply use the middle portion.
3445 	char fname_p_last_b[MAX_FILENAME_LEN] = "weapons2_b";
3446 	char fname_s_top[MAX_FILENAME_LEN] = "weapons3";
3447 	char fname_s_top_b[MAX_FILENAME_LEN] = "weapons3_b";
3448 	char fname_s_middle[MAX_FILENAME_LEN] = "weapons4";
3449 	char fname_s_middle_b[MAX_FILENAME_LEN] = "weapons4_b";
3450 	char fname_s_bottom[MAX_FILENAME_LEN] = "weapons5";
3451 	char fname_s_bottom_b[MAX_FILENAME_LEN] = "weapons5_b";
3452 
3453 	settings->origin[0] = 1.0f;
3454 	settings->origin[1] = 1.0f;
3455 
3456 	if(gr_screen.res == GR_640) {
3457 		settings->offset[0] = -143;
3458 		settings->offset[1] = -228;
3459 	} else {
3460 		settings->offset[0] = -144;
3461 		settings->offset[1] = -257;
3462 	}
3463 
3464 	top_offset_x[0] = 12;
3465 	top_offset_x[1] = -12;
3466 
3467 	Weapon_header_offsets[0][0] = 21;
3468 	Weapon_header_offsets[0][1] = 2;
3469 	Weapon_header_offsets[1][0] = -10;
3470 	Weapon_header_offsets[1][1] = 2;
3471 
3472 	frame_offset_x[0] = 0;
3473 	frame_offset_x[1] = -12;
3474 
3475 	Weapon_plink_offset_x = 33;
3476 	Weapon_pname_offset_x = 39;
3477 	Weapon_pammo_offset_x = 28;
3478 	Weapon_sammo_offset_x = 28;
3479 	Weapon_sname_offset_x = 39;
3480 	Weapon_sreload_offset_x = 118;
3481 	Weapon_slinked_offset_x = 28;
3482 	Weapon_sunlinked_offset_x = 33;
3483 
3484 	top_primary_h = 20;
3485 	top_secondary_h = 12;
3486 	pname_start_offset_y = 12;
3487 	sname_start_offset_y = 4;
3488 
3489 	primary_text_h = 12;
3490 	secondary_text_h = 9;
3491 
3492 	auto hud_gauge = gauge_load_common<HudGaugeWeapons>(settings);
3493 
3494 	if(optional_string("Primary List Top Background Filename:")) {
3495 		stuff_string(fname_p_top, F_NAME, MAX_FILENAME_LEN);
3496 		if(optional_string("Alt Ballistic Filename:")) {
3497 			stuff_string(fname_p_top_b, F_NAME, MAX_FILENAME_LEN);
3498 		}
3499 	}
3500 	if(optional_string("Primary List Middle Background Filename:")) {
3501 		stuff_string(fname_p_middle, F_NAME, MAX_FILENAME_LEN);
3502 		if(optional_string("Alt Ballistic Filename:")) {
3503 			stuff_string(fname_p_middle_b, F_NAME, MAX_FILENAME_LEN);
3504 		}
3505 	}
3506 	if(optional_string("Primary List Bottom Background Filename:")) {
3507 		stuff_string(fname_p_last, F_NAME, MAX_FILENAME_LEN);
3508 		if(optional_string("Alt Ballistic Filename:")) {
3509 			stuff_string(fname_p_last_b, F_NAME, MAX_FILENAME_LEN);
3510 		}
3511 	}
3512 	if(optional_string("Secondary List Top Background Filename:")) {
3513 		stuff_string(fname_s_top, F_NAME, MAX_FILENAME_LEN);
3514 		if(optional_string("Alt Ballistic Filename:")) {
3515 			stuff_string(fname_s_top_b, F_NAME, MAX_FILENAME_LEN);
3516 		}
3517 	}
3518 	if(optional_string("Secondary List Entry Background Filename:")) {
3519 		stuff_string(fname_s_middle, F_NAME, MAX_FILENAME_LEN);
3520 		if(optional_string("Alt Ballistic Filename:")) {
3521 			stuff_string(fname_s_middle_b, F_NAME, MAX_FILENAME_LEN);
3522 		}
3523 	}
3524 	if(optional_string("Secondary List Bottom Background Filename:")) {
3525 		stuff_string(fname_s_bottom, F_NAME, MAX_FILENAME_LEN);
3526 		if(optional_string("Alt Ballistic Filename:")) {
3527 			stuff_string(fname_s_bottom_b, F_NAME, MAX_FILENAME_LEN);
3528 		}
3529 	}
3530 	if(optional_string("Header Offsets:")) {
3531 		stuff_int_list(Weapon_header_offsets[0], 2);
3532 		if(optional_string("Alt Ballistic Offsets:")) {
3533 			stuff_int_list(Weapon_header_offsets[1], 2);
3534 		}
3535 	}
3536 	if(optional_string("Top Primary Background X-offset:")) {
3537 		stuff_int(&top_offset_x[0]);
3538 		if(optional_string("Alt Ballistic X-offset:")) {
3539 			stuff_int(&top_offset_x[1]);
3540 		}
3541 	}
3542 	if(optional_string("Text X-offset:")) {
3543 		stuff_int(&frame_offset_x[0]);
3544 		if(optional_string("Alt Ballistic X-offset:")) {
3545 			stuff_int(&frame_offset_x[1]);
3546 		}
3547 	}
3548 	if(optional_string("Top Primary Frame Height:")) {
3549 		stuff_int(&top_primary_h);
3550 	}
3551 	if(optional_string("Top Secondary Frame Height:")) {
3552 		stuff_int(&top_secondary_h);
3553 	}
3554 	if(optional_string("Primary List Start Y-offset:")) {
3555 		stuff_int(&pname_start_offset_y);
3556 	}
3557 	if(optional_string("Secondary List Start Y-offset:")) {
3558 		stuff_int(&sname_start_offset_y);
3559 	}
3560 	if(optional_string("Primary Weapon Ammo X-offset:")) {
3561 		stuff_int(&Weapon_pammo_offset_x);
3562 	}
3563 	if(optional_string("Primary Weapon Link X-offset:")) {
3564 		stuff_int(&Weapon_plink_offset_x);
3565 	}
3566 	if(optional_string("Primary Weapon Name X-offset:")) {
3567 		stuff_int(&Weapon_pname_offset_x);
3568 	}
3569 	if(optional_string("Secondary Weapon Ammo X-offset:")) {
3570 		stuff_int(&Weapon_sammo_offset_x);
3571 	}
3572 	if(optional_string("Secondary Weapon Unlinked X-offset:")) {
3573 		stuff_int(&Weapon_sunlinked_offset_x);
3574 	}
3575 	if(optional_string("Secondary Weapon Linked X-offset:")) {
3576 		stuff_int(&Weapon_slinked_offset_x);
3577 	}
3578 	if(optional_string("Secondary Weapon Name X-offset:")) {
3579 		stuff_int(&Weapon_sname_offset_x);
3580 	}
3581 	if(optional_string("Secondary Weapon Reload X-offset:")) {
3582 		stuff_int(&Weapon_sreload_offset_x);
3583 	}
3584 	if(optional_string("Primary Weapon Entry Height:")) {
3585 		stuff_int(&primary_text_h);
3586 	}
3587 	if(optional_string("Secondary Weapon Entry Height:")) {
3588 		stuff_int(&secondary_text_h);
3589 	}
3590 
3591 	hud_gauge->initBitmapsPrimaryTop(fname_p_top, fname_p_top_b);
3592 	hud_gauge->initBitmapsPrimaryMiddle(fname_p_middle, fname_p_middle_b);
3593 	hud_gauge->initBitmapsPrimaryLast(fname_p_last, fname_p_last_b);
3594 	hud_gauge->initBitmapsSecondaryTop(fname_s_top, fname_s_top_b);
3595 	hud_gauge->initBitmapsSecondaryMiddle(fname_s_middle, fname_s_middle_b);
3596 	hud_gauge->initBitmapsSecondaryBottom(fname_s_bottom, fname_s_bottom_b);
3597 	hud_gauge->initTopOffsetX(top_offset_x[0], top_offset_x[1]);
3598 	hud_gauge->initHeaderOffsets(Weapon_header_offsets[0][0], Weapon_header_offsets[0][1],
3599 		Weapon_header_offsets[1][0], Weapon_header_offsets[1][1]);
3600 	hud_gauge->initFrameOffsetX(frame_offset_x[0], frame_offset_x[1]);
3601 	hud_gauge->initStartNameOffsetsY(pname_start_offset_y, sname_start_offset_y);
3602 	hud_gauge->initPrimaryWeaponOffsets(Weapon_plink_offset_x, Weapon_pname_offset_x, Weapon_pammo_offset_x);
3603 	hud_gauge->initSecondaryWeaponOffsets(Weapon_sammo_offset_x, Weapon_sname_offset_x, Weapon_sreload_offset_x, Weapon_slinked_offset_x, Weapon_sunlinked_offset_x);
3604 	hud_gauge->initPrimaryHeights(top_primary_h, primary_text_h);
3605 	hud_gauge->initSecondaryHeights(top_secondary_h, secondary_text_h);
3606 	hud_gauge->initLinkIcon();
3607 
3608 	gauge_assign_common(settings, std::move(hud_gauge));
3609 }
3610 
load_gauge_directives(gauge_settings * settings)3611 void load_gauge_directives(gauge_settings* settings)
3612 {
3613 	int header_offsets[2];
3614 	int middle_frame_offset_y;
3615 	int text_start_offsets[2];
3616 	int text_h;
3617 	int max_line_width = 167;
3618 	char fname_top[MAX_FILENAME_LEN] = "directives1";
3619 	char fname_middle[MAX_FILENAME_LEN] = "directives2";
3620 	char fname_bottom[MAX_FILENAME_LEN] = "directives3";
3621 	int bottom_bg_offset = 0;
3622 
3623 	settings->origin[0] = 0.0f;
3624 	settings->origin[1] = 0.5f;
3625 
3626 	if(gr_screen.res == GR_640) {
3627 		settings->offset[0] = 5;
3628 		settings->offset[1] = -62;
3629 	} else {
3630 		settings->offset[0] = 5;
3631 		settings->offset[1] = -106;
3632 	}
3633 
3634 	header_offsets[0] = 2;
3635 	header_offsets[1] = 2;
3636 	middle_frame_offset_y = 12;
3637 	text_start_offsets[0] = 3;
3638 	text_start_offsets[1] = 14;
3639 	text_h = 9;
3640 
3641 	auto hud_gauge = gauge_load_common<HudGaugeDirectives>(settings);
3642 
3643 	if(optional_string("Top Background Filename:")) {
3644 		stuff_string(fname_top, F_NAME, MAX_FILENAME_LEN);
3645 	}
3646 	if(optional_string("Entry Background Filename:")) {
3647 		stuff_string(fname_middle, F_NAME, MAX_FILENAME_LEN);
3648 	}
3649 	if(optional_string("Bottom Background Filename:")) {
3650 		stuff_string(fname_bottom, F_NAME, MAX_FILENAME_LEN);
3651 	}
3652 	if(optional_string("Header Offsets:")) {
3653 		stuff_int_list(header_offsets, 2);
3654 	}
3655 	if(optional_string("Top Background Height:")) {
3656 		stuff_int(&middle_frame_offset_y);
3657 	}
3658 	if(optional_string("List Start Offsets:")) {
3659 		stuff_int_list(text_start_offsets, 2);
3660 	}
3661 	if(optional_string("Entry Height:")) {
3662 		stuff_int(&text_h);
3663 	}
3664 	if(optional_string("Bottom Background Offset:")) {
3665 		stuff_int(&bottom_bg_offset);
3666 	}
3667 	if ( optional_string("Max Line Width:") ) {
3668 		stuff_int(&max_line_width);
3669 	}
3670 
3671 	hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
3672 	hud_gauge->initMiddleFrameOffsetY(middle_frame_offset_y);
3673 	hud_gauge->initTextHeight(text_h);
3674 	hud_gauge->initBottomBgOffset(bottom_bg_offset);
3675 	hud_gauge->initTextStartOffsets(text_start_offsets[0], text_start_offsets[1]);
3676 	hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
3677 	hud_gauge->initMaxLineWidth(max_line_width);
3678 
3679 	gauge_assign_common(settings, std::move(hud_gauge));
3680 }
3681 
load_gauge_talking_head(gauge_settings * settings)3682 void load_gauge_talking_head(gauge_settings* settings)
3683 {
3684 	int Header_offsets[2];
3685 	int Anim_offsets[2];
3686 	int Anim_size[2];
3687 	char fname[MAX_FILENAME_LEN] = "head1";
3688 
3689 	settings->origin[0] = 0.0f;
3690 	settings->origin[1] = 0.0f;
3691 
3692 	if(gr_screen.res == GR_640) {
3693 		settings->offset[0] = 5;
3694 		settings->offset[1] = 35;
3695 	} else {
3696 		settings->offset[0] = 5;
3697 		settings->offset[1] = 56;
3698 	}
3699 
3700 	Header_offsets[0] = 2;
3701 	Header_offsets[1] = 2;
3702 	Anim_offsets[0] = 2;
3703 	Anim_offsets[1] = 10;
3704 	Anim_size[0] = 160;
3705 	Anim_size[1] = 120;
3706 
3707 	auto hud_gauge = gauge_load_common<HudGaugeTalkingHead>(settings);
3708 
3709 	if(optional_string("Filename:")) {
3710 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
3711 	}
3712 	if(optional_string("Header Offsets:")) {
3713 		stuff_int_list(Header_offsets, 2);
3714 	}
3715 	if(optional_string("Animation Offsets:")) {
3716 		stuff_int_list(Anim_offsets, 2);
3717 	}
3718 	if(optional_string("Animation Background Size:")) {
3719 		mprintf(("Animation Background Size in hud_gauges.tbl and -hdg.tbms is deprecated. Use \"Animation Size\" instead.\n"));
3720 		stuff_int_list(Anim_size, 2);
3721 	}
3722 	if(optional_string("Animation Size:")) {
3723 		stuff_int_list(Anim_size, 2);
3724 	}
3725 
3726 	hud_gauge->initAnimOffsets(Anim_offsets[0], Anim_offsets[1]);
3727 	hud_gauge->initAnimSizes(Anim_size[0], Anim_size[1]);
3728 	hud_gauge->initBitmaps(fname);
3729 	hud_gauge->initHeaderOffsets(Header_offsets[0], Header_offsets[1]);
3730 
3731 	gauge_assign_common(settings, std::move(hud_gauge));
3732 }
3733 
load_gauge_countermeasures(gauge_settings * settings)3734 void load_gauge_countermeasures(gauge_settings* settings)
3735 {
3736 	int cm_text_offset[2];
3737 	int cm_text_val_offset[2];
3738 	char fname[MAX_FILENAME_LEN] = "countermeasure1";
3739 
3740 	settings->origin[0] = 1.0f;
3741 	settings->origin[1] = 1.0f;
3742 
3743 	if(gr_screen.res == GR_640) {
3744 		settings->offset[0] = -143;
3745 		settings->offset[1] = -137;
3746 	} else {
3747 		settings->offset[0] = -144;
3748 		settings->offset[1] = -166;
3749 	}
3750 	cm_text_offset[0] = 36;
3751 	cm_text_offset[1] = 4;
3752 	cm_text_val_offset[0] = 9;
3753 	cm_text_val_offset[1] = 4;
3754 
3755 	auto hud_gauge = gauge_load_common<HudGaugeCmeasures>(settings);
3756 
3757 	if(optional_string("Filename:")) {
3758 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
3759 	}
3760 	if(optional_string("Text Offsets:")) {
3761 		stuff_int_list(cm_text_offset, 2);
3762 	}
3763 	if(optional_string("Value Offsets:")) {
3764 		stuff_int_list(cm_text_val_offset, 2);
3765 	}
3766 
3767 	hud_gauge->initBitmaps(fname);
3768 	hud_gauge->initCountTextOffsets(cm_text_offset[0], cm_text_offset[1]);
3769 	hud_gauge->initCountValueOffsets(cm_text_val_offset[0], cm_text_val_offset[1]);
3770 
3771 	gauge_assign_common(settings, std::move(hud_gauge));
3772 }
3773 
load_gauge_auto_target(gauge_settings * settings)3774 void load_gauge_auto_target(gauge_settings* settings)
3775 {
3776 	int auto_text_offset[2];
3777 	int target_text_offset[2];
3778 	char fname[MAX_FILENAME_LEN] = "toggle1";
3779 
3780 	int on_color[4] = {0, 0, 0, 255};
3781 	int off_color[4] = {-1, -1, -1, -1};
3782 
3783 	settings->origin[0] = 1.0f;
3784 	settings->origin[1] = 1.0f;
3785 
3786 	if(gr_screen.res == GR_640) {
3787 		settings->offset[0] = -63;
3788 		settings->offset[1] = -100;
3789 	} else {
3790 		settings->offset[0] = -64;
3791 		settings->offset[1] = -120;
3792 	}
3793 
3794 	auto_text_offset[0] = 13;
3795 	auto_text_offset[1] = 2;
3796 	if (Lcl_pl) {
3797 		target_text_offset[0] = 2;
3798 		target_text_offset[1] = 10;
3799 	} else {
3800 		target_text_offset[0] = 7;
3801 		target_text_offset[1] = 10;
3802 	}
3803 
3804 	auto hud_gauge = gauge_load_common<HudGaugeAutoTarget>(settings);
3805 
3806 	if(optional_string("Filename:")) {
3807 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
3808 	}
3809 	if(optional_string("Auto Offsets:")) {
3810 		stuff_int_list(auto_text_offset, 2);
3811 	}
3812 	if(optional_string("Target Offsets:")) {
3813 		stuff_int_list(target_text_offset, 2);
3814 	}
3815 
3816 	if ( optional_string("On Text Color:") ) {
3817 		stuff_int_list(on_color, 4);
3818 	}
3819 
3820 	if ( optional_string("Off Text Color:") ) {
3821 		stuff_int_list(off_color, 4);
3822 	}
3823 
3824 	hud_gauge->initAutoTextOffsets(auto_text_offset[0], auto_text_offset[1]);
3825 	hud_gauge->initBitmaps(fname);
3826 	hud_gauge->initTargetTextOffsets(target_text_offset[0], target_text_offset[1]);
3827 	hud_gauge->initOnColor(on_color[0], on_color[1], on_color[2], on_color[3]);
3828 	hud_gauge->initOffColor(off_color[0], off_color[1], off_color[2], off_color[3]);
3829 
3830 	gauge_assign_common(settings, std::move(hud_gauge));
3831 }
3832 
load_gauge_auto_speed(gauge_settings * settings)3833 void load_gauge_auto_speed(gauge_settings* settings)
3834 {
3835 	int auto_text_offset[2];
3836 	int speed_text_offset[2];
3837 	char fname[MAX_FILENAME_LEN] = "toggle1";
3838 	int on_color[4] = {0, 0, 0, 255};
3839 	int off_color[4] = {-1, -1, -1, -1};
3840 
3841 	settings->origin[0] = 1.0f;
3842 	settings->origin[1] = 1.0f;
3843 
3844 	if(gr_screen.res == GR_640) {
3845 		settings->offset[0] = -63;
3846 		settings->offset[1] = -76;
3847 	} else {
3848 		settings->offset[0] = -64;
3849 		settings->offset[1] = -96;
3850 	}
3851 
3852 	auto_text_offset[0] = 13;
3853 	auto_text_offset[1] = 2;
3854 	if (Lcl_pl) {
3855 		speed_text_offset[0] = 9;
3856 		speed_text_offset[1] = 10;
3857 	} else {
3858 		speed_text_offset[0] = 10;
3859 		speed_text_offset[1] = 10;
3860 	}
3861 
3862 	auto hud_gauge = gauge_load_common<HudGaugeAutoSpeed>(settings);
3863 
3864 	if(optional_string("Filename:")) {
3865 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
3866 	}
3867 	if(optional_string("Auto Offsets:")) {
3868 		stuff_int_list(auto_text_offset, 2);
3869 	}
3870 	if(optional_string("Speed Offsets:")) {
3871 		stuff_int_list(speed_text_offset, 2);
3872 	}
3873 
3874 	if ( optional_string("On Text Color:") ) {
3875 		stuff_int_list(on_color, 4);
3876 	}
3877 
3878 	if ( optional_string("Off Text Color:") ) {
3879 		stuff_int_list(off_color, 4);
3880 	}
3881 
3882 	hud_gauge->initAutoTextOffsets(auto_text_offset[0], auto_text_offset[1]);
3883 	hud_gauge->initBitmaps(fname);
3884 	hud_gauge->initSpeedTextOffsets(speed_text_offset[0], speed_text_offset[1]);
3885 	hud_gauge->initOnColor(on_color[0], on_color[1], on_color[2], on_color[3]);
3886 	hud_gauge->initOffColor(off_color[0], off_color[1], off_color[2], off_color[3]);
3887 
3888 	gauge_assign_common(settings, std::move(hud_gauge));
3889 }
3890 
load_gauge_wingman_status(gauge_settings * settings)3891 void load_gauge_wingman_status(gauge_settings* settings)
3892 {
3893 	int header_offsets[2];
3894 	bool fixed_header_position;
3895 	int left_frame_end_x;
3896 
3897 	int single_wing_offsets[2];
3898 	int multiple_wing_offsets[2];
3899 	int wing_width;
3900 	int right_bg_offset = 0;
3901 	int wing_name_offsets[2];
3902 
3903 	int wingmate_offsets[MAX_SHIPS_PER_WING][2];
3904 	char fname_left[MAX_FILENAME_LEN] = "wingman1";
3905 	char fname_middle[MAX_FILENAME_LEN] = "wingman2";
3906 	char fname_right[MAX_FILENAME_LEN] = "wingman3";
3907 	char fname_dots[MAX_FILENAME_LEN] = "wingman4";
3908 	// "wingman5" isn't used anymore since Goober implemented string based wing names
3909 
3910 	settings->origin[0] = 1.0f;
3911 	settings->origin[1] = 0.0f;
3912 
3913 	if(gr_screen.res == GR_640) {
3914 		settings->offset[0] = -90;
3915 		settings->offset[1] = 144;
3916 	} else {
3917 		settings->offset[0] = -92;
3918 		settings->offset[1] = 144;
3919 	}
3920 
3921 	header_offsets[0] = 2;
3922 	header_offsets[1] = 2;
3923 	fixed_header_position = false;
3924 	left_frame_end_x = 71;
3925 
3926 	single_wing_offsets[0] = 28;
3927 	single_wing_offsets[1] = 15;
3928 	multiple_wing_offsets[0] = 46;
3929 	multiple_wing_offsets[1] = 15;
3930 	wing_width = 35;
3931 	wing_name_offsets[0] = 15;
3932 	wing_name_offsets[1] = 26;
3933 
3934 	wingmate_offsets[0][0] = 11;
3935 	wingmate_offsets[0][1] = 0;
3936 	wingmate_offsets[1][0] = 4;
3937 	wingmate_offsets[1][1] = 8;
3938 	wingmate_offsets[2][0] = 18;
3939 	wingmate_offsets[2][1] = 8;
3940 	wingmate_offsets[3][0] = 11;
3941 	wingmate_offsets[3][1] = 16;
3942 	wingmate_offsets[4][0] = 0;
3943 	wingmate_offsets[4][1] = 16;
3944 	wingmate_offsets[5][0] = 22;
3945 	wingmate_offsets[5][1] = 16;
3946 
3947 	auto hud_gauge = gauge_load_common<HudGaugeWingmanStatus>(settings);
3948 
3949 	if(optional_string("Left Background Filename:")) {
3950 		stuff_string(fname_left, F_NAME, MAX_FILENAME_LEN);
3951 	}
3952 	if(optional_string("First Background Filename:")) {
3953 		stuff_string(fname_left, F_NAME, MAX_FILENAME_LEN);
3954 	}
3955 	if(optional_string("Entry Background Filename:")) {
3956 		stuff_string(fname_middle, F_NAME, MAX_FILENAME_LEN);
3957 	}
3958 	if(optional_string("Right Background Filename:") || optional_string("Last Background Filename:")) {
3959 		stuff_string(fname_right, F_NAME, MAX_FILENAME_LEN);
3960 	}
3961 	if(optional_string("Dot Filename:")) {
3962 		stuff_string(fname_dots, F_NAME, MAX_FILENAME_LEN);
3963 	}
3964 	if(optional_string("Header Offsets:")) {
3965 		stuff_int_list(header_offsets, 2);
3966 	}
3967 	if(optional_string("Fixed Header Position:")) {
3968 		stuff_boolean(&fixed_header_position);
3969 	}
3970 	if(optional_string("Left Background Width:")) {
3971 		stuff_int(&left_frame_end_x);
3972 	}
3973 	if(optional_string("First Background Size:")) {
3974 		stuff_int(&left_frame_end_x);
3975 	}
3976 	if(optional_string("Entry Width:")) {
3977 		stuff_int(&wing_width);
3978 	}
3979 	if(optional_string("Entry Size:")) {
3980 		stuff_int(&wing_width);
3981 	}
3982 	if(optional_string("Right Background Offset:") || optional_string("Last Background Offset:")) {
3983 		stuff_int(&right_bg_offset);
3984 	}
3985 	if(optional_string("Single Wing Offsets:")) {
3986 		stuff_int_list(single_wing_offsets, 2);
3987 	}
3988 	if(optional_string("Multiple Wing Start Offsets:")) {
3989 		stuff_int_list(multiple_wing_offsets, 2);
3990 	}
3991 	if(optional_string("Wing Name Offsets:")) {
3992 		stuff_int_list(wing_name_offsets, 2);
3993 	}
3994 	if(optional_string("Dot Offsets:")) {
3995 		stuff_int_list(wingmate_offsets[0], 2);
3996 		stuff_int_list(wingmate_offsets[1], 2);
3997 		stuff_int_list(wingmate_offsets[2], 2);
3998 		stuff_int_list(wingmate_offsets[3], 2);
3999 		stuff_int_list(wingmate_offsets[4], 2);
4000 		stuff_int_list(wingmate_offsets[5], 2);
4001 	}
4002 
4003 	int grow_mode = 0; //By default, expand the gauge to the left (in -x direction)
4004 
4005 	if(optional_string("Expansion Mode:")) {
4006 		if(optional_string("Right"))
4007 			grow_mode = 1;
4008 		else if(optional_string("Down"))
4009 			grow_mode = 2;
4010 	}
4011 
4012 	hud_gauge->initBitmaps(fname_left, fname_middle, fname_right, fname_dots);
4013 	hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
4014 	hud_gauge->initFixedHeaderPosition(fixed_header_position);
4015 	hud_gauge->initLeftFrameEndX(left_frame_end_x);
4016 	hud_gauge->initMultipleWingOffsets(multiple_wing_offsets[0], multiple_wing_offsets[1]);
4017 	hud_gauge->initSingleWingOffsets(single_wing_offsets[0], single_wing_offsets[1]);
4018 	hud_gauge->initWingmate1Offsets(wingmate_offsets[0][0], wingmate_offsets[0][1]);
4019 	hud_gauge->initWingmate2Offsets(wingmate_offsets[1][0],	wingmate_offsets[1][1]);
4020 	hud_gauge->initWingmate3Offsets(wingmate_offsets[2][0],	wingmate_offsets[2][1]);
4021 	hud_gauge->initWingmate4Offsets(wingmate_offsets[3][0],	wingmate_offsets[3][1]);
4022 	hud_gauge->initWingmate5Offsets(wingmate_offsets[4][0],	wingmate_offsets[4][1]);
4023 	hud_gauge->initWingmate6Offsets(wingmate_offsets[5][0], wingmate_offsets[5][1]);
4024 	hud_gauge->initWingNameOffsets(wing_name_offsets[0], wing_name_offsets[1]);
4025 	hud_gauge->initWingWidth(wing_width);
4026 	hud_gauge->initRightBgOffset(right_bg_offset);
4027 	hud_gauge->initGrowMode(grow_mode);
4028 
4029 	gauge_assign_common(settings, std::move(hud_gauge));
4030 }
4031 
load_gauge_damage(gauge_settings * settings)4032 void load_gauge_damage(gauge_settings* settings)
4033 {
4034 	int header_offsets[2];
4035 	int hull_integ_offsets[2];
4036 	int hull_integ_val_offset_x;
4037 	int middle_frame_start_offset_y;
4038 	int subsys_integ_start_offsets[2];
4039 	int subsys_integ_val_offset_x;
4040 	int bottom_bg_offset = 0;
4041 	int line_h;
4042 	char fname_top[MAX_FILENAME_LEN] = "damage1";
4043 	char fname_middle[MAX_FILENAME_LEN] = "damage2";
4044 	char fname_bottom[MAX_FILENAME_LEN] = "damage3";
4045 
4046 	settings->origin[0] = 0.5f;
4047 	settings->origin[1] = 0.0f;
4048 
4049 	if(gr_screen.res == GR_640) {
4050 		settings->offset[0] = -75;
4051 		settings->offset[1] = 38;
4052 	} else {
4053 		settings->offset[0] = -72;
4054 		settings->offset[1] = 61;
4055 	}
4056 	header_offsets[0] = 3;
4057 	header_offsets[1] = 2;
4058 	hull_integ_offsets[0] = 4;
4059 	hull_integ_offsets[1] = 15;
4060 	hull_integ_val_offset_x = 142;
4061 	middle_frame_start_offset_y = 25;
4062 	subsys_integ_start_offsets[0] = 4;
4063 	subsys_integ_start_offsets[1] = 27;
4064 	subsys_integ_val_offset_x = 142;
4065 	line_h = 9;
4066 
4067 	auto hud_gauge = gauge_load_common<HudGaugeDamage>(settings);
4068 
4069 	if(optional_string("Top Background Filename:")) {
4070 		stuff_string(fname_top, F_NAME, MAX_FILENAME_LEN);
4071 	}
4072 	if(optional_string("Entry Background Filename:")) {
4073 		stuff_string(fname_middle, F_NAME, MAX_FILENAME_LEN);
4074 	}
4075 	if(optional_string("Bottom Background Filename:")) {
4076 		stuff_string(fname_bottom, F_NAME, MAX_FILENAME_LEN);
4077 	}
4078 	if(optional_string("Header Offsets:")) {
4079 		stuff_int_list(header_offsets, 2);
4080 	}
4081 	if(optional_string("Hull Integrity Offsets:")) {
4082 		stuff_int_list(hull_integ_offsets, 2);
4083 	}
4084 	if(optional_string("Hull Integrity Value X-offset:")) {
4085 		stuff_int(&hull_integ_val_offset_x);
4086 	}
4087 	if(optional_string("Top Background Height:")) {
4088 		stuff_int(&middle_frame_start_offset_y);
4089 	}
4090 	if(optional_string("Subsystem Entry Height:")) {
4091 		stuff_int(&line_h);
4092 	}
4093 	if(optional_string("Subsystem List Start Offsets:")) {
4094 		stuff_int_list(subsys_integ_start_offsets, 2);
4095 	}
4096 	if(optional_string("Subsystem Entry Value X-offset:")) {
4097 		stuff_int(&subsys_integ_val_offset_x);
4098 	}
4099 	if(optional_string("Bottom Background Offset:")) {
4100 		stuff_int(&bottom_bg_offset);
4101 	}
4102 
4103 	hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
4104 	hud_gauge->initHullIntegOffsets(hull_integ_offsets[0], hull_integ_offsets[1]);
4105 	hud_gauge->initHullIntegValueOffsetX(hull_integ_val_offset_x);
4106 	hud_gauge->initLineHeight(line_h);
4107 	hud_gauge->initMiddleFrameStartOffsetY(middle_frame_start_offset_y);
4108 	hud_gauge->initSubsysIntegStartOffsets(subsys_integ_start_offsets[0], subsys_integ_start_offsets[1]);
4109 	hud_gauge->initSubsysIntegValueOffsetX(subsys_integ_val_offset_x);
4110 	hud_gauge->initBottomBgOffset(bottom_bg_offset);
4111 	hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
4112 
4113 	gauge_assign_common(settings, std::move(hud_gauge));
4114 }
4115 
load_gauge_support(gauge_settings * settings)4116 void load_gauge_support(gauge_settings* settings)
4117 {
4118 	int header_offsets[2];
4119 	int text_val_offset_y;
4120 	int text_dock_offset_x;
4121 	int text_dock_val_offset_x;
4122 	char fname[MAX_FILENAME_LEN] = "support1";
4123 
4124 	settings->origin[0] = 0.5f;
4125 	settings->origin[1] = 0.5f;
4126 
4127 	if(gr_screen.res == GR_640) {
4128 		settings->offset[0] = -55;
4129 		settings->offset[1] = 94;
4130 
4131 		header_offsets[0] = 2;
4132 		header_offsets[1] = 1;
4133 		text_val_offset_y = 14;
4134 		text_dock_offset_x = 5;
4135 		text_dock_val_offset_x = 63;
4136 	} else {
4137 		settings->offset[0] = -53;
4138 		settings->offset[1] = 150;
4139 
4140 		header_offsets[0] = 3;
4141 		header_offsets[1] = 2;
4142 		text_val_offset_y = 12;
4143 		text_dock_offset_x = 6;
4144 		text_dock_val_offset_x = 65;
4145 	}
4146 
4147 	auto hud_gauge = gauge_load_common<HudGaugeSupport>(settings);
4148 
4149 	if(optional_string("Filename:")) {
4150 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
4151 	}
4152 	if(optional_string("Header Offsets:")) {
4153 		stuff_int_list(header_offsets, 2);
4154 	}
4155 	if(optional_string("Text Y-offset:")) {
4156 		stuff_int(&text_val_offset_y);
4157 	}
4158 	if(optional_string("Dock Status X-offset:")) {
4159 		stuff_int(&text_dock_offset_x);
4160 	}
4161 	if(optional_string("Dock Time X-offset:")) {
4162 		stuff_int(&text_dock_val_offset_x);
4163 	}
4164 
4165 	hud_gauge->initBitmaps(fname);
4166 	hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
4167 	hud_gauge->initTextDockOffsetX(text_dock_offset_x);
4168 	hud_gauge->initTextDockValueOffsetX(text_dock_val_offset_x);
4169 	hud_gauge->initTextValueOffsetY(text_val_offset_y);
4170 
4171 	gauge_assign_common(settings, std::move(hud_gauge));
4172 }
4173 
load_gauge_training_messages(gauge_settings * settings)4174 void load_gauge_training_messages(gauge_settings* settings)
4175 {
4176 	settings->origin[0] = 0.5f;
4177 	settings->origin[1] = 0.5f;
4178 
4179 	if(gr_screen.res == GR_640) {
4180 		settings->offset[0] = -146;
4181 		settings->offset[1] = -200;
4182 	} else {
4183 		settings->offset[0] = -133;
4184 		settings->offset[1] = -259;
4185 	}
4186 
4187 	auto hud_gauge = gauge_load_common<HudGaugeTrainingMessages>(settings);
4188 
4189 	gauge_assign_common(settings, std::move(hud_gauge));
4190 }
4191 
load_gauge_messages(gauge_settings * settings)4192 void load_gauge_messages(gauge_settings* settings)
4193 {
4194 	int max_lines = 3;
4195 	int max_width;
4196 	int scroll_time = 30;
4197 	int step_size = 3;
4198 	int total_life = 14000;
4199 	int line_height = 9;
4200 	bool hidden_by_comms_menu = true;
4201 
4202 	settings->origin[0] = 0.0f;
4203 	settings->origin[1] = 0.0f;
4204 	settings->offset[0] = 8;
4205 	settings->offset[1] = 5;
4206 
4207 	if(gr_screen.res == GR_640) {
4208 		max_width = 620;
4209 	} else {
4210 		max_width = 1004;
4211 	}
4212 
4213 	auto hud_gauge = gauge_load_common<HudGaugeMessages>(settings);
4214 
4215 	if ( optional_string("Max Lines:") ) {
4216 		stuff_int(&max_lines);
4217 	}
4218 	if ( optional_string("Max Width:") ) {
4219 		stuff_int(&max_width);
4220 	}
4221 	if ( optional_string("Line Height:") ) {
4222 		stuff_int(&line_height);
4223 	}
4224 	if ( optional_string("Total Lifetime:") ) {
4225 		stuff_int(&total_life);
4226 	}
4227 	if ( optional_string("Scroll Time:") ) {
4228 		stuff_int(&scroll_time);
4229 	}
4230 	if ( optional_string("Step Size:") ) {
4231 		stuff_int(&step_size);
4232 	}
4233 	if ( optional_string("Hidden By Comms Menu:") ) {
4234 		stuff_boolean(&hidden_by_comms_menu);
4235 	}
4236 
4237 	hud_gauge->initMaxLines(max_lines);
4238 	hud_gauge->initMaxWidth(max_width);
4239 	hud_gauge->initScrollTime(scroll_time);
4240 	hud_gauge->initStepSize(step_size);
4241 	hud_gauge->initTotalLife(total_life);
4242 	hud_gauge->initLineHeight(line_height);
4243 	hud_gauge->initHiddenByCommsMenu(hidden_by_comms_menu);
4244 
4245 	gauge_assign_common(settings, std::move(hud_gauge));
4246 }
4247 
load_gauge_fixed_messages(gauge_settings * settings)4248 void load_gauge_fixed_messages(gauge_settings* settings)
4249 {
4250 	font::set_font(font::FONT1);
4251 
4252 	int h = gr_get_font_height();
4253 
4254 	bool center_text;
4255 
4256 	settings->use_coords = true;
4257 	// set both coords to INT_MIN so that it's possible to check whether a HUD table has overridden them
4258 	// (this is necessary to determine the default value for center_text)
4259 	settings->coords[0] = INT_MIN;
4260 	settings->coords[1] = INT_MIN;
4261 
4262 	auto hud_gauge = gauge_load_common<HudGaugeFixedMessages>(settings);
4263 
4264 	if(settings->coords[0] == INT_MIN && settings->coords[1] == INT_MIN) {
4265 		// coords have almost certainly not been overridden; set them to their true defaults and set center_text to true
4266 		settings->coords[0] = settings->base_res[0] / 2;
4267 		settings->coords[1] = 5 + (h * 3);
4268 		hud_gauge->initPosition(settings->coords[0], settings->coords[1]);
4269 		center_text = true;
4270 	} else {
4271 		// coords have been overridden; set center_text to false
4272 		center_text = false;
4273 	}
4274 
4275 	if(optional_string("Center Text On Gauge X-Position:")) {
4276 		stuff_boolean(&center_text);
4277 	}
4278 
4279 	hud_gauge->initCenterText(center_text);
4280 
4281 	gauge_assign_common(settings, std::move(hud_gauge));
4282 }
4283 
load_gauge_weapon_linking(gauge_settings * settings)4284 void load_gauge_weapon_linking(gauge_settings* settings)
4285 {
4286 	int Weapon_link_offsets[NUM_WEAPON_LINK_MODES][2];
4287 	char fname_arc[MAX_FILENAME_LEN];
4288 	char fname_primary_link_1[MAX_FILENAME_LEN];
4289 	char fname_primary_link_2[MAX_FILENAME_LEN];
4290 	char fname_secondary_link_1[MAX_FILENAME_LEN];
4291 	char fname_secondary_link_2[MAX_FILENAME_LEN];
4292 	char fname_secondary_link_3[MAX_FILENAME_LEN];
4293 
4294 	settings->origin[0] = 0.5f;
4295 	settings->origin[1] = 0.5f;
4296 	settings->slew = true;
4297 
4298 	if(gr_screen.res == GR_640) {
4299 		settings->offset[0] = 54;
4300 		settings->offset[1] = 2;
4301 
4302 		Weapon_link_offsets[LINK_ONE_PRIMARY][0] = 32;
4303 		Weapon_link_offsets[LINK_ONE_PRIMARY][1] = 11;
4304 		Weapon_link_offsets[LINK_TWO_PRIMARY][0] = 32;
4305 		Weapon_link_offsets[LINK_TWO_PRIMARY][1] = 11;
4306 		Weapon_link_offsets[LINK_ONE_SECONDARY][0] = 17;
4307 		Weapon_link_offsets[LINK_ONE_SECONDARY][1] = 34;
4308 		Weapon_link_offsets[LINK_TWO_SECONDARY][0] = 17;
4309 		Weapon_link_offsets[LINK_TWO_SECONDARY][1] = 34;
4310 		Weapon_link_offsets[LINK_THREE_SECONDARY][0] = 17;
4311 		Weapon_link_offsets[LINK_THREE_SECONDARY][1] = 34;
4312 
4313 		strcpy_s(fname_arc, "rightarc1_fs1");
4314 		strcpy_s(fname_primary_link_1, "rightarc2_fs1");
4315 		strcpy_s(fname_primary_link_2, "rightarc3_fs1");
4316 		strcpy_s(fname_secondary_link_1, "rightarc4_fs1");
4317 		strcpy_s(fname_secondary_link_2, "rightarc5_fs1");
4318 		strcpy_s(fname_secondary_link_3, "rightarc6_fs1");
4319 	} else {
4320 		settings->offset[0] = 86;
4321 		settings->offset[1] = 3;
4322 
4323 		Weapon_link_offsets[LINK_ONE_PRIMARY][0] = 52;
4324 		Weapon_link_offsets[LINK_ONE_PRIMARY][1] = 18;
4325 		Weapon_link_offsets[LINK_TWO_PRIMARY][0] = 52;
4326 		Weapon_link_offsets[LINK_TWO_PRIMARY][1] = 18;
4327 		Weapon_link_offsets[LINK_ONE_SECONDARY][0] = 28;
4328 		Weapon_link_offsets[LINK_ONE_SECONDARY][1] = 55;
4329 		Weapon_link_offsets[LINK_TWO_SECONDARY][0] = 28;
4330 		Weapon_link_offsets[LINK_TWO_SECONDARY][1] = 55;
4331 		Weapon_link_offsets[LINK_THREE_SECONDARY][0] = 28;
4332 		Weapon_link_offsets[LINK_THREE_SECONDARY][1] = 55;
4333 
4334 		strcpy_s(fname_arc, "2_rightarc1_fs1");
4335 		strcpy_s(fname_primary_link_1, "2_rightarc2_fs1");
4336 		strcpy_s(fname_primary_link_2, "2_rightarc3_fs1");
4337 		strcpy_s(fname_secondary_link_1, "2_rightarc4_fs1");
4338 		strcpy_s(fname_secondary_link_2, "2_rightarc5_fs1");
4339 		strcpy_s(fname_secondary_link_3, "2_rightarc6_fs1");
4340 	}
4341 
4342 	auto hud_gauge = gauge_load_common<HudGaugeWeaponLinking>(settings);
4343 
4344 	if(optional_string("Arc Filename:")) {
4345 		stuff_string(fname_arc, F_NAME, MAX_FILENAME_LEN);
4346 	}
4347 	if(optional_string("Single Primary Filename:")) {
4348 		stuff_string(fname_primary_link_1, F_NAME, MAX_FILENAME_LEN);
4349 	}
4350 	if(optional_string("Double Primary Filename:")) {
4351 		stuff_string(fname_primary_link_2, F_NAME, MAX_FILENAME_LEN);
4352 	}
4353 	if(optional_string("Single Secondary Filename:")) {
4354 		stuff_string(fname_secondary_link_1, F_NAME, MAX_FILENAME_LEN);
4355 	}
4356 	if(optional_string("Double Secondary Filename:")) {
4357 		stuff_string(fname_secondary_link_2, F_NAME, MAX_FILENAME_LEN);
4358 	}
4359 	if(optional_string("Triple Secondary Filename:")) {
4360 		stuff_string(fname_secondary_link_3, F_NAME, MAX_FILENAME_LEN);
4361 	}
4362 	if(optional_string("Single Primary Offsets:")) {
4363 		stuff_int_list(Weapon_link_offsets[LINK_ONE_PRIMARY], 2);
4364 	}
4365 	if(optional_string("Double Primary Offsets:")) {
4366 		stuff_int_list(Weapon_link_offsets[LINK_TWO_PRIMARY], 2);
4367 	}
4368 	if(optional_string("Single Secondary Offsets:")) {
4369 		stuff_int_list(Weapon_link_offsets[LINK_ONE_SECONDARY], 2);
4370 	}
4371 	if(optional_string("Double Secondary Offsets:")) {
4372 		stuff_int_list(Weapon_link_offsets[LINK_TWO_SECONDARY], 2);
4373 	}
4374 	if(optional_string("Triple Secondary Offsets:")) {
4375 		stuff_int_list(Weapon_link_offsets[LINK_THREE_SECONDARY], 2);
4376 	}
4377 
4378 	hud_gauge->init1PrimaryOffsets(Weapon_link_offsets[LINK_ONE_PRIMARY][0], Weapon_link_offsets[LINK_ONE_PRIMARY][1]);
4379 	hud_gauge->init2PrimaryOffsets(Weapon_link_offsets[LINK_TWO_PRIMARY][0], Weapon_link_offsets[LINK_TWO_PRIMARY][1]);
4380 	hud_gauge->init1SecondaryOffsets(Weapon_link_offsets[LINK_ONE_SECONDARY][0], Weapon_link_offsets[LINK_ONE_SECONDARY][1]);
4381 	hud_gauge->init2SecondaryOffsets(Weapon_link_offsets[LINK_TWO_SECONDARY][0], Weapon_link_offsets[LINK_TWO_SECONDARY][1]);
4382 	hud_gauge->init3SecondaryOffsets(Weapon_link_offsets[LINK_THREE_SECONDARY][0], Weapon_link_offsets[LINK_THREE_SECONDARY][1]);
4383 	hud_gauge->initBitmaps(fname_arc, fname_primary_link_1, fname_primary_link_2, fname_secondary_link_1, fname_secondary_link_2, fname_secondary_link_3);
4384 
4385 	gauge_assign_common(settings, std::move(hud_gauge));
4386 }
4387 
load_gauge_multi_msg(gauge_settings * settings)4388 void load_gauge_multi_msg(gauge_settings* settings)
4389 {
4390 	settings->origin[0] = 0.0f;
4391 	settings->origin[1] = 0.5f;
4392 
4393 	if(gr_screen.res == GR_640) {
4394 		settings->offset[0] = 5;
4395 		settings->offset[1] = -90;
4396 	} else {
4397 		settings->offset[0] = 8;
4398 		settings->offset[1] = -144;
4399 	}
4400 
4401 	auto hud_gauge = gauge_load_common<HudGaugeMultiMsg>(settings);
4402 
4403 	gauge_assign_common(settings, std::move(hud_gauge));
4404 }
4405 
load_gauge_voice_status(gauge_settings * settings)4406 void load_gauge_voice_status(gauge_settings* settings)
4407 {
4408 	settings->origin[0] = 0.0f;
4409 	settings->origin[1] = 0.5f;
4410 
4411 	if(gr_screen.res == GR_640) {
4412 		settings->offset[0] = 5;
4413 		settings->offset[1] = -75;
4414 	} else {
4415 		settings->offset[0] = 8;
4416 		settings->offset[1] = -129;
4417 	}
4418 
4419 	auto hud_gauge = gauge_load_common<HudGaugeVoiceStatus>(settings);
4420 
4421 	gauge_assign_common(settings, std::move(hud_gauge));
4422 }
4423 
load_gauge_ping(gauge_settings * settings)4424 void load_gauge_ping(gauge_settings* settings)
4425 {
4426 	settings->origin[0] = 1.0f;
4427 	settings->origin[1] = 0.0f;
4428 
4429 	if(gr_screen.res == GR_640) {
4430 		settings->offset[0] = -80;
4431 		settings->offset[1] = 3;
4432 	} else {
4433 		settings->offset[0] = -128;
4434 		settings->offset[1] = 5;
4435 	}
4436 
4437 	auto hud_gauge = gauge_load_common<HudGaugePing>(settings);
4438 
4439 	gauge_assign_common(settings, std::move(hud_gauge));
4440 }
4441 
load_gauge_supernova(gauge_settings * settings)4442 void load_gauge_supernova(gauge_settings* settings)
4443 {
4444 	settings->origin[0] = 0.5f;
4445 	settings->origin[1] = 0.5f;
4446 
4447 	if(gr_screen.res == GR_640) {
4448 		settings->offset[0] = -220;
4449 		settings->offset[1] = -140;
4450 	} else {
4451 		settings->offset[0] = -342;
4452 		settings->offset[1] = -214;
4453 	}
4454 
4455 	auto hud_gauge = gauge_load_common<HudGaugeSupernova>(settings);
4456 
4457 	gauge_assign_common(settings, std::move(hud_gauge));
4458 }
4459 
load_gauge_lock(gauge_settings * settings)4460 void load_gauge_lock(gauge_settings* settings)
4461 {
4462 	int Lock_gauge_half_w;
4463 	int Lock_gauge_half_h;
4464 	int Lockspin_half_w;
4465 	int Lockspin_half_h;
4466 	float Lock_triangle_height;
4467 	float Lock_triangle_base;
4468 	int Lock_target_box_width;
4469 	int Lock_target_box_height;
4470 	bool loop_locked_anim;
4471 	bool blink_locked_anim;
4472 	char fname_lock[MAX_FILENAME_LEN];
4473 	char fname_spin[MAX_FILENAME_LEN];
4474 
4475 	settings->set_position = false;
4476 	settings->set_colour = false;
4477 
4478 	if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
4479 		if(gr_screen.res == GR_640) {
4480 			Lock_gauge_half_w = 15;
4481 			Lock_gauge_half_h = 15;
4482 			Lockspin_half_w = 16;
4483 			Lockspin_half_h = 16;
4484 			Lock_triangle_height = 4.0f;
4485 			Lock_triangle_base = 4.0f;
4486 			Lock_target_box_width = 19;
4487 			Lock_target_box_height = 30;
4488 			loop_locked_anim = true;
4489 			blink_locked_anim = false;
4490 
4491 			strcpy_s(fname_lock, "lock1_fs1");
4492 			strcpy_s(fname_spin, "lockspin_fs1");
4493 		} else {
4494 			Lock_gauge_half_w = 24;
4495 			Lock_gauge_half_h = 25;
4496 			Lockspin_half_w = 26;
4497 			Lockspin_half_h = 26;
4498 			Lock_triangle_height = 6.5f;
4499 			Lock_triangle_base = 6.5f;
4500 			Lock_target_box_width = 19;
4501 			Lock_target_box_height = 30;
4502 			loop_locked_anim = true;
4503 			blink_locked_anim = false;
4504 
4505 			strcpy_s(fname_lock, "2_lock1_fs1");
4506 			strcpy_s(fname_spin, "2_lockspin_fs1");
4507 		}
4508 	} else {
4509 		if(gr_screen.res == GR_640) {
4510 			Lock_gauge_half_w = 17;
4511 			Lock_gauge_half_h = 15;
4512 			Lockspin_half_w = 31;
4513 			Lockspin_half_h = 32;
4514 			Lock_triangle_height = 4.0f;
4515 			Lock_triangle_base = 4.0f;
4516 			Lock_target_box_width = 19;
4517 			Lock_target_box_height = 30;
4518 			loop_locked_anim = false;
4519 			blink_locked_anim = true;
4520 
4521 			strcpy_s(fname_lock, "lock1");
4522 			strcpy_s(fname_spin, "lockspin");
4523 		} else {
4524 			Lock_gauge_half_w = 28;
4525 			Lock_gauge_half_h = 25;
4526 			Lockspin_half_w = 50;
4527 			Lockspin_half_h = 52;
4528 			Lock_triangle_height = 6.5f;
4529 			Lock_triangle_base = 6.5f;
4530 			Lock_target_box_width = 19;
4531 			Lock_target_box_height = 30;
4532 			loop_locked_anim = false;
4533 			blink_locked_anim = true;
4534 
4535 			strcpy_s(fname_lock, "2_lock1");
4536 			strcpy_s(fname_spin, "2_lockspin");
4537 		}
4538 	}
4539 
4540 	auto hud_gauge = gauge_load_common<HudGaugeLock>(settings);
4541 
4542 	if(optional_string("Lock Filename:")) {
4543 		stuff_string(fname_lock, F_NAME, MAX_FILENAME_LEN);
4544 	}
4545 	if(optional_string("Locked Filename:")) {
4546 		stuff_string(fname_spin, F_NAME, MAX_FILENAME_LEN);
4547 	}
4548 	if(optional_string("Lock Center Offsets:")) {
4549 		int temp[2];
4550 
4551 		stuff_int_list(temp, 2);
4552 
4553 		Lock_gauge_half_w = temp[0];
4554 		Lock_gauge_half_h = temp[1];
4555 	}
4556 	if(optional_string("Locked Center Offsets:")) {
4557 		int temp[2];
4558 
4559 		stuff_int_list(temp, 2);
4560 
4561 		Lockspin_half_w = temp[0];
4562 		Lockspin_half_h = temp[1];
4563 	}
4564 
4565 	hud_gauge->initBitmaps(fname_lock, fname_spin);
4566 	hud_gauge->initLoopLockedAnim(loop_locked_anim);
4567 	hud_gauge->initBlinkLockedAnim(blink_locked_anim);
4568 	hud_gauge->initGaugeHalfSize(Lock_gauge_half_w, Lock_gauge_half_h);
4569 	hud_gauge->initSpinHalfSize(Lockspin_half_w, Lockspin_half_h);
4570 	hud_gauge->initTriHeight(Lock_triangle_height);
4571 	hud_gauge->initTriBase(Lock_triangle_base);
4572 	hud_gauge->initTargetBoxSize(Lock_target_box_width,	Lock_target_box_height);
4573 
4574 	gauge_assign_common(settings, std::move(hud_gauge));
4575 }
4576 
load_gauge_offscreen(gauge_settings * settings)4577 void load_gauge_offscreen(gauge_settings* settings)
4578 {
4579 	float Max_offscreen_tri_seperation;
4580 	float Max_front_seperation;
4581 	float Offscreen_tri_base;
4582 	float Offscreen_tri_height;
4583 
4584 	settings->set_position = false;
4585 	settings->set_colour = false;
4586 
4587 	if(gr_screen.res == GR_640) {
4588 		Max_offscreen_tri_seperation = 10.0f;
4589 		Max_front_seperation = 10.0f;
4590 		Offscreen_tri_base = 6.0f;
4591 		Offscreen_tri_height = 7.0f;
4592 	} else {
4593 		Max_offscreen_tri_seperation = 16.0f;
4594 		Max_front_seperation = 16.0f;
4595 		Offscreen_tri_base = 9.5f;
4596 		Offscreen_tri_height = 11.0f;
4597 	}
4598 
4599 	auto hud_gauge = gauge_load_common<HudGaugeOffscreen>(settings);
4600 
4601 	hud_gauge->initMaxTriSeperation(Max_offscreen_tri_seperation);
4602 	hud_gauge->initMaxFrontSeperation(Max_front_seperation);
4603 	hud_gauge->initTriBase(Offscreen_tri_base);
4604 	hud_gauge->initTriHeight(Offscreen_tri_height);
4605 
4606 	gauge_assign_common(settings, std::move(hud_gauge));
4607 }
4608 
load_gauge_brackets(gauge_settings * settings)4609 void load_gauge_brackets(gauge_settings* settings)
4610 {
4611 	int min_target_box[2];
4612 	int min_subtarget_box[2];
4613 	char fname[MAX_FILENAME_LEN] = "attacker";
4614 
4615 	settings->set_position = false;
4616 	settings->set_colour = false;
4617 
4618 	if(gr_screen.res == GR_640) {
4619 		min_target_box[0] = 20;
4620 		min_target_box[1] = 20;
4621 		min_subtarget_box[0] = 12;
4622 		min_subtarget_box[1] = 12;
4623 	} else {
4624 		min_target_box[0] = 30;
4625 		min_target_box[1] = 30;
4626 		min_subtarget_box[0] = 24;
4627 		min_subtarget_box[1] = 24;
4628 	}
4629 
4630 	auto hud_gauge = gauge_load_common<HudGaugeBrackets>(settings);
4631 
4632 	if(optional_string("Dot Filename:")) {
4633 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
4634 	}
4635 
4636 	hud_gauge->initBitmaps(fname);
4637 	hud_gauge->initMinSubTargetBoxSizes(min_subtarget_box[0], min_subtarget_box[1]);
4638 	hud_gauge->initMinTargetBoxSizes(min_target_box[0], min_target_box[1]);
4639 
4640 	gauge_assign_common(settings, std::move(hud_gauge));
4641 }
4642 
load_gauge_hostile_tri(gauge_settings * settings)4643 void load_gauge_hostile_tri(gauge_settings* settings)
4644 {
4645 	int Radius;
4646 	float Target_triangle_base;
4647 	float Target_triangle_height;
4648 
4649 	settings->origin[0] = 0.5f;
4650 	settings->origin[1] = 0.5f;
4651 	settings->slew = true;
4652 
4653 	if(gr_screen.res == GR_640) {
4654 		settings->offset[0] = 0;
4655 		settings->offset[1] = 2;
4656 
4657 		Target_triangle_base = 6.0f;
4658 		Target_triangle_height = 7.0f;
4659 		Radius = 104;
4660 	} else {
4661 		settings->offset[0] = 0;
4662 		settings->offset[1] = 3;
4663 
4664 		Target_triangle_base = 9.5f;
4665 		Target_triangle_height = 11.0f;
4666 		Radius = 166;
4667 	}
4668 
4669 	auto hud_gauge = gauge_load_common<HudGaugeHostileTriangle>(settings);
4670 
4671 	if(optional_string("Radius:")) {
4672 		stuff_int(&Radius);
4673 	}
4674 	if(optional_string("Triangle Base:")) {
4675 		stuff_float(&Target_triangle_base);
4676 	}
4677 	if(optional_string("Triangle Height:")) {
4678 		stuff_float(&Target_triangle_height);
4679 	}
4680 
4681 	hud_gauge->initRadius(Radius);
4682 	hud_gauge->initTriBase(Target_triangle_base);
4683 	hud_gauge->initTriHeight(Target_triangle_height);
4684 
4685 	gauge_assign_common(settings, std::move(hud_gauge));
4686 }
4687 
load_gauge_target_tri(gauge_settings * settings)4688 void load_gauge_target_tri(gauge_settings* settings)
4689 {
4690 	int Radius;
4691 	float Target_triangle_base;
4692 	float Target_triangle_height;
4693 
4694 	settings->origin[0] = 0.5f;
4695 	settings->origin[1] = 0.5f;
4696 	settings->slew = true;
4697 
4698 	if(gr_screen.res == GR_640) {
4699 		settings->offset[0] = 0;
4700 		settings->offset[1] = 2;
4701 
4702 		Target_triangle_base = 6.0f;
4703 		Target_triangle_height = 7.0f;
4704 		Radius = 104;
4705 	} else {
4706 		settings->offset[0] = 0;
4707 		settings->offset[1] = 3;
4708 
4709 		Target_triangle_base = 9.5f;
4710 		Target_triangle_height = 11.0f;
4711 		Radius = 166;
4712 	}
4713 
4714 	auto hud_gauge = gauge_load_common<HudGaugeTargetTriangle>(settings);
4715 
4716 	if(optional_string("Radius:")) {
4717 		stuff_int(&Radius);
4718 	}
4719 	if(optional_string("Triangle Base:")) {
4720 		stuff_float(&Target_triangle_base);
4721 	}
4722 	if(optional_string("Triangle Height:")) {
4723 		stuff_float(&Target_triangle_height);
4724 	}
4725 
4726 	hud_gauge->initRadius(Radius);
4727 	hud_gauge->initTriBase(Target_triangle_base);
4728 	hud_gauge->initTriHeight(Target_triangle_height);
4729 
4730 	gauge_assign_common(settings, std::move(hud_gauge));
4731 }
4732 
load_gauge_missile_tri(gauge_settings * settings)4733 void load_gauge_missile_tri(gauge_settings* settings)
4734 {
4735 	int Radius;
4736 	float Target_triangle_base;
4737 	float Target_triangle_height;
4738 
4739 	settings->origin[0] = 0.5f;
4740 	settings->origin[1] = 0.5f;
4741 	settings->slew = true;
4742 
4743 	if(gr_screen.res == GR_640) {
4744 		settings->offset[0] = 0;
4745 		settings->offset[1] = 2;
4746 
4747 		Target_triangle_base = 6.0f;
4748 		Target_triangle_height = 7.0f;
4749 		Radius = 104;
4750 	} else {
4751 		settings->offset[0] = 0;
4752 		settings->offset[1] = 3;
4753 
4754 		Target_triangle_base = 9.5f;
4755 		Target_triangle_height = 11.0f;
4756 		Radius = 166;
4757 	}
4758 
4759 	auto hud_gauge = gauge_load_common<HudGaugeMissileTriangles>(settings);
4760 
4761 	if(optional_string("Radius:")) {
4762 		stuff_int(&Radius);
4763 	}
4764 	if(optional_string("Triangle Base:")) {
4765 		stuff_float(&Target_triangle_base);
4766 	}
4767 	if(optional_string("Triangle Height:")) {
4768 		stuff_float(&Target_triangle_height);
4769 	}
4770 
4771 	hud_gauge->initRadius(Radius);
4772 	hud_gauge->initTriBase(Target_triangle_base);
4773 	hud_gauge->initTriHeight(Target_triangle_height);
4774 
4775 	gauge_assign_common(settings, std::move(hud_gauge));
4776 }
4777 
load_gauge_lead(gauge_settings * settings)4778 void load_gauge_lead(gauge_settings* settings)
4779 {
4780 	float Lead_indicator_half[2];
4781 	char fname[MAX_FILENAME_LEN];
4782 
4783 	settings->set_position = false;
4784 	settings->set_colour = false;
4785 
4786 	if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
4787 		if(gr_screen.res == GR_640) {
4788 			Lead_indicator_half[0] = 12.5f;
4789 			Lead_indicator_half[1] = 12.5f;
4790 
4791 			strcpy_s(fname, "lead1_fs1");
4792 		} else {
4793 			Lead_indicator_half[0] = 20.0f;
4794 			Lead_indicator_half[1] = 20.0f;
4795 
4796 			strcpy_s(fname, "2_lead1_fs1");
4797 		}
4798 	} else {
4799 		if(gr_screen.res == GR_640) {
4800 			Lead_indicator_half[0] = 8.0f;
4801 			Lead_indicator_half[1] = 8.0f;
4802 
4803 			strcpy_s(fname, "lead1");
4804 		} else {
4805 			Lead_indicator_half[0] = 13.0f;
4806 			Lead_indicator_half[1] = 13.0f;
4807 
4808 			strcpy_s(fname, "2_lead1");
4809 		}
4810 	}
4811 
4812 	auto hud_gauge = gauge_load_common<HudGaugeLeadIndicator>(settings);
4813 
4814 	if(optional_string("Filename:")) {
4815 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
4816 	}
4817 	if(optional_string("Center Offsets:")) {
4818 		int temp[2];
4819 
4820 		stuff_int_list(temp, 2);
4821 
4822 		Lead_indicator_half[0] = i2fl(temp[0]);
4823 		Lead_indicator_half[1] = i2fl(temp[1]);
4824 	}
4825 
4826 	hud_gauge->initHalfSize(Lead_indicator_half[0], Lead_indicator_half[1]);
4827 	hud_gauge->initBitmaps(fname);
4828 
4829 	gauge_assign_common(settings, std::move(hud_gauge));
4830 }
4831 
load_gauge_orientation_tee(gauge_settings * settings)4832 void load_gauge_orientation_tee(gauge_settings* settings)
4833 {
4834 	int Radius;
4835 
4836 	settings->origin[0] = 0.5f;
4837 	settings->origin[1] = 0.5f;
4838 	settings->slew = true;
4839 
4840 	if(gr_screen.res == GR_640) {
4841 		settings->offset[0] = 0;
4842 		settings->offset[1] = 2;
4843 
4844 		Radius = 104;
4845 	} else {
4846 		settings->offset[0] = 0;
4847 		settings->offset[1] = 3;
4848 
4849 		Radius = 166;
4850 	}
4851 
4852 	auto hud_gauge = gauge_load_common<HudGaugeOrientationTee>(settings);
4853 
4854 	if(optional_string("Radius:")) {
4855 		stuff_int(&Radius);
4856 	}
4857 
4858 	hud_gauge->initRadius(Radius);
4859 
4860 	gauge_assign_common(settings, std::move(hud_gauge));
4861 }
4862 
load_gauge_lead_sight(gauge_settings * settings)4863 void load_gauge_lead_sight(gauge_settings* settings)
4864 {
4865 	char fname[MAX_FILENAME_LEN] = "leadsight";
4866 
4867 	settings->origin[0] = 0.5f;
4868 	settings->origin[1] = 0.5f;
4869 	settings->slew = true;
4870 
4871 	if(gr_screen.res == GR_640) {
4872 		settings->offset[0] = 0;
4873 		settings->offset[1] = 2;
4874 	} else {
4875 		settings->offset[0] = 0;
4876 		settings->offset[1] = 3;
4877 	}
4878 
4879 	auto hud_gauge = gauge_load_common<HudGaugeLeadSight>(settings);
4880 
4881 	if(optional_string("Filename:")) {
4882 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
4883 	}
4884 
4885 	hud_gauge->initBitmaps(fname);
4886 
4887 	gauge_assign_common(settings, std::move(hud_gauge));
4888 }
4889 
load_gauge_kills(gauge_settings * settings)4890 void load_gauge_kills(gauge_settings* settings)
4891 {
4892 	int text_offsets[2] = {6, 4};
4893 	int text_value_offsets[2] = {74, 4};
4894 	char fname[MAX_FILENAME_LEN] = "kills1";
4895 
4896 	settings->origin[0] = 1.0f;
4897 	settings->origin[1] = 1.0f;
4898 
4899 	if(gr_screen.res == GR_640) {
4900 		settings->offset[0] = -143;
4901 		settings->offset[1] = -119;
4902 
4903 		if(Lcl_gr) {
4904 			text_value_offsets[0] = 118;
4905 			text_value_offsets[1] = 4;
4906 		}
4907 	} else {
4908 		settings->offset[0] = -144;
4909 		settings->offset[1] = -144;
4910 
4911 		if(Lcl_gr) {
4912 			text_value_offsets[0] = 104;
4913 			text_value_offsets[1] = 4;
4914 		}
4915 	}
4916 
4917 	auto hud_gauge = gauge_load_common<HudGaugeKills>(settings);
4918 
4919 	if(optional_string("Filename:")) {
4920 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
4921 	}
4922 	if(optional_string("Text Offsets:")) {
4923 		stuff_int_list(text_offsets, 2);
4924 	}
4925 	if(optional_string("Value Offsets:")) {
4926 		stuff_int_list(text_value_offsets, 2);
4927 	}
4928 
4929 	hud_gauge->initBitmaps(fname);
4930 	hud_gauge->initTextOffsets(text_offsets[0], text_offsets[1]);
4931 	hud_gauge->initTextValueOffsets(text_value_offsets[0], text_value_offsets[1]);
4932 
4933 	gauge_assign_common(settings, std::move(hud_gauge));
4934 }
4935 
load_gauge_flight_path(gauge_settings * settings)4936 void load_gauge_flight_path(gauge_settings* settings)
4937 {
4938 	int Marker_half[2];
4939 	char fname[MAX_FILENAME_LEN] = "flight_path";
4940 
4941 	Marker_half[0] = 21;
4942 	Marker_half[1] = 21;
4943 
4944 	settings->set_position = false;
4945 
4946 	auto hud_gauge = gauge_load_common<HudGaugeFlightPath>(settings);
4947 
4948 	if(optional_string("Filename:")) {
4949 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
4950 	}
4951 	if(optional_string("Center Offsets:")) {
4952 		stuff_int_list(Marker_half, 2);
4953 	}
4954 
4955 	hud_gauge->initHalfSize(Marker_half[0], Marker_half[1]);
4956 	hud_gauge->initBitmap(fname);
4957 
4958 	gauge_assign_common(settings, std::move(hud_gauge));
4959 }
4960 
load_gauge_warhead_count(gauge_settings * settings)4961 void load_gauge_warhead_count(gauge_settings* settings)
4962 {
4963 	int warhead_name_offsets[2] = {6, 4};
4964 	int warhead_count_offsets[2] = {74, 4};
4965 	int icon_width = 0;
4966 	int icon_height = 0;
4967 	int max_icons = 0;
4968 	int max_columns = 0;
4969 	HudAlignment alignment = HudAlignment::NONE;
4970 	char fname[MAX_FILENAME_LEN] = "warhead_icon";
4971 
4972 	settings->origin[0] = 1.0f;
4973 	settings->origin[1] = 1.0f;
4974 	settings->slew = true;
4975 
4976 	if ( gr_screen.res == GR_640 ) {
4977 		settings->offset[0] = -143;
4978 		settings->offset[1] = -119;
4979 	} else {
4980 		settings->offset[0] = -144;
4981 		settings->offset[1] = -144;
4982 	}
4983 
4984 	auto hud_gauge = gauge_load_common<HudGaugeWarheadCount>(settings);
4985 
4986 	if ( optional_string("Filename:") ) {
4987 		stuff_string(fname, F_NAME, MAX_FILENAME_LEN);
4988 	}
4989 
4990 	if ( optional_string("Name Offsets:") ) {
4991 		stuff_int_list(warhead_name_offsets, 2);
4992 	}
4993 
4994 	if ( optional_string("Count Offsets:") ) {
4995 		stuff_int_list(warhead_count_offsets, 2);
4996 	}
4997 
4998 	if ( optional_string("Icon Width:") ) {
4999 		stuff_int(&icon_width);
5000 	}
5001 
5002 	if ( optional_string("Icon Height:") ) {
5003 		stuff_int(&icon_height);
5004 	}
5005 
5006 	if ( optional_string("Max Icons:") ) {
5007 		stuff_int(&max_icons);
5008 	}
5009 
5010 	if ( optional_string("Max Columns:") ) {
5011 		stuff_int(&max_columns);
5012 	}
5013 
5014 	if ( optional_string("Name Alignment:") ) {
5015 		char temp[NAME_LENGTH];
5016 		stuff_string(temp, F_NAME, NAME_LENGTH);
5017 		alignment = hud_alignment_lookup(temp);
5018 	}
5019 
5020 	hud_gauge->initBitmap(fname);
5021 	hud_gauge->initNameOffsets(warhead_name_offsets[0], warhead_name_offsets[1]);
5022 	hud_gauge->initCountOffsets(warhead_count_offsets[0], warhead_count_offsets[1]);
5023 	hud_gauge->initCountSizes(icon_width, icon_height);
5024 	hud_gauge->initMaxSymbols(max_icons);
5025 	hud_gauge->initMaxColumns(max_columns);
5026 	hud_gauge->initTextAlign(alignment);
5027 
5028 	gauge_assign_common(settings, std::move(hud_gauge));
5029 }
5030 
load_gauge_hardpoints(gauge_settings * settings)5031 void load_gauge_hardpoints(gauge_settings* settings)
5032 {
5033 	int sizes[2] = {150, 150};
5034 	float line_width = 1.0f;
5035 	int view_dir = HudGaugeHardpoints::TOP;
5036 	bool show_primary = false;
5037 	bool show_secondary = true;
5038 
5039 	settings->origin[0] = 1.0f;
5040 	settings->origin[1] = 1.0f;
5041 
5042 	if(gr_screen.res == GR_640) {
5043 		settings->offset[0] = -244;
5044 		settings->offset[1] = -101;
5045 	} else {
5046 		settings->offset[0] = -390;
5047 		settings->offset[1] = -98;
5048 	}
5049 
5050 	auto hud_gauge = gauge_load_common<HudGaugeHardpoints>(settings);
5051 
5052 	if ( optional_string("Size:") ) {
5053 		stuff_int_list(sizes, 2);
5054 	}
5055 
5056 	if ( optional_string("Line Width:") ) {
5057 		stuff_float(&line_width);
5058 	}
5059 
5060 	if ( optional_string("View Direction:") ) {
5061 		if ( optional_string("Top") ) {
5062 			view_dir = HudGaugeHardpoints::TOP;
5063 		} else if ( optional_string("Front") ) {
5064 			view_dir = HudGaugeHardpoints::FRONT;
5065 		}
5066 	}
5067 
5068 	if ( optional_string("Show Primary Weapons:") ) {
5069 		stuff_boolean(&show_primary);
5070 	}
5071 
5072 	if ( optional_string("Show Secondary Weapons:") ) {
5073 		stuff_boolean(&show_secondary);
5074 	}
5075 
5076 	hud_gauge->initSizes(sizes[0], sizes[1]);
5077 	hud_gauge->initLineWidth(line_width);
5078 	hud_gauge->initViewDir(view_dir);
5079 	hud_gauge->initDrawOptions(show_primary, show_secondary);
5080 
5081 	gauge_assign_common(settings, std::move(hud_gauge));
5082 }
5083 
load_gauge_primary_weapons(gauge_settings * settings)5084 void load_gauge_primary_weapons(gauge_settings* settings)
5085 {
5086 	char fname_first[MAX_FILENAME_LEN] = "weapon_list1";
5087 	char fname_entry[MAX_FILENAME_LEN] = "weapon_list2";
5088 	char fname_last[MAX_FILENAME_LEN] = "weapon_list3";
5089 	int header_offsets[2] = {2, 2};
5090 	char header_text[NAME_LENGTH] = "Primary Weapons";
5091 	int first_bg_h = 12;
5092 	int first_bg_offset_x = 0;
5093 	int entry_bg_h = 12;
5094 	int entry_bg_offset_x = 0;
5095 	int last_bg_offset_x = 0;
5096 	int last_bg_offset_y = 0;
5097 	int entry_h = 10;
5098 	int entry_start_offset_y = 12;
5099 	int ammo_x = 28;
5100 	int link_x = 33;
5101 	int name_x = 35;
5102 
5103 	auto hud_gauge = gauge_load_common<HudGaugePrimaryWeapons>(settings);
5104 
5105 	if ( optional_string("Header Offsets:") ) {
5106 		stuff_int_list(header_offsets, 2);
5107 	}
5108 
5109 	if ( optional_string("Header Text:") ) {
5110 		stuff_string(header_text, F_NAME, NAME_LENGTH);
5111 	}
5112 
5113 	if ( optional_string("First Background Filename:") ) {
5114 		stuff_string(fname_first, F_NAME, MAX_FILENAME_LEN);
5115 	}
5116 
5117 	if ( optional_string("First Background Height:") ) {
5118 		stuff_int(&first_bg_h);
5119 	}
5120 
5121 	if ( optional_string("First Background X-offset:") ) {
5122 		stuff_int(&first_bg_offset_x);
5123 	}
5124 
5125 	if ( optional_string("Entry Background Filename:") ) {
5126 		stuff_string(fname_entry, F_NAME, MAX_FILENAME_LEN);
5127 	}
5128 
5129 	if ( optional_string("Entry Background Height:") ) {
5130 		stuff_int(&entry_bg_h);
5131 	}
5132 
5133 	if ( optional_string("Entry Background X-offset:") ) {
5134 		stuff_int(&entry_bg_offset_x);
5135 	}
5136 
5137 	if ( optional_string("Last Background Filename:") ) {
5138 		stuff_string(fname_last, F_NAME, MAX_FILENAME_LEN);
5139 	}
5140 
5141 	if ( optional_string("Last Background X-offset:") ) {
5142 		stuff_int(&last_bg_offset_x);
5143 	}
5144 
5145 	if ( optional_string("Last Background Y-offset:") ) {
5146 		stuff_int(&last_bg_offset_y);
5147 	}
5148 
5149 	if ( optional_string("Entry Height:") ) {
5150 		stuff_int(&entry_h);
5151 	}
5152 
5153 	if ( optional_string("List Start Y-offset:") ) {
5154 		stuff_int(&entry_start_offset_y);
5155 	}
5156 
5157 	if ( optional_string("Ammo X-offset:") ) {
5158 		stuff_int(&ammo_x);
5159 	}
5160 
5161 	if ( optional_string("Link X-offset:") ) {
5162 		stuff_int(&link_x);
5163 	}
5164 
5165 	if ( optional_string("Name X-offset:") ) {
5166 		stuff_int(&name_x);
5167 	}
5168 
5169 	hud_gauge->initBitmaps(fname_first, fname_entry, fname_last);
5170 	hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
5171 	hud_gauge->initHeaderText(header_text);
5172 	hud_gauge->initBgFirstHeight(first_bg_h);
5173 	hud_gauge->initBgFirstOffsetX(first_bg_offset_x);
5174 	hud_gauge->initBgEntryHeight(entry_bg_h);
5175 	hud_gauge->initBgEntryOffsetX(entry_bg_offset_x);
5176 	hud_gauge->initBgLastOffsetX(last_bg_offset_x);
5177 	hud_gauge->initBgLastOffsetY(last_bg_offset_y);
5178 	hud_gauge->initEntryHeight(entry_h);
5179 	hud_gauge->initEntryStartY(entry_start_offset_y);
5180 	hud_gauge->initPrimaryAmmoOffsetX(ammo_x);
5181 	hud_gauge->initPrimaryLinkOffsetX(link_x);
5182 	hud_gauge->initPrimaryNameOffsetX(name_x);
5183 	hud_gauge->initLinkIcon();
5184 
5185 	gauge_assign_common(settings, std::move(hud_gauge));
5186 }
5187 
load_gauge_secondary_weapons(gauge_settings * settings)5188 void load_gauge_secondary_weapons(gauge_settings* settings)
5189 {
5190 	char fname_first[MAX_FILENAME_LEN] = "weapon_list1";
5191 	char fname_entry[MAX_FILENAME_LEN] = "weapon_list2";
5192 	char fname_last[MAX_FILENAME_LEN] = "weapon_list3";
5193 	int header_offsets[2] = {2, 2};
5194 	char header_text[NAME_LENGTH] = "Secondary Weapons";
5195 	int first_bg_h = 12;
5196 	int first_bg_offset_x = 0;
5197 	int entry_bg_h = 12;
5198 	int entry_bg_offset_x = 0;
5199 	int last_bg_offset_x = 0;
5200 	int last_bg_offset_y = 0;
5201 	int entry_h = 10;
5202 	int entry_start_offset_y = 12;
5203 	int ammo_x = 28;
5204 	int link_x = 28;
5205 	int name_x = 39;
5206 	int reload_x = 118;
5207 	int unlink_x = 33;
5208 
5209 	auto hud_gauge = gauge_load_common<HudGaugeSecondaryWeapons>(settings);
5210 
5211 	if ( optional_string("Header Offsets:") ) {
5212 		stuff_int_list(header_offsets, 2);
5213 	}
5214 
5215 	if ( optional_string("Header Text:") ) {
5216 		stuff_string(header_text, F_NAME, NAME_LENGTH);
5217 	}
5218 
5219 	if ( optional_string("First Background Filename:") ) {
5220 		stuff_string(fname_first, F_NAME, MAX_FILENAME_LEN);
5221 	}
5222 
5223 	if ( optional_string("First Background Height:") ) {
5224 		stuff_int(&first_bg_h);
5225 	}
5226 
5227 	if ( optional_string("First Background X-offset:") ) {
5228 		stuff_int(&first_bg_offset_x);
5229 	}
5230 
5231 	if ( optional_string("Entry Background Filename:") ) {
5232 		stuff_string(fname_entry, F_NAME, MAX_FILENAME_LEN);
5233 	}
5234 
5235 	if ( optional_string("Entry Background Height:") ) {
5236 		stuff_int(&entry_bg_h);
5237 	}
5238 
5239 	if ( optional_string("Entry Background X-offset:") ) {
5240 		stuff_int(&entry_bg_offset_x);
5241 	}
5242 
5243 	if ( optional_string("Last Background Filename:") ) {
5244 		stuff_string(fname_last, F_NAME, MAX_FILENAME_LEN);
5245 	}
5246 
5247 	if ( optional_string("Last Background X-offset:") ) {
5248 		stuff_int(&last_bg_offset_x);
5249 	}
5250 
5251 	if ( optional_string("Last Background Y-offset:") ) {
5252 		stuff_int(&last_bg_offset_y);
5253 	}
5254 
5255 	if ( optional_string("Entry Height:") ) {
5256 		stuff_int(&entry_h);
5257 	}
5258 
5259 	if ( optional_string("List Start Y-offset:") ) {
5260 		stuff_int(&entry_start_offset_y);
5261 	}
5262 
5263 	if ( optional_string("Ammo X-offset:") ) {
5264 		stuff_int(&ammo_x);
5265 	}
5266 
5267 	if ( optional_string("Link X-offset:") ) {
5268 		stuff_int(&link_x);
5269 	}
5270 
5271 	if ( optional_string("Name X-offset:") ) {
5272 		stuff_int(&name_x);
5273 	}
5274 
5275 	if ( optional_string("Unlink X-offset:") ) {
5276 		stuff_int(&unlink_x);
5277 	}
5278 
5279 	if ( optional_string("Reload X-offset:") ) {
5280 		stuff_int(&reload_x);
5281 	}
5282 
5283 	hud_gauge->initBitmaps(fname_first, fname_entry, fname_last);
5284 	hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
5285 	hud_gauge->initHeaderText(header_text);
5286 	hud_gauge->initBgFirstHeight(first_bg_h);
5287 	hud_gauge->initBgFirstOffsetX(first_bg_offset_x);
5288 	hud_gauge->initBgEntryHeight(entry_bg_h);
5289 	hud_gauge->initBgEntryOffsetX(entry_bg_offset_x);
5290 	hud_gauge->initBgLastOffsetX(last_bg_offset_x);
5291 	hud_gauge->initBgLastOffsetY(last_bg_offset_y);
5292 	hud_gauge->initEntryHeight(entry_h);
5293 	hud_gauge->initEntryStartY(entry_start_offset_y);
5294 	hud_gauge->initSecondaryAmmoOffsetX(ammo_x);
5295 	hud_gauge->initSecondaryLinkedOffsetX(link_x);
5296 	hud_gauge->initSecondaryNameOffsetX(name_x);
5297 	hud_gauge->initSecondaryReloadOffsetX(reload_x);
5298 	hud_gauge->initSecondaryUnlinkedOffsetX(unlink_x);
5299 	hud_gauge->initLinkIcon();
5300 
5301 	gauge_assign_common(settings, std::move(hud_gauge));
5302 }
5303 
load_gauge_scripting(gauge_settings * settings)5304 void load_gauge_scripting(gauge_settings* settings) {
5305 	auto hud_gauge = gauge_load_common<HudGaugeScripting>(settings);
5306 
5307 	required_string("Name:");
5308 	SCP_string name;
5309 	stuff_string(name, F_NAME);
5310 
5311 	hud_gauge->initName(name);
5312 
5313 	gauge_assign_common(settings, std::move(hud_gauge));
5314 }
5315