1
2 /* WARNING:
3 * This is magic-number central, but these numbers are set specifically
4 * to the acceptable defaults or range values that were used when the
5 * pl2/plr files were created. Standard game defines should not be used in
6 * place of these major numbers for /any/ reason, *ever*!
7 */
8
9 #include "cfile/cfilesystem.h"
10 #include "mission/missionbriefcommon.h"
11 #include "network/psnet2.h"
12 #include "pilotfile/pilotfile_convert.h"
13
14
15 // this struct isn't well packed, and is written whole to the pilot file, so
16 // we can't easily just get the RGBA that we need and instead must retain this
17 typedef struct conv_color { //-V802
18 uint screen_sig;
19 ubyte red;
20 ubyte green;
21 ubyte blue;
22 ubyte alpha;
23 ubyte ac_type;
24 int is_alphacolor;
25 ubyte raw8;
26 int alphacolor;
27 int magic;
28 } conv_color;
29
30
plr_data()31 plr_data::plr_data()
32 {
33 // not carried over, just for reference during conversion process
34 version = 0;
35 is_multi = 0;
36 lcl_get_language_name(language);
37
38 // basic flags and settings
39 tips = 0;
40 rank = 0;
41 skill_level = 1;
42 save_flags = 0;
43 readyroom_listing_mode = 0;
44 voice_enabled = 1;
45 auto_advance = 1;
46 Use_mouse_to_fly = 0;
47 Mouse_sensitivity = 4;
48 Joy_sensitivity = 9;
49 Dead_zone_size = 10;
50
51 // multiplayer settings/options
52 net_protocol = 1;
53
54 multi_squad_set = 2;
55 multi_endgame_set = 3;
56 multi_flags = 3;
57 multi_respawn = 2;
58 multi_max_observers = 2;
59 multi_skill_level = 2;
60 multi_voice_qos = 10;
61 multi_voice_token_wait = 2000;
62 multi_voice_record_time = 5000;
63 multi_time_limit = -65536;
64 multi_kill_limit = 9999;
65
66 multi_local_flags = 5;
67 multi_local_update_level = 0;
68
69 // pilot info stuff
70 memset(image_filename, 0, sizeof(image_filename));
71 memset(squad_name, 0, sizeof(squad_name));
72 memset(squad_filename, 0, sizeof(squad_filename));
73 memset(current_campaign, 0, sizeof(current_campaign));
74 memset(last_ship_flown, 0, sizeof(last_ship_flown));
75
76 // HUD config
77 hud_show_flags = -1;
78 hud_show_flags2 = 31;
79 hud_popup_flags = 0;
80 hud_popup_flags2 = 0;
81 hud_num_lines = 4;
82 hud_rp_flags = 7;
83 hud_rp_dist = 2;
84
85 for (int idx = 0; idx < 39; idx++) {
86 hud_colors[idx][0] = 0;
87 hud_colors[idx][1] = 255;
88 hud_colors[idx][2] = 0;
89 hud_colors[idx][3] = 144;
90 }
91
92 // control setup
93 joy_axis_map_to[0] = 0;
94 joy_axis_map_to[1] = 1;
95 joy_axis_map_to[2] = 3;
96 joy_invert_axis[3] = -1;
97 joy_invert_axis[4] = -1;
98
99 memset(joy_invert_axis, 0, sizeof(joy_invert_axis));
100
101 // audio
102 sound_volume = 1.0f;
103 music_volume = 0.5f;
104 voice_volume = 0.7f;
105
106 // detail settings
107 detail_setting = 3;
108 detail_nebula = 3;
109 detail_distance = 3;
110 detail_hardware_textures = 4;
111 detail_num_debris = 4;
112 detail_num_particles = 3;
113 detail_num_stars = 4;
114 detail_shield_effects = 4;
115 detail_lighting = 4;
116 detail_targetview_model = 1;
117 detail_planets_suns = 1;
118 detail_weapon_extras = 1;
119 }
120
~plr_data()121 plr_data::~plr_data()
122 {
123 controls.clear();
124 }
125
plr_import_controls()126 void pilotfile_convert::plr_import_controls()
127 {
128 int idx;
129 CCI con;
130 short buf;
131
132 unsigned char num_controls = cfread_ubyte(cfp);
133
134 if ( !num_controls ) {
135 return;
136 }
137
138 // it may be less than 118, but it shouldn't be more than 118
139 // Don't touch this magic number! This is for old playerfiles. See banner at top of this file.
140 if (num_controls > 118) {
141 throw "Data check failure in controls!";
142 }
143
144 plr->controls.reserve(num_controls);
145
146 for (idx = 0; idx < num_controls; idx++) {
147 buf = cfread_short(cfp);
148 if (buf == 255) {
149 buf = -1;
150 }
151 con.take(CC_bind(CID_KEYBOARD, buf), 0);
152
153 buf = cfread_short(cfp);
154 if (buf == 255) {
155 buf = -1;
156 }
157 con.take(CC_bind(CID_JOY0, buf), 1);
158
159 plr->controls.push_back( con );
160 }
161 }
162
plr_import_hud()163 void pilotfile_convert::plr_import_hud()
164 {
165 int idx;
166 conv_color c;
167
168 plr->hud_show_flags = cfread_int(cfp);
169 plr->hud_show_flags2 = cfread_int(cfp);
170
171 plr->hud_popup_flags = cfread_int(cfp);
172 plr->hud_popup_flags2 = cfread_int(cfp);
173
174 plr->hud_num_lines = cfread_ubyte(cfp);
175 plr->hud_rp_flags = cfread_int(cfp);
176 plr->hud_rp_dist = cfread_int(cfp);
177
178 for (idx = 0; idx < 39; idx++) {
179 cfread(&c, sizeof(conv_color), 1, cfp);
180
181 if ( (c.alphacolor != -1) || (c.is_alphacolor != 1) ) {
182 throw "Data check failure in hud!";
183 }
184
185 plr->hud_colors[idx][0] = c.red;
186 plr->hud_colors[idx][1] = c.green;
187 plr->hud_colors[idx][2] = c.blue;
188 plr->hud_colors[idx][3] = c.alpha;
189 }
190 }
191
plr_import_detail()192 void pilotfile_convert::plr_import_detail()
193 {
194 bool data_failure = false;
195
196 plr->detail_setting = cfread_int(cfp);
197 plr->detail_nebula = cfread_int(cfp);
198 plr->detail_distance = cfread_int(cfp);
199 plr->detail_hardware_textures = cfread_int(cfp);
200 plr->detail_num_debris = cfread_int(cfp);
201 plr->detail_num_particles = cfread_int(cfp);
202 plr->detail_num_stars = cfread_int(cfp);
203 plr->detail_shield_effects = cfread_int(cfp);
204 plr->detail_lighting = cfread_int(cfp);
205 plr->detail_targetview_model = cfread_int(cfp);
206 plr->detail_planets_suns = cfread_int(cfp);
207 plr->detail_weapon_extras = cfread_int(cfp);
208
209 if ( (plr->detail_setting < -1) || (plr->detail_setting > 4) ) {
210 data_failure = true;
211 } else if ( (plr->detail_nebula < 0) || (plr->detail_nebula > 4) ) {
212 data_failure = true;
213 } else if ( (plr->detail_distance < 0) || (plr->detail_distance > 4) ) {
214 data_failure = true;
215 } else if ( (plr->detail_hardware_textures < 0) || (plr->detail_hardware_textures > 4) ) {
216 data_failure = true;
217 } else if ( (plr->detail_num_debris < 0) || (plr->detail_num_debris > 4) ) {
218 data_failure = true;
219 } else if ( (plr->detail_num_particles < 0) || (plr->detail_num_particles > 4) ) {
220 data_failure = true;
221 } else if ( (plr->detail_num_stars < 0) || (plr->detail_num_stars > 4) ) {
222 data_failure = true;
223 } else if ( (plr->detail_shield_effects < 0) || (plr->detail_shield_effects > 4) ) {
224 data_failure = true;
225 } else if ( (plr->detail_lighting < 0) || (plr->detail_lighting > 4) ) {
226 data_failure = true;
227 } else if ( (plr->detail_targetview_model < 0) || (plr->detail_targetview_model > 1) ) {
228 data_failure = true;
229 } else if ( (plr->detail_planets_suns < 0) || (plr->detail_planets_suns > 1) ) {
230 data_failure = true;
231 } else if ( (plr->detail_weapon_extras < 0) || (plr->detail_weapon_extras > 1) ) {
232 data_failure = true;
233 }
234
235 if (data_failure) {
236 throw "Data check failure in details!";
237 }
238 }
239
plr_import_stats()240 void pilotfile_convert::plr_import_stats()
241 {
242 int idx;
243 char name[35];
244
245 if (fver >= 242) {
246 return;
247 }
248
249 // read everything, but we don't need any of it ...
250
251 cfread_int(cfp); // score
252 cfread_int(cfp); // rank
253 cfread_int(cfp); // assists
254
255 // medals
256 for (idx = 0; idx < 18; idx++) {
257 cfread_int(cfp);
258 }
259
260 // kills per ship
261 int count = cfread_int(cfp);
262
263 for (idx = 0; idx < count; idx++) {
264 cfread_ushort(cfp);
265 cfread_string_len(name, sizeof(name), cfp);
266 }
267
268 cfread_int(cfp); // kill_count
269 cfread_int(cfp); // kill_count_ok
270
271 cfread_uint(cfp); // p_shots_fired
272 cfread_uint(cfp); // s_shots_fired
273 cfread_uint(cfp); // p_shots_hit
274 cfread_uint(cfp); // s_shots_hit
275
276 cfread_uint(cfp); // p_bonehead_hits
277 cfread_uint(cfp); // s_bonehead_hits
278 cfread_uint(cfp); // bonehead_kills
279 }
280
plr_import_loadout()281 void pilotfile_convert::plr_import_loadout()
282 {
283 int idx, j;
284 int s_count, w_count;
285 char name[52];
286
287 if (fver >= 242) {
288 return;
289 }
290
291 // have to read it, but don't need any of it ...
292
293 cfread_string_len(name, sizeof(name), cfp); // filename
294 cfread_string_len(name, sizeof(name), cfp); // last_modified
295
296 s_count = cfread_int(cfp); // num ships
297 w_count = cfread_int(cfp); // num weapons
298
299 // ships
300 for (idx = 0; idx < s_count; idx++) {
301 cfread_int(cfp); // count
302 cfread_string_len(name, sizeof(name), cfp); // name
303 }
304
305 // weapons
306 for (idx = 0; idx < w_count; idx++) {
307 cfread_int(cfp); // count
308 cfread_string_len(name, sizeof(name), cfp); // name
309 }
310
311 // loadout info
312 for (idx = 0; idx < 12; idx++) {
313 cfread_int(cfp); // ship class
314 cfread_string_len(name, sizeof(name), cfp); // ship name
315
316 for (j = 0; j < 12; j++) {
317 cfread_int(cfp); // weapon type
318 cfread_int(cfp); // weapon count
319 cfread_string_len(name, sizeof(name), cfp); // weapon name
320 }
321 }
322 }
323
plr_import_multiplayer()324 void pilotfile_convert::plr_import_multiplayer()
325 {
326 plr->multi_squad_set = cfread_ubyte(cfp);
327 plr->multi_endgame_set = cfread_ubyte(cfp);
328 plr->multi_flags = cfread_int(cfp);
329 plr->multi_respawn = cfread_uint(cfp);
330 plr->multi_max_observers = cfread_ubyte(cfp);
331 plr->multi_skill_level = cfread_ubyte(cfp);
332 plr->multi_voice_qos = cfread_ubyte(cfp);
333 plr->multi_voice_token_wait = cfread_int(cfp);
334 plr->multi_voice_record_time = cfread_int(cfp);
335 plr->multi_time_limit = cfread_int(cfp);
336 plr->multi_kill_limit = cfread_int(cfp);
337
338 plr->multi_local_flags = cfread_int(cfp);
339 plr->multi_local_update_level = cfread_int(cfp);
340 }
341
plr_import_red_alert()342 void pilotfile_convert::plr_import_red_alert()
343 {
344 int idx, j;
345 char name[35];
346
347 if (fver >= 242) {
348 return;
349 }
350
351 // have to read it, but don't need any of it ...
352
353 int num_slots = cfread_int(cfp);
354
355 if ( (num_slots < 0) || (num_slots >= 32) ) {
356 throw "Data check failure in red-alert!";
357 }
358
359 if ( !num_slots ) {
360 return;
361 }
362
363 for (idx = 0; idx < num_slots; idx++) {
364 cfread_string(name, sizeof(name) - 1, cfp);
365 cfread_float(cfp);
366
367 cfread_string_len(name, sizeof(name), cfp);
368
369 // subsystem hits
370 for (j = 0; j < 64; j++) {
371 cfread_float(cfp);
372 }
373
374 // aggregate hits
375 for (j = 0; j < 12; j++) {
376 cfread_float(cfp);
377 }
378
379 // weapons
380 for (j = 0; j < 12; j++) {
381 cfread_string_len(name, sizeof(name), cfp);
382 cfread_int(cfp);
383 }
384 }
385 }
386
plr_import_variables()387 void pilotfile_convert::plr_import_variables()
388 {
389 int idx;
390 sexp_variable nvar;
391
392 int num_variables = cfread_int(cfp);
393
394 if ( (num_variables < 0) || (num_variables >= 100) ) {
395 throw "Data check failure in variables!";
396 }
397
398 plr->variables.reserve(num_variables);
399
400 for (idx = 0; idx < num_variables; idx++) {
401 nvar.type = cfread_int(cfp);
402 cfread_string_len(nvar.text, sizeof(nvar.text), cfp);
403 cfread_string_len(nvar.variable_name, sizeof(nvar.variable_name), cfp);
404
405 plr->variables.push_back( nvar );
406 }
407 }
408
plr_import()409 void pilotfile_convert::plr_import()
410 {
411 char name[35];
412 int idx;
413
414 unsigned int plr_id = cfread_uint(cfp);
415
416 if (plr_id != 0x46505346) {
417 throw "Invalid file signature!";
418 }
419
420 fver = cfread_uint(cfp);
421
422 if ( (fver != 142) && (fver != 242) ) {
423 throw "Unsupported file version!";
424 }
425
426 // multi flag
427 plr->is_multi = (int)cfread_ubyte(cfp);
428
429 // rank
430 plr->rank = cfread_int(cfp);
431
432 // mainhall, don't need it
433 if (fver < 242) {
434 cfread_ubyte(cfp);
435 }
436
437 plr->tips = cfread_int(cfp);
438
439 if ( (plr->tips < 0) || (plr->tips > 1) ) {
440 throw "Data check failure!";
441 }
442
443 cfread_string_len(plr->image_filename, sizeof(plr->image_filename), cfp);
444 cfread_string_len(plr->squad_name, sizeof(plr->squad_name), cfp);
445 cfread_string_len(plr->squad_filename, sizeof(plr->squad_filename), cfp);
446 cfread_string_len(plr->current_campaign, sizeof(plr->current_campaign), cfp);
447 cfread_string_len(plr->last_ship_flown, sizeof(plr->last_ship_flown), cfp);
448
449 // controls
450 plr_import_controls();
451
452 // hud config
453 plr_import_hud();
454
455 // cutscenes, don't need it
456 if (fver < 242) {
457 cfread_int(cfp);
458 }
459
460 // volume stuff
461 plr->sound_volume = cfread_float(cfp);
462 plr->music_volume = cfread_float(cfp);
463 plr->voice_volume = cfread_float(cfp);
464
465 // detail settings
466 plr_import_detail();
467
468 // recent missions, don't need it
469 int num_missions = cfread_int(cfp);
470
471 for (idx = 0; idx < num_missions; idx++) {
472 cfread_string_len(name, sizeof(name), cfp);
473 }
474
475 // stats, will skip if fver < 242
476 plr_import_stats();
477
478 plr->skill_level = cfread_int(cfp);
479
480 if ( (plr->skill_level < 0) || (plr->skill_level > 4) ) {
481 throw "Data check failure!";
482 }
483
484 // extra joystick stuff
485 for (idx = 0; idx < 5; idx++) {
486 plr->joy_axis_map_to[idx] = cfread_int(cfp);
487 plr->joy_invert_axis[idx] = cfread_int(cfp);
488 }
489
490 // flags
491 plr->save_flags = cfread_int(cfp);
492
493 // loadout, will skip if fver < 242
494 plr_import_loadout();
495
496 // multiplayer
497 plr_import_multiplayer();
498
499 // two briefing related values
500 plr->readyroom_listing_mode = cfread_int(cfp);
501 Briefing_voice_enabled = cfread_int(cfp) != 0;
502
503 plr->net_protocol = cfread_int(cfp);
504
505 // protocol must be set to something
506 if (plr->net_protocol == NET_NONE) {
507 plr->net_protocol = NET_TCP;
508 } else if ( (plr->net_protocol < 0) || (plr->net_protocol > NET_VMT) ) {
509 throw "Data check failure!";
510 }
511
512 // red alert status, will skip if fver < 242 (and should be empty if multi)
513 plr_import_red_alert();
514
515 // briefing auto-advance
516 plr->auto_advance = cfread_int(cfp);
517
518 if ( (plr->auto_advance < 0) || (plr->auto_advance > 1) ) {
519 throw "Data check failure!";
520 }
521
522 // some input options
523 plr->Use_mouse_to_fly = cfread_int(cfp);
524 plr->Mouse_sensitivity = cfread_int(cfp);
525 plr->Joy_sensitivity = cfread_int(cfp);
526 plr->Dead_zone_size = cfread_int(cfp);
527
528 // variables
529 plr_import_variables();
530
531
532 // and... we're done! :)
533 }
534
plr_export_flags()535 void pilotfile_convert::plr_export_flags()
536 {
537 startSection(Section::Flags);
538
539 // tips
540 cfwrite_ubyte((unsigned char)plr->tips, cfp);
541
542 // saved flags
543 cfwrite_int(plr->save_flags, cfp);
544
545 // listing mode (single or campaign missions)
546 cfwrite_int(plr->readyroom_listing_mode, cfp);
547
548 // briefing auto-play
549 cfwrite_int(plr->auto_advance, cfp);
550
551 // special rank setting (to avoid having to read all stats on verify)
552 cfwrite_int(plr->rank, cfp);
553
554 // What game mode we were in last on this pilot
555 cfwrite_int(plr->is_multi, cfp);
556
557 // which language was this pilot created with
558 cfwrite_string_len(plr->language, cfp);
559
560 endSection();
561 }
562
plr_export_info()563 void pilotfile_convert::plr_export_info()
564 {
565 startSection(Section::Info);
566
567 // pilot image
568 cfwrite_string_len(plr->image_filename, cfp);
569
570 // squad name
571 cfwrite_string_len(plr->squad_name, cfp);
572
573 // squad image
574 cfwrite_string_len(plr->squad_filename, cfp);
575
576 // active campaign
577 cfwrite_string_len(plr->current_campaign, cfp);
578
579 endSection();
580 }
581
plr_export_stats()582 void pilotfile_convert::plr_export_stats()
583 {
584 int idx, list_size = 0;
585
586 startSection(Section::Scoring);
587
588 // global, all-time stats
589 cfwrite_int(all_time_stats.score, cfp);
590 cfwrite_int(all_time_stats.rank, cfp);
591 cfwrite_int(all_time_stats.assists, cfp);
592 cfwrite_int(all_time_stats.kill_count, cfp);
593 cfwrite_int(all_time_stats.kill_count_ok, cfp);
594 cfwrite_int(all_time_stats.bonehead_kills, cfp);
595
596 cfwrite_uint(all_time_stats.p_shots_fired, cfp);
597 cfwrite_uint(all_time_stats.p_shots_hit, cfp);
598 cfwrite_uint(all_time_stats.p_bonehead_hits, cfp);
599
600 cfwrite_uint(all_time_stats.s_shots_fired, cfp);
601 cfwrite_uint(all_time_stats.s_shots_hit, cfp);
602 cfwrite_uint(all_time_stats.s_bonehead_hits, cfp);
603
604 cfwrite_uint(all_time_stats.flight_time, cfp);
605 cfwrite_uint(all_time_stats.missions_flown, cfp);
606 cfwrite_int((int)all_time_stats.last_flown, cfp);
607 cfwrite_int((int)all_time_stats.last_backup, cfp);
608
609 // ship kills (contains ships across all mods, not just current)
610 list_size = (int)all_time_stats.ship_kills.size();
611 cfwrite_int(list_size, cfp);
612
613 for (idx = 0; idx < list_size; idx++) {
614 cfwrite_string_len(all_time_stats.ship_kills[idx].name.c_str(), cfp);
615 cfwrite_int(all_time_stats.ship_kills[idx].val, cfp);
616 }
617
618 // medals earned (contains medals across all mods, not just current)
619 list_size = (int)all_time_stats.medals_earned.size();
620 cfwrite_int(list_size, cfp);
621
622 for (idx = 0; idx < list_size; idx++) {
623 cfwrite_string_len(all_time_stats.medals_earned[idx].name.c_str(), cfp);
624 cfwrite_int(all_time_stats.medals_earned[idx].val, cfp);
625 }
626
627 endSection();
628 }
629
plr_export_stats_multi()630 void pilotfile_convert::plr_export_stats_multi()
631 {
632 int idx, list_size = 0;
633
634 startSection(Section::ScoringMulti);
635
636 // global, all-time stats
637 cfwrite_int(multi_stats.score, cfp);
638 cfwrite_int(multi_stats.rank, cfp);
639 cfwrite_int(multi_stats.assists, cfp);
640 cfwrite_int(multi_stats.kill_count, cfp);
641 cfwrite_int(multi_stats.kill_count_ok, cfp);
642 cfwrite_int(multi_stats.bonehead_kills, cfp);
643
644 cfwrite_uint(multi_stats.p_shots_fired, cfp);
645 cfwrite_uint(multi_stats.p_shots_hit, cfp);
646 cfwrite_uint(multi_stats.p_bonehead_hits, cfp);
647
648 cfwrite_uint(multi_stats.s_shots_fired, cfp);
649 cfwrite_uint(multi_stats.s_shots_hit, cfp);
650 cfwrite_uint(multi_stats.s_bonehead_hits, cfp);
651
652 cfwrite_uint(multi_stats.flight_time, cfp);
653 cfwrite_uint(multi_stats.missions_flown, cfp);
654 cfwrite_int((int)multi_stats.last_flown, cfp);
655 cfwrite_int((int)multi_stats.last_backup, cfp);
656
657 // ship kills (contains medals across all mods, not just current)
658 list_size = (int)multi_stats.ship_kills.size();
659 cfwrite_int(list_size, cfp);
660
661 for (idx = 0; idx < list_size; idx++) {
662 cfwrite_string_len(multi_stats.ship_kills[idx].name.c_str(), cfp);
663 cfwrite_int(multi_stats.ship_kills[idx].val, cfp);
664 }
665
666 // medals earned (contains medals across all mods, not just current)
667 list_size = (int)multi_stats.medals_earned.size();
668 cfwrite_int(list_size, cfp);
669
670 for (idx = 0; idx < list_size; idx++) {
671 cfwrite_string_len(multi_stats.medals_earned[idx].name.c_str(), cfp);
672 cfwrite_int(multi_stats.medals_earned[idx].val, cfp);
673 }
674
675 endSection();
676 }
677
plr_export_hud()678 void pilotfile_convert::plr_export_hud()
679 {
680 int idx;
681
682 startSection(Section::HUD);
683
684 // flags
685 cfwrite_int(plr->hud_show_flags, cfp);
686 cfwrite_int(plr->hud_show_flags2, cfp);
687
688 cfwrite_int(plr->hud_popup_flags, cfp);
689 cfwrite_int(plr->hud_popup_flags2, cfp);
690
691 // settings
692 cfwrite_ubyte(plr->hud_num_lines, cfp);
693
694 cfwrite_int(plr->hud_rp_flags, cfp);
695 cfwrite_int(plr->hud_rp_dist, cfp);
696
697 // basic colors
698 cfwrite_int(0, cfp); // color
699 cfwrite_int(8, cfp); // alpha
700
701 // gauge-specific colors
702 cfwrite_int(39, cfp);
703
704 for (idx = 0; idx < 39; idx++) {
705 cfwrite_ubyte(plr->hud_colors[idx][0], cfp);
706 cfwrite_ubyte(plr->hud_colors[idx][1], cfp);
707 cfwrite_ubyte(plr->hud_colors[idx][2], cfp);
708 cfwrite_ubyte(plr->hud_colors[idx][3], cfp);
709 }
710
711 endSection();
712 }
713
plr_export_variables()714 void pilotfile_convert::plr_export_variables()
715 {
716 int list_size = 0;
717 int idx;
718
719 startSection(Section::Variables);
720
721 list_size = (int)plr->variables.size();
722
723 cfwrite_int(list_size, cfp);
724
725 for (idx = 0; idx < list_size; idx++) {
726 cfwrite_int(plr->variables[idx].type, cfp);
727 cfwrite_string_len(plr->variables[idx].text, cfp);
728 cfwrite_string_len(plr->variables[idx].variable_name, cfp);
729 }
730
731 endSection();
732 }
733
plr_export_multiplayer()734 void pilotfile_convert::plr_export_multiplayer()
735 {
736 startSection(Section::Multiplayer);
737
738 // netgame options
739 cfwrite_ubyte(plr->multi_squad_set, cfp);
740 cfwrite_ubyte(plr->multi_endgame_set, cfp);
741 cfwrite_int(plr->multi_flags, cfp);
742 cfwrite_uint(plr->multi_respawn, cfp);
743 cfwrite_ubyte(plr->multi_max_observers, cfp);
744 cfwrite_ubyte(plr->multi_skill_level, cfp);
745 cfwrite_ubyte(plr->multi_voice_qos, cfp);
746 cfwrite_int(plr->multi_voice_token_wait, cfp);
747 cfwrite_int(plr->multi_voice_record_time, cfp);
748 cfwrite_int(plr->multi_time_limit, cfp);
749 cfwrite_int(plr->multi_kill_limit, cfp);
750
751 // local options
752 cfwrite_int(plr->multi_local_flags, cfp);
753 cfwrite_int(plr->multi_local_update_level, cfp);
754
755 // netgame protocol
756 cfwrite_int(plr->net_protocol, cfp);
757
758 endSection();
759 }
760
plr_export_controls()761 void pilotfile_convert::plr_export_controls()
762 {
763 unsigned int idx;
764
765 startSection(Section::Controls);
766
767 cfwrite_ushort((unsigned short)plr->controls.size(), cfp);
768
769 for (idx = 0; idx < plr->controls.size(); idx++) {
770 cfwrite_short(plr->controls[idx].get_btn(CID_KEYBOARD), cfp);
771 cfwrite_short(plr->controls[idx].get_btn(CID_JOY0), cfp);
772 // placeholder? for future mouse_id?
773 cfwrite_short(-1, cfp);
774 }
775
776 // extra joystick stuff
777 cfwrite_int(MAX_JOY_AXES_CONV, cfp);
778 for (idx = 0; idx < MAX_JOY_AXES_CONV; idx++) {
779 cfwrite_int(plr->joy_axis_map_to[idx], cfp);
780 cfwrite_int(plr->joy_invert_axis[idx], cfp);
781 }
782
783 endSection();
784 }
785
plr_export_settings()786 void pilotfile_convert::plr_export_settings()
787 {
788 startSection(Section::Settings);
789
790 // sound/voice/music
791 cfwrite_float(plr->sound_volume, cfp);
792 cfwrite_float(plr->music_volume, cfp);
793 cfwrite_float(plr->voice_volume, cfp);
794
795 cfwrite_int(plr->voice_enabled, cfp);
796
797 // skill level
798 cfwrite_int(plr->skill_level, cfp);
799
800 // input options
801 cfwrite_int(plr->Use_mouse_to_fly, cfp);
802 cfwrite_int(plr->Mouse_sensitivity, cfp);
803 cfwrite_int(plr->Joy_sensitivity, cfp);
804 cfwrite_int(plr->Dead_zone_size, cfp);
805
806 // detail
807 cfwrite_int(plr->detail_setting, cfp);
808 cfwrite_int(plr->detail_nebula, cfp);
809 cfwrite_int(plr->detail_distance, cfp);
810 cfwrite_int(plr->detail_hardware_textures, cfp);
811 cfwrite_int(plr->detail_num_debris, cfp);
812 cfwrite_int(plr->detail_num_particles, cfp);
813 cfwrite_int(plr->detail_num_stars, cfp);
814 cfwrite_int(plr->detail_shield_effects, cfp);
815 cfwrite_int(plr->detail_lighting, cfp);
816 cfwrite_int(plr->detail_targetview_model, cfp);
817 cfwrite_int(plr->detail_planets_suns, cfp);
818 cfwrite_int(plr->detail_weapon_extras, cfp);
819
820 endSection();
821 }
822
plr_export()823 void pilotfile_convert::plr_export()
824 {
825 Assert( cfp != NULL );
826
827 // header and version
828 cfwrite_int(PLR_FILE_ID, cfp);
829 cfwrite_ubyte(PLR_VERSION, cfp);
830
831 // flags and info sections go first
832 plr_export_flags();
833 plr_export_info();
834
835 // everything else is next, not order specific
836 plr_export_stats();
837 plr_export_stats_multi();
838 plr_export_hud();
839 plr_export_variables();
840 plr_export_multiplayer();
841 plr_export_controls();
842 plr_export_settings();
843
844
845 // and... we're done! :)
846 }
847
plr_convert(const char * fname,bool inferno)848 bool pilotfile_convert::plr_convert(const char *fname, bool inferno)
849 {
850 Assert( fname != NULL );
851
852 SCP_string filename;
853 bool rval = true;
854
855
856 if (plr == NULL) {
857 plr = new(std::nothrow) plr_data;
858 }
859
860 if (plr == NULL) {
861 return false;
862 }
863
864 filename.reserve(200);
865
866 cf_create_default_path_string(filename, CF_TYPE_SINGLE_PLAYERS, (inferno) ? "inferno" : nullptr, false,
867 CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
868
869 if (inferno) {
870 filename.append(DIR_SEPARATOR_STR);
871 }
872
873 filename.append(fname);
874 filename.append(".pl2");
875
876 mprintf((" PL2 => Converting '%s'...\n", filename.c_str()));
877
878 cfp = cfopen(filename.c_str(), "rb", CFILE_NORMAL);
879
880 if ( !cfp ) {
881 mprintf((" PL2 => Unable to open '%s' for import!\n", fname));
882 return false;
883 }
884
885 try {
886 plr_import();
887 } catch (const char *err) {
888 mprintf(( " PL2 => Import ERROR: %s\n", err));
889 rval = false;
890 }
891
892 cfclose(cfp);
893 cfp = NULL;
894
895 if ( !rval ) {
896 return false;
897 }
898
899 filename.assign(fname);
900 filename.append(".plr");
901
902 cfp = cfopen(filename.c_str(), "wb", CFILE_NORMAL, CF_TYPE_PLAYERS, false,
903 CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
904
905 if ( !cfp ) {
906 mprintf((" PLR => Unable to open '%s' for export!\n", fname));
907 return false;
908 }
909
910 try {
911 plr_export();
912 } catch (const char *err) {
913 mprintf((" PLR => Export ERROR: %s\n", err));
914 rval = false;
915 }
916
917 cfclose(cfp);
918 cfp = NULL;
919
920 if (rval) {
921 mprintf((" PLR => Conversion complete!\n"));
922 }
923
924 return rval;
925 }
926
927