2 * $Logfile: /Freespace2/code/MenuUI/OptionsMenuMulti.cpp $
8 * Revision 1.4 2002/06/05 08:05:29 relnev
9 * stub/warning removal.
11 * reworked the sound code.
13 * Revision 1.3 2002/06/02 06:02:59 relnev
16 * Revision 1.2 2002/05/07 03:16:46 theoddone33
17 * The Great Newline Fix
19 * Revision 1.1.1.1 2002/05/03 03:28:09 root
23 * 21 10/25/99 5:47p Jefff
24 * reassigned some xstr ids
26 * 20 8/02/99 2:44p Dave
27 * Disable IPX for demo build.
29 * 19 7/15/99 7:15p Jefff
30 * Added various sound FX
32 * 18 7/15/99 9:20a Andsager
33 * FS2_DEMO initial checkin
35 * 17 6/25/99 11:59a Dave
36 * Multi options screen.
38 * 16 6/22/99 7:03p Dave
39 * New detail options screen.
41 * 15 4/25/99 3:02p Dave
42 * Build defines for the E3 build.
44 * 14 2/25/99 4:19p Dave
45 * Added multiplayer_beta defines. Added cd_check define. Fixed a few
46 * release build warnings. Added more data to the squad war request and
49 * 13 2/19/99 2:55p Dave
50 * Temporary checking to report the winner of a squad war match.
52 * 12 2/17/99 2:10p Dave
53 * First full run of squad war. All freespace and tracker side stuff
56 * 11 2/12/99 6:16p Dave
57 * Pre-mission Squad War code is 95% done.
59 * 10 2/05/99 7:22p Neilk
60 * Fixed gamma bitmap and converted coordinates for multiple resolutions
62 * 9 2/02/99 11:36a Dave
63 * Removed obsolete data reference.
65 * 8 12/18/98 1:13a Dave
66 * Rough 1024x768 support for Direct3D. Proper detection and usage through
69 * 7 11/20/98 11:16a Dave
70 * Fixed up IPX support a bit. Making sure that switching modes and
71 * loading/saving pilot files maintains proper state.
73 * 6 11/19/98 4:19p Dave
74 * Put IPX sockets back in psnet. Consolidated all multiplayer config
77 * 5 11/05/98 5:55p Dave
78 * Big pass at reducing #includes
80 * 4 10/13/98 9:28a Dave
81 * Started neatening up freespace.h. Many variables renamed and
82 * reorganized. Added AlphaColors.[h,cpp]
84 * 3 10/09/98 2:57p Dave
85 * Starting splitting up OS stuff.
87 * 2 10/07/98 10:53a Dave
90 * 1 10/07/98 10:49a Dave
92 * 27 7/08/98 11:56a Dave
93 * Changed mic problem error message.
95 * 26 6/12/98 7:13p Hoffoss
96 * Fixed options screen problem where it wasn't showing tooltips.
98 * 25 6/09/98 10:31a Hoffoss
99 * Created index numbers for all xstr() references. Any new xstr() stuff
100 * added from here on out should be added to the end if the list. The
101 * current list count can be found in FreeSpace.cpp (search for
104 * 24 6/01/98 11:43a John
105 * JAS & MK: Classified all strings for localization.
107 * 23 5/21/98 9:45p Dave
108 * Lengthened tracker polling times. Put in initial support for PXO
109 * servers with channel filters. Fixed several small UI bugs.
111 * 22 5/20/98 2:24a Dave
112 * Fixed server side voice muting. Tweaked multi debrief/endgame
113 * sequencing a bit. Much friendlier for stats tossing/accepting now.
115 * 21 5/19/98 1:35a Dave
116 * Tweaked pxo interface. Added rankings url to pxo.cfg. Make netplayer
117 * local options update dynamically in netgames.
119 * 20 5/18/98 12:03p Frank
120 * Make sure network changes made in options screen are loaded into any
121 * current Net_player as well as the Player.
123 * 19 5/11/98 11:39p Dave
126 * 18 5/10/98 7:05p Dave
127 * Fix endgame sequencing ESC key. Changed how host options warning popups
128 * are done. Fixed pause/message scrollback/options screen problems in mp.
129 * Make sure observer HUD doesn't try to lock weapons.
131 * 17 5/08/98 7:08p Dave
132 * Lots of UI tweaking.
134 * 16 5/08/98 5:04p Dave
135 * Go to the join game screen when quitting multiplayer. Fixed mission
136 * text chat bugs. Put mission type symbols on the create game list.
137 * Started updating standalone gui controls.
139 * 15 5/07/98 12:57a Dave
140 * Fixed incorrect calls to free() from stats code. Put in new artwork for
141 * debrief and host options screens. Another modification to scoring
142 * system for secondary weapons.
144 * 14 5/06/98 8:06p Dave
145 * Made standalone reset properly under weird conditions. Tweak
146 * optionsmulti screen. Upped MAX_WEAPONS to 350. Put in new launch
147 * countdown anim. Minro ui fixes/tweaks.
149 * 13 5/02/98 5:38p Dave
150 * Put in new tracker API code. Put in ship information on mp team select
151 * screen. Make standalone server name permanent. Fixed standalone server
154 * 12 4/30/98 5:24p Adam
155 * JAS: Made multi config specify path.
157 * 11 4/28/98 5:13p Dave
158 * Remove references to old MT API
160 * 10 4/25/98 2:00p Dave
161 * Installed a bunch of multiplayer context help screens. Reworked ingame
162 * join ship select screen. Fix places where network timestamps get hosed.
164 * 9 4/22/98 4:09p John
165 * String externalization
167 * 8 4/22/98 12:34a Dave
168 * Make sure hud config and control config buttons draw properly in all
169 * tab modes. Make small tab buttons light up correctly in multi options
172 * 7 4/21/98 4:44p Dave
173 * Implement Vasudan ships in multiplayer. Added a debug function to bash
174 * player rank. Fixed a few rtvoice buffer overrun problems. Fixed ui
175 * problem in options screen.
177 * 6 4/20/98 6:04p Dave
178 * Implement multidata cache flushing and xferring mission files to
179 * multidata. Make sure observers can't change hud config. Fix pilot image
180 * viewing in popup. Put in game status field. Tweaked multi options.
182 * 5 4/18/98 12:45p Dave
183 * Aesthetic changes to multi options screen. Put in missing exit button.
186 * 4 4/17/98 6:33p Dave
187 * Finished first run of the screen. About time.
189 * 3 4/17/98 5:27p Dave
190 * More work on the multi options screen. Fixed many minor ui todo bugs.
192 * 2 4/17/98 12:42a Dave
193 * Worked on voice tab. Need to implement mic testing and player muting
196 * 1 4/16/98 11:39p Dave
209 #include "freespace.h"
212 #include "multi_voice.h"
215 #include "optionsmenu.h"
216 #include "optionsmenumulti.h"
218 #include "osregistry.h"
219 #include "alphacolors.h"
222 // general data section ------------------------------------------------
223 UI_WINDOW *Om_window = NULL;
225 static char* Om_background_0_fname[GR_NUM_RESOLUTIONS] = {
226 "OptionsMultiGen", // GR_640
227 "2_OptionsMultiGen" // GR_1024
230 static char* Om_background_0_mask_fname[GR_NUM_RESOLUTIONS] = {
231 "OptionsMultiGen-M", // GR_640
232 "2_OptionsMultiGen-M" // GR_1024
235 static char* Om_background_1_fname[GR_NUM_RESOLUTIONS] = {
236 "OptionsMultiVox", // GR_640
237 "2_OptionsMultiVox" // GR_1024
240 static char* Om_background_1_mask_fname[GR_NUM_RESOLUTIONS] = {
241 "OptionsMultiVox-M", // GR_640
242 "2_OptionsMultiVox-M" // GR_1024
245 int Om_background_0 = -1;
248 int Om_background_1 = -1;
252 #define OM_MODE_NONE -1 // no mode (unintialized)
253 #define OM_MODE_GENERAL 0 // general tab
254 #define OM_MODE_VOX 1 // voice tab
255 int Om_mode = OM_MODE_NONE;
257 // notification stuff
258 #define OM_NOTIFY_TIME 8000
259 #define OM_NOTIFY_Y 430
260 #define OM_NOTIFY_Y2 440
261 int Om_notify_stamp = -1;
262 char Om_notify_string[255];
264 // load all background bitmaps
265 void options_multi_load_bmaps();
267 // unload all the background bitmaps
268 void options_multi_unload_bmaps();
270 // add a notification message
271 void options_multi_add_notify(char *str);
273 // process and blit any notification messages
274 void options_multi_notify_process();
277 // protocol options section -------------------------------------------
278 #define OM_PRO_NUM_BUTTONS 10
282 #define OM_PRO_SCROLL_IP_UP 2
283 #define OM_PRO_SCROLL_IP_DOWN 3
284 #define OM_PRO_ADD_IP 4
285 #define OM_PRO_DELETE_IP 5
286 #define OM_PRO_LOCAL_BROADCAST 6
288 #define OM_PRO_VOX_TAB 8
289 #define OM_PRO_GEN_TAB 9
291 ui_button_info Om_pro_buttons[GR_NUM_RESOLUTIONS][OM_PRO_NUM_BUTTONS] = {
293 ui_button_info("OMuB_07", 7, 66, -1, -1, 7),
294 ui_button_info("OMuB_08", 7, 84, -1, -1, 8),
295 ui_button_info("OMuB_09", 1, 124, -1, -1, 9),
296 ui_button_info("OMuB_10", 1, 157, -1, -1, 10),
297 ui_button_info("OMuB_11", 20, 207, -1, -1, 11),
298 ui_button_info("OMuB_12", 64, 207, -1, -1, 12),
299 ui_button_info("OMuB_13", 9, 251, -1, -1, 13),
300 ui_button_info("OMuB_14", 9, 282, -1, -1, 14),
301 ui_button_info("OMuB_15", 610, 53, -1, -1, 15),
302 ui_button_info("OMuB_16", 610, 72, -1, -1, 16),
305 ui_button_info("2_OMuB_07", 12, 105, -1, -1, 7),
306 ui_button_info("2_OMuB_08", 12, 134, -1, -1, 8),
307 ui_button_info("2_OMuB_09", 2, 198, -1, -1, 9),
308 ui_button_info("2_OMuB_10", 2, 252, -1, -1, 10),
309 ui_button_info("2_OMuB_11", 32, 332, -1, -1, 11),
310 ui_button_info("2_OMuB_12", 103, 332, -1, -1, 12),
311 ui_button_info("2_OMuB_13", 14, 402, -1, -1, 13),
312 ui_button_info("2_OMuB_14", 14, 452, -1, -1, 14),
313 ui_button_info("2_OMuB_15", 976, 85, -1, -1, 15),
314 ui_button_info("2_OMuB_16", 976, 114, -1, -1, 16),
318 UI_GADGET Om_pro_bogus;
321 #define OM_PRO_NUM_TEXT 12
322 UI_XSTR Om_pro_text[GR_NUM_RESOLUTIONS][OM_PRO_NUM_TEXT] = {
324 { "TCP", 1378, 38, 70, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_TCP].button },
325 { "IPX", 1379, 38, 88, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_IPX].button },
326 { "IP Address", 1380, 30, 128, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
327 { "add", 1381, 22, 235, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_ADD_IP].button },
328 { "rem.", 1382, 68, 235, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_DELETE_IP].button },
329 { "Broadcast Locally", 1397, 42, 260, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_LOCAL_BROADCAST].button },
330 { "PXO", 1383, 42, 291, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_VMT].button },
331 { "Login", 1384, 14, 309, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
332 { "Password", 1385, 14, 336, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
333 { "Squadron", 1386, 14, 363, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
334 { "Voice", 1528, 557, 60, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_VOX_TAB].button },
335 { "General", 1388, 542, 77, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_GEN_TAB].button },
338 { "TCP", 1378, 61, 113, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_TCP].button },
339 { "IPX", 1379, 61, 141, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_IPX].button },
340 { "IP Address", 1380, 47, 206, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
341 { "add", 1381, 36, 375, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_ADD_IP].button },
342 { "rem.", 1382, 109, 375, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_DELETE_IP].button },
343 { "Broadcast Locally", 1397, 68, 417, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_LOCAL_BROADCAST].button },
344 { "PXO", 1383, 68, 467, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_VMT].button },
345 { "Login", 1384, 23, 495, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
346 { "Password", 1385, 23, 538, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
347 { "Squadron", 1386, 23, 582, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
348 { "Voice", 1528, 921, 96, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_VOX_TAB].button },
349 { "General", 1388, 902, 123, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_GEN_TAB].button },
353 // defines for the tracker input boxes
354 int Om_tracker_login_coords[GR_NUM_RESOLUTIONS][4] = {
356 19, 322, 226, -1 // GR_640
359 31, 518, 361, -1 // GR_1024
362 int Om_tracker_passwd_coords[GR_NUM_RESOLUTIONS][4] = {
364 19, 350, 226, -1 // GR_640
367 31, 562, 361, -1 // GR_1024
370 int Om_tracker_squad_name_coords[GR_NUM_RESOLUTIONS][4] = {
372 19, 378, 226, -1 // GR_640
375 31, 607, 361, -1 // GR_1024
379 // protocol section tracker login input box
380 UI_INPUTBOX Om_tracker_login;
382 // protocol section tracker passwd input box
383 UI_INPUTBOX Om_tracker_passwd;
385 // pxo squad name/password
386 UI_INPUTBOX Om_tracker_squad_name;
388 #define TRACKER_FOCUS_NONE 0
389 #define TRACKER_FOCUS_LOGIN 1
390 #define TRACKER_FOCUS_PASSWORD 2
391 #define TRACKER_FOCUS_SQUADRON 3
392 static int Om_tracker_focus = 0;
394 // ip address list vars
395 #define IP_STRING_LEN 255
396 #define MAX_IP_ADDRS 100
398 #define IP_EMPTY_STRING ""
400 int Ip_list_coords[GR_NUM_RESOLUTIONS][4] = {
402 29, 137, 227, 67 // GR_640
405 46, 220, 364, 106 // GR_1024
410 int Ip_list_max_display[GR_NUM_RESOLUTIONS] = {
415 static int Ip_input_coords[GR_NUM_RESOLUTIONS][4] = {
417 109, 128, 140, -1 // GR_640
420 132, 206, 261, -1 // GR_640
424 int Om_input_mode = 0;
425 int Om_ip_start; // index of the first element to be displayed in the list box
426 int Om_ip_selected; // the selected default IP address
427 int Om_ip_disp_count; // how many items are currently being displayed
428 int Om_num_ips; // # of ip addresses we have
429 char Om_ip_addrs[MAX_IP_ADDRS][IP_STRING_LEN]; // the ip addresses themselves
430 UI_BUTTON Om_ip_button; // button for detecting clicks on the ip address list
431 UI_INPUTBOX Om_ip_input; // input box for adding new ip addresses
434 int Om_local_broadcast; // whether the player has local broadcast selected or not
435 int Om_tracker_flag; // if the guy has the tracker selected
436 int Om_protocol; // protocol in use
438 // load all the controls for the protocol section
439 void options_multi_load_protocol_controls();
441 // disable/hide all the controls for the protocol section
442 void options_multi_disable_protocol_controls();
444 // enable/unhide all the controls for the protocol section
445 void options_multi_enable_protocol_controls();
447 // intialize the protocol section vars
448 void options_multi_init_protocol_vars();
450 // do frame for the protocol section
451 void options_multi_protocol_do(int key);
453 // if the accept button was hit
454 void options_multi_protocol_accept();
456 // check for button presses
457 void options_multi_protocol_check_buttons();
459 // if a button was pressed
460 void options_multi_protocol_button_pressed(int n);
462 // load the ip address file
463 void options_multi_protocol_load_ip_file();
465 // save the ip address file
466 void options_multi_protocol_save_ip_file();
468 // draw the list of ip addresses
469 void options_multi_protocol_display_ips();
471 // scroll the list of ip addresses down
472 void options_multi_protocol_scroll_ip_down();
474 // scroll the list of ip addresses up
475 void options_multi_protocol_scroll_ip_up();
477 // check the ip list to see if the user has selected a new item
478 void options_multi_protocol_check_ip_list();
480 // delete the currently selected ip if any
481 void options_multi_protocol_delete_ip();
483 // attempt to add the currently entered ip address
484 void options_multi_protocol_add_current_ip();
487 // general options tab section -------------------------------------------
488 #define OM_GEN_NUM_BUTTONS 10
490 #define OM_GEN_OBJ_LOW 0
491 #define OM_GEN_OBJ_MED 1
492 #define OM_GEN_OBJ_HIGH 2
493 #define OM_GEN_OBJ_LAN 3
494 #define OM_GEN_PIX_YES 4
495 #define OM_GEN_PIX_NO 5
496 #define OM_GEN_XFER_MULTIDATA_YES 6
497 #define OM_GEN_XFER_MULTIDATA_NO 7
498 #define OM_GEN_FLUSH_NO 8
499 #define OM_GEN_FLUSH_YES 9
501 ui_button_info Om_gen_buttons[GR_NUM_RESOLUTIONS][OM_GEN_NUM_BUTTONS] = {
503 ui_button_info("OGB_17", 598, 117, -1, -1, 17),
504 ui_button_info("OGB_18", 598, 139, -1, -1, 18),
505 ui_button_info("OGB_19", 598, 161, -1, -1, 19),
506 ui_button_info("OGB_20", 598, 183, -1, -1, 20),
507 ui_button_info("OGB_21", 549, 229, -1, -1, 21),
508 ui_button_info("OGB_22", 598, 229, -1, -1, 22),
509 ui_button_info("OGB_23", 598, 286, -1, -1, 23),
510 ui_button_info("OGB_24", 598, 307, -1, -1, 24),
511 ui_button_info("OGB_25", 598, 347, -1, -1, 25),
512 ui_button_info("OGB_26", 598, 368, -1, -1, 26),
515 ui_button_info("2_OGB_17", 957, 188, -1, -1, 17),
516 ui_button_info("2_OGB_18", 957, 223, -1, -1, 18),
517 ui_button_info("2_OGB_19", 957, 258, -1, -1, 19),
518 ui_button_info("2_OGB_20", 957, 293, -1, -1, 20),
519 ui_button_info("2_OGB_21", 879, 366, -1, -1, 21),
520 ui_button_info("2_OGB_22", 957, 366, -1, -1, 22),
521 ui_button_info("2_OGB_23", 957, 457, -1, -1, 23),
522 ui_button_info("2_OGB_24", 957, 491, -1, -1, 24),
523 ui_button_info("2_OGB_25", 957, 555, -1, -1, 25),
524 ui_button_info("2_OGB_26", 957, 589, -1, -1, 26),
528 UI_GADGET Om_gen_bogus;
531 #define OM_GEN_NUM_TEXT 14
532 UI_XSTR Om_gen_text[GR_NUM_RESOLUTIONS][OM_GEN_NUM_TEXT] = {
534 { "Object Update", 1391, 511, 104, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
535 { "Low", 1160, 558, 127, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_LOW].button },
536 { "Medium", 1161, 538, 149, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_MED].button },
537 { "High", 1162, 556, 171, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_HIGH].button },
538 { "Lan", 1392, 561, 193, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_LAN].button },
539 { "Pilot / Squad Images", 1393, 463, 214, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
540 { "Yes", 1394, 555, 257, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_PIX_YES].button },
541 { "No", 1395, 604, 257, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_PIX_NO].button },
542 { "Transfer Missions", 1396, 478, 271, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
543 { "/multidata", 1397, 519, 292, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_XFER_MULTIDATA_YES].button },
544 { "/missions", 1398, 527, 314, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_XFER_MULTIDATA_NO].button },
545 { "Flush Cache", 1399, 529, 334, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
546 { "Never", 1400, 548, 355, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_FLUSH_NO].button },
547 { "Before Game", 1401, 502, 377, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_FLUSH_YES].button },
550 { "Object Update", 1391, 818, 166, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
551 { "Low", 1160, 913, 204, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_LOW].button },
552 { "Medium", 1161, 892, 239, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_MED].button },
553 { "High", 1162, 909, 274, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_HIGH].button },
554 { "Lan", 1392, 916, 310, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_LAN].button },
555 { "Pilot / Squad Images", 1393, 821, 345, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
556 { "Yes", 1394, 887, 411, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_PIX_YES].button },
557 { "No", 1395, 966, 411, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_PIX_NO].button },
558 { "Transfer Missions", 1396, 844, 435, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
559 { "/multidata", 1397, 858, 468, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_XFER_MULTIDATA_YES].button },
560 { "/missions", 1398, 870, 503, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_XFER_MULTIDATA_NO].button },
561 { "Flush Cache", 1399, 886, 533, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
562 { "Never", 1400, 897, 568, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_FLUSH_NO].button },
563 { "Before Game", 1401, 849, 603, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_FLUSH_YES].button },
568 int Om_gen_obj_update; // object update level
569 int Om_gen_pix; // accept pilot pix or not
570 int Om_gen_xfer_multidata; // xfer missions to multidata or not
571 int Om_gen_flush_cache; // flush multidata directory before every game
573 // load all the general tab controls
574 void options_multi_load_gen_controls();
576 // disable/hide all the general tab controls
577 void options_multi_disable_gen_controls();
579 // enable/unhide all the general tab controls
580 void options_multi_enable_gen_controls();
582 // initialize the general tab vars
583 void options_multi_init_gen_vars();
585 // accept function for the general tab
586 void options_multi_gen_accept();
588 // do frame for the general tab
589 void options_multi_gen_do();
591 // check for button presses
592 void options_multi_gen_check_buttons();
594 // a button was pressed
595 void options_multi_gen_button_pressed(int n);
598 // voice options tab section -------------------------------------------
599 #define OM_VOX_NUM_BUTTONS 6
601 #define OM_VOX_VOICE_TEST 0
602 #define OM_VOX_VOICE_YES 1
603 #define OM_VOX_VOICE_NO 2
604 #define OM_VOX_PLIST_UP 3
605 #define OM_VOX_PLIST_DOWN 4
606 #define OM_VOX_VOICE_MUTE 5
608 UI_GADGET Om_vox_bogus;
610 ui_button_info Om_vox_buttons[GR_NUM_RESOLUTIONS][OM_VOX_NUM_BUTTONS] = {
612 ui_button_info("OVB_17", 562, 118, -1, -1, 17),
613 ui_button_info("OVB_19", 551, 208, -1, -1, 19),
614 ui_button_info("OVB_20", 599, 208, -1, -1, 20),
615 ui_button_info("OVB_21", 614, 256, -1, -1, 21),
616 ui_button_info("OVB_22", 614, 290, -1, -1, 22),
617 ui_button_info("OVB_23", 599, 354, -1, -1, 23),
620 ui_button_info("2_OVB_17", 900, 189, -1, -1, 17),
621 ui_button_info("2_OVB_19", 882, 333, -1, -1, 19),
622 ui_button_info("2_OVB_20", 959, 333, -1, -1, 20),
623 ui_button_info("2_OVB_21", 983, 410, -1, -1, 21),
624 ui_button_info("2_OVB_22", 983, 464, -1, -1, 22),
625 ui_button_info("2_OVB_23", 959, 566, -1, -1, 23),
630 #define OM_VOX_NUM_TEXT 6
631 UI_XSTR Om_vox_text[GR_NUM_RESOLUTIONS][OM_VOX_NUM_TEXT] = {
633 { "Mic test", 1389, 567, 104, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_TEST].button },
634 { "Voice Quality", 1531, 439, 149, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
635 { "Voice Transmission", 1530, 439, 193, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
636 { "On", 1285, 556, 233, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_YES].button },
637 { "Off", 1286, 604, 233, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_NO].button },
638 { "Mute", 1390, 594, 381, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_MUTE].button },
641 { "mic test", 1389, 908, 166, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_TEST].button },
642 { "Voice Quality", 1531, 703, 239, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
643 { "Voice Transmission", 1530, 783, 310, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
644 { "On", 1285, 890, 373, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_YES].button },
645 { "Off", 1286, 967, 373, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_NO].button },
646 { "Mute", 1390, 950, 609, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_MUTE].button },
650 #define NUM_OM_VOX_SLIDERS 1
651 #define OM_VOX_QOS_SLIDER 0
653 op_sliders Om_vox_sliders[GR_NUM_RESOLUTIONS][NUM_OM_VOX_SLIDERS] = {
655 op_sliders("OVB_18", 429, 162, -1, -1, 18, 20, 10, NULL, -1, -1, -1, NULL, -1, -1, -1), // voice QOS
658 op_sliders("2_OVB_18", 686, 259, -1, -1, 18, 20, 10, NULL, -1, -1, -1, NULL, -1, -1, -1), // voice QOS
663 int Om_vox_plist_coords[GR_NUM_RESOLUTIONS][4] = {
671 int Om_vox_plist_max_display[GR_NUM_RESOLUTIONS] = {
676 int Om_vox_plist_start;
677 UI_BUTTON Om_vox_plist_button;
680 #define OM_VOX_BUF_SIZE (1<<12)
681 #define OM_VOX_COMP_SIZE ((1<<15) + (1<<14))
683 #define OM_VOX_WAVE_Y 240
684 #define OM_VOX_WAVE_WIDTH 300
686 #define OM_VOX_DROP_ICON_X 100
687 #define OM_VOX_DROP_ICON_Y 100
689 #define OM_VOX_RECORD_INT 175
691 unsigned char Om_vox_voice_buffer[OM_VOX_BUF_SIZE];
692 int Om_vox_voice_buffer_size = -1;
694 unsigned char Om_vox_comp_buffer[OM_VOX_COMP_SIZE];
695 int Om_vox_voice_comp_size = -1;
697 int Om_vox_playback_handle;
699 // status of any test voice recording
700 #define OM_VOX_TEST_NONE -1
701 #define OM_VOX_TEST_RECORDING 0
702 #define OM_VOX_TEST_PLAYBACK 1
703 int Om_vox_test_status = OM_VOX_TEST_NONE;
706 int Om_vox_accept_voice;
708 // simple list of players we are looking through
709 net_player *Om_vox_players[MAX_PLAYERS];
712 net_player *Om_vox_player_select;
714 // mute or don't mute for each player
715 int Om_vox_player_flags[MAX_PLAYERS];
718 int Om_vox_num_players;
720 // load all the voice tab controls
721 void options_multi_load_vox_controls();
723 // disable/hide all the voice tab controls
724 void options_multi_disable_vox_controls();
726 // enable/unhide all the voice tab controls
727 void options_multi_enable_vox_controls();
729 // initialize the voice tab vars
730 void options_multi_init_vox_vars();
732 // accept function for the voice tab
733 void options_multi_vox_accept();
735 // do frame for the voice tab
736 void options_multi_vox_do();
738 // check for button presses
739 void options_multi_vox_check_buttons();
741 // a button was pressed
742 void options_multi_vox_button_pressed(int n);
744 // process/display the player list
745 void options_multi_vox_process_player_list();
747 // scroll the player list down
748 void options_multi_vox_plist_scroll_down();
750 // scroll the player list up
751 void options_multi_vox_plist_scroll_up();
753 // get the index into the player list of the passed netplayer
754 int options_multi_vox_plist_get(net_player *pl);
757 // general data section ------------------------------------------------
759 // load all background bitmaps
760 void options_multi_load_bmaps()
762 // load both background bitmaps
763 Om_background_0 = bm_load(Om_background_0_fname[gr_screen.res]);
764 if(Om_background_0 == -1){
765 nprintf(("Network","Error loading options background %s\n",Om_background_0_fname[gr_screen.res]));
768 Om_background_1 = bm_load(Om_background_1_fname[gr_screen.res]);
769 if(Om_background_1 == -1){
770 nprintf(("Network","Error loading options background %s\n",Om_background_1_fname[gr_screen.res]));
773 // load in both mask bitmaps
774 Om_mask_0 = bm_load(Om_background_0_mask_fname[gr_screen.res]);
776 nprintf(("Network","Error loading options background mask %s\n",Om_background_0_mask_fname[gr_screen.res]));
779 Om_mask_1 = bm_load(Om_background_1_mask_fname[gr_screen.res]);
781 nprintf(("Network","Error loading options background mask %s\n",Om_background_1_mask_fname[gr_screen.res]));
785 // unload all the background bitmaps
786 void options_multi_unload_bmaps()
788 // unload all background bitmaps
789 if(Om_background_0 != -1){
790 bm_release(Om_background_0);
791 Om_background_0 = -1;
793 if(Om_background_1 != -1){
794 bm_release(Om_background_1);
795 Om_background_1 = -1;
798 // unload all mask bitmaps
800 bm_release(Om_mask_0);
804 bm_release(Om_mask_1);
809 // add a notification message
810 void options_multi_add_notify(char *str)
813 memset(Om_notify_string,0,255);
815 strcpy(Om_notify_string,str);
819 Om_notify_stamp = timestamp(OM_NOTIFY_TIME);
822 // process and blit any notification messages
823 void options_multi_notify_process()
833 // if there is no timestamp, do nothing
834 if(Om_notify_stamp == -1){
838 // otherwise, if it has elapsed, unset it
839 if(timestamp_elapsed(Om_notify_stamp)){
840 Om_notify_stamp = -1;
844 // otherwise display the string
845 line_count = split_str(Om_notify_string, 600, n_chars, p_str, 3);
846 y_start = OM_NOTIFY_Y;
847 gr_set_color_fast(&Color_bright);
848 for(idx=0;idx<line_count;idx++){
849 memset(line, 0, 255);
850 strncpy(line, p_str[idx], n_chars[idx]);
852 gr_get_string_size(&w,NULL,line);
853 gr_string((600 - w)/2,y_start,line);
860 // protocol section --------------------------------------------------------
862 // load all the controls for the protocol section
863 void options_multi_load_protocol_controls()
867 Assert(Om_window != NULL);
869 // instantiate all the buttons
870 for(idx=0; idx<OM_PRO_NUM_BUTTONS; idx++){
872 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);
874 // set the sound to play when highlighted
875 Om_pro_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
877 // set the ani for the button
878 Om_pro_buttons[gr_screen.res][idx].button.set_bmaps(Om_pro_buttons[gr_screen.res][idx].filename);
881 Om_pro_buttons[gr_screen.res][idx].button.link_hotspot(Om_pro_buttons[gr_screen.res][idx].hotspot);
885 for(idx=0; idx<OM_PRO_NUM_TEXT; idx++){
886 Om_window->add_XSTR(&Om_pro_text[gr_screen.res][idx]);
889 // create the tracker input boxes
890 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);
891 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], 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);
892 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);
894 // create the invisible button for checking for clicks on the ip address list
895 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);
898 // create the new ip address input box
899 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);
901 Om_ip_input.disable();
903 // disable IPX button in demo
905 Om_pro_buttons[gr_screen.res][OM_PRO_IPX].button.disable();
906 Om_pro_buttons[gr_screen.res][OM_PRO_IPX].button.hide();
910 Om_pro_bogus.base_create(Om_window, UI_KIND_ICON, 0, 0, 0, 0);
913 // disable/hide all the controls for the protocol section
914 void options_multi_disable_protocol_controls()
918 // hide and disable all the protocol buttons
919 for(idx=0;idx<OM_PRO_NUM_BUTTONS;idx++){
921 Om_pro_buttons[gr_screen.res][idx].button.hide();
923 // disable the button
924 Om_pro_buttons[gr_screen.res][idx].button.disable();
927 // hide and disable the tracker input boxes
928 Om_tracker_login.hide();
929 Om_tracker_login.disable();
930 Om_tracker_passwd.hide();
931 Om_tracker_passwd.disable();
932 Om_tracker_squad_name.hide();
933 Om_tracker_squad_name.disable();
935 // disable the click detection button
936 Om_ip_button.disable();
938 // disable and hide the ip address inputbox
940 Om_ip_input.disable();
942 // undo input mode if necessary
947 Om_pro_bogus.disable();
950 // enable/unhide all the controls for the protocol section
951 void options_multi_enable_protocol_controls()
955 // unhide and enable all the protocol buttons
956 for(idx=0;idx<OM_PRO_NUM_BUTTONS;idx++){
958 Om_pro_buttons[gr_screen.res][idx].button.enable();
961 Om_pro_buttons[gr_screen.res][idx].button.unhide();
964 // unhide and enable the tracker input boxes
966 Om_tracker_login.enable();
967 Om_tracker_passwd.enable();
968 Om_tracker_squad_name.enable();
970 Om_tracker_login.unhide();
971 Om_tracker_passwd.unhide();
972 Om_tracker_squad_name.unhide();
974 // enable the click detection button
975 Om_ip_button.enable();
978 Om_pro_bogus.enable();
979 Om_pro_bogus.unhide();
982 // intialize the protocol section vars
983 void options_multi_init_protocol_vars()
986 Om_protocol = Multi_options_g.protocol;
988 // whether or not the user has the local broadcast button selected
989 Om_local_broadcast = (Player->m_local_options.flags & MLO_FLAG_LOCAL_BROADCAST) ? 1 : 0;
991 // whether or not we're playing on the tracker
992 Om_tracker_flag = 0; // (Multi_options_g.protocol == NET_TCP) && Multi_options_g.pxo ? 1 : 0;
994 // load the ip address list
995 Om_ip_disp_count = 0;
996 options_multi_protocol_load_ip_file();
997 Om_ip_selected = Om_num_ips - 1;
998 Om_ip_start = Om_num_ips - 1;
1001 // do frame for the protocol section
1002 void options_multi_protocol_do(int key)
1004 // check for button presses
1005 options_multi_protocol_check_buttons();
1007 // force draw the correct "local broadcast" button
1008 if(Om_local_broadcast){
1009 Om_pro_buttons[gr_screen.res][OM_PRO_LOCAL_BROADCAST].button.draw_forced(2);
1012 // draw the "vmt" button if it is selected
1013 if(Om_tracker_flag){
1014 Om_pro_buttons[gr_screen.res][OM_PRO_VMT].button.draw_forced(2);
1017 // see if he hit any interesting key presses
1020 // add a new ip string if we're in "input" mode
1022 options_multi_protocol_add_current_ip();
1024 // clear the text control and input mode
1025 Om_ip_input.set_text("");
1026 Om_ip_input.clear_focus();
1027 Om_ip_input.disable();
1031 // if the tracker login inputbox has focus, lose it
1032 if(Om_tracker_login.has_focus()){
1033 Om_tracker_login.clear_focus();
1034 gamesnd_play_iface(SND_COMMIT_PRESSED);
1036 // if the tracker password inputbox has focus, lose it
1037 if(Om_tracker_passwd.has_focus()){
1038 Om_tracker_passwd.clear_focus();
1039 gamesnd_play_iface(SND_COMMIT_PRESSED);
1041 // if the tracker squad name inputbox has focus, lose it
1042 if(Om_tracker_squad_name.has_focus()){
1043 Om_tracker_squad_name.clear_focus();
1044 gamesnd_play_iface(SND_COMMIT_PRESSED);
1049 // if we're in input mode, cancel out
1051 // clear the text control and input mode
1052 Om_ip_input.set_text("");
1053 Om_ip_input.clear_focus();
1054 Om_ip_input.disable();
1057 // otherwise quit the options screen altogether
1059 options_cancel_exit();
1064 // tab through the tracker input controls
1065 if(Om_tracker_login.has_focus()){
1066 Om_tracker_passwd.set_focus();
1067 } else if(Om_tracker_passwd.has_focus()){
1068 Om_tracker_squad_name.set_focus();
1069 } else if(Om_tracker_squad_name.has_focus()){
1070 Om_tracker_login.set_focus();
1075 // force draw the proper protocol
1076 if (Om_protocol == NET_IPX) {
1077 Om_pro_buttons[gr_screen.res][OM_PRO_IPX].button.draw_forced(2);
1079 Om_pro_buttons[gr_screen.res][OM_PRO_TCP].button.draw_forced(2);
1082 // force draw the proper tab button
1084 case OM_MODE_GENERAL:
1085 Om_pro_buttons[gr_screen.res][OM_PRO_GEN_TAB].button.draw_forced(2);
1089 Om_pro_buttons[gr_screen.res][OM_PRO_VOX_TAB].button.draw_forced(2);
1093 // check to see if the user has clicked on the ip list and selected a new item
1094 options_multi_protocol_check_ip_list();
1096 // draw the list of ip addresses
1097 options_multi_protocol_display_ips();
1099 // hack to play sound when input boxes gain focus
1100 if (Om_tracker_login.has_focus()) {
1101 if (Om_tracker_focus != TRACKER_FOCUS_LOGIN) {
1102 Om_tracker_focus = TRACKER_FOCUS_LOGIN;
1103 gamesnd_play_iface(SND_USER_SELECT);
1105 } else if (Om_tracker_passwd.has_focus()) {
1106 if (Om_tracker_focus != TRACKER_FOCUS_PASSWORD) {
1107 Om_tracker_focus = TRACKER_FOCUS_PASSWORD;
1108 gamesnd_play_iface(SND_USER_SELECT);
1110 } else if (Om_tracker_squad_name.has_focus()) {
1111 if (Om_tracker_focus != TRACKER_FOCUS_SQUADRON) {
1112 Om_tracker_focus = TRACKER_FOCUS_SQUADRON;
1113 gamesnd_play_iface(SND_USER_SELECT);
1116 Om_tracker_focus = TRACKER_FOCUS_NONE;
1120 // if the accept button was hit
1121 void options_multi_protocol_accept()
1123 // if the user has selected local broadcast write it into his options struct
1124 Player->m_local_options.flags &= ~(MLO_FLAG_LOCAL_BROADCAST);
1125 if(Om_local_broadcast){
1126 Player->m_local_options.flags |= MLO_FLAG_LOCAL_BROADCAST;
1130 Multi_options_g.protocol = Om_protocol;
1132 // copy the VMT login and password data
1133 Om_tracker_login.get_text(Multi_tracker_login);
1134 Om_tracker_passwd.get_text(Multi_tracker_passwd);
1135 Om_tracker_squad_name.get_text(Multi_tracker_squad_name);
1137 // write out the tracker login and passwd values to the registry
1138 os_config_write_string( "PXO", "Login", Multi_tracker_login );
1139 os_config_write_string( "PXO", "Password", Multi_tracker_passwd );
1141 // write out the PXO squad name and passwd values to the registry
1142 os_config_write_string( "PXO", "SquadName", Multi_tracker_squad_name );
1144 // save the ip address list
1145 options_multi_protocol_save_ip_file();
1148 // check for button presses
1149 void options_multi_protocol_check_buttons()
1153 // go through each button
1154 for(idx=0;idx<OM_PRO_NUM_BUTTONS;idx++){
1155 if(Om_pro_buttons[gr_screen.res][idx].button.pressed()){
1156 options_multi_protocol_button_pressed(idx);
1162 // if a button was pressed
1163 void options_multi_protocol_button_pressed(int n)
1166 // add an ip address
1168 // don't process if we're in input mode
1173 // setup the input mode
1175 Om_ip_input.enable();
1176 Om_ip_input.unhide();
1177 Om_ip_input.set_text(IP_EMPTY_STRING);
1178 Om_ip_input.set_focus();
1179 gamesnd_play_iface(SND_USER_SELECT);
1182 // delete the currently selected ip
1183 case OM_PRO_DELETE_IP:
1184 // don't process if we're in input mode
1189 options_multi_protocol_delete_ip();
1190 gamesnd_play_iface(SND_USER_SELECT);
1193 // the "local" broadcast button - toggle
1194 case OM_PRO_LOCAL_BROADCAST:
1195 // don't process if we're in input mode
1200 if(!Om_local_broadcast){
1201 Om_local_broadcast = 1;
1203 Om_local_broadcast = 0;
1206 gamesnd_play_iface(SND_USER_SELECT);
1210 case OM_PRO_SCROLL_IP_DOWN:
1211 // don't process if we're in input mode
1216 options_multi_protocol_scroll_ip_down();
1220 case OM_PRO_SCROLL_IP_UP:
1221 // don't process if we're in input mode
1226 options_multi_protocol_scroll_ip_up();
1231 // for the multiplayer beta, always force tracker mode
1232 #ifdef MULTIPLAYER_BETA_BUILD // do we want this for FS2_DEMO
1233 Om_tracker_flag = 1;
1235 // don't process if we're in input mode
1240 // toggle the stupid thing
1241 Om_tracker_flag = !Om_tracker_flag;
1243 // if the thing is toggled on - enable the inputbox controls, else diable them
1244 if(Om_tracker_flag){
1245 Om_tracker_login.enable();
1246 Om_tracker_passwd.enable();
1247 Om_tracker_squad_name.enable();
1249 Om_tracker_login.disable();
1250 Om_tracker_passwd.disable();
1251 Om_tracker_squad_name.disable();
1255 gamesnd_play_iface(SND_USER_SELECT);
1259 // general tab button
1260 case OM_PRO_GEN_TAB:
1261 if(Om_mode != OM_MODE_GENERAL){
1262 // set the general tab
1263 Om_mode = OM_MODE_GENERAL;
1265 // disable the voice controls
1266 options_multi_disable_vox_controls();
1268 // enable the general controls
1269 options_multi_enable_gen_controls();
1271 // set the general screen mask
1272 Assert(Om_mask_0 >= 0);
1273 Om_window->set_mask_bmap(Om_mask_0, Om_background_0_mask_fname[gr_screen.res]);
1277 gamesnd_play_iface(SND_USER_SELECT);
1282 case OM_PRO_VOX_TAB:
1283 if(Om_mode != OM_MODE_VOX){
1284 // set the voice tab
1285 Om_mode = OM_MODE_VOX;
1287 // disable the general controls
1288 options_multi_disable_gen_controls();
1290 // enable the voice controls
1291 options_multi_enable_vox_controls();
1293 // set the voice screen mask
1294 Assert(Om_mask_1 >= 0);
1295 Om_window->set_mask_bmap(Om_mask_1, Om_background_1_mask_fname[gr_screen.res]);
1298 gamesnd_play_iface(SND_USER_SELECT);
1304 Om_protocol = NET_TCP;
1305 gamesnd_play_iface(SND_USER_SELECT);
1311 Om_protocol = NET_IPX;
1312 gamesnd_play_iface(SND_USER_SELECT);
1318 // load the ip address file
1319 void options_multi_protocol_load_ip_file()
1321 char line[IP_STRING_LEN];
1324 // reset the ip address count
1327 // attempt to open the ip list file
1328 file = cfopen(IP_CONFIG_FNAME,"rt",CFILE_NORMAL,CF_TYPE_DATA);
1330 nprintf(("Network","Error loading tcp.cfg file!\n"));
1334 // read in all the strings in the file
1335 while(!cfeof(file)){
1337 cfgets(line,IP_STRING_LEN,file);
1339 // strip off any newline character
1340 if(line[strlen(line) - 1] == '\n'){
1341 line[strlen(line) - 1] = '\0';
1344 // 0 length lines don't get processed
1345 if((line[0] == '\0') || (line[0] == '\n') )
1348 if ( !psnet_is_valid_ip_string(line) ) {
1349 nprintf(("Network","Invalid ip string (%s)\n",line));
1351 if(Om_num_ips < MAX_IP_ADDRS-1){
1352 strcpy(Om_ip_addrs[Om_num_ips++],line);
1360 // save the ip address file
1361 void options_multi_protocol_save_ip_file()
1366 // attempt to open the ip list file for writing
1367 file = cfopen(IP_CONFIG_FNAME,"wt",CFILE_NORMAL,CF_TYPE_DATA );
1369 nprintf(("Network","Error loading tcp.cfg file\n"));
1373 // write out all the string we have
1374 for(idx=0;idx<Om_num_ips;idx++){
1375 // make _absolutely_ sure its a valid address
1376 // MWA -- commented out next line because name resolution might fail when
1377 // it was added. We'll only grab games that we can actually get to.
1378 //Assert(psnet_is_valid_ip_string(Multi_ip_addrs[idx]));
1380 cfputs(Om_ip_addrs[idx],file);
1382 // make sure to tack on a newline if necessary
1383 if(Om_ip_addrs[idx][strlen(&Om_ip_addrs[idx][0]) - 1] != '\n'){
1384 cfputs(NOX("\n"),file);
1391 // draw the list of ip addresses
1392 void options_multi_protocol_display_ips()
1395 int y_start = Ip_list_coords[gr_screen.res][1];
1397 // get the # of items we should be displaying based upon the # of addresses and the starting display point
1398 if(Om_ip_start >= Ip_list_max_display[gr_screen.res]){
1399 Om_ip_disp_count = Ip_list_max_display[gr_screen.res];
1401 Om_ip_disp_count = Om_ip_start + 1;
1404 // display the addresses
1405 for(idx=Om_ip_start; idx >= Om_ip_start - Om_ip_disp_count + 1 ; idx--){
1406 if(idx == Om_ip_selected){
1407 gr_set_color_fast(&Color_bright);
1409 gr_set_color_fast(&Color_white);
1412 gr_printf(Ip_list_coords[gr_screen.res][0], y_start, Om_ip_addrs[idx]);
1417 // scroll the list of ip addresses down
1418 void options_multi_protocol_scroll_ip_down()
1420 if(Om_ip_start >= Ip_list_max_display[gr_screen.res]){
1421 gamesnd_play_iface(SND_SCROLL);
1424 gamesnd_play_iface(SND_GENERAL_FAIL);
1428 // scroll the list of ip addresses up
1429 void options_multi_protocol_scroll_ip_up()
1431 if(Om_ip_start < Om_num_ips-1){
1432 gamesnd_play_iface(SND_SCROLL);
1435 gamesnd_play_iface(SND_GENERAL_FAIL);
1439 // check the ip list to see if the user has selected a new item
1440 void options_multi_protocol_check_ip_list()
1445 if(Om_ip_button.pressed()){
1446 // determine which item he clicked on
1447 Om_ip_button.get_mouse_pos(NULL, &click_y);
1448 item = click_y / 10;
1450 // determine if there is an item in this location, and select it if so
1451 if(item < Om_ip_disp_count){
1452 Om_ip_selected = Om_ip_start - item;
1457 // delete the currently selected ip if any
1458 void options_multi_protocol_delete_ip()
1462 // attempt to delete the currently highlighted item
1463 if(Om_ip_selected != -1){
1465 // move down all the other items
1466 for(idx=Om_ip_selected; idx < Om_num_ips; idx++){
1467 strcpy(Om_ip_addrs[idx],Om_ip_addrs[idx+1]);
1470 // make sure to decrement the starting index
1473 // check to make sure that the selected item is valid
1475 if(Om_num_ips <= 0){
1476 Om_ip_selected = -1;
1478 if(Om_ip_selected > 0){
1485 // return 10, if successflu
1486 char Ip_str[IP_STRING_LEN+1];
1487 int Ip_validated_already = 0;
1488 int options_multi_verify_ip()
1492 if(!Ip_validated_already){
1493 // see if its a valid ip address
1494 result = psnet_is_valid_ip_string(Ip_str);
1496 // if the result is a valid ip string, return immediately
1501 // otherwise, change the popup text to indicate that it is invalid and wait for the user to click ok
1502 popup_change_text(XSTR( "Ip string is invalid!", 386));
1505 Ip_validated_already = 1;
1507 // always wait for the user to hit the "cancel" button
1511 // attempt to add the currently entered ip address
1512 void options_multi_protocol_add_current_ip()
1514 // get the entered string
1515 Om_ip_input.get_text(Ip_str);
1517 // this popup wil do several things.
1518 // 1.) It will display a popup so the user isn't left scratching his head
1519 // 2.) If the address
1520 Ip_validated_already = 0;
1521 if(popup_till_condition(options_multi_verify_ip, XSTR( "Cancel", 387), XSTR( "Verifying ip address", 388)) == 10){
1522 if(Om_num_ips < MAX_IP_ADDRS){
1523 strcpy(Om_ip_addrs[Om_num_ips],Ip_str);
1524 Om_ip_start = Om_num_ips;
1527 // if this is the first item on the list, select it
1528 if(Om_num_ips == 1){
1532 options_multi_add_notify(XSTR( "Max # of IP addresses reached!", 389));
1537 // general options tab section -------------------------------------------
1539 // load all the general tab controls
1540 void options_multi_load_gen_controls()
1544 Assert(Om_window != NULL);
1546 // instantiate all the buttons
1547 for(idx=0; idx<OM_GEN_NUM_BUTTONS; idx++){
1548 // create the object
1549 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);
1551 // set the sound to play when highlighted
1552 Om_gen_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
1554 // set the ani for the button
1555 Om_gen_buttons[gr_screen.res][idx].button.set_bmaps(Om_gen_buttons[gr_screen.res][idx].filename);
1558 Om_gen_buttons[gr_screen.res][idx].button.link_hotspot(Om_gen_buttons[gr_screen.res][idx].hotspot);
1562 for(idx=0; idx<OM_GEN_NUM_TEXT; idx++){
1563 Om_window->add_XSTR(&Om_gen_text[gr_screen.res][idx]);
1567 Om_gen_bogus.base_create(Om_window, UI_KIND_ICON, 0, 0, 0, 0);
1570 // disable/hide all the general tab controls
1571 void options_multi_disable_gen_controls()
1575 // go through all the controls
1576 for(idx=0;idx<OM_GEN_NUM_BUTTONS;idx++){
1577 Om_gen_buttons[gr_screen.res][idx].button.hide();
1578 Om_gen_buttons[gr_screen.res][idx].button.disable();
1582 Om_gen_bogus.hide();
1583 Om_gen_bogus.disable();
1586 // enable/unhide all the general tab controls
1587 void options_multi_enable_gen_controls()
1591 // go through all the controls
1592 for(idx=0;idx<OM_GEN_NUM_BUTTONS;idx++){
1593 Om_gen_buttons[gr_screen.res][idx].button.enable();
1594 Om_gen_buttons[gr_screen.res][idx].button.unhide();
1598 Om_gen_bogus.enable();
1599 Om_gen_bogus.unhide();
1602 // initialize the general tab vars
1603 void options_multi_init_gen_vars()
1605 // initialize the object update
1606 Om_gen_obj_update = Player->m_local_options.obj_update_level;
1608 // initialize the accept pix var
1609 if(Player->m_local_options.flags & MLO_FLAG_ACCEPT_PIX){
1615 // initialize the xfer_multidata var
1616 if(Player->m_local_options.flags & MLO_FLAG_XFER_MULTIDATA){
1617 Om_gen_xfer_multidata = 1;
1619 Om_gen_xfer_multidata = 0;
1622 // initialize the flush cache var
1623 if(Player->m_local_options.flags & MLO_FLAG_FLUSH_CACHE){
1624 Om_gen_flush_cache = 1;
1626 Om_gen_flush_cache = 0;
1630 // accept function for the general tab
1631 void options_multi_gen_accept()
1633 // apply the object update level
1634 Player->m_local_options.obj_update_level = Om_gen_obj_update;
1636 // apply the accept pix var
1637 Player->m_local_options.flags &= ~(MLO_FLAG_ACCEPT_PIX);
1639 Player->m_local_options.flags |= MLO_FLAG_ACCEPT_PIX;
1642 // apply the xfer multidata var
1643 Player->m_local_options.flags &= ~(MLO_FLAG_XFER_MULTIDATA);
1644 if(Om_gen_xfer_multidata){
1645 Player->m_local_options.flags |= MLO_FLAG_XFER_MULTIDATA;
1648 // apply the flush cache var
1649 Player->m_local_options.flags &= ~(MLO_FLAG_FLUSH_CACHE);
1650 if(Om_gen_flush_cache){
1651 Player->m_local_options.flags |= MLO_FLAG_FLUSH_CACHE;
1655 // do frame for the general tab
1656 void options_multi_gen_do()
1658 // check for button presses
1659 options_multi_gen_check_buttons();
1661 // draw the proper object update button
1662 switch(Om_gen_obj_update){
1663 case OBJ_UPDATE_LOW:
1664 Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_LOW].button.draw_forced(2);
1666 case OBJ_UPDATE_MEDIUM:
1667 Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_MED].button.draw_forced(2);
1669 case OBJ_UPDATE_HIGH:
1670 Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_HIGH].button.draw_forced(2);
1672 case OBJ_UPDATE_LAN:
1673 Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_LAN].button.draw_forced(2);
1679 // draw the proper pix button
1681 Om_gen_buttons[gr_screen.res][OM_GEN_PIX_YES].button.draw_forced(2);
1683 Om_gen_buttons[gr_screen.res][OM_GEN_PIX_NO].button.draw_forced(2);
1686 // draw the proper xfer multidata button
1687 if(Om_gen_xfer_multidata){
1688 Om_gen_buttons[gr_screen.res][OM_GEN_XFER_MULTIDATA_YES].button.draw_forced(2);
1690 Om_gen_buttons[gr_screen.res][OM_GEN_XFER_MULTIDATA_NO].button.draw_forced(2);
1693 // draw the proper flush cache button
1694 if(Om_gen_flush_cache){
1695 Om_gen_buttons[gr_screen.res][OM_GEN_FLUSH_YES].button.draw_forced(2);
1697 Om_gen_buttons[gr_screen.res][OM_GEN_FLUSH_NO].button.draw_forced(2);
1701 // check for button presses
1702 void options_multi_gen_check_buttons()
1706 // go through all the buttons
1707 for(idx=0;idx<OM_GEN_NUM_BUTTONS;idx++){
1708 if(Om_gen_buttons[gr_screen.res][idx].button.pressed()){
1709 options_multi_gen_button_pressed(idx);
1715 // a button was pressed
1716 void options_multi_gen_button_pressed(int n)
1719 // low object update level
1720 case OM_GEN_OBJ_LOW:
1721 if(Om_gen_obj_update != OBJ_UPDATE_LOW){
1722 gamesnd_play_iface(SND_USER_SELECT);
1723 Om_gen_obj_update = OBJ_UPDATE_LOW;
1725 gamesnd_play_iface(SND_GENERAL_FAIL);
1729 // medium object update level
1730 case OM_GEN_OBJ_MED:
1731 if(Om_gen_obj_update != OBJ_UPDATE_MEDIUM){
1732 gamesnd_play_iface(SND_USER_SELECT);
1733 Om_gen_obj_update = OBJ_UPDATE_MEDIUM;
1735 gamesnd_play_iface(SND_GENERAL_FAIL);
1739 // high object update level
1740 case OM_GEN_OBJ_HIGH:
1741 if(Om_gen_obj_update != OBJ_UPDATE_HIGH){
1742 gamesnd_play_iface(SND_USER_SELECT);
1743 Om_gen_obj_update = OBJ_UPDATE_HIGH;
1745 gamesnd_play_iface(SND_GENERAL_FAIL);
1749 // lan object update level
1750 case OM_GEN_OBJ_LAN:
1751 if(Om_gen_obj_update != OBJ_UPDATE_LAN){
1752 gamesnd_play_iface(SND_USER_SELECT);
1753 Om_gen_obj_update = OBJ_UPDATE_LAN;
1755 gamesnd_play_iface(SND_GENERAL_FAIL);
1760 case OM_GEN_PIX_YES:
1762 gamesnd_play_iface(SND_USER_SELECT);
1765 gamesnd_play_iface(SND_GENERAL_FAIL);
1772 gamesnd_play_iface(SND_USER_SELECT);
1775 gamesnd_play_iface(SND_GENERAL_FAIL);
1779 // put missions in the multidate directory
1780 case OM_GEN_XFER_MULTIDATA_YES:
1781 if(!Om_gen_xfer_multidata){
1782 gamesnd_play_iface(SND_USER_SELECT);
1783 Om_gen_xfer_multidata = 1;
1785 gamesnd_play_iface(SND_GENERAL_FAIL);
1789 // dont put missions in the multidata directory
1790 case OM_GEN_XFER_MULTIDATA_NO:
1791 if(Om_gen_xfer_multidata){
1792 gamesnd_play_iface(SND_USER_SELECT);
1793 Om_gen_xfer_multidata = 0;
1795 gamesnd_play_iface(SND_GENERAL_FAIL);
1799 // flush the cache before each mission
1800 case OM_GEN_FLUSH_YES:
1801 if(!Om_gen_flush_cache){
1802 gamesnd_play_iface(SND_USER_SELECT);
1803 Om_gen_flush_cache = 1;
1805 gamesnd_play_iface(SND_GENERAL_FAIL);
1809 // don't flush the cache before each mission
1810 case OM_GEN_FLUSH_NO:
1811 if(Om_gen_flush_cache){
1812 gamesnd_play_iface(SND_USER_SELECT);
1813 Om_gen_flush_cache = 0;
1815 gamesnd_play_iface(SND_GENERAL_FAIL);
1821 // voice options tab section -------------------------------------------
1823 // load all the voice tab controls
1824 void options_multi_load_vox_controls()
1828 Assert(Om_window != NULL);
1830 // instantiate all the buttons
1831 for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
1832 // create the object
1833 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);
1835 // set the sound to play when highlighted
1836 Om_vox_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
1838 // set the ani for the button
1839 Om_vox_buttons[gr_screen.res][idx].button.set_bmaps(Om_vox_buttons[gr_screen.res][idx].filename);
1842 Om_vox_buttons[gr_screen.res][idx].button.link_hotspot(Om_vox_buttons[gr_screen.res][idx].hotspot);
1846 for(idx=0; idx<OM_VOX_NUM_TEXT; idx++){
1847 Om_window->add_XSTR(&Om_vox_text[gr_screen.res][idx]);
1851 for ( idx = 0; idx < NUM_OM_VOX_SLIDERS; idx++ ) {
1852 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,
1853 Om_vox_sliders[gr_screen.res][idx].dots, Om_vox_sliders[gr_screen.res][idx].filename,
1854 Om_vox_sliders[gr_screen.res][idx].hotspot, 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,
1855 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,
1856 Om_vox_sliders[gr_screen.res][idx].dot_w);
1859 // create the player list select button
1860 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);
1861 Om_vox_plist_button.hide();
1863 // build a list of net players
1864 Om_vox_num_players = 0;
1865 for(idx=0;idx<MAX_PLAYERS;idx++){
1866 Om_vox_players[idx] = NULL;
1868 // if i'm not connected, do nothing
1869 if((Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_CONNECTED)){
1873 // add all players I know about
1874 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (Net_player != &Net_players[idx])){
1875 // set the netplayer pointer
1876 Om_vox_players[Om_vox_num_players] = &Net_players[idx];
1878 // set his mute flag
1879 Om_vox_player_flags[Om_vox_num_players] = (Multi_voice_local_prefs & (1<<idx)) ? 1 : 0;
1881 // increment the count
1882 Om_vox_num_players++;
1887 Om_vox_bogus.base_create(Om_window, UI_KIND_ICON, 0, 0, 0, 0);
1890 // disable/hide all the voice tab controls
1891 void options_multi_disable_vox_controls()
1895 // go through all the controls
1896 for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
1897 Om_vox_buttons[gr_screen.res][idx].button.hide();
1898 Om_vox_buttons[gr_screen.res][idx].button.disable();
1901 // hide the qos control
1902 Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.hide();
1903 Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.disable();
1905 // unset the sound buffer size so we don't display any waveforms
1906 Om_vox_voice_buffer_size = -1;
1907 Om_vox_voice_comp_size = -1;
1908 Om_vox_playback_handle = -1;
1909 Om_vox_test_status = OM_VOX_TEST_NONE;
1911 // disable the player list select button
1912 Om_vox_plist_button.disable();
1915 Om_vox_bogus.hide();
1916 Om_vox_bogus.disable();
1919 // enable/unhide all the voice tab controls
1920 void options_multi_enable_vox_controls()
1924 // go through all the controls
1925 for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
1926 Om_vox_buttons[gr_screen.res][idx].button.enable();
1927 Om_vox_buttons[gr_screen.res][idx].button.unhide();
1930 // unhide the qos control
1931 Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.enable();
1932 Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.unhide();
1934 // unset the sound buffer size so we don't display any waveforms
1935 Om_vox_voice_buffer_size = -1;
1936 Om_vox_voice_comp_size = -1;
1937 Om_vox_playback_handle = -1;
1938 Om_vox_test_status = OM_VOX_TEST_NONE;
1940 // select the first player on the list
1941 Om_vox_player_select = Om_vox_players[0];
1942 Om_vox_plist_start = 0;
1944 // enable the player list select button
1945 Om_vox_plist_button.enable();
1948 Om_vox_bogus.enable();
1949 Om_vox_bogus.unhide();
1952 // initialize the voice tab vars
1953 void options_multi_init_vox_vars()
1955 // intialize the accept voice var
1956 if(Player->m_local_options.flags & MLO_FLAG_NO_VOICE){
1957 Om_vox_accept_voice = 0;
1959 Om_vox_accept_voice = 1;
1963 // accept function for the voice tab
1964 void options_multi_vox_accept()
1967 int voice_pref_flags;
1969 // set the accept voice flag
1970 Player->m_local_options.flags &= ~(MLO_FLAG_NO_VOICE);
1971 if(!Om_vox_accept_voice){
1972 Player->m_local_options.flags |= MLO_FLAG_NO_VOICE;
1975 // build the voice preferences stuff
1976 voice_pref_flags = 0xffffffff;
1977 for(idx=0;idx<Om_vox_num_players;idx++){
1978 // if this guy is muted
1979 if(!Om_vox_player_flags[idx]){
1980 voice_pref_flags &= ~(1 << NET_PLAYER_INDEX(Om_vox_players[idx]));
1983 multi_voice_set_prefs(voice_pref_flags);
1986 // do frame for the voice tab
1987 void options_multi_vox_do()
1991 // check for button presses
1992 options_multi_vox_check_buttons();
1994 // draw the proper accept voice button
1995 if(Om_vox_accept_voice){
1996 Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_YES].button.draw_forced(2);
1998 Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_NO].button.draw_forced(2);
2001 // if the currently selected player is muted
2002 if((Om_vox_player_select != NULL) && !Om_vox_player_flags[options_multi_vox_plist_get(Om_vox_player_select)]){
2003 Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_MUTE].button.draw_forced(2);
2006 // process and display the player list
2007 options_multi_vox_process_player_list();
2009 // if we're currently doing a voice test recording, process some stuff
2010 switch(Om_vox_test_status){
2011 case OM_VOX_TEST_RECORDING:
2012 multi_voice_test_process();
2014 // force draw the mic test button
2015 Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_TEST].button.draw_forced(2);
2017 // if we are no longer recording, switch to playback if possible
2018 if(!multi_voice_test_recording()){
2019 Om_vox_test_status = OM_VOX_TEST_PLAYBACK;
2021 if(Om_vox_voice_comp_size != -1){
2022 // stop any playing back sounds
2023 rtvoice_stop_playback_all();
2025 // attempt to get a playback handle
2026 handle = multi_voice_test_get_playback_buffer();
2028 Om_vox_playback_handle = rtvoice_play_uncompressed(handle, Om_vox_comp_buffer, Om_vox_voice_comp_size);
2030 // mark us as playing back
2031 Om_vox_test_status = OM_VOX_TEST_PLAYBACK;
2033 // on error, notify the user something is wrong
2035 options_multi_add_notify(XSTR( "Error trying to playback recorded voice! Check your hardware", 390));
2037 // mark us as doing nothing
2038 Om_vox_test_status = OM_VOX_TEST_NONE;
2041 // mark us as doing nothing
2042 Om_vox_test_status = OM_VOX_TEST_NONE;
2047 case OM_VOX_TEST_PLAYBACK:
2048 // if we were playing a sound back, but now the sound is done
2049 if((Om_vox_playback_handle != -1) && (ds_get_play_position(ds_get_channel(Om_vox_playback_handle)) >= (DWORD)Om_vox_voice_comp_size)){
2050 // flush all playing sounds safely
2051 rtvoice_stop_playback_all();
2053 // null the sound handle
2054 Om_vox_playback_handle = -1;
2056 // set this so we know not to display any more waveforms
2057 Om_vox_voice_buffer_size = -1;
2058 Om_vox_voice_comp_size = -1;
2060 // free the status up
2061 Om_vox_test_status = OM_VOX_TEST_NONE;
2067 // check for button presses
2068 void options_multi_vox_check_buttons()
2072 // go through all the buttons
2073 for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
2074 if(Om_vox_buttons[gr_screen.res][idx].button.pressed()){
2075 options_multi_vox_button_pressed(idx);
2081 // a button was pressed
2082 void options_multi_vox_button_pressed(int n)
2085 // accept voice button
2086 case OM_VOX_VOICE_YES:
2087 if(!Om_vox_accept_voice){
2088 gamesnd_play_iface(SND_USER_SELECT);
2089 Om_vox_accept_voice = 1;
2091 gamesnd_play_iface(SND_GENERAL_FAIL);
2095 // don't accept voice button
2096 case OM_VOX_VOICE_NO:
2097 if(Om_vox_accept_voice){
2098 gamesnd_play_iface(SND_USER_SELECT);
2099 Om_vox_accept_voice = 0;
2101 gamesnd_play_iface(SND_GENERAL_FAIL);
2105 // mute/unmute button
2106 case OM_VOX_VOICE_MUTE:
2107 if(Om_vox_player_select != NULL){
2108 Om_vox_player_flags[options_multi_vox_plist_get(Om_vox_player_select)] = !Om_vox_player_flags[options_multi_vox_plist_get(Om_vox_player_select)];
2109 gamesnd_play_iface(SND_USER_SELECT);
2111 gamesnd_play_iface(SND_GENERAL_FAIL);
2115 // scroll the player list up
2116 case OM_VOX_PLIST_UP:
2117 options_multi_vox_plist_scroll_up();
2120 // scroll the player list down
2121 case OM_VOX_PLIST_DOWN:
2122 options_multi_vox_plist_scroll_down();
2126 case OM_VOX_VOICE_TEST:
2127 // if in a multiplayer game, don't allow testing
2128 if((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_CONNECTED)){
2129 options_multi_add_notify(XSTR( "Cannot test mic while in a multiplayer game!", 391));
2133 // if this machine is not capable of playing
2134 if(!Multi_voice_can_record){
2135 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));
2137 // if we're not already doing a record test
2138 if(Om_vox_test_status == OM_VOX_TEST_NONE){
2139 // set the quality of sound
2140 rtvoice_set_qos(Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.pos + 1);
2142 // clear the comp buffer
2143 memset(Om_vox_comp_buffer,128,OM_VOX_COMP_SIZE);
2145 Om_vox_test_status = OM_VOX_TEST_RECORDING;
2146 multi_voice_test_record_start();
2154 extern shader Grey_shader;
2156 // process and blit any voice waveform if necessary
2157 void options_multi_vox_process_waveform()
2159 int c_width = OM_VOX_WAVE_WIDTH;
2162 int idx,a_idx,running_avg;
2164 // if we're not in recording or playback mode
2165 if(Om_vox_test_status == OM_VOX_TEST_NONE){
2170 gr_set_shader(&Grey_shader);
2171 gr_shade(0,0,gr_screen.clip_width, gr_screen.clip_height);
2173 switch(Om_vox_test_status){
2174 case OM_VOX_TEST_RECORDING:
2175 // if we have no sound buffer size, do nothing
2176 if(Om_vox_voice_buffer_size <= 0){
2180 // if we are not recording, do nothing
2181 if(Om_vox_test_status != OM_VOX_TEST_RECORDING){
2185 // get the # of samples we'll average for one line
2186 avg_len = Om_vox_voice_buffer_size / c_width;
2188 // blit the waveform
2189 gr_set_color_fast(&Color_green);
2191 for(idx=0; idx < c_width; idx++){
2192 // reset the running average
2194 for(a_idx = 0; a_idx < avg_len; a_idx++){
2195 running_avg += (int)Om_vox_voice_buffer[buf_offset] - 128;
2197 // increment the buffer offset
2201 running_avg /= avg_len;
2202 gr_line((gr_screen.max_w - OM_VOX_WAVE_WIDTH)/2 + idx, OM_VOX_WAVE_Y, (gr_screen.max_w - OM_VOX_WAVE_WIDTH)/2 + idx, OM_VOX_WAVE_Y + running_avg);
2205 // if this packet would have been dropped, notify the user
2206 if(multi_voice_test_packet_tossed()){
2207 gr_set_color_fast(&Color_bright);
2208 gr_string(OM_VOX_DROP_ICON_X,OM_VOX_DROP_ICON_Y, XSTR( "Packet Overflow", 393));
2212 case OM_VOX_TEST_PLAYBACK:
2213 // get the offset into the playing direct sound buffer
2214 buf_offset = ds_get_play_position(ds_get_channel(Om_vox_playback_handle));
2216 // get the # of samples we'll average for one line
2217 avg_len = (int)((float)OM_VOX_RECORD_INT * ((1024.0f * 11.0f) / 1000.0f)) / c_width;
2219 // blit the waveform
2220 gr_set_color_fast(&Color_red);
2221 for(idx=0; idx < c_width; idx++){
2222 // reset the running average
2224 for(a_idx = 0; a_idx < avg_len; a_idx++){
2225 if(buf_offset < (OM_VOX_COMP_SIZE - 2)){
2226 running_avg += (int)Om_vox_comp_buffer[buf_offset] - 128;
2228 // increment the buffer offset
2233 running_avg /= avg_len;
2234 gr_line((gr_screen.max_w - OM_VOX_WAVE_WIDTH)/2 + idx, OM_VOX_WAVE_Y, (gr_screen.max_w - OM_VOX_WAVE_WIDTH)/2 + idx, OM_VOX_WAVE_Y + running_avg);
2240 // process/display the player list
2241 void options_multi_vox_process_player_list()
2244 int y_start,p_count;
2245 int selected_index,click_y;
2246 char str[CALLSIGN_LEN+2];
2248 // check for mouse clicks
2249 if(Om_vox_plist_button.pressed()){
2250 Om_vox_plist_button.get_mouse_pos(NULL,&click_y);
2251 selected_index = (click_y / 10) + Om_vox_plist_start;
2253 // if he clicked on a valid player, select him
2254 if(Om_vox_players[selected_index] != NULL){
2255 Om_vox_player_select = Om_vox_players[selected_index];
2257 nprintf(("Network","Selecting player %s\n",Om_vox_player_select->player->callsign));
2261 // draw the list of players
2263 y_start = Om_vox_plist_coords[gr_screen.res][1];
2264 for(idx = Om_vox_plist_start; idx < Om_vox_num_players; idx++){
2265 if(Om_vox_players[idx] != NULL){
2266 // if he's the selected player, highlight him
2267 if(Om_vox_players[idx] == Om_vox_player_select){
2268 gr_set_color_fast(&Color_bright);
2270 gr_set_color_fast(&Color_normal);
2273 // force fit his callsign
2274 strcpy(str,Om_vox_players[idx]->player->callsign);
2275 gr_force_fit_string(str, CALLSIGN_LEN+1, Om_vox_plist_coords[gr_screen.res][2]);
2277 // blit the callsign
2278 gr_string(Om_vox_plist_coords[gr_screen.res][0], y_start, str);
2280 // increment the y index
2283 // increment the player count
2287 // if we've reached max display, break out
2288 if(p_count >= Om_vox_plist_max_display[gr_screen.res]){
2294 // get the index into the player list of the passed netplayer
2295 int options_multi_vox_plist_get(net_player *pl)
2299 for(idx=0;idx<Om_vox_num_players;idx++){
2300 if(pl == Om_vox_players[idx]){
2305 // should neve get here. hmmm.
2310 // scroll the player list down
2311 void options_multi_vox_plist_scroll_down()
2313 if(Om_vox_num_players < Om_vox_plist_max_display[gr_screen.res]){
2314 gamesnd_play_iface(SND_GENERAL_FAIL);
2318 if((Om_vox_num_players - Om_vox_plist_start) >= Om_vox_plist_max_display[gr_screen.res]){
2319 Om_vox_plist_start++;
2320 gamesnd_play_iface(SND_USER_SELECT);
2322 gamesnd_play_iface(SND_GENERAL_FAIL);
2326 // scroll the player list up
2327 void options_multi_vox_plist_scroll_up()
2329 if(Om_vox_plist_start > 0){
2330 Om_vox_plist_start--;
2331 gamesnd_play_iface(SND_USER_SELECT);
2333 gamesnd_play_iface(SND_GENERAL_FAIL);
2338 // extern functions -----------------------------------------------------
2340 // called when the options screen is initialized, pass in the UI window
2341 void options_multi_init(UI_WINDOW *options_window)
2343 // assign the options window
2344 Om_window = options_window;
2346 // load the background bitmaps
2347 options_multi_load_bmaps();
2349 // load the controls for the protocol area
2350 options_multi_load_protocol_controls();
2352 // load the controls for the general tab
2353 options_multi_load_gen_controls();
2355 // load the controls for the voice tab
2356 options_multi_load_vox_controls();
2358 // disable all the protocol controls
2359 options_multi_disable_protocol_controls();
2361 // disable all the general tab controls
2362 options_multi_disable_gen_controls();
2364 // disable all the voice tab controls
2365 options_multi_disable_vox_controls();
2367 // intialize the protocol section vars
2368 options_multi_init_protocol_vars();
2370 // initialize the general tab vars
2371 options_multi_init_gen_vars();
2373 // initialize the voice tab vars
2374 options_multi_init_vox_vars();
2376 // intialize the multiplayer voice recording system
2377 if( !((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_CONNECTED)) ){
2381 // set the default screen mode
2382 Om_mode = OM_MODE_NONE;
2385 // do frame for the multi options screen
2386 void options_multi_do(int key)
2388 // do frame for the protocol section
2389 options_multi_protocol_do(key);
2391 // process and blit any notification messages
2392 options_multi_notify_process();
2394 // process the proper tab control
2396 case OM_MODE_GENERAL:
2397 options_multi_gen_do();
2400 options_multi_vox_do();
2407 // called when the entire options screen is closed
2408 void options_multi_close()
2410 // null out the window handle
2413 // unload all background bitmaps
2414 options_multi_unload_bmaps();
2416 // stop any playing voice
2417 rtvoice_stop_playback_all();
2419 // unset the screen mode
2420 Om_mode = OM_MODE_NONE;
2423 // called if the accept button on the main options screen was hit
2424 void options_multi_accept()
2426 // accept function for the protocol section
2427 options_multi_protocol_accept();
2429 // accept function for the general tab
2430 options_multi_gen_accept();
2432 // accept function for the voice tab
2433 options_multi_vox_accept();
2435 // if Net_player is not null, copy these new settings to him
2436 if(Net_player != NULL){
2437 multi_options_local_load(&Net_player->p_info.options, NULL);
2439 multi_options_local_load(&Player->m_local_options, NULL);
2441 // if we're connected to a game server, update our options on the server now
2442 if((Net_player != NULL) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && MULTI_CONNECTED(Net_players[MY_NET_PLAYER_NUM]) ){
2443 multi_options_update_local();
2447 // called when the multiplayer tab is hit - initializes/switches all necessary data.
2448 // NOTE : this is different from the initialization function, which is called only when the options menu is started
2449 void options_multi_select()
2451 // set the windows mask bitmap
2452 Assert(Om_mask_0 >= 0);
2453 Om_window->set_mask_bmap(Om_mask_0, Om_background_0_mask_fname[gr_screen.res]);
2455 // set the default screen mode
2456 Om_mode = OM_MODE_GENERAL;
2458 // clear any notification messages
2459 Om_notify_stamp = -1;
2461 // enable all the protocol controls
2462 options_multi_enable_protocol_controls();
2464 // enable the general tab controls
2465 options_multi_enable_gen_controls();
2468 // return the bitmap handle of the current background bitmap, or -1 if the multiplayer tab is not active
2469 int options_multi_background_bitmap()
2471 // return the background bitmap mode based upon the current mode
2473 case OM_MODE_GENERAL:
2474 return Om_background_0;
2477 return Om_background_1;
2480 // unknown mode of some kind
2484 // called when the multiplayer tab has been switched from
2485 void options_multi_unselect()
2488 Om_mode = OM_MODE_NONE;
2490 // disable all the protocol controls
2491 options_multi_disable_protocol_controls();
2493 // disable all the general tab controls
2494 options_multi_disable_gen_controls();
2496 // disable all the vox tab controls
2497 options_multi_disable_vox_controls();
2499 // stop any test voice recording
2500 multi_voice_test_record_stop();
2503 // set voice sound buffer for display
2504 void options_multi_set_voice_data(unsigned char *sound_buf,int buf_size,unsigned char *comp_buf, int comp_size, int uncomp_size, double gain)
2506 // copy the buffer to the vox tab data
2507 if(buf_size > OM_VOX_BUF_SIZE){
2508 memcpy(Om_vox_voice_buffer,sound_buf,OM_VOX_BUF_SIZE);
2509 Om_vox_voice_buffer_size = OM_VOX_BUF_SIZE;
2511 memcpy(Om_vox_voice_buffer,sound_buf,buf_size);
2512 Om_vox_voice_buffer_size = buf_size;
2515 // copy and uncompress the compressed buffer
2516 if(Om_vox_voice_comp_size == -1){
2517 Om_vox_voice_comp_size = 0;
2519 // if we can fit it, decompress this data
2520 if((Om_vox_voice_comp_size + uncomp_size) < OM_VOX_COMP_SIZE){
2521 // uncompress the data
2522 rtvoice_uncompress(comp_buf, comp_size, gain, Om_vox_comp_buffer + Om_vox_voice_comp_size, uncomp_size);
2524 Om_vox_voice_comp_size += uncomp_size;
2528 // return whether we want to eat a tabbed keypress
2529 int options_multi_eat_tab()
2531 // do we want to eat the tab key or not
2532 if(Om_tracker_passwd.has_focus() || Om_tracker_login.has_focus() || Om_tracker_squad_name.has_focus()){