Files

2336 lines
68 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#include "cfile/cfile.h"
#include "gamesnd/gamesnd.h"
#include "globalincs/alphacolors.h"
#include "graphics/font.h"
#include "io/key.h"
#include "io/timer.h"
#include "menuui/optionsmenu.h"
#include "menuui/optionsmenumulti.h"
#include "network/multi.h"
#include "network/multiui.h"
#include "network/multi_voice.h"
#include "options/OptionsManager.h"
#include "osapi/osregistry.h"
#include "parse/parselo.h"
#include "playerman/player.h"
#include "popup/popup.h"
#include "sound/ds.h"
#include "sound/rtvoice.h"
// general data section ------------------------------------------------
UI_WINDOW *Om_window = NULL;
static const char* Om_background_0_fname[GR_NUM_RESOLUTIONS] = {
"OptionsMultiGen", // GR_640
"2_OptionsMultiGen" // GR_1024
};
static const char* Om_background_0_mask_fname[GR_NUM_RESOLUTIONS] = {
"OptionsMultiGen-M", // GR_640
"2_OptionsMultiGen-M" // GR_1024
};
static const char* Om_background_1_fname[GR_NUM_RESOLUTIONS] = {
"OptionsMultiVox", // GR_640
"2_OptionsMultiVox" // GR_1024
};
static const char* Om_background_1_mask_fname[GR_NUM_RESOLUTIONS] = {
"OptionsMultiVox-M", // GR_640
"2_OptionsMultiVox-M" // GR_1024
};
int Om_background_0 = -1;
int Om_mask_0 = -1;
int Om_background_1 = -1;
int Om_mask_1 = -1;
#define OM_NOTIFICATION_LINE_LEN 255
// screen modes
#define OM_MODE_NONE -1 // no mode (unintialized)
#define OM_MODE_GENERAL 0 // general tab
#define OM_MODE_VOX 1 // voice tab
int Om_mode = OM_MODE_NONE;
// notification stuff
#define OM_NOTIFY_TIME 8000
#define OM_NOTIFY_Y 430
#define OM_NOTIFY_Y2 440
UI_TIMESTAMP Om_notify_stamp;
char Om_notify_string[255];
// load all background bitmaps
void options_multi_load_bmaps();
// unload all the background bitmaps
void options_multi_unload_bmaps();
// add a notification message
void options_multi_add_notify(const char *str);
// process and blit any notification messages
void options_multi_notify_process();
// protocol options section -------------------------------------------
#define OM_PRO_NUM_BUTTONS 10
#define OM_PRO_TCP 0
#define OM_PRO_IPX 1
#define OM_PRO_SCROLL_IP_UP 2
#define OM_PRO_SCROLL_IP_DOWN 3
#define OM_PRO_ADD_IP 4
#define OM_PRO_DELETE_IP 5
#define OM_PRO_LOCAL_BROADCAST 6
#define OM_PRO_VMT 7
#define OM_PRO_VOX_TAB 8
#define OM_PRO_GEN_TAB 9
ui_button_info Om_pro_buttons[GR_NUM_RESOLUTIONS][OM_PRO_NUM_BUTTONS] = {
{ // GR_640
ui_button_info("OMuB_07", 7, 66, -1, -1, 7),
ui_button_info("OMuB_08", 7, 84, -1, -1, 8),
ui_button_info("OMuB_09", 1, 124, -1, -1, 9),
ui_button_info("OMuB_10", 1, 157, -1, -1, 10),
ui_button_info("OMuB_11", 20, 207, -1, -1, 11),
ui_button_info("OMuB_12", 64, 207, -1, -1, 12),
ui_button_info("OMuB_13", 9, 251, -1, -1, 13),
ui_button_info("OMuB_14", 9, 282, -1, -1, 14),
ui_button_info("OMuB_15", 610, 53, -1, -1, 15),
ui_button_info("OMuB_16", 610, 72, -1, -1, 16),
},
{ // GR_1024
ui_button_info("2_OMuB_07", 12, 105, -1, -1, 7),
ui_button_info("2_OMuB_08", 12, 134, -1, -1, 8),
ui_button_info("2_OMuB_09", 2, 198, -1, -1, 9),
ui_button_info("2_OMuB_10", 2, 252, -1, -1, 10),
ui_button_info("2_OMuB_11", 32, 332, -1, -1, 11),
ui_button_info("2_OMuB_12", 103, 332, -1, -1, 12),
ui_button_info("2_OMuB_13", 14, 402, -1, -1, 13),
ui_button_info("2_OMuB_14", 14, 452, -1, -1, 14),
ui_button_info("2_OMuB_15", 976, 85, -1, -1, 15),
ui_button_info("2_OMuB_16", 976, 114, -1, -1, 16),
}
};
UI_GADGET Om_pro_bogus;
// test
#define OM_PRO_NUM_TEXT 12
UI_XSTR Om_pro_text[GR_NUM_RESOLUTIONS][OM_PRO_NUM_TEXT] = {
{ // GR_640
{ "TCP", 1378, 38, 70, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_TCP].button },
{ "IPX", 1379, 38, 88, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_IPX].button },
{ "IP Address", 1380, 30, 128, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
{ "add", 1381, 22, 235, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_ADD_IP].button },
{ "rem.", 1382, 68, 235, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_DELETE_IP].button },
{ "Broadcast Locally", 1387, 42, 260, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_LOCAL_BROADCAST].button },
{ "PXO", 1383, 42, 291, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_VMT].button },
{ "Login", 1384, 14, 309, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
{ "Password", 1385, 14, 336, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
{ "Squadron", 1386, 14, 363, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
{ "Voice", 1528, 557, 60, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_VOX_TAB].button },
{ "General", 1388, 542, 77, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_GEN_TAB].button },
},
{ // GR_1024
{ "TCP", 1378, 61, 113, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_TCP].button },
{ "IPX", 1379, 61, 141, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_IPX].button },
{ "IP Address", 1380, 47, 206, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
{ "add", 1381, 36, 375, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_ADD_IP].button },
{ "rem.", 1382, 109, 375, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_DELETE_IP].button },
{ "Broadcast Locally", 1387, 68, 417, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_LOCAL_BROADCAST].button },
{ "PXO", 1383, 68, 467, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_VMT].button },
{ "Login", 1384, 23, 495, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
{ "Password", 1385, 23, 538, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
{ "Squadron", 1386, 23, 582, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
{ "Voice", 1528, 921, 96, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_VOX_TAB].button },
{ "General", 1388, 902, 123, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_GEN_TAB].button },
}
};
// defines for the tracker input boxes
int Om_tracker_login_coords[GR_NUM_RESOLUTIONS][4] = {
{
19, 322, 226, -1 // GR_640
},
{
31, 518, 361, -1 // GR_1024
}
};
int Om_tracker_passwd_coords[GR_NUM_RESOLUTIONS][4] = {
{
19, 350, 226, -1 // GR_640
},
{
31, 562, 361, -1 // GR_1024
}
};
int Om_tracker_squad_name_coords[GR_NUM_RESOLUTIONS][4] = {
{
19, 378, 226, -1 // GR_640
},
{
31, 607, 361, -1 // GR_1024
}
};
// protocol section tracker login input box
UI_INPUTBOX Om_tracker_login;
// protocol section tracker passwd input box
UI_INPUTBOX Om_tracker_passwd;
// pxo squad name/password
UI_INPUTBOX Om_tracker_squad_name;
#define TRACKER_FOCUS_NONE 0
#define TRACKER_FOCUS_LOGIN 1
#define TRACKER_FOCUS_PASSWORD 2
#define TRACKER_FOCUS_SQUADRON 3
static int Om_tracker_focus = 0;
#define IP_CONFIG_FNAME NOX("Tcp.cfg")
#define IP_EMPTY_STRING ""
int Ip_list_coords[GR_NUM_RESOLUTIONS][4] = {
{
29, 137, 227, 67 // GR_640
},
{
46, 220, 364, 106 // GR_1024
}
};
int Ip_list_max_display[GR_NUM_RESOLUTIONS] = {
5,
5
};
static int Ip_input_coords[GR_NUM_RESOLUTIONS][4] = {
{
109, 128, 140, -1 // GR_640
},
{
132, 206, 261, -1 // GR_640
}
};
int Om_input_mode = 0;
int Om_ip_start; // index of the first element to be displayed in the list box
int Om_ip_selected; // the selected default IP address
int Om_ip_disp_count; // how many items are currently being displayed
int Om_num_ips; // # of ip addresses we have
char Om_ip_addrs[MAX_IP_ADDRS][IP_STRING_LEN]; // the ip addresses themselves
UI_BUTTON Om_ip_button; // button for detecting clicks on the ip address list
UI_INPUTBOX Om_ip_input; // input box for adding new ip addresses
// setting vars
bool Om_local_broadcast; // whether the player has local broadcast selected or not
bool Om_tracker_flag; // whether the player has the PXO tracker selected
int Om_protocol; // protocol in use
// load all the controls for the protocol section
void options_multi_load_protocol_controls();
// disable/hide all the controls for the protocol section
void options_multi_disable_protocol_controls();
// enable/unhide all the controls for the protocol section
void options_multi_enable_protocol_controls();
// intialize the protocol section vars
void options_multi_init_protocol_vars();
// do frame for the protocol section
void options_multi_protocol_do(int key);
// if the accept button was hit
void options_multi_protocol_accept();
// check for button presses
void options_multi_protocol_check_buttons();
// if a button was pressed
void options_multi_protocol_button_pressed(int n);
// load the ip address file
void options_multi_protocol_load_ip_file();
// save the ip address file
void options_multi_protocol_save_ip_file();
// draw the list of ip addresses
void options_multi_protocol_display_ips();
// scroll the list of ip addresses down
void options_multi_protocol_scroll_ip_down();
// scroll the list of ip addresses up
void options_multi_protocol_scroll_ip_up();
// check the ip list to see if the user has selected a new item
void options_multi_protocol_check_ip_list();
// delete the currently selected ip if any
void options_multi_protocol_delete_ip();
// attempt to add the currently entered ip address
void options_multi_protocol_add_current_ip();
// general options tab section -------------------------------------------
#define OM_GEN_NUM_BUTTONS 10
#define OM_GEN_OBJ_LOW 0
#define OM_GEN_OBJ_MED 1
#define OM_GEN_OBJ_HIGH 2
#define OM_GEN_OBJ_LAN 3
#define OM_GEN_PIX_YES 4
#define OM_GEN_PIX_NO 5
#define OM_GEN_XFER_MULTIDATA_YES 6
#define OM_GEN_XFER_MULTIDATA_NO 7
#define OM_GEN_FLUSH_NO 8
#define OM_GEN_FLUSH_YES 9
ui_button_info Om_gen_buttons[GR_NUM_RESOLUTIONS][OM_GEN_NUM_BUTTONS] = {
{ // GR_640
ui_button_info("OGB_17", 598, 117, -1, -1, 17),
ui_button_info("OGB_18", 598, 139, -1, -1, 18),
ui_button_info("OGB_19", 598, 161, -1, -1, 19),
ui_button_info("OGB_20", 598, 183, -1, -1, 20),
ui_button_info("OGB_21", 549, 229, -1, -1, 21),
ui_button_info("OGB_22", 598, 229, -1, -1, 22),
ui_button_info("OGB_23", 598, 286, -1, -1, 23),
ui_button_info("OGB_24", 598, 307, -1, -1, 24),
ui_button_info("OGB_25", 598, 347, -1, -1, 25),
ui_button_info("OGB_26", 598, 368, -1, -1, 26),
},
{ // GR_1024
ui_button_info("2_OGB_17", 957, 188, -1, -1, 17),
ui_button_info("2_OGB_18", 957, 223, -1, -1, 18),
ui_button_info("2_OGB_19", 957, 258, -1, -1, 19),
ui_button_info("2_OGB_20", 957, 293, -1, -1, 20),
ui_button_info("2_OGB_21", 879, 366, -1, -1, 21),
ui_button_info("2_OGB_22", 957, 366, -1, -1, 22),
ui_button_info("2_OGB_23", 957, 457, -1, -1, 23),
ui_button_info("2_OGB_24", 957, 491, -1, -1, 24),
ui_button_info("2_OGB_25", 957, 555, -1, -1, 25),
ui_button_info("2_OGB_26", 957, 589, -1, -1, 26),
}
};
UI_GADGET Om_gen_bogus;
// text
#define OM_GEN_NUM_TEXT 14
UI_XSTR Om_gen_text[GR_NUM_RESOLUTIONS][OM_GEN_NUM_TEXT] = {
{ // GR_640
{ "Object Update", 1391, 511, 104, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
{ "Low", 1160, 558, 127, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_LOW].button },
{ "Medium", 1161, 538, 149, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_MED].button },
{ "High", 1162, 556, 171, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_HIGH].button },
{ "Lan", 1392, 561, 193, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_LAN].button },
{ "Pilot / Squad Images", 1393, 463, 214, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
{ "Yes", 1394, 555, 257, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_PIX_YES].button },
{ "No", 1395, 604, 257, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_PIX_NO].button },
{ "Transfer Missions", 1396, 478, 271, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
{ "/multidata", 1397, 519, 292, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_XFER_MULTIDATA_YES].button },
{ "/missions", 1398, 527, 314, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_XFER_MULTIDATA_NO].button },
{ "Flush Cache", 1399, 529, 334, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
{ "Never", 1400, 548, 355, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_FLUSH_NO].button },
{ "Before Game", 1401, 502, 377, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_FLUSH_YES].button },
},
{ // GR_1024
{ "Object Update", 1391, 818, 166, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
{ "Low", 1160, 913, 204, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_LOW].button },
{ "Medium", 1161, 892, 239, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_MED].button },
{ "High", 1162, 909, 274, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_HIGH].button },
{ "Lan", 1392, 916, 310, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_LAN].button },
{ "Pilot / Squad Images", 1393, 821, 345, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
{ "Yes", 1394, 887, 411, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_PIX_YES].button },
{ "No", 1395, 966, 411, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_PIX_NO].button },
{ "Transfer Missions", 1396, 844, 435, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
{ "/multidata", 1397, 858, 468, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_XFER_MULTIDATA_YES].button },
{ "/missions", 1398, 870, 503, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_XFER_MULTIDATA_NO].button },
{ "Flush Cache", 1399, 886, 533, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
{ "Never", 1400, 897, 568, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_FLUSH_NO].button },
{ "Before Game", 1401, 849, 603, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_FLUSH_YES].button },
}
};
// setting vars
int Om_gen_obj_update; // object update level
bool Om_gen_pix; // accept pilot pix or not
bool Om_gen_xfer_multidata; // xfer missions to multidata or not
bool Om_gen_flush_cache; // flush multidata directory before every game
// load all the general tab controls
void options_multi_load_gen_controls();
// disable/hide all the general tab controls
void options_multi_disable_gen_controls();
// enable/unhide all the general tab controls
void options_multi_enable_gen_controls();
// initialize the general tab vars
void options_multi_init_gen_vars();
// accept function for the general tab
void options_multi_gen_accept();
// do frame for the general tab
void options_multi_gen_do();
// check for button presses
void options_multi_gen_check_buttons();
// a button was pressed
void options_multi_gen_button_pressed(int n);
// voice options tab section -------------------------------------------
#define OM_VOX_NUM_BUTTONS 6
#define OM_VOX_VOICE_TEST 0
#define OM_VOX_VOICE_YES 1
#define OM_VOX_VOICE_NO 2
#define OM_VOX_PLIST_UP 3
#define OM_VOX_PLIST_DOWN 4
#define OM_VOX_VOICE_MUTE 5
UI_GADGET Om_vox_bogus;
ui_button_info Om_vox_buttons[GR_NUM_RESOLUTIONS][OM_VOX_NUM_BUTTONS] = {
{ // GR_640
ui_button_info("OVB_17", 562, 118, -1, -1, 17),
ui_button_info("OVB_19", 551, 208, -1, -1, 19),
ui_button_info("OVB_20", 599, 208, -1, -1, 20),
ui_button_info("OVB_21", 614, 256, -1, -1, 21),
ui_button_info("OVB_22", 614, 290, -1, -1, 22),
ui_button_info("OVB_23", 599, 354, -1, -1, 23),
},
{ // GR_640
ui_button_info("2_OVB_17", 900, 189, -1, -1, 17),
ui_button_info("2_OVB_19", 882, 333, -1, -1, 19),
ui_button_info("2_OVB_20", 959, 333, -1, -1, 20),
ui_button_info("2_OVB_21", 983, 410, -1, -1, 21),
ui_button_info("2_OVB_22", 983, 464, -1, -1, 22),
ui_button_info("2_OVB_23", 959, 566, -1, -1, 23),
}
};
// text
#define OM_VOX_NUM_TEXT 6
UI_XSTR Om_vox_text[GR_NUM_RESOLUTIONS][OM_VOX_NUM_TEXT] = {
{ // GR_640
{ "Mic test", 1389, 567, 104, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_TEST].button },
{ "Voice Quality", 1531, 439, 149, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
{ "Voice Transmission", 1530, 439, 193, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
{ "On", 1285, 556, 233, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_YES].button },
{ "Off", 1286, 604, 233, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_NO].button },
{ "Mute", 1390, 594, 381, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_MUTE].button },
},
{ // GR_1024
{ "mic test", 1389, 908, 166, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_TEST].button },
{ "Voice Quality", 1531, 703, 239, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
{ "Voice Transmission", 1530, 783, 310, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
{ "On", 1285, 890, 373, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_YES].button },
{ "Off", 1286, 967, 373, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_NO].button },
{ "Mute", 1390, 950, 609, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_MUTE].button },
}
};
#define NUM_OM_VOX_SLIDERS 1
#define OM_VOX_QOS_SLIDER 0
op_sliders Om_vox_sliders[GR_NUM_RESOLUTIONS][NUM_OM_VOX_SLIDERS] = {
{ // GR_640
op_sliders("OVB_18", 429, 162, -1, -1, 18, 20, 10, NULL, -1, -1, -1, NULL, -1, -1, -1), // voice QOS
},
{ // GR_1024
op_sliders("2_OVB_18", 686, 259, -1, -1, 18, 31, 10, NULL, -1, -1, -1, NULL, -1, -1, -1), // voice QOS
}
};
// player list area
int Om_vox_plist_coords[GR_NUM_RESOLUTIONS][4] = {
{ // GR_640
377, 270, 232, 79
},
{ // GR_1024
604, 432, 371, 127
}
};
int Om_vox_plist_max_display[GR_NUM_RESOLUTIONS] = {
6,
6
};
int Om_vox_plist_start;
UI_BUTTON Om_vox_plist_button;
// voice test buffer
#define OM_VOX_BUF_SIZE (1<<12)
#define OM_VOX_COMP_SIZE ((1<<15) + (1<<14))
#define OM_VOX_WAVE_Y 240
#define OM_VOX_WAVE_WIDTH 300
#define OM_VOX_DROP_ICON_X 100
#define OM_VOX_DROP_ICON_Y 100
#define OM_VOX_RECORD_INT 175
unsigned char Om_vox_voice_buffer[OM_VOX_BUF_SIZE];
int Om_vox_voice_buffer_size = -1;
unsigned char Om_vox_comp_buffer[OM_VOX_COMP_SIZE];
int Om_vox_voice_comp_size = -1;
sound_handle Om_vox_playback_handle;
// status of any test voice recording
#define OM_VOX_TEST_NONE -1
#define OM_VOX_TEST_RECORDING 0
#define OM_VOX_TEST_PLAYBACK 1
int Om_vox_test_status = OM_VOX_TEST_NONE;
// setting vars
int Om_vox_accept_voice;
// simple list of players we are looking through
net_player *Om_vox_players[MAX_PLAYERS];
// selected player
net_player *Om_vox_player_select;
// mute or don't mute for each player
int Om_vox_player_flags[MAX_PLAYERS];
// the # of players
int Om_vox_num_players;
// load all the voice tab controls
void options_multi_load_vox_controls();
// disable/hide all the voice tab controls
void options_multi_disable_vox_controls();
// enable/unhide all the voice tab controls
void options_multi_enable_vox_controls();
// initialize the voice tab vars
void options_multi_init_vox_vars();
// accept function for the voice tab
void options_multi_vox_accept();
// do frame for the voice tab
void options_multi_vox_do();
// check for button presses
void options_multi_vox_check_buttons();
// a button was pressed
void options_multi_vox_button_pressed(int n);
// process/display the player list
void options_multi_vox_process_player_list();
// scroll the player list down
void options_multi_vox_plist_scroll_down();
// scroll the player list up
void options_multi_vox_plist_scroll_up();
// get the index into the player list of the passed netplayer
int options_multi_vox_plist_get(net_player *pl);
// general data section ------------------------------------------------
// load all background bitmaps
void options_multi_load_bmaps()
{
// load both background bitmaps
Om_background_0 = bm_load(Om_background_0_fname[gr_screen.res]);
if(Om_background_0 == -1){
nprintf(("Network","Error loading options background %s\n",Om_background_0_fname[gr_screen.res]));
}
Om_background_1 = bm_load(Om_background_1_fname[gr_screen.res]);
if(Om_background_1 == -1){
nprintf(("Network","Error loading options background %s\n",Om_background_1_fname[gr_screen.res]));
}
// load in both mask bitmaps
Om_mask_0 = bm_load(Om_background_0_mask_fname[gr_screen.res]);
if(Om_mask_0 == -1){
nprintf(("Network","Error loading options background mask %s\n",Om_background_0_mask_fname[gr_screen.res]));
}
Om_mask_1 = bm_load(Om_background_1_mask_fname[gr_screen.res]);
if(Om_mask_1 == -1){
nprintf(("Network","Error loading options background mask %s\n",Om_background_1_mask_fname[gr_screen.res]));
}
}
// unload all the background bitmaps
void options_multi_unload_bmaps()
{
// unload all background bitmaps
if(Om_background_0 != -1){
bm_release(Om_background_0);
Om_background_0 = -1;
}
if(Om_background_1 != -1){
bm_release(Om_background_1);
Om_background_1 = -1;
}
// unload all mask bitmaps
if(Om_mask_0 != -1){
bm_release(Om_mask_0);
Om_mask_0 = -1;
}
if(Om_mask_1 != -1){
bm_release(Om_mask_1);
Om_mask_1 = -1;
}
}
// add a notification message
void options_multi_add_notify(const char *str)
{
// copy the string
memset(Om_notify_string,0,255);
if(str != NULL){
strcpy_s(Om_notify_string,str);
}
// set the timestamp
Om_notify_stamp = ui_timestamp(OM_NOTIFY_TIME);
}
// process and blit any notification messages
void options_multi_notify_process()
{
int w;
const char *p_str[3];
int n_chars[3];
char line[OM_NOTIFICATION_LINE_LEN];
int line_count;
int y_start;
int idx;
int line_height;
// if there is no timestamp, do nothing
if (!Om_notify_stamp.isValid()){
return;
}
// otherwise, if it has elapsed, unset it
if (ui_timestamp_elapsed(Om_notify_stamp)){
Om_notify_stamp = UI_TIMESTAMP::invalid();
return;
}
// otherwise display the string
line_height = gr_get_font_height() + 1;
line_count = split_str(Om_notify_string, 600, n_chars, p_str, 3, OM_NOTIFICATION_LINE_LEN);
y_start = OM_NOTIFY_Y;
gr_set_color_fast(&Color_bright);
for(idx=0;idx<line_count;idx++){
memset(line, 0, OM_NOTIFICATION_LINE_LEN);
strncpy(line, p_str[idx], n_chars[idx]);
gr_get_string_size(&w,NULL,line);
gr_string((600 - w)/2,y_start,line,GR_RESIZE_MENU);
y_start += line_height;
}
}
// protocol section --------------------------------------------------------
// load all the controls for the protocol section
void options_multi_load_protocol_controls()
{
int idx;
Assert(Om_window != NULL);
// instantiate all the buttons
for(idx=0; idx<OM_PRO_NUM_BUTTONS; idx++){
// create the object
Om_pro_buttons[gr_screen.res][idx].button.create(Om_window, "", Om_pro_buttons[gr_screen.res][idx].x, Om_pro_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
// set the sound to play when highlighted
Om_pro_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
// set the ani for the button
Om_pro_buttons[gr_screen.res][idx].button.set_bmaps(Om_pro_buttons[gr_screen.res][idx].filename);
// set the hotspot
Om_pro_buttons[gr_screen.res][idx].button.link_hotspot(Om_pro_buttons[gr_screen.res][idx].hotspot);
}
// text
for(idx=0; idx<OM_PRO_NUM_TEXT; idx++){
Om_window->add_XSTR(&Om_pro_text[gr_screen.res][idx]);
}
// create the tracker input boxes
Om_tracker_login.create(Om_window, Om_tracker_login_coords[gr_screen.res][0], Om_tracker_login_coords[gr_screen.res][1], Om_tracker_login_coords[gr_screen.res][2], LOGIN_LEN - 1, Multi_tracker_login, UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_KEYTHRU | UI_INPUTBOX_FLAG_NO_BACK);
Om_tracker_passwd.create(Om_window, Om_tracker_passwd_coords[gr_screen.res][0], Om_tracker_passwd_coords[gr_screen.res][1], Om_tracker_passwd_coords[gr_screen.res][2], LOGIN_LEN - 1, Multi_tracker_passwd, UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_PASSWD | UI_INPUTBOX_FLAG_KEYTHRU | UI_INPUTBOX_FLAG_NO_BACK);
Om_tracker_squad_name.create(Om_window, Om_tracker_squad_name_coords[gr_screen.res][0], Om_tracker_squad_name_coords[gr_screen.res][1], Om_tracker_squad_name_coords[gr_screen.res][2], LOGIN_LEN - 1, Multi_tracker_squad_name, UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_KEYTHRU | UI_INPUTBOX_FLAG_NO_BACK);
// create the invisible button for checking for clicks on the ip address list
Om_ip_button.create(Om_window, "", Ip_list_coords[gr_screen.res][0], Ip_list_coords[gr_screen.res][1], Ip_list_coords[gr_screen.res][2], Ip_list_coords[gr_screen.res][3], 0, 1);
Om_ip_button.hide();
// create the new ip address input box
Om_ip_input.create(Om_window, Ip_input_coords[gr_screen.res][0], Ip_input_coords[gr_screen.res][1], Ip_input_coords[gr_screen.res][2], IP_STRING_LEN, IP_EMPTY_STRING, UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_KEYTHRU);
Om_ip_input.hide();
Om_ip_input.disable();
// bogus control
Om_pro_bogus.base_create(Om_window, UI_KIND_ICON, 0, 0, 0, 0);
}
// disable/hide all the controls for the protocol section
void options_multi_disable_protocol_controls()
{
int idx;
// hide and disable all the protocol buttons
for(idx=0;idx<OM_PRO_NUM_BUTTONS;idx++){
// hide the button
Om_pro_buttons[gr_screen.res][idx].button.hide();
// disable the button
Om_pro_buttons[gr_screen.res][idx].button.disable();
}
// hide and disable the tracker input boxes
Om_tracker_login.hide();
Om_tracker_login.disable();
Om_tracker_passwd.hide();
Om_tracker_passwd.disable();
Om_tracker_squad_name.hide();
Om_tracker_squad_name.disable();
// disable the click detection button
Om_ip_button.disable();
// disable and hide the ip address inputbox
Om_ip_input.hide();
Om_ip_input.disable();
// undo input mode if necessary
Om_input_mode = 0;
// bogus control
Om_pro_bogus.hide();
Om_pro_bogus.disable();
}
// enable/unhide all the controls for the protocol section
void options_multi_enable_protocol_controls()
{
int idx;
// unhide and enable all the protocol buttons
for(idx=0;idx<OM_PRO_NUM_BUTTONS;idx++){
// enable the button
Om_pro_buttons[gr_screen.res][idx].button.enable();
// unhide the button
Om_pro_buttons[gr_screen.res][idx].button.unhide();
}
// unhide and enable the tracker input boxes
if(Om_tracker_flag){
Om_tracker_login.enable();
Om_tracker_passwd.enable();
Om_tracker_squad_name.enable();
}
Om_tracker_login.unhide();
Om_tracker_passwd.unhide();
Om_tracker_squad_name.unhide();
// enable the click detection button
Om_ip_button.enable();
// bogus control
Om_pro_bogus.enable();
Om_pro_bogus.unhide();
}
// intialize the protocol section vars
void options_multi_init_protocol_vars()
{
// current protocol
Om_protocol = Multi_options_g.protocol;
// whether or not the user has the local broadcast button selected
Om_local_broadcast = (Player->m_local_options.flags & MLO_FLAG_LOCAL_BROADCAST);
// whether or not we're playing on the tracker
Om_tracker_flag = Multi_options_g.pxo;
// load the ip address list
Om_ip_disp_count = 0;
options_multi_protocol_load_ip_file();
Om_ip_selected = Om_num_ips - 1;
Om_ip_start = Om_num_ips - 1;
}
// do frame for the protocol section
void options_multi_protocol_do(int key)
{
// check for button presses
options_multi_protocol_check_buttons();
// force draw the correct "local broadcast" button
if(Om_local_broadcast){
Om_pro_buttons[gr_screen.res][OM_PRO_LOCAL_BROADCAST].button.draw_forced(2);
}
// draw the "vmt" button if it is selected
if(Om_tracker_flag){
Om_pro_buttons[gr_screen.res][OM_PRO_VMT].button.draw_forced(2);
}
// see if he hit any interesting key presses
switch(key){
case KEY_ENTER:
// add a new ip string if we're in "input" mode
if(Om_input_mode){
options_multi_protocol_add_current_ip();
// clear the text control and input mode
Om_ip_input.set_text("");
Om_ip_input.clear_focus();
Om_ip_input.disable();
Om_input_mode = 0;
}
// if the tracker login inputbox has focus, lose it
if(Om_tracker_login.has_focus()){
Om_tracker_login.clear_focus();
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
}
// if the tracker password inputbox has focus, lose it
if(Om_tracker_passwd.has_focus()){
Om_tracker_passwd.clear_focus();
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
}
// if the tracker squad name inputbox has focus, lose it
if(Om_tracker_squad_name.has_focus()){
Om_tracker_squad_name.clear_focus();
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
}
break;
case KEY_ESC:
// if we're in input mode, cancel out
if(Om_input_mode){
// clear the text control and input mode
Om_ip_input.set_text("");
Om_ip_input.clear_focus();
Om_ip_input.disable();
Om_input_mode = 0;
}
// otherwise quit the options screen altogether
else {
// reaching this section is unlikely because
// escape key detection is already executed
// within options_menu_do_frame(),
// which runs before options_multi_do()
// --wookieejedi
options_cancel_exit();
return;
}
break;
case KEY_TAB:
// tab through the tracker input controls
if(Om_tracker_login.has_focus()){
Om_tracker_passwd.set_focus();
} else if(Om_tracker_passwd.has_focus()){
Om_tracker_squad_name.set_focus();
} else if(Om_tracker_squad_name.has_focus()){
Om_tracker_login.set_focus();
}
break;
}
// force draw the proper protocol
Om_pro_buttons[gr_screen.res][OM_PRO_TCP].button.draw_forced(2);
// force draw the proper tab button
switch (Om_mode) {
case OM_MODE_GENERAL:
Om_pro_buttons[gr_screen.res][OM_PRO_GEN_TAB].button.draw_forced(2);
break;
case OM_MODE_VOX:
Om_pro_buttons[gr_screen.res][OM_PRO_VOX_TAB].button.draw_forced(2);
break;
}
// check to see if the user has clicked on the ip list and selected a new item
options_multi_protocol_check_ip_list();
// draw the list of ip addresses
options_multi_protocol_display_ips();
// hack to play sound when input boxes gain focus
if (Om_tracker_login.has_focus()) {
if (Om_tracker_focus != TRACKER_FOCUS_LOGIN) {
Om_tracker_focus = TRACKER_FOCUS_LOGIN;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
} else if (Om_tracker_passwd.has_focus()) {
if (Om_tracker_focus != TRACKER_FOCUS_PASSWORD) {
Om_tracker_focus = TRACKER_FOCUS_PASSWORD;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
} else if (Om_tracker_squad_name.has_focus()) {
if (Om_tracker_focus != TRACKER_FOCUS_SQUADRON) {
Om_tracker_focus = TRACKER_FOCUS_SQUADRON;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
} else {
Om_tracker_focus = TRACKER_FOCUS_NONE;
}
}
// if the accept button was hit
void options_multi_protocol_accept()
{
// if the user has selected local broadcast write it into his options struct
Player->m_local_options.flags &= ~(MLO_FLAG_LOCAL_BROADCAST);
if (Om_local_broadcast) {
Player->m_local_options.flags |= MLO_FLAG_LOCAL_BROADCAST;
}
options::OptionsManager::instance()->set_ingame_binary_option("Multi.LocalBroadcast", Om_local_broadcast);
// active protocol
Multi_options_g.protocol = Om_protocol;
// VMT status
Multi_options_g.pxo = Om_tracker_flag;
options::OptionsManager::instance()->set_ingame_binary_option("Multi.TogglePXO", Om_tracker_flag);
// copy the VMT login, password and PXO squad name data
Om_tracker_login.get_text(Multi_tracker_login);
Om_tracker_passwd.get_text(Multi_tracker_passwd);
Om_tracker_squad_name.get_text(Multi_tracker_squad_name);
// write out the tracker login, passwd, and PXO squad name values to the registry
os_config_write_string( "PXO", "Login", Multi_tracker_login );
os_config_write_string( "PXO", "Password", Multi_tracker_passwd );
os_config_write_string( "PXO", "SquadName", Multi_tracker_squad_name );
// save the ip address list
options_multi_protocol_save_ip_file();
}
// check for button presses
void options_multi_protocol_check_buttons()
{
int idx;
// go through each button
for(idx=0;idx<OM_PRO_NUM_BUTTONS;idx++){
if(Om_pro_buttons[gr_screen.res][idx].button.pressed()){
options_multi_protocol_button_pressed(idx);
break;
}
}
}
// if a button was pressed
void options_multi_protocol_button_pressed(int n)
{
switch(n){
// add an ip address
case OM_PRO_ADD_IP:
// don't process if we're in input mode
if(Om_input_mode){
break;
}
// setup the input mode
Om_input_mode = 1;
Om_ip_input.enable();
Om_ip_input.unhide();
Om_ip_input.set_text(IP_EMPTY_STRING);
Om_ip_input.set_focus();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
// delete the currently selected ip
case OM_PRO_DELETE_IP:
// don't process if we're in input mode
if(Om_input_mode){
break;
}
options_multi_protocol_delete_ip();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
// the "local" broadcast button - toggle
case OM_PRO_LOCAL_BROADCAST:
// don't process if we're in input mode
if(Om_input_mode){
break;
}
Om_local_broadcast = !Om_local_broadcast;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
// scroll ips down
case OM_PRO_SCROLL_IP_DOWN:
// don't process if we're in input mode
if(Om_input_mode){
break;
}
options_multi_protocol_scroll_ip_down();
break;
// scroll ips up
case OM_PRO_SCROLL_IP_UP:
// don't process if we're in input mode
if(Om_input_mode){
break;
}
options_multi_protocol_scroll_ip_up();
break;
// the vmt button
case OM_PRO_VMT:
// for the multiplayer beta, always force tracker mode
// don't process if we're in input mode
if(Om_input_mode){
break;
}
// toggle the stupid thing
Om_tracker_flag = !Om_tracker_flag;
// if the thing is toggled on - enable the inputbox controls, else diable them
if(Om_tracker_flag){
Om_tracker_login.enable();
Om_tracker_passwd.enable();
Om_tracker_squad_name.enable();
} else {
Om_tracker_login.disable();
Om_tracker_passwd.disable();
Om_tracker_squad_name.disable();
}
// play a sound
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
// general tab button
case OM_PRO_GEN_TAB:
if(Om_mode != OM_MODE_GENERAL){
// set the general tab
Om_mode = OM_MODE_GENERAL;
// disable the voice controls
options_multi_disable_vox_controls();
// enable the general controls
options_multi_enable_gen_controls();
// set the general screen mask
Assert(Om_mask_0 >= 0);
Om_window->set_mask_bmap(Om_mask_0, Om_background_0_mask_fname[gr_screen.res]);
}
// play a sound
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
// voice tab button
case OM_PRO_VOX_TAB:
if(Om_mode != OM_MODE_VOX){
// set the voice tab
Om_mode = OM_MODE_VOX;
// disable the general controls
options_multi_disable_gen_controls();
// enable the voice controls
options_multi_enable_vox_controls();
// set the voice screen mask
Assert(Om_mask_1 >= 0);
Om_window->set_mask_bmap(Om_mask_1, Om_background_1_mask_fname[gr_screen.res]);
}
// play a sound
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
// tcp mode
case OM_PRO_TCP:
Om_protocol = NET_TCP;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
// ipx mode, no longer supported
case OM_PRO_IPX:
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, "The old IPX protocol is no longer supported.");
break;
}
}
// load the ip address file
void options_multi_protocol_load_ip_file()
{
// reset the ip address count
Om_num_ips = 0;
SCP_list<SCP_string> list;
multi_join_read_ip_address_file(list);
for (auto const &ip : list)
{
if (Om_num_ips < MAX_IP_ADDRS - 1) {
strcpy_s(Om_ip_addrs[Om_num_ips++], ip.c_str());
}
}
}
// save the ip address file
void options_multi_protocol_save_ip_file()
{
SCP_list<SCP_string> list;
// make a quick list
for(int idx=0;idx<Om_num_ips;idx++){
list.push_back(Om_ip_addrs[idx]);
}
multi_join_write_ip_address_file(list);
}
// draw the list of ip addresses
void options_multi_protocol_display_ips()
{
int idx;
int y_start = Ip_list_coords[gr_screen.res][1];
int line_height = gr_get_font_height() + 1;
// get the # of items we should be displaying based upon the # of addresses and the starting display point
if(Om_ip_start >= Ip_list_max_display[gr_screen.res]){
Om_ip_disp_count = Ip_list_max_display[gr_screen.res];
} else {
Om_ip_disp_count = Om_ip_start + 1;
}
// display the addresses
for(idx=Om_ip_start; idx >= Om_ip_start - Om_ip_disp_count + 1 ; idx--){
if(idx == Om_ip_selected){
gr_set_color_fast(&Color_bright);
} else {
gr_set_color_fast(&Color_white);
}
gr_printf_menu(Ip_list_coords[gr_screen.res][0], y_start, "%s", Om_ip_addrs[idx]);
y_start += line_height;
}
}
// scroll the list of ip addresses down
void options_multi_protocol_scroll_ip_down()
{
if(Om_ip_start >= Ip_list_max_display[gr_screen.res]){
gamesnd_play_iface(InterfaceSounds::SCROLL);
Om_ip_start--;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
// scroll the list of ip addresses up
void options_multi_protocol_scroll_ip_up()
{
if(Om_ip_start < Om_num_ips-1){
gamesnd_play_iface(InterfaceSounds::SCROLL);
Om_ip_start++;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
// check the ip list to see if the user has selected a new item
void options_multi_protocol_check_ip_list()
{
int click_y;
int item;
if(Om_ip_button.pressed()){
// determine which item he clicked on
Om_ip_button.get_mouse_pos(NULL, &click_y);
item = click_y / (gr_get_font_height() + 1);
// determine if there is an item in this location, and select it if so
if(item < Om_ip_disp_count){
Om_ip_selected = Om_ip_start - item;
}
}
}
// delete the currently selected ip if any
void options_multi_protocol_delete_ip()
{
int idx;
// attempt to delete the currently highlighted item
if(Om_ip_selected != -1){
// move down all the other items
for(idx=Om_ip_selected; idx < Om_num_ips; idx++){
strcpy_s(Om_ip_addrs[idx],Om_ip_addrs[idx+1]);
}
// make sure to decrement the starting index
Om_ip_start--;
// check to make sure that the selected item is valid
Om_num_ips--;
if(Om_num_ips <= 0){
Om_ip_selected = -1;
} else {
if(Om_ip_selected > 0){
Om_ip_selected--;
}
}
}
}
// return 10, if successflu
char Ip_str[IP_STRING_LEN+1];
int Ip_validated_already = 0;
int options_multi_verify_ip()
{
bool result;
if(!Ip_validated_already){
// see if its a valid ip address
result = psnet_is_valid_ip_string(Ip_str);
// if the result is a valid ip string, return immediately
if(result){
return 10;
}
// otherwise, change the popup text to indicate that it is invalid and wait for the user to click ok
popup_change_text(XSTR( "Ip string is invalid!", 386));
}
Ip_validated_already = 1;
// always wait for the user to hit the "cancel" button
return 0;
}
// attempt to add the currently entered ip address
void options_multi_protocol_add_current_ip()
{
// get the entered string
Om_ip_input.get_text(Ip_str);
// this popup wil do several things.
// 1.) It will display a popup so the user isn't left scratching his head
// 2.) If the address
Ip_validated_already = 0;
if(popup_till_condition(options_multi_verify_ip, XSTR( "Cancel", 387), XSTR( "Verifying ip address", 388)) == 10){
if(Om_num_ips < MAX_IP_ADDRS){
strcpy_s(Om_ip_addrs[Om_num_ips],Ip_str);
Om_ip_start = Om_num_ips;
Om_num_ips++;
// if this is the first item on the list, select it
if(Om_num_ips == 1){
Om_ip_selected = 0;
}
} else {
options_multi_add_notify(XSTR( "Max # of IP addresses reached!", 389));
}
}
}
// general options tab section -------------------------------------------
// load all the general tab controls
void options_multi_load_gen_controls()
{
int idx;
Assert(Om_window != NULL);
// instantiate all the buttons
for(idx=0; idx<OM_GEN_NUM_BUTTONS; idx++){
// create the object
Om_gen_buttons[gr_screen.res][idx].button.create(Om_window, "", Om_gen_buttons[gr_screen.res][idx].x, Om_gen_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
// set the sound to play when highlighted
Om_gen_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
// set the ani for the button
Om_gen_buttons[gr_screen.res][idx].button.set_bmaps(Om_gen_buttons[gr_screen.res][idx].filename);
// set the hotspot
Om_gen_buttons[gr_screen.res][idx].button.link_hotspot(Om_gen_buttons[gr_screen.res][idx].hotspot);
}
// text
for(idx=0; idx<OM_GEN_NUM_TEXT; idx++){
Om_window->add_XSTR(&Om_gen_text[gr_screen.res][idx]);
}
// bogus control
Om_gen_bogus.base_create(Om_window, UI_KIND_ICON, 0, 0, 0, 0);
}
// disable/hide all the general tab controls
void options_multi_disable_gen_controls()
{
int idx;
// go through all the controls
for(idx=0;idx<OM_GEN_NUM_BUTTONS;idx++){
Om_gen_buttons[gr_screen.res][idx].button.hide();
Om_gen_buttons[gr_screen.res][idx].button.disable();
}
// bogus control
Om_gen_bogus.hide();
Om_gen_bogus.disable();
}
// enable/unhide all the general tab controls
void options_multi_enable_gen_controls()
{
int idx;
// go through all the controls
for(idx=0;idx<OM_GEN_NUM_BUTTONS;idx++){
Om_gen_buttons[gr_screen.res][idx].button.enable();
Om_gen_buttons[gr_screen.res][idx].button.unhide();
}
// bogus control
Om_gen_bogus.enable();
Om_gen_bogus.unhide();
}
// initialize the general tab vars
void options_multi_init_gen_vars()
{
// initialize the object update
Om_gen_obj_update = Player->m_local_options.obj_update_level;
// initialize the accept pix var
Om_gen_pix = (Player->m_local_options.flags & MLO_FLAG_ACCEPT_PIX);
// initialize the xfer_multidata var
Om_gen_xfer_multidata = (Player->m_local_options.flags & MLO_FLAG_XFER_MULTIDATA);
// initialize the flush cache var
Om_gen_flush_cache = (Player->m_local_options.flags & MLO_FLAG_FLUSH_CACHE);
}
// accept function for the general tab
void options_multi_gen_accept()
{
// apply the object update level
Player->m_local_options.obj_update_level = Om_gen_obj_update;
// apply the accept pix var
Player->m_local_options.flags &= ~(MLO_FLAG_ACCEPT_PIX);
if(Om_gen_pix){
Player->m_local_options.flags |= MLO_FLAG_ACCEPT_PIX;
}
// apply the xfer multidata var
Player->m_local_options.flags &= ~(MLO_FLAG_XFER_MULTIDATA);
if(Om_gen_xfer_multidata){
Player->m_local_options.flags |= MLO_FLAG_XFER_MULTIDATA;
}
options::OptionsManager::instance()->set_ingame_binary_option("Multi.TransferMissions", Om_gen_xfer_multidata);
// apply the flush cache var
Player->m_local_options.flags &= ~(MLO_FLAG_FLUSH_CACHE);
if(Om_gen_flush_cache){
Player->m_local_options.flags |= MLO_FLAG_FLUSH_CACHE;
}
options::OptionsManager::instance()->set_ingame_binary_option("Multi.FlushCache", Om_gen_flush_cache);
}
// do frame for the general tab
void options_multi_gen_do()
{
// check for button presses
options_multi_gen_check_buttons();
// draw the proper object update button
switch(Om_gen_obj_update){
case OBJ_UPDATE_LOW:
Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_LOW].button.draw_forced(2);
break;
case OBJ_UPDATE_MEDIUM:
Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_MED].button.draw_forced(2);
break;
case OBJ_UPDATE_HIGH:
Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_HIGH].button.draw_forced(2);
break;
case OBJ_UPDATE_LAN:
Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_LAN].button.draw_forced(2);
break;
default :
Int3();
}
// draw the proper pix button
if(Om_gen_pix){
Om_gen_buttons[gr_screen.res][OM_GEN_PIX_YES].button.draw_forced(2);
} else {
Om_gen_buttons[gr_screen.res][OM_GEN_PIX_NO].button.draw_forced(2);
}
// draw the proper xfer multidata button
if(Om_gen_xfer_multidata){
Om_gen_buttons[gr_screen.res][OM_GEN_XFER_MULTIDATA_YES].button.draw_forced(2);
} else {
Om_gen_buttons[gr_screen.res][OM_GEN_XFER_MULTIDATA_NO].button.draw_forced(2);
}
// draw the proper flush cache button
if(Om_gen_flush_cache){
Om_gen_buttons[gr_screen.res][OM_GEN_FLUSH_YES].button.draw_forced(2);
} else {
Om_gen_buttons[gr_screen.res][OM_GEN_FLUSH_NO].button.draw_forced(2);
}
}
// check for button presses
void options_multi_gen_check_buttons()
{
int idx;
// go through all the buttons
for(idx=0;idx<OM_GEN_NUM_BUTTONS;idx++){
if(Om_gen_buttons[gr_screen.res][idx].button.pressed()){
options_multi_gen_button_pressed(idx);
break;
}
}
}
// a button was pressed
void options_multi_gen_button_pressed(int n)
{
switch(n){
// low object update level
case OM_GEN_OBJ_LOW:
if(Om_gen_obj_update != OBJ_UPDATE_LOW){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_obj_update = OBJ_UPDATE_LOW;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// medium object update level
case OM_GEN_OBJ_MED:
if(Om_gen_obj_update != OBJ_UPDATE_MEDIUM){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_obj_update = OBJ_UPDATE_MEDIUM;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// high object update level
case OM_GEN_OBJ_HIGH:
if(Om_gen_obj_update != OBJ_UPDATE_HIGH){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_obj_update = OBJ_UPDATE_HIGH;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// lan object update level
case OM_GEN_OBJ_LAN:
if(Om_gen_obj_update != OBJ_UPDATE_LAN){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_obj_update = OBJ_UPDATE_LAN;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// accept pix
case OM_GEN_PIX_YES:
if(!Om_gen_pix){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_pix = true;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// don't accept pix
case OM_GEN_PIX_NO:
if(Om_gen_pix){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_pix = false;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// put missions in the multidate directory
case OM_GEN_XFER_MULTIDATA_YES:
if(!Om_gen_xfer_multidata){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_xfer_multidata = true;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// don't put missions in the multidata directory
case OM_GEN_XFER_MULTIDATA_NO:
if(Om_gen_xfer_multidata){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_xfer_multidata = false;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// flush the cache before each mission
case OM_GEN_FLUSH_YES:
if(!Om_gen_flush_cache){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_flush_cache = true;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// don't flush the cache before each mission
case OM_GEN_FLUSH_NO:
if(Om_gen_flush_cache){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_flush_cache = false;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
}
}
// voice options tab section -------------------------------------------
// load all the voice tab controls
void options_multi_load_vox_controls()
{
int idx;
Assert(Om_window != NULL);
// instantiate all the buttons
for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
// create the object
Om_vox_buttons[gr_screen.res][idx].button.create(Om_window, "", Om_vox_buttons[gr_screen.res][idx].x, Om_vox_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
// set the sound to play when highlighted
Om_vox_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
// set the ani for the button
Om_vox_buttons[gr_screen.res][idx].button.set_bmaps(Om_vox_buttons[gr_screen.res][idx].filename);
// set the hotspot
Om_vox_buttons[gr_screen.res][idx].button.link_hotspot(Om_vox_buttons[gr_screen.res][idx].hotspot);
}
// text
for(idx=0; idx<OM_VOX_NUM_TEXT; idx++){
Om_window->add_XSTR(&Om_vox_text[gr_screen.res][idx]);
}
// sliders
for ( idx = 0; idx < NUM_OM_VOX_SLIDERS; idx++ ) {
Om_vox_sliders[gr_screen.res][idx].slider.create(Om_window, Om_vox_sliders[gr_screen.res][idx].x, Om_vox_sliders[gr_screen.res][idx].y,
Om_vox_sliders[gr_screen.res][idx].dots, Om_vox_sliders[gr_screen.res][idx].filename,
Om_vox_sliders[gr_screen.res][idx].hotspot,
Om_vox_sliders[gr_screen.res][idx].left_filename, Om_vox_sliders[gr_screen.res][idx].left_mask, Om_vox_sliders[gr_screen.res][idx].left_x, Om_vox_sliders[gr_screen.res][idx].left_y,
Om_vox_sliders[gr_screen.res][idx].right_filename, Om_vox_sliders[gr_screen.res][idx].right_mask, Om_vox_sliders[gr_screen.res][idx].right_x, Om_vox_sliders[gr_screen.res][idx].right_y,
Om_vox_sliders[gr_screen.res][idx].dot_w);
}
// create the player list select button
Om_vox_plist_button.create(Om_window, "", Om_vox_plist_coords[gr_screen.res][0], Om_vox_plist_coords[gr_screen.res][1], Om_vox_plist_coords[gr_screen.res][2], Om_vox_plist_coords[gr_screen.res][3], 0, 1);
Om_vox_plist_button.hide();
// build a list of net players
Om_vox_num_players = 0;
for(idx=0;idx<MAX_PLAYERS;idx++){
Om_vox_players[idx] = NULL;
// if i'm not connected, do nothing
if((Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_CONNECTED)){
continue;
}
// add all players I know about
if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (Net_player != &Net_players[idx])){
// set the netplayer pointer
Om_vox_players[Om_vox_num_players] = &Net_players[idx];
// set his mute flag
Om_vox_player_flags[Om_vox_num_players] = (Multi_voice_local_prefs & (1<<idx)) ? 1 : 0;
// increment the count
Om_vox_num_players++;
}
}
// bogus control
Om_vox_bogus.base_create(Om_window, UI_KIND_ICON, 0, 0, 0, 0);
}
// disable/hide all the voice tab controls
void options_multi_disable_vox_controls()
{
int idx;
// go through all the controls
for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
Om_vox_buttons[gr_screen.res][idx].button.hide();
Om_vox_buttons[gr_screen.res][idx].button.disable();
}
// hide the qos control
Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.hide();
Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.disable();
// unset the sound buffer size so we don't display any waveforms
Om_vox_voice_buffer_size = -1;
Om_vox_voice_comp_size = -1;
Om_vox_playback_handle = sound_handle::invalid();
Om_vox_test_status = OM_VOX_TEST_NONE;
// disable the player list select button
Om_vox_plist_button.disable();
// bogus controls
Om_vox_bogus.hide();
Om_vox_bogus.disable();
}
// enable/unhide all the voice tab controls
void options_multi_enable_vox_controls()
{
int idx;
// go through all the controls
for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
Om_vox_buttons[gr_screen.res][idx].button.enable();
Om_vox_buttons[gr_screen.res][idx].button.unhide();
}
// unhide the qos control
Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.enable();
Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.unhide();
// unset the sound buffer size so we don't display any waveforms
Om_vox_voice_buffer_size = -1;
Om_vox_voice_comp_size = -1;
Om_vox_playback_handle = sound_handle::invalid();
Om_vox_test_status = OM_VOX_TEST_NONE;
// select the first player on the list
Om_vox_player_select = Om_vox_players[0];
Om_vox_plist_start = 0;
// enable the player list select button
Om_vox_plist_button.enable();
// bogus controls
Om_vox_bogus.enable();
Om_vox_bogus.unhide();
}
// initialize the voice tab vars
void options_multi_init_vox_vars()
{
// intialize the accept voice var
if(Player->m_local_options.flags & MLO_FLAG_NO_VOICE){
Om_vox_accept_voice = 0;
} else {
Om_vox_accept_voice = 1;
}
}
// accept function for the voice tab
void options_multi_vox_accept()
{
int idx;
int voice_pref_flags;
// set the accept voice flag
Player->m_local_options.flags &= ~(MLO_FLAG_NO_VOICE);
if(!Om_vox_accept_voice){
Player->m_local_options.flags |= MLO_FLAG_NO_VOICE;
}
// build the voice preferences stuff
voice_pref_flags = 0xffffffff;
for(idx=0;idx<Om_vox_num_players;idx++){
// if this guy is muted
if(!Om_vox_player_flags[idx]){
voice_pref_flags &= ~(1 << NET_PLAYER_INDEX(Om_vox_players[idx]));
}
}
multi_voice_set_prefs(voice_pref_flags);
}
// do frame for the voice tab
void options_multi_vox_do()
{
int handle;
// check for button presses
options_multi_vox_check_buttons();
// draw the proper accept voice button
if(Om_vox_accept_voice){
Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_YES].button.draw_forced(2);
} else {
Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_NO].button.draw_forced(2);
}
// if the currently selected player is muted
if((Om_vox_player_select != NULL) && options_multi_vox_plist_get(Om_vox_player_select) > -1 && !Om_vox_player_flags[options_multi_vox_plist_get(Om_vox_player_select)]){
Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_MUTE].button.draw_forced(2);
}
// process and display the player list
options_multi_vox_process_player_list();
// if we're currently doing a voice test recording, process some stuff
switch(Om_vox_test_status){
case OM_VOX_TEST_RECORDING:
multi_voice_test_process();
// force draw the mic test button
Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_TEST].button.draw_forced(2);
// if we are no longer recording, switch to playback if possible
if(!multi_voice_test_recording()){
Om_vox_test_status = OM_VOX_TEST_PLAYBACK;
if(Om_vox_voice_comp_size != -1){
// stop any playing back sounds
rtvoice_stop_playback_all();
// attempt to get a playback handle
handle = multi_voice_test_get_playback_buffer();
if(handle != -1){
Om_vox_playback_handle = rtvoice_play(handle, Om_vox_comp_buffer, Om_vox_voice_comp_size);
// mark us as playing back
Om_vox_test_status = OM_VOX_TEST_PLAYBACK;
}
// on error, notify the user something is wrong
else {
options_multi_add_notify(XSTR( "Error trying to playback recorded voice! Check your hardware", 390));
// mark us as doing nothing
Om_vox_test_status = OM_VOX_TEST_NONE;
}
} else {
// mark us as doing nothing
Om_vox_test_status = OM_VOX_TEST_NONE;
}
}
break;
case OM_VOX_TEST_PLAYBACK:
// if we were playing a sound back, but now the sound is done
if ((Om_vox_playback_handle.isValid()) && !ds_is_channel_playing(ds_get_channel(Om_vox_playback_handle))) {
// flush all playing sounds safely
rtvoice_stop_playback_all();
// null the sound handle
Om_vox_playback_handle = sound_handle::invalid();
// set this so we know not to display any more waveforms
Om_vox_voice_buffer_size = -1;
Om_vox_voice_comp_size = -1;
// free the status up
Om_vox_test_status = OM_VOX_TEST_NONE;
}
break;
}
}
// check for button presses
void options_multi_vox_check_buttons()
{
int idx;
// go through all the buttons
for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
if(Om_vox_buttons[gr_screen.res][idx].button.pressed()){
options_multi_vox_button_pressed(idx);
break;
}
}
}
// a button was pressed
void options_multi_vox_button_pressed(int n)
{
switch(n){
// accept voice button
case OM_VOX_VOICE_YES:
if(!Om_vox_accept_voice){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_vox_accept_voice = 1;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// don't accept voice button
case OM_VOX_VOICE_NO:
if(Om_vox_accept_voice){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_vox_accept_voice = 0;
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// mute/unmute button
case OM_VOX_VOICE_MUTE:
if(Om_vox_player_select != NULL){
int index = options_multi_vox_plist_get(Om_vox_player_select);
// there's already an assertion for this in options_multi_vox_plist_get, just ignore in release
if (index < 0){
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
break;
}
Om_vox_player_flags[index] = !Om_vox_player_flags[index];
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
break;
// scroll the player list up
case OM_VOX_PLIST_UP:
options_multi_vox_plist_scroll_up();
break;
// scroll the player list down
case OM_VOX_PLIST_DOWN:
options_multi_vox_plist_scroll_down();
break;
// mic test button
case OM_VOX_VOICE_TEST:
// if in a multiplayer game, don't allow testing
if((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_CONNECTED)){
options_multi_add_notify(XSTR( "Cannot test mic while in a multiplayer game!", 391));
break;
}
// if this machine is not capable of playing
if(!Multi_voice_can_record){
options_multi_add_notify(XSTR( "DirectSoundCapture could not be initialized. To initialize DirectSoundCapture your sound card must be full duplex and your sound card drivers must support DirectSoundCapture", 392));
} else {
// if we're not already doing a record test
if(Om_vox_test_status == OM_VOX_TEST_NONE){
// set the quality of sound
rtvoice_set_qos(Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.pos + 1);
// clear the comp buffer
memset(Om_vox_comp_buffer,128,OM_VOX_COMP_SIZE);
Om_vox_test_status = OM_VOX_TEST_RECORDING;
multi_voice_test_record_start();
}
}
break;
}
}
// screen shader
extern shader Grey_shader;
// process and blit any voice waveform if necessary
void options_multi_vox_process_waveform()
{
int c_width = OM_VOX_WAVE_WIDTH;
int avg_len;
int buf_offset;
int idx,a_idx,running_avg;
// if we're not in recording or playback mode
if(Om_vox_test_status == OM_VOX_TEST_NONE){
return;
}
// grey the screen
gr_set_shader(&Grey_shader);
gr_shade(0,0,gr_screen.clip_width, gr_screen.clip_height, GR_RESIZE_NONE);
switch(Om_vox_test_status){
case OM_VOX_TEST_RECORDING:
// if we have no sound buffer size, do nothing
if(Om_vox_voice_buffer_size <= 0){
return;
}
// if we are not recording, do nothing
if(Om_vox_test_status != OM_VOX_TEST_RECORDING){
return;
}
// get the # of samples we'll average for one line
avg_len = Om_vox_voice_buffer_size / c_width;
// blit the waveform
gr_set_color_fast(&Color_green);
buf_offset = 0;
for(idx=0; idx < c_width; idx++){
// reset the running average
running_avg = 0;
for(a_idx = 0; a_idx < avg_len; a_idx++){
running_avg += (int)Om_vox_voice_buffer[buf_offset] - 128;
// increment the buffer offset
buf_offset++;
}
running_avg /= avg_len;
gr_line((gr_screen.max_w_unscaled - OM_VOX_WAVE_WIDTH)/2 + idx, OM_VOX_WAVE_Y, (gr_screen.max_w_unscaled - OM_VOX_WAVE_WIDTH)/2 + idx, OM_VOX_WAVE_Y + running_avg, GR_RESIZE_MENU);
}
// if this packet would have been dropped, notify the user
if(multi_voice_test_packet_tossed()){
gr_set_color_fast(&Color_bright);
gr_string(OM_VOX_DROP_ICON_X,OM_VOX_DROP_ICON_Y, XSTR( "Packet Overflow", 393), GR_RESIZE_MENU);
}
break;
case OM_VOX_TEST_PLAYBACK:
// get the offset into the playing direct sound buffer
buf_offset = ds_get_play_position(ds_get_channel(Om_vox_playback_handle));
// get the # of samples we'll average for one line
avg_len = (int)((float)OM_VOX_RECORD_INT * ((1024.0f * 11.0f) / 1000.0f)) / c_width;
// blit the waveform
gr_set_color_fast(&Color_red);
for(idx=0; idx < c_width; idx++){
// reset the running average
running_avg = 0;
for(a_idx = 0; a_idx < avg_len; a_idx++){
if(buf_offset < (OM_VOX_COMP_SIZE - 2)){
running_avg += (int)Om_vox_comp_buffer[buf_offset] - 128;
// increment the buffer offset
buf_offset++;
}
}
running_avg /= avg_len;
gr_line((gr_screen.max_w_unscaled - OM_VOX_WAVE_WIDTH)/2 + idx, OM_VOX_WAVE_Y, (gr_screen.max_w_unscaled - OM_VOX_WAVE_WIDTH)/2 + idx, OM_VOX_WAVE_Y + running_avg, GR_RESIZE_MENU);
}
break;
}
}
// process/display the player list
void options_multi_vox_process_player_list()
{
int idx;
int y_start,p_count;
int selected_index,click_y;
char str[CALLSIGN_LEN+2];
int line_height = gr_get_font_height() + 1;
// check for mouse clicks
if(Om_vox_plist_button.pressed()){
Om_vox_plist_button.get_mouse_pos(NULL,&click_y);
selected_index = (click_y / line_height) + Om_vox_plist_start;
// if he clicked on a valid player, select him
if(Om_vox_players[selected_index] != NULL){
Om_vox_player_select = Om_vox_players[selected_index];
nprintf(("Network","Selecting player %s\n",Om_vox_player_select->m_player->callsign));
}
}
// draw the list of players
p_count = 0;
y_start = Om_vox_plist_coords[gr_screen.res][1];
for(idx = Om_vox_plist_start; idx < Om_vox_num_players; idx++){
if(Om_vox_players[idx] != NULL){
// if he's the selected player, highlight him
if(Om_vox_players[idx] == Om_vox_player_select){
gr_set_color_fast(&Color_bright);
} else {
gr_set_color_fast(&Color_normal);
}
// force fit his callsign
strcpy_s(str,Om_vox_players[idx]->m_player->callsign);
font::force_fit_string(str, CALLSIGN_LEN+1, Om_vox_plist_coords[gr_screen.res][2]);
// blit the callsign
gr_string(Om_vox_plist_coords[gr_screen.res][0], y_start, str, GR_RESIZE_MENU);
// increment the y index
y_start += line_height;
// increment the player count
p_count++;
}
// if we've reached max display, break out
if(p_count >= Om_vox_plist_max_display[gr_screen.res]){
break;
}
}
}
// get the index into the player list of the passed netplayer
int options_multi_vox_plist_get(net_player *pl)
{
int idx;
for(idx=0;idx<Om_vox_num_players;idx++){
if(pl == Om_vox_players[idx]){
break;
}
}
// Should never get a bad value here, but the places where this is called can now handle the negative return value, as it's not catastrophic.
// Still Assert to assist with bug tracking in debug.
Assertion(idx < Om_vox_num_players, "options_multi_vox_plist_get() could not find the correct net player. Please report to an SCP member!");
if (idx >= Om_vox_num_players)
return -1;
else
return idx;
}
// scroll the player list down
void options_multi_vox_plist_scroll_down()
{
if(Om_vox_num_players < Om_vox_plist_max_display[gr_screen.res]){
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return;
}
if((Om_vox_num_players - Om_vox_plist_start) >= Om_vox_plist_max_display[gr_screen.res]){
Om_vox_plist_start++;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
// scroll the player list up
void options_multi_vox_plist_scroll_up()
{
if(Om_vox_plist_start > 0){
Om_vox_plist_start--;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
// extern functions -----------------------------------------------------
// called when the options screen is initialized, pass in the UI window
void options_multi_init(UI_WINDOW *options_window)
{
// assign the options window
Om_window = options_window;
// load the background bitmaps
options_multi_load_bmaps();
// load the controls for the protocol area
options_multi_load_protocol_controls();
// load the controls for the general tab
options_multi_load_gen_controls();
// load the controls for the voice tab
options_multi_load_vox_controls();
// disable all the protocol controls
options_multi_disable_protocol_controls();
// disable all the general tab controls
options_multi_disable_gen_controls();
// disable all the voice tab controls
options_multi_disable_vox_controls();
// intialize the protocol section vars
options_multi_init_protocol_vars();
// initialize the general tab vars
options_multi_init_gen_vars();
// initialize the voice tab vars
options_multi_init_vox_vars();
// intialize the multiplayer voice recording system
if( !((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_CONNECTED)) ){
multi_voice_init();
}
// set the default screen mode
Om_mode = OM_MODE_NONE;
}
// do frame for the multi options screen
void options_multi_do(int key)
{
// do frame for the protocol section
options_multi_protocol_do(key);
// process and blit any notification messages
options_multi_notify_process();
// process the proper tab control
switch(Om_mode){
case OM_MODE_GENERAL:
options_multi_gen_do();
break;
case OM_MODE_VOX:
options_multi_vox_do();
break;
default :
Int3();
}
}
// called when the entire options screen is closed
void options_multi_close()
{
// null out the window handle
Om_window = NULL;
// unload all background bitmaps
options_multi_unload_bmaps();
// stop any playing voice
rtvoice_stop_playback_all();
// unset the screen mode
Om_mode = OM_MODE_NONE;
}
/**
* Checks if the multiplayer config screen is in a legal state to exit
**/
bool options_multi_ok_to_accept()
{
// if PXO is turned on, do we have a username and password?
if (Multi_options_g.pxo) {
if (strlen(Multi_tracker_login) == 0) {
return false;
}
else if (strlen(Multi_tracker_passwd) == 0) {
return false;
}
}
return true;
}
/**
* Called if the accept button on the main options screen was hit.
* Also allows saving PXO credentials as "".
**/
void options_multi_accept()
{
// is it legal to leave this screen?
// The following check has been commented out for the following reasons:
// 1) Retail never had such a check,
// 2) when starting PXO in multiplayer, the PXO lobby screen
// displays a warning if the login values are actually valid or not,
// 3) and not having this function be a bool allows for
// much more streamlined option managment, especially with in-game options.
// --wookieejedi and confirmed with taylor
//if (!options_multi_ok_to_accept()) {
//return false;
//}
// accept function for the protocol section
options_multi_protocol_accept();
// accept function for the general tab
options_multi_gen_accept();
// accept function for the voice tab
options_multi_vox_accept();
// if Net_player is not null, copy these new settings to him
if(Net_player != NULL){
multi_options_local_load(&Net_player->p_info.options, NULL);
}
multi_options_local_load(&Player->m_local_options, NULL);
// if we're connected to a game server, update our options on the server now
if((Net_player != NULL) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && MULTI_CONNECTED(Net_players[MY_NET_PLAYER_NUM]) ){
multi_options_update_local();
}
// recall that in-game option values get persisted/saved to file within options_accept() in optionsmenu.cpp
}
// called when the multiplayer tab is hit - initializes/switches all necessary data.
// NOTE : this is different from the initialization function, which is called only when the options menu is started
void options_multi_select()
{
// set the windows mask bitmap
Assert(Om_mask_0 >= 0);
Om_window->set_mask_bmap(Om_mask_0, Om_background_0_mask_fname[gr_screen.res]);
// set the default screen mode
Om_mode = OM_MODE_GENERAL;
// clear any notification messages
Om_notify_stamp = UI_TIMESTAMP::invalid();
// enable all the protocol controls
options_multi_enable_protocol_controls();
// enable the general tab controls
options_multi_enable_gen_controls();
}
// return the bitmap handle of the current background bitmap, or -1 if the multiplayer tab is not active
int options_multi_background_bitmap()
{
// return the background bitmap mode based upon the current mode
switch(Om_mode){
case OM_MODE_GENERAL:
return Om_background_0;
case OM_MODE_VOX:
return Om_background_1;
}
// unknown mode of some kind
return -1;
}
// called when the multiplayer tab has been switched from
void options_multi_unselect()
{
// unset the mode
Om_mode = OM_MODE_NONE;
// disable all the protocol controls
options_multi_disable_protocol_controls();
// disable all the general tab controls
options_multi_disable_gen_controls();
// disable all the vox tab controls
options_multi_disable_vox_controls();
// stop any test voice recording
multi_voice_test_record_stop();
}
// set voice sound buffer for display
void options_multi_set_voice_data(unsigned char *sound_buf, int buf_size, double /*gain*/)
{
if ( (sound_buf == NULL) || (buf_size <= 0) ) {
return;
}
// copy the buffer to the vox tab data
Om_vox_voice_buffer_size = MIN(buf_size, OM_VOX_BUF_SIZE);
memcpy(Om_vox_voice_buffer, sound_buf, Om_vox_voice_buffer_size);
// copy and uncompress the compressed buffer
if(Om_vox_voice_comp_size == -1){
Om_vox_voice_comp_size = 0;
}
if ( (Om_vox_voice_comp_size + buf_size) < OM_VOX_COMP_SIZE ) {
memcpy(Om_vox_comp_buffer + Om_vox_voice_comp_size, sound_buf, buf_size);
Om_vox_voice_comp_size += buf_size;
}
}
// return whether we want to eat a tabbed keypress
int options_multi_eat_tab()
{
// do we want to eat the tab key or not
if(Om_tracker_passwd.has_focus() || Om_tracker_login.has_focus() || Om_tracker_squad_name.has_focus()){
return 1;
}
return 0;
}