Files
fs2open.github.com/code/pilotfile/plr_convert.cpp
asarium a13b503b83 Add more features for the new Options UI
The largest new feature is that it is now possible to include other
files into the RML by using the "include" tag. This is useful for making
markup files more modular.

Also added some more options for existing things (e.g. built-in detail
options).
2020-02-08 13:28:53 +01:00

925 lines
22 KiB
C++

/* WARNING:
* This is magic-number central, but these numbers are set specifically
* to the acceptable defaults or range values that were used when the
* pl2/plr files were created. Standard game defines should not be used in
* place of these major numbers for /any/ reason, *ever*!
*/
#include "cfile/cfilesystem.h"
#include "mission/missionbriefcommon.h"
#include "network/psnet2.h"
#include "pilotfile/pilotfile_convert.h"
// this struct isn't well packed, and is written whole to the pilot file, so
// we can't easily just get the RGBA that we need and instead must retain this
typedef struct conv_color { //-V802
uint screen_sig;
ubyte red;
ubyte green;
ubyte blue;
ubyte alpha;
ubyte ac_type;
int is_alphacolor;
ubyte raw8;
int alphacolor;
int magic;
} conv_color;
plr_data::plr_data()
{
// not carried over, just for reference during conversion process
version = 0;
is_multi = 0;
lcl_get_language_name(language);
// basic flags and settings
tips = 0;
rank = 0;
skill_level = 1;
save_flags = 0;
readyroom_listing_mode = 0;
voice_enabled = 1;
auto_advance = 1;
Use_mouse_to_fly = 0;
Mouse_sensitivity = 4;
Joy_sensitivity = 9;
Dead_zone_size = 10;
// multiplayer settings/options
net_protocol = 1;
multi_squad_set = 2;
multi_endgame_set = 3;
multi_flags = 3;
multi_respawn = 2;
multi_max_observers = 2;
multi_skill_level = 2;
multi_voice_qos = 10;
multi_voice_token_wait = 2000;
multi_voice_record_time = 5000;
multi_time_limit = -65536;
multi_kill_limit = 9999;
multi_local_flags = 5;
multi_local_update_level = 0;
// pilot info stuff
memset(image_filename, 0, sizeof(image_filename));
memset(squad_name, 0, sizeof(squad_name));
memset(squad_filename, 0, sizeof(squad_filename));
memset(current_campaign, 0, sizeof(current_campaign));
memset(last_ship_flown, 0, sizeof(last_ship_flown));
// HUD config
hud_show_flags = -1;
hud_show_flags2 = 31;
hud_popup_flags = 0;
hud_popup_flags2 = 0;
hud_num_lines = 4;
hud_rp_flags = 7;
hud_rp_dist = 2;
for (int idx = 0; idx < 39; idx++) {
hud_colors[idx][0] = 0;
hud_colors[idx][1] = 255;
hud_colors[idx][2] = 0;
hud_colors[idx][3] = 144;
}
// control setup
joy_axis_map_to[0] = 0;
joy_axis_map_to[1] = 1;
joy_axis_map_to[2] = 3;
joy_invert_axis[3] = -1;
joy_invert_axis[4] = -1;
memset(joy_invert_axis, 0, sizeof(joy_invert_axis));
// audio
sound_volume = 1.0f;
music_volume = 0.5f;
voice_volume = 0.7f;
// detail settings
detail_setting = 3;
detail_nebula = 3;
detail_distance = 3;
detail_hardware_textures = 4;
detail_num_debris = 4;
detail_num_particles = 3;
detail_num_stars = 4;
detail_shield_effects = 4;
detail_lighting = 4;
detail_targetview_model = 1;
detail_planets_suns = 1;
detail_weapon_extras = 1;
}
plr_data::~plr_data()
{
controls.clear();
}
void pilotfile_convert::plr_import_controls()
{
int idx;
config_item con;
unsigned char num_controls = cfread_ubyte(cfp);
if ( !num_controls ) {
return;
}
// it may be less than 118, but it shouldn't be more than 118
if (num_controls > 118) {
throw "Data check failure in controls!";
}
plr->controls.reserve(num_controls);
for (idx = 0; idx < num_controls; idx++) {
con.key_id = cfread_short(cfp);
if (con.key_id == 255) {
con.key_id = -1;
}
con.joy_id = cfread_short(cfp);
if (con.joy_id == 255) {
con.joy_id = -1;
}
plr->controls.push_back( con );
}
}
void pilotfile_convert::plr_import_hud()
{
int idx;
conv_color c;
plr->hud_show_flags = cfread_int(cfp);
plr->hud_show_flags2 = cfread_int(cfp);
plr->hud_popup_flags = cfread_int(cfp);
plr->hud_popup_flags2 = cfread_int(cfp);
plr->hud_num_lines = cfread_ubyte(cfp);
plr->hud_rp_flags = cfread_int(cfp);
plr->hud_rp_dist = cfread_int(cfp);
for (idx = 0; idx < 39; idx++) {
cfread(&c, sizeof(conv_color), 1, cfp);
if ( (c.alphacolor != -1) || (c.is_alphacolor != 1) ) {
throw "Data check failure in hud!";
}
plr->hud_colors[idx][0] = c.red;
plr->hud_colors[idx][1] = c.green;
plr->hud_colors[idx][2] = c.blue;
plr->hud_colors[idx][3] = c.alpha;
}
}
void pilotfile_convert::plr_import_detail()
{
bool data_failure = false;
plr->detail_setting = cfread_int(cfp);
plr->detail_nebula = cfread_int(cfp);
plr->detail_distance = cfread_int(cfp);
plr->detail_hardware_textures = cfread_int(cfp);
plr->detail_num_debris = cfread_int(cfp);
plr->detail_num_particles = cfread_int(cfp);
plr->detail_num_stars = cfread_int(cfp);
plr->detail_shield_effects = cfread_int(cfp);
plr->detail_lighting = cfread_int(cfp);
plr->detail_targetview_model = cfread_int(cfp);
plr->detail_planets_suns = cfread_int(cfp);
plr->detail_weapon_extras = cfread_int(cfp);
if ( (plr->detail_setting < -1) || (plr->detail_setting > 4) ) {
data_failure = true;
} else if ( (plr->detail_nebula < 0) || (plr->detail_nebula > 4) ) {
data_failure = true;
} else if ( (plr->detail_distance < 0) || (plr->detail_distance > 4) ) {
data_failure = true;
} else if ( (plr->detail_hardware_textures < 0) || (plr->detail_hardware_textures > 4) ) {
data_failure = true;
} else if ( (plr->detail_num_debris < 0) || (plr->detail_num_debris > 4) ) {
data_failure = true;
} else if ( (plr->detail_num_particles < 0) || (plr->detail_num_particles > 4) ) {
data_failure = true;
} else if ( (plr->detail_num_stars < 0) || (plr->detail_num_stars > 4) ) {
data_failure = true;
} else if ( (plr->detail_shield_effects < 0) || (plr->detail_shield_effects > 4) ) {
data_failure = true;
} else if ( (plr->detail_lighting < 0) || (plr->detail_lighting > 4) ) {
data_failure = true;
} else if ( (plr->detail_targetview_model < 0) || (plr->detail_targetview_model > 1) ) {
data_failure = true;
} else if ( (plr->detail_planets_suns < 0) || (plr->detail_planets_suns > 1) ) {
data_failure = true;
} else if ( (plr->detail_weapon_extras < 0) || (plr->detail_weapon_extras > 1) ) {
data_failure = true;
}
if (data_failure) {
throw "Data check failure in details!";
}
}
void pilotfile_convert::plr_import_stats()
{
int idx;
char name[35];
if (fver >= 242) {
return;
}
// read everything, but we don't need any of it ...
cfread_int(cfp); // score
cfread_int(cfp); // rank
cfread_int(cfp); // assists
// medals
for (idx = 0; idx < 18; idx++) {
cfread_int(cfp);
}
// kills per ship
int count = cfread_int(cfp);
for (idx = 0; idx < count; idx++) {
cfread_ushort(cfp);
cfread_string_len(name, sizeof(name), cfp);
}
cfread_int(cfp); // kill_count
cfread_int(cfp); // kill_count_ok
cfread_uint(cfp); // p_shots_fired
cfread_uint(cfp); // s_shots_fired
cfread_uint(cfp); // p_shots_hit
cfread_uint(cfp); // s_shots_hit
cfread_uint(cfp); // p_bonehead_hits
cfread_uint(cfp); // s_bonehead_hits
cfread_uint(cfp); // bonehead_kills
}
void pilotfile_convert::plr_import_loadout()
{
int idx, j;
int s_count, w_count;
char name[52];
if (fver >= 242) {
return;
}
// have to read it, but don't need any of it ...
cfread_string_len(name, sizeof(name), cfp); // filename
cfread_string_len(name, sizeof(name), cfp); // last_modified
s_count = cfread_int(cfp); // num ships
w_count = cfread_int(cfp); // num weapons
// ships
for (idx = 0; idx < s_count; idx++) {
cfread_int(cfp); // count
cfread_string_len(name, sizeof(name), cfp); // name
}
// weapons
for (idx = 0; idx < w_count; idx++) {
cfread_int(cfp); // count
cfread_string_len(name, sizeof(name), cfp); // name
}
// loadout info
for (idx = 0; idx < 12; idx++) {
cfread_int(cfp); // ship class
cfread_string_len(name, sizeof(name), cfp); // ship name
for (j = 0; j < 12; j++) {
cfread_int(cfp); // weapon type
cfread_int(cfp); // weapon count
cfread_string_len(name, sizeof(name), cfp); // weapon name
}
}
}
void pilotfile_convert::plr_import_multiplayer()
{
plr->multi_squad_set = cfread_ubyte(cfp);
plr->multi_endgame_set = cfread_ubyte(cfp);
plr->multi_flags = cfread_int(cfp);
plr->multi_respawn = cfread_uint(cfp);
plr->multi_max_observers = cfread_ubyte(cfp);
plr->multi_skill_level = cfread_ubyte(cfp);
plr->multi_voice_qos = cfread_ubyte(cfp);
plr->multi_voice_token_wait = cfread_int(cfp);
plr->multi_voice_record_time = cfread_int(cfp);
plr->multi_time_limit = cfread_int(cfp);
plr->multi_kill_limit = cfread_int(cfp);
plr->multi_local_flags = cfread_int(cfp);
plr->multi_local_update_level = cfread_int(cfp);
}
void pilotfile_convert::plr_import_red_alert()
{
int idx, j;
char name[35];
if (fver >= 242) {
return;
}
// have to read it, but don't need any of it ...
int num_slots = cfread_int(cfp);
if ( (num_slots < 0) || (num_slots >= 32) ) {
throw "Data check failure in red-alert!";
}
if ( !num_slots ) {
return;
}
for (idx = 0; idx < num_slots; idx++) {
cfread_string(name, sizeof(name) - 1, cfp);
cfread_float(cfp);
cfread_string_len(name, sizeof(name), cfp);
// subsystem hits
for (j = 0; j < 64; j++) {
cfread_float(cfp);
}
// aggregate hits
for (j = 0; j < 12; j++) {
cfread_float(cfp);
}
// weapons
for (j = 0; j < 12; j++) {
cfread_string_len(name, sizeof(name), cfp);
cfread_int(cfp);
}
}
}
void pilotfile_convert::plr_import_variables()
{
int idx;
sexp_variable nvar;
int num_variables = cfread_int(cfp);
if ( (num_variables < 0) || (num_variables >= 100) ) {
throw "Data check failure in variables!";
}
plr->variables.reserve(num_variables);
for (idx = 0; idx < num_variables; idx++) {
nvar.type = cfread_int(cfp);
cfread_string_len(nvar.text, sizeof(nvar.text), cfp);
cfread_string_len(nvar.variable_name, sizeof(nvar.variable_name), cfp);
plr->variables.push_back( nvar );
}
}
void pilotfile_convert::plr_import()
{
char name[35];
int idx;
unsigned int plr_id = cfread_uint(cfp);
if (plr_id != 0x46505346) {
throw "Invalid file signature!";
}
fver = cfread_uint(cfp);
if ( (fver != 142) && (fver != 242) ) {
throw "Unsupported file version!";
}
// multi flag
plr->is_multi = (int)cfread_ubyte(cfp);
// rank
plr->rank = cfread_int(cfp);
// mainhall, don't need it
if (fver < 242) {
cfread_ubyte(cfp);
}
plr->tips = cfread_int(cfp);
if ( (plr->tips < 0) || (plr->tips > 1) ) {
throw "Data check failure!";
}
cfread_string_len(plr->image_filename, sizeof(plr->image_filename), cfp);
cfread_string_len(plr->squad_name, sizeof(plr->squad_name), cfp);
cfread_string_len(plr->squad_filename, sizeof(plr->squad_filename), cfp);
cfread_string_len(plr->current_campaign, sizeof(plr->current_campaign), cfp);
cfread_string_len(plr->last_ship_flown, sizeof(plr->last_ship_flown), cfp);
// controls
plr_import_controls();
// hud config
plr_import_hud();
// cutscenes, don't need it
if (fver < 242) {
cfread_int(cfp);
}
// volume stuff
plr->sound_volume = cfread_float(cfp);
plr->music_volume = cfread_float(cfp);
plr->voice_volume = cfread_float(cfp);
// detail settings
plr_import_detail();
// recent missions, don't need it
int num_missions = cfread_int(cfp);
for (idx = 0; idx < num_missions; idx++) {
cfread_string_len(name, sizeof(name), cfp);
}
// stats, will skip if fver < 242
plr_import_stats();
plr->skill_level = cfread_int(cfp);
if ( (plr->skill_level < 0) || (plr->skill_level > 4) ) {
throw "Data check failure!";
}
// extra joystick stuff
for (idx = 0; idx < 5; idx++) {
plr->joy_axis_map_to[idx] = cfread_int(cfp);
plr->joy_invert_axis[idx] = cfread_int(cfp);
}
// flags
plr->save_flags = cfread_int(cfp);
// loadout, will skip if fver < 242
plr_import_loadout();
// multiplayer
plr_import_multiplayer();
// two briefing related values
plr->readyroom_listing_mode = cfread_int(cfp);
Briefing_voice_enabled = cfread_int(cfp) != 0;
plr->net_protocol = cfread_int(cfp);
// protocol must be set to something
if (plr->net_protocol == NET_NONE) {
plr->net_protocol = NET_TCP;
} else if ( (plr->net_protocol < 0) || (plr->net_protocol > NET_VMT) ) {
throw "Data check failure!";
}
// red alert status, will skip if fver < 242 (and should be empty if multi)
plr_import_red_alert();
// briefing auto-advance
plr->auto_advance = cfread_int(cfp);
if ( (plr->auto_advance < 0) || (plr->auto_advance > 1) ) {
throw "Data check failure!";
}
// some input options
plr->Use_mouse_to_fly = cfread_int(cfp);
plr->Mouse_sensitivity = cfread_int(cfp);
plr->Joy_sensitivity = cfread_int(cfp);
plr->Dead_zone_size = cfread_int(cfp);
// variables
plr_import_variables();
// and... we're done! :)
}
void pilotfile_convert::plr_export_flags()
{
startSection(Section::Flags);
// tips
cfwrite_ubyte((unsigned char)plr->tips, cfp);
// saved flags
cfwrite_int(plr->save_flags, cfp);
// listing mode (single or campaign missions)
cfwrite_int(plr->readyroom_listing_mode, cfp);
// briefing auto-play
cfwrite_int(plr->auto_advance, cfp);
// special rank setting (to avoid having to read all stats on verify)
cfwrite_int(plr->rank, cfp);
// What game mode we were in last on this pilot
cfwrite_int(plr->is_multi, cfp);
// which language was this pilot created with
cfwrite_string_len(plr->language, cfp);
endSection();
}
void pilotfile_convert::plr_export_info()
{
startSection(Section::Info);
// pilot image
cfwrite_string_len(plr->image_filename, cfp);
// squad name
cfwrite_string_len(plr->squad_name, cfp);
// squad image
cfwrite_string_len(plr->squad_filename, cfp);
// active campaign
cfwrite_string_len(plr->current_campaign, cfp);
endSection();
}
void pilotfile_convert::plr_export_stats()
{
int idx, list_size = 0;
startSection(Section::Scoring);
// global, all-time stats
cfwrite_int(all_time_stats.score, cfp);
cfwrite_int(all_time_stats.rank, cfp);
cfwrite_int(all_time_stats.assists, cfp);
cfwrite_int(all_time_stats.kill_count, cfp);
cfwrite_int(all_time_stats.kill_count_ok, cfp);
cfwrite_int(all_time_stats.bonehead_kills, cfp);
cfwrite_uint(all_time_stats.p_shots_fired, cfp);
cfwrite_uint(all_time_stats.p_shots_hit, cfp);
cfwrite_uint(all_time_stats.p_bonehead_hits, cfp);
cfwrite_uint(all_time_stats.s_shots_fired, cfp);
cfwrite_uint(all_time_stats.s_shots_hit, cfp);
cfwrite_uint(all_time_stats.s_bonehead_hits, cfp);
cfwrite_uint(all_time_stats.flight_time, cfp);
cfwrite_uint(all_time_stats.missions_flown, cfp);
cfwrite_int((int)all_time_stats.last_flown, cfp);
cfwrite_int((int)all_time_stats.last_backup, cfp);
// ship kills (contains ships across all mods, not just current)
list_size = (int)all_time_stats.ship_kills.size();
cfwrite_int(list_size, cfp);
for (idx = 0; idx < list_size; idx++) {
cfwrite_string_len(all_time_stats.ship_kills[idx].name.c_str(), cfp);
cfwrite_int(all_time_stats.ship_kills[idx].val, cfp);
}
// medals earned (contains medals across all mods, not just current)
list_size = (int)all_time_stats.medals_earned.size();
cfwrite_int(list_size, cfp);
for (idx = 0; idx < list_size; idx++) {
cfwrite_string_len(all_time_stats.medals_earned[idx].name.c_str(), cfp);
cfwrite_int(all_time_stats.medals_earned[idx].val, cfp);
}
endSection();
}
void pilotfile_convert::plr_export_stats_multi()
{
int idx, list_size = 0;
startSection(Section::ScoringMulti);
// global, all-time stats
cfwrite_int(multi_stats.score, cfp);
cfwrite_int(multi_stats.rank, cfp);
cfwrite_int(multi_stats.assists, cfp);
cfwrite_int(multi_stats.kill_count, cfp);
cfwrite_int(multi_stats.kill_count_ok, cfp);
cfwrite_int(multi_stats.bonehead_kills, cfp);
cfwrite_uint(multi_stats.p_shots_fired, cfp);
cfwrite_uint(multi_stats.p_shots_hit, cfp);
cfwrite_uint(multi_stats.p_bonehead_hits, cfp);
cfwrite_uint(multi_stats.s_shots_fired, cfp);
cfwrite_uint(multi_stats.s_shots_hit, cfp);
cfwrite_uint(multi_stats.s_bonehead_hits, cfp);
cfwrite_uint(multi_stats.flight_time, cfp);
cfwrite_uint(multi_stats.missions_flown, cfp);
cfwrite_int((int)multi_stats.last_flown, cfp);
cfwrite_int((int)multi_stats.last_backup, cfp);
// ship kills (contains medals across all mods, not just current)
list_size = (int)multi_stats.ship_kills.size();
cfwrite_int(list_size, cfp);
for (idx = 0; idx < list_size; idx++) {
cfwrite_string_len(multi_stats.ship_kills[idx].name.c_str(), cfp);
cfwrite_int(multi_stats.ship_kills[idx].val, cfp);
}
// medals earned (contains medals across all mods, not just current)
list_size = (int)multi_stats.medals_earned.size();
cfwrite_int(list_size, cfp);
for (idx = 0; idx < list_size; idx++) {
cfwrite_string_len(multi_stats.medals_earned[idx].name.c_str(), cfp);
cfwrite_int(multi_stats.medals_earned[idx].val, cfp);
}
endSection();
}
void pilotfile_convert::plr_export_hud()
{
int idx;
startSection(Section::HUD);
// flags
cfwrite_int(plr->hud_show_flags, cfp);
cfwrite_int(plr->hud_show_flags2, cfp);
cfwrite_int(plr->hud_popup_flags, cfp);
cfwrite_int(plr->hud_popup_flags2, cfp);
// settings
cfwrite_ubyte(plr->hud_num_lines, cfp);
cfwrite_int(plr->hud_rp_flags, cfp);
cfwrite_int(plr->hud_rp_dist, cfp);
// basic colors
cfwrite_int(0, cfp); // color
cfwrite_int(8, cfp); // alpha
// gauge-specific colors
cfwrite_int(39, cfp);
for (idx = 0; idx < 39; idx++) {
cfwrite_ubyte(plr->hud_colors[idx][0], cfp);
cfwrite_ubyte(plr->hud_colors[idx][1], cfp);
cfwrite_ubyte(plr->hud_colors[idx][2], cfp);
cfwrite_ubyte(plr->hud_colors[idx][3], cfp);
}
endSection();
}
void pilotfile_convert::plr_export_variables()
{
int list_size = 0;
int idx;
startSection(Section::Variables);
list_size = (int)plr->variables.size();
cfwrite_int(list_size, cfp);
for (idx = 0; idx < list_size; idx++) {
cfwrite_int(plr->variables[idx].type, cfp);
cfwrite_string_len(plr->variables[idx].text, cfp);
cfwrite_string_len(plr->variables[idx].variable_name, cfp);
}
endSection();
}
void pilotfile_convert::plr_export_multiplayer()
{
startSection(Section::Multiplayer);
// netgame options
cfwrite_ubyte(plr->multi_squad_set, cfp);
cfwrite_ubyte(plr->multi_endgame_set, cfp);
cfwrite_int(plr->multi_flags, cfp);
cfwrite_uint(plr->multi_respawn, cfp);
cfwrite_ubyte(plr->multi_max_observers, cfp);
cfwrite_ubyte(plr->multi_skill_level, cfp);
cfwrite_ubyte(plr->multi_voice_qos, cfp);
cfwrite_int(plr->multi_voice_token_wait, cfp);
cfwrite_int(plr->multi_voice_record_time, cfp);
cfwrite_int(plr->multi_time_limit, cfp);
cfwrite_int(plr->multi_kill_limit, cfp);
// local options
cfwrite_int(plr->multi_local_flags, cfp);
cfwrite_int(plr->multi_local_update_level, cfp);
// netgame protocol
cfwrite_int(plr->net_protocol, cfp);
endSection();
}
void pilotfile_convert::plr_export_controls()
{
unsigned int idx;
startSection(Section::Controls);
cfwrite_ushort((unsigned short)plr->controls.size(), cfp);
for (idx = 0; idx < plr->controls.size(); idx++) {
cfwrite_short(plr->controls[idx].key_id, cfp);
cfwrite_short(plr->controls[idx].joy_id, cfp);
// placeholder? for future mouse_id?
cfwrite_short(-1, cfp);
}
// extra joystick stuff
cfwrite_int(MAX_JOY_AXES_CONV, cfp);
for (idx = 0; idx < MAX_JOY_AXES_CONV; idx++) {
cfwrite_int(plr->joy_axis_map_to[idx], cfp);
cfwrite_int(plr->joy_invert_axis[idx], cfp);
}
endSection();
}
void pilotfile_convert::plr_export_settings()
{
startSection(Section::Settings);
// sound/voice/music
cfwrite_float(plr->sound_volume, cfp);
cfwrite_float(plr->music_volume, cfp);
cfwrite_float(plr->voice_volume, cfp);
cfwrite_int(plr->voice_enabled, cfp);
// skill level
cfwrite_int(plr->skill_level, cfp);
// input options
cfwrite_int(plr->Use_mouse_to_fly, cfp);
cfwrite_int(plr->Mouse_sensitivity, cfp);
cfwrite_int(plr->Joy_sensitivity, cfp);
cfwrite_int(plr->Dead_zone_size, cfp);
// detail
cfwrite_int(plr->detail_setting, cfp);
cfwrite_int(plr->detail_nebula, cfp);
cfwrite_int(plr->detail_distance, cfp);
cfwrite_int(plr->detail_hardware_textures, cfp);
cfwrite_int(plr->detail_num_debris, cfp);
cfwrite_int(plr->detail_num_particles, cfp);
cfwrite_int(plr->detail_num_stars, cfp);
cfwrite_int(plr->detail_shield_effects, cfp);
cfwrite_int(plr->detail_lighting, cfp);
cfwrite_int(plr->detail_targetview_model, cfp);
cfwrite_int(plr->detail_planets_suns, cfp);
cfwrite_int(plr->detail_weapon_extras, cfp);
endSection();
}
void pilotfile_convert::plr_export()
{
Assert( cfp != NULL );
// header and version
cfwrite_int(PLR_FILE_ID, cfp);
cfwrite_ubyte(PLR_VERSION, cfp);
// flags and info sections go first
plr_export_flags();
plr_export_info();
// everything else is next, not order specific
plr_export_stats();
plr_export_stats_multi();
plr_export_hud();
plr_export_variables();
plr_export_multiplayer();
plr_export_controls();
plr_export_settings();
// and... we're done! :)
}
bool pilotfile_convert::plr_convert(const char *fname, bool inferno)
{
Assert( fname != NULL );
SCP_string filename;
bool rval = true;
if (plr == NULL) {
plr = new(std::nothrow) plr_data;
}
if (plr == NULL) {
return false;
}
filename.reserve(200);
cf_create_default_path_string(filename, CF_TYPE_SINGLE_PLAYERS, (inferno) ? "inferno" : nullptr, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if (inferno) {
filename.append(DIR_SEPARATOR_STR);
}
filename.append(fname);
filename.append(".pl2");
mprintf((" PL2 => Converting '%s'...\n", filename.c_str()));
cfp = cfopen(filename.c_str(), "rb", CFILE_NORMAL);
if ( !cfp ) {
mprintf((" PL2 => Unable to open '%s' for import!\n", fname));
return false;
}
try {
plr_import();
} catch (const char *err) {
mprintf(( " PL2 => Import ERROR: %s\n", err));
rval = false;
}
cfclose(cfp);
cfp = NULL;
if ( !rval ) {
return false;
}
filename.assign(fname);
filename.append(".plr");
cfp = cfopen(filename.c_str(), "wb", CFILE_NORMAL, CF_TYPE_PLAYERS, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if ( !cfp ) {
mprintf((" PLR => Unable to open '%s' for export!\n", fname));
return false;
}
try {
plr_export();
} catch (const char *err) {
mprintf((" PLR => Export ERROR: %s\n", err));
rval = false;
}
cfclose(cfp);
cfp = NULL;
if (rval) {
mprintf((" PLR => Conversion complete!\n"));
}
return rval;
}