2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/MenuUI/OptionsMenuMulti.cpp $
16 * Revision 1.7 2005/03/29 02:18:47 taylor
17 * Various 64-bit platform fixes
18 * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
19 * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
20 * Streaming audio support (big thanks to Pierre Willenbrock!!)
21 * Removed dependance on strings.tbl for FS1 since we don't actually need it now
23 * Revision 1.6 2003/05/25 02:30:42 taylor
26 * Revision 1.5 2002/06/09 04:41:22 relnev
27 * added copyright header
29 * Revision 1.4 2002/06/05 08:05:29 relnev
30 * stub/warning removal.
32 * reworked the sound code.
34 * Revision 1.3 2002/06/02 06:02:59 relnev
37 * Revision 1.2 2002/05/07 03:16:46 theoddone33
38 * The Great Newline Fix
40 * Revision 1.1.1.1 2002/05/03 03:28:09 root
44 * 21 10/25/99 5:47p Jefff
45 * reassigned some xstr ids
47 * 20 8/02/99 2:44p Dave
48 * Disable IPX for demo build.
50 * 19 7/15/99 7:15p Jefff
51 * Added various sound FX
53 * 18 7/15/99 9:20a Andsager
54 * FS2_DEMO initial checkin
56 * 17 6/25/99 11:59a Dave
57 * Multi options screen.
59 * 16 6/22/99 7:03p Dave
60 * New detail options screen.
62 * 15 4/25/99 3:02p Dave
63 * Build defines for the E3 build.
65 * 14 2/25/99 4:19p Dave
66 * Added multiplayer_beta defines. Added cd_check define. Fixed a few
67 * release build warnings. Added more data to the squad war request and
70 * 13 2/19/99 2:55p Dave
71 * Temporary checking to report the winner of a squad war match.
73 * 12 2/17/99 2:10p Dave
74 * First full run of squad war. All freespace and tracker side stuff
77 * 11 2/12/99 6:16p Dave
78 * Pre-mission Squad War code is 95% done.
80 * 10 2/05/99 7:22p Neilk
81 * Fixed gamma bitmap and converted coordinates for multiple resolutions
83 * 9 2/02/99 11:36a Dave
84 * Removed obsolete data reference.
86 * 8 12/18/98 1:13a Dave
87 * Rough 1024x768 support for Direct3D. Proper detection and usage through
90 * 7 11/20/98 11:16a Dave
91 * Fixed up IPX support a bit. Making sure that switching modes and
92 * loading/saving pilot files maintains proper state.
94 * 6 11/19/98 4:19p Dave
95 * Put IPX sockets back in psnet. Consolidated all multiplayer config
98 * 5 11/05/98 5:55p Dave
99 * Big pass at reducing #includes
101 * 4 10/13/98 9:28a Dave
102 * Started neatening up freespace.h. Many variables renamed and
103 * reorganized. Added AlphaColors.[h,cpp]
105 * 3 10/09/98 2:57p Dave
106 * Starting splitting up OS stuff.
108 * 2 10/07/98 10:53a Dave
111 * 1 10/07/98 10:49a Dave
113 * 27 7/08/98 11:56a Dave
114 * Changed mic problem error message.
116 * 26 6/12/98 7:13p Hoffoss
117 * Fixed options screen problem where it wasn't showing tooltips.
119 * 25 6/09/98 10:31a Hoffoss
120 * Created index numbers for all xstr() references. Any new xstr() stuff
121 * added from here on out should be added to the end if the list. The
122 * current list count can be found in FreeSpace.cpp (search for
125 * 24 6/01/98 11:43a John
126 * JAS & MK: Classified all strings for localization.
128 * 23 5/21/98 9:45p Dave
129 * Lengthened tracker polling times. Put in initial support for PXO
130 * servers with channel filters. Fixed several small UI bugs.
132 * 22 5/20/98 2:24a Dave
133 * Fixed server side voice muting. Tweaked multi debrief/endgame
134 * sequencing a bit. Much friendlier for stats tossing/accepting now.
136 * 21 5/19/98 1:35a Dave
137 * Tweaked pxo interface. Added rankings url to pxo.cfg. Make netplayer
138 * local options update dynamically in netgames.
140 * 20 5/18/98 12:03p Frank
141 * Make sure network changes made in options screen are loaded into any
142 * current Net_player as well as the Player.
144 * 19 5/11/98 11:39p Dave
147 * 18 5/10/98 7:05p Dave
148 * Fix endgame sequencing ESC key. Changed how host options warning popups
149 * are done. Fixed pause/message scrollback/options screen problems in mp.
150 * Make sure observer HUD doesn't try to lock weapons.
152 * 17 5/08/98 7:08p Dave
153 * Lots of UI tweaking.
155 * 16 5/08/98 5:04p Dave
156 * Go to the join game screen when quitting multiplayer. Fixed mission
157 * text chat bugs. Put mission type symbols on the create game list.
158 * Started updating standalone gui controls.
160 * 15 5/07/98 12:57a Dave
161 * Fixed incorrect calls to free() from stats code. Put in new artwork for
162 * debrief and host options screens. Another modification to scoring
163 * system for secondary weapons.
165 * 14 5/06/98 8:06p Dave
166 * Made standalone reset properly under weird conditions. Tweak
167 * optionsmulti screen. Upped MAX_WEAPONS to 350. Put in new launch
168 * countdown anim. Minro ui fixes/tweaks.
170 * 13 5/02/98 5:38p Dave
171 * Put in new tracker API code. Put in ship information on mp team select
172 * screen. Make standalone server name permanent. Fixed standalone server
175 * 12 4/30/98 5:24p Adam
176 * JAS: Made multi config specify path.
178 * 11 4/28/98 5:13p Dave
179 * Remove references to old MT API
181 * 10 4/25/98 2:00p Dave
182 * Installed a bunch of multiplayer context help screens. Reworked ingame
183 * join ship select screen. Fix places where network timestamps get hosed.
185 * 9 4/22/98 4:09p John
186 * String externalization
188 * 8 4/22/98 12:34a Dave
189 * Make sure hud config and control config buttons draw properly in all
190 * tab modes. Make small tab buttons light up correctly in multi options
193 * 7 4/21/98 4:44p Dave
194 * Implement Vasudan ships in multiplayer. Added a debug function to bash
195 * player rank. Fixed a few rtvoice buffer overrun problems. Fixed ui
196 * problem in options screen.
198 * 6 4/20/98 6:04p Dave
199 * Implement multidata cache flushing and xferring mission files to
200 * multidata. Make sure observers can't change hud config. Fix pilot image
201 * viewing in popup. Put in game status field. Tweaked multi options.
203 * 5 4/18/98 12:45p Dave
204 * Aesthetic changes to multi options screen. Put in missing exit button.
207 * 4 4/17/98 6:33p Dave
208 * Finished first run of the screen. About time.
210 * 3 4/17/98 5:27p Dave
211 * More work on the multi options screen. Fixed many minor ui todo bugs.
213 * 2 4/17/98 12:42a Dave
214 * Worked on voice tab. Need to implement mic testing and player muting
217 * 1 4/16/98 11:39p Dave
230 #include "freespace.h"
233 #include "multi_voice.h"
236 #include "optionsmenu.h"
237 #include "optionsmenumulti.h"
239 #include "osregistry.h"
240 #include "alphacolors.h"
242 #include "gamesequence.h" // needed for FS1
246 // general data section ------------------------------------------------
247 UI_WINDOW *Om_window = NULL;
250 static const char* Om_background_0_fname[GR_NUM_RESOLUTIONS] = {
251 "OptionsMultiGen", // GR_640
252 "2_OptionsMultiGen" // GR_1024
255 static const char* Om_background_0_mask_fname[GR_NUM_RESOLUTIONS] = {
256 "OptionsMultiGen-M", // GR_640
257 "2_OptionsMultiGen-M" // GR_1024
260 static const char* Om_background_1_fname[GR_NUM_RESOLUTIONS] = {
261 "OptionsMultiVox", // GR_640
262 "2_OptionsMultiVox" // GR_1024
265 static const char* Om_background_1_mask_fname[GR_NUM_RESOLUTIONS] = {
266 "OptionsMultiVox-M", // GR_640
267 "2_OptionsMultiVox-M" // GR_1024
270 int Om_background_0 = -1;
273 int Om_background_1 = -1;
278 #define OM_MODE_NONE -1 // no mode (unintialized)
279 #define OM_MODE_GENERAL 0 // general tab
280 #define OM_MODE_VOX 1 // voice tab
281 int Om_mode = OM_MODE_NONE;
283 // notification stuff
284 #define OM_NOTIFY_TIME 8000
285 #define OM_NOTIFY_Y 430
286 #define OM_NOTIFY_Y2 440
287 int Om_notify_stamp = -1;
288 char Om_notify_string[255];
290 // load all background bitmaps
291 void options_multi_load_bmaps();
293 // unload all the background bitmaps
294 void options_multi_unload_bmaps();
296 // add a notification message
297 void options_multi_add_notify(const char *str);
299 // process and blit any notification messages
300 void options_multi_notify_process();
303 // protocol options section -------------------------------------------
305 #define OM_PRO_NUM_BUTTONS 12
307 #define ABORT_GAME_BUTTON 0
308 #define CONTROL_CONFIG_BUTTON 1
309 #define HUD_CONFIG_BUTTON 2
310 #define OM_PRO_SCROLL_IP_UP 3
311 #define OM_PRO_SCROLL_IP_DOWN 4
312 #define OM_PRO_ADD_IP 5
313 #define OM_PRO_DELETE_IP 6
314 #define OM_PRO_LOCAL_BROADCAST_YES 7
315 #define OM_PRO_LOCAL_BROADCAST_NO 8
317 #define OM_PRO_VOX_TAB 10
318 #define OM_PRO_GEN_TAB 11
320 #define OM_PRO_NUM_BUTTONS 10
324 #define OM_PRO_SCROLL_IP_UP 2
325 #define OM_PRO_SCROLL_IP_DOWN 3
326 #define OM_PRO_ADD_IP 4
327 #define OM_PRO_DELETE_IP 5
328 #define OM_PRO_LOCAL_BROADCAST 6
330 #define OM_PRO_VOX_TAB 8
331 #define OM_PRO_GEN_TAB 9
334 ui_button_info Om_pro_buttons[GR_NUM_RESOLUTIONS][OM_PRO_NUM_BUTTONS] = {
337 ui_button_info("OPb_04", 6, 377, -1, -1, 4), // Exit Game
338 ui_button_info("OPb_05", 448, 335, -1, -1, 5), // Control Config
339 ui_button_info("OPb_06", 541, 335, -1, -1, 6), // HUD Config
341 ui_button_info("OPb_87", 252, 129, -1, -1, 87), // Scroll IP Up
342 ui_button_info("OPb_88", 252, 166, -1, -1, 88), // Scroll IP Down
343 ui_button_info("OPb_85", 26, 131, -1, -1, 85), // Add IP
344 ui_button_info("OPb_86", 26, 166, -1, -1, 86), // Remove IP
345 ui_button_info("OPb_89", 26, 221, -1, -1, 89), // Local Broadcast Yes
346 ui_button_info("OPb_90", 104, 221, -1, -1, 90), // Local Broadcast No
347 ui_button_info("OPb_91", 26, 243, -1, -1, 91), // Parallax Online
348 ui_button_info("OPb_92", 402, 72, -1, -1, 92), // Voice Tab
349 ui_button_info("OPb_93", 487, 72, -1, -1, 93), // General Tab
351 ui_button_info("OMuB_07", 7, 66, -1, -1, 7),
352 ui_button_info("OMuB_08", 7, 84, -1, -1, 8),
353 ui_button_info("OMuB_09", 1, 124, -1, -1, 9),
354 ui_button_info("OMuB_10", 1, 157, -1, -1, 10),
355 ui_button_info("OMuB_11", 20, 207, -1, -1, 11),
356 ui_button_info("OMuB_12", 64, 207, -1, -1, 12),
357 ui_button_info("OMuB_13", 9, 251, -1, -1, 13),
358 ui_button_info("OMuB_14", 9, 282, -1, -1, 14),
359 ui_button_info("OMuB_15", 610, 53, -1, -1, 15),
360 ui_button_info("OMuB_16", 610, 72, -1, -1, 16),
364 ui_button_info("2_OMuB_07", 12, 105, -1, -1, 7),
365 ui_button_info("2_OMuB_08", 12, 134, -1, -1, 8),
366 ui_button_info("2_OMuB_09", 2, 198, -1, -1, 9),
367 ui_button_info("2_OMuB_10", 2, 252, -1, -1, 10),
368 ui_button_info("2_OMuB_11", 32, 332, -1, -1, 11),
369 ui_button_info("2_OMuB_12", 103, 332, -1, -1, 12),
370 ui_button_info("2_OMuB_13", 14, 402, -1, -1, 13),
371 ui_button_info("2_OMuB_14", 14, 452, -1, -1, 14),
372 ui_button_info("2_OMuB_15", 976, 85, -1, -1, 15),
373 ui_button_info("2_OMuB_16", 976, 114, -1, -1, 16),
375 // filler for extra FS1 buttons
376 ui_button_info("none", -1, -1, -1, -1, -1),
377 ui_button_info("none", -1, -1, -1, -1, -1),
382 UI_GADGET Om_pro_bogus;
386 #define OM_PRO_NUM_TEXT 12
388 UI_XSTR Om_pro_text[GR_NUM_RESOLUTIONS][OM_PRO_NUM_TEXT] = {
390 { "TCP", 1378, 38, 70, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_TCP].button },
391 { "IPX", 1379, 38, 88, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_IPX].button },
392 { "IP Address", 1380, 30, 128, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
393 { "add", 1381, 22, 235, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_ADD_IP].button },
394 { "rem.", 1382, 68, 235, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_DELETE_IP].button },
395 { "Broadcast Locally", 1397, 42, 260, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_LOCAL_BROADCAST].button },
396 { "PXO", 1383, 42, 291, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_VMT].button },
397 { "Login", 1384, 14, 309, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
398 { "Password", 1385, 14, 336, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
399 { "Squadron", 1386, 14, 363, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
400 { "Voice", 1528, 557, 60, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_VOX_TAB].button },
401 { "General", 1388, 542, 77, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[0][OM_PRO_GEN_TAB].button },
404 { "TCP", 1378, 61, 113, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_TCP].button },
405 { "IPX", 1379, 61, 141, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_IPX].button },
406 { "IP Address", 1380, 47, 206, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
407 { "add", 1381, 36, 375, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_ADD_IP].button },
408 { "rem.", 1382, 109, 375, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_DELETE_IP].button },
409 { "Broadcast Locally", 1397, 68, 417, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_LOCAL_BROADCAST].button },
410 { "PXO", 1383, 68, 467, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_VMT].button },
411 { "Login", 1384, 23, 495, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
412 { "Password", 1385, 23, 538, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
413 { "Squadron", 1386, 23, 582, UI_XSTR_COLOR_GREEN, -1, &Om_pro_bogus },
414 { "Voice", 1528, 921, 96, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_VOX_TAB].button },
415 { "General", 1388, 902, 123, UI_XSTR_COLOR_GREEN, -1, &Om_pro_buttons[1][OM_PRO_GEN_TAB].button },
420 // defines for the tracker input boxes
421 int Om_tracker_login_coords[GR_NUM_RESOLUTIONS][4] = {
426 19, 322, 226, -1 // GR_640
430 31, 518, 361, -1 // GR_1024
433 int Om_tracker_passwd_coords[GR_NUM_RESOLUTIONS][4] = {
438 19, 350, 226, -1 // GR_640
442 31, 562, 361, -1 // GR_1024
445 int Om_tracker_squad_name_coords[GR_NUM_RESOLUTIONS][4] = {
447 19, 378, 226, -1 // GR_640
450 31, 607, 361, -1 // GR_1024
454 // protocol section tracker login input box
455 UI_INPUTBOX Om_tracker_login;
457 // protocol section tracker passwd input box
458 UI_INPUTBOX Om_tracker_passwd;
460 // pxo squad name/password
461 UI_INPUTBOX Om_tracker_squad_name;
463 #define TRACKER_FOCUS_NONE 0
464 #define TRACKER_FOCUS_LOGIN 1
465 #define TRACKER_FOCUS_PASSWORD 2
466 #define TRACKER_FOCUS_SQUADRON 3
467 static int Om_tracker_focus = 0;
469 // ip address list vars
470 #define IP_STRING_LEN 255
471 #define MAX_IP_ADDRS 100
473 #define IP_EMPTY_STRING ""
475 int Ip_list_coords[GR_NUM_RESOLUTIONS][4] = {
480 29, 137, 227, 67 // GR_640
484 46, 220, 364, 106 // GR_1024
489 int Ip_list_max_display[GR_NUM_RESOLUTIONS] = {
494 static int Ip_input_coords[GR_NUM_RESOLUTIONS][4] = {
499 109, 128, 140, -1 // GR_640
503 132, 206, 261, -1 // GR_640
507 int Om_input_mode = 0;
508 int Om_ip_start; // index of the first element to be displayed in the list box
509 int Om_ip_selected; // the selected default IP address
510 int Om_ip_disp_count; // how many items are currently being displayed
511 int Om_num_ips; // # of ip addresses we have
512 char Om_ip_addrs[MAX_IP_ADDRS][IP_STRING_LEN]; // the ip addresses themselves
513 UI_BUTTON Om_ip_button; // button for detecting clicks on the ip address list
514 UI_INPUTBOX Om_ip_input; // input box for adding new ip addresses
517 int Om_local_broadcast; // whether the player has local broadcast selected or not
518 int Om_tracker_flag; // if the guy has the tracker selected
519 int Om_protocol; // protocol in use
521 // load all the controls for the protocol section
522 void options_multi_load_protocol_controls();
524 // disable/hide all the controls for the protocol section
525 void options_multi_disable_protocol_controls();
527 // enable/unhide all the controls for the protocol section
528 void options_multi_enable_protocol_controls();
530 // intialize the protocol section vars
531 void options_multi_init_protocol_vars();
533 // do frame for the protocol section
534 void options_multi_protocol_do(int key);
536 // if the accept button was hit
537 void options_multi_protocol_accept();
539 // check for button presses
540 void options_multi_protocol_check_buttons();
542 // if a button was pressed
543 void options_multi_protocol_button_pressed(int n);
545 // load the ip address file
546 void options_multi_protocol_load_ip_file();
548 // save the ip address file
549 void options_multi_protocol_save_ip_file();
551 // draw the list of ip addresses
552 void options_multi_protocol_display_ips();
554 // scroll the list of ip addresses down
555 void options_multi_protocol_scroll_ip_down();
557 // scroll the list of ip addresses up
558 void options_multi_protocol_scroll_ip_up();
560 // check the ip list to see if the user has selected a new item
561 void options_multi_protocol_check_ip_list();
563 // delete the currently selected ip if any
564 void options_multi_protocol_delete_ip();
566 // attempt to add the currently entered ip address
567 void options_multi_protocol_add_current_ip();
570 // general options tab section -------------------------------------------
571 #define OM_GEN_NUM_BUTTONS 10
573 #define OM_GEN_OBJ_LOW 0
574 #define OM_GEN_OBJ_MED 1
575 #define OM_GEN_OBJ_HIGH 2
576 #define OM_GEN_OBJ_LAN 3
577 #define OM_GEN_PIX_YES 4
578 #define OM_GEN_PIX_NO 5
579 #define OM_GEN_XFER_MULTIDATA_YES 6
580 #define OM_GEN_XFER_MULTIDATA_NO 7
581 #define OM_GEN_FLUSH_NO 8
582 #define OM_GEN_FLUSH_YES 9
584 ui_button_info Om_gen_buttons[GR_NUM_RESOLUTIONS][OM_GEN_NUM_BUTTONS] = {
587 ui_button_info("OPb_94", 410, 121, -1, -1, 94),
588 ui_button_info("OPb_95", 410, 143, -1, -1, 95),
589 ui_button_info("OPb_96", 410, 165, -1, -1, 96),
590 ui_button_info("none", -1, -1, -1, -1, -1), // no LAN setting in FS1
591 ui_button_info("OPb_97", 410, 199, -1, -1, 97),
592 ui_button_info("OPb_98", 496, 199, -1, -1, 98),
593 ui_button_info("OPb_99", 410, 233, -1, -1, 99),
594 ui_button_info("OPb_100", 410, 256, -1, -1, 100),
595 ui_button_info("OPb_101", 410, 290, -1, -1, 101),
596 ui_button_info("OPb_102", 410, 313, -1, -1, 102),
598 ui_button_info("OGB_17", 598, 117, -1, -1, 17),
599 ui_button_info("OGB_18", 598, 139, -1, -1, 18),
600 ui_button_info("OGB_19", 598, 161, -1, -1, 19),
601 ui_button_info("OGB_20", 598, 183, -1, -1, 20),
602 ui_button_info("OGB_21", 549, 229, -1, -1, 21),
603 ui_button_info("OGB_22", 598, 229, -1, -1, 22),
604 ui_button_info("OGB_23", 598, 286, -1, -1, 23),
605 ui_button_info("OGB_24", 598, 307, -1, -1, 24),
606 ui_button_info("OGB_25", 598, 347, -1, -1, 25),
607 ui_button_info("OGB_26", 598, 368, -1, -1, 26),
611 ui_button_info("2_OGB_17", 957, 188, -1, -1, 17),
612 ui_button_info("2_OGB_18", 957, 223, -1, -1, 18),
613 ui_button_info("2_OGB_19", 957, 258, -1, -1, 19),
614 ui_button_info("2_OGB_20", 957, 293, -1, -1, 20),
615 ui_button_info("2_OGB_21", 879, 366, -1, -1, 21),
616 ui_button_info("2_OGB_22", 957, 366, -1, -1, 22),
617 ui_button_info("2_OGB_23", 957, 457, -1, -1, 23),
618 ui_button_info("2_OGB_24", 957, 491, -1, -1, 24),
619 ui_button_info("2_OGB_25", 957, 555, -1, -1, 25),
620 ui_button_info("2_OGB_26", 957, 589, -1, -1, 26),
624 UI_GADGET Om_gen_bogus;
628 #define OM_GEN_NUM_TEXT 14
630 UI_XSTR Om_gen_text[GR_NUM_RESOLUTIONS][OM_GEN_NUM_TEXT] = {
632 { "Object Update", 1391, 511, 104, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
633 { "Low", 1160, 558, 127, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_LOW].button },
634 { "Medium", 1161, 538, 149, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_MED].button },
635 { "High", 1162, 556, 171, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_HIGH].button },
636 { "Lan", 1392, 561, 193, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_OBJ_LAN].button },
637 { "Pilot / Squad Images", 1393, 463, 214, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
638 { "Yes", 1394, 555, 257, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_PIX_YES].button },
639 { "No", 1395, 604, 257, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_PIX_NO].button },
640 { "Transfer Missions", 1396, 478, 271, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
641 { "/multidata", 1397, 519, 292, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_XFER_MULTIDATA_YES].button },
642 { "/missions", 1398, 527, 314, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_XFER_MULTIDATA_NO].button },
643 { "Flush Cache", 1399, 529, 334, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
644 { "Never", 1400, 548, 355, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_FLUSH_NO].button },
645 { "Before Game", 1401, 502, 377, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[0][OM_GEN_FLUSH_YES].button },
648 { "Object Update", 1391, 818, 166, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
649 { "Low", 1160, 913, 204, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_LOW].button },
650 { "Medium", 1161, 892, 239, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_MED].button },
651 { "High", 1162, 909, 274, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_HIGH].button },
652 { "Lan", 1392, 916, 310, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_OBJ_LAN].button },
653 { "Pilot / Squad Images", 1393, 821, 345, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
654 { "Yes", 1394, 887, 411, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_PIX_YES].button },
655 { "No", 1395, 966, 411, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_PIX_NO].button },
656 { "Transfer Missions", 1396, 844, 435, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
657 { "/multidata", 1397, 858, 468, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_XFER_MULTIDATA_YES].button },
658 { "/missions", 1398, 870, 503, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_XFER_MULTIDATA_NO].button },
659 { "Flush Cache", 1399, 886, 533, UI_XSTR_COLOR_GREEN, -1, &Om_gen_bogus },
660 { "Never", 1400, 897, 568, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_FLUSH_NO].button },
661 { "Before Game", 1401, 849, 603, UI_XSTR_COLOR_GREEN, -1, &Om_gen_buttons[1][OM_GEN_FLUSH_YES].button },
667 int Om_gen_obj_update; // object update level
668 int Om_gen_pix; // accept pilot pix or not
669 int Om_gen_xfer_multidata; // xfer missions to multidata or not
670 int Om_gen_flush_cache; // flush multidata directory before every game
672 // load all the general tab controls
673 void options_multi_load_gen_controls();
675 // disable/hide all the general tab controls
676 void options_multi_disable_gen_controls();
678 // enable/unhide all the general tab controls
679 void options_multi_enable_gen_controls();
681 // initialize the general tab vars
682 void options_multi_init_gen_vars();
684 // accept function for the general tab
685 void options_multi_gen_accept();
687 // do frame for the general tab
688 void options_multi_gen_do();
690 // check for button presses
691 void options_multi_gen_check_buttons();
693 // a button was pressed
694 void options_multi_gen_button_pressed(int n);
697 // voice options tab section -------------------------------------------
698 #define OM_VOX_NUM_BUTTONS 6
700 #define OM_VOX_VOICE_TEST 0
701 #define OM_VOX_VOICE_YES 1
702 #define OM_VOX_VOICE_NO 2
703 #define OM_VOX_PLIST_UP 3
704 #define OM_VOX_PLIST_DOWN 4
705 #define OM_VOX_VOICE_MUTE 5
707 UI_GADGET Om_vox_bogus;
709 ui_button_info Om_vox_buttons[GR_NUM_RESOLUTIONS][OM_VOX_NUM_BUTTONS] = {
712 ui_button_info("OPb_103", 413, 110, -1, -1, 103),
713 ui_button_info("OPb_105", 413, 186, -1, -1, 105),
714 ui_button_info("OPb_106", 491, 186, -1, -1, 106),
715 ui_button_info("OPb_108", 413, 253, -1, -1, 108),
716 ui_button_info("OPb_109", 413, 291, -1, -1, 109),
717 ui_button_info("OPb_107", 413, 229, -1, -1, 107),
719 ui_button_info("OVB_17", 562, 118, -1, -1, 17),
720 ui_button_info("OVB_19", 551, 208, -1, -1, 19),
721 ui_button_info("OVB_20", 599, 208, -1, -1, 20),
722 ui_button_info("OVB_21", 614, 256, -1, -1, 21),
723 ui_button_info("OVB_22", 614, 290, -1, -1, 22),
724 ui_button_info("OVB_23", 599, 354, -1, -1, 23),
728 ui_button_info("2_OVB_17", 900, 189, -1, -1, 17),
729 ui_button_info("2_OVB_19", 882, 333, -1, -1, 19),
730 ui_button_info("2_OVB_20", 959, 333, -1, -1, 20),
731 ui_button_info("2_OVB_21", 983, 410, -1, -1, 21),
732 ui_button_info("2_OVB_22", 983, 464, -1, -1, 22),
733 ui_button_info("2_OVB_23", 959, 566, -1, -1, 23),
739 #define OM_VOX_NUM_TEXT 6
741 UI_XSTR Om_vox_text[GR_NUM_RESOLUTIONS][OM_VOX_NUM_TEXT] = {
743 { "Mic test", 1389, 567, 104, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_TEST].button },
744 { "Voice Quality", 1531, 439, 149, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
745 { "Voice Transmission", 1530, 439, 193, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
746 { "On", 1285, 556, 233, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_YES].button },
747 { "Off", 1286, 604, 233, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_NO].button },
748 { "Mute", 1390, 594, 381, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[0][OM_VOX_VOICE_MUTE].button },
751 { "mic test", 1389, 908, 166, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_TEST].button },
752 { "Voice Quality", 1531, 703, 239, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
753 { "Voice Transmission", 1530, 783, 310, UI_XSTR_COLOR_GREEN, -1, &Om_vox_bogus },
754 { "On", 1285, 890, 373, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_YES].button },
755 { "Off", 1286, 967, 373, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_NO].button },
756 { "Mute", 1390, 950, 609, UI_XSTR_COLOR_GREEN, -1, &Om_vox_buttons[1][OM_VOX_VOICE_MUTE].button },
761 #define NUM_OM_VOX_SLIDERS 1
762 #define OM_VOX_QOS_SLIDER 0
764 op_sliders Om_vox_sliders[GR_NUM_RESOLUTIONS][NUM_OM_VOX_SLIDERS] = {
767 op_sliders("OPb_104", 413, 151, -1, -1, 104, 20, 10, NULL, -1, -1, -1, NULL, -1, -1, -1),
769 op_sliders("OVB_18", 429, 162, -1, -1, 18, 20, 10, NULL, -1, -1, -1, NULL, -1, -1, -1), // voice QOS
773 op_sliders("2_OVB_18", 686, 259, -1, -1, 18, 32, 10, NULL, -1, -1, -1, NULL, -1, -1, -1), // voice QOS
778 int Om_vox_plist_coords[GR_NUM_RESOLUTIONS][4] = {
790 int Om_vox_plist_max_display[GR_NUM_RESOLUTIONS] = {
795 int Om_vox_plist_start;
796 UI_BUTTON Om_vox_plist_button;
799 #define OM_VOX_BUF_SIZE (1<<12)
800 #define OM_VOX_COMP_SIZE ((1<<15) + (1<<14))
802 #define OM_VOX_WAVE_Y 240
803 #define OM_VOX_WAVE_WIDTH 300
805 #define OM_VOX_DROP_ICON_X 100
806 #define OM_VOX_DROP_ICON_Y 100
808 #define OM_VOX_RECORD_INT 175
810 unsigned char Om_vox_voice_buffer[OM_VOX_BUF_SIZE];
811 int Om_vox_voice_buffer_size = -1;
813 unsigned char Om_vox_comp_buffer[OM_VOX_COMP_SIZE];
814 int Om_vox_voice_comp_size = -1;
816 int Om_vox_playback_handle;
818 // status of any test voice recording
819 #define OM_VOX_TEST_NONE -1
820 #define OM_VOX_TEST_RECORDING 0
821 #define OM_VOX_TEST_PLAYBACK 1
822 int Om_vox_test_status = OM_VOX_TEST_NONE;
825 int Om_vox_accept_voice;
827 // simple list of players we are looking through
828 net_player *Om_vox_players[MAX_PLAYERS];
831 net_player *Om_vox_player_select;
834 static int Om_vox_qos_pos;
836 // mute or don't mute for each player
837 int Om_vox_player_flags[MAX_PLAYERS];
840 int Om_vox_num_players;
842 // load all the voice tab controls
843 void options_multi_load_vox_controls();
845 // disable/hide all the voice tab controls
846 void options_multi_disable_vox_controls();
848 // enable/unhide all the voice tab controls
849 void options_multi_enable_vox_controls();
851 // initialize the voice tab vars
852 void options_multi_init_vox_vars();
854 // accept function for the voice tab
855 void options_multi_vox_accept();
857 // do frame for the voice tab
858 void options_multi_vox_do();
860 // check for button presses
861 void options_multi_vox_check_buttons();
863 // a button was pressed
864 void options_multi_vox_button_pressed(int n);
866 // process/display the player list
867 void options_multi_vox_process_player_list();
869 // scroll the player list down
870 void options_multi_vox_plist_scroll_down();
872 // scroll the player list up
873 void options_multi_vox_plist_scroll_up();
875 // get the index into the player list of the passed netplayer
876 int options_multi_vox_plist_get(net_player *pl);
879 // general data section ------------------------------------------------
881 // load all background bitmaps
882 void options_multi_load_bmaps()
885 // load both background bitmaps
886 Om_background_0 = bm_load(Om_background_0_fname[gr_screen.res]);
887 if(Om_background_0 == -1){
888 nprintf(("Network","Error loading options background %s\n",Om_background_0_fname[gr_screen.res]));
891 Om_background_1 = bm_load(Om_background_1_fname[gr_screen.res]);
892 if(Om_background_1 == -1){
893 nprintf(("Network","Error loading options background %s\n",Om_background_1_fname[gr_screen.res]));
896 // load in both mask bitmaps
897 Om_mask_0 = bm_load(Om_background_0_mask_fname[gr_screen.res]);
899 nprintf(("Network","Error loading options background mask %s\n",Om_background_0_mask_fname[gr_screen.res]));
902 Om_mask_1 = bm_load(Om_background_1_mask_fname[gr_screen.res]);
904 nprintf(("Network","Error loading options background mask %s\n",Om_background_1_mask_fname[gr_screen.res]));
909 // unload all the background bitmaps
910 void options_multi_unload_bmaps()
913 // unload all background bitmaps
914 if(Om_background_0 != -1){
915 bm_release(Om_background_0);
916 Om_background_0 = -1;
918 if(Om_background_1 != -1){
919 bm_release(Om_background_1);
920 Om_background_1 = -1;
923 // unload all mask bitmaps
925 bm_release(Om_mask_0);
929 bm_release(Om_mask_1);
935 // add a notification message
936 void options_multi_add_notify(const char *str)
939 memset(Om_notify_string,0,255);
941 SDL_strlcpy(Om_notify_string, str, SDL_arraysize(Om_notify_string));
945 Om_notify_stamp = timestamp(OM_NOTIFY_TIME);
948 // process and blit any notification messages
949 void options_multi_notify_process()
960 // if there is no timestamp, do nothing
961 if(Om_notify_stamp == -1){
965 // otherwise, if it has elapsed, unset it
966 if(timestamp_elapsed(Om_notify_stamp)){
967 Om_notify_stamp = -1;
971 // otherwise display the string
972 line_count = split_str(Om_notify_string, 600, n_chars, p_str, 3);
973 y_start = OM_NOTIFY_Y;
974 gr_set_color_fast(&Color_bright);
975 for(idx=0;idx<line_count;idx++){
976 len = min(n_chars[idx] + 1, (int)SDL_arraysize(line));
977 SDL_strlcpy(line, p_str[idx], len);
979 gr_get_string_size(&w,NULL,line);
980 gr_string((600 - w)/2,y_start,line);
987 // protocol section --------------------------------------------------------
989 // load all the controls for the protocol section
990 void options_multi_load_protocol_controls()
994 SDL_assert(Om_window != NULL);
996 // instantiate all the buttons
997 for(idx=0; idx<OM_PRO_NUM_BUTTONS; idx++){
999 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);
1001 // set the sound to play when highlighted
1002 Om_pro_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
1004 // set the ani for the button
1005 Om_pro_buttons[gr_screen.res][idx].button.set_bmaps(Om_pro_buttons[gr_screen.res][idx].filename);
1008 Om_pro_buttons[gr_screen.res][idx].button.link_hotspot(Om_pro_buttons[gr_screen.res][idx].hotspot);
1013 for(idx=0; idx<OM_PRO_NUM_TEXT; idx++){
1014 Om_window->add_XSTR(&Om_pro_text[gr_screen.res][idx]);
1018 // create the tracker input boxes
1019 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);
1020 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], PASSWORD_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);
1021 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);
1023 // create the invisible button for checking for clicks on the ip address list
1024 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);
1025 Om_ip_button.hide();
1027 // create the new ip address input box
1028 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);
1030 Om_ip_input.disable();
1032 // disable IPX button in demo
1034 Om_pro_buttons[gr_screen.res][OM_PRO_IPX].button.disable();
1035 Om_pro_buttons[gr_screen.res][OM_PRO_IPX].button.hide();
1039 Om_pro_bogus.base_create(Om_window, UI_KIND_ICON, 0, 0, 0, 0);
1042 // disable/hide all the controls for the protocol section
1043 void options_multi_disable_protocol_controls()
1047 // hide and disable all the protocol buttons
1048 for(idx=0;idx<OM_PRO_NUM_BUTTONS;idx++){
1050 Om_pro_buttons[gr_screen.res][idx].button.hide();
1052 // disable the button
1053 Om_pro_buttons[gr_screen.res][idx].button.disable();
1056 // hide and disable the tracker input boxes
1057 Om_tracker_login.hide();
1058 Om_tracker_login.disable();
1059 Om_tracker_passwd.hide();
1060 Om_tracker_passwd.disable();
1061 Om_tracker_squad_name.hide();
1062 Om_tracker_squad_name.disable();
1064 // disable the click detection button
1065 Om_ip_button.disable();
1067 // disable and hide the ip address inputbox
1069 Om_ip_input.disable();
1071 // undo input mode if necessary
1075 Om_pro_bogus.hide();
1076 Om_pro_bogus.disable();
1079 // enable/unhide all the controls for the protocol section
1080 void options_multi_enable_protocol_controls()
1084 // unhide and enable all the protocol buttons
1085 for(idx=0;idx<OM_PRO_NUM_BUTTONS;idx++){
1086 // enable the button
1087 Om_pro_buttons[gr_screen.res][idx].button.enable();
1089 // unhide the button
1090 Om_pro_buttons[gr_screen.res][idx].button.unhide();
1093 // unhide and enable the tracker input boxes
1094 if(Om_tracker_flag){
1095 Om_tracker_login.enable();
1096 Om_tracker_passwd.enable();
1097 Om_tracker_squad_name.enable();
1099 Om_tracker_login.unhide();
1100 Om_tracker_passwd.unhide();
1101 Om_tracker_squad_name.unhide();
1103 // enable the click detection button
1104 Om_ip_button.enable();
1107 Om_pro_bogus.enable();
1108 Om_pro_bogus.unhide();
1111 // intialize the protocol section vars
1112 void options_multi_init_protocol_vars()
1115 Om_protocol = Multi_options_g.protocol;
1117 // whether or not the user has the local broadcast button selected
1118 Om_local_broadcast = (Player->m_local_options.flags & MLO_FLAG_LOCAL_BROADCAST) ? 1 : 0;
1120 // whether or not we're playing on the tracker
1121 Om_tracker_flag = (Multi_options_g.protocol == NET_TCP) && Multi_options_g.pxo ? 1 : 0;
1123 // load the ip address list
1124 Om_ip_disp_count = 0;
1125 options_multi_protocol_load_ip_file();
1126 Om_ip_selected = Om_num_ips - 1;
1127 Om_ip_start = Om_num_ips - 1;
1130 // do frame for the protocol section
1131 void options_multi_protocol_do(int key)
1133 // check for button presses
1134 options_multi_protocol_check_buttons();
1136 // force draw the correct "local broadcast" button
1137 if(Om_local_broadcast){
1139 Om_pro_buttons[gr_screen.res][OM_PRO_LOCAL_BROADCAST_YES].button.draw_forced(2);
1141 Om_pro_buttons[gr_screen.res][OM_PRO_LOCAL_BROADCAST_NO].button.draw_forced(2);
1143 Om_pro_buttons[gr_screen.res][OM_PRO_LOCAL_BROADCAST].button.draw_forced(2);
1147 // draw the "vmt" button if it is selected
1148 if(Om_tracker_flag){
1149 Om_pro_buttons[gr_screen.res][OM_PRO_VMT].button.draw_forced(2);
1152 // see if he hit any interesting key presses
1155 // add a new ip string if we're in "input" mode
1157 options_multi_protocol_add_current_ip();
1159 // clear the text control and input mode
1160 Om_ip_input.set_text("");
1161 Om_ip_input.clear_focus();
1162 Om_ip_input.disable();
1166 // if the tracker login inputbox has focus, lose it
1167 if(Om_tracker_login.has_focus()){
1168 Om_tracker_login.clear_focus();
1169 gamesnd_play_iface(SND_COMMIT_PRESSED);
1171 // if the tracker password inputbox has focus, lose it
1172 if(Om_tracker_passwd.has_focus()){
1173 Om_tracker_passwd.clear_focus();
1174 gamesnd_play_iface(SND_COMMIT_PRESSED);
1176 // if the tracker squad name inputbox has focus, lose it
1177 if(Om_tracker_squad_name.has_focus()){
1178 Om_tracker_squad_name.clear_focus();
1179 gamesnd_play_iface(SND_COMMIT_PRESSED);
1184 // if we're in input mode, cancel out
1186 // clear the text control and input mode
1187 Om_ip_input.set_text("");
1188 Om_ip_input.clear_focus();
1189 Om_ip_input.disable();
1192 // otherwise quit the options screen altogether
1194 options_cancel_exit();
1199 // tab through the tracker input controls
1200 if(Om_tracker_login.has_focus()){
1201 Om_tracker_passwd.set_focus();
1202 } else if(Om_tracker_passwd.has_focus()){
1203 Om_tracker_squad_name.set_focus();
1204 } else if(Om_tracker_squad_name.has_focus()){
1205 Om_tracker_login.set_focus();
1210 // force draw the proper protocol
1211 #ifndef MAKE_FS1 // not in FS1 menu
1212 if (Om_protocol == NET_IPX) {
1213 Om_pro_buttons[gr_screen.res][OM_PRO_IPX].button.draw_forced(2);
1215 Om_pro_buttons[gr_screen.res][OM_PRO_TCP].button.draw_forced(2);
1219 // force draw the proper tab button
1221 case OM_MODE_GENERAL:
1222 Om_pro_buttons[gr_screen.res][OM_PRO_GEN_TAB].button.draw_forced(2);
1226 Om_pro_buttons[gr_screen.res][OM_PRO_VOX_TAB].button.draw_forced(2);
1230 // check to see if the user has clicked on the ip list and selected a new item
1231 options_multi_protocol_check_ip_list();
1233 // draw the list of ip addresses
1234 options_multi_protocol_display_ips();
1236 // hack to play sound when input boxes gain focus
1237 if (Om_tracker_login.has_focus()) {
1238 if (Om_tracker_focus != TRACKER_FOCUS_LOGIN) {
1239 Om_tracker_focus = TRACKER_FOCUS_LOGIN;
1240 gamesnd_play_iface(SND_USER_SELECT);
1242 } else if (Om_tracker_passwd.has_focus()) {
1243 if (Om_tracker_focus != TRACKER_FOCUS_PASSWORD) {
1244 Om_tracker_focus = TRACKER_FOCUS_PASSWORD;
1245 gamesnd_play_iface(SND_USER_SELECT);
1247 } else if (Om_tracker_squad_name.has_focus()) {
1248 if (Om_tracker_focus != TRACKER_FOCUS_SQUADRON) {
1249 Om_tracker_focus = TRACKER_FOCUS_SQUADRON;
1250 gamesnd_play_iface(SND_USER_SELECT);
1253 Om_tracker_focus = TRACKER_FOCUS_NONE;
1257 // if the accept button was hit
1258 void options_multi_protocol_accept()
1260 // if the user has selected local broadcast write it into his options struct
1261 Player->m_local_options.flags &= ~(MLO_FLAG_LOCAL_BROADCAST);
1262 if(Om_local_broadcast){
1263 Player->m_local_options.flags |= MLO_FLAG_LOCAL_BROADCAST;
1267 Multi_options_g.protocol = Om_protocol;
1270 Multi_options_g.pxo = Om_tracker_flag;
1272 // copy the VMT login and password data
1273 Om_tracker_login.get_text(Multi_tracker_login);
1274 Om_tracker_passwd.get_text(Multi_tracker_passwd);
1275 Om_tracker_squad_name.get_text(Multi_tracker_squad_name);
1277 // write out the tracker login and passwd values to the registry
1278 os_config_write_string( "PXO", "Login", Multi_tracker_login );
1279 os_config_write_string( "PXO", "Password", Multi_tracker_passwd );
1281 // write out the PXO squad name and passwd values to the registry
1282 os_config_write_string( "PXO", "SquadName", Multi_tracker_squad_name );
1284 // save the ip address list
1285 options_multi_protocol_save_ip_file();
1288 // check for button presses
1289 void options_multi_protocol_check_buttons()
1293 // go through each button
1294 for(idx=0;idx<OM_PRO_NUM_BUTTONS;idx++){
1295 if(Om_pro_buttons[gr_screen.res][idx].button.pressed()){
1296 options_multi_protocol_button_pressed(idx);
1302 // if a button was pressed
1303 void options_multi_protocol_button_pressed(int n)
1310 // add an ip address
1312 // don't process if we're in input mode
1317 // setup the input mode
1319 Om_ip_input.enable();
1320 Om_ip_input.unhide();
1321 Om_ip_input.set_text(IP_EMPTY_STRING);
1322 Om_ip_input.set_focus();
1323 gamesnd_play_iface(SND_USER_SELECT);
1326 // delete the currently selected ip
1327 case OM_PRO_DELETE_IP:
1328 // don't process if we're in input mode
1333 options_multi_protocol_delete_ip();
1334 gamesnd_play_iface(SND_USER_SELECT);
1337 // the "local" broadcast button - toggle
1339 // Yes and No buttons in FS1
1340 case OM_PRO_LOCAL_BROADCAST_YES:
1345 Om_local_broadcast = 1;
1347 gamesnd_play_iface(SND_USER_SELECT);
1350 case OM_PRO_LOCAL_BROADCAST_NO:
1355 Om_local_broadcast = 0;
1357 gamesnd_play_iface(SND_USER_SELECT);
1360 case OM_PRO_LOCAL_BROADCAST:
1361 // don't process if we're in input mode
1366 if(!Om_local_broadcast){
1367 Om_local_broadcast = 1;
1369 Om_local_broadcast = 0;
1372 gamesnd_play_iface(SND_USER_SELECT);
1377 case OM_PRO_SCROLL_IP_DOWN:
1378 // don't process if we're in input mode
1383 options_multi_protocol_scroll_ip_down();
1387 case OM_PRO_SCROLL_IP_UP:
1388 // don't process if we're in input mode
1393 options_multi_protocol_scroll_ip_up();
1398 // for the multiplayer beta, always force tracker mode
1399 #ifdef MULTIPLAYER_BETA_BUILD // do we want this for FS2_DEMO
1400 Om_tracker_flag = 1;
1402 // don't process if we're in input mode
1407 // toggle the stupid thing
1408 Om_tracker_flag = !Om_tracker_flag;
1410 // if the thing is toggled on - enable the inputbox controls, else diable them
1411 if(Om_tracker_flag){
1412 Om_tracker_login.enable();
1413 Om_tracker_passwd.enable();
1414 Om_tracker_squad_name.enable();
1416 Om_tracker_login.disable();
1417 Om_tracker_passwd.disable();
1418 Om_tracker_squad_name.disable();
1422 gamesnd_play_iface(SND_USER_SELECT);
1426 // general tab button
1428 case OM_PRO_GEN_TAB:
1429 if(Om_mode != OM_MODE_GENERAL){
1430 // set the general tab
1431 Om_mode = OM_MODE_GENERAL;
1433 // disable the voice controls
1434 options_multi_disable_vox_controls();
1436 // enable the general controls
1437 options_multi_enable_gen_controls();
1439 // set the general screen mask
1440 SDL_assert(Om_mask_0 >= 0);
1441 Om_window->set_mask_bmap(Om_mask_0, Om_background_0_mask_fname[gr_screen.res]);
1445 gamesnd_play_iface(SND_USER_SELECT);
1450 case OM_PRO_VOX_TAB:
1451 if(Om_mode != OM_MODE_VOX){
1452 // set the voice tab
1453 Om_mode = OM_MODE_VOX;
1455 // disable the general controls
1456 options_multi_disable_gen_controls();
1458 // enable the voice controls
1459 options_multi_enable_vox_controls();
1461 // set the voice screen mask
1462 SDL_assert(Om_mask_1 >= 0);
1463 Om_window->set_mask_bmap(Om_mask_1, Om_background_1_mask_fname[gr_screen.res]);
1466 gamesnd_play_iface(SND_USER_SELECT);
1472 #ifndef MAKE_FS1 // not in FS1 option menu
1474 Om_protocol = NET_TCP;
1475 gamesnd_play_iface(SND_USER_SELECT);
1481 Om_protocol = NET_IPX;
1482 gamesnd_play_iface(SND_USER_SELECT);
1488 case ABORT_GAME_BUTTON:
1489 gamesnd_play_iface(SND_USER_SELECT);
1490 choice = popup( PF_NO_NETWORKING | PF_BODY_BIG, 2, POPUP_NO, POPUP_YES, XSTR("Exit Game?", 374));
1492 gameseq_post_event(GS_EVENT_QUIT_GAME);
1498 // load the ip address file
1499 void options_multi_protocol_load_ip_file()
1501 char line[IP_STRING_LEN];
1504 // reset the ip address count
1507 // attempt to open the ip list file
1508 file = cfopen(IP_CONFIG_FNAME,"rt",CFILE_NORMAL,CF_TYPE_DATA);
1510 nprintf(("Network","Error loading tcp.cfg file!\n"));
1514 // read in all the strings in the file
1515 while(!cfeof(file)){
1517 cfgets(line,IP_STRING_LEN,file);
1519 // strip off any newline character
1520 if(line[strlen(line) - 1] == '\n'){
1521 line[strlen(line) - 1] = '\0';
1524 // 0 length lines don't get processed
1525 if((line[0] == '\0') || (line[0] == '\n') )
1528 if ( !psnet_is_valid_ip_string(line) ) {
1529 nprintf(("Network","Invalid ip string (%s)\n",line));
1531 if(Om_num_ips < MAX_IP_ADDRS-1){
1532 SDL_strlcpy(Om_ip_addrs[Om_num_ips++], line, IP_STRING_LEN);
1540 // save the ip address file
1541 void options_multi_protocol_save_ip_file()
1546 // attempt to open the ip list file for writing
1547 file = cfopen(IP_CONFIG_FNAME,"wt",CFILE_NORMAL,CF_TYPE_DATA );
1549 nprintf(("Network","Error loading tcp.cfg file\n"));
1553 // write out all the string we have
1554 for(idx=0;idx<Om_num_ips;idx++){
1555 // make _absolutely_ sure its a valid address
1556 // MWA -- commented out next line because name resolution might fail when
1557 // it was added. We'll only grab games that we can actually get to.
1558 //SDL_assert(psnet_is_valid_ip_string(Multi_ip_addrs[idx]));
1560 cfputs(Om_ip_addrs[idx],file);
1562 // make sure to tack on a newline if necessary
1563 if(Om_ip_addrs[idx][strlen(&Om_ip_addrs[idx][0]) - 1] != '\n'){
1564 cfputs(NOX("\n"),file);
1571 // draw the list of ip addresses
1572 void options_multi_protocol_display_ips()
1575 int y_start = Ip_list_coords[gr_screen.res][1];
1577 // get the # of items we should be displaying based upon the # of addresses and the starting display point
1578 if(Om_ip_start >= Ip_list_max_display[gr_screen.res]){
1579 Om_ip_disp_count = Ip_list_max_display[gr_screen.res];
1581 Om_ip_disp_count = Om_ip_start + 1;
1584 // display the addresses
1585 for(idx=Om_ip_start; idx >= Om_ip_start - Om_ip_disp_count + 1 ; idx--){
1586 if(idx == Om_ip_selected){
1587 gr_set_color_fast(&Color_bright);
1589 gr_set_color_fast(&Color_white);
1592 gr_printf(Ip_list_coords[gr_screen.res][0], y_start, Om_ip_addrs[idx]);
1597 // scroll the list of ip addresses down
1598 void options_multi_protocol_scroll_ip_down()
1600 if(Om_ip_start >= Ip_list_max_display[gr_screen.res]){
1601 gamesnd_play_iface(SND_SCROLL);
1604 gamesnd_play_iface(SND_GENERAL_FAIL);
1608 // scroll the list of ip addresses up
1609 void options_multi_protocol_scroll_ip_up()
1611 if(Om_ip_start < Om_num_ips-1){
1612 gamesnd_play_iface(SND_SCROLL);
1615 gamesnd_play_iface(SND_GENERAL_FAIL);
1619 // check the ip list to see if the user has selected a new item
1620 void options_multi_protocol_check_ip_list()
1625 if(Om_ip_button.pressed()){
1626 // determine which item he clicked on
1627 Om_ip_button.get_mouse_pos(NULL, &click_y);
1628 item = click_y / 10;
1630 // determine if there is an item in this location, and select it if so
1631 if(item < Om_ip_disp_count){
1632 Om_ip_selected = Om_ip_start - item;
1637 // delete the currently selected ip if any
1638 void options_multi_protocol_delete_ip()
1642 // attempt to delete the currently highlighted item
1643 if(Om_ip_selected != -1){
1645 // move down all the other items
1646 for(idx=Om_ip_selected; idx < Om_num_ips; idx++){
1647 SDL_strlcpy(Om_ip_addrs[idx], Om_ip_addrs[idx+1], IP_STRING_LEN);
1650 // make sure to decrement the starting index
1653 // check to make sure that the selected item is valid
1655 if(Om_num_ips <= 0){
1656 Om_ip_selected = -1;
1658 if(Om_ip_selected > 0){
1665 // return 10, if successflu
1666 char Ip_str[IP_STRING_LEN+1];
1667 int Ip_validated_already = 0;
1668 int options_multi_verify_ip()
1672 if(!Ip_validated_already){
1673 // see if its a valid ip address
1674 result = psnet_is_valid_ip_string(Ip_str);
1676 // if the result is a valid ip string, return immediately
1681 // otherwise, change the popup text to indicate that it is invalid and wait for the user to click ok
1682 popup_change_text(XSTR( "Ip string is invalid!", 386));
1685 Ip_validated_already = 1;
1687 // always wait for the user to hit the "cancel" button
1691 // attempt to add the currently entered ip address
1692 void options_multi_protocol_add_current_ip()
1694 // get the entered string
1695 Om_ip_input.get_text(Ip_str);
1697 // this popup wil do several things.
1698 // 1.) It will display a popup so the user isn't left scratching his head
1699 // 2.) If the address
1700 Ip_validated_already = 0;
1701 if(popup_till_condition(options_multi_verify_ip, XSTR( "Cancel", 387), XSTR( "Verifying ip address", 388)) == 10){
1702 if(Om_num_ips < MAX_IP_ADDRS){
1703 SDL_strlcpy(Om_ip_addrs[Om_num_ips], Ip_str, IP_STRING_LEN);
1704 Om_ip_start = Om_num_ips;
1707 // if this is the first item on the list, select it
1708 if(Om_num_ips == 1){
1712 options_multi_add_notify(XSTR( "Max # of IP addresses reached!", 389));
1717 // general options tab section -------------------------------------------
1719 // load all the general tab controls
1720 void options_multi_load_gen_controls()
1724 SDL_assert(Om_window != NULL);
1726 // instantiate all the buttons
1727 for(idx=0; idx<OM_GEN_NUM_BUTTONS; idx++){
1728 // create the object
1729 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);
1731 // set the sound to play when highlighted
1732 Om_gen_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
1734 // set the ani for the button
1735 Om_gen_buttons[gr_screen.res][idx].button.set_bmaps(Om_gen_buttons[gr_screen.res][idx].filename);
1738 Om_gen_buttons[gr_screen.res][idx].button.link_hotspot(Om_gen_buttons[gr_screen.res][idx].hotspot);
1743 for(idx=0; idx<OM_GEN_NUM_TEXT; idx++){
1744 Om_window->add_XSTR(&Om_gen_text[gr_screen.res][idx]);
1749 Om_gen_bogus.base_create(Om_window, UI_KIND_ICON, 0, 0, 0, 0);
1752 // disable/hide all the general tab controls
1753 void options_multi_disable_gen_controls()
1757 // go through all the controls
1758 for(idx=0;idx<OM_GEN_NUM_BUTTONS;idx++){
1759 Om_gen_buttons[gr_screen.res][idx].button.hide();
1760 Om_gen_buttons[gr_screen.res][idx].button.disable();
1764 Om_gen_bogus.hide();
1765 Om_gen_bogus.disable();
1768 // enable/unhide all the general tab controls
1769 void options_multi_enable_gen_controls()
1773 // go through all the controls
1774 for(idx=0;idx<OM_GEN_NUM_BUTTONS;idx++){
1775 Om_gen_buttons[gr_screen.res][idx].button.enable();
1776 Om_gen_buttons[gr_screen.res][idx].button.unhide();
1780 Om_gen_bogus.enable();
1781 Om_gen_bogus.unhide();
1784 // initialize the general tab vars
1785 void options_multi_init_gen_vars()
1787 // initialize the object update
1788 Om_gen_obj_update = Player->m_local_options.obj_update_level;
1790 // initialize the accept pix var
1791 if(Player->m_local_options.flags & MLO_FLAG_ACCEPT_PIX){
1797 // initialize the xfer_multidata var
1798 if(Player->m_local_options.flags & MLO_FLAG_XFER_MULTIDATA){
1799 Om_gen_xfer_multidata = 1;
1801 Om_gen_xfer_multidata = 0;
1804 // initialize the flush cache var
1805 if(Player->m_local_options.flags & MLO_FLAG_FLUSH_CACHE){
1806 Om_gen_flush_cache = 1;
1808 Om_gen_flush_cache = 0;
1812 // accept function for the general tab
1813 void options_multi_gen_accept()
1815 // apply the object update level
1816 Player->m_local_options.obj_update_level = Om_gen_obj_update;
1818 // apply the accept pix var
1819 Player->m_local_options.flags &= ~(MLO_FLAG_ACCEPT_PIX);
1821 Player->m_local_options.flags |= MLO_FLAG_ACCEPT_PIX;
1824 // apply the xfer multidata var
1825 Player->m_local_options.flags &= ~(MLO_FLAG_XFER_MULTIDATA);
1826 if(Om_gen_xfer_multidata){
1827 Player->m_local_options.flags |= MLO_FLAG_XFER_MULTIDATA;
1830 // apply the flush cache var
1831 Player->m_local_options.flags &= ~(MLO_FLAG_FLUSH_CACHE);
1832 if(Om_gen_flush_cache){
1833 Player->m_local_options.flags |= MLO_FLAG_FLUSH_CACHE;
1837 // do frame for the general tab
1838 void options_multi_gen_do()
1840 // check for button presses
1841 options_multi_gen_check_buttons();
1843 // draw the proper object update button
1844 switch(Om_gen_obj_update){
1845 case OBJ_UPDATE_LOW:
1846 Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_LOW].button.draw_forced(2);
1848 case OBJ_UPDATE_MEDIUM:
1849 Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_MED].button.draw_forced(2);
1851 case OBJ_UPDATE_HIGH:
1852 Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_HIGH].button.draw_forced(2);
1854 case OBJ_UPDATE_LAN:
1855 Om_gen_buttons[gr_screen.res][OM_GEN_OBJ_LAN].button.draw_forced(2);
1861 // draw the proper pix button
1863 Om_gen_buttons[gr_screen.res][OM_GEN_PIX_YES].button.draw_forced(2);
1865 Om_gen_buttons[gr_screen.res][OM_GEN_PIX_NO].button.draw_forced(2);
1868 // draw the proper xfer multidata button
1869 if(Om_gen_xfer_multidata){
1870 Om_gen_buttons[gr_screen.res][OM_GEN_XFER_MULTIDATA_YES].button.draw_forced(2);
1872 Om_gen_buttons[gr_screen.res][OM_GEN_XFER_MULTIDATA_NO].button.draw_forced(2);
1875 // draw the proper flush cache button
1876 if(Om_gen_flush_cache){
1877 Om_gen_buttons[gr_screen.res][OM_GEN_FLUSH_YES].button.draw_forced(2);
1879 Om_gen_buttons[gr_screen.res][OM_GEN_FLUSH_NO].button.draw_forced(2);
1883 // check for button presses
1884 void options_multi_gen_check_buttons()
1888 // go through all the buttons
1889 for(idx=0;idx<OM_GEN_NUM_BUTTONS;idx++){
1890 if(Om_gen_buttons[gr_screen.res][idx].button.pressed()){
1891 options_multi_gen_button_pressed(idx);
1897 // a button was pressed
1898 void options_multi_gen_button_pressed(int n)
1901 // low object update level
1902 case OM_GEN_OBJ_LOW:
1903 if(Om_gen_obj_update != OBJ_UPDATE_LOW){
1904 gamesnd_play_iface(SND_USER_SELECT);
1905 Om_gen_obj_update = OBJ_UPDATE_LOW;
1907 gamesnd_play_iface(SND_GENERAL_FAIL);
1911 // medium object update level
1912 case OM_GEN_OBJ_MED:
1913 if(Om_gen_obj_update != OBJ_UPDATE_MEDIUM){
1914 gamesnd_play_iface(SND_USER_SELECT);
1915 Om_gen_obj_update = OBJ_UPDATE_MEDIUM;
1917 gamesnd_play_iface(SND_GENERAL_FAIL);
1921 // high object update level
1922 case OM_GEN_OBJ_HIGH:
1923 if(Om_gen_obj_update != OBJ_UPDATE_HIGH){
1924 gamesnd_play_iface(SND_USER_SELECT);
1925 Om_gen_obj_update = OBJ_UPDATE_HIGH;
1927 gamesnd_play_iface(SND_GENERAL_FAIL);
1931 // lan object update level
1932 case OM_GEN_OBJ_LAN:
1933 if(Om_gen_obj_update != OBJ_UPDATE_LAN){
1934 gamesnd_play_iface(SND_USER_SELECT);
1935 Om_gen_obj_update = OBJ_UPDATE_LAN;
1937 gamesnd_play_iface(SND_GENERAL_FAIL);
1942 case OM_GEN_PIX_YES:
1944 gamesnd_play_iface(SND_USER_SELECT);
1947 gamesnd_play_iface(SND_GENERAL_FAIL);
1954 gamesnd_play_iface(SND_USER_SELECT);
1957 gamesnd_play_iface(SND_GENERAL_FAIL);
1961 // put missions in the multidate directory
1962 case OM_GEN_XFER_MULTIDATA_YES:
1963 if(!Om_gen_xfer_multidata){
1964 gamesnd_play_iface(SND_USER_SELECT);
1965 Om_gen_xfer_multidata = 1;
1967 gamesnd_play_iface(SND_GENERAL_FAIL);
1971 // dont put missions in the multidata directory
1972 case OM_GEN_XFER_MULTIDATA_NO:
1973 if(Om_gen_xfer_multidata){
1974 gamesnd_play_iface(SND_USER_SELECT);
1975 Om_gen_xfer_multidata = 0;
1977 gamesnd_play_iface(SND_GENERAL_FAIL);
1981 // flush the cache before each mission
1982 case OM_GEN_FLUSH_YES:
1983 if(!Om_gen_flush_cache){
1984 gamesnd_play_iface(SND_USER_SELECT);
1985 Om_gen_flush_cache = 1;
1987 gamesnd_play_iface(SND_GENERAL_FAIL);
1991 // don't flush the cache before each mission
1992 case OM_GEN_FLUSH_NO:
1993 if(Om_gen_flush_cache){
1994 gamesnd_play_iface(SND_USER_SELECT);
1995 Om_gen_flush_cache = 0;
1997 gamesnd_play_iface(SND_GENERAL_FAIL);
2003 // voice options tab section -------------------------------------------
2005 // load all the voice tab controls
2006 void options_multi_load_vox_controls()
2010 SDL_assert(Om_window != NULL);
2012 // instantiate all the buttons
2013 for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
2014 // create the object
2015 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);
2017 // set the sound to play when highlighted
2018 Om_vox_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
2020 // set the ani for the button
2021 Om_vox_buttons[gr_screen.res][idx].button.set_bmaps(Om_vox_buttons[gr_screen.res][idx].filename);
2024 Om_vox_buttons[gr_screen.res][idx].button.link_hotspot(Om_vox_buttons[gr_screen.res][idx].hotspot);
2029 for(idx=0; idx<OM_VOX_NUM_TEXT; idx++){
2030 Om_window->add_XSTR(&Om_vox_text[gr_screen.res][idx]);
2035 for ( idx = 0; idx < NUM_OM_VOX_SLIDERS; idx++ ) {
2036 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,
2037 Om_vox_sliders[gr_screen.res][idx].dots, Om_vox_sliders[gr_screen.res][idx].filename,
2038 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,
2039 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,
2040 Om_vox_sliders[gr_screen.res][idx].dot_w);
2043 // default position from settings (slider is 0-9, hence the -1)
2044 Om_vox_qos_pos = Player->m_server_options.voice_qos - 1;
2045 Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.pos = Om_vox_qos_pos;
2047 // create the player list select button
2048 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);
2049 Om_vox_plist_button.hide();
2051 // build a list of net players
2052 Om_vox_num_players = 0;
2053 for(idx=0;idx<MAX_PLAYERS;idx++){
2054 Om_vox_players[idx] = NULL;
2056 // if i'm not connected, do nothing
2057 if((Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_CONNECTED)){
2061 // add all players I know about
2062 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (Net_player != &Net_players[idx])){
2063 // set the netplayer pointer
2064 Om_vox_players[Om_vox_num_players] = &Net_players[idx];
2066 // set his mute flag
2067 Om_vox_player_flags[Om_vox_num_players] = (Multi_voice_local_prefs & (1<<idx)) ? 1 : 0;
2069 // increment the count
2070 Om_vox_num_players++;
2075 Om_vox_bogus.base_create(Om_window, UI_KIND_ICON, 0, 0, 0, 0);
2078 // disable/hide all the voice tab controls
2079 void options_multi_disable_vox_controls()
2083 // go through all the controls
2084 for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
2085 Om_vox_buttons[gr_screen.res][idx].button.hide();
2086 Om_vox_buttons[gr_screen.res][idx].button.disable();
2089 // hide the qos control
2090 Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.hide();
2091 Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.disable();
2093 // unset the sound buffer size so we don't display any waveforms
2094 Om_vox_voice_buffer_size = -1;
2095 Om_vox_voice_comp_size = -1;
2096 Om_vox_playback_handle = -1;
2097 Om_vox_test_status = OM_VOX_TEST_NONE;
2099 // disable the player list select button
2100 Om_vox_plist_button.disable();
2103 Om_vox_bogus.hide();
2104 Om_vox_bogus.disable();
2107 // enable/unhide all the voice tab controls
2108 void options_multi_enable_vox_controls()
2112 // go through all the controls
2113 for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
2114 Om_vox_buttons[gr_screen.res][idx].button.enable();
2115 Om_vox_buttons[gr_screen.res][idx].button.unhide();
2118 // unhide the qos control
2119 Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.enable();
2120 Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.unhide();
2122 // unset the sound buffer size so we don't display any waveforms
2123 Om_vox_voice_buffer_size = -1;
2124 Om_vox_voice_comp_size = -1;
2125 Om_vox_playback_handle = -1;
2126 Om_vox_test_status = OM_VOX_TEST_NONE;
2128 // select the first player on the list
2129 Om_vox_player_select = Om_vox_players[0];
2130 Om_vox_plist_start = 0;
2132 // enable the player list select button
2133 Om_vox_plist_button.enable();
2136 Om_vox_bogus.enable();
2137 Om_vox_bogus.unhide();
2140 // initialize the voice tab vars
2141 void options_multi_init_vox_vars()
2143 // intialize the accept voice var
2144 if(Player->m_local_options.flags & MLO_FLAG_NO_VOICE){
2145 Om_vox_accept_voice = 0;
2147 Om_vox_accept_voice = 1;
2151 // accept function for the voice tab
2152 void options_multi_vox_accept()
2155 int voice_pref_flags;
2157 // set the accept voice flag
2158 Player->m_local_options.flags &= ~(MLO_FLAG_NO_VOICE);
2159 if(!Om_vox_accept_voice){
2160 Player->m_local_options.flags |= MLO_FLAG_NO_VOICE;
2164 Players->m_server_options.voice_qos = (ubyte)(Om_vox_qos_pos + 1);
2166 // build the voice preferences stuff
2167 voice_pref_flags = 0xffffffff;
2168 for(idx=0;idx<Om_vox_num_players;idx++){
2169 // if this guy is muted
2170 if(!Om_vox_player_flags[idx]){
2171 voice_pref_flags &= ~(1 << NET_PLAYER_INDEX(Om_vox_players[idx]));
2174 multi_voice_set_prefs(voice_pref_flags);
2177 // do frame for the voice tab
2178 void options_multi_vox_do()
2182 // check for button presses
2183 options_multi_vox_check_buttons();
2185 // maybe do something with the QoS slider
2186 if (Om_vox_qos_pos != Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.pos) {
2187 Om_vox_qos_pos = Om_vox_sliders[gr_screen.res][OM_VOX_QOS_SLIDER].slider.pos;
2188 gamesnd_play_iface(SND_USER_SELECT);
2191 // draw the proper accept voice button
2192 if(Om_vox_accept_voice){
2193 Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_YES].button.draw_forced(2);
2195 Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_NO].button.draw_forced(2);
2198 // if the currently selected player is muted
2199 if((Om_vox_player_select != NULL) && !Om_vox_player_flags[options_multi_vox_plist_get(Om_vox_player_select)]){
2200 Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_MUTE].button.draw_forced(2);
2203 // process and display the player list
2204 options_multi_vox_process_player_list();
2206 // if we're currently doing a voice test recording, process some stuff
2207 switch(Om_vox_test_status){
2208 case OM_VOX_TEST_RECORDING:
2209 multi_voice_test_process();
2211 // force draw the mic test button
2212 Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_TEST].button.draw_forced(2);
2214 // if we are no longer recording, switch to playback if possible
2215 if(!multi_voice_test_recording()){
2216 Om_vox_test_status = OM_VOX_TEST_PLAYBACK;
2218 if(Om_vox_voice_comp_size != -1){
2219 // stop any playing back sounds
2220 rtvoice_stop_playback_all();
2222 // attempt to get a playback handle
2223 handle = multi_voice_test_get_playback_buffer();
2225 Om_vox_playback_handle = rtvoice_play_uncompressed(handle, Om_vox_comp_buffer, Om_vox_voice_comp_size);
2227 // mark us as playing back
2228 Om_vox_test_status = OM_VOX_TEST_PLAYBACK;
2230 // on error, notify the user something is wrong
2232 options_multi_add_notify(XSTR( "Error trying to playback recorded voice! Check your hardware", 390));
2234 // mark us as doing nothing
2235 Om_vox_test_status = OM_VOX_TEST_NONE;
2238 // mark us as doing nothing
2239 Om_vox_test_status = OM_VOX_TEST_NONE;
2244 case OM_VOX_TEST_PLAYBACK:
2245 // if we were playing a sound back, but now the sound is done
2246 if (Om_vox_playback_handle != -1) {
2247 int channel = oal_get_channel(Om_vox_playback_handle);
2249 // channel will be -1 if sound has already stopped playing
2250 if ( (channel == -1) || (oal_get_play_position(channel) >= Om_vox_voice_comp_size) ) {
2251 // flush all playing sounds safely
2252 rtvoice_stop_playback_all();
2254 // null the sound handle
2255 Om_vox_playback_handle = -1;
2257 // set this so we know not to display any more waveforms
2258 Om_vox_voice_buffer_size = -1;
2259 Om_vox_voice_comp_size = -1;
2261 // free the status up
2262 Om_vox_test_status = OM_VOX_TEST_NONE;
2269 // check for button presses
2270 void options_multi_vox_check_buttons()
2274 // go through all the buttons
2275 for(idx=0; idx<OM_VOX_NUM_BUTTONS; idx++){
2276 if(Om_vox_buttons[gr_screen.res][idx].button.pressed()){
2277 options_multi_vox_button_pressed(idx);
2283 // a button was pressed
2284 void options_multi_vox_button_pressed(int n)
2287 // accept voice button
2288 case OM_VOX_VOICE_YES:
2289 if(!Om_vox_accept_voice){
2290 gamesnd_play_iface(SND_USER_SELECT);
2291 Om_vox_accept_voice = 1;
2293 gamesnd_play_iface(SND_GENERAL_FAIL);
2297 // don't accept voice button
2298 case OM_VOX_VOICE_NO:
2299 if(Om_vox_accept_voice){
2300 gamesnd_play_iface(SND_USER_SELECT);
2301 Om_vox_accept_voice = 0;
2303 gamesnd_play_iface(SND_GENERAL_FAIL);
2307 // mute/unmute button
2308 case OM_VOX_VOICE_MUTE:
2309 if(Om_vox_player_select != NULL){
2310 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)];
2311 gamesnd_play_iface(SND_USER_SELECT);
2313 gamesnd_play_iface(SND_GENERAL_FAIL);
2317 // scroll the player list up
2318 case OM_VOX_PLIST_UP:
2319 options_multi_vox_plist_scroll_up();
2322 // scroll the player list down
2323 case OM_VOX_PLIST_DOWN:
2324 options_multi_vox_plist_scroll_down();
2328 case OM_VOX_VOICE_TEST:
2329 // if in a multiplayer game, don't allow testing
2330 if((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_CONNECTED)){
2331 options_multi_add_notify(XSTR( "Cannot test mic while in a multiplayer game!", 391));
2335 // if this machine is not capable of playing
2336 if(!Multi_voice_can_record){
2337 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));
2339 // if we're not already doing a record test
2340 if(Om_vox_test_status == OM_VOX_TEST_NONE){
2341 // set the quality of sound
2342 rtvoice_set_qos(Om_vox_qos_pos + 1);
2344 // clear the comp buffer
2345 memset(Om_vox_comp_buffer,128,OM_VOX_COMP_SIZE);
2347 Om_vox_test_status = OM_VOX_TEST_RECORDING;
2348 multi_voice_test_record_start();
2356 extern shader Grey_shader;
2358 // process and blit any voice waveform if necessary
2359 void options_multi_vox_process_waveform()
2361 int c_width = OM_VOX_WAVE_WIDTH;
2364 int idx,a_idx,running_avg;
2366 // if we're not in recording or playback mode
2367 if(Om_vox_test_status == OM_VOX_TEST_NONE){
2372 gr_set_shader(&Grey_shader);
2373 gr_shade(0,0,gr_screen.clip_width, gr_screen.clip_height);
2375 switch(Om_vox_test_status){
2376 case OM_VOX_TEST_RECORDING:
2377 // if we have no sound buffer size, do nothing
2378 if(Om_vox_voice_buffer_size <= 0){
2382 // if we are not recording, do nothing
2383 if(Om_vox_test_status != OM_VOX_TEST_RECORDING){
2387 // get the # of samples we'll average for one line
2388 avg_len = Om_vox_voice_buffer_size / c_width;
2390 // blit the waveform
2391 gr_set_color_fast(&Color_green);
2393 for(idx=0; idx < c_width; idx++){
2394 // reset the running average
2396 for(a_idx = 0; a_idx < avg_len; a_idx++){
2397 running_avg += (int)Om_vox_voice_buffer[buf_offset] - 128;
2399 // increment the buffer offset
2403 running_avg /= avg_len;
2404 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);
2407 // if this packet would have been dropped, notify the user
2408 if(multi_voice_test_packet_tossed()){
2409 gr_set_color_fast(&Color_bright);
2410 gr_string(OM_VOX_DROP_ICON_X,OM_VOX_DROP_ICON_Y, XSTR( "Packet Overflow", 393));
2414 case OM_VOX_TEST_PLAYBACK:
2415 // get the offset into the playing direct sound buffer
2416 buf_offset = oal_get_play_position(oal_get_channel(Om_vox_playback_handle));
2418 // get the # of samples we'll average for one line
2419 avg_len = (int)((float)OM_VOX_RECORD_INT * ((1024.0f * 11.0f) / 1000.0f)) / c_width;
2421 // blit the waveform
2422 gr_set_color_fast(&Color_red);
2423 for(idx=0; idx < c_width; idx++){
2424 // reset the running average
2426 for(a_idx = 0; a_idx < avg_len; a_idx++){
2427 if(buf_offset < (OM_VOX_COMP_SIZE - 2)){
2428 running_avg += (int)Om_vox_comp_buffer[buf_offset] - 128;
2430 // increment the buffer offset
2435 running_avg /= avg_len;
2436 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);
2442 // process/display the player list
2443 void options_multi_vox_process_player_list()
2446 int y_start,p_count;
2447 int selected_index,click_y;
2448 char str[CALLSIGN_LEN+2];
2450 // check for mouse clicks
2451 if(Om_vox_plist_button.pressed()){
2452 Om_vox_plist_button.get_mouse_pos(NULL,&click_y);
2453 selected_index = (click_y / 10) + Om_vox_plist_start;
2455 // if he clicked on a valid player, select him
2456 if(Om_vox_players[selected_index] != NULL){
2457 Om_vox_player_select = Om_vox_players[selected_index];
2459 nprintf(("Network","Selecting player %s\n",Om_vox_player_select->player->callsign));
2463 // draw the list of players
2465 y_start = Om_vox_plist_coords[gr_screen.res][1];
2466 for(idx = Om_vox_plist_start; idx < Om_vox_num_players; idx++){
2467 if(Om_vox_players[idx] != NULL){
2468 // if he's the selected player, highlight him
2469 if(Om_vox_players[idx] == Om_vox_player_select){
2470 gr_set_color_fast(&Color_bright);
2472 gr_set_color_fast(&Color_normal);
2475 // force fit his callsign
2476 SDL_strlcpy(str, Om_vox_players[idx]->player->callsign, SDL_arraysize(str));
2477 gr_force_fit_string(str, CALLSIGN_LEN+1, Om_vox_plist_coords[gr_screen.res][2]);
2479 // blit the callsign
2480 gr_string(Om_vox_plist_coords[gr_screen.res][0], y_start, str);
2482 // increment the y index
2485 // increment the player count
2489 // if we've reached max display, break out
2490 if(p_count >= Om_vox_plist_max_display[gr_screen.res]){
2496 // get the index into the player list of the passed netplayer
2497 int options_multi_vox_plist_get(net_player *pl)
2501 for(idx=0;idx<Om_vox_num_players;idx++){
2502 if(pl == Om_vox_players[idx]){
2507 // should neve get here. hmmm.
2512 // scroll the player list down
2513 void options_multi_vox_plist_scroll_down()
2515 if(Om_vox_num_players < Om_vox_plist_max_display[gr_screen.res]){
2516 gamesnd_play_iface(SND_GENERAL_FAIL);
2520 if((Om_vox_num_players - Om_vox_plist_start) >= Om_vox_plist_max_display[gr_screen.res]){
2521 Om_vox_plist_start++;
2522 gamesnd_play_iface(SND_USER_SELECT);
2524 gamesnd_play_iface(SND_GENERAL_FAIL);
2528 // scroll the player list up
2529 void options_multi_vox_plist_scroll_up()
2531 if(Om_vox_plist_start > 0){
2532 Om_vox_plist_start--;
2533 gamesnd_play_iface(SND_USER_SELECT);
2535 gamesnd_play_iface(SND_GENERAL_FAIL);
2540 // extern functions -----------------------------------------------------
2542 // called when the options screen is initialized, pass in the UI window
2543 void options_multi_init(UI_WINDOW *options_window)
2545 // assign the options window
2546 Om_window = options_window;
2548 // load the background bitmaps
2549 options_multi_load_bmaps();
2551 // load the controls for the protocol area
2552 options_multi_load_protocol_controls();
2554 // load the controls for the general tab
2555 options_multi_load_gen_controls();
2557 // load the controls for the voice tab
2558 options_multi_load_vox_controls();
2560 // disable all the protocol controls
2561 options_multi_disable_protocol_controls();
2563 // disable all the general tab controls
2564 options_multi_disable_gen_controls();
2566 // disable all the voice tab controls
2567 options_multi_disable_vox_controls();
2569 // intialize the protocol section vars
2570 options_multi_init_protocol_vars();
2572 // initialize the general tab vars
2573 options_multi_init_gen_vars();
2575 // initialize the voice tab vars
2576 options_multi_init_vox_vars();
2578 // intialize the multiplayer voice recording system
2579 if( !((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_CONNECTED)) ){
2583 // set the default screen mode
2584 Om_mode = OM_MODE_NONE;
2587 // do frame for the multi options screen
2588 void options_multi_do(int key)
2590 // do frame for the protocol section
2591 options_multi_protocol_do(key);
2593 // process and blit any notification messages
2594 options_multi_notify_process();
2596 // process the proper tab control
2598 case OM_MODE_GENERAL:
2599 options_multi_gen_do();
2602 options_multi_vox_do();
2609 // called when the entire options screen is closed
2610 void options_multi_close()
2612 // null out the window handle
2615 // unload all background bitmaps
2616 options_multi_unload_bmaps();
2618 // stop any playing voice
2619 rtvoice_stop_playback_all();
2621 // unset the screen mode
2622 Om_mode = OM_MODE_NONE;
2625 // called if the accept button on the main options screen was hit
2626 void options_multi_accept()
2628 // accept function for the protocol section
2629 options_multi_protocol_accept();
2631 // accept function for the general tab
2632 options_multi_gen_accept();
2634 // accept function for the voice tab
2635 options_multi_vox_accept();
2637 // if Net_player is not null, copy these new settings to him
2638 if(Net_player != NULL){
2639 multi_options_local_load(&Net_player->p_info.options, NULL);
2641 multi_options_local_load(&Player->m_local_options, NULL);
2643 // if we're connected to a game server, update our options on the server now
2644 if((Net_player != NULL) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && MULTI_CONNECTED(Net_players[MY_NET_PLAYER_NUM]) ){
2645 multi_options_update_local();
2649 // called when the multiplayer tab is hit - initializes/switches all necessary data.
2650 // NOTE : this is different from the initialization function, which is called only when the options menu is started
2651 void options_multi_select()
2654 // set the windows mask bitmap
2655 SDL_assert(Om_mask_0 >= 0);
2656 Om_window->set_mask_bmap(Om_mask_0, Om_background_0_mask_fname[gr_screen.res]);
2658 // set the default screen mode
2659 Om_mode = OM_MODE_GENERAL;
2661 // clear any notification messages
2662 Om_notify_stamp = -1;
2664 // enable all the protocol controls
2665 options_multi_enable_protocol_controls();
2667 // enable the general tab controls
2668 options_multi_enable_gen_controls();
2672 // return the bitmap handle of the current background bitmap, or -1 if the multiplayer tab is not active
2673 int options_multi_background_bitmap()
2676 // return the background bitmap mode based upon the current mode
2678 case OM_MODE_GENERAL:
2679 return Om_background_0;
2682 return Om_background_1;
2685 // unknown mode of some kind
2690 // called when the multiplayer tab has been switched from
2691 void options_multi_unselect()
2694 Om_mode = OM_MODE_NONE;
2696 // disable all the protocol controls
2697 options_multi_disable_protocol_controls();
2699 // disable all the general tab controls
2700 options_multi_disable_gen_controls();
2702 // disable all the vox tab controls
2703 options_multi_disable_vox_controls();
2705 // stop any test voice recording
2706 multi_voice_test_record_stop();
2709 // set voice sound buffer for display
2710 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)
2712 // copy the buffer to the vox tab data
2713 if(buf_size > OM_VOX_BUF_SIZE){
2714 memcpy(Om_vox_voice_buffer,sound_buf,OM_VOX_BUF_SIZE);
2715 Om_vox_voice_buffer_size = OM_VOX_BUF_SIZE;
2717 memcpy(Om_vox_voice_buffer,sound_buf,buf_size);
2718 Om_vox_voice_buffer_size = buf_size;
2721 // copy and uncompress the compressed buffer
2722 if(Om_vox_voice_comp_size == -1){
2723 Om_vox_voice_comp_size = 0;
2725 // if we can fit it, decompress this data
2726 if((Om_vox_voice_comp_size + uncomp_size) < OM_VOX_COMP_SIZE){
2727 // uncompress the data
2728 rtvoice_uncompress(comp_buf, comp_size, gain, Om_vox_comp_buffer + Om_vox_voice_comp_size, uncomp_size);
2730 Om_vox_voice_comp_size += uncomp_size;
2734 // return whether we want to eat a tabbed keypress
2735 int options_multi_eat_tab()
2737 // do we want to eat the tab key or not
2738 if(Om_tracker_passwd.has_focus() || Om_tracker_login.has_focus() || Om_tracker_squad_name.has_focus()){